mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 03:01:56 +00:00
Split HookContext and HookCommandContext to prevent deadlocks
HookContext (all events): - isIdle() - read-only state check - hasQueuedMessages() - read-only state check - abort() - fire-and-forget, does not wait HookCommandContext (slash commands only): - waitForIdle() - waits for agent to finish - newSession(options?) - create new session - branch(entryId) - branch from entry - navigateTree(targetId, options?) - navigate session tree Session control methods moved from HookAPI (pi.*) to HookCommandContext (ctx.*) because they can deadlock when called from event handlers that run inside the agent loop (tool_call, tool_result, context events).
This commit is contained in:
parent
ccdd7bd283
commit
0d9fddec1e
9 changed files with 170 additions and 203 deletions
|
|
@ -62,7 +62,7 @@ export type SendMessageHandler = <T = unknown>(
|
|||
export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;
|
||||
|
||||
/**
|
||||
* New session handler type for pi.newSession().
|
||||
* New session handler type for ctx.newSession() in HookCommandContext.
|
||||
*/
|
||||
export type NewSessionHandler = (options?: {
|
||||
parentSession?: string;
|
||||
|
|
@ -70,12 +70,12 @@ export type NewSessionHandler = (options?: {
|
|||
}) => Promise<{ cancelled: boolean }>;
|
||||
|
||||
/**
|
||||
* Branch handler type for pi.branch().
|
||||
* Branch handler type for ctx.branch() in HookCommandContext.
|
||||
*/
|
||||
export type BranchHandler = (entryId: string) => Promise<{ cancelled: boolean }>;
|
||||
|
||||
/**
|
||||
* Navigate tree handler type for pi.navigateTree().
|
||||
* Navigate tree handler type for ctx.navigateTree() in HookCommandContext.
|
||||
*/
|
||||
export type NavigateTreeHandler = (
|
||||
targetId: string,
|
||||
|
|
@ -100,12 +100,6 @@ export interface LoadedHook {
|
|||
setSendMessageHandler: (handler: SendMessageHandler) => void;
|
||||
/** Set the append entry handler for this hook's pi.appendEntry() */
|
||||
setAppendEntryHandler: (handler: AppendEntryHandler) => void;
|
||||
/** Set the new session handler for this hook's pi.newSession() */
|
||||
setNewSessionHandler: (handler: NewSessionHandler) => void;
|
||||
/** Set the branch handler for this hook's pi.branch() */
|
||||
setBranchHandler: (handler: BranchHandler) => void;
|
||||
/** Set the navigate tree handler for this hook's pi.navigateTree() */
|
||||
setNavigateTreeHandler: (handler: NavigateTreeHandler) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -165,9 +159,6 @@ function createHookAPI(
|
|||
commands: Map<string, RegisteredCommand>;
|
||||
setSendMessageHandler: (handler: SendMessageHandler) => void;
|
||||
setAppendEntryHandler: (handler: AppendEntryHandler) => void;
|
||||
setNewSessionHandler: (handler: NewSessionHandler) => void;
|
||||
setBranchHandler: (handler: BranchHandler) => void;
|
||||
setNavigateTreeHandler: (handler: NavigateTreeHandler) => void;
|
||||
} {
|
||||
let sendMessageHandler: SendMessageHandler = () => {
|
||||
// Default no-op until mode sets the handler
|
||||
|
|
@ -175,18 +166,6 @@ function createHookAPI(
|
|||
let appendEntryHandler: AppendEntryHandler = () => {
|
||||
// Default no-op until mode sets the handler
|
||||
};
|
||||
let newSessionHandler: NewSessionHandler = async () => {
|
||||
// Default no-op until mode sets the handler
|
||||
return { cancelled: false };
|
||||
};
|
||||
let branchHandler: BranchHandler = async () => {
|
||||
// Default no-op until mode sets the handler
|
||||
return { cancelled: false };
|
||||
};
|
||||
let navigateTreeHandler: NavigateTreeHandler = async () => {
|
||||
// Default no-op until mode sets the handler
|
||||
return { cancelled: false };
|
||||
};
|
||||
const messageRenderers = new Map<string, HookMessageRenderer>();
|
||||
const commands = new Map<string, RegisteredCommand>();
|
||||
|
||||
|
|
@ -213,15 +192,6 @@ function createHookAPI(
|
|||
exec(command: string, args: string[], options?: ExecOptions) {
|
||||
return execCommand(command, args, options?.cwd ?? cwd, options);
|
||||
},
|
||||
newSession(options) {
|
||||
return newSessionHandler(options);
|
||||
},
|
||||
branch(entryId) {
|
||||
return branchHandler(entryId);
|
||||
},
|
||||
navigateTree(targetId, options) {
|
||||
return navigateTreeHandler(targetId, options);
|
||||
},
|
||||
} as HookAPI;
|
||||
|
||||
return {
|
||||
|
|
@ -234,15 +204,6 @@ function createHookAPI(
|
|||
setAppendEntryHandler: (handler: AppendEntryHandler) => {
|
||||
appendEntryHandler = handler;
|
||||
},
|
||||
setNewSessionHandler: (handler: NewSessionHandler) => {
|
||||
newSessionHandler = handler;
|
||||
},
|
||||
setBranchHandler: (handler: BranchHandler) => {
|
||||
branchHandler = handler;
|
||||
},
|
||||
setNavigateTreeHandler: (handler: NavigateTreeHandler) => {
|
||||
navigateTreeHandler = handler;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -270,16 +231,10 @@ 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,
|
||||
setNewSessionHandler,
|
||||
setBranchHandler,
|
||||
setNavigateTreeHandler,
|
||||
} = createHookAPI(handlers, cwd);
|
||||
const { api, messageRenderers, commands, setSendMessageHandler, setAppendEntryHandler } = createHookAPI(
|
||||
handlers,
|
||||
cwd,
|
||||
);
|
||||
|
||||
// Call factory to register handlers
|
||||
factory(api);
|
||||
|
|
@ -293,9 +248,6 @@ async function loadHook(hookPath: string, cwd: string): Promise<{ hook: LoadedHo
|
|||
commands,
|
||||
setSendMessageHandler,
|
||||
setAppendEntryHandler,
|
||||
setNewSessionHandler,
|
||||
setBranchHandler,
|
||||
setNavigateTreeHandler,
|
||||
},
|
||||
error: null,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue