@bli-cockpit/cli 0.2.48 → 0.2.50
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.
- package/dist/adapters/raw-evidence-attribution-gaps.js +133 -0
- package/dist/adapters/raw-evidence-claude-reader.js +108 -0
- package/dist/adapters/raw-evidence-codex-reader.js +147 -0
- package/dist/adapters/raw-evidence-collection-state.js +199 -0
- package/dist/adapters/raw-evidence-facts.js +338 -0
- package/dist/adapters/raw-evidence-git-diff-reader.js +187 -0
- package/dist/adapters/raw-evidence-image-reader.js +107 -0
- package/dist/adapters/raw-evidence-sanitize.js +56 -0
- package/dist/adapters/raw-evidence-transcript-file.js +182 -0
- package/dist/adapters/raw-evidence.js +94 -1203
- package/dist/autostart-contract.js +79 -0
- package/dist/autostart-darwin-plist.js +265 -0
- package/dist/autostart-darwin.js +171 -0
- package/dist/autostart-windows-scripts.js +310 -0
- package/dist/autostart-windows-task-xml.js +260 -0
- package/dist/autostart-windows.js +237 -0
- package/dist/autostart-xml.js +23 -0
- package/dist/autostart.js +35 -1148
- package/dist/commands/agent-rules-command.js +55 -0
- package/dist/commands/agent-session-report.js +290 -0
- package/dist/commands/analyze.js +131 -0
- package/dist/commands/autostart-command.js +105 -0
- package/dist/commands/backfill-batches.js +34 -0
- package/dist/commands/backfill-candidates.js +54 -0
- package/dist/commands/backfill-checkpoint.js +101 -0
- package/dist/commands/backfill-command-line.js +70 -0
- package/dist/commands/backfill-evidence-outcomes.js +104 -0
- package/dist/commands/backfill-issues.js +265 -0
- package/dist/commands/backfill-output.js +75 -0
- package/dist/commands/backfill-plan.js +71 -0
- package/dist/commands/backfill-reasons.js +107 -0
- package/dist/commands/backfill-report.js +298 -0
- package/dist/commands/backfill-result.js +150 -0
- package/dist/commands/backfill-scan.js +274 -0
- package/dist/commands/backfill-scope.js +114 -0
- package/dist/commands/backfill-session-report.js +145 -0
- package/dist/commands/backfill-types.js +1 -0
- package/dist/commands/backfill-upload.js +212 -0
- package/dist/commands/backfill.js +58 -1705
- package/dist/commands/cli-io.js +13 -0
- package/dist/commands/doctor.js +57 -0
- package/dist/commands/jarvis-trace.js +184 -0
- package/dist/commands/jarvis.js +323 -7
- package/dist/commands/local-arg-values.js +169 -0
- package/dist/commands/local-args-collector.js +604 -0
- package/dist/commands/local-args-tower.js +891 -0
- package/dist/commands/local-args.js +10 -1549
- package/dist/commands/local-help.js +30 -5
- package/dist/commands/local.js +21 -1786
- package/dist/commands/login.js +53 -0
- package/dist/commands/logout.js +66 -0
- package/dist/commands/memory-install-claude.js +294 -0
- package/dist/commands/memory-install-codex.js +205 -0
- package/dist/commands/memory-install-contract.js +231 -0
- package/dist/commands/memory-install-files.js +63 -0
- package/dist/commands/memory-install-skills.js +121 -0
- package/dist/commands/memory-install-toml.js +265 -0
- package/dist/commands/memory-install.js +378 -0
- package/dist/commands/onboard-receipts.js +66 -0
- package/dist/commands/onboard-report.js +274 -0
- package/dist/commands/onboard.js +449 -0
- package/dist/commands/ops-render.js +36 -0
- package/dist/commands/public-root.js +1 -1
- package/dist/commands/serve.js +13 -0
- package/dist/commands/session-sync.js +513 -534
- package/dist/commands/settings-render.js +28 -0
- package/dist/commands/settings.js +66 -2
- package/dist/commands/start.js +47 -0
- package/dist/commands/sync-followups.js +308 -0
- package/dist/commands/sync.js +387 -0
- package/dist/local-state-attributed-target.js +75 -0
- package/dist/local-state-config.js +147 -0
- package/dist/local-state-files.js +59 -0
- package/dist/local-state-identity.js +73 -0
- package/dist/local-state-pairing.js +263 -0
- package/dist/local-state-paths.js +61 -0
- package/dist/local-state-session.js +68 -0
- package/dist/local-state-status.js +163 -0
- package/dist/local-state-work-context.js +190 -0
- package/dist/local-state.js +34 -848
- package/dist/tower-client.js +3 -2
- package/dist/tower-stream.js +76 -6
- package/package.json +2 -1
package/dist/tower-client.js
CHANGED
|
@@ -81,14 +81,15 @@ export async function towerRequest(options) {
|
|
|
81
81
|
};
|
|
82
82
|
try {
|
|
83
83
|
const response = await options.fetch(url, init);
|
|
84
|
+
const respondedMs = Date.now() - startedAt;
|
|
84
85
|
log(`[tower client] responded ${JSON.stringify({
|
|
85
86
|
request: options.label,
|
|
86
87
|
http_status: response.status,
|
|
87
88
|
content_type: response.headers.get("content-type") ?? "none",
|
|
88
89
|
streamed: (response.headers.get("content-type") ?? "").includes("application/x-ndjson"),
|
|
89
|
-
elapsed_ms:
|
|
90
|
+
elapsed_ms: respondedMs,
|
|
90
91
|
})}`);
|
|
91
|
-
return { ok: true, response };
|
|
92
|
+
return { ok: true, response, startedAt, respondedMs };
|
|
92
93
|
}
|
|
93
94
|
catch (error) {
|
|
94
95
|
const reason = isAbortError(error)
|
package/dist/tower-stream.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Reading a Tower turn as it happens (BLI-3457).
|
|
3
3
|
*
|
|
4
4
|
* The dashboard's conversation routes speak one JSON object per line
|
|
5
|
-
* (`application/x-ndjson`): `activity` events as tools start and settle,
|
|
6
|
-
*
|
|
5
|
+
* (`application/x-ndjson`): `activity` events as tools start and settle,
|
|
6
|
+
* `token` events carrying the answer as it is written (BLI-3517), then exactly
|
|
7
|
+
* one `final` event carrying what the plain JSON response used to be.
|
|
7
8
|
* That is the same wire format the browser already reads
|
|
8
9
|
* (`apps/dashboard/src/lib/webchat/tool-trace.ts`); this is the terminal's
|
|
9
10
|
* reader for it.
|
|
@@ -39,7 +40,7 @@ const CEILING_HINT_MS = 110_000;
|
|
|
39
40
|
* from a dashboard that does not stream yet (yielded as the final event, after
|
|
40
41
|
* a `stream_not_available` note).
|
|
41
42
|
*/
|
|
42
|
-
export async function* readTowerStream(response) {
|
|
43
|
+
export async function* readTowerStream(response, options = {}) {
|
|
43
44
|
const contentType = response.headers.get("content-type") ?? "";
|
|
44
45
|
if (!contentType.includes("application/x-ndjson")) {
|
|
45
46
|
yield* readPlainJsonBody(response);
|
|
@@ -48,6 +49,7 @@ export async function* readTowerStream(response) {
|
|
|
48
49
|
let buffer = "";
|
|
49
50
|
try {
|
|
50
51
|
for await (const chunk of iterateBody(response)) {
|
|
52
|
+
options.onBytes?.();
|
|
51
53
|
buffer += chunk;
|
|
52
54
|
const lines = buffer.split("\n");
|
|
53
55
|
buffer = lines.pop() ?? "";
|
|
@@ -89,7 +91,18 @@ export async function readTowerTurn(response, options = {}) {
|
|
|
89
91
|
const notes = [];
|
|
90
92
|
let streamed = true;
|
|
91
93
|
let final = null;
|
|
92
|
-
|
|
94
|
+
let draft = "";
|
|
95
|
+
let tokenFrames = 0;
|
|
96
|
+
let firstByteMs = null;
|
|
97
|
+
let firstFrameMs = null;
|
|
98
|
+
let firstTokenMs = null;
|
|
99
|
+
for await (const item of readTowerStream(response, {
|
|
100
|
+
onBytes: () => {
|
|
101
|
+
firstByteMs ??= Date.now() - startedAt;
|
|
102
|
+
},
|
|
103
|
+
})) {
|
|
104
|
+
if (item.kind === "event")
|
|
105
|
+
firstFrameMs ??= Date.now() - startedAt;
|
|
93
106
|
if (item.kind === "note") {
|
|
94
107
|
if (item.reason === "stream_not_available")
|
|
95
108
|
streamed = false;
|
|
@@ -101,10 +114,21 @@ export async function readTowerTurn(response, options = {}) {
|
|
|
101
114
|
final = item.event;
|
|
102
115
|
break;
|
|
103
116
|
}
|
|
117
|
+
if (item.event.type === "token") {
|
|
118
|
+
const text = item.event.text ?? "";
|
|
119
|
+
// The mark a person actually feels: the first frame with WORDS in it.
|
|
120
|
+
if (text)
|
|
121
|
+
firstTokenMs ??= Date.now() - startedAt;
|
|
122
|
+
tokenFrames += 1;
|
|
123
|
+
draft = item.event.reset ? text : draft + text;
|
|
124
|
+
options.onToken?.(item.event);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
104
127
|
activity.push(item.event);
|
|
105
128
|
options.onActivity?.(item.event);
|
|
106
129
|
}
|
|
107
130
|
const elapsedMs = Date.now() - startedAt;
|
|
131
|
+
const timing = { firstByteMs, firstFrameMs, firstTokenMs };
|
|
108
132
|
if (!final) {
|
|
109
133
|
// The last named note is the truest reason we have; absent one, a stream
|
|
110
134
|
// that simply stopped near the dashboard's ceiling is a timeout.
|
|
@@ -117,18 +141,64 @@ export async function readTowerTurn(response, options = {}) {
|
|
|
117
141
|
options.log?.(`[tower stream] turn incomplete ${JSON.stringify({
|
|
118
142
|
reason,
|
|
119
143
|
activity_events: activity.length,
|
|
144
|
+
token_frames: tokenFrames,
|
|
145
|
+
drafted_chars: draft.length,
|
|
120
146
|
notes: notes.length,
|
|
121
147
|
elapsed_ms: elapsedMs,
|
|
148
|
+
// BLI-3591: a turn that died still says how far it got — a stream that
|
|
149
|
+
// never produced a byte and one that produced words and then broke are
|
|
150
|
+
// different failures.
|
|
151
|
+
...turnTimingFields(timing),
|
|
122
152
|
})}`);
|
|
123
153
|
return { ok: false, reason, detail: streamFailureDetail(reason, terminal?.detail) };
|
|
124
154
|
}
|
|
125
155
|
options.log?.(`[tower stream] turn complete ${JSON.stringify({
|
|
126
156
|
streamed,
|
|
157
|
+
// BLI-3582: the dashboard's own split of the wait, relayed verbatim off
|
|
158
|
+
// the final frame — `wire_ms` (request accepted → first byte out),
|
|
159
|
+
// `prep_ms` (→ the model call started) and `model_ttft_ms` (→ its first
|
|
160
|
+
// token). All null against a dashboard that does not send them, which is
|
|
161
|
+
// a different fact from a turn that was instant.
|
|
162
|
+
...finalLatencyFields(final),
|
|
127
163
|
activity_events: activity.length,
|
|
164
|
+
// BLI-3517: zero token frames against a streaming dashboard means the
|
|
165
|
+
// answer arrived all at once — worth telling apart from a quiet turn.
|
|
166
|
+
token_frames: tokenFrames,
|
|
167
|
+
drafted_chars: draft.length,
|
|
128
168
|
notes: notes.length,
|
|
129
169
|
elapsed_ms: elapsedMs,
|
|
170
|
+
// BLI-3591: this side's own three marks, beside the dashboard's three
|
|
171
|
+
// above. `first_byte_ms` is the socket opening (the dashboard's flushed
|
|
172
|
+
// newline), `first_frame_ms` the first readable frame and
|
|
173
|
+
// `first_token_ms` the first WORDS — so the 1-2 s that used to sit
|
|
174
|
+
// unexplained between the dashboard's first token and the terminal's
|
|
175
|
+
// first visible character now has a number on each end of it.
|
|
176
|
+
...turnTimingFields(timing),
|
|
130
177
|
})}`);
|
|
131
|
-
return { ok: true, final, activity, streamed };
|
|
178
|
+
return { ok: true, final, activity, streamed, draft, timing };
|
|
179
|
+
}
|
|
180
|
+
/** The same three marks as log fields, snake_case like every other line here. */
|
|
181
|
+
export function turnTimingFields(timing) {
|
|
182
|
+
return {
|
|
183
|
+
first_byte_ms: timing.firstByteMs,
|
|
184
|
+
first_frame_ms: timing.firstFrameMs,
|
|
185
|
+
first_token_ms: timing.firstTokenMs,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The three latency spans off a final frame, as log fields (BLI-3582).
|
|
190
|
+
*
|
|
191
|
+
* Read defensively: this module knows the ENVELOPE, not the body, and a body
|
|
192
|
+
* shape that drifts must degrade to three nulls rather than a thrown turn.
|
|
193
|
+
*/
|
|
194
|
+
function finalLatencyFields(final) {
|
|
195
|
+
const raw = final["latency"];
|
|
196
|
+
const latency = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
197
|
+
const ms = (key) => {
|
|
198
|
+
const value = latency[key];
|
|
199
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
200
|
+
};
|
|
201
|
+
return { wire_ms: ms("wireMs"), prep_ms: ms("prepMs"), model_ttft_ms: ms("modelTtftMs") };
|
|
132
202
|
}
|
|
133
203
|
/** One plain sentence per way a turn can end without an answer. */
|
|
134
204
|
export function streamFailureDetail(reason, detail) {
|
|
@@ -207,7 +277,7 @@ function parseLine(line) {
|
|
|
207
277
|
return { kind: "note", reason: "unexpected_event_type" };
|
|
208
278
|
}
|
|
209
279
|
const type = parsed.type;
|
|
210
|
-
if (type !== "activity" && type !== "final") {
|
|
280
|
+
if (type !== "activity" && type !== "token" && type !== "final") {
|
|
211
281
|
return { kind: "note", reason: "unexpected_event_type" };
|
|
212
282
|
}
|
|
213
283
|
return { kind: "event", event: parsed };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.50",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"test": "node dist/cli.js --help && node ../../scripts/assert-public-cli-routing.mjs && node ../../scripts/assert-public-cli-runtime-files.mjs && node ../../scripts/assert-public-cli-no-fleet-posts.mjs && node ../../scripts/assert-public-package-pack.mjs --workspace=@bli-cockpit/cli"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@bli-cockpit/memory-mcp": "0.1.0",
|
|
30
31
|
"@bli-cockpit/telemetry-core": "0.1.26"
|
|
31
32
|
}
|
|
32
33
|
}
|