skydive-cli 0.3.0 → 0.4.0
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 +27 -0
- package/README.md +28 -2
- package/dist/js/billing-blocked-CwfG1BTR.mjs +71 -0
- package/dist/js/billing-blocked-euid6MN9.mjs +4 -0
- package/dist/js/bin.mjs +247 -89
- package/dist/js/{boot-HAgDg_b4.mjs → boot-on5ucI_Z.mjs} +228 -50
- package/dist/js/chat/tui/chunks/grammars/assets/bash.highlights.scm +56 -0
- package/dist/js/chat/tui/chunks/grammars/assets/bash.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/c.highlights.scm +81 -0
- package/dist/js/chat/tui/chunks/grammars/assets/c.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/cpp.highlights.scm +70 -0
- package/dist/js/chat/tui/chunks/grammars/assets/cpp.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/css.highlights.scm +76 -0
- package/dist/js/chat/tui/chunks/grammars/assets/css.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/go.highlights.scm +123 -0
- package/dist/js/chat/tui/chunks/grammars/assets/go.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/html.highlights.scm +13 -0
- package/dist/js/chat/tui/chunks/grammars/assets/html.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/java.highlights.scm +149 -0
- package/dist/js/chat/tui/chunks/grammars/assets/java.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/json.highlights.scm +16 -0
- package/dist/js/chat/tui/chunks/grammars/assets/json.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/lua.highlights.scm +201 -0
- package/dist/js/chat/tui/chunks/grammars/assets/lua.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/python.highlights.scm +137 -0
- package/dist/js/chat/tui/chunks/grammars/assets/python.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/ruby.highlights.scm +154 -0
- package/dist/js/chat/tui/chunks/grammars/assets/ruby.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/rust.highlights.scm +161 -0
- package/dist/js/chat/tui/chunks/grammars/assets/rust.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/toml.highlights.scm +53 -0
- package/dist/js/chat/tui/chunks/grammars/assets/toml.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/yaml.highlights.scm +79 -0
- package/dist/js/chat/tui/chunks/grammars/assets/yaml.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/grammars.ts +146 -0
- package/dist/js/{client-Dc7GZ3PG.mjs → client-CKzK-12y.mjs} +1 -1
- package/dist/js/client-D6apKmV0.mjs +6 -0
- package/dist/js/daemon-BADmpJAs.mjs +7 -0
- package/dist/js/{daemon-Co4CtpXZ.mjs → daemon-CaFz7Wtw.mjs} +2 -2
- package/dist/js/{install-CMYBFvR2.mjs → install-Ba-UTi-l.mjs} +2 -2
- package/dist/js/{print-CPCFci60.mjs → print-BXNq9UxE.mjs} +3 -2
- package/dist/js/{print-Cd-bVSEJ.mjs → print-X2N5wJ5l.mjs} +84 -2
- package/dist/js/{print-share-7qfpQtWK.mjs → print-share-D72CfWJk.mjs} +1 -1
- package/dist/js/{raw-pty-BcjbTjHJ.mjs → raw-pty-DAmb8uqt.mjs} +1 -1
- package/dist/js/raw-pty-t5DC-e1T.mjs +5 -0
- package/dist/js/rest-Br2eFTlj.mjs +5 -0
- package/dist/js/{rest-BlN_uWmL.mjs → rest-imDZZGQA.mjs} +10 -2
- package/package.json +1 -1
- package/dist/js/client-DuwxEDG4.mjs +0 -5
- package/dist/js/daemon-Ch_MSDmQ.mjs +0 -6
- package/dist/js/raw-pty-ChUHav4d.mjs +0 -5
- package/dist/js/rest-CDTXCmUb.mjs +0 -4
- /package/dist/js/{client-DfcJFEbh.mjs → client-D8s9vY4p.mjs} +0 -0
package/dist/js/bin.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as setActiveWorkspace, S as listWorkspaces, T as version, _ as themes, b as getActiveWorkspaceId, o as brandHelpArt, t as installCrashHandler, w as name, x as getSessionIdentity, y as ensureActiveOrganization } from "./install-
|
|
3
|
-
import { A as
|
|
2
|
+
import { C as setActiveWorkspace, S as listWorkspaces, T as version, _ as themes, b as getActiveWorkspaceId, o as brandHelpArt, t as installCrashHandler, w as name, x as getSessionIdentity, y as ensureActiveOrganization } from "./install-Ba-UTi-l.mjs";
|
|
3
|
+
import { A as getStoredApiKeyWorkspaceName, C as getLastSeenVersion, F as resolveManagementAuth, I as resolveSession, M as resolveAppUrl, N as resolveChatAuth, O as getShareMachineDefault, P as resolveConfig, R as saveConfig, S as getConfigPath, T as getPromptHistoryPath, V as setLastSeenVersion, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getUpdateCheckDisabled, k as getStoredApiKeyId, v as DEFAULT_API_URL, w as getPreference, x as deleteConfig, z as saveSession } from "./print-X2N5wJ5l.mjs";
|
|
4
4
|
import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
|
|
5
|
-
import { n as createRestClient, t as HttpError } from "./rest-
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { n as createRestClient, t as HttpError } from "./rest-imDZZGQA.mjs";
|
|
6
|
+
import "./billing-blocked-CwfG1BTR.mjs";
|
|
7
|
+
import { a as registerPortalDevice, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice, s as machineIdentity } from "./client-CKzK-12y.mjs";
|
|
8
|
+
import { c as PORTAL_DAEMON_FLAG, i as queryDaemonStatus, l as daemonPaths, n as ensureDaemonRunning, o as stopDaemon } from "./daemon-CaFz7Wtw.mjs";
|
|
9
|
+
import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
|
|
9
10
|
import { hideBin } from "yargs/helpers";
|
|
10
11
|
import yargs from "yargs";
|
|
11
12
|
import os, { hostname } from "node:os";
|
|
@@ -72,31 +73,24 @@ var SkydiveApiClient = class {
|
|
|
72
73
|
this.authKind = config.kind;
|
|
73
74
|
}
|
|
74
75
|
/**
|
|
75
|
-
* List agents in the caller's workspace
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* roster continues past what was returned.
|
|
76
|
+
* List one page of agents in the caller's workspace. The server caps a
|
|
77
|
+
* page at {@link MAX_AGENT_PAGE}, so `limit` is clamped to that. Callers
|
|
78
|
+
* page forward by passing the returned `nextCursor` back in as `cursor`;
|
|
79
|
+
* `nextCursor` is null once the roster is exhausted.
|
|
80
80
|
*/
|
|
81
81
|
async listAgents(params) {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
schema: ListAgentsResponseSchema
|
|
92
|
-
});
|
|
93
|
-
if (page.isErr()) return err(page.error);
|
|
94
|
-
agents.push(...page.value.agents);
|
|
95
|
-
cursor = page.value.nextCursor;
|
|
96
|
-
} while (cursor && agents.length < params.limit);
|
|
82
|
+
const query = new URLSearchParams({ limit: String(Math.min(MAX_AGENT_PAGE, params.limit)) });
|
|
83
|
+
if (params.scope) query.set("scope", params.scope);
|
|
84
|
+
if (params.cursor) query.set("cursor", params.cursor);
|
|
85
|
+
const page = await this.request({
|
|
86
|
+
method: "GET",
|
|
87
|
+
path: `/agents?${query.toString()}`,
|
|
88
|
+
schema: ListAgentsResponseSchema
|
|
89
|
+
});
|
|
90
|
+
if (page.isErr()) return err(page.error);
|
|
97
91
|
return ok({
|
|
98
|
-
agents,
|
|
99
|
-
|
|
92
|
+
agents: page.value.agents,
|
|
93
|
+
nextCursor: page.value.nextCursor
|
|
100
94
|
});
|
|
101
95
|
}
|
|
102
96
|
async getAgent(id) {
|
|
@@ -1047,22 +1041,29 @@ function requireManagementClient(argv) {
|
|
|
1047
1041
|
}
|
|
1048
1042
|
/** Resolve the session (see {@link requireSession}) and build a REST client. */
|
|
1049
1043
|
function requireRestClient(argv) {
|
|
1050
|
-
const
|
|
1044
|
+
const auth = resolveChatAuth({ appUrl: resolveAppUrl({ appUrl: argv["api-url"] }) });
|
|
1045
|
+
if (auth.isErr()) {
|
|
1046
|
+
printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
1047
|
+
process.exit(1);
|
|
1048
|
+
}
|
|
1051
1049
|
return createRestClient({
|
|
1052
|
-
appUrl:
|
|
1053
|
-
sessionToken:
|
|
1050
|
+
appUrl: auth.value.appUrl,
|
|
1051
|
+
sessionToken: auth.value.token
|
|
1054
1052
|
});
|
|
1055
1053
|
}
|
|
1056
1054
|
|
|
1057
1055
|
//#endregion
|
|
1058
1056
|
//#region src/commands/agents.ts
|
|
1059
|
-
const listCommand$
|
|
1057
|
+
const listCommand$5 = {
|
|
1060
1058
|
command: "list",
|
|
1061
1059
|
describe: "List agents in the active workspace",
|
|
1062
1060
|
builder: (y) => y.option("limit", {
|
|
1063
1061
|
type: "number",
|
|
1064
1062
|
default: 20,
|
|
1065
|
-
describe: "
|
|
1063
|
+
describe: "Results per page"
|
|
1064
|
+
}).option("cursor", {
|
|
1065
|
+
type: "string",
|
|
1066
|
+
describe: "Page token from a previous list to fetch the next page"
|
|
1066
1067
|
}).option("scope", {
|
|
1067
1068
|
type: "string",
|
|
1068
1069
|
choices: ["mine", "org"],
|
|
@@ -1071,15 +1072,19 @@ const listCommand$4 = {
|
|
|
1071
1072
|
handler: async (argv) => {
|
|
1072
1073
|
const result = await requireManagementClient(argv).listAgents({
|
|
1073
1074
|
limit: argv.limit,
|
|
1074
|
-
scope: argv.scope ?? null
|
|
1075
|
+
scope: argv.scope ?? null,
|
|
1076
|
+
cursor: argv.cursor
|
|
1075
1077
|
});
|
|
1076
1078
|
if (result.isErr()) {
|
|
1077
1079
|
printError(result.error.message);
|
|
1078
1080
|
process.exit(1);
|
|
1079
1081
|
}
|
|
1080
|
-
const { agents,
|
|
1082
|
+
const { agents, nextCursor } = result.value;
|
|
1081
1083
|
if (argv.json) {
|
|
1082
|
-
output(argv,
|
|
1084
|
+
output(argv, {
|
|
1085
|
+
agents,
|
|
1086
|
+
nextCursor
|
|
1087
|
+
});
|
|
1083
1088
|
return;
|
|
1084
1089
|
}
|
|
1085
1090
|
if (agents.length === 0) {
|
|
@@ -1088,7 +1093,7 @@ const listCommand$4 = {
|
|
|
1088
1093
|
}
|
|
1089
1094
|
const { headers, rows } = buildAgentTable(agents);
|
|
1090
1095
|
printTable(headers, rows);
|
|
1091
|
-
if (
|
|
1096
|
+
if (nextCursor && !argv.quiet) console.log(`\nMore results. Next page: --cursor ${nextCursor}`);
|
|
1092
1097
|
}
|
|
1093
1098
|
};
|
|
1094
1099
|
const DESCRIPTION_MAX = 48;
|
|
@@ -1131,7 +1136,7 @@ function truncate(value, max) {
|
|
|
1131
1136
|
if (trimmed.length <= max) return trimmed || "-";
|
|
1132
1137
|
return `${trimmed.slice(0, max - 1)}\u2026`;
|
|
1133
1138
|
}
|
|
1134
|
-
const getCommand$
|
|
1139
|
+
const getCommand$2 = {
|
|
1135
1140
|
command: "get <id>",
|
|
1136
1141
|
describe: "Get agent details",
|
|
1137
1142
|
builder: (y) => y.positional("id", {
|
|
@@ -1201,7 +1206,7 @@ const createCommand$1 = {
|
|
|
1201
1206
|
const agentsCommand = {
|
|
1202
1207
|
command: "agents",
|
|
1203
1208
|
describe: "Manage agents",
|
|
1204
|
-
builder: (y) => y.command(listCommand$
|
|
1209
|
+
builder: (y) => y.command(listCommand$5).command(getCommand$2).command(createCommand$1).demandCommand(1, "Specify a subcommand: list, get, create"),
|
|
1205
1210
|
handler: () => {}
|
|
1206
1211
|
};
|
|
1207
1212
|
|
|
@@ -1500,7 +1505,7 @@ const importCommand = {
|
|
|
1500
1505
|
process.exit(1);
|
|
1501
1506
|
}
|
|
1502
1507
|
}
|
|
1503
|
-
const { runChat } = await import("./boot-
|
|
1508
|
+
const { runChat } = await import("./boot-on5ucI_Z.mjs");
|
|
1504
1509
|
await runChat({
|
|
1505
1510
|
appUrl,
|
|
1506
1511
|
sessionToken: session.value.sessionToken,
|
|
@@ -1527,7 +1532,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1527
1532
|
printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
1528
1533
|
process.exit(1);
|
|
1529
1534
|
}
|
|
1530
|
-
const { connectMachineShare } = await import("./print-share-
|
|
1535
|
+
const { connectMachineShare } = await import("./print-share-D72CfWJk.mjs");
|
|
1531
1536
|
const machineShare = await connectMachineShare({
|
|
1532
1537
|
appUrl,
|
|
1533
1538
|
sessionToken: session.value.sessionToken,
|
|
@@ -1535,7 +1540,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1535
1540
|
});
|
|
1536
1541
|
const extra = (argv.print ?? "").trim();
|
|
1537
1542
|
const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
|
|
1538
|
-
const { runPrint } = await import("./print-
|
|
1543
|
+
const { runPrint } = await import("./print-BXNq9UxE.mjs");
|
|
1539
1544
|
try {
|
|
1540
1545
|
const result = await runPrint({
|
|
1541
1546
|
appUrl,
|
|
@@ -1559,7 +1564,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1559
1564
|
|
|
1560
1565
|
//#endregion
|
|
1561
1566
|
//#region src/commands/keys.ts
|
|
1562
|
-
const listCommand$
|
|
1567
|
+
const listCommand$4 = {
|
|
1563
1568
|
command: "list",
|
|
1564
1569
|
describe: "List API keys for an agent",
|
|
1565
1570
|
handler: async (argv) => {
|
|
@@ -1648,7 +1653,7 @@ const keysCommand = {
|
|
|
1648
1653
|
type: "string",
|
|
1649
1654
|
demandOption: true,
|
|
1650
1655
|
describe: "Agent ID"
|
|
1651
|
-
}).command(listCommand$
|
|
1656
|
+
}).command(listCommand$4).command(createCommand).command(revokeCommand$1).demandCommand(1, "Specify a subcommand: list, create, revoke"),
|
|
1652
1657
|
handler: () => {}
|
|
1653
1658
|
};
|
|
1654
1659
|
|
|
@@ -1660,7 +1665,7 @@ async function readStdin() {
|
|
|
1660
1665
|
for await (const chunk of process.stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1661
1666
|
return Buffer.concat(chunks).toString("utf8").replace(/\n$/, "");
|
|
1662
1667
|
}
|
|
1663
|
-
const listCommand$
|
|
1668
|
+
const listCommand$3 = {
|
|
1664
1669
|
command: "list",
|
|
1665
1670
|
describe: "List secret names for an agent (values are never shown)",
|
|
1666
1671
|
handler: async (argv) => {
|
|
@@ -1681,7 +1686,7 @@ const listCommand$2 = {
|
|
|
1681
1686
|
printTable(["Name"], keys.map((k) => [k]));
|
|
1682
1687
|
}
|
|
1683
1688
|
};
|
|
1684
|
-
const setCommand = {
|
|
1689
|
+
const setCommand$1 = {
|
|
1685
1690
|
command: "set <key> [value]",
|
|
1686
1691
|
describe: "Set (create or overwrite) a secret. Reads value from stdin if omitted.",
|
|
1687
1692
|
builder: (y) => y.positional("key", {
|
|
@@ -1746,7 +1751,7 @@ const secretsCommand = {
|
|
|
1746
1751
|
type: "string",
|
|
1747
1752
|
demandOption: true,
|
|
1748
1753
|
describe: "Agent ID"
|
|
1749
|
-
}).command(listCommand$
|
|
1754
|
+
}).command(listCommand$3).command(setCommand$1).command(rmCommand).demandCommand(1, "Specify a subcommand: list, set, rm"),
|
|
1750
1755
|
handler: () => {}
|
|
1751
1756
|
};
|
|
1752
1757
|
|
|
@@ -1885,10 +1890,10 @@ const chatCommand = {
|
|
|
1885
1890
|
printError(`chat needs the Bun runtime and it couldn't be set up automatically (no network, an unsupported platform, or a failed download). Install Bun (https://bun.sh) and run chat under it, e.g. \`bun ${process.argv[1] ?? "skydive"} chat\`, or point SKYDIVE_BUN_PATH at an existing bun binary. For a non-interactive one-shot that runs under Node, use \`chat -p "<prompt>"\`.`);
|
|
1886
1891
|
process.exit(1);
|
|
1887
1892
|
}
|
|
1888
|
-
let
|
|
1889
|
-
if (
|
|
1893
|
+
let auth = resolveChatAuth({ appUrl });
|
|
1894
|
+
if (auth.isErr()) {
|
|
1890
1895
|
if (isNonInteractive()) {
|
|
1891
|
-
printError("Not signed in
|
|
1896
|
+
printError("Not signed in and no interactive terminal. Run `skydive auth login`, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.");
|
|
1892
1897
|
process.exit(1);
|
|
1893
1898
|
}
|
|
1894
1899
|
const login = await loginWithDevice({ appUrl });
|
|
@@ -1896,8 +1901,8 @@ const chatCommand = {
|
|
|
1896
1901
|
printError(login.error.message);
|
|
1897
1902
|
process.exit(1);
|
|
1898
1903
|
}
|
|
1899
|
-
|
|
1900
|
-
if (
|
|
1904
|
+
auth = resolveChatAuth({ appUrl });
|
|
1905
|
+
if (auth.isErr()) {
|
|
1901
1906
|
printError("Signed in, but no session was stored.");
|
|
1902
1907
|
process.exit(1);
|
|
1903
1908
|
}
|
|
@@ -1909,13 +1914,14 @@ const chatCommand = {
|
|
|
1909
1914
|
}
|
|
1910
1915
|
await ensureAgentWorkspace({
|
|
1911
1916
|
appUrl,
|
|
1912
|
-
sessionToken:
|
|
1917
|
+
sessionToken: auth.value.token,
|
|
1913
1918
|
agentSelector: argv.agent ?? null
|
|
1914
1919
|
});
|
|
1915
|
-
const { runChat } = await import("./boot-
|
|
1920
|
+
const { runChat } = await import("./boot-on5ucI_Z.mjs");
|
|
1916
1921
|
await runChat({
|
|
1917
|
-
appUrl,
|
|
1918
|
-
sessionToken:
|
|
1922
|
+
appUrl: auth.value.appUrl,
|
|
1923
|
+
sessionToken: auth.value.token,
|
|
1924
|
+
authKind: auth.value.kind,
|
|
1919
1925
|
shareMachine: resolveShareMachine(argv),
|
|
1920
1926
|
promptHistoryPath: getPromptHistoryPath(),
|
|
1921
1927
|
theme: themeId,
|
|
@@ -1973,15 +1979,15 @@ async function ensureAgentWorkspace({ appUrl, sessionToken, agentSelector }) {
|
|
|
1973
1979
|
process.exit(1);
|
|
1974
1980
|
}
|
|
1975
1981
|
async function runPrintMode({ argv, appUrl }) {
|
|
1976
|
-
const
|
|
1977
|
-
if (
|
|
1978
|
-
printError(`${
|
|
1982
|
+
const auth = resolveChatAuth({ appUrl });
|
|
1983
|
+
if (auth.isErr()) {
|
|
1984
|
+
printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
1979
1985
|
process.exit(1);
|
|
1980
1986
|
}
|
|
1981
|
-
const { runPrint, readStdin } = await import("./print-
|
|
1987
|
+
const { runPrint, readStdin } = await import("./print-BXNq9UxE.mjs");
|
|
1982
1988
|
await ensureAgentWorkspace({
|
|
1983
1989
|
appUrl,
|
|
1984
|
-
sessionToken:
|
|
1990
|
+
sessionToken: auth.value.token,
|
|
1985
1991
|
agentSelector: argv.agent ?? null
|
|
1986
1992
|
});
|
|
1987
1993
|
let prompt = (argv.print ?? "").trim();
|
|
@@ -1997,18 +2003,23 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
1997
2003
|
}
|
|
1998
2004
|
}
|
|
1999
2005
|
let machineShare = null;
|
|
2000
|
-
if (resolveShareMachine(argv)) {
|
|
2001
|
-
|
|
2006
|
+
if (resolveShareMachine(argv)) if (auth.value.kind === "api-key") {
|
|
2007
|
+
if (argv["share-machine"] === true) {
|
|
2008
|
+
printError("Machine sharing needs a browser session (API keys cannot grant local access). Run `skydive auth login --web` first, or re-run with --no-share-machine.");
|
|
2009
|
+
process.exit(1);
|
|
2010
|
+
}
|
|
2011
|
+
} else {
|
|
2012
|
+
const { connectMachineShare } = await import("./print-share-D72CfWJk.mjs");
|
|
2002
2013
|
machineShare = await connectMachineShare({
|
|
2003
|
-
appUrl,
|
|
2004
|
-
sessionToken:
|
|
2014
|
+
appUrl: auth.value.appUrl,
|
|
2015
|
+
sessionToken: auth.value.token,
|
|
2005
2016
|
timeoutHint: "Re-run with --no-share-machine (or unset `shareMachineDefault` in the CLI config), or check `skydive portal status`."
|
|
2006
2017
|
});
|
|
2007
2018
|
}
|
|
2008
2019
|
try {
|
|
2009
2020
|
const result = await runPrint({
|
|
2010
|
-
appUrl,
|
|
2011
|
-
sessionToken:
|
|
2021
|
+
appUrl: auth.value.appUrl,
|
|
2022
|
+
sessionToken: auth.value.token,
|
|
2012
2023
|
prompt,
|
|
2013
2024
|
agentSelector: argv.agent ?? null,
|
|
2014
2025
|
conversationId: argv.conversation ?? null,
|
|
@@ -2018,6 +2029,12 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
2018
2029
|
});
|
|
2019
2030
|
if (argv.json) output(argv, result);
|
|
2020
2031
|
} catch (error) {
|
|
2032
|
+
const { BillingBlockedError, BILLING_BLOCKED_EXIT_CODE, billingBlockedJsonResult } = await import("./billing-blocked-euid6MN9.mjs");
|
|
2033
|
+
if (error instanceof BillingBlockedError) {
|
|
2034
|
+
if (argv.json) output(argv, billingBlockedJsonResult(error, null));
|
|
2035
|
+
printError(error.message);
|
|
2036
|
+
process.exit(BILLING_BLOCKED_EXIT_CODE);
|
|
2037
|
+
}
|
|
2021
2038
|
printError(error instanceof Error ? error.message : String(error));
|
|
2022
2039
|
process.exit(1);
|
|
2023
2040
|
} finally {
|
|
@@ -2042,7 +2059,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
2042
2059
|
* Message ids are the currency of this API: `chat -p --json` reports the
|
|
2043
2060
|
* `messageId` and this command consumes it. Run ids stay server-side.
|
|
2044
2061
|
*/
|
|
2045
|
-
const getCommand = {
|
|
2062
|
+
const getCommand$1 = {
|
|
2046
2063
|
command: "get <message-id>",
|
|
2047
2064
|
describe: "Fetch a message by id and print the reply (recovers a timed-out -p)",
|
|
2048
2065
|
builder: (y) => y.positional("message-id", {
|
|
@@ -2051,22 +2068,27 @@ const getCommand = {
|
|
|
2051
2068
|
describe: "Message id (the `messageId` from a prior `chat -p --json`)"
|
|
2052
2069
|
}),
|
|
2053
2070
|
handler: async (argv) => {
|
|
2054
|
-
const
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
printError(`${session.error.message} Run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
2071
|
+
const auth = resolveChatAuth({ appUrl: resolveAppUrl({ appUrl: argv["api-url"] }) });
|
|
2072
|
+
if (auth.isErr()) {
|
|
2073
|
+
printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
2058
2074
|
process.exit(1);
|
|
2059
2075
|
}
|
|
2060
|
-
const { messageGet } = await import("./print-
|
|
2076
|
+
const { messageGet } = await import("./print-BXNq9UxE.mjs");
|
|
2061
2077
|
try {
|
|
2062
2078
|
const result = await messageGet({
|
|
2063
|
-
appUrl,
|
|
2064
|
-
sessionToken:
|
|
2079
|
+
appUrl: auth.value.appUrl,
|
|
2080
|
+
sessionToken: auth.value.token,
|
|
2065
2081
|
messageId: argv["message-id"],
|
|
2066
2082
|
json: argv.json
|
|
2067
2083
|
});
|
|
2068
2084
|
if (argv.json) output(argv, result);
|
|
2069
2085
|
} catch (error) {
|
|
2086
|
+
const { BillingBlockedError, BILLING_BLOCKED_EXIT_CODE, billingBlockedJsonResult } = await import("./billing-blocked-euid6MN9.mjs");
|
|
2087
|
+
if (error instanceof BillingBlockedError) {
|
|
2088
|
+
if (argv.json) output(argv, billingBlockedJsonResult(error, argv["message-id"]));
|
|
2089
|
+
printError(error.message);
|
|
2090
|
+
process.exit(BILLING_BLOCKED_EXIT_CODE);
|
|
2091
|
+
}
|
|
2070
2092
|
printError(error instanceof Error ? error.message : String(error));
|
|
2071
2093
|
process.exit(1);
|
|
2072
2094
|
}
|
|
@@ -2075,7 +2097,7 @@ const getCommand = {
|
|
|
2075
2097
|
const messagesCommand = {
|
|
2076
2098
|
command: "messages",
|
|
2077
2099
|
describe: "Inspect chat messages and re-fetch agent replies",
|
|
2078
|
-
builder: (y) => y.command(getCommand).demandCommand(1, "Specify a subcommand: get"),
|
|
2100
|
+
builder: (y) => y.command(getCommand$1).demandCommand(1, "Specify a subcommand: get"),
|
|
2079
2101
|
handler: () => {}
|
|
2080
2102
|
};
|
|
2081
2103
|
|
|
@@ -2098,7 +2120,7 @@ function messageToText(message) {
|
|
|
2098
2120
|
}
|
|
2099
2121
|
return chunks.join("\n").trim();
|
|
2100
2122
|
}
|
|
2101
|
-
const listCommand$
|
|
2123
|
+
const listCommand$2 = {
|
|
2102
2124
|
command: "list",
|
|
2103
2125
|
describe: "List an agent's conversations",
|
|
2104
2126
|
builder: (y) => y.option("agent", {
|
|
@@ -2188,7 +2210,7 @@ const conversationsCommand = {
|
|
|
2188
2210
|
command: "conversations",
|
|
2189
2211
|
aliases: ["conv"],
|
|
2190
2212
|
describe: "List and read agent conversations",
|
|
2191
|
-
builder: (y) => y.command(listCommand$
|
|
2213
|
+
builder: (y) => y.command(listCommand$2).command(showCommand).demandCommand(1, "Specify a subcommand: list, show"),
|
|
2192
2214
|
handler: () => {}
|
|
2193
2215
|
};
|
|
2194
2216
|
|
|
@@ -2230,7 +2252,7 @@ async function runList(argv, { hint }) {
|
|
|
2230
2252
|
]));
|
|
2231
2253
|
if (hint && !argv.quiet) console.log("\nRun `skydive workspace switch` to pick a workspace, or pass its slug directly.");
|
|
2232
2254
|
}
|
|
2233
|
-
const listCommand = {
|
|
2255
|
+
const listCommand$1 = {
|
|
2234
2256
|
command: "list",
|
|
2235
2257
|
describe: "List workspaces on your account",
|
|
2236
2258
|
handler: (argv) => runList(argv, { hint: false })
|
|
@@ -2254,7 +2276,7 @@ const switchCommand = {
|
|
|
2254
2276
|
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.");
|
|
2255
2277
|
process.exit(1);
|
|
2256
2278
|
}
|
|
2257
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
2279
|
+
const { runWorkspacePicker } = await import("./boot-on5ucI_Z.mjs");
|
|
2258
2280
|
await runWorkspacePicker(session);
|
|
2259
2281
|
return;
|
|
2260
2282
|
}
|
|
@@ -2287,7 +2309,7 @@ const switchCommand = {
|
|
|
2287
2309
|
const workspaceCommand = {
|
|
2288
2310
|
command: "workspace",
|
|
2289
2311
|
describe: "List or switch the workspace all `skydive` commands act on",
|
|
2290
|
-
builder: (y) => y.command(listCommand).command(switchCommand),
|
|
2312
|
+
builder: (y) => y.command(listCommand$1).command(switchCommand),
|
|
2291
2313
|
handler: (argv) => runList(argv, { hint: true })
|
|
2292
2314
|
};
|
|
2293
2315
|
|
|
@@ -2332,7 +2354,7 @@ const openCommand = {
|
|
|
2332
2354
|
const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
|
|
2333
2355
|
const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
|
|
2334
2356
|
const { machineName } = machineIdentity();
|
|
2335
|
-
const { PortalClient } = await import("./client-
|
|
2357
|
+
const { PortalClient } = await import("./client-D6apKmV0.mjs");
|
|
2336
2358
|
let lastLine = "";
|
|
2337
2359
|
let signalConnected;
|
|
2338
2360
|
const connected = new Promise((resolve) => {
|
|
@@ -2605,8 +2627,8 @@ const sandboxCommand = {
|
|
|
2605
2627
|
}).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`"),
|
|
2606
2628
|
handler: async (argv) => {
|
|
2607
2629
|
const session = requireSession(argv);
|
|
2608
|
-
const { createRestClient } = await import("./rest-
|
|
2609
|
-
const { resolveAgent } = await import("./print-
|
|
2630
|
+
const { createRestClient } = await import("./rest-Br2eFTlj.mjs");
|
|
2631
|
+
const { resolveAgent } = await import("./print-BXNq9UxE.mjs");
|
|
2610
2632
|
const client = createRestClient({
|
|
2611
2633
|
appUrl: session.appUrl,
|
|
2612
2634
|
sessionToken: session.sessionToken
|
|
@@ -2675,7 +2697,7 @@ async function runPty({ session, agentId, agentName }) {
|
|
|
2675
2697
|
return 1;
|
|
2676
2698
|
}
|
|
2677
2699
|
console.error(`Connecting to ${agentName}'s sandbox… (Ctrl-] detaches)`);
|
|
2678
|
-
const { runRawPtyPassthrough } = await import("./raw-pty-
|
|
2700
|
+
const { runRawPtyPassthrough } = await import("./raw-pty-t5DC-e1T.mjs");
|
|
2679
2701
|
const result = await runRawPtyPassthrough({
|
|
2680
2702
|
stdin: process.stdin,
|
|
2681
2703
|
stdout: process.stdout,
|
|
@@ -3356,10 +3378,146 @@ const updateCommand = {
|
|
|
3356
3378
|
}
|
|
3357
3379
|
};
|
|
3358
3380
|
|
|
3381
|
+
//#endregion
|
|
3382
|
+
//#region src/commands/config.ts
|
|
3383
|
+
/**
|
|
3384
|
+
* Resolve a preference key or exit 1 with a clear message. `choices` on each
|
|
3385
|
+
* positional already rejects unknown keys through yargs' own validation
|
|
3386
|
+
* (routing to the top-level `.fail()` handler), so this is a defensive guard
|
|
3387
|
+
* that also narrows the type. It follows the CLI's convention of
|
|
3388
|
+
* `printError` + `process.exit(1)` rather than throwing, because a throw from
|
|
3389
|
+
* an async yargs handler rejects `parseAsync` instead of being caught by
|
|
3390
|
+
* `.fail()`. `process.exit` returns `never`, so callers can treat the result
|
|
3391
|
+
* as always defined.
|
|
3392
|
+
*/
|
|
3393
|
+
function resolvePreference(key) {
|
|
3394
|
+
const pref = getPreference(key ?? "");
|
|
3395
|
+
if (!pref) {
|
|
3396
|
+
printError(`Unknown preference "${key}". Run \`skydive config list\` to see editable keys.`);
|
|
3397
|
+
process.exit(1);
|
|
3398
|
+
}
|
|
3399
|
+
return pref;
|
|
3400
|
+
}
|
|
3401
|
+
/** One row's worth of state for a preference, used by `list` and `get`. */
|
|
3402
|
+
function snapshot(pref) {
|
|
3403
|
+
return {
|
|
3404
|
+
key: pref.key,
|
|
3405
|
+
value: pref.read(),
|
|
3406
|
+
source: pref.isSet() ? "set" : "default",
|
|
3407
|
+
describe: pref.describe
|
|
3408
|
+
};
|
|
3409
|
+
}
|
|
3410
|
+
const listCommand = {
|
|
3411
|
+
command: "list",
|
|
3412
|
+
aliases: ["ls"],
|
|
3413
|
+
describe: "Show every editable preference, its value, and its source",
|
|
3414
|
+
handler: (argv) => {
|
|
3415
|
+
const rows = PREFERENCES.map(snapshot);
|
|
3416
|
+
if (argv.json) {
|
|
3417
|
+
output(argv, rows);
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
printTable([
|
|
3421
|
+
"Key",
|
|
3422
|
+
"Value",
|
|
3423
|
+
"Source",
|
|
3424
|
+
"Description"
|
|
3425
|
+
], rows.map((r) => [
|
|
3426
|
+
r.key,
|
|
3427
|
+
String(r.value),
|
|
3428
|
+
r.source,
|
|
3429
|
+
r.describe
|
|
3430
|
+
]));
|
|
3431
|
+
}
|
|
3432
|
+
};
|
|
3433
|
+
const getCommand = {
|
|
3434
|
+
command: "get <key>",
|
|
3435
|
+
describe: "Print the effective value of one preference",
|
|
3436
|
+
builder: (y) => y.positional("key", {
|
|
3437
|
+
type: "string",
|
|
3438
|
+
demandOption: true,
|
|
3439
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3440
|
+
describe: "Preference key"
|
|
3441
|
+
}),
|
|
3442
|
+
handler: (argv) => {
|
|
3443
|
+
const pref = resolvePreference(argv.key);
|
|
3444
|
+
if (argv.json) {
|
|
3445
|
+
output(argv, snapshot(pref));
|
|
3446
|
+
return;
|
|
3447
|
+
}
|
|
3448
|
+
console.log(String(pref.read()));
|
|
3449
|
+
}
|
|
3450
|
+
};
|
|
3451
|
+
const setCommand = {
|
|
3452
|
+
command: "set <key> <value>",
|
|
3453
|
+
describe: "Set a preference (e.g. `config set updateCheck false`)",
|
|
3454
|
+
builder: (y) => y.positional("key", {
|
|
3455
|
+
type: "string",
|
|
3456
|
+
demandOption: true,
|
|
3457
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3458
|
+
describe: "Preference key"
|
|
3459
|
+
}).positional("value", {
|
|
3460
|
+
type: "string",
|
|
3461
|
+
demandOption: true,
|
|
3462
|
+
describe: "New value"
|
|
3463
|
+
}),
|
|
3464
|
+
handler: (argv) => {
|
|
3465
|
+
const pref = resolvePreference(argv.key);
|
|
3466
|
+
const parsed = pref.parse(argv.value ?? "");
|
|
3467
|
+
if (parsed.isErr()) {
|
|
3468
|
+
printError(`${pref.key}: ${parsed.error}`);
|
|
3469
|
+
process.exit(1);
|
|
3470
|
+
}
|
|
3471
|
+
pref.write(parsed.value);
|
|
3472
|
+
if (argv.json) {
|
|
3473
|
+
output(argv, snapshot(pref));
|
|
3474
|
+
return;
|
|
3475
|
+
}
|
|
3476
|
+
if (!argv.quiet) console.log(`Set ${pref.key} = ${String(parsed.value)}`);
|
|
3477
|
+
}
|
|
3478
|
+
};
|
|
3479
|
+
const unsetCommand = {
|
|
3480
|
+
command: "unset <key>",
|
|
3481
|
+
aliases: ["reset"],
|
|
3482
|
+
describe: "Remove a preference, reverting it to the built-in default",
|
|
3483
|
+
builder: (y) => y.positional("key", {
|
|
3484
|
+
type: "string",
|
|
3485
|
+
demandOption: true,
|
|
3486
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3487
|
+
describe: "Preference key"
|
|
3488
|
+
}),
|
|
3489
|
+
handler: (argv) => {
|
|
3490
|
+
const pref = resolvePreference(argv.key);
|
|
3491
|
+
pref.clear();
|
|
3492
|
+
if (argv.json) {
|
|
3493
|
+
output(argv, snapshot(pref));
|
|
3494
|
+
return;
|
|
3495
|
+
}
|
|
3496
|
+
if (!argv.quiet) console.log(`Unset ${pref.key} (now ${String(pref.read())} by default)`);
|
|
3497
|
+
}
|
|
3498
|
+
};
|
|
3499
|
+
const pathCommand = {
|
|
3500
|
+
command: "path",
|
|
3501
|
+
describe: "Print the on-disk config file path",
|
|
3502
|
+
handler: (argv) => {
|
|
3503
|
+
if (argv.json) {
|
|
3504
|
+
output(argv, { path: getConfigPath() });
|
|
3505
|
+
return;
|
|
3506
|
+
}
|
|
3507
|
+
console.log(getConfigPath());
|
|
3508
|
+
}
|
|
3509
|
+
};
|
|
3510
|
+
const configCommand = {
|
|
3511
|
+
command: "config",
|
|
3512
|
+
describe: "View and set CLI preferences (safe, hand-editable keys only)",
|
|
3513
|
+
builder: (y) => y.command(listCommand).command(getCommand).command(setCommand).command(unsetCommand).command(pathCommand),
|
|
3514
|
+
handler: (argv) => listCommand.handler(argv)
|
|
3515
|
+
};
|
|
3516
|
+
|
|
3359
3517
|
//#endregion
|
|
3360
3518
|
//#region src/cli.ts
|
|
3361
3519
|
function createCli(argv) {
|
|
3362
|
-
return yargs(argv).scriptName("skydive").usage("$0 <command> [options]").parserConfiguration({ "populate--": true }).example("skydive auth login", "Store your API key").example("skydive chat", "Open the interactive chat TUI (prod)").example("skydive chat --api-url http://localhost:4500", "Chat against a local dev API").example("skydive agents list", "List your agents").example("skydive completion install", "Set up TAB completion for your shell").example("skydive keys create \"my-key\"", "Create an API key").example("skydive secrets set OPENAI_API_KEY --agent-id <id>", "Set a secret (value from stdin)").example("skydive workspace list", "List workspaces on your account").example("skydive workspace switch acme-team", "Switch the workspace all `skydive` commands act on").example("skydive portal open --agent grace", "Open the portal to this machine for an agent, headless (no TUI)").option("json", {
|
|
3520
|
+
return yargs(argv).scriptName("skydive").usage("$0 <command> [options]").parserConfiguration({ "populate--": true }).example("skydive auth login", "Store your API key").example("skydive chat", "Open the interactive chat TUI (prod)").example("skydive chat --api-url http://localhost:4500", "Chat against a local dev API").example("skydive agents list", "List your agents").example("skydive completion install", "Set up TAB completion for your shell").example("skydive keys create \"my-key\"", "Create an API key").example("skydive secrets set OPENAI_API_KEY --agent-id <id>", "Set a secret (value from stdin)").example("skydive workspace list", "List workspaces on your account").example("skydive config set updateCheck false", "Disable the daily update check").example("skydive workspace switch acme-team", "Switch the workspace all `skydive` commands act on").example("skydive portal open --agent grace", "Open the portal to this machine for an agent, headless (no TUI)").option("json", {
|
|
3363
3521
|
type: "boolean",
|
|
3364
3522
|
default: false,
|
|
3365
3523
|
global: true,
|
|
@@ -3373,7 +3531,7 @@ function createCli(argv) {
|
|
|
3373
3531
|
type: "string",
|
|
3374
3532
|
global: true,
|
|
3375
3533
|
describe: "Override API base URL"
|
|
3376
|
-
}).command(authCommand).command(chatCommand).command(messagesCommand).command(conversationsCommand).command(agentsCommand).command(importCommand).command(keysCommand).command(secretsCommand).command(workspaceCommand).command(portalCommand).command(sandboxCommand).command(updateCommand).command(completionCommand).demandCommand(1, "Specify a command. Run --help for usage.").strict().wrap(null).version(version).alias("v", "version").alias("h", "help").help().fail((msg, err) => {
|
|
3534
|
+
}).command(authCommand).command(chatCommand).command(messagesCommand).command(conversationsCommand).command(agentsCommand).command(importCommand).command(keysCommand).command(secretsCommand).command(workspaceCommand).command(portalCommand).command(sandboxCommand).command(updateCommand).command(configCommand).command(completionCommand).demandCommand(1, "Specify a command. Run --help for usage.").strict().wrap(null).version(version).alias("v", "version").alias("h", "help").help().fail((msg, err) => {
|
|
3377
3535
|
printError(err ? err instanceof Error ? err.message : String(err) : msg ?? "Unknown error");
|
|
3378
3536
|
process.exit(1);
|
|
3379
3537
|
});
|
|
@@ -3586,7 +3744,7 @@ function setupUpdateCheck(argv) {
|
|
|
3586
3744
|
|
|
3587
3745
|
//#endregion
|
|
3588
3746
|
//#region src/changelog.generated.ts
|
|
3589
|
-
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## [0.3.0] - 2026-08-04\n\n### Added\n\n**Chat TUI**\n\n- `/fork` slash command to fork a conversation at any point and continue in a new thread.\n- `/conversation` switches threads from inside a live session.\n- `/compact` triggers manual conversation compaction.\n- `/portal` and `/copy` slash commands.\n- Archive the current conversation from the chat TUI.\n- `--new` flag on `skydive chat` to start a fresh conversation.\n- Debounced server-side conversation search in the picker, with title matches ranked first.\n- File review pane orientation toggle, and review comments in the file pane.\n- Pinned plan card controls and a jump-to-latest hint.\n- Terminal title (OSC) follows the live conversation title on every screen; inside cmux the workspace is renamed too, and linked PRs are pushed to the cmux sidebar.\n- Every participating agent shows in the conversation list; connect cards each have their own identity, and ctrl+r asks which connect card to act on.\n- Colored Skydive splash art in `skydive --help` and the TUI pickers.\n- New-agent name prefilled from the server's suggestion.\n\n**CLI & platform**\n\n- `skydive update` self-updater, with an update notice when a new version is available.\n- Shell completions for bash, zsh, and fish via `completion install`.\n- Portal daemon: one connection per host with per-conversation working directories.\n- Agent-led coding-agent import (`skydive import`).\n- Per-workspace scoping on the REST client, and cross-org `--agent <uuid>` auto-switches workspace.\n- `skydive-beta` wrapper for the canary channel.\n\n### Fixed\n\n- `skydive update` no longer claims an update is available on every npm install.\n- Chat memory is bounded (payload clamps + windowed rows) with a memory watchdog and OOM diagnostic report; transcript rows are memoized so streaming stops re-rendering the whole chat.\n- Chat-send failures map to real error messages.\n- Notification and sidebar previews use the last text block of the reply and strip inline markdown.\n- Picker rows no longer overlap when a conversation title contains a newline, tab, or control character.\n- Sending to non-web channel conversations is blocked in the TUI.\n- GitHub bot connect opens on the web front door, not api.skydive.com.\n- TUI activity counter times from the run, not the screen.\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";
|
|
3747
|
+
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## [0.4.0] - 2026-08-07\n\n### Added\n\n- `skydive chat` works with API key auth: an API key alone now opens the chat TUI (and headless `chat -p`) without a browser login, using the key's pinned workspace.\n- `skydive config` command to view and set the safe, hand-editable CLI preferences (`shareMachineDefault`, `updateCheck`) without opening `config.json`. `config`/`config list` shows each key, its effective value, and whether it comes from the file or the built-in default; `config get`/`set`/`unset` read and change one key; `config path` prints the config file location. It only ever touches those preference keys, never credentials or flow-managed state.\n- Billing-blocked sends and runs now surface the server-authored recovery\n guidance from the typed billing outcome. The chat TUI renders it as a\n warning-toned system-notice row — live when a send is refused or a run is\n stopped at the billing boundary, and again when reopening a conversation\n that holds a persisted billing notice — instead of a generic error.\n Headless `chat -p` and `messages get` print the guidance (state, recovery\n step, and manage-billing URL) on stderr, keep any partial output already\n streamed on stdout, and exit with code `5` (distinct from the generic `1`)\n so scripted callers can tell a billing pause from a failure.\n- Syntax highlighting for 14 more languages in the chat transcript and file/review panes (python, bash, go, rust, c, cpp, java, ruby, css, html, json, yaml, and more) — previously only JavaScript/TypeScript rendered colored.\n\n### Changed\n\n- `skydive agent list` lists the full agent roster by default instead of a truncated page.\n\n### Fixed\n\n- Long multi-line bash tool-call commands (e.g. heredocs) are clamped with a `+N more · click to expand` tail instead of dumping their whole body into the scrollback.\n- Tool error output is clipped the same way as ok output, so a failing command no longer floods the transcript.\n- The TUI toast overlay has an opaque background instead of letting the transcript bleed through.\n\n## [0.3.0] - 2026-08-04\n\n### Added\n\n**Chat TUI**\n\n- `/fork` slash command to fork a conversation at any point and continue in a new thread.\n- `/conversation` switches threads from inside a live session.\n- `/compact` triggers manual conversation compaction.\n- `/portal` and `/copy` slash commands.\n- Archive the current conversation from the chat TUI.\n- `--new` flag on `skydive chat` to start a fresh conversation.\n- Debounced server-side conversation search in the picker, with title matches ranked first.\n- File review pane orientation toggle, and review comments in the file pane.\n- Pinned plan card controls and a jump-to-latest hint.\n- Terminal title (OSC) follows the live conversation title on every screen; inside cmux the workspace is renamed too, and linked PRs are pushed to the cmux sidebar.\n- Every participating agent shows in the conversation list; connect cards each have their own identity, and ctrl+r asks which connect card to act on.\n- Colored Skydive splash art in `skydive --help` and the TUI pickers.\n- New-agent name prefilled from the server's suggestion.\n\n**CLI & platform**\n\n- `skydive update` self-updater, with an update notice when a new version is available.\n- Shell completions for bash, zsh, and fish via `completion install`.\n- Portal daemon: one connection per host with per-conversation working directories.\n- Agent-led coding-agent import (`skydive import`).\n- Per-workspace scoping on the REST client, and cross-org `--agent <uuid>` auto-switches workspace.\n- `skydive-beta` wrapper for the canary channel.\n\n### Fixed\n\n- `skydive update` no longer claims an update is available on every npm install.\n- Chat memory is bounded (payload clamps + windowed rows) with a memory watchdog and OOM diagnostic report; transcript rows are memoized so streaming stops re-rendering the whole chat.\n- Chat-send failures map to real error messages.\n- Notification and sidebar previews use the last text block of the reply and strip inline markdown.\n- Picker rows no longer overlap when a conversation title contains a newline, tab, or control character.\n- Sending to non-web channel conversations is blocked in the TUI.\n- GitHub bot connect opens on the web front door, not api.skydive.com.\n- TUI activity counter times from the run, not the screen.\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";
|
|
3590
3748
|
|
|
3591
3749
|
//#endregion
|
|
3592
3750
|
//#region src/whats-new.ts
|
|
@@ -3728,7 +3886,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
|
|
|
3728
3886
|
process.exit(0);
|
|
3729
3887
|
}
|
|
3730
3888
|
if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
|
|
3731
|
-
const { runPortalDaemon } = await import("./daemon-
|
|
3889
|
+
const { runPortalDaemon } = await import("./daemon-BADmpJAs.mjs");
|
|
3732
3890
|
runPortalDaemon(process.argv);
|
|
3733
3891
|
} else runCli();
|
|
3734
3892
|
function runCli() {
|