authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-09-29 12:51:36-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-29 12:51:36-07:00
log451afcb22d93f06cb24f9bc16703404564952553
tree9f69767113f071ce9ba266b67d512cd3d8acd86f
parent2cbc24fcae2b5649d7b60b68da72053a37fa82d5
signature Signed by PGP key B5690EEEBB952194

fix(codex): Pro Max accounts load, so Ultrafast shows up (#14304)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

5 files changed, 57 insertions(+), 193 deletions(-)

apps/server/src/provider/Layers/CodexProvider.test.ts+10
......@@ -81,6 +81,11 @@ it("uses standard routing when the catalog has no default service tier", () => {
8181 name: "Fast",
8282 description: "1.5x speed, increased usage",
8383 },
84 {
85 id: "ultrafast",
86 name: "Ultrafast",
87 description: "The fastest available responses for latency-sensitive work.",
88 },
8489 ],
8590 supportedReasoningEfforts: [],
8691 });
......@@ -97,6 +102,11 @@ it("uses standard routing when the catalog has no default service tier", () => {
97102 label: "Fast",
98103 description: "1.5x speed, increased usage",
99104 },
105 {
106 id: "ultrafast",
107 label: "Ultrafast",
108 description: "Even faster, more expensive",
109 },
100110 ],
101111 currentValue: "default",
102112 },
apps/server/src/provider/Layers/CodexProvider.ts+16-6
......@@ -90,6 +90,11 @@ const REASONING_EFFORT_LABELS: Readonly<Record<string, string>> = {
9090
9191const DEFAULT_SERVICE_TIER_ID = "default";
9292
93/** Shorter copy for tiers whose catalog description wraps in the traits menu. */
94const SERVICE_TIER_DESCRIPTIONS: Readonly<Record<string, string>> = {
95 ultrafast: "Even faster, more expensive",
96};
97
9398function reasoningEffortLabel(reasoningEffort: string): string {
9499 return REASONING_EFFORT_LABELS[reasoningEffort] ?? reasoningEffort;
95100}
......@@ -115,6 +120,8 @@ export function codexPlanLabel(planType: string | null | undefined): string | un
115120 return "ChatGPT Pro 20x Subscription";
116121 case "prolite":
117122 return "ChatGPT Pro 5x Subscription";
123 case "promax":
124 return "ChatGPT Pro Max Subscription";
118125 case "team":
119126 return "ChatGPT Team Subscription";
120127 case "self_serve_business_prolite":
......@@ -195,12 +202,15 @@ export function mapCodexModelCapabilities(
195202 label: "Standard",
196203 ...(defaultServiceTier === DEFAULT_SERVICE_TIER_ID ? { isDefault: true } : {}),
197204 },
198 ...serviceTiers.map((tier) => ({
199 id: tier.id,
200 label: tier.name,
201 ...(tier.description ? { description: tier.description } : {}),
202 ...(defaultServiceTier === tier.id ? { isDefault: true } : {}),
203 })),
205 ...serviceTiers.map((tier) => {
206 const description = SERVICE_TIER_DESCRIPTIONS[tier.id] ?? tier.description;
207 return {
208 id: tier.id,
209 label: tier.name,
210 ...(description ? { description } : {}),
211 ...(defaultServiceTier === tier.id ? { isDefault: true } : {}),
212 };
213 }),
204214 ],
205215 currentValue: defaultServiceTier,
206216 });
packages/effect-codex-app-server/scripts/generate.ts+8-1
......@@ -145,6 +145,13 @@ const ManualSchemas: Record<string, Schema.Json> = {
145145 },
146146};
147147
148// Codex adds plan slugs between our protocol refreshes (0.159 added `promax`).
149// T3 Code only uses the plan for labels, so an unknown slug must not fail the
150// whole `account/read` decode and take the provider down with it.
151const DefinitionOverrides: Record<string, Schema.Json> = {
152 PlanType: { type: "string" },
153};
154
148155const getGeneratedPaths = Effect.fn("getGeneratedPaths")(function* () {
149156 const path = yield* Path.Path;
150157 const generatedDir = path.join(import.meta.dirname, "..", "src", "_generated");
......@@ -643,7 +650,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
643650 aggregateSchemas[localDefinitionNames.get(definitionName)!] = stripNullDefaults(
644651 normalizeNullableTypes(
645652 rewriteExternalRefs(
646 definitionSchema,
653 DefinitionOverrides[definitionName] ?? definitionSchema,
647654 localDefinitionNames,
648655 file.namespace,
649656 exportNameByQualifiedName,
packages/effect-codex-app-server/src/_generated/schema.gen.ts+20-185
......@@ -3204,43 +3204,10 @@ export const ServerNotification__AuthMode = Schema.Union(
32043204 identifier: "ServerNotification__AuthMode",
32053205});
32063206
3207export type ServerNotification__PlanType =
3208 | "free"
3209 | "go"
3210 | "plus"
3211 | "pro"
3212 | "prolite"
3213 | "team"
3214 | "self_serve_business_prolite"
3215 | "self_serve_business_usage_based"
3216 | "business"
3217 | "ent26"
3218 | "enterprise_cbp_automation"
3219 | "enterprise_cbp_usage_based"
3220 | "enterprise"
3221 | "edu"
3222 | "edu_plus"
3223 | "edu_pro"
3224 | "unknown";
3225export const ServerNotification__PlanType = Schema.Literals([
3226 "free",
3227 "go",
3228 "plus",
3229 "pro",
3230 "prolite",
3231 "team",
3232 "self_serve_business_prolite",
3233 "self_serve_business_usage_based",
3234 "business",
3235 "ent26",
3236 "enterprise_cbp_automation",
3237 "enterprise_cbp_usage_based",
3238 "enterprise",
3239 "edu",
3240 "edu_plus",
3241 "edu_pro",
3242 "unknown",
3243]).annotate({ identifier: "ServerNotification__PlanType" });
3207export type ServerNotification__PlanType = string;
3208export const ServerNotification__PlanType = Schema.String.annotate({
3209 identifier: "ServerNotification__PlanType",
3210});
32443211
32453212export type ServerNotification__CreditsSnapshot = {
32463213 readonly balance?: string | null;
......@@ -4138,43 +4105,10 @@ export const V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot =
41384105 used: Schema.String,
41394106}).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot" });
41404107
4141export type V2AccountRateLimitsUpdatedNotification__PlanType =
4142 | "free"
4143 | "go"
4144 | "plus"
4145 | "pro"
4146 | "prolite"
4147 | "team"
4148 | "self_serve_business_prolite"
4149 | "self_serve_business_usage_based"
4150 | "business"
4151 | "ent26"
4152 | "enterprise_cbp_automation"
4153 | "enterprise_cbp_usage_based"
4154 | "enterprise"
4155 | "edu"
4156 | "edu_plus"
4157 | "edu_pro"
4158 | "unknown";
4159export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.Literals([
4160 "free",
4161 "go",
4162 "plus",
4163 "pro",
4164 "prolite",
4165 "team",
4166 "self_serve_business_prolite",
4167 "self_serve_business_usage_based",
4168 "business",
4169 "ent26",
4170 "enterprise_cbp_automation",
4171 "enterprise_cbp_usage_based",
4172 "enterprise",
4173 "edu",
4174 "edu_plus",
4175 "edu_pro",
4176 "unknown",
4177]).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__PlanType" });
4108export type V2AccountRateLimitsUpdatedNotification__PlanType = string;
4109export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.String.annotate({
4110 identifier: "V2AccountRateLimitsUpdatedNotification__PlanType",
4111});
41784112
41794113export type V2AccountRateLimitsUpdatedNotification__RateLimitWindow = {
41804114 readonly resetsAt?: number | null;
......@@ -4260,43 +4194,10 @@ export const V2AccountUpdatedNotification__AuthMode = Schema.Union(
42604194 identifier: "V2AccountUpdatedNotification__AuthMode",
42614195});
42624196
4263export type V2AccountUpdatedNotification__PlanType =
4264 | "free"
4265 | "go"
4266 | "plus"
4267 | "pro"
4268 | "prolite"
4269 | "team"
4270 | "self_serve_business_prolite"
4271 | "self_serve_business_usage_based"
4272 | "business"
4273 | "ent26"
4274 | "enterprise_cbp_automation"
4275 | "enterprise_cbp_usage_based"
4276 | "enterprise"
4277 | "edu"
4278 | "edu_plus"
4279 | "edu_pro"
4280 | "unknown";
4281export const V2AccountUpdatedNotification__PlanType = Schema.Literals([
4282 "free",
4283 "go",
4284 "plus",
4285 "pro",
4286 "prolite",
4287 "team",
4288 "self_serve_business_prolite",
4289 "self_serve_business_usage_based",
4290 "business",
4291 "ent26",
4292 "enterprise_cbp_automation",
4293 "enterprise_cbp_usage_based",
4294 "enterprise",
4295 "edu",
4296 "edu_plus",
4297 "edu_pro",
4298 "unknown",
4299]).annotate({ identifier: "V2AccountUpdatedNotification__PlanType" });
4197export type V2AccountUpdatedNotification__PlanType = string;
4198export const V2AccountUpdatedNotification__PlanType = Schema.String.annotate({
4199 identifier: "V2AccountUpdatedNotification__PlanType",
4200});
43004201
43014202export type V2AppListUpdatedNotification__AppReview = { readonly status: string };
43024203export const V2AppListUpdatedNotification__AppReview = Schema.Struct({
......@@ -5484,43 +5385,10 @@ export const V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = Schema.
54845385 used: Schema.String,
54855386}).annotate({ identifier: "V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot" });
54865387
5487export type V2GetAccountRateLimitsResponse__PlanType =
5488 | "free"
5489 | "go"
5490 | "plus"
5491 | "pro"
5492 | "prolite"
5493 | "team"
5494 | "self_serve_business_prolite"
5495 | "self_serve_business_usage_based"
5496 | "business"
5497 | "ent26"
5498 | "enterprise_cbp_automation"
5499 | "enterprise_cbp_usage_based"
5500 | "enterprise"
5501 | "edu"
5502 | "edu_plus"
5503 | "edu_pro"
5504 | "unknown";
5505export const V2GetAccountRateLimitsResponse__PlanType = Schema.Literals([
5506 "free",
5507 "go",
5508 "plus",
5509 "pro",
5510 "prolite",
5511 "team",
5512 "self_serve_business_prolite",
5513 "self_serve_business_usage_based",
5514 "business",
5515 "ent26",
5516 "enterprise_cbp_automation",
5517 "enterprise_cbp_usage_based",
5518 "enterprise",
5519 "edu",
5520 "edu_plus",
5521 "edu_pro",
5522 "unknown",
5523]).annotate({ identifier: "V2GetAccountRateLimitsResponse__PlanType" });
5388export type V2GetAccountRateLimitsResponse__PlanType = string;
5389export const V2GetAccountRateLimitsResponse__PlanType = Schema.String.annotate({
5390 identifier: "V2GetAccountRateLimitsResponse__PlanType",
5391});
55245392
55255393export type V2GetAccountRateLimitsResponse__RateLimitWindow = {
55265394 readonly resetsAt?: number | null;
......@@ -5563,43 +5431,10 @@ export const V2GetAccountRateLimitsResponse__RateLimitReachedType = Schema.Liter
55635431 "workspace_member_usage_limit_reached",
55645432]).annotate({ identifier: "V2GetAccountRateLimitsResponse__RateLimitReachedType" });
55655433
5566export type V2GetAccountResponse__PlanType =
5567 | "free"
5568 | "go"
5569 | "plus"
5570 | "pro"
5571 | "prolite"
5572 | "team"
5573 | "self_serve_business_prolite"
5574 | "self_serve_business_usage_based"
5575 | "business"
5576 | "ent26"
5577 | "enterprise_cbp_automation"
5578 | "enterprise_cbp_usage_based"
5579 | "enterprise"
5580 | "edu"
5581 | "edu_plus"
5582 | "edu_pro"
5583 | "unknown";
5584export const V2GetAccountResponse__PlanType = Schema.Literals([
5585 "free",
5586 "go",
5587 "plus",
5588 "pro",
5589 "prolite",
5590 "team",
5591 "self_serve_business_prolite",
5592 "self_serve_business_usage_based",
5593 "business",
5594 "ent26",
5595 "enterprise_cbp_automation",
5596 "enterprise_cbp_usage_based",
5597 "enterprise",
5598 "edu",
5599 "edu_plus",
5600 "edu_pro",
5601 "unknown",
5602]).annotate({ identifier: "V2GetAccountResponse__PlanType" });
5434export type V2GetAccountResponse__PlanType = string;
5435export const V2GetAccountResponse__PlanType = Schema.String.annotate({
5436 identifier: "V2GetAccountResponse__PlanType",
5437});
56035438
56045439export type V2GetAccountResponse__AccountRoutingOverride = "NO_CONSTRAINT" | "us" | "us_cr";
56055440export const V2GetAccountResponse__AccountRoutingOverride = Schema.Literals([
packages/effect-codex-app-server/src/schema.test.ts+3-1
......@@ -201,13 +201,15 @@ it("accepts Codex misalignment policy errors for thread responses", () => {
201201 );
202202});
203203
204it("accepts Codex 0.150 account plan values", () => {
204it("accepts account plan slugs newer than the pinned protocol", () => {
205205 const planTypes = [
206206 "self_serve_business_prolite",
207207 "ent26",
208208 "enterprise_cbp_automation",
209209 "edu_plus",
210210 "edu_pro",
211 "promax",
212 "some_future_plan",
211213 ];
212214
213215 for (const planType of planTypes) {