@fastgpt-sdk/sandbox-adapter 0.0.5 → 0.0.7

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';
3
+ import { ISandbox } from '@/interfaces';
5
4
  export { BaseSandboxAdapter } from './BaseSandboxAdapter';
6
5
  export { SealosDevboxAdapter, type SealosDevboxConfig } from './SealosDevboxAdapter';
7
- export { MinimalProviderAdapter, type MinimalProviderConfig, type MinimalProviderConnection } from './MinimalProviderAdapter';
8
6
  export { OpenSandboxAdapter, type OpenSandboxConnectionConfig, type SandboxRuntimeType } from './OpenSandboxAdapter';
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,14 +845,12 @@ 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,
844
851
  timeoutSeconds: options?.timeoutMs ? Math.ceil(options.timeoutMs / 1000) : undefined
845
852
  });
846
853
  if (!res.data) {
847
- console.log(res);
848
854
  throw new CommandExecutionError(`Command execution failed: ${command}`, command);
849
855
  }
850
856
  return {
@@ -868,91 +874,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
868
874
  }
869
875
  }
870
876
 
871
- // src/adapters/MinimalProviderAdapter.ts
872
- class MinimalProviderAdapter extends BaseSandboxAdapter {
873
- config;
874
- provider = "minimal";
875
- _id = "";
876
- connection;
877
- constructor(config) {
878
- super();
879
- this.config = config;
880
- this.polyfillService = new CommandPolyfillService(this);
881
- }
882
- get id() {
883
- return this._id;
884
- }
885
- async create(config) {
886
- if (!this.config?.connectionFactory) {
887
- throw new ConnectionError("Connection factory not provided");
888
- }
889
- try {
890
- this._status = { state: "Creating" };
891
- this.connection = await this.config.connectionFactory();
892
- this._id = this.connection.id;
893
- this._status = { state: "Running" };
894
- if (config.entrypoint && config.entrypoint.length > 0) {
895
- await this.execute(config.entrypoint.join(" "));
896
- }
897
- } catch (error) {
898
- this._status = { state: "Error", message: String(error) };
899
- throw new ConnectionError("Failed to create sandbox", undefined, error);
900
- }
901
- }
902
- async connect(connection) {
903
- this.connection = connection;
904
- this._id = connection.id;
905
- this._status = await connection.getStatus();
906
- }
907
- async start() {
908
- this._status = { state: "Running" };
909
- }
910
- async stop() {
911
- await this.execute("exit 0").catch(() => {});
912
- await this.connection?.close();
913
- this._status = { state: "Stopped" };
914
- }
915
- async delete() {
916
- await this.stop();
917
- this._status = { state: "UnExist" };
918
- }
919
- async getInfo() {
920
- if (!this.connection)
921
- return null;
922
- return {
923
- id: this._id,
924
- image: { repository: "minimal", tag: "latest" },
925
- entrypoint: [],
926
- status: this._status,
927
- createdAt: new Date
928
- };
929
- }
930
- async execute(command, options) {
931
- if (!this.connection) {
932
- throw new Error("Not connected to minimal provider");
933
- }
934
- let finalCommand = command;
935
- if (options?.workingDirectory) {
936
- finalCommand = `cd "${options.workingDirectory}" && ${command}`;
937
- }
938
- if (options?.timeoutMs && options.timeoutMs > 0) {
939
- const timeoutSec = Math.ceil(options.timeoutMs / 1000);
940
- finalCommand = `timeout ${timeoutSec} sh -c '${finalCommand.replace(/'/g, `'"'"'`)}'`;
941
- }
942
- if (options?.env && Object.keys(options.env).length > 0) {
943
- const envVars = Object.entries(options.env).map(([k, v]) => `${k}="${v.replace(/"/g, '"')}"`).join(" ");
944
- finalCommand = `export ${envVars} && ${finalCommand}`;
945
- }
946
- const result = await this.connection.execute(finalCommand);
947
- return {
948
- stdout: result.stdout,
949
- stderr: result.stderr,
950
- exitCode: result.exitCode
951
- };
952
- }
953
- }
954
-
955
- // src/adapters/OpenSandboxAdapter.ts
877
+ // src/adapters/OpenSandboxAdapter/index.ts
956
878
  import { ConnectionConfig, Sandbox } from "@alibaba-group/opensandbox";
957
879
  class OpenSandboxAdapter extends BaseSandboxAdapter {
958
880
  connectionConfig;
@@ -1068,6 +990,9 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
1068
990
  }
1069
991
  return result;
1070
992
  }
993
+ async ensureRunning(config) {
994
+ return this.create(config);
995
+ }
1071
996
  async create(config) {
1072
997
  try {
1073
998
  this._status = { state: "Creating" };
@@ -1272,8 +1197,6 @@ var createSandbox = ({ provider, config }) => {
1272
1197
  switch (provider) {
1273
1198
  case "opensandbox":
1274
1199
  return new OpenSandboxAdapter(config);
1275
- case "minimal":
1276
- return new MinimalProviderAdapter(config);
1277
1200
  case "sealos-devbox":
1278
1201
  return new SealosDevboxAdapter(config);
1279
1202
  default:
@@ -1288,7 +1211,6 @@ export {
1288
1211
  SandboxReadyTimeoutError,
1289
1212
  SandboxException,
1290
1213
  OpenSandboxAdapter,
1291
- MinimalProviderAdapter,
1292
1214
  FileOperationError,
1293
1215
  FeatureNotSupportedError,
1294
1216
  ConnectionError,
@@ -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.5",
3
+ "version": "0.0.7",
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
- }