UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

251 lines (250 loc) 11.6 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import { l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js"; import { M as containsAuthoredInclude, j as classifyOtelGrpcMigrationOwnership, k as applyLegacyDoctorMigrations } from "./io.runtime-B9iJRs3w.js"; import { j as resolveConfigIncludes } from "./redact-BtvPPfTi.js"; import "./utils-P__uGsPB.js"; import { v as resolveIncludeRoots } from "./paths-D2sRr1a_.js"; import { r as collectConfiguredModelRefs } from "./configured-model-refs-DEXTV_K3.js"; import { n as createMergePatch } from "./merge-patch-DCMj2JVh.js"; import { t as splitTrailingAuthProfile } from "./model-ref-profile-BIKs-96s.js"; import { o as restoreEnvVarRefs } from "./io.types-BUCjdS5v.js"; import { n as formatConfigIssueLines } from "./issue-format-CQvxWNW8.js"; import { t as configIncludeOwnsAgentRoster } from "./agent-roster-provenance-TGrT9xta.js"; import { t as projectAuthoredAgentRosterForWrite } from "./io.write-prepare-ijfpLGq7.js"; import { c as stripUnknownConfigKeys } from "./doctor-config-analysis-BuQuAQxk.js"; import { t as migrateLegacyConfig } from "./legacy-config-migrate-ibYHB0mZ.js"; import { isDeepStrictEqual } from "node:util"; //#region src/commands/doctor-auth-profile-config.ts /** Protects active auth profile metadata while doctor repairs broader config state. */ const AUTH_PROFILE_MODES = /* @__PURE__ */ new Set([ "api_key", "aws-sdk", "oauth", "token" ]); function normalizeProviderId(value) { return normalizeLowercaseStringOrEmpty(value); } function normalizeProfileId(value) { return normalizeOptionalString(value) ?? null; } function normalizeMode(value) { return typeof value === "string" && AUTH_PROFILE_MODES.has(value) ? value : null; } function extractProviderFromModelRef(value) { const { model } = splitTrailingAuthProfile(value); const slash = model.indexOf("/"); if (slash <= 0) return null; return normalizeProviderId(model.slice(0, slash)) || null; } function extractProviderFromProfileId(profileId) { const colon = profileId.indexOf(":"); if (colon <= 0) return null; return normalizeProviderId(profileId.slice(0, colon)) || null; } function collectActiveAuthHints(config) { const activeProviders = /* @__PURE__ */ new Set(); const explicitProfileIds = /* @__PURE__ */ new Set(); const explicitProfileProviders = /* @__PURE__ */ new Map(); const models = isRecord(config.models) ? config.models : {}; const providers = isRecord(models.providers) ? models.providers : {}; for (const providerId of Object.keys(providers)) { const normalized = normalizeProviderId(providerId); if (normalized) activeProviders.add(normalized); } for (const { value } of collectConfiguredModelRefs(config)) { const { profile } = splitTrailingAuthProfile(value); const provider = extractProviderFromModelRef(value); if (profile) { explicitProfileIds.add(profile); if (provider) { const providersLocal = explicitProfileProviders.get(profile) ?? /* @__PURE__ */ new Set(); providersLocal.add(provider); explicitProfileProviders.set(profile, providersLocal); } } if (provider) activeProviders.add(provider); } const auth = isRecord(config.auth) ? config.auth : {}; const order = isRecord(auth.order) ? auth.order : {}; for (const [providerId, profileIds] of Object.entries(order)) { const provider = normalizeProviderId(providerId); if (!provider || !activeProviders.has(provider) || !Array.isArray(profileIds)) continue; for (const profileId of profileIds) { const normalized = normalizeProfileId(profileId); if (normalized) explicitProfileIds.add(normalized); } } return { activeProviders, explicitProfileIds, explicitProfileProviders }; } function isValidProfileMetadata(value) { if (!isRecord(value)) return false; return normalizeProviderId(value.provider) !== "" && normalizeMode(value.mode) !== null; } function buildProfileMetadata(params) { const before = isRecord(params.before) ? params.before : {}; const after = isRecord(params.after) ? params.after : {}; const provider = normalizeProviderId(after.provider) || normalizeProviderId(before.provider) || extractProviderFromProfileId(params.profileId) || normalizeProviderId(params.providerHint); if (!provider) return null; const repaired = { provider, mode: normalizeMode(after.mode) ?? normalizeMode(before.mode) ?? "api_key" }; const email = normalizeOptionalString(after.email) ?? normalizeOptionalString(before.email); const displayName = normalizeOptionalString(after.displayName) ?? normalizeOptionalString(before.displayName); if (email) repaired.email = email; if (displayName) repaired.displayName = displayName; return repaired; } function ensureAuthProfiles(config) { const root = config; const auth = isRecord(root.auth) ? root.auth : {}; if (root.auth !== auth) root.auth = auth; if (!isRecord(auth.profiles)) auth.profiles = {}; return auth.profiles; } /** * Restores valid metadata for auth profiles still referenced by active model config. * * Doctor can rebuild or prune auth config; this guard keeps active profiles usable when their * provider/mode metadata can be inferred from the before/after config or profile id. */ function protectActiveAuthProfileConfig(params) { const { activeProviders, explicitProfileIds, explicitProfileProviders } = collectActiveAuthHints(params.before); const beforeAuth = isRecord(params.before.auth) ? params.before.auth : {}; const beforeProfiles = isRecord(beforeAuth.profiles) ? beforeAuth.profiles : {}; if (Object.keys(beforeProfiles).length === 0) return { config: params.after, repairs: [], warnings: [] }; const config = structuredClone(params.after); const afterAuth = isRecord(config.auth) ? config.auth : {}; const afterProfiles = isRecord(afterAuth.profiles) ? afterAuth.profiles : {}; const repairs = []; const warnings = []; for (const [profileId, beforeProfile] of Object.entries(beforeProfiles)) { const afterProfile = afterProfiles[profileId]; const afterProfileRecord = isRecord(afterProfile) ? afterProfile : null; const beforeProfileRecord = isRecord(beforeProfile) ? beforeProfile : null; if (isValidProfileMetadata(afterProfile)) continue; const provider = normalizeProviderId(afterProfileRecord?.provider) || normalizeProviderId(beforeProfileRecord?.provider) || extractProviderFromProfileId(profileId); const protectsActiveProvider = provider !== null && activeProviders.has(provider); const protectsExplicitProfile = explicitProfileIds.has(profileId); if (!protectsActiveProvider && !protectsExplicitProfile) continue; const repaired = buildProfileMetadata({ profileId, before: beforeProfile, after: afterProfile, providerHint: explicitProfileProviders.get(profileId)?.size === 1 ? [...explicitProfileProviders.get(profileId) ?? []][0] : void 0 }); if (!repaired) { warnings.push(`auth.profiles.${profileId}: active auth profile metadata could not be inferred; repair manually before running doctor --fix.`); continue; } const profiles = ensureAuthProfiles(config); profiles[profileId] = repaired; repairs.push(`Repaired auth.profiles.${profileId} metadata for active ${repaired.provider} auth.`); } return { config, repairs, warnings }; } //#endregion //#region src/commands/doctor/shared/config-flow-steps.ts /** Apply legacy config migrations and update preview/fix state for doctor config flow. */ function applyLegacyCompatibilityStep(params) { if (params.snapshot.legacyIssues.length === 0) return { state: params.state, issueLines: [], changeLines: [] }; const issueLines = formatConfigIssueLines(params.snapshot.legacyIssues, "-"); const otelOwnership = classifyOtelGrpcMigrationOwnership({ snapshot: params.snapshot, authoredConfig: params.snapshot.parsed, resolvedConfig: params.snapshot.sourceConfig }); if (otelOwnership) { const ownership = otelOwnership; if (ownership.kind === "manual") { const otelPath = "diagnostics.otel.protocol"; const targets = ownership.targetPaths.length > 0 ? ` Inspect these candidate source files and remove or replace ${otelPath} = "grpc" from every definition: ${ownership.targetPaths.join(", ")}.` : ` Remove or replace ${otelPath} = "grpc" in the owning $include directive or included file.`; return { state: params.state, issueLines: [...issueLines, `- ${otelPath}: Doctor cannot safely rewrite this $include ownership.${targets} No config files were changed.`], changeLines: [], blocksWrite: true }; } } const hasAuthoredIncludes = containsAuthoredInclude(params.snapshot.parsed); const { config: migrated, sourceConfig: migratedSource, changes, partiallyValid } = migrateLegacyConfig(params.snapshot.sourceConfig, { authoredRaw: params.snapshot.parsed, resolvedRaw: params.snapshot.sourceConfig }); const migrationCandidate = hasAuthoredIncludes && migratedSource ? migratedSource : migrated; const hasLegacyChanges = changes.length > 0 || !isDeepStrictEqual(params.snapshot.sourceConfigBeforeMigrations ?? (hasAuthoredIncludes ? params.snapshot.sourceConfig : params.snapshot.parsed), params.snapshot.sourceConfig); return { state: { ...params.state, ...migrationCandidate ? { cfg: migrationCandidate, candidate: migrationCandidate } : {}, pendingChanges: params.state.pendingChanges || hasLegacyChanges, fixHints: params.shouldRepair || !hasLegacyChanges ? params.state.fixHints : [...params.state.fixHints, `Run "${params.doctorFixCommand}" to ${partiallyValid ? "finish fixing" : "migrate"} legacy config keys.`] }, issueLines, changeLines: changes, partiallyValid: partiallyValid === true ? true : void 0 }; } /** Strip unknown config keys while preserving active auth profile settings. */ function applyUnknownConfigKeyStep(params) { const unknown = stripUnknownConfigKeys(params.state.candidate); if (unknown.removed.length === 0) return { state: params.state, removed: [], repairs: [], warnings: [] }; const protectedAuth = protectActiveAuthProfileConfig({ before: params.state.candidate, after: unknown.config }); return { state: { cfg: params.shouldRepair ? protectedAuth.config : params.state.cfg, candidate: protectedAuth.config, pendingChanges: true, fixHints: params.shouldRepair ? params.state.fixHints : [...params.state.fixHints, `Run "${params.doctorFixCommand}" to remove these keys.`] }, removed: unknown.removed, repairs: protectedAuth.repairs, warnings: protectedAuth.warnings }; } /** Restore references moved by Doctor while keeping resolved values for its state repairs. */ function restoreDoctorConfigEnvRefs(candidate, snapshot, env) { const authored = resolveConfigIncludes(snapshot.parsed, snapshot.path, void 0, { allowedRoots: resolveIncludeRoots(env) }); const canonicalAuthored = projectAuthoredAgentRosterForWrite({ rootAuthoredConfig: authored, sourceConfigBeforeMigrations: snapshot.sourceConfigBeforeMigrations }); const migrated = applyLegacyDoctorMigrations(canonicalAuthored, { authoredRaw: snapshot.parsed, resolvedRaw: snapshot.sourceConfig }); const referenceBase = containsAuthoredInclude(snapshot.parsed) && !configIncludeOwnsAgentRoster(snapshot) ? canonicalAuthored : authored; const referenceTemplate = createMergePatch(referenceBase, migrated.next ?? canonicalAuthored); return restoreEnvVarRefs(candidate, referenceTemplate, env); } //#endregion export { applyUnknownConfigKeyStep as n, restoreDoctorConfigEnvRefs as r, applyLegacyCompatibilityStep as t };