import type { CliBackendConfig } from "openclaw/plugin-sdk/cli-backend"; export const CLAUDE_CLI_BACKEND_ID = "claude-cli"; export const CLAUDE_CLI_DEFAULT_MODEL_REF = `${CLAUDE_CLI_BACKEND_ID}/claude-sonnet-4-6`; export const CLAUDE_CLI_DEFAULT_ALLOWLIST_REFS = [ CLAUDE_CLI_DEFAULT_MODEL_REF, `${CLAUDE_CLI_BACKEND_ID}/claude-opus-4-6`, `${CLAUDE_CLI_BACKEND_ID}/claude-opus-4-5`, `${CLAUDE_CLI_BACKEND_ID}/claude-sonnet-4-5`, `${CLAUDE_CLI_BACKEND_ID}/claude-haiku-4-5`, ] as const; export const CLAUDE_CLI_MODEL_ALIASES: Record = { opus: "opus", "opus-4.6": "opus", "opus-4.5": "opus", "opus-4": "opus", "claude-opus-4-6": "opus", "claude-opus-4-5": "opus", "claude-opus-4": "opus", sonnet: "sonnet", "sonnet-4.6": "sonnet", "sonnet-4.5": "sonnet", "sonnet-4.1": "sonnet", "sonnet-4.0": "sonnet", "claude-sonnet-4-6": "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", }; export const CLAUDE_CLI_SESSION_ID_FIELDS = [ "session_id", "sessionId", "conversation_id", "conversationId", ] as const; export const CLAUDE_CLI_HOST_MANAGED_ENV = { CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST: "1", } as const; // Claude Code honors provider-routing, auth, and config-root env before // consulting its local login state, so inherited shell overrides must not // steer OpenClaw-managed Claude CLI runs toward a different provider, // endpoint, token source, plugin/config tree, or telemetry bootstrap mode. export const CLAUDE_CLI_CLEAR_ENV = [ "ANTHROPIC_API_KEY", "ANTHROPIC_API_KEY_OLD", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_BASE_URL", "ANTHROPIC_UNIX_SOCKET", "CLAUDE_CONFIG_DIR", "CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR", "CLAUDE_CODE_ENTRYPOINT", "CLAUDE_CODE_OAUTH_REFRESH_TOKEN", "CLAUDE_CODE_OAUTH_SCOPES", "CLAUDE_CODE_OAUTH_TOKEN", "CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR", "CLAUDE_CODE_PLUGIN_CACHE_DIR", "CLAUDE_CODE_PLUGIN_SEED_DIR", "CLAUDE_CODE_REMOTE", "CLAUDE_CODE_USE_COWORK_PLUGINS", "CLAUDE_CODE_USE_BEDROCK", "CLAUDE_CODE_USE_FOUNDRY", "CLAUDE_CODE_USE_VERTEX", "OTEL_EXPORTER_OTLP_ENDPOINT", "OTEL_EXPORTER_OTLP_HEADERS", "OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", "OTEL_EXPORTER_OTLP_LOGS_HEADERS", "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL", "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", "OTEL_EXPORTER_OTLP_METRICS_HEADERS", "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL", "OTEL_EXPORTER_OTLP_PROTOCOL", "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "OTEL_EXPORTER_OTLP_TRACES_HEADERS", "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL", "OTEL_LOGS_EXPORTER", "OTEL_METRICS_EXPORTER", "OTEL_SDK_DISABLED", "OTEL_TRACES_EXPORTER", ] as const; const CLAUDE_LEGACY_SKIP_PERMISSIONS_ARG = "--dangerously-skip-permissions"; const CLAUDE_PERMISSION_MODE_ARG = "--permission-mode"; const CLAUDE_BYPASS_PERMISSIONS_MODE = "bypassPermissions"; const CLAUDE_SETTING_SOURCES_ARG = "--setting-sources"; const CLAUDE_SAFE_SETTING_SOURCES = "user"; export function isClaudeCliProvider(providerId: string): boolean { return providerId.trim().toLowerCase() === CLAUDE_CLI_BACKEND_ID; } export function normalizeClaudePermissionArgs(args?: string[]): string[] | undefined { if (!args) { return args; } const normalized: string[] = []; let hasPermissionMode = false; for (let i = 0; i < args.length; i += 1) { const arg = args[i]; if (arg === CLAUDE_LEGACY_SKIP_PERMISSIONS_ARG) { continue; } if (arg === CLAUDE_PERMISSION_MODE_ARG) { const maybeValue = args[i + 1]; if ( typeof maybeValue === "string" && maybeValue.trim().length > 0 && !maybeValue.startsWith("-") ) { hasPermissionMode = true; normalized.push(arg); normalized.push(maybeValue); i += 1; } continue; } if (arg.startsWith(`${CLAUDE_PERMISSION_MODE_ARG}=`)) { hasPermissionMode = true; } normalized.push(arg); } if (!hasPermissionMode) { normalized.push(CLAUDE_PERMISSION_MODE_ARG, CLAUDE_BYPASS_PERMISSIONS_MODE); } return normalized; } export function normalizeClaudeSettingSourcesArgs(args?: string[]): string[] | undefined { if (!args) { return args; } const normalized: string[] = []; let hasSettingSources = false; for (let i = 0; i < args.length; i += 1) { const arg = args[i]; if (arg === CLAUDE_SETTING_SOURCES_ARG) { const maybeValue = args[i + 1]; if ( typeof maybeValue === "string" && maybeValue.trim().length > 0 && !maybeValue.startsWith("-") ) { hasSettingSources = true; normalized.push(arg, CLAUDE_SAFE_SETTING_SOURCES); i += 1; } continue; } if (arg.startsWith(`${CLAUDE_SETTING_SOURCES_ARG}=`)) { hasSettingSources = true; normalized.push(`${CLAUDE_SETTING_SOURCES_ARG}=${CLAUDE_SAFE_SETTING_SOURCES}`); continue; } normalized.push(arg); } if (!hasSettingSources) { normalized.push(CLAUDE_SETTING_SOURCES_ARG, CLAUDE_SAFE_SETTING_SOURCES); } return normalized; } export function normalizeClaudeBackendConfig(config: CliBackendConfig): CliBackendConfig { return { ...config, args: normalizeClaudePermissionArgs(normalizeClaudeSettingSourcesArgs(config.args)), resumeArgs: normalizeClaudePermissionArgs(normalizeClaudeSettingSourcesArgs(config.resumeArgs)), }; }