UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

445 lines (444 loc) • 25.5 kB
import { i as collectNestedErrorCandidates } from "./error-coercion-W9BtigRm.mjs"; import { n as isTruthyEnvValue } from "./env-Ca5Je5YP.mjs"; import { a as measureGatewayBootstrapStep } from "./startup-trace-DQN0c5Oa.mjs"; import { r as resolveStateDir } from "./state-dir-CYkBUd_G.mjs"; import { m as resolveConfigPath } from "./paths-BP0DYpE8.mjs"; import { t as UpdateSchemaRefusalError } from "./openclaw-update-schema-refusal-D1MbU6wE.mjs"; import { t as createSubsystemLogger } from "./subsystem-4NzR43uz.mjs"; import { a as resolveUpdateRehearsalRoot } from "./update-rehearsal-paths-FgHeU_TR.mjs"; import { d as withCommandProcessScope } from "./exec-spawn-rD1j0ZHJ.mjs"; import { t as _usingCtx } from "./usingCtx-BhiZp_rS.mjs"; import { n as formatUpdateFailureFact } from "./update-failure-facts-format-DbAtk-ZC.mjs"; import { r as createUpdateFailureFact } from "./update-failure-facts-CUaw-9AP.mjs"; import { n as formatUpdateDoctorConfigChange } from "./update-doctor-config-BrLAVDg0.mjs"; import { l as isUpdateDoctorLintPass } from "./update-phase-YMT_h9sM.mjs"; import { a as UpdateDoctorError, b as writeUpdatePostInstallDoctorResult, i as UPDATE_POST_INSTALL_DOCTOR_RESULT_PATH_ENV, m as normalizeUpdatePostInstallDoctorWarnings, s as captureUpdateDoctorConfigWrites, t as DoctorMaintenanceRefusalError } from "./update-doctor-result-Buvixhp2.mjs"; import { t as ConfigWritePostCommitError } from "./io.write-errors-B-bJYfsA.mjs"; import { n as withDeferredDebugProxyCapture } from "./runtime-deferral-Bdhp4T3g.mjs"; import { n as withPluginLoadDiagnostics } from "./load-diagnostics-ue2aSd6P.mjs"; import { n as retainCurrentDeferredPluginMigrationWarnings } from "./deferred-plugin-migration-warnings-CpaVE9Sv.mjs"; import { n as retainUpdateDoctorProcesses } from "./update-doctor-process-custody-BUf-A79_.mjs"; import { r as stylePromptTitle } from "./prompt-style-zarsDmI2.mjs"; import { n as resolveDoctorRepairMode, t as isDoctorUpdateRepairMode } from "./doctor-repair-mode-p8fxj8I_.mjs"; import { t as exitDoctorHealthFlow } from "./doctor-health-startup-BWsglIYK.mjs"; import { intro, outro } from "@clack/prompts"; //#region src/flows/doctor-health-update-result.ts async function publishDoctorUpdateResult(params) { const { updateResult, doctorResult, healthContext, maintenance } = params; for (const change of updateResult.capture.configChanges) createSubsystemLogger("update").warn(formatUpdateDoctorConfigChange(change)); const contributionWarnings = healthContext?.updateWarnings ?? []; const deferredCount = healthContext?.updateBudget?.deferred.size ?? 0; const warnings = await retainCurrentDeferredPluginMigrationWarnings(normalizeUpdatePostInstallDoctorWarnings([ ...contributionWarnings.slice(0, deferredCount), ...doctorResult.warnings ?? [], ...(maintenance?.warnings ?? []).filter((warning) => !doctorResult.warnings?.includes(warning)), ...contributionWarnings.slice(deferredCount) ])); const outcome = { ...doctorResult }; delete outcome.warnings; await writeUpdatePostInstallDoctorResult({ resultPath: updateResult.resultPath, result: { ...outcome, ...maintenance?.databaseWrites ? { databaseWrites: maintenance.databaseWrites } : {}, ...updateResult.capture.fileWrites ? { configFileWrites: updateResult.capture.fileWrites } : {}, ...warnings.length ? { warnings } : {}, ...updateResult.capture.configChanges.length ? { configChanges: updateResult.capture.configChanges } : {}, ...updateResult.capture.configWriteRefusal ? { configWriteRefusal: updateResult.capture.configWriteRefusal } : {}, configHash: updateResult.capture.hash, ...updateResult.capture.inputHash === void 0 ? {} : { configInputHash: updateResult.capture.inputHash } } }); } //#endregion //#region src/flows/doctor-health.ts const intro$1 = (message) => intro(stylePromptTitle(message) ?? message); const outro$1 = (message) => outro(stylePromptTitle(message) ?? message); /** Runs the full interactive doctor flow against the provided or default runtime. */ async function runDoctorHealthFlow(runtime, options = {}, writeAuthority, databasePreflight) { try { var _usingCtx$1 = _usingCtx(); const custody = _usingCtx$1.u(await retainUpdateDoctorProcesses(writeAuthority?.assertCurrent, writeAuthority?.commandAuthority)); let requestedExit; const run = () => withDeferredDebugProxyCapture(async (resumeCapture) => { let preparedPreflight = databasePreflight; const preserveSourceArtifacts = writeAuthority?.databaseGenerations ? true : void 0; const preCaptureRehearsalRoot = !writeAuthority?.postCoreSchemaRepair && (options.repair === true || options.yes === true) ? resolveUpdateRehearsalRoot(process.env) : void 0; if (process.env.OPENCLAW_UPDATE_IN_PROGRESS === "1" && !writeAuthority?.postCoreSchemaRepair) { const { guardUpdateDoctorSchemaUpgrade, rehearseDeferredUpdateDoctorSchema } = await import("./commands/doctor-update-schema-guard.js"); const guarded = await guardUpdateDoctorSchemaUpgrade({ schemas: preparedPreflight, runtime, json: options.json, statePublicationOnly: preCaptureRehearsalRoot !== void 0, preserveSourceArtifacts }); if (!preCaptureRehearsalRoot) preparedPreflight = guarded ?? preparedPreflight; if (!preCaptureRehearsalRoot && preparedPreflight?.updateSchemaRehearsal) { await rehearseDeferredUpdateDoctorSchema(preparedPreflight, runtime); return; } } const resultPath = process.env[UPDATE_POST_INSTALL_DOCTOR_RESULT_PATH_ENV]?.trim(); return withPluginLoadDiagnostics((diagnostics) => { const runDoctor = (capture) => runDoctorHealthFlowWithResult((selectedRuntime, code) => { requestedExit = () => exitDoctorHealthFlow(selectedRuntime, code); }, runtime, options, preparedPreflight, diagnostics, resultPath && capture ? { resultPath, capture } : void 0, writeAuthority, resumeCapture, preCaptureRehearsalRoot); return resultPath ? captureUpdateDoctorConfigWrites(resolveConfigPath(), runDoctor, writeAuthority) : runDoctor(); }); }); const { withPluginGenerationSourceCustody } = await import("./plugin-generation-source-lookup-dQvdgTo6.mjs"); await withPluginGenerationSourceCustody(() => custody ? withCommandProcessScope(run, void 0, custody) : run()); requestedExit?.(); } catch (_) { _usingCtx$1.e = _; } finally { _usingCtx$1.d(); } } async function runDoctorHealthFlowWithResult(requestExit, runtime, options, databasePreflight, diagnostics, updateResult, writeAuthority, resumeCapture, preCaptureRehearsalRoot) { const { prepareDoctorHealthFlow, prepareDoctorInteractiveMaintenance, prepareDoctorMaintenanceArchives, prepareDoctorStateSchema } = await import("./doctor-health-startup-BFcyIdpL.mjs"); const { effectiveRuntime, repairRuntime, stateDirExistedAtStart, root } = await prepareDoctorHealthFlow(runtime, options, intro$1); let maintenance; let sqliteNoCowPaths = []; const preflightOptions = { preserveSourceArtifacts: writeAuthority?.databaseGenerations ? true : void 0 }; let sqliteReclamationAgents; let exitCode; let healthContext; let preparedArchiveDiscovery; let doctorResult = { status: "error" }; const recordConfigWriteRefusal = (ctx) => { if (!ctx.configWriteRefusal) return false; outro$1(ctx.configResultWriteCommitted === true ? "Doctor finished, but some config fixes were not applied." : "Doctor finished, but config fixes were not applied."); exitCode = 1; doctorResult = { status: "error", failureFacts: [createUpdateFailureFact({ check: "config-write", code: ctx.configWriteRefusal, message: "Doctor config fixes were not applied." })] }; return true; }; const repairMode = resolveDoctorRepairMode(options); let interactiveRepair = false; let updateAdmissionComplete = false; if (repairMode.canPrompt && !repairMode.shouldRepair) { const admission = await prepareDoctorInteractiveMaintenance({ runtime: effectiveRuntime, options, databasePreflight, root, outro: outro$1 }); if (admission !== "accepted") { if (admission !== "handled") requestExit(effectiveRuntime, admission.diagnosticExitCode); return; } interactiveRepair = true; updateAdmissionComplete = true; } try { const { assertDoctorRetiredStateAdmission } = await import("./doctor-retired-state-admission-BM3jTrxn.mjs"); assertDoctorRetiredStateAdmission(); if (options.repair === true || options.yes === true || interactiveRepair) preparedArchiveDiscovery = await prepareDoctorMaintenanceArchives(databasePreflight, effectiveRuntime, preflightOptions); const [{ beginDoctorMaintenance }, { createDoctorOriginalCaptureHook }] = await Promise.all([import("./doctor-maintenance-8NRA9QLM.mjs"), import("./doctor-original-capture-admission-CxJh9ggw.mjs")]); maintenance = await measureGatewayBootstrapStep("doctor.maintenance.begin", () => beginDoctorMaintenance({ options, interactiveRepair, root, runtime: repairRuntime, assertCurrent: writeAuthority?.assertCurrent, databaseGenerations: writeAuthority?.databaseGenerations, beforeStateMutation: createDoctorOriginalCaptureHook({ root, runtime: repairRuntime, writeAuthority, rehearsalRoot: preCaptureRehearsalRoot, json: options.json }) })); const runChecks = async () => { const doctorRuntime = maintenance ? repairRuntime : effectiveRuntime; const { createDoctorPrompter } = await import("./doctor-prompter-DfExfSVV.mjs"); const { prepareDoctorDatabasePreflight } = await import("./doctor-database-preflight-Boy2l09m.mjs"); const prompter = createDoctorPrompter({ runtime: doctorRuntime, options, signal: maintenance?.signal }); if (!maintenance && !updateAdmissionComplete) { if (!databasePreflight) await prepareDoctorDatabasePreflight({ scope: "state" }); const { maybeOfferUpdateBeforeDoctor } = await import("./doctor-update-0LFi29rj.mjs"); if ((await maybeOfferUpdateBeforeDoctor({ options, root, confirm: (p) => prompter.confirm(p), outro: outro$1 })).handled) return; } const refreshRecoveryInventory = maintenance && databasePreflight?.agentDatabaseMigrationDiscovery?.discovery.deletionJournal.status === "unavailable"; let schemas = databasePreflight && !refreshRecoveryInventory ? databasePreflight : await measureGatewayBootstrapStep("doctor.database-preflight", () => prepareDoctorDatabasePreflight(preflightOptions)); const { recordAgentDatabaseAdmissions } = await import("./agent-database-admission-B9BU-GOv.mjs"); if (options.repair !== true && options.yes !== true) recordAgentDatabaseAdmissions(schemas.agentRefusals ?? []); const { guardUpdateDoctorSchemaUpgrade } = await import("./commands/doctor-update-schema-guard.js"); let verifiedSnapshots = []; await guardUpdateDoctorSchemaUpgrade({ schemas, runtime: doctorRuntime, json: options.json, postCoreSchemaRepair: writeAuthority?.postCoreSchemaRepair, onVerifiedBackup: (snapshots) => { verifiedSnapshots = snapshots; } }); if (maintenance && (options.repair === true || options.yes === true)) { const { repairOpenClawStateDatabaseIndexesForDoctor, repairOpenClawStateDatabaseReadabilityForDoctor } = await import("./openclaw-state-db-BoNab8eI.mjs"); let repairedState = false; for (const repair of [repairOpenClawStateDatabaseIndexesForDoctor, repairOpenClawStateDatabaseReadabilityForDoctor]) { const result = repair({ env: process.env }); repairedState ||= result.changes.length > 0; if (result.warnings.length > 0) throw new Error(result.warnings.join("\n")); for (const change of result.changes) effectiveRuntime.log(change); } if (repairedState) schemas = await prepareDoctorDatabasePreflight(); } if (maintenance) { const { backupDoctorMigrationDatabases } = await import("./doctor-migration-backup-eE-e_MvM.mjs"); const { createOpenClawAgentDatabasePathMatcher } = await import("./openclaw-agent-db.paths-CNQ-l_7i.mjs"); const { normalizeAgentId } = await import("./session-key-D01uynzU.mjs"); const samePath = createOpenClawAgentDatabasePathMatcher(); const discovery = schemas.agentDatabaseMigrationDiscovery?.discovery; const databaseTargets = discovery?.targets.filter((database) => !schemas.agentRefusals?.some((refusal) => normalizeAgentId(refusal.agentId) === normalizeAgentId(database.agentId) && refusal.paths.some((pathname) => samePath(pathname, database.path))) && !schemas.indeterminate.some((failure) => failure.kind === "agent" && (failure.path === database.path || discovery.sourceIdentities.get(failure.path)?.realPath === database.realPath))); const backups = await backupDoctorMigrationDatabases({ env: process.env, databasePaths: databaseTargets?.map((database) => database.path) ?? [], agentDatabaseTargets: databaseTargets, pendingDatabasePaths: schemas.pendingMigrations?.map((database) => database.path) ?? [], verifiedSnapshots }); for (const message of [...backups.changes, ...backups.warnings]) effectiveRuntime.log(message); } const stateSchemaPreparation = await prepareDoctorStateSchema(schemas, prompter.shouldRepair); const { repairDoctorAgentDeletionJournal } = await import("./doctor-agent-deletion-journal-Dgw7EByc.mjs"); const deletionJournal = await repairDoctorAgentDeletionJournal({ preflight: schemas, shouldRepair: prompter.shouldRepair, env: process.env }); for (const message of [...deletionJournal.changes, ...deletionJournal.warnings]) effectiveRuntime.log(message); if (deletionJournal.changes.length > 0) schemas = await prepareDoctorDatabasePreflight(); const { inspectDoctorSqliteNoCow } = await import("./doctor-sqlite-nocow-CughfiVR.mjs"); const { resolveOpenClawStateSqlitePath } = await import("./openclaw-state-db.paths-aljaknM8.mjs"); const nocow = inspectDoctorSqliteNoCow([resolveOpenClawStateSqlitePath(), ...schemas.agentDatabaseMigrationDiscovery?.discovery.targets.map((target) => target.path) ?? []]); sqliteNoCowPaths = nocow.paths; for (const message of nocow.notes) doctorRuntime.log(message); const { maybeRepairUiProtocolFreshness } = await import("./doctor-ui-Bj-8z-yS.mjs"); const { noteSourceInstallIssues } = await import("./doctor-install-CP2tvg7i.mjs"); const { noteBunCliLauncherIssues } = await import("./doctor-bun-cli-launcher-BmMyK0ew.mjs"); const { noteStalePluginRuntimeSymlinks } = await import("./plugin-runtime-symlinks-Epndzb1N.mjs"); const { noteStartupOptimizationHints } = await import("./doctor-platform-notes-C2KUiBfy.mjs"); await maybeRepairUiProtocolFreshness(doctorRuntime, prompter); await noteSourceInstallIssues(root); await noteBunCliLauncherIssues({ root, prompter }); await noteStalePluginRuntimeSymlinks(root); noteStartupOptimizationHints(); const discovery = schemas.agentDatabaseMigrationDiscovery; if (discovery && discovery.stateDir === preparedArchiveDiscovery?.stateDir) discovery.preparedTranscriptArchives = preparedArchiveDiscovery?.preparedTranscriptArchives; const { loadAndMaybeMigrateDoctorConfig } = await import("./doctor-config-flow-DFEVfFg2.mjs"); const configResult = await measureGatewayBootstrapStep("doctor.config-flow", () => loadAndMaybeMigrateDoctorConfig({ options, retiredStateAdmitted: true, stateSchemaPreparation, agentDatabaseMigrationDiscovery: schemas.agentDatabaseMigrationDiscovery, confirm: (p) => prompter.confirm(p), runtime: doctorRuntime, prompter })); const admissionSchemas = schemas.agentDatabaseMigrationDiscovery && schemas.agentDatabaseMigrationDiscovery.stateDir !== resolveStateDir() ? await prepareDoctorDatabasePreflight({ cfg: configResult.cfg }) : schemas; const recoveredPaths = new Set(configResult.stateMigrationStepReceipts?.flatMap((receipt) => receipt.id === "media-persistence" ? receipt.recoveredAgentDatabasePaths ?? [] : [])); const sourceIdentities = admissionSchemas.agentDatabaseMigrationDiscovery?.discovery.sourceIdentities; const agentDatabaseRefusals = (admissionSchemas.agentRefusals ?? []).filter((refusal) => !refusal.paths.every((pathname) => recoveredPaths.has(pathname) || recoveredPaths.has(sourceIdentities?.get(pathname)?.realPath ?? pathname))); recordAgentDatabaseAdmissions(agentDatabaseRefusals); const { CONFIG_PATH } = await import("./config/config.js"); const ctx = { runtime: doctorRuntime, options, prompter, configResult, cfg: configResult.cfg, cfgForPersistence: structuredClone(configResult.cfg), sourceConfigValid: configResult.sourceConfigValid ?? true, configPath: configResult.path ?? CONFIG_PATH, stateDirExistedAtStart, gatewayMaintenanceActive: maintenance !== void 0, agentDatabaseRefusals, updateWarnings: deletionJournal.warnings, preparedAgentCount: Math.max(admissionSchemas.agentDatabaseMigrationDiscovery?.configuredAgentDatabaseTargets.length ?? 0, admissionSchemas.agentDatabaseMigrationDiscovery?.registeredAgentDatabases.length ?? 0), runWithPluginMetadataSnapshot: configResult.runWithPluginMetadataSnapshot, invalidatePluginMetadataSnapshot: configResult.invalidatePluginMetadataSnapshot }; healthContext = ctx; const { runDoctorHealthContributions } = await import("./doctor-health-contributions-C7ikux4z.mjs"); await measureGatewayBootstrapStep("doctor.contributions", () => runDoctorHealthContributions(ctx)); if (recordConfigWriteRefusal(ctx)) return; if (maintenance) { const { validateDoctorExternalConfigForStartup } = await import("./doctor-external-config-jZDfqMi5.mjs"); if (!await validateDoctorExternalConfigForStartup(effectiveRuntime)) { exitCode = 1; return; } const { assertDoctorMaintenanceReady } = await import("./doctor-maintenance-inspection-Bzev9Eep.mjs"); if (!(await measureGatewayBootstrapStep("doctor.maintenance-ready", () => assertDoctorMaintenanceReady(ctx.cfg, process.env, effectiveRuntime.log, admissionSchemas.agentDatabaseMigrationDiscovery?.discovery.targets ?? []))).schemaPublicationDeferred) { sqliteReclamationAgents = admissionSchemas.agentDatabaseMigrationDiscovery?.discovery.targets ?? []; resumeCapture?.(); if (isTruthyEnvValue(process.env.OPENCLAW_DEBUG_PROXY_ENABLED)) { const { initializeDebugProxyCaptureAsync } = await import("./runtime-C1iR68W0.mjs"); await initializeDebugProxyCaptureAsync("cli"); } } const { repairGatewayMaintenanceStartupFailures } = await import("./gateway-boot-lifecycle-DQxCZyHx.mjs"); repairGatewayMaintenanceStartupFailures(); } return ctx; }; let ctx; let failure; try { ctx = await (maintenance ? maintenance.run(runChecks) : runChecks()); if (ctx && maintenance && options.repair === true && sqliteNoCowPaths.length > 0) { if (resolveDoctorRepairMode(options).updateInProgress && !isTruthyEnvValue(process.env["OPENCLAW_DOCTOR_SQLITE_NOCOW_REPAIR"])) effectiveRuntime.log("SQLite NOCOW repair deferred: the managed updater did not request the store rewrite in this run."); else await maintenance.repairSqliteNoCow(sqliteNoCowPaths); } if (ctx && maintenance && ctx.prompter.shouldRepair) { if (isDoctorUpdateRepairMode(ctx.prompter.repairMode) && sqliteReclamationAgents) await maintenance.enableSqliteReclamation(sqliteReclamationAgents); await maintenance.cleanupRetainedRuntimes(); } } catch (error) { failure = error; throw error; } finally { const activeMaintenance = maintenance; if (activeMaintenance) { const completed = ctx; await measureGatewayBootstrapStep("doctor.maintenance.finish", () => activeMaintenance.finish(completed?.cfg, completed ? async (nextConfig) => { const { writeDoctorGatewayConfig } = await import("./doctor-health-contribution-runners.gateway-CjOittMs.mjs"); return writeDoctorGatewayConfig(completed, nextConfig); } : void 0, failure)); } } if (!ctx || recordConfigWriteRefusal(ctx)) return; const pluginWarnings = []; if (diagnostics.length > 0) { const { collectPluginLoadHealthFindings } = await import("./doctor-workspace-status-BWfgSRXb.mjs"); const { renderStructuredHealthFindings } = await import("./doctor-health-contribution-CcJvLXy5.mjs"); const findings = collectPluginLoadHealthFindings(diagnostics); renderStructuredHealthFindings(ctx, findings); pluginWarnings.push(...findings.map((finding) => `${finding.checkId}: ${finding.message}`)); } const warnings = normalizeUpdatePostInstallDoctorWarnings([ ...pluginWarnings, ...ctx.configResult.warnings ?? [], ...maintenance?.warnings ?? [], ...(ctx.configResult.stateMigrationStepReceipts ?? []).flatMap((receipt) => receipt.outcome === "warning" || receipt.outcome === "skipped" || receipt.outcome === "deferred" ? receipt.warnings : []), ...ctx.postInstallDoctorResult?.warnings ?? [] ]); doctorResult = { ...ctx.postInstallDoctorResult ?? { status: "ok" }, ...warnings.length ? { warnings } : {}, ...maintenance?.failureFacts?.length ? { failureFacts: [...maintenance.failureFacts, ...ctx.postInstallDoctorResult?.failureFacts ?? []] } : {} }; if (updateResult && doctorResult.status === "advisory") { exitCode = 86; return; } if (pluginWarnings.length > 0) { outro$1("Doctor finished with plugin load errors."); if (options.nonInteractive && !isUpdateDoctorLintPass(process.env)) exitCode = 1; return; } } catch (error) { if (!maintenance && error instanceof DoctorMaintenanceRefusalError && error.refusal.kind === "deferred" && isDoctorUpdateRepairMode(resolveDoctorRepairMode(options))) { writeAuthority?.assertCurrent(); const { recordUpdateDoctorRefusal } = await import("./doctor-update-refusal-CSySjvCQ.mjs"); recordUpdateDoctorRefusal(error.message); effectiveRuntime.error(error.message); doctorResult = { status: "ok", warnings: [error.message], maintenanceRefusal: error.refusal }; const runId = process.env.OPENCLAW_UPDATE_RUN_ID?.trim(); if (!updateResult && runId) try { const { recordUpdateRunStep } = await import("./update-run-ledger-MI1l64NJ.mjs"); recordUpdateRunStep(runId, { step: "warning:doctor-maintenance", status: "completed", endedAtMs: Date.now(), detail: error.message }); } catch { effectiveRuntime.error("Doctor maintenance warning could not be saved to update history."); } outro$1("Doctor maintenance deferred; pending repairs remain unchanged."); exitCode = 0; return; } const { DoctorStateMigrationRefusalError } = await import("./state-migrations.messages-JeVUPL7d.mjs"); const refusalWarnings = error instanceof DoctorStateMigrationRefusalError ? error.failureFacts.map(formatUpdateFailureFact) : []; if (healthContext && refusalWarnings.length > 0) { const { recordDoctorHealthWarnings } = await import("./doctor-health-contribution-CcJvLXy5.mjs"); recordDoctorHealthWarnings(healthContext, [], refusalWarnings, { prepend: true }); } if (error instanceof DoctorStateMigrationRefusalError) { const { recordUpdateDoctorRefusal, resolveUpdateDoctorGitRecovery } = await import("./doctor-update-refusal-CSySjvCQ.mjs"); const recovery = await resolveUpdateDoctorGitRecovery({ root, stateRepaired: true }); if (recovery) { error.message += `\n${recovery.message}`; recordUpdateDoctorRefusal(error.message); } } const causes = collectNestedErrorCandidates(error); const { classifyDoctorMaintenanceRefusal } = await import("./doctor-maintenance-inspection-Bzev9Eep.mjs"); const maintenanceRefusal = classifyDoctorMaintenanceRefusal(error); const unsafeConfigWrite = causes.find((cause) => cause instanceof ConfigWritePostCommitError && cause.rollbackStatus !== "restored"); const schemaRefusal = causes.find((cause) => cause instanceof UpdateSchemaRefusalError); const refusalFacts = causes.flatMap((cause) => cause instanceof UpdateDoctorError || cause instanceof DoctorStateMigrationRefusalError ? cause.failureFacts : []); doctorResult = { status: "error", ...maintenanceRefusal.kind === "data-at-risk" ? { maintenanceRefusal } : {}, ...!healthContext && refusalWarnings.length > 0 ? { warnings: refusalWarnings } : {}, failureFacts: !unsafeConfigWrite && !schemaRefusal && refusalFacts.length > 0 ? refusalFacts : [createUpdateFailureFact({ check: unsafeConfigWrite ? "config-write" : schemaRefusal ? "database-schema-preflight" : "doctor", code: unsafeConfigWrite ? "rollback-state-unverified" : schemaRefusal?.code ?? "doctor-failed", message: unsafeConfigWrite ? `${unsafeConfigWrite.publication} config publication; rollback ${unsafeConfigWrite.rollbackStatus}. ${unsafeConfigWrite.message}` : schemaRefusal?.message ?? (error instanceof Error ? error.message : String(error)) })] }; if (maintenance && !(error instanceof DoctorStateMigrationRefusalError)) effectiveRuntime.error("Doctor could not complete maintenance. Check the reported service state and resolve the failure."); throw error; } finally { await measureGatewayBootstrapStep("doctor.maintenance.release", async () => { await maintenance?.release(); }); if (updateResult) await publishDoctorUpdateResult({ updateResult, doctorResult, healthContext, maintenance }); if (exitCode !== void 0) requestExit(effectiveRuntime, exitCode); } outro$1("Doctor complete."); } //#endregion export { runDoctorHealthFlow };