agentkernel 0.8.0 → 0.10.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/README.md +138 -3
- package/dist/index.cjs +264 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +173 -5
- package/dist/index.d.ts +173 -5
- package/dist/index.js +262 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,105 @@ console.log(result.output);
|
|
|
37
37
|
// sandbox auto-removed when scope exits
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
## Exec Options
|
|
41
|
+
|
|
42
|
+
Run commands with a working directory, environment variables, or as root:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
const result = await client.execInSandbox("my-sandbox", ["npm", "start"], {
|
|
46
|
+
workdir: "/app",
|
|
47
|
+
env: ["NODE_ENV=production"],
|
|
48
|
+
sudo: true,
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Works on sandbox sessions too:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
await using sb = await client.sandbox("dev");
|
|
56
|
+
await sb.run(["pip", "install", "-r", "requirements.txt"], {
|
|
57
|
+
workdir: "/app",
|
|
58
|
+
sudo: true,
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Git Source Cloning
|
|
63
|
+
|
|
64
|
+
Clone a git repo into the sandbox at creation time:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
const sb = await client.createSandbox("my-project", {
|
|
68
|
+
image: "node:20-alpine",
|
|
69
|
+
source_url: "https://github.com/user/repo.git",
|
|
70
|
+
source_ref: "main",
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Persistent Volumes
|
|
75
|
+
|
|
76
|
+
Mount volumes that persist across sandbox restarts:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// First create volumes via CLI: agentkernel volume create mydata
|
|
80
|
+
|
|
81
|
+
const sb = await client.createSandbox("my-project", {
|
|
82
|
+
image: "node:20-alpine",
|
|
83
|
+
volumes: ["mydata:/data", "cache:/tmp/cache:ro"],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Data in /data persists across sandbox restarts
|
|
87
|
+
await sb.run(["sh", "-c", "echo hello > /data/test.txt"]);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## File Operations
|
|
91
|
+
|
|
92
|
+
Read, write, and delete files in a sandbox:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// Write a file
|
|
96
|
+
await client.writeFile("my-sandbox", "app/main.py", "print('hello')");
|
|
97
|
+
|
|
98
|
+
// Read a file
|
|
99
|
+
const file = await client.readFile("my-sandbox", "app/main.py");
|
|
100
|
+
console.log(file.content);
|
|
101
|
+
|
|
102
|
+
// Delete a file
|
|
103
|
+
await client.deleteFile("my-sandbox", "app/main.py");
|
|
104
|
+
|
|
105
|
+
// Batch write multiple files at once
|
|
106
|
+
await client.writeFiles("my-sandbox", {
|
|
107
|
+
"/app/index.js": "console.log('hi')",
|
|
108
|
+
"/app/package.json": '{"name":"app"}',
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Detached Commands
|
|
113
|
+
|
|
114
|
+
Run long-lived processes in the background and retrieve their output later:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Start a background process
|
|
118
|
+
const cmd = await client.execDetached("my-sandbox", ["python3", "train.py"]);
|
|
119
|
+
console.log(`Started: ${cmd.id} (pid ${cmd.pid})`);
|
|
120
|
+
|
|
121
|
+
// Check status
|
|
122
|
+
const status = await client.detachedStatus("my-sandbox", cmd.id);
|
|
123
|
+
console.log(status.status); // "running" | "completed" | "failed"
|
|
124
|
+
|
|
125
|
+
// Get logs
|
|
126
|
+
const logs = await client.detachedLogs("my-sandbox", cmd.id);
|
|
127
|
+
console.log(logs.stdout);
|
|
128
|
+
|
|
129
|
+
// Get stderr only
|
|
130
|
+
const stderr = await client.detachedLogs("my-sandbox", cmd.id, "stderr");
|
|
131
|
+
|
|
132
|
+
// List all detached commands
|
|
133
|
+
const all = await client.detachedList("my-sandbox");
|
|
134
|
+
|
|
135
|
+
// Kill a running command
|
|
136
|
+
await client.detachedKill("my-sandbox", cmd.id);
|
|
137
|
+
```
|
|
138
|
+
|
|
40
139
|
## Streaming
|
|
41
140
|
|
|
42
141
|
```typescript
|
|
@@ -91,7 +190,7 @@ List all sandboxes.
|
|
|
91
190
|
|
|
92
191
|
### `client.createSandbox(name, options?)`
|
|
93
192
|
|
|
94
|
-
Create a new sandbox.
|
|
193
|
+
Create a new sandbox. Options: `image`, `vcpus`, `memory_mb`, `profile`, `source_url`, `source_ref`, `volumes`.
|
|
95
194
|
|
|
96
195
|
### `client.getSandbox(name)`
|
|
97
196
|
|
|
@@ -101,9 +200,45 @@ Get sandbox info.
|
|
|
101
200
|
|
|
102
201
|
Remove a sandbox.
|
|
103
202
|
|
|
104
|
-
### `client.execInSandbox(name, command)`
|
|
203
|
+
### `client.execInSandbox(name, command, options?)`
|
|
204
|
+
|
|
205
|
+
Run a command in an existing sandbox. Options: `env`, `workdir`, `sudo`.
|
|
206
|
+
|
|
207
|
+
### `client.readFile(name, path)`
|
|
208
|
+
|
|
209
|
+
Read a file from a sandbox.
|
|
210
|
+
|
|
211
|
+
### `client.writeFile(name, path, content, options?)`
|
|
212
|
+
|
|
213
|
+
Write a file to a sandbox.
|
|
214
|
+
|
|
215
|
+
### `client.deleteFile(name, path)`
|
|
216
|
+
|
|
217
|
+
Delete a file from a sandbox.
|
|
218
|
+
|
|
219
|
+
### `client.writeFiles(name, files)`
|
|
220
|
+
|
|
221
|
+
Write multiple files to a sandbox in one request. `files` is a `Record<string, string>` of path to content.
|
|
222
|
+
|
|
223
|
+
### `client.execDetached(name, command, options?)`
|
|
224
|
+
|
|
225
|
+
Start a detached (background) command. Returns a `DetachedCommand`.
|
|
226
|
+
|
|
227
|
+
### `client.detachedStatus(name, cmdId)`
|
|
228
|
+
|
|
229
|
+
Get the status of a detached command.
|
|
230
|
+
|
|
231
|
+
### `client.detachedLogs(name, cmdId, stream?)`
|
|
232
|
+
|
|
233
|
+
Get stdout/stderr from a detached command. Pass `"stderr"` to get only stderr.
|
|
234
|
+
|
|
235
|
+
### `client.detachedKill(name, cmdId)`
|
|
236
|
+
|
|
237
|
+
Kill a detached command.
|
|
238
|
+
|
|
239
|
+
### `client.detachedList(name)`
|
|
105
240
|
|
|
106
|
-
|
|
241
|
+
List all detached commands in a sandbox.
|
|
107
242
|
|
|
108
243
|
### `client.sandbox(name, options?)`
|
|
109
244
|
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
AgentKernel: () => AgentKernel,
|
|
24
24
|
AgentKernelError: () => AgentKernelError,
|
|
25
25
|
AuthError: () => AuthError,
|
|
26
|
+
BROWSER_SETUP_CMD: () => BROWSER_SETUP_CMD,
|
|
27
|
+
BrowserSession: () => BrowserSession,
|
|
26
28
|
NetworkError: () => NetworkError,
|
|
27
29
|
NotFoundError: () => NotFoundError,
|
|
28
30
|
SandboxSession: () => SandboxSession,
|
|
@@ -113,6 +115,127 @@ function errorFromStatus(status, body) {
|
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
|
|
118
|
+
// src/browser.ts
|
|
119
|
+
var GOTO_SCRIPT = `
|
|
120
|
+
import asyncio, json, sys
|
|
121
|
+
from playwright.async_api import async_playwright
|
|
122
|
+
async def main():
|
|
123
|
+
url = sys.argv[1]
|
|
124
|
+
async with async_playwright() as p:
|
|
125
|
+
b = await p.chromium.launch()
|
|
126
|
+
page = await b.new_page()
|
|
127
|
+
await page.goto(url, timeout=30000)
|
|
128
|
+
title = await page.title()
|
|
129
|
+
url_final = page.url
|
|
130
|
+
text = await page.evaluate("() => document.body.innerText.slice(0, 8000)")
|
|
131
|
+
links = await page.evaluate('''() =>
|
|
132
|
+
Array.from(document.querySelectorAll('a[href]'))
|
|
133
|
+
.slice(0, 50)
|
|
134
|
+
.map(a => ({text: a.textContent.trim(), href: a.href}))
|
|
135
|
+
.filter(l => l.href.startsWith("http"))
|
|
136
|
+
''')
|
|
137
|
+
print(json.dumps({"title": title, "url": url_final, "text": text, "links": links}))
|
|
138
|
+
await b.close()
|
|
139
|
+
asyncio.run(main())
|
|
140
|
+
`;
|
|
141
|
+
var SCREENSHOT_SCRIPT = `
|
|
142
|
+
import asyncio, base64, sys
|
|
143
|
+
from playwright.async_api import async_playwright
|
|
144
|
+
async def main():
|
|
145
|
+
url = sys.argv[1]
|
|
146
|
+
async with async_playwright() as p:
|
|
147
|
+
b = await p.chromium.launch()
|
|
148
|
+
page = await b.new_page()
|
|
149
|
+
await page.goto(url, timeout=30000)
|
|
150
|
+
data = await page.screenshot()
|
|
151
|
+
print(base64.b64encode(data).decode())
|
|
152
|
+
await b.close()
|
|
153
|
+
asyncio.run(main())
|
|
154
|
+
`;
|
|
155
|
+
var EVALUATE_SCRIPT = `
|
|
156
|
+
import asyncio, json, sys
|
|
157
|
+
from playwright.async_api import async_playwright
|
|
158
|
+
async def main():
|
|
159
|
+
url = sys.argv[1]
|
|
160
|
+
expr = sys.argv[2]
|
|
161
|
+
async with async_playwright() as p:
|
|
162
|
+
b = await p.chromium.launch()
|
|
163
|
+
page = await b.new_page()
|
|
164
|
+
await page.goto(url, timeout=30000)
|
|
165
|
+
result = await page.evaluate(expr)
|
|
166
|
+
print(json.dumps(result))
|
|
167
|
+
await b.close()
|
|
168
|
+
asyncio.run(main())
|
|
169
|
+
`;
|
|
170
|
+
var BROWSER_SETUP_CMD = [
|
|
171
|
+
"sh",
|
|
172
|
+
"-c",
|
|
173
|
+
"pip install -q playwright && playwright install --with-deps chromium"
|
|
174
|
+
];
|
|
175
|
+
var BrowserSession = class {
|
|
176
|
+
name;
|
|
177
|
+
_removed = false;
|
|
178
|
+
_lastUrl = null;
|
|
179
|
+
_run;
|
|
180
|
+
_remove;
|
|
181
|
+
/** @internal */
|
|
182
|
+
constructor(name, runFn, removeFn) {
|
|
183
|
+
this.name = name;
|
|
184
|
+
this._run = runFn;
|
|
185
|
+
this._remove = removeFn;
|
|
186
|
+
}
|
|
187
|
+
/** Navigate to a URL and return page data (title, text, links). */
|
|
188
|
+
async goto(url) {
|
|
189
|
+
const result = await this._run(this.name, [
|
|
190
|
+
"python3",
|
|
191
|
+
"-c",
|
|
192
|
+
GOTO_SCRIPT,
|
|
193
|
+
url
|
|
194
|
+
]);
|
|
195
|
+
this._lastUrl = url;
|
|
196
|
+
return JSON.parse(result.output);
|
|
197
|
+
}
|
|
198
|
+
/** Take a PNG screenshot. Returns a base64-encoded string. */
|
|
199
|
+
async screenshot(url) {
|
|
200
|
+
const target = url ?? this._lastUrl;
|
|
201
|
+
if (!target) {
|
|
202
|
+
throw new Error("No URL specified and no previous goto() call");
|
|
203
|
+
}
|
|
204
|
+
const result = await this._run(this.name, [
|
|
205
|
+
"python3",
|
|
206
|
+
"-c",
|
|
207
|
+
SCREENSHOT_SCRIPT,
|
|
208
|
+
target
|
|
209
|
+
]);
|
|
210
|
+
return result.output.trim();
|
|
211
|
+
}
|
|
212
|
+
/** Run a JavaScript expression on a page and return the result. */
|
|
213
|
+
async evaluate(expression, url) {
|
|
214
|
+
const target = url ?? this._lastUrl;
|
|
215
|
+
if (!target) {
|
|
216
|
+
throw new Error("No URL specified and no previous goto() call");
|
|
217
|
+
}
|
|
218
|
+
const result = await this._run(this.name, [
|
|
219
|
+
"python3",
|
|
220
|
+
"-c",
|
|
221
|
+
EVALUATE_SCRIPT,
|
|
222
|
+
target,
|
|
223
|
+
expression
|
|
224
|
+
]);
|
|
225
|
+
return JSON.parse(result.output);
|
|
226
|
+
}
|
|
227
|
+
/** Remove the sandbox. Idempotent. */
|
|
228
|
+
async remove() {
|
|
229
|
+
if (this._removed) return;
|
|
230
|
+
this._removed = true;
|
|
231
|
+
await this._remove(this.name);
|
|
232
|
+
}
|
|
233
|
+
/** Auto-cleanup for `await using`. */
|
|
234
|
+
async [Symbol.asyncDispose]() {
|
|
235
|
+
await this.remove();
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
116
239
|
// src/sandbox.ts
|
|
117
240
|
var SandboxSession = class {
|
|
118
241
|
name;
|
|
@@ -120,21 +243,27 @@ var SandboxSession = class {
|
|
|
120
243
|
_execInSandbox;
|
|
121
244
|
_removeSandbox;
|
|
122
245
|
_getSandbox;
|
|
246
|
+
_writeFiles;
|
|
123
247
|
/** @internal */
|
|
124
|
-
constructor(name, execInSandbox, removeSandbox, getSandbox) {
|
|
248
|
+
constructor(name, execInSandbox, removeSandbox, getSandbox, writeFiles) {
|
|
125
249
|
this.name = name;
|
|
126
250
|
this._execInSandbox = execInSandbox;
|
|
127
251
|
this._removeSandbox = removeSandbox;
|
|
128
252
|
this._getSandbox = getSandbox;
|
|
253
|
+
this._writeFiles = writeFiles;
|
|
129
254
|
}
|
|
130
255
|
/** Run a command in this sandbox. */
|
|
131
|
-
async run(command) {
|
|
132
|
-
return this._execInSandbox(this.name, command);
|
|
256
|
+
async run(command, opts) {
|
|
257
|
+
return this._execInSandbox(this.name, command, opts);
|
|
133
258
|
}
|
|
134
259
|
/** Get sandbox info. */
|
|
135
260
|
async info() {
|
|
136
261
|
return this._getSandbox(this.name);
|
|
137
262
|
}
|
|
263
|
+
/** Write multiple files in one request. */
|
|
264
|
+
async writeFiles(files) {
|
|
265
|
+
return this._writeFiles(this.name, files);
|
|
266
|
+
}
|
|
138
267
|
/** Remove the sandbox. Idempotent. */
|
|
139
268
|
async remove() {
|
|
140
269
|
if (this._removed) return;
|
|
@@ -217,7 +346,7 @@ async function* parseSSE(body) {
|
|
|
217
346
|
}
|
|
218
347
|
|
|
219
348
|
// src/client.ts
|
|
220
|
-
var SDK_VERSION = "0.
|
|
349
|
+
var SDK_VERSION = "0.3.0";
|
|
221
350
|
var AgentKernel = class {
|
|
222
351
|
baseUrl;
|
|
223
352
|
apiKey;
|
|
@@ -285,7 +414,10 @@ var AgentKernel = class {
|
|
|
285
414
|
image: opts?.image,
|
|
286
415
|
vcpus: opts?.vcpus,
|
|
287
416
|
memory_mb: opts?.memory_mb,
|
|
288
|
-
profile: opts?.profile
|
|
417
|
+
profile: opts?.profile,
|
|
418
|
+
source_url: opts?.source_url,
|
|
419
|
+
source_ref: opts?.source_ref,
|
|
420
|
+
volumes: opts?.volumes
|
|
289
421
|
});
|
|
290
422
|
}
|
|
291
423
|
/** Get info about a sandbox. */
|
|
@@ -297,11 +429,16 @@ var AgentKernel = class {
|
|
|
297
429
|
await this.request("DELETE", `/sandboxes/${encodeURIComponent(name)}`);
|
|
298
430
|
}
|
|
299
431
|
/** Run a command in an existing sandbox. */
|
|
300
|
-
async execInSandbox(name, command) {
|
|
432
|
+
async execInSandbox(name, command, opts) {
|
|
301
433
|
return this.request(
|
|
302
434
|
"POST",
|
|
303
435
|
`/sandboxes/${encodeURIComponent(name)}/exec`,
|
|
304
|
-
{
|
|
436
|
+
{
|
|
437
|
+
command,
|
|
438
|
+
env: opts?.env,
|
|
439
|
+
workdir: opts?.workdir,
|
|
440
|
+
sudo: opts?.sudo
|
|
441
|
+
}
|
|
305
442
|
);
|
|
306
443
|
}
|
|
307
444
|
/** Read a file from a sandbox. */
|
|
@@ -333,10 +470,60 @@ var AgentKernel = class {
|
|
|
333
470
|
`/sandboxes/${encodeURIComponent(name)}/logs`
|
|
334
471
|
);
|
|
335
472
|
}
|
|
473
|
+
/** Write multiple files to a sandbox in one request. */
|
|
474
|
+
async writeFiles(name, files) {
|
|
475
|
+
return this.request(
|
|
476
|
+
"POST",
|
|
477
|
+
`/sandboxes/${encodeURIComponent(name)}/files`,
|
|
478
|
+
{ files }
|
|
479
|
+
);
|
|
480
|
+
}
|
|
336
481
|
/** Run multiple commands in parallel. */
|
|
337
482
|
async batchRun(commands) {
|
|
338
483
|
return this.request("POST", "/batch/run", { commands });
|
|
339
484
|
}
|
|
485
|
+
/** Start a detached (background) command in a sandbox. */
|
|
486
|
+
async execDetached(name, command, opts) {
|
|
487
|
+
return this.request(
|
|
488
|
+
"POST",
|
|
489
|
+
`/sandboxes/${encodeURIComponent(name)}/exec/detach`,
|
|
490
|
+
{
|
|
491
|
+
command,
|
|
492
|
+
env: opts?.env,
|
|
493
|
+
workdir: opts?.workdir,
|
|
494
|
+
sudo: opts?.sudo
|
|
495
|
+
}
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
/** Get the status of a detached command. */
|
|
499
|
+
async detachedStatus(name, cmdId) {
|
|
500
|
+
return this.request(
|
|
501
|
+
"GET",
|
|
502
|
+
`/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
/** Get logs from a detached command. */
|
|
506
|
+
async detachedLogs(name, cmdId, stream) {
|
|
507
|
+
const query = stream === "stderr" ? "?stream=stderr" : "";
|
|
508
|
+
return this.request(
|
|
509
|
+
"GET",
|
|
510
|
+
`/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
/** Kill a detached command. */
|
|
514
|
+
async detachedKill(name, cmdId) {
|
|
515
|
+
return this.request(
|
|
516
|
+
"DELETE",
|
|
517
|
+
`/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
/** List detached commands in a sandbox. */
|
|
521
|
+
async detachedList(name) {
|
|
522
|
+
return this.request(
|
|
523
|
+
"GET",
|
|
524
|
+
`/sandboxes/${encodeURIComponent(name)}/exec/detached`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
340
527
|
/**
|
|
341
528
|
* Create a sandbox session with automatic cleanup.
|
|
342
529
|
*
|
|
@@ -354,9 +541,75 @@ var AgentKernel = class {
|
|
|
354
541
|
await this.createSandbox(name, opts);
|
|
355
542
|
return new SandboxSession(
|
|
356
543
|
name,
|
|
357
|
-
(n, cmd) => this.execInSandbox(n, cmd),
|
|
544
|
+
(n, cmd, o) => this.execInSandbox(n, cmd, o),
|
|
358
545
|
(n) => this.removeSandbox(n),
|
|
359
|
-
(n) => this.getSandbox(n)
|
|
546
|
+
(n) => this.getSandbox(n),
|
|
547
|
+
(n, f) => this.writeFiles(n, f)
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Create a sandboxed browser session with automatic cleanup.
|
|
552
|
+
*
|
|
553
|
+
* Creates a sandbox with Chromium pre-installed via Playwright.
|
|
554
|
+
* Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```ts
|
|
558
|
+
* await using browser = await client.browser("my-browser");
|
|
559
|
+
* const page = await browser.goto("https://example.com");
|
|
560
|
+
* console.log(page.title, page.links);
|
|
561
|
+
* // sandbox auto-removed when scope exits
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
async browser(name, opts) {
|
|
565
|
+
await this.createSandbox(name, {
|
|
566
|
+
image: "python:3.12-slim",
|
|
567
|
+
memory_mb: opts?.memory_mb ?? 2048,
|
|
568
|
+
profile: "moderate"
|
|
569
|
+
});
|
|
570
|
+
await this.execInSandbox(name, BROWSER_SETUP_CMD);
|
|
571
|
+
return new BrowserSession(
|
|
572
|
+
name,
|
|
573
|
+
(n, cmd) => this.execInSandbox(n, cmd),
|
|
574
|
+
(n) => this.removeSandbox(n)
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
// -- TTL & Snapshot methods --
|
|
578
|
+
/** Extend a sandbox's TTL. Returns the new expiry time. */
|
|
579
|
+
async extendTtl(name, opts) {
|
|
580
|
+
return this.request(
|
|
581
|
+
"POST",
|
|
582
|
+
`/sandboxes/${encodeURIComponent(name)}/extend`,
|
|
583
|
+
{ by: opts.by }
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
/** List all snapshots. */
|
|
587
|
+
async listSnapshots() {
|
|
588
|
+
return this.request("GET", "/snapshots");
|
|
589
|
+
}
|
|
590
|
+
/** Take a snapshot of a sandbox. */
|
|
591
|
+
async takeSnapshot(opts) {
|
|
592
|
+
return this.request("POST", "/snapshots", opts);
|
|
593
|
+
}
|
|
594
|
+
/** Get info about a snapshot. */
|
|
595
|
+
async getSnapshot(name) {
|
|
596
|
+
return this.request(
|
|
597
|
+
"GET",
|
|
598
|
+
`/snapshots/${encodeURIComponent(name)}`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
/** Delete a snapshot. */
|
|
602
|
+
async deleteSnapshot(name) {
|
|
603
|
+
await this.request(
|
|
604
|
+
"DELETE",
|
|
605
|
+
`/snapshots/${encodeURIComponent(name)}`
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
/** Restore a sandbox from a snapshot. */
|
|
609
|
+
async restoreSnapshot(name) {
|
|
610
|
+
return this.request(
|
|
611
|
+
"POST",
|
|
612
|
+
`/snapshots/${encodeURIComponent(name)}/restore`
|
|
360
613
|
);
|
|
361
614
|
}
|
|
362
615
|
// -- Internal helpers --
|
|
@@ -410,6 +663,8 @@ var AgentKernel = class {
|
|
|
410
663
|
AgentKernel,
|
|
411
664
|
AgentKernelError,
|
|
412
665
|
AuthError,
|
|
666
|
+
BROWSER_SETUP_CMD,
|
|
667
|
+
BrowserSession,
|
|
413
668
|
NetworkError,
|
|
414
669
|
NotFoundError,
|
|
415
670
|
SandboxSession,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/sandbox.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["export { AgentKernel } from \"./client.js\";\nexport { SandboxSession } from \"./sandbox.js\";\nexport {\n AgentKernelError,\n AuthError,\n NotFoundError,\n ValidationError,\n ServerError,\n NetworkError,\n StreamError,\n} from \"./errors.js\";\nexport type {\n AgentKernelOptions,\n RunOptions,\n CreateSandboxOptions,\n RunOutput,\n SandboxInfo,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\n ApiResponse,\n} from \"./types.js\";\n","import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","import type { RunOutput, SandboxInfo } from \"./types.js\";\n\ntype ExecFn = (name: string, command: string[]) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[]): Promise<RunOutput> {\n return this._execInSandbox(this.name, command);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n ApiResponse,\n BatchCommand,\n BatchRunResponse,\n CreateSandboxOptions,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\n StreamEvent,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.4.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(name: string, command: string[]): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n { command },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/browser.ts","../src/sandbox.ts","../src/sse.ts","../src/client.ts"],"sourcesContent":["export { AgentKernel } from \"./client.js\";\nexport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nexport { SandboxSession } from \"./sandbox.js\";\nexport {\n AgentKernelError,\n AuthError,\n NotFoundError,\n ValidationError,\n ServerError,\n NetworkError,\n StreamError,\n} from \"./errors.js\";\nexport type {\n AgentKernelOptions,\n BatchFileWriteResponse,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n DetachedStatus,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n PageLink,\n PageResult,\n RunOptions,\n RunOutput,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n StreamEventType,\n SecurityProfile,\n SandboxStatus,\n TakeSnapshotOptions,\n ApiResponse,\n} from \"./types.js\";\n","import type { AgentKernelOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"http://localhost:18888\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/** Resolve configuration from constructor args, env vars, and defaults. */\nexport function resolveConfig(opts?: AgentKernelOptions) {\n const baseUrl =\n opts?.baseUrl ??\n process.env.AGENTKERNEL_BASE_URL ??\n DEFAULT_BASE_URL;\n\n const apiKey =\n opts?.apiKey ??\n process.env.AGENTKERNEL_API_KEY ??\n undefined;\n\n const timeout = opts?.timeout ?? DEFAULT_TIMEOUT;\n\n return {\n baseUrl: baseUrl.replace(/\\/+$/, \"\"),\n apiKey,\n timeout,\n };\n}\n","/** Base error for all agentkernel SDK errors. */\nexport class AgentKernelError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentKernelError\";\n }\n}\n\n/** 401 Unauthorized. */\nexport class AuthError extends AgentKernelError {\n readonly status = 401;\n constructor(message = \"Unauthorized\") {\n super(message);\n this.name = \"AuthError\";\n }\n}\n\n/** 404 Not Found. */\nexport class NotFoundError extends AgentKernelError {\n readonly status = 404;\n constructor(message = \"Not found\") {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\n/** 400 Bad Request. */\nexport class ValidationError extends AgentKernelError {\n readonly status = 400;\n constructor(message = \"Bad request\") {\n super(message);\n this.name = \"ValidationError\";\n }\n}\n\n/** 500 Internal Server Error. */\nexport class ServerError extends AgentKernelError {\n readonly status = 500;\n constructor(message = \"Internal server error\") {\n super(message);\n this.name = \"ServerError\";\n }\n}\n\n/** Network / connection error. */\nexport class NetworkError extends AgentKernelError {\n constructor(message = \"Network error\") {\n super(message);\n this.name = \"NetworkError\";\n }\n}\n\n/** SSE streaming error. */\nexport class StreamError extends AgentKernelError {\n constructor(message = \"Stream error\") {\n super(message);\n this.name = \"StreamError\";\n }\n}\n\n/** Map an HTTP status code + body to the appropriate error. */\nexport function errorFromStatus(status: number, body: string): AgentKernelError {\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.error ?? body;\n } catch {\n message = body;\n }\n\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n return new AuthError(message);\n case 404:\n return new NotFoundError(message);\n default:\n return new ServerError(message);\n }\n}\n","/**\n * Browser session for orchestrating headless browsers in sandboxes.\n *\n * Each method generates a self-contained Python/Playwright script,\n * runs it inside the sandbox, and parses the JSON result.\n */\n\nimport type { PageResult, RunOutput } from \"./types.js\";\n\ntype RunInSandboxFn = (\n name: string,\n command: string[],\n) => Promise<RunOutput>;\ntype RemoveSandboxFn = (name: string) => Promise<void>;\n\nconst GOTO_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n title = await page.title()\n url_final = page.url\n text = await page.evaluate(\"() => document.body.innerText.slice(0, 8000)\")\n links = await page.evaluate('''() =>\n Array.from(document.querySelectorAll('a[href]'))\n .slice(0, 50)\n .map(a => ({text: a.textContent.trim(), href: a.href}))\n .filter(l => l.href.startsWith(\"http\"))\n ''')\n print(json.dumps({\"title\": title, \"url\": url_final, \"text\": text, \"links\": links}))\n await b.close()\nasyncio.run(main())\n`;\n\nconst SCREENSHOT_SCRIPT = `\nimport asyncio, base64, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n data = await page.screenshot()\n print(base64.b64encode(data).decode())\n await b.close()\nasyncio.run(main())\n`;\n\nconst EVALUATE_SCRIPT = `\nimport asyncio, json, sys\nfrom playwright.async_api import async_playwright\nasync def main():\n url = sys.argv[1]\n expr = sys.argv[2]\n async with async_playwright() as p:\n b = await p.chromium.launch()\n page = await b.new_page()\n await page.goto(url, timeout=30000)\n result = await page.evaluate(expr)\n print(json.dumps(result))\n await b.close()\nasyncio.run(main())\n`;\n\n/** Command to install Playwright + Chromium inside the sandbox. */\nexport const BROWSER_SETUP_CMD = [\n \"sh\",\n \"-c\",\n \"pip install -q playwright && playwright install --with-deps chromium\",\n];\n\n/**\n * A sandboxed headless browser controlled from outside.\n *\n * The browser (Chromium via Playwright) runs inside an agentkernel sandbox.\n * You call high-level methods; the SDK generates and runs scripts internally.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * ```\n */\nexport class BrowserSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private _lastUrl: string | null = null;\n private readonly _run: RunInSandboxFn;\n private readonly _remove: RemoveSandboxFn;\n\n /** @internal */\n constructor(name: string, runFn: RunInSandboxFn, removeFn: RemoveSandboxFn) {\n this.name = name;\n this._run = runFn;\n this._remove = removeFn;\n }\n\n /** Navigate to a URL and return page data (title, text, links). */\n async goto(url: string): Promise<PageResult> {\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n GOTO_SCRIPT,\n url,\n ]);\n this._lastUrl = url;\n return JSON.parse(result.output) as PageResult;\n }\n\n /** Take a PNG screenshot. Returns a base64-encoded string. */\n async screenshot(url?: string): Promise<string> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n SCREENSHOT_SCRIPT,\n target,\n ]);\n return result.output.trim();\n }\n\n /** Run a JavaScript expression on a page and return the result. */\n async evaluate(expression: string, url?: string): Promise<unknown> {\n const target = url ?? this._lastUrl;\n if (!target) {\n throw new Error(\"No URL specified and no previous goto() call\");\n }\n const result = await this._run(this.name, [\n \"python3\",\n \"-c\",\n EVALUATE_SCRIPT,\n target,\n expression,\n ]);\n return JSON.parse(result.output);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._remove(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import type {\n BatchFileWriteResponse,\n ExecOptions,\n RunOutput,\n SandboxInfo,\n} from \"./types.js\";\n\ntype ExecFn = (\n name: string,\n command: string[],\n opts?: ExecOptions,\n) => Promise<RunOutput>;\ntype RemoveFn = (name: string) => Promise<void>;\ntype GetFn = (name: string) => Promise<SandboxInfo>;\ntype WriteFilesFn = (\n name: string,\n files: Record<string, string>,\n) => Promise<BatchFileWriteResponse>;\n\n/**\n * A sandbox session that auto-removes the sandbox on dispose.\n *\n * Supports both explicit cleanup via remove() and automatic cleanup via\n * Symbol.asyncDispose (TS 5.2+ `await using`).\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\");\n * await sb.exec([\"echo\", \"hello\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\nexport class SandboxSession implements AsyncDisposable {\n readonly name: string;\n private _removed = false;\n private readonly _execInSandbox: ExecFn;\n private readonly _removeSandbox: RemoveFn;\n private readonly _getSandbox: GetFn;\n private readonly _writeFiles: WriteFilesFn;\n\n /** @internal */\n constructor(\n name: string,\n execInSandbox: ExecFn,\n removeSandbox: RemoveFn,\n getSandbox: GetFn,\n writeFiles: WriteFilesFn,\n ) {\n this.name = name;\n this._execInSandbox = execInSandbox;\n this._removeSandbox = removeSandbox;\n this._getSandbox = getSandbox;\n this._writeFiles = writeFiles;\n }\n\n /** Run a command in this sandbox. */\n async run(command: string[], opts?: ExecOptions): Promise<RunOutput> {\n return this._execInSandbox(this.name, command, opts);\n }\n\n /** Get sandbox info. */\n async info(): Promise<SandboxInfo> {\n return this._getSandbox(this.name);\n }\n\n /** Write multiple files in one request. */\n async writeFiles(\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this._writeFiles(this.name, files);\n }\n\n /** Remove the sandbox. Idempotent. */\n async remove(): Promise<void> {\n if (this._removed) return;\n this._removed = true;\n await this._removeSandbox(this.name);\n }\n\n /** Auto-cleanup for `await using`. */\n async [Symbol.asyncDispose](): Promise<void> {\n await this.remove();\n }\n}\n","import { createParser, type EventSourceMessage } from \"eventsource-parser\";\nimport type { StreamEvent, StreamEventType } from \"./types.js\";\n\nconst KNOWN_EVENTS = new Set<string>([\"started\", \"progress\", \"output\", \"done\", \"error\"]);\n\n/** Shared mutable state between the pump and the generator. */\ninterface PumpState {\n events: StreamEvent[];\n resolve: (() => void) | null;\n done: boolean;\n}\n\nfunction pushEvent(state: PumpState, event: StreamEvent): void {\n state.events.push(event);\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n}\n\n/**\n * Parse an SSE response body into an async generator of StreamEvents.\n *\n * Consumes a ReadableStream<Uint8Array> from fetch() and yields typed events\n * until the stream closes or a \"done\"/\"error\" event is received.\n */\nexport async function* parseSSE(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamEvent> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n const state: PumpState = { events: [], resolve: null, done: false };\n\n const parser = createParser({\n onEvent(event: EventSourceMessage) {\n const type = event.event ?? \"message\";\n if (!KNOWN_EVENTS.has(type)) return;\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(event.data);\n } catch {\n data = { raw: event.data };\n }\n\n pushEvent(state, { type: type as StreamEventType, data });\n },\n });\n\n // Read the stream in the background\n const pump = (async () => {\n try {\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n parser.feed(decoder.decode(result.value, { stream: true }));\n }\n } catch (err) {\n pushEvent(state, {\n type: \"error\",\n data: { message: err instanceof Error ? err.message : String(err) },\n });\n } finally {\n state.done = true;\n if (state.resolve) {\n const cb = state.resolve;\n state.resolve = null;\n cb();\n }\n }\n })();\n\n try {\n for (;;) {\n // Yield all buffered events\n while (state.events.length > 0) {\n const event = state.events.shift()!;\n yield event;\n if (event.type === \"done\" || event.type === \"error\") return;\n }\n\n // If the stream is done and no more events, exit\n if (state.done) return;\n\n // Wait for the next event\n await new Promise<void>((r) => {\n state.resolve = r;\n });\n }\n } finally {\n reader.cancel().catch(() => {});\n await pump.catch(() => {});\n }\n}\n","import { resolveConfig } from \"./config.js\";\nimport {\n AgentKernelError,\n NetworkError,\n errorFromStatus,\n} from \"./errors.js\";\nimport { BrowserSession, BROWSER_SETUP_CMD } from \"./browser.js\";\nimport { SandboxSession } from \"./sandbox.js\";\nimport { parseSSE } from \"./sse.js\";\nimport type {\n AgentKernelOptions,\n ApiResponse,\n BatchCommand,\n BatchFileWriteResponse,\n BatchRunResponse,\n CreateSandboxOptions,\n DetachedCommand,\n DetachedLogsResponse,\n ExecOptions,\n ExtendTtlOptions,\n ExtendTtlResponse,\n FileReadResponse,\n FileWriteOptions,\n RunOptions,\n RunOutput,\n SandboxInfo,\n SnapshotMeta,\n StreamEvent,\n TakeSnapshotOptions,\n} from \"./types.js\";\n\nconst SDK_VERSION = \"0.3.0\";\n\n/**\n * Client for the agentkernel HTTP API.\n *\n * @example\n * ```ts\n * const client = new AgentKernel();\n * const result = await client.run([\"echo\", \"hello\"]);\n * console.log(result.output); // \"hello\\n\"\n * ```\n */\nexport class AgentKernel {\n private readonly baseUrl: string;\n private readonly apiKey: string | undefined;\n private readonly timeout: number;\n\n constructor(opts?: AgentKernelOptions) {\n const config = resolveConfig(opts);\n this.baseUrl = config.baseUrl;\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n // -- Core API methods --\n\n /** Health check. Returns \"ok\" if the server is running. */\n async health(): Promise<string> {\n const res = await this.request<string>(\"GET\", \"/health\");\n return res;\n }\n\n /** Run a command in a temporary sandbox. */\n async run(command: string[], opts?: RunOptions): Promise<RunOutput> {\n return this.request<RunOutput>(\"POST\", \"/run\", {\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n }\n\n /**\n * Run a command with SSE streaming output.\n *\n * @example\n * ```ts\n * for await (const event of client.runStream([\"python3\", \"script.py\"])) {\n * if (event.type === \"output\") process.stdout.write(String(event.data.data));\n * }\n * ```\n */\n async *runStream(\n command: string[],\n opts?: RunOptions,\n ): AsyncGenerator<StreamEvent> {\n const body = JSON.stringify({\n command,\n image: opts?.image,\n profile: opts?.profile,\n fast: opts?.fast ?? true,\n });\n\n const response = await this.fetch(\"/run/stream\", {\n method: \"POST\",\n headers: this.headers(\"application/json\"),\n body,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw errorFromStatus(response.status, text);\n }\n\n if (!response.body) {\n throw new AgentKernelError(\"No response body for SSE stream\");\n }\n\n yield* parseSSE(response.body);\n }\n\n /** List all sandboxes. */\n async listSandboxes(): Promise<SandboxInfo[]> {\n return this.request<SandboxInfo[]>(\"GET\", \"/sandboxes\");\n }\n\n /** Create a new sandbox. */\n async createSandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"POST\", \"/sandboxes\", {\n name,\n image: opts?.image,\n vcpus: opts?.vcpus,\n memory_mb: opts?.memory_mb,\n profile: opts?.profile,\n source_url: opts?.source_url,\n source_ref: opts?.source_ref,\n volumes: opts?.volumes,\n });\n }\n\n /** Get info about a sandbox. */\n async getSandbox(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\"GET\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Remove a sandbox. */\n async removeSandbox(name: string): Promise<void> {\n await this.request<string>(\"DELETE\", `/sandboxes/${encodeURIComponent(name)}`);\n }\n\n /** Run a command in an existing sandbox. */\n async execInSandbox(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<RunOutput> {\n return this.request<RunOutput>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Read a file from a sandbox. */\n async readFile(name: string, path: string): Promise<FileReadResponse> {\n return this.request<FileReadResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Write a file to a sandbox. */\n async writeFile(\n name: string,\n path: string,\n content: string,\n opts?: FileWriteOptions,\n ): Promise<string> {\n return this.request<string>(\n \"PUT\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n { content, encoding: opts?.encoding ?? \"utf8\" },\n );\n }\n\n /** Delete a file from a sandbox. */\n async deleteFile(name: string, path: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/files/${path}`,\n );\n }\n\n /** Get audit log entries for a sandbox. */\n async getSandboxLogs(name: string): Promise<Record<string, unknown>[]> {\n return this.request<Record<string, unknown>[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/logs`,\n );\n }\n\n /** Write multiple files to a sandbox in one request. */\n async writeFiles(\n name: string,\n files: Record<string, string>,\n ): Promise<BatchFileWriteResponse> {\n return this.request<BatchFileWriteResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/files`,\n { files },\n );\n }\n\n /** Run multiple commands in parallel. */\n async batchRun(commands: BatchCommand[]): Promise<BatchRunResponse> {\n return this.request<BatchRunResponse>(\"POST\", \"/batch/run\", { commands });\n }\n\n /** Start a detached (background) command in a sandbox. */\n async execDetached(\n name: string,\n command: string[],\n opts?: ExecOptions,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detach`,\n {\n command,\n env: opts?.env,\n workdir: opts?.workdir,\n sudo: opts?.sudo,\n },\n );\n }\n\n /** Get the status of a detached command. */\n async detachedStatus(\n name: string,\n cmdId: string,\n ): Promise<DetachedCommand> {\n return this.request<DetachedCommand>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** Get logs from a detached command. */\n async detachedLogs(\n name: string,\n cmdId: string,\n stream?: \"stdout\" | \"stderr\",\n ): Promise<DetachedLogsResponse> {\n const query = stream === \"stderr\" ? \"?stream=stderr\" : \"\";\n return this.request<DetachedLogsResponse>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}/logs${query}`,\n );\n }\n\n /** Kill a detached command. */\n async detachedKill(name: string, cmdId: string): Promise<string> {\n return this.request<string>(\n \"DELETE\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached/${encodeURIComponent(cmdId)}`,\n );\n }\n\n /** List detached commands in a sandbox. */\n async detachedList(name: string): Promise<DetachedCommand[]> {\n return this.request<DetachedCommand[]>(\n \"GET\",\n `/sandboxes/${encodeURIComponent(name)}/exec/detached`,\n );\n }\n\n /**\n * Create a sandbox session with automatic cleanup.\n *\n * The returned SandboxSession implements AsyncDisposable,\n * so it works with `await using` (TS 5.2+):\n *\n * @example\n * ```ts\n * await using sb = await client.sandbox(\"test\", { image: \"python:3.12-alpine\" });\n * await sb.run([\"pip\", \"install\", \"numpy\"]);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async sandbox(\n name: string,\n opts?: CreateSandboxOptions,\n ): Promise<SandboxSession> {\n await this.createSandbox(name, opts);\n return new SandboxSession(\n name,\n (n, cmd, o) => this.execInSandbox(n, cmd, o),\n (n) => this.removeSandbox(n),\n (n) => this.getSandbox(n),\n (n, f) => this.writeFiles(n, f),\n );\n }\n\n /**\n * Create a sandboxed browser session with automatic cleanup.\n *\n * Creates a sandbox with Chromium pre-installed via Playwright.\n * Use `goto()`, `screenshot()`, and `evaluate()` to interact with web pages.\n *\n * @example\n * ```ts\n * await using browser = await client.browser(\"my-browser\");\n * const page = await browser.goto(\"https://example.com\");\n * console.log(page.title, page.links);\n * // sandbox auto-removed when scope exits\n * ```\n */\n async browser(\n name: string,\n opts?: { memory_mb?: number },\n ): Promise<BrowserSession> {\n await this.createSandbox(name, {\n image: \"python:3.12-slim\",\n memory_mb: opts?.memory_mb ?? 2048,\n profile: \"moderate\",\n });\n await this.execInSandbox(name, BROWSER_SETUP_CMD);\n return new BrowserSession(\n name,\n (n, cmd) => this.execInSandbox(n, cmd),\n (n) => this.removeSandbox(n),\n );\n }\n\n // -- TTL & Snapshot methods --\n\n /** Extend a sandbox's TTL. Returns the new expiry time. */\n async extendTtl(name: string, opts: ExtendTtlOptions): Promise<ExtendTtlResponse> {\n return this.request<ExtendTtlResponse>(\n \"POST\",\n `/sandboxes/${encodeURIComponent(name)}/extend`,\n { by: opts.by },\n );\n }\n\n /** List all snapshots. */\n async listSnapshots(): Promise<SnapshotMeta[]> {\n return this.request<SnapshotMeta[]>(\"GET\", \"/snapshots\");\n }\n\n /** Take a snapshot of a sandbox. */\n async takeSnapshot(opts: TakeSnapshotOptions): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\"POST\", \"/snapshots\", opts);\n }\n\n /** Get info about a snapshot. */\n async getSnapshot(name: string): Promise<SnapshotMeta> {\n return this.request<SnapshotMeta>(\n \"GET\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Delete a snapshot. */\n async deleteSnapshot(name: string): Promise<void> {\n await this.request<string>(\n \"DELETE\",\n `/snapshots/${encodeURIComponent(name)}`,\n );\n }\n\n /** Restore a sandbox from a snapshot. */\n async restoreSnapshot(name: string): Promise<SandboxInfo> {\n return this.request<SandboxInfo>(\n \"POST\",\n `/snapshots/${encodeURIComponent(name)}/restore`,\n );\n }\n\n // -- Internal helpers --\n\n private headers(contentType?: string): Record<string, string> {\n const h: Record<string, string> = {\n \"User-Agent\": `agentkernel-nodejs-sdk/${SDK_VERSION}`,\n };\n if (contentType) h[\"Content-Type\"] = contentType;\n if (this.apiKey) h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n return h;\n }\n\n private async fetch(path: string, init: RequestInit): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n try {\n return await fetch(url, {\n ...init,\n signal: AbortSignal.timeout(this.timeout),\n });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"TimeoutError\") {\n throw new NetworkError(`Request timed out after ${this.timeout}ms`);\n }\n if (err instanceof TypeError) {\n throw new NetworkError(`Failed to connect to ${this.baseUrl}: ${err.message}`);\n }\n throw new NetworkError(\n err instanceof Error ? err.message : String(err),\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<T> {\n const init: RequestInit = {\n method,\n headers: this.headers(body ? \"application/json\" : undefined),\n };\n if (body) init.body = JSON.stringify(body);\n\n const response = await this.fetch(path, init);\n\n const text = await response.text();\n if (!response.ok) {\n throw errorFromStatus(response.status, text);\n }\n\n const parsed: ApiResponse<T> = JSON.parse(text);\n if (!parsed.success) {\n throw new AgentKernelError(parsed.error ?? \"Unknown error\");\n }\n return parsed.data as T;\n }\n}\n"],"mappings":"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","names":[]}
|