@bli-cockpit/cli 0.2.237 → 0.2.239
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/attribution-core-fallbacks.js +15 -11
- package/dist/adapters/attribution-core-score.js +111 -87
- package/dist/adapters/car-state.js +38 -35
- package/dist/adapters/claude-attribution-discovery.js +81 -56
- package/dist/adapters/claude-attribution-score.js +108 -94
- package/dist/adapters/claude-attribution-signals.js +52 -42
- package/dist/adapters/codex-attribution.js +42 -33
- package/dist/adapters/codex-session-signals.js +11 -9
- package/dist/adapters/git-state.js +56 -50
- package/dist/adapters/local-sources.js +52 -43
- package/dist/adapters/raw-evidence-git-diff.js +4 -2
- package/dist/adapters/raw-evidence-sanitize.js +15 -12
- package/dist/adapters/raw-evidence-transcript-file.js +32 -31
- package/dist/autostart-self-heal.js +18 -2
- package/dist/commands/agent-session-report.js +51 -59
- package/dist/commands/agent-setup-observed.js +30 -23
- package/dist/commands/agent-setup.js +96 -45
- package/dist/commands/autostart-heal.js +8 -2
- package/dist/commands/autostart-reading.js +3 -0
- package/dist/commands/backfill-evidence-outcomes.js +9 -6
- package/dist/commands/backfill-issues.js +3 -0
- package/dist/commands/backfill-scan.js +27 -22
- package/dist/commands/backfill-upload.js +69 -60
- package/dist/commands/backfill.js +26 -21
- package/dist/commands/brief-done.js +4 -1
- package/dist/commands/brief-edit.js +71 -46
- package/dist/commands/cal-detail.js +35 -0
- package/dist/commands/cal-direct.js +119 -0
- package/dist/commands/cal-overlay.js +73 -30
- package/dist/commands/cal.js +62 -25
- package/dist/commands/clean.js +4 -1
- package/dist/commands/docs-read.js +5 -2
- package/dist/commands/docs.js +38 -6
- package/dist/commands/doctor-backfill.js +88 -71
- package/dist/commands/doctor-pipeline.js +59 -46
- package/dist/commands/heartbeat-post.js +116 -0
- package/dist/commands/heartbeat-token-lock.js +46 -33
- package/dist/commands/heartbeat.js +43 -125
- package/dist/commands/install-update.js +17 -15
- package/dist/commands/issue-show.js +27 -28
- package/dist/commands/issue-versions.js +93 -0
- package/dist/commands/issue-write.js +70 -23
- package/dist/commands/issue.js +73 -37
- package/dist/commands/jarvis-live-answer.js +99 -0
- package/dist/commands/jarvis-render.js +1 -94
- package/dist/commands/jarvis-trace.js +30 -22
- package/dist/commands/jarvis-turn-report.js +124 -0
- package/dist/commands/jarvis-turn.js +108 -182
- package/dist/commands/jarvis.js +26 -17
- package/dist/commands/local-args-collector-setup.js +82 -84
- package/dist/commands/local-args-collector-work.js +37 -38
- package/dist/commands/local-args-tower-admin.js +155 -142
- package/dist/commands/local-args-tower-cal.js +69 -54
- package/dist/commands/local-args-tower-careers.js +73 -54
- package/dist/commands/local-args-tower-docs-msg.js +79 -51
- package/dist/commands/local-args-tower-github.js +26 -20
- package/dist/commands/local-args-tower-hits.js +32 -20
- package/dist/commands/local-args-tower-manager.js +85 -4
- package/dist/commands/local-args-tower-memory.js +139 -117
- package/dist/commands/local-args-tower-msg.js +24 -6
- package/dist/commands/local-args-tower-notes.js +346 -0
- package/dist/commands/local-args-tower-pages.js +100 -378
- package/dist/commands/local-args-tower-settings.js +28 -29
- package/dist/commands/local-args-tower-setup.js +11 -4
- package/dist/commands/local-args-tower-work.js +74 -37
- package/dist/commands/local-args.js +80 -129
- package/dist/commands/local-help-commands-tower-ops.js +15 -4
- package/dist/commands/local-help-commands-tower.js +20 -7
- package/dist/commands/local-help-commands.js +342 -341
- package/dist/commands/local-help.js +87 -83
- package/dist/commands/local-run-guards.js +100 -0
- package/dist/commands/local.js +137 -206
- package/dist/commands/login.js +13 -9
- package/dist/commands/logs.js +55 -38
- package/dist/commands/mail-attachments.js +44 -26
- package/dist/commands/manager-render-home.js +208 -0
- package/dist/commands/manager-render.js +7 -3
- package/dist/commands/manager-requests.js +33 -0
- package/dist/commands/manager.js +39 -5
- package/dist/commands/memory-consolidation.js +18 -9
- package/dist/commands/memory-daemon-probe.js +37 -28
- package/dist/commands/memory-install-config.js +64 -60
- package/dist/commands/memory-install.js +21 -41
- package/dist/commands/memory-requeue.js +26 -19
- package/dist/commands/memory-rules.js +26 -18
- package/dist/commands/memory-search-print.js +26 -0
- package/dist/commands/memory-store.js +14 -30
- package/dist/commands/memory-verb-list.js +49 -48
- package/dist/commands/msg-read-line.js +32 -0
- package/dist/commands/msg.js +45 -3
- package/dist/commands/notes-accounts.js +49 -32
- package/dist/commands/notes-sync-loop.js +115 -89
- package/dist/commands/notes-wisprflow-login.js +44 -23
- package/dist/commands/notes-writes.js +115 -100
- package/dist/commands/notes.js +33 -55
- package/dist/commands/onboard-flows.js +69 -51
- package/dist/commands/onboard.js +11 -9
- package/dist/commands/ops-render-memory.js +10 -7
- package/dist/commands/ops-render.js +33 -30
- package/dist/commands/ops.js +3 -0
- package/dist/commands/public-root.js +1 -1
- package/dist/commands/session-sync-outside-roots.js +40 -36
- package/dist/commands/session-sync-plan.js +14 -10
- package/dist/commands/session-sync-upload.js +24 -22
- package/dist/commands/session-sync.js +19 -8
- package/dist/commands/setup.js +13 -0
- package/dist/commands/slack.js +25 -16
- package/dist/commands/sources-check.js +13 -7
- package/dist/commands/sources-discovery.js +25 -17
- package/dist/commands/sources-verdict.js +19 -18
- package/dist/commands/speed.js +23 -19
- package/dist/commands/start.js +20 -16
- package/dist/commands/sync-doctor.js +52 -48
- package/dist/commands/sync.js +22 -16
- package/dist/commands/usage-telemetry-toml.js +71 -45
- package/dist/commands/usage.js +94 -68
- package/dist/commands/workbook-render.js +10 -7
- package/dist/evidence-reconcile-client.js +75 -64
- package/dist/evidence-redelivery-plan.js +37 -34
- package/dist/evidence-redelivery.js +32 -29
- package/dist/evidence-transcripts-client.js +20 -20
- package/dist/evidence-upload-object.js +86 -89
- package/dist/evidence-upload-plan.js +94 -83
- package/dist/evidence-upload-terminal.js +45 -50
- package/dist/image-description-session.js +156 -159
- package/dist/local-state-pairing-code.js +39 -31
- package/dist/local-state-status.js +9 -2
- package/dist/onboarding-roots.js +5 -8
- package/dist/process-runner.js +8 -8
- package/dist/raw-evidence-gc.js +33 -38
- package/dist/raw-evidence-stuck-summary.js +7 -14
- package/dist/repo-identity.js +26 -23
- package/dist/scheduled-self-update.js +11 -15
- package/dist/second-install.js +3 -0
- package/dist/slim/codex-rules.js +23 -36
- package/dist/spool/local-spool-parse.js +13 -12
- package/dist/sync-lock.js +5 -15
- package/dist/tower-client.js +36 -53
- package/dist/tower-stream.js +7 -24
- package/dist/upload-agent-artifacts.js +58 -64
- package/dist/upload-envelope-build.js +60 -59
- package/dist/upload-evidence-delivery-reconcile.js +58 -56
- package/dist/upload-evidence-delivery-summary.js +32 -34
- package/dist/upload-ingest-receipt.js +20 -23
- package/dist/upload-session-reports-queue.js +4 -1
- package/dist/upload-session-reports-wire.js +64 -68
- package/dist/upload-sync.js +171 -157
- package/package.json +4 -4
|
@@ -119,6 +119,40 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
119
119
|
const values = parseNamedArgs(args, { allowedFlags: ALLOWED_FLAGS, valueFlags: VALUE_FLAGS });
|
|
120
120
|
const rest = values.positionals.slice(1);
|
|
121
121
|
const containers = values.flagValues.get("--container") ?? [];
|
|
122
|
+
rejectFlagsThatDoNotBelongTo(action, values, containers, rest);
|
|
123
|
+
const command = {
|
|
124
|
+
kind: "memory-store",
|
|
125
|
+
homeDir: optionalNonEmpty(values.flags.get("--home")),
|
|
126
|
+
dashboardUrl: optionalUrl(values.flags.get("--dashboard-url")),
|
|
127
|
+
workspace: optionalNonEmpty(workRootFlagValue(values)),
|
|
128
|
+
containerTags: containers
|
|
129
|
+
.map((tag) => tag.trim())
|
|
130
|
+
.filter((tag) => tag.length > 0),
|
|
131
|
+
json: values.booleans.has("--json"),
|
|
132
|
+
};
|
|
133
|
+
if (action === "requeue")
|
|
134
|
+
return parseRequeueVerb(command, values, rest);
|
|
135
|
+
if (action === "profile")
|
|
136
|
+
return parseProfileVerb(command, rest);
|
|
137
|
+
if (action === "search")
|
|
138
|
+
return parseSearchVerb(command, values, rest);
|
|
139
|
+
if (action === "consolidation")
|
|
140
|
+
return { ...command, action };
|
|
141
|
+
if (action === "exam")
|
|
142
|
+
return parseExamVerb(command, values, rest);
|
|
143
|
+
if (action === "source")
|
|
144
|
+
return parseSourceVerb(command, values, rest);
|
|
145
|
+
if (action === "private" || action === "public" || action === "chain") {
|
|
146
|
+
return parseOneMemoryIdVerb(command, action, rest);
|
|
147
|
+
}
|
|
148
|
+
if (action === "save")
|
|
149
|
+
return parseSaveVerb(command, values, rest);
|
|
150
|
+
if (action === "update")
|
|
151
|
+
return parseUpdateVerb(command, values, rest);
|
|
152
|
+
return parseForgetVerb(command, values, rest);
|
|
153
|
+
}
|
|
154
|
+
/** Every flag is legal to the parser; this says which verb each one belongs to. */
|
|
155
|
+
function rejectFlagsThatDoNotBelongTo(action, values, containers, rest) {
|
|
122
156
|
if (action !== "search" && action !== "consolidation" && containers.length > 1) {
|
|
123
157
|
throw new Error(`memory ${action} takes at most one --container.`);
|
|
124
158
|
}
|
|
@@ -166,130 +200,118 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
166
200
|
if (values.flags.has("--file") && action !== "save" && action !== "update") {
|
|
167
201
|
throw new Error("--file only applies to memory save and memory update.");
|
|
168
202
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
containerTags: containers
|
|
176
|
-
.map((tag) => tag.trim())
|
|
177
|
-
.filter((tag) => tag.length > 0),
|
|
178
|
-
json: values.booleans.has("--json"),
|
|
179
|
-
};
|
|
180
|
-
if (action === "requeue") {
|
|
181
|
-
// A window is REQUIRED. There is no requeue-everything: applying re-runs
|
|
182
|
-
// one model call per receipt, so the ceiling on a wrong filter is a bill.
|
|
183
|
-
if (rest.length > 0) {
|
|
184
|
-
throw new Error("memory requeue takes no words; name the window with --since and --until.");
|
|
185
|
-
}
|
|
186
|
-
const since = readInstant(values.flags.get("--since"), "--since");
|
|
187
|
-
if (!since) {
|
|
188
|
-
throw new Error("memory requeue needs --since <iso>, e.g. `cockpit memory requeue --since 2026-09-21T04:10:00Z --dry-run`.");
|
|
189
|
-
}
|
|
190
|
-
const until = readInstant(values.flags.get("--until"), "--until");
|
|
191
|
-
if (until && until < since)
|
|
192
|
-
throw new Error("--until is before --since; nothing could match.");
|
|
193
|
-
const source = optionalNonEmpty(values.flags.get("--source"));
|
|
194
|
-
if (source && source !== "hook" && source !== "harvest") {
|
|
195
|
-
throw new Error("--source is hook or harvest — the two values a receipt can carry.");
|
|
196
|
-
}
|
|
197
|
-
if (values.booleans.has("--dry-run") && values.booleans.has("--apply")) {
|
|
198
|
-
throw new Error("--dry-run and --apply are opposites; name one.");
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
...command,
|
|
202
|
-
action,
|
|
203
|
-
since,
|
|
204
|
-
until,
|
|
205
|
-
...(source ? { source: source } : {}),
|
|
206
|
-
// The safe question unless somebody typed otherwise.
|
|
207
|
-
dryRun: !values.booleans.has("--apply"),
|
|
208
|
-
reason: optionalNonEmpty(values.flags.get("--reason")),
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
if (action === "profile") {
|
|
212
|
-
// A pure read of ONE container's compiled page. No positional: there is
|
|
213
|
-
// nothing to ask it, and a stray word would look like a query this verb
|
|
214
|
-
// silently ignored.
|
|
215
|
-
if (rest.length > 0) {
|
|
216
|
-
throw new Error("memory profile takes no words; it reads this repository's compiled page. Name another space with --container.");
|
|
217
|
-
}
|
|
218
|
-
return { ...command, action };
|
|
203
|
+
}
|
|
204
|
+
function parseRequeueVerb(command, values, rest) {
|
|
205
|
+
// A window is REQUIRED. There is no requeue-everything: applying re-runs
|
|
206
|
+
// one model call per receipt, so the ceiling on a wrong filter is a bill.
|
|
207
|
+
if (rest.length > 0) {
|
|
208
|
+
throw new Error("memory requeue takes no words; name the window with --since and --until.");
|
|
219
209
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
// search` and `cockpit cal find` already have.
|
|
224
|
-
const query = rest.join(" ").trim();
|
|
225
|
-
if (!query)
|
|
226
|
-
throw new Error("memory search needs a question, e.g. `cockpit memory search \"pagination rule\"`.");
|
|
227
|
-
// BLI-19246: both flags absent leaves the choice to the door (exact-detail questions reach the originals).
|
|
228
|
-
const includeOriginals = values.booleans.has("--include-originals") ? true : values.booleans.has("--no-originals") ? false : undefined;
|
|
229
|
-
// BLI-19255: the raw source behind the top hits; absent lets the door decide by the question.
|
|
230
|
-
const includeSource = values.booleans.has("--include-source") ? true : values.booleans.has("--no-source") ? false : undefined;
|
|
231
|
-
return {
|
|
232
|
-
...command, action, query, limit: readLimit(values.flags.get("--limit")), includeRecent: !values.booleans.has("--no-recent"),
|
|
233
|
-
...(includeOriginals === undefined ? {} : { includeOriginals }),
|
|
234
|
-
...(includeSource === undefined ? {} : { includeSource }),
|
|
235
|
-
};
|
|
210
|
+
const since = readInstant(values.flags.get("--since"), "--since");
|
|
211
|
+
if (!since) {
|
|
212
|
+
throw new Error("memory requeue needs --since <iso>, e.g. `cockpit memory requeue --since 2026-09-21T04:10:00Z --dry-run`.");
|
|
236
213
|
}
|
|
237
|
-
|
|
238
|
-
|
|
214
|
+
const until = readInstant(values.flags.get("--until"), "--until");
|
|
215
|
+
if (until && until < since)
|
|
216
|
+
throw new Error("--until is before --since; nothing could match.");
|
|
217
|
+
const source = optionalNonEmpty(values.flags.get("--source"));
|
|
218
|
+
if (source && source !== "hook" && source !== "harvest") {
|
|
219
|
+
throw new Error("--source is hook or harvest — the two values a receipt can carry.");
|
|
239
220
|
}
|
|
240
|
-
if (
|
|
241
|
-
|
|
242
|
-
throw new Error("memory exam takes no words: `cockpit memory exam [--night <YYYY-MM-DD>] [--misses] [--json]`.");
|
|
243
|
-
const night = optionalNonEmpty(values.flags.get("--night"));
|
|
244
|
-
if (night && !/^\d{4}-\d{2}-\d{2}$/.test(night))
|
|
245
|
-
throw new Error("--night must be a date like 2026-10-14.");
|
|
246
|
-
return { ...command, action, ...(night ? { night } : {}), misses: values.booleans.has("--misses") };
|
|
221
|
+
if (values.booleans.has("--dry-run") && values.booleans.has("--apply")) {
|
|
222
|
+
throw new Error("--dry-run and --apply are opposites; name one.");
|
|
247
223
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
224
|
+
return {
|
|
225
|
+
...command,
|
|
226
|
+
action: "requeue",
|
|
227
|
+
since,
|
|
228
|
+
until,
|
|
229
|
+
...(source ? { source: source } : {}),
|
|
230
|
+
// The safe question unless somebody typed otherwise.
|
|
231
|
+
dryRun: !values.booleans.has("--apply"),
|
|
232
|
+
reason: optionalNonEmpty(values.flags.get("--reason")),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function parseProfileVerb(command, rest) {
|
|
236
|
+
// A pure read of ONE container's compiled page. No positional: there is
|
|
237
|
+
// nothing to ask it, and a stray word would look like a query this verb
|
|
238
|
+
// silently ignored.
|
|
239
|
+
if (rest.length > 0) {
|
|
240
|
+
throw new Error("memory profile takes no words; it reads this repository's compiled page. Name another space with --container.");
|
|
260
241
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
242
|
+
return { ...command, action: "profile" };
|
|
243
|
+
}
|
|
244
|
+
function parseSearchVerb(command, values, rest) {
|
|
245
|
+
// Every remaining positional joined, so `cockpit memory search what did we
|
|
246
|
+
// decide about pagination` needs no quotes — the same shape `cockpit
|
|
247
|
+
// search` and `cockpit cal find` already have.
|
|
248
|
+
const query = rest.join(" ").trim();
|
|
249
|
+
if (!query)
|
|
250
|
+
throw new Error("memory search needs a question, e.g. `cockpit memory search \"pagination rule\"`.");
|
|
251
|
+
// BLI-19246: both flags absent leaves the choice to the door (exact-detail questions reach the originals).
|
|
252
|
+
const includeOriginals = values.booleans.has("--include-originals") ? true : values.booleans.has("--no-originals") ? false : undefined;
|
|
253
|
+
// BLI-19255: the raw source behind the top hits; absent lets the door decide by the question.
|
|
254
|
+
const includeSource = values.booleans.has("--include-source") ? true : values.booleans.has("--no-source") ? false : undefined;
|
|
255
|
+
return {
|
|
256
|
+
...command, action: "search", query, limit: readLimit(values.flags.get("--limit")), includeRecent: !values.booleans.has("--no-recent"),
|
|
257
|
+
...(includeOriginals === undefined ? {} : { includeOriginals }),
|
|
258
|
+
...(includeSource === undefined ? {} : { includeSource }),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function parseExamVerb(command, values, rest) {
|
|
262
|
+
if (rest.length > 0)
|
|
263
|
+
throw new Error("memory exam takes no words: `cockpit memory exam [--night <YYYY-MM-DD>] [--misses] [--json]`.");
|
|
264
|
+
const night = optionalNonEmpty(values.flags.get("--night"));
|
|
265
|
+
if (night && !/^\d{4}-\d{2}-\d{2}$/.test(night))
|
|
266
|
+
throw new Error("--night must be a date like 2026-10-14.");
|
|
267
|
+
return { ...command, action: "exam", ...(night ? { night } : {}), misses: values.booleans.has("--misses") };
|
|
268
|
+
}
|
|
269
|
+
function parseSourceVerb(command, values, rest) {
|
|
270
|
+
// BLI-19255: one memory, named by the id `cockpit memory search` printed; `--query` steers which part of the source.
|
|
271
|
+
const memoryId = optionalNonEmpty(rest[0]);
|
|
272
|
+
if (!memoryId)
|
|
273
|
+
throw new Error("memory source needs the memory id `cockpit memory search` printed.");
|
|
274
|
+
if (rest.length > 1)
|
|
275
|
+
throw new Error("memory source takes one id.");
|
|
276
|
+
const rawChars = values.flags.get("--chars");
|
|
277
|
+
const chars = rawChars === undefined ? undefined : Number(rawChars);
|
|
278
|
+
if (chars !== undefined && (!Number.isInteger(chars) || chars < 200 || chars > 6000))
|
|
279
|
+
throw new Error("--chars is a whole number from 200 to 6000.");
|
|
280
|
+
return { ...command, action: "source", memoryId, ...(values.flags.get("--query") ? { sourceQuery: values.flags.get("--query") } : {}), ...(chars === undefined ? {} : { sourceChars: chars }) };
|
|
281
|
+
}
|
|
282
|
+
function parseOneMemoryIdVerb(command, action, rest) {
|
|
283
|
+
// BLI-12927: one memory, named by the id `cockpit memory search` printed.
|
|
284
|
+
const memoryId = optionalNonEmpty(rest[0]);
|
|
285
|
+
if (!memoryId) {
|
|
286
|
+
throw new Error(`memory ${action} needs the memory id \`cockpit memory search\` printed.`);
|
|
270
287
|
}
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
customId: optionalNonEmpty(values.flags.get("--custom-id")),
|
|
279
|
-
...(values.flagValues.has("--alias") ? { aliases: values.flagValues.get("--alias") } : {}),
|
|
280
|
-
extract: values.booleans.has("--extract"),
|
|
281
|
-
filePath: optionalNonEmpty(values.flags.get("--file")),
|
|
282
|
-
};
|
|
288
|
+
if (rest.length > 1)
|
|
289
|
+
throw new Error(`memory ${action} takes one id.`);
|
|
290
|
+
return { ...command, action, memoryId };
|
|
291
|
+
}
|
|
292
|
+
function parseSaveVerb(command, values, rest) {
|
|
293
|
+
if (rest.length > 0) {
|
|
294
|
+
throw new Error("memory save reads the memory from stdin or --file, never from the command line: `echo \"...\" | cockpit memory save`.");
|
|
283
295
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
296
|
+
return {
|
|
297
|
+
...command,
|
|
298
|
+
action: "save",
|
|
299
|
+
customId: optionalNonEmpty(values.flags.get("--custom-id")),
|
|
300
|
+
...(values.flagValues.has("--alias") ? { aliases: values.flagValues.get("--alias") } : {}),
|
|
301
|
+
extract: values.booleans.has("--extract"),
|
|
302
|
+
filePath: optionalNonEmpty(values.flags.get("--file")),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
function parseUpdateVerb(command, values, rest) {
|
|
306
|
+
const memoryId = optionalNonEmpty(rest[0]);
|
|
307
|
+
if (!memoryId)
|
|
308
|
+
throw new Error("memory update needs the memory id `cockpit memory search` printed.");
|
|
309
|
+
if (rest.length > 1) {
|
|
310
|
+
throw new Error("memory update takes one id; the replacement text comes from stdin or --file, never from the command line.");
|
|
292
311
|
}
|
|
312
|
+
return { ...command, action: "update", memoryId, filePath: optionalNonEmpty(values.flags.get("--file")) };
|
|
313
|
+
}
|
|
314
|
+
function parseForgetVerb(command, values, rest) {
|
|
293
315
|
const memoryId = optionalNonEmpty(rest[0]);
|
|
294
316
|
if (rest.length > 1)
|
|
295
317
|
throw new Error("memory forget takes one id, or --content-stdin with a --container.");
|
|
@@ -302,7 +324,7 @@ export function parseMemoryStoreArgs(action, args) {
|
|
|
302
324
|
}
|
|
303
325
|
return {
|
|
304
326
|
...command,
|
|
305
|
-
action,
|
|
327
|
+
action: "forget",
|
|
306
328
|
memoryId,
|
|
307
329
|
contentStdin,
|
|
308
330
|
reason: optionalNonEmpty(values.flags.get("--reason")),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { optionalNonEmpty, optionalPositiveInteger, optionalUrl, parseNamedArgs } from "./local-arg-values.js";
|
|
2
|
-
const MSG_ACTIONS = new Set(["channels", "read", "send", "thread", "create", "dm", "show"]);
|
|
3
|
-
const MSG_ACTIONS_NEEDING_A_CHANNEL = new Set(["read", "send"]);
|
|
2
|
+
const MSG_ACTIONS = new Set(["channels", "read", "send", "thread", "create", "dm", "show", "unread"]);
|
|
3
|
+
const MSG_ACTIONS_NEEDING_A_CHANNEL = new Set(["read", "send", "unread"]);
|
|
4
4
|
/**
|
|
5
5
|
* `--members a@x.test,b@y.test` — addresses only, split on commas, never
|
|
6
6
|
* fuzzy (BLI-3749). The door resolves each one exactly, so a typo comes back
|
|
@@ -35,24 +35,40 @@ export function parseMsgArgs(args) {
|
|
|
35
35
|
"--private",
|
|
36
36
|
"--members",
|
|
37
37
|
"--description",
|
|
38
|
+
"--from",
|
|
39
|
+
"--mark-read",
|
|
38
40
|
"--json",
|
|
39
41
|
],
|
|
40
|
-
valueFlags: ["--home", "--dashboard-url", "--channel", "--thread", "--limit", "--members", "--description", "--before"],
|
|
42
|
+
valueFlags: ["--home", "--dashboard-url", "--channel", "--thread", "--limit", "--members", "--description", "--before", "--from"],
|
|
41
43
|
});
|
|
42
44
|
const { action, rest } = parseMsgAction(values.positionals);
|
|
43
45
|
if (values.flags.has("--before") && action !== "read" && action !== "thread") {
|
|
44
46
|
throw new Error("--before belongs to msg read or msg thread.");
|
|
45
47
|
}
|
|
48
|
+
const { markRead, unreadFrom } = parseMsgReadLineFlags(action, values);
|
|
46
49
|
const { channelName, dmEmail } = parseMsgCreateTarget(action, rest);
|
|
47
50
|
const { isPrivate, memberEmails, description } = parseMsgCreateFlags(action, values);
|
|
48
51
|
const { channelRef, threadId, limit } = parseMsgReadTarget(action, rest, values);
|
|
49
|
-
return buildMsgCommand(values, action, channelRef, channelName, dmEmail, memberEmails, description, isPrivate, threadId, limit);
|
|
52
|
+
return buildMsgCommand(values, action, channelRef, channelName, dmEmail, memberEmails, description, isPrivate, threadId, limit, markRead, unreadFrom);
|
|
53
|
+
}
|
|
54
|
+
/** `read --mark-read` and `unread --from <message-id>` (BLI-21299): the read line, moved on purpose. */
|
|
55
|
+
function parseMsgReadLineFlags(action, values) {
|
|
56
|
+
const markRead = values.booleans.has("--mark-read");
|
|
57
|
+
if (markRead && action !== "read")
|
|
58
|
+
throw new Error("--mark-read belongs to `cockpit msg read`.");
|
|
59
|
+
const unreadFrom = optionalNonEmpty(values.flags.get("--from"));
|
|
60
|
+
if (action === "unread" && !unreadFrom) {
|
|
61
|
+
throw new Error("msg unread needs --from <message-id>, e.g. `cockpit msg unread general --from <message-id>`.");
|
|
62
|
+
}
|
|
63
|
+
if (unreadFrom && action !== "unread")
|
|
64
|
+
throw new Error("--from belongs to `cockpit msg unread`.");
|
|
65
|
+
return { markRead, unreadFrom };
|
|
50
66
|
}
|
|
51
67
|
function parseMsgAction(positionals) {
|
|
52
68
|
const first = positionals[0];
|
|
53
69
|
const action = (first === undefined ? "channels" : first);
|
|
54
70
|
if (!MSG_ACTIONS.has(action)) {
|
|
55
|
-
throw new Error(`Unknown msg command: ${first}. Try channels, read, send, thread, create, dm, or show.`);
|
|
71
|
+
throw new Error(`Unknown msg command: ${first}. Try channels, read, unread, send, thread, create, dm, or show.`);
|
|
56
72
|
}
|
|
57
73
|
return { action, rest: positionals.slice(first === undefined ? 0 : 1) };
|
|
58
74
|
}
|
|
@@ -129,7 +145,7 @@ function parseMsgReadTarget(action, rest, values) {
|
|
|
129
145
|
}
|
|
130
146
|
return { channelRef, threadId, limit };
|
|
131
147
|
}
|
|
132
|
-
function buildMsgCommand(values, action, channelRef, channelName, dmEmail, memberEmails, description, isPrivate, threadId, limit) {
|
|
148
|
+
function buildMsgCommand(values, action, channelRef, channelName, dmEmail, memberEmails, description, isPrivate, threadId, limit, markRead, unreadFrom) {
|
|
133
149
|
return {
|
|
134
150
|
kind: "msg",
|
|
135
151
|
action,
|
|
@@ -144,6 +160,8 @@ function buildMsgCommand(values, action, channelRef, channelName, dmEmail, membe
|
|
|
144
160
|
isPrivate,
|
|
145
161
|
...(threadId ? { threadId } : {}),
|
|
146
162
|
...(limit === undefined ? {} : { limit }),
|
|
163
|
+
...(markRead ? { markRead } : {}),
|
|
164
|
+
...(unreadFrom ? { unreadFrom } : {}),
|
|
147
165
|
json: values.booleans.has("--json"),
|
|
148
166
|
};
|
|
149
167
|
}
|