custom-tool.ts
1 /** 2 * Custom Tool Example 3 * Demonstrates creating custom tools using BaseTool class (plugin pattern) 4 */ 5 6 import { BaseTool, createTool, tool, ToolRegistry } from 'praisonai'; 7 8 // Method 1: Extend BaseTool class (recommended for complex tools) 9 class WeatherTool extends BaseTool<{ location: string; units?: string }, { temp: number; condition: string }> { 10 name = 'get_weather'; 11 description = 'Get current weather for a location'; 12 parameters = { 13 type: 'object' as const, 14 properties: { 15 location: { type: 'string', description: 'City name' }, 16 units: { type: 'string', description: 'celsius or fahrenheit', default: 'celsius' } 17 }, 18 required: ['location'] 19 }; 20 21 async run(params: { location: string; units?: string }): Promise<{ temp: number; condition: string }> { 22 // Simulate API call 23 console.log(`Getting weather for ${params.location} in ${params.units || 'celsius'}`); 24 return { temp: 22, condition: 'sunny' }; 25 } 26 } 27 28 // Method 2: Use createTool function (quick inline tools) 29 const calculatorTool = createTool({ 30 name: 'calculator', 31 description: 'Evaluate a math expression', 32 parameters: { 33 type: 'object', 34 properties: { 35 expression: { type: 'string', description: 'Math expression to evaluate' } 36 }, 37 required: ['expression'] 38 }, 39 run: (params: { expression: string }) => { 40 try { 41 // Only allow safe numeric math characters 42 if (!/^[0-9+\-*/.() ]+$/.test(params.expression)) { 43 return 'Error: Only basic math expressions are allowed'; 44 } 45 const result = new Function(`"use strict"; return (${params.expression})`)(); 46 if (typeof result !== 'number' || !isFinite(result)) return 'Error: Invalid result'; 47 return result; 48 } catch { 49 return 'Error: Invalid expression'; 50 } 51 } 52 }); 53 54 // Method 3: Use tool() function with config object 55 const greeterTool = tool({ 56 name: 'greeter', 57 description: 'Generate a personalized greeting', 58 parameters: { 59 type: 'object', 60 properties: { 61 name: { type: 'string', description: 'Name to greet' }, 62 style: { type: 'string', description: 'Greeting style: formal or casual' } 63 }, 64 required: ['name'] 65 }, 66 execute: async (params: { name: string; style?: string }) => { 67 if (params.style === 'formal') { 68 return `Good day, ${params.name}. How may I assist you?`; 69 } 70 return `Hey ${params.name}! What's up?`; 71 } 72 }); 73 74 async function main() { 75 console.log('=== Custom Tool Examples ===\n'); 76 77 // Test WeatherTool (class-based) 78 console.log('--- WeatherTool (class-based) ---'); 79 const weather = new WeatherTool(); 80 console.log('Name:', weather.name); 81 console.log('Description:', weather.description); 82 83 const weatherResult = await weather.run({ location: 'New York' }); 84 console.log('Result:', weatherResult); 85 86 // Safe execution with error handling 87 const safeResult = await weather.safeRun({ location: 'London' }); 88 console.log('Safe result:', safeResult); 89 90 // Get OpenAI schema 91 console.log('OpenAI Schema:', JSON.stringify(weather.getSchema(), null, 2)); 92 93 // Test calculatorTool (createTool) 94 console.log('\n--- Calculator Tool (createTool) ---'); 95 const calcResult = await calculatorTool.run({ expression: '10 * 5 + 2' }); 96 console.log('10 * 5 + 2 =', calcResult); 97 98 // Test greeterTool (tool function) 99 console.log('\n--- Greeter Tool (tool function) ---'); 100 const greeting1 = await greeterTool.execute({ name: 'Alice' }); 101 console.log('Casual:', greeting1); 102 103 const greeting2 = await greeterTool.execute({ name: 'Mr. Smith', style: 'formal' }); 104 console.log('Formal:', greeting2); 105 106 // Register tools in registry 107 console.log('\n--- Tool Registry ---'); 108 const registry = new ToolRegistry(); 109 registry.register(greeterTool); 110 111 console.log('Registered tools:', registry.list().map(t => t.name)); 112 console.log('OpenAI tools format:', registry.toOpenAITools().length, 'tools'); 113 114 // Validate tool 115 console.log('\n--- Validation ---'); 116 console.log('WeatherTool valid:', weather.validate()); 117 } 118 119 main().catch(console.error);