Merge pull request #1446 from frizynn/refactor/extension-type-guards-consolidation
refactor: consolidate extension type guards and inline handler aliases
This commit is contained in:
commit
671b72b684
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