diff --git a/apps/server/src/provider/Layers/CodexProvider.ts b/apps/server/src/provider/Layers/CodexProvider.ts index 57b0cab334bb..f65d4432ab6a 100644 --- a/apps/server/src/provider/Layers/CodexProvider.ts +++ b/apps/server/src/provider/Layers/CodexProvider.ts @@ -115,6 +115,8 @@ export function codexPlanLabel(planType: string | null | undefined): string | un return "ChatGPT Pro 20x Subscription"; case "prolite": return "ChatGPT Pro 5x Subscription"; + case "promax": + return "ChatGPT Pro 25x Subscription"; case "team": return "ChatGPT Team Subscription"; case "self_serve_business_prolite": diff --git a/packages/effect-codex-app-server/scripts/generate.ts b/packages/effect-codex-app-server/scripts/generate.ts index b2696097ef8c..dbcf55c6c663 100644 --- a/packages/effect-codex-app-server/scripts/generate.ts +++ b/packages/effect-codex-app-server/scripts/generate.ts @@ -145,6 +145,12 @@ const ManualSchemas: Record = { }, }; +// Codex ships new ChatGPT plans between protocol refreshes and reads unknown +// ones as `unknown`. Accept any plan so a new one cannot fail account reads. +const DefinitionSchemaOverrides: Record = { + PlanType: { type: "string" }, +}; + const getGeneratedPaths = Effect.fn("getGeneratedPaths")(function* () { const path = yield* Path.Path; const generatedDir = path.join(import.meta.dirname, "..", "src", "_generated"); @@ -643,7 +649,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () { aggregateSchemas[localDefinitionNames.get(definitionName)!] = stripNullDefaults( normalizeNullableTypes( rewriteExternalRefs( - definitionSchema, + DefinitionSchemaOverrides[definitionName] ?? definitionSchema, localDefinitionNames, file.namespace, exportNameByQualifiedName, diff --git a/packages/effect-codex-app-server/src/_generated/schema.gen.ts b/packages/effect-codex-app-server/src/_generated/schema.gen.ts index 9bc7b1ec1e9e..e9ac22ec120b 100644 --- a/packages/effect-codex-app-server/src/_generated/schema.gen.ts +++ b/packages/effect-codex-app-server/src/_generated/schema.gen.ts @@ -3204,43 +3204,10 @@ export const ServerNotification__AuthMode = Schema.Union( identifier: "ServerNotification__AuthMode", }); -export type ServerNotification__PlanType = - | "free" - | "go" - | "plus" - | "pro" - | "prolite" - | "team" - | "self_serve_business_prolite" - | "self_serve_business_usage_based" - | "business" - | "ent26" - | "enterprise_cbp_automation" - | "enterprise_cbp_usage_based" - | "enterprise" - | "edu" - | "edu_plus" - | "edu_pro" - | "unknown"; -export const ServerNotification__PlanType = Schema.Literals([ - "free", - "go", - "plus", - "pro", - "prolite", - "team", - "self_serve_business_prolite", - "self_serve_business_usage_based", - "business", - "ent26", - "enterprise_cbp_automation", - "enterprise_cbp_usage_based", - "enterprise", - "edu", - "edu_plus", - "edu_pro", - "unknown", -]).annotate({ identifier: "ServerNotification__PlanType" }); +export type ServerNotification__PlanType = string; +export const ServerNotification__PlanType = Schema.String.annotate({ + identifier: "ServerNotification__PlanType", +}); export type ServerNotification__CreditsSnapshot = { readonly balance?: string | null; @@ -4138,43 +4105,10 @@ export const V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot = used: Schema.String, }).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot" }); -export type V2AccountRateLimitsUpdatedNotification__PlanType = - | "free" - | "go" - | "plus" - | "pro" - | "prolite" - | "team" - | "self_serve_business_prolite" - | "self_serve_business_usage_based" - | "business" - | "ent26" - | "enterprise_cbp_automation" - | "enterprise_cbp_usage_based" - | "enterprise" - | "edu" - | "edu_plus" - | "edu_pro" - | "unknown"; -export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.Literals([ - "free", - "go", - "plus", - "pro", - "prolite", - "team", - "self_serve_business_prolite", - "self_serve_business_usage_based", - "business", - "ent26", - "enterprise_cbp_automation", - "enterprise_cbp_usage_based", - "enterprise", - "edu", - "edu_plus", - "edu_pro", - "unknown", -]).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__PlanType" }); +export type V2AccountRateLimitsUpdatedNotification__PlanType = string; +export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.String.annotate({ + identifier: "V2AccountRateLimitsUpdatedNotification__PlanType", +}); export type V2AccountRateLimitsUpdatedNotification__RateLimitWindow = { readonly resetsAt?: number | null; @@ -4260,43 +4194,10 @@ export const V2AccountUpdatedNotification__AuthMode = Schema.Union( identifier: "V2AccountUpdatedNotification__AuthMode", }); -export type V2AccountUpdatedNotification__PlanType = - | "free" - | "go" - | "plus" - | "pro" - | "prolite" - | "team" - | "self_serve_business_prolite" - | "self_serve_business_usage_based" - | "business" - | "ent26" - | "enterprise_cbp_automation" - | "enterprise_cbp_usage_based" - | "enterprise" - | "edu" - | "edu_plus" - | "edu_pro" - | "unknown"; -export const V2AccountUpdatedNotification__PlanType = Schema.Literals([ - "free", - "go", - "plus", - "pro", - "prolite", - "team", - "self_serve_business_prolite", - "self_serve_business_usage_based", - "business", - "ent26", - "enterprise_cbp_automation", - "enterprise_cbp_usage_based", - "enterprise", - "edu", - "edu_plus", - "edu_pro", - "unknown", -]).annotate({ identifier: "V2AccountUpdatedNotification__PlanType" }); +export type V2AccountUpdatedNotification__PlanType = string; +export const V2AccountUpdatedNotification__PlanType = Schema.String.annotate({ + identifier: "V2AccountUpdatedNotification__PlanType", +}); export type V2AppListUpdatedNotification__AppReview = { readonly status: string }; export const V2AppListUpdatedNotification__AppReview = Schema.Struct({ @@ -5484,43 +5385,10 @@ export const V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = Schema. used: Schema.String, }).annotate({ identifier: "V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot" }); -export type V2GetAccountRateLimitsResponse__PlanType = - | "free" - | "go" - | "plus" - | "pro" - | "prolite" - | "team" - | "self_serve_business_prolite" - | "self_serve_business_usage_based" - | "business" - | "ent26" - | "enterprise_cbp_automation" - | "enterprise_cbp_usage_based" - | "enterprise" - | "edu" - | "edu_plus" - | "edu_pro" - | "unknown"; -export const V2GetAccountRateLimitsResponse__PlanType = Schema.Literals([ - "free", - "go", - "plus", - "pro", - "prolite", - "team", - "self_serve_business_prolite", - "self_serve_business_usage_based", - "business", - "ent26", - "enterprise_cbp_automation", - "enterprise_cbp_usage_based", - "enterprise", - "edu", - "edu_plus", - "edu_pro", - "unknown", -]).annotate({ identifier: "V2GetAccountRateLimitsResponse__PlanType" }); +export type V2GetAccountRateLimitsResponse__PlanType = string; +export const V2GetAccountRateLimitsResponse__PlanType = Schema.String.annotate({ + identifier: "V2GetAccountRateLimitsResponse__PlanType", +}); export type V2GetAccountRateLimitsResponse__RateLimitWindow = { readonly resetsAt?: number | null; @@ -5563,43 +5431,10 @@ export const V2GetAccountRateLimitsResponse__RateLimitReachedType = Schema.Liter "workspace_member_usage_limit_reached", ]).annotate({ identifier: "V2GetAccountRateLimitsResponse__RateLimitReachedType" }); -export type V2GetAccountResponse__PlanType = - | "free" - | "go" - | "plus" - | "pro" - | "prolite" - | "team" - | "self_serve_business_prolite" - | "self_serve_business_usage_based" - | "business" - | "ent26" - | "enterprise_cbp_automation" - | "enterprise_cbp_usage_based" - | "enterprise" - | "edu" - | "edu_plus" - | "edu_pro" - | "unknown"; -export const V2GetAccountResponse__PlanType = Schema.Literals([ - "free", - "go", - "plus", - "pro", - "prolite", - "team", - "self_serve_business_prolite", - "self_serve_business_usage_based", - "business", - "ent26", - "enterprise_cbp_automation", - "enterprise_cbp_usage_based", - "enterprise", - "edu", - "edu_plus", - "edu_pro", - "unknown", -]).annotate({ identifier: "V2GetAccountResponse__PlanType" }); +export type V2GetAccountResponse__PlanType = string; +export const V2GetAccountResponse__PlanType = Schema.String.annotate({ + identifier: "V2GetAccountResponse__PlanType", +}); export type V2GetAccountResponse__AccountRoutingOverride = "NO_CONSTRAINT" | "us" | "us_cr"; export const V2GetAccountResponse__AccountRoutingOverride = Schema.Literals([ diff --git a/packages/effect-codex-app-server/src/schema.test.ts b/packages/effect-codex-app-server/src/schema.test.ts index b12b33e02854..9f5e2c7beaf7 100644 --- a/packages/effect-codex-app-server/src/schema.test.ts +++ b/packages/effect-codex-app-server/src/schema.test.ts @@ -4,6 +4,10 @@ import * as Schema from "effect/Schema"; import * as CodexSchema from "./schema.ts"; const isGetAccountResponse = Schema.is(CodexSchema.V2GetAccountResponse); +const isAccountUpdatedNotification = Schema.is(CodexSchema.V2AccountUpdatedNotification); +const isAccountRateLimitsUpdatedNotification = Schema.is( + CodexSchema.V2AccountRateLimitsUpdatedNotification, +); const isThreadReadResponse = Schema.is(CodexSchema.V2ThreadReadResponse); const isThreadResumeResponse = Schema.is(CodexSchema.V2ThreadResumeResponse); const isThreadForkResponse = Schema.is(CodexSchema.V2ThreadForkResponse); @@ -201,16 +205,8 @@ it("accepts Codex misalignment policy errors for thread responses", () => { ); }); -it("accepts Codex 0.150 account plan values", () => { - const planTypes = [ - "self_serve_business_prolite", - "ent26", - "enterprise_cbp_automation", - "edu_plus", - "edu_pro", - ]; - - for (const planType of planTypes) { +it("accepts account plans newer than the generated protocol", () => { + for (const planType of ["promax", "a_plan_codex_adds_later"]) { const accountResponse = { account: { email: "user@example.com", @@ -221,5 +217,7 @@ it("accepts Codex 0.150 account plan values", () => { }; assert.equal(isGetAccountResponse(accountResponse), true); + assert.equal(isAccountUpdatedNotification({ authMode: "chatgpt", planType }), true); + assert.equal(isAccountRateLimitsUpdatedNotification({ rateLimits: { planType } }), true); } });