openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
144 lines (143 loc) • 6.87 kB
JavaScript
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { m as shortenHomePath } from "./utils-P__uGsPB.js";
import { t as createSubsystemLogger } from "./subsystem-Dy2tqXOS.js";
import { c as resolveSharedMainAuthAgentDir, s as resolveSharedAuthStorePath } from "./path-resolve-oRkRBkQd.js";
import { D as resolveLegacyAuthProfileSourceCandidates, E as listLegacyAuthProfileSources, c as inspectPersistedSharedAuthProfileStoreRaw, h as resolveAuthProfileDatabasePath, o as inspectPersistedAuthProfileStoreRaw } from "./sqlite-MN_7y26V.js";
import fs from "node:fs";
//#region src/agents/auth-profiles/legacy-source-diagnostic.ts
const AUTH_PROFILE_MIGRATION_REQUIRED_CODE = "AUTH_PROFILE_MIGRATION_REQUIRED";
const AUTH_PROFILE_MIGRATION_COMMAND = "openclaw doctor --fix";
const log = createSubsystemLogger("auth-profiles/persistence");
function isCredentialSource(source) {
return source.kind !== "auth-state";
}
function resolveAuthProfileOwnerPath(agentDir, env) {
return agentDir ? resolveAuthProfileDatabasePath(agentDir) : resolveSharedAuthStorePath(env);
}
function hasLegacyAuthProfileCredentialSource(agentDir) {
return listLegacyAuthProfileSources({ agentDir }).some(isCredentialSource);
}
/**
* True when the canonical SQLite store already holds credentials for this owner.
* A retired JSON file sitting next to a populated store is leftover bytes Doctor
* has not archived yet, not unmigrated credentials: failing runtime closed there
* would strand a working store over a file nothing reads.
*/
function hasMigratedAuthProfileCredentials(agentDir, env) {
let inspection;
try {
inspection = !agentDir && env ? inspectPersistedSharedAuthProfileStoreRaw(env) : inspectPersistedAuthProfileStoreRaw(agentDir);
} catch {
return false;
}
if (inspection.status !== "readable") return false;
const profiles = isRecord(inspection.raw) ? inspection.raw.profiles : void 0;
return isRecord(profiles) && Object.keys(profiles).length > 0;
}
function listStartupLegacyAuthProfileSources(params) {
const sharedMainDir = resolveSharedMainAuthAgentDir(params.env);
return [.../* @__PURE__ */ new Set([...params.agentDirs, sharedMainDir])].map((agentDir) => {
const sources = listLegacyAuthProfileSources({
agentDir,
env: params.env
});
const credentialSources = sources.filter(isCredentialSource);
return {
agentDir,
sources,
unmigratedCredentialSources: credentialSources.length > 0 && hasMigratedAuthProfileCredentials(agentDir) ? [] : credentialSources
};
});
}
function hasLegacyAuthProfileSourcesForStartup(params) {
let detected = false;
for (const { agentDir, sources, unmigratedCredentialSources } of listStartupLegacyAuthProfileSources(params)) {
detected ||= sources.length > 0;
if (unmigratedCredentialSources.length > 0) markAuthProfileMigrationRequired(agentDir, new AuthProfileMigrationRequiredError({
agentDir,
sources: unmigratedCredentialSources
}));
}
return detected;
}
var AuthProfileMigrationRequiredError = class extends Error {
constructor(params) {
const ownerId = shortenHomePath(params.databasePath ?? resolveAuthProfileOwnerPath(params.agentDir, params.env));
const sourceKinds = [...new Set(params.sources.map((source) => source.kind))].toSorted();
super(`Auth profile store ${ownerId} requires legacy credential migration; run ${AUTH_PROFILE_MIGRATION_COMMAND}.`);
this.code = AUTH_PROFILE_MIGRATION_REQUIRED_CODE;
this.action = AUTH_PROFILE_MIGRATION_COMMAND;
this.name = "AuthProfileMigrationRequiredError";
this.ownerId = ownerId;
this.sourceKinds = sourceKinds;
}
};
var AuthProfileStoreUnreadableError = class extends Error {
constructor(databasePath) {
super(`Auth profile store ${shortenHomePath(databasePath)} is unreadable; run ${AUTH_PROFILE_MIGRATION_COMMAND}.`);
this.code = "AUTH_PROFILE_STORE_UNREADABLE";
this.action = AUTH_PROFILE_MIGRATION_COMMAND;
this.name = "AuthProfileStoreUnreadableError";
}
};
const migrationRequiredByDatabase = /* @__PURE__ */ new Map();
const warnedLegacySourceDatabases = /* @__PURE__ */ new Set();
function warnLegacyAuthProfileSourcesIgnored(params) {
if (params.sources.length === 0) return;
const databasePath = params.databasePath ?? resolveAuthProfileOwnerPath(params.agentDir, params.env);
if (warnedLegacySourceDatabases.has(databasePath)) return;
warnedLegacySourceDatabases.add(databasePath);
log.warn("retired auth profile files are ignored by runtime; run Doctor to archive them", {
code: AUTH_PROFILE_MIGRATION_REQUIRED_CODE,
ownerId: shortenHomePath(databasePath),
sourceKinds: [...new Set(params.sources.map((source) => source.kind))].toSorted(),
action: AUTH_PROFILE_MIGRATION_COMMAND
});
}
function markAuthProfileMigrationRequired(agentDir, error, env) {
const databasePath = resolveAuthProfileOwnerPath(agentDir, env);
migrationRequiredByDatabase.set(databasePath, error);
}
function clearAuthProfileMigrationRequired(agentDir, env) {
const databasePath = resolveAuthProfileOwnerPath(agentDir, env);
migrationRequiredByDatabase.delete(databasePath);
}
/** Publication must honor a recorded refusal without rediscovering an ambient owner. */
function assertAuthProfileMigrationStateAtDatabasePath(databasePath) {
const error = migrationRequiredByDatabase.get(databasePath);
if (error) throw error;
}
function assertAuthProfileMigrationCandidates(params) {
assertAuthProfileMigrationStateAtDatabasePath(params.databasePath);
const sources = params.candidates.filter((source) => isCredentialSource(source) && fs.existsSync(source.path));
if (sources.length === 0) return;
if (params.hasCredentials()) {
warnLegacyAuthProfileSourcesIgnored({
databasePath: params.databasePath,
sources
});
return;
}
const migrationError = new AuthProfileMigrationRequiredError({
databasePath: params.databasePath,
sources
});
migrationRequiredByDatabase.set(params.databasePath, migrationError);
throw migrationError;
}
function assertAuthProfileMigrationReady(agentDir, env) {
assertAuthProfileMigrationCandidates({
databasePath: resolveAuthProfileOwnerPath(agentDir, env),
candidates: resolveLegacyAuthProfileSourceCandidates({
agentDir,
env
}),
hasCredentials: () => hasMigratedAuthProfileCredentials(agentDir, env)
});
}
function clearAuthProfileMigrationDiagnostics() {
migrationRequiredByDatabase.clear();
warnedLegacySourceDatabases.clear();
}
//#endregion
export { assertAuthProfileMigrationStateAtDatabasePath as a, hasLegacyAuthProfileCredentialSource as c, warnLegacyAuthProfileSourcesIgnored as d, assertAuthProfileMigrationReady as i, hasLegacyAuthProfileSourcesForStartup as l, AuthProfileStoreUnreadableError as n, clearAuthProfileMigrationDiagnostics as o, assertAuthProfileMigrationCandidates as r, clearAuthProfileMigrationRequired as s, AuthProfileMigrationRequiredError as t, markAuthProfileMigrationRequired as u };