@fastgpt-sdk/sandbox-adapter 0.0.15 → 0.0.16

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.
@@ -54,4 +54,6 @@ export declare abstract class BaseSandboxAdapter implements ISandbox {
54
54
  getMetrics(): Promise<SandboxMetrics>;
55
55
  protected sleep(ms: number): Promise<void>;
56
56
  protected requirePolyfillService(feature: string, message: string): CommandPolyfillService;
57
+ protected escapeShellArg(arg: string): string;
58
+ protected buildCommand(command: string, workingDirectory?: string): string[];
57
59
  }
@@ -1,4 +1,4 @@
1
- import type { ExecuteOptions, ExecuteResult, SandboxId, SandboxInfo, SandboxMetrics, StreamHandlers } from '@/types';
1
+ import type { Endpoint, ExecuteOptions, ExecuteResult, 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';
@@ -44,13 +44,13 @@ export interface OpenSandboxConnectionConfig {
44
44
  */
45
45
  export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
46
46
  private connectionConfig;
47
- private createConfig;
47
+ private createConfig?;
48
48
  readonly provider: "opensandbox";
49
49
  readonly runtime: SandboxRuntimeType;
50
50
  private _sandbox?;
51
51
  private _connection;
52
52
  private _id;
53
- constructor(connectionConfig: OpenSandboxConnectionConfig | undefined, createConfig: OpenSandboxConfigType);
53
+ constructor(connectionConfig?: OpenSandboxConnectionConfig, createConfig?: OpenSandboxConfigType | undefined);
54
54
  get id(): SandboxId;
55
55
  private get sandbox();
56
56
  private createConnectionConfig;
@@ -66,6 +66,23 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
66
66
  start(): Promise<void>;
67
67
  stop(): Promise<void>;
68
68
  delete(): Promise<void>;
69
+ /**
70
+ * Release client-side resources owned by this Sandbox instance.
71
+ * Does NOT stop or delete the container - the sandbox keeps running.
72
+ * Use this to disconnect from a sandbox without destroying it.
73
+ */
74
+ close(): Promise<void>;
75
+ /**
76
+ * Get endpoint information for a specific port exposed by the sandbox.
77
+ * @param port The port number to get endpoint for
78
+ * @returns Endpoint with host, port, protocol and url fields
79
+ */
80
+ getEndpoint(port: number): Promise<Endpoint>;
81
+ /**
82
+ * Convert SDK Endpoint (no-scheme string) to our Endpoint type.
83
+ * SDK format: "localhost:44772" or "domain/route/.../44772"
84
+ */
85
+ private convertSdkEndpoint;
69
86
  getInfo(): Promise<SandboxInfo | null>;
70
87
  renewExpiration(additionalSeconds: number): Promise<void>;
71
88
  execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
@@ -1,6 +1,10 @@
1
1
  import { type SealosDevboxConfig } from './SealosDevboxAdapter';
2
2
  import { type OpenSandboxConnectionConfig, type OpenSandboxConfigType } from './OpenSandboxAdapter';
3
3
  import { ISandbox } from '@/interfaces';
4
+ export { SealosDevboxAdapter } from './SealosDevboxAdapter';
5
+ export type { SealosDevboxConfig } from './SealosDevboxAdapter';
6
+ export { OpenSandboxAdapter } from './OpenSandboxAdapter';
7
+ export type { OpenSandboxConfigType, OpenSandboxConnectionConfig } from './OpenSandboxAdapter';
4
8
  export type SandboxProviderType = 'opensandbox' | 'sealosdevbox';
5
9
  /** Maps each provider name to the ISandbox config type it exposes. */
6
10
  interface SandboxConfigMap {
@@ -21,5 +25,4 @@ interface SandboxConnectionConfig {
21
25
  * @returns Configured sandbox instance
22
26
  * @throws Error if provider type is unknown
23
27
  */
24
- export declare function createSandbox<P extends SandboxProviderType>(provider: P, config: SandboxConnectionConfig[P], createConfig: SandboxConfigMap[P]): ISandbox;
25
- export {};
28
+ export declare function createSandbox<P extends SandboxProviderType>(provider: P, config: SandboxConnectionConfig[P], createConfig?: SandboxConfigMap[P]): ISandbox;
package/dist/index.js CHANGED
@@ -356,6 +356,8 @@ POLYFILL_EOF`);
356
356
  };
357
357
  }
358
358
  escapePath(path) {
359
+ if (!path)
360
+ return ".";
359
361
  return path.replace(/"/g, "\\\"");
360
362
  }
361
363
  parseLsOutput(output, basePath) {
@@ -624,6 +626,16 @@ class BaseSandboxAdapter {
624
626
  }
625
627
  return this.polyfillService;
626
628
  }
629
+ escapeShellArg(arg) {
630
+ return `'${arg.replace(/'/g, "'\\''")}'`;
631
+ }
632
+ buildCommand(command, workingDirectory) {
633
+ if (workingDirectory) {
634
+ const escapedDir = this.escapeShellArg(workingDirectory);
635
+ return ["sh", "-lc", `cd ${escapedDir} && ${command}`];
636
+ }
637
+ return ["sh", "-lc", command];
638
+ }
627
639
  }
628
640
 
629
641
  // src/adapters/SealosDevboxAdapter/api.ts
@@ -650,6 +662,9 @@ class DevboxApi {
650
662
  headers.set("Content-Type", "application/json");
651
663
  }
652
664
  const res = await fetch(input, { ...init, headers });
665
+ if (!res.ok) {
666
+ throw new Error(res.statusText || res.status.toString());
667
+ }
653
668
  const result = await res.json();
654
669
  return result;
655
670
  }
@@ -805,7 +820,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
805
820
  }
806
821
  await this.create();
807
822
  } catch (error) {
808
- throw new ConnectionError("Failed to ensure sandbox running", this.config.baseUrl, error);
823
+ throw new ConnectionError(`Failed to ensure sandbox running: ${error?.message || error?.code}`, this.config.baseUrl, error);
809
824
  }
810
825
  }
811
826
  async create() {
@@ -848,7 +863,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
848
863
  }
849
864
  }
850
865
  async execute(command, options) {
851
- const cmd = options?.workingDirectory ? ["sh", "-lc", `cd ${options.workingDirectory} && ${command}`] : ["sh", "-lc", command];
866
+ const cmd = this.buildCommand(command, options?.workingDirectory);
867
+ console.log(cmd, 2222);
852
868
  try {
853
869
  const res = await this.api.exec(this._id, {
854
870
  command: cmd,
@@ -879,7 +895,10 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
879
895
  }
880
896
 
881
897
  // src/adapters/OpenSandboxAdapter/index.ts
882
- import { ConnectionConfig, Sandbox } from "@alibaba-group/opensandbox";
898
+ import {
899
+ ConnectionConfig,
900
+ Sandbox
901
+ } from "@alibaba-group/opensandbox";
883
902
  class OpenSandboxAdapter extends BaseSandboxAdapter {
884
903
  connectionConfig;
885
904
  createConfig;
@@ -894,6 +913,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
894
913
  this.createConfig = createConfig;
895
914
  this.runtime = connectionConfig.runtime ?? "docker";
896
915
  this._connection = this.createConnectionConfig();
916
+ this.polyfillService = new CommandPolyfillService(this);
897
917
  }
898
918
  get id() {
899
919
  return this._id;
@@ -1000,18 +1020,22 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
1000
1020
  return this.create();
1001
1021
  }
1002
1022
  async create() {
1023
+ if (!this.createConfig) {
1024
+ throw new Error("createConfig is required to create a sandbox. Pass it as the third argument to createSandbox().");
1025
+ }
1026
+ const cfg = this.createConfig;
1003
1027
  try {
1004
1028
  this._status = { state: "Creating" };
1005
- const image = this.convertImageSpec(this.createConfig.image);
1006
- const resource = this.convertResourceLimits(this.createConfig.resourceLimits);
1029
+ const image = this.convertImageSpec(cfg.image);
1030
+ const resource = this.convertResourceLimits(cfg.resourceLimits);
1007
1031
  this._sandbox = await Sandbox.create({
1008
1032
  connectionConfig: this._connection,
1009
1033
  image,
1010
- entrypoint: this.createConfig.entrypoint,
1011
- timeoutSeconds: this.createConfig.timeout,
1034
+ entrypoint: cfg.entrypoint,
1035
+ timeoutSeconds: cfg.timeout,
1012
1036
  resource,
1013
- env: this.createConfig.env,
1014
- metadata: this.createConfig.metadata
1037
+ env: cfg.env,
1038
+ metadata: cfg.metadata
1015
1039
  });
1016
1040
  this._id = this._sandbox.id;
1017
1041
  this._status = { state: "Running" };
@@ -1067,6 +1091,33 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
1067
1091
  throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
1068
1092
  }
1069
1093
  }
1094
+ async close() {
1095
+ if (this._sandbox) {
1096
+ await this._sandbox.close();
1097
+ }
1098
+ }
1099
+ async getEndpoint(port) {
1100
+ const sdkEndpoint = await this.sandbox.getEndpoint(port);
1101
+ return this.convertSdkEndpoint(sdkEndpoint, port);
1102
+ }
1103
+ convertSdkEndpoint(sdkEndpoint, requestedPort) {
1104
+ const raw = sdkEndpoint.endpoint;
1105
+ const colonIdx = raw.lastIndexOf(":");
1106
+ const hasPathBeforeColon = colonIdx !== -1 && raw.slice(0, colonIdx).includes("/");
1107
+ if (colonIdx !== -1 && !hasPathBeforeColon) {
1108
+ const host = raw.slice(0, colonIdx);
1109
+ const parsedPort = parseInt(raw.slice(colonIdx + 1), 10);
1110
+ const port = isNaN(parsedPort) ? requestedPort : parsedPort;
1111
+ const protocol = port === 443 ? "https" : "http";
1112
+ return { host, port, protocol, url: `${protocol}://${raw}` };
1113
+ }
1114
+ return {
1115
+ host: raw,
1116
+ port: requestedPort,
1117
+ protocol: "https",
1118
+ url: `https://${raw}`
1119
+ };
1120
+ }
1070
1121
  async getInfo() {
1071
1122
  if (!this._sandbox)
1072
1123
  return null;
@@ -1212,9 +1263,11 @@ function createSandbox(provider, config, createConfig) {
1212
1263
  export {
1213
1264
  createSandbox,
1214
1265
  TimeoutError,
1266
+ SealosDevboxAdapter,
1215
1267
  SandboxStateError,
1216
1268
  SandboxReadyTimeoutError,
1217
1269
  SandboxException,
1270
+ OpenSandboxAdapter,
1218
1271
  FileOperationError,
1219
1272
  FeatureNotSupportedError,
1220
1273
  ConnectionError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastgpt-sdk/sandbox-adapter",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
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.js",