mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
* Terminal: measure grapheme display width * Tests: cover grapheme terminal width * Terminal: wrap table cells by grapheme width * Tests: cover emoji table alignment * Terminal: refine table wrapping and width handling * Terminal: stop shrinking CLI tables by one column * Skills: use Terminal-safe emoji in list output * Changelog: note terminal skills table fixes * Skills: normalize emoji presentation across outputs * Terminal: consume unsupported escape bytes in tables
129 lines
3.6 KiB
TypeScript
129 lines
3.6 KiB
TypeScript
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.log(
|
|
JSON.stringify(
|
|
{
|
|
update,
|
|
channel: {
|
|
value: channelInfo.channel,
|
|
source: channelInfo.source,
|
|
label: channelLabel,
|
|
config: configChannel,
|
|
},
|
|
availability: updateAvailability,
|
|
},
|
|
null,
|
|
2,
|
|
),
|
|
);
|
|
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));
|
|
}
|
|
}
|