skydive-cli 0.6.0-beta.3 → 0.6.0-beta.31
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 +4 -0
- package/dist/js/bin.mjs +27 -24
- package/dist/js/{boot-CleHADz9.mjs → boot-DioqUxIR.mjs} +2219 -1208
- package/dist/js/{client-CErCpXl9.mjs → client-B72n-W4g.mjs} +34 -6
- package/dist/js/client-CIwTYHhL.mjs +5 -0
- package/dist/js/{client-Btq6bMzX.mjs → client-l6orYfqq.mjs} +22 -1
- package/dist/js/{daemon-Cuy4S6Rw.mjs → daemon-C4cZdILE.mjs} +23 -3
- package/dist/js/{daemon-BuTGs-Ns.mjs → daemon-DyRnbB8K.mjs} +2 -2
- package/dist/js/daemon-client-Ct4HIyrx.mjs +8 -0
- package/dist/js/{daemon-client-b10uck-j.mjs → daemon-client-P4qpHwFG.mjs} +1 -1
- package/dist/js/{install-D7MwRv0n.mjs → install-CLgma6A8.mjs} +2 -2
- package/dist/js/{print-VulYMc7x.mjs → print-Bb4HiYmg.mjs} +2 -2
- package/dist/js/{print-B3yhPm0N.mjs → print-D1CeaocN.mjs} +62 -2
- package/dist/js/{print-share-DfTHn1HL.mjs → print-share-BlwlkQ-M.mjs} +1 -1
- package/dist/js/raw-pty-DRZuf1oW.mjs +5 -0
- package/dist/js/{raw-pty-D5PhKZSl.mjs → raw-pty-dndn1Kxc.mjs} +1 -1
- package/dist/js/{rest-CRRpVyot.mjs → rest-C6XQyC5g.mjs} +1 -1
- package/dist/js/{rest-ChXt8YGA.mjs → rest-DU74TXCi.mjs} +38 -2
- package/package.json +8 -7
- package/dist/js/client-qY4nTj2Y.mjs +0 -5
- package/dist/js/daemon-client-BVX-rWfX.mjs +0 -8
- package/dist/js/raw-pty-Ci2qFR9F.mjs +0 -5
|
@@ -160,7 +160,7 @@ function errorMessage(err) {
|
|
|
160
160
|
* the commit time of the built tree is one monotonic clock they share.
|
|
161
161
|
*/
|
|
162
162
|
function portalDaemonBuild() {
|
|
163
|
-
return "
|
|
163
|
+
return "1790192806";
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
166
|
* Whether a client carrying `mine` should replace a running daemon carrying
|
|
@@ -186,6 +186,8 @@ function parseStamp(stamp) {
|
|
|
186
186
|
|
|
187
187
|
//#endregion
|
|
188
188
|
//#region ../portal-protocol/src/index.ts
|
|
189
|
+
const CLOSE_SUPERSEDED = 4001;
|
|
190
|
+
const CLOSE_FLAP_COOLDOWN = 4002;
|
|
189
191
|
const MAX_WS_FRAME_BYTES = 16 * 1024 * 1024;
|
|
190
192
|
const T_DATA = 1;
|
|
191
193
|
const T_CTRL = 2;
|
|
@@ -584,7 +586,11 @@ const DEFAULT_HEARTBEAT = {
|
|
|
584
586
|
wakeGapThresholdMs: 1e4,
|
|
585
587
|
netWatchTickMs: 2e3,
|
|
586
588
|
initialBackoffMs: 500,
|
|
587
|
-
maxBackoffMs: 1e4
|
|
589
|
+
maxBackoffMs: 1e4,
|
|
590
|
+
supersededBackoffFloorMs: 5e3,
|
|
591
|
+
flapWindowMs: 6e4,
|
|
592
|
+
flapMaxStandDowns: 3,
|
|
593
|
+
flapBackoffMs: 6e4
|
|
588
594
|
};
|
|
589
595
|
/**
|
|
590
596
|
* A cheap fingerprint of the machine's network identity: every non-internal
|
|
@@ -669,6 +675,7 @@ var PortalClient = class {
|
|
|
669
675
|
netWatch = null;
|
|
670
676
|
netFingerprint = networkFingerprint();
|
|
671
677
|
backoffKick = null;
|
|
678
|
+
inStandDownSleep = false;
|
|
672
679
|
dialReason = null;
|
|
673
680
|
disconnectedAt = null;
|
|
674
681
|
handingOff = false;
|
|
@@ -739,6 +746,7 @@ var PortalClient = class {
|
|
|
739
746
|
this.ws.terminate();
|
|
740
747
|
return;
|
|
741
748
|
}
|
|
749
|
+
if (this.inStandDownSleep) return;
|
|
742
750
|
this.kickBackoff();
|
|
743
751
|
}
|
|
744
752
|
kickBackoff() {
|
|
@@ -914,11 +922,23 @@ var PortalClient = class {
|
|
|
914
922
|
this.opts.onMachineName(identity.machineName, identity.machineNameSource);
|
|
915
923
|
}
|
|
916
924
|
let backoff = this.heartbeatConfig.initialBackoffMs;
|
|
925
|
+
let standDowns = [];
|
|
917
926
|
while (this.enabled && !this.disposed && !this.handingOff) {
|
|
918
927
|
this.setStatus("connecting");
|
|
928
|
+
let sleepFloor = 0;
|
|
919
929
|
try {
|
|
920
930
|
const token = await this.wsToken();
|
|
921
|
-
|
|
931
|
+
const { healthy, standDown } = await this.runConnection(token);
|
|
932
|
+
if (standDown) {
|
|
933
|
+
const now = Date.now();
|
|
934
|
+
standDowns.push(now);
|
|
935
|
+
standDowns = standDowns.filter((at) => now - at <= this.heartbeatConfig.flapWindowMs);
|
|
936
|
+
if (standDowns.length >= this.heartbeatConfig.flapMaxStandDowns) {
|
|
937
|
+
backoff = this.heartbeatConfig.flapBackoffMs;
|
|
938
|
+
this.setStatus("error", "another portal connection for this machine keeps taking over — if Skydive Desktop or `skydive portal open` is running twice, quit the duplicate; an unstable network can also cause this briefly");
|
|
939
|
+
} else backoff = Math.max(Math.min(backoff * 2, this.heartbeatConfig.maxBackoffMs), this.heartbeatConfig.supersededBackoffFloorMs);
|
|
940
|
+
sleepFloor = backoff / 2;
|
|
941
|
+
} else if (healthy) backoff = this.heartbeatConfig.initialBackoffMs;
|
|
922
942
|
else backoff = Math.min(backoff * 2, this.heartbeatConfig.maxBackoffMs);
|
|
923
943
|
} catch (err) {
|
|
924
944
|
if (!this.enabled || this.disposed || this.handingOff) break;
|
|
@@ -926,17 +946,23 @@ var PortalClient = class {
|
|
|
926
946
|
backoff = Math.min(backoff * 2, this.heartbeatConfig.maxBackoffMs);
|
|
927
947
|
}
|
|
928
948
|
if (!this.enabled || this.disposed || this.handingOff) break;
|
|
929
|
-
|
|
949
|
+
this.inStandDownSleep = sleepFloor > 0;
|
|
950
|
+
await this.backoffSleep(sleepFloor + Math.random() * Math.max(backoff - sleepFloor, 0));
|
|
951
|
+
this.inStandDownSleep = false;
|
|
930
952
|
}
|
|
931
953
|
}
|
|
932
954
|
runConnection(token) {
|
|
933
955
|
return new Promise((resolve) => {
|
|
934
956
|
let settled = false;
|
|
935
957
|
let healthy = false;
|
|
958
|
+
let standDown = false;
|
|
936
959
|
const settle = () => {
|
|
937
960
|
if (settled) return;
|
|
938
961
|
settled = true;
|
|
939
|
-
resolve(
|
|
962
|
+
resolve({
|
|
963
|
+
healthy,
|
|
964
|
+
standDown
|
|
965
|
+
});
|
|
940
966
|
};
|
|
941
967
|
const ws = new WebSocket(portalWsUrl(this.opts.appUrl, this.machineName, this.friendlyName, {
|
|
942
968
|
build: portalDaemonBuild(),
|
|
@@ -988,7 +1014,9 @@ var PortalClient = class {
|
|
|
988
1014
|
ws.on("error", (err) => {
|
|
989
1015
|
this.error = errorMessage(err);
|
|
990
1016
|
});
|
|
991
|
-
ws.on("close", (code) => {
|
|
1017
|
+
ws.on("close", (code, reason) => {
|
|
1018
|
+
standDown = code === CLOSE_SUPERSEDED || code === CLOSE_FLAP_COOLDOWN || code === 1e3 && reason.toString() === "superseded";
|
|
1019
|
+
if (standDown) this.dialReason ??= `superseded (code ${code})`;
|
|
992
1020
|
this.dialReason ??= `connection closed (code ${code})`;
|
|
993
1021
|
this.disconnectedAt ??= Date.now();
|
|
994
1022
|
clearInterval(heartbeat);
|
|
@@ -223,8 +223,23 @@ var SandboxStream = class SandboxStream {
|
|
|
223
223
|
}
|
|
224
224
|
});
|
|
225
225
|
let failure = null;
|
|
226
|
+
ws.on("unexpected-response", (_request, response) => {
|
|
227
|
+
const chunks = [];
|
|
228
|
+
let bytes = 0;
|
|
229
|
+
response.on("data", (chunk) => {
|
|
230
|
+
if (bytes >= MAX_HANDSHAKE_BODY_BYTES) return;
|
|
231
|
+
const remaining = MAX_HANDSHAKE_BODY_BYTES - bytes;
|
|
232
|
+
const kept = Buffer.from(chunk).subarray(0, remaining);
|
|
233
|
+
chunks.push(kept);
|
|
234
|
+
bytes += kept.length;
|
|
235
|
+
});
|
|
236
|
+
response.on("end", () => {
|
|
237
|
+
failure = formatHandshakeRejection(response.statusCode, response.statusMessage, Buffer.concat(chunks).toString("utf8"));
|
|
238
|
+
ws.terminate();
|
|
239
|
+
});
|
|
240
|
+
});
|
|
226
241
|
ws.on("error", (err) => {
|
|
227
|
-
failure
|
|
242
|
+
failure ??= err.message;
|
|
228
243
|
});
|
|
229
244
|
ws.on("close", () => {
|
|
230
245
|
this.closed = true;
|
|
@@ -265,6 +280,12 @@ var SandboxStream = class SandboxStream {
|
|
|
265
280
|
return new SandboxStream(new WebSocket(url.toString(), { headers: { authorization: `Bearer ${opts.sessionToken}` } }), opts.onEvent);
|
|
266
281
|
}
|
|
267
282
|
};
|
|
283
|
+
const MAX_HANDSHAKE_BODY_BYTES = 512;
|
|
284
|
+
function formatHandshakeRejection(statusCode, statusMessage, body) {
|
|
285
|
+
const status = [statusCode, statusMessage].filter(Boolean).join(" ");
|
|
286
|
+
const reason = Array.from(body, (char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127 ? " " : char).join("").replace(/\s+/g, " ").trim();
|
|
287
|
+
return reason ? `${status}: ${reason}` : status || "WebSocket upgrade rejected";
|
|
288
|
+
}
|
|
268
289
|
function toBuffer(data) {
|
|
269
290
|
if (Buffer.isBuffer(data)) return data;
|
|
270
291
|
if (Array.isArray(data)) return Buffer.concat(data);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as isRecord, n as isNewerBuild, r as portalDaemonBuild, t as PortalClient } from "./client-
|
|
2
|
+
import { i as isRecord, n as isNewerBuild, r as portalDaemonBuild, t as PortalClient } from "./client-B72n-W4g.mjs";
|
|
3
3
|
import { t as defaultTlsCertSource } from "./tls-cert-Rua2oV7n.mjs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
@@ -73,17 +73,37 @@ function canonicalPortalAppUrl(appUrl) {
|
|
|
73
73
|
* every alias of one deployment (see {@link canonicalPortalAppUrl}) shares
|
|
74
74
|
* one. Kept under the OS temp dir because Unix socket paths are
|
|
75
75
|
* length-limited (~104 bytes on macOS).
|
|
76
|
+
*
|
|
77
|
+
* Darwin `sockaddr_un.sun_path` is 104 bytes including NUL (103 usable).
|
|
78
|
+
* `os.tmpdir()` on macOS is `$TMPDIR` (`/var/folders/<id>/T`, often ~50
|
|
79
|
+
* chars). Adding `skydive-portal-<user>-<hash>/daemon.sock` overruns that
|
|
80
|
+
* cap: bind() fails, the sidecar handshake still reports the long path, and
|
|
81
|
+
* connect() returns ENOENT (or Go's "path must be shorter than SUN_LEN").
|
|
82
|
+
* Stay in `os.tmpdir()` (do not relocate to `/tmp`) and shorten the leaf
|
|
83
|
+
* when the composed path would blow the cap. Windows named pipes have no
|
|
84
|
+
* sun_path, so they keep the long leaf.
|
|
76
85
|
*/
|
|
86
|
+
const SUN_PATH_MAX = 103;
|
|
77
87
|
function daemonPaths(appUrl) {
|
|
88
|
+
const parent = os.tmpdir();
|
|
78
89
|
const user = safeSegment(os.userInfo().username || "user");
|
|
79
90
|
const app = createHash("sha256").update(canonicalPortalAppUrl(appUrl)).digest("hex").slice(0, 12);
|
|
80
|
-
const dir = path.join(
|
|
81
|
-
|
|
91
|
+
const dir = path.join(parent, `skydive-portal-${user}-${app}`);
|
|
92
|
+
const paths = {
|
|
82
93
|
dir,
|
|
83
94
|
socketPath: path.join(dir, "daemon.sock"),
|
|
84
95
|
statePath: path.join(dir, "state.json"),
|
|
85
96
|
logPath: path.join(dir, "daemon.log")
|
|
86
97
|
};
|
|
98
|
+
if (process.platform === "win32" || Buffer.byteLength(paths.socketPath) <= SUN_PATH_MAX) return paths;
|
|
99
|
+
const short = createHash("sha256").update(`${os.userInfo().username || "user"}\0${canonicalPortalAppUrl(appUrl)}`).digest("hex").slice(0, 12);
|
|
100
|
+
const shortDir = path.join(parent, `skydive-p-${short}`);
|
|
101
|
+
return {
|
|
102
|
+
dir: shortDir,
|
|
103
|
+
socketPath: path.join(shortDir, "d.sock"),
|
|
104
|
+
statePath: path.join(shortDir, "state.json"),
|
|
105
|
+
logPath: path.join(shortDir, "daemon.log")
|
|
106
|
+
};
|
|
87
107
|
}
|
|
88
108
|
function safeSegment(value) {
|
|
89
109
|
return value.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 24) || "user";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./client-
|
|
2
|
+
import "./client-B72n-W4g.mjs";
|
|
3
3
|
import "./tls-cert-Rua2oV7n.mjs";
|
|
4
4
|
import "./api-BFQ4PQDA.mjs";
|
|
5
|
-
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-
|
|
5
|
+
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-C4cZdILE.mjs";
|
|
6
6
|
|
|
7
7
|
export { runPortalDaemon };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { d as daemonPaths, f as encodeLine, l as LOCAL_PROTOCOL_VERSION, m as parseDaemonMessage, n as ensureDaemonRunning, p as makeLineParser } from "./daemon-
|
|
2
|
+
import { d as daemonPaths, f as encodeLine, l as LOCAL_PROTOCOL_VERSION, m as parseDaemonMessage, n as ensureDaemonRunning, p as makeLineParser } from "./daemon-C4cZdILE.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
|
-
import { c as version$1 } from "./rest-
|
|
3
|
-
import {
|
|
2
|
+
import { c as version$1 } from "./rest-DU74TXCi.mjs";
|
|
3
|
+
import { E as getConfigPath } from "./print-D1CeaocN.mjs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { err, ok } from "neverthrow";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./rest-
|
|
3
|
-
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-
|
|
2
|
+
import "./rest-DU74TXCi.mjs";
|
|
3
|
+
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-D1CeaocN.mjs";
|
|
4
4
|
import "./billing-blocked-D3l5kJlX.mjs";
|
|
5
5
|
|
|
6
6
|
export { messageGet, readStdin, resolveAgent, runPrint };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as errorMessage, i as sendErrorMessage, o as isRecord, t as createRestClient } from "./rest-
|
|
2
|
+
import { a as errorMessage, i as sendErrorMessage, o as isRecord, t as createRestClient } from "./rest-DU74TXCi.mjs";
|
|
3
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";
|
|
@@ -691,6 +691,66 @@ function reconcileMaskedInput(previousValue, displayed) {
|
|
|
691
691
|
while (kept < displayed.length && kept < previousValue.length && displayed[kept] === MASK_CHAR) kept++;
|
|
692
692
|
return previousValue.slice(0, kept) + displayed.slice(kept);
|
|
693
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* Whether a card is one an agent RUN is actively blocked on until the user
|
|
696
|
+
* decides here: a portal-share consent (`platform portal request`), a compute
|
|
697
|
+
* upgrade decision (`platform compute request`), or a connect/credential card
|
|
698
|
+
* the run is waiting to be fulfilled. The lone non-blocking actionable card is
|
|
699
|
+
* `answer_question` — a `platform ask` form, whose answer is a normal user
|
|
700
|
+
* message (the run keeps going regardless), so it must never shadow a decision
|
|
701
|
+
* the agent is stalled on.
|
|
702
|
+
*/
|
|
703
|
+
function isBlockingCardAction(action) {
|
|
704
|
+
return action.kind !== "answer_question";
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Narrow a set of actionable cards to the ones ctrl+r (and the card picker)
|
|
708
|
+
* should target, prioritizing blocking cards over `platform ask` forms. When
|
|
709
|
+
* both a blocking card and a stale `answer_question` are waiting, ctrl+r must
|
|
710
|
+
* approve the thing the agent is stalled on, not re-answer an earlier ask that
|
|
711
|
+
* never stops being actionable (the CLI only settles it via the AskPicker, so
|
|
712
|
+
* an ignored or composer-answered ask lingers forever). Falls through to the
|
|
713
|
+
* ask forms only when they are the only actionable cards left. Preserves input
|
|
714
|
+
* order within a tier, so a single card and genuine multi-card cases behave
|
|
715
|
+
* exactly as before.
|
|
716
|
+
*/
|
|
717
|
+
function prioritizeActionableCards(cards) {
|
|
718
|
+
const blocking = cards.filter((c) => c.card.button !== null && isBlockingCardAction(c.card.button.action));
|
|
719
|
+
return blocking.length > 0 ? blocking : [...cards];
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* The footer verb for a single card action. Derived from the action's own
|
|
723
|
+
* `kind`, not from `isBlockingCardAction` (which answers a different question —
|
|
724
|
+
* "is the run stalled on this" — and is right for prioritization but wrong as a
|
|
725
|
+
* label: it would read a portal-share or compute-approval card as "connect").
|
|
726
|
+
* Each blocking kind gets the verb that matches what the chord actually does:
|
|
727
|
+
* an OAuth/credential card connects, a portal-share card grants, a compute
|
|
728
|
+
* request is decided, a `platform ask` form is answered.
|
|
729
|
+
*/
|
|
730
|
+
function verbForAction(action) {
|
|
731
|
+
switch (action.kind) {
|
|
732
|
+
case "open_oauth":
|
|
733
|
+
case "open_external_oauth":
|
|
734
|
+
case "open_github_app":
|
|
735
|
+
case "submit_credential": return "connect";
|
|
736
|
+
case "grant_portal": return "grant";
|
|
737
|
+
case "decide_compute": return "decide";
|
|
738
|
+
case "answer_question": return "answer";
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* The footer verb for the actionable cards ctrl+r would target. Reflects the
|
|
743
|
+
* first card's actual action so a stale ask never mislabels the footer as
|
|
744
|
+
* "connect", and a portal/compute card reads as "grant"/"decide" rather than
|
|
745
|
+
* being lumped under "connect". Pass the ALREADY-prioritized set (see
|
|
746
|
+
* prioritizeActionableCards) so the label matches what ctrl+r acts on; null
|
|
747
|
+
* when nothing is waiting.
|
|
748
|
+
*/
|
|
749
|
+
function actionableCardVerb(cards) {
|
|
750
|
+
const [first] = cards;
|
|
751
|
+
if (!first || first.card.button === null) return null;
|
|
752
|
+
return verbForAction(first.card.button.action);
|
|
753
|
+
}
|
|
694
754
|
|
|
695
755
|
//#endregion
|
|
696
756
|
//#region src/chat/connect-cards.ts
|
|
@@ -1017,4 +1077,4 @@ async function readStdin() {
|
|
|
1017
1077
|
}
|
|
1018
1078
|
|
|
1019
1079
|
//#endregion
|
|
1020
|
-
export {
|
|
1080
|
+
export { getPromptHistoryPath as A, resolveConfig as B, DEFAULT_APP_URL as C, getDefaultAgent as D, getConfigPath as E, getStoredApiKeyWorkspaceName as F, saveSession as G, resolveSession as H, getUpdateCheckDisabled as I, saveTheme as K, recordDefaultAgent as L, getSavedTheme as M, getShareMachineDefault as N, getLastSeenVersion as O, getStoredApiKeyId as P, resolveAppUrl as R, DEFAULT_API_URL as S, deleteConfig as T, resolveWebUrl as U, resolveManagementAuth as V, saveConfig as W, parseConnectCard as _, runPrint as a, API_KEY_FAMILY_PREFIX as b, actionableCardVerb as c, parseOauthConnectParams as d, prioritizeActionableCards as f, computeSettledLabel as g, composeQuestionAnswer as h, resolveAgent as i, getReviewStateDir as j, getPreference as k, cardActionErrorMessage as l, resolveConnectUrl as m, messageGet as n, toPrintError as o, reconcileMaskedInput as p, setLastSeenVersion as q, readStdin as r, MASK_CHAR as s, collectRunText as t, parseExternalOauthConnectParams as u, specKeyFor as v, PREFERENCES as w, API_KEY_PREFIX as x, API_KEYS_URL as y, resolveChatAuth as z };
|
|
@@ -14,7 +14,7 @@ import { n as printError } from "./output-C9mb3sUB.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-CIwTYHhL.mjs");
|
|
18
18
|
const { defaultTlsCertSource } = await import("./tls-cert-BpCaD5AT.mjs");
|
|
19
19
|
let signalConnected;
|
|
20
20
|
const connected = new Promise((resolve) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as sendErrorMessage, n as errorDetail, r as filenameFromContentDisposition, t as createRestClient } from "./rest-
|
|
2
|
+
import { i as sendErrorMessage, n as errorDetail, r as filenameFromContentDisposition, t as createRestClient } from "./rest-DU74TXCi.mjs";
|
|
3
3
|
import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
|
|
4
4
|
import "./billing-blocked-D3l5kJlX.mjs";
|
|
5
5
|
|
|
@@ -6,7 +6,7 @@ import { createParser } from "eventsource-parser";
|
|
|
6
6
|
|
|
7
7
|
//#region package.json
|
|
8
8
|
var name = "skydive-cli";
|
|
9
|
-
var version = "0.6.0-beta.
|
|
9
|
+
var version = "0.6.0-beta.31";
|
|
10
10
|
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region src/chat/util.ts
|
|
@@ -279,6 +279,14 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
279
279
|
for (const [modelId, config] of Object.entries(modelConfigOverrides ?? {})) if (config.thinkingLevel) efforts[modelId] = config.thinkingLevel;
|
|
280
280
|
return efforts;
|
|
281
281
|
},
|
|
282
|
+
getBillingSummary: async () => {
|
|
283
|
+
const { result } = await get("/api/v1/trpc/v2.billing.getBillingOrgSummary", billingSummaryResponseSchema);
|
|
284
|
+
return result.data;
|
|
285
|
+
},
|
|
286
|
+
getFreeFloorState: async () => {
|
|
287
|
+
const { result } = await get("/api/v1/trpc/v2.billing.freeFloorState", freeFloorStateResponseSchema);
|
|
288
|
+
return result.data;
|
|
289
|
+
},
|
|
282
290
|
setModelEffort: async ({ modelId, thinkingLevel }) => {
|
|
283
291
|
await post("/api/v1/models/config", {
|
|
284
292
|
modelId,
|
|
@@ -295,6 +303,17 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
295
303
|
thinkingLevel: agent.thinkingLevel ?? null
|
|
296
304
|
};
|
|
297
305
|
},
|
|
306
|
+
setConversationModel: async ({ conversationId, agentId, model, thinkingLevel }) => {
|
|
307
|
+
const settled = await post(`/api/v1/conversations/${conversationId}/model`, {
|
|
308
|
+
agentId,
|
|
309
|
+
model,
|
|
310
|
+
thinkingLevel
|
|
311
|
+
}, conversationModelResponseSchema);
|
|
312
|
+
return {
|
|
313
|
+
...settled,
|
|
314
|
+
scope: settled.scope ?? null
|
|
315
|
+
};
|
|
316
|
+
},
|
|
298
317
|
updateAgentEffort: async ({ agentId, thinkingLevel }) => {
|
|
299
318
|
const { agent } = await patchAgent(agentId, { thinkingLevel });
|
|
300
319
|
return { thinkingLevel: agent.thinkingLevel ?? null };
|
|
@@ -541,6 +560,21 @@ const platformModelSchema = z.object({
|
|
|
541
560
|
}).passthrough();
|
|
542
561
|
const listModelsResponseSchema = z.object({ models: z.array(platformModelSchema) });
|
|
543
562
|
const modelEffortPreferencesResponseSchema = z.object({ modelConfigOverrides: z.record(z.string(), z.object({ thinkingLevel: z.string().optional() })).optional() });
|
|
563
|
+
const billingSummaryResponseSchema = z.object({ result: z.object({ data: z.object({
|
|
564
|
+
planKey: z.string().nullable(),
|
|
565
|
+
blockReason: z.string().nullable(),
|
|
566
|
+
billingEnforcementEnabled: z.boolean()
|
|
567
|
+
}) }) });
|
|
568
|
+
const freeFloorStateResponseSchema = z.object({ result: z.object({ data: z.object({
|
|
569
|
+
available: z.boolean(),
|
|
570
|
+
models: z.array(z.string()),
|
|
571
|
+
resetsAt: z.string().nullable()
|
|
572
|
+
}).nullable() }) });
|
|
573
|
+
const conversationModelResponseSchema = z.object({
|
|
574
|
+
model: z.string().nullable(),
|
|
575
|
+
thinkingLevel: z.string().nullable(),
|
|
576
|
+
scope: z.enum(["agent", "conversation"]).nullish()
|
|
577
|
+
});
|
|
544
578
|
const updateAgentResponseSchema = z.object({ agent: z.object({
|
|
545
579
|
model: z.string().nullable().optional(),
|
|
546
580
|
thinkingLevel: z.string().nullable().optional()
|
|
@@ -573,6 +607,7 @@ const conversationSummarySchema = z.object({
|
|
|
573
607
|
channel: z.string().nullable(),
|
|
574
608
|
channelLabel: z.string().nullable(),
|
|
575
609
|
viewerArchivedAt: z.string().nullable().optional(),
|
|
610
|
+
viewerParticipates: z.boolean().optional(),
|
|
576
611
|
unread: z.boolean().optional(),
|
|
577
612
|
agent: conversationAgentSchema,
|
|
578
613
|
agents: z.array(conversationAgentSchema).optional()
|
|
@@ -709,7 +744,8 @@ const conversationStreamEventSchema = z.discriminatedUnion("kind", [
|
|
|
709
744
|
id: z.string(),
|
|
710
745
|
model: z.string().nullable(),
|
|
711
746
|
modelLocked: z.boolean(),
|
|
712
|
-
thinkingLevel: z.string().nullish()
|
|
747
|
+
thinkingLevel: z.string().nullish(),
|
|
748
|
+
agentModel: z.string().nullish()
|
|
713
749
|
}),
|
|
714
750
|
z.object({
|
|
715
751
|
kind: z.literal("run"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skydive-cli",
|
|
3
|
-
"version": "0.6.0-beta.
|
|
3
|
+
"version": "0.6.0-beta.31",
|
|
4
4
|
"description": "Skydive CLI — cloud agents from the command line",
|
|
5
5
|
"homepage": "https://skydive.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
"test:unit": "vitest run --passWithNoTests && yarn test:tui",
|
|
26
26
|
"test:ci": "vitest run --coverage --coverage.reporter=lcovonly --reporter=default --reporter=github-actions --minWorkers=1 --maxWorkers=2 --passWithNoTests && yarn test:tui",
|
|
27
27
|
"test:tui": "node scripts/run-tui-tests.mjs",
|
|
28
|
+
"test:blackbox": "bun test test/blackbox --timeout 120000",
|
|
28
29
|
"render:frames": "bun scripts/render-frames.tsx",
|
|
29
30
|
"render:send-errors": "bun scripts/render-send-errors.tsx",
|
|
30
31
|
"typecheck": "tsgo --noEmit"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@opentui/react": "0.
|
|
34
|
+
"@opentui/react": "0.4.3",
|
|
34
35
|
"conf": "^13.0.1",
|
|
35
36
|
"diff": "9.0.0",
|
|
36
37
|
"eventsource-parser": "^3.0.8",
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
"fuzzysort": "^3.1.0",
|
|
39
40
|
"neverthrow": "^8.2.0",
|
|
40
41
|
"open": "^10.1.0",
|
|
41
|
-
"react": "^19.
|
|
42
|
+
"react": "^19.0.0",
|
|
42
43
|
"react-devtools-core": "^7.0.1",
|
|
43
44
|
"safe-stable-stringify": "^2.3.1",
|
|
44
45
|
"semver": "^7.7.4",
|
|
@@ -70,9 +71,9 @@
|
|
|
70
71
|
},
|
|
71
72
|
"//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.",
|
|
72
73
|
"optionalDependencies": {
|
|
73
|
-
"skydive-cli-darwin-arm64": "0.6.0-beta.
|
|
74
|
-
"skydive-cli-darwin-x64": "0.6.0-beta.
|
|
75
|
-
"skydive-cli-linux-x64": "0.6.0-beta.
|
|
76
|
-
"skydive-cli-linux-arm64": "0.6.0-beta.
|
|
74
|
+
"skydive-cli-darwin-arm64": "0.6.0-beta.31",
|
|
75
|
+
"skydive-cli-darwin-x64": "0.6.0-beta.31",
|
|
76
|
+
"skydive-cli-linux-x64": "0.6.0-beta.31",
|
|
77
|
+
"skydive-cli-linux-arm64": "0.6.0-beta.31"
|
|
77
78
|
}
|
|
78
79
|
}
|