@ornncompute/cli 1.0.113 → 1.0.115
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/README.md +2 -3
- package/package.json +1 -1
- package/src/catalog-shell.mjs +4 -1
- package/src/device-auth.mjs +31 -25
- package/src/machine-reference.mjs +2 -1
- package/src/mount-commands.mjs +0 -206
- package/src/registry-commands.mjs +7 -2
- package/src/session-commands.mjs +20 -15
- package/vendor/api-client/authorization.js +128 -0
- package/vendor/capabilities/cli.js +7 -98
package/README.md
CHANGED
|
@@ -91,7 +91,6 @@ volumes files list | upload | download | delete
|
|
|
91
91
|
volumes folders delete
|
|
92
92
|
volume-mounts candidates | show | attach | wait | detach
|
|
93
93
|
external-buckets list | show | connect | update-credentials | verify | import | disconnect
|
|
94
|
-
filesystems deploy | show | wait | delete
|
|
95
94
|
```
|
|
96
95
|
|
|
97
96
|
`ssh-keys list` uses backend cursors; see [pagination](../../docs/cli.md#advanced-customer-resources).
|
|
@@ -273,7 +272,7 @@ as `--erase-local-data` or `--delete-node-record`. Machine retries require a
|
|
|
273
272
|
caller-stable idempotency key and reconcile against durable owner state.
|
|
274
273
|
|
|
275
274
|
Permanent deletion and teardown requests execute directly when explicitly
|
|
276
|
-
requested. Private networks, detached volumes,
|
|
275
|
+
requested. Private networks, detached volumes, and
|
|
277
276
|
Kubernetes or Slurm clusters use their command arguments to express the exact
|
|
278
277
|
operation. Clearing a volume or deleting nested content is live-terminal only
|
|
279
278
|
and does not prompt for consent.
|
|
@@ -365,7 +364,7 @@ with one replacement and <https://docs.ornn.com/cli#migrating-to-vnext>.
|
|
|
365
364
|
| `ornn storage volumes *` | `ornn volumes <verb>` |
|
|
366
365
|
| `ornn storage files *` | `ornn volumes files <verb>` |
|
|
367
366
|
| `ornn storage buckets *` | `ornn external-buckets <verb>` |
|
|
368
|
-
| Storage targets, deploy, status, detach
|
|
367
|
+
| Storage targets, deploy, status, detach | exact `ornn volume-mounts` leaf printed |
|
|
369
368
|
| `ornn billing` | Use the Ornn web app. |
|
|
370
369
|
| customer-root `facilities`, `tokens`, `users`, `node`, or staff `reservations *` | exact `ornn admin ...` command printed by the error |
|
|
371
370
|
| `ornn api`, `commerce`, `orchestrator`, `cache purge` | `ornn resources`; no generic replacement exists |
|
package/package.json
CHANGED
package/src/catalog-shell.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCliSession } from "../vendor/api-client/authorization.js";
|
|
1
2
|
import { readFileSync } from "node:fs";
|
|
2
3
|
|
|
3
4
|
import {
|
|
@@ -1009,7 +1010,9 @@ async function executeCapability(
|
|
|
1009
1010
|
}
|
|
1010
1011
|
if (capability.domain === "listings" && ownOrganizationId === undefined) {
|
|
1011
1012
|
// Verify listing owner IDs before the request, never after a committed mutation.
|
|
1012
|
-
const session = await
|
|
1013
|
+
const session = await getCliSession((path, init) =>
|
|
1014
|
+
customerCapabilityFetch(io, path, init, authSnapshot)
|
|
1015
|
+
);
|
|
1013
1016
|
ownOrganizationId = session.selectedOrganization?.id ?? null;
|
|
1014
1017
|
}
|
|
1015
1018
|
return customerCapabilityFetch(io, path, init, authSnapshot);
|
package/src/device-auth.mjs
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
startCliDeviceAuthorization,
|
|
3
|
+
pollCliDeviceAuthorization,
|
|
4
|
+
} from "../vendor/api-client/authorization.js";
|
|
1
5
|
import { spawn } from "node:child_process";
|
|
2
6
|
|
|
3
7
|
import { configuredAuthBaseUrl } from "./auth-store.mjs";
|
|
@@ -90,7 +94,7 @@ export async function openBrowser(url, { platform = process.platform, spawnImpl
|
|
|
90
94
|
|
|
91
95
|
export async function startDeviceFlow({ apiBaseUrl, authBaseUrl, fetchImpl = fetch } = {}) {
|
|
92
96
|
const requestBaseUrl = apiBaseUrl || authBaseUrl;
|
|
93
|
-
const data = await
|
|
97
|
+
const data = await startCliDeviceAuthorization(deviceRequest(fetchImpl, requestBaseUrl));
|
|
94
98
|
|
|
95
99
|
const deviceCode = pickString(data, "deviceCode", "device_code");
|
|
96
100
|
const userCode = pickString(data, "userCode", "user_code");
|
|
@@ -126,11 +130,10 @@ export async function pollDeviceFlow({
|
|
|
126
130
|
signal,
|
|
127
131
|
} = {}) {
|
|
128
132
|
const requestBaseUrl = apiBaseUrl || authBaseUrl;
|
|
129
|
-
return
|
|
130
|
-
fetchImpl,
|
|
131
|
-
`${requestBaseUrl}/v1/cli/device/poll`,
|
|
133
|
+
return pollCliDeviceAuthorization(
|
|
134
|
+
deviceRequest(fetchImpl, requestBaseUrl),
|
|
132
135
|
{ device_code: deviceCode },
|
|
133
|
-
|
|
136
|
+
signal
|
|
134
137
|
);
|
|
135
138
|
}
|
|
136
139
|
|
|
@@ -258,28 +261,31 @@ export async function waitForDeviceApproval({
|
|
|
258
261
|
}
|
|
259
262
|
}
|
|
260
263
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const data = text ? parseJson(text, url) : {};
|
|
273
|
-
|
|
274
|
-
if (!response.ok) {
|
|
275
|
-
const detail = data.detail || data.error || response.statusText;
|
|
276
|
-
throw new DeviceAuthError(`Auth request failed: ${detail}`, {
|
|
277
|
-
detail: data,
|
|
278
|
-
status: response.status,
|
|
264
|
+
function deviceRequest(fetchImpl, baseUrl) {
|
|
265
|
+
return async (path, { body, method, signal } = {}) => {
|
|
266
|
+
const url = `${baseUrl}${path}`;
|
|
267
|
+
const response = await fetchImpl(url, {
|
|
268
|
+
body: JSON.stringify(body),
|
|
269
|
+
headers: {
|
|
270
|
+
Accept: "application/json",
|
|
271
|
+
"Content-Type": "application/json",
|
|
272
|
+
},
|
|
273
|
+
method,
|
|
274
|
+
...(signal ? { signal } : {}),
|
|
279
275
|
});
|
|
280
|
-
|
|
276
|
+
const text = await response.text();
|
|
277
|
+
const data = text ? parseJson(text, url) : {};
|
|
281
278
|
|
|
282
|
-
|
|
279
|
+
if (!response.ok) {
|
|
280
|
+
const detail = data.detail || data.error || response.statusText;
|
|
281
|
+
throw new DeviceAuthError(`Auth request failed: ${detail}`, {
|
|
282
|
+
detail: data,
|
|
283
|
+
status: response.status,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return data;
|
|
288
|
+
};
|
|
283
289
|
}
|
|
284
290
|
|
|
285
291
|
function parseJson(text, url) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCliSession } from "../vendor/api-client/authorization.js";
|
|
1
2
|
import { listAllReservations } from "../vendor/api-client/commerce.js";
|
|
2
3
|
import { gpuLabeler } from "./gpu-catalog.mjs";
|
|
3
4
|
|
|
@@ -114,7 +115,7 @@ function invalidGateway(interaction, message) {
|
|
|
114
115
|
export async function listActiveReservations(context, interaction) {
|
|
115
116
|
const session = context.cli?.session
|
|
116
117
|
? (await context.cli.session("context", {})).data
|
|
117
|
-
: await context.fetch
|
|
118
|
+
: await getCliSession(context.fetch);
|
|
118
119
|
const customerId = text((session.selectedOrganization ?? session.selected_organization)?.id);
|
|
119
120
|
if (!customerId) {
|
|
120
121
|
interaction.usage("Select an organization before choosing a reservation.", {
|
package/src/mount-commands.mjs
CHANGED
|
@@ -55,17 +55,6 @@ function accessMode(value, interaction) {
|
|
|
55
55
|
return candidate;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function positiveInteger(value, field, interaction) {
|
|
59
|
-
const parsed = integer(value);
|
|
60
|
-
if (parsed === null || parsed < 1) {
|
|
61
|
-
interaction.usage(`--${field} must be a positive integer.`, {
|
|
62
|
-
code: "invalid_input",
|
|
63
|
-
field,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return parsed;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
58
|
function timeoutMilliseconds(value, interaction, fallback = DEFAULT_MOUNT_TIMEOUT) {
|
|
70
59
|
const candidate = text(value) ?? fallback;
|
|
71
60
|
const match = /^(\d+)(ms|s|m|h)$/.exec(candidate);
|
|
@@ -141,12 +130,6 @@ function reservationDeploymentPath(reservationId) {
|
|
|
141
130
|
);
|
|
142
131
|
}
|
|
143
132
|
|
|
144
|
-
function reservationFilesystemPath(reservationId) {
|
|
145
|
-
return computeEndpoint(
|
|
146
|
-
`/nodes/reservations/${encodeURIComponent(reservationId)}/filesystem-deployment`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
133
|
function stableAttachmentPhase(value) {
|
|
151
134
|
const state = text(value)?.toLowerCase() ?? "pending";
|
|
152
135
|
if (["attached", "ready"].includes(state)) return state;
|
|
@@ -255,14 +238,6 @@ function mountSatisfied(mount, goal) {
|
|
|
255
238
|
);
|
|
256
239
|
}
|
|
257
240
|
|
|
258
|
-
function filesystemSatisfied(mount, performanceTier, capacityGib) {
|
|
259
|
-
return Boolean(
|
|
260
|
-
mount &&
|
|
261
|
-
mount.filesystem.performance_tier === performanceTier &&
|
|
262
|
-
mount.filesystem.capacity_gib === capacityGib
|
|
263
|
-
);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
241
|
function mountReady(mount) {
|
|
267
242
|
return Boolean(
|
|
268
243
|
mount && mount.readiness.expected > 0 && mount.readiness.ready === mount.readiness.expected
|
|
@@ -843,179 +818,6 @@ export async function detachVolumeMount(input, runtime) {
|
|
|
843
818
|
});
|
|
844
819
|
}
|
|
845
820
|
|
|
846
|
-
async function deployFilesystem(input, runtime) {
|
|
847
|
-
const [rawReservation] = positionals(
|
|
848
|
-
input,
|
|
849
|
-
1,
|
|
850
|
-
"ornn filesystems deploy <canonical-reservation-id> --performance-tier <tier> --capacity-gib <gib>",
|
|
851
|
-
runtime.interaction
|
|
852
|
-
);
|
|
853
|
-
requireMachineMutation(input, runtime.interaction);
|
|
854
|
-
const reservationId = canonical(rawReservation, "reservation", runtime.interaction);
|
|
855
|
-
const performanceTier = required(input.performanceTier, "performance-tier", runtime.interaction);
|
|
856
|
-
const capacityGib = positiveInteger(input.capacityGib, "capacity-gib", runtime.interaction);
|
|
857
|
-
const wait = shouldWait(input, runtime.interaction);
|
|
858
|
-
let current = await fetchMount(runtime, reservationId);
|
|
859
|
-
if (current && ["detached", "ended"].includes(current.lifecycle.phase)) current = null;
|
|
860
|
-
if (current) {
|
|
861
|
-
const sameGoal = filesystemSatisfied(current, performanceTier, capacityGib);
|
|
862
|
-
if (!sameGoal) {
|
|
863
|
-
runtime.interaction.error(
|
|
864
|
-
"This capacity reservation already has a different managed filesystem relationship.",
|
|
865
|
-
{
|
|
866
|
-
action: {
|
|
867
|
-
command: `ornn filesystems show ${reservationId}`,
|
|
868
|
-
description:
|
|
869
|
-
"Inspect the current deployment before changing its exact capacity or performance goal.",
|
|
870
|
-
type: "command",
|
|
871
|
-
},
|
|
872
|
-
code: "filesystem_deployment_conflict",
|
|
873
|
-
}
|
|
874
|
-
);
|
|
875
|
-
}
|
|
876
|
-
return wait && !mountReady(current)
|
|
877
|
-
? waitForMount(input, runtime, reservationId, current, "filesystems deploy")
|
|
878
|
-
: mountResult(runtime.interaction, current, reservationId, { replayed: true });
|
|
879
|
-
}
|
|
880
|
-
current = await fetchMount(runtime, reservationId);
|
|
881
|
-
if (current && ["detached", "ended"].includes(current.lifecycle.phase)) current = null;
|
|
882
|
-
if (current && !filesystemSatisfied(current, performanceTier, capacityGib)) {
|
|
883
|
-
runtime.interaction.error("The managed filesystem relationship changed before deployment.", {
|
|
884
|
-
code: "filesystem_deployment_conflict",
|
|
885
|
-
});
|
|
886
|
-
}
|
|
887
|
-
if (!current) {
|
|
888
|
-
try {
|
|
889
|
-
current = await withMachineCount(
|
|
890
|
-
runtime,
|
|
891
|
-
projectVolumeMount(
|
|
892
|
-
await runtime.fetch(reservationFilesystemPath(reservationId), {
|
|
893
|
-
method: "POST",
|
|
894
|
-
headers: idempotencyHeaders(input),
|
|
895
|
-
body: { performance_tier: performanceTier, capacity_gib: capacityGib },
|
|
896
|
-
}),
|
|
897
|
-
reservationId
|
|
898
|
-
),
|
|
899
|
-
reservationId
|
|
900
|
-
);
|
|
901
|
-
} catch (error) {
|
|
902
|
-
if (error instanceof CliApiError && (error.status === undefined || error.status >= 500)) {
|
|
903
|
-
current = await fetchMount(runtime, reservationId);
|
|
904
|
-
if (!filesystemSatisfied(current, performanceTier, capacityGib)) throw error;
|
|
905
|
-
} else {
|
|
906
|
-
safeFailure(runtime.interaction, error, "The filesystem could not be deployed safely.");
|
|
907
|
-
}
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
if (!filesystemSatisfied(current, performanceTier, capacityGib)) {
|
|
911
|
-
runtime.interaction.error(
|
|
912
|
-
"The accepted filesystem deployment did not match the reviewed goal.",
|
|
913
|
-
{
|
|
914
|
-
code: "filesystem_deployment_goal_mismatch",
|
|
915
|
-
}
|
|
916
|
-
);
|
|
917
|
-
}
|
|
918
|
-
return wait && !mountReady(current)
|
|
919
|
-
? waitForMount(input, runtime, reservationId, current, "filesystems deploy")
|
|
920
|
-
: mountResult(runtime.interaction, current, reservationId);
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
function filesystemExecution(result) {
|
|
924
|
-
if (!result?.data || !Object.hasOwn(result.data, "volume_mount")) return result;
|
|
925
|
-
const { volume_mount: filesystemDeployment, ...data } = result.data;
|
|
926
|
-
return {
|
|
927
|
-
...result,
|
|
928
|
-
data: {
|
|
929
|
-
...data,
|
|
930
|
-
filesystem_deployment: filesystemDeployment,
|
|
931
|
-
},
|
|
932
|
-
};
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
async function deleteFilesystem(input, runtime) {
|
|
936
|
-
const [rawReservation] = positionals(
|
|
937
|
-
input,
|
|
938
|
-
1,
|
|
939
|
-
"ornn filesystems delete <canonical-reservation-id>",
|
|
940
|
-
runtime.interaction
|
|
941
|
-
);
|
|
942
|
-
requireMachineMutation(input, runtime.interaction);
|
|
943
|
-
const reservationId = canonical(rawReservation, "reservation", runtime.interaction);
|
|
944
|
-
const current = await fetchMount(runtime, reservationId);
|
|
945
|
-
if (!current || ["detached", "ended"].includes(current.lifecycle.phase)) {
|
|
946
|
-
return runtime.interaction.result({
|
|
947
|
-
data: {
|
|
948
|
-
filesystem_deployment: current,
|
|
949
|
-
replayed: true,
|
|
950
|
-
reservation_id: reservationId,
|
|
951
|
-
volume_preserved: current?.volume ?? null,
|
|
952
|
-
},
|
|
953
|
-
outcome: { class: "ended", phase: "deleted" },
|
|
954
|
-
presentation: {
|
|
955
|
-
lines: [
|
|
956
|
-
`Capacity reservation ${reservationId} already has no managed filesystem deployment.`,
|
|
957
|
-
],
|
|
958
|
-
},
|
|
959
|
-
});
|
|
960
|
-
}
|
|
961
|
-
const refreshed = await fetchMount(runtime, reservationId);
|
|
962
|
-
if (!refreshed || refreshed.id !== current.id || refreshed.volume.id !== current.volume.id) {
|
|
963
|
-
runtime.interaction.error("The managed filesystem relationship changed before deletion.", {
|
|
964
|
-
code: "filesystem_deployment_changed",
|
|
965
|
-
});
|
|
966
|
-
}
|
|
967
|
-
let deleting;
|
|
968
|
-
try {
|
|
969
|
-
deleting = await withMachineCount(
|
|
970
|
-
runtime,
|
|
971
|
-
projectVolumeMount(
|
|
972
|
-
await runtime.fetch(reservationFilesystemPath(reservationId), {
|
|
973
|
-
headers: idempotencyHeaders(input),
|
|
974
|
-
method: "DELETE",
|
|
975
|
-
}),
|
|
976
|
-
reservationId
|
|
977
|
-
),
|
|
978
|
-
reservationId
|
|
979
|
-
);
|
|
980
|
-
} catch (error) {
|
|
981
|
-
if (error instanceof CliApiError && (error.status === undefined || error.status >= 500)) {
|
|
982
|
-
const reconciled = await fetchMount(runtime, reservationId);
|
|
983
|
-
const deletingState = reconciled?.filesystem?.phase;
|
|
984
|
-
if (
|
|
985
|
-
reconciled &&
|
|
986
|
-
!["deleting", "deleted", "ended"].includes(deletingState) &&
|
|
987
|
-
!["detached", "ended"].includes(reconciled.lifecycle.phase)
|
|
988
|
-
) {
|
|
989
|
-
throw error;
|
|
990
|
-
}
|
|
991
|
-
deleting = reconciled;
|
|
992
|
-
} else {
|
|
993
|
-
safeFailure(
|
|
994
|
-
runtime.interaction,
|
|
995
|
-
error,
|
|
996
|
-
"The filesystem deployment could not be deleted safely."
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
return runtime.interaction.result({
|
|
1001
|
-
data: {
|
|
1002
|
-
filesystem_deployment: deleting,
|
|
1003
|
-
replayed: false,
|
|
1004
|
-
reservation_id: reservationId,
|
|
1005
|
-
volume_preserved: current.volume,
|
|
1006
|
-
},
|
|
1007
|
-
outcome: { class: "working", phase: "deleting" },
|
|
1008
|
-
resume: { kind: "filesystem_deployment", ref: reservationId },
|
|
1009
|
-
presentation: {
|
|
1010
|
-
lines: [
|
|
1011
|
-
`Filesystem deployment removal accepted for ${reservationId}.`,
|
|
1012
|
-
`Managed volume ${current.volume.name ?? current.volume.id} was preserved.`,
|
|
1013
|
-
],
|
|
1014
|
-
next: `ornn filesystems show ${reservationId}`,
|
|
1015
|
-
},
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
821
|
export async function executeMountCommand(command, input, runtime) {
|
|
1020
822
|
switch (command) {
|
|
1021
823
|
case "storage.volume-mounts.candidates":
|
|
@@ -1028,14 +830,6 @@ export async function executeMountCommand(command, input, runtime) {
|
|
|
1028
830
|
return waitCommand(input, runtime, "volume-mounts wait");
|
|
1029
831
|
case "storage.volume-mounts.detach":
|
|
1030
832
|
return detachVolumeMount(input, runtime);
|
|
1031
|
-
case "storage.filesystems.deploy":
|
|
1032
|
-
return filesystemExecution(await deployFilesystem(input, runtime));
|
|
1033
|
-
case "storage.filesystems.show":
|
|
1034
|
-
return filesystemExecution(await show(input, runtime, "filesystems show"));
|
|
1035
|
-
case "storage.filesystems.wait":
|
|
1036
|
-
return filesystemExecution(await waitCommand(input, runtime, "filesystems wait"));
|
|
1037
|
-
case "storage.filesystems.delete":
|
|
1038
|
-
return deleteFilesystem(input, runtime);
|
|
1039
833
|
default:
|
|
1040
834
|
runtime.interaction.error("Unknown mount command.", { code: "unknown_command" });
|
|
1041
835
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
listApiKeys,
|
|
3
|
+
createApiKey,
|
|
4
|
+
revokeApiKey,
|
|
5
|
+
getCliSession,
|
|
6
|
+
} from "../vendor/api-client/authorization.js";
|
|
2
7
|
import { spawn as spawnProcessDefault } from "node:child_process";
|
|
3
8
|
import os from "node:os";
|
|
4
9
|
|
|
@@ -19,7 +24,7 @@ async function login({
|
|
|
19
24
|
hostname = os.hostname(),
|
|
20
25
|
}) {
|
|
21
26
|
const registry = await fetch("/v1/orchestrator/registry");
|
|
22
|
-
const session = await fetch
|
|
27
|
+
const session = await getCliSession(fetch);
|
|
23
28
|
const organizationId = (session?.selectedOrganization ?? session?.selected_organization)?.id;
|
|
24
29
|
if (typeof organizationId !== "string" || !organizationId) {
|
|
25
30
|
interaction.usage("Join an organization before logging in to its registry.", {
|
package/src/session-commands.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCliSession, revokeCliSession } from "../vendor/api-client/authorization.js";
|
|
1
2
|
import { CliApiError, cliRequest, resolveApiBaseUrl } from "./api-client.mjs";
|
|
2
3
|
import {
|
|
3
4
|
bindAuthUser,
|
|
@@ -143,13 +144,15 @@ async function context({ env, fetchImpl, sessionSnapshot }) {
|
|
|
143
144
|
sessionSnapshot.current = localSession;
|
|
144
145
|
}
|
|
145
146
|
const data = sessionContext(
|
|
146
|
-
await
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
await getCliSession((endpoint, init) =>
|
|
148
|
+
cliRequest({
|
|
149
|
+
...init,
|
|
150
|
+
endpoint,
|
|
151
|
+
env,
|
|
152
|
+
fetchImpl,
|
|
153
|
+
session: localSession,
|
|
154
|
+
})
|
|
155
|
+
)
|
|
153
156
|
);
|
|
154
157
|
await bindAuthUser(data.user, {
|
|
155
158
|
env,
|
|
@@ -291,14 +294,16 @@ async function logout(runtime) {
|
|
|
291
294
|
try {
|
|
292
295
|
if (!revocationError && session?.accessToken) {
|
|
293
296
|
attempted = true;
|
|
294
|
-
await
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
297
|
+
await revokeCliSession((endpoint, init) =>
|
|
298
|
+
cliRequest({
|
|
299
|
+
...init,
|
|
300
|
+
endpoint,
|
|
301
|
+
env: runtime.env,
|
|
302
|
+
fetchImpl: runtime.fetchImpl,
|
|
303
|
+
raw: true,
|
|
304
|
+
session,
|
|
305
|
+
})
|
|
306
|
+
);
|
|
302
307
|
}
|
|
303
308
|
} catch (error) {
|
|
304
309
|
revocationError = error;
|
|
@@ -305,22 +305,137 @@ function createSupplierApplication(fetcher, body, query = {}) {
|
|
|
305
305
|
body: JSON.stringify(body)
|
|
306
306
|
});
|
|
307
307
|
}
|
|
308
|
+
|
|
309
|
+
// ../../packages/api-client/dist/authorization/sessions.js
|
|
310
|
+
var browserSessionPath = "/v1/auth/session";
|
|
311
|
+
var signInPath = "/v1/auth/sign-in";
|
|
312
|
+
var inviteRedeemPath = "/v1/auth/invites/redeem";
|
|
313
|
+
var unsubscribePath = "/v1/auth/unsubscribe";
|
|
314
|
+
var post = (body, signal) => ({
|
|
315
|
+
method: "POST",
|
|
316
|
+
headers: { "Content-Type": "application/json" },
|
|
317
|
+
body: JSON.stringify(body),
|
|
318
|
+
...signal ? { signal } : {}
|
|
319
|
+
});
|
|
320
|
+
function getBrowserSession(fetcher, query = {}, options = {}) {
|
|
321
|
+
return fetcher(withQuery(browserSessionPath, query), { ...options, method: "GET" });
|
|
322
|
+
}
|
|
323
|
+
function signOutBrowserSession(fetcher, next) {
|
|
324
|
+
return fetcher(withQuery("/v1/auth/sign-out", { next }), post({}));
|
|
325
|
+
}
|
|
326
|
+
function changeEmail(fetcher, body) {
|
|
327
|
+
return fetcher("/v1/auth/change-email", post(body));
|
|
328
|
+
}
|
|
329
|
+
function authorizeStaff(fetcher, body, signal) {
|
|
330
|
+
return fetcher("/v1/authorize", post(body, signal));
|
|
331
|
+
}
|
|
332
|
+
function createSlackSession(fetcher, body, signal) {
|
|
333
|
+
return fetcher("/v1/slack/session", post(body, signal));
|
|
334
|
+
}
|
|
335
|
+
function startCliDeviceAuthorization(request) {
|
|
336
|
+
return request("/v1/cli/device/start", {
|
|
337
|
+
method: "POST",
|
|
338
|
+
body: {}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
function pollCliDeviceAuthorization(request, body, signal) {
|
|
342
|
+
return request("/v1/cli/device/poll", { method: "POST", body, signal });
|
|
343
|
+
}
|
|
344
|
+
function approveCliDeviceAuthorization(fetcher, body) {
|
|
345
|
+
return fetcher("/v1/cli/device/approve", post(body));
|
|
346
|
+
}
|
|
347
|
+
function getCliSession(request) {
|
|
348
|
+
return request("/v1/cli/session", { method: "GET" });
|
|
349
|
+
}
|
|
350
|
+
function revokeCliSession(request) {
|
|
351
|
+
return request("/v1/cli/session", { method: "DELETE" });
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ../../packages/api-client/dist/authorization/mcp.js
|
|
355
|
+
function getMcpApplication(fetcher, clientId) {
|
|
356
|
+
return fetcher(`/v1/mcp/applications/${encodeURIComponent(clientId)}`, { method: "GET" });
|
|
357
|
+
}
|
|
358
|
+
function listMcpConnections(fetcher, userId) {
|
|
359
|
+
return fetcher(withQuery("/v1/mcp/connections", { user_id: userId }), { method: "GET" });
|
|
360
|
+
}
|
|
361
|
+
function revokeMcpConnection(fetcher, userId, clientId) {
|
|
362
|
+
return fetcher(withQuery(`/v1/mcp/connections/${encodeURIComponent(clientId)}`, { user_id: userId }), { method: "DELETE" });
|
|
363
|
+
}
|
|
364
|
+
function resolveMcpSession(fetcher, token) {
|
|
365
|
+
return fetcher("/v1/mcp/session", {
|
|
366
|
+
method: "POST",
|
|
367
|
+
headers: { "Content-Type": "application/json" },
|
|
368
|
+
body: JSON.stringify({ token })
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function authorizeMcp(fetcher, body, signal) {
|
|
372
|
+
return fetcher("/v1/auth/mcp/authorize", {
|
|
373
|
+
method: "POST",
|
|
374
|
+
headers: { "Content-Type": "application/json" },
|
|
375
|
+
body: JSON.stringify(body),
|
|
376
|
+
signal
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
function consentMcp(fetcher, body, signal) {
|
|
380
|
+
return fetcher("/v1/auth/mcp/consent", {
|
|
381
|
+
method: "POST",
|
|
382
|
+
headers: { "Content-Type": "application/json" },
|
|
383
|
+
body: JSON.stringify(body),
|
|
384
|
+
signal
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ../../packages/api-client/dist/authorization/impersonation.js
|
|
389
|
+
function getActiveImpersonationGrant(fetcher, staffUserId) {
|
|
390
|
+
return fetcher(`/v1/impersonation/active/${encodeURIComponent(staffUserId)}`, { method: "GET" });
|
|
391
|
+
}
|
|
392
|
+
function deleteImpersonationGrant(fetcher, staffUserId) {
|
|
393
|
+
return fetcher(`/v1/impersonation/${encodeURIComponent(staffUserId)}`, { method: "DELETE" });
|
|
394
|
+
}
|
|
395
|
+
function listImpersonationCustomers(request, query = {}, signal) {
|
|
396
|
+
return request(withQuery("/v1/staff/impersonation/customers", query), {
|
|
397
|
+
method: "GET",
|
|
398
|
+
signal
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
function startStaffImpersonation(fetcher, body) {
|
|
402
|
+
return fetcher("/v1/staff/impersonation/start", {
|
|
403
|
+
method: "POST",
|
|
404
|
+
headers: { "Content-Type": "application/json" },
|
|
405
|
+
body: JSON.stringify(body)
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
function stopStaffImpersonation(fetcher) {
|
|
409
|
+
return fetcher("/v1/staff/impersonation/stop", { method: "POST" });
|
|
410
|
+
}
|
|
308
411
|
export {
|
|
309
412
|
acceptInvite,
|
|
310
413
|
addStaffOrganizationMember,
|
|
414
|
+
approveCliDeviceAuthorization,
|
|
311
415
|
approveSupplierApplicationFromSlack,
|
|
416
|
+
authorizeMcp,
|
|
417
|
+
authorizeStaff,
|
|
312
418
|
bookOnboardingCall,
|
|
419
|
+
browserSessionPath,
|
|
313
420
|
cancelOnboardingCall,
|
|
314
421
|
cancelOrganizationFollowUp,
|
|
422
|
+
changeEmail,
|
|
423
|
+
consentMcp,
|
|
315
424
|
countOrganizations,
|
|
316
425
|
createApiKey,
|
|
317
426
|
createInvite,
|
|
318
427
|
createOrganization,
|
|
428
|
+
createSlackSession,
|
|
319
429
|
createSshKey,
|
|
320
430
|
createStaffInvite,
|
|
321
431
|
createStaffOrganization,
|
|
322
432
|
createSupplierApplication,
|
|
433
|
+
deleteImpersonationGrant,
|
|
434
|
+
getActiveImpersonationGrant,
|
|
435
|
+
getBrowserSession,
|
|
436
|
+
getCliSession,
|
|
323
437
|
getInvite,
|
|
438
|
+
getMcpApplication,
|
|
324
439
|
getNotificationPreferences,
|
|
325
440
|
getOrganization,
|
|
326
441
|
getOrganizationMembership,
|
|
@@ -328,10 +443,13 @@ export {
|
|
|
328
443
|
getStaffOrganization,
|
|
329
444
|
getUserPreferences,
|
|
330
445
|
getUserProfile,
|
|
446
|
+
inviteRedeemPath,
|
|
331
447
|
listAllSshKeys,
|
|
332
448
|
listApiKeys,
|
|
333
449
|
listAvailabilityAlerts,
|
|
450
|
+
listImpersonationCustomers,
|
|
334
451
|
listInvites,
|
|
452
|
+
listMcpConnections,
|
|
335
453
|
listOnboardingSlots,
|
|
336
454
|
listOrganizationMembers,
|
|
337
455
|
listOrganizations,
|
|
@@ -344,16 +462,26 @@ export {
|
|
|
344
462
|
listSupplierOrganizations,
|
|
345
463
|
organizationAvatarPath,
|
|
346
464
|
personAvatarPath,
|
|
465
|
+
pollCliDeviceAuthorization,
|
|
347
466
|
removeOrganizationMember,
|
|
348
467
|
removeStaffOrganizationMember,
|
|
468
|
+
resolveMcpSession,
|
|
349
469
|
revokeApiKey,
|
|
470
|
+
revokeCliSession,
|
|
350
471
|
revokeInvite,
|
|
472
|
+
revokeMcpConnection,
|
|
351
473
|
revokeSshKey,
|
|
352
474
|
revokeStaffOrganizationInvite,
|
|
353
475
|
searchStaffOrganizations,
|
|
354
476
|
searchStaffPeople,
|
|
355
477
|
setAvailabilityAlert,
|
|
478
|
+
signInPath,
|
|
479
|
+
signOutBrowserSession,
|
|
480
|
+
startCliDeviceAuthorization,
|
|
481
|
+
startStaffImpersonation,
|
|
482
|
+
stopStaffImpersonation,
|
|
356
483
|
submitOnboardingIntake,
|
|
484
|
+
unsubscribePath,
|
|
357
485
|
updateNotificationPreferences,
|
|
358
486
|
updateOrganization,
|
|
359
487
|
updateOrganizationApproval,
|
|
@@ -268,6 +268,11 @@ function createStaffInvite(request, body2) {
|
|
|
268
268
|
return request("/v1/staff/invites", { method: "POST", body: body2 });
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
// ../../packages/api-client/dist/authorization/sessions.js
|
|
272
|
+
function getCliSession(request) {
|
|
273
|
+
return request("/v1/cli/session", { method: "GET" });
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
// ../../packages/capabilities/dist/supplier-directory.js
|
|
272
277
|
function listSupplierOrganizationPage(fetch, input) {
|
|
273
278
|
return listOrganizations(fetch, {
|
|
@@ -3322,7 +3327,6 @@ var launchCapability = cliOnly({
|
|
|
3322
3327
|
"machines list",
|
|
3323
3328
|
"clusters show",
|
|
3324
3329
|
"volume-mounts show",
|
|
3325
|
-
"filesystems show",
|
|
3326
3330
|
"ssh-keys list",
|
|
3327
3331
|
"ssh-keys assignments status"
|
|
3328
3332
|
]
|
|
@@ -4841,12 +4845,10 @@ import { z as z23 } from "zod";
|
|
|
4841
4845
|
var mountInput = z23.object({
|
|
4842
4846
|
$positionals: z23.array(z23.string()).default([]),
|
|
4843
4847
|
access: z23.string().optional(),
|
|
4844
|
-
capacityGib: z23.union([z23.string(), z23.number()]).optional(),
|
|
4845
4848
|
cursor: z23.string().optional(),
|
|
4846
4849
|
idempotencyKey: z23.string().optional(),
|
|
4847
4850
|
limit: z23.union([z23.string(), z23.number()]).optional(),
|
|
4848
4851
|
noWait: z23.boolean().optional(),
|
|
4849
|
-
performanceTier: z23.string().optional(),
|
|
4850
4852
|
timeout: z23.string().optional(),
|
|
4851
4853
|
volume: z23.string().optional(),
|
|
4852
4854
|
wait: z23.boolean().optional(),
|
|
@@ -4955,59 +4957,6 @@ var mountCapabilities = [
|
|
|
4955
4957
|
review: "Review the exact relationship and access loss; the managed volume remains.",
|
|
4956
4958
|
resumableStates: ["detaching", "ended"],
|
|
4957
4959
|
related: ["volumes show", "private-networks list"]
|
|
4958
|
-
}),
|
|
4959
|
-
mountCapability({
|
|
4960
|
-
id: "storage.filesystems.deploy",
|
|
4961
|
-
command: ["filesystems", "deploy"],
|
|
4962
|
-
description: "Deploy one managed filesystem for an exact capacity reservation.",
|
|
4963
|
-
mutation: "preview-confirm",
|
|
4964
|
-
order: 550,
|
|
4965
|
-
outcome: "Create or rediscover one filesystem deployment and expose every machine mount.",
|
|
4966
|
-
human: "ornn filesystems deploy <canonical-reservation-id> --performance-tier <tier> --capacity-gib <gib> [--no-wait]",
|
|
4967
|
-
automation: "ornn filesystems deploy <canonical-reservation-id> --performance-tier <tier> --capacity-gib <gib> --idempotency-key <key> --format json",
|
|
4968
|
-
acceptedReferences: ["canonical capacity-reservation ID"],
|
|
4969
|
-
review: "Review the exact reservation, performance tier, capacity, and managed filesystem consequence.",
|
|
4970
|
-
resumableStates: ["accepted", "partial", "ready"],
|
|
4971
|
-
related: ["filesystems wait", "filesystems delete"]
|
|
4972
|
-
}),
|
|
4973
|
-
mountCapability({
|
|
4974
|
-
id: "storage.filesystems.show",
|
|
4975
|
-
command: ["filesystems", "show"],
|
|
4976
|
-
description: "Summarize one filesystem deployment from its underlying per-machine mounts.",
|
|
4977
|
-
mutation: "read",
|
|
4978
|
-
order: 551,
|
|
4979
|
-
outcome: "Show actual per-machine filesystem readiness without changing volume state.",
|
|
4980
|
-
human: "ornn filesystems show <canonical-reservation-id>",
|
|
4981
|
-
automation: "ornn filesystems show <canonical-reservation-id> --format json",
|
|
4982
|
-
acceptedReferences: ["canonical capacity-reservation ID"],
|
|
4983
|
-
related: ["filesystems wait", "volume-mounts show"]
|
|
4984
|
-
}),
|
|
4985
|
-
mountCapability({
|
|
4986
|
-
id: "storage.filesystems.wait",
|
|
4987
|
-
command: ["filesystems", "wait"],
|
|
4988
|
-
description: "Wait locally for a filesystem deployment's per-machine mount goal.",
|
|
4989
|
-
mutation: "read",
|
|
4990
|
-
order: 552,
|
|
4991
|
-
outcome: "Wait for every filesystem member while retaining partial member data.",
|
|
4992
|
-
human: "ornn filesystems wait <canonical-reservation-id> [--timeout <duration>]",
|
|
4993
|
-
automation: "ornn filesystems wait <canonical-reservation-id> --timeout <duration> --format json",
|
|
4994
|
-
acceptedReferences: ["canonical capacity-reservation ID"],
|
|
4995
|
-
resumableStates: ["partial", "ready"],
|
|
4996
|
-
related: ["filesystems show", "filesystems delete"]
|
|
4997
|
-
}),
|
|
4998
|
-
mountCapability({
|
|
4999
|
-
id: "storage.filesystems.delete",
|
|
5000
|
-
command: ["filesystems", "delete"],
|
|
5001
|
-
description: "Remove one filesystem deployment relationship without deleting its managed volume.",
|
|
5002
|
-
mutation: "preview-confirm",
|
|
5003
|
-
order: 553,
|
|
5004
|
-
outcome: "Detach every filesystem member while preserving the underlying managed volume.",
|
|
5005
|
-
human: "ornn filesystems delete <canonical-reservation-id>",
|
|
5006
|
-
automation: "ornn filesystems delete <canonical-reservation-id> --idempotency-key <key> --format json",
|
|
5007
|
-
acceptedReferences: ["canonical capacity-reservation ID"],
|
|
5008
|
-
review: "Review the exact deployment and access loss; its managed volume remains.",
|
|
5009
|
-
resumableStates: ["detaching", "ended"],
|
|
5010
|
-
related: ["volumes show", "filesystems deploy"]
|
|
5011
4960
|
})
|
|
5012
4961
|
];
|
|
5013
4962
|
|
|
@@ -5109,7 +5058,7 @@ var whoamiCapability = defineCapability({
|
|
|
5109
5058
|
mutation: "read",
|
|
5110
5059
|
http: { method: "GET", path: "/v1/cli/session" },
|
|
5111
5060
|
input: emptyInput3,
|
|
5112
|
-
execute: async (ctx) => ctx.fetch
|
|
5061
|
+
execute: async (ctx) => getCliSession(ctx.fetch)
|
|
5113
5062
|
});
|
|
5114
5063
|
var statusCapability = defineCapability({
|
|
5115
5064
|
id: "identity.status",
|
|
@@ -7505,7 +7454,7 @@ var storageVerbCapabilities = [
|
|
|
7505
7454
|
id: "storage.deployment_status",
|
|
7506
7455
|
domain: "storage",
|
|
7507
7456
|
roles: ["user"],
|
|
7508
|
-
description: "Show a reservation's storage
|
|
7457
|
+
description: "Show a reservation's storage deployment (attachment) status.",
|
|
7509
7458
|
mutation: "read",
|
|
7510
7459
|
http: {
|
|
7511
7460
|
method: "GET",
|
|
@@ -7517,42 +7466,6 @@ var storageVerbCapabilities = [
|
|
|
7517
7466
|
method: "GET"
|
|
7518
7467
|
})
|
|
7519
7468
|
}),
|
|
7520
|
-
defineCapability({
|
|
7521
|
-
id: "storage.filesystem_deploy",
|
|
7522
|
-
domain: "storage",
|
|
7523
|
-
roles: ["user"],
|
|
7524
|
-
description: "Deploy a managed filesystem (Filestore) onto a reservation. Both performanceTier and capacityGib are required. Capacity starts at 1024 GiB and must land on the tier's increment: standard accepts any GiB up to 65433, performance uses 256 GiB steps to 9984 GiB then 2560 GiB steps to 102400 GiB, enterprise uses 256 GiB steps to 10240 GiB.",
|
|
7525
|
-
mutation: "preview-confirm",
|
|
7526
|
-
http: {
|
|
7527
|
-
method: "POST",
|
|
7528
|
-
path: "/v1/workflows/compute/nodes/reservations/{reservationId}/filesystem-deployment"
|
|
7529
|
-
},
|
|
7530
|
-
input: reservationWrite.extend({
|
|
7531
|
-
performanceTier: z30.enum(["standard", "performance", "enterprise"]),
|
|
7532
|
-
capacityGib: z30.number().int().positive()
|
|
7533
|
-
}),
|
|
7534
|
-
slack: false,
|
|
7535
|
-
execute: (ctx, input) => ctx.fetch(reservationStorageRoute(input.reservationId, "filesystem-deployment"), {
|
|
7536
|
-
method: "POST",
|
|
7537
|
-
body: { performance_tier: input.performanceTier, capacity_gib: input.capacityGib }
|
|
7538
|
-
})
|
|
7539
|
-
}),
|
|
7540
|
-
defineCapability({
|
|
7541
|
-
id: "storage.filesystem_delete",
|
|
7542
|
-
domain: "storage",
|
|
7543
|
-
roles: ["user"],
|
|
7544
|
-
description: "Delete a reservation's managed filesystem (Filestore) deployment.",
|
|
7545
|
-
mutation: "preview-confirm",
|
|
7546
|
-
http: {
|
|
7547
|
-
method: "DELETE",
|
|
7548
|
-
path: "/v1/workflows/compute/nodes/reservations/{reservationId}/filesystem-deployment"
|
|
7549
|
-
},
|
|
7550
|
-
input: reservationWrite,
|
|
7551
|
-
slack: false,
|
|
7552
|
-
execute: (ctx, input) => ctx.fetch(reservationStorageRoute(input.reservationId, "filesystem-deployment"), {
|
|
7553
|
-
method: "DELETE"
|
|
7554
|
-
})
|
|
7555
|
-
}),
|
|
7556
7469
|
defineCapability({
|
|
7557
7470
|
id: "storage.targets",
|
|
7558
7471
|
domain: "storage",
|
|
@@ -8027,10 +7940,6 @@ var LEGACY_CLI_MIGRATIONS = [
|
|
|
8027
7940
|
{ legacy: ["storage", "deploy"], replacement: "ornn volume-mounts attach" },
|
|
8028
7941
|
{ legacy: ["storage", "status"], replacement: "ornn volume-mounts show" },
|
|
8029
7942
|
{ legacy: ["storage", "detach"], replacement: "ornn volume-mounts detach" },
|
|
8030
|
-
{ legacy: ["storage", "filesystem"], replacement: "ornn filesystems show" },
|
|
8031
|
-
{ legacy: ["storage", "filesystem", "deploy"], replacement: "ornn filesystems deploy" },
|
|
8032
|
-
{ legacy: ["storage", "filesystem", "status"], replacement: "ornn filesystems show" },
|
|
8033
|
-
{ legacy: ["storage", "filesystem", "delete"], replacement: "ornn filesystems delete" },
|
|
8034
7943
|
{
|
|
8035
7944
|
legacy: ["billing", "summary"],
|
|
8036
7945
|
replacement: "ornn capacity-offers list (use the Ornn web app for commercial workflows)"
|