feat: add CLI backend fallback
This commit is contained in:
110
src/agents/cli-backends.ts
Normal file
110
src/agents/cli-backends.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import type { CliBackendConfig } from "../config/types.js";
|
||||
import { normalizeProviderId } from "./model-selection.js";
|
||||
|
||||
export type ResolvedCliBackend = {
|
||||
id: string;
|
||||
config: CliBackendConfig;
|
||||
};
|
||||
|
||||
const CLAUDE_MODEL_ALIASES: Record<string, string> = {
|
||||
opus: "opus",
|
||||
"opus-4.5": "opus",
|
||||
"opus-4": "opus",
|
||||
"claude-opus-4-5": "opus",
|
||||
"claude-opus-4": "opus",
|
||||
sonnet: "sonnet",
|
||||
"sonnet-4.5": "sonnet",
|
||||
"sonnet-4.1": "sonnet",
|
||||
"sonnet-4.0": "sonnet",
|
||||
"claude-sonnet-4-5": "sonnet",
|
||||
"claude-sonnet-4-1": "sonnet",
|
||||
"claude-sonnet-4-0": "sonnet",
|
||||
haiku: "haiku",
|
||||
"haiku-3.5": "haiku",
|
||||
"claude-haiku-3-5": "haiku",
|
||||
};
|
||||
|
||||
const DEFAULT_CLAUDE_BACKEND: CliBackendConfig = {
|
||||
command: "claude",
|
||||
args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"],
|
||||
output: "json",
|
||||
input: "arg",
|
||||
modelArg: "--model",
|
||||
modelAliases: CLAUDE_MODEL_ALIASES,
|
||||
sessionArg: "--session-id",
|
||||
sessionMode: "always",
|
||||
sessionIdFields: [
|
||||
"session_id",
|
||||
"sessionId",
|
||||
"conversation_id",
|
||||
"conversationId",
|
||||
],
|
||||
systemPromptArg: "--append-system-prompt",
|
||||
systemPromptMode: "append",
|
||||
systemPromptWhen: "first",
|
||||
clearEnv: ["ANTHROPIC_API_KEY"],
|
||||
serialize: true,
|
||||
};
|
||||
|
||||
function normalizeBackendKey(key: string): string {
|
||||
return normalizeProviderId(key);
|
||||
}
|
||||
|
||||
function pickBackendConfig(
|
||||
config: Record<string, CliBackendConfig>,
|
||||
normalizedId: string,
|
||||
): CliBackendConfig | undefined {
|
||||
for (const [key, entry] of Object.entries(config)) {
|
||||
if (normalizeBackendKey(key) === normalizedId) return entry;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function mergeBackendConfig(
|
||||
base: CliBackendConfig,
|
||||
override?: CliBackendConfig,
|
||||
): CliBackendConfig {
|
||||
if (!override) return { ...base };
|
||||
return {
|
||||
...base,
|
||||
...override,
|
||||
args: override.args ?? base.args,
|
||||
env: { ...base.env, ...override.env },
|
||||
modelAliases: { ...base.modelAliases, ...override.modelAliases },
|
||||
clearEnv: Array.from(
|
||||
new Set([...(base.clearEnv ?? []), ...(override.clearEnv ?? [])]),
|
||||
),
|
||||
sessionIdFields: override.sessionIdFields ?? base.sessionIdFields,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveCliBackendIds(cfg?: ClawdbotConfig): Set<string> {
|
||||
const ids = new Set<string>([normalizeBackendKey("claude-cli")]);
|
||||
const configured = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||
for (const key of Object.keys(configured)) {
|
||||
ids.add(normalizeBackendKey(key));
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
export function resolveCliBackendConfig(
|
||||
provider: string,
|
||||
cfg?: ClawdbotConfig,
|
||||
): ResolvedCliBackend | null {
|
||||
const normalized = normalizeBackendKey(provider);
|
||||
const configured = cfg?.agents?.defaults?.cliBackends ?? {};
|
||||
const override = pickBackendConfig(configured, normalized);
|
||||
|
||||
if (normalized === "claude-cli") {
|
||||
const merged = mergeBackendConfig(DEFAULT_CLAUDE_BACKEND, override);
|
||||
const command = merged.command?.trim();
|
||||
if (!command) return null;
|
||||
return { id: normalized, config: { ...merged, command } };
|
||||
}
|
||||
|
||||
if (!override) return null;
|
||||
const command = override.command?.trim();
|
||||
if (!command) return null;
|
||||
return { id: normalized, config: { ...override, command } };
|
||||
}
|
||||
Reference in New Issue
Block a user