skydive-cli 0.6.0-beta.29 → 0.6.0-beta.30

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-DRpmhj-Y.mjs";
3
- import { A as getPromptHistoryPath, B as resolveConfig, D as getDefaultAgent, E as getConfigPath, F as getStoredApiKeyWorkspaceName, G as saveSession, H as resolveSession$1, I as getUpdateCheckDisabled, N as getShareMachineDefault, O as getLastSeenVersion, P as getStoredApiKeyId, R as resolveAppUrl, S as DEFAULT_API_URL, T as deleteConfig, V as resolveManagementAuth, W as saveConfig, b as API_KEY_FAMILY_PREFIX, i as resolveAgent$1, k as getPreference, q as setLastSeenVersion, w as PREFERENCES, x as API_KEY_PREFIX, y as API_KEYS_URL, z as resolveChatAuth } from "./print-BNGt-DNP.mjs";
4
- import { A as installAgentAlias, B as resolveWorkspaceId, D as machineOsFromPlatform, E as buildImportSeedPrompt, F as detectShell, I as ensureActiveOrganization, L as getActiveWorkspaceId, M as takenAliasNames, N as SUPPORTED_SHELLS, O as aliasActivationHint, P as defaultInstallEnv, R as getSessionIdentity, V as setActiveWorkspace, c as getAutomaticLogsDir, j as slugifyAliasName, k as dedupeAliasName, l as maybeStartProfiling, o as brandHelpArt, t as installCrashHandler, u as profileDir, w as themes, z as listWorkspaces } from "./install-DA93B-HZ.mjs";
2
+ import { c as version, s as name, t as createRestClient } from "./rest-D-QhD4Ey.mjs";
3
+ import { A as getPromptHistoryPath, B as resolveConfig, D as getDefaultAgent, E as getConfigPath, F as getStoredApiKeyWorkspaceName, G as saveSession, H as resolveSession$1, I as getUpdateCheckDisabled, N as getShareMachineDefault, O as getLastSeenVersion, P as getStoredApiKeyId, R as resolveAppUrl, S as DEFAULT_API_URL, T as deleteConfig, V as resolveManagementAuth, W as saveConfig, b as API_KEY_FAMILY_PREFIX, i as resolveAgent$1, k as getPreference, q as setLastSeenVersion, w as PREFERENCES, x as API_KEY_PREFIX, y as API_KEYS_URL, z as resolveChatAuth } from "./print-DOGluqfs.mjs";
4
+ import { A as installAgentAlias, B as resolveWorkspaceId, D as machineOsFromPlatform, E as buildImportSeedPrompt, F as detectShell, I as ensureActiveOrganization, L as getActiveWorkspaceId, M as takenAliasNames, N as SUPPORTED_SHELLS, O as aliasActivationHint, P as defaultInstallEnv, R as getSessionIdentity, V as setActiveWorkspace, c as getAutomaticLogsDir, j as slugifyAliasName, k as dedupeAliasName, l as maybeStartProfiling, o as brandHelpArt, t as installCrashHandler, u as profileDir, w as themes, z as listWorkspaces } from "./install-D4zmUhGt.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 { a as resolveMachineIdentity } from "./client-CG6Ex3kN.mjs";
8
+ import { a as resolveMachineIdentity } from "./client-C6nIuyAZ.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-DN2YUdTA.mjs";
11
+ import { d as daemonPaths, i as queryDaemonStatus, n as ensureDaemonRunning, s as stopDaemon, u as PORTAL_DAEMON_FLAG } from "./daemon-DJLsd6X4.mjs";
12
12
  import { a as encodeFsRequest, i as decodeFsResponse, n as SANDBOX_STREAM_PATH, r as streamSpecToQuery, t as SandboxStream } from "./client-l6orYfqq.mjs";
13
13
  import { hideBin } from "yargs/helpers";
14
14
  import yargs from "yargs";
@@ -1586,7 +1586,7 @@ const importCommand = {
1586
1586
  process.exit(1);
1587
1587
  }
1588
1588
  }
1589
- const { runChat } = await import("./boot-OoLJGLIa.mjs");
1589
+ const { runChat } = await import("./boot-DZqQZFlg.mjs");
1590
1590
  await runChat({
1591
1591
  appUrl,
1592
1592
  sessionToken: session.value.sessionToken,
@@ -1616,7 +1616,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1616
1616
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
1617
1617
  process.exit(1);
1618
1618
  }
1619
- const { connectMachineShare } = await import("./print-share-CF3XfGTI.mjs");
1619
+ const { connectMachineShare } = await import("./print-share-BsJI8x3l.mjs");
1620
1620
  const machineShare = await connectMachineShare({
1621
1621
  appUrl,
1622
1622
  sessionToken: session.value.sessionToken,
@@ -1624,7 +1624,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1624
1624
  });
1625
1625
  const extra = (argv.print ?? "").trim();
1626
1626
  const prompt = buildImportSeedPrompt(process.cwd(), machineOsFromPlatform(process.platform)) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
1627
- const { runPrint } = await import("./print-BF20aQme.mjs");
1627
+ const { runPrint } = await import("./print-DjXrn_7U.mjs");
1628
1628
  try {
1629
1629
  const result = await runPrint({
1630
1630
  appUrl,
@@ -2031,7 +2031,7 @@ const chatCommand = {
2031
2031
  sessionToken: auth.value.token,
2032
2032
  agentSelector: argv.agent ?? null
2033
2033
  });
2034
- const { runChat } = await import("./boot-OoLJGLIa.mjs");
2034
+ const { runChat } = await import("./boot-DZqQZFlg.mjs");
2035
2035
  await runChat({
2036
2036
  appUrl: auth.value.appUrl,
2037
2037
  sessionToken: auth.value.token,
@@ -2115,7 +2115,7 @@ async function runPrintMode({ argv, appUrl }) {
2115
2115
  printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
2116
2116
  process.exit(1);
2117
2117
  }
2118
- const { runPrint, readStdin } = await import("./print-BF20aQme.mjs");
2118
+ const { runPrint, readStdin } = await import("./print-DjXrn_7U.mjs");
2119
2119
  const workspaceId = await resolveWorkspaceFlag({
2120
2120
  appUrl,
2121
2121
  sessionToken: auth.value.token,
@@ -2145,7 +2145,7 @@ async function runPrintMode({ argv, appUrl }) {
2145
2145
  process.exit(1);
2146
2146
  }
2147
2147
  } else {
2148
- const { connectMachineShare } = await import("./print-share-CF3XfGTI.mjs");
2148
+ const { connectMachineShare } = await import("./print-share-BsJI8x3l.mjs");
2149
2149
  machineShare = await connectMachineShare({
2150
2150
  appUrl: auth.value.appUrl,
2151
2151
  sessionToken: auth.value.token,
@@ -2210,7 +2210,7 @@ const getCommand$1 = {
2210
2210
  printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
2211
2211
  process.exit(1);
2212
2212
  }
2213
- const { messageGet } = await import("./print-BF20aQme.mjs");
2213
+ const { messageGet } = await import("./print-DjXrn_7U.mjs");
2214
2214
  try {
2215
2215
  const result = await messageGet({
2216
2216
  appUrl: auth.value.appUrl,
@@ -2413,7 +2413,7 @@ const switchCommand = {
2413
2413
  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.");
2414
2414
  process.exit(1);
2415
2415
  }
2416
- const { runWorkspacePicker } = await import("./boot-OoLJGLIa.mjs");
2416
+ const { runWorkspacePicker } = await import("./boot-DZqQZFlg.mjs");
2417
2417
  await runWorkspacePicker(session);
2418
2418
  return;
2419
2419
  }
@@ -2492,7 +2492,7 @@ const openCommand = {
2492
2492
  const agent = argv.agent ? resolveAgent$1((await fetchPortalDevices(session)).agents, argv.agent) : null;
2493
2493
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
2494
2494
  const { machineName } = await resolveMachineIdentity(null);
2495
- const { PortalDaemonClient } = await import("./daemon-client-CwjSyo8J.mjs");
2495
+ const { PortalDaemonClient } = await import("./daemon-client-CoFALl4c.mjs");
2496
2496
  let lastLine = "";
2497
2497
  let signalConnected;
2498
2498
  const connected = new Promise((resolve) => {
@@ -2849,8 +2849,8 @@ const sandboxCommand = {
2849
2849
  }).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`"),
2850
2850
  handler: async (argv) => {
2851
2851
  const session = requireSession(argv);
2852
- const { createRestClient } = await import("./rest-CNsQGKy6.mjs");
2853
- const { resolveAgent } = await import("./print-BF20aQme.mjs");
2852
+ const { createRestClient } = await import("./rest--lkwhdUi.mjs");
2853
+ const { resolveAgent } = await import("./print-DjXrn_7U.mjs");
2854
2854
  const client = createRestClient({
2855
2855
  appUrl: session.appUrl,
2856
2856
  sessionToken: session.sessionToken
@@ -3121,8 +3121,8 @@ const fsEditCommand = {
3121
3121
  handler: async (argv) => {
3122
3122
  const session = requireSession(argv);
3123
3123
  const remotePath = argv.path;
3124
- const { createRestClient } = await import("./rest-CNsQGKy6.mjs");
3125
- const { resolveAgent } = await import("./print-BF20aQme.mjs");
3124
+ const { createRestClient } = await import("./rest--lkwhdUi.mjs");
3125
+ const { resolveAgent } = await import("./print-DjXrn_7U.mjs");
3126
3126
  const client = createRestClient({
3127
3127
  appUrl: session.appUrl,
3128
3128
  sessionToken: session.sessionToken
@@ -4575,7 +4575,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
4575
4575
  process.exit(0);
4576
4576
  }
4577
4577
  if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
4578
- const { runPortalDaemon } = await import("./daemon-0z1XgxXA.mjs");
4578
+ const { runPortalDaemon } = await import("./daemon-7UmxwQfJ.mjs");
4579
4579
  runPortalDaemon(process.argv);
4580
4580
  } else runCli();
4581
4581
  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-DRpmhj-Y.mjs";
3
- import { C as DEFAULT_APP_URL, E as getConfigPath, K as saveTheme, L as recordDefaultAgent, M as getSavedTheme, S as DEFAULT_API_URL, U as resolveWebUrl, _ as parseConnectCard, c as actionableCardVerb, d as parseOauthConnectParams, f as prioritizeActionableCards, g as computeSettledLabel, h as composeQuestionAnswer, i as resolveAgent, j as getReviewStateDir, l as cardActionErrorMessage, m as resolveConnectUrl, p as reconcileMaskedInput, s as MASK_CHAR, u as parseExternalOauthConnectParams, v as specKeyFor } from "./print-BNGt-DNP.mjs";
4
- import { A as installAgentAlias, C as themeVersion, D as machineOsFromPlatform, F as detectShell, L as getActiveWorkspaceId, M as takenAliasNames, O as aliasActivationHint, S as themeModeFromColorFgBg, T as themesForMode, V as setActiveWorkspace, _ as monoTheme, a as WORDMARK, b as themeForMode, d as profilingEnabled, f as record, g as findTheme, h as applyTheme, i as MARK_CELLS, j as slugifyAliasName, k as dedupeAliasName, m as DEFAULT_THEME_ID, n as buildCrashReport, p as writeArtifact, r as writeCrashReport, s as splashFitsWidth, t as installCrashHandler, v as noColorRequested, x as themeMode, y as theme, z as listWorkspaces } from "./install-DA93B-HZ.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, n as errorDetail, o as isRecord, t as createRestClient } from "./rest-D-QhD4Ey.mjs";
3
+ import { C as DEFAULT_APP_URL, E as getConfigPath, K as saveTheme, L as recordDefaultAgent, M as getSavedTheme, S as DEFAULT_API_URL, U as resolveWebUrl, _ as parseConnectCard, c as actionableCardVerb, d as parseOauthConnectParams, f as prioritizeActionableCards, g as computeSettledLabel, h as composeQuestionAnswer, i as resolveAgent, j as getReviewStateDir, l as cardActionErrorMessage, m as resolveConnectUrl, p as reconcileMaskedInput, s as MASK_CHAR, u as parseExternalOauthConnectParams, v as specKeyFor } from "./print-DOGluqfs.mjs";
4
+ import { A as installAgentAlias, C as themeVersion, D as machineOsFromPlatform, F as detectShell, L as getActiveWorkspaceId, M as takenAliasNames, O as aliasActivationHint, S as themeModeFromColorFgBg, T as themesForMode, V as setActiveWorkspace, _ as monoTheme, a as WORDMARK, b as themeForMode, d as profilingEnabled, f as record, g as findTheme, h as applyTheme, i as MARK_CELLS, j as slugifyAliasName, k as dedupeAliasName, m as DEFAULT_THEME_ID, n as buildCrashReport, p as writeArtifact, r as writeCrashReport, s as splashFitsWidth, t as installCrashHandler, v as noColorRequested, x as themeMode, y as theme, z as listWorkspaces } from "./install-D4zmUhGt.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 { t as PortalClient } from "./client-CG6Ex3kN.mjs";
7
+ import { t as PortalClient } from "./client-C6nIuyAZ.mjs";
8
8
  import { t as defaultTlsCertSource } from "./tls-cert-Rua2oV7n.mjs";
9
9
  import "./api-BFQ4PQDA.mjs";
10
- import "./daemon-DN2YUdTA.mjs";
10
+ import "./daemon-DJLsd6X4.mjs";
11
11
  import { t as SandboxStream } from "./client-l6orYfqq.mjs";
12
- import { t as PortalDaemonClient } from "./daemon-client-DqJfdD6H.mjs";
12
+ import { t as PortalDaemonClient } from "./daemon-client-BPy3PPu_.mjs";
13
13
  import { t as runRawPtyPassthrough } from "./raw-pty-dndn1Kxc.mjs";
14
14
  import * as os$1 from "node:os";
15
15
  import { homedir, platform, release, tmpdir } from "node:os";
@@ -7628,6 +7628,8 @@ function subagentTaskTitles(input) {
7628
7628
  });
7629
7629
  }
7630
7630
  const QUEUED_TASK_ID_LINE = /^\s*-\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}):\s/i;
7631
+ const QUEUED_TASK_ID_PARENS = /\(taskId\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\)/i;
7632
+ const QUEUED_TASK_CONV_PREFIX = /^\s*-\s*conversation\s+([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}):\s/i;
7631
7633
  const QUEUED_TASK_CONVERSATION_TAIL = /peek:\s*conversations show ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\s*$/i;
7632
7634
  /**
7633
7635
  * The runs a `subagent` call queued, read back out of its own output. The
@@ -7640,11 +7642,11 @@ function queuedSubagentTasks(output) {
7640
7642
  if (!text) return [];
7641
7643
  const tasks = [];
7642
7644
  for (const line of text.split("\n")) {
7643
- const id = line.match(QUEUED_TASK_ID_LINE)?.[1];
7644
- if (!id) continue;
7645
+ const rawId = line.match(QUEUED_TASK_ID_PARENS)?.[1] ?? line.match(QUEUED_TASK_ID_LINE)?.[1];
7646
+ if (!rawId) continue;
7645
7647
  tasks.push({
7646
- id: id.toLowerCase(),
7647
- conversationId: line.match(QUEUED_TASK_CONVERSATION_TAIL)?.[1]?.toLowerCase() ?? null
7648
+ id: rawId.toLowerCase(),
7649
+ conversationId: (line.match(QUEUED_TASK_CONV_PREFIX)?.[1] ?? line.match(QUEUED_TASK_CONVERSATION_TAIL)?.[1])?.toLowerCase() ?? null
7648
7650
  });
7649
7651
  }
7650
7652
  return tasks;
@@ -8805,6 +8807,83 @@ function createResponsePreview() {
8805
8807
  };
8806
8808
  }
8807
8809
 
8810
+ //#endregion
8811
+ //#region src/chat/tui/side-panel-layout.ts
8812
+ /**
8813
+ * Layout policy for the chat side panel, split out of the component so it
8814
+ * stays testable without a renderer.
8815
+ *
8816
+ * The panel mimics OpenCode's sidebar: a fixed-width column docked on the
8817
+ * right of the chat, toggled by a keybind rather than shown automatically.
8818
+ * It renders only when the terminal has room for a usable chat strip next to
8819
+ * it; a cramped terminal keeps the toggle inert instead of squeezing the
8820
+ * conversation.
8821
+ */
8822
+ /** Fixed panel width, matching OpenCode's sidebar (42 cols minus padding). */
8823
+ const SIDE_PANEL_WIDTH = 40;
8824
+ /**
8825
+ * The narrowest terminal that can host the panel: panel width plus the
8826
+ * bare-minimum chat strip (30 cols) and app chrome (2 padding columns).
8827
+ */
8828
+ const SIDE_PANEL_MIN_WIDTH = SIDE_PANEL_WIDTH + 30 + 2;
8829
+ function sidePanelPlacement({ open, width }) {
8830
+ return open && width >= SIDE_PANEL_MIN_WIDTH ? "side" : "hidden";
8831
+ }
8832
+
8833
+ //#endregion
8834
+ //#region src/chat/tui/side-panel.tsx
8835
+ /**
8836
+ * The chat side panel: a fixed-width column docked on the right of the
8837
+ * conversation, modeled on OpenCode's sidebar (fixed width, background-color
8838
+ * separation instead of a border, full chat height, generous padding, a
8839
+ * blank row between sections). Toggled with ctrl+s; placement and room
8840
+ * checks live in side-panel-layout.ts.
8841
+ *
8842
+ * Sections are deliberately pluggable: the panel body is a stack of blocks,
8843
+ * so costs, computer stats, etc. land here later without re-touching the
8844
+ * chat.tsx layout.
8845
+ */
8846
+ function SidePanel({ open, width, height, agentName, title }) {
8847
+ if (sidePanelPlacement({
8848
+ open,
8849
+ width
8850
+ }) === "hidden") return null;
8851
+ themeVersion();
8852
+ return /* @__PURE__ */ jsx("box", {
8853
+ style: {
8854
+ width: SIDE_PANEL_WIDTH,
8855
+ height,
8856
+ backgroundColor: theme.surface,
8857
+ paddingLeft: 2,
8858
+ paddingRight: 2,
8859
+ paddingTop: 1,
8860
+ paddingBottom: 1,
8861
+ flexShrink: 0,
8862
+ flexDirection: "column"
8863
+ },
8864
+ children: /* @__PURE__ */ jsx("box", {
8865
+ style: {
8866
+ flexDirection: "column",
8867
+ gap: 2,
8868
+ flexShrink: 0
8869
+ },
8870
+ children: /* @__PURE__ */ jsxs("box", {
8871
+ style: {
8872
+ flexDirection: "column",
8873
+ flexShrink: 0
8874
+ },
8875
+ children: [/* @__PURE__ */ jsx("text", {
8876
+ fg: theme.fg,
8877
+ children: /* @__PURE__ */ jsx("b", { children: title || agentName })
8878
+ }), /* @__PURE__ */ jsx("text", {
8879
+ fg: theme.dim,
8880
+ children: agentName
8881
+ })]
8882
+ })
8883
+ })
8884
+ }, "side-panel");
8885
+ }
8886
+
8808
8887
  //#endregion
8809
8888
  //#region src/chat/tui/new-chat-splash.tsx
8810
8889
  /** Rows the splash art needs before it's worth painting: the 6-row mark, a
@@ -9064,6 +9143,10 @@ const keybindGroups = [
9064
9143
  keys: "ctrl+g",
9065
9144
  action: "toggle file review pane"
9066
9145
  },
9146
+ {
9147
+ keys: "ctrl+s",
9148
+ action: "toggle the side panel"
9149
+ },
9067
9150
  {
9068
9151
  keys: "exit",
9069
9152
  action: "quit (type it as a message)"
@@ -13996,6 +14079,7 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
13996
14079
  const goTo = useStore((s) => s.goTo);
13997
14080
  const drillTo = useStore((s) => s.drillTo);
13998
14081
  const setChatTitle = useStore((s) => s.setChatTitle);
14082
+ const chatTitle = useStore((s) => s.chatTitle);
13999
14083
  const workspaceName = useStore((s) => s.workspaceName);
14000
14084
  const portal = useStore((s) => s.portal);
14001
14085
  const portalClient = useStore((s) => s.portalClient);
@@ -14088,6 +14172,7 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
14088
14172
  const creditsSequenceRef = useRef(0);
14089
14173
  const [reviewOpen, setReviewOpen] = useState(false);
14090
14174
  const [reviewFocused, setReviewFocused] = useState(false);
14175
+ const [sidePanelOpen, setSidePanelOpen] = useState(false);
14091
14176
  const [reviewTab, setReviewTab] = useState("changes");
14092
14177
  const [reviewChangeFile, setReviewChangeFile] = useState(null);
14093
14178
  const [reviewSizePref, setReviewSizePref] = useState({
@@ -14245,6 +14330,11 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
14245
14330
  const reviewContentWidth = reviewPlacement === "side" ? Math.max(1, reviewWidth - 4) : reviewPlacement === "below" ? Math.max(1, bodyWidth - 4) : bodyWidth;
14246
14331
  const reviewContentHeight = reviewPlacement === "fullscreen" ? bodyHeight : Math.max(1, reviewHeight - 2);
14247
14332
  const chatHeight = bodyHeight;
14333
+ const sidePanelShown = reviewPlacement !== "fullscreen" && sidePanelPlacement({
14334
+ open: sidePanelOpen,
14335
+ width
14336
+ }) === "side";
14337
+ const sidePanelWidth = sidePanelShown ? SIDE_PANEL_WIDTH : 0;
14248
14338
  const inlineReviewHeight = reviewOpen && reviewPlacement === "below" ? reviewHeight : 0;
14249
14339
  const menuRows = menuOpen ? completionMenuHeight(menuCommands.length) : 0;
14250
14340
  const todoCardVisible = !credPrompt && !planHidden && !!todos && todos.length > 0;
@@ -15816,6 +15906,20 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
15816
15906
  setPortalPrompt
15817
15907
  ]);
15818
15908
  useKeyboard((key) => {
15909
+ if (key.name === "s" && key.ctrl) {
15910
+ if (!sidePanelOpen && sidePanelPlacement({
15911
+ open: true,
15912
+ width
15913
+ }) === "hidden") {
15914
+ useStore.getState().showToast({
15915
+ message: `terminal too narrow for the side panel (needs ${SIDE_PANEL_MIN_WIDTH} cols)`,
15916
+ variant: "warning"
15917
+ });
15918
+ return;
15919
+ }
15920
+ setSidePanelOpen((o) => !o);
15921
+ return;
15922
+ }
15819
15923
  if (reviewOpen) {
15820
15924
  if (key.name === "g" && key.ctrl) {
15821
15925
  if (reviewPlacement === "fullscreen" && !reviewFocused) setReviewFocused(true);
@@ -16358,7 +16462,7 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
16358
16462
  }) : items.length === 0 && !terminalReady ? /* @__PURE__ */ jsx("box", { style: { height: Math.max(1, scrollHeight - 1) } }) : items.length === 0 ? /* @__PURE__ */ jsx(NewChatSplash, {
16359
16463
  agentName: agent.name,
16360
16464
  agentTitle: agent.title ?? null,
16361
- width: reviewView && reviewPlacement === "side" ? Math.max(1, bodyWidth - reviewWidth - 1) : bodyWidth,
16465
+ width: reviewView && reviewPlacement === "side" ? Math.max(1, bodyWidth - reviewWidth - 1 - sidePanelWidth) : Math.max(1, bodyWidth - sidePanelWidth),
16362
16466
  height: Math.max(1, scrollHeight - 1)
16363
16467
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [transcriptWindow.hiddenCount > 0 ? /* @__PURE__ */ jsx("box", {
16364
16468
  style: {
@@ -16652,7 +16756,37 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
16652
16756
  value: conversationContext,
16653
16757
  children: chatViewBody
16654
16758
  });
16655
- if (!reviewView || reviewPlacement === "below") return chatView;
16759
+ if (!reviewView || reviewPlacement === "below") {
16760
+ if (!sidePanelShown) return chatView;
16761
+ return /* @__PURE__ */ jsxs("box", {
16762
+ style: {
16763
+ flexDirection: "row",
16764
+ flexGrow: 1,
16765
+ width: bodyWidth,
16766
+ height: chatHeight
16767
+ },
16768
+ children: [
16769
+ /* @__PURE__ */ jsx("box", {
16770
+ style: {
16771
+ flexGrow: 1,
16772
+ flexShrink: 1
16773
+ },
16774
+ children: chatView
16775
+ }),
16776
+ sidePanelShown ? /* @__PURE__ */ jsx("box", { style: {
16777
+ width: 2,
16778
+ flexShrink: 0
16779
+ } }) : null,
16780
+ sidePanelShown ? /* @__PURE__ */ jsx(SidePanel, {
16781
+ open: sidePanelOpen,
16782
+ width,
16783
+ height: bodyHeight,
16784
+ agentName: agent.name,
16785
+ title: chatTitle
16786
+ }) : null
16787
+ ]
16788
+ });
16789
+ }
16656
16790
  const fullscreen = reviewPlacement === "fullscreen";
16657
16791
  return /* @__PURE__ */ jsxs("box", {
16658
16792
  onMouseDown: (event) => {
@@ -16683,26 +16817,40 @@ function ChatScreen({ agent, conversation, attachRunId, parentConversationId })
16683
16817
  flexDirection: reviewPlacement === "side" ? "row" : "column",
16684
16818
  flexGrow: 1
16685
16819
  },
16686
- children: [!fullscreen || !reviewFocused ? /* @__PURE__ */ jsx("box", {
16687
- onMouseDown: () => setReviewFocused(false),
16688
- style: {
16689
- flexGrow: 1,
16690
- paddingRight: reviewPlacement === "side" ? 1 : 0
16691
- },
16692
- children: chatView
16693
- }, "chat") : null, !fullscreen || reviewFocused ? /* @__PURE__ */ jsx("box", {
16694
- ref: reviewSideBoxRef,
16695
- onMouseDown: () => setReviewFocused(true),
16696
- style: {
16697
- width: reviewPlacement === "side" ? reviewWidth : bodyWidth,
16820
+ children: [
16821
+ !fullscreen || !reviewFocused ? /* @__PURE__ */ jsx("box", {
16822
+ onMouseDown: () => setReviewFocused(false),
16823
+ style: {
16824
+ flexGrow: 1,
16825
+ paddingRight: reviewPlacement === "side" ? 1 : 0
16826
+ },
16827
+ children: chatView
16828
+ }, "chat") : null,
16829
+ !fullscreen || reviewFocused ? /* @__PURE__ */ jsx("box", {
16830
+ ref: reviewSideBoxRef,
16831
+ onMouseDown: () => setReviewFocused(true),
16832
+ style: {
16833
+ width: reviewPlacement === "side" ? reviewWidth : bodyWidth,
16834
+ height: bodyHeight,
16835
+ border: !fullscreen,
16836
+ borderColor: reviewFocused ? theme.accent : theme.faint,
16837
+ paddingLeft: fullscreen ? 0 : 1,
16838
+ paddingRight: fullscreen ? 0 : 1
16839
+ },
16840
+ children: reviewView
16841
+ }, "review") : null,
16842
+ sidePanelShown ? /* @__PURE__ */ jsx("box", { style: {
16843
+ width: 2,
16844
+ flexShrink: 0
16845
+ } }) : null,
16846
+ sidePanelShown ? /* @__PURE__ */ jsx(SidePanel, {
16847
+ open: sidePanelOpen,
16848
+ width,
16698
16849
  height: bodyHeight,
16699
- border: !fullscreen,
16700
- borderColor: reviewFocused ? theme.accent : theme.faint,
16701
- paddingLeft: fullscreen ? 0 : 1,
16702
- paddingRight: fullscreen ? 0 : 1
16703
- },
16704
- children: reviewView
16705
- }, "review") : null]
16850
+ agentName: agent.name,
16851
+ title: chatTitle
16852
+ }) : null
16853
+ ]
16706
16854
  });
16707
16855
  }
16708
16856
  /**
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { t as PortalClient } from "./client-C6nIuyAZ.mjs";
3
+ import "./api-BFQ4PQDA.mjs";
4
+
5
+ export { PortalClient };
@@ -160,7 +160,7 @@ function errorMessage(err) {
160
160
  * the commit time of the built tree is one monotonic clock they share.
161
161
  */
162
162
  function portalDaemonBuild() {
163
- return "1790118208";
163
+ return "1790189602";
164
164
  }
165
165
  /**
166
166
  * Whether a client carrying `mine` should replace a running daemon carrying
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import "./client-CG6Ex3kN.mjs";
2
+ import "./client-C6nIuyAZ.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-DN2YUdTA.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-DJLsd6X4.mjs";
6
6
 
7
7
  export { runPortalDaemon };
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as isRecord, n as isNewerBuild, r as portalDaemonBuild, t as PortalClient } from "./client-CG6Ex3kN.mjs";
2
+ import { i as isRecord, n as isNewerBuild, r as portalDaemonBuild, t as PortalClient } from "./client-C6nIuyAZ.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,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-DN2YUdTA.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-DJLsd6X4.mjs";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { connect } from "node:net";
5
5
 
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import "./client-C6nIuyAZ.mjs";
3
+ import "./tls-cert-Rua2oV7n.mjs";
4
+ import "./api-BFQ4PQDA.mjs";
5
+ import "./daemon-DJLsd6X4.mjs";
6
+ import { t as PortalDaemonClient } from "./daemon-client-BPy3PPu_.mjs";
7
+
8
+ export { PortalDaemonClient };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { c as version$1 } from "./rest-DRpmhj-Y.mjs";
3
- import { E as getConfigPath } from "./print-BNGt-DNP.mjs";
2
+ import { c as version$1 } from "./rest-D-QhD4Ey.mjs";
3
+ import { E as getConfigPath } from "./print-DOGluqfs.mjs";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { err, ok } from "neverthrow";
@@ -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-DRpmhj-Y.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, o as isRecord, t as createRestClient } from "./rest-D-QhD4Ey.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";
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import "./rest-DRpmhj-Y.mjs";
3
- import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-BNGt-DNP.mjs";
2
+ import "./rest-D-QhD4Ey.mjs";
3
+ import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-DOGluqfs.mjs";
4
4
  import "./billing-blocked-D3l5kJlX.mjs";
5
5
 
6
6
  export { messageGet, readStdin, resolveAgent, runPrint };
@@ -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-CH-83KyD.mjs");
17
+ const { PortalClient } = await import("./client-AlyJpq9J.mjs");
18
18
  const { defaultTlsCertSource } = await import("./tls-cert-BpCaD5AT.mjs");
19
19
  let signalConnected;
20
20
  const connected = new Promise((resolve) => {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { i as sendErrorMessage, n as errorDetail, r as filenameFromContentDisposition, t as createRestClient } from "./rest-DRpmhj-Y.mjs";
2
+ import { i as sendErrorMessage, n as errorDetail, r as filenameFromContentDisposition, t as createRestClient } from "./rest-D-QhD4Ey.mjs";
3
3
  import { t as HttpError } from "./http-error-BF2NZZE3.mjs";
4
4
  import "./billing-blocked-D3l5kJlX.mjs";
5
5
 
@@ -6,7 +6,7 @@ import { createParser } from "eventsource-parser";
6
6
 
7
7
  //#region package.json
8
8
  var name = "skydive-cli";
9
- var version = "0.6.0-beta.29";
9
+ var version = "0.6.0-beta.30";
10
10
 
11
11
  //#endregion
12
12
  //#region src/chat/util.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.6.0-beta.29",
3
+ "version": "0.6.0-beta.30",
4
4
  "description": "Skydive CLI — cloud agents from the command line",
5
5
  "homepage": "https://skydive.com",
6
6
  "license": "MIT",
@@ -71,9 +71,9 @@
71
71
  },
72
72
  "//optionalDependencies": "The per-platform binary packages (skydive-cli-<os>-<arch>) are INTENTIONALLY not committed here. They are published by release-skydive-cli-binaries.yml and injected — pinned to the exact version being published — into the published launcher's optionalDependencies at release time (scripts/prepare-platform-packages.mjs --pin-version, run in release-skydive-cli.yml). Committing them would make `yarn install` try to resolve versions that only exist post-publish, breaking local dev and CI. npm installs of a published skydive-cli still get them (os/cpu-gated); the launcher (src/launcher.ts) resolves and execs the matching one. Local dev never needs them: it runs the JS bundle or `build:binary` directly.",
73
73
  "optionalDependencies": {
74
- "skydive-cli-darwin-arm64": "0.6.0-beta.29",
75
- "skydive-cli-darwin-x64": "0.6.0-beta.29",
76
- "skydive-cli-linux-x64": "0.6.0-beta.29",
77
- "skydive-cli-linux-arm64": "0.6.0-beta.29"
74
+ "skydive-cli-darwin-arm64": "0.6.0-beta.30",
75
+ "skydive-cli-darwin-x64": "0.6.0-beta.30",
76
+ "skydive-cli-linux-x64": "0.6.0-beta.30",
77
+ "skydive-cli-linux-arm64": "0.6.0-beta.30"
78
78
  }
79
79
  }
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import { t as PortalClient } from "./client-CG6Ex3kN.mjs";
3
- import "./api-BFQ4PQDA.mjs";
4
-
5
- export { PortalClient };
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./client-CG6Ex3kN.mjs";
3
- import "./tls-cert-Rua2oV7n.mjs";
4
- import "./api-BFQ4PQDA.mjs";
5
- import "./daemon-DN2YUdTA.mjs";
6
- import { t as PortalDaemonClient } from "./daemon-client-DqJfdD6H.mjs";
7
-
8
- export { PortalDaemonClient };