|
|
|
|
|
|
|
|
| import fs from 'fs';
|
| import path from 'path';
|
|
|
| export interface ToolParams {
|
| url?: string;
|
| prompt?: string;
|
| input?: string;
|
| raw?: string;
|
| captures?: string[];
|
| [key: string]: unknown;
|
| }
|
|
|
| export interface ToolResult {
|
| transcript?: string;
|
| downloadUrl?: string;
|
| filename?: string;
|
| method?: string;
|
| message?: string;
|
| mock?: boolean;
|
| error?: string;
|
| [key: string]: unknown;
|
| }
|
|
|
| export type ProgressEmitter = (message: string) => void;
|
|
|
| export interface ToolDefinition {
|
| name: string;
|
| description: string;
|
| syntax: string;
|
| pattern: RegExp;
|
| mock: boolean;
|
| execute: (params: ToolParams, emitProgress: ProgressEmitter) => Promise<ToolResult>;
|
| }
|
|
|
| export interface ToolSummary {
|
| name: string;
|
| description: string;
|
| syntax: string;
|
| mock: boolean;
|
| }
|
|
|
| export interface ToolMatch {
|
| tool: ToolDefinition;
|
| params: ToolParams;
|
| }
|
|
|
| export class ToolRegistry {
|
| private tools = new Map<string, ToolDefinition>();
|
|
|
| register(tool: ToolDefinition): void {
|
| if (!tool.name || !tool.execute) {
|
| throw new Error('Tool must have a name and execute function.');
|
| }
|
| this.tools.set(tool.name, tool);
|
| console.log(` [ToolRegistry] Registered: ${tool.name}`);
|
| }
|
|
|
| listTools(): ToolSummary[] {
|
| return Array.from(this.tools.values()).map((t) => ({
|
| name: t.name,
|
| description: t.description,
|
| syntax: t.syntax,
|
| mock: t.mock,
|
| }));
|
| }
|
|
|
| getTool(name: string): ToolDefinition | null {
|
| return this.tools.get(name) ?? null;
|
| }
|
|
|
| matchTool(message: string): ToolMatch | null {
|
| for (const tool of this.tools.values()) {
|
| if (!tool.pattern) continue;
|
| const match = message.match(tool.pattern);
|
| if (match) {
|
| return {
|
| tool,
|
| params: { ...match.groups, raw: message, captures: match.slice(1) },
|
| };
|
| }
|
| }
|
| return null;
|
| }
|
| }
|
|
|
| export function setupToolRegistry(): ToolRegistry {
|
| const registry = new ToolRegistry();
|
| const toolsDir = path.join(__dirname, 'tools');
|
|
|
| if (fs.existsSync(toolsDir)) {
|
| const files = fs.readdirSync(toolsDir).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));
|
| for (const file of files) {
|
| try {
|
| const mod = require(path.join(toolsDir, file));
|
| if (typeof mod.register === 'function') {
|
| mod.register(registry);
|
| }
|
| } catch (err: any) {
|
| console.error(` [ToolRegistry] Failed to load ${file}: ${err.message}`);
|
| }
|
| }
|
| }
|
|
|
| return registry;
|
| }
|
|
|