Update tool registration
| @@ -5,6 +5,7 @@ import { Popup } from './popup.js'; | |||
| 5 | /** | 5 | /** |
| 6 | * @typedef {object} ToolInvocation | 6 | * @typedef {object} ToolInvocation |
| 7 | * @property {string} id - A unique identifier for the tool invocation. | 7 | * @property {string} id - A unique identifier for the tool invocation. |
| 8 | * @property {string} displayName - The display name of the tool. | ||
| 8 | * @property {string} name - The name of the tool. | 9 | * @property {string} name - The name of the tool. |
| 9 | * @property {string} parameters - The parameters for the tool invocation. | 10 | * @property {string} parameters - The parameters for the tool invocation. |
| 10 | * @property {string} result - The result of the tool invocation. | 11 | * @property {string} result - The result of the tool invocation. |
| @@ -28,6 +29,12 @@ class ToolDefinition { | |||
| 28 | #name; | 29 | #name; |
| 29 | 30 | ||
| 30 | /** | 31 | /** |
| 32 | * A user-friendly display name for the tool. | ||
| 33 | * @type {string} | ||
| 34 | */ | ||
| 35 | #displayName; | ||
| 36 | |||
| 37 | /** | ||
| 31 | * A description of what the tool does. | 38 | * A description of what the tool does. |
| 32 | * @type {string} | 39 | * @type {string} |
| 33 | */ | 40 | */ |
| @@ -46,17 +53,27 @@ class ToolDefinition { | |||
| 46 | #action; | 53 | #action; |
| 47 | 54 | ||
| 48 | /** | 55 | /** |
| 56 | * A function that will be called to format the tool call toast. | ||
| 57 | * @type {function} | ||
| 58 | */ | ||
| 59 | #formatMessage; | ||
| 60 | |||
| 61 | /** | ||
| 49 | * Creates a new ToolDefinition. | 62 | * Creates a new ToolDefinition. |
| 50 | * @param {string} name A unique name for the tool. | 63 | * @param {string} name A unique name for the tool. |
| 64 | * @param {string} displayName A user-friendly display name for the tool. | ||
| 51 | * @param {string} description A description of what the tool does. | 65 | * @param {string} description A description of what the tool does. |
| 52 | * @param {object} parameters A JSON schema for the parameters that the tool accepts. | 66 | * @param {object} parameters A JSON schema for the parameters that the tool accepts. |
| 53 | * @param {function} action A function that will be called when the tool is executed. | 67 | * @param {function} action A function that will be called when the tool is executed. |
| 68 | * @param {function} formatMessage A function that will be called to format the tool call toast. | ||
| 54 | */ | 69 | */ |
| 55 | constructor(name, description, parameters, action) { | 70 | constructor(name, displayName, description, parameters, action, formatMessage) { |
| 56 | this.#name = name; | 71 | this.#name = name; |
| 72 | this.#displayName = displayName; | ||
| 57 | this.#description = description; | 73 | this.#description = description; |
| 58 | this.#parameters = parameters; | 74 | this.#parameters = parameters; |
| 59 | this.#action = action; | 75 | this.#action = action; |
| 76 | this.#formatMessage = formatMessage; | ||
| 60 | } | 77 | } |
| 61 | 78 | ||
| 62 | /** | 79 | /** |
| @@ -82,6 +99,21 @@ class ToolDefinition { | |||
| 82 | async invoke(parameters) { | 99 | async invoke(parameters) { |
| 83 | return await this.#action(parameters); | 100 | return await this.#action(parameters); |
| 84 | } | 101 | } |
| 102 | |||
| 103 | /** | ||
| 104 | * Formats a message with the tool invocation. | ||
| 105 | * @param {object} parameters The parameters to pass to the tool. | ||
| 106 | * @returns {string} The formatted message. | ||
| 107 | */ | ||
| 108 | formatMessage(parameters) { | ||
| 109 | return typeof this.#formatMessage === 'function' | ||
| 110 | ? this.#formatMessage(parameters) | ||
| 111 | : `Invoking tool: ${this.#displayName || this.#name}`; | ||
| 112 | } | ||
| 113 | |||
| 114 | get displayName() { | ||
| 115 | return this.#displayName; | ||
| 116 | } | ||
| 85 | } | 117 | } |
| 86 | 118 | ||
| 87 | /** | 119 | /** |
| @@ -104,17 +136,25 @@ export class ToolManager { | |||
| 104 | 136 | ||
| 105 | /** | 137 | /** |
| 106 | * Registers a new tool with the tool registry. | 138 | * Registers a new tool with the tool registry. |
| 107 | * @param {string} name The name of the tool. | 139 | * @param {object} tool The tool to register. |
| 108 | * @param {string} description A description of what the tool does. | 140 | * @param {string} tool.name The name of the tool. |
| 109 | * @param {object} parameters A JSON schema for the parameters that the tool accepts. | 141 | * @param {string} tool.displayName A user-friendly display name for the tool. |
| 110 | * @param {function} action A function that will be called when the tool is executed. | 142 | * @param {string} tool.description A description of what the tool does. |
| 143 | * @param {object} tool.parameters A JSON schema for the parameters that the tool accepts. | ||
| 144 | * @param {function} tool.action A function that will be called when the tool is executed. | ||
| 145 | * @param {function} tool.formatMessage A function that will be called to format the tool call toast. | ||
| 111 | */ | 146 | */ |
| 112 | static registerFunctionTool(name, description, parameters, action) { | 147 | static registerFunctionTool({ name, displayName, description, parameters, action, formatMessage }) { |
| 148 | // Convert WIP arguments | ||
| 149 | if (typeof arguments[0] !== 'object') { | ||
| 150 | [name, description, parameters, action] = arguments; | ||
| 151 | } | ||
| 152 | |||
| 113 | if (this.#tools.has(name)) { | 153 | if (this.#tools.has(name)) { |
| 114 | console.warn(`A tool with the name "${name}" has already been registered. The definition will be overwritten.`); | 154 | console.warn(`A tool with the name "${name}" has already been registered. The definition will be overwritten.`); |
| 115 | } | 155 | } |
| 116 | 156 | ||
| 117 | const definition = new ToolDefinition(name, description, parameters, action); | 157 | const definition = new ToolDefinition(name, displayName, description, parameters, action, formatMessage); |
| 118 | this.#tools.set(name, definition); | 158 | this.#tools.set(name, definition); |
| 119 | console.log('[ToolManager] Registered function tool:', definition); | 159 | console.log('[ToolManager] Registered function tool:', definition); |
| 120 | } | 160 | } |
| @@ -161,6 +201,35 @@ export class ToolManager { | |||
| 161 | } | 201 | } |
| 162 | } | 202 | } |
| 163 | 203 | ||
| 204 | static formatToolCallMessage(name, parameters) { | ||
| 205 | if (!this.#tools.has(name)) { | ||
| 206 | return `Invoked unknown tool: ${name}`; | ||
| 207 | } | ||
| 208 | |||
| 209 | try { | ||
| 210 | const tool = this.#tools.get(name); | ||
| 211 | const formatParameters = typeof parameters === 'string' ? JSON.parse(parameters) : parameters; | ||
| 212 | return tool.formatMessage(formatParameters); | ||
| 213 | } catch (error) { | ||
| 214 | console.error(`An error occurred while formatting the tool call message for "${name}":`, error); | ||
| 215 | return `Invoking tool: ${name}`; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | /** | ||
| 220 | * Gets the display name of a tool by name. | ||
| 221 | * @param {string} name | ||
| 222 | * @returns {string} The display name of the tool. | ||
| 223 | */ | ||
| 224 | static getDisplayName(name) { | ||
| 225 | if (!this.#tools.has(name)) { | ||
| 226 | return name; | ||
| 227 | } | ||
| 228 | |||
| 229 | const tool = this.#tools.get(name); | ||
| 230 | return tool.displayName || name; | ||
| 231 | } | ||
| 232 | |||
| 164 | /** | 233 | /** |
| 165 | * Register function tools for the next chat completion request. | 234 | * Register function tools for the next chat completion request. |
| 166 | * @param {object} data Generation data | 235 | * @param {object} data Generation data |
| @@ -352,9 +421,11 @@ export class ToolManager { | |||
| 352 | const id = toolCall.id; | 421 | const id = toolCall.id; |
| 353 | const parameters = toolCall.function.arguments; | 422 | const parameters = toolCall.function.arguments; |
| 354 | const name = toolCall.function.name; | 423 | const name = toolCall.function.name; |
| 424 | const displayName = ToolManager.getDisplayName(name); | ||
| 355 | result.hadToolCalls = true; | 425 | result.hadToolCalls = true; |
| 356 | 426 | ||
| 357 | const toast = toastr.info(`Invoking function tool: ${name}`); | 427 | const message = ToolManager.formatToolCallMessage(name, parameters); |
| 428 | const toast = message && toastr.info(message, 'Tool Calling', { timeOut: 0 }); | ||
| 358 | const toolResult = await ToolManager.invokeFunctionTool(name, parameters); | 429 | const toolResult = await ToolManager.invokeFunctionTool(name, parameters); |
| 359 | toastr.clear(toast); | 430 | toastr.clear(toast); |
| 360 | console.log('Function tool result:', result); | 431 | console.log('Function tool result:', result); |
| @@ -365,7 +436,14 @@ export class ToolManager { | |||
| 365 | continue; | 436 | continue; |
| 366 | } | 437 | } |
| 367 | 438 | ||
| 368 | result.invocations.push({ id, name, parameters, result: toolResult }); | 439 | const invocation = { |
| 440 | id, | ||
| 441 | displayName, | ||
| 442 | name, | ||
| 443 | parameters, | ||
| 444 | result: toolResult, | ||
| 445 | }; | ||
| 446 | result.invocations.push(invocation); | ||
| 369 | } | 447 | } |
| 370 | } | 448 | } |
| 371 | 449 | ||
| @@ -414,8 +492,8 @@ export class ToolManager { | |||
| 414 | codeElement.classList.add('language-json'); | 492 | codeElement.classList.add('language-json'); |
| 415 | data.forEach(i => i.parameters = tryParse(i.parameters)); | 493 | data.forEach(i => i.parameters = tryParse(i.parameters)); |
| 416 | codeElement.textContent = JSON.stringify(data, null, 2); | 494 | codeElement.textContent = JSON.stringify(data, null, 2); |
| 417 | const toolNames = data.map(i => i.name).join(', '); | 495 | const toolNames = data.map(i => i.displayName || i.name).join(', '); |
| 418 | summaryElement.textContent = `Performed tool calls: ${toolNames}`; | 496 | summaryElement.textContent = `Tool calls: ${toolNames}`; |
| 419 | preElement.append(codeElement); | 497 | preElement.append(codeElement); |
| 420 | detailsElement.append(summaryElement, preElement); | 498 | detailsElement.append(summaryElement, preElement); |
| 421 | return detailsElement.outerHTML; | 499 | return detailsElement.outerHTML; |