chore(status): clarify bootstrap file semantics

This commit is contained in:
HeMuling
2026-02-23 14:42:31 +08:00
committed by Peter Steinberger
parent c3b3065cc9
commit d0e008d460
5 changed files with 82 additions and 7 deletions

View File

@@ -58,7 +58,7 @@ describe("subagent registry persistence", () => {
const storePath = resolveSessionStorePath(tempStateDir, agentId);
const store = await readSessionStore(storePath);
store[params.sessionKey] = {
...(store[params.sessionKey] ?? {}),
...store[params.sessionKey],
sessionId: params.sessionId ?? `sess-${agentId}-${Date.now()}`,
updatedAt: params.updatedAt ?? Date.now(),
};

View File

@@ -0,0 +1,74 @@
import { describe, expect, it, vi } from "vitest";
import type { ProgressReporter } from "../../cli/progress.js";
import { buildStatusAllReportLines } from "./report-lines.js";
const diagnosisSpy = vi.hoisted(() => vi.fn(async () => {}));
vi.mock("./diagnosis.js", () => ({
appendStatusAllDiagnosis: diagnosisSpy,
}));
describe("buildStatusAllReportLines", () => {
it("renders bootstrap column using file-presence semantics", async () => {
const progress: ProgressReporter = {
setLabel: () => {},
setPercent: () => {},
tick: () => {},
done: () => {},
};
const lines = await buildStatusAllReportLines({
progress,
overviewRows: [{ Item: "Gateway", Value: "ok" }],
channels: {
rows: [],
details: [],
},
channelIssues: [],
agentStatus: {
agents: [
{
id: "main",
bootstrapPending: true,
sessionsCount: 1,
lastActiveAgeMs: 12_000,
sessionsPath: "/tmp/main-sessions.json",
},
{
id: "ops",
bootstrapPending: false,
sessionsCount: 0,
lastActiveAgeMs: null,
sessionsPath: "/tmp/ops-sessions.json",
},
],
},
connectionDetailsForReport: "",
diagnosis: {
snap: null,
remoteUrlMissing: false,
sentinel: null,
lastErr: null,
port: 18789,
portUsage: null,
tailscaleMode: "off",
tailscale: {
backendState: null,
dnsName: null,
ips: [],
error: null,
},
tailscaleHttpsUrl: null,
skillStatus: null,
channelsStatus: null,
channelIssues: [],
gatewayReachable: false,
health: null,
},
});
const output = lines.join("\n");
expect(output).toContain("Bootstrap file");
expect(output).toContain("PRESENT");
expect(output).toContain("ABSENT");
});
});

View File

@@ -121,11 +121,11 @@ export async function buildStatusAllReportLines(params: {
const agentRows = params.agentStatus.agents.map((a) => ({
Agent: a.name?.trim() ? `${a.id} (${a.name.trim()})` : a.id,
Bootstrap:
BootstrapFile:
a.bootstrapPending === true
? warn("PENDING")
? warn("PRESENT")
: a.bootstrapPending === false
? ok("OK")
? ok("ABSENT")
: "unknown",
Sessions: String(a.sessionsCount),
Active: a.lastActiveAgeMs != null ? formatTimeAgo(a.lastActiveAgeMs) : "unknown",
@@ -136,7 +136,7 @@ export async function buildStatusAllReportLines(params: {
width: tableWidth,
columns: [
{ key: "Agent", header: "Agent", minWidth: 12 },
{ key: "Bootstrap", header: "Bootstrap", minWidth: 10 },
{ key: "BootstrapFile", header: "Bootstrap file", minWidth: 14 },
{ key: "Sessions", header: "Sessions", align: "right", minWidth: 8 },
{ key: "Active", header: "Active", minWidth: 10 },
{ key: "Store", header: "Store", flex: true, minWidth: 34 },

View File

@@ -265,8 +265,8 @@ export async function statusCommand(
const agentsValue = (() => {
const pending =
agentStatus.bootstrapPendingCount > 0
? `${agentStatus.bootstrapPendingCount} bootstrapping`
: "no bootstraps";
? `${agentStatus.bootstrapPendingCount} bootstrap file${agentStatus.bootstrapPendingCount === 1 ? "" : "s"} present`
: "no bootstrap files";
const def = agentStatus.agents.find((a) => a.id === agentStatus.defaultId);
const defActive = def?.lastActiveAgeMs != null ? formatTimeAgo(def.lastActiveAgeMs) : "unknown";
const defSuffix = def ? ` · default ${def.id} active ${defActive}` : "";

View File

@@ -388,6 +388,7 @@ describe("statusCommand", () => {
expect(logs.some((l: string) => l.includes("Memory"))).toBe(true);
expect(logs.some((l: string) => l.includes("Channels"))).toBe(true);
expect(logs.some((l: string) => l.includes("WhatsApp"))).toBe(true);
expect(logs.some((l: string) => l.includes("bootstrap files"))).toBe(true);
expect(logs.some((l: string) => l.includes("Sessions"))).toBe(true);
expect(logs.some((l: string) => l.includes("+1000"))).toBe(true);
expect(logs.some((l: string) => l.includes("50%"))).toBe(true);