@bli-cockpit/cli 0.2.222 → 0.2.236

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.
Files changed (75) hide show
  1. package/dist/agent-plugins-converge.js +182 -0
  2. package/dist/agent-plugins.js +116 -0
  3. package/dist/autostart-darwin-plist.js +2 -2
  4. package/dist/autostart-windows-scripts.js +2 -2
  5. package/dist/commands/agent-door.js +35 -0
  6. package/dist/commands/approvals.js +3 -1
  7. package/dist/commands/brain.js +23 -0
  8. package/dist/commands/ci.js +23 -0
  9. package/dist/commands/docs-export.js +62 -0
  10. package/dist/commands/docs.js +3 -0
  11. package/dist/commands/doctor-access.js +2 -2
  12. package/dist/commands/doctor-agent-plugins.js +82 -0
  13. package/dist/commands/doctor-pipeline.js +2 -2
  14. package/dist/commands/doctor-report.js +1 -0
  15. package/dist/commands/doctor-update.js +2 -2
  16. package/dist/commands/doctor.js +6 -0
  17. package/dist/commands/drills-render.js +63 -0
  18. package/dist/commands/drills.js +152 -0
  19. package/dist/commands/hits.js +83 -0
  20. package/dist/commands/intentions.js +49 -0
  21. package/dist/commands/local-args-docs-export.js +23 -0
  22. package/dist/commands/local-args-tower-admin.js +8 -0
  23. package/dist/commands/local-args-tower-brain-ladder.js +90 -0
  24. package/dist/commands/local-args-tower-brain.js +11 -1
  25. package/dist/commands/local-args-tower-docs-msg.js +9 -3
  26. package/dist/commands/local-args-tower-drills.js +87 -0
  27. package/dist/commands/local-args-tower-hits.js +93 -0
  28. package/dist/commands/local-args-tower-intentions.js +70 -0
  29. package/dist/commands/local-args-tower-logs-search.js +51 -0
  30. package/dist/commands/local-args-tower-logs.js +3 -0
  31. package/dist/commands/local-args-tower-memory.js +67 -1
  32. package/dist/commands/local-args-tower-pages.js +3 -1
  33. package/dist/commands/local-args-tower-people.js +25 -0
  34. package/dist/commands/local-args-tower-usage.js +4 -4
  35. package/dist/commands/local-args-tower-who.js +36 -0
  36. package/dist/commands/local-args-tower.js +8 -1
  37. package/dist/commands/local-args.js +15 -1
  38. package/dist/commands/local-auth.js +5 -2
  39. package/dist/commands/local-command-shapes-auth.js +1 -0
  40. package/dist/commands/local-command-shapes-drills.js +7 -0
  41. package/dist/commands/local-command-shapes-hits.js +5 -0
  42. package/dist/commands/local-help-commands-tower-ops.js +123 -1
  43. package/dist/commands/local-help-commands-tower.js +19 -7
  44. package/dist/commands/local-help-commands.js +3 -0
  45. package/dist/commands/local-help.js +24 -4
  46. package/dist/commands/local-run-ops.js +11 -0
  47. package/dist/commands/local.js +16 -8
  48. package/dist/commands/logs-search.js +45 -0
  49. package/dist/commands/logs.js +3 -0
  50. package/dist/commands/memory-exam.js +47 -0
  51. package/dist/commands/memory-repeats.js +44 -0
  52. package/dist/commands/memory-search-print.js +95 -0
  53. package/dist/commands/memory-source.js +39 -0
  54. package/dist/commands/memory-store.js +18 -30
  55. package/dist/commands/memory-verb-list.js +7 -2
  56. package/dist/commands/notes-reads.js +20 -0
  57. package/dist/commands/notes-writes.js +24 -0
  58. package/dist/commands/notes.js +4 -2
  59. package/dist/commands/people.js +29 -0
  60. package/dist/commands/public-root.js +1 -1
  61. package/dist/commands/spend.js +79 -0
  62. package/dist/commands/sync-heal-agent-plugins.js +46 -0
  63. package/dist/commands/sync-heal.js +6 -0
  64. package/dist/commands/team.js +35 -0
  65. package/dist/commands/usage.js +9 -0
  66. package/dist/commands/who.js +36 -0
  67. package/dist/evidence-upload-direct.js +44 -0
  68. package/dist/evidence-upload-object.js +18 -4
  69. package/dist/evidence-upload-plan.js +1 -0
  70. package/dist/evidence-upload-transport.js +2 -0
  71. package/dist/local-state-config.js +21 -1
  72. package/dist/local-state.js +1 -1
  73. package/dist/process-runner.js +7 -3
  74. package/dist/state-dir-audit.js +1 -0
  75. package/package.json +4 -4
@@ -8,6 +8,10 @@
8
8
  * failed install retried hourly
9
9
  * sign-in lapsed record the ONE human written when the heartbeat
10
10
  * action, stop nagging could not renew, reported daily
11
+ * company plugin missing install it for Claude inspected every tick, a failed
12
+ * (BLI-18200) Code and Codex host retried every six hours,
13
+ * (sync-heal-agent- an installed one refreshed daily
14
+ * plugins.ts)
11
15
  *
12
16
  * The rest of the table is already on the tick elsewhere: the CLI floor
13
17
  * (`sync-followups-self-update.ts`), the scheduler incl. an ABSENT one
@@ -23,6 +27,7 @@ import path from "node:path";
23
27
  import { redactedSyncErrorDetail, reportInstallEventsBestEffort, } from "./install-receipts.js";
24
28
  import { heartbeatRefusalStatus } from "./heartbeat-token.js";
25
29
  import { SIGN_IN_ACTION } from "../sign-in-action.js";
30
+ import { healAgentPlugins } from "./sync-heal-agent-plugins.js";
26
31
  import { inspectAgentRules, installAgentRules } from "../agent-rules.js";
27
32
  import { getCollectorRuntimePaths, readLocalCollectorConfig, readLocalCollectorSessionFile, toSessionReference, } from "../local-state.js";
28
33
  import { normalizeCollectionRoots } from "../root-normalization.js";
@@ -37,6 +42,7 @@ export async function runMachineHealAfterSync(command, io, dashboardUrl, options
37
42
  const events = [];
38
43
  for (const heal of [
39
44
  () => healAgentRules(command, paths, now),
45
+ () => healAgentPlugins(command, io, paths, now),
40
46
  () => noteSessionState(paths, heartbeatRefusalStatus(), now),
41
47
  ]) {
42
48
  try {
@@ -25,6 +25,8 @@ export async function runTeam(command, io) {
25
25
  const tower = await openTower("team", command, io);
26
26
  if (command.action.startsWith("github-login-"))
27
27
  return githubLogin(command, tower, io);
28
+ if (command.action.startsWith("timezone-"))
29
+ return timezone(command, tower, io);
28
30
  if (command.action === "members")
29
31
  return showMembers(command, tower, io);
30
32
  if (command.action === "invite")
@@ -272,6 +274,39 @@ async function githubLogin(command, tower, io) {
272
274
  `GitHub logins: ${[body.primary_login, ...(Array.isArray(body.extra_logins) ? body.extra_logins : [])].filter(Boolean).join(", ") || "none"}. History is preserved.`);
273
275
  return 0;
274
276
  }
277
+ /**
278
+ * `cockpit team timezone list|set` (BLI-19277). The server owns every rule: who
279
+ * may ask (super admin), how a person is found (the one identity resolver, exact
280
+ * after case folding) and what counts as an IANA zone. This only relays and words
281
+ * the answer, so a stale CLI can be wrong about wording and never about a zone.
282
+ */
283
+ async function timezone(command, tower, io) {
284
+ const setting = command.action === "timezone-set";
285
+ const result = await callTower(tower, { path: "/api/team/timezones", method: setting ? "PUT" : "GET", label: "team timezone",
286
+ ...(setting ? { body: { person: command.personRef, timezone: command.zone } } : {}) });
287
+ writeLine(io.stderr, `[team cli] timezone ${JSON.stringify({ action: setting ? "set" : "list", reason: result.ok ? "answered" : result.reason })}`);
288
+ if (!result.ok)
289
+ return writeCommandFailure(io, command.json, result);
290
+ const body = asRecord(result.body);
291
+ if (command.json) {
292
+ writeLine(io.stdout, JSON.stringify(body));
293
+ return 0;
294
+ }
295
+ if (setting) {
296
+ const name = String(body.display_name ?? command.personRef);
297
+ const before = String(body.before ?? "unknown");
298
+ const after = String(body.after ?? "unknown");
299
+ writeLine(io.stdout, body.changed === false ? `${name} already has ${after}. Nothing changed.` : `${name}: ${before} -> ${after}.`);
300
+ return 0;
301
+ }
302
+ const people = (Array.isArray(body.people) ? body.people : []).map(asRecord);
303
+ const width = Math.max(6, ...people.map(person => String(person.display_name ?? "").length));
304
+ for (const person of people) {
305
+ writeLine(io.stdout, `${String(person.display_name ?? "").padEnd(width)} ${String(person.timezone_label ?? "unknown").padEnd(24)}${person.active === false ? " (inactive)" : ""}`);
306
+ }
307
+ writeLine(io.stdout, `${people.length} people, ${String(body.unknown_count ?? 0)} with an unknown timezone.`);
308
+ return 0;
309
+ }
275
310
  async function changeGrant(command, tower, io) {
276
311
  const result = await callTower(tower, { path: "/api/team/grants", method: "POST", label: "team section grant",
277
312
  body: { person_id: command.targetUserId, section: command.section, level: command.level ?? "see", action: command.action } });
@@ -15,6 +15,8 @@ export async function runUsage(command, io) {
15
15
  query.set("groupBy", "task_type");
16
16
  if (command.byRepo)
17
17
  query.set("groupBy", "repo");
18
+ if (command.byClient)
19
+ query.set("groupBy", "client");
18
20
  if (command.until)
19
21
  query.set("until", command.until);
20
22
  if (command.includeAutomated)
@@ -43,6 +45,13 @@ export async function runUsage(command, io) {
43
45
  if (!answer.ok)
44
46
  return failAgentDoor(door, "[usage]", answer.reason, answer.detail);
45
47
  const body = answer.body;
48
+ // Ticket 19258: the client app split reads everyone and prints the door's own words (medians always with their N).
49
+ if (command.byClient) {
50
+ if (door.json)
51
+ return emitAgentDoor(door, answer.body);
52
+ writeLine(io.stdout, String(answer.body.text ?? ""));
53
+ return 0;
54
+ }
46
55
  if (command.person) {
47
56
  const email = command.person === "me" ? (await loadPairedSession("usage", command.homeDir)).email : command.person;
48
57
  if (!email)
@@ -0,0 +1,36 @@
1
+ import { askAgentDoor, emitAgentDoor, failAgentDoor, openAgentDoor } from "./agent-door.js";
2
+ import { writeLine } from "./cli-io.js";
3
+ const TAG = "[who cli]";
4
+ const READ_DEADLINE_MS = 30_000;
5
+ export async function runWho(command, io) {
6
+ let door;
7
+ try {
8
+ door = await openAgentDoor("who", command, io);
9
+ }
10
+ catch (error) {
11
+ const detail = error instanceof Error ? error.message : "this machine is not paired with Tower";
12
+ writeLine(io.stderr, `${TAG} refused ${JSON.stringify({ reason: "not_paired" })}`);
13
+ if (command.json)
14
+ writeLine(io.stdout, JSON.stringify({ ok: false, error: "not_paired", detail }));
15
+ else
16
+ writeLine(io.stderr, detail);
17
+ return 1;
18
+ }
19
+ const query = new URLSearchParams();
20
+ if (command.topic)
21
+ query.set("topic", command.topic);
22
+ if (command.layer)
23
+ query.set("layer", command.layer);
24
+ if (command.limit)
25
+ query.set("limit", String(command.limit));
26
+ const asked = query.toString();
27
+ const answer = await askAgentDoor(door, { path: asked ? `/api/who?${asked}` : "/api/who", method: "GET", label: "who", timeoutMs: READ_DEADLINE_MS });
28
+ if (!answer.ok)
29
+ return failAgentDoor(door, TAG, answer.reason, answer.detail);
30
+ const body = answer.body;
31
+ writeLine(io.stderr, `${TAG} answered ${JSON.stringify({ resolved_as: body.resolved_as, areas: body.areas.length, as_of: body.as_of })}`);
32
+ if (command.json)
33
+ return emitAgentDoor(door, body);
34
+ writeLine(io.stdout, body.text);
35
+ return 0;
36
+ }
@@ -0,0 +1,44 @@
1
+ import { encodeEvidenceBytes } from "@bli-cockpit/telemetry-core/evidence-storage-encoding";
2
+ import { noteSyncProgress } from "./sync-lock.js";
3
+ /** The signed capability is the only credential sent to Storage. Never log it,
4
+ * its query string, provider bodies, or thrown errors that might contain it. */
5
+ export async function putSignedChunk(options, signedUrl, bytes, uploadId, index) {
6
+ // Identical manifest + gzip framing to the server chunk route staging write.
7
+ const encoded = encodeEvidenceBytes(bytes);
8
+ console.error("[evidence-upload] chunk encoded for storage", JSON.stringify({
9
+ upload_id: uploadId, chunk_index: index, chunk_encoding: "gzip",
10
+ bytes_before: bytes.length, bytes_after: encoded.length,
11
+ }));
12
+ const attempts = options.maxAttemptsPerRequest ?? 3;
13
+ for (let attempt = 1; attempt <= attempts; attempt++) {
14
+ let status = 0;
15
+ try {
16
+ const response = await options.fetchImpl(signedUrl, {
17
+ method: "PUT", headers: { "Content-Type": "application/octet-stream", "x-upsert": "false" },
18
+ body: new Uint8Array(encoded), signal: AbortSignal.timeout(60_000), redirect: "error",
19
+ });
20
+ status = response.status;
21
+ await response.body?.cancel();
22
+ if (response.ok) {
23
+ noteSyncProgress();
24
+ log("signed_chunk_uploaded", uploadId, index, attempt, status);
25
+ return true;
26
+ }
27
+ log("signed_upload_refused", uploadId, index, attempt, status);
28
+ if (status < 500 && status !== 429)
29
+ return false;
30
+ }
31
+ catch {
32
+ log("signed_upload_network_failure", uploadId, index, attempt, status);
33
+ }
34
+ if (attempt < attempts)
35
+ await (options.sleep ?? sleep)(250 * attempt);
36
+ }
37
+ return false;
38
+ }
39
+ function log(reason, uploadId, index, attempt, status) {
40
+ console.error("[evidence-upload] direct chunk", JSON.stringify({
41
+ reason, upload_id: uploadId, chunk_index: index, attempt, http_status: status,
42
+ }));
43
+ }
44
+ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
@@ -1,3 +1,4 @@
1
+ import { putSignedChunk } from "./evidence-upload-direct.js";
1
2
  import { gzipSync } from "node:zlib";
2
3
  import { COMMIT_CRASHED_PLATFORM, RawEvidenceUploadCommitResponseSchema, isPermanentUploadFailure, } from "@bli-cockpit/telemetry-core";
3
4
  import { beginOneObject } from "./evidence-upload-terminal.js";
@@ -17,10 +18,11 @@ export async function uploadOneObject(options, entry, disposition, chunkSizeByte
17
18
  if (disposition.disposition === "conflict" || !disposition.upload_id) {
18
19
  return failedOutcome(entry.file, disposition.reason ?? "upload_conflict");
19
20
  }
20
- const chunked = await uploadObjectChunks(options, entry, disposition, chunkSizeBytes, objectKey);
21
+ const directChunks = [];
22
+ const chunked = await uploadObjectChunks(options, entry, disposition, chunkSizeBytes, objectKey, directChunks);
21
23
  if (!chunked.ok)
22
24
  return chunked.outcome;
23
- const committed = await commitUploadedObject(options, entry, disposition, objectKey, chunked.uploadedChunks);
25
+ const committed = await commitUploadedObject(options, entry, disposition, objectKey, chunked.uploadedChunks, directChunks);
24
26
  if (committed.reason !== "commit_failed_http_409_staging_missing_between_passes")
25
27
  return committed;
26
28
  if (restageAttempted)
@@ -37,7 +39,7 @@ export async function uploadOneObject(options, entry, disposition, chunkSizeByte
37
39
  }
38
40
  return retried;
39
41
  }
40
- async function uploadObjectChunks(options, entry, disposition, chunkSizeBytes, objectKey) {
42
+ async function uploadObjectChunks(options, entry, disposition, chunkSizeBytes, objectKey, directChunks) {
41
43
  const received = new Set(disposition.received_chunk_indexes);
42
44
  let uploadedChunks = 0;
43
45
  if (disposition.disposition === "already_committed" || disposition.commit_ready) {
@@ -47,6 +49,17 @@ async function uploadObjectChunks(options, entry, disposition, chunkSizeBytes, o
47
49
  if (received.has(index))
48
50
  continue;
49
51
  const chunk = entry.bytes.subarray(index * chunkSizeBytes, Math.min((index + 1) * chunkSizeBytes, entry.bytes.byteLength));
52
+ const offer = disposition.signed_uploads?.find(upload => upload.chunk_index === index);
53
+ if (offer && await putSignedChunk(options, offer.signed_url, chunk, disposition.upload_id, index)) {
54
+ directChunks.push({ chunk_index: index, byte_size: chunk.length,
55
+ chunk_hash_sha256: sha256(chunk) });
56
+ uploadedChunks += 1;
57
+ continue;
58
+ }
59
+ console.error("[evidence-upload] using chunk route", JSON.stringify({
60
+ reason: offer ? "signed_upload_refused_fallback" : "signed_upload_not_offered",
61
+ upload_id: disposition.upload_id, chunk_index: index,
62
+ }));
50
63
  const encodedChunk = gzipSync(chunk);
51
64
  console.error("[evidence-upload] chunk encoded", JSON.stringify({
52
65
  upload_id: disposition.upload_id, chunk_index: index, chunk_encoding: "gzip",
@@ -97,13 +110,14 @@ async function uploadObjectChunks(options, entry, disposition, chunkSizeBytes, o
97
110
  }
98
111
  return { ok: true, uploadedChunks };
99
112
  }
100
- async function commitUploadedObject(options, entry, disposition, objectKey, uploadedChunks) {
113
+ async function commitUploadedObject(options, entry, disposition, objectKey, uploadedChunks, directChunks) {
101
114
  const commit = await requestJson(options, "/api/ambient/evidence/upload/commit", {
102
115
  schema_version: "ambient-raw-evidence-upload-commit.v1",
103
116
  generated_at: options.generatedAt,
104
117
  provenance: options.provenance,
105
118
  upload_id: disposition.upload_id,
106
119
  object_key: objectKey,
120
+ ...(disposition.signed_uploads ? { direct_chunks: directChunks } : {}),
107
121
  });
108
122
  if (!commit.ok) {
109
123
  // The server can tell us this object will be refused again. Take its reason
@@ -225,6 +225,7 @@ export function readBeginDispositions(body) {
225
225
  upload_id: entry.upload_id ?? null,
226
226
  received_chunk_indexes: entry.received_chunk_indexes,
227
227
  commit_ready: entry.commit_ready === true,
228
+ signed_uploads: entry.signed_uploads,
228
229
  reason: entry.reason ?? null,
229
230
  raw_evidence_pointer_id: entry.raw_evidence_pointer_id,
230
231
  });
@@ -22,6 +22,8 @@ export async function requestJson(options, routePath, body) {
22
22
  headers: {
23
23
  "Authorization": `Bearer ${options.deviceToken}`,
24
24
  "Content-Type": "application/json",
25
+ ...(routePath.endsWith("/evidence/upload/begin")
26
+ ? { "x-tower-evidence-direct": "staged-gzip-v1" } : {}),
25
27
  },
26
28
  body: JSON.stringify(body),
27
29
  });
@@ -11,7 +11,27 @@ const localCollectorPackage = JSON.parse(readFileSync(new URL("../package.json",
11
11
  export const LOCAL_COLLECTOR_VERSION = typeof localCollectorPackage.version === "string"
12
12
  ? localCollectorPackage.version
13
13
  : "0.0.0";
14
- export const DEFAULT_DASHBOARD_URL = "https://bli-cockpit-dashboard.vercel.app";
14
+ export const DEFAULT_DASHBOARD_URL = "https://tower.buildlaunchiterate.ca";
15
+ /**
16
+ * The address every machine paired before 2026-10-14 saved. It stays live as an
17
+ * alias of the same deployment forever, so a saved config naming it keeps
18
+ * working untouched and counts as the default wherever the default is decided.
19
+ */
20
+ export const LEGACY_DASHBOARD_URL = "https://bli-cockpit-dashboard.vercel.app";
21
+ function dashboardUrlKey(value) {
22
+ return value.trim().replace(/\/+$/, "").toLowerCase();
23
+ }
24
+ /** True for either address of the production Tower; a staging or local URL is false. */
25
+ export function isDefaultDashboardUrl(value) {
26
+ const key = dashboardUrlKey(value);
27
+ return key === dashboardUrlKey(DEFAULT_DASHBOARD_URL) || key === dashboardUrlKey(LEGACY_DASHBOARD_URL);
28
+ }
29
+ /** Same dashboard, the two production addresses counted as one. */
30
+ export function sameDashboardUrl(a, b) {
31
+ if (isDefaultDashboardUrl(a) && isDefaultDashboardUrl(b))
32
+ return true;
33
+ return dashboardUrlKey(a) === dashboardUrlKey(b);
34
+ }
15
35
  /**
16
36
  * `cockpit install` — the one write that registers collection roots, because
17
37
  * widening an operator's boundary is a consent decision and nothing else may
@@ -36,7 +36,7 @@
36
36
  * `runtimeFiles`, or the repo tests stay green while the packed CLI breaks.
37
37
  */
38
38
  export { getCollectorRuntimePaths } from "./local-state-paths.js";
39
- export { DEFAULT_DASHBOARD_URL, ensureLocalCollectorConfig, installLocalCollector, LOCAL_COLLECTOR_VERSION, readLocalCollectorConfig, } from "./local-state-config.js";
39
+ export { DEFAULT_DASHBOARD_URL, ensureLocalCollectorConfig, installLocalCollector, isDefaultDashboardUrl, LEGACY_DASHBOARD_URL, LOCAL_COLLECTOR_VERSION, sameDashboardUrl, readLocalCollectorConfig, } from "./local-state-config.js";
40
40
  export { readLocalCollectorSessionFile, readLocalSessionReference, toSessionReference, } from "./local-state-session.js";
41
41
  export { logoutLocalCollector, pairLocalCollector, recordDeviceTokenExpiry, } from "./local-state-pairing.js";
42
42
  export { PairingCodeError, pairLocalCollectorViaLink, } from "./local-state-pairing-code.js";
@@ -35,12 +35,16 @@ export function createCapturedExecRunner(options = {}) {
35
35
  encoding: "utf8",
36
36
  env,
37
37
  windowsVerbatimArguments: invocation.windowsVerbatimArguments,
38
+ ...(runOptions?.timeoutMs ? { timeout: runOptions.timeoutMs } : {}),
38
39
  }, (error, stdout, stderr) => {
40
+ // A child ended by `timeoutMs` reports code 124, never a bare 1.
39
41
  const code = error == null
40
42
  ? 0
41
- : typeof error.code === "number"
42
- ? error.code
43
- : 1;
43
+ : error.killed === true && runOptions?.timeoutMs
44
+ ? 124
45
+ : typeof error.code === "number"
46
+ ? error.code
47
+ : 1;
44
48
  resolve({
45
49
  code,
46
50
  stdout: stdout ?? "",
@@ -55,6 +55,7 @@ export const STATE_DIR_RULES = [
55
55
  // tiny by construction; naming them keeps the unrecognised bucket meaning
56
56
  // "something nobody registered", not "something small we forgot".
57
57
  { name: "session-needs-login.json", match: "exact", class: "state", bound: "one small note, overwritten at most daily and removed when the sign-in is valid again (sync-heal.ts)" },
58
+ { name: "agent-plugins.json", match: "exact", class: "state", bound: "one small file, overwritten: per host the last install attempt, its failure label and the last daily refresh (agent-plugins-converge.ts, BLI-18200)" },
58
59
  { name: "autostart-uninstalled", match: "exact", class: "state", bound: "a zero-byte marker written by `cockpit autostart uninstall` and removed by install or doctor" },
59
60
  { name: "last-turn-trace.json", match: "exact", class: "state", bound: "one file, overwritten" },
60
61
  { name: "sync.lock", match: "exact", class: "state", bound: "lock file, removed when the tick ends" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bli-cockpit/cli",
3
- "version": "0.2.222",
3
+ "version": "0.2.236",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,9 +27,9 @@
27
27
  "test": "node dist/cli.js --help && node ../../scripts/assert-public-cli-routing.mjs && node ../../scripts/assert-public-cli-verb-help.mjs && node ../../scripts/assert-public-cli-surface-doors.mjs && node ../../scripts/assert-public-cli-runtime-files.mjs && node ../../scripts/assert-public-cli-exit-contract.mjs && node ../../scripts/assert-public-cli-no-fleet-posts.mjs && node ../../scripts/assert-public-cli-doctor-json.mjs && node ../../scripts/assert-public-package-pack.mjs --workspace=@bli-cockpit/cli"
28
28
  },
29
29
  "dependencies": {
30
- "@bli-cockpit/memory-mcp": "0.1.66",
31
- "@bli-cockpit/mcp": "0.1.129",
32
- "@bli-cockpit/telemetry-core": "0.1.75"
30
+ "@bli-cockpit/memory-mcp": "0.1.69",
31
+ "@bli-cockpit/mcp": "0.1.141",
32
+ "@bli-cockpit/telemetry-core": "0.1.76"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",