@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
package/README.md CHANGED
@@ -10,10 +10,8 @@ run commands, stream results back, and tear it down.
10
10
  The point of the port is that the orchestration layer holds no provider
11
11
  knowledge. Swapping providers is a change of adapter, not a change of caller.
12
12
 
13
- > **Status: pre-release scaffold.** This repository currently contains the
14
- > package skeleton — build, typecheck, test, and release wiring. The runtime
15
- > adapters and orchestrator land in subsequent changes, and the public API is
16
- > not stable until a `1.0.0` release.
13
+ > **Status: pre-1.0.** The public API may still change before a `1.0.0`
14
+ > release.
17
15
 
18
16
  ## Install
19
17
 
@@ -23,6 +21,47 @@ npm install @agent-relay/sandbox
23
21
 
24
22
  Provider SDKs are peer dependencies: install the one you intend to use. A
25
23
  consumer that only runs local sandboxes does not need a remote provider SDK.
24
+ Adapters for providers that publish no JavaScript SDK speak their HTTP API
25
+ directly and add no dependency at all; they take an injectable `fetch` instead.
26
+
27
+ ### Provider constraints
28
+
29
+ Each adapter inherits its provider SDK's requirements, and they are not all the
30
+ same as this package's:
31
+
32
+ | Adapter | Peer dependency | Requirements beyond this package's |
33
+ | --- | --- | --- |
34
+ | `DaytonaRuntime` | `@daytonaio/sdk` | — |
35
+ | `E2BSandboxRuntime` | `e2b` | — |
36
+ | `MicrosandboxRuntime` | `microsandbox` | **Node.js 22+**, a platform-specific native addon (macOS arm64, Linux x64/arm64, Windows x64/arm64), and — for its `local` backend — hardware virtualization: KVM on Linux, Apple Silicon on macOS, or WHP on Windows 10+ |
37
+ | `LocalSandboxRuntime` | — | A reachable local sandbox service |
38
+
39
+ The package itself keeps a Node 20 floor, because a consumer that never touches
40
+ the microsandbox adapter never loads that SDK: it is imported lazily, at first
41
+ use, and a load failure is reported with the constraint that most often
42
+ explains it.
43
+
44
+ ### Microsandbox capabilities are backend-sensitive
45
+
46
+ `MicrosandboxRuntime.capabilities` is derived from the backend the instance is
47
+ bound to, not reported as a single process-wide constant:
48
+
49
+ | Capability | `local` | `cloud` | Why |
50
+ | --- | --- | --- | --- |
51
+ | `snapshots` | `true` | `false` | A snapshot is a host-local artifact: the installed SDK's typings describe `Snapshot` as an artifact on disk and resolve one under `~/.microsandbox/snapshots/<name>/`. This adapter consumes such an artifact from the calling host and never transfers it, so a create issued against a remote backend has nothing to resolve. Configuring `snapshot` with a cloud backend is refused in the constructor, before any SDK call. |
52
+ | `isolation` | `'strong'` | `'unknown'` | Locally the SDK boots a microVM with its own guest kernel on a virtualization-capable host, and the installed package states that requirement itself, so `'strong'` rests on something checkable here. This adapter observes and measures nothing about the cloud backend's isolation. |
53
+
54
+ Both values describe what this package has **established**, not what any
55
+ provider documents. `'unknown'` is not a synonym for weak and is not a claim
56
+ that the guarantee is missing — it means this package has not established one,
57
+ so a caller that requires a specific guarantee must decide for itself rather
58
+ than read an unverified `'strong'`.
59
+
60
+ Cloud region placement and resource enforcement are likewise not represented as
61
+ measured facts. Custom or published **ports are not supported**: the SDK builder
62
+ exposes `port()`/`portBind()`, but the ports this package targets have no
63
+ public-port surface, so the adapter never calls them and never implies a
64
+ reachable port.
26
65
 
27
66
  ## Design
28
67
 
@@ -40,6 +79,187 @@ is a required argument supplied by the caller. This keeps the package usable
40
79
  outside the environment it was extracted from, and keeps credential handling in
41
80
  the caller where it belongs.
42
81
 
82
+ Each adapter also declares what it genuinely supports rather than what its
83
+ method names imply. `resolveSandboxRuntimeCapabilities` reads that declaration,
84
+ so a caller learns up front whether a provider can reattach to a sandbox by id,
85
+ poll a background command, hand back a still-booting sandbox, or search by
86
+ label — instead of discovering the answer from a failure at run time.
87
+
88
+ ### Daytona restart recovery
89
+
90
+ `DaytonaRuntime.start()` does not trust the provider state transition alone. It
91
+ rehydrates the SDK sandbox and runs a bounded `true` readiness probe after `start`,
92
+ because Daytona can report `STARTED` while its Toolbox exec daemon remains
93
+ unavailable. A healthy restart keeps the same sandbox ID. A failure during that
94
+ rehydration itself (auth, rate limit, or network) is not proof the exec daemon
95
+ is dead, so it is propagated as-is and never triggers a replacement.
96
+
97
+ When the post-start readiness probe fails, the runtime defaults to creating and proving
98
+ a replacement before deleting the unusable sandbox. The returned handle is
99
+ updated in place and can therefore have a new `id`; callers must persist that
100
+ returned ID. The replacement preserves the configured snapshot plus provider
101
+ labels, environment, lifecycle, volume, and network settings, but non-volume
102
+ filesystem changes in the old sandbox are not copied. Stateful callers that
103
+ prefer a hard failure to that trade-off can set `recreateOnFailedStart: false`.
104
+
105
+ ### E2B runtime contract
106
+
107
+ `E2BSandboxRuntime` implements both the outer orchestration port and the live
108
+ `WorkflowRuntime` surface: metadata/state lookup, reattachment, synchronous and
109
+ durable asynchronous execution, upload/download, home-directory resolution,
110
+ pause/resume, and owned-resource teardown. It deliberately does not expose a
111
+ detached-launch method because E2B's public create call waits for a running
112
+ sandbox. Its live capability descriptor likewise reports PTY and streaming logs
113
+ as unsupported because this adapter exposes neither behavior, even though the
114
+ provider SDK has lower-level APIs for them.
115
+
116
+ The adapter applies an explicit sandbox lifetime on create, reconnect, and
117
+ synchronous use; `sandboxLifetimeMs` defaults to the configured asynchronous
118
+ run budget.
119
+
120
+ Synchronous runs always carry an explicit command lifetime cap, because E2B —
121
+ alone among the providers here — applies a 60-second default when the field is
122
+ omitted, while the orchestrator omits `timeoutMs` on most execs. A run without a
123
+ caller timeout therefore uses `syncRunBudgetMs`, which defaults to the
124
+ configured `runBudgetMs` (30 minutes unless set). An explicit caller timeout
125
+ always wins, and is the only thing that extends the sandbox past
126
+ `sandboxLifetimeMs`; the implicit budget never does.
127
+
128
+ Asynchronous session IDs are immutable idempotency keys. A retry
129
+ reconciles the durable admission record with E2B's process list and will not
130
+ erase the session directory or submit another copy. Status is pending only
131
+ while the matching provider process is present. If that process disappears
132
+ without publishing its exit sidecar, status becomes terminal with
133
+ `E2B_ASYNC_PROCESS_LOST_EXIT_CODE` (`255`).
134
+
135
+ ### Daytona wire-supplement
136
+
137
+ Daytona's Sandbox wire response carries two fields — `sandboxClass` (the
138
+ sandbox's class/tier) and `warmPoolId` (set while a sandbox is an unclaimed
139
+ warm-pool member) — that exist on the low-level `@daytona/api-client` DTOs but
140
+ that the vendored `@daytonaio/sdk`'s `Sandbox` class does not copy onto
141
+ itself. `DaytonaRuntime.getWireSupplement(handle)` fetches both directly via
142
+ the SDK's low-level `sandboxApi`, the same reach pattern `runtime.ts` already
143
+ uses for detached create.
144
+
145
+ This is a narrow, deliberately temporary gap, not a fork of the SDK: the
146
+ other fields once suspected missing (`autoDestroyAt`, `autoPauseInterval`,
147
+ `spot`) already ship on the public `Sandbox` class as of `@daytonaio/sdk`
148
+ 0.200.0–0.205.0 — a dependency bump alone covers those. Tracked upstream at
149
+ [daytona/clients#207](https://github.com/daytona/clients/issues/207)
150
+ (precedent: [#192](https://github.com/daytona/clients/pull/192), which added
151
+ `spot` the same way). Retire `src/daytona/wire-supplement.ts` once
152
+ `processSandboxDto()` copies `sandboxClass`/`warmPoolId` and a subsequent SDK
153
+ bump picks that up — `runtime.test.ts`'s `DaytonaRuntime smoke` suite has a
154
+ load-bearing regression test that fails once that happens.
155
+ ### Freestyle runtime contract
156
+
157
+ `FreestyleRuntime` uses an explicit API key, home directory, ownership-name
158
+ prefix, and persistence policy. It never reads ambient credentials. Freestyle
159
+ does not expose labels on VM creation, so label lookup and warm leasing remain
160
+ unsupported; ownership and cleanup are scoped to collision-safe names under the
161
+ configured prefix. Deleted list rows are treated as gone only when the provider
162
+ sets `deleted: true`.
163
+
164
+ The adapter exposes buffered exec, file transfer, reattachment, owned-resource
165
+ listing, and verified deletion. Stop/start methods exist as a conservative
166
+ probe surface, but lifecycle remains undeclared because the live validation
167
+ account could not create a persistent VM. PTY, snapshots, streaming logs, fork,
168
+ and never-idle behavior are likewise not advertised without the required live
169
+ proof through this package's public port.
170
+
171
+ The official SDK is isolated under `src/freestyle/internal/`; public
172
+ configuration and capability metadata do not import vendor types. All create,
173
+ lookup, exec, lifecycle, and deletion operations have explicit deadlines. See
174
+ [the Freestyle adapter notes](./docs/freestyle.md) for dependency provenance,
175
+ provider constraints, and capability evidence.
176
+
177
+ ### Vercel Sandbox runtime contract
178
+
179
+ `VercelSandboxRuntime` takes an explicit token, team id, project id, ownership
180
+ name prefix, and home directory, and passes credentials on every SDK call so the
181
+ vendor's own environment and on-disk OAuth fallbacks can never supply an
182
+ operator's identity.
183
+
184
+ A Vercel sandbox is addressed by its **name**, not an opaque id, so
185
+ `RuntimeHandle.id` carries the name and the configured prefix is a real
186
+ ownership boundary: stop, start, and delete refuse any name outside it.
187
+ `Sandbox.list` supports server-side `namePrefix` and `tags` filters, so label
188
+ lookup is a real search here — but every row is re-checked against the requested
189
+ tags in process, because a server filter that were ever ignored would hand back
190
+ someone else's sandbox as a warm lease. `getById` is implemented over `list`
191
+ rather than `Sandbox.get`, which resumes and bills the sandbox as a side effect.
192
+
193
+ Deletion is verified by absence, and a row that reappears under the same name
194
+ with a different `createdAt` counts as proof our sandbox is gone rather than as
195
+ a survivor. Failed verification retains the registration so cleanup stays
196
+ retryable. `acquire()` returns an `AsyncDisposable` for `await using` scopes.
197
+
198
+ Commands run as `sh -c` with `cwd` and `env` passed through provider fields, so
199
+ no caller value is spliced into a command string. Every operation carries its
200
+ own deadline, under an absolute `retryDeadlineMs` ceiling that spans the SDK's
201
+ internal retries.
202
+
203
+ Warm leasing, lifecycle, PTY, snapshots, streaming logs, fork, and verified
204
+ cleanup are all declared `false` pending live evidence; never-idle is settled
205
+ false, because every Vercel sandbox carries a termination deadline. The official
206
+ SDK is isolated under `src/vercel/internal/`. See
207
+ [the Vercel adapter notes](./docs/vercel.md) for dependency provenance,
208
+ capability evidence, and the active-CPU-versus-wall-clock pricing analysis.
209
+
210
+ Capabilities are also declared structurally. PTY and snapshots resolve to
211
+ `"not-exposed"` — real in the SDK, unreachable through this port, and so not
212
+ something a live probe may promote — while `lifetime` resolves to `"deadline"`,
213
+ the settled reason a Vercel sandbox has no never-idle tier. `filesystem` is
214
+ deliberately left `"unknown"`: durability is per-instance configuration
215
+ (`persistent`), and surviving a stop/resume is the same round trip `lifecycle`
216
+ is still awaiting live proof of.
217
+
218
+ ### Modal runtime contract
219
+
220
+ `ModalRuntime` takes an explicit Modal **token pair** (`tokenId` and
221
+ `tokenSecret` — Modal does not use a single bearer key), an App name, an image
222
+ tag, a home directory, and an ownership-name prefix. It never reads ambient
223
+ credentials or a local Modal profile.
224
+
225
+ A Modal Sandbox is a child of an App, built from an Image, and it has a
226
+ **maximum lifetime after which the provider terminates it** — the SDK's own
227
+ default is five minutes. `maxLifetimeMs` is therefore required configuration and
228
+ is always sent explicitly. `createTimeoutSeconds` on `launch` is a deadline on
229
+ the create call and is deliberately not forwarded to that lifetime.
230
+
231
+ Modal exposes no stop/start for a Sandbox; `terminate` is the only lifecycle
232
+ transition and it is terminal. `start` and `stop` are absent rather than
233
+ no-ops, and `lifecycle` is declared false permanently. Async exec is likewise
234
+ not implemented: Modal cannot re-resolve a running exec by id, so the
235
+ `startScript`/`getScriptStatus`/`getScriptLogs` trio is omitted entirely instead
236
+ of being half-supported.
237
+
238
+ Ownership rides on Modal's native server-side tags rather than on a naming
239
+ convention. Every sandbox carries an ownership tag, every lookup filters on it
240
+ server-side, and reattachment and deletion both re-check it. Warm leasing is
241
+ implemented against that real tag filter but remains undeclared until a live
242
+ probe confirms it. Snapshots, volumes, PTY, and tunnels exist in the provider
243
+ and are documented, but are not advertised because this package's port exposes
244
+ no operation for them.
245
+
246
+ That last distinction is now stated structurally rather than in prose. The
247
+ adapter declares `declaredCapabilityModes`, so PTY and snapshots resolve to
248
+ `"not-exposed"` — a fact about this package's port, which `isPendingEvidence()`
249
+ reports as unmovable — rather than to a bare `false` a later canary might read
250
+ as merely unverified. `lifetime` resolves to `"deadline"`, which is the
251
+ structural reason a Modal sandbox can never be never-idle. Output is
252
+ `"buffered"`: Modal streams, the adapter drains. Warm leasing deliberately gets
253
+ no mode, because modes describe a capability's shape and not its verification
254
+ state.
255
+
256
+ The official SDK is isolated under `src/modal/internal/`, and because that SDK
257
+ speaks gRPC rather than HTTP there is no injectable transport seam; the boundary
258
+ is a structural mirror that is checked at build time instead. All create,
259
+ lookup, exec, upload, and deletion operations have explicit deadlines. See
260
+ [the Modal adapter notes](./docs/modal.md) for dependency provenance, provider
261
+ constraints, cost model, and capability evidence.
262
+
43
263
  ## Development
44
264
 
45
265
  ```bash
@@ -49,7 +269,8 @@ npm run typecheck
49
269
  npm test # node:test
50
270
  ```
51
271
 
52
- Requires Node.js 20 or newer.
272
+ Requires Node.js 20 or newer. The microsandbox adapter's own tests need Node 22+
273
+ to load the real SDK; without it, its SDK-contract checks skip rather than fail.
53
274
 
54
275
  ## Releasing
55
276
 
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Minimal HTTP client for the Agent37 Cloud API.
3
+ *
4
+ * There is no official Agent37 JavaScript SDK to depend on: the only published
5
+ * npm package (`agent37`) is a command-line interface that exposes a `bin`, no
6
+ * library entry point, and no runtime dependencies. So this adapter speaks the
7
+ * documented HTTP contract directly over `fetch`, and takes an injectable
8
+ * `fetch` seam instead of a peer dependency. That is deliberate — an optional
9
+ * peer dependency pointing at a CLI would be a dependency on something that
10
+ * cannot be imported.
11
+ *
12
+ * Agent37 exposes two planes that share one credential but not one header:
13
+ *
14
+ * - the **hosting plane** (`{baseUrl}/v1/instances/...`), authenticated with
15
+ * `Authorization: Bearer <key>`, which creates, lists, execs, and tears down
16
+ * instances; and
17
+ * - the **instance plane** (the `url` an instance object reports),
18
+ * authenticated with `X-Agent37-Key: <key>`, which serves that one
19
+ * instance's filesystem.
20
+ *
21
+ * The instance plane's origin is never constructed here. It is read off the
22
+ * instance object, so no provider hostname is baked into this package.
23
+ */
24
+ /** Response shape this client needs. Structurally satisfied by global `Response`. */
25
+ export type Agent37FetchResponse = {
26
+ readonly ok: boolean;
27
+ readonly status: number;
28
+ text(): Promise<string>;
29
+ arrayBuffer(): Promise<ArrayBuffer>;
30
+ };
31
+ /** Request shape this client sends. Structurally satisfied by global `RequestInit`. */
32
+ export type Agent37FetchInit = {
33
+ method?: string;
34
+ headers?: Record<string, string>;
35
+ body?: string | Uint8Array;
36
+ signal?: AbortSignal;
37
+ };
38
+ /** Injection seam for the transport. Global `fetch` is assignable to this. */
39
+ export type Agent37Fetch = (url: string, init?: Agent37FetchInit) => Promise<Agent37FetchResponse>;
40
+ /**
41
+ * A non-2xx response from either Agent37 plane.
42
+ *
43
+ * `code` is the machine-readable identifier the API documents callers should
44
+ * branch on — never the message text, and never the HTTP status alone, because
45
+ * one status carries several codes (409 is both `try_again` and
46
+ * `instance_limit_reached`).
47
+ */
48
+ export declare class Agent37ApiError extends Error {
49
+ readonly status: number;
50
+ readonly code: string;
51
+ /** Method and path only. Never the query string, body, or any header. */
52
+ readonly request: string;
53
+ readonly retryable: boolean;
54
+ constructor(options: {
55
+ status: number;
56
+ code: string;
57
+ message: string;
58
+ request: string;
59
+ retryable: boolean;
60
+ });
61
+ }
62
+ export type Agent37ClientOptions = {
63
+ /**
64
+ * An `sk_live_` workspace key. Required, and never read from the environment
65
+ * by this package: credential sourcing belongs to the caller.
66
+ */
67
+ apiKey: string;
68
+ /**
69
+ * Origin of the Agent37 hosting API, without a trailing slash — for example
70
+ * the provider's public control plane, or a proxy in front of it. Required:
71
+ * this package ships no endpoint defaults.
72
+ */
73
+ baseUrl: string;
74
+ /** Transport seam. Defaults to the global `fetch`. */
75
+ fetch?: Agent37Fetch;
76
+ /** Total attempts for a retryable failure, including the first. Default 3. */
77
+ maxAttempts?: number;
78
+ /** First backoff step; doubles per attempt. Default 250ms. */
79
+ retryBaseDelayMs?: number;
80
+ /** Sleep seam, so retry backoff is deterministic under test. */
81
+ sleep?: (ms: number) => Promise<void>;
82
+ };
83
+ export declare class Agent37Client {
84
+ private readonly apiKey;
85
+ private readonly baseUrl;
86
+ private readonly fetchImpl;
87
+ private readonly maxAttempts;
88
+ private readonly retryBaseDelayMs;
89
+ private readonly sleep;
90
+ constructor(options: Agent37ClientOptions);
91
+ /** JSON call against the hosting plane (`Authorization: Bearer`). */
92
+ hosting<T>(method: string, path: string, options?: {
93
+ body?: unknown;
94
+ query?: Record<string, string | undefined>;
95
+ timeoutMs?: number;
96
+ }): Promise<T>;
97
+ /** JSON call against one instance's own plane (`X-Agent37-Key`). */
98
+ instance<T>(instanceUrl: string, method: string, path: string, options?: {
99
+ body?: string | Uint8Array;
100
+ contentType?: string;
101
+ query?: Record<string, string | undefined>;
102
+ timeoutMs?: number;
103
+ headers?: Record<string, string>;
104
+ }): Promise<T>;
105
+ /** Byte-stream call against one instance's own plane, for file downloads. */
106
+ instanceBytes(instanceUrl: string, method: string, path: string, options?: {
107
+ query?: Record<string, string | undefined>;
108
+ timeoutMs?: number;
109
+ }): Promise<Uint8Array>;
110
+ private send;
111
+ private buildHeaders;
112
+ }
113
+ /** Exported for tests and for callers that want to mirror the retry policy. */
114
+ export declare function isRetryableAgent37Code(code: string): boolean;
115
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/agent37/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * Minimal HTTP client for the Agent37 Cloud API.
3
+ *
4
+ * There is no official Agent37 JavaScript SDK to depend on: the only published
5
+ * npm package (`agent37`) is a command-line interface that exposes a `bin`, no
6
+ * library entry point, and no runtime dependencies. So this adapter speaks the
7
+ * documented HTTP contract directly over `fetch`, and takes an injectable
8
+ * `fetch` seam instead of a peer dependency. That is deliberate — an optional
9
+ * peer dependency pointing at a CLI would be a dependency on something that
10
+ * cannot be imported.
11
+ *
12
+ * Agent37 exposes two planes that share one credential but not one header:
13
+ *
14
+ * - the **hosting plane** (`{baseUrl}/v1/instances/...`), authenticated with
15
+ * `Authorization: Bearer <key>`, which creates, lists, execs, and tears down
16
+ * instances; and
17
+ * - the **instance plane** (the `url` an instance object reports),
18
+ * authenticated with `X-Agent37-Key: <key>`, which serves that one
19
+ * instance's filesystem.
20
+ *
21
+ * The instance plane's origin is never constructed here. It is read off the
22
+ * instance object, so no provider hostname is baked into this package.
23
+ */
24
+ /**
25
+ * A non-2xx response from either Agent37 plane.
26
+ *
27
+ * `code` is the machine-readable identifier the API documents callers should
28
+ * branch on — never the message text, and never the HTTP status alone, because
29
+ * one status carries several codes (409 is both `try_again` and
30
+ * `instance_limit_reached`).
31
+ */
32
+ export class Agent37ApiError extends Error {
33
+ status;
34
+ code;
35
+ /** Method and path only. Never the query string, body, or any header. */
36
+ request;
37
+ retryable;
38
+ constructor(options) {
39
+ super(`Agent37 ${options.request} failed: ${options.status} ${options.code}: ${options.message}`);
40
+ this.name = "Agent37ApiError";
41
+ this.status = options.status;
42
+ this.code = options.code;
43
+ this.request = options.request;
44
+ this.retryable = options.retryable;
45
+ }
46
+ }
47
+ /**
48
+ * Codes the API documents as safe to retry with backoff.
49
+ *
50
+ * Everything absent from this set is retried never, not "retried cautiously".
51
+ * Two exclusions are load-bearing rather than conservative:
52
+ *
53
+ * - `provisioning_failed` (502) is also what a synchronous `exec` returns when
54
+ * it passes the provider's 280-second command cap. Retrying it would run the
55
+ * caller's command a second time, on an instance where the first copy is
56
+ * still running.
57
+ * - `container_unavailable` (502) means the instance is stopped. Retrying
58
+ * cannot change that; `start` can.
59
+ */
60
+ const RETRYABLE_CODES = new Set([
61
+ // hosting plane
62
+ "no_capacity",
63
+ "try_again",
64
+ // transport plane
65
+ "container_unreachable",
66
+ "upstream_unreachable",
67
+ "host_mesh_not_ready",
68
+ "instance_saturated",
69
+ "wake_timeout",
70
+ "upstream_timeout",
71
+ // agent plane
72
+ "rate_limited",
73
+ ]);
74
+ const DEFAULT_MAX_ATTEMPTS = 3;
75
+ const DEFAULT_RETRY_BASE_DELAY_MS = 250;
76
+ export class Agent37Client {
77
+ apiKey;
78
+ baseUrl;
79
+ fetchImpl;
80
+ maxAttempts;
81
+ retryBaseDelayMs;
82
+ sleep;
83
+ constructor(options) {
84
+ const apiKey = options.apiKey?.trim();
85
+ if (!apiKey) {
86
+ throw new Error("Agent37Client requires a non-empty apiKey");
87
+ }
88
+ const baseUrl = options.baseUrl?.trim();
89
+ if (!baseUrl) {
90
+ throw new Error("Agent37Client requires an explicit baseUrl: this package ships no endpoint defaults");
91
+ }
92
+ this.apiKey = apiKey;
93
+ this.baseUrl = stripTrailingSlash(baseUrl);
94
+ this.fetchImpl = options.fetch ?? globalThis.fetch;
95
+ if (typeof this.fetchImpl !== "function") {
96
+ throw new Error("Agent37Client requires a fetch implementation (none found on globalThis)");
97
+ }
98
+ // Non-finite maxAttempts (NaN, ±Infinity) would poison the retry loop:
99
+ // `attempt >= NaN` is always false, so the throw guard never fires and the
100
+ // loop retries a retryable failure forever. Reject explicitly rather than
101
+ // silently coercing.
102
+ const requestedAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
103
+ if (!Number.isFinite(requestedAttempts)) {
104
+ throw new Error(`Agent37Client maxAttempts must be a finite number; got ${String(options.maxAttempts)}`);
105
+ }
106
+ this.maxAttempts = Math.max(1, Math.floor(requestedAttempts));
107
+ const requestedRetryBase = options.retryBaseDelayMs ?? DEFAULT_RETRY_BASE_DELAY_MS;
108
+ if (!Number.isFinite(requestedRetryBase) || requestedRetryBase < 0) {
109
+ throw new Error(`Agent37Client retryBaseDelayMs must be a finite, non-negative number; got ${String(options.retryBaseDelayMs)}`);
110
+ }
111
+ this.retryBaseDelayMs = requestedRetryBase;
112
+ this.sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
113
+ }
114
+ /** JSON call against the hosting plane (`Authorization: Bearer`). */
115
+ async hosting(method, path, options = {}) {
116
+ const response = await this.send({
117
+ method,
118
+ origin: this.baseUrl,
119
+ path,
120
+ ...(options.query ? { query: options.query } : {}),
121
+ headerStyle: "bearer",
122
+ ...(options.body === undefined
123
+ ? {}
124
+ : { body: JSON.stringify(options.body), contentType: "application/json" }),
125
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
126
+ });
127
+ return (await readJson(response));
128
+ }
129
+ /** JSON call against one instance's own plane (`X-Agent37-Key`). */
130
+ async instance(instanceUrl, method, path, options = {}) {
131
+ const response = await this.send({
132
+ method,
133
+ origin: stripTrailingSlash(instanceUrl),
134
+ path,
135
+ ...(options.query ? { query: options.query } : {}),
136
+ headerStyle: "instance-key",
137
+ ...(options.body === undefined ? {} : { body: options.body }),
138
+ ...(options.contentType === undefined ? {} : { contentType: options.contentType }),
139
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
140
+ ...(options.headers ? { headers: options.headers } : {}),
141
+ });
142
+ return (await readJson(response));
143
+ }
144
+ /** Byte-stream call against one instance's own plane, for file downloads. */
145
+ async instanceBytes(instanceUrl, method, path, options = {}) {
146
+ const response = await this.send({
147
+ method,
148
+ origin: stripTrailingSlash(instanceUrl),
149
+ path,
150
+ ...(options.query ? { query: options.query } : {}),
151
+ headerStyle: "instance-key",
152
+ ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),
153
+ });
154
+ return new Uint8Array(await response.arrayBuffer());
155
+ }
156
+ // --- internals ----------------------------------------------------------
157
+ async send(options) {
158
+ // `request` is what surfaces in errors: method and path, never the query
159
+ // string (it carries filesystem paths) and never a header (it carries the
160
+ // credential).
161
+ const request = `${options.method} ${options.path}`;
162
+ const url = buildUrl(options.origin, options.path, options.query);
163
+ let attempt = 0;
164
+ for (;;) {
165
+ attempt += 1;
166
+ // A thrown transport failure is NOT retried. The outcome of a POST that
167
+ // never returned is unknown, and re-sending it is how one submitted
168
+ // command becomes two. Only a *classified* response is retried, because
169
+ // only then is it known that the server rejected rather than accepted.
170
+ const response = await this.fetchImpl(url, {
171
+ method: options.method,
172
+ headers: this.buildHeaders(options),
173
+ ...(options.body === undefined ? {} : { body: options.body }),
174
+ ...(options.timeoutMs === undefined || options.timeoutMs <= 0
175
+ ? {}
176
+ : { signal: AbortSignal.timeout(options.timeoutMs) }),
177
+ });
178
+ if (response.ok) {
179
+ return response;
180
+ }
181
+ const error = await toApiError(response, request);
182
+ if (!error.retryable || attempt >= this.maxAttempts) {
183
+ throw error;
184
+ }
185
+ await this.sleep(this.retryBaseDelayMs * 2 ** (attempt - 1));
186
+ }
187
+ }
188
+ buildHeaders(options) {
189
+ const headers = { ...(options.headers ?? {}) };
190
+ if (options.headerStyle === "bearer") {
191
+ headers.Authorization = `Bearer ${this.apiKey}`;
192
+ }
193
+ else {
194
+ headers["X-Agent37-Key"] = this.apiKey;
195
+ }
196
+ if (options.contentType) {
197
+ headers["Content-Type"] = options.contentType;
198
+ }
199
+ return headers;
200
+ }
201
+ }
202
+ // --- helpers --------------------------------------------------------------
203
+ function stripTrailingSlash(value) {
204
+ return value.replace(/\/+$/, "");
205
+ }
206
+ function buildUrl(origin, path, query) {
207
+ const params = new URLSearchParams();
208
+ for (const [key, value] of Object.entries(query ?? {})) {
209
+ if (value !== undefined) {
210
+ params.append(key, value);
211
+ }
212
+ }
213
+ const search = params.toString();
214
+ return `${origin}${path}${search ? `?${search}` : ""}`;
215
+ }
216
+ async function readJson(response) {
217
+ const text = await response.text();
218
+ if (!text) {
219
+ return {};
220
+ }
221
+ try {
222
+ return JSON.parse(text);
223
+ }
224
+ catch {
225
+ return {};
226
+ }
227
+ }
228
+ /**
229
+ * Normalize the three documented error envelopes into one error.
230
+ *
231
+ * - hosting/agent plane: `{ "error": { "code", "message", ... } }`
232
+ * - transport plane: `{ "error": "flat_string_code" }`
233
+ * - neither (HTML from a proxy, empty body): synthesize `http_<status>`, which
234
+ * is never in the retryable set, so an unparseable failure fails fast.
235
+ */
236
+ async function toApiError(response, request) {
237
+ let code = `http_${response.status}`;
238
+ let message = "";
239
+ try {
240
+ const parsed = JSON.parse(await response.text());
241
+ const raw = parsed.error;
242
+ if (typeof raw === "string" && raw) {
243
+ code = raw;
244
+ }
245
+ else if (raw && typeof raw === "object") {
246
+ const shaped = raw;
247
+ if (typeof shaped.code === "string" && shaped.code) {
248
+ code = shaped.code;
249
+ }
250
+ if (typeof shaped.message === "string") {
251
+ message = shaped.message;
252
+ }
253
+ }
254
+ }
255
+ catch {
256
+ // Leave the synthesized code in place.
257
+ }
258
+ return new Agent37ApiError({
259
+ status: response.status,
260
+ code,
261
+ message,
262
+ request,
263
+ retryable: RETRYABLE_CODES.has(code),
264
+ });
265
+ }
266
+ /** Exported for tests and for callers that want to mirror the retry policy. */
267
+ export function isRetryableAgent37Code(code) {
268
+ return RETRYABLE_CODES.has(code);
269
+ }
270
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/agent37/client.ts"],"names":[],"mappings":"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"}