@claxedo/sandbox-manager 0.9.0 → 0.10.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/README.md +233 -26
- package/dist/checkpoint-manager.d.ts +29 -4
- package/dist/checkpoint-manager.mjs +133 -24
- package/dist/command.d.ts +9 -2
- package/dist/command.mjs +8 -8
- package/dist/contract.d.ts +687 -0
- package/dist/driver-billing.d.ts +29 -0
- package/dist/driver-catalog.d.ts +42 -7
- package/dist/driver-catalog.mjs +115 -161
- package/dist/drivers/boat-client.d.ts +95 -0
- package/dist/drivers/boat-named-snapshots.d.ts +31 -0
- package/dist/drivers/boat-template.d.ts +49 -0
- package/dist/drivers/boat-template.mjs +1196 -0
- package/dist/drivers/boat.d.ts +64 -0
- package/dist/drivers/boat.mjs +990 -0
- package/dist/drivers/cloudflare.d.ts +3 -3
- package/dist/drivers/cloudflare.mjs +208 -147
- package/dist/drivers/docker.d.ts +4 -3
- package/dist/drivers/docker.mjs +154 -126
- package/dist/drivers/local-brokering.d.ts +14 -0
- package/dist/drivers/local-brokering.mjs +1029 -0
- package/dist/drivers/modal.d.ts +2 -2
- package/dist/drivers/modal.mjs +121 -111
- package/dist/drivers/transient-error.d.ts +2 -0
- package/dist/drivers/vercel.d.ts +3 -2
- package/dist/drivers/vercel.mjs +151 -115
- package/dist/egress-policy.d.ts +134 -0
- package/dist/egress-warnings.d.ts +22 -0
- package/dist/garbage-collect.d.ts +14 -0
- package/dist/hosted-network-policy.d.ts +9 -2
- package/dist/hosted-network-policy.mjs +218 -1
- package/dist/image-name.d.ts +12 -2
- package/dist/image-name.mjs +14 -5
- package/dist/image.d.ts +1 -20
- package/dist/image.mjs +11 -88
- package/dist/index.d.ts +8 -578
- package/dist/index.mjs +1379 -320
- package/dist/lease-failure.d.ts +173 -0
- package/dist/lease-lifecycle.d.ts +65 -0
- package/dist/lease-retry-wait.d.ts +8 -0
- package/dist/lease-start.d.ts +21 -0
- package/dist/lease-types.d.ts +4 -3
- package/dist/manager.d.ts +2 -0
- package/dist/runtime-env.d.ts +4 -2
- package/dist/runtime-env.mjs +37 -2
- package/dist/runtime-snapshot.d.ts +49 -0
- package/dist/runtime-version.d.ts +9 -0
- package/dist/runtime-version.mjs +2 -0
- package/dist/service-url-exposure.d.ts +0 -1
- package/dist/service-url-exposure.mjs +0 -9
- package/dist/start-fresh.d.ts +17 -0
- package/dist/start-telemetry.d.ts +37 -0
- package/dist/stores/memory.d.ts +1 -1
- package/dist/stores/memory.mjs +63 -52
- package/package.json +26 -42
- package/dist/daytona-allow-list.d.ts +0 -16
- package/dist/daytona-allow-list.mjs +0 -11
- package/dist/drivers/box.d.ts +0 -52
- package/dist/drivers/box.mjs +0 -574
- package/dist/drivers/daytona.d.ts +0 -163
- package/dist/drivers/daytona.mjs +0 -683
- package/dist/drivers/exe.d.ts +0 -26
- package/dist/drivers/exe.mjs +0 -492
- package/dist/drivers/fetch-bridge.d.ts +0 -10
- package/dist/drivers/fetch-bridge.mjs +0 -126
- package/dist/lease-policy.d.ts +0 -52
- package/dist/lease-policy.mjs +0 -290
package/dist/lease-policy.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { SandboxLeaseRow } from "./lease-types";
|
|
2
|
-
import type { SandboxDriverID } from "@claxedo/sandbox-contract";
|
|
3
|
-
export type SandboxDecision = {
|
|
4
|
-
action: "skip";
|
|
5
|
-
reason: string;
|
|
6
|
-
} | {
|
|
7
|
-
action: "wait";
|
|
8
|
-
until: number;
|
|
9
|
-
reason: string;
|
|
10
|
-
} | {
|
|
11
|
-
action: "resume";
|
|
12
|
-
reason: string;
|
|
13
|
-
} | {
|
|
14
|
-
action: "restore_snapshot";
|
|
15
|
-
snapshot_id: string;
|
|
16
|
-
reason: string;
|
|
17
|
-
} | {
|
|
18
|
-
action: "start_prepared";
|
|
19
|
-
image_id: string;
|
|
20
|
-
reason: string;
|
|
21
|
-
} | {
|
|
22
|
-
action: "start_fresh";
|
|
23
|
-
reason: string;
|
|
24
|
-
} | {
|
|
25
|
-
action: "stop_idle";
|
|
26
|
-
reason: string;
|
|
27
|
-
} | {
|
|
28
|
-
action: "mark_failed";
|
|
29
|
-
reason: string;
|
|
30
|
-
};
|
|
31
|
-
export type SandboxDecisionConfig = {
|
|
32
|
-
maxRetries: number;
|
|
33
|
-
idleMs: number;
|
|
34
|
-
backoffMaxMs: number;
|
|
35
|
-
healthTimeoutMs: number;
|
|
36
|
-
};
|
|
37
|
-
export type SandboxDriverPlacement = {
|
|
38
|
-
canPauseAndRestartSameResource: boolean;
|
|
39
|
-
canCreateFilesystemSnapshot: boolean;
|
|
40
|
-
canStartFromPreparedImage: boolean;
|
|
41
|
-
canStopExplicitly: boolean;
|
|
42
|
-
hasHealthProbe: boolean;
|
|
43
|
-
};
|
|
44
|
-
export declare const DEFAULT_WORKSPACE_HOST_DECISION_CONFIG: SandboxDecisionConfig;
|
|
45
|
-
export declare function sandboxDriverPlacement(driver: SandboxDriverID): SandboxDriverPlacement;
|
|
46
|
-
export declare function decideSandboxStart(lease: SandboxLeaseRow, placement: SandboxDriverPlacement, now: number, config?: SandboxDecisionConfig): SandboxDecision;
|
|
47
|
-
/**
|
|
48
|
-
* Health-failure policy is placement-independent: retry budget and backoff are
|
|
49
|
-
* the same question for every driver, so this deliberately takes no placement.
|
|
50
|
-
*/
|
|
51
|
-
export declare function decideSandboxHealthFailure(lease: SandboxLeaseRow, now: number, config?: SandboxDecisionConfig): SandboxDecision;
|
|
52
|
-
export declare function nextSandboxRetryAt(retryCount: number, now: number, config?: SandboxDecisionConfig): number | null;
|
package/dist/lease-policy.mjs
DELETED
|
@@ -1,290 +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
|
-
// ../sandbox-contract/dist/index.mjs
|
|
28
|
-
var sandboxDriverCredentialFields = {
|
|
29
|
-
exe: [{ key: "api_token", label: "API Token", secret: true }],
|
|
30
|
-
daytona: [{ key: "api_key", label: "API Key", secret: true }],
|
|
31
|
-
modal: [
|
|
32
|
-
{ key: "token_id", label: "Token ID", secret: true },
|
|
33
|
-
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
34
|
-
],
|
|
35
|
-
vercel: [
|
|
36
|
-
{ key: "access_token", label: "Access Token", secret: true },
|
|
37
|
-
{ key: "team_id", label: "Team ID" },
|
|
38
|
-
{ key: "project_id", label: "Project ID" }
|
|
39
|
-
],
|
|
40
|
-
cloudflare: [
|
|
41
|
-
{ key: "api_token", label: "API Token", secret: true },
|
|
42
|
-
{ key: "worker_url", label: "Worker URL" }
|
|
43
|
-
],
|
|
44
|
-
box: [{ key: "api_key", label: "API Key", secret: true }],
|
|
45
|
-
docker: [{ key: "image", label: "Image" }]
|
|
46
|
-
};
|
|
47
|
-
var sandboxDriverLabels = {
|
|
48
|
-
exe: "exe.dev",
|
|
49
|
-
daytona: "Daytona",
|
|
50
|
-
modal: "Modal",
|
|
51
|
-
vercel: "Vercel",
|
|
52
|
-
cloudflare: "Cloudflare",
|
|
53
|
-
box: "Box",
|
|
54
|
-
docker: "Docker"
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// src/driver-catalog.ts
|
|
58
|
-
var sandboxDriverCatalog = {
|
|
59
|
-
exe: {
|
|
60
|
-
id: "exe",
|
|
61
|
-
label: sandboxDriverLabels.exe,
|
|
62
|
-
credentialFields: sandboxDriverCredentialFields.exe,
|
|
63
|
-
metadata: {
|
|
64
|
-
driverRunsIn: ["worker", "node"],
|
|
65
|
-
hostStopBehavior: "not-supported",
|
|
66
|
-
hostResumeBehavior: "same-host",
|
|
67
|
-
targetAccess: "relay",
|
|
68
|
-
secretBrokering: "none",
|
|
69
|
-
egressControl: "none",
|
|
70
|
-
persistence: {
|
|
71
|
-
resume: "same-sandbox",
|
|
72
|
-
capture: "none",
|
|
73
|
-
clone: true,
|
|
74
|
-
captureSource: "not-applicable",
|
|
75
|
-
retention: "provider-managed",
|
|
76
|
-
restoreMount: "same-resource"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
daytona: {
|
|
81
|
-
id: "daytona",
|
|
82
|
-
label: sandboxDriverLabels.daytona,
|
|
83
|
-
credentialFields: sandboxDriverCredentialFields.daytona,
|
|
84
|
-
metadata: {
|
|
85
|
-
driverRunsIn: ["worker", "node"],
|
|
86
|
-
hostStopBehavior: "suspends-host",
|
|
87
|
-
hostResumeBehavior: "same-host",
|
|
88
|
-
targetAccess: "relay",
|
|
89
|
-
secretBrokering: "native",
|
|
90
|
-
// The driver translates names to domainAllowList, or addresses to networkAllowList.
|
|
91
|
-
egressControl: "hosts-and-cidrs",
|
|
92
|
-
persistence: {
|
|
93
|
-
resume: "same-sandbox",
|
|
94
|
-
capture: "filesystem",
|
|
95
|
-
clone: false,
|
|
96
|
-
captureSource: "preserved",
|
|
97
|
-
retention: "provider-managed",
|
|
98
|
-
restoreMount: "new-resource"
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
modal: {
|
|
103
|
-
id: "modal",
|
|
104
|
-
label: sandboxDriverLabels.modal,
|
|
105
|
-
credentialFields: sandboxDriverCredentialFields.modal,
|
|
106
|
-
metadata: {
|
|
107
|
-
driverRunsIn: ["node"],
|
|
108
|
-
hostStopBehavior: "terminates-host",
|
|
109
|
-
hostResumeBehavior: "replacement-host",
|
|
110
|
-
targetAccess: "relay",
|
|
111
|
-
secretBrokering: "none",
|
|
112
|
-
// The driver does not install Modal's domain allowlist or alpha sidecar.
|
|
113
|
-
egressControl: "none",
|
|
114
|
-
persistence: {
|
|
115
|
-
resume: "replacement-restore",
|
|
116
|
-
capture: "filesystem",
|
|
117
|
-
clone: false,
|
|
118
|
-
captureSource: "preserved",
|
|
119
|
-
retention: "provider-managed",
|
|
120
|
-
restoreMount: "new-resource"
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
vercel: {
|
|
125
|
-
id: "vercel",
|
|
126
|
-
label: sandboxDriverLabels.vercel,
|
|
127
|
-
credentialFields: sandboxDriverCredentialFields.vercel,
|
|
128
|
-
metadata: {
|
|
129
|
-
driverRunsIn: ["node"],
|
|
130
|
-
hostStopBehavior: "terminates-host",
|
|
131
|
-
hostResumeBehavior: "replacement-host",
|
|
132
|
-
targetAccess: "relay",
|
|
133
|
-
secretBrokering: "native",
|
|
134
|
-
// The driver translates hosts only; the SDK's subnet rules are not wired to net.cidrs.
|
|
135
|
-
egressControl: "hosts",
|
|
136
|
-
persistence: {
|
|
137
|
-
resume: "replacement-restore",
|
|
138
|
-
capture: "filesystem",
|
|
139
|
-
clone: false,
|
|
140
|
-
captureSource: "stopped",
|
|
141
|
-
retention: "explicit",
|
|
142
|
-
restoreMount: "new-resource"
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
cloudflare: {
|
|
147
|
-
id: "cloudflare",
|
|
148
|
-
label: sandboxDriverLabels.cloudflare,
|
|
149
|
-
credentialFields: sandboxDriverCredentialFields.cloudflare,
|
|
150
|
-
metadata: {
|
|
151
|
-
driverRunsIn: ["worker"],
|
|
152
|
-
hostStopBehavior: "not-supported",
|
|
153
|
-
hostResumeBehavior: "same-host",
|
|
154
|
-
targetAccess: "relay",
|
|
155
|
-
secretBrokering: "native",
|
|
156
|
-
// Credential handlers do not restrict unrelated destinations.
|
|
157
|
-
egressControl: "none",
|
|
158
|
-
persistence: {
|
|
159
|
-
resume: "replacement-restore",
|
|
160
|
-
capture: "directories",
|
|
161
|
-
clone: false,
|
|
162
|
-
captureSource: "preserved",
|
|
163
|
-
retention: "provider-managed",
|
|
164
|
-
restoreMount: "copy-on-write"
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
box: {
|
|
169
|
-
id: "box",
|
|
170
|
-
label: sandboxDriverLabels.box,
|
|
171
|
-
credentialFields: sandboxDriverCredentialFields.box,
|
|
172
|
-
metadata: {
|
|
173
|
-
driverRunsIn: ["node"],
|
|
174
|
-
hostStopBehavior: "suspends-host",
|
|
175
|
-
hostResumeBehavior: "same-host",
|
|
176
|
-
targetAccess: "relay",
|
|
177
|
-
secretBrokering: "none",
|
|
178
|
-
egressControl: "none",
|
|
179
|
-
persistence: {
|
|
180
|
-
resume: "same-sandbox",
|
|
181
|
-
capture: "none",
|
|
182
|
-
clone: false,
|
|
183
|
-
captureSource: "not-applicable",
|
|
184
|
-
retention: "provider-managed",
|
|
185
|
-
restoreMount: "same-resource"
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
},
|
|
189
|
-
docker: {
|
|
190
|
-
id: "docker",
|
|
191
|
-
label: sandboxDriverLabels.docker,
|
|
192
|
-
credentialFields: sandboxDriverCredentialFields.docker,
|
|
193
|
-
metadata: {
|
|
194
|
-
driverRunsIn: ["local"],
|
|
195
|
-
hostStopBehavior: "terminates-host",
|
|
196
|
-
hostResumeBehavior: "same-host",
|
|
197
|
-
targetAccess: "loopback",
|
|
198
|
-
secretBrokering: "none",
|
|
199
|
-
egressControl: "none",
|
|
200
|
-
persistence: {
|
|
201
|
-
resume: "replacement-restore",
|
|
202
|
-
capture: "same-resource",
|
|
203
|
-
clone: false,
|
|
204
|
-
captureSource: "preserved",
|
|
205
|
-
retention: "provider-managed",
|
|
206
|
-
restoreMount: "same-resource"
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// src/lease-policy.ts
|
|
213
|
-
var DEFAULT_WORKSPACE_HOST_DECISION_CONFIG = {
|
|
214
|
-
maxRetries: 8,
|
|
215
|
-
idleMs: 10 * 60 * 1e3,
|
|
216
|
-
backoffMaxMs: 3e4,
|
|
217
|
-
healthTimeoutMs: 6e4
|
|
218
|
-
};
|
|
219
|
-
function sandboxDriverPlacement(driver) {
|
|
220
|
-
const metadata = sandboxDriverCatalog[driver].metadata;
|
|
221
|
-
return {
|
|
222
|
-
canPauseAndRestartSameResource: metadata.persistence.resume === "same-sandbox",
|
|
223
|
-
canCreateFilesystemSnapshot: metadata.persistence.capture === "filesystem" || metadata.persistence.capture === "directories",
|
|
224
|
-
canStartFromPreparedImage: driver === "exe" || driver === "daytona" || driver === "modal" || driver === "box" || driver === "docker",
|
|
225
|
-
canStopExplicitly: metadata.hostStopBehavior !== "not-supported",
|
|
226
|
-
hasHealthProbe: true
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
function decideSandboxStart(lease, placement, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
|
|
230
|
-
if (lease.status === "ready") {
|
|
231
|
-
return { action: "skip", reason: "already ready" };
|
|
232
|
-
}
|
|
233
|
-
if (lease.status === "failed") {
|
|
234
|
-
return { action: "mark_failed", reason: `terminal failure: ${lease.last_error ?? "unknown"}` };
|
|
235
|
-
}
|
|
236
|
-
if (lease.status === "backoff") {
|
|
237
|
-
if (lease.retry_count >= config.maxRetries) {
|
|
238
|
-
return { action: "mark_failed", reason: `exceeded max retries (${config.maxRetries})` };
|
|
239
|
-
}
|
|
240
|
-
if (lease.next_retry_at && now < lease.next_retry_at) {
|
|
241
|
-
return { action: "wait", until: lease.next_retry_at, reason: "backoff timer not elapsed" };
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (lease.status === "acquiring" || lease.status === "starting") {
|
|
245
|
-
return { action: "skip", reason: `already ${lease.status}` };
|
|
246
|
-
}
|
|
247
|
-
return decideStartMethod(lease, placement);
|
|
248
|
-
}
|
|
249
|
-
function decideSandboxHealthFailure(lease, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
|
|
250
|
-
if (lease.status !== "ready" && lease.status !== "unhealthy") {
|
|
251
|
-
return { action: "skip", reason: `status is ${lease.status}, health check not applicable` };
|
|
252
|
-
}
|
|
253
|
-
const retryCount = lease.retry_count + 1;
|
|
254
|
-
if (retryCount > config.maxRetries) {
|
|
255
|
-
return { action: "mark_failed", reason: `health failures exceeded max retries (${config.maxRetries})` };
|
|
256
|
-
}
|
|
257
|
-
const backoff = Math.min(config.backoffMaxMs, 1e3 * 2 ** Math.max(0, retryCount - 1));
|
|
258
|
-
return { action: "wait", until: now + backoff, reason: `health failure #${retryCount}, backoff ${backoff}ms` };
|
|
259
|
-
}
|
|
260
|
-
function nextSandboxRetryAt(retryCount, now, config = DEFAULT_WORKSPACE_HOST_DECISION_CONFIG) {
|
|
261
|
-
if (retryCount >= config.maxRetries) return null;
|
|
262
|
-
return now + Math.min(config.backoffMaxMs, 1e3 * 2 ** Math.max(0, retryCount));
|
|
263
|
-
}
|
|
264
|
-
function decideStartMethod(lease, placement) {
|
|
265
|
-
if (lease.sandbox_id && placement.canPauseAndRestartSameResource) {
|
|
266
|
-
return { action: "resume", reason: `resume sandbox ${lease.sandbox_id}` };
|
|
267
|
-
}
|
|
268
|
-
if (lease.accel_snapshot_id && placement.canCreateFilesystemSnapshot) {
|
|
269
|
-
return {
|
|
270
|
-
action: "restore_snapshot",
|
|
271
|
-
snapshot_id: lease.accel_snapshot_id,
|
|
272
|
-
reason: `restore snapshot ${lease.accel_snapshot_id}`
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
if (lease.accel_prepared_image_id && placement.canStartFromPreparedImage) {
|
|
276
|
-
return {
|
|
277
|
-
action: "start_prepared",
|
|
278
|
-
image_id: lease.accel_prepared_image_id,
|
|
279
|
-
reason: `start from prepared image ${lease.accel_prepared_image_id}`
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
return { action: "start_fresh", reason: "no acceleration available, cold start" };
|
|
283
|
-
}
|
|
284
|
-
export {
|
|
285
|
-
DEFAULT_WORKSPACE_HOST_DECISION_CONFIG,
|
|
286
|
-
decideSandboxHealthFailure,
|
|
287
|
-
decideSandboxStart,
|
|
288
|
-
nextSandboxRetryAt,
|
|
289
|
-
sandboxDriverPlacement
|
|
290
|
-
};
|