@sandboxrouter/sdk 0.1.0 → 0.3.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 +271 -62
- package/dist/bench.js +4 -4
- package/dist/catalog.d.ts +232 -3
- package/dist/catalog.js +569 -14
- package/dist/check.d.ts +28 -0
- package/dist/check.js +185 -0
- package/dist/cli.js +149 -12
- package/dist/computers.d.ts +55 -13
- package/dist/computers.js +132 -6
- package/dist/conformance.d.ts +46 -0
- package/dist/conformance.js +65 -0
- package/dist/cost.d.ts +67 -0
- package/dist/cost.js +153 -0
- package/dist/gc.d.ts +29 -0
- package/dist/gc.js +54 -0
- package/dist/index.d.ts +34 -2
- package/dist/index.js +34 -2
- package/dist/leaderboard.d.ts +6 -0
- package/dist/leaderboard.js +5 -4
- package/dist/ledger.d.ts +38 -0
- package/dist/ledger.js +89 -0
- package/dist/providers/agent37.d.ts +40 -0
- package/dist/providers/agent37.js +224 -0
- package/dist/providers/agentcore.d.ts +71 -0
- package/dist/providers/agentcore.js +446 -0
- package/dist/providers/alibaba.d.ts +18 -0
- package/dist/providers/alibaba.js +106 -0
- package/dist/providers/azure.d.ts +43 -0
- package/dist/providers/azure.js +330 -0
- package/dist/providers/beam.d.ts +11 -0
- package/dist/providers/beam.js +179 -0
- package/dist/providers/blaxel.d.ts +3 -1
- package/dist/providers/blaxel.js +32 -22
- package/dist/providers/boat.d.ts +25 -0
- package/dist/providers/boat.js +263 -0
- package/dist/providers/cloudflare.d.ts +30 -0
- package/dist/providers/cloudflare.js +152 -0
- package/dist/providers/codesandbox.d.ts +59 -0
- package/dist/providers/codesandbox.js +287 -0
- package/dist/providers/daytona.d.ts +25 -4
- package/dist/providers/daytona.js +449 -28
- package/dist/providers/dedalus.d.ts +12 -0
- package/dist/providers/dedalus.js +244 -0
- package/dist/providers/deno.d.ts +50 -0
- package/dist/providers/deno.js +170 -0
- package/dist/providers/docker.d.ts +17 -0
- package/dist/providers/docker.js +154 -0
- package/dist/providers/e2b.d.ts +70 -3
- package/dist/providers/e2b.js +376 -8
- package/dist/providers/exedev.d.ts +23 -0
- package/dist/providers/exedev.js +290 -0
- package/dist/providers/freestyle.d.ts +49 -0
- package/dist/providers/freestyle.js +261 -0
- package/dist/providers/hopx.d.ts +15 -0
- package/dist/providers/hopx.js +177 -0
- package/dist/providers/instabox.d.ts +76 -0
- package/dist/providers/instabox.js +360 -0
- package/dist/providers/koyeb.d.ts +71 -0
- package/dist/providers/koyeb.js +379 -0
- package/dist/providers/lambda.d.ts +51 -0
- package/dist/providers/lambda.js +467 -0
- package/dist/providers/langsmith.d.ts +16 -0
- package/dist/providers/langsmith.js +149 -0
- package/dist/providers/limrun.d.ts +77 -0
- package/dist/providers/limrun.js +626 -0
- package/dist/providers/maritime.d.ts +5 -1
- package/dist/providers/maritime.js +39 -8
- package/dist/providers/mobilerun.d.ts +44 -0
- package/dist/providers/mobilerun.js +417 -0
- package/dist/providers/modal.js +12 -4
- package/dist/providers/morph.js +12 -4
- package/dist/providers/northflank.d.ts +21 -0
- package/dist/providers/northflank.js +259 -0
- package/dist/providers/novita.d.ts +12 -0
- package/dist/providers/novita.js +81 -0
- package/dist/providers/openscale.d.ts +17 -0
- package/dist/providers/openscale.js +87 -0
- package/dist/providers/orgo.d.ts +45 -0
- package/dist/providers/orgo.js +414 -0
- package/dist/providers/sail.d.ts +32 -0
- package/dist/providers/sail.js +372 -0
- package/dist/providers/superserve.d.ts +25 -0
- package/dist/providers/superserve.js +337 -0
- package/dist/providers/tensorlake.js +17 -14
- package/dist/providers/upstash.d.ts +30 -0
- package/dist/providers/upstash.js +258 -0
- package/dist/providers/vercel.js +14 -3
- package/dist/providers/workspaces.d.ts +60 -0
- package/dist/providers/workspaces.js +662 -0
- package/dist/router.d.ts +36 -5
- package/dist/router.js +174 -25
- package/dist/server.d.ts +1 -1
- package/dist/server.js +22 -3
- package/dist/types.d.ts +18 -6
- package/dist/util.d.ts +28 -1
- package/dist/util.js +56 -7
- package/package.json +106 -17
package/dist/catalog.js
CHANGED
|
@@ -1,18 +1,61 @@
|
|
|
1
|
+
import { KOYEB_INSTANCES, koyebInstance } from "./providers/koyeb.js";
|
|
2
|
+
import { AGENT37_SHAPES, agent37Shape } from "./providers/agent37.js";
|
|
3
|
+
import { INSTABOX_SIZES, instaboxSize } from "./providers/instabox.js";
|
|
4
|
+
import { FREESTYLE_SIZES, freestyleSize } from "./providers/freestyle.js";
|
|
5
|
+
import { langsmithSize } from "./providers/langsmith.js";
|
|
6
|
+
/** Short label for a gated provider's sign-up status, or null when anyone can sign up. */
|
|
7
|
+
export function accessLabel(id) {
|
|
8
|
+
const a = CATALOG.find((c) => c.id === id)?.access;
|
|
9
|
+
return a ? (a.status === "waitlist" ? "sign-up waitlisted" : "not taking new accounts") : null;
|
|
10
|
+
}
|
|
11
|
+
/** Short label for the plan a provider needs before you can use it: "none", "$20/mo (credited)", "$5/mo". */
|
|
12
|
+
export function planLabel(id) {
|
|
13
|
+
const p = CATALOG.find((c) => c.id === id)?.plan;
|
|
14
|
+
if (!p)
|
|
15
|
+
return "none";
|
|
16
|
+
return `${p.unclear ? "maybe " : ""}$${p.usdMonth}/mo${p.credited ? " (credited)" : ""}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The order tables list providers in (README, CLI, website): providers anyone can sign up for that can
|
|
20
|
+
* take this size, cheapest first, ties alphabetical; then waitlisted or closed sign-ups; then providers
|
|
21
|
+
* that can't take the size; then Docker. The router uses the same price order, but only among providers
|
|
22
|
+
* you have keys for, so a gated provider only gets work if you already have an account there.
|
|
23
|
+
*/
|
|
24
|
+
export function listingOrder(spec = {}) {
|
|
25
|
+
const rank = (c) => (c.local ? 3 : unfit(c.id, spec) ? 2 : c.access ? 1 : 0);
|
|
26
|
+
return [...CATALOG].sort((a, b) => rank(a) - rank(b) || hourlyCost(a.id, spec) - hourlyCost(b.id, spec) || a.id.localeCompare(b.id));
|
|
27
|
+
}
|
|
1
28
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
29
|
+
* Every provider is treated the same: the router orders candidates by list price for the requested
|
|
30
|
+
* size (or by your measured cold starts), ties broken alphabetically. Nobody gets a better slot.
|
|
31
|
+
* Prices come from each provider's public pricing page; PRs that correct one are welcome.
|
|
5
32
|
*/
|
|
6
|
-
|
|
33
|
+
const ENTRIES = [
|
|
34
|
+
{
|
|
35
|
+
id: "docker",
|
|
36
|
+
name: "Docker (local)",
|
|
37
|
+
pricing: {
|
|
38
|
+
vcpuHour: 0,
|
|
39
|
+
gbHour: 0,
|
|
40
|
+
note: "runs on your own machine; free, but shares your kernel, so weaker isolation than a cloud micro-VM",
|
|
41
|
+
source: "https://docs.docker.com/engine/",
|
|
42
|
+
checked: "2026-11-04",
|
|
43
|
+
},
|
|
44
|
+
capabilities: ["pause", "custom-image"],
|
|
45
|
+
limits: { maxVcpu: 64, maxMemoryGb: 256 },
|
|
46
|
+
local: true,
|
|
47
|
+
credentials: [],
|
|
48
|
+
docs: "https://docs.docker.com/engine/",
|
|
49
|
+
},
|
|
7
50
|
{
|
|
8
51
|
id: "maritime",
|
|
9
52
|
name: "Maritime",
|
|
10
53
|
pricing: {
|
|
11
54
|
vcpuHour: 0.0055,
|
|
12
55
|
gbHour: 0.00275,
|
|
13
|
-
note: "per second, disk included",
|
|
56
|
+
note: "per second, no minimum runtime; running disk included; Starter $20/mo incl. $20 usage; paused disk $0.08/GB-month (default idle action deletes sandbox)",
|
|
14
57
|
source: "https://maritime.sh/pricing",
|
|
15
|
-
checked: "2026-11-
|
|
58
|
+
checked: "2026-11-05",
|
|
16
59
|
},
|
|
17
60
|
capabilities: ["pause", "custom-image"],
|
|
18
61
|
limits: { maxVcpu: 16, maxMemoryGb: 64 },
|
|
@@ -25,12 +68,14 @@ export const CATALOG = [
|
|
|
25
68
|
pricing: {
|
|
26
69
|
vcpuHour: 0.0504,
|
|
27
70
|
gbHour: 0.0162,
|
|
28
|
-
note: "per second;
|
|
71
|
+
note: "per second; free Hobby tier ($100 one-time credit, 1-hour sessions, 20 at once); Pro $150/mo for longer sessions",
|
|
29
72
|
source: "https://e2b.dev/pricing",
|
|
30
73
|
checked: "2026-11-04",
|
|
31
74
|
},
|
|
32
75
|
capabilities: ["pause", "custom-image"],
|
|
33
76
|
limits: { maxVcpu: 8, maxMemoryGb: 8 },
|
|
77
|
+
// The default template; a bigger size needs a template built with --cpu-count / --memory-mb.
|
|
78
|
+
defaultSize: { vcpu: 2, memoryGb: 0.5, measured: "2026-11-06" },
|
|
34
79
|
credentials: [["E2B_API_KEY"]],
|
|
35
80
|
docs: "https://e2b.dev/docs",
|
|
36
81
|
},
|
|
@@ -46,6 +91,8 @@ export const CATALOG = [
|
|
|
46
91
|
},
|
|
47
92
|
capabilities: ["pause", "custom-image"],
|
|
48
93
|
limits: { maxVcpu: 4, maxMemoryGb: 8 },
|
|
94
|
+
// The default snapshot; resources only apply when creating from an image (image.daytona).
|
|
95
|
+
defaultSize: { vcpu: 1, memoryGb: 1, measured: "2026-11-06" },
|
|
49
96
|
credentials: [["DAYTONA_API_KEY"]],
|
|
50
97
|
docs: "https://www.daytona.io/docs",
|
|
51
98
|
},
|
|
@@ -53,11 +100,11 @@ export const CATALOG = [
|
|
|
53
100
|
id: "modal",
|
|
54
101
|
name: "Modal",
|
|
55
102
|
pricing: {
|
|
56
|
-
vcpuHour: 0.
|
|
57
|
-
gbHour: 0.
|
|
58
|
-
note: "sandbox rates, GPUs extra; region pinning x1.15-1.75",
|
|
103
|
+
vcpuHour: 0.070956,
|
|
104
|
+
gbHour: 0.024012,
|
|
105
|
+
note: "sandbox rates, per second ($0.00003942 per physical core = 2 vCPUs); GPUs extra; region pinning x1.15-1.75; Starter includes $30/mo credit",
|
|
59
106
|
source: "https://modal.com/pricing",
|
|
60
|
-
checked: "2026-11-
|
|
107
|
+
checked: "2026-11-05",
|
|
61
108
|
},
|
|
62
109
|
capabilities: ["gpu", "custom-image"],
|
|
63
110
|
limits: { maxVcpu: 64, maxMemoryGb: 256 },
|
|
@@ -70,9 +117,9 @@ export const CATALOG = [
|
|
|
70
117
|
pricing: {
|
|
71
118
|
vcpuHour: 0.128,
|
|
72
119
|
gbHour: 0.0212,
|
|
73
|
-
note: "
|
|
120
|
+
note: "iad1; active CPU, provisioned RAM in minimum 1-minute increments (2 GB/vCPU); full-CPU estimate; Hobby free within quotas, Pro $20/mo usage credit; creations $0.60/million and retained snapshots $0.08/GB-month extra",
|
|
74
121
|
source: "https://vercel.com/docs/vercel-sandbox/pricing",
|
|
75
|
-
checked: "2026-11-
|
|
122
|
+
checked: "2026-11-05",
|
|
76
123
|
},
|
|
77
124
|
capabilities: [],
|
|
78
125
|
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
@@ -120,7 +167,7 @@ export const CATALOG = [
|
|
|
120
167
|
source: "https://blaxel.ai/pricing",
|
|
121
168
|
checked: "2026-11-04",
|
|
122
169
|
},
|
|
123
|
-
capabilities: ["
|
|
170
|
+
capabilities: ["custom-image"],
|
|
124
171
|
// Self-serve caps are per-tier and not published; these are conservative.
|
|
125
172
|
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
126
173
|
credentials: [["BL_API_KEY", "BL_WORKSPACE"]],
|
|
@@ -157,6 +204,449 @@ export const CATALOG = [
|
|
|
157
204
|
docs: "https://docs.runloop.ai",
|
|
158
205
|
},
|
|
159
206
|
];
|
|
207
|
+
ENTRIES.push({
|
|
208
|
+
id: "boat",
|
|
209
|
+
name: "Boat",
|
|
210
|
+
pricing: {
|
|
211
|
+
vcpuHour: 0.009,
|
|
212
|
+
gbHour: 0,
|
|
213
|
+
note: "fixed sizes billed per second ($0.018/h for 2 vCPU / 4 GB up to $0.20/h for 16 / 32); needs a plan from $20/mo, paid back as VM time",
|
|
214
|
+
source: "https://docs.boat.dev/pricing.md",
|
|
215
|
+
checked: "2026-11-04",
|
|
216
|
+
},
|
|
217
|
+
// "pause" here is Boat's stop: the disk is kept, running processes end.
|
|
218
|
+
capabilities: ["pause", "custom-image"],
|
|
219
|
+
limits: { maxVcpu: 16, maxMemoryGb: 32 },
|
|
220
|
+
credentials: [["BOAT_API_KEY"]],
|
|
221
|
+
docs: "https://docs.boat.dev",
|
|
222
|
+
}, {
|
|
223
|
+
id: "exedev",
|
|
224
|
+
name: "exe.dev",
|
|
225
|
+
pricing: {
|
|
226
|
+
vcpuHour: 0.0525,
|
|
227
|
+
gbHour: 0,
|
|
228
|
+
note: "standalone reserved size, per second: $0.105/h per 2 vCPU / 4 GiB unit; stopped CPU/RAM free, retained disk separate; Personal from $15/mo (up to 16 vCPU / 32 GiB), Work $75/mo (32 / 64 without approval)",
|
|
229
|
+
source: "https://exe.dev/docs/standalone-vms.md",
|
|
230
|
+
checked: "2026-11-05",
|
|
231
|
+
},
|
|
232
|
+
capabilities: ["custom-image"],
|
|
233
|
+
// 16 / 32 is the biggest Personal plan; Work allows 32 / 64, but the router can't tell which plan you have.
|
|
234
|
+
limits: { maxVcpu: 16, maxMemoryGb: 32 },
|
|
235
|
+
credentials: [["EXE_TOKEN"]],
|
|
236
|
+
docs: "https://exe.dev/docs/https-api.md",
|
|
237
|
+
}, {
|
|
238
|
+
id: "northflank",
|
|
239
|
+
name: "Northflank",
|
|
240
|
+
pricing: {
|
|
241
|
+
vcpuHour: 0.01667,
|
|
242
|
+
gbHour: 0.00833,
|
|
243
|
+
note: "per second on Northflank Cloud, ephemeral disk included; sandboxes run as deployment services (microVMs)",
|
|
244
|
+
source: "https://northflank.com/pricing",
|
|
245
|
+
checked: "2026-11-04",
|
|
246
|
+
},
|
|
247
|
+
capabilities: ["custom-image"],
|
|
248
|
+
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
249
|
+
credentials: [["NORTHFLANK_API_TOKEN", "NORTHFLANK_PROJECT_ID"]],
|
|
250
|
+
docs: "https://northflank.com/docs/v1/application/overview",
|
|
251
|
+
}, {
|
|
252
|
+
id: "hopx",
|
|
253
|
+
name: "HOPX",
|
|
254
|
+
pricing: {
|
|
255
|
+
vcpuHour: 0.0504,
|
|
256
|
+
gbHour: 0.0162,
|
|
257
|
+
note: "per second, plus storage; size comes from the template, not the request",
|
|
258
|
+
source: "https://hopx.ai/pricing",
|
|
259
|
+
checked: "2026-11-04",
|
|
260
|
+
},
|
|
261
|
+
capabilities: ["pause", "custom-image"],
|
|
262
|
+
// HOPX takes no size at create; capped at the default size so bigger requests go elsewhere.
|
|
263
|
+
limits: { maxVcpu: 2, maxMemoryGb: 4 },
|
|
264
|
+
credentials: [["HOPX_API_KEY"]],
|
|
265
|
+
docs: "https://docs.hopx.ai",
|
|
266
|
+
}, {
|
|
267
|
+
id: "cloudflare",
|
|
268
|
+
name: "Cloudflare Sandbox",
|
|
269
|
+
pricing: {
|
|
270
|
+
vcpuHour: 0.072,
|
|
271
|
+
gbHour: 0.009,
|
|
272
|
+
note: "10 ms billing on active CPU and allocated instance memory; full-CPU estimate excludes allocated disk ($0.000252/GB-h), Worker and Durable Objects charges; needs Workers Paid ($5/mo) and bridges/cloudflare",
|
|
273
|
+
source: "https://developers.cloudflare.com/containers/platform/pricing/",
|
|
274
|
+
checked: "2026-11-05",
|
|
275
|
+
},
|
|
276
|
+
capabilities: [],
|
|
277
|
+
limits: { maxVcpu: 4, maxMemoryGb: 12 },
|
|
278
|
+
credentials: [["CLOUDFLARE_SANDBOX_URL", "CLOUDFLARE_SANDBOX_TOKEN"]],
|
|
279
|
+
docs: "https://developers.cloudflare.com/sandbox/",
|
|
280
|
+
});
|
|
281
|
+
ENTRIES.push({
|
|
282
|
+
id: "agentcore",
|
|
283
|
+
name: "Amazon Bedrock AgentCore Code Interpreter",
|
|
284
|
+
pricing: {
|
|
285
|
+
vcpuHour: 0.0895,
|
|
286
|
+
gbHour: 0.00945,
|
|
287
|
+
note: "per second; CPU billed on actual use (I/O wait free), memory on peak; fixed 2 vCPU / 8 GB session, this is the 100%-CPU price",
|
|
288
|
+
source: "https://aws.amazon.com/bedrock/agentcore/pricing/",
|
|
289
|
+
checked: "2026-11-04",
|
|
290
|
+
},
|
|
291
|
+
capabilities: [],
|
|
292
|
+
limits: { maxVcpu: 2, maxMemoryGb: 8 },
|
|
293
|
+
credentials: [
|
|
294
|
+
["AGENTCORE_CODE_INTERPRETER_ID", "AWS_REGION", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
|
|
295
|
+
["AGENTCORE_CODE_INTERPRETER_ID", "AWS_REGION", "AWS_PROFILE"],
|
|
296
|
+
],
|
|
297
|
+
docs: "https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/code-interpreter-api-reference-examples.html",
|
|
298
|
+
}, {
|
|
299
|
+
id: "azure",
|
|
300
|
+
name: "Azure Container Apps dynamic sessions",
|
|
301
|
+
pricing: {
|
|
302
|
+
vcpuHour: 0.03,
|
|
303
|
+
gbHour: 0,
|
|
304
|
+
note: "flat $0.03 per session-hour (built-in Shell pools), billed per allocated session in 1-hour increments, East US; needs a session pool you create once",
|
|
305
|
+
source: "https://learn.microsoft.com/en-us/azure/container-apps/billing#dynamic-sessions",
|
|
306
|
+
checked: "2026-11-04",
|
|
307
|
+
},
|
|
308
|
+
capabilities: [],
|
|
309
|
+
// Per-session size isn't published; placeholder until measured with nproc / free.
|
|
310
|
+
limits: { maxVcpu: 1, maxMemoryGb: 2 },
|
|
311
|
+
credentials: [
|
|
312
|
+
["AZURE_SESSIONS_POOL_ENDPOINT", "AZURE_SESSIONS_TOKEN"],
|
|
313
|
+
["AZURE_SESSIONS_POOL_ENDPOINT", "AZURE_TENANT_ID", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET"],
|
|
314
|
+
],
|
|
315
|
+
docs: "https://learn.microsoft.com/en-us/azure/container-apps/sessions-tutorial-shell",
|
|
316
|
+
}, {
|
|
317
|
+
id: "lambda",
|
|
318
|
+
name: "AWS Lambda MicroVMs",
|
|
319
|
+
pricing: {
|
|
320
|
+
vcpuHour: 0.09969984,
|
|
321
|
+
gbHour: 0.01320012,
|
|
322
|
+
note: "us-east-1 ARM; billed on the image's baseline size (2 GB per vCPU) while running, per-second burst up to 4x; suspended VMs pay snapshot storage; needs a MicroVM image you build once",
|
|
323
|
+
source: "https://aws.amazon.com/lambda/pricing/",
|
|
324
|
+
checked: "2026-11-05",
|
|
325
|
+
},
|
|
326
|
+
capabilities: ["pause", "custom-image"],
|
|
327
|
+
limits: { maxVcpu: 4, maxMemoryGb: 8 },
|
|
328
|
+
credentials: [
|
|
329
|
+
["AWS_REGION", "LAMBDA_MICROVM_IMAGE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"],
|
|
330
|
+
["AWS_REGION", "LAMBDA_MICROVM_IMAGE", "AWS_PROFILE"],
|
|
331
|
+
],
|
|
332
|
+
docs: "https://docs.aws.amazon.com/lambda/latest/dg/lambda-microvms-guide.html",
|
|
333
|
+
}, {
|
|
334
|
+
id: "agent37",
|
|
335
|
+
name: "Agent37",
|
|
336
|
+
pricing: {
|
|
337
|
+
vcpuHour: 0.8 / 730,
|
|
338
|
+
gbHour: 0.7 / 730,
|
|
339
|
+
note: "whole-minute billing: monthly shape total / 730 / 60; running estimate includes default disk (2 vCPU / 4 GB / 4 GB disk = $4.76/mo); sleeping/stopped disk $0.09/GB-mo; gVisor; $5 minimum top-up, wallet must hold one running day",
|
|
340
|
+
source: "https://www.agent37.com/docs/agents-api/billing",
|
|
341
|
+
checked: "2026-11-05",
|
|
342
|
+
},
|
|
343
|
+
capabilities: ["pause", "custom-image"],
|
|
344
|
+
limits: { maxVcpu: 4, maxMemoryGb: 32 },
|
|
345
|
+
credentials: [["AGENT37_API_KEY"]],
|
|
346
|
+
docs: "https://www.agent37.com/docs/agents-api/overview",
|
|
347
|
+
}, {
|
|
348
|
+
id: "alibaba",
|
|
349
|
+
name: "Alibaba Cloud Agent Sandbox",
|
|
350
|
+
pricing: {
|
|
351
|
+
vcpuHour: 0.017856,
|
|
352
|
+
gbHour: 0.008928,
|
|
353
|
+
note: "per second; Default QoS, Hong Kong and regions outside mainland China; disk separately $0.00025308/GiB-h; code-interpreter-v1 template is 2 vCPU / 2 GiB with 10 GiB disk (E2B-compatible API)",
|
|
354
|
+
source: "https://www.alibabacloud.com/help/en/agent-sandbox/product-overview/billing-overview",
|
|
355
|
+
checked: "2026-11-05",
|
|
356
|
+
},
|
|
357
|
+
capabilities: ["custom-image"],
|
|
358
|
+
// No published maximum; the default template is 2 vCPU / 2 GB, so bigger requests go elsewhere.
|
|
359
|
+
limits: { maxVcpu: 2, maxMemoryGb: 2 },
|
|
360
|
+
credentials: [["ALIBABA_SANDBOX_API_KEY"]],
|
|
361
|
+
docs: "https://www.alibabacloud.com/help/en/agent-sandbox/e2b-sdk-integration-parameter-description",
|
|
362
|
+
}, {
|
|
363
|
+
id: "beam",
|
|
364
|
+
name: "Beam",
|
|
365
|
+
pricing: {
|
|
366
|
+
vcpuHour: 0.05,
|
|
367
|
+
gbHour: 0.01,
|
|
368
|
+
note: "per second, Performance tier (sandbox default); Developer plan $20/mo incl. $20 credits; GPUs billed separately",
|
|
369
|
+
source: "https://www.beam.cloud/pricing",
|
|
370
|
+
checked: "2026-11-04",
|
|
371
|
+
},
|
|
372
|
+
capabilities: ["custom-image"],
|
|
373
|
+
// Not documented per sandbox: 30 is the Developer plan's concurrent vCPU cap.
|
|
374
|
+
limits: { maxVcpu: 30, maxMemoryGb: 64 },
|
|
375
|
+
credentials: [["BEAM_TOKEN", "BEAM_WORKSPACE_ID"]],
|
|
376
|
+
docs: "https://docs.beam.cloud/v2/reference/ts-sdk",
|
|
377
|
+
}, {
|
|
378
|
+
id: "codesandbox",
|
|
379
|
+
name: "CodeSandbox SDK (Together)",
|
|
380
|
+
pricing: {
|
|
381
|
+
vcpuHour: 0.0743,
|
|
382
|
+
gbHour: 0,
|
|
383
|
+
note: "fixed tiers: Pico 2 vCPU / 1 GB $0.0743/h, Nano 2 / 4 $0.1486/h, up to 64 / 128 $4.7552/h; credits $0.01486, billed per started minute; Build free, 10 concurrent; Scale $170/mo incl. 1,100 credits",
|
|
384
|
+
source: "https://docs.together.ai/docs/together-code-sandbox-legacy",
|
|
385
|
+
checked: "2026-11-05",
|
|
386
|
+
},
|
|
387
|
+
capabilities: ["pause", "custom-image"],
|
|
388
|
+
limits: { maxVcpu: 64, maxMemoryGb: 128 },
|
|
389
|
+
credentials: [["CSB_API_KEY"]],
|
|
390
|
+
docs: "https://codesandbox.io/docs/sdk",
|
|
391
|
+
}, {
|
|
392
|
+
id: "superserve",
|
|
393
|
+
name: "Superserve",
|
|
394
|
+
pricing: {
|
|
395
|
+
vcpuHour: 0.0504,
|
|
396
|
+
gbHour: 0.0162,
|
|
397
|
+
note: "per second active; superserve/base fixed at 2 vCPU / 4 GiB / 8 GiB disk; retained storage $0.000108/GiB-h (shared template plus changed blocks); Developer $20/mo incl. $20, max 4/16 with team templates; recurring Free allowance not published on pricing page",
|
|
398
|
+
source: "https://superserve.ai/pricing",
|
|
399
|
+
checked: "2026-11-05",
|
|
400
|
+
},
|
|
401
|
+
capabilities: ["pause", "custom-image"],
|
|
402
|
+
limits: { maxVcpu: 2, maxMemoryGb: 4 },
|
|
403
|
+
credentials: [["SUPERSERVE_API_KEY"]],
|
|
404
|
+
docs: "https://docs.superserve.ai",
|
|
405
|
+
}, {
|
|
406
|
+
id: "sail",
|
|
407
|
+
name: "Sailboxes (Sail Research)",
|
|
408
|
+
pricing: {
|
|
409
|
+
vcpuHour: 0.015,
|
|
410
|
+
gbHour: 0.008,
|
|
411
|
+
note: "per second on what the box uses (CPU time, RAM it holds, disk $0.0007/GiB-h), billed per minute; RAM counts the VM's file cache, up to the 16 GiB minimum limit, so file-heavy work can hold more than you asked for; paused/sleeping free; creation $0.01 at 2-4 vCPU on the free plan ($5/mo credit with a card), waived on Pro $250/mo",
|
|
412
|
+
source: "https://docs.sailresearch.com/sailboxes-pricing.md",
|
|
413
|
+
checked: "2026-11-06",
|
|
414
|
+
},
|
|
415
|
+
capabilities: ["pause"],
|
|
416
|
+
limits: { maxVcpu: 64, maxMemoryGb: 512 },
|
|
417
|
+
credentials: [["SAIL_API_KEY"]],
|
|
418
|
+
docs: "https://docs.sailresearch.com/sailboxes.md",
|
|
419
|
+
}, {
|
|
420
|
+
id: "openscale",
|
|
421
|
+
name: "OpenScale Sandboxes",
|
|
422
|
+
pricing: {
|
|
423
|
+
vcpuHour: 0.0065,
|
|
424
|
+
gbHour: 0.001,
|
|
425
|
+
note: "per second on allocated size; no platform fee or minimum; paused = free; size comes from the template (E2B-compatible API); Singapore only; needs a pay-as-you-go key",
|
|
426
|
+
source: "https://openscale.so/sandboxes",
|
|
427
|
+
checked: "2026-11-05",
|
|
428
|
+
},
|
|
429
|
+
capabilities: ["pause", "custom-image"],
|
|
430
|
+
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
431
|
+
// The "base" template; size comes from the template.
|
|
432
|
+
defaultSize: { vcpu: 2, memoryGb: 1, measured: "2026-11-06" },
|
|
433
|
+
credentials: [["OPENSCALE_API_KEY"]],
|
|
434
|
+
docs: "https://openscale.so/sandboxes",
|
|
435
|
+
}, {
|
|
436
|
+
id: "dedalus",
|
|
437
|
+
name: "Dedalus Machines",
|
|
438
|
+
pricing: {
|
|
439
|
+
vcpuHour: 0.04536,
|
|
440
|
+
gbHour: 0.01458,
|
|
441
|
+
note: "per second while awake; sleeping machines bill storage only (10 GiB included on Hobby, 20 on Pro); Hobby plan max 4 vCPU / 16 GiB; private beta",
|
|
442
|
+
source: "https://docs.dedaluslabs.ai/dcs/dm/pricing",
|
|
443
|
+
checked: "2026-11-05",
|
|
444
|
+
},
|
|
445
|
+
capabilities: ["pause"],
|
|
446
|
+
limits: { maxVcpu: 16, maxMemoryGb: 64 },
|
|
447
|
+
credentials: [["DEDALUS_API_KEY"]],
|
|
448
|
+
docs: "https://docs.dedaluslabs.ai/dcs/dm/quickstart",
|
|
449
|
+
access: { status: "waitlist", note: "private beta: your organization has to be admitted before keys work", checked: "2026-11-05" },
|
|
450
|
+
}, {
|
|
451
|
+
id: "deno",
|
|
452
|
+
name: "Deno Sandbox",
|
|
453
|
+
pricing: {
|
|
454
|
+
vcpuHour: 0.1,
|
|
455
|
+
gbHour: 0.025,
|
|
456
|
+
note: "billed on CPU time, not wall clock (estimate assumes both vCPUs busy); fixed 2 vCPU, 0.75-4 GB, max 30 min lifetime; needs a paid Deno Deploy plan",
|
|
457
|
+
source: "https://deno.com/sandbox",
|
|
458
|
+
checked: "2026-11-04",
|
|
459
|
+
},
|
|
460
|
+
capabilities: ["custom-image"],
|
|
461
|
+
limits: { maxVcpu: 2, maxMemoryGb: 4 },
|
|
462
|
+
credentials: [["DENO_DEPLOY_TOKEN"]],
|
|
463
|
+
docs: "https://docs.deno.com/sandbox/",
|
|
464
|
+
}, {
|
|
465
|
+
id: "freestyle",
|
|
466
|
+
name: "Freestyle",
|
|
467
|
+
pricing: {
|
|
468
|
+
vcpuHour: 0.04032,
|
|
469
|
+
gbHour: 0.0129,
|
|
470
|
+
note: "per second on allocated fixed snapshot size; estimate includes disk at $0.000086/GiB-h; free monthly 200 vCPU-h, 400 GiB-h RAM, 60,000 GiB-h disk; Hobby $50/mo incl. $50 (max 8/16), Pro $500 (max 32/64); paused storage only",
|
|
471
|
+
source: "https://www.freestyle.sh/docs/vms/pricing-and-limits",
|
|
472
|
+
checked: "2026-11-05",
|
|
473
|
+
},
|
|
474
|
+
capabilities: ["pause", "custom-image"],
|
|
475
|
+
limits: { maxVcpu: 32, maxMemoryGb: 64 },
|
|
476
|
+
credentials: [["FREESTYLE_API_KEY"]],
|
|
477
|
+
docs: "https://www.freestyle.sh/docs/vms",
|
|
478
|
+
}, {
|
|
479
|
+
id: "instabox",
|
|
480
|
+
name: "InstaBox",
|
|
481
|
+
pricing: {
|
|
482
|
+
vcpuHour: 0.004,
|
|
483
|
+
gbHour: 0.00225,
|
|
484
|
+
note: "per second while running on fixed sizes (2/4, 4/8, 8/16); paused or stopped boxes bill only /data beyond the included disk ($0.00011/GiB-h); Pro $20/mo includes $20 credits; free plan: 1 box at 4/8",
|
|
485
|
+
source: "https://instabox.sh/docs/pricing.md",
|
|
486
|
+
checked: "2026-11-05",
|
|
487
|
+
},
|
|
488
|
+
capabilities: ["pause", "custom-image"],
|
|
489
|
+
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
490
|
+
credentials: [["INSTABOX_API_KEY"]],
|
|
491
|
+
docs: "https://instabox.sh/docs/api.md",
|
|
492
|
+
access: { status: "waitlist", note: "new accounts go on a waitlist before they can create boxes or keys", checked: "2026-11-05" },
|
|
493
|
+
}, {
|
|
494
|
+
id: "koyeb",
|
|
495
|
+
name: "Koyeb Sandboxes",
|
|
496
|
+
pricing: {
|
|
497
|
+
vcpuHour: 0.0144,
|
|
498
|
+
gbHour: 0,
|
|
499
|
+
note: "per second; fixed Standard instance sizes (1 vCPU + 1 GB = $0.0144/h); sandboxes need a paid plan (Pro $29/mo); public preview",
|
|
500
|
+
source: "https://www.koyeb.com/docs/reference/instances",
|
|
501
|
+
checked: "2026-11-04",
|
|
502
|
+
},
|
|
503
|
+
capabilities: ["custom-image"],
|
|
504
|
+
limits: { maxVcpu: 40, maxMemoryGb: 128 },
|
|
505
|
+
credentials: [["KOYEB_API_TOKEN"]],
|
|
506
|
+
docs: "https://www.koyeb.com/docs/sandboxes",
|
|
507
|
+
access: {
|
|
508
|
+
status: "closed",
|
|
509
|
+
note: "Koyeb is joining Mistral; a new account's dashboard only shows that notice, with no way to create sandboxes or tokens. Existing accounts are unaffected",
|
|
510
|
+
checked: "2026-11-05",
|
|
511
|
+
},
|
|
512
|
+
}, {
|
|
513
|
+
id: "langsmith",
|
|
514
|
+
name: "LangSmith Sandboxes",
|
|
515
|
+
pricing: {
|
|
516
|
+
vcpuHour: 0.0576,
|
|
517
|
+
gbHour: 0.01845,
|
|
518
|
+
note: "per second; memory must be 2 to 6 GiB per vCPU; storage $0.000123/GiB-h; 8 LSU ($8) of sandbox usage a month included; Developer plan max 10 sandboxes",
|
|
519
|
+
source: "https://www.langchain.com/pricing",
|
|
520
|
+
checked: "2026-11-05",
|
|
521
|
+
},
|
|
522
|
+
capabilities: ["pause", "custom-image"],
|
|
523
|
+
// Not published; 16 vCPU / 96 GiB stays inside the 6 GiB per vCPU band. Real runs will tell.
|
|
524
|
+
limits: { maxVcpu: 16, maxMemoryGb: 96 },
|
|
525
|
+
credentials: [["LANGSMITH_API_KEY"]],
|
|
526
|
+
docs: "https://docs.langchain.com/langsmith/sandboxes",
|
|
527
|
+
}, {
|
|
528
|
+
id: "novita",
|
|
529
|
+
name: "Novita AI Agent Sandbox",
|
|
530
|
+
pricing: {
|
|
531
|
+
vcpuHour: 0.03528,
|
|
532
|
+
gbHour: 0.01152,
|
|
533
|
+
note: "per second ($0.0000098/vCPU/s, $0.0000032/GiB/s); size comes from the template; paused = storage only",
|
|
534
|
+
source: "https://docs.novita.ai/guides/sandbox-pricing",
|
|
535
|
+
checked: "2026-11-04",
|
|
536
|
+
},
|
|
537
|
+
capabilities: ["pause", "custom-image"],
|
|
538
|
+
limits: { maxVcpu: 8, maxMemoryGb: 8 },
|
|
539
|
+
credentials: [["NOVITA_API_KEY"]],
|
|
540
|
+
docs: "https://docs.novita.ai/guides/sandbox-overview",
|
|
541
|
+
}, {
|
|
542
|
+
id: "upstash",
|
|
543
|
+
name: "Upstash Box",
|
|
544
|
+
pricing: {
|
|
545
|
+
vcpuHour: 0.1,
|
|
546
|
+
gbHour: 0,
|
|
547
|
+
note: "billed per active CPU core-hour only (memory and idle time free); estimate assumes every core of the box busy; fixed sizes 2/4, 4/8, 8/16",
|
|
548
|
+
source: "https://upstash.com/pricing/box",
|
|
549
|
+
checked: "2026-11-04",
|
|
550
|
+
},
|
|
551
|
+
capabilities: [],
|
|
552
|
+
limits: { maxVcpu: 8, maxMemoryGb: 16 },
|
|
553
|
+
credentials: [["UPSTASH_BOX_API_KEY"]],
|
|
554
|
+
docs: "https://upstash.com/docs/box/overall/ephemeral-box",
|
|
555
|
+
});
|
|
556
|
+
/**
|
|
557
|
+
* How each provider bills, and the monthly plan it needs before the API will create sandboxes.
|
|
558
|
+
* Every provider must be listed (the Record type checks it). Plan fees come from each pricing page,
|
|
559
|
+
* checked 2026-11-06; prepaid top-ups that turn into usage aren't fees, so they don't count.
|
|
560
|
+
*/
|
|
561
|
+
const P = "2026-11-06";
|
|
562
|
+
const BILLING = {
|
|
563
|
+
docker: { billing: "allocated" },
|
|
564
|
+
agent37: { billing: "allocated" },
|
|
565
|
+
agentcore: { billing: "active-cpu" },
|
|
566
|
+
alibaba: { billing: "allocated" },
|
|
567
|
+
azure: { billing: "allocated" },
|
|
568
|
+
beam: { billing: "allocated", plan: { usdMonth: 20, credited: true, note: "Developer plan; no free plan", checked: P } },
|
|
569
|
+
blaxel: { billing: "allocated" },
|
|
570
|
+
boat: { billing: "allocated", plan: { usdMonth: 20, credited: true, note: "plan paid back as VM time; 7-day trial needs a card", checked: P } },
|
|
571
|
+
cloudflare: {
|
|
572
|
+
billing: "active-cpu",
|
|
573
|
+
plan: { usdMonth: 5, credited: false, note: "Workers Paid; includes usage allowances, not credit", checked: P },
|
|
574
|
+
},
|
|
575
|
+
codesandbox: { billing: "allocated" },
|
|
576
|
+
daytona: { billing: "allocated" },
|
|
577
|
+
dedalus: { billing: "allocated" },
|
|
578
|
+
deno: {
|
|
579
|
+
billing: "active-cpu",
|
|
580
|
+
plan: { usdMonth: 20, credited: false, note: "the free Deno Deploy plan has no sandboxes; Pro includes allowances, not credit", checked: P },
|
|
581
|
+
},
|
|
582
|
+
e2b: { billing: "allocated" },
|
|
583
|
+
exedev: { billing: "allocated", plan: { usdMonth: 15, credited: false, note: "Personal plan; VMs are metered on top; 7-day trial", checked: P } },
|
|
584
|
+
freestyle: { billing: "allocated" },
|
|
585
|
+
hopx: { billing: "allocated" },
|
|
586
|
+
instabox: { billing: "allocated" },
|
|
587
|
+
koyeb: { billing: "allocated", plan: { usdMonth: 29, credited: false, note: "sandboxes need a paid plan; Pro includes $10 of compute", checked: P } },
|
|
588
|
+
lambda: { billing: "allocated" },
|
|
589
|
+
langsmith: { billing: "allocated" },
|
|
590
|
+
maritime: { billing: "allocated", plan: { usdMonth: 20, credited: true, note: "Starter plan; no free tier; 7-day trial needs a card", checked: P } },
|
|
591
|
+
modal: { billing: "active-cpu" },
|
|
592
|
+
morph: { billing: "allocated" },
|
|
593
|
+
northflank: { billing: "allocated" },
|
|
594
|
+
novita: { billing: "allocated" },
|
|
595
|
+
openscale: { billing: "allocated" },
|
|
596
|
+
runloop: { billing: "allocated" },
|
|
597
|
+
sprites: { billing: "active-cpu" },
|
|
598
|
+
sail: { billing: "active-cpu" },
|
|
599
|
+
superserve: {
|
|
600
|
+
billing: "allocated",
|
|
601
|
+
plan: { usdMonth: 20, credited: true, unclear: true, note: "Developer plan; the page offers a free start but doesn't say what it includes", checked: P },
|
|
602
|
+
},
|
|
603
|
+
tensorlake: { billing: "active-cpu" },
|
|
604
|
+
upstash: { billing: "active-cpu" },
|
|
605
|
+
vercel: { billing: "active-cpu" },
|
|
606
|
+
};
|
|
607
|
+
export const CATALOG = ENTRIES.map((e) => ({ ...e, ...BILLING[e.id] })).sort((a, b) => a.name.localeCompare(b.name));
|
|
608
|
+
/** Cloudflare only rents fixed instance types: https://developers.cloudflare.com/containers/platform/limits/ */
|
|
609
|
+
export const CLOUDFLARE_INSTANCES = [
|
|
610
|
+
{ name: "lite", vcpu: 1 / 16, memoryGb: 0.25 },
|
|
611
|
+
{ name: "basic", vcpu: 1 / 4, memoryGb: 1 },
|
|
612
|
+
{ name: "standard-1", vcpu: 1 / 2, memoryGb: 4 },
|
|
613
|
+
{ name: "standard-2", vcpu: 1, memoryGb: 6 },
|
|
614
|
+
{ name: "standard-3", vcpu: 2, memoryGb: 8 },
|
|
615
|
+
{ name: "standard-4", vcpu: 4, memoryGb: 12 },
|
|
616
|
+
];
|
|
617
|
+
/** CodeSandbox VM tiers: https://docs.together.ai/docs/together-code-sandbox-legacy (Pico supports 2 vCPU / 1 GB). */
|
|
618
|
+
export const CODESANDBOX_TIERS = [
|
|
619
|
+
{ name: "Pico", vcpu: 2, memoryGb: 1, usdHour: 0.0743 },
|
|
620
|
+
{ name: "Nano", vcpu: 2, memoryGb: 4, usdHour: 0.1486 },
|
|
621
|
+
{ name: "Micro", vcpu: 4, memoryGb: 8, usdHour: 0.2972 },
|
|
622
|
+
{ name: "Small", vcpu: 8, memoryGb: 16, usdHour: 0.5944 },
|
|
623
|
+
{ name: "Medium", vcpu: 16, memoryGb: 32, usdHour: 1.1888 },
|
|
624
|
+
{ name: "Large", vcpu: 32, memoryGb: 64, usdHour: 2.3776 },
|
|
625
|
+
{ name: "XLarge", vcpu: 64, memoryGb: 128, usdHour: 4.7552 },
|
|
626
|
+
];
|
|
627
|
+
/** Smallest tier with at least the requested vCPUs and memory (the largest if nothing fits). */
|
|
628
|
+
export function codesandboxTier(vcpu, memoryGb) {
|
|
629
|
+
return CODESANDBOX_TIERS.find((t) => t.vcpu >= vcpu && t.memoryGb >= memoryGb) ?? CODESANDBOX_TIERS[CODESANDBOX_TIERS.length - 1];
|
|
630
|
+
}
|
|
631
|
+
/** Upstash Box sizes (https://upstash.com/docs/box/overall/how-it-works.md#box-size). */
|
|
632
|
+
export const UPSTASH_SIZES = [
|
|
633
|
+
{ size: "small", vcpu: 2, memoryGb: 4 },
|
|
634
|
+
{ size: "medium", vcpu: 4, memoryGb: 8 },
|
|
635
|
+
{ size: "large", vcpu: 8, memoryGb: 16 },
|
|
636
|
+
];
|
|
637
|
+
export function upstashSize(vcpu, memoryGb) {
|
|
638
|
+
return UPSTASH_SIZES.find((s) => s.vcpu >= vcpu && s.memoryGb >= memoryGb) ?? UPSTASH_SIZES[UPSTASH_SIZES.length - 1];
|
|
639
|
+
}
|
|
640
|
+
/** Boat's fixed machine sizes and hourly prices: https://docs.boat.dev/machines.md */
|
|
641
|
+
export const BOAT_SIZES = [
|
|
642
|
+
{ type: "small", vcpu: 2, memoryGb: 4, usdHour: 0.018 },
|
|
643
|
+
{ type: "default", vcpu: 4, memoryGb: 8, usdHour: 0.036 },
|
|
644
|
+
{ type: "large", vcpu: 8, memoryGb: 16, usdHour: 0.072 },
|
|
645
|
+
{ type: "xlarge", vcpu: 16, memoryGb: 32, usdHour: 0.2 },
|
|
646
|
+
];
|
|
647
|
+
export function cloudflareInstance(vcpu, memoryGb) {
|
|
648
|
+
return CLOUDFLARE_INSTANCES.find((t) => t.vcpu >= vcpu && t.memoryGb >= memoryGb) ?? CLOUDFLARE_INSTANCES[CLOUDFLARE_INSTANCES.length - 1];
|
|
649
|
+
}
|
|
160
650
|
export function info(id) {
|
|
161
651
|
const p = CATALOG.find((c) => c.id === id);
|
|
162
652
|
if (!p)
|
|
@@ -166,8 +656,21 @@ export function info(id) {
|
|
|
166
656
|
export const DEFAULT_VCPU = 2;
|
|
167
657
|
export const DEFAULT_MEMORY_GB = 4;
|
|
168
658
|
/** Estimated USD per hour for this spec on this provider (list price, while running). */
|
|
659
|
+
/** The size the sandbox will really have when it's fixed by the default image, else null. */
|
|
660
|
+
export function fixedSize(id, spec = {}) {
|
|
661
|
+
const d = info(id).defaultSize;
|
|
662
|
+
return d && !spec.image?.[id] ? { vcpu: d.vcpu, memoryGb: d.memoryGb } : null;
|
|
663
|
+
}
|
|
664
|
+
/** A spec this provider can take as-is: its default size if it has one, else the router default. */
|
|
665
|
+
export function fittingSpec(id) {
|
|
666
|
+
return fixedSize(id) ?? { vcpu: DEFAULT_VCPU, memoryGb: DEFAULT_MEMORY_GB };
|
|
667
|
+
}
|
|
169
668
|
export function hourlyCost(id, spec = {}) {
|
|
170
669
|
const { pricing } = info(id);
|
|
670
|
+
// You get, and pay for, the default image's size whatever you asked for.
|
|
671
|
+
const fixed = fixedSize(id, spec);
|
|
672
|
+
if (fixed)
|
|
673
|
+
return fixed.vcpu * pricing.vcpuHour + fixed.memoryGb * pricing.gbHour;
|
|
171
674
|
const vcpu = spec.vcpu ?? DEFAULT_VCPU;
|
|
172
675
|
let mem = spec.memoryGb ?? DEFAULT_MEMORY_GB;
|
|
173
676
|
// Vercel fixes memory at 2 GB per vCPU.
|
|
@@ -176,6 +679,55 @@ export function hourlyCost(id, spec = {}) {
|
|
|
176
679
|
// Blaxel sizes by memory, about 2 GB per core.
|
|
177
680
|
if (id === "blaxel")
|
|
178
681
|
mem = Math.max(mem, vcpu * 2);
|
|
682
|
+
// Boat rents the smallest fixed size that fits.
|
|
683
|
+
if (id === "boat") {
|
|
684
|
+
const s = BOAT_SIZES.find((b) => b.vcpu >= vcpu && b.memoryGb >= mem) ?? BOAT_SIZES[BOAT_SIZES.length - 1];
|
|
685
|
+
return s.usdHour;
|
|
686
|
+
}
|
|
687
|
+
// exe.dev bills per vCPU with up to 2 GiB each, so memory beyond that adds vCPUs.
|
|
688
|
+
if (id === "exedev")
|
|
689
|
+
return Math.max(Math.ceil(vcpu), Math.ceil(mem / 2)) * pricing.vcpuHour;
|
|
690
|
+
// Cloudflare bills the instance type that fits, not the exact request.
|
|
691
|
+
if (id === "cloudflare") {
|
|
692
|
+
const t = cloudflareInstance(vcpu, mem);
|
|
693
|
+
return t.vcpu * pricing.vcpuHour + t.memoryGb * pricing.gbHour;
|
|
694
|
+
}
|
|
695
|
+
// Azure bills a flat rate per allocated session.
|
|
696
|
+
if (id === "azure")
|
|
697
|
+
return pricing.vcpuHour;
|
|
698
|
+
// Lambda MicroVMs bill the smallest baseline image size that fits (2 GB per vCPU).
|
|
699
|
+
if (id === "lambda") {
|
|
700
|
+
const size = [0.5, 1, 2, 4, 8].find((s) => s >= Math.max(mem, vcpu * 2)) ?? 8;
|
|
701
|
+
return size * pricing.gbHour + (size / 2) * pricing.vcpuHour;
|
|
702
|
+
}
|
|
703
|
+
// Superserve system templates are a fixed 2 vCPU / 4 GiB, billed whole.
|
|
704
|
+
if (id === "superserve")
|
|
705
|
+
return 2 * pricing.vcpuHour + 4 * pricing.gbHour;
|
|
706
|
+
// InstaBox bills the fixed size that fits.
|
|
707
|
+
if (id === "instabox") {
|
|
708
|
+
const s = instaboxSize(vcpu, mem) ?? INSTABOX_SIZES[INSTABOX_SIZES.length - 1];
|
|
709
|
+
return s.vcpu * pricing.vcpuHour + s.memoryGb * pricing.gbHour;
|
|
710
|
+
}
|
|
711
|
+
// Agent37 publishes total running shapes per 730-hour month, including their default disk.
|
|
712
|
+
if (id === "agent37")
|
|
713
|
+
return (agent37Shape(vcpu, mem) ?? AGENT37_SHAPES[AGENT37_SHAPES.length - 1]).usdMonth / 730;
|
|
714
|
+
if (id === "codesandbox")
|
|
715
|
+
return codesandboxTier(vcpu, mem).usdHour;
|
|
716
|
+
if (id === "koyeb")
|
|
717
|
+
return (koyebInstance(vcpu, mem) ?? KOYEB_INSTANCES[KOYEB_INSTANCES.length - 1]).usdHour;
|
|
718
|
+
if (id === "freestyle")
|
|
719
|
+
return (freestyleSize(vcpu, mem) ?? FREESTYLE_SIZES[FREESTYLE_SIZES.length - 1]).usdHour;
|
|
720
|
+
// Upstash bills active core-hours on the box size that fits; this assumes every core is busy.
|
|
721
|
+
if (id === "upstash")
|
|
722
|
+
return upstashSize(vcpu, mem).vcpu * pricing.vcpuHour;
|
|
723
|
+
// Deno bills CPU time on a fixed 2 vCPU box, with at least 768 MB of memory.
|
|
724
|
+
if (id === "deno")
|
|
725
|
+
return 2 * pricing.vcpuHour + Math.max(mem, 0.75) * pricing.gbHour;
|
|
726
|
+
// LangSmith runs 2 to 6 GiB per vCPU, so a request outside that band is widened.
|
|
727
|
+
if (id === "langsmith") {
|
|
728
|
+
const s = langsmithSize(vcpu, mem);
|
|
729
|
+
return s.vcpu * pricing.vcpuHour + s.memoryGb * pricing.gbHour;
|
|
730
|
+
}
|
|
179
731
|
// Morph bills whole MCUs: the larger of vCPUs and 4 GB blocks of memory.
|
|
180
732
|
if (id === "morph")
|
|
181
733
|
return Math.max(vcpu, Math.ceil(mem / 4)) * pricing.vcpuHour;
|
|
@@ -194,5 +746,8 @@ export function unfit(id, spec, require = []) {
|
|
|
194
746
|
return `max ${p.limits.maxVcpu} vCPU`;
|
|
195
747
|
if ((spec.memoryGb ?? DEFAULT_MEMORY_GB) > p.limits.maxMemoryGb)
|
|
196
748
|
return `max ${p.limits.maxMemoryGb} GB memory`;
|
|
749
|
+
const fixed = fixedSize(id, spec);
|
|
750
|
+
if (fixed && ((spec.vcpu ?? DEFAULT_VCPU) > fixed.vcpu || (spec.memoryGb ?? DEFAULT_MEMORY_GB) > fixed.memoryGb))
|
|
751
|
+
return `default size ${fixed.vcpu} vCPU / ${fixed.memoryGb} GB; more needs image.${id}`;
|
|
197
752
|
return null;
|
|
198
753
|
}
|