skydive-cli 0.1.0-beta.342 → 0.1.0-beta.351
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/README.md +21 -1
- package/dist/js/bin.mjs +3 -3
- package/dist/js/{boot-BcuOicbb.mjs → boot-C2plQe9S.mjs} +86 -32
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -70,6 +70,26 @@ skydive portal status
|
|
|
70
70
|
|
|
71
71
|
Global flags: `--json`, `--quiet`, `--api-url <url>`.
|
|
72
72
|
|
|
73
|
+
## Workspaces
|
|
74
|
+
|
|
75
|
+
Every `skydive` command acts inside one **workspace** — the org/team boundary
|
|
76
|
+
that owns your agents, conversations, and secrets. If your account belongs to
|
|
77
|
+
several workspaces (say, your company org and a personal one), the same agent
|
|
78
|
+
name can exist in both, so which workspace is active determines what every
|
|
79
|
+
command sees.
|
|
80
|
+
|
|
81
|
+
- `skydive workspace list` — workspaces on your account, with the active one
|
|
82
|
+
marked.
|
|
83
|
+
- `skydive workspace switch [workspace]` — change the active workspace. All
|
|
84
|
+
commands — `agents`, `secrets`, `keys`, `chat`, `conversations` — follow it.
|
|
85
|
+
- `skydive auth status` — shows who you're logged in as and which workspace is
|
|
86
|
+
active.
|
|
87
|
+
- In the chat TUI, `ctrl+w` switches workspace from the agent picker.
|
|
88
|
+
|
|
89
|
+
The active workspace is stored in the CLI config file and persists across
|
|
90
|
+
invocations. If a command can't find an agent you know exists, check
|
|
91
|
+
`skydive auth status` first — you're probably in the wrong workspace.
|
|
92
|
+
|
|
73
93
|
## `skydive secrets`
|
|
74
94
|
|
|
75
95
|
Manage the environment secrets injected into an agent's sandbox. All
|
|
@@ -250,7 +270,7 @@ environments, and driving agents from other tools:
|
|
|
250
270
|
```sh
|
|
251
271
|
skydive portal open # connect and stay in the foreground (ctrl+c to close)
|
|
252
272
|
skydive portal open --agent grace # …and grant that agent on first connect
|
|
253
|
-
skydive portal open --cwd ~/some/repo # working directory for the agent's commands
|
|
273
|
+
skydive portal open --cwd ~/some/repo # working directory for the agent's commands (a starting point, not a boundary — see above)
|
|
254
274
|
skydive portal grant --agent grace # allow an agent (registers this machine if needed)
|
|
255
275
|
skydive portal revoke --agent grace # remove an agent's access
|
|
256
276
|
skydive portal status # machines, connection state, granted agents
|
package/dist/js/bin.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import zlib from "node:zlib";
|
|
|
16
16
|
import os from "node:os";
|
|
17
17
|
|
|
18
18
|
//#region package.json
|
|
19
|
-
var version$1 = "0.1.0-beta.
|
|
19
|
+
var version$1 = "0.1.0-beta.351";
|
|
20
20
|
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/types.ts
|
|
@@ -2622,7 +2622,7 @@ const chatCommand = {
|
|
|
2622
2622
|
printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
|
|
2623
2623
|
process.exit(1);
|
|
2624
2624
|
}
|
|
2625
|
-
const { runChat } = await import("./boot-
|
|
2625
|
+
const { runChat } = await import("./boot-C2plQe9S.mjs");
|
|
2626
2626
|
await runChat({
|
|
2627
2627
|
appUrl,
|
|
2628
2628
|
sessionToken: session.value.sessionToken,
|
|
@@ -3416,7 +3416,7 @@ const switchCommand = {
|
|
|
3416
3416
|
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.");
|
|
3417
3417
|
process.exit(1);
|
|
3418
3418
|
}
|
|
3419
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
3419
|
+
const { runWorkspacePicker } = await import("./boot-C2plQe9S.mjs");
|
|
3420
3420
|
await runWorkspacePicker(session);
|
|
3421
3421
|
return;
|
|
3422
3422
|
}
|
|
@@ -5285,21 +5285,75 @@ function formatShellContext(command, output, exitCode) {
|
|
|
5285
5285
|
}
|
|
5286
5286
|
|
|
5287
5287
|
//#endregion
|
|
5288
|
-
//#region src/
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
* session into the agent's own sandbox — a live interactive PTY or a one-shot
|
|
5292
|
-
* streamed exec. Mirrors the transport shape of `portal/client.ts`, but dials a
|
|
5293
|
-
* different endpoint and speaks the sandbox-stream frame protocol (see the
|
|
5294
|
-
* server's sandbox-stream-ws.ts).
|
|
5295
|
-
*/
|
|
5296
|
-
const T = {
|
|
5288
|
+
//#region ../sandbox-stream-protocol/src/index.ts
|
|
5289
|
+
const SANDBOX_STREAM_PATH = "/api/v1/sandbox/stream";
|
|
5290
|
+
const FRAME = {
|
|
5297
5291
|
DATA: 1,
|
|
5298
5292
|
EXIT: 2,
|
|
5299
5293
|
ERROR: 3,
|
|
5300
5294
|
INPUT: 16,
|
|
5301
5295
|
RESIZE: 17
|
|
5302
5296
|
};
|
|
5297
|
+
const MAX_INPUT_BYTES = 1 * 1024 * 1024;
|
|
5298
|
+
/** Query params for the upgrade URL, from a spec. Inverse of {@link parseStreamSpec}. */
|
|
5299
|
+
function streamSpecToQuery(spec) {
|
|
5300
|
+
if (spec.mode === "pty") return {
|
|
5301
|
+
agentId: spec.agentId,
|
|
5302
|
+
mode: "pty",
|
|
5303
|
+
cols: String(spec.cols),
|
|
5304
|
+
rows: String(spec.rows)
|
|
5305
|
+
};
|
|
5306
|
+
return {
|
|
5307
|
+
agentId: spec.agentId,
|
|
5308
|
+
mode: "exec",
|
|
5309
|
+
command: spec.command
|
|
5310
|
+
};
|
|
5311
|
+
}
|
|
5312
|
+
function withType(type, payload) {
|
|
5313
|
+
const frame = new Uint8Array(1 + payload.length);
|
|
5314
|
+
frame[0] = type;
|
|
5315
|
+
frame.set(payload, 1);
|
|
5316
|
+
return frame;
|
|
5317
|
+
}
|
|
5318
|
+
/** client → server: keystroke bytes for the pty stdin. */
|
|
5319
|
+
function encodeInput(data) {
|
|
5320
|
+
return withType(FRAME.INPUT, data);
|
|
5321
|
+
}
|
|
5322
|
+
/** client → server: the client terminal was resized. */
|
|
5323
|
+
function encodeResize(cols, rows) {
|
|
5324
|
+
const frame = new Uint8Array(5);
|
|
5325
|
+
frame[0] = FRAME.RESIZE;
|
|
5326
|
+
const view = new DataView(frame.buffer);
|
|
5327
|
+
view.setUint16(1, cols & 65535);
|
|
5328
|
+
view.setUint16(3, rows & 65535);
|
|
5329
|
+
return frame;
|
|
5330
|
+
}
|
|
5331
|
+
const view = (frame) => new DataView(frame.buffer, frame.byteOffset, frame.byteLength);
|
|
5332
|
+
/**
|
|
5333
|
+
* Decode a frame the server sent. Returns null for an empty, unknown, or
|
|
5334
|
+
* truncated frame — a peer speaking a newer protocol must not crash us.
|
|
5335
|
+
*/
|
|
5336
|
+
function decodeServerFrame(frame) {
|
|
5337
|
+
const payload = frame.subarray(1);
|
|
5338
|
+
switch (frame[0]) {
|
|
5339
|
+
case FRAME.DATA: return {
|
|
5340
|
+
type: "data",
|
|
5341
|
+
payload
|
|
5342
|
+
};
|
|
5343
|
+
case FRAME.EXIT: return {
|
|
5344
|
+
type: "exit",
|
|
5345
|
+
code: payload.length >= 4 ? view(frame).getInt32(1) : 0
|
|
5346
|
+
};
|
|
5347
|
+
case FRAME.ERROR: return {
|
|
5348
|
+
type: "error",
|
|
5349
|
+
message: new TextDecoder().decode(payload)
|
|
5350
|
+
};
|
|
5351
|
+
default: return null;
|
|
5352
|
+
}
|
|
5353
|
+
}
|
|
5354
|
+
|
|
5355
|
+
//#endregion
|
|
5356
|
+
//#region src/chat/sandbox/client.ts
|
|
5303
5357
|
function wsBase(appUrl) {
|
|
5304
5358
|
const base = appUrl.replace(/\/+$/, "");
|
|
5305
5359
|
if (base.startsWith("https://")) return `wss://${base.slice(8)}`;
|
|
@@ -5317,26 +5371,25 @@ var SandboxStream = class SandboxStream {
|
|
|
5317
5371
|
this.ws = ws;
|
|
5318
5372
|
ws.on("message", (data, isBinary) => {
|
|
5319
5373
|
if (!isBinary) return;
|
|
5320
|
-
const
|
|
5321
|
-
if (
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
case T.DATA:
|
|
5374
|
+
const frame = decodeServerFrame(toBuffer(data));
|
|
5375
|
+
if (!frame) return;
|
|
5376
|
+
switch (frame.type) {
|
|
5377
|
+
case "data":
|
|
5325
5378
|
onEvent({
|
|
5326
5379
|
type: "data",
|
|
5327
|
-
bytes: new Uint8Array(
|
|
5380
|
+
bytes: new Uint8Array(frame.payload)
|
|
5328
5381
|
});
|
|
5329
5382
|
break;
|
|
5330
|
-
case
|
|
5383
|
+
case "exit":
|
|
5331
5384
|
onEvent({
|
|
5332
5385
|
type: "exit",
|
|
5333
|
-
code:
|
|
5386
|
+
code: frame.code
|
|
5334
5387
|
});
|
|
5335
5388
|
break;
|
|
5336
|
-
case
|
|
5389
|
+
case "error":
|
|
5337
5390
|
onEvent({
|
|
5338
5391
|
type: "error",
|
|
5339
|
-
message:
|
|
5392
|
+
message: frame.message
|
|
5340
5393
|
});
|
|
5341
5394
|
break;
|
|
5342
5395
|
}
|
|
@@ -5350,16 +5403,12 @@ var SandboxStream = class SandboxStream {
|
|
|
5350
5403
|
/** Feed keystroke bytes to the pty stdin. */
|
|
5351
5404
|
sendInput(data) {
|
|
5352
5405
|
if (this.closed || this.ws.readyState !== WebSocket.OPEN) return;
|
|
5353
|
-
this.ws.send(
|
|
5406
|
+
this.ws.send(encodeInput(data));
|
|
5354
5407
|
}
|
|
5355
5408
|
/** Notify the pty of a terminal resize. */
|
|
5356
5409
|
resize(cols, rows) {
|
|
5357
5410
|
if (this.closed || this.ws.readyState !== WebSocket.OPEN) return;
|
|
5358
|
-
|
|
5359
|
-
b[0] = T.RESIZE;
|
|
5360
|
-
b.writeUInt16BE(cols & 65535, 1);
|
|
5361
|
-
b.writeUInt16BE(rows & 65535, 3);
|
|
5362
|
-
this.ws.send(b);
|
|
5411
|
+
this.ws.send(encodeResize(cols, rows));
|
|
5363
5412
|
}
|
|
5364
5413
|
close() {
|
|
5365
5414
|
this.closed = true;
|
|
@@ -5367,13 +5416,18 @@ var SandboxStream = class SandboxStream {
|
|
|
5367
5416
|
}
|
|
5368
5417
|
/** Open a stream. `mode` is 'pty' (interactive) or 'exec' (one-shot). */
|
|
5369
5418
|
static open(opts) {
|
|
5370
|
-
const
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5419
|
+
const spec = opts.mode === "pty" ? {
|
|
5420
|
+
mode: "pty",
|
|
5421
|
+
agentId: opts.agentId,
|
|
5422
|
+
cols: opts.cols,
|
|
5423
|
+
rows: opts.rows
|
|
5424
|
+
} : {
|
|
5425
|
+
mode: "exec",
|
|
5426
|
+
agentId: opts.agentId,
|
|
5427
|
+
command: opts.command
|
|
5428
|
+
};
|
|
5429
|
+
const url = new URL(`${wsBase(opts.appUrl)}${SANDBOX_STREAM_PATH}`);
|
|
5430
|
+
for (const [key, value] of Object.entries(streamSpecToQuery(spec))) url.searchParams.set(key, value);
|
|
5377
5431
|
return new SandboxStream(new WebSocket(url.toString(), { headers: { authorization: `Bearer ${opts.sessionToken}` } }), opts.onEvent);
|
|
5378
5432
|
}
|
|
5379
5433
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skydive-cli",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.351",
|
|
4
4
|
"description": "Skydive CLI — manage AI agents from the command line",
|
|
5
5
|
"homepage": "https://skydive.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@createinc/anyone-portal-protocol": "0.0.0",
|
|
49
|
+
"@createinc/anyone-sandbox-stream-protocol": "0.0.0",
|
|
49
50
|
"@createinc/tsconfig": "0.0.0",
|
|
50
51
|
"@types/bun": "^1.3.14",
|
|
51
52
|
"@types/node": "^24.0.0",
|