@ornncompute/cli 1.0.72 → 1.0.97

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 +55 -24
  2. package/package.json +4 -2
  3. package/src/admin-capacity-reservations.mjs +6 -13
  4. package/src/admin-command-handlers.mjs +2 -1
  5. package/src/admin-credits.mjs +1 -2
  6. package/src/admin-enrollment.mjs +22 -30
  7. package/src/admin-mutations.mjs +6 -56
  8. package/src/admin-node-diagnostics.mjs +3 -41
  9. package/src/admin-node-lifecycle.mjs +40 -160
  10. package/src/admin-node-sanitize.mjs +243 -0
  11. package/src/admin-shell.mjs +39 -32
  12. package/src/catalog-shell.mjs +6 -6
  13. package/src/evidence-commands.mjs +4 -6
  14. package/src/external-bucket-commands.mjs +76 -96
  15. package/src/interaction-runtime.mjs +5 -37
  16. package/src/kubernetes-commands.mjs +25 -183
  17. package/src/launch-mode-handlers.mjs +0 -1
  18. package/src/machine-reference.mjs +33 -56
  19. package/src/mount-commands.mjs +25 -131
  20. package/src/slurm-commands.mjs +13 -2
  21. package/src/storage-commands.mjs +2 -87
  22. package/src/vm-commands.mjs +48 -101
  23. package/vendor/api-client/commerce.js +743 -0
  24. package/vendor/capabilities/cli.js +7688 -7
  25. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +0 -101
  26. package/vendor/capabilities/capabilities/admin-enrollment.js +0 -321
  27. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +0 -88
  28. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +0 -235
  29. package/vendor/capabilities/capabilities/admin.js +0 -91
  30. package/vendor/capabilities/capabilities/cli.js +0 -156
  31. package/vendor/capabilities/capabilities/clusters.js +0 -248
  32. package/vendor/capabilities/capabilities/commerce-market.js +0 -405
  33. package/vendor/capabilities/capabilities/compute.js +0 -523
  34. package/vendor/capabilities/capabilities/credits.js +0 -78
  35. package/vendor/capabilities/capabilities/evidence.js +0 -145
  36. package/vendor/capabilities/capabilities/external-buckets.js +0 -191
  37. package/vendor/capabilities/capabilities/fleet.js +0 -306
  38. package/vendor/capabilities/capabilities/identity.js +0 -129
  39. package/vendor/capabilities/capabilities/listings.js +0 -398
  40. package/vendor/capabilities/capabilities/locality.js +0 -42
  41. package/vendor/capabilities/capabilities/market-shared.js +0 -46
  42. package/vendor/capabilities/capabilities/markets.js +0 -482
  43. package/vendor/capabilities/capabilities/mounts.js +0 -176
  44. package/vendor/capabilities/capabilities/native-listing.js +0 -99
  45. package/vendor/capabilities/capabilities/networks.js +0 -1264
  46. package/vendor/capabilities/capabilities/observability.js +0 -218
  47. package/vendor/capabilities/capabilities/organization-invites.js +0 -53
  48. package/vendor/capabilities/capabilities/reservation-list.js +0 -68
  49. package/vendor/capabilities/capabilities/staff-shared.js +0 -64
  50. package/vendor/capabilities/capabilities/tokens.js +0 -165
  51. package/vendor/capabilities/capabilities/users.js +0 -159
  52. package/vendor/capabilities/capabilities/volumes.js +0 -178
  53. package/vendor/capabilities/capability.js +0 -99
  54. package/vendor/capabilities/cli-catalog.js +0 -73
  55. package/vendor/capabilities/cli-migrations.js +0 -264
  56. package/vendor/capabilities/names.js +0 -6
  57. package/vendor/capabilities/software-catalog.js +0 -82
  58. package/vendor/capabilities/spec-catalog.js +0 -151
  59. package/vendor/capabilities/supplier-directory.js +0 -20
@@ -1,3 +1,4 @@
1
+ import { getReservation } from "../vendor/api-client/commerce.js";
1
2
  import { spawn as spawnProcessDefault } from "node:child_process";
2
3
  import { createHash } from "node:crypto";
3
4
  import { readFile } from "node:fs/promises";
@@ -9,6 +10,7 @@ import { resolvedMountPath } from "./mount-commands.mjs";
9
10
  import {
10
11
  isReferenceMiss,
11
12
  listActiveDirectReservations,
13
+ listActiveReservations,
12
14
  listOwnedActiveMachines,
13
15
  reservationLabeler,
14
16
  resolveMachineReference,
@@ -70,14 +72,13 @@ function machineAccessMode(value) {
70
72
 
71
73
  function reservationAccessMode(value) {
72
74
  const reservation = record(value);
73
- const mode =
74
- (text(reservation.access_mode) ?? text(reservation.accessMode))?.toLowerCase() ?? null;
75
+ const mode = text(reservation.provisioningType)?.toLowerCase() ?? null;
75
76
  return mode === "virtual-machine" ? "vm" : mode;
76
77
  }
77
78
 
78
79
  function isDirectReservation(value) {
79
80
  const mode = reservationAccessMode(value);
80
- return !mode || mode === "vm" || mode === "bare-metal";
81
+ return mode === "vm" || mode === "bare-metal";
81
82
  }
82
83
 
83
84
  function machineIsReady(value) {
@@ -303,7 +304,6 @@ function failedOperationRecoveryCommand(value, interaction) {
303
304
  `--mode ${accessMode}`,
304
305
  `--network ${networkMode}`,
305
306
  accessMode !== sourceMode ? "--erase-local-data" : null,
306
- "--yes",
307
307
  `--idempotency-key ${requestId}`,
308
308
  ]
309
309
  .filter(Boolean)
@@ -317,7 +317,6 @@ function failedOperationRecoveryCommand(value, interaction) {
317
317
  `ornn machines ${command}`,
318
318
  shellQuote(id),
319
319
  command === "reset" ? "--erase-local-data" : null,
320
- "--yes",
321
320
  `--idempotency-key ${requestId}`,
322
321
  ]
323
322
  .filter(Boolean)
@@ -392,7 +391,7 @@ function positional(input, expected, usage, interaction) {
392
391
  return values;
393
392
  }
394
393
 
395
- function machineMutationPreflight(input, interaction, { requireYes = true } = {}) {
394
+ function machineMutationPreflight(input, interaction) {
396
395
  if (!interaction.machine) return;
397
396
  if (!text(input.idempotencyKey)) {
398
397
  interaction.usage("--idempotency-key is required for automation.", {
@@ -400,12 +399,6 @@ function machineMutationPreflight(input, interaction, { requireYes = true } = {}
400
399
  field: "idempotencyKey",
401
400
  });
402
401
  }
403
- if (requireYes && input.yes !== true) {
404
- interaction.usage("--yes is required for automation after reviewing the exact intent.", {
405
- code: "consent_required",
406
- field: "yes",
407
- });
408
- }
409
402
  }
410
403
 
411
404
  async function selectedOrganization(context, interaction, expectedId) {
@@ -432,7 +425,7 @@ async function selectedOrganization(context, interaction, expectedId) {
432
425
 
433
426
  function assertActiveReservation(value, expectedRef, interaction, expectedMode = null) {
434
427
  const reservation = record(value);
435
- const ref = resourceId(reservation);
428
+ const ref = text(reservation.reservationId);
436
429
  if (!ref || ref !== expectedRef) {
437
430
  interaction.error("The gateway returned an unrelated capacity reservation.", {
438
431
  code: "reservation_correlation_changed",
@@ -471,7 +464,7 @@ async function resolveReservation(context, input, interaction, expectedMode = nu
471
464
  if (supplied) {
472
465
  const ref = requireCanonical(interaction, supplied, "reservation", "Capacity reservation");
473
466
  return assertActiveReservation(
474
- await context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(ref)}`),
467
+ await getReservation(context.fetch, ref),
475
468
  ref,
476
469
  interaction,
477
470
  expectedMode
@@ -483,29 +476,23 @@ async function resolveReservation(context, input, interaction, expectedMode = nu
483
476
  field: "reservation",
484
477
  });
485
478
  }
486
- const payload = await context.fetch("/v1/workflows/commerce/reservations?status=active&limit=50");
487
479
  const requestedMode = expectedMode ?? text(input.mode)?.toLowerCase() ?? null;
488
- const candidates = (Array.isArray(payload) ? payload : (record(payload).reservations ?? []))
489
- .map(record)
490
- .filter(
491
- (reservation) =>
492
- (text(reservation.status) ?? "").toLowerCase() === ACTIVE_RESERVATION &&
493
- resourceId(reservation) &&
494
- (!requestedMode || reservationAccessMode(reservation) === requestedMode)
495
- );
480
+ const candidates = (await listActiveReservations(context, interaction)).filter(
481
+ (reservation) => !requestedMode || reservationAccessMode(reservation) === requestedMode
482
+ );
496
483
  if (!candidates.length) {
497
484
  interaction.error("No active capacity reservation is eligible for launch.", {
498
485
  code: "no_active_reservation",
499
486
  });
500
487
  }
501
- let ref = resourceId(candidates[0]);
488
+ let ref = text(candidates[0].reservationId);
502
489
  if (candidates.length > 1) {
503
490
  const reservationLabel = await reservationLabeler(context.fetch);
504
491
  ref = await interaction.ask({
505
492
  label: "Capacity reservation",
506
493
  choices: candidates.map((reservation) => ({
507
494
  label: reservationLabel(reservation),
508
- value: resourceId(reservation),
495
+ value: text(reservation.reservationId),
509
496
  })),
510
497
  });
511
498
  }
@@ -514,7 +501,7 @@ async function resolveReservation(context, input, interaction, expectedMode = nu
514
501
  code: "missing_input",
515
502
  });
516
503
  return assertActiveReservation(
517
- await context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(ref)}`),
504
+ await getReservation(context.fetch, ref),
518
505
  ref,
519
506
  interaction,
520
507
  expectedMode
@@ -821,12 +808,6 @@ function launchInputPreflight(input, interaction) {
821
808
  field: "label",
822
809
  });
823
810
  }
824
- if (input.yes !== true) {
825
- interaction.usage("--yes is required for automation after reviewing the launch intent.", {
826
- code: "consent_required",
827
- field: "yes",
828
- });
829
- }
830
811
  if (!text(input.idempotencyKey)) {
831
812
  interaction.usage("--idempotency-key is required for automation.", {
832
813
  code: "idempotency_key_required",
@@ -1058,7 +1039,7 @@ export const vmLaunchModeHandler = {
1058
1039
  input = await normalizePublicKeyInput(input);
1059
1040
  const organization = await selectedOrganization(context, interaction);
1060
1041
  const reservation = await resolveReservation(context, input, interaction, "vm");
1061
- const reservationId = resourceId(reservation);
1042
+ const reservationId = text(reservation.reservationId);
1062
1043
  const keyPlan = await keyPlanFromInput(context, input, interaction);
1063
1044
  const [reviewedMachines, reviewedRelationships] = await Promise.all([
1064
1045
  fetchMachines(context, reservationId),
@@ -1109,9 +1090,7 @@ export const vmLaunchModeHandler = {
1109
1090
 
1110
1091
  await selectedOrganization(context, interaction, organization.id);
1111
1092
  const currentReservation = assertActiveReservation(
1112
- await context.fetch(
1113
- `/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`
1114
- ),
1093
+ await getReservation(context.fetch, reservationId),
1115
1094
  reservationId,
1116
1095
  interaction,
1117
1096
  "vm"
@@ -1199,7 +1178,7 @@ export const vmLaunchModeHandler = {
1199
1178
  resourceId(key),
1200
1179
  "--idempotency-key",
1201
1180
  idempotencyKey,
1202
- ...(interaction.machine ? ["--yes", "--no-wait", "--format", "json"] : []),
1181
+ ...(interaction.machine ? ["--no-wait", "--format", "json"] : []),
1203
1182
  ].join(" ");
1204
1183
  return uncertainMutationFailure(interaction, error, {
1205
1184
  data: {
@@ -1362,15 +1341,13 @@ function reservationAllocationContext(value) {
1362
1341
  const reservation = record(value);
1363
1342
  return {
1364
1343
  term: {
1365
- start: text(reservation.start_at) ?? text(reservation.start),
1366
- end: text(reservation.end_at) ?? text(reservation.end),
1344
+ start: text(reservation.startsAt),
1345
+ end: text(reservation.endsAt),
1367
1346
  },
1368
- machine_count: Number.isSafeInteger(reservation.node_count)
1369
- ? reservation.node_count
1370
- : Number.isSafeInteger(reservation.machine_count)
1371
- ? reservation.machine_count
1372
- : null,
1373
- gpu_count: Number.isSafeInteger(reservation.gpu_count) ? reservation.gpu_count : null,
1347
+ machine_count: reservation.reservedNodeCount,
1348
+ gpu_count: Number.isSafeInteger(reservation.reservedGpuCount)
1349
+ ? reservation.reservedGpuCount
1350
+ : null,
1374
1351
  };
1375
1352
  }
1376
1353
 
@@ -1434,7 +1411,7 @@ function bareMetalIntentSignature(reservation, relationships) {
1434
1411
  }
1435
1412
 
1436
1413
  function bareMetalLaunchData(reservation, machine, key, relationships, waitPolicy, replayed) {
1437
- const reservationId = resourceId(reservation);
1414
+ const reservationId = text(reservation.reservationId);
1438
1415
  const invocation = isSshReady(machine, key) ? sshInvocation(machine) : null;
1439
1416
  return {
1440
1417
  mode: "bare-metal",
@@ -1520,16 +1497,13 @@ function durableWorkspaceAllocation(reservation, interaction) {
1520
1497
  const endMilliseconds = Date.parse(end ?? "");
1521
1498
  const duration = endMilliseconds - startMilliseconds;
1522
1499
  const machineCount = allocation.machine_count;
1523
- const gpusPerMachine = Number.isSafeInteger(reservation.gpus_per_node)
1524
- ? reservation.gpus_per_node
1525
- : Number.isSafeInteger(reservation.gpus_per_machine)
1526
- ? reservation.gpus_per_machine
1527
- : null;
1500
+ const gpusPerMachine = reservation.gpusPerNode;
1528
1501
  const gpuCount = Number.isSafeInteger(allocation.gpu_count)
1529
1502
  ? allocation.gpu_count
1530
1503
  : Number.isSafeInteger(machineCount) && Number.isSafeInteger(gpusPerMachine)
1531
1504
  ? machineCount * gpusPerMachine
1532
1505
  : null;
1506
+ // CPU capacity has no GPUs; a workspace needs only its whole machines.
1533
1507
  if (
1534
1508
  !start ||
1535
1509
  !end ||
@@ -1537,9 +1511,7 @@ function durableWorkspaceAllocation(reservation, interaction) {
1537
1511
  !Number.isFinite(endMilliseconds) ||
1538
1512
  duration <= 0 ||
1539
1513
  !Number.isSafeInteger(machineCount) ||
1540
- machineCount < 1 ||
1541
- !Number.isSafeInteger(gpuCount) ||
1542
- gpuCount < 1
1514
+ machineCount < 1
1543
1515
  ) {
1544
1516
  interaction.error("The active capacity reservation does not contain valid allocation facts.", {
1545
1517
  code: "reservation_allocation_incomplete",
@@ -1559,7 +1531,6 @@ function durableWorkspaceAllocation(reservation, interaction) {
1559
1531
  function workspaceStepContext(context, interaction, signal) {
1560
1532
  const stepInteraction = Object.create(interaction);
1561
1533
  stepInteraction.review = async () => true;
1562
- stepInteraction.options = { ...interaction.options, yes: true };
1563
1534
  return {
1564
1535
  ...context,
1565
1536
  fetch: (path, init = {}) =>
@@ -1642,7 +1613,7 @@ function workspaceRelationshipConflict(facts, goal, interaction) {
1642
1613
  function durableWorkspaceSignature(reservation, key, facts, goal, interaction) {
1643
1614
  return JSON.stringify({
1644
1615
  capacity_reservation: {
1645
- id: resourceId(reservation),
1616
+ id: text(reservation.reservationId),
1646
1617
  status: text(reservation.status),
1647
1618
  allocation: durableWorkspaceAllocation(reservation, interaction),
1648
1619
  },
@@ -1681,7 +1652,7 @@ function workspaceResumeCommand(input, goal, facts, id, interaction, localResume
1681
1652
  if (goal.username) parts.push("--username", goal.username);
1682
1653
  if (input.noWait) parts.push("--no-wait");
1683
1654
  if (input.wait) parts.push("--wait", "--timeout", text(input.timeout));
1684
- if (interaction.machine) parts.push("--yes", "--format", interaction.format);
1655
+ if (interaction.machine) parts.push("--format", interaction.format);
1685
1656
  return parts.map(shellQuote).join(" ");
1686
1657
  }
1687
1658
 
@@ -1799,7 +1770,7 @@ async function launchDurableBareMetalWorkspace({
1799
1770
  keyPlan,
1800
1771
  }) {
1801
1772
  const id = workspaceId(input, interaction);
1802
- const reservationId = resourceId(reservation);
1773
+ const reservationId = text(reservation.reservationId);
1803
1774
  if (keyPlan.kind !== "existing") {
1804
1775
  interaction.usage("A durable Bare Metal workspace requires a declared existing SSH key.", {
1805
1776
  code: "workspace_ssh_key_required",
@@ -1843,8 +1814,8 @@ async function launchDurableBareMetalWorkspace({
1843
1814
  value: `${allocation.term.start} to ${allocation.term.end} (${allocation.term.hours} hours)`,
1844
1815
  },
1845
1816
  {
1846
- label: "GPU quantity",
1847
- value: `${allocation.quantity.gpu_count} GPUs across ${allocation.quantity.machine_count} machine${allocation.quantity.machine_count === 1 ? "" : "s"}`,
1817
+ label: "Quantity",
1818
+ value: `${allocation.quantity.gpu_count > 0 ? `${allocation.quantity.gpu_count} GPUs` : "CPU"} across ${allocation.quantity.machine_count} machine${allocation.quantity.machine_count === 1 ? "" : "s"}`,
1848
1819
  },
1849
1820
  {
1850
1821
  label: "Creation",
@@ -1875,7 +1846,7 @@ async function launchDurableBareMetalWorkspace({
1875
1846
 
1876
1847
  await selectedOrganization(context, interaction, organization.id);
1877
1848
  const [currentReservationValue, currentKeyPlan, currentFacts] = await Promise.all([
1878
- context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`),
1849
+ getReservation(context.fetch, reservationId),
1879
1850
  keyPlanFromInput(context, input, interaction),
1880
1851
  workspaceResourceFacts(context, interaction, input, reservationId),
1881
1852
  ]);
@@ -1952,7 +1923,6 @@ async function launchDurableBareMetalWorkspace({
1952
1923
  $positionals: [reservationId],
1953
1924
  key: resourceId(key),
1954
1925
  idempotencyKey: `${id}:ssh-key`,
1955
- yes: true,
1956
1926
  }
1957
1927
  );
1958
1928
  states.ssh_key_assignment = {
@@ -1988,7 +1958,6 @@ async function launchDurableBareMetalWorkspace({
1988
1958
  idempotencyKey: `${id}:volume-mount`,
1989
1959
  noWait: true,
1990
1960
  volume: facts.volume.id,
1991
- yes: true,
1992
1961
  }
1993
1962
  );
1994
1963
  facts.volumeMount = mount.data.volume_mount;
@@ -2307,7 +2276,7 @@ export const bareMetalLaunchModeHandler = {
2307
2276
  input = await normalizePublicKeyInput(input);
2308
2277
  const organization = await selectedOrganization(context, interaction, resumeOrganizationId);
2309
2278
  const reservation = await resolveReservation(context, input, interaction, "bare-metal");
2310
- const reservationId = resourceId(reservation);
2279
+ const reservationId = text(reservation.reservationId);
2311
2280
  const keyPlan = await keyPlanFromInput(context, input, interaction);
2312
2281
  if (durableWorkspace) {
2313
2282
  return launchDurableBareMetalWorkspace({
@@ -2375,7 +2344,7 @@ export const bareMetalLaunchModeHandler = {
2375
2344
 
2376
2345
  const [currentReservationValue, currentRelationships, existingAssigned, projectedMachines] =
2377
2346
  await Promise.all([
2378
- context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`),
2347
+ getReservation(context.fetch, reservationId),
2379
2348
  bareMetalRelationships(context, reservationId),
2380
2349
  fetchAssignedKeys(context, reservationId),
2381
2350
  fetchMachines(context, reservationId),
@@ -2464,7 +2433,7 @@ export const bareMetalLaunchModeHandler = {
2464
2433
  resourceId(key),
2465
2434
  "--idempotency-key",
2466
2435
  idempotencyKey,
2467
- ...(interaction.machine ? ["--yes", "--no-wait", "--format", "json"] : []),
2436
+ ...(interaction.machine ? ["--no-wait", "--format", "json"] : []),
2468
2437
  ].join(" ");
2469
2438
  return uncertainMutationFailure(interaction, error, {
2470
2439
  data: {
@@ -2757,9 +2726,7 @@ function createDirectMachineConnectModeHandler({
2757
2726
  code: "machine_correlation_failed",
2758
2727
  });
2759
2728
  }
2760
- const reservation = await context.fetch(
2761
- `/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`
2762
- );
2729
+ const reservation = await getReservation(context.fetch, reservationId);
2763
2730
  if (!isDirectReservation(reservation)) return null;
2764
2731
  const privateTransportRequired = text(machine.network_mode) === "private";
2765
2732
  return {
@@ -3002,24 +2969,12 @@ function validateWaitInput(input, interaction, { waitCommand = false } = {}) {
3002
2969
  function requireMachineMutationSafety(input, interaction, { destructive = false } = {}) {
3003
2970
  validateWaitInput(input, interaction);
3004
2971
  if (destructive && input.eraseLocalData !== true) {
3005
- interaction.usage(
3006
- "machines reset requires --erase-local-data; --yes cannot infer destructive scope.",
3007
- {
3008
- code: "erase_local_data_required",
3009
- field: "eraseLocalData",
3010
- }
3011
- );
2972
+ interaction.usage("machines reset requires --erase-local-data.", {
2973
+ code: "erase_local_data_required",
2974
+ field: "eraseLocalData",
2975
+ });
3012
2976
  }
3013
2977
  if (interaction.machine || !interaction.eligibleHuman) {
3014
- if (input.yes !== true) {
3015
- interaction.usage(
3016
- "--yes is required outside an eligible terminal after reviewing the exact intent.",
3017
- {
3018
- code: "consent_required",
3019
- field: "yes",
3020
- }
3021
- );
3022
- }
3023
2978
  if (!text(input.idempotencyKey)) {
3024
2979
  interaction.usage("--idempotency-key is required outside an eligible terminal.", {
3025
2980
  code: "idempotency_key_required",
@@ -3103,9 +3058,7 @@ async function resolveMachineCommandTarget(input, context, interaction, usage) {
3103
3058
  code: "machine_correlation_failed",
3104
3059
  });
3105
3060
  }
3106
- const reservation = await context.fetch(
3107
- `/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`
3108
- );
3061
+ const reservation = await getReservation(context.fetch, reservationId);
3109
3062
  if (!isDirectReservation(reservation)) {
3110
3063
  interaction.error(
3111
3064
  "The selected machine belongs to a cluster rather than the direct-machine lifecycle.",
@@ -3360,19 +3313,19 @@ async function guidedSwitchReservation(context, interaction) {
3360
3313
  code: "no_active_reservation",
3361
3314
  });
3362
3315
  }
3363
- let reference = resourceId(reservations[0]);
3316
+ let reference = text(reservations[0].reservationId);
3364
3317
  if (reservations.length > 1) {
3365
3318
  const reservationLabel = await reservationLabeler(context.fetch);
3366
3319
  reference = await interaction.ask({
3367
3320
  label: "Capacity reservation",
3368
3321
  choices: reservations.map((reservation) => ({
3369
3322
  label: reservationLabel(reservation),
3370
- value: resourceId(reservation),
3323
+ value: text(reservation.reservationId),
3371
3324
  })),
3372
3325
  });
3373
3326
  }
3374
3327
  return assertActiveReservation(
3375
- await context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(reference)}`),
3328
+ await getReservation(context.fetch, reference),
3376
3329
  reference,
3377
3330
  interaction
3378
3331
  );
@@ -3409,14 +3362,12 @@ async function switchMachine(input, context, interaction) {
3409
3362
  }
3410
3363
  const reservation = suppliedReservation
3411
3364
  ? assertActiveReservation(
3412
- await context.fetch(
3413
- `/v1/workflows/commerce/reservations/${encodeURIComponent(suppliedReservation)}`
3414
- ),
3365
+ await getReservation(context.fetch, suppliedReservation),
3415
3366
  suppliedReservation,
3416
3367
  interaction
3417
3368
  )
3418
3369
  : await guidedSwitchReservation(context, interaction);
3419
- const reservationId = resourceId(reservation);
3370
+ const reservationId = text(reservation.reservationId);
3420
3371
  if (!isDirectReservation(reservation)) {
3421
3372
  interaction.error("machines switch accepts only a direct VM or Bare Metal reservation.", {
3422
3373
  code: "reservation_not_direct",
@@ -3452,7 +3403,7 @@ async function switchMachine(input, context, interaction) {
3452
3403
  const erasesLocalData = targetMode !== currentMode;
3453
3404
  if (erasesLocalData && input.eraseLocalData !== true) {
3454
3405
  interaction.usage(
3455
- "Changing between VM and Bare Metal permanently erases source-local data and requires --erase-local-data; --yes cannot infer destructive scope.",
3406
+ "Changing between VM and Bare Metal permanently erases source-local data and requires --erase-local-data; cannot infer destructive scope.",
3456
3407
  { code: "erase_local_data_required", field: "eraseLocalData" }
3457
3408
  );
3458
3409
  }
@@ -3525,7 +3476,7 @@ async function switchMachine(input, context, interaction) {
3525
3476
  }
3526
3477
  const [currentReservationValue, currentMachines, currentRelationships, currentKeys] =
3527
3478
  await Promise.all([
3528
- context.fetch(`/v1/workflows/commerce/reservations/${encodeURIComponent(reservationId)}`),
3479
+ getReservation(context.fetch, reservationId),
3529
3480
  fetchMachines(context, reservationId),
3530
3481
  bareMetalRelationships(context, reservationId),
3531
3482
  fetchAssignedKeys(context, reservationId),
@@ -3561,7 +3512,6 @@ async function switchMachine(input, context, interaction) {
3561
3512
  requestedMode ? `--mode ${requestedMode}` : null,
3562
3513
  requestedNetwork ? `--network ${requestedNetwork}` : null,
3563
3514
  erasesLocalData ? "--erase-local-data" : null,
3564
- "--yes",
3565
3515
  "--no-wait",
3566
3516
  `--idempotency-key ${shellQuote(idempotencyKey)}`,
3567
3517
  ]
@@ -3663,7 +3613,6 @@ async function switchMachine(input, context, interaction) {
3663
3613
  `--mode ${targetMode}`,
3664
3614
  `--network ${targetNetwork}`,
3665
3615
  erasesLocalData ? "--erase-local-data" : null,
3666
- "--yes",
3667
3616
  `--idempotency-key ${shellQuote(interaction.idempotencyKey())}`,
3668
3617
  ]
3669
3618
  .filter(Boolean)
@@ -3781,7 +3730,6 @@ async function maintainMachine(command, input, context, interaction) {
3781
3730
  `ornn machines ${command}`,
3782
3731
  shellQuote(machineId(machine)),
3783
3732
  destructive ? "--erase-local-data" : null,
3784
- "--yes",
3785
3733
  "--no-wait",
3786
3734
  `--idempotency-key ${shellQuote(idempotencyKey)}`,
3787
3735
  ]
@@ -3874,7 +3822,6 @@ async function maintainMachine(command, input, context, interaction) {
3874
3822
  `ornn machines ${command}`,
3875
3823
  shellQuote(machineId(waitOutcome.value)),
3876
3824
  destructive ? "--erase-local-data" : null,
3877
- "--yes",
3878
3825
  `--idempotency-key ${shellQuote(interaction.idempotencyKey())}`,
3879
3826
  ]
3880
3827
  .filter(Boolean)