@fastgpt-sdk/sandbox-adapter 0.0.40-beta.4 → 0.0.40-beta.5
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,4 +1,10 @@
|
|
|
1
1
|
import { type DevboxApiConfig, type DevboxApiResponse, type DevboxCreateRequest, type DevboxInfoData, type DevboxMutationData, type DownloadFileParams, type ExecRequest, type ExecResponseData, type UploadFileParams, type UploadResponseData } from './type';
|
|
2
|
+
export declare class DevboxApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly rawBody: string;
|
|
5
|
+
readonly url: string;
|
|
6
|
+
constructor(message: string, status: number, rawBody: string, url: string);
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* HTTP client for the Sealos Devbox REST API.
|
|
4
10
|
*
|
|
@@ -38,6 +38,13 @@ export declare class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
38
38
|
private removeUndefined;
|
|
39
39
|
private assertMutationSuccess;
|
|
40
40
|
private isNotFoundResponse;
|
|
41
|
+
private isRetryableGetInfoError;
|
|
42
|
+
/**
|
|
43
|
+
* Devbox gateway can briefly return 502/503/504 during restart before the sandbox
|
|
44
|
+
* status is readable. Limit retry to the initial info probe to avoid repeating
|
|
45
|
+
* lifecycle mutations such as create/resume/delete.
|
|
46
|
+
*/
|
|
47
|
+
private getInfoWithProviderRetry;
|
|
41
48
|
getInfo(): Promise<SandboxInfo | null>;
|
|
42
49
|
ensureRunning(): Promise<void>;
|
|
43
50
|
create(): Promise<void>;
|
package/dist/index.cjs
CHANGED
|
@@ -45625,6 +45625,20 @@ class BaseSandboxAdapter {
|
|
|
45625
45625
|
}
|
|
45626
45626
|
|
|
45627
45627
|
// src/adapters/SealosDevboxAdapter/api.ts
|
|
45628
|
+
class DevboxApiError extends Error {
|
|
45629
|
+
status;
|
|
45630
|
+
rawBody;
|
|
45631
|
+
url;
|
|
45632
|
+
constructor(message, status, rawBody, url) {
|
|
45633
|
+
super(message);
|
|
45634
|
+
this.status = status;
|
|
45635
|
+
this.rawBody = rawBody;
|
|
45636
|
+
this.url = url;
|
|
45637
|
+
this.name = "DevboxApiError";
|
|
45638
|
+
Object.setPrototypeOf(this, DevboxApiError.prototype);
|
|
45639
|
+
}
|
|
45640
|
+
}
|
|
45641
|
+
|
|
45628
45642
|
class DevboxApi {
|
|
45629
45643
|
baseUrl;
|
|
45630
45644
|
token;
|
|
@@ -45648,7 +45662,13 @@ class DevboxApi {
|
|
|
45648
45662
|
headers.set("Content-Type", "application/json");
|
|
45649
45663
|
}
|
|
45650
45664
|
const res = await fetch(input, { ...init, headers });
|
|
45651
|
-
const
|
|
45665
|
+
const rawBody = typeof res.text === "function" ? await res.text() : JSON.stringify(await res.json());
|
|
45666
|
+
let result;
|
|
45667
|
+
try {
|
|
45668
|
+
result = JSON.parse(rawBody);
|
|
45669
|
+
} catch {
|
|
45670
|
+
throw new DevboxApiError(`Devbox API returned non-JSON response (${res.status}): ${rawBody || res.statusText || res.status}`, res.status, rawBody, input);
|
|
45671
|
+
}
|
|
45652
45672
|
return {
|
|
45653
45673
|
...result,
|
|
45654
45674
|
code: result.code ?? res.status
|
|
@@ -45762,6 +45782,9 @@ function joinUrlPath(url, path) {
|
|
|
45762
45782
|
}
|
|
45763
45783
|
|
|
45764
45784
|
// src/adapters/SealosDevboxAdapter/index.ts
|
|
45785
|
+
var GET_INFO_RETRY_TIMEOUT_MS = 30000;
|
|
45786
|
+
var GET_INFO_RETRY_INTERVAL_MS = 1000;
|
|
45787
|
+
|
|
45765
45788
|
class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
45766
45789
|
config;
|
|
45767
45790
|
createConfig;
|
|
@@ -45832,6 +45855,33 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
45832
45855
|
isNotFoundResponse(res) {
|
|
45833
45856
|
return res.code === 404 || String(res.message ?? "").toLowerCase().includes("not found");
|
|
45834
45857
|
}
|
|
45858
|
+
isRetryableGetInfoError(error) {
|
|
45859
|
+
let current = error;
|
|
45860
|
+
while (current instanceof Error) {
|
|
45861
|
+
if (current instanceof DevboxApiError) {
|
|
45862
|
+
const rawBody = current.rawBody.toLowerCase();
|
|
45863
|
+
return [502, 503, 504].includes(current.status) || rawBody.includes("no healthy upstream");
|
|
45864
|
+
}
|
|
45865
|
+
current = current.cause;
|
|
45866
|
+
}
|
|
45867
|
+
return false;
|
|
45868
|
+
}
|
|
45869
|
+
async getInfoWithProviderRetry(timeoutMs = GET_INFO_RETRY_TIMEOUT_MS, intervalMs = GET_INFO_RETRY_INTERVAL_MS) {
|
|
45870
|
+
const startTime = Date.now();
|
|
45871
|
+
let lastError;
|
|
45872
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
45873
|
+
try {
|
|
45874
|
+
return await this.getInfo();
|
|
45875
|
+
} catch (error) {
|
|
45876
|
+
lastError = error;
|
|
45877
|
+
if (!this.isRetryableGetInfoError(error)) {
|
|
45878
|
+
throw error;
|
|
45879
|
+
}
|
|
45880
|
+
await this.sleep(intervalMs);
|
|
45881
|
+
}
|
|
45882
|
+
}
|
|
45883
|
+
throw lastError;
|
|
45884
|
+
}
|
|
45835
45885
|
async getInfo() {
|
|
45836
45886
|
try {
|
|
45837
45887
|
const res = await this.api.info(this._id);
|
|
@@ -45858,7 +45908,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
45858
45908
|
}
|
|
45859
45909
|
async ensureRunning() {
|
|
45860
45910
|
try {
|
|
45861
|
-
const sandbox = await this.
|
|
45911
|
+
const sandbox = await this.getInfoWithProviderRetry();
|
|
45862
45912
|
if (sandbox) {
|
|
45863
45913
|
const status = sandbox.status.state;
|
|
45864
45914
|
switch (status) {
|
package/dist/index.js
CHANGED
|
@@ -45609,6 +45609,20 @@ class BaseSandboxAdapter {
|
|
|
45609
45609
|
}
|
|
45610
45610
|
|
|
45611
45611
|
// src/adapters/SealosDevboxAdapter/api.ts
|
|
45612
|
+
class DevboxApiError extends Error {
|
|
45613
|
+
status;
|
|
45614
|
+
rawBody;
|
|
45615
|
+
url;
|
|
45616
|
+
constructor(message, status, rawBody, url) {
|
|
45617
|
+
super(message);
|
|
45618
|
+
this.status = status;
|
|
45619
|
+
this.rawBody = rawBody;
|
|
45620
|
+
this.url = url;
|
|
45621
|
+
this.name = "DevboxApiError";
|
|
45622
|
+
Object.setPrototypeOf(this, DevboxApiError.prototype);
|
|
45623
|
+
}
|
|
45624
|
+
}
|
|
45625
|
+
|
|
45612
45626
|
class DevboxApi {
|
|
45613
45627
|
baseUrl;
|
|
45614
45628
|
token;
|
|
@@ -45632,7 +45646,13 @@ class DevboxApi {
|
|
|
45632
45646
|
headers.set("Content-Type", "application/json");
|
|
45633
45647
|
}
|
|
45634
45648
|
const res = await fetch(input, { ...init, headers });
|
|
45635
|
-
const
|
|
45649
|
+
const rawBody = typeof res.text === "function" ? await res.text() : JSON.stringify(await res.json());
|
|
45650
|
+
let result;
|
|
45651
|
+
try {
|
|
45652
|
+
result = JSON.parse(rawBody);
|
|
45653
|
+
} catch {
|
|
45654
|
+
throw new DevboxApiError(`Devbox API returned non-JSON response (${res.status}): ${rawBody || res.statusText || res.status}`, res.status, rawBody, input);
|
|
45655
|
+
}
|
|
45636
45656
|
return {
|
|
45637
45657
|
...result,
|
|
45638
45658
|
code: result.code ?? res.status
|
|
@@ -45746,6 +45766,9 @@ function joinUrlPath(url, path) {
|
|
|
45746
45766
|
}
|
|
45747
45767
|
|
|
45748
45768
|
// src/adapters/SealosDevboxAdapter/index.ts
|
|
45769
|
+
var GET_INFO_RETRY_TIMEOUT_MS = 30000;
|
|
45770
|
+
var GET_INFO_RETRY_INTERVAL_MS = 1000;
|
|
45771
|
+
|
|
45749
45772
|
class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
45750
45773
|
config;
|
|
45751
45774
|
createConfig;
|
|
@@ -45816,6 +45839,33 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
45816
45839
|
isNotFoundResponse(res) {
|
|
45817
45840
|
return res.code === 404 || String(res.message ?? "").toLowerCase().includes("not found");
|
|
45818
45841
|
}
|
|
45842
|
+
isRetryableGetInfoError(error) {
|
|
45843
|
+
let current = error;
|
|
45844
|
+
while (current instanceof Error) {
|
|
45845
|
+
if (current instanceof DevboxApiError) {
|
|
45846
|
+
const rawBody = current.rawBody.toLowerCase();
|
|
45847
|
+
return [502, 503, 504].includes(current.status) || rawBody.includes("no healthy upstream");
|
|
45848
|
+
}
|
|
45849
|
+
current = current.cause;
|
|
45850
|
+
}
|
|
45851
|
+
return false;
|
|
45852
|
+
}
|
|
45853
|
+
async getInfoWithProviderRetry(timeoutMs = GET_INFO_RETRY_TIMEOUT_MS, intervalMs = GET_INFO_RETRY_INTERVAL_MS) {
|
|
45854
|
+
const startTime = Date.now();
|
|
45855
|
+
let lastError;
|
|
45856
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
45857
|
+
try {
|
|
45858
|
+
return await this.getInfo();
|
|
45859
|
+
} catch (error) {
|
|
45860
|
+
lastError = error;
|
|
45861
|
+
if (!this.isRetryableGetInfoError(error)) {
|
|
45862
|
+
throw error;
|
|
45863
|
+
}
|
|
45864
|
+
await this.sleep(intervalMs);
|
|
45865
|
+
}
|
|
45866
|
+
}
|
|
45867
|
+
throw lastError;
|
|
45868
|
+
}
|
|
45819
45869
|
async getInfo() {
|
|
45820
45870
|
try {
|
|
45821
45871
|
const res = await this.api.info(this._id);
|
|
@@ -45842,7 +45892,7 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
|
|
|
45842
45892
|
}
|
|
45843
45893
|
async ensureRunning() {
|
|
45844
45894
|
try {
|
|
45845
|
-
const sandbox = await this.
|
|
45895
|
+
const sandbox = await this.getInfoWithProviderRetry();
|
|
45846
45896
|
if (sandbox) {
|
|
45847
45897
|
const status = sandbox.status.state;
|
|
45848
45898
|
switch (status) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fastgpt-sdk/sandbox-adapter",
|
|
3
|
-
"version": "0.0.40-beta.
|
|
3
|
+
"version": "0.0.40-beta.5",
|
|
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",
|