@tangle-network/sandbox 0.10.5-develop.20260713235503.8f2cefc → 0.10.5-develop.20260715115519.fee3d86
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 +96 -0
- package/dist/agent/index.d.ts +3 -3
- package/dist/{client-C-4NcZoa.d.ts → client-CSaBJ8wD.d.ts} +2 -2
- package/dist/{client-CL_cbjU4.js → client-_OBj4sNO.js} +376 -10
- package/dist/core.d.ts +3 -3
- package/dist/core.js +2 -2
- package/dist/{index-DFJiN98I.d.ts → index-CEZaPvfX.d.ts} +2 -2
- package/dist/index.d.ts +27 -6
- package/dist/index.js +5 -280
- package/dist/{runtime-api-CaXI7Kl2.js → runtime-api-BWq4XSrb.js} +254 -2
- package/dist/runtime.d.ts +43 -2
- package/dist/runtime.js +2 -2
- package/dist/{sandbox-BvNEOnIl.d.ts → sandbox-B9P4tyt4.d.ts} +6 -1
- package/dist/{sandbox-CIHssZCH.js → sandbox-KiKLRbR_.js} +14 -2
- package/dist/tangle/index.d.ts +1 -1
- package/dist/tangle/index.js +1 -1
- package/dist/{tangle-C-5OvIj8.js → tangle-Os9sH-ms.js} +1 -1
- package/dist/{types-yNRVRww-.d.ts → types-LNLeU9Ub.d.ts} +82 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -222,6 +222,38 @@ A gateway crash before acknowledgement redelivers the same event IDs, which the
|
|
|
222
222
|
See `examples/cf-worker-chat.ts`, `examples/browser-streaming-resume.ts`, and
|
|
223
223
|
`examples/reconnect-from-last-event-id.ts` for end-to-end patterns.
|
|
224
224
|
|
|
225
|
+
### Browser-safe scoped runtime client
|
|
226
|
+
|
|
227
|
+
`@tangle-network/sandbox/runtime` is a browser- and Worker-safe entry point
|
|
228
|
+
(no `node:` imports) for talking directly to one sandbox's runtime with a
|
|
229
|
+
short-lived scoped token — never the account-level Sandbox API key — minted
|
|
230
|
+
server-side via `box.mintScopedToken({ scope: "session-runtime", sessionId })`
|
|
231
|
+
or `box.mintScopedToken({ scope: "read-only" })`.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { createSandboxRuntimeClient } from "@tangle-network/sandbox/runtime";
|
|
235
|
+
|
|
236
|
+
const runtime = createSandboxRuntimeClient({
|
|
237
|
+
baseUrl: scopedToken.sidecarProxyUrl, // browser-safe proxy base from box.mintScopedToken()
|
|
238
|
+
token: scopedToken.token,
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
await runtime.writeFile("/workspace/notes.md", "# from the browser");
|
|
242
|
+
|
|
243
|
+
// Binary-safe, chunked upload for payloads over ~1 MiB — same engine and
|
|
244
|
+
// size contract as SandboxInstance.fs.uploadData, wired to the scoped token
|
|
245
|
+
const blob = await fileInput.files[0].arrayBuffer();
|
|
246
|
+
await runtime.uploadData("/workspace/uploads/file.bin", blob, {
|
|
247
|
+
onProgress: (p) => console.log(`${p.percentage.toFixed(1)}%`),
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Every method on the scoped client — `writeFile`, `readFiles`, `uploadData`,
|
|
252
|
+
terminals, sessions — carries the same `Authorization: Bearer <token>` header
|
|
253
|
+
and base URL prefix, so the request conventions match whether the token
|
|
254
|
+
scope allows the call or not; a denied call fails with the typed
|
|
255
|
+
`SandboxError`, not a silent no-op.
|
|
256
|
+
|
|
225
257
|
## Features
|
|
226
258
|
|
|
227
259
|
- **Sandbox Management** - Create, list, stop, resume, and delete sandboxes
|
|
@@ -727,6 +759,70 @@ for await (const event of box.events({ signal: controller.signal })) {
|
|
|
727
759
|
}
|
|
728
760
|
```
|
|
729
761
|
|
|
762
|
+
### File I/O
|
|
763
|
+
|
|
764
|
+
| Method | Environment | Payload | Notes |
|
|
765
|
+
|---|---|---|---|
|
|
766
|
+
| `fs.read(path)` / `fs.write(path, content, options?)` | Node + browser | UTF-8 string, or base64 via `options.encoding` | Single request — see the size contract below for the cap |
|
|
767
|
+
| `fs.writeMany(files, options?)` | Node + browser | Same as `write`; per-file `encoding` | Paced, retry-aware batch through `fs.write`'s endpoint; fails loud on the first file that can't be written |
|
|
768
|
+
| `fs.upload(localPath, remotePath, options?)` | Node only | Local file path | Reads the local file with `node:fs`; not available in a browser tab |
|
|
769
|
+
| `fs.uploadData(remotePath, data, options?)` | Node + browser | `Blob \| ArrayBuffer \| ArrayBufferView \| string` | Browser/Worker-safe, binary-safe — the sanctioned path for payloads over ~1 MiB (see below) |
|
|
770
|
+
| `fs.download(remotePath, localPath, options?)` | Node only | — | Writes to a local path with `node:fs` |
|
|
771
|
+
| `fs.uploadDir` / `fs.downloadDir` | Node only | Local directory path | tar-based directory transfer |
|
|
772
|
+
| `fs.list` / `fs.stat` / `fs.mkdir` / `fs.delete` / `fs.rename` / `fs.exists` | Node + browser | — | Directory listing and file metadata operations |
|
|
773
|
+
|
|
774
|
+
```typescript
|
|
775
|
+
// Text write/read (UTF-8 by default)
|
|
776
|
+
await box.fs.write("/workspace/config.json", JSON.stringify(config));
|
|
777
|
+
const raw = await box.fs.read("/workspace/config.json");
|
|
778
|
+
|
|
779
|
+
// Base64 for binary content through the same single-shot endpoint
|
|
780
|
+
await box.fs.write("/workspace/icon.png", base64Png, { encoding: "base64" });
|
|
781
|
+
|
|
782
|
+
// Batch-write many small files (paced, retried)
|
|
783
|
+
await box.fs.writeMany([
|
|
784
|
+
{ path: "skills/review.md", content: reviewSkill },
|
|
785
|
+
{ path: "assets/logo.png", content: base64Logo, encoding: "base64" },
|
|
786
|
+
]);
|
|
787
|
+
|
|
788
|
+
// Node-only: upload a local file
|
|
789
|
+
await box.fs.upload("./model.bin", "/workspace/models/model.bin");
|
|
790
|
+
|
|
791
|
+
// Browser/Worker-safe: upload in-memory data over ~1 MiB (e.g. an
|
|
792
|
+
// <input type="file"> Blob) — chunked and verified end-to-end
|
|
793
|
+
const blob = await fetch("https://example.com/model.bin").then((r) => r.blob());
|
|
794
|
+
await box.fs.uploadData("/workspace/models/model.bin", blob, {
|
|
795
|
+
onProgress: (p) => console.log(`${p.percentage.toFixed(1)}%`),
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
await box.fs.download("/workspace/results.zip", "./results.zip");
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
`fs.uploadData` is the sanctioned path once a payload clears the single-shot
|
|
802
|
+
write cap: it splits the payload into server-sized parts against a chunked
|
|
803
|
+
upload-session and verifies the whole payload with a SHA-256 at commit, so
|
|
804
|
+
it's safe for arbitrarily-shaped binary content (video, model weights,
|
|
805
|
+
archives) up to the session cap. It works identically whether the sandbox is
|
|
806
|
+
reached through the gateway proxy or a direct sidecar connection
|
|
807
|
+
(`box.direct()`).
|
|
808
|
+
|
|
809
|
+
#### File size contract
|
|
810
|
+
|
|
811
|
+
| Surface | Cap | Constant | Failure |
|
|
812
|
+
|---|---|---|---|
|
|
813
|
+
| Single-shot decoded write (`fs.write`, `fs.writeMany`) | 5 MiB | `FILE_DECODED_WRITE_MAX_BYTES` | `FILE_TOO_LARGE` |
|
|
814
|
+
| Gateway proxy request (wire, any route) | 1 MiB | `SANDBOX_PROXY_REQUEST_MAX_BYTES` | `PAYLOAD_TOO_LARGE` |
|
|
815
|
+
| Direct-runtime write request (wire, `box.direct()` only) | 32 MiB | `SANDBOX_DIRECT_FILE_REQUEST_MAX_BYTES` | `PAYLOAD_TOO_LARGE` |
|
|
816
|
+
| Multipart upload (`fs.upload`) | 5 MiB | `FILE_MULTIPART_UPLOAD_MAX_BYTES` | `FILE_TOO_LARGE` |
|
|
817
|
+
| Chunked upload part (`fs.uploadData`, internal) | 768 KiB | `FILE_UPLOAD_PART_MAX_BYTES` | — (server-sized, transparent to callers) |
|
|
818
|
+
| Chunked upload session (`fs.uploadData`) | 64 MiB | `FILE_UPLOAD_SESSION_MAX_BYTES` | `PAYLOAD_TOO_LARGE` |
|
|
819
|
+
|
|
820
|
+
All constants are exported from `@tangle-network/runtime-contracts`. Use
|
|
821
|
+
`fs.uploadData` for anything above the single-shot caps. `PAYLOAD_TOO_LARGE`
|
|
822
|
+
means split the delivery (use `fs.uploadData` instead of one request);
|
|
823
|
+
`FILE_TOO_LARGE` means the content itself exceeds what that surface accepts,
|
|
824
|
+
no matter how it's delivered.
|
|
825
|
+
|
|
730
826
|
### Snapshots
|
|
731
827
|
|
|
732
828
|
#### `box.snapshot(options?)`
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as
|
|
2
|
-
import { n as SandboxInstance } from "../sandbox-
|
|
3
|
-
import { i as SandboxClient } from "../client-
|
|
1
|
+
import { D as CodeExecutionOptions, O as CodeExecutionResult, j as CodeResultPart, k as CodeLanguage } from "../types-LNLeU9Ub.js";
|
|
2
|
+
import { n as SandboxInstance } from "../sandbox-B9P4tyt4.js";
|
|
3
|
+
import { i as SandboxClient } from "../client-CSaBJ8wD.js";
|
|
4
4
|
import * as _$_modelcontextprotocol_sdk_server_index_js0 from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
5
|
|
|
6
6
|
//#region src/agent/tools/_specs.d.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $n as
|
|
2
|
-
import { a as TraceExportSink, i as TraceExportResult, n as SandboxInstance, t as HttpClient } from "./sandbox-
|
|
1
|
+
import { $n as SandboxFleetDriverCapability, An as ReconcileSandboxFleetsResult, B as CreateSandboxOptions, Cn as PublicTemplateInfo, Ct as FleetPromptDispatchResult, Dn as ReapExpiredSandboxFleetsOptions, En as PublishPublicTemplateVersionOptions, Er as SandboxProfileSummary, F as CreateIntelligenceReportOptions, Gt as IntelligenceReportCompareTo, I as CreateRequestOptions, Jn as SandboxFleetArtifact, Kn as SandboxEnvironment, L as CreateSandboxFleetOptions, On as ReapExpiredSandboxFleetsResult, Qn as SandboxFleetDispatchResponse, Qt as ListSandboxOptions, R as CreateSandboxFleetTokenOptions, St as FleetPromptDispatchOptions, Ti as TokenRefreshHandler, Tn as PublishPublicTemplateOptions, Ut as IntelligenceReport, Wn as SandboxClientConfig, Wt as IntelligenceReportBudget, Xn as SandboxFleetCostEstimate, Yn as SandboxFleetArtifactSpec, Zt as ListSandboxFleetOptions, _ as BatchResult, _n as PromptOptions, _t as FleetDispatchResultBufferOptions, a as AttachSandboxFleetMachineOptions, ar as SandboxFleetMachineRecord, br as SandboxFleetWorkspaceSnapshotResult, bt as FleetExecDispatchResult, ci as SshKeysManager, dr as SandboxFleetToken, fi as SubscriptionInfo, fr as SandboxFleetTraceBundle, g as BatchOptions, gn as PromptInputPart, gr as SandboxFleetUsage, gt as FleetDispatchResultBuffer, hr as SandboxFleetTraceOptions, ht as FleetDispatchCancelResult, ji as UsageInfo, kn as ReconcileSandboxFleetsOptions, lr as SandboxFleetOperationsSummary, m as BatchEvent, nt as ExecOptions, qr as SecretsManager, qt as IntelligenceReportWindow, rt as ExecResult, sr as SandboxFleetManifest, tr as SandboxFleetInfo, v as BatchRunOptions, vn as PromptResult, vr as SandboxFleetWorkspaceReconcileResult, vt as FleetDispatchStreamOptions, wn as PublicTemplateVersionInfo, x as BatchTask, xr as SandboxInfo, xt as FleetMachineId, y as BatchRunRequest, yr as SandboxFleetWorkspaceRestoreResult, yt as FleetExecDispatchOptions, z as CreateSandboxFleetWithCoordinatorOptions } from "./types-LNLeU9Ub.js";
|
|
2
|
+
import { a as TraceExportSink, i as TraceExportResult, n as SandboxInstance, t as HttpClient } from "./sandbox-B9P4tyt4.js";
|
|
3
3
|
|
|
4
4
|
//#region src/lib/sse-parser.d.ts
|
|
5
5
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as NotFoundError, c as SandboxError, d as TimeoutError, f as ValidationError, i as NetworkError, p as parseErrorResponse, t as AuthError } from "./errors-wd266B9Q.js";
|
|
2
|
-
import { d as exportTraceBundle, g as parseSSEStream, l as normalizeConnection, m as encodePromptForWire, n as normalizeStartupDiagnostics, t as SandboxInstance } from "./sandbox-
|
|
1
|
+
import { a as NotFoundError, c as SandboxError, d as TimeoutError, f as ValidationError, i as NetworkError, o as PartialFailureError, p as parseErrorResponse, t as AuthError } from "./errors-wd266B9Q.js";
|
|
2
|
+
import { d as exportTraceBundle, g as parseSSEStream, h as encodeTextForWire, l as normalizeConnection, m as encodePromptForWire, n as normalizeStartupDiagnostics, t as SandboxInstance } from "./sandbox-KiKLRbR_.js";
|
|
3
|
+
import { FILE_DECODED_WRITE_MAX_BYTES, SANDBOX_PROXY_REQUEST_MAX_BYTES } from "@tangle-network/runtime-contracts";
|
|
3
4
|
//#region src/resources.ts
|
|
4
5
|
/**
|
|
5
6
|
* Compute tiers, ordered smallest → largest. Defined HERE (not imported from
|
|
@@ -946,6 +947,338 @@ function getMachineRole(info) {
|
|
|
946
947
|
return value === "coordinator" || value === "worker" ? value : void 0;
|
|
947
948
|
}
|
|
948
949
|
//#endregion
|
|
950
|
+
//#region src/profile-file-mounts.ts
|
|
951
|
+
const PROFILE_FILE_MOUNT_B64_CHUNK_CHARS = 3e3;
|
|
952
|
+
const PROFILE_FILE_MOUNT_MAX_RETRIES = 4;
|
|
953
|
+
const PROFILE_FILE_MOUNT_RETRY_BASE_MS = 250;
|
|
954
|
+
const PROFILE_FILE_MOUNT_RETRY_MAX_MS = 2e3;
|
|
955
|
+
const PROFILE_FILE_MOUNT_EXEC_TIMEOUT_MS = 3e4;
|
|
956
|
+
const PROFILE_FILE_MOUNT_PACE_MS = 150;
|
|
957
|
+
const PROFILE_BIN_DIR_RE = /(^|\/)(s?bin)\//;
|
|
958
|
+
/**
|
|
959
|
+
* Wire budget for a single-shot `POST /files/write` of a mount.
|
|
960
|
+
* Materialization runs over whatever connection the box has — on the
|
|
961
|
+
* default create() path that is the GATEWAY, whose wire cap
|
|
962
|
+
* ({@link SANDBOX_PROXY_REQUEST_MAX_BYTES}, 1 MiB) binds long before the
|
|
963
|
+
* sidecar's 5 MiB decoded cap. The routing decision measures the ACTUAL
|
|
964
|
+
* serialized content (JSON escaping inflates unevenly — a NUL byte
|
|
965
|
+
* becomes the six characters `\u0000`, a backslash doubles — so no fixed
|
|
966
|
+
* inflation factor is safe), leaving headroom for the request envelope
|
|
967
|
+
* (path up to 4 KiB, mode, encoding, braces). Anything that doesn't fit
|
|
968
|
+
* rides chunked upload, whose parts are sized for the gateway.
|
|
969
|
+
*/
|
|
970
|
+
const PROFILE_FILE_WRITE_WIRE_BUDGET_BYTES = SANDBOX_PROXY_REQUEST_MAX_BYTES - 8 * 1024;
|
|
971
|
+
function fitsSingleShotWrite(content, contentBytes) {
|
|
972
|
+
if (contentBytes > FILE_DECODED_WRITE_MAX_BYTES) return false;
|
|
973
|
+
if (contentBytes * 6 <= PROFILE_FILE_WRITE_WIRE_BUDGET_BYTES) return true;
|
|
974
|
+
return new TextEncoder().encode(JSON.stringify(content)).byteLength <= PROFILE_FILE_WRITE_WIRE_BUDGET_BYTES;
|
|
975
|
+
}
|
|
976
|
+
const DEFAULT_PROFILE_FILE_API_ABSOLUTE_PREFIXES = [
|
|
977
|
+
["/home", "agent"].join("/"),
|
|
978
|
+
["/home", "user"].join("/"),
|
|
979
|
+
"/tmp",
|
|
980
|
+
"/output"
|
|
981
|
+
];
|
|
982
|
+
function inlineContent(mount) {
|
|
983
|
+
const resource = mount.resource;
|
|
984
|
+
if (resource.kind !== "inline") throw new Error(`materializeProfileFileMounts: ${mount.path} requires an inline resource`);
|
|
985
|
+
if (typeof resource.content !== "string") throw new Error(`materializeProfileFileMounts: ${mount.path} inline resource requires string content`);
|
|
986
|
+
return resource.content;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Synchronous pre-flight validation of deferred inline mounts: the same
|
|
990
|
+
* content/path rules {@link materializeProfileFileMounts} enforces, runnable
|
|
991
|
+
* BEFORE a sandbox is provisioned. create() calls this ahead of its POST so
|
|
992
|
+
* client-detectable bad input (traversal paths, control characters,
|
|
993
|
+
* non-string content) fails without paying for a sandbox that would only be
|
|
994
|
+
* orphaned by the post-provision throw.
|
|
995
|
+
*/
|
|
996
|
+
function validateDeferredProfileFileMounts(files) {
|
|
997
|
+
for (const mount of files) {
|
|
998
|
+
inlineContent(mount);
|
|
999
|
+
validateProfileFilePath(mount.path);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function splitInlineProfileFileMounts(profile) {
|
|
1003
|
+
const files = profile.resources?.files ?? [];
|
|
1004
|
+
const deferredFiles = [];
|
|
1005
|
+
const keptFiles = [];
|
|
1006
|
+
for (const mount of files) if (mount.resource.kind === "inline") deferredFiles.push(mount);
|
|
1007
|
+
else keptFiles.push(mount);
|
|
1008
|
+
if (deferredFiles.length === 0) return {
|
|
1009
|
+
leanProfile: profile,
|
|
1010
|
+
deferredFiles
|
|
1011
|
+
};
|
|
1012
|
+
return {
|
|
1013
|
+
leanProfile: {
|
|
1014
|
+
...profile,
|
|
1015
|
+
resources: {
|
|
1016
|
+
...profile.resources ?? {},
|
|
1017
|
+
files: keptFiles
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
deferredFiles
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
function shellSingleQuote(value) {
|
|
1024
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1025
|
+
}
|
|
1026
|
+
function shellPath(path) {
|
|
1027
|
+
if (path === "~") return "\"$HOME\"";
|
|
1028
|
+
if (path.startsWith("~/")) {
|
|
1029
|
+
const rest = path.slice(2);
|
|
1030
|
+
return rest ? `"$HOME"/${shellSingleQuote(rest)}` : "\"$HOME\"";
|
|
1031
|
+
}
|
|
1032
|
+
return shellSingleQuote(path);
|
|
1033
|
+
}
|
|
1034
|
+
function validateProfileFilePath(path) {
|
|
1035
|
+
if (!path) throw new Error("materializeProfileFileMounts: file path is required");
|
|
1036
|
+
if (path.endsWith("/")) throw new Error(`materializeProfileFileMounts: refusing directory-shaped file path ${path}`);
|
|
1037
|
+
if (hasControlCharacter(path)) throw new Error(`materializeProfileFileMounts: refusing unsafe file path ${JSON.stringify(path)}`);
|
|
1038
|
+
if (path === "~" || /^~[^/]/.test(path)) throw new Error(`materializeProfileFileMounts: refusing unsupported home path ${path}`);
|
|
1039
|
+
if (hasUnsafeFileApiSegment(path)) throw new Error(`materializeProfileFileMounts: refusing unsafe file path ${path}`);
|
|
1040
|
+
}
|
|
1041
|
+
function hasUnsafeFileApiSegment(path) {
|
|
1042
|
+
return path.split("/").some((segment) => segment === "." || segment === ".." || segment === ".sidecar");
|
|
1043
|
+
}
|
|
1044
|
+
function hasControlCharacter(value) {
|
|
1045
|
+
for (let i = 0; i < value.length; i++) {
|
|
1046
|
+
const code = value.charCodeAt(i);
|
|
1047
|
+
if (code < 32 || code === 127) return true;
|
|
1048
|
+
}
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
function normalizeAbsolutePrefixes(prefixes) {
|
|
1052
|
+
return prefixes.map((prefix) => {
|
|
1053
|
+
const normalized = prefix.trim().replace(/\/+$/, "");
|
|
1054
|
+
if (!normalized.startsWith("/") || hasControlCharacter(normalized)) throw new Error(`materializeProfileFileMounts: fileApiAbsolutePrefixes must contain absolute paths; received ${JSON.stringify(prefix)}`);
|
|
1055
|
+
if (hasUnsafeFileApiSegment(normalized)) throw new Error(`materializeProfileFileMounts: fileApiAbsolutePrefixes contains unsafe path ${JSON.stringify(prefix)}`);
|
|
1056
|
+
return normalized;
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
function isAllowedAbsoluteFileApiPath(path, prefixes) {
|
|
1060
|
+
for (const prefix of prefixes) if (path === prefix || path.startsWith(`${prefix}/`)) return true;
|
|
1061
|
+
return false;
|
|
1062
|
+
}
|
|
1063
|
+
function fileApiTarget(mount, absolutePrefixes) {
|
|
1064
|
+
if (mount.path.startsWith("~/")) return null;
|
|
1065
|
+
if (mount.path.startsWith("/")) return isAllowedAbsoluteFileApiPath(mount.path, absolutePrefixes) ? mount.path : null;
|
|
1066
|
+
if (mount.path.startsWith("~")) return null;
|
|
1067
|
+
if (mount.path.length === 0) return null;
|
|
1068
|
+
return mount.path;
|
|
1069
|
+
}
|
|
1070
|
+
function isExecutableProfileFile(mount) {
|
|
1071
|
+
return mount.executable ?? PROFILE_BIN_DIR_RE.test(mount.path);
|
|
1072
|
+
}
|
|
1073
|
+
function profileFileMode(mount) {
|
|
1074
|
+
return isExecutableProfileFile(mount) ? 493 : void 0;
|
|
1075
|
+
}
|
|
1076
|
+
function fileApiSupportsMode(box) {
|
|
1077
|
+
return box.fs?.supportsWriteMode === true;
|
|
1078
|
+
}
|
|
1079
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1080
|
+
var ProfileFileMountExecTimeoutError = class extends Error {
|
|
1081
|
+
constructor(timeoutMs) {
|
|
1082
|
+
super(`exec exceeded ${timeoutMs}ms`);
|
|
1083
|
+
this.name = "ProfileFileMountExecTimeoutError";
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
function execWithTimeout(box, cmd, timeoutMs) {
|
|
1087
|
+
return new Promise((resolve, reject) => {
|
|
1088
|
+
let settled = false;
|
|
1089
|
+
const timer = setTimeout(() => {
|
|
1090
|
+
if (settled) return;
|
|
1091
|
+
settled = true;
|
|
1092
|
+
reject(new ProfileFileMountExecTimeoutError(timeoutMs));
|
|
1093
|
+
}, timeoutMs);
|
|
1094
|
+
box.exec(cmd, { timeoutMs }).then((res) => {
|
|
1095
|
+
if (settled) return;
|
|
1096
|
+
settled = true;
|
|
1097
|
+
clearTimeout(timer);
|
|
1098
|
+
resolve(res);
|
|
1099
|
+
}, (err) => {
|
|
1100
|
+
if (settled) return;
|
|
1101
|
+
settled = true;
|
|
1102
|
+
clearTimeout(timer);
|
|
1103
|
+
reject(err);
|
|
1104
|
+
});
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
const TRANSIENT_EXEC_STATUS_CODES = new Set([
|
|
1108
|
+
408,
|
|
1109
|
+
409,
|
|
1110
|
+
425,
|
|
1111
|
+
429,
|
|
1112
|
+
500,
|
|
1113
|
+
502,
|
|
1114
|
+
503,
|
|
1115
|
+
504
|
|
1116
|
+
]);
|
|
1117
|
+
const TRANSIENT_EXEC_CODE_RE = /^(ECONNRESET|ECONNREFUSED|ETIMEDOUT|EPIPE|ECONNABORTED)$/i;
|
|
1118
|
+
const TRANSIENT_EXEC_MESSAGE_RE = /\b(408|409|425|429|500|502|503|504)\b|rate.?limit|too many requests|\bfetch failed\b|network error|connection reset|socket hang up|timed? out|service unavailable|bad gateway|gateway timeout|internal server error|\b(?:sidecar|runtime|exec(?:ution)?|terminal|sandbox|service|command(?:s)?|proxy)\b.{0,80}\bnot ready\b|\bnot ready\b.{0,80}\b(?:sidecar|runtime|exec(?:ution)?|terminal|sandbox|service|command(?:s)?|proxy)\b/i;
|
|
1119
|
+
function errorStatus(err) {
|
|
1120
|
+
const rawStatus = err.status ?? err.statusCode ?? (err.response && typeof err.response === "object" ? err.response.status : void 0);
|
|
1121
|
+
if (typeof rawStatus === "number") return rawStatus;
|
|
1122
|
+
if (typeof rawStatus === "string" && /^\d+$/.test(rawStatus)) return Number(rawStatus);
|
|
1123
|
+
}
|
|
1124
|
+
function retryAfterMs(err, seen = /* @__PURE__ */ new Set()) {
|
|
1125
|
+
if (!err || typeof err !== "object") return void 0;
|
|
1126
|
+
if (seen.has(err)) return void 0;
|
|
1127
|
+
seen.add(err);
|
|
1128
|
+
const e = err;
|
|
1129
|
+
if (typeof e.retryAfterMs === "number") return e.retryAfterMs;
|
|
1130
|
+
return retryAfterMs(e.cause, seen);
|
|
1131
|
+
}
|
|
1132
|
+
function isTransientExecError(err, seen = /* @__PURE__ */ new Set()) {
|
|
1133
|
+
if (!err || typeof err !== "object") return false;
|
|
1134
|
+
if (seen.has(err)) return false;
|
|
1135
|
+
seen.add(err);
|
|
1136
|
+
const e = err;
|
|
1137
|
+
const status = errorStatus(e);
|
|
1138
|
+
if (status !== void 0 && TRANSIENT_EXEC_STATUS_CODES.has(status)) return true;
|
|
1139
|
+
if (typeof e.code === "string") {
|
|
1140
|
+
if (TRANSIENT_EXEC_CODE_RE.test(e.code)) return true;
|
|
1141
|
+
if (/rate.?limit|too.?many.?requests|429|server.?error|service.?unavailable/i.test(e.code)) return true;
|
|
1142
|
+
}
|
|
1143
|
+
if (typeof e.message === "string" && TRANSIENT_EXEC_MESSAGE_RE.test(e.message)) return true;
|
|
1144
|
+
return isTransientExecError(e.cause, seen);
|
|
1145
|
+
}
|
|
1146
|
+
function transientExecError(err) {
|
|
1147
|
+
if (err instanceof ProfileFileMountExecTimeoutError) return { retryable: false };
|
|
1148
|
+
if (isTransientExecError(err)) return {
|
|
1149
|
+
retryable: true,
|
|
1150
|
+
retryAfterMs: retryAfterMs(err)
|
|
1151
|
+
};
|
|
1152
|
+
return { retryable: false };
|
|
1153
|
+
}
|
|
1154
|
+
async function sha256Hex(content) {
|
|
1155
|
+
const bytes = new TextEncoder().encode(content);
|
|
1156
|
+
const webSubtle = globalThis.crypto?.subtle;
|
|
1157
|
+
if (webSubtle) {
|
|
1158
|
+
const digest = await webSubtle.digest("SHA-256", bytes);
|
|
1159
|
+
return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1160
|
+
}
|
|
1161
|
+
const { createHash } = await import("node:crypto");
|
|
1162
|
+
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
1163
|
+
}
|
|
1164
|
+
async function execProfileFileMount(box, mount, content, options, execState) {
|
|
1165
|
+
const maxRetries = options.maxRetries ?? PROFILE_FILE_MOUNT_MAX_RETRIES;
|
|
1166
|
+
const path = mount.path;
|
|
1167
|
+
const b64 = encodeTextForWire(content);
|
|
1168
|
+
const b64Chunks = [];
|
|
1169
|
+
for (let i = 0; i < b64.length; i += PROFILE_FILE_MOUNT_B64_CHUNK_CHARS) b64Chunks.push(b64.slice(i, i + PROFILE_FILE_MOUNT_B64_CHUNK_CHARS));
|
|
1170
|
+
const expectedSha256 = await sha256Hex(content);
|
|
1171
|
+
const dir = path.replace(/\/[^/]*$/, "");
|
|
1172
|
+
const executable = isExecutableProfileFile(mount);
|
|
1173
|
+
const q = shellPath(path);
|
|
1174
|
+
const qb64 = shellPath(`${path}.b64`);
|
|
1175
|
+
const qtmp = shellPath(`${path}.tmp`);
|
|
1176
|
+
const qpartPrefix = shellPath(`${path}.b64.part.`);
|
|
1177
|
+
const homeGuard = path.startsWith("~/") ? `[ -n "$HOME" ] || { echo ${shellSingleQuote(`materializeProfileFileMounts: HOME is unset for ${path}`)} >&2; exit 1; }; ` : "";
|
|
1178
|
+
const run = async (cmd) => {
|
|
1179
|
+
for (let attempt = 0;; attempt++) {
|
|
1180
|
+
if (execState.started && options.paceMs > 0) await sleep(options.paceMs);
|
|
1181
|
+
execState.started = true;
|
|
1182
|
+
try {
|
|
1183
|
+
return await execWithTimeout(box, cmd, options.execTimeoutMs);
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
const { retryable, retryAfterMs: retryAfter } = transientExecError(err);
|
|
1186
|
+
if (retryable && attempt < maxRetries) {
|
|
1187
|
+
const backoff = Math.min(PROFILE_FILE_MOUNT_RETRY_BASE_MS * 2 ** attempt, PROFILE_FILE_MOUNT_RETRY_MAX_MS);
|
|
1188
|
+
await sleep(Math.min(retryAfter ?? backoff, PROFILE_FILE_MOUNT_RETRY_MAX_MS));
|
|
1189
|
+
continue;
|
|
1190
|
+
}
|
|
1191
|
+
throw new Error(`materializeProfileFileMounts: exec failed for ${path}`, { cause: err });
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
const step = async (cmd) => {
|
|
1196
|
+
const result = await run(`${homeGuard}${cmd}`);
|
|
1197
|
+
if (result.exitCode !== 0) throw new Error(`materializeProfileFileMounts: failed to write ${path} (exit ${result.exitCode}): ${result.stderr.slice(0, 500)}`);
|
|
1198
|
+
};
|
|
1199
|
+
await step(dir ? `mkdir -p ${shellPath(dir)}` : ":");
|
|
1200
|
+
for (let i = 0; i < b64Chunks.length; i++) {
|
|
1201
|
+
const slice = b64Chunks[i];
|
|
1202
|
+
if (slice === void 0) continue;
|
|
1203
|
+
await step(`printf '%s' '${slice}' > ${shellPath(`${path}.b64.part.${i}`)}`);
|
|
1204
|
+
}
|
|
1205
|
+
const chmod = executable ? `chmod +x ${q} || exit 1; ` : "";
|
|
1206
|
+
const checksumMismatch = shellSingleQuote(`materializeProfileFileMounts: checksum mismatch for ${path}`);
|
|
1207
|
+
await step(`cleanup() { ${`rm -f ${qb64} ${qtmp}; i=0; while [ "$i" -lt ${b64Chunks.length} ]; do rm -f ${qpartPrefix}$i; i=$((i+1)); done`}; }; trap cleanup EXIT; expected='${expectedSha256}'; if [ -f ${q} ] && [ "$(sha256sum ${q} | awk '{print $1}')" = "$expected" ]; then ${chmod}exit 0; fi; : > ${qb64} && i=0; while [ "$i" -lt ${b64Chunks.length} ]; do cat ${qpartPrefix}$i >> ${qb64} || exit 1; i=$((i+1)); done && base64 -d ${qb64} > ${qtmp} && [ "$(sha256sum ${qtmp} | awk '{print $1}')" = "$expected" ] || { echo ${checksumMismatch} >&2; exit 1; }; mv ${qtmp} ${q} && ${executable ? `chmod +x ${q} && ` : ""}[ "$(sha256sum ${q} | awk '{print $1}')" = "$expected" ] || { echo ${checksumMismatch} >&2; exit 1; }`);
|
|
1208
|
+
}
|
|
1209
|
+
async function materializeProfileFileMounts(box, files, options = {}) {
|
|
1210
|
+
const execTimeoutMs = options.execTimeoutMs ?? PROFILE_FILE_MOUNT_EXEC_TIMEOUT_MS;
|
|
1211
|
+
const paceMs = options.paceMs ?? PROFILE_FILE_MOUNT_PACE_MS;
|
|
1212
|
+
const maxRetries = options.maxRetries ?? PROFILE_FILE_MOUNT_MAX_RETRIES;
|
|
1213
|
+
const absolutePrefixes = normalizeAbsolutePrefixes(options.fileApiAbsolutePrefixes ?? DEFAULT_PROFILE_FILE_API_ABSOLUTE_PREFIXES);
|
|
1214
|
+
const fs = box.fs;
|
|
1215
|
+
const fileApiAvailable = typeof fs?.writeMany === "function";
|
|
1216
|
+
const modeAwareFileApi = fileApiSupportsMode(box);
|
|
1217
|
+
const uploadDataFn = fs?.uploadData;
|
|
1218
|
+
const viaFileApi = [];
|
|
1219
|
+
const viaExec = [];
|
|
1220
|
+
const viaUpload = [];
|
|
1221
|
+
for (const mount of files) {
|
|
1222
|
+
const content = inlineContent(mount);
|
|
1223
|
+
validateProfileFilePath(mount.path);
|
|
1224
|
+
const target = fileApiAvailable ? fileApiTarget(mount, absolutePrefixes) : null;
|
|
1225
|
+
const executable = isExecutableProfileFile(mount);
|
|
1226
|
+
if (target !== null && (!executable || modeAwareFileApi)) {
|
|
1227
|
+
const mode = profileFileMode(mount);
|
|
1228
|
+
const contentBytes = new TextEncoder().encode(content).byteLength;
|
|
1229
|
+
if (!fitsSingleShotWrite(content, contentBytes)) {
|
|
1230
|
+
if (typeof uploadDataFn !== "function") throw new Error(`materializeProfileFileMounts: ${mount.path} (${contentBytes} bytes decoded) does not fit a gateway-safe single-shot write once JSON-serialized, and the box does not expose fs.uploadData for chunked delivery`);
|
|
1231
|
+
viaUpload.push({
|
|
1232
|
+
path: target,
|
|
1233
|
+
content,
|
|
1234
|
+
...mode !== void 0 ? { mode } : {}
|
|
1235
|
+
});
|
|
1236
|
+
continue;
|
|
1237
|
+
}
|
|
1238
|
+
viaFileApi.push({
|
|
1239
|
+
path: target,
|
|
1240
|
+
content,
|
|
1241
|
+
...mode !== void 0 ? { mode } : {}
|
|
1242
|
+
});
|
|
1243
|
+
} else viaExec.push({
|
|
1244
|
+
mount,
|
|
1245
|
+
content
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
if (viaFileApi.length > 0) try {
|
|
1249
|
+
await fs?.writeMany(viaFileApi, {
|
|
1250
|
+
paceMs,
|
|
1251
|
+
maxRetries
|
|
1252
|
+
});
|
|
1253
|
+
} catch (err) {
|
|
1254
|
+
throw new Error("materializeProfileFileMounts: file API batch write failed", { cause: err });
|
|
1255
|
+
}
|
|
1256
|
+
if (viaUpload.length > 0) {
|
|
1257
|
+
if (typeof uploadDataFn !== "function") throw new Error("materializeProfileFileMounts: viaUpload entries exist but fs.uploadData is unavailable");
|
|
1258
|
+
for (const item of viaUpload) try {
|
|
1259
|
+
await uploadDataFn(item.path, item.content, {
|
|
1260
|
+
...item.mode !== void 0 ? { mode: item.mode } : {},
|
|
1261
|
+
paceMs,
|
|
1262
|
+
maxRetries
|
|
1263
|
+
});
|
|
1264
|
+
} catch (err) {
|
|
1265
|
+
throw new Error(`materializeProfileFileMounts: uploadData failed for ${item.path}`, { cause: err });
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
const execState = { started: false };
|
|
1269
|
+
for (const item of viaExec) await execProfileFileMount(box, item.mount, item.content, {
|
|
1270
|
+
execTimeoutMs,
|
|
1271
|
+
paceMs,
|
|
1272
|
+
maxRetries
|
|
1273
|
+
}, execState);
|
|
1274
|
+
return {
|
|
1275
|
+
written: viaFileApi.length + viaExec.length + viaUpload.length,
|
|
1276
|
+
viaFileApi: viaFileApi.length,
|
|
1277
|
+
viaExec: viaExec.length,
|
|
1278
|
+
viaUpload: viaUpload.length
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
//#endregion
|
|
949
1282
|
//#region src/session-events.ts
|
|
950
1283
|
async function broadcastSessionEvent(client, sessionId, event) {
|
|
951
1284
|
if (!sessionId.trim()) throw new ValidationError("Session ID is required");
|
|
@@ -980,11 +1313,6 @@ async function broadcastSessionAgentEvent(client, sessionId, event) {
|
|
|
980
1313
|
}
|
|
981
1314
|
//#endregion
|
|
982
1315
|
//#region src/client.ts
|
|
983
|
-
/**
|
|
984
|
-
* Sandbox Client
|
|
985
|
-
*
|
|
986
|
-
* Main client class for interacting with the Sandbox API.
|
|
987
|
-
*/
|
|
988
1316
|
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
989
1317
|
/**
|
|
990
1318
|
* Default time budget for `create()` — the full create-and-reach-running
|
|
@@ -1326,6 +1654,22 @@ var SandboxClient = class {
|
|
|
1326
1654
|
...backend,
|
|
1327
1655
|
type: backend.type ?? "opencode"
|
|
1328
1656
|
} : void 0;
|
|
1657
|
+
const autoMaterializeProfileFiles = options?.autoMaterializeProfileFiles ?? true;
|
|
1658
|
+
let deferredProfileFiles = [];
|
|
1659
|
+
let profileFilesFailOnError = true;
|
|
1660
|
+
let requestBackend = resolvedBackend;
|
|
1661
|
+
if (autoMaterializeProfileFiles && resolvedBackend?.profile && typeof resolvedBackend.profile === "object") {
|
|
1662
|
+
const split = splitInlineProfileFileMounts(resolvedBackend.profile);
|
|
1663
|
+
deferredProfileFiles = split.deferredFiles;
|
|
1664
|
+
if (deferredProfileFiles.length > 0) {
|
|
1665
|
+
requestBackend = {
|
|
1666
|
+
...resolvedBackend,
|
|
1667
|
+
profile: split.leanProfile
|
|
1668
|
+
};
|
|
1669
|
+
profileFilesFailOnError = resolvedBackend.profile.resources?.failOnError !== false;
|
|
1670
|
+
if (profileFilesFailOnError) validateDeferredProfileFileMounts(deferredProfileFiles);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1329
1673
|
const resources = normalizeSandboxResources(options?.resources, options?.driver);
|
|
1330
1674
|
const postDeadline = AbortSignal.timeout(timeoutMs);
|
|
1331
1675
|
const postSignal = requestOptions?.signal ? AbortSignal.any([requestOptions.signal, postDeadline]) : postDeadline;
|
|
@@ -1340,7 +1684,7 @@ var SandboxClient = class {
|
|
|
1340
1684
|
bare: options?.bare,
|
|
1341
1685
|
...options?.publicEdge === false ? { publicEdge: false } : {},
|
|
1342
1686
|
driver: options?.driver,
|
|
1343
|
-
backend:
|
|
1687
|
+
backend: requestBackend,
|
|
1344
1688
|
permissions: options?.permissions,
|
|
1345
1689
|
env: options?.env,
|
|
1346
1690
|
resources,
|
|
@@ -1401,7 +1745,7 @@ var SandboxClient = class {
|
|
|
1401
1745
|
}
|
|
1402
1746
|
if (!response) throw createTimeoutError();
|
|
1403
1747
|
const data = await response.json();
|
|
1404
|
-
const instance = new SandboxInstance(this, this.parseInfo(data),
|
|
1748
|
+
const instance = new SandboxInstance(this, this.parseInfo(data), requestBackend);
|
|
1405
1749
|
if (instance.status === "provisioning" || instance.status === "pending") {
|
|
1406
1750
|
const remainingMs = Math.max(0, deadline - Date.now());
|
|
1407
1751
|
await instance.waitFor("running", {
|
|
@@ -1409,6 +1753,28 @@ var SandboxClient = class {
|
|
|
1409
1753
|
signal: requestOptions?.signal
|
|
1410
1754
|
});
|
|
1411
1755
|
}
|
|
1756
|
+
if (deferredProfileFiles.length > 0) {
|
|
1757
|
+
if (instance.status !== "running") {
|
|
1758
|
+
const paths = deferredProfileFiles.map((file) => file.path);
|
|
1759
|
+
const message = `Sandbox ${instance.id} reached status "${instance.status}" before its ${deferredProfileFiles.length} deferred inline profile file mount(s) [${paths.join(", ")}] could be materialized. The sandbox was NOT deleted — inspect it, or recreate with autoMaterializeProfileFiles: false.`;
|
|
1760
|
+
if (!profileFilesFailOnError) {
|
|
1761
|
+
console.warn(`[sandbox.create] ${message}`);
|
|
1762
|
+
return instance;
|
|
1763
|
+
}
|
|
1764
|
+
throw new PartialFailureError(message, "PROFILE_FILES_MATERIALIZE_FAILED", 502, void 0, paths.map((path) => ({ path })));
|
|
1765
|
+
}
|
|
1766
|
+
try {
|
|
1767
|
+
await materializeProfileFileMounts(instance, deferredProfileFiles);
|
|
1768
|
+
} catch (err) {
|
|
1769
|
+
const paths = deferredProfileFiles.map((file) => file.path);
|
|
1770
|
+
const message = `Sandbox ${instance.id} is RUNNING but INCOMPLETELY PROVISIONED: materialization of its ${deferredProfileFiles.length} deferred inline profile file mount(s) failed partway; some or all of [${paths.join(", ")}] may be missing in the sandbox. The sandbox was NOT deleted — inspect it, retry writing the files yourself, or delete it once you've recovered what you need. Cause: ${err instanceof Error ? err.message : String(err)}`;
|
|
1771
|
+
if (!profileFilesFailOnError) {
|
|
1772
|
+
console.warn(`[sandbox.create] ${message}`);
|
|
1773
|
+
return instance;
|
|
1774
|
+
}
|
|
1775
|
+
throw new PartialFailureError(message, "PROFILE_FILES_MATERIALIZE_FAILED", 502, void 0, paths.map((path) => ({ path })));
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1412
1778
|
return instance;
|
|
1413
1779
|
}
|
|
1414
1780
|
/**
|
|
@@ -2298,4 +2664,4 @@ var TeamsClient = class {
|
|
|
2298
2664
|
}
|
|
2299
2665
|
};
|
|
2300
2666
|
//#endregion
|
|
2301
|
-
export {
|
|
2667
|
+
export { validateDeferredProfileFileMounts as a, DEFAULT_SANDBOX_SIZE as c, resolveSandboxResources as d, sandboxResourcesForSize as f, splitInlineProfileFileMounts as i, SANDBOX_SIZE_PRESETS as l, SandboxClient as n, SandboxFleet as o, materializeProfileFileMounts as r, SandboxFleetClient as s, IntelligenceClient as t, SANDBOX_SIZE_PRESET_NAMES as u };
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as SandboxInstance } from "./sandbox-
|
|
3
|
-
import { i as SandboxClient } from "./client-
|
|
1
|
+
import { B as CreateSandboxOptions, Mr as SandboxStatus, Wn as SandboxClientConfig, cn as PreviewLinkManager, nn as NetworkConfig, nt as ExecOptions, rt as ExecResult, sn as PreviewLinkInfo, xr as SandboxInfo } from "./types-LNLeU9Ub.js";
|
|
2
|
+
import { n as SandboxInstance } from "./sandbox-B9P4tyt4.js";
|
|
3
|
+
import { i as SandboxClient } from "./client-CSaBJ8wD.js";
|
|
4
4
|
import { a as NotFoundError, c as SandboxError, d as ServerError, f as StateError, i as NetworkError, l as SandboxErrorJson, m as ValidationError, n as CapabilityError, o as PartialFailureError, p as TimeoutError, s as QuotaError, t as AuthError, u as SandboxFailureDetail } from "./errors-CNCz3Ms9.js";
|
|
5
5
|
export { AuthError, CapabilityError, type CreateSandboxOptions, type ExecOptions, type ExecResult, type NetworkConfig, NetworkError, NotFoundError, PartialFailureError, type PreviewLinkInfo, type PreviewLinkManager, QuotaError, SandboxClient as Sandbox, SandboxClient, type SandboxClientConfig, SandboxError, type SandboxErrorJson, type SandboxFailureDetail, type SandboxInfo, SandboxInstance, type SandboxStatus, ServerError, StateError, TimeoutError, ValidationError };
|
package/dist/core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { a as NotFoundError, c as SandboxError, d as TimeoutError, f as ValidationError, i as NetworkError, l as ServerError, n as CapabilityError, o as PartialFailureError, s as QuotaError, t as AuthError, u as StateError } from "./errors-wd266B9Q.js";
|
|
2
|
-
import { t as SandboxInstance } from "./sandbox-
|
|
3
|
-
import { n as SandboxClient } from "./client-
|
|
2
|
+
import { t as SandboxInstance } from "./sandbox-KiKLRbR_.js";
|
|
3
|
+
import { n as SandboxClient } from "./client-_OBj4sNO.js";
|
|
4
4
|
export { AuthError, CapabilityError, NetworkError, NotFoundError, PartialFailureError, QuotaError, SandboxClient as Sandbox, SandboxClient, SandboxError, SandboxInstance, ServerError, StateError, TimeoutError, ValidationError };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as SandboxInstance, t as HttpClient } from "./sandbox-
|
|
1
|
+
import { B as CreateSandboxOptions } from "./types-LNLeU9Ub.js";
|
|
2
|
+
import { n as SandboxInstance, t as HttpClient } from "./sandbox-B9P4tyt4.js";
|
|
3
3
|
|
|
4
4
|
//#region src/tangle/abi.d.ts
|
|
5
5
|
/**
|