From 9a0b48ca61e7468b2585b87f518ecdc9b2878d07 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sun, 16 Aug 2026 09:32:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20chat-engine.ts=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E6=B6=88=E6=81=AF=E6=B5=81=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/drizzle-pkg/db.sqlite | Bin 692224 -> 757760 bytes server/service/agent/chat-engine.ts | 93 ++++++++++++++++++++++++++++-------- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite index 3bea3ffd6d355b26bc5eebf36fa2bc0090b7a843..c71227351db81d681bbba598dfe645da037064e9 100644 GIT binary patch delta 39332 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 delta 2292 zcmc(geQXow9mnr{XP@uvyC;-J#UTq1^%#XBlhUQop)HWA;zgK1NfC(ByM!SK$mXsk(AEnUVo_FMu9 z>-b}TOqz6h^xX4%`F@_?J-_D?t)4{d{NppNCkcW$-vEorlid|<3v+022QLr@!Cf#4 zM!=n(*-)VMC(CRfI(qIDzX!;I(uZ)SGT@k zp$Y^&$y9t3uc$(g9`TCyuYxru)cK_IS1a-I4ZFTz%nEH*yw({{uKz=qU?S8~5&^Q{ zm!LN(+`LOl*mH{|&qWnk#Bh07-RX<^s+DpzwDYw^h2IVmd-V7Q$37=lYuQbJ47dim zlfv-D)4Wf>T`f*3XT){3eIuQ(sN>T9gA+=;|ea2 zbPnfso}3b2hBK^mqO%KG7LBqFpudw(Zgf*_;6}_cvc&4f)$n4U>w?Wnvjpiz^GeB& zDO@tdtRugrZ&^p~=97ictMjjtUywL(1!5}5MY+A80UQRq!42>W@Dnfq+JP6Wz=_5L zG<=V?>T6{3I$xZ}5aiPYX{9t-4wd^Q%@-)&uF4ULY#IG)?+5uVY@hojd$`InZXNu} z3{+7=x@_39&-Da~*O0k1o_Fh~YRD5gxp~uRaxVFB=5Un@6(1#Yr_Y#1lkWQ_RT33n z;0b-(QS!(q{Iii*xKdKEz~|3iua8>lqf~vAu8&&lqqg2CW2>Of6SO{Um}#Z?lV#L& zVx}wpeIG$g*Smhhe8Z6w3WaTC%O8!|%s695?@fko&2vz16T;t|9nKQ&s-3X4Sx2l( z=woyN^){}^KFVHQ;2_*CHjEN2+}!;i)!Frr>ez+(ZhTY(riPjaYw&aX7<$KANktWMhbIjkU4}Fi# z{V`=HH|R{1`v>4C`Yyp&@DBPeX8996=eV=h!WR|I+B@eA#S-}AJ?czP;C=Q1$HyBI zLjyr21R3b(b@j zno^frZzY;Djqyvj5@%C=31a}iH{u5yZlfP&ng`N#J=yLzu_@Jecxd1>$IYLQ6Qr9H z7%kI$c#;CAH`+SV?R(Ovy3%^L(bk+fxZh~Lm~QOFbf&evK6|JeV}6>bHQFv1$4rV; zzqv9rz#X}L`dDi4ig6C1X(?_g`uz%rZL>cZse&S`l*E`8^v6Ol8jv*^%6=G@;8W?d zokstjc^YhQ8Oi`c{JoBM8}y-S|8TJ zX*^KF`R+rRt?zjy@=D}CSRd>How~-kfDbw@zZetA1E zs6xLO44JgMf?5D;Mny%H;L9(qfs&%g%D)NYQsSaa=tDU&Nr=5YuvCFzb63LD$KD=O zHMG3imiyuYxLw|1s)&_xOoKt~;X;~wk|RC|hGj*1z)=?3FU*ER6 zaPi_o)crGVAzHiF{y6$`gMAiyW1gcCZSAx>kXNud(ceGh;EWwRR(n^jf2M5p#=!Pi mVOeRZR> = []; let chunkPartId = 0; + let streamedParts: Array> = []; + let activeTextPartIdx = -1; + let activeReasoningPartIdx = -1; params.onClientClose?.(() => { if (!serverAbortController.signal.aborted) { @@ -561,8 +564,39 @@ export async function executeChat(params: ChatEngineParams): Promise { if (chunk.type === "text-delta") { streamedText += chunk.text; + if (activeTextPartIdx < 0) { + activeTextPartIdx = streamedParts.length; + streamedParts.push({ id: `p_${chunkPartId++}`, type: "text", text: "" }); + } + const tp = streamedParts[activeTextPartIdx] as Record; + tp.text = ((tp.text as string) || "") + chunk.text; + } else if (chunk.type === "text-start") { + activeTextPartIdx = streamedParts.length; + streamedParts.push({ id: `p_${chunkPartId++}`, type: "text", text: "" }); + } else if (chunk.type === "text-end") { + activeTextPartIdx = -1; } else if (chunk.type === "reasoning-delta") { streamedReasoning += chunk.text; + if (activeReasoningPartIdx < 0) { + activeReasoningPartIdx = streamedParts.length; + streamedParts.push({ id: `p_${chunkPartId++}`, type: "reasoning", text: "" }); + } + const rp = streamedParts[activeReasoningPartIdx] as Record; + rp.text = ((rp.text as string) || "") + chunk.text; + } else if (chunk.type === "reasoning-start") { + activeReasoningPartIdx = streamedParts.length; + streamedParts.push({ id: `p_${chunkPartId++}`, type: "reasoning", text: "" }); + } else if (chunk.type === "reasoning-end") { + activeReasoningPartIdx = -1; + } else if (chunk.type === "tool-input-start") { + streamedParts.push({ + id: `p_${chunkPartId++}`, + type: "tool-call", + toolCallId: chunk.id, + toolName: chunk.toolName, + args: undefined, + state: "preparing", + }); } else if (chunk.type === "tool-call") { streamedToolCalls.push({ id: `p_${chunkPartId++}`, @@ -572,6 +606,22 @@ export async function executeChat(params: ChatEngineParams): Promise p.type === "tool-call" && p.toolCallId === chunk.toolCallId, + ); + if (existing) { + existing.args = chunk.input; + existing.state = "call"; + } else { + streamedParts.push({ + id: `p_${chunkPartId++}`, + type: "tool-call", + toolCallId: chunk.toolCallId, + toolName: chunk.toolName, + args: chunk.input, + state: "call", + }); + } } else if (chunk.type === "tool-result") { const tcIdx = streamedToolCalls.findIndex((tc) => tc.toolCallId === chunk.toolCallId); const tcEntry = tcIdx >= 0 ? streamedToolCalls[tcIdx] : undefined; @@ -579,6 +629,13 @@ export async function executeChat(params: ChatEngineParams): Promise p.type === "tool-call" && p.toolCallId === chunk.toolCallId, + ); + if (part) { + part.result = chunk.output; + part.state = "result"; + } } }, onFinish: async ({ finishReason, usage, steps, text: assistantText }) => { @@ -602,6 +659,12 @@ export async function executeChat(params: ChatEngineParams): Promise [tr.toolCallId, tr.output])); const contentArr = step.content as Array>; + logger.info( + "[%s] [CHAT-ENGINE] step %d content order: %s", + requestId, + step.stepNumber, + contentArr.map((cp) => cp.type + (cp.type === "tool-call" ? `(${(cp as any).toolName})` : "")).join(" → "), + ); const approvalToolCallIds = new Set(); for (const cp of contentArr) { if (cp.type === "tool-approval-request" && (cp as any).approvalId && (cp as any).toolCall) { @@ -746,33 +809,21 @@ export async function executeChat(params: ChatEngineParams): Promise> = []; - let hasTextPart = false; - if (streamedReasoning.trim()) { - parts.push({ id: `p_${parts.length}`, type: "reasoning", text: streamedReasoning }); - } - if (partialText.trim()) { - parts.push({ id: `p_${parts.length}`, type: "text", text: partialText }); - hasTextPart = true; - } - for (const tc of streamedToolCalls) { - parts.push({ - id: `p_${parts.length}`, - type: "tool-call", - toolCallId: tc.toolCallId, - toolName: tc.toolName, - args: tc.args, - result: tc.result, - state: tc.result !== undefined ? "result" : "call", - }); - } - + const parts: Array> = streamedParts + .filter((p) => { + if (p.type === "text") return ((p.text as string) || "").trim().length > 0; + if (p.type === "reasoning") return ((p.text as string) || "").trim().length > 0; + return true; + }) + .map((p, i) => ({ ...p, id: `p_${i}` })); + let hasTextPart = parts.some((p) => p.type === "text"); const hasToolCallPart = parts.some((p) => p.type === "tool-call"); let finalText = partialText; if (!hasTextPart && hasToolCallPart) { const noticeText = "(对话已停止,以上是已完成的工具调用记录。)"; parts.push({ id: `p_${parts.length}`, type: "text", text: noticeText }); finalText = (finalText || "") + noticeText; + hasTextPart = true; logger.info("[%s] [CHAT-ENGINE] aborted with tool calls but no text, appended notice", requestId); }