@fastgpt-sdk/sandbox-adapter 0.0.40-beta.0 → 0.0.40-beta.1

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.
@@ -74,6 +74,8 @@ export declare class OpenSandboxAdapter extends BaseSandboxAdapter {
74
74
  private parseResourceLimits;
75
75
  private extractExitCode;
76
76
  private getSandboxBySessionId;
77
+ private waitUntilSessionDeleted;
78
+ private killSandboxById;
77
79
  ensureRunning(): Promise<void>;
78
80
  create(): Promise<void>;
79
81
  connect(sandboxId: string): Promise<void>;
@@ -36,6 +36,7 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
36
36
  private StatusAdapt;
37
37
  private buildCreateRequest;
38
38
  private removeUndefined;
39
+ private assertMutationSuccess;
39
40
  getInfo(): Promise<SandboxInfo | null>;
40
41
  ensureRunning(): Promise<void>;
41
42
  create(): Promise<void>;
package/dist/index.cjs CHANGED
@@ -45819,6 +45819,12 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45819
45819
  removeUndefined(obj) {
45820
45820
  return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
45821
45821
  }
45822
+ assertMutationSuccess(res, action, okCodes = []) {
45823
+ if (res.code >= 200 && res.code < 300 || okCodes.includes(res.code)) {
45824
+ return;
45825
+ }
45826
+ throw new Error(res.message || `Devbox ${action} failed with code ${res.code}`);
45827
+ }
45822
45828
  async getInfo() {
45823
45829
  try {
45824
45830
  const res = await this.api.info(this._id);
@@ -45881,9 +45887,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45881
45887
  try {
45882
45888
  this._status = { state: "Creating" };
45883
45889
  const res = await this.api.create(this.buildCreateRequest());
45884
- if (res.code !== 200 && res.code !== 201) {
45885
- throw new Error(res.message || `Devbox create failed with code ${res.code}`);
45886
- }
45890
+ this.assertMutationSuccess(res, "create");
45887
45891
  await this.waitUntilReady();
45888
45892
  await new Promise((resolve) => setTimeout(resolve, 1000));
45889
45893
  this._status = { state: "Running" };
@@ -45894,7 +45898,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45894
45898
  async stop() {
45895
45899
  try {
45896
45900
  this._status = { state: "Stopping" };
45897
- await this.api.stop(this._id);
45901
+ const res = await this.api.stop(this._id);
45902
+ this.assertMutationSuccess(res, "stop");
45898
45903
  this._status = { state: "Stopped" };
45899
45904
  } catch (error) {
45900
45905
  throw new CommandExecutionError("Failed to stop sandbox", "stop", error instanceof Error ? error : undefined);
@@ -45903,7 +45908,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45903
45908
  async start() {
45904
45909
  try {
45905
45910
  this._status = { state: "Starting" };
45906
- await this.api.resume(this._id);
45911
+ const res = await this.api.resume(this._id);
45912
+ this.assertMutationSuccess(res, "resume");
45907
45913
  await this.waitUntilReady();
45908
45914
  this._status = { state: "Running" };
45909
45915
  } catch (error) {
@@ -45914,7 +45920,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45914
45920
  try {
45915
45921
  const targetId = sandboxId ?? this._id;
45916
45922
  this._status = { state: "Deleting" };
45917
- await this.api.delete(targetId);
45923
+ const res = await this.api.delete(targetId);
45924
+ this.assertMutationSuccess(res, "delete", [404]);
45918
45925
  this._id = targetId;
45919
45926
  await this.waitUntilDeleted();
45920
45927
  this._status = { state: "UnExist" };
@@ -48375,16 +48382,44 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48375
48382
  }
48376
48383
  async getSandboxBySessionId() {
48377
48384
  const manager = SandboxManager.create({ connectionConfig: this._connection });
48378
- const result = await manager.listSandboxInfos({
48379
- metadata: { sessionId: this.connectionConfig.sessionId }
48380
- });
48381
- const val = result.items[0];
48382
- if (val) {
48383
- const status = this.mapStatus(val.status);
48384
- return {
48385
- id: val.id,
48386
- status
48387
- };
48385
+ try {
48386
+ const result = await manager.listSandboxInfos({
48387
+ metadata: { sessionId: this.connectionConfig.sessionId }
48388
+ });
48389
+ const val = result.items[0];
48390
+ if (val) {
48391
+ const status = this.mapStatus(val.status);
48392
+ return {
48393
+ id: val.id,
48394
+ status
48395
+ };
48396
+ }
48397
+ } finally {
48398
+ await manager.close().catch(() => {
48399
+ return;
48400
+ });
48401
+ }
48402
+ }
48403
+ async waitUntilSessionDeleted(timeoutMs = 120000) {
48404
+ const startTime = Date.now();
48405
+ const checkInterval = 1000;
48406
+ while (Date.now() - startTime < timeoutMs) {
48407
+ const sandbox = await this.getSandboxBySessionId();
48408
+ if (!sandbox) {
48409
+ return;
48410
+ }
48411
+ await this.sleep(checkInterval);
48412
+ }
48413
+ throw new SandboxStateError(`Sandbox session ${this.connectionConfig.sessionId} was not deleted within ${timeoutMs}ms`, "Deleting", "UnExist");
48414
+ }
48415
+ async killSandboxById(sandboxId) {
48416
+ const manager = SandboxManager.create({ connectionConfig: this._connection });
48417
+ try {
48418
+ await manager.killSandbox(sandboxId);
48419
+ } finally {
48420
+ await manager.close().catch(() => {
48421
+ return;
48422
+ });
48388
48423
  }
48389
48424
  }
48390
48425
  async ensureRunning() {
@@ -48399,14 +48434,14 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48399
48434
  break;
48400
48435
  case "Creating":
48401
48436
  case "Starting":
48402
- await this.waitUntilReady();
48437
+ await this.connect(sandbox.id);
48403
48438
  break;
48404
48439
  case "Stopping":
48405
48440
  case "Stopped":
48406
48441
  await this.resume(sandbox.id);
48407
48442
  break;
48408
48443
  case "Deleting":
48409
- await this.waitUntilDeleted();
48444
+ await this.waitUntilSessionDeleted();
48410
48445
  await this.create();
48411
48446
  break;
48412
48447
  case "Error":
@@ -48503,7 +48538,15 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48503
48538
  async stop() {
48504
48539
  try {
48505
48540
  this._status = { state: "Stopping" };
48506
- await this.sandbox.kill();
48541
+ const existing = await this.getSandboxBySessionId();
48542
+ if (!existing) {
48543
+ this._status = { state: "Stopped" };
48544
+ return;
48545
+ }
48546
+ await this.killSandboxById(existing.id);
48547
+ if (existing.id === this._id) {
48548
+ this.sandbox = undefined;
48549
+ }
48507
48550
  this._status = { state: "Stopped" };
48508
48551
  } catch (error) {
48509
48552
  const message = error instanceof SandboxException2 ? error.error.message : undefined;
@@ -48519,23 +48562,22 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48519
48562
  async delete(sandboxId) {
48520
48563
  try {
48521
48564
  this._status = { state: "Deleting" };
48522
- if (sandboxId) {
48523
- const manager = SandboxManager.create({ connectionConfig: this._connection });
48524
- try {
48525
- await manager.killSandbox(sandboxId);
48526
- } finally {
48527
- await manager.close().catch(() => {
48528
- return;
48529
- });
48530
- }
48531
- if (sandboxId === this._id) {
48565
+ const targetId = sandboxId ?? this._id;
48566
+ if (targetId) {
48567
+ await this.killSandboxById(targetId);
48568
+ if (targetId === this._id) {
48532
48569
  this.sandbox = undefined;
48533
48570
  }
48534
48571
  this._status = { state: "UnExist" };
48535
48572
  return;
48536
48573
  }
48537
- await this.sandbox.kill();
48538
- this.sandbox = undefined;
48574
+ const existing = await this.getSandboxBySessionId();
48575
+ if (existing) {
48576
+ await this.killSandboxById(existing.id);
48577
+ if (existing.id === this._id) {
48578
+ this.sandbox = undefined;
48579
+ }
48580
+ }
48539
48581
  this._status = { state: "UnExist" };
48540
48582
  } catch (error) {
48541
48583
  throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
package/dist/index.js CHANGED
@@ -45803,6 +45803,12 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45803
45803
  removeUndefined(obj) {
45804
45804
  return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
45805
45805
  }
45806
+ assertMutationSuccess(res, action, okCodes = []) {
45807
+ if (res.code >= 200 && res.code < 300 || okCodes.includes(res.code)) {
45808
+ return;
45809
+ }
45810
+ throw new Error(res.message || `Devbox ${action} failed with code ${res.code}`);
45811
+ }
45806
45812
  async getInfo() {
45807
45813
  try {
45808
45814
  const res = await this.api.info(this._id);
@@ -45865,9 +45871,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45865
45871
  try {
45866
45872
  this._status = { state: "Creating" };
45867
45873
  const res = await this.api.create(this.buildCreateRequest());
45868
- if (res.code !== 200 && res.code !== 201) {
45869
- throw new Error(res.message || `Devbox create failed with code ${res.code}`);
45870
- }
45874
+ this.assertMutationSuccess(res, "create");
45871
45875
  await this.waitUntilReady();
45872
45876
  await new Promise((resolve) => setTimeout(resolve, 1000));
45873
45877
  this._status = { state: "Running" };
@@ -45878,7 +45882,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45878
45882
  async stop() {
45879
45883
  try {
45880
45884
  this._status = { state: "Stopping" };
45881
- await this.api.stop(this._id);
45885
+ const res = await this.api.stop(this._id);
45886
+ this.assertMutationSuccess(res, "stop");
45882
45887
  this._status = { state: "Stopped" };
45883
45888
  } catch (error) {
45884
45889
  throw new CommandExecutionError("Failed to stop sandbox", "stop", error instanceof Error ? error : undefined);
@@ -45887,7 +45892,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45887
45892
  async start() {
45888
45893
  try {
45889
45894
  this._status = { state: "Starting" };
45890
- await this.api.resume(this._id);
45895
+ const res = await this.api.resume(this._id);
45896
+ this.assertMutationSuccess(res, "resume");
45891
45897
  await this.waitUntilReady();
45892
45898
  this._status = { state: "Running" };
45893
45899
  } catch (error) {
@@ -45898,7 +45904,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45898
45904
  try {
45899
45905
  const targetId = sandboxId ?? this._id;
45900
45906
  this._status = { state: "Deleting" };
45901
- await this.api.delete(targetId);
45907
+ const res = await this.api.delete(targetId);
45908
+ this.assertMutationSuccess(res, "delete", [404]);
45902
45909
  this._id = targetId;
45903
45910
  await this.waitUntilDeleted();
45904
45911
  this._status = { state: "UnExist" };
@@ -48359,16 +48366,44 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48359
48366
  }
48360
48367
  async getSandboxBySessionId() {
48361
48368
  const manager = SandboxManager.create({ connectionConfig: this._connection });
48362
- const result = await manager.listSandboxInfos({
48363
- metadata: { sessionId: this.connectionConfig.sessionId }
48364
- });
48365
- const val = result.items[0];
48366
- if (val) {
48367
- const status = this.mapStatus(val.status);
48368
- return {
48369
- id: val.id,
48370
- status
48371
- };
48369
+ try {
48370
+ const result = await manager.listSandboxInfos({
48371
+ metadata: { sessionId: this.connectionConfig.sessionId }
48372
+ });
48373
+ const val = result.items[0];
48374
+ if (val) {
48375
+ const status = this.mapStatus(val.status);
48376
+ return {
48377
+ id: val.id,
48378
+ status
48379
+ };
48380
+ }
48381
+ } finally {
48382
+ await manager.close().catch(() => {
48383
+ return;
48384
+ });
48385
+ }
48386
+ }
48387
+ async waitUntilSessionDeleted(timeoutMs = 120000) {
48388
+ const startTime = Date.now();
48389
+ const checkInterval = 1000;
48390
+ while (Date.now() - startTime < timeoutMs) {
48391
+ const sandbox = await this.getSandboxBySessionId();
48392
+ if (!sandbox) {
48393
+ return;
48394
+ }
48395
+ await this.sleep(checkInterval);
48396
+ }
48397
+ throw new SandboxStateError(`Sandbox session ${this.connectionConfig.sessionId} was not deleted within ${timeoutMs}ms`, "Deleting", "UnExist");
48398
+ }
48399
+ async killSandboxById(sandboxId) {
48400
+ const manager = SandboxManager.create({ connectionConfig: this._connection });
48401
+ try {
48402
+ await manager.killSandbox(sandboxId);
48403
+ } finally {
48404
+ await manager.close().catch(() => {
48405
+ return;
48406
+ });
48372
48407
  }
48373
48408
  }
48374
48409
  async ensureRunning() {
@@ -48383,14 +48418,14 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48383
48418
  break;
48384
48419
  case "Creating":
48385
48420
  case "Starting":
48386
- await this.waitUntilReady();
48421
+ await this.connect(sandbox.id);
48387
48422
  break;
48388
48423
  case "Stopping":
48389
48424
  case "Stopped":
48390
48425
  await this.resume(sandbox.id);
48391
48426
  break;
48392
48427
  case "Deleting":
48393
- await this.waitUntilDeleted();
48428
+ await this.waitUntilSessionDeleted();
48394
48429
  await this.create();
48395
48430
  break;
48396
48431
  case "Error":
@@ -48487,7 +48522,15 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48487
48522
  async stop() {
48488
48523
  try {
48489
48524
  this._status = { state: "Stopping" };
48490
- await this.sandbox.kill();
48525
+ const existing = await this.getSandboxBySessionId();
48526
+ if (!existing) {
48527
+ this._status = { state: "Stopped" };
48528
+ return;
48529
+ }
48530
+ await this.killSandboxById(existing.id);
48531
+ if (existing.id === this._id) {
48532
+ this.sandbox = undefined;
48533
+ }
48491
48534
  this._status = { state: "Stopped" };
48492
48535
  } catch (error) {
48493
48536
  const message = error instanceof SandboxException2 ? error.error.message : undefined;
@@ -48503,23 +48546,22 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48503
48546
  async delete(sandboxId) {
48504
48547
  try {
48505
48548
  this._status = { state: "Deleting" };
48506
- if (sandboxId) {
48507
- const manager = SandboxManager.create({ connectionConfig: this._connection });
48508
- try {
48509
- await manager.killSandbox(sandboxId);
48510
- } finally {
48511
- await manager.close().catch(() => {
48512
- return;
48513
- });
48514
- }
48515
- if (sandboxId === this._id) {
48549
+ const targetId = sandboxId ?? this._id;
48550
+ if (targetId) {
48551
+ await this.killSandboxById(targetId);
48552
+ if (targetId === this._id) {
48516
48553
  this.sandbox = undefined;
48517
48554
  }
48518
48555
  this._status = { state: "UnExist" };
48519
48556
  return;
48520
48557
  }
48521
- await this.sandbox.kill();
48522
- this.sandbox = undefined;
48558
+ const existing = await this.getSandboxBySessionId();
48559
+ if (existing) {
48560
+ await this.killSandboxById(existing.id);
48561
+ if (existing.id === this._id) {
48562
+ this.sandbox = undefined;
48563
+ }
48564
+ }
48523
48565
  this._status = { state: "UnExist" };
48524
48566
  } catch (error) {
48525
48567
  throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
@@ -28,7 +28,7 @@ export interface ISandboxLifecycle {
28
28
  /**
29
29
  * Delete the sandbox permanently.
30
30
  *
31
- * When `sandboxId` is provided, implementations should delete that provider
31
+ * When `sandboxId` is provided, implementations should delete that target
32
32
  * sandbox directly without requiring callers to first bind the adapter via
33
33
  * `connect()`.
34
34
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastgpt-sdk/sandbox-adapter",
3
- "version": "0.0.40-beta.0",
3
+ "version": "0.0.40-beta.1",
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",