skydive-cli 0.1.0-beta.347 → 0.1.0-beta.353
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/js/bin.mjs
CHANGED
|
@@ -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.353";
|
|
20
20
|
|
|
21
21
|
//#endregion
|
|
22
22
|
//#region src/types.ts
|
|
@@ -1033,15 +1033,6 @@ function createRestClient({ appUrl, sessionToken }) {
|
|
|
1033
1033
|
...input,
|
|
1034
1034
|
clientSurface
|
|
1035
1035
|
}, sendResultSchema),
|
|
1036
|
-
activeRun: async ({ conversationId }) => {
|
|
1037
|
-
const { run } = await get(`/api/v1/chat/active-run?${new URLSearchParams({ conversationId }).toString()}`, activeRunResponseSchema);
|
|
1038
|
-
if (!run) return null;
|
|
1039
|
-
return {
|
|
1040
|
-
runId: run.runId,
|
|
1041
|
-
agentId: run.agentId ?? "",
|
|
1042
|
-
agentName: run.agentName ?? ""
|
|
1043
|
-
};
|
|
1044
|
-
},
|
|
1045
1036
|
cancelRun: async ({ runId }) => {
|
|
1046
1037
|
await post(`/api/v1/chat/runs/${encodeURIComponent(runId)}/cancel`, {}, z.object({ ok: z.boolean() }));
|
|
1047
1038
|
},
|
|
@@ -1236,11 +1227,6 @@ const finalizeResponseSchema = z.object({
|
|
|
1236
1227
|
mediaType: z.string(),
|
|
1237
1228
|
sizeBytes: z.number().nullable().optional()
|
|
1238
1229
|
});
|
|
1239
|
-
const activeRunResponseSchema = z.object({ run: z.object({
|
|
1240
|
-
runId: z.string(),
|
|
1241
|
-
agentId: z.string().nullish(),
|
|
1242
|
-
agentName: z.string().nullish()
|
|
1243
|
-
}).nullable() });
|
|
1244
1230
|
const oauthConnectResponseSchema = z.object({ connectLink: z.string() }).passthrough();
|
|
1245
1231
|
const externalOauthConnectResponseSchema = z.object({ authorizationUrl: z.string().optional() }).passthrough();
|
|
1246
1232
|
const runStreamEventSchema = z.union([z.object({
|
|
@@ -1252,11 +1238,14 @@ const runStreamEventSchema = z.union([z.object({
|
|
|
1252
1238
|
error: z.string().nullish()
|
|
1253
1239
|
})]);
|
|
1254
1240
|
const streamErrorSchema = z.object({ error: z.string() });
|
|
1255
|
-
const conversationStreamEventSchema = z.object({
|
|
1241
|
+
const conversationStreamEventSchema = z.discriminatedUnion("kind", [z.object({
|
|
1256
1242
|
kind: z.literal("conversation"),
|
|
1257
1243
|
id: z.string(),
|
|
1258
1244
|
title: z.string().nullable()
|
|
1259
|
-
})
|
|
1245
|
+
}), z.object({
|
|
1246
|
+
kind: z.literal("run"),
|
|
1247
|
+
runId: z.string()
|
|
1248
|
+
})]);
|
|
1260
1249
|
|
|
1261
1250
|
//#endregion
|
|
1262
1251
|
//#region src/commands/session.ts
|
|
@@ -2622,7 +2611,7 @@ const chatCommand = {
|
|
|
2622
2611
|
printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
|
|
2623
2612
|
process.exit(1);
|
|
2624
2613
|
}
|
|
2625
|
-
const { runChat } = await import("./boot-
|
|
2614
|
+
const { runChat } = await import("./boot-DLHvjtxn.mjs");
|
|
2626
2615
|
await runChat({
|
|
2627
2616
|
appUrl,
|
|
2628
2617
|
sessionToken: session.value.sessionToken,
|
|
@@ -3416,7 +3405,7 @@ const switchCommand = {
|
|
|
3416
3405
|
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
3406
|
process.exit(1);
|
|
3418
3407
|
}
|
|
3419
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
3408
|
+
const { runWorkspacePicker } = await import("./boot-DLHvjtxn.mjs");
|
|
3420
3409
|
await runWorkspacePicker(session);
|
|
3421
3410
|
return;
|
|
3422
3411
|
}
|
|
@@ -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
|
};
|
|
@@ -5594,6 +5648,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5594
5648
|
inputRef.current = input;
|
|
5595
5649
|
const credPromptRef = useRef(credPrompt);
|
|
5596
5650
|
credPromptRef.current = credPrompt;
|
|
5651
|
+
const seenRunsRef = useRef(/* @__PURE__ */ new Set());
|
|
5597
5652
|
const shellSessionRef = useRef(null);
|
|
5598
5653
|
const hostState = grantPrompt || credPrompt ? "blocked" : run.kind === "idle" ? "idle" : "working";
|
|
5599
5654
|
useEffect(() => {
|
|
@@ -5667,6 +5722,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5667
5722
|
}, [rest, initialConversationId]);
|
|
5668
5723
|
const attachToRun = useCallback((runId, runAgentName) => {
|
|
5669
5724
|
if (!rest) return;
|
|
5725
|
+
seenRunsRef.current.add(runId);
|
|
5670
5726
|
const abort = new AbortController();
|
|
5671
5727
|
const responsePreview = createResponsePreview();
|
|
5672
5728
|
const streamAgentName = runAgentName ?? agent.name;
|
|
@@ -5727,6 +5783,12 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5727
5783
|
conversationId,
|
|
5728
5784
|
signal: abort.signal,
|
|
5729
5785
|
onEvent: (event) => {
|
|
5786
|
+
if (event.kind === "run") {
|
|
5787
|
+
if (seenRunsRef.current.has(event.runId)) return;
|
|
5788
|
+
if (runRef.current.kind !== "idle") return;
|
|
5789
|
+
attachToRun(event.runId);
|
|
5790
|
+
return;
|
|
5791
|
+
}
|
|
5730
5792
|
if (event.title) setChatTitle(event.title);
|
|
5731
5793
|
}
|
|
5732
5794
|
}).catch(() => {});
|
|
@@ -5734,22 +5796,9 @@ function ChatScreen({ agent, conversation }) {
|
|
|
5734
5796
|
}, [
|
|
5735
5797
|
rest,
|
|
5736
5798
|
conversationId,
|
|
5737
|
-
setChatTitle
|
|
5799
|
+
setChatTitle,
|
|
5800
|
+
attachToRun
|
|
5738
5801
|
]);
|
|
5739
|
-
useEffect(() => {
|
|
5740
|
-
if (!rest || !conversationId) return;
|
|
5741
|
-
let cancelled = false;
|
|
5742
|
-
(async () => {
|
|
5743
|
-
try {
|
|
5744
|
-
const active = await rest.activeRun({ conversationId });
|
|
5745
|
-
if (cancelled || !active) return;
|
|
5746
|
-
attachToRun(active.runId, active.agentName || null);
|
|
5747
|
-
} catch (_error) {}
|
|
5748
|
-
})();
|
|
5749
|
-
return () => {
|
|
5750
|
-
cancelled = true;
|
|
5751
|
-
};
|
|
5752
|
-
}, []);
|
|
5753
5802
|
const sendContent = useCallback(async (content, staged, opts) => {
|
|
5754
5803
|
if (!rest) return;
|
|
5755
5804
|
const trimmed = content.trim();
|
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.353",
|
|
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",
|