feat(extensions): forward message and tool execution events to extensions (#1375)

The extension system currently only forwards agent_start, agent_end,
turn_start, and turn_end events. This means extensions cannot access
streaming text (token-by-token), message lifecycle, or tool execution
progress — all of which are available to internal subscribers.

This adds forwarding for the remaining 6 agent event types:
- message_start, message_update, message_end
- tool_execution_start, tool_execution_update, tool_execution_end

These follow the exact same pattern as the existing forwarded events:
new interfaces in types.ts, exports in index.ts, and else-if blocks
in _emitExtensionEvent(). The new types are included in ExtensionEvent
and automatically flow through RunnerEmitEvent (they're not in the
exclusion list).

This enables extensions to build real-time UIs, streaming WebSocket
bridges, and other integrations that need fine-grained event access.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
This commit is contained in:
Sumeet Agarwal 2026-02-12 11:30:46 -08:00 committed by GitHub
parent 4793f7c92d
commit ff5148e7cc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 117 additions and 0 deletions

View file

@ -81,9 +81,13 @@ export type {
LoadExtensionsResult,
LsToolCallEvent,
LsToolResultEvent,
// Events - Message
MessageEndEvent,
// Message Rendering
MessageRenderer,
MessageRenderOptions,
MessageStartEvent,
MessageUpdateEvent,
ModelSelectEvent,
ModelSelectSource,
// Provider Registration
@ -124,6 +128,10 @@ export type {
ToolCallEventResult,
// Tools
ToolDefinition,
// Events - Tool Execution
ToolExecutionEndEvent,
ToolExecutionStartEvent,
ToolExecutionUpdateEvent,
ToolInfo,
ToolRenderResultOptions,
ToolResultEvent,

View file

@ -16,6 +16,7 @@ import type {
} from "@mariozechner/pi-agent-core";
import type {
Api,
AssistantMessageEvent,
AssistantMessageEventStream,
Context,
ImageContent,
@ -512,6 +513,51 @@ export interface TurnEndEvent {
toolResults: ToolResultMessage[];
}
/** Fired when a message starts (user, assistant, or toolResult) */
export interface MessageStartEvent {
type: "message_start";
message: AgentMessage;
}
/** Fired during assistant message streaming with token-by-token updates */
export interface MessageUpdateEvent {
type: "message_update";
message: AgentMessage;
assistantMessageEvent: AssistantMessageEvent;
}
/** Fired when a message ends */
export interface MessageEndEvent {
type: "message_end";
message: AgentMessage;
}
/** Fired when a tool starts executing */
export interface ToolExecutionStartEvent {
type: "tool_execution_start";
toolCallId: string;
toolName: string;
args: any;
}
/** Fired during tool execution with partial/streaming output */
export interface ToolExecutionUpdateEvent {
type: "tool_execution_update";
toolCallId: string;
toolName: string;
args: any;
partialResult: any;
}
/** Fired when a tool finishes executing */
export interface ToolExecutionEndEvent {
type: "tool_execution_end";
toolCallId: string;
toolName: string;
result: any;
isError: boolean;
}
// ============================================================================
// Model Events
// ============================================================================
@ -752,6 +798,12 @@ export type ExtensionEvent =
| AgentEndEvent
| TurnStartEvent
| TurnEndEvent
| MessageStartEvent
| MessageUpdateEvent
| MessageEndEvent
| ToolExecutionStartEvent
| ToolExecutionUpdateEvent
| ToolExecutionEndEvent
| ModelSelectEvent
| UserBashEvent
| InputEvent
@ -883,6 +935,12 @@ export interface ExtensionAPI {
on(event: "agent_end", handler: ExtensionHandler<AgentEndEvent>): void;
on(event: "turn_start", handler: ExtensionHandler<TurnStartEvent>): void;
on(event: "turn_end", handler: ExtensionHandler<TurnEndEvent>): void;
on(event: "message_start", handler: ExtensionHandler<MessageStartEvent>): void;
on(event: "message_update", handler: ExtensionHandler<MessageUpdateEvent>): void;
on(event: "message_end", handler: ExtensionHandler<MessageEndEvent>): void;
on(event: "tool_execution_start", handler: ExtensionHandler<ToolExecutionStartEvent>): void;
on(event: "tool_execution_update", handler: ExtensionHandler<ToolExecutionUpdateEvent>): void;
on(event: "tool_execution_end", handler: ExtensionHandler<ToolExecutionEndEvent>): void;
on(event: "model_select", handler: ExtensionHandler<ModelSelectEvent>): void;
on(event: "tool_call", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;
on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;