@claxedo/sandbox-manager 0.7.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.
Files changed (70) hide show
  1. package/README.md +245 -42
  2. package/dist/checkpoint-manager.d.ts +29 -4
  3. package/dist/checkpoint-manager.mjs +133 -24
  4. package/dist/command.d.ts +9 -2
  5. package/dist/command.mjs +8 -8
  6. package/dist/contract.d.ts +687 -0
  7. package/dist/driver-billing.d.ts +29 -0
  8. package/dist/driver-catalog.d.ts +43 -58
  9. package/dist/driver-catalog.mjs +192 -229
  10. package/dist/drivers/boat-client.d.ts +95 -0
  11. package/dist/drivers/boat-named-snapshots.d.ts +31 -0
  12. package/dist/drivers/boat-template.d.ts +49 -0
  13. package/dist/drivers/boat-template.mjs +1196 -0
  14. package/dist/drivers/boat.d.ts +64 -0
  15. package/dist/drivers/boat.mjs +990 -0
  16. package/dist/drivers/cloudflare.d.ts +5 -8
  17. package/dist/drivers/cloudflare.mjs +364 -213
  18. package/dist/drivers/docker.d.ts +4 -3
  19. package/dist/drivers/docker.mjs +244 -165
  20. package/dist/drivers/local-brokering.d.ts +14 -0
  21. package/dist/drivers/local-brokering.mjs +1029 -0
  22. package/dist/drivers/modal.d.ts +4 -7
  23. package/dist/drivers/modal.mjs +220 -155
  24. package/dist/drivers/transient-error.d.ts +13 -0
  25. package/dist/drivers/vercel.d.ts +21 -23
  26. package/dist/drivers/vercel.mjs +279 -169
  27. package/dist/egress-policy.d.ts +134 -0
  28. package/dist/egress-warnings.d.ts +22 -0
  29. package/dist/garbage-collect.d.ts +14 -0
  30. package/dist/hosted-network-policy.d.ts +11 -4
  31. package/dist/hosted-network-policy.mjs +221 -4
  32. package/dist/image-name.d.ts +12 -2
  33. package/dist/image-name.mjs +43 -0
  34. package/dist/image.d.ts +1 -20
  35. package/dist/image.mjs +11 -66
  36. package/dist/index.d.ts +8 -533
  37. package/dist/index.mjs +1420 -315
  38. package/dist/json.d.ts +13 -0
  39. package/dist/lease-failure.d.ts +173 -0
  40. package/dist/lease-lifecycle.d.ts +65 -0
  41. package/dist/lease-retry-wait.d.ts +8 -0
  42. package/dist/lease-start.d.ts +21 -0
  43. package/dist/lease-types.d.ts +15 -5
  44. package/dist/manager.d.ts +2 -0
  45. package/dist/runtime-env.d.ts +15 -2
  46. package/dist/runtime-env.mjs +50 -1
  47. package/dist/runtime-snapshot.d.ts +49 -0
  48. package/dist/runtime-version.d.ts +9 -0
  49. package/dist/runtime-version.mjs +2 -0
  50. package/dist/service-url-exposure.d.ts +1 -3
  51. package/dist/service-url-exposure.mjs +1 -26
  52. package/dist/start-fresh.d.ts +17 -0
  53. package/dist/start-telemetry.d.ts +37 -0
  54. package/dist/stores/memory.d.ts +1 -1
  55. package/dist/stores/memory.mjs +65 -54
  56. package/package.json +67 -81
  57. package/dist/daytona-allow-list.d.ts +0 -16
  58. package/dist/daytona-allow-list.mjs +0 -11
  59. package/dist/drivers/box.d.ts +0 -52
  60. package/dist/drivers/box.mjs +0 -499
  61. package/dist/drivers/cloudflare-egress.d.ts +0 -40
  62. package/dist/drivers/cloudflare-egress.mjs +0 -113
  63. package/dist/drivers/daytona.d.ts +0 -127
  64. package/dist/drivers/daytona.mjs +0 -541
  65. package/dist/drivers/exe.d.ts +0 -26
  66. package/dist/drivers/exe.mjs +0 -469
  67. package/dist/drivers/fetch-bridge.d.ts +0 -10
  68. package/dist/drivers/fetch-bridge.mjs +0 -111
  69. package/dist/lease-policy.d.ts +0 -48
  70. package/dist/lease-policy.mjs +0 -280
@@ -1,280 +0,0 @@
1
- // src/hosted-network-policy.ts
2
- var SANDBOX_MODEL_PROVIDER_HOSTS = [
3
- "api.anthropic.com",
4
- "api.openai.com",
5
- "generativelanguage.googleapis.com",
6
- "openrouter.ai",
7
- // Model catalog + engine config, fetched on runner startup.
8
- "models.dev",
9
- "opencode.ai"
10
- ];
11
- var SANDBOX_PACKAGE_REGISTRY_HOSTS = [
12
- "registry.npmjs.org",
13
- "nodejs.org",
14
- "pypi.org",
15
- "files.pythonhosted.org",
16
- "crates.io",
17
- "static.crates.io",
18
- "index.crates.io",
19
- "proxy.golang.org",
20
- "sum.golang.org"
21
- ];
22
- var SANDBOX_BASELINE_EGRESS_HOSTS = [
23
- ...SANDBOX_MODEL_PROVIDER_HOSTS,
24
- ...SANDBOX_PACKAGE_REGISTRY_HOSTS
25
- ];
26
-
27
- // src/driver-catalog.ts
28
- var sandboxDriverCatalog = {
29
- exe: {
30
- id: "exe",
31
- label: "exe.dev",
32
- credentialFields: [{ key: "api_token", label: "API Token", secret: true }],
33
- metadata: {
34
- driverRunsIn: ["worker", "node"],
35
- hostStopBehavior: "not-supported",
36
- hostResumeBehavior: "same-host",
37
- targetAccess: "relay",
38
- secretBrokering: "none",
39
- egressControl: "none",
40
- persistence: {
41
- resume: "same-sandbox",
42
- capture: "none",
43
- clone: true,
44
- captureSource: "not-applicable",
45
- retention: "provider-managed",
46
- restoreMount: "same-resource"
47
- }
48
- }
49
- },
50
- daytona: {
51
- id: "daytona",
52
- label: "Daytona",
53
- credentialFields: [{ key: "api_key", label: "API Key", secret: true }],
54
- metadata: {
55
- driverRunsIn: ["worker", "node"],
56
- hostStopBehavior: "suspends-host",
57
- hostResumeBehavior: "same-host",
58
- targetAccess: "relay",
59
- secretBrokering: "native",
60
- // Daytona is the only driver that can filter egress by NAME as well as
61
- // by address: `domainAllowList` (names) alongside `networkAllowList`
62
- // (CIDRs), with `networkBlockAll` as the deny-all floor.
63
- egressControl: "hosts-and-cidrs",
64
- persistence: {
65
- resume: "same-sandbox",
66
- capture: "filesystem",
67
- clone: false,
68
- captureSource: "preserved",
69
- retention: "provider-managed",
70
- restoreMount: "new-resource"
71
- }
72
- }
73
- },
74
- modal: {
75
- id: "modal",
76
- label: "Modal",
77
- credentialFields: [
78
- { key: "token_id", label: "Token ID", secret: true },
79
- { key: "token_secret", label: "Token Secret", secret: true }
80
- ],
81
- metadata: {
82
- driverRunsIn: ["node"],
83
- hostStopBehavior: "terminates-host",
84
- hostResumeBehavior: "replacement-host",
85
- targetAccess: "relay",
86
- secretBrokering: "none",
87
- // Modal can cut the network entirely (`blockNetwork`) but cannot express
88
- // an allowlist, and its driver throws on a host policy. A blackout is
89
- // not containment for a workspace that has to clone and reach a model.
90
- egressControl: "none",
91
- persistence: {
92
- resume: "replacement-restore",
93
- capture: "filesystem",
94
- clone: false,
95
- captureSource: "preserved",
96
- retention: "provider-managed",
97
- restoreMount: "new-resource"
98
- }
99
- }
100
- },
101
- vercel: {
102
- id: "vercel",
103
- label: "Vercel",
104
- credentialFields: [
105
- { key: "access_token", label: "Access Token", secret: true },
106
- { key: "team_id", label: "Team ID" },
107
- { key: "project_id", label: "Project ID" }
108
- ],
109
- metadata: {
110
- driverRunsIn: ["node"],
111
- hostStopBehavior: "terminates-host",
112
- hostResumeBehavior: "replacement-host",
113
- targetAccess: "relay",
114
- secretBrokering: "native",
115
- // Vercel's sandbox firewall takes a hostname allow list (or "deny-all"),
116
- // never CIDRs.
117
- egressControl: "hosts",
118
- persistence: {
119
- resume: "replacement-restore",
120
- capture: "filesystem",
121
- clone: false,
122
- captureSource: "stopped",
123
- retention: "explicit",
124
- restoreMount: "new-resource"
125
- }
126
- }
127
- },
128
- cloudflare: {
129
- id: "cloudflare",
130
- label: "Cloudflare",
131
- credentialFields: [
132
- { key: "api_token", label: "API Token", secret: true },
133
- { key: "worker_url", label: "Worker URL" }
134
- ],
135
- metadata: {
136
- driverRunsIn: ["worker"],
137
- hostStopBehavior: "not-supported",
138
- hostResumeBehavior: "same-host",
139
- targetAccess: "relay",
140
- secretBrokering: "proxy",
141
- // The Cloudflare Sandbox Worker exposes no egress filter: its broker
142
- // (drivers/cloudflare-egress.ts) is an OPT-IN proxy the sandbox chooses
143
- // to route brokered-credential requests through, not a boundary. The
144
- // driver therefore drops `net` entirely — which is exactly why this
145
- // must be declared, so the manager refuses instead of provisioning a
146
- // sandbox the caller believes is contained.
147
- egressControl: "none",
148
- persistence: {
149
- resume: "replacement-restore",
150
- capture: "directories",
151
- clone: false,
152
- captureSource: "preserved",
153
- retention: "provider-managed",
154
- restoreMount: "copy-on-write"
155
- }
156
- }
157
- },
158
- box: {
159
- id: "box",
160
- label: "Box",
161
- credentialFields: [{ key: "api_key", label: "API Key", secret: true }],
162
- metadata: {
163
- driverRunsIn: ["node"],
164
- hostStopBehavior: "suspends-host",
165
- hostResumeBehavior: "same-host",
166
- targetAccess: "relay",
167
- secretBrokering: "none",
168
- egressControl: "none",
169
- persistence: {
170
- resume: "same-sandbox",
171
- capture: "none",
172
- clone: false,
173
- captureSource: "not-applicable",
174
- retention: "provider-managed",
175
- restoreMount: "same-resource"
176
- }
177
- }
178
- },
179
- docker: {
180
- id: "docker",
181
- label: "Docker",
182
- credentialFields: [{ key: "image", label: "Image" }],
183
- metadata: {
184
- driverRunsIn: ["local"],
185
- hostStopBehavior: "terminates-host",
186
- hostResumeBehavior: "same-host",
187
- targetAccess: "loopback",
188
- secretBrokering: "none",
189
- egressControl: "none",
190
- persistence: {
191
- resume: "replacement-restore",
192
- capture: "same-resource",
193
- clone: false,
194
- captureSource: "preserved",
195
- retention: "provider-managed",
196
- restoreMount: "same-resource"
197
- }
198
- }
199
- }
200
- };
201
-
202
- // src/lease-policy.ts
203
- var DEFAULT_WORKSPACE_HOST_DECISION_CONFIG = {
204
- maxRetries: 8,
205
- idleMs: 10 * 60 * 1e3,
206
- backoffMaxMs: 3e4,
207
- healthTimeoutMs: 6e4
208
- };
209
- function sandboxDriverPlacement(driver) {
210
- const metadata = sandboxDriverCatalog[driver].metadata;
211
- return {
212
- canPauseAndRestartSameResource: metadata.persistence.resume === "same-sandbox",
213
- canCreateFilesystemSnapshot: metadata.persistence.capture === "filesystem" || metadata.persistence.capture === "directories",
214
- canStartFromPreparedImage: driver === "exe" || driver === "daytona" || driver === "modal" || driver === "box" || driver === "docker",
215
- canStopExplicitly: metadata.hostStopBehavior !== "not-supported",
216
- hasHealthProbe: true
217
- };
218
- }
219
- function decideSandboxStart(lease, placement, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
220
- if (lease.status === "ready") {
221
- return { action: "skip", reason: "already ready" };
222
- }
223
- if (lease.status === "failed") {
224
- return { action: "mark_failed", reason: `terminal failure: ${lease.last_error ?? "unknown"}` };
225
- }
226
- if (lease.status === "backoff") {
227
- if (lease.retry_count >= config.maxRetries) {
228
- return { action: "mark_failed", reason: `exceeded max retries (${config.maxRetries})` };
229
- }
230
- if (lease.next_retry_at && now < lease.next_retry_at) {
231
- return { action: "wait", until: lease.next_retry_at, reason: "backoff timer not elapsed" };
232
- }
233
- }
234
- if (lease.status === "acquiring" || lease.status === "starting") {
235
- return { action: "skip", reason: `already ${lease.status}` };
236
- }
237
- return decideStartMethod(lease, placement);
238
- }
239
- function decideSandboxHealthFailure(lease, _placement, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
240
- if (lease.status !== "ready" && lease.status !== "unhealthy") {
241
- return { action: "skip", reason: `status is ${lease.status}, health check not applicable` };
242
- }
243
- const retryCount = lease.retry_count + 1;
244
- if (retryCount > config.maxRetries) {
245
- return { action: "mark_failed", reason: `health failures exceeded max retries (${config.maxRetries})` };
246
- }
247
- const backoff = Math.min(config.backoffMaxMs, 1e3 * 2 ** Math.max(0, retryCount - 1));
248
- return { action: "wait", until: now + backoff, reason: `health failure #${retryCount}, backoff ${backoff}ms` };
249
- }
250
- function nextSandboxRetryAt(retryCount, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
251
- if (retryCount >= config.maxRetries) return null;
252
- return now + Math.min(config.backoffMaxMs, 1e3 * 2 ** Math.max(0, retryCount));
253
- }
254
- function decideStartMethod(lease, placement) {
255
- if (lease.sandbox_id && placement.canPauseAndRestartSameResource) {
256
- return { action: "resume", reason: `resume sandbox ${lease.sandbox_id}` };
257
- }
258
- if (lease.accel_snapshot_id && placement.canCreateFilesystemSnapshot) {
259
- return {
260
- action: "restore_snapshot",
261
- snapshot_id: lease.accel_snapshot_id,
262
- reason: `restore snapshot ${lease.accel_snapshot_id}`
263
- };
264
- }
265
- if (lease.accel_prepared_image_id && placement.canStartFromPreparedImage) {
266
- return {
267
- action: "start_prepared",
268
- image_id: lease.accel_prepared_image_id,
269
- reason: `start from prepared image ${lease.accel_prepared_image_id}`
270
- };
271
- }
272
- return { action: "start_fresh", reason: "no acceleration available, cold start" };
273
- }
274
- export {
275
- DEFAULT_WORKSPACE_HOST_DECISION_CONFIG,
276
- decideSandboxHealthFailure,
277
- decideSandboxStart,
278
- nextSandboxRetryAt,
279
- sandboxDriverPlacement
280
- };