@alibaba-group/opensandbox 0.1.0-dev1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -0
- package/dist/adapters/commandsAdapter.d.ts +22 -0
- package/dist/adapters/commandsAdapter.d.ts.map +1 -0
- package/dist/adapters/commandsAdapter.js +76 -0
- package/dist/adapters/filesystemAdapter.d.ts +52 -0
- package/dist/adapters/filesystemAdapter.d.ts.map +1 -0
- package/dist/adapters/filesystemAdapter.js +398 -0
- package/dist/adapters/healthAdapter.d.ts +8 -0
- package/dist/adapters/healthAdapter.d.ts.map +1 -0
- package/dist/adapters/healthAdapter.js +25 -0
- package/dist/adapters/metricsAdapter.d.ts +9 -0
- package/dist/adapters/metricsAdapter.d.ts.map +1 -0
- package/dist/adapters/metricsAdapter.js +43 -0
- package/dist/adapters/openapiError.d.ts +5 -0
- package/dist/adapters/openapiError.d.ts.map +1 -0
- package/dist/adapters/openapiError.js +33 -0
- package/dist/adapters/sandboxesAdapter.d.ts +18 -0
- package/dist/adapters/sandboxesAdapter.d.ts.map +1 -0
- package/dist/adapters/sandboxesAdapter.js +146 -0
- package/dist/adapters/sse.d.ts +9 -0
- package/dist/adapters/sse.d.ts.map +1 -0
- package/dist/adapters/sse.js +84 -0
- package/dist/api/execd.d.ts +1555 -0
- package/dist/api/execd.d.ts.map +1 -0
- package/dist/api/execd.js +14 -0
- package/dist/api/lifecycle.d.ts +787 -0
- package/dist/api/lifecycle.d.ts.map +1 -0
- package/dist/api/lifecycle.js +14 -0
- package/dist/config/connection.d.ts +58 -0
- package/dist/config/connection.d.ts.map +1 -0
- package/dist/config/connection.js +171 -0
- package/dist/core/constants.d.ts +9 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +24 -0
- package/dist/core/exceptions.d.ts +74 -0
- package/dist/core/exceptions.d.ts.map +1 -0
- package/dist/core/exceptions.js +103 -0
- package/dist/factory/adapterFactory.d.ts +33 -0
- package/dist/factory/adapterFactory.d.ts.map +1 -0
- package/dist/factory/adapterFactory.js +14 -0
- package/dist/factory/defaultAdapterFactory.d.ts +7 -0
- package/dist/factory/defaultAdapterFactory.d.ts.map +1 -0
- package/dist/factory/defaultAdapterFactory.js +61 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/internal.d.ts +22 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +30 -0
- package/dist/manager.d.ts +40 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +71 -0
- package/dist/models/execd.d.ts +54 -0
- package/dist/models/execd.d.ts.map +1 -0
- package/dist/models/execd.js +14 -0
- package/dist/models/execution.d.ts +52 -0
- package/dist/models/execution.d.ts.map +1 -0
- package/dist/models/execution.js +14 -0
- package/dist/models/executionEventDispatcher.d.ts +15 -0
- package/dist/models/executionEventDispatcher.d.ts.map +1 -0
- package/dist/models/executionEventDispatcher.js +95 -0
- package/dist/models/filesystem.d.ts +77 -0
- package/dist/models/filesystem.d.ts.map +1 -0
- package/dist/models/filesystem.js +14 -0
- package/dist/models/sandboxes.d.ts +105 -0
- package/dist/models/sandboxes.d.ts.map +1 -0
- package/dist/models/sandboxes.js +15 -0
- package/dist/openapi/execdClient.d.ts +25 -0
- package/dist/openapi/execdClient.d.ts.map +1 -0
- package/dist/openapi/execdClient.js +21 -0
- package/dist/openapi/lifecycleClient.d.ts +28 -0
- package/dist/openapi/lifecycleClient.d.ts.map +1 -0
- package/dist/openapi/lifecycleClient.js +35 -0
- package/dist/sandbox.d.ts +132 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +250 -0
- package/dist/services/execdCommands.d.ts +19 -0
- package/dist/services/execdCommands.d.ts.map +1 -0
- package/dist/services/execdCommands.js +14 -0
- package/dist/services/execdHealth.d.ts +4 -0
- package/dist/services/execdHealth.d.ts.map +1 -0
- package/dist/services/execdHealth.js +14 -0
- package/dist/services/execdMetrics.d.ts +5 -0
- package/dist/services/execdMetrics.d.ts.map +1 -0
- package/dist/services/execdMetrics.js +14 -0
- package/dist/services/filesystem.d.ts +30 -0
- package/dist/services/filesystem.d.ts.map +1 -0
- package/dist/services/filesystem.js +14 -0
- package/dist/services/sandboxes.d.ts +12 -0
- package/dist/services/sandboxes.d.ts.map +1 -0
- package/dist/services/sandboxes.js +14 -0
- package/package.json +52 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain models for sandbox lifecycle.
|
|
3
|
+
*
|
|
4
|
+
* IMPORTANT:
|
|
5
|
+
* - These are NOT OpenAPI-generated types.
|
|
6
|
+
* - They are intentionally stable and JS-friendly.
|
|
7
|
+
*
|
|
8
|
+
* The internal OpenAPI schemas may change frequently; adapters map responses into these models.
|
|
9
|
+
*/
|
|
10
|
+
export type SandboxId = string;
|
|
11
|
+
export interface ImageAuth extends Record<string, unknown> {
|
|
12
|
+
username?: string;
|
|
13
|
+
password?: string;
|
|
14
|
+
token?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ImageSpec {
|
|
17
|
+
uri: string;
|
|
18
|
+
auth?: ImageAuth;
|
|
19
|
+
}
|
|
20
|
+
export type ResourceLimits = Record<string, string>;
|
|
21
|
+
export type SandboxState = "Creating" | "Running" | "Pausing" | "Paused" | "Resuming" | "Deleting" | "Deleted" | "Error" | string;
|
|
22
|
+
export interface SandboxStatus extends Record<string, unknown> {
|
|
23
|
+
state: SandboxState;
|
|
24
|
+
reason?: string;
|
|
25
|
+
message?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SandboxInfo extends Record<string, unknown> {
|
|
28
|
+
id: SandboxId;
|
|
29
|
+
image: ImageSpec;
|
|
30
|
+
entrypoint: string[];
|
|
31
|
+
metadata?: Record<string, string>;
|
|
32
|
+
status: SandboxStatus;
|
|
33
|
+
/**
|
|
34
|
+
* Sandbox creation time.
|
|
35
|
+
*/
|
|
36
|
+
createdAt: Date;
|
|
37
|
+
/**
|
|
38
|
+
* Sandbox expiration time (server-side TTL).
|
|
39
|
+
*/
|
|
40
|
+
expiresAt: Date;
|
|
41
|
+
}
|
|
42
|
+
export interface CreateSandboxRequest extends Record<string, unknown> {
|
|
43
|
+
image: ImageSpec;
|
|
44
|
+
entrypoint: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Timeout in seconds (server semantics).
|
|
47
|
+
*/
|
|
48
|
+
timeout: number;
|
|
49
|
+
resourceLimits: ResourceLimits;
|
|
50
|
+
env?: Record<string, string>;
|
|
51
|
+
metadata?: Record<string, string>;
|
|
52
|
+
extensions?: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
export interface CreateSandboxResponse extends Record<string, unknown> {
|
|
55
|
+
id: SandboxId;
|
|
56
|
+
status: SandboxStatus;
|
|
57
|
+
metadata?: Record<string, string>;
|
|
58
|
+
/**
|
|
59
|
+
* Sandbox expiration time after creation.
|
|
60
|
+
*/
|
|
61
|
+
expiresAt: Date;
|
|
62
|
+
/**
|
|
63
|
+
* Sandbox creation time.
|
|
64
|
+
*/
|
|
65
|
+
createdAt: Date;
|
|
66
|
+
entrypoint: string[];
|
|
67
|
+
}
|
|
68
|
+
export interface PaginationInfo extends Record<string, unknown> {
|
|
69
|
+
page: number;
|
|
70
|
+
pageSize: number;
|
|
71
|
+
totalItems: number;
|
|
72
|
+
totalPages: number;
|
|
73
|
+
hasNextPage: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface ListSandboxesResponse extends Record<string, unknown> {
|
|
76
|
+
items: SandboxInfo[];
|
|
77
|
+
pagination?: PaginationInfo;
|
|
78
|
+
}
|
|
79
|
+
export interface RenewSandboxExpirationRequest {
|
|
80
|
+
expiresAt: string;
|
|
81
|
+
}
|
|
82
|
+
export interface RenewSandboxExpirationResponse extends Record<string, unknown> {
|
|
83
|
+
/**
|
|
84
|
+
* Updated expiration time (if the server returns it).
|
|
85
|
+
*/
|
|
86
|
+
expiresAt?: Date;
|
|
87
|
+
}
|
|
88
|
+
export interface Endpoint extends Record<string, unknown> {
|
|
89
|
+
endpoint: string;
|
|
90
|
+
}
|
|
91
|
+
export interface ListSandboxesParams {
|
|
92
|
+
/**
|
|
93
|
+
* Filter by lifecycle state (the API supports multiple `state` query params).
|
|
94
|
+
* Example: `{ states: ["Running", "Paused"] }`
|
|
95
|
+
*/
|
|
96
|
+
states?: string[];
|
|
97
|
+
/**
|
|
98
|
+
* Filter by metadata key-value pairs.
|
|
99
|
+
* NOTE: This will be encoded to a single `metadata` query parameter as described in the spec.
|
|
100
|
+
*/
|
|
101
|
+
metadata?: Record<string, string>;
|
|
102
|
+
page?: number;
|
|
103
|
+
pageSize?: number;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=sandboxes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxes.d.ts","sourceRoot":"","sources":["../../src/models/sandboxes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Copyright 2026 Alibaba Group Holding Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Client } from "openapi-fetch";
|
|
2
|
+
import type { paths as ExecdPaths } from "../api/execd.js";
|
|
3
|
+
export type ExecdClient = Client<ExecdPaths>;
|
|
4
|
+
export interface CreateExecdClientOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Base URL to the Execd API (no `/v1` prefix).
|
|
7
|
+
* Examples:
|
|
8
|
+
* - `http://localhost:44772`
|
|
9
|
+
* - `http://api.opensandbox.io/sandboxes/<id>/port/44772`
|
|
10
|
+
*/
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
/**
|
|
13
|
+
* Extra headers applied to every request.
|
|
14
|
+
*/
|
|
15
|
+
headers?: Record<string, string>;
|
|
16
|
+
/**
|
|
17
|
+
* Custom fetch implementation.
|
|
18
|
+
*
|
|
19
|
+
* Useful for proxies, custom TLS, request tracing, retries, or running in environments
|
|
20
|
+
* where a global `fetch` is not available.
|
|
21
|
+
*/
|
|
22
|
+
fetch?: typeof fetch;
|
|
23
|
+
}
|
|
24
|
+
export declare function createExecdClient(opts: CreateExecdClientOptions): ExecdClient;
|
|
25
|
+
//# sourceMappingURL=execdClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execdClient.d.ts","sourceRoot":"","sources":["../../src/openapi/execdClient.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,WAAW,CAM7E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright 2026 Alibaba Group Holding Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import createClient from "openapi-fetch";
|
|
15
|
+
export function createExecdClient(opts) {
|
|
16
|
+
return createClient({
|
|
17
|
+
baseUrl: opts.baseUrl,
|
|
18
|
+
headers: opts.headers,
|
|
19
|
+
fetch: opts.fetch,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Client } from "openapi-fetch";
|
|
2
|
+
import type { paths as LifecyclePaths } from "../api/lifecycle.js";
|
|
3
|
+
export type LifecycleClient = Client<LifecyclePaths>;
|
|
4
|
+
export interface CreateLifecycleClientOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Base URL to OpenSandbox Lifecycle API, including the `/v1` prefix.
|
|
7
|
+
* Example: `http://localhost:8080/v1`
|
|
8
|
+
*/
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
/**
|
|
11
|
+
* API key for `OPEN-SANDBOX-API-KEY` header.
|
|
12
|
+
* If omitted, reads from `process.env.OPEN_SANDBOX_API_KEY` when available.
|
|
13
|
+
*/
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Extra headers applied to every request.
|
|
17
|
+
*/
|
|
18
|
+
headers?: Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Custom fetch implementation.
|
|
21
|
+
*
|
|
22
|
+
* Useful for proxies, custom TLS, request tracing, retries, or running in environments
|
|
23
|
+
* where a global `fetch` is not available.
|
|
24
|
+
*/
|
|
25
|
+
fetch?: typeof fetch;
|
|
26
|
+
}
|
|
27
|
+
export declare function createLifecycleClient(opts?: CreateLifecycleClientOptions): LifecycleClient;
|
|
28
|
+
//# sourceMappingURL=lifecycleClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycleClient.d.ts","sourceRoot":"","sources":["../../src/openapi/lifecycleClient.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAErD,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAUD,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,4BAAiC,GAAG,eAAe,CAgB9F"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Copyright 2026 Alibaba Group Holding Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import createClient from "openapi-fetch";
|
|
15
|
+
function readEnvApiKey() {
|
|
16
|
+
// Avoid requiring @types/node by not referencing `process` directly.
|
|
17
|
+
// In Node, `globalThis.process.env` exists; in browsers it won't.
|
|
18
|
+
const env = globalThis?.process?.env;
|
|
19
|
+
const v = env?.OPEN_SANDBOX_API_KEY;
|
|
20
|
+
return typeof v === "string" && v.length ? v : undefined;
|
|
21
|
+
}
|
|
22
|
+
export function createLifecycleClient(opts = {}) {
|
|
23
|
+
const apiKey = opts.apiKey ?? readEnvApiKey();
|
|
24
|
+
const headers = {
|
|
25
|
+
...(opts.headers ?? {}),
|
|
26
|
+
};
|
|
27
|
+
if (apiKey && !headers["OPEN-SANDBOX-API-KEY"]) {
|
|
28
|
+
headers["OPEN-SANDBOX-API-KEY"] = apiKey;
|
|
29
|
+
}
|
|
30
|
+
return createClient({
|
|
31
|
+
baseUrl: opts.baseUrl ?? "http://localhost:8080/v1",
|
|
32
|
+
headers,
|
|
33
|
+
fetch: opts.fetch,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { ConnectionConfig, type ConnectionConfigOptions } from "./config/connection.js";
|
|
2
|
+
import type { SandboxFiles } from "./services/filesystem.js";
|
|
3
|
+
import type { AdapterFactory } from "./factory/adapterFactory.js";
|
|
4
|
+
import type { Sandboxes } from "./services/sandboxes.js";
|
|
5
|
+
import type { ExecdCommands } from "./services/execdCommands.js";
|
|
6
|
+
import type { ExecdHealth } from "./services/execdHealth.js";
|
|
7
|
+
import type { ExecdMetrics } from "./services/execdMetrics.js";
|
|
8
|
+
import type { Endpoint, RenewSandboxExpirationResponse, SandboxId, SandboxInfo } from "./models/sandboxes.js";
|
|
9
|
+
export interface SandboxCreateOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Connection configuration for calling the OpenSandbox Lifecycle API and the sandbox's execd API.
|
|
12
|
+
*/
|
|
13
|
+
connectionConfig?: ConnectionConfig | ConnectionConfigOptions;
|
|
14
|
+
/**
|
|
15
|
+
* Advanced override: inject a custom adapter factory (custom transports, dependency injection).
|
|
16
|
+
*/
|
|
17
|
+
adapterFactory?: AdapterFactory;
|
|
18
|
+
/**
|
|
19
|
+
* Container image uri, e.g. `python:3.11`
|
|
20
|
+
*/
|
|
21
|
+
image: string | {
|
|
22
|
+
uri: string;
|
|
23
|
+
auth?: {
|
|
24
|
+
username: string;
|
|
25
|
+
password: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
entrypoint?: string[];
|
|
29
|
+
env?: Record<string, string>;
|
|
30
|
+
metadata?: Record<string, string>;
|
|
31
|
+
extensions?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Resource limits applied to the sandbox container.
|
|
34
|
+
*
|
|
35
|
+
* This is forwarded to the Lifecycle API as `resourceLimits`.
|
|
36
|
+
*/
|
|
37
|
+
resource?: Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Sandbox timeout in seconds.
|
|
40
|
+
*/
|
|
41
|
+
timeoutSeconds?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Skip readiness checks during create/connect.
|
|
44
|
+
*
|
|
45
|
+
* When true, the SDK will not wait for lifecycle state `Running` or perform the health check.
|
|
46
|
+
* The returned sandbox instance may not be ready yet.
|
|
47
|
+
*/
|
|
48
|
+
skipHealthCheck?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Optional custom readiness check used by {@link Sandbox.waitUntilReady}.
|
|
51
|
+
*
|
|
52
|
+
* If provided, the SDK will call this function during readiness checks instead of
|
|
53
|
+
* using the default `execd` ping check.
|
|
54
|
+
*/
|
|
55
|
+
healthCheck?: (sbx: Sandbox) => boolean | Promise<boolean>;
|
|
56
|
+
readyTimeoutSeconds?: number;
|
|
57
|
+
healthCheckPollingInterval?: number;
|
|
58
|
+
}
|
|
59
|
+
export interface SandboxConnectOptions {
|
|
60
|
+
connectionConfig?: ConnectionConfig | ConnectionConfigOptions;
|
|
61
|
+
adapterFactory?: AdapterFactory;
|
|
62
|
+
sandboxId: SandboxId;
|
|
63
|
+
skipHealthCheck?: boolean;
|
|
64
|
+
healthCheck?: (sbx: Sandbox) => boolean | Promise<boolean>;
|
|
65
|
+
readyTimeoutSeconds?: number;
|
|
66
|
+
healthCheckPollingInterval?: number;
|
|
67
|
+
}
|
|
68
|
+
export declare class Sandbox {
|
|
69
|
+
readonly id: SandboxId;
|
|
70
|
+
readonly connectionConfig: ConnectionConfig;
|
|
71
|
+
/**
|
|
72
|
+
* Lifecycle (sandbox management) service.
|
|
73
|
+
*/
|
|
74
|
+
readonly sandboxes: Sandboxes;
|
|
75
|
+
/**
|
|
76
|
+
* Execd services.
|
|
77
|
+
*/
|
|
78
|
+
readonly commands: ExecdCommands;
|
|
79
|
+
/**
|
|
80
|
+
* High-level filesystem facade (JS-friendly).
|
|
81
|
+
*/
|
|
82
|
+
readonly files: SandboxFiles;
|
|
83
|
+
readonly health: ExecdHealth;
|
|
84
|
+
readonly metrics: ExecdMetrics;
|
|
85
|
+
/**
|
|
86
|
+
* Internal state kept out of the public instance shape.
|
|
87
|
+
*
|
|
88
|
+
* This avoids nominal typing issues when multiple copies of the SDK exist in a dependency graph.
|
|
89
|
+
*/
|
|
90
|
+
private static readonly _priv;
|
|
91
|
+
private constructor();
|
|
92
|
+
static create(opts: SandboxCreateOptions): Promise<Sandbox>;
|
|
93
|
+
static connect(opts: SandboxConnectOptions): Promise<Sandbox>;
|
|
94
|
+
getInfo(): Promise<SandboxInfo>;
|
|
95
|
+
isHealthy(): Promise<boolean>;
|
|
96
|
+
getMetrics(): Promise<import("./index.js").SandboxMetrics>;
|
|
97
|
+
pause(): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Resume a paused sandbox and return a fresh, connected Sandbox instance.
|
|
100
|
+
*
|
|
101
|
+
* After resume, the execd endpoint may change, so this method returns a new
|
|
102
|
+
* {@link Sandbox} instance with a refreshed execd base URL.
|
|
103
|
+
*/
|
|
104
|
+
resume(opts?: {
|
|
105
|
+
skipHealthCheck?: boolean;
|
|
106
|
+
readyTimeoutSeconds?: number;
|
|
107
|
+
healthCheckPollingInterval?: number;
|
|
108
|
+
}): Promise<Sandbox>;
|
|
109
|
+
/**
|
|
110
|
+
* Resume a paused sandbox by id, then connect to its execd endpoint.
|
|
111
|
+
*/
|
|
112
|
+
static resume(opts: SandboxConnectOptions): Promise<Sandbox>;
|
|
113
|
+
kill(): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Renew expiration by setting expiresAt to now + timeoutSeconds.
|
|
116
|
+
*/
|
|
117
|
+
renew(timeoutSeconds: number): Promise<RenewSandboxExpirationResponse>;
|
|
118
|
+
/**
|
|
119
|
+
* Get sandbox endpoint for a port (STRICT: no scheme), e.g. "localhost:44772" or "domain/route/.../44772".
|
|
120
|
+
*/
|
|
121
|
+
getEndpoint(port: number): Promise<Endpoint>;
|
|
122
|
+
/**
|
|
123
|
+
* Get absolute endpoint URL with scheme (convenience for HTTP clients).
|
|
124
|
+
*/
|
|
125
|
+
getEndpointUrl(port: number): Promise<string>;
|
|
126
|
+
waitUntilReady(opts: {
|
|
127
|
+
readyTimeoutSeconds: number;
|
|
128
|
+
pollingIntervalMillis: number;
|
|
129
|
+
healthCheck?: (sbx: Sandbox) => boolean | Promise<boolean>;
|
|
130
|
+
}): Promise<void>;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=sandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
|
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
// Copyright 2026 Alibaba Group Holding Ltd.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
import { DEFAULT_ENTRYPOINT, DEFAULT_EXECD_PORT, DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS, DEFAULT_READY_TIMEOUT_SECONDS, DEFAULT_RESOURCE_LIMITS, DEFAULT_TIMEOUT_SECONDS, } from "./core/constants.js";
|
|
15
|
+
import { ConnectionConfig } from "./config/connection.js";
|
|
16
|
+
import { createDefaultAdapterFactory } from "./factory/defaultAdapterFactory.js";
|
|
17
|
+
import { SandboxReadyTimeoutException } from "./core/exceptions.js";
|
|
18
|
+
function sleep(ms) {
|
|
19
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
20
|
+
}
|
|
21
|
+
function toImageSpec(image) {
|
|
22
|
+
if (typeof image === "string")
|
|
23
|
+
return { uri: image };
|
|
24
|
+
return { uri: image.uri, auth: image.auth };
|
|
25
|
+
}
|
|
26
|
+
export class Sandbox {
|
|
27
|
+
id;
|
|
28
|
+
connectionConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Lifecycle (sandbox management) service.
|
|
31
|
+
*/
|
|
32
|
+
sandboxes;
|
|
33
|
+
/**
|
|
34
|
+
* Execd services.
|
|
35
|
+
*/
|
|
36
|
+
commands;
|
|
37
|
+
/**
|
|
38
|
+
* High-level filesystem facade (JS-friendly).
|
|
39
|
+
*/
|
|
40
|
+
files;
|
|
41
|
+
health;
|
|
42
|
+
metrics;
|
|
43
|
+
/**
|
|
44
|
+
* Internal state kept out of the public instance shape.
|
|
45
|
+
*
|
|
46
|
+
* This avoids nominal typing issues when multiple copies of the SDK exist in a dependency graph.
|
|
47
|
+
*/
|
|
48
|
+
static _priv = new WeakMap();
|
|
49
|
+
constructor(opts) {
|
|
50
|
+
this.id = opts.id;
|
|
51
|
+
this.connectionConfig = opts.connectionConfig;
|
|
52
|
+
Sandbox._priv.set(this, {
|
|
53
|
+
adapterFactory: opts.adapterFactory,
|
|
54
|
+
lifecycleBaseUrl: opts.lifecycleBaseUrl,
|
|
55
|
+
execdBaseUrl: opts.execdBaseUrl,
|
|
56
|
+
});
|
|
57
|
+
this.sandboxes = opts.sandboxes;
|
|
58
|
+
this.commands = opts.commands;
|
|
59
|
+
this.files = opts.files;
|
|
60
|
+
this.health = opts.health;
|
|
61
|
+
this.metrics = opts.metrics;
|
|
62
|
+
}
|
|
63
|
+
static async create(opts) {
|
|
64
|
+
const connectionConfig = opts.connectionConfig instanceof ConnectionConfig
|
|
65
|
+
? opts.connectionConfig
|
|
66
|
+
: new ConnectionConfig(opts.connectionConfig);
|
|
67
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
68
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
69
|
+
const { sandboxes } = adapterFactory.createLifecycleStack({
|
|
70
|
+
connectionConfig,
|
|
71
|
+
lifecycleBaseUrl,
|
|
72
|
+
});
|
|
73
|
+
const req = {
|
|
74
|
+
image: toImageSpec(opts.image),
|
|
75
|
+
entrypoint: opts.entrypoint ?? DEFAULT_ENTRYPOINT,
|
|
76
|
+
timeout: Math.max(60, Math.floor(opts.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS)),
|
|
77
|
+
resourceLimits: opts.resource ?? DEFAULT_RESOURCE_LIMITS,
|
|
78
|
+
env: opts.env ?? {},
|
|
79
|
+
metadata: opts.metadata ?? {},
|
|
80
|
+
extensions: opts.extensions ?? {},
|
|
81
|
+
};
|
|
82
|
+
const created = await sandboxes.createSandbox(req);
|
|
83
|
+
const sandboxId = created.id;
|
|
84
|
+
const endpoint = await sandboxes.getSandboxEndpoint(sandboxId, DEFAULT_EXECD_PORT);
|
|
85
|
+
const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
|
|
86
|
+
const { commands, files, health, metrics } = adapterFactory.createExecdStack({
|
|
87
|
+
connectionConfig,
|
|
88
|
+
execdBaseUrl,
|
|
89
|
+
});
|
|
90
|
+
const sbx = new Sandbox({
|
|
91
|
+
id: sandboxId,
|
|
92
|
+
connectionConfig,
|
|
93
|
+
adapterFactory,
|
|
94
|
+
lifecycleBaseUrl,
|
|
95
|
+
execdBaseUrl,
|
|
96
|
+
sandboxes,
|
|
97
|
+
commands,
|
|
98
|
+
files,
|
|
99
|
+
health,
|
|
100
|
+
metrics,
|
|
101
|
+
});
|
|
102
|
+
if (!(opts.skipHealthCheck ?? false)) {
|
|
103
|
+
await sbx.waitUntilReady({
|
|
104
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds ?? DEFAULT_READY_TIMEOUT_SECONDS,
|
|
105
|
+
pollingIntervalMillis: opts.healthCheckPollingInterval ??
|
|
106
|
+
DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS,
|
|
107
|
+
healthCheck: opts.healthCheck,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return sbx;
|
|
111
|
+
}
|
|
112
|
+
static async connect(opts) {
|
|
113
|
+
const connectionConfig = opts.connectionConfig instanceof ConnectionConfig
|
|
114
|
+
? opts.connectionConfig
|
|
115
|
+
: new ConnectionConfig(opts.connectionConfig);
|
|
116
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
117
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
118
|
+
const { sandboxes } = adapterFactory.createLifecycleStack({
|
|
119
|
+
connectionConfig,
|
|
120
|
+
lifecycleBaseUrl,
|
|
121
|
+
});
|
|
122
|
+
const endpoint = await sandboxes.getSandboxEndpoint(opts.sandboxId, DEFAULT_EXECD_PORT);
|
|
123
|
+
const execdBaseUrl = `${connectionConfig.protocol}://${endpoint.endpoint}`;
|
|
124
|
+
const { commands, files, health, metrics } = adapterFactory.createExecdStack({
|
|
125
|
+
connectionConfig,
|
|
126
|
+
execdBaseUrl,
|
|
127
|
+
});
|
|
128
|
+
const sbx = new Sandbox({
|
|
129
|
+
id: opts.sandboxId,
|
|
130
|
+
connectionConfig,
|
|
131
|
+
adapterFactory,
|
|
132
|
+
lifecycleBaseUrl,
|
|
133
|
+
execdBaseUrl,
|
|
134
|
+
sandboxes,
|
|
135
|
+
commands,
|
|
136
|
+
files,
|
|
137
|
+
health,
|
|
138
|
+
metrics,
|
|
139
|
+
});
|
|
140
|
+
if (!(opts.skipHealthCheck ?? false)) {
|
|
141
|
+
await sbx.waitUntilReady({
|
|
142
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds ?? DEFAULT_READY_TIMEOUT_SECONDS,
|
|
143
|
+
pollingIntervalMillis: opts.healthCheckPollingInterval ??
|
|
144
|
+
DEFAULT_HEALTH_CHECK_POLLING_INTERVAL_MILLIS,
|
|
145
|
+
healthCheck: opts.healthCheck,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return sbx;
|
|
149
|
+
}
|
|
150
|
+
async getInfo() {
|
|
151
|
+
return await this.sandboxes.getSandbox(this.id);
|
|
152
|
+
}
|
|
153
|
+
async isHealthy() {
|
|
154
|
+
try {
|
|
155
|
+
return await this.health.ping();
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async getMetrics() {
|
|
162
|
+
return await this.metrics.getMetrics();
|
|
163
|
+
}
|
|
164
|
+
async pause() {
|
|
165
|
+
await this.sandboxes.pauseSandbox(this.id);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Resume a paused sandbox and return a fresh, connected Sandbox instance.
|
|
169
|
+
*
|
|
170
|
+
* After resume, the execd endpoint may change, so this method returns a new
|
|
171
|
+
* {@link Sandbox} instance with a refreshed execd base URL.
|
|
172
|
+
*/
|
|
173
|
+
async resume(opts = {}) {
|
|
174
|
+
await this.sandboxes.resumeSandbox(this.id);
|
|
175
|
+
return await Sandbox.connect({
|
|
176
|
+
sandboxId: this.id,
|
|
177
|
+
connectionConfig: this.connectionConfig,
|
|
178
|
+
adapterFactory: Sandbox._priv.get(this).adapterFactory,
|
|
179
|
+
skipHealthCheck: opts.skipHealthCheck ?? false,
|
|
180
|
+
readyTimeoutSeconds: opts.readyTimeoutSeconds,
|
|
181
|
+
healthCheckPollingInterval: opts.healthCheckPollingInterval,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Resume a paused sandbox by id, then connect to its execd endpoint.
|
|
186
|
+
*/
|
|
187
|
+
static async resume(opts) {
|
|
188
|
+
const connectionConfig = opts.connectionConfig instanceof ConnectionConfig
|
|
189
|
+
? opts.connectionConfig
|
|
190
|
+
: new ConnectionConfig(opts.connectionConfig);
|
|
191
|
+
const adapterFactory = opts.adapterFactory ?? createDefaultAdapterFactory();
|
|
192
|
+
const lifecycleBaseUrl = connectionConfig.getBaseUrl();
|
|
193
|
+
const { sandboxes } = adapterFactory.createLifecycleStack({
|
|
194
|
+
connectionConfig,
|
|
195
|
+
lifecycleBaseUrl,
|
|
196
|
+
});
|
|
197
|
+
await sandboxes.resumeSandbox(opts.sandboxId);
|
|
198
|
+
return await Sandbox.connect({ ...opts, connectionConfig, adapterFactory });
|
|
199
|
+
}
|
|
200
|
+
async kill() {
|
|
201
|
+
await this.sandboxes.deleteSandbox(this.id);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Renew expiration by setting expiresAt to now + timeoutSeconds.
|
|
205
|
+
*/
|
|
206
|
+
async renew(timeoutSeconds) {
|
|
207
|
+
const expiresAt = new Date(Date.now() + timeoutSeconds * 1000).toISOString();
|
|
208
|
+
return await this.sandboxes.renewSandboxExpiration(this.id, { expiresAt });
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get sandbox endpoint for a port (STRICT: no scheme), e.g. "localhost:44772" or "domain/route/.../44772".
|
|
212
|
+
*/
|
|
213
|
+
async getEndpoint(port) {
|
|
214
|
+
return await this.sandboxes.getSandboxEndpoint(this.id, port);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get absolute endpoint URL with scheme (convenience for HTTP clients).
|
|
218
|
+
*/
|
|
219
|
+
async getEndpointUrl(port) {
|
|
220
|
+
const ep = await this.getEndpoint(port);
|
|
221
|
+
return `${this.connectionConfig.protocol}://${ep.endpoint}`;
|
|
222
|
+
}
|
|
223
|
+
async waitUntilReady(opts) {
|
|
224
|
+
const deadline = Date.now() + opts.readyTimeoutSeconds * 1000;
|
|
225
|
+
// Wait until execd becomes reachable and passes health check.
|
|
226
|
+
while (true) {
|
|
227
|
+
if (Date.now() > deadline) {
|
|
228
|
+
throw new SandboxReadyTimeoutException({
|
|
229
|
+
message: `Sandbox not ready: timed out waiting for health check (timeoutSeconds=${opts.readyTimeoutSeconds})`,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
if (opts.healthCheck) {
|
|
234
|
+
const ok = await opts.healthCheck(this);
|
|
235
|
+
if (ok)
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
const ok = await this.health.ping();
|
|
240
|
+
if (ok)
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// ignore and retry
|
|
246
|
+
}
|
|
247
|
+
await sleep(opts.pollingIntervalMillis);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ExecutionHandlers } from "../models/execution.js";
|
|
2
|
+
import type { CommandExecution, RunCommandOpts, ServerStreamEvent } from "../models/execd.js";
|
|
3
|
+
export interface ExecdCommands {
|
|
4
|
+
/**
|
|
5
|
+
* Run a command and stream server events (SSE). This is the lowest-level API.
|
|
6
|
+
*/
|
|
7
|
+
runStream(command: string, opts?: RunCommandOpts, signal?: AbortSignal): AsyncIterable<ServerStreamEvent>;
|
|
8
|
+
/**
|
|
9
|
+
* Convenience: run a command, consume the stream, and build a structured execution result.
|
|
10
|
+
*/
|
|
11
|
+
run(command: string, opts?: RunCommandOpts, handlers?: ExecutionHandlers, signal?: AbortSignal): Promise<CommandExecution>;
|
|
12
|
+
/**
|
|
13
|
+
* Interrupt the current execution in the given context/session.
|
|
14
|
+
*
|
|
15
|
+
* Note: Execd spec uses `DELETE /command?id=<sessionId>`.
|
|
16
|
+
*/
|
|
17
|
+
interrupt(sessionId: string): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=execdCommands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execdCommands.d.ts","sourceRoot":"","sources":["../../src/services/execdCommands.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9F,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAE1G;;OAEG;IACH,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE3H;;;;OAIG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C"}
|