diff --git a/src/agents/models-config.providers.openai-codex.test.ts b/src/agents/models-config.providers.openai-codex.test.ts index e6515a0f576..77591b76a06 100644 --- a/src/agents/models-config.providers.openai-codex.test.ts +++ b/src/agents/models-config.providers.openai-codex.test.ts @@ -1,142 +1,58 @@ -import fs from "node:fs/promises"; -import path from "node:path"; -import { describe, expect, it, vi } from "vitest"; -import { createConfigRuntimeEnv } from "../config/env-vars.js"; -import { resolveOpenClawAgentDir } from "./agent-paths.js"; -import { - installModelsConfigTestHooks, - MODELS_CONFIG_IMPLICIT_ENV_VARS, - unsetEnv, - withModelsTempHome, - withTempEnv, -} from "./models-config.e2e-harness.js"; -import { planOpenClawModelsJson } from "./models-config.plan.js"; +import { beforeAll, describe, expect, it } from "vitest"; -vi.mock("./cli-credentials.js", () => ({ - readCodexCliCredentialsCached: () => null, - readMiniMaxCliCredentialsCached: () => null, -})); - -installModelsConfigTestHooks(); - -async function writeCodexOauthProfile(agentDir: string) { - await fs.mkdir(agentDir, { recursive: true }); - await fs.writeFile( - path.join(agentDir, "auth-profiles.json"), - JSON.stringify( - { - version: 1, - profiles: { - "openai-codex:default": { - type: "oauth", - provider: "openai-codex", - access: "access-token", - refresh: "refresh-token", - expires: Date.now() + 60_000, - }, - }, - order: { - "openai-codex": ["openai-codex:default"], - }, - }, - null, - 2, - ), - "utf8", - ); -} +let buildOpenAICodexProviderPlugin: typeof import("../../extensions/openai/openai-codex-provider.js").buildOpenAICodexProviderPlugin; describe("openai-codex implicit provider", () => { - it("normalizes generated openai-codex rows back to the Codex transport when oauth exists", async () => { - await withModelsTempHome(async () => { - await withTempEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS, async () => { - unsetEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS); - process.env.OPENCLAW_TEST_ONLY_PROVIDER_PLUGIN_IDS = "openai-codex"; - const agentDir = resolveOpenClawAgentDir(); - await writeCodexOauthProfile(agentDir); - const existingParsed = { - providers: { - "openai-codex": { - baseUrl: "https://api.openai.com/v1", - api: "openai-responses", - models: [ - { - id: "gpt-5.4", - name: "GPT-5.4", - api: "openai-responses", - contextWindow: 1_000_000, - maxTokens: 100_000, - }, - ], - }, - }, - }; - const plan = await planOpenClawModelsJson({ - cfg: {}, - sourceConfigForSecrets: {}, - agentDir, - env: createConfigRuntimeEnv({}), - existingRaw: `${JSON.stringify(existingParsed, null, 2)}\n`, - existingParsed, - }); + beforeAll(async () => { + ({ buildOpenAICodexProviderPlugin } = + await import("../../extensions/openai/openai-codex-provider.js")); + }); - expect(plan.action).toBe("write"); - const parsed = JSON.parse((plan as { contents: string }).contents) as { - providers: Record; - }; - expect(parsed.providers["openai-codex"]).toMatchObject({ - baseUrl: "https://chatgpt.com/backend-api", - api: "openai-codex-responses", - }); - }); + it("normalizes generated openai-codex rows back to the Codex transport", () => { + const provider = buildOpenAICodexProviderPlugin(); + const normalized = provider.normalizeResolvedModel?.({ + provider: "openai-codex", + model: { + id: "gpt-5.4", + name: "GPT-5.4", + provider: "openai-codex", + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + reasoning: true, + input: ["text"], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 1_000_000, + maxTokens: 100_000, + }, + } as never); + + expect(normalized).toMatchObject({ + baseUrl: "https://chatgpt.com/backend-api", + api: "openai-codex-responses", }); }); - it("preserves an existing baseUrl for explicit openai-codex config without oauth synthesis", async () => { - await withModelsTempHome(async () => { - await withTempEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS, async () => { - unsetEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS); - process.env.OPENCLAW_TEST_ONLY_PROVIDER_PLUGIN_IDS = "openai-codex"; - const agentDir = resolveOpenClawAgentDir(); - const cfg = { - models: { - mode: "merge", - providers: { - "openai-codex": { - baseUrl: "", - api: "openai-codex-responses", - models: [], - }, - }, - }, - }; - const existingParsed = { - providers: { - "openai-codex": { - baseUrl: "https://chatgpt.com/backend-api", - api: "openai-codex-responses", - models: [], - }, - }, - }; - const plan = await planOpenClawModelsJson({ - cfg, - sourceConfigForSecrets: cfg, - agentDir, - env: createConfigRuntimeEnv(cfg), - existingRaw: `${JSON.stringify(existingParsed, null, 2)}\n`, - existingParsed, - }); + it("preserves an existing Codex baseUrl for explicit openai-codex config", () => { + const provider = buildOpenAICodexProviderPlugin(); + const normalized = provider.normalizeResolvedModel?.({ + provider: "openai-codex", + model: { + id: "gpt-5.4", + name: "GPT-5.4", + provider: "openai-codex", + api: "openai-codex-responses", + baseUrl: "https://chatgpt.com/backend-api", + reasoning: true, + input: ["text"], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 1_000_000, + maxTokens: 100_000, + }, + } as never); - expect(plan.action).toBe("write"); - const parsed = JSON.parse((plan as { contents: string }).contents) as { - providers: Record; - }; - expect(parsed.providers["openai-codex"]).toMatchObject({ - baseUrl: "https://chatgpt.com/backend-api", - api: "openai-codex-responses", - }); - }); + expect(normalized).toMatchObject({ + baseUrl: "https://chatgpt.com/backend-api", + api: "openai-codex-responses", }); }); });