@bli-cockpit/cli 0.2.65 → 0.2.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -59,6 +59,7 @@ export const JARVIS_ANSWER_ENVELOPE_KEYS = [
|
|
|
59
59
|
"thread_id",
|
|
60
60
|
"trace_thread_id",
|
|
61
61
|
"proposal_id",
|
|
62
|
+
"next_action",
|
|
62
63
|
"degraded",
|
|
63
64
|
"degraded_reasons",
|
|
64
65
|
];
|
|
@@ -195,6 +196,7 @@ export function buildJarvisAnswerEnvelope(input) {
|
|
|
195
196
|
thread_id: input.thread ?? null,
|
|
196
197
|
trace_thread_id: input.traceThread ?? null,
|
|
197
198
|
proposal_id: input.proposalId ?? null,
|
|
199
|
+
next_action: input.nextAction ?? null,
|
|
198
200
|
degraded: reasons.length > 0,
|
|
199
201
|
degraded_reasons: reasons,
|
|
200
202
|
};
|
|
@@ -158,6 +158,9 @@ export async function sendOneTurn(context, prompt, io) {
|
|
|
158
158
|
revised: body.revised,
|
|
159
159
|
trace,
|
|
160
160
|
proposalId: body.proposalId,
|
|
161
|
+
// BLI-3787: the sentence beside it — what a person must do next when
|
|
162
|
+
// the arm proposed something, and when it refused instead.
|
|
163
|
+
nextAction: body.nextAction,
|
|
161
164
|
// BLI-3770: the door's own structured citations. Absent from a
|
|
162
165
|
// dashboard that predates it, and the envelope falls back to
|
|
163
166
|
// reading the answer's own `Source:` lines when it is.
|
|
@@ -254,7 +254,8 @@ export function localSubcommandHelp(command) {
|
|
|
254
254
|
"Trace lines arrive live while JARVIS works; pass --no-stream to wait for the whole answer in one piece instead.",
|
|
255
255
|
"--json writes one machine-readable response (including trace and model) to stdout; operational metadata stays on stderr. A --json run never streams fragments, whichever mode it is in.",
|
|
256
256
|
"A --json turn is treated as an AGENT surface: if it proposes a coding task, JARVIS answers with proposal_id and NOT the eight-character approval code, because a code a program can read is a code it could approve with. The person fetches the code themself — a Tower browser tab, their Slack DM, or an interactive `cockpit jarvis` — and hands it back. Pass --show-approval-code when a script really is driving a dispatch for a person; the run says on stderr that it did.",
|
|
257
|
-
"That object carries answer, sources (the Source: lines inside it), turn_id (pass it to --trace), thread_id (pass it to --thread), proposal_id
|
|
257
|
+
"That object carries answer, sources (the Source: lines inside it), turn_id (pass it to --trace), thread_id (pass it to --thread), proposal_id, next_action, degraded and degraded_reasons — the SAME shape the bli-tower MCP server's jarvis_ask tool returns, so a script and an agent read one contract. reply/thread/traceId/model/trace/latency are still there beside it and still mean what they always meant.",
|
|
258
|
+
"proposal_id carries the coding-arm proposal a turn made, and is null when it made none — including when the arm refused. next_action is the sentence that says which of those it was and what a PERSON has to do about it: fetch the approval code for that proposal (a Tower tab, their Slack DM, or their own interactive `cockpit jarvis`), or approve a refused one where a person reads. A null proposal_id is never on its own. Do not send a proposal_id back on a --json turn: this is the surface the code was withheld from, and reading it back is refused here.",
|
|
258
259
|
"A turn that outlives the dashboard's own ceiling is reported as turn_timed_out — an incomplete answer is never printed as a finished one.",
|
|
259
260
|
"The command uses the existing paired device identity. It cannot override the caller, team, role, or person scope.",
|
|
260
261
|
"A thread is SINGLE-WRITER: two turns in the same conversation at the same time can read each other, and one can answer the other's question. Your own terminal is one conversation, named main, and stays that way. A --json turn is a program's, so it gets a FRESH conversation per call unless --thread names one, and the answer's thread_id is the name it used — pass that back with --thread to continue it deliberately. On a --json turn, --thread main asks for the shared default nobody chose, so it is treated as naming nothing and a fresh conversation is minted anyway.",
|
|
@@ -15,7 +15,7 @@ export async function runCockpitCli(argv, io) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
if (command === "--version" || command === "-V" || command === "version") {
|
|
18
|
-
writeLine(io?.stdout ?? process.stdout, "0.2.
|
|
18
|
+
writeLine(io?.stdout ?? process.stdout, "0.2.67");
|
|
19
19
|
return 0;
|
|
20
20
|
}
|
|
21
21
|
|
package/dist/commands/status.js
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* pastes into Slack when something looks wrong. The `--json` payload is the
|
|
9
9
|
* machine contract and is byte-for-byte unchanged — `status-json-shape.test.ts`
|
|
10
10
|
* holds it to that.
|
|
11
|
+
*
|
|
12
|
+
* Two branches, one machine: a folder holding several repos prints a row each,
|
|
13
|
+
* a single repo prints the full block, and BOTH carry the setup receipt
|
|
14
|
+
* (BLI-3789) — it says whether this HOST is connected, which does not change
|
|
15
|
+
* with the folder you are standing in.
|
|
11
16
|
*/
|
|
12
17
|
import { readdir, stat } from "node:fs/promises";
|
|
13
18
|
import os from "node:os";
|
|
@@ -24,6 +29,18 @@ import { getCollectorRuntimePaths, inspectLocalCollectorStatus, readLocalCollect
|
|
|
24
29
|
import { normalizeCollectionRoots } from "../root-normalization.js";
|
|
25
30
|
export async function runStatus(command, io) {
|
|
26
31
|
const backfillCursor = await inspectBackfillCursor(command.homeDir);
|
|
32
|
+
// BLI-3731: "is this machine actually connected?" belongs beside "is it
|
|
33
|
+
// collecting?", and it is read back off the host rather than remembered.
|
|
34
|
+
// Refreshing here also keeps the heartbeat's cache warm without the 15-minute
|
|
35
|
+
// tick paying for the probe.
|
|
36
|
+
//
|
|
37
|
+
// BLI-3789: read it BEFORE the branch below, not after. The receipt is a fact
|
|
38
|
+
// about the MACHINE, so it cannot depend on whether the folder you happen to
|
|
39
|
+
// stand in holds one repo or six — and the multi-repo branch, which every
|
|
40
|
+
// agent machine takes, used to return before the receipt was ever built.
|
|
41
|
+
const setupReceipt = await refreshSetupReceipt(io, {
|
|
42
|
+
...(command.homeDir ? { homeDir: command.homeDir } : {}),
|
|
43
|
+
});
|
|
27
44
|
const worktrees = await discoverCommandWorktrees(command.repoRoot, { maxDepth: command.maxDepth, maxRepos: command.maxRepos, homeDir: command.homeDir }, io);
|
|
28
45
|
if (worktrees.length > 1) {
|
|
29
46
|
const statuses = await Promise.all(worktrees.map(async (worktree) => ({
|
|
@@ -34,7 +51,17 @@ export async function runStatus(command, io) {
|
|
|
34
51
|
head_sha: worktree.head_sha,
|
|
35
52
|
})));
|
|
36
53
|
if (command.json) {
|
|
37
|
-
writeLine(io.stdout, JSON.stringify({
|
|
54
|
+
writeLine(io.stdout, JSON.stringify({
|
|
55
|
+
mode: "multi_repo",
|
|
56
|
+
statuses,
|
|
57
|
+
backfill_cursor: backfillCursor,
|
|
58
|
+
// Beside `backfill_cursor`, and for the same reason: both are facts
|
|
59
|
+
// about this machine, so both sit at the top of the payload rather
|
|
60
|
+
// than once per repo row. Null means this run could not read the
|
|
61
|
+
// host — `refreshSetupReceipt` named the reason on stderr — never
|
|
62
|
+
// "this machine is not connected".
|
|
63
|
+
setup_receipt: setupReceipt?.receipt ?? null,
|
|
64
|
+
}, null, 2));
|
|
38
65
|
return 0;
|
|
39
66
|
}
|
|
40
67
|
writeLine(io.stdout, "Tower status — every repo below this folder");
|
|
@@ -42,16 +69,10 @@ export async function runStatus(command, io) {
|
|
|
42
69
|
for (const status of statuses) {
|
|
43
70
|
writeLine(io.stdout, `- ${status.repo_label ?? status.repo}/${status.worktree_label ?? "worktree"} · ${status.branch} · head:${shortSha(status.head_sha)} · ${status.upload_state}`);
|
|
44
71
|
}
|
|
72
|
+
writeConnectedBlock(io, setupReceipt);
|
|
45
73
|
return 0;
|
|
46
74
|
}
|
|
47
75
|
const status = await inspectLocalCollectorStatus(command);
|
|
48
|
-
// BLI-3731: "is this machine actually connected?" belongs beside "is it
|
|
49
|
-
// collecting?", and it is read back off the host rather than remembered.
|
|
50
|
-
// Refreshing here also keeps the heartbeat's cache warm without the 15-minute
|
|
51
|
-
// tick paying for the probe.
|
|
52
|
-
const setupReceipt = await refreshSetupReceipt(io, {
|
|
53
|
-
...(command.homeDir ? { homeDir: command.homeDir } : {}),
|
|
54
|
-
});
|
|
55
76
|
if (command.json) {
|
|
56
77
|
writeLine(io.stdout, JSON.stringify({
|
|
57
78
|
...status,
|
|
@@ -88,13 +109,22 @@ export async function runStatus(command, io) {
|
|
|
88
109
|
writeLine(io.stdout, `Stuck files: ${stuckEvidenceLine(status)}`);
|
|
89
110
|
for (const detail of status.details)
|
|
90
111
|
writeLine(io.stdout, `- ${detail}`);
|
|
112
|
+
writeConnectedBlock(io, setupReceipt);
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The receipt block, in the words `cockpit doctor` prints, from the one reader
|
|
117
|
+
* (BLI-3789). Both branches of `status` call this: a person standing in a
|
|
118
|
+
* parent folder is asking about the same machine as a person standing in one
|
|
119
|
+
* repo, and only one of them used to be told.
|
|
120
|
+
*/
|
|
121
|
+
function writeConnectedBlock(io, setupReceipt) {
|
|
91
122
|
writeLine(io.stdout, "Connected:");
|
|
92
123
|
for (const line of setupReceipt
|
|
93
124
|
? setupReceiptBlock(setupReceipt, { indent: " " })
|
|
94
125
|
: [" unknown — run `cockpit doctor` to read this machine."]) {
|
|
95
126
|
writeLine(io.stdout, line);
|
|
96
127
|
}
|
|
97
|
-
return 0;
|
|
98
128
|
}
|
|
99
129
|
/**
|
|
100
130
|
* Done, still working, or never started — and when it is still working, how
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.67",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@bli-cockpit/memory-mcp": "0.1.9",
|
|
31
|
-
"@bli-cockpit/mcp": "0.1.
|
|
31
|
+
"@bli-cockpit/mcp": "0.1.9",
|
|
32
32
|
"@bli-cockpit/telemetry-core": "0.1.30"
|
|
33
33
|
}
|
|
34
34
|
}
|