Compare commits

...

1 Commits

Author SHA1 Message Date
Vincent Koc
02975bf6c2 fix: start codex for selectable openai models 2026-05-14 08:39:25 +08:00
4 changed files with 136 additions and 0 deletions

View File

@@ -3,6 +3,71 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
import { collectConfiguredAgentHarnessRuntimes } from "./harness-runtimes.js";
describe("collectConfiguredAgentHarnessRuntimes", () => {
it("includes Codex for selectable OpenAI default models when primary is not OpenAI", () => {
const config = {
agents: {
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-6",
},
models: {
"anthropic/claude-sonnet-4-6": {},
"openai/gpt-5.5": {},
},
},
},
} as unknown as OpenClawConfig;
expect(collectConfiguredAgentHarnessRuntimes(config, {}, { includeEnvRuntime: false })).toEqual(
["codex"],
);
});
it("does not include Codex for selectable OpenAI models pinned to PI", () => {
const config = {
agents: {
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-6",
},
models: {
"openai/gpt-5.5": {
agentRuntime: { id: "pi" },
},
},
},
},
} as unknown as OpenClawConfig;
expect(collectConfiguredAgentHarnessRuntimes(config, {}, { includeEnvRuntime: false })).toEqual(
[],
);
});
it("includes Codex for selectable per-agent OpenAI models", () => {
const config = {
agents: {
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-6",
},
},
list: [
{
id: "ops",
models: {
"openai/gpt-5.5": {},
},
},
],
},
} as unknown as OpenClawConfig;
expect(collectConfiguredAgentHarnessRuntimes(config, {}, { includeEnvRuntime: false })).toEqual(
["codex"],
);
});
it("ignores malformed agents.list while scanning best-effort config", () => {
const config = {
agents: {

View File

@@ -72,6 +72,13 @@ function hasOpenAIModelRef(config: OpenClawConfig, value: unknown, agentId?: str
});
}
function hasOpenAIModelMapRef(config: OpenClawConfig, models: unknown, agentId?: string): boolean {
if (!isRecord(models)) {
return false;
}
return Object.keys(models).some((ref) => hasOpenAIModelRef(config, ref, agentId));
}
function pushConfiguredModelRuntimeIds(config: OpenClawConfig, runtimes: Set<string>): void {
for (const providerConfig of Object.values(config.models?.providers ?? {})) {
const providerRuntime = normalizeRuntimeId(providerConfig?.agentRuntime?.id);
@@ -141,6 +148,11 @@ export function collectConfiguredAgentHarnessRuntimes(
runtimes.add("codex");
}
};
const pushCodexForOpenAIModelMap = (models: unknown, agentId?: string) => {
if (hasOpenAIModelMapRef(config, models, agentId)) {
runtimes.add("codex");
}
};
if (includeEnvRuntime) {
const envRuntime = normalizeRuntimeId(env.OPENCLAW_AGENT_RUNTIME);
@@ -154,6 +166,7 @@ export function collectConfiguredAgentHarnessRuntimes(
}
const defaultsModel = config.agents?.defaults?.model;
pushCodexForOpenAIModel(defaultsModel);
pushCodexForOpenAIModelMap(config.agents?.defaults?.models);
if (Array.isArray(config.agents?.list)) {
for (const agent of config.agents.list) {
if (!isRecord(agent)) {
@@ -163,6 +176,7 @@ export function collectConfiguredAgentHarnessRuntimes(
agent.model ?? defaultsModel,
typeof agent.id === "string" ? agent.id : undefined,
);
pushCodexForOpenAIModelMap(agent.models, typeof agent.id === "string" ? agent.id : undefined);
}
}

View File

@@ -675,6 +675,41 @@ describe("applyPluginAutoEnable core", () => {
]);
});
it("auto-enables Codex when OpenAI is configured as a selectable model", () => {
const result = applyPluginAutoEnable({
config: {
agents: {
defaults: {
model: {
primary: "anthropic/claude-sonnet-4-6",
},
models: {
"anthropic/claude-sonnet-4-6": {},
"openai/gpt-5.5": {},
},
},
},
},
env,
manifestRegistry: makeRegistry([
{ id: "openai", channels: [], providers: ["openai", "openai-codex"] },
{
id: "codex",
channels: [],
providers: ["codex"],
activation: { onAgentHarnesses: ["codex"] },
},
]),
});
expect(result.config.plugins?.entries?.openai?.enabled).toBe(true);
expect(result.config.plugins?.entries?.codex?.enabled).toBe(true);
expect(result.changes).toEqual([
"openai/gpt-5.5 model configured, enabled automatically.",
"codex agent runtime configured, enabled automatically.",
]);
});
it("auto-enables an opt-in plugin when a provider runtime is configured", () => {
const result = applyPluginAutoEnable({
config: {

View File

@@ -1445,6 +1445,28 @@ describe("resolveGatewayStartupPluginIds", () => {
});
});
it("includes Codex when OpenAI is configured as a selectable model", () => {
expectStartupPluginIdsCase({
config: {
agents: {
defaults: {
model: { primary: "anthropic/claude-sonnet-4-6" },
models: {
"anthropic/claude-sonnet-4-6": {},
"openai/gpt-5.5": {},
},
},
},
plugins: {
entries: {
codex: { enabled: true },
},
},
} as OpenClawConfig,
expected: ["demo-channel", "browser", "codex", "memory-core"],
});
});
it("does not include Codex when an OpenAI model is manually pinned to PI", () => {
expectStartupPluginIdsCase({
config: {