skydive-cli 0.5.0-beta.41 → 0.5.0-beta.46
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/CHANGELOG.md +2 -0
- package/dist/js/{api-DQCaztBg.mjs → api-TwLD7ibI.mjs} +1 -1
- package/dist/js/bin.mjs +27 -25
- package/dist/js/{boot-B1Y1D48W.mjs → boot-BD8HZcOo.mjs} +387 -32
- package/dist/js/{client-DMYwKALl.mjs → client-C2lPer4b.mjs} +49 -4
- package/dist/js/client-CSKr4Swa.mjs +5 -0
- package/dist/js/{daemon-D8WoX21I.mjs → daemon-MZN78SYL.mjs} +94 -5
- package/dist/js/daemon-S0p-4FGa.mjs +7 -0
- package/dist/js/daemon-client-DMx26-Rz.mjs +8 -0
- package/dist/js/{daemon-client-Bp5DMeIi.mjs → daemon-client-qNlw9inL.mjs} +1 -1
- package/dist/js/{forward-zwB55Bls.mjs → forward-Ct8Vd2WW.mjs} +1 -1
- package/dist/js/{install-BkMcGVYS.mjs → install-DNJ6k578.mjs} +3 -7
- package/dist/js/{print-BAmEefvX.mjs → print-BAdeImNJ.mjs} +2 -2
- package/dist/js/{print-CwbdwCeQ.mjs → print-Bg8rzq9t.mjs} +82 -6
- package/dist/js/{print-share-azWHVxpt.mjs → print-share-D20YvVbb.mjs} +2 -2
- package/dist/js/{rest-B5DVQ1LM.mjs → rest-8QGtGZIO.mjs} +2 -2
- package/dist/js/{rest-Bbe-RhMy.mjs → rest-BtHVI0y6.mjs} +13 -4
- package/package.json +5 -5
- package/dist/js/client-DCwVlAal.mjs +0 -5
- package/dist/js/daemon-By-I_HVM.mjs +0 -7
- package/dist/js/daemon-client-_SVAskeO.mjs +0 -8
- /package/dist/js/{http-error-UHH3mVBF.mjs → http-error-BF2NZZE3.mjs} +0 -0
- /package/dist/js/{output-wY0VQDea.mjs → output-C9mb3sUB.mjs} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as isRecord, t as PortalClient } from "./client-
|
|
2
|
+
import { n as isRecord, t as PortalClient } from "./client-C2lPer4b.mjs";
|
|
3
3
|
import { t as defaultTlsCertSource } from "./tls-cert-CV-pwxVN.mjs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
@@ -21,7 +21,7 @@ import { access, appendFile, mkdir, readFile, unlink, writeFile } from "node:fs/
|
|
|
21
21
|
* the commit time of the built tree is one monotonic clock they share.
|
|
22
22
|
*/
|
|
23
23
|
function portalDaemonBuild() {
|
|
24
|
-
return "
|
|
24
|
+
return "1787048488";
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Whether a client carrying `mine` should replace a running daemon carrying
|
|
@@ -220,6 +220,20 @@ const clientStatusSchema = z.object({ t: z.literal("status") });
|
|
|
220
220
|
* exits — cutting live exec/tunnel connections, not just refusing new ones.
|
|
221
221
|
*/
|
|
222
222
|
const clientShutdownSchema = z.object({ t: z.literal("shutdown") });
|
|
223
|
+
/**
|
|
224
|
+
* `shutdown_handoff` — a newer daemon taking over (self-update / newest-build-
|
|
225
|
+
* wins) asks the incumbent to step down WITHOUT dropping the portal connection
|
|
226
|
+
* first. The incumbent frees the control socket and disconnects attached CLIs
|
|
227
|
+
* (they reconnect to the new daemon in ~500ms, unchanged), but KEEPS its
|
|
228
|
+
* outbound portal WebSocket — and thus its presence claim — alive until the
|
|
229
|
+
* new daemon has dialled out and claimed the machine's presence slot, at which
|
|
230
|
+
* point the server supersedes the incumbent's socket and it exits. This is a
|
|
231
|
+
* make-before-break handoff: the presence key is owned by one daemon or the
|
|
232
|
+
* other for the entire takeover, so `exec`/`file write` never sees a
|
|
233
|
+
* `registered but not connected` gap mid-upgrade. A bounded fallback timeout
|
|
234
|
+
* ensures the incumbent still exits if the successor never comes up.
|
|
235
|
+
*/
|
|
236
|
+
const clientShutdownHandoffSchema = z.object({ t: z.literal("shutdown_handoff") });
|
|
223
237
|
const clientMessageSchema = z.discriminatedUnion("t", [
|
|
224
238
|
clientHelloSchema,
|
|
225
239
|
clientBindSchema,
|
|
@@ -230,7 +244,8 @@ const clientMessageSchema = z.discriminatedUnion("t", [
|
|
|
230
244
|
clientDeclineSchema,
|
|
231
245
|
clientByeSchema,
|
|
232
246
|
clientStatusSchema,
|
|
233
|
-
clientShutdownSchema
|
|
247
|
+
clientShutdownSchema,
|
|
248
|
+
clientShutdownHandoffSchema
|
|
234
249
|
]);
|
|
235
250
|
/**
|
|
236
251
|
* `state` — the shared portal status, pushed to every attached client so each
|
|
@@ -357,6 +372,14 @@ function parseDaemonMessage(line) {
|
|
|
357
372
|
*/
|
|
358
373
|
/** Grace period after the last client detaches before the daemon exits. */
|
|
359
374
|
const IDLE_SHUTDOWN_MS = 3e4;
|
|
375
|
+
/**
|
|
376
|
+
* Upper bound an incumbent daemon waits, during a graceful handoff, for the
|
|
377
|
+
* successor to dial out and claim presence before giving up and releasing the
|
|
378
|
+
* slot itself. Comfortably above a normal successor boot + WS dial (a few
|
|
379
|
+
* hundred ms to a couple of seconds), and short enough that a failed successor
|
|
380
|
+
* doesn't strand the machine as reachable-but-dead for long.
|
|
381
|
+
*/
|
|
382
|
+
const HANDOFF_MAX_WAIT_MS = 1e4;
|
|
360
383
|
var PortalDaemon = class {
|
|
361
384
|
appUrl;
|
|
362
385
|
paths;
|
|
@@ -369,6 +392,7 @@ var PortalDaemon = class {
|
|
|
369
392
|
persistedMachineName = null;
|
|
370
393
|
fallbackCwd;
|
|
371
394
|
idleTimer = null;
|
|
395
|
+
handingOff = false;
|
|
372
396
|
sessionToken = null;
|
|
373
397
|
deviceToken = null;
|
|
374
398
|
constructor(appUrl) {
|
|
@@ -478,6 +502,9 @@ var PortalDaemon = class {
|
|
|
478
502
|
case "shutdown":
|
|
479
503
|
this.forceShutdown();
|
|
480
504
|
return;
|
|
505
|
+
case "shutdown_handoff":
|
|
506
|
+
this.gracefulHandoffShutdown();
|
|
507
|
+
return;
|
|
481
508
|
default: return msg;
|
|
482
509
|
}
|
|
483
510
|
}
|
|
@@ -615,6 +642,37 @@ var PortalDaemon = class {
|
|
|
615
642
|
this.server?.close();
|
|
616
643
|
process.exit(0);
|
|
617
644
|
}
|
|
645
|
+
/**
|
|
646
|
+
* Graceful takeover step-down (a newer daemon is replacing us). Unlike
|
|
647
|
+
* `forceShutdown`, this does NOT drop the portal connection up front: doing so
|
|
648
|
+
* would let this machine's presence key expire (10s TTL) before the successor
|
|
649
|
+
* dials out and re-claims it, which is the `registered but not connected` gap
|
|
650
|
+
* that made `exec`/`file write` fail mid-self-update.
|
|
651
|
+
*
|
|
652
|
+
* Order matters. We free the control socket and disconnect attached CLIs
|
|
653
|
+
* first, because the successor cannot bind the singleton socket (and thus
|
|
654
|
+
* cannot start its own portal client) until we release it. But we KEEP our
|
|
655
|
+
* outbound portal WebSocket — and its presence claim — alive across that
|
|
656
|
+
* window. When the successor connects and `claim()`s the slot, the server
|
|
657
|
+
* supersedes us and closes our socket; `beginHandoff` resolves on that close
|
|
658
|
+
* and we exit. A bounded fallback inside `beginHandoff` still exits us if the
|
|
659
|
+
* successor never comes up, so we never hold a dead slot forever.
|
|
660
|
+
*/
|
|
661
|
+
async gracefulHandoffShutdown() {
|
|
662
|
+
if (this.handingOff) return;
|
|
663
|
+
this.handingOff = true;
|
|
664
|
+
for (const conn of this.conns) try {
|
|
665
|
+
conn.socket.destroy();
|
|
666
|
+
} catch (_error) {}
|
|
667
|
+
this.conns.clear();
|
|
668
|
+
this.server?.close();
|
|
669
|
+
this.server = null;
|
|
670
|
+
if (this.client) {
|
|
671
|
+
await this.client.beginHandoff(HANDOFF_MAX_WAIT_MS);
|
|
672
|
+
this.client.dispose();
|
|
673
|
+
}
|
|
674
|
+
process.exit(0);
|
|
675
|
+
}
|
|
618
676
|
async loadState() {
|
|
619
677
|
try {
|
|
620
678
|
const raw = await readFile(this.paths.statePath, "utf8");
|
|
@@ -663,7 +721,7 @@ async function ensureDaemonRunning(appUrl) {
|
|
|
663
721
|
if (await isDaemonListening(socketPath)) {
|
|
664
722
|
const status = await queryDaemonStatus(appUrl);
|
|
665
723
|
if (!status || !isNewerBuild(portalDaemonBuild(), status.build)) return;
|
|
666
|
-
if (await
|
|
724
|
+
if (await stopDaemonForHandoff(appUrl) === "failed") return;
|
|
667
725
|
}
|
|
668
726
|
const entry = process.argv[1];
|
|
669
727
|
const args = entry ? [
|
|
@@ -758,6 +816,37 @@ async function queryDaemonStatus(appUrl) {
|
|
|
758
816
|
});
|
|
759
817
|
}
|
|
760
818
|
/**
|
|
819
|
+
* Ask a running incumbent daemon to step down for a make-before-break handoff
|
|
820
|
+
* (see the daemon's `gracefulHandoffShutdown`). Sends `shutdown_handoff` and
|
|
821
|
+
* waits for the incumbent to release the CONTROL SOCKET — at which point the
|
|
822
|
+
* successor can bind it and start its own portal client. Crucially, the
|
|
823
|
+
* incumbent keeps its portal connection (and presence) alive past this point,
|
|
824
|
+
* so the successor's subsequent `claim()` supersedes it with no presence gap.
|
|
825
|
+
*
|
|
826
|
+
* Returns `stopped` once the socket is free, `failed` if it never freed (the
|
|
827
|
+
* caller should then leave the incumbent alone rather than fight it — same
|
|
828
|
+
* fallback semantics as `stopDaemon`), or `not-running` if nothing was there.
|
|
829
|
+
* Unlike `stopDaemon` this never SIGKILLs: the incumbent is intentionally still
|
|
830
|
+
* alive (holding presence) after it frees the socket, so killing it by pid is
|
|
831
|
+
* exactly the gap this path exists to avoid.
|
|
832
|
+
*/
|
|
833
|
+
async function stopDaemonForHandoff(appUrl) {
|
|
834
|
+
const { socketPath } = daemonPaths(appUrl);
|
|
835
|
+
if (!await isDaemonListening(socketPath)) return "not-running";
|
|
836
|
+
const sock = await connectControl(socketPath);
|
|
837
|
+
if (!sock) return "failed";
|
|
838
|
+
sock.write(encodeLine({ t: "shutdown_handoff" }));
|
|
839
|
+
for (let i = 0; i < 50; i += 1) {
|
|
840
|
+
await sleep(100);
|
|
841
|
+
if (!await isDaemonListening(socketPath)) {
|
|
842
|
+
sock.destroy();
|
|
843
|
+
return "stopped";
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
sock.destroy();
|
|
847
|
+
return "failed";
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
761
850
|
* Hard-stop a running daemon. Preferred path: send `shutdown` over the control
|
|
762
851
|
* socket so it drains clients and exits cleanly. If the socket is unresponsive
|
|
763
852
|
* (a wedged daemon), fall back to SIGTERM then SIGKILL by the pid the status
|
|
@@ -809,4 +898,4 @@ function sleep(ms) {
|
|
|
809
898
|
}
|
|
810
899
|
|
|
811
900
|
//#endregion
|
|
812
|
-
export { runPortalDaemon as a,
|
|
901
|
+
export { runPortalDaemon as a, stopDaemonForHandoff as c, daemonPaths as d, encodeLine as f, queryDaemonStatus as i, LOCAL_PROTOCOL_VERSION as l, parseDaemonMessage as m, ensureDaemonRunning as n, startPortalDaemon as o, makeLineParser as p, isDaemonListening as r, stopDaemon as s, PortalDaemon as t, PORTAL_DAEMON_FLAG as u };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./client-C2lPer4b.mjs";
|
|
3
|
+
import { a as runPortalDaemon, c as stopDaemonForHandoff, i as queryDaemonStatus, n as ensureDaemonRunning, o as startPortalDaemon, r as isDaemonListening, s as stopDaemon, t as PortalDaemon } from "./daemon-MZN78SYL.mjs";
|
|
4
|
+
import "./tls-cert-CV-pwxVN.mjs";
|
|
5
|
+
import "./api-TwLD7ibI.mjs";
|
|
6
|
+
|
|
7
|
+
export { runPortalDaemon };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { d as daemonPaths, f as encodeLine, l as LOCAL_PROTOCOL_VERSION, m as parseDaemonMessage, n as ensureDaemonRunning, p as makeLineParser } from "./daemon-MZN78SYL.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { connect } from "node:net";
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { r as warnOnRebindProtection } from "./tls-cert-CV-pwxVN.mjs";
|
|
3
|
-
import { l as startTlsForward, t as fetchForwardTarget } from "./api-
|
|
3
|
+
import { l as startTlsForward, t as fetchForwardTarget } from "./api-TwLD7ibI.mjs";
|
|
4
4
|
import net from "node:net";
|
|
5
5
|
import { WebSocket, createWebSocketStream } from "ws";
|
|
6
6
|
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { s as version$1 } from "./rest-BtHVI0y6.mjs";
|
|
3
|
+
import { w as getConfigPath } from "./print-Bg8rzq9t.mjs";
|
|
3
4
|
import os from "node:os";
|
|
4
5
|
import path from "node:path";
|
|
5
6
|
import { err, ok } from "neverthrow";
|
|
6
7
|
import { z } from "zod";
|
|
7
8
|
import fs from "node:fs";
|
|
8
9
|
|
|
9
|
-
//#region package.json
|
|
10
|
-
var name = "skydive-cli";
|
|
11
|
-
var version$1 = "0.5.0-beta.41";
|
|
12
|
-
|
|
13
|
-
//#endregion
|
|
14
10
|
//#region src/auth/organization.ts
|
|
15
11
|
const workspaceSchema = z.object({
|
|
16
12
|
id: z.string(),
|
|
@@ -1582,4 +1578,4 @@ function printFatalNotice(file, memory) {
|
|
|
1582
1578
|
}
|
|
1583
1579
|
|
|
1584
1580
|
//#endregion
|
|
1585
|
-
export { installAgentAlias as A, resolveWorkspaceId as B, themeVersion as C, machineOsFromPlatform as D, buildImportSeedPrompt as E, detectShell as F,
|
|
1581
|
+
export { installAgentAlias as A, resolveWorkspaceId as B, themeVersion as C, machineOsFromPlatform as D, buildImportSeedPrompt as E, detectShell as F, ensureActiveOrganization as I, getActiveWorkspaceId as L, takenAliasNames as M, SUPPORTED_SHELLS as N, aliasActivationHint as O, defaultInstallEnv as P, getSessionIdentity as R, themeModeFromColorFgBg as S, themesForMode as T, setActiveWorkspace as V, monoTheme as _, WORDMARK as a, themeForMode as b, getAutomaticLogsDir as c, profilingEnabled as d, record as f, findTheme as g, applyTheme as h, MARK_CELLS as i, slugifyAliasName as j, dedupeAliasName as k, maybeStartProfiling as l, DEFAULT_THEME_ID as m, buildCrashReport as n, brandHelpArt as o, writeArtifact as p, writeCrashReport as r, splashFitsWidth as s, installCrashHandler as t, profileDir as u, noColorRequested as v, themes as w, themeMode as x, theme as y, listWorkspaces as z };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import "./
|
|
2
|
+
import "./rest-BtHVI0y6.mjs";
|
|
3
|
+
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-Bg8rzq9t.mjs";
|
|
4
4
|
import "./billing-blocked-D3l5kJlX.mjs";
|
|
5
5
|
|
|
6
6
|
export { messageGet, readStdin, resolveAgent, runPrint };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
2
|
+
import { a as isRecord, i as errorMessage, r as sendErrorMessage, t as createRestClient } from "./rest-BtHVI0y6.mjs";
|
|
3
|
+
import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
|
|
4
4
|
import { i as billingBlockedOutcomeFromSendResponse, n as BillingBlockedError } from "./billing-blocked-D3l5kJlX.mjs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import Conf from "conf";
|
|
@@ -440,7 +440,8 @@ function parseDesktopHandoffCard(rootEl) {
|
|
|
440
440
|
},
|
|
441
441
|
state: {},
|
|
442
442
|
computeRequestId: null,
|
|
443
|
-
settled: null
|
|
443
|
+
settled: null,
|
|
444
|
+
questions: []
|
|
444
445
|
};
|
|
445
446
|
}
|
|
446
447
|
/**
|
|
@@ -478,7 +479,70 @@ function parseComputeRequestCard(rootEl) {
|
|
|
478
479
|
},
|
|
479
480
|
state: {},
|
|
480
481
|
computeRequestId: requestId,
|
|
481
|
-
settled
|
|
482
|
+
settled,
|
|
483
|
+
questions: []
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function readQuestionOptions(raw) {
|
|
487
|
+
if (!Array.isArray(raw)) return [];
|
|
488
|
+
return raw.flatMap((o) => {
|
|
489
|
+
if (!isRecord(o)) return [];
|
|
490
|
+
const label = optionalString(o.label);
|
|
491
|
+
if (!label) return [];
|
|
492
|
+
return [{ label }];
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
function readQuestionEntries(raw) {
|
|
496
|
+
if (!Array.isArray(raw)) return [];
|
|
497
|
+
return raw.flatMap((q) => {
|
|
498
|
+
if (!isRecord(q)) return [];
|
|
499
|
+
const question = optionalString(q.question);
|
|
500
|
+
if (!question) return [];
|
|
501
|
+
const options = readQuestionOptions(q.options);
|
|
502
|
+
if (options.length < 2) return [];
|
|
503
|
+
return [{
|
|
504
|
+
question,
|
|
505
|
+
options,
|
|
506
|
+
multiSelect: Boolean(q.multiSelect)
|
|
507
|
+
}];
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* The `platform ask` form. The web renders it as an interactive picker; here
|
|
512
|
+
* it maps onto an answer_question button so ctrl+r (and letter shortcuts)
|
|
513
|
+
* open an in-TUI picker. The composed answer is sent as a normal user
|
|
514
|
+
* message — same non-blocking model as the web card. Without this the spec
|
|
515
|
+
* is not a Card, parses to null, and the question is silently dropped.
|
|
516
|
+
*/
|
|
517
|
+
/** Compose the user-message body the web card also sends. */
|
|
518
|
+
function composeQuestionAnswer(questions, answers) {
|
|
519
|
+
if (questions.length === 1) return (answers[0] ?? []).join(", ");
|
|
520
|
+
return questions.map((q, i) => `${q.question} → ${(answers[i] ?? []).join(", ")}`).join("\n");
|
|
521
|
+
}
|
|
522
|
+
function parseQuestionCard(rootEl) {
|
|
523
|
+
const props = isRecord(rootEl.props) ? rootEl.props : {};
|
|
524
|
+
const cardId = optionalString(props.cardId);
|
|
525
|
+
if (!cardId) return null;
|
|
526
|
+
const questions = readQuestionEntries(props.questions);
|
|
527
|
+
if (questions.length === 0) return null;
|
|
528
|
+
const settled = (props.status === "answered" ? "answered" : "pending") === "answered" ? optionalString(props.answerSummary) ?? "answered" : null;
|
|
529
|
+
const only = questions.length === 1 ? questions[0] : void 0;
|
|
530
|
+
return {
|
|
531
|
+
title: only ? only.question : "Questions",
|
|
532
|
+
subtitle: null,
|
|
533
|
+
description: null,
|
|
534
|
+
fields: [],
|
|
535
|
+
button: settled ? null : {
|
|
536
|
+
label: "Answer",
|
|
537
|
+
action: {
|
|
538
|
+
kind: "answer_question",
|
|
539
|
+
cardId
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
state: {},
|
|
543
|
+
computeRequestId: null,
|
|
544
|
+
settled,
|
|
545
|
+
questions
|
|
482
546
|
};
|
|
483
547
|
}
|
|
484
548
|
function parseConnectCard(spec) {
|
|
@@ -489,6 +553,7 @@ function parseConnectCard(spec) {
|
|
|
489
553
|
if (!isRecord(rootEl)) return null;
|
|
490
554
|
if (rootEl.type === "DesktopHandoffCard") return parseDesktopHandoffCard(rootEl);
|
|
491
555
|
if (rootEl.type === "ComputeRequestCard") return parseComputeRequestCard(rootEl);
|
|
556
|
+
if (rootEl.type === "QuestionCard") return parseQuestionCard(rootEl);
|
|
492
557
|
if (rootEl.type !== "Card") return null;
|
|
493
558
|
const rootProps = isRecord(rootEl.props) ? rootEl.props : {};
|
|
494
559
|
const title = optionalString(rootProps.title);
|
|
@@ -529,7 +594,8 @@ function parseConnectCard(spec) {
|
|
|
529
594
|
} : null,
|
|
530
595
|
state: isRecord(spec.state) ? spec.state : {},
|
|
531
596
|
computeRequestId: null,
|
|
532
|
-
settled: null
|
|
597
|
+
settled: null,
|
|
598
|
+
questions: []
|
|
533
599
|
};
|
|
534
600
|
}
|
|
535
601
|
|
|
@@ -677,6 +743,13 @@ function summarizeConnectCard(card, appUrl) {
|
|
|
677
743
|
requestId: act.requestId
|
|
678
744
|
}
|
|
679
745
|
};
|
|
746
|
+
case "answer_question": return {
|
|
747
|
+
...base,
|
|
748
|
+
action: {
|
|
749
|
+
kind: "answer_question",
|
|
750
|
+
questions: card.questions.map((q) => q.question)
|
|
751
|
+
}
|
|
752
|
+
};
|
|
680
753
|
default: return {
|
|
681
754
|
...base,
|
|
682
755
|
action: { kind: "unsupported" }
|
|
@@ -717,6 +790,9 @@ function formatConnectCard(card) {
|
|
|
717
790
|
case "decide_compute":
|
|
718
791
|
lines.push("Approve or deny this compute increase in the interactive TUI or web app.");
|
|
719
792
|
break;
|
|
793
|
+
case "answer_question":
|
|
794
|
+
lines.push(`Answer in the interactive TUI or web app: ${card.action.questions.join("; ")}`);
|
|
795
|
+
break;
|
|
720
796
|
case "unsupported":
|
|
721
797
|
lines.push("Open this conversation in the web app to continue.");
|
|
722
798
|
break;
|
|
@@ -936,4 +1012,4 @@ async function readStdin() {
|
|
|
936
1012
|
}
|
|
937
1013
|
|
|
938
1014
|
//#endregion
|
|
939
|
-
export {
|
|
1015
|
+
export { getSavedTheme as A, resolveSession as B, deleteConfig as C, getPreference as D, getLastSeenVersion as E, recordDefaultAgent as F, setLastSeenVersion as G, saveConfig as H, resolveAppUrl as I, resolveChatAuth as L, getStoredApiKeyId as M, getStoredApiKeyWorkspaceName as N, getPromptHistoryPath as O, getUpdateCheckDisabled as P, resolveConfig as R, PREFERENCES as S, getDefaultAgent as T, saveSession as U, resolveWebUrl as V, saveTheme as W, API_KEYS_URL as _, runPrint as a, DEFAULT_API_URL as b, cardActionErrorMessage as c, reconcileMaskedInput as d, resolveConnectUrl as f, specKeyFor as g, parseConnectCard as h, resolveAgent as i, getShareMachineDefault as j, getReviewStateDir as k, parseExternalOauthConnectParams as l, computeSettledLabel as m, messageGet as n, toPrintError as o, composeQuestionAnswer as p, readStdin as r, MASK_CHAR as s, collectRunText as t, parseOauthConnectParams as u, API_KEY_FAMILY_PREFIX as v, getConfigPath as w, DEFAULT_APP_URL as x, API_KEY_PREFIX as y, resolveManagementAuth as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as printError } from "./output-
|
|
2
|
+
import { n as printError } from "./output-C9mb3sUB.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/chat/print-share.ts
|
|
5
5
|
/**
|
|
@@ -14,7 +14,7 @@ import { n as printError } from "./output-wY0VQDea.mjs";
|
|
|
14
14
|
* the reply (and to --json).
|
|
15
15
|
*/
|
|
16
16
|
async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
|
|
17
|
-
const { PortalClient } = await import("./client-
|
|
17
|
+
const { PortalClient } = await import("./client-CSKr4Swa.mjs");
|
|
18
18
|
const { defaultTlsCertSource } = await import("./tls-cert-CLgSQALB.mjs");
|
|
19
19
|
let signalConnected;
|
|
20
20
|
const connected = new Promise((resolve) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
2
|
+
import { n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-BtHVI0y6.mjs";
|
|
3
|
+
import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
|
|
4
4
|
import "./billing-blocked-D3l5kJlX.mjs";
|
|
5
5
|
|
|
6
6
|
export { createRestClient };
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as HttpError } from "./http-error-
|
|
2
|
+
import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
|
|
3
3
|
import { a as billingBlockedOutcomeSchema } from "./billing-blocked-D3l5kJlX.mjs";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createParser } from "eventsource-parser";
|
|
6
6
|
|
|
7
|
+
//#region package.json
|
|
8
|
+
var name = "skydive-cli";
|
|
9
|
+
var version = "0.5.0-beta.46";
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
7
12
|
//#region src/chat/util.ts
|
|
8
13
|
/** Narrowing helper for the many `unknown` payloads the chat stream and
|
|
9
14
|
* tool inputs/outputs carry. A type predicate (not an `as` cast), so call
|
|
@@ -18,6 +23,7 @@ function errorMessage(err) {
|
|
|
18
23
|
|
|
19
24
|
//#endregion
|
|
20
25
|
//#region src/chat/api/rest.ts
|
|
26
|
+
const CLI_VERSION_HEADER = "x-skydive-cli-version";
|
|
21
27
|
const ERROR_DETAIL_MAX_BODY = 2e3;
|
|
22
28
|
/**
|
|
23
29
|
* Fullest renderable text for a thrown value. `HttpError.message` clips the
|
|
@@ -104,7 +110,8 @@ const MAX_STREAM_RECONNECTS = 5;
|
|
|
104
110
|
function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
105
111
|
const baseHeaders = {
|
|
106
112
|
authorization: `Bearer ${sessionToken}`,
|
|
107
|
-
accept: "application/json"
|
|
113
|
+
accept: "application/json",
|
|
114
|
+
[CLI_VERSION_HEADER]: version
|
|
108
115
|
};
|
|
109
116
|
if (workspaceId) baseHeaders["x-workspace-id"] = workspaceId;
|
|
110
117
|
async function get(path, schema) {
|
|
@@ -147,7 +154,8 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
147
154
|
try {
|
|
148
155
|
const headers = {
|
|
149
156
|
authorization: `Bearer ${sessionToken}`,
|
|
150
|
-
accept: "text/event-stream"
|
|
157
|
+
accept: "text/event-stream",
|
|
158
|
+
[CLI_VERSION_HEADER]: version
|
|
151
159
|
};
|
|
152
160
|
if (workspaceId) headers["x-workspace-id"] = workspaceId;
|
|
153
161
|
if (lastEventId) headers["last-event-id"] = lastEventId;
|
|
@@ -441,6 +449,7 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
441
449
|
headers: {
|
|
442
450
|
authorization: `Bearer ${sessionToken}`,
|
|
443
451
|
accept: "text/event-stream",
|
|
452
|
+
[CLI_VERSION_HEADER]: version,
|
|
444
453
|
...workspaceId ? { "x-workspace-id": workspaceId } : {}
|
|
445
454
|
},
|
|
446
455
|
signal
|
|
@@ -687,4 +696,4 @@ const conversationStreamEventSchema = z.discriminatedUnion("kind", [
|
|
|
687
696
|
]);
|
|
688
697
|
|
|
689
698
|
//#endregion
|
|
690
|
-
export { isRecord as a, errorMessage as i, errorDetail as n, sendErrorMessage as r, createRestClient as t };
|
|
699
|
+
export { isRecord as a, errorMessage as i, errorDetail as n, name as o, sendErrorMessage as r, version as s, createRestClient as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skydive-cli",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.46",
|
|
4
4
|
"description": "Skydive CLI — cloud agents from the command line",
|
|
5
5
|
"homepage": "https://skydive.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
},
|
|
70
70
|
"//optionalDependencies": "The per-platform binary packages (skydive-cli-<os>-<arch>) are INTENTIONALLY not committed here. They are published by release-skydive-cli-binaries.yml and injected — pinned to the exact version being published — into the published launcher's optionalDependencies at release time (scripts/prepare-platform-packages.mjs --pin-version, run in release-skydive-cli.yml). Committing them would make `yarn install` try to resolve versions that only exist post-publish, breaking local dev and CI. npm installs of a published skydive-cli still get them (os/cpu-gated); the launcher (src/launcher.ts) resolves and execs the matching one. Local dev never needs them: it runs the JS bundle or `build:binary` directly.",
|
|
71
71
|
"optionalDependencies": {
|
|
72
|
-
"skydive-cli-darwin-arm64": "0.5.0-beta.
|
|
73
|
-
"skydive-cli-darwin-x64": "0.5.0-beta.
|
|
74
|
-
"skydive-cli-linux-x64": "0.5.0-beta.
|
|
75
|
-
"skydive-cli-linux-arm64": "0.5.0-beta.
|
|
72
|
+
"skydive-cli-darwin-arm64": "0.5.0-beta.46",
|
|
73
|
+
"skydive-cli-darwin-x64": "0.5.0-beta.46",
|
|
74
|
+
"skydive-cli-linux-x64": "0.5.0-beta.46",
|
|
75
|
+
"skydive-cli-linux-arm64": "0.5.0-beta.46"
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import "./client-DMYwKALl.mjs";
|
|
3
|
-
import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as startPortalDaemon, r as isDaemonListening, s as stopDaemon, t as PortalDaemon } from "./daemon-D8WoX21I.mjs";
|
|
4
|
-
import "./tls-cert-CV-pwxVN.mjs";
|
|
5
|
-
import "./api-DQCaztBg.mjs";
|
|
6
|
-
|
|
7
|
-
export { runPortalDaemon };
|
|
File without changes
|
|
File without changes
|