@lizard-build/sdk 0.1.49 → 0.1.52

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/index.d.ts 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
- /** When the process started, unix milliseconds. */
393
- startedAt: number;
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 group, so a shell's children die with it —
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 string, e.g. `-rw-r--r--`. Absent on older sandboxes. */
518
- mode?: string;
519
- /** Last modification time, unix milliseconds. Absent on older sandboxes. */
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
- * Byte input must contain valid UTF-8; arbitrary binary uploads are unsupported.
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 UTF-8 bytes:
562
+ * @example Write binary data:
543
563
  * ```ts
544
- * await sandbox.fs.write('/app/notes.txt', new TextEncoder().encode('hello'))
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. Sandboxes created before
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
- * Sandboxes created before this shipped run a guest agent without it and throw
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;
@@ -773,6 +788,8 @@ interface SandboxInfo {
773
788
  /** Region the sandbox runs in — the volume's region when one is attached. */
774
789
  region?: string;
775
790
  status?: string;
791
+ /** The sandbox runtime: `'firecracker'` (a microVM), `'container'`, or `null` when unknown. */
792
+ runtime?: 'firecracker' | 'container' | null;
776
793
  pauseError?: string | null;
777
794
  /** Machine size (`'small' | 'medium' | 'large'`); may be `null` for a sandbox created from a private snapshot. */
778
795
  size?: 'small' | 'medium' | 'large' | null;
@@ -782,6 +799,19 @@ interface SandboxInfo {
782
799
  memoryMb?: number;
783
800
  metadata?: Record<string, string>;
784
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
+ }
785
815
  interface SandboxOpts extends ConnectionOpts {
786
816
  /**
787
817
  * The project this sandbox belongs to — its ID, slug, or name. Required:
@@ -808,7 +838,9 @@ interface SandboxOpts extends ConnectionOpts {
808
838
  * Measured CPU/RAM are not charged and egress is free. Ignored with {@link SandboxOpts.snapshotId}.
809
839
  */
810
840
  size?: 'small' | 'medium' | 'large';
841
+ /** Your own key/value labels for the sandbox, returned by `getInfo()` and `list()`. */
811
842
  metadata?: Record<string, string>;
843
+ /** Environment variables set in the sandbox, visible to every command it runs. */
812
844
  envs?: Record<string, string>;
813
845
  timeoutMs?: number;
814
846
  /**
@@ -868,10 +900,7 @@ declare class SandboxClient {
868
900
  }): Promise<SandboxInfo[]>;
869
901
  protected static getSandboxInfo(sandboxId: string, opts?: ConnectionOpts): Promise<SandboxInfo>;
870
902
  protected static setTimeoutSandbox(sandboxId: string, timeoutMs: number, opts?: ConnectionOpts): Promise<void>;
871
- protected static exposeSandboxPort(sandboxId: string, port: number, opts?: ConnectionOpts): Promise<{
872
- hostname: string;
873
- url: string;
874
- }>;
903
+ protected static exposeSandboxPort(sandboxId: string, port: number, opts?: ConnectionOpts): Promise<ExposedPort>;
875
904
  }
876
905
 
877
906
  interface SandboxSnapshot {
@@ -887,18 +916,37 @@ interface SandboxSnapshot {
887
916
  error: string | null;
888
917
  cpus: number;
889
918
  memoryMb: number;
919
+ /** Unix milliseconds. */
890
920
  createdAt: number;
891
921
  }
892
922
  interface SnapshotOpts {
923
+ /** Warm copies to keep ready (container sandboxes only; ignored for Firecracker, whose snapshots restore from disk). */
893
924
  poolSize?: number;
894
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
+ };
895
939
  interface SnapshotWaitOpts extends ConnectionOpts {
896
940
  waitTimeoutMs?: number;
897
941
  }
898
942
  /**
899
- * A Linux sandbox running on Kubernetes.
943
+ * A Linux sandbox: a Firecracker microVM with its own kernel.
900
944
  *
901
- * 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.
902
950
  *
903
951
  * Sandboxes are **ephemeral**: killing one, or letting it hit its timeout, discards
904
952
  * everything written inside it. State that has to outlive a sandbox belongs on a
@@ -990,8 +1038,9 @@ declare class Sandbox extends SandboxClient {
990
1038
  * Create a new Lizard sandbox from the specified template.
991
1039
  *
992
1040
  * Template availability and installed tools depend on the platform and region.
993
- * Use `base` for shell commands or `interpreter` for Python process commands.
994
- * Hosted templates do not support the legacy `CodeSandbox` execution API.
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.
995
1044
  *
996
1045
  * @param template Name of the sandbox template to boot from.
997
1046
  *
@@ -1033,9 +1082,15 @@ declare class Sandbox extends SandboxClient {
1033
1082
  * @returns `true` if the sandbox was terminated, `false` if it was already gone.
1034
1083
  */
1035
1084
  kill(opts?: ConnectionOpts): Promise<boolean>;
1036
- /** Queue a CRIU checkpoint and stop compute. Use waitForStatus('paused') before resuming. */
1085
+ /**
1086
+ * Pause the sandbox: its memory, running processes and files are kept and
1087
+ * compute stops. Wait with `waitForStatus('paused')` before resuming.
1088
+ */
1037
1089
  pause(opts?: ConnectionOpts): Promise<boolean>;
1038
- /** Queue restoration of saved memory and files. Use waitForStatus('running') before executing. */
1090
+ /**
1091
+ * Resume a paused sandbox exactly where it stopped, processes included. Wait
1092
+ * with `waitForStatus('running')` before running commands.
1093
+ */
1039
1094
  resume(opts?: ConnectionOpts): Promise<boolean>;
1040
1095
  /** Wait for an asynchronous pause/resume operation to finish. */
1041
1096
  waitForStatus(status: 'paused' | 'running', opts?: SnapshotWaitOpts): Promise<SandboxInfo>;
@@ -1050,39 +1105,81 @@ declare class Sandbox extends SandboxClient {
1050
1105
  */
1051
1106
  setTimeout(timeoutMs: number, opts?: ConnectionOpts): Promise<void>;
1052
1107
  /**
1053
- * Register a public HTTPS route and return its hostname without a scheme.
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.
1054
1114
  *
1055
- * Useful for accessing HTTP servers started inside the sandbox from your
1056
- * agent or tests without additional tunneling.
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.
1057
1118
  *
1058
1119
  * @example
1059
1120
  * ```ts
1060
1121
  * // Start an HTTP server on port 3000 before exposing it.
1061
1122
  * const hostname = await sandbox.getHost(3000)
1062
- * console.log(`https://${hostname}`)
1123
+ * const res = await fetch(`https://${hostname}/`, {
1124
+ * headers: { 'X-Lizard-Access-Token': sandbox.accessToken! },
1125
+ * })
1063
1126
  * ```
1064
1127
  */
1065
1128
  getHost(port: number, opts?: ConnectionOpts): Promise<string>;
1066
- /** Fork is unsupported on Kubernetes; the backend returns HTTP 501. */
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
+ */
1067
1158
  fork(opts?: {
1068
1159
  count?: number;
1069
1160
  timeoutMs?: number;
1070
- }): Promise<unknown>;
1071
- /** Capture memory and workspace files. Disconnect active clients before capturing. */
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
+ */
1072
1168
  snapshot(name?: string, opts?: SnapshotOpts): Promise<SandboxSnapshot>;
1073
1169
  unexpose(port: number): Promise<void>;
1170
+ /** Stream the sandbox's logs. Not available on Firecracker sandboxes yet (`LizardError`, 501). */
1074
1171
  logs(opts?: {
1075
1172
  tail?: number;
1076
1173
  signal?: AbortSignal;
1077
1174
  }): AsyncGenerator<StreamEvent, any, any>;
1078
1175
  static snapshots(projectId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot[]>;
1079
1176
  static getSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
1080
- /** Start a sandbox from an available warm copy in the snapshot's project and region. */
1177
+ /** Start a new sandbox from a snapshot, in the snapshot's project and region. */
1081
1178
  static restore(snapshotId: string, opts?: ConnectionOpts & {
1082
1179
  timeoutMs?: number;
1083
1180
  }): Promise<Sandbox>;
1084
1181
  static setSnapshotWarmPool(snapshotId: string, poolSize: number, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
1085
- /** 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. */
1086
1183
  static pauseSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
1087
1184
  /** Refill the configured warm pool without another capture. */
1088
1185
  static resumeSnapshot(snapshotId: string, opts?: ConnectionOpts): Promise<SandboxSnapshot>;
@@ -1423,6 +1520,7 @@ declare class RegionsAPI {
1423
1520
  list(): Promise<Region[]>;
1424
1521
  }
1425
1522
 
1523
+ /** Prepaid credits balance: old credits accounts (`plan: 'payg'`) until 1 November 2026, and enterprise usage. */
1426
1524
  interface Balance {
1427
1525
  plan: string;
1428
1526
  status: 'active' | 'grace' | 'frozen' | string;
@@ -1461,61 +1559,180 @@ interface ListTransactionsOpts {
1461
1559
  includeUsage?: boolean;
1462
1560
  }
1463
1561
  /**
1464
- * Account balance and usage.
1562
+ * `none`: no plan yet (creating anything answers 402). `pro`: the Pro subscription, see
1563
+ * {@link Subscription.status}. `payg`: old prepaid credits, until 1 November 2026.
1564
+ * `enterprise`: pay as you go, invoiced monthly.
1565
+ */
1566
+ type Plan = 'none' | 'pro' | 'payg' | 'enterprise';
1567
+ /** Pro subscription status; `none` when there is no subscription. */
1568
+ type SubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'none';
1569
+ interface Subscription {
1570
+ plan: Plan | (string & {});
1571
+ status: SubscriptionStatus | (string & {});
1572
+ /** False when read for a workspace the caller does not own; card and invoice fields are then null. */
1573
+ isOwner: boolean;
1574
+ /** 1900: $19/month. */
1575
+ priceCents: number;
1576
+ /** The price includes taxes. */
1577
+ taxIncluded: boolean;
1578
+ /** Credits included each paid month, in cents (1900). */
1579
+ includedCents: number;
1580
+ trial: {
1581
+ /** The account can start a trial now. */
1582
+ eligible: boolean;
1583
+ /** Trial length it would get, or got. */
1584
+ days: number | null;
1585
+ /** Trial credits, in cents. */
1586
+ creditCents: number | null;
1587
+ /** Promo code held for the trial, if any. */
1588
+ promoCode: string | null;
1589
+ /** Trial end (ms); null when not trialing. */
1590
+ endsAt: number | null;
1591
+ /** Trial credits used (trialing only). */
1592
+ usedCents: number | null;
1593
+ remainingCents: number | null;
1594
+ };
1595
+ /** The current Pro period; null when there is none. */
1596
+ period: {
1597
+ kind: 'trial' | 'paid';
1598
+ start: number;
1599
+ end: number;
1600
+ /** 500 in the trial, 1900 in a paid month. */
1601
+ includedCents: number;
1602
+ usedCents: number;
1603
+ /** Paid month: usage above the included credits. */
1604
+ overageCents: number;
1605
+ /** Of the overage, already invoiced. */
1606
+ billedOverageCents: number;
1607
+ unbilledOverageCents: number;
1608
+ /** Paid month: unbilled overage at which the next invoice goes out. */
1609
+ nextOverageChargeAtCents: number | null;
1610
+ } | null;
1611
+ /** Null when there is none, or the subscription is cancelling. */
1612
+ nextCharge: {
1613
+ at: number | null;
1614
+ amountCents: number;
1615
+ } | null;
1616
+ /** When a cancelled subscription ends (ms). */
1617
+ cancelAt: number | null;
1618
+ /** An invoice is unpaid. */
1619
+ pastDue: boolean;
1620
+ /** Stripe page that pays it (owner only). */
1621
+ openInvoiceUrl: string | null;
1622
+ paymentMethod: {
1623
+ brand: string;
1624
+ last4: string;
1625
+ expMonth: number;
1626
+ expYear: number;
1627
+ } | null;
1628
+ /** Pro only: `tier` is `trial` or `pro`. */
1629
+ limits: {
1630
+ tier: string;
1631
+ replicasPerApp: number;
1632
+ } | null;
1633
+ /** Pro Checkout is open for this account. */
1634
+ checkoutAvailable: boolean;
1635
+ }
1636
+ interface StartCheckoutOpts {
1637
+ /** Dashboard path to come back to after Checkout, e.g. `/projects/abc`. */
1638
+ returnUrl?: string;
1639
+ }
1640
+ interface CheckoutSession {
1641
+ /** Stripe Checkout page. The user finishes it in a browser. */
1642
+ url: string;
1643
+ sessionId: string;
1644
+ /** Null when the account already had a trial: Pro starts at once and charges $19. */
1645
+ trialDays: number | null;
1646
+ trialCreditCents: number | null;
1647
+ }
1648
+ interface StartProNowResult {
1649
+ /**
1650
+ * `active`: charged $19, the first paid month started. `requires_action`: the bank
1651
+ * wants a confirmation (or declined); open `invoiceUrl`, the trial continues.
1652
+ * `failed`: nothing changed, the trial continues.
1653
+ */
1654
+ status: 'active' | 'requires_action' | 'failed';
1655
+ invoiceUrl?: string | null;
1656
+ }
1657
+ interface PromoRedemption {
1658
+ /** `pending_payment_method`: held for the trial Checkout starts. `applied`: applied now. */
1659
+ status: string;
1660
+ code?: string;
1661
+ /** The trial credits (older servers: the credit amount). */
1662
+ creditCents: number;
1663
+ expiresAt: number | null;
1664
+ /** Kept for older clients. */
1665
+ balanceCents: number;
1666
+ /** Trial length the code gives. Missing from servers before Pro. */
1667
+ trialDays?: number;
1668
+ trialCreditCents?: number;
1669
+ /** `next_checkout`: held for the trial `startCheckout` opens. `current_trial`: extended the running trial. */
1670
+ appliesTo?: 'next_checkout' | 'current_trial';
1671
+ }
1672
+ /**
1673
+ * The account's plan, balance and usage.
1674
+ *
1675
+ * Pro costs $19/month, taxes included, with $19 of credits each month; usage above that
1676
+ * is pay as you go, invoiced as it builds up. A new account starts with a 7-day trial
1677
+ * with $5 of credits. Enterprise is pay as you go, invoiced monthly. Old prepaid
1678
+ * credits accounts (`plan: 'payg'`) keep {@link balance} and {@link transactions}
1679
+ * until 1 November 2026.
1465
1680
  *
1466
1681
  * Billing is **account-scoped, not workspace-scoped**: every workspace you create for
1467
1682
  * a user bills to the account that owns the key. That is what makes per-user
1468
- * workspaces a safe pattern — your users get isolation, you keep one bill — and also
1469
- * what makes {@link Balance.runwayHours} worth watching before you provision more.
1683
+ * workspaces a safe pattern — your users get isolation, you keep one bill.
1684
+ *
1685
+ * **Requires an unscoped key**, except {@link subscription} with a `workspaceId` the
1686
+ * key can reach. A scoped key is refused with 403 `ACCOUNT_SCOPE_REQUIRED`, because a
1687
+ * scoped key is meant to be handed to an end user, who should not be reading your
1688
+ * card details or changing your plan. For per-workspace spend, use
1689
+ * {@link MetricsAPI.cost} instead.
1470
1690
  *
1471
- * **Requires an unscoped key.** A scoped key is refused with 403
1472
- * `ACCOUNT_SCOPE_REQUIRED`, because there is no workspace-scoped view of one shared
1473
- * balance, ledger and set of saved cards — and because a scoped key is meant to be
1474
- * handed to an end user, who should not be reading your card details or spending
1475
- * against them. For per-workspace spend, use {@link MetricsAPI.cost} instead.
1691
+ * Checkout and invoices are web pages: methods return their URL for the user to open.
1692
+ * Nothing here retries a payment.
1476
1693
  */
1477
1694
  declare class BillingAPI {
1478
1695
  private readonly client;
1479
1696
  constructor(client: PlatformClient);
1480
- /** Current balance, status, burn rate, and runway. */
1697
+ /**
1698
+ * The plan: trial, this month's credits, overage, next charge, cancel date. With
1699
+ * `workspaceId`, the plan of that workspace's owner (`isOwner: false`, no card or
1700
+ * invoice fields).
1701
+ */
1702
+ subscription(opts?: {
1703
+ workspaceId?: string;
1704
+ }): Promise<Subscription>;
1705
+ /**
1706
+ * Opens Stripe Checkout for Pro: the trial when the account can have one, otherwise
1707
+ * Pro at once ($19 today). Returns the page for the user to finish; a second call
1708
+ * while it is open returns the same session.
1709
+ */
1710
+ startCheckout(opts?: StartCheckoutOpts): Promise<CheckoutSession>;
1711
+ /** Ends the trial now: charges $19 and starts the first paid month with $19 of credits. */
1712
+ startProNow(): Promise<StartProNowResult>;
1713
+ /** Cancels Pro at the end of the current month or trial. Cancelling in the trial costs nothing. */
1714
+ cancel(): Promise<{
1715
+ cancelAt: number | null;
1716
+ }>;
1717
+ /** Undoes {@link cancel}: Pro renews as usual. */
1718
+ resume(): Promise<{
1719
+ cancelAt: null;
1720
+ }>;
1721
+ /** Redeems a promo code: a longer trial with more trial credits. Works only before the first payment. */
1722
+ redeemPromo(code: string): Promise<PromoRedemption>;
1723
+ /** Prepaid credits balance, status, burn rate and runway (old `payg` accounts and enterprise). */
1481
1724
  balance(): Promise<Balance>;
1482
- /** A page of balance transactions, newest first. */
1725
+ /** A page of balance transactions, newest first (old `payg` accounts and enterprise). */
1483
1726
  transactions(opts?: ListTransactionsOpts): Promise<TransactionPage>;
1484
1727
  /** Cost summary for the current billing period, broken down by resource. */
1485
1728
  summary(): Promise<unknown>;
1486
1729
  /** Live (not-yet-invoiced) usage accumulating right now. */
1487
1730
  live(): Promise<unknown>;
1731
+ /** Saved cards. Cards are added in Checkout or on the Billing page. */
1488
1732
  paymentMethods(): Promise<{
1489
1733
  items: unknown[];
1490
1734
  }>;
1491
- setupPaymentMethod(returnUrl?: string): Promise<{
1492
- url: string;
1493
- }>;
1494
1735
  removePaymentMethod(id: string): Promise<void>;
1495
- purchase(creditCents: number, opts?: {
1496
- paymentMethod?: 'card' | 'crypto';
1497
- returnUrl?: string;
1498
- }): Promise<{
1499
- url: string;
1500
- sessionId?: string;
1501
- }>;
1502
- autoTopup(): Promise<unknown>;
1503
- setAutoTopup(opts: {
1504
- enabled: boolean;
1505
- thresholdCents: number;
1506
- amountCents: number;
1507
- paymentMethodIds: string[];
1508
- }): Promise<unknown>;
1509
- runAutoTopup(): Promise<unknown>;
1510
- redeemPromo(code: string): Promise<unknown>;
1511
- x402Quote(creditCents: number): Promise<unknown>;
1512
- paymentStatus(attemptId: string): Promise<unknown>;
1513
- /** Pay with the CLI's durable x402 journal. Requires CLI >= 4.0.8. Amounts are cents. */
1514
- payX402(creditCents: number, opts: {
1515
- maxTotalCents: number;
1516
- requestId?: string;
1517
- executable?: string;
1518
- }): Promise<unknown>;
1519
1736
  }
1520
1737
 
1521
1738
  interface VolumeInfo {
@@ -1527,8 +1744,10 @@ interface VolumeInfo {
1527
1744
  /** Region the volume's node lives in. A sandbox mounting it runs here too. */
1528
1745
  region?: string;
1529
1746
  status: string;
1747
+ /** Id of the sandbox the volume is attached to, or `null` when it is free. */
1530
1748
  attachedTo?: string | null;
1531
- createdAt: number;
1749
+ /** Creation time: an ISO-8601 string for Firecracker volumes, unix milliseconds for container volumes. */
1750
+ createdAt: string | number;
1532
1751
  /**
1533
1752
  * Whether `sizeGb` is actually enforced as a hard limit on the volume's node.
1534
1753
  * Returned by {@link Volume.resize}; `false` means the size was recorded but the
@@ -1537,7 +1756,7 @@ interface VolumeInfo {
1537
1756
  sizeEnforced?: boolean;
1538
1757
  }
1539
1758
  interface CreateVolumeOpts extends ConnectionOpts {
1540
- /** 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; use `Volume.resize` for that. */
1759
+ /** 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. */
1541
1760
  sizeGb?: number;
1542
1761
  /**
1543
1762
  * Region to place the volume in, e.g. `'us-east-1'`. A volume is node-local, so
@@ -1560,7 +1779,9 @@ interface CreateVolumeOpts extends ConnectionOpts {
1560
1779
  * Names are slugs: lowercase letters, digits and dashes, starting and ending with a
1561
1780
  * letter or digit, up to 64 characters.
1562
1781
  *
1563
- * Mount one to a sandbox via `Sandbox.create({ volumeName: 'my-data' })`.
1782
+ * Mount one to a sandbox via `Sandbox.create({ volumeName: 'my-data' })`; it appears
1783
+ * at `/workspace`. A volume is attached to one sandbox at a time (`attachedTo`), and
1784
+ * a sandbox with a volume attached cannot be forked.
1564
1785
  */
1565
1786
  declare class Volume {
1566
1787
  /** The volume's generated id. Stable, but you rarely need it — address by name. */
@@ -1583,7 +1804,7 @@ declare class Volume {
1583
1804
  * "the scratch disk for this task" no longer has to store an id between runs.
1584
1805
  *
1585
1806
  * An existing volume is returned as-is — `sizeGb` applies only to a fresh create,
1586
- * so an existing volume keeps its size. Call {@link Volume.resize} to change it.
1807
+ * so an existing volume keeps its size.
1587
1808
  */
1588
1809
  static getOrCreate(projectId: string, name: string, opts?: CreateVolumeOpts): Promise<Volume>;
1589
1810
  /** Look a volume up by name or by id. */
@@ -1594,11 +1815,15 @@ declare class Volume {
1594
1815
  /**
1595
1816
  * Resize a volume, by name or by id, to `sizeGb`.
1596
1817
  *
1597
- * The change is in place and online: the size is a quota, so no data is copied,
1598
- * it completes in well under a second, and a sandbox that has the volume mounted
1599
- * keeps running and sees the new size immediately. Both growing and shrinking are
1600
- * allowed, but a shrink must leave at least 10% of the new size free — otherwise
1601
- * it throws `ConflictError` with `code: 'volume_too_full_to_shrink'`.
1818
+ * **Firecracker volumes cannot be resized yet**: volumes created for the default
1819
+ * Firecracker sandboxes throw `LizardError` (400) with `code: 'volume_not_resizable'`.
1820
+ * Create the volume at the size you need, or copy the data to a new, larger one.
1821
+ *
1822
+ * On a container volume the change is in place and online: the size is a quota,
1823
+ * so no data is copied and a mounted sandbox sees the new size immediately. Both
1824
+ * growing and shrinking are allowed, but a shrink must leave at least 10% of the
1825
+ * new size free — otherwise it throws `ConflictError` with
1826
+ * `code: 'volume_too_full_to_shrink'`.
1602
1827
  *
1603
1828
  * Other failures carry a `code` too: `invalid_volume_size`, `volume_not_resizable`,
1604
1829
  * `volume_resize_in_progress`, `volume_not_provisioned`,
@@ -1609,7 +1834,7 @@ declare class Volume {
1609
1834
  */
1610
1835
  static resize(projectId: string, nameOrId: string, sizeGb: number, opts?: ConnectionOpts): Promise<VolumeInfo>;
1611
1836
  getInfo(projectId: string): Promise<VolumeInfo>;
1612
- /** Resize this volume in place — see the static {@link Volume.resize}. */
1837
+ /** Resize this volume — see the static {@link Volume.resize} (not supported for Firecracker volumes yet). */
1613
1838
  resize(projectId: string, sizeGb: number): Promise<VolumeInfo>;
1614
1839
  delete(projectId: string): Promise<void>;
1615
1840
  }
@@ -1791,6 +2016,34 @@ declare class ConflictError extends LizardError {
1791
2016
  declare class TimeoutError extends LizardError {
1792
2017
  constructor(message?: string);
1793
2018
  }
2019
+ /**
2020
+ * The account has to pay before it can do this (HTTP 402). Every create call answers
2021
+ * 402 when the account has no plan yet, its trial credits are used up, or an invoice
2022
+ * is unpaid. Show {@link message} to the user as is and send them to {@link url}.
2023
+ *
2024
+ * Still a {@link LizardError}, so existing `catch` blocks keep working.
2025
+ */
2026
+ declare class PaymentRequiredError extends LizardError {
2027
+ /**
2028
+ * Why payment is needed: `trial_available` (start the Pro trial),
2029
+ * `subscription_required` (the trial was used: start Pro), `trial_credits_used`
2030
+ * (start Pro now), `past_due` or `paused` (pay the open invoice), or, for accounts
2031
+ * on the old prepaid credits, `grace`, `frozen`, `card_required` or
2032
+ * `credits_required`. {@link LizardError.status} stays the HTTP status, 402.
2033
+ */
2034
+ paymentStatus?: string;
2035
+ /** Billing page that starts the Pro trial, or Pro when the trial was used. */
2036
+ subscribeUrl?: string;
2037
+ /** The Billing page. */
2038
+ billingUrl?: string;
2039
+ /** The Credits page, for accounts on the old prepaid credits. */
2040
+ topupUrl?: string;
2041
+ /** Stripe page that pays an unpaid invoice (`code` `UNPAID_INVOICE`). */
2042
+ invoiceUrl?: string;
2043
+ constructor(message?: string);
2044
+ /** The one page to open next for this {@link paymentStatus}. */
2045
+ get url(): string | undefined;
2046
+ }
1794
2047
 
1795
2048
  /** A single output item produced during code execution. */
1796
2049
  type OutputItem = {
@@ -1827,7 +2080,7 @@ declare class Execution {
1827
2080
  results: OutputItem[];
1828
2081
  /** Execution error if the code threw an exception. */
1829
2082
  error?: ExecutionError;
1830
- /** Monotonically increasing counter for this context. */
2083
+ /** Monotonically increasing counter for this context (the Python kernel's `In[n]`). */
1831
2084
  executionCount: number;
1832
2085
  get success(): boolean;
1833
2086
  get text(): string;
@@ -1842,11 +2095,15 @@ type RunCodeLanguage = 'python' | 'javascript' | 'bash' | (string & Record<never
1842
2095
  interface RunCodeOpts {
1843
2096
  /** Language to run in. Defaults to python. */
1844
2097
  language?: RunCodeLanguage;
1845
- /** Use a specific context instead of the per-language default. */
2098
+ /** Use a specific context (from `createContext`) instead of the per-language default. */
1846
2099
  context?: CodeContext;
1847
2100
  /** Extra environment variables available to the code. */
1848
2101
  envs?: Record<string, string>;
1849
- /** Client timeout in milliseconds. No client timer is set when omitted. */
2102
+ /**
2103
+ * Execution timeout in milliseconds, default 60 000. A Python kernel that runs
2104
+ * past it is interrupted (its state is kept) and `execution.error.name` is
2105
+ * `'TimeoutError'`; a process is killed.
2106
+ */
1850
2107
  timeoutMs?: number;
1851
2108
  onStdout?: (data: string) => void;
1852
2109
  onStderr?: (data: string) => void;
@@ -1859,31 +2116,47 @@ interface CreateContextOpts {
1859
2116
  }
1860
2117
 
1861
2118
  /**
1862
- * Legacy client for the code-interpreter execution server.
2119
+ * A sandbox for running code snippets, built on {@link Sandbox.process}.
2120
+ *
2121
+ * Boots the `interpreter` template by default. Python runs in a persistent
2122
+ * Jupyter kernel per context, so variables, imports and functions carry over
2123
+ * between calls, `execution.results` holds rich output (the value of the last
2124
+ * expression, matplotlib charts as `image/png`, HTML, ...) and errors carry
2125
+ * the exception name and traceback.
1863
2126
  *
1864
- * Current hosted templates do not provide this server. The default
1865
- * `code-interpreter-v1` template is unavailable; selecting `interpreter`
1866
- * does not enable this API. Use `Sandbox.create('interpreter', options)`
1867
- * and `sandbox.process.exec()` for Python commands instead.
2127
+ * Limits, honestly:
2128
+ * - `javascript` (node) and `bash` run each call as a fresh process: no state
2129
+ * carries over and `results` stays empty. `node` must be installed in the
2130
+ * template; the `interpreter` template does not ship it.
2131
+ * - On a template without Jupyter (e.g. `base`), Python also runs as a fresh
2132
+ * process per call.
2133
+ * - `stdout`/`stderr` are delivered in the chunks the kernel or process
2134
+ * produced them, not per character.
1868
2135
  *
1869
- * The methods remain for compatibility with a separately provided server.
2136
+ * Kernels live inside the sandbox's microVM, so pause/resume, snapshots and
2137
+ * forks keep their state.
2138
+ *
2139
+ * @example
2140
+ * ```ts
2141
+ * const sandbox = await CodeSandbox.create({ project: 'my-project' })
2142
+ * await sandbox.runCode('x = 21')
2143
+ * const run = await sandbox.runCode('x * 2')
2144
+ * console.log(run.results[0].data) // "42"
2145
+ * await sandbox.kill()
2146
+ * ```
1870
2147
  */
1871
2148
  declare class CodeSandbox extends Sandbox {
1872
- protected static readonly defaultTemplate = "code-interpreter-v1";
1873
- private get serverUrl();
2149
+ protected static readonly defaultTemplate: string;
1874
2150
  /**
1875
- * Execute code in a persistent kernel.
2151
+ * Execute code and wait for it to finish.
1876
2152
  *
1877
- * Variables, imports, and function definitions from previous calls are
1878
- * available in subsequent calls within the same context.
2153
+ * Python keeps its state per context (the default context, per language,
2154
+ * when none is given). Code errors appear in `execution.error`; request
2155
+ * failures throw.
1879
2156
  *
1880
2157
  * @param code Source code to run.
1881
2158
  * @param opts Language, context, env vars, timeout, and streaming callbacks.
1882
2159
  *
1883
- * @returns Execution result with stdout, stderr, results, and any error.
1884
- *
1885
- * Code errors appear in `execution.error`; request failures throw.
1886
- *
1887
2160
  * @example
1888
2161
  * ```ts
1889
2162
  * const result = await sandbox.runCode(`
@@ -1897,8 +2170,8 @@ declare class CodeSandbox extends Sandbox {
1897
2170
  /**
1898
2171
  * Create a new isolated execution context.
1899
2172
  *
1900
- * Each context maintains its own variable namespace and process state.
1901
- * Useful for running multiple independent sessions in the same sandbox.
2173
+ * A Python context is its own kernel: its own variables, and `cwd` as its
2174
+ * working directory. Other languages get the working directory only.
1902
2175
  *
1903
2176
  * @example
1904
2177
  * ```ts
@@ -1908,18 +2181,14 @@ declare class CodeSandbox extends Sandbox {
1908
2181
  * ```
1909
2182
  */
1910
2183
  createContext(opts?: CreateContextOpts): Promise<CodeContext>;
1911
- /**
1912
- * List all active execution contexts in this sandbox.
1913
- */
2184
+ /** List the contexts created with {@link createContext} in this sandbox. */
1914
2185
  listContexts(): Promise<CodeContext[]>;
1915
- /**
1916
- * Delete an execution context and free its resources.
1917
- */
2186
+ /** Delete an execution context, stopping its kernel. */
1918
2187
  deleteContext(context: CodeContext | string): Promise<void>;
1919
- /**
1920
- * Restart a context, clearing all variables and state.
1921
- */
2188
+ /** Restart a context, clearing all variables and state. */
1922
2189
  restartContext(context: CodeContext | string): Promise<void>;
2190
+ /** Run the in-sandbox runner with `args` and hand each of its events to `onEvent`. */
2191
+ private runner;
1923
2192
  static create(opts?: SandboxOpts): Promise<CodeSandbox>;
1924
2193
  static create(template: string, opts?: SandboxOpts): Promise<CodeSandbox>;
1925
2194
  static connect(sandboxId: string, opts?: ConnectionOpts): Promise<CodeSandbox>;
@@ -1949,4 +2218,4 @@ declare class LizardCLI {
1949
2218
  }): Promise<CLIResult>;
1950
2219
  }
1951
2220
 
1952
- 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 };
2221
+ export { type Account, type Addon, type AddonType, AddonsAPI, type ApiKey, type ApiKeyScope, ApiKeysAPI, AuthenticationError, type Balance, BillingAPI, type CLIOptions, type CLIResult, type CheckoutSession, 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, PaymentRequiredError, type Plan, PlatformClient, type ProcessInfo, type ProcessOpts, type ProcessResult, type ProcessSignal, type Project, type ProjectConfig, type ProjectCost, ProjectsAPI, type PromoRedemption, 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, type StartCheckoutOpts, type StartProNowResult, StorageAPI, type StreamEvent, type Subscription, type SubscriptionStatus, TimeoutError, type Transaction, type TransactionPage, Volume, type VolumeInfo, type Workspace, WorkspacesAPI, resolveProjectId };