UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

263 lines (262 loc) 11.4 kB
import { c as isRecord } from "./record-coerce-DItp3I4t.js"; import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { n as resolveAuthStorePathForDisplay } from "./paths-DLuhw03H.js"; import { m as loadAuthProfileStoreWithoutExternalProfiles } from "./store-F1B2duCT.js"; import "./provider-auth-BeZ7NZUU.js"; import { n as updateAuthProfileStoreWithLockCompat } from "./provider-auth-write-compat-B_rokROR.js"; import "./string-coerce-runtime-GQa0ehRA.js"; import "./agent-runtime-B15RhSG0.js"; import { n as hasAuthProfileConfigConflict, r as hasCurrentAuthProfileConfigConflict, t as applyAuthProfileConfigWithConflictCheck } from "./auth-config-BQ4l7Wu7.js"; import { a as parseEnv, c as readText, u as sanitizeName } from "./helpers-DWNr52wp.js"; import { _ as readHermesSecretDetails, d as createHermesSecretItem, h as hermesItemSkipped, l as HERMES_REASON_SECRET_NO_LONGER_PRESENT, m as hermesItemError, n as HERMES_REASON_AUTH_PROFILE_EXISTS, p as hermesItemConflict, r as HERMES_REASON_AUTH_PROFILE_WRITE_FAILED, s as HERMES_REASON_MISSING_SECRET_METADATA } from "./items-BfpzP26U.js"; import { r as normalizeHermesProviderId } from "./model-jtqSnRdw.js"; import { n as collectHermesProviderSecretBindings } from "./config-providers-Cy1MVYhW.js"; import { t as SECRET_MAPPINGS } from "./secret-mappings-BQkMl4NU.js"; //#region extensions/migrate-hermes/secrets.ts function authProfileTarget(agentDir, profileId) { return `${resolveAuthStorePathForDisplay(agentDir)}#${profileId}`; } function secretAuthProfileConfig(details) { return { profileId: details.profileId, provider: details.provider, mode: details.mode ?? "api_key", displayName: "Hermes import" }; } function secretMode(mapping) { return mapping.mode ?? "api_key"; } function buildEnvSecretCandidates(params) { const configuredBindings = collectHermesProviderSecretBindings(params.config, params.env); const claimedEnvVars = new Set(configuredBindings.map((binding) => binding.envVar)); const configured = configuredBindings.flatMap((binding) => { if (!params.env[binding.envVar]?.trim()) return []; return [{ id: `secret:${binding.provider}`, source: params.envPath, envVar: binding.envVar, provider: binding.provider, profileId: `${binding.provider}:hermes-import`, mode: "api_key" }]; }); const standard = SECRET_MAPPINGS.flatMap((mapping) => { if (claimedEnvVars.has(mapping.envVar)) return []; const value = params.env[mapping.envVar]?.trim(); if (!value) return []; const provider = mapping.envVar === "KIMI_API_KEY" || mapping.envVar === "KIMI_CODING_API_KEY" ? value.startsWith("sk-kimi-") ? "kimi" : "moonshot" : mapping.provider; return [{ id: `secret:${provider}`, source: params.envPath, envVar: mapping.envVar, provider, profileId: provider === mapping.provider ? mapping.profileId : `${provider}:hermes-import`, mode: secretMode(mapping) }]; }); return [...configured, ...standard]; } async function readAuthJson(authPath) { const raw = await readText(authPath); if (!raw) return {}; try { const parsed = JSON.parse(raw); return isRecord(parsed) ? parsed : {}; } catch { return {}; } } async function buildOpenCodeSecretCandidates(authPath) { if (!authPath) return []; const auth = await readAuthJson(authPath); const opencode = isRecord(auth.opencode) ? auth.opencode : {}; const opencodeGo = isRecord(auth["opencode-go"]) ? auth["opencode-go"] : {}; const githubCopilot = isRecord(auth["github-copilot"]) ? auth["github-copilot"] : {}; const githubCopilotEnterpriseUrl = normalizeOptionalString(githubCopilot.enterpriseUrl); const candidates = []; if (normalizeOptionalString(opencode.key)) candidates.push({ id: "secret:opencode:opencode-auth-json", source: authPath, provider: "opencode", profileId: "opencode:hermes-import", mode: "api_key", sourceKind: "opencode-auth-json", sourceProvider: "opencode", secretField: "key" }); if (normalizeOptionalString(opencodeGo.key)) candidates.push({ id: "secret:opencode-go:opencode-auth-json", source: authPath, provider: "opencode-go", profileId: "opencode-go:hermes-import", mode: "api_key", sourceKind: "opencode-auth-json", sourceProvider: "opencode-go", secretField: "key" }); if (normalizeOptionalString(githubCopilot.refresh) && !githubCopilotEnterpriseUrl) candidates.push({ id: "secret:github-copilot:opencode-auth-json", source: authPath, provider: "github-copilot", profileId: "github-copilot:github", mode: "token", sourceKind: "opencode-auth-json", sourceProvider: "github-copilot", secretField: "refresh" }); return candidates; } function normalizeHermesPoolProvider(provider) { return normalizeHermesProviderId(provider); } async function buildHermesPoolSecretCandidates(authPath, globalAuthPath) { if (!authPath && !globalAuthPath) return []; const auth = await readAuthJson(authPath); const globalAuth = await readAuthJson(globalAuthPath); const pool = isRecord(auth.credential_pool) ? auth.credential_pool : {}; const globalPool = isRecord(globalAuth.credential_pool) ? globalAuth.credential_pool : {}; const candidates = []; const sourceProviders = /* @__PURE__ */ new Set([...Object.keys(pool), ...Object.keys(globalPool)]); for (const sourceProvider of [...sourceProviders].toSorted()) { const profileEntries = Array.isArray(pool[sourceProvider]) ? pool[sourceProvider] : []; const globalEntries = Array.isArray(globalPool[sourceProvider]) ? globalPool[sourceProvider] : []; const rawEntries = profileEntries.length > 0 ? profileEntries : globalEntries; const sourcePath = profileEntries.length > 0 ? authPath : globalAuthPath; if (sourceProvider === "openai-codex" || !sourcePath) continue; for (const rawEntry of rawEntries) { if (!isRecord(rawEntry)) continue; const sourceCredentialId = normalizeOptionalString(rawEntry.id); const authType = normalizeOptionalString(rawEntry.auth_type); const source = normalizeOptionalString(rawEntry.source); if (!sourceCredentialId || authType !== "api_key" || source !== "manual" || !normalizeOptionalString(rawEntry.access_token)) continue; const provider = normalizeHermesPoolProvider(sourceProvider); const profileSuffix = sanitizeName(sourceCredentialId); if (!provider || !profileSuffix) continue; candidates.push({ id: `secret:${provider}:hermes-auth-json:${profileSuffix}`, source: sourcePath, provider, profileId: `${provider}:hermes-${profileSuffix}`, mode: "api_key", sourceKind: "hermes-auth-json", sourceProvider, sourceCredentialId, secretField: "access_token" }); } } return candidates; } async function readSecretCandidateValue(details, source) { if (details.sourceKind === "opencode-auth-json") { const auth = await readAuthJson(source); const sourceProvider = details.sourceProvider; const secretField = details.secretField; if (!sourceProvider || !secretField) return; const provider = isRecord(auth[sourceProvider]) ? auth[sourceProvider] : {}; return normalizeOptionalString(provider[secretField]); } if (details.sourceKind === "hermes-auth-json") { const auth = await readAuthJson(source); const pool = isRecord(auth.credential_pool) ? auth.credential_pool : {}; const entries = details.sourceProvider ? pool[details.sourceProvider] : void 0; if (!Array.isArray(entries) || !details.sourceCredentialId) return; const entry = entries.find((candidate) => isRecord(candidate) && candidate.id === details.sourceCredentialId); return isRecord(entry) ? normalizeOptionalString(entry.access_token) : void 0; } if (!details.envVar) return; return parseEnv(await readText(source))[details.envVar]?.trim() || void 0; } async function buildSecretItems(params) { const env = parseEnv(await readText(params.source.envPath)); const store = loadAuthProfileStoreWithoutExternalProfiles(params.targets.agentDir); const seenProfiles = /* @__PURE__ */ new Set(); const items = []; const candidates = [ ...buildEnvSecretCandidates({ config: params.config, env, envPath: params.source.envPath }), ...await buildHermesPoolSecretCandidates(params.source.authPath, params.source.globalAuthPath), ...await buildOpenCodeSecretCandidates(params.source.opencodeAuthPath) ]; for (const candidate of candidates) { if (seenProfiles.has(candidate.profileId)) continue; seenProfiles.add(candidate.profileId); const existsAlready = Boolean(store.profiles[candidate.profileId]); const configConflict = hasAuthProfileConfigConflict(params.ctx.config, secretAuthProfileConfig(candidate), Boolean(params.ctx.overwrite)); items.push(createHermesSecretItem({ id: candidate.id, source: candidate.source, target: authProfileTarget(params.targets.agentDir, candidate.profileId), includeSecrets: params.ctx.includeSecrets, existsAlready: existsAlready && !params.ctx.overwrite || configConflict, details: { ...candidate.envVar ? { envVar: candidate.envVar } : {}, provider: candidate.provider, profileId: candidate.profileId, ...candidate.mode === "token" ? { mode: candidate.mode } : {}, ...candidate.sourceKind ? { sourceKind: candidate.sourceKind } : {}, ...candidate.sourceProvider ? { sourceProvider: candidate.sourceProvider } : {}, ...candidate.sourceCredentialId ? { sourceCredentialId: candidate.sourceCredentialId } : {}, ...candidate.secretField ? { secretField: candidate.secretField } : {} } })); } return items; } async function applySecretItem(ctx, item, targets) { if (item.status !== "planned") return item; const details = readHermesSecretDetails(item); const source = item.source; if (!details || !source) return hermesItemError(item, HERMES_REASON_MISSING_SECRET_METADATA); const key = await readSecretCandidateValue(details, source); if (!key) return hermesItemSkipped(item, HERMES_REASON_SECRET_NO_LONGER_PRESENT); const configProfile = secretAuthProfileConfig(details); if (hasCurrentAuthProfileConfigConflict(ctx, configProfile)) return hermesItemConflict(item, HERMES_REASON_AUTH_PROFILE_EXISTS); let conflicted = false; let wrote = false; const store = await updateAuthProfileStoreWithLockCompat({ agentDir: targets.agentDir, stateDir: ctx.stateDir, updater: (freshStore) => { if (!ctx.overwrite && freshStore.profiles[details.profileId]) { conflicted = true; return false; } freshStore.profiles[details.profileId] = details.mode === "token" ? { type: "token", provider: details.provider, token: key, displayName: "Hermes import" } : { type: "api_key", provider: details.provider, key, displayName: "Hermes import" }; wrote = true; return true; } }); if (conflicted) return hermesItemConflict(item, HERMES_REASON_AUTH_PROFILE_EXISTS); if (!store?.profiles[details.profileId]) return hermesItemError(item, HERMES_REASON_AUTH_PROFILE_WRITE_FAILED); if (!wrote && !ctx.overwrite) return hermesItemConflict(item, HERMES_REASON_AUTH_PROFILE_EXISTS); const configResult = await applyAuthProfileConfigWithConflictCheck({ ctx, profile: configProfile }); if (configResult === "conflict") return hermesItemConflict(item, HERMES_REASON_AUTH_PROFILE_EXISTS); return { ...item, status: "migrated", details: { ...item.details, configUpdated: configResult === "configured" } }; } //#endregion export { buildSecretItems as n, applySecretItem as t };