withruntime 0.5.1 → 0.6.1
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/LICENSE +55 -0
- package/README.md +8 -4
- package/dist/ai-harness/index.d.ts +194 -0
- package/dist/ai-harness/index.js +504 -0
- package/dist/cli-extras.d.ts +24 -0
- package/dist/cli-extras.js +205 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.js +403 -28
- package/dist/e2b/filesystem.d.ts +26 -1
- package/dist/e2b/filesystem.js +30 -2
- package/dist/e2b/index.d.ts +1 -1
- package/dist/e2b/index.js +1 -1
- package/dist/errors.js +2 -0
- package/dist/identity.d.ts +27 -0
- package/dist/identity.js +56 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +7 -0
- package/dist/mcp.js +16 -3
- package/dist/network-cli.d.ts +15 -0
- package/dist/network-cli.js +323 -0
- package/dist/products/desktop.d.ts +41 -4
- package/dist/products/desktop.js +73 -3
- package/dist/products/index.d.ts +12 -0
- package/dist/products/index.js +12 -0
- package/dist/products/interpreter.d.ts +5 -3
- package/dist/products/interpreter.js +2 -1
- package/dist/products/mcp.d.ts +79 -0
- package/dist/products/mcp.js +37 -0
- package/dist/products/mounts.d.ts +49 -0
- package/dist/products/mounts.js +21 -0
- package/dist/products/network-products.d.ts +167 -0
- package/dist/products/network-products.js +82 -0
- package/dist/products/network.d.ts +1 -1
- package/dist/products/sso.d.ts +44 -0
- package/dist/products/sso.js +8 -0
- package/dist/products/volumes.d.ts +68 -5
- package/dist/products/volumes.js +52 -4
- package/dist/products/watch.d.ts +91 -0
- package/dist/products/watch.js +135 -0
- package/dist/sandbox.d.ts +32 -2
- package/dist/sandbox.js +93 -16
- package/dist/snapshots.d.ts +11 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.js +4 -1
- package/dist/wireguard.d.ts +7 -0
- package/dist/wireguard.js +13 -0
- package/package.json +49 -18
package/dist/sandbox.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommandError, RuntimeError } from "./errors.js";
|
|
2
2
|
import { Page } from "./page.js";
|
|
3
|
+
import { sandboxWatches, watchDirectory, } from "./products/watch.js";
|
|
3
4
|
import { sandboxFactories } from "./products/index.js";
|
|
4
5
|
import { Tunnel } from "./tunnel.js";
|
|
5
6
|
const CHUNK = 1_048_576;
|
|
@@ -274,6 +275,13 @@ export class Sandbox {
|
|
|
274
275
|
async snapshot(options = {}) {
|
|
275
276
|
const { idempotencyKey, signal, timeoutMs, ...body } = options;
|
|
276
277
|
await this.refresh();
|
|
278
|
+
// Straight after a fork or a wake the sandbox is still `resuming`, and
|
|
279
|
+
// after a pause still `pausing`: wait for where it is going, or a
|
|
280
|
+
// snapshot of it is refused as not paused (user lane, 23 September 2026).
|
|
281
|
+
if (this.state === "resuming" || this.state === "starting")
|
|
282
|
+
await this.waitFor("running");
|
|
283
|
+
else if (this.state === "pausing")
|
|
284
|
+
await this.waitFor("paused");
|
|
277
285
|
const running = this.state === "running";
|
|
278
286
|
if (running)
|
|
279
287
|
await this.pause();
|
|
@@ -552,6 +560,22 @@ export class Files {
|
|
|
552
560
|
this.sandboxId = sandboxId;
|
|
553
561
|
}
|
|
554
562
|
#path = (suffix) => `/v1/sandboxes/${enc(this.sandboxId)}${suffix}`;
|
|
563
|
+
/** Watch a directory: `onEvent` gets create, write, remove, rename and
|
|
564
|
+
* chmod events until `handle.stop()`. E2B's `watchDir`, plus filters,
|
|
565
|
+
* batches, and a watch that loses nothing across a pause:
|
|
566
|
+
*
|
|
567
|
+
* const watch = await sbx.files.watch("/workspace", (e) => console.log(e.type, e.path),
|
|
568
|
+
* { recursive: true, exclude: ["node_modules"] });
|
|
569
|
+
* ...
|
|
570
|
+
* await watch.stop();
|
|
571
|
+
*/
|
|
572
|
+
watch(path, onEvent, options) {
|
|
573
|
+
return watchDirectory(this.t, this.sandboxId, path, onEvent, options);
|
|
574
|
+
}
|
|
575
|
+
/** The watches running in the sandbox, and polling reads by cursor. */
|
|
576
|
+
get watches() {
|
|
577
|
+
return sandboxWatches(this.t, this.sandboxId);
|
|
578
|
+
}
|
|
555
579
|
/** A file's bytes, any size. */
|
|
556
580
|
async read(path, options = {}) {
|
|
557
581
|
return this.t.bytes({
|
|
@@ -566,8 +590,11 @@ export class Files {
|
|
|
566
590
|
return new TextDecoder().decode(await this.read(path, options));
|
|
567
591
|
}
|
|
568
592
|
/** Writes a file of any size, atomically, making parent directories. Large
|
|
569
|
-
* ones go in parallel 1 MiB chunks checked against their SHA-256.
|
|
570
|
-
|
|
593
|
+
* ones go in parallel 1 MiB chunks checked against their SHA-256. `mode`
|
|
594
|
+
* sets its permissions (0o755 for a program); 0o644 when left out. */
|
|
595
|
+
async write(path, data, writeOptions = {}) {
|
|
596
|
+
const { mode, ...options } = writeOptions;
|
|
597
|
+
const octal = mode === undefined ? undefined : (mode & 0o777).toString(8).padStart(3, "0");
|
|
571
598
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
572
599
|
if (bytes.length <= CHUNK) {
|
|
573
600
|
// bytes(), not send(): the answer is read, so its connection is free
|
|
@@ -575,7 +602,7 @@ export class Files {
|
|
|
575
602
|
await this.t.bytes({
|
|
576
603
|
method: "PUT",
|
|
577
604
|
path: this.#path("/files/content"),
|
|
578
|
-
query: { path },
|
|
605
|
+
query: { path, ...(octal ? { mode: octal } : {}) },
|
|
579
606
|
bytes,
|
|
580
607
|
...options,
|
|
581
608
|
});
|
|
@@ -583,12 +610,55 @@ export class Files {
|
|
|
583
610
|
}
|
|
584
611
|
const { createHash } = await import("node:crypto");
|
|
585
612
|
const sha256 = createHash("sha256").update(bytes).digest("hex");
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
613
|
+
// A guest journals mutations across operations, not per URL. One logical
|
|
614
|
+
// write therefore owns separate stable keys for each mutation phase.
|
|
615
|
+
const uploadKey = options.idempotencyKey ?? crypto.randomUUID();
|
|
616
|
+
const phaseOptions = (phase) => ({
|
|
590
617
|
...options,
|
|
618
|
+
idempotencyKey: createHash("sha256")
|
|
619
|
+
.update(JSON.stringify(["files.write", uploadKey, phase]))
|
|
620
|
+
.digest("hex"),
|
|
621
|
+
});
|
|
622
|
+
let begin;
|
|
623
|
+
try {
|
|
624
|
+
begin = await this.t.json({
|
|
625
|
+
method: "POST",
|
|
626
|
+
path: this.#path("/uploads"),
|
|
627
|
+
body: { path, size: bytes.length, sha256, ...(octal ? { mode: octal } : {}) },
|
|
628
|
+
...phaseOptions("begin"),
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
catch (error) {
|
|
632
|
+
if (!octal || !(error instanceof RuntimeError) || error.code !== "guest_upgrade_required")
|
|
633
|
+
throw error;
|
|
634
|
+
// The API aborted the unsupported transfer before accepting chunks.
|
|
635
|
+
// A different body needs a different key; retain deterministic retries.
|
|
636
|
+
begin = await this.t.json({
|
|
637
|
+
method: "POST",
|
|
638
|
+
path: this.#path("/uploads"),
|
|
639
|
+
body: { path, size: bytes.length, sha256 },
|
|
640
|
+
...phaseOptions("legacy-begin"),
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
const commit = () => this.t.json({
|
|
644
|
+
method: "POST",
|
|
645
|
+
path: this.#path(`/uploads/${enc(begin.uploadId)}:commit`),
|
|
646
|
+
body: {},
|
|
647
|
+
...phaseOptions("commit"),
|
|
591
648
|
});
|
|
649
|
+
let committed = false;
|
|
650
|
+
if (begin.replayed) {
|
|
651
|
+
// A completed commit removed the transfer. Ask its journal before
|
|
652
|
+
// resending chunks; an incomplete transfer alone is safe to continue.
|
|
653
|
+
try {
|
|
654
|
+
await commit();
|
|
655
|
+
committed = true;
|
|
656
|
+
}
|
|
657
|
+
catch (error) {
|
|
658
|
+
if (!(error instanceof RuntimeError) || error.code !== "upload_incomplete")
|
|
659
|
+
throw error;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
592
662
|
const offsets = [];
|
|
593
663
|
for (let offset = 0; offset < bytes.length; offset += begin.chunkBytes)
|
|
594
664
|
offsets.push(offset);
|
|
@@ -605,13 +675,18 @@ export class Files {
|
|
|
605
675
|
}
|
|
606
676
|
};
|
|
607
677
|
try {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
678
|
+
if (!committed) {
|
|
679
|
+
await Promise.all(Array.from({ length: Math.min(PARALLEL, offsets.length) }, worker));
|
|
680
|
+
await commit();
|
|
681
|
+
}
|
|
682
|
+
// An older sandbox image ignores the mode in the upload; set it after.
|
|
683
|
+
if (octal && begin.mode !== octal)
|
|
684
|
+
await this.t.json({
|
|
685
|
+
method: "POST",
|
|
686
|
+
path: this.#path("/files:chmod"),
|
|
687
|
+
body: { path, mode: octal },
|
|
688
|
+
...phaseOptions("chmod"),
|
|
689
|
+
});
|
|
615
690
|
}
|
|
616
691
|
catch (error) {
|
|
617
692
|
await this.t
|
|
@@ -619,6 +694,7 @@ export class Files {
|
|
|
619
694
|
method: "POST",
|
|
620
695
|
path: this.#path(`/uploads/${enc(begin.uploadId)}:abort`),
|
|
621
696
|
body: {},
|
|
697
|
+
...phaseOptions("abort"),
|
|
622
698
|
})
|
|
623
699
|
.catch(() => undefined);
|
|
624
700
|
throw error;
|
|
@@ -669,7 +745,8 @@ export class Files {
|
|
|
669
745
|
const { stat, readFile } = await import("node:fs/promises");
|
|
670
746
|
const info = await stat(localPath);
|
|
671
747
|
if (info.isFile()) {
|
|
672
|
-
|
|
748
|
+
// Its permissions travel with it: an uploaded script stays runnable.
|
|
749
|
+
await this.write(remotePath, await readFile(localPath), { mode: info.mode & 0o777 });
|
|
673
750
|
return;
|
|
674
751
|
}
|
|
675
752
|
const { packDirectory } = await import("./tar.js");
|
|
@@ -681,7 +758,7 @@ export class Files {
|
|
|
681
758
|
const result = await new Sandbox(this.t, { id: this.sandboxId }).exec([
|
|
682
759
|
"sh",
|
|
683
760
|
"-c",
|
|
684
|
-
'mkdir -p "$1" && tar -
|
|
761
|
+
'mkdir -p "$1" && tar -xpzf "$2" -C "$1"; code=$?; rm -f "$2"; exit $code',
|
|
685
762
|
"sh",
|
|
686
763
|
remotePath,
|
|
687
764
|
staging,
|
package/dist/snapshots.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Page } from "./page.js";
|
|
2
2
|
import type { RequestOptions, Transport } from "./transport.js";
|
|
3
3
|
/** A sandbox's whole machine (files, memory, running processes), kept on its
|
|
4
|
-
* host to start new sandboxes from
|
|
4
|
+
* host to start new sandboxes from, and copied off the host so it survives
|
|
5
|
+
* losing that host. */
|
|
5
6
|
export type Snapshot = {
|
|
6
7
|
id: string;
|
|
7
8
|
kind: "snapshot";
|
|
@@ -19,6 +20,15 @@ export type Snapshot = {
|
|
|
19
20
|
/** What it stores, and what storage is metered for: the bytes it alone holds. */
|
|
20
21
|
storedBytes: number | null;
|
|
21
22
|
meteredBytes: number | null;
|
|
23
|
+
/** Whether its copy off the host is made and checked. */
|
|
24
|
+
backedUp: boolean;
|
|
25
|
+
/** Where that copy stands. `restoring`: its host was lost and it is being
|
|
26
|
+
* restored onto another; forks answer `snapshot_restoring` until it is. */
|
|
27
|
+
durability: {
|
|
28
|
+
state: "none" | "pending" | "durable" | "failed" | "restoring";
|
|
29
|
+
durableAt: string | null;
|
|
30
|
+
storedBytes: number | null;
|
|
31
|
+
};
|
|
22
32
|
error: string | null;
|
|
23
33
|
createdAt: string;
|
|
24
34
|
readyAt: string | null;
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RuntimeError } from "./errors.js";
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.6.1";
|
|
3
3
|
export declare const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
4
4
|
export type RequestOptions = {
|
|
5
5
|
/** Sent as Idempotency-Key. Omit it: the SDK makes one per call and keeps
|
package/dist/transport.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConnectionError, errorFor, RuntimeError, WAITS_FOR_ROOM } from "./errors.js";
|
|
2
2
|
import { describeRoute, envFetch, openWebSocket } from "./proxy.js";
|
|
3
|
-
export const VERSION = "0.
|
|
3
|
+
export const VERSION = "0.6.1";
|
|
4
4
|
export const DEFAULT_BASE_URL = "https://api.withruntime.com";
|
|
5
5
|
export function apiOrigin(value) {
|
|
6
6
|
const url = new URL(value);
|
|
@@ -289,6 +289,9 @@ export class Transport {
|
|
|
289
289
|
yield JSON.parse(buffer);
|
|
290
290
|
}
|
|
291
291
|
finally {
|
|
292
|
+
// Returning early from the iterator must close the HTTP stream too.
|
|
293
|
+
// Cleanup must not replace a parse, network or callback error.
|
|
294
|
+
await reader.cancel().catch(() => undefined);
|
|
292
295
|
reader.releaseLock();
|
|
293
296
|
}
|
|
294
297
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A WireGuard key pair, as `wg genkey | wg pubkey` makes: X25519, each half
|
|
2
|
+
* 32 bytes of base64. Made on the machine that will use it, so the private
|
|
3
|
+
* key is never sent anywhere. */
|
|
4
|
+
export declare function generateWireGuardKeyPair(): {
|
|
5
|
+
privateKey: string;
|
|
6
|
+
publicKey: string;
|
|
7
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { generateKeyPairSync } from "node:crypto";
|
|
2
|
+
/** A WireGuard key pair, as `wg genkey | wg pubkey` makes: X25519, each half
|
|
3
|
+
* 32 bytes of base64. Made on the machine that will use it, so the private
|
|
4
|
+
* key is never sent anywhere. */
|
|
5
|
+
export function generateWireGuardKeyPair() {
|
|
6
|
+
const { privateKey, publicKey } = generateKeyPairSync("x25519");
|
|
7
|
+
const d = privateKey.export({ format: "jwk" }).d;
|
|
8
|
+
const x = publicKey.export({ format: "jwk" }).x;
|
|
9
|
+
return {
|
|
10
|
+
privateKey: Buffer.from(d, "base64url").toString("base64"),
|
|
11
|
+
publicKey: Buffer.from(x, "base64url").toString("base64"),
|
|
12
|
+
};
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,44 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "withruntime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
|
+
"license": "Apache-2.0",
|
|
4
5
|
"mcpName": "com.withruntime/runtime",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"exports": {
|
|
7
8
|
".": {
|
|
8
9
|
"types": "./dist/index.d.ts",
|
|
9
|
-
"import": "./dist/index.js"
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
10
12
|
},
|
|
11
13
|
"./e2b": {
|
|
12
14
|
"types": "./dist/e2b/index.d.ts",
|
|
13
|
-
"import": "./dist/e2b/index.js"
|
|
15
|
+
"import": "./dist/e2b/index.js",
|
|
16
|
+
"default": "./dist/e2b/index.js"
|
|
14
17
|
},
|
|
15
18
|
"./e2b/code-interpreter": {
|
|
16
19
|
"types": "./dist/e2b/code-interpreter.d.ts",
|
|
17
|
-
"import": "./dist/e2b/code-interpreter.js"
|
|
20
|
+
"import": "./dist/e2b/code-interpreter.js",
|
|
21
|
+
"default": "./dist/e2b/code-interpreter.js"
|
|
18
22
|
},
|
|
19
23
|
"./daytona": {
|
|
20
24
|
"types": "./dist/daytona/index.d.ts",
|
|
21
|
-
"import": "./dist/daytona/index.js"
|
|
25
|
+
"import": "./dist/daytona/index.js",
|
|
26
|
+
"default": "./dist/daytona/index.js"
|
|
22
27
|
},
|
|
23
28
|
"./vercel": {
|
|
24
29
|
"types": "./dist/vercel/index.d.ts",
|
|
25
|
-
"import": "./dist/vercel/index.js"
|
|
30
|
+
"import": "./dist/vercel/index.js",
|
|
31
|
+
"default": "./dist/vercel/index.js"
|
|
26
32
|
},
|
|
27
33
|
"./tools": {
|
|
28
34
|
"types": "./dist/tools/index.d.ts",
|
|
29
|
-
"import": "./dist/tools/index.js"
|
|
35
|
+
"import": "./dist/tools/index.js",
|
|
36
|
+
"default": "./dist/tools/index.js"
|
|
30
37
|
},
|
|
31
38
|
"./ai": {
|
|
32
39
|
"types": "./dist/ai/index.d.ts",
|
|
33
|
-
"import": "./dist/ai/index.js"
|
|
40
|
+
"import": "./dist/ai/index.js",
|
|
41
|
+
"default": "./dist/ai/index.js"
|
|
34
42
|
},
|
|
35
43
|
"./claude-agent-sdk": {
|
|
36
44
|
"types": "./dist/claude-agent-sdk/index.d.ts",
|
|
37
|
-
"import": "./dist/claude-agent-sdk/index.js"
|
|
45
|
+
"import": "./dist/claude-agent-sdk/index.js",
|
|
46
|
+
"default": "./dist/claude-agent-sdk/index.js"
|
|
38
47
|
},
|
|
39
48
|
"./openai-agents": {
|
|
40
49
|
"types": "./dist/openai-agents/index.d.ts",
|
|
41
|
-
"import": "./dist/openai-agents/index.js"
|
|
50
|
+
"import": "./dist/openai-agents/index.js",
|
|
51
|
+
"default": "./dist/openai-agents/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./ai-harness": {
|
|
54
|
+
"types": "./dist/ai-harness/index.d.ts",
|
|
55
|
+
"import": "./dist/ai-harness/index.js",
|
|
56
|
+
"default": "./dist/ai-harness/index.js"
|
|
42
57
|
}
|
|
43
58
|
},
|
|
44
59
|
"bin": {
|
|
@@ -50,7 +65,8 @@
|
|
|
50
65
|
"README.md",
|
|
51
66
|
"E2B.md",
|
|
52
67
|
"DAYTONA.md",
|
|
53
|
-
"VERCEL.md"
|
|
68
|
+
"VERCEL.md",
|
|
69
|
+
"LICENSE"
|
|
54
70
|
],
|
|
55
71
|
"engines": {
|
|
56
72
|
"node": ">=22"
|
|
@@ -60,23 +76,34 @@
|
|
|
60
76
|
"prepack": "bun run build",
|
|
61
77
|
"check-types": "tsc --noEmit",
|
|
62
78
|
"lint": "eslint",
|
|
63
|
-
"test": "bun test && bun scripts/test-python.ts && bun scripts/test-go.ts",
|
|
79
|
+
"test": "bun test && bun scripts/test-python.ts && bun scripts/test-go.ts && bun ../../sdks/java/scripts/check.ts && bun ../../sdks/ruby/scripts/check.ts",
|
|
80
|
+
"test:java": "bun ../../sdks/java/scripts/check.ts",
|
|
81
|
+
"test:ruby": "bun ../../sdks/ruby/scripts/check.ts",
|
|
64
82
|
"test:python": "bun scripts/test-python.ts",
|
|
65
83
|
"test:go": "bun scripts/test-go.ts"
|
|
66
84
|
},
|
|
67
85
|
"devDependencies": {
|
|
86
|
+
"@ai-sdk/harness": "1.0.124",
|
|
87
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.277",
|
|
88
|
+
"@anthropic-ai/sdk": "0.128.0",
|
|
89
|
+
"@google/genai": "2.24.0",
|
|
90
|
+
"@mastra/core": "1.71.0",
|
|
91
|
+
"@mistralai/mistralai": "2.7.0",
|
|
92
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
93
|
+
"@openai/agents": "0.18.0",
|
|
94
|
+
"@openai/agents-core": "0.18.0",
|
|
95
|
+
"@openrouter/sdk": "1.3.27",
|
|
68
96
|
"@runtime/eslint-config": "workspace:*",
|
|
69
97
|
"@runtime/typescript-config": "workspace:*",
|
|
70
98
|
"@types/bun": "^1.4.0",
|
|
71
99
|
"@types/node": "^20",
|
|
100
|
+
"ai": "7.0.87",
|
|
72
101
|
"eslint": "^9",
|
|
102
|
+
"groq-sdk": "1.6.0",
|
|
103
|
+
"openai": "7.23.0",
|
|
104
|
+
"together-ai": "0.55.0",
|
|
73
105
|
"typescript": "^5",
|
|
74
|
-
"
|
|
75
|
-
"@openai/agents-core": "0.18.0",
|
|
76
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.277",
|
|
77
|
-
"ai": "7.0.87",
|
|
78
|
-
"zod": "^4.1.8",
|
|
79
|
-
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
106
|
+
"zod": "^4.1.8"
|
|
80
107
|
},
|
|
81
108
|
"publishConfig": {
|
|
82
109
|
"access": "public",
|
|
@@ -96,6 +123,7 @@
|
|
|
96
123
|
"undici": "^7.29.1"
|
|
97
124
|
},
|
|
98
125
|
"peerDependencies": {
|
|
126
|
+
"@ai-sdk/harness": "^1.0.0",
|
|
99
127
|
"@anthropic-ai/claude-agent-sdk": ">=0.2.0",
|
|
100
128
|
"@openai/agents": ">=0.18.0",
|
|
101
129
|
"@openai/agents-core": ">=0.18.0",
|
|
@@ -103,6 +131,9 @@
|
|
|
103
131
|
"zod": ">=3.25.0"
|
|
104
132
|
},
|
|
105
133
|
"peerDependenciesMeta": {
|
|
134
|
+
"@ai-sdk/harness": {
|
|
135
|
+
"optional": true
|
|
136
|
+
},
|
|
106
137
|
"@anthropic-ai/claude-agent-sdk": {
|
|
107
138
|
"optional": true
|
|
108
139
|
},
|