@declaw/sdk 1.1.0 → 1.1.2

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.js CHANGED
@@ -139,6 +139,12 @@ var ApiClient = class {
139
139
  async get(path, opts) {
140
140
  return this.requestWithRetry("GET", path, opts);
141
141
  }
142
+ /** Send a GET request and return the response body as raw bytes. */
143
+ async getBytes(path, opts) {
144
+ const response = await this.requestWithRetry("GET", path, opts, true);
145
+ const buf = await response.arrayBuffer();
146
+ return new Uint8Array(buf);
147
+ }
142
148
  /** Send a POST request and return parsed JSON. */
143
149
  async post(path, opts) {
144
150
  return this.requestWithRetry("POST", path, opts);
@@ -171,6 +177,12 @@ var ApiClient = class {
171
177
  }
172
178
  /**
173
179
  * Abort all in-flight requests and release resources.
180
+ *
181
+ * Since 1.1.1 the SDK maintains a process-wide shared ApiClient cache
182
+ * for hot class-method paths (Sandbox.create, Volumes.*, Template.*).
183
+ * Calling `close()` on a shared instance aborts its AbortController,
184
+ * which would cancel any concurrent in-flight call. Prefer
185
+ * `resetSharedClients()` if you want to tear down every cached client.
174
186
  */
175
187
  close() {
176
188
  this.abortController.abort();
@@ -290,6 +302,28 @@ var ApiClient = class {
290
302
  await new Promise((resolve) => setTimeout(resolve, ms));
291
303
  }
292
304
  };
305
+ var _sharedClients = /* @__PURE__ */ new Map();
306
+ function sharedKey(config) {
307
+ return [config.apiKey ?? "", config.apiUrl, config.requestTimeout ?? ""].join("|");
308
+ }
309
+ function getSharedClient(config) {
310
+ const key = sharedKey(config);
311
+ let client = _sharedClients.get(key);
312
+ if (!client) {
313
+ client = new ApiClient(config);
314
+ _sharedClients.set(key, client);
315
+ }
316
+ return client;
317
+ }
318
+ function resetSharedClients() {
319
+ for (const client of _sharedClients.values()) {
320
+ try {
321
+ client.close();
322
+ } catch {
323
+ }
324
+ }
325
+ _sharedClients.clear();
326
+ }
293
327
 
294
328
  // src/sandbox/network.ts
295
329
  var ALL_TRAFFIC = "0.0.0.0/0";
@@ -1235,15 +1269,18 @@ var Filesystem = class {
1235
1269
  this.sandboxId = sandboxId;
1236
1270
  this.client = client;
1237
1271
  }
1238
- /**
1239
- * Read a file's contents as a string.
1240
- *
1241
- * @param path - Absolute path to the file.
1242
- * @param opts - Optional user and request timeout.
1243
- * @returns The file contents as a string.
1244
- */
1245
1272
  async read(path, opts) {
1246
1273
  const user = opts?.user ?? DEFAULT_USER;
1274
+ if (opts?.format === "bytes") {
1275
+ return this.client.getBytes(
1276
+ `/sandboxes/${this.sandboxId}/files`,
1277
+ {
1278
+ params: { path, username: user },
1279
+ headers: { "Accept": "application/octet-stream" },
1280
+ timeout: opts?.requestTimeout
1281
+ }
1282
+ );
1283
+ }
1247
1284
  const result = await this.client.get(
1248
1285
  `/sandboxes/${this.sandboxId}/files`,
1249
1286
  {
@@ -1839,54 +1876,49 @@ var Sandbox = class _Sandbox {
1839
1876
  apiUrl: opts?.apiUrl,
1840
1877
  requestTimeout: opts?.requestTimeout
1841
1878
  });
1842
- const client = new ApiClient(config);
1843
- try {
1844
- const body = {
1845
- template: opts?.template ?? DEFAULT_TEMPLATE,
1846
- timeout: opts?.timeout ?? DEFAULT_TIMEOUT,
1847
- secure: opts?.secure ?? true
1848
- };
1849
- if (opts?.metadata) {
1850
- body.metadata = opts.metadata;
1851
- }
1852
- if (opts?.envs) {
1853
- body.envs = opts.envs;
1854
- }
1855
- if (opts?.network) {
1856
- body.network = networkOptsToJSON(opts.network);
1857
- } else if (opts?.allowInternetAccess === false) {
1858
- body.network = { deny_out: [ALL_TRAFFIC] };
1859
- }
1860
- if (opts?.security) {
1861
- body.security = { policy_json: JSON.stringify(securityPolicyToJSON(opts.security)) };
1862
- if (opts.security.network && !body.network) {
1863
- body.network = typeof opts.security.network === "object" && "allowOut" in opts.security.network ? networkOptsToJSON(opts.security.network) : opts.security.network;
1864
- }
1865
- }
1866
- if (opts?.lifecycle) {
1867
- body.lifecycle = lifecycleToJSON(opts.lifecycle);
1868
- }
1869
- if (opts?.volumes && opts.volumes.length > 0) {
1870
- body.volumes = opts.volumes.map(volumeAttachmentToJSON);
1879
+ const client = getSharedClient(config);
1880
+ const body = {
1881
+ template: opts?.template ?? DEFAULT_TEMPLATE,
1882
+ timeout: opts?.timeout ?? DEFAULT_TIMEOUT,
1883
+ secure: opts?.secure ?? true
1884
+ };
1885
+ if (opts?.metadata) {
1886
+ body.metadata = opts.metadata;
1887
+ }
1888
+ if (opts?.envs) {
1889
+ body.envs = opts.envs;
1890
+ }
1891
+ if (opts?.network) {
1892
+ body.network = networkOptsToJSON(opts.network);
1893
+ } else if (opts?.allowInternetAccess === false) {
1894
+ body.network = { deny_out: [ALL_TRAFFIC] };
1895
+ }
1896
+ if (opts?.security) {
1897
+ body.security = { policy_json: JSON.stringify(securityPolicyToJSON(opts.security)) };
1898
+ if (opts.security.network && !body.network) {
1899
+ body.network = typeof opts.security.network === "object" && "allowOut" in opts.security.network ? networkOptsToJSON(opts.security.network) : opts.security.network;
1871
1900
  }
1872
- const data = await client.post("/sandboxes", {
1873
- json: body,
1874
- timeout: opts?.requestTimeout
1875
- });
1876
- const sandboxId = data.sandbox_id;
1877
- assertValidId(sandboxId, "sandbox ID (from server)");
1878
- return new _Sandbox(
1879
- sandboxId,
1880
- config,
1881
- client,
1882
- data.envd_access_token,
1883
- data.sandbox_domain,
1884
- data.traffic_access_token
1885
- );
1886
- } catch (error) {
1887
- client.close();
1888
- throw error;
1889
1901
  }
1902
+ if (opts?.lifecycle) {
1903
+ body.lifecycle = lifecycleToJSON(opts.lifecycle);
1904
+ }
1905
+ if (opts?.volumes && opts.volumes.length > 0) {
1906
+ body.volumes = opts.volumes.map(volumeAttachmentToJSON);
1907
+ }
1908
+ const data = await client.post("/sandboxes", {
1909
+ json: body,
1910
+ timeout: opts?.requestTimeout
1911
+ });
1912
+ const sandboxId = data.sandbox_id;
1913
+ assertValidId(sandboxId, "sandbox ID (from server)");
1914
+ return new _Sandbox(
1915
+ sandboxId,
1916
+ config,
1917
+ client,
1918
+ data.envd_access_token,
1919
+ data.sandbox_domain,
1920
+ data.traffic_access_token
1921
+ );
1890
1922
  }
1891
1923
  /**
1892
1924
  * Connect to an existing sandbox.
@@ -1903,23 +1935,18 @@ var Sandbox = class _Sandbox {
1903
1935
  apiUrl: opts?.apiUrl,
1904
1936
  requestTimeout: opts?.requestTimeout
1905
1937
  });
1906
- const client = new ApiClient(config);
1907
- try {
1908
- const data = await client.get(`/sandboxes/${sandboxId}`, {
1909
- timeout: opts?.requestTimeout
1910
- });
1911
- return new _Sandbox(
1912
- data.sandbox_id,
1913
- config,
1914
- client,
1915
- data.envd_access_token,
1916
- data.sandbox_domain,
1917
- data.traffic_access_token
1918
- );
1919
- } catch (error) {
1920
- client.close();
1921
- throw error;
1922
- }
1938
+ const client = getSharedClient(config);
1939
+ const data = await client.get(`/sandboxes/${sandboxId}`, {
1940
+ timeout: opts?.requestTimeout
1941
+ });
1942
+ return new _Sandbox(
1943
+ data.sandbox_id,
1944
+ config,
1945
+ client,
1946
+ data.envd_access_token,
1947
+ data.sandbox_domain,
1948
+ data.traffic_access_token
1949
+ );
1923
1950
  }
1924
1951
  /**
1925
1952
  * List sandboxes.
@@ -1936,35 +1963,31 @@ var Sandbox = class _Sandbox {
1936
1963
  apiUrl: opts?.apiUrl,
1937
1964
  requestTimeout: opts?.requestTimeout
1938
1965
  });
1939
- const client = new ApiClient(config);
1940
- try {
1941
- const params = {};
1942
- if (opts?.query) {
1943
- for (const [key, value] of Object.entries(opts.query)) {
1944
- params[key] = value;
1945
- }
1946
- }
1947
- if (opts?.limit !== void 0) {
1948
- params.limit = String(opts.limit);
1949
- }
1950
- if (opts?.nextToken) {
1951
- params.next_token = opts.nextToken;
1966
+ const client = getSharedClient(config);
1967
+ const params = {};
1968
+ if (opts?.query) {
1969
+ for (const [key, value] of Object.entries(opts.query)) {
1970
+ params[key] = value;
1952
1971
  }
1953
- const data = await client.get("/sandboxes", {
1954
- params,
1955
- timeout: opts?.requestTimeout
1956
- });
1957
- const rawSandboxes = data.sandboxes ?? [];
1958
- const sandboxes = rawSandboxes.map(
1959
- (s) => parseSandboxInfo(s)
1960
- );
1961
- return {
1962
- sandboxes,
1963
- nextToken: data.next_token ?? void 0
1964
- };
1965
- } finally {
1966
- client.close();
1967
1972
  }
1973
+ if (opts?.limit !== void 0) {
1974
+ params.limit = String(opts.limit);
1975
+ }
1976
+ if (opts?.nextToken) {
1977
+ params.next_token = opts.nextToken;
1978
+ }
1979
+ const data = await client.get("/sandboxes", {
1980
+ params,
1981
+ timeout: opts?.requestTimeout
1982
+ });
1983
+ const rawSandboxes = data.sandboxes ?? [];
1984
+ const sandboxes = rawSandboxes.map(
1985
+ (s) => parseSandboxInfo(s)
1986
+ );
1987
+ return {
1988
+ sandboxes,
1989
+ nextToken: data.next_token ?? void 0
1990
+ };
1968
1991
  }
1969
1992
  /**
1970
1993
  * Kill this sandbox.
@@ -2116,33 +2139,31 @@ var Sandbox = class _Sandbox {
2116
2139
  apiUrl: options.apiUrl,
2117
2140
  requestTimeout: options.requestTimeout
2118
2141
  });
2119
- const client = new ApiClient(config);
2120
- try {
2121
- const query = options.snapshotId ? `?snapshot_id=${encodeURIComponent(options.snapshotId)}` : "";
2122
- await client.post(`/sandboxes/${sandboxId}/restore${query}`, {
2123
- timeout: options.requestTimeout
2124
- });
2125
- const data = await client.get(`/sandboxes/${sandboxId}`, {
2126
- timeout: options.requestTimeout
2127
- });
2128
- return new _Sandbox(
2129
- data.sandbox_id,
2130
- config,
2131
- client,
2132
- data.envd_access_token,
2133
- data.sandbox_domain,
2134
- data.traffic_access_token
2135
- );
2136
- } catch (error) {
2137
- client.close();
2138
- throw error;
2139
- }
2142
+ const client = getSharedClient(config);
2143
+ const query = options.snapshotId ? `?snapshot_id=${encodeURIComponent(options.snapshotId)}` : "";
2144
+ await client.post(`/sandboxes/${sandboxId}/restore${query}`, {
2145
+ timeout: options.requestTimeout
2146
+ });
2147
+ const data = await client.get(`/sandboxes/${sandboxId}`, {
2148
+ timeout: options.requestTimeout
2149
+ });
2150
+ return new _Sandbox(
2151
+ data.sandbox_id,
2152
+ config,
2153
+ client,
2154
+ data.envd_access_token,
2155
+ data.sandbox_domain,
2156
+ data.traffic_access_token
2157
+ );
2140
2158
  }
2141
2159
  /**
2142
- * Close the underlying HTTP client and release resources.
2160
+ * Historically closed the sandbox's HTTP client; since 1.1.1 the SDK
2161
+ * maintains a process-wide shared ApiClient (see `getSharedClient` in
2162
+ * api/client.ts) so per-sandbox close no longer tears the connection
2163
+ * pool down. Kept as a no-op for backwards compatibility — call
2164
+ * `resetSharedClients()` if you want to force a full teardown.
2143
2165
  */
2144
2166
  close() {
2145
- this._client.close();
2146
2167
  }
2147
2168
  /**
2148
2169
  * Support `await using sandbox = await Sandbox.create(...)` for automatic cleanup.
@@ -2372,36 +2393,32 @@ var Template = class {
2372
2393
  domain: opts?.domain,
2373
2394
  requestTimeout: opts?.requestTimeout
2374
2395
  });
2375
- const client = new ApiClient(config);
2376
- try {
2377
- const body = {
2378
- template: template.toJSON(),
2379
- alias
2380
- };
2381
- if (opts?.cpuCount !== void 0) {
2382
- body.cpu_count = opts.cpuCount;
2383
- }
2384
- if (opts?.memoryMb !== void 0) {
2385
- body.memory_mb = opts.memoryMb;
2386
- }
2387
- if (opts?.diskMb !== void 0) {
2388
- body.disk_mb = opts.diskMb;
2389
- }
2390
- const data = await client.post("/templates/build", {
2391
- json: body,
2392
- timeout: opts?.requestTimeout
2393
- });
2394
- const response = data;
2395
- const result = parseBuildInfo(response);
2396
- if (opts?.onBuildLogs && Array.isArray(response.logs)) {
2397
- for (const log of response.logs) {
2398
- opts.onBuildLogs(log);
2399
- }
2396
+ const client = getSharedClient(config);
2397
+ const body = {
2398
+ template: template.toJSON(),
2399
+ alias
2400
+ };
2401
+ if (opts?.cpuCount !== void 0) {
2402
+ body.cpu_count = opts.cpuCount;
2403
+ }
2404
+ if (opts?.memoryMb !== void 0) {
2405
+ body.memory_mb = opts.memoryMb;
2406
+ }
2407
+ if (opts?.diskMb !== void 0) {
2408
+ body.disk_mb = opts.diskMb;
2409
+ }
2410
+ const data = await client.post("/templates/build", {
2411
+ json: body,
2412
+ timeout: opts?.requestTimeout
2413
+ });
2414
+ const response = data;
2415
+ const result = parseBuildInfo(response);
2416
+ if (opts?.onBuildLogs && Array.isArray(response.logs)) {
2417
+ for (const log of response.logs) {
2418
+ opts.onBuildLogs(log);
2400
2419
  }
2401
- return result;
2402
- } finally {
2403
- client.close();
2404
2420
  }
2421
+ return result;
2405
2422
  }
2406
2423
  /**
2407
2424
  * Start a template build in the background.
@@ -2414,30 +2431,26 @@ var Template = class {
2414
2431
  domain: opts?.domain,
2415
2432
  requestTimeout: opts?.requestTimeout
2416
2433
  });
2417
- const client = new ApiClient(config);
2418
- try {
2419
- const body = {
2420
- template: template.toJSON(),
2421
- alias,
2422
- background: true
2423
- };
2424
- if (opts?.cpuCount !== void 0) {
2425
- body.cpu_count = opts.cpuCount;
2426
- }
2427
- if (opts?.memoryMb !== void 0) {
2428
- body.memory_mb = opts.memoryMb;
2429
- }
2430
- if (opts?.diskMb !== void 0) {
2431
- body.disk_mb = opts.diskMb;
2432
- }
2433
- const data = await client.post("/templates/build", {
2434
- json: body,
2435
- timeout: opts?.requestTimeout
2436
- });
2437
- return parseBuildInfo(data);
2438
- } finally {
2439
- client.close();
2434
+ const client = getSharedClient(config);
2435
+ const body = {
2436
+ template: template.toJSON(),
2437
+ alias,
2438
+ background: true
2439
+ };
2440
+ if (opts?.cpuCount !== void 0) {
2441
+ body.cpu_count = opts.cpuCount;
2442
+ }
2443
+ if (opts?.memoryMb !== void 0) {
2444
+ body.memory_mb = opts.memoryMb;
2440
2445
  }
2446
+ if (opts?.diskMb !== void 0) {
2447
+ body.disk_mb = opts.diskMb;
2448
+ }
2449
+ const data = await client.post("/templates/build", {
2450
+ json: body,
2451
+ timeout: opts?.requestTimeout
2452
+ });
2453
+ return parseBuildInfo(data);
2441
2454
  }
2442
2455
  /**
2443
2456
  * Get the status of a template build.
@@ -2451,15 +2464,11 @@ var Template = class {
2451
2464
  domain: opts?.domain,
2452
2465
  requestTimeout: opts?.requestTimeout
2453
2466
  });
2454
- const client = new ApiClient(config);
2455
- try {
2456
- const data = await client.get(`/templates/builds/${buildId}`, {
2457
- timeout: opts?.requestTimeout
2458
- });
2459
- return parseTemplateBuildStatus(data);
2460
- } finally {
2461
- client.close();
2462
- }
2467
+ const client = getSharedClient(config);
2468
+ const data = await client.get(`/templates/builds/${buildId}`, {
2469
+ timeout: opts?.requestTimeout
2470
+ });
2471
+ return parseTemplateBuildStatus(data);
2463
2472
  }
2464
2473
  };
2465
2474
 
@@ -2484,19 +2493,15 @@ var Volumes = class {
2484
2493
  apiUrl: opts?.apiUrl,
2485
2494
  requestTimeout: opts?.requestTimeout
2486
2495
  });
2487
- const client = new ApiClient(config);
2488
- try {
2489
- const body = data instanceof Uint8Array ? data : new Uint8Array(data);
2490
- const resp = await client.post("/volumes", {
2491
- params: { name },
2492
- body,
2493
- headers: { "Content-Type": opts?.contentType ?? "application/gzip" },
2494
- timeout: opts?.requestTimeout
2495
- });
2496
- return parseVolumeInfo(resp);
2497
- } finally {
2498
- client.close();
2499
- }
2496
+ const client = getSharedClient(config);
2497
+ const body = data instanceof Uint8Array ? data : new Uint8Array(data);
2498
+ const resp = await client.post("/volumes", {
2499
+ params: { name },
2500
+ body,
2501
+ headers: { "Content-Type": opts?.contentType ?? "application/gzip" },
2502
+ timeout: opts?.requestTimeout
2503
+ });
2504
+ return parseVolumeInfo(resp);
2500
2505
  }
2501
2506
  /** Fetch metadata for a single volume. */
2502
2507
  static async get(volumeId, opts) {
@@ -2507,15 +2512,11 @@ var Volumes = class {
2507
2512
  apiUrl: opts?.apiUrl,
2508
2513
  requestTimeout: opts?.requestTimeout
2509
2514
  });
2510
- const client = new ApiClient(config);
2511
- try {
2512
- const resp = await client.get(`/volumes/${volumeId}`, {
2513
- timeout: opts?.requestTimeout
2514
- });
2515
- return parseVolumeInfo(resp);
2516
- } finally {
2517
- client.close();
2518
- }
2515
+ const client = getSharedClient(config);
2516
+ const resp = await client.get(`/volumes/${volumeId}`, {
2517
+ timeout: opts?.requestTimeout
2518
+ });
2519
+ return parseVolumeInfo(resp);
2519
2520
  }
2520
2521
  /** List all volumes owned by the caller, newest first. */
2521
2522
  static async list(opts) {
@@ -2525,16 +2526,12 @@ var Volumes = class {
2525
2526
  apiUrl: opts?.apiUrl,
2526
2527
  requestTimeout: opts?.requestTimeout
2527
2528
  });
2528
- const client = new ApiClient(config);
2529
- try {
2530
- const resp = await client.get("/volumes", {
2531
- timeout: opts?.requestTimeout
2532
- });
2533
- const rows = resp.volumes ?? [];
2534
- return rows.map(parseVolumeInfo);
2535
- } finally {
2536
- client.close();
2537
- }
2529
+ const client = getSharedClient(config);
2530
+ const resp = await client.get("/volumes", {
2531
+ timeout: opts?.requestTimeout
2532
+ });
2533
+ const rows = resp.volumes ?? [];
2534
+ return rows.map(parseVolumeInfo);
2538
2535
  }
2539
2536
  /** Delete a volume and its blob. Idempotent on the wire. */
2540
2537
  static async delete(volumeId, opts) {
@@ -2545,12 +2542,8 @@ var Volumes = class {
2545
2542
  apiUrl: opts?.apiUrl,
2546
2543
  requestTimeout: opts?.requestTimeout
2547
2544
  });
2548
- const client = new ApiClient(config);
2549
- try {
2550
- await client.delete(`/volumes/${volumeId}`, { timeout: opts?.requestTimeout });
2551
- } finally {
2552
- client.close();
2553
- }
2545
+ const client = getSharedClient(config);
2546
+ await client.delete(`/volumes/${volumeId}`, { timeout: opts?.requestTimeout });
2554
2547
  }
2555
2548
  };
2556
2549
  export {
@@ -2603,6 +2596,7 @@ export {
2603
2596
  createToxicityConfig,
2604
2597
  createTransformationRule,
2605
2598
  domainMatches,
2599
+ getSharedClient,
2606
2600
  invisibleTextConfigToJSON,
2607
2601
  isSensitive,
2608
2602
  networkPolicyToOpts,
@@ -2630,6 +2624,7 @@ export {
2630
2624
  parseVolumeInfo,
2631
2625
  parseWriteInfo,
2632
2626
  requiresTlsInterception,
2627
+ resetSharedClients,
2633
2628
  securityPolicyToJSON,
2634
2629
  toxicityConfigToJSON,
2635
2630
  validateNetworkEntry,