diff --git a/packages/effect-codex-app-server/src/_internal/shared.test.ts b/packages/effect-codex-app-server/src/_internal/shared.test.ts index ba354d568701..2c316147f658 100644 --- a/packages/effect-codex-app-server/src/_internal/shared.test.ts +++ b/packages/effect-codex-app-server/src/_internal/shared.test.ts @@ -136,26 +136,35 @@ it.effect("passes request errors through without adding a wrapper", () => }), ); -it.effect("normalizes unrecognized plan types to unknown before decoding", () => +it.effect("normalizes unrecognized account plan types to unknown before decoding", () => Effect.gen(function* () { - const account = yield* Shared.decodeOptionalPayload( - "account/read", - CodexSchema.V2GetAccountResponse, - { - account: { - type: "chatgpt", - email: "edu@example.com", - planType: "edu_plus", + const plansAddedAfterThePinnedSchema = [ + "self_serve_business_prolite", + "ent26", + "enterprise_cbp_automation", + "edu_plus", + "edu_pro", + ]; + for (const planType of plansAddedAfterThePinnedSchema) { + const account = yield* Shared.decodeOptionalPayload( + "account/read", + CodexSchema.V2GetAccountResponse, + { + account: { + type: "chatgpt", + email: "new-plan@example.com", + planType, + }, + requiresOpenaiAuth: false, }, - requiresOpenaiAuth: false, - }, - ); + ); - assert.deepEqual(account.account, { - type: "chatgpt", - email: "edu@example.com", - planType: "unknown", - }); + assert.deepEqual(account.account, { + type: "chatgpt", + email: "new-plan@example.com", + planType: "unknown", + }); + } const knownPlan = yield* Shared.decodeOptionalPayload( "account/read", diff --git a/packages/effect-codex-app-server/src/_internal/shared.ts b/packages/effect-codex-app-server/src/_internal/shared.ts index 2fb916145259..27143a49e301 100644 --- a/packages/effect-codex-app-server/src/_internal/shared.ts +++ b/packages/effect-codex-app-server/src/_internal/shared.ts @@ -18,9 +18,9 @@ export const JsonRpcResponseEnvelope = Schema.Struct({ }); // Plan types emitted by the running codex binary can be newer than the pinned -// protocol schema (e.g. "edu_plus"). Upstream maps unrecognized plans to -// "unknown" via #[serde(other)]; mirror that so account payloads still decode. -const KNOWN_PLAN_TYPES = new Set([ +// protocol schema. Upstream maps unrecognized plans to "unknown" via +// #[serde(other)]; mirror that so account payloads still decode. +const PINNED_PLAN_TYPES = new Set([ "free", "go", "plus", @@ -46,7 +46,7 @@ export const normalizeUnknownPlanTypes = (value: unknown): unknown => { return Object.fromEntries( Object.entries(value).map(([key, child]) => [ key, - key === "planType" && typeof child === "string" && !KNOWN_PLAN_TYPES.has(child) + key === "planType" && typeof child === "string" && !PINNED_PLAN_TYPES.has(child) ? "unknown" : normalizeUnknownPlanTypes(child), ]),