skydive-cli 0.2.0-beta.583 → 0.2.0-beta.594
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/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
- Chat TUI sets the terminal title (OSC) to the live conversation title, so a terminal multiplexer (cmux, tmux, zellij) or window names its tab after the conversation. Follows renames from autoname, web, and Slack, and resets to a neutral default on exit.
|
|
13
13
|
- Every TUI screen (pickers included), not just chat, now drives the title, and inside cmux the workspace (sidebar entry) is renamed too via the cmux control socket. A workspace title you set by hand is left untouched. The tab and workspace title read title-first (title then agent name), while the in-app status bar stays agent-first.
|
|
14
|
+
- Notification and sidebar previews use the last text block of the reply (the answer, not the opening preamble) and render as plain text, stripping inline markdown so markers like asterisks and backticks no longer leak into the preview.
|
|
14
15
|
|
|
15
16
|
## [0.2.0] - 2026-07-29
|
|
16
17
|
|
package/dist/js/bin.mjs
CHANGED
|
@@ -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.
|
|
23
|
+
var version = "0.2.0-beta.594";
|
|
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-
|
|
1203
|
+
const { runChat } = await import("./boot-C-sSzYb6.mjs");
|
|
1204
1204
|
await runChat({
|
|
1205
1205
|
appUrl,
|
|
1206
1206
|
sessionToken: session.value.sessionToken,
|
|
@@ -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-
|
|
1514
|
+
const { runChat } = await import("./boot-C-sSzYb6.mjs");
|
|
1515
1515
|
await runChat({
|
|
1516
1516
|
appUrl,
|
|
1517
1517
|
sessionToken: session.value.sessionToken,
|
|
@@ -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-
|
|
1813
|
+
const { runWorkspacePicker } = await import("./boot-C-sSzYb6.mjs");
|
|
1814
1814
|
await runWorkspacePicker(session);
|
|
1815
1815
|
return;
|
|
1816
1816
|
}
|
|
@@ -2466,7 +2466,7 @@ function setupUpdateCheck(argv) {
|
|
|
2466
2466
|
|
|
2467
2467
|
//#endregion
|
|
2468
2468
|
//#region src/changelog.generated.ts
|
|
2469
|
-
const CHANGELOG_MD = "# Changelog\n\nAll notable changes to the Skydive CLI are documented here.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n\n- Chat TUI sets the terminal title (OSC) to the live conversation title, so a terminal multiplexer (cmux, tmux, zellij) or window names its tab after the conversation. Follows renames from autoname, web, and Slack, and resets to a neutral default on exit.\n- Every TUI screen (pickers included), not just chat, now drives the title, and inside cmux the workspace (sidebar entry) is renamed too via the cmux control socket. A workspace title you set by hand is left untouched. The tab and workspace title read title-first (title then agent name), while the in-app status bar stays agent-first.\n\n## [0.2.0] - 2026-07-29\n\n### Added\n\n**Sandbox & machine access**\n\n- Standalone `skydive sandbox` command for direct access to an agent's sandbox.\n- `/sandbox` in the chat TUI — live PTY session and one-shot command execution.\n- Headless machine sharing via `skydive portal`, with self-registering portal grants.\n- `shareMachineDefault` config key for always-on portal sharing.\n\n**Chat TUI**\n\n- File pane (`ctrl+g`) with Changes and Files tabs: a shared file tree plus source viewer and a workspace browser, mouse-resizable and responsive to terminal size.\n- Agent todo list rendered in the chat TUI, above the composer, mirroring the web chat's todo card.\n- Fuzzy finder in the conversation and agent pickers.\n- Slash-command autocomplete menu.\n- Paste or drag-and-drop any file into the composer; paste clipboard images with Cmd+V.\n- Run local shell commands with `!` in the composer.\n- Conversation recaps, streamed live title updates, and per-agent attribution on assistant turns.\n- Working timer rolls up into minutes and hours.\n- Conversation picker paginates past 50 conversations and shows only your own conversations.\n- Esc leaves a live run; typing `exit` quits the chat.\n- Cursor Dark theme.\n- Picker rows no longer overlap when a conversation title contains a newline, tab, or control character.\n\n**Headless & scripting**\n\n- Resume a conversation by id.\n- `conversations list` and `conversations show` for transcript reads.\n- `messages get`, with run recovery keyed on message id.\n- Connect cards surface in headless `-p` mode so a driving agent never gets stuck.\n\n**Authentication**\n\n- `skydive auth login` via the browser now auto-mints an API key, so one login yields both a chat session and a usable management credential. Management commands announce the key's pinned workspace when it drives them, so a workspace mismatch is visible at use time.\n- Workspace picker on the device authorization page.\n- Account and workspace identity shown in `auth status`.\n\n**Platform**\n\n- Standalone binary builds compiling the CLI into a per-target executable.\n- Interactive workspace switcher; management commands follow the active workspace.\n- Terminal host integrations and agent notifications.\n\n### Fixed\n\n- Transcript errors collapse to one line, click to expand (REST and portal errors keep their full body).\n- Dragged/pasted image file paths attach the file instead of inserting path text, including macOS paths with literal parentheses.\n- Bare URLs in chat markdown are hyperlinked so they survive text wrap.\n- Composer draft is preserved across TUI overlays.\n- Relative connect links resolve before opening the browser.\n- Numbered markdown headings render colored in the TUI.\n- Chat transcript pages by 75% of a screen; picker rows stay on one line.\n- Run starts push to the TUI over the conversation stream.\n- Security: remediated high-severity dependency findings and cleared tar/shell-quote CVEs.\n\n## [0.1.0] - 2026-07-21\n\nInitial public release: `skydive chat` TUI, agent and conversation management,\ndevice authorization, and headless `-p` mode.\n";
|
|
2469
|
+
const CHANGELOG_MD = "# Changelog\n\nAll notable changes to the Skydive CLI are documented here.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n\n### Added\n\n- Chat TUI sets the terminal title (OSC) to the live conversation title, so a terminal multiplexer (cmux, tmux, zellij) or window names its tab after the conversation. Follows renames from autoname, web, and Slack, and resets to a neutral default on exit.\n- Every TUI screen (pickers included), not just chat, now drives the title, and inside cmux the workspace (sidebar entry) is renamed too via the cmux control socket. A workspace title you set by hand is left untouched. The tab and workspace title read title-first (title then agent name), while the in-app status bar stays agent-first.\n- Notification and sidebar previews use the last text block of the reply (the answer, not the opening preamble) and render as plain text, stripping inline markdown so markers like asterisks and backticks no longer leak into the preview.\n\n## [0.2.0] - 2026-07-29\n\n### Added\n\n**Sandbox & machine access**\n\n- Standalone `skydive sandbox` command for direct access to an agent's sandbox.\n- `/sandbox` in the chat TUI — live PTY session and one-shot command execution.\n- Headless machine sharing via `skydive portal`, with self-registering portal grants.\n- `shareMachineDefault` config key for always-on portal sharing.\n\n**Chat TUI**\n\n- File pane (`ctrl+g`) with Changes and Files tabs: a shared file tree plus source viewer and a workspace browser, mouse-resizable and responsive to terminal size.\n- Agent todo list rendered in the chat TUI, above the composer, mirroring the web chat's todo card.\n- Fuzzy finder in the conversation and agent pickers.\n- Slash-command autocomplete menu.\n- Paste or drag-and-drop any file into the composer; paste clipboard images with Cmd+V.\n- Run local shell commands with `!` in the composer.\n- Conversation recaps, streamed live title updates, and per-agent attribution on assistant turns.\n- Working timer rolls up into minutes and hours.\n- Conversation picker paginates past 50 conversations and shows only your own conversations.\n- Esc leaves a live run; typing `exit` quits the chat.\n- Cursor Dark theme.\n- Picker rows no longer overlap when a conversation title contains a newline, tab, or control character.\n\n**Headless & scripting**\n\n- Resume a conversation by id.\n- `conversations list` and `conversations show` for transcript reads.\n- `messages get`, with run recovery keyed on message id.\n- Connect cards surface in headless `-p` mode so a driving agent never gets stuck.\n\n**Authentication**\n\n- `skydive auth login` via the browser now auto-mints an API key, so one login yields both a chat session and a usable management credential. Management commands announce the key's pinned workspace when it drives them, so a workspace mismatch is visible at use time.\n- Workspace picker on the device authorization page.\n- Account and workspace identity shown in `auth status`.\n\n**Platform**\n\n- Standalone binary builds compiling the CLI into a per-target executable.\n- Interactive workspace switcher; management commands follow the active workspace.\n- Terminal host integrations and agent notifications.\n\n### Fixed\n\n- Transcript errors collapse to one line, click to expand (REST and portal errors keep their full body).\n- Dragged/pasted image file paths attach the file instead of inserting path text, including macOS paths with literal parentheses.\n- Bare URLs in chat markdown are hyperlinked so they survive text wrap.\n- Composer draft is preserved across TUI overlays.\n- Relative connect links resolve before opening the browser.\n- Numbered markdown headings render colored in the TUI.\n- Chat transcript pages by 75% of a screen; picker rows stay on one line.\n- Run starts push to the TUI over the conversation stream.\n- Security: remediated high-severity dependency findings and cleared tar/shell-quote CVEs.\n\n## [0.1.0] - 2026-07-21\n\nInitial public release: `skydive chat` TUI, agent and conversation management,\ndevice authorization, and headless `-p` mode.\n";
|
|
2470
2470
|
|
|
2471
2471
|
//#endregion
|
|
2472
2472
|
//#region src/whats-new.ts
|
|
@@ -4368,9 +4368,29 @@ function formatShare(share) {
|
|
|
4368
4368
|
//#region src/chat/notification-preview.ts
|
|
4369
4369
|
const MAX_NOTIFICATION_PREVIEW_CHARS = 240;
|
|
4370
4370
|
/**
|
|
4371
|
+
* Flattens common inline markdown to plain text for a notification / sidebar
|
|
4372
|
+
* preview, which renders as raw text (no markdown). Without this the preview
|
|
4373
|
+
* shows literal `**bold**` and `*italic*` markers. Intentionally lightweight —
|
|
4374
|
+
* not a full parser, just the inline markers that show up in a one-line
|
|
4375
|
+
* preview: emphasis, inline code, links/images, headings, blockquotes, and
|
|
4376
|
+
* list bullets. Block structure is already gone by the time we preview (we
|
|
4377
|
+
* collapse whitespace to a single line).
|
|
4378
|
+
*/
|
|
4379
|
+
function stripInlineMarkdown(input) {
|
|
4380
|
+
return input.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/(\*\*\*|\*\*|\*|___|__|_)(?=\S)(.*?\S)\1/g, "$2").replace(/(\*\*\*|\*\*|\*|___|__|_)(?=\S)(.*?\S)\1/g, "$2").replace(/~~(?=\S)(.*?\S)~~/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/^\s{0,3}>\s?/gm, "").replace(/^\s{0,3}(?:[-*+]|\d+\.)\s+/gm, "");
|
|
4381
|
+
}
|
|
4382
|
+
/**
|
|
4371
4383
|
* Collects assistant `text-delta` chunks for one run and turns them into a
|
|
4372
|
-
*
|
|
4384
|
+
* notification/side-panel-sized preview. Reasoning, tool output, cards, errors,
|
|
4373
4385
|
* and old transcript items are intentionally excluded.
|
|
4386
|
+
*
|
|
4387
|
+
* A run is a sequence of text parts split by tool calls and reasoning
|
|
4388
|
+
* (text → tool → text → … → final text). The meaningful summary of a run is
|
|
4389
|
+
* its **last** text part: the closing answer the agent lands on after all its
|
|
4390
|
+
* tool work, not the "let me look into this…" preamble it opened with. So the
|
|
4391
|
+
* preview keeps only the final part's text, and when that part is longer than
|
|
4392
|
+
* the cap it keeps the **beginning** with a trailing ellipsis (the
|
|
4393
|
+
* conventional truncation) — the block already opens on the answer.
|
|
4374
4394
|
*/
|
|
4375
4395
|
function createResponsePreview() {
|
|
4376
4396
|
let text = "";
|
|
@@ -4380,12 +4400,12 @@ function createResponsePreview() {
|
|
|
4380
4400
|
if (chunk.type !== "text-delta") return;
|
|
4381
4401
|
const delta = typeof chunk.delta === "string" ? chunk.delta : typeof chunk.text === "string" ? chunk.text : "";
|
|
4382
4402
|
const partId = typeof chunk.id === "string" ? chunk.id : void 0;
|
|
4383
|
-
if (
|
|
4403
|
+
if (partId && lastPartId && partId !== lastPartId) text = "";
|
|
4384
4404
|
text += delta;
|
|
4385
4405
|
lastPartId = partId ?? lastPartId;
|
|
4386
4406
|
},
|
|
4387
4407
|
get() {
|
|
4388
|
-
const normalized = text.replace(/\s+/g, " ").trim();
|
|
4408
|
+
const normalized = stripInlineMarkdown(text).replace(/\s+/g, " ").trim();
|
|
4389
4409
|
if (!normalized) return void 0;
|
|
4390
4410
|
const characters = Array.from(normalized);
|
|
4391
4411
|
if (characters.length <= MAX_NOTIFICATION_PREVIEW_CHARS) return normalized;
|
|
@@ -5189,6 +5209,13 @@ const slashCommands = [
|
|
|
5189
5209
|
description: "copy the agent's last message to the clipboard",
|
|
5190
5210
|
action: { kind: "copy" }
|
|
5191
5211
|
},
|
|
5212
|
+
{
|
|
5213
|
+
name: "portal",
|
|
5214
|
+
aliases: ["local"],
|
|
5215
|
+
argsHint: null,
|
|
5216
|
+
description: "allow this agent to access your computer",
|
|
5217
|
+
action: { kind: "portal" }
|
|
5218
|
+
},
|
|
5192
5219
|
{
|
|
5193
5220
|
name: "help",
|
|
5194
5221
|
aliases: [],
|
|
@@ -8248,6 +8275,7 @@ function routeInput(raw) {
|
|
|
8248
8275
|
case "browser":
|
|
8249
8276
|
case "connect":
|
|
8250
8277
|
case "copy":
|
|
8278
|
+
case "portal":
|
|
8251
8279
|
case "help":
|
|
8252
8280
|
case "quit": return { kind: action.kind };
|
|
8253
8281
|
default: {
|
|
@@ -9426,6 +9454,48 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9426
9454
|
setPortalPrompt(null);
|
|
9427
9455
|
useStore.getState().showToast({ message: "kept this machine private" });
|
|
9428
9456
|
}, [agent.id, setPortalPrompt]);
|
|
9457
|
+
const openPortalAccess = useCallback(() => {
|
|
9458
|
+
if (!portalClient) {
|
|
9459
|
+
useStore.getState().showToast({ message: "local access is unavailable in this session" });
|
|
9460
|
+
return;
|
|
9461
|
+
}
|
|
9462
|
+
switch (portal.status) {
|
|
9463
|
+
case "off":
|
|
9464
|
+
declinedRef.current.delete(agent.id);
|
|
9465
|
+
portalClient.enable();
|
|
9466
|
+
useStore.getState().showToast({ message: "enabling local access on this machine…" });
|
|
9467
|
+
break;
|
|
9468
|
+
case "connecting":
|
|
9469
|
+
useStore.getState().showToast({ message: "local access is still connecting…" });
|
|
9470
|
+
break;
|
|
9471
|
+
case "connected":
|
|
9472
|
+
if (portal.grantedAgentIds.includes(agent.id)) {
|
|
9473
|
+
useStore.getState().showToast({ message: `${agent.name} can already run commands on this machine` });
|
|
9474
|
+
break;
|
|
9475
|
+
}
|
|
9476
|
+
declinedRef.current.delete(agent.id);
|
|
9477
|
+
setPortalPrompt({
|
|
9478
|
+
agentId: agent.id,
|
|
9479
|
+
agentName: agent.name
|
|
9480
|
+
});
|
|
9481
|
+
break;
|
|
9482
|
+
case "error":
|
|
9483
|
+
useStore.getState().showToast({ message: portal.error ? `local access error: ${portal.error}` : "local access hit an error" });
|
|
9484
|
+
break;
|
|
9485
|
+
default: {
|
|
9486
|
+
const exhaustive = portal.status;
|
|
9487
|
+
throw new Error(`unhandled portal status: ${String(exhaustive)}`);
|
|
9488
|
+
}
|
|
9489
|
+
}
|
|
9490
|
+
}, [
|
|
9491
|
+
portalClient,
|
|
9492
|
+
portal.status,
|
|
9493
|
+
portal.grantedAgentIds,
|
|
9494
|
+
portal.error,
|
|
9495
|
+
agent.id,
|
|
9496
|
+
agent.name,
|
|
9497
|
+
setPortalPrompt
|
|
9498
|
+
]);
|
|
9429
9499
|
const executeLine = useCallback((content, staged) => {
|
|
9430
9500
|
if (!content && staged.length === 0) return;
|
|
9431
9501
|
const routed = routeInput(content);
|
|
@@ -9511,6 +9581,9 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9511
9581
|
case "copy":
|
|
9512
9582
|
copyLastMessage();
|
|
9513
9583
|
break;
|
|
9584
|
+
case "portal":
|
|
9585
|
+
openPortalAccess();
|
|
9586
|
+
break;
|
|
9514
9587
|
case "connect":
|
|
9515
9588
|
if (!promptForCards()) useStore.getState().showToast({ message: "no connect card waiting for action" });
|
|
9516
9589
|
break;
|
|
@@ -9544,6 +9617,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9544
9617
|
toggleShare,
|
|
9545
9618
|
openInBrowser,
|
|
9546
9619
|
copyLastMessage,
|
|
9620
|
+
openPortalAccess,
|
|
9547
9621
|
quit,
|
|
9548
9622
|
sendContent,
|
|
9549
9623
|
goTo,
|