diff --git a/src/praisonai-ts/examples/simple/direct-function-tools.ts b/src/praisonai-ts/examples/simple/direct-function-tools.ts new file mode 100644 index 000000000..5e780c417 --- /dev/null +++ b/src/praisonai-ts/examples/simple/direct-function-tools.ts @@ -0,0 +1,35 @@ +import { Agent } from 'praisonai'; + +/** + * Example of a simple agent with direct function registration + * + * This example demonstrates how to create a simple agent that uses directly + * registered functions as tools without having to define tool schemas manually + * or make functions globally available. + */ + +// Define the functions directly +async function getWeather(location: string) { + console.log(`Getting weather for ${location}...`); + return `${Math.floor(Math.random() * 30)}°C`; +} + +async function getTime(location: string) { + console.log(`Getting time for ${location}...`); + const now = new Date(); + return `${now.getHours()}:${now.getMinutes()}`; +} + +// Create an agent with directly registered functions +const agent = new Agent({ + instructions: `You provide the current weather and time for requested locations.`, + name: "DirectFunctionAgent", + // Register functions directly without needing to make them global + toolFunctions: { + get_weather: getWeather, + get_time: getTime + } +}); + +// Start the agent with a prompt that will trigger tool usage +agent.start("What's the weather and time in Paris, France and Tokyo, Japan?"); diff --git a/src/praisonai-ts/examples/simple/multi-tool-call.ts b/src/praisonai-ts/examples/simple/multi-tool-call.ts new file mode 100644 index 000000000..596ec7235 --- /dev/null +++ b/src/praisonai-ts/examples/simple/multi-tool-call.ts @@ -0,0 +1,73 @@ +import { Agent } from 'praisonai'; + +/** + * Example of a simple agent with multiple tool calling capability + * + * This example demonstrates how to create a simple agent that can use multiple tools + * to get weather and time information for different locations. + */ + +// Define a weather tool +const getWeather = { + type: "function", + function: { + name: "get_weather", + description: "Get current temperature for a given location.", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City and country e.g. Bogotá, Colombia" + } + }, + required: ["location"], + additionalProperties: false + }, + strict: true + } +}; + +// Define a time tool +const getTime = { + type: "function", + function: { + name: "get_time", + description: "Get current time for a given location.", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City and country e.g. Bogotá, Colombia" + } + }, + required: ["location"], + additionalProperties: false + }, + strict: true + } +}; + +// Make the functions globally available +// The agent will automatically find and use these functions +(global as any).get_weather = async function(location: string) { + console.log(`Getting weather for ${location}...`); + return `${Math.floor(Math.random() * 30)}°C`; +}; + +(global as any).get_time = async function(location: string) { + console.log(`Getting time for ${location}...`); + const now = new Date(); + return `${now.getHours()}:${now.getMinutes()}`; +}; + +// Create an agent with both weather and time tools +const agent = new Agent({ + instructions: `You provide the current weather and time for requested locations.`, + name: "WeatherTimeAgent", + tools: [getWeather, getTime] +}); + +// Start the agent with a prompt that will trigger multiple tool calls +agent.start("What's the weather and time in Paris, France and Tokyo, Japan?"); diff --git a/src/praisonai-ts/examples/simple/single-agent-tool-call.ts b/src/praisonai-ts/examples/simple/single-agent-tool-call.ts new file mode 100644 index 000000000..348da0ead --- /dev/null +++ b/src/praisonai-ts/examples/simple/single-agent-tool-call.ts @@ -0,0 +1,46 @@ +import { Agent } from 'praisonai'; + +/** + * Example of a simple agent with tool calling capability + * + * This example demonstrates how to create a simple agent that can use tools + * to get weather information for a location. + */ + +// Define a weather tool +const getWeather = { + type: "function", + function: { + name: "get_weather", + description: "Get current temperature for a given location.", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City and country e.g. Bogotá, Colombia" + } + }, + required: ["location"], + additionalProperties: false + }, + strict: true + } +}; + +// Make the function globally available +// The agent will automatically find and use this function +(global as any).get_weather = async function(location: string) { + console.log(`Getting weather for ${location}...`); + return `20°C`; +}; + +// Create an agent with the weather tool +const agent = new Agent({ + instructions: `You provide the current weather for requested locations.`, + name: "WeatherAgent", + tools: [getWeather] +}); + +// Start the agent with a prompt that will trigger tool usage +agent.start("What's the weather in Paris, France?"); diff --git a/src/praisonai-ts/package.json b/src/praisonai-ts/package.json index 85c88e147..4fbe3c220 100644 --- a/src/praisonai-ts/package.json +++ b/src/praisonai-ts/package.json @@ -1,6 +1,6 @@ { "name": "praisonai", - "version": "1.0.17", + "version": "1.0.18", "description": "PraisonAI TypeScript AI Agents Framework - Node.js, npm, and Javascript AI Agents Framework", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -62,7 +62,7 @@ "fast-xml-parser": "^4.5.1", "node-fetch": "^2.6.9", "openai": "^4.81.0", - "praisonai": "^1.0.12" + "praisonai": "^1.0.17" }, "optionalDependencies": { "boxen": "^7.1.1", diff --git a/src/praisonai-ts/src/agent/index.ts b/src/praisonai-ts/src/agent/index.ts index 1056b3716..139949447 100644 --- a/src/praisonai-ts/src/agent/index.ts +++ b/src/praisonai-ts/src/agent/index.ts @@ -6,6 +6,7 @@ export function setTaskMode(enabled: boolean) { } export { Agent, PraisonAIAgents, Task } from './proxy'; +export type { ProxyAgentConfig } from './proxy'; export type { AgentConfig } from './types'; export type { TaskConfig } from './types'; -export type { PraisonAIAgentsConfig } from './simple'; +export type { PraisonAIAgentsConfig, SimpleAgentConfig } from './simple'; diff --git a/src/praisonai-ts/src/agent/proxy.ts b/src/praisonai-ts/src/agent/proxy.ts index d4862a723..1c0d87f58 100644 --- a/src/praisonai-ts/src/agent/proxy.ts +++ b/src/praisonai-ts/src/agent/proxy.ts @@ -6,6 +6,7 @@ import type { ChatCompletionTool } from 'openai/resources/chat/completions'; export interface ProxyAgentConfig extends Partial, Partial { task?: Task; tools?: any[]; + toolFunctions?: Record; } export class Agent { @@ -35,7 +36,8 @@ export class Agent { verbose: config.verbose, llm: config.llm, markdown: config.markdown, - tools: config.tools + tools: config.tools, + toolFunctions: config.toolFunctions }; this.simpleAgent = new SimpleAgent(simpleConfig); } diff --git a/src/praisonai-ts/src/agent/simple.ts b/src/praisonai-ts/src/agent/simple.ts index d407f346c..95705ab5c 100644 --- a/src/praisonai-ts/src/agent/simple.ts +++ b/src/praisonai-ts/src/agent/simple.ts @@ -11,6 +11,7 @@ export interface SimpleAgentConfig { markdown?: boolean; stream?: boolean; tools?: any[]; + toolFunctions?: Record; } export class Agent { @@ -39,6 +40,18 @@ export class Agent { // Configure logging Logger.setVerbose(this.verbose); Logger.setPretty(this.pretty); + + // Register directly provided tool functions if any + if (config.toolFunctions) { + for (const [name, func] of Object.entries(config.toolFunctions)) { + this.registerToolFunction(name, func); + + // Auto-generate tool definition if not already provided + if (!this.hasToolDefinition(name)) { + this.addAutoGeneratedToolDefinition(name, func); + } + } + } } private createSystemPrompt(): string { @@ -58,6 +71,76 @@ export class Agent { this.toolFunctions[name] = fn; Logger.debug(`Registered tool function: ${name}`); } + + /** + * Check if a tool definition exists for the given function name + * @param name Function name + * @returns True if a tool definition exists + */ + private hasToolDefinition(name: string): boolean { + if (!this.tools) return false; + + return this.tools.some(tool => { + if (tool.type === 'function' && tool.function) { + return tool.function.name === name; + } + return false; + }); + } + + /** + * Auto-generate a tool definition based on the function + * @param name Function name + * @param func Function implementation + */ + private addAutoGeneratedToolDefinition(name: string, func: Function): void { + if (!this.tools) { + this.tools = []; + } + + // Extract parameter names from function + const funcStr = func.toString(); + const paramMatch = funcStr.match(/\(([^)]*)\)/); + const params = paramMatch ? paramMatch[1].split(',').map(p => p.trim()).filter(p => p) : []; + + // Create a basic tool definition + const toolDef = { + type: "function", + function: { + name, + description: `Auto-generated function for ${name}`, + parameters: { + type: "object", + properties: {}, + required: [] as string[] + } + } + }; + + // Add parameters to the definition + if (params.length > 0) { + const properties: Record = {}; + const required: string[] = []; + + params.forEach(param => { + // Remove type annotations if present + const paramName = param.split(':')[0].trim(); + if (paramName) { + properties[paramName] = { + type: "string", + description: `Parameter ${paramName} for function ${name}` + }; + required.push(paramName); + } + }); + + toolDef.function.parameters.properties = properties; + toolDef.function.parameters.required = required; + } + + this.tools.push(toolDef); + Logger.debug(`Auto-generated tool definition for ${name}`); + } /** * Process tool calls from the model diff --git a/src/praisonai-ts/tests/development/simple/direct-function-tools.ts b/src/praisonai-ts/tests/development/simple/direct-function-tools.ts new file mode 100644 index 000000000..2665c9085 --- /dev/null +++ b/src/praisonai-ts/tests/development/simple/direct-function-tools.ts @@ -0,0 +1,35 @@ +import { Agent } from '../../../src/agent/proxy'; + +/** + * Example of a simple agent with direct function registration + * + * This example demonstrates how to create a simple agent that uses directly + * registered functions as tools without having to define tool schemas manually + * or make functions globally available. + */ + +// Define the functions directly +async function getWeather(location: string) { + console.log(`Getting weather for ${location}...`); + return `${Math.floor(Math.random() * 30)}°C`; +} + +async function getTime(location: string) { + console.log(`Getting time for ${location}...`); + const now = new Date(); + return `${now.getHours()}:${now.getMinutes()}`; +} + +// Create an agent with directly registered functions +const agent = new Agent({ + instructions: `You provide the current weather and time for requested locations.`, + name: "DirectFunctionAgent", + // Register functions directly without needing to make them global + toolFunctions: { + get_weather: getWeather, + get_time: getTime + } +}); + +// Start the agent with a prompt that will trigger tool usage +agent.start("What's the weather and time in Paris, France and Tokyo, Japan?");