mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 22:01:41 +00:00
Update plan: HookCommandContext without sendMessage (use pi closure)
This commit is contained in:
parent
60130a4c53
commit
09e7e9196c
5 changed files with 22 additions and 27 deletions
|
|
@ -165,20 +165,20 @@ Calls `sessionManager.appendCustomEntry()` directly.
|
||||||
**New: `registerCommand()` (types ✅, wiring TODO)**
|
**New: `registerCommand()` (types ✅, wiring TODO)**
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface CommandContext {
|
interface HookCommandContext {
|
||||||
args: string; // Everything after /commandname
|
args: string; // Everything after /commandname
|
||||||
ui: HookUIContext;
|
ui: HookUIContext;
|
||||||
hasUI: boolean;
|
hasUI: boolean;
|
||||||
cwd: string;
|
cwd: string;
|
||||||
sessionManager: SessionManager;
|
sessionManager: SessionManager;
|
||||||
modelRegistry: ModelRegistry;
|
modelRegistry: ModelRegistry;
|
||||||
sendMessage: HookAPI['sendMessage'];
|
|
||||||
exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
exec(command: string, args: string[], options?: ExecOptions): Promise<ExecResult>;
|
||||||
}
|
}
|
||||||
|
// Note: sendMessage not on context - handler captures `pi` in closure
|
||||||
|
|
||||||
registerCommand(name: string, options: {
|
registerCommand(name: string, options: {
|
||||||
description?: string;
|
description?: string;
|
||||||
handler: (ctx: CommandContext) => Promise<string | undefined>;
|
handler: (ctx: HookCommandContext) => Promise<void>;
|
||||||
}): void;
|
}): void;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -188,7 +188,7 @@ Handler return:
|
||||||
Wiring (all in AgentSession.prompt()):
|
Wiring (all in AgentSession.prompt()):
|
||||||
- [x] Add hook commands to autocomplete in interactive-mode
|
- [x] Add hook commands to autocomplete in interactive-mode
|
||||||
- [x] `_tryExecuteHookCommand()` in AgentSession handles command execution
|
- [x] `_tryExecuteHookCommand()` in AgentSession handles command execution
|
||||||
- [x] Build CommandContext with ui (from hookRunner), exec, sessionManager, etc.
|
- [x] Build HookCommandContext with ui (from hookRunner), exec, sessionManager, etc.
|
||||||
- [x] If handler returns string, use as prompt text
|
- [x] If handler returns string, use as prompt text
|
||||||
- [x] If handler returns undefined, return early (no LLM call)
|
- [x] If handler returns undefined, return early (no LLM call)
|
||||||
- [x] Works for all modes (interactive, RPC, print) via shared AgentSession
|
- [x] Works for all modes (interactive, RPC, print) via shared AgentSession
|
||||||
|
|
@ -243,7 +243,7 @@ Review and update all docs:
|
||||||
- New `pi.appendEntry()` for state persistence
|
- New `pi.appendEntry()` for state persistence
|
||||||
- New `pi.registerCommand()` for custom slash commands
|
- New `pi.registerCommand()` for custom slash commands
|
||||||
- New `pi.registerCustomMessageRenderer()` for custom TUI rendering
|
- New `pi.registerCustomMessageRenderer()` for custom TUI rendering
|
||||||
- `CommandContext` interface and handler patterns
|
- `HookCommandContext` interface and handler patterns
|
||||||
- `HookMessage<T>` type
|
- `HookMessage<T>` type
|
||||||
- Updated event signatures (`SessionEventBase`, `before_compact`, etc.)
|
- Updated event signatures (`SessionEventBase`, `before_compact`, etc.)
|
||||||
- [ ] `docs/hooks-v2.md` - Review/merge or remove if obsolete
|
- [ ] `docs/hooks-v2.md` - Review/merge or remove if obsolete
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ import {
|
||||||
import type { LoadedCustomTool, SessionEvent as ToolSessionEvent } from "./custom-tools/index.js";
|
import type { LoadedCustomTool, SessionEvent as ToolSessionEvent } from "./custom-tools/index.js";
|
||||||
import { exportSessionToHtml } from "./export-html.js";
|
import { exportSessionToHtml } from "./export-html.js";
|
||||||
import {
|
import {
|
||||||
type CommandContext,
|
|
||||||
type ExecOptions,
|
type ExecOptions,
|
||||||
execCommand,
|
execCommand,
|
||||||
|
type HookCommandContext,
|
||||||
type HookMessage,
|
type HookMessage,
|
||||||
type HookRunner,
|
type HookRunner,
|
||||||
type SessionEventResult,
|
type SessionEventResult,
|
||||||
|
|
@ -512,18 +512,13 @@ export class AgentSession {
|
||||||
|
|
||||||
// Build command context
|
// Build command context
|
||||||
const cwd = process.cwd();
|
const cwd = process.cwd();
|
||||||
const ctx: CommandContext = {
|
const ctx: HookCommandContext = {
|
||||||
args,
|
args,
|
||||||
ui: uiContext,
|
ui: uiContext,
|
||||||
hasUI: this._hookRunner.getHasUI(),
|
hasUI: this._hookRunner.getHasUI(),
|
||||||
cwd,
|
cwd,
|
||||||
sessionManager: this.sessionManager,
|
sessionManager: this.sessionManager,
|
||||||
modelRegistry: this._modelRegistry,
|
modelRegistry: this._modelRegistry,
|
||||||
sendMessage: (message, triggerTurn) => {
|
|
||||||
this.sendHookMessage(message, triggerTurn).catch(() => {
|
|
||||||
// Error handling is done in sendHookMessage
|
|
||||||
});
|
|
||||||
},
|
|
||||||
exec: (cmd: string, cmdArgs: string[], options?: ExecOptions) => execCommand(cmd, cmdArgs, cwd, options),
|
exec: (cmd: string, cmdArgs: string[], options?: ExecOptions) => execCommand(cmd, cmdArgs, cwd, options),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
|
// biome-ignore assist/source/organizeImports: biome is not smart
|
||||||
export {
|
export {
|
||||||
type AppendEntryHandler,
|
|
||||||
discoverAndLoadHooks,
|
discoverAndLoadHooks,
|
||||||
|
loadHooks,
|
||||||
|
type AppendEntryHandler,
|
||||||
type LoadedHook,
|
type LoadedHook,
|
||||||
type LoadHooksResult,
|
type LoadHooksResult,
|
||||||
loadHooks,
|
|
||||||
type SendMessageHandler,
|
type SendMessageHandler,
|
||||||
} from "./loader.js";
|
} from "./loader.js";
|
||||||
export { execCommand, type HookErrorListener, HookRunner } from "./runner.js";
|
export { execCommand, HookRunner, type HookErrorListener } from "./runner.js";
|
||||||
export { wrapToolsWithHooks, wrapToolWithHooks } from "./tool-wrapper.js";
|
export { wrapToolsWithHooks, wrapToolWithHooks } from "./tool-wrapper.js";
|
||||||
export type {
|
export type {
|
||||||
AgentEndEvent,
|
AgentEndEvent,
|
||||||
AgentStartEvent,
|
AgentStartEvent,
|
||||||
BashToolResultEvent,
|
BashToolResultEvent,
|
||||||
CommandContext,
|
|
||||||
CustomMessageRenderer,
|
CustomMessageRenderer,
|
||||||
CustomMessageRenderOptions,
|
CustomMessageRenderOptions,
|
||||||
CustomToolResultEvent,
|
CustomToolResultEvent,
|
||||||
|
|
@ -22,6 +22,7 @@ export type {
|
||||||
FindToolResultEvent,
|
FindToolResultEvent,
|
||||||
GrepToolResultEvent,
|
GrepToolResultEvent,
|
||||||
HookAPI,
|
HookAPI,
|
||||||
|
HookCommandContext,
|
||||||
HookError,
|
HookError,
|
||||||
HookEvent,
|
HookEvent,
|
||||||
HookEventContext,
|
HookEventContext,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import type { Theme } from "../../modes/interactive/theme/theme.js";
|
||||||
import type { CompactionPreparation, CompactionResult } from "../compaction.js";
|
import type { CompactionPreparation, CompactionResult } from "../compaction.js";
|
||||||
import type { ModelRegistry } from "../model-registry.js";
|
import type { ModelRegistry } from "../model-registry.js";
|
||||||
import type { CompactionEntry, CustomMessageEntry, SessionManager } from "../session-manager.js";
|
import type { CompactionEntry, CustomMessageEntry, SessionManager } from "../session-manager.js";
|
||||||
|
import type { EditToolDetails } from "../tools/edit.js";
|
||||||
import type {
|
import type {
|
||||||
BashToolDetails,
|
BashToolDetails,
|
||||||
FindToolDetails,
|
FindToolDetails,
|
||||||
|
|
@ -237,7 +238,7 @@ export interface ReadToolResultEvent extends ToolResultEventBase {
|
||||||
/** Tool result event for edit tool */
|
/** Tool result event for edit tool */
|
||||||
export interface EditToolResultEvent extends ToolResultEventBase {
|
export interface EditToolResultEvent extends ToolResultEventBase {
|
||||||
toolName: "edit";
|
toolName: "edit";
|
||||||
details: undefined;
|
details: EditToolDetails | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Tool result event for write tool */
|
/** Tool result event for write tool */
|
||||||
|
|
@ -394,9 +395,9 @@ export type CustomMessageRenderer<T = unknown> = (
|
||||||
export type HookMessage<T = unknown> = Pick<CustomMessageEntry<T>, "customType" | "content" | "display" | "details">;
|
export type HookMessage<T = unknown> = Pick<CustomMessageEntry<T>, "customType" | "content" | "display" | "details">;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context passed to command handlers.
|
* Context passed to hook command handlers.
|
||||||
*/
|
*/
|
||||||
export interface CommandContext {
|
export interface HookCommandContext {
|
||||||
/** Arguments after the command name */
|
/** Arguments after the command name */
|
||||||
args: string;
|
args: string;
|
||||||
/** UI methods for user interaction */
|
/** UI methods for user interaction */
|
||||||
|
|
@ -411,13 +412,6 @@ export interface CommandContext {
|
||||||
sessionManager: SessionManager;
|
sessionManager: SessionManager;
|
||||||
/** Model registry for API keys */
|
/** Model registry for API keys */
|
||||||
modelRegistry: ModelRegistry;
|
modelRegistry: ModelRegistry;
|
||||||
/**
|
|
||||||
* Send a custom message to the session.
|
|
||||||
* If streaming, queued and appended after turn ends.
|
|
||||||
* If idle and triggerTurn=true, appends and triggers a new turn.
|
|
||||||
* If idle and triggerTurn=false (default), just appends.
|
|
||||||
*/
|
|
||||||
sendMessage<T = unknown>(message: HookMessage<T>, triggerTurn?: boolean): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -426,7 +420,7 @@ export interface CommandContext {
|
||||||
export interface RegisteredCommand {
|
export interface RegisteredCommand {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
handler: (ctx: CommandContext) => Promise<void>;
|
handler: (ctx: HookCommandContext) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,11 @@ const editSchema = Type.Object({
|
||||||
newText: Type.String({ description: "New text to replace the old text with" }),
|
newText: Type.String({ description: "New text to replace the old text with" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export interface EditToolDetails {
|
||||||
|
/** Unified diff of the changes made */
|
||||||
|
diff: string;
|
||||||
|
}
|
||||||
|
|
||||||
export function createEditTool(cwd: string): AgentTool<typeof editSchema> {
|
export function createEditTool(cwd: string): AgentTool<typeof editSchema> {
|
||||||
return {
|
return {
|
||||||
name: "edit",
|
name: "edit",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue