diff --git a/src/agents/subagent-registry.persistence.test.ts b/src/agents/subagent-registry.persistence.test.ts index 5558d77785e..1c3db23672f 100644 --- a/src/agents/subagent-registry.persistence.test.ts +++ b/src/agents/subagent-registry.persistence.test.ts @@ -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(), }; diff --git a/src/commands/status-all/report-lines.test.ts b/src/commands/status-all/report-lines.test.ts new file mode 100644 index 00000000000..5769bc0d41d --- /dev/null +++ b/src/commands/status-all/report-lines.test.ts @@ -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"); + }); +}); diff --git a/src/commands/status-all/report-lines.ts b/src/commands/status-all/report-lines.ts index 71dc035ad84..0db503002bd 100644 --- a/src/commands/status-all/report-lines.ts +++ b/src/commands/status-all/report-lines.ts @@ -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 }, diff --git a/src/commands/status.command.ts b/src/commands/status.command.ts index a613f0896ee..e78faa4cc38 100644 --- a/src/commands/status.command.ts +++ b/src/commands/status.command.ts @@ -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}` : ""; diff --git a/src/commands/status.test.ts b/src/commands/status.test.ts index 4532acb3ea2..e628d79aa7d 100644 --- a/src/commands/status.test.ts +++ b/src/commands/status.test.ts @@ -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);