skydive-cli 0.3.0-beta.776 → 0.3.0-beta.794
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 +1 -0
- package/README.md +16 -2
- package/dist/js/bin.mjs +162 -26
- package/dist/js/{boot-Dbcys7qY.mjs → boot-C-PAidLX.mjs} +2 -2
- package/dist/js/{install-CDccuBwm.mjs → install-DqLgkAHr.mjs} +2 -2
- package/dist/js/{print-Cd-bVSEJ.mjs → print-Bmgp3ZT9.mjs} +51 -1
- package/dist/js/{print-CPCFci60.mjs → print-CB9kyvkV.mjs} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
35
35
|
- Agent-led coding-agent import (`skydive import`).
|
|
36
36
|
- Per-workspace scoping on the REST client, and cross-org `--agent <uuid>` auto-switches workspace.
|
|
37
37
|
- `skydive-beta` wrapper for the canary channel.
|
|
38
|
+
- `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.
|
|
38
39
|
|
|
39
40
|
### Fixed
|
|
40
41
|
|
package/README.md
CHANGED
|
@@ -132,6 +132,9 @@ skydive portal grant --agent <id|name>
|
|
|
132
132
|
skydive portal revoke --agent <id|name>
|
|
133
133
|
skydive portal status
|
|
134
134
|
|
|
135
|
+
skydive config # list CLI preferences
|
|
136
|
+
skydive config set updateCheck false
|
|
137
|
+
|
|
135
138
|
skydive completion install # set up TAB completion for your shell
|
|
136
139
|
```
|
|
137
140
|
|
|
@@ -433,9 +436,20 @@ Persistent state lives in a per-user JSON file managed by
|
|
|
433
436
|
`SKYDIVE_CONFIG_NAME`). Most keys are written by flows — `auth login`, the
|
|
434
437
|
device-login flow, the in-TUI theme picker — but the file is plain JSON and
|
|
435
438
|
read fresh on every invocation, so preference keys can be set by editing it
|
|
436
|
-
directly.
|
|
439
|
+
directly.
|
|
440
|
+
|
|
441
|
+
The safe, hand-editable preference keys are also managed by `skydive config`,
|
|
442
|
+
which only ever touches those keys — never credentials or flow-managed state:
|
|
443
|
+
|
|
444
|
+
```sh
|
|
445
|
+
skydive config # list preferences, values, and source
|
|
446
|
+
skydive config get updateCheck # print the effective value of one key
|
|
447
|
+
skydive config set updateCheck false
|
|
448
|
+
skydive config unset updateCheck # revert to the built-in default
|
|
449
|
+
skydive config path # print the config.json location
|
|
450
|
+
```
|
|
437
451
|
|
|
438
|
-
|
|
452
|
+
Editable keys:
|
|
439
453
|
|
|
440
454
|
| Key | Type | Effect |
|
|
441
455
|
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
package/dist/js/bin.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-DqLgkAHr.mjs";
|
|
3
|
+
import { A as getStoredApiKeyWorkspaceName, B as setLastSeenVersion, C as getLastSeenVersion, F as resolveSession, L as saveConfig, M as resolveAppUrl, N as resolveConfig, O as getShareMachineDefault, P as resolveManagementAuth, R as saveSession, S as getConfigPath, T as getPromptHistoryPath, _ 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 } from "./print-Bmgp3ZT9.mjs";
|
|
4
4
|
import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
|
|
5
5
|
import { n as createRestClient, t as HttpError } from "./rest-BlN_uWmL.mjs";
|
|
6
6
|
import { a as registerPortalDevice, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice, s as machineIdentity } from "./client-Dc7GZ3PG.mjs";
|
|
@@ -1056,7 +1056,7 @@ function requireRestClient(argv) {
|
|
|
1056
1056
|
|
|
1057
1057
|
//#endregion
|
|
1058
1058
|
//#region src/commands/agents.ts
|
|
1059
|
-
const listCommand$
|
|
1059
|
+
const listCommand$5 = {
|
|
1060
1060
|
command: "list",
|
|
1061
1061
|
describe: "List agents in the active workspace",
|
|
1062
1062
|
builder: (y) => y.option("limit", {
|
|
@@ -1131,7 +1131,7 @@ function truncate(value, max) {
|
|
|
1131
1131
|
if (trimmed.length <= max) return trimmed || "-";
|
|
1132
1132
|
return `${trimmed.slice(0, max - 1)}\u2026`;
|
|
1133
1133
|
}
|
|
1134
|
-
const getCommand$
|
|
1134
|
+
const getCommand$2 = {
|
|
1135
1135
|
command: "get <id>",
|
|
1136
1136
|
describe: "Get agent details",
|
|
1137
1137
|
builder: (y) => y.positional("id", {
|
|
@@ -1201,7 +1201,7 @@ const createCommand$1 = {
|
|
|
1201
1201
|
const agentsCommand = {
|
|
1202
1202
|
command: "agents",
|
|
1203
1203
|
describe: "Manage agents",
|
|
1204
|
-
builder: (y) => y.command(listCommand$
|
|
1204
|
+
builder: (y) => y.command(listCommand$5).command(getCommand$2).command(createCommand$1).demandCommand(1, "Specify a subcommand: list, get, create"),
|
|
1205
1205
|
handler: () => {}
|
|
1206
1206
|
};
|
|
1207
1207
|
|
|
@@ -1500,7 +1500,7 @@ const importCommand = {
|
|
|
1500
1500
|
process.exit(1);
|
|
1501
1501
|
}
|
|
1502
1502
|
}
|
|
1503
|
-
const { runChat } = await import("./boot-
|
|
1503
|
+
const { runChat } = await import("./boot-C-PAidLX.mjs");
|
|
1504
1504
|
await runChat({
|
|
1505
1505
|
appUrl,
|
|
1506
1506
|
sessionToken: session.value.sessionToken,
|
|
@@ -1535,7 +1535,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1535
1535
|
});
|
|
1536
1536
|
const extra = (argv.print ?? "").trim();
|
|
1537
1537
|
const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
|
|
1538
|
-
const { runPrint } = await import("./print-
|
|
1538
|
+
const { runPrint } = await import("./print-CB9kyvkV.mjs");
|
|
1539
1539
|
try {
|
|
1540
1540
|
const result = await runPrint({
|
|
1541
1541
|
appUrl,
|
|
@@ -1559,7 +1559,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1559
1559
|
|
|
1560
1560
|
//#endregion
|
|
1561
1561
|
//#region src/commands/keys.ts
|
|
1562
|
-
const listCommand$
|
|
1562
|
+
const listCommand$4 = {
|
|
1563
1563
|
command: "list",
|
|
1564
1564
|
describe: "List API keys for an agent",
|
|
1565
1565
|
handler: async (argv) => {
|
|
@@ -1648,7 +1648,7 @@ const keysCommand = {
|
|
|
1648
1648
|
type: "string",
|
|
1649
1649
|
demandOption: true,
|
|
1650
1650
|
describe: "Agent ID"
|
|
1651
|
-
}).command(listCommand$
|
|
1651
|
+
}).command(listCommand$4).command(createCommand).command(revokeCommand$1).demandCommand(1, "Specify a subcommand: list, create, revoke"),
|
|
1652
1652
|
handler: () => {}
|
|
1653
1653
|
};
|
|
1654
1654
|
|
|
@@ -1660,7 +1660,7 @@ async function readStdin() {
|
|
|
1660
1660
|
for await (const chunk of process.stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1661
1661
|
return Buffer.concat(chunks).toString("utf8").replace(/\n$/, "");
|
|
1662
1662
|
}
|
|
1663
|
-
const listCommand$
|
|
1663
|
+
const listCommand$3 = {
|
|
1664
1664
|
command: "list",
|
|
1665
1665
|
describe: "List secret names for an agent (values are never shown)",
|
|
1666
1666
|
handler: async (argv) => {
|
|
@@ -1681,7 +1681,7 @@ const listCommand$2 = {
|
|
|
1681
1681
|
printTable(["Name"], keys.map((k) => [k]));
|
|
1682
1682
|
}
|
|
1683
1683
|
};
|
|
1684
|
-
const setCommand = {
|
|
1684
|
+
const setCommand$1 = {
|
|
1685
1685
|
command: "set <key> [value]",
|
|
1686
1686
|
describe: "Set (create or overwrite) a secret. Reads value from stdin if omitted.",
|
|
1687
1687
|
builder: (y) => y.positional("key", {
|
|
@@ -1746,7 +1746,7 @@ const secretsCommand = {
|
|
|
1746
1746
|
type: "string",
|
|
1747
1747
|
demandOption: true,
|
|
1748
1748
|
describe: "Agent ID"
|
|
1749
|
-
}).command(listCommand$
|
|
1749
|
+
}).command(listCommand$3).command(setCommand$1).command(rmCommand).demandCommand(1, "Specify a subcommand: list, set, rm"),
|
|
1750
1750
|
handler: () => {}
|
|
1751
1751
|
};
|
|
1752
1752
|
|
|
@@ -1912,7 +1912,7 @@ const chatCommand = {
|
|
|
1912
1912
|
sessionToken: session.value.sessionToken,
|
|
1913
1913
|
agentSelector: argv.agent ?? null
|
|
1914
1914
|
});
|
|
1915
|
-
const { runChat } = await import("./boot-
|
|
1915
|
+
const { runChat } = await import("./boot-C-PAidLX.mjs");
|
|
1916
1916
|
await runChat({
|
|
1917
1917
|
appUrl,
|
|
1918
1918
|
sessionToken: session.value.sessionToken,
|
|
@@ -1978,7 +1978,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
1978
1978
|
printError(`${session.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
1979
1979
|
process.exit(1);
|
|
1980
1980
|
}
|
|
1981
|
-
const { runPrint, readStdin } = await import("./print-
|
|
1981
|
+
const { runPrint, readStdin } = await import("./print-CB9kyvkV.mjs");
|
|
1982
1982
|
await ensureAgentWorkspace({
|
|
1983
1983
|
appUrl,
|
|
1984
1984
|
sessionToken: session.value.sessionToken,
|
|
@@ -2042,7 +2042,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
2042
2042
|
* Message ids are the currency of this API: `chat -p --json` reports the
|
|
2043
2043
|
* `messageId` and this command consumes it. Run ids stay server-side.
|
|
2044
2044
|
*/
|
|
2045
|
-
const getCommand = {
|
|
2045
|
+
const getCommand$1 = {
|
|
2046
2046
|
command: "get <message-id>",
|
|
2047
2047
|
describe: "Fetch a message by id and print the reply (recovers a timed-out -p)",
|
|
2048
2048
|
builder: (y) => y.positional("message-id", {
|
|
@@ -2057,7 +2057,7 @@ const getCommand = {
|
|
|
2057
2057
|
printError(`${session.error.message} Run \`skydive auth login\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
2058
2058
|
process.exit(1);
|
|
2059
2059
|
}
|
|
2060
|
-
const { messageGet } = await import("./print-
|
|
2060
|
+
const { messageGet } = await import("./print-CB9kyvkV.mjs");
|
|
2061
2061
|
try {
|
|
2062
2062
|
const result = await messageGet({
|
|
2063
2063
|
appUrl,
|
|
@@ -2075,7 +2075,7 @@ const getCommand = {
|
|
|
2075
2075
|
const messagesCommand = {
|
|
2076
2076
|
command: "messages",
|
|
2077
2077
|
describe: "Inspect chat messages and re-fetch agent replies",
|
|
2078
|
-
builder: (y) => y.command(getCommand).demandCommand(1, "Specify a subcommand: get"),
|
|
2078
|
+
builder: (y) => y.command(getCommand$1).demandCommand(1, "Specify a subcommand: get"),
|
|
2079
2079
|
handler: () => {}
|
|
2080
2080
|
};
|
|
2081
2081
|
|
|
@@ -2098,7 +2098,7 @@ function messageToText(message) {
|
|
|
2098
2098
|
}
|
|
2099
2099
|
return chunks.join("\n").trim();
|
|
2100
2100
|
}
|
|
2101
|
-
const listCommand$
|
|
2101
|
+
const listCommand$2 = {
|
|
2102
2102
|
command: "list",
|
|
2103
2103
|
describe: "List an agent's conversations",
|
|
2104
2104
|
builder: (y) => y.option("agent", {
|
|
@@ -2188,7 +2188,7 @@ const conversationsCommand = {
|
|
|
2188
2188
|
command: "conversations",
|
|
2189
2189
|
aliases: ["conv"],
|
|
2190
2190
|
describe: "List and read agent conversations",
|
|
2191
|
-
builder: (y) => y.command(listCommand$
|
|
2191
|
+
builder: (y) => y.command(listCommand$2).command(showCommand).demandCommand(1, "Specify a subcommand: list, show"),
|
|
2192
2192
|
handler: () => {}
|
|
2193
2193
|
};
|
|
2194
2194
|
|
|
@@ -2230,7 +2230,7 @@ async function runList(argv, { hint }) {
|
|
|
2230
2230
|
]));
|
|
2231
2231
|
if (hint && !argv.quiet) console.log("\nRun `skydive workspace switch` to pick a workspace, or pass its slug directly.");
|
|
2232
2232
|
}
|
|
2233
|
-
const listCommand = {
|
|
2233
|
+
const listCommand$1 = {
|
|
2234
2234
|
command: "list",
|
|
2235
2235
|
describe: "List workspaces on your account",
|
|
2236
2236
|
handler: (argv) => runList(argv, { hint: false })
|
|
@@ -2254,7 +2254,7 @@ const switchCommand = {
|
|
|
2254
2254
|
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
2255
|
process.exit(1);
|
|
2256
2256
|
}
|
|
2257
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
2257
|
+
const { runWorkspacePicker } = await import("./boot-C-PAidLX.mjs");
|
|
2258
2258
|
await runWorkspacePicker(session);
|
|
2259
2259
|
return;
|
|
2260
2260
|
}
|
|
@@ -2287,7 +2287,7 @@ const switchCommand = {
|
|
|
2287
2287
|
const workspaceCommand = {
|
|
2288
2288
|
command: "workspace",
|
|
2289
2289
|
describe: "List or switch the workspace all `skydive` commands act on",
|
|
2290
|
-
builder: (y) => y.command(listCommand).command(switchCommand),
|
|
2290
|
+
builder: (y) => y.command(listCommand$1).command(switchCommand),
|
|
2291
2291
|
handler: (argv) => runList(argv, { hint: true })
|
|
2292
2292
|
};
|
|
2293
2293
|
|
|
@@ -2606,7 +2606,7 @@ const sandboxCommand = {
|
|
|
2606
2606
|
handler: async (argv) => {
|
|
2607
2607
|
const session = requireSession(argv);
|
|
2608
2608
|
const { createRestClient } = await import("./rest-CDTXCmUb.mjs");
|
|
2609
|
-
const { resolveAgent } = await import("./print-
|
|
2609
|
+
const { resolveAgent } = await import("./print-CB9kyvkV.mjs");
|
|
2610
2610
|
const client = createRestClient({
|
|
2611
2611
|
appUrl: session.appUrl,
|
|
2612
2612
|
sessionToken: session.sessionToken
|
|
@@ -3356,10 +3356,146 @@ const updateCommand = {
|
|
|
3356
3356
|
}
|
|
3357
3357
|
};
|
|
3358
3358
|
|
|
3359
|
+
//#endregion
|
|
3360
|
+
//#region src/commands/config.ts
|
|
3361
|
+
/**
|
|
3362
|
+
* Resolve a preference key or exit 1 with a clear message. `choices` on each
|
|
3363
|
+
* positional already rejects unknown keys through yargs' own validation
|
|
3364
|
+
* (routing to the top-level `.fail()` handler), so this is a defensive guard
|
|
3365
|
+
* that also narrows the type. It follows the CLI's convention of
|
|
3366
|
+
* `printError` + `process.exit(1)` rather than throwing, because a throw from
|
|
3367
|
+
* an async yargs handler rejects `parseAsync` instead of being caught by
|
|
3368
|
+
* `.fail()`. `process.exit` returns `never`, so callers can treat the result
|
|
3369
|
+
* as always defined.
|
|
3370
|
+
*/
|
|
3371
|
+
function resolvePreference(key) {
|
|
3372
|
+
const pref = getPreference(key ?? "");
|
|
3373
|
+
if (!pref) {
|
|
3374
|
+
printError(`Unknown preference "${key}". Run \`skydive config list\` to see editable keys.`);
|
|
3375
|
+
process.exit(1);
|
|
3376
|
+
}
|
|
3377
|
+
return pref;
|
|
3378
|
+
}
|
|
3379
|
+
/** One row's worth of state for a preference, used by `list` and `get`. */
|
|
3380
|
+
function snapshot(pref) {
|
|
3381
|
+
return {
|
|
3382
|
+
key: pref.key,
|
|
3383
|
+
value: pref.read(),
|
|
3384
|
+
source: pref.isSet() ? "set" : "default",
|
|
3385
|
+
describe: pref.describe
|
|
3386
|
+
};
|
|
3387
|
+
}
|
|
3388
|
+
const listCommand = {
|
|
3389
|
+
command: "list",
|
|
3390
|
+
aliases: ["ls"],
|
|
3391
|
+
describe: "Show every editable preference, its value, and its source",
|
|
3392
|
+
handler: (argv) => {
|
|
3393
|
+
const rows = PREFERENCES.map(snapshot);
|
|
3394
|
+
if (argv.json) {
|
|
3395
|
+
output(argv, rows);
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3398
|
+
printTable([
|
|
3399
|
+
"Key",
|
|
3400
|
+
"Value",
|
|
3401
|
+
"Source",
|
|
3402
|
+
"Description"
|
|
3403
|
+
], rows.map((r) => [
|
|
3404
|
+
r.key,
|
|
3405
|
+
String(r.value),
|
|
3406
|
+
r.source,
|
|
3407
|
+
r.describe
|
|
3408
|
+
]));
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3411
|
+
const getCommand = {
|
|
3412
|
+
command: "get <key>",
|
|
3413
|
+
describe: "Print the effective value of one preference",
|
|
3414
|
+
builder: (y) => y.positional("key", {
|
|
3415
|
+
type: "string",
|
|
3416
|
+
demandOption: true,
|
|
3417
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3418
|
+
describe: "Preference key"
|
|
3419
|
+
}),
|
|
3420
|
+
handler: (argv) => {
|
|
3421
|
+
const pref = resolvePreference(argv.key);
|
|
3422
|
+
if (argv.json) {
|
|
3423
|
+
output(argv, snapshot(pref));
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3426
|
+
console.log(String(pref.read()));
|
|
3427
|
+
}
|
|
3428
|
+
};
|
|
3429
|
+
const setCommand = {
|
|
3430
|
+
command: "set <key> <value>",
|
|
3431
|
+
describe: "Set a preference (e.g. `config set updateCheck false`)",
|
|
3432
|
+
builder: (y) => y.positional("key", {
|
|
3433
|
+
type: "string",
|
|
3434
|
+
demandOption: true,
|
|
3435
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3436
|
+
describe: "Preference key"
|
|
3437
|
+
}).positional("value", {
|
|
3438
|
+
type: "string",
|
|
3439
|
+
demandOption: true,
|
|
3440
|
+
describe: "New value"
|
|
3441
|
+
}),
|
|
3442
|
+
handler: (argv) => {
|
|
3443
|
+
const pref = resolvePreference(argv.key);
|
|
3444
|
+
const parsed = pref.parse(argv.value ?? "");
|
|
3445
|
+
if (parsed.isErr()) {
|
|
3446
|
+
printError(`${pref.key}: ${parsed.error}`);
|
|
3447
|
+
process.exit(1);
|
|
3448
|
+
}
|
|
3449
|
+
pref.write(parsed.value);
|
|
3450
|
+
if (argv.json) {
|
|
3451
|
+
output(argv, snapshot(pref));
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
if (!argv.quiet) console.log(`Set ${pref.key} = ${String(parsed.value)}`);
|
|
3455
|
+
}
|
|
3456
|
+
};
|
|
3457
|
+
const unsetCommand = {
|
|
3458
|
+
command: "unset <key>",
|
|
3459
|
+
aliases: ["reset"],
|
|
3460
|
+
describe: "Remove a preference, reverting it to the built-in default",
|
|
3461
|
+
builder: (y) => y.positional("key", {
|
|
3462
|
+
type: "string",
|
|
3463
|
+
demandOption: true,
|
|
3464
|
+
choices: PREFERENCES.map((p) => p.key),
|
|
3465
|
+
describe: "Preference key"
|
|
3466
|
+
}),
|
|
3467
|
+
handler: (argv) => {
|
|
3468
|
+
const pref = resolvePreference(argv.key);
|
|
3469
|
+
pref.clear();
|
|
3470
|
+
if (argv.json) {
|
|
3471
|
+
output(argv, snapshot(pref));
|
|
3472
|
+
return;
|
|
3473
|
+
}
|
|
3474
|
+
if (!argv.quiet) console.log(`Unset ${pref.key} (now ${String(pref.read())} by default)`);
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3477
|
+
const pathCommand = {
|
|
3478
|
+
command: "path",
|
|
3479
|
+
describe: "Print the on-disk config file path",
|
|
3480
|
+
handler: (argv) => {
|
|
3481
|
+
if (argv.json) {
|
|
3482
|
+
output(argv, { path: getConfigPath() });
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
console.log(getConfigPath());
|
|
3486
|
+
}
|
|
3487
|
+
};
|
|
3488
|
+
const configCommand = {
|
|
3489
|
+
command: "config",
|
|
3490
|
+
describe: "View and set CLI preferences (safe, hand-editable keys only)",
|
|
3491
|
+
builder: (y) => y.command(listCommand).command(getCommand).command(setCommand).command(unsetCommand).command(pathCommand),
|
|
3492
|
+
handler: (argv) => listCommand.handler(argv)
|
|
3493
|
+
};
|
|
3494
|
+
|
|
3359
3495
|
//#endregion
|
|
3360
3496
|
//#region src/cli.ts
|
|
3361
3497
|
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", {
|
|
3498
|
+
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
3499
|
type: "boolean",
|
|
3364
3500
|
default: false,
|
|
3365
3501
|
global: true,
|
|
@@ -3373,7 +3509,7 @@ function createCli(argv) {
|
|
|
3373
3509
|
type: "string",
|
|
3374
3510
|
global: true,
|
|
3375
3511
|
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) => {
|
|
3512
|
+
}).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
3513
|
printError(err ? err instanceof Error ? err.message : String(err) : msg ?? "Unknown error");
|
|
3378
3514
|
process.exit(1);
|
|
3379
3515
|
});
|
|
@@ -3586,7 +3722,7 @@ function setupUpdateCheck(argv) {
|
|
|
3586
3722
|
|
|
3587
3723
|
//#endregion
|
|
3588
3724
|
//#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";
|
|
3725
|
+
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- `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\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
3726
|
|
|
3591
3727
|
//#endregion
|
|
3592
3728
|
//#region src/whats-new.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as setActiveWorkspace, S as listWorkspaces, a as WORDMARK, b as getActiveWorkspaceId, c as applyTheme, d as noColorRequested, f as theme, g as themeVersion, h as themeModeFromColorFgBg, i as MARK_CELLS, l as findTheme, m as themeMode, n as buildCrashReport, p as themeForMode, r as writeCrashReport, s as DEFAULT_THEME_ID, t as installCrashHandler, u as monoTheme, v as themesForMode } from "./install-
|
|
3
|
-
import {
|
|
2
|
+
import { C as setActiveWorkspace, S as listWorkspaces, a as WORDMARK, b as getActiveWorkspaceId, c as applyTheme, d as noColorRequested, f as theme, g as themeVersion, h as themeModeFromColorFgBg, i as MARK_CELLS, l as findTheme, m as themeMode, n as buildCrashReport, p as themeForMode, r as writeCrashReport, s as DEFAULT_THEME_ID, t as installCrashHandler, u as monoTheme, v as themesForMode } from "./install-DqLgkAHr.mjs";
|
|
3
|
+
import { D as getSavedTheme, E as getReviewStateDir, I as resolveWebUrl, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL, z as saveTheme } from "./print-Bmgp3ZT9.mjs";
|
|
4
4
|
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-BlN_uWmL.mjs";
|
|
5
5
|
import { t as PortalClient } from "./client-Dc7GZ3PG.mjs";
|
|
6
6
|
import { d as makeLineParser, f as parseDaemonMessage, l as daemonPaths, n as ensureDaemonRunning, s as LOCAL_PROTOCOL_VERSION, u as encodeLine } from "./daemon-Co4CtpXZ.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { S as getConfigPath } from "./print-Bmgp3ZT9.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { err, ok } from "neverthrow";
|
|
@@ -8,7 +8,7 @@ import fs from "node:fs";
|
|
|
8
8
|
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name = "skydive-cli";
|
|
11
|
-
var version$1 = "0.3.0-beta.
|
|
11
|
+
var version$1 = "0.3.0-beta.794";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/auth/organization.ts
|
|
@@ -175,6 +175,10 @@ function saveTheme(mode, themeId) {
|
|
|
175
175
|
function getShareMachineDefault() {
|
|
176
176
|
return store.get("shareMachineDefault") ?? false;
|
|
177
177
|
}
|
|
178
|
+
/** Test-only setter; production writes happen by editing config.json. */
|
|
179
|
+
function saveShareMachineDefault(value) {
|
|
180
|
+
store.set("shareMachineDefault", value);
|
|
181
|
+
}
|
|
178
182
|
/**
|
|
179
183
|
* Whether the update check is disabled via config.json (`"updateCheck":
|
|
180
184
|
* false`). The persistent counterpart to the SKYDIVE_NO_UPDATE_CHECK /
|
|
@@ -184,6 +188,52 @@ function getShareMachineDefault() {
|
|
|
184
188
|
function getUpdateCheckDisabled() {
|
|
185
189
|
return store.get("updateCheck") === false;
|
|
186
190
|
}
|
|
191
|
+
/** Test-only setter; production writes happen by editing config.json. */
|
|
192
|
+
function saveUpdateCheck(value) {
|
|
193
|
+
if (value === void 0) {
|
|
194
|
+
store.delete("updateCheck");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
store.set("updateCheck", value);
|
|
198
|
+
}
|
|
199
|
+
function parseBoolean(raw) {
|
|
200
|
+
const v = raw.trim().toLowerCase();
|
|
201
|
+
if ([
|
|
202
|
+
"true",
|
|
203
|
+
"1",
|
|
204
|
+
"yes",
|
|
205
|
+
"on"
|
|
206
|
+
].includes(v)) return ok(true);
|
|
207
|
+
if ([
|
|
208
|
+
"false",
|
|
209
|
+
"0",
|
|
210
|
+
"no",
|
|
211
|
+
"off"
|
|
212
|
+
].includes(v)) return ok(false);
|
|
213
|
+
return err(`Expected a boolean (true/false), got "${raw}".`);
|
|
214
|
+
}
|
|
215
|
+
const PREFERENCES = [{
|
|
216
|
+
key: "shareMachineDefault",
|
|
217
|
+
type: "boolean",
|
|
218
|
+
describe: "Share this machine over the portal on `skydive chat` launch, as if --share-machine were passed. Default false.",
|
|
219
|
+
read: () => getShareMachineDefault(),
|
|
220
|
+
isSet: () => store.has("shareMachineDefault"),
|
|
221
|
+
parse: parseBoolean,
|
|
222
|
+
write: (value) => saveShareMachineDefault(value),
|
|
223
|
+
clear: () => store.delete("shareMachineDefault")
|
|
224
|
+
}, {
|
|
225
|
+
key: "updateCheck",
|
|
226
|
+
type: "boolean",
|
|
227
|
+
describe: "Run the daily background update check and its \"Update available\" notice. Set false to disable. Default true.",
|
|
228
|
+
read: () => !getUpdateCheckDisabled(),
|
|
229
|
+
isSet: () => store.has("updateCheck"),
|
|
230
|
+
parse: parseBoolean,
|
|
231
|
+
write: (value) => saveUpdateCheck(value),
|
|
232
|
+
clear: () => store.delete("updateCheck")
|
|
233
|
+
}];
|
|
234
|
+
function getPreference(key) {
|
|
235
|
+
return PREFERENCES.find((p) => p.key === key);
|
|
236
|
+
}
|
|
187
237
|
|
|
188
238
|
//#endregion
|
|
189
239
|
//#region src/chat/tui/chat/card.ts
|
|
@@ -677,4 +727,4 @@ async function readStdin() {
|
|
|
677
727
|
}
|
|
678
728
|
|
|
679
729
|
//#endregion
|
|
680
|
-
export {
|
|
730
|
+
export { getStoredApiKeyWorkspaceName as A, setLastSeenVersion as B, getLastSeenVersion as C, getSavedTheme as D, getReviewStateDir as E, resolveSession as F, resolveWebUrl as I, saveConfig as L, resolveAppUrl as M, resolveConfig as N, getShareMachineDefault as O, resolveManagementAuth as P, saveSession as R, getConfigPath as S, getPromptHistoryPath as T, API_KEY_PREFIX as _, runPrint as a, PREFERENCES as b, cardActionErrorMessage as c, reconcileMaskedInput as d, resolveConnectUrl as f, API_KEY_FAMILY_PREFIX as g, API_KEYS_URL as h, resolveAgent as i, getUpdateCheckDisabled as j, getStoredApiKeyId as k, parseExternalOauthConnectParams as l, specKeyFor as m, messageGet as n, toPrintError as o, parseConnectCard as p, readStdin as r, MASK_CHAR as s, collectRunText as t, parseOauthConnectParams as u, DEFAULT_API_URL as v, getPreference as w, deleteConfig as x, DEFAULT_APP_URL as y, saveTheme as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-
|
|
2
|
+
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-Bmgp3ZT9.mjs";
|
|
3
3
|
import "./rest-BlN_uWmL.mjs";
|
|
4
4
|
|
|
5
5
|
export { messageGet, readStdin, resolveAgent, runPrint };
|