From 4f50092530ef69367b40d2adbbad293e13dfcd4b Mon Sep 17 00:00:00 2001 From: hbw00111 <196409728+hbw00111@users.noreply.github.com> Date: Mon, 14 Sep 2026 19:14:06 +0800 Subject: [PATCH] fix(core): isolate Codex OAuth input-limit metadata Avoid inheriting public OpenAI API input limits for OAuth model metadata, including refreshed and fallback entries. Preserve explicit limit validation. Generated-by: OpenAI Codex --- .../core/src/__tests__/model-metadata.test.ts | 38 ++++++++++ packages/core/src/model-metadata.ts | 22 ++++-- .../context-budget-model-facts.test.ts | 70 +++++++++++++++++++ 3 files changed, 124 insertions(+), 6 deletions(-) diff --git a/packages/core/src/__tests__/model-metadata.test.ts b/packages/core/src/__tests__/model-metadata.test.ts index 8609efcfb8..3d0d1f0f06 100644 --- a/packages/core/src/__tests__/model-metadata.test.ts +++ b/packages/core/src/__tests__/model-metadata.test.ts @@ -20,6 +20,7 @@ import { strict as assert } from 'node:assert'; import { describe, it } from 'node:test'; import { + installRefreshedModelMetadata, lookupModelMetadata, openAiAdapterApiProtocol, providerReportsCompleteModelCatalog, @@ -36,6 +37,43 @@ describe('provider model-catalog completeness', () => { }); }); +describe('OpenAI Codex OAuth metadata', () => { + it('does not inherit public API input limits across shipped, refreshed, and fallback metadata', () => { + assert.equal(lookupModelMetadata('openai', 'gpt-5.6-sol').inputLimit, 922_000); + assert.equal(lookupModelMetadata('openai-codex', 'gpt-5.6-sol').inputLimit, undefined); + assert.equal(lookupModelMetadata('openai-codex', 'gpt-5.6-terra').inputLimit, undefined); + + installRefreshedModelMetadata({ + openai: { + 'gpt-5.6-sol': { displayName: 'Refreshed Sol', inputLimit: 123_456 }, + 'gpt-5.6-luna': { + displayName: 'Refreshed Luna', + inputLimit: 234_567, + capabilities: { vision: true }, + }, + }, + }); + try { + assert.equal(lookupModelMetadata('openai', 'gpt-5.6-sol').inputLimit, 123_456); + assert.equal(lookupModelMetadata('openai-codex', 'gpt-5.6-sol').inputLimit, undefined); + const refreshedLuna = lookupModelMetadata('openai', 'gpt-5.6-luna'); + assert.equal(refreshedLuna.inputLimit, 234_567); + + const oauthLuna = lookupModelMetadata('openai-codex', 'gpt-5.6-luna'); + assert.equal(oauthLuna.displayName, 'Refreshed Luna'); + assert.equal(oauthLuna.capabilities?.vision, true); + assert.equal(oauthLuna.inputLimit, undefined); + + const fallback = lookupModelMetadata('openai-codex', 'gpt-5.5'); + assert.equal(fallback.displayName, 'GPT-5.5'); + assert.equal(fallback.contextWindow, 272_000); + assert.equal(fallback.inputLimit, undefined); + } finally { + installRefreshedModelMetadata(undefined); + } + }); +}); + describe('model-metadata vision capability', () => { it('treats a Claude newer than the generated snapshot as able to read images', () => { assert.deepEqual(lookupModelMetadata('anthropic', 'claude-opus-6'), {}); diff --git a/packages/core/src/model-metadata.ts b/packages/core/src/model-metadata.ts index 4669523e59..bc9af6a159 100644 --- a/packages/core/src/model-metadata.ts +++ b/packages/core/src/model-metadata.ts @@ -105,6 +105,8 @@ export function lookupModelMetadata(providerType: ProviderType, modelId: string) const id = modelId.trim(); const metadataProviderType = generatedMetadataProviderType(providerType); const generated = activeMetadata()[metadataProviderType]?.[id]; + const providerMetadata = + providerType === 'openai-codex' ? withoutInputLimit(generated) : generated; const statics = staticModelMetadata(); const override = statics[providerType]?.[id] ?? @@ -113,13 +115,13 @@ export function lookupModelMetadata(providerType: ProviderType, modelId: string) : providerType === 'opencode-free' ? statics.opencode?.[id] : undefined); - if (!generated) return override ?? {}; - if (!override) return generated; + if (!providerMetadata) return override ?? {}; + if (!override) return providerMetadata; return { - ...generated, + ...providerMetadata, ...override, - capabilities: { ...generated.capabilities, ...override.capabilities }, - modalities: override.modalities ?? generated.modalities, + capabilities: { ...providerMetadata.capabilities, ...override.capabilities }, + modalities: override.modalities ?? providerMetadata.modalities, }; } @@ -251,7 +253,15 @@ const GOOGLE_MODEL_OVERRIDES: Record = { // catalog says. Base facts come from the active table, falling back to the // shipped snapshot so a model upstream stops listing keeps a display name. function openAiOAuthBase(active: ModelsDevMetadata, modelId: string): ModelMetadata { - return active.openai?.[modelId] ?? GENERATED_MODELS_DEV_METADATA.openai[modelId] ?? {}; + const metadata = active.openai?.[modelId] ?? GENERATED_MODELS_DEV_METADATA.openai[modelId]; + return withoutInputLimit(metadata) ?? {}; +} + +/** OAuth model metadata must not inherit public OpenAI API input limits. */ +function withoutInputLimit(metadata: ModelMetadata | undefined): ModelMetadata | undefined { + if (!metadata) return undefined; + const { inputLimit: _inputLimit, ...withoutLimit } = metadata; + return withoutLimit; } function openAiOAuthModelMetadata(active: ModelsDevMetadata): Record { diff --git a/packages/runtime/src/__tests__/context-budget-model-facts.test.ts b/packages/runtime/src/__tests__/context-budget-model-facts.test.ts index adedc41dc2..1bb00d8759 100644 --- a/packages/runtime/src/__tests__/context-budget-model-facts.test.ts +++ b/packages/runtime/src/__tests__/context-budget-model-facts.test.ts @@ -120,3 +120,73 @@ test('a reported model context window is metadata, not a Maka declaration', () = assert.equal(resolveSelectedModelContextWindow(connection, undefined), 100_000); assert.equal(resolveDeclaredContextWindow(connection, undefined), undefined); }); + +test('Codex OAuth pinned windows do not inherit public API input limits', () => { + for (const [modelId, window] of [ + ['gpt-5.5', 272_000], + ['gpt-5.4', 272_000], + ['gpt-5.6-sol', 372_000], + ['gpt-5.4-mini', 272_000], + ] as const) { + const connection = { + slug: 'codex', + providerType: 'openai-codex' as const, + defaultModel: modelId, + }; + assert.equal(resolveSelectedModelContextWindow(connection, undefined), window, modelId); + assert.equal(resolveDeclaredContextWindow(connection, undefined), undefined); + } +}); + +test('Codex OAuth discovered windows remain usable after model discovery', () => { + for (const id of ['gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.5']) { + const connection = { + slug: 'codex', + providerType: 'openai-codex' as const, + defaultModel: id, + models: [{ id, contextWindow: 272_000 }], + }; + assert.equal(resolveSelectedModelContextWindow(connection, undefined), 272_000, id); + assert.equal(resolveDeclaredContextWindow(connection, undefined), undefined); + assert.equal( + resolveSelectedModelContextWindow( + { ...connection, modelOverrides: { [id]: { inputLimit: 262_144 } } }, + undefined, + ), + 262_144, + ); + } +}); + +test('Codex OAuth keeps explicit input limits and rejects their conflicts', () => { + const connection = { + slug: 'codex', + providerType: 'openai-codex' as const, + defaultModel: 'gpt-5.5', + models: [{ id: 'gpt-5.5', contextWindow: 272_000, inputLimit: 200_000 }], + }; + assert.equal(resolveSelectedModelContextWindow(connection, undefined), 200_000); + assert.equal( + resolveSelectedModelContextWindow( + { ...connection, modelOverrides: { 'gpt-5.5': { inputLimit: 262_144 } } }, + undefined, + ), + 262_144, + ); + assert.throws( + () => + resolveSelectedModelContextWindow( + { ...connection, modelOverrides: { 'gpt-5.5': { inputLimit: 300_000 } } }, + undefined, + ), + /input limit exceeds/i, + ); + assert.throws( + () => + resolveSelectedModelContextWindow( + { ...connection, models: [{ id: 'gpt-5.5', contextWindow: 272_000, inputLimit: 300_000 }] }, + undefined, + ), + /input limit exceeds/i, + ); +});