skydive-cli 0.5.0-beta.3 → 0.5.0-beta.5

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/dist/js/bin.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-DtuXkIkR.mjs";
2
+ import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-LLaIFZgn.mjs";
3
3
  import { A as getStoredApiKeyWorkspaceName, C as getLastSeenVersion, F as resolveManagementAuth, I as resolveSession, M as resolveAppUrl, N as resolveChatAuth, O as getShareMachineDefault, P as resolveConfig, R as saveConfig, S as getConfigPath, T as getPromptHistoryPath, V as setLastSeenVersion, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getUpdateCheckDisabled, k as getStoredApiKeyId, v as DEFAULT_API_URL, w as getPreference, x as deleteConfig, z as saveSession } from "./print-CbayCa87.mjs";
4
4
  import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
5
5
  import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
6
6
  import { t as createRestClient } from "./rest-BY2nADw5.mjs";
7
7
  import "./billing-blocked-2wju4gC_.mjs";
8
8
  import { a as registerPortalDevice, c as resolveMachineIdentity, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice } from "./client-Dd5sMXPv.mjs";
9
- import { i as queryDaemonStatus, l as PORTAL_DAEMON_FLAG, n as ensureDaemonRunning, s as stopDaemon, u as daemonPaths } from "./daemon-Bq93vOIk.mjs";
9
+ import { i as queryDaemonStatus, l as PORTAL_DAEMON_FLAG, n as ensureDaemonRunning, s as stopDaemon, u as daemonPaths } from "./daemon-BhArnzeW.mjs";
10
10
  import { t as SandboxStream } from "./client-Cn2af31H.mjs";
11
11
  import { hideBin } from "yargs/helpers";
12
12
  import yargs from "yargs";
@@ -1516,7 +1516,7 @@ const importCommand = {
1516
1516
  process.exit(1);
1517
1517
  }
1518
1518
  }
1519
- const { runChat } = await import("./boot-BVVbrf2k.mjs");
1519
+ const { runChat } = await import("./boot-Brwh0it_.mjs");
1520
1520
  await runChat({
1521
1521
  appUrl,
1522
1522
  sessionToken: session.value.sessionToken,
@@ -1543,7 +1543,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1543
1543
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
1544
1544
  process.exit(1);
1545
1545
  }
1546
- const { connectMachineShare } = await import("./print-share-C1LPsgTP.mjs");
1546
+ const { connectMachineShare } = await import("./print-share-uwUG16Ov.mjs");
1547
1547
  const machineShare = await connectMachineShare({
1548
1548
  appUrl,
1549
1549
  sessionToken: session.value.sessionToken,
@@ -1928,7 +1928,7 @@ const chatCommand = {
1928
1928
  sessionToken: auth.value.token,
1929
1929
  agentSelector: argv.agent ?? null
1930
1930
  });
1931
- const { runChat } = await import("./boot-BVVbrf2k.mjs");
1931
+ const { runChat } = await import("./boot-Brwh0it_.mjs");
1932
1932
  await runChat({
1933
1933
  appUrl: auth.value.appUrl,
1934
1934
  sessionToken: auth.value.token,
@@ -2020,7 +2020,7 @@ async function runPrintMode({ argv, appUrl }) {
2020
2020
  process.exit(1);
2021
2021
  }
2022
2022
  } else {
2023
- const { connectMachineShare } = await import("./print-share-C1LPsgTP.mjs");
2023
+ const { connectMachineShare } = await import("./print-share-uwUG16Ov.mjs");
2024
2024
  machineShare = await connectMachineShare({
2025
2025
  appUrl: auth.value.appUrl,
2026
2026
  sessionToken: auth.value.token,
@@ -2287,7 +2287,7 @@ const switchCommand = {
2287
2287
  printError("The workspace picker needs the Bun runtime and it could not be set up automatically. Pass a workspace slug instead, or install Bun and retry.");
2288
2288
  process.exit(1);
2289
2289
  }
2290
- const { runWorkspacePicker } = await import("./boot-BVVbrf2k.mjs");
2290
+ const { runWorkspacePicker } = await import("./boot-Brwh0it_.mjs");
2291
2291
  await runWorkspacePicker(session);
2292
2292
  return;
2293
2293
  }
@@ -2366,7 +2366,7 @@ const openCommand = {
2366
2366
  const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
2367
2367
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
2368
2368
  const { machineName } = await resolveMachineIdentity();
2369
- const { PortalDaemonClient } = await import("./daemon-client-srAit8Fz.mjs");
2369
+ const { PortalDaemonClient } = await import("./daemon-client-D8bNXTxu.mjs");
2370
2370
  let lastLine = "";
2371
2371
  let signalConnected;
2372
2372
  const connected = new Promise((resolve) => {
@@ -4169,7 +4169,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
4169
4169
  process.exit(0);
4170
4170
  }
4171
4171
  if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
4172
- const { runPortalDaemon } = await import("./daemon-DDBIumf1.mjs");
4172
+ const { runPortalDaemon } = await import("./daemon-CjzrUvXx.mjs");
4173
4173
  runPortalDaemon(process.argv);
4174
4174
  } else runCli();
4175
4175
  function runCli() {
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-DtuXkIkR.mjs";
2
+ import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-LLaIFZgn.mjs";
3
3
  import { B as saveTheme, D as getSavedTheme, E as getReviewStateDir, L as resolveWebUrl, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL } from "./print-CbayCa87.mjs";
4
4
  import { t as HttpError } from "./http-error-DzyrsLAZ.mjs";
5
5
  import { a as isRecord, i as errorMessage, n as errorDetail, r as sendErrorMessage, t as createRestClient } from "./rest-BY2nADw5.mjs";
6
6
  import { i as billingBlockedOutcomeFromSendResponse } from "./billing-blocked-2wju4gC_.mjs";
7
7
  import { t as PortalClient } from "./client-Dd5sMXPv.mjs";
8
- import "./daemon-Bq93vOIk.mjs";
8
+ import "./daemon-BhArnzeW.mjs";
9
9
  import { t as SandboxStream } from "./client-Cn2af31H.mjs";
10
- import { t as PortalDaemonClient } from "./daemon-client-Bewt98dE.mjs";
10
+ import { t as PortalDaemonClient } from "./daemon-client-DcuD4v12.mjs";
11
11
  import { t as runRawPtyPassthrough } from "./raw-pty-B6mAroiI.mjs";
12
12
  import * as os$1 from "node:os";
13
13
  import { homedir, platform, release, tmpdir } from "node:os";
@@ -4529,20 +4529,23 @@ function RenderItem({ item }) {
4529
4529
  children: [item.text ? /* @__PURE__ */ jsx("text", {
4530
4530
  fg: theme.user,
4531
4531
  children: item.text
4532
- }) : null, item.attachments && item.attachments.length > 0 ? /* @__PURE__ */ jsxs("text", {
4532
+ }) : null, item.attachments.length > 0 ? /* @__PURE__ */ jsxs("text", {
4533
4533
  fg: theme.muted,
4534
4534
  children: ["⎘ ", item.attachments.join(" · ")]
4535
4535
  }) : null]
4536
4536
  });
4537
- case "pending-steer": return /* @__PURE__ */ jsx(Row, {
4537
+ case "pending-steer": return /* @__PURE__ */ jsxs(Row, {
4538
4538
  barColor: theme.dim,
4539
- children: /* @__PURE__ */ jsxs("text", {
4539
+ children: [/* @__PURE__ */ jsxs("text", {
4540
4540
  fg: theme.muted,
4541
4541
  children: [item.text, /* @__PURE__ */ jsx("span", {
4542
4542
  fg: theme.dim,
4543
4543
  children: " · steering… (esc to cancel)"
4544
4544
  })]
4545
- })
4545
+ }), item.attachments.length > 0 ? /* @__PURE__ */ jsxs("text", {
4546
+ fg: theme.dim,
4547
+ children: ["⎘ ", item.attachments.join(" · ")]
4548
+ }) : null]
4546
4549
  });
4547
4550
  case "assistant-text":
4548
4551
  if (item.done) return /* @__PURE__ */ jsx(Row, {
@@ -5277,7 +5280,8 @@ function applyChunk(items, chunk, agentName = null) {
5277
5280
  return items.map((m) => m.kind === "pending-steer" && ids.has(m.id) ? {
5278
5281
  kind: "user",
5279
5282
  id: m.id,
5280
- text: m.text
5283
+ text: m.text,
5284
+ attachments: m.attachments
5281
5285
  } : m);
5282
5286
  }
5283
5287
  case "data-anyone-render-spec": {
@@ -5518,7 +5522,7 @@ function uiMessagesToItems(messages) {
5518
5522
  kind: "user",
5519
5523
  id: m.id,
5520
5524
  text,
5521
- ...attachments.length > 0 ? { attachments } : {}
5525
+ attachments
5522
5526
  });
5523
5527
  continue;
5524
5528
  }
@@ -10436,7 +10440,8 @@ function ChatScreen({ agent, conversation }) {
10436
10440
  setItems((prev) => prev.map((m) => m.kind === "pending-steer" ? {
10437
10441
  kind: "user",
10438
10442
  id: m.id,
10439
- text: m.text
10443
+ text: m.text,
10444
+ attachments: m.attachments
10440
10445
  } : m));
10441
10446
  setRun({ kind: "idle" });
10442
10447
  agentHost.transition({
@@ -10513,7 +10518,7 @@ function ChatScreen({ agent, conversation }) {
10513
10518
  kind: "user",
10514
10519
  id: optimisticId,
10515
10520
  text: trimmed,
10516
- ...stagedNames.length > 0 ? { attachments: stagedNames } : {}
10521
+ attachments: stagedNames
10517
10522
  }]);
10518
10523
  const wasStreaming = runRef.current.kind === "streaming";
10519
10524
  if (!wasStreaming) setRun({
@@ -10562,7 +10567,8 @@ function ChatScreen({ agent, conversation }) {
10562
10567
  if (directiveId) setItems((prev) => prev.map((m) => m.id === optimisticId ? {
10563
10568
  kind: "pending-steer",
10564
10569
  id: directiveId,
10565
- text: trimmed
10570
+ text: trimmed,
10571
+ attachments: m.kind === "user" || m.kind === "pending-steer" ? m.attachments : []
10566
10572
  } : m));
10567
10573
  const current = runRef.current;
10568
10574
  if (!(current.kind === "streaming" && current.runId === result.runId)) attachToRun(result.runId, result.agentName ?? null);
@@ -11066,7 +11072,8 @@ function ChatScreen({ agent, conversation }) {
11066
11072
  setItems((prev) => prev.map((m) => m.kind === "pending-steer" ? {
11067
11073
  kind: "user",
11068
11074
  id: m.id,
11069
- text: m.text
11075
+ text: m.text,
11076
+ attachments: m.attachments
11070
11077
  } : m));
11071
11078
  useStore.getState().showToast({ message: "run cancelled" });
11072
11079
  }, [rest]);
@@ -8,6 +8,43 @@ import { createHash } from "node:crypto";
8
8
  import { connect, createServer } from "node:net";
9
9
  import { access, appendFile, mkdir, readFile, unlink, writeFile } from "node:fs/promises";
10
10
 
11
+ //#region ../portal-daemon/src/build-stamp.ts
12
+ /**
13
+ * This build's stamp: the unix commit time (seconds) of the source it was
14
+ * compiled from. Empty string when unstamped (a dev source run without the
15
+ * env override).
16
+ *
17
+ * Why a commit time and not a package version: the daemon ships inside two
18
+ * independently-versioned installers (the skydive CLI and the desktop app),
19
+ * so their semvers are not comparable — but both build from this repo, so
20
+ * the commit time of the built tree is one monotonic clock they share.
21
+ */
22
+ function portalDaemonBuild() {
23
+ return "1786586981";
24
+ }
25
+ /**
26
+ * Whether a client carrying `mine` should replace a running daemon carrying
27
+ * `theirs` (newest build wins):
28
+ *
29
+ * - an unstamped client never takes over — it can't prove it's newer;
30
+ * - a stamped client replaces an unstamped daemon — every stamped build
31
+ * postdates stamping, so the unstamped daemon is older by construction;
32
+ * - otherwise strictly greater wins; equal keeps the incumbent, so two
33
+ * identical builds never bounce the daemon between them.
34
+ */
35
+ function isNewerBuild(mine, theirs) {
36
+ const mineAt = parseStamp(mine);
37
+ if (mineAt === null) return false;
38
+ const theirsAt = parseStamp(theirs);
39
+ if (theirsAt === null) return true;
40
+ return mineAt > theirsAt;
41
+ }
42
+ function parseStamp(stamp) {
43
+ if (!/^[0-9]+$/.test(stamp)) return null;
44
+ return Number(stamp);
45
+ }
46
+
47
+ //#endregion
11
48
  //#region ../portal-daemon/src/local-protocol.ts
12
49
  /**
13
50
  * Local IPC between the portal DAEMON and the `skydive` CLI processes attached
@@ -220,6 +257,7 @@ const daemonStatusResultSchema = z.object({
220
257
  v: z.number(),
221
258
  pid: z.number(),
222
259
  appUrl: z.string(),
260
+ build: z.string().default(""),
223
261
  portal: z.object({
224
262
  status: z.enum([
225
263
  "off",
@@ -516,6 +554,7 @@ var PortalDaemon = class {
516
554
  v: LOCAL_PROTOCOL_VERSION,
517
555
  pid: process.pid,
518
556
  appUrl: this.appUrl,
557
+ build: portalDaemonBuild(),
519
558
  portal: {
520
559
  status: portal?.status ?? "off",
521
560
  machineName: portal?.machineName ?? "",
@@ -573,10 +612,23 @@ var PortalDaemon = class {
573
612
  * before dispatching a normal command — the same pattern the update-check
574
613
  * worker uses, so it survives bundling (import.meta.url points at the bundle,
575
614
  * not a standalone daemon module).
615
+ *
616
+ * Newest build wins: the daemon is embedded in two independently-updated
617
+ * installers (the skydive CLI and the desktop app), and whoever spawned first
618
+ * would otherwise hold the socket forever — a stale desktop daemon serving a
619
+ * newer CLI indefinitely. So when a daemon is already listening, compare its
620
+ * build stamp to ours: if ours is strictly newer, ask it to shut down (it
621
+ * drains attached clients, who reconnect within ~500ms) and spawn from this
622
+ * binary. Both spawners apply the same rule, so a host converges on the
623
+ * newest installed build with at most one bounce.
576
624
  */
577
625
  async function ensureDaemonRunning(appUrl) {
578
626
  const { socketPath } = daemonPaths(appUrl);
579
- if (await isDaemonListening(socketPath)) return;
627
+ if (await isDaemonListening(socketPath)) {
628
+ const status = await queryDaemonStatus(appUrl);
629
+ if (!status || !isNewerBuild(portalDaemonBuild(), status.build)) return;
630
+ if (await stopDaemon(appUrl) === "failed") return;
631
+ }
580
632
  const entry = process.argv[1];
581
633
  const args = entry ? [
582
634
  entry,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import "./client-Dd5sMXPv.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-Bq93vOIk.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-BhArnzeW.mjs";
4
4
 
5
5
  export { runPortalDaemon };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import "./client-Dd5sMXPv.mjs";
3
+ import "./daemon-BhArnzeW.mjs";
4
+ import { t as PortalDaemonClient } from "./daemon-client-DcuD4v12.mjs";
5
+
6
+ export { PortalDaemonClient };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { c as LOCAL_PROTOCOL_VERSION, d as encodeLine, f as makeLineParser, n as ensureDaemonRunning, p as parseDaemonMessage, u as daemonPaths } from "./daemon-Bq93vOIk.mjs";
2
+ import { c as LOCAL_PROTOCOL_VERSION, d as encodeLine, f as makeLineParser, n as ensureDaemonRunning, p as parseDaemonMessage, u as daemonPaths } from "./daemon-BhArnzeW.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { connect } from "node:net";
5
5
 
@@ -14,7 +14,7 @@ import { n as printError } from "./output-DYzzdXYV.mjs";
14
14
  * the reply (and to --json).
15
15
  */
16
16
  async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
17
- const { PortalClient } = await import("./client-CKBQ8pft.mjs");
17
+ const { PortalClient } = await import("./client-DZstLQ_1.mjs");
18
18
  let signalConnected;
19
19
  const connected = new Promise((resolve) => {
20
20
  signalConnected = resolve;
@@ -8,7 +8,7 @@ import fs from "node:fs";
8
8
 
9
9
  //#region package.json
10
10
  var name = "skydive-cli";
11
- var version$1 = "0.5.0-beta.3";
11
+ var version$1 = "0.5.0-beta.5";
12
12
 
13
13
  //#endregion
14
14
  //#region src/auth/organization.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.5.0-beta.3",
3
+ "version": "0.5.0-beta.5",
4
4
  "description": "Skydive CLI — cloud agents from the command line",
5
5
  "homepage": "https://skydive.com",
6
6
  "license": "MIT",
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./client-Dd5sMXPv.mjs";
3
- import "./daemon-Bq93vOIk.mjs";
4
- import { t as PortalDaemonClient } from "./daemon-client-Bewt98dE.mjs";
5
-
6
- export { PortalDaemonClient };