@fastgpt-sdk/sandbox-adapter 0.0.30 → 0.0.32
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/adapters/BaseSandboxAdapter.d.ts +2 -1
- package/dist/adapters/E2BAdapter/type.d.ts +1 -1
- package/dist/adapters/OpenSandboxAdapter/index.d.ts +9 -10
- package/dist/adapters/OpenSandboxAdapter/type.d.ts +1 -1
- package/dist/adapters/SealosDevboxAdapter/index.d.ts +0 -1
- package/dist/adapters/index.d.ts +1 -1
- package/dist/index.cjs +106 -44
- package/dist/index.d.ts +1 -0
- package/dist/index.js +106 -44
- package/dist/interfaces/ISandboxLifecycle.d.ts +2 -1
- package/package.json +2 -4
- package/opensandbox/chunk-PHJSF3IJ.js +0 -1067
- package/opensandbox/chunk-PHJSF3IJ.js.map +0 -1
- package/opensandbox/cjs/index.cjs +0 -1912
- package/opensandbox/cjs/index.cjs.map +0 -1
- package/opensandbox/cjs/internal.cjs +0 -1060
- package/opensandbox/cjs/internal.cjs.map +0 -1
- package/opensandbox/index.d.ts +0 -463
- package/opensandbox/index.js +0 -826
- package/opensandbox/index.js.map +0 -1
- package/opensandbox/internal.d.ts +0 -2862
- package/opensandbox/internal.js +0 -19
- package/opensandbox/internal.js.map +0 -1
- package/opensandbox/package.json +0 -15
- package/opensandbox/sandboxes-pbhLrfFS.d.ts +0 -498
|
@@ -9,7 +9,7 @@ import type { ContentReplaceEntry, DirectoryEntry, ExecuteOptions, ExecuteResult
|
|
|
9
9
|
* Subclasses can override the polyfill service in their constructor.
|
|
10
10
|
*/
|
|
11
11
|
export declare abstract class BaseSandboxAdapter implements ISandbox {
|
|
12
|
-
abstract readonly id
|
|
12
|
+
abstract readonly id?: SandboxId;
|
|
13
13
|
abstract readonly provider: string;
|
|
14
14
|
protected _status: SandboxStatus;
|
|
15
15
|
protected polyfillService?: CommandPolyfillService;
|
|
@@ -22,6 +22,7 @@ export declare abstract class BaseSandboxAdapter implements ISandbox {
|
|
|
22
22
|
abstract delete(): Promise<void>;
|
|
23
23
|
abstract getInfo(): Promise<SandboxInfo | null>;
|
|
24
24
|
waitUntilReady(timeoutMs?: number): Promise<void>;
|
|
25
|
+
waitUntilDeleted(timeoutMs?: number): Promise<void>;
|
|
25
26
|
renewExpiration(_additionalSeconds: number): Promise<void>;
|
|
26
27
|
abstract execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
27
28
|
executeStream(command: string, handlers: StreamHandlers, options?: ExecuteOptions): Promise<void>;
|
|
@@ -12,8 +12,9 @@ export type SandboxRuntimeType = 'docker' | 'kubernetes';
|
|
|
12
12
|
* Connection configuration options for OpenSandboxAdapter.
|
|
13
13
|
*/
|
|
14
14
|
export interface OpenSandboxConnectionConfig {
|
|
15
|
+
sessionId: string;
|
|
15
16
|
/** Base URL for the OpenSandbox API */
|
|
16
|
-
baseUrl
|
|
17
|
+
baseUrl: string;
|
|
17
18
|
/** API key for authentication */
|
|
18
19
|
apiKey?: string;
|
|
19
20
|
/** SDK request timeout in seconds */
|
|
@@ -50,14 +51,15 @@ export interface OpenSandboxConnectionConfig {
|
|
|
50
51
|
*/
|
|
51
52
|
export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
52
53
|
private connectionConfig;
|
|
53
|
-
private createConfig
|
|
54
|
+
private createConfig;
|
|
54
55
|
readonly provider: "opensandbox";
|
|
55
56
|
readonly runtime: SandboxRuntimeType;
|
|
56
57
|
private _sandbox?;
|
|
57
58
|
private _connection;
|
|
58
|
-
private _id
|
|
59
|
-
constructor(connectionConfig
|
|
60
|
-
get id(): SandboxId;
|
|
59
|
+
private _id?;
|
|
60
|
+
constructor(connectionConfig: OpenSandboxConnectionConfig, createConfig: OpenSandboxConfigType);
|
|
61
|
+
get id(): SandboxId | undefined;
|
|
62
|
+
private set sandbox(value);
|
|
61
63
|
private get sandbox();
|
|
62
64
|
private createConnectionConfig;
|
|
63
65
|
private static readonly STATE_MAP;
|
|
@@ -67,9 +69,11 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
67
69
|
private convertResourceLimits;
|
|
68
70
|
private parseResourceLimits;
|
|
69
71
|
private extractExitCode;
|
|
72
|
+
private getSandboxBySessionId;
|
|
70
73
|
ensureRunning(): Promise<void>;
|
|
71
74
|
create(): Promise<void>;
|
|
72
75
|
connect(sandboxId: string): Promise<void>;
|
|
76
|
+
private resume;
|
|
73
77
|
start(): Promise<void>;
|
|
74
78
|
stop(): Promise<void>;
|
|
75
79
|
delete(): Promise<void>;
|
|
@@ -85,11 +89,6 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
85
89
|
* @returns Endpoint with host, port, protocol and url fields
|
|
86
90
|
*/
|
|
87
91
|
getEndpoint(port: number): Promise<Endpoint>;
|
|
88
|
-
/**
|
|
89
|
-
* Convert SDK Endpoint (no-scheme string) to our Endpoint type.
|
|
90
|
-
* SDK format: "localhost:44772" or "domain/route/.../44772"
|
|
91
|
-
*/
|
|
92
|
-
private convertSdkEndpoint;
|
|
93
92
|
getInfo(): Promise<SandboxInfo | null>;
|
|
94
93
|
renewExpiration(additionalSeconds: number): Promise<void>;
|
|
95
94
|
execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
@@ -18,7 +18,6 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
18
18
|
constructor(config: SealosDevboxConfig);
|
|
19
19
|
get id(): SandboxId;
|
|
20
20
|
private StatusAdapt;
|
|
21
|
-
private waitUntilDeleted;
|
|
22
21
|
getInfo(): Promise<SandboxInfo | null>;
|
|
23
22
|
ensureRunning(): Promise<void>;
|
|
24
23
|
create(): Promise<void>;
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { SealosDevboxAdapter } from './SealosDevboxAdapter';
|
|
|
6
6
|
export type { SealosDevboxConfig } from './SealosDevboxAdapter';
|
|
7
7
|
export { OpenSandboxAdapter } from './OpenSandboxAdapter';
|
|
8
8
|
export type { OpenSandboxConfigType, OpenSandboxConnectionConfig } from './OpenSandboxAdapter';
|
|
9
|
-
export type { Volume as OpenSandboxVolume } from '
|
|
9
|
+
export type { Volume as OpenSandboxVolume } from '../../opensandbox';
|
|
10
10
|
export { E2BAdapter } from './E2BAdapter';
|
|
11
11
|
export type { E2BConfig } from './E2BAdapter';
|
|
12
12
|
export type SandboxProviderType = 'opensandbox' | 'sealosdevbox' | 'e2b';
|
package/dist/index.cjs
CHANGED
|
@@ -47519,7 +47519,19 @@ class BaseSandboxAdapter {
|
|
|
47519
47519
|
}
|
|
47520
47520
|
await this.sleep(checkInterval);
|
|
47521
47521
|
}
|
|
47522
|
-
throw new SandboxReadyTimeoutError(this.id, timeoutMs);
|
|
47522
|
+
throw new SandboxReadyTimeoutError(this.id ?? "Unknown", timeoutMs);
|
|
47523
|
+
}
|
|
47524
|
+
async waitUntilDeleted(timeoutMs = 120000) {
|
|
47525
|
+
const startTime = Date.now();
|
|
47526
|
+
const checkInterval = 1000;
|
|
47527
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
47528
|
+
const data = await this.getInfo().catch(() => true);
|
|
47529
|
+
if (!data) {
|
|
47530
|
+
return;
|
|
47531
|
+
}
|
|
47532
|
+
await this.sleep(checkInterval);
|
|
47533
|
+
}
|
|
47534
|
+
throw new SandboxReadyTimeoutError(this.id ?? "Unknown", timeoutMs);
|
|
47523
47535
|
}
|
|
47524
47536
|
async renewExpiration(_additionalSeconds) {
|
|
47525
47537
|
throw new FeatureNotSupportedError("Sandbox expiration renewal not supported by this provider", "renewExpiration", this.provider);
|
|
@@ -47854,18 +47866,6 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
47854
47866
|
return "Error";
|
|
47855
47867
|
}
|
|
47856
47868
|
}
|
|
47857
|
-
async waitUntilDeleted() {
|
|
47858
|
-
const startTime = Date.now();
|
|
47859
|
-
const checkInterval = 1000;
|
|
47860
|
-
while (Date.now() - startTime < 120000) {
|
|
47861
|
-
const data = await this.getInfo().catch(() => true);
|
|
47862
|
-
if (!data) {
|
|
47863
|
-
return;
|
|
47864
|
-
}
|
|
47865
|
-
await this.sleep(checkInterval);
|
|
47866
|
-
}
|
|
47867
|
-
throw new TimeoutError("Sandbox not deleted", 120000, "waitUntilDeleted");
|
|
47868
|
-
}
|
|
47869
47869
|
async getInfo() {
|
|
47870
47870
|
try {
|
|
47871
47871
|
const res = await this.api.info(this._id);
|
|
@@ -47995,8 +47995,8 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
47995
47995
|
runtime;
|
|
47996
47996
|
_sandbox;
|
|
47997
47997
|
_connection;
|
|
47998
|
-
_id
|
|
47999
|
-
constructor(connectionConfig
|
|
47998
|
+
_id;
|
|
47999
|
+
constructor(connectionConfig, createConfig) {
|
|
48000
48000
|
super();
|
|
48001
48001
|
this.connectionConfig = connectionConfig;
|
|
48002
48002
|
this.createConfig = createConfig;
|
|
@@ -48007,6 +48007,10 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48007
48007
|
get id() {
|
|
48008
48008
|
return this._id;
|
|
48009
48009
|
}
|
|
48010
|
+
set sandbox(sandbox) {
|
|
48011
|
+
this._sandbox = sandbox;
|
|
48012
|
+
this._id = sandbox?.id;
|
|
48013
|
+
}
|
|
48010
48014
|
get sandbox() {
|
|
48011
48015
|
if (!this._sandbox) {
|
|
48012
48016
|
throw new SandboxStateError("Sandbox not initialized. Call create() or connect() first.", "UnExist", "Running");
|
|
@@ -48015,9 +48019,6 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48015
48019
|
}
|
|
48016
48020
|
createConnectionConfig() {
|
|
48017
48021
|
const { baseUrl, apiKey, requestTimeoutSeconds, debug, useServerProxy } = this.connectionConfig;
|
|
48018
|
-
if (!baseUrl) {
|
|
48019
|
-
return new import_opensandbox.ConnectionConfig({ apiKey, requestTimeoutSeconds, debug, useServerProxy });
|
|
48020
|
-
}
|
|
48021
48022
|
return new import_opensandbox.ConnectionConfig({
|
|
48022
48023
|
domain: baseUrl,
|
|
48023
48024
|
apiKey,
|
|
@@ -48128,32 +48129,74 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48128
48129
|
}
|
|
48129
48130
|
return 0;
|
|
48130
48131
|
}
|
|
48132
|
+
async getSandboxBySessionId() {
|
|
48133
|
+
const manager = import_opensandbox.SandboxManager.create({ connectionConfig: this._connection });
|
|
48134
|
+
const result = await manager.listSandboxInfos({
|
|
48135
|
+
metadata: { sessionId: this.connectionConfig.sessionId }
|
|
48136
|
+
});
|
|
48137
|
+
const val = result.items[0];
|
|
48138
|
+
if (val) {
|
|
48139
|
+
const status = this.mapStatus(val.status);
|
|
48140
|
+
return {
|
|
48141
|
+
id: val.id,
|
|
48142
|
+
status
|
|
48143
|
+
};
|
|
48144
|
+
}
|
|
48145
|
+
}
|
|
48131
48146
|
async ensureRunning() {
|
|
48132
|
-
|
|
48147
|
+
const sandbox = await this.getSandboxBySessionId();
|
|
48148
|
+
if (sandbox) {
|
|
48149
|
+
switch (sandbox.status.state) {
|
|
48150
|
+
case "UnExist":
|
|
48151
|
+
await this.create();
|
|
48152
|
+
break;
|
|
48153
|
+
case "Running":
|
|
48154
|
+
await this.connect(sandbox.id);
|
|
48155
|
+
break;
|
|
48156
|
+
case "Creating":
|
|
48157
|
+
case "Starting":
|
|
48158
|
+
await this.waitUntilReady();
|
|
48159
|
+
break;
|
|
48160
|
+
case "Stopping":
|
|
48161
|
+
case "Stopped":
|
|
48162
|
+
await this.resume(sandbox.id);
|
|
48163
|
+
break;
|
|
48164
|
+
case "Deleting":
|
|
48165
|
+
await this.waitUntilDeleted();
|
|
48166
|
+
await this.create();
|
|
48167
|
+
break;
|
|
48168
|
+
case "Error":
|
|
48169
|
+
throw new ConnectionError(`Sandbox error: ${sandbox.status.message}`);
|
|
48170
|
+
default:
|
|
48171
|
+
throw new ConnectionError(`Sandbox state ${sandbox.status.state} not supported`);
|
|
48172
|
+
}
|
|
48173
|
+
} else {
|
|
48174
|
+
await this.create();
|
|
48175
|
+
}
|
|
48133
48176
|
}
|
|
48134
48177
|
async create() {
|
|
48135
|
-
if (!this.createConfig) {
|
|
48136
|
-
throw new Error("createConfig is required to create a sandbox. Pass it as the third argument to createSandbox().");
|
|
48137
|
-
}
|
|
48138
48178
|
const cfg = this.createConfig;
|
|
48139
48179
|
try {
|
|
48140
48180
|
this._status = { state: "Creating" };
|
|
48141
48181
|
const image = this.convertImageSpec(cfg.image);
|
|
48142
48182
|
const resource = this.convertResourceLimits(cfg.resourceLimits);
|
|
48143
|
-
this.
|
|
48183
|
+
this.sandbox = await import_opensandbox.Sandbox.create({
|
|
48144
48184
|
connectionConfig: this._connection,
|
|
48145
48185
|
image,
|
|
48146
48186
|
entrypoint: cfg.entrypoint,
|
|
48147
48187
|
timeoutSeconds: cfg.timeoutSeconds ?? null,
|
|
48148
48188
|
resource,
|
|
48149
48189
|
env: cfg.env,
|
|
48150
|
-
metadata:
|
|
48190
|
+
metadata: {
|
|
48191
|
+
...cfg.metadata,
|
|
48192
|
+
sessionId: this.connectionConfig.sessionId
|
|
48193
|
+
},
|
|
48151
48194
|
volumes: cfg.volumes,
|
|
48152
48195
|
skipHealthCheck: cfg.skipHealthCheck,
|
|
48153
48196
|
readyTimeoutSeconds: cfg.readyTimeoutSeconds,
|
|
48154
48197
|
healthCheckPollingInterval: cfg.healthCheckPollingInterval
|
|
48155
48198
|
});
|
|
48156
|
-
|
|
48199
|
+
await this.waitUntilReady();
|
|
48157
48200
|
this._status = { state: "Running" };
|
|
48158
48201
|
} catch (error) {
|
|
48159
48202
|
this._status = { state: "Error", message: String(error) };
|
|
@@ -48163,31 +48206,51 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48163
48206
|
async connect(sandboxId) {
|
|
48164
48207
|
try {
|
|
48165
48208
|
this._status = { state: "Starting" };
|
|
48166
|
-
this.
|
|
48209
|
+
this.sandbox = await import_opensandbox.Sandbox.connect({
|
|
48167
48210
|
sandboxId,
|
|
48168
48211
|
connectionConfig: this._connection,
|
|
48169
48212
|
skipHealthCheck: this.createConfig?.skipHealthCheck,
|
|
48170
48213
|
readyTimeoutSeconds: this.createConfig?.readyTimeoutSeconds,
|
|
48171
48214
|
healthCheckPollingInterval: this.createConfig?.healthCheckPollingInterval
|
|
48172
48215
|
});
|
|
48173
|
-
this._id = this._sandbox.id;
|
|
48174
48216
|
this._status = { state: "Running" };
|
|
48175
48217
|
} catch (error) {
|
|
48176
48218
|
this._status = { state: "Error", message: String(error) };
|
|
48177
48219
|
throw new ConnectionError(`Failed to connect to sandbox ${sandboxId}`, this.connectionConfig.baseUrl, error);
|
|
48178
48220
|
}
|
|
48179
48221
|
}
|
|
48222
|
+
async resume(sandboxId) {
|
|
48223
|
+
try {
|
|
48224
|
+
this._status = { state: "Starting" };
|
|
48225
|
+
this.sandbox = await import_opensandbox.Sandbox.resume({
|
|
48226
|
+
sandboxId,
|
|
48227
|
+
connectionConfig: this._connection,
|
|
48228
|
+
skipHealthCheck: this.createConfig?.skipHealthCheck,
|
|
48229
|
+
readyTimeoutSeconds: this.createConfig?.readyTimeoutSeconds,
|
|
48230
|
+
healthCheckPollingInterval: this.createConfig?.healthCheckPollingInterval
|
|
48231
|
+
});
|
|
48232
|
+
this._status = { state: "Running" };
|
|
48233
|
+
} catch (error) {
|
|
48234
|
+
this._status = { state: "Error", message: String(error) };
|
|
48235
|
+
throw new ConnectionError(`Failed to resume sandbox ${sandboxId}`, this.connectionConfig.baseUrl, error);
|
|
48236
|
+
}
|
|
48237
|
+
}
|
|
48180
48238
|
async start() {
|
|
48181
48239
|
try {
|
|
48182
48240
|
this._status = { state: "Starting" };
|
|
48183
|
-
this.
|
|
48184
|
-
|
|
48241
|
+
this.sandbox = await this.sandbox.resume();
|
|
48242
|
+
await this.waitUntilReady();
|
|
48185
48243
|
this._status = { state: "Running" };
|
|
48186
48244
|
} catch (error) {
|
|
48187
|
-
|
|
48188
|
-
|
|
48245
|
+
const code = error instanceof import_opensandbox.SandboxException ? error.error.code : undefined;
|
|
48246
|
+
switch (code) {
|
|
48247
|
+
case "DOCKER::SANDBOX_NOT_PAUSED":
|
|
48248
|
+
return;
|
|
48249
|
+
case "SANDBOX::API_NOT_SUPPORTED":
|
|
48250
|
+
throw new FeatureNotSupportedError("Start/resume not supported by this runtime", "start", this.provider);
|
|
48251
|
+
default:
|
|
48252
|
+
throw new CommandExecutionError("Failed to start sandbox", "start", error instanceof Error ? error : undefined);
|
|
48189
48253
|
}
|
|
48190
|
-
throw new CommandExecutionError("Failed to start sandbox", "start", error instanceof Error ? error : undefined);
|
|
48191
48254
|
}
|
|
48192
48255
|
}
|
|
48193
48256
|
async stop() {
|
|
@@ -48196,6 +48259,10 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48196
48259
|
await this.sandbox.pause();
|
|
48197
48260
|
this._status = { state: "Stopped" };
|
|
48198
48261
|
} catch (error) {
|
|
48262
|
+
const message = error instanceof import_opensandbox.SandboxException ? error.error.message : undefined;
|
|
48263
|
+
if (message?.includes("already paused")) {
|
|
48264
|
+
return;
|
|
48265
|
+
}
|
|
48199
48266
|
if (error && typeof error === "object" && "code" in error && error.code === "SANDBOX::API_NOT_SUPPORTED") {
|
|
48200
48267
|
throw new FeatureNotSupportedError("Stop/pause not supported by this runtime", "stop", this.provider);
|
|
48201
48268
|
}
|
|
@@ -48206,43 +48273,38 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48206
48273
|
try {
|
|
48207
48274
|
this._status = { state: "Deleting" };
|
|
48208
48275
|
await this.sandbox.kill();
|
|
48209
|
-
this.
|
|
48210
|
-
this._id = "";
|
|
48276
|
+
this.sandbox = undefined;
|
|
48211
48277
|
this._status = { state: "UnExist" };
|
|
48212
48278
|
} catch (error) {
|
|
48213
48279
|
throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
|
|
48214
48280
|
}
|
|
48215
48281
|
}
|
|
48216
48282
|
async close() {
|
|
48217
|
-
|
|
48218
|
-
await this._sandbox.close();
|
|
48219
|
-
}
|
|
48283
|
+
await this.sandbox.close();
|
|
48220
48284
|
}
|
|
48221
48285
|
async getEndpoint(port) {
|
|
48222
48286
|
const sdkEndpoint = await this.sandbox.getEndpoint(port);
|
|
48223
|
-
return this.convertSdkEndpoint(sdkEndpoint, port);
|
|
48224
|
-
}
|
|
48225
|
-
convertSdkEndpoint(sdkEndpoint, requestedPort) {
|
|
48226
48287
|
const raw = sdkEndpoint.endpoint;
|
|
48227
48288
|
const colonIdx = raw.lastIndexOf(":");
|
|
48228
48289
|
const hasPathBeforeColon = colonIdx !== -1 && raw.slice(0, colonIdx).includes("/");
|
|
48229
48290
|
if (colonIdx !== -1 && !hasPathBeforeColon) {
|
|
48230
48291
|
const host = raw.slice(0, colonIdx);
|
|
48231
48292
|
const parsedPort = parseInt(raw.slice(colonIdx + 1), 10);
|
|
48232
|
-
const
|
|
48293
|
+
const portNumber = isNaN(parsedPort) ? port : parsedPort;
|
|
48233
48294
|
const protocol = port === 443 ? "https" : "http";
|
|
48234
|
-
return { host, port, protocol, url: `${protocol}://${raw}` };
|
|
48295
|
+
return { host, port: portNumber, protocol, url: `${protocol}://${raw}` };
|
|
48235
48296
|
}
|
|
48236
48297
|
return {
|
|
48237
48298
|
host: raw,
|
|
48238
|
-
port
|
|
48299
|
+
port,
|
|
48239
48300
|
protocol: "https",
|
|
48240
48301
|
url: `https://${raw}`
|
|
48241
48302
|
};
|
|
48242
48303
|
}
|
|
48243
48304
|
async getInfo() {
|
|
48244
|
-
if (!this._sandbox)
|
|
48305
|
+
if (!this._sandbox) {
|
|
48245
48306
|
return null;
|
|
48307
|
+
}
|
|
48246
48308
|
try {
|
|
48247
48309
|
const info = await this.sandbox.getInfo();
|
|
48248
48310
|
return {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -47503,7 +47503,19 @@ class BaseSandboxAdapter {
|
|
|
47503
47503
|
}
|
|
47504
47504
|
await this.sleep(checkInterval);
|
|
47505
47505
|
}
|
|
47506
|
-
throw new SandboxReadyTimeoutError(this.id, timeoutMs);
|
|
47506
|
+
throw new SandboxReadyTimeoutError(this.id ?? "Unknown", timeoutMs);
|
|
47507
|
+
}
|
|
47508
|
+
async waitUntilDeleted(timeoutMs = 120000) {
|
|
47509
|
+
const startTime = Date.now();
|
|
47510
|
+
const checkInterval = 1000;
|
|
47511
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
47512
|
+
const data = await this.getInfo().catch(() => true);
|
|
47513
|
+
if (!data) {
|
|
47514
|
+
return;
|
|
47515
|
+
}
|
|
47516
|
+
await this.sleep(checkInterval);
|
|
47517
|
+
}
|
|
47518
|
+
throw new SandboxReadyTimeoutError(this.id ?? "Unknown", timeoutMs);
|
|
47507
47519
|
}
|
|
47508
47520
|
async renewExpiration(_additionalSeconds) {
|
|
47509
47521
|
throw new FeatureNotSupportedError("Sandbox expiration renewal not supported by this provider", "renewExpiration", this.provider);
|
|
@@ -47838,18 +47850,6 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
47838
47850
|
return "Error";
|
|
47839
47851
|
}
|
|
47840
47852
|
}
|
|
47841
|
-
async waitUntilDeleted() {
|
|
47842
|
-
const startTime = Date.now();
|
|
47843
|
-
const checkInterval = 1000;
|
|
47844
|
-
while (Date.now() - startTime < 120000) {
|
|
47845
|
-
const data = await this.getInfo().catch(() => true);
|
|
47846
|
-
if (!data) {
|
|
47847
|
-
return;
|
|
47848
|
-
}
|
|
47849
|
-
await this.sleep(checkInterval);
|
|
47850
|
-
}
|
|
47851
|
-
throw new TimeoutError("Sandbox not deleted", 120000, "waitUntilDeleted");
|
|
47852
|
-
}
|
|
47853
47853
|
async getInfo() {
|
|
47854
47854
|
try {
|
|
47855
47855
|
const res = await this.api.info(this._id);
|
|
@@ -47979,8 +47979,8 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
47979
47979
|
runtime;
|
|
47980
47980
|
_sandbox;
|
|
47981
47981
|
_connection;
|
|
47982
|
-
_id
|
|
47983
|
-
constructor(connectionConfig
|
|
47982
|
+
_id;
|
|
47983
|
+
constructor(connectionConfig, createConfig) {
|
|
47984
47984
|
super();
|
|
47985
47985
|
this.connectionConfig = connectionConfig;
|
|
47986
47986
|
this.createConfig = createConfig;
|
|
@@ -47991,6 +47991,10 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
47991
47991
|
get id() {
|
|
47992
47992
|
return this._id;
|
|
47993
47993
|
}
|
|
47994
|
+
set sandbox(sandbox) {
|
|
47995
|
+
this._sandbox = sandbox;
|
|
47996
|
+
this._id = sandbox?.id;
|
|
47997
|
+
}
|
|
47994
47998
|
get sandbox() {
|
|
47995
47999
|
if (!this._sandbox) {
|
|
47996
48000
|
throw new SandboxStateError("Sandbox not initialized. Call create() or connect() first.", "UnExist", "Running");
|
|
@@ -47999,9 +48003,6 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
47999
48003
|
}
|
|
48000
48004
|
createConnectionConfig() {
|
|
48001
48005
|
const { baseUrl, apiKey, requestTimeoutSeconds, debug, useServerProxy } = this.connectionConfig;
|
|
48002
|
-
if (!baseUrl) {
|
|
48003
|
-
return new import_opensandbox.ConnectionConfig({ apiKey, requestTimeoutSeconds, debug, useServerProxy });
|
|
48004
|
-
}
|
|
48005
48006
|
return new import_opensandbox.ConnectionConfig({
|
|
48006
48007
|
domain: baseUrl,
|
|
48007
48008
|
apiKey,
|
|
@@ -48112,32 +48113,74 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48112
48113
|
}
|
|
48113
48114
|
return 0;
|
|
48114
48115
|
}
|
|
48116
|
+
async getSandboxBySessionId() {
|
|
48117
|
+
const manager = import_opensandbox.SandboxManager.create({ connectionConfig: this._connection });
|
|
48118
|
+
const result = await manager.listSandboxInfos({
|
|
48119
|
+
metadata: { sessionId: this.connectionConfig.sessionId }
|
|
48120
|
+
});
|
|
48121
|
+
const val = result.items[0];
|
|
48122
|
+
if (val) {
|
|
48123
|
+
const status = this.mapStatus(val.status);
|
|
48124
|
+
return {
|
|
48125
|
+
id: val.id,
|
|
48126
|
+
status
|
|
48127
|
+
};
|
|
48128
|
+
}
|
|
48129
|
+
}
|
|
48115
48130
|
async ensureRunning() {
|
|
48116
|
-
|
|
48131
|
+
const sandbox = await this.getSandboxBySessionId();
|
|
48132
|
+
if (sandbox) {
|
|
48133
|
+
switch (sandbox.status.state) {
|
|
48134
|
+
case "UnExist":
|
|
48135
|
+
await this.create();
|
|
48136
|
+
break;
|
|
48137
|
+
case "Running":
|
|
48138
|
+
await this.connect(sandbox.id);
|
|
48139
|
+
break;
|
|
48140
|
+
case "Creating":
|
|
48141
|
+
case "Starting":
|
|
48142
|
+
await this.waitUntilReady();
|
|
48143
|
+
break;
|
|
48144
|
+
case "Stopping":
|
|
48145
|
+
case "Stopped":
|
|
48146
|
+
await this.resume(sandbox.id);
|
|
48147
|
+
break;
|
|
48148
|
+
case "Deleting":
|
|
48149
|
+
await this.waitUntilDeleted();
|
|
48150
|
+
await this.create();
|
|
48151
|
+
break;
|
|
48152
|
+
case "Error":
|
|
48153
|
+
throw new ConnectionError(`Sandbox error: ${sandbox.status.message}`);
|
|
48154
|
+
default:
|
|
48155
|
+
throw new ConnectionError(`Sandbox state ${sandbox.status.state} not supported`);
|
|
48156
|
+
}
|
|
48157
|
+
} else {
|
|
48158
|
+
await this.create();
|
|
48159
|
+
}
|
|
48117
48160
|
}
|
|
48118
48161
|
async create() {
|
|
48119
|
-
if (!this.createConfig) {
|
|
48120
|
-
throw new Error("createConfig is required to create a sandbox. Pass it as the third argument to createSandbox().");
|
|
48121
|
-
}
|
|
48122
48162
|
const cfg = this.createConfig;
|
|
48123
48163
|
try {
|
|
48124
48164
|
this._status = { state: "Creating" };
|
|
48125
48165
|
const image = this.convertImageSpec(cfg.image);
|
|
48126
48166
|
const resource = this.convertResourceLimits(cfg.resourceLimits);
|
|
48127
|
-
this.
|
|
48167
|
+
this.sandbox = await import_opensandbox.Sandbox.create({
|
|
48128
48168
|
connectionConfig: this._connection,
|
|
48129
48169
|
image,
|
|
48130
48170
|
entrypoint: cfg.entrypoint,
|
|
48131
48171
|
timeoutSeconds: cfg.timeoutSeconds ?? null,
|
|
48132
48172
|
resource,
|
|
48133
48173
|
env: cfg.env,
|
|
48134
|
-
metadata:
|
|
48174
|
+
metadata: {
|
|
48175
|
+
...cfg.metadata,
|
|
48176
|
+
sessionId: this.connectionConfig.sessionId
|
|
48177
|
+
},
|
|
48135
48178
|
volumes: cfg.volumes,
|
|
48136
48179
|
skipHealthCheck: cfg.skipHealthCheck,
|
|
48137
48180
|
readyTimeoutSeconds: cfg.readyTimeoutSeconds,
|
|
48138
48181
|
healthCheckPollingInterval: cfg.healthCheckPollingInterval
|
|
48139
48182
|
});
|
|
48140
|
-
|
|
48183
|
+
await this.waitUntilReady();
|
|
48141
48184
|
this._status = { state: "Running" };
|
|
48142
48185
|
} catch (error) {
|
|
48143
48186
|
this._status = { state: "Error", message: String(error) };
|
|
@@ -48147,31 +48190,51 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48147
48190
|
async connect(sandboxId) {
|
|
48148
48191
|
try {
|
|
48149
48192
|
this._status = { state: "Starting" };
|
|
48150
|
-
this.
|
|
48193
|
+
this.sandbox = await import_opensandbox.Sandbox.connect({
|
|
48151
48194
|
sandboxId,
|
|
48152
48195
|
connectionConfig: this._connection,
|
|
48153
48196
|
skipHealthCheck: this.createConfig?.skipHealthCheck,
|
|
48154
48197
|
readyTimeoutSeconds: this.createConfig?.readyTimeoutSeconds,
|
|
48155
48198
|
healthCheckPollingInterval: this.createConfig?.healthCheckPollingInterval
|
|
48156
48199
|
});
|
|
48157
|
-
this._id = this._sandbox.id;
|
|
48158
48200
|
this._status = { state: "Running" };
|
|
48159
48201
|
} catch (error) {
|
|
48160
48202
|
this._status = { state: "Error", message: String(error) };
|
|
48161
48203
|
throw new ConnectionError(`Failed to connect to sandbox ${sandboxId}`, this.connectionConfig.baseUrl, error);
|
|
48162
48204
|
}
|
|
48163
48205
|
}
|
|
48206
|
+
async resume(sandboxId) {
|
|
48207
|
+
try {
|
|
48208
|
+
this._status = { state: "Starting" };
|
|
48209
|
+
this.sandbox = await import_opensandbox.Sandbox.resume({
|
|
48210
|
+
sandboxId,
|
|
48211
|
+
connectionConfig: this._connection,
|
|
48212
|
+
skipHealthCheck: this.createConfig?.skipHealthCheck,
|
|
48213
|
+
readyTimeoutSeconds: this.createConfig?.readyTimeoutSeconds,
|
|
48214
|
+
healthCheckPollingInterval: this.createConfig?.healthCheckPollingInterval
|
|
48215
|
+
});
|
|
48216
|
+
this._status = { state: "Running" };
|
|
48217
|
+
} catch (error) {
|
|
48218
|
+
this._status = { state: "Error", message: String(error) };
|
|
48219
|
+
throw new ConnectionError(`Failed to resume sandbox ${sandboxId}`, this.connectionConfig.baseUrl, error);
|
|
48220
|
+
}
|
|
48221
|
+
}
|
|
48164
48222
|
async start() {
|
|
48165
48223
|
try {
|
|
48166
48224
|
this._status = { state: "Starting" };
|
|
48167
|
-
this.
|
|
48168
|
-
|
|
48225
|
+
this.sandbox = await this.sandbox.resume();
|
|
48226
|
+
await this.waitUntilReady();
|
|
48169
48227
|
this._status = { state: "Running" };
|
|
48170
48228
|
} catch (error) {
|
|
48171
|
-
|
|
48172
|
-
|
|
48229
|
+
const code = error instanceof import_opensandbox.SandboxException ? error.error.code : undefined;
|
|
48230
|
+
switch (code) {
|
|
48231
|
+
case "DOCKER::SANDBOX_NOT_PAUSED":
|
|
48232
|
+
return;
|
|
48233
|
+
case "SANDBOX::API_NOT_SUPPORTED":
|
|
48234
|
+
throw new FeatureNotSupportedError("Start/resume not supported by this runtime", "start", this.provider);
|
|
48235
|
+
default:
|
|
48236
|
+
throw new CommandExecutionError("Failed to start sandbox", "start", error instanceof Error ? error : undefined);
|
|
48173
48237
|
}
|
|
48174
|
-
throw new CommandExecutionError("Failed to start sandbox", "start", error instanceof Error ? error : undefined);
|
|
48175
48238
|
}
|
|
48176
48239
|
}
|
|
48177
48240
|
async stop() {
|
|
@@ -48180,6 +48243,10 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48180
48243
|
await this.sandbox.pause();
|
|
48181
48244
|
this._status = { state: "Stopped" };
|
|
48182
48245
|
} catch (error) {
|
|
48246
|
+
const message = error instanceof import_opensandbox.SandboxException ? error.error.message : undefined;
|
|
48247
|
+
if (message?.includes("already paused")) {
|
|
48248
|
+
return;
|
|
48249
|
+
}
|
|
48183
48250
|
if (error && typeof error === "object" && "code" in error && error.code === "SANDBOX::API_NOT_SUPPORTED") {
|
|
48184
48251
|
throw new FeatureNotSupportedError("Stop/pause not supported by this runtime", "stop", this.provider);
|
|
48185
48252
|
}
|
|
@@ -48190,43 +48257,38 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48190
48257
|
try {
|
|
48191
48258
|
this._status = { state: "Deleting" };
|
|
48192
48259
|
await this.sandbox.kill();
|
|
48193
|
-
this.
|
|
48194
|
-
this._id = "";
|
|
48260
|
+
this.sandbox = undefined;
|
|
48195
48261
|
this._status = { state: "UnExist" };
|
|
48196
48262
|
} catch (error) {
|
|
48197
48263
|
throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
|
|
48198
48264
|
}
|
|
48199
48265
|
}
|
|
48200
48266
|
async close() {
|
|
48201
|
-
|
|
48202
|
-
await this._sandbox.close();
|
|
48203
|
-
}
|
|
48267
|
+
await this.sandbox.close();
|
|
48204
48268
|
}
|
|
48205
48269
|
async getEndpoint(port) {
|
|
48206
48270
|
const sdkEndpoint = await this.sandbox.getEndpoint(port);
|
|
48207
|
-
return this.convertSdkEndpoint(sdkEndpoint, port);
|
|
48208
|
-
}
|
|
48209
|
-
convertSdkEndpoint(sdkEndpoint, requestedPort) {
|
|
48210
48271
|
const raw = sdkEndpoint.endpoint;
|
|
48211
48272
|
const colonIdx = raw.lastIndexOf(":");
|
|
48212
48273
|
const hasPathBeforeColon = colonIdx !== -1 && raw.slice(0, colonIdx).includes("/");
|
|
48213
48274
|
if (colonIdx !== -1 && !hasPathBeforeColon) {
|
|
48214
48275
|
const host = raw.slice(0, colonIdx);
|
|
48215
48276
|
const parsedPort = parseInt(raw.slice(colonIdx + 1), 10);
|
|
48216
|
-
const
|
|
48277
|
+
const portNumber = isNaN(parsedPort) ? port : parsedPort;
|
|
48217
48278
|
const protocol = port === 443 ? "https" : "http";
|
|
48218
|
-
return { host, port, protocol, url: `${protocol}://${raw}` };
|
|
48279
|
+
return { host, port: portNumber, protocol, url: `${protocol}://${raw}` };
|
|
48219
48280
|
}
|
|
48220
48281
|
return {
|
|
48221
48282
|
host: raw,
|
|
48222
|
-
port
|
|
48283
|
+
port,
|
|
48223
48284
|
protocol: "https",
|
|
48224
48285
|
url: `https://${raw}`
|
|
48225
48286
|
};
|
|
48226
48287
|
}
|
|
48227
48288
|
async getInfo() {
|
|
48228
|
-
if (!this._sandbox)
|
|
48289
|
+
if (!this._sandbox) {
|
|
48229
48290
|
return null;
|
|
48291
|
+
}
|
|
48230
48292
|
try {
|
|
48231
48293
|
const info = await this.sandbox.getInfo();
|
|
48232
48294
|
return {
|
|
@@ -5,7 +5,7 @@ import type { SandboxId, SandboxInfo, SandboxStatus } from '../types';
|
|
|
5
5
|
*/
|
|
6
6
|
export interface ISandboxLifecycle {
|
|
7
7
|
/** Unique identifier for this sandbox */
|
|
8
|
-
readonly id
|
|
8
|
+
readonly id?: SandboxId;
|
|
9
9
|
/** Current status of the sandbox */
|
|
10
10
|
readonly status: SandboxStatus;
|
|
11
11
|
/**
|
|
@@ -39,6 +39,7 @@ export interface ISandboxLifecycle {
|
|
|
39
39
|
* @throws {SandboxReadyTimeoutError} If timeout is exceeded
|
|
40
40
|
*/
|
|
41
41
|
waitUntilReady(timeoutMs?: number): Promise<void>;
|
|
42
|
+
waitUntilDeleted(timeoutMs?: number): Promise<void>;
|
|
42
43
|
/**
|
|
43
44
|
* Renew the sandbox expiration, extending its lifetime.
|
|
44
45
|
* Not all providers support this.
|