@promigence/sdk 0.1.0-beta.16 → 0.1.0-beta.17

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/proxy.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { request as httpRequest } from "node:http";
2
2
  import { request as httpsRequest } from "node:https";
3
3
  import { connect as tlsConnect } from "node:tls";
4
- import { Readable } from "node:stream";
4
+ import { Readable, pipeline } from "node:stream";
5
+ import { constants as zlibConstants, createBrotliDecompress, createGunzip } from "node:zlib";
5
6
  import { guardCertChain, makeCertChainGuard } from "./ca-guard.js";
6
7
  function withCertGuard(existing) {
7
8
  return existing === undefined ? guardCertChain : makeCertChainGuard(existing);
@@ -130,7 +131,32 @@ async function bodyOf(init) {
130
131
  return Buffer.from(b);
131
132
  return Buffer.from(await new Response(b).arrayBuffer());
132
133
  }
133
- function toResponse(res) {
134
+ const ACCEPT_ENCODING = "br, gzip";
135
+ function decoded(res) {
136
+ const enc = res.headers["content-encoding"];
137
+ if (typeof enc !== "string")
138
+ return res;
139
+ const steps = [];
140
+ for (const c of enc.toLowerCase().split(",").map((s) => s.trim()).reverse()) {
141
+ if (c === "" || c === "identity")
142
+ continue;
143
+ if (c === "gzip" || c === "x-gzip") {
144
+ steps.push(createGunzip({ flush: zlibConstants.Z_SYNC_FLUSH, finishFlush: zlibConstants.Z_SYNC_FLUSH }));
145
+ }
146
+ else if (c === "br") {
147
+ steps.push(createBrotliDecompress({
148
+ flush: zlibConstants.BROTLI_OPERATION_FLUSH, finishFlush: zlibConstants.BROTLI_OPERATION_FLUSH,
149
+ }));
150
+ }
151
+ else {
152
+ return res;
153
+ }
154
+ }
155
+ if (steps.length === 0)
156
+ return res;
157
+ return pipeline([res, ...steps], () => { });
158
+ }
159
+ function toResponse(res, head) {
134
160
  const headers = new Headers();
135
161
  for (const [k, v] of Object.entries(res.headers)) {
136
162
  if (v === undefined)
@@ -143,7 +169,8 @@ function toResponse(res) {
143
169
  }
144
170
  const status = res.statusCode ?? 502;
145
171
  const noBody = status === 204 || status === 304;
146
- return new Response(noBody ? null : Readable.toWeb(res), {
172
+ const body = head ? res : decoded(res);
173
+ return new Response(noBody ? null : Readable.toWeb(body), {
147
174
  status, statusText: res.statusMessage ?? "", headers,
148
175
  });
149
176
  }
@@ -156,6 +183,8 @@ export function proxyFetch(proxy) {
156
183
  const url = new URL(typeof input === "string" ? input : input instanceof URL ? input.href : input.url);
157
184
  const method = (init?.method ?? "GET").toUpperCase();
158
185
  const headers = headersOf(init);
186
+ if (headers["accept-encoding"] === undefined)
187
+ headers["accept-encoding"] = ACCEPT_ENCODING;
159
188
  const body = await bodyOf(init);
160
189
  if (body)
161
190
  headers["content-length"] = String(body.length);
@@ -178,7 +207,7 @@ export function proxyFetch(proxy) {
178
207
  const done = (res) => {
179
208
  settled = true;
180
209
  signal?.removeEventListener("abort", onAbort);
181
- resolve(toResponse(res));
210
+ resolve(toResponse(res, method === "HEAD"));
182
211
  };
183
212
  if (url.protocol === "http:") {
184
213
  const req = proxyRequest({
package/dist/sandbox.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { inspect, type InspectOptions } from "node:util";
13
13
  import { type CommandResult, type CommandRunOpts, type ForkOpts, type OptimizeFor, type SandboxOpts, type Tier } from "./core.js";
14
- import { PromigenceClient, type BackgroundExecRecord, type DirEntry, type DirListOpts, type ExtractResult, type FileInfo, type FileMatch, type Page, type PortRecord, type AutoPauseMode, type SandboxRecord, type SearchOpts, type SecretBinding, type SnapshotBuild, type VerifySpec } from "./client.js";
14
+ import { PromigenceClient, type BackgroundExecRecord, type DirEntry, type DirListOpts, type ExtractResult, type FileInfo, type FileMatch, type Page, type PortExposeOpts, type PortRecord, type AutoPauseMode, type SandboxRecord, type SearchOpts, type SecretBinding, type SnapshotBuild, type VerifySpec } from "./client.js";
15
15
  import { CommandHandle } from "./handles.js";
16
16
  import type { PtyExit, PtySession, PtySize } from "./pty.js";
17
17
  /** `setTimeout`'s fix when the longer timeout does not fit under the run's spend cap. */
@@ -289,6 +289,7 @@ export declare class Sandbox {
289
289
  /**
290
290
  * Run `cmd` and resolve with its result. A non-zero exit throws `CommandExitError`; a command
291
291
  * killed at its own `timeoutMs` throws `CommandTimeoutError` (a `CommandExitError` too).
292
+ * With `throwOnExit: false` both resolve instead, and the result's `timedOut` tells them apart.
292
293
  */
293
294
  run(cmd: string, opts?: ForegroundRunOpts): Promise<CommandResult>;
294
295
  /** Background commands in this sandbox (running and ended, until killed with forget). */
@@ -325,7 +326,11 @@ export declare class Sandbox {
325
326
  * `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
326
327
  */
327
328
  readonly ports: {
328
- expose(port: number): Promise<PortRecord>;
329
+ /**
330
+ * Publish `port`: `{ length: "long" }` for a longer, harder-to-guess URL (apps with sensitive
331
+ * data); omitted, the length this sandbox's project or organization chose (short by default).
332
+ */
333
+ expose(port: number, opts?: PortExposeOpts): Promise<PortRecord>;
329
334
  list(): Promise<PortRecord[]>;
330
335
  /** A token revokes that URL; a port number every URL for it. Returns the revoked tokens. */
331
336
  revoke(tokenOrPort: string | number): Promise<string[]>;
@@ -490,8 +495,9 @@ export declare class Sandbox {
490
495
  * the window may be. Bring it back with `resume()`, which is the warm path.
491
496
  *
492
497
  * `mode: "activity"` is for an agent that runs inside the sandbox on its own: it also waits
493
- * until nothing inside has used CPU, moved a byte or held a connection open for the window
494
- * (`AutoPauseMode`). Omitted, the mode is left as it is (`"requests"` unless set).
498
+ * until, for the whole window, the sandbox has used under 5% of one core, sent and received no
499
+ * network byte and held no connection out open; disk writes do not count (`AutoPauseMode`).
500
+ * Omitted, the mode is left as it is (`"requests"` unless set).
495
501
  */
496
502
  setAutoPause(seconds: number, mode?: AutoPauseMode): Promise<void>;
497
503
  /** The idle rule in force: seconds before it pauses itself, `0` when it never does. */
@@ -513,7 +519,8 @@ export declare class Sandbox {
513
519
  * full `url` with its scheme.
514
520
  *
515
521
  * Async, because the address is a capability minted on demand rather than
516
- * a hostname derived from the id. An existing URL for the port is reused, not re-minted.
522
+ * a hostname derived from the id. An existing URL for the port is reused, not re-minted; a new
523
+ * one has the length this sandbox's project or organization chose (short by default).
517
524
  *
518
525
  * If your account's preview URLs aren't on, this throws `PreviewsUnavailableError`; write to
519
526
  * support@promigence.ai to have them turned on, and meanwhile reach the port with
package/dist/sandbox.js CHANGED
@@ -361,7 +361,7 @@ export class Sandbox {
361
361
  },
362
362
  };
363
363
  this.ports = {
364
- expose: (port) => this.#client.sandboxes.ports.expose(this.sandboxId, port),
364
+ expose: (port, opts) => this.#client.sandboxes.ports.expose(this.sandboxId, port, opts),
365
365
  list: () => this.#client.sandboxes.ports.list(this.sandboxId),
366
366
  revoke: async (tokenOrPort) => (await this.#client.sandboxes.ports.revoke(this.sandboxId, tokenOrPort)).revoked,
367
367
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promigence/sdk",
3
- "version": "0.1.0-beta.16",
3
+ "version": "0.1.0-beta.17",
4
4
  "description": "The fastest sandboxes for AI agents and code. The Promigence TypeScript SDK: snapshot an environment once, fork it as often as you need, run commands in every copy. A simple Sandbox class and the full PromigenceClient, with zero runtime dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://www.promigence.ai",