fix(workbench): use single turn projection authority

This commit is contained in:
lyon
2026-06-19 04:17:28 +08:00
parent 6f13f5df2e
commit e5994d8af1
9 changed files with 433 additions and 115 deletions
@@ -280,6 +280,7 @@ function createScenarioState(scenarioId: string): ScenarioState {
}
if (id === "progress-only-final-response") markRunningProgressOnly(sessions, traces);
if (id === "terminal-completed-no-final-response") markRunningNoFinalResponse(sessions, traces);
if (id === "tool-completed-projection-running") markToolCompletedProjectionRunning(sessions, traces);
if (id === "scroll-follow-long-trace") {
const session = scrollFollowSession();
sessions.unshift(session);
@@ -302,7 +303,7 @@ function createScenarioState(scenarioId: string): ScenarioState {
? "ses_completed"
: id === "terminal-empty-trace"
? "ses_terminal_empty"
: id === "progress-only-final-response" || id === "terminal-completed-no-final-response"
: id === "progress-only-final-response" || id === "terminal-completed-no-final-response" || id === "tool-completed-projection-running"
? "ses_running"
: base.selectedSessionId;
const staleTraceId = id === "stale-nested-trace" || id === "stale-submit-restore" ? "trc_stale_502" : null;
@@ -370,6 +371,44 @@ function markRunningNoFinalResponse(sessions: SessionRecord[], traces: Record<st
});
}
function markToolCompletedProjectionRunning(sessions: SessionRecord[], traces: Record<string, JsonRecord>): void {
const trace = toolCompletedProjectionRunningTrace();
traces.trc_running = trace;
const session = sessions.find((item) => item.sessionId === "ses_running");
if (!session) return;
session.status = "running";
session.lastTraceId = "trc_running";
session.firstUserMessagePreview = "tool completed but turn still running";
session.messages = (session.messages ?? []).map((message) => {
if (message.role === "user") return { ...message, text: "tool completed but turn still running" };
if (message.role !== "agent" || message.traceId !== "trc_running") return message;
return { ...message, text: "", status: "running", runnerTrace: trace };
});
}
function toolCompletedProjectionRunningTrace(): JsonRecord {
const createdAt = new Date().toISOString();
const events = [
{ seq: 1, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", terminal: false, message: "正在安装 Python。" },
{ seq: 2, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", terminal: false, command: "ls -ld .", stdout: "OK\n" }
];
return {
traceId: "trc_running",
status: "completed",
turnStatus: "running",
projectionStatus: "projecting",
sessionId: "ses_running",
threadId: "thr_running",
turnId: "turn_running",
events,
eventCount: events.length,
fullTraceLoaded: true,
hasMore: false,
finalResponse: null,
assistantText: null
};
}
function noFinalRunningTrace(): JsonRecord {
const createdAt = new Date().toISOString();
return {
@@ -862,6 +901,7 @@ function turnPayload(traceId: string): JsonRecord {
return state.traces[traceId] ?? liveBackfillEarlyTrace(sessionId, threadId, traceId);
}
const trace = state.traces[traceId] ?? { traceId, status: "unknown", events: [] };
if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") return { ...trace, traceId, status: "running", running: true, terminal: false, projectionStatus: "projecting", trace: { status: trace.status, eventCount: trace.eventCount ?? 0 } };
if (state.scenarioId === "terminal-turn-stale-session-active" && traceId === "trc_completed") return { ...trace, traceId, status: "active", running: true, terminal: false, trace: { status: "completed", eventCount: trace.eventCount ?? 0 } };
const status = String(trace.status ?? "unknown");
return { ...trace, traceId, status, running: ["running", "pending", "accepted"].includes(status), terminal: ["completed", "failed", "blocked", "timeout", "canceled"].includes(status) };
@@ -882,6 +922,9 @@ function tracePayload(traceId: string, url: URL): JsonRecord {
function workbenchTracePayload(traceId: string, url: URL): JsonRecord {
const payload = tracePayload(traceId, url);
if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") {
return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: "completed", events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextSeq: payload.nextSinceSeq, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, projectionStatus: "projecting", terminalEvidence: null, finalResponse: null, traceSummary: payload.traceSummary, retention: payload.retention };
}
return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: payload.status, events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextSeq: payload.nextSinceSeq, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, terminalEvidence: payload.terminalEvidence, finalResponse: payload.finalResponse, traceSummary: payload.traceSummary, retention: payload.retention };
}