56 lines
1.6 KiB
TypeScript
56 lines
1.6 KiB
TypeScript
import type { ToolDefinition } from '../../provider/types.ts';
|
|
|
|
/** Safely extract a string from tool args (avoids no-base-to-string lint). */
|
|
export function strArg(args: Record<string, unknown>, key: string, fallback = ''): string {
|
|
const v = args[key];
|
|
return typeof v === 'string' ? v : fallback;
|
|
}
|
|
|
|
export interface Tool {
|
|
readonly name: string;
|
|
readonly description: string;
|
|
/** JSON Schema `properties` object for the tool's parameters. */
|
|
readonly parameters: Record<string, unknown>;
|
|
/** Which parameters are required. Defaults to all keys if not set. */
|
|
readonly required?: string[];
|
|
execute(args: Record<string, unknown>): Promise<string>;
|
|
}
|
|
|
|
export class ToolRegistry {
|
|
private _tools = new Map<string, Tool>();
|
|
|
|
register(tool: Tool): void {
|
|
this._tools.set(tool.name, tool);
|
|
}
|
|
|
|
get(name: string): Tool | undefined {
|
|
return this._tools.get(name);
|
|
}
|
|
|
|
getDefinitions(): ToolDefinition[] {
|
|
return [...this._tools.values()].map((t) => ({
|
|
type: 'function' as const,
|
|
function: {
|
|
name: t.name,
|
|
description: t.description,
|
|
parameters: {
|
|
type: 'object',
|
|
properties: t.parameters,
|
|
required: t.required ?? Object.keys(t.parameters),
|
|
},
|
|
},
|
|
}));
|
|
}
|
|
|
|
async execute(name: string, args: Record<string, unknown>): Promise<string> {
|
|
const tool = this._tools.get(name);
|
|
if (!tool) return `Error: unknown tool "${name}"`;
|
|
|
|
try {
|
|
return await tool.execute(args);
|
|
} catch (err) {
|
|
return `Error: ${String(err)}\n[Analyze the error above and retry with a different approach if needed.]`;
|
|
}
|
|
}
|
|
}
|