Tool Calling: add shouldRegister function to tool defintion
| @@ -32,6 +32,7 @@ import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHel | |||
| 32 | * @property {object} parameters - The parameters for the tool. | 32 | * @property {object} parameters - The parameters for the tool. |
| 33 | * @property {function} action - The action to perform when the tool is invoked. | 33 | * @property {function} action - The action to perform when the tool is invoked. |
| 34 | * @property {function} formatMessage - A function to format the tool call message. | 34 | * @property {function} formatMessage - A function to format the tool call message. |
| 35 | * @property {function} shouldRegister - A function to determine if the tool should be registered. | ||
| 35 | */ | 36 | */ |
| 36 | 37 | ||
| 37 | /** | 38 | /** |
| @@ -138,6 +139,12 @@ class ToolDefinition { | |||
| 138 | #formatMessage; | 139 | #formatMessage; |
| 139 | 140 | ||
| 140 | /** | 141 | /** |
| 142 | * A function that will be called to determine if the tool should be registered. | ||
| 143 | * @type {function} | ||
| 144 | */ | ||
| 145 | #shouldRegister; | ||
| 146 | |||
| 147 | /** | ||
| 141 | * Creates a new ToolDefinition. | 148 | * Creates a new ToolDefinition. |
| 142 | * @param {string} name A unique name for the tool. | 149 | * @param {string} name A unique name for the tool. |
| 143 | * @param {string} displayName A user-friendly display name for the tool. | 150 | * @param {string} displayName A user-friendly display name for the tool. |
| @@ -145,14 +152,16 @@ class ToolDefinition { | |||
| 145 | * @param {object} parameters A JSON schema for the parameters that the tool accepts. | 152 | * @param {object} parameters A JSON schema for the parameters that the tool accepts. |
| 146 | * @param {function} action A function that will be called when the tool is executed. | 153 | * @param {function} action A function that will be called when the tool is executed. |
| 147 | * @param {function} formatMessage A function that will be called to format the tool call toast. | 154 | * @param {function} formatMessage A function that will be called to format the tool call toast. |
| 155 | * @param {function} shouldRegister A function that will be called to determine if the tool should be registered. | ||
| 148 | */ | 156 | */ |
| 149 | constructor(name, displayName, description, parameters, action, formatMessage) { | 157 | constructor(name, displayName, description, parameters, action, formatMessage, shouldRegister) { |
| 150 | this.#name = name; | 158 | this.#name = name; |
| 151 | this.#displayName = displayName; | 159 | this.#displayName = displayName; |
| 152 | this.#description = description; | 160 | this.#description = description; |
| 153 | this.#parameters = parameters; | 161 | this.#parameters = parameters; |
| 154 | this.#action = action; | 162 | this.#action = action; |
| 155 | this.#formatMessage = formatMessage; | 163 | this.#formatMessage = formatMessage; |
| 164 | this.#shouldRegister = shouldRegister; | ||
| 156 | } | 165 | } |
| 157 | 166 | ||
| 158 | /** | 167 | /** |
| @@ -193,6 +202,12 @@ class ToolDefinition { | |||
| 193 | : `Invoking tool: ${this.#displayName || this.#name}`; | 202 | : `Invoking tool: ${this.#displayName || this.#name}`; |
| 194 | } | 203 | } |
| 195 | 204 | ||
| 205 | async shouldRegister() { | ||
| 206 | return typeof this.#shouldRegister === 'function' | ||
| 207 | ? await this.#shouldRegister() | ||
| 208 | : true; | ||
| 209 | } | ||
| 210 | |||
| 196 | get displayName() { | 211 | get displayName() { |
| 197 | return this.#displayName; | 212 | return this.#displayName; |
| 198 | } | 213 | } |
| @@ -228,17 +243,17 @@ export class ToolManager { | |||
| 228 | * Registers a new tool with the tool registry. | 243 | * Registers a new tool with the tool registry. |
| 229 | * @param {ToolRegistration} tool The tool to register. | 244 | * @param {ToolRegistration} tool The tool to register. |
| 230 | */ | 245 | */ |
| 231 | static registerFunctionTool({ name, displayName, description, parameters, action, formatMessage }) { | 246 | static registerFunctionTool({ name, displayName, description, parameters, action, formatMessage, shouldRegister }) { |
| 232 | // Convert WIP arguments | 247 | // Convert WIP arguments |
| 233 | if (typeof arguments[0] !== 'object') { | 248 | if (typeof arguments[0] !== 'object') { |
| 234 | [name, description, parameters, action] = arguments; | 249 | [name, description, parameters, action] = arguments; |
| 235 | } | 250 | } |
| 236 | 251 | ||
| 237 | if (this.#tools.has(name)) { | 252 | if (this.#tools.has(name)) { |
| 238 | console.warn(`A tool with the name "${name}" has already been registered. The definition will be overwritten.`); | 253 | console.warn(`[ToolManager] A tool with the name "${name}" has already been registered. The definition will be overwritten.`); |
| 239 | } | 254 | } |
| 240 | 255 | ||
| 241 | const definition = new ToolDefinition(name, displayName, description, parameters, action, formatMessage); | 256 | const definition = new ToolDefinition(name, displayName, description, parameters, action, formatMessage, shouldRegister); |
| 242 | this.#tools.set(name, definition); | 257 | this.#tools.set(name, definition); |
| 243 | console.log('[ToolManager] Registered function tool:', definition); | 258 | console.log('[ToolManager] Registered function tool:', definition); |
| 244 | } | 259 | } |
| @@ -273,7 +288,7 @@ export class ToolManager { | |||
| 273 | const result = await tool.invoke(invokeParameters); | 288 | const result = await tool.invoke(invokeParameters); |
| 274 | return typeof result === 'string' ? result : JSON.stringify(result); | 289 | return typeof result === 'string' ? result : JSON.stringify(result); |
| 275 | } catch (error) { | 290 | } catch (error) { |
| 276 | console.error(`An error occurred while invoking the tool "${name}":`, error); | 291 | console.error(`[ToolManager] An error occurred while invoking the tool "${name}":`, error); |
| 277 | 292 | ||
| 278 | if (error instanceof Error) { | 293 | if (error instanceof Error) { |
| 279 | error.cause = name; | 294 | error.cause = name; |
| @@ -300,7 +315,7 @@ export class ToolManager { | |||
| 300 | const formatParameters = typeof parameters === 'string' ? JSON.parse(parameters) : parameters; | 315 | const formatParameters = typeof parameters === 'string' ? JSON.parse(parameters) : parameters; |
| 301 | return tool.formatMessage(formatParameters); | 316 | return tool.formatMessage(formatParameters); |
| 302 | } catch (error) { | 317 | } catch (error) { |
| 303 | console.error(`An error occurred while formatting the tool call message for "${name}":`, error); | 318 | console.error(`[ToolManager] An error occurred while formatting the tool call message for "${name}":`, error); |
| 304 | return `Invoking tool: ${name}`; | 319 | return `Invoking tool: ${name}`; |
| 305 | } | 320 | } |
| 306 | } | 321 | } |
| @@ -327,11 +342,16 @@ export class ToolManager { | |||
| 327 | const tools = []; | 342 | const tools = []; |
| 328 | 343 | ||
| 329 | for (const tool of ToolManager.tools) { | 344 | for (const tool of ToolManager.tools) { |
| 345 | const register = await tool.shouldRegister(); | ||
| 346 | if (!register) { | ||
| 347 | console.log('[ToolManager] Skipping tool registration:', tool); | ||
| 348 | continue; | ||
| 349 | } | ||
| 330 | tools.push(tool.toFunctionOpenAI()); | 350 | tools.push(tool.toFunctionOpenAI()); |
| 331 | } | 351 | } |
| 332 | 352 | ||
| 333 | if (tools.length) { | 353 | if (tools.length) { |
| 334 | console.log('Registered function tools:', tools); | 354 | console.log('[ToolManager] Registered function tools:', tools); |
| 335 | 355 | ||
| 336 | data['tools'] = tools; | 356 | data['tools'] = tools; |
| 337 | data['tool_choice'] = 'auto'; | 357 | data['tool_choice'] = 'auto'; |
| @@ -422,7 +442,7 @@ export class ToolManager { | |||
| 422 | delete targetToolCall[this.#INPUT_DELTA_KEY]; | 442 | delete targetToolCall[this.#INPUT_DELTA_KEY]; |
| 423 | ToolManager.#applyToolCallDelta(targetToolCall, jsonDelta); | 443 | ToolManager.#applyToolCallDelta(targetToolCall, jsonDelta); |
| 424 | } catch (error) { | 444 | } catch (error) { |
| 425 | console.warn('Failed to apply input JSON delta:', error); | 445 | console.warn('[ToolManager] Failed to apply input JSON delta:', error); |
| 426 | } | 446 | } |
| 427 | } | 447 | } |
| 428 | } | 448 | } |
| @@ -564,7 +584,7 @@ export class ToolManager { | |||
| 564 | continue; | 584 | continue; |
| 565 | } | 585 | } |
| 566 | 586 | ||
| 567 | console.log('Function tool call:', toolCall); | 587 | console.log('[ToolManager] Function tool call:', toolCall); |
| 568 | const id = toolCall.id; | 588 | const id = toolCall.id; |
| 569 | const parameters = toolCall.function.arguments; | 589 | const parameters = toolCall.function.arguments; |
| 570 | const name = toolCall.function.name; | 590 | const name = toolCall.function.name; |
| @@ -574,7 +594,7 @@ export class ToolManager { | |||
| 574 | const toast = message && toastr.info(message, 'Tool Calling', { timeOut: 0 }); | 594 | const toast = message && toastr.info(message, 'Tool Calling', { timeOut: 0 }); |
| 575 | const toolResult = await ToolManager.invokeFunctionTool(name, parameters); | 595 | const toolResult = await ToolManager.invokeFunctionTool(name, parameters); |
| 576 | toastr.clear(toast); | 596 | toastr.clear(toast); |
| 577 | console.log('Function tool result:', result); | 597 | console.log('[ToolManager] Function tool result:', result); |
| 578 | 598 | ||
| 579 | // Save a successful invocation | 599 | // Save a successful invocation |
| 580 | if (toolResult instanceof Error) { | 600 | if (toolResult instanceof Error) { |