@promigence/sdk 0.1.0-beta.8 → 0.1.0-beta.9
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/cjs/client.d.ts +29 -6
- package/dist/cjs/client.js +10 -2
- package/dist/cjs/core.d.ts +8 -6
- package/dist/cjs/core.js +2 -2
- package/dist/cjs/github.d.ts +1 -1
- package/dist/cjs/gitlab.d.ts +1 -1
- package/dist/cjs/models.gen.d.ts +79 -16
- package/dist/cjs/sandbox.d.ts +9 -10
- package/dist/cjs/sandbox.js +7 -3
- package/dist/client.d.ts +29 -6
- package/dist/client.js +10 -2
- package/dist/core.d.ts +8 -6
- package/dist/core.js +2 -2
- package/dist/github.d.ts +1 -1
- package/dist/gitlab.d.ts +1 -1
- package/dist/models.gen.d.ts +79 -16
- package/dist/sandbox.d.ts +9 -10
- package/dist/sandbox.js +7 -3
- package/package.json +1 -1
package/dist/cjs/client.d.ts
CHANGED
|
@@ -420,7 +420,19 @@ export interface SnapshotBuild {
|
|
|
420
420
|
/** `true` when the snapshot this build made has since been deleted. */
|
|
421
421
|
snapshot_deleted?: boolean;
|
|
422
422
|
tier_assigned?: string;
|
|
423
|
+
/**
|
|
424
|
+
* The most the build can cost, USD, said before it runs: `max_seconds` at `per_second_usd`. A build
|
|
425
|
+
* is billed per second for the time it runs; what it cost is `cost_usd` once it has ended.
|
|
426
|
+
*/
|
|
423
427
|
build_price?: number;
|
|
428
|
+
/** What one second of the build costs, USD: its tier's per-second rate. */
|
|
429
|
+
per_second_usd?: number;
|
|
430
|
+
/** The longest the build may run, in seconds: it is billed for at most this long. */
|
|
431
|
+
max_seconds?: number;
|
|
432
|
+
/** Once it has ended, the seconds it is billed for; 0 when it failed on our side. */
|
|
433
|
+
billable_seconds?: number;
|
|
434
|
+
/** Once it has ended, what it cost, USD; 0 when nothing was charged. */
|
|
435
|
+
cost_usd?: number;
|
|
424
436
|
repo?: string;
|
|
425
437
|
commit?: string;
|
|
426
438
|
verification?: Record<string, unknown>;
|
|
@@ -847,7 +859,10 @@ export interface PricingView {
|
|
|
847
859
|
gib_second_usd: number;
|
|
848
860
|
preemptible_vcpu_second_usd: number;
|
|
849
861
|
preemptible_gib_second_usd: number;
|
|
850
|
-
/**
|
|
862
|
+
/**
|
|
863
|
+
* The most one snapshot build of the default tier can cost (`limits.build_max_s` seconds at that
|
|
864
|
+
* tier's rate). A build is billed per second at its own tier's rate for the time it runs.
|
|
865
|
+
*/
|
|
851
866
|
build_usd: number;
|
|
852
867
|
/** Per GiB of data out above the month's allowance; `null` when not priced. */
|
|
853
868
|
egress_gb_usd: number | null;
|
|
@@ -872,6 +887,8 @@ export interface PricingView {
|
|
|
872
887
|
max_egress_gb_month: number | null;
|
|
873
888
|
/** Outbound mail ports open. */
|
|
874
889
|
smtp: boolean;
|
|
890
|
+
/** The longest a snapshot build may run, in seconds: the most one build is billed for. */
|
|
891
|
+
build_max_s?: number;
|
|
875
892
|
};
|
|
876
893
|
/** The free credit a new account gets (an account's own: `GET /credits/offer`). */
|
|
877
894
|
free_credit: {
|
|
@@ -1447,7 +1464,11 @@ export interface PromigenceClientOpts {
|
|
|
1447
1464
|
* From the CLI: `promigence --request-timeout DUR` or `PROMIGENCE_REQUEST_TIMEOUT`.
|
|
1448
1465
|
*/
|
|
1449
1466
|
requestTimeoutMs?: number;
|
|
1450
|
-
/**
|
|
1467
|
+
/**
|
|
1468
|
+
* How many times a request is sent again (default 3): after a 429 or a 503, and after a 502 or
|
|
1469
|
+
* 504 that is not the API's own answer when sending twice is harmless (a read, a delete, or a
|
|
1470
|
+
* create with its idempotency key).
|
|
1471
|
+
*/
|
|
1451
1472
|
maxRetries?: number;
|
|
1452
1473
|
/** Backoff base when the server sends no `Retry-After` (default 250 ms). */
|
|
1453
1474
|
retryBaseMs?: number;
|
|
@@ -1885,7 +1906,7 @@ interface RequestOpts {
|
|
|
1885
1906
|
signal?: AbortSignal;
|
|
1886
1907
|
/** Skip the Authorization header (unauthenticated routes). */
|
|
1887
1908
|
anonymous?: boolean;
|
|
1888
|
-
/** Called with the response headers of the attempt that answered (not of
|
|
1909
|
+
/** Called with the response headers of the attempt that answered (not of one that was retried). */
|
|
1889
1910
|
onHeaders?: (headers: Headers) => void;
|
|
1890
1911
|
/** Extra request headers (e.g. `promigence-replaced-by`). Never the authorization. */
|
|
1891
1912
|
headers?: Record<string, string>;
|
|
@@ -1960,8 +1981,10 @@ export declare class PromigenceClient {
|
|
|
1960
1981
|
* rule `request()` applies, for the calls that cannot go through it (byte transfers, the
|
|
1961
1982
|
* opening of an exec stream, the terminal handshake). Retried: a 429, and a 503 that says
|
|
1962
1983
|
* nothing started — any 503 for a request safe to send twice, else only one carrying a
|
|
1963
|
-
* `Retry-After` (every refusal at the door sets one) or a refusal code
|
|
1964
|
-
*
|
|
1984
|
+
* `Retry-After` (every refusal at the door sets one) or a refusal code — and, for a request
|
|
1985
|
+
* safe to send twice, a 502 or 504 that is not the API's own answer (it carries no error
|
|
1986
|
+
* code). At most `maxRetries` times, and never a `Retry-After` longer than
|
|
1987
|
+
* MAX_RETRY_SLEEP_MS: that one is the caller's.
|
|
1965
1988
|
*/
|
|
1966
1989
|
private refusalBackoff;
|
|
1967
1990
|
/** A long-poll request must outlive its own `wait_ms`; everything else keeps the default. */
|
|
@@ -1998,7 +2021,7 @@ export declare class PromigenceClient {
|
|
|
1998
2021
|
}): Promise<StatusResponse>;
|
|
1999
2022
|
/**
|
|
2000
2023
|
* `GET /pricing` — your organization's price list, live: the per-second rates, every sandbox
|
|
2001
|
-
* shape on sale and its price
|
|
2024
|
+
* shape on sale and its price (a snapshot build bills at its tier's), the limits, the free credit and the plan they
|
|
2002
2025
|
* come from, read on every call from what billing charges. Needs a key: without one this throws
|
|
2003
2026
|
* `AuthError` and sends nothing. The published list prices are on the pricing page.
|
|
2004
2027
|
*
|
package/dist/cjs/client.js
CHANGED
|
@@ -870,7 +870,8 @@ class PromigenceClient {
|
|
|
870
870
|
refusalBackoff(status, retryAfterMs, code, attempt, replayable, signal) {
|
|
871
871
|
if (attempt >= this.maxRetries || signal?.aborted)
|
|
872
872
|
return undefined;
|
|
873
|
-
|
|
873
|
+
const gateway = (status === 502 || status === 504) && replayable && code === undefined;
|
|
874
|
+
if (status !== 429 && status !== 503 && !gateway)
|
|
874
875
|
return undefined;
|
|
875
876
|
if ((retryAfterMs ?? 0) > MAX_RETRY_SLEEP_MS)
|
|
876
877
|
return undefined;
|
|
@@ -993,12 +994,17 @@ class PromigenceClient {
|
|
|
993
994
|
throw new core_js_1.UnreachableError(`cannot reach ${url}: ${transportDetail(e)}`);
|
|
994
995
|
}
|
|
995
996
|
const retryAfterMs = parseRetryAfter(headerOf(res, "retry-after"));
|
|
996
|
-
|
|
997
|
+
const gateway = (res.status === 502 || res.status === 504) && replayable;
|
|
998
|
+
let retryable = (res.status === 429 || res.status === 503 || gateway) && (retryAfterMs ?? 0) <= MAX_RETRY_SLEEP_MS;
|
|
997
999
|
let body;
|
|
998
1000
|
if (retryable && res.status === 503 && !replayable && retryAfterMs === undefined) {
|
|
999
1001
|
body = await res.text().catch(() => "");
|
|
1000
1002
|
retryable = REFUSED_503_CODES.has(errorCodeOf(body) ?? "");
|
|
1001
1003
|
}
|
|
1004
|
+
if (retryable && gateway) {
|
|
1005
|
+
body = await res.text().catch(() => "");
|
|
1006
|
+
retryable = errorCodeOf(body) === undefined;
|
|
1007
|
+
}
|
|
1002
1008
|
if (retryable && attempt < this.maxRetries) {
|
|
1003
1009
|
const backoff = Math.min(MAX_RETRY_SLEEP_MS, this.retryBaseMs * 2 ** attempt);
|
|
1004
1010
|
const jitter = Math.random();
|
|
@@ -1006,6 +1012,8 @@ class PromigenceClient {
|
|
|
1006
1012
|
? retryAfterMs + jitter * Math.min(250, this.retryBaseMs)
|
|
1007
1013
|
: backoff * (0.5 + jitter * 0.5);
|
|
1008
1014
|
this.stats.retries++;
|
|
1015
|
+
if (gateway && opts.method === "DELETE")
|
|
1016
|
+
resentDelete = true;
|
|
1009
1017
|
if (body === undefined)
|
|
1010
1018
|
try {
|
|
1011
1019
|
await res.text();
|
package/dist/cjs/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Promigence SDK — constants, error hierarchy and shared types. */
|
|
2
|
-
export declare const VERSION = "0.1.0-beta.
|
|
2
|
+
export declare const VERSION = "0.1.0-beta.9";
|
|
3
3
|
export declare const DOCS_URL = "https://promigence.ai";
|
|
4
4
|
/** The error reference; each code is an anchor on it (the API's `docs` link has the same form). */
|
|
5
5
|
export declare const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
|
@@ -14,12 +14,14 @@ export declare const WAIT_TIMEOUT_MS = 100000;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const IMAGE_BUILD_TIMEOUT_MS: number;
|
|
16
16
|
/**
|
|
17
|
-
* The
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* The most one new snapshot build of the default tier can cost at the list prices this SDK was
|
|
18
|
+
* built with, in USD: its time limit (an hour) at that tier's per-second rate. A build is billed per
|
|
19
|
+
* second for the time it runs; reusing or joining an identical build is free. Prices change: the
|
|
20
|
+
* live figure is `client.pricing()`'s `rates.build_usd` (this key's organization's), and a build's
|
|
21
|
+
* own arrives as `build_price` in the `POST /snapshots` answer. This is only the fallback when the
|
|
22
|
+
* API cannot be asked.
|
|
21
23
|
*/
|
|
22
|
-
export declare const IMAGE_BUILD_LIST_PRICE =
|
|
24
|
+
export declare const IMAGE_BUILD_LIST_PRICE = 0.1656;
|
|
23
25
|
/** Inline output budget for an exec before `truncated` + `_ref`. */
|
|
24
26
|
export declare const MAX_OUTPUT_BYTES_DEFAULT: number;
|
|
25
27
|
/** One request of a `files.put`. **Not a file-size limit** — `put` loops. */
|
package/dist/cjs/core.js
CHANGED
|
@@ -7,14 +7,14 @@ exports.fixBeyondMessage = fixBeyondMessage;
|
|
|
7
7
|
exports.previewsOff = previewsOff;
|
|
8
8
|
exports.exitForCode = exitForCode;
|
|
9
9
|
const hint_js_1 = require("./hint.js");
|
|
10
|
-
exports.VERSION = "0.1.0-beta.
|
|
10
|
+
exports.VERSION = "0.1.0-beta.9";
|
|
11
11
|
exports.DOCS_URL = "https://promigence.ai";
|
|
12
12
|
exports.ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
|
13
13
|
exports.DEFAULT_API_URL = "https://api.promigence.ai/v1";
|
|
14
14
|
exports.KEY_CONTACT = "support@promigence.ai";
|
|
15
15
|
exports.WAIT_TIMEOUT_MS = 100_000;
|
|
16
16
|
exports.IMAGE_BUILD_TIMEOUT_MS = 15 * 60_000;
|
|
17
|
-
exports.IMAGE_BUILD_LIST_PRICE =
|
|
17
|
+
exports.IMAGE_BUILD_LIST_PRICE = 0.1656;
|
|
18
18
|
exports.MAX_OUTPUT_BYTES_DEFAULT = 64 * 1024;
|
|
19
19
|
exports.FILE_PUT_CHUNK_BYTES = 16 * 1024 * 1024;
|
|
20
20
|
const PREVIEWS_OFF = /^previews are not enabled on this deployment\.?$/i;
|
package/dist/cjs/github.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface GithubPending {
|
|
|
34
34
|
state: string;
|
|
35
35
|
message: string;
|
|
36
36
|
}
|
|
37
|
-
/** A snapshot that follows a branch: every push builds it again (
|
|
37
|
+
/** A snapshot that follows a branch: every push builds it again (each build billed per second). */
|
|
38
38
|
export interface GithubTrack {
|
|
39
39
|
track_id: string;
|
|
40
40
|
repo: string;
|
package/dist/cjs/gitlab.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface GitlabPending {
|
|
|
37
37
|
expires_at: string;
|
|
38
38
|
message: string;
|
|
39
39
|
}
|
|
40
|
-
/** A snapshot that follows a GitLab branch: each new commit builds it again (
|
|
40
|
+
/** A snapshot that follows a GitLab branch: each new commit builds it again (each build billed per second). */
|
|
41
41
|
export interface GitlabTrack {
|
|
42
42
|
track_id: string;
|
|
43
43
|
repo: string;
|
package/dist/cjs/models.gen.d.ts
CHANGED
|
@@ -346,16 +346,29 @@ export interface BuildJoined {
|
|
|
346
346
|
alias?: string | null;
|
|
347
347
|
alias_applied?: boolean | null;
|
|
348
348
|
/**
|
|
349
|
-
* The alias that was asked for, when the
|
|
350
|
-
* `
|
|
349
|
+
* The alias that was asked for, when the build in progress was to carry another, or none.
|
|
350
|
+
* The build carries it now (`alias_applied: true`) and its snapshot is stored under it;
|
|
351
|
+
* `warnings` names the alias the build was to carry.
|
|
351
352
|
*/
|
|
352
353
|
alias_requested?: string | null;
|
|
354
|
+
/**
|
|
355
|
+
* Once the build has ended, the seconds it is billed for: the time it ran, whether it was
|
|
356
|
+
* stored, its own `setup` or `verify` failed, or it ran to its time limit; 0 when it failed
|
|
357
|
+
* on our side. Absent while it is queued or running, and for a build priced per build.
|
|
358
|
+
*/
|
|
359
|
+
billable_seconds?: number | null;
|
|
353
360
|
build_id: string;
|
|
354
361
|
/**
|
|
355
|
-
*
|
|
362
|
+
* The most the build can cost, in USD, as said when it was started: `max_seconds` at
|
|
363
|
+
* `per_second_usd`. What it was billed is `cost_usd`.
|
|
356
364
|
*/
|
|
357
365
|
build_price: number;
|
|
358
366
|
commit: string;
|
|
367
|
+
/**
|
|
368
|
+
* Once the build has ended, what it cost in USD; 0 when nothing was charged. Absent while it
|
|
369
|
+
* is queued or running.
|
|
370
|
+
*/
|
|
371
|
+
cost_usd?: number | null;
|
|
359
372
|
/**
|
|
360
373
|
* RFC 3339.
|
|
361
374
|
*/
|
|
@@ -378,10 +391,20 @@ export interface BuildJoined {
|
|
|
378
391
|
* Always true here.
|
|
379
392
|
*/
|
|
380
393
|
joined: boolean;
|
|
394
|
+
/**
|
|
395
|
+
* The longest the build may run, in seconds: it is billed for at most this long. Absent for
|
|
396
|
+
* a build priced per build.
|
|
397
|
+
*/
|
|
398
|
+
max_seconds?: number | null;
|
|
381
399
|
/**
|
|
382
400
|
* What to do next, ready to run.
|
|
383
401
|
*/
|
|
384
402
|
next: Array<string>;
|
|
403
|
+
/**
|
|
404
|
+
* What one second of the build costs, in USD: its tier's per-second rate. Absent for a build
|
|
405
|
+
* priced per build, before builds were billed per second.
|
|
406
|
+
*/
|
|
407
|
+
per_second_usd?: number | null;
|
|
385
408
|
repo: string;
|
|
386
409
|
setup: Array<string>;
|
|
387
410
|
/**
|
|
@@ -412,8 +435,8 @@ export interface BuildJoined {
|
|
|
412
435
|
/**
|
|
413
436
|
* True when the build finished `verified` and its verification command passed. False while
|
|
414
437
|
* it is queued or running, when it failed or was rejected, and for an image built without
|
|
415
|
-
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored
|
|
416
|
-
*
|
|
438
|
+
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored if the
|
|
439
|
+
* command exits non-zero; the time the build ran is billed.
|
|
417
440
|
*/
|
|
418
441
|
verified: boolean;
|
|
419
442
|
/**
|
|
@@ -455,7 +478,8 @@ export interface BuildQueued {
|
|
|
455
478
|
alias?: string | null;
|
|
456
479
|
build_id: string;
|
|
457
480
|
/**
|
|
458
|
-
*
|
|
481
|
+
* The most the build can cost, in USD, said before it runs: `max_seconds` at
|
|
482
|
+
* `per_second_usd`. It is billed per second for the time it runs.
|
|
459
483
|
*/
|
|
460
484
|
build_price: number;
|
|
461
485
|
commit: string;
|
|
@@ -469,10 +493,18 @@ export interface BuildQueued {
|
|
|
469
493
|
* given, so a client can say which earlier request this repeats.
|
|
470
494
|
*/
|
|
471
495
|
idempotent_replay_age_s?: number | null;
|
|
496
|
+
/**
|
|
497
|
+
* The longest the build may run, in seconds: it is billed for at most this long.
|
|
498
|
+
*/
|
|
499
|
+
max_seconds?: number | null;
|
|
472
500
|
/**
|
|
473
501
|
* What to do next, ready to run.
|
|
474
502
|
*/
|
|
475
503
|
next: Array<string>;
|
|
504
|
+
/**
|
|
505
|
+
* What one second of the build costs, in USD: its tier's per-second rate.
|
|
506
|
+
*/
|
|
507
|
+
per_second_usd?: number | null;
|
|
476
508
|
repo: string;
|
|
477
509
|
/**
|
|
478
510
|
* What it is being built from. The `kind` field says which of the three forms it is.
|
|
@@ -511,12 +543,24 @@ export interface BuildView {
|
|
|
511
543
|
* the snapshot is deleted: the name may belong to another snapshot by then.
|
|
512
544
|
*/
|
|
513
545
|
alias?: string | null;
|
|
546
|
+
/**
|
|
547
|
+
* Once the build has ended, the seconds it is billed for: the time it ran, whether it was
|
|
548
|
+
* stored, its own `setup` or `verify` failed, or it ran to its time limit; 0 when it failed
|
|
549
|
+
* on our side. Absent while it is queued or running, and for a build priced per build.
|
|
550
|
+
*/
|
|
551
|
+
billable_seconds?: number | null;
|
|
514
552
|
build_id: string;
|
|
515
553
|
/**
|
|
516
|
-
*
|
|
554
|
+
* The most the build can cost, in USD, as said when it was started: `max_seconds` at
|
|
555
|
+
* `per_second_usd`. What it was billed is `cost_usd`.
|
|
517
556
|
*/
|
|
518
557
|
build_price: number;
|
|
519
558
|
commit: string;
|
|
559
|
+
/**
|
|
560
|
+
* Once the build has ended, what it cost in USD; 0 when nothing was charged. Absent while it
|
|
561
|
+
* is queued or running.
|
|
562
|
+
*/
|
|
563
|
+
cost_usd?: number | null;
|
|
520
564
|
/**
|
|
521
565
|
* RFC 3339.
|
|
522
566
|
*/
|
|
@@ -529,10 +573,20 @@ export interface BuildView {
|
|
|
529
573
|
* RFC 3339.
|
|
530
574
|
*/
|
|
531
575
|
finished_at?: string | null;
|
|
576
|
+
/**
|
|
577
|
+
* The longest the build may run, in seconds: it is billed for at most this long. Absent for
|
|
578
|
+
* a build priced per build.
|
|
579
|
+
*/
|
|
580
|
+
max_seconds?: number | null;
|
|
532
581
|
/**
|
|
533
582
|
* What to do next, ready to run.
|
|
534
583
|
*/
|
|
535
584
|
next: Array<string>;
|
|
585
|
+
/**
|
|
586
|
+
* What one second of the build costs, in USD: its tier's per-second rate. Absent for a build
|
|
587
|
+
* priced per build, before builds were billed per second.
|
|
588
|
+
*/
|
|
589
|
+
per_second_usd?: number | null;
|
|
536
590
|
repo: string;
|
|
537
591
|
setup: Array<string>;
|
|
538
592
|
/**
|
|
@@ -563,8 +617,8 @@ export interface BuildView {
|
|
|
563
617
|
/**
|
|
564
618
|
* True when the build finished `verified` and its verification command passed. False while
|
|
565
619
|
* it is queued or running, when it failed or was rejected, and for an image built without
|
|
566
|
-
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored
|
|
567
|
-
*
|
|
620
|
+
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored if the
|
|
621
|
+
* command exits non-zero; the time the build ran is billed.
|
|
568
622
|
*/
|
|
569
623
|
verified: boolean;
|
|
570
624
|
/**
|
|
@@ -2460,7 +2514,7 @@ export interface LedgerEntryView {
|
|
|
2460
2514
|
*/
|
|
2461
2515
|
seconds: number;
|
|
2462
2516
|
/**
|
|
2463
|
-
* What was charged: a sandbox id or a build id.
|
|
2517
|
+
* What was charged: a sandbox id or a build id; for credit, what it is for (e.g. "Credit from Promigence").
|
|
2464
2518
|
*/
|
|
2465
2519
|
subject: string;
|
|
2466
2520
|
tier: string;
|
|
@@ -3103,6 +3157,11 @@ export interface PricingFreeCredit {
|
|
|
3103
3157
|
* The limits in force.
|
|
3104
3158
|
*/
|
|
3105
3159
|
export interface PricingLimits {
|
|
3160
|
+
/**
|
|
3161
|
+
* The longest a snapshot build may run, in seconds, and so the most seconds one build is
|
|
3162
|
+
* billed for.
|
|
3163
|
+
*/
|
|
3164
|
+
build_max_s?: number | null;
|
|
3106
3165
|
/**
|
|
3107
3166
|
* A sandbox's timeout when its run names none, in seconds.
|
|
3108
3167
|
*/
|
|
@@ -3161,8 +3220,11 @@ export interface PricingPlan {
|
|
|
3161
3220
|
*/
|
|
3162
3221
|
export interface PricingRates {
|
|
3163
3222
|
/**
|
|
3164
|
-
*
|
|
3165
|
-
*
|
|
3223
|
+
* The most one snapshot build of the default tier can cost: `limits.build_max_s` seconds at
|
|
3224
|
+
* that tier's per-second rate. A build is billed per second at its own tier's rate (`tiers`)
|
|
3225
|
+
* for the time it runs, whether it is stored, its own `setup` or `verify` fails, or it runs to
|
|
3226
|
+
* its time limit; a failure on our side, and reusing or joining an identical build, cost
|
|
3227
|
+
* nothing.
|
|
3166
3228
|
*/
|
|
3167
3229
|
build_usd: number;
|
|
3168
3230
|
/**
|
|
@@ -5201,8 +5263,7 @@ export interface SnapshotCreate {
|
|
|
5201
5263
|
*/
|
|
5202
5264
|
export type SnapshotCreated = BuildQueued | BuildJoined | SnapshotDeduped;
|
|
5203
5265
|
/**
|
|
5204
|
-
* Inputs that are already built: the existing snapshot,
|
|
5205
|
-
* for could be applied to it.
|
|
5266
|
+
* Inputs that are already built: the existing snapshot, named with the alias that was asked for.
|
|
5206
5267
|
*/
|
|
5207
5268
|
export interface SnapshotDeduped {
|
|
5208
5269
|
/**
|
|
@@ -5211,8 +5272,10 @@ export interface SnapshotDeduped {
|
|
|
5211
5272
|
alias?: string | null;
|
|
5212
5273
|
alias_applied?: boolean | null;
|
|
5213
5274
|
/**
|
|
5214
|
-
* The alias that was asked for, when
|
|
5215
|
-
*
|
|
5275
|
+
* The alias that was asked for, when the snapshot did not hold it. The snapshot takes it
|
|
5276
|
+
* (`alias_applied: true`) as a new build would: another snapshot of the project that had it
|
|
5277
|
+
* keeps its row, without a name. A snapshot has one alias, so a name it had before gives
|
|
5278
|
+
* way, and `warnings` says which.
|
|
5216
5279
|
*/
|
|
5217
5280
|
alias_requested?: string | null;
|
|
5218
5281
|
/**
|
package/dist/cjs/sandbox.d.ts
CHANGED
|
@@ -136,7 +136,7 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
136
136
|
/**
|
|
137
137
|
* A container image instead of a snapshot — a tag (`python:3.12`, pinned to its digest by the
|
|
138
138
|
* API) or `registry/name@sha256:<64 hex>`: the snapshot of this image is built on first use
|
|
139
|
-
* (a new build is
|
|
139
|
+
* (a new build is billed per second while it runs, at its tier's rate, `client.pricing()`; pass
|
|
140
140
|
* `allowBuild: true` to allow it) and
|
|
141
141
|
* reused after (same digest + same inputs → the same snapshot). A name with no tag or digest is
|
|
142
142
|
* refused: it would pin whatever `:latest` is today. The fields below shape that snapshot and
|
|
@@ -156,17 +156,17 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
156
156
|
buildTimeoutMs?: number;
|
|
157
157
|
/**
|
|
158
158
|
* Let `Sandbox.create({ image })` build the image's snapshot when none exists yet. A new build
|
|
159
|
-
*
|
|
160
|
-
* is free. Without it, a create from an image is refused before anything is sent: whether the
|
|
159
|
+
* is billed per second while it runs, at most `build_price` (your plan's rates, `client.pricing()`);
|
|
160
|
+
* reusing a snapshot already built is free. Without it, a create from an image is refused before anything is sent: whether the
|
|
161
161
|
* image's snapshot exists is only known once a build is submitted, and a submitted build cannot
|
|
162
162
|
* be withdrawn. The other way to pay once and on purpose: `promigence snapshot create --image
|
|
163
163
|
* REF --alias NAME`, then `Sandbox.create("NAME")`.
|
|
164
164
|
*/
|
|
165
165
|
allowBuild?: boolean;
|
|
166
166
|
/**
|
|
167
|
-
* Called with the `POST /snapshots` answer before any wait: `build_price
|
|
168
|
-
* `joined` when nothing new is charged. Without it,
|
|
169
|
-
* process warning (stderr) before the build is waited for.
|
|
167
|
+
* Called with the `POST /snapshots` answer before any wait: `build_price` (the most the build can
|
|
168
|
+
* cost) and `per_second_usd`, and `deduped` or `joined` when nothing new is charged. Without it,
|
|
169
|
+
* a new build's price is reported as a process warning (stderr) before the build is waited for.
|
|
170
170
|
*/
|
|
171
171
|
onBuild?: (build: SnapshotBuild) => void | Promise<void>;
|
|
172
172
|
/**
|
|
@@ -198,9 +198,8 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
198
198
|
*/
|
|
199
199
|
export declare function imageSnapshot(client: PromigenceClient, opts: Pick<SandboxCreateOpts, "image" | "setup" | "verify" | "start" | "tier" | "alias" | "registrySecret" | "buildTimeoutMs">, hooks?: {
|
|
200
200
|
/**
|
|
201
|
-
* The `POST /snapshots` answer, before any wait: `build_price`
|
|
202
|
-
* or `joined` (nothing new charged). An implicit build costs money, so a caller
|
|
203
|
-
* that prints prices prints this one too.
|
|
201
|
+
* The `POST /snapshots` answer, before any wait: `build_price` (the most it can cost) and
|
|
202
|
+
* whether it was `deduped` or `joined` (nothing new charged). An implicit build costs money, so a caller that prints prices prints this one too.
|
|
204
203
|
*/
|
|
205
204
|
onBuild?: (build: SnapshotBuild) => void | Promise<void>;
|
|
206
205
|
/** Ends the wait for a build at once; the build itself, once submitted, is not withdrawn. */
|
|
@@ -375,7 +374,7 @@ export declare class Sandbox {
|
|
|
375
374
|
/**
|
|
376
375
|
* Fork of 1 from a snapshot (`snap_<id>` | `<alias>` | `<alias>@<commit7>`), or from the
|
|
377
376
|
* snapshot of an image: `Sandbox.create({ image: 'python:3.12', allowBuild: true })` builds it
|
|
378
|
-
* on first use (a new build at
|
|
377
|
+
* on first use (a new build billed per second at its tier's rate, bounded by `buildTimeoutMs`, default 15 min) and reuses it
|
|
379
378
|
* free after. An image needs `allowBuild: true` and a tag or digest; without either it is
|
|
380
379
|
* refused before any request.
|
|
381
380
|
*
|
package/dist/cjs/sandbox.js
CHANGED
|
@@ -75,12 +75,16 @@ function buildNotice(image) {
|
|
|
75
75
|
return (b) => {
|
|
76
76
|
if (buildIsFree(b))
|
|
77
77
|
return;
|
|
78
|
-
const price = typeof b.build_price === "number"
|
|
79
|
-
|
|
78
|
+
const price = typeof b.build_price === "number"
|
|
79
|
+
? typeof b.per_second_usd === "number"
|
|
80
|
+
? `billed per second while it builds ($${Number(b.per_second_usd.toPrecision(12))}/s), at most $${b.build_price.toFixed(2)}`
|
|
81
|
+
: `build_price $${b.build_price.toFixed(2)}, charged once it verifies`
|
|
82
|
+
: "billed at your plan's rates";
|
|
83
|
+
process.emitWarning(`building a snapshot of ${image}: ${price} (later creates from this image reuse it free)`, { code: "PROMIGENCE_BUILD" });
|
|
80
84
|
};
|
|
81
85
|
}
|
|
82
86
|
function buildNotAllowed(image) {
|
|
83
|
-
return new core_js_1.InvalidArgumentError(`Sandbox.create({ image: ${JSON.stringify(image)} }) builds that image's snapshot unless one already exists, and a new build is
|
|
87
|
+
return new core_js_1.InvalidArgumentError(`Sandbox.create({ image: ${JSON.stringify(image)} }) builds that image's snapshot unless one already exists, and a new build is billed per second while it runs (\`promigence pricing\` shows the rates; reusing a snapshot already built is free). Nothing was sent.`, `To allow the build: Sandbox.create({ image: ${JSON.stringify(image)}, allowBuild: true }). Or build it once, ` +
|
|
84
88
|
`\`promigence snapshot create --image ${(0, hint_js_1.hintArg)(image)} --alias NAME\`, and create from its name: Sandbox.create("NAME").`);
|
|
85
89
|
}
|
|
86
90
|
async function imageSnapshot(client, opts, hooks = {}) {
|
package/dist/client.d.ts
CHANGED
|
@@ -420,7 +420,19 @@ export interface SnapshotBuild {
|
|
|
420
420
|
/** `true` when the snapshot this build made has since been deleted. */
|
|
421
421
|
snapshot_deleted?: boolean;
|
|
422
422
|
tier_assigned?: string;
|
|
423
|
+
/**
|
|
424
|
+
* The most the build can cost, USD, said before it runs: `max_seconds` at `per_second_usd`. A build
|
|
425
|
+
* is billed per second for the time it runs; what it cost is `cost_usd` once it has ended.
|
|
426
|
+
*/
|
|
423
427
|
build_price?: number;
|
|
428
|
+
/** What one second of the build costs, USD: its tier's per-second rate. */
|
|
429
|
+
per_second_usd?: number;
|
|
430
|
+
/** The longest the build may run, in seconds: it is billed for at most this long. */
|
|
431
|
+
max_seconds?: number;
|
|
432
|
+
/** Once it has ended, the seconds it is billed for; 0 when it failed on our side. */
|
|
433
|
+
billable_seconds?: number;
|
|
434
|
+
/** Once it has ended, what it cost, USD; 0 when nothing was charged. */
|
|
435
|
+
cost_usd?: number;
|
|
424
436
|
repo?: string;
|
|
425
437
|
commit?: string;
|
|
426
438
|
verification?: Record<string, unknown>;
|
|
@@ -847,7 +859,10 @@ export interface PricingView {
|
|
|
847
859
|
gib_second_usd: number;
|
|
848
860
|
preemptible_vcpu_second_usd: number;
|
|
849
861
|
preemptible_gib_second_usd: number;
|
|
850
|
-
/**
|
|
862
|
+
/**
|
|
863
|
+
* The most one snapshot build of the default tier can cost (`limits.build_max_s` seconds at that
|
|
864
|
+
* tier's rate). A build is billed per second at its own tier's rate for the time it runs.
|
|
865
|
+
*/
|
|
851
866
|
build_usd: number;
|
|
852
867
|
/** Per GiB of data out above the month's allowance; `null` when not priced. */
|
|
853
868
|
egress_gb_usd: number | null;
|
|
@@ -872,6 +887,8 @@ export interface PricingView {
|
|
|
872
887
|
max_egress_gb_month: number | null;
|
|
873
888
|
/** Outbound mail ports open. */
|
|
874
889
|
smtp: boolean;
|
|
890
|
+
/** The longest a snapshot build may run, in seconds: the most one build is billed for. */
|
|
891
|
+
build_max_s?: number;
|
|
875
892
|
};
|
|
876
893
|
/** The free credit a new account gets (an account's own: `GET /credits/offer`). */
|
|
877
894
|
free_credit: {
|
|
@@ -1447,7 +1464,11 @@ export interface PromigenceClientOpts {
|
|
|
1447
1464
|
* From the CLI: `promigence --request-timeout DUR` or `PROMIGENCE_REQUEST_TIMEOUT`.
|
|
1448
1465
|
*/
|
|
1449
1466
|
requestTimeoutMs?: number;
|
|
1450
|
-
/**
|
|
1467
|
+
/**
|
|
1468
|
+
* How many times a request is sent again (default 3): after a 429 or a 503, and after a 502 or
|
|
1469
|
+
* 504 that is not the API's own answer when sending twice is harmless (a read, a delete, or a
|
|
1470
|
+
* create with its idempotency key).
|
|
1471
|
+
*/
|
|
1451
1472
|
maxRetries?: number;
|
|
1452
1473
|
/** Backoff base when the server sends no `Retry-After` (default 250 ms). */
|
|
1453
1474
|
retryBaseMs?: number;
|
|
@@ -1885,7 +1906,7 @@ interface RequestOpts {
|
|
|
1885
1906
|
signal?: AbortSignal;
|
|
1886
1907
|
/** Skip the Authorization header (unauthenticated routes). */
|
|
1887
1908
|
anonymous?: boolean;
|
|
1888
|
-
/** Called with the response headers of the attempt that answered (not of
|
|
1909
|
+
/** Called with the response headers of the attempt that answered (not of one that was retried). */
|
|
1889
1910
|
onHeaders?: (headers: Headers) => void;
|
|
1890
1911
|
/** Extra request headers (e.g. `promigence-replaced-by`). Never the authorization. */
|
|
1891
1912
|
headers?: Record<string, string>;
|
|
@@ -1960,8 +1981,10 @@ export declare class PromigenceClient {
|
|
|
1960
1981
|
* rule `request()` applies, for the calls that cannot go through it (byte transfers, the
|
|
1961
1982
|
* opening of an exec stream, the terminal handshake). Retried: a 429, and a 503 that says
|
|
1962
1983
|
* nothing started — any 503 for a request safe to send twice, else only one carrying a
|
|
1963
|
-
* `Retry-After` (every refusal at the door sets one) or a refusal code
|
|
1964
|
-
*
|
|
1984
|
+
* `Retry-After` (every refusal at the door sets one) or a refusal code — and, for a request
|
|
1985
|
+
* safe to send twice, a 502 or 504 that is not the API's own answer (it carries no error
|
|
1986
|
+
* code). At most `maxRetries` times, and never a `Retry-After` longer than
|
|
1987
|
+
* MAX_RETRY_SLEEP_MS: that one is the caller's.
|
|
1965
1988
|
*/
|
|
1966
1989
|
private refusalBackoff;
|
|
1967
1990
|
/** A long-poll request must outlive its own `wait_ms`; everything else keeps the default. */
|
|
@@ -1998,7 +2021,7 @@ export declare class PromigenceClient {
|
|
|
1998
2021
|
}): Promise<StatusResponse>;
|
|
1999
2022
|
/**
|
|
2000
2023
|
* `GET /pricing` — your organization's price list, live: the per-second rates, every sandbox
|
|
2001
|
-
* shape on sale and its price
|
|
2024
|
+
* shape on sale and its price (a snapshot build bills at its tier's), the limits, the free credit and the plan they
|
|
2002
2025
|
* come from, read on every call from what billing charges. Needs a key: without one this throws
|
|
2003
2026
|
* `AuthError` and sends nothing. The published list prices are on the pricing page.
|
|
2004
2027
|
*
|
package/dist/client.js
CHANGED
|
@@ -837,7 +837,8 @@ export class PromigenceClient {
|
|
|
837
837
|
refusalBackoff(status, retryAfterMs, code, attempt, replayable, signal) {
|
|
838
838
|
if (attempt >= this.maxRetries || signal?.aborted)
|
|
839
839
|
return undefined;
|
|
840
|
-
|
|
840
|
+
const gateway = (status === 502 || status === 504) && replayable && code === undefined;
|
|
841
|
+
if (status !== 429 && status !== 503 && !gateway)
|
|
841
842
|
return undefined;
|
|
842
843
|
if ((retryAfterMs ?? 0) > MAX_RETRY_SLEEP_MS)
|
|
843
844
|
return undefined;
|
|
@@ -960,12 +961,17 @@ export class PromigenceClient {
|
|
|
960
961
|
throw new UnreachableError(`cannot reach ${url}: ${transportDetail(e)}`);
|
|
961
962
|
}
|
|
962
963
|
const retryAfterMs = parseRetryAfter(headerOf(res, "retry-after"));
|
|
963
|
-
|
|
964
|
+
const gateway = (res.status === 502 || res.status === 504) && replayable;
|
|
965
|
+
let retryable = (res.status === 429 || res.status === 503 || gateway) && (retryAfterMs ?? 0) <= MAX_RETRY_SLEEP_MS;
|
|
964
966
|
let body;
|
|
965
967
|
if (retryable && res.status === 503 && !replayable && retryAfterMs === undefined) {
|
|
966
968
|
body = await res.text().catch(() => "");
|
|
967
969
|
retryable = REFUSED_503_CODES.has(errorCodeOf(body) ?? "");
|
|
968
970
|
}
|
|
971
|
+
if (retryable && gateway) {
|
|
972
|
+
body = await res.text().catch(() => "");
|
|
973
|
+
retryable = errorCodeOf(body) === undefined;
|
|
974
|
+
}
|
|
969
975
|
if (retryable && attempt < this.maxRetries) {
|
|
970
976
|
const backoff = Math.min(MAX_RETRY_SLEEP_MS, this.retryBaseMs * 2 ** attempt);
|
|
971
977
|
const jitter = Math.random();
|
|
@@ -973,6 +979,8 @@ export class PromigenceClient {
|
|
|
973
979
|
? retryAfterMs + jitter * Math.min(250, this.retryBaseMs)
|
|
974
980
|
: backoff * (0.5 + jitter * 0.5);
|
|
975
981
|
this.stats.retries++;
|
|
982
|
+
if (gateway && opts.method === "DELETE")
|
|
983
|
+
resentDelete = true;
|
|
976
984
|
if (body === undefined)
|
|
977
985
|
try {
|
|
978
986
|
await res.text();
|
package/dist/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Promigence SDK — constants, error hierarchy and shared types. */
|
|
2
|
-
export declare const VERSION = "0.1.0-beta.
|
|
2
|
+
export declare const VERSION = "0.1.0-beta.9";
|
|
3
3
|
export declare const DOCS_URL = "https://promigence.ai";
|
|
4
4
|
/** The error reference; each code is an anchor on it (the API's `docs` link has the same form). */
|
|
5
5
|
export declare const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
|
@@ -14,12 +14,14 @@ export declare const WAIT_TIMEOUT_MS = 100000;
|
|
|
14
14
|
*/
|
|
15
15
|
export declare const IMAGE_BUILD_TIMEOUT_MS: number;
|
|
16
16
|
/**
|
|
17
|
-
* The
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* The most one new snapshot build of the default tier can cost at the list prices this SDK was
|
|
18
|
+
* built with, in USD: its time limit (an hour) at that tier's per-second rate. A build is billed per
|
|
19
|
+
* second for the time it runs; reusing or joining an identical build is free. Prices change: the
|
|
20
|
+
* live figure is `client.pricing()`'s `rates.build_usd` (this key's organization's), and a build's
|
|
21
|
+
* own arrives as `build_price` in the `POST /snapshots` answer. This is only the fallback when the
|
|
22
|
+
* API cannot be asked.
|
|
21
23
|
*/
|
|
22
|
-
export declare const IMAGE_BUILD_LIST_PRICE =
|
|
24
|
+
export declare const IMAGE_BUILD_LIST_PRICE = 0.1656;
|
|
23
25
|
/** Inline output budget for an exec before `truncated` + `_ref`. */
|
|
24
26
|
export declare const MAX_OUTPUT_BYTES_DEFAULT: number;
|
|
25
27
|
/** One request of a `files.put`. **Not a file-size limit** — `put` loops. */
|
package/dist/core.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { hintArg } from "./hint.js";
|
|
2
|
-
export const VERSION = "0.1.0-beta.
|
|
2
|
+
export const VERSION = "0.1.0-beta.9";
|
|
3
3
|
export const DOCS_URL = "https://promigence.ai";
|
|
4
4
|
export const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
|
5
5
|
export const DEFAULT_API_URL = "https://api.promigence.ai/v1";
|
|
6
6
|
export const KEY_CONTACT = "support@promigence.ai";
|
|
7
7
|
export const WAIT_TIMEOUT_MS = 100_000;
|
|
8
8
|
export const IMAGE_BUILD_TIMEOUT_MS = 15 * 60_000;
|
|
9
|
-
export const IMAGE_BUILD_LIST_PRICE =
|
|
9
|
+
export const IMAGE_BUILD_LIST_PRICE = 0.1656;
|
|
10
10
|
export const MAX_OUTPUT_BYTES_DEFAULT = 64 * 1024;
|
|
11
11
|
export const FILE_PUT_CHUNK_BYTES = 16 * 1024 * 1024;
|
|
12
12
|
const PREVIEWS_OFF = /^previews are not enabled on this deployment\.?$/i;
|
package/dist/github.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface GithubPending {
|
|
|
34
34
|
state: string;
|
|
35
35
|
message: string;
|
|
36
36
|
}
|
|
37
|
-
/** A snapshot that follows a branch: every push builds it again (
|
|
37
|
+
/** A snapshot that follows a branch: every push builds it again (each build billed per second). */
|
|
38
38
|
export interface GithubTrack {
|
|
39
39
|
track_id: string;
|
|
40
40
|
repo: string;
|
package/dist/gitlab.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface GitlabPending {
|
|
|
37
37
|
expires_at: string;
|
|
38
38
|
message: string;
|
|
39
39
|
}
|
|
40
|
-
/** A snapshot that follows a GitLab branch: each new commit builds it again (
|
|
40
|
+
/** A snapshot that follows a GitLab branch: each new commit builds it again (each build billed per second). */
|
|
41
41
|
export interface GitlabTrack {
|
|
42
42
|
track_id: string;
|
|
43
43
|
repo: string;
|
package/dist/models.gen.d.ts
CHANGED
|
@@ -346,16 +346,29 @@ export interface BuildJoined {
|
|
|
346
346
|
alias?: string | null;
|
|
347
347
|
alias_applied?: boolean | null;
|
|
348
348
|
/**
|
|
349
|
-
* The alias that was asked for, when the
|
|
350
|
-
* `
|
|
349
|
+
* The alias that was asked for, when the build in progress was to carry another, or none.
|
|
350
|
+
* The build carries it now (`alias_applied: true`) and its snapshot is stored under it;
|
|
351
|
+
* `warnings` names the alias the build was to carry.
|
|
351
352
|
*/
|
|
352
353
|
alias_requested?: string | null;
|
|
354
|
+
/**
|
|
355
|
+
* Once the build has ended, the seconds it is billed for: the time it ran, whether it was
|
|
356
|
+
* stored, its own `setup` or `verify` failed, or it ran to its time limit; 0 when it failed
|
|
357
|
+
* on our side. Absent while it is queued or running, and for a build priced per build.
|
|
358
|
+
*/
|
|
359
|
+
billable_seconds?: number | null;
|
|
353
360
|
build_id: string;
|
|
354
361
|
/**
|
|
355
|
-
*
|
|
362
|
+
* The most the build can cost, in USD, as said when it was started: `max_seconds` at
|
|
363
|
+
* `per_second_usd`. What it was billed is `cost_usd`.
|
|
356
364
|
*/
|
|
357
365
|
build_price: number;
|
|
358
366
|
commit: string;
|
|
367
|
+
/**
|
|
368
|
+
* Once the build has ended, what it cost in USD; 0 when nothing was charged. Absent while it
|
|
369
|
+
* is queued or running.
|
|
370
|
+
*/
|
|
371
|
+
cost_usd?: number | null;
|
|
359
372
|
/**
|
|
360
373
|
* RFC 3339.
|
|
361
374
|
*/
|
|
@@ -378,10 +391,20 @@ export interface BuildJoined {
|
|
|
378
391
|
* Always true here.
|
|
379
392
|
*/
|
|
380
393
|
joined: boolean;
|
|
394
|
+
/**
|
|
395
|
+
* The longest the build may run, in seconds: it is billed for at most this long. Absent for
|
|
396
|
+
* a build priced per build.
|
|
397
|
+
*/
|
|
398
|
+
max_seconds?: number | null;
|
|
381
399
|
/**
|
|
382
400
|
* What to do next, ready to run.
|
|
383
401
|
*/
|
|
384
402
|
next: Array<string>;
|
|
403
|
+
/**
|
|
404
|
+
* What one second of the build costs, in USD: its tier's per-second rate. Absent for a build
|
|
405
|
+
* priced per build, before builds were billed per second.
|
|
406
|
+
*/
|
|
407
|
+
per_second_usd?: number | null;
|
|
385
408
|
repo: string;
|
|
386
409
|
setup: Array<string>;
|
|
387
410
|
/**
|
|
@@ -412,8 +435,8 @@ export interface BuildJoined {
|
|
|
412
435
|
/**
|
|
413
436
|
* True when the build finished `verified` and its verification command passed. False while
|
|
414
437
|
* it is queued or running, when it failed or was rejected, and for an image built without
|
|
415
|
-
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored
|
|
416
|
-
*
|
|
438
|
+
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored if the
|
|
439
|
+
* command exits non-zero; the time the build ran is billed.
|
|
417
440
|
*/
|
|
418
441
|
verified: boolean;
|
|
419
442
|
/**
|
|
@@ -455,7 +478,8 @@ export interface BuildQueued {
|
|
|
455
478
|
alias?: string | null;
|
|
456
479
|
build_id: string;
|
|
457
480
|
/**
|
|
458
|
-
*
|
|
481
|
+
* The most the build can cost, in USD, said before it runs: `max_seconds` at
|
|
482
|
+
* `per_second_usd`. It is billed per second for the time it runs.
|
|
459
483
|
*/
|
|
460
484
|
build_price: number;
|
|
461
485
|
commit: string;
|
|
@@ -469,10 +493,18 @@ export interface BuildQueued {
|
|
|
469
493
|
* given, so a client can say which earlier request this repeats.
|
|
470
494
|
*/
|
|
471
495
|
idempotent_replay_age_s?: number | null;
|
|
496
|
+
/**
|
|
497
|
+
* The longest the build may run, in seconds: it is billed for at most this long.
|
|
498
|
+
*/
|
|
499
|
+
max_seconds?: number | null;
|
|
472
500
|
/**
|
|
473
501
|
* What to do next, ready to run.
|
|
474
502
|
*/
|
|
475
503
|
next: Array<string>;
|
|
504
|
+
/**
|
|
505
|
+
* What one second of the build costs, in USD: its tier's per-second rate.
|
|
506
|
+
*/
|
|
507
|
+
per_second_usd?: number | null;
|
|
476
508
|
repo: string;
|
|
477
509
|
/**
|
|
478
510
|
* What it is being built from. The `kind` field says which of the three forms it is.
|
|
@@ -511,12 +543,24 @@ export interface BuildView {
|
|
|
511
543
|
* the snapshot is deleted: the name may belong to another snapshot by then.
|
|
512
544
|
*/
|
|
513
545
|
alias?: string | null;
|
|
546
|
+
/**
|
|
547
|
+
* Once the build has ended, the seconds it is billed for: the time it ran, whether it was
|
|
548
|
+
* stored, its own `setup` or `verify` failed, or it ran to its time limit; 0 when it failed
|
|
549
|
+
* on our side. Absent while it is queued or running, and for a build priced per build.
|
|
550
|
+
*/
|
|
551
|
+
billable_seconds?: number | null;
|
|
514
552
|
build_id: string;
|
|
515
553
|
/**
|
|
516
|
-
*
|
|
554
|
+
* The most the build can cost, in USD, as said when it was started: `max_seconds` at
|
|
555
|
+
* `per_second_usd`. What it was billed is `cost_usd`.
|
|
517
556
|
*/
|
|
518
557
|
build_price: number;
|
|
519
558
|
commit: string;
|
|
559
|
+
/**
|
|
560
|
+
* Once the build has ended, what it cost in USD; 0 when nothing was charged. Absent while it
|
|
561
|
+
* is queued or running.
|
|
562
|
+
*/
|
|
563
|
+
cost_usd?: number | null;
|
|
520
564
|
/**
|
|
521
565
|
* RFC 3339.
|
|
522
566
|
*/
|
|
@@ -529,10 +573,20 @@ export interface BuildView {
|
|
|
529
573
|
* RFC 3339.
|
|
530
574
|
*/
|
|
531
575
|
finished_at?: string | null;
|
|
576
|
+
/**
|
|
577
|
+
* The longest the build may run, in seconds: it is billed for at most this long. Absent for
|
|
578
|
+
* a build priced per build.
|
|
579
|
+
*/
|
|
580
|
+
max_seconds?: number | null;
|
|
532
581
|
/**
|
|
533
582
|
* What to do next, ready to run.
|
|
534
583
|
*/
|
|
535
584
|
next: Array<string>;
|
|
585
|
+
/**
|
|
586
|
+
* What one second of the build costs, in USD: its tier's per-second rate. Absent for a build
|
|
587
|
+
* priced per build, before builds were billed per second.
|
|
588
|
+
*/
|
|
589
|
+
per_second_usd?: number | null;
|
|
536
590
|
repo: string;
|
|
537
591
|
setup: Array<string>;
|
|
538
592
|
/**
|
|
@@ -563,8 +617,8 @@ export interface BuildView {
|
|
|
563
617
|
/**
|
|
564
618
|
* True when the build finished `verified` and its verification command passed. False while
|
|
565
619
|
* it is queued or running, when it failed or was rejected, and for an image built without
|
|
566
|
-
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored
|
|
567
|
-
*
|
|
620
|
+
* `verify` (state `built`: stored, but nothing was verified). Nothing is stored if the
|
|
621
|
+
* command exits non-zero; the time the build ran is billed.
|
|
568
622
|
*/
|
|
569
623
|
verified: boolean;
|
|
570
624
|
/**
|
|
@@ -2460,7 +2514,7 @@ export interface LedgerEntryView {
|
|
|
2460
2514
|
*/
|
|
2461
2515
|
seconds: number;
|
|
2462
2516
|
/**
|
|
2463
|
-
* What was charged: a sandbox id or a build id.
|
|
2517
|
+
* What was charged: a sandbox id or a build id; for credit, what it is for (e.g. "Credit from Promigence").
|
|
2464
2518
|
*/
|
|
2465
2519
|
subject: string;
|
|
2466
2520
|
tier: string;
|
|
@@ -3103,6 +3157,11 @@ export interface PricingFreeCredit {
|
|
|
3103
3157
|
* The limits in force.
|
|
3104
3158
|
*/
|
|
3105
3159
|
export interface PricingLimits {
|
|
3160
|
+
/**
|
|
3161
|
+
* The longest a snapshot build may run, in seconds, and so the most seconds one build is
|
|
3162
|
+
* billed for.
|
|
3163
|
+
*/
|
|
3164
|
+
build_max_s?: number | null;
|
|
3106
3165
|
/**
|
|
3107
3166
|
* A sandbox's timeout when its run names none, in seconds.
|
|
3108
3167
|
*/
|
|
@@ -3161,8 +3220,11 @@ export interface PricingPlan {
|
|
|
3161
3220
|
*/
|
|
3162
3221
|
export interface PricingRates {
|
|
3163
3222
|
/**
|
|
3164
|
-
*
|
|
3165
|
-
*
|
|
3223
|
+
* The most one snapshot build of the default tier can cost: `limits.build_max_s` seconds at
|
|
3224
|
+
* that tier's per-second rate. A build is billed per second at its own tier's rate (`tiers`)
|
|
3225
|
+
* for the time it runs, whether it is stored, its own `setup` or `verify` fails, or it runs to
|
|
3226
|
+
* its time limit; a failure on our side, and reusing or joining an identical build, cost
|
|
3227
|
+
* nothing.
|
|
3166
3228
|
*/
|
|
3167
3229
|
build_usd: number;
|
|
3168
3230
|
/**
|
|
@@ -5201,8 +5263,7 @@ export interface SnapshotCreate {
|
|
|
5201
5263
|
*/
|
|
5202
5264
|
export type SnapshotCreated = BuildQueued | BuildJoined | SnapshotDeduped;
|
|
5203
5265
|
/**
|
|
5204
|
-
* Inputs that are already built: the existing snapshot,
|
|
5205
|
-
* for could be applied to it.
|
|
5266
|
+
* Inputs that are already built: the existing snapshot, named with the alias that was asked for.
|
|
5206
5267
|
*/
|
|
5207
5268
|
export interface SnapshotDeduped {
|
|
5208
5269
|
/**
|
|
@@ -5211,8 +5272,10 @@ export interface SnapshotDeduped {
|
|
|
5211
5272
|
alias?: string | null;
|
|
5212
5273
|
alias_applied?: boolean | null;
|
|
5213
5274
|
/**
|
|
5214
|
-
* The alias that was asked for, when
|
|
5215
|
-
*
|
|
5275
|
+
* The alias that was asked for, when the snapshot did not hold it. The snapshot takes it
|
|
5276
|
+
* (`alias_applied: true`) as a new build would: another snapshot of the project that had it
|
|
5277
|
+
* keeps its row, without a name. A snapshot has one alias, so a name it had before gives
|
|
5278
|
+
* way, and `warnings` says which.
|
|
5216
5279
|
*/
|
|
5217
5280
|
alias_requested?: string | null;
|
|
5218
5281
|
/**
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -136,7 +136,7 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
136
136
|
/**
|
|
137
137
|
* A container image instead of a snapshot — a tag (`python:3.12`, pinned to its digest by the
|
|
138
138
|
* API) or `registry/name@sha256:<64 hex>`: the snapshot of this image is built on first use
|
|
139
|
-
* (a new build is
|
|
139
|
+
* (a new build is billed per second while it runs, at its tier's rate, `client.pricing()`; pass
|
|
140
140
|
* `allowBuild: true` to allow it) and
|
|
141
141
|
* reused after (same digest + same inputs → the same snapshot). A name with no tag or digest is
|
|
142
142
|
* refused: it would pin whatever `:latest` is today. The fields below shape that snapshot and
|
|
@@ -156,17 +156,17 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
156
156
|
buildTimeoutMs?: number;
|
|
157
157
|
/**
|
|
158
158
|
* Let `Sandbox.create({ image })` build the image's snapshot when none exists yet. A new build
|
|
159
|
-
*
|
|
160
|
-
* is free. Without it, a create from an image is refused before anything is sent: whether the
|
|
159
|
+
* is billed per second while it runs, at most `build_price` (your plan's rates, `client.pricing()`);
|
|
160
|
+
* reusing a snapshot already built is free. Without it, a create from an image is refused before anything is sent: whether the
|
|
161
161
|
* image's snapshot exists is only known once a build is submitted, and a submitted build cannot
|
|
162
162
|
* be withdrawn. The other way to pay once and on purpose: `promigence snapshot create --image
|
|
163
163
|
* REF --alias NAME`, then `Sandbox.create("NAME")`.
|
|
164
164
|
*/
|
|
165
165
|
allowBuild?: boolean;
|
|
166
166
|
/**
|
|
167
|
-
* Called with the `POST /snapshots` answer before any wait: `build_price
|
|
168
|
-
* `joined` when nothing new is charged. Without it,
|
|
169
|
-
* process warning (stderr) before the build is waited for.
|
|
167
|
+
* Called with the `POST /snapshots` answer before any wait: `build_price` (the most the build can
|
|
168
|
+
* cost) and `per_second_usd`, and `deduped` or `joined` when nothing new is charged. Without it,
|
|
169
|
+
* a new build's price is reported as a process warning (stderr) before the build is waited for.
|
|
170
170
|
*/
|
|
171
171
|
onBuild?: (build: SnapshotBuild) => void | Promise<void>;
|
|
172
172
|
/**
|
|
@@ -198,9 +198,8 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
198
198
|
*/
|
|
199
199
|
export declare function imageSnapshot(client: PromigenceClient, opts: Pick<SandboxCreateOpts, "image" | "setup" | "verify" | "start" | "tier" | "alias" | "registrySecret" | "buildTimeoutMs">, hooks?: {
|
|
200
200
|
/**
|
|
201
|
-
* The `POST /snapshots` answer, before any wait: `build_price`
|
|
202
|
-
* or `joined` (nothing new charged). An implicit build costs money, so a caller
|
|
203
|
-
* that prints prices prints this one too.
|
|
201
|
+
* The `POST /snapshots` answer, before any wait: `build_price` (the most it can cost) and
|
|
202
|
+
* whether it was `deduped` or `joined` (nothing new charged). An implicit build costs money, so a caller that prints prices prints this one too.
|
|
204
203
|
*/
|
|
205
204
|
onBuild?: (build: SnapshotBuild) => void | Promise<void>;
|
|
206
205
|
/** Ends the wait for a build at once; the build itself, once submitted, is not withdrawn. */
|
|
@@ -375,7 +374,7 @@ export declare class Sandbox {
|
|
|
375
374
|
/**
|
|
376
375
|
* Fork of 1 from a snapshot (`snap_<id>` | `<alias>` | `<alias>@<commit7>`), or from the
|
|
377
376
|
* snapshot of an image: `Sandbox.create({ image: 'python:3.12', allowBuild: true })` builds it
|
|
378
|
-
* on first use (a new build at
|
|
377
|
+
* on first use (a new build billed per second at its tier's rate, bounded by `buildTimeoutMs`, default 15 min) and reuses it
|
|
379
378
|
* free after. An image needs `allowBuild: true` and a tag or digest; without either it is
|
|
380
379
|
* refused before any request.
|
|
381
380
|
*
|
package/dist/sandbox.js
CHANGED
|
@@ -65,12 +65,16 @@ function buildNotice(image) {
|
|
|
65
65
|
return (b) => {
|
|
66
66
|
if (buildIsFree(b))
|
|
67
67
|
return;
|
|
68
|
-
const price = typeof b.build_price === "number"
|
|
69
|
-
|
|
68
|
+
const price = typeof b.build_price === "number"
|
|
69
|
+
? typeof b.per_second_usd === "number"
|
|
70
|
+
? `billed per second while it builds ($${Number(b.per_second_usd.toPrecision(12))}/s), at most $${b.build_price.toFixed(2)}`
|
|
71
|
+
: `build_price $${b.build_price.toFixed(2)}, charged once it verifies`
|
|
72
|
+
: "billed at your plan's rates";
|
|
73
|
+
process.emitWarning(`building a snapshot of ${image}: ${price} (later creates from this image reuse it free)`, { code: "PROMIGENCE_BUILD" });
|
|
70
74
|
};
|
|
71
75
|
}
|
|
72
76
|
function buildNotAllowed(image) {
|
|
73
|
-
return new InvalidArgumentError(`Sandbox.create({ image: ${JSON.stringify(image)} }) builds that image's snapshot unless one already exists, and a new build is
|
|
77
|
+
return new InvalidArgumentError(`Sandbox.create({ image: ${JSON.stringify(image)} }) builds that image's snapshot unless one already exists, and a new build is billed per second while it runs (\`promigence pricing\` shows the rates; reusing a snapshot already built is free). Nothing was sent.`, `To allow the build: Sandbox.create({ image: ${JSON.stringify(image)}, allowBuild: true }). Or build it once, ` +
|
|
74
78
|
`\`promigence snapshot create --image ${hintArg(image)} --alias NAME\`, and create from its name: Sandbox.create("NAME").`);
|
|
75
79
|
}
|
|
76
80
|
export async function imageSnapshot(client, opts, hooks = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promigence/sdk",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.9",
|
|
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",
|