skydive-cli 0.6.0-beta.61 → 0.6.0-beta.63

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,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { c as version, s as name, t as createRestClient } from "./rest-M2ACdTWv.mjs";
3
- import { A as getPreference, B as resolveChatAuth, C as DEFAULT_API_URL, D as getConfigPath, E as deleteConfig, F as getStoredApiKeyId, G as saveConfig, H as resolveManagementAuth, I as getStoredApiKeyWorkspaceName, J as setLastSeenVersion, K as saveSession, L as getUpdateCheckDisabled, O as getDefaultAgent, P as getShareMachineDefault, S as API_KEY_PREFIX, T as PREFERENCES, U as resolveSession$1, V as resolveConfig, b as API_KEYS_URL, i as resolveAgent$1, j as getPromptHistoryPath, k as getLastSeenVersion, x as API_KEY_FAMILY_PREFIX, z as resolveAppUrl } from "./print-D2Wr8TLu.mjs";
4
- import { A as aliasActivationHint, B as getSessionIdentity, E as themes, F as SUPPORTED_SHELLS, H as resolveWorkspaceId, I as defaultInstallEnv, L as detectShell, M as installAgentAlias, N as slugifyAliasName, O as buildImportSeedPrompt, P as takenAliasNames, R as ensureActiveOrganization, U as setActiveWorkspace, V as listWorkspaces, c as brandHelpArt, d as maybeStartProfiling, f as profileDir, j as dedupeAliasName, k as machineOsFromPlatform, t as installCrashHandler, u as getAutomaticLogsDir, z as getActiveWorkspaceId } from "./install-CTggKxXe.mjs";
2
+ import { c as version, s as name, t as createRestClient } from "./rest-CvzARHxA.mjs";
3
+ import { A as getPreference, B as resolveChatAuth, C as DEFAULT_API_URL, D as getConfigPath, E as deleteConfig, F as getStoredApiKeyId, G as saveConfig, H as resolveManagementAuth, I as getStoredApiKeyWorkspaceName, J as setLastSeenVersion, K as saveSession, L as getUpdateCheckDisabled, O as getDefaultAgent, P as getShareMachineDefault, S as API_KEY_PREFIX, T as PREFERENCES, U as resolveSession$1, V as resolveConfig, b as API_KEYS_URL, i as resolveAgent$1, j as getPromptHistoryPath, k as getLastSeenVersion, x as API_KEY_FAMILY_PREFIX, z as resolveAppUrl } from "./print-CAaspHCe.mjs";
4
+ import { A as aliasActivationHint, B as getSessionIdentity, E as themes, F as SUPPORTED_SHELLS, H as resolveWorkspaceId, I as defaultInstallEnv, L as detectShell, M as installAgentAlias, N as slugifyAliasName, O as buildImportSeedPrompt, P as takenAliasNames, R as ensureActiveOrganization, U as setActiveWorkspace, V as listWorkspaces, c as brandHelpArt, d as maybeStartProfiling, f as profileDir, j as dedupeAliasName, k as machineOsFromPlatform, t as installCrashHandler, u as getAutomaticLogsDir, z as getActiveWorkspaceId } from "./install-BuIBR9T2.mjs";
5
5
  import { n as printError, r as printTable, t as output } from "./output-C9mb3sUB.mjs";
6
6
  import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
7
7
  import "./billing-blocked-D3l5kJlX.mjs";
8
- import { s as resolveMachineIdentity } from "./client-CCmpwqiy.mjs";
8
+ import { s as resolveMachineIdentity } from "./client-CCqRgRPa.mjs";
9
9
  import "./tls-cert-Rua2oV7n.mjs";
10
10
  import { i as grantPortalAccess, n as fetchPortalDevices, o as registerPortalDevice, r as findThisDevice, s as revokePortalAccess } from "./api-BFQ4PQDA.mjs";
11
- import { d as daemonPaths, i as queryDaemonStatus, n as ensureDaemonRunning, s as stopDaemon, u as PORTAL_DAEMON_FLAG } from "./daemon-WuGKA-0c.mjs";
11
+ import { d as daemonPaths, i as queryDaemonStatus, n as ensureDaemonRunning, s as stopDaemon, u as PORTAL_DAEMON_FLAG } from "./daemon-DL2gBVMN.mjs";
12
12
  import { a as decodeFsResponse, i as FS_MAX_BLOB_BYTES, n as SANDBOX_STREAM_PATH, o as encodeFsRequest, r as streamSpecToQuery, t as SandboxStream } from "./client-CAX6sE_Y.mjs";
13
13
  import { hideBin } from "yargs/helpers";
14
14
  import yargs from "yargs";
@@ -1176,7 +1176,7 @@ async function resolveTargetAgentId(client, selector) {
1176
1176
  printError("Missing --agent <id or name>. Run `skydive agents list` for candidates.");
1177
1177
  process.exit(1);
1178
1178
  }
1179
- const { resolveAgent } = await import("./print-CWJ4mQg2.mjs");
1179
+ const { resolveAgent } = await import("./print-Bdc6WIBW.mjs");
1180
1180
  const result = await client.listAgents({
1181
1181
  scope: "org",
1182
1182
  limit: 100
@@ -1985,7 +1985,7 @@ const importCommand = {
1985
1985
  process.exit(1);
1986
1986
  }
1987
1987
  }
1988
- const { runChat } = await import("./boot-yjPVUsuA.mjs");
1988
+ const { runChat } = await import("./boot-Xuh-2x4s.mjs");
1989
1989
  await runChat({
1990
1990
  appUrl,
1991
1991
  sessionToken: session.value.sessionToken,
@@ -2015,7 +2015,7 @@ async function runImportPrintMode({ argv, appUrl }) {
2015
2015
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
2016
2016
  process.exit(1);
2017
2017
  }
2018
- const { connectMachineShare } = await import("./print-share-DI57ILtA.mjs");
2018
+ const { connectMachineShare } = await import("./print-share-Cezembox.mjs");
2019
2019
  const machineShare = await connectMachineShare({
2020
2020
  appUrl,
2021
2021
  sessionToken: session.value.sessionToken,
@@ -2023,7 +2023,7 @@ async function runImportPrintMode({ argv, appUrl }) {
2023
2023
  });
2024
2024
  const extra = (argv.print ?? "").trim();
2025
2025
  const prompt = buildImportSeedPrompt(process.cwd(), machineOsFromPlatform(process.platform)) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
2026
- const { runPrint } = await import("./print-CWJ4mQg2.mjs");
2026
+ const { runPrint } = await import("./print-Bdc6WIBW.mjs");
2027
2027
  try {
2028
2028
  const result = await runPrint({
2029
2029
  appUrl,
@@ -2446,7 +2446,7 @@ const chatCommand = {
2446
2446
  sessionToken: auth.value.token,
2447
2447
  agentSelector: argv.agent ?? null
2448
2448
  });
2449
- const { runChat } = await import("./boot-yjPVUsuA.mjs");
2449
+ const { runChat } = await import("./boot-Xuh-2x4s.mjs");
2450
2450
  await runChat({
2451
2451
  appUrl: auth.value.appUrl,
2452
2452
  sessionToken: auth.value.token,
@@ -2530,7 +2530,7 @@ async function runPrintMode({ argv, appUrl }) {
2530
2530
  printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
2531
2531
  process.exit(1);
2532
2532
  }
2533
- const { runPrint, readStdin } = await import("./print-CWJ4mQg2.mjs");
2533
+ const { runPrint, readStdin } = await import("./print-Bdc6WIBW.mjs");
2534
2534
  const workspaceId = await resolveWorkspaceFlag({
2535
2535
  appUrl,
2536
2536
  sessionToken: auth.value.token,
@@ -2560,7 +2560,7 @@ async function runPrintMode({ argv, appUrl }) {
2560
2560
  process.exit(1);
2561
2561
  }
2562
2562
  } else {
2563
- const { connectMachineShare } = await import("./print-share-DI57ILtA.mjs");
2563
+ const { connectMachineShare } = await import("./print-share-Cezembox.mjs");
2564
2564
  machineShare = await connectMachineShare({
2565
2565
  appUrl: auth.value.appUrl,
2566
2566
  sessionToken: auth.value.token,
@@ -2625,7 +2625,7 @@ const getCommand$1 = {
2625
2625
  printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
2626
2626
  process.exit(1);
2627
2627
  }
2628
- const { messageGet } = await import("./print-CWJ4mQg2.mjs");
2628
+ const { messageGet } = await import("./print-Bdc6WIBW.mjs");
2629
2629
  try {
2630
2630
  const result = await messageGet({
2631
2631
  appUrl: auth.value.appUrl,
@@ -2828,7 +2828,7 @@ const switchCommand = {
2828
2828
  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.");
2829
2829
  process.exit(1);
2830
2830
  }
2831
- const { runWorkspacePicker } = await import("./boot-yjPVUsuA.mjs");
2831
+ const { runWorkspacePicker } = await import("./boot-Xuh-2x4s.mjs");
2832
2832
  await runWorkspacePicker(session);
2833
2833
  return;
2834
2834
  }
@@ -2907,7 +2907,7 @@ const openCommand = {
2907
2907
  const agent = argv.agent ? resolveAgent$1((await fetchPortalDevices(session)).agents, argv.agent) : null;
2908
2908
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
2909
2909
  const { machineName } = await resolveMachineIdentity(null);
2910
- const { PortalDaemonClient } = await import("./daemon-client-Bi6Vfc-j.mjs");
2910
+ const { PortalDaemonClient } = await import("./daemon-client-Bgxq4nzw.mjs");
2911
2911
  let lastLine = "";
2912
2912
  let signalConnected;
2913
2913
  const connected = new Promise((resolve) => {
@@ -3267,8 +3267,8 @@ const sandboxCommand = {
3267
3267
  }).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`"),
3268
3268
  handler: async (argv) => {
3269
3269
  const session = requireSession(argv);
3270
- const { createRestClient } = await import("./rest-BAmUrIrT.mjs");
3271
- const { resolveAgent } = await import("./print-CWJ4mQg2.mjs");
3270
+ const { createRestClient } = await import("./rest-DtH09FEU.mjs");
3271
+ const { resolveAgent } = await import("./print-Bdc6WIBW.mjs");
3272
3272
  const client = createRestClient({
3273
3273
  appUrl: session.appUrl,
3274
3274
  sessionToken: session.sessionToken
@@ -3560,8 +3560,8 @@ function resolveEditor(override, env, platform = process.platform) {
3560
3560
  * `sandbox-fs-enabled` kill switch) exits here before any file work.
3561
3561
  */
3562
3562
  async function openAgentFs(session, agentSelector) {
3563
- const { createRestClient } = await import("./rest-BAmUrIrT.mjs");
3564
- const { resolveAgent } = await import("./print-CWJ4mQg2.mjs");
3563
+ const { createRestClient } = await import("./rest-DtH09FEU.mjs");
3564
+ const { resolveAgent } = await import("./print-Bdc6WIBW.mjs");
3565
3565
  let agent;
3566
3566
  try {
3567
3567
  agent = resolveAgent(await createRestClient({
@@ -5351,7 +5351,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
5351
5351
  process.exit(0);
5352
5352
  }
5353
5353
  if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
5354
- const { runPortalDaemon } = await import("./daemon-D9AW5Lxq.mjs");
5354
+ const { runPortalDaemon } = await import("./daemon-KyMdrC66.mjs");
5355
5355
  runPortalDaemon(process.argv);
5356
5356
  } else runCli();
5357
5357
  function runCli() {
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage, i as sendErrorMessage, n as errorDetail, o as isRecord, t as createRestClient } from "./rest-M2ACdTWv.mjs";
3
- import { C as DEFAULT_API_URL, D as getConfigPath, M as getReviewStateDir, N as getSavedTheme, R as recordDefaultAgent, W as resolveWebUrl, _ as computeSettledLabel, c as actionableCardVerb, d as parseOauthConnectParams, f as prioritizeActionableCards, g as composeQuestionAnswerEntries, h as composeQuestionAnswer, i as resolveAgent, l as cardActionErrorMessage, m as resolveConnectUrl, p as reconcileMaskedInput, q as saveTheme, s as MASK_CHAR, u as parseExternalOauthConnectParams, v as parseConnectCard, w as DEFAULT_APP_URL, y as specKeyFor } from "./print-D2Wr8TLu.mjs";
4
- import { A as aliasActivationHint, C as themeMode, D as themesForMode, L as detectShell, M as installAgentAlias, N as slugifyAliasName, P as takenAliasNames, S as themeForMode, T as themeVersion, U as setActiveWorkspace, V as listWorkspaces, _ as applyTheme, a as writeCrashReport, b as noColorRequested, g as DEFAULT_THEME_ID, h as writeArtifact, i as buildCrashReport, j as dedupeAliasName, k as machineOsFromPlatform, l as splashFitsWidth, m as record, n as disableTerminalAutowrap, o as MARK_CELLS, p as profilingEnabled, r as restoreTerminalAutowrap, s as WORDMARK, t as installCrashHandler, v as findTheme, w as themeModeFromColorFgBg, x as theme, y as monoTheme, z as getActiveWorkspaceId } from "./install-CTggKxXe.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, n as errorDetail, o as isRecord, t as createRestClient } from "./rest-CvzARHxA.mjs";
3
+ import { C as DEFAULT_API_URL, D as getConfigPath, M as getReviewStateDir, N as getSavedTheme, R as recordDefaultAgent, W as resolveWebUrl, _ as computeSettledLabel, c as actionableCardVerb, d as parseOauthConnectParams, f as prioritizeActionableCards, g as composeQuestionAnswerEntries, h as composeQuestionAnswer, i as resolveAgent, l as cardActionErrorMessage, m as resolveConnectUrl, p as reconcileMaskedInput, q as saveTheme, s as MASK_CHAR, u as parseExternalOauthConnectParams, v as parseConnectCard, w as DEFAULT_APP_URL, y as specKeyFor } from "./print-CAaspHCe.mjs";
4
+ import { A as aliasActivationHint, C as themeMode, D as themesForMode, L as detectShell, M as installAgentAlias, N as slugifyAliasName, P as takenAliasNames, S as themeForMode, T as themeVersion, U as setActiveWorkspace, V as listWorkspaces, _ as applyTheme, a as writeCrashReport, b as noColorRequested, g as DEFAULT_THEME_ID, h as writeArtifact, i as buildCrashReport, j as dedupeAliasName, k as machineOsFromPlatform, l as splashFitsWidth, m as record, n as disableTerminalAutowrap, o as MARK_CELLS, p as profilingEnabled, r as restoreTerminalAutowrap, s as WORDMARK, t as installCrashHandler, v as findTheme, w as themeModeFromColorFgBg, x as theme, y as monoTheme, z as getActiveWorkspaceId } from "./install-BuIBR9T2.mjs";
5
5
  import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
6
6
  import { i as billingBlockedOutcomeFromSendResponse } from "./billing-blocked-D3l5kJlX.mjs";
7
- import { n as PortalClient } from "./client-CCmpwqiy.mjs";
7
+ import { n as PortalClient } from "./client-CCqRgRPa.mjs";
8
8
  import { t as defaultTlsCertSource } from "./tls-cert-Rua2oV7n.mjs";
9
9
  import "./api-BFQ4PQDA.mjs";
10
- import "./daemon-WuGKA-0c.mjs";
10
+ import "./daemon-DL2gBVMN.mjs";
11
11
  import { t as SandboxStream } from "./client-CAX6sE_Y.mjs";
12
- import { t as PortalDaemonClient } from "./daemon-client-BB8AZuDU.mjs";
12
+ import { t as PortalDaemonClient } from "./daemon-client-DJTiIbbr.mjs";
13
13
  import { t as runRawPtyPassthrough } from "./raw-pty-BcZNOOGh.mjs";
14
14
  import * as os$1 from "node:os";
15
15
  import { homedir, platform, release, tmpdir } from "node:os";
@@ -4371,6 +4371,49 @@ function fitHintLine(segments, width) {
4371
4371
  return truncate(kept.join(" · "), width);
4372
4372
  }
4373
4373
 
4374
+ //#endregion
4375
+ //#region src/chat/tui/spinner-frames.ts
4376
+ /** Braille dot-cycle frames — the classic smooth terminal spinner. */
4377
+ const SPINNER_FRAMES = [
4378
+ "⠋",
4379
+ "⠙",
4380
+ "⠹",
4381
+ "⠸",
4382
+ "⠼",
4383
+ "⠴",
4384
+ "⠦",
4385
+ "⠧",
4386
+ "⠇",
4387
+ "⠏"
4388
+ ];
4389
+ /** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
4390
+ const SPINNER_INTERVAL_MS = 80;
4391
+ /** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
4392
+ function spinnerFrame(tick) {
4393
+ const n = SPINNER_FRAMES.length;
4394
+ return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
4395
+ }
4396
+
4397
+ //#endregion
4398
+ //#region src/chat/tui/spinner.tsx
4399
+ /**
4400
+ * An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
4401
+ * a self-owned interval that's cleared on unmount, so the animation runs only
4402
+ * while the component is mounted. Returns a <span>, so render it inside a
4403
+ * <text> (matching how the rest of the TUI composes inline glyphs).
4404
+ */
4405
+ function Spinner({ color }) {
4406
+ const [tick, setTick] = useState(0);
4407
+ useEffect(() => {
4408
+ const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
4409
+ return () => clearInterval(id);
4410
+ }, []);
4411
+ return /* @__PURE__ */ jsx("span", {
4412
+ fg: color,
4413
+ children: spinnerFrame(tick)
4414
+ });
4415
+ }
4416
+
4374
4417
  //#endregion
4375
4418
  //#region src/chat/tui/use-debounced-value.ts
4376
4419
  /**
@@ -4543,6 +4586,46 @@ function ConversationPickerScreen({ agent, initialQuery }) {
4543
4586
  cacheKey,
4544
4587
  cache
4545
4588
  ]);
4589
+ useEffect(() => {
4590
+ if (!rest) return;
4591
+ const id = setInterval(() => {
4592
+ (async () => {
4593
+ try {
4594
+ const fresh = await rest.listConversations({
4595
+ agentId: agent.id,
4596
+ limit: 100,
4597
+ channels: showAutomated ? void 0 : humanChannels,
4598
+ archived: showArchived ? "include" : "exclude",
4599
+ onPage: null
4600
+ });
4601
+ const flags = new Map(fresh.map((c) => [c.id, c.activeRun === true]));
4602
+ const withFlags = (conversations) => conversations.map((c) => flags.has(c.id) ? {
4603
+ ...c,
4604
+ activeRun: flags.get(c.id)
4605
+ } : c);
4606
+ setState((prev) => prev.kind === "ready" ? {
4607
+ ...prev,
4608
+ conversations: withFlags(prev.conversations)
4609
+ } : prev);
4610
+ setCache((prev) => {
4611
+ const cached = prev[cacheKey];
4612
+ if (!cached) return prev;
4613
+ return {
4614
+ ...prev,
4615
+ [cacheKey]: withFlags(cached)
4616
+ };
4617
+ });
4618
+ } catch {}
4619
+ })();
4620
+ }, ACTIVE_RUN_POLL_MS);
4621
+ return () => clearInterval(id);
4622
+ }, [
4623
+ rest,
4624
+ agent.id,
4625
+ showAutomated,
4626
+ showArchived,
4627
+ cacheKey
4628
+ ]);
4546
4629
  if (state.kind === "loading") return /* @__PURE__ */ jsx(HomeFrame, { children: /* @__PURE__ */ jsx("box", {
4547
4630
  style: {
4548
4631
  flexDirection: "column",
@@ -5122,7 +5205,7 @@ function ConversationHome({ agent, initialQuery, conversations, showAutomated, o
5122
5205
  const fg = selected ? theme.accent : theme.fg;
5123
5206
  const marker = selected ? "› " : " ";
5124
5207
  const archived = isArchived(row.hit.item);
5125
- const { title, time } = layoutRow(`${isPinned(row.hit.item) ? "pinned · " : ""}${archived ? "archived · " : ""}${singleLine(row.hit.item.title ?? "(untitled)")}`, relativeTime(row.hit.item.updatedAt), coAgentsTag(row.hit.item, agent.id), rowWidth);
5208
+ const { title, time } = layoutRow(`${isPinned(row.hit.item) ? "pinned · " : ""}${archived ? "archived · " : ""}${singleLine(row.hit.item.title ?? "(untitled)")}`, relativeTime(row.hit.item.updatedAt), coAgentsTag(row.hit.item, agent.id), row.hit.item.activeRun === true ? RUN_BADGE_COLS : 0, rowWidth);
5126
5209
  const glyph = channelGlyph(row.hit.item.channel);
5127
5210
  const tag = coAgentsTag(row.hit.item, agent.id);
5128
5211
  const unread = row.hit.item.unread === true;
@@ -5146,6 +5229,10 @@ function ConversationHome({ agent, initialQuery, conversations, showAutomated, o
5146
5229
  fg: theme.muted,
5147
5230
  children: [" ", tag]
5148
5231
  }) : null,
5232
+ row.hit.item.activeRun === true ? /* @__PURE__ */ jsxs("span", {
5233
+ fg: theme.accent,
5234
+ children: [" ", /* @__PURE__ */ jsx(Spinner, {})]
5235
+ }) : null,
5149
5236
  /* @__PURE__ */ jsx("span", {
5150
5237
  fg: theme.dim,
5151
5238
  children: time
@@ -5164,27 +5251,32 @@ function ConversationHome({ agent, initialQuery, conversations, showAutomated, o
5164
5251
  });
5165
5252
  }
5166
5253
  const MIN_LIST_ROWS = 3;
5254
+ const RUN_BADGE_COLS = 2;
5255
+ const ACTIVE_RUN_POLL_MS = 5e3;
5167
5256
  const LIST_GAP_ROWS = 5;
5168
5257
  /**
5169
5258
  * The picker's vertical budget in one place, so the composer cap, the list
5170
5259
  * window, and the gap can't drift apart into competing formulas. Priority,
5171
- * top of the screen down: the composer grows to fit its content first (capped
5172
- * so it can't eat the gap — past the cap the textarea scrolls instead of
5173
- * growing), the gap then always keeps its LIST_GAP_ROWS empty rows, and the
5174
- * list window gets the remaining spare (floored at MIN_LIST_ROWS for
5175
- * terminals too short to afford both). The box is content-height, so a short
5176
- * list's leftover spare becomes extra breathing room on top of the reserved
5177
- * gap.
5260
+ * top of the screen down: the composer grows to fit its content, consuming
5261
+ * the reserved gap rows one for one first (a multiline draft expands into
5262
+ * the gap instead of pushing the conversation list down) and capping at
5263
+ * LIST_GAP_ROWS + 1 lines, past the cap the textarea scrolls instead of
5264
+ * growing. The list window keeps the size a single-line composer affords,
5265
+ * floored at MIN_LIST_ROWS for terminals too short to afford both. The box
5266
+ * is content-height, so a short list's leftover spare becomes extra
5267
+ * breathing room on top of the gap.
5178
5268
  */
5179
5269
  function pickerRowBudget(input) {
5180
- const composerRows = Math.max(1, Math.min(input.composerLines, input.height - input.fixedRows - 2 - LIST_GAP_ROWS));
5270
+ const composerRows = Math.max(1, Math.min(input.composerLines, LIST_GAP_ROWS + 1, input.height - input.fixedRows - 2 - MIN_LIST_ROWS));
5181
5271
  const spareRows = input.height - input.fixedRows - (composerRows + 2);
5182
- const visibleRows = Math.max(MIN_LIST_ROWS, spareRows - LIST_GAP_ROWS);
5272
+ const gapEaten = Math.min(LIST_GAP_ROWS, composerRows - 1);
5273
+ const listBudget = spareRows - (LIST_GAP_ROWS - gapEaten);
5274
+ const visibleRows = Math.max(MIN_LIST_ROWS, Math.min(input.listRowCount, listBudget));
5183
5275
  const paintedRows = Math.min(Math.max(input.listRowCount, 1), visibleRows);
5184
5276
  return {
5185
5277
  composerRows,
5186
5278
  visibleRows,
5187
- listGapRows: Math.max(0, Math.min(LIST_GAP_ROWS, spareRows - paintedRows))
5279
+ listGapRows: Math.max(0, Math.min(LIST_GAP_ROWS - gapEaten, spareRows - paintedRows))
5188
5280
  };
5189
5281
  }
5190
5282
  const composerKeyBindings$1 = [
@@ -5284,17 +5376,17 @@ function channelGlyph(channel) {
5284
5376
  * flush against the right edge; when the row is too narrow to fit the title
5285
5377
  * AND the time, the time is dropped rather than wrapping the row.
5286
5378
  */
5287
- function layoutRow(title, time, tag, width) {
5379
+ function layoutRow(title, time, tag, badgeCols, width) {
5288
5380
  const GLYPH = 2;
5289
5381
  const tagCost = tag ? tag.length + 1 : 0;
5290
5382
  const timeCost = time.length + 1;
5291
- const titleBudget = width - GLYPH - tagCost - timeCost;
5383
+ const titleBudget = width - GLYPH - tagCost - badgeCols - timeCost;
5292
5384
  if (titleBudget < 8) return {
5293
- title: truncate(title, Math.max(1, width - GLYPH - tagCost)),
5385
+ title: truncate(title, Math.max(1, width - GLYPH - tagCost - badgeCols)),
5294
5386
  time: ""
5295
5387
  };
5296
5388
  const fitTitle = truncate(title, titleBudget);
5297
- const used = GLYPH + fitTitle.length + tagCost;
5389
+ const used = GLYPH + fitTitle.length + tagCost + badgeCols;
5298
5390
  const pad = Math.max(1, width - used - time.length);
5299
5391
  return {
5300
5392
  title: fitTitle,
@@ -7528,49 +7620,6 @@ function TodoCardView({ todos, isActive, minimized, expanded, onToggleMinimized,
7528
7620
  });
7529
7621
  }
7530
7622
 
7531
- //#endregion
7532
- //#region src/chat/tui/spinner-frames.ts
7533
- /** Braille dot-cycle frames — the classic smooth terminal spinner. */
7534
- const SPINNER_FRAMES = [
7535
- "⠋",
7536
- "⠙",
7537
- "⠹",
7538
- "⠸",
7539
- "⠼",
7540
- "⠴",
7541
- "⠦",
7542
- "⠧",
7543
- "⠇",
7544
- "⠏"
7545
- ];
7546
- /** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
7547
- const SPINNER_INTERVAL_MS = 80;
7548
- /** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
7549
- function spinnerFrame(tick) {
7550
- const n = SPINNER_FRAMES.length;
7551
- return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
7552
- }
7553
-
7554
- //#endregion
7555
- //#region src/chat/tui/spinner.tsx
7556
- /**
7557
- * An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
7558
- * a self-owned interval that's cleared on unmount, so the animation runs only
7559
- * while the component is mounted. Returns a <span>, so render it inside a
7560
- * <text> (matching how the rest of the TUI composes inline glyphs).
7561
- */
7562
- function Spinner({ color }) {
7563
- const [tick, setTick] = useState(0);
7564
- useEffect(() => {
7565
- const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
7566
- return () => clearInterval(id);
7567
- }, []);
7568
- return /* @__PURE__ */ jsx("span", {
7569
- fg: color,
7570
- children: spinnerFrame(tick)
7571
- });
7572
- }
7573
-
7574
7623
  //#endregion
7575
7624
  //#region src/chat/tui/format-elapsed.ts
7576
7625
  /**
@@ -161,7 +161,7 @@ function errorMessage(err) {
161
161
  * the commit time of the built tree is one monotonic clock they share.
162
162
  */
163
163
  function portalDaemonBuild() {
164
- return "1791440490";
164
+ return "1791485423";
165
165
  }
166
166
  /**
167
167
  * Whether a client carrying `mine` should replace a running daemon carrying
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as PortalClient, r as RATE_LIMIT_STAND_DOWN_MS, t as AUTH_STAND_DOWN_MS } from "./client-CCmpwqiy.mjs";
2
+ import { n as PortalClient, r as RATE_LIMIT_STAND_DOWN_MS, t as AUTH_STAND_DOWN_MS } from "./client-CCqRgRPa.mjs";
3
3
  import "./api-BFQ4PQDA.mjs";
4
4
 
5
5
  export { PortalClient };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as portalDaemonBuild, i as isNewerBuild, n as PortalClient, o as isRecord } from "./client-CCmpwqiy.mjs";
2
+ import { a as portalDaemonBuild, i as isNewerBuild, n as PortalClient, o as isRecord } from "./client-CCqRgRPa.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";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import "./client-CCmpwqiy.mjs";
2
+ import "./client-CCqRgRPa.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-WuGKA-0c.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-DL2gBVMN.mjs";
6
6
 
7
7
  export { runPortalDaemon };
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import "./client-CCqRgRPa.mjs";
3
+ import "./tls-cert-Rua2oV7n.mjs";
4
+ import "./api-BFQ4PQDA.mjs";
5
+ import "./daemon-DL2gBVMN.mjs";
6
+ import { t as PortalDaemonClient } from "./daemon-client-DJTiIbbr.mjs";
7
+
8
+ export { PortalDaemonClient };
@@ -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-WuGKA-0c.mjs";
2
+ import { d as daemonPaths, f as encodeLine, l as LOCAL_PROTOCOL_VERSION, m as parseDaemonMessage, n as ensureDaemonRunning, p as makeLineParser } from "./daemon-DL2gBVMN.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-M2ACdTWv.mjs";
3
- import { D as getConfigPath } from "./print-D2Wr8TLu.mjs";
2
+ import { c as version$1 } from "./rest-CvzARHxA.mjs";
3
+ import { D as getConfigPath } from "./print-CAaspHCe.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-M2ACdTWv.mjs";
3
- import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-D2Wr8TLu.mjs";
2
+ import "./rest-CvzARHxA.mjs";
3
+ import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-CAaspHCe.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-M2ACdTWv.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, o as isRecord, t as createRestClient } from "./rest-CvzARHxA.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";
@@ -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-Da280z8Q.mjs");
17
+ const { PortalClient } = await import("./client-D_HkrXJN.mjs");
18
18
  const { defaultTlsCertSource } = await import("./tls-cert-BpCaD5AT.mjs");
19
19
  let signalConnected;
20
20
  const connected = new Promise((resolve) => {
@@ -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.61";
9
+ var version = "0.6.0-beta.63";
10
10
 
11
11
  //#endregion
12
12
  //#region src/chat/util.ts
@@ -629,6 +629,7 @@ const conversationSummarySchema = z.object({
629
629
  viewerPinnedAt: z.string().nullable().optional(),
630
630
  viewerParticipates: z.boolean().optional(),
631
631
  unread: z.boolean().optional(),
632
+ activeRun: z.boolean().optional(),
632
633
  agent: conversationAgentSchema,
633
634
  agents: z.array(conversationAgentSchema).optional()
634
635
  });
@@ -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-M2ACdTWv.mjs";
2
+ import { i as sendErrorMessage, n as errorDetail, r as filenameFromContentDisposition, t as createRestClient } from "./rest-CvzARHxA.mjs";
3
3
  import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
4
4
  import "./billing-blocked-D3l5kJlX.mjs";
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.6.0-beta.61",
3
+ "version": "0.6.0-beta.63",
4
4
  "description": "Skydive CLI — cloud agents from the command line",
5
5
  "homepage": "https://skydive.com",
6
6
  "license": "MIT",
@@ -72,9 +72,9 @@
72
72
  },
73
73
  "//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.",
74
74
  "optionalDependencies": {
75
- "skydive-cli-darwin-arm64": "0.6.0-beta.61",
76
- "skydive-cli-darwin-x64": "0.6.0-beta.61",
77
- "skydive-cli-linux-x64": "0.6.0-beta.61",
78
- "skydive-cli-linux-arm64": "0.6.0-beta.61"
75
+ "skydive-cli-darwin-arm64": "0.6.0-beta.63",
76
+ "skydive-cli-darwin-x64": "0.6.0-beta.63",
77
+ "skydive-cli-linux-x64": "0.6.0-beta.63",
78
+ "skydive-cli-linux-arm64": "0.6.0-beta.63"
79
79
  }
80
80
  }
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./client-CCmpwqiy.mjs";
3
- import "./tls-cert-Rua2oV7n.mjs";
4
- import "./api-BFQ4PQDA.mjs";
5
- import "./daemon-WuGKA-0c.mjs";
6
- import { t as PortalDaemonClient } from "./daemon-client-BB8AZuDU.mjs";
7
-
8
- export { PortalDaemonClient };