mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-18 17:04:49 +00:00
Add extensions option to createAgentSession SDK
- Accept ExtensionFactory[] for inline extensions (merged with discovery) - Mark preloadedExtensions as @internal (CLI implementation detail) - Update sdk.md with inline extension example - Update CHANGELOG
This commit is contained in:
parent
8da793b1ba
commit
79cb8f0906
6 changed files with 138 additions and 24 deletions
|
|
@ -2,7 +2,7 @@
|
|||
* Extension system for lifecycle events and custom tools.
|
||||
*/
|
||||
|
||||
export { discoverAndLoadExtensions, loadExtensions } from "./loader.js";
|
||||
export { discoverAndLoadExtensions, loadExtensionFromFactory, loadExtensions } from "./loader.js";
|
||||
export type { BranchHandler, ExtensionErrorListener, NavigateTreeHandler, NewSessionHandler } from "./runner.js";
|
||||
export { ExtensionRunner } from "./runner.js";
|
||||
export type {
|
||||
|
|
|
|||
|
|
@ -375,6 +375,54 @@ async function loadExtension(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LoadedExtension from an inline factory function.
|
||||
*/
|
||||
export function loadExtensionFromFactory(
|
||||
factory: ExtensionFactory,
|
||||
cwd: string,
|
||||
eventBus: EventBus,
|
||||
sharedUI: { ui: ExtensionUIContext; hasUI: boolean },
|
||||
name = "<inline>",
|
||||
): LoadedExtension {
|
||||
const handlers = new Map<string, HandlerFn[]>();
|
||||
const tools = new Map<string, RegisteredTool>();
|
||||
const {
|
||||
api,
|
||||
messageRenderers,
|
||||
commands,
|
||||
flags,
|
||||
flagValues,
|
||||
shortcuts,
|
||||
setSendMessageHandler,
|
||||
setAppendEntryHandler,
|
||||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setFlagValue,
|
||||
} = createExtensionAPI(handlers, tools, cwd, name, eventBus, sharedUI);
|
||||
|
||||
factory(api);
|
||||
|
||||
return {
|
||||
path: name,
|
||||
resolvedPath: name,
|
||||
handlers,
|
||||
tools,
|
||||
messageRenderers,
|
||||
commands,
|
||||
flags,
|
||||
flagValues,
|
||||
shortcuts,
|
||||
setSendMessageHandler,
|
||||
setAppendEntryHandler,
|
||||
setGetActiveToolsHandler,
|
||||
setGetAllToolsHandler,
|
||||
setSetActiveToolsHandler,
|
||||
setFlagValue,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load extensions from paths.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ import { AuthStorage } from "./auth-storage.js";
|
|||
import { createEventBus, type EventBus } from "./event-bus.js";
|
||||
import {
|
||||
discoverAndLoadExtensions,
|
||||
type ExtensionFactory,
|
||||
ExtensionRunner,
|
||||
type LoadExtensionsResult,
|
||||
type LoadedExtension,
|
||||
loadExtensionFromFactory,
|
||||
type ToolDefinition,
|
||||
wrapRegisteredTools,
|
||||
wrapToolsWithExtensions,
|
||||
|
|
@ -99,9 +101,14 @@ export interface CreateAgentSessionOptions {
|
|||
tools?: Tool[];
|
||||
/** Custom tools to register (in addition to built-in tools). */
|
||||
customTools?: ToolDefinition[];
|
||||
/** Inline extensions (merged with discovery). */
|
||||
extensions?: ExtensionFactory[];
|
||||
/** Additional extension paths to load (merged with discovery). */
|
||||
additionalExtensionPaths?: string[];
|
||||
/** Pre-loaded extensions (skips loading, used when extensions were loaded early for CLI flags). */
|
||||
/**
|
||||
* Pre-loaded extensions (skips file discovery).
|
||||
* @internal Used by CLI when extensions are loaded early to parse custom flags.
|
||||
*/
|
||||
preloadedExtensions?: LoadedExtension[];
|
||||
|
||||
/** Shared event bus for tool/extension communication. Default: creates new bus. */
|
||||
|
|
@ -447,6 +454,42 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|||
}
|
||||
}
|
||||
|
||||
// Load inline extensions from factories
|
||||
if (options.extensions && options.extensions.length > 0) {
|
||||
// Create shared UI context holder that will be set later
|
||||
const uiHolder: { ui: any; hasUI: boolean } = {
|
||||
ui: {
|
||||
select: async () => undefined,
|
||||
confirm: async () => false,
|
||||
input: async () => undefined,
|
||||
notify: () => {},
|
||||
setStatus: () => {},
|
||||
setWidget: () => {},
|
||||
setTitle: () => {},
|
||||
custom: async () => undefined as never,
|
||||
setEditorText: () => {},
|
||||
getEditorText: () => "",
|
||||
editor: async () => undefined,
|
||||
get theme() {
|
||||
return {} as any;
|
||||
},
|
||||
},
|
||||
hasUI: false,
|
||||
};
|
||||
for (let i = 0; i < options.extensions.length; i++) {
|
||||
const factory = options.extensions[i];
|
||||
const loaded = loadExtensionFromFactory(factory, cwd, eventBus, uiHolder, `<inline-${i}>`);
|
||||
extensionsResult.extensions.push(loaded);
|
||||
}
|
||||
// Extend setUIContext to update inline extensions too
|
||||
const originalSetUIContext = extensionsResult.setUIContext;
|
||||
extensionsResult.setUIContext = (uiContext, hasUI) => {
|
||||
originalSetUIContext(uiContext, hasUI);
|
||||
uiHolder.ui = uiContext;
|
||||
uiHolder.hasUI = hasUI;
|
||||
};
|
||||
}
|
||||
|
||||
// Create extension runner if we have extensions
|
||||
let extensionRunner: ExtensionRunner | undefined;
|
||||
if (extensionsResult.extensions.length > 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue