@lizard-build/sdk 0.1.44 → 0.1.45
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 +1 -1
- package/dist/index.d.mts +42 -17
- package/dist/index.d.ts +42 -17
- package/dist/index.js +56 -18
- package/dist/index.mjs +56 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,7 +79,7 @@ Pass `timeoutMs` to `create()` to set the sandbox lifetime. The default is five
|
|
|
79
79
|
|
|
80
80
|
## Runtime limits
|
|
81
81
|
|
|
82
|
-
Sandboxes run on Kubernetes. Use volumes mounted at `/workspace` to keep files after a sandbox ends.
|
|
82
|
+
Sandboxes run on Kubernetes. Use volumes mounted at `/workspace` to keep files after a sandbox ends. CRIU pause/resume and private snapshots preserve running memory and workspace files. Snapshot pools keep five copies warm by default and can be paused to release idle compute. Fork and file watching remain unsupported. See the [snapshot lifecycle guide](../../docs/sandboxes.md#snapshots-and-criu-pause-resume).
|
|
83
83
|
|
|
84
84
|
`getHost()` returns a hostname without `https://`. File writes accept UTF-8 text or valid UTF-8 bytes; `readBytes()` supports binary downloads.
|
|
85
85
|
|
package/dist/index.d.mts
CHANGED
|
@@ -650,6 +650,9 @@ interface SandboxInfo {
|
|
|
650
650
|
/** Region the sandbox runs in — the volume's region when one is attached. */
|
|
651
651
|
region?: string;
|
|
652
652
|
status?: string;
|
|
653
|
+
pauseError?: string | null;
|
|
654
|
+
size?: 'small' | 'medium' | 'large' | null;
|
|
655
|
+
pricePerHour?: number | null;
|
|
653
656
|
cpus?: number;
|
|
654
657
|
memoryMb?: number;
|
|
655
658
|
metadata?: Record<string, string>;
|
|
@@ -665,6 +668,8 @@ interface SandboxOpts extends ConnectionOpts {
|
|
|
665
668
|
/** Exact project ID — skips resolving {@link SandboxOpts.project}. */
|
|
666
669
|
projectId?: string;
|
|
667
670
|
template?: string;
|
|
671
|
+
snapshotId?: string;
|
|
672
|
+
size?: 'small' | 'medium' | 'large';
|
|
668
673
|
metadata?: Record<string, string>;
|
|
669
674
|
envs?: Record<string, string>;
|
|
670
675
|
timeoutMs?: number;
|
|
@@ -731,6 +736,27 @@ declare class SandboxClient {
|
|
|
731
736
|
}>;
|
|
732
737
|
}
|
|
733
738
|
|
|
739
|
+
interface SandboxSnapshot {
|
|
740
|
+
id: string;
|
|
741
|
+
name: string;
|
|
742
|
+
projectId: string;
|
|
743
|
+
workspaceId: string;
|
|
744
|
+
region: string;
|
|
745
|
+
sourceSandboxId: string;
|
|
746
|
+
status: 'building' | 'warming' | 'ready' | 'paused' | 'suspended' | 'failed';
|
|
747
|
+
poolSize: number;
|
|
748
|
+
readyCount: number;
|
|
749
|
+
error: string | null;
|
|
750
|
+
cpus: number;
|
|
751
|
+
memoryMb: number;
|
|
752
|
+
createdAt: number;
|
|
753
|
+
}
|
|
754
|
+
interface SnapshotOpts {
|
|
755
|
+
poolSize?: number;
|
|
756
|
+
}
|
|
757
|
+
interface SnapshotWaitOpts extends ConnectionOpts {
|
|
758
|
+
waitTimeoutMs?: number;
|
|
759
|
+
}
|
|
734
760
|
/**
|
|
735
761
|
* A Linux sandbox running on Kubernetes.
|
|
736
762
|
*
|
|
@@ -856,20 +882,12 @@ declare class Sandbox extends SandboxClient {
|
|
|
856
882
|
* @returns `true` if the sandbox was terminated, `false` if it was already gone.
|
|
857
883
|
*/
|
|
858
884
|
kill(opts?: ConnectionOpts): Promise<boolean>;
|
|
859
|
-
/**
|
|
860
|
-
* Request sandbox pause. The Kubernetes backend returns HTTP 501.
|
|
861
|
-
*
|
|
862
|
-
* @deprecated Unsupported on Kubernetes. Save files to a {@link Volume}
|
|
863
|
-
* and attach it to a new sandbox instead.
|
|
864
|
-
*/
|
|
885
|
+
/** Queue a CRIU checkpoint and stop compute. Use waitForStatus('paused') before resuming. */
|
|
865
886
|
pause(opts?: ConnectionOpts): Promise<boolean>;
|
|
866
|
-
/**
|
|
867
|
-
* Request sandbox resume. The Kubernetes backend returns HTTP 501.
|
|
868
|
-
*
|
|
869
|
-
* @deprecated Unsupported on Kubernetes. Use {@link Sandbox.connect} to
|
|
870
|
-
* reconnect to a running sandbox.
|
|
871
|
-
*/
|
|
887
|
+
/** Queue restoration of saved memory and files. Use waitForStatus('running') before executing. */
|
|
872
888
|
resume(opts?: ConnectionOpts): Promise<boolean>;
|
|
889
|
+
/** Wait for an asynchronous pause/resume operation to finish. */
|
|
890
|
+
waitForStatus(status: 'paused' | 'running', opts?: SnapshotWaitOpts): Promise<SandboxInfo>;
|
|
873
891
|
/**
|
|
874
892
|
* Get metadata and status information about this sandbox.
|
|
875
893
|
*/
|
|
@@ -899,18 +917,25 @@ declare class Sandbox extends SandboxClient {
|
|
|
899
917
|
count?: number;
|
|
900
918
|
timeoutMs?: number;
|
|
901
919
|
}): Promise<unknown>;
|
|
902
|
-
/**
|
|
903
|
-
snapshot(name?: string): Promise<
|
|
920
|
+
/** Capture memory and workspace files. Disconnect active clients before capturing. */
|
|
921
|
+
snapshot(name?: string, opts?: SnapshotOpts): Promise<SandboxSnapshot>;
|
|
904
922
|
unexpose(port: number): Promise<void>;
|
|
905
923
|
logs(opts?: {
|
|
906
924
|
tail?: number;
|
|
907
925
|
signal?: AbortSignal;
|
|
908
926
|
}): AsyncGenerator<StreamEvent, any, any>;
|
|
909
|
-
static snapshots(projectId: string, opts?: ConnectionOpts): Promise<
|
|
910
|
-
|
|
927
|
+
static snapshots(projectId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot[]>;
|
|
928
|
+
static getSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
929
|
+
/** Start a sandbox from an available warm copy in the snapshot's project and region. */
|
|
911
930
|
static restore(snapshotId: string, opts?: ConnectionOpts & {
|
|
912
931
|
timeoutMs?: number;
|
|
913
932
|
}): Promise<Sandbox>;
|
|
933
|
+
static setSnapshotWarmPool(snapshotId: string, poolSize: number, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
934
|
+
/** Release idle warm copies; retain saved state and existing claimed sandboxes. */
|
|
935
|
+
static pauseSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
936
|
+
/** Refill the configured warm pool without another capture. */
|
|
937
|
+
static resumeSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
938
|
+
static waitForSnapshot(snapshotId: string, opts?: SnapshotWaitOpts): Promise<SandboxSnapshot>;
|
|
914
939
|
static deleteSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<void>;
|
|
915
940
|
private resolveOpts;
|
|
916
941
|
}
|
|
@@ -1773,4 +1798,4 @@ declare class LizardCLI {
|
|
|
1773
1798
|
}): Promise<CLIResult>;
|
|
1774
1799
|
}
|
|
1775
1800
|
|
|
1776
|
-
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type CodeContext, CodeSandbox, ConfigApplyError, type ConfigResult, ConflictError, type ConnectionOpts, type CostMetrics, type CreateAddonOpts, type CreateApiKeyOpts, type CreateContextOpts, type CreateProjectOpts, type CreateServiceOpts, type CreateVolumeOpts, type CreateWorkspaceOpts, type CreatedApiKey, type DeployEvent, DeployHandle, type DomainInfo, type DomainStatus, DomainsAPI, Execution, ExecutionError, type FileInfo, type FsOpts, GitHubAPI, type ListTransactionsOpts, Lizard, LizardCLI, LizardError, type LizardOpts, type LogLine, type MetricPoint, type MetricRange, MetricsAPI, NotFoundError, PlatformClient, type ProcessOpts, type ProcessResult, type Project, type ProjectConfig, type ProjectCost, ProjectsAPI, type RawMetrics, type Region, RegionsAPI, type RunCodeLanguage, type RunCodeOpts, Sandbox, type SandboxInfo, type SandboxOpts, type ScaleOpts, type Secret, SecretsAPI, type Service, type ServiceMetrics, type ServiceUpdate, ServicesAPI, type SetSecretOpts, StorageAPI, type StreamEvent, TimeoutError, type Transaction, type TransactionPage, Volume, type VolumeInfo, type Workspace, WorkspacesAPI, resolveProjectId };
|
|
1801
|
+
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type CodeContext, CodeSandbox, ConfigApplyError, type ConfigResult, ConflictError, type ConnectionOpts, type CostMetrics, type CreateAddonOpts, type CreateApiKeyOpts, type CreateContextOpts, type CreateProjectOpts, type CreateServiceOpts, type CreateVolumeOpts, type CreateWorkspaceOpts, type CreatedApiKey, type DeployEvent, DeployHandle, type DomainInfo, type DomainStatus, DomainsAPI, Execution, ExecutionError, type FileInfo, type FsOpts, GitHubAPI, type ListTransactionsOpts, Lizard, LizardCLI, LizardError, type LizardOpts, type LogLine, type MetricPoint, type MetricRange, MetricsAPI, NotFoundError, PlatformClient, type ProcessOpts, type ProcessResult, type Project, type ProjectConfig, type ProjectCost, ProjectsAPI, type RawMetrics, type Region, RegionsAPI, type RunCodeLanguage, type RunCodeOpts, Sandbox, type SandboxInfo, type SandboxOpts, type SandboxSnapshot, type ScaleOpts, type Secret, SecretsAPI, type Service, type ServiceMetrics, type ServiceUpdate, ServicesAPI, type SetSecretOpts, type SnapshotOpts, type SnapshotWaitOpts, StorageAPI, type StreamEvent, TimeoutError, type Transaction, type TransactionPage, Volume, type VolumeInfo, type Workspace, WorkspacesAPI, resolveProjectId };
|
package/dist/index.d.ts
CHANGED
|
@@ -650,6 +650,9 @@ interface SandboxInfo {
|
|
|
650
650
|
/** Region the sandbox runs in — the volume's region when one is attached. */
|
|
651
651
|
region?: string;
|
|
652
652
|
status?: string;
|
|
653
|
+
pauseError?: string | null;
|
|
654
|
+
size?: 'small' | 'medium' | 'large' | null;
|
|
655
|
+
pricePerHour?: number | null;
|
|
653
656
|
cpus?: number;
|
|
654
657
|
memoryMb?: number;
|
|
655
658
|
metadata?: Record<string, string>;
|
|
@@ -665,6 +668,8 @@ interface SandboxOpts extends ConnectionOpts {
|
|
|
665
668
|
/** Exact project ID — skips resolving {@link SandboxOpts.project}. */
|
|
666
669
|
projectId?: string;
|
|
667
670
|
template?: string;
|
|
671
|
+
snapshotId?: string;
|
|
672
|
+
size?: 'small' | 'medium' | 'large';
|
|
668
673
|
metadata?: Record<string, string>;
|
|
669
674
|
envs?: Record<string, string>;
|
|
670
675
|
timeoutMs?: number;
|
|
@@ -731,6 +736,27 @@ declare class SandboxClient {
|
|
|
731
736
|
}>;
|
|
732
737
|
}
|
|
733
738
|
|
|
739
|
+
interface SandboxSnapshot {
|
|
740
|
+
id: string;
|
|
741
|
+
name: string;
|
|
742
|
+
projectId: string;
|
|
743
|
+
workspaceId: string;
|
|
744
|
+
region: string;
|
|
745
|
+
sourceSandboxId: string;
|
|
746
|
+
status: 'building' | 'warming' | 'ready' | 'paused' | 'suspended' | 'failed';
|
|
747
|
+
poolSize: number;
|
|
748
|
+
readyCount: number;
|
|
749
|
+
error: string | null;
|
|
750
|
+
cpus: number;
|
|
751
|
+
memoryMb: number;
|
|
752
|
+
createdAt: number;
|
|
753
|
+
}
|
|
754
|
+
interface SnapshotOpts {
|
|
755
|
+
poolSize?: number;
|
|
756
|
+
}
|
|
757
|
+
interface SnapshotWaitOpts extends ConnectionOpts {
|
|
758
|
+
waitTimeoutMs?: number;
|
|
759
|
+
}
|
|
734
760
|
/**
|
|
735
761
|
* A Linux sandbox running on Kubernetes.
|
|
736
762
|
*
|
|
@@ -856,20 +882,12 @@ declare class Sandbox extends SandboxClient {
|
|
|
856
882
|
* @returns `true` if the sandbox was terminated, `false` if it was already gone.
|
|
857
883
|
*/
|
|
858
884
|
kill(opts?: ConnectionOpts): Promise<boolean>;
|
|
859
|
-
/**
|
|
860
|
-
* Request sandbox pause. The Kubernetes backend returns HTTP 501.
|
|
861
|
-
*
|
|
862
|
-
* @deprecated Unsupported on Kubernetes. Save files to a {@link Volume}
|
|
863
|
-
* and attach it to a new sandbox instead.
|
|
864
|
-
*/
|
|
885
|
+
/** Queue a CRIU checkpoint and stop compute. Use waitForStatus('paused') before resuming. */
|
|
865
886
|
pause(opts?: ConnectionOpts): Promise<boolean>;
|
|
866
|
-
/**
|
|
867
|
-
* Request sandbox resume. The Kubernetes backend returns HTTP 501.
|
|
868
|
-
*
|
|
869
|
-
* @deprecated Unsupported on Kubernetes. Use {@link Sandbox.connect} to
|
|
870
|
-
* reconnect to a running sandbox.
|
|
871
|
-
*/
|
|
887
|
+
/** Queue restoration of saved memory and files. Use waitForStatus('running') before executing. */
|
|
872
888
|
resume(opts?: ConnectionOpts): Promise<boolean>;
|
|
889
|
+
/** Wait for an asynchronous pause/resume operation to finish. */
|
|
890
|
+
waitForStatus(status: 'paused' | 'running', opts?: SnapshotWaitOpts): Promise<SandboxInfo>;
|
|
873
891
|
/**
|
|
874
892
|
* Get metadata and status information about this sandbox.
|
|
875
893
|
*/
|
|
@@ -899,18 +917,25 @@ declare class Sandbox extends SandboxClient {
|
|
|
899
917
|
count?: number;
|
|
900
918
|
timeoutMs?: number;
|
|
901
919
|
}): Promise<unknown>;
|
|
902
|
-
/**
|
|
903
|
-
snapshot(name?: string): Promise<
|
|
920
|
+
/** Capture memory and workspace files. Disconnect active clients before capturing. */
|
|
921
|
+
snapshot(name?: string, opts?: SnapshotOpts): Promise<SandboxSnapshot>;
|
|
904
922
|
unexpose(port: number): Promise<void>;
|
|
905
923
|
logs(opts?: {
|
|
906
924
|
tail?: number;
|
|
907
925
|
signal?: AbortSignal;
|
|
908
926
|
}): AsyncGenerator<StreamEvent, any, any>;
|
|
909
|
-
static snapshots(projectId: string, opts?: ConnectionOpts): Promise<
|
|
910
|
-
|
|
927
|
+
static snapshots(projectId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot[]>;
|
|
928
|
+
static getSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
929
|
+
/** Start a sandbox from an available warm copy in the snapshot's project and region. */
|
|
911
930
|
static restore(snapshotId: string, opts?: ConnectionOpts & {
|
|
912
931
|
timeoutMs?: number;
|
|
913
932
|
}): Promise<Sandbox>;
|
|
933
|
+
static setSnapshotWarmPool(snapshotId: string, poolSize: number, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
934
|
+
/** Release idle warm copies; retain saved state and existing claimed sandboxes. */
|
|
935
|
+
static pauseSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
936
|
+
/** Refill the configured warm pool without another capture. */
|
|
937
|
+
static resumeSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
938
|
+
static waitForSnapshot(snapshotId: string, opts?: SnapshotWaitOpts): Promise<SandboxSnapshot>;
|
|
914
939
|
static deleteSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<void>;
|
|
915
940
|
private resolveOpts;
|
|
916
941
|
}
|
|
@@ -1773,4 +1798,4 @@ declare class LizardCLI {
|
|
|
1773
1798
|
}): Promise<CLIResult>;
|
|
1774
1799
|
}
|
|
1775
1800
|
|
|
1776
|
-
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type CodeContext, CodeSandbox, ConfigApplyError, type ConfigResult, ConflictError, type ConnectionOpts, type CostMetrics, type CreateAddonOpts, type CreateApiKeyOpts, type CreateContextOpts, type CreateProjectOpts, type CreateServiceOpts, type CreateVolumeOpts, type CreateWorkspaceOpts, type CreatedApiKey, type DeployEvent, DeployHandle, type DomainInfo, type DomainStatus, DomainsAPI, Execution, ExecutionError, type FileInfo, type FsOpts, GitHubAPI, type ListTransactionsOpts, Lizard, LizardCLI, LizardError, type LizardOpts, type LogLine, type MetricPoint, type MetricRange, MetricsAPI, NotFoundError, PlatformClient, type ProcessOpts, type ProcessResult, type Project, type ProjectConfig, type ProjectCost, ProjectsAPI, type RawMetrics, type Region, RegionsAPI, type RunCodeLanguage, type RunCodeOpts, Sandbox, type SandboxInfo, type SandboxOpts, type ScaleOpts, type Secret, SecretsAPI, type Service, type ServiceMetrics, type ServiceUpdate, ServicesAPI, type SetSecretOpts, StorageAPI, type StreamEvent, TimeoutError, type Transaction, type TransactionPage, Volume, type VolumeInfo, type Workspace, WorkspacesAPI, resolveProjectId };
|
|
1801
|
+
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type CodeContext, CodeSandbox, ConfigApplyError, type ConfigResult, ConflictError, type ConnectionOpts, type CostMetrics, type CreateAddonOpts, type CreateApiKeyOpts, type CreateContextOpts, type CreateProjectOpts, type CreateServiceOpts, type CreateVolumeOpts, type CreateWorkspaceOpts, type CreatedApiKey, type DeployEvent, DeployHandle, type DomainInfo, type DomainStatus, DomainsAPI, Execution, ExecutionError, type FileInfo, type FsOpts, GitHubAPI, type ListTransactionsOpts, Lizard, LizardCLI, LizardError, type LizardOpts, type LogLine, type MetricPoint, type MetricRange, MetricsAPI, NotFoundError, PlatformClient, type ProcessOpts, type ProcessResult, type Project, type ProjectConfig, type ProjectCost, ProjectsAPI, type RawMetrics, type Region, RegionsAPI, type RunCodeLanguage, type RunCodeOpts, Sandbox, type SandboxInfo, type SandboxOpts, type SandboxSnapshot, type ScaleOpts, type Secret, SecretsAPI, type Service, type ServiceMetrics, type ServiceUpdate, ServicesAPI, type SetSecretOpts, type SnapshotOpts, type SnapshotWaitOpts, StorageAPI, type StreamEvent, TimeoutError, type Transaction, type TransactionPage, Volume, type VolumeInfo, type Workspace, WorkspacesAPI, resolveProjectId };
|
package/dist/index.js
CHANGED
|
@@ -849,6 +849,8 @@ var SandboxClient = class {
|
|
|
849
849
|
headers: config.headers,
|
|
850
850
|
body: JSON.stringify({
|
|
851
851
|
template,
|
|
852
|
+
snapshotId: opts?.snapshotId,
|
|
853
|
+
size: opts?.size,
|
|
852
854
|
timeoutMs,
|
|
853
855
|
projectId,
|
|
854
856
|
metadata: opts?.metadata,
|
|
@@ -981,24 +983,28 @@ var Sandbox = class extends SandboxClient {
|
|
|
981
983
|
async kill(opts) {
|
|
982
984
|
return SandboxClient.killSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
983
985
|
}
|
|
984
|
-
/**
|
|
985
|
-
* Request sandbox pause. The Kubernetes backend returns HTTP 501.
|
|
986
|
-
*
|
|
987
|
-
* @deprecated Unsupported on Kubernetes. Save files to a {@link Volume}
|
|
988
|
-
* and attach it to a new sandbox instead.
|
|
989
|
-
*/
|
|
986
|
+
/** Queue a CRIU checkpoint and stop compute. Use waitForStatus('paused') before resuming. */
|
|
990
987
|
async pause(opts) {
|
|
991
988
|
return SandboxClient.pauseSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
992
989
|
}
|
|
993
|
-
/**
|
|
994
|
-
* Request sandbox resume. The Kubernetes backend returns HTTP 501.
|
|
995
|
-
*
|
|
996
|
-
* @deprecated Unsupported on Kubernetes. Use {@link Sandbox.connect} to
|
|
997
|
-
* reconnect to a running sandbox.
|
|
998
|
-
*/
|
|
990
|
+
/** Queue restoration of saved memory and files. Use waitForStatus('running') before executing. */
|
|
999
991
|
async resume(opts) {
|
|
1000
992
|
return SandboxClient.resumeSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
1001
993
|
}
|
|
994
|
+
/** Wait for an asynchronous pause/resume operation to finish. */
|
|
995
|
+
async waitForStatus(status, opts) {
|
|
996
|
+
const deadline = Date.now() + (opts?.waitTimeoutMs ?? 6e5);
|
|
997
|
+
do {
|
|
998
|
+
const info = await this.getInfo(opts);
|
|
999
|
+
if (info.status === status) return info;
|
|
1000
|
+
if (["failed", "stopped", "deleted"].includes(info.status ?? "") || info.pauseError) {
|
|
1001
|
+
throw new ConflictError(info.pauseError ?? `Sandbox is ${info.status}`);
|
|
1002
|
+
}
|
|
1003
|
+
if (Date.now() >= deadline) break;
|
|
1004
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1005
|
+
} while (Date.now() < deadline);
|
|
1006
|
+
throw new TimeoutError(`Sandbox did not become ${status} within the wait timeout`);
|
|
1007
|
+
}
|
|
1002
1008
|
/**
|
|
1003
1009
|
* Get metadata and status information about this sandbox.
|
|
1004
1010
|
*/
|
|
@@ -1034,9 +1040,9 @@ var Sandbox = class extends SandboxClient {
|
|
|
1034
1040
|
fork(opts = {}) {
|
|
1035
1041
|
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/fork`, { count: opts.count ?? 1, timeoutMs: opts.timeoutMs ?? 0 });
|
|
1036
1042
|
}
|
|
1037
|
-
/**
|
|
1038
|
-
snapshot(name) {
|
|
1039
|
-
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/snapshot`, { name });
|
|
1043
|
+
/** Capture memory and workspace files. Disconnect active clients before capturing. */
|
|
1044
|
+
snapshot(name = `Snapshot ${this.sandboxId}`, opts = {}) {
|
|
1045
|
+
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/snapshot`, { name, poolSize: opts.poolSize ?? 5 });
|
|
1040
1046
|
}
|
|
1041
1047
|
unexpose(port) {
|
|
1042
1048
|
return new PlatformClient(this.resolveOpts()).delete(`/api/sandboxes/${this.sandboxId}/expose/${port}`);
|
|
@@ -1045,13 +1051,45 @@ var Sandbox = class extends SandboxClient {
|
|
|
1045
1051
|
return new PlatformClient(this.resolveOpts()).events(query(`/api/sandboxes/${this.sandboxId}/logs`, { tail: opts.tail }), { signal: opts.signal });
|
|
1046
1052
|
}
|
|
1047
1053
|
static snapshots(projectId, opts) {
|
|
1048
|
-
return new PlatformClient(opts ?? {}).get(`/api/projects/${projectId}/snapshots`);
|
|
1054
|
+
return new PlatformClient(opts ?? {}).get(`/api/projects/${encodeURIComponent(projectId)}/snapshots`);
|
|
1055
|
+
}
|
|
1056
|
+
static getSnapshot(snapshotId, opts) {
|
|
1057
|
+
return new PlatformClient(opts ?? {}).get(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`);
|
|
1049
1058
|
}
|
|
1050
|
-
/**
|
|
1059
|
+
/** Start a sandbox from an available warm copy in the snapshot's project and region. */
|
|
1051
1060
|
static async restore(snapshotId, opts) {
|
|
1052
|
-
const
|
|
1061
|
+
const client = new PlatformClient(opts ?? {});
|
|
1062
|
+
const snapshot = await this.getSnapshot(snapshotId, opts);
|
|
1063
|
+
const result = await client.post("/api/sandboxes", {
|
|
1064
|
+
snapshotId,
|
|
1065
|
+
projectId: snapshot.projectId,
|
|
1066
|
+
region: snapshot.region,
|
|
1067
|
+
timeoutMs: opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS
|
|
1068
|
+
});
|
|
1053
1069
|
return new this({ ...opts, sandboxId: result.sandboxId ?? result.id });
|
|
1054
1070
|
}
|
|
1071
|
+
static setSnapshotWarmPool(snapshotId, poolSize, opts) {
|
|
1072
|
+
return new PlatformClient(opts ?? {}).patch(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`, { poolSize });
|
|
1073
|
+
}
|
|
1074
|
+
/** Release idle warm copies; retain saved state and existing claimed sandboxes. */
|
|
1075
|
+
static pauseSnapshot(snapshotId, opts) {
|
|
1076
|
+
return new PlatformClient(opts ?? {}).post(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}/pause`, {});
|
|
1077
|
+
}
|
|
1078
|
+
/** Refill the configured warm pool without another capture. */
|
|
1079
|
+
static resumeSnapshot(snapshotId, opts) {
|
|
1080
|
+
return new PlatformClient(opts ?? {}).post(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}/resume`, {});
|
|
1081
|
+
}
|
|
1082
|
+
static async waitForSnapshot(snapshotId, opts) {
|
|
1083
|
+
const deadline = Date.now() + (opts?.waitTimeoutMs ?? 9e5);
|
|
1084
|
+
do {
|
|
1085
|
+
const snapshot = await this.getSnapshot(snapshotId, opts);
|
|
1086
|
+
if (snapshot.status === "ready") return snapshot;
|
|
1087
|
+
if (["failed", "paused", "suspended"].includes(snapshot.status)) throw new ConflictError(snapshot.error ?? `Snapshot is ${snapshot.status}`);
|
|
1088
|
+
if (Date.now() >= deadline) break;
|
|
1089
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1090
|
+
} while (Date.now() < deadline);
|
|
1091
|
+
throw new TimeoutError("Snapshot did not become ready within the wait timeout");
|
|
1092
|
+
}
|
|
1055
1093
|
static deleteSnapshot(snapshotId, opts) {
|
|
1056
1094
|
return new PlatformClient(opts ?? {}).delete(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`);
|
|
1057
1095
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -798,6 +798,8 @@ var SandboxClient = class {
|
|
|
798
798
|
headers: config.headers,
|
|
799
799
|
body: JSON.stringify({
|
|
800
800
|
template,
|
|
801
|
+
snapshotId: opts?.snapshotId,
|
|
802
|
+
size: opts?.size,
|
|
801
803
|
timeoutMs,
|
|
802
804
|
projectId,
|
|
803
805
|
metadata: opts?.metadata,
|
|
@@ -930,24 +932,28 @@ var Sandbox = class extends SandboxClient {
|
|
|
930
932
|
async kill(opts) {
|
|
931
933
|
return SandboxClient.killSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
932
934
|
}
|
|
933
|
-
/**
|
|
934
|
-
* Request sandbox pause. The Kubernetes backend returns HTTP 501.
|
|
935
|
-
*
|
|
936
|
-
* @deprecated Unsupported on Kubernetes. Save files to a {@link Volume}
|
|
937
|
-
* and attach it to a new sandbox instead.
|
|
938
|
-
*/
|
|
935
|
+
/** Queue a CRIU checkpoint and stop compute. Use waitForStatus('paused') before resuming. */
|
|
939
936
|
async pause(opts) {
|
|
940
937
|
return SandboxClient.pauseSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
941
938
|
}
|
|
942
|
-
/**
|
|
943
|
-
* Request sandbox resume. The Kubernetes backend returns HTTP 501.
|
|
944
|
-
*
|
|
945
|
-
* @deprecated Unsupported on Kubernetes. Use {@link Sandbox.connect} to
|
|
946
|
-
* reconnect to a running sandbox.
|
|
947
|
-
*/
|
|
939
|
+
/** Queue restoration of saved memory and files. Use waitForStatus('running') before executing. */
|
|
948
940
|
async resume(opts) {
|
|
949
941
|
return SandboxClient.resumeSandbox(this.sandboxId, this.resolveOpts(opts));
|
|
950
942
|
}
|
|
943
|
+
/** Wait for an asynchronous pause/resume operation to finish. */
|
|
944
|
+
async waitForStatus(status, opts) {
|
|
945
|
+
const deadline = Date.now() + (opts?.waitTimeoutMs ?? 6e5);
|
|
946
|
+
do {
|
|
947
|
+
const info = await this.getInfo(opts);
|
|
948
|
+
if (info.status === status) return info;
|
|
949
|
+
if (["failed", "stopped", "deleted"].includes(info.status ?? "") || info.pauseError) {
|
|
950
|
+
throw new ConflictError(info.pauseError ?? `Sandbox is ${info.status}`);
|
|
951
|
+
}
|
|
952
|
+
if (Date.now() >= deadline) break;
|
|
953
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
954
|
+
} while (Date.now() < deadline);
|
|
955
|
+
throw new TimeoutError(`Sandbox did not become ${status} within the wait timeout`);
|
|
956
|
+
}
|
|
951
957
|
/**
|
|
952
958
|
* Get metadata and status information about this sandbox.
|
|
953
959
|
*/
|
|
@@ -983,9 +989,9 @@ var Sandbox = class extends SandboxClient {
|
|
|
983
989
|
fork(opts = {}) {
|
|
984
990
|
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/fork`, { count: opts.count ?? 1, timeoutMs: opts.timeoutMs ?? 0 });
|
|
985
991
|
}
|
|
986
|
-
/**
|
|
987
|
-
snapshot(name) {
|
|
988
|
-
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/snapshot`, { name });
|
|
992
|
+
/** Capture memory and workspace files. Disconnect active clients before capturing. */
|
|
993
|
+
snapshot(name = `Snapshot ${this.sandboxId}`, opts = {}) {
|
|
994
|
+
return new PlatformClient(this.resolveOpts()).post(`/api/sandboxes/${this.sandboxId}/snapshot`, { name, poolSize: opts.poolSize ?? 5 });
|
|
989
995
|
}
|
|
990
996
|
unexpose(port) {
|
|
991
997
|
return new PlatformClient(this.resolveOpts()).delete(`/api/sandboxes/${this.sandboxId}/expose/${port}`);
|
|
@@ -994,13 +1000,45 @@ var Sandbox = class extends SandboxClient {
|
|
|
994
1000
|
return new PlatformClient(this.resolveOpts()).events(query(`/api/sandboxes/${this.sandboxId}/logs`, { tail: opts.tail }), { signal: opts.signal });
|
|
995
1001
|
}
|
|
996
1002
|
static snapshots(projectId, opts) {
|
|
997
|
-
return new PlatformClient(opts ?? {}).get(`/api/projects/${projectId}/snapshots`);
|
|
1003
|
+
return new PlatformClient(opts ?? {}).get(`/api/projects/${encodeURIComponent(projectId)}/snapshots`);
|
|
1004
|
+
}
|
|
1005
|
+
static getSnapshot(snapshotId, opts) {
|
|
1006
|
+
return new PlatformClient(opts ?? {}).get(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`);
|
|
998
1007
|
}
|
|
999
|
-
/**
|
|
1008
|
+
/** Start a sandbox from an available warm copy in the snapshot's project and region. */
|
|
1000
1009
|
static async restore(snapshotId, opts) {
|
|
1001
|
-
const
|
|
1010
|
+
const client = new PlatformClient(opts ?? {});
|
|
1011
|
+
const snapshot = await this.getSnapshot(snapshotId, opts);
|
|
1012
|
+
const result = await client.post("/api/sandboxes", {
|
|
1013
|
+
snapshotId,
|
|
1014
|
+
projectId: snapshot.projectId,
|
|
1015
|
+
region: snapshot.region,
|
|
1016
|
+
timeoutMs: opts?.timeoutMs ?? DEFAULT_SANDBOX_TIMEOUT_MS
|
|
1017
|
+
});
|
|
1002
1018
|
return new this({ ...opts, sandboxId: result.sandboxId ?? result.id });
|
|
1003
1019
|
}
|
|
1020
|
+
static setSnapshotWarmPool(snapshotId, poolSize, opts) {
|
|
1021
|
+
return new PlatformClient(opts ?? {}).patch(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`, { poolSize });
|
|
1022
|
+
}
|
|
1023
|
+
/** Release idle warm copies; retain saved state and existing claimed sandboxes. */
|
|
1024
|
+
static pauseSnapshot(snapshotId, opts) {
|
|
1025
|
+
return new PlatformClient(opts ?? {}).post(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}/pause`, {});
|
|
1026
|
+
}
|
|
1027
|
+
/** Refill the configured warm pool without another capture. */
|
|
1028
|
+
static resumeSnapshot(snapshotId, opts) {
|
|
1029
|
+
return new PlatformClient(opts ?? {}).post(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}/resume`, {});
|
|
1030
|
+
}
|
|
1031
|
+
static async waitForSnapshot(snapshotId, opts) {
|
|
1032
|
+
const deadline = Date.now() + (opts?.waitTimeoutMs ?? 9e5);
|
|
1033
|
+
do {
|
|
1034
|
+
const snapshot = await this.getSnapshot(snapshotId, opts);
|
|
1035
|
+
if (snapshot.status === "ready") return snapshot;
|
|
1036
|
+
if (["failed", "paused", "suspended"].includes(snapshot.status)) throw new ConflictError(snapshot.error ?? `Snapshot is ${snapshot.status}`);
|
|
1037
|
+
if (Date.now() >= deadline) break;
|
|
1038
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1039
|
+
} while (Date.now() < deadline);
|
|
1040
|
+
throw new TimeoutError("Snapshot did not become ready within the wait timeout");
|
|
1041
|
+
}
|
|
1004
1042
|
static deleteSnapshot(snapshotId, opts) {
|
|
1005
1043
|
return new PlatformClient(opts ?? {}).delete(`/api/sandbox-snapshots/${encodeURIComponent(snapshotId)}`);
|
|
1006
1044
|
}
|
package/package.json
CHANGED