@agent-relay/sandbox 0.1.2 → 0.1.5

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 (161) hide show
  1. package/README.md +247 -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/index.d.ts +5 -0
  7. package/dist/agent37/index.d.ts.map +1 -0
  8. package/dist/agent37/index.js +3 -0
  9. package/dist/agent37/index.js.map +1 -0
  10. package/dist/agent37/runtime.d.ts +415 -0
  11. package/dist/agent37/runtime.d.ts.map +1 -0
  12. package/dist/agent37/runtime.js +855 -0
  13. package/dist/agent37/runtime.js.map +1 -0
  14. package/dist/agentcore/bench.d.ts +93 -0
  15. package/dist/agentcore/bench.d.ts.map +1 -0
  16. package/dist/agentcore/bench.js +125 -0
  17. package/dist/agentcore/bench.js.map +1 -0
  18. package/dist/agentcore/capabilities.d.ts +169 -0
  19. package/dist/agentcore/capabilities.d.ts.map +1 -0
  20. package/dist/agentcore/capabilities.js +153 -0
  21. package/dist/agentcore/capabilities.js.map +1 -0
  22. package/dist/agentcore/config.d.ts +156 -0
  23. package/dist/agentcore/config.d.ts.map +1 -0
  24. package/dist/agentcore/config.js +12 -0
  25. package/dist/agentcore/config.js.map +1 -0
  26. package/dist/agentcore/index.d.ts +6 -0
  27. package/dist/agentcore/index.d.ts.map +1 -0
  28. package/dist/agentcore/index.js +3 -0
  29. package/dist/agentcore/index.js.map +1 -0
  30. package/dist/agentcore/internal/sdk.d.ts +181 -0
  31. package/dist/agentcore/internal/sdk.d.ts.map +1 -0
  32. package/dist/agentcore/internal/sdk.js +223 -0
  33. package/dist/agentcore/internal/sdk.js.map +1 -0
  34. package/dist/agentcore/runtime.d.ts +177 -0
  35. package/dist/agentcore/runtime.d.ts.map +1 -0
  36. package/dist/agentcore/runtime.js +706 -0
  37. package/dist/agentcore/runtime.js.map +1 -0
  38. package/dist/core/index.d.ts +13 -0
  39. package/dist/core/index.d.ts.map +1 -0
  40. package/dist/core/index.js +11 -0
  41. package/dist/core/index.js.map +1 -0
  42. package/dist/daytona/index.d.ts +5 -0
  43. package/dist/daytona/index.d.ts.map +1 -0
  44. package/dist/daytona/index.js +3 -0
  45. package/dist/daytona/index.js.map +1 -0
  46. package/dist/daytona/runtime.d.ts +23 -0
  47. package/dist/daytona/runtime.d.ts.map +1 -1
  48. package/dist/daytona/runtime.js +167 -5
  49. package/dist/daytona/runtime.js.map +1 -1
  50. package/dist/daytona/wire-supplement.d.ts +25 -0
  51. package/dist/daytona/wire-supplement.d.ts.map +1 -0
  52. package/dist/daytona/wire-supplement.js +16 -0
  53. package/dist/daytona/wire-supplement.js.map +1 -0
  54. package/dist/e2b/index.d.ts +3 -0
  55. package/dist/e2b/index.d.ts.map +1 -0
  56. package/dist/e2b/index.js +2 -0
  57. package/dist/e2b/index.js.map +1 -0
  58. package/dist/e2b/runtime.d.ts +107 -72
  59. package/dist/e2b/runtime.d.ts.map +1 -1
  60. package/dist/e2b/runtime.js +675 -190
  61. package/dist/e2b/runtime.js.map +1 -1
  62. package/dist/freestyle/capabilities.d.ts +28 -0
  63. package/dist/freestyle/capabilities.d.ts.map +1 -0
  64. package/dist/freestyle/capabilities.js +42 -0
  65. package/dist/freestyle/capabilities.js.map +1 -0
  66. package/dist/freestyle/config.d.ts +36 -0
  67. package/dist/freestyle/config.d.ts.map +1 -0
  68. package/dist/freestyle/config.js +2 -0
  69. package/dist/freestyle/config.js.map +1 -0
  70. package/dist/freestyle/index.d.ts +6 -0
  71. package/dist/freestyle/index.d.ts.map +1 -0
  72. package/dist/freestyle/index.js +3 -0
  73. package/dist/freestyle/index.js.map +1 -0
  74. package/dist/freestyle/internal/sdk.d.ts +69 -0
  75. package/dist/freestyle/internal/sdk.d.ts.map +1 -0
  76. package/dist/freestyle/internal/sdk.js +19 -0
  77. package/dist/freestyle/internal/sdk.js.map +1 -0
  78. package/dist/freestyle/runtime.d.ts +163 -0
  79. package/dist/freestyle/runtime.d.ts.map +1 -0
  80. package/dist/freestyle/runtime.js +798 -0
  81. package/dist/freestyle/runtime.js.map +1 -0
  82. package/dist/index.d.ts +34 -13
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +19 -10
  85. package/dist/index.js.map +1 -1
  86. package/dist/local/index.d.ts +3 -0
  87. package/dist/local/index.d.ts.map +1 -0
  88. package/dist/local/index.js +2 -0
  89. package/dist/local/index.js.map +1 -0
  90. package/dist/microsandbox/index.d.ts +3 -0
  91. package/dist/microsandbox/index.d.ts.map +1 -0
  92. package/dist/microsandbox/index.js +2 -0
  93. package/dist/microsandbox/index.js.map +1 -0
  94. package/dist/microsandbox/runtime.d.ts +793 -0
  95. package/dist/microsandbox/runtime.d.ts.map +1 -0
  96. package/dist/microsandbox/runtime.js +2303 -0
  97. package/dist/microsandbox/runtime.js.map +1 -0
  98. package/dist/modal/bench.d.ts +199 -0
  99. package/dist/modal/bench.d.ts.map +1 -0
  100. package/dist/modal/bench.js +450 -0
  101. package/dist/modal/bench.js.map +1 -0
  102. package/dist/modal/capabilities.d.ts +180 -0
  103. package/dist/modal/capabilities.d.ts.map +1 -0
  104. package/dist/modal/capabilities.js +159 -0
  105. package/dist/modal/capabilities.js.map +1 -0
  106. package/dist/modal/config.d.ts +192 -0
  107. package/dist/modal/config.d.ts.map +1 -0
  108. package/dist/modal/config.js +169 -0
  109. package/dist/modal/config.js.map +1 -0
  110. package/dist/modal/index.d.ts +9 -0
  111. package/dist/modal/index.d.ts.map +1 -0
  112. package/dist/modal/index.js +5 -0
  113. package/dist/modal/index.js.map +1 -0
  114. package/dist/modal/internal/sdk.d.ts +141 -0
  115. package/dist/modal/internal/sdk.d.ts.map +1 -0
  116. package/dist/modal/internal/sdk.js +51 -0
  117. package/dist/modal/internal/sdk.js.map +1 -0
  118. package/dist/modal/runtime.d.ts +271 -0
  119. package/dist/modal/runtime.d.ts.map +1 -0
  120. package/dist/modal/runtime.js +871 -0
  121. package/dist/modal/runtime.js.map +1 -0
  122. package/dist/mount-script.d.ts +16 -1
  123. package/dist/mount-script.d.ts.map +1 -1
  124. package/dist/mount-script.js +76 -15
  125. package/dist/mount-script.js.map +1 -1
  126. package/dist/orchestrator.d.ts +15 -0
  127. package/dist/orchestrator.d.ts.map +1 -1
  128. package/dist/orchestrator.js +13 -1
  129. package/dist/orchestrator.js.map +1 -1
  130. package/dist/port.d.ts +144 -6
  131. package/dist/port.d.ts.map +1 -1
  132. package/dist/port.js +27 -5
  133. package/dist/port.js.map +1 -1
  134. package/dist/types.d.ts +50 -1
  135. package/dist/types.d.ts.map +1 -1
  136. package/dist/vercel/bench.d.ts +169 -0
  137. package/dist/vercel/bench.d.ts.map +1 -0
  138. package/dist/vercel/bench.js +337 -0
  139. package/dist/vercel/bench.js.map +1 -0
  140. package/dist/vercel/capabilities.d.ts +106 -0
  141. package/dist/vercel/capabilities.d.ts.map +1 -0
  142. package/dist/vercel/capabilities.js +128 -0
  143. package/dist/vercel/capabilities.js.map +1 -0
  144. package/dist/vercel/config.d.ts +119 -0
  145. package/dist/vercel/config.d.ts.map +1 -0
  146. package/dist/vercel/config.js +8 -0
  147. package/dist/vercel/config.js.map +1 -0
  148. package/dist/vercel/index.d.ts +6 -0
  149. package/dist/vercel/index.d.ts.map +1 -0
  150. package/dist/vercel/index.js +3 -0
  151. package/dist/vercel/index.js.map +1 -0
  152. package/dist/vercel/internal/sdk.d.ts +173 -0
  153. package/dist/vercel/internal/sdk.d.ts.map +1 -0
  154. package/dist/vercel/internal/sdk.js +117 -0
  155. package/dist/vercel/internal/sdk.js.map +1 -0
  156. package/dist/vercel/runtime.d.ts +305 -0
  157. package/dist/vercel/runtime.d.ts.map +1 -0
  158. package/dist/vercel/runtime.js +1169 -0
  159. package/dist/vercel/runtime.js.map +1 -0
  160. package/docs/freestyle.md +110 -0
  161. package/package.json +41 -5
@@ -0,0 +1,793 @@
1
+ import { Buffer } from "node:buffer";
2
+ import type { AsyncExecStartResult, AsyncExecStatus, ExecOptions, ExecResult, LaunchOptions, RuntimeCapabilities, RuntimeHandle, WorkflowRuntime } from "../types.js";
3
+ import type { AsyncRunStartResult, AsyncRunStatus, RunScriptResult, SandboxCountOptions, SandboxLookupOptions, SandboxRuntime } from "../port.js";
4
+ /**
5
+ * Admit one async run.
6
+ *
7
+ * Arguments: `$1` command, `$2` run directory, `$3` its parent, `$4` shell.
8
+ *
9
+ * Prints exactly one of:
10
+ * - `ADMITTED <pid>` — this call created the run.
11
+ * - `CLAIMED <pid>` — the session was already admitted for THIS EXACT
12
+ * command, so its existing run is adopted. This is the outcome-unknown
13
+ * case: a submit whose response was lost is retried by the caller and
14
+ * resolves here, without ever starting a second process.
15
+ * - `CONFLICT` — the session is already admitted for a DIFFERENT
16
+ * command (or its record is unreadable). Nothing is started and nothing is
17
+ * overwritten; the caller gets a typed error.
18
+ *
19
+ * @internal Exported only so the protocol tests can execute it under a real
20
+ * `/bin/sh`. Not part of the package's public API.
21
+ */
22
+ export declare const MICROSANDBOX_RUN_ADMIT_SCRIPT: string;
23
+ /**
24
+ * Report one async run's outcome.
25
+ *
26
+ * Argument: `$1` run directory. Prints exactly one of `EXIT <code>`,
27
+ * `RUNNING`, `MISSING`, `UNKNOWN <reason>`, or `LOST <reason>`.
28
+ *
29
+ * The exit file is checked first and again last: the wrapper writes it as its
30
+ * final act, so re-reading after the liveness probe closes the window where a
31
+ * run finishes mid-probe and would otherwise read as lost.
32
+ *
33
+ * LIVENESS IS THREE CHECKS, not one, because each answers a different way of
34
+ * losing a run:
35
+ * - boot id, for "the sandbox restarted underneath it";
36
+ * - `kill -0`, for "the process is gone";
37
+ * - START TIME, for "the pid is alive but it is somebody else's now". Without
38
+ * the third, a recycled pid reports RUNNING forever, which is the one
39
+ * failure a poll loop cannot end on.
40
+ *
41
+ * FALLBACK, stated because it is a real reduction in what the probe can tell
42
+ * apart: when the guest has no procfs, admission records no start time and the
43
+ * probe degrades to boot id + pid liveness — exactly the behaviour before start
44
+ * time existed. The fallback is chosen by the ABSENCE of a recorded start time,
45
+ * never by a failure to read the current one: if a start time was recorded and
46
+ * the current read fails while the pid is alive, the probe emits an explicit
47
+ * UNKNOWN marker. That is neither proof of continued life nor proof of pid
48
+ * reuse, so the adapter turns it into a retryable status-probe error.
49
+ *
50
+ * @internal Exported only for the protocol tests (see above).
51
+ */
52
+ export declare const MICROSANDBOX_RUN_STATUS_SCRIPT: string;
53
+ /**
54
+ * Read one run's captured output.
55
+ *
56
+ * Arguments: `$1` log path, `$2` byte cap. Exits 0 with the last `$2` bytes of
57
+ * the file, or 0 with NO output when the file is genuinely absent; any other
58
+ * failure exits non-zero.
59
+ *
60
+ * THE EXIT CODE IS THE WHOLE POINT. The previous form of this read was
61
+ * `tail -c N path 2>/dev/null || true`, which flattened three different
62
+ * situations — "the run has not written anything yet", "the log is
63
+ * unreadable", and "the guest call failed" — onto the same empty string. Empty
64
+ * output is a legitimate answer for a run that printed nothing, so a caller
65
+ * cannot tell that reading from an unreadable one. Absence is now the ONLY
66
+ * condition that yields empty-and-successful; everything else fails loudly and
67
+ * the adapter raises {@link MicrosandboxLogReadError}.
68
+ *
69
+ * The cap is read as one byte MORE than the caller's limit, so the adapter can
70
+ * see that a longer file exists and report `truncated` rather than handing back
71
+ * a tail that reads like a complete log.
72
+ *
73
+ * @internal Exported only for the protocol tests (see above).
74
+ */
75
+ export declare const MICROSANDBOX_RUN_LOG_SCRIPT: string;
76
+ /** `SandboxStatus` — the SDK's own status vocabulary. */
77
+ export type MicrosandboxStatus = "running" | "stopped" | "crashed" | "draining";
78
+ type MsbExecOutput = {
79
+ readonly code: number;
80
+ readonly success: boolean;
81
+ stdout(): string;
82
+ stderr(): string;
83
+ };
84
+ type MsbExecOptionsBuilder = {
85
+ args(args: string[]): MsbExecOptionsBuilder;
86
+ cwd(cwd: string): MsbExecOptionsBuilder;
87
+ envs(vars: Record<string, string>): MsbExecOptionsBuilder;
88
+ timeout(ms: number): MsbExecOptionsBuilder;
89
+ tty(enabled: boolean): MsbExecOptionsBuilder;
90
+ };
91
+ type MsbFsOps = {
92
+ write(path: string, data: Uint8Array | string): Promise<void>;
93
+ read(path: string): Promise<Uint8Array>;
94
+ readToString(path: string): Promise<string>;
95
+ mkdir(path: string): Promise<void>;
96
+ exists(path: string): Promise<boolean>;
97
+ copyFromHost(hostPath: string, guestPath: string): Promise<void>;
98
+ copyToHost(guestPath: string, hostPath: string): Promise<void>;
99
+ };
100
+ type MsbSandbox = {
101
+ readonly name: string;
102
+ exec(cmd: string, args?: Iterable<string>): Promise<MsbExecOutput>;
103
+ execWith(cmd: string, configure: (b: MsbExecOptionsBuilder) => MsbExecOptionsBuilder): Promise<MsbExecOutput>;
104
+ fs(): MsbFsOps;
105
+ detach?(): Promise<void>;
106
+ };
107
+ type MsbSandboxHandle = {
108
+ readonly name: string;
109
+ readonly status: MicrosandboxStatus;
110
+ readonly createdAt?: Date | null;
111
+ readonly updatedAt?: Date | null;
112
+ connect(): Promise<MsbSandbox>;
113
+ connectWithTimeout(timeoutMs: number): Promise<MsbSandbox>;
114
+ start(): Promise<MsbSandbox>;
115
+ startDetached(): Promise<MsbSandbox>;
116
+ stop(): Promise<void>;
117
+ kill(): Promise<void>;
118
+ remove(): Promise<void>;
119
+ };
120
+ type MsbSandboxPage = {
121
+ sandboxes: MsbSandboxHandle[];
122
+ nextCursor?: string;
123
+ };
124
+ type MsbSandboxListBuilder = {
125
+ limit(limit: number): MsbSandboxListBuilder;
126
+ cursor(cursor: string): MsbSandboxListBuilder;
127
+ labels(labels: Record<string, string>): MsbSandboxListBuilder;
128
+ };
129
+ type MsbSandboxBuilder = {
130
+ image(image: string): MsbSandboxBuilder;
131
+ fromSnapshot(pathOrName: string): MsbSandboxBuilder;
132
+ cpus(n: number): MsbSandboxBuilder;
133
+ memory(mib: number): MsbSandboxBuilder;
134
+ workdir(path: string): MsbSandboxBuilder;
135
+ envs(vars: Record<string, string>): MsbSandboxBuilder;
136
+ labels(labels: Record<string, string>): MsbSandboxBuilder;
137
+ detached(enabled: boolean): MsbSandboxBuilder;
138
+ idleTimeout(secs: number): MsbSandboxBuilder;
139
+ maxDuration(secs: number): MsbSandboxBuilder;
140
+ replace(): MsbSandboxBuilder;
141
+ create(): Promise<MsbSandbox>;
142
+ };
143
+ type MsbSandboxStatics = {
144
+ builder(name: string): MsbSandboxBuilder;
145
+ get(name: string): Promise<MsbSandboxHandle | null>;
146
+ listWith(configure: (b: MsbSandboxListBuilder) => MsbSandboxListBuilder): Promise<MsbSandboxPage>;
147
+ };
148
+ /**
149
+ * The slice of the `microsandbox` module this adapter binds to.
150
+ *
151
+ * Exported so a consumer can supply a double (tests, a proxy that adds
152
+ * tracing) through {@link MicrosandboxRuntimeOptions.sdk} without depending on
153
+ * the SDK's internal type graph.
154
+ */
155
+ export type MicrosandboxSdk = {
156
+ Sandbox: MsbSandboxStatics;
157
+ withDefaultBackend<T>(backend: MicrosandboxBackend, fn: () => Promise<T> | T): Promise<T>;
158
+ };
159
+ /**
160
+ * Backend routing for one runtime instance — mirrors the SDK's
161
+ * `DefaultBackend`.
162
+ *
163
+ * There is deliberately no default: `"local"` would silently run workloads on
164
+ * the caller's host, and a cloud URL is deployment-specific. The API key is
165
+ * accepted here as a value the caller supplies at construction from its own
166
+ * secret store; this package never reads an environment variable, never logs
167
+ * the key, and never writes it to disk.
168
+ */
169
+ export type MicrosandboxBackend = "local" | {
170
+ kind: "cloud";
171
+ /** Hosted API endpoint. Omit to use the SDK's own default endpoint. */
172
+ url?: string;
173
+ apiKey: string;
174
+ } | {
175
+ kind: "cloud";
176
+ profile: string;
177
+ };
178
+ export type MicrosandboxRuntimeOptions = {
179
+ /**
180
+ * Backend this runtime routes every SDK call through. Required: see
181
+ * {@link MicrosandboxBackend}.
182
+ */
183
+ backend: MicrosandboxBackend;
184
+ /**
185
+ * OCI image to boot. Required unless {@link snapshot} is given: images are
186
+ * registry- and consumer-specific, so no default is correct for anyone else.
187
+ */
188
+ image?: string;
189
+ /**
190
+ * Snapshot to boot from instead of an image. Mutually exclusive with
191
+ * {@link image}.
192
+ */
193
+ snapshot?: string;
194
+ /**
195
+ * Home directory inside the guest, reported by `getHomeDir`. Required: it is
196
+ * a property of the image, which this package does not choose.
197
+ */
198
+ homeDir: string;
199
+ /** Default working directory for launched sandboxes. */
200
+ workdir?: string;
201
+ /** vCPU count applied at create time. Omit to accept the image default. */
202
+ cpus?: number;
203
+ /** Guest memory in MiB applied at create time. */
204
+ memoryMiB?: number;
205
+ /** Idle-shutdown budget in seconds, applied at create time. */
206
+ idleTimeoutSeconds?: number;
207
+ /** Hard sandbox lifetime in seconds, applied at create time. */
208
+ maxDurationSeconds?: number;
209
+ /**
210
+ * Replace a same-named sandbox at create time. Defaults to `false`: names are
211
+ * the identity here, so replacing on collision would destroy a sandbox this
212
+ * caller may not own.
213
+ */
214
+ replaceExisting?: boolean;
215
+ /** Prefix for generated sandbox names when the caller supplies none. */
216
+ namePrefix?: string;
217
+ /** Guest directory holding async-run state files. Defaults to `/tmp/microsandbox-run`. */
218
+ runStateDir?: string;
219
+ /** Shell used to interpret command strings. Defaults to `/bin/sh`. */
220
+ shell?: string;
221
+ /** Timeout for `connect` to an already-running sandbox. Defaults to 10s. */
222
+ connectTimeoutMs?: number;
223
+ /**
224
+ * Deadline for a whole label lookup, including every page it drains.
225
+ * Defaults to 10s, and is overridden per call by `options.timeoutMs`.
226
+ */
227
+ lookupTimeoutMs?: number;
228
+ /** Page size used when draining label listings. Defaults to 100. */
229
+ listPageSize?: number;
230
+ /**
231
+ * How long a call may wait for the process-global backend gate before failing
232
+ * with {@link MicrosandboxBackendBusyError}. Defaults to 30s.
233
+ *
234
+ * Only meaningful in a process that drives MORE THAN ONE backend: a process
235
+ * on a single backend shares one open scope and never queues.
236
+ */
237
+ backendQueueTimeoutMs?: number;
238
+ /** Injection seam for tests / a wrapping adapter — defaults to lazy `import("microsandbox")`. */
239
+ sdk?: MicrosandboxSdk;
240
+ /**
241
+ * Called when the reclamation of a late-succeeded create — the one triggered
242
+ * by `MicrosandboxCreateTimeoutError` — could not tear the sandbox down.
243
+ *
244
+ * The reclamation path used to swallow every error silently, on the theory
245
+ * that a leaked microVM is at worst best-effort waste. It is not: a
246
+ * silently swallowed teardown is a leak that no downstream observer can see
247
+ * or bill, which is exactly the failure mode PR #10 was blocked on. Now the
248
+ * silent catch is replaced by this hook, called synchronously with the
249
+ * sandbox NAME (never argv, never a secret) and the underlying error, so
250
+ * consumers can log, page, or re-queue an operator cleanup. The reclamation
251
+ * promise still resolves — the caller of `launch` already has its typed
252
+ * timeout error, and throwing here would produce an unhandled rejection
253
+ * on a promise the caller cannot await.
254
+ *
255
+ * The hook is CALLED SYNCHRONOUSLY inside the reclamation's async catch,
256
+ * so it must not throw or the runtime will emit an unhandled rejection. Any
257
+ * async follow-up (log flush, alert dispatch) should be scheduled by the
258
+ * hook and awaited elsewhere.
259
+ */
260
+ onReclaimFailure?: (sandboxName: string, error: unknown) => void;
261
+ };
262
+ /**
263
+ * A sandbox name exceeded the SDK's 128 UTF-8 byte cap.
264
+ *
265
+ * Raised instead of truncating: the name IS the identity, so a truncated name
266
+ * would collide two distinct sandboxes onto one addressable handle.
267
+ */
268
+ export declare class MicrosandboxNameTooLongError extends Error {
269
+ readonly name = "MicrosandboxNameTooLongError";
270
+ readonly sandboxName: string;
271
+ readonly byteLength: number;
272
+ readonly maxByteLength = 128;
273
+ constructor(sandboxName: string, byteLength: number);
274
+ }
275
+ /**
276
+ * The create deadline supplied by the caller elapsed before the sandbox
277
+ * finished booting.
278
+ *
279
+ * The create itself is NOT abandoned: the SDK exposes no cancellation for it,
280
+ * so the adapter keeps watching that promise and, if the sandbox does finish
281
+ * booting afterwards, reclaims it (kill + remove) rather than leaving a
282
+ * running microVM nobody is waiting for and a name nobody can reuse.
283
+ */
284
+ export declare class MicrosandboxCreateTimeoutError extends Error {
285
+ readonly name = "MicrosandboxCreateTimeoutError";
286
+ readonly sandboxName: string;
287
+ readonly timeoutMs: number;
288
+ constructor(sandboxName: string, timeoutMs: number);
289
+ }
290
+ /**
291
+ * A label lookup did not finish within its deadline.
292
+ *
293
+ * Raised rather than returning a partial page: a warm-lease decision made from
294
+ * a truncated listing is a decision made from data the caller cannot tell apart
295
+ * from "there is nothing else".
296
+ */
297
+ export declare class MicrosandboxLookupTimeoutError extends Error {
298
+ readonly name = "MicrosandboxLookupTimeoutError";
299
+ readonly timeoutMs: number;
300
+ constructor(timeoutMs: number, description: string);
301
+ }
302
+ /**
303
+ * A label listing could not be drained to a trustworthy end.
304
+ *
305
+ * Raised rather than returning what was collected so far. A short list and a
306
+ * complete one are indistinguishable to the caller, so a drain that gave up on
307
+ * a cursor that never advances, or on a page body it cannot read, would answer
308
+ * "there is nothing else" — and a warm-lease decision or a quota count made
309
+ * from that answer is made from data the provider never actually supplied.
310
+ */
311
+ export declare class MicrosandboxPaginationError extends Error {
312
+ readonly name = "MicrosandboxPaginationError";
313
+ readonly pages: number;
314
+ constructor(pages: number, detail: string);
315
+ }
316
+ /**
317
+ * A call gave up waiting for the process-global backend gate.
318
+ *
319
+ * The gate exists because `withDefaultBackend` mutates ONE process-wide slot,
320
+ * so a call on backend A cannot run while backend B holds the scope. Normally
321
+ * the wait is short. It is NOT short when the scope holder has been abandoned:
322
+ * a create or a lookup that outlived its own client-side deadline returned a
323
+ * typed error to ITS caller, but the SDK exposes no cancellation, so the
324
+ * request is still in flight and the process-wide backend still has to be its
325
+ * own until it settles.
326
+ *
327
+ * Waiting forever in that situation deadlocks every other backend in the
328
+ * process. Running anyway would send this call to whatever backend the process
329
+ * default happens to hold, which is the one outcome the gate exists to prevent.
330
+ * So the queued call FAILS, loudly and with a typed error the caller can retry
331
+ * on — the honest third option.
332
+ */
333
+ export declare class MicrosandboxBackendBusyError extends Error {
334
+ readonly name = "MicrosandboxBackendBusyError";
335
+ readonly waitedMs: number;
336
+ constructor(waitedMs: number);
337
+ }
338
+ /**
339
+ * `startScript` was called for a session id that is already admitted for a
340
+ * DIFFERENT command.
341
+ *
342
+ * Nothing was started and nothing was overwritten. A session id is the identity
343
+ * of one run's durable state; reusing it for another command would either
344
+ * strand the first run or report its exit code as the second one's.
345
+ */
346
+ export declare class MicrosandboxSessionConflictError extends Error {
347
+ readonly name = "MicrosandboxSessionConflictError";
348
+ readonly sessionId: string;
349
+ constructor(sessionId: string);
350
+ }
351
+ /**
352
+ * An admitted run can no longer produce an exit code.
353
+ *
354
+ * The wrapper writes the exit file as its final act, so a run whose process is
355
+ * gone without one — killed, out of memory, or interrupted by a sandbox
356
+ * restart — will never complete. Raised so a poll loop ends with a terminal
357
+ * outcome instead of asking forever.
358
+ */
359
+ export declare class MicrosandboxRunLostError extends Error {
360
+ readonly name = "MicrosandboxRunLostError";
361
+ readonly sessionId: string;
362
+ readonly commandId: string;
363
+ readonly reason: string;
364
+ constructor(sessionId: string, commandId: string, reason: string);
365
+ }
366
+ /**
367
+ * `getExecLogs` was asked for a terminal result while the run is still going.
368
+ *
369
+ * The bootstrap-plane `ExecResult` has no "unfinished" value — its `exitCode`
370
+ * is a number — so returning one here would have to invent a code. Callers poll
371
+ * `getExecStatus` and read logs once it reports terminal.
372
+ */
373
+ export declare class MicrosandboxRunNotFinishedError extends Error {
374
+ readonly name = "MicrosandboxRunNotFinishedError";
375
+ readonly sessionId: string;
376
+ readonly commandId: string;
377
+ constructor(sessionId: string, commandId: string);
378
+ }
379
+ /**
380
+ * The process-wide default backend could not be restored, so no later
381
+ * default-dependent SDK static may be issued from this process.
382
+ *
383
+ * `withDefaultBackend` sets one process-global slot and restores it on the way
384
+ * out. When the RESTORE is what failed, the slot holds an unknown value: not
385
+ * necessarily this runtime's backend, not necessarily the previous one. Every
386
+ * static the adapter calls reads that slot, so the only two honest options are
387
+ * to guess or to stop. This adapter stops — permanently, for the life of the
388
+ * process, because nothing it is willing to do can re-establish the truth.
389
+ * (Calling `setDefaultBackend` to force a known value would mutate the host
390
+ * process on behalf of a library, which this adapter never does.)
391
+ *
392
+ * Sandbox and handle instances resolved BEFORE the failure are unaffected and
393
+ * still usable: the SDK binds each one to the backend it was resolved on (its
394
+ * typings call this "backend retained by this sandbox"), so their exec,
395
+ * filesystem and lifecycle calls read no global state.
396
+ */
397
+ export declare class MicrosandboxBackendPoisonedError extends Error {
398
+ readonly name = "MicrosandboxBackendPoisonedError";
399
+ constructor(cause: unknown);
400
+ }
401
+ /**
402
+ * A command finished, but the SDK reported no exit code for it.
403
+ *
404
+ * The bootstrap-plane `ExecResult.exitCode` is a number, so this adapter would
405
+ * have to INVENT one — and the only plausible invention, `0`, is the value that
406
+ * says "this succeeded". A command whose outcome the provider did not report is
407
+ * not a command that succeeded, so the caller is told the outcome is unknown
408
+ * instead of being told a comfortable lie it cannot detect.
409
+ */
410
+ export declare class MicrosandboxUnknownOutcomeError extends Error {
411
+ readonly name = "MicrosandboxUnknownOutcomeError";
412
+ readonly sandboxName: string;
413
+ constructor(sandboxName: string);
414
+ }
415
+ /**
416
+ * The status probe for an async run did not produce a verdict.
417
+ *
418
+ * Distinct from {@link MicrosandboxRunLostError}, which IS a verdict — the run
419
+ * is over and cannot complete. This error says the adapter learned NOTHING:
420
+ * the guest call failed, a required guest-state read was unavailable, or it
421
+ * answered something this protocol does not define. Returning "still running"
422
+ * for any of those would be a positive claim the probe never made, and a poll
423
+ * loop reading it would wait for an outcome that may already have happened.
424
+ *
425
+ * It is safe to retry: nothing about the run was changed by asking.
426
+ */
427
+ export declare class MicrosandboxStatusProbeError extends Error {
428
+ readonly name = "MicrosandboxStatusProbeError";
429
+ readonly sessionId: string;
430
+ readonly commandId: string;
431
+ /**
432
+ * `"transport"` — the probe call or a required guest-state read failed.
433
+ * `"unrecognized"` — it answered off-protocol.
434
+ */
435
+ readonly reason: "transport" | "unrecognized";
436
+ /** Retrying is harmless; the probe has no side effects on the run. */
437
+ readonly retryable = true;
438
+ constructor(sessionId: string, commandId: string, reason: "transport" | "unrecognized", detail: string, cause?: unknown);
439
+ }
440
+ /**
441
+ * A run's captured output could not be read.
442
+ *
443
+ * Raised instead of returning `""`. An empty log is a legitimate outcome — a
444
+ * command that printed nothing has one — so a failed read that answered `""`
445
+ * would be indistinguishable from a real result, and the caller would record
446
+ * "the command produced no output" as a fact about a read that never happened.
447
+ * A genuinely ABSENT log file still yields `""`, which is the one case where
448
+ * empty is the truth.
449
+ */
450
+ export declare class MicrosandboxLogReadError extends Error {
451
+ readonly name = "MicrosandboxLogReadError";
452
+ readonly sessionId: string;
453
+ readonly path: string;
454
+ constructor(sessionId: string, path: string, detail: string, cause?: unknown);
455
+ }
456
+ /**
457
+ * `startScript`/`startExec` was given a `timeoutMs`, which this adapter cannot
458
+ * honour as the port defines it.
459
+ *
460
+ * The port's `timeoutMs` is the COMMAND's lifetime. For a synchronous
461
+ * `runScript` that is exactly what the SDK's `ExecOptionsBuilder.timeout` gives,
462
+ * so the sync path honours it. An async run is different: it is detached inside
463
+ * the guest by the durable wrapper and outlives the submit call, so the submit
464
+ * call's timeout bounds nothing about the command.
465
+ *
466
+ * The adapter previously applied it to the submit call anyway. That is the
467
+ * failure mode this error exists to remove — a caller that asked for a 30s
468
+ * command budget got a 30s SUBMIT budget and a command that runs forever, with
469
+ * nothing in the result to say so.
470
+ *
471
+ * It is refused rather than approximated because the honest enforcement is not
472
+ * available here: killing the run's shell on expiry would leave that shell's
473
+ * own descendants running, so the adapter would report a terminated run while
474
+ * the work continued — a fabricated outcome, which is worse than a refusal. Use
475
+ * `maxDurationSeconds` for a sandbox-lifetime bound, or put the bound in the
476
+ * command itself (`timeout 30 ...`), where the guest can enforce it properly.
477
+ */
478
+ export declare class MicrosandboxRunTimeoutUnsupportedError extends Error {
479
+ readonly name = "MicrosandboxRunTimeoutUnsupportedError";
480
+ readonly sessionId: string;
481
+ readonly timeoutMs: number;
482
+ constructor(sessionId: string, timeoutMs: number);
483
+ }
484
+ /**
485
+ * Reset the module-global gate. TEST-ONLY.
486
+ *
487
+ * The gate is process-global on purpose, and poisoning it is permanent on
488
+ * purpose — which makes the poison path untestable in-process without a way
489
+ * back. Exported from the module but NOT from the package barrel, so it is
490
+ * reachable from this file's tests and from nowhere a consumer imports.
491
+ *
492
+ * @internal
493
+ */
494
+ export declare function __resetBackendGateForTests(): void;
495
+ /**
496
+ * How many callers are queued on the gate right now. TEST-ONLY.
497
+ *
498
+ * The leak this exists to catch is INVISIBLE from the outside: a waiter that
499
+ * timed out still reports the same typed `MicrosandboxBackendBusyError` to its
500
+ * caller whether or not it deregistered itself, so a test written against
501
+ * observable behaviour alone passes against the bug. The only discriminating
502
+ * signal is the length of the queue itself, so the queue is what the test
503
+ * asserts on.
504
+ *
505
+ * @internal
506
+ */
507
+ export declare function __backendGateWaiterCountForTests(): number;
508
+ export declare class MicrosandboxRuntime implements SandboxRuntime, WorkflowRuntime {
509
+ readonly id = "microsandbox";
510
+ /**
511
+ * Bootstrap-plane capabilities. These describe what THIS ADAPTER exposes
512
+ * through the port, not everything the SDK can do — the same convention the
513
+ * Daytona adapter follows.
514
+ *
515
+ * TWO OF THESE ARE BACKEND-SENSITIVE, and both were previously reported as
516
+ * flat process-wide constants — which published a claim about the cloud
517
+ * backend that this package cannot stand behind. They are now derived from
518
+ * the backend this instance is bound to.
519
+ *
520
+ * - `pty: false` — the SDK's `ExecOptionsBuilder.tty(true)` and
521
+ * `ExecHandle.resize()` are real, but the port has no pty method and this
522
+ * adapter never allocates one.
523
+ * - `snapshots` — LOCAL only, and the claim is about THIS ADAPTER's boot
524
+ * path, not about the provider's hosted service. `launch` sources a
525
+ * sandbox through the builder's `fromSnapshot`, which consumes a
526
+ * host-local artifact: the installed SDK's typings describe `Snapshot` as
527
+ * "an artifact on disk" and resolve one under
528
+ * `~/.microsandbox/snapshots/<name>/`. This adapter never transfers that
529
+ * artifact anywhere, so on a remote backend there is nothing for a create
530
+ * to resolve — hence `false`, and a constructor that refuses the pairing.
531
+ * Note the adapter only ever CONSUMES a snapshot; it never creates one, so
532
+ * `SandboxHandle.snapshot()` is not on this path.
533
+ * - `isolation` — `'strong'` on LOCAL, `'unknown'` on CLOUD, and both values
534
+ * describe what this package has ESTABLISHED rather than what any provider
535
+ * documentation says. Locally the SDK boots each sandbox as a microVM with
536
+ * its own guest kernel on a virtualization-capable host, and the installed
537
+ * package states that requirement itself (Node 22+, a native addon, KVM /
538
+ * Apple Silicon / WHP), so `'strong'` rests on something checkable here.
539
+ * For the cloud backend this adapter observes nothing about isolation,
540
+ * region placement or resource enforcement and measures nothing against
541
+ * them, so it reports `'unknown'` — which is a statement about this
542
+ * package's evidence, not an assertion that the guarantee is absent. See
543
+ * {@link IsolationLevel}.
544
+ * - `persistentHandle: true` — a sandbox is re-resolvable by name from a
545
+ * fresh process via `Sandbox.get(name)` + `connect()`, and
546
+ * `launchDetached` sets `detached(true)` so it outlives this process.
547
+ * - `streamingLogs: false` — the SDK ships `logStream({follow:true})` and
548
+ * `execStream`, but this adapter's log path is a durable file read, so
549
+ * claiming a streaming capability here would be claiming a code path that
550
+ * does not exist.
551
+ *
552
+ * NOT SUPPORTED, and deliberately absent rather than silently ignored: custom
553
+ * or published PORTS. The SDK builder exposes `port()`/`portBind()`/`portUdp()`,
554
+ * but the ports this package targets have no public-port surface to express
555
+ * them, so this adapter never calls them and never implies a reachable port.
556
+ */
557
+ readonly capabilities: RuntimeCapabilities;
558
+ /**
559
+ * Both true, and declared rather than left to default so the reasoning is on
560
+ * the record. `warmLease`: `Sandbox.listWith(b => b.labels(...))` is a real
561
+ * server-side label query with cursor pagination, so a warm-lease lookup is
562
+ * meaningful. `lifecycle`: `start`/`stop` map onto `SandboxHandle.start()` /
563
+ * `SandboxHandle.stop()`, which genuinely resume and halt a microVM — unlike
564
+ * the E2B adapter, where both are no-ops. Both apply to sandboxes this
565
+ * runtime OWNS; an attached sandbox is deliberately left alone.
566
+ */
567
+ readonly declaredCapabilities: {
568
+ readonly warmLease: true;
569
+ readonly lifecycle: true;
570
+ };
571
+ private readonly backend;
572
+ private readonly image?;
573
+ private readonly snapshot?;
574
+ private readonly homeDir;
575
+ private readonly defaultWorkdir?;
576
+ private readonly cpus?;
577
+ private readonly memoryMiB?;
578
+ private readonly idleTimeoutSeconds?;
579
+ private readonly maxDurationSeconds?;
580
+ private readonly replaceExisting;
581
+ private readonly namePrefix;
582
+ private readonly runStateDir;
583
+ private readonly shell;
584
+ private readonly connectTimeoutMs;
585
+ private readonly lookupTimeoutMs;
586
+ private readonly listPageSize;
587
+ private readonly backendQueueTimeoutMs;
588
+ private readonly injectedSdk?;
589
+ private readonly onReclaimFailure?;
590
+ private sdkPromise?;
591
+ private readonly registry;
592
+ private readonly pendingReclaims;
593
+ constructor(options: MicrosandboxRuntimeOptions);
594
+ findByLabels(labels: Record<string, string>, options?: SandboxLookupOptions): Promise<RuntimeHandle | null>;
595
+ findAllByLabels(labels: Record<string, string>, options?: SandboxLookupOptions): Promise<RuntimeHandle[]>;
596
+ countByLabels(labels: Record<string, string>, options?: SandboxCountOptions): Promise<number>;
597
+ /**
598
+ * Drain the cursor-paginated, server-side label listing, keeping the entries
599
+ * that match `states` and are not excluded, and stopping as soon as `cap`
600
+ * such handles are collected or the lookup deadline elapses.
601
+ */
602
+ private collectByLabels;
603
+ getById(id: string, options?: {
604
+ states?: readonly string[] | null;
605
+ owned?: boolean;
606
+ homeDir?: string;
607
+ workdir?: string;
608
+ }): Promise<RuntimeHandle | null>;
609
+ launch(options?: LaunchOptions): Promise<RuntimeHandle>;
610
+ launchDetached(options?: LaunchOptions): Promise<RuntimeHandle>;
611
+ private createSandbox;
612
+ /**
613
+ * Take responsibility for a create that lost the race with its deadline.
614
+ *
615
+ * The SDK offers no way to cancel an in-flight create, so the promise is
616
+ * watched instead of dropped. Two things follow from that, and both matter:
617
+ * the eventual rejection is consumed here (an abandoned rejected promise is
618
+ * an unhandled rejection, which crashes a Node process configured to treat
619
+ * them as fatal), and an eventual SUCCESS is reclaimed — the caller already
620
+ * saw a failure, so a sandbox nobody is waiting for would otherwise burn
621
+ * provider resources and hold its name against the next launch.
622
+ */
623
+ private reclaimLateCreate;
624
+ private resolveName;
625
+ /**
626
+ * Bootstrap-plane exec. Same call as `runScript`, narrower result shape.
627
+ *
628
+ * `ExecResult.exitCode` is a `number`, and `RunScriptResult.exitCode` is
629
+ * `number | null`, so this is where a missing outcome would have to be
630
+ * invented. It is not: a `null` becomes a typed error rather than the `0`
631
+ * that would report an unobserved command as a successful one.
632
+ */
633
+ exec(handle: RuntimeHandle, command: string, options?: ExecOptions): Promise<ExecResult>;
634
+ runScript(handle: RuntimeHandle, options: {
635
+ command: string;
636
+ sessionId?: string;
637
+ cwd?: string;
638
+ timeoutMs?: number;
639
+ env?: Record<string, string>;
640
+ }): Promise<RunScriptResult>;
641
+ /**
642
+ * Submit one durable async run.
643
+ *
644
+ * The guest wrapper (see {@link MICROSANDBOX_RUN_ADMIT_SCRIPT}) claims the
645
+ * session's run directory with an atomic `mkdir`, so this is idempotent in
646
+ * the way that actually matters for an outcome-unknown submit: a retry of
647
+ * the SAME command adopts the run that is already there (`reconciled: true`)
648
+ * instead of starting a second one, and a retry with a DIFFERENT command is
649
+ * refused instead of overwriting the first run's state.
650
+ */
651
+ startScript(handle: RuntimeHandle, options: {
652
+ command: string;
653
+ sessionId?: string;
654
+ cwd?: string;
655
+ timeoutMs?: number;
656
+ env?: Record<string, string>;
657
+ suppressInputEcho?: boolean;
658
+ }): Promise<AsyncRunStartResult>;
659
+ getScriptStatus(handle: RuntimeHandle, sessionId: string, commandId: string): Promise<AsyncRunStatus>;
660
+ getScriptLogs(handle: RuntimeHandle, sessionId: string, commandId: string): Promise<RunScriptResult>;
661
+ startExec(handle: RuntimeHandle, command: string, options?: ExecOptions & {
662
+ sessionId?: string;
663
+ }): Promise<AsyncExecStartResult>;
664
+ getExecStatus(handle: RuntimeHandle, sessionId: string, commandId: string): Promise<AsyncExecStatus>;
665
+ /**
666
+ * Terminal result of an async run: its captured output AND the exit code the
667
+ * run actually recorded.
668
+ *
669
+ * The exit code comes from `getScriptStatus`, never from the log read.
670
+ * `getScriptLogs` reports `exitCode: null` by design, and defaulting that to
671
+ * `0` here would report every unfinished — and every lost — run as a success.
672
+ */
673
+ getExecLogs(handle: RuntimeHandle, sessionId: string, commandId: string): Promise<ExecResult>;
674
+ /**
675
+ * Put one file into the guest.
676
+ *
677
+ * A `string` source is a HOST PATH and a `Buffer` source is file CONTENT —
678
+ * the same split the Daytona adapter uses, so this class's `uploadFile` and
679
+ * `uploadBundle` cannot disagree with each other.
680
+ */
681
+ uploadFile(handle: RuntimeHandle, source: string | Buffer, destination: string): Promise<void>;
682
+ uploadBundle(handle: RuntimeHandle, options: {
683
+ files: Array<{
684
+ source: string | Buffer;
685
+ destination: string;
686
+ }>;
687
+ }): Promise<void>;
688
+ downloadFile(handle: RuntimeHandle, source: string, destination?: string): Promise<Buffer | void>;
689
+ getHomeDir(handle: RuntimeHandle): Promise<string>;
690
+ start(handle: RuntimeHandle): Promise<RuntimeHandle>;
691
+ stop(handle: RuntimeHandle): Promise<void>;
692
+ /**
693
+ * Halt the sandbox AND drop its database record — but only if this runtime
694
+ * owns it.
695
+ *
696
+ * Both halves of the teardown matter: the name is the identity, so leaving a
697
+ * stopped record behind would make the next `launch` under that name collide.
698
+ * The ownership check matters more: `destroy` is the one call here that
699
+ * cannot be undone, and a lease-reattach path that resolved a borrowed
700
+ * sandbox by name must not be able to delete it. An unowned (or unknown)
701
+ * handle drops this runtime's local state and makes no remote call at all.
702
+ */
703
+ destroy(handle: RuntimeHandle): Promise<void>;
704
+ /**
705
+ * Stop-if-running + remove by name, with no ownership check.
706
+ *
707
+ * Private on purpose: the only callers are `destroy` (which has already
708
+ * checked) and the reclamation of a create that landed after its deadline
709
+ * (which is reclaiming a sandbox this runtime itself asked for).
710
+ *
711
+ * Backend-safe order — this is what makes the destroy path work on the
712
+ * hosted cloud backend. `SandboxHandle.kill()` is not implemented there:
713
+ * the SDK answers it with `UnsupportedError` (code `"unsupported"`,
714
+ * message `"Sandbox::kill is not supported by this backend: use
715
+ * Sandbox::stop"`), and the previous code re-threw that error before
716
+ * `remove()` was ever reached, so every cloud destroy left a running
717
+ * sandbox behind. `stop()` works on both backends, so the sequence is:
718
+ *
719
+ * 1. Try `kill()` — a stronger, faster teardown that local supports.
720
+ * 2. If the backend answers `Unsupported`, fall back to `stop()` — the
721
+ * call the hosted backend documents.
722
+ * 3. Either way, `remove()` clears the record (which requires the
723
+ * sandbox to be stopped, and cannot delete a still-running one).
724
+ *
725
+ * `already-stopped` and `not-found` on the first-step call are both fine
726
+ * because they mean the same thing for the caller: the sandbox is
727
+ * quiescent by the time `remove()` runs. Any other error is fatal to the
728
+ * teardown and re-thrown, so the caller retains responsibility.
729
+ */
730
+ private forceDestroy;
731
+ private sdk;
732
+ /**
733
+ * Run one DEFAULT-DEPENDENT SDK static with this runtime's backend in scope.
734
+ *
735
+ * `setDefaultBackend` is never called from this adapter: constructing a
736
+ * runtime must not mutate the host process. The scoped form IS process-wide
737
+ * while it is open, which is why every static goes through the module's
738
+ * backend gate (see `withBackendScope`) rather than opening its own scope.
739
+ *
740
+ * ONLY the three statics this adapter calls belong here — `Sandbox.builder`
741
+ * (through its terminal `create()`), `Sandbox.get` and `Sandbox.listWith`.
742
+ * Operations on a resolved `Sandbox` or `SandboxHandle` are bound to the
743
+ * backend they were resolved on and are issued directly, off the gate.
744
+ */
745
+ private withBackendStatic;
746
+ private lookupHandle;
747
+ private register;
748
+ private isOwned;
749
+ /** Drop the live connection but keep what this runtime knows about the name. */
750
+ private forgetInstance;
751
+ private requireSandbox;
752
+ private ensureParentDir;
753
+ /**
754
+ * Read one run's captured output, bounded, without turning a failure into an
755
+ * empty log.
756
+ *
757
+ * The read goes through {@link MICROSANDBOX_RUN_LOG_SCRIPT} rather than
758
+ * `fs.readToString` for two reasons that both matter to the caller: an
759
+ * ABSENT log is a success with no output (a run that has printed nothing has
760
+ * one), and everything else — an unreadable file, a failed guest call — is a
761
+ * failure. The previous form could not tell those apart, because it answered
762
+ * `""` to all of them.
763
+ *
764
+ * One byte MORE than the cap is requested, so a longer log is detectable
765
+ * rather than silently tailed: the extra byte is what turns "here is the
766
+ * output" into "here is the last `maxBytes` of it".
767
+ */
768
+ private readRunLog;
769
+ private lookupDeadline;
770
+ /**
771
+ * Run `build` under the ONE overall deadline, cancelling its admission when
772
+ * that deadline expires.
773
+ *
774
+ * Racing a timer against the operation is not enough on its own. The gate is
775
+ * a queue, so a lookup that gives up while queued is still queued: it can be
776
+ * admitted later and issue a static against the process default long after
777
+ * the caller stopped waiting for it. The signal is what actually withdraws
778
+ * it from the queue.
779
+ */
780
+ private awaitWithinCancelling;
781
+ private awaitWithin;
782
+ /**
783
+ * Guest directory holding one session's run state.
784
+ *
785
+ * The encoding is reversible, so two different session ids can never land on
786
+ * one directory. A sanitizing replacement cannot promise that: it maps `a/b`
787
+ * and `a_b` onto the same path, which is enough to hand one run's exit code
788
+ * to the other.
789
+ */
790
+ private scriptRunDir;
791
+ }
792
+ export {};
793
+ //# sourceMappingURL=runtime.d.ts.map