UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

225 lines (224 loc) • 8.42 kB
import { r as defaultRuntime } from "./runtime-DlO3PTAd.mjs"; import { t as formatErrorMessage } from "./errors-O33D01XW.mjs"; import { h as StateDatabaseOfflineMaintenanceError, m as StateDatabaseAdmissionPendingError } from "./gateway-state-owner-DmHycK5o.mjs"; import { n as UPDATE_RUN_PHASES } from "./update-run-vocabulary-BuT3Q1bJ.mjs"; import { r as theme } from "./theme-DzaUZY4q.mjs"; import { o as toPublicUpdateRun, s as updateStepDiagnostics } from "./update-run-record-Cu3LgwJt.mjs"; import { r as isFailedUpdateStep } from "./update-run-step-BDxgGAu8.mjs"; import "./update-run-ledger-jBhhLo0P.mjs"; import { i as getUpdateRun, o as getUpdateRunForProgressAsync } from "./update-run-reader-B7x8dkVs.mjs"; import { r as formatUpdateDoctorLintFinding } from "./update-doctor-lint-kv_-CSRP.mjs"; import { r as formatDurationPrecise } from "./format-duration-BIQQYTeV.mjs"; import { t as formatUpdateFailureFact } from "./update-failure-facts-format-Uhxv535Y.mjs"; import { a as renderUpdateRunReport, c as updateRunReportInputFromResult } from "./update-run-report-C8yK_gib.mjs"; import { u as writeUpdateRunReportArtifact } from "./update-failure-report-artifact-DSFBsmLj.mjs"; import { spinner } from "@clack/prompts"; //#region src/cli/update-cli/progress.ts const activeUpdateProgress = /* @__PURE__ */ new Map(); const UPDATE_PROGRESS_POLL_MS = 250; const UPDATE_STEP_NOTICE_MS = 3e4; function isProgressMaintenanceContention(error) { if (error instanceof AggregateError) return error.errors.length > 0 && error.errors.every(isProgressMaintenanceContention); return error instanceof StateDatabaseAdmissionPendingError || error instanceof StateDatabaseOfflineMaintenanceError; } function readDisplayRecord(runId, env, source = "report") { try { return getUpdateRun(runId, { env }); } catch (error) { defaultRuntime.error(`Update ${source} history unavailable: ${formatErrorMessage(error)}`); return; } } function createUpdateProgress(enabled, run) { if (!enabled) return { progress: {}, stop: () => {}, suspend: () => {}, resume: () => {}, dispose: () => {} }; let currentSpinner = null; let timer; let stepNotice; let currentPhase; let currentRecord; let pendingRead; let polling = true; let observation = "active"; const seenPhases = /* @__PURE__ */ new Set(); const stop = () => { if (stepNotice) { clearInterval(stepNotice); stepNotice = void 0; } currentSpinner?.clear(); currentSpinner = null; }; const clearTimer = () => { if (timer) { clearTimeout(timer); timer = void 0; } }; const pausePolling = () => { polling = false; clearTimer(); pendingRead?.abort(); }; const renderRecord = (record) => { if (observation !== "active" || !run || !record) return; currentRecord = record; currentPhase = record.phase; for (const phase of UPDATE_RUN_PHASES) { const recorded = record.steps.some((step) => step.step === phase && step.status !== "pending"); if (!seenPhases.has(phase) && (recorded || phase === record.phase)) { seenPhases.add(phase); stop(); defaultRuntime.log(`Phase: ${phase}`); } } if (record.status !== "running") clearTimer(); }; const finalize = (record, terminal = record?.status !== "running") => { try { renderRecord(record); } finally { if (terminal) { observation = "disposed"; pausePolling(); if (run && activeUpdateProgress.get(run.runId)?.finish === finalize) activeUpdateProgress.delete(run.runId); } stop(); } }; const poll = async () => { timer = void 0; if (!polling || pendingRead || observation !== "active" || !run) return; const controller = new AbortController(); pendingRead = controller; try { const record = await getUpdateRunForProgressAsync(run.runId, { env: run.env }, controller.signal); if (!controller.signal.aborted) { if (!currentRecord || !record || record.updatedAtMs >= currentRecord.updatedAtMs) renderRecord(record); polling = record?.status === "running"; } } catch (error) { if (!controller.signal.aborted && !isProgressMaintenanceContention(error)) { polling = false; defaultRuntime.error(`Update progress history unavailable: ${formatErrorMessage(error)}`); } } finally { pendingRead = void 0; if (polling && observation === "active") { timer = setTimeout(() => void poll(), UPDATE_PROGRESS_POLL_MS); timer.unref?.(); } } }; if (run) { poll(); activeUpdateProgress.set(run.runId, { finish: finalize, pause: () => { pausePolling(); stop(); } }); } return { progress: { onStepStart: (step, record) => { finalize(record ?? currentRecord, false); const label = currentPhase ? `${currentPhase} — ${step.name}` : step.name; if (process.stdout.isTTY) { currentSpinner = spinner({ indicator: "timer" }); currentSpinner.start(theme.accent(label)); } else { defaultRuntime.log(`${label}...`); const startedAtMs = Date.now(); stepNotice = setInterval(() => { defaultRuntime.log(`${label} — still running (${formatDurationPrecise(Date.now() - startedAtMs)})`); }, UPDATE_STEP_NOTICE_MS); stepNotice.unref?.(); } }, onStepComplete: (step, record) => { finalize(record ?? currentRecord, false); printStep(step); } }, stop, suspend: () => { if (observation === "active") { observation = "suspended"; currentPhase = void 0; currentRecord = void 0; pausePolling(); stop(); } }, resume: () => { if (observation === "suspended") { observation = "active"; polling = true; poll(); } }, dispose: () => finalize(currentRecord, true) }; } function printStep(step) { const duration = theme.muted(`(${formatDurationPrecise(step.durationMs)})`); const termination = step.termination === "timeout" || step.termination === "no-output-timeout" ? " — timed out" : step.signal ? ` — interrupted (${step.signal})` : ""; defaultRuntime.log(` ${formatStepStatus(step)} ${step.name}${termination} ${duration}`); for (const finding of step.doctorLintFindings ?? []) defaultRuntime.log(` ${formatUpdateDoctorLintFinding(finding)}`); if (step.advisory === void 0 && !isFailedUpdateStep(step)) return; if (!step.advisory && step.failureFacts?.length) for (const fact of step.failureFacts) defaultRuntime.log(` ${theme.error(formatUpdateFailureFact(fact))}`); const color = step.advisory !== void 0 ? theme.warn : theme.error; if (step.advisory) defaultRuntime.log(` ${color(step.advisory.message)}`); const tails = step.advisory ? [step.stdoutTail, step.stderrTail] : updateStepDiagnostics(step).tails; for (const output of tails) for (const line of (output ?? "").trimEnd().split("\n").slice(step.termination === "signal" ? -80 : -10)) if (line.trim()) defaultRuntime.log(` ${color(line)}`); } function formatStepStatus(step) { return step.advisory ? theme.warn("!") : !isFailedUpdateStep(step) ? theme.success("✓") : step.exitCode === null ? theme.warn("?") : theme.error("✗"); } async function printResult(result, opts, reportHints = {}) { const finalizeProgress = result.runId ? activeUpdateProgress.get(result.runId) : void 0; finalizeProgress?.pause(); let run; let report; const readRun = result.runId && !reportHints.record && reportHints.readHistory !== false ? () => readDisplayRecord(result.runId, opts.run?.env) : void 0; const renderReport = (current) => { run = reportHints.record ?? current; finalizeProgress?.finish(run); report = renderUpdateRunReport(updateRunReportInputFromResult(result, run), { ...reportHints, mode: result.mode === "unknown" ? run?.target.kind : result.mode }); return report; }; const reportPath = await writeUpdateRunReportArtifact({ result, report: renderReport, readRun, env: opts.run?.env, detached: reportHints.readHistory === false }).catch((error) => { defaultRuntime.error(`Update report could not be saved: ${formatErrorMessage(error)}`); }); report ??= renderReport(readRun?.()); if (opts.json) { defaultRuntime.writeJson({ ...result, ...run ? { run: toPublicUpdateRun(run) } : {}, reportPath }); return; } defaultRuntime.log(""); defaultRuntime.log(theme.heading(report.headline)); if (reportPath) defaultRuntime.log(`Report: ${reportPath}`); for (const line of report.lines) defaultRuntime.log(line); } //#endregion export { printResult as n, createUpdateProgress as t };