@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 +91 -5
- package/dist/MicroVM.js +86 -4
- package/dist/index.d.ts +2 -2
- package/dist/internal/client.d.ts +115 -10
- package/dist/internal/client.js +515 -39
- package/dist/types.d.ts +379 -14
- package/package.json +9 -4
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.
|
|
21
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
34
|
-
|
|
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).
|
|
53
|
-
*
|
|
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
|
-
|
|
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
|
|
173
|
-
*
|
|
174
|
-
*
|
|
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
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
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
|
}
|