@lizard-build/sdk 0.1.48 → 0.1.51
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 +25 -6
- package/dist/index.d.mts +209 -87
- package/dist/index.d.ts +209 -87
- package/dist/index.js +535 -166
- package/dist/index.mjs +535 -166
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lizard SDK for TypeScript
|
|
2
2
|
|
|
3
|
-
Run commands, work with files and execute code in Linux sandboxes
|
|
3
|
+
Run commands, work with files and execute code in Linux sandboxes (Firecracker microVMs). The SDK also manages Lizard apps, databases, storage and projects.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -79,7 +79,7 @@ Treat `url` like a credential: anyone with it can see and control the desktop. S
|
|
|
79
79
|
|
|
80
80
|
## Run Python
|
|
81
81
|
|
|
82
|
-
Run Python with the `interpreter` template. Each process command starts a separate Python process, so Python variables do not survive between calls
|
|
82
|
+
Run Python with the `interpreter` template. Each process command starts a separate Python process, so Python variables do not survive between calls; use `CodeSandbox` (below) when they should.
|
|
83
83
|
|
|
84
84
|
```ts
|
|
85
85
|
import { Sandbox } from '@lizard-build/sdk';
|
|
@@ -95,7 +95,26 @@ try {
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
To run code snippets with state carried between calls, use `CodeSandbox` (`runCode` / `run_code`): it boots the `interpreter` template and runs Python in a persistent Jupyter kernel inside the sandbox. See [Run code](https://github.com/lizard-build/lizard-sdk/blob/main/docs/sandboxes.md#run-code-codesandbox).
|
|
99
|
+
|
|
100
|
+
## Run code with state (CodeSandbox)
|
|
101
|
+
|
|
102
|
+
`CodeSandbox` boots the `interpreter` template and runs Python in a persistent Jupyter kernel inside the sandbox: variables survive between calls, the value of the last expression and matplotlib charts come back in `results`, and exceptions in `error`.
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { CodeSandbox } from '@lizard-build/sdk';
|
|
106
|
+
|
|
107
|
+
const sandbox = await CodeSandbox.create({ projectId: 'proj_123' });
|
|
108
|
+
try {
|
|
109
|
+
await sandbox.runCode('x = 21');
|
|
110
|
+
const run = await sandbox.runCode('x * 2');
|
|
111
|
+
console.log(run.results[0].data); // "42"
|
|
112
|
+
} finally {
|
|
113
|
+
await sandbox.kill();
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`language: 'bash'` (and `'javascript'` where `node` is installed; the `interpreter` template does not ship it) runs each call as a fresh process with no shared state.
|
|
99
118
|
|
|
100
119
|
## Configuration
|
|
101
120
|
|
|
@@ -105,13 +124,13 @@ Pass `timeoutMs` to `create()` to set the sandbox lifetime. The default is five
|
|
|
105
124
|
|
|
106
125
|
## Runtime limits
|
|
107
126
|
|
|
108
|
-
|
|
127
|
+
Each sandbox is a Firecracker microVM with its own kernel. Use volumes mounted at `/workspace` to keep files after a sandbox ends. `pause()`/`resume()` keep memory and running processes; `snapshot()` is ready in about 2 s and `Sandbox.restore()` starts a copy in about 0.4 s; `fork()` clones a running sandbox. File watching and sandbox log streaming are not available on Firecracker sandboxes yet, volumes cannot be resized yet, and a sandbox with a volume attached cannot be forked. See the [snapshot guide](../../docs/sandboxes.md#pause-resume-snapshots-and-fork).
|
|
109
128
|
|
|
110
|
-
`getHost()` returns a hostname without `https
|
|
129
|
+
`getHost()` returns a hostname without `https://`; the port is private, so send `sandbox.accessToken` as the `X-Lizard-Access-Token` header (or use `exposePort()`, which also returns a browser `url` carrying the token). File writes accept text or bytes (binary is sent exactly); `readBytes()` supports binary downloads.
|
|
111
130
|
|
|
112
131
|
## Current command and lifetime limits
|
|
113
132
|
|
|
114
|
-
Command results contain stdout, stderr, and the exit code. Command timeouts are limited to 1–600 seconds. The
|
|
133
|
+
Command results contain stdout, stderr, and the exit code. Command timeouts are limited to 1–600 seconds. The command options `envs`, `workdir` and `user` apply to that command; create-time `envs` apply to every command, and create-time `metadata` is returned by `getInfo()` / `get_info()`.
|
|
115
134
|
|
|
116
135
|
The SDK and CLI default to a five-minute lifetime. The raw API and dashboard default to no expiration. Set an explicit lifetime: `timeoutMs: 0` at creation disables expiration; a positive value sets a deadline. `setTimeout` accepts 1000–2147483647 ms, not zero. Commands do not reset the deadline. This is not an idle timer.
|
|
117
136
|
|
package/dist/index.d.mts
CHANGED
|
@@ -385,12 +385,19 @@ declare class GitHubAPI {
|
|
|
385
385
|
checkout(serviceId: string, branch: string): Promise<DeployHandle>;
|
|
386
386
|
}
|
|
387
387
|
|
|
388
|
-
/** A process this sandbox is currently running. */
|
|
388
|
+
/** A process this sandbox is currently running (one started through `exec`). */
|
|
389
389
|
interface ProcessInfo {
|
|
390
390
|
pid: number;
|
|
391
|
+
/** The argv: `['/bin/sh', '-c', 'npm test']` for a shell command. */
|
|
391
392
|
cmd: string[];
|
|
392
|
-
/**
|
|
393
|
-
|
|
393
|
+
/** `cmd` joined with spaces, for display. */
|
|
394
|
+
command?: string;
|
|
395
|
+
/** Working directory the process was started in, when known. */
|
|
396
|
+
cwd?: string | null;
|
|
397
|
+
/** The process's tag, when it was started with one. */
|
|
398
|
+
tag?: string | null;
|
|
399
|
+
/** When the process started, unix milliseconds. Not reported by every sandbox. */
|
|
400
|
+
startedAt?: number;
|
|
394
401
|
}
|
|
395
402
|
/** Signals accepted by {@link Process.kill}. */
|
|
396
403
|
type ProcessSignal = 'SIGTERM' | 'SIGKILL' | 'SIGINT' | 'SIGHUP' | 'SIGQUIT' | 'SIGUSR1' | 'SIGUSR2';
|
|
@@ -460,11 +467,6 @@ declare class Process {
|
|
|
460
467
|
* ```
|
|
461
468
|
*/
|
|
462
469
|
exec(cmd: string | string[], opts?: ProcessOpts): Promise<ProcessResult>;
|
|
463
|
-
/**
|
|
464
|
-
* Read an SSE exec stream, handing each line to the caller as it arrives while
|
|
465
|
-
* still accumulating the full result. Events are `{stream, line}` for output and
|
|
466
|
-
* `{exitCode}` at the end.
|
|
467
|
-
*/
|
|
468
470
|
/**
|
|
469
471
|
* List the processes this sandbox is currently running.
|
|
470
472
|
*
|
|
@@ -482,8 +484,8 @@ declare class Process {
|
|
|
482
484
|
/**
|
|
483
485
|
* Signal a running process. Defaults to `SIGTERM`.
|
|
484
486
|
*
|
|
485
|
-
* The signal goes to the process
|
|
486
|
-
* killing `sh -c 'sleep 100'` otherwise leaves the sleep running.
|
|
487
|
+
* The signal goes to the whole process tree, so a shell's children die with
|
|
488
|
+
* it — killing `sh -c 'sleep 100'` otherwise leaves the sleep running.
|
|
487
489
|
*
|
|
488
490
|
* The pid comes from {@link list}, or from the `pid` event at the start of a
|
|
489
491
|
* streaming `exec`.
|
|
@@ -495,6 +497,11 @@ declare class Process {
|
|
|
495
497
|
* ```
|
|
496
498
|
*/
|
|
497
499
|
kill(pid: number, signal?: ProcessSignal): Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* Read an SSE exec stream, handing each line to the caller as it arrives while
|
|
502
|
+
* still accumulating the full result. Events are `{pid}` first (when asked for
|
|
503
|
+
* with `pidEvent`), `{stream, line}` for output and `{exitCode}` at the end.
|
|
504
|
+
*/
|
|
498
505
|
private consumeStream;
|
|
499
506
|
}
|
|
500
507
|
|
|
@@ -514,10 +521,20 @@ interface FileInfo {
|
|
|
514
521
|
path: string;
|
|
515
522
|
type: 'file' | 'dir' | 'symlink';
|
|
516
523
|
size: number;
|
|
517
|
-
/** Permission bits as a
|
|
518
|
-
mode?:
|
|
519
|
-
/**
|
|
524
|
+
/** Permission bits as a number, e.g. `0o644` (420). */
|
|
525
|
+
mode?: number;
|
|
526
|
+
/** Permission bits as a string, e.g. `-rw-r--r--`. */
|
|
527
|
+
permissions?: string;
|
|
528
|
+
/** Owning user name. */
|
|
529
|
+
owner?: string;
|
|
530
|
+
/** Owning group name. */
|
|
531
|
+
group?: string;
|
|
532
|
+
/** Last modification time, unix milliseconds. */
|
|
520
533
|
modTime?: number;
|
|
534
|
+
/** Same as `modTime`, unix milliseconds. */
|
|
535
|
+
modifiedAt?: number;
|
|
536
|
+
/** Where a symlink points, for a symlink. */
|
|
537
|
+
symlinkTarget?: string;
|
|
521
538
|
}
|
|
522
539
|
/**
|
|
523
540
|
* Read and write files inside a Lizard sandbox.
|
|
@@ -531,25 +548,29 @@ declare class Fs {
|
|
|
531
548
|
/**
|
|
532
549
|
* Write a file into the sandbox filesystem.
|
|
533
550
|
*
|
|
534
|
-
* Creates parent directories automatically if they don't exist.
|
|
535
|
-
*
|
|
551
|
+
* Creates parent directories automatically if they don't exist. A string is
|
|
552
|
+
* written as UTF-8; bytes (`Uint8Array`, `Buffer` or `ArrayBuffer`) are written
|
|
553
|
+
* exactly as given, so binary files round-trip with {@link readBytes}.
|
|
554
|
+
*
|
|
555
|
+
* With `opts.user` the file is written as (and owned by) that user.
|
|
536
556
|
*
|
|
537
557
|
* @example
|
|
538
558
|
* ```ts
|
|
539
559
|
* await sandbox.fs.write('/app/index.js', 'console.log("hello")')
|
|
540
560
|
* ```
|
|
541
561
|
*
|
|
542
|
-
* @example Write
|
|
562
|
+
* @example Write binary data:
|
|
543
563
|
* ```ts
|
|
544
|
-
* await sandbox.fs.write('/app/
|
|
564
|
+
* await sandbox.fs.write('/app/logo.png', await readFile('logo.png'))
|
|
545
565
|
* ```
|
|
546
566
|
*/
|
|
547
|
-
write(path: string, data: string | Uint8Array, opts?: FsOpts): Promise<void>;
|
|
567
|
+
write(path: string, data: string | Uint8Array | ArrayBuffer, opts?: FsOpts): Promise<void>;
|
|
548
568
|
/**
|
|
549
569
|
* Read a file from the sandbox filesystem.
|
|
550
570
|
*
|
|
551
|
-
* @returns The file contents as a UTF-8 string.
|
|
571
|
+
* @returns The file contents as a UTF-8 string. Use {@link readBytes} for binary files.
|
|
552
572
|
*
|
|
573
|
+
* Throws `NotFoundError` if the path does not exist.
|
|
553
574
|
* @example
|
|
554
575
|
* ```ts
|
|
555
576
|
* const content = await sandbox.fs.read('/app/index.js')
|
|
@@ -587,9 +608,7 @@ declare class Fs {
|
|
|
587
608
|
* console.log(info.size, info.type)
|
|
588
609
|
* ```
|
|
589
610
|
*
|
|
590
|
-
* Throws `NotFoundError` if the path does not exist.
|
|
591
|
-
* this shipped run a guest agent without it and throw `LizardError` (501) —
|
|
592
|
-
* recreate the sandbox to use it.
|
|
611
|
+
* Throws `NotFoundError` if the path does not exist.
|
|
593
612
|
*/
|
|
594
613
|
stat(path: string, opts?: FsOpts): Promise<FileInfo>;
|
|
595
614
|
/**
|
|
@@ -599,9 +618,6 @@ declare class Fs {
|
|
|
599
618
|
* ```ts
|
|
600
619
|
* await sandbox.fs.move('/tmp/build.log', '/app/logs/build.log')
|
|
601
620
|
* ```
|
|
602
|
-
*
|
|
603
|
-
* Sandboxes created before this shipped run a guest agent without it and throw
|
|
604
|
-
* `LizardError` (501) — recreate the sandbox to use it.
|
|
605
621
|
*/
|
|
606
622
|
move(from: string, to: string): Promise<void>;
|
|
607
623
|
/**
|
|
@@ -623,8 +639,7 @@ declare class Fs {
|
|
|
623
639
|
* }, 1000)
|
|
624
640
|
* ```
|
|
625
641
|
*
|
|
626
|
-
*
|
|
627
|
-
* `LizardError` (501) — recreate the sandbox to use it.
|
|
642
|
+
* Not available on Firecracker sandboxes yet: the call throws `LizardError` (501).
|
|
628
643
|
*/
|
|
629
644
|
watch(path: string, opts?: {
|
|
630
645
|
recursive?: boolean;
|
|
@@ -710,7 +725,8 @@ declare class Desktop {
|
|
|
710
725
|
private readonly sandboxId;
|
|
711
726
|
private readonly config;
|
|
712
727
|
private readonly process;
|
|
713
|
-
|
|
728
|
+
private readonly fs;
|
|
729
|
+
constructor(sandboxId: string, config: ConnectionConfig, process: Process, fs: Fs);
|
|
714
730
|
private get client();
|
|
715
731
|
private get path();
|
|
716
732
|
/**
|
|
@@ -772,6 +788,8 @@ interface SandboxInfo {
|
|
|
772
788
|
/** Region the sandbox runs in — the volume's region when one is attached. */
|
|
773
789
|
region?: string;
|
|
774
790
|
status?: string;
|
|
791
|
+
/** The sandbox runtime: `'firecracker'` (a microVM), `'container'`, or `null` when unknown. */
|
|
792
|
+
runtime?: 'firecracker' | 'container' | null;
|
|
775
793
|
pauseError?: string | null;
|
|
776
794
|
/** Machine size (`'small' | 'medium' | 'large'`); may be `null` for a sandbox created from a private snapshot. */
|
|
777
795
|
size?: 'small' | 'medium' | 'large' | null;
|
|
@@ -781,6 +799,19 @@ interface SandboxInfo {
|
|
|
781
799
|
memoryMb?: number;
|
|
782
800
|
metadata?: Record<string, string>;
|
|
783
801
|
}
|
|
802
|
+
/** A sandbox port published on a public HTTPS hostname. See {@link Sandbox.exposePort}. */
|
|
803
|
+
interface ExposedPort {
|
|
804
|
+
/** Hostname without a scheme, e.g. `abc-3000.sandbox.eu-west-lim-a.onlizard.com`. */
|
|
805
|
+
hostname: string;
|
|
806
|
+
/** A browser URL that carries the access token (`?lizard_token=...`). */
|
|
807
|
+
url: string;
|
|
808
|
+
port: number;
|
|
809
|
+
/**
|
|
810
|
+
* The port is private: every request needs this token, either as the
|
|
811
|
+
* `X-Lizard-Access-Token` header or once as `?lizard_token=` (a browser then gets a cookie).
|
|
812
|
+
*/
|
|
813
|
+
accessToken: string;
|
|
814
|
+
}
|
|
784
815
|
interface SandboxOpts extends ConnectionOpts {
|
|
785
816
|
/**
|
|
786
817
|
* The project this sandbox belongs to — its ID, slug, or name. Required:
|
|
@@ -807,7 +838,9 @@ interface SandboxOpts extends ConnectionOpts {
|
|
|
807
838
|
* Measured CPU/RAM are not charged and egress is free. Ignored with {@link SandboxOpts.snapshotId}.
|
|
808
839
|
*/
|
|
809
840
|
size?: 'small' | 'medium' | 'large';
|
|
841
|
+
/** Your own key/value labels for the sandbox, returned by `getInfo()` and `list()`. */
|
|
810
842
|
metadata?: Record<string, string>;
|
|
843
|
+
/** Environment variables set in the sandbox, visible to every command it runs. */
|
|
811
844
|
envs?: Record<string, string>;
|
|
812
845
|
timeoutMs?: number;
|
|
813
846
|
/**
|
|
@@ -867,10 +900,7 @@ declare class SandboxClient {
|
|
|
867
900
|
}): Promise<SandboxInfo[]>;
|
|
868
901
|
protected static getSandboxInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
|
|
869
902
|
protected static setTimeoutSandbox(sandboxId: string, timeoutMs: number, opts?: ConnectionOpts): Promise<void>;
|
|
870
|
-
protected static exposeSandboxPort(sandboxId: string, port: number, opts?: ConnectionOpts): Promise<
|
|
871
|
-
hostname: string;
|
|
872
|
-
url: string;
|
|
873
|
-
}>;
|
|
903
|
+
protected static exposeSandboxPort(sandboxId: string, port: number, opts?: ConnectionOpts): Promise<ExposedPort>;
|
|
874
904
|
}
|
|
875
905
|
|
|
876
906
|
interface SandboxSnapshot {
|
|
@@ -886,18 +916,37 @@ interface SandboxSnapshot {
|
|
|
886
916
|
error: string | null;
|
|
887
917
|
cpus: number;
|
|
888
918
|
memoryMb: number;
|
|
919
|
+
/** Unix milliseconds. */
|
|
889
920
|
createdAt: number;
|
|
890
921
|
}
|
|
891
922
|
interface SnapshotOpts {
|
|
923
|
+
/** Warm copies to keep ready (container sandboxes only; ignored for Firecracker, whose snapshots restore from disk). */
|
|
892
924
|
poolSize?: number;
|
|
893
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* One entry of {@link Sandbox.fork}'s result: the new sandbox, or why that copy
|
|
928
|
+
* could not be made (e.g. the account's sandbox limit).
|
|
929
|
+
*/
|
|
930
|
+
type ForkResult<S extends Sandbox = Sandbox> = {
|
|
931
|
+
sandbox: S;
|
|
932
|
+
info: SandboxInfo;
|
|
933
|
+
error?: undefined;
|
|
934
|
+
} | {
|
|
935
|
+
sandbox?: undefined;
|
|
936
|
+
info?: undefined;
|
|
937
|
+
error: string;
|
|
938
|
+
};
|
|
894
939
|
interface SnapshotWaitOpts extends ConnectionOpts {
|
|
895
940
|
waitTimeoutMs?: number;
|
|
896
941
|
}
|
|
897
942
|
/**
|
|
898
|
-
* A Linux sandbox
|
|
943
|
+
* A Linux sandbox: a Firecracker microVM with its own kernel.
|
|
899
944
|
*
|
|
900
|
-
* Run commands, read and write files, and expose HTTP ports in a sandbox.
|
|
945
|
+
* Run commands, read and write files, and expose HTTP ports in a sandbox. A
|
|
946
|
+
* sandbox boots in well under a second; {@link pause} and {@link resume} keep its
|
|
947
|
+
* memory and running processes, {@link snapshot} saves it in about 2 s and
|
|
948
|
+
* {@link restore} starts a copy in about 0.4 s, and {@link fork} clones a running
|
|
949
|
+
* sandbox, processes and all.
|
|
901
950
|
*
|
|
902
951
|
* Sandboxes are **ephemeral**: killing one, or letting it hit its timeout, discards
|
|
903
952
|
* everything written inside it. State that has to outlive a sandbox belongs on a
|
|
@@ -989,8 +1038,9 @@ declare class Sandbox extends SandboxClient {
|
|
|
989
1038
|
* Create a new Lizard sandbox from the specified template.
|
|
990
1039
|
*
|
|
991
1040
|
* Template availability and installed tools depend on the platform and region.
|
|
992
|
-
* Use `base` for shell commands
|
|
993
|
-
*
|
|
1041
|
+
* Use `base` for shell commands, `interpreter` for Python with the data stack
|
|
1042
|
+
* (use {@link CodeSandbox} to run code snippets in it), or `desktop` for a
|
|
1043
|
+
* graphical desktop.
|
|
994
1044
|
*
|
|
995
1045
|
* @param template Name of the sandbox template to boot from.
|
|
996
1046
|
*
|
|
@@ -1032,9 +1082,15 @@ declare class Sandbox extends SandboxClient {
|
|
|
1032
1082
|
* @returns `true` if the sandbox was terminated, `false` if it was already gone.
|
|
1033
1083
|
*/
|
|
1034
1084
|
kill(opts?: ConnectionOpts): Promise<boolean>;
|
|
1035
|
-
/**
|
|
1085
|
+
/**
|
|
1086
|
+
* Pause the sandbox: its memory, running processes and files are kept and
|
|
1087
|
+
* compute stops. Wait with `waitForStatus('paused')` before resuming.
|
|
1088
|
+
*/
|
|
1036
1089
|
pause(opts?: ConnectionOpts): Promise<boolean>;
|
|
1037
|
-
/**
|
|
1090
|
+
/**
|
|
1091
|
+
* Resume a paused sandbox exactly where it stopped, processes included. Wait
|
|
1092
|
+
* with `waitForStatus('running')` before running commands.
|
|
1093
|
+
*/
|
|
1038
1094
|
resume(opts?: ConnectionOpts): Promise<boolean>;
|
|
1039
1095
|
/** Wait for an asynchronous pause/resume operation to finish. */
|
|
1040
1096
|
waitForStatus(status: 'paused' | 'running', opts?: SnapshotWaitOpts): Promise<SandboxInfo>;
|
|
@@ -1049,39 +1105,81 @@ declare class Sandbox extends SandboxClient {
|
|
|
1049
1105
|
*/
|
|
1050
1106
|
setTimeout(timeoutMs: number, opts?: ConnectionOpts): Promise<void>;
|
|
1051
1107
|
/**
|
|
1052
|
-
*
|
|
1108
|
+
* The token that opens this sandbox's published ports. Set by {@link getHost}
|
|
1109
|
+
* and {@link exposePort}; send it as the `X-Lizard-Access-Token` header.
|
|
1110
|
+
*/
|
|
1111
|
+
accessToken?: string;
|
|
1112
|
+
/**
|
|
1113
|
+
* Publish a port on a public HTTPS hostname and return the hostname without a scheme.
|
|
1053
1114
|
*
|
|
1054
|
-
*
|
|
1055
|
-
*
|
|
1115
|
+
* The port is private: requests need {@link accessToken} (set by this call) as
|
|
1116
|
+
* the `X-Lizard-Access-Token` header, or `?lizard_token=<token>` in a browser.
|
|
1117
|
+
* {@link exposePort} returns the token and a ready-made browser URL together.
|
|
1056
1118
|
*
|
|
1057
1119
|
* @example
|
|
1058
1120
|
* ```ts
|
|
1059
1121
|
* // Start an HTTP server on port 3000 before exposing it.
|
|
1060
1122
|
* const hostname = await sandbox.getHost(3000)
|
|
1061
|
-
*
|
|
1123
|
+
* const res = await fetch(`https://${hostname}/`, {
|
|
1124
|
+
* headers: { 'X-Lizard-Access-Token': sandbox.accessToken! },
|
|
1125
|
+
* })
|
|
1062
1126
|
* ```
|
|
1063
1127
|
*/
|
|
1064
1128
|
getHost(port: number, opts?: ConnectionOpts): Promise<string>;
|
|
1065
|
-
/**
|
|
1129
|
+
/**
|
|
1130
|
+
* Publish a port and return everything needed to reach it: the hostname, a
|
|
1131
|
+
* browser `url` that carries the token, and the `accessToken` for API clients.
|
|
1132
|
+
*
|
|
1133
|
+
* @example
|
|
1134
|
+
* ```ts
|
|
1135
|
+
* const { url, hostname, accessToken } = await sandbox.exposePort(3000)
|
|
1136
|
+
* console.log(url) // open in a browser
|
|
1137
|
+
* await fetch(`https://${hostname}/api`, { headers: { 'X-Lizard-Access-Token': accessToken } })
|
|
1138
|
+
* ```
|
|
1139
|
+
*/
|
|
1140
|
+
exposePort(port: number, opts?: ConnectionOpts): Promise<ExposedPort>;
|
|
1141
|
+
/**
|
|
1142
|
+
* Clone this running sandbox `count` times (1-10). Each fork is a copy of the
|
|
1143
|
+
* microVM at this instant -- memory, running processes and files -- and is
|
|
1144
|
+
* billed like its source. The source keeps running.
|
|
1145
|
+
*
|
|
1146
|
+
* Returns one entry per requested fork, in order: `{ sandbox, info }`, or
|
|
1147
|
+
* `{ error }` for a copy that could not be made (e.g. the account's sandbox
|
|
1148
|
+
* limit). A sandbox with a volume attached cannot be forked (`ConflictError`, 409).
|
|
1149
|
+
*
|
|
1150
|
+
* @param opts.timeoutMs Lifetime of each fork; defaults to the source's timeout.
|
|
1151
|
+
*
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```ts
|
|
1154
|
+
* const forks = await sandbox.fork({ count: 2 })
|
|
1155
|
+
* for (const f of forks) if (f.sandbox) await f.sandbox.process.exec('echo hi')
|
|
1156
|
+
* ```
|
|
1157
|
+
*/
|
|
1066
1158
|
fork(opts?: {
|
|
1067
1159
|
count?: number;
|
|
1068
1160
|
timeoutMs?: number;
|
|
1069
|
-
}): Promise<
|
|
1070
|
-
/**
|
|
1161
|
+
}): Promise<ForkResult<this>[]>;
|
|
1162
|
+
/**
|
|
1163
|
+
* Save this sandbox -- memory, running processes and files -- as a private
|
|
1164
|
+
* snapshot. A Firecracker snapshot is `ready` as soon as this returns (about 2 s);
|
|
1165
|
+
* start copies of it with {@link Sandbox.restore} (about 0.4 s each). The source
|
|
1166
|
+
* keeps running. `poolSize` applies to container sandboxes only.
|
|
1167
|
+
*/
|
|
1071
1168
|
snapshot(name?: string, opts?: SnapshotOpts): Promise<SandboxSnapshot>;
|
|
1072
1169
|
unexpose(port: number): Promise<void>;
|
|
1170
|
+
/** Stream the sandbox's logs. Not available on Firecracker sandboxes yet (`LizardError`, 501). */
|
|
1073
1171
|
logs(opts?: {
|
|
1074
1172
|
tail?: number;
|
|
1075
1173
|
signal?: AbortSignal;
|
|
1076
1174
|
}): AsyncGenerator<StreamEvent, any, any>;
|
|
1077
1175
|
static snapshots(projectId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot[]>;
|
|
1078
1176
|
static getSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
1079
|
-
/** Start a sandbox from
|
|
1177
|
+
/** Start a new sandbox from a snapshot, in the snapshot's project and region. */
|
|
1080
1178
|
static restore(snapshotId: string, opts?: ConnectionOpts & {
|
|
1081
1179
|
timeoutMs?: number;
|
|
1082
1180
|
}): Promise<Sandbox>;
|
|
1083
1181
|
static setSnapshotWarmPool(snapshotId: string, poolSize: number, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
1084
|
-
/** Release idle warm copies; retain saved state and existing claimed sandboxes. */
|
|
1182
|
+
/** Release idle warm copies (container snapshots); retain saved state and existing claimed sandboxes. */
|
|
1085
1183
|
static pauseSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
1086
1184
|
/** Refill the configured warm pool without another capture. */
|
|
1087
1185
|
static resumeSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
|
|
@@ -1526,8 +1624,10 @@ interface VolumeInfo {
|
|
|
1526
1624
|
/** Region the volume's node lives in. A sandbox mounting it runs here too. */
|
|
1527
1625
|
region?: string;
|
|
1528
1626
|
status: string;
|
|
1627
|
+
/** Id of the sandbox the volume is attached to, or `null` when it is free. */
|
|
1529
1628
|
attachedTo?: string | null;
|
|
1530
|
-
|
|
1629
|
+
/** Creation time: an ISO-8601 string for Firecracker volumes, unix milliseconds for container volumes. */
|
|
1630
|
+
createdAt: string | number;
|
|
1531
1631
|
/**
|
|
1532
1632
|
* Whether `sizeGb` is actually enforced as a hard limit on the volume's node.
|
|
1533
1633
|
* Returned by {@link Volume.resize}; `false` means the size was recorded but the
|
|
@@ -1536,7 +1636,7 @@ interface VolumeInfo {
|
|
|
1536
1636
|
sizeEnforced?: boolean;
|
|
1537
1637
|
}
|
|
1538
1638
|
interface CreateVolumeOpts extends ConnectionOpts {
|
|
1539
|
-
/** Whole GB, default 5. New volumes allow 1–50 GB unless the server config sets another maximum. Creating never changes an existing volume's size
|
|
1639
|
+
/** Whole GB, default 5. New volumes allow 1–50 GB unless the server config sets another maximum. Creating never changes an existing volume's size. */
|
|
1540
1640
|
sizeGb?: number;
|
|
1541
1641
|
/**
|
|
1542
1642
|
* Region to place the volume in, e.g. `'us-east-1'`. A volume is node-local, so
|
|
@@ -1559,7 +1659,9 @@ interface CreateVolumeOpts extends ConnectionOpts {
|
|
|
1559
1659
|
* Names are slugs: lowercase letters, digits and dashes, starting and ending with a
|
|
1560
1660
|
* letter or digit, up to 64 characters.
|
|
1561
1661
|
*
|
|
1562
|
-
* Mount one to a sandbox via `Sandbox.create({ volumeName: 'my-data' })
|
|
1662
|
+
* Mount one to a sandbox via `Sandbox.create({ volumeName: 'my-data' })`; it appears
|
|
1663
|
+
* at `/workspace`. A volume is attached to one sandbox at a time (`attachedTo`), and
|
|
1664
|
+
* a sandbox with a volume attached cannot be forked.
|
|
1563
1665
|
*/
|
|
1564
1666
|
declare class Volume {
|
|
1565
1667
|
/** The volume's generated id. Stable, but you rarely need it — address by name. */
|
|
@@ -1582,7 +1684,7 @@ declare class Volume {
|
|
|
1582
1684
|
* "the scratch disk for this task" no longer has to store an id between runs.
|
|
1583
1685
|
*
|
|
1584
1686
|
* An existing volume is returned as-is — `sizeGb` applies only to a fresh create,
|
|
1585
|
-
* so an existing volume keeps its size.
|
|
1687
|
+
* so an existing volume keeps its size.
|
|
1586
1688
|
*/
|
|
1587
1689
|
static getOrCreate(projectId: string, name: string, opts?: CreateVolumeOpts): Promise<Volume>;
|
|
1588
1690
|
/** Look a volume up by name or by id. */
|
|
@@ -1593,11 +1695,15 @@ declare class Volume {
|
|
|
1593
1695
|
/**
|
|
1594
1696
|
* Resize a volume, by name or by id, to `sizeGb`.
|
|
1595
1697
|
*
|
|
1596
|
-
*
|
|
1597
|
-
*
|
|
1598
|
-
*
|
|
1599
|
-
*
|
|
1600
|
-
*
|
|
1698
|
+
* **Firecracker volumes cannot be resized yet**: volumes created for the default
|
|
1699
|
+
* Firecracker sandboxes throw `LizardError` (400) with `code: 'volume_not_resizable'`.
|
|
1700
|
+
* Create the volume at the size you need, or copy the data to a new, larger one.
|
|
1701
|
+
*
|
|
1702
|
+
* On a container volume the change is in place and online: the size is a quota,
|
|
1703
|
+
* so no data is copied and a mounted sandbox sees the new size immediately. Both
|
|
1704
|
+
* growing and shrinking are allowed, but a shrink must leave at least 10% of the
|
|
1705
|
+
* new size free — otherwise it throws `ConflictError` with
|
|
1706
|
+
* `code: 'volume_too_full_to_shrink'`.
|
|
1601
1707
|
*
|
|
1602
1708
|
* Other failures carry a `code` too: `invalid_volume_size`, `volume_not_resizable`,
|
|
1603
1709
|
* `volume_resize_in_progress`, `volume_not_provisioned`,
|
|
@@ -1608,7 +1714,7 @@ declare class Volume {
|
|
|
1608
1714
|
*/
|
|
1609
1715
|
static resize(projectId: string, nameOrId: string, sizeGb: number, opts?: ConnectionOpts): Promise<VolumeInfo>;
|
|
1610
1716
|
getInfo(projectId: string): Promise<VolumeInfo>;
|
|
1611
|
-
/** Resize this volume
|
|
1717
|
+
/** Resize this volume — see the static {@link Volume.resize} (not supported for Firecracker volumes yet). */
|
|
1612
1718
|
resize(projectId: string, sizeGb: number): Promise<VolumeInfo>;
|
|
1613
1719
|
delete(projectId: string): Promise<void>;
|
|
1614
1720
|
}
|
|
@@ -1826,7 +1932,7 @@ declare class Execution {
|
|
|
1826
1932
|
results: OutputItem[];
|
|
1827
1933
|
/** Execution error if the code threw an exception. */
|
|
1828
1934
|
error?: ExecutionError;
|
|
1829
|
-
/** Monotonically increasing counter for this context. */
|
|
1935
|
+
/** Monotonically increasing counter for this context (the Python kernel's `In[n]`). */
|
|
1830
1936
|
executionCount: number;
|
|
1831
1937
|
get success(): boolean;
|
|
1832
1938
|
get text(): string;
|
|
@@ -1841,11 +1947,15 @@ type RunCodeLanguage = 'python' | 'javascript' | 'bash' | (string & Record<never
|
|
|
1841
1947
|
interface RunCodeOpts {
|
|
1842
1948
|
/** Language to run in. Defaults to python. */
|
|
1843
1949
|
language?: RunCodeLanguage;
|
|
1844
|
-
/** Use a specific context instead of the per-language default. */
|
|
1950
|
+
/** Use a specific context (from `createContext`) instead of the per-language default. */
|
|
1845
1951
|
context?: CodeContext;
|
|
1846
1952
|
/** Extra environment variables available to the code. */
|
|
1847
1953
|
envs?: Record<string, string>;
|
|
1848
|
-
/**
|
|
1954
|
+
/**
|
|
1955
|
+
* Execution timeout in milliseconds, default 60 000. A Python kernel that runs
|
|
1956
|
+
* past it is interrupted (its state is kept) and `execution.error.name` is
|
|
1957
|
+
* `'TimeoutError'`; a process is killed.
|
|
1958
|
+
*/
|
|
1849
1959
|
timeoutMs?: number;
|
|
1850
1960
|
onStdout?: (data: string) => void;
|
|
1851
1961
|
onStderr?: (data: string) => void;
|
|
@@ -1858,31 +1968,47 @@ interface CreateContextOpts {
|
|
|
1858
1968
|
}
|
|
1859
1969
|
|
|
1860
1970
|
/**
|
|
1861
|
-
*
|
|
1971
|
+
* A sandbox for running code snippets, built on {@link Sandbox.process}.
|
|
1862
1972
|
*
|
|
1863
|
-
*
|
|
1864
|
-
*
|
|
1865
|
-
*
|
|
1866
|
-
*
|
|
1973
|
+
* Boots the `interpreter` template by default. Python runs in a persistent
|
|
1974
|
+
* Jupyter kernel per context, so variables, imports and functions carry over
|
|
1975
|
+
* between calls, `execution.results` holds rich output (the value of the last
|
|
1976
|
+
* expression, matplotlib charts as `image/png`, HTML, ...) and errors carry
|
|
1977
|
+
* the exception name and traceback.
|
|
1867
1978
|
*
|
|
1868
|
-
*
|
|
1979
|
+
* Limits, honestly:
|
|
1980
|
+
* - `javascript` (node) and `bash` run each call as a fresh process: no state
|
|
1981
|
+
* carries over and `results` stays empty. `node` must be installed in the
|
|
1982
|
+
* template; the `interpreter` template does not ship it.
|
|
1983
|
+
* - On a template without Jupyter (e.g. `base`), Python also runs as a fresh
|
|
1984
|
+
* process per call.
|
|
1985
|
+
* - `stdout`/`stderr` are delivered in the chunks the kernel or process
|
|
1986
|
+
* produced them, not per character.
|
|
1987
|
+
*
|
|
1988
|
+
* Kernels live inside the sandbox's microVM, so pause/resume, snapshots and
|
|
1989
|
+
* forks keep their state.
|
|
1990
|
+
*
|
|
1991
|
+
* @example
|
|
1992
|
+
* ```ts
|
|
1993
|
+
* const sandbox = await CodeSandbox.create({ project: 'my-project' })
|
|
1994
|
+
* await sandbox.runCode('x = 21')
|
|
1995
|
+
* const run = await sandbox.runCode('x * 2')
|
|
1996
|
+
* console.log(run.results[0].data) // "42"
|
|
1997
|
+
* await sandbox.kill()
|
|
1998
|
+
* ```
|
|
1869
1999
|
*/
|
|
1870
2000
|
declare class CodeSandbox extends Sandbox {
|
|
1871
|
-
protected static readonly defaultTemplate
|
|
1872
|
-
private get serverUrl();
|
|
2001
|
+
protected static readonly defaultTemplate: string;
|
|
1873
2002
|
/**
|
|
1874
|
-
* Execute code
|
|
2003
|
+
* Execute code and wait for it to finish.
|
|
1875
2004
|
*
|
|
1876
|
-
*
|
|
1877
|
-
*
|
|
2005
|
+
* Python keeps its state per context (the default context, per language,
|
|
2006
|
+
* when none is given). Code errors appear in `execution.error`; request
|
|
2007
|
+
* failures throw.
|
|
1878
2008
|
*
|
|
1879
2009
|
* @param code Source code to run.
|
|
1880
2010
|
* @param opts Language, context, env vars, timeout, and streaming callbacks.
|
|
1881
2011
|
*
|
|
1882
|
-
* @returns Execution result with stdout, stderr, results, and any error.
|
|
1883
|
-
*
|
|
1884
|
-
* Code errors appear in `execution.error`; request failures throw.
|
|
1885
|
-
*
|
|
1886
2012
|
* @example
|
|
1887
2013
|
* ```ts
|
|
1888
2014
|
* const result = await sandbox.runCode(`
|
|
@@ -1896,8 +2022,8 @@ declare class CodeSandbox extends Sandbox {
|
|
|
1896
2022
|
/**
|
|
1897
2023
|
* Create a new isolated execution context.
|
|
1898
2024
|
*
|
|
1899
|
-
*
|
|
1900
|
-
*
|
|
2025
|
+
* A Python context is its own kernel: its own variables, and `cwd` as its
|
|
2026
|
+
* working directory. Other languages get the working directory only.
|
|
1901
2027
|
*
|
|
1902
2028
|
* @example
|
|
1903
2029
|
* ```ts
|
|
@@ -1907,18 +2033,14 @@ declare class CodeSandbox extends Sandbox {
|
|
|
1907
2033
|
* ```
|
|
1908
2034
|
*/
|
|
1909
2035
|
createContext(opts?: CreateContextOpts): Promise<CodeContext>;
|
|
1910
|
-
/**
|
|
1911
|
-
* List all active execution contexts in this sandbox.
|
|
1912
|
-
*/
|
|
2036
|
+
/** List the contexts created with {@link createContext} in this sandbox. */
|
|
1913
2037
|
listContexts(): Promise<CodeContext[]>;
|
|
1914
|
-
/**
|
|
1915
|
-
* Delete an execution context and free its resources.
|
|
1916
|
-
*/
|
|
2038
|
+
/** Delete an execution context, stopping its kernel. */
|
|
1917
2039
|
deleteContext(context: CodeContext | string): Promise<void>;
|
|
1918
|
-
/**
|
|
1919
|
-
* Restart a context, clearing all variables and state.
|
|
1920
|
-
*/
|
|
2040
|
+
/** Restart a context, clearing all variables and state. */
|
|
1921
2041
|
restartContext(context: CodeContext | string): Promise<void>;
|
|
2042
|
+
/** Run the in-sandbox runner with `args` and hand each of its events to `onEvent`. */
|
|
2043
|
+
private runner;
|
|
1922
2044
|
static create(opts?: SandboxOpts): Promise<CodeSandbox>;
|
|
1923
2045
|
static create(template: string, opts?: SandboxOpts): Promise<CodeSandbox>;
|
|
1924
2046
|
static connect(sandboxId: string, opts?: ConnectionOpts): Promise<CodeSandbox>;
|
|
@@ -1948,4 +2070,4 @@ declare class LizardCLI {
|
|
|
1948
2070
|
}): Promise<CLIResult>;
|
|
1949
2071
|
}
|
|
1950
2072
|
|
|
1951
|
-
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type ClickOpts, 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, Desktop, type DesktopInfo, type DesktopStartOpts, 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, type MouseButton, 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 ScrollDirection, 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 };
|
|
2073
|
+
export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type ClickOpts, 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, Desktop, type DesktopInfo, type DesktopStartOpts, type DomainInfo, type DomainStatus, DomainsAPI, Execution, ExecutionError, type ExposedPort, type FileInfo, type ForkResult, type FsEvent, type FsOpts, GitHubAPI, type ListTransactionsOpts, Lizard, LizardCLI, LizardError, type LizardOpts, type LogLine, type MetricPoint, type MetricRange, MetricsAPI, type MouseButton, NotFoundError, PlatformClient, type ProcessInfo, type ProcessOpts, type ProcessResult, type ProcessSignal, 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 ScrollDirection, 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 };
|