@fastgpt-sdk/sandbox-adapter 0.0.6 → 0.0.8

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.
@@ -1,6 +1,6 @@
1
1
  import type { ISandbox } from '../interfaces/ISandbox';
2
2
  import { CommandPolyfillService } from '../polyfill/CommandPolyfillService';
3
- import type { ContentReplaceEntry, DirectoryEntry, ExecuteOptions, ExecuteResult, FileDeleteResult, FileInfo, FileReadResult, FileWriteEntry, FileWriteResult, MoveEntry, PermissionEntry, ReadFileOptions, SandboxConfig, SandboxId, SandboxInfo, SandboxMetrics, SandboxStatus, SearchResult, StreamHandlers } from '../types';
3
+ import type { ContentReplaceEntry, DirectoryEntry, ExecuteOptions, ExecuteResult, FileDeleteResult, FileInfo, FileReadResult, FileWriteEntry, FileWriteResult, MoveEntry, PermissionEntry, ReadFileOptions, SandboxId, SandboxInfo, SandboxMetrics, SandboxStatus, SearchResult, StreamHandlers } from '../types';
4
4
  /**
5
5
  * Abstract base class for all sandbox adapters.
6
6
  *
@@ -8,14 +8,15 @@ import type { ContentReplaceEntry, DirectoryEntry, ExecuteOptions, ExecuteResult
8
8
  * search, health, and metrics operations via CommandPolyfillService.
9
9
  * Subclasses can override the polyfill service in their constructor.
10
10
  */
11
- export declare abstract class BaseSandboxAdapter implements ISandbox {
11
+ export declare abstract class BaseSandboxAdapter<TSandboxConfig = unknown> implements ISandbox<TSandboxConfig> {
12
12
  abstract readonly id: SandboxId;
13
13
  abstract readonly provider: string;
14
14
  protected _status: SandboxStatus;
15
15
  protected polyfillService?: CommandPolyfillService;
16
16
  constructor();
17
17
  get status(): SandboxStatus;
18
- abstract create(config: SandboxConfig): Promise<void>;
18
+ abstract ensureRunning(config?: TSandboxConfig): Promise<void>;
19
+ abstract create(config?: TSandboxConfig): Promise<void>;
19
20
  abstract start(): Promise<void>;
20
21
  abstract stop(): Promise<void>;
21
22
  abstract delete(): Promise<void>;
@@ -1,5 +1,6 @@
1
- import type { ExecuteOptions, ExecuteResult, SandboxConfig, SandboxId, SandboxInfo, SandboxMetrics, StreamHandlers } from '../types';
2
- import { BaseSandboxAdapter } from './BaseSandboxAdapter';
1
+ import type { ExecuteOptions, ExecuteResult, SandboxId, SandboxInfo, SandboxMetrics, StreamHandlers } from '@/types';
2
+ import { BaseSandboxAdapter } from '../BaseSandboxAdapter';
3
+ import { OpenSandboxConfigType } from './type';
3
4
  /**
4
5
  * Sandbox runtime type.
5
6
  * - docker: Full-featured runtime with pause/resume support
@@ -40,7 +41,7 @@ export interface OpenSandboxConnectionConfig {
40
41
  * console.log(result.stdout); // v18.x.x
41
42
  * ```
42
43
  */
43
- export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
44
+ export declare class OpenSandboxAdapter extends BaseSandboxAdapter<OpenSandboxConfigType> {
44
45
  private connectionConfig;
45
46
  readonly provider: "opensandbox";
46
47
  readonly runtime: SandboxRuntimeType;
@@ -57,7 +58,8 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
57
58
  private parseImageSpec;
58
59
  private convertResourceLimits;
59
60
  private parseResourceLimits;
60
- create(config: SandboxConfig): Promise<void>;
61
+ ensureRunning(config: OpenSandboxConfigType): Promise<void>;
62
+ create(config: OpenSandboxConfigType): Promise<void>;
61
63
  connect(sandboxId: string): Promise<void>;
62
64
  start(): Promise<void>;
63
65
  stop(): Promise<void>;
@@ -0,0 +1,22 @@
1
+ import { ImageSpec, NetworkPolicy, ResourceLimits } from '@/types';
2
+ /**
3
+ * Configuration for creating a sandbox.
4
+ */
5
+ export interface OpenSandboxConfigType {
6
+ /** Container image specification */
7
+ image: ImageSpec;
8
+ /** Entrypoint command */
9
+ entrypoint?: string[];
10
+ /** Timeout in seconds (0 for no timeout) */
11
+ timeout?: number;
12
+ /** Resource limits */
13
+ resourceLimits?: ResourceLimits;
14
+ /** Environment variables */
15
+ env?: Record<string, string>;
16
+ /** Metadata for the sandbox */
17
+ metadata?: Record<string, any>;
18
+ /** Network access policy */
19
+ networkPolicy?: NetworkPolicy;
20
+ /** Provider-specific extensions */
21
+ extensions?: Record<string, unknown>;
22
+ }
@@ -1,4 +1,4 @@
1
- import type { ExecuteOptions, ExecuteResult, SandboxConfig, SandboxId, SandboxInfo } from '../../types';
1
+ import type { ExecuteOptions, ExecuteResult, SandboxId, SandboxInfo } from '../../types';
2
2
  import { BaseSandboxAdapter } from '../BaseSandboxAdapter';
3
3
  /**
4
4
  * Configuration for Sealos Devbox Adapter.
@@ -20,7 +20,8 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
20
20
  private StatusAdapt;
21
21
  private waitUntilDeleted;
22
22
  getInfo(): Promise<SandboxInfo | null>;
23
- create(_config: SandboxConfig): Promise<void>;
23
+ ensureRunning(): Promise<void>;
24
+ create(): Promise<void>;
24
25
  stop(): Promise<void>;
25
26
  start(): Promise<void>;
26
27
  delete(): Promise<void>;
@@ -1,17 +1,12 @@
1
- import { ISandbox } from '../interfaces';
2
1
  import { type SealosDevboxConfig } from './SealosDevboxAdapter';
3
- import { type MinimalProviderConfig } from './MinimalProviderAdapter';
4
2
  import { type OpenSandboxConnectionConfig } from './OpenSandboxAdapter';
5
- export { BaseSandboxAdapter } from './BaseSandboxAdapter';
3
+ import { ISandbox } from '@/interfaces';
6
4
  export { SealosDevboxAdapter, type SealosDevboxConfig } from './SealosDevboxAdapter';
7
- export { MinimalProviderAdapter, type MinimalProviderConfig, type MinimalProviderConnection } from './MinimalProviderAdapter';
8
5
  export { OpenSandboxAdapter, type OpenSandboxConnectionConfig, type SandboxRuntimeType } from './OpenSandboxAdapter';
6
+ export type SandboxProvider = 'opensandbox' | 'sealos-devbox';
9
7
  type CreateProviderType = {
10
8
  provider: 'opensandbox';
11
9
  config: OpenSandboxConnectionConfig;
12
- } | {
13
- provider: 'minimal';
14
- config: MinimalProviderConfig;
15
10
  } | {
16
11
  provider: 'sealos-devbox';
17
12
  config: SealosDevboxConfig;
@@ -23,4 +18,4 @@ type CreateProviderType = {
23
18
  * @returns Configured sandbox instance
24
19
  * @throws Error if provider type is unknown
25
20
  */
26
- export declare const createSandbox: ({ provider, config }: CreateProviderType) => ISandbox;
21
+ export declare const createSandbox: ({ provider, config }: CreateProviderType) => ISandbox<unknown>;
package/dist/index.js CHANGED
@@ -776,7 +776,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
776
776
  throw new CommandExecutionError("Failed to get sandbox info", "getInfo", error instanceof Error ? error : undefined);
777
777
  }
778
778
  }
779
- async create(_config) {
779
+ async ensureRunning() {
780
780
  try {
781
781
  const sandbox = await this.getInfo();
782
782
  if (sandbox) {
@@ -794,13 +794,21 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
794
794
  return;
795
795
  case "Deleting":
796
796
  await this.waitUntilDeleted();
797
+ await this.create();
798
+ return;
797
799
  default:
798
800
  throw new ConnectionError(`Failed to create sandbox: ${status}, ${sandbox.status.message}`);
799
801
  }
800
802
  }
803
+ await this.create();
804
+ } catch (error) {
805
+ throw new ConnectionError("Failed to ensure sandbox running", this.config.baseUrl, error);
806
+ }
807
+ }
808
+ async create() {
809
+ try {
801
810
  this._status = { state: "Creating" };
802
811
  await this.api.create(this._id);
803
- await this.waitUntilReady();
804
812
  this._status = { state: "Running" };
805
813
  } catch (error) {
806
814
  throw new ConnectionError("Failed to create sandbox", this.config.baseUrl, error);
@@ -837,7 +845,6 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
837
845
  }
838
846
  async execute(command, options) {
839
847
  try {
840
- await this.waitUntilReady();
841
848
  const cmd = options?.workingDirectory ? ["sh", "-lc", `cd ${options.workingDirectory} && ${command}`] : ["sh", "-lc", command];
842
849
  const res = await this.api.exec(this._id, {
843
850
  command: cmd,
@@ -867,91 +874,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
867
874
  }
868
875
  }
869
876
 
870
- // src/adapters/MinimalProviderAdapter.ts
871
- class MinimalProviderAdapter extends BaseSandboxAdapter {
872
- config;
873
- provider = "minimal";
874
- _id = "";
875
- connection;
876
- constructor(config) {
877
- super();
878
- this.config = config;
879
- this.polyfillService = new CommandPolyfillService(this);
880
- }
881
- get id() {
882
- return this._id;
883
- }
884
- async create(config) {
885
- if (!this.config?.connectionFactory) {
886
- throw new ConnectionError("Connection factory not provided");
887
- }
888
- try {
889
- this._status = { state: "Creating" };
890
- this.connection = await this.config.connectionFactory();
891
- this._id = this.connection.id;
892
- this._status = { state: "Running" };
893
- if (config.entrypoint && config.entrypoint.length > 0) {
894
- await this.execute(config.entrypoint.join(" "));
895
- }
896
- } catch (error) {
897
- this._status = { state: "Error", message: String(error) };
898
- throw new ConnectionError("Failed to create sandbox", undefined, error);
899
- }
900
- }
901
- async connect(connection) {
902
- this.connection = connection;
903
- this._id = connection.id;
904
- this._status = await connection.getStatus();
905
- }
906
- async start() {
907
- this._status = { state: "Running" };
908
- }
909
- async stop() {
910
- await this.execute("exit 0").catch(() => {});
911
- await this.connection?.close();
912
- this._status = { state: "Stopped" };
913
- }
914
- async delete() {
915
- await this.stop();
916
- this._status = { state: "UnExist" };
917
- }
918
- async getInfo() {
919
- if (!this.connection)
920
- return null;
921
- return {
922
- id: this._id,
923
- image: { repository: "minimal", tag: "latest" },
924
- entrypoint: [],
925
- status: this._status,
926
- createdAt: new Date
927
- };
928
- }
929
- async execute(command, options) {
930
- if (!this.connection) {
931
- throw new Error("Not connected to minimal provider");
932
- }
933
- let finalCommand = command;
934
- if (options?.workingDirectory) {
935
- finalCommand = `cd "${options.workingDirectory}" && ${command}`;
936
- }
937
- if (options?.timeoutMs && options.timeoutMs > 0) {
938
- const timeoutSec = Math.ceil(options.timeoutMs / 1000);
939
- finalCommand = `timeout ${timeoutSec} sh -c '${finalCommand.replace(/'/g, `'"'"'`)}'`;
940
- }
941
- if (options?.env && Object.keys(options.env).length > 0) {
942
- const envVars = Object.entries(options.env).map(([k, v]) => `${k}="${v.replace(/"/g, '"')}"`).join(" ");
943
- finalCommand = `export ${envVars} && ${finalCommand}`;
944
- }
945
- const result = await this.connection.execute(finalCommand);
946
- return {
947
- stdout: result.stdout,
948
- stderr: result.stderr,
949
- exitCode: result.exitCode
950
- };
951
- }
952
- }
953
-
954
- // src/adapters/OpenSandboxAdapter.ts
877
+ // src/adapters/OpenSandboxAdapter/index.ts
955
878
  import { ConnectionConfig, Sandbox } from "@alibaba-group/opensandbox";
956
879
  class OpenSandboxAdapter extends BaseSandboxAdapter {
957
880
  connectionConfig;
@@ -1067,6 +990,9 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
1067
990
  }
1068
991
  return result;
1069
992
  }
993
+ async ensureRunning(config) {
994
+ return this.create(config);
995
+ }
1070
996
  async create(config) {
1071
997
  try {
1072
998
  this._status = { state: "Creating" };
@@ -1271,8 +1197,6 @@ var createSandbox = ({ provider, config }) => {
1271
1197
  switch (provider) {
1272
1198
  case "opensandbox":
1273
1199
  return new OpenSandboxAdapter(config);
1274
- case "minimal":
1275
- return new MinimalProviderAdapter(config);
1276
1200
  case "sealos-devbox":
1277
1201
  return new SealosDevboxAdapter(config);
1278
1202
  default:
@@ -1287,10 +1211,8 @@ export {
1287
1211
  SandboxReadyTimeoutError,
1288
1212
  SandboxException,
1289
1213
  OpenSandboxAdapter,
1290
- MinimalProviderAdapter,
1291
1214
  FileOperationError,
1292
1215
  FeatureNotSupportedError,
1293
1216
  ConnectionError,
1294
- CommandExecutionError,
1295
- BaseSandboxAdapter
1217
+ CommandExecutionError
1296
1218
  };
@@ -12,7 +12,7 @@ import type { ISandboxLifecycle } from './ISandboxLifecycle';
12
12
  * Following Interface Segregation Principle, this interface
13
13
  * is composed of smaller, focused interfaces.
14
14
  */
15
- export interface ISandbox extends ISandboxLifecycle, ICommandExecution, IFileSystem, IHealthCheck {
15
+ export interface ISandbox<TSandboxConfig = unknown> extends ISandboxLifecycle<TSandboxConfig>, ICommandExecution, IFileSystem, IHealthCheck {
16
16
  /** Provider name (e.g., 'opensandbox') */
17
17
  readonly provider: string;
18
18
  }
@@ -1,18 +1,22 @@
1
- import type { SandboxConfig, SandboxId, SandboxInfo, SandboxStatus } from '../types';
1
+ import type { SandboxId, SandboxInfo, SandboxStatus } from '../types';
2
2
  /**
3
3
  * Interface for sandbox lifecycle operations.
4
4
  * Follows Interface Segregation Principle - only lifecycle methods.
5
5
  */
6
- export interface ISandboxLifecycle {
6
+ export interface ISandboxLifecycle<TSandboxConfig = unknown> {
7
7
  /** Unique identifier for this sandbox */
8
8
  readonly id: SandboxId;
9
9
  /** Current status of the sandbox */
10
10
  readonly status: SandboxStatus;
11
+ /**
12
+ * Ensure the sandbox is running.
13
+ */
14
+ ensureRunning(config?: TSandboxConfig): Promise<void>;
11
15
  /**
12
16
  * Create a new sandbox with the given configuration.
13
17
  * The sandbox ID is assigned after creation.
14
18
  */
15
- create(config: SandboxConfig): Promise<void>;
19
+ create(config?: TSandboxConfig): Promise<void>;
16
20
  /**
17
21
  * Start a stopped sandbox.
18
22
  */
@@ -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, NetworkPolicy, ResourceLimits, SandboxConfig, SandboxId, SandboxInfo, SandboxMetrics, SandboxState, SandboxStatus } from './sandbox';
3
+ export type { Endpoint, ImageSpec, NetworkPolicy, ResourceLimits, SandboxId, SandboxInfo, SandboxMetrics, SandboxState, SandboxStatus } from './sandbox';
@@ -37,27 +37,6 @@ export interface NetworkPolicy {
37
37
  allowEgress?: boolean;
38
38
  allowedHosts?: string[];
39
39
  }
40
- /**
41
- * Configuration for creating a sandbox.
42
- */
43
- export interface SandboxConfig {
44
- /** Container image specification */
45
- image: ImageSpec;
46
- /** Entrypoint command */
47
- entrypoint?: string[];
48
- /** Timeout in seconds (0 for no timeout) */
49
- timeout?: number;
50
- /** Resource limits */
51
- resourceLimits?: ResourceLimits;
52
- /** Environment variables */
53
- env?: Record<string, string>;
54
- /** Metadata for the sandbox */
55
- metadata?: Record<string, any>;
56
- /** Network access policy */
57
- networkPolicy?: NetworkPolicy;
58
- /** Provider-specific extensions */
59
- extensions?: Record<string, unknown>;
60
- }
61
40
  /**
62
41
  * Information about a sandbox.
63
42
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastgpt-sdk/sandbox-adapter",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
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",
@@ -1,46 +0,0 @@
1
- import type { ExecuteOptions, ExecuteResult, SandboxConfig, SandboxId, SandboxInfo, SandboxStatus } from '../types';
2
- import { BaseSandboxAdapter } from './BaseSandboxAdapter';
3
- /**
4
- * Connection interface for minimal providers.
5
- * Represents a provider that only supports basic command execution.
6
- */
7
- export interface MinimalProviderConnection {
8
- /** Unique identifier for the sandbox */
9
- id: string;
10
- /** Execute a command and return result */
11
- execute(command: string): Promise<{
12
- stdout: string;
13
- stderr: string;
14
- exitCode: number;
15
- }>;
16
- /** Get current status */
17
- getStatus(): Promise<SandboxStatus>;
18
- close(): Promise<void>;
19
- }
20
- export type MinimalProviderConfig = {
21
- connectionFactory?: () => Promise<MinimalProviderConnection>;
22
- };
23
- /**
24
- * Minimal provider adapter.
25
- *
26
- * Adapts a provider with minimal capabilities (only command execution)
27
- * to the full ISandbox interface using the CommandPolyfillService.
28
- *
29
- * Use case: Legacy SSH-based sandboxes, custom container providers,
30
- * or any provider that only exposes a shell interface.
31
- */
32
- export declare class MinimalProviderAdapter extends BaseSandboxAdapter {
33
- private config?;
34
- readonly provider = "minimal";
35
- private _id;
36
- private connection?;
37
- constructor(config?: MinimalProviderConfig | undefined);
38
- get id(): SandboxId;
39
- create(config: SandboxConfig): Promise<void>;
40
- connect(connection: MinimalProviderConnection): Promise<void>;
41
- start(): Promise<void>;
42
- stop(): Promise<void>;
43
- delete(): Promise<void>;
44
- getInfo(): Promise<SandboxInfo | null>;
45
- execute(command: string, options?: ExecuteOptions): Promise<ExecuteResult>;
46
- }