openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
251 lines (250 loc) • 11.6 kB
JavaScript
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 };