refactor: consolidate extension type guards and inline handler type aliases
Replace 7 individual ToolResultEvent type guards (isBashToolResult, isReadToolResult, etc.) with a unified isToolResultEventType() function, mirroring the existing isToolCallEventType() pattern. Inline 14 handler type aliases (SendMessageHandler, SetModelHandler, etc.) directly into the ExtensionActions interface since they were only used there and added no semantic value. Update documentation examples to use the new unified guard.
This commit is contained in:
parent
eaf0538150
commit
bbc180a3b6
5 changed files with 58 additions and 103 deletions
|
|
@ -72,7 +72,7 @@ pi.on("event_name", async (event, ctx: ExtensionContext) => {
|
|||
### Type Narrowing for Tool Events
|
||||
|
||||
```typescript
|
||||
import { isToolCallEventType, isBashToolResult } from "@mariozechner/pi-coding-agent";
|
||||
import { isToolCallEventType, isToolResultEventType } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
pi.on("tool_call", async (event, ctx) => {
|
||||
if (isToolCallEventType("bash", event)) {
|
||||
|
|
@ -84,7 +84,7 @@ pi.on("tool_call", async (event, ctx) => {
|
|||
});
|
||||
|
||||
pi.on("tool_result", async (event, ctx) => {
|
||||
if (isBashToolResult(event)) {
|
||||
if (isToolResultEventType("bash", event)) {
|
||||
// event.details is typed as BashToolDetails
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ export type {
|
|||
AgentToolUpdateCallback,
|
||||
// App keybindings (for custom editors)
|
||||
AppAction,
|
||||
AppendEntryHandler,
|
||||
// Events - Tool (ToolCallEvent types)
|
||||
BashToolCallEvent,
|
||||
BashToolResultEvent,
|
||||
|
|
@ -73,10 +72,6 @@ export type {
|
|||
ExtensionWidgetOptions,
|
||||
FindToolCallEvent,
|
||||
FindToolResultEvent,
|
||||
GetActiveToolsHandler,
|
||||
GetAllToolsHandler,
|
||||
GetCommandsHandler,
|
||||
GetThinkingLevelHandler,
|
||||
GrepToolCallEvent,
|
||||
GrepToolResultEvent,
|
||||
// Events - Input
|
||||
|
|
@ -107,8 +102,6 @@ export type {
|
|||
// Events - Resources
|
||||
ResourcesDiscoverEvent,
|
||||
ResourcesDiscoverResult,
|
||||
SendMessageHandler,
|
||||
SendUserMessageHandler,
|
||||
SessionBeforeCompactEvent,
|
||||
SessionBeforeCompactResult,
|
||||
SessionBeforeForkEvent,
|
||||
|
|
@ -128,10 +121,6 @@ export type {
|
|||
SessionStartEvent,
|
||||
SessionSwitchEvent,
|
||||
SessionTreeEvent,
|
||||
SetActiveToolsHandler,
|
||||
SetLabelHandler,
|
||||
SetModelHandler,
|
||||
SetThinkingLevelHandler,
|
||||
TerminalInputHandler,
|
||||
// Events - Tool
|
||||
ToolCallEvent,
|
||||
|
|
@ -157,16 +146,7 @@ export type {
|
|||
WriteToolResultEvent,
|
||||
} from "./types.js";
|
||||
// Type guards
|
||||
export {
|
||||
isBashToolResult,
|
||||
isEditToolResult,
|
||||
isFindToolResult,
|
||||
isGrepToolResult,
|
||||
isLsToolResult,
|
||||
isReadToolResult,
|
||||
isToolCallEventType,
|
||||
isWriteToolResult,
|
||||
} from "./types.js";
|
||||
export { isToolCallEventType, isToolResultEventType } from "./types.js";
|
||||
export {
|
||||
wrapRegisteredTool,
|
||||
wrapRegisteredTools,
|
||||
|
|
|
|||
|
|
@ -761,27 +761,36 @@ export type ToolResultEvent =
|
|||
| LsToolResultEvent
|
||||
| CustomToolResultEvent;
|
||||
|
||||
// Type guards for ToolResultEvent
|
||||
export function isBashToolResult(e: ToolResultEvent): e is BashToolResultEvent {
|
||||
return e.toolName === "bash";
|
||||
}
|
||||
export function isReadToolResult(e: ToolResultEvent): e is ReadToolResultEvent {
|
||||
return e.toolName === "read";
|
||||
}
|
||||
export function isEditToolResult(e: ToolResultEvent): e is EditToolResultEvent {
|
||||
return e.toolName === "edit";
|
||||
}
|
||||
export function isWriteToolResult(e: ToolResultEvent): e is WriteToolResultEvent {
|
||||
return e.toolName === "write";
|
||||
}
|
||||
export function isGrepToolResult(e: ToolResultEvent): e is GrepToolResultEvent {
|
||||
return e.toolName === "grep";
|
||||
}
|
||||
export function isFindToolResult(e: ToolResultEvent): e is FindToolResultEvent {
|
||||
return e.toolName === "find";
|
||||
}
|
||||
export function isLsToolResult(e: ToolResultEvent): e is LsToolResultEvent {
|
||||
return e.toolName === "ls";
|
||||
/**
|
||||
* Type guard for narrowing ToolResultEvent by tool name.
|
||||
*
|
||||
* Built-in tools narrow automatically (no type params needed):
|
||||
* ```ts
|
||||
* if (isToolResultEventType("bash", event)) {
|
||||
* event.details; // BashToolDetails | undefined
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Custom tools require explicit type parameters:
|
||||
* ```ts
|
||||
* if (isToolResultEventType<"my_tool", MyDetails>("my_tool", event)) {
|
||||
* event.details; // typed
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function isToolResultEventType(toolName: "bash", event: ToolResultEvent): event is BashToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "read", event: ToolResultEvent): event is ReadToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "edit", event: ToolResultEvent): event is EditToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "write", event: ToolResultEvent): event is WriteToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "grep", event: ToolResultEvent): event is GrepToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "find", event: ToolResultEvent): event is FindToolResultEvent;
|
||||
export function isToolResultEventType(toolName: "ls", event: ToolResultEvent): event is LsToolResultEvent;
|
||||
export function isToolResultEventType<TName extends string, TDetails = unknown>(
|
||||
toolName: TName,
|
||||
event: ToolResultEvent,
|
||||
): event is ToolResultEvent & { toolName: TName; details: TDetails };
|
||||
export function isToolResultEventType(toolName: string, event: ToolResultEvent): boolean {
|
||||
return event.toolName === toolName;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1274,43 +1283,9 @@ export interface ExtensionShortcut {
|
|||
|
||||
type HandlerFn = (...args: unknown[]) => Promise<unknown>;
|
||||
|
||||
export type SendMessageHandler = <T = unknown>(
|
||||
message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details">,
|
||||
options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
|
||||
) => void;
|
||||
|
||||
export type SendUserMessageHandler = (
|
||||
content: string | (TextContent | ImageContent)[],
|
||||
options?: { deliverAs?: "steer" | "followUp" },
|
||||
) => void;
|
||||
|
||||
export type AppendEntryHandler = <T = unknown>(customType: string, data?: T) => void;
|
||||
|
||||
export type SetSessionNameHandler = (name: string) => void;
|
||||
|
||||
export type GetSessionNameHandler = () => string | undefined;
|
||||
|
||||
export type GetActiveToolsHandler = () => string[];
|
||||
|
||||
/** Tool info with name, description, and parameter schema */
|
||||
export type ToolInfo = Pick<ToolDefinition, "name" | "description" | "parameters">;
|
||||
|
||||
export type GetAllToolsHandler = () => ToolInfo[];
|
||||
|
||||
export type GetCommandsHandler = () => SlashCommandInfo[];
|
||||
|
||||
export type SetActiveToolsHandler = (toolNames: string[]) => void;
|
||||
|
||||
export type RefreshToolsHandler = () => void;
|
||||
|
||||
export type SetModelHandler = (model: Model<any>, options?: { persist?: boolean }) => Promise<boolean>;
|
||||
|
||||
export type GetThinkingLevelHandler = () => ThinkingLevel;
|
||||
|
||||
export type SetThinkingLevelHandler = (level: ThinkingLevel) => void;
|
||||
|
||||
export type SetLabelHandler = (entryId: string, label: string | undefined) => void;
|
||||
|
||||
/**
|
||||
* Shared state created by loader, used during registration and runtime.
|
||||
* Contains flag values (defaults set during registration, CLI values set after).
|
||||
|
|
@ -1334,21 +1309,27 @@ export interface ExtensionRuntimeState {
|
|||
* Provided to runner.initialize(), copied into the shared runtime.
|
||||
*/
|
||||
export interface ExtensionActions {
|
||||
sendMessage: SendMessageHandler;
|
||||
sendUserMessage: SendUserMessageHandler;
|
||||
sendMessage: <T = unknown>(
|
||||
message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details">,
|
||||
options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
|
||||
) => void;
|
||||
sendUserMessage: (
|
||||
content: string | (TextContent | ImageContent)[],
|
||||
options?: { deliverAs?: "steer" | "followUp" },
|
||||
) => void;
|
||||
retryLastTurn: () => void;
|
||||
appendEntry: AppendEntryHandler;
|
||||
setSessionName: SetSessionNameHandler;
|
||||
getSessionName: GetSessionNameHandler;
|
||||
setLabel: SetLabelHandler;
|
||||
getActiveTools: GetActiveToolsHandler;
|
||||
getAllTools: GetAllToolsHandler;
|
||||
setActiveTools: SetActiveToolsHandler;
|
||||
refreshTools: RefreshToolsHandler;
|
||||
getCommands: GetCommandsHandler;
|
||||
setModel: SetModelHandler;
|
||||
getThinkingLevel: GetThinkingLevelHandler;
|
||||
setThinkingLevel: SetThinkingLevelHandler;
|
||||
appendEntry: <T = unknown>(customType: string, data?: T) => void;
|
||||
setSessionName: (name: string) => void;
|
||||
getSessionName: () => string | undefined;
|
||||
setLabel: (entryId: string, label: string | undefined) => void;
|
||||
getActiveTools: () => string[];
|
||||
getAllTools: () => ToolInfo[];
|
||||
setActiveTools: (toolNames: string[]) => void;
|
||||
refreshTools: () => void;
|
||||
getCommands: () => SlashCommandInfo[];
|
||||
setModel: (model: Model<any>, options?: { persist?: boolean }) => Promise<boolean>;
|
||||
getThinkingLevel: () => ThinkingLevel;
|
||||
setThinkingLevel: (level: ThinkingLevel) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -128,14 +128,8 @@ export {
|
|||
discoverAndLoadExtensions,
|
||||
ExtensionRunner,
|
||||
importExtensionModule,
|
||||
isBashToolResult,
|
||||
isEditToolResult,
|
||||
isFindToolResult,
|
||||
isGrepToolResult,
|
||||
isLsToolResult,
|
||||
isReadToolResult,
|
||||
isToolCallEventType,
|
||||
isWriteToolResult,
|
||||
isToolResultEventType,
|
||||
wrapRegisteredTool,
|
||||
wrapRegisteredTools,
|
||||
wrapToolsWithExtensions,
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ pi.on("tool_call", async (event, ctx) => {
|
|||
|
||||
**tool_result** — Fired after tool executes. Can modify result. Handlers chain like middleware.
|
||||
```typescript
|
||||
import { isBashToolResult } from "@mariozechner/pi-coding-agent";
|
||||
import { isToolResultEventType } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
pi.on("tool_result", async (event, ctx) => {
|
||||
if (isBashToolResult(event)) {
|
||||
if (isToolResultEventType("bash", event)) {
|
||||
// event.details is typed as BashToolDetails
|
||||
}
|
||||
// Return partial patch: { content, details, isError }
|
||||
|
|
@ -105,7 +105,7 @@ pi.on("model_select", async (event, ctx) => {
|
|||
Built-in type guards for tool events:
|
||||
|
||||
```typescript
|
||||
import { isToolCallEventType, isBashToolResult } from "@mariozechner/pi-coding-agent";
|
||||
import { isToolCallEventType, isToolResultEventType } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
// Tool calls — narrows event.input type
|
||||
if (isToolCallEventType("bash", event)) { /* event.input: { command, timeout? } */ }
|
||||
|
|
@ -114,7 +114,7 @@ if (isToolCallEventType("write", event)) { /* event.input: { path, content } */
|
|||
if (isToolCallEventType("edit", event)) { /* event.input: { path, oldText, newText } */ }
|
||||
|
||||
// Tool results — narrows event.details type
|
||||
if (isBashToolResult(event)) { /* event.details: BashToolDetails */ }
|
||||
if (isToolResultEventType("bash", event)) { /* event.details: BashToolDetails */ }
|
||||
```
|
||||
|
||||
For custom tools, export your input type and use explicit type params:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue