@promigence/sdk 0.1.0-beta.15 → 0.1.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/caller.js +1 -1
- package/dist/cjs/caller.js +1 -1
- package/dist/cjs/client.d.ts +173 -19
- package/dist/cjs/client.js +451 -129
- package/dist/cjs/command-errors.d.ts +1 -0
- package/dist/cjs/command-errors.js +2 -0
- package/dist/cjs/context.d.ts +20 -4
- package/dist/cjs/context.js +82 -5
- package/dist/cjs/core.d.ts +56 -5
- package/dist/cjs/core.js +49 -5
- package/dist/cjs/handles.js +2 -1
- package/dist/cjs/http2.d.ts +8 -0
- package/dist/cjs/http2.js +27 -1
- package/dist/cjs/models.gen.d.ts +269 -30
- package/dist/cjs/proxy.js +32 -3
- package/dist/cjs/sandbox.d.ts +38 -13
- package/dist/cjs/sandbox.js +29 -5
- package/dist/cjs/transport-worker.js +10 -1
- package/dist/client.d.ts +173 -19
- package/dist/client.js +450 -126
- package/dist/command-errors.d.ts +1 -0
- package/dist/command-errors.js +3 -1
- package/dist/context.d.ts +20 -4
- package/dist/context.js +79 -4
- package/dist/core.d.ts +56 -5
- package/dist/core.js +44 -4
- package/dist/handles.js +2 -1
- package/dist/http2.d.ts +8 -0
- package/dist/http2.js +27 -1
- package/dist/models.gen.d.ts +269 -30
- package/dist/proxy.js +33 -4
- package/dist/sandbox.d.ts +38 -13
- package/dist/sandbox.js +29 -5
- package/dist/transport-worker.js +10 -1
- package/package.json +1 -1
package/dist/cjs/sandbox.d.ts
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { inspect, type InspectOptions } from "node:util";
|
|
13
13
|
import { type CommandResult, type CommandRunOpts, type ForkOpts, type OptimizeFor, type SandboxOpts, type Tier } from "./core.js";
|
|
14
|
-
import { PromigenceClient, type BackgroundExecRecord, type DirEntry, type DirListOpts, type ExtractResult, type FileInfo, type FileMatch, type Page, type PortRecord, type AutoPauseMode, type SandboxRecord, type SearchOpts, type SecretBinding, type SnapshotBuild, type VerifySpec } from "./client.js";
|
|
14
|
+
import { PromigenceClient, type BackgroundExecRecord, type DirEntry, type DirListOpts, type ExtractResult, type FileInfo, type FileMatch, type Page, type PortExposeOpts, type PortRecord, type AutoPauseMode, type SandboxRecord, type SearchOpts, type SecretBinding, type SnapshotBuild, type VerifySpec } from "./client.js";
|
|
15
15
|
import { CommandHandle } from "./handles.js";
|
|
16
16
|
import type { PtyExit, PtySession, PtySize } from "./pty.js";
|
|
17
|
+
/** `setTimeout`'s fix when the longer timeout does not fit under the run's spend cap. */
|
|
18
|
+
export declare const EXTEND_OVER_CAP_FIX: string;
|
|
17
19
|
/**
|
|
18
20
|
* `commands.run` options for a foreground command. The call resolves with the whole result when
|
|
19
21
|
* the command ends; `onStdout` / `onStderr` also receive its output as it is written.
|
|
@@ -150,6 +152,8 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
150
152
|
start?: string | string[];
|
|
151
153
|
tier?: Tier;
|
|
152
154
|
alias?: string;
|
|
155
|
+
/** With `alias`: take the name from the snapshot that has it (refused without this). */
|
|
156
|
+
moveAlias?: boolean;
|
|
153
157
|
/** Name of a stored secret holding the registry credentials. */
|
|
154
158
|
registrySecret?: string;
|
|
155
159
|
/** Bound on the first build of an image (default 15 min). Expiry cancels nothing. */
|
|
@@ -196,7 +200,7 @@ export interface SandboxCreateOpts extends SandboxOpts {
|
|
|
196
200
|
* inputs) was built before, or 202 with a `build_id`. The **body**, not the status, decides: an
|
|
197
201
|
* idempotency replay answers 202 with a document that may already be `verified`.
|
|
198
202
|
*/
|
|
199
|
-
export declare function imageSnapshot(client: PromigenceClient, opts: Pick<SandboxCreateOpts, "image" | "setup" | "verify" | "start" | "tier" | "alias" | "registrySecret" | "buildTimeoutMs">, hooks?: {
|
|
203
|
+
export declare function imageSnapshot(client: PromigenceClient, opts: Pick<SandboxCreateOpts, "image" | "setup" | "verify" | "start" | "tier" | "alias" | "moveAlias" | "registrySecret" | "buildTimeoutMs">, hooks?: {
|
|
200
204
|
/**
|
|
201
205
|
* The `POST /snapshots` answer, before any wait: `build_price` (the most it can cost) and
|
|
202
206
|
* whether it was `deduped` or `joined` (nothing new charged). An implicit build costs money, so a caller that prints prices prints this one too.
|
|
@@ -285,6 +289,7 @@ export declare class Sandbox {
|
|
|
285
289
|
/**
|
|
286
290
|
* Run `cmd` and resolve with its result. A non-zero exit throws `CommandExitError`; a command
|
|
287
291
|
* killed at its own `timeoutMs` throws `CommandTimeoutError` (a `CommandExitError` too).
|
|
292
|
+
* With `throwOnExit: false` both resolve instead, and the result's `timedOut` tells them apart.
|
|
288
293
|
*/
|
|
289
294
|
run(cmd: string, opts?: ForegroundRunOpts): Promise<CommandResult>;
|
|
290
295
|
/** Background commands in this sandbox (running and ended, until killed with forget). */
|
|
@@ -312,9 +317,20 @@ export declare class Sandbox {
|
|
|
312
317
|
resize(pid: number, size: PtySize): Promise<void>;
|
|
313
318
|
kill(pid: number): Promise<boolean>;
|
|
314
319
|
};
|
|
315
|
-
/**
|
|
320
|
+
/**
|
|
321
|
+
* Preview URLs for ports inside the sandbox (`getHost` gives the address alone).
|
|
322
|
+
*
|
|
323
|
+
* Anyone holding a preview URL can open it; revoke it any time, and it ends with the sandbox.
|
|
324
|
+
* If your account's preview URLs aren't on, `expose` throws `PreviewsUnavailableError`; write to
|
|
325
|
+
* support@promigence.ai to have them turned on, and meanwhile reach the port with
|
|
326
|
+
* `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
|
|
327
|
+
*/
|
|
316
328
|
readonly ports: {
|
|
317
|
-
|
|
329
|
+
/**
|
|
330
|
+
* Publish `port`: `{ length: "long" }` for a longer, harder-to-guess URL (apps with sensitive
|
|
331
|
+
* data); omitted, the length this sandbox's project or organization chose (short by default).
|
|
332
|
+
*/
|
|
333
|
+
expose(port: number, opts?: PortExposeOpts): Promise<PortRecord>;
|
|
318
334
|
list(): Promise<PortRecord[]>;
|
|
319
335
|
/** A token revokes that URL; a port number every URL for it. Returns the revoked tokens. */
|
|
320
336
|
revoke(tokenOrPort: string | number): Promise<string[]>;
|
|
@@ -458,13 +474,16 @@ export declare class Sandbox {
|
|
|
458
474
|
}>;
|
|
459
475
|
isRunning(): Promise<boolean>;
|
|
460
476
|
/**
|
|
461
|
-
* `PATCH /sandboxes/:id` —
|
|
477
|
+
* `PATCH /sandboxes/:id` — set this sandbox's timeout, in milliseconds.
|
|
478
|
+
*
|
|
479
|
+
* The timeout is the sandbox's total lifetime, counted from its start, not from now:
|
|
480
|
+
* `setTimeout(600_000)` on a sandbox that has run 2 minutes leaves it 8 more.
|
|
462
481
|
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
482
|
+
* - Raising it commits the added seconds, which has to fit in what is left of the spend cap you set
|
|
483
|
+
* (the run's, or the org default): past it, it throws `SpendCapError` (409) rather than silently
|
|
484
|
+
* extending.
|
|
485
|
+
* - Lowering it goes down to what the sandbox has run plus 60 s, and no further
|
|
486
|
+
* (`InvalidArgumentError` below that). To stop it now, `kill()` it.
|
|
468
487
|
*/
|
|
469
488
|
setTimeout(ms: number): Promise<void>;
|
|
470
489
|
/**
|
|
@@ -476,8 +495,9 @@ export declare class Sandbox {
|
|
|
476
495
|
* the window may be. Bring it back with `resume()`, which is the warm path.
|
|
477
496
|
*
|
|
478
497
|
* `mode: "activity"` is for an agent that runs inside the sandbox on its own: it also waits
|
|
479
|
-
* until
|
|
480
|
-
*
|
|
498
|
+
* until, for the whole window, the sandbox has used under 5% of one core, sent and received no
|
|
499
|
+
* network byte and held no connection out open; disk writes do not count (`AutoPauseMode`).
|
|
500
|
+
* Omitted, the mode is left as it is (`"requests"` unless set).
|
|
481
501
|
*/
|
|
482
502
|
setAutoPause(seconds: number, mode?: AutoPauseMode): Promise<void>;
|
|
483
503
|
/** The idle rule in force: seconds before it pauses itself, `0` when it never does. */
|
|
@@ -499,7 +519,12 @@ export declare class Sandbox {
|
|
|
499
519
|
* full `url` with its scheme.
|
|
500
520
|
*
|
|
501
521
|
* Async, because the address is a capability minted on demand rather than
|
|
502
|
-
* a hostname derived from the id. An existing URL for the port is reused, not re-minted
|
|
522
|
+
* a hostname derived from the id. An existing URL for the port is reused, not re-minted; a new
|
|
523
|
+
* one has the length this sandbox's project or organization chose (short by default).
|
|
524
|
+
*
|
|
525
|
+
* If your account's preview URLs aren't on, this throws `PreviewsUnavailableError`; write to
|
|
526
|
+
* support@promigence.ai to have them turned on, and meanwhile reach the port with
|
|
527
|
+
* `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
|
|
503
528
|
*/
|
|
504
529
|
getHost(port: number): Promise<string>;
|
|
505
530
|
/**
|
package/dist/cjs/sandbox.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Sandbox = exports.DEFAULT_SNAPSHOT = exports.DEFAULT_PTY_CMD = void 0;
|
|
3
|
+
exports.Sandbox = exports.DEFAULT_SNAPSHOT = exports.DEFAULT_PTY_CMD = exports.EXTEND_OVER_CAP_FIX = void 0;
|
|
4
4
|
exports.shellQuote = shellQuote;
|
|
5
5
|
exports.ptyCommand = ptyCommand;
|
|
6
6
|
exports.toEntryInfo = toEntryInfo;
|
|
@@ -14,6 +14,8 @@ const client_js_1 = require("./client.js");
|
|
|
14
14
|
const handles_js_1 = require("./handles.js");
|
|
15
15
|
const command_errors_js_1 = require("./command-errors.js");
|
|
16
16
|
const hint_js_1 = require("./hint.js");
|
|
17
|
+
exports.EXTEND_OVER_CAP_FIX = "Raising the timeout must fit in what is left of the run's spend cap, and this does not: start a new " +
|
|
18
|
+
"sandbox with the longer `timeoutMs` and a `spendCap` that covers it.";
|
|
17
19
|
const EXEC_TIMEOUT_DEFAULT_MS = 15 * 60_000;
|
|
18
20
|
function textSink(cb) {
|
|
19
21
|
if (!cb)
|
|
@@ -47,6 +49,15 @@ function ptyCommand(opts) {
|
|
|
47
49
|
parts.push(opts.cmd ?? exports.DEFAULT_PTY_CMD);
|
|
48
50
|
return parts.join(" ");
|
|
49
51
|
}
|
|
52
|
+
function allowList(hosts) {
|
|
53
|
+
if (!Array.isArray(hosts)) {
|
|
54
|
+
throw new core_js_1.InvalidArgumentError("allowHosts must be a list of hosts", 'Pass allowHosts: ["github.com"].');
|
|
55
|
+
}
|
|
56
|
+
if (!hosts.some((h) => typeof h !== "string" || h.trim() !== "")) {
|
|
57
|
+
throw new core_js_1.InvalidArgumentError("allowHosts names no host, so the allow-list is empty", 'Name each host the sandbox may reach: allowHosts: ["github.com"]. For no network pass allowInternetAccess: false; to reach anything leave allowHosts out.');
|
|
58
|
+
}
|
|
59
|
+
return hosts;
|
|
60
|
+
}
|
|
50
61
|
function permString(mode) {
|
|
51
62
|
const r = (m) => `${m & 4 ? "r" : "-"}${m & 2 ? "w" : "-"}${m & 1 ? "x" : "-"}`;
|
|
52
63
|
return r((mode >> 6) & 7) + r((mode >> 3) & 7) + r(mode & 7);
|
|
@@ -99,6 +110,8 @@ async function imageSnapshot(client, opts, hooks = {}) {
|
|
|
99
110
|
create.tier = opts.tier;
|
|
100
111
|
if (opts.alias !== undefined)
|
|
101
112
|
create.alias = opts.alias;
|
|
113
|
+
if (opts.moveAlias)
|
|
114
|
+
create.moveAlias = true;
|
|
102
115
|
if (opts.registrySecret !== undefined)
|
|
103
116
|
create.registrySecret = opts.registrySecret;
|
|
104
117
|
let build = (await client.snapshots.create(create)) ?? {};
|
|
@@ -358,7 +371,7 @@ class Sandbox {
|
|
|
358
371
|
},
|
|
359
372
|
};
|
|
360
373
|
this.ports = {
|
|
361
|
-
expose: (port) => this.#client.sandboxes.ports.expose(this.sandboxId, port),
|
|
374
|
+
expose: (port, opts) => this.#client.sandboxes.ports.expose(this.sandboxId, port, opts),
|
|
362
375
|
list: () => this.#client.sandboxes.ports.list(this.sandboxId),
|
|
363
376
|
revoke: async (tokenOrPort) => (await this.#client.sandboxes.ports.revoke(this.sandboxId, tokenOrPort)).revoked,
|
|
364
377
|
};
|
|
@@ -372,6 +385,9 @@ class Sandbox {
|
|
|
372
385
|
return format === "bytes" ? bytes : new TextDecoder().decode(bytes);
|
|
373
386
|
}),
|
|
374
387
|
write: async (path, data, opts = {}) => {
|
|
388
|
+
if (typeof path !== "string") {
|
|
389
|
+
throw new core_js_1.InvalidArgumentError(`files.write takes one path and its data; got ${Array.isArray(path) ? "an array" : path === null ? "null" : typeof path} as the path`, "Write each file with its own call: for (const f of files) await sandbox.files.write(f.path, f.data).");
|
|
390
|
+
}
|
|
375
391
|
let body;
|
|
376
392
|
if (typeof data === "string" || data instanceof Uint8Array)
|
|
377
393
|
body = data;
|
|
@@ -566,8 +582,8 @@ class Sandbox {
|
|
|
566
582
|
start.timeoutMs = opts.timeoutMs;
|
|
567
583
|
if (opts.allowInternetAccess === false)
|
|
568
584
|
start.network = "none";
|
|
569
|
-
if (opts.allowHosts
|
|
570
|
-
start.network = { allow: opts.allowHosts };
|
|
585
|
+
if (opts.allowHosts !== undefined && opts.allowHosts !== null)
|
|
586
|
+
start.network = { allow: allowList(opts.allowHosts) };
|
|
571
587
|
if (opts.metadata)
|
|
572
588
|
start.labels = opts.metadata;
|
|
573
589
|
if (opts.secrets?.length)
|
|
@@ -705,7 +721,15 @@ class Sandbox {
|
|
|
705
721
|
return rec.state === "ready" || rec.state === "running";
|
|
706
722
|
}
|
|
707
723
|
async setTimeout(ms) {
|
|
708
|
-
|
|
724
|
+
try {
|
|
725
|
+
await this.#client.sandboxes.patch(this.sandboxId, { timeoutMs: ms });
|
|
726
|
+
}
|
|
727
|
+
catch (e) {
|
|
728
|
+
if (e instanceof core_js_1.SpendCapError && e.code === "cap_exceeded") {
|
|
729
|
+
Object.defineProperty(e, "fix", { value: exports.EXTEND_OVER_CAP_FIX, enumerable: true, configurable: true });
|
|
730
|
+
}
|
|
731
|
+
throw e;
|
|
732
|
+
}
|
|
709
733
|
this.timeoutMs = ms;
|
|
710
734
|
}
|
|
711
735
|
async setAutoPause(seconds, mode) {
|
|
@@ -292,6 +292,7 @@ function start(init) {
|
|
|
292
292
|
let rrAny = 0;
|
|
293
293
|
let pumpTimer;
|
|
294
294
|
let pumpSoon;
|
|
295
|
+
let turnsHeld = false;
|
|
295
296
|
const freeNow = (l, now) => {
|
|
296
297
|
for (let i = 0; i < l.length; i++) {
|
|
297
298
|
const k = (rr + i) % l.length;
|
|
@@ -306,6 +307,8 @@ function start(init) {
|
|
|
306
307
|
const pump = () => {
|
|
307
308
|
pumpTimer = undefined;
|
|
308
309
|
pumpSoon = undefined;
|
|
310
|
+
if (turnsHeld)
|
|
311
|
+
return;
|
|
309
312
|
while (waiting.length > 0) {
|
|
310
313
|
const l = live();
|
|
311
314
|
if (l.length === 0) {
|
|
@@ -348,7 +351,7 @@ function start(init) {
|
|
|
348
351
|
rrAny = (rrAny % l.length) + 1;
|
|
349
352
|
return e;
|
|
350
353
|
}
|
|
351
|
-
if (waiting.length === 0) {
|
|
354
|
+
if (waiting.length === 0 && !turnsHeld) {
|
|
352
355
|
const now = hrNow();
|
|
353
356
|
const e = freeNow(l, now);
|
|
354
357
|
if (e !== undefined) {
|
|
@@ -529,6 +532,12 @@ function start(init) {
|
|
|
529
532
|
}
|
|
530
533
|
else if (m?.t === "crash-for-test")
|
|
531
534
|
setImmediate(() => { throw new Error("transport thread crash (test)"); });
|
|
535
|
+
else if (m?.t === "hold-turns-for-test")
|
|
536
|
+
turnsHeld = true;
|
|
537
|
+
else if (m?.t === "release-turns-for-test") {
|
|
538
|
+
turnsHeld = false;
|
|
539
|
+
pump();
|
|
540
|
+
}
|
|
532
541
|
});
|
|
533
542
|
void open();
|
|
534
543
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { inspect, type InspectOptions } from "node:util";
|
|
3
3
|
import { PromigenceError, type CommandResult, type NetworkMode, type OptimizeFor, type Tier } from "./core.js";
|
|
4
4
|
import { type Bundle } from "./bundle.js";
|
|
5
|
+
import { type CredentialStore } from "./credstore.js";
|
|
5
6
|
import { type PtyExit, type PtySession } from "./pty.js";
|
|
6
7
|
import { type SshTunnel } from "./ssh.js";
|
|
7
8
|
import type * as M from "./models.gen.js";
|
|
@@ -177,6 +178,8 @@ export interface SandboxRef extends QueuedInfo {
|
|
|
177
178
|
}
|
|
178
179
|
/** How a grader's result is read. */
|
|
179
180
|
export type ScoreMode = M.ScoreMode;
|
|
181
|
+
/** Which of a run's sandboxes are kept to reopen where they ended (`RunStartOpts.capture`). */
|
|
182
|
+
export type CaptureMode = M.CaptureMode;
|
|
180
183
|
/**
|
|
181
184
|
* Score the agent's work after the episode, in a clean copy of the snapshot with the agent's
|
|
182
185
|
* changes applied. `holdout_cmd` is your own second test set; the report carries the gap
|
|
@@ -280,6 +283,10 @@ export interface ReportSandbox extends QueuedInfo {
|
|
|
280
283
|
sandbox_id: string;
|
|
281
284
|
state: SandboxState;
|
|
282
285
|
attempt?: number;
|
|
286
|
+
/** `PROMIGENCE_INDEX`: its place in the run, from 0. Absent when the run's command set it itself. */
|
|
287
|
+
index?: number;
|
|
288
|
+
/** `PROMIGENCE_SEED`: the number its commands were given. Absent when the run's command set it itself. */
|
|
289
|
+
seed?: number;
|
|
283
290
|
queued_ms?: number;
|
|
284
291
|
ready_ms?: number;
|
|
285
292
|
e2e_ms?: number;
|
|
@@ -319,11 +326,16 @@ export interface RunReport {
|
|
|
319
326
|
snapshot_id?: string;
|
|
320
327
|
alias?: string;
|
|
321
328
|
labels?: Record<string, string>;
|
|
329
|
+
/**
|
|
330
|
+
* What the run asked for. `network` is `"allow"` for a run behind an allowlist, whose hosts are
|
|
331
|
+
* `allow` (a service before it said `"egress"` for one).
|
|
332
|
+
*/
|
|
322
333
|
requested?: {
|
|
323
334
|
count: number;
|
|
324
335
|
timeout_ms: number;
|
|
325
336
|
verify_each: boolean;
|
|
326
|
-
network: NetworkMode;
|
|
337
|
+
network: NetworkMode | "allow";
|
|
338
|
+
allow?: string[];
|
|
327
339
|
allow_partial: boolean;
|
|
328
340
|
secrets?: string[];
|
|
329
341
|
grade?: GradeSpec;
|
|
@@ -386,6 +398,12 @@ export interface SecretRecord {
|
|
|
386
398
|
raw?: "allowed" | "refused";
|
|
387
399
|
/** Whether the value is kept out of the bound hosts' answers (present when `hosts` is). */
|
|
388
400
|
scan_responses?: boolean;
|
|
401
|
+
/**
|
|
402
|
+
* On `secrets.set` only: things to know about the value just stored, one `code: sentence` each;
|
|
403
|
+
* absent when there are none. `api_key_value`: the value holds an API key of this service, which
|
|
404
|
+
* any command in a sandbox given this secret can use.
|
|
405
|
+
*/
|
|
406
|
+
warnings?: string[];
|
|
389
407
|
}
|
|
390
408
|
/**
|
|
391
409
|
* `secrets.set` options: bind the secret to hosts. Requests a sandbox sends to the host's address
|
|
@@ -437,13 +455,19 @@ export interface SnapshotBuild {
|
|
|
437
455
|
repo?: string;
|
|
438
456
|
commit?: string;
|
|
439
457
|
verification?: Record<string, unknown>;
|
|
440
|
-
/**
|
|
458
|
+
/**
|
|
459
|
+
* A rejected build names the guard and the measured value; nothing was stored. `log_tail` is
|
|
460
|
+
* your build's own output: for a step of yours that failed (its start command, a setup step, its
|
|
461
|
+
* verify), that step's last lines. `fix`, when present, is what to change.
|
|
462
|
+
*/
|
|
441
463
|
error?: {
|
|
442
464
|
code?: string;
|
|
443
465
|
guard?: string;
|
|
444
466
|
message?: string;
|
|
445
467
|
values?: number[];
|
|
446
468
|
stored?: boolean;
|
|
469
|
+
log_tail?: string[];
|
|
470
|
+
fix?: string;
|
|
447
471
|
} | null;
|
|
448
472
|
/** Set when an identical build already existed. */
|
|
449
473
|
deduped?: boolean;
|
|
@@ -729,8 +753,25 @@ export interface OrgRecord {
|
|
|
729
753
|
created_at: string;
|
|
730
754
|
/** Days command output is kept after a sandbox ends; `null` = the default, 7. */
|
|
731
755
|
output_retention_days?: number | null;
|
|
732
|
-
/**
|
|
756
|
+
/**
|
|
757
|
+
* This organization's choice: keep a failed sandbox to reopen where it broke, when a run does not say (`capture`);
|
|
758
|
+
* absent or `null` = not chosen, so the default applies: not kept unless the organization or project chose to keep
|
|
759
|
+
* them. What applies is `failure_captures_effective`.
|
|
760
|
+
*/
|
|
733
761
|
failure_captures?: boolean | null;
|
|
762
|
+
/** The length of new preview URLs when a request does not say; absent or `null` = the default, short. */
|
|
763
|
+
preview_link_length?: PreviewLinkLength | null;
|
|
764
|
+
/** What applies to a failed run that does not say: kept or not, and whose choice decided it. */
|
|
765
|
+
failure_captures_effective?: CapturesEffective;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* What applies to a failed run's sandboxes when the run does not say (`capture`): `kept`, and `from`, whose choice
|
|
769
|
+
* decided it: `project`, `org`, or `default` (neither chose: not kept unless the organization or project chose to
|
|
770
|
+
* keep them). A run's own `capture` is followed either way.
|
|
771
|
+
*/
|
|
772
|
+
export interface CapturesEffective {
|
|
773
|
+
kept: boolean;
|
|
774
|
+
from: "project" | "org" | "default" | (string & {});
|
|
734
775
|
}
|
|
735
776
|
export interface ProjectRecord {
|
|
736
777
|
project_id: string;
|
|
@@ -742,8 +783,16 @@ export interface ProjectRecord {
|
|
|
742
783
|
monthly_cap_usd?: number | null;
|
|
743
784
|
/** Days this project's command output is kept after a sandbox ends; `null` = the organization's. */
|
|
744
785
|
output_retention_days?: number | null;
|
|
745
|
-
/**
|
|
786
|
+
/**
|
|
787
|
+
* This project's choice: keep its failed sandboxes to reopen, when a run does not say (`capture`); absent or `null` =
|
|
788
|
+
* the organization's choice, and where neither chose, the default: not kept unless the organization or project
|
|
789
|
+
* chose to keep them. What applies is `failure_captures_effective`.
|
|
790
|
+
*/
|
|
746
791
|
failure_captures?: boolean | null;
|
|
792
|
+
/** The length of this project's new preview URLs when a request does not say; absent or `null` = the organization's. */
|
|
793
|
+
preview_link_length?: PreviewLinkLength | null;
|
|
794
|
+
/** What applies to its failed runs that do not say: kept or not, and whose choice decided it. */
|
|
795
|
+
failure_captures_effective?: CapturesEffective;
|
|
747
796
|
created_at: string;
|
|
748
797
|
}
|
|
749
798
|
/** The longest command output may be kept after a sandbox ends, in days. */
|
|
@@ -1153,8 +1202,9 @@ export interface SandboxPatchResponse {
|
|
|
1153
1202
|
/**
|
|
1154
1203
|
* What the idle rule counts as idle. `"requests"` (the default): nobody has called the sandbox
|
|
1155
1204
|
* for the window and no command, terminal or SSH session is open. `"activity"`: all of that, and
|
|
1156
|
-
* for the whole window
|
|
1157
|
-
* connection to the outside is open — for an agent
|
|
1205
|
+
* for the whole window the sandbox used under 5% of one core, sent and received no network byte
|
|
1206
|
+
* (disk writes do not count), and no network connection to the outside is open — for an agent
|
|
1207
|
+
* that runs inside the sandbox on its own.
|
|
1158
1208
|
*/
|
|
1159
1209
|
export type AutoPauseMode = M.AutoPauseMode;
|
|
1160
1210
|
/** `POST /snapshots/:id/verify` — re-run the recorded `verify` in a fresh fork. */
|
|
@@ -1366,12 +1416,33 @@ export interface SshRevoked {
|
|
|
1366
1416
|
export interface PortRecord {
|
|
1367
1417
|
sandbox_id: string;
|
|
1368
1418
|
port: number;
|
|
1369
|
-
/**
|
|
1419
|
+
/** The URL's own name: anyone with the URL reaches the port. Pass it to `revoke` to take this one URL down. */
|
|
1370
1420
|
token: string;
|
|
1371
1421
|
url: string;
|
|
1372
1422
|
/** The same token as a DNS label, for a wildcard-DNS deployment (`<label>.<suffix>`). */
|
|
1373
1423
|
host_url_label?: string;
|
|
1374
1424
|
created_unix_ns?: number;
|
|
1425
|
+
/** When the URL stops working on its own (`ttl_s`); `null` for one that works until revoked. */
|
|
1426
|
+
expires_unix_ns?: number | null;
|
|
1427
|
+
/**
|
|
1428
|
+
* `"short"` (`https://brave-otter-48213.<domain>/`, the default) or `"long"` (a longer,
|
|
1429
|
+
* harder-to-guess URL, for apps with sensitive data).
|
|
1430
|
+
*/
|
|
1431
|
+
length?: PreviewLinkLength;
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* How long a preview URL is: `"short"` (the default, `https://brave-otter-48213.<domain>/`) or
|
|
1435
|
+
* `"long"` (a longer, harder-to-guess URL, for apps with sensitive data). Custom domains are
|
|
1436
|
+
* coming soon.
|
|
1437
|
+
*/
|
|
1438
|
+
export type PreviewLinkLength = "short" | "long";
|
|
1439
|
+
/** Options of `ports.expose`. */
|
|
1440
|
+
export interface PortExposeOpts {
|
|
1441
|
+
/**
|
|
1442
|
+
* `"short"` or `"long"`. Omitted: the length the sandbox's project chose, else its
|
|
1443
|
+
* organization's, else short.
|
|
1444
|
+
*/
|
|
1445
|
+
length?: PreviewLinkLength;
|
|
1375
1446
|
}
|
|
1376
1447
|
/** A key named without its secret (`/me`'s `key`, the key lists). */
|
|
1377
1448
|
export interface KeyRef {
|
|
@@ -1403,8 +1474,31 @@ export interface MeResponse {
|
|
|
1403
1474
|
max_concurrency?: number;
|
|
1404
1475
|
max_session_s?: number | null;
|
|
1405
1476
|
max_sandbox_vcpus?: number | null;
|
|
1477
|
+
/** Everything stored together, in GB: snapshots, paused sandboxes and saved failures; `null` for no limit. */
|
|
1478
|
+
max_storage_gb?: number | null;
|
|
1479
|
+
/**
|
|
1480
|
+
* The storage saved failures may use, in GB: when a new one would pass it, the oldest are removed to make room;
|
|
1481
|
+
* `null` for no limit.
|
|
1482
|
+
*/
|
|
1483
|
+
max_capture_storage_gb?: number | null;
|
|
1484
|
+
/** Snapshots that may be kept; `null` for no limit. */
|
|
1485
|
+
max_snapshots?: number | null;
|
|
1486
|
+
/** Paused sandboxes that may be kept; `null` for no limit. */
|
|
1487
|
+
max_paused?: number | null;
|
|
1406
1488
|
[extra: string]: number | null | undefined;
|
|
1407
1489
|
};
|
|
1490
|
+
/**
|
|
1491
|
+
* What the organisation stores now, in bytes (a GB of `limits` is 2^30 bytes): everything together (`used_bytes`,
|
|
1492
|
+
* against `limits.max_storage_gb`) and its saved failures (`captures_bytes`, against
|
|
1493
|
+
* `limits.max_capture_storage_gb`), with the counts. Absent from a server before it.
|
|
1494
|
+
*/
|
|
1495
|
+
storage?: {
|
|
1496
|
+
used_bytes: number;
|
|
1497
|
+
captures_bytes: number;
|
|
1498
|
+
snapshots: number;
|
|
1499
|
+
paused: number;
|
|
1500
|
+
captures: number;
|
|
1501
|
+
} | null;
|
|
1408
1502
|
/**
|
|
1409
1503
|
* Sandboxes holding capacity now (queued, starting, ready or running; paused ones hold none)
|
|
1410
1504
|
* against the limit.
|
|
@@ -1518,6 +1612,12 @@ export interface PromigenceClientOpts {
|
|
|
1518
1612
|
*/
|
|
1519
1613
|
onTiming?: (timing: Timing) => void;
|
|
1520
1614
|
}
|
|
1615
|
+
/** Where a client's key came from: the option, PROMIGENCE_API_KEY (`env`), the stored sign-in, or a fallback. */
|
|
1616
|
+
export interface KeyOrigin {
|
|
1617
|
+
source: "option" | "env" | "stored" | "fallback";
|
|
1618
|
+
/** The stored sign-in's store, for `stored`. */
|
|
1619
|
+
store?: CredentialStore;
|
|
1620
|
+
}
|
|
1521
1621
|
/** `GET /sandboxes/:id/network`. */
|
|
1522
1622
|
export interface SandboxNetwork {
|
|
1523
1623
|
sandbox_id: string;
|
|
@@ -1578,6 +1678,12 @@ export interface RunStartOpts {
|
|
|
1578
1678
|
verifyEach?: boolean;
|
|
1579
1679
|
network?: NetworkMode;
|
|
1580
1680
|
optimizeFor?: OptimizeFor;
|
|
1681
|
+
/**
|
|
1682
|
+
* Which of this run's sandboxes are kept to reopen where they ended (`runs.open`): `on_failure`
|
|
1683
|
+
* keeps one whose command failed, `off` keeps none, `always` keeps every one. Left out, the
|
|
1684
|
+
* default applies.
|
|
1685
|
+
*/
|
|
1686
|
+
capture?: CaptureMode;
|
|
1581
1687
|
/**
|
|
1582
1688
|
* Secrets for every sandbox of this run. An `exec` is no longer required: a run that names
|
|
1583
1689
|
* its secrets here gives them to every command run against every one of its sandboxes,
|
|
@@ -1641,9 +1747,9 @@ export interface ExecOpts {
|
|
|
1641
1747
|
*/
|
|
1642
1748
|
secrets?: SecretBinding[];
|
|
1643
1749
|
/**
|
|
1644
|
-
* Cancel an in-flight exec, streamed or not: the client stops waiting and the
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
1750
|
+
* Cancel an in-flight exec, streamed or not: the client stops waiting and tells the service to
|
|
1751
|
+
* stop the command in the sandbox. A buffered exec then throws `TimeoutError` ("aborted by the
|
|
1752
|
+
* caller's signal"); a streamed one rejects with the signal's `AbortError`.
|
|
1647
1753
|
*/
|
|
1648
1754
|
signal?: AbortSignal;
|
|
1649
1755
|
/**
|
|
@@ -1756,6 +1862,11 @@ export interface SnapshotCreateOpts {
|
|
|
1756
1862
|
*/
|
|
1757
1863
|
setupUser?: string;
|
|
1758
1864
|
alias?: string;
|
|
1865
|
+
/**
|
|
1866
|
+
* With `alias`: take the name from the snapshot that has it, which stays, unnamed. Without it, an
|
|
1867
|
+
* alias another snapshot has is refused (`usage`, 400) and nothing is built.
|
|
1868
|
+
*/
|
|
1869
|
+
moveAlias?: boolean;
|
|
1759
1870
|
/**
|
|
1760
1871
|
* A DEFAULT grader for this snapshot: a run on it with no `grade` of its own uses this one.
|
|
1761
1872
|
* The same shape as `runs.start({ grade })`.
|
|
@@ -1841,11 +1952,12 @@ export declare function credentialsExposure(path: string): string | undefined;
|
|
|
1841
1952
|
* `credentialsTrustProblem`).
|
|
1842
1953
|
*/
|
|
1843
1954
|
export declare function readCredentials(env?: NodeJS.ProcessEnv): Credentials;
|
|
1844
|
-
export declare function apiUrlFromCompatUrl(url: string | undefined): string | undefined;
|
|
1845
|
-
export declare function apiUrlFromCompatDomain(domain: string | undefined): string | undefined;
|
|
1846
|
-
export declare function compatApiKey(key: string | undefined): string | undefined;
|
|
1847
1955
|
/** Which variable a key came from, for `promigence doctor`. */
|
|
1848
1956
|
export declare function keyOrigin(env?: NodeJS.ProcessEnv): string | undefined;
|
|
1957
|
+
/** A request with no key found anywhere: none passed, none in the environment, none stored. */
|
|
1958
|
+
export declare const NO_KEY_MESSAGE = "no API key: none was given, PROMIGENCE_API_KEY is not set, and none is stored";
|
|
1959
|
+
/** What a caller of this SDK does about it. */
|
|
1960
|
+
export declare const NO_KEY_FIX = "Pass { apiKey } or set PROMIGENCE_API_KEY. No key yet: `promigence login` signs you up or in and stores one.";
|
|
1849
1961
|
/** `name@sha256:<64 hex>`, optionally with a tag before the `@`: a reference already pinned. */
|
|
1850
1962
|
export declare const IMAGE_DIGEST_RE: RegExp;
|
|
1851
1963
|
/**
|
|
@@ -2031,6 +2143,9 @@ export declare class PromigenceClient {
|
|
|
2031
2143
|
private guardDispatcher;
|
|
2032
2144
|
private dispatcherFor;
|
|
2033
2145
|
private againKeyed;
|
|
2146
|
+
private heldExec;
|
|
2147
|
+
private reattachBuffered;
|
|
2148
|
+
private cancelHeldExec;
|
|
2034
2149
|
request<T>(opts: RequestOpts): Promise<T>;
|
|
2035
2150
|
/**
|
|
2036
2151
|
* A request whose body — in either direction — is **bytes, not JSON** (`files get|put`).
|
|
@@ -2228,15 +2343,29 @@ export declare class PromigenceClient {
|
|
|
2228
2343
|
/** `PATCH /orgs/:org/projects/:project {name}` — rename it (the `default` project keeps its name). */
|
|
2229
2344
|
rename: (org: string, project: string, name: string) => Promise<ProjectRecord>;
|
|
2230
2345
|
/**
|
|
2231
|
-
* `PATCH /orgs/:org/projects/:project` — rename it, set how long its command output is kept,
|
|
2232
|
-
* whether its failed sandboxes are kept to reopen (
|
|
2346
|
+
* `PATCH /orgs/:org/projects/:project` — rename it, set how long its command output is kept,
|
|
2347
|
+
* whether its failed sandboxes are kept to reopen (on its own; `null` = the organization's choice, and
|
|
2348
|
+
* where neither chose, not kept unless the organization or project chose to keep them), or how long
|
|
2349
|
+
* its new preview URLs are (on its own). The settings need an owner signed in.
|
|
2233
2350
|
*/
|
|
2234
2351
|
update: (org: string, project: string, update: {
|
|
2235
2352
|
name?: string;
|
|
2236
2353
|
outputRetentionDays?: number | null;
|
|
2237
2354
|
failureCaptures?: boolean | null;
|
|
2355
|
+
previewLinkLength?: PreviewLinkLength | null;
|
|
2238
2356
|
}) => Promise<ProjectRecord>;
|
|
2239
2357
|
};
|
|
2358
|
+
/**
|
|
2359
|
+
* `PATCH /orgs/:org` — rename it, set how long its command output is kept, whether its failed
|
|
2360
|
+
* sandboxes are kept to reopen, or how long its new preview URLs are (those two each on their
|
|
2361
|
+
* own). The settings need an owner signed in.
|
|
2362
|
+
*/
|
|
2363
|
+
update: (org: string, update: {
|
|
2364
|
+
name?: string;
|
|
2365
|
+
outputRetentionDays?: number | null;
|
|
2366
|
+
failureCaptures?: boolean | null;
|
|
2367
|
+
previewLinkLength?: PreviewLinkLength | null;
|
|
2368
|
+
}) => Promise<OrgRecord>;
|
|
2240
2369
|
};
|
|
2241
2370
|
private group_orgs;
|
|
2242
2371
|
readonly credits: {
|
|
@@ -2410,7 +2539,13 @@ export declare class PromigenceClient {
|
|
|
2410
2539
|
*/
|
|
2411
2540
|
private waitLoop;
|
|
2412
2541
|
readonly sandboxes: {
|
|
2413
|
-
/**
|
|
2542
|
+
/**
|
|
2543
|
+
* `POST /sandboxes/:id/execs` — foreground exec, inline output up to `maxOutputBytes`.
|
|
2544
|
+
*
|
|
2545
|
+
* If the connection drops while the command runs, the SDK picks the command up again where the
|
|
2546
|
+
* service keeps it and returns its own answer; when it cannot, it throws `ExecLostError`. The
|
|
2547
|
+
* command is never sent a second time.
|
|
2548
|
+
*/
|
|
2414
2549
|
exec: (sandboxId: string, opts: ExecOpts) => Promise<ExecResponse>;
|
|
2415
2550
|
/**
|
|
2416
2551
|
* `POST /sandboxes/:id/execs` with `Accept: text/event-stream`.
|
|
@@ -2422,6 +2557,10 @@ export declare class PromigenceClient {
|
|
|
2422
2557
|
*
|
|
2423
2558
|
* Uses `fetch`'s streaming body rather than `res.text()`, which is what `request()` does and
|
|
2424
2559
|
* why it cannot be reused here: `await res.text()` is precisely the buffering this removes.
|
|
2560
|
+
*
|
|
2561
|
+
* If the connection drops while the command runs, the SDK picks the command up again where the
|
|
2562
|
+
* service keeps it, and the stream goes on where it left off; when it cannot, it throws
|
|
2563
|
+
* `ExecLostError`. The command is never sent a second time.
|
|
2425
2564
|
*/
|
|
2426
2565
|
execStream: (sandboxId: string, opts: ExecOpts, on?: {
|
|
2427
2566
|
stdout?: (chunk: Uint8Array) => void;
|
|
@@ -2510,9 +2649,18 @@ export declare class PromigenceClient {
|
|
|
2510
2649
|
/**
|
|
2511
2650
|
* Preview URLs for ports inside the sandbox. A URL is a capability — anyone holding it reaches
|
|
2512
2651
|
* that port — and dies with `revoke`, with a pause, or with the sandbox.
|
|
2652
|
+
*
|
|
2653
|
+
* If your account's preview URLs aren't on, `expose` throws `PreviewsUnavailableError`; write to
|
|
2654
|
+
* support@promigence.ai to have them turned on, and meanwhile reach the port with
|
|
2655
|
+
* `promigence sandbox ssh <sid> -- -N -L <port>:localhost:<port>`.
|
|
2513
2656
|
*/
|
|
2514
2657
|
ports: {
|
|
2515
|
-
|
|
2658
|
+
/**
|
|
2659
|
+
* Publish a port: `{ length: "long" }` for a longer, harder-to-guess URL (apps with
|
|
2660
|
+
* sensitive data); omitted, the length the sandbox's project or organization chose
|
|
2661
|
+
* (short by default).
|
|
2662
|
+
*/
|
|
2663
|
+
expose: (sandboxId: string, port: number, opts?: PortExposeOpts) => Promise<PortRecord>;
|
|
2516
2664
|
list: (sandboxId: string) => Promise<PortRecord[]>;
|
|
2517
2665
|
/** A token revokes that URL; a port number revokes every URL for that port. */
|
|
2518
2666
|
revoke: (sandboxId: string, tokenOrPort: string | number) => Promise<{
|
|
@@ -3049,8 +3197,14 @@ export declare class PromigenceClient {
|
|
|
3049
3197
|
alias?: string | null;
|
|
3050
3198
|
deleted: boolean;
|
|
3051
3199
|
}>;
|
|
3052
|
-
/**
|
|
3053
|
-
|
|
3200
|
+
/**
|
|
3201
|
+
* `PUT /snapshots/:id/alias` — the sidecar's one mutable field. A name another snapshot
|
|
3202
|
+
* has is refused (`usage`, 400) unless `moveAlias: true`, which takes it; that one stays,
|
|
3203
|
+
* unnamed.
|
|
3204
|
+
*/
|
|
3205
|
+
alias: (idOrAlias: string, alias: string | null, opts?: {
|
|
3206
|
+
moveAlias?: boolean;
|
|
3207
|
+
}) => Promise<SnapshotRecord>;
|
|
3054
3208
|
/**
|
|
3055
3209
|
* Wait for a build to leave `running`, bounded by `waitTimeoutMs` (default 100 s).
|
|
3056
3210
|
*
|