@bli-cockpit/cli 0.2.131 → 0.2.133
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/commands/local-args-tower-memory.js +63 -4
- package/dist/commands/local-command-shapes-memory.js +3 -3
- package/dist/commands/local-help-commands.js +7 -1
- package/dist/commands/memory-requeue.js +107 -0
- package/dist/commands/memory-store.js +13 -3
- package/dist/commands/public-root.js +1 -1
- package/dist/commands/usage.js +6 -1
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `cockpit memory search|save|update|forget|profile` —
|
|
3
|
-
* (BLI-4047; `profile` added by BLI-4533
|
|
2
|
+
* `cockpit memory search|save|update|forget|profile|consolidation|requeue` —
|
|
3
|
+
* the argument table (BLI-4047; `profile` added by BLI-4533, `consolidation`
|
|
4
|
+
* by BLI-4534, `requeue` by BLI-4539).
|
|
4
5
|
*
|
|
5
6
|
* BLI Memory was the one Tower surface with no command-line door: the browser
|
|
6
7
|
* had one, the `bli-memory` MCP server had one, and a person or a script at a
|
|
@@ -41,6 +42,7 @@ export const MEMORY_STORE_ACTIONS = new Set([
|
|
|
41
42
|
// write a memory. It runs no pass and changes nothing — the pass is a
|
|
42
43
|
// Railway cron; this is how a person or an agent asks what it did.
|
|
43
44
|
"consolidation",
|
|
45
|
+
"requeue",
|
|
44
46
|
]);
|
|
45
47
|
const ALLOWED_FLAGS = [
|
|
46
48
|
"--home",
|
|
@@ -56,6 +58,11 @@ const ALLOWED_FLAGS = [
|
|
|
56
58
|
"--file",
|
|
57
59
|
"--content-stdin",
|
|
58
60
|
"--reason",
|
|
61
|
+
"--since",
|
|
62
|
+
"--until",
|
|
63
|
+
"--source",
|
|
64
|
+
"--dry-run",
|
|
65
|
+
"--apply",
|
|
59
66
|
"--json",
|
|
60
67
|
];
|
|
61
68
|
const VALUE_FLAGS = [
|
|
@@ -69,6 +76,9 @@ const VALUE_FLAGS = [
|
|
|
69
76
|
"--alias",
|
|
70
77
|
"--file",
|
|
71
78
|
"--reason",
|
|
79
|
+
"--since",
|
|
80
|
+
"--until",
|
|
81
|
+
"--source",
|
|
72
82
|
];
|
|
73
83
|
export function parseMemoryStoreArgs(action, args) {
|
|
74
84
|
const values = parseNamedArgs(args, { allowedFlags: ALLOWED_FLAGS, valueFlags: VALUE_FLAGS });
|
|
@@ -89,8 +99,16 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
89
99
|
if (action !== "save" && (values.flags.has("--custom-id") || values.booleans.has("--extract"))) {
|
|
90
100
|
throw new Error("--custom-id and --extract only apply to memory save.");
|
|
91
101
|
}
|
|
92
|
-
if (action !== "forget" &&
|
|
93
|
-
throw new Error("--
|
|
102
|
+
if (action !== "forget" && values.booleans.has("--content-stdin")) {
|
|
103
|
+
throw new Error("--content-stdin only applies to memory forget.");
|
|
104
|
+
}
|
|
105
|
+
if (action !== "forget" && action !== "requeue" && values.flags.has("--reason")) {
|
|
106
|
+
throw new Error("--reason only applies to memory forget and memory requeue.");
|
|
107
|
+
}
|
|
108
|
+
if (action !== "requeue"
|
|
109
|
+
&& (values.flags.has("--since") || values.flags.has("--until") || values.flags.has("--source")
|
|
110
|
+
|| values.booleans.has("--dry-run") || values.booleans.has("--apply"))) {
|
|
111
|
+
throw new Error("--since, --until, --source, --dry-run and --apply only apply to memory requeue.");
|
|
94
112
|
}
|
|
95
113
|
if (values.flags.has("--file") && action !== "save" && action !== "update") {
|
|
96
114
|
throw new Error("--file only applies to memory save and memory update.");
|
|
@@ -106,6 +124,37 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
106
124
|
.filter((tag) => tag.length > 0),
|
|
107
125
|
json: values.booleans.has("--json"),
|
|
108
126
|
};
|
|
127
|
+
if (action === "requeue") {
|
|
128
|
+
// A window is REQUIRED. There is no requeue-everything: applying re-runs
|
|
129
|
+
// one model call per receipt, so the ceiling on a wrong filter is a bill.
|
|
130
|
+
if (rest.length > 0) {
|
|
131
|
+
throw new Error("memory requeue takes no words; name the window with --since and --until.");
|
|
132
|
+
}
|
|
133
|
+
const since = readInstant(values.flags.get("--since"), "--since");
|
|
134
|
+
if (!since) {
|
|
135
|
+
throw new Error("memory requeue needs --since <iso>, e.g. `cockpit memory requeue --since 2026-09-21T04:10:00Z --dry-run`.");
|
|
136
|
+
}
|
|
137
|
+
const until = readInstant(values.flags.get("--until"), "--until");
|
|
138
|
+
if (until && until < since)
|
|
139
|
+
throw new Error("--until is before --since; nothing could match.");
|
|
140
|
+
const source = optionalNonEmpty(values.flags.get("--source"));
|
|
141
|
+
if (source && source !== "hook" && source !== "harvest") {
|
|
142
|
+
throw new Error("--source is hook or harvest — the two values a receipt can carry.");
|
|
143
|
+
}
|
|
144
|
+
if (values.booleans.has("--dry-run") && values.booleans.has("--apply")) {
|
|
145
|
+
throw new Error("--dry-run and --apply are opposites; name one.");
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
...command,
|
|
149
|
+
action,
|
|
150
|
+
since,
|
|
151
|
+
until,
|
|
152
|
+
...(source ? { source: source } : {}),
|
|
153
|
+
// The safe question unless somebody typed otherwise.
|
|
154
|
+
dryRun: !values.booleans.has("--apply"),
|
|
155
|
+
reason: optionalNonEmpty(values.flags.get("--reason")),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
109
158
|
if (action === "profile") {
|
|
110
159
|
// A pure read of ONE container's compiled page. No positional: there is
|
|
111
160
|
// nothing to ask it, and a stray word would look like a query this verb
|
|
@@ -167,6 +216,16 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
167
216
|
reason: optionalNonEmpty(values.flags.get("--reason")),
|
|
168
217
|
};
|
|
169
218
|
}
|
|
219
|
+
/** An ISO instant, normalised, or a refusal naming the flag that was wrong. */
|
|
220
|
+
function readInstant(value, flag) {
|
|
221
|
+
if (value === undefined)
|
|
222
|
+
return undefined;
|
|
223
|
+
const parsed = Date.parse(value);
|
|
224
|
+
if (!Number.isFinite(parsed)) {
|
|
225
|
+
throw new Error(`${flag} must be an ISO instant like 2026-09-21T04:10:00Z.`);
|
|
226
|
+
}
|
|
227
|
+
return new Date(parsed).toISOString();
|
|
228
|
+
}
|
|
170
229
|
/** 1..20, the same window the MCP tool and the door both accept. */
|
|
171
230
|
function readLimit(value) {
|
|
172
231
|
if (value === undefined)
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*
|
|
11
11
|
* `memory` install / status / help — acts on THIS MACHINE, writing an
|
|
12
12
|
* MCP registration and three hooks into a home directory.
|
|
13
|
-
* `memory-store` search / save / update / forget
|
|
14
|
-
* `/api/memory/*`, the same doors the
|
|
15
|
-
* server and the browser call.
|
|
13
|
+
* `memory-store` search / save / update / forget / profile / requeue —
|
|
14
|
+
* acts on TOWER, over `/api/memory/*`, the same doors the
|
|
15
|
+
* `bli-memory` MCP server and the browser call.
|
|
16
16
|
* `memory-log` the agent-experience opinion, part local file part Tower.
|
|
17
17
|
*
|
|
18
18
|
* They are separate kinds rather than one widening `action` union because they
|
|
@@ -580,7 +580,7 @@ export function localSubcommandHelp(command) {
|
|
|
580
580
|
[
|
|
581
581
|
"memory",
|
|
582
582
|
[
|
|
583
|
-
"Usage: cockpit memory [search|save|update|forget|consolidation|install|status|log] [flags]",
|
|
583
|
+
"Usage: cockpit memory [search|save|update|forget|profile|consolidation|requeue|install|status|log] [flags]",
|
|
584
584
|
"",
|
|
585
585
|
"The STORE, over the same /api/memory/* doors the bli-memory MCP server calls:",
|
|
586
586
|
" search \"<question>\" [--container <tag>] [--limit 1..20] [--no-recent]",
|
|
@@ -593,10 +593,16 @@ export function localSubcommandHelp(command) {
|
|
|
593
593
|
" update <id> [--file <path>] replacement text on stdin; the old row is kept as history.",
|
|
594
594
|
" forget <id> [--reason <label>]",
|
|
595
595
|
" forget --content-stdin --container <tag> [--reason <label>] forget by exact text.",
|
|
596
|
+
" profile [--container <tag>] the compiled one-page briefing; a read, never a compile.",
|
|
596
597
|
" consolidation [--container <tag>] what the nightly tidy-up pass did.",
|
|
597
598
|
" Clusters looked at, edits by verb, refusals by reason, model and cost.",
|
|
598
599
|
" Read-only: the pass is a nightly cron, it never deletes a memory, and",
|
|
599
600
|
" report mode changes nothing on the shelf at all.",
|
|
601
|
+
" requeue --since <iso> [--until <iso>] [--source hook|harvest] [--reason <label>] [--apply]",
|
|
602
|
+
" puts finished extractions back in the queue after the store refused their",
|
|
603
|
+
" writes. Super admins only. A DRY RUN unless you pass --apply, because an",
|
|
604
|
+
" apply re-runs one model call per receipt. Nothing is ever deleted: each",
|
|
605
|
+
" row keeps its previous outcome under result.requeued_from.",
|
|
600
606
|
"Refusals keep the door's own label — needs_rls_client, unknown_memory,",
|
|
601
607
|
"already_superseded, no_match — and --json prints the door's answer unchanged.",
|
|
602
608
|
"",
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cockpit memory requeue` — put a window of extractions back (BLI-4539).
|
|
3
|
+
*
|
|
4
|
+
* The terminal twin of `POST /api/memory/requeue`, and the reason it exists at
|
|
5
|
+
* all: between 04:16Z and 11:36Z on 2026-09-21 every insert into the memory
|
|
6
|
+
* store that carried aliases was refused, 122 extraction receipts closed as if
|
|
7
|
+
* nothing were wrong, and putting them back took a one-off script somebody
|
|
8
|
+
* wrote by hand at a keyboard. The masked content sits on those rows for seven
|
|
9
|
+
* days; recovering it should be one command.
|
|
10
|
+
*
|
|
11
|
+
* Its own module rather than a sixth branch of `memory-store.ts`, because that
|
|
12
|
+
* file is already at the readability band and because this verb refuses
|
|
13
|
+
* different things from its five siblings: a window is required, the gate is
|
|
14
|
+
* super_admin, and the default is a DRY RUN.
|
|
15
|
+
*
|
|
16
|
+
* **A dry run is the default.** `--dry-run` is the safe question and an apply
|
|
17
|
+
* takes `--apply` explicitly. Applying re-runs one model call per receipt, so
|
|
18
|
+
* the shape of the mistake is somebody's bill, and a flag you have to type is
|
|
19
|
+
* the cheapest possible guard against it.
|
|
20
|
+
*
|
|
21
|
+
* **The door's own reason label reaches the terminal unchanged** —
|
|
22
|
+
* `since_required`, `window_inverted`, `source_unknown`, `reason_not_a_label`,
|
|
23
|
+
* `requeue_count_failed` — printed verbatim by `failAgentDoor`, never
|
|
24
|
+
* rephrased here.
|
|
25
|
+
*/
|
|
26
|
+
import { askAgentDoor, emitAgentDoor, failAgentDoor, openAgentDoor, } from "./agent-door.js";
|
|
27
|
+
import { writeLine } from "./cli-io.js";
|
|
28
|
+
const TAG = "[memory requeue cli]";
|
|
29
|
+
/** Long: the door walks up to twenty pages of receipts and writes each row on its own. */
|
|
30
|
+
const REQUEUE_DEADLINE_MS = 300_000;
|
|
31
|
+
export async function runMemoryRequeue(command, io) {
|
|
32
|
+
const door = await openAgentDoor("memory", command, io);
|
|
33
|
+
const answer = await askAgentDoor(door, {
|
|
34
|
+
path: "/api/memory/requeue",
|
|
35
|
+
method: "POST",
|
|
36
|
+
label: "memory requeue",
|
|
37
|
+
timeoutMs: REQUEUE_DEADLINE_MS,
|
|
38
|
+
body: {
|
|
39
|
+
since: command.since ?? "",
|
|
40
|
+
...(command.until ? { until: command.until } : {}),
|
|
41
|
+
...(command.reason ? { reason: command.reason } : {}),
|
|
42
|
+
...(command.source ? { source: command.source } : {}),
|
|
43
|
+
dryRun: command.dryRun,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
if (!answer.ok)
|
|
47
|
+
return failAgentDoor(door, TAG, answer.reason, answer.detail);
|
|
48
|
+
const body = answer.body;
|
|
49
|
+
// An HTTP 200 is not an answer. A dashboard that has not shipped this door
|
|
50
|
+
// yet renders its own 404 PAGE at 200 with an HTML body, and this verb
|
|
51
|
+
// printed `applied {matched: 0}` for it — a silent success over a route that
|
|
52
|
+
// does not exist, which is the exact shape of lie the whole ticket is about.
|
|
53
|
+
// Proven against production on 2026-09-21, before the door was deployed.
|
|
54
|
+
if (typeof body.matched !== "number") {
|
|
55
|
+
return failAgentDoor(door, TAG, "requeue_answer_unreadable", "Tower answered 200 with no requeue receipt in it. The usual cause is a dashboard that has not shipped POST /api/memory/requeue yet; nothing was requeued.");
|
|
56
|
+
}
|
|
57
|
+
// Counts and labels only: a receipt's content never enters a log line.
|
|
58
|
+
writeLine(door.io.stderr, `${TAG} ${body.dryRun ? "dry run" : "applied"} ${JSON.stringify({
|
|
59
|
+
since: command.since ?? "",
|
|
60
|
+
until: command.until ?? null,
|
|
61
|
+
source: command.source ?? null,
|
|
62
|
+
matched: body.matched ?? 0,
|
|
63
|
+
scanned: body.scanned ?? 0,
|
|
64
|
+
requeued: body.requeued ?? 0,
|
|
65
|
+
refused: body.refused ?? 0,
|
|
66
|
+
coverage: body.coverage ?? "unknown",
|
|
67
|
+
})}`);
|
|
68
|
+
if (door.json)
|
|
69
|
+
return emitAgentDoor(door, answer.body);
|
|
70
|
+
const matched = body.matched ?? 0;
|
|
71
|
+
if (matched === 0) {
|
|
72
|
+
// Silence is not an outage, and it is not a wrong filter either — say
|
|
73
|
+
// which one this is by naming the window that was asked about.
|
|
74
|
+
writeLine(door.io.stdout, `No finished extraction receipt is in that window (${command.since} → ${command.until ?? "now"}${command.source ? `, ${command.source} only` : ""}). Nothing to requeue; the receipts table answered.`);
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
writeLine(door.io.stdout, body.dryRun
|
|
78
|
+
? `${matched} receipt(s) would be requeued (${describeSplit(body.bySource)}).`
|
|
79
|
+
: `${body.requeued ?? 0} of ${matched} receipt(s) requeued (${describeSplit(body.bySource)}).`);
|
|
80
|
+
const reasons = describeSplit(body.byReason);
|
|
81
|
+
if (reasons)
|
|
82
|
+
writeLine(door.io.stdout, ` by reason: ${reasons}`);
|
|
83
|
+
if ((body.refused ?? 0) > 0) {
|
|
84
|
+
writeLine(door.io.stdout, ` ${body.refused} row(s) were refused — a drain claimed them between the read and the write, which is the conditional update doing its job.`);
|
|
85
|
+
}
|
|
86
|
+
if (body.coverage === "capped") {
|
|
87
|
+
writeLine(door.io.stdout, " The page ceiling stopped this run before the window ended. Run it again for the rest; nothing is lost.");
|
|
88
|
+
}
|
|
89
|
+
if (body.dryRun) {
|
|
90
|
+
writeLine(door.io.stdout, "");
|
|
91
|
+
writeLine(door.io.stdout, "Nothing was written. Add --apply to do it for real.");
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
writeLine(door.io.stdout, "");
|
|
95
|
+
writeLine(door.io.stdout, "They are queued again: the hourly sweep reruns the hook receipts and the harvest pass reserves the rest. The previous result is kept on each row under result.requeued_from.");
|
|
96
|
+
}
|
|
97
|
+
return 0;
|
|
98
|
+
}
|
|
99
|
+
/** `hook:104, harvest:18` — counts and labels, in the order the door sorted them. */
|
|
100
|
+
function describeSplit(split) {
|
|
101
|
+
if (!split)
|
|
102
|
+
return "";
|
|
103
|
+
return Object.entries(split)
|
|
104
|
+
.sort((left, right) => right[1] - left[1] || (left[0] < right[0] ? -1 : 1))
|
|
105
|
+
.map(([label, count]) => `${label}:${count}`)
|
|
106
|
+
.join(", ");
|
|
107
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `cockpit memory search|save|update|forget|profile` —
|
|
3
|
-
* (BLI-4047; `profile` added by BLI-4533
|
|
2
|
+
* `cockpit memory search|save|update|forget|profile|consolidation|requeue` —
|
|
3
|
+
* BLI Memory at a terminal (BLI-4047; `profile` added by BLI-4533,
|
|
4
|
+
* `consolidation` by BLI-4534 and `requeue` by BLI-4539, the last two running
|
|
5
|
+
* in `memory-consolidation.ts` and `memory-requeue.ts` next door).
|
|
4
6
|
*
|
|
5
7
|
* Memory was the one Tower surface with no command-line door. The browser had
|
|
6
8
|
* one, the `bli-memory` MCP server had four tools, and a person or a script
|
|
@@ -44,6 +46,7 @@ import { resolveContainerTag } from "@bli-cockpit/memory-mcp/dist/container-tag.
|
|
|
44
46
|
import { askAgentDoor, emitAgentDoor, failAgentDoor, openAgentDoor, } from "./agent-door.js";
|
|
45
47
|
import { isInteractiveStdin, readPipedText, writeLine } from "./cli-io.js";
|
|
46
48
|
import { runMemoryConsolidation } from "./memory-consolidation.js";
|
|
49
|
+
import { runMemoryRequeue } from "./memory-requeue.js";
|
|
47
50
|
import { readNoteFile } from "./notes-file.js";
|
|
48
51
|
const TAG = "[memory cli]";
|
|
49
52
|
const SEARCH_DEADLINE_MS = 60_000;
|
|
@@ -71,6 +74,10 @@ export async function runMemoryStore(command, io) {
|
|
|
71
74
|
// different shape, and is the only memory verb that is about the JOB
|
|
72
75
|
// rather than about a memory.
|
|
73
76
|
return runMemoryConsolidation(command, door);
|
|
77
|
+
case "requeue":
|
|
78
|
+
// Its own module too: a window-shaped, super-admin, dry-run-by-default
|
|
79
|
+
// verb that refuses nothing the others refuse (BLI-4539).
|
|
80
|
+
return runMemoryRequeue(command, io);
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
83
|
/**
|
|
@@ -138,7 +145,7 @@ export function runMemoryVerbList(io, json) {
|
|
|
138
145
|
ok: true,
|
|
139
146
|
noun: "memory",
|
|
140
147
|
machine_verbs: ["install", "status"],
|
|
141
|
-
store_verbs: ["search", "save", "update", "forget", "profile", "consolidation"],
|
|
148
|
+
store_verbs: ["search", "save", "update", "forget", "profile", "consolidation", "requeue"],
|
|
142
149
|
log_verbs: ["log"],
|
|
143
150
|
}));
|
|
144
151
|
return 0;
|
|
@@ -157,6 +164,9 @@ export function runMemoryVerbList(io, json) {
|
|
|
157
164
|
" the compiled one-page briefing every session opens with; a read, never a compile",
|
|
158
165
|
" cockpit memory consolidation [--container <tag>] [--json]",
|
|
159
166
|
" what the nightly tidy-up pass did: clusters, edits by verb, refusals, cost",
|
|
167
|
+
" cockpit memory requeue --since <iso> [--until <iso>] [--source hook|harvest] [--reason <label>] [--apply] [--json]",
|
|
168
|
+
" put a window of finished extractions back in the queue after the store refused",
|
|
169
|
+
" their writes; super admins only, and a DRY RUN unless you pass --apply",
|
|
160
170
|
"",
|
|
161
171
|
"This machine:",
|
|
162
172
|
" cockpit memory install [--dry-run] [--json] register the MCP server and the three hooks",
|
|
@@ -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.133");
|
|
19
19
|
return 0;
|
|
20
20
|
}
|
|
21
21
|
|
package/dist/commands/usage.js
CHANGED
|
@@ -101,8 +101,13 @@ export async function runUsage(command, io) {
|
|
|
101
101
|
writeLine(io.stdout, ` and ${repos.length - 10} more ${command.byTask ? "tasks" : command.byTopic ? "topics" : "repos"}`);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
// BLI-4554: the door sends the label, and the label carries the price
|
|
105
|
+
// sheet's version and date, so a figure on a terminal can be traced to the
|
|
106
|
+
// rates that produced it. The fallback is only reached against a dashboard
|
|
107
|
+
// deployed before that door existed, and says so rather than inventing a
|
|
108
|
+
// date it cannot know.
|
|
104
109
|
writeLine(io.stdout, "");
|
|
105
|
-
writeLine(io.stdout, body.api_list_price_equivalent_label ?? "API list-price equivalent
|
|
110
|
+
writeLine(io.stdout, body.api_list_price_equivalent_label ?? "API list-price equivalent, not actual spend (this dashboard sent no price-sheet version)");
|
|
106
111
|
writeLine(io.stdout, `${body.coverage?.sessions_extracted ?? 0} of ${body.coverage?.sessions_observed ?? 0} sessions extracted`);
|
|
107
112
|
// BLI-4356: the gap says why. A session observed with no tokens is either
|
|
108
113
|
// waiting on a count that has not run yet, or an automated one this view
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.133",
|
|
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.35",
|
|
31
|
-
"@bli-cockpit/mcp": "0.1.
|
|
31
|
+
"@bli-cockpit/mcp": "0.1.59",
|
|
32
32
|
"@bli-cockpit/telemetry-core": "0.1.48"
|
|
33
33
|
}
|
|
34
34
|
}
|