import {
formatUpdateAvailableHint,
formatUpdateOneLiner,
resolveUpdateAvailability,
} from "../../commands/status.update.js" ;
import { readConfigFileSnapshot } from "../../config/config.js" ;
import {
normalizeUpdateChannel,
resolveUpdateChannelDisplay,
} from "../../infra/update-channels.js" ;
import { checkUpdateStatus } from "../../infra/update-check.js" ;
import { defaultRuntime } from "../../runtime.js" ;
import { getTerminalTableWidth, renderTable } from "../../terminal/table.js" ;
import { theme } from "../../terminal/theme.js" ;
import { parseTimeoutMsOrExit, 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 = parseTimeoutMsOrExit(opts.timeout);
if (timeoutMs === null ) {
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 = resolveUpdateChannelDisplay({
configChannel,
installKind: update.installKind,
gitTag: update.git?.tag ?? null ,
gitBranch: update.git?.branch ?? null ,
});
const channelLabel = channelInfo.label;
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.writeJson({
update,
channel: {
value: channelInfo.channel,
source: channelInfo.source,
label: channelLabel,
config: configChannel,
},
availability: updateAvailability,
});
return ;
}
const tableWidth = getTerminalTableWidth();
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));
}
}
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-07)
¤
*© Formatika GbR, Deutschland