@claxedo/sandbox-manager 0.10.1 → 0.10.3
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 +100 -30
- package/dist/checkpoint-manager.mjs +19 -0
- package/dist/contract.d.ts +40 -17
- package/dist/driver-billing.d.ts +23 -0
- package/dist/driver-catalog.mjs +57 -3
- package/dist/driver-ensure-input.d.ts +22 -0
- package/dist/drivers/agent37-client.d.ts +87 -0
- package/dist/drivers/agent37.d.ts +25 -0
- package/dist/drivers/agent37.mjs +888 -0
- package/dist/drivers/boat-client.d.ts +4 -4
- package/dist/drivers/boat-machine.d.ts +80 -0
- package/dist/drivers/boat-preparation.test-support.d.ts +2 -0
- package/dist/drivers/boat-template.mjs +196 -92
- package/dist/drivers/boat.d.ts +0 -17
- package/dist/drivers/boat.mjs +200 -108
- package/dist/drivers/cloudflare.d.ts +5 -9
- package/dist/drivers/cloudflare.mjs +71 -7
- package/dist/drivers/docker.mjs +57 -2
- package/dist/drivers/local-brokering.d.ts +12 -0
- package/dist/drivers/local-brokering.mjs +99 -24
- package/dist/drivers/modal.mjs +57 -2
- package/dist/drivers/transient-error.d.ts +0 -1
- package/dist/drivers/vercel.mjs +61 -3
- package/dist/egress-policy.d.ts +33 -32
- package/dist/egress-warnings.d.ts +4 -6
- package/dist/hosted-network-policy.d.ts +10 -64
- package/dist/hosted-network-policy.mjs +1 -1
- package/dist/image-name.d.ts +0 -1
- package/dist/image-name.mjs +5 -0
- package/dist/image.d.ts +1 -0
- package/dist/image.mjs +6 -0
- package/dist/index.mjs +180 -112
- package/dist/json.d.ts +1 -10
- package/dist/lease-failure.d.ts +20 -1
- package/dist/lease-types.d.ts +1 -10
- package/dist/runtime-env.d.ts +6 -0
- package/dist/runtime-env.mjs +5 -0
- package/dist/runtime-version.d.ts +25 -7
- package/dist/runtime-version.mjs +13 -2
- package/dist/start-admission.d.ts +32 -0
- package/dist/start-telemetry.d.ts +5 -3
- package/package.json +12 -4
|
@@ -12,6 +12,27 @@ var boatBilling = {
|
|
|
12
12
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
+
var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
|
|
16
|
+
var AGENT37_MONTH_HOURS = 730;
|
|
17
|
+
var agent37MachineShapes = {
|
|
18
|
+
small: { cpu: 2, memory: 4, disk: 10 },
|
|
19
|
+
default: { cpu: 4, memory: 8, disk: 20 },
|
|
20
|
+
large: { cpu: 4, memory: 16, disk: 40 }
|
|
21
|
+
};
|
|
22
|
+
function agent37Rate(shape) {
|
|
23
|
+
const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
|
|
24
|
+
return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
|
|
25
|
+
}
|
|
26
|
+
var agent37Billing = {
|
|
27
|
+
source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
|
|
28
|
+
meter: "Agent37 meters an instance per minute at a monthly rate over 730 hours: $0.80 per vCPU, $0.70 per GB of memory and $0.09 per GB of disk while it runs, and the disk alone while it is stopped.",
|
|
29
|
+
rates: {
|
|
30
|
+
small: agent37Rate(agent37MachineShapes.small),
|
|
31
|
+
default: agent37Rate(agent37MachineShapes.default),
|
|
32
|
+
large: agent37Rate(agent37MachineShapes.large)
|
|
33
|
+
},
|
|
34
|
+
excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
|
|
35
|
+
};
|
|
15
36
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
16
37
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
17
38
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -31,7 +52,7 @@ var cloudflareBilling = {
|
|
|
31
52
|
};
|
|
32
53
|
|
|
33
54
|
// ../sandbox-contract/dist/index.mjs
|
|
34
|
-
var sandboxCheckpointUnusableCauses = ["expired", "
|
|
55
|
+
var sandboxCheckpointUnusableCauses = ["expired", "runtime_modified", "not_restorable"];
|
|
35
56
|
function isSandboxCheckpointUnusableCause(value) {
|
|
36
57
|
return sandboxCheckpointUnusableCauses.some((cause) => cause === value);
|
|
37
58
|
}
|
|
@@ -50,6 +71,7 @@ var sandboxDriverCredentialFields = {
|
|
|
50
71
|
{ key: "worker_url", label: "Worker URL" }
|
|
51
72
|
],
|
|
52
73
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
74
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
53
75
|
docker: [{ key: "image", label: "Image" }]
|
|
54
76
|
};
|
|
55
77
|
var sandboxDriverLabels = {
|
|
@@ -57,6 +79,7 @@ var sandboxDriverLabels = {
|
|
|
57
79
|
vercel: "Vercel",
|
|
58
80
|
cloudflare: "Cloudflare",
|
|
59
81
|
boat: "Boat",
|
|
82
|
+
agent37: "Agent37",
|
|
60
83
|
docker: "Docker"
|
|
61
84
|
};
|
|
62
85
|
function cloudflareWorkerBaseUrl(input) {
|
|
@@ -139,8 +162,8 @@ var sandboxDriverCatalog = {
|
|
|
139
162
|
hostWatchesIdle: true,
|
|
140
163
|
targetAccess: "relay",
|
|
141
164
|
secretBrokering: "native",
|
|
142
|
-
//
|
|
143
|
-
egressControl: "
|
|
165
|
+
// The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
|
|
166
|
+
egressControl: "hosts",
|
|
144
167
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
145
168
|
persistence: {
|
|
146
169
|
resume: "replacement-restore",
|
|
@@ -178,6 +201,33 @@ var sandboxDriverCatalog = {
|
|
|
178
201
|
machineClasses: ["small", "default", "large"]
|
|
179
202
|
}
|
|
180
203
|
},
|
|
204
|
+
agent37: {
|
|
205
|
+
id: "agent37",
|
|
206
|
+
label: sandboxDriverLabels.agent37,
|
|
207
|
+
credentialFields: sandboxDriverCredentialFields.agent37,
|
|
208
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
209
|
+
runtimeEnv: "callback",
|
|
210
|
+
preparedImage: true,
|
|
211
|
+
billing: agent37Billing,
|
|
212
|
+
metadata: {
|
|
213
|
+
driverRunsIn: ["worker", "node"],
|
|
214
|
+
hostStopBehavior: "suspends-host",
|
|
215
|
+
hostResumeBehavior: "same-host",
|
|
216
|
+
targetAccess: "relay",
|
|
217
|
+
secretBrokering: "none",
|
|
218
|
+
// An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
|
|
219
|
+
egressControl: "hosts-and-cidrs",
|
|
220
|
+
persistence: {
|
|
221
|
+
resume: "same-sandbox",
|
|
222
|
+
capture: "none",
|
|
223
|
+
clone: false,
|
|
224
|
+
captureSource: "not-applicable",
|
|
225
|
+
retention: "provider-managed",
|
|
226
|
+
restoreMount: "same-resource"
|
|
227
|
+
},
|
|
228
|
+
machineClasses: ["small", "default", "large"]
|
|
229
|
+
}
|
|
230
|
+
},
|
|
181
231
|
docker: {
|
|
182
232
|
id: "docker",
|
|
183
233
|
label: sandboxDriverLabels.docker,
|
|
@@ -311,7 +361,11 @@ function workspaceRuntimeSourceEnv(input) {
|
|
|
311
361
|
}
|
|
312
362
|
|
|
313
363
|
// src/runtime-version.ts
|
|
314
|
-
var
|
|
364
|
+
var SERVED_WORKSPACE_RUNTIME_FLOOR = {
|
|
365
|
+
version: "0.10.1",
|
|
366
|
+
image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
|
|
367
|
+
};
|
|
368
|
+
var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
|
|
315
369
|
|
|
316
370
|
// src/drivers/cloudflare.ts
|
|
317
371
|
function registryEntries(input) {
|
|
@@ -437,10 +491,15 @@ function createCloudflareSandboxDriver(options) {
|
|
|
437
491
|
};
|
|
438
492
|
});
|
|
439
493
|
}
|
|
494
|
+
function networkPolicy(input) {
|
|
495
|
+
if (!input.net || input.net.mode === "allow-all") return void 0;
|
|
496
|
+
return { hosts: [...new Set(input.net.hosts ?? [])] };
|
|
497
|
+
}
|
|
440
498
|
async function ensureHost(input) {
|
|
441
499
|
const sandboxId = sandboxIdFor(input.workspaceId);
|
|
442
500
|
const hostId = sandboxId;
|
|
443
501
|
const egress = egressRegistrations(input);
|
|
502
|
+
const net = networkPolicy(input);
|
|
444
503
|
const response = await call(
|
|
445
504
|
sandboxId,
|
|
446
505
|
"ensure-runtime",
|
|
@@ -452,8 +511,9 @@ function createCloudflareSandboxDriver(options) {
|
|
|
452
511
|
// what makes this driver's `list()` (and therefore GC) possible at all.
|
|
453
512
|
// Not container env — labels are control-plane metadata.
|
|
454
513
|
labels: input.labels,
|
|
455
|
-
...input.bootSource?.kind === "driver-snapshot" ? { restore: { snapshotId: input.bootSource.snapshotId }, minimumRuntimeVersion:
|
|
456
|
-
...egress ? { egress } : {}
|
|
514
|
+
...input.bootSource?.kind === "driver-snapshot" ? { restore: { snapshotId: input.bootSource.snapshotId }, minimumRuntimeVersion: MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION } : {},
|
|
515
|
+
...egress ? { egress } : {},
|
|
516
|
+
...net ? { net } : {}
|
|
457
517
|
}
|
|
458
518
|
).catch((error) => {
|
|
459
519
|
if (error instanceof Error && error.name === "TimeoutError") return void 0;
|
|
@@ -473,6 +533,10 @@ function createCloudflareSandboxDriver(options) {
|
|
|
473
533
|
const reason = `Cloudflare ensure-runtime failed (${status}): ${text(data.error) ?? "no runtime url"}`;
|
|
474
534
|
throw status === 401 || status === 403 ? new SandboxProviderKeyRefusedError(reason) : new Error(reason);
|
|
475
535
|
}
|
|
536
|
+
if (net && asRecord(data.egress)?.contained !== true) {
|
|
537
|
+
await call(sandboxId, "stop", { epoch: input.epoch }).catch(() => void 0);
|
|
538
|
+
throw new Error("Cloudflare sandbox Worker did not confirm egress containment; deploy the current sandbox Worker (scripts/sandbox/cloudflare-worker)");
|
|
539
|
+
}
|
|
476
540
|
const targetOut = {
|
|
477
541
|
workspaceId: input.workspaceId,
|
|
478
542
|
sandboxId,
|
|
@@ -558,7 +622,7 @@ function createCloudflareSandboxDriver(options) {
|
|
|
558
622
|
hostWatchesIdle: true,
|
|
559
623
|
targetAccess: "relay",
|
|
560
624
|
secretBrokering: "native",
|
|
561
|
-
egressControl: "
|
|
625
|
+
egressControl: "hosts",
|
|
562
626
|
persistence: sandboxDriverCatalog.cloudflare.metadata.persistence
|
|
563
627
|
},
|
|
564
628
|
ensureHost,
|
package/dist/drivers/docker.mjs
CHANGED
|
@@ -91,6 +91,11 @@ var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
|
|
|
91
91
|
function workspaceRuntimeVersion() {
|
|
92
92
|
return process.env.WORKSPACE_RUNTIME_VERSION || DEFAULT_WORKSPACE_RUNTIME_VERSION;
|
|
93
93
|
}
|
|
94
|
+
var SERVED_WORKSPACE_RUNTIME_FLOOR = {
|
|
95
|
+
version: "0.10.1",
|
|
96
|
+
image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
|
|
97
|
+
};
|
|
98
|
+
var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
|
|
94
99
|
|
|
95
100
|
// src/image-name.ts
|
|
96
101
|
var SNAPSHOT_SCHEMA_VERSION = 8;
|
|
@@ -133,6 +138,27 @@ var boatBilling = {
|
|
|
133
138
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
134
139
|
}
|
|
135
140
|
};
|
|
141
|
+
var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
|
|
142
|
+
var AGENT37_MONTH_HOURS = 730;
|
|
143
|
+
var agent37MachineShapes = {
|
|
144
|
+
small: { cpu: 2, memory: 4, disk: 10 },
|
|
145
|
+
default: { cpu: 4, memory: 8, disk: 20 },
|
|
146
|
+
large: { cpu: 4, memory: 16, disk: 40 }
|
|
147
|
+
};
|
|
148
|
+
function agent37Rate(shape) {
|
|
149
|
+
const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
|
|
150
|
+
return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
|
|
151
|
+
}
|
|
152
|
+
var agent37Billing = {
|
|
153
|
+
source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
|
|
154
|
+
meter: "Agent37 meters an instance per minute at a monthly rate over 730 hours: $0.80 per vCPU, $0.70 per GB of memory and $0.09 per GB of disk while it runs, and the disk alone while it is stopped.",
|
|
155
|
+
rates: {
|
|
156
|
+
small: agent37Rate(agent37MachineShapes.small),
|
|
157
|
+
default: agent37Rate(agent37MachineShapes.default),
|
|
158
|
+
large: agent37Rate(agent37MachineShapes.large)
|
|
159
|
+
},
|
|
160
|
+
excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
|
|
161
|
+
};
|
|
136
162
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
137
163
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
138
164
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -167,6 +193,7 @@ var sandboxDriverCredentialFields = {
|
|
|
167
193
|
{ key: "worker_url", label: "Worker URL" }
|
|
168
194
|
],
|
|
169
195
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
196
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
170
197
|
docker: [{ key: "image", label: "Image" }]
|
|
171
198
|
};
|
|
172
199
|
var sandboxDriverLabels = {
|
|
@@ -174,6 +201,7 @@ var sandboxDriverLabels = {
|
|
|
174
201
|
vercel: "Vercel",
|
|
175
202
|
cloudflare: "Cloudflare",
|
|
176
203
|
boat: "Boat",
|
|
204
|
+
agent37: "Agent37",
|
|
177
205
|
docker: "Docker"
|
|
178
206
|
};
|
|
179
207
|
|
|
@@ -244,8 +272,8 @@ var sandboxDriverCatalog = {
|
|
|
244
272
|
hostWatchesIdle: true,
|
|
245
273
|
targetAccess: "relay",
|
|
246
274
|
secretBrokering: "native",
|
|
247
|
-
//
|
|
248
|
-
egressControl: "
|
|
275
|
+
// The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
|
|
276
|
+
egressControl: "hosts",
|
|
249
277
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
250
278
|
persistence: {
|
|
251
279
|
resume: "replacement-restore",
|
|
@@ -283,6 +311,33 @@ var sandboxDriverCatalog = {
|
|
|
283
311
|
machineClasses: ["small", "default", "large"]
|
|
284
312
|
}
|
|
285
313
|
},
|
|
314
|
+
agent37: {
|
|
315
|
+
id: "agent37",
|
|
316
|
+
label: sandboxDriverLabels.agent37,
|
|
317
|
+
credentialFields: sandboxDriverCredentialFields.agent37,
|
|
318
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
319
|
+
runtimeEnv: "callback",
|
|
320
|
+
preparedImage: true,
|
|
321
|
+
billing: agent37Billing,
|
|
322
|
+
metadata: {
|
|
323
|
+
driverRunsIn: ["worker", "node"],
|
|
324
|
+
hostStopBehavior: "suspends-host",
|
|
325
|
+
hostResumeBehavior: "same-host",
|
|
326
|
+
targetAccess: "relay",
|
|
327
|
+
secretBrokering: "none",
|
|
328
|
+
// An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
|
|
329
|
+
egressControl: "hosts-and-cidrs",
|
|
330
|
+
persistence: {
|
|
331
|
+
resume: "same-sandbox",
|
|
332
|
+
capture: "none",
|
|
333
|
+
clone: false,
|
|
334
|
+
captureSource: "not-applicable",
|
|
335
|
+
retention: "provider-managed",
|
|
336
|
+
restoreMount: "same-resource"
|
|
337
|
+
},
|
|
338
|
+
machineClasses: ["small", "default", "large"]
|
|
339
|
+
}
|
|
340
|
+
},
|
|
286
341
|
docker: {
|
|
287
342
|
id: "docker",
|
|
288
343
|
label: sandboxDriverLabels.docker,
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import type { SandboxDriver } from "../contract";
|
|
2
2
|
import { localBrokeringTestDriverCatalogEntry } from "../driver-catalog";
|
|
3
|
+
/**
|
|
4
|
+
* A published runtime image to run instead of `executable`: Docker on the host
|
|
5
|
+
* network, with the paths the runtime reads mounted where they are, and no
|
|
6
|
+
* sandbox-exec network policy, so it runs on Linux. The version-skew suite
|
|
7
|
+
* runs the control plane against the oldest image it still serves this way.
|
|
8
|
+
*/
|
|
9
|
+
export type LocalBrokeringContainer = {
|
|
10
|
+
image: string;
|
|
11
|
+
command: string;
|
|
12
|
+
mounts: readonly string[];
|
|
13
|
+
};
|
|
3
14
|
export type LocalBrokeringDriverOptions = {
|
|
4
15
|
root: string;
|
|
5
16
|
executable: string;
|
|
6
17
|
args: string[];
|
|
18
|
+
container?: LocalBrokeringContainer;
|
|
7
19
|
allowedOrigins: readonly string[];
|
|
8
20
|
directOrigins: readonly string[];
|
|
9
21
|
upstreams?: Readonly<Record<string, string>>;
|
|
@@ -15,11 +15,6 @@ function asRecord(value) {
|
|
|
15
15
|
return isRecord(value) ? value : void 0;
|
|
16
16
|
}
|
|
17
17
|
var CLAXEDO_TOOL_NAMES = [
|
|
18
|
-
"task_list",
|
|
19
|
-
"task_get",
|
|
20
|
-
"task_create",
|
|
21
|
-
"task_edit",
|
|
22
|
-
"task_start",
|
|
23
18
|
"session_create",
|
|
24
19
|
"sessions_list",
|
|
25
20
|
"session_get",
|
|
@@ -30,8 +25,6 @@ var CLAXEDO_TOOL_NAMES = [
|
|
|
30
25
|
"session_rename",
|
|
31
26
|
"session_delete",
|
|
32
27
|
"session_changes",
|
|
33
|
-
"documents_list",
|
|
34
|
-
"documents_open",
|
|
35
28
|
"subagent_capabilities",
|
|
36
29
|
"create_subagent",
|
|
37
30
|
"subagent_status",
|
|
@@ -157,17 +150,17 @@ var AGENT_PRESENTATION_EVENT_TYPES = Object.keys(AGENT_PRESENTATION_EVENT_TYPE_R
|
|
|
157
150
|
var mode = (id, name, description, level) => ({
|
|
158
151
|
id,
|
|
159
152
|
name,
|
|
160
|
-
description,
|
|
153
|
+
...description ? { description } : {},
|
|
161
154
|
...level ? { level } : {}
|
|
162
155
|
});
|
|
163
156
|
var CLAUDE_PERMISSION_MODES = {
|
|
164
157
|
modes: [
|
|
165
|
-
mode("default", "Default", "
|
|
166
|
-
mode("acceptEdits", "Accept edits"
|
|
167
|
-
mode("auto", "Auto", "
|
|
168
|
-
mode("plan", "Plan", "
|
|
169
|
-
mode("dontAsk", "Don't ask", "
|
|
170
|
-
mode("bypassPermissions", "Bypass permissions", "
|
|
158
|
+
mode("default", "Default", "Asks before dangerous operations", "ask"),
|
|
159
|
+
mode("acceptEdits", "Accept edits"),
|
|
160
|
+
mode("auto", "Auto", "A model decides which actions to allow", "auto"),
|
|
161
|
+
mode("plan", "Plan", "Runs no tools"),
|
|
162
|
+
mode("dontAsk", "Don't ask", "Denies anything not pre-approved"),
|
|
163
|
+
mode("bypassPermissions", "Bypass permissions", "Runs everything without asking", "full")
|
|
171
164
|
],
|
|
172
165
|
appliesFrom: "immediate",
|
|
173
166
|
defaultModeId: "auto"
|
|
@@ -180,9 +173,18 @@ var CURSOR_PERMISSION_MODES = {
|
|
|
180
173
|
],
|
|
181
174
|
appliesFrom: "next-turn"
|
|
182
175
|
};
|
|
176
|
+
var ANTIGRAVITY_PERMISSION_MODES = {
|
|
177
|
+
modes: [
|
|
178
|
+
mode("default", "Default", "Ask before edits and commands, per your permission settings.", "ask"),
|
|
179
|
+
mode("accept-edits", "Accept edits", "Approve file edits in the workspace without asking."),
|
|
180
|
+
mode("plan", "Plan")
|
|
181
|
+
],
|
|
182
|
+
appliesFrom: "immediate",
|
|
183
|
+
defaultModeId: "default"
|
|
184
|
+
};
|
|
183
185
|
var CODEX_PERMISSION_MODES = {
|
|
184
186
|
modes: [
|
|
185
|
-
mode("read-only", "Read only", "Never asks;
|
|
187
|
+
mode("read-only", "Read only", "Never asks; writes fail", "ask"),
|
|
186
188
|
mode("workspace-write", "Workspace write", "Runs commands inside the workspace without asking; escalates outside it", "auto"),
|
|
187
189
|
mode("untrusted", "Untrusted", "Only trusted commands run without asking; anything else escalates"),
|
|
188
190
|
mode("full-access", "Full access", "Never asks; full filesystem and network access", "full")
|
|
@@ -226,6 +228,15 @@ var AGENT_HARNESS_DEFINITIONS = [
|
|
|
226
228
|
authSlot: "cursor",
|
|
227
229
|
cloudHost: "workspace-runtime"
|
|
228
230
|
},
|
|
231
|
+
{
|
|
232
|
+
key: "antigravity",
|
|
233
|
+
id: "antigravity",
|
|
234
|
+
access: "native",
|
|
235
|
+
label: "Antigravity",
|
|
236
|
+
authEnv: "GEMINI_API_KEY",
|
|
237
|
+
authSlot: "google",
|
|
238
|
+
cloudHost: "workspace-runtime"
|
|
239
|
+
},
|
|
229
240
|
{
|
|
230
241
|
key: "pi",
|
|
231
242
|
id: "pi",
|
|
@@ -246,7 +257,7 @@ var AGENT_HARNESS_DEFINITIONS = [
|
|
|
246
257
|
}
|
|
247
258
|
];
|
|
248
259
|
var AGENT_HARNESS_KEYS = AGENT_HARNESS_DEFINITIONS.map((item) => item.key);
|
|
249
|
-
var HARNESS_IDS = ["claude", "codex", "cursor"];
|
|
260
|
+
var HARNESS_IDS = ["claude", "codex", "cursor", "antigravity"];
|
|
250
261
|
var HARNESS_TABLE = {
|
|
251
262
|
claude: {
|
|
252
263
|
label: "Claude Code",
|
|
@@ -276,6 +287,15 @@ var HARNESS_TABLE = {
|
|
|
276
287
|
machineLoginServes: ["cursor-acp"],
|
|
277
288
|
permissionModes: CURSOR_PERMISSION_MODES,
|
|
278
289
|
defaultModelId: "auto"
|
|
290
|
+
},
|
|
291
|
+
antigravity: {
|
|
292
|
+
label: "Antigravity",
|
|
293
|
+
vendor: "Google",
|
|
294
|
+
providerIds: ["antigravity", "google"],
|
|
295
|
+
connectProvider: "antigravity",
|
|
296
|
+
vendorProvider: "google",
|
|
297
|
+
machineLoginServes: ["antigravity"],
|
|
298
|
+
permissionModes: ANTIGRAVITY_PERMISSION_MODES
|
|
279
299
|
}
|
|
280
300
|
};
|
|
281
301
|
function harnessBindingIds(harness) {
|
|
@@ -451,6 +471,27 @@ var boatBilling = {
|
|
|
451
471
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
452
472
|
}
|
|
453
473
|
};
|
|
474
|
+
var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
|
|
475
|
+
var AGENT37_MONTH_HOURS = 730;
|
|
476
|
+
var agent37MachineShapes = {
|
|
477
|
+
small: { cpu: 2, memory: 4, disk: 10 },
|
|
478
|
+
default: { cpu: 4, memory: 8, disk: 20 },
|
|
479
|
+
large: { cpu: 4, memory: 16, disk: 40 }
|
|
480
|
+
};
|
|
481
|
+
function agent37Rate(shape) {
|
|
482
|
+
const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
|
|
483
|
+
return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
|
|
484
|
+
}
|
|
485
|
+
var agent37Billing = {
|
|
486
|
+
source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
|
|
487
|
+
meter: "Agent37 meters an instance per minute at a monthly rate over 730 hours: $0.80 per vCPU, $0.70 per GB of memory and $0.09 per GB of disk while it runs, and the disk alone while it is stopped.",
|
|
488
|
+
rates: {
|
|
489
|
+
small: agent37Rate(agent37MachineShapes.small),
|
|
490
|
+
default: agent37Rate(agent37MachineShapes.default),
|
|
491
|
+
large: agent37Rate(agent37MachineShapes.large)
|
|
492
|
+
},
|
|
493
|
+
excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
|
|
494
|
+
};
|
|
454
495
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
455
496
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
456
497
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -485,6 +526,7 @@ var sandboxDriverCredentialFields = {
|
|
|
485
526
|
{ key: "worker_url", label: "Worker URL" }
|
|
486
527
|
],
|
|
487
528
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
529
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
488
530
|
docker: [{ key: "image", label: "Image" }]
|
|
489
531
|
};
|
|
490
532
|
var sandboxDriverLabels = {
|
|
@@ -492,6 +534,7 @@ var sandboxDriverLabels = {
|
|
|
492
534
|
vercel: "Vercel",
|
|
493
535
|
cloudflare: "Cloudflare",
|
|
494
536
|
boat: "Boat",
|
|
537
|
+
agent37: "Agent37",
|
|
495
538
|
docker: "Docker"
|
|
496
539
|
};
|
|
497
540
|
|
|
@@ -586,8 +629,8 @@ var sandboxDriverCatalog = {
|
|
|
586
629
|
hostWatchesIdle: true,
|
|
587
630
|
targetAccess: "relay",
|
|
588
631
|
secretBrokering: "native",
|
|
589
|
-
//
|
|
590
|
-
egressControl: "
|
|
632
|
+
// The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
|
|
633
|
+
egressControl: "hosts",
|
|
591
634
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
592
635
|
persistence: {
|
|
593
636
|
resume: "replacement-restore",
|
|
@@ -625,6 +668,33 @@ var sandboxDriverCatalog = {
|
|
|
625
668
|
machineClasses: ["small", "default", "large"]
|
|
626
669
|
}
|
|
627
670
|
},
|
|
671
|
+
agent37: {
|
|
672
|
+
id: "agent37",
|
|
673
|
+
label: sandboxDriverLabels.agent37,
|
|
674
|
+
credentialFields: sandboxDriverCredentialFields.agent37,
|
|
675
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
676
|
+
runtimeEnv: "callback",
|
|
677
|
+
preparedImage: true,
|
|
678
|
+
billing: agent37Billing,
|
|
679
|
+
metadata: {
|
|
680
|
+
driverRunsIn: ["worker", "node"],
|
|
681
|
+
hostStopBehavior: "suspends-host",
|
|
682
|
+
hostResumeBehavior: "same-host",
|
|
683
|
+
targetAccess: "relay",
|
|
684
|
+
secretBrokering: "none",
|
|
685
|
+
// An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
|
|
686
|
+
egressControl: "hosts-and-cidrs",
|
|
687
|
+
persistence: {
|
|
688
|
+
resume: "same-sandbox",
|
|
689
|
+
capture: "none",
|
|
690
|
+
clone: false,
|
|
691
|
+
captureSource: "not-applicable",
|
|
692
|
+
retention: "provider-managed",
|
|
693
|
+
restoreMount: "same-resource"
|
|
694
|
+
},
|
|
695
|
+
machineClasses: ["small", "default", "large"]
|
|
696
|
+
}
|
|
697
|
+
},
|
|
628
698
|
docker: {
|
|
629
699
|
id: "docker",
|
|
630
700
|
label: sandboxDriverLabels.docker,
|
|
@@ -793,6 +863,7 @@ ${lines}` : ""}`);
|
|
|
793
863
|
}
|
|
794
864
|
async function closeHost(host) {
|
|
795
865
|
const child = host.child;
|
|
866
|
+
if (host.container) execFileSync("docker", ["rm", "-f", host.container], { stdio: "ignore" });
|
|
796
867
|
if (child && child.exitCode === null) {
|
|
797
868
|
child.kill("SIGTERM");
|
|
798
869
|
await new Promise((resolve) => child.once("exit", () => resolve()));
|
|
@@ -802,8 +873,14 @@ async function closeHost(host) {
|
|
|
802
873
|
await new Promise((resolve) => host.proxy.close(() => resolve()));
|
|
803
874
|
await fs.rm(host.directory, { recursive: true, force: true });
|
|
804
875
|
}
|
|
876
|
+
function containerRun(container, name, input) {
|
|
877
|
+
const user = `${process.getuid?.() ?? 0}:${process.getgid?.() ?? 0}`;
|
|
878
|
+
const mounts = [.../* @__PURE__ */ new Set([input.root, ...container.mounts])].flatMap((mount) => ["-v", `${mount}:${mount}`]);
|
|
879
|
+
const env = Object.keys(input.env).filter((key) => key !== "PATH").flatMap((key) => ["-e", key]);
|
|
880
|
+
return { name, args: ["run", "--rm", "--name", name, "--network", "host", "--user", user, ...mounts, ...env, "-w", input.workspace, "--entrypoint", container.command, container.image] };
|
|
881
|
+
}
|
|
805
882
|
function createLocalBrokeringSandboxDriver(options) {
|
|
806
|
-
if (process.platform !== "darwin") throw new Error("local brokering test driver requires macOS sandbox-exec network policy");
|
|
883
|
+
if (process.platform !== "darwin" && !options.container) throw new Error("local brokering test driver requires macOS sandbox-exec network policy, or a runtime container");
|
|
807
884
|
const authority = createTestAuthority(options.root);
|
|
808
885
|
const hosts = /* @__PURE__ */ new Map();
|
|
809
886
|
const allowedOrigins = new Set(options.allowedOrigins.map((origin) => new URL(origin).origin));
|
|
@@ -976,11 +1053,9 @@ function createLocalBrokeringSandboxDriver(options) {
|
|
|
976
1053
|
const log = openSync(logFile, "w", 384);
|
|
977
1054
|
let child;
|
|
978
1055
|
try {
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
stdio: ["ignore", log, log]
|
|
983
|
-
});
|
|
1056
|
+
const container = options.container ? containerRun(options.container, `claxedo-local-${target.sandboxId}`, { root: options.root, workspace, env }) : void 0;
|
|
1057
|
+
if (container) host.container = container.name;
|
|
1058
|
+
child = container ? spawn("docker", container.args, { env: { ...process.env, ...env }, stdio: ["ignore", log, log] }) : spawn("/usr/bin/sandbox-exec", ["-p", networkPolicy, options.executable, ...options.args], { cwd: workspace, env, stdio: ["ignore", log, log] });
|
|
984
1059
|
} finally {
|
|
985
1060
|
closeSync(log);
|
|
986
1061
|
}
|
package/dist/drivers/modal.mjs
CHANGED
|
@@ -73,6 +73,11 @@ var DEFAULT_WORKSPACE_RUNTIME_VERSION = "0.5.2";
|
|
|
73
73
|
function workspaceRuntimeVersion() {
|
|
74
74
|
return process.env.WORKSPACE_RUNTIME_VERSION || DEFAULT_WORKSPACE_RUNTIME_VERSION;
|
|
75
75
|
}
|
|
76
|
+
var SERVED_WORKSPACE_RUNTIME_FLOOR = {
|
|
77
|
+
version: "0.10.1",
|
|
78
|
+
image: "ghcr.io/kyashrathore/claxedo-sandbox:workspace-runtime-0-10-1-40706b7356-agent-plugins-v8"
|
|
79
|
+
};
|
|
80
|
+
var MINIMUM_SERVED_WORKSPACE_RUNTIME_VERSION = SERVED_WORKSPACE_RUNTIME_FLOOR.version;
|
|
76
81
|
|
|
77
82
|
// src/image-name.ts
|
|
78
83
|
var SNAPSHOT_SCHEMA_VERSION = 8;
|
|
@@ -109,6 +114,27 @@ var boatBilling = {
|
|
|
109
114
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
110
115
|
}
|
|
111
116
|
};
|
|
117
|
+
var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
|
|
118
|
+
var AGENT37_MONTH_HOURS = 730;
|
|
119
|
+
var agent37MachineShapes = {
|
|
120
|
+
small: { cpu: 2, memory: 4, disk: 10 },
|
|
121
|
+
default: { cpu: 4, memory: 8, disk: 20 },
|
|
122
|
+
large: { cpu: 4, memory: 16, disk: 40 }
|
|
123
|
+
};
|
|
124
|
+
function agent37Rate(shape) {
|
|
125
|
+
const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
|
|
126
|
+
return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
|
|
127
|
+
}
|
|
128
|
+
var agent37Billing = {
|
|
129
|
+
source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
|
|
130
|
+
meter: "Agent37 meters an instance per minute at a monthly rate over 730 hours: $0.80 per vCPU, $0.70 per GB of memory and $0.09 per GB of disk while it runs, and the disk alone while it is stopped.",
|
|
131
|
+
rates: {
|
|
132
|
+
small: agent37Rate(agent37MachineShapes.small),
|
|
133
|
+
default: agent37Rate(agent37MachineShapes.default),
|
|
134
|
+
large: agent37Rate(agent37MachineShapes.large)
|
|
135
|
+
},
|
|
136
|
+
excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
|
|
137
|
+
};
|
|
112
138
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
113
139
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
114
140
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -143,6 +169,7 @@ var sandboxDriverCredentialFields = {
|
|
|
143
169
|
{ key: "worker_url", label: "Worker URL" }
|
|
144
170
|
],
|
|
145
171
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
172
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
146
173
|
docker: [{ key: "image", label: "Image" }]
|
|
147
174
|
};
|
|
148
175
|
var sandboxDriverLabels = {
|
|
@@ -150,6 +177,7 @@ var sandboxDriverLabels = {
|
|
|
150
177
|
vercel: "Vercel",
|
|
151
178
|
cloudflare: "Cloudflare",
|
|
152
179
|
boat: "Boat",
|
|
180
|
+
agent37: "Agent37",
|
|
153
181
|
docker: "Docker"
|
|
154
182
|
};
|
|
155
183
|
|
|
@@ -220,8 +248,8 @@ var sandboxDriverCatalog = {
|
|
|
220
248
|
hostWatchesIdle: true,
|
|
221
249
|
targetAccess: "relay",
|
|
222
250
|
secretBrokering: "native",
|
|
223
|
-
//
|
|
224
|
-
egressControl: "
|
|
251
|
+
// The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
|
|
252
|
+
egressControl: "hosts",
|
|
225
253
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
226
254
|
persistence: {
|
|
227
255
|
resume: "replacement-restore",
|
|
@@ -259,6 +287,33 @@ var sandboxDriverCatalog = {
|
|
|
259
287
|
machineClasses: ["small", "default", "large"]
|
|
260
288
|
}
|
|
261
289
|
},
|
|
290
|
+
agent37: {
|
|
291
|
+
id: "agent37",
|
|
292
|
+
label: sandboxDriverLabels.agent37,
|
|
293
|
+
credentialFields: sandboxDriverCredentialFields.agent37,
|
|
294
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
295
|
+
runtimeEnv: "callback",
|
|
296
|
+
preparedImage: true,
|
|
297
|
+
billing: agent37Billing,
|
|
298
|
+
metadata: {
|
|
299
|
+
driverRunsIn: ["worker", "node"],
|
|
300
|
+
hostStopBehavior: "suspends-host",
|
|
301
|
+
hostResumeBehavior: "same-host",
|
|
302
|
+
targetAccess: "relay",
|
|
303
|
+
secretBrokering: "none",
|
|
304
|
+
// An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
|
|
305
|
+
egressControl: "hosts-and-cidrs",
|
|
306
|
+
persistence: {
|
|
307
|
+
resume: "same-sandbox",
|
|
308
|
+
capture: "none",
|
|
309
|
+
clone: false,
|
|
310
|
+
captureSource: "not-applicable",
|
|
311
|
+
retention: "provider-managed",
|
|
312
|
+
restoreMount: "same-resource"
|
|
313
|
+
},
|
|
314
|
+
machineClasses: ["small", "default", "large"]
|
|
315
|
+
}
|
|
316
|
+
},
|
|
262
317
|
docker: {
|
|
263
318
|
id: "docker",
|
|
264
319
|
label: sandboxDriverLabels.docker,
|