@promigence/sdk 0.1.0-beta.15 → 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/caller.js CHANGED
@@ -3,7 +3,7 @@ export const CALLER_ENV = "PROMIGENCE_CALLER";
3
3
  export const CALLER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,31}$/;
4
4
  export const CALLER_VERSION_RE = /^[A-Za-z0-9.+_~-]{0,31}$/;
5
5
  export const RESERVED_CALLERS = [
6
- "cli", "harbor", "inspect", "e2b-compat", "computesdk", "mcp",
6
+ "cli", "harbor", "inspect", "computesdk", "mcp",
7
7
  ];
8
8
  let globalCaller;
9
9
  let defaultCaller;
@@ -13,7 +13,7 @@ exports.CALLER_ENV = "PROMIGENCE_CALLER";
13
13
  exports.CALLER_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,31}$/;
14
14
  exports.CALLER_VERSION_RE = /^[A-Za-z0-9.+_~-]{0,31}$/;
15
15
  exports.RESERVED_CALLERS = [
16
- "cli", "harbor", "inspect", "e2b-compat", "computesdk", "mcp",
16
+ "cli", "harbor", "inspect", "computesdk", "mcp",
17
17
  ];
18
18
  let globalCaller;
19
19
  let defaultCaller;
@@ -2,6 +2,7 @@
2
2
  import { inspect, type InspectOptions } from "node:util";
3
3
  import { PromigenceError, type CommandResult, type NetworkMode, type OptimizeFor, type Tier } from "./core.js";
4
4
  import { type Bundle } from "./bundle.js";
5
+ import { type CredentialStore } from "./credstore.js";
5
6
  import { type PtyExit, type PtySession } from "./pty.js";
6
7
  import { type SshTunnel } from "./ssh.js";
7
8
  import type * as M from "./models.gen.js";
@@ -177,6 +178,8 @@ export interface SandboxRef extends QueuedInfo {
177
178
  }
178
179
  /** How a grader's result is read. */
179
180
  export type ScoreMode = M.ScoreMode;
181
+ /** Which of a run's sandboxes are kept to reopen where they ended (`RunStartOpts.capture`). */
182
+ export type CaptureMode = M.CaptureMode;
180
183
  /**
181
184
  * Score the agent's work after the episode, in a clean copy of the snapshot with the agent's
182
185
  * changes applied. `holdout_cmd` is your own second test set; the report carries the gap
@@ -280,6 +283,10 @@ export interface ReportSandbox extends QueuedInfo {
280
283
  sandbox_id: string;
281
284
  state: SandboxState;
282
285
  attempt?: number;
286
+ /** `PROMIGENCE_INDEX`: its place in the run, from 0. Absent when the run's command set it itself. */
287
+ index?: number;
288
+ /** `PROMIGENCE_SEED`: the number its commands were given. Absent when the run's command set it itself. */
289
+ seed?: number;
283
290
  queued_ms?: number;
284
291
  ready_ms?: number;
285
292
  e2e_ms?: number;
@@ -319,11 +326,16 @@ export interface RunReport {
319
326
  snapshot_id?: string;
320
327
  alias?: string;
321
328
  labels?: Record<string, string>;
329
+ /**
330
+ * What the run asked for. `network` is `"allow"` for a run behind an allowlist, whose hosts are
331
+ * `allow` (a service before it said `"egress"` for one).
332
+ */
322
333
  requested?: {
323
334
  count: number;
324
335
  timeout_ms: number;
325
336
  verify_each: boolean;
326
- network: NetworkMode;
337
+ network: NetworkMode | "allow";
338
+ allow?: string[];
327
339
  allow_partial: boolean;
328
340
  secrets?: string[];
329
341
  grade?: GradeSpec;
@@ -386,6 +398,12 @@ export interface SecretRecord {
386
398
  raw?: "allowed" | "refused";
387
399
  /** Whether the value is kept out of the bound hosts' answers (present when `hosts` is). */
388
400
  scan_responses?: boolean;
401
+ /**
402
+ * On `secrets.set` only: things to know about the value just stored, one `code: sentence` each;
403
+ * absent when there are none. `api_key_value`: the value holds an API key of this service, which
404
+ * any command in a sandbox given this secret can use.
405
+ */
406
+ warnings?: string[];
389
407
  }
390
408
  /**
391
409
  * `secrets.set` options: bind the secret to hosts. Requests a sandbox sends to the host's address
@@ -437,13 +455,19 @@ export interface SnapshotBuild {
437
455
  repo?: string;
438
456
  commit?: string;
439
457
  verification?: Record<string, unknown>;
440
- /** A rejected build names the guard and the measured value; nothing was stored. */
458
+ /**
459
+ * A rejected build names the guard and the measured value; nothing was stored. `log_tail` is
460
+ * your build's own output: for a step of yours that failed (its start command, a setup step, its
461
+ * verify), that step's last lines. `fix`, when present, is what to change.
462
+ */
441
463
  error?: {
442
464
  code?: string;
443
465
  guard?: string;
444
466
  message?: string;
445
467
  values?: number[];
446
468
  stored?: boolean;
469
+ log_tail?: string[];
470
+ fix?: string;
447
471
  } | null;
448
472
  /** Set when an identical build already existed. */
449
473
  deduped?: boolean;
@@ -729,8 +753,25 @@ export interface OrgRecord {
729
753
  created_at: string;
730
754
  /** Days command output is kept after a sandbox ends; `null` = the default, 7. */
731
755
  output_retention_days?: number | null;
732
- /** Keep a failed sandbox to reopen where it broke, when a run does not say; absent or `null` = the default. */
756
+ /**
757
+ * This organization's choice: keep a failed sandbox to reopen where it broke, when a run does not say (`capture`);
758
+ * absent or `null` = not chosen, so the default applies: not kept unless the organization or project chose to keep
759
+ * them. What applies is `failure_captures_effective`.
760
+ */
733
761
  failure_captures?: boolean | null;
762
+ /** The length of new preview URLs when a request does not say; absent or `null` = the default, short. */
763
+ preview_link_length?: PreviewLinkLength | null;
764
+ /** What applies to a failed run that does not say: kept or not, and whose choice decided it. */
765
+ failure_captures_effective?: CapturesEffective;
766
+ }
767
+ /**
768
+ * What applies to a failed run's sandboxes when the run does not say (`capture`): `kept`, and `from`, whose choice
769
+ * decided it: `project`, `org`, or `default` (neither chose: not kept unless the organization or project chose to
770
+ * keep them). A run's own `capture` is followed either way.
771
+ */
772
+ export interface CapturesEffective {
773
+ kept: boolean;
774
+ from: "project" | "org" | "default" | (string & {});
734
775
  }
735
776
  export interface ProjectRecord {
736
777
  project_id: string;
@@ -742,8 +783,16 @@ export interface ProjectRecord {
742
783
  monthly_cap_usd?: number | null;
743
784
  /** Days this project's command output is kept after a sandbox ends; `null` = the organization's. */
744
785
  output_retention_days?: number | null;
745
- /** Keep this project's failed sandboxes to reopen, when a run does not say; absent or `null` = the organization's. */
786
+ /**
787
+ * This project's choice: keep its failed sandboxes to reopen, when a run does not say (`capture`); absent or `null` =
788
+ * the organization's choice, and where neither chose, the default: not kept unless the organization or project
789
+ * chose to keep them. What applies is `failure_captures_effective`.
790
+ */
746
791
  failure_captures?: boolean | null;
792
+ /** The length of this project's new preview URLs when a request does not say; absent or `null` = the organization's. */
793
+ preview_link_length?: PreviewLinkLength | null;
794
+ /** What applies to its failed runs that do not say: kept or not, and whose choice decided it. */
795
+ failure_captures_effective?: CapturesEffective;
747
796
  created_at: string;
748
797
  }
749
798
  /** The longest command output may be kept after a sandbox ends, in days. */
@@ -1153,8 +1202,9 @@ export interface SandboxPatchResponse {
1153
1202
  /**
1154
1203
  * What the idle rule counts as idle. `"requests"` (the default): nobody has called the sandbox
1155
1204
  * for the window and no command, terminal or SSH session is open. `"activity"`: all of that, and
1156
- * for the whole window nothing inside used CPU or sent or received a byte, and no network
1157
- * connection to the outside is open — for an agent that runs inside the sandbox on its own.
1205
+ * for the whole window the sandbox used under 5% of one core, sent and received no network byte
1206
+ * (disk writes do not count), and no network connection to the outside is open — for an agent
1207
+ * that runs inside the sandbox on its own.
1158
1208
  */
1159
1209
  export type AutoPauseMode = M.AutoPauseMode;
1160
1210
  /** `POST /snapshots/:id/verify` — re-run the recorded `verify` in a fresh fork. */
@@ -1366,12 +1416,33 @@ export interface SshRevoked {
1366
1416
  export interface PortRecord {
1367
1417
  sandbox_id: string;
1368
1418
  port: number;
1369
- /** 256-bit capability; anyone with the URL reaches the port. */
1419
+ /** The URL's own name: anyone with the URL reaches the port. Pass it to `revoke` to take this one URL down. */
1370
1420
  token: string;
1371
1421
  url: string;
1372
1422
  /** The same token as a DNS label, for a wildcard-DNS deployment (`<label>.<suffix>`). */
1373
1423
  host_url_label?: string;
1374
1424
  created_unix_ns?: number;
1425
+ /** When the URL stops working on its own (`ttl_s`); `null` for one that works until revoked. */
1426
+ expires_unix_ns?: number | null;
1427
+ /**
1428
+ * `"short"` (`https://brave-otter-48213.<domain>/`, the default) or `"long"` (a longer,
1429
+ * harder-to-guess URL, for apps with sensitive data).
1430
+ */
1431
+ length?: PreviewLinkLength;
1432
+ }
1433
+ /**
1434
+ * How long a preview URL is: `"short"` (the default, `https://brave-otter-48213.<domain>/`) or
1435
+ * `"long"` (a longer, harder-to-guess URL, for apps with sensitive data). Custom domains are
1436
+ * coming soon.
1437
+ */
1438
+ export type PreviewLinkLength = "short" | "long";
1439
+ /** Options of `ports.expose`. */
1440
+ export interface PortExposeOpts {
1441
+ /**
1442
+ * `"short"` or `"long"`. Omitted: the length the sandbox's project chose, else its
1443
+ * organization's, else short.
1444
+ */
1445
+ length?: PreviewLinkLength;
1375
1446
  }
1376
1447
  /** A key named without its secret (`/me`'s `key`, the key lists). */
1377
1448
  export interface KeyRef {
@@ -1403,8 +1474,31 @@ export interface MeResponse {
1403
1474
  max_concurrency?: number;
1404
1475
  max_session_s?: number | null;
1405
1476
  max_sandbox_vcpus?: number | null;
1477
+ /** Everything stored together, in GB: snapshots, paused sandboxes and saved failures; `null` for no limit. */
1478
+ max_storage_gb?: number | null;
1479
+ /**
1480
+ * The storage saved failures may use, in GB: when a new one would pass it, the oldest are removed to make room;
1481
+ * `null` for no limit.
1482
+ */
1483
+ max_capture_storage_gb?: number | null;
1484
+ /** Snapshots that may be kept; `null` for no limit. */
1485
+ max_snapshots?: number | null;
1486
+ /** Paused sandboxes that may be kept; `null` for no limit. */
1487
+ max_paused?: number | null;
1406
1488
  [extra: string]: number | null | undefined;
1407
1489
  };
1490
+ /**
1491
+ * What the organisation stores now, in bytes (a GB of `limits` is 2^30 bytes): everything together (`used_bytes`,
1492
+ * against `limits.max_storage_gb`) and its saved failures (`captures_bytes`, against
1493
+ * `limits.max_capture_storage_gb`), with the counts. Absent from a server before it.
1494
+ */
1495
+ storage?: {
1496
+ used_bytes: number;
1497
+ captures_bytes: number;
1498
+ snapshots: number;
1499
+ paused: number;
1500
+ captures: number;
1501
+ } | null;
1408
1502
  /**
1409
1503
  * Sandboxes holding capacity now (queued, starting, ready or running; paused ones hold none)
1410
1504
  * against the limit.
@@ -1518,6 +1612,12 @@ export interface PromigenceClientOpts {
1518
1612
  */
1519
1613
  onTiming?: (timing: Timing) => void;
1520
1614
  }
1615
+ /** Where a client's key came from: the option, PROMIGENCE_API_KEY (`env`), the stored sign-in, or a fallback. */
1616
+ export interface KeyOrigin {
1617
+ source: "option" | "env" | "stored" | "fallback";
1618
+ /** The stored sign-in's store, for `stored`. */
1619
+ store?: CredentialStore;
1620
+ }
1521
1621
  /** `GET /sandboxes/:id/network`. */
1522
1622
  export interface SandboxNetwork {
1523
1623
  sandbox_id: string;
@@ -1578,6 +1678,12 @@ export interface RunStartOpts {
1578
1678
  verifyEach?: boolean;
1579
1679
  network?: NetworkMode;
1580
1680
  optimizeFor?: OptimizeFor;
1681
+ /**
1682
+ * Which of this run's sandboxes are kept to reopen where they ended (`runs.open`): `on_failure`
1683
+ * keeps one whose command failed, `off` keeps none, `always` keeps every one. Left out, the
1684
+ * default applies.
1685
+ */
1686
+ capture?: CaptureMode;
1581
1687
  /**
1582
1688
  * Secrets for every sandbox of this run. An `exec` is no longer required: a run that names
1583
1689
  * its secrets here gives them to every command run against every one of its sandboxes,
@@ -1641,9 +1747,9 @@ export interface ExecOpts {
1641
1747
  */
1642
1748
  secrets?: SecretBinding[];
1643
1749
  /**
1644
- * Cancel an in-flight exec, streamed or not: the client stops waiting and the request is closed,
1645
- * which ends the command in the sandbox. A buffered exec then throws `TimeoutError` ("aborted by
1646
- * the caller's signal"); a streamed one rejects with the signal's `AbortError`.
1750
+ * Cancel an in-flight exec, streamed or not: the client stops waiting and tells the service to
1751
+ * stop the command in the sandbox. A buffered exec then throws `TimeoutError` ("aborted by the
1752
+ * caller's signal"); a streamed one rejects with the signal's `AbortError`.
1647
1753
  */
1648
1754
  signal?: AbortSignal;
1649
1755
  /**
@@ -1756,6 +1862,11 @@ export interface SnapshotCreateOpts {
1756
1862
  */
1757
1863
  setupUser?: string;
1758
1864
  alias?: string;
1865
+ /**
1866
+ * With `alias`: take the name from the snapshot that has it, which stays, unnamed. Without it, an
1867
+ * alias another snapshot has is refused (`usage`, 400) and nothing is built.
1868
+ */
1869
+ moveAlias?: boolean;
1759
1870
  /**
1760
1871
  * A DEFAULT grader for this snapshot: a run on it with no `grade` of its own uses this one.
1761
1872
  * The same shape as `runs.start({ grade })`.
@@ -1841,11 +1952,12 @@ export declare function credentialsExposure(path: string): string | undefined;
1841
1952
  * `credentialsTrustProblem`).
1842
1953
  */
1843
1954
  export declare function readCredentials(env?: NodeJS.ProcessEnv): Credentials;
1844
- export declare function apiUrlFromCompatUrl(url: string | undefined): string | undefined;
1845
- export declare function apiUrlFromCompatDomain(domain: string | undefined): string | undefined;
1846
- export declare function compatApiKey(key: string | undefined): string | undefined;
1847
1955
  /** Which variable a key came from, for `promigence doctor`. */
1848
1956
  export declare function keyOrigin(env?: NodeJS.ProcessEnv): string | undefined;
1957
+ /** A request with no key found anywhere: none passed, none in the environment, none stored. */
1958
+ export declare const NO_KEY_MESSAGE = "no API key: none was given, PROMIGENCE_API_KEY is not set, and none is stored";
1959
+ /** What a caller of this SDK does about it. */
1960
+ export declare const NO_KEY_FIX = "Pass { apiKey } or set PROMIGENCE_API_KEY. No key yet: `promigence login` signs you up or in and stores one.";
1849
1961
  /** `name@sha256:<64 hex>`, optionally with a tag before the `@`: a reference already pinned. */
1850
1962
  export declare const IMAGE_DIGEST_RE: RegExp;
1851
1963
  /**
@@ -2031,6 +2143,9 @@ export declare class PromigenceClient {
2031
2143
  private guardDispatcher;
2032
2144
  private dispatcherFor;
2033
2145
  private againKeyed;
2146
+ private heldExec;
2147
+ private reattachBuffered;
2148
+ private cancelHeldExec;
2034
2149
  request<T>(opts: RequestOpts): Promise<T>;
2035
2150
  /**
2036
2151
  * A request whose body — in either direction — is **bytes, not JSON** (`files get|put`).
@@ -2228,15 +2343,29 @@ export declare class PromigenceClient {
2228
2343
  /** `PATCH /orgs/:org/projects/:project {name}` — rename it (the `default` project keeps its name). */
2229
2344
  rename: (org: string, project: string, name: string) => Promise<ProjectRecord>;
2230
2345
  /**
2231
- * `PATCH /orgs/:org/projects/:project` — rename it, set how long its command output is kept, or
2232
- * whether its failed sandboxes are kept to reopen (that one on its own). The settings need an owner signed in.
2346
+ * `PATCH /orgs/:org/projects/:project` — rename it, set how long its command output is kept,
2347
+ * whether its failed sandboxes are kept to reopen (on its own; `null` = the organization's choice, and
2348
+ * where neither chose, not kept unless the organization or project chose to keep them), or how long
2349
+ * its new preview URLs are (on its own). The settings need an owner signed in.
2233
2350
  */
2234
2351
  update: (org: string, project: string, update: {
2235
2352
  name?: string;
2236
2353
  outputRetentionDays?: number | null;
2237
2354
  failureCaptures?: boolean | null;
2355
+ previewLinkLength?: PreviewLinkLength | null;
2238
2356
  }) => Promise<ProjectRecord>;
2239
2357
  };
2358
+ /**
2359
+ * `PATCH /orgs/:org` — rename it, set how long its command output is kept, whether its failed
2360
+ * sandboxes are kept to reopen, or how long its new preview URLs are (those two each on their
2361
+ * own). The settings need an owner signed in.
2362
+ */
2363
+ update: (org: string, update: {
2364
+ name?: string;
2365
+ outputRetentionDays?: number | null;
2366
+ failureCaptures?: boolean | null;
2367
+ previewLinkLength?: PreviewLinkLength | null;
2368
+ }) => Promise<OrgRecord>;
2240
2369
  };
2241
2370
  private group_orgs;
2242
2371
  readonly credits: {
@@ -2410,7 +2539,13 @@ export declare class PromigenceClient {
2410
2539
  */
2411
2540
  private waitLoop;
2412
2541
  readonly sandboxes: {
2413
- /** `POST /sandboxes/:id/execs` — foreground exec, inline output up to `maxOutputBytes`. */
2542
+ /**
2543
+ * `POST /sandboxes/:id/execs` — foreground exec, inline output up to `maxOutputBytes`.
2544
+ *
2545
+ * If the connection drops while the command runs, the SDK picks the command up again where the
2546
+ * service keeps it and returns its own answer; when it cannot, it throws `ExecLostError`. The
2547
+ * command is never sent a second time.
2548
+ */
2414
2549
  exec: (sandboxId: string, opts: ExecOpts) => Promise<ExecResponse>;
2415
2550
  /**
2416
2551
  * `POST /sandboxes/:id/execs` with `Accept: text/event-stream`.
@@ -2422,6 +2557,10 @@ export declare class PromigenceClient {
2422
2557
  *
2423
2558
  * Uses `fetch`'s streaming body rather than `res.text()`, which is what `request()` does and
2424
2559
  * why it cannot be reused here: `await res.text()` is precisely the buffering this removes.
2560
+ *
2561
+ * If the connection drops while the command runs, the SDK picks the command up again where the
2562
+ * service keeps it, and the stream goes on where it left off; when it cannot, it throws
2563
+ * `ExecLostError`. The command is never sent a second time.
2425
2564
  */
2426
2565
  execStream: (sandboxId: string, opts: ExecOpts, on?: {
2427
2566
  stdout?: (chunk: Uint8Array) => void;
@@ -2510,9 +2649,18 @@ export declare class PromigenceClient {
2510
2649
  /**
2511
2650
  * Preview URLs for ports inside the sandbox. A URL is a capability — anyone holding it reaches
2512
2651
  * that port — and dies with `revoke`, with a pause, or with the sandbox.
2652
+ *
2653
+ * If your account's preview URLs aren't on, `expose` throws `PreviewsUnavailableError`; write to
2654
+ * support@promigence.ai to have them turned on, and meanwhile reach the port with
2655
+ * `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
2513
2656
  */
2514
2657
  ports: {
2515
- expose: (sandboxId: string, port: number) => Promise<PortRecord>;
2658
+ /**
2659
+ * Publish a port: `{ length: "long" }` for a longer, harder-to-guess URL (apps with
2660
+ * sensitive data); omitted, the length the sandbox's project or organization chose
2661
+ * (short by default).
2662
+ */
2663
+ expose: (sandboxId: string, port: number, opts?: PortExposeOpts) => Promise<PortRecord>;
2516
2664
  list: (sandboxId: string) => Promise<PortRecord[]>;
2517
2665
  /** A token revokes that URL; a port number revokes every URL for that port. */
2518
2666
  revoke: (sandboxId: string, tokenOrPort: string | number) => Promise<{
@@ -3049,8 +3197,14 @@ export declare class PromigenceClient {
3049
3197
  alias?: string | null;
3050
3198
  deleted: boolean;
3051
3199
  }>;
3052
- /** `PUT /snapshots/:id/alias` — the sidecar's one mutable field. */
3053
- alias: (idOrAlias: string, alias: string | null) => Promise<SnapshotRecord>;
3200
+ /**
3201
+ * `PUT /snapshots/:id/alias` — the sidecar's one mutable field. A name another snapshot
3202
+ * has is refused (`usage`, 400) unless `moveAlias: true`, which takes it; that one stays,
3203
+ * unnamed.
3204
+ */
3205
+ alias: (idOrAlias: string, alias: string | null, opts?: {
3206
+ moveAlias?: boolean;
3207
+ }) => Promise<SnapshotRecord>;
3054
3208
  /**
3055
3209
  * Wait for a build to leave `running`, bounded by `waitTimeoutMs` (default 100 s).
3056
3210
  *