@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.
- package/README.md +226 -5
- package/dist/agent37/client.d.ts +115 -0
- package/dist/agent37/client.d.ts.map +1 -0
- package/dist/agent37/client.js +270 -0
- package/dist/agent37/client.js.map +1 -0
- package/dist/agent37/runtime.d.ts +415 -0
- package/dist/agent37/runtime.d.ts.map +1 -0
- package/dist/agent37/runtime.js +855 -0
- package/dist/agent37/runtime.js.map +1 -0
- package/dist/agentcore/bench.d.ts +93 -0
- package/dist/agentcore/bench.d.ts.map +1 -0
- package/dist/agentcore/bench.js +125 -0
- package/dist/agentcore/bench.js.map +1 -0
- package/dist/agentcore/capabilities.d.ts +169 -0
- package/dist/agentcore/capabilities.d.ts.map +1 -0
- package/dist/agentcore/capabilities.js +153 -0
- package/dist/agentcore/capabilities.js.map +1 -0
- package/dist/agentcore/config.d.ts +156 -0
- package/dist/agentcore/config.d.ts.map +1 -0
- package/dist/agentcore/config.js +12 -0
- package/dist/agentcore/config.js.map +1 -0
- package/dist/agentcore/internal/sdk.d.ts +181 -0
- package/dist/agentcore/internal/sdk.d.ts.map +1 -0
- package/dist/agentcore/internal/sdk.js +223 -0
- package/dist/agentcore/internal/sdk.js.map +1 -0
- package/dist/agentcore/runtime.d.ts +177 -0
- package/dist/agentcore/runtime.d.ts.map +1 -0
- package/dist/agentcore/runtime.js +706 -0
- package/dist/agentcore/runtime.js.map +1 -0
- package/dist/daytona/runtime.d.ts +23 -0
- package/dist/daytona/runtime.d.ts.map +1 -1
- package/dist/daytona/runtime.js +167 -5
- package/dist/daytona/runtime.js.map +1 -1
- package/dist/daytona/wire-supplement.d.ts +25 -0
- package/dist/daytona/wire-supplement.d.ts.map +1 -0
- package/dist/daytona/wire-supplement.js +16 -0
- package/dist/daytona/wire-supplement.js.map +1 -0
- package/dist/e2b/runtime.d.ts +107 -72
- package/dist/e2b/runtime.d.ts.map +1 -1
- package/dist/e2b/runtime.js +675 -190
- package/dist/e2b/runtime.js.map +1 -1
- package/dist/freestyle/capabilities.d.ts +28 -0
- package/dist/freestyle/capabilities.d.ts.map +1 -0
- package/dist/freestyle/capabilities.js +42 -0
- package/dist/freestyle/capabilities.js.map +1 -0
- package/dist/freestyle/config.d.ts +36 -0
- package/dist/freestyle/config.d.ts.map +1 -0
- package/dist/freestyle/config.js +2 -0
- package/dist/freestyle/config.js.map +1 -0
- package/dist/freestyle/internal/sdk.d.ts +69 -0
- package/dist/freestyle/internal/sdk.d.ts.map +1 -0
- package/dist/freestyle/internal/sdk.js +19 -0
- package/dist/freestyle/internal/sdk.js.map +1 -0
- package/dist/freestyle/runtime.d.ts +163 -0
- package/dist/freestyle/runtime.d.ts.map +1 -0
- package/dist/freestyle/runtime.js +798 -0
- package/dist/freestyle/runtime.js.map +1 -0
- package/dist/index.d.ts +35 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -2
- package/dist/index.js.map +1 -1
- package/dist/microsandbox/runtime.d.ts +793 -0
- package/dist/microsandbox/runtime.d.ts.map +1 -0
- package/dist/microsandbox/runtime.js +2303 -0
- package/dist/microsandbox/runtime.js.map +1 -0
- package/dist/modal/bench.d.ts +199 -0
- package/dist/modal/bench.d.ts.map +1 -0
- package/dist/modal/bench.js +450 -0
- package/dist/modal/bench.js.map +1 -0
- package/dist/modal/capabilities.d.ts +180 -0
- package/dist/modal/capabilities.d.ts.map +1 -0
- package/dist/modal/capabilities.js +159 -0
- package/dist/modal/capabilities.js.map +1 -0
- package/dist/modal/config.d.ts +192 -0
- package/dist/modal/config.d.ts.map +1 -0
- package/dist/modal/config.js +169 -0
- package/dist/modal/config.js.map +1 -0
- package/dist/modal/internal/sdk.d.ts +141 -0
- package/dist/modal/internal/sdk.d.ts.map +1 -0
- package/dist/modal/internal/sdk.js +51 -0
- package/dist/modal/internal/sdk.js.map +1 -0
- package/dist/modal/runtime.d.ts +271 -0
- package/dist/modal/runtime.d.ts.map +1 -0
- package/dist/modal/runtime.js +871 -0
- package/dist/modal/runtime.js.map +1 -0
- package/dist/mount-script.d.ts +16 -1
- package/dist/mount-script.d.ts.map +1 -1
- package/dist/mount-script.js +76 -15
- package/dist/mount-script.js.map +1 -1
- package/dist/orchestrator.d.ts +15 -0
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +13 -1
- package/dist/orchestrator.js.map +1 -1
- package/dist/port.d.ts +144 -6
- package/dist/port.d.ts.map +1 -1
- package/dist/port.js +27 -5
- package/dist/port.js.map +1 -1
- package/dist/types.d.ts +50 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vercel/bench.d.ts +169 -0
- package/dist/vercel/bench.d.ts.map +1 -0
- package/dist/vercel/bench.js +337 -0
- package/dist/vercel/bench.js.map +1 -0
- package/dist/vercel/capabilities.d.ts +106 -0
- package/dist/vercel/capabilities.d.ts.map +1 -0
- package/dist/vercel/capabilities.js +128 -0
- package/dist/vercel/capabilities.js.map +1 -0
- package/dist/vercel/config.d.ts +119 -0
- package/dist/vercel/config.d.ts.map +1 -0
- package/dist/vercel/config.js +8 -0
- package/dist/vercel/config.js.map +1 -0
- package/dist/vercel/internal/sdk.d.ts +173 -0
- package/dist/vercel/internal/sdk.d.ts.map +1 -0
- package/dist/vercel/internal/sdk.js +117 -0
- package/dist/vercel/internal/sdk.js.map +1 -0
- package/dist/vercel/runtime.d.ts +305 -0
- package/dist/vercel/runtime.d.ts.map +1 -0
- package/dist/vercel/runtime.js +1169 -0
- package/dist/vercel/runtime.js.map +1 -0
- package/docs/freestyle.md +110 -0
- package/package.json +35 -4
|
@@ -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
|