sbox-sdk 0.0.2

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 (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -0
  3. package/dist/adapter/index.d.ts +22 -0
  4. package/dist/adapter/index.d.ts.map +1 -0
  5. package/dist/adapter/index.js +16 -0
  6. package/dist/agent-tools/index.d.ts +13 -0
  7. package/dist/agent-tools/index.d.ts.map +1 -0
  8. package/dist/agent-tools/index.js +9 -0
  9. package/dist/agent-tools/policy.d.ts +48 -0
  10. package/dist/agent-tools/policy.d.ts.map +1 -0
  11. package/dist/agent-tools/policy.js +51 -0
  12. package/dist/agent-tools/registry.d.ts +9 -0
  13. package/dist/agent-tools/registry.d.ts.map +1 -0
  14. package/dist/agent-tools/registry.js +412 -0
  15. package/dist/agent-tools/result.d.ts +32 -0
  16. package/dist/agent-tools/result.d.ts.map +1 -0
  17. package/dist/agent-tools/result.js +14 -0
  18. package/dist/agent-tools/types.d.ts +76 -0
  19. package/dist/agent-tools/types.d.ts.map +1 -0
  20. package/dist/agent-tools/types.js +1 -0
  21. package/dist/ai/index.d.ts +36 -0
  22. package/dist/ai/index.d.ts.map +1 -0
  23. package/dist/ai/index.js +40 -0
  24. package/dist/ai-sdk/index.d.ts +31 -0
  25. package/dist/ai-sdk/index.d.ts.map +1 -0
  26. package/dist/ai-sdk/index.js +80 -0
  27. package/dist/anthropic/index.d.ts +42 -0
  28. package/dist/anthropic/index.d.ts.map +1 -0
  29. package/dist/anthropic/index.js +64 -0
  30. package/dist/aws-lambda/index.d.ts +87 -0
  31. package/dist/aws-lambda/index.d.ts.map +1 -0
  32. package/dist/aws-lambda/index.js +290 -0
  33. package/dist/beam/index.d.ts +92 -0
  34. package/dist/beam/index.d.ts.map +1 -0
  35. package/dist/beam/index.js +222 -0
  36. package/dist/blaxel/index.d.ts +125 -0
  37. package/dist/blaxel/index.d.ts.map +1 -0
  38. package/dist/blaxel/index.js +220 -0
  39. package/dist/cli.d.ts +3 -0
  40. package/dist/cli.d.ts.map +1 -0
  41. package/dist/cli.js +249 -0
  42. package/dist/cloudflare/index.d.ts +64 -0
  43. package/dist/cloudflare/index.d.ts.map +1 -0
  44. package/dist/cloudflare/index.js +259 -0
  45. package/dist/codesandbox/index.d.ts +100 -0
  46. package/dist/codesandbox/index.d.ts.map +1 -0
  47. package/dist/codesandbox/index.js +227 -0
  48. package/dist/conformance/index.d.ts +20 -0
  49. package/dist/conformance/index.d.ts.map +1 -0
  50. package/dist/conformance/index.js +189 -0
  51. package/dist/daytona/index.d.ts +64 -0
  52. package/dist/daytona/index.d.ts.map +1 -0
  53. package/dist/daytona/index.js +258 -0
  54. package/dist/e2b/index.d.ts +63 -0
  55. package/dist/e2b/index.d.ts.map +1 -0
  56. package/dist/e2b/index.js +411 -0
  57. package/dist/fly/index.d.ts +75 -0
  58. package/dist/fly/index.d.ts.map +1 -0
  59. package/dist/fly/index.js +222 -0
  60. package/dist/index.d.ts +21 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +16 -0
  63. package/dist/internal/capabilities.d.ts +57 -0
  64. package/dist/internal/capabilities.d.ts.map +1 -0
  65. package/dist/internal/capabilities.js +68 -0
  66. package/dist/internal/client.d.ts +9 -0
  67. package/dist/internal/client.d.ts.map +1 -0
  68. package/dist/internal/client.js +126 -0
  69. package/dist/internal/encoding.d.ts +8 -0
  70. package/dist/internal/encoding.d.ts.map +1 -0
  71. package/dist/internal/encoding.js +20 -0
  72. package/dist/internal/errors.d.ts +45 -0
  73. package/dist/internal/errors.d.ts.map +1 -0
  74. package/dist/internal/errors.js +79 -0
  75. package/dist/internal/exec.d.ts +19 -0
  76. package/dist/internal/exec.d.ts.map +1 -0
  77. package/dist/internal/exec.js +208 -0
  78. package/dist/internal/plugin.d.ts +38 -0
  79. package/dist/internal/plugin.d.ts.map +1 -0
  80. package/dist/internal/plugin.js +1 -0
  81. package/dist/internal/runtime.d.ts +8 -0
  82. package/dist/internal/runtime.d.ts.map +1 -0
  83. package/dist/internal/runtime.js +21 -0
  84. package/dist/internal/sandbox.d.ts +12 -0
  85. package/dist/internal/sandbox.d.ts.map +1 -0
  86. package/dist/internal/sandbox.js +438 -0
  87. package/dist/internal/shell.d.ts +36 -0
  88. package/dist/internal/shell.d.ts.map +1 -0
  89. package/dist/internal/shell.js +88 -0
  90. package/dist/internal/stream.d.ts +15 -0
  91. package/dist/internal/stream.d.ts.map +1 -0
  92. package/dist/internal/stream.js +58 -0
  93. package/dist/internal/types.d.ts +381 -0
  94. package/dist/internal/types.d.ts.map +1 -0
  95. package/dist/internal/types.js +1 -0
  96. package/dist/langchain/index.d.ts +25 -0
  97. package/dist/langchain/index.d.ts.map +1 -0
  98. package/dist/langchain/index.js +61 -0
  99. package/dist/mastra/index.d.ts +43 -0
  100. package/dist/mastra/index.d.ts.map +1 -0
  101. package/dist/mastra/index.js +69 -0
  102. package/dist/memory/index.d.ts +57 -0
  103. package/dist/memory/index.d.ts.map +1 -0
  104. package/dist/memory/index.js +573 -0
  105. package/dist/modal/index.d.ts +67 -0
  106. package/dist/modal/index.d.ts.map +1 -0
  107. package/dist/modal/index.js +223 -0
  108. package/dist/morph/index.d.ts +91 -0
  109. package/dist/morph/index.d.ts.map +1 -0
  110. package/dist/morph/index.js +221 -0
  111. package/dist/northflank/index.d.ts +74 -0
  112. package/dist/northflank/index.d.ts.map +1 -0
  113. package/dist/northflank/index.js +265 -0
  114. package/dist/openai/index.d.ts +25 -0
  115. package/dist/openai/index.d.ts.map +1 -0
  116. package/dist/openai/index.js +71 -0
  117. package/dist/railway/index.d.ts +109 -0
  118. package/dist/railway/index.d.ts.map +1 -0
  119. package/dist/railway/index.js +219 -0
  120. package/dist/runloop/index.d.ts +69 -0
  121. package/dist/runloop/index.d.ts.map +1 -0
  122. package/dist/runloop/index.js +226 -0
  123. package/dist/testing/index.d.ts +44 -0
  124. package/dist/testing/index.d.ts.map +1 -0
  125. package/dist/testing/index.js +61 -0
  126. package/dist/vercel/index.d.ts +63 -0
  127. package/dist/vercel/index.d.ts.map +1 -0
  128. package/dist/vercel/index.js +241 -0
  129. package/package.json +252 -0
  130. package/src/aws-lambda/runner/Dockerfile +15 -0
  131. package/src/aws-lambda/runner/README.md +59 -0
  132. package/src/aws-lambda/runner/server.mjs +91 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * `sbox-sdk/ai-sdk` — Vercel AI SDK adapter. Projects the provider-neutral
3
+ * sandbox tool registry into the AI SDK's `tool()` shape, keyed by tool name so
4
+ * the result drops straight into `generateText({ tools })` / `streamText`.
5
+ *
6
+ * Approval: stable `ai` v5 has no `needsApproval` field on a tool, so the
7
+ * `SandboxPolicy` is enforced inside `execute` — `"deny"` short-circuits with a
8
+ * message the model reads, and `"ask"` awaits `policy.onApprovalRequest` when
9
+ * one is configured (otherwise it proceeds; HITL is opt-in). For AI SDK v7,
10
+ * `toolApproval()` builds the call-site approval map instead.
11
+ *
12
+ * Peer dependency: `ai` (optional).
13
+ */
14
+ import { tool } from "ai";
15
+ import { decide, enforcePolicy } from "../agent-tools/policy.js";
16
+ import { createSandboxTools } from "../agent-tools/registry.js";
17
+ function resolve(source, opts) {
18
+ return Array.isArray(source)
19
+ ? { specs: source }
20
+ : { sandbox: source, specs: createSandboxTools(source, opts) };
21
+ }
22
+ /**
23
+ * Build AI SDK tools from a live sandbox (capability-gated) or a pre-built
24
+ * `ToolSpec[]`. Hand the result to `generateText({ tools })`.
25
+ */
26
+ export function toAISDKTools(source, opts = {}) {
27
+ const { specs, sandbox } = resolve(source, opts);
28
+ const { policy } = opts;
29
+ const tools = {};
30
+ for (const spec of specs) {
31
+ tools[spec.name] = tool({
32
+ description: spec.description,
33
+ execute: async (input, options) => {
34
+ const ctx = { sandbox, signal: options.abortSignal };
35
+ const denied = await enforcePolicy(spec, input, ctx, policy);
36
+ if (denied !== null) {
37
+ return denied;
38
+ }
39
+ const result = await spec.execute(input, ctx);
40
+ return result.text;
41
+ },
42
+ inputSchema: spec.inputSchema,
43
+ });
44
+ }
45
+ return tools;
46
+ }
47
+ /**
48
+ * The Vercel AI SDK framework adapter for the `ai()` plugin:
49
+ *
50
+ * ```ts
51
+ * import { ai } from "sbox-sdk/ai";
52
+ * import { aiSdk } from "sbox-sdk/ai-sdk";
53
+ *
54
+ * const client = createSandboxClient({ provider: e2b(), plugins: [ai({ framework: aiSdk() })] });
55
+ * const sandbox = await client.create();
56
+ * await generateText({ model, prompt, tools: sandbox.tools });
57
+ * ```
58
+ */
59
+ export function aiSdk() {
60
+ return {
61
+ build: (sandbox, opts) => toAISDKTools(sandbox, opts),
62
+ name: "ai-sdk",
63
+ };
64
+ }
65
+ /**
66
+ * AI SDK v7 forward-compat: build the call-site `toolApproval` map
67
+ * (`generateText({ tools, toolApproval })`) from the same policy. Each entry
68
+ * returns `"user-approval"` when the policy says "ask", else `undefined`.
69
+ */
70
+ export function toolApproval(source, opts = {}) {
71
+ const { specs, sandbox } = resolve(source, opts);
72
+ const { policy } = opts;
73
+ const map = {};
74
+ for (const spec of specs) {
75
+ map[spec.name] = async (input) => decide(spec, input, { sandbox }, policy) === "ask"
76
+ ? "user-approval"
77
+ : undefined;
78
+ }
79
+ return map;
80
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `sbox-sdk/anthropic` — Anthropic (Claude) adapter. Projects the
3
+ * provider-neutral sandbox tool registry into the SDK's `betaZodTool()` shape.
4
+ *
5
+ * The returned `BetaRunnableTool[]` serves BOTH Claude tool-use paths, because a
6
+ * `BetaRunnableTool` IS a tool definition (`BetaToolUnion`) plus a `run`/`parse`:
7
+ * • auto-loop — `anthropic.beta.messages.toolRunner({ tools })`
8
+ * • manual loop — `anthropic.beta.messages.create({ tools })`, then on a
9
+ * `tool_use` block: `tool.run(tool.parse(block.input))` -> `tool_result`.
10
+ *
11
+ * Approval: Claude has no native HITL, so the shared `enforcePolicy` runs inside
12
+ * `run` — `"deny"` short-circuits and `"ask"` awaits `policy.onApprovalRequest`
13
+ * (when configured); both return a message Claude reads.
14
+ *
15
+ * Peer dependency: `@anthropic-ai/sdk` (optional).
16
+ */
17
+ import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
18
+ import type { FrameworkAdapter, ToolSetOptions, ToolSpec } from "../agent-tools/types.js";
19
+ import type { Sandbox } from "../internal/types.js";
20
+ export type AnthropicToolOptions = ToolSetOptions;
21
+ /** Array of runnable Claude tools (also valid tool definitions for create()). */
22
+ export type AnthropicToolSet = ReturnType<typeof betaZodTool>[];
23
+ /**
24
+ * Build Claude tools from a live sandbox (capability-gated) or a pre-built
25
+ * `ToolSpec[]`. Pass the result to `anthropic.beta.messages.toolRunner({ tools })`
26
+ * or `anthropic.beta.messages.create({ tools })`.
27
+ */
28
+ export declare function toAnthropicTools(source: Sandbox | ToolSpec[], opts?: AnthropicToolOptions): AnthropicToolSet;
29
+ /**
30
+ * The Anthropic (Claude) framework adapter for the `ai()` plugin:
31
+ *
32
+ * ```ts
33
+ * import { ai } from "sbox-sdk/ai";
34
+ * import { anthropic } from "sbox-sdk/anthropic";
35
+ *
36
+ * const client = createSandboxClient({ provider: e2b(), plugins: [ai({ framework: anthropic() })] });
37
+ * const sandbox = await client.create();
38
+ * const msg = await claude.beta.messages.toolRunner({ model, messages, tools: sandbox.tools });
39
+ * ```
40
+ */
41
+ export declare function anthropic(): FrameworkAdapter<AnthropicToolSet>;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/anthropic/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAIjE,OAAO,KAAK,EACV,gBAAgB,EAEhB,cAAc,EACd,QAAQ,EACT,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,cAAc,CAAC;AAElD,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,EAAE,CAAC;AAahE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE,EAC5B,IAAI,GAAE,oBAAyB,GAC9B,gBAAgB,CAkBlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAK9D"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * `sbox-sdk/anthropic` — Anthropic (Claude) adapter. Projects the
3
+ * provider-neutral sandbox tool registry into the SDK's `betaZodTool()` shape.
4
+ *
5
+ * The returned `BetaRunnableTool[]` serves BOTH Claude tool-use paths, because a
6
+ * `BetaRunnableTool` IS a tool definition (`BetaToolUnion`) plus a `run`/`parse`:
7
+ * • auto-loop — `anthropic.beta.messages.toolRunner({ tools })`
8
+ * • manual loop — `anthropic.beta.messages.create({ tools })`, then on a
9
+ * `tool_use` block: `tool.run(tool.parse(block.input))` -> `tool_result`.
10
+ *
11
+ * Approval: Claude has no native HITL, so the shared `enforcePolicy` runs inside
12
+ * `run` — `"deny"` short-circuits and `"ask"` awaits `policy.onApprovalRequest`
13
+ * (when configured); both return a message Claude reads.
14
+ *
15
+ * Peer dependency: `@anthropic-ai/sdk` (optional).
16
+ */
17
+ import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
18
+ import { enforcePolicy } from "../agent-tools/policy.js";
19
+ import { createSandboxTools } from "../agent-tools/registry.js";
20
+ function resolve(source, opts) {
21
+ return Array.isArray(source)
22
+ ? { specs: source }
23
+ : { sandbox: source, specs: createSandboxTools(source, opts) };
24
+ }
25
+ /**
26
+ * Build Claude tools from a live sandbox (capability-gated) or a pre-built
27
+ * `ToolSpec[]`. Pass the result to `anthropic.beta.messages.toolRunner({ tools })`
28
+ * or `anthropic.beta.messages.create({ tools })`.
29
+ */
30
+ export function toAnthropicTools(source, opts = {}) {
31
+ const { specs, sandbox } = resolve(source, opts);
32
+ const { policy } = opts;
33
+ return specs.map((spec) => betaZodTool({
34
+ description: spec.description,
35
+ inputSchema: spec.inputSchema,
36
+ name: spec.name,
37
+ run: async (args) => {
38
+ const ctx = { sandbox };
39
+ const denied = await enforcePolicy(spec, args, ctx, policy);
40
+ if (denied !== null) {
41
+ return denied;
42
+ }
43
+ return (await spec.execute(args, ctx)).text;
44
+ },
45
+ }));
46
+ }
47
+ /**
48
+ * The Anthropic (Claude) framework adapter for the `ai()` plugin:
49
+ *
50
+ * ```ts
51
+ * import { ai } from "sbox-sdk/ai";
52
+ * import { anthropic } from "sbox-sdk/anthropic";
53
+ *
54
+ * const client = createSandboxClient({ provider: e2b(), plugins: [ai({ framework: anthropic() })] });
55
+ * const sandbox = await client.create();
56
+ * const msg = await claude.beta.messages.toolRunner({ model, messages, tools: sandbox.tools });
57
+ * ```
58
+ */
59
+ export function anthropic() {
60
+ return {
61
+ build: (sandbox, opts) => toAnthropicTools(sandbox, opts),
62
+ name: "anthropic",
63
+ };
64
+ }
@@ -0,0 +1,87 @@
1
+ import type { SandboxProvider } from "../adapter/index.js";
2
+ export interface AwsLambdaOptions {
3
+ /** ARN of the MicroVM image to run (default for create when spec.template is unset). */
4
+ imageIdentifier?: string;
5
+ region?: string;
6
+ credentials?: {
7
+ accessKeyId: string;
8
+ secretAccessKey: string;
9
+ sessionToken?: string;
10
+ };
11
+ /** Runner port inside the MicroVM (default 8080). */
12
+ port?: number;
13
+ /** Base path your runner serves under (default ""). */
14
+ runnerBasePath?: string;
15
+ /** Auth-token lifetime in minutes (default 30). */
16
+ tokenTtlMinutes?: number;
17
+ /** Max running+suspended lifetime in seconds (1–28800). */
18
+ maximumDurationInSeconds?: number;
19
+ executionRoleArn?: string;
20
+ ingressNetworkConnectors?: string[];
21
+ egressNetworkConnectors?: string[];
22
+ /** Override the control-plane client endpoint (testing/localstack). */
23
+ endpoint?: string;
24
+ /** Injectable fetch for the data plane (testing); defaults to globalThis.fetch. */
25
+ fetch?: typeof fetch;
26
+ }
27
+ interface MicrovmRef {
28
+ microvmId: string;
29
+ endpoint: string;
30
+ }
31
+ export declare const AWS_LAMBDA_CAPS: {
32
+ readonly background: "unsupported";
33
+ readonly codeInterpreter: "unsupported";
34
+ readonly egressControl: "unsupported";
35
+ readonly exposePort: "native";
36
+ readonly filesUpload: "native";
37
+ readonly filesWatch: "unsupported";
38
+ readonly fork: "unsupported";
39
+ readonly gpu: "unsupported";
40
+ readonly killProcess: "unsupported";
41
+ readonly list: "native";
42
+ readonly metrics: "unsupported";
43
+ readonly pause: "native";
44
+ readonly privatePreview: "native";
45
+ readonly proxiedFetch: "unsupported";
46
+ readonly pty: "unsupported";
47
+ readonly region: "native";
48
+ readonly secretsVault: "unsupported";
49
+ readonly setTimeout: "unsupported";
50
+ readonly snapshot: "unsupported";
51
+ readonly ssh: "unsupported";
52
+ readonly statefulKernel: "unsupported";
53
+ readonly stdin: "unsupported";
54
+ readonly stop: "unsupported";
55
+ readonly streaming: "emulated";
56
+ readonly volumes: "unsupported";
57
+ };
58
+ export type AwsLambdaCaps = typeof AWS_LAMBDA_CAPS;
59
+ export declare const awsLambda: (opts: AwsLambdaOptions) => SandboxProvider<{
60
+ readonly background: "unsupported";
61
+ readonly codeInterpreter: "unsupported";
62
+ readonly egressControl: "unsupported";
63
+ readonly exposePort: "native";
64
+ readonly filesUpload: "native";
65
+ readonly filesWatch: "unsupported";
66
+ readonly fork: "unsupported";
67
+ readonly gpu: "unsupported";
68
+ readonly killProcess: "unsupported";
69
+ readonly list: "native";
70
+ readonly metrics: "unsupported";
71
+ readonly pause: "native";
72
+ readonly privatePreview: "native";
73
+ readonly proxiedFetch: "unsupported";
74
+ readonly pty: "unsupported";
75
+ readonly region: "native";
76
+ readonly secretsVault: "unsupported";
77
+ readonly setTimeout: "unsupported";
78
+ readonly snapshot: "unsupported";
79
+ readonly ssh: "unsupported";
80
+ readonly statefulKernel: "unsupported";
81
+ readonly stdin: "unsupported";
82
+ readonly stop: "unsupported";
83
+ readonly streaming: "emulated";
84
+ readonly volumes: "unsupported";
85
+ }, MicrovmRef>;
86
+ export {};
87
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aws-lambda/index.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EASV,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,gBAAgB;IAC/B,wFAAwF;IACxF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE;QACZ,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;IACpC,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BM,CAAC;AAEnC,MAAM,MAAM,aAAa,GAAG,OAAO,eAAe,CAAC;AA8DnD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;cA0PpB,CAAC"}
@@ -0,0 +1,290 @@
1
+ /**
2
+ * `sbox-sdk/aws-lambda` — adapter for AWS Lambda MicroVMs (Firecracker-based
3
+ * serverless sandboxes, GA June 2026).
4
+ *
5
+ * Two planes:
6
+ * - CONTROL plane via `@aws-sdk/client-lambda-microvms`: RunMicrovm (launch from
7
+ * a pre-built image ARN) -> {microvmId, endpoint}; CreateMicrovmAuthToken (JWE);
8
+ * Suspend/Resume (preserve memory+disk up to 8h); Terminate; ListMicrovms.
9
+ * - DATA plane via fetch to the microVM's dedicated HTTPS endpoint, with headers
10
+ * `X-aws-proxy-auth` (token) and `X-aws-proxy-port`. AWS does NOT provide a
11
+ * built-in exec/fs API — your image must run an HTTP "runner". This adapter
12
+ * speaks a tiny runner protocol (see ./runner): POST /sbox/exec, /sbox/fs/read,
13
+ * /sbox/fs/write. Bake the reference runner into your MicroVM image.
14
+ *
15
+ * `pause()` = Suspend (memory preserved); `destroy()` = Terminate. `stop()` is
16
+ * unsupported (there is no keep-compute-but-release state in between). Requires
17
+ * the optional peer dependency `@aws-sdk/client-lambda-microvms`.
18
+ */
19
+ import { AsyncQueue, base64ToBytes, bytesToBase64, defineProvider, SandboxError, } from "../adapter/index.js";
20
+ export const AWS_LAMBDA_CAPS = {
21
+ background: "unsupported",
22
+ codeInterpreter: "unsupported",
23
+ egressControl: "unsupported",
24
+ exposePort: "native",
25
+ filesUpload: "native",
26
+ filesWatch: "unsupported",
27
+ fork: "unsupported",
28
+ gpu: "unsupported",
29
+ killProcess: "unsupported",
30
+ list: "native",
31
+ metrics: "unsupported",
32
+ pause: "native",
33
+ privatePreview: "native",
34
+ proxiedFetch: "unsupported",
35
+ pty: "unsupported",
36
+ region: "native",
37
+ secretsVault: "unsupported",
38
+ setTimeout: "unsupported",
39
+ snapshot: "unsupported",
40
+ ssh: "unsupported",
41
+ statefulKernel: "unsupported",
42
+ stdin: "unsupported",
43
+ stop: "unsupported",
44
+ streaming: "emulated",
45
+ volumes: "unsupported",
46
+ };
47
+ const AWS_LAMBDA_FLAGS = {
48
+ exitCodeNative: true,
49
+ perCommandEnvCwd: true, // the runner applies cwd/env per /sbox/exec request
50
+ preservesDiskOnStop: false,
51
+ preservesMemoryOnPause: true, // Suspend preserves memory + disk
52
+ previewModel: "tunnel",
53
+ };
54
+ let cached = null;
55
+ async function loadAws() {
56
+ if (!cached) {
57
+ cached =
58
+ (await import("@aws-sdk/client-lambda-microvms"));
59
+ }
60
+ return cached;
61
+ }
62
+ function mapStatus(s) {
63
+ if (s === 404) {
64
+ return "NotFound";
65
+ }
66
+ if (s === 401 || s === 403) {
67
+ return "Unauthorized";
68
+ }
69
+ if (s === 429) {
70
+ return "QuotaExceeded";
71
+ }
72
+ if (s === 408) {
73
+ return "Timeout";
74
+ }
75
+ return "Provider";
76
+ }
77
+ function mapState(state) {
78
+ switch ((state ?? "").toUpperCase()) {
79
+ case "RUNNING": {
80
+ return "running";
81
+ }
82
+ case "SUSPENDED": {
83
+ return "paused";
84
+ }
85
+ case "PENDING":
86
+ case "STARTING": {
87
+ return "creating";
88
+ }
89
+ case "TERMINATED": {
90
+ return "destroyed";
91
+ }
92
+ default: {
93
+ return "unknown";
94
+ }
95
+ }
96
+ }
97
+ export const awsLambda = defineProvider((opts) => {
98
+ const port = opts.port ?? 8080;
99
+ const runnerBase = opts.runnerBasePath ?? "";
100
+ const fetchImpl = opts.fetch ?? globalThis.fetch;
101
+ let clientP = null;
102
+ const getClient = async () => {
103
+ if (!clientP) {
104
+ clientP = loadAws().then((mod) => new mod.LambdaMicrovmsClient({
105
+ region: opts.region,
106
+ credentials: opts.credentials,
107
+ endpoint: opts.endpoint,
108
+ }));
109
+ }
110
+ return clientP;
111
+ };
112
+ const mintToken = async (microvmId) => {
113
+ const mod = await loadAws();
114
+ const client = await getClient();
115
+ const res = await client.send(new mod.CreateMicrovmAuthTokenCommand({
116
+ microvmIdentifier: microvmId,
117
+ expirationInMinutes: opts.tokenTtlMinutes ?? 30,
118
+ allowedPorts: [{ allPorts: {} }],
119
+ }));
120
+ const authToken = res.authToken;
121
+ return authToken?.["X-aws-proxy-auth"] ?? "";
122
+ };
123
+ const makeHandle = (ref, initialToken) => {
124
+ let token = initialToken;
125
+ const dp = async (path, body) => {
126
+ const call = () => fetchImpl(`https://${ref.endpoint}${runnerBase}${path}`, {
127
+ method: "POST",
128
+ headers: {
129
+ "x-aws-proxy-auth": token,
130
+ "x-aws-proxy-port": String(port),
131
+ "content-type": "application/json",
132
+ },
133
+ body: JSON.stringify(body),
134
+ });
135
+ let res = await call();
136
+ if (res.status === 401) {
137
+ token = await mintToken(ref.microvmId); // token expired -> refresh once
138
+ res = await call();
139
+ }
140
+ if (res.status === 404) {
141
+ throw new SandboxError("NotFound", `${path} -> 404`, {
142
+ provider: "aws-lambda",
143
+ status: 404,
144
+ });
145
+ }
146
+ if (!res.ok) {
147
+ const text = await res.text().catch(() => "");
148
+ throw new SandboxError(mapStatus(res.status), `aws-lambda ${path} -> ${res.status} ${text}`, {
149
+ provider: "aws-lambda",
150
+ status: res.status,
151
+ retryable: res.status === 429 || res.status >= 500,
152
+ });
153
+ }
154
+ return (await res.json());
155
+ };
156
+ const ctl = async (Command, input) => {
157
+ const mod = (await loadAws());
158
+ const client = await getClient();
159
+ return client.send(new mod[Command](input));
160
+ };
161
+ return {
162
+ id: ref.microvmId,
163
+ raw: ref,
164
+ getInfo() {
165
+ return {
166
+ id: ref.microvmId,
167
+ state: "running",
168
+ provider: "aws-lambda",
169
+ metadata: {},
170
+ raw: ref,
171
+ };
172
+ },
173
+ async destroy() {
174
+ await ctl("TerminateMicrovmCommand", {
175
+ microvmIdentifier: ref.microvmId,
176
+ });
177
+ },
178
+ async pause() {
179
+ await ctl("SuspendMicrovmCommand", {
180
+ microvmIdentifier: ref.microvmId,
181
+ });
182
+ },
183
+ async resume() {
184
+ await ctl("ResumeMicrovmCommand", { microvmIdentifier: ref.microvmId });
185
+ },
186
+ exec(cmd, options) {
187
+ const queue = new AsyncQueue();
188
+ void dp("/sbox/exec", {
189
+ cmd,
190
+ cwd: options.cwd,
191
+ env: options.env,
192
+ timeoutMs: options.timeoutMs,
193
+ })
194
+ .then((r) => {
195
+ if (r.stdout) {
196
+ queue.push({ type: "stdout", data: r.stdout });
197
+ }
198
+ if (r.stderr) {
199
+ queue.push({ type: "stderr", data: r.stderr });
200
+ }
201
+ queue.push({ type: "exit", exitCode: r.exitCode ?? 0 });
202
+ queue.close();
203
+ })
204
+ .catch((error) => queue.fail(error instanceof SandboxError
205
+ ? error
206
+ : SandboxError.wrap(error, "aws-lambda")));
207
+ return {
208
+ pid: Promise.resolve(""),
209
+ async kill() {
210
+ /* buffered runner exec; no kill handle */
211
+ },
212
+ [Symbol.asyncIterator]: () => queue.iterator(),
213
+ };
214
+ },
215
+ async readFile(path) {
216
+ const r = await dp("/sbox/fs/read", {
217
+ path,
218
+ });
219
+ return base64ToBytes(r.contentBase64);
220
+ },
221
+ async writeFile(path, data) {
222
+ await dp("/sbox/fs/write", {
223
+ path,
224
+ contentBase64: bytesToBase64(data),
225
+ });
226
+ },
227
+ exposePort(p) {
228
+ // Single endpoint + port routing via the X-aws-proxy-port header; the JWE
229
+ // token authorizes access. Consumers send both headers.
230
+ return { url: `https://${ref.endpoint}`, port: p, token };
231
+ },
232
+ };
233
+ };
234
+ const provider = {
235
+ name: "aws-lambda",
236
+ capabilities: AWS_LAMBDA_CAPS,
237
+ flags: AWS_LAMBDA_FLAGS,
238
+ async create(spec) {
239
+ const image = spec.template ?? opts.imageIdentifier;
240
+ if (!image) {
241
+ throw new SandboxError("Validation", "aws-lambda requires an image ARN (spec.template or imageIdentifier option)", { provider: "aws-lambda" });
242
+ }
243
+ const mod = await loadAws();
244
+ const client = await getClient();
245
+ const run = await client.send(new mod.RunMicrovmCommand({
246
+ imageIdentifier: image,
247
+ executionRoleArn: opts.executionRoleArn,
248
+ maximumDurationInSeconds: opts.maximumDurationInSeconds ??
249
+ (spec.ttlMs ? Math.ceil(spec.ttlMs / 1000) : undefined),
250
+ ingressNetworkConnectors: opts.ingressNetworkConnectors,
251
+ egressNetworkConnectors: opts.egressNetworkConnectors,
252
+ runHookPayload: spec.env
253
+ ? JSON.stringify({ env: spec.env })
254
+ : undefined,
255
+ }));
256
+ const ref = {
257
+ microvmId: run.microvmId,
258
+ endpoint: run.endpoint,
259
+ };
260
+ return makeHandle(ref, await mintToken(ref.microvmId));
261
+ },
262
+ async connect(id) {
263
+ const mod = await loadAws();
264
+ const client = await getClient();
265
+ const got = await client.send(new mod.GetMicrovmCommand({ microvmIdentifier: id }));
266
+ const ref = {
267
+ microvmId: id,
268
+ endpoint: got.endpoint,
269
+ };
270
+ return makeHandle(ref, await mintToken(id));
271
+ },
272
+ async *list() {
273
+ const mod = await loadAws();
274
+ const client = await getClient();
275
+ const res = await client.send(new mod.ListMicrovmsCommand({}));
276
+ const items = (res.microvms ?? res.items ?? []);
277
+ for (const m of items) {
278
+ const id = m.microvmId ?? m.id ?? "";
279
+ yield {
280
+ id,
281
+ state: mapState(m.state),
282
+ provider: "aws-lambda",
283
+ metadata: {},
284
+ raw: m,
285
+ };
286
+ }
287
+ },
288
+ };
289
+ return provider;
290
+ });
@@ -0,0 +1,92 @@
1
+ import type { SandboxProvider } from "../adapter/index.js";
2
+ export interface BeamOptions {
3
+ /** Beam API token (falls back to the SDK's standard environment). */
4
+ token?: string;
5
+ /** Beam workspace id (falls back to the SDK's standard environment). */
6
+ workspaceId?: string;
7
+ /** Default base image when a spec omits `template`. */
8
+ image?: string;
9
+ /** Default vCPUs for new sandboxes. */
10
+ cpu?: number;
11
+ /** Default memory (e.g. "1Gi") for new sandboxes. */
12
+ memory?: string;
13
+ }
14
+ export declare const BEAM_CAPS: {
15
+ readonly background: "unsupported";
16
+ readonly codeInterpreter: "unsupported";
17
+ readonly egressControl: "unsupported";
18
+ readonly exposePort: "native";
19
+ readonly filesUpload: "native";
20
+ readonly filesWatch: "unsupported";
21
+ readonly fork: "native";
22
+ readonly gpu: "native";
23
+ readonly killProcess: "unsupported";
24
+ readonly list: "unsupported";
25
+ readonly metrics: "unsupported";
26
+ readonly pause: "unsupported";
27
+ readonly privatePreview: "unsupported";
28
+ readonly proxiedFetch: "unsupported";
29
+ readonly pty: "unsupported";
30
+ readonly region: "unsupported";
31
+ readonly secretsVault: "unsupported";
32
+ readonly setTimeout: "native";
33
+ readonly snapshot: "native";
34
+ readonly ssh: "unsupported";
35
+ readonly statefulKernel: "unsupported";
36
+ readonly stdin: "unsupported";
37
+ readonly stop: "unsupported";
38
+ readonly streaming: "emulated";
39
+ readonly volumes: "unsupported";
40
+ };
41
+ export type BeamCaps = typeof BEAM_CAPS;
42
+ interface BeamStream {
43
+ read?(): Promise<string | Uint8Array | null>;
44
+ [Symbol.asyncIterator]?(): AsyncIterator<string | Uint8Array>;
45
+ }
46
+ interface BeamProcess {
47
+ pid?: number;
48
+ stdout?: BeamStream | string;
49
+ stderr?: BeamStream | string;
50
+ wait(): Promise<number>;
51
+ kill(): Promise<void>;
52
+ }
53
+ interface BeamInstance {
54
+ exec(command: string | string[], opts?: {
55
+ cwd?: string;
56
+ env?: Record<string, string>;
57
+ }): Promise<BeamProcess>;
58
+ exposePort(port: number): Promise<string>;
59
+ snapshot(): Promise<string>;
60
+ updateTtl(ttl: number): Promise<void>;
61
+ terminate(): Promise<boolean>;
62
+ sandboxId(): string;
63
+ }
64
+ export declare const beam: (opts: BeamOptions) => SandboxProvider<{
65
+ readonly background: "unsupported";
66
+ readonly codeInterpreter: "unsupported";
67
+ readonly egressControl: "unsupported";
68
+ readonly exposePort: "native";
69
+ readonly filesUpload: "native";
70
+ readonly filesWatch: "unsupported";
71
+ readonly fork: "native";
72
+ readonly gpu: "native";
73
+ readonly killProcess: "unsupported";
74
+ readonly list: "unsupported";
75
+ readonly metrics: "unsupported";
76
+ readonly pause: "unsupported";
77
+ readonly privatePreview: "unsupported";
78
+ readonly proxiedFetch: "unsupported";
79
+ readonly pty: "unsupported";
80
+ readonly region: "unsupported";
81
+ readonly secretsVault: "unsupported";
82
+ readonly setTimeout: "native";
83
+ readonly snapshot: "native";
84
+ readonly ssh: "unsupported";
85
+ readonly statefulKernel: "unsupported";
86
+ readonly stdin: "unsupported";
87
+ readonly stop: "unsupported";
88
+ readonly streaming: "emulated";
89
+ readonly volumes: "unsupported";
90
+ }, BeamInstance>;
91
+ export {};
92
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/beam/index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EASV,eAAe,EAGhB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BY,CAAC;AAEnC,MAAM,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC;AAWxC,UAAU,UAAU;IAClB,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC;IAC7C,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,aAAa,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;CAC/D;AACD,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAC7B,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AACD,UAAU,YAAY;IACpB,IAAI,CACF,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,EAC1B,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACpD,OAAO,CAAC,WAAW,CAAC,CAAC;IACxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,SAAS,IAAI,MAAM,CAAC;CACrB;AAoDD,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;gBAyKhB,CAAC"}