Update tool registration

5cf64a2613252cc9ab8557fe145fab7546ea56ec

Cohee <18619528+Cohee1207@users.noreply.github.com>

1 files changed, +89 -11Ignore whitespace
public/scripts/tool-calling.js+89 -11
@@ -5,6 +5,7 @@ import { Popup } from './popup.js';
5/**5/**
6 * @typedef {object} ToolInvocation6 * @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;
2930
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;
4754
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 }
6178
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}
86118
87/**119/**
@@ -104,17 +136,25 @@ export class ToolManager {
104136
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 }
116156
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 }
163203
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 data235 * @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;
356426
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 }
367438
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 }
371449
@@ -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;