langsmith 0.5.18 → 0.5.20
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/dist/client.cjs +24 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.js +24 -0
- package/dist/experimental/anthropic/context.cjs +5 -0
- package/dist/experimental/anthropic/context.js +5 -0
- package/dist/experimental/anthropic/index.cjs +1 -0
- package/dist/experimental/anthropic/index.js +1 -0
- package/dist/experimental/sandbox/client.cjs +234 -11
- package/dist/experimental/sandbox/client.d.ts +76 -4
- package/dist/experimental/sandbox/client.js +234 -11
- package/dist/experimental/sandbox/index.cjs +0 -3
- package/dist/experimental/sandbox/index.d.ts +1 -1
- package/dist/experimental/sandbox/index.js +0 -3
- package/dist/experimental/sandbox/sandbox.cjs +65 -1
- package/dist/experimental/sandbox/sandbox.d.ts +35 -5
- package/dist/experimental/sandbox/sandbox.js +65 -1
- package/dist/experimental/sandbox/types.d.ts +92 -1
- package/dist/experimental/vercel/index.cjs +11 -0
- package/dist/experimental/vercel/index.js +12 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
|
@@ -7,6 +7,27 @@ import { AsyncCaller } from "../../utils/async_caller.js";
|
|
|
7
7
|
import { Sandbox } from "./sandbox.js";
|
|
8
8
|
import { LangSmithResourceCreationError, LangSmithResourceNameConflictError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithSandboxAPIError, } from "./errors.js";
|
|
9
9
|
import { handleClientHttpError, handleConflictError, handlePoolError, handleResourceInUseError, handleSandboxCreationError, handleVolumeCreationError, validateTtl, } from "./helpers.js";
|
|
10
|
+
/**
|
|
11
|
+
* Sleep that can be interrupted by an AbortSignal.
|
|
12
|
+
* Resolves after `ms` milliseconds or rejects immediately if the signal fires.
|
|
13
|
+
*/
|
|
14
|
+
function sleepWithSignal(ms, signal) {
|
|
15
|
+
if (!signal) {
|
|
16
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
+
}
|
|
18
|
+
signal.throwIfAborted();
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const timer = setTimeout(() => {
|
|
21
|
+
signal.removeEventListener("abort", onAbort);
|
|
22
|
+
resolve();
|
|
23
|
+
}, ms);
|
|
24
|
+
function onAbort() {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
reject(signal.reason);
|
|
27
|
+
}
|
|
28
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
29
|
+
});
|
|
30
|
+
}
|
|
10
31
|
/**
|
|
11
32
|
* Get the default sandbox API endpoint from environment.
|
|
12
33
|
*
|
|
@@ -50,6 +71,8 @@ function getDefaultApiKey() {
|
|
|
50
71
|
* await sandbox.delete();
|
|
51
72
|
* }
|
|
52
73
|
* ```
|
|
74
|
+
*
|
|
75
|
+
* @experimental This feature is experimental, and breaking changes are expected.
|
|
53
76
|
*/
|
|
54
77
|
export class SandboxClient {
|
|
55
78
|
constructor(config = {}) {
|
|
@@ -110,6 +133,25 @@ export class SandboxClient {
|
|
|
110
133
|
getApiKey() {
|
|
111
134
|
return this._apiKey;
|
|
112
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* JSON POST helper. Sends JSON body, checks response status,
|
|
138
|
+
* and returns the Response for further processing.
|
|
139
|
+
* Throws on non-ok responses via handleClientHttpError.
|
|
140
|
+
* Callers can add specific status checks (e.g. 404) before calling this.
|
|
141
|
+
* @internal
|
|
142
|
+
*/
|
|
143
|
+
async _postJson(url, body, options) {
|
|
144
|
+
const response = await this._fetch(url, {
|
|
145
|
+
method: "POST",
|
|
146
|
+
headers: { "Content-Type": "application/json" },
|
|
147
|
+
body: JSON.stringify(body),
|
|
148
|
+
signal: options?.signal,
|
|
149
|
+
});
|
|
150
|
+
if (!response.ok) {
|
|
151
|
+
await handleClientHttpError(response);
|
|
152
|
+
}
|
|
153
|
+
return response;
|
|
154
|
+
}
|
|
113
155
|
// =========================================================================
|
|
114
156
|
// Volume Operations
|
|
115
157
|
// =========================================================================
|
|
@@ -535,14 +577,25 @@ export class SandboxClient {
|
|
|
535
577
|
* ```
|
|
536
578
|
*/
|
|
537
579
|
async createSandbox(templateName, options = {}) {
|
|
538
|
-
const { name, timeout = 30, waitForReady = true, ttlSeconds, idleTtlSeconds, } = options;
|
|
580
|
+
const { snapshotId, name, timeout = 30, waitForReady = true, ttlSeconds, idleTtlSeconds, vCpus, memBytes, fsCapacityBytes, } = options;
|
|
581
|
+
if (!templateName && !snapshotId) {
|
|
582
|
+
throw new Error("Either templateName or snapshotId is required");
|
|
583
|
+
}
|
|
584
|
+
if (templateName && snapshotId) {
|
|
585
|
+
throw new Error("Cannot specify both templateName and snapshotId");
|
|
586
|
+
}
|
|
539
587
|
validateTtl(ttlSeconds, "ttlSeconds");
|
|
540
588
|
validateTtl(idleTtlSeconds, "idleTtlSeconds");
|
|
541
589
|
const url = `${this._baseUrl}/boxes`;
|
|
542
590
|
const payload = {
|
|
543
|
-
template_name: templateName,
|
|
544
591
|
wait_for_ready: waitForReady,
|
|
545
592
|
};
|
|
593
|
+
if (templateName) {
|
|
594
|
+
payload.template_name = templateName;
|
|
595
|
+
}
|
|
596
|
+
if (snapshotId) {
|
|
597
|
+
payload.snapshot_id = snapshotId;
|
|
598
|
+
}
|
|
546
599
|
if (waitForReady) {
|
|
547
600
|
payload.timeout = timeout;
|
|
548
601
|
}
|
|
@@ -555,6 +608,15 @@ export class SandboxClient {
|
|
|
555
608
|
if (idleTtlSeconds !== undefined) {
|
|
556
609
|
payload.idle_ttl_seconds = idleTtlSeconds;
|
|
557
610
|
}
|
|
611
|
+
if (vCpus !== undefined) {
|
|
612
|
+
payload.vcpus = vCpus;
|
|
613
|
+
}
|
|
614
|
+
if (memBytes !== undefined) {
|
|
615
|
+
payload.mem_bytes = memBytes;
|
|
616
|
+
}
|
|
617
|
+
if (fsCapacityBytes !== undefined) {
|
|
618
|
+
payload.fs_capacity_bytes = fsCapacityBytes;
|
|
619
|
+
}
|
|
558
620
|
const httpTimeout = waitForReady ? (timeout + 30) * 1000 : 30 * 1000;
|
|
559
621
|
const response = await this._fetch(url, {
|
|
560
622
|
method: "POST",
|
|
@@ -577,9 +639,9 @@ export class SandboxClient {
|
|
|
577
639
|
* @returns Sandbox.
|
|
578
640
|
* @throws LangSmithResourceNotFoundError if sandbox not found.
|
|
579
641
|
*/
|
|
580
|
-
async getSandbox(name) {
|
|
642
|
+
async getSandbox(name, options) {
|
|
581
643
|
const url = `${this._baseUrl}/boxes/${encodeURIComponent(name)}`;
|
|
582
|
-
const response = await this._fetch(url);
|
|
644
|
+
const response = await this._fetch(url, { signal: options?.signal });
|
|
583
645
|
if (!response.ok) {
|
|
584
646
|
if (response.status === 404) {
|
|
585
647
|
throw new LangSmithResourceNotFoundError(`Sandbox '${name}' not found`, "sandbox");
|
|
@@ -674,9 +736,9 @@ export class SandboxClient {
|
|
|
674
736
|
* @returns ResourceStatus with status and optional status_message.
|
|
675
737
|
* @throws LangSmithResourceNotFoundError if sandbox not found.
|
|
676
738
|
*/
|
|
677
|
-
async getSandboxStatus(name) {
|
|
739
|
+
async getSandboxStatus(name, options) {
|
|
678
740
|
const url = `${this._baseUrl}/boxes/${encodeURIComponent(name)}/status`;
|
|
679
|
-
const response = await this._fetch(url);
|
|
741
|
+
const response = await this._fetch(url, { signal: options?.signal });
|
|
680
742
|
if (!response.ok) {
|
|
681
743
|
if (response.status === 404) {
|
|
682
744
|
throw new LangSmithResourceNotFoundError(`Sandbox '${name}' not found`, "sandbox");
|
|
@@ -706,21 +768,182 @@ export class SandboxClient {
|
|
|
706
768
|
* ```
|
|
707
769
|
*/
|
|
708
770
|
async waitForSandbox(name, options = {}) {
|
|
709
|
-
const { timeout = 120, pollInterval = 1.0 } = options;
|
|
771
|
+
const { timeout = 120, pollInterval = 1.0, signal } = options;
|
|
710
772
|
const deadline = Date.now() + timeout * 1000;
|
|
711
773
|
let lastStatus = "provisioning";
|
|
712
774
|
while (Date.now() < deadline) {
|
|
713
|
-
|
|
775
|
+
signal?.throwIfAborted();
|
|
776
|
+
const statusResult = await this.getSandboxStatus(name, { signal });
|
|
714
777
|
lastStatus = statusResult.status;
|
|
715
778
|
if (statusResult.status === "ready") {
|
|
716
|
-
return this.getSandbox(name);
|
|
779
|
+
return this.getSandbox(name, { signal });
|
|
717
780
|
}
|
|
718
781
|
if (statusResult.status === "failed") {
|
|
719
782
|
throw new LangSmithResourceCreationError(statusResult.status_message ?? `Sandbox '${name}' creation failed`, "sandbox");
|
|
720
783
|
}
|
|
721
|
-
// Wait before polling again
|
|
722
|
-
|
|
784
|
+
// Wait before polling again, capped to remaining time + jitter
|
|
785
|
+
const remaining = deadline - Date.now();
|
|
786
|
+
const jitter = pollInterval * 200 * (Math.random() - 0.5); // ±10%
|
|
787
|
+
const delay = Math.min(pollInterval * 1000 + jitter, remaining);
|
|
788
|
+
if (delay > 0) {
|
|
789
|
+
await sleepWithSignal(delay, signal);
|
|
790
|
+
}
|
|
723
791
|
}
|
|
724
792
|
throw new LangSmithResourceTimeoutError(`Sandbox '${name}' did not become ready within ${timeout}s`, "sandbox", lastStatus);
|
|
725
793
|
}
|
|
794
|
+
/**
|
|
795
|
+
* Start a stopped sandbox and wait until ready.
|
|
796
|
+
*
|
|
797
|
+
* @param name - Sandbox name.
|
|
798
|
+
* @param options - Options with timeout.
|
|
799
|
+
* @returns Sandbox in "ready" status.
|
|
800
|
+
*/
|
|
801
|
+
async startSandbox(name, options = {}) {
|
|
802
|
+
const { timeout = 120, signal } = options;
|
|
803
|
+
const url = `${this._baseUrl}/boxes/${encodeURIComponent(name)}/start`;
|
|
804
|
+
await this._postJson(url, {}, { signal });
|
|
805
|
+
return this.waitForSandbox(name, { timeout, signal });
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Stop a running sandbox (preserves sandbox files for later restart).
|
|
809
|
+
*
|
|
810
|
+
* @param name - Sandbox name.
|
|
811
|
+
*/
|
|
812
|
+
async stopSandbox(name) {
|
|
813
|
+
const url = `${this._baseUrl}/boxes/${encodeURIComponent(name)}/stop`;
|
|
814
|
+
await this._postJson(url, {});
|
|
815
|
+
}
|
|
816
|
+
// =========================================================================
|
|
817
|
+
// Snapshot Operations
|
|
818
|
+
// =========================================================================
|
|
819
|
+
/**
|
|
820
|
+
* Build a snapshot from a Docker image.
|
|
821
|
+
*
|
|
822
|
+
* Blocks until the snapshot is ready (polls with 2s interval).
|
|
823
|
+
*
|
|
824
|
+
* @param name - Snapshot name.
|
|
825
|
+
* @param dockerImage - Docker image to build from (e.g., "python:3.12-slim").
|
|
826
|
+
* @param fsCapacityBytes - Filesystem capacity in bytes.
|
|
827
|
+
* @param options - Additional options (registry credentials, timeout).
|
|
828
|
+
* @returns Snapshot in "ready" status.
|
|
829
|
+
*/
|
|
830
|
+
async createSnapshot(name, dockerImage, fsCapacityBytes, options = {}) {
|
|
831
|
+
const { registryId, registryUrl, registryUsername, registryPassword, timeout = 60, signal, } = options;
|
|
832
|
+
const url = `${this._baseUrl}/snapshots`;
|
|
833
|
+
const payload = {
|
|
834
|
+
name,
|
|
835
|
+
docker_image: dockerImage,
|
|
836
|
+
fs_capacity_bytes: fsCapacityBytes,
|
|
837
|
+
};
|
|
838
|
+
if (registryId !== undefined) {
|
|
839
|
+
payload.registry_id = registryId;
|
|
840
|
+
}
|
|
841
|
+
if (registryUrl !== undefined) {
|
|
842
|
+
payload.registry_url = registryUrl;
|
|
843
|
+
}
|
|
844
|
+
if (registryUsername !== undefined) {
|
|
845
|
+
payload.registry_username = registryUsername;
|
|
846
|
+
}
|
|
847
|
+
if (registryPassword !== undefined) {
|
|
848
|
+
payload.registry_password = registryPassword;
|
|
849
|
+
}
|
|
850
|
+
const response = await this._postJson(url, payload, { signal });
|
|
851
|
+
const snapshot = (await response.json());
|
|
852
|
+
return this.waitForSnapshot(snapshot.id, { timeout, signal });
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Capture a snapshot from a running sandbox.
|
|
856
|
+
*
|
|
857
|
+
* Blocks until the snapshot is ready (polls with 2s interval).
|
|
858
|
+
*
|
|
859
|
+
* @param sandboxName - Name of the sandbox to capture from.
|
|
860
|
+
* @param name - Snapshot name.
|
|
861
|
+
* @param options - Capture options (checkpoint, timeout).
|
|
862
|
+
* @returns Snapshot in "ready" status.
|
|
863
|
+
*/
|
|
864
|
+
async captureSnapshot(sandboxName, name, options = {}) {
|
|
865
|
+
const { checkpoint, timeout = 60, signal } = options;
|
|
866
|
+
const url = `${this._baseUrl}/boxes/${encodeURIComponent(sandboxName)}/snapshot`;
|
|
867
|
+
const payload = { name };
|
|
868
|
+
if (checkpoint !== undefined) {
|
|
869
|
+
payload.checkpoint = checkpoint;
|
|
870
|
+
}
|
|
871
|
+
const response = await this._postJson(url, payload, { signal });
|
|
872
|
+
const snapshot = (await response.json());
|
|
873
|
+
return this.waitForSnapshot(snapshot.id, { timeout, signal });
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Get a snapshot by ID.
|
|
877
|
+
*
|
|
878
|
+
* @param snapshotId - Snapshot UUID.
|
|
879
|
+
* @returns Snapshot.
|
|
880
|
+
*/
|
|
881
|
+
async getSnapshot(snapshotId, options) {
|
|
882
|
+
const url = `${this._baseUrl}/snapshots/${encodeURIComponent(snapshotId)}`;
|
|
883
|
+
const response = await this._fetch(url, { signal: options?.signal });
|
|
884
|
+
if (!response.ok) {
|
|
885
|
+
if (response.status === 404) {
|
|
886
|
+
throw new LangSmithResourceNotFoundError(`Snapshot '${snapshotId}' not found`, "snapshot");
|
|
887
|
+
}
|
|
888
|
+
await handleClientHttpError(response);
|
|
889
|
+
}
|
|
890
|
+
return (await response.json());
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* List all snapshots.
|
|
894
|
+
*
|
|
895
|
+
* @returns List of Snapshots.
|
|
896
|
+
*/
|
|
897
|
+
async listSnapshots() {
|
|
898
|
+
const url = `${this._baseUrl}/snapshots`;
|
|
899
|
+
const response = await this._fetch(url);
|
|
900
|
+
if (!response.ok) {
|
|
901
|
+
await handleClientHttpError(response);
|
|
902
|
+
}
|
|
903
|
+
const data = await response.json();
|
|
904
|
+
return (data.snapshots ?? []);
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Delete a snapshot.
|
|
908
|
+
*
|
|
909
|
+
* @param snapshotId - Snapshot UUID.
|
|
910
|
+
*/
|
|
911
|
+
async deleteSnapshot(snapshotId) {
|
|
912
|
+
const url = `${this._baseUrl}/snapshots/${encodeURIComponent(snapshotId)}`;
|
|
913
|
+
const response = await this._fetch(url, { method: "DELETE" });
|
|
914
|
+
if (!response.ok) {
|
|
915
|
+
await handleClientHttpError(response);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Poll until a snapshot reaches "ready" or "failed" status.
|
|
920
|
+
*
|
|
921
|
+
* @param snapshotId - Snapshot UUID.
|
|
922
|
+
* @param options - Polling options (timeout, pollInterval).
|
|
923
|
+
* @returns Snapshot in "ready" status.
|
|
924
|
+
*/
|
|
925
|
+
async waitForSnapshot(snapshotId, options = {}) {
|
|
926
|
+
const { timeout = 300, pollInterval = 2.0, signal } = options;
|
|
927
|
+
const deadline = Date.now() + timeout * 1000;
|
|
928
|
+
let lastStatus = "building";
|
|
929
|
+
while (Date.now() < deadline) {
|
|
930
|
+
signal?.throwIfAborted();
|
|
931
|
+
const snapshot = await this.getSnapshot(snapshotId, { signal });
|
|
932
|
+
lastStatus = snapshot.status;
|
|
933
|
+
if (snapshot.status === "ready") {
|
|
934
|
+
return snapshot;
|
|
935
|
+
}
|
|
936
|
+
if (snapshot.status === "failed") {
|
|
937
|
+
throw new LangSmithResourceCreationError(snapshot.status_message ?? `Snapshot '${snapshotId}' build failed`, "snapshot");
|
|
938
|
+
}
|
|
939
|
+
// Cap sleep to remaining time + jitter
|
|
940
|
+
const remaining = deadline - Date.now();
|
|
941
|
+
const jitter = pollInterval * 200 * (Math.random() - 0.5); // ±10%
|
|
942
|
+
const delay = Math.min(pollInterval * 1000 + jitter, remaining);
|
|
943
|
+
if (delay > 0) {
|
|
944
|
+
await sleepWithSignal(delay, signal);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
throw new LangSmithResourceTimeoutError(`Snapshot '${snapshotId}' did not become ready within ${timeout}s`, "snapshot", lastStatus);
|
|
948
|
+
}
|
|
726
949
|
}
|
|
@@ -25,9 +25,6 @@
|
|
|
25
25
|
*/
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
27
|
exports.LangSmithDataplaneNotConfiguredError = exports.LangSmithCommandTimeoutError = exports.LangSmithSandboxOperationError = exports.LangSmithSandboxNotReadyError = exports.LangSmithSandboxCreationError = exports.LangSmithResourceCreationError = exports.LangSmithQuotaExceededError = exports.LangSmithValidationError = exports.LangSmithResourceNameConflictError = exports.LangSmithResourceAlreadyExistsError = exports.LangSmithResourceInUseError = exports.LangSmithResourceTimeoutError = exports.LangSmithResourceNotFoundError = exports.LangSmithSandboxServerReloadError = exports.LangSmithSandboxConnectionError = exports.LangSmithSandboxAuthenticationError = exports.LangSmithSandboxAPIError = exports.LangSmithSandboxError = exports.CommandHandle = exports.Sandbox = exports.SandboxClient = void 0;
|
|
28
|
-
// Emit warning on import (alpha feature)
|
|
29
|
-
console.warn("langsmith/experimental/sandbox is in alpha. " +
|
|
30
|
-
"This feature is experimental, and breaking changes are expected.");
|
|
31
28
|
// Main classes
|
|
32
29
|
var client_js_1 = require("./client.cjs");
|
|
33
30
|
Object.defineProperty(exports, "SandboxClient", { enumerable: true, get: function () { return client_js_1.SandboxClient; } });
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
export { SandboxClient } from "./client.js";
|
|
26
26
|
export { Sandbox } from "./sandbox.js";
|
|
27
27
|
export { CommandHandle } from "./command_handle.js";
|
|
28
|
-
export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceSpec, ResourceStatus, VolumeMountSpec, Volume, SandboxTemplate, Pool, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, CreateVolumeOptions, CreateTemplateOptions, UpdateTemplateOptions, CreatePoolOptions, UpdateVolumeOptions, UpdatePoolOptions, } from "./types.js";
|
|
28
|
+
export type { ExecutionResult, OutputChunk, WsMessage, WsRunOptions, ResourceSpec, ResourceStatus, Snapshot, VolumeMountSpec, Volume, SandboxTemplate, Pool, SandboxData, SandboxClientConfig, RunOptions, CreateSandboxOptions, CreateSnapshotOptions, CaptureSnapshotOptions, WaitForSnapshotOptions, StartSandboxOptions, UpdateSandboxOptions, WaitForSandboxOptions, CreateVolumeOptions, CreateTemplateOptions, UpdateTemplateOptions, CreatePoolOptions, UpdateVolumeOptions, UpdatePoolOptions, } from "./types.js";
|
|
29
29
|
export { LangSmithSandboxError, LangSmithSandboxAPIError, LangSmithSandboxAuthenticationError, LangSmithSandboxConnectionError, LangSmithSandboxServerReloadError, LangSmithResourceNotFoundError, LangSmithResourceTimeoutError, LangSmithResourceInUseError, LangSmithResourceAlreadyExistsError, LangSmithResourceNameConflictError, LangSmithValidationError, LangSmithQuotaExceededError, LangSmithResourceCreationError, LangSmithSandboxCreationError, LangSmithSandboxNotReadyError, LangSmithSandboxOperationError, LangSmithCommandTimeoutError, LangSmithDataplaneNotConfiguredError, } from "./errors.js";
|
|
@@ -22,9 +22,6 @@
|
|
|
22
22
|
*
|
|
23
23
|
* @packageDocumentation
|
|
24
24
|
*/
|
|
25
|
-
// Emit warning on import (alpha feature)
|
|
26
|
-
console.warn("langsmith/experimental/sandbox is in alpha. " +
|
|
27
|
-
"This feature is experimental, and breaking changes are expected.");
|
|
28
25
|
// Main classes
|
|
29
26
|
export { SandboxClient } from "./client.js";
|
|
30
27
|
export { Sandbox } from "./sandbox.js";
|
|
@@ -25,6 +25,8 @@ const ws_execute_js_1 = require("./ws_execute.cjs");
|
|
|
25
25
|
* await sandbox.delete();
|
|
26
26
|
* }
|
|
27
27
|
* ```
|
|
28
|
+
*
|
|
29
|
+
* @experimental This feature is experimental, and breaking changes are expected.
|
|
28
30
|
*/
|
|
29
31
|
class Sandbox {
|
|
30
32
|
/** @internal */
|
|
@@ -50,7 +52,7 @@ class Sandbox {
|
|
|
50
52
|
writable: true,
|
|
51
53
|
value: void 0
|
|
52
54
|
});
|
|
53
|
-
/** Provisioning status ("provisioning", "ready", "failed"). */
|
|
55
|
+
/** Provisioning status ("provisioning", "ready", "failed", "stopped"). */
|
|
54
56
|
Object.defineProperty(this, "status", {
|
|
55
57
|
enumerable: true,
|
|
56
58
|
configurable: true,
|
|
@@ -106,6 +108,34 @@ class Sandbox {
|
|
|
106
108
|
writable: true,
|
|
107
109
|
value: void 0
|
|
108
110
|
});
|
|
111
|
+
/** Snapshot ID used to create this sandbox. */
|
|
112
|
+
Object.defineProperty(this, "snapshot_id", {
|
|
113
|
+
enumerable: true,
|
|
114
|
+
configurable: true,
|
|
115
|
+
writable: true,
|
|
116
|
+
value: void 0
|
|
117
|
+
});
|
|
118
|
+
/** Number of vCPUs allocated. */
|
|
119
|
+
Object.defineProperty(this, "vCpus", {
|
|
120
|
+
enumerable: true,
|
|
121
|
+
configurable: true,
|
|
122
|
+
writable: true,
|
|
123
|
+
value: void 0
|
|
124
|
+
});
|
|
125
|
+
/** Memory allocation in bytes. */
|
|
126
|
+
Object.defineProperty(this, "mem_bytes", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
configurable: true,
|
|
129
|
+
writable: true,
|
|
130
|
+
value: void 0
|
|
131
|
+
});
|
|
132
|
+
/** Root filesystem capacity in bytes. */
|
|
133
|
+
Object.defineProperty(this, "fs_capacity_bytes", {
|
|
134
|
+
enumerable: true,
|
|
135
|
+
configurable: true,
|
|
136
|
+
writable: true,
|
|
137
|
+
value: void 0
|
|
138
|
+
});
|
|
109
139
|
Object.defineProperty(this, "_client", {
|
|
110
140
|
enumerable: true,
|
|
111
141
|
configurable: true,
|
|
@@ -123,6 +153,10 @@ class Sandbox {
|
|
|
123
153
|
this.ttl_seconds = data.ttl_seconds;
|
|
124
154
|
this.idle_ttl_seconds = data.idle_ttl_seconds;
|
|
125
155
|
this.expires_at = data.expires_at;
|
|
156
|
+
this.snapshot_id = data.snapshot_id;
|
|
157
|
+
this.vCpus = data.vcpus;
|
|
158
|
+
this.mem_bytes = data.mem_bytes;
|
|
159
|
+
this.fs_capacity_bytes = data.fs_capacity_bytes;
|
|
126
160
|
this._client = client;
|
|
127
161
|
}
|
|
128
162
|
/**
|
|
@@ -337,5 +371,35 @@ class Sandbox {
|
|
|
337
371
|
async delete() {
|
|
338
372
|
await this._client.deleteSandbox(this.name);
|
|
339
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Start a stopped sandbox and wait until ready.
|
|
376
|
+
*
|
|
377
|
+
* Updates this sandbox's status and dataplane_url in place.
|
|
378
|
+
*
|
|
379
|
+
* @param timeout - Timeout in seconds when waiting for ready. Default: 120.
|
|
380
|
+
*/
|
|
381
|
+
async start(options = {}) {
|
|
382
|
+
const refreshed = await this._client.startSandbox(this.name, options);
|
|
383
|
+
this.status = refreshed.status;
|
|
384
|
+
this.dataplane_url = refreshed.dataplane_url;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Stop a running sandbox (preserves sandbox files for later restart).
|
|
388
|
+
*/
|
|
389
|
+
async stop() {
|
|
390
|
+
await this._client.stopSandbox(this.name);
|
|
391
|
+
this.status = "stopped";
|
|
392
|
+
this.dataplane_url = undefined;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Capture a snapshot from this sandbox.
|
|
396
|
+
*
|
|
397
|
+
* @param name - Snapshot name.
|
|
398
|
+
* @param options - Capture options (checkpoint, timeout).
|
|
399
|
+
* @returns Snapshot in "ready" status.
|
|
400
|
+
*/
|
|
401
|
+
async captureSnapshot(name, options = {}) {
|
|
402
|
+
return this._client.captureSnapshot(this.name, name, options);
|
|
403
|
+
}
|
|
340
404
|
}
|
|
341
405
|
exports.Sandbox = Sandbox;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sandbox class for interacting with a specific sandbox instance.
|
|
3
3
|
*/
|
|
4
|
-
import type { ExecutionResult, RunOptions } from "./types.js";
|
|
4
|
+
import type { CaptureSnapshotOptions, ExecutionResult, RunOptions, Snapshot, StartSandboxOptions } from "./types.js";
|
|
5
5
|
import { CommandHandle } from "./command_handle.js";
|
|
6
6
|
/**
|
|
7
7
|
* Represents an active sandbox for running commands and file operations.
|
|
@@ -20,16 +20,18 @@ import { CommandHandle } from "./command_handle.js";
|
|
|
20
20
|
* await sandbox.delete();
|
|
21
21
|
* }
|
|
22
22
|
* ```
|
|
23
|
+
*
|
|
24
|
+
* @experimental This feature is experimental, and breaking changes are expected.
|
|
23
25
|
*/
|
|
24
26
|
export declare class Sandbox {
|
|
25
27
|
/** Display name (can be updated). */
|
|
26
28
|
readonly name: string;
|
|
27
29
|
/** Name of the template used to create this sandbox. */
|
|
28
|
-
readonly template_name
|
|
30
|
+
readonly template_name?: string;
|
|
29
31
|
/** URL for data plane operations (file I/O, command execution). */
|
|
30
|
-
|
|
31
|
-
/** Provisioning status ("provisioning", "ready", "failed"). */
|
|
32
|
-
|
|
32
|
+
dataplane_url?: string;
|
|
33
|
+
/** Provisioning status ("provisioning", "ready", "failed", "stopped"). */
|
|
34
|
+
status?: string;
|
|
33
35
|
/** Human-readable status message (e.g., error details when failed). */
|
|
34
36
|
readonly status_message?: string;
|
|
35
37
|
/** Unique identifier (UUID). Remains constant even if name changes. */
|
|
@@ -44,6 +46,14 @@ export declare class Sandbox {
|
|
|
44
46
|
readonly idle_ttl_seconds?: number;
|
|
45
47
|
/** Computed expiration timestamp when a TTL is active. */
|
|
46
48
|
readonly expires_at?: string;
|
|
49
|
+
/** Snapshot ID used to create this sandbox. */
|
|
50
|
+
readonly snapshot_id?: string;
|
|
51
|
+
/** Number of vCPUs allocated. */
|
|
52
|
+
readonly vCpus?: number;
|
|
53
|
+
/** Memory allocation in bytes. */
|
|
54
|
+
readonly mem_bytes?: number;
|
|
55
|
+
/** Root filesystem capacity in bytes. */
|
|
56
|
+
readonly fs_capacity_bytes?: number;
|
|
47
57
|
private _client;
|
|
48
58
|
/**
|
|
49
59
|
* Validate and return the dataplane URL.
|
|
@@ -145,4 +155,24 @@ export declare class Sandbox {
|
|
|
145
155
|
* ```
|
|
146
156
|
*/
|
|
147
157
|
delete(): Promise<void>;
|
|
158
|
+
/**
|
|
159
|
+
* Start a stopped sandbox and wait until ready.
|
|
160
|
+
*
|
|
161
|
+
* Updates this sandbox's status and dataplane_url in place.
|
|
162
|
+
*
|
|
163
|
+
* @param timeout - Timeout in seconds when waiting for ready. Default: 120.
|
|
164
|
+
*/
|
|
165
|
+
start(options?: StartSandboxOptions): Promise<void>;
|
|
166
|
+
/**
|
|
167
|
+
* Stop a running sandbox (preserves sandbox files for later restart).
|
|
168
|
+
*/
|
|
169
|
+
stop(): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Capture a snapshot from this sandbox.
|
|
172
|
+
*
|
|
173
|
+
* @param name - Snapshot name.
|
|
174
|
+
* @param options - Capture options (checkpoint, timeout).
|
|
175
|
+
* @returns Snapshot in "ready" status.
|
|
176
|
+
*/
|
|
177
|
+
captureSnapshot(name: string, options?: CaptureSnapshotOptions): Promise<Snapshot>;
|
|
148
178
|
}
|
|
@@ -22,6 +22,8 @@ import { reconnectWsStream, runWsStream } from "./ws_execute.js";
|
|
|
22
22
|
* await sandbox.delete();
|
|
23
23
|
* }
|
|
24
24
|
* ```
|
|
25
|
+
*
|
|
26
|
+
* @experimental This feature is experimental, and breaking changes are expected.
|
|
25
27
|
*/
|
|
26
28
|
export class Sandbox {
|
|
27
29
|
/** @internal */
|
|
@@ -47,7 +49,7 @@ export class Sandbox {
|
|
|
47
49
|
writable: true,
|
|
48
50
|
value: void 0
|
|
49
51
|
});
|
|
50
|
-
/** Provisioning status ("provisioning", "ready", "failed"). */
|
|
52
|
+
/** Provisioning status ("provisioning", "ready", "failed", "stopped"). */
|
|
51
53
|
Object.defineProperty(this, "status", {
|
|
52
54
|
enumerable: true,
|
|
53
55
|
configurable: true,
|
|
@@ -103,6 +105,34 @@ export class Sandbox {
|
|
|
103
105
|
writable: true,
|
|
104
106
|
value: void 0
|
|
105
107
|
});
|
|
108
|
+
/** Snapshot ID used to create this sandbox. */
|
|
109
|
+
Object.defineProperty(this, "snapshot_id", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: void 0
|
|
114
|
+
});
|
|
115
|
+
/** Number of vCPUs allocated. */
|
|
116
|
+
Object.defineProperty(this, "vCpus", {
|
|
117
|
+
enumerable: true,
|
|
118
|
+
configurable: true,
|
|
119
|
+
writable: true,
|
|
120
|
+
value: void 0
|
|
121
|
+
});
|
|
122
|
+
/** Memory allocation in bytes. */
|
|
123
|
+
Object.defineProperty(this, "mem_bytes", {
|
|
124
|
+
enumerable: true,
|
|
125
|
+
configurable: true,
|
|
126
|
+
writable: true,
|
|
127
|
+
value: void 0
|
|
128
|
+
});
|
|
129
|
+
/** Root filesystem capacity in bytes. */
|
|
130
|
+
Object.defineProperty(this, "fs_capacity_bytes", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true,
|
|
134
|
+
value: void 0
|
|
135
|
+
});
|
|
106
136
|
Object.defineProperty(this, "_client", {
|
|
107
137
|
enumerable: true,
|
|
108
138
|
configurable: true,
|
|
@@ -120,6 +150,10 @@ export class Sandbox {
|
|
|
120
150
|
this.ttl_seconds = data.ttl_seconds;
|
|
121
151
|
this.idle_ttl_seconds = data.idle_ttl_seconds;
|
|
122
152
|
this.expires_at = data.expires_at;
|
|
153
|
+
this.snapshot_id = data.snapshot_id;
|
|
154
|
+
this.vCpus = data.vcpus;
|
|
155
|
+
this.mem_bytes = data.mem_bytes;
|
|
156
|
+
this.fs_capacity_bytes = data.fs_capacity_bytes;
|
|
123
157
|
this._client = client;
|
|
124
158
|
}
|
|
125
159
|
/**
|
|
@@ -334,4 +368,34 @@ export class Sandbox {
|
|
|
334
368
|
async delete() {
|
|
335
369
|
await this._client.deleteSandbox(this.name);
|
|
336
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Start a stopped sandbox and wait until ready.
|
|
373
|
+
*
|
|
374
|
+
* Updates this sandbox's status and dataplane_url in place.
|
|
375
|
+
*
|
|
376
|
+
* @param timeout - Timeout in seconds when waiting for ready. Default: 120.
|
|
377
|
+
*/
|
|
378
|
+
async start(options = {}) {
|
|
379
|
+
const refreshed = await this._client.startSandbox(this.name, options);
|
|
380
|
+
this.status = refreshed.status;
|
|
381
|
+
this.dataplane_url = refreshed.dataplane_url;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Stop a running sandbox (preserves sandbox files for later restart).
|
|
385
|
+
*/
|
|
386
|
+
async stop() {
|
|
387
|
+
await this._client.stopSandbox(this.name);
|
|
388
|
+
this.status = "stopped";
|
|
389
|
+
this.dataplane_url = undefined;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Capture a snapshot from this sandbox.
|
|
393
|
+
*
|
|
394
|
+
* @param name - Snapshot name.
|
|
395
|
+
* @param options - Capture options (checkpoint, timeout).
|
|
396
|
+
* @returns Snapshot in "ready" status.
|
|
397
|
+
*/
|
|
398
|
+
async captureSnapshot(name, options = {}) {
|
|
399
|
+
return this._client.captureSnapshot(this.name, name, options);
|
|
400
|
+
}
|
|
337
401
|
}
|