Rework custom tools API with CustomToolContext

- CustomAgentTool renamed to CustomTool
- ToolAPI renamed to CustomToolAPI
- ToolContext renamed to CustomToolContext
- ToolSessionEvent renamed to CustomToolSessionEvent
- Added CustomToolContext parameter to execute() and onSession()
- CustomToolFactory now returns CustomTool<any, any> for type compatibility
- dispose() replaced with onSession({ reason: 'shutdown' })
- Added wrapCustomTool() to convert CustomTool to AgentTool
- Session exposes setToolUIContext() instead of leaking internals
- Fix ToolExecutionComponent to sync with toolOutputExpanded state
- Update all custom tool examples for new API
This commit is contained in:
Mario Zechner 2025-12-31 12:05:24 +01:00
parent b123df5fab
commit 568150f18b
27 changed files with 336 additions and 289 deletions

View file

@ -17,7 +17,7 @@ import { getAgentDir, isBunBinary } from "../../config.js";
import type { ExecOptions } from "../exec.js";
import { execCommand } from "../exec.js";
import type { HookUIContext } from "../hooks/types.js";
import type { CustomToolFactory, CustomToolsLoadResult, LoadedCustomTool, ToolAPI } from "./types.js";
import type { CustomToolAPI, CustomToolFactory, CustomToolsLoadResult, LoadedCustomTool } from "./types.js";
// Create require function to resolve module paths at runtime
const require = createRequire(import.meta.url);
@ -104,7 +104,7 @@ function createNoOpUIContext(): HookUIContext {
*/
async function loadToolWithBun(
resolvedPath: string,
sharedApi: ToolAPI,
sharedApi: CustomToolAPI,
): Promise<{ tools: LoadedCustomTool[] | null; error: string | null }> {
try {
// Try to import directly - will work for tools without @mariozechner/* imports
@ -149,7 +149,7 @@ async function loadToolWithBun(
async function loadTool(
toolPath: string,
cwd: string,
sharedApi: ToolAPI,
sharedApi: CustomToolAPI,
): Promise<{ tools: LoadedCustomTool[] | null; error: string | null }> {
const resolvedPath = resolveToolPath(toolPath, cwd);
@ -209,7 +209,7 @@ export async function loadCustomTools(
const seenNames = new Set<string>(builtInToolNames);
// Shared API object - all tools get the same instance
const sharedApi: ToolAPI = {
const sharedApi: CustomToolAPI = {
cwd,
exec: (command: string, args: string[], options?: ExecOptions) =>
execCommand(command, args, options?.cwd ?? cwd, options),