@ornncompute/cli 0.2.23 → 1.0.25

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 (85) hide show
  1. package/README.md +304 -420
  2. package/package.json +12 -6
  3. package/src/admin-capacity-reservations.mjs +280 -0
  4. package/src/admin-command-handlers.mjs +57 -0
  5. package/src/admin-enrollment.mjs +680 -0
  6. package/src/admin-mutations.mjs +187 -0
  7. package/src/admin-node-diagnostics.mjs +412 -0
  8. package/src/admin-node-lifecycle.mjs +908 -0
  9. package/src/admin-shell.mjs +322 -0
  10. package/src/api-client.mjs +81 -28
  11. package/src/atomic-output.mjs +112 -0
  12. package/src/auth-store.mjs +182 -11
  13. package/src/capability-catalog.mjs +7 -0
  14. package/src/catalog-shell.mjs +1350 -0
  15. package/src/cli.mjs +123 -10266
  16. package/src/connect-mode-handlers.mjs +170 -0
  17. package/src/device-auth.mjs +178 -61
  18. package/src/evidence-commands.mjs +1340 -0
  19. package/src/external-bucket-commands.mjs +1374 -0
  20. package/src/interaction-runtime.mjs +310 -0
  21. package/src/kubernetes-commands.mjs +2229 -0
  22. package/src/launch-mode-handlers.mjs +119 -0
  23. package/src/machine-reference.mjs +277 -0
  24. package/src/mount-commands.mjs +1146 -0
  25. package/src/session-commands.mjs +565 -0
  26. package/src/slurm-commands.mjs +263 -0
  27. package/src/startup.mjs +34 -11
  28. package/src/storage-commands.mjs +1144 -0
  29. package/src/update.mjs +172 -24
  30. package/src/vm-commands.mjs +4273 -0
  31. package/src/vpn-secret-output.mjs +150 -0
  32. package/src/wait-runtime.mjs +231 -0
  33. package/vendor/capabilities/capabilities/admin-capacity-reservations.js +126 -0
  34. package/vendor/capabilities/capabilities/admin-enrollment.js +321 -0
  35. package/vendor/capabilities/capabilities/admin-node-diagnostics.js +88 -0
  36. package/vendor/capabilities/capabilities/admin-nodes-lifecycle.js +235 -0
  37. package/vendor/capabilities/capabilities/admin.js +89 -0
  38. package/vendor/capabilities/capabilities/capacity-offers.js +368 -0
  39. package/vendor/capabilities/capabilities/cli.js +156 -0
  40. package/vendor/capabilities/capabilities/clusters.js +150 -1
  41. package/vendor/capabilities/capabilities/compute.js +522 -0
  42. package/vendor/capabilities/capabilities/evidence.js +145 -0
  43. package/vendor/capabilities/capabilities/external-buckets.js +191 -0
  44. package/vendor/capabilities/capabilities/fleet.js +21 -5
  45. package/vendor/capabilities/capabilities/identity.js +114 -3
  46. package/vendor/capabilities/capabilities/listings.js +14 -8
  47. package/vendor/capabilities/capabilities/mounts.js +176 -0
  48. package/vendor/capabilities/capabilities/networks.js +1257 -0
  49. package/vendor/capabilities/capabilities/observability.js +38 -8
  50. package/vendor/capabilities/capabilities/tokens.js +20 -8
  51. package/vendor/capabilities/capabilities/volumes.js +178 -0
  52. package/vendor/capabilities/capability.js +19 -13
  53. package/vendor/capabilities/cli-catalog.js +65 -0
  54. package/vendor/capabilities/cli-migrations.js +288 -0
  55. package/vendor/capabilities/cli.js +7 -0
  56. package/vendor/capabilities/software-catalog.js +36 -0
  57. package/vendor/capabilities/spec-catalog.js +2 -2
  58. package/src/catalog-dispatch.mjs +0 -605
  59. package/src/color.mjs +0 -71
  60. package/vendor/capabilities/capabilities/clusters.d.ts +0 -2
  61. package/vendor/capabilities/capabilities/fleet.d.ts +0 -8
  62. package/vendor/capabilities/capabilities/identity.d.ts +0 -3
  63. package/vendor/capabilities/capabilities/listings.d.ts +0 -51
  64. package/vendor/capabilities/capabilities/observability.d.ts +0 -5
  65. package/vendor/capabilities/capabilities/staff-access.d.ts +0 -29
  66. package/vendor/capabilities/capabilities/staff-access.js +0 -278
  67. package/vendor/capabilities/capabilities/staff-commerce.d.ts +0 -160
  68. package/vendor/capabilities/capabilities/staff-commerce.js +0 -689
  69. package/vendor/capabilities/capabilities/staff-fleet.d.ts +0 -140
  70. package/vendor/capabilities/capabilities/staff-fleet.js +0 -538
  71. package/vendor/capabilities/capabilities/staff-gtm.d.ts +0 -142
  72. package/vendor/capabilities/capabilities/staff-gtm.js +0 -521
  73. package/vendor/capabilities/capabilities/staff-shared.d.ts +0 -47
  74. package/vendor/capabilities/capabilities/staff-shared.js +0 -98
  75. package/vendor/capabilities/capabilities/tokens.d.ts +0 -10
  76. package/vendor/capabilities/capabilities/users.d.ts +0 -2
  77. package/vendor/capabilities/capability.d.ts +0 -93
  78. package/vendor/capabilities/catalog.d.ts +0 -3
  79. package/vendor/capabilities/catalog.js +0 -26
  80. package/vendor/capabilities/index.d.ts +0 -16
  81. package/vendor/capabilities/index.js +0 -16
  82. package/vendor/capabilities/names.d.ts +0 -6
  83. package/vendor/capabilities/role.d.ts +0 -6
  84. package/vendor/capabilities/role.js +0 -17
  85. package/vendor/capabilities/spec-catalog.d.ts +0 -78
@@ -1,7 +1,9 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
- import { dirname, join, resolve } from "node:path";
2
+ import { mkdir, readFile, rm } from "node:fs/promises";
4
3
  import { homedir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+
6
+ import { writeAtomicOutput } from "./atomic-output.mjs";
5
7
 
6
8
  const APP_DIR = "ornn";
7
9
  const AUTH_FILE = "auth.json";
@@ -46,6 +48,15 @@ export function configuredApiBaseUrl(env = process.env) {
46
48
  }
47
49
  }
48
50
 
51
+ export function configuredInstallerBaseUrl(env = process.env) {
52
+ try {
53
+ const value = JSON.parse(readFileSync(getCliConfigPath(env), "utf8"))?.installerBaseUrl;
54
+ return typeof value === "string" ? value.trim() : "";
55
+ } catch {
56
+ return "";
57
+ }
58
+ }
59
+
49
60
  export async function loadAuthSession({ env = process.env } = {}) {
50
61
  const path = getAuthConfigPath(env);
51
62
 
@@ -60,20 +71,180 @@ export async function loadAuthSession({ env = process.env } = {}) {
60
71
  }
61
72
  }
62
73
 
63
- export async function saveAuthSession(session, { env = process.env, now = new Date() } = {}) {
74
+ async function writeAuthSession(session, env) {
64
75
  const path = getAuthConfigPath(env);
76
+ await mkdir(getAuthConfigDir(env), { recursive: true, mode: 0o700 });
77
+ await writeAtomicOutput(path, `${JSON.stringify(session, null, 2)}\n`, {
78
+ mode: 0o600,
79
+ overwrite: true,
80
+ });
81
+ return session;
82
+ }
83
+
84
+ export async function saveAuthSession(session, { env = process.env, now = new Date() } = {}) {
85
+ const existing = await loadAuthSession({ env });
86
+ const payload = { ...session };
87
+ delete payload.pendingPurchase;
88
+ delete payload.pendingWorkspace;
89
+ delete payload.recoveryUserId;
90
+ const userId = pendingString(session?.user, "id");
91
+ const existingOwnerId = recoveryOwnerId(existing);
92
+ const existingRecovery =
93
+ userId && existingOwnerId === userId
94
+ ? durableRecoveryFields(existing)
95
+ : !userId && existingOwnerId
96
+ ? durableRecoveryFields(existing)
97
+ : {};
98
+ const suppliedRecovery = userId ? durableRecoveryFields(session) : {};
99
+ const retainedRecoveryOwnerId =
100
+ !userId && Object.keys(existingRecovery).length > 0 ? existingOwnerId : null;
101
+ return writeAuthSession(
102
+ {
103
+ ...payload,
104
+ ...existingRecovery,
105
+ ...suppliedRecovery,
106
+ ...(retainedRecoveryOwnerId ? { recoveryUserId: retainedRecoveryOwnerId } : {}),
107
+ savedAt: now.toISOString(),
108
+ },
109
+ env
110
+ );
111
+ }
112
+
113
+ export async function bindAuthUser(user, { env = process.env, expectedAccessToken } = {}) {
114
+ const userId = pendingString(user, "id");
115
+ if (!userId) return false;
116
+ const existing = await loadAuthSession({ env });
117
+ if (
118
+ !existing?.accessToken ||
119
+ (expectedAccessToken && existing.accessToken !== expectedAccessToken)
120
+ ) {
121
+ return false;
122
+ }
65
123
  const payload = {
66
- ...session,
67
- savedAt: now.toISOString(),
124
+ ...existing,
125
+ user: { ...(existing.user ?? {}), ...user, id: userId },
68
126
  };
127
+ const ownerId = recoveryOwnerId(existing);
128
+ if (ownerId && ownerId !== userId) {
129
+ delete payload.pendingPurchase;
130
+ delete payload.pendingWorkspace;
131
+ }
132
+ delete payload.recoveryUserId;
133
+ await writeAuthSession(payload, env);
134
+ return true;
135
+ }
69
136
 
70
- await mkdir(dirname(path), { recursive: true, mode: 0o700 });
71
- await writeFile(path, `${JSON.stringify(payload, null, 2)}\n`, {
72
- encoding: "utf8",
73
- mode: 0o600,
74
- });
137
+ export async function saveOrganizationHint(
138
+ selectedOrganizationId,
139
+ { env = process.env, expectedAccessToken } = {}
140
+ ) {
141
+ const session = await loadAuthSession({ env });
142
+ if (
143
+ !session?.accessToken ||
144
+ (expectedAccessToken && session.accessToken !== expectedAccessToken)
145
+ ) {
146
+ return null;
147
+ }
148
+ const payload = { ...session };
149
+ if (typeof selectedOrganizationId === "string" && selectedOrganizationId.trim()) {
150
+ payload.selectedOrganizationId = selectedOrganizationId.trim();
151
+ } else {
152
+ delete payload.selectedOrganizationId;
153
+ }
154
+ return writeAuthSession(payload, env);
155
+ }
156
+
157
+ function pendingString(value, field) {
158
+ return typeof value?.[field] === "string" ? value[field].trim() : "";
159
+ }
75
160
 
76
- return payload;
161
+ function pendingWorkspaceValue(value) {
162
+ const pending = value && typeof value === "object" ? value : {};
163
+ const required = [
164
+ "id",
165
+ "organizationId",
166
+ "reservationId",
167
+ "keyId",
168
+ "networkId",
169
+ "volumeId",
170
+ "mountAccess",
171
+ ];
172
+ const normalized = Object.fromEntries(
173
+ required.map((field) => [
174
+ field,
175
+ typeof pending[field] === "string" ? pending[field].trim() : "",
176
+ ])
177
+ );
178
+ if (required.some((field) => !normalized[field])) return null;
179
+ return {
180
+ ...normalized,
181
+ username:
182
+ typeof pending.username === "string" && pending.username.trim()
183
+ ? pending.username.trim()
184
+ : null,
185
+ };
186
+ }
187
+
188
+ function durableRecoveryFields(value) {
189
+ const pendingWorkspace = pendingWorkspaceValue(value?.pendingWorkspace);
190
+ return {
191
+ ...(pendingWorkspace ? { pendingWorkspace } : {}),
192
+ };
193
+ }
194
+
195
+ function recoveryOwnerId(value) {
196
+ return pendingString(value?.user, "id") || pendingString(value, "recoveryUserId");
197
+ }
198
+
199
+ export async function loadPendingWorkspace({ env = process.env, session: suppliedSession } = {}) {
200
+ const session = suppliedSession === undefined ? await loadAuthSession({ env }) : suppliedSession;
201
+ return pendingWorkspaceValue(session?.pendingWorkspace);
202
+ }
203
+
204
+ export async function savePendingWorkspace(value, { env = process.env, expectedAccessToken } = {}) {
205
+ const pendingWorkspace = pendingWorkspaceValue(value);
206
+ if (!pendingWorkspace) return false;
207
+ const session = await loadAuthSession({ env });
208
+ if (
209
+ !session?.accessToken ||
210
+ (expectedAccessToken && session.accessToken !== expectedAccessToken)
211
+ ) {
212
+ return false;
213
+ }
214
+ const existing = pendingWorkspaceValue(session.pendingWorkspace);
215
+ if (existing && existing.id !== pendingWorkspace.id) return false;
216
+ await writeAuthSession({ ...session, pendingWorkspace }, env);
217
+ return true;
218
+ }
219
+
220
+ export async function clearPendingWorkspace(id, { env = process.env, expectedAccessToken } = {}) {
221
+ const session = await loadAuthSession({ env });
222
+ if (!session?.pendingWorkspace) return false;
223
+ if (expectedAccessToken && session.accessToken !== expectedAccessToken) return false;
224
+ if (id && session.pendingWorkspace.id !== id) return false;
225
+ const payload = { ...session };
226
+ delete payload.pendingWorkspace;
227
+ await writeAuthSession(payload, env);
228
+ return true;
229
+ }
230
+
231
+ export async function clearAuthCredentials({ env = process.env, expectedAccessToken } = {}) {
232
+ const existing = await loadAuthSession({ env });
233
+ if (
234
+ expectedAccessToken &&
235
+ existing?.accessToken &&
236
+ existing.accessToken !== expectedAccessToken
237
+ ) {
238
+ return false;
239
+ }
240
+ const recovery = durableRecoveryFields(existing);
241
+ const recoveryUserId = recoveryOwnerId(existing);
242
+ if (Object.keys(recovery).length === 0 || !recoveryUserId) {
243
+ await rm(getAuthConfigPath(env), { force: true });
244
+ return true;
245
+ }
246
+ await writeAuthSession({ ...recovery, recoveryUserId }, env);
247
+ return true;
77
248
  }
78
249
 
79
250
  export async function clearAuthSession({ env = process.env } = {}) {
@@ -0,0 +1,7 @@
1
+ export async function loadCapabilities() {
2
+ try {
3
+ return await import("@ornn/capabilities/cli");
4
+ } catch {
5
+ return await import("../vendor/capabilities/cli.js");
6
+ }
7
+ }