@lizard-build/sdk 0.1.83 → 1.0.1

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 CHANGED
@@ -106,9 +106,10 @@ if (result.exitCode !== 0) throw new Error(result.stderr)
106
106
  The `desktop` template runs an Openbox desktop with Chromium, streamed to a browser over WebRTC (with noVNC as the fallback). You can watch it, and an agent can drive it:
107
107
 
108
108
  ```ts
109
- import { Sandbox } from '@lizard-build/sdk'
109
+ import { Lizard } from '@lizard-build/sdk'
110
110
 
111
- const sandbox = await Sandbox.create('desktop', { project: 'my-project' })
111
+ const lizard = new Lizard({ project: 'my-project' })
112
+ const sandbox = await lizard.create('desktop')
112
113
  try {
113
114
  const { url, viewOnlyUrl } = await sandbox.desktop.start() // open `url` in a browser
114
115
  await sandbox.desktop.openUrl('https://example.com')
@@ -128,11 +129,10 @@ Treat `url` like a credential: anyone with it can see and control the desktop. S
128
129
  Run Python with the `interpreter` template. Each process command starts a separate Python process, so Python variables do not survive between calls; use `CodeSandbox` when they should.
129
130
 
130
131
  ```ts
131
- import { Sandbox } from '@lizard-build/sdk'
132
+ import { Lizard } from '@lizard-build/sdk'
132
133
 
133
- const sandbox = await Sandbox.create('interpreter', {
134
- project: 'my-project', timeoutMs: 300_000,
135
- })
134
+ const lizard = new Lizard({ project: 'my-project' })
135
+ const sandbox = await lizard.create('interpreter', { timeoutMs: 300_000 })
136
136
  try {
137
137
  const result = await sandbox.process.exec("python -c 'print(2 ** 10)'")
138
138
  if (result.exitCode !== 0) throw new Error(result.stderr)
@@ -164,6 +164,14 @@ Command results contain stdout, stderr, and the exit code. Command timeouts are
164
164
 
165
165
  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.
166
166
 
167
+ ## Versions and API stability
168
+
169
+ Lizard SDK follows [semantic versioning](https://semver.org) from 1.0.0. A change that breaks a documented method, option or return type ships only in a new major version. New features come in minor versions, fixes in patch versions. The npm and PyPI packages share one version number. The [changelog](https://github.com/lizard-build/lizard-sdk/blob/main/CHANGELOG.md) lists what changed, including the API changes made before 1.0.
170
+
171
+ There are two ways to create a sandbox, and both are stable: `new Lizard({ project }).create(template)` and `Sandbox.create(template, { project })`. The client passes its project to `Sandbox.create()`, so both send the same request. The examples use the client because it also reaches volumes and the platform API. `CodeSandbox.create({ project })` takes the project the same way as `Sandbox.create()`.
172
+
173
+ Platform facts such as prices, limits and templates can change without a new SDK version. See [current limits](https://lizard.build/docs/sandboxes/).
174
+
167
175
  ## Other SDK capabilities
168
176
 
169
177
  The SDK also manages apps, Managed Postgres, Managed Redis, Managed Object Storage and projects. See the [platform guide](https://github.com/lizard-build/lizard-sdk/blob/main/docs/platform.md).
@@ -176,6 +184,7 @@ The SDK also manages apps, Managed Postgres, Managed Redis, Managed Object Stora
176
184
  - [Sandbox reference](https://github.com/lizard-build/lizard-sdk/blob/main/docs/sandboxes.md)
177
185
  - [Platform guide](https://github.com/lizard-build/lizard-sdk/blob/main/docs/platform.md)
178
186
  - [CLI coverage and migration](https://github.com/lizard-build/lizard-sdk/blob/main/docs/cli-parity.md)
187
+ - [Changelog](https://github.com/lizard-build/lizard-sdk/blob/main/CHANGELOG.md)
179
188
  - [Source and issues](https://github.com/lizard-build/lizard-sdk)
180
189
 
181
190
  [Apache-2.0](https://github.com/lizard-build/lizard-sdk/blob/main/LICENSE)
package/dist/index.d.mts CHANGED
@@ -1829,7 +1829,7 @@ interface SandboxOpts extends ConnectionOpts {
1829
1829
  * is not in is rejected with a 400 rather than silently moved — that combination
1830
1830
  * cannot be satisfied.
1831
1831
  *
1832
- * Defaults to the platform's default sandbox region.
1832
+ * Defaults to `'us-east-1'`, or to the volume's or snapshot's region when one is given.
1833
1833
  */
1834
1834
  region?: string;
1835
1835
  /** Attach a persistent volume by id, mounted at `/workspace`. */
package/dist/index.d.ts CHANGED
@@ -1829,7 +1829,7 @@ interface SandboxOpts extends ConnectionOpts {
1829
1829
  * is not in is rejected with a 400 rather than silently moved — that combination
1830
1830
  * cannot be satisfied.
1831
1831
  *
1832
- * Defaults to the platform's default sandbox region.
1832
+ * Defaults to `'us-east-1'`, or to the volume's or snapshot's region when one is given.
1833
1833
  */
1834
1834
  region?: string;
1835
1835
  /** Attach a persistent volume by id, mounted at `/workspace`. */
package/dist/index.js CHANGED
@@ -73,6 +73,7 @@ module.exports = __toCommonJS(index_exports);
73
73
  // src/config.ts
74
74
  var DEFAULT_API_URL = "https://lizard.build";
75
75
  var DEFAULT_SANDBOX_TIMEOUT_MS = 5 * 60 * 1e3;
76
+ var DEFAULT_SANDBOX_REGION = "us-east-1";
76
77
  var ConnectionConfig = class {
77
78
  constructor(opts) {
78
79
  this.apiKey = opts?.apiKey ?? process.env.LIZARD_API_KEY ?? "";
@@ -1686,12 +1687,21 @@ function coord(n) {
1686
1687
  }
1687
1688
 
1688
1689
  // src/sandbox/client.ts
1690
+ async function regionUnavailable(res) {
1691
+ try {
1692
+ const body = await res.clone().json();
1693
+ return body?.code === "region_unavailable";
1694
+ } catch {
1695
+ return false;
1696
+ }
1697
+ }
1689
1698
  var SandboxClient = class {
1690
1699
  static async createSandbox(template, timeoutMs, opts) {
1691
1700
  const ref = requireProjectRef(opts);
1692
1701
  const config = new ConnectionConfig(opts);
1693
1702
  const projectId = ref.projectId ?? await resolveProjectId(ref.project, config);
1694
- const res = await fetch(`${config.apiUrl}/api/sandboxes`, {
1703
+ const defaultRegion = !opts?.region && !opts?.volumeId && !opts?.volumeName && !opts?.snapshotId;
1704
+ const post = (region) => fetch(`${config.apiUrl}/api/sandboxes`, {
1695
1705
  method: "POST",
1696
1706
  headers: config.headers,
1697
1707
  body: JSON.stringify({
@@ -1702,12 +1712,14 @@ var SandboxClient = class {
1702
1712
  projectId,
1703
1713
  metadata: opts?.metadata,
1704
1714
  envs: opts?.envs,
1705
- region: opts?.region,
1715
+ region,
1706
1716
  volumeId: opts?.volumeId,
1707
1717
  volumeName: opts?.volumeName,
1708
1718
  lizardToken: opts?.lizardToken
1709
1719
  })
1710
1720
  });
1721
+ let res = await post(opts?.region || (defaultRegion ? DEFAULT_SANDBOX_REGION : void 0));
1722
+ if (defaultRegion && res.status === 503 && await regionUnavailable(res)) res = await post(void 0);
1711
1723
  if (!res.ok) await handleApiError(res);
1712
1724
  return res.json();
1713
1725
  }
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/config.ts
2
2
  var DEFAULT_API_URL = "https://lizard.build";
3
3
  var DEFAULT_SANDBOX_TIMEOUT_MS = 5 * 60 * 1e3;
4
+ var DEFAULT_SANDBOX_REGION = "us-east-1";
4
5
  var ConnectionConfig = class {
5
6
  constructor(opts) {
6
7
  this.apiKey = opts?.apiKey ?? process.env.LIZARD_API_KEY ?? "";
@@ -1614,12 +1615,21 @@ function coord(n) {
1614
1615
  }
1615
1616
 
1616
1617
  // src/sandbox/client.ts
1618
+ async function regionUnavailable(res) {
1619
+ try {
1620
+ const body = await res.clone().json();
1621
+ return body?.code === "region_unavailable";
1622
+ } catch {
1623
+ return false;
1624
+ }
1625
+ }
1617
1626
  var SandboxClient = class {
1618
1627
  static async createSandbox(template, timeoutMs, opts) {
1619
1628
  const ref = requireProjectRef(opts);
1620
1629
  const config = new ConnectionConfig(opts);
1621
1630
  const projectId = ref.projectId ?? await resolveProjectId(ref.project, config);
1622
- const res = await fetch(`${config.apiUrl}/api/sandboxes`, {
1631
+ const defaultRegion = !opts?.region && !opts?.volumeId && !opts?.volumeName && !opts?.snapshotId;
1632
+ const post = (region) => fetch(`${config.apiUrl}/api/sandboxes`, {
1623
1633
  method: "POST",
1624
1634
  headers: config.headers,
1625
1635
  body: JSON.stringify({
@@ -1630,12 +1640,14 @@ var SandboxClient = class {
1630
1640
  projectId,
1631
1641
  metadata: opts?.metadata,
1632
1642
  envs: opts?.envs,
1633
- region: opts?.region,
1643
+ region,
1634
1644
  volumeId: opts?.volumeId,
1635
1645
  volumeName: opts?.volumeName,
1636
1646
  lizardToken: opts?.lizardToken
1637
1647
  })
1638
1648
  });
1649
+ let res = await post(opts?.region || (defaultRegion ? DEFAULT_SANDBOX_REGION : void 0));
1650
+ if (defaultRegion && res.status === 503 && await regionUnavailable(res)) res = await post(void 0);
1639
1651
  if (!res.ok) await handleApiError(res);
1640
1652
  return res.json();
1641
1653
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lizard-build/sdk",
3
- "version": "0.1.83",
3
+ "version": "1.0.1",
4
4
  "description": "TypeScript and JavaScript SDK for Lizard (lizard.build): cloud sandboxes for AI agents and code execution.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",