| |
|
| |
|
| |
|
| |
|
| | 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;
|
| | }
|
| |
|