diff --git a/internal/cloud/access-control.test.ts b/internal/cloud/access-control.test.ts index 2a3ffdb8..41c18b8f 100644 --- a/internal/cloud/access-control.test.ts +++ b/internal/cloud/access-control.test.ts @@ -999,6 +999,28 @@ test("workbench workspace read does not repair terminal selected conversation af assert.equal(restored.body.workspace.selectedConversation.messages.some((message) => message.text === "repair completed"), false); assert.equal(restored.body.workspace.revision, 2); assert.equal(agentRunCalls.length, 0); + + const legacyStale = await patchJson(port, `/v1/workbench/workspace/${workspace.body.workspace.workspaceId}`, { + expectedRevision: 2, + workspace: { + selectedConversationId: "cnv_legacy_stale_workspace", + selectedAgentSessionId: "ses_legacy_stale_workspace", + providerProfile: "deepseek", + sessionStatus: "running", + lastTraceId: "trc_legacy_stale_workspace" + }, + updatedByClient: "test-suite-legacy-stale" + }, aliceLogin.cookie); + assert.equal(legacyStale.status, 200); + assert.equal(legacyStale.body.workspace.activeTraceId, null); + assert.equal(legacyStale.body.workspace.workspace.lastTraceId, undefined); + assert.equal(legacyStale.body.workspace.workspace.sessionStatus, undefined); + + const legacyRestored = await getJson(port, "/v1/workbench/workspace?projectId=prj_hwpod_workbench", aliceLogin.cookie); + assert.equal(legacyRestored.status, 200); + assert.equal(legacyRestored.body.workspace.activeTraceId, null); + assert.equal(legacyRestored.body.workspace.workspace.lastTraceId, undefined); + assert.equal(legacyRestored.body.workspace.workspace.sessionStatus, undefined); } finally { await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve()))); await new Promise((resolve, reject) => agentRunServer.close((error) => (error ? reject(error) : resolve()))); diff --git a/internal/cloud/access-control.ts b/internal/cloud/access-control.ts index 61ff579d..e4da7988 100644 --- a/internal/cloud/access-control.ts +++ b/internal/cloud/access-control.ts @@ -2133,14 +2133,17 @@ function workspaceJsonForSelectedConversation(workspace, conversation = null) { } function redactedWorkspaceJson(value = {}) { const workspace = normalizeObject(value); + const activeTraceId = textOr(workspace.activeTraceId, ""); + const sessionStatus = textOr(workspace.sessionStatus, ""); + const staleActiveSessionStatus = !activeTraceId && isActiveConversationStatus(sessionStatus); return pruneEmpty({ selectedConversationId: textOr(workspace.selectedConversationId, ""), selectedAgentSessionId: textOr(workspace.selectedAgentSessionId, ""), - activeTraceId: textOr(workspace.activeTraceId, ""), + activeTraceId, previousActiveTraceId: textOr(workspace.previousActiveTraceId, ""), providerProfile: textOr(workspace.providerProfile, ""), - sessionStatus: textOr(workspace.sessionStatus, ""), - lastTraceId: textOr(workspace.lastTraceId, ""), + sessionStatus: staleActiveSessionStatus ? "" : sessionStatus, + lastTraceId: activeTraceId ? textOr(workspace.lastTraceId, "") : "", workspaceRevisionConflict: workspace.workspaceRevisionConflict === true, expectedWorkspaceRevision: Number.isFinite(Number(workspace.expectedWorkspaceRevision)) ? Number(workspace.expectedWorkspaceRevision) : undefined, staleContinuationCleared: workspace.staleContinuationCleared === true,