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

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";
@@ -280,6 +281,10 @@ export interface ReportSandbox extends QueuedInfo {
280
281
  sandbox_id: string;
281
282
  state: SandboxState;
282
283
  attempt?: number;
284
+ /** `PROMIGENCE_INDEX`: its place in the run, from 0. Absent when the run's command set it itself. */
285
+ index?: number;
286
+ /** `PROMIGENCE_SEED`: the number its commands were given. Absent when the run's command set it itself. */
287
+ seed?: number;
283
288
  queued_ms?: number;
284
289
  ready_ms?: number;
285
290
  e2e_ms?: number;
@@ -319,11 +324,16 @@ export interface RunReport {
319
324
  snapshot_id?: string;
320
325
  alias?: string;
321
326
  labels?: Record<string, string>;
327
+ /**
328
+ * What the run asked for. `network` is `"allow"` for a run behind an allowlist, whose hosts are
329
+ * `allow` (a service before it said `"egress"` for one).
330
+ */
322
331
  requested?: {
323
332
  count: number;
324
333
  timeout_ms: number;
325
334
  verify_each: boolean;
326
- network: NetworkMode;
335
+ network: NetworkMode | "allow";
336
+ allow?: string[];
327
337
  allow_partial: boolean;
328
338
  secrets?: string[];
329
339
  grade?: GradeSpec;
@@ -437,13 +447,19 @@ export interface SnapshotBuild {
437
447
  repo?: string;
438
448
  commit?: string;
439
449
  verification?: Record<string, unknown>;
440
- /** A rejected build names the guard and the measured value; nothing was stored. */
450
+ /**
451
+ * A rejected build names the guard and the measured value; nothing was stored. `log_tail` is
452
+ * your build's own output: for a step of yours that failed (its start command, a setup step, its
453
+ * verify), that step's last lines. `fix`, when present, is what to change.
454
+ */
441
455
  error?: {
442
456
  code?: string;
443
457
  guard?: string;
444
458
  message?: string;
445
459
  values?: number[];
446
460
  stored?: boolean;
461
+ log_tail?: string[];
462
+ fix?: string;
447
463
  } | null;
448
464
  /** Set when an identical build already existed. */
449
465
  deduped?: boolean;
@@ -727,6 +743,10 @@ export interface OrgRecord {
727
743
  projects: number;
728
744
  members: number;
729
745
  created_at: string;
746
+ /** Days command output is kept after a sandbox ends; `null` = the default, 7. */
747
+ output_retention_days?: number | null;
748
+ /** Keep a failed sandbox to reopen where it broke, when a run does not say; absent or `null` = the default. */
749
+ failure_captures?: boolean | null;
730
750
  }
731
751
  export interface ProjectRecord {
732
752
  project_id: string;
@@ -736,8 +756,14 @@ export interface ProjectRecord {
736
756
  keys: number;
737
757
  /** The most the project may bill in a calendar month (UTC); `null` = no cap. */
738
758
  monthly_cap_usd?: number | null;
759
+ /** Days this project's command output is kept after a sandbox ends; `null` = the organization's. */
760
+ output_retention_days?: number | null;
761
+ /** Keep this project's failed sandboxes to reopen, when a run does not say; absent or `null` = the organization's. */
762
+ failure_captures?: boolean | null;
739
763
  created_at: string;
740
764
  }
765
+ /** The longest command output may be kept after a sandbox ends, in days. */
766
+ export declare const OUTPUT_RETENTION_MAX_DAYS = 30;
741
767
  export interface MemberRecord {
742
768
  user_id: string;
743
769
  email: string;
@@ -905,8 +931,10 @@ export interface PricingView {
905
931
  invite_required: boolean;
906
932
  };
907
933
  monthly_fee_usd: number;
908
- /** Usage the monthly fee includes each month, USD. */
934
+ /** Credits the plan adds each paid month, USD. */
909
935
  included_credits_usd: number;
936
+ /** For how many paid months the plan adds `included_credits_usd`; `null` when it adds them every paid month. */
937
+ included_credits_promo_months?: number | null;
910
938
  monthly_minimum_usd: number;
911
939
  }
912
940
  export interface BillingUsage {
@@ -957,6 +985,20 @@ export interface BillingUsage {
957
985
  period_end?: string | null;
958
986
  } | null;
959
987
  upcoming_invoice_error?: string | null;
988
+ /** What the organization's credits can pay for: balance, held, available, the next to expire. */
989
+ credits?: M.BillingCredits;
990
+ /** Auto-reload: when available credits fall below `threshold_usd`, `amount_usd` is added from `card`. */
991
+ auto_reload?: M.AutoReload;
992
+ /** The plan in force, and a renewal payment in trouble. */
993
+ plan_status?: M.PlanStatus;
994
+ /** `credits` (paid from credits bought in advance) or `postpaid` (billed after use, until `switch.at`). */
995
+ model?: string;
996
+ /** For a `postpaid` organization: when it moves to credits, and the credits ready then. */
997
+ switch?: M.BillingSwitch | null;
998
+ /** What this organization can buy now. */
999
+ trust?: M.TrustLimits;
1000
+ /** A hold that refuses new work, and the page that lifts it; `null` when there is none. */
1001
+ hold?: M.BillingHold | null;
960
1002
  [extra: string]: unknown;
961
1003
  }
962
1004
  /** One row of `GET /billing/history`: a credit the organization received, or a payment. */
@@ -1127,8 +1169,9 @@ export interface SandboxPatchResponse {
1127
1169
  /**
1128
1170
  * What the idle rule counts as idle. `"requests"` (the default): nobody has called the sandbox
1129
1171
  * for the window and no command, terminal or SSH session is open. `"activity"`: all of that, and
1130
- * for the whole window nothing inside used CPU or sent or received a byte, and no network
1131
- * connection to the outside is open — for an agent that runs inside the sandbox on its own.
1172
+ * for the whole window the sandbox used under 5% of one core, sent and received no network byte
1173
+ * (disk writes do not count), and no network connection to the outside is open — for an agent
1174
+ * that runs inside the sandbox on its own.
1132
1175
  */
1133
1176
  export type AutoPauseMode = M.AutoPauseMode;
1134
1177
  /** `POST /snapshots/:id/verify` — re-run the recorded `verify` in a fresh fork. */
@@ -1150,7 +1193,7 @@ export interface SnapshotVerifyResponse {
1150
1193
  state: string;
1151
1194
  }>;
1152
1195
  }
1153
- /** `GET /sandboxes/:id/files/stat`. */
1196
+ /** `POST /sandboxes/:id/files/stat`. */
1154
1197
  export interface FileStat {
1155
1198
  path: string;
1156
1199
  size: number;
@@ -1178,7 +1221,7 @@ export interface DirEntry {
1178
1221
  }
1179
1222
  /** An opaque label of how a file request was answered, passed through for support. */
1180
1223
  export type ServedBy = string;
1181
- /** `GET /sandboxes/:id/files/list?path=`. */
1224
+ /** `POST /sandboxes/:id/files/list`. */
1182
1225
  export interface DirListing {
1183
1226
  sandbox_id: string;
1184
1227
  path: string;
@@ -1187,7 +1230,7 @@ export interface DirListing {
1187
1230
  truncated: boolean;
1188
1231
  served_by?: ServedBy;
1189
1232
  }
1190
- /** `?recursive=&depth=&limit=&hidden=` on `files/list`. */
1233
+ /** `recursive`, `depth`, `limit` and `hidden` on `files/list` (sent in the request body). */
1191
1234
  export interface DirListOpts {
1192
1235
  recursive?: boolean;
1193
1236
  /** With `recursive`: how many levels below `path`. Unset = no bound. */
@@ -1207,7 +1250,7 @@ export interface FileInfo {
1207
1250
  is_symlink: boolean;
1208
1251
  served_by?: ServedBy;
1209
1252
  }
1210
- /** One hit of `GET /sandboxes/:id/files/search`. `line`/`text` only for a `contains` search. */
1253
+ /** One hit of `POST /sandboxes/:id/files/search`. `line`/`text` only for a `contains` search. */
1211
1254
  export interface FileMatch {
1212
1255
  path: string;
1213
1256
  line?: number | null;
@@ -1346,6 +1389,8 @@ export interface PortRecord {
1346
1389
  /** The same token as a DNS label, for a wildcard-DNS deployment (`<label>.<suffix>`). */
1347
1390
  host_url_label?: string;
1348
1391
  created_unix_ns?: number;
1392
+ /** When the URL stops working on its own (`ttl_s`); `null` for one that works until revoked. */
1393
+ expires_unix_ns?: number | null;
1349
1394
  }
1350
1395
  /** A key named without its secret (`/me`'s `key`, the key lists). */
1351
1396
  export interface KeyRef {
@@ -1492,6 +1537,12 @@ export interface PromigenceClientOpts {
1492
1537
  */
1493
1538
  onTiming?: (timing: Timing) => void;
1494
1539
  }
1540
+ /** Where a client's key came from: the option, PROMIGENCE_API_KEY (`env`), the stored sign-in, or a fallback. */
1541
+ export interface KeyOrigin {
1542
+ source: "option" | "env" | "stored" | "fallback";
1543
+ /** The stored sign-in's store, for `stored`. */
1544
+ store?: CredentialStore;
1545
+ }
1495
1546
  /** `GET /sandboxes/:id/network`. */
1496
1547
  export interface SandboxNetwork {
1497
1548
  sandbox_id: string;
@@ -1730,6 +1781,11 @@ export interface SnapshotCreateOpts {
1730
1781
  */
1731
1782
  setupUser?: string;
1732
1783
  alias?: string;
1784
+ /**
1785
+ * With `alias`: take the name from the snapshot that has it, which stays, unnamed. Without it, an
1786
+ * alias another snapshot has is refused (`usage`, 400) and nothing is built.
1787
+ */
1788
+ moveAlias?: boolean;
1733
1789
  /**
1734
1790
  * A DEFAULT grader for this snapshot: a run on it with no `grade` of its own uses this one.
1735
1791
  * The same shape as `runs.start({ grade })`.
@@ -1815,11 +1871,12 @@ export declare function credentialsExposure(path: string): string | undefined;
1815
1871
  * `credentialsTrustProblem`).
1816
1872
  */
1817
1873
  export declare function readCredentials(env?: NodeJS.ProcessEnv): Credentials;
1818
- export declare function apiUrlFromCompatUrl(url: string | undefined): string | undefined;
1819
- export declare function apiUrlFromCompatDomain(domain: string | undefined): string | undefined;
1820
- export declare function compatApiKey(key: string | undefined): string | undefined;
1821
1874
  /** Which variable a key came from, for `promigence doctor`. */
1822
1875
  export declare function keyOrigin(env?: NodeJS.ProcessEnv): string | undefined;
1876
+ /** A request with no key found anywhere: none passed, none in the environment, none stored. */
1877
+ export declare const NO_KEY_MESSAGE = "no API key: none was given, PROMIGENCE_API_KEY is not set, and none is stored";
1878
+ /** What a caller of this SDK does about it. */
1879
+ 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.";
1823
1880
  /** `name@sha256:<64 hex>`, optionally with a tag before the `@`: a reference already pinned. */
1824
1881
  export declare const IMAGE_DIGEST_RE: RegExp;
1825
1882
  /**
@@ -1906,6 +1963,8 @@ interface RequestOpts {
1906
1963
  onHeaders?: (headers: Headers) => void;
1907
1964
  /** Extra request headers (e.g. `promigence-replaced-by`). Never the authorization. */
1908
1965
  headers?: Record<string, string>;
1966
+ /** A `POST` that changes nothing (a file read): safe to send twice, so it is retried as a `GET` is. */
1967
+ replayable?: boolean;
1909
1968
  }
1910
1969
  /** One answer's timing ([`PromigenceClient.lastTiming`]). */
1911
1970
  export interface Timing {
@@ -2011,13 +2070,16 @@ export declare class PromigenceClient {
2011
2070
  * artefact must not go through: it would corrupt binary and cost a second copy of a file that
2012
2071
  * can be gigabytes. This reads the body as an `ArrayBuffer` and hands it back untouched.
2013
2072
  * Errors still arrive as JSON, so a non-2xx answer is decoded and mapped the same way.
2073
+ *
2074
+ * `body` is sent as given with its content type (a JSON question, or a `files put` form).
2075
+ * `read`: the request changes nothing, so a refusal is sent again as a `GET` would be.
2014
2076
  */
2015
2077
  private bytes;
2016
2078
  /**
2017
- * `GET` a byte body **without holding it**: each chunk goes to `onChunk` as it arrives, and
2079
+ * Read a byte body **without holding it**: each chunk goes to `onChunk` as it arrives, and
2018
2080
  * the next is not read until `onChunk` has finished with it, so a 10 GiB artefact costs one
2019
- * chunk of memory. Errors arrive
2020
- * as JSON and are mapped exactly as [`bytes`] maps them; a door refusal is sent again.
2081
+ * chunk of memory. A read only (a `POST` carries its question as `body`), so a door refusal
2082
+ * is sent again. Errors arrive as JSON and are mapped exactly as [`bytes`] maps them.
2021
2083
  */
2022
2084
  private stream;
2023
2085
  /**
@@ -2075,7 +2137,7 @@ export declare class PromigenceClient {
2075
2137
  signal?: AbortSignal;
2076
2138
  }): Promise<Outcomes>;
2077
2139
  readonly billing: {
2078
- /** `GET /billing` — plan, card, period, usage, trial, upcoming invoice. */
2140
+ /** `GET /billing` — plan, credits, auto-reload, card, period, usage, trial, the next plan invoice. */
2079
2141
  usage: () => Promise<BillingUsage>;
2080
2142
  /** `GET /me/ledger?limit=N` — the metered rows the month's total is the sum of (one page). */
2081
2143
  ledger: (limit?: number) => Promise<LedgerEntry[]>;
@@ -2097,6 +2159,29 @@ export declare class PromigenceClient {
2097
2159
  limit?: number;
2098
2160
  cursor?: string;
2099
2161
  }) => Promise<Page<BillingHistoryEntry>>;
2162
+ /** `GET /billing/holds` — what each running or paused sandbox holds of the organization's credits. */
2163
+ holds: () => Promise<M.CreditHolds>;
2164
+ /**
2165
+ * `POST /billing/credits` — a payment page to buy credits, from $5, in whole dollars. The credits are
2166
+ * added when the payment goes through: `settleCredits(session_id)` checks it. An owner's full-access key.
2167
+ */
2168
+ buyCredits: (amountUsd: number) => Promise<M.PaymentPage>;
2169
+ /** `POST /billing/credits/:session_id/settle` — check a credits payment and add its credits if it went through. */
2170
+ settleCredits: (sessionId: string) => Promise<M.CreditsSettled>;
2171
+ /** `GET /billing/auto-reload` — the auto-reload settings, and the authorization turning it on asks for. */
2172
+ autoReload: () => Promise<M.AutoReload>;
2173
+ /**
2174
+ * `PUT /billing/auto-reload` — turn auto-reload on or off, or change it. Turning it on, or changing the level or
2175
+ * the amount, needs `authorizationVersion`: the version of the authorization the owner accepted.
2176
+ */
2177
+ setAutoReload: (opts: {
2178
+ on: boolean;
2179
+ thresholdUsd?: number;
2180
+ amountUsd?: number;
2181
+ authorizationVersion?: string;
2182
+ }) => Promise<M.AutoReload>;
2183
+ /** `POST /billing/disputes/:dispute_id/repay` — a payment page to repay a disputed payment. */
2184
+ repayDispute: (disputeId: string) => Promise<M.PaymentPage>;
2100
2185
  /** `POST /billing/checkout` — the hosted page that puts a card on file. */
2101
2186
  checkout: () => Promise<{
2102
2187
  url: string;
@@ -2109,7 +2194,7 @@ export declare class PromigenceClient {
2109
2194
  }>;
2110
2195
  /** `GET /referrals` — your code and its offer, your referrals by status, what they earned. */
2111
2196
  referrals: () => Promise<ReferralStatus>;
2112
- /** `POST /referrals/apply` — apply a referral code (an owner's key, before the first paid invoice). */
2197
+ /** `POST /referrals/apply` — apply a referral code (an owner's key, before the first payment of at least the reward). */
2113
2198
  applyReferral: (code: string) => Promise<ReferralApplied>;
2114
2199
  };
2115
2200
  private group_billing;
@@ -2173,6 +2258,15 @@ export declare class PromigenceClient {
2173
2258
  create: (org: string, name: string) => Promise<ProjectRecord>;
2174
2259
  /** `PATCH /orgs/:org/projects/:project {name}` — rename it (the `default` project keeps its name). */
2175
2260
  rename: (org: string, project: string, name: string) => Promise<ProjectRecord>;
2261
+ /**
2262
+ * `PATCH /orgs/:org/projects/:project` — rename it, set how long its command output is kept, or
2263
+ * whether its failed sandboxes are kept to reopen (that one on its own). The settings need an owner signed in.
2264
+ */
2265
+ update: (org: string, project: string, update: {
2266
+ name?: string;
2267
+ outputRetentionDays?: number | null;
2268
+ failureCaptures?: boolean | null;
2269
+ }) => Promise<ProjectRecord>;
2176
2270
  };
2177
2271
  };
2178
2272
  private group_orgs;
@@ -2447,6 +2541,10 @@ export declare class PromigenceClient {
2447
2541
  /**
2448
2542
  * Preview URLs for ports inside the sandbox. A URL is a capability — anyone holding it reaches
2449
2543
  * that port — and dies with `revoke`, with a pause, or with the sandbox.
2544
+ *
2545
+ * If your account's preview URLs aren't on, `expose` throws `PreviewsUnavailableError`; write to
2546
+ * support@promigence.ai to have them turned on, and meanwhile reach the port with
2547
+ * `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
2450
2548
  */
2451
2549
  ports: {
2452
2550
  expose: (sandboxId: string, port: number) => Promise<PortRecord>;
@@ -2499,7 +2597,7 @@ export declare class PromigenceClient {
2499
2597
  rows?: number;
2500
2598
  cmd?: string;
2501
2599
  /** Stored secret names, or `{name, as}` bindings, put into the terminal's environment
2502
- * by the server. Names travel in a header; values never leave the service. */
2600
+ * by the server. Names travel inside the terminal's connection; values never leave the service. */
2503
2601
  secrets?: SecretBinding[];
2504
2602
  onData?: (data: Uint8Array) => void;
2505
2603
  onExit?: (exit: PtyExit) => void;
@@ -2544,6 +2642,12 @@ export declare class PromigenceClient {
2544
2642
  optimizeFor?: OptimizeFor;
2545
2643
  spendCap?: number;
2546
2644
  }) => Promise<ResumeResult>;
2645
+ /**
2646
+ * `POST /sandboxes/resume {paused_for: "credits"}` — resume every sandbox paused because credits
2647
+ * ran out. Each resume is checked like new work: the answer lists the sandboxes that resumed and
2648
+ * those that still need credits.
2649
+ */
2650
+ resumePausedForCredits: () => Promise<M.SandboxesResumed>;
2547
2651
  /**
2548
2652
  * `POST /sandboxes/:id/snapshot` — photograph a running sandbox and keep it running.
2549
2653
  *
@@ -2656,8 +2760,9 @@ export declare class PromigenceClient {
2656
2760
  }) => Promise<SandboxPatchResponse>;
2657
2761
  /**
2658
2762
  * `get` streams: the body is handed back as bytes and never parsed, because an eval
2659
- * artefact, a trace or a run log is exactly what this is for. `put` sends the file as the
2660
- * body rather than base64 inside JSON.
2763
+ * artefact, a trace or a run log is exactly what this is for. `put` sends the file's bytes
2764
+ * as they are rather than base64 inside JSON. A file's path, a name pattern and a search
2765
+ * text travel in the request body, never in the URL.
2661
2766
  */
2662
2767
  files: {
2663
2768
  /**
@@ -2744,7 +2849,7 @@ export declare class PromigenceClient {
2744
2849
  /**
2745
2850
  * Write a file of **any size**, in [`FILE_PUT_CHUNK_BYTES`] requests.
2746
2851
  *
2747
- * Chunk 0 goes without `?offset=`, which means "this is the file" (create, truncate);
2852
+ * Chunk 0 goes without an `offset`, which means "this is the file" (create, truncate);
2748
2853
  * every later chunk carries one, which appends, so a file has no size limit here.
2749
2854
  *
2750
2855
  * A failure mid-loop leaves a **prefix** in the sandbox, not a corrupt file. Re-running the
@@ -2979,8 +3084,14 @@ export declare class PromigenceClient {
2979
3084
  alias?: string | null;
2980
3085
  deleted: boolean;
2981
3086
  }>;
2982
- /** `PUT /snapshots/:id/alias` — the sidecar's one mutable field. */
2983
- alias: (idOrAlias: string, alias: string | null) => Promise<SnapshotRecord>;
3087
+ /**
3088
+ * `PUT /snapshots/:id/alias` — the sidecar's one mutable field. A name another snapshot
3089
+ * has is refused (`usage`, 400) unless `moveAlias: true`, which takes it; that one stays,
3090
+ * unnamed.
3091
+ */
3092
+ alias: (idOrAlias: string, alias: string | null, opts?: {
3093
+ moveAlias?: boolean;
3094
+ }) => Promise<SnapshotRecord>;
2984
3095
  /**
2985
3096
  * Wait for a build to leave `running`, bounded by `waitTimeoutMs` (default 100 s).
2986
3097
  *