skydive-cli 0.4.1-beta.6 → 0.5.0-beta.10
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 +15 -4
- package/dist/js/api-DG5W6iwx.mjs +131 -0
- package/dist/js/bin.mjs +79 -33
- package/dist/js/{boot-B48inW5D.mjs → boot-BuxaHgFi.mjs} +241 -74
- package/dist/js/client-BuU34IVE.mjs +5 -0
- package/dist/js/{client-mykp1DVb.mjs → client-DabRpc_T.mjs} +187 -118
- package/dist/js/{daemon-CfbpCjAw.mjs → daemon-CYYE2BTu.mjs} +179 -28
- package/dist/js/{daemon-D4ZX3wNG.mjs → daemon-Dk5LeS1S.mjs} +3 -2
- package/dist/js/{daemon-client-6xtta_n2.mjs → daemon-client-3A9afTFC.mjs} +35 -10
- package/dist/js/daemon-client-Dh7G9RxC.mjs +7 -0
- package/dist/js/forward-18QoL5dO.mjs +68 -0
- package/dist/js/{print-ba_0hiV9.mjs → print-Bo06tvfV.mjs} +2 -2
- package/dist/js/{print-CbayCa87.mjs → print-ClPkgR9z.mjs} +105 -29
- package/dist/js/{print-share-ZV88PqDu.mjs → print-share-CKLPmsg0.mjs} +5 -2
- package/dist/js/{profiler-94qrV53c.mjs → profiler-Zs3BHURc.mjs} +2 -2
- package/dist/js/{raw-pty-B6mAroiI.mjs → raw-pty-DY4KelZW.mjs} +1 -1
- package/dist/js/raw-pty-DmdUf4_w.mjs +5 -0
- package/dist/js/{rest-DADJh0bi.mjs → rest-D29qNkto.mjs} +1 -1
- package/dist/js/{rest-BY2nADw5.mjs → rest-I3imNduB.mjs} +6 -11
- package/package.json +2 -2
- package/dist/js/client-NBj0KZSP.mjs +0 -4
- package/dist/js/daemon-client-BHehCLrO.mjs +0 -6
- package/dist/js/raw-pty-3EkG-jjH.mjs +0 -5
- /package/dist/js/{client-Cn2af31H.mjs → client-c4c5MmgN.mjs} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { a as mintPortalDeviceToken, c as unifyLegacyCliGrants, i as grantPortalAccess, n as fetchPortalDevices, r as findThisDevice } from "./api-DG5W6iwx.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { execFile, spawn } from "node:child_process";
|
|
6
|
-
import
|
|
6
|
+
import net from "node:net";
|
|
7
|
+
import { WebSocket, createWebSocketStream } from "ws";
|
|
7
8
|
|
|
8
9
|
//#region ../portal-daemon/src/machine.ts
|
|
9
10
|
/**
|
|
@@ -58,12 +59,18 @@ const INHERITED_ENV = [
|
|
|
58
59
|
"TERM",
|
|
59
60
|
"PATH"
|
|
60
61
|
];
|
|
62
|
+
const DARWIN_PATH_PREPEND = ["/opt/homebrew/bin", "/usr/local/bin"];
|
|
61
63
|
function buildEnv(extra) {
|
|
62
64
|
const env = {};
|
|
63
65
|
for (const key of INHERITED_ENV) {
|
|
64
66
|
const value = process.env[key];
|
|
65
67
|
if (value !== void 0) env[key] = value;
|
|
66
68
|
}
|
|
69
|
+
if (process.platform === "darwin") {
|
|
70
|
+
const current = env.PATH ? env.PATH.split(":") : [];
|
|
71
|
+
const missing = DARWIN_PATH_PREPEND.filter((dir) => !current.includes(dir));
|
|
72
|
+
if (missing.length > 0) env.PATH = [...missing, ...current].join(":");
|
|
73
|
+
}
|
|
67
74
|
if (extra) for (const [key, value] of Object.entries(extra)) env[key] = value;
|
|
68
75
|
return env;
|
|
69
76
|
}
|
|
@@ -128,6 +135,18 @@ const ctrlMessageSchema = z.discriminatedUnion("t", [
|
|
|
128
135
|
conversationId: z.string().nullable().optional()
|
|
129
136
|
}),
|
|
130
137
|
z.object({ t: z.literal("stdin_eof") }),
|
|
138
|
+
z.object({
|
|
139
|
+
t: z.literal("reverse_listen"),
|
|
140
|
+
listenPort: z.number().int().positive(),
|
|
141
|
+
targetPort: z.number().int().positive(),
|
|
142
|
+
dialOrigin: z.string().min(1),
|
|
143
|
+
token: z.string().min(1)
|
|
144
|
+
}),
|
|
145
|
+
z.object({ t: z.literal("reverse_listening") }),
|
|
146
|
+
z.object({
|
|
147
|
+
t: z.literal("reverse_token"),
|
|
148
|
+
token: z.string().min(1)
|
|
149
|
+
}),
|
|
131
150
|
z.object({ t: z.literal("pause") }),
|
|
132
151
|
z.object({ t: z.literal("resume") }),
|
|
133
152
|
z.object({ t: z.literal("cancel") }),
|
|
@@ -163,6 +182,62 @@ function decodeFrame(frame) {
|
|
|
163
182
|
};
|
|
164
183
|
}
|
|
165
184
|
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region ../portal-daemon/src/reverse-listener.ts
|
|
187
|
+
/**
|
|
188
|
+
* The desktop half of an agent-initiated expose tunnel (`platform portal
|
|
189
|
+
* expose`): listen on the local loopback and pipe each accepted TCP
|
|
190
|
+
* connection to the agent sandbox's daemon (`/portal/tcp`) through the
|
|
191
|
+
* agent-webserver edge Worker — the same per-connection dial-and-pipe as the
|
|
192
|
+
* user-initiated `skydive portal forward`, just started from a directive
|
|
193
|
+
* instead of a terminal. Tunnel bytes never touch the directive stream that
|
|
194
|
+
* created this listener; it only anchors the lifetime and carries the token.
|
|
195
|
+
*
|
|
196
|
+
* `target()` is read per connection so a token refresh (or any future
|
|
197
|
+
* retarget) applies to the next dial without touching established pipes.
|
|
198
|
+
*/
|
|
199
|
+
var ReverseListener = class {
|
|
200
|
+
server = null;
|
|
201
|
+
conns = /* @__PURE__ */ new Set();
|
|
202
|
+
constructor(opts) {
|
|
203
|
+
this.opts = opts;
|
|
204
|
+
}
|
|
205
|
+
start() {
|
|
206
|
+
const server = net.createServer((sock) => {
|
|
207
|
+
this.conns.add(sock);
|
|
208
|
+
sock.once("close", () => this.conns.delete(sock));
|
|
209
|
+
sock.pause();
|
|
210
|
+
const { dialOrigin, targetPort, token } = this.opts.target();
|
|
211
|
+
const ws = new WebSocket(`${dialOrigin.replace(/^http/, "ws")}/portal/tcp?port=${targetPort}`, { headers: { authorization: `Bearer ${token}` } });
|
|
212
|
+
ws.on("open", () => {
|
|
213
|
+
const stream = createWebSocketStream(ws);
|
|
214
|
+
stream.on("error", () => sock.destroy());
|
|
215
|
+
sock.on("error", () => stream.destroy());
|
|
216
|
+
sock.pipe(stream).pipe(sock);
|
|
217
|
+
sock.resume();
|
|
218
|
+
});
|
|
219
|
+
ws.on("error", (err) => {
|
|
220
|
+
this.opts.log(`expose: tunnel connect failed: ${err.message}`);
|
|
221
|
+
sock.destroy();
|
|
222
|
+
});
|
|
223
|
+
ws.on("unexpected-response", (_req, res) => {
|
|
224
|
+
this.opts.log(`expose: tunnel rejected (HTTP ${res.statusCode ?? "?"})`);
|
|
225
|
+
res.destroy();
|
|
226
|
+
sock.destroy();
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
server.once("error", (err) => this.opts.onListening(err));
|
|
230
|
+
server.listen(this.opts.listenPort, "127.0.0.1", () => this.opts.onListening(null));
|
|
231
|
+
this.server = server;
|
|
232
|
+
}
|
|
233
|
+
stop() {
|
|
234
|
+
this.server?.close();
|
|
235
|
+
this.server = null;
|
|
236
|
+
for (const sock of this.conns) sock.destroy();
|
|
237
|
+
this.conns.clear();
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
166
241
|
//#endregion
|
|
167
242
|
//#region ../portal-daemon/src/exec.ts
|
|
168
243
|
/**
|
|
@@ -175,6 +250,7 @@ function decodeFrame(frame) {
|
|
|
175
250
|
*/
|
|
176
251
|
var JobManager = class {
|
|
177
252
|
jobs = /* @__PURE__ */ new Map();
|
|
253
|
+
reverse = /* @__PURE__ */ new Map();
|
|
178
254
|
constructor(opts) {
|
|
179
255
|
this.opts = opts;
|
|
180
256
|
}
|
|
@@ -194,12 +270,35 @@ var JobManager = class {
|
|
|
194
270
|
job.child.kill("SIGKILL");
|
|
195
271
|
}
|
|
196
272
|
this.jobs.clear();
|
|
273
|
+
for (const rev of this.reverse.values()) {
|
|
274
|
+
rev.settled = true;
|
|
275
|
+
rev.listener.stop();
|
|
276
|
+
}
|
|
277
|
+
this.reverse.clear();
|
|
197
278
|
}
|
|
198
279
|
handleCtrl(id, msg) {
|
|
199
280
|
switch (msg.t) {
|
|
200
281
|
case "open":
|
|
201
282
|
this.startJob(id, msg.argv, msg.env, msg.conversationId ?? null);
|
|
202
283
|
return;
|
|
284
|
+
case "reverse_listen":
|
|
285
|
+
this.startReverse(id, {
|
|
286
|
+
listenPort: msg.listenPort,
|
|
287
|
+
target: {
|
|
288
|
+
dialOrigin: msg.dialOrigin,
|
|
289
|
+
targetPort: msg.targetPort,
|
|
290
|
+
token: msg.token
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
return;
|
|
294
|
+
case "reverse_token": {
|
|
295
|
+
const rev = this.reverse.get(id);
|
|
296
|
+
if (rev) rev.target = {
|
|
297
|
+
...rev.target,
|
|
298
|
+
token: msg.token
|
|
299
|
+
};
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
203
302
|
case "stdin_eof":
|
|
204
303
|
this.jobs.get(id)?.child.stdin.end();
|
|
205
304
|
return;
|
|
@@ -211,12 +310,51 @@ var JobManager = class {
|
|
|
211
310
|
return;
|
|
212
311
|
case "cancel":
|
|
213
312
|
this.jobs.get(id)?.child.kill("SIGKILL");
|
|
313
|
+
this.stopReverse(id);
|
|
214
314
|
return;
|
|
215
315
|
case "close":
|
|
216
|
-
case "error":
|
|
316
|
+
case "error":
|
|
317
|
+
case "reverse_listening": return;
|
|
217
318
|
default: return msg;
|
|
218
319
|
}
|
|
219
320
|
}
|
|
321
|
+
startReverse(id, { listenPort, target }) {
|
|
322
|
+
const rev = {
|
|
323
|
+
settled: false,
|
|
324
|
+
target,
|
|
325
|
+
seq: 0,
|
|
326
|
+
listener: new ReverseListener({
|
|
327
|
+
listenPort,
|
|
328
|
+
target: () => rev.target,
|
|
329
|
+
log: (msg) => {
|
|
330
|
+
if (rev.settled) return;
|
|
331
|
+
this.opts.send(encodeData(id, STREAM.stderr, rev.seq, Buffer.from(msg)));
|
|
332
|
+
rev.seq = rev.seq + 1 >>> 0;
|
|
333
|
+
},
|
|
334
|
+
onListening: (err) => {
|
|
335
|
+
if (err) {
|
|
336
|
+
rev.settled = true;
|
|
337
|
+
this.reverse.delete(id);
|
|
338
|
+
this.opts.send(encodeCtrl(id, {
|
|
339
|
+
t: "error",
|
|
340
|
+
message: `reverse listen failed: ${err.message}`
|
|
341
|
+
}));
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
this.opts.send(encodeCtrl(id, { t: "reverse_listening" }));
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
};
|
|
348
|
+
this.reverse.set(id, rev);
|
|
349
|
+
rev.listener.start();
|
|
350
|
+
}
|
|
351
|
+
stopReverse(id) {
|
|
352
|
+
const rev = this.reverse.get(id);
|
|
353
|
+
if (!rev) return;
|
|
354
|
+
rev.settled = true;
|
|
355
|
+
this.reverse.delete(id);
|
|
356
|
+
rev.listener.stop();
|
|
357
|
+
}
|
|
220
358
|
setPaused(id, paused) {
|
|
221
359
|
const job = this.jobs.get(id);
|
|
222
360
|
if (!job) return;
|
|
@@ -290,111 +428,6 @@ var JobManager = class {
|
|
|
290
428
|
}
|
|
291
429
|
};
|
|
292
430
|
|
|
293
|
-
//#endregion
|
|
294
|
-
//#region ../portal-daemon/src/api.ts
|
|
295
|
-
/**
|
|
296
|
-
* The portal's session-authed REST surface, shared by `PortalClient` (the
|
|
297
|
-
* TUI/`portal open` connection) and the `skydive portal` management
|
|
298
|
-
* commands, so the endpoint contracts and response schemas live in exactly
|
|
299
|
-
* one place.
|
|
300
|
-
*/
|
|
301
|
-
const deviceSchema = z.object({
|
|
302
|
-
id: z.string(),
|
|
303
|
-
machineName: z.string(),
|
|
304
|
-
friendlyName: z.string(),
|
|
305
|
-
connected: z.boolean(),
|
|
306
|
-
lastSeen: z.string().nullable(),
|
|
307
|
-
grantedAgentIds: z.array(z.string())
|
|
308
|
-
});
|
|
309
|
-
const devicesResponseSchema = z.object({
|
|
310
|
-
devices: z.array(deviceSchema),
|
|
311
|
-
agents: z.array(z.object({
|
|
312
|
-
id: z.string(),
|
|
313
|
-
name: z.string()
|
|
314
|
-
}))
|
|
315
|
-
});
|
|
316
|
-
const deviceTokenSchema = z.object({ token: z.string().min(1) });
|
|
317
|
-
async function portalFetch(auth, path, init) {
|
|
318
|
-
const res = await fetch(`${auth.appUrl}${path}`, {
|
|
319
|
-
method: init.method,
|
|
320
|
-
headers: {
|
|
321
|
-
authorization: `Bearer ${auth.sessionToken}`,
|
|
322
|
-
accept: "application/json",
|
|
323
|
-
...init.body ? { "content-type": "application/json" } : {}
|
|
324
|
-
},
|
|
325
|
-
...init.body ? { body: init.body } : {}
|
|
326
|
-
});
|
|
327
|
-
if (!res.ok) {
|
|
328
|
-
const body = await res.text().catch(() => "");
|
|
329
|
-
throw new HttpError(res.status, body);
|
|
330
|
-
}
|
|
331
|
-
return res.json();
|
|
332
|
-
}
|
|
333
|
-
async function fetchPortalDevices(auth) {
|
|
334
|
-
const json = await portalFetch(auth, "/api/v1/portal/devices", { method: "GET" });
|
|
335
|
-
return devicesResponseSchema.parse(json);
|
|
336
|
-
}
|
|
337
|
-
const registerResponseSchema = z.object({ device: z.object({ id: z.string() }) });
|
|
338
|
-
/**
|
|
339
|
-
* Register this machine's device row without connecting. Connecting registers
|
|
340
|
-
* as a side effect; this covers granting an agent on a machine that has never
|
|
341
|
-
* shared yet (the grant references the device row).
|
|
342
|
-
*/
|
|
343
|
-
async function registerPortalDevice(auth, { machineName, friendlyName }) {
|
|
344
|
-
const json = await portalFetch(auth, "/api/v1/portal/devices", {
|
|
345
|
-
method: "POST",
|
|
346
|
-
body: JSON.stringify({
|
|
347
|
-
machineName,
|
|
348
|
-
friendlyName
|
|
349
|
-
})
|
|
350
|
-
});
|
|
351
|
-
return registerResponseSchema.parse(json).device;
|
|
352
|
-
}
|
|
353
|
-
/** Short-lived token the machine presents when dialing the portal WebSocket. */
|
|
354
|
-
async function mintPortalDeviceToken(auth) {
|
|
355
|
-
const json = await portalFetch(auth, "/api/v1/portal/device-token", { method: "POST" });
|
|
356
|
-
return deviceTokenSchema.parse(json).token;
|
|
357
|
-
}
|
|
358
|
-
async function grantPortalAccess(auth, { deviceId, agentId }) {
|
|
359
|
-
await portalFetch(auth, `/api/v1/portal/devices/${encodeURIComponent(deviceId)}/grants`, {
|
|
360
|
-
method: "POST",
|
|
361
|
-
body: JSON.stringify({ agentId })
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
async function revokePortalAccess(auth, { deviceId, agentId }) {
|
|
365
|
-
await portalFetch(auth, `/api/v1/portal/devices/${encodeURIComponent(deviceId)}/grants/${encodeURIComponent(agentId)}`, { method: "DELETE" });
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* The device row for a given machine identity. Matching is by `machineName`
|
|
369
|
-
* equality — the stable handle the machine registers under, not the display
|
|
370
|
-
* label.
|
|
371
|
-
*/
|
|
372
|
-
function findThisDevice(devices, machineName) {
|
|
373
|
-
return devices.find((device) => device.machineName === machineName) ?? null;
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* One-time grant migration onto the merged device. Earlier CLI builds
|
|
377
|
-
* registered a separate `<machineName>-cli` device, so a user's existing
|
|
378
|
-
* approvals hang off that row; the merged device would start with zero grants
|
|
379
|
-
* and every already-authorized agent would ask again. Copy any grant the
|
|
380
|
-
* merged device is missing (the grant endpoint upserts, so re-runs are
|
|
381
|
-
* no-ops). The legacy row is left in place — an old CLI build may still
|
|
382
|
-
* connect under it. Returns how many grants were copied.
|
|
383
|
-
*/
|
|
384
|
-
async function unifyLegacyCliGrants(auth, machineName) {
|
|
385
|
-
const { devices } = await fetchPortalDevices(auth);
|
|
386
|
-
const merged = findThisDevice(devices, machineName);
|
|
387
|
-
const legacy = findThisDevice(devices, `${machineName}-cli`);
|
|
388
|
-
if (!merged || !legacy) return 0;
|
|
389
|
-
const have = new Set(merged.grantedAgentIds);
|
|
390
|
-
const missing = legacy.grantedAgentIds.filter((id) => !have.has(id));
|
|
391
|
-
for (const agentId of missing) await grantPortalAccess(auth, {
|
|
392
|
-
deviceId: merged.id,
|
|
393
|
-
agentId
|
|
394
|
-
});
|
|
395
|
-
return missing.length;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
431
|
//#endregion
|
|
399
432
|
//#region ../portal-daemon/src/client.ts
|
|
400
433
|
const INITIAL_BACKOFF_MS = 500;
|
|
@@ -430,6 +463,10 @@ var PortalClient = class {
|
|
|
430
463
|
isGranted(agentId) {
|
|
431
464
|
return this.granted.has(agentId);
|
|
432
465
|
}
|
|
466
|
+
/** Agents currently authorized on this machine (last known server state). */
|
|
467
|
+
grantedAgentIds() {
|
|
468
|
+
return [...this.granted];
|
|
469
|
+
}
|
|
433
470
|
enable() {
|
|
434
471
|
if (this.enabled || this.disposed) return;
|
|
435
472
|
this.enabled = true;
|
|
@@ -459,16 +496,44 @@ var PortalClient = class {
|
|
|
459
496
|
this.ws?.close();
|
|
460
497
|
this.ws = null;
|
|
461
498
|
}
|
|
462
|
-
/**
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
499
|
+
/**
|
|
500
|
+
* Grant one agent access to this machine (default-deny; user-initiated).
|
|
501
|
+
* `conversationId` is the conversation whose run asked (null when the grant
|
|
502
|
+
* is not answering an in-chat request) — the server uses it to wake the
|
|
503
|
+
* waiting agent.
|
|
504
|
+
*/
|
|
505
|
+
async grantAgent(agentId, conversationId) {
|
|
506
|
+
const auth = this.sessionAuth();
|
|
507
|
+
if (!auth) throw new Error("granting needs a signed-in CLI session on this machine (the desktop connection alone cannot manage grants)");
|
|
508
|
+
await grantPortalAccess(auth, {
|
|
509
|
+
deviceId: await this.ensureDeviceId(),
|
|
510
|
+
agentId,
|
|
511
|
+
conversationId
|
|
468
512
|
});
|
|
469
513
|
this.granted.add(agentId);
|
|
470
514
|
this.emit();
|
|
471
515
|
}
|
|
516
|
+
/** Session-authed REST auth, or null when only a device token is held. */
|
|
517
|
+
sessionAuth() {
|
|
518
|
+
const { sessionToken } = this.opts.credentials();
|
|
519
|
+
return sessionToken ? {
|
|
520
|
+
appUrl: this.opts.appUrl,
|
|
521
|
+
sessionToken
|
|
522
|
+
} : null;
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* The bearer token for the portal WebSocket dial: minted from the session
|
|
526
|
+
* when one is held, otherwise the pre-minted device token as-is.
|
|
527
|
+
*/
|
|
528
|
+
async wsToken() {
|
|
529
|
+
const creds = this.opts.credentials();
|
|
530
|
+
if (creds.sessionToken) return mintPortalDeviceToken({
|
|
531
|
+
appUrl: this.opts.appUrl,
|
|
532
|
+
sessionToken: creds.sessionToken
|
|
533
|
+
});
|
|
534
|
+
if (creds.deviceToken) return creds.deviceToken;
|
|
535
|
+
throw new Error("no portal credentials (not signed in)");
|
|
536
|
+
}
|
|
472
537
|
setStatus(status, error = null) {
|
|
473
538
|
this.status = status;
|
|
474
539
|
this.error = error;
|
|
@@ -493,7 +558,7 @@ var PortalClient = class {
|
|
|
493
558
|
while (this.enabled && !this.disposed) {
|
|
494
559
|
this.setStatus("connecting");
|
|
495
560
|
try {
|
|
496
|
-
const token = await
|
|
561
|
+
const token = await this.wsToken();
|
|
497
562
|
await this.runConnection(token);
|
|
498
563
|
backoff = INITIAL_BACKOFF_MS;
|
|
499
564
|
} catch (err) {
|
|
@@ -547,8 +612,10 @@ var PortalClient = class {
|
|
|
547
612
|
throw new Error("this machine is not connected yet");
|
|
548
613
|
}
|
|
549
614
|
async refreshDevice() {
|
|
615
|
+
const auth = this.sessionAuth();
|
|
616
|
+
if (!auth) return;
|
|
550
617
|
try {
|
|
551
|
-
const { devices } = await fetchPortalDevices(
|
|
618
|
+
const { devices } = await fetchPortalDevices(auth);
|
|
552
619
|
const mine = findThisDevice(devices, this.machineName);
|
|
553
620
|
if (!mine) return;
|
|
554
621
|
this.deviceId = mine.id;
|
|
@@ -565,9 +632,11 @@ var PortalClient = class {
|
|
|
565
632
|
async syncDeviceState() {
|
|
566
633
|
await this.refreshDevice();
|
|
567
634
|
if (this.legacyGrantsChecked) return;
|
|
635
|
+
const auth = this.sessionAuth();
|
|
636
|
+
if (!auth) return;
|
|
568
637
|
this.legacyGrantsChecked = true;
|
|
569
638
|
try {
|
|
570
|
-
if (await unifyLegacyCliGrants(
|
|
639
|
+
if (await unifyLegacyCliGrants(auth, this.machineName) > 0) await this.refreshDevice();
|
|
571
640
|
} catch (_error) {}
|
|
572
641
|
}
|
|
573
642
|
};
|
|
@@ -581,4 +650,4 @@ function sleep(ms) {
|
|
|
581
650
|
}
|
|
582
651
|
|
|
583
652
|
//#endregion
|
|
584
|
-
export {
|
|
653
|
+
export { isRecord as n, resolveMachineIdentity as r, PortalClient as t };
|