openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
120 lines (119 loc) • 4.18 kB
JavaScript
import { r as defaultRuntime } from "./runtime-CF2WjnNZ.js";
import { r as theme } from "./theme-vjDs9tao.js";
import { t as UPDATE_RUN_PHASES } from "./update-run-vocabulary-BYZF4sMi.js";
import { i as getUpdateRun } from "./update-run-ledger-Dse_-g6v.js";
import { r as formatDurationPrecise } from "./format-duration-CeDWULoS.js";
import { n as renderUpdateRunReport, r as updateRunReportInputFromResult } from "./update-run-report-CEiRumC4.js";
import { spinner } from "@clack/prompts";
//#region src/cli/update-cli/progress.ts
const activeUpdateProgress = /* @__PURE__ */ new Map();
const UPDATE_PROGRESS_POLL_MS = 250;
function isAdvisoryStep(step) {
return step.advisory !== void 0;
}
/** Create a progress adapter for the updater runner without coupling runner code to terminal UI. */
function createUpdateProgress(enabled, run) {
if (!enabled) return {
progress: {},
stop: () => {},
dispose: () => {}
};
let currentSpinner = null;
let timer;
let currentPhase;
const seenPhases = /* @__PURE__ */ new Set();
const stop = () => {
currentSpinner?.clear();
currentSpinner = null;
};
const refresh = () => {
const record = run ? getUpdateRun(run.runId, { env: run.env }) : void 0;
if (!record) return;
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" && timer) {
clearTimeout(timer);
timer = void 0;
}
return record;
};
const flush = () => {
refresh();
stop();
};
const poll = () => {
timer = void 0;
if (refresh()?.status === "running") {
timer = setTimeout(poll, UPDATE_PROGRESS_POLL_MS);
timer.unref?.();
}
};
if (run) {
activeUpdateProgress.set(run.runId, flush);
poll();
}
return {
progress: {
onStepStart: (step) => {
flush();
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}...`);
},
onStepComplete: (step) => {
flush();
printStep(step);
}
},
stop,
dispose: () => {
flush();
if (timer) {
clearTimeout(timer);
timer = void 0;
}
if (run && activeUpdateProgress.get(run.runId) === flush) activeUpdateProgress.delete(run.runId);
}
};
}
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}`);
if (!isAdvisoryStep(step) && step.exitCode === 0) return;
const color = isAdvisoryStep(step) ? theme.warn : theme.error;
for (const output of [step.stdoutTail, step.stderrTail]) for (const line of (output ?? "").trimEnd().split("\n").slice(-10)) if (line.trim()) defaultRuntime.log(` ${color(line)}`);
}
function formatStepStatus(step) {
if (isAdvisoryStep(step)) return theme.warn("!");
if (step.exitCode === 0) return theme.success("✓");
if (step.exitCode === null) return theme.warn("?");
return theme.error("✗");
}
/** Render a completed updater run as JSON or terminal output. */
function printResult(result, opts, reportHints = {}) {
const run = result.runId ? getUpdateRun(result.runId, { env: opts.run?.env }) : void 0;
if (opts.json) {
defaultRuntime.writeJson({
...result,
...run ? { run } : {}
});
return;
}
if (result.runId) activeUpdateProgress.get(result.runId)?.();
const report = renderUpdateRunReport(run ?? updateRunReportInputFromResult(result), reportHints);
defaultRuntime.log("");
defaultRuntime.log(theme.heading(report.headline));
for (const line of report.lines) defaultRuntime.log(line);
}
//#endregion
export { printResult as n, createUpdateProgress as t };