@fastgpt-sdk/sandbox-adapter 0.0.40-beta.5 → 0.0.40-beta.6
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 +1 -2
- package/dist/adapters/OpenSandboxAdapter/index.d.ts +1 -2
- package/dist/adapters/SealosDevboxAdapter/index.d.ts +1 -3
- package/dist/index.cjs +34 -86
- package/dist/index.js +34 -86
- package/dist/interfaces/ISandbox.d.ts +1 -3
- package/dist/types/index.d.ts +1 -1
- package/dist/types/sandbox.d.ts +1 -9
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ISandbox } from '../interfaces/ISandbox';
|
|
2
2
|
import { CommandPolyfillService } from '../polyfill/CommandPolyfillService';
|
|
3
|
-
import type { ContentReplaceEntry, DirectoryEntry, Endpoint, ExecuteOptions, ExecuteResult, FileDeleteResult, FileInfo, FileReadResult, FileWriteEntry, FileWriteResult, MoveEntry, PermissionEntry, ReadFileOptions, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics,
|
|
3
|
+
import type { ContentReplaceEntry, DirectoryEntry, Endpoint, ExecuteOptions, ExecuteResult, FileDeleteResult, FileInfo, FileReadResult, FileWriteEntry, FileWriteResult, MoveEntry, PermissionEntry, ReadFileOptions, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics, SandboxStatus, SearchResult, StreamHandlers } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* Abstract base class for all sandbox adapters.
|
|
6
6
|
*
|
|
@@ -38,7 +38,6 @@ export declare abstract class BaseSandboxAdapter implements ISandbox {
|
|
|
38
38
|
waitUntilDeleted(timeoutMs?: number): Promise<void>;
|
|
39
39
|
renewExpiration(_additionalSeconds: number): Promise<void>;
|
|
40
40
|
getEndpoint(_selector: SandboxEndpointSelector): Promise<Endpoint>;
|
|
41
|
-
getProxyTarget(_service?: SandboxProxyService): Promise<SandboxProxyTarget>;
|
|
42
41
|
abstract execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
43
42
|
executeStream(command: string, handlers: StreamHandlers, options?: ExecuteOptions): Promise<void>;
|
|
44
43
|
executeBackground(_command: string, _options?: ExecuteOptions): Promise<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Endpoint, ExecuteOptions, ExecuteResult, FileWriteEntry, FileWriteResult, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics,
|
|
1
|
+
import type { Endpoint, ExecuteOptions, ExecuteResult, FileWriteEntry, FileWriteResult, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics, StreamHandlers } from '@/types';
|
|
2
2
|
import { BaseSandboxAdapter } from '../BaseSandboxAdapter';
|
|
3
3
|
import type { OpenSandboxConfigType } from './type';
|
|
4
4
|
export type { OpenSandboxConfigType } from './type';
|
|
@@ -94,7 +94,6 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
94
94
|
*/
|
|
95
95
|
getEndpoint(selector: SandboxEndpointSelector): Promise<Endpoint>;
|
|
96
96
|
private getOpenSandboxEndpoint;
|
|
97
|
-
getProxyTarget(service?: SandboxProxyService): Promise<SandboxProxyTarget>;
|
|
98
97
|
private getDirectEndpointOrigin;
|
|
99
98
|
getInfo(): Promise<SandboxInfo | null>;
|
|
100
99
|
renewExpiration(additionalSeconds: number): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Endpoint, ExecuteOptions, ExecuteResult, ImageSpec, KubeAccessPolicy, LabelSpec, LifecyclePolicy, SandboxEndpointSelector, SandboxId, SandboxInfo
|
|
1
|
+
import type { Endpoint, ExecuteOptions, ExecuteResult, ImageSpec, KubeAccessPolicy, LabelSpec, LifecyclePolicy, SandboxEndpointSelector, SandboxId, SandboxInfo } from '../../types';
|
|
2
2
|
import { BaseSandboxAdapter } from '../BaseSandboxAdapter';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration for Sealos Devbox Adapter.
|
|
@@ -53,8 +53,6 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
53
53
|
delete(sandboxId?: SandboxId): Promise<void>;
|
|
54
54
|
execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
55
55
|
getEndpoint(selector: SandboxEndpointSelector): Promise<Endpoint>;
|
|
56
|
-
getProxyTarget(service?: SandboxProxyService): Promise<SandboxProxyTarget>;
|
|
57
|
-
private waitForCodeServerHealthz;
|
|
58
56
|
private getHttpgateTarget;
|
|
59
57
|
private getGatewayUniqueID;
|
|
60
58
|
private getHttpgateDomain;
|
package/dist/index.cjs
CHANGED
|
@@ -45192,7 +45192,10 @@ POLYFILL_EOF`);
|
|
|
45192
45192
|
}
|
|
45193
45193
|
}
|
|
45194
45194
|
async listDirectory(path) {
|
|
45195
|
-
|
|
45195
|
+
let result = await this.executor.execute(`ls -la "${this.escapePath(path)}" --time-style=+"%Y-%m-%dT%H:%M:%S" 2>/dev/null || echo "DIRECTORY_NOT_FOUND"`);
|
|
45196
|
+
if (result.stdout.includes("DIRECTORY_NOT_FOUND") || result.exitCode !== 0) {
|
|
45197
|
+
result = await this.executor.execute(`ls -la "${this.escapePath(path)}" 2>/dev/null || echo "DIRECTORY_NOT_FOUND"`);
|
|
45198
|
+
}
|
|
45196
45199
|
if (result.stdout.includes("DIRECTORY_NOT_FOUND")) {
|
|
45197
45200
|
throw new FileOperationError("Directory not found", path, "FILE_NOT_FOUND");
|
|
45198
45201
|
}
|
|
@@ -45323,7 +45326,7 @@ POLYFILL_EOF`);
|
|
|
45323
45326
|
if (line.startsWith("total") || !line.trim()) {
|
|
45324
45327
|
continue;
|
|
45325
45328
|
}
|
|
45326
|
-
|
|
45329
|
+
let match = line.match(/^([-dl])([-rwxsStT]{9})\s+\d+\s+\S+\s+\S+\s+(\d+)\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\s+(.+)$/);
|
|
45327
45330
|
if (match) {
|
|
45328
45331
|
const [, type, , size, dateStr, name] = match;
|
|
45329
45332
|
if (name === "." || name === "..") {
|
|
@@ -45339,6 +45342,24 @@ POLYFILL_EOF`);
|
|
|
45339
45342
|
size: Number.parseInt(size, 10) || undefined,
|
|
45340
45343
|
modifiedAt: new Date(dateStr)
|
|
45341
45344
|
});
|
|
45345
|
+
continue;
|
|
45346
|
+
}
|
|
45347
|
+
const parts = line.trim().split(/\s+/);
|
|
45348
|
+
if (parts.length >= 8) {
|
|
45349
|
+
const permissions = parts[0];
|
|
45350
|
+
const type = permissions[0];
|
|
45351
|
+
const size = parts[4];
|
|
45352
|
+
const name = parts.slice(8).join(" ");
|
|
45353
|
+
if (name === "." || name === "..") {
|
|
45354
|
+
continue;
|
|
45355
|
+
}
|
|
45356
|
+
entries.push({
|
|
45357
|
+
name,
|
|
45358
|
+
path: `${basePath}/${name}`,
|
|
45359
|
+
isDirectory: type === "d" || type === "l",
|
|
45360
|
+
isFile: type === "-",
|
|
45361
|
+
size: Number.parseInt(size, 10) || undefined
|
|
45362
|
+
});
|
|
45342
45363
|
}
|
|
45343
45364
|
}
|
|
45344
45365
|
return entries;
|
|
@@ -45412,9 +45433,6 @@ class BaseSandboxAdapter {
|
|
|
45412
45433
|
async getEndpoint(_selector) {
|
|
45413
45434
|
throw new FeatureNotSupportedError("Endpoint resolution not supported by this provider", "getEndpoint", this.provider);
|
|
45414
45435
|
}
|
|
45415
|
-
async getProxyTarget(_service = "code-server") {
|
|
45416
|
-
throw new FeatureNotSupportedError("Proxy target resolution not supported by this provider", "getProxyTarget", this.provider);
|
|
45417
|
-
}
|
|
45418
45436
|
async executeStream(command, handlers, options) {
|
|
45419
45437
|
const result = await this.execute(command, options);
|
|
45420
45438
|
if (handlers.onStdout && result.stdout) {
|
|
@@ -45740,11 +45758,6 @@ class DevboxApi {
|
|
|
45740
45758
|
}
|
|
45741
45759
|
}
|
|
45742
45760
|
|
|
45743
|
-
// src/adapters/ports.ts
|
|
45744
|
-
var OPEN_SANDBOX_EXECD_PORT = 44772;
|
|
45745
|
-
var OPEN_SANDBOX_CODE_SERVER_PORT = 8080;
|
|
45746
|
-
var SEALOS_DEVBOX_CODE_SERVER_PORT = 1318;
|
|
45747
|
-
|
|
45748
45761
|
// src/utils/image.ts
|
|
45749
45762
|
function formatImageSpec(image) {
|
|
45750
45763
|
const parts = [image.repository];
|
|
@@ -46010,11 +46023,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
46010
46023
|
}
|
|
46011
46024
|
}
|
|
46012
46025
|
async getEndpoint(selector) {
|
|
46013
|
-
const
|
|
46014
|
-
const target = await this.getHttpgateTarget(port);
|
|
46015
|
-
if (selector === "code-server") {
|
|
46016
|
-
await this.waitForCodeServerHealthz(target);
|
|
46017
|
-
}
|
|
46026
|
+
const target = await this.getHttpgateTarget(selector);
|
|
46018
46027
|
const url = new URL(target.origin);
|
|
46019
46028
|
return {
|
|
46020
46029
|
host: url.host,
|
|
@@ -46023,61 +46032,11 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
46023
46032
|
url: joinUrlPath(target.origin, target.basePath)
|
|
46024
46033
|
};
|
|
46025
46034
|
}
|
|
46026
|
-
async getProxyTarget(service = "code-server") {
|
|
46027
|
-
if (service !== "code-server") {
|
|
46028
|
-
throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
|
|
46029
|
-
}
|
|
46030
|
-
const target = await this.getHttpgateTarget(SEALOS_DEVBOX_CODE_SERVER_PORT);
|
|
46031
|
-
return {
|
|
46032
|
-
service,
|
|
46033
|
-
origin: target.origin,
|
|
46034
|
-
basePath: target.basePath,
|
|
46035
|
-
auth: "code-server",
|
|
46036
|
-
...target.password ? { password: target.password } : {}
|
|
46037
|
-
};
|
|
46038
|
-
}
|
|
46039
|
-
async waitForCodeServerHealthz(target) {
|
|
46040
|
-
const healthUrl = joinUrlPath(joinUrlPath(target.origin, target.basePath), "/healthz");
|
|
46041
|
-
const timeoutMs = 60000;
|
|
46042
|
-
const intervalMs = 500;
|
|
46043
|
-
const requestTimeoutMs = 3000;
|
|
46044
|
-
const deadline = Date.now() + timeoutMs;
|
|
46045
|
-
let lastResult = "not checked";
|
|
46046
|
-
while (Date.now() < deadline) {
|
|
46047
|
-
try {
|
|
46048
|
-
const res = await fetch(healthUrl, {
|
|
46049
|
-
method: "GET",
|
|
46050
|
-
signal: AbortSignal.timeout(requestTimeoutMs)
|
|
46051
|
-
});
|
|
46052
|
-
if (res.status >= 200 && res.status < 400) {
|
|
46053
|
-
return;
|
|
46054
|
-
}
|
|
46055
|
-
lastResult = `status ${res.status}`;
|
|
46056
|
-
} catch (error) {
|
|
46057
|
-
lastResult = error instanceof Error ? error.message : String(error);
|
|
46058
|
-
}
|
|
46059
|
-
await this.sleep(intervalMs);
|
|
46060
|
-
}
|
|
46061
|
-
throw new ConnectionError(`Devbox code-server health check ${healthUrl} did not become ready within ${timeoutMs}ms. Last result: ${lastResult}`, this.config.baseUrl);
|
|
46062
|
-
}
|
|
46063
46035
|
async getHttpgateTarget(port) {
|
|
46064
46036
|
const res = await this.api.info(this._id);
|
|
46065
46037
|
if (res.code !== 200 || !res.data) {
|
|
46066
46038
|
throw new ConnectionError(`Failed to get devbox info: ${res.message}`, this.config.baseUrl);
|
|
46067
46039
|
}
|
|
46068
|
-
if (port === SEALOS_DEVBOX_CODE_SERVER_PORT) {
|
|
46069
|
-
const gateway2 = res.data.codeServerGateway;
|
|
46070
|
-
if (!gateway2?.url) {
|
|
46071
|
-
throw new ConnectionError("Devbox info does not include codeServerGateway.url; cannot resolve code-server endpoint", this.config.baseUrl);
|
|
46072
|
-
}
|
|
46073
|
-
const codeServerUrl = new URL(gateway2.url);
|
|
46074
|
-
return {
|
|
46075
|
-
origin: codeServerUrl.origin,
|
|
46076
|
-
basePath: normalizePathPrefix(codeServerUrl.pathname),
|
|
46077
|
-
port: gateway2.port ?? port,
|
|
46078
|
-
password: gateway2.password
|
|
46079
|
-
};
|
|
46080
|
-
}
|
|
46081
46040
|
const gatewayUrl = res.data.gateway?.url;
|
|
46082
46041
|
if (!gatewayUrl) {
|
|
46083
46042
|
throw new ConnectionError("Devbox info does not include gateway.url; cannot derive httpgate endpoint", this.config.baseUrl);
|
|
@@ -48648,15 +48607,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48648
48607
|
await this.sandbox.close();
|
|
48649
48608
|
}
|
|
48650
48609
|
async getEndpoint(selector) {
|
|
48651
|
-
|
|
48652
|
-
const endpoint = await this.getOpenSandboxEndpoint(port);
|
|
48653
|
-
if (selector === "code-server") {
|
|
48654
|
-
return {
|
|
48655
|
-
...endpoint,
|
|
48656
|
-
url: joinUrlPath(endpoint.url, `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`)
|
|
48657
|
-
};
|
|
48658
|
-
}
|
|
48659
|
-
return endpoint;
|
|
48610
|
+
return this.getOpenSandboxEndpoint(selector);
|
|
48660
48611
|
}
|
|
48661
48612
|
async getOpenSandboxEndpoint(port) {
|
|
48662
48613
|
const sdkEndpoint = await this.sandbox.getEndpoint(port);
|
|
@@ -48677,17 +48628,6 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48677
48628
|
url: `https://${raw}`
|
|
48678
48629
|
};
|
|
48679
48630
|
}
|
|
48680
|
-
async getProxyTarget(service = "code-server") {
|
|
48681
|
-
if (service !== "code-server") {
|
|
48682
|
-
throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
|
|
48683
|
-
}
|
|
48684
|
-
return {
|
|
48685
|
-
service,
|
|
48686
|
-
origin: await this.getDirectEndpointOrigin(OPEN_SANDBOX_EXECD_PORT),
|
|
48687
|
-
basePath: `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`,
|
|
48688
|
-
auth: "code-server"
|
|
48689
|
-
};
|
|
48690
|
-
}
|
|
48691
48631
|
async getDirectEndpointOrigin(port) {
|
|
48692
48632
|
if (!this.id) {
|
|
48693
48633
|
throw new SandboxStateError("Sandbox not initialized. Call create() or connect() first.", "UnExist", "Running");
|
|
@@ -48743,10 +48683,18 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48743
48683
|
for (const entry of entries) {
|
|
48744
48684
|
const normalizedPath = this.normalizePath(entry.path);
|
|
48745
48685
|
try {
|
|
48686
|
+
let data = entry.data;
|
|
48687
|
+
if (data instanceof Uint8Array) {
|
|
48688
|
+
if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
|
|
48689
|
+
data = data.buffer;
|
|
48690
|
+
} else {
|
|
48691
|
+
data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
48692
|
+
}
|
|
48693
|
+
}
|
|
48746
48694
|
await this.sandbox.files.writeFiles([
|
|
48747
48695
|
{
|
|
48748
48696
|
path: normalizedPath,
|
|
48749
|
-
data
|
|
48697
|
+
data,
|
|
48750
48698
|
mode: entry.mode,
|
|
48751
48699
|
owner: entry.owner,
|
|
48752
48700
|
group: entry.group
|
package/dist/index.js
CHANGED
|
@@ -45176,7 +45176,10 @@ POLYFILL_EOF`);
|
|
|
45176
45176
|
}
|
|
45177
45177
|
}
|
|
45178
45178
|
async listDirectory(path) {
|
|
45179
|
-
|
|
45179
|
+
let result = await this.executor.execute(`ls -la "${this.escapePath(path)}" --time-style=+"%Y-%m-%dT%H:%M:%S" 2>/dev/null || echo "DIRECTORY_NOT_FOUND"`);
|
|
45180
|
+
if (result.stdout.includes("DIRECTORY_NOT_FOUND") || result.exitCode !== 0) {
|
|
45181
|
+
result = await this.executor.execute(`ls -la "${this.escapePath(path)}" 2>/dev/null || echo "DIRECTORY_NOT_FOUND"`);
|
|
45182
|
+
}
|
|
45180
45183
|
if (result.stdout.includes("DIRECTORY_NOT_FOUND")) {
|
|
45181
45184
|
throw new FileOperationError("Directory not found", path, "FILE_NOT_FOUND");
|
|
45182
45185
|
}
|
|
@@ -45307,7 +45310,7 @@ POLYFILL_EOF`);
|
|
|
45307
45310
|
if (line.startsWith("total") || !line.trim()) {
|
|
45308
45311
|
continue;
|
|
45309
45312
|
}
|
|
45310
|
-
|
|
45313
|
+
let match = line.match(/^([-dl])([-rwxsStT]{9})\s+\d+\s+\S+\s+\S+\s+(\d+)\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\s+(.+)$/);
|
|
45311
45314
|
if (match) {
|
|
45312
45315
|
const [, type, , size, dateStr, name] = match;
|
|
45313
45316
|
if (name === "." || name === "..") {
|
|
@@ -45323,6 +45326,24 @@ POLYFILL_EOF`);
|
|
|
45323
45326
|
size: Number.parseInt(size, 10) || undefined,
|
|
45324
45327
|
modifiedAt: new Date(dateStr)
|
|
45325
45328
|
});
|
|
45329
|
+
continue;
|
|
45330
|
+
}
|
|
45331
|
+
const parts = line.trim().split(/\s+/);
|
|
45332
|
+
if (parts.length >= 8) {
|
|
45333
|
+
const permissions = parts[0];
|
|
45334
|
+
const type = permissions[0];
|
|
45335
|
+
const size = parts[4];
|
|
45336
|
+
const name = parts.slice(8).join(" ");
|
|
45337
|
+
if (name === "." || name === "..") {
|
|
45338
|
+
continue;
|
|
45339
|
+
}
|
|
45340
|
+
entries.push({
|
|
45341
|
+
name,
|
|
45342
|
+
path: `${basePath}/${name}`,
|
|
45343
|
+
isDirectory: type === "d" || type === "l",
|
|
45344
|
+
isFile: type === "-",
|
|
45345
|
+
size: Number.parseInt(size, 10) || undefined
|
|
45346
|
+
});
|
|
45326
45347
|
}
|
|
45327
45348
|
}
|
|
45328
45349
|
return entries;
|
|
@@ -45396,9 +45417,6 @@ class BaseSandboxAdapter {
|
|
|
45396
45417
|
async getEndpoint(_selector) {
|
|
45397
45418
|
throw new FeatureNotSupportedError("Endpoint resolution not supported by this provider", "getEndpoint", this.provider);
|
|
45398
45419
|
}
|
|
45399
|
-
async getProxyTarget(_service = "code-server") {
|
|
45400
|
-
throw new FeatureNotSupportedError("Proxy target resolution not supported by this provider", "getProxyTarget", this.provider);
|
|
45401
|
-
}
|
|
45402
45420
|
async executeStream(command, handlers, options) {
|
|
45403
45421
|
const result = await this.execute(command, options);
|
|
45404
45422
|
if (handlers.onStdout && result.stdout) {
|
|
@@ -45724,11 +45742,6 @@ class DevboxApi {
|
|
|
45724
45742
|
}
|
|
45725
45743
|
}
|
|
45726
45744
|
|
|
45727
|
-
// src/adapters/ports.ts
|
|
45728
|
-
var OPEN_SANDBOX_EXECD_PORT = 44772;
|
|
45729
|
-
var OPEN_SANDBOX_CODE_SERVER_PORT = 8080;
|
|
45730
|
-
var SEALOS_DEVBOX_CODE_SERVER_PORT = 1318;
|
|
45731
|
-
|
|
45732
45745
|
// src/utils/image.ts
|
|
45733
45746
|
function formatImageSpec(image) {
|
|
45734
45747
|
const parts = [image.repository];
|
|
@@ -45994,11 +46007,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
45994
46007
|
}
|
|
45995
46008
|
}
|
|
45996
46009
|
async getEndpoint(selector) {
|
|
45997
|
-
const
|
|
45998
|
-
const target = await this.getHttpgateTarget(port);
|
|
45999
|
-
if (selector === "code-server") {
|
|
46000
|
-
await this.waitForCodeServerHealthz(target);
|
|
46001
|
-
}
|
|
46010
|
+
const target = await this.getHttpgateTarget(selector);
|
|
46002
46011
|
const url = new URL(target.origin);
|
|
46003
46012
|
return {
|
|
46004
46013
|
host: url.host,
|
|
@@ -46007,61 +46016,11 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
46007
46016
|
url: joinUrlPath(target.origin, target.basePath)
|
|
46008
46017
|
};
|
|
46009
46018
|
}
|
|
46010
|
-
async getProxyTarget(service = "code-server") {
|
|
46011
|
-
if (service !== "code-server") {
|
|
46012
|
-
throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
|
|
46013
|
-
}
|
|
46014
|
-
const target = await this.getHttpgateTarget(SEALOS_DEVBOX_CODE_SERVER_PORT);
|
|
46015
|
-
return {
|
|
46016
|
-
service,
|
|
46017
|
-
origin: target.origin,
|
|
46018
|
-
basePath: target.basePath,
|
|
46019
|
-
auth: "code-server",
|
|
46020
|
-
...target.password ? { password: target.password } : {}
|
|
46021
|
-
};
|
|
46022
|
-
}
|
|
46023
|
-
async waitForCodeServerHealthz(target) {
|
|
46024
|
-
const healthUrl = joinUrlPath(joinUrlPath(target.origin, target.basePath), "/healthz");
|
|
46025
|
-
const timeoutMs = 60000;
|
|
46026
|
-
const intervalMs = 500;
|
|
46027
|
-
const requestTimeoutMs = 3000;
|
|
46028
|
-
const deadline = Date.now() + timeoutMs;
|
|
46029
|
-
let lastResult = "not checked";
|
|
46030
|
-
while (Date.now() < deadline) {
|
|
46031
|
-
try {
|
|
46032
|
-
const res = await fetch(healthUrl, {
|
|
46033
|
-
method: "GET",
|
|
46034
|
-
signal: AbortSignal.timeout(requestTimeoutMs)
|
|
46035
|
-
});
|
|
46036
|
-
if (res.status >= 200 && res.status < 400) {
|
|
46037
|
-
return;
|
|
46038
|
-
}
|
|
46039
|
-
lastResult = `status ${res.status}`;
|
|
46040
|
-
} catch (error) {
|
|
46041
|
-
lastResult = error instanceof Error ? error.message : String(error);
|
|
46042
|
-
}
|
|
46043
|
-
await this.sleep(intervalMs);
|
|
46044
|
-
}
|
|
46045
|
-
throw new ConnectionError(`Devbox code-server health check ${healthUrl} did not become ready within ${timeoutMs}ms. Last result: ${lastResult}`, this.config.baseUrl);
|
|
46046
|
-
}
|
|
46047
46019
|
async getHttpgateTarget(port) {
|
|
46048
46020
|
const res = await this.api.info(this._id);
|
|
46049
46021
|
if (res.code !== 200 || !res.data) {
|
|
46050
46022
|
throw new ConnectionError(`Failed to get devbox info: ${res.message}`, this.config.baseUrl);
|
|
46051
46023
|
}
|
|
46052
|
-
if (port === SEALOS_DEVBOX_CODE_SERVER_PORT) {
|
|
46053
|
-
const gateway2 = res.data.codeServerGateway;
|
|
46054
|
-
if (!gateway2?.url) {
|
|
46055
|
-
throw new ConnectionError("Devbox info does not include codeServerGateway.url; cannot resolve code-server endpoint", this.config.baseUrl);
|
|
46056
|
-
}
|
|
46057
|
-
const codeServerUrl = new URL(gateway2.url);
|
|
46058
|
-
return {
|
|
46059
|
-
origin: codeServerUrl.origin,
|
|
46060
|
-
basePath: normalizePathPrefix(codeServerUrl.pathname),
|
|
46061
|
-
port: gateway2.port ?? port,
|
|
46062
|
-
password: gateway2.password
|
|
46063
|
-
};
|
|
46064
|
-
}
|
|
46065
46024
|
const gatewayUrl = res.data.gateway?.url;
|
|
46066
46025
|
if (!gatewayUrl) {
|
|
46067
46026
|
throw new ConnectionError("Devbox info does not include gateway.url; cannot derive httpgate endpoint", this.config.baseUrl);
|
|
@@ -48632,15 +48591,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48632
48591
|
await this.sandbox.close();
|
|
48633
48592
|
}
|
|
48634
48593
|
async getEndpoint(selector) {
|
|
48635
|
-
|
|
48636
|
-
const endpoint = await this.getOpenSandboxEndpoint(port);
|
|
48637
|
-
if (selector === "code-server") {
|
|
48638
|
-
return {
|
|
48639
|
-
...endpoint,
|
|
48640
|
-
url: joinUrlPath(endpoint.url, `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`)
|
|
48641
|
-
};
|
|
48642
|
-
}
|
|
48643
|
-
return endpoint;
|
|
48594
|
+
return this.getOpenSandboxEndpoint(selector);
|
|
48644
48595
|
}
|
|
48645
48596
|
async getOpenSandboxEndpoint(port) {
|
|
48646
48597
|
const sdkEndpoint = await this.sandbox.getEndpoint(port);
|
|
@@ -48661,17 +48612,6 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48661
48612
|
url: `https://${raw}`
|
|
48662
48613
|
};
|
|
48663
48614
|
}
|
|
48664
|
-
async getProxyTarget(service = "code-server") {
|
|
48665
|
-
if (service !== "code-server") {
|
|
48666
|
-
throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
|
|
48667
|
-
}
|
|
48668
|
-
return {
|
|
48669
|
-
service,
|
|
48670
|
-
origin: await this.getDirectEndpointOrigin(OPEN_SANDBOX_EXECD_PORT),
|
|
48671
|
-
basePath: `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`,
|
|
48672
|
-
auth: "code-server"
|
|
48673
|
-
};
|
|
48674
|
-
}
|
|
48675
48615
|
async getDirectEndpointOrigin(port) {
|
|
48676
48616
|
if (!this.id) {
|
|
48677
48617
|
throw new SandboxStateError("Sandbox not initialized. Call create() or connect() first.", "UnExist", "Running");
|
|
@@ -48727,10 +48667,18 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
|
|
|
48727
48667
|
for (const entry of entries) {
|
|
48728
48668
|
const normalizedPath = this.normalizePath(entry.path);
|
|
48729
48669
|
try {
|
|
48670
|
+
let data = entry.data;
|
|
48671
|
+
if (data instanceof Uint8Array) {
|
|
48672
|
+
if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
|
|
48673
|
+
data = data.buffer;
|
|
48674
|
+
} else {
|
|
48675
|
+
data = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
48676
|
+
}
|
|
48677
|
+
}
|
|
48730
48678
|
await this.sandbox.files.writeFiles([
|
|
48731
48679
|
{
|
|
48732
48680
|
path: normalizedPath,
|
|
48733
|
-
data
|
|
48681
|
+
data,
|
|
48734
48682
|
mode: entry.mode,
|
|
48735
48683
|
owner: entry.owner,
|
|
48736
48684
|
group: entry.group
|
|
@@ -2,7 +2,7 @@ import type { ICommandExecution } from './ICommandExecution';
|
|
|
2
2
|
import type { IFileSystem } from './IFileSystem';
|
|
3
3
|
import type { IHealthCheck } from './IHealthCheck';
|
|
4
4
|
import type { ISandboxLifecycle } from './ISandboxLifecycle';
|
|
5
|
-
import type { Endpoint, SandboxEndpointSelector
|
|
5
|
+
import type { Endpoint, SandboxEndpointSelector } from '../types';
|
|
6
6
|
/**
|
|
7
7
|
* Unified sandbox interface.
|
|
8
8
|
* Composes all sandbox behaviors into a single interface.
|
|
@@ -18,6 +18,4 @@ export interface ISandbox extends ISandboxLifecycle, ICommandExecution, IFileSys
|
|
|
18
18
|
readonly provider: string;
|
|
19
19
|
/** Resolve an endpoint exposed by the sandbox provider. */
|
|
20
20
|
getEndpoint(selector: SandboxEndpointSelector): Promise<Endpoint>;
|
|
21
|
-
/** Resolve the upstream target used by FastGPT sandbox-proxy. */
|
|
22
|
-
getProxyTarget(service?: SandboxProxyService): Promise<SandboxProxyTarget>;
|
|
23
21
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type { BackgroundExecution, ExecuteOptions, ExecuteResult, OutputMessage, StreamHandlers } from './execution';
|
|
2
2
|
export type { ContentReplaceEntry, DirectoryEntry, FileDeleteResult, FileInfo, FileReadResult, FileWriteEntry, FileWriteResult, MoveEntry, PermissionEntry, ReadFileOptions, SearchResult } from './filesystem';
|
|
3
|
-
export type { Endpoint, ImageSpec, KubeAccessPolicy, LabelSpec, LifecyclePolicy, NetworkPolicy, ResourceLimits, SandboxCreateSpec, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics,
|
|
3
|
+
export type { Endpoint, ImageSpec, KubeAccessPolicy, LabelSpec, LifecyclePolicy, NetworkPolicy, ResourceLimits, SandboxCreateSpec, SandboxEndpointSelector, SandboxId, SandboxInfo, SandboxMetrics, SandboxState, SandboxStatus } from './sandbox';
|
package/dist/types/sandbox.d.ts
CHANGED
|
@@ -105,12 +105,4 @@ export interface SandboxCreateSpec {
|
|
|
105
105
|
readyTimeoutSeconds?: number;
|
|
106
106
|
healthCheckPollingInterval?: number;
|
|
107
107
|
}
|
|
108
|
-
export type
|
|
109
|
-
export type SandboxEndpointSelector = number | SandboxProxyService;
|
|
110
|
-
export interface SandboxProxyTarget {
|
|
111
|
-
service: SandboxProxyService;
|
|
112
|
-
origin: string;
|
|
113
|
-
basePath: string;
|
|
114
|
-
auth: 'code-server';
|
|
115
|
-
password?: string;
|
|
116
|
-
}
|
|
108
|
+
export type SandboxEndpointSelector = number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastgpt-sdk/sandbox-adapter",
|
|
3
|
-
"version": "0.0.40-beta.
|
|
3
|
+
"version": "0.0.40-beta.6",
|
|
4
4
|
"description": "Unified abstraction layer for cloud sandbox providers with adapter pattern and feature polyfilling",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|