/** * External CLI auth discovery scope extraction from config. * Collects provider/profile ids from configured models, runtimes, auth order, * and agent defaults to limit CLI credential probing. */ import { normalizeProviderId } from "@openclaw/model-catalog-core/provider-id"; import { resolveAgentModelFallbackValues, resolveAgentModelPrimaryValue, } from "../../config/model-input.js"; import type { AgentModelConfig } from "../../config/types.agents-shared.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { listAgentEntries } from "../agent-scope-config.js"; /** Provider/profile ids that may need external CLI auth discovery. */ export type ExternalCliAuthScope = { providerIds: string[]; profileIds: string[]; }; // Include both raw and normalized provider ids so config aliases and canonical // provider ids can both match external CLI auth providers. function addProviderScopeId(out: Set, value: string | undefined): void { const raw = value?.trim(); if (!raw) { return; } out.add(raw); const normalized = normalizeProviderId(raw); if (normalized) { out.add(normalized); } } // Model refs are provider/model strings. Only the provider prefix matters for // deciding which external CLI auth source may be queried. function addProviderScopeFromModelRef(out: Set, value: string | undefined): void { const raw = value?.trim(); if (!raw) { return; } const slash = raw.indexOf("/"); if (slash <= 0) { return; } addProviderScopeId(out, raw.slice(0, slash)); } function addProviderScopeFromModelConfig(out: Set, model: AgentModelConfig | undefined) { addProviderScopeFromModelRef(out, resolveAgentModelPrimaryValue(model)); for (const fallback of resolveAgentModelFallbackValues(model)) { addProviderScopeFromModelRef(out, fallback); } } // Some runtime ids imply an external CLI auth source even when the model ref is // not provider-qualified, so include known CLI runtimes in provider scope. function addExternalCliRuntimeScope(out: Set, value: string | undefined): void { const normalized = normalizeProviderId(value?.trim() ?? ""); if ( normalized === "claude-cli" || normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "google-gemini-cli" || normalized === "openai" || normalized === "minimax" || normalized === "minimax-cli" || normalized === "minimax-portal" ) { addProviderScopeId(out, normalized); } } function addExternalCliRuntimeScopeFromModelMap( out: Set, models: Record | undefined, ): void { for (const entry of Object.values(models ?? {})) { addExternalCliRuntimeScope(out, entry?.agentRuntime?.id); } } /** Resolves external CLI auth discovery scope from configured auth/model surfaces. */ export function resolveExternalCliAuthScopeFromConfig( cfg: OpenClawConfig, ): ExternalCliAuthScope | undefined { const providerIds = new Set(); const profileIds = new Set(); for (const id of Object.keys(cfg.models?.providers ?? {})) { addProviderScopeId(providerIds, id); } for (const [profileId, profile] of Object.entries(cfg.auth?.profiles ?? {})) { const normalizedProfileId = profileId.trim(); if (normalizedProfileId) { profileIds.add(normalizedProfileId); } addProviderScopeId(providerIds, profile?.provider); } for (const [provider, orderedProfileIds] of Object.entries(cfg.auth?.order ?? {})) { addProviderScopeId(providerIds, provider); for (const profileId of orderedProfileIds ?? []) { const normalizedProfileId = profileId.trim(); if (normalizedProfileId) { profileIds.add(normalizedProfileId); } } } const defaults = cfg.agents?.defaults; addProviderScopeFromModelConfig(providerIds, defaults?.model); addProviderScopeFromModelConfig(providerIds, defaults?.imageModel); addProviderScopeFromModelConfig(providerIds, defaults?.mediaModels?.image); addProviderScopeFromModelConfig(providerIds, defaults?.mediaModels?.video); addProviderScopeFromModelConfig(providerIds, defaults?.mediaModels?.music); addProviderScopeFromModelConfig(providerIds, defaults?.voiceModel); addProviderScopeFromModelConfig(providerIds, defaults?.pdfModel); addExternalCliRuntimeScopeFromModelMap(providerIds, defaults?.models); for (const provider of Object.values(cfg.models?.providers ?? {})) { addExternalCliRuntimeScope(providerIds, provider?.agentRuntime?.id); for (const model of provider?.models ?? []) { addExternalCliRuntimeScope(providerIds, model?.agentRuntime?.id); } } for (const agent of listAgentEntries(cfg)) { addProviderScopeFromModelConfig(providerIds, agent.model); addProviderScopeFromModelConfig(providerIds, agent.subagents?.model); addExternalCliRuntimeScopeFromModelMap(providerIds, agent.models); } if (providerIds.size === 0 && profileIds.size === 0) { return undefined; } return { providerIds: [...providerIds].toSorted((left, right) => left.localeCompare(right)), profileIds: [...profileIds].toSorted((left, right) => left.localeCompare(right)), }; }