@agent-relay/sandbox 0.1.1 → 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 +292 -10
  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 +55 -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,159 @@
1
+ /**
2
+ * SDK-free capability metadata for the Modal adapter.
3
+ *
4
+ * House rule: a behavioral claim stays `false` until a live probe against the
5
+ * pinned SDK establishes it. "The SDK has a method for it" is not evidence —
6
+ * a method can exist and degrade, and a capability means *reachable through
7
+ * this package's port*, not *present in the vendor surface*.
8
+ */
9
+ export const modalSandboxCapabilities = {
10
+ /**
11
+ * Modal genuinely has server-side label search: `sandboxes.list({ tags })`
12
+ * returns only sandboxes carrying all the given tags, and the adapter routes
13
+ * every lookup through it. That is a real warm-lease implementation, unlike
14
+ * providers where `findAllByLabels` degrades to `[]`.
15
+ *
16
+ * It is nevertheless declared `false` until the live canary proves that a
17
+ * tagged sandbox is actually returned by a tag-filtered list. Promoting it
18
+ * on the strength of a type signature is exactly the inference this field
19
+ * exists to prevent, and `false` fails in the safe direction: the
20
+ * orchestrator declines to rely on warm leases rather than leaking them.
21
+ */
22
+ warmLease: false,
23
+ /**
24
+ * Permanently false, and not pending verification.
25
+ *
26
+ * Modal exposes no stop/start for a Sandbox. `terminate()` is the only
27
+ * lifecycle transition and it is terminal — there is no suspend, resume, or
28
+ * wake. The adapter therefore omits `start`/`stop` entirely rather than
29
+ * shipping no-ops, and this flag records the structural fact for the
30
+ * capability resolver, which cannot see an absent method.
31
+ */
32
+ lifecycle: false,
33
+ };
34
+ /**
35
+ * Bootstrap-plane capabilities. Note this is `RuntimeCapabilities` from
36
+ * `../types.js` — the live in-sandbox plane — and NOT the orchestration-plane
37
+ * `SandboxRuntimeCapabilities`. The two are deliberately distinct.
38
+ */
39
+ export const modalWorkflowCapabilities = {
40
+ /**
41
+ * Modal supports PTY on both `create` and `exec` (`pty: true`, which
42
+ * multiplexes stderr into stdout). This package's port exposes no PTY
43
+ * operation, so it is not reachable here.
44
+ */
45
+ pty: false,
46
+ /**
47
+ * Modal exposes real filesystem snapshots — `snapshotFilesystem()` and
48
+ * `snapshotDirectory(path)`, both returning an `Image` reusable as a create
49
+ * source (30-day default TTL, `ttlMs: null` to retain indefinitely). This
50
+ * package's port exposes no snapshot operation, so the capability is not
51
+ * reachable through it. Documented here so the surface is not lost.
52
+ */
53
+ snapshots: false,
54
+ /** Modal Sandboxes are gVisor-isolated containers with their own filesystem. */
55
+ isolation: "strong",
56
+ /** A sandbox id survives the client: `sandboxes.fromId(id)` re-resolves it. */
57
+ persistentHandle: true,
58
+ /**
59
+ * `exec()` returns live `stdout`/`stderr` as `ReadableStream`s, so Modal can
60
+ * genuinely stream. The adapter drains them to completion to satisfy the
61
+ * port's buffered `RunScriptResult`, and the port exposes no streaming
62
+ * surface, so this is false *for this port* while true of the provider.
63
+ */
64
+ streamingLogs: false,
65
+ };
66
+ /** Nothing promoted yet: no live run has happened. Awaiting credentials. */
67
+ export const modalObservedCapabilities = {
68
+ cleanupVerified: false,
69
+ snapshotCapture: false,
70
+ warmLease: false,
71
+ reattach: false,
72
+ lifecycle: false,
73
+ neverIdle: false,
74
+ lifetimeOverride: false,
75
+ concurrencyCeiling: false,
76
+ };
77
+ /**
78
+ * Cells that are **settled structural facts**, not pending observations.
79
+ *
80
+ * The distinction matters for review: everything else in
81
+ * {@link modalObservedCapabilities} is `false` only because no live run has
82
+ * happened yet and will flip when one does. These two are `false` because the
83
+ * provider cannot do the thing at all, so a future canary must not "promote"
84
+ * them and a future reader must not try to "fix" them.
85
+ */
86
+ export const MODAL_STRUCTURALLY_FALSE = [
87
+ "lifecycle",
88
+ "neverIdle",
89
+ ];
90
+ /**
91
+ * Structured capability modes for the Modal adapter.
92
+ *
93
+ * Every cell below restates, in the type system, something this file already
94
+ * documented in prose. That is the whole reason to fill them in: the booleans
95
+ * above cannot distinguish "Modal cannot do this" from "Modal can, but our port
96
+ * exposes no operation reaching it" from "nobody has checked yet", and this
97
+ * adapter is the one that had to work around that by hand — see
98
+ * {@link MODAL_STRUCTURALLY_FALSE}.
99
+ *
100
+ * Note what is deliberately *not* here: `warmLease` stays a `false` boolean
101
+ * pending the live canary. Modes describe the shape of a capability, not its
102
+ * verification state, so a mode is not a back door for promoting a cell that
103
+ * the house rule keeps unproven.
104
+ */
105
+ export const modalCapabilityModes = {
106
+ /**
107
+ * `buffered`, not `separate-streams`.
108
+ *
109
+ * Modal's `exec()` does return live `stdout`/`stderr` as separate
110
+ * `ReadableStream`s, and `runScript` does hand back separated `stdout` and
111
+ * `stderr` fields. But both streaming members of the union require output to
112
+ * be *streamed live*, and the adapter drains both pipes to completion with
113
+ * `readText()` before it returns anything. Separated-after-the-fact is still
114
+ * buffered. Declaring `separate-streams` would promise callers an incremental
115
+ * channel this port does not have.
116
+ */
117
+ outputStreams: "buffered",
118
+ /**
119
+ * Anything written is lost when the sandbox goes away, and on Modal it always
120
+ * goes away: `terminate()` is the only lifecycle transition and it is
121
+ * terminal. There is no stop/start pair for state to survive across, so
122
+ * `persistent` cannot apply.
123
+ */
124
+ filesystem: "ephemeral",
125
+ /**
126
+ * The structural fact behind `neverIdle: false` in
127
+ * {@link MODAL_STRUCTURALLY_FALSE}, now stated in the type rather than in a
128
+ * hand-maintained list. *Every* Modal Sandbox carries a maximum lifetime —
129
+ * five minutes by default, 24 hours at the ceiling (`MODAL_MAX_LIFETIME_MS`),
130
+ * and the provider terminates it when that elapses. There is no "no deadline"
131
+ * setting, so no live run can ever move this.
132
+ *
133
+ * `deadline` says that on its own; per the union's own note, a provider that
134
+ * always terminates at a deadline cannot offer a never-idle tier, so this
135
+ * needs no separate `unsupported`.
136
+ */
137
+ lifetime: "deadline",
138
+ /**
139
+ * `not-exposed`, emphatically not `unsupported`: Modal supports PTY on both
140
+ * `create` and `exec` (`pty: true`). This package's port declares no PTY
141
+ * operation, so it is unreachable *here*. It moves if someone adds one — and
142
+ * `isPendingEvidence()` correctly reports false for it, because no canary
143
+ * against Modal can change a fact about our own port surface.
144
+ */
145
+ interactive: "not-exposed",
146
+ /**
147
+ * Also `not-exposed`. Modal has real filesystem snapshots —
148
+ * `snapshotFilesystem()` and `snapshotDirectory(path)`, both returning an
149
+ * `Image` reusable as a create source. The port exposes no snapshot
150
+ * operation, so the capability is not reachable through it.
151
+ *
152
+ * This is exactly the cell the absence vocabulary was added to protect:
153
+ * `modalObservedCapabilities.snapshotCapture` is a *pending* observation
154
+ * about the provider, while this is a *settled* fact about our port. A canary
155
+ * may promote that one; it must never promote this one.
156
+ */
157
+ snapshots: "not-exposed",
158
+ };
159
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/modal/capabilities.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,KAAK;IAChB;;;;;;;;OAQG;IACH,SAAS,EAAE,KAAK;CACqC,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC;;;;OAIG;IACH,GAAG,EAAE,KAAK;IACV;;;;;;OAMG;IACH,SAAS,EAAE,KAAK;IAChB,gFAAgF;IAChF,SAAS,EAAE,QAAQ;IACnB,+EAA+E;IAC/E,gBAAgB,EAAE,IAAI;IACtB;;;;;OAKG;IACH,aAAa,EAAE,KAAK;CACkB,CAAC;AAoCzC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,yBAAyB,GAA8B;IAClE,eAAe,EAAE,KAAK;IACtB,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,KAAK;IAChB,gBAAgB,EAAE,KAAK;IACvB,kBAAkB,EAAE,KAAK;CAC1B,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,WAAW;IACX,WAAW;CACsD,CAAC;AAEpE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC;;;;;;;;;;OAUG;IACH,aAAa,EAAE,UAAU;IACzB;;;;;OAKG;IACH,UAAU,EAAE,WAAW;IACvB;;;;;;;;;;;OAWG;IACH,QAAQ,EAAE,UAAU;IACpB;;;;;;OAMG;IACH,WAAW,EAAE,aAAa;IAC1B;;;;;;;;;;OAUG;IACH,SAAS,EAAE,aAAa;CACiB,CAAC"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * SDK-free configuration for the Modal adapter.
3
+ *
4
+ * Nothing in this module imports the vendor SDK, so config can be constructed,
5
+ * validated, and asserted on without pulling in a gRPC stack.
6
+ *
7
+ * Modal's object model is not the one this package's port assumes, and the
8
+ * difference is load-bearing rather than cosmetic:
9
+ *
10
+ * - A Modal Sandbox is **a child of an App**, created from an **Image**.
11
+ * `sandboxes.create(app, image, params)` takes both as required arguments.
12
+ * There is no "just make me a sandbox" entry point, so `appName` and
13
+ * `imageTag` are required here. No default is correct for every consumer,
14
+ * and this package bakes none in.
15
+ * - A Modal Sandbox has a **maximum lifetime**, after which the provider
16
+ * terminates it. The SDK's default is five minutes. That default is a trap
17
+ * for every caller who expects E2B/Daytona semantics, so `maxLifetimeMs` is
18
+ * required and always sent explicitly — see {@link ModalRuntimeOptions.maxLifetimeMs}.
19
+ * - A Modal Sandbox **cannot be stopped and restarted**. `terminate()` is the
20
+ * only lifecycle transition and it is terminal.
21
+ */
22
+ /**
23
+ * Modal credentials. Modal does not use a single bearer key: it authenticates
24
+ * with a token *pair*. Both halves are required, and neither is ever read from
25
+ * ambient process state — credential sourcing belongs to the caller.
26
+ */
27
+ export interface ModalCredentials {
28
+ /** Modal token id, conventionally prefixed `ak-`. */
29
+ tokenId: string;
30
+ /** Modal token secret, conventionally prefixed `as-`. */
31
+ tokenSecret: string;
32
+ }
33
+ /** Compute shape requested for each sandbox. Drives both placement and billing. */
34
+ export interface ModalResourceShape {
35
+ /**
36
+ * Reservation of **physical** CPU cores; may be fractional. Modal counts one
37
+ * physical core as two vCPU, so a "2 vCPU" reference shape is `cpu: 1`.
38
+ * Modal enforces a floor of 0.125 cores per container.
39
+ */
40
+ cpu?: number;
41
+ /** Hard CPU limit in physical cores. Omitted means no limit beyond the reservation. */
42
+ cpuLimit?: number;
43
+ /** Memory reservation in MiB. */
44
+ memoryMiB?: number;
45
+ /** Hard memory limit in MiB. */
46
+ memoryLimitMiB?: number;
47
+ }
48
+ export interface ModalRuntimeOptions {
49
+ /** Modal token pair. Required; never sourced from the environment here. */
50
+ credentials: ModalCredentials;
51
+ /**
52
+ * Name of the Modal App that owns every sandbox this runtime creates.
53
+ * Required: Modal has no appless sandbox, and no app name is universally
54
+ * correct. The adapter resolves it with `apps.fromName(name, {createIfMissing})`.
55
+ */
56
+ appName: string;
57
+ /**
58
+ * Whether the adapter may create `appName` if it does not exist. Defaults to
59
+ * `false`: creating provider-side objects as a side effect of a lookup is the
60
+ * kind of thing a caller should opt into, not discover.
61
+ */
62
+ createAppIfMissing?: boolean;
63
+ /**
64
+ * Registry tag for the sandbox image, e.g. `python:3.13` or a private
65
+ * registry reference. Required for the same reason as `appName`.
66
+ */
67
+ imageTag: string;
68
+ /**
69
+ * Modal environment name. Omitted means the credential's default environment.
70
+ * Set it to scope resources away from `main`.
71
+ */
72
+ environment?: string;
73
+ /** Optional control-plane endpoint override. Omitted uses the SDK's endpoint. */
74
+ endpoint?: string;
75
+ /**
76
+ * Home directory inside the image. Required because it is image-specific and
77
+ * no universal default exists.
78
+ */
79
+ defaultHomeDir: string;
80
+ /** Working directory for the sandbox and for exec'd commands. Defaults to `defaultHomeDir`. */
81
+ workdir?: string;
82
+ /**
83
+ * Prefix identifying resources this runtime is allowed to own. Used both as
84
+ * the sandbox name prefix and as the value of the ownership tag.
85
+ */
86
+ namePrefix: string;
87
+ /**
88
+ * Tag key carrying the ownership marker. Defaults to `agentRelayOwner`.
89
+ *
90
+ * Ownership is enforced through Modal's **server-side tag filter**, not
91
+ * through client-side name matching: `sandboxes.list({ tags })` returns only
92
+ * sandboxes carrying *all* the given tags, so injecting the ownership tag
93
+ * into every lookup makes cross-tenant collision structurally impossible
94
+ * rather than merely unlikely.
95
+ */
96
+ ownerTagKey?: string;
97
+ /**
98
+ * **Maximum sandbox lifetime.** Required, and deliberately so.
99
+ *
100
+ * Modal terminates a sandbox once this elapses, whether or not work is still
101
+ * running, and the SDK's own default is 5 minutes. Every other provider this
102
+ * package adapts treats a sandbox as living until told otherwise, so silently
103
+ * inheriting a 5-minute cap would strand callers' long-running work with no
104
+ * diagnosable cause. Making it required forces the decision into the open.
105
+ *
106
+ * This is NOT a request deadline. For that, see `createTimeoutMs`.
107
+ */
108
+ maxLifetimeMs: number;
109
+ /**
110
+ * Idle timeout in milliseconds — an independent knob from `maxLifetimeMs`.
111
+ * Omitted means Modal applies no idle termination.
112
+ */
113
+ idleTimeoutMs?: number;
114
+ /** Compute shape for each sandbox. Omitted fields fall back to Modal's defaults. */
115
+ resources?: ModalResourceShape;
116
+ /** Cloud provider to place sandboxes on. Omitted lets Modal choose. */
117
+ cloud?: string;
118
+ /** Region(s) to place sandboxes in. Omitted lets Modal choose. */
119
+ regions?: string[];
120
+ /** Block all outbound network access from the sandbox. */
121
+ blockNetwork?: boolean;
122
+ /** Per-request deadline handed to the SDK client. Default 30_000. */
123
+ requestTimeoutMs?: number;
124
+ /** Total deadline for a create call. Default 120_000. */
125
+ createTimeoutMs?: number;
126
+ /** Total deadline for list/get/count calls. Default 30_000. */
127
+ lookupTimeoutMs?: number;
128
+ /** Default deadline for a single exec when the caller does not supply one. Default 120_000. */
129
+ execTimeoutMs?: number;
130
+ /** Deadline for terminate plus its post-condition check. Default 60_000. */
131
+ destroyTimeoutMs?: number;
132
+ /** Deadline for a file upload. Default 60_000. */
133
+ uploadTimeoutMs?: number;
134
+ /** Polling interval for delete verification. Default 500. */
135
+ pollIntervalMs?: number;
136
+ /**
137
+ * Re-check each listed sandbox's tags in-process instead of trusting the
138
+ * server-side filter. Defaults to `true`.
139
+ *
140
+ * `sandboxes.list({ tags })` is documented to return only sandboxes carrying
141
+ * all the requested tags, and this adapter's whole ownership model rests on
142
+ * that. But a filter that is silently ignored, partially applied, or changed
143
+ * by a future release would hand a caller a **foreign sandbox as a warm
144
+ * lease** — strictly worse than returning no lease at all, because the caller
145
+ * would then exec into someone else's container. Until `warmLease` is
146
+ * promoted by a live probe, the filter is an unproven claim, and this adapter
147
+ * does not build ownership on unproven claims.
148
+ *
149
+ * The cost is real and worth stating: unlike providers that return tags
150
+ * inline with the listing, Modal's `Sandbox` object exposes `getTags()` as a
151
+ * separate call, so verification costs **one extra round trip per candidate**.
152
+ * Callers who have measured the filter and accept the risk can set this to
153
+ * `false`; the default errs toward correctness.
154
+ */
155
+ verifyTagsClientSide?: boolean;
156
+ }
157
+ /** Defaults applied by {@link resolveModalRuntimeOptions}. */
158
+ export declare const MODAL_DEFAULTS: {
159
+ readonly ownerTagKey: "agentRelayOwner";
160
+ readonly createAppIfMissing: false;
161
+ readonly verifyTagsClientSide: true;
162
+ readonly requestTimeoutMs: 30000;
163
+ readonly createTimeoutMs: 120000;
164
+ readonly lookupTimeoutMs: 30000;
165
+ readonly execTimeoutMs: 120000;
166
+ readonly destroyTimeoutMs: 60000;
167
+ readonly uploadTimeoutMs: 60000;
168
+ readonly pollIntervalMs: 500;
169
+ };
170
+ /**
171
+ * Modal's documented floor for a CPU reservation. Requesting less is rejected
172
+ * here rather than at the provider, so the failure names the real cause.
173
+ */
174
+ export declare const MODAL_MIN_CPU_CORES = 0.125;
175
+ /**
176
+ * Modal's documented hard ceiling on a sandbox's maximum lifetime: 24 hours.
177
+ *
178
+ * Beyond this the provider offers no continuous-run option at all — its own
179
+ * guidance is to take a filesystem snapshot and restore it into a *new*
180
+ * sandbox. So a request for a longer-lived sandbox is not merely optimistic,
181
+ * it is unsatisfiable, and it fails here rather than at create time.
182
+ */
183
+ export declare const MODAL_MAX_LIFETIME_MS: number;
184
+ /** Config with every optional field resolved. */
185
+ export type ResolvedModalRuntimeOptions = Omit<ModalRuntimeOptions, keyof typeof MODAL_DEFAULTS | "workdir"> & {
186
+ [K in keyof typeof MODAL_DEFAULTS]-?: NonNullable<ModalRuntimeOptions[K]>;
187
+ } & {
188
+ workdir: string;
189
+ };
190
+ /** Validate and normalize caller config. Throws on anything unusable. */
191
+ export declare function resolveModalRuntimeOptions(options: ModalRuntimeOptions): ResolvedModalRuntimeOptions;
192
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/modal/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,WAAW,EAAE,gBAAgB,CAAC;IAE9B;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB,+FAA+F;IAC/F,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;;OAUG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,oFAAoF;IACpF,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAE/B,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAEnB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;;;;;;;;;;;;;;;;OAkBG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,8DAA8D;AAC9D,eAAO,MAAM,cAAc;;;;;;;;;;;CAWjB,CAAC;AAEX;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QAAsB,CAAC;AAEzD,iDAAiD;AACjD,MAAM,MAAM,2BAA2B,GACnC,IAAI,CAAC,mBAAmB,EAAE,MAAM,OAAO,cAAc,GAAG,SAAS,CAAC,GAClE;KAAG,CAAC,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;CAAE,GAC7E;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAyBxB,yEAAyE;AACzE,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,mBAAmB,GAC3B,2BAA2B,CAgK7B"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * SDK-free configuration for the Modal adapter.
3
+ *
4
+ * Nothing in this module imports the vendor SDK, so config can be constructed,
5
+ * validated, and asserted on without pulling in a gRPC stack.
6
+ *
7
+ * Modal's object model is not the one this package's port assumes, and the
8
+ * difference is load-bearing rather than cosmetic:
9
+ *
10
+ * - A Modal Sandbox is **a child of an App**, created from an **Image**.
11
+ * `sandboxes.create(app, image, params)` takes both as required arguments.
12
+ * There is no "just make me a sandbox" entry point, so `appName` and
13
+ * `imageTag` are required here. No default is correct for every consumer,
14
+ * and this package bakes none in.
15
+ * - A Modal Sandbox has a **maximum lifetime**, after which the provider
16
+ * terminates it. The SDK's default is five minutes. That default is a trap
17
+ * for every caller who expects E2B/Daytona semantics, so `maxLifetimeMs` is
18
+ * required and always sent explicitly — see {@link ModalRuntimeOptions.maxLifetimeMs}.
19
+ * - A Modal Sandbox **cannot be stopped and restarted**. `terminate()` is the
20
+ * only lifecycle transition and it is terminal.
21
+ */
22
+ /** Defaults applied by {@link resolveModalRuntimeOptions}. */
23
+ export const MODAL_DEFAULTS = {
24
+ ownerTagKey: "agentRelayOwner",
25
+ createAppIfMissing: false,
26
+ verifyTagsClientSide: true,
27
+ requestTimeoutMs: 30_000,
28
+ createTimeoutMs: 120_000,
29
+ lookupTimeoutMs: 30_000,
30
+ execTimeoutMs: 120_000,
31
+ destroyTimeoutMs: 60_000,
32
+ uploadTimeoutMs: 60_000,
33
+ pollIntervalMs: 500,
34
+ };
35
+ /**
36
+ * Modal's documented floor for a CPU reservation. Requesting less is rejected
37
+ * here rather than at the provider, so the failure names the real cause.
38
+ */
39
+ export const MODAL_MIN_CPU_CORES = 0.125;
40
+ /**
41
+ * Modal's documented hard ceiling on a sandbox's maximum lifetime: 24 hours.
42
+ *
43
+ * Beyond this the provider offers no continuous-run option at all — its own
44
+ * guidance is to take a filesystem snapshot and restore it into a *new*
45
+ * sandbox. So a request for a longer-lived sandbox is not merely optimistic,
46
+ * it is unsatisfiable, and it fails here rather than at create time.
47
+ */
48
+ export const MODAL_MAX_LIFETIME_MS = 24 * 60 * 60 * 1000;
49
+ function requireNonEmpty(value, field) {
50
+ const trimmed = value?.trim();
51
+ if (!trimmed) {
52
+ throw new Error(`ModalRuntime requires a non-empty ${field}`);
53
+ }
54
+ return trimmed;
55
+ }
56
+ /**
57
+ * A positive, finite duration. Non-finite values are rejected rather than
58
+ * coerced: `NaN` propagated into a deadline comparison silently disables the
59
+ * deadline instead of failing, which is the worst of both outcomes.
60
+ */
61
+ function requirePositiveMs(value, fallback, field) {
62
+ const resolved = value ?? fallback;
63
+ if (!Number.isFinite(resolved) || resolved <= 0) {
64
+ throw new Error(`ModalRuntime ${field} must be a finite, positive number of milliseconds; got ${String(value)}`);
65
+ }
66
+ return resolved;
67
+ }
68
+ /** Validate and normalize caller config. Throws on anything unusable. */
69
+ export function resolveModalRuntimeOptions(options) {
70
+ const tokenId = requireNonEmpty(options.credentials?.tokenId, "credentials.tokenId");
71
+ const tokenSecret = requireNonEmpty(options.credentials?.tokenSecret, "credentials.tokenSecret");
72
+ const appName = requireNonEmpty(options.appName, "appName");
73
+ const imageTag = requireNonEmpty(options.imageTag, "imageTag");
74
+ const defaultHomeDir = requireNonEmpty(options.defaultHomeDir, "defaultHomeDir");
75
+ const namePrefix = requireNonEmpty(options.namePrefix, "namePrefix");
76
+ const ownerTagKey = requireNonEmpty(options.ownerTagKey ?? MODAL_DEFAULTS.ownerTagKey, "ownerTagKey");
77
+ // Required and unforgiving: inheriting Modal's 5-minute default silently caps
78
+ // every caller's work.
79
+ if (options.maxLifetimeMs === undefined) {
80
+ throw new Error("ModalRuntime requires an explicit maxLifetimeMs: a Modal Sandbox is terminated by "
81
+ + "the provider once its maximum lifetime elapses, and the SDK default is 5 minutes. "
82
+ + "No default here would be correct for every caller.");
83
+ }
84
+ const maxLifetimeMs = requirePositiveMs(options.maxLifetimeMs, Number.NaN, "maxLifetimeMs");
85
+ if (maxLifetimeMs > MODAL_MAX_LIFETIME_MS) {
86
+ throw new Error(`ModalRuntime maxLifetimeMs (${maxLifetimeMs}) exceeds Modal's documented 24-hour ceiling `
87
+ + `(${MODAL_MAX_LIFETIME_MS}). Modal has no longer-lived sandbox: past 24 hours its own `
88
+ + "guidance is to snapshot the filesystem and restore into a new sandbox.");
89
+ }
90
+ const idleTimeoutMs = options.idleTimeoutMs === undefined
91
+ ? undefined
92
+ : requirePositiveMs(options.idleTimeoutMs, Number.NaN, "idleTimeoutMs");
93
+ if (idleTimeoutMs !== undefined && idleTimeoutMs > maxLifetimeMs) {
94
+ // Not fatal for Modal, but it always means the caller misread one of the
95
+ // two knobs: an idle timeout longer than the hard lifetime can never fire.
96
+ throw new Error(`ModalRuntime idleTimeoutMs (${idleTimeoutMs}) exceeds maxLifetimeMs (${maxLifetimeMs}); `
97
+ + "the idle timeout could never fire before the sandbox is terminated outright");
98
+ }
99
+ const resources = options.resources;
100
+ if (resources?.cpu !== undefined) {
101
+ if (!Number.isFinite(resources.cpu) || resources.cpu < MODAL_MIN_CPU_CORES) {
102
+ throw new Error(`ModalRuntime resources.cpu must be a finite number >= ${MODAL_MIN_CPU_CORES} `
103
+ + `physical cores; got ${String(resources.cpu)}`);
104
+ }
105
+ }
106
+ if (resources?.memoryMiB !== undefined) {
107
+ if (!Number.isFinite(resources.memoryMiB) || resources.memoryMiB <= 0) {
108
+ throw new Error(`ModalRuntime resources.memoryMiB must be a finite, positive number; got ${String(resources.memoryMiB)}`);
109
+ }
110
+ }
111
+ // Hard limits are validated on their own before any comparison with a
112
+ // reservation. Otherwise `cpuLimit: NaN` or `memoryLimitMiB: -1` slips
113
+ // through whenever the matching reservation is omitted, and the failure
114
+ // resurfaces at `sandboxes.create` with a message that no longer names the
115
+ // real cause.
116
+ if (resources?.cpuLimit !== undefined) {
117
+ if (!Number.isFinite(resources.cpuLimit) || resources.cpuLimit < MODAL_MIN_CPU_CORES) {
118
+ throw new Error(`ModalRuntime resources.cpuLimit must be a finite number >= ${MODAL_MIN_CPU_CORES} `
119
+ + `physical cores; got ${String(resources.cpuLimit)}`);
120
+ }
121
+ }
122
+ if (resources?.memoryLimitMiB !== undefined) {
123
+ if (!Number.isFinite(resources.memoryLimitMiB) || resources.memoryLimitMiB <= 0) {
124
+ throw new Error(`ModalRuntime resources.memoryLimitMiB must be a finite, positive number; `
125
+ + `got ${String(resources.memoryLimitMiB)}`);
126
+ }
127
+ }
128
+ if (resources?.cpu !== undefined && resources.cpuLimit !== undefined
129
+ && resources.cpuLimit < resources.cpu) {
130
+ throw new Error(`ModalRuntime resources.cpuLimit (${resources.cpuLimit}) is below resources.cpu (${resources.cpu})`);
131
+ }
132
+ if (resources?.memoryMiB !== undefined && resources.memoryLimitMiB !== undefined
133
+ && resources.memoryLimitMiB < resources.memoryMiB) {
134
+ throw new Error(`ModalRuntime resources.memoryLimitMiB (${resources.memoryLimitMiB}) is below `
135
+ + `resources.memoryMiB (${resources.memoryMiB})`);
136
+ }
137
+ // `blockNetwork` and `regions` are independent Modal parameters: a
138
+ // sandbox can legitimately need outbound-network isolation *and* placement
139
+ // in a specific region for data residency, latency, or capacity reasons.
140
+ // Blocking network access does not make physical placement meaningless.
141
+ return {
142
+ credentials: { tokenId, tokenSecret },
143
+ appName,
144
+ imageTag,
145
+ defaultHomeDir,
146
+ workdir: options.workdir?.trim() || defaultHomeDir,
147
+ namePrefix,
148
+ ownerTagKey,
149
+ createAppIfMissing: options.createAppIfMissing ?? MODAL_DEFAULTS.createAppIfMissing,
150
+ verifyTagsClientSide: options.verifyTagsClientSide
151
+ ?? MODAL_DEFAULTS.verifyTagsClientSide,
152
+ maxLifetimeMs,
153
+ ...(idleTimeoutMs === undefined ? {} : { idleTimeoutMs }),
154
+ ...(options.environment === undefined ? {} : { environment: options.environment }),
155
+ ...(options.endpoint === undefined ? {} : { endpoint: options.endpoint }),
156
+ ...(resources === undefined ? {} : { resources }),
157
+ ...(options.cloud === undefined ? {} : { cloud: options.cloud }),
158
+ ...(options.regions === undefined ? {} : { regions: options.regions }),
159
+ ...(options.blockNetwork === undefined ? {} : { blockNetwork: options.blockNetwork }),
160
+ requestTimeoutMs: requirePositiveMs(options.requestTimeoutMs, MODAL_DEFAULTS.requestTimeoutMs, "requestTimeoutMs"),
161
+ createTimeoutMs: requirePositiveMs(options.createTimeoutMs, MODAL_DEFAULTS.createTimeoutMs, "createTimeoutMs"),
162
+ lookupTimeoutMs: requirePositiveMs(options.lookupTimeoutMs, MODAL_DEFAULTS.lookupTimeoutMs, "lookupTimeoutMs"),
163
+ execTimeoutMs: requirePositiveMs(options.execTimeoutMs, MODAL_DEFAULTS.execTimeoutMs, "execTimeoutMs"),
164
+ destroyTimeoutMs: requirePositiveMs(options.destroyTimeoutMs, MODAL_DEFAULTS.destroyTimeoutMs, "destroyTimeoutMs"),
165
+ uploadTimeoutMs: requirePositiveMs(options.uploadTimeoutMs, MODAL_DEFAULTS.uploadTimeoutMs, "uploadTimeoutMs"),
166
+ pollIntervalMs: requirePositiveMs(options.pollIntervalMs, MODAL_DEFAULTS.pollIntervalMs, "pollIntervalMs"),
167
+ };
168
+ }
169
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/modal/config.ts"],"names":[],"mappings":"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"}