From aa7ade90fd416e75c36cf3aad6245bdcec22ec9c Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Sat, 7 Nov 2026 21:31:12 +0000 Subject: [PATCH] fix(server): retain feature definitions in stored agent snapshots Stored fetches dropped saved features that unread and archive updates already published. Project them through the existing normalizer so both interfaces expose the same definitions without reopening the runtime. --- .../server/agent/agent-projections.test.ts | 37 +++++++++++++++++++ .../src/server/agent/agent-projections.ts | 1 + 2 files changed, 38 insertions(+) diff --git a/packages/server/src/server/agent/agent-projections.test.ts b/packages/server/src/server/agent/agent-projections.test.ts index e9c6289db5..bb98b9baee 100644 --- a/packages/server/src/server/agent/agent-projections.test.ts +++ b/packages/server/src/server/agent/agent-projections.test.ts @@ -485,6 +485,43 @@ describe("toAgentPayload", () => { }); }); +describe("buildStoredAgentPayload features", () => { + it.each([null, "2026-11-01T00:00:00.000Z"])( + "preserves saved feature definitions like live snapshots (archivedAt=%s)", + (archivedAt) => { + const features: AgentFeature[] = [ + createFeature({ value: false }), + { + type: "select", + id: "service_tier", + label: "Service tier", + value: "default", + options: [ + { id: "default", label: "Normal" }, + { id: "fast", label: "Fast" }, + ], + }, + ]; + const agent = createManagedAgent({ features }); + const record = { ...toStoredAgentRecord(agent), archivedAt }; + + const payload = buildStoredAgentPayload(record, [agent.provider]); + + expect(payload.features).toEqual(features); + expect(payload.features).toEqual(toAgentPayload(agent).features); + expect(payload.features).not.toBe(record.features); + expect(payload.features?.[0]).not.toBe(record.features?.[0]); + }, + ); + + it("uses an empty feature list for older records without saved definitions", () => { + const record = toStoredAgentRecord(createManagedAgent()); + delete record.features; + + expect(buildStoredAgentPayload(record, [record.provider]).features).toEqual([]); + }); +}); + describe("toRecentProviderSessionDescriptorPayload", () => { it("projects provider import rows to provider-opaque public recent sessions", () => { const session: ImportableProviderSession & { provider: string } = { diff --git a/packages/server/src/server/agent/agent-projections.ts b/packages/server/src/server/agent/agent-projections.ts index b11021a99c..c3bd4909fc 100644 --- a/packages/server/src/server/agent/agent-projections.ts +++ b/packages/server/src/server/agent/agent-projections.ts @@ -263,6 +263,7 @@ export function buildStoredAgentPayload( capabilities: defaultCapabilities, currentModeId: record.lastModeId ?? null, availableModes: [], + features: normalizeFeatures(record.features), pendingPermissions: [], persistence, title: record.title ?? null,