@sixb/cli-core 0.1.9 → 0.1.10

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 (59) 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/index.d.ts +1 -1
  9. package/dist/commands/index.d.ts.map +1 -1
  10. package/dist/commands/memory.d.ts +3 -0
  11. package/dist/commands/memory.d.ts.map +1 -0
  12. package/dist/commands/metadata.d.ts +10 -4
  13. package/dist/commands/metadata.d.ts.map +1 -1
  14. package/dist/commands/runs.d.ts +8 -1
  15. package/dist/commands/runs.d.ts.map +1 -1
  16. package/dist/commands/shared.d.ts +2 -0
  17. package/dist/commands/shared.d.ts.map +1 -1
  18. package/dist/commands/system.d.ts +21 -0
  19. package/dist/commands/system.d.ts.map +1 -0
  20. package/dist/commands/users.d.ts.map +1 -1
  21. package/dist/generated/sixb.mjs +2547 -0
  22. package/dist/index.d.ts +8 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +290 -58
  25. package/dist/index.js.map +21 -17
  26. package/dist/main.d.ts +3 -0
  27. package/dist/main.d.ts.map +1 -0
  28. package/dist/memory.d.ts +21 -0
  29. package/dist/memory.d.ts.map +1 -0
  30. package/dist/policies.d.ts +9 -0
  31. package/dist/policies.d.ts.map +1 -1
  32. package/dist/run.d.ts +1 -0
  33. package/dist/run.d.ts.map +1 -1
  34. package/dist/sandbox-cli.d.ts +8 -0
  35. package/dist/sandbox-cli.d.ts.map +1 -0
  36. package/package.json +15 -1
  37. package/src/api-client.ts +70 -2
  38. package/src/bin/sixb +26 -0
  39. package/src/commands/actions.ts +3 -3
  40. package/src/commands/data.ts +90 -0
  41. package/src/commands/files.ts +27 -3
  42. package/src/commands/index.ts +16 -0
  43. package/src/commands/memory.ts +358 -0
  44. package/src/commands/metadata.ts +69 -29
  45. package/src/commands/models.ts +3 -3
  46. package/src/commands/ontology.ts +2 -2
  47. package/src/commands/runs.ts +22 -16
  48. package/src/commands/shared.ts +6 -0
  49. package/src/commands/system.ts +67 -0
  50. package/src/commands/telemetry.ts +2 -2
  51. package/src/commands/users.ts +22 -2
  52. package/src/commands/workflows.ts +3 -3
  53. package/src/generated/sixb.mjs +2547 -0
  54. package/src/index.ts +12 -3
  55. package/src/main.ts +39 -0
  56. package/src/memory.ts +30 -0
  57. package/src/policies.ts +3 -0
  58. package/src/run.ts +3 -2
  59. 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,8 @@ 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
+ datasetVersions: { default: 20, maximum: 100 },
356
+ datasetRows: { default: 100, maximum: 1000 },
307
357
  inspect: {
308
358
  depth: { default: 2, maximum: 3 },
309
359
  objects: { default: 20, maximum: 100 },
@@ -316,17 +366,17 @@ var DEFAULT_OBJECT_ORDER_BY = "updatedAt";
316
366
  var DEFAULT_TELEMETRY_ORDER = "desc";
317
367
 
318
368
  // src/commands/metadata.ts
319
- var SANDBOX_MAIN_HELP = `Sixb agent CLI
369
+ var SANDBOX_MAIN_HELP = `Sixb CLI
320
370
 
321
371
  Usage:
322
372
  sixb <command> [options]
323
373
 
324
- The CLI uses the run-scoped SIXB_API_BASE_URL. Do not configure authentication or another origin.
374
+ The CLI uses the run's SIXB_API_BASE_URL, which adds its credentials. Do not configure authentication or another origin.
325
375
  API commands emit JSON. Help, version, and examples emit text. Downloads write to --output and
326
376
  emit a JSON receipt.
327
377
 
328
378
  Discovery:
329
- sixb doctor Check the sandbox and API gateway
379
+ sixb status Check the sandbox and its API access
330
380
  sixb context Print the current run context
331
381
  sixb project show Show project metadata
332
382
  sixb ontology list Compact visible type and relationship catalog
@@ -361,6 +411,13 @@ Actions and workflows:
361
411
  sixb workflows list|get|start ...
362
412
  sixb workflow-runs list|get ...
363
413
 
414
+ Data:
415
+ sixb datasets list|get|versions|rows ...
416
+ sixb syncs list|get ... Syncs you may run, each with its latest run
417
+ sixb sync-runs list ...
418
+ sixb pipelines list|get ... Pipelines you may run, each with its latest run
419
+ sixb pipeline-runs list|get ...
420
+
364
421
  Files:
365
422
  sixb files upload|download ...
366
423
 
@@ -373,23 +430,8 @@ A user parameter or property is {"type":"user","id":"<user-id>"}. Find the id wi
373
430
 
374
431
  Run \`sixb <group> --help\` or \`sixb <group> <command> --help\` for exact arguments.
375
432
  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;
433
+ function renderInstanceHelp() {
434
+ return SANDBOX_MAIN_HELP;
393
435
  }
394
436
  var SEARCH_DETAILS = `Without --type, search matches primary-id prefixes and full-text fields across visible types.
395
437
  With --type, the server embeds the text with the profile's model and ranks results by score,
@@ -513,7 +555,7 @@ identities. Put limits and pages inside the query tree.
513
555
  Vector profile names are the keys of the type's search.vectors. Vector input is a start node,
514
556
  optionally under filters; k bounds the ranked matches and results carry a score.`;
515
557
  var GROUP_HELP = {
516
- doctor: "Usage: sixb doctor",
558
+ status: "Usage: sixb status",
517
559
  context: "Usage: sixb context",
518
560
  project: "Usage: sixb project show",
519
561
  ontology: `Usage:
@@ -555,7 +597,8 @@ List options:
555
597
  files: `Usage:
556
598
  sixb files upload <local-path> [--logical-path <path>]
557
599
  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>`,
600
+ sixb files download action-run|workflow-run <run-id> --path <json-pointer> --output <local-path>
601
+ sixb files download url <content-url> --output <local-path>`,
559
602
  workflows: `Usage:
560
603
  sixb workflows list
561
604
  sixb workflows get <workflow-id>
@@ -566,14 +609,15 @@ for the user's approval prints \`"status": "awaiting_approval"\` and exits with
566
609
  users: `Usage:
567
610
  sixb users list [options]
568
611
  sixb users search <text> [options]
569
- sixb users get <user-id>
612
+ sixb users get <user-id|email>
570
613
 
571
614
  Options:
572
615
  --status active|suspended|all Defaults to active
573
616
  --limit <1-${CLI_LIMITS.users.maximum}> Defaults to ${CLI_LIMITS.users.default}
574
617
  --offset <n> Non-negative; defaults to 0
575
618
 
576
- \`users search\` matches part of a display name or email, ignoring case. Each member is
619
+ \`users search\` matches part of a display name or email, ignoring case; \`users get\` takes an
620
+ exact email, ignoring case, and finds suspended members too. Each member is
577
621
  {"id","email","displayName","avatarUrl","status"}; a user parameter takes
578
622
  {"type":"user","id":"<id>"}. Reading members requires can.view(project.users).`,
579
623
  models: `Usage:
@@ -611,7 +655,57 @@ List options:
611
655
  --started-after|--started-before <RFC3339>
612
656
  --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
613
657
  --offset <n> Non-negative; defaults to 0
614
- --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`
658
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`,
659
+ datasets: `Usage:
660
+ sixb datasets list
661
+ sixb datasets get <dataset-id>
662
+ sixb datasets versions <dataset-id> [--limit <1-${CLI_LIMITS.datasetVersions.maximum}>]
663
+ sixb datasets rows <dataset-id> [options]
664
+
665
+ Rows options:
666
+ --version <version-id> Defaults to the latest version
667
+ --columns <a,b,...> Defaults to every column
668
+ --limit <1-${CLI_LIMITS.datasetRows.maximum}> Defaults to ${CLI_LIMITS.datasetRows.default}
669
+ --offset <n> Non-negative; defaults to 0
670
+
671
+ \`list\` and \`get\` show a dataset's schema, its latest version, and the syncs and pipelines you
672
+ may run that read or write it. \`versions\` lists the newest first. \`rows\` leaves out the
673
+ columns your clearances do not cover and names them under redactions.`,
674
+ syncs: `Usage:
675
+ sixb syncs list
676
+ sixb syncs get <sync-id>
677
+
678
+ Lists the syncs you may run, each with its latest run. \`sixb sync-runs list\` shows the history.`,
679
+ "sync-runs": `Usage:
680
+ sixb sync-runs list [options]
681
+
682
+ List options:
683
+ --sync <sync-id>
684
+ --dataset <dataset-id>
685
+ --status queued|running|succeeded|failed|cancelled
686
+ --started-after|--started-before <RFC3339>
687
+ --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
688
+ --offset <n> Non-negative; defaults to 0
689
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}`,
690
+ pipelines: `Usage:
691
+ sixb pipelines list
692
+ sixb pipelines get <pipeline-id>
693
+
694
+ Lists the pipelines you may run, each with its latest run. \`sixb pipeline-runs\` shows the
695
+ history and each run's steps.`,
696
+ "pipeline-runs": `Usage:
697
+ sixb pipeline-runs list [options]
698
+ sixb pipeline-runs get <run-id>
699
+
700
+ List options:
701
+ --pipeline <pipeline-id>
702
+ --status queued|running|succeeded|failed|cancelled
703
+ --started-after|--started-before <RFC3339>
704
+ --limit <1-${CLI_LIMITS.list.maximum}> Defaults to ${CLI_LIMITS.list.default}
705
+ --offset <n> Non-negative; defaults to 0
706
+ --order <asc|desc> Started-time order; defaults to ${DEFAULT_LIST_ORDER}
707
+
708
+ \`get\` includes the run's steps.`
615
709
  };
616
710
  var QUERY_EXAMPLES = {
617
711
  exact: '{"kind":"refs","refs":[{"objectTypeId":"RepositoryIssue","primaryId":"github:issue:owner/repo#297"}]}',
@@ -633,6 +727,11 @@ var FACETS_EXAMPLE = '{"query":{"kind":"start","objectTypeId":"WorkOrder"},"face
633
727
 
634
728
  // src/commands/shared.ts
635
729
  import { readFile as readFile2 } from "fs/promises";
730
+ function idSegment(value) {
731
+ if (!value || value === "." || value === "..")
732
+ fail(`'${value ?? ""}' is not an id.`);
733
+ return encodeURIComponent(value);
734
+ }
636
735
  function parseQueryOptions(args, names, command) {
637
736
  const kinds = Object.fromEntries(Object.keys(names).map((flag) => [flag, "string"]));
638
737
  const { options } = parseCommandArgs(args, kinds, command);
@@ -706,7 +805,7 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
706
805
  return writeText(GROUP_HELP.actions);
707
806
  if (sub === "get") {
708
807
  const { positionals } = parseCommandArgs(rest, {}, "actions get", 1);
709
- return writeJson(await api.get(`/api/actions/${encodeURIComponent(positionals[0] ?? "")}`));
808
+ return writeJson(await api.get(`/api/actions/${idSegment(positionals[0])}`));
710
809
  }
711
810
  if (sub === "list") {
712
811
  const options = parseQueryOptions(rest, { "--type": "objectTypeId" }, "actions list");
@@ -739,7 +838,7 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
739
838
  const requestedRunId = runId ?? `act_${randomUUID2()}`;
740
839
  const waiting = AbortSignal.timeout(requestWaitMs);
741
840
  try {
742
- return writeRequestResult(await api.post(`/api/actions/${encodeURIComponent(actionId)}`, {
841
+ return writeRequestResult(await api.post(`/api/actions/${idSegment(actionId)}`, {
743
842
  params,
744
843
  ...subjectType && subjectId ? { subject: { kind: "object", objectTypeId: subjectType, primaryId: subjectId } } : {},
745
844
  runId: requestedRunId
@@ -757,6 +856,59 @@ async function actions(api, args, requestWaitMs = ACTION_REQUEST_WAIT_MS) {
757
856
  fail(`Unknown actions command '${sub}'.`);
758
857
  }
759
858
 
859
+ // src/commands/data.ts
860
+ async function datasets(api, args) {
861
+ const [sub, ...rest] = args;
862
+ if (!sub || isHelp(sub) || requestsHelp(rest))
863
+ return writeText(GROUP_HELP.datasets);
864
+ if (sub === "list") {
865
+ parseCommandArgs(rest, {}, "datasets list");
866
+ return writeJson(await api.get("/api/datasets"));
867
+ }
868
+ if (sub === "get") {
869
+ const { positionals } = parseCommandArgs(rest, {}, "datasets get", 1);
870
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}`));
871
+ }
872
+ if (sub === "versions") {
873
+ const { positionals, options } = parseCommandArgs(rest, { "--limit": "string" }, "datasets versions", 1);
874
+ const { default: fallback, maximum } = CLI_LIMITS.datasetVersions;
875
+ const limit = integerInRange("--limit", options["--limit"] ?? String(fallback), 1, maximum);
876
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}/versions`, { limit: String(limit) }));
877
+ }
878
+ if (sub === "rows") {
879
+ const { positionals, options } = parseCommandArgs(rest, { "--version": "string", "--columns": "string", "--limit": "string", "--offset": "string" }, "datasets rows", 1);
880
+ const { default: fallback, maximum } = CLI_LIMITS.datasetRows;
881
+ const query = {
882
+ limit: String(integerInRange("--limit", options["--limit"] ?? String(fallback), 1, maximum)),
883
+ ...options["--version"] === undefined ? {} : { versionId: options["--version"] },
884
+ ...options["--columns"] === undefined ? {} : { columns: columnList(options["--columns"]) },
885
+ ...options["--offset"] === undefined ? {} : { offset: String(nonNegativeInteger("--offset", options["--offset"])) }
886
+ };
887
+ return writeJson(await api.get(`/api/datasets/${idSegment(positionals[0])}/rows`, query));
888
+ }
889
+ fail(`Unknown datasets command '${sub}'.`);
890
+ }
891
+ async function runnables(api, group, args) {
892
+ const [sub, ...rest] = args;
893
+ if (!sub || isHelp(sub) || requestsHelp(rest))
894
+ return writeText(GROUP_HELP[group]);
895
+ if (sub === "list") {
896
+ parseCommandArgs(rest, {}, `${group} list`);
897
+ return writeJson(await api.get(`/api/${group}`));
898
+ }
899
+ if (sub === "get") {
900
+ const { positionals } = parseCommandArgs(rest, {}, `${group} get`, 1);
901
+ return writeJson(await api.get(`/api/${group}/${idSegment(positionals[0])}`));
902
+ }
903
+ fail(`Unknown ${group} command '${sub}'.`);
904
+ }
905
+ function columnList(value) {
906
+ const columns = value.split(",").map((column) => column.trim());
907
+ if (columns.some((column) => !column))
908
+ fail("--columns takes column names separated by commas.");
909
+ return columns.join(",");
910
+ }
911
+
760
912
  // src/commands/files.ts
761
913
  import { access } from "fs/promises";
762
914
  async function files(api, args) {
@@ -776,20 +928,28 @@ async function files(api, args) {
776
928
  if (sub === "download") {
777
929
  const { positionals, options } = parseCommandArgs(rest, { "--path": "string", "--output": "string" }, "files download", [2, 3]);
778
930
  const context = positionals[0];
931
+ const output = options["--output"];
932
+ if (context === "url") {
933
+ requireExact(positionals, 2, "files download url requires exactly one content URL.");
934
+ const url = parseContentUrl(positionals[1] ?? "");
935
+ if (!output)
936
+ fail("files download requires --output <local-path>.");
937
+ await api.download(url.pathname, output, Object.fromEntries(url.searchParams));
938
+ return writeJson({ downloaded: true, output });
939
+ }
779
940
  let route;
780
941
  if (context === "object") {
781
942
  requireExact(positionals, 3, "files download object requires object type and primary id.");
782
943
  const type = positionals[1] ?? "";
783
944
  const id = positionals[2] ?? "";
784
- route = `/api/objects/${encodeURIComponent(type)}/${encodeURIComponent(id)}/files/content`;
945
+ route = `/api/objects/${idSegment(type)}/${idSegment(id)}/files/content`;
785
946
  } else if (context === "action-run" || context === "workflow-run") {
786
947
  requireExact(positionals, 2, `files download ${context} requires exactly one run id.`);
787
948
  const id = positionals[1] ?? "";
788
- route = `/api/${context}s/${encodeURIComponent(id)}/files/content`;
949
+ route = `/api/${context}s/${idSegment(id)}/files/content`;
789
950
  } else
790
951
  fail(`Unknown file download context '${context}'.`);
791
952
  const path = options["--path"];
792
- const output = options["--output"];
793
953
  if (!path)
794
954
  fail("files download requires --path <json-pointer>.");
795
955
  if (!output)
@@ -799,6 +959,18 @@ async function files(api, args) {
799
959
  }
800
960
  fail(`Unknown files command '${sub}'.`);
801
961
  }
962
+ function parseContentUrl(value) {
963
+ let url;
964
+ try {
965
+ url = new URL(value);
966
+ } catch {
967
+ fail(`'${value}' is not a URL.`);
968
+ }
969
+ if (!url.pathname.startsWith("/api/") || !url.pathname.endsWith("/files/content")) {
970
+ fail(`'${value}' is not a Sixb file content URL.`);
971
+ }
972
+ return url;
973
+ }
802
974
 
803
975
  // src/commands/models.ts
804
976
  import { access as access2, mkdir, stat } from "fs/promises";
@@ -979,7 +1151,7 @@ async function calls(api, args) {
979
1151
  fail(`Unknown models calls command '${sub ?? ""}'. Use 'models calls files'.`);
980
1152
  const { positionals, options } = parseCommandArgs(rest, { "--output": "string" }, "models calls files", 1);
981
1153
  const callId = positionals[0] ?? "";
982
- const call = await api.get(`/api/ai/model-calls/${encodeURIComponent(callId)}/files`);
1154
+ const call = await api.get(`/api/ai/model-calls/${idSegment(callId)}/files`);
983
1155
  const output = options["--output"];
984
1156
  if (output === undefined)
985
1157
  return writeJson(call);
@@ -1052,7 +1224,7 @@ async function saveFiles(api, callId, files, output) {
1052
1224
  });
1053
1225
  for (const [index, path] of paths.entries()) {
1054
1226
  await mkdir(dirname2(path), { recursive: true });
1055
- await api.download(`/api/ai/model-calls/${encodeURIComponent(callId)}/files/content`, path, {
1227
+ await api.download(`/api/ai/model-calls/${idSegment(callId)}/files/content`, path, {
1056
1228
  path: `/files/${index}`
1057
1229
  });
1058
1230
  }
@@ -1696,7 +1868,7 @@ async function ontology(api, args) {
1696
1868
  if (requestsHelp(rest))
1697
1869
  return writeText("Usage: sixb ontology get <object-type>");
1698
1870
  const { positionals } = parseCommandArgs(rest, {}, "ontology get", 1);
1699
- return writeJson(await api.get(`/api/object-types/${encodeURIComponent(positionals[0] ?? "")}`));
1871
+ return writeJson(await api.get(`/api/object-types/${idSegment(positionals[0])}`));
1700
1872
  }
1701
1873
  fail(`Unknown ontology command '${sub}'.`);
1702
1874
  }
@@ -1722,12 +1894,25 @@ var WORKFLOW_RUN_STATUSES = [
1722
1894
  "failed",
1723
1895
  "cancelled"
1724
1896
  ];
1897
+ var DATA_RUN_STATUSES = ["queued", "running", "succeeded", "failed", "cancelled"];
1898
+ var STATUSES = {
1899
+ action: ACTION_RUN_STATUSES,
1900
+ workflow: WORKFLOW_RUN_STATUSES,
1901
+ sync: DATA_RUN_STATUSES,
1902
+ pipeline: DATA_RUN_STATUSES
1903
+ };
1904
+ var FILTERS = {
1905
+ action: { "--action": "actionId", "--type": "objectTypeId", "--id": "primaryId" },
1906
+ workflow: { "--workflow": "workflowId" },
1907
+ sync: { "--sync": "syncId", "--dataset": "datasetId" },
1908
+ pipeline: { "--pipeline": "pipelineId" }
1909
+ };
1725
1910
  async function runs(api, kind, args) {
1726
1911
  const [sub, ...rest] = args;
1727
1912
  const group = `${kind}-runs`;
1728
1913
  if (!sub || isHelp(sub) || requestsHelp(rest))
1729
1914
  return writeText(GROUP_HELP[group]);
1730
- if (sub === "get") {
1915
+ if (sub === "get" && kind !== "sync") {
1731
1916
  const { positionals } = parseCommandArgs(rest, {}, `${group} get`, 1);
1732
1917
  return writeJson(await api.get(`/api/${group}/${encodeURIComponent(positionals[0] ?? "")}`));
1733
1918
  }
@@ -1740,21 +1925,14 @@ async function runs(api, kind, args) {
1740
1925
  "--offset": "offset",
1741
1926
  "--order": "order"
1742
1927
  };
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`), {
1928
+ const options = normalizeWindowOptions(parseQueryOptions(rest, { ...common, ...FILTERS[kind] }, `${group} list`), {
1751
1929
  defaultLimit: CLI_LIMITS.list.default,
1752
1930
  maximumLimit: CLI_LIMITS.list.maximum,
1753
1931
  defaultOrder: DEFAULT_LIST_ORDER,
1754
1932
  offset: true
1755
1933
  });
1756
1934
  if (options.status !== undefined) {
1757
- options.status = enumValue("--status", options.status, kind === "action" ? ACTION_RUN_STATUSES : WORKFLOW_RUN_STATUSES);
1935
+ options.status = enumValue("--status", options.status, STATUSES[kind]);
1758
1936
  }
1759
1937
  for (const [name, flag] of [
1760
1938
  ["startedAfter", "--started-after"],
@@ -1808,7 +1986,7 @@ async function telemetry(api, args) {
1808
1986
  fail(`Unknown telemetry command '${sub}'.`);
1809
1987
  }
1810
1988
  function telemetryPath(args, terminal) {
1811
- return `/api/objects/${encodeURIComponent(args[0] ?? "")}/${encodeURIComponent(args[1] ?? "")}/telemetry/${encodeURIComponent(args[2] ?? "")}/${terminal}`;
1989
+ return `/api/objects/${idSegment(args[0])}/${idSegment(args[1])}/telemetry/${idSegment(args[2])}/${terminal}`;
1812
1990
  }
1813
1991
  function normalizeTelemetryQueryInput(input) {
1814
1992
  if (Array.isArray(input) || typeof input !== "object" || input === null) {
@@ -1850,7 +2028,18 @@ async function users(api, args) {
1850
2028
  return writeText(GROUP_HELP.users);
1851
2029
  if (sub === "get") {
1852
2030
  const { positionals } = parseCommandArgs(rest, {}, "users get", 1);
1853
- return writeJson(await api.get(`/api/users/${encodeURIComponent(positionals[0] ?? "")}`));
2031
+ const user = positionals[0]?.trim();
2032
+ if (!user)
2033
+ fail("users get requires a user id or email.");
2034
+ if (!user.includes("@")) {
2035
+ return writeJson(await api.get(`/api/users/${idSegment(user)}`));
2036
+ }
2037
+ const page = await api.get("/api/users", { email: user });
2038
+ const [member] = isRecord(page) && Array.isArray(page.users) ? page.users : [];
2039
+ if (member === undefined) {
2040
+ throw new CliError({ code: "not_found", message: `No member has the email '${user}'.` }, EXIT_API);
2041
+ }
2042
+ return writeJson(member);
1854
2043
  }
1855
2044
  if (sub === "list") {
1856
2045
  const { options } = parseCommandArgs(rest, LIST_FLAGS, "users list");
@@ -1873,6 +2062,9 @@ function listQuery(options) {
1873
2062
  ...options["--offset"] === undefined ? {} : { offset: String(nonNegativeInteger("--offset", options["--offset"])) }
1874
2063
  };
1875
2064
  }
2065
+ function isRecord(value) {
2066
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2067
+ }
1876
2068
 
1877
2069
  // src/commands/workflows.ts
1878
2070
  import { randomUUID as randomUUID3 } from "crypto";
@@ -1888,7 +2080,7 @@ async function workflows(api, args) {
1888
2080
  const {
1889
2081
  positionals: [workflowId]
1890
2082
  } = parseCommandArgs(rest, {}, "workflows get", 1);
1891
- return writeJson(await api.get(`/api/workflows/${encodeURIComponent(workflowId ?? "")}`));
2083
+ return writeJson(await api.get(`/api/workflows/${idSegment(workflowId)}`));
1892
2084
  }
1893
2085
  if (sub === "start") {
1894
2086
  const {
@@ -1900,7 +2092,7 @@ async function workflows(api, args) {
1900
2092
  fail("Workflow input must be a JSON object.");
1901
2093
  }
1902
2094
  const runId = options["--run-id"] ?? `run_${randomUUID3()}`;
1903
- return writeRequestResult(await api.post(`/api/workflows/${encodeURIComponent(workflowId ?? "")}/runs`, {
2095
+ return writeRequestResult(await api.post(`/api/workflows/${idSegment(workflowId)}/runs`, {
1904
2096
  input,
1905
2097
  runId
1906
2098
  }));
@@ -1920,7 +2112,12 @@ var INSTANCE_COMMANDS = [
1920
2112
  "workflows",
1921
2113
  "workflow-runs",
1922
2114
  "users",
1923
- "models"
2115
+ "models",
2116
+ "datasets",
2117
+ "syncs",
2118
+ "sync-runs",
2119
+ "pipelines",
2120
+ "pipeline-runs"
1924
2121
  ];
1925
2122
  function isInstanceCommand(command) {
1926
2123
  return INSTANCE_COMMANDS.includes(command);
@@ -1949,6 +2146,16 @@ async function dispatch(api, command, args) {
1949
2146
  return users(api, args);
1950
2147
  case "models":
1951
2148
  return models(api, args);
2149
+ case "datasets":
2150
+ return datasets(api, args);
2151
+ case "syncs":
2152
+ return runnables(api, "syncs", args);
2153
+ case "sync-runs":
2154
+ return runs(api, "sync", args);
2155
+ case "pipelines":
2156
+ return runnables(api, "pipelines", args);
2157
+ case "pipeline-runs":
2158
+ return runs(api, "pipeline", args);
1952
2159
  default:
1953
2160
  fail(`Unknown command '${command}'. Run 'sixb --help'.`);
1954
2161
  }
@@ -1963,29 +2170,54 @@ function createInstanceApiClient(mode) {
1963
2170
  baseUrl: mode.baseUrl,
1964
2171
  ...mode.kind === "local" && mode.token ? { authorization: `Bearer ${mode.token}` } : {},
1965
2172
  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."
2173
+ unavailableMessage: mode.kind === "sandbox" ? "The Sixb API could not be reached from the sandbox." : "The Sixb API could not be reached.",
2174
+ 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
2175
  });
1969
2176
  }
2177
+
2178
+ // src/commands/system.ts
2179
+ var AGENT_RUNTIME_PROFILE = "sixb-agent-runtime/v1";
2180
+ // src/memory.ts
2181
+ import { createHash } from "crypto";
2182
+ var AGENT_MEMORY_MANIFEST = "context/memory.json";
2183
+ var AGENT_MEMORY_ENTRY = "MEMORY.md";
2184
+ var AGENT_MEMORY_STARTER = `# Memory
2185
+
2186
+ `;
2187
+ function agentMemoryFileHash(contents) {
2188
+ return createHash("sha256").update(contents).digest("hex");
2189
+ }
2190
+ // src/sandbox-cli.ts
2191
+ import { readFile as readFile3 } from "fs/promises";
2192
+ var cachedAssets;
2193
+ function loadSandboxCliAssets() {
2194
+ cachedAssets ??= Promise.all([
2195
+ readFile3(new URL("./bin/sixb", import.meta.url), "utf8"),
2196
+ readFile3(new URL("./generated/sixb.mjs", import.meta.url))
2197
+ ]).then(([launcher, artifact]) => ({ launcher, artifact }));
2198
+ return cachedAssets;
2199
+ }
1970
2200
  export {
2201
+ AGENT_MEMORY_ENTRY,
2202
+ AGENT_MEMORY_MANIFEST,
2203
+ AGENT_MEMORY_STARTER,
2204
+ AGENT_RUNTIME_PROFILE,
1971
2205
  ApiClient,
1972
2206
  CliError,
1973
2207
  EXIT_API,
1974
2208
  EXIT_USAGE,
1975
2209
  INSTANCE_CLI_VERSION,
1976
2210
  INSTANCE_COMMANDS,
1977
- asRecord2 as asRecord,
2211
+ agentMemoryFileHash,
1978
2212
  createInstanceApiClient,
1979
2213
  fail,
1980
- isFileError,
1981
- isHelp,
1982
2214
  isInstanceCommand,
2215
+ loadSandboxCliAssets,
1983
2216
  renderInstanceHelp,
1984
2217
  reportError,
1985
2218
  requestsHelp,
1986
2219
  runInstanceCli,
1987
- writeJson,
1988
- writeText
2220
+ writeJson
1989
2221
  };
1990
2222
 
1991
- //# debugId=7F5CD0F40A1B96CA64756E2164756E21
2223
+ //# debugId=3808833041577FAB64756E2164756E21