diff --git a/extensions/codex/harness.test.ts b/extensions/codex/harness.test.ts index 2dbb0737886d..c387732d9ebf 100644 --- a/extensions/codex/harness.test.ts +++ b/extensions/codex/harness.test.ts @@ -248,6 +248,51 @@ describe("Codex agent harness supports()", () => { expect(!result.supported ? result.reason : undefined).toContain("not declared"); }); + it("lets explicitly selected Codex discover unlisted models with its own account", () => { + expect( + harness.supports({ + provider: "openai", + modelId: "gpt-future", + requestedRuntime: "codex", + modelProvider: { + requestTransportOverrides: "none", + preparedAuth: { source: "harness" }, + }, + }), + ).toEqual({ supported: true, priority: 100 }); + }); + + it.each([ + { + label: "automatic runtime selection", + requestedRuntime: "auto" as const, + modelProvider: { preparedAuth: { source: "harness" as const } }, + }, + { + label: "an authored endpoint", + requestedRuntime: "codex" as const, + modelProvider: { + baseUrl: "https://relay.example.test/v1", + preparedAuth: { source: "harness" as const }, + }, + }, + { + label: "an owner-selected credential", + requestedRuntime: "codex" as const, + modelProvider: { preparedAuth: { source: "profile" as const, mode: "api-key" } }, + }, + ])("does not infer native model access for $label", ({ requestedRuntime, modelProvider }) => { + const result = harness.supports({ + provider: "openai", + modelId: "gpt-future", + requestedRuntime, + modelProvider: { requestTransportOverrides: "none", ...modelProvider }, + }); + + expect(result.supported).toBe(false); + expect(!result.supported ? result.reason : undefined).toContain("not declared"); + }); + it.each([ { label: "forwarded OAuth subscription", diff --git a/extensions/codex/harness.ts b/extensions/codex/harness.ts index b1ccb94fe5bc..8fdb1698da98 100644 --- a/extensions/codex/harness.ts +++ b/extensions/codex/harness.ts @@ -204,6 +204,19 @@ export function createCodexAppServerAgentHarness( } const preparedAuth = ctx.modelProvider?.preparedAuth; const runtimePolicy = ctx.modelProvider?.runtimePolicy; + // Codex owns discovery and auth for new first-party models. Only trust that + // native account when no authored transport or host credential is involved. + const nativeAccountOwnsUnobservedModel = + provider === "openai" && + ctx.requestedRuntime === "codex" && + Boolean(ctx.modelId?.trim()) && + preparedAuth?.source === "harness" && + preparedAuth.mode === undefined && + preparedAuth.requirement === undefined && + ctx.modelProvider?.api === undefined && + ctx.modelProvider?.baseUrl === undefined && + ctx.modelProvider?.azureApiVersion === undefined && + ctx.modelProvider?.request === undefined; if (runtimePolicy) { const compatible = runtimePolicy.compatibleIds.some( (id) => id.trim().toLowerCase() === normalizedHarnessRuntimeId, @@ -214,7 +227,7 @@ export function createCodexAppServerAgentHarness( reason: "Codex cannot reproduce the prepared provider route", }; } - } else if (ctx.modelProvider && provider !== "codex") { + } else if (ctx.modelProvider && provider !== "codex" && !nativeAccountOwnsUnobservedModel) { return { supported: false, reason: "provider route compatibility with Codex is not declared",