@ornncompute/cli 1.0.113 → 1.0.114
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 +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/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 +6 -1
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.", {
|
|
@@ -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, {
|
|
@@ -5109,7 +5114,7 @@ var whoamiCapability = defineCapability({
|
|
|
5109
5114
|
mutation: "read",
|
|
5110
5115
|
http: { method: "GET", path: "/v1/cli/session" },
|
|
5111
5116
|
input: emptyInput3,
|
|
5112
|
-
execute: async (ctx) => ctx.fetch
|
|
5117
|
+
execute: async (ctx) => getCliSession(ctx.fetch)
|
|
5113
5118
|
});
|
|
5114
5119
|
var statusCapability = defineCapability({
|
|
5115
5120
|
id: "identity.status",
|