export type ToolParameterType = 'string' | 'number' | 'boolean' | 'object' | 'array'; export interface ToolParameter { type: ToolParameterType; description: string; required?: boolean; properties?: Record; items?: ToolParameter; } export interface ToolSchema { type: 'local'; name: string; description: string; config: { timeout: number; parameters: { type: 'object'; title: string; required: string[]; properties: Record; }; output: { type: 'object'; title: string; properties: Record; }; }; } export interface ToolDefinition { name: string; description: string; title?: string; timeout?: number; parameters: Record; output: Record; // eslint-disable-next-line @typescript-eslint/no-explicit-any implementation: (...args: any[]) => any; } /** * Create a tool parameter definition */ export function createParameter( type: ToolParameterType, description: string, options?: { required?: boolean; properties?: Record; items?: ToolParameter; }, ): ToolParameter { return { type, description, ...options, }; } /** * Generate a tool schema from a tool definition */ export function generateToolSchema(definition: ToolDefinition): ToolSchema { const requiredParams = Object.entries(definition.parameters) // eslint-disable-next-line @typescript-eslint/no-unused-vars .filter(([_name, param]) => param.required) .map(([name]) => name); return { type: 'local', name: definition.name, description: definition.description, config: { timeout: definition.timeout || 60, parameters: { type: 'object', title: definition.title || `${definition.name} parameters`, required: requiredParams, properties: definition.parameters, }, output: { type: 'object', title: `${definition.name} output`, properties: definition.output, }, }, }; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export type ToolInstance = { schema: ToolSchema; implementation: (...args: any[]) => any }; /** * Create a complete tool definition with schema and implementation */ export function createTool(definition: ToolDefinition): ToolInstance { return { schema: generateToolSchema(definition), implementation: definition.implementation, }; } /** * Extract function signature and generate schema from a JavaScript function * This is a utility to help convert existing functions to tool schemas */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export function createToolFromFunction( name: string, description: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any fn: (...args: any[]) => any, parameterTypes: Record, outputTypes: Record, options?: { title?: string; timeout?: number; }, ): ToolInstance { const definition: ToolDefinition = { name, description, title: options?.title, timeout: options?.timeout, parameters: parameterTypes, output: outputTypes, implementation: fn, }; return createTool(definition); } // Example usage for the sum function you provided: export const sumTool = createToolFromFunction( 'sum', 'Sum two numbers', function sum(a: number, b: number) { const result = a + b; return { result }; }, { a: createParameter('number', 'First number to sum', { required: true }), b: createParameter('number', 'Second number to sum', { required: true }), }, { result: createParameter('number', 'Sum of two numbers'), }, ); // Example for the navigate_to function as shown in the user's request: export const navigateToToolExample = createTool({ name: 'navigate_to', description: 'Allow agent to redirect user to specific sub page like /foo or #/foo or anything like that', title: 'Sum two numbers', // As per the user's example timeout: 60, parameters: { a: createParameter('number', 'First number to sum'), b: createParameter('number', 'Seconth number to sum'), // Keeping the typo as in the original }, output: { result: createParameter('number', 'Sum of two numbers'), }, implementation: function navigateTo(a: number, b: number) { // This is just an example - you would implement actual navigation logic here const result = a + b; return { result }; }, }); // Helper function to create multiple tools at once export function createToolRegistry(tools: ToolDefinition[]): { schemas: ToolSchema[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any implementations: Record any>; } { const schemas: ToolSchema[] = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any const implementations: Record any> = {}; tools.forEach((tool) => { const { schema, implementation } = createTool(tool); schemas.push(schema); implementations[tool.name] = implementation; }); return { schemas, implementations }; } // Utility to validate tool parameters at runtime // eslint-disable-next-line @typescript-eslint/no-explicit-any export function validateToolParameters(parameters: Record, schema: ToolSchema): boolean { const { required, properties } = schema.config.parameters; // Check required parameters for (const requiredParam of required) { if (!(requiredParam in parameters)) { throw new Error(`Missing required parameter: ${requiredParam}`); } } // Type checking (basic) for (const [paramName, paramValue] of Object.entries(parameters)) { const paramSchema = properties[paramName]; if (paramSchema) { if (paramSchema.type === 'number' && typeof paramValue !== 'number') { throw new Error(`Parameter ${paramName} should be a number`); } if (paramSchema.type === 'string' && typeof paramValue !== 'string') { throw new Error(`Parameter ${paramName} should be a string`); } if (paramSchema.type === 'boolean' && typeof paramValue !== 'boolean') { throw new Error(`Parameter ${paramName} should be a boolean`); } } } return true; }