From 183794dc4273057972c778d0c693672a0e79d3fa Mon Sep 17 00:00:00 2001 From: gongzhiyong Date: Sat, 11 Apr 2026 22:35:52 +0800 Subject: [PATCH] fix: sandbox friendly error card + ticket_list empty guard + search auto-supplement - coder/tool-executor: push sandbox-result card with friendly message on failure instead of raw error, guide user to local execution or retry - enterprise/tool-executor: skip ticket-summary card when ticket_list returns empty, only return hint in tool message to avoid blank UI - searcher/tool-executor: auto-supplement web_search_deep with google_search when results < 3, matching existing google_search behavior - ticket_detail UUID: already correctly uses find() match (no change needed) Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../src/agent/coder/nodes/tool-executor.ts | 20 +++++++++++++++++-- .../agent/enterprise/nodes/tool-executor.ts | 17 +++++++++------- .../src/agent/searcher/nodes/tool-executor.ts | 17 ++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/langgraph/src/agent/coder/nodes/tool-executor.ts b/langgraph/src/agent/coder/nodes/tool-executor.ts index b42246a..fdaf367 100644 --- a/langgraph/src/agent/coder/nodes/tool-executor.ts +++ b/langgraph/src/agent/coder/nodes/tool-executor.ts @@ -93,12 +93,28 @@ export async function toolExecutorNode( }; } } catch (e) { + // Push a friendly sandbox-result card showing the failure + ui.push( + { + name: "sandbox-result", + props: { + language: (args as { language?: string }).language ?? "python", + exit_code: -1, + stdout: "沙盒环境暂时不可用,请稍后重试。您也可以将代码粘贴到本地环境运行。", + has_more: false, + duration_ms: 0, + sourceType: "code_execution", + confidence: "low", + }, + }, + { message: lastAiMessage }, + ); return { role: "tool" as const, tool_call_id: id, content: JSON.stringify({ - error: formatToolError(name, e), - fallback_hint: "沙盒暂时不可用。请告知用户:1) 可以直接分析代码逻辑而无需执行;2) 可稍后重试;3) 可以把代码粘贴到本地环境运行。", + error: "沙盒暂时不可用", + fallback_hint: "沙盒暂时不可用。请告知用户:1) 可以直接分析代码逻辑而无需执行;2) 可稍后重试;3) 可以把代码粘贴到本地环境运行。不要暴露技术报错信息。", }), }; } diff --git a/langgraph/src/agent/enterprise/nodes/tool-executor.ts b/langgraph/src/agent/enterprise/nodes/tool-executor.ts index 6803e6e..f745290 100644 --- a/langgraph/src/agent/enterprise/nodes/tool-executor.ts +++ b/langgraph/src/agent/enterprise/nodes/tool-executor.ts @@ -226,13 +226,16 @@ export async function toolExecutorNode( tickets.forEach((t) => { stats[t.status] = (stats[t.status] ?? 0) + 1; }); - ui.push( - { - name: "ticket-summary", - props: { total: tickets.length, tickets, stats, sourceType: "ticket_system", confidence: "high" }, - }, - { message: lastAiMessage }, - ); + // Only push ticket-summary + chart when there are actual results + if (tickets.length > 0) { + ui.push( + { + name: "ticket-summary", + props: { total: tickets.length, tickets, stats, sourceType: "ticket_system", confidence: "high" }, + }, + { message: lastAiMessage }, + ); + } // Push chart-result card for ticket distribution if (tickets.length > 0) { diff --git a/langgraph/src/agent/searcher/nodes/tool-executor.ts b/langgraph/src/agent/searcher/nodes/tool-executor.ts index e2a0f0f..2acded7 100644 --- a/langgraph/src/agent/searcher/nodes/tool-executor.ts +++ b/langgraph/src/agent/searcher/nodes/tool-executor.ts @@ -140,6 +140,23 @@ export async function toolExecutorNode( snippet: (r.description ?? r.content ?? "").slice(0, 200), })); + // Auto-supplement with google_search if results < 3 + if (enriched.length < 3) { + try { + const supplementData = await googleSearch(parsed.query + " 解决方案"); + const supplementResults = supplementData.results + .slice(0, 3 - enriched.length) + .map((r) => ({ + title: r.title, + url: r.url, + snippet: r.snippet.slice(0, 200), + })); + enriched = [...enriched, ...supplementResults]; + } catch { + /* supplement search failed silently */ + } + } + // Rerank results using Jina Reranker as post-processing try { const docs = enriched.map((r) => `${r.title} ${r.snippet}`);