openclaw/src/agents/models-config.providers.ope...

157 lines
4.7 KiB
TypeScript

import fs from "node:fs/promises";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { resolveOpenClawAgentDir } from "./agent-paths.js";
import {
installModelsConfigTestHooks,
MODELS_CONFIG_IMPLICIT_ENV_VARS,
resolveImplicitProvidersForTest,
unsetEnv,
withModelsTempHome,
withTempEnv,
} from "./models-config.e2e-harness.js";
import { ensureOpenClawModelsJson } from "./models-config.js";
import { readGeneratedModelsJson } from "./models-config.test-utils.js";
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",
);
}
describe("openai-codex implicit provider", () => {
it("injects an implicit provider when Codex OAuth exists", async () => {
await withModelsTempHome(async () => {
await withTempEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS, async () => {
unsetEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS);
const agentDir = resolveOpenClawAgentDir();
await writeCodexOauthProfile(agentDir);
const providers = await resolveImplicitProvidersForTest({ agentDir });
expect(providers?.["openai-codex"]).toMatchObject({
baseUrl: "https://chatgpt.com/backend-api",
api: "openai-codex-responses",
models: [],
});
expect(providers?.["openai-codex"]).not.toHaveProperty("apiKey");
});
});
});
it("replaces stale openai-codex baseUrl in generated models.json", async () => {
await withModelsTempHome(async () => {
await withTempEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS, async () => {
unsetEnv(MODELS_CONFIG_IMPLICIT_ENV_VARS);
const agentDir = resolveOpenClawAgentDir();
await writeCodexOauthProfile(agentDir);
await fs.writeFile(
path.join(agentDir, "models.json"),
JSON.stringify(
{
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,
},
],
},
},
},
null,
2,
),
"utf8",
);
await ensureOpenClawModelsJson({});
const parsed = await readGeneratedModelsJson<{
providers: Record<string, { baseUrl?: string; api?: string }>;
}>();
expect(parsed.providers["openai-codex"]).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);
const agentDir = resolveOpenClawAgentDir();
await fs.mkdir(agentDir, { recursive: true });
await fs.writeFile(
path.join(agentDir, "models.json"),
JSON.stringify(
{
providers: {
"openai-codex": {
baseUrl: "https://chatgpt.com/backend-api",
api: "openai-codex-responses",
models: [],
},
},
},
null,
2,
),
"utf8",
);
await ensureOpenClawModelsJson({
models: {
mode: "merge",
providers: {
"openai-codex": {
baseUrl: "",
api: "openai-codex-responses",
models: [],
},
},
},
});
const parsed = await readGeneratedModelsJson<{
providers: Record<string, { baseUrl?: string; api?: string }>;
}>();
expect(parsed.providers["openai-codex"]).toMatchObject({
baseUrl: "https://chatgpt.com/backend-api",
api: "openai-codex-responses",
});
});
});
});
});