mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 03:01:56 +00:00
WIP: Add hook API for dynamic tool control with plan-mode hook example
- Add pi.getTools() and pi.setTools(toolNames) to HookAPI - Hooks can now enable/disable tools dynamically - Changes take effect on next agent turn New example hook: plan-mode.ts - Claude Code-style read-only exploration mode - /plan command toggles plan mode on/off - Plan mode tools: read, bash, grep, find, ls - Edit/write tools disabled in plan mode - Injects context telling agent about restrictions - After each response, prompts to execute/stay/refine - State persists across sessions
This commit is contained in:
parent
6ddfd1be13
commit
57bba4e32b
14 changed files with 304 additions and 8 deletions
|
|
@ -61,6 +61,16 @@ export type SendMessageHandler = <T = unknown>(
|
|||
*/
|
||||
export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;
|
||||
|
||||
/**
|
||||
* Get tools handler type for pi.getTools().
|
||||
*/
|
||||
export type GetToolsHandler = () => string[];
|
||||
|
||||
/**
|
||||
* Set tools handler type for pi.setTools().
|
||||
*/
|
||||
export type SetToolsHandler = (toolNames: string[]) => void;
|
||||
|
||||
/**
|
||||
* New session handler type for ctx.newSession() in HookCommandContext.
|
||||
*/
|
||||
|
|
@ -100,6 +110,10 @@ export interface LoadedHook {
|
|||
setSendMessageHandler: (handler: SendMessageHandler) => void;
|
||||
/** Set the append entry handler for this hook's pi.appendEntry() */
|
||||
setAppendEntryHandler: (handler: AppendEntryHandler) => void;
|
||||
/** Set the get tools handler for this hook's pi.getTools() */
|
||||
setGetToolsHandler: (handler: GetToolsHandler) => void;
|
||||
/** Set the set tools handler for this hook's pi.setTools() */
|
||||
setSetToolsHandler: (handler: SetToolsHandler) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -159,6 +173,8 @@ function createHookAPI(
|
|||
commands: Map<string, RegisteredCommand>;
|
||||
setSendMessageHandler: (handler: SendMessageHandler) => void;
|
||||
setAppendEntryHandler: (handler: AppendEntryHandler) => void;
|
||||
setGetToolsHandler: (handler: GetToolsHandler) => void;
|
||||
setSetToolsHandler: (handler: SetToolsHandler) => void;
|
||||
} {
|
||||
let sendMessageHandler: SendMessageHandler = () => {
|
||||
// Default no-op until mode sets the handler
|
||||
|
|
@ -166,6 +182,10 @@ function createHookAPI(
|
|||
let appendEntryHandler: AppendEntryHandler = () => {
|
||||
// Default no-op until mode sets the handler
|
||||
};
|
||||
let getToolsHandler: GetToolsHandler = () => [];
|
||||
let setToolsHandler: SetToolsHandler = () => {
|
||||
// Default no-op until mode sets the handler
|
||||
};
|
||||
const messageRenderers = new Map<string, HookMessageRenderer>();
|
||||
const commands = new Map<string, RegisteredCommand>();
|
||||
|
||||
|
|
@ -195,6 +215,12 @@ function createHookAPI(
|
|||
exec(command: string, args: string[], options?: ExecOptions) {
|
||||
return execCommand(command, args, options?.cwd ?? cwd, options);
|
||||
},
|
||||
getTools(): string[] {
|
||||
return getToolsHandler();
|
||||
},
|
||||
setTools(toolNames: string[]): void {
|
||||
setToolsHandler(toolNames);
|
||||
},
|
||||
} as HookAPI;
|
||||
|
||||
return {
|
||||
|
|
@ -207,6 +233,12 @@ function createHookAPI(
|
|||
setAppendEntryHandler: (handler: AppendEntryHandler) => {
|
||||
appendEntryHandler = handler;
|
||||
},
|
||||
setGetToolsHandler: (handler: GetToolsHandler) => {
|
||||
getToolsHandler = handler;
|
||||
},
|
||||
setSetToolsHandler: (handler: SetToolsHandler) => {
|
||||
setToolsHandler = handler;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -234,10 +266,15 @@ async function loadHook(hookPath: string, cwd: string): Promise<{ hook: LoadedHo
|
|||
|
||||
// Create handlers map and API
|
||||
const handlers = new Map<string, HandlerFn[]>();
|
||||
const { api, messageRenderers, commands, setSendMessageHandler, setAppendEntryHandler } = createHookAPI(
|
||||
handlers,
|
||||
cwd,
|
||||
);
|
||||
const {
|
||||
api,
|
||||
messageRenderers,
|
||||
commands,
|
||||
setSendMessageHandler,
|
||||
setAppendEntryHandler,
|
||||
setGetToolsHandler,
|
||||
setSetToolsHandler,
|
||||
} = createHookAPI(handlers, cwd);
|
||||
|
||||
// Call factory to register handlers
|
||||
factory(api);
|
||||
|
|
@ -251,6 +288,8 @@ async function loadHook(hookPath: string, cwd: string): Promise<{ hook: LoadedHo
|
|||
commands,
|
||||
setSendMessageHandler,
|
||||
setAppendEntryHandler,
|
||||
setGetToolsHandler,
|
||||
setSetToolsHandler,
|
||||
},
|
||||
error: null,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue