skydive-cli 0.2.0-beta.604 → 0.2.0-beta.605

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-vu2-Lrsa.mjs";
2
+ import { t as HttpError } from "./rest-DMpigwmN.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 getPromptHistoryPath, B as resolveSession, C as API_KEY_PREFIX, D as deleteConfig, E as DEFAULT_WEB_URL, F as getStoredApiKeyWorkspaceName, G as setLastSeenVersion, H as saveConfig, I as getUpdateCheckDisabled, L as resolveAppUrl, N as getShareMachineDefault, O as getConfigPath, P as getStoredApiKeyId, R as resolveConfig, S as API_KEY_FAMILY_PREFIX, U as saveSession, _ as getActiveWorkspaceId, b as setActiveWorkspace, g as ensureActiveOrganization, k as getLastSeenVersion, m as themes, r as brandHelpArt, v as getSessionIdentity, w as DEFAULT_API_URL, x as API_KEYS_URL, y as listWorkspaces, z as resolveManagementAuth } from "./brand-BVALAEf1.mjs";
3
3
  import { n as printError, r as printTable, t as output } from "./output-B4cW10Ph.mjs";
4
- import { n as createRestClient } from "./rest-vu2-Lrsa.mjs";
5
- import { i as resolveAgent } from "./print-DLGCpIM9.mjs";
6
- import { a as registerPortalDevice, c as machineIdentity, n as findThisDevice, o as revokePortalAccess, r as grantPortalAccess, t as fetchPortalDevices } from "./api-Bx5VyWaC.mjs";
4
+ import { n as createRestClient } from "./rest-DMpigwmN.mjs";
5
+ import { i as resolveAgent } from "./print-6Bm51XhR.mjs";
6
+ import { a as registerPortalDevice, c as machineIdentity, n as findThisDevice, o as revokePortalAccess, r as grantPortalAccess, t as fetchPortalDevices } from "./api-BGWcPuik.mjs";
7
7
  import { t as SandboxStream } from "./client-BVOAwU8M.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.604";
23
+ var version = "0.2.0-beta.605";
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-Cmte0eob.mjs");
1203
+ const { runChat } = await import("./boot-B_I9v5NI.mjs");
1204
1204
  await runChat({
1205
1205
  appUrl,
1206
1206
  sessionToken: session.value.sessionToken,
@@ -1227,7 +1227,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1227
1227
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
1228
1228
  process.exit(1);
1229
1229
  }
1230
- const { connectMachineShare } = await import("./print-share-DPsQq2Cy.mjs");
1230
+ const { connectMachineShare } = await import("./print-share-DE_dkZX7.mjs");
1231
1231
  const machineShare = await connectMachineShare({
1232
1232
  appUrl,
1233
1233
  sessionToken: session.value.sessionToken,
@@ -1235,7 +1235,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1235
1235
  });
1236
1236
  const extra = (argv.print ?? "").trim();
1237
1237
  const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
1238
- const { runPrint } = await import("./print-QPPaRx38.mjs");
1238
+ const { runPrint } = await import("./print-qXJymvuF.mjs");
1239
1239
  try {
1240
1240
  const result = await runPrint({
1241
1241
  appUrl,
@@ -1516,7 +1516,7 @@ const chatCommand = {
1516
1516
  printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
1517
1517
  process.exit(1);
1518
1518
  }
1519
- const { runChat } = await import("./boot-Cmte0eob.mjs");
1519
+ const { runChat } = await import("./boot-B_I9v5NI.mjs");
1520
1520
  await runChat({
1521
1521
  appUrl,
1522
1522
  sessionToken: session.value.sessionToken,
@@ -1553,7 +1553,7 @@ async function runPrintMode({ argv, appUrl }) {
1553
1553
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
1554
1554
  process.exit(1);
1555
1555
  }
1556
- const { runPrint, readStdin } = await import("./print-QPPaRx38.mjs");
1556
+ const { runPrint, readStdin } = await import("./print-qXJymvuF.mjs");
1557
1557
  let prompt = (argv.print ?? "").trim();
1558
1558
  if (!prompt) {
1559
1559
  if (process.stdin.isTTY) {
@@ -1568,7 +1568,7 @@ async function runPrintMode({ argv, appUrl }) {
1568
1568
  }
1569
1569
  let machineShare = null;
1570
1570
  if (resolveShareMachine(argv)) {
1571
- const { connectMachineShare } = await import("./print-share-DPsQq2Cy.mjs");
1571
+ const { connectMachineShare } = await import("./print-share-DE_dkZX7.mjs");
1572
1572
  machineShare = await connectMachineShare({
1573
1573
  appUrl,
1574
1574
  sessionToken: session.value.sessionToken,
@@ -1627,7 +1627,7 @@ const getCommand = {
1627
1627
  printError(`${session.error.message} Run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
1628
1628
  process.exit(1);
1629
1629
  }
1630
- const { messageGet } = await import("./print-QPPaRx38.mjs");
1630
+ const { messageGet } = await import("./print-qXJymvuF.mjs");
1631
1631
  try {
1632
1632
  const result = await messageGet({
1633
1633
  appUrl,
@@ -1824,7 +1824,7 @@ const switchCommand = {
1824
1824
  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.");
1825
1825
  process.exit(1);
1826
1826
  }
1827
- const { runWorkspacePicker } = await import("./boot-Cmte0eob.mjs");
1827
+ const { runWorkspacePicker } = await import("./boot-B_I9v5NI.mjs");
1828
1828
  await runWorkspacePicker(session);
1829
1829
  return;
1830
1830
  }
@@ -1902,7 +1902,7 @@ const openCommand = {
1902
1902
  const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
1903
1903
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
1904
1904
  const { machineName } = machineIdentity();
1905
- const { PortalClient } = await import("./client-BYYp0E6M.mjs");
1905
+ const { PortalClient } = await import("./client-BRfmlbgI.mjs");
1906
1906
  let lastLine = "";
1907
1907
  let signalConnected;
1908
1908
  const connected = new Promise((resolve) => {
@@ -2074,8 +2074,8 @@ const sandboxCommand = {
2074
2074
  }).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`"),
2075
2075
  handler: async (argv) => {
2076
2076
  const session = requireSession(argv);
2077
- const { createRestClient } = await import("./rest-nx0AmgJy.mjs");
2078
- const { resolveAgent } = await import("./print-QPPaRx38.mjs");
2077
+ const { createRestClient } = await import("./rest-C3RySrPa.mjs");
2078
+ const { resolveAgent } = await import("./print-qXJymvuF.mjs");
2079
2079
  const client = createRestClient({
2080
2080
  appUrl: session.appUrl,
2081
2081
  sessionToken: session.sessionToken
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { M as getSavedTheme, O as getConfigPath, T as DEFAULT_APP_URL, V as resolveWebUrl, W as saveTheme, _ as getActiveWorkspaceId, a as applyTheme, b as setActiveWorkspace, c as noColorRequested, d as themeMode, f as themeModeFromColorFgBg, h as themesForMode, i as DEFAULT_THEME_ID, j as getReviewStateDir, l as theme, n as WORDMARK, o as findTheme, p as themeVersion, s as monoTheme, t as MARK_CELLS, u as themeForMode, w as DEFAULT_API_URL, y as listWorkspaces } from "./brand-BVALAEf1.mjs";
3
- import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-vu2-Lrsa.mjs";
4
- 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-DLGCpIM9.mjs";
5
- import "./api-Bx5VyWaC.mjs";
3
+ import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-DMpigwmN.mjs";
4
+ 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-6Bm51XhR.mjs";
5
+ import "./api-BGWcPuik.mjs";
6
6
  import { t as SandboxStream } from "./client-BVOAwU8M.mjs";
7
- import { t as PortalClient } from "./client-BsLCAWf1.mjs";
7
+ import { t as PortalClient } from "./client-l3OrGKaC.mjs";
8
8
  import { t as runRawPtyPassthrough } from "./raw-pty-Dbi2kb9v.mjs";
9
9
  import * as os$1 from "node:os";
10
10
  import { homedir, platform, release, tmpdir } from "node:os";
@@ -1862,8 +1862,28 @@ function fitHintLine(segments, width) {
1862
1862
  return truncate(kept.join(" · "), width);
1863
1863
  }
1864
1864
 
1865
+ //#endregion
1866
+ //#region src/chat/tui/use-debounced-value.ts
1867
+ /**
1868
+ * Returns a copy of `value` that only updates after it has stopped changing
1869
+ * for `delayMs`. Use it to throttle work driven by fast-changing state — e.g.
1870
+ * a search input whose every keystroke would otherwise fire a new request.
1871
+ *
1872
+ * Mirrors the web app's `useDebouncedValue` so the CLI conversation search
1873
+ * debounces its server query the same way the web sidebar does.
1874
+ */
1875
+ function useDebouncedValue(value, delayMs) {
1876
+ const [debounced, setDebounced] = useState(value);
1877
+ useEffect(() => {
1878
+ const timer = setTimeout(() => setDebounced(value), delayMs);
1879
+ return () => clearTimeout(timer);
1880
+ }, [value, delayMs]);
1881
+ return debounced;
1882
+ }
1883
+
1865
1884
  //#endregion
1866
1885
  //#region src/chat/tui/screens/conversation-picker.tsx
1886
+ const SEARCH_DEBOUNCE_MS = 250;
1867
1887
  const humanChannels = [
1868
1888
  "web",
1869
1889
  "slack",
@@ -1971,16 +1991,83 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
1971
1991
  const rest = useStore((s) => s.rest);
1972
1992
  const [query, setQuery] = useState("");
1973
1993
  const [highlight, setHighlight] = useState(0);
1994
+ const debouncedQuery = useDebouncedValue(query.trim(), SEARCH_DEBOUNCE_MS);
1995
+ const isSearching = debouncedQuery.length > 0;
1996
+ const [search, setSearch] = useState(null);
1997
+ useEffect(() => {
1998
+ if (!rest || !isSearching) {
1999
+ setSearch(null);
2000
+ return;
2001
+ }
2002
+ let cancelled = false;
2003
+ setSearch({
2004
+ query: debouncedQuery,
2005
+ state: { kind: "loading" }
2006
+ });
2007
+ (async () => {
2008
+ try {
2009
+ const results = await rest.listConversations({
2010
+ agentId: agent.id,
2011
+ channels: showAutomated ? void 0 : humanChannels,
2012
+ archived: showArchived ? "include" : "exclude",
2013
+ query: debouncedQuery,
2014
+ onPage: (partial) => {
2015
+ if (!cancelled) setSearch({
2016
+ query: debouncedQuery,
2017
+ state: {
2018
+ kind: "ready",
2019
+ conversations: partial
2020
+ }
2021
+ });
2022
+ }
2023
+ });
2024
+ if (cancelled) return;
2025
+ setSearch({
2026
+ query: debouncedQuery,
2027
+ state: {
2028
+ kind: "ready",
2029
+ conversations: results
2030
+ }
2031
+ });
2032
+ } catch (err) {
2033
+ if (cancelled) return;
2034
+ setSearch({
2035
+ query: debouncedQuery,
2036
+ state: {
2037
+ kind: "error",
2038
+ message: err instanceof Error ? err.message : String(err)
2039
+ }
2040
+ });
2041
+ }
2042
+ })();
2043
+ return () => {
2044
+ cancelled = true;
2045
+ };
2046
+ }, [
2047
+ rest,
2048
+ agent.id,
2049
+ debouncedQuery,
2050
+ isSearching,
2051
+ showAutomated,
2052
+ showArchived
2053
+ ]);
1974
2054
  const [removedIds, setRemovedIds] = useState(/* @__PURE__ */ new Set());
1975
2055
  const [archiveOverrides, setArchiveOverrides] = useState(/* @__PURE__ */ new Map());
1976
2056
  const [confirmId, setConfirmId] = useState(null);
1977
2057
  const [error, setError] = useState(null);
1978
2058
  const isArchived = (c) => archiveOverrides.get(c.id) ?? c.viewerArchivedAt != null;
1979
- const list = conversations.filter((c) => !removedIds.has(c.id) && (showArchived || !isArchived(c)));
2059
+ const list = ((isSearching && search?.query === debouncedQuery && search.state.kind === "ready" ? search.state.conversations : null) ?? conversations).filter((c) => !removedIds.has(c.id) && (showArchived || !isArchived(c)));
1980
2060
  useEffect(() => {
1981
2061
  setHighlight(0);
1982
2062
  }, [showAutomated, showArchived]);
1983
- const hits = fuzzyFilter(query, list, conversationKeys);
2063
+ const hits = isSearching ? list.map((item) => ({
2064
+ item,
2065
+ highlights: [
2066
+ substringIndexes(singleLine(item.title ?? ""), debouncedQuery),
2067
+ null,
2068
+ null
2069
+ ]
2070
+ })) : fuzzyFilter(query, list, conversationKeys);
1984
2071
  const rows = [{ kind: "new" }, ...hits.map((hit) => ({
1985
2072
  kind: "conv",
1986
2073
  hit
@@ -1991,6 +2078,8 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
1991
2078
  const highlightRow = rows[clamped];
1992
2079
  const highlightArchived = highlightRow?.kind === "conv" && isArchived(highlightRow.hit.item);
1993
2080
  const confirmConv = confirmId !== null ? list.find((c) => c.id === confirmId) : void 0;
2081
+ const searchState = isSearching ? search?.state : void 0;
2082
+ const countSegment = isSearching && (searchState?.kind === "loading" || search === null) ? "searching…" : isSearching && searchState?.kind === "error" ? `search failed: ${searchState.message}` : `${hits.length}/${list.length}${complete || isSearching ? "" : " (loading…)"}`;
1994
2083
  const status = confirmConv ? {
1995
2084
  fg: theme.error,
1996
2085
  text: truncate(`delete “${confirmConv.title ?? "(untitled)"}”? y/n`, innerWidth)
@@ -2000,7 +2089,7 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
2000
2089
  } : {
2001
2090
  fg: theme.dim,
2002
2091
  text: fitHintLine([
2003
- `${hits.length}/${list.length}${complete ? "" : " (loading…)"}`,
2092
+ countSegment,
2004
2093
  `ctrl+a ${highlightArchived ? "unarchive" : "archive"}`,
2005
2094
  "ctrl+d delete",
2006
2095
  `tab ${showAutomated ? "hide" : "show"} agent runs`,
@@ -2191,6 +2280,20 @@ const conversationKeys = [
2191
2280
  (c) => c.preview ?? "",
2192
2281
  (c) => conversationAgents(c).map((a) => a.name).join(" ")
2193
2282
  ];
2283
+ /**
2284
+ * Character indexes of the first case-insensitive occurrence of `needle` in
2285
+ * `haystack`, for highlighting a literal title match under server search (the
2286
+ * server's title branch is a substring ILIKE). Null when it doesn't occur — a
2287
+ * server row can match on message body or participant name without its title
2288
+ * containing the query, in which case nothing in the title is highlighted.
2289
+ */
2290
+ function substringIndexes(haystack, needle) {
2291
+ const trimmed = needle.trim();
2292
+ if (!trimmed) return null;
2293
+ const at = haystack.toLowerCase().indexOf(trimmed.toLowerCase());
2294
+ if (at < 0) return null;
2295
+ return Array.from({ length: trimmed.length }, (_, i) => at + i);
2296
+ }
2194
2297
  function previewLine(c) {
2195
2298
  const when = relativeTime(c.updatedAt);
2196
2299
  const prefix = c.preview ? c.preview.replace(/\s+/g, " ").trim() : "";
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import "./rest-DMpigwmN.mjs";
3
+ import "./api-BGWcPuik.mjs";
4
+ import { t as PortalClient } from "./client-l3OrGKaC.mjs";
5
+
6
+ export { PortalClient };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage } from "./rest-vu2-Lrsa.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-Bx5VyWaC.mjs";
2
+ import { a as errorMessage } from "./rest-DMpigwmN.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-BGWcPuik.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 { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, t as HttpError } from "./rest-vu2-Lrsa.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, t as HttpError } from "./rest-DMpigwmN.mjs";
3
3
  import stableStringify from "safe-stable-stringify";
4
4
 
5
5
  //#region src/chat/tui/chat/card.ts
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "./rest-vu2-Lrsa.mjs";
3
- import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-DLGCpIM9.mjs";
2
+ import "./rest-DMpigwmN.mjs";
3
+ import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-6Bm51XhR.mjs";
4
4
 
5
5
  export { messageGet, readStdin, resolveAgent, runPrint };
@@ -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-BYYp0E6M.mjs");
17
+ const { PortalClient } = await import("./client-BRfmlbgI.mjs");
18
18
  let signalConnected;
19
19
  const connected = new Promise((resolve) => {
20
20
  signalConnected = resolve;
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-vu2-Lrsa.mjs";
2
+ import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-DMpigwmN.mjs";
3
3
 
4
4
  export { createRestClient };
@@ -226,7 +226,8 @@ function createRestClient({ appUrl, sessionToken }) {
226
226
  const { agent } = await post(`/api/v1/agents/${encodeURIComponent(agentId)}`, { model }, updateAgentResponseSchema, "PATCH");
227
227
  return { model: agent.model ?? null };
228
228
  },
229
- listConversations: async ({ agentId, limit, channels, archived, onPage }) => {
229
+ listConversations: async ({ agentId, limit, channels, archived, query, onPage }) => {
230
+ const trimmedQuery = query?.trim();
230
231
  const all = [];
231
232
  const maxConversations = limit ?? 5e3;
232
233
  let cursor;
@@ -239,6 +240,7 @@ function createRestClient({ appUrl, sessionToken }) {
239
240
  params.set("limit", String(Math.min(remaining, 100)));
240
241
  if (cursor) params.set("cursor", cursor);
241
242
  if (archived) params.set("archived", archived);
243
+ if (trimmedQuery) params.set("query", trimmedQuery);
242
244
  for (const channel of channels ?? []) params.append("channels", channel);
243
245
  const page = await get(`/api/v1/conversations?${params.toString()}`, listConversationsResponseSchema);
244
246
  all.push(...page.conversations);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.2.0-beta.604",
3
+ "version": "0.2.0-beta.605",
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-vu2-Lrsa.mjs";
3
- import "./api-Bx5VyWaC.mjs";
4
- import { t as PortalClient } from "./client-BsLCAWf1.mjs";
5
-
6
- export { PortalClient };