@promigence/sdk 0.1.0-beta.7 → 0.1.0-beta.8
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/README.md +3 -2
- package/dist/cjs/client.d.ts +38 -0
- package/dist/cjs/client.js +28 -12
- package/dist/cjs/core.d.ts +10 -1
- package/dist/cjs/core.js +11 -3
- package/dist/cjs/credstore.d.ts +3 -2
- package/dist/cjs/credstore.js +17 -4
- package/dist/cjs/models.gen.d.ts +148 -6
- package/dist/cjs/proxy.js +2 -1
- package/dist/cjs/pty.d.ts +65 -3
- package/dist/cjs/pty.js +270 -34
- package/dist/cjs/sandbox.d.ts +32 -0
- package/dist/cjs/sandbox.js +3 -0
- package/dist/cjs/ssh.js +1 -0
- package/dist/client.d.ts +38 -0
- package/dist/client.js +29 -13
- package/dist/core.d.ts +10 -1
- package/dist/core.js +9 -2
- package/dist/credstore.d.ts +3 -2
- package/dist/credstore.js +17 -4
- package/dist/models.gen.d.ts +148 -6
- package/dist/proxy.js +2 -1
- package/dist/pty.d.ts +65 -3
- package/dist/pty.js +269 -33
- package/dist/sandbox.d.ts +32 -0
- package/dist/sandbox.js +3 -0
- package/dist/ssh.js +1 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -2,7 +2,7 @@ import { readFileSync, statSync } from "node:fs";
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { inspect } from "node:util";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
-
import { ApiError, AuthError, EnvFailedError, PromigenceError, InvalidArgumentError, NotFoundError, NotReleasedError, NotVerifiedError, RateLimitError, SpendCapError, TimeoutError, UnreachableError, DEFAULT_API_URL, ERRORS_DOCS_URL, FILE_PUT_CHUNK_BYTES, MAX_OUTPUT_BYTES_DEFAULT, VERSION, WAIT_TIMEOUT_MS, PreviewsUnavailableError, exitForCode, previewsOff, withPreviewsFix, } from "./core.js";
|
|
5
|
+
import { ApiError, AuthError, EnvFailedError, PromigenceError, InvalidArgumentError, NotFoundError, NotReleasedError, NotVerifiedError, RateLimitError, ServiceRestartError, SpendCapError, TimeoutError, UnreachableError, DEFAULT_API_URL, ERRORS_DOCS_URL, FILE_PUT_CHUNK_BYTES, MAX_OUTPUT_BYTES_DEFAULT, VERSION, WAIT_TIMEOUT_MS, PreviewsUnavailableError, exitForCode, previewsOff, withPreviewsFix, } from "./core.js";
|
|
6
6
|
import { buildBundle } from "./bundle.js";
|
|
7
7
|
import { keychainReadCached, keychainStore, storeLabel } from "./credstore.js";
|
|
8
8
|
import { CALLER_HEADER, resolveCaller, userAgentWithCaller } from "./caller.js";
|
|
@@ -135,7 +135,7 @@ function decodeCredentials(buf) {
|
|
|
135
135
|
return buf.subarray(3).toString("utf8");
|
|
136
136
|
return buf.toString("utf8");
|
|
137
137
|
}
|
|
138
|
-
export function storedCredentials(env = process.env) {
|
|
138
|
+
export function storedCredentials(env = process.env, platform = process.platform) {
|
|
139
139
|
const path = credentialsPath(env);
|
|
140
140
|
let present = true;
|
|
141
141
|
try {
|
|
@@ -145,7 +145,7 @@ export function storedCredentials(env = process.env) {
|
|
|
145
145
|
present = e.code !== "ENOENT";
|
|
146
146
|
}
|
|
147
147
|
if (!present) {
|
|
148
|
-
const store = keychainStore(env);
|
|
148
|
+
const store = keychainStore(env, platform);
|
|
149
149
|
if (store === undefined)
|
|
150
150
|
return undefined;
|
|
151
151
|
const r = keychainReadCached(store, path, env);
|
|
@@ -259,8 +259,6 @@ export function keyOrigin(env = process.env) {
|
|
|
259
259
|
const stored = readCredentialsWithStore(env);
|
|
260
260
|
if (stored.creds.api_key)
|
|
261
261
|
return stored.store === "macos-keychain" ? "macOS Keychain" : stored.store === "secret-service" ? "Secret Service keyring" : "credentials file";
|
|
262
|
-
if (compatApiKey(env["E2B_API_KEY"]))
|
|
263
|
-
return "E2B_API_KEY (compat)";
|
|
264
262
|
return undefined;
|
|
265
263
|
}
|
|
266
264
|
function resolveCredentials(opts, env = process.env) {
|
|
@@ -269,17 +267,19 @@ function resolveCredentials(opts, env = process.env) {
|
|
|
269
267
|
const t = u.replace(/\/+$/, "");
|
|
270
268
|
return /^https?:\/\/[^/?#]+$/i.test(t) ? `${t}/v1` : t;
|
|
271
269
|
};
|
|
272
|
-
const { creds, store } = readCredentialsWithStore(env);
|
|
273
270
|
const envKey = set(env["PROMIGENCE_API_KEY"]?.trim());
|
|
274
271
|
const envUrl = set(env["PROMIGENCE_API_URL"]);
|
|
275
272
|
const optKey = opts.apiKey?.trim();
|
|
273
|
+
const given = optKey !== undefined || envKey !== undefined;
|
|
274
|
+
const { creds, store } = given
|
|
275
|
+
? { creds: {}, store: undefined }
|
|
276
|
+
: readCredentialsWithStore(env);
|
|
276
277
|
const source = optKey !== undefined ? "opts" : envKey !== undefined ? "env" : creds.api_key !== undefined ? "file" : undefined;
|
|
277
278
|
const ours = optKey ?? envKey ?? creds.api_key;
|
|
278
|
-
const
|
|
279
|
-
const
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const fromFile = trim(creds.api_url ?? compatUrl ?? DEFAULT_API_URL);
|
|
279
|
+
const fallback = ours === undefined ? opts.fallbackKey : undefined;
|
|
280
|
+
const fallbackKey = set(fallback?.apiKey.trim());
|
|
281
|
+
const fallbackUrl = fallbackKey === undefined ? undefined : set(fallback?.apiUrl);
|
|
282
|
+
const fromFile = trim(creds.api_url ?? fallbackUrl ?? DEFAULT_API_URL);
|
|
283
283
|
const fromEnv = envUrl !== undefined ? trim(envUrl) : fromFile;
|
|
284
284
|
const apiUrl = opts.apiUrl !== undefined ? trim(opts.apiUrl) : fromEnv;
|
|
285
285
|
const paired = source === "file" ? fromFile : source === "env" ? fromEnv : apiUrl;
|
|
@@ -291,10 +291,10 @@ function resolveCredentials(opts, env = process.env) {
|
|
|
291
291
|
: "Pass apiKey together with apiUrl, or set PROMIGENCE_API_URL to that URL instead of passing apiUrl.");
|
|
292
292
|
return { apiKey: undefined, apiUrl, refusal };
|
|
293
293
|
}
|
|
294
|
-
const key = ours ??
|
|
294
|
+
const key = ours ?? fallbackKey;
|
|
295
295
|
if (key) {
|
|
296
296
|
const from = source === "opts" ? "the apiKey option" : source === "env" ? "PROMIGENCE_API_KEY"
|
|
297
|
-
: source === "file" ? storedName(store, env) :
|
|
297
|
+
: source === "file" ? storedName(store, env) : fallback.from;
|
|
298
298
|
const refusal = keyRefusal(key, from);
|
|
299
299
|
if (refusal)
|
|
300
300
|
return { apiKey: undefined, apiUrl, refusal };
|
|
@@ -652,6 +652,7 @@ export function errorFor(code, message, fix, extra = {}) {
|
|
|
652
652
|
case "invalid_argument":
|
|
653
653
|
return attach(new InvalidArgumentError(message, extra.cli ? fix : withoutCliHelp(fix), code));
|
|
654
654
|
case "not_released": return attach(new NotReleasedError(message));
|
|
655
|
+
case "service_restart": return attach(new ServiceRestartError(message, fix));
|
|
655
656
|
default:
|
|
656
657
|
if (ENV_CODES.has(code) || extra.category === "env")
|
|
657
658
|
return attach(new EnvFailedError(code, message, fix));
|
|
@@ -1258,6 +1259,14 @@ export class PromigenceClient {
|
|
|
1258
1259
|
const r = await this.request({ method: "GET", path: `/me/ledger?${pageQuery(limit, 1000, opts.cursor)}` });
|
|
1259
1260
|
return pageOf(r, "entries", limit);
|
|
1260
1261
|
},
|
|
1262
|
+
historyPage: async (opts = {}) => {
|
|
1263
|
+
const limit = opts.limit ?? 50;
|
|
1264
|
+
const q = new URLSearchParams(pageQuery(limit, 100, opts.cursor));
|
|
1265
|
+
if (opts.kind !== undefined && opts.kind !== "all")
|
|
1266
|
+
q.set("kind", opts.kind);
|
|
1267
|
+
const r = await this.request({ method: "GET", path: `/billing/history?${q.toString()}` });
|
|
1268
|
+
return pageOf(r, "entries", limit);
|
|
1269
|
+
},
|
|
1261
1270
|
checkout: () => this.request({ method: "POST", path: "/billing/checkout", body: {} }),
|
|
1262
1271
|
portal: () => this.request({ method: "POST", path: "/billing/portal", body: {} }),
|
|
1263
1272
|
referrals: () => this.request({ method: "GET", path: "/referrals" }),
|
|
@@ -1752,6 +1761,10 @@ export class PromigenceClient {
|
|
|
1752
1761
|
on.heartbeat?.();
|
|
1753
1762
|
continue;
|
|
1754
1763
|
}
|
|
1764
|
+
if (event === "reconnect") {
|
|
1765
|
+
reader.cancel().catch(() => { });
|
|
1766
|
+
throw new ServiceRestartError(`a service restart stopped the command on sandbox ${sandboxId} while its output was streaming`, "Not billed: the time the command ran is credited back. The sandbox kept running; the command may have done part of its work before it stopped: run it again if that is safe.");
|
|
1767
|
+
}
|
|
1755
1768
|
let parsed = {};
|
|
1756
1769
|
try {
|
|
1757
1770
|
parsed = JSON.parse(data);
|
|
@@ -1987,6 +2000,9 @@ export class PromigenceClient {
|
|
|
1987
2000
|
...(opts.onData ? { onData: opts.onData } : {}),
|
|
1988
2001
|
...(opts.onExit ? { onExit: opts.onExit } : {}),
|
|
1989
2002
|
...(opts.timeoutMs === undefined ? {} : { timeoutMs: opts.timeoutMs }),
|
|
2003
|
+
...(opts.resume === undefined ? {} : { resume: opts.resume }),
|
|
2004
|
+
...(opts.reconnect === undefined ? {} : { reconnect: opts.reconnect }),
|
|
2005
|
+
...(opts.onReconnected ? { onReconnected: opts.onReconnected } : {}),
|
|
1990
2006
|
refuse: (status, text, retryAfter) => {
|
|
1991
2007
|
let payload = {};
|
|
1992
2008
|
try {
|
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.8";
|
|
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";
|
|
@@ -190,6 +190,15 @@ export declare class TimeoutError extends PromigenceError {
|
|
|
190
190
|
runId?: string;
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* A service update may stop a command that was running while its output was streaming to you
|
|
195
|
+
* (`execStream`, `commands.run` with output callbacks); the time it ran is credited back, and the
|
|
196
|
+
* sandbox keeps running. `retryable` is `false`: the command may have done part of its work before
|
|
197
|
+
* it stopped, so run it again only if that is safe. exit 3
|
|
198
|
+
*/
|
|
199
|
+
export declare class ServiceRestartError extends PromigenceError {
|
|
200
|
+
constructor(message: string, fix: string);
|
|
201
|
+
}
|
|
193
202
|
/** An API error with no more specific class (5xx, unknown code). exit from the table. */
|
|
194
203
|
export declare class ApiError extends PromigenceError {
|
|
195
204
|
}
|
package/dist/core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hintArg } from "./hint.js";
|
|
2
|
-
export const VERSION = "0.1.0-beta.
|
|
2
|
+
export const VERSION = "0.1.0-beta.8";
|
|
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";
|
|
@@ -194,6 +194,11 @@ export class TimeoutError extends PromigenceError {
|
|
|
194
194
|
this.runId = ids.runId;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
+
export class ServiceRestartError extends PromigenceError {
|
|
198
|
+
constructor(message, fix) {
|
|
199
|
+
super({ code: "service_restart", message, fix, exitCode: 3, category: "env", retryable: false });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
197
202
|
export class ApiError extends PromigenceError {
|
|
198
203
|
}
|
|
199
204
|
export class NotReleasedError extends PromigenceError {
|
|
@@ -210,6 +215,7 @@ export const EXIT_BY_CODE = {
|
|
|
210
215
|
invalid_argument: 2, unsupported: 2, not_released: 1, task_failed: 4,
|
|
211
216
|
env_failed: 3, snapshot_rejected: 6, build_failed: 3, snapshot_failed: 4,
|
|
212
217
|
not_connected: 7,
|
|
218
|
+
service_restart: 3,
|
|
213
219
|
fork_failed: 3, start_timeout: 3, readiness_failed: 3, verify_too_slow: 3,
|
|
214
220
|
verify_each_failed: 3, toolchain_mismatch: 3, sandbox_unresponsive: 3, oom_within_tier: 3,
|
|
215
221
|
disk_full_within_tier: 3, sandbox_interrupted: 3, integrity_mismatch: 3, egress_unavailable: 3,
|
|
@@ -236,10 +242,11 @@ export const EXIT_BY_CODE = {
|
|
|
236
242
|
build_timeout: 4,
|
|
237
243
|
image_unresolvable: 2,
|
|
238
244
|
registry_unavailable: 3,
|
|
239
|
-
trial_credits_exhausted: 5, card_required: 5, credit_unclaimed: 5, concurrency_limit: 5, egress_cap_reached:
|
|
245
|
+
trial_credits_exhausted: 5, card_required: 5, credit_unclaimed: 5, concurrency_limit: 5, egress_cap_reached: 5,
|
|
240
246
|
billing_unavailable: 5,
|
|
241
247
|
project_cap_reached: 5,
|
|
242
248
|
spend_limit_reached: 5,
|
|
249
|
+
billing_hold: 5,
|
|
243
250
|
tier_over_plan: 2,
|
|
244
251
|
network_host_refused: 9, network_policy_unsupported: 3,
|
|
245
252
|
secrets_in_snapshot: 2, secrets_unavailable: 3,
|
package/dist/credstore.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* the credentials file (`~/.config/promigence/credentials`, 0600). The CLI writes it
|
|
4
4
|
* (`promigence login`, `promigence auth login`, `promigence logout`); the CLI and both SDKs read it.
|
|
5
5
|
*
|
|
6
|
-
* macOS the login Keychain, through `security` (when
|
|
6
|
+
* macOS the login Keychain, through `security` (when the user's home holds one: HOME,
|
|
7
|
+
* or the account's own home when the environment has no HOME)
|
|
7
8
|
* Linux and BSD the Secret Service (GNOME Keyring, KWallet), through `secret-tool`, when a
|
|
8
9
|
* desktop session bus is there (a CI job or an SSH shell has none: the file)
|
|
9
10
|
* Windows the file: no tool that ships with Windows can read a stored secret back
|
|
@@ -34,7 +35,7 @@ export declare function storeLabel(store: CredentialStore, path?: string): strin
|
|
|
34
35
|
* The keychain this process stores a sign-in in, or undefined for the file. `auto` is decided by
|
|
35
36
|
* the platform and by whether its tool (and, for the Secret Service, a session bus) is there.
|
|
36
37
|
*/
|
|
37
|
-
export declare function keychainStore(env?: NodeJS.ProcessEnv, platform?: string): KeychainStore | undefined;
|
|
38
|
+
export declare function keychainStore(env?: NodeJS.ProcessEnv, platform?: string, home?: () => string): KeychainStore | undefined;
|
|
38
39
|
/**
|
|
39
40
|
* The keychains a sign-out (or a sign-in that lands in the file) must clear for this path: the one
|
|
40
41
|
* in use, and the platform's own even when `PROMIGENCE_CREDENTIAL_STORE=file` (an item a previous
|
package/dist/credstore.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { accessSync, constants, existsSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
3
4
|
import { delimiter, join } from "node:path";
|
|
4
5
|
export const KEYCHAIN_SERVICE = "promigence-cli";
|
|
5
6
|
const KEYCHAIN_LABEL = "Promigence CLI credentials";
|
|
@@ -30,8 +31,19 @@ function sessionBus(env) {
|
|
|
30
31
|
const run = env["XDG_RUNTIME_DIR"];
|
|
31
32
|
return Boolean(run) && existsSync(join(run, "bus"));
|
|
32
33
|
}
|
|
34
|
+
function userHome(env, home = homedir) {
|
|
35
|
+
const h = env["HOME"];
|
|
36
|
+
if (h)
|
|
37
|
+
return h;
|
|
38
|
+
try {
|
|
39
|
+
return home() || undefined;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
33
45
|
const warnedSetting = new Set();
|
|
34
|
-
export function keychainStore(env = process.env, platform = process.platform) {
|
|
46
|
+
export function keychainStore(env = process.env, platform = process.platform, home = homedir) {
|
|
35
47
|
const raw = (env["PROMIGENCE_CREDENTIAL_STORE"] ?? "").trim().toLowerCase();
|
|
36
48
|
switch (raw) {
|
|
37
49
|
case "file": return undefined;
|
|
@@ -46,8 +58,8 @@ export function keychainStore(env = process.env, platform = process.platform) {
|
|
|
46
58
|
}
|
|
47
59
|
}
|
|
48
60
|
if (platform === "darwin") {
|
|
49
|
-
const
|
|
50
|
-
return
|
|
61
|
+
const h = userHome(env, home);
|
|
62
|
+
return h && existsSync(join(h, "Library", "Keychains")) && onPath("security", env) ? "macos-keychain" : undefined;
|
|
51
63
|
}
|
|
52
64
|
if (platform === "win32")
|
|
53
65
|
return undefined;
|
|
@@ -94,8 +106,9 @@ function runTool(store, args, env, input, timeout) {
|
|
|
94
106
|
const bin = onPath(toolName(store), env);
|
|
95
107
|
if (bin === undefined)
|
|
96
108
|
throw Object.assign(new Error(`${toolName(store)} not found`), { code: "ENOENT" });
|
|
109
|
+
const h = store === "macos-keychain" && !env["HOME"] ? userHome(env) : undefined;
|
|
97
110
|
return execFileSync(bin, args, {
|
|
98
|
-
encoding: "utf8", timeout, env,
|
|
111
|
+
encoding: "utf8", timeout, env: h ? { ...env, HOME: h } : env,
|
|
99
112
|
...(input === undefined ? { stdio: ["ignore", "pipe", "pipe"] } : { input, stdio: ["pipe", "pipe", "pipe"] }),
|
|
100
113
|
});
|
|
101
114
|
}
|
package/dist/models.gen.d.ts
CHANGED
|
@@ -243,6 +243,36 @@ export interface BackgroundExecList {
|
|
|
243
243
|
execs: Array<BackgroundExec>;
|
|
244
244
|
sandbox_id: string;
|
|
245
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* `GET /v1/billing/history` — your billing history, newest first: every credit you received and
|
|
248
|
+
* every payment, one page at a time.
|
|
249
|
+
*/
|
|
250
|
+
export interface BillingHistory {
|
|
251
|
+
entries: Array<BillingHistoryEntry>;
|
|
252
|
+
/**
|
|
253
|
+
* Pass as `cursor` for the next, older page; `null` on the last page.
|
|
254
|
+
*/
|
|
255
|
+
next_cursor?: string | null;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* One entry of your billing history: a credit you received or a payment. Exactly one of
|
|
259
|
+
* `credit` and `payment` is set.
|
|
260
|
+
*/
|
|
261
|
+
export interface BillingHistoryEntry {
|
|
262
|
+
/**
|
|
263
|
+
* When it happened, RFC 3339: when a credit was added, when a payment was made, failed or
|
|
264
|
+
* was refunded.
|
|
265
|
+
*/
|
|
266
|
+
at: string;
|
|
267
|
+
/**
|
|
268
|
+
* A credit you received; `null` for a payment.
|
|
269
|
+
*/
|
|
270
|
+
credit?: CreditGrant | null;
|
|
271
|
+
/**
|
|
272
|
+
* A payment; `null` for a credit.
|
|
273
|
+
*/
|
|
274
|
+
payment?: Payment | null;
|
|
275
|
+
}
|
|
246
276
|
/**
|
|
247
277
|
* The billing period `usage` covers.
|
|
248
278
|
*/
|
|
@@ -261,9 +291,9 @@ export interface BillingPeriod {
|
|
|
261
291
|
start: string;
|
|
262
292
|
}
|
|
263
293
|
/**
|
|
264
|
-
* `GET /v1/billing` — plan, card on file, this month's usage, and the upcoming invoice
|
|
265
|
-
*
|
|
266
|
-
*
|
|
294
|
+
* `GET /v1/billing` — plan, card on file, this month's usage, and the upcoming invoice preview.
|
|
295
|
+
* Never fails because the payment provider is slow: the estimate is the only part that asks it,
|
|
296
|
+
* and its failure is a field, not a status.
|
|
267
297
|
*/
|
|
268
298
|
export interface BillingStatus {
|
|
269
299
|
/**
|
|
@@ -274,11 +304,22 @@ export interface BillingStatus {
|
|
|
274
304
|
* `null` while no card is on file.
|
|
275
305
|
*/
|
|
276
306
|
card?: CardOnFile | null;
|
|
307
|
+
/**
|
|
308
|
+
* A sentence to show beside the card when it does not unlock paid limits for this
|
|
309
|
+
* organization (it already pays for another one, or it is being confirmed with a $1 charge, or
|
|
310
|
+
* that charge did not go through); `null` otherwise.
|
|
311
|
+
*/
|
|
312
|
+
card_note?: string | null;
|
|
277
313
|
card_on_file: boolean;
|
|
278
314
|
/**
|
|
279
315
|
* True once a billing customer exists for the organisation.
|
|
280
316
|
*/
|
|
281
317
|
customer: boolean;
|
|
318
|
+
/**
|
|
319
|
+
* The $1 that confirms the payment method on file when it has no stable payer (Apple Pay,
|
|
320
|
+
* Google Pay, Amazon Pay); `null` when it needed none.
|
|
321
|
+
*/
|
|
322
|
+
method_check?: MethodCheckView | null;
|
|
282
323
|
notice?: TrialNotice | null;
|
|
283
324
|
org_id: string;
|
|
284
325
|
period: BillingPeriod;
|
|
@@ -830,7 +871,7 @@ export interface CliTokenCreate {
|
|
|
830
871
|
/**
|
|
831
872
|
* Every error and failure code the API returns.
|
|
832
873
|
*/
|
|
833
|
-
export type Code = "fork_failed" | "start_timeout" | "readiness_failed" | "verify_too_slow" | "verify_each_failed" | "sandbox_unresponsive" | "oom_within_tier" | "disk_full_within_tier" | "sandbox_interrupted" | "integrity_mismatch" | "egress_unavailable" | "service_timeout" | "capacity_busy" | "verify_did_not_cover" | "nonzero_exit" | "task_timeout" | "oom_over_tier" | "disk_over_tier" | "cap_killed" | "cap_exceeded" | "aborted_by_client" | "expired" | "not_started" | "superseded" | "usage" | "internal" | "auth" | "not_found" | "unreachable" | "rate_limited" | "timeout" | "not_verified" | "enoent" | "trial_credits_exhausted" | "card_required" | "concurrency_limit" | "egress_cap_reached" | "network_policy_unsupported" | "network_host_refused" | "toolchain_mismatch" | "resume_unavailable" | "sandbox_unreachable" | "region_at_capacity" | "tier_unavailable" | "snapshot_unavailable" | "capacity_limit" | "build_timeout" | "builder_unavailable" | "builder_busy" | "overloaded" | "preempted" | "grader_failed" | "grade_not_passed" | "shutdown_by_task" | "modified_by_task" | "cap_paused" | "credits_paused" | "stopped_by_support" | "forbidden" | "snapshot_incompatible" | "storage_limit_reached" | "dockerfile_build_failed" | "image_unresolvable" | "registry_unavailable" | "credit_unclaimed" | "billing_unavailable" | "project_cap_reached" | "spend_limit_reached" | "tier_over_plan" | "secrets_in_snapshot" | "secrets_unavailable" | "secret_binding_unsupported" | "idempotency_key_reused" | "idempotency_key_in_use" | "repo_credentials_not_supported" | "account_exists" | "invite_invalid" | "invite_required" | "key_expired" | "account_blocked" | "setup_required";
|
|
874
|
+
export type Code = "fork_failed" | "start_timeout" | "readiness_failed" | "verify_too_slow" | "verify_each_failed" | "sandbox_unresponsive" | "oom_within_tier" | "disk_full_within_tier" | "sandbox_interrupted" | "integrity_mismatch" | "egress_unavailable" | "service_timeout" | "capacity_busy" | "verify_did_not_cover" | "nonzero_exit" | "task_timeout" | "oom_over_tier" | "disk_over_tier" | "cap_killed" | "cap_exceeded" | "aborted_by_client" | "expired" | "not_started" | "superseded" | "usage" | "internal" | "auth" | "not_found" | "unreachable" | "rate_limited" | "timeout" | "not_verified" | "enoent" | "trial_credits_exhausted" | "card_required" | "concurrency_limit" | "egress_cap_reached" | "network_policy_unsupported" | "network_host_refused" | "toolchain_mismatch" | "resume_unavailable" | "sandbox_unreachable" | "region_at_capacity" | "tier_unavailable" | "snapshot_unavailable" | "capacity_limit" | "build_timeout" | "builder_unavailable" | "builder_busy" | "overloaded" | "preempted" | "grader_failed" | "grade_not_passed" | "shutdown_by_task" | "modified_by_task" | "cap_paused" | "credits_paused" | "stopped_by_support" | "forbidden" | "snapshot_incompatible" | "storage_limit_reached" | "dockerfile_build_failed" | "image_unresolvable" | "registry_unavailable" | "credit_unclaimed" | "billing_unavailable" | "project_cap_reached" | "spend_limit_reached" | "billing_hold" | "tier_over_plan" | "secrets_in_snapshot" | "secrets_unavailable" | "secret_binding_unsupported" | "idempotency_key_reused" | "idempotency_key_in_use" | "repo_credentials_not_supported" | "account_exists" | "invite_invalid" | "invite_required" | "key_expired" | "account_blocked" | "setup_required";
|
|
834
875
|
export interface Concurrency {
|
|
835
876
|
}
|
|
836
877
|
/**
|
|
@@ -916,6 +957,41 @@ export interface CreditClaim {
|
|
|
916
957
|
terms_version?: string | null;
|
|
917
958
|
token?: string | null;
|
|
918
959
|
}
|
|
960
|
+
/**
|
|
961
|
+
* A credit your organization received, and what is left of it.
|
|
962
|
+
*/
|
|
963
|
+
export interface CreditGrant {
|
|
964
|
+
/**
|
|
965
|
+
* When it expires, RFC 3339; `null` when it never expires.
|
|
966
|
+
*/
|
|
967
|
+
expires_at?: string | null;
|
|
968
|
+
/**
|
|
969
|
+
* When it was added, RFC 3339.
|
|
970
|
+
*/
|
|
971
|
+
granted_at: string;
|
|
972
|
+
/**
|
|
973
|
+
* USD.
|
|
974
|
+
*/
|
|
975
|
+
granted_usd: number;
|
|
976
|
+
/**
|
|
977
|
+
* What it is: `free_credit` (the free credit), `card_bonus` (credit for adding a card),
|
|
978
|
+
* `referral` (a referral reward), `plan` (usage included with a paid plan),
|
|
979
|
+
* `from_promigence` (credit Promigence added to your account), `service_restart` (credit
|
|
980
|
+
* for a command a service restart stopped), `confirmation_credit` (a $1 charge that
|
|
981
|
+
* confirmed a payment method, added back as credit), or `other`.
|
|
982
|
+
*/
|
|
983
|
+
kind: string;
|
|
984
|
+
/**
|
|
985
|
+
* What is left of it, USD: 0 once it is used, expired or taken back. Credit that expires
|
|
986
|
+
* soonest is used first, and credit that never expires last.
|
|
987
|
+
*/
|
|
988
|
+
remaining_usd: number;
|
|
989
|
+
/**
|
|
990
|
+
* `active` (some of it is left), `used` (all of it was used), `expired` (it expired before
|
|
991
|
+
* all of it was used), or `taken_back`.
|
|
992
|
+
*/
|
|
993
|
+
status: string;
|
|
994
|
+
}
|
|
919
995
|
/**
|
|
920
996
|
* The account's free credit (`GET /v1/credits/offer`, and the answer to a claim). The credit is
|
|
921
997
|
* claimed in the browser, where the terms are accepted: `POST /v1/credits/claim-link` makes the
|
|
@@ -942,6 +1018,11 @@ export interface CreditOffer {
|
|
|
942
1018
|
* One sentence for a person.
|
|
943
1019
|
*/
|
|
944
1020
|
message: string;
|
|
1021
|
+
/**
|
|
1022
|
+
* USD charged to confirm a payment method with no stable payer when it is added (Apple Pay,
|
|
1023
|
+
* Google Pay, Amazon Pay): it is added to your credit, and the card bonus comes with it.
|
|
1024
|
+
*/
|
|
1025
|
+
method_check_usd?: number;
|
|
945
1026
|
/**
|
|
946
1027
|
* `claimable`, `claimed`, `pending_review`, `needs_card`, `not_eligible`, `offer_ended`,
|
|
947
1028
|
* `denied` or `none`.
|
|
@@ -1075,7 +1156,7 @@ export interface ErrorBody {
|
|
|
1075
1156
|
/**
|
|
1076
1157
|
* Every error code the API returns. `category` decides whether the failure is billed: `env` is ours (not billed before hand-over; after it, the time since the sandbox's last snapshot is credited back, up to 24 hours, when our side shows the cause), `task` is your command and is billed. The full table is `x-promigence-error-codes` at the document root.
|
|
1077
1158
|
*/
|
|
1078
|
-
export type ErrorCode = "fork_failed" | "start_timeout" | "readiness_failed" | "verify_too_slow" | "verify_each_failed" | "toolchain_mismatch" | "sandbox_unresponsive" | "oom_within_tier" | "disk_full_within_tier" | "sandbox_interrupted" | "integrity_mismatch" | "egress_unavailable" | "service_timeout" | "preempted" | "verify_did_not_cover" | "grader_failed" | "nonzero_exit" | "grade_not_passed" | "task_timeout" | "oom_over_tier" | "disk_over_tier" | "shutdown_by_task" | "modified_by_task" | "cap_killed" | "cap_exceeded" | "cap_paused" | "credits_paused" | "aborted_by_client" | "stopped_by_support" | "expired" | "not_started" | "superseded" | "usage" | "internal" | "auth" | "forbidden" | "not_found" | "unreachable" | "rate_limited" | "timeout" | "not_verified" | "snapshot_incompatible" | "storage_limit_reached" | "resume_unavailable" | "sandbox_unreachable" | "capacity_busy" | "region_at_capacity" | "builder_unavailable" | "builder_busy" | "overloaded" | "tier_unavailable" | "snapshot_unavailable" | "capacity_limit" | "build_timeout" | "dockerfile_build_failed" | "image_unresolvable" | "registry_unavailable" | "enoent" | "trial_credits_exhausted" | "credit_unclaimed" | "setup_required" | "card_required" | "billing_unavailable" | "concurrency_limit" | "egress_cap_reached" | "project_cap_reached" | "spend_limit_reached" | "tier_over_plan" | "network_host_refused" | "network_policy_unsupported" | "secrets_in_snapshot" | "secrets_unavailable" | "secret_binding_unsupported" | "idempotency_key_reused" | "idempotency_key_in_use" | "repo_credentials_not_supported" | "account_exists" | "invite_invalid" | "invite_required" | "key_expired" | "account_blocked";
|
|
1159
|
+
export type ErrorCode = "fork_failed" | "start_timeout" | "readiness_failed" | "verify_too_slow" | "verify_each_failed" | "toolchain_mismatch" | "sandbox_unresponsive" | "oom_within_tier" | "disk_full_within_tier" | "sandbox_interrupted" | "integrity_mismatch" | "egress_unavailable" | "service_timeout" | "preempted" | "verify_did_not_cover" | "grader_failed" | "nonzero_exit" | "grade_not_passed" | "task_timeout" | "oom_over_tier" | "disk_over_tier" | "shutdown_by_task" | "modified_by_task" | "cap_killed" | "cap_exceeded" | "cap_paused" | "credits_paused" | "aborted_by_client" | "stopped_by_support" | "expired" | "not_started" | "superseded" | "usage" | "internal" | "auth" | "forbidden" | "not_found" | "unreachable" | "rate_limited" | "timeout" | "not_verified" | "snapshot_incompatible" | "storage_limit_reached" | "resume_unavailable" | "sandbox_unreachable" | "capacity_busy" | "region_at_capacity" | "builder_unavailable" | "builder_busy" | "overloaded" | "tier_unavailable" | "snapshot_unavailable" | "capacity_limit" | "build_timeout" | "dockerfile_build_failed" | "image_unresolvable" | "registry_unavailable" | "enoent" | "trial_credits_exhausted" | "credit_unclaimed" | "setup_required" | "card_required" | "billing_unavailable" | "concurrency_limit" | "egress_cap_reached" | "project_cap_reached" | "spend_limit_reached" | "billing_hold" | "tier_over_plan" | "network_host_refused" | "network_policy_unsupported" | "secrets_in_snapshot" | "secrets_unavailable" | "secret_binding_unsupported" | "idempotency_key_reused" | "idempotency_key_in_use" | "repo_credentials_not_supported" | "account_exists" | "invite_invalid" | "invite_required" | "key_expired" | "account_blocked";
|
|
1079
1160
|
/**
|
|
1080
1161
|
* `POST /v1/sandboxes/{id}/execs`, and the `exec` of `POST /v1/runs`: one command. `argv` (a
|
|
1081
1162
|
* non-empty list) or `sh` (a shell line) is required.
|
|
@@ -2547,6 +2628,29 @@ export interface MemberView {
|
|
|
2547
2628
|
*/
|
|
2548
2629
|
you: boolean;
|
|
2549
2630
|
}
|
|
2631
|
+
/**
|
|
2632
|
+
* The $1 charged to confirm a payment method with no stable payer (`GET /v1/billing`
|
|
2633
|
+
* `method_check`).
|
|
2634
|
+
*/
|
|
2635
|
+
export interface MethodCheckView {
|
|
2636
|
+
/**
|
|
2637
|
+
* USD charged; added to your credit once paid.
|
|
2638
|
+
*/
|
|
2639
|
+
amount_usd: number;
|
|
2640
|
+
/**
|
|
2641
|
+
* USD of credit that came with it (the card bonus), once paid; `null` otherwise.
|
|
2642
|
+
*/
|
|
2643
|
+
bonus_usd?: number | null;
|
|
2644
|
+
/**
|
|
2645
|
+
* The method as a person reads it: `Apple Pay`, `Google Pay`, `Amazon Pay`, ...
|
|
2646
|
+
*/
|
|
2647
|
+
method: string;
|
|
2648
|
+
/**
|
|
2649
|
+
* `confirming` (charged, its answer not in yet), `paid` (it counts as your payment method) or
|
|
2650
|
+
* `failed` (declined, or it needed you there to approve it: it does not count; add a card).
|
|
2651
|
+
*/
|
|
2652
|
+
status: string;
|
|
2653
|
+
}
|
|
2550
2654
|
/**
|
|
2551
2655
|
* `POST /v1/orgs` and `POST /v1/orgs/{org}/projects`.
|
|
2552
2656
|
*/
|
|
@@ -2814,6 +2918,44 @@ export interface ParkedBytes {
|
|
|
2814
2918
|
*/
|
|
2815
2919
|
allocated: number;
|
|
2816
2920
|
}
|
|
2921
|
+
/**
|
|
2922
|
+
* A payment: an invoice paid, a payment that failed, a refund, or the charge that confirmed a
|
|
2923
|
+
* payment method.
|
|
2924
|
+
*/
|
|
2925
|
+
export interface Payment {
|
|
2926
|
+
/**
|
|
2927
|
+
* USD: what was paid, what was due, what was refunded, or what confirmed the method.
|
|
2928
|
+
*/
|
|
2929
|
+
amount_usd: number;
|
|
2930
|
+
/**
|
|
2931
|
+
* The invoice's number, as the invoice shows it; `null` when not known.
|
|
2932
|
+
*/
|
|
2933
|
+
invoice_number?: string | null;
|
|
2934
|
+
/**
|
|
2935
|
+
* The invoice's page: its receipt once it is paid, where to pay it while a payment has
|
|
2936
|
+
* failed; `null` when not known.
|
|
2937
|
+
*/
|
|
2938
|
+
invoice_url?: string | null;
|
|
2939
|
+
/**
|
|
2940
|
+
* `invoice_paid`, `payment_failed`, `refund`, or `method_check` (a charge, usually $1, that
|
|
2941
|
+
* confirmed a payment method; it comes back as credit).
|
|
2942
|
+
*/
|
|
2943
|
+
kind: string;
|
|
2944
|
+
/**
|
|
2945
|
+
* `method_check`: the payment method it confirmed, by name (`Apple Pay`); `null` otherwise.
|
|
2946
|
+
*/
|
|
2947
|
+
method?: string | null;
|
|
2948
|
+
/**
|
|
2949
|
+
* The plan whose fee the invoice billed; `null` when it billed usage alone.
|
|
2950
|
+
*/
|
|
2951
|
+
plan?: string | null;
|
|
2952
|
+
/**
|
|
2953
|
+
* `paid` (for a payment that failed: paid since), `retrying` (it failed and will be tried
|
|
2954
|
+
* again), `failed` (it failed and will not be tried again; for `method_check`, the method
|
|
2955
|
+
* was not confirmed), `refunded`, or `confirmed` (`method_check`: the method is confirmed).
|
|
2956
|
+
*/
|
|
2957
|
+
status: string;
|
|
2958
|
+
}
|
|
2817
2959
|
export interface Percentiles {
|
|
2818
2960
|
p50: number;
|
|
2819
2961
|
p95: number;
|
|
@@ -4502,7 +4644,7 @@ export interface SandboxView {
|
|
|
4502
4644
|
*/
|
|
4503
4645
|
outcome?: string | null;
|
|
4504
4646
|
/**
|
|
4505
|
-
* While it is paused: when it will be deleted, with its
|
|
4647
|
+
* While it is paused: when it will be deleted, with its files and state, unless it is
|
|
4506
4648
|
* resumed before then (RFC 3339). A paused sandbox is kept for 30 days, and resuming it
|
|
4507
4649
|
* starts the 30 days again. Absent while it is not paused, and for a paused sandbox that is
|
|
4508
4650
|
* not due to be deleted.
|
package/dist/proxy.js
CHANGED
|
@@ -199,8 +199,9 @@ export function requestVia(url, options, env = process.env) {
|
|
|
199
199
|
connect.end();
|
|
200
200
|
return undefined;
|
|
201
201
|
};
|
|
202
|
+
const { agent: _agent, ...direct } = options;
|
|
202
203
|
return httpsRequest(url, {
|
|
203
|
-
...
|
|
204
|
+
...direct,
|
|
204
205
|
createConnection: createConnection,
|
|
205
206
|
});
|
|
206
207
|
}
|
package/dist/pty.d.ts
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
*/
|
|
14
14
|
/** Largest terminal input frame sent; the server's cap is 1 MiB per client frame. */
|
|
15
15
|
export declare const PTY_INPUT_CHUNK: number;
|
|
16
|
+
/** How much of what was typed a session keeps, to send again to a terminal picked up again. */
|
|
17
|
+
export declare const PTY_INPUT_KEEP: number;
|
|
18
|
+
/** The header a terminal is picked up again with (its resume token). */
|
|
19
|
+
export declare const PTY_RESUME_HEADER = "promigence-resume";
|
|
16
20
|
export interface PtySize {
|
|
17
21
|
cols: number;
|
|
18
22
|
rows: number;
|
|
@@ -53,6 +57,33 @@ export interface PtyConnectOpts {
|
|
|
53
57
|
caller?: string;
|
|
54
58
|
onData?: (data: Uint8Array) => void;
|
|
55
59
|
onExit?: (exit: PtyExit) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Reconnect in a new shell when the service is updated (a WebSocket `Close` 1012) and the
|
|
62
|
+
* terminal cannot be picked up again ([`resume`]). The session goes on over a new connection,
|
|
63
|
+
* with its callbacks, its size and what was typed meanwhile, in a NEW shell: what ran in the old
|
|
64
|
+
* one has ended. Tried for up to 30 s ([`PTY_RECONNECT_FOR_MS`]); past that the session ends with
|
|
65
|
+
* `error.code` `"service_restart"`.
|
|
66
|
+
*
|
|
67
|
+
* Default: on for a shell, off when `command` is set (reconnecting starts the command again,
|
|
68
|
+
* which may not be safe to run twice); `true` or `false` decides either way.
|
|
69
|
+
*/
|
|
70
|
+
reconnect?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Pick the same terminal up again when its connection drops or the service restarts (default
|
|
73
|
+
* on): the terminal keeps running for a short while, and the session picks up where it left off
|
|
74
|
+
* over a new connection, with what was typed meanwhile delivered once — the same shell, or the
|
|
75
|
+
* same command, still running. Where it cannot be picked up (it ended meanwhile, or too much time
|
|
76
|
+
* passed), a restart falls back to [`reconnect`]; a dropped connection ends the session, as
|
|
77
|
+
* before.
|
|
78
|
+
*/
|
|
79
|
+
resume?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Called after each reconnect: `resumed` is `true` when it is the same terminal picked up
|
|
82
|
+
* again, `false` when it is a new shell (what ran in the old one has ended).
|
|
83
|
+
*/
|
|
84
|
+
onReconnected?: (how: {
|
|
85
|
+
resumed: boolean;
|
|
86
|
+
}) => void;
|
|
56
87
|
/** Handshake bound (default 30 s). The session itself has none. */
|
|
57
88
|
timeoutMs?: number;
|
|
58
89
|
/** Maps a refused upgrade (`status`, body text, its `Retry-After`) onto the SDK's error classes. */
|
|
@@ -80,15 +111,28 @@ export declare class FrameReader {
|
|
|
80
111
|
*/
|
|
81
112
|
export declare class PtySession {
|
|
82
113
|
#private;
|
|
83
|
-
private
|
|
84
|
-
/**
|
|
114
|
+
private socket;
|
|
115
|
+
/**
|
|
116
|
+
* The id of the terminal's process inside the sandbox (`req_id`); what `pty.kill(pid)`
|
|
117
|
+
* addresses. It names this session: it stays the same after a reconnect.
|
|
118
|
+
*/
|
|
85
119
|
readonly pid: number;
|
|
86
120
|
cols: number;
|
|
87
121
|
rows: number;
|
|
88
122
|
private closed;
|
|
89
123
|
private readonly done;
|
|
124
|
+
/** Frames written while the session reconnects, sent once it has (at most 1 MiB). */
|
|
125
|
+
private pending;
|
|
126
|
+
/** Keystrokes written to a connection, in all, and the last of them, from `inputBase` on: what a
|
|
127
|
+
* terminal picked up again did not take is sent again. */
|
|
128
|
+
private inputSent;
|
|
129
|
+
private inputBase;
|
|
130
|
+
private inputLog;
|
|
90
131
|
/** `true` once the terminal has ended (its exit arrived, or the socket closed). */
|
|
91
132
|
get ended(): boolean;
|
|
133
|
+
private flush;
|
|
134
|
+
/** Write a frame to the connection now, counting keystrokes. */
|
|
135
|
+
private writeNow;
|
|
92
136
|
private send;
|
|
93
137
|
/** Keystrokes / a paste. A string is sent as UTF-8. */
|
|
94
138
|
write(data: string | Uint8Array): void;
|
|
@@ -105,5 +149,23 @@ export declare class PtySession {
|
|
|
105
149
|
*/
|
|
106
150
|
disconnect(): void;
|
|
107
151
|
}
|
|
108
|
-
/**
|
|
152
|
+
/** The `Close` code a terminal is asked to reconnect with: 1012, "service restart" (RFC 6455's registry). */
|
|
153
|
+
export declare const PTY_RECONNECT_CODE = 1012;
|
|
154
|
+
/** How long a terminal tries to reconnect before it ends (`error.code` `"service_restart"`). */
|
|
155
|
+
export declare const PTY_RECONNECT_FOR_MS = 30000;
|
|
156
|
+
/** The first wait before a reconnect, doubled each try up to [`PTY_RECONNECT_MAX_WAIT_MS`]; each wait is jittered (50-100 %). */
|
|
157
|
+
export declare const PTY_RECONNECT_FIRST_WAIT_MS = 250;
|
|
158
|
+
export declare const PTY_RECONNECT_MAX_WAIT_MS = 4000;
|
|
159
|
+
/** How a session that could not reconnect within [`PTY_RECONNECT_FOR_MS`] ends. */
|
|
160
|
+
export declare const PTY_RESTART_EXIT: PtyExit;
|
|
161
|
+
/** How a session that is not to reconnect (`reconnect` off, or a command's) ends at a 1012. */
|
|
162
|
+
export declare const PTY_RESTART_CLOSED_EXIT: PtyExit;
|
|
163
|
+
/**
|
|
164
|
+
* Open a terminal. Rejects with `opts.refuse(...)` if the server does not switch protocols.
|
|
165
|
+
*
|
|
166
|
+
* When its connection drops, or the service asks it to reconnect (`Close` 1012), the session goes
|
|
167
|
+
* on over a new connection: the same terminal picked up again where the service still holds it
|
|
168
|
+
* ([`PtyConnectOpts.resume`]), else, at a restart, a new shell ([`PtyConnectOpts.reconnect`]).
|
|
169
|
+
* `wait()` resolves only when the session really ends.
|
|
170
|
+
*/
|
|
109
171
|
export declare function connectPty(opts: PtyConnectOpts): Promise<PtySession>;
|