From 313b5f6db70afbce6ce16d7cc09dea7a184e2c70 Mon Sep 17 00:00:00 2001 From: hanishkvc Date: Thu, 6 Nov 2025 18:51:42 +0530 Subject: [PATCH] SimpleChatTC:TrackToolCalls:helps ignor delayed response, if reqd Add a pending object which maintains the pending toolcallid wrt each chat session, when ever a tool call is made. In turn when ever a tool call response is got cross check if its toolcallid matches that in the pending list. If so accept the tool call response and remove from pending list. If not just ignore the response. NOTE: The current implementation supports only 1 pending tool call at any time. NOTE: Had to change from a anonymous to arrow function so as to be able to get access to the ToolsManager instance (this) from within the function. ie make use of lexical binding semantic of arrow functions. --- tools/server/public_simplechat/tools.mjs | 54 +++++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tools/server/public_simplechat/tools.mjs b/tools/server/public_simplechat/tools.mjs index b3aa3d843f..9c955415a6 100644 --- a/tools/server/public_simplechat/tools.mjs +++ b/tools/server/public_simplechat/tools.mjs @@ -26,6 +26,12 @@ export class ToolsManager { db: /** @type {Worker} */(/** @type {unknown} */(undefined)), } + /** + * Maintain the latest pending tool call id for each unique chat session id + * @type {Object} + */ + this.pending = {} + } setup_workers() { @@ -74,6 +80,43 @@ export class ToolsManager { return tools } + /** + * Add specified toolcallid to pending list for specified chat session id. + * @param {string} chatid + * @param {string} toolcallid + */ + toolcallpending_add(chatid, toolcallid) { + console.debug(`DBUG:ToolsManager:ToolCallPendingAdd:${chatid}:${toolcallid}`) + this.pending[chatid] = toolcallid; + } + + /** + * Clear pending list for specified chat session id. + * @param {string} chatid + * @param {string} tag + */ + toolcallpending_clear(chatid, tag) { + let curtcid = this.pending[chatid]; + console.debug(`DBUG:ToolsManager:ToolCallPendingClear:${tag}:${chatid}:${curtcid}`) + delete(this.pending[chatid]); + } + + /** + * Check if there is a pending tool call awaiting tool call result for given chat session id. + * Clears from pending list, if found. + * @param {string} chatid + * @param {string} toolcallid + * @param {string} tag + */ + toolcallpending_found_cleared(chatid, toolcallid, tag) { + if (this.pending[chatid] !== toolcallid) { + console.log(`WARN:ToolsManager:ToolCallPendingFoundCleared:${tag}:${chatid}:${toolcallid} not found, skipping...`) + return false + } + this.toolcallpending_clear(chatid, tag) + return true + } + /** * Try call the specified tool/function call. * Returns undefined, if the call was placed successfully @@ -87,6 +130,7 @@ export class ToolsManager { for (const fn in this.tc_switch) { if (fn == toolname) { try { + this.toolcallpending_add(chatid, toolcallid); this.tc_switch[fn]["handler"](chatid, toolcallid, fn, JSON.parse(toolargs)) return undefined } catch (/** @type {any} */error) { @@ -103,10 +147,16 @@ export class ToolsManager { * @param {(chatId: string, toolCallId: string, name: string, data: string) => void} cb */ workers_cb(cb) { - this.workers.js.onmessage = function (ev) { + this.workers.js.onmessage = (ev) => { + if (!this.toolcallpending_found_cleared(ev.data.cid, ev.data.tcid, 'js')) { + return + } cb(ev.data.cid, ev.data.tcid, ev.data.name, ev.data.data) } - this.workers.db.onmessage = function (ev) { + this.workers.db.onmessage = (ev) => { + if (!this.toolcallpending_found_cleared(ev.data.cid, ev.data.tcid, 'db')) { + return + } cb(ev.data.cid, ev.data.tcid, ev.data.name, JSON.stringify(ev.data.data, (k,v)=>{ return (v === undefined) ? '__UNDEFINED__' : v; }));