@aerol-ai/aerolvm-sdk 0.5.4 → 0.7.0

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/MicroVM.d.ts CHANGED
@@ -1,11 +1,40 @@
1
1
  import { type APIVersion, type RetryConfig } from "./internal/client.js";
2
2
  import { Sandbox } from "./Sandbox.js";
3
3
  import { Image } from "./Image.js";
4
- import type { BuildImageOptions, BuildImageResult, CloneGeneration, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, PushWasmModuleOptions, PushWasmModuleResult, ExecStreamHandle, ExecStreamOptions, HealthStatus, IngressTarget, Lifecycle, ListOptions, MountSpecRedacted, RegisterSnapshotOptions, ResizeOptions, SandboxSnapshot, Session, SessionAttachHandle, SessionAttachOptions, Template, WasmModule } from "./types.js";
4
+ import type { APITokenList, BuildImageOptions, BuildImageResult, CloneGeneration, CreateAPITokenOptions, CreatedAPIToken, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, PushWasmModuleOptions, PushWasmModuleResult, ExecStreamHandle, ExecStreamOptions, HealthStatus, EgressProfile, EgressProfileList, EgressProfileOptions, ListEgressProfilesOptions, NetworkPolicyCheckOptions, NetworkPolicyCheckResult, IngressTarget, Lifecycle, GetOptions, ListOptions, MountSpecRedacted, RegisterSnapshotOptions, ListSnapshotsOptions, SnapshotList, ResizeOptions, SandboxSnapshot, Session, SessionAttachHandle, SessionAttachOptions, Template, WasmModule, WhoAmI } from "./types.js";
5
5
  type FetchLike = typeof fetch;
6
+ /** Scoped API token calls, reached as `microvm.tokens`. */
7
+ export interface Tokens {
8
+ /**
9
+ * Mint a token (admin only). The result's `token` is the secret, returned
10
+ * this once and never again. A 409 means the name is taken, possibly by an
11
+ * earlier attempt whose reply was lost; that secret cannot be recovered,
12
+ * so revoke the token and create it again.
13
+ */
14
+ create(options: CreateAPITokenOptions): Promise<CreatedAPIToken>;
15
+ /** List every token (auditor or admin); expired ones stay listed for 30 days. */
16
+ list(): Promise<APITokenList>;
17
+ /** Revoke a token by id (admin only). Revoking one already gone succeeds. */
18
+ revoke(id: string): Promise<void>;
19
+ }
6
20
  export interface MicroVMConfig {
21
+ /**
22
+ * The bearer every request carries: the operator PAT, an `avm_` API token
23
+ * or an OIDC ID token. Defaults to `SB_PAT_TOKEN`, then its alias
24
+ * `SB_API_TOKEN`; when both are set, `SB_PAT_TOKEN` wins.
25
+ */
7
26
  patToken?: string;
8
27
  apiUrl?: string;
28
+ /**
29
+ * The team requests act for, sent as the `X-AerolVM-Team` header on every
30
+ * HTTP request. Defaults to `SB_TEAM`; with neither, no header is sent and
31
+ * the server uses the credential's first matching binding. The header only
32
+ * chooses among teams the credential is already bound to (a team it does
33
+ * not hold is refused with 403), and the operator PAT ignores it.
34
+ * WebSocket streams (`execStream`, `attachSession`) cannot carry custom
35
+ * headers from a browser or Node, so they go without it.
36
+ */
37
+ team?: string;
9
38
  fetch?: FetchLike;
10
39
  /**
11
40
  * Wire version of the sandbox daemon API to call. Defaults to the SDK's
@@ -16,25 +45,55 @@ export interface MicroVMConfig {
16
45
  apiVersion?: APIVersion;
17
46
  /**
18
47
  * Retry policy for transient transport errors (socket closed, connection
19
- * reset) and retryable HTTP status codes (429, 502, 503, 504). The SDK
20
- * retries up to 3 times with exponential backoff by default. Pass
21
- * `{ maxRetries: 0 }` to disable.
48
+ * reset) and retryable HTTP status codes (421, 429, 502, 503, 504). The SDK
49
+ * retries up to 3 times with exponential backoff by default. `exec` retries
50
+ * only failures that prove the command never reached the server
51
+ * (connection refused, connect timeout, DNS) and HTTP 429/503, so a command
52
+ * never runs twice. Pass `{ maxRetries: 0 }` to disable. A 429 or 503
53
+ * waits as long as the server's `Retry-After` asks, up to
54
+ * `retry.maxRetryAfterMs` (30 s by default).
22
55
  */
23
56
  retry?: RetryConfig;
57
+ /**
58
+ * Cancels the client's HTTP requests: aborting it ends the request in
59
+ * flight and any retry wait, so a call never sits out a long
60
+ * `Retry-After` once aborted. Pass `AbortSignal.timeout(ms)` to bound
61
+ * how long the client may run. WebSocket streams are not affected.
62
+ */
63
+ signal?: AbortSignal;
24
64
  }
25
65
  export declare class MicroVM {
26
66
  readonly apiUrl: string;
27
67
  readonly patToken: string;
68
+ /** The team sent as `X-AerolVM-Team`, or `""` when none is. */
69
+ readonly team: string;
28
70
  private readonly client;
29
71
  constructor(config?: MicroVMConfig);
30
72
  create(options: CreateOptions): Promise<Sandbox>;
31
73
  list(options?: ListOptions): Promise<Sandbox[]>;
32
- get(id: string): Promise<Sandbox>;
74
+ /**
75
+ * Iterates one server page at a time. Use this for large fleet inventories so
76
+ * the SDK does not retain every sandbox in memory.
77
+ */
78
+ listPages(options?: ListOptions): AsyncGenerator<Sandbox[]>;
79
+ get(id: string, options?: GetOptions): Promise<Sandbox>;
80
+ /**
81
+ * Returns the caller's sandbox with this name, or `null` when there is none.
82
+ * Names are unique per owner. Throws when the server predates name lookup
83
+ * (it ignores `?name=`), rather than guessing from an unfiltered list.
84
+ */
85
+ getByName(name: string, options?: GetOptions): Promise<Sandbox | null>;
33
86
  start(id: string): Promise<Sandbox>;
34
87
  stop(id: string): Promise<Sandbox>;
35
88
  createSnapshot(id: string, name: string): Promise<SandboxSnapshot>;
36
89
  registerSnapshot(options: RegisterSnapshotOptions): Promise<SandboxSnapshot>;
37
90
  registerSnapshotFromImage(name: string, image: Image, options?: Omit<RegisterSnapshotOptions, "name" | "image" | "dockerfileContent">): Promise<SandboxSnapshot>;
91
+ /** Look a snapshot up by name. In a cluster the request is routed to the node holding the image. */
92
+ getSnapshot(name: string): Promise<SandboxSnapshot>;
93
+ /** List the caller's snapshots, one name-ordered page at a time. */
94
+ listSnapshots(options?: ListSnapshotsOptions): Promise<SnapshotList>;
95
+ /** Delete a snapshot by name (idempotent 404 if it does not exist). */
96
+ deleteSnapshot(name: string): Promise<void>;
38
97
  destroy(id: string): Promise<void>;
39
98
  resize(id: string, options: ResizeOptions): Promise<Sandbox>;
40
99
  updateLifecycle(id: string, lifecycle: Lifecycle): Promise<Sandbox>;
@@ -47,6 +106,22 @@ export declare class MicroVM {
47
106
  */
48
107
  buildImage(image: Image, options?: BuildImageOptions): Promise<BuildImageResult>;
49
108
  health(): Promise<HealthStatus>;
109
+ /**
110
+ * Asks whether a sandbox created with these egress fields would reach a
111
+ * destination, using the same matcher the filter enforces. No sandbox is
112
+ * needed.
113
+ */
114
+ checkNetworkPolicy(options: NetworkPolicyCheckOptions): Promise<NetworkPolicyCheckResult>;
115
+ /**
116
+ * Creates or replaces a named egress profile (a full replace: the same body
117
+ * twice is a no-op). Sandboxes reference it through `egressProfiles`, and a
118
+ * change reaches every one of them.
119
+ */
120
+ putEgressProfile(name: string, options: EgressProfileOptions): Promise<EgressProfile>;
121
+ getEgressProfile(name: string): Promise<EgressProfile>;
122
+ listEgressProfiles(options?: ListEgressProfilesOptions): Promise<EgressProfileList>;
123
+ /** Deletes a profile; one that sandboxes still reference is refused (409). */
124
+ deleteEgressProfile(name: string): Promise<void>;
50
125
  mounts(sandboxID: string): Promise<MountSpecRedacted[]>;
51
126
  /**
52
127
  * Read a sandbox's clone-generation token. The token changes whenever the
@@ -116,6 +191,17 @@ export declare class MicroVM {
116
191
  get dns(): {
117
192
  target(): Promise<IngressTarget>;
118
193
  };
194
+ /**
195
+ * Who the server says the caller is: principal, role, team and when the
196
+ * credential expires. Every valid credential may ask.
197
+ */
198
+ whoami(): Promise<WhoAmI>;
199
+ /**
200
+ * Scoped API tokens (`avm_…`) for services and CI, as
201
+ * `microvm.tokens.create/list/revoke`. Same namespaced shape as
202
+ * {@link MicroVM.dns}.
203
+ */
204
+ get tokens(): Tokens;
119
205
  private wrap;
120
206
  }
121
207
  export {};
package/dist/MicroVM.js CHANGED
@@ -1,25 +1,31 @@
1
1
  import { APIClient, stripTrailingSlashes } from "./internal/client.js";
2
2
  import { Sandbox } from "./Sandbox.js";
3
3
  const defaultAPIURL = "http://127.0.0.1:21212";
4
- const authRequiredErrorMessage = "PAT token is required. Set patToken or SB_PAT_TOKEN.";
4
+ const authRequiredErrorMessage = "PAT token is required. Set patToken, SB_PAT_TOKEN or SB_API_TOKEN.";
5
5
  export class MicroVM {
6
6
  apiUrl;
7
7
  patToken;
8
+ /** The team sent as `X-AerolVM-Team`, or `""` when none is. */
9
+ team;
8
10
  client;
9
11
  constructor(config = {}) {
10
- const patToken = config.patToken ?? readEnv("SB_PAT_TOKEN") ?? "";
12
+ const patToken = config.patToken ?? readEnv("SB_PAT_TOKEN") ?? readEnv("SB_API_TOKEN") ?? "";
11
13
  const apiUrl = normalizeURL(config.apiUrl ?? readEnv("SB_API_URL") ?? defaultAPIURL);
14
+ const team = (config.team ?? readEnv("SB_TEAM") ?? "").trim();
12
15
  if (patToken === "") {
13
16
  throw new Error(authRequiredErrorMessage);
14
17
  }
15
18
  this.apiUrl = apiUrl;
16
19
  this.patToken = patToken;
20
+ this.team = team;
17
21
  this.client = new APIClient({
18
22
  baseURL: apiUrl,
19
23
  patToken,
24
+ team,
20
25
  fetch: config.fetch,
21
26
  apiVersion: config.apiVersion,
22
27
  retry: config.retry,
28
+ signal: config.signal,
23
29
  });
24
30
  }
25
31
  async create(options) {
@@ -30,10 +36,28 @@ export class MicroVM {
30
36
  const sandboxes = await this.client.list(options);
31
37
  return sandboxes.map((sandbox) => this.wrap(sandbox.toJSON()));
32
38
  }
33
- async get(id) {
34
- const sandbox = await this.client.get(id);
39
+ /**
40
+ * Iterates one server page at a time. Use this for large fleet inventories so
41
+ * the SDK does not retain every sandbox in memory.
42
+ */
43
+ async *listPages(options) {
44
+ for await (const page of this.client.listPages(options)) {
45
+ yield page.map((sandbox) => this.wrap(sandbox.toJSON()));
46
+ }
47
+ }
48
+ async get(id, options) {
49
+ const sandbox = await this.client.get(id, options);
35
50
  return this.wrap(sandbox.toJSON());
36
51
  }
52
+ /**
53
+ * Returns the caller's sandbox with this name, or `null` when there is none.
54
+ * Names are unique per owner. Throws when the server predates name lookup
55
+ * (it ignores `?name=`), rather than guessing from an unfiltered list.
56
+ */
57
+ async getByName(name, options) {
58
+ const sandbox = await this.client.getByName(name, options);
59
+ return sandbox === null ? null : this.wrap(sandbox.toJSON());
60
+ }
37
61
  async start(id) {
38
62
  const sandbox = await this.client.start(id);
39
63
  return this.wrap(sandbox.toJSON());
@@ -51,6 +75,18 @@ export class MicroVM {
51
75
  async registerSnapshotFromImage(name, image, options = {}) {
52
76
  return this.client.registerSnapshotFromImage(name, image, options);
53
77
  }
78
+ /** Look a snapshot up by name. In a cluster the request is routed to the node holding the image. */
79
+ async getSnapshot(name) {
80
+ return this.client.getSnapshot(name);
81
+ }
82
+ /** List the caller's snapshots, one name-ordered page at a time. */
83
+ async listSnapshots(options = {}) {
84
+ return this.client.listSnapshots(options);
85
+ }
86
+ /** Delete a snapshot by name (idempotent 404 if it does not exist). */
87
+ async deleteSnapshot(name) {
88
+ return this.client.deleteSnapshot(name);
89
+ }
54
90
  async destroy(id) {
55
91
  await this.client.destroy(id);
56
92
  }
@@ -77,6 +113,32 @@ export class MicroVM {
77
113
  async health() {
78
114
  return this.client.health();
79
115
  }
116
+ /**
117
+ * Asks whether a sandbox created with these egress fields would reach a
118
+ * destination, using the same matcher the filter enforces. No sandbox is
119
+ * needed.
120
+ */
121
+ async checkNetworkPolicy(options) {
122
+ return this.client.checkNetworkPolicy(options);
123
+ }
124
+ /**
125
+ * Creates or replaces a named egress profile (a full replace: the same body
126
+ * twice is a no-op). Sandboxes reference it through `egressProfiles`, and a
127
+ * change reaches every one of them.
128
+ */
129
+ async putEgressProfile(name, options) {
130
+ return this.client.putEgressProfile(name, options);
131
+ }
132
+ async getEgressProfile(name) {
133
+ return this.client.getEgressProfile(name);
134
+ }
135
+ async listEgressProfiles(options) {
136
+ return this.client.listEgressProfiles(options);
137
+ }
138
+ /** Deletes a profile; one that sandboxes still reference is refused (409). */
139
+ async deleteEgressProfile(name) {
140
+ return this.client.deleteEgressProfile(name);
141
+ }
80
142
  async mounts(sandboxID) {
81
143
  return this.client.mounts(sandboxID);
82
144
  }
@@ -193,6 +255,26 @@ export class MicroVM {
193
255
  target: () => client.ingressDNS(),
194
256
  };
195
257
  }
258
+ /**
259
+ * Who the server says the caller is: principal, role, team and when the
260
+ * credential expires. Every valid credential may ask.
261
+ */
262
+ async whoami() {
263
+ return this.client.whoami();
264
+ }
265
+ /**
266
+ * Scoped API tokens (`avm_…`) for services and CI, as
267
+ * `microvm.tokens.create/list/revoke`. Same namespaced shape as
268
+ * {@link MicroVM.dns}.
269
+ */
270
+ get tokens() {
271
+ const client = this.client;
272
+ return {
273
+ create: (options) => client.createAPIToken(options),
274
+ list: () => client.listAPITokens(),
275
+ revoke: (id) => client.revokeAPIToken(id),
276
+ };
277
+ }
196
278
  wrap(sandbox) {
197
279
  return new Sandbox(this.client, sandbox);
198
280
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { MicroVM } from "./MicroVM.js";
2
2
  export { Sandbox } from "./Sandbox.js";
3
3
  export { Image } from "./Image.js";
4
- export type { MicroVMConfig } from "./MicroVM.js";
4
+ export type { MicroVMConfig, Tokens } from "./MicroVM.js";
5
5
  export type { RetryConfig } from "./internal/client.js";
6
- export type { AddCustomDomainOptions, BinaryLike, BuildImageOptions, BuildImagePushOptions, BuildImageResult, CloneGeneration, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, CustomDomain, CustomDomainDNSRecords, CustomDomainStatus, DNSRecord, DNSRecordType, ExecRequest, ExecResult, ExecExitInfo, ExposedPort, ExposePortOptions, ExposeProtocol, ExposeResult, Failover, FailoverPolicy, HealthStatus, IngressTarget, IngressTargetSource, Lifecycle, MountSpec, MountSpecRedacted, MountType, PlatformVolumeMount, RegisterSnapshotOptions, RegistryAuth, ResizeOptions, Sandbox as SandboxData, SandboxSnapshot, SandboxStatus, Session, SessionAttachHandle, SessionAttachOptions, SessionStatus, Template, TemplatePushState, TemplateStatus, WasmModule, WasmModuleStatus, PushWasmModuleOptions, PushWasmModuleResult, UpdateLifecycleOptions, } from "./types.js";
6
+ export type { AddCustomDomainOptions, APIToken, APITokenList, CreateAPITokenOptions, CreatedAPIToken, WhoAmI, WhoAmIPrincipal, AuditEvent, AuditOptions, AuditPage, EgressProfile, EgressProfileList, EgressProfileOptions, EgressProfileRef, EgressInject, EgressRule, ListEgressProfilesOptions, NetworkLearned, NetworkLearnedEntry, NetworkPolicy, NetworkPolicyCheckOptions, NetworkPolicyCheckResult, NetworkPolicyOptions, BinaryLike, BuildImageOptions, BuildImagePushOptions, BuildImageResult, CloneGeneration, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, CustomDomain, CustomDomainDNSRecords, CustomDomainStatus, DNSRecord, DNSRecordType, ExecRequest, ExecResult, ExecExitInfo, ExposedPort, ExposePortOptions, ExposeProtocol, ExposeResult, Failover, FailoverPolicy, GetOptions, HealthStatus, IngressTarget, IngressTargetSource, Lifecycle, ListOptions, MountSpec, MountSpecRedacted, MountType, PlatformVolumeMount, RegisterSnapshotOptions, ListSnapshotsOptions, SnapshotList, RegistryAuth, ResizeOptions, Sandbox as SandboxData, SandboxSnapshot, SandboxStatus, Session, SessionAttachHandle, SessionAttachOptions, SessionStatus, Template, TemplatePushState, TemplateStatus, WasmModule, WasmModuleStatus, PushWasmModuleOptions, PushWasmModuleResult, UpdateLifecycleOptions, } from "./types.js";
@@ -1,6 +1,11 @@
1
1
  import { Image } from "../Image.js";
2
- import type { AddCustomDomainOptions, BinaryLike, BuildImageOptions, BuildImageResult, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, PushWasmModuleOptions, PushWasmModuleResult, CustomDomain, CloneGeneration, CustomDomainDNSRecords, ExecRequest, ExecResult, ExecStreamHandle, ExecStreamOptions, ExposedPort, ExposePortOptions, ExposeResult, Failover, HealthStatus, IngressTarget, Lifecycle, ListOptions, MountSpecRedacted, NetworkUsage, RegisterSnapshotOptions, SetNetworkLimitsOptions, ResizeOptions, Sandbox, SandboxSnapshot, Session, SessionAttachHandle, SessionAttachOptions, Template, WasmModule } from "../types.js";
2
+ import type { AddCustomDomainOptions, APITokenList, BinaryLike, BuildImageOptions, BuildImageResult, CreateAPITokenOptions, CreatedAPIToken, CreateOptions, CreateSessionOptions, CreateTemplateOptions, CreateWasmModuleOptions, PushWasmModuleOptions, PushWasmModuleResult, CustomDomain, CloneGeneration, CustomDomainDNSRecords, ExecRequest, ExecResult, ExecStreamHandle, ExecStreamOptions, ExposedPort, ExposePortOptions, ExposeResult, Failover, HealthStatus, IngressTarget, Lifecycle, GetOptions, ListOptions, MountSpecRedacted, NetworkUsage, AuditOptions, AuditPage, EgressProfile, EgressProfileList, EgressProfileOptions, EgressProfileRef, EgressRule, ListEgressProfilesOptions, NetworkLearned, NetworkPolicy, NetworkPolicyCheckOptions, NetworkPolicyCheckResult, NetworkPolicyOptions, ListSnapshotsOptions, RegisterSnapshotOptions, SnapshotList, SetNetworkLimitsOptions, ResizeOptions, Sandbox, SandboxSnapshot, Session, SessionAttachHandle, SessionAttachOptions, Template, WasmModule, WhoAmI } from "../types.js";
3
3
  type FetchLike = typeof fetch;
4
+ /**
5
+ * The request header that selects which of a credential's teams a request
6
+ * acts for. Keep in sync with pkg/api.HeaderTeam on the server.
7
+ */
8
+ export declare const TEAM_HEADER = "X-AerolVM-Team";
4
9
  /**
5
10
  * Wire version of the v1-style sandbox endpoints (`/v1/sandboxes`, etc.) this
6
11
  * client speaks. The SDK and the server version independently — bumping the
@@ -36,10 +41,24 @@ export interface RetryConfig {
36
41
  * waits when `maxRetries` is high. Defaults to `5000`.
37
42
  */
38
43
  maxDelayMs?: number;
44
+ /**
45
+ * Cap in milliseconds on the wait before re-sending a 429 or 503. The SDK
46
+ * waits as long as the server's `Retry-After` header asks (seconds or an
47
+ * HTTP date), never less than its own backoff, plus up to a fifth more so
48
+ * clients told the same value spread out; a longer ask is cut to this. A
49
+ * missing or malformed header uses the backoff above. Defaults to
50
+ * `30000`; `0` ignores `Retry-After`.
51
+ */
52
+ maxRetryAfterMs?: number;
39
53
  }
40
54
  export interface APIClientConfig {
41
55
  baseURL: string;
42
56
  patToken?: string;
57
+ /**
58
+ * Sent as the {@link TEAM_HEADER} header on every HTTP request. Empty or
59
+ * absent sends no header.
60
+ */
61
+ team?: string;
43
62
  fetch?: FetchLike;
44
63
  /**
45
64
  * Wire version to call. Defaults to "v1". Pin this if you need a specific
@@ -49,11 +68,37 @@ export interface APIClientConfig {
49
68
  apiVersion?: APIVersion;
50
69
  /**
51
70
  * Retry policy for transient transport errors (socket closed, connection
52
- * reset) and retryable HTTP status codes (429, 502, 503, 504). Pass
53
- * `{ maxRetries: 0 }` to disable retry entirely.
71
+ * reset) and retryable HTTP status codes (421, 429, 502, 503, 504). `exec`
72
+ * is narrower: it retries only failures that prove the command never
73
+ * reached the server (connection refused, connect timeout, DNS) and HTTP
74
+ * 429/503. Pass `{ maxRetries: 0 }` to disable retry entirely.
54
75
  */
55
76
  retry?: RetryConfig;
77
+ /**
78
+ * Cancels the client's HTTP requests: aborting it ends the request in
79
+ * flight and any retry wait, so a call never sits out a long
80
+ * `Retry-After` once aborted. WebSocket streams are not affected.
81
+ */
82
+ signal?: AbortSignal;
56
83
  }
84
+ /**
85
+ * Reads a `Retry-After` value in either form RFC 9110 allows: delta-seconds
86
+ * (`"120"`) or an HTTP date. Returns the wait in milliseconds (0 for a date
87
+ * already past), or `undefined` for an absent or malformed value.
88
+ */
89
+ export declare function parseRetryAfter(value: string | null | undefined, nowMs: number): number | undefined;
90
+ /**
91
+ * How long {@link APIClient.request} waits before re-sending. `attempt`
92
+ * counts from 0, `retryAfter` is a 429/503's `Retry-After` header (null
93
+ * otherwise) and `random` is uniform in [0, 1).
94
+ *
95
+ * Without a usable header it is the exponential backoff ±25%. With one, it
96
+ * never retries sooner than the server asked (nor sooner than the backoff)
97
+ * and adds up to a fifth so clients told the same value spread out.
98
+ * `maxRetryAfterMs` is a hard ceiling: when the server asks for at least
99
+ * that long the client is early anyway, so the spread goes below it instead.
100
+ */
101
+ export declare function retryDelayMs(config: Required<RetryConfig>, attempt: number, retryAfter: string | null, nowMs: number, random: number): number;
57
102
  /**
58
103
  * Trim trailing slashes from a URL without a backtracking regex. The natural
59
104
  * `value.replace(/\/+$/, "")` is an anchored `+` quantifier — a polynomial
@@ -64,9 +109,11 @@ export declare class APIClient {
64
109
  readonly baseURL: string;
65
110
  readonly apiVersion: APIVersion;
66
111
  private readonly patToken;
112
+ private readonly team;
67
113
  private readonly fetchFn;
68
114
  private readonly versionPrefix;
69
115
  private readonly retryConfig;
116
+ private readonly signal;
70
117
  constructor(config: APIClientConfig);
71
118
  /**
72
119
  * Build a versioned API path. Pass the suffix beginning with "/" (e.g.
@@ -90,12 +137,25 @@ export declare class APIClient {
90
137
  buildImage(image: Image, options?: BuildImageOptions): Promise<BuildImageResult>;
91
138
  private resolveImage;
92
139
  list(options?: ListOptions): Promise<SandboxResource[]>;
93
- get(id: string): Promise<SandboxResource>;
140
+ /** Streams bounded cluster-list pages and never accumulates the full fleet. */
141
+ listPages(options?: ListOptions): AsyncGenerator<SandboxResource[]>;
142
+ /**
143
+ * Looks up the caller's sandbox by name with one request. The reply is only
144
+ * trusted when it holds at most one sandbox and that sandbox carries the
145
+ * requested name: a server that predates `?name=` ignores the filter and
146
+ * returns an ordinary list page, and acting on its first row would target
147
+ * the wrong sandbox.
148
+ */
149
+ getByName(name: string, options?: GetOptions): Promise<SandboxResource | null>;
150
+ get(id: string, options?: GetOptions): Promise<SandboxResource>;
94
151
  start(id: string): Promise<SandboxResource>;
95
152
  stop(id: string): Promise<SandboxResource>;
96
153
  createSnapshot(id: string, name: string): Promise<SandboxSnapshot>;
97
154
  registerSnapshot(options: RegisterSnapshotOptions): Promise<SandboxSnapshot>;
98
155
  registerSnapshotFromImage(name: string, image: Image, options?: Omit<RegisterSnapshotOptions, "name" | "image" | "dockerfileContent">): Promise<SandboxSnapshot>;
156
+ getSnapshot(name: string): Promise<SandboxSnapshot>;
157
+ listSnapshots(options?: ListSnapshotsOptions): Promise<SnapshotList>;
158
+ deleteSnapshot(name: string): Promise<void>;
99
159
  destroy(id: string): Promise<void>;
100
160
  resize(id: string, options: ResizeOptions): Promise<SandboxResource>;
101
161
  updateLifecycle(id: string, lifecycle: Lifecycle): Promise<SandboxResource>;
@@ -149,10 +209,18 @@ export declare class APIClient {
149
209
  customDomainDNS(id: string): Promise<CustomDomainDNSRecords>;
150
210
  reconcile(): Promise<void>;
151
211
  health(): Promise<HealthStatus>;
212
+ checkNetworkPolicy(options: NetworkPolicyCheckOptions): Promise<NetworkPolicyCheckResult>;
152
213
  mounts(id: string): Promise<MountSpecRedacted[]>;
153
214
  cloneGeneration(id: string): Promise<CloneGeneration>;
154
215
  getNetworkUsage(id: string): Promise<NetworkUsage>;
216
+ getAudit(id: string, options?: AuditOptions): Promise<AuditPage>;
155
217
  setNetworkLimits(id: string, options: SetNetworkLimitsOptions): Promise<NetworkUsage>;
218
+ setNetworkPolicy(id: string, options: NetworkPolicyOptions): Promise<NetworkPolicy>;
219
+ getNetworkLearned(id: string): Promise<NetworkLearned>;
220
+ putEgressProfile(name: string, options: EgressProfileOptions): Promise<EgressProfile>;
221
+ getEgressProfile(name: string): Promise<EgressProfile>;
222
+ listEgressProfiles(options?: ListEgressProfilesOptions): Promise<EgressProfileList>;
223
+ deleteEgressProfile(name: string): Promise<void>;
156
224
  createTemplate(options: CreateTemplateOptions): Promise<Template>;
157
225
  listTemplates(): Promise<Template[]>;
158
226
  getTemplate(id: string): Promise<Template>;
@@ -163,19 +231,31 @@ export declare class APIClient {
163
231
  deleteWasmModule(id: string): Promise<void>;
164
232
  pushWasmModule(options: PushWasmModuleOptions): Promise<PushWasmModuleResult>;
165
233
  rebuildTemplate(id: string): Promise<Template>;
234
+ whoami(): Promise<WhoAmI>;
235
+ createAPIToken(options: CreateAPITokenOptions): Promise<CreatedAPIToken>;
236
+ listAPITokens(): Promise<APITokenList>;
237
+ revokeAPIToken(id: string): Promise<void>;
166
238
  private wrap;
167
239
  private doJSON;
168
240
  private doBytes;
169
241
  /**
170
242
  * Low-level HTTP request with automatic retry for transient failures.
171
243
  *
172
- * Transport-level errors (socket closed, connection reset, DNS blip) are
173
- * always retried regardless of HTTP method — the request never reached the
174
- * server so there is no idempotency concern.
244
+ * Transport-level errors (socket closed, connection reset, timeouts, DNS
245
+ * blip) and HTTP 421/429/502/503/504 are retried regardless of HTTP method.
246
+ * Several of those failures can happen after the server received the
247
+ * request, so a retry may deliver it twice; that is safe only because every
248
+ * mutating endpoint in the daemon is designed for idempotent retry (e.g.
249
+ * INSERT OR IGNORE + disambiguation).
250
+ *
251
+ * A request passed `{ idempotent: false }` (exec) retries only transport
252
+ * failures that prove the request never left the client and HTTP 429/503;
253
+ * everything else is surfaced to the caller rather than risk running the
254
+ * command twice.
175
255
  *
176
- * HTTP-level retryable codes (429, 502, 503, 504) are retried for ALL
177
- * methods because every mutating endpoint in the daemon is already
178
- * designed for idempotent retry (e.g. INSERT OR IGNORE + disambiguation).
256
+ * A 429 or 503 waits as long as its `Retry-After` asks (see
257
+ * {@link retryDelayMs}). The client's `signal` ends the request and any
258
+ * wait.
179
259
  */
180
260
  private request;
181
261
  }
@@ -192,6 +272,11 @@ export declare class SandboxResource implements Sandbox {
192
272
  osUser: string;
193
273
  env?: Record<string, string>;
194
274
  networkBlockAll: boolean;
275
+ egressStatus?: string;
276
+ egressProfiles?: string[];
277
+ egressProfilesApplied?: EgressProfileRef[];
278
+ networkEgressMode?: string;
279
+ networkEgressRules?: EgressRule[];
195
280
  toolboxEnabled: boolean;
196
281
  sshPublicKey?: string;
197
282
  sshPrivateKey?: string;
@@ -199,6 +284,8 @@ export declare class SandboxResource implements Sandbox {
199
284
  createdAt: string;
200
285
  updatedAt: string;
201
286
  lastActiveAt: string;
287
+ name?: string;
288
+ tags?: Record<string, string>;
202
289
  lastError?: string;
203
290
  containerCommand?: string[];
204
291
  lifecycle: Lifecycle;
@@ -251,6 +338,24 @@ export declare class SandboxResource implements Sandbox {
251
338
  updateLifecycle(lifecycle: Lifecycle): Promise<this>;
252
339
  getNetworkUsage(): Promise<NetworkUsage>;
253
340
  setNetworkLimits(options: SetNetworkLimitsOptions): Promise<NetworkUsage>;
341
+ /**
342
+ * Replaces this sandbox's egress policy while it runs. The call returns
343
+ * once the new policy is enforced; sending the same policy again is a
344
+ * no-op, so it is safe to retry.
345
+ */
346
+ setNetworkPolicy(options: NetworkPolicyOptions): Promise<NetworkPolicy>;
347
+ /**
348
+ * Reads what this sandbox reached in learn mode and the allow list that
349
+ * would have allowed it. A recording stays readable after the sandbox
350
+ * switches to enforce, until it is destroyed.
351
+ */
352
+ learned(): Promise<NetworkLearned>;
353
+ /**
354
+ * Reads this sandbox's audit log: outbound connections and egress denials
355
+ * (`kind: "egress"`), and secret reads. Denials carry `result: "failure"`
356
+ * and the policy `reason`.
357
+ */
358
+ audit(options?: AuditOptions): Promise<AuditPage>;
254
359
  toJSON(): Sandbox;
255
360
  private apply;
256
361
  }