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

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,8 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
36
36
  private StatusAdapt;
37
37
  private buildCreateRequest;
38
38
  private removeUndefined;
39
+ private assertMutationSuccess;
40
+ private isNotFoundResponse;
39
41
  getInfo(): Promise<SandboxInfo | null>;
40
42
  ensureRunning(): Promise<void>;
41
43
  create(): Promise<void>;
package/dist/index.cjs CHANGED
@@ -45819,6 +45819,15 @@ 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
+ }
45828
+ isNotFoundResponse(res) {
45829
+ return res.code === 404 || String(res.message ?? "").toLowerCase().includes("not found");
45830
+ }
45822
45831
  async getInfo() {
45823
45832
  try {
45824
45833
  const res = await this.api.info(this._id);
@@ -45881,9 +45890,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45881
45890
  try {
45882
45891
  this._status = { state: "Creating" };
45883
45892
  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
- }
45893
+ this.assertMutationSuccess(res, "create");
45887
45894
  await this.waitUntilReady();
45888
45895
  await new Promise((resolve) => setTimeout(resolve, 1000));
45889
45896
  this._status = { state: "Running" };
@@ -45894,7 +45901,12 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45894
45901
  async stop() {
45895
45902
  try {
45896
45903
  this._status = { state: "Stopping" };
45897
- await this.api.stop(this._id);
45904
+ const res = await this.api.stop(this._id);
45905
+ if (this.isNotFoundResponse(res)) {
45906
+ this._status = { state: "Stopped" };
45907
+ return;
45908
+ }
45909
+ this.assertMutationSuccess(res, "stop");
45898
45910
  this._status = { state: "Stopped" };
45899
45911
  } catch (error) {
45900
45912
  throw new CommandExecutionError("Failed to stop sandbox", "stop", error instanceof Error ? error : undefined);
@@ -45903,7 +45915,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45903
45915
  async start() {
45904
45916
  try {
45905
45917
  this._status = { state: "Starting" };
45906
- await this.api.resume(this._id);
45918
+ const res = await this.api.resume(this._id);
45919
+ this.assertMutationSuccess(res, "resume");
45907
45920
  await this.waitUntilReady();
45908
45921
  this._status = { state: "Running" };
45909
45922
  } catch (error) {
@@ -45914,7 +45927,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45914
45927
  try {
45915
45928
  const targetId = sandboxId ?? this._id;
45916
45929
  this._status = { state: "Deleting" };
45917
- await this.api.delete(targetId);
45930
+ const res = await this.api.delete(targetId);
45931
+ this.assertMutationSuccess(res, "delete", [404]);
45918
45932
  this._id = targetId;
45919
45933
  await this.waitUntilDeleted();
45920
45934
  this._status = { state: "UnExist" };
@@ -48375,16 +48389,44 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48375
48389
  }
48376
48390
  async getSandboxBySessionId() {
48377
48391
  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
- };
48392
+ try {
48393
+ const result = await manager.listSandboxInfos({
48394
+ metadata: { sessionId: this.connectionConfig.sessionId }
48395
+ });
48396
+ const val = result.items[0];
48397
+ if (val) {
48398
+ const status = this.mapStatus(val.status);
48399
+ return {
48400
+ id: val.id,
48401
+ status
48402
+ };
48403
+ }
48404
+ } finally {
48405
+ await manager.close().catch(() => {
48406
+ return;
48407
+ });
48408
+ }
48409
+ }
48410
+ async waitUntilSessionDeleted(timeoutMs = 120000) {
48411
+ const startTime = Date.now();
48412
+ const checkInterval = 1000;
48413
+ while (Date.now() - startTime < timeoutMs) {
48414
+ const sandbox = await this.getSandboxBySessionId();
48415
+ if (!sandbox) {
48416
+ return;
48417
+ }
48418
+ await this.sleep(checkInterval);
48419
+ }
48420
+ throw new SandboxStateError(`Sandbox session ${this.connectionConfig.sessionId} was not deleted within ${timeoutMs}ms`, "Deleting", "UnExist");
48421
+ }
48422
+ async killSandboxById(sandboxId) {
48423
+ const manager = SandboxManager.create({ connectionConfig: this._connection });
48424
+ try {
48425
+ await manager.killSandbox(sandboxId);
48426
+ } finally {
48427
+ await manager.close().catch(() => {
48428
+ return;
48429
+ });
48388
48430
  }
48389
48431
  }
48390
48432
  async ensureRunning() {
@@ -48399,14 +48441,14 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48399
48441
  break;
48400
48442
  case "Creating":
48401
48443
  case "Starting":
48402
- await this.waitUntilReady();
48444
+ await this.connect(sandbox.id);
48403
48445
  break;
48404
48446
  case "Stopping":
48405
48447
  case "Stopped":
48406
48448
  await this.resume(sandbox.id);
48407
48449
  break;
48408
48450
  case "Deleting":
48409
- await this.waitUntilDeleted();
48451
+ await this.waitUntilSessionDeleted();
48410
48452
  await this.create();
48411
48453
  break;
48412
48454
  case "Error":
@@ -48503,7 +48545,15 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48503
48545
  async stop() {
48504
48546
  try {
48505
48547
  this._status = { state: "Stopping" };
48506
- await this.sandbox.kill();
48548
+ const existing = await this.getSandboxBySessionId();
48549
+ if (!existing) {
48550
+ this._status = { state: "Stopped" };
48551
+ return;
48552
+ }
48553
+ await this.killSandboxById(existing.id);
48554
+ if (existing.id === this._id) {
48555
+ this.sandbox = undefined;
48556
+ }
48507
48557
  this._status = { state: "Stopped" };
48508
48558
  } catch (error) {
48509
48559
  const message = error instanceof SandboxException2 ? error.error.message : undefined;
@@ -48519,23 +48569,22 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48519
48569
  async delete(sandboxId) {
48520
48570
  try {
48521
48571
  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) {
48572
+ const targetId = sandboxId ?? this._id;
48573
+ if (targetId) {
48574
+ await this.killSandboxById(targetId);
48575
+ if (targetId === this._id) {
48532
48576
  this.sandbox = undefined;
48533
48577
  }
48534
48578
  this._status = { state: "UnExist" };
48535
48579
  return;
48536
48580
  }
48537
- await this.sandbox.kill();
48538
- this.sandbox = undefined;
48581
+ const existing = await this.getSandboxBySessionId();
48582
+ if (existing) {
48583
+ await this.killSandboxById(existing.id);
48584
+ if (existing.id === this._id) {
48585
+ this.sandbox = undefined;
48586
+ }
48587
+ }
48539
48588
  this._status = { state: "UnExist" };
48540
48589
  } catch (error) {
48541
48590
  throw new CommandExecutionError("Failed to delete sandbox", "delete", error instanceof Error ? error : undefined);
package/dist/index.js CHANGED
@@ -45803,6 +45803,15 @@ 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
+ }
45812
+ isNotFoundResponse(res) {
45813
+ return res.code === 404 || String(res.message ?? "").toLowerCase().includes("not found");
45814
+ }
45806
45815
  async getInfo() {
45807
45816
  try {
45808
45817
  const res = await this.api.info(this._id);
@@ -45865,9 +45874,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45865
45874
  try {
45866
45875
  this._status = { state: "Creating" };
45867
45876
  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
- }
45877
+ this.assertMutationSuccess(res, "create");
45871
45878
  await this.waitUntilReady();
45872
45879
  await new Promise((resolve) => setTimeout(resolve, 1000));
45873
45880
  this._status = { state: "Running" };
@@ -45878,7 +45885,12 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45878
45885
  async stop() {
45879
45886
  try {
45880
45887
  this._status = { state: "Stopping" };
45881
- await this.api.stop(this._id);
45888
+ const res = await this.api.stop(this._id);
45889
+ if (this.isNotFoundResponse(res)) {
45890
+ this._status = { state: "Stopped" };
45891
+ return;
45892
+ }
45893
+ this.assertMutationSuccess(res, "stop");
45882
45894
  this._status = { state: "Stopped" };
45883
45895
  } catch (error) {
45884
45896
  throw new CommandExecutionError("Failed to stop sandbox", "stop", error instanceof Error ? error : undefined);
@@ -45887,7 +45899,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45887
45899
  async start() {
45888
45900
  try {
45889
45901
  this._status = { state: "Starting" };
45890
- await this.api.resume(this._id);
45902
+ const res = await this.api.resume(this._id);
45903
+ this.assertMutationSuccess(res, "resume");
45891
45904
  await this.waitUntilReady();
45892
45905
  this._status = { state: "Running" };
45893
45906
  } catch (error) {
@@ -45898,7 +45911,8 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45898
45911
  try {
45899
45912
  const targetId = sandboxId ?? this._id;
45900
45913
  this._status = { state: "Deleting" };
45901
- await this.api.delete(targetId);
45914
+ const res = await this.api.delete(targetId);
45915
+ this.assertMutationSuccess(res, "delete", [404]);
45902
45916
  this._id = targetId;
45903
45917
  await this.waitUntilDeleted();
45904
45918
  this._status = { state: "UnExist" };
@@ -48359,16 +48373,44 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48359
48373
  }
48360
48374
  async getSandboxBySessionId() {
48361
48375
  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
- };
48376
+ try {
48377
+ const result = await manager.listSandboxInfos({
48378
+ metadata: { sessionId: this.connectionConfig.sessionId }
48379
+ });
48380
+ const val = result.items[0];
48381
+ if (val) {
48382
+ const status = this.mapStatus(val.status);
48383
+ return {
48384
+ id: val.id,
48385
+ status
48386
+ };
48387
+ }
48388
+ } finally {
48389
+ await manager.close().catch(() => {
48390
+ return;
48391
+ });
48392
+ }
48393
+ }
48394
+ async waitUntilSessionDeleted(timeoutMs = 120000) {
48395
+ const startTime = Date.now();
48396
+ const checkInterval = 1000;
48397
+ while (Date.now() - startTime < timeoutMs) {
48398
+ const sandbox = await this.getSandboxBySessionId();
48399
+ if (!sandbox) {
48400
+ return;
48401
+ }
48402
+ await this.sleep(checkInterval);
48403
+ }
48404
+ throw new SandboxStateError(`Sandbox session ${this.connectionConfig.sessionId} was not deleted within ${timeoutMs}ms`, "Deleting", "UnExist");
48405
+ }
48406
+ async killSandboxById(sandboxId) {
48407
+ const manager = SandboxManager.create({ connectionConfig: this._connection });
48408
+ try {
48409
+ await manager.killSandbox(sandboxId);
48410
+ } finally {
48411
+ await manager.close().catch(() => {
48412
+ return;
48413
+ });
48372
48414
  }
48373
48415
  }
48374
48416
  async ensureRunning() {
@@ -48383,14 +48425,14 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48383
48425
  break;
48384
48426
  case "Creating":
48385
48427
  case "Starting":
48386
- await this.waitUntilReady();
48428
+ await this.connect(sandbox.id);
48387
48429
  break;
48388
48430
  case "Stopping":
48389
48431
  case "Stopped":
48390
48432
  await this.resume(sandbox.id);
48391
48433
  break;
48392
48434
  case "Deleting":
48393
- await this.waitUntilDeleted();
48435
+ await this.waitUntilSessionDeleted();
48394
48436
  await this.create();
48395
48437
  break;
48396
48438
  case "Error":
@@ -48487,7 +48529,15 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48487
48529
  async stop() {
48488
48530
  try {
48489
48531
  this._status = { state: "Stopping" };
48490
- await this.sandbox.kill();
48532
+ const existing = await this.getSandboxBySessionId();
48533
+ if (!existing) {
48534
+ this._status = { state: "Stopped" };
48535
+ return;
48536
+ }
48537
+ await this.killSandboxById(existing.id);
48538
+ if (existing.id === this._id) {
48539
+ this.sandbox = undefined;
48540
+ }
48491
48541
  this._status = { state: "Stopped" };
48492
48542
  } catch (error) {
48493
48543
  const message = error instanceof SandboxException2 ? error.error.message : undefined;
@@ -48503,23 +48553,22 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48503
48553
  async delete(sandboxId) {
48504
48554
  try {
48505
48555
  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) {
48556
+ const targetId = sandboxId ?? this._id;
48557
+ if (targetId) {
48558
+ await this.killSandboxById(targetId);
48559
+ if (targetId === this._id) {
48516
48560
  this.sandbox = undefined;
48517
48561
  }
48518
48562
  this._status = { state: "UnExist" };
48519
48563
  return;
48520
48564
  }
48521
- await this.sandbox.kill();
48522
- this.sandbox = undefined;
48565
+ const existing = await this.getSandboxBySessionId();
48566
+ if (existing) {
48567
+ await this.killSandboxById(existing.id);
48568
+ if (existing.id === this._id) {
48569
+ this.sandbox = undefined;
48570
+ }
48571
+ }
48523
48572
  this._status = { state: "UnExist" };
48524
48573
  } catch (error) {
48525
48574
  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.2",
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",