@claxedo/sandbox-manager 0.10.2 → 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 +67 -29
- package/dist/checkpoint-manager.mjs +11 -0
- package/dist/contract.d.ts +28 -16
- package/dist/driver-billing.d.ts +23 -0
- package/dist/driver-catalog.mjs +57 -3
- package/dist/driver-ensure-input.d.ts +3 -2
- 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 +7 -17
- package/dist/drivers/boat-template.mjs +67 -14
- package/dist/drivers/boat.d.ts +0 -5
- package/dist/drivers/boat.mjs +67 -14
- package/dist/drivers/cloudflare.d.ts +5 -9
- package/dist/drivers/cloudflare.mjs +64 -4
- package/dist/drivers/docker.mjs +52 -2
- package/dist/drivers/local-brokering.mjs +88 -18
- package/dist/drivers/modal.mjs +52 -2
- package/dist/drivers/transient-error.d.ts +0 -1
- package/dist/drivers/vercel.mjs +56 -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/index.mjs +103 -67
- package/dist/json.d.ts +1 -10
- package/dist/lease-failure.d.ts +3 -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 +4 -0
- package/dist/runtime-version.mjs +6 -0
- package/dist/start-admission.d.ts +32 -0
- package/package.json +12 -4
package/dist/drivers/docker.mjs
CHANGED
|
@@ -138,6 +138,27 @@ var boatBilling = {
|
|
|
138
138
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
139
139
|
}
|
|
140
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
|
+
};
|
|
141
162
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
142
163
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
143
164
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -172,6 +193,7 @@ var sandboxDriverCredentialFields = {
|
|
|
172
193
|
{ key: "worker_url", label: "Worker URL" }
|
|
173
194
|
],
|
|
174
195
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
196
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
175
197
|
docker: [{ key: "image", label: "Image" }]
|
|
176
198
|
};
|
|
177
199
|
var sandboxDriverLabels = {
|
|
@@ -179,6 +201,7 @@ var sandboxDriverLabels = {
|
|
|
179
201
|
vercel: "Vercel",
|
|
180
202
|
cloudflare: "Cloudflare",
|
|
181
203
|
boat: "Boat",
|
|
204
|
+
agent37: "Agent37",
|
|
182
205
|
docker: "Docker"
|
|
183
206
|
};
|
|
184
207
|
|
|
@@ -249,8 +272,8 @@ var sandboxDriverCatalog = {
|
|
|
249
272
|
hostWatchesIdle: true,
|
|
250
273
|
targetAccess: "relay",
|
|
251
274
|
secretBrokering: "native",
|
|
252
|
-
//
|
|
253
|
-
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",
|
|
254
277
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
255
278
|
persistence: {
|
|
256
279
|
resume: "replacement-restore",
|
|
@@ -288,6 +311,33 @@ var sandboxDriverCatalog = {
|
|
|
288
311
|
machineClasses: ["small", "default", "large"]
|
|
289
312
|
}
|
|
290
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
|
+
},
|
|
291
341
|
docker: {
|
|
292
342
|
id: "docker",
|
|
293
343
|
label: sandboxDriverLabels.docker,
|
|
@@ -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,
|
package/dist/drivers/modal.mjs
CHANGED
|
@@ -114,6 +114,27 @@ var boatBilling = {
|
|
|
114
114
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
115
115
|
}
|
|
116
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
|
+
};
|
|
117
138
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
118
139
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
119
140
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -148,6 +169,7 @@ var sandboxDriverCredentialFields = {
|
|
|
148
169
|
{ key: "worker_url", label: "Worker URL" }
|
|
149
170
|
],
|
|
150
171
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
172
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
151
173
|
docker: [{ key: "image", label: "Image" }]
|
|
152
174
|
};
|
|
153
175
|
var sandboxDriverLabels = {
|
|
@@ -155,6 +177,7 @@ var sandboxDriverLabels = {
|
|
|
155
177
|
vercel: "Vercel",
|
|
156
178
|
cloudflare: "Cloudflare",
|
|
157
179
|
boat: "Boat",
|
|
180
|
+
agent37: "Agent37",
|
|
158
181
|
docker: "Docker"
|
|
159
182
|
};
|
|
160
183
|
|
|
@@ -225,8 +248,8 @@ var sandboxDriverCatalog = {
|
|
|
225
248
|
hostWatchesIdle: true,
|
|
226
249
|
targetAccess: "relay",
|
|
227
250
|
secretBrokering: "native",
|
|
228
|
-
//
|
|
229
|
-
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",
|
|
230
253
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
231
254
|
persistence: {
|
|
232
255
|
resume: "replacement-restore",
|
|
@@ -264,6 +287,33 @@ var sandboxDriverCatalog = {
|
|
|
264
287
|
machineClasses: ["small", "default", "large"]
|
|
265
288
|
}
|
|
266
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
|
+
},
|
|
267
317
|
docker: {
|
|
268
318
|
id: "docker",
|
|
269
319
|
label: sandboxDriverLabels.docker,
|
package/dist/drivers/vercel.mjs
CHANGED
|
@@ -101,6 +101,27 @@ var boatBilling = {
|
|
|
101
101
|
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
|
+
var AGENT37_USD_PER_MONTH = { vcpu: 0.8, memoryGb: 0.7, diskGb: 0.09 };
|
|
105
|
+
var AGENT37_MONTH_HOURS = 730;
|
|
106
|
+
var agent37MachineShapes = {
|
|
107
|
+
small: { cpu: 2, memory: 4, disk: 10 },
|
|
108
|
+
default: { cpu: 4, memory: 8, disk: 20 },
|
|
109
|
+
large: { cpu: 4, memory: 16, disk: 40 }
|
|
110
|
+
};
|
|
111
|
+
function agent37Rate(shape) {
|
|
112
|
+
const usdPerMonth = shape.cpu * AGENT37_USD_PER_MONTH.vcpu + shape.memory * AGENT37_USD_PER_MONTH.memoryGb + shape.disk * AGENT37_USD_PER_MONTH.diskGb;
|
|
113
|
+
return { size: `${shape.cpu} vCPU / ${shape.memory} GB`, vcpu: shape.cpu, memoryGb: shape.memory, usdPerHour: usdPerMonth / AGENT37_MONTH_HOURS };
|
|
114
|
+
}
|
|
115
|
+
var agent37Billing = {
|
|
116
|
+
source: { url: "https://www.agent37.com/docs/agents-api/billing", readOn: "2026-11-11" },
|
|
117
|
+
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.",
|
|
118
|
+
rates: {
|
|
119
|
+
small: agent37Rate(agent37MachineShapes.small),
|
|
120
|
+
default: agent37Rate(agent37MachineShapes.default),
|
|
121
|
+
large: agent37Rate(agent37MachineShapes.large)
|
|
122
|
+
},
|
|
123
|
+
excludes: `the disk of a stopped instance, billed at $${AGENT37_USD_PER_MONTH.diskGb} per GB a month until the instance is deleted`
|
|
124
|
+
};
|
|
104
125
|
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
105
126
|
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
106
127
|
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
@@ -135,6 +156,7 @@ var sandboxDriverCredentialFields = {
|
|
|
135
156
|
{ key: "worker_url", label: "Worker URL" }
|
|
136
157
|
],
|
|
137
158
|
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
159
|
+
agent37: [{ key: "api_key", label: "API Key", secret: true }],
|
|
138
160
|
docker: [{ key: "image", label: "Image" }]
|
|
139
161
|
};
|
|
140
162
|
var sandboxDriverLabels = {
|
|
@@ -142,6 +164,7 @@ var sandboxDriverLabels = {
|
|
|
142
164
|
vercel: "Vercel",
|
|
143
165
|
cloudflare: "Cloudflare",
|
|
144
166
|
boat: "Boat",
|
|
167
|
+
agent37: "Agent37",
|
|
145
168
|
docker: "Docker"
|
|
146
169
|
};
|
|
147
170
|
|
|
@@ -212,8 +235,8 @@ var sandboxDriverCatalog = {
|
|
|
212
235
|
hostWatchesIdle: true,
|
|
213
236
|
targetAccess: "relay",
|
|
214
237
|
secretBrokering: "native",
|
|
215
|
-
//
|
|
216
|
-
egressControl: "
|
|
238
|
+
// The sandbox Worker starts the container without internet and routes each allowed host through itself; a Worker that cannot confirm that refuses the start.
|
|
239
|
+
egressControl: "hosts",
|
|
217
240
|
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
218
241
|
persistence: {
|
|
219
242
|
resume: "replacement-restore",
|
|
@@ -251,6 +274,33 @@ var sandboxDriverCatalog = {
|
|
|
251
274
|
machineClasses: ["small", "default", "large"]
|
|
252
275
|
}
|
|
253
276
|
},
|
|
277
|
+
agent37: {
|
|
278
|
+
id: "agent37",
|
|
279
|
+
label: sandboxDriverLabels.agent37,
|
|
280
|
+
credentialFields: sandboxDriverCredentialFields.agent37,
|
|
281
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
282
|
+
runtimeEnv: "callback",
|
|
283
|
+
preparedImage: true,
|
|
284
|
+
billing: agent37Billing,
|
|
285
|
+
metadata: {
|
|
286
|
+
driverRunsIn: ["worker", "node"],
|
|
287
|
+
hostStopBehavior: "suspends-host",
|
|
288
|
+
hostResumeBehavior: "same-host",
|
|
289
|
+
targetAccess: "relay",
|
|
290
|
+
secretBrokering: "none",
|
|
291
|
+
// An instance's network policy lists domains, reached over HTTPS on 443 alone, and IPv4 ranges; private ranges stay blocked whatever it lists.
|
|
292
|
+
egressControl: "hosts-and-cidrs",
|
|
293
|
+
persistence: {
|
|
294
|
+
resume: "same-sandbox",
|
|
295
|
+
capture: "none",
|
|
296
|
+
clone: false,
|
|
297
|
+
captureSource: "not-applicable",
|
|
298
|
+
retention: "provider-managed",
|
|
299
|
+
restoreMount: "same-resource"
|
|
300
|
+
},
|
|
301
|
+
machineClasses: ["small", "default", "large"]
|
|
302
|
+
}
|
|
303
|
+
},
|
|
254
304
|
docker: {
|
|
255
305
|
id: "docker",
|
|
256
306
|
label: sandboxDriverLabels.docker,
|
|
@@ -492,17 +542,20 @@ function createVercelSandboxDriver(options) {
|
|
|
492
542
|
"curl https://cursor.com/install -fsS | bash",
|
|
493
543
|
"curl -fsSL https://ampcode.com/install.sh | bash",
|
|
494
544
|
"curl -fsSL https://app.factory.ai/cli | sh",
|
|
545
|
+
"curl -fsSL https://antigravity.google/cli/install.sh | bash",
|
|
495
546
|
"sudo ln -sf $HOME/.local/bin/agent /usr/local/bin/agent",
|
|
496
547
|
"sudo ln -sf $HOME/.local/bin/cursor-agent /usr/local/bin/cursor-agent",
|
|
497
548
|
"sudo ln -sf $HOME/.local/bin/amp /usr/local/bin/amp",
|
|
498
549
|
"sudo ln -sf $HOME/.local/bin/droid /usr/local/bin/droid",
|
|
550
|
+
"sudo ln -sf $HOME/.local/bin/agy /usr/local/bin/agy",
|
|
499
551
|
"command -v opencode",
|
|
500
552
|
"command -v claude",
|
|
501
553
|
"command -v codex",
|
|
502
554
|
"command -v agent",
|
|
503
555
|
"command -v cursor-agent",
|
|
504
556
|
"command -v amp",
|
|
505
|
-
"command -v droid"
|
|
557
|
+
"command -v droid",
|
|
558
|
+
"command -v agy"
|
|
506
559
|
].join(" && "));
|
|
507
560
|
await runSetup(builder, [
|
|
508
561
|
`sudo mkdir -p ${shell(RUNTIME_DIR)}`,
|
package/dist/egress-policy.d.ts
CHANGED
|
@@ -8,26 +8,32 @@ export declare function sandboxNetworkPolicyWithBrokeredHosts(policy: SandboxNet
|
|
|
8
8
|
/** @see SandboxDriverMetadata.egressControl */
|
|
9
9
|
export type SandboxEgressControl = "none" | "hosts" | "hosts-and-cidrs";
|
|
10
10
|
/**
|
|
11
|
-
* What
|
|
12
|
-
*
|
|
11
|
+
* What a start does with a restricted policy on a driver that cannot contain
|
|
12
|
+
* egress: `"refuse"` the start, or `"allow"` the sandbox to run with the policy
|
|
13
|
+
* withheld and the gap reported. Refusing is the default; allowing is the
|
|
14
|
+
* workspace owner's explicit, auditable decision.
|
|
15
|
+
*/
|
|
16
|
+
export type SandboxUncontainedEgress = "refuse" | "allow";
|
|
17
|
+
/**
|
|
18
|
+
* What the manager does with a caller's `net` for a given driver.
|
|
13
19
|
*
|
|
14
20
|
* - `"enforce"` — the driver gets the policy verbatim and contains the
|
|
15
21
|
* sandbox. Also the answer when the caller asked for no containment
|
|
16
22
|
* (absent / `allow-all`), which is nothing to enforce.
|
|
17
|
-
* - `"withhold"` — the driver declares `egressControl: "none"
|
|
18
|
-
*
|
|
19
|
-
* drivers throw on a restricted policy (docker, modal, boat)
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* particular policy's encoding (a
|
|
27
|
-
* allowlist).
|
|
28
|
-
* on an otherwise-enforcing driver
|
|
29
|
-
* weaken the enforcing path
|
|
30
|
-
* hosts, so no production path reaches it.
|
|
23
|
+
* - `"withhold"` — the driver declares `egressControl: "none"` and the
|
|
24
|
+
* start allows uncontained egress. The policy is NOT handed down: the
|
|
25
|
+
* `"none"` drivers throw on a restricted policy (docker, modal, boat), so
|
|
26
|
+
* withholding at the manager keeps their throws as their own last line of
|
|
27
|
+
* defence. The sandbox comes up with UNRESTRICTED egress, which is a real
|
|
28
|
+
* exposure, so the manager warns (see `onEgressUnenforced`).
|
|
29
|
+
* - `"refuse"` — either the driver declares `egressControl: "none"` and the
|
|
30
|
+
* start does not allow uncontained egress (`sandbox_egress_uncontained`,
|
|
31
|
+
* the default), or the driver HAS egress control but cannot express this
|
|
32
|
+
* particular policy's encoding (`sandbox_egress_policy_unenforceable`: a
|
|
33
|
+
* hosts-only driver handed an address-only allowlist). The second is a
|
|
34
|
+
* composition mistake on an otherwise-enforcing driver; degrading it to
|
|
35
|
+
* "withhold" would weaken the enforcing path, and `hostedSandboxNetworkPolicy`
|
|
36
|
+
* only ever emits hosts, so no production path reaches it.
|
|
31
37
|
*
|
|
32
38
|
* Pure, like `validateSandboxPersistenceCapabilities`, so the manager, the
|
|
33
39
|
* composition layer, and tests can all ask the same question.
|
|
@@ -39,22 +45,18 @@ export type SandboxEgressDisposition = {
|
|
|
39
45
|
reason: "sandbox_egress_uncontained";
|
|
40
46
|
} | {
|
|
41
47
|
action: "refuse";
|
|
42
|
-
reason: "sandbox_egress_policy_unenforceable";
|
|
48
|
+
reason: "sandbox_egress_uncontained" | "sandbox_egress_policy_unenforceable";
|
|
43
49
|
};
|
|
44
50
|
/** @see SandboxEgressDisposition */
|
|
45
|
-
export declare function sandboxEgressDisposition(control: SandboxEgressControl, net: SandboxNetworkPolicy | undefined): SandboxEgressDisposition;
|
|
51
|
+
export declare function sandboxEgressDisposition(control: SandboxEgressControl, net: SandboxNetworkPolicy | undefined, uncontained?: SandboxUncontainedEgress): SandboxEgressDisposition;
|
|
46
52
|
/**
|
|
47
|
-
* Emitted
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* - `"composition"` — once per `createSandboxManager` per driver, at boot.
|
|
53
|
-
* - `"ensure"` — every time a caller's policy is actually withheld, naming the
|
|
54
|
-
* workspace and the allowlist that did not take effect.
|
|
53
|
+
* Emitted the first time per driver per isolate that a start which allows
|
|
54
|
+
* uncontained egress has its restricted policy withheld because the driver
|
|
55
|
+
* declares no egress control: an unrestricted sandbox that nobody was told
|
|
56
|
+
* about is the exposure, so the degrade is never silent. A start that refuses
|
|
57
|
+
* uncontained egress emits none: it never runs.
|
|
55
58
|
*/
|
|
56
59
|
export type SandboxEgressUnenforcedEvent = {
|
|
57
|
-
phase: "composition" | "ensure";
|
|
58
60
|
reason: "sandbox_egress_uncontained";
|
|
59
61
|
/** `SandboxDriver.id` of the composed driver. */
|
|
60
62
|
driver: string;
|
|
@@ -62,12 +64,11 @@ export type SandboxEgressUnenforcedEvent = {
|
|
|
62
64
|
egressControl: SandboxEgressControl;
|
|
63
65
|
/** Ready-to-log sentence. Sinks that only forward text can use this alone. */
|
|
64
66
|
message: string;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/** The start's placement labels. Present on `"ensure"`. */
|
|
67
|
+
workspaceId: string;
|
|
68
|
+
/** The start's placement labels. */
|
|
68
69
|
labels?: Record<string, string>;
|
|
69
|
-
/** The allowlist the caller asked for and did NOT get.
|
|
70
|
-
requested
|
|
70
|
+
/** The allowlist the caller asked for and did NOT get. */
|
|
71
|
+
requested: SandboxNetworkPolicy;
|
|
71
72
|
};
|
|
72
73
|
/**
|
|
73
74
|
* A credential the SANDBOX must be able to USE for outbound requests but must
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { SandboxEgressControl, SandboxEgressUnenforcedEvent, SandboxNetworkPolicy } from "./egress-policy";
|
|
2
2
|
/**
|
|
3
|
-
* The
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* wherever the process starts, so an operator learns of it BEFORE the first
|
|
7
|
-
* workspace exists. `withheld` is the start half, raised once per driver per
|
|
8
|
-
* isolate from the first start whose policy the driver could not enforce.
|
|
3
|
+
* The warning that a start runs with unrestricted egress, raised once per
|
|
4
|
+
* driver per isolate from the first start whose policy the driver could not
|
|
5
|
+
* enforce. A refused start raises none: its refusal is that start's own answer.
|
|
9
6
|
*/
|
|
10
7
|
export declare function createEgressWarnings(input: {
|
|
11
8
|
driver: {
|
|
@@ -20,3 +17,4 @@ export declare function createEgressWarnings(input: {
|
|
|
20
17
|
requested: SandboxNetworkPolicy;
|
|
21
18
|
}): void;
|
|
22
19
|
};
|
|
20
|
+
export type EgressWarnings = ReturnType<typeof createEgressWarnings>;
|