| import { |
| formatUpdateAvailableHint, |
| formatUpdateOneLiner, |
| resolveUpdateAvailability, |
| } from "../../commands/status.update.js"; |
| import { readConfigFileSnapshot } from "../../config/config.js"; |
| import { |
| formatUpdateChannelLabel, |
| normalizeUpdateChannel, |
| resolveEffectiveUpdateChannel, |
| } from "../../infra/update-channels.js"; |
| import { checkUpdateStatus } from "../../infra/update-check.js"; |
| import { defaultRuntime } from "../../runtime.js"; |
| import { renderTable } from "../../terminal/table.js"; |
| import { theme } from "../../terminal/theme.js"; |
| import { resolveUpdateRoot, type UpdateStatusOptions } from "./shared.js"; |
|
|
| function formatGitStatusLine(params: { |
| branch: string | null; |
| tag: string | null; |
| sha: string | null; |
| }): string { |
| const shortSha = params.sha ? params.sha.slice(0, 8) : null; |
| const branch = params.branch && params.branch !== "HEAD" ? params.branch : null; |
| const tag = params.tag; |
| const parts = [ |
| branch ?? (tag ? "detached" : "git"), |
| tag ? `tag ${tag}` : null, |
| shortSha ? `@ ${shortSha}` : null, |
| ].filter(Boolean); |
| return parts.join(" · "); |
| } |
|
|
| export async function updateStatusCommand(opts: UpdateStatusOptions): Promise<void> { |
| const timeoutMs = opts.timeout ? Number.parseInt(opts.timeout, 10) * 1000 : undefined; |
| if (timeoutMs !== undefined && (Number.isNaN(timeoutMs) || timeoutMs <= 0)) { |
| defaultRuntime.error("--timeout must be a positive integer (seconds)"); |
| defaultRuntime.exit(1); |
| return; |
| } |
|
|
| const root = await resolveUpdateRoot(); |
| const configSnapshot = await readConfigFileSnapshot(); |
| const configChannel = configSnapshot.valid |
| ? normalizeUpdateChannel(configSnapshot.config.update?.channel) |
| : null; |
|
|
| const update = await checkUpdateStatus({ |
| root, |
| timeoutMs: timeoutMs ?? 3500, |
| fetchGit: true, |
| includeRegistry: true, |
| }); |
|
|
| const channelInfo = resolveEffectiveUpdateChannel({ |
| configChannel, |
| installKind: update.installKind, |
| git: update.git ? { tag: update.git.tag, branch: update.git.branch } : undefined, |
| }); |
| const channelLabel = formatUpdateChannelLabel({ |
| channel: channelInfo.channel, |
| source: channelInfo.source, |
| gitTag: update.git?.tag ?? null, |
| gitBranch: update.git?.branch ?? null, |
| }); |
|
|
| const gitLabel = |
| update.installKind === "git" |
| ? formatGitStatusLine({ |
| branch: update.git?.branch ?? null, |
| tag: update.git?.tag ?? null, |
| sha: update.git?.sha ?? null, |
| }) |
| : null; |
|
|
| const updateAvailability = resolveUpdateAvailability(update); |
| const updateLine = formatUpdateOneLiner(update).replace(/^Update:\s*/i, ""); |
|
|
| if (opts.json) { |
| defaultRuntime.log( |
| JSON.stringify( |
| { |
| update, |
| channel: { |
| value: channelInfo.channel, |
| source: channelInfo.source, |
| label: channelLabel, |
| config: configChannel, |
| }, |
| availability: updateAvailability, |
| }, |
| null, |
| 2, |
| ), |
| ); |
| return; |
| } |
|
|
| const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1); |
| const installLabel = |
| update.installKind === "git" |
| ? `git (${update.root ?? "unknown"})` |
| : update.installKind === "package" |
| ? update.packageManager |
| : "unknown"; |
|
|
| const rows = [ |
| { Item: "Install", Value: installLabel }, |
| { Item: "Channel", Value: channelLabel }, |
| ...(gitLabel ? [{ Item: "Git", Value: gitLabel }] : []), |
| { |
| Item: "Update", |
| Value: updateAvailability.available ? theme.warn(`available · ${updateLine}`) : updateLine, |
| }, |
| ]; |
|
|
| defaultRuntime.log(theme.heading("OpenClaw update status")); |
| defaultRuntime.log(""); |
| defaultRuntime.log( |
| renderTable({ |
| width: tableWidth, |
| columns: [ |
| { key: "Item", header: "Item", minWidth: 10 }, |
| { key: "Value", header: "Value", flex: true, minWidth: 24 }, |
| ], |
| rows, |
| }).trimEnd(), |
| ); |
| defaultRuntime.log(""); |
|
|
| const updateHint = formatUpdateAvailableHint(update); |
| if (updateHint) { |
| defaultRuntime.log(theme.warn(updateHint)); |
| } |
| } |
|
|