@ornncompute/cli 1.0.138 → 1.0.139

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ornncompute/cli",
3
- "version": "1.0.138",
3
+ "version": "1.0.139",
4
4
  "description": "Command-line interface for Ornn compute access workflows.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -814,7 +814,7 @@ function assertCustomerResultSafe(value, ownOrganizationId) {
814
814
  }
815
815
 
816
816
  function parseCapabilityInput(capability, rawInput) {
817
- const parsed = capability.input.safeParse(rawInput);
817
+ const parsed = (capability.cli?.input ?? capability.input).safeParse(rawInput);
818
818
  if (parsed.success) return parsed.data;
819
819
  const issue = parsed.error.issues[0];
820
820
  if (issue?.path?.[0] === "$positionals") {
@@ -992,7 +992,7 @@ async function executeCapability(
992
992
  let ownOrganizationId;
993
993
  let data;
994
994
  try {
995
- data = await capability.execute(
995
+ data = await (capability.cli?.execute ?? capability.execute)(
996
996
  {
997
997
  actor: "",
998
998
  confirmed,
@@ -1,5 +1,6 @@
1
1
  import * as storageApi from "../vendor/api-client/orchestrator.js";
2
2
  import * as gatewayApi from "../vendor/api-client/gateway.js";
3
+ import { bucketShowCapability, bucketDisconnectCapability } from "../vendor/capabilities/cli.js";
3
4
  import { createHash } from "node:crypto";
4
5
  import { readFile } from "node:fs/promises";
5
6
 
@@ -479,7 +480,11 @@ async function listBuckets(input, runtime) {
479
480
 
480
481
  async function showBucket(input, runtime) {
481
482
  const [reference] = positions(input, 1, "ornn external-buckets show <external-bucket>");
482
- const bucket = resolveExternalBucket(await fetchDrives(runtime), reference);
483
+ const source = resolveExternalBucket(await fetchDrives(runtime), reference);
484
+ const bucket = await bucketShowCapability.execute(
485
+ { actor: "", role: "user", fetch: runtime.fetch },
486
+ { driveId: source.id }
487
+ );
483
488
  return runtime.interaction.result({ data: { external_bucket: safeExternalBucket(bucket) } });
484
489
  }
485
490
 
@@ -692,11 +697,20 @@ async function disconnectBucket(input, runtime) {
692
697
  );
693
698
  }
694
699
  try {
695
- await storageApi.deleteDrive(
696
- runtime.fetch,
697
- safe.id,
698
- {},
699
- { headers: idempotencyHeaders(input) }
700
+ await bucketDisconnectCapability.execute(
701
+ {
702
+ actor: "",
703
+ role: "user",
704
+ confirmed: true,
705
+ fetch: (path, init) =>
706
+ runtime.fetch(path, {
707
+ ...init,
708
+ ...(init?.method === "DELETE"
709
+ ? { headers: { ...init.headers, ...idempotencyHeaders(input) } }
710
+ : {}),
711
+ }),
712
+ },
713
+ { driveId: safe.id }
700
714
  );
701
715
  } catch (error) {
702
716
  throw safeExternalError(error, "The external bucket could not be disconnected safely.");
@@ -1,4 +1,5 @@
1
1
  import * as storageApi from "../vendor/api-client/orchestrator.js";
2
+ import { bucketListCapability, volumeFilesListCapability } from "../vendor/capabilities/cli.js";
2
3
  import { createHash } from "node:crypto";
3
4
  import { createReadStream } from "node:fs";
4
5
  import { stat } from "node:fs/promises";
@@ -292,11 +293,14 @@ export async function fetchDrivePage(runtime, { limit = 25, cursor, scope = "all
292
293
  usage("--limit must be an integer from 1 through 100.", "limit");
293
294
  }
294
295
  try {
295
- const payload = await storageApi.listDrives(runtime.fetch, {
296
- limit: Number(limit),
297
- scope,
298
- ...(cursor ? { cursor } : {}),
299
- });
296
+ const input = { limit: Number(limit), ...(cursor ? { cursor } : {}) };
297
+ const payload =
298
+ scope === "external"
299
+ ? await bucketListCapability.execute(
300
+ { actor: "", role: "user", fetch: runtime.fetch },
301
+ input
302
+ )
303
+ : await storageApi.listDrives(runtime.fetch, { ...input, scope });
300
304
  return { drives: volumeRows(payload), next_cursor: payload?.next_cursor ?? null };
301
305
  } catch (error) {
302
306
  throw safeStorageError(error, "Volumes could not be loaded safely.");
@@ -552,33 +556,21 @@ function shellQuote(value) {
552
556
  }
553
557
 
554
558
  async function fetchFileRows(runtime, drive, prefix) {
555
- const folder = prefix.includes("/") ? prefix.slice(0, prefix.lastIndexOf("/")) : "";
556
559
  const entries = [];
557
- let cursor = 0;
558
- while (cursor !== null) {
559
- let page;
560
- try {
561
- page = await storageApi.listDriveContents(runtime.fetch, String(drive.id), {
562
- recursive: true,
563
- ...(folder ? { path: folder } : {}),
564
- ...(cursor ? { cursor } : {}),
565
- });
566
- } catch (error) {
567
- throw safeStorageError(error, "Volume files could not be listed safely.");
568
- }
569
- entries.push(...(Array.isArray(page?.entries) ? page.entries : []));
570
- const next = page?.next_cursor;
571
- cursor = Number.isInteger(next) || (typeof next === "string" && next) ? next : null;
572
- }
573
- return entries
574
- .filter((entry) => entry?.kind === "file")
575
- .map(safeFile)
576
- .filter((entry) => entry.path && entry.path.startsWith(prefix))
577
- .sort(
578
- (left, right) =>
579
- (Date.parse(right.updated_at ?? "") || 0) - (Date.parse(left.updated_at ?? "") || 0) ||
580
- left.path.localeCompare(right.path)
560
+ try {
561
+ const files = await volumeFilesListCapability.execute(
562
+ { actor: "", role: "user", fetch: runtime.fetch },
563
+ { driveId: drive.id, prefix }
581
564
  );
565
+ for await (const entry of files) entries.push(safeFile(entry));
566
+ } catch (error) {
567
+ throw safeStorageError(error, "Volume files could not be listed safely.");
568
+ }
569
+ return entries.sort(
570
+ (left, right) =>
571
+ (Date.parse(right.updated_at ?? "") || 0) - (Date.parse(left.updated_at ?? "") || 0) ||
572
+ left.path.localeCompare(right.path)
573
+ );
582
574
  }
583
575
 
584
576
  async function listFiles(input, runtime) {
@@ -333,8 +333,8 @@ function defineCapability(spec) {
333
333
  ...rest,
334
334
  ...cli !== false && cli !== void 0 ? {
335
335
  cli: {
336
- command: cli.command ?? names.cli,
337
- ...cli.vnext ? { vnext: cli.vnext } : {}
336
+ ...cli,
337
+ command: cli.command ?? names.cli
338
338
  }
339
339
  } : {},
340
340
  ...mcp === false ? {} : { mcp: { name: mcp?.name ?? names.mcp } },
@@ -4730,30 +4730,119 @@ function externalBucketCapability({ acceptedReferences = [], automation, command
4730
4730
  });
4731
4731
  }
4732
4732
  var gcsImportGuidance = "GCS requires bucket-level read access for your organization's Ornn transfer account. Connecting prints the account and the two gcloud grants (roles/storage.objectViewer and roles/storage.legacyBucketReader). After granting, deploy the volume from the Ornn console; CLI 1.x import still requires verification, which GCS does not support. Steps: https://docs.ornn.com/cli#gcs-imports-and-storage-transfer-service";
4733
- var externalBucketCapabilities = [
4734
- externalBucketCapability({
4735
- id: "storage.external-buckets.list",
4733
+ function isExternalBucket(drive) {
4734
+ const source = drive.source;
4735
+ if (!source || source.managed === true || source.provider === "ornn_object")
4736
+ return false;
4737
+ return ["external_gcs", "s3", "r2", "cloudflare_r2"].includes(source.provider ?? "") || Boolean(source.bucket);
4738
+ }
4739
+ var bucketInput = z21.object({ driveId: z21.string() });
4740
+ var bucketListCapability = defineCapability({
4741
+ id: "storage.external-buckets.list",
4742
+ domain: "storage",
4743
+ roles: ["user"],
4744
+ description: "List a page of connected external buckets. Pass next_cursor as cursor to continue.",
4745
+ mutation: "read",
4746
+ input: z21.object({
4747
+ limit: z21.number().int().min(1).max(100).optional(),
4748
+ cursor: z21.string().optional()
4749
+ }),
4750
+ mcp: { name: "storage_buckets_list" },
4751
+ slack: false,
4752
+ execute: async (context, input) => {
4753
+ const page = await listDrives(context.fetch, {
4754
+ limit: input.limit ?? 25,
4755
+ scope: "external",
4756
+ ...input.cursor ? { cursor: input.cursor } : {}
4757
+ });
4758
+ return { ...page, drives: page.drives.filter(isExternalBucket) };
4759
+ },
4760
+ cli: {
4736
4761
  command: ["external-buckets", "list"],
4737
- description: "List connected GCS, S3, and R2 buckets in one bounded page.",
4738
- mutation: "read",
4739
4762
  input: pageInput2,
4740
- outcome: "List external bucket connections without exposing stored credentials.",
4741
- human: "ornn external-buckets list [--limit <1-100>] [--cursor <cursor>]",
4742
- automation: "ornn external-buckets list --limit 50 --format json",
4743
- related: ["external-buckets show", "external-buckets connect"]
4744
- }),
4745
- externalBucketCapability({
4746
- id: "storage.external-buckets.show",
4763
+ execute: (context, input) => externalBucketExecutor(context)("storage.external-buckets.list", input),
4764
+ vnext: {
4765
+ arguments: "semantic",
4766
+ audience: "customer",
4767
+ category: "resource",
4768
+ outcome: "List external bucket connections without exposing stored credentials.",
4769
+ human: "ornn external-buckets list [--limit <1-100>] [--cursor <cursor>]",
4770
+ automation: "ornn external-buckets list --limit 50 --format json",
4771
+ acceptedReferences: [],
4772
+ related: ["external-buckets show", "external-buckets connect"],
4773
+ resumableStates: []
4774
+ }
4775
+ }
4776
+ });
4777
+ var bucketShowCapability = defineCapability({
4778
+ id: "storage.external-buckets.show",
4779
+ domain: "storage",
4780
+ roles: ["user"],
4781
+ description: "Show a single connected external bucket by drive id.",
4782
+ mutation: "read",
4783
+ input: bucketInput,
4784
+ mcp: { name: "storage_buckets_show" },
4785
+ slack: false,
4786
+ execute: async (context, input) => {
4787
+ const bucket = await getDrive(context.fetch, input.driveId);
4788
+ if (!isExternalBucket(bucket))
4789
+ throw new Error(`Storage bucket not found: ${input.driveId}`);
4790
+ return bucket;
4791
+ },
4792
+ cli: {
4747
4793
  command: ["external-buckets", "show"],
4748
- description: "Inspect one connected external bucket by canonical ID or exact unique name.",
4749
- mutation: "read",
4750
4794
  input: showInput,
4751
- outcome: "Inspect one credential-safe external bucket connection.",
4752
- human: "ornn external-buckets show <external-bucket>",
4753
- automation: "ornn external-buckets show <external-bucket-id> --format json",
4754
- acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
4755
- related: ["external-buckets verify", "external-buckets import"]
4756
- }),
4795
+ execute: (context, input) => externalBucketExecutor(context)("storage.external-buckets.show", input),
4796
+ vnext: {
4797
+ arguments: "semantic",
4798
+ audience: "customer",
4799
+ category: "resource",
4800
+ outcome: "Inspect one credential-safe external bucket connection.",
4801
+ human: "ornn external-buckets show <external-bucket>",
4802
+ automation: "ornn external-buckets show <external-bucket-id> --format json",
4803
+ acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
4804
+ related: ["external-buckets verify", "external-buckets import"],
4805
+ resumableStates: []
4806
+ }
4807
+ }
4808
+ });
4809
+ var bucketDisconnectCapability = defineCapability({
4810
+ id: "storage.external-buckets.disconnect",
4811
+ domain: "storage",
4812
+ roles: ["user"],
4813
+ description: "Disconnect a connected external bucket (deletes the backing drive record).",
4814
+ mutation: "preview-confirm",
4815
+ input: bucketInput,
4816
+ mcp: { name: "storage_buckets_disconnect" },
4817
+ slack: false,
4818
+ execute: async (context, input) => {
4819
+ if (!context.confirmed)
4820
+ return preview("storage.external-buckets.disconnect", input);
4821
+ await bucketShowCapability.execute(context, input);
4822
+ await deleteDrive(context.fetch, input.driveId);
4823
+ return { disconnected: true, drive_id: input.driveId };
4824
+ },
4825
+ cli: {
4826
+ command: ["external-buckets", "disconnect"],
4827
+ input: disconnectInput,
4828
+ execute: (context, input) => externalBucketExecutor(context)("storage.external-buckets.disconnect", input),
4829
+ vnext: {
4830
+ arguments: "semantic",
4831
+ audience: "customer",
4832
+ category: "resource",
4833
+ outcome: "Remove one external source connection without writing to its source bucket.",
4834
+ human: "ornn external-buckets disconnect <external-bucket>",
4835
+ automation: "ornn external-buckets disconnect <external-bucket-id> --idempotency-key <key> --format json",
4836
+ acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
4837
+ review: "Disconnecting reduces access to the source and is blocked while mounts remain.",
4838
+ related: ["storage detach", "external-buckets show"],
4839
+ resumableStates: []
4840
+ }
4841
+ }
4842
+ });
4843
+ var externalBucketCapabilities = [
4844
+ bucketListCapability,
4845
+ bucketShowCapability,
4757
4846
  externalBucketCapability({
4758
4847
  id: "storage.external-buckets.connect",
4759
4848
  command: ["external-buckets", "connect"],
@@ -4806,19 +4895,7 @@ var externalBucketCapabilities = [
4806
4895
  resumableStates: ["pending", "working", "partial", "failed", "interrupted"],
4807
4896
  related: ["external-buckets show", "storage status", "volumes files list"]
4808
4897
  }),
4809
- externalBucketCapability({
4810
- id: "storage.external-buckets.disconnect",
4811
- command: ["external-buckets", "disconnect"],
4812
- description: "Disconnect an external bucket record after its working volume is detached.",
4813
- mutation: "preview-confirm",
4814
- input: disconnectInput,
4815
- outcome: "Remove one external source connection without writing to its source bucket.",
4816
- human: "ornn external-buckets disconnect <external-bucket>",
4817
- automation: "ornn external-buckets disconnect <external-bucket-id> --idempotency-key <key> --format json",
4818
- acceptedReferences: ["canonical external bucket ID", "exact unique external bucket name"],
4819
- review: "Disconnecting reduces access to the source and is blocked while mounts remain.",
4820
- related: ["storage detach", "external-buckets show"]
4821
- })
4898
+ bucketDisconnectCapability
4822
4899
  ];
4823
4900
 
4824
4901
  // ../../packages/capabilities/dist/capabilities/evidence.js
@@ -6444,6 +6521,50 @@ function storageCapability({ id, command, description, mutation, outcome, human,
6444
6521
  execute: async (context, input) => storageExecutor(context)(id, input)
6445
6522
  });
6446
6523
  }
6524
+ var filesListInput = z30.object({ driveId: z30.string(), prefix: z30.string().optional() });
6525
+ async function* listFiles(context, input) {
6526
+ const prefix = input.prefix ?? "";
6527
+ const folder = prefix.includes("/") ? prefix.slice(0, prefix.lastIndexOf("/")) : "";
6528
+ let cursor = 0;
6529
+ while (cursor !== null) {
6530
+ const page = await listDriveContents(context.fetch, input.driveId, {
6531
+ recursive: true,
6532
+ ...folder ? { path: folder } : {},
6533
+ ...cursor ? { cursor } : {}
6534
+ });
6535
+ for (const entry of page.entries) {
6536
+ if (entry.kind === "file" && entry.path.startsWith(prefix))
6537
+ yield entry;
6538
+ }
6539
+ cursor = page.next_cursor ?? null;
6540
+ }
6541
+ }
6542
+ var volumeFilesListCapability = defineCapability({
6543
+ id: "storage.volumes.files.list",
6544
+ domain: "storage",
6545
+ roles: ["user"],
6546
+ description: "List files on a storage volume (drive). Optional prefix filters paths. This is a listing only -- it does not download bytes.",
6547
+ mutation: "read",
6548
+ input: filesListInput,
6549
+ mcp: { name: "storage_files_ls" },
6550
+ slack: false,
6551
+ execute: async (context, input) => listFiles(context, input),
6552
+ cli: {
6553
+ command: ["volumes", "files", "list"],
6554
+ input: storageCliInput,
6555
+ execute: (context, input) => storageExecutor(context)("storage.volumes.files.list", input),
6556
+ vnext: {
6557
+ arguments: "semantic",
6558
+ audience: "customer",
6559
+ category: "resource",
6560
+ outcome: "List nested volume files by semantic remote path.",
6561
+ human: "ornn volumes files list <volume> [--prefix <remote-path>] [--limit <1-500>] [--cursor <cursor>]",
6562
+ automation: "ornn volumes files list <volume-id> --limit 50 --format json",
6563
+ acceptedReferences: ["canonical volume ID", "exact unique volume name"],
6564
+ related: ["volumes files upload", "volumes files download"]
6565
+ }
6566
+ }
6567
+ });
6447
6568
  var volumeCapabilities = [
6448
6569
  storageCapability({
6449
6570
  id: "storage.volumes.list",
@@ -6512,17 +6633,7 @@ var volumeCapabilities = [
6512
6633
  review: "The volume and all of its data are permanently deleted.",
6513
6634
  related: ["volume-mounts detach", "volumes show"]
6514
6635
  }),
6515
- storageCapability({
6516
- id: "storage.volumes.files.list",
6517
- command: ["volumes", "files", "list"],
6518
- description: "List nested files in one volume in a bounded page.",
6519
- mutation: "read",
6520
- outcome: "List nested volume files by semantic remote path.",
6521
- human: "ornn volumes files list <volume> [--prefix <remote-path>] [--limit <1-500>] [--cursor <cursor>]",
6522
- automation: "ornn volumes files list <volume-id> --limit 50 --format json",
6523
- acceptedReferences: ["canonical volume ID", "exact unique volume name"],
6524
- related: ["volumes files upload", "volumes files download"]
6525
- }),
6636
+ volumeFilesListCapability,
6526
6637
  storageCapability({
6527
6638
  id: "storage.volumes.files.upload",
6528
6639
  command: ["volumes", "files", "upload"],
@@ -6778,46 +6889,6 @@ var storageVerbCapabilities = [
6778
6889
  })
6779
6890
  })
6780
6891
  ];
6781
- var bucketListCapability = defineCapability({
6782
- id: "bucket.list",
6783
- domain: "storage",
6784
- roles: ["user"],
6785
- description: "List a page of connected external buckets. Pass next_cursor as cursor to continue.",
6786
- mutation: "read",
6787
- input: z30.object({
6788
- limit: z30.number().int().min(1).max(100).optional(),
6789
- cursor: z30.string().optional()
6790
- }),
6791
- mcp: { name: "storage_buckets_list" },
6792
- slack: false,
6793
- execute: (ctx, input) => listDrives(ctx.fetch, {
6794
- limit: input.limit ?? 25,
6795
- scope: "external",
6796
- ...input.cursor ? { cursor: input.cursor } : {}
6797
- })
6798
- });
6799
- var storageCompositionCapabilities = [
6800
- bucketListCapability,
6801
- defineCapability({
6802
- id: "volume.contents",
6803
- domain: "storage",
6804
- roles: ["user"],
6805
- description: "List one page of a storage volume's contents.",
6806
- mutation: "read",
6807
- input: z30.object({
6808
- driveId: z30.string(),
6809
- path: z30.string().optional(),
6810
- cursor: z30.union([z30.string(), z30.number()]).optional()
6811
- }),
6812
- mcp: false,
6813
- slack: false,
6814
- execute: (ctx, input) => listDriveContents(ctx.fetch, input.driveId, {
6815
- recursive: true,
6816
- ...input.path ? { path: input.path } : {},
6817
- ...input.cursor ? { cursor: input.cursor } : {}
6818
- })
6819
- })
6820
- ];
6821
6892
 
6822
6893
  // ../../packages/capabilities/dist/cli-catalog.js
6823
6894
  function canonicalCliCatalog(capabilities) {
@@ -6830,6 +6901,7 @@ function canonicalCliCatalog(capabilities) {
6830
6901
  return {
6831
6902
  ...capability,
6832
6903
  cli: {
6904
+ ...capability.cli,
6833
6905
  command: [...help3.command ?? capability.cli?.command ?? []],
6834
6906
  vnext: help3
6835
6907
  }
@@ -6859,7 +6931,6 @@ var catalog = [
6859
6931
  ...networkVerbCapabilities,
6860
6932
  ...accessVerbCapabilities,
6861
6933
  ...storageVerbCapabilities,
6862
- ...storageCompositionCapabilities,
6863
6934
  machinePushKeysCapability,
6864
6935
  ...machineMetricsCapabilities,
6865
6936
  ...billingCapabilities,
@@ -7137,11 +7208,15 @@ export {
7137
7208
  ADMIN_CLI_ROOTS,
7138
7209
  CLI_MIGRATION_GUIDE_URL,
7139
7210
  LEGACY_CLI_MIGRATIONS,
7211
+ bucketDisconnectCapability,
7212
+ bucketListCapability,
7213
+ bucketShowCapability,
7140
7214
  byCliCommand,
7141
7215
  byMcpName,
7142
7216
  catalog,
7143
7217
  findLegacyCliMigration,
7144
7218
  forRole,
7145
7219
  gpuDisplay,
7146
- parseHardwareCatalog
7220
+ parseHardwareCatalog,
7221
+ volumeFilesListCapability
7147
7222
  };