diff --git a/tools/server/public_simplechat/main.js b/tools/server/public_simplechat/main.js index e441dab74a..652228058a 100644 --- a/tools/server/public_simplechat/main.js +++ b/tools/server/public_simplechat/main.js @@ -26,10 +26,12 @@ function startme() { gMe = new mChatMagic.Me(); gMe.debug_disable(); devel_expose() - gMe.toolsMgr.init(gMe).then(()=>{ + gMe.toolsMgr.init(gMe).then(async ()=>{ + let sL = [] for (let cid of gMe.defaultChatIds) { - gMe.multiChat.new_chat_session(cid); + sL.push(gMe.multiChat.new_chat_session(cid)); } + await Promise.allSettled(sL) gMe.multiChat.setup_ui(gMe.defaultChatIds[0]); gMe.multiChat.show_sessions(); gMe.multiChat.handle_session_switch(gMe.multiChat.curChatId) diff --git a/tools/server/public_simplechat/simplechat.js b/tools/server/public_simplechat/simplechat.js index c2ac025304..51f3642733 100644 --- a/tools/server/public_simplechat/simplechat.js +++ b/tools/server/public_simplechat/simplechat.js @@ -525,10 +525,13 @@ class ELDivStream { export class SimpleChat { /** + * Create an instance of SimpleChat + * * dont forget to call setup * @param {string} chatId * @param {Config} cfg + * @param {mTools.ToolsManager} toolsMgr */ - constructor(chatId, cfg) { + constructor(chatId, cfg, toolsMgr) { this.chatId = chatId; /** * Maintain in a form suitable for common LLM web service chat/completions' messages entry @@ -538,6 +541,7 @@ export class SimpleChat { this.iLastSys = -1; this.latestResponse = new ChatMessageEx(); this.cfg = Config.clone(cfg); + this.toolsMgr = toolsMgr } clear() { @@ -546,6 +550,10 @@ export class SimpleChat { this.latestResponse = new ChatMessageEx(); } + setup() { + return this.toolsMgr.setup(this.chatId) + } + /** * Given a string, gives the equivalent simplified string which could be used as chatId. * * Converts the very 1st char into upper case. @@ -835,7 +843,7 @@ export class SimpleChat { obj["stream"] = true; } if (this.cfg.tools.enabled) { - obj["tools"] = this.me.toolsMgr.meta(); + obj["tools"] = this.toolsMgr.meta(this.chatId); } return JSON.stringify(obj); } @@ -1072,9 +1080,9 @@ export class SimpleChat { return "Tool/Function call name not specified" } try { - return await this.me.toolsMgr.tool_call(this.chatId, toolcallid, toolname, toolargs) + return await this.toolsMgr.tool_call(this.chatId, toolcallid, toolname, toolargs) } catch (/** @type {any} */error) { - this.me.toolsMgr.toolcallpending_found_cleared(this.chatId, toolcallid, 'SC:HandleToolCall:Exc') + this.toolsMgr.toolcallpending_found_cleared(this.chatId, toolcallid, 'SC:HandleToolCall:Exc') return `Tool/Function call raised an exception:${error.name}:${error.message}` } } @@ -1730,16 +1738,16 @@ class MultiChatUI { * @param {string} chatId * @param {boolean} bSwitchSession */ - new_chat_session(chatId, bSwitchSession=false) { - this.simpleChats[chatId] = new SimpleChat(chatId, this.me.defaultCfg); + async new_chat_session(chatId, bSwitchSession=false) { + this.simpleChats[chatId] = new SimpleChat(chatId, this.me.defaultCfg, this.me.toolsMgr); + await this.simpleChats[chatId].setup(); this.elDivStreams[chatId] = new ELDivStream(chatId); - this.elDivStreams[chatId].clear() + this.elDivStreams[chatId].clear(); if (bSwitchSession) { this.handle_session_switch(chatId); } } - /** * Handle user query submit request, wrt specified chat session. * @@ -1874,9 +1882,10 @@ class MultiChatUI { return; } chatIdGot = SimpleChat.ChatIdClean(chatIdGot) - this.new_chat_session(chatIdGot, true); - this.create_session_btn(elDiv, chatIdGot); - ui.el_children_config_class(elDiv, chatIdGot, "session-selected", ""); + this.new_chat_session(chatIdGot, true).then(()=>{ + this.create_session_btn(elDiv, chatIdGot); + ui.el_children_config_class(elDiv, chatIdGot, "session-selected", ""); + }) },"NewChat", "+ new"); btnNew.title = "start a new chat session" elDiv.appendChild(btnNew); diff --git a/tools/server/public_simplechat/toolai.mjs b/tools/server/public_simplechat/toolai.mjs index 1e5d957712..3833606bd4 100644 --- a/tools/server/public_simplechat/toolai.mjs +++ b/tools/server/public_simplechat/toolai.mjs @@ -6,6 +6,7 @@ // import * as mChatMagic from './simplechat.js' +import * as mToolsMgr from './tools.mjs' let gMe = /** @type{mChatMagic.Me} */(/** @type {unknown} */(null)); @@ -104,9 +105,9 @@ function externalai_run(chatid, toolcallid, toolname, obj) { /** - * @type {Object>} + * @type {mToolsMgr.TCSwitch} */ -export let tc_switch = { +let tc_switch = { "external_ai": { "handler": externalai_run, "meta": externalai_meta, @@ -125,3 +126,11 @@ export let tc_switch = { export async function init(me) { gMe = me } + + +/** + * @param {string} chatId + */ +export async function setup(chatId) { + return tc_switch; +} diff --git a/tools/server/public_simplechat/tooldb.mjs b/tools/server/public_simplechat/tooldb.mjs index 365006dced..6272bcf053 100644 --- a/tools/server/public_simplechat/tooldb.mjs +++ b/tools/server/public_simplechat/tooldb.mjs @@ -6,6 +6,7 @@ // import * as mChatMagic from './simplechat.js' +import * as mToolsMgr from './tools.mjs' let gMe = /** @type{mChatMagic.Me} */(/** @type {unknown} */(null)); @@ -101,9 +102,9 @@ function dsops_run(chatid, toolcallid, toolname, obj) { /** - * @type {Object>} + * @type {mToolsMgr.TCSwitch} */ -export let tc_switch = { +let tc_switch = { "data_store_get": { "handler": dsops_run, "meta": dsget_meta, @@ -135,3 +136,11 @@ export let tc_switch = { export async function init(me) { gMe = me } + + +/** + * @param {string} chatId + */ +export async function setup(chatId) { + return tc_switch; +} diff --git a/tools/server/public_simplechat/tooljs.mjs b/tools/server/public_simplechat/tooljs.mjs index 425dcfbd2e..7854a0baf3 100644 --- a/tools/server/public_simplechat/tooljs.mjs +++ b/tools/server/public_simplechat/tooljs.mjs @@ -8,6 +8,7 @@ // import * as mChatMagic from './simplechat.js' +import * as mToolsMgr from './tools.mjs' let gMe = /** @type{mChatMagic.Me} */(/** @type {unknown} */(null)); @@ -152,9 +153,9 @@ function calc_run(chatid, toolcallid, toolname, obj) { /** - * @type {Object>} + * @type {mToolsMgr.TCSwitch} */ -export let tc_switch = { +let tc_switch = { "sys_date_time": { "handler": sysdatetime_run, "meta": sysdatetime_meta, @@ -181,3 +182,11 @@ export let tc_switch = { export async function init(me) { gMe = me } + + +/** + * @param {string} chatId + */ +export async function setup(chatId) { + return tc_switch; +} diff --git a/tools/server/public_simplechat/tools.mjs b/tools/server/public_simplechat/tools.mjs index 634e484acf..95db01f4d5 100644 --- a/tools/server/public_simplechat/tools.mjs +++ b/tools/server/public_simplechat/tools.mjs @@ -12,15 +12,17 @@ import * as tai from './toolai.mjs' import * as mChatMagic from './simplechat.js' +/** @typedef {Object>} TCSwitch */ + export class ToolsManager { constructor() { /** * Maintain currently available tool/function calls - * @type {Object>} + * @type {Object} */ - this.tc_switch = {} + this.tc_switchs = {} this.workers = { js: /** @type {Worker} */(/** @type {unknown} */(undefined)), @@ -46,43 +48,56 @@ export class ToolsManager { * @param {mChatMagic.Me} me */ async init(me) { + this.me = me this.setup_workers(); - /** - * @type {string[]} - */ - me.defaultCfg.tools.toolNames = [] - await tjs.init(me).then(()=>{ - for (const key in tjs.tc_switch) { - this.tc_switch[key] = tjs.tc_switch[key] - me.defaultCfg.tools.toolNames.push(key) + let tcM = [] + tcM.push(tjs.init(me)) + tcM.push(tdb.init(me)) + tcM.push(tai.init(me)) + tcM.push(tweb.init(me)) + return Promise.all(tcM) + } + + /** + * @param {string} chatId + */ + async setup(chatId) { + this.tc_switchs[chatId] = {} + let chat = this.me?.multiChat.simpleChats[chatId] + await tjs.setup(chatId).then((tcs)=>{ + for (const key in tcs) { + this.tc_switchs[chatId][key] = tcs[key] + chat?.cfg.tools.toolNames.push(key) } }) - await tdb.init(me).then(()=>{ - for (const key in tdb.tc_switch) { - this.tc_switch[key] = tdb.tc_switch[key] - me.defaultCfg.tools.toolNames.push(key) + await tdb.setup(chatId).then((tcs)=>{ + for (const key in tcs) { + this.tc_switchs[chatId][key] = tcs[key] + chat?.cfg.tools.toolNames.push(key) } }) - await tai.init(me).then(()=>{ - for (const key in tai.tc_switch) { - this.tc_switch[key] = tai.tc_switch[key] - me.defaultCfg.tools.toolNames.push(key) + await tai.setup(chatId).then((tcs)=>{ + for (const key in tcs) { + this.tc_switchs[chatId][key] = tcs[key] + chat?.cfg.tools.toolNames.push(key) + } + }) + await tweb.setup(chatId).then((tcs)=>{ + for (const key in tcs) { + this.tc_switchs[chatId][key] = tcs[key] + chat?.cfg.tools.toolNames.push(key) } }) - let tNs = await tweb.init(me) - for (const key in tNs) { - this.tc_switch[key] = tNs[key] - me.defaultCfg.tools.toolNames.push(key) - } } /** * Prepare the tools meta data that can be passed to the ai server. + * @param {string} chatId */ - meta() { + meta(chatId) { let tools = [] - for (const key in this.tc_switch) { - tools.push(this.tc_switch[key]["meta"]) + for (const key in this.tc_switchs[chatId]) { + tools.push(this.tc_switchs[chatId][key]["meta"]) } return tools } @@ -134,11 +149,11 @@ export class ToolsManager { * @param {string} toolargs */ async tool_call(chatid, toolcallid, toolname, toolargs) { - for (const fn in this.tc_switch) { + for (const fn in this.tc_switchs[chatid]) { if (fn == toolname) { try { this.toolcallpending_add(chatid, toolcallid); - this.tc_switch[fn]["handler"](chatid, toolcallid, fn, JSON.parse(toolargs)) + this.tc_switchs[chatid][fn]["handler"](chatid, toolcallid, fn, JSON.parse(toolargs)) return undefined } catch (/** @type {any} */error) { this.toolcallpending_found_cleared(chatid, toolcallid, 'ToolsManager:ToolCall:Exc') diff --git a/tools/server/public_simplechat/toolweb.mjs b/tools/server/public_simplechat/toolweb.mjs index 8649431d5d..6bbb5b42f0 100644 --- a/tools/server/public_simplechat/toolweb.mjs +++ b/tools/server/public_simplechat/toolweb.mjs @@ -17,6 +17,7 @@ import * as mChatMagic from './simplechat.js' +import * as mToolsMgr from './tools.mjs' /** @@ -77,13 +78,15 @@ async function proxyserver_get_anyargs(chatid, toolcallid, toolname, objSearchPa * Setup a proxy server dependent tool call * NOTE: Currently the logic is setup for the bundled simpleproxy.py * @param {string} tag + * @param {string} chatId * @param {string} tcPath * @param {string} tcName * @param {{ [x: string]: any; }} tcsData - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs */ -async function proxyserver_tc_setup(tag, tcPath, tcName, tcsData, tcs) { - await fetch(`${gMe.defaultCfg.tools.proxyUrl}/aum?url=${tcPath}.jambudweepe.akashaganga.multiverse.987654321123456789`).then(resp=>{ +async function proxyserver_tc_setup(tag, chatId, tcPath, tcName, tcsData, tcs) { + let chat = gMe.multiChat.simpleChats[chatId] + await fetch(`${chat.cfg.tools.proxyUrl}/aum?url=${tcPath}.jambudweepe.akashaganga.multiverse.987654321123456789`).then(resp=>{ if (resp.statusText != 'bharatavarshe') { console.log(`WARN:ToolWeb:${tag}:Dont forget to run the bundled local.tools/simpleproxy.py to enable me`) return @@ -141,10 +144,11 @@ function fetchweburlraw_run(chatid, toolcallid, toolname, obj) { /** * Setup fetch_web_url_raw for tool calling * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs + * @param {string} chatId */ -async function fetchweburlraw_setup(tcs) { - return proxyserver_tc_setup('FetchWebUrlRaw', 'urlraw', 'fetch_web_url_raw', { +async function fetchweburlraw_setup(tcs, chatId) { + return proxyserver_tc_setup('FetchWebUrlRaw', chatId, 'urlraw', 'fetch_web_url_raw', { "handler": fetchweburlraw_run, "meta": fetchweburlraw_meta, "result": "" @@ -195,10 +199,11 @@ function fetchhtmltext_run(chatid, toolcallid, toolname, obj) { /** * Setup fetch_html_text for tool calling * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs + * @param {string} chatId */ -async function fetchhtmltext_setup(tcs) { - return proxyserver_tc_setup('FetchHtmlText', 'htmltext', 'fetch_html_text', { +async function fetchhtmltext_setup(tcs, chatId) { + return proxyserver_tc_setup('FetchHtmlText', chatId, 'htmltext', 'fetch_html_text', { "handler": fetchhtmltext_run, "meta": fetchhtmltext_meta, "result": "" @@ -254,10 +259,11 @@ function searchwebtext_run(chatid, toolcallid, toolname, obj) { /** * Setup search_web_text for tool calling * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs + * @param {string} chatId */ -async function searchwebtext_setup(tcs) { - return proxyserver_tc_setup('SearchWebText', 'htmltext', 'search_web_text', { +async function searchwebtext_setup(tcs, chatId) { + return proxyserver_tc_setup('SearchWebText', chatId, 'htmltext', 'search_web_text', { "handler": searchwebtext_run, "meta": searchwebtext_meta, "result": "" @@ -319,10 +325,11 @@ function fetchpdftext_run(chatid, toolcallid, toolname, obj) { /** * Setup fetchpdftext for tool calling * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs + * @param {string} chatId */ -async function fetchpdftext_setup(tcs) { - return proxyserver_tc_setup('FetchPdfAsText', 'pdftext', 'fetch_pdf_as_text', { +async function fetchpdftext_setup(tcs, chatId) { + return proxyserver_tc_setup('FetchPdfAsText', chatId, 'pdftext', 'fetch_pdf_as_text', { "handler": fetchpdftext_run, "meta": fetchpdftext_meta, "result": "" @@ -391,10 +398,11 @@ function fetchxmlfiltered_run(chatid, toolcallid, toolname, obj) { /** * Setup fetch_xml_filtered for tool calling * NOTE: Currently the logic is setup for the bundled simpleproxy.py - * @param {Object>} tcs + * @param {mToolsMgr.TCSwitch} tcs + * @param {string} chatId */ -async function fetchxmlfiltered_setup(tcs) { - return proxyserver_tc_setup('FetchXmlFiltered', 'xmlfiltered', 'fetch_xml_filtered', { +async function fetchxmlfiltered_setup(tcs, chatId) { + return proxyserver_tc_setup('FetchXmlFiltered', chatId, 'xmlfiltered', 'fetch_xml_filtered', { "handler": fetchxmlfiltered_run, "meta": fetchxmlfiltered_meta, "result": "" @@ -413,15 +421,22 @@ async function fetchxmlfiltered_setup(tcs) { * @param {mChatMagic.Me} me */ export async function init(me) { + gMe = me +} + + +/** + * @param {string} chatId + */ +export async function setup(chatId) { /** - * @type {Object>} tcs + * @type {mToolsMgr.TCSwitch} tcs */ let tc_switch = {} - gMe = me - await fetchweburlraw_setup(tc_switch) - await fetchhtmltext_setup(tc_switch) - await searchwebtext_setup(tc_switch) - await fetchpdftext_setup(tc_switch) - await fetchxmlfiltered_setup(tc_switch) + await fetchweburlraw_setup(tc_switch, chatId) + await fetchhtmltext_setup(tc_switch, chatId) + await searchwebtext_setup(tc_switch, chatId) + await fetchpdftext_setup(tc_switch, chatId) + await fetchxmlfiltered_setup(tc_switch, chatId) return tc_switch }