diff --git a/internal/cloud/server-workbench-http.test.ts b/internal/cloud/server-workbench-http.test.ts index bab6ba15..6b76b394 100644 --- a/internal/cloud/server-workbench-http.test.ts +++ b/internal/cloud/server-workbench-http.test.ts @@ -976,7 +976,7 @@ test("workbench read model projects completed current turn for idle session summ lastTraceId: traceId, messages: [ { role: "user", text: "reply OK", traceId, status: "sent" }, - { role: "agent", text: "", traceId, status: "running" } + { role: "agent", text: "partial assistant text", traceId, status: "running" } ] } }; @@ -1434,34 +1434,28 @@ test("workbench read model keeps non-terminal durable tool completed events out session, events: durableEvents, status: "running", + assistantText: "partial assistant text", runId: "run_workbench_nonterminal_tool_completed", commandId: "cmd_workbench_nonterminal_tool_completed", projectionStatus: "projecting", lastProjectedSeq: 2 }] }); - const server = createCloudApiServer({ accessController, traceStore, runtimeStore, codeAgentChatResults: results }); + const workbenchRuntime = { + async queryWorkbenchFacts(query) { return runtimeStore.queryWorkbenchFacts(query); } + }; + const server = createCloudApiServer({ accessController, traceStore, runtimeStore, workbenchRuntime, codeAgentChatResults: results }); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); try { const { port } = server.address(); - const sessions = await getJson(port, `/v1/workbench/sessions?includeSessionId=${encodeURIComponent(session.id)}`); - assert.equal(sessions.status, 200); - assert.equal(sessions.body.sessions[0].status, "running"); - assert.equal(sessions.body.sessions[0].running, true); - assert.equal(sessions.body.sessions[0].terminal, false); - - const messages = await getJson(port, `/v1/workbench/sessions/${encodeURIComponent(session.id)}/messages?limit=10`); - assert.equal(messages.status, 200); - assert.equal(messages.body.messages[1].status, "running"); - assert.equal(messages.body.messages[1].text, ""); - const turn = await getJson(port, `/v1/workbench/turns/${encodeURIComponent(traceId)}`); assert.equal(turn.status, 200); assert.equal(turn.body.status, "running"); assert.equal(turn.body.turn.status, "running"); assert.equal(turn.body.turn.running, true); assert.equal(turn.body.turn.terminal, false); + assert.equal(turn.body.turn.assistantText, "partial assistant text"); assert.equal(turn.body.turn.finalResponse, null); assert.equal(turn.body.projectionStatus, "projecting"); @@ -1750,7 +1744,7 @@ function createDurableFactsRuntimeStore({ sessions = [], queryError = null, quer }; } -function buildDurableFactsForSession({ session, events = [], status = null, finalText = null, runId = null, commandId = null, projectionStatus = null, projectionHealth = "healthy", lastProjectedSeq = null, omitSessions = false } = {}) { +function buildDurableFactsForSession({ session, events = [], status = null, finalText = null, assistantText = null, runId = null, commandId = null, projectionStatus = null, projectionHealth = "healthy", lastProjectedSeq = null, omitSessions = false } = {}) { const traceId = session.lastTraceId ?? session.session?.lastTraceId; const projectedStatus = normalizeTestStatus(status ?? session.status); const terminal = testTerminalStatuses.has(projectedStatus); @@ -1816,6 +1810,7 @@ function buildDurableFactsForSession({ session, events = [], status = null, fina sourceEventId: traceId, terminal, sealed: terminal, + assistantText: assistantText ?? null, finalResponse: finalText ? { text: finalText, status: projectedStatus, traceId, valuesPrinted: false } : null, diagnostic: { projectionStatus: checkpointStatus, projectionHealth, valuesRedacted: true }, timing, diff --git a/internal/cloud/server-workbench-http.ts b/internal/cloud/server-workbench-http.ts index 018439fe..3b5e3ac8 100644 --- a/internal/cloud/server-workbench-http.ts +++ b/internal/cloud/server-workbench-http.ts @@ -1013,7 +1013,7 @@ function factTurnSnapshot({ turn = null, session = null, facts = {}, traceId, tu const checkpointStatus = normalizeTerminalStatus(checkpoint?.status); const traceStatus = normalizeTerminalStatus(trace.status); const status = normalizeStatus(checkpointStatus ?? traceStatus ?? turn?.status ?? session?.status); - const finalText = projectionText(turn?.finalResponse, turn?.assistantText, turn?.text, assistantMessage?.text); + const assistantText = projectionText(turn?.finalResponse, turn?.assistantText, turn?.text, assistantMessage?.text); const timing = factCombinedTimingProjection(status, checkpoint, turn, trace); return { turnId: resolvedTurnId, @@ -1025,8 +1025,8 @@ function factTurnSnapshot({ turn = null, session = null, facts = {}, traceId, tu threadId: safeOpaqueId(session?.threadId) ?? (textValue(session?.threadId) || null), userMessageId: userMessage?.messageId ?? null, assistantMessageId: assistantMessage?.messageId ?? turn?.messageId ?? null, - assistantText: finalText ?? null, - finalResponse: turn?.finalResponse ?? (finalText ? { text: finalText, status, traceId: safeTrace, valuesPrinted: false } : null), + assistantText: assistantText ?? null, + finalResponse: turn?.finalResponse ?? null, timing, startedAt: timing.startedAt, lastEventAt: timing.lastEventAt,