mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:00:42 +00:00
test: route cli backend live refs through runtime
This commit is contained in:
@@ -562,6 +562,61 @@ describe("CLI attempt execution", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("routes canonical OpenAI models through the configured Codex CLI runtime", async () => {
|
||||
const sessionKey = "agent:main:direct:canonical-codex-cli";
|
||||
const sessionEntry: SessionEntry = {
|
||||
sessionId: "openclaw-session-canonical-codex-cli",
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
const sessionStore: Record<string, SessionEntry> = { [sessionKey]: sessionEntry };
|
||||
await fs.writeFile(storePath, JSON.stringify(sessionStore, null, 2), "utf-8");
|
||||
runCliAgentMock.mockResolvedValueOnce(makeCliResult("canonical codex cli"));
|
||||
|
||||
await runAgentAttempt({
|
||||
providerOverride: "openai",
|
||||
originalProvider: "openai",
|
||||
modelOverride: "gpt-5.4",
|
||||
cfg: {
|
||||
agents: {
|
||||
defaults: {
|
||||
agentRuntime: { id: "codex-cli", fallback: "none" },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
sessionEntry,
|
||||
sessionId: sessionEntry.sessionId,
|
||||
sessionKey,
|
||||
sessionAgentId: "main",
|
||||
sessionFile: path.join(tmpDir, "session.jsonl"),
|
||||
workspaceDir: tmpDir,
|
||||
body: "route this",
|
||||
isFallbackRetry: false,
|
||||
resolvedThinkLevel: "medium",
|
||||
timeoutMs: 1_000,
|
||||
runId: "run-canonical-codex-cli",
|
||||
opts: { senderIsOwner: false } as Parameters<typeof runAgentAttempt>[0]["opts"],
|
||||
runContext: {} as Parameters<typeof runAgentAttempt>[0]["runContext"],
|
||||
spawnedBy: undefined,
|
||||
messageChannel: "telegram",
|
||||
skillsSnapshot: undefined,
|
||||
resolvedVerboseLevel: undefined,
|
||||
agentDir: tmpDir,
|
||||
onAgentEvent: vi.fn(),
|
||||
authProfileProvider: "openai",
|
||||
sessionStore,
|
||||
storePath,
|
||||
sessionHasHistory: false,
|
||||
});
|
||||
|
||||
expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled();
|
||||
expect(runCliAgentMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
provider: "codex-cli",
|
||||
model: "gpt-5.4",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps one-shot model runs on the raw embedded provider path", async () => {
|
||||
const sessionKey = "agent:main:direct:model-run-raw";
|
||||
const sessionEntry: SessionEntry = {
|
||||
|
||||
@@ -115,6 +115,38 @@ describe("gateway cli backend live helpers", () => {
|
||||
expect(shouldRunCliModelSwitchProbe("codex-cli", "codex-cli/gpt-5.5")).toBe(false);
|
||||
});
|
||||
|
||||
it("configures legacy CLI model refs as canonical provider models plus CLI runtime", async () => {
|
||||
const { resolveCliBackendLiveModelSelection } =
|
||||
await import("./gateway-cli-backend.live-helpers.js");
|
||||
|
||||
expect(
|
||||
resolveCliBackendLiveModelSelection({
|
||||
rawModel: "codex-cli/gpt-5.4",
|
||||
defaultProvider: "claude-cli",
|
||||
}),
|
||||
).toEqual({
|
||||
providerId: "codex-cli",
|
||||
cliModelKey: "codex-cli/gpt-5.4",
|
||||
configModelKey: "openai/gpt-5.4",
|
||||
configModelSwitchTarget: undefined,
|
||||
agentRuntime: { id: "codex-cli", fallback: "none" },
|
||||
});
|
||||
|
||||
expect(
|
||||
resolveCliBackendLiveModelSelection({
|
||||
rawModel: "claude-cli/claude-sonnet-4-6",
|
||||
defaultProvider: "claude-cli",
|
||||
modelSwitchTarget: "claude-cli/claude-opus-4-6",
|
||||
}),
|
||||
).toEqual({
|
||||
providerId: "claude-cli",
|
||||
cliModelKey: "claude-cli/claude-sonnet-4-6",
|
||||
configModelKey: "anthropic/claude-sonnet-4-6",
|
||||
configModelSwitchTarget: "anthropic/claude-opus-4-6",
|
||||
agentRuntime: { id: "claude-cli", fallback: "none" },
|
||||
});
|
||||
});
|
||||
|
||||
it("lets env disable the model switch probe", async () => {
|
||||
const { shouldRunCliModelSwitchProbe } = await import("./gateway-cli-backend.live-helpers.js");
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import { randomUUID } from "node:crypto";
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { resolveCliBackendLiveTest } from "../agents/cli-backends.js";
|
||||
import { migrateLegacyRuntimeModelRef } from "../agents/model-runtime-aliases.js";
|
||||
import { parseModelRef } from "../agents/model-selection.js";
|
||||
import {
|
||||
loadOrCreateDeviceIdentity,
|
||||
publicKeyRawBase64UrlFromPem,
|
||||
@@ -33,6 +35,14 @@ export type SystemPromptReport = {
|
||||
injectedWorkspaceFiles?: Array<{ name?: string }>;
|
||||
};
|
||||
|
||||
export type CliBackendLiveModelSelection = {
|
||||
providerId: string;
|
||||
cliModelKey: string;
|
||||
configModelKey: string;
|
||||
configModelSwitchTarget: string | undefined;
|
||||
agentRuntime: { id: string; fallback: "pi" | "none" };
|
||||
};
|
||||
|
||||
export type CliBackendLiveEnvSnapshot = {
|
||||
configPath?: string;
|
||||
stateDir?: string;
|
||||
@@ -49,6 +59,41 @@ export type CliBackendLiveEnvSnapshot = {
|
||||
anthropicApiKeyOld?: string;
|
||||
};
|
||||
|
||||
export function resolveCliBackendLiveModelSelection(params: {
|
||||
rawModel: string;
|
||||
defaultProvider: string;
|
||||
modelSwitchTarget?: string;
|
||||
}): CliBackendLiveModelSelection {
|
||||
const parsed = parseModelRef(params.rawModel, params.defaultProvider);
|
||||
if (!parsed) {
|
||||
throw new Error(
|
||||
`OPENCLAW_LIVE_CLI_BACKEND_MODEL must resolve to a CLI backend model. Got: ${params.rawModel}`,
|
||||
);
|
||||
}
|
||||
|
||||
const migrated = migrateLegacyRuntimeModelRef(params.rawModel);
|
||||
if (migrated?.cli) {
|
||||
return {
|
||||
providerId: migrated.runtime,
|
||||
cliModelKey: `${migrated.runtime}/${migrated.model}`,
|
||||
configModelKey: migrated.ref,
|
||||
configModelSwitchTarget: params.modelSwitchTarget
|
||||
? (migrateLegacyRuntimeModelRef(params.modelSwitchTarget)?.ref ?? params.modelSwitchTarget)
|
||||
: undefined,
|
||||
agentRuntime: { id: migrated.runtime, fallback: "none" },
|
||||
};
|
||||
}
|
||||
|
||||
const modelKey = `${parsed.provider}/${parsed.model}`;
|
||||
return {
|
||||
providerId: parsed.provider,
|
||||
cliModelKey: modelKey,
|
||||
configModelKey: modelKey,
|
||||
configModelSwitchTarget: params.modelSwitchTarget,
|
||||
agentRuntime: { id: "pi", fallback: "pi" },
|
||||
};
|
||||
}
|
||||
|
||||
export function parseJsonStringArray(name: string, raw?: string): string[] | undefined {
|
||||
const trimmed = raw?.trim();
|
||||
if (!trimmed) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
parseImageMode,
|
||||
resolveCliModelSwitchProbeTarget,
|
||||
resolveCliBackendLiveArgs,
|
||||
resolveCliBackendLiveModelSelection,
|
||||
parseJsonStringArray,
|
||||
restoreCliBackendLiveEnv,
|
||||
shouldRunCliImageProbe,
|
||||
@@ -204,25 +205,34 @@ describeLive("gateway live (cli backend)", () => {
|
||||
logCliBackendLiveStep("env-ready", { port });
|
||||
|
||||
const rawModel = process.env.OPENCLAW_LIVE_CLI_BACKEND_MODEL ?? DEFAULT_MODEL;
|
||||
const parsed = parseModelRef(rawModel, "claude-cli");
|
||||
if (!parsed) {
|
||||
throw new Error(
|
||||
`OPENCLAW_LIVE_CLI_BACKEND_MODEL must resolve to a CLI backend model. Got: ${rawModel}`,
|
||||
);
|
||||
}
|
||||
|
||||
const providerId = parsed.provider;
|
||||
const modelKey = `${providerId}/${parsed.model}`;
|
||||
const initialParsed = parseModelRef(rawModel, "claude-cli");
|
||||
const initialProviderId = initialParsed?.provider ?? "";
|
||||
const initialModelKey = initialParsed
|
||||
? `${initialProviderId}/${initialParsed.model}`
|
||||
: rawModel;
|
||||
const initialModelSwitchTarget = resolveCliModelSwitchProbeTarget(
|
||||
initialProviderId,
|
||||
initialModelKey,
|
||||
);
|
||||
const modelSelection = resolveCliBackendLiveModelSelection({
|
||||
rawModel,
|
||||
defaultProvider: "claude-cli",
|
||||
modelSwitchTarget: initialModelSwitchTarget,
|
||||
});
|
||||
const providerId = modelSelection.providerId;
|
||||
const modelKey = modelSelection.cliModelKey;
|
||||
const configModelKey = modelSelection.configModelKey;
|
||||
const backendResolved = resolveCliBackendConfig(providerId);
|
||||
const enableCliImageProbe = shouldRunCliImageProbe(providerId);
|
||||
const enableCliMcpProbe = shouldRunCliMcpProbe(providerId);
|
||||
const enableCliModelSwitchProbe = shouldRunCliModelSwitchProbe(providerId, modelKey);
|
||||
const modelSwitchTarget = enableCliModelSwitchProbe
|
||||
? resolveCliModelSwitchProbeTarget(providerId, modelKey)
|
||||
? modelSelection.configModelSwitchTarget
|
||||
: undefined;
|
||||
logCliBackendLiveStep("model-selected", {
|
||||
providerId,
|
||||
modelKey,
|
||||
configModelKey,
|
||||
enableCliImageProbe,
|
||||
enableCliMcpProbe,
|
||||
enableCliModelSwitchProbe,
|
||||
@@ -328,7 +338,7 @@ describeLive("gateway live (cli backend)", () => {
|
||||
providers: {
|
||||
...cfg.models?.providers,
|
||||
openai: {
|
||||
...openAiProviderConfigForCodexCli(modelKey),
|
||||
...openAiProviderConfigForCodexCli(configModelKey),
|
||||
...cfg.models?.providers?.openai,
|
||||
},
|
||||
},
|
||||
@@ -347,12 +357,12 @@ describeLive("gateway live (cli backend)", () => {
|
||||
defaults: {
|
||||
...cfg.agents?.defaults,
|
||||
...(bootstrapWorkspace ? { workspace: bootstrapWorkspace.workspaceRootDir } : {}),
|
||||
model: { primary: modelKey },
|
||||
model: { primary: configModelKey },
|
||||
models: {
|
||||
[modelKey]: {},
|
||||
[configModelKey]: {},
|
||||
...(modelSwitchTarget ? { [modelSwitchTarget]: {} } : {}),
|
||||
},
|
||||
agentRuntime: { id: "pi", fallback: "pi" },
|
||||
agentRuntime: modelSelection.agentRuntime,
|
||||
cliBackends: {
|
||||
...existingBackends,
|
||||
[providerId]: {
|
||||
|
||||
Reference in New Issue
Block a user