@sixb/cli-core 0.1.9 → 0.2.0

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 (62) hide show
  1. package/README.md +21 -16
  2. package/dist/api-client.d.ts +1 -0
  3. package/dist/api-client.d.ts.map +1 -1
  4. package/dist/bin/sixb +26 -0
  5. package/dist/commands/data.d.ts +5 -0
  6. package/dist/commands/data.d.ts.map +1 -0
  7. package/dist/commands/files.d.ts.map +1 -1
  8. package/dist/commands/history.d.ts +7 -0
  9. package/dist/commands/history.d.ts.map +1 -0
  10. package/dist/commands/index.d.ts +1 -1
  11. package/dist/commands/index.d.ts.map +1 -1
  12. package/dist/commands/memory.d.ts +3 -0
  13. package/dist/commands/memory.d.ts.map +1 -0
  14. package/dist/commands/metadata.d.ts +11 -4
  15. package/dist/commands/metadata.d.ts.map +1 -1
  16. package/dist/commands/runs.d.ts +8 -1
  17. package/dist/commands/runs.d.ts.map +1 -1
  18. package/dist/commands/shared.d.ts +2 -0
  19. package/dist/commands/shared.d.ts.map +1 -1
  20. package/dist/commands/system.d.ts +21 -0
  21. package/dist/commands/system.d.ts.map +1 -0
  22. package/dist/commands/users.d.ts.map +1 -1
  23. package/dist/generated/sixb.mjs +2658 -0
  24. package/dist/index.d.ts +8 -3
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +298 -58
  27. package/dist/index.js.map +21 -17
  28. package/dist/main.d.ts +3 -0
  29. package/dist/main.d.ts.map +1 -0
  30. package/dist/memory.d.ts +21 -0
  31. package/dist/memory.d.ts.map +1 -0
  32. package/dist/policies.d.ts +14 -0
  33. package/dist/policies.d.ts.map +1 -1
  34. package/dist/run.d.ts +1 -0
  35. package/dist/run.d.ts.map +1 -1
  36. package/dist/sandbox-cli.d.ts +8 -0
  37. package/dist/sandbox-cli.d.ts.map +1 -0
  38. package/package.json +15 -1
  39. package/src/api-client.ts +70 -2
  40. package/src/bin/sixb +26 -0
  41. package/src/commands/actions.ts +3 -3
  42. package/src/commands/data.ts +90 -0
  43. package/src/commands/files.ts +27 -3
  44. package/src/commands/history.ts +204 -0
  45. package/src/commands/index.ts +16 -0
  46. package/src/commands/memory.ts +358 -0
  47. package/src/commands/metadata.ts +76 -29
  48. package/src/commands/models.ts +3 -3
  49. package/src/commands/ontology.ts +2 -2
  50. package/src/commands/runs.ts +22 -16
  51. package/src/commands/shared.ts +6 -0
  52. package/src/commands/system.ts +67 -0
  53. package/src/commands/telemetry.ts +2 -2
  54. package/src/commands/users.ts +22 -2
  55. package/src/commands/workflows.ts +3 -3
  56. package/src/generated/sixb.mjs +2658 -0
  57. package/src/index.ts +12 -3
  58. package/src/main.ts +41 -0
  59. package/src/memory.ts +30 -0
  60. package/src/policies.ts +5 -0
  61. package/src/run.ts +3 -2
  62. package/src/sandbox-cli.ts +18 -0
package/dist/index.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  export type { ApiClientOptions } from "./api-client";
2
2
  export { ApiClient } from "./api-client";
3
- export { isHelp, requestsHelp } from "./arguments";
3
+ export { requestsHelp } from "./arguments";
4
4
  export type { InstanceCommand } from "./commands";
5
5
  export { INSTANCE_COMMANDS, isInstanceCommand } from "./commands";
6
6
  export { renderInstanceHelp } from "./commands/metadata";
7
- export { asRecord, isFileError } from "./commands/shared";
8
- export { CliError, EXIT_API, EXIT_USAGE, fail, INSTANCE_CLI_VERSION, reportError, writeJson, writeText, } from "./output";
7
+ export type { SandboxStatusReport } from "./commands/system";
8
+ export { AGENT_RUNTIME_PROFILE } from "./commands/system";
9
+ export type { AgentMemoryManifest, AgentMemoryRepo } from "./memory";
10
+ export { AGENT_MEMORY_ENTRY, AGENT_MEMORY_MANIFEST, AGENT_MEMORY_STARTER, agentMemoryFileHash, } from "./memory";
11
+ export { CliError, EXIT_API, EXIT_USAGE, fail, INSTANCE_CLI_VERSION, reportError, writeJson, } from "./output";
9
12
  export type { InstanceCliMode, LocalInstanceCliMode, RunInstanceCliInput, SandboxInstanceCliMode, } from "./run";
10
13
  export { createInstanceApiClient, runInstanceCli } from "./run";
14
+ export type { SandboxCliAssets } from "./sandbox-cli";
15
+ export { loadSandboxCliAssets } from "./sandbox-cli";
11
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAClD,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,oBAAoB,EACpB,WAAW,EACX,SAAS,EACT,SAAS,GACV,MAAM,UAAU,CAAA;AACjB,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,oBAAoB,EACpB,WAAW,EACX,SAAS,GACV,MAAM,UAAU,CAAA;AACjB,YAAY,EACV,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAC/D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import { randomUUID } from "crypto";
4
4
  import { createWriteStream } from "fs";
5
5
  import { readFile, rename, rm } from "fs/promises";
6
+ import { request as httpRequest } from "http";
6
7
  import { basename, dirname, join } from "path";
7
8
  import { Readable } from "stream";
8
9
  import { pipeline } from "stream/promises";
@@ -63,14 +64,19 @@ function reportError(error) {
63
64
  }
64
65
 
65
66
  // src/api-client.ts
67
+ var UNIX_BASE_URL_PREFIX = "unix:";
68
+
66
69
  class ApiClient {
67
70
  baseUrl;
71
+ socketPath;
68
72
  authorization;
69
73
  missingBaseUrlMessage;
70
74
  unavailableMessage;
71
75
  unavailableHint;
72
76
  constructor(options) {
73
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
77
+ const baseUrl = options.baseUrl.replace(/\/+$/, "");
78
+ this.socketPath = baseUrl.startsWith(UNIX_BASE_URL_PREFIX) ? baseUrl.slice(UNIX_BASE_URL_PREFIX.length) : undefined;
79
+ this.baseUrl = this.socketPath === undefined ? baseUrl : "http://localhost";
74
80
  this.authorization = options.authorization;
75
81
  this.missingBaseUrlMessage = options.missingBaseUrlMessage;
76
82
  this.unavailableMessage = options.unavailableMessage;
@@ -136,7 +142,7 @@ class ApiClient {
136
142
  const headers = new Headers(init.headers);
137
143
  if (this.authorization)
138
144
  headers.set("authorization", this.authorization);
139
- response = await fetch(url, { ...init, headers });
145
+ response = await send(url, { ...init, headers }, this.socketPath);
140
146
  } catch (error) {
141
147
  if (init.signal?.aborted)
142
148
  throw error;
@@ -193,6 +199,48 @@ function stringField(record, key) {
193
199
  const value = record[key];
194
200
  return typeof value === "string" ? value : undefined;
195
201
  }
202
+ function send(url, init, socketPath) {
203
+ if (socketPath === undefined)
204
+ return fetch(url, init);
205
+ if (typeof Bun !== "undefined")
206
+ return fetch(url, { ...init, unix: socketPath });
207
+ return sendOverNodeSocket(url, init, socketPath);
208
+ }
209
+ async function sendOverNodeSocket(url, init, socketPath) {
210
+ const outgoing = new Request(url, init);
211
+ const body = outgoing.body ? Buffer.from(await outgoing.arrayBuffer()) : undefined;
212
+ const headers = Object.fromEntries(outgoing.headers);
213
+ if (body)
214
+ headers["content-length"] = String(body.byteLength);
215
+ return new Promise((resolve, reject) => {
216
+ const request = httpRequest({
217
+ socketPath,
218
+ method: outgoing.method,
219
+ path: `${url.pathname}${url.search}`,
220
+ headers: { ...headers, host: "localhost" },
221
+ ...init.signal ? { signal: init.signal } : {}
222
+ }, (response) => {
223
+ const responseHeaders = new Headers;
224
+ for (const [name, value] of Object.entries(response.headers)) {
225
+ for (const each of Array.isArray(value) ? value : value === undefined ? [] : [value]) {
226
+ responseHeaders.append(name, each);
227
+ }
228
+ }
229
+ const status = response.statusCode ?? 502;
230
+ const empty = status === 204 || status === 304 || outgoing.method === "HEAD";
231
+ resolve(new Response(empty ? null : nodeBody(response), {
232
+ status,
233
+ statusText: response.statusMessage ?? "",
234
+ headers: responseHeaders
235
+ }));
236
+ });
237
+ request.on("error", reject);
238
+ request.end(body);
239
+ });
240
+ }
241
+ function nodeBody(response) {
242
+ return Readable.toWeb(response);
243
+ }
196
244
  // src/arguments.ts
197
245
  function parseCommandArgs(args, kinds, command, positionalCount = 0) {
198
246
  const positionals = [];
@@ -304,6 +352,9 @@ var CLI_LIMITS = {
304
352
  telemetryHistory: { default: 100, maximum: 1000 },
305
353
  linkPage: { default: 100, maximum: 1000 },
306
354
  users: { default: 20, maximum: 200 },
355
+ history: { default: 20, maximum: 100 },
356
+ datasetVersions: { default: 20, maximum: 100 },
357
+ datasetRows: { default: 100, maximum: 1000 },
307
358
  inspect: {
308
359
  depth: { default: 2, maximum: 3 },
309
360
  objects: { default: 20, maximum: 100 },
@@ -316,17 +367,17 @@ var DEFAULT_OBJECT_ORDER_BY = "updatedAt";
316
367
  var DEFAULT_TELEMETRY_ORDER = "desc";
317
368
 
318
369
  // src/commands/metadata.ts
319
- var SANDBOX_MAIN_HELP = `Sixb agent CLI
370
+ var SANDBOX_MAIN_HELP = `Sixb CLI
320
371
 
321
372
  Usage:
322
373
  sixb <command> [options]
323
374
 
324
- The CLI uses the run-scoped SIXB_API_BASE_URL. Do not configure authentication or another origin.
375
+ The CLI uses the run's SIXB_API_BASE_URL, which adds its credentials. Do not configure authentication or another origin.
325
376
  API commands emit JSON. Help, version, and examples emit text. Downloads write to --output and
326
377
  emit a JSON receipt.
327
378
 
328
379
  Discovery:
329
- sixb doctor Check the sandbox and API gateway
380
+ sixb status Check the sandbox and its API access
330
381
  sixb context Print the current run context
331
382
  sixb project show Show project metadata
332
383
  sixb ontology list Compact visible type and relationship catalog
@@ -361,6 +412,13 @@ Actions and workflows:
361
412
  sixb workflows list|get|start ...
362
413
  sixb workflow-runs list|get ...
363
414
 
415
+ Data:
416
+ sixb datasets list|get|versions|rows ...
417
+ sixb syncs list|get ... Syncs you may run, each with its latest run
418
+ sixb sync-runs list ...
419
+ sixb pipelines list|get ... Pipelines you may run, each with its latest run
420
+ sixb pipeline-runs list|get ...
421
+
364
422
  Files:
365
423
  sixb files upload|download ...
366
424
 
@@ -373,23 +431,8 @@ A user parameter or property is {"type":"user","id":"<user-id>"}. Find the id wi
373
431
 
374
432
  Run \`sixb <group> --help\` or \`sixb <group> <command> --help\` for exact arguments.
375
433
  For query IR, run \`sixb objects query --help\` and \`sixb objects query --example list\`.`;
376
- var LOCAL_MAIN_HELP = SANDBOX_MAIN_HELP.replace("Sixb agent CLI", "Sixb instance CLI").replace("The CLI uses the run-scoped SIXB_API_BASE_URL. Do not configure authentication or another origin.", "The CLI uses the selected local profile and its API credentials.").replace(` sixb doctor Check the sandbox and API gateway
377
- sixb context Print the current run context
378
- `, "").replace(`
379
- When you do not know a type's properties or links, read its file under $SIXB_ONTOLOGY_DIR. Use
380
- \`sixb ontology get\` for a type that has no file there.
381
- `, "").replace(`Files:
382
- sixb files upload|download ...
383
- `, `Files:
384
- sixb files upload|download ...
385
-
386
- Models:
387
- sixb models list [--kind <kind>] Configured models of every kind, with prices
388
- sixb models get <model> One model's options and rate card
389
- sixb models text|image|speech|transcribe ... Call a model; see sixb models --help
390
- `);
391
- function renderInstanceHelp(mode) {
392
- return mode === "sandbox" ? SANDBOX_MAIN_HELP : LOCAL_MAIN_HELP;
434
+ function renderInstanceHelp() {
435
+ return SANDBOX_MAIN_HELP;
393
436
  }
394
437
  var SEARCH_DETAILS = `Without --type, search matches primary-id prefixes and full-text fields across visible types.
395
438
  With --type, the server embeds the text with the profile's model and ranks results by score,
@@ -513,8 +556,15 @@ identities. Put limits and pages inside the query tree.
513
556
  Vector profile names are the keys of the type's search.vectors. Vector input is a start node,
514
557
  optionally under filters; k bounds the ranked matches and results carry a score.`;
515
558
  var GROUP_HELP = {
516
- doctor: "Usage: sixb doctor",
559
+ status: "Usage: sixb status",
517
560
  context: "Usage: sixb context",
561
+ history: `Usage:
562
+ sixb history [--offset <n>] [--limit <1-${CLI_LIMITS.history.maximum}>]
563
+ sixb history <seq>
564
+
565
+ Prints this conversation's messages as text, oldest first, including those summarized when it
566
+ was compacted: what was said, the files sent, and each tool call with its result. A page holds
567
+ ${CLI_LIMITS.history.default} messages by default and cuts long text; \`sixb history <seq>\` prints one message whole.`,
518
568
  project: "Usage: sixb project show",
519
569
  ontology: `Usage:
520
570
  sixb ontology list [--full]
@@ -555,7 +605,8 @@ List options:
555
605
  files: `Usage:
556
606
  sixb files upload <local-path> [--logical-path <path>]
557
607
  sixb files download object <type> <id> --path <json-pointer> --output <local-path>
558
- sixb files download action-run|workflow-run <run-id> --path <json-pointer> --output <local-path>`,
608
+ sixb files download action-run|workflow-run <run-id> --path <json-pointer> --output <local-path>
609
+ sixb files download url <content-url> --output <local-path>`,
559
610
  workflows: `Usage:
560
611
  sixb workflows list
561
612
  sixb workflows get <workflow-id>
@@ -566,14 +617,15 @@ for the user's approval prints \`"status": "awaiting_approval"\` and exits with
566
617
  users: `Usage:
567
618
  sixb users list [options]
568
619
  sixb users search <text> [options]
569
- sixb users get <user-id>
620
+ sixb users get <user-id|email>
570
621
 
571
622
  Options:
572
623
  --status active|suspended|all Defaults to active
573
624
  --limit <1-${CLI_LIMITS.users.maximum}> Defaults to ${CLI_LIMITS.users.default}
574
625
  --offset <n> Non-negative; defaults to 0
575
626
 
576
- \`users search\` matches part of a display name or email, ignoring case. Each member is
627
+ \`users search\` matches part of a display name or email, ignoring case; \`users get\` takes an
628
+ exact email, ignoring case, and finds suspended members too. Each member is
577
629
  {"id","email","displayName","avatarUrl","status"}; a user parameter takes
578
630
  {"type":"user","id":"<id>"}. Reading members requires can.view(project.users).`,
579
631
  models: `Usage:
@@ -611,7 +663,57 @@ List options:
611
663
  --started-after|--started-before <RFC3339>
612
664
  --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
613
665
  --offset <n> Non-negative; defaults to 0
614
- --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`
666
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`,
667
+ datasets: `Usage:
668
+ sixb datasets list
669
+ sixb datasets get <dataset-id>
670
+ sixb datasets versions <dataset-id> [--limit <1-${CLI_LIMITS.datasetVersions.maximum}>]
671
+ sixb datasets rows <dataset-id> [options]
672
+
673
+ Rows options:
674
+ --version <version-id> Defaults to the latest version
675
+ --columns <a,b,...> Defaults to every column
676
+ --limit <1-${CLI_LIMITS.datasetRows.maximum}> Defaults to ${CLI_LIMITS.datasetRows.default}
677
+ --offset <n> Non-negative; defaults to 0
678
+
679
+ \`list\` and \`get\` show a dataset's schema, its latest version, and the syncs and pipelines you
680
+ may run that read or write it. \`versions\` lists the newest first. \`rows\` leaves out the
681
+ columns your clearances do not cover and names them under redactions.`,
682
+ syncs: `Usage:
683
+ sixb syncs list
684
+ sixb syncs get <sync-id>
685
+
686
+ Lists the syncs you may run, each with its latest run. \`sixb sync-runs list\` shows the history.`,
687
+ "sync-runs": `Usage:
688
+ sixb sync-runs list [options]
689
+
690
+ List options:
691
+ --sync <sync-id>
692
+ --dataset <dataset-id>
693
+ --status queued|running|succeeded|failed|cancelled
694
+ --started-after|--started-before <RFC3339>
695
+ --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
696
+ --offset <n> Non-negative; defaults to 0
697
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`,
698
+ pipelines: `Usage:
699
+ sixb pipelines list
700
+ sixb pipelines get <pipeline-id>
701
+
702
+ Lists the pipelines you may run, each with its latest run. \`sixb pipeline-runs\` shows the
703
+ history and each run's steps.`,
704
+ "pipeline-runs": `Usage:
705
+ sixb pipeline-runs list [options]
706
+ sixb pipeline-runs get <run-id>
707
+
708
+ List options:
709
+ --pipeline <pipeline-id>
710
+ --status queued|running|succeeded|failed|cancelled
711
+ --started-after|--started-before <RFC3339>
712
+ --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
713
+ --offset <n> Non-negative; defaults to 0
714
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}
715
+
716
+ \`get\` includes the run's steps.`
615
717
  };
616
718
  var QUERY_EXAMPLES = {
617
719
  exact: '{"kind":"refs","refs":[{"objectTypeId":"RepositoryIssue","primaryId":"github:issue:owner/repo#297"}]}',
@@ -633,6 +735,11 @@ var FACETS_EXAMPLE = '{"query":{"kind":"start","objectTypeId":"WorkOrder"},"face
633
735
 
634
736
  // src/commands/shared.ts
635
737
  import { readFile as readFile2 } from "fs/promises";
738
+ function idSegment(value) {
739
+ if (!value || value === "." || value === "..")
740
+ fail(`'${value ?? ""}' is not an id.`);
741
+ return encodeURIComponent(value);
742
+ }
636
743
  function parseQueryOptions(args, names, command) {
637
744
  const kinds = Object.fromEntries(Object.keys(names).map((flag) => [flag, "string"]));
638
745
  const { options } = parseCommandArgs(args, kinds, command);
@@ -706,7 +813,7 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
706
813
  return writeText(GROUP_HELP.actions);
707
814
  if (sub === "get") {
708
815
  const { positionals } = parseCommandArgs(rest, {}, "actions get", 1);
709
- return writeJson(await api.get(`/api/actions/${encodeURIComponent(positionals[0] ?? "")}`));
816
+ return writeJson(await api.get(`/api/actions/${idSegment(positionals[0])}`));
710
817
  }
711
818
  if (sub === "list") {
712
819
  const options = parseQueryOptions(rest, { "--type": "objectTypeId" }, "actions list");
@@ -739,7 +846,7 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
739
846
  const requestedRunId = runId ?? `act_${randomUUID2()}`;
740
847
  const waiting = AbortSignal.timeout(requestWaitMs);
741
848
  try {
742
- return writeRequestResult(await api.post(`/api/actions/${encodeURIComponent(actionId)}`, {
849
+ return writeRequestResult(await api.post(`/api/actions/${idSegment(actionId)}`, {
743
850
  params,
744
851
  ...subjectType && subjectId ? { subject: { kind: "object", objectTypeId: subjectType, primaryId: subjectId } } : {},
745
852
  runId: requestedRunId
@@ -757,6 +864,59 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
757
864
  fail(`Unknown actions command '${sub}'.`);
758
865
  }
759
866
 
867
+ // src/commands/data.ts
868
+ async function datasets(api, args) {
869
+ const [sub, ...rest] = args;
870
+ if (!sub || isHelp(sub) || requestsHelp(rest))
871
+ return writeText(GROUP_HELP.datasets);
872
+ if (sub === "list") {
873
+ parseCommandArgs(rest, {}, "datasets list");
874
+ return writeJson(await api.get("/api/datasets"));
875
+ }
876
+ if (sub === "get") {
877
+ const { positionals } = parseCommandArgs(rest, {}, "datasets get", 1);
878
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}`));
879
+ }
880
+ if (sub === "versions") {
881
+ const { positionals, options } = parseCommandArgs(rest, { "--limit": "string" }, "datasets versions", 1);
882
+ const { default: fallback, maximum } = CLI_LIMITS.datasetVersions;
883
+ const limit = integerInRange("--limit", options["--limit"] ?? String(fallback), 1, maximum);
884
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}/versions`, { limit: String(limit) }));
885
+ }
886
+ if (sub === "rows") {
887
+ const { positionals, options } = parseCommandArgs(rest, { "--version": "string", "--columns": "string", "--limit": "string", "--offset": "string" }, "datasets rows", 1);
888
+ const { default: fallback, maximum } = CLI_LIMITS.datasetRows;
889
+ const query = {
890
+ limit: String(integerInRange("--limit", options["--limit"] ?? String(fallback), 1, maximum)),
891
+ ...options["--version"] === undefined ? {} : { versionId: options["--version"] },
892
+ ...options["--columns"] === undefined ? {} : { columns: columnList(options["--columns"]) },
893
+ ...options["--offset"] === undefined ? {} : { offset: String(nonNegativeInteger("--offset", options["--offset"])) }
894
+ };
895
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}/rows`, query));
896
+ }
897
+ fail(`Unknown datasets command '${sub}'.`);
898
+ }
899
+ async function runnables(api, group, args) {
900
+ const [sub, ...rest] = args;
901
+ if (!sub || isHelp(sub) || requestsHelp(rest))
902
+ return writeText(GROUP_HELP[group]);
903
+ if (sub === "list") {
904
+ parseCommandArgs(rest, {}, `${group} list`);
905
+ return writeJson(await api.get(`/api/${group}`));
906
+ }
907
+ if (sub === "get") {
908
+ const { positionals } = parseCommandArgs(rest, {}, `${group} get`, 1);
909
+ return writeJson(await api.get(`/api/${group}/${idSegment(positionals[0])}`));
910
+ }
911
+ fail(`Unknown ${group} command '${sub}'.`);
912
+ }
913
+ function columnList(value) {
914
+ const columns = value.split(",").map((column) => column.trim());
915
+ if (columns.some((column) => !column))
916
+ fail("--columns takes column names separated by commas.");
917
+ return columns.join(",");
918
+ }
919
+
760
920
  // src/commands/files.ts
761
921
  import { access } from "fs/promises";
762
922
  async function files(api, args) {
@@ -776,20 +936,28 @@ async function files(api, args) {
776
936
  if (sub === "download") {
777
937
  const { positionals, options } = parseCommandArgs(rest, { "--path": "string", "--output": "string" }, "files download", [2, 3]);
778
938
  const context = positionals[0];
939
+ const output = options["--output"];
940
+ if (context === "url") {
941
+ requireExact(positionals, 2, "files download url requires exactly one content URL.");
942
+ const url = parseContentUrl(positionals[1] ?? "");
943
+ if (!output)
944
+ fail("files download requires --output <local-path>.");
945
+ await api.download(url.pathname, output, Object.fromEntries(url.searchParams));
946
+ return writeJson({ downloaded: true, output });
947
+ }
779
948
  let route;
780
949
  if (context === "object") {
781
950
  requireExact(positionals, 3, "files download object requires object type and primary id.");
782
951
  const type = positionals[1] ?? "";
783
952
  const id = positionals[2] ?? "";
784
- route = `/api/objects/${encodeURIComponent(type)}/${encodeURIComponent(id)}/files/content`;
953
+ route = `/api/objects/${idSegment(type)}/${idSegment(id)}/files/content`;
785
954
  } else if (context === "action-run" || context === "workflow-run") {
786
955
  requireExact(positionals, 2, `files download ${context} requires exactly one run id.`);
787
956
  const id = positionals[1] ?? "";
788
- route = `/api/${context}s/${encodeURIComponent(id)}/files/content`;
957
+ route = `/api/${context}s/${idSegment(id)}/files/content`;
789
958
  } else
790
959
  fail(`Unknown file download context '${context}'.`);
791
960
  const path = options["--path"];
792
- const output = options["--output"];
793
961
  if (!path)
794
962
  fail("files download requires --path <json-pointer>.");
795
963
  if (!output)
@@ -799,6 +967,18 @@ async function files(api, args) {
799
967
  }
800
968
  fail(`Unknown files command '${sub}'.`);
801
969
  }
970
+ function parseContentUrl(value) {
971
+ let url;
972
+ try {
973
+ url = new URL(value);
974
+ } catch {
975
+ fail(`'${value}' is not a URL.`);
976
+ }
977
+ if (!url.pathname.startsWith("/api/") || !url.pathname.endsWith("/files/content")) {
978
+ fail(`'${value}' is not a Sixb file content URL.`);
979
+ }
980
+ return url;
981
+ }
802
982
 
803
983
  // src/commands/models.ts
804
984
  import { access as access2, mkdir, stat } from "fs/promises";
@@ -979,7 +1159,7 @@ async function calls(api, args) {
979
1159
  fail(`Unknown models calls command '${sub ?? ""}'. Use 'models calls files'.`);
980
1160
  const { positionals, options } = parseCommandArgs(rest, { "--output": "string" }, "models calls files", 1);
981
1161
  const callId = positionals[0] ?? "";
982
- const call = await api.get(`/api/ai/model-calls/${encodeURIComponent(callId)}/files`);
1162
+ const call = await api.get(`/api/ai/model-calls/${idSegment(callId)}/files`);
983
1163
  const output = options["--output"];
984
1164
  if (output === undefined)
985
1165
  return writeJson(call);
@@ -1052,7 +1232,7 @@ async function saveFiles(api, callId, files, output) {
1052
1232
  });
1053
1233
  for (const [index, path] of paths.entries()) {
1054
1234
  await mkdir(dirname2(path), { recursive: true });
1055
- await api.download(`/api/ai/model-calls/${encodeURIComponent(callId)}/files/content`, path, {
1235
+ await api.download(`/api/ai/model-calls/${idSegment(callId)}/files/content`, path, {
1056
1236
  path: `/files/${index}`
1057
1237
  });
1058
1238
  }
@@ -1696,7 +1876,7 @@ async function ontology(api, args) {
1696
1876
  if (requestsHelp(rest))
1697
1877
  return writeText("Usage: sixb ontology get <object-type>");
1698
1878
  const { positionals } = parseCommandArgs(rest, {}, "ontology get", 1);
1699
- return writeJson(await api.get(`/api/object-types/${encodeURIComponent(positionals[0] ?? "")}`));
1879
+ return writeJson(await api.get(`/api/object-types/${idSegment(positionals[0])}`));
1700
1880
  }
1701
1881
  fail(`Unknown ontology command '${sub}'.`);
1702
1882
  }
@@ -1722,12 +1902,25 @@ var WORKFLOW_RUN_STATUSES = [
1722
1902
  "failed",
1723
1903
  "cancelled"
1724
1904
  ];
1905
+ var DATA_RUN_STATUSES = ["queued", "running", "succeeded", "failed", "cancelled"];
1906
+ var STATUSES = {
1907
+ action: ACTION_RUN_STATUSES,
1908
+ workflow: WORKFLOW_RUN_STATUSES,
1909
+ sync: DATA_RUN_STATUSES,
1910
+ pipeline: DATA_RUN_STATUSES
1911
+ };
1912
+ var FILTERS = {
1913
+ action: { "--action": "actionId", "--type": "objectTypeId", "--id": "primaryId" },
1914
+ workflow: { "--workflow": "workflowId" },
1915
+ sync: { "--sync": "syncId", "--dataset": "datasetId" },
1916
+ pipeline: { "--pipeline": "pipelineId" }
1917
+ };
1725
1918
  async function runs(api, kind, args) {
1726
1919
  const [sub, ...rest] = args;
1727
1920
  const group = `${kind}-runs`;
1728
1921
  if (!sub || isHelp(sub) || requestsHelp(rest))
1729
1922
  return writeText(GROUP_HELP[group]);
1730
- if (sub === "get") {
1923
+ if (sub === "get" && kind !== "sync") {
1731
1924
  const { positionals } = parseCommandArgs(rest, {}, `${group} get`, 1);
1732
1925
  return writeJson(await api.get(`/api/${group}/${encodeURIComponent(positionals[0] ?? "")}`));
1733
1926
  }
@@ -1740,21 +1933,14 @@ async function runs(api, kind, args) {
1740
1933
  "--offset": "offset",
1741
1934
  "--order": "order"
1742
1935
  };
1743
- const action = {
1744
- ...common,
1745
- "--action": "actionId",
1746
- "--type": "objectTypeId",
1747
- "--id": "primaryId"
1748
- };
1749
- const workflow = { ...common, "--workflow": "workflowId" };
1750
- const options = normalizeWindowOptions(parseQueryOptions(rest, kind === "action" ? action : workflow, `${group} list`), {
1936
+ const options = normalizeWindowOptions(parseQueryOptions(rest, { ...common, ...FILTERS[kind] }, `${group} list`), {
1751
1937
  defaultLimit: CLI_LIMITS.list.default,
1752
1938
  maximumLimit: CLI_LIMITS.list.maximum,
1753
1939
  defaultOrder: DEFAULT_LIST_ORDER,
1754
1940
  offset: true
1755
1941
  });
1756
1942
  if (options.status !== undefined) {
1757
- options.status = enumValue("--status", options.status, kind === "action" ? ACTION_RUN_STATUSES : WORKFLOW_RUN_STATUSES);
1943
+ options.status = enumValue("--status", options.status, STATUSES[kind]);
1758
1944
  }
1759
1945
  for (const [name, flag] of [
1760
1946
  ["startedAfter", "--started-after"],
@@ -1808,7 +1994,7 @@ async function telemetry(api, args) {
1808
1994
  fail(`Unknown telemetry command '${sub}'.`);
1809
1995
  }
1810
1996
  function telemetryPath(args, terminal) {
1811
- return `/api/objects/${encodeURIComponent(args[0] ?? "")}/${encodeURIComponent(args[1] ?? "")}/telemetry/${encodeURIComponent(args[2] ?? "")}/${terminal}`;
1997
+ return `/api/objects/${idSegment(args[0])}/${idSegment(args[1])}/telemetry/${idSegment(args[2])}/${terminal}`;
1812
1998
  }
1813
1999
  function normalizeTelemetryQueryInput(input) {
1814
2000
  if (Array.isArray(input) || typeof input !== "object" || input === null) {
@@ -1850,7 +2036,18 @@ async function users(api, args) {
1850
2036
  return writeText(GROUP_HELP.users);
1851
2037
  if (sub === "get") {
1852
2038
  const { positionals } = parseCommandArgs(rest, {}, "users get", 1);
1853
- return writeJson(await api.get(`/api/users/${encodeURIComponent(positionals[0] ?? "")}`));
2039
+ const user = positionals[0]?.trim();
2040
+ if (!user)
2041
+ fail("users get requires a user id or email.");
2042
+ if (!user.includes("@")) {
2043
+ return writeJson(await api.get(`/api/users/${idSegment(user)}`));
2044
+ }
2045
+ const page = await api.get("/api/users", { email: user });
2046
+ const [member] = isRecord(page) && Array.isArray(page.users) ? page.users : [];
2047
+ if (member === undefined) {
2048
+ throw new CliError({ code: "not_found", message: `No member has the email '${user}'.` }, EXIT_API);
2049
+ }
2050
+ return writeJson(member);
1854
2051
  }
1855
2052
  if (sub === "list") {
1856
2053
  const { options } = parseCommandArgs(rest, LIST_FLAGS, "users list");
@@ -1873,6 +2070,9 @@ function listQuery(options) {
1873
2070
  ...options["--offset"] === undefined ? {} : { offset: String(nonNegativeInteger("--offset", options["--offset"])) }
1874
2071
  };
1875
2072
  }
2073
+ function isRecord(value) {
2074
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2075
+ }
1876
2076
 
1877
2077
  // src/commands/workflows.ts
1878
2078
  import { randomUUID as randomUUID3 } from "crypto";
@@ -1888,7 +2088,7 @@ async function workflows(api, args) {
1888
2088
  const {
1889
2089
  positionals: [workflowId]
1890
2090
  } = parseCommandArgs(rest, {}, "workflows get", 1);
1891
- return writeJson(await api.get(`/api/workflows/${encodeURIComponent(workflowId ?? "")}`));
2091
+ return writeJson(await api.get(`/api/workflows/${idSegment(workflowId)}`));
1892
2092
  }
1893
2093
  if (sub === "start") {
1894
2094
  const {
@@ -1900,7 +2100,7 @@ async function workflows(api, args) {
1900
2100
  fail("Workflow input must be a JSON object.");
1901
2101
  }
1902
2102
  const runId = options["--run-id"] ?? `run_${randomUUID3()}`;
1903
- return writeRequestResult(await api.post(`/api/workflows/${encodeURIComponent(workflowId ?? "")}/runs`, {
2103
+ return writeRequestResult(await api.post(`/api/workflows/${idSegment(workflowId)}/runs`, {
1904
2104
  input,
1905
2105
  runId
1906
2106
  }));
@@ -1920,7 +2120,12 @@ var INSTANCE_COMMANDS = [
1920
2120
  "workflows",
1921
2121
  "workflow-runs",
1922
2122
  "users",
1923
- "models"
2123
+ "models",
2124
+ "datasets",
2125
+ "syncs",
2126
+ "sync-runs",
2127
+ "pipelines",
2128
+ "pipeline-runs"
1924
2129
  ];
1925
2130
  function isInstanceCommand(command) {
1926
2131
  return INSTANCE_COMMANDS.includes(command);
@@ -1949,6 +2154,16 @@ async function dispatch(api, command, args) {
1949
2154
  return users(api, args);
1950
2155
  case "models":
1951
2156
  return models(api, args);
2157
+ case "datasets":
2158
+ return datasets(api, args);
2159
+ case "syncs":
2160
+ return runnables(api, "syncs", args);
2161
+ case "sync-runs":
2162
+ return runs(api, "sync", args);
2163
+ case "pipelines":
2164
+ return runnables(api, "pipelines", args);
2165
+ case "pipeline-runs":
2166
+ return runs(api, "pipeline", args);
1952
2167
  default:
1953
2168
  fail(`Unknown command '${command}'. Run 'sixb --help'.`);
1954
2169
  }
@@ -1963,29 +2178,54 @@ function createInstanceApiClient(mode) {
1963
2178
  baseUrl: mode.baseUrl,
1964
2179
  ...mode.kind === "local" && mode.token ? { authorization: `Bearer ${mode.token}` } : {},
1965
2180
  missingBaseUrlMessage: mode.kind === "sandbox" ? "SIXB_API_BASE_URL is not set." : "The selected Sixb profile has no API URL.",
1966
- unavailableMessage: mode.kind === "sandbox" ? "The Sixb API gateway could not be reached." : "The Sixb API could not be reached.",
1967
- unavailableHint: mode.kind === "sandbox" ? "Run 'sixb doctor' to verify the sandbox runtime and gateway." : "Run 'sixb status' to verify the current profile."
2181
+ unavailableMessage: mode.kind === "sandbox" ? "The Sixb API could not be reached from the sandbox." : "The Sixb API could not be reached.",
2182
+ unavailableHint: mode.kind === "sandbox" ? "Run 'sixb status' to verify the sandbox runtime and its API access." : "Run 'sixb status' to verify the current profile."
1968
2183
  });
1969
2184
  }
2185
+
2186
+ // src/commands/system.ts
2187
+ var AGENT_RUNTIME_PROFILE = "sixb-agent-runtime/v1";
2188
+ // src/memory.ts
2189
+ import { createHash } from "crypto";
2190
+ var AGENT_MEMORY_MANIFEST = "context/memory.json";
2191
+ var AGENT_MEMORY_ENTRY = "MEMORY.md";
2192
+ var AGENT_MEMORY_STARTER = `# Memory
2193
+
2194
+ `;
2195
+ function agentMemoryFileHash(contents) {
2196
+ return createHash("sha256").update(contents).digest("hex");
2197
+ }
2198
+ // src/sandbox-cli.ts
2199
+ import { readFile as readFile3 } from "fs/promises";
2200
+ var cachedAssets;
2201
+ function loadSandboxCliAssets() {
2202
+ cachedAssets ??= Promise.all([
2203
+ readFile3(new URL("./bin/sixb", import.meta.url), "utf8"),
2204
+ readFile3(new URL("./generated/sixb.mjs", import.meta.url))
2205
+ ]).then(([launcher, artifact]) => ({ launcher, artifact }));
2206
+ return cachedAssets;
2207
+ }
1970
2208
  export {
2209
+ AGENT_MEMORY_ENTRY,
2210
+ AGENT_MEMORY_MANIFEST,
2211
+ AGENT_MEMORY_STARTER,
2212
+ AGENT_RUNTIME_PROFILE,
1971
2213
  ApiClient,
1972
2214
  CliError,
1973
2215
  EXIT_API,
1974
2216
  EXIT_USAGE,
1975
2217
  INSTANCE_CLI_VERSION,
1976
2218
  INSTANCE_COMMANDS,
1977
- asRecord2 as asRecord,
2219
+ agentMemoryFileHash,
1978
2220
  createInstanceApiClient,
1979
2221
  fail,
1980
- isFileError,
1981
- isHelp,
1982
2222
  isInstanceCommand,
2223
+ loadSandboxCliAssets,
1983
2224
  renderInstanceHelp,
1984
2225
  reportError,
1985
2226
  requestsHelp,
1986
2227
  runInstanceCli,
1987
- writeJson,
1988
- writeText
2228
+ writeJson
1989
2229
  };
1990
2230
 
1991
- //# debugId=7F5CD0F40A1B96CA64756E2164756E21
2231
+ //# debugId=35B6967DDC6E812864756E2164756E21