@sechroom/cli 2026.9.27-rc.1ea98ba09 → 2026.10.1-rc.8cc2a58bd

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 (2) hide show
  1. package/dist/index.js +140 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10171,6 +10171,21 @@ function snapshotGetNotFoundHint(includeAll, status) {
10171
10171
  }
10172
10172
 
10173
10173
  // src/commands/desk.ts
10174
+ function deskPacksRequest(opts) {
10175
+ const filter = opts.filter ?? "published";
10176
+ if (filter !== "published" && filter !== "work-layer")
10177
+ throw new Error('--filter must be "published" or "work-layer"');
10178
+ let pageSize;
10179
+ if (opts.pageSize !== void 0) {
10180
+ pageSize = Number(opts.pageSize);
10181
+ if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > 100)
10182
+ throw new Error(`--page-size must be a whole number from 1 to 100, got "${opts.pageSize}"`);
10183
+ }
10184
+ return {
10185
+ path: "/desk/packs",
10186
+ query: { filter, workspaceId: opts.workspaceId, cursor: opts.cursor, pageSize }
10187
+ };
10188
+ }
10174
10189
  function downloadRequestsRequest(opts) {
10175
10190
  if (opts.platform) {
10176
10191
  if (opts.take !== void 0 || opts.user !== void 0)
@@ -10195,6 +10210,7 @@ function downloadRequestsRequest(opts) {
10195
10210
  }
10196
10211
  function registerDesk(program2) {
10197
10212
  const desk = program2.command("desk").description("Sechroom Desk administration");
10213
+ registerDeskPacks(desk);
10198
10214
  const downloads = desk.command("downloads").description("Desk Downloads: which tenants see the page, and who requested which build").addHelpText(
10199
10215
  "after",
10200
10216
  `
@@ -10266,6 +10282,25 @@ Examples:
10266
10282
  registerDeskRooms(desk);
10267
10283
  registerDeskWorkspaces(desk);
10268
10284
  }
10285
+ function registerDeskPacks(desk) {
10286
+ desk.command("packs").description("Browse readable published context packs and visible Work Layer task packs").command("list").description("Page through readable Sechroom packs in this tenant (GET /desk/packs)").option("--filter <filter>", 'published or work-layer (default "published")').option("--workspace-id <id>", "limit Work Layer task packs to this workspace").option("--cursor <cursor>", "continue from the previous page").option("--page-size <n>", "rows per page, from 1 to 100 (default 50)").action(async (opts, cmd) => {
10287
+ let request;
10288
+ try {
10289
+ request = deskPacksRequest(opts);
10290
+ } catch (error) {
10291
+ fail(error);
10292
+ }
10293
+ const globals = cmd.optsWithGlobals();
10294
+ const cfg = resolveConfig(globals);
10295
+ const data = await runApi(
10296
+ "Listing Desk context packs",
10297
+ async () => (await makeClient(cfg)).GET("/desk/packs", {
10298
+ params: { query: request.query }
10299
+ })
10300
+ );
10301
+ emit(data, globals.json);
10302
+ });
10303
+ }
10269
10304
  function registerDeskRooms(desk) {
10270
10305
  const rooms = desk.command("rooms").description("Governed Desk rooms: which user a device is, and who may be invited").addHelpText(
10271
10306
  "after",
@@ -13043,6 +13078,110 @@ Note: CLI memory get omits relationships by default; MCP get_memory includes the
13043
13078
  });
13044
13079
  }
13045
13080
 
13081
+ // src/commands/retrieval.ts
13082
+ function parseWholeNumber(name, raw) {
13083
+ if (!/^\d+$/.test(raw.trim())) {
13084
+ fail(`${name} must be a non-negative whole number (got "${raw}").`);
13085
+ }
13086
+ const n = Number(raw);
13087
+ if (!Number.isSafeInteger(n) || n > 2147483647) {
13088
+ fail(`${name} is out of range (got "${raw}").`);
13089
+ }
13090
+ return n;
13091
+ }
13092
+ var MAX_SCOPE_PAGES = 8;
13093
+ function registerRetrieval(program2) {
13094
+ const memory = program2.commands.find((c) => c.name() === "memory") ?? program2.command("memory").description("Create, read, and search memories");
13095
+ memory.command("evidence <memoryId>").description(
13096
+ "Read a byte-exact span of a memory's text at an explicit version, with digests (GET /memories/{targetMemoryId}/evidence)"
13097
+ ).requiredOption(
13098
+ "--at <version>",
13099
+ "Required: 'latest' or a positive version number (no default, so a citation never comes from an implicit head)"
13100
+ ).option("--start <byte>", "Inclusive start byte (with --end)").option("--end <byte>", "Exclusive end byte (with --start); both on UTF-8 character boundaries").option("--include-archived", "Allow reading an archived memory", false).addHelpText(
13101
+ "after",
13102
+ `
13103
+ Offsets are BYTES of the UTF-8 text, not characters. Omit --start/--end for the whole text (refused above 64 KiB).
13104
+ --at is required. An exact version that is unavailable is refused; it never falls back to another version.
13105
+
13106
+ Examples:
13107
+ $ sechroom memory evidence mem_XXXX --at latest --json
13108
+ $ sechroom memory evidence mem_XXXX --at 3 --start 0 --end 120 --json`
13109
+ ).action(async (memoryId, opts, cmd) => {
13110
+ const cfg = resolveConfig(cmd.optsWithGlobals());
13111
+ if (opts.start == null !== (opts.end == null)) {
13112
+ fail("Provide both --start and --end, or neither.");
13113
+ }
13114
+ const query = {};
13115
+ query.version = String(opts.at);
13116
+ if (opts.start != null) {
13117
+ query.startByte = parseWholeNumber("--start", String(opts.start));
13118
+ query.endByte = parseWholeNumber("--end", String(opts.end));
13119
+ }
13120
+ if (opts.includeArchived) query.includeArchived = true;
13121
+ const data = await runApi("Reading evidence", async () => {
13122
+ const client = await makeClient(cfg);
13123
+ return client.GET("/memories/{targetMemoryId}/evidence", {
13124
+ params: { path: { targetMemoryId: memoryId }, query }
13125
+ });
13126
+ });
13127
+ emit(data, cmd.optsWithGlobals().json);
13128
+ });
13129
+ const scope = program2.command("scope").description("Navigate the authorised workspace/project scope");
13130
+ scope.command("ls").description("List the workspaces and projects you may see under a scope (GET /retrieval/scope)").option("--kind <kind>", "tenant (default), workspace, project or memories").option("--id <id>", "Workspace or project id (kind workspace/project)").option("--mode <mode>", "direct (default) or subtree").option("--memory-ids <ids>", "Comma-separated memory ids (kind memories, max 100)").option("--limit <n>", "Page size, 1 to 100 (default 50)").option("--cursor <token>", "Continuation token from the previous page").option("--include-archived", "Include archived nodes", false).option(
13131
+ "--all",
13132
+ `Follow continuations (up to ${MAX_SCOPE_PAGES} pages) and print one combined result`,
13133
+ false
13134
+ ).addHelpText(
13135
+ "after",
13136
+ `
13137
+ Hidden nodes are never named or counted; an id you cannot see is refused like one that does not exist.
13138
+ coverage.scopeExhausted=true with no continuation means the authorised scope is fully listed.
13139
+ A continuation is bound to you, this credential and the current authority state: if anything changes the read is
13140
+ refused (409 continuation_invalidated) and you restart it.
13141
+
13142
+ Examples:
13143
+ $ sechroom scope ls --json
13144
+ $ sechroom scope ls --kind workspace --id wsp_XXXX --mode subtree --all --json
13145
+ $ sechroom scope ls --kind memories --memory-ids mem_A,mem_B --json`
13146
+ ).action(async (opts, cmd) => {
13147
+ const cfg = resolveConfig(cmd.optsWithGlobals());
13148
+ const base = {};
13149
+ if (opts.kind) base.kind = String(opts.kind);
13150
+ if (opts.id) base.id = String(opts.id);
13151
+ if (opts.mode) base.mode = String(opts.mode);
13152
+ if (opts.memoryIds) base.memoryIds = String(opts.memoryIds);
13153
+ if (opts.limit != null) base.limit = parseWholeNumber("--limit", String(opts.limit));
13154
+ if (opts.includeArchived) base.includeArchived = true;
13155
+ const fetchPage = (cursor) => runApi("Listing scope", async () => {
13156
+ const client = await makeClient(cfg);
13157
+ return client.GET("/retrieval/scope", {
13158
+ params: { query: { ...base, ...cursor ? { cursor } : {} } }
13159
+ });
13160
+ });
13161
+ let page = await fetchPage(opts.cursor);
13162
+ if (!opts.all) {
13163
+ emit(page, cmd.optsWithGlobals().json);
13164
+ return;
13165
+ }
13166
+ const items = [...page.items];
13167
+ let pages = 1;
13168
+ while (page.continuation && pages < MAX_SCOPE_PAGES) {
13169
+ page = await fetchPage(page.continuation);
13170
+ items.push(...page.items);
13171
+ pages++;
13172
+ }
13173
+ emit(
13174
+ {
13175
+ ...page,
13176
+ items,
13177
+ coverage: { ...page.coverage, returned: items.length },
13178
+ pages
13179
+ },
13180
+ cmd.optsWithGlobals().json
13181
+ );
13182
+ });
13183
+ }
13184
+
13046
13185
  // src/setup/apply.ts
13047
13186
  import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
13048
13187
  import {
@@ -17558,6 +17697,7 @@ local: ${d.localPath ?? "(none)"} ${JSON.stringify(readLocalConfig())}
17558
17697
  });
17559
17698
  registerAccounts(program);
17560
17699
  registerMemory(program);
17700
+ registerRetrieval(program);
17561
17701
  registerLaneGrant(program);
17562
17702
  registerWorklog(program);
17563
17703
  registerFeedback(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sechroom/cli",
3
- "version": "2026.9.27-rc.1ea98ba09",
3
+ "version": "2026.10.1-rc.8cc2a58bd",
4
4
  "description": "Command-line interface for Sechroom — sign in, wire your AI tools, and work with your sechroom from the terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",