Merge pull request #2350 from pikasTech/fix/2345-workbench-terminal-seal

fix: seal Workbench terminal turn body
This commit is contained in:
Lyon
2026-07-02 19:55:51 +08:00
committed by GitHub
2 changed files with 20 additions and 2 deletions
@@ -1,4 +1,7 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "bun:test";
import type { AgentChatResultResponse, ChatMessage } from "../types";
@@ -11,6 +14,8 @@ import {
turnResultStatusForMerge
} from "./workbench-message-projection-runtime";
const storeDir = path.dirname(fileURLToPath(import.meta.url));
function agentMessage(input: Partial<ChatMessage> & Pick<ChatMessage, "id" | "traceId">): ChatMessage {
return {
role: "agent",
@@ -103,3 +108,14 @@ test("terminal response helpers treat failed body as sealed authority", () => {
assert.equal(messageNeedsTerminalDiagnostics(unsealed), true);
assert.equal(traceHasTerminalResponse(traceId, [unsealed]), false);
});
test("workbench active terminal paths seal final response from turn authority", () => {
const source = fs.readFileSync(path.join(storeDir, "workbench.ts"), "utf8");
const terminalPatchUses = source.match(/terminalMessagePatchFromTurnResult\(message, result(?: as AgentChatResultResponse)?\) \?\? \{\}/gu) ?? [];
const syncBlock = source.slice(source.indexOf("function syncTurnStatusToMessage"), source.indexOf("async function submitMessage"));
const completeBlock = source.slice(source.indexOf("function completeTrace"), source.indexOf("async function hydrateTerminalMessageDiagnostics"));
assert.equal(terminalPatchUses.length, 2);
assert.match(syncBlock, /\.\.\.terminalPatch/u);
assert.match(completeBlock, /\.\.\.terminalPatch/u);
});
+4 -2
View File
@@ -616,7 +616,8 @@ export const useWorkbenchStore = defineStore("workbench", () => {
const error = resultError ?? (terminal || clearCompletedDiagnostics ? null : normalizeAgentError(runnerTrace?.error ?? message.error));
const agentRun = agentRunFromResult(result as AgentChatResultResponse, runnerTrace) ?? agentRunFromMessage(message);
const projection = clearCompletedDiagnostics ? nonBlockingProjection(resultProjection) : resultProjection ?? (terminal ? null : runnerTrace.projection ?? message.projection ?? null);
return { ...message, ...messageTimingPatchForMerge(message, result), ...messageStatusPatchForTerminalMerge(message, resultStatus, terminal), runnerTrace, error, projection, projectionStatus: projection?.projectionStatus ?? null, projectionHealth: projection?.projectionHealth ?? null, blocker: projection?.blocker ?? null, agentRun: agentRun ?? undefined, updatedAt: new Date().toISOString() };
const terminalPatch = terminalMessagePatchFromTurnResult(message, result as AgentChatResultResponse) ?? {};
return { ...message, ...messageTimingPatchForMerge(message, result), ...messageStatusPatchForTerminalMerge(message, resultStatus, terminal), runnerTrace, error, projection, projectionStatus: projection?.projectionStatus ?? null, projectionHealth: projection?.projectionHealth ?? null, blocker: projection?.blocker ?? null, agentRun: agentRun ?? undefined, ...terminalPatch, updatedAt: new Date().toISOString() };
});
}
@@ -1281,7 +1282,8 @@ export const useWorkbenchStore = defineStore("workbench", () => {
const error = resultError ?? (terminal || clearCompletedDiagnostics ? null : normalizeAgentError(runnerTrace?.error ?? message.error));
const projection = clearCompletedDiagnostics ? nonBlockingProjection(resultProjection) : resultProjection ?? (terminal ? null : runnerTrace.projection ?? message.projection ?? null);
const agentRun = agentRunFromResult(result, runnerTrace) ?? agentRunFromMessage(message);
return { ...message, ...messageTimingPatchForMerge(message, result), ...messageStatusPatchForTerminalMerge(message, resultStatus, terminal), runnerTrace, error, projection, projectionStatus: projection?.projectionStatus ?? null, projectionHealth: projection?.projectionHealth ?? null, blocker: projection?.blocker ?? null, agentRun: agentRun ?? undefined, updatedAt: new Date().toISOString() };
const terminalPatch = terminalMessagePatchFromTurnResult(message, result) ?? {};
return { ...message, ...messageTimingPatchForMerge(message, result), ...messageStatusPatchForTerminalMerge(message, resultStatus, terminal), runnerTrace, error, projection, projectionStatus: projection?.projectionStatus ?? null, projectionHealth: projection?.projectionHealth ?? null, blocker: projection?.blocker ?? null, agentRun: agentRun ?? undefined, ...terminalPatch, updatedAt: new Date().toISOString() };
}));
rememberTurnStatus(traceId, result);
markWorkbenchTraceProjected(traceId);