From 65baaaced5113bfaea4c57f28e4d178c1a6b8e82 Mon Sep 17 00:00:00 2001 From: M3gA-Mind Date: Tue, 10 Mar 2026 05:24:16 +0530 Subject: [PATCH] feat: enhance Conversations component with detailed logging and tool call execution - Updated the inference request structure to improve type safety and added comprehensive logging for both requests and responses. - Modified tool call execution to handle only the latest tool call while sending placeholders for previous calls. - Implemented error handling for tool results, ensuring proper logging and formatting of error messages. - Introduced a timeout parameter for network requests in the ops_net module to enhance request reliability. --- .../services/quickjs-libs/qjs_ops/ops_net.rs | 7 +++ src/pages/Conversations.tsx | 54 ++++++++++++++++--- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/services/quickjs-libs/qjs_ops/ops_net.rs b/src-tauri/src/services/quickjs-libs/qjs_ops/ops_net.rs index 4024ef8e2..80e451092 100644 --- a/src-tauri/src/services/quickjs-libs/qjs_ops/ops_net.rs +++ b/src-tauri/src/services/quickjs-libs/qjs_ops/ops_net.rs @@ -20,6 +20,10 @@ pub fn register<'js>(ctx: &Ctx<'js>, ops: &Object<'js>, ws_state: Arc(ctx: &Ctx<'js>, ops: &Object<'js>, ws_state: Arc client.get(&url), "POST" => client.post(&url), "PUT" => client.put(&url), + "PATCH" => client.patch(&url), "DELETE" => client.delete(&url), _ => client.get(&url), }; + req = req.timeout(std::time::Duration::from_secs(timeout_secs)); + if let Some(h) = headers_obj { for (k, v) in h { if let Some(val_str) = v.as_str() { diff --git a/src/pages/Conversations.tsx b/src/pages/Conversations.tsx index 070505376..a3f92e70a 100644 --- a/src/pages/Conversations.tsx +++ b/src/pages/Conversations.tsx @@ -381,12 +381,27 @@ const Conversations = () => { const MAX_TOOL_ROUNDS = 5; for (let round = 0; round < MAX_TOOL_ROUNDS; round++) { - const response = await inferenceApi.createChatCompletion({ + const request: Parameters[0] = { model: selectedModel, messages: loopMessages, - ...(allSkillTools.length > 0 ? { tools: allSkillTools, tool_choice: 'auto' } : {}), + ...(allSkillTools.length > 0 + ? { tools: allSkillTools, tool_choice: 'auto' as const } + : {}), + }; + console.log('[Conversations] inference request:', { + round: round + 1, + model: request.model, + messageCount: request.messages.length, + tools: request.tools?.length ?? 0, + payload: request, + }); + const response = await inferenceApi.createChatCompletion(request); + console.log('[Conversations] inference response:', { + round: round + 1, + choices: response.choices?.length ?? 0, + usage: response.usage, + payload: response, }); - console.log('🚀 ~ handleSendMessage ~ response:', response); const choice = response.choices[0]; if (!choice) break; @@ -401,8 +416,19 @@ const Conversations = () => { tool_calls: message.tool_calls, }); - // Execute each tool and collect results - for (const tc of message.tool_calls) { + const latestIndex = message.tool_calls.length - 1; + // API requires a tool message for every tool_call_id; we execute only the latest and send placeholders for the rest + for (let i = 0; i < message.tool_calls.length; i++) { + const tc = message.tool_calls[i]; + if (i !== latestIndex) { + loopMessages.push({ + role: 'tool', + tool_call_id: tc.id, + content: '', + }); + continue; + } + const dunderIdx = tc.function.name.indexOf('__'); const skillId = dunderIdx !== -1 ? tc.function.name.substring(0, dunderIdx) : ''; const toolName = @@ -426,12 +452,26 @@ const Conversations = () => { ); const result = await skillManager.callTool(skillId, toolName, toolArgs); toolResultContent = result.content.map(c => c.text).join('\n'); - if (result.isError) { + let toolReturnedError = result.isError; + if (!toolReturnedError && toolResultContent) { + try { + const parsed = JSON.parse(toolResultContent) as Record; + if (parsed && typeof parsed.error === 'string') { + toolReturnedError = true; + toolResultContent = `Error: ${parsed.error}`; + } + } catch { + // not JSON or no error key — keep content as-is + } + } + if (toolReturnedError) { console.warn( `[Conversations] tool "${toolName}" returned an error:`, toolResultContent ); - toolResultContent = `Error: ${toolResultContent}`; + if (!toolResultContent.startsWith('Error: ')) { + toolResultContent = `Error: ${toolResultContent}`; + } } else { console.log( `[Conversations] tool "${toolName}" succeeded:`,