UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

65 lines (64 loc) • 3.8 kB
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs"; import { n as safeParseJsonRecord } from "./json-coercion-pfKbZnCJ.mjs"; import { t as formatErrorMessage } from "./errors-O33D01XW.mjs"; import { M as parseAgentSessionKey } from "./session-key-C09ow4h0.mjs"; //#region src/config/io.cron-owner-refusal.ts const RETRY = " Run \"openclaw doctor --fix\", then retry."; const CRON_OWNER_REFUSAL = "cron-owner-safety"; function createCronOwnerWriteRefusalError(message, cause) { return Object.assign(new Error(message, cause === void 0 ? void 0 : { cause }), { code: "CONFIG_WRITE_REJECTED", refusal: CRON_OWNER_REFUSAL }); } function isCronOwnerWriteRefusalError(error) { return error instanceof Error && "refusal" in error && error.refusal === CRON_OWNER_REFUSAL; } function hasOwner(record) { if (!record) return false; return Boolean(normalizeOptionalString(record.agentId) || parseAgentSessionKey(normalizeOptionalString(record.sessionKey))?.agentId); } async function loadDefaultDeps() { const [{ readActiveGatewayLockIdentity }, { loadLegacyCronRepairState }] = await Promise.all([import("./gateway-lock-C0JnIOLH.mjs"), import("./legacy-repair-B3Id5yeg.mjs")]); return { readActiveGatewayLockIdentity, loadLegacyCronRepairState }; } async function assertSafe(cfg, storePath, env, deps, provenOwnerAgentId) { const active = await deps.readActiveGatewayLockIdentity({ env }).catch((error) => { throw createCronOwnerWriteRefusalError(`Config write refused: cannot inspect the Gateway lock (${formatErrorMessage(error)}).${RETRY}`, error); }); const state = await deps.loadLegacyCronRepairState({ cfg, storePath, env, readOnly: true }).catch((error) => { throw createCronOwnerWriteRefusalError(`Config write refused: cannot inspect cron ownership at ${storePath} (${formatErrorMessage(error)}).${RETRY}`, error); }); let unresolved = 0; let projectedDynamicDefaults = 0; for (const job of state?.rawJobs ?? []) { if (hasOwner(job)) continue; const id = normalizeOptionalString(job.id) ?? normalizeOptionalString(job.jobId); const projection = id ? state?.projectedOwnersByJobId.get(id) : void 0; if (!projection || projection.kind === "unresolved") unresolved += 1; else if (projection.kind === "runtime-default") projectedDynamicDefaults += 1; } const unverifiable = state?.invalidConfigRows?.length ?? 0; if (unverifiable > 0) throw createCronOwnerWriteRefusalError(`Config write refused: cron store ${storePath} contains ${unverifiable} corrupt row(s) whose ownership cannot be verified.${RETRY}`); const sqlOnlyOwners = state?.ownerRows.filter((row) => normalizeOptionalString(row.agent_id) && !hasOwner(safeParseJsonRecord(row.job_json))).length ?? 0; const requiresRepair = unresolved + (provenOwnerAgentId ? projectedDynamicDefaults + sqlOnlyOwners : 0); if (requiresRepair > 0) throw createCronOwnerWriteRefusalError(`Config write refused: cron store ${storePath} contains ${requiresRepair} ownerless legacy cron job(s).${RETRY}`); if (active && active.pid !== process.pid && active.cronOwnerProjection !== "dynamic-default-v1") throw createCronOwnerWriteRefusalError(`Config write refused: live external Gateway pid ${active.pid} does not prove compatibility with the current cron ownership projection. Restart it with this OpenClaw version, or stop it, then retry.`); } async function prepareCronOwnerWriteRefusal(cfg, params, injectedDeps) { const env = params.env ?? process.env; const deps = injectedDeps ?? await loadDefaultDeps(); const recheck = () => assertSafe(cfg, params.storePath, env, deps, params.provenOwnerAgentId); await recheck(); return { recheck }; } //#endregion export { isCronOwnerWriteRefusalError as n, prepareCronOwnerWriteRefusal as r, createCronOwnerWriteRefusalError as t };