@agentsky/sky 2.10.0 → 2.12.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/dist/chunk-7LUCHBX6.js +168 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-RF5JICNX.js +54 -0
- package/dist/{chunk-5QRKU3BR.js → chunk-XXDQKVPS.js} +2690 -2566
- package/dist/harness-connect-DUC7GIBL.js +102 -0
- package/dist/index.js +862 -328
- package/dist/products.d.ts +9 -0
- package/dist/products.js +2 -1
- package/dist/{src-RYECJN5I.js → src-S777KCS5.js} +21 -2
- package/dist/trace-UJTFSXNM.js +367 -0
- package/dist/trace-library-474QJTAZ.js +710 -0
- package/dist/worker-6Q4K4HZW.js +190 -0
- package/package.json +4 -3
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import "./chunk-MLKGABMK.js";
|
|
2
|
+
|
|
3
|
+
// src/worker.ts
|
|
4
|
+
import { mkdirSync, writeFileSync, rmSync } from "fs";
|
|
5
|
+
import { tmpdir } from "os";
|
|
6
|
+
import { join } from "path";
|
|
7
|
+
import { randomBytes } from "crypto";
|
|
8
|
+
var RealDockerRunner = class {
|
|
9
|
+
async run({ image, envFile, port, signal }) {
|
|
10
|
+
const { spawn } = await import("child_process");
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const child = spawn(
|
|
13
|
+
"docker",
|
|
14
|
+
[
|
|
15
|
+
"run",
|
|
16
|
+
"--rm",
|
|
17
|
+
"--pull=always",
|
|
18
|
+
`--env-file=${envFile}`,
|
|
19
|
+
`-p`,
|
|
20
|
+
`127.0.0.1:${port}:8080`,
|
|
21
|
+
image
|
|
22
|
+
],
|
|
23
|
+
{ stdio: "inherit" }
|
|
24
|
+
);
|
|
25
|
+
signal.addEventListener("abort", () => {
|
|
26
|
+
child.kill("SIGTERM");
|
|
27
|
+
});
|
|
28
|
+
child.on("error", reject);
|
|
29
|
+
child.on("exit", (code) => {
|
|
30
|
+
if (code === 0 || signal.aborted) resolve();
|
|
31
|
+
else reject(new Error(`docker exited with code ${code}`));
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var POD_PORT = 18080;
|
|
37
|
+
var HEARTBEAT_INTERVAL_MS = 15e3;
|
|
38
|
+
async function startWorker(opts) {
|
|
39
|
+
const docker = opts.docker ?? new RealDockerRunner();
|
|
40
|
+
const signal = opts.signal ?? new AbortController().signal;
|
|
41
|
+
const wsUrl = opts.apiBase.replace(/^https?:\/\//, (m) => m === "https://" ? "wss://" : "ws://").replace(/\/$/, "");
|
|
42
|
+
const connectUrl = `${wsUrl}/api/v1/worker-pools/${opts.poolId}/connect`;
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
import("ws").then(({ default: WS }) => {
|
|
45
|
+
const ws = new WS(connectUrl, {
|
|
46
|
+
headers: { authorization: `Bearer ${opts.token}` }
|
|
47
|
+
});
|
|
48
|
+
let currentContainer = null;
|
|
49
|
+
const heartbeatTimer = setInterval(() => {
|
|
50
|
+
if (ws.readyState === WS.OPEN) {
|
|
51
|
+
ws.send(JSON.stringify({ type: "heartbeat" }));
|
|
52
|
+
}
|
|
53
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
54
|
+
signal.addEventListener("abort", () => {
|
|
55
|
+
clearInterval(heartbeatTimer);
|
|
56
|
+
currentContainer?.abort();
|
|
57
|
+
ws.close();
|
|
58
|
+
resolve();
|
|
59
|
+
});
|
|
60
|
+
ws.on("open", () => {
|
|
61
|
+
ws.send(JSON.stringify({
|
|
62
|
+
type: "hello",
|
|
63
|
+
label: opts.label,
|
|
64
|
+
imageDigest: "unknown",
|
|
65
|
+
capacity: 1
|
|
66
|
+
}));
|
|
67
|
+
console.log(`[sky worker] connected to pool ${opts.poolId}`);
|
|
68
|
+
});
|
|
69
|
+
ws.on("message", async (raw) => {
|
|
70
|
+
let msg;
|
|
71
|
+
try {
|
|
72
|
+
msg = JSON.parse(raw.toString());
|
|
73
|
+
} catch {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (msg.type === "start") {
|
|
77
|
+
await handleStart(msg, ws, WS, docker, currentContainer);
|
|
78
|
+
} else if (msg.type === "stop") {
|
|
79
|
+
currentContainer?.abort();
|
|
80
|
+
currentContainer = null;
|
|
81
|
+
} else if (msg.type === "http") {
|
|
82
|
+
await handleHttp(msg, ws);
|
|
83
|
+
} else if (msg.type === "stream_open") {
|
|
84
|
+
void handleStreamOpen(msg, ws);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
ws.on("close", () => {
|
|
88
|
+
clearInterval(heartbeatTimer);
|
|
89
|
+
currentContainer?.abort();
|
|
90
|
+
resolve();
|
|
91
|
+
});
|
|
92
|
+
ws.on("error", (err) => {
|
|
93
|
+
clearInterval(heartbeatTimer);
|
|
94
|
+
currentContainer?.abort();
|
|
95
|
+
reject(err);
|
|
96
|
+
});
|
|
97
|
+
}).catch(reject);
|
|
98
|
+
});
|
|
99
|
+
async function handleStart(msg, ws, WS, docker2, existingContainer) {
|
|
100
|
+
if (existingContainer) existingContainer.abort();
|
|
101
|
+
const dir = join(tmpdir(), `sky-worker-${randomBytes(6).toString("hex")}`);
|
|
102
|
+
mkdirSync(dir, { mode: 448 });
|
|
103
|
+
const envFile = join(dir, "pod.env");
|
|
104
|
+
const envLines = Object.entries(msg.env).map(([k, v]) => `${k}=${v.replace(/\n/g, "\\n")}`).join("\n");
|
|
105
|
+
writeFileSync(envFile, envLines, { mode: 384 });
|
|
106
|
+
const containerAbort = new AbortController();
|
|
107
|
+
try {
|
|
108
|
+
void docker2.run({
|
|
109
|
+
image: msg.image,
|
|
110
|
+
envFile,
|
|
111
|
+
port: POD_PORT,
|
|
112
|
+
signal: containerAbort.signal
|
|
113
|
+
}).finally(() => {
|
|
114
|
+
try {
|
|
115
|
+
rmSync(dir, { recursive: true });
|
|
116
|
+
} catch {
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
} catch (err) {
|
|
120
|
+
try {
|
|
121
|
+
rmSync(dir, { recursive: true });
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
console.error("[sky worker] docker run failed:", err);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function handleHttp(msg, ws) {
|
|
128
|
+
const url = `http://127.0.0.1:${POD_PORT}${msg.path}`;
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch(url, {
|
|
131
|
+
method: msg.method,
|
|
132
|
+
headers: msg.headers,
|
|
133
|
+
body: msg.body || void 0,
|
|
134
|
+
signal: AbortSignal.timeout(3e4)
|
|
135
|
+
});
|
|
136
|
+
const body = await response.text();
|
|
137
|
+
const headers = {};
|
|
138
|
+
response.headers.forEach((v, k) => {
|
|
139
|
+
headers[k] = v;
|
|
140
|
+
});
|
|
141
|
+
const resp = {
|
|
142
|
+
type: "http_response",
|
|
143
|
+
id: msg.id,
|
|
144
|
+
status: response.status,
|
|
145
|
+
headers,
|
|
146
|
+
body
|
|
147
|
+
};
|
|
148
|
+
ws.send(JSON.stringify(resp));
|
|
149
|
+
} catch (err) {
|
|
150
|
+
ws.send(JSON.stringify({
|
|
151
|
+
type: "http_response",
|
|
152
|
+
id: msg.id,
|
|
153
|
+
status: 502,
|
|
154
|
+
headers: {},
|
|
155
|
+
body: String(err)
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function handleStreamOpen(msg, ws) {
|
|
160
|
+
const url = `http://127.0.0.1:${POD_PORT}${msg.path}`;
|
|
161
|
+
try {
|
|
162
|
+
const response = await fetch(url, {
|
|
163
|
+
headers: { accept: "text/event-stream" },
|
|
164
|
+
signal: AbortSignal.timeout(3e5)
|
|
165
|
+
});
|
|
166
|
+
const reader = response.body?.getReader();
|
|
167
|
+
if (!reader) {
|
|
168
|
+
ws.send(JSON.stringify({ type: "stream_close", id: msg.id }));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const decoder = new TextDecoder();
|
|
172
|
+
for (; ; ) {
|
|
173
|
+
const { done, value } = await reader.read();
|
|
174
|
+
if (done) break;
|
|
175
|
+
ws.send(JSON.stringify({
|
|
176
|
+
type: "stream_event",
|
|
177
|
+
id: msg.id,
|
|
178
|
+
data: decoder.decode(value, { stream: true })
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
ws.send(JSON.stringify({ type: "stream_close", id: msg.id }));
|
|
182
|
+
} catch {
|
|
183
|
+
ws.send(JSON.stringify({ type: "stream_close", id: msg.id }));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
RealDockerRunner,
|
|
189
|
+
startWorker
|
|
190
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentsky/sky",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "sky
|
|
3
|
+
"version": "2.12.0",
|
|
4
|
+
"description": "sky \u2014 the AgentSky developer CLI: launch and talk to long-lived agents from your terminal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"commander": "^14.0.0",
|
|
24
24
|
"smol-toml": "^1.4.2",
|
|
25
|
-
"zod": "4.5.4"
|
|
25
|
+
"zod": "4.5.4",
|
|
26
|
+
"ws": "^8.18.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@agent/chat": "*",
|