@agent-relay/sandbox 0.1.2 → 0.1.3

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 (121) hide show
  1. package/README.md +226 -5
  2. package/dist/agent37/client.d.ts +115 -0
  3. package/dist/agent37/client.d.ts.map +1 -0
  4. package/dist/agent37/client.js +270 -0
  5. package/dist/agent37/client.js.map +1 -0
  6. package/dist/agent37/runtime.d.ts +415 -0
  7. package/dist/agent37/runtime.d.ts.map +1 -0
  8. package/dist/agent37/runtime.js +855 -0
  9. package/dist/agent37/runtime.js.map +1 -0
  10. package/dist/agentcore/bench.d.ts +93 -0
  11. package/dist/agentcore/bench.d.ts.map +1 -0
  12. package/dist/agentcore/bench.js +125 -0
  13. package/dist/agentcore/bench.js.map +1 -0
  14. package/dist/agentcore/capabilities.d.ts +169 -0
  15. package/dist/agentcore/capabilities.d.ts.map +1 -0
  16. package/dist/agentcore/capabilities.js +153 -0
  17. package/dist/agentcore/capabilities.js.map +1 -0
  18. package/dist/agentcore/config.d.ts +156 -0
  19. package/dist/agentcore/config.d.ts.map +1 -0
  20. package/dist/agentcore/config.js +12 -0
  21. package/dist/agentcore/config.js.map +1 -0
  22. package/dist/agentcore/internal/sdk.d.ts +181 -0
  23. package/dist/agentcore/internal/sdk.d.ts.map +1 -0
  24. package/dist/agentcore/internal/sdk.js +223 -0
  25. package/dist/agentcore/internal/sdk.js.map +1 -0
  26. package/dist/agentcore/runtime.d.ts +177 -0
  27. package/dist/agentcore/runtime.d.ts.map +1 -0
  28. package/dist/agentcore/runtime.js +706 -0
  29. package/dist/agentcore/runtime.js.map +1 -0
  30. package/dist/daytona/runtime.d.ts +23 -0
  31. package/dist/daytona/runtime.d.ts.map +1 -1
  32. package/dist/daytona/runtime.js +167 -5
  33. package/dist/daytona/runtime.js.map +1 -1
  34. package/dist/daytona/wire-supplement.d.ts +25 -0
  35. package/dist/daytona/wire-supplement.d.ts.map +1 -0
  36. package/dist/daytona/wire-supplement.js +16 -0
  37. package/dist/daytona/wire-supplement.js.map +1 -0
  38. package/dist/e2b/runtime.d.ts +107 -72
  39. package/dist/e2b/runtime.d.ts.map +1 -1
  40. package/dist/e2b/runtime.js +675 -190
  41. package/dist/e2b/runtime.js.map +1 -1
  42. package/dist/freestyle/capabilities.d.ts +28 -0
  43. package/dist/freestyle/capabilities.d.ts.map +1 -0
  44. package/dist/freestyle/capabilities.js +42 -0
  45. package/dist/freestyle/capabilities.js.map +1 -0
  46. package/dist/freestyle/config.d.ts +36 -0
  47. package/dist/freestyle/config.d.ts.map +1 -0
  48. package/dist/freestyle/config.js +2 -0
  49. package/dist/freestyle/config.js.map +1 -0
  50. package/dist/freestyle/internal/sdk.d.ts +69 -0
  51. package/dist/freestyle/internal/sdk.d.ts.map +1 -0
  52. package/dist/freestyle/internal/sdk.js +19 -0
  53. package/dist/freestyle/internal/sdk.js.map +1 -0
  54. package/dist/freestyle/runtime.d.ts +163 -0
  55. package/dist/freestyle/runtime.d.ts.map +1 -0
  56. package/dist/freestyle/runtime.js +798 -0
  57. package/dist/freestyle/runtime.js.map +1 -0
  58. package/dist/index.d.ts +35 -4
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +16 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/microsandbox/runtime.d.ts +793 -0
  63. package/dist/microsandbox/runtime.d.ts.map +1 -0
  64. package/dist/microsandbox/runtime.js +2303 -0
  65. package/dist/microsandbox/runtime.js.map +1 -0
  66. package/dist/modal/bench.d.ts +199 -0
  67. package/dist/modal/bench.d.ts.map +1 -0
  68. package/dist/modal/bench.js +450 -0
  69. package/dist/modal/bench.js.map +1 -0
  70. package/dist/modal/capabilities.d.ts +180 -0
  71. package/dist/modal/capabilities.d.ts.map +1 -0
  72. package/dist/modal/capabilities.js +159 -0
  73. package/dist/modal/capabilities.js.map +1 -0
  74. package/dist/modal/config.d.ts +192 -0
  75. package/dist/modal/config.d.ts.map +1 -0
  76. package/dist/modal/config.js +169 -0
  77. package/dist/modal/config.js.map +1 -0
  78. package/dist/modal/internal/sdk.d.ts +141 -0
  79. package/dist/modal/internal/sdk.d.ts.map +1 -0
  80. package/dist/modal/internal/sdk.js +51 -0
  81. package/dist/modal/internal/sdk.js.map +1 -0
  82. package/dist/modal/runtime.d.ts +271 -0
  83. package/dist/modal/runtime.d.ts.map +1 -0
  84. package/dist/modal/runtime.js +871 -0
  85. package/dist/modal/runtime.js.map +1 -0
  86. package/dist/mount-script.d.ts +16 -1
  87. package/dist/mount-script.d.ts.map +1 -1
  88. package/dist/mount-script.js +76 -15
  89. package/dist/mount-script.js.map +1 -1
  90. package/dist/orchestrator.d.ts +15 -0
  91. package/dist/orchestrator.d.ts.map +1 -1
  92. package/dist/orchestrator.js +13 -1
  93. package/dist/orchestrator.js.map +1 -1
  94. package/dist/port.d.ts +144 -6
  95. package/dist/port.d.ts.map +1 -1
  96. package/dist/port.js +27 -5
  97. package/dist/port.js.map +1 -1
  98. package/dist/types.d.ts +50 -1
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/vercel/bench.d.ts +169 -0
  101. package/dist/vercel/bench.d.ts.map +1 -0
  102. package/dist/vercel/bench.js +337 -0
  103. package/dist/vercel/bench.js.map +1 -0
  104. package/dist/vercel/capabilities.d.ts +106 -0
  105. package/dist/vercel/capabilities.d.ts.map +1 -0
  106. package/dist/vercel/capabilities.js +128 -0
  107. package/dist/vercel/capabilities.js.map +1 -0
  108. package/dist/vercel/config.d.ts +119 -0
  109. package/dist/vercel/config.d.ts.map +1 -0
  110. package/dist/vercel/config.js +8 -0
  111. package/dist/vercel/config.js.map +1 -0
  112. package/dist/vercel/internal/sdk.d.ts +173 -0
  113. package/dist/vercel/internal/sdk.d.ts.map +1 -0
  114. package/dist/vercel/internal/sdk.js +117 -0
  115. package/dist/vercel/internal/sdk.js.map +1 -0
  116. package/dist/vercel/runtime.d.ts +305 -0
  117. package/dist/vercel/runtime.d.ts.map +1 -0
  118. package/dist/vercel/runtime.js +1169 -0
  119. package/dist/vercel/runtime.js.map +1 -0
  120. package/docs/freestyle.md +110 -0
  121. package/package.json +35 -4
@@ -0,0 +1,141 @@
1
+ /**
2
+ * The only module in this package that imports the Modal SDK.
3
+ *
4
+ * Everything the adapter uses is expressed here as a structural interface, so
5
+ * `runtime.ts` depends on shapes rather than on the vendor package. That
6
+ * matters more for Modal than for a REST provider: the official SDK speaks
7
+ * **gRPC** (`nice-grpc` / `protobufjs` / `cbor-x`), so there is no HTTP layer
8
+ * to intercept and no injectable `fetch` seam of the kind the Agent37 client
9
+ * uses. Structural interfaces plus a factory are the only way to keep the
10
+ * adapter's tests off the wire.
11
+ *
12
+ * Pinned surface: `modal@0.9.0` (modal-labs/libmodal), published 2026-07-09,
13
+ * Apache-2.0.
14
+ * integrity sha512-kCXcdJkhbJorf/q/6T9Wdlg6in9JmRnCNQnV6rVBMyeqNV/iXI6BYk4IzY4cvZ6dbauNeDMjk/Q08cbxvoIaXg==
15
+ * gitHead 79b729fb75abdde51d1130d3a7347416a5da75b6
16
+ * docs https://modal.com/docs/sdk/js/latest/Sandbox
17
+ * The declarations below were read from that release's shipped `index.d.ts`,
18
+ * whose tarball SHA-1 was verified against the registry's `dist.shasum`.
19
+ *
20
+ * The SDK is a `0.x` beta and its own README warns that breaking changes ship
21
+ * in `0.X.0` releases, which is why the peer range is pinned narrowly.
22
+ */
23
+ import type { ResolvedModalRuntimeOptions } from "../config.js";
24
+ /** A Modal App. Opaque: the adapter only ever passes it back to `create`. */
25
+ export interface ModalAppLike {
26
+ readonly appId?: string;
27
+ }
28
+ /** A Modal Image. Opaque: the adapter only ever passes it back to `create`. */
29
+ export interface ModalImageLike {
30
+ readonly imageId?: string;
31
+ }
32
+ /** A drainable output stream. Modal's `ModalReadStream` satisfies this. */
33
+ export interface ModalReadStreamLike {
34
+ readText(): Promise<string>;
35
+ }
36
+ /**
37
+ * A running exec.
38
+ *
39
+ * Note what is *absent*: there is no public way to re-resolve a
40
+ * `ContainerProcess` from an id later. Its `execId` reattach path is marked
41
+ * `@ignore` in the SDK and is not exported. That absence is why this adapter
42
+ * declines to implement the port's async-exec trio — see `runtime.ts`.
43
+ */
44
+ export interface ModalContainerProcessLike {
45
+ readonly stdout: ModalReadStreamLike;
46
+ readonly stderr: ModalReadStreamLike;
47
+ wait(): Promise<number>;
48
+ }
49
+ /** The subset of Modal's `SandboxFilesystem` the adapter uses. */
50
+ export interface ModalFilesystemLike {
51
+ writeBytes(data: Uint8Array, remotePath: string): Promise<void>;
52
+ readBytes(remotePath: string): Promise<Uint8Array>;
53
+ makeDirectory(remotePath: string, options?: {
54
+ createParents?: boolean;
55
+ }): Promise<void>;
56
+ }
57
+ export interface ModalExecParams {
58
+ workdir?: string;
59
+ timeoutMs?: number;
60
+ env?: Record<string, string>;
61
+ stdout?: "pipe" | "ignore";
62
+ stderr?: "pipe" | "ignore";
63
+ }
64
+ /** The subset of Modal's `Sandbox` the adapter uses. */
65
+ export interface ModalSandboxLike {
66
+ readonly sandboxId: string;
67
+ readonly filesystem: ModalFilesystemLike;
68
+ /**
69
+ * Note the signature: Modal takes an **argv array**, not a shell string.
70
+ * The adapter is responsible for wrapping caller commands.
71
+ */
72
+ exec(command: string[], params?: ModalExecParams): Promise<ModalContainerProcessLike>;
73
+ /**
74
+ * Terminate the sandbox. With `{ wait: true }` Modal resolves only once the
75
+ * sandbox has actually finished and returns its exit code — the provider's
76
+ * own verified-gone signal, which the adapter prefers over polling.
77
+ */
78
+ terminate(params?: {
79
+ wait?: boolean;
80
+ }): Promise<number | void>;
81
+ /** `null` while running; the exit code once finished. */
82
+ poll(): Promise<number | null>;
83
+ wait(): Promise<number>;
84
+ setTags(tags: Record<string, string>): Promise<void>;
85
+ getTags(): Promise<Record<string, string>>;
86
+ }
87
+ export interface ModalSandboxCreateParams {
88
+ name?: string;
89
+ tags?: Record<string, string>;
90
+ env?: Record<string, string>;
91
+ command?: string[];
92
+ workdir?: string;
93
+ /** Maximum sandbox lifetime. Modal terminates the sandbox once it elapses. */
94
+ timeoutMs?: number;
95
+ idleTimeoutMs?: number;
96
+ cpu?: number;
97
+ cpuLimit?: number;
98
+ memoryMiB?: number;
99
+ memoryLimitMiB?: number;
100
+ cloud?: string;
101
+ regions?: string[];
102
+ blockNetwork?: boolean;
103
+ }
104
+ export interface ModalSandboxListParams {
105
+ appId?: string;
106
+ tags?: Record<string, string>;
107
+ environment?: string;
108
+ }
109
+ export interface ModalSandboxServiceLike {
110
+ create(app: ModalAppLike, image: ModalImageLike, params?: ModalSandboxCreateParams): Promise<ModalSandboxLike>;
111
+ fromId(sandboxId: string): Promise<ModalSandboxLike>;
112
+ /** Server-side tag filter: yields only sandboxes carrying *all* given tags. */
113
+ list(params?: ModalSandboxListParams): AsyncIterable<ModalSandboxLike>;
114
+ }
115
+ export interface ModalClientLike {
116
+ readonly apps: {
117
+ fromName(name: string, params?: {
118
+ environment?: string;
119
+ createIfMissing?: boolean;
120
+ }): Promise<ModalAppLike>;
121
+ };
122
+ readonly images: {
123
+ fromRegistry(tag: string): ModalImageLike;
124
+ };
125
+ readonly sandboxes: ModalSandboxServiceLike;
126
+ /** Closes the gRPC channel. Not optional in practice: see `runtime.ts`. */
127
+ close(): void;
128
+ }
129
+ /** Injection seam. The adapter never constructs a vendor client directly. */
130
+ export type ModalClientFactory = (options: ResolvedModalRuntimeOptions) => Promise<ModalClientLike> | ModalClientLike;
131
+ /**
132
+ * Construct the official client.
133
+ *
134
+ * Credentials are passed explicitly rather than left to the SDK's ambient
135
+ * resolution (`~/.modal.toml`, `MODAL_TOKEN_*`). The SDK will happily fall back
136
+ * to a developer's local profile if `tokenId`/`tokenSecret` are omitted, which
137
+ * would make this adapter silently use whatever account the host happens to be
138
+ * logged into. Passing both explicitly closes that path.
139
+ */
140
+ export declare function createOfficialModalClient(options: ResolvedModalRuntimeOptions): Promise<ModalClientLike>;
141
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../../src/modal/internal/sdk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The only module in this package that imports the Modal SDK.
3
+ *
4
+ * Everything the adapter uses is expressed here as a structural interface, so
5
+ * `runtime.ts` depends on shapes rather than on the vendor package. That
6
+ * matters more for Modal than for a REST provider: the official SDK speaks
7
+ * **gRPC** (`nice-grpc` / `protobufjs` / `cbor-x`), so there is no HTTP layer
8
+ * to intercept and no injectable `fetch` seam of the kind the Agent37 client
9
+ * uses. Structural interfaces plus a factory are the only way to keep the
10
+ * adapter's tests off the wire.
11
+ *
12
+ * Pinned surface: `modal@0.9.0` (modal-labs/libmodal), published 2026-07-09,
13
+ * Apache-2.0.
14
+ * integrity sha512-kCXcdJkhbJorf/q/6T9Wdlg6in9JmRnCNQnV6rVBMyeqNV/iXI6BYk4IzY4cvZ6dbauNeDMjk/Q08cbxvoIaXg==
15
+ * gitHead 79b729fb75abdde51d1130d3a7347416a5da75b6
16
+ * docs https://modal.com/docs/sdk/js/latest/Sandbox
17
+ * The declarations below were read from that release's shipped `index.d.ts`,
18
+ * whose tarball SHA-1 was verified against the registry's `dist.shasum`.
19
+ *
20
+ * The SDK is a `0.x` beta and its own README warns that breaking changes ship
21
+ * in `0.X.0` releases, which is why the peer range is pinned narrowly.
22
+ */
23
+ /**
24
+ * Construct the official client.
25
+ *
26
+ * Credentials are passed explicitly rather than left to the SDK's ambient
27
+ * resolution (`~/.modal.toml`, `MODAL_TOKEN_*`). The SDK will happily fall back
28
+ * to a developer's local profile if `tokenId`/`tokenSecret` are omitted, which
29
+ * would make this adapter silently use whatever account the host happens to be
30
+ * logged into. Passing both explicitly closes that path.
31
+ */
32
+ export async function createOfficialModalClient(options) {
33
+ const { ModalClient } = await import("modal");
34
+ // Deliberately a *checked* assignment, not an `as unknown as` cast.
35
+ //
36
+ // Every declaration in this module is a hand-written mirror of a vendor type,
37
+ // and the SDK is a 0.x beta that ships breaking changes in minor releases.
38
+ // A blind cast would let the real surface drift away from this mirror and
39
+ // fail at runtime, in production, against a live sandbox. Assigning through
40
+ // the structural type instead makes any drift a build error here, which is
41
+ // the whole reason the boundary exists.
42
+ const client = new ModalClient({
43
+ tokenId: options.credentials.tokenId,
44
+ tokenSecret: options.credentials.tokenSecret,
45
+ timeoutMs: options.requestTimeoutMs,
46
+ ...(options.environment === undefined ? {} : { environment: options.environment }),
47
+ ...(options.endpoint === undefined ? {} : { endpoint: options.endpoint }),
48
+ });
49
+ return client;
50
+ }
51
+ //# sourceMappingURL=sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../../src/modal/internal/sdk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AA6HH;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAAoC;IAEpC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,oEAAoE;IACpE,EAAE;IACF,8EAA8E;IAC9E,2EAA2E;IAC3E,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,wCAAwC;IACxC,MAAM,MAAM,GAAoB,IAAI,WAAW,CAAC;QAC9C,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO;QACpC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,WAAW;QAC5C,SAAS,EAAE,OAAO,CAAC,gBAAgB;QACnC,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAClF,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;KAC1E,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,271 @@
1
+ import { Buffer } from "node:buffer";
2
+ import type { DeclaredSandboxRuntimeCapabilities, RunScriptResult, SandboxCapabilityModes, SandboxCountOptions, SandboxLookupOptions, SandboxRuntime } from "../port.js";
3
+ import type { RuntimeHandle } from "../types.js";
4
+ import { type ModalRuntimeOptions } from "./config.js";
5
+ import { type ModalClientFactory } from "./internal/sdk.js";
6
+ /**
7
+ * Modal sandbox runtime.
8
+ *
9
+ * ## How Modal's model differs, and what this adapter does about it
10
+ *
11
+ * **Sandboxes are children of an App, built from an Image.** `create` takes
12
+ * both, so the runtime resolves one `App` and one `Image` up front and reuses
13
+ * them. Neither has a default; both come from config.
14
+ *
15
+ * **Sandboxes have a maximum lifetime and the SDK default is five minutes.**
16
+ * The provider terminates the sandbox when it elapses, running work included.
17
+ * `maxLifetimeMs` is therefore required config and is always sent explicitly.
18
+ * It is unrelated to any request deadline — see the note on
19
+ * `createTimeoutSeconds` in {@link ModalRuntime.launch}.
20
+ *
21
+ * **Sandboxes cannot be stopped and restarted.** `terminate()` is the only
22
+ * lifecycle transition and it is terminal. `start`/`stop` are absent from this
23
+ * class rather than present as no-ops, and `lifecycle: false` is declared so
24
+ * the capability resolver — which cannot see an absent method — agrees.
25
+ *
26
+ * **Ownership rides on Modal's native, server-side tags.** Every sandbox is
27
+ * created carrying an ownership tag, every lookup filters on it server-side,
28
+ * and every destructive or reattaching operation re-checks it. Collision
29
+ * safety is structural here, not a naming convention.
30
+ *
31
+ * **Async exec is deliberately not implemented.** Modal's `exec` hands back a
32
+ * live `ContainerProcess`, but nothing public re-resolves one from an id after
33
+ * the fact. Implementing `startScript` without a real `getScriptStatus` would
34
+ * let a caller submit a command it could never poll or reap — precisely the
35
+ * failure the port's all-or-nothing `asyncExec` rule exists to prevent. The
36
+ * trio is omitted, so the resolver derives `asyncExec: false`.
37
+ *
38
+ * **V1 `create` is pinned on purpose.** Modal also offers
39
+ * `experimentalCreate` (the V2 backend). V2 sandboxes do not support tags and
40
+ * are not returned by `sandboxes.list()`, which would silently destroy both the
41
+ * ownership model and the cleanup story above. Do not "upgrade" this call.
42
+ */
43
+ export declare class ModalRuntime implements SandboxRuntime {
44
+ readonly id = "modal";
45
+ readonly declaredCapabilities: Partial<DeclaredSandboxRuntimeCapabilities>;
46
+ readonly declaredCapabilityModes: Partial<SandboxCapabilityModes>;
47
+ private readonly options;
48
+ private readonly clientFactory;
49
+ private clientPromise;
50
+ private contextPromise;
51
+ /**
52
+ * Reconciliation tasks that outlive their caller.
53
+ *
54
+ * The only source today is `launch()` racing a `sandboxes.create()` past its
55
+ * client-side deadline: when the deadline fires the create can still complete
56
+ * and hand back a sandbox that would otherwise bill silently. `close()` awaits
57
+ * these before releasing the gRPC channel so that a reconciliation cannot be
58
+ * orphaned by teardown.
59
+ */
60
+ private readonly reconciliations;
61
+ constructor(options: ModalRuntimeOptions & {
62
+ clientFactory?: ModalClientFactory;
63
+ });
64
+ findByLabels(labels: Record<string, string>, options?: SandboxLookupOptions): Promise<RuntimeHandle | null>;
65
+ /**
66
+ * Server-side tag search.
67
+ *
68
+ * Two honesty notes:
69
+ *
70
+ * - Modal's `list` yields sandboxes carrying *at least* the requested tags,
71
+ * so the ownership tag is merged into the filter rather than applied after
72
+ * the fact. A foreign sandbox is never fetched, let alone returned.
73
+ * - Modal's `Sandbox` object carries **no state field**. The only way to
74
+ * learn whether one is running is `poll()`, one round trip each. So state
75
+ * is left `undefined` unless the caller actually asked to filter on it,
76
+ * in which case each candidate costs one extra call. Reporting a guessed
77
+ * state for free would be worse than reporting none.
78
+ */
79
+ findAllByLabels(labels: Record<string, string>, options?: SandboxLookupOptions): Promise<RuntimeHandle[]>;
80
+ countByLabels(labels: Record<string, string>, options?: SandboxCountOptions): Promise<number>;
81
+ /**
82
+ * Re-resolve a sandbox by id.
83
+ *
84
+ * Ownership is re-checked here, not assumed. `fromId` will happily return any
85
+ * sandbox in the workspace, so a caller holding a synthesized or stale id
86
+ * could otherwise reattach to a sandbox belonging to another lane. A foreign
87
+ * sandbox reads as absent (`null`) rather than raising, because "not one of
88
+ * mine" and "not there" are the same answer to this question.
89
+ *
90
+ * Unlike `findAllByLabels`/`countByLabels`, this path is not server-side
91
+ * tag-filtered: Modal's `fromId` accepts no tag argument, so a foreign
92
+ * sandbox is fetched before `isOwned()` can reject it. That costs one extra
93
+ * `getTags()` round trip for a lookup a lane could otherwise have skipped;
94
+ * the trade is deliberate because `fromId` is the only reattach primitive
95
+ * Modal exposes.
96
+ */
97
+ getById(id: string, options?: {
98
+ states?: readonly string[] | null;
99
+ owned?: boolean;
100
+ }): Promise<RuntimeHandle | null>;
101
+ /**
102
+ * Create a sandbox.
103
+ *
104
+ * `createTimeoutSeconds` is a **client-side deadline on this call**. It is
105
+ * deliberately NOT forwarded to Modal's `timeoutMs`, which despite the name
106
+ * is the sandbox's maximum lifetime. Conflating them would make a caller who
107
+ * asked to wait 30 s for provisioning receive a sandbox that self-destructs
108
+ * 30 s later. Lifetime comes from `maxLifetimeMs` config and nowhere else.
109
+ */
110
+ launch(options?: {
111
+ name?: string;
112
+ env?: Record<string, string>;
113
+ labels?: Record<string, string>;
114
+ createTimeoutSeconds?: number;
115
+ }): Promise<RuntimeHandle>;
116
+ /**
117
+ * Terminate a create that outlived its deadline.
118
+ *
119
+ * Runs after `launch()` has already rejected, so the caller has no handle
120
+ * for the sandbox that might still be materialising. Failure modes here are
121
+ * all silent by design: if the create ultimately rejects there is nothing to
122
+ * clean up; if terminate fails there is no caller to raise to. `close()`
123
+ * awaits these before releasing the gRPC channel so a reconciliation cannot
124
+ * be orphaned by teardown.
125
+ */
126
+ private reconcileOrphanedCreate;
127
+ private trackReconciliation;
128
+ /**
129
+ * Terminate a sandbox and verify it is gone.
130
+ *
131
+ * Ownership is checked before the terminate, not after. `destroy` is
132
+ * irreversible, so paying one extra round trip to be certain the sandbox is
133
+ * ours is the correct trade — a mis-routed handle must fail loudly rather
134
+ * than delete another lane's work.
135
+ *
136
+ * Verification prefers Modal's own signal: `terminate({ wait: true })`
137
+ * resolves with an exit code only once the sandbox has actually finished. If
138
+ * the provider resolves without one, the adapter falls back to polling until
139
+ * `poll()` reports a finished sandbox, so `cleanupVerified` never rests on a
140
+ * request merely having been accepted.
141
+ */
142
+ destroy(handle: RuntimeHandle): Promise<void>;
143
+ uploadBundle(handle: RuntimeHandle, options: {
144
+ files: Array<{
145
+ source: string | Buffer;
146
+ destination: string;
147
+ }>;
148
+ }): Promise<void>;
149
+ /**
150
+ * Run a command to completion and return its buffered output.
151
+ *
152
+ * Modal's `exec` takes an **argv array**, not a shell string, so the caller's
153
+ * command is wrapped in `sh -lc`. Without that wrapping every pipeline,
154
+ * redirect, and variable expansion a caller writes would be passed through as
155
+ * a literal argument.
156
+ *
157
+ * stdout, stderr, and the exit code are awaited together. Draining the
158
+ * streams only after `wait()` resolves risks deadlocking against a process
159
+ * that fills a pipe buffer and blocks before exiting.
160
+ */
161
+ runScript(handle: RuntimeHandle, options: {
162
+ command: string;
163
+ sessionId?: string;
164
+ timeoutMs?: number;
165
+ env?: Record<string, string>;
166
+ }): Promise<RunScriptResult>;
167
+ /** Tags every sandbox this runtime creates must carry. */
168
+ private ownerTags;
169
+ /**
170
+ * Merge caller labels with the ownership tag, refusing to let a caller
171
+ * overwrite it. Silently winning that collision either way is a bug: our
172
+ * value would make a foreign sandbox look owned, theirs would make ours
173
+ * invisible to cleanup.
174
+ */
175
+ private buildOwnedTags;
176
+ private buildLookupTags;
177
+ private listParams;
178
+ /**
179
+ * Confirm in-process that a listed sandbox really carries the tags we
180
+ * filtered on.
181
+ *
182
+ * The server-side filter is the mechanism this adapter's ownership rests on,
183
+ * and it has not yet been proven live — `warmLease` is still `false`. A
184
+ * filter that is silently ignored or partially applied would return a foreign
185
+ * sandbox, and handing that back as a warm lease is worse than returning
186
+ * nothing: the caller would exec into another tenant's container. So the
187
+ * claim is re-checked against the sandbox's own tags rather than trusted.
188
+ *
189
+ * Skipped when there is nothing to check, so an unfiltered audit listing
190
+ * (`owned: false` with no labels) does not pay for a round trip that could
191
+ * not reject anything.
192
+ */
193
+ private tagsReallyMatch;
194
+ private isOwned;
195
+ /**
196
+ * Resolve a sandbox by id and prove ownership before returning it.
197
+ *
198
+ * Every write-or-execute path that takes a caller-supplied id must go
199
+ * through this: `fromId` will happily return any sandbox in the workspace,
200
+ * so a stale or synthesized handle would otherwise let a caller reattach to
201
+ * another lane's sandbox and mutate it. `destroy` uses its own resolution
202
+ * because it must also treat an already-absent sandbox as success — the
203
+ * only shape here that is idempotent.
204
+ */
205
+ private ownedSandbox;
206
+ private waitUntilGone;
207
+ private sandboxName;
208
+ private toHandle;
209
+ private deadline;
210
+ private client;
211
+ /**
212
+ * Resolve the App and Image once and reuse them. Both are required by every
213
+ * `create`, neither changes over the runtime's life, and each resolution is
214
+ * a round trip.
215
+ */
216
+ private context;
217
+ /**
218
+ * Release the gRPC channel.
219
+ *
220
+ * Not part of `SandboxRuntime`, but necessary: the SDK holds an open HTTP/2
221
+ * connection, and a Node process that never calls this will not exit on its
222
+ * own. Long-lived hosts can ignore it; short-lived scripts and tests cannot.
223
+ */
224
+ close(): Promise<void>;
225
+ }
226
+ /** A handle that does not carry this runtime's ownership tag. */
227
+ export declare class ModalForeignSandboxError extends Error {
228
+ readonly sandboxId: string;
229
+ readonly expectedOwner: string;
230
+ constructor(sandboxId: string, expectedOwner: string);
231
+ }
232
+ /** A caller label collided with the reserved ownership tag key. */
233
+ export declare class ModalTagCollisionError extends Error {
234
+ readonly tagKey: string;
235
+ constructor(tagKey: string);
236
+ }
237
+ /**
238
+ * An operation exceeded its explicit client-side deadline.
239
+ *
240
+ * Two independent caps bound any Modal call: this per-operation budget, and
241
+ * the SDK's own per-request `requestTimeoutMs`. They fail differently on
242
+ * purpose — the SDK's cap surfaces as a gRPC error from the vendor, this one
243
+ * as `ModalDeadlineExceededError` — so the error *type* already says which
244
+ * fired. The message names the sibling cap anyway, because a reader looking at
245
+ * a timeout usually needs to check both numbers before concluding the network
246
+ * was slow.
247
+ */
248
+ export declare class ModalDeadlineExceededError extends Error {
249
+ readonly operation: string;
250
+ readonly timeoutMs: number;
251
+ /** The SDK's per-request cap, when the runtime knew it. */
252
+ readonly requestTimeoutMs: number | undefined;
253
+ constructor(operation: string, timeoutMs: number, requestTimeoutMs?: number);
254
+ }
255
+ /** Declared capabilities disagree with what this class actually implements. */
256
+ export declare class ModalCapabilityMismatchError extends Error {
257
+ readonly mismatches: readonly string[];
258
+ constructor(mismatches: readonly string[]);
259
+ }
260
+ /**
261
+ * Assert at construction time that every declared capability matches what this
262
+ * class actually implements.
263
+ *
264
+ * The point is to fail on the developer's machine rather than in production.
265
+ * A declaration and an implementation drift apart silently — someone adds a
266
+ * `stop` that no-ops, or flips `warmLease` to true while `findAllByLabels`
267
+ * still returns `[]` — and the orchestrator believes the declaration. Every
268
+ * rule below encodes a way this adapter could lie.
269
+ */
270
+ export declare function reconcileModalCapabilities(runtime: SandboxRuntime): void;
271
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/modal/runtime.ts"],"names":[],"mappings":"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"}