diff --git a/internal/cloud/server-agent-chat.test.ts b/internal/cloud/server-agent-chat.test.ts index 9478d444..6bf0b5ce 100644 --- a/internal/cloud/server-agent-chat.test.ts +++ b/internal/cloud/server-agent-chat.test.ts @@ -2308,7 +2308,7 @@ test("cloud api running trace reports current projection without AgentRun event } }); -test("cloud api turn status backfills terminal AgentRun projection on read (#1555)", async () => { +test("cloud api turn status does not backfill terminal AgentRun projection on GET (#1585)", async () => { const calls = []; const traceId = "trc_issue1422_turn_status_fast_path"; const runId = "run_issue1422_turn_status_fast_path"; @@ -2383,14 +2383,13 @@ test("cloud api turn status backfills terminal AgentRun projection on read (#155 }); assert.equal(response.status, 200); const body = await response.json(); - assert.equal(body.status, "completed"); - assert.equal(body.terminal, true); - assert.equal(body.agentRun.runStatus, "claimed"); - assert.equal(body.agentRun.commandState, "completed"); - assert.equal(body.agentRun.terminalStatus, "completed"); - assert.match(body.finalResponse.text, /issue 1555 read-side backfill/u); - assert.equal(calls.filter((call) => call.path === `/api/v1/runs/${runId}/events`).length, 1); - assert.equal(calls.some((call) => call.path === `/api/v1/runs/${runId}/commands/${commandId}/result`), true); + assert.equal(body.status, "running"); + assert.equal(body.terminal, false); + assert.equal(body.projectionStatus, "projecting"); + assert.equal(body.agentRun.commandState, "running"); + assert.equal(body.agentRun.terminalStatus ?? null, null); + assert.equal(body.finalResponse, null); + assert.deepEqual(calls, []); } finally { await new Promise((resolve, reject) => { server.close((error) => (error ? reject(error) : resolve())); diff --git a/internal/cloud/server-code-agent-http.ts b/internal/cloud/server-code-agent-http.ts index 139bd4d7..7f4572a6 100644 --- a/internal/cloud/server-code-agent-http.ts +++ b/internal/cloud/server-code-agent-http.ts @@ -9,7 +9,6 @@ import { cancelAgentRunChatTurn, codeAgentAgentRunAdapterEnabled, initialAgentRunChatResult, - agentRunTerminalResultRefreshSatisfied, loadPersistedAgentRunResult, steerAgentRunChatTurn, submitAgentRunChatTurn, @@ -1242,68 +1241,6 @@ function codeAgentTurnStatusRefreshOptions(options = {}) { }; } -async function refreshAgentRunProjectionForCompatRead({ traceId, result = null, trace = null, options = {} } = {}) { - if (!safeTraceId(traceId) || !shouldRefreshAgentRunProjectionOnRead(result)) return { result, runnerTrace: trace, refreshError: null }; - const traceStore = options.traceStore ?? defaultCodeAgentTraceStore; - const refreshOptions = codeAgentTurnStatusRefreshOptions(options); - const performanceStore = options.backendPerformanceStore ?? options.backendPerformance; - const startedAt = nowMs(); - performanceStore?.recordWorkbenchProjectorCandidate?.({ status: "seen", reason: "read_side_refresh" }); - try { - const synced = await syncAgentRunChatResult({ - traceId, - currentResult: result, - options: refreshOptions, - traceStore, - forceResultSync: agentRunProjectionObservedTerminal(result, trace) - }); - const payload = synced.result ?? result; - if (payload && isTraceCommandTerminalStatus(payload.status)) { - await recordCodeAgentTerminalTurnStatusEffects({ - payload, - params: codeAgentReadSideTerminalParams(payload, options), - options: refreshOptions - }); - } - performanceStore?.recordWorkbenchProjectorBatch?.({ phase: "turn_finalize", status: "ok", durationMs: nowMs() - startedAt }); - return { result: payload, runnerTrace: synced.runnerTrace ?? traceStore.snapshot(traceId), refreshError: null }; - } catch (error) { - performanceStore?.recordWorkbenchProjectorBatch?.({ phase: "turn_finalize", status: error?.code === "agentrun_timeout" ? "timeout" : "error", durationMs: nowMs() - startedAt }); - performanceStore?.recordWorkbenchProjectorError?.({ reason: error?.code ?? "agentrun_read_side_sync_failed" }); - traceStore.append(traceId, { - type: "projection_refresh", - status: "degraded", - label: "agentrun:read_side_sync:failed", - errorCode: error?.code ?? "agentrun_read_side_sync_failed", - message: error?.message ?? "AgentRun read-side projection refresh failed", - terminal: false, - valuesPrinted: false - }); - return { result, runnerTrace: traceStore.snapshot(traceId), refreshError: error }; - } -} - -function shouldRefreshAgentRunProjectionOnRead(result = {}) { - const agentRun = result?.agentRun && typeof result.agentRun === "object" ? result.agentRun : null; - if (!agentRun?.runId || !agentRun?.commandId) return false; - if (isTraceCommandTerminalStatus(result?.status) && agentRunTerminalResultRefreshSatisfied(result, result?.traceId)) return false; - return true; -} - -function codeAgentReadSideTerminalParams(payload = {}, options = {}) { - const session = payload.session && typeof payload.session === "object" ? payload.session : null; - const sessionReuse = payload.sessionReuse && typeof payload.sessionReuse === "object" ? payload.sessionReuse : null; - return { - traceId: payload.traceId, - conversationId: safeConversationId(payload.conversationId ?? session?.conversationId ?? sessionReuse?.conversationId) || null, - sessionId: safeSessionId(payload.sessionId ?? session?.sessionId ?? sessionReuse?.sessionId) || null, - threadId: safeOpaqueId(payload.threadId ?? session?.threadId ?? sessionReuse?.threadId) || null, - projectId: payload.projectId ?? null, - ownerUserId: payload.ownerUserId ?? options.actor?.id, - ownerRole: payload.ownerRole ?? options.actor?.role - }; -} - function codeAgentRequestScopedOptions(options = {}) { return { ...options, @@ -1341,16 +1278,10 @@ async function readCodeAgentCompatProjection(traceId, options = {}) { if (result?.ownerUserId && !readModel.canReadOwner(result.ownerUserId)) return forbiddenTurnSnapshot(traceId); const projectionTrace = await readModel.traceSnapshot(traceId); let trace = traceSnapshotWithTerminalEvidence(projectionTrace, result, traceId, null); - const refreshed = await refreshAgentRunProjectionForCompatRead({ traceId, result, trace, options }); - if (refreshed.runnerTrace) trace = traceSnapshotWithTerminalEvidence(refreshed.runnerTrace, result, traceId, refreshed.refreshError ?? null); - if (refreshed.result && refreshed.result !== result) { - result = refreshed.result; - trace = traceSnapshotWithTerminalEvidence(refreshed.runnerTrace ?? trace, result, traceId, refreshed.refreshError ?? null); - } - const projection = readModel.projectionDiagnostics({ traceId, result, trace, refreshError: refreshed.refreshError ?? null }); - recordCodeAgentProjectionMetrics(options, { result, trace, projection, refreshError: refreshed.refreshError ?? null }); + const projection = readModel.projectionDiagnostics({ traceId, result, trace, refreshError: null }); + recordCodeAgentProjectionMetrics(options, { result, trace, projection, refreshError: null }); const found = Boolean(result || session || (trace && trace.status !== "missing") || trace?.persisted === true); - return { result, session, trace, projection, found, refreshError: refreshed.refreshError ?? null }; + return { result, session, trace, projection, found, refreshError: null }; } function projectedSessionTraceResult(session, traceId) { @@ -2736,6 +2667,8 @@ function traceSnapshotWithTerminalEvidence(snapshot, result, traceId, refreshErr ok: true, status: "expired", traceStatus: "expired", + projectionStatus: "projecting", + projectionHealth: "degraded", persisted: true, retention: traceRetentionSummary("expired"), conversationId: evidence.conversationId,