mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 03:01:56 +00:00
feat(coding-agent): add input event for extension input interception (#761)
* feat(coding-agent): add input event for extension input interception Extensions can now intercept, transform, or handle user input before the agent processes it. Three result types: continue (pass through), transform (modify text/images), handled (respond without LLM). Handlers chain transforms and short-circuit on handled. Source field identifies origin. * fix: make source public, use if/else over ternary * fix: remove response field, extension handles own UI
This commit is contained in:
parent
012319e15a
commit
3e5d91f287
11 changed files with 282 additions and 5 deletions
|
|
@ -61,6 +61,10 @@ export type {
|
|||
GetAllToolsHandler,
|
||||
GetThinkingLevelHandler,
|
||||
GrepToolResultEvent,
|
||||
// Events - Input
|
||||
InputEvent,
|
||||
InputEventResult,
|
||||
InputSource,
|
||||
KeybindingsManager,
|
||||
LoadExtensionsResult,
|
||||
LsToolResultEvent,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ import type {
|
|||
ExtensionRuntime,
|
||||
ExtensionShortcut,
|
||||
ExtensionUIContext,
|
||||
InputEvent,
|
||||
InputEventResult,
|
||||
InputSource,
|
||||
MessageRenderer,
|
||||
RegisteredCommand,
|
||||
RegisteredTool,
|
||||
|
|
@ -538,4 +541,35 @@ export class ExtensionRunner {
|
|||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Emit input event. Transforms chain, "handled" short-circuits. */
|
||||
async emitInput(text: string, images: ImageContent[] | undefined, source: InputSource): Promise<InputEventResult> {
|
||||
const ctx = this.createContext();
|
||||
let currentText = text;
|
||||
let currentImages = images;
|
||||
|
||||
for (const ext of this.extensions) {
|
||||
for (const handler of ext.handlers.get("input") ?? []) {
|
||||
try {
|
||||
const event: InputEvent = { type: "input", text: currentText, images: currentImages, source };
|
||||
const result = (await handler(event, ctx)) as InputEventResult | undefined;
|
||||
if (result?.action === "handled") return result;
|
||||
if (result?.action === "transform") {
|
||||
currentText = result.text;
|
||||
currentImages = result.images ?? currentImages;
|
||||
}
|
||||
} catch (err) {
|
||||
this.emitError({
|
||||
extensionPath: ext.path,
|
||||
event: "input",
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
stack: err instanceof Error ? err.stack : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentText !== text || currentImages !== images
|
||||
? { action: "transform", text: currentText, images: currentImages }
|
||||
: { action: "continue" };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -446,6 +446,30 @@ export interface UserBashEvent {
|
|||
cwd: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Input Events
|
||||
// ============================================================================
|
||||
|
||||
/** Source of user input */
|
||||
export type InputSource = "interactive" | "rpc" | "extension";
|
||||
|
||||
/** Fired when user input is received, before agent processing */
|
||||
export interface InputEvent {
|
||||
type: "input";
|
||||
/** The input text */
|
||||
text: string;
|
||||
/** Attached images, if any */
|
||||
images?: ImageContent[];
|
||||
/** Where the input came from */
|
||||
source: InputSource;
|
||||
}
|
||||
|
||||
/** Result from input event handler */
|
||||
export type InputEventResult =
|
||||
| { action: "continue" }
|
||||
| { action: "transform"; text: string; images?: ImageContent[] }
|
||||
| { action: "handled" };
|
||||
|
||||
// ============================================================================
|
||||
// Tool Events
|
||||
// ============================================================================
|
||||
|
|
@ -551,6 +575,7 @@ export type ExtensionEvent =
|
|||
| TurnEndEvent
|
||||
| ModelSelectEvent
|
||||
| UserBashEvent
|
||||
| InputEvent
|
||||
| ToolCallEvent
|
||||
| ToolResultEvent;
|
||||
|
||||
|
|
@ -675,6 +700,7 @@ export interface ExtensionAPI {
|
|||
on(event: "tool_call", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;
|
||||
on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;
|
||||
on(event: "user_bash", handler: ExtensionHandler<UserBashEvent, UserBashEventResult>): void;
|
||||
on(event: "input", handler: ExtensionHandler<InputEvent, InputEventResult>): void;
|
||||
|
||||
// =========================================================================
|
||||
// Tool Registration
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue