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", () => {...@@ -81,6 +81,11 @@ it("uses standard routing when the catalog has no default service tier", () => {
81 name: "Fast",81 name: "Fast",
82 description: "1.5x speed, increased usage",82 description: "1.5x speed, increased usage",
83 },83 },
84 {
85 id: "ultrafast",
86 name: "Ultrafast",
87 description: "The fastest available responses for latency-sensitive work.",
88 },
84 ],89 ],
85 supportedReasoningEfforts: [],90 supportedReasoningEfforts: [],
86 });91 });
...@@ -97,6 +102,11 @@ it("uses standard routing when the catalog has no default service tier", () => {...@@ -97,6 +102,11 @@ it("uses standard routing when the catalog has no default service tier", () => {
97 label: "Fast",102 label: "Fast",
98 description: "1.5x speed, increased usage",103 description: "1.5x speed, increased usage",
99 },104 },
105 {
106 id: "ultrafast",
107 label: "Ultrafast",
108 description: "Even faster, more expensive",
109 },
100 ],110 ],
101 currentValue: "default",111 currentValue: "default",
102 },112 },
apps/server/src/provider/Layers/CodexProvider.ts+16-6
...@@ -90,6 +90,11 @@ const REASONING_EFFORT_LABELS: Readonly<Record<string, string>> = {...@@ -90,6 +90,11 @@ const REASONING_EFFORT_LABELS: Readonly<Record<string, string>> = {
9090
91const DEFAULT_SERVICE_TIER_ID = "default";91const 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
93function reasoningEffortLabel(reasoningEffort: string): string {98function reasoningEffortLabel(reasoningEffort: string): string {
94 return REASONING_EFFORT_LABELS[reasoningEffort] ?? reasoningEffort;99 return REASONING_EFFORT_LABELS[reasoningEffort] ?? reasoningEffort;
95}100}
...@@ -115,6 +120,8 @@ export function codexPlanLabel(planType: string | null | undefined): string | un...@@ -115,6 +120,8 @@ export function codexPlanLabel(planType: string | null | undefined): string | un
115 return "ChatGPT Pro 20x Subscription";120 return "ChatGPT Pro 20x Subscription";
116 case "prolite":121 case "prolite":
117 return "ChatGPT Pro 5x Subscription";122 return "ChatGPT Pro 5x Subscription";
123 case "promax":
124 return "ChatGPT Pro Max Subscription";
118 case "team":125 case "team":
119 return "ChatGPT Team Subscription";126 return "ChatGPT Team Subscription";
120 case "self_serve_business_prolite":127 case "self_serve_business_prolite":
...@@ -195,12 +202,15 @@ export function mapCodexModelCapabilities(...@@ -195,12 +202,15 @@ export function mapCodexModelCapabilities(
195 label: "Standard",202 label: "Standard",
196 ...(defaultServiceTier === DEFAULT_SERVICE_TIER_ID ? { isDefault: true } : {}),203 ...(defaultServiceTier === DEFAULT_SERVICE_TIER_ID ? { isDefault: true } : {}),
197 },204 },
198 ...serviceTiers.map((tier) => ({205 ...serviceTiers.map((tier) => {
199 id: tier.id,206 const description = SERVICE_TIER_DESCRIPTIONS[tier.id] ?? tier.description;
200 label: tier.name,207 return {
201 ...(tier.description ? { description: tier.description } : {}),208 id: tier.id,
202 ...(defaultServiceTier === tier.id ? { isDefault: true } : {}),209 label: tier.name,
203 })),210 ...(description ? { description } : {}),
211 ...(defaultServiceTier === tier.id ? { isDefault: true } : {}),
212 };
213 }),
204 ],214 ],
205 currentValue: defaultServiceTier,215 currentValue: defaultServiceTier,
206 });216 });
packages/effect-codex-app-server/scripts/generate.ts+8-1
...@@ -145,6 +145,13 @@ const ManualSchemas: Record<string, Schema.Json> = {...@@ -145,6 +145,13 @@ const ManualSchemas: Record<string, Schema.Json> = {
145 },145 },
146};146};
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
148const getGeneratedPaths = Effect.fn("getGeneratedPaths")(function* () {155const getGeneratedPaths = Effect.fn("getGeneratedPaths")(function* () {
149 const path = yield* Path.Path;156 const path = yield* Path.Path;
150 const generatedDir = path.join(import.meta.dirname, "..", "src", "_generated");157 const generatedDir = path.join(import.meta.dirname, "..", "src", "_generated");
...@@ -643,7 +650,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {...@@ -643,7 +650,7 @@ const generateFiles = Effect.fn("generateFiles")(function* () {
643 aggregateSchemas[localDefinitionNames.get(definitionName)!] = stripNullDefaults(650 aggregateSchemas[localDefinitionNames.get(definitionName)!] = stripNullDefaults(
644 normalizeNullableTypes(651 normalizeNullableTypes(
645 rewriteExternalRefs(652 rewriteExternalRefs(
646 definitionSchema,653 DefinitionOverrides[definitionName] ?? definitionSchema,
647 localDefinitionNames,654 localDefinitionNames,
648 file.namespace,655 file.namespace,
649 exportNameByQualifiedName,656 exportNameByQualifiedName,
packages/effect-codex-app-server/src/_generated/schema.gen.ts+20-185
...@@ -3204,43 +3204,10 @@ export const ServerNotification__AuthMode = Schema.Union(...@@ -3204,43 +3204,10 @@ export const ServerNotification__AuthMode = Schema.Union(
3204 identifier: "ServerNotification__AuthMode",3204 identifier: "ServerNotification__AuthMode",
3205});3205});
32063206
3207export type ServerNotification__PlanType =3207export type ServerNotification__PlanType = string;
3208 | "free"3208export const ServerNotification__PlanType = Schema.String.annotate({
3209 | "go"3209 identifier: "ServerNotification__PlanType",
3210 | "plus"3210});
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" });
32443211
3245export type ServerNotification__CreditsSnapshot = {3212export type ServerNotification__CreditsSnapshot = {
3246 readonly balance?: string | null;3213 readonly balance?: string | null;
...@@ -4138,43 +4105,10 @@ export const V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot =...@@ -4138,43 +4105,10 @@ export const V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot =
4138 used: Schema.String,4105 used: Schema.String,
4139}).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot" });4106}).annotate({ identifier: "V2AccountRateLimitsUpdatedNotification__SpendControlLimitSnapshot" });
41404107
4141export type V2AccountRateLimitsUpdatedNotification__PlanType =4108export type V2AccountRateLimitsUpdatedNotification__PlanType = string;
4142 | "free"4109export const V2AccountRateLimitsUpdatedNotification__PlanType = Schema.String.annotate({
4143 | "go"4110 identifier: "V2AccountRateLimitsUpdatedNotification__PlanType",
4144 | "plus"4111});
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" });
41784112
4179export type V2AccountRateLimitsUpdatedNotification__RateLimitWindow = {4113export type V2AccountRateLimitsUpdatedNotification__RateLimitWindow = {
4180 readonly resetsAt?: number | null;4114 readonly resetsAt?: number | null;
...@@ -4260,43 +4194,10 @@ export const V2AccountUpdatedNotification__AuthMode = Schema.Union(...@@ -4260,43 +4194,10 @@ export const V2AccountUpdatedNotification__AuthMode = Schema.Union(
4260 identifier: "V2AccountUpdatedNotification__AuthMode",4194 identifier: "V2AccountUpdatedNotification__AuthMode",
4261});4195});
42624196
4263export type V2AccountUpdatedNotification__PlanType =4197export type V2AccountUpdatedNotification__PlanType = string;
4264 | "free"4198export const V2AccountUpdatedNotification__PlanType = Schema.String.annotate({
4265 | "go"4199 identifier: "V2AccountUpdatedNotification__PlanType",
4266 | "plus"4200});
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" });
43004201
4301export type V2AppListUpdatedNotification__AppReview = { readonly status: string };4202export type V2AppListUpdatedNotification__AppReview = { readonly status: string };
4302export const V2AppListUpdatedNotification__AppReview = Schema.Struct({4203export const V2AppListUpdatedNotification__AppReview = Schema.Struct({
...@@ -5484,43 +5385,10 @@ export const V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = Schema....@@ -5484,43 +5385,10 @@ export const V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot = Schema.
5484 used: Schema.String,5385 used: Schema.String,
5485}).annotate({ identifier: "V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot" });5386}).annotate({ identifier: "V2GetAccountRateLimitsResponse__SpendControlLimitSnapshot" });
54865387
5487export type V2GetAccountRateLimitsResponse__PlanType =5388export type V2GetAccountRateLimitsResponse__PlanType = string;
5488 | "free"5389export const V2GetAccountRateLimitsResponse__PlanType = Schema.String.annotate({
5489 | "go"5390 identifier: "V2GetAccountRateLimitsResponse__PlanType",
5490 | "plus"5391});
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" });
55245392
5525export type V2GetAccountRateLimitsResponse__RateLimitWindow = {5393export type V2GetAccountRateLimitsResponse__RateLimitWindow = {
5526 readonly resetsAt?: number | null;5394 readonly resetsAt?: number | null;
...@@ -5563,43 +5431,10 @@ export const V2GetAccountRateLimitsResponse__RateLimitReachedType = Schema.Liter...@@ -5563,43 +5431,10 @@ export const V2GetAccountRateLimitsResponse__RateLimitReachedType = Schema.Liter
5563 "workspace_member_usage_limit_reached",5431 "workspace_member_usage_limit_reached",
5564]).annotate({ identifier: "V2GetAccountRateLimitsResponse__RateLimitReachedType" });5432]).annotate({ identifier: "V2GetAccountRateLimitsResponse__RateLimitReachedType" });
55655433
5566export type V2GetAccountResponse__PlanType =5434export type V2GetAccountResponse__PlanType = string;
5567 | "free"5435export const V2GetAccountResponse__PlanType = Schema.String.annotate({
5568 | "go"5436 identifier: "V2GetAccountResponse__PlanType",
5569 | "plus"5437});
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" });
56035438
5604export type V2GetAccountResponse__AccountRoutingOverride = "NO_CONSTRAINT" | "us" | "us_cr";5439export type V2GetAccountResponse__AccountRoutingOverride = "NO_CONSTRAINT" | "us" | "us_cr";
5605export const V2GetAccountResponse__AccountRoutingOverride = Schema.Literals([5440export 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", () => {...@@ -201,13 +201,15 @@ it("accepts Codex misalignment policy errors for thread responses", () => {
201 );201 );
202});202});
203203
204it("accepts Codex 0.150 account plan values", () => {204it("accepts account plan slugs newer than the pinned protocol", () => {
205 const planTypes = [205 const planTypes = [
206 "self_serve_business_prolite",206 "self_serve_business_prolite",
207 "ent26",207 "ent26",
208 "enterprise_cbp_automation",208 "enterprise_cbp_automation",
209 "edu_plus",209 "edu_plus",
210 "edu_pro",210 "edu_pro",
211 "promax",
212 "some_future_plan",
211 ];213 ];
212214
213 for (const planType of planTypes) {215 for (const planType of planTypes) {