@claxedo/sandbox-manager 0.9.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.
- 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/drivers/modal.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SandboxDriver, SandboxDriverEnsureInput } from "
|
|
1
|
+
import type { SandboxDriver, SandboxDriverEnsureInput } from "../contract";
|
|
2
2
|
import { type WorkspaceRuntimeControlEnv } from "../runtime-env";
|
|
3
3
|
type ModalAppLike = unknown;
|
|
4
4
|
type ModalImageLike = {
|
|
@@ -49,7 +49,7 @@ export type ModalSandboxDriverOptions = {
|
|
|
49
49
|
runtimePort?: number;
|
|
50
50
|
runtimeCommand?: string;
|
|
51
51
|
workspaceDir?: string;
|
|
52
|
-
|
|
52
|
+
nativeHarness?: string;
|
|
53
53
|
controlEnv?: WorkspaceRuntimeControlEnv;
|
|
54
54
|
env?: (input: SandboxDriverEnsureInput, host: {
|
|
55
55
|
id: string;
|
package/dist/drivers/modal.mjs
CHANGED
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
// src/runtime-env.ts
|
|
2
|
+
var WORKSPACE_RUNTIME_IDENTITY_ENV_KEYS = [
|
|
3
|
+
"WORKSPACE_RUNTIME_WORKSPACE_ID",
|
|
4
|
+
"WORKSPACE_RUNTIME_HOST_ID",
|
|
5
|
+
"WORKSPACE_RUNTIME_RELAY_WORKSPACE_IDS"
|
|
6
|
+
];
|
|
7
|
+
function workspaceRuntimeIdentityEnvConflicts(env) {
|
|
8
|
+
if (!env) return [];
|
|
9
|
+
return WORKSPACE_RUNTIME_IDENTITY_ENV_KEYS.filter((key) => env[key] !== void 0);
|
|
10
|
+
}
|
|
11
|
+
function assertWorkspaceRuntimeIdentityEnv(env) {
|
|
12
|
+
const conflicts = workspaceRuntimeIdentityEnvConflicts(env);
|
|
13
|
+
if (conflicts.length === 0) return;
|
|
14
|
+
throw new Error(
|
|
15
|
+
`sandbox env cannot set runtime identity ${conflicts.join(", ")}: the driver's placement owns the identity its target reports and the lease records`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
var WORKSPACE_RUNTIME_PUBLIC_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
19
|
+
...WORKSPACE_RUNTIME_IDENTITY_ENV_KEYS,
|
|
20
|
+
"WORKSPACE_RUNTIME_DIRECTORY",
|
|
21
|
+
"WORKSPACE_RUNTIME_PORT",
|
|
22
|
+
"WORKSPACE_RUNTIME_HOST",
|
|
23
|
+
"WORKSPACE_RUNTIME_SOURCE_KIND",
|
|
24
|
+
"WORKSPACE_RUNTIME_GIT_REPO_URL",
|
|
25
|
+
"WORKSPACE_RUNTIME_GIT_BRANCH",
|
|
26
|
+
"WORKSPACE_RUNTIME_NATIVE_HARNESS",
|
|
27
|
+
"WORKSPACE_RUNTIME_RELAY_JWKS_URL",
|
|
28
|
+
"WORKSPACE_RUNTIME_MANAGEMENT_JWKS_URL",
|
|
29
|
+
"WORKSPACE_RUNTIME_SESSION_AUTHORITY_URL"
|
|
30
|
+
]);
|
|
2
31
|
function workspaceRuntimeBootEnv(input) {
|
|
32
|
+
assertWorkspaceRuntimeIdentityEnv(input.env);
|
|
3
33
|
const env = {
|
|
4
34
|
...workspaceRuntimeTargetEnv(input),
|
|
5
35
|
...workspaceRuntimeSourceEnv(input),
|
|
6
36
|
...input.env
|
|
7
37
|
};
|
|
8
|
-
if (input.
|
|
38
|
+
if (input.nativeHarness) env.WORKSPACE_RUNTIME_NATIVE_HARNESS = input.nativeHarness;
|
|
9
39
|
if (input.controlEnv?.relayJwksUrl) env.WORKSPACE_RUNTIME_RELAY_JWKS_URL = input.controlEnv.relayJwksUrl;
|
|
10
40
|
if (input.controlEnv?.relayVerifyPem) env.WORKSPACE_RUNTIME_RELAY_HOST_VERIFY_PEM = input.controlEnv.relayVerifyPem;
|
|
11
41
|
if (input.controlEnv?.managementJwksUrl) env.WORKSPACE_RUNTIME_MANAGEMENT_JWKS_URL = input.controlEnv.managementJwksUrl;
|
|
@@ -58,61 +88,47 @@ function buildIdSuffix(buildId, env) {
|
|
|
58
88
|
const id = (buildId ?? env.CLAXEDO_SANDBOX_BUILD_ID)?.trim();
|
|
59
89
|
return id ? `-${snapshotVersion(id)}` : "";
|
|
60
90
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return `claxedo-workspace-runtime-${snapshotVersion(version)}${buildIdSuffix(buildId, env)}-v${SNAPSHOT_SCHEMA_VERSION}`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// ../claxedo-helpers/dist/guards.mjs
|
|
69
|
-
function isRecord(value) {
|
|
70
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
71
|
-
}
|
|
72
|
-
function asRecord(value) {
|
|
73
|
-
return isRecord(value) ? value : void 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// src/json.ts
|
|
77
|
-
function num(input) {
|
|
78
|
-
return typeof input === "number" ? input : void 0;
|
|
91
|
+
var AGENT_PLUGINS_TAG = "-agent-plugins";
|
|
92
|
+
function defaultSandboxImage(version = workspaceRuntimeVersion(), buildId, env = process.env, options = {}) {
|
|
93
|
+
const feature = options.agentPlugins ? AGENT_PLUGINS_TAG : "";
|
|
94
|
+
return `${sandboxImageRepository(env)}:workspace-runtime-${snapshotVersion(version)}${buildIdSuffix(buildId, env)}${feature}-v${SNAPSHOT_SCHEMA_VERSION}`;
|
|
79
95
|
}
|
|
80
96
|
|
|
81
97
|
// src/image.ts
|
|
82
98
|
var SANDBOX_IMAGE_REPOSITORY = sandboxImageRepository();
|
|
83
99
|
var SANDBOX_IMAGE = process.env.CLAXEDO_SANDBOX_IMAGE || defaultSandboxImage();
|
|
84
|
-
var SNAPSHOT_NAME = process.env.CLAXEDO_SNAPSHOT_NAME || defaultSnapshotName();
|
|
85
100
|
|
|
86
|
-
// src/
|
|
87
|
-
var
|
|
88
|
-
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
"
|
|
103
|
-
"
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
// src/driver-billing.ts
|
|
102
|
+
var HOUR_SECONDS = 3600;
|
|
103
|
+
var boatBilling = {
|
|
104
|
+
source: { url: "https://docs.boat.dev/pricing", readOn: "2026-10-12" },
|
|
105
|
+
meter: "Boat bills machine time per second while a sandbox runs, at an hourly rate per size; a stopped sandbox costs nothing.",
|
|
106
|
+
rates: {
|
|
107
|
+
small: { size: "small", vcpu: 2, memoryGb: 4, usdPerHour: 0.018 },
|
|
108
|
+
default: { size: "default", vcpu: 4, memoryGb: 8, usdPerHour: 0.036 },
|
|
109
|
+
large: { size: "large", vcpu: 8, memoryGb: 16, usdPerHour: 0.072 }
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY = 25e-7;
|
|
113
|
+
var CLOUDFLARE_USD_PER_GB_SECOND_DISK = 7e-8;
|
|
114
|
+
var CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE = 2e-5;
|
|
115
|
+
var CLOUDFLARE_STANDARD_1 = { size: "standard-1", vcpu: 0.5, memoryGb: 4, diskGb: 8 };
|
|
116
|
+
var cloudflareBilling = {
|
|
117
|
+
source: { url: "https://developers.cloudflare.com/containers/pricing/", readOn: "2026-10-12" },
|
|
118
|
+
meter: "Cloudflare bills a container for every 10 ms it runs: memory at $0.0000025 per GiB-second and disk at $0.00000007 per GB-second for the whole run, plus CPU at $0.00002 per vCPU-second of active use.",
|
|
119
|
+
rates: {
|
|
120
|
+
default: {
|
|
121
|
+
size: CLOUDFLARE_STANDARD_1.size,
|
|
122
|
+
vcpu: CLOUDFLARE_STANDARD_1.vcpu,
|
|
123
|
+
memoryGb: CLOUDFLARE_STANDARD_1.memoryGb,
|
|
124
|
+
usdPerHour: (CLOUDFLARE_STANDARD_1.memoryGb * CLOUDFLARE_USD_PER_GIB_SECOND_MEMORY + CLOUDFLARE_STANDARD_1.diskGb * CLOUDFLARE_USD_PER_GB_SECOND_DISK) * HOUR_SECONDS
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
excludes: `active CPU, billed at $${CLOUDFLARE_USD_PER_VCPU_SECOND_ACTIVE} per vCPU-second and not measured by Claxedo, and the monthly allowance a Workers Paid plan includes`
|
|
128
|
+
};
|
|
111
129
|
|
|
112
130
|
// ../sandbox-contract/dist/index.mjs
|
|
113
131
|
var sandboxDriverCredentialFields = {
|
|
114
|
-
exe: [{ key: "api_token", label: "API Token", secret: true }],
|
|
115
|
-
daytona: [{ key: "api_key", label: "API Key", secret: true }],
|
|
116
132
|
modal: [
|
|
117
133
|
{ key: "token_id", label: "Token ID", secret: true },
|
|
118
134
|
{ key: "token_secret", label: "Token Secret", secret: true }
|
|
@@ -126,68 +142,26 @@ var sandboxDriverCredentialFields = {
|
|
|
126
142
|
{ key: "api_token", label: "API Token", secret: true },
|
|
127
143
|
{ key: "worker_url", label: "Worker URL" }
|
|
128
144
|
],
|
|
129
|
-
|
|
145
|
+
boat: [{ key: "api_key", label: "API Key", secret: true }],
|
|
130
146
|
docker: [{ key: "image", label: "Image" }]
|
|
131
147
|
};
|
|
132
148
|
var sandboxDriverLabels = {
|
|
133
|
-
exe: "exe.dev",
|
|
134
|
-
daytona: "Daytona",
|
|
135
149
|
modal: "Modal",
|
|
136
150
|
vercel: "Vercel",
|
|
137
151
|
cloudflare: "Cloudflare",
|
|
138
|
-
|
|
152
|
+
boat: "Boat",
|
|
139
153
|
docker: "Docker"
|
|
140
154
|
};
|
|
141
155
|
|
|
142
156
|
// src/driver-catalog.ts
|
|
143
157
|
var sandboxDriverCatalog = {
|
|
144
|
-
exe: {
|
|
145
|
-
id: "exe",
|
|
146
|
-
label: sandboxDriverLabels.exe,
|
|
147
|
-
credentialFields: sandboxDriverCredentialFields.exe,
|
|
148
|
-
metadata: {
|
|
149
|
-
driverRunsIn: ["worker", "node"],
|
|
150
|
-
hostStopBehavior: "not-supported",
|
|
151
|
-
hostResumeBehavior: "same-host",
|
|
152
|
-
targetAccess: "relay",
|
|
153
|
-
secretBrokering: "none",
|
|
154
|
-
egressControl: "none",
|
|
155
|
-
persistence: {
|
|
156
|
-
resume: "same-sandbox",
|
|
157
|
-
capture: "none",
|
|
158
|
-
clone: true,
|
|
159
|
-
captureSource: "not-applicable",
|
|
160
|
-
retention: "provider-managed",
|
|
161
|
-
restoreMount: "same-resource"
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
},
|
|
165
|
-
daytona: {
|
|
166
|
-
id: "daytona",
|
|
167
|
-
label: sandboxDriverLabels.daytona,
|
|
168
|
-
credentialFields: sandboxDriverCredentialFields.daytona,
|
|
169
|
-
metadata: {
|
|
170
|
-
driverRunsIn: ["worker", "node"],
|
|
171
|
-
hostStopBehavior: "suspends-host",
|
|
172
|
-
hostResumeBehavior: "same-host",
|
|
173
|
-
targetAccess: "relay",
|
|
174
|
-
secretBrokering: "native",
|
|
175
|
-
// The driver translates names to domainAllowList, or addresses to networkAllowList.
|
|
176
|
-
egressControl: "hosts-and-cidrs",
|
|
177
|
-
persistence: {
|
|
178
|
-
resume: "same-sandbox",
|
|
179
|
-
capture: "filesystem",
|
|
180
|
-
clone: false,
|
|
181
|
-
captureSource: "preserved",
|
|
182
|
-
retention: "provider-managed",
|
|
183
|
-
restoreMount: "new-resource"
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
158
|
modal: {
|
|
188
159
|
id: "modal",
|
|
189
160
|
label: sandboxDriverLabels.modal,
|
|
190
161
|
credentialFields: sandboxDriverCredentialFields.modal,
|
|
162
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
163
|
+
runtimeEnv: "callback",
|
|
164
|
+
preparedImage: true,
|
|
191
165
|
metadata: {
|
|
192
166
|
driverRunsIn: ["node"],
|
|
193
167
|
hostStopBehavior: "terminates-host",
|
|
@@ -210,6 +184,9 @@ var sandboxDriverCatalog = {
|
|
|
210
184
|
id: "vercel",
|
|
211
185
|
label: sandboxDriverLabels.vercel,
|
|
212
186
|
credentialFields: sandboxDriverCredentialFields.vercel,
|
|
187
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
188
|
+
runtimeEnv: "callback",
|
|
189
|
+
preparedImage: false,
|
|
213
190
|
metadata: {
|
|
214
191
|
driverRunsIn: ["node"],
|
|
215
192
|
hostStopBehavior: "terminates-host",
|
|
@@ -232,30 +209,40 @@ var sandboxDriverCatalog = {
|
|
|
232
209
|
id: "cloudflare",
|
|
233
210
|
label: sandboxDriverLabels.cloudflare,
|
|
234
211
|
credentialFields: sandboxDriverCredentialFields.cloudflare,
|
|
212
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
213
|
+
runtimeEnv: "callback",
|
|
214
|
+
preparedImage: false,
|
|
215
|
+
billing: cloudflareBilling,
|
|
235
216
|
metadata: {
|
|
236
217
|
driverRunsIn: ["worker"],
|
|
237
|
-
hostStopBehavior: "
|
|
218
|
+
hostStopBehavior: "terminates-host",
|
|
238
219
|
hostResumeBehavior: "same-host",
|
|
220
|
+
hostWatchesIdle: true,
|
|
239
221
|
targetAccess: "relay",
|
|
240
222
|
secretBrokering: "native",
|
|
241
223
|
// Credential handlers do not restrict unrelated destinations.
|
|
242
224
|
egressControl: "none",
|
|
225
|
+
// A container snapshot holds the whole root filesystem; the platform keeps it 30 days past its last restore and offers no deletion.
|
|
243
226
|
persistence: {
|
|
244
227
|
resume: "replacement-restore",
|
|
245
|
-
capture: "
|
|
228
|
+
capture: "filesystem",
|
|
246
229
|
clone: false,
|
|
247
230
|
captureSource: "preserved",
|
|
248
231
|
retention: "provider-managed",
|
|
249
|
-
restoreMount: "
|
|
232
|
+
restoreMount: "new-resource"
|
|
250
233
|
}
|
|
251
234
|
}
|
|
252
235
|
},
|
|
253
|
-
|
|
254
|
-
id: "
|
|
255
|
-
label: sandboxDriverLabels.
|
|
256
|
-
credentialFields: sandboxDriverCredentialFields.
|
|
236
|
+
boat: {
|
|
237
|
+
id: "boat",
|
|
238
|
+
label: sandboxDriverLabels.boat,
|
|
239
|
+
credentialFields: sandboxDriverCredentialFields.boat,
|
|
240
|
+
runtimeNetwork: { controlPlane: "direct", relay: "configured" },
|
|
241
|
+
runtimeEnv: "callback",
|
|
242
|
+
preparedImage: true,
|
|
243
|
+
billing: boatBilling,
|
|
257
244
|
metadata: {
|
|
258
|
-
driverRunsIn: ["node"],
|
|
245
|
+
driverRunsIn: ["worker", "node"],
|
|
259
246
|
hostStopBehavior: "suspends-host",
|
|
260
247
|
hostResumeBehavior: "same-host",
|
|
261
248
|
targetAccess: "relay",
|
|
@@ -268,13 +255,17 @@ var sandboxDriverCatalog = {
|
|
|
268
255
|
captureSource: "not-applicable",
|
|
269
256
|
retention: "provider-managed",
|
|
270
257
|
restoreMount: "same-resource"
|
|
271
|
-
}
|
|
258
|
+
},
|
|
259
|
+
machineClasses: ["small", "default", "large"]
|
|
272
260
|
}
|
|
273
261
|
},
|
|
274
262
|
docker: {
|
|
275
263
|
id: "docker",
|
|
276
264
|
label: sandboxDriverLabels.docker,
|
|
277
265
|
credentialFields: sandboxDriverCredentialFields.docker,
|
|
266
|
+
runtimeNetwork: { controlPlane: "docker-host", relay: "configured" },
|
|
267
|
+
runtimeEnv: "callback",
|
|
268
|
+
preparedImage: true,
|
|
278
269
|
metadata: {
|
|
279
270
|
driverRunsIn: ["local"],
|
|
280
271
|
hostStopBehavior: "terminates-host",
|
|
@@ -294,6 +285,19 @@ var sandboxDriverCatalog = {
|
|
|
294
285
|
}
|
|
295
286
|
};
|
|
296
287
|
|
|
288
|
+
// ../claxedo-helpers/dist/guards.mjs
|
|
289
|
+
function isRecord(value) {
|
|
290
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
291
|
+
}
|
|
292
|
+
function asRecord(value) {
|
|
293
|
+
return isRecord(value) ? value : void 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/json.ts
|
|
297
|
+
function num(input) {
|
|
298
|
+
return typeof input === "number" ? input : void 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
297
301
|
// src/drivers/transient-error.ts
|
|
298
302
|
function textOf(input) {
|
|
299
303
|
return typeof input === "string" ? input : "";
|
|
@@ -302,15 +306,18 @@ function driverErrorSignals(err) {
|
|
|
302
306
|
const shaped = isRecord(err) ? err : {};
|
|
303
307
|
const nested = isRecord(shaped.response) ? shaped.response : {};
|
|
304
308
|
return {
|
|
305
|
-
|
|
309
|
+
// `response.status` is the axios shape; `statusCode` is what SDK-native
|
|
310
|
+
// error classes expose instead.
|
|
311
|
+
status: num(nested.status) ?? num(shaped.status) ?? num(shaped.statusCode),
|
|
306
312
|
text: `${textOf(shaped.code)} ${textOf(shaped.name)} ${textOf(shaped.message)}`.toLowerCase()
|
|
307
313
|
};
|
|
308
314
|
}
|
|
309
315
|
function isTransientDriverError(err, markers) {
|
|
310
|
-
const { status, text
|
|
316
|
+
const { status, text } = driverErrorSignals(err);
|
|
311
317
|
if (status !== void 0 && status >= 500) return true;
|
|
312
|
-
return markers.some((marker) =>
|
|
318
|
+
return markers.some((marker) => text.includes(marker));
|
|
313
319
|
}
|
|
320
|
+
var TRANSIENT_DRIVER_RETRY_MS = 2e3;
|
|
314
321
|
|
|
315
322
|
// src/drivers/modal.ts
|
|
316
323
|
var DEFAULT_APP_NAME = "claxedo";
|
|
@@ -365,7 +372,7 @@ function createModalSandboxDriver(options) {
|
|
|
365
372
|
host: "0.0.0.0",
|
|
366
373
|
source: input.source,
|
|
367
374
|
env: input.env,
|
|
368
|
-
|
|
375
|
+
nativeHarness: options.nativeHarness,
|
|
369
376
|
controlEnv: options.controlEnv
|
|
370
377
|
});
|
|
371
378
|
}
|
|
@@ -383,10 +390,13 @@ function createModalSandboxDriver(options) {
|
|
|
383
390
|
return { blockNetwork: true };
|
|
384
391
|
}
|
|
385
392
|
async function readyTarget(input, sandbox, hostId) {
|
|
386
|
-
await sandbox.setTags(input.labels)
|
|
387
|
-
const tunnels = await sandbox.tunnels(tunnelTimeoutMs).catch(() =>
|
|
393
|
+
await sandbox.setTags(input.labels);
|
|
394
|
+
const tunnels = await sandbox.tunnels(tunnelTimeoutMs).catch((error) => {
|
|
395
|
+
if (error instanceof Error && error.name === "SandboxTimeoutError") return void 0;
|
|
396
|
+
throw error;
|
|
397
|
+
});
|
|
388
398
|
const tunnel = tunnels?.[runtimePort];
|
|
389
|
-
if (!tunnel?.url) return { provisioning: true, retryAfterMs:
|
|
399
|
+
if (!tunnel?.url) return { provisioning: true, retryAfterMs: 0 };
|
|
390
400
|
return {
|
|
391
401
|
workspaceId: input.workspaceId,
|
|
392
402
|
sandboxId: sandbox.sandboxId,
|
|
@@ -427,7 +437,7 @@ function createModalSandboxDriver(options) {
|
|
|
427
437
|
if (transientDriverError(err)) return void 0;
|
|
428
438
|
throw err;
|
|
429
439
|
});
|
|
430
|
-
if (!sandbox) return { provisioning: true, retryAfterMs:
|
|
440
|
+
if (!sandbox) return { provisioning: true, retryAfterMs: TRANSIENT_DRIVER_RETRY_MS };
|
|
431
441
|
return readyTarget(input, sandbox, hostId);
|
|
432
442
|
}
|
|
433
443
|
async function sandboxById(target) {
|
|
@@ -9,3 +9,5 @@ export declare function driverErrorSignals(err: unknown): {
|
|
|
9
9
|
* seen its own SDK produce.
|
|
10
10
|
*/
|
|
11
11
|
export declare function isTransientDriverError(err: unknown, markers: readonly string[]): boolean;
|
|
12
|
+
/** How long a driver waits before asking a provider again after a failure `isTransientDriverError` admits, so a provider in trouble is not asked at once. */
|
|
13
|
+
export declare const TRANSIENT_DRIVER_RETRY_MS = 2000;
|
package/dist/drivers/vercel.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { NetworkPolicy } from "@vercel/sandbox";
|
|
2
|
-
import { type
|
|
2
|
+
import { type SandboxDriver, type SandboxDriverEnsureInput } from "../contract";
|
|
3
|
+
import { type SandboxBrokeredSecret } from "../egress-policy";
|
|
3
4
|
import { type WorkspaceRuntimeControlEnv } from "../runtime-env";
|
|
4
5
|
type VercelSnapshotLike = {
|
|
5
6
|
snapshotId: string;
|
|
@@ -80,7 +81,7 @@ export type VercelSandboxDriverOptions = {
|
|
|
80
81
|
runtimePort?: number;
|
|
81
82
|
runtimeCommand?: string;
|
|
82
83
|
workspaceDir?: string;
|
|
83
|
-
|
|
84
|
+
nativeHarness?: string;
|
|
84
85
|
controlEnv?: WorkspaceRuntimeControlEnv;
|
|
85
86
|
env?: (input: SandboxDriverEnsureInput, host: {
|
|
86
87
|
id: string;
|