From 6af815bda182b1669b2c67d4b56d4f0d9cfbd7f9 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 31 May 2026 16:24:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20v0.2=20Device=20Pod?= =?UTF-8?q?=20=E5=8F=B3=E6=A0=8F=E4=B8=8E=E5=8A=A9=E6=89=8B=E6=B6=88?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/cloud/code-agent-trace-store.ts | 2 +- .../cloud/codex-stdio-session-turn-state.ts | 5 ++- web/hwlab-cloud-web/app-trace.test.ts | 35 +++++++++++++++++++ web/hwlab-cloud-web/index.html | 4 --- web/hwlab-cloud-web/scripts/check.ts | 11 ++++++ web/hwlab-cloud-web/styles.css | 8 ++--- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/internal/cloud/code-agent-trace-store.ts b/internal/cloud/code-agent-trace-store.ts index 1819454c..35e39d99 100644 --- a/internal/cloud/code-agent-trace-store.ts +++ b/internal/cloud/code-agent-trace-store.ts @@ -332,7 +332,7 @@ function normalizeTraceEvent(event, { traceId, seq, now, fallbackRunnerKind } = stdoutSummary: safeText(event.stdoutSummary, 600), stderrSummary: safeText(event.stderrSummary, 600), chunk: safeText(event.chunk, 400), - message: safeText(event.message, 500), + message: safeText(event.message, 1200), errorCode: safeText(event.errorCode, 120), waitingFor: safeText(event.waitingFor, 220), timeoutMs: typeof event.timeoutMs === "number" ? Math.trunc(event.timeoutMs) : undefined, diff --git a/internal/cloud/codex-stdio-session-turn-state.ts b/internal/cloud/codex-stdio-session-turn-state.ts index 1d6a9ea9..0329b0b3 100644 --- a/internal/cloud/codex-stdio-session-turn-state.ts +++ b/internal/cloud/codex-stdio-session-turn-state.ts @@ -161,11 +161,14 @@ export function createAppServerTurnState({ traceRecorder, session } = {}) { return; } if (method === "item/completed" && item?.type === "agentMessage") { - if (typeof item.text === "string") finalResponse = item.text; + const completedText = typeof item.text === "string" ? item.text : ""; + if (completedText) finalResponse = completedText; appendTrace({ type: "assistant_message", status: "completed", label: "assistant:item_completed", + itemId: optionalId(item.id), + message: redactText(completedText), sessionId: session?.sessionId, sessionStatus: session?.status, turn: session?.turn, diff --git a/web/hwlab-cloud-web/app-trace.test.ts b/web/hwlab-cloud-web/app-trace.test.ts index cc9b6398..9952486e 100644 --- a/web/hwlab-cloud-web/app-trace.test.ts +++ b/web/hwlab-cloud-web/app-trace.test.ts @@ -32,6 +32,41 @@ test("trace display rows render completion when no terminal assistant event exis assert.equal(rows.some((row) => /轮次完成/u.test(row.header)), true); }); +test("trace display rows render assistant item text when stream snapshot is absent", () => { + const events = [ + event(1, "request:accepted", { promptSummary: "请列出 device-pod" }), + event(2, "assistant:item_completed", { + type: "assistant_message", + status: "completed", + itemId: "msg_item_0", + message: "当前有以下 **5 个 device-pod** 可用。" + }), + commandEvent(3, "item/commandExecution:completed", { + itemId: "cmd-trace-2", + command: "grep -rn device-pod /workspace/hwlab", + status: "completed", + exitCode: 0, + stdoutSummary: "success=true" + }), + event(4, "assistant:completed", { + type: "assistant_message", + terminal: true, + status: "completed", + itemId: "assistant-final", + message: "可以继续指定要操作的 device-pod。" + }) + ]; + + const rows = traceDisplayRows({ traceId: "trc_assistant_item_text", events }, events); + const text = rows.map((row) => `${row.header}\n${row.body ?? ""}`).join("\n---\n"); + + assert.match(text, /🤖 助手消息(第一条)/u); + assert.match(text, /当前有以下 \*\*5 个 device-pod\*\* 可用/u); + assert.match(text, /工具调用/u); + assert.match(text, /助手最后一条消息/u); + assert.match(text, /可以继续指定要操作的 device-pod/u); +}); + function traceEvents() { return [ event(1, "request:accepted", { promptSummary: "请检查 trace" }), diff --git a/web/hwlab-cloud-web/index.html b/web/hwlab-cloud-web/index.html index 24840b68..0c56e57f 100644 --- a/web/hwlab-cloud-web/index.html +++ b/web/hwlab-cloud-web/index.html @@ -314,10 +314,6 @@
等待 /v1/device-pods 事件流。
-
diff --git a/web/hwlab-cloud-web/scripts/check.ts b/web/hwlab-cloud-web/scripts/check.ts index 2134afce..37ecc177 100644 --- a/web/hwlab-cloud-web/scripts/check.ts +++ b/web/hwlab-cloud-web/scripts/check.ts @@ -82,9 +82,12 @@ for (const term of [ } assert.doesNotMatch(rightSidebar, /]*role="button"[^>]*tabindex="0"/u, "Pod summary is a click/keyboard summary tile"); assert.match(rightSidebar, /= 0 ? source.slice(match.index, bodyEnd + 1) : source.slice(match.index); +} + function functionBody(source, name) { const match = new RegExp(`function\\s+${escapeRegExp(name)}\\s*\\([^)]*\\)\\s*\\{`, "u").exec(source); if (!match) return ""; diff --git a/web/hwlab-cloud-web/styles.css b/web/hwlab-cloud-web/styles.css index 3486e236..4b882eeb 100644 --- a/web/hwlab-cloud-web/styles.css +++ b/web/hwlab-cloud-web/styles.css @@ -1797,7 +1797,7 @@ h3 { .right-sidebar { position: relative; display: grid; - grid-template-rows: auto auto auto minmax(0, 1fr); + grid-auto-rows: max-content; gap: 8px; padding: 10px 10px 10px 16px; background: rgba(18, 20, 18, 0.98); @@ -2465,7 +2465,7 @@ tbody tr:last-child td { } .device-pod-workspace { - grid-template-rows: auto minmax(180px, 1fr) auto; + grid-template-rows: auto auto; } .device-pod-selector-row { @@ -2567,9 +2567,9 @@ tbody tr:last-child td { .device-event-panel { min-width: 0; - min-height: 180px; + min-height: 240px; display: grid; - grid-template-rows: auto minmax(0, 1fr); + grid-template-rows: auto minmax(180px, 1fr); border: 1px solid var(--line); background: #101310; }