skydive-cli 0.2.0-beta.426 → 0.2.0-beta.455

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as HttpError } from "./rest-04eiQEA9.mjs";
2
+ import { t as HttpError } from "./rest-BBQrPIwq.mjs";
3
3
  import os from "node:os";
4
4
  import { z } from "zod";
5
5
 
package/dist/js/bin.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { A as getShareMachineDefault, B as saveSession, C as DEFAULT_WEB_URL, D as getPromptHistoryPath, E as getLastSeenVersion, F as resolveConfig, H as setLastSeenVersion, I as resolveManagementAuth, L as resolveSession, M as getStoredApiKeyWorkspaceName, N as getUpdateCheckDisabled, P as resolveAppUrl, T as getConfigPath, _ as setActiveWorkspace, b as API_KEY_PREFIX, d as themes, g as listWorkspaces, h as getSessionIdentity, j as getStoredApiKeyId, m as getActiveWorkspaceId, p as ensureActiveOrganization, v as API_KEYS_URL, w as deleteConfig, x as DEFAULT_API_URL, y as API_KEY_FAMILY_PREFIX, z as saveConfig } from "./theme-CuQhvqzN.mjs";
3
3
  import { n as printError, r as printTable, t as output } from "./output-B4cW10Ph.mjs";
4
- import { n as createRestClient } from "./rest-04eiQEA9.mjs";
5
- import { i as resolveAgent } from "./print-CouegX9S.mjs";
6
- import { a as registerPortalDevice, c as machineIdentity, n as findThisDevice, o as revokePortalAccess, r as grantPortalAccess, t as fetchPortalDevices } from "./api-DcGNxnLr.mjs";
4
+ import { n as createRestClient } from "./rest-BBQrPIwq.mjs";
5
+ import { i as resolveAgent } from "./print-YqNIRwdf.mjs";
6
+ import { a as registerPortalDevice, c as machineIdentity, n as findThisDevice, o as revokePortalAccess, r as grantPortalAccess, t as fetchPortalDevices } from "./api-zUf_Vrzh.mjs";
7
7
  import { t as SandboxStream } from "./client-CpEvH2Pq.mjs";
8
8
  import { hideBin } from "yargs/helpers";
9
9
  import yargs from "yargs";
@@ -20,7 +20,7 @@ import semver from "semver";
20
20
 
21
21
  //#region package.json
22
22
  var name = "skydive-cli";
23
- var version = "0.2.0-beta.426";
23
+ var version = "0.2.0-beta.455";
24
24
 
25
25
  //#endregion
26
26
  //#region src/types.ts
@@ -1200,7 +1200,7 @@ const importCommand = {
1200
1200
  process.exit(1);
1201
1201
  }
1202
1202
  }
1203
- const { runChat } = await import("./boot-BJeHUB6U.mjs");
1203
+ const { runChat } = await import("./boot-SxcKHfwY.mjs");
1204
1204
  await runChat({
1205
1205
  appUrl,
1206
1206
  sessionToken: session.value.sessionToken,
@@ -1226,7 +1226,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1226
1226
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
1227
1227
  process.exit(1);
1228
1228
  }
1229
- const { connectMachineShare } = await import("./print-share-BS60u1H2.mjs");
1229
+ const { connectMachineShare } = await import("./print-share-B8sZ0w-M.mjs");
1230
1230
  const machineShare = await connectMachineShare({
1231
1231
  appUrl,
1232
1232
  sessionToken: session.value.sessionToken,
@@ -1234,7 +1234,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1234
1234
  });
1235
1235
  const extra = (argv.print ?? "").trim();
1236
1236
  const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
1237
- const { runPrint } = await import("./print-CKEKn9wS.mjs");
1237
+ const { runPrint } = await import("./print-DUsH9Dlh.mjs");
1238
1238
  try {
1239
1239
  const result = await runPrint({
1240
1240
  appUrl,
@@ -1511,7 +1511,7 @@ const chatCommand = {
1511
1511
  printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
1512
1512
  process.exit(1);
1513
1513
  }
1514
- const { runChat } = await import("./boot-BJeHUB6U.mjs");
1514
+ const { runChat } = await import("./boot-SxcKHfwY.mjs");
1515
1515
  await runChat({
1516
1516
  appUrl,
1517
1517
  sessionToken: session.value.sessionToken,
@@ -1539,7 +1539,7 @@ async function runPrintMode({ argv, appUrl }) {
1539
1539
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
1540
1540
  process.exit(1);
1541
1541
  }
1542
- const { runPrint, readStdin } = await import("./print-CKEKn9wS.mjs");
1542
+ const { runPrint, readStdin } = await import("./print-DUsH9Dlh.mjs");
1543
1543
  let prompt = (argv.print ?? "").trim();
1544
1544
  if (!prompt) {
1545
1545
  if (process.stdin.isTTY) {
@@ -1554,7 +1554,7 @@ async function runPrintMode({ argv, appUrl }) {
1554
1554
  }
1555
1555
  let machineShare = null;
1556
1556
  if (resolveShareMachine(argv)) {
1557
- const { connectMachineShare } = await import("./print-share-BS60u1H2.mjs");
1557
+ const { connectMachineShare } = await import("./print-share-B8sZ0w-M.mjs");
1558
1558
  machineShare = await connectMachineShare({
1559
1559
  appUrl,
1560
1560
  sessionToken: session.value.sessionToken,
@@ -1613,7 +1613,7 @@ const getCommand = {
1613
1613
  printError(`${session.error.message} Run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
1614
1614
  process.exit(1);
1615
1615
  }
1616
- const { messageGet } = await import("./print-CKEKn9wS.mjs");
1616
+ const { messageGet } = await import("./print-DUsH9Dlh.mjs");
1617
1617
  try {
1618
1618
  const result = await messageGet({
1619
1619
  appUrl,
@@ -1810,7 +1810,7 @@ const switchCommand = {
1810
1810
  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.");
1811
1811
  process.exit(1);
1812
1812
  }
1813
- const { runWorkspacePicker } = await import("./boot-BJeHUB6U.mjs");
1813
+ const { runWorkspacePicker } = await import("./boot-SxcKHfwY.mjs");
1814
1814
  await runWorkspacePicker(session);
1815
1815
  return;
1816
1816
  }
@@ -1888,7 +1888,7 @@ const openCommand = {
1888
1888
  const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
1889
1889
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
1890
1890
  const { machineName } = machineIdentity();
1891
- const { PortalClient } = await import("./client-Blf9mdM0.mjs");
1891
+ const { PortalClient } = await import("./client-A4m7lNDg.mjs");
1892
1892
  let lastLine = "";
1893
1893
  let signalConnected;
1894
1894
  const connected = new Promise((resolve) => {
@@ -2060,8 +2060,8 @@ const sandboxCommand = {
2060
2060
  }).example("skydive sandbox --agent grace", "Live terminal (Ctrl-] detaches)").example("skydive sandbox --agent grace -- tail -n 50 /tmp/harness.log", "One-shot command (use `--` so its flags reach the sandbox)").example("skydive sandbox --agent grace -- sh -c 'ls /tmp | wc -l'", "Shell features go through an explicit `sh -c`"),
2061
2061
  handler: async (argv) => {
2062
2062
  const session = requireSession(argv);
2063
- const { createRestClient } = await import("./rest-CHW9mvHI.mjs");
2064
- const { resolveAgent } = await import("./print-CKEKn9wS.mjs");
2063
+ const { createRestClient } = await import("./rest-Cz0VLhmi.mjs");
2064
+ const { resolveAgent } = await import("./print-DUsH9Dlh.mjs");
2065
2065
  const client = createRestClient({
2066
2066
  appUrl: session.appUrl,
2067
2067
  sessionToken: session.sessionToken
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import { O as getReviewStateDir, R as resolveWebUrl, S as DEFAULT_APP_URL, T as getConfigPath, V as saveTheme, _ as setActiveWorkspace, a as noColorRequested, c as themeMode, f as themesForMode, g as listWorkspaces, i as monoTheme, k as getSavedTheme, l as themeModeFromColorFgBg, m as getActiveWorkspaceId, n as applyTheme, o as theme, r as findTheme, s as themeForMode, t as DEFAULT_THEME_ID, u as themeVersion, x as DEFAULT_API_URL } from "./theme-CuQhvqzN.mjs";
3
- import { n as createRestClient, r as errorDetail, t as HttpError } from "./rest-04eiQEA9.mjs";
3
+ import { n as createRestClient, r as errorDetail, t as HttpError } from "./rest-BBQrPIwq.mjs";
4
4
  import { n as isRecord, t as errorMessage } from "./util-CeisaZVY.mjs";
5
- import { 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 } from "./print-CouegX9S.mjs";
6
- import "./api-DcGNxnLr.mjs";
5
+ import { 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 } from "./print-YqNIRwdf.mjs";
6
+ import "./api-zUf_Vrzh.mjs";
7
7
  import { t as SandboxStream } from "./client-CpEvH2Pq.mjs";
8
- import { t as PortalClient } from "./client-CxOKgU7M.mjs";
8
+ import { t as PortalClient } from "./client-DuPxkSoH.mjs";
9
9
  import { t as runRawPtyPassthrough } from "./raw-pty-GAvxm2ol.mjs";
10
10
  import * as os$1 from "node:os";
11
11
  import { homedir, platform, release, tmpdir } from "node:os";
@@ -4357,6 +4357,10 @@ const keybindGroups = [
4357
4357
  keys: "1 / 2",
4358
4358
  action: "switch Changes / Files"
4359
4359
  },
4360
+ {
4361
+ keys: "\\",
4362
+ action: "toggle side / stacked layout"
4363
+ },
4360
4364
  {
4361
4365
  keys: "↵ / o / l",
4362
4366
  action: "focus selected file preview"
@@ -6747,7 +6751,7 @@ function gcOnce() {
6747
6751
  gcStarted = true;
6748
6752
  store.gc();
6749
6753
  }
6750
- function ReviewPane({ agentId, conversationId, items, viewportWidth, viewportHeight, active, shellLayout, tab, onTabChange, selectedChangeFile, onSelectedChangeFileChange, selectedWorkspaceFile, onSelectedWorkspaceFileChange, navigatorSize, onNavigatorResize, onInsertToComposer, onRequestChatFocus, onClose }) {
6754
+ function ReviewPane({ agentId, conversationId, items, viewportWidth, viewportHeight, active, shellLayout, tab, onTabChange, selectedChangeFile, onSelectedChangeFileChange, selectedWorkspaceFile, onSelectedWorkspaceFileChange, navigatorSize, onNavigatorResize, onToggleOrientation, onInsertToComposer, onRequestChatFocus, onClose }) {
6751
6755
  const width = viewportWidth;
6752
6756
  const height = viewportHeight;
6753
6757
  const shellHeight = Math.max(6, height - 2);
@@ -6898,6 +6902,10 @@ function ReviewPane({ agentId, conversationId, items, viewportWidth, viewportHei
6898
6902
  onTabChange("files");
6899
6903
  return;
6900
6904
  }
6905
+ if (key.name === "\\") {
6906
+ if (onToggleOrientation() === "unavailable") setStatus("no room to change layout in this terminal");
6907
+ return;
6908
+ }
6901
6909
  if (key.name === "s") {
6902
6910
  if (comments.length === 0) {
6903
6911
  setStatus("no pending comments");
@@ -7288,18 +7296,93 @@ function PaneRowView({ row, width, isCursor, inSelection, isAnchor, isCommented
7288
7296
  //#endregion
7289
7297
  //#region src/chat/tui/file-pane-layout.ts
7290
7298
  /**
7299
+ * Terminal cells are about twice as tall as they are wide, so a raw
7300
+ * cols-vs-rows compare would call almost any terminal "wide". Scale rows by
7301
+ * this factor to compare the *visual* aspect: a square-looking terminal has
7302
+ * `width ≈ height * CELL_ASPECT`.
7303
+ */
7304
+ const CELL_ASPECT = 2;
7305
+ /**
7306
+ * The automatic split follows the terminal's visual aspect: wider than tall
7307
+ * places review beside the chat (a vertical divider), taller than wide stacks
7308
+ * it underneath (a horizontal divider). This is the responsive default when
7309
+ * the user hasn't pinned an orientation.
7310
+ */
7311
+ function autoPrefersSide({ width, height }) {
7312
+ return width >= height * CELL_ASPECT;
7313
+ }
7314
+ /**
7315
+ * Bare-minimum room to render a split at all (as opposed to the higher
7316
+ * comfort thresholds the automatic choice uses). A user pin is honored down
7317
+ * to these: chat + review each need a usable strip, but we don't insist on
7318
+ * the roomier auto breakpoints. Mirrors the clamps in clampSidePaneWidth /
7319
+ * clampBelowPaneHeight so a pinned split never renders narrower than those.
7320
+ */
7321
+ function canRenderSide({ width, height }) {
7322
+ return width >= 76 && height >= 8;
7323
+ }
7324
+ function canRenderBelow({ width, height }) {
7325
+ return height >= 24 && width >= 24;
7326
+ }
7327
+ /**
7291
7328
  * Responsive placement for the file pane.
7292
7329
  *
7293
- * Wide terminals keep the conversation readable and place review beside it.
7294
- * Tall terminals without enough horizontal room stack review underneath.
7295
- * Cramped terminals give review the full body rather than rendering two
7296
- * unusably small surfaces.
7330
+ * With no user pin the split follows the terminal's visual aspect (see
7331
+ * autoPrefersSide): wider than tall -> side, taller than wide -> stacked.
7332
+ * The preferred split still has to be renderable; if it isn't we use the
7333
+ * other, and cramped terminals that can render neither get the full body.
7334
+ *
7335
+ * A user `orientation` pin always wins as long as the terminal can render
7336
+ * that split at all (the lower canRender* bar) — so you get the layout you
7337
+ * asked for even on a smallish terminal. Only when the pinned split
7338
+ * genuinely can't fit do we fall back: to the other split if it can render,
7339
+ * else to `fullscreen`.
7297
7340
  */
7298
- function filePanePlacement({ width, height }) {
7299
- if (width >= 140 && height >= 24) return "side";
7300
- if (width >= 50 && height >= 40) return "below";
7341
+ function filePanePlacement({ width, height, orientation }) {
7342
+ const renderSide = canRenderSide({
7343
+ width,
7344
+ height
7345
+ });
7346
+ const renderBelow = canRenderBelow({
7347
+ width,
7348
+ height
7349
+ });
7350
+ if (orientation === "side") {
7351
+ if (renderSide) return "side";
7352
+ if (renderBelow) return "below";
7353
+ return "fullscreen";
7354
+ }
7355
+ if (orientation === "below") {
7356
+ if (renderBelow) return "below";
7357
+ if (renderSide) return "side";
7358
+ return "fullscreen";
7359
+ }
7360
+ if (autoPrefersSide({
7361
+ width,
7362
+ height
7363
+ })) {
7364
+ if (renderSide) return "side";
7365
+ if (renderBelow) return "below";
7366
+ return "fullscreen";
7367
+ }
7368
+ if (renderBelow) return "below";
7369
+ if (renderSide) return "side";
7301
7370
  return "fullscreen";
7302
7371
  }
7372
+ /**
7373
+ * Whether toggling the orientation would actually change anything: both
7374
+ * splits must be renderable. When only one (or neither) can render, the
7375
+ * caller surfaces a hint instead of a silent no-op.
7376
+ */
7377
+ function canToggleOrientation({ width, height }) {
7378
+ return canRenderSide({
7379
+ width,
7380
+ height
7381
+ }) && canRenderBelow({
7382
+ width,
7383
+ height
7384
+ });
7385
+ }
7303
7386
  /** Keep a dragged side pane wide enough to use and leave the chat usable. */
7304
7387
  function clampSidePaneWidth(width, bodyWidth) {
7305
7388
  return Math.max(44, Math.min(bodyWidth - 30, width));
@@ -7753,6 +7836,15 @@ const maxAttachments = 10;
7753
7836
  function isNewConversation(c) {
7754
7837
  return "kind" in c && c.kind === "new";
7755
7838
  }
7839
+ /**
7840
+ * A server timestamp as local epoch ms, or null when it is missing or
7841
+ * unparseable so the caller can fall back to its own clock.
7842
+ */
7843
+ function parseStampMs(iso) {
7844
+ if (!iso) return null;
7845
+ const ms = Date.parse(iso);
7846
+ return Number.isNaN(ms) ? null : ms;
7847
+ }
7756
7848
  function formatBytes(bytes) {
7757
7849
  if (bytes < 1024) return `${bytes} B`;
7758
7850
  if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;
@@ -7818,6 +7910,7 @@ function ChatScreen({ agent, conversation }) {
7818
7910
  side: null,
7819
7911
  stacked: null
7820
7912
  });
7913
+ const [reviewOrientation, setReviewOrientation] = useState(null);
7821
7914
  const [reviewWorkspaceFile, setReviewWorkspaceFile] = useState(null);
7822
7915
  useEffect(() => {
7823
7916
  setReviewChangeFile(null);
@@ -7873,7 +7966,8 @@ function ChatScreen({ agent, conversation }) {
7873
7966
  const bodyHeight = Math.max(1, height - 3);
7874
7967
  const reviewPlacement = filePanePlacement({
7875
7968
  width,
7876
- height
7969
+ height,
7970
+ orientation: reviewOrientation
7877
7971
  });
7878
7972
  const reviewWidth = reviewPlacement === "side" ? clampSidePaneWidth(reviewSizePref.side ?? sidePaneWidth(bodyWidth), bodyWidth) : bodyWidth;
7879
7973
  const reviewHeight = reviewPlacement === "below" ? clampBelowPaneHeight(reviewSizePref.below ?? belowPaneHeight(bodyHeight), bodyHeight) : bodyHeight;
@@ -7916,6 +8010,7 @@ function ChatScreen({ agent, conversation }) {
7916
8010
  helpOpen,
7917
8011
  reviewOpen,
7918
8012
  reviewFocused,
8013
+ reviewPlacement,
7919
8014
  credPromptOpen
7920
8015
  ]);
7921
8016
  useEffect(() => {
@@ -7948,17 +8043,18 @@ function ChatScreen({ agent, conversation }) {
7948
8043
  cancelled = true;
7949
8044
  };
7950
8045
  }, [rest, initialConversationId]);
7951
- const attachToRun = useCallback((runId, runAgentName) => {
8046
+ const attachToRun = useCallback((runId, runAgentName, runStartedAtMs) => {
7952
8047
  if (!rest) return;
7953
8048
  seenRunsRef.current.add(runId);
7954
8049
  const abort = new AbortController();
7955
8050
  const responsePreview = createResponsePreview();
7956
8051
  const streamAgentName = runAgentName ?? agent.name;
7957
- setRun({
8052
+ setRun((prev) => ({
7958
8053
  kind: "streaming",
7959
8054
  runId,
7960
- abort
7961
- });
8055
+ abort,
8056
+ startedAtMs: runStartedAtMs ?? (prev.kind === "idle" ? Date.now() : prev.startedAtMs)
8057
+ }));
7962
8058
  rest.streamRun({
7963
8059
  runId,
7964
8060
  signal: abort.signal,
@@ -8019,7 +8115,7 @@ function ChatScreen({ agent, conversation }) {
8019
8115
  if (event.kind === "run") {
8020
8116
  if (seenRunsRef.current.has(event.runId)) return;
8021
8117
  if (runRef.current.kind !== "idle") return;
8022
- attachToRun(event.runId);
8118
+ attachToRun(event.runId, null, parseStampMs(event.createdAt));
8023
8119
  return;
8024
8120
  }
8025
8121
  if (event.title) setChatTitle(event.title);
@@ -8046,7 +8142,10 @@ function ChatScreen({ agent, conversation }) {
8046
8142
  ...stagedNames.length > 0 ? { attachments: stagedNames } : {}
8047
8143
  }]);
8048
8144
  const wasStreaming = runRef.current.kind === "streaming";
8049
- if (!wasStreaming) setRun({ kind: "sending" });
8145
+ if (!wasStreaming) setRun({
8146
+ kind: "sending",
8147
+ startedAtMs: Date.now()
8148
+ });
8050
8149
  try {
8051
8150
  const attachmentIds = [];
8052
8151
  const restorable = [];
@@ -9006,6 +9105,14 @@ function ChatScreen({ agent, conversation }) {
9006
9105
  ...prev,
9007
9106
  side: size
9008
9107
  }),
9108
+ onToggleOrientation: () => {
9109
+ if (!canToggleOrientation({
9110
+ width,
9111
+ height
9112
+ })) return "unavailable";
9113
+ setReviewOrientation(reviewPlacement === "below" ? "side" : "below");
9114
+ return "toggled";
9115
+ },
9009
9116
  onInsertToComposer: (review) => {
9010
9117
  const next = [inputRef.current.trimEnd(), review].filter((part) => part.length > 0).join("\n\n");
9011
9118
  setInput(next);
@@ -9105,7 +9212,10 @@ function ChatScreen({ agent, conversation }) {
9105
9212
  })
9106
9213
  }) : null, /* @__PURE__ */ jsx(RenderItem, { item })]
9107
9214
  }, item.id);
9108
- }) }), run.kind !== "idle" ? /* @__PURE__ */ jsx(ActivityRow, { label: run.kind === "sending" ? "sending" : "working" }) : null]
9215
+ }) }), run.kind !== "idle" ? /* @__PURE__ */ jsx(ActivityRow, {
9216
+ label: run.kind === "sending" ? "sending" : "working",
9217
+ startedAtMs: run.startedAtMs
9218
+ }) : null]
9109
9219
  })
9110
9220
  }),
9111
9221
  todoCardVisible && todos ? /* @__PURE__ */ jsx(TodoCardView, {
@@ -9350,16 +9460,18 @@ function CredentialPromptBox({ prompt, height, onInput, onSubmit }) {
9350
9460
  /**
9351
9461
  * A live indicator at the foot of the transcript while a run is in flight: an
9352
9462
  * animated spinner plus a label and a seconds counter, so it's obvious the
9353
- * agent is still working even during long gaps between chunks. Owns its own
9354
- * elapsed-time timer so ticking the counter doesn't re-render the transcript.
9463
+ * agent is still working even during long gaps between chunks. The counter
9464
+ * measures from the run's own start, not from this row appearing, so reopening
9465
+ * a conversation mid-run shows how long the agent has really been at it. Owns
9466
+ * its own clock so ticking it doesn't re-render the transcript.
9355
9467
  */
9356
- function ActivityRow({ label }) {
9357
- const [elapsed, setElapsed] = useState(0);
9468
+ function ActivityRow({ label, startedAtMs }) {
9469
+ const [now, setNow] = useState(() => Date.now());
9358
9470
  useEffect(() => {
9359
- const start = Date.now();
9360
- const id = setInterval(() => setElapsed(Math.floor((Date.now() - start) / 1e3)), 250);
9471
+ const id = setInterval(() => setNow(Date.now()), 250);
9361
9472
  return () => clearInterval(id);
9362
9473
  }, []);
9474
+ const elapsed = Math.floor((now - startedAtMs) / 1e3);
9363
9475
  return /* @__PURE__ */ jsxs("box", {
9364
9476
  style: {
9365
9477
  flexDirection: "row",
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import "./rest-BBQrPIwq.mjs";
3
+ import "./api-zUf_Vrzh.mjs";
4
+ import { t as PortalClient } from "./client-DuPxkSoH.mjs";
5
+
6
+ export { PortalClient };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as errorMessage } from "./util-CeisaZVY.mjs";
3
- import { c as machineIdentity, i as mintPortalDeviceToken, l as portalWsUrl, n as findThisDevice, r as grantPortalAccess, s as buildEnv, t as fetchPortalDevices } from "./api-DcGNxnLr.mjs";
3
+ import { c as machineIdentity, i as mintPortalDeviceToken, l as portalWsUrl, n as findThisDevice, r as grantPortalAccess, s as buildEnv, t as fetchPortalDevices } from "./api-zUf_Vrzh.mjs";
4
4
  import { z } from "zod";
5
5
  import { spawn } from "node:child_process";
6
6
  import { WebSocket } from "ws";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./rest-04eiQEA9.mjs";
3
- import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-CouegX9S.mjs";
2
+ import "./rest-BBQrPIwq.mjs";
3
+ import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-YqNIRwdf.mjs";
4
4
 
5
5
  export { messageGet, readStdin, resolveAgent, runPrint };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as createRestClient, t as HttpError } from "./rest-04eiQEA9.mjs";
2
+ import { n as createRestClient, t as HttpError } from "./rest-BBQrPIwq.mjs";
3
3
  import { n as isRecord, t as errorMessage } from "./util-CeisaZVY.mjs";
4
4
  import stableStringify from "safe-stable-stringify";
5
5
 
@@ -14,7 +14,7 @@ import { n as printError } from "./output-B4cW10Ph.mjs";
14
14
  * the reply (and to --json).
15
15
  */
16
16
  async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
17
- const { PortalClient } = await import("./client-Blf9mdM0.mjs");
17
+ const { PortalClient } = await import("./client-A4m7lNDg.mjs");
18
18
  let signalConnected;
19
19
  const connected = new Promise((resolve) => {
20
20
  signalConnected = resolve;
@@ -455,7 +455,8 @@ const conversationStreamEventSchema = z.discriminatedUnion("kind", [z.object({
455
455
  title: z.string().nullable()
456
456
  }), z.object({
457
457
  kind: z.literal("run"),
458
- runId: z.string()
458
+ runId: z.string(),
459
+ createdAt: z.string().nullish()
459
460
  })]);
460
461
 
461
462
  //#endregion
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { n as createRestClient, r as errorDetail, t as HttpError } from "./rest-04eiQEA9.mjs";
2
+ import { n as createRestClient, r as errorDetail, t as HttpError } from "./rest-BBQrPIwq.mjs";
3
3
 
4
4
  export { createRestClient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.2.0-beta.426",
3
+ "version": "0.2.0-beta.455",
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 "./rest-04eiQEA9.mjs";
3
- import "./api-DcGNxnLr.mjs";
4
- import { t as PortalClient } from "./client-CxOKgU7M.mjs";
5
-
6
- export { PortalClient };