@boxrouter/sdk 0.0.1-alpha.0 → 0.12.190
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/NOTICE +29 -5
- package/README.md +497 -24
- package/dist/addresses.d.ts +5 -0
- package/dist/addresses.js +10 -0
- package/dist/api-error.d.ts +62 -0
- package/dist/api-error.js +264 -0
- package/dist/boxrouter.d.ts +68 -0
- package/dist/boxrouter.js +291 -0
- package/dist/browser-session/index.d.ts +17 -0
- package/dist/browser-session/index.js +48 -0
- package/dist/browser-session/operations.gen.d.ts +272 -0
- package/dist/browser-session/operations.gen.js +58 -0
- package/dist/browser-session/responseContracts/api_keys.d.ts +2 -0
- package/dist/browser-session/responseContracts/api_keys.js +10 -0
- package/dist/browser-session/responseContracts/credits.d.ts +2 -0
- package/dist/browser-session/responseContracts/credits.js +8 -0
- package/dist/browser-session/responseContracts/github.d.ts +2 -0
- package/dist/browser-session/responseContracts/github.js +11 -0
- package/dist/browser-session/responseContracts/identity.d.ts +2 -0
- package/dist/browser-session/responseContracts/identity.js +30 -0
- package/dist/browser-session/responseContracts/organizations.d.ts +2 -0
- package/dist/browser-session/responseContracts/organizations.js +17 -0
- package/dist/browser-session/responseContracts/privacy.d.ts +2 -0
- package/dist/browser-session/responseContracts/privacy.js +7 -0
- package/dist/browser-session/responseContracts.gen.d.ts +3 -0
- package/dist/browser-session/responseContracts.gen.js +10 -0
- package/dist/browser-session/responseValidators/api_keys-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/api_keys-diagnostics.d.cts +4 -0
- package/dist/browser-session/responseValidators/api_keys.cjs +2 -0
- package/dist/browser-session/responseValidators/api_keys.d.cts +4 -0
- package/dist/browser-session/responseValidators/credits-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/credits-diagnostics.d.cts +3 -0
- package/dist/browser-session/responseValidators/credits.cjs +2 -0
- package/dist/browser-session/responseValidators/credits.d.cts +3 -0
- package/dist/browser-session/responseValidators/github-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/github-diagnostics.d.cts +3 -0
- package/dist/browser-session/responseValidators/github.cjs +2 -0
- package/dist/browser-session/responseValidators/github.d.cts +3 -0
- package/dist/browser-session/responseValidators/identity-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/identity-diagnostics.d.cts +23 -0
- package/dist/browser-session/responseValidators/identity.cjs +2 -0
- package/dist/browser-session/responseValidators/identity.d.cts +23 -0
- package/dist/browser-session/responseValidators/organizations-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/organizations-diagnostics.d.cts +15 -0
- package/dist/browser-session/responseValidators/organizations.cjs +2 -0
- package/dist/browser-session/responseValidators/organizations.d.cts +15 -0
- package/dist/browser-session/responseValidators/privacy-diagnostics.cjs +1 -0
- package/dist/browser-session/responseValidators/privacy-diagnostics.d.cts +2 -0
- package/dist/browser-session/responseValidators/privacy.cjs +2 -0
- package/dist/browser-session/responseValidators/privacy.d.cts +2 -0
- package/dist/client/client.gen.d.ts +1 -1
- package/dist/client/client.gen.js +46 -94
- package/dist/client/index.d.ts +10 -10
- package/dist/client/index.js +16 -5
- package/dist/client/types.gen.d.ts +6 -6
- package/dist/client/types.gen.js +2 -1
- package/dist/client/utils.gen.d.ts +2 -2
- package/dist/client/utils.gen.js +31 -20
- package/dist/client.gen.d.ts +2 -2
- package/dist/client.gen.js +5 -2
- package/dist/command-check.gen.d.ts +14 -0
- package/dist/command-check.gen.js +23 -0
- package/dist/command-input.gen.d.ts +6 -0
- package/dist/command-input.gen.js +45 -0
- package/dist/core/auth.gen.js +5 -1
- package/dist/core/binaryStream.d.ts +8 -0
- package/dist/core/binaryStream.js +76 -0
- package/dist/core/bodySerializer.gen.d.ts +1 -1
- package/dist/core/bodySerializer.gen.js +8 -5
- package/dist/core/commandValidators.cjs +1 -0
- package/dist/core/commandValidators.d.cts +14 -0
- package/dist/core/eventValidation.d.ts +17 -0
- package/dist/core/eventValidation.js +56 -0
- package/dist/core/eventValidators.cjs +1 -0
- package/dist/core/eventValidators.d.cts +2 -0
- package/dist/core/json.d.ts +3 -0
- package/dist/core/json.js +33 -0
- package/dist/core/params.gen.js +4 -1
- package/dist/core/pathSerializer.gen.js +20 -11
- package/dist/core/queryKeySerializer.gen.js +12 -6
- package/dist/core/responseContracts/actions.d.ts +2 -0
- package/dist/core/responseContracts/actions.js +30 -0
- package/dist/core/responseContracts/agents.d.ts +2 -0
- package/dist/core/responseContracts/agents.js +7 -0
- package/dist/core/responseContracts/artifacts.d.ts +2 -0
- package/dist/core/responseContracts/artifacts.js +8 -0
- package/dist/core/responseContracts/commands.d.ts +2 -0
- package/dist/core/responseContracts/commands.js +6 -0
- package/dist/core/responseContracts/credits.d.ts +2 -0
- package/dist/core/responseContracts/credits.js +27 -0
- package/dist/core/responseContracts/files.d.ts +2 -0
- package/dist/core/responseContracts/files.js +15 -0
- package/dist/core/responseContracts/github.d.ts +2 -0
- package/dist/core/responseContracts/github.js +8 -0
- package/dist/core/responseContracts/images.d.ts +2 -0
- package/dist/core/responseContracts/images.js +8 -0
- package/dist/core/responseContracts/launchRuns.d.ts +2 -0
- package/dist/core/responseContracts/launchRuns.js +10 -0
- package/dist/core/responseContracts/launches.d.ts +2 -0
- package/dist/core/responseContracts/launches.js +10 -0
- package/dist/core/responseContracts/operations.d.ts +2 -0
- package/dist/core/responseContracts/operations.js +7 -0
- package/dist/core/responseContracts/previews.d.ts +2 -0
- package/dist/core/responseContracts/previews.js +8 -0
- package/dist/core/responseContracts/pricing.d.ts +2 -0
- package/dist/core/responseContracts/pricing.js +6 -0
- package/dist/core/responseContracts/processes.d.ts +2 -0
- package/dist/core/responseContracts/processes.js +11 -0
- package/dist/core/responseContracts/provider_accounts.d.ts +2 -0
- package/dist/core/responseContracts/provider_accounts.js +13 -0
- package/dist/core/responseContracts/providers.d.ts +2 -0
- package/dist/core/responseContracts/providers.js +6 -0
- package/dist/core/responseContracts/routing.d.ts +2 -0
- package/dist/core/responseContracts/routing.js +8 -0
- package/dist/core/responseContracts/sandboxes.d.ts +2 -0
- package/dist/core/responseContracts/sandboxes.js +15 -0
- package/dist/core/responseContracts/secrets.d.ts +2 -0
- package/dist/core/responseContracts/secrets.js +8 -0
- package/dist/core/responseContracts/spend_limits.d.ts +2 -0
- package/dist/core/responseContracts/spend_limits.js +8 -0
- package/dist/core/responseContracts/terminals.d.ts +2 -0
- package/dist/core/responseContracts/terminals.js +11 -0
- package/dist/core/responseContracts/usage.d.ts +2 -0
- package/dist/core/responseContracts/usage.js +7 -0
- package/dist/core/responseContracts/volumes.d.ts +2 -0
- package/dist/core/responseContracts/volumes.js +19 -0
- package/dist/core/responseContracts.gen.d.ts +3 -0
- package/dist/core/responseContracts.gen.js +27 -0
- package/dist/core/responseModes.d.ts +19 -0
- package/dist/core/responseModes.js +13 -0
- package/dist/core/responseValidation.d.ts +44 -0
- package/dist/core/responseValidation.js +174 -0
- package/dist/core/responseValidators/actions-diagnostics.cjs +4 -0
- package/dist/core/responseValidators/actions-diagnostics.d.cts +24 -0
- package/dist/core/responseValidators/actions.cjs +2 -0
- package/dist/core/responseValidators/actions.d.cts +24 -0
- package/dist/core/responseValidators/agents-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/agents-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/agents.cjs +2 -0
- package/dist/core/responseValidators/agents.d.cts +2 -0
- package/dist/core/responseValidators/artifacts-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/artifacts-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/artifacts.cjs +2 -0
- package/dist/core/responseValidators/artifacts.d.cts +2 -0
- package/dist/core/responseValidators/commands-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/commands-diagnostics.d.cts +1 -0
- package/dist/core/responseValidators/commands.cjs +2 -0
- package/dist/core/responseValidators/commands.d.cts +1 -0
- package/dist/core/responseValidators/compact.cjs +122 -0
- package/dist/core/responseValidators/credits-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/credits-diagnostics.d.cts +21 -0
- package/dist/core/responseValidators/credits.cjs +2 -0
- package/dist/core/responseValidators/credits.d.cts +21 -0
- package/dist/core/responseValidators/files-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/files-diagnostics.d.cts +5 -0
- package/dist/core/responseValidators/files.cjs +2 -0
- package/dist/core/responseValidators/files.d.cts +5 -0
- package/dist/core/responseValidators/github-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/github-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/github.cjs +2 -0
- package/dist/core/responseValidators/github.d.cts +2 -0
- package/dist/core/responseValidators/images-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/images-diagnostics.d.cts +3 -0
- package/dist/core/responseValidators/images.cjs +2 -0
- package/dist/core/responseValidators/images.d.cts +3 -0
- package/dist/core/responseValidators/launchRuns-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/launchRuns-diagnostics.d.cts +5 -0
- package/dist/core/responseValidators/launchRuns.cjs +2 -0
- package/dist/core/responseValidators/launchRuns.d.cts +5 -0
- package/dist/core/responseValidators/launches-diagnostics.cjs +10 -0
- package/dist/core/responseValidators/launches-diagnostics.d.cts +5 -0
- package/dist/core/responseValidators/launches.cjs +2 -0
- package/dist/core/responseValidators/launches.d.cts +5 -0
- package/dist/core/responseValidators/operations-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/operations-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/operations.cjs +2 -0
- package/dist/core/responseValidators/operations.d.cts +2 -0
- package/dist/core/responseValidators/previews-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/previews-diagnostics.d.cts +3 -0
- package/dist/core/responseValidators/previews.cjs +2 -0
- package/dist/core/responseValidators/previews.d.cts +3 -0
- package/dist/core/responseValidators/pricing-diagnostics.cjs +7 -0
- package/dist/core/responseValidators/pricing-diagnostics.d.cts +1 -0
- package/dist/core/responseValidators/pricing.cjs +2 -0
- package/dist/core/responseValidators/pricing.d.cts +1 -0
- package/dist/core/responseValidators/processes-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/processes-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/processes.cjs +2 -0
- package/dist/core/responseValidators/processes.d.cts +2 -0
- package/dist/core/responseValidators/provider_accounts-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/provider_accounts-diagnostics.d.cts +8 -0
- package/dist/core/responseValidators/provider_accounts.cjs +2 -0
- package/dist/core/responseValidators/provider_accounts.d.cts +8 -0
- package/dist/core/responseValidators/providers-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/providers-diagnostics.d.cts +1 -0
- package/dist/core/responseValidators/providers.cjs +2 -0
- package/dist/core/responseValidators/providers.d.cts +1 -0
- package/dist/core/responseValidators/routing-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/routing-diagnostics.d.cts +3 -0
- package/dist/core/responseValidators/routing.cjs +2 -0
- package/dist/core/responseValidators/routing.d.cts +3 -0
- package/dist/core/responseValidators/sandboxes-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/sandboxes-diagnostics.d.cts +10 -0
- package/dist/core/responseValidators/sandboxes.cjs +2 -0
- package/dist/core/responseValidators/sandboxes.d.cts +10 -0
- package/dist/core/responseValidators/secrets-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/secrets-diagnostics.d.cts +1 -0
- package/dist/core/responseValidators/secrets.cjs +2 -0
- package/dist/core/responseValidators/secrets.d.cts +1 -0
- package/dist/core/responseValidators/spend_limits-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/spend_limits-diagnostics.d.cts +3 -0
- package/dist/core/responseValidators/spend_limits.cjs +2 -0
- package/dist/core/responseValidators/spend_limits.d.cts +3 -0
- package/dist/core/responseValidators/terminals-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/terminals-diagnostics.d.cts +2 -0
- package/dist/core/responseValidators/terminals.cjs +2 -0
- package/dist/core/responseValidators/terminals.d.cts +2 -0
- package/dist/core/responseValidators/usage-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/usage-diagnostics.d.cts +1 -0
- package/dist/core/responseValidators/usage.cjs +2 -0
- package/dist/core/responseValidators/usage.d.cts +1 -0
- package/dist/core/responseValidators/volumes-diagnostics.cjs +1 -0
- package/dist/core/responseValidators/volumes-diagnostics.d.cts +10 -0
- package/dist/core/responseValidators/volumes.cjs +2 -0
- package/dist/core/responseValidators/volumes.d.cts +10 -0
- package/dist/core/serverSentEvents.gen.d.ts +21 -62
- package/dist/core/serverSentEvents.gen.js +297 -116
- package/dist/core/streamErrors.d.ts +32 -0
- package/dist/core/streamErrors.js +51 -0
- package/dist/core/types.gen.d.ts +2 -2
- package/dist/core/types.gen.js +2 -1
- package/dist/core/utils.gen.d.ts +1 -1
- package/dist/core/utils.gen.js +16 -10
- package/dist/creation.gen.d.ts +21 -0
- package/dist/creation.gen.js +35 -0
- package/dist/data-origin.d.ts +25 -0
- package/dist/data-origin.js +57 -0
- package/dist/error-codes.gen.d.ts +2 -0
- package/dist/error-codes.gen.js +2 -0
- package/dist/idempotency.gen.d.ts +1 -0
- package/dist/idempotency.gen.js +60 -0
- package/dist/images.d.ts +74 -0
- package/dist/images.js +88 -0
- package/dist/index.d.ts +22 -2
- package/dist/index.js +79 -1
- package/dist/launch-input.gen.d.ts +9 -0
- package/dist/launch-input.gen.js +83 -0
- package/dist/launch.d.ts +28 -0
- package/dist/launch.js +222 -0
- package/dist/namespace-actions.d.mts +307 -0
- package/dist/namespace-actions.mjs +595 -0
- package/dist/namespace-agents.d.mts +33 -0
- package/dist/namespace-agents.mjs +40 -0
- package/dist/namespace-artifacts.d.mts +46 -0
- package/dist/namespace-artifacts.mjs +69 -0
- package/dist/namespace-base.d.mts +7 -0
- package/dist/namespace-base.mjs +7 -0
- package/dist/namespace-commands.d.mts +57 -0
- package/dist/namespace-commands.mjs +57 -0
- package/dist/namespace-credits.d.mts +213 -0
- package/dist/namespace-credits.mjs +476 -0
- package/dist/namespace-files.d.mts +203 -0
- package/dist/namespace-files.mjs +334 -0
- package/dist/namespace-github.d.mts +50 -0
- package/dist/namespace-github.mjs +68 -0
- package/dist/namespace-images.d.mts +52 -0
- package/dist/namespace-images.mjs +78 -0
- package/dist/namespace-launch_runs.d.mts +89 -0
- package/dist/namespace-launch_runs.mjs +133 -0
- package/dist/namespace-launches.d.mts +89 -0
- package/dist/namespace-launches.mjs +133 -0
- package/dist/namespace-operations.d.mts +45 -0
- package/dist/namespace-operations.mjs +52 -0
- package/dist/namespace-previews.d.mts +79 -0
- package/dist/namespace-previews.mjs +101 -0
- package/dist/namespace-pricing.d.mts +31 -0
- package/dist/namespace-pricing.mjs +22 -0
- package/dist/namespace-processes.d.mts +125 -0
- package/dist/namespace-processes.mjs +184 -0
- package/dist/namespace-provider_accounts.d.mts +156 -0
- package/dist/namespace-provider_accounts.mjs +241 -0
- package/dist/namespace-providers.d.mts +28 -0
- package/dist/namespace-providers.mjs +24 -0
- package/dist/namespace-routing.d.mts +64 -0
- package/dist/namespace-routing.mjs +86 -0
- package/dist/namespace-sandboxes.d.mts +287 -0
- package/dist/namespace-sandboxes.mjs +402 -0
- package/dist/namespace-secrets.d.mts +46 -0
- package/dist/namespace-secrets.mjs +68 -0
- package/dist/namespace-spend_limits.d.mts +48 -0
- package/dist/namespace-spend_limits.mjs +70 -0
- package/dist/namespace-terminals.d.mts +112 -0
- package/dist/namespace-terminals.mjs +177 -0
- package/dist/namespace-usage.d.mts +46 -0
- package/dist/namespace-usage.mjs +53 -0
- package/dist/namespace-volumes.d.mts +110 -0
- package/dist/namespace-volumes.mjs +269 -0
- package/dist/operations.d.ts +14 -0
- package/dist/operations.js +31 -0
- package/dist/retry.d.ts +8 -0
- package/dist/retry.js +63 -0
- package/dist/routing-choices.gen.d.ts +132 -0
- package/dist/routing-choices.gen.js +136 -0
- package/dist/routing.d.ts +23 -0
- package/dist/routing.js +38 -0
- package/dist/sandbox-handle.gen.d.ts +8 -0
- package/dist/sandbox-handle.gen.js +14 -0
- package/dist/sandboxes.d.ts +213 -0
- package/dist/sandboxes.js +507 -0
- package/dist/sdk.gen.d.ts +2016 -12
- package/dist/sdk.gen.js +3862 -16
- package/dist/server-timing.d.ts +19 -0
- package/dist/server-timing.gen.d.ts +265 -0
- package/dist/server-timing.gen.js +254 -0
- package/dist/server-timing.js +421 -0
- package/dist/spend-limits.d.ts +17 -0
- package/dist/spend-limits.js +26 -0
- package/dist/telemetry.d.ts +51 -0
- package/dist/telemetry.gen.d.ts +1 -0
- package/dist/telemetry.gen.js +5 -0
- package/dist/telemetry.js +438 -0
- package/dist/terminal.d.ts +61 -0
- package/dist/terminal.js +266 -0
- package/dist/transfer.d.ts +75 -0
- package/dist/transfer.js +389 -0
- package/dist/types.gen.d.ts +14936 -110
- package/dist/types.gen.js +2 -1
- package/dist/user-agent.d.ts +2 -0
- package/dist/user-agent.js +18 -0
- package/dist/version.gen.d.ts +1 -0
- package/dist/version.gen.js +5 -0
- package/dist/volumes.d.ts +33 -0
- package/dist/volumes.js +221 -0
- package/dist/waits.d.ts +31 -0
- package/dist/waits.js +42 -0
- package/dist/workflow-policy.gen.d.ts +41 -0
- package/dist/workflow-policy.gen.js +45 -0
- package/package.json +124 -14
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SandboxFiles = exports.ProcessHandle = exports.SandboxProcesses = exports.SandboxPreviews = exports.SandboxHandle = exports.SandboxResources = void 0;
|
|
4
|
+
exports.mutationOptions = mutationOptions;
|
|
5
|
+
exports.decodeBase64 = decodeBase64;
|
|
6
|
+
const command_check_gen_1 = require("./command-check.gen");
|
|
7
|
+
const command_input_gen_1 = require("./command-input.gen");
|
|
8
|
+
const api_error_1 = require("./api-error");
|
|
9
|
+
const terminal_1 = require("./terminal");
|
|
10
|
+
const launch_1 = require("./launch");
|
|
11
|
+
const transfer_1 = require("./transfer");
|
|
12
|
+
const creation_gen_1 = require("./creation.gen");
|
|
13
|
+
const sandbox_handle_gen_1 = require("./sandbox-handle.gen");
|
|
14
|
+
const data_origin_1 = require("./data-origin");
|
|
15
|
+
const workflow_policy_gen_1 = require("./workflow-policy.gen");
|
|
16
|
+
function mutationOptions({ signal, idempotencyKey }) {
|
|
17
|
+
return {
|
|
18
|
+
signal,
|
|
19
|
+
headers: idempotencyKey === undefined ? undefined : { 'Idempotency-Key': idempotencyKey },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function decodeBase64(value) {
|
|
23
|
+
const decoded = atob(value);
|
|
24
|
+
return Uint8Array.from(decoded, character => character.charCodeAt(0));
|
|
25
|
+
}
|
|
26
|
+
/** Provider-neutral sandbox operations. */
|
|
27
|
+
class SandboxResources {
|
|
28
|
+
api;
|
|
29
|
+
constructor(api) {
|
|
30
|
+
this.api = api;
|
|
31
|
+
}
|
|
32
|
+
async agents(options = {}) {
|
|
33
|
+
return this.api.agents.list({ signal: options.signal });
|
|
34
|
+
}
|
|
35
|
+
async create(config, options = {}) {
|
|
36
|
+
const sandbox = await this.api.sandboxes.create({ body: (0, creation_gen_1.creationBody)(config), ...mutationOptions(options) });
|
|
37
|
+
return new SandboxHandle(this.api, sandbox);
|
|
38
|
+
}
|
|
39
|
+
/** Explain which routes creation would use for the same config, without creating anything. */
|
|
40
|
+
async match(config, options = {}) {
|
|
41
|
+
return this.api.sandboxes.match({ body: (0, creation_gen_1.matchBody)(config), signal: options.signal });
|
|
42
|
+
}
|
|
43
|
+
/** Read a sandbox's live state from Cloud and return its handle. */
|
|
44
|
+
async get(id, options = {}) {
|
|
45
|
+
const sandbox = await this.api.sandboxes.get({ path: { sandbox_id: id }, signal: options.signal });
|
|
46
|
+
return new SandboxHandle(this.api, sandbox);
|
|
47
|
+
}
|
|
48
|
+
/** One page of the caller's sandboxes; the query filters and pages as the list operation defines. */
|
|
49
|
+
async list(query, options = {}) {
|
|
50
|
+
return this.api.sandboxes.list({ query, signal: options.signal });
|
|
51
|
+
}
|
|
52
|
+
/** Open a PTY shell by sandbox ID, or attach with terminalId; the shell keeps running afterwards. */
|
|
53
|
+
openTerminal(id, options = {}) {
|
|
54
|
+
return (0, terminal_1.openTerminal)(this.api, id, options);
|
|
55
|
+
}
|
|
56
|
+
async launch(agentOrOptions = {}, maybeOptions = {}) {
|
|
57
|
+
const [agent, options] = typeof agentOrOptions === 'string'
|
|
58
|
+
? [agentOrOptions, maybeOptions] : [undefined, agentOrOptions];
|
|
59
|
+
const { launch, terminalCommand } = await (0, launch_1.launchAgent)(this.api, agent, options);
|
|
60
|
+
let sandbox;
|
|
61
|
+
try {
|
|
62
|
+
sandbox = await this.api.sandboxes.get({ path: { sandbox_id: launch.sandbox_id }, signal: options.signal });
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// The launch succeeded: say which sandbox it made so the caller can read or destroy it.
|
|
66
|
+
if (error instanceof Error)
|
|
67
|
+
error.message += `\nSandbox ID: ${launch.sandbox_id}`;
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
return new SandboxHandle(this.api, sandbox, { launch, terminalCommand });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.SandboxResources = SandboxResources;
|
|
74
|
+
/**
|
|
75
|
+
* A bound sandbox. Its properties are the Sandbox fields (`state`, `lifetime`, `route`, ...) as
|
|
76
|
+
* of the last response: `get` returns a handle, `refresh` reads again, and `destroy`, `pause`,
|
|
77
|
+
* `resume` and `extend` update it. Every handle has every method: a sandbox created without the
|
|
78
|
+
* requirement a method needs answers with an `APIError` whose code is `not_named`.
|
|
79
|
+
*/
|
|
80
|
+
class SandboxHandle {
|
|
81
|
+
#sandbox;
|
|
82
|
+
#terminalObservers = new Set();
|
|
83
|
+
#terminalCommand;
|
|
84
|
+
/** The launch result when `sandboxes.launch` returned this handle (with `interactive` resolved), otherwise undefined. */
|
|
85
|
+
launch;
|
|
86
|
+
files;
|
|
87
|
+
processes;
|
|
88
|
+
previews;
|
|
89
|
+
api;
|
|
90
|
+
static {
|
|
91
|
+
(0, sandbox_handle_gen_1.defineSandboxFields)(SandboxHandle, handle => handle.#sandbox);
|
|
92
|
+
}
|
|
93
|
+
constructor(api, sandbox, launched) {
|
|
94
|
+
this.api = api;
|
|
95
|
+
this.#sandbox = sandbox;
|
|
96
|
+
this.launch = launched?.launch;
|
|
97
|
+
this.#terminalCommand = launched?.terminalCommand;
|
|
98
|
+
const limits = sandbox.limits;
|
|
99
|
+
this.files = new SandboxFiles(api, sandbox.id, limits?.inline_transfer_max_bytes);
|
|
100
|
+
this.processes = new SandboxProcesses(api, sandbox.id);
|
|
101
|
+
this.previews = new SandboxPreviews(api, sandbox.id);
|
|
102
|
+
}
|
|
103
|
+
#registerTerminalObserver(close) {
|
|
104
|
+
this.#terminalObservers.add(close);
|
|
105
|
+
return () => this.#terminalObservers.delete(close);
|
|
106
|
+
}
|
|
107
|
+
async [Symbol.asyncDispose]() {
|
|
108
|
+
await this.destroy();
|
|
109
|
+
}
|
|
110
|
+
/** Read the sandbox again from Cloud and update this handle's properties. */
|
|
111
|
+
async refresh(options = {}) {
|
|
112
|
+
this.#sandbox = await this.api.sandboxes.get({ path: { sandbox_id: this.#sandbox.id }, signal: options.signal });
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Open a PTY shell in this sandbox, or attach with terminalId. After `sandboxes.launch`, a new shell starts
|
|
117
|
+
* the launch's command (written first, with a 3600 s timeout unless you give one).
|
|
118
|
+
*/
|
|
119
|
+
async openTerminal(options = {}) {
|
|
120
|
+
const command = options.terminalId === undefined ? this.#terminalCommand : undefined;
|
|
121
|
+
const terminal = await (0, terminal_1.openTerminal)(this.api, this.id, {
|
|
122
|
+
...options, timeoutSeconds: options.timeoutSeconds ?? (command === undefined ? undefined : 3600),
|
|
123
|
+
}, close => this.#registerTerminalObserver(close));
|
|
124
|
+
if (command !== undefined) {
|
|
125
|
+
await terminal.write(new TextEncoder().encode(`${command}\n`), { signal: options.signal });
|
|
126
|
+
}
|
|
127
|
+
return terminal;
|
|
128
|
+
}
|
|
129
|
+
async exec(command, { check, ...config } = {}, options = {}) {
|
|
130
|
+
const body = { ...config, command };
|
|
131
|
+
(0, command_input_gen_1.validateCommand)(body);
|
|
132
|
+
const result = await this.api.commands.run({
|
|
133
|
+
path: { sandbox_id: this.id }, body, ...mutationOptions(options),
|
|
134
|
+
});
|
|
135
|
+
if (config.output !== 'bytes')
|
|
136
|
+
return (0, command_check_gen_1.checkedCommand)(result, check);
|
|
137
|
+
if (!('stdout_base64' in result) || !('stderr_base64' in result)) {
|
|
138
|
+
throw new TypeError('Unexpected BoxRouter response: expected byte command output');
|
|
139
|
+
}
|
|
140
|
+
const { stdout_base64, stderr_base64, ...metadata } = result;
|
|
141
|
+
return (0, command_check_gen_1.checkedCommand)({ ...metadata, stdout: decodeBase64(stdout_base64), stderr: decodeBase64(stderr_base64) }, check);
|
|
142
|
+
}
|
|
143
|
+
async saveVolume(...[options = {}]) {
|
|
144
|
+
const volumeId = this.volume?.id;
|
|
145
|
+
if (!volumeId)
|
|
146
|
+
throw new TypeError('Sandbox does not identify an attached BoxRouter Volume');
|
|
147
|
+
const { signal, idempotencyKey, ...fields } = options;
|
|
148
|
+
return this.api.volumes.save({ path: { volume_id: volumeId }, body: (0, creation_gen_1.volumeSaveBody)({ ...fields, sandboxId: this.id }),
|
|
149
|
+
...mutationOptions({ signal, idempotencyKey }) });
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Request destruction and update this handle from the sandbox Cloud returns: `destroyed`, or
|
|
153
|
+
* `destroying` with an `operation_id` while Cloud finishes the destroy without the caller.
|
|
154
|
+
*/
|
|
155
|
+
async destroy(options = {}) {
|
|
156
|
+
const { discardUnsaved, ...mutation } = options;
|
|
157
|
+
const failures = [];
|
|
158
|
+
try {
|
|
159
|
+
(0, terminal_1.closeObservers)(this.#terminalObservers);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
failures.push(error);
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
this.#sandbox = await this.api.sandboxes.destroy({ path: { sandbox_id: this.id },
|
|
166
|
+
query: { discard_unsaved: discardUnsaved }, ...mutationOptions(mutation) });
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
failures.push(error);
|
|
170
|
+
}
|
|
171
|
+
if (failures.length)
|
|
172
|
+
throw (0, terminal_1.combineCleanupErrors)(failures, 'Sandbox cleanup failed');
|
|
173
|
+
return this.#sandbox;
|
|
174
|
+
}
|
|
175
|
+
/** Pause the sandbox; the handle's `state` and `lifetime` follow the response. */
|
|
176
|
+
async pause(options = {}) {
|
|
177
|
+
const paused = await this.api.sandboxes.pause({ path: { sandbox_id: this.id }, ...mutationOptions(options) });
|
|
178
|
+
this.#sandbox = { ...this.#sandbox, state: paused.state, lifetime: paused.lifetime };
|
|
179
|
+
return paused;
|
|
180
|
+
}
|
|
181
|
+
/** Resume the sandbox; undefined means it was already running (204), and nothing changes. */
|
|
182
|
+
async resume(options = {}) {
|
|
183
|
+
const resumed = await this.api.sandboxes.resume({ path: { sandbox_id: this.id }, ...mutationOptions(options) });
|
|
184
|
+
if (resumed === undefined)
|
|
185
|
+
return undefined;
|
|
186
|
+
this.#sandbox = { ...this.#sandbox, state: resumed.state, lifetime: resumed.lifetime };
|
|
187
|
+
return resumed;
|
|
188
|
+
}
|
|
189
|
+
/** Set the sandbox's new total running-time budget in seconds (not an increment). */
|
|
190
|
+
async extend(body, options = {}) {
|
|
191
|
+
const lifetime = await this.api.sandboxes.extend({ path: { sandbox_id: this.id }, body, ...mutationOptions(options) });
|
|
192
|
+
this.#sandbox = { ...this.#sandbox, lifetime };
|
|
193
|
+
return lifetime;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.SandboxHandle = SandboxHandle;
|
|
197
|
+
/** Previews of one sandbox. */
|
|
198
|
+
class SandboxPreviews {
|
|
199
|
+
api;
|
|
200
|
+
id;
|
|
201
|
+
constructor(api, id) {
|
|
202
|
+
this.api = api;
|
|
203
|
+
this.id = id;
|
|
204
|
+
}
|
|
205
|
+
/** Open a preview of `port`, which the sandbox's previews requirement must name. */
|
|
206
|
+
async open(port, config = {}, options = {}) {
|
|
207
|
+
return this.api.previews.open({ path: { sandbox_id: this.id }, body: { ...config, port }, ...mutationOptions(options) });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.SandboxPreviews = SandboxPreviews;
|
|
211
|
+
const WAIT_POLL_MS = workflow_policy_gen_1.PROCESS_WAIT_POLL_INTERVAL_SECONDS * 1000;
|
|
212
|
+
/** What a command result carries that a process does not: the same value for every process. */
|
|
213
|
+
const FIXED_RESULT = JSON.parse(workflow_policy_gen_1.PROCESS_WAIT_FIXED_RESULT_JSON);
|
|
214
|
+
function joined(pages) {
|
|
215
|
+
const bytes = new Uint8Array(pages.reduce((total, page) => total + page.length, 0));
|
|
216
|
+
let at = 0;
|
|
217
|
+
for (const page of pages) {
|
|
218
|
+
bytes.set(page, at);
|
|
219
|
+
at += page.length;
|
|
220
|
+
}
|
|
221
|
+
return bytes;
|
|
222
|
+
}
|
|
223
|
+
/** Node's longest timer delay. */
|
|
224
|
+
const MAX_TIMER_MS = 2 ** 31 - 1;
|
|
225
|
+
/** Background commands bound to one sandbox. */
|
|
226
|
+
class SandboxProcesses {
|
|
227
|
+
api;
|
|
228
|
+
id;
|
|
229
|
+
constructor(api, id) {
|
|
230
|
+
this.api = api;
|
|
231
|
+
this.id = id;
|
|
232
|
+
}
|
|
233
|
+
async start(command, config = {}, options = {}) {
|
|
234
|
+
const body = { ...config, command };
|
|
235
|
+
(0, command_input_gen_1.validateProcess)(body);
|
|
236
|
+
const { id } = await this.api.processes.start({
|
|
237
|
+
path: { sandbox_id: this.id }, body, ...mutationOptions(options),
|
|
238
|
+
});
|
|
239
|
+
return new ProcessHandle(this.api, this.id, id);
|
|
240
|
+
}
|
|
241
|
+
/** A handle for a started process. */
|
|
242
|
+
fromId(processId) {
|
|
243
|
+
return new ProcessHandle(this.api, this.id, processId);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
exports.SandboxProcesses = SandboxProcesses;
|
|
247
|
+
function offset(name, value) {
|
|
248
|
+
const bytes = Number(value);
|
|
249
|
+
if (!Number.isSafeInteger(bytes) || bytes < 0)
|
|
250
|
+
throw new TypeError(`${name} must be a non-negative integer byte offset`);
|
|
251
|
+
return bytes;
|
|
252
|
+
}
|
|
253
|
+
/** A started command, addressed by its durable ID. Nothing here cancels it implicitly. */
|
|
254
|
+
class ProcessHandle {
|
|
255
|
+
api;
|
|
256
|
+
#path;
|
|
257
|
+
constructor(api, sandboxId, processId) {
|
|
258
|
+
this.api = api;
|
|
259
|
+
this.#path = { sandbox_id: sandboxId, process_id: processId };
|
|
260
|
+
}
|
|
261
|
+
get id() { return this.#path.process_id; }
|
|
262
|
+
/**
|
|
263
|
+
* Output from the given byte offsets; continue from next_stdout and next_stderr.
|
|
264
|
+
* exit_code is set once the process ended and both streams were read to their ends.
|
|
265
|
+
*/
|
|
266
|
+
async read(options = {}) {
|
|
267
|
+
return this.api.processes.read({
|
|
268
|
+
path: this.#path,
|
|
269
|
+
query: { stdout: offset('stdout', options.stdout ?? 0), stderr: offset('stderr', options.stderr ?? 0) },
|
|
270
|
+
signal: options.signal,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async wait(options = {}) {
|
|
274
|
+
if (options.output !== undefined && options.output !== 'text' && options.output !== 'bytes') {
|
|
275
|
+
throw new TypeError("output must be 'text' or 'bytes'");
|
|
276
|
+
}
|
|
277
|
+
const deadline = options.timeoutSeconds === undefined ? Infinity : Date.now() + options.timeoutSeconds * 1000;
|
|
278
|
+
const readBefore = async (stdout, stderr) => {
|
|
279
|
+
const expired = () => new DOMException(`Process ${this.id} did not exit within ${options.timeoutSeconds} seconds`, 'TimeoutError');
|
|
280
|
+
const left = deadline - Date.now();
|
|
281
|
+
if (left <= 0)
|
|
282
|
+
throw expired();
|
|
283
|
+
// Node fires timers longer than its maximum delay at once, so those reads rely on the checks.
|
|
284
|
+
const timer = left <= MAX_TIMER_MS ? AbortSignal.timeout(Math.ceil(left)) : undefined;
|
|
285
|
+
const signals = [options.signal, timer].filter(signal => signal !== undefined);
|
|
286
|
+
try {
|
|
287
|
+
const output = await this.read({ stdout, stderr, signal: signals.length > 1 ? AbortSignal.any(signals) : signals[0] });
|
|
288
|
+
if (Date.now() >= deadline)
|
|
289
|
+
throw expired();
|
|
290
|
+
return output;
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
if (timer?.aborted && !options.signal?.aborted)
|
|
294
|
+
throw expired();
|
|
295
|
+
throw error;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
let output = await readBefore(options.stdout ?? 0, options.stderr ?? 0);
|
|
299
|
+
const stdout = [decodeBase64(output.stdout_base64)];
|
|
300
|
+
const stderr = [decodeBase64(output.stderr_base64)];
|
|
301
|
+
while (output.exit_code === null) {
|
|
302
|
+
await new Promise(resolve => setTimeout(resolve, Math.max(0, Math.min(WAIT_POLL_MS, deadline - Date.now()))));
|
|
303
|
+
output = await readBefore(output.next_stdout, output.next_stderr);
|
|
304
|
+
stdout.push(decodeBase64(output.stdout_base64));
|
|
305
|
+
stderr.push(decodeBase64(output.stderr_base64));
|
|
306
|
+
}
|
|
307
|
+
const exit = { exit_code: output.exit_code, ...FIXED_RESULT };
|
|
308
|
+
if (options.output === 'bytes')
|
|
309
|
+
return { stdout: joined(stdout), stderr: joined(stderr), ...exit };
|
|
310
|
+
// Decoded once, after the pages are joined, so a character split between pages survives.
|
|
311
|
+
const text = new TextDecoder();
|
|
312
|
+
return { stdout: text.decode(joined(stdout)), stderr: text.decode(joined(stderr)), ...exit };
|
|
313
|
+
}
|
|
314
|
+
/** Appends text to stdin; the process must have started with stdin: true. */
|
|
315
|
+
async writeStdin(data, options = {}) {
|
|
316
|
+
await this.api.processes.writeStdin({ path: this.#path, body: { data }, ...mutationOptions(options) });
|
|
317
|
+
}
|
|
318
|
+
async closeStdin(options = {}) {
|
|
319
|
+
await this.api.processes.closeStdin({ path: this.#path, signal: options.signal });
|
|
320
|
+
}
|
|
321
|
+
/** Requests termination; wait() or read() confirms the exit. */
|
|
322
|
+
async cancel(options = {}) {
|
|
323
|
+
await this.api.processes.cancel({ path: this.#path, ...mutationOptions(options) });
|
|
324
|
+
}
|
|
325
|
+
/** Deletes the retained output of a finished process. */
|
|
326
|
+
async remove(options = {}) {
|
|
327
|
+
await this.api.processes.remove({ path: this.#path, ...mutationOptions(options) });
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
exports.ProcessHandle = ProcessHandle;
|
|
331
|
+
// Mirrors the `file_transfer_bytes` default in the OpenAPI capabilities limits: the largest file
|
|
332
|
+
// `readFile` and `writeFile` carry in one request.
|
|
333
|
+
const SMALL_FILE_LIMIT = 1_048_576;
|
|
334
|
+
function fileOutputLimit(error) {
|
|
335
|
+
// `output_limit` is the earlier name some routes still return for the same refusal.
|
|
336
|
+
return error instanceof api_error_1.APIError && error.status === 413 && (error.code === 'resource_limit' || error.code === 'output_limit');
|
|
337
|
+
}
|
|
338
|
+
// The three upload calls require an Idempotency-Key. Each gets its own key derived from one base key:
|
|
339
|
+
// the caller's, or a fresh UUID when the caller gave none.
|
|
340
|
+
function operationOptions(base, signal, operation) {
|
|
341
|
+
const suffix = `:${operation}`;
|
|
342
|
+
return { signal, headers: { 'Idempotency-Key': `${base.slice(0, 128 - suffix.length)}${suffix}` } };
|
|
343
|
+
}
|
|
344
|
+
class SandboxFiles {
|
|
345
|
+
api;
|
|
346
|
+
id;
|
|
347
|
+
inlineTransferMaxBytes;
|
|
348
|
+
constructor(api, id, inlineTransferMaxBytes) {
|
|
349
|
+
this.api = api;
|
|
350
|
+
this.id = id;
|
|
351
|
+
this.inlineTransferMaxBytes = inlineTransferMaxBytes;
|
|
352
|
+
}
|
|
353
|
+
/** The route's advertised inline size, capped at the inline read's own bound. */
|
|
354
|
+
inlineBelow() {
|
|
355
|
+
return this.inlineTransferMaxBytes === undefined
|
|
356
|
+
? undefined
|
|
357
|
+
: Math.min(this.inlineTransferMaxBytes, 5 * 1024 * 1024);
|
|
358
|
+
}
|
|
359
|
+
async list(path, options = {}) {
|
|
360
|
+
return this.api.files.list({
|
|
361
|
+
path: { sandbox_id: this.id }, query: { path }, signal: options.signal,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async exists(path, options = {}) {
|
|
365
|
+
return this.api.files.exists({
|
|
366
|
+
path: { sandbox_id: this.id }, query: { path }, signal: options.signal,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
async mkdir(path, options = {}) {
|
|
370
|
+
await this.api.files.mkdir({
|
|
371
|
+
path: { sandbox_id: this.id }, body: { path, parents: options.parents },
|
|
372
|
+
...mutationOptions(options),
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
async remove(path, options = {}) {
|
|
376
|
+
await this.api.files.remove({
|
|
377
|
+
path: { sandbox_id: this.id }, body: { path, recursive: options.recursive },
|
|
378
|
+
...mutationOptions(options),
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
async read(path, options = {}) {
|
|
382
|
+
const inline = this.inlineBelow();
|
|
383
|
+
if (inline !== undefined) {
|
|
384
|
+
// The route advertises one inline request: the body or a transfer link.
|
|
385
|
+
const answer = await this.api.files.createDownload({
|
|
386
|
+
path: { sandbox_id: this.id },
|
|
387
|
+
body: { path, inline_below: inline },
|
|
388
|
+
signal: options.signal,
|
|
389
|
+
});
|
|
390
|
+
if (answer.content !== undefined)
|
|
391
|
+
return decodeBase64(answer.content);
|
|
392
|
+
const stream = await this.download(path, undefined, options);
|
|
393
|
+
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
394
|
+
}
|
|
395
|
+
try {
|
|
396
|
+
const bytes = await this.api.files.read({
|
|
397
|
+
path: { sandbox_id: this.id }, query: { path }, parseAs: 'blob', signal: options.signal,
|
|
398
|
+
...(0, data_origin_1.dataOriginOptions)(this.api, true),
|
|
399
|
+
});
|
|
400
|
+
return new Uint8Array(await bytes.arrayBuffer());
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
if (!fileOutputLimit(error))
|
|
404
|
+
throw error;
|
|
405
|
+
}
|
|
406
|
+
// Over the small-file limit: the same bytes through the download flow, into memory.
|
|
407
|
+
const stream = await this.download(path, undefined, options);
|
|
408
|
+
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
409
|
+
}
|
|
410
|
+
async write(path, content, options = {}) {
|
|
411
|
+
const bytes = typeof content === 'string' ? new TextEncoder().encode(content) : content;
|
|
412
|
+
if ((bytes instanceof Blob ? bytes.size : bytes.byteLength) > SMALL_FILE_LIMIT) {
|
|
413
|
+
await this.upload(bytes, path, options);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
await this.api.files.write({
|
|
417
|
+
path: { sandbox_id: this.id }, query: { path },
|
|
418
|
+
body: bytes instanceof Blob ? bytes : new Blob([bytes]),
|
|
419
|
+
...(0, data_origin_1.dataOriginOptions)(this.api, (bytes instanceof Blob ? bytes.size : bytes.byteLength) >= data_origin_1.LARGE_WRITE_BYTES),
|
|
420
|
+
...mutationOptions(options),
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Upload a local file path, Blob, bytes or stream to `remotePath`. A stream needs `size`. The request
|
|
425
|
+
* carries the exact length, so a stream is first spooled to a temporary file (never into memory).
|
|
426
|
+
* `progress` is called as each part finishes. An upload that fails before completion is sent is aborted;
|
|
427
|
+
* one that fails after is left as it is, its outcome unknown. Bytes already written may remain.
|
|
428
|
+
*/
|
|
429
|
+
async upload(source, remotePath, options = {}) {
|
|
430
|
+
const opened = await (0, transfer_1.openSource)({ source, size: options.size }, options.signal);
|
|
431
|
+
const baseKey = options.idempotencyKey ?? globalThis.crypto.randomUUID();
|
|
432
|
+
try {
|
|
433
|
+
const session = await this.api.files.createUpload({
|
|
434
|
+
path: { sandbox_id: this.id }, body: { path: remotePath, size: opened.size },
|
|
435
|
+
...operationOptions(baseKey, options.signal, 'create'),
|
|
436
|
+
});
|
|
437
|
+
let completing = false;
|
|
438
|
+
try {
|
|
439
|
+
const parts = await (0, transfer_1.sendParts)(opened, session.parts, {
|
|
440
|
+
concurrency: options.concurrency ?? 4, replayParts: false, label: 'Sandbox',
|
|
441
|
+
progress: options.progress, signal: options.signal,
|
|
442
|
+
});
|
|
443
|
+
completing = true;
|
|
444
|
+
// The completion key is fixed up front, so every retry of an unknown outcome reuses it.
|
|
445
|
+
const complete = operationOptions(baseKey, options.signal, 'complete');
|
|
446
|
+
await (0, transfer_1.retryCompletion)(() => this.api.files.completeUpload({
|
|
447
|
+
path: { sandbox_id: this.id, upload_id: session.id }, body: { parts }, ...complete,
|
|
448
|
+
}), options.signal);
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
// Once completion was sent the upload may be finished: abort is for uploads that never were.
|
|
452
|
+
if (!completing) {
|
|
453
|
+
try {
|
|
454
|
+
await this.api.files.abortUpload({
|
|
455
|
+
path: { sandbox_id: this.id, upload_id: session.id },
|
|
456
|
+
...operationOptions(baseKey, undefined, 'abort'),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
catch {
|
|
460
|
+
// Preserve the failure that caused cleanup.
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
throw error;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
await opened.close();
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async download(remotePath, localPath, options = {}) {
|
|
471
|
+
const inline = this.inlineBelow();
|
|
472
|
+
const answer = await this.api.files.createDownload({
|
|
473
|
+
path: { sandbox_id: this.id },
|
|
474
|
+
body: inline === undefined ? { path: remotePath } : { path: remotePath, inline_below: inline },
|
|
475
|
+
signal: options.signal,
|
|
476
|
+
});
|
|
477
|
+
if (answer.content !== undefined) {
|
|
478
|
+
// The body came inline; keep the same atomic replace as a streamed download.
|
|
479
|
+
const bytes = decodeBase64(answer.content);
|
|
480
|
+
if (localPath === undefined) {
|
|
481
|
+
return new ReadableStream({
|
|
482
|
+
start: (controller) => {
|
|
483
|
+
controller.enqueue(bytes);
|
|
484
|
+
controller.close();
|
|
485
|
+
},
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
const [fs, paths, crypto] = await Promise.all([
|
|
489
|
+
import('node:fs/promises'), import('node:path'), import('node:crypto'),
|
|
490
|
+
]);
|
|
491
|
+
const temporary = `${localPath}.part-${crypto.randomBytes(6).toString('hex')}`;
|
|
492
|
+
await fs.mkdir(paths.dirname(localPath), { recursive: true });
|
|
493
|
+
const existing = await fs.stat(localPath).catch(() => undefined);
|
|
494
|
+
await fs.writeFile(temporary, bytes, { mode: existing ? existing.mode & 0o7777 : 0o666 });
|
|
495
|
+
await fs.rename(temporary, localPath);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (answer.url === undefined)
|
|
499
|
+
throw new transfer_1.TransferError('Sandbox download answer carried no link');
|
|
500
|
+
const link = { ...answer, url: answer.url };
|
|
501
|
+
const transfer = { size: link.size == null ? undefined : Number(link.size), label: 'Sandbox', progress: options.progress, signal: options.signal };
|
|
502
|
+
if (localPath === undefined)
|
|
503
|
+
return (0, transfer_1.downloadStream)(link, transfer);
|
|
504
|
+
await (0, transfer_1.downloadToFile)(link, localPath, transfer);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
exports.SandboxFiles = SandboxFiles;
|