computesdk 2.5.3 → 2.6.0
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.
- package/README.md +92 -84
- package/dist/index.d.mts +103 -419
- package/dist/index.d.ts +103 -419
- package/dist/index.js +281 -990
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +280 -971
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,34 +22,16 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
CommandExitError: () => CommandExitError,
|
|
24
24
|
FileWatcher: () => FileWatcher,
|
|
25
|
-
GatewaySandbox: () => Sandbox,
|
|
26
25
|
MessageType: () => MessageType,
|
|
27
|
-
PROVIDER_AUTH: () => PROVIDER_AUTH,
|
|
28
|
-
PROVIDER_DASHBOARD_URLS: () => PROVIDER_DASHBOARD_URLS,
|
|
29
|
-
PROVIDER_ENV_MAP: () => PROVIDER_ENV_MAP,
|
|
30
|
-
PROVIDER_ENV_VARS: () => PROVIDER_ENV_VARS,
|
|
31
|
-
PROVIDER_HEADERS: () => PROVIDER_HEADERS,
|
|
32
|
-
PROVIDER_NAMES: () => PROVIDER_NAMES,
|
|
33
|
-
PROVIDER_PRIORITY: () => PROVIDER_PRIORITY,
|
|
34
26
|
Sandbox: () => Sandbox,
|
|
35
27
|
SignalService: () => SignalService,
|
|
36
|
-
TRIBUTARY_URL: () => TRIBUTARY_URL,
|
|
37
28
|
TerminalInstance: () => TerminalInstance,
|
|
38
|
-
autoConfigureCompute: () => autoConfigureCompute,
|
|
39
|
-
buildProviderHeaders: () => buildProviderHeaders,
|
|
40
29
|
buildSetupPayload: () => buildSetupPayload,
|
|
41
30
|
compute: () => compute,
|
|
42
31
|
decodeBinaryMessage: () => decodeBinaryMessage,
|
|
43
|
-
detectProvider: () => detectProvider,
|
|
44
32
|
encodeBinaryMessage: () => encodeBinaryMessage,
|
|
45
33
|
encodeSetupPayload: () => encodeSetupPayload,
|
|
46
|
-
|
|
47
|
-
getProviderConfigFromEnv: () => getProviderConfigFromEnv,
|
|
48
|
-
getProviderHeaders: () => getProviderHeaders,
|
|
49
|
-
isCommandExitError: () => isCommandExitError,
|
|
50
|
-
isGatewayModeEnabled: () => isGatewayModeEnabled,
|
|
51
|
-
isProviderAuthComplete: () => isProviderAuthComplete,
|
|
52
|
-
isValidProvider: () => isValidProvider
|
|
34
|
+
isCommandExitError: () => isCommandExitError
|
|
53
35
|
});
|
|
54
36
|
module.exports = __toCommonJS(index_exports);
|
|
55
37
|
|
|
@@ -3546,16 +3528,15 @@ API request failed (${response.status}): ${error}`
|
|
|
3546
3528
|
const parts = url.hostname.split(".");
|
|
3547
3529
|
const subdomain = parts[0];
|
|
3548
3530
|
const baseDomain = parts.slice(1).join(".");
|
|
3549
|
-
|
|
3550
|
-
return `${protocol}://${subdomain}-${options.port}.${previewDomain}`;
|
|
3531
|
+
return `${protocol}://${subdomain}-${options.port}.${baseDomain}`;
|
|
3551
3532
|
}
|
|
3552
3533
|
/**
|
|
3553
3534
|
* Get provider instance
|
|
3554
|
-
* Note: Not available
|
|
3535
|
+
* Note: Not available on direct Sandbox client instances
|
|
3555
3536
|
*/
|
|
3556
3537
|
getProvider() {
|
|
3557
3538
|
throw new Error(
|
|
3558
|
-
"getProvider() is not available on Sandbox. This method is only available
|
|
3539
|
+
"getProvider() is not available on Sandbox. This method is only available on provider SDK sandbox wrappers."
|
|
3559
3540
|
);
|
|
3560
3541
|
}
|
|
3561
3542
|
/**
|
|
@@ -3568,7 +3549,7 @@ API request failed (${response.status}): ${error}`
|
|
|
3568
3549
|
/**
|
|
3569
3550
|
* Destroy the sandbox (Sandbox interface method)
|
|
3570
3551
|
*
|
|
3571
|
-
* If a destroyHandler was provided
|
|
3552
|
+
* If a destroyHandler was provided, calls it to destroy
|
|
3572
3553
|
* the sandbox on the backend. Otherwise, only disconnects the WebSocket.
|
|
3573
3554
|
*/
|
|
3574
3555
|
async destroy() {
|
|
@@ -3629,1003 +3610,331 @@ var encodeSetupPayload = (options) => {
|
|
|
3629
3610
|
return encodeBase64(JSON.stringify(payload));
|
|
3630
3611
|
};
|
|
3631
3612
|
|
|
3632
|
-
// src/
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
daytona: [["DAYTONA_API_KEY"]],
|
|
3639
|
-
vercel: [
|
|
3640
|
-
["VERCEL_OIDC_TOKEN"],
|
|
3641
|
-
["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"]
|
|
3642
|
-
],
|
|
3643
|
-
runloop: [["RUNLOOP_API_KEY"]],
|
|
3644
|
-
cloudflare: [
|
|
3645
|
-
["CLOUDFLARE_SANDBOX_URL", "CLOUDFLARE_SANDBOX_SECRET"],
|
|
3646
|
-
["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"]
|
|
3647
|
-
],
|
|
3648
|
-
codesandbox: [["CSB_API_KEY"]],
|
|
3649
|
-
blaxel: [["BL_API_KEY", "BL_WORKSPACE"]],
|
|
3650
|
-
namespace: [["NSC_TOKEN"], ["NSC_TOKEN_FILE"]],
|
|
3651
|
-
hopx: [["HOPX_API_KEY"]],
|
|
3652
|
-
beam: [["BEAM_TOKEN", "BEAM_WORKSPACE_ID"]],
|
|
3653
|
-
sprites: [["SPRITES_TOKEN"]],
|
|
3654
|
-
freestyle: [["FREESTYLE_API_KEY"]],
|
|
3655
|
-
upstash: [["UPSTASH_BOX_API_KEY"]],
|
|
3656
|
-
"just-bash": [[]],
|
|
3657
|
-
"secure-exec": [[]]
|
|
3658
|
-
};
|
|
3659
|
-
var PROVIDER_NAMES = Object.keys(PROVIDER_AUTH);
|
|
3660
|
-
var PROVIDER_HEADERS = {
|
|
3661
|
-
e2b: {
|
|
3662
|
-
apiKey: "X-E2B-API-Key"
|
|
3663
|
-
},
|
|
3664
|
-
modal: {
|
|
3665
|
-
tokenId: "X-Modal-Token-Id",
|
|
3666
|
-
tokenSecret: "X-Modal-Token-Secret"
|
|
3667
|
-
},
|
|
3668
|
-
railway: {
|
|
3669
|
-
apiToken: "X-Railway-API-Key",
|
|
3670
|
-
projectId: "X-Railway-Project-ID",
|
|
3671
|
-
environmentId: "X-Railway-Environment-ID"
|
|
3672
|
-
},
|
|
3673
|
-
render: {
|
|
3674
|
-
apiKey: "X-Render-API-Key",
|
|
3675
|
-
ownerId: "X-Render-Owner-ID"
|
|
3676
|
-
},
|
|
3677
|
-
daytona: {
|
|
3678
|
-
apiKey: "X-Daytona-API-Key"
|
|
3679
|
-
},
|
|
3680
|
-
vercel: {
|
|
3681
|
-
oidcToken: "X-Vercel-OIDC-Token",
|
|
3682
|
-
token: "X-Vercel-Token",
|
|
3683
|
-
teamId: "X-Vercel-Team-Id",
|
|
3684
|
-
projectId: "X-Vercel-Project-Id"
|
|
3685
|
-
},
|
|
3686
|
-
runloop: {
|
|
3687
|
-
apiKey: "X-Runloop-API-Key"
|
|
3688
|
-
},
|
|
3689
|
-
cloudflare: {
|
|
3690
|
-
sandboxUrl: "X-Cloudflare-Sandbox-Url",
|
|
3691
|
-
sandboxSecret: "X-Cloudflare-Sandbox-Secret",
|
|
3692
|
-
apiToken: "X-Cloudflare-API-Token",
|
|
3693
|
-
accountId: "X-Cloudflare-Account-Id"
|
|
3694
|
-
},
|
|
3695
|
-
codesandbox: {
|
|
3696
|
-
apiKey: "X-CODESANDBOX-API-Key"
|
|
3697
|
-
},
|
|
3698
|
-
blaxel: {
|
|
3699
|
-
apiKey: "X-Blaxel-API-Key",
|
|
3700
|
-
workspace: "X-Blaxel-Workspace"
|
|
3701
|
-
},
|
|
3702
|
-
namespace: {
|
|
3703
|
-
token: "X-Namespace-Token"
|
|
3704
|
-
},
|
|
3705
|
-
hopx: {
|
|
3706
|
-
apiKey: "X-HOPX-API-Key"
|
|
3707
|
-
},
|
|
3708
|
-
beam: {
|
|
3709
|
-
token: "X-Beam-Token",
|
|
3710
|
-
workspaceId: "X-Beam-Workspace-Id"
|
|
3711
|
-
},
|
|
3712
|
-
sprites: {
|
|
3713
|
-
apiKey: "X-Sprites-Token"
|
|
3714
|
-
},
|
|
3715
|
-
freestyle: {
|
|
3716
|
-
apiKey: "X-Freestyle-API-Key"
|
|
3717
|
-
},
|
|
3718
|
-
upstash: {
|
|
3719
|
-
apiKey: "X-Upstash-Box-API-Key"
|
|
3720
|
-
},
|
|
3721
|
-
"just-bash": {},
|
|
3722
|
-
"secure-exec": {}
|
|
3723
|
-
};
|
|
3724
|
-
var PROVIDER_ENV_MAP = {
|
|
3725
|
-
e2b: {
|
|
3726
|
-
E2B_API_KEY: "apiKey"
|
|
3727
|
-
},
|
|
3728
|
-
modal: {
|
|
3729
|
-
MODAL_TOKEN_ID: "tokenId",
|
|
3730
|
-
MODAL_TOKEN_SECRET: "tokenSecret"
|
|
3731
|
-
},
|
|
3732
|
-
railway: {
|
|
3733
|
-
RAILWAY_API_KEY: "apiToken",
|
|
3734
|
-
RAILWAY_PROJECT_ID: "projectId",
|
|
3735
|
-
RAILWAY_ENVIRONMENT_ID: "environmentId"
|
|
3736
|
-
},
|
|
3737
|
-
render: {
|
|
3738
|
-
RENDER_API_KEY: "apiKey",
|
|
3739
|
-
RENDER_OWNER_ID: "ownerId"
|
|
3740
|
-
},
|
|
3741
|
-
daytona: {
|
|
3742
|
-
DAYTONA_API_KEY: "apiKey"
|
|
3743
|
-
},
|
|
3744
|
-
vercel: {
|
|
3745
|
-
VERCEL_OIDC_TOKEN: "oidcToken",
|
|
3746
|
-
VERCEL_TOKEN: "token",
|
|
3747
|
-
VERCEL_TEAM_ID: "teamId",
|
|
3748
|
-
VERCEL_PROJECT_ID: "projectId"
|
|
3749
|
-
},
|
|
3750
|
-
runloop: {
|
|
3751
|
-
RUNLOOP_API_KEY: "apiKey"
|
|
3752
|
-
},
|
|
3753
|
-
cloudflare: {
|
|
3754
|
-
CLOUDFLARE_SANDBOX_URL: "sandboxUrl",
|
|
3755
|
-
CLOUDFLARE_SANDBOX_SECRET: "sandboxSecret",
|
|
3756
|
-
CLOUDFLARE_API_TOKEN: "apiToken",
|
|
3757
|
-
CLOUDFLARE_ACCOUNT_ID: "accountId"
|
|
3758
|
-
},
|
|
3759
|
-
codesandbox: {
|
|
3760
|
-
CSB_API_KEY: "apiKey"
|
|
3761
|
-
},
|
|
3762
|
-
blaxel: {
|
|
3763
|
-
BL_API_KEY: "apiKey",
|
|
3764
|
-
BL_WORKSPACE: "workspace"
|
|
3765
|
-
},
|
|
3766
|
-
namespace: {
|
|
3767
|
-
NSC_TOKEN: "token",
|
|
3768
|
-
NSC_TOKEN_FILE: "tokenFile"
|
|
3769
|
-
},
|
|
3770
|
-
hopx: {
|
|
3771
|
-
HOPX_API_KEY: "apiKey"
|
|
3772
|
-
},
|
|
3773
|
-
beam: {
|
|
3774
|
-
BEAM_TOKEN: "token",
|
|
3775
|
-
BEAM_WORKSPACE_ID: "workspaceId"
|
|
3776
|
-
},
|
|
3777
|
-
sprites: {
|
|
3778
|
-
SPRITES_TOKEN: "apiKey"
|
|
3779
|
-
},
|
|
3780
|
-
freestyle: {
|
|
3781
|
-
FREESTYLE_API_KEY: "apiKey"
|
|
3782
|
-
},
|
|
3783
|
-
upstash: {
|
|
3784
|
-
UPSTASH_BOX_API_KEY: "apiKey"
|
|
3785
|
-
},
|
|
3786
|
-
"just-bash": {},
|
|
3787
|
-
"secure-exec": {}
|
|
3788
|
-
};
|
|
3789
|
-
var PROVIDER_DASHBOARD_URLS = {
|
|
3790
|
-
e2b: "https://e2b.dev/dashboard",
|
|
3791
|
-
modal: "https://modal.com/settings",
|
|
3792
|
-
railway: "https://railway.app/account/tokens",
|
|
3793
|
-
render: "https://dashboard.render.com/account",
|
|
3794
|
-
daytona: "https://daytona.io/dashboard",
|
|
3795
|
-
vercel: "https://vercel.com/account/tokens",
|
|
3796
|
-
runloop: "https://runloop.ai/dashboard",
|
|
3797
|
-
cloudflare: "https://dash.cloudflare.com/profile/api-tokens",
|
|
3798
|
-
codesandbox: "https://codesandbox.io/dashboard/settings",
|
|
3799
|
-
blaxel: "https://blaxel.ai/dashboard",
|
|
3800
|
-
namespace: "https://cloud.namespace.so",
|
|
3801
|
-
hopx: "https://hopx.ai/dashboard",
|
|
3802
|
-
beam: "https://app.beam.cloud",
|
|
3803
|
-
sprites: "https://sprites.dev",
|
|
3804
|
-
freestyle: "https://dash.freestyle.sh",
|
|
3805
|
-
upstash: "https://console.upstash.com",
|
|
3806
|
-
"just-bash": "https://github.com/vercel-labs/just-bash",
|
|
3807
|
-
"secure-exec": "https://github.com/anomalyco/secure-exec"
|
|
3808
|
-
};
|
|
3809
|
-
function isValidProvider(name) {
|
|
3810
|
-
return name in PROVIDER_AUTH;
|
|
3811
|
-
}
|
|
3812
|
-
function buildProviderHeaders(provider, config) {
|
|
3813
|
-
const headers = {};
|
|
3814
|
-
const headerMap = PROVIDER_HEADERS[provider];
|
|
3815
|
-
for (const [configKey, headerName] of Object.entries(headerMap)) {
|
|
3816
|
-
const value = config[configKey];
|
|
3817
|
-
if (value) {
|
|
3818
|
-
headers[headerName] = value;
|
|
3819
|
-
}
|
|
3820
|
-
}
|
|
3821
|
-
return headers;
|
|
3822
|
-
}
|
|
3823
|
-
function getProviderConfigFromEnv(provider) {
|
|
3824
|
-
const config = {};
|
|
3825
|
-
const envMap = PROVIDER_ENV_MAP[provider];
|
|
3826
|
-
for (const [envVar, configKey] of Object.entries(envMap)) {
|
|
3827
|
-
const value = process.env[envVar];
|
|
3828
|
-
if (value) {
|
|
3829
|
-
config[configKey] = value;
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
return config;
|
|
3833
|
-
}
|
|
3834
|
-
function isProviderAuthComplete(provider) {
|
|
3835
|
-
const authOptions = PROVIDER_AUTH[provider];
|
|
3836
|
-
for (const option of authOptions) {
|
|
3837
|
-
const allPresent = option.every((envVar) => !!process.env[envVar]);
|
|
3838
|
-
if (allPresent) return true;
|
|
3839
|
-
}
|
|
3840
|
-
return false;
|
|
3841
|
-
}
|
|
3842
|
-
function getMissingEnvVars(provider) {
|
|
3843
|
-
const authOptions = PROVIDER_AUTH[provider];
|
|
3844
|
-
let bestOption = null;
|
|
3845
|
-
for (const option of authOptions) {
|
|
3846
|
-
const missing = [];
|
|
3847
|
-
let presentCount = 0;
|
|
3848
|
-
for (const envVar of option) {
|
|
3849
|
-
if (process.env[envVar]) {
|
|
3850
|
-
presentCount++;
|
|
3851
|
-
} else {
|
|
3852
|
-
missing.push(envVar);
|
|
3853
|
-
}
|
|
3854
|
-
}
|
|
3855
|
-
if (missing.length === 0) return [];
|
|
3856
|
-
if (!bestOption || presentCount > bestOption.presentCount) {
|
|
3857
|
-
bestOption = { presentCount, missing };
|
|
3858
|
-
}
|
|
3859
|
-
}
|
|
3860
|
-
return bestOption?.missing ?? [];
|
|
3861
|
-
}
|
|
3862
|
-
|
|
3863
|
-
// src/constants.ts
|
|
3864
|
-
var TRIBUTARY_URL = "https://tributary.edge.computesdk.com";
|
|
3865
|
-
var PROVIDER_PRIORITY = [
|
|
3866
|
-
"e2b",
|
|
3867
|
-
"railway",
|
|
3868
|
-
"render",
|
|
3869
|
-
"daytona",
|
|
3870
|
-
"modal",
|
|
3871
|
-
"runloop",
|
|
3872
|
-
"vercel",
|
|
3873
|
-
"cloudflare",
|
|
3874
|
-
"codesandbox",
|
|
3875
|
-
"blaxel",
|
|
3876
|
-
"namespace",
|
|
3877
|
-
"hopx",
|
|
3878
|
-
"beam",
|
|
3879
|
-
"sprites",
|
|
3880
|
-
"freestyle",
|
|
3881
|
-
"upstash",
|
|
3882
|
-
"secure-exec"
|
|
3883
|
-
];
|
|
3884
|
-
var PROVIDER_ENV_VARS = {
|
|
3885
|
-
e2b: ["E2B_API_KEY"],
|
|
3886
|
-
railway: ["RAILWAY_API_KEY", "RAILWAY_PROJECT_ID", "RAILWAY_ENVIRONMENT_ID"],
|
|
3887
|
-
render: ["RENDER_API_KEY", "RENDER_OWNER_ID"],
|
|
3888
|
-
daytona: ["DAYTONA_API_KEY"],
|
|
3889
|
-
modal: ["MODAL_TOKEN_ID", "MODAL_TOKEN_SECRET"],
|
|
3890
|
-
runloop: ["RUNLOOP_API_KEY"],
|
|
3891
|
-
vercel: ["VERCEL_TOKEN", "VERCEL_TEAM_ID", "VERCEL_PROJECT_ID"],
|
|
3892
|
-
cloudflare: ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"],
|
|
3893
|
-
codesandbox: ["CSB_API_KEY"],
|
|
3894
|
-
blaxel: ["BL_API_KEY", "BL_WORKSPACE"],
|
|
3895
|
-
namespace: ["NSC_TOKEN"],
|
|
3896
|
-
hopx: ["HOPX_API_KEY"],
|
|
3897
|
-
beam: ["BEAM_TOKEN", "BEAM_WORKSPACE_ID"],
|
|
3898
|
-
sprites: ["SPRITES_TOKEN"],
|
|
3899
|
-
freestyle: ["FREESTYLE_API_KEY"],
|
|
3900
|
-
upstash: ["UPSTASH_BOX_API_KEY"],
|
|
3901
|
-
"just-bash": [],
|
|
3902
|
-
"secure-exec": []
|
|
3903
|
-
};
|
|
3904
|
-
|
|
3905
|
-
// src/auto-detect.ts
|
|
3906
|
-
function isGatewayModeEnabled() {
|
|
3907
|
-
return !!(typeof process !== "undefined" && process.env?.COMPUTESDK_API_KEY);
|
|
3908
|
-
}
|
|
3909
|
-
function hasProviderEnv(provider) {
|
|
3910
|
-
if (typeof process === "undefined") return false;
|
|
3911
|
-
const requiredVars = PROVIDER_ENV_VARS[provider];
|
|
3912
|
-
if (!requiredVars || requiredVars.length === 0) return false;
|
|
3913
|
-
return requiredVars.every((varName) => !!process.env?.[varName]);
|
|
3914
|
-
}
|
|
3915
|
-
function getProviderEnvStatus(provider) {
|
|
3916
|
-
const requiredVars = PROVIDER_ENV_VARS[provider];
|
|
3917
|
-
if (typeof process === "undefined" || !requiredVars) {
|
|
3918
|
-
return { provider, present: [], missing: requiredVars ? [...requiredVars] : [], isComplete: false };
|
|
3919
|
-
}
|
|
3920
|
-
const present = requiredVars.filter((varName) => !!process.env?.[varName]);
|
|
3921
|
-
const missing = requiredVars.filter((varName) => !process.env?.[varName]);
|
|
3922
|
-
return {
|
|
3923
|
-
provider,
|
|
3924
|
-
present: [...present],
|
|
3925
|
-
missing: [...missing],
|
|
3926
|
-
isComplete: missing.length === 0
|
|
3927
|
-
};
|
|
3928
|
-
}
|
|
3929
|
-
function detectProvider() {
|
|
3930
|
-
if (typeof process === "undefined") return null;
|
|
3931
|
-
const explicit = process.env.COMPUTESDK_PROVIDER?.toLowerCase();
|
|
3932
|
-
if (explicit && hasProviderEnv(explicit)) {
|
|
3933
|
-
return explicit;
|
|
3934
|
-
}
|
|
3935
|
-
if (explicit && !hasProviderEnv(explicit)) {
|
|
3936
|
-
console.warn(
|
|
3937
|
-
`\u26A0\uFE0F COMPUTESDK_PROVIDER is set to "${explicit}" but required credentials are missing.
|
|
3938
|
-
Required: ${PROVIDER_ENV_VARS[explicit]?.join(", ") || "unknown"}
|
|
3939
|
-
Falling back to auto-detection...`
|
|
3940
|
-
);
|
|
3941
|
-
}
|
|
3942
|
-
for (const provider of PROVIDER_PRIORITY) {
|
|
3943
|
-
if (hasProviderEnv(provider)) {
|
|
3944
|
-
return provider;
|
|
3945
|
-
}
|
|
3946
|
-
}
|
|
3947
|
-
return null;
|
|
3948
|
-
}
|
|
3949
|
-
function getProviderHeaders(provider) {
|
|
3950
|
-
if (typeof process === "undefined") return {};
|
|
3951
|
-
const headers = {};
|
|
3952
|
-
switch (provider) {
|
|
3953
|
-
case "e2b":
|
|
3954
|
-
if (process.env.E2B_API_KEY) {
|
|
3955
|
-
headers["X-E2B-API-Key"] = process.env.E2B_API_KEY;
|
|
3956
|
-
}
|
|
3957
|
-
break;
|
|
3958
|
-
case "railway":
|
|
3959
|
-
if (process.env.RAILWAY_API_KEY) {
|
|
3960
|
-
headers["X-Railway-API-Key"] = process.env.RAILWAY_API_KEY;
|
|
3961
|
-
}
|
|
3962
|
-
if (process.env.RAILWAY_PROJECT_ID) {
|
|
3963
|
-
headers["X-Railway-Project-ID"] = process.env.RAILWAY_PROJECT_ID;
|
|
3964
|
-
}
|
|
3965
|
-
if (process.env.RAILWAY_ENVIRONMENT_ID) {
|
|
3966
|
-
headers["X-Railway-Environment-ID"] = process.env.RAILWAY_ENVIRONMENT_ID;
|
|
3967
|
-
}
|
|
3968
|
-
break;
|
|
3969
|
-
case "daytona":
|
|
3970
|
-
if (process.env.DAYTONA_API_KEY) {
|
|
3971
|
-
headers["X-Daytona-API-Key"] = process.env.DAYTONA_API_KEY;
|
|
3972
|
-
}
|
|
3973
|
-
break;
|
|
3974
|
-
case "modal":
|
|
3975
|
-
if (process.env.MODAL_TOKEN_ID) {
|
|
3976
|
-
headers["X-Modal-Token-ID"] = process.env.MODAL_TOKEN_ID;
|
|
3977
|
-
}
|
|
3978
|
-
if (process.env.MODAL_TOKEN_SECRET) {
|
|
3979
|
-
headers["X-Modal-Token-Secret"] = process.env.MODAL_TOKEN_SECRET;
|
|
3980
|
-
}
|
|
3981
|
-
break;
|
|
3982
|
-
case "runloop":
|
|
3983
|
-
if (process.env.RUNLOOP_API_KEY) {
|
|
3984
|
-
headers["X-Runloop-API-Key"] = process.env.RUNLOOP_API_KEY;
|
|
3985
|
-
}
|
|
3986
|
-
break;
|
|
3987
|
-
case "vercel":
|
|
3988
|
-
if (process.env.VERCEL_TOKEN) {
|
|
3989
|
-
headers["X-Vercel-Token"] = process.env.VERCEL_TOKEN;
|
|
3990
|
-
}
|
|
3991
|
-
if (process.env.VERCEL_TEAM_ID) {
|
|
3992
|
-
headers["X-Vercel-Team-ID"] = process.env.VERCEL_TEAM_ID;
|
|
3993
|
-
}
|
|
3994
|
-
if (process.env.VERCEL_PROJECT_ID) {
|
|
3995
|
-
headers["X-Vercel-Project-ID"] = process.env.VERCEL_PROJECT_ID;
|
|
3996
|
-
}
|
|
3997
|
-
break;
|
|
3998
|
-
case "cloudflare":
|
|
3999
|
-
if (process.env.CLOUDFLARE_API_TOKEN) {
|
|
4000
|
-
headers["X-Cloudflare-API-Token"] = process.env.CLOUDFLARE_API_TOKEN;
|
|
4001
|
-
}
|
|
4002
|
-
if (process.env.CLOUDFLARE_ACCOUNT_ID) {
|
|
4003
|
-
headers["X-Cloudflare-Account-ID"] = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
4004
|
-
}
|
|
4005
|
-
break;
|
|
4006
|
-
case "codesandbox":
|
|
4007
|
-
if (process.env.CSB_API_KEY) {
|
|
4008
|
-
headers["X-CodeSandbox-API-Key"] = process.env.CSB_API_KEY;
|
|
4009
|
-
}
|
|
4010
|
-
break;
|
|
4011
|
-
case "blaxel":
|
|
4012
|
-
if (process.env.BL_API_KEY) {
|
|
4013
|
-
headers["X-Blaxel-API-Key"] = process.env.BL_API_KEY;
|
|
4014
|
-
}
|
|
4015
|
-
if (process.env.BL_WORKSPACE) {
|
|
4016
|
-
headers["X-Blaxel-Workspace"] = process.env.BL_WORKSPACE;
|
|
4017
|
-
}
|
|
4018
|
-
break;
|
|
4019
|
-
case "namespace":
|
|
4020
|
-
if (process.env.NSC_TOKEN) {
|
|
4021
|
-
headers["X-Namespace-Token"] = process.env.NSC_TOKEN;
|
|
4022
|
-
}
|
|
4023
|
-
break;
|
|
4024
|
-
case "hopx":
|
|
4025
|
-
if (process.env.HOPX_API_KEY) {
|
|
4026
|
-
headers["X-HOPX-API-Key"] = process.env.HOPX_API_KEY;
|
|
4027
|
-
}
|
|
4028
|
-
break;
|
|
4029
|
-
case "render":
|
|
4030
|
-
if (process.env.RENDER_API_KEY) {
|
|
4031
|
-
headers["X-Render-API-Key"] = process.env.RENDER_API_KEY;
|
|
4032
|
-
}
|
|
4033
|
-
if (process.env.RENDER_OWNER_ID) {
|
|
4034
|
-
headers["X-Render-Owner-ID"] = process.env.RENDER_OWNER_ID;
|
|
4035
|
-
}
|
|
4036
|
-
break;
|
|
4037
|
-
case "beam":
|
|
4038
|
-
if (process.env.BEAM_TOKEN) {
|
|
4039
|
-
headers["X-Beam-Token"] = process.env.BEAM_TOKEN;
|
|
4040
|
-
}
|
|
4041
|
-
if (process.env.BEAM_WORKSPACE_ID) {
|
|
4042
|
-
headers["X-Beam-Workspace-Id"] = process.env.BEAM_WORKSPACE_ID;
|
|
4043
|
-
}
|
|
4044
|
-
break;
|
|
4045
|
-
case "sprites":
|
|
4046
|
-
if (process.env.SPRITES_TOKEN) {
|
|
4047
|
-
headers["X-Sprites-Token"] = process.env.SPRITES_TOKEN;
|
|
4048
|
-
}
|
|
4049
|
-
break;
|
|
4050
|
-
case "just-bash":
|
|
4051
|
-
break;
|
|
4052
|
-
case "secure-exec":
|
|
4053
|
-
break;
|
|
4054
|
-
case "upstash":
|
|
4055
|
-
if (process.env.UPSTASH_BOX_API_KEY) {
|
|
4056
|
-
headers["X-Upstash-Box-API-Key"] = process.env.UPSTASH_BOX_API_KEY;
|
|
4057
|
-
}
|
|
4058
|
-
break;
|
|
4059
|
-
}
|
|
4060
|
-
return headers;
|
|
3613
|
+
// src/compute.ts
|
|
3614
|
+
function isProviderLike(value) {
|
|
3615
|
+
if (!value || typeof value !== "object") return false;
|
|
3616
|
+
const candidate = value;
|
|
3617
|
+
const sandbox = candidate.sandbox;
|
|
3618
|
+
return !!(sandbox && typeof sandbox.create === "function" && typeof sandbox.getById === "function" && typeof sandbox.destroy === "function");
|
|
4061
3619
|
}
|
|
4062
|
-
function
|
|
4063
|
-
|
|
4064
|
-
return null;
|
|
4065
|
-
}
|
|
4066
|
-
const provider = detectProvider();
|
|
4067
|
-
if (!provider) {
|
|
4068
|
-
const detectionResults = PROVIDER_PRIORITY.map((p) => getProviderEnvStatus(p));
|
|
4069
|
-
const statusLines = detectionResults.map((result) => {
|
|
4070
|
-
const status = result.isComplete ? "\u2705" : result.present.length > 0 ? "\u26A0\uFE0F " : "\u274C";
|
|
4071
|
-
const ratio = `${result.present.length}/${result.present.length + result.missing.length}`;
|
|
4072
|
-
let line = ` ${status} ${result.provider.padEnd(12)} ${ratio} credentials`;
|
|
4073
|
-
if (result.present.length > 0 && result.missing.length > 0) {
|
|
4074
|
-
line += ` (missing: ${result.missing.join(", ")})`;
|
|
4075
|
-
}
|
|
4076
|
-
return line;
|
|
4077
|
-
});
|
|
4078
|
-
throw new Error(
|
|
4079
|
-
`COMPUTESDK_API_KEY is set but no provider detected.
|
|
4080
|
-
|
|
4081
|
-
Provider detection results:
|
|
4082
|
-
` + statusLines.join("\n") + `
|
|
4083
|
-
|
|
4084
|
-
To fix this, set one of the following:
|
|
4085
|
-
|
|
4086
|
-
E2B: export E2B_API_KEY=xxx
|
|
4087
|
-
Railway: export RAILWAY_API_KEY=xxx RAILWAY_PROJECT_ID=xxx RAILWAY_ENVIRONMENT_ID=xxx
|
|
4088
|
-
Daytona: export DAYTONA_API_KEY=xxx
|
|
4089
|
-
Modal: export MODAL_TOKEN_ID=xxx MODAL_TOKEN_SECRET=xxx
|
|
4090
|
-
Runloop: export RUNLOOP_API_KEY=xxx
|
|
4091
|
-
Vercel: export VERCEL_TOKEN=xxx VERCEL_TEAM_ID=xxx VERCEL_PROJECT_ID=xxx
|
|
4092
|
-
Cloudflare: export CLOUDFLARE_API_TOKEN=xxx CLOUDFLARE_ACCOUNT_ID=xxx
|
|
4093
|
-
CodeSandbox: export CSB_API_KEY=xxx
|
|
4094
|
-
Blaxel: export BL_API_KEY=xxx BL_WORKSPACE=xxx
|
|
4095
|
-
Namespace: export NSC_TOKEN=xxx
|
|
4096
|
-
HopX: export HOPX_API_KEY=xxx
|
|
4097
|
-
Render: export RENDER_API_KEY=xxx RENDER_OWNER_ID=xxx
|
|
4098
|
-
Beam: export BEAM_TOKEN=xxx BEAM_WORKSPACE_ID=xxx
|
|
4099
|
-
Sprites: export SPRITES_TOKEN=xxx
|
|
4100
|
-
Upstash: export UPSTASH_BOX_API_KEY=xxx
|
|
4101
|
-
just-bash: (no credentials needed - local sandbox)
|
|
4102
|
-
secure-exec: (no credentials needed - local sandbox)
|
|
4103
|
-
|
|
4104
|
-
Or set COMPUTESDK_PROVIDER to specify explicitly:
|
|
4105
|
-
export COMPUTESDK_PROVIDER=<provider>
|
|
4106
|
-
|
|
4107
|
-
Docs: https://computesdk.com/docs/quickstart`
|
|
4108
|
-
);
|
|
4109
|
-
}
|
|
4110
|
-
const gatewayUrl = process.env.COMPUTESDK_TRIBUTARY_URL || TRIBUTARY_URL;
|
|
4111
|
-
const computesdkApiKey = process.env.COMPUTESDK_API_KEY;
|
|
4112
|
-
const providerHeaders = getProviderHeaders(provider);
|
|
4113
|
-
try {
|
|
4114
|
-
new URL(gatewayUrl);
|
|
4115
|
-
} catch (error) {
|
|
4116
|
-
throw new Error(
|
|
4117
|
-
`Invalid gateway URL: "${gatewayUrl}"
|
|
4118
|
-
|
|
4119
|
-
The URL must be a valid HTTP/HTTPS URL.
|
|
4120
|
-
Check your COMPUTESDK_TRIBUTARY_URL environment variable.`
|
|
4121
|
-
);
|
|
4122
|
-
}
|
|
4123
|
-
if (process.env.COMPUTESDK_DEBUG) {
|
|
4124
|
-
console.log(`\u2728 ComputeSDK: Auto-detected ${provider} provider`);
|
|
4125
|
-
console.log(`\u{1F310} Gateway: ${gatewayUrl}`);
|
|
4126
|
-
console.log(`\u{1F511} Provider headers:`, Object.keys(providerHeaders).join(", "));
|
|
4127
|
-
}
|
|
4128
|
-
const config = {
|
|
4129
|
-
apiKey: computesdkApiKey,
|
|
4130
|
-
gatewayUrl,
|
|
4131
|
-
provider,
|
|
4132
|
-
providerHeaders
|
|
4133
|
-
};
|
|
4134
|
-
return config;
|
|
3620
|
+
function getProviderLabel(provider, index) {
|
|
3621
|
+
return provider.name || `provider-${index + 1}`;
|
|
4135
3622
|
}
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
const headers = {};
|
|
4140
|
-
const provider = config.provider;
|
|
4141
|
-
const headerMap = PROVIDER_HEADERS[provider];
|
|
4142
|
-
const providerConfig = config[provider];
|
|
4143
|
-
if (!providerConfig || !headerMap) return headers;
|
|
4144
|
-
for (const [configKey, headerName] of Object.entries(headerMap)) {
|
|
4145
|
-
const value = providerConfig[configKey];
|
|
4146
|
-
if (value) {
|
|
4147
|
-
headers[headerName] = value;
|
|
4148
|
-
}
|
|
3623
|
+
function getProviderErrorDetail(error) {
|
|
3624
|
+
if (error instanceof Error) {
|
|
3625
|
+
return error.message;
|
|
4149
3626
|
}
|
|
4150
|
-
return
|
|
3627
|
+
return String(error);
|
|
4151
3628
|
}
|
|
4152
|
-
function
|
|
4153
|
-
const
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
if (
|
|
4158
|
-
|
|
4159
|
-
}
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
if (
|
|
3629
|
+
function resolveProviders(config) {
|
|
3630
|
+
const candidates = [];
|
|
3631
|
+
if (config.provider) {
|
|
3632
|
+
candidates.push(config.provider);
|
|
3633
|
+
}
|
|
3634
|
+
if (Array.isArray(config.providers)) {
|
|
3635
|
+
candidates.push(...config.providers);
|
|
3636
|
+
}
|
|
3637
|
+
const providers = [];
|
|
3638
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3639
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
3640
|
+
for (const candidate of candidates) {
|
|
3641
|
+
if (!isProviderLike(candidate)) continue;
|
|
3642
|
+
if (seen.has(candidate)) continue;
|
|
3643
|
+
const name = candidate.name;
|
|
3644
|
+
if (name && seenNames.has(name)) continue;
|
|
3645
|
+
providers.push(candidate);
|
|
3646
|
+
seen.add(candidate);
|
|
3647
|
+
if (name) {
|
|
3648
|
+
seenNames.add(name);
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
if (providers.length > 0) {
|
|
3652
|
+
return providers;
|
|
4166
3653
|
}
|
|
4167
|
-
const configExample = buildConfigExample(provider, authOptions);
|
|
4168
3654
|
throw new Error(
|
|
4169
|
-
|
|
4170
|
-
${configExample}
|
|
4171
|
-
|
|
4172
|
-
Get your credentials at: ${dashboardUrl}`
|
|
4173
|
-
);
|
|
4174
|
-
}
|
|
4175
|
-
function envVarToConfigField(provider, envVar) {
|
|
4176
|
-
return PROVIDER_ENV_MAP[provider]?.[envVar] ?? envVar.toLowerCase();
|
|
4177
|
-
}
|
|
4178
|
-
function buildConfigExample(provider, authOptions) {
|
|
4179
|
-
if (authOptions.length === 1) {
|
|
4180
|
-
const fields = authOptions[0].map((envVar) => {
|
|
4181
|
-
const field = envVarToConfigField(provider, envVar);
|
|
4182
|
-
return `${field}: '...'`;
|
|
4183
|
-
});
|
|
4184
|
-
return ` ${provider}: { ${fields.join(", ")} }`;
|
|
4185
|
-
}
|
|
4186
|
-
const options = authOptions.map((option, i) => {
|
|
4187
|
-
const fields = option.map((envVar) => {
|
|
4188
|
-
const field = envVarToConfigField(provider, envVar);
|
|
4189
|
-
return `${field}: '...'`;
|
|
4190
|
-
});
|
|
4191
|
-
return ` Option ${i + 1}:
|
|
4192
|
-
${provider}: { ${fields.join(", ")} }`;
|
|
4193
|
-
});
|
|
4194
|
-
return options.join("\n\n");
|
|
4195
|
-
}
|
|
4196
|
-
function createConfigFromExplicit(config) {
|
|
4197
|
-
const computesdkApiKey = config.computesdkApiKey || config.apiKey;
|
|
4198
|
-
if (!computesdkApiKey) {
|
|
4199
|
-
throw new Error(
|
|
4200
|
-
`Missing ComputeSDK API key. Set 'computesdkApiKey' in your config.
|
|
4201
|
-
|
|
4202
|
-
Example:
|
|
4203
|
-
compute.setConfig({
|
|
4204
|
-
provider: 'e2b',
|
|
4205
|
-
computesdkApiKey: process.env.COMPUTESDK_API_KEY,
|
|
4206
|
-
e2b: { apiKey: process.env.E2B_API_KEY }
|
|
4207
|
-
})
|
|
4208
|
-
|
|
4209
|
-
Get your API key at: https://computesdk.com/dashboard`
|
|
4210
|
-
);
|
|
4211
|
-
}
|
|
4212
|
-
validateProviderConfig(config);
|
|
4213
|
-
const providerHeaders = buildProviderHeaders2(config);
|
|
4214
|
-
return {
|
|
4215
|
-
apiKey: computesdkApiKey,
|
|
4216
|
-
gatewayUrl: config.gatewayUrl || process.env.COMPUTESDK_TRIBUTARY_URL || TRIBUTARY_URL,
|
|
4217
|
-
provider: config.provider,
|
|
4218
|
-
providerHeaders,
|
|
4219
|
-
requestTimeoutMs: config.requestTimeoutMs,
|
|
4220
|
-
WebSocket: config.WebSocket
|
|
4221
|
-
};
|
|
4222
|
-
}
|
|
4223
|
-
|
|
4224
|
-
// src/compute-daemon/lifecycle.ts
|
|
4225
|
-
async function waitForComputeReady(client, options = {}) {
|
|
4226
|
-
const maxRetries = options.maxRetries ?? 30;
|
|
4227
|
-
const initialDelayMs = options.initialDelayMs ?? 500;
|
|
4228
|
-
const maxDelayMs = options.maxDelayMs ?? 5e3;
|
|
4229
|
-
const backoffFactor = options.backoffFactor ?? 1.5;
|
|
4230
|
-
let lastError = null;
|
|
4231
|
-
let currentDelay = initialDelayMs;
|
|
4232
|
-
for (let i = 0; i < maxRetries; i++) {
|
|
4233
|
-
try {
|
|
4234
|
-
await client.health();
|
|
4235
|
-
if (process.env.COMPUTESDK_DEBUG) {
|
|
4236
|
-
console.log(`[Lifecycle] Sandbox ready after ${i + 1} attempt${i === 0 ? "" : "s"}`);
|
|
4237
|
-
}
|
|
4238
|
-
return;
|
|
4239
|
-
} catch (error) {
|
|
4240
|
-
lastError = error instanceof Error ? error : new Error(String(error));
|
|
4241
|
-
if (i === maxRetries - 1) {
|
|
4242
|
-
throw new Error(
|
|
4243
|
-
`Sandbox failed to become ready after ${maxRetries} attempts.
|
|
4244
|
-
Last error: ${lastError.message}
|
|
4245
|
-
|
|
4246
|
-
Possible causes:
|
|
4247
|
-
1. Sandbox failed to start (check provider dashboard for errors)
|
|
4248
|
-
2. Network connectivity issues between your app and the sandbox
|
|
4249
|
-
3. Sandbox is taking longer than expected to initialize
|
|
4250
|
-
4. Invalid sandbox URL or authentication credentials
|
|
4251
|
-
|
|
4252
|
-
Troubleshooting:
|
|
4253
|
-
- Check sandbox logs in your provider dashboard
|
|
4254
|
-
- Verify your network connection
|
|
4255
|
-
- Try increasing maxRetries if initialization is slow
|
|
4256
|
-
- Enable debug mode: export COMPUTESDK_DEBUG=1`
|
|
4257
|
-
);
|
|
4258
|
-
}
|
|
4259
|
-
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
4260
|
-
currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
|
|
4261
|
-
}
|
|
4262
|
-
}
|
|
4263
|
-
}
|
|
4264
|
-
|
|
4265
|
-
// src/compute.ts
|
|
4266
|
-
async function tributaryFetch(url, config, options = {}) {
|
|
4267
|
-
const timeout = config.requestTimeoutMs ?? 3e4;
|
|
4268
|
-
const controller = new AbortController();
|
|
4269
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
4270
|
-
try {
|
|
4271
|
-
const response = await fetch(url, {
|
|
4272
|
-
...options,
|
|
4273
|
-
signal: controller.signal,
|
|
4274
|
-
headers: {
|
|
4275
|
-
"Content-Type": "application/json",
|
|
4276
|
-
"X-ComputeSDK-API-Key": config.apiKey,
|
|
4277
|
-
"X-Provider": config.provider,
|
|
4278
|
-
...config.providerHeaders,
|
|
4279
|
-
...options.headers
|
|
4280
|
-
}
|
|
4281
|
-
});
|
|
4282
|
-
clearTimeout(timeoutId);
|
|
4283
|
-
if (!response.ok) {
|
|
4284
|
-
if (response.status === 404) {
|
|
4285
|
-
return { success: false };
|
|
4286
|
-
}
|
|
4287
|
-
const errorText = await response.text().catch(() => response.statusText);
|
|
4288
|
-
let errorMessage = `Gateway API error: ${errorText}`;
|
|
4289
|
-
if (response.status === 401) {
|
|
4290
|
-
errorMessage = `Invalid ComputeSDK API key. Check your COMPUTESDK_API_KEY environment variable.`;
|
|
4291
|
-
} else if (response.status === 403) {
|
|
4292
|
-
errorMessage = `Access forbidden. Your API key may not have permission to use provider "${config.provider}".`;
|
|
4293
|
-
}
|
|
4294
|
-
throw new Error(errorMessage);
|
|
4295
|
-
}
|
|
4296
|
-
return await response.json();
|
|
4297
|
-
} catch (error) {
|
|
4298
|
-
clearTimeout(timeoutId);
|
|
4299
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
4300
|
-
throw new Error(`Request timed out after ${timeout}ms`);
|
|
4301
|
-
}
|
|
4302
|
-
throw error;
|
|
4303
|
-
}
|
|
4304
|
-
}
|
|
4305
|
-
async function waitForSandboxStatus(config, endpoint, body, options = {}) {
|
|
4306
|
-
const maxWaitMs = options.maxWaitMs ?? 6e4;
|
|
4307
|
-
const initialDelayMs = 500;
|
|
4308
|
-
const maxDelayMs = 2e3;
|
|
4309
|
-
const backoffFactor = 1.5;
|
|
4310
|
-
const startTime = Date.now();
|
|
4311
|
-
let currentDelay = initialDelayMs;
|
|
4312
|
-
while (Date.now() - startTime < maxWaitMs) {
|
|
4313
|
-
const result = await tributaryFetch(endpoint, config, {
|
|
4314
|
-
method: "POST",
|
|
4315
|
-
body: JSON.stringify(body)
|
|
4316
|
-
});
|
|
4317
|
-
if (!result.success || !result.data) {
|
|
4318
|
-
return result;
|
|
4319
|
-
}
|
|
4320
|
-
if (result.data.status !== "creating") {
|
|
4321
|
-
return result;
|
|
4322
|
-
}
|
|
4323
|
-
if (process.env.COMPUTESDK_DEBUG) {
|
|
4324
|
-
console.log(`[Compute] Sandbox still creating, waiting ${currentDelay}ms...`);
|
|
4325
|
-
}
|
|
4326
|
-
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
4327
|
-
currentDelay = Math.min(currentDelay * backoffFactor, maxDelayMs);
|
|
4328
|
-
}
|
|
4329
|
-
throw new Error(
|
|
4330
|
-
`Sandbox is still being created after ${maxWaitMs}ms. This may indicate the sandbox failed to start. Check your provider dashboard.`
|
|
3655
|
+
"No provider instance configured.\n\nConfigure compute with provider instances:\n\n compute.setConfig({ providers: [e2b({...}), modal({...})] })\n // or: compute.setConfig({ provider: e2b({...}) })"
|
|
4331
3656
|
);
|
|
4332
3657
|
}
|
|
4333
3658
|
var ComputeManager = class {
|
|
4334
3659
|
constructor() {
|
|
4335
|
-
this.
|
|
4336
|
-
this.
|
|
3660
|
+
this.providers = [];
|
|
3661
|
+
this.providerStrategy = "priority";
|
|
3662
|
+
this.fallbackOnError = true;
|
|
3663
|
+
this.roundRobinCursor = 0;
|
|
3664
|
+
this.sandboxProviders = /* @__PURE__ */ new Map();
|
|
3665
|
+
this.snapshotProviders = /* @__PURE__ */ new Map();
|
|
4337
3666
|
this.sandbox = {
|
|
4338
|
-
/**
|
|
4339
|
-
* Create a new sandbox
|
|
4340
|
-
*
|
|
4341
|
-
* @example
|
|
4342
|
-
* ```typescript
|
|
4343
|
-
* const sandbox = await compute.sandbox.create({
|
|
4344
|
-
* directory: '/custom/path',
|
|
4345
|
-
* overlays: [
|
|
4346
|
-
* {
|
|
4347
|
-
* source: '/templates/nextjs',
|
|
4348
|
-
* target: 'app',
|
|
4349
|
-
* strategy: 'smart',
|
|
4350
|
-
* },
|
|
4351
|
-
* ],
|
|
4352
|
-
* servers: [
|
|
4353
|
-
* {
|
|
4354
|
-
* slug: 'web',
|
|
4355
|
-
* start: 'npm run dev',
|
|
4356
|
-
* path: '/app',
|
|
4357
|
-
* },
|
|
4358
|
-
* ],
|
|
4359
|
-
* });
|
|
4360
|
-
* ```
|
|
4361
|
-
*/
|
|
4362
3667
|
create: async (options) => {
|
|
4363
|
-
|
|
4364
|
-
const result = await tributaryFetch(`${config.gatewayUrl}/v1/sandboxes`, config, {
|
|
4365
|
-
method: "POST",
|
|
4366
|
-
body: JSON.stringify(options || {})
|
|
4367
|
-
});
|
|
4368
|
-
if (!result.success || !result.data) {
|
|
4369
|
-
throw new Error(`Gateway returned invalid response`);
|
|
4370
|
-
}
|
|
4371
|
-
const { sandboxId, url, token, provider, metadata, name, namespace, overlays, servers } = result.data;
|
|
4372
|
-
const sandbox = new Sandbox({
|
|
4373
|
-
sandboxUrl: url,
|
|
4374
|
-
sandboxId,
|
|
4375
|
-
provider,
|
|
4376
|
-
token: token || config.apiKey,
|
|
4377
|
-
metadata: {
|
|
4378
|
-
...metadata,
|
|
4379
|
-
...name && { name },
|
|
4380
|
-
...namespace && { namespace },
|
|
4381
|
-
...overlays && { overlays },
|
|
4382
|
-
...servers && { servers }
|
|
4383
|
-
},
|
|
4384
|
-
WebSocket: config.WebSocket || globalThis.WebSocket,
|
|
4385
|
-
destroyHandler: async () => {
|
|
4386
|
-
await tributaryFetch(`${config.gatewayUrl}/v1/sandboxes/${sandboxId}`, config, {
|
|
4387
|
-
method: "DELETE"
|
|
4388
|
-
});
|
|
4389
|
-
}
|
|
4390
|
-
});
|
|
4391
|
-
await waitForComputeReady(sandbox);
|
|
4392
|
-
return sandbox;
|
|
3668
|
+
return this.createWithFallback(options);
|
|
4393
3669
|
},
|
|
4394
|
-
/**
|
|
4395
|
-
* Get an existing sandbox by ID
|
|
4396
|
-
*/
|
|
4397
3670
|
getById: async (sandboxId) => {
|
|
4398
|
-
const
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
const { url, token, provider, metadata } = result.data;
|
|
4404
|
-
const sandbox = new Sandbox({
|
|
4405
|
-
sandboxUrl: url,
|
|
4406
|
-
sandboxId,
|
|
4407
|
-
provider,
|
|
4408
|
-
token: token || config.apiKey,
|
|
4409
|
-
metadata,
|
|
4410
|
-
WebSocket: config.WebSocket || globalThis.WebSocket,
|
|
4411
|
-
destroyHandler: async () => {
|
|
4412
|
-
await tributaryFetch(`${config.gatewayUrl}/v1/sandboxes/${sandboxId}`, config, {
|
|
4413
|
-
method: "DELETE"
|
|
4414
|
-
});
|
|
3671
|
+
for (const provider of this.getByIdCandidates(sandboxId)) {
|
|
3672
|
+
const sandbox = await provider.sandbox.getById(sandboxId);
|
|
3673
|
+
if (sandbox) {
|
|
3674
|
+
this.registerSandboxProvider(sandbox, provider);
|
|
3675
|
+
return sandbox;
|
|
4415
3676
|
}
|
|
4416
|
-
}
|
|
4417
|
-
|
|
4418
|
-
return
|
|
3677
|
+
}
|
|
3678
|
+
this.sandboxProviders.delete(sandboxId);
|
|
3679
|
+
return null;
|
|
4419
3680
|
},
|
|
4420
|
-
/**
|
|
4421
|
-
* List all active sandboxes
|
|
4422
|
-
*/
|
|
4423
3681
|
list: async () => {
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
3682
|
+
const all = [];
|
|
3683
|
+
for (const provider of this.getProviders()) {
|
|
3684
|
+
if (!provider.sandbox.list) {
|
|
3685
|
+
continue;
|
|
3686
|
+
}
|
|
3687
|
+
const sandboxes = await provider.sandbox.list();
|
|
3688
|
+
for (const sandbox of sandboxes) {
|
|
3689
|
+
this.registerSandboxProvider(sandbox, provider);
|
|
3690
|
+
}
|
|
3691
|
+
all.push(...sandboxes);
|
|
3692
|
+
}
|
|
3693
|
+
return all;
|
|
4427
3694
|
},
|
|
4428
|
-
/**
|
|
4429
|
-
* Destroy a sandbox
|
|
4430
|
-
*/
|
|
4431
3695
|
destroy: async (sandboxId) => {
|
|
4432
|
-
const
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
const config = this.getGatewayConfig();
|
|
4442
|
-
const { name, namespace, ...restOptions } = options;
|
|
4443
|
-
const result = await waitForSandboxStatus(
|
|
4444
|
-
config,
|
|
4445
|
-
`${config.gatewayUrl}/v1/sandboxes/find-or-create`,
|
|
4446
|
-
{
|
|
4447
|
-
namespace: namespace || "default",
|
|
4448
|
-
name,
|
|
4449
|
-
...restOptions
|
|
3696
|
+
const candidates = this.getByIdCandidates(sandboxId);
|
|
3697
|
+
const errors = [];
|
|
3698
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3699
|
+
try {
|
|
3700
|
+
await provider.sandbox.destroy(sandboxId);
|
|
3701
|
+
this.sandboxProviders.delete(sandboxId);
|
|
3702
|
+
return;
|
|
3703
|
+
} catch (error) {
|
|
3704
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
4450
3705
|
}
|
|
4451
|
-
);
|
|
4452
|
-
if (!result.success || !result.data) {
|
|
4453
|
-
throw new Error(`Gateway returned invalid response`);
|
|
4454
3706
|
}
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
...metadata,
|
|
4463
|
-
name: result.data.name,
|
|
4464
|
-
namespace: result.data.namespace
|
|
4465
|
-
},
|
|
4466
|
-
WebSocket: config.WebSocket || globalThis.WebSocket,
|
|
4467
|
-
destroyHandler: async () => {
|
|
4468
|
-
await tributaryFetch(`${config.gatewayUrl}/v1/sandboxes/${sandboxId}`, config, {
|
|
4469
|
-
method: "DELETE"
|
|
4470
|
-
});
|
|
4471
|
-
}
|
|
4472
|
-
});
|
|
4473
|
-
await waitForComputeReady(sandbox);
|
|
4474
|
-
return sandbox;
|
|
3707
|
+
throw new Error(
|
|
3708
|
+
`Failed to destroy sandbox "${sandboxId}" across ${candidates.length} provider(s).
|
|
3709
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3710
|
+
);
|
|
3711
|
+
},
|
|
3712
|
+
findOrCreate: async (options) => {
|
|
3713
|
+
return this.findOrCreateWithFallback(options);
|
|
4475
3714
|
},
|
|
4476
|
-
/**
|
|
4477
|
-
* Find existing sandbox by (namespace, name) without creating
|
|
4478
|
-
*/
|
|
4479
3715
|
find: async (options) => {
|
|
4480
|
-
const
|
|
4481
|
-
const
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
{
|
|
4485
|
-
|
|
4486
|
-
name: options.name
|
|
3716
|
+
const preferredProviderName = options.provider;
|
|
3717
|
+
const { provider: _providerName, ...providerOptions } = options;
|
|
3718
|
+
const candidates = this.getCreateCandidates(preferredProviderName);
|
|
3719
|
+
for (const provider of candidates) {
|
|
3720
|
+
if (!provider.sandbox.find) {
|
|
3721
|
+
continue;
|
|
4487
3722
|
}
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
const { sandboxId, url, token, provider, metadata, name, namespace } = result.data;
|
|
4493
|
-
const sandbox = new Sandbox({
|
|
4494
|
-
sandboxUrl: url,
|
|
4495
|
-
sandboxId,
|
|
4496
|
-
provider,
|
|
4497
|
-
token: token || config.apiKey,
|
|
4498
|
-
metadata: {
|
|
4499
|
-
...metadata,
|
|
4500
|
-
name,
|
|
4501
|
-
namespace
|
|
4502
|
-
},
|
|
4503
|
-
WebSocket: config.WebSocket || globalThis.WebSocket,
|
|
4504
|
-
destroyHandler: async () => {
|
|
4505
|
-
await tributaryFetch(`${config.gatewayUrl}/v1/sandboxes/${sandboxId}`, config, {
|
|
4506
|
-
method: "DELETE"
|
|
4507
|
-
});
|
|
3723
|
+
const sandbox = await provider.sandbox.find(providerOptions);
|
|
3724
|
+
if (sandbox) {
|
|
3725
|
+
this.registerSandboxProvider(sandbox, provider);
|
|
3726
|
+
return sandbox;
|
|
4508
3727
|
}
|
|
4509
|
-
}
|
|
4510
|
-
|
|
4511
|
-
return sandbox;
|
|
3728
|
+
}
|
|
3729
|
+
return null;
|
|
4512
3730
|
},
|
|
4513
|
-
/**
|
|
4514
|
-
* Extend sandbox timeout/expiration
|
|
4515
|
-
*/
|
|
4516
3731
|
extendTimeout: async (sandboxId, options) => {
|
|
4517
|
-
const
|
|
4518
|
-
const
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
3732
|
+
const candidates = this.getByIdCandidates(sandboxId);
|
|
3733
|
+
const errors = [];
|
|
3734
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3735
|
+
if (!provider.sandbox.extendTimeout) {
|
|
3736
|
+
errors.push(`${getProviderLabel(provider, index)}: extendTimeout() not supported`);
|
|
3737
|
+
continue;
|
|
3738
|
+
}
|
|
3739
|
+
try {
|
|
3740
|
+
await provider.sandbox.extendTimeout(sandboxId, options);
|
|
3741
|
+
this.sandboxProviders.set(sandboxId, provider);
|
|
3742
|
+
return;
|
|
3743
|
+
} catch (error) {
|
|
3744
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
throw new Error(
|
|
3748
|
+
`Failed to extend timeout for sandbox "${sandboxId}" across ${candidates.length} provider(s).
|
|
3749
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3750
|
+
);
|
|
4523
3751
|
}
|
|
4524
3752
|
};
|
|
4525
3753
|
this.snapshot = {
|
|
4526
|
-
/**
|
|
4527
|
-
* Create a snapshot from a running sandbox
|
|
4528
|
-
*
|
|
4529
|
-
* @param sandboxId ID of the sandbox to snapshot
|
|
4530
|
-
* @param options Snapshot options (name, metadata)
|
|
4531
|
-
*/
|
|
4532
3754
|
create: async (sandboxId, options) => {
|
|
4533
|
-
const
|
|
4534
|
-
const
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
3755
|
+
const preferredProviderName = options?.provider;
|
|
3756
|
+
const { provider: _providerName, ...providerOptions } = options || {};
|
|
3757
|
+
const candidates = this.getSnapshotCreateCandidates(sandboxId, preferredProviderName);
|
|
3758
|
+
const errors = [];
|
|
3759
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3760
|
+
if (!provider.snapshot) {
|
|
3761
|
+
errors.push(`${getProviderLabel(provider, index)}: snapshots not supported`);
|
|
3762
|
+
continue;
|
|
3763
|
+
}
|
|
3764
|
+
try {
|
|
3765
|
+
const snapshot = await provider.snapshot.create(sandboxId, providerOptions);
|
|
3766
|
+
this.snapshotProviders.set(snapshot.id, provider);
|
|
3767
|
+
return {
|
|
3768
|
+
...snapshot,
|
|
3769
|
+
createdAt: new Date(snapshot.createdAt)
|
|
3770
|
+
};
|
|
3771
|
+
} catch (error) {
|
|
3772
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
3773
|
+
}
|
|
4540
3774
|
}
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
3775
|
+
throw new Error(
|
|
3776
|
+
`Failed to create snapshot for sandbox "${sandboxId}" across ${candidates.length} provider(s).
|
|
3777
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3778
|
+
);
|
|
4545
3779
|
},
|
|
4546
|
-
/**
|
|
4547
|
-
* List all snapshots
|
|
4548
|
-
*/
|
|
4549
3780
|
list: async () => {
|
|
4550
|
-
const
|
|
4551
|
-
const
|
|
4552
|
-
|
|
4553
|
-
|
|
3781
|
+
const snapshots = [];
|
|
3782
|
+
for (const provider of this.getProviders()) {
|
|
3783
|
+
if (!provider.snapshot) continue;
|
|
3784
|
+
const listed = await provider.snapshot.list();
|
|
3785
|
+
for (const snapshot of listed) {
|
|
3786
|
+
this.snapshotProviders.set(snapshot.id, provider);
|
|
3787
|
+
snapshots.push({
|
|
3788
|
+
...snapshot,
|
|
3789
|
+
createdAt: new Date(snapshot.createdAt)
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
4554
3792
|
}
|
|
4555
|
-
return
|
|
4556
|
-
...s,
|
|
4557
|
-
createdAt: new Date(s.createdAt)
|
|
4558
|
-
}));
|
|
3793
|
+
return snapshots;
|
|
4559
3794
|
},
|
|
4560
|
-
/**
|
|
4561
|
-
* Delete a snapshot
|
|
4562
|
-
*/
|
|
4563
3795
|
delete: async (snapshotId) => {
|
|
4564
|
-
const
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
3796
|
+
const candidates = this.getSnapshotDeleteCandidates(snapshotId);
|
|
3797
|
+
const errors = [];
|
|
3798
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3799
|
+
if (!provider.snapshot) continue;
|
|
3800
|
+
try {
|
|
3801
|
+
await provider.snapshot.delete(snapshotId);
|
|
3802
|
+
this.snapshotProviders.delete(snapshotId);
|
|
3803
|
+
return;
|
|
3804
|
+
} catch (error) {
|
|
3805
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
throw new Error(
|
|
3809
|
+
`Failed to delete snapshot "${snapshotId}" across ${candidates.length} provider(s).
|
|
3810
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3811
|
+
);
|
|
4568
3812
|
}
|
|
4569
3813
|
};
|
|
4570
3814
|
}
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
*/
|
|
4574
|
-
ensureConfigured() {
|
|
4575
|
-
if (this.config) return;
|
|
4576
|
-
if (this.autoConfigured) return;
|
|
4577
|
-
const config = autoConfigureCompute();
|
|
4578
|
-
this.autoConfigured = true;
|
|
4579
|
-
if (config) {
|
|
4580
|
-
this.config = config;
|
|
4581
|
-
}
|
|
4582
|
-
}
|
|
4583
|
-
/**
|
|
4584
|
-
* Get gateway config, throwing if not configured
|
|
4585
|
-
*/
|
|
4586
|
-
getGatewayConfig() {
|
|
4587
|
-
this.ensureConfigured();
|
|
4588
|
-
if (!this.config) {
|
|
3815
|
+
getProviders() {
|
|
3816
|
+
if (this.providers.length === 0) {
|
|
4589
3817
|
throw new Error(
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
Options:
|
|
4593
|
-
1. Zero-config: Set COMPUTESDK_API_KEY and provider credentials (e.g., E2B_API_KEY)
|
|
4594
|
-
2. Explicit: Call compute.setConfig({ provider: "e2b", computesdkApiKey: "...", e2b: { apiKey: "..." } })
|
|
4595
|
-
3. Use provider directly: import { e2b } from '@computesdk/e2b'
|
|
4596
|
-
|
|
4597
|
-
Docs: https://computesdk.com/docs/quickstart`
|
|
3818
|
+
"No compute provider configured.\n\nOptions:\n1. Configure providers: compute.setConfig({ providers: [e2b({...}), modal({...})] })\n2. Configure a single provider: compute.setConfig({ provider: e2b({...}) })\n3. Use provider directly: const sdk = e2b({...}); await sdk.sandbox.create()"
|
|
4598
3819
|
);
|
|
4599
3820
|
}
|
|
4600
|
-
return this.
|
|
3821
|
+
return this.providers;
|
|
3822
|
+
}
|
|
3823
|
+
getProviderByName(name) {
|
|
3824
|
+
const provider = this.getProviders().find((p) => p.name === name);
|
|
3825
|
+
if (!provider) {
|
|
3826
|
+
const names = this.getProviders().map((p, i) => getProviderLabel(p, i)).join(", ");
|
|
3827
|
+
throw new Error(`Provider "${name}" is not configured. Configured providers: ${names || "(none)"}.`);
|
|
3828
|
+
}
|
|
3829
|
+
return provider;
|
|
3830
|
+
}
|
|
3831
|
+
registerSandboxProvider(sandbox, provider) {
|
|
3832
|
+
const sandboxId = sandbox?.sandboxId;
|
|
3833
|
+
if (sandboxId) {
|
|
3834
|
+
this.sandboxProviders.set(sandboxId, provider);
|
|
3835
|
+
}
|
|
3836
|
+
}
|
|
3837
|
+
getCreateCandidates(preferredProviderName) {
|
|
3838
|
+
const providers = this.getProviders();
|
|
3839
|
+
if (preferredProviderName) {
|
|
3840
|
+
return [this.getProviderByName(preferredProviderName)];
|
|
3841
|
+
}
|
|
3842
|
+
if (providers.length <= 1 || this.providerStrategy === "priority") {
|
|
3843
|
+
return [...providers];
|
|
3844
|
+
}
|
|
3845
|
+
const start = this.roundRobinCursor % providers.length;
|
|
3846
|
+
this.roundRobinCursor = (this.roundRobinCursor + 1) % providers.length;
|
|
3847
|
+
return [
|
|
3848
|
+
...providers.slice(start),
|
|
3849
|
+
...providers.slice(0, start)
|
|
3850
|
+
];
|
|
3851
|
+
}
|
|
3852
|
+
getByIdCandidates(sandboxId) {
|
|
3853
|
+
const known = this.sandboxProviders.get(sandboxId);
|
|
3854
|
+
if (!known) return this.getProviders();
|
|
3855
|
+
const providers = this.getProviders();
|
|
3856
|
+
return [known, ...providers.filter((p) => p !== known)];
|
|
3857
|
+
}
|
|
3858
|
+
getSnapshotDeleteCandidates(snapshotId) {
|
|
3859
|
+
const known = this.snapshotProviders.get(snapshotId);
|
|
3860
|
+
const providers = this.getProviders().filter((p) => !!p.snapshot);
|
|
3861
|
+
if (!known) return providers;
|
|
3862
|
+
return [known, ...providers.filter((p) => p !== known)];
|
|
3863
|
+
}
|
|
3864
|
+
getSnapshotCreateCandidates(sandboxId, preferredProviderName) {
|
|
3865
|
+
if (preferredProviderName) {
|
|
3866
|
+
return [this.getProviderByName(preferredProviderName)];
|
|
3867
|
+
}
|
|
3868
|
+
const known = this.sandboxProviders.get(sandboxId);
|
|
3869
|
+
const providers = this.getProviders().filter((p) => !!p.snapshot);
|
|
3870
|
+
if (known && known.snapshot) {
|
|
3871
|
+
return [known, ...providers.filter((p) => p !== known)];
|
|
3872
|
+
}
|
|
3873
|
+
return providers;
|
|
3874
|
+
}
|
|
3875
|
+
async createWithFallback(options) {
|
|
3876
|
+
const preferredProviderName = options?.provider;
|
|
3877
|
+
const { provider: _providerName, ...providerOptions } = options || {};
|
|
3878
|
+
const candidates = this.getCreateCandidates(preferredProviderName);
|
|
3879
|
+
const canFallback = this.fallbackOnError && !preferredProviderName;
|
|
3880
|
+
const errors = [];
|
|
3881
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3882
|
+
try {
|
|
3883
|
+
const sandbox = await provider.sandbox.create(providerOptions);
|
|
3884
|
+
this.registerSandboxProvider(sandbox, provider);
|
|
3885
|
+
return sandbox;
|
|
3886
|
+
} catch (error) {
|
|
3887
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
3888
|
+
if (!canFallback) {
|
|
3889
|
+
throw error;
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
throw new Error(
|
|
3894
|
+
`Failed to create sandbox across ${candidates.length} provider(s).
|
|
3895
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3896
|
+
);
|
|
3897
|
+
}
|
|
3898
|
+
async findOrCreateWithFallback(options) {
|
|
3899
|
+
const preferredProviderName = options.provider;
|
|
3900
|
+
const { provider: _providerName, ...providerOptions } = options;
|
|
3901
|
+
const candidates = this.getCreateCandidates(preferredProviderName);
|
|
3902
|
+
const canFallback = this.fallbackOnError && !preferredProviderName;
|
|
3903
|
+
const errors = [];
|
|
3904
|
+
for (const [index, provider] of candidates.entries()) {
|
|
3905
|
+
try {
|
|
3906
|
+
if (!provider.sandbox.findOrCreate) {
|
|
3907
|
+
errors.push(`${getProviderLabel(provider, index)}: findOrCreate() not supported`);
|
|
3908
|
+
continue;
|
|
3909
|
+
}
|
|
3910
|
+
const sandbox = await provider.sandbox.findOrCreate(providerOptions);
|
|
3911
|
+
this.registerSandboxProvider(sandbox, provider);
|
|
3912
|
+
return sandbox;
|
|
3913
|
+
} catch (error) {
|
|
3914
|
+
errors.push(`${getProviderLabel(provider, index)}: ${getProviderErrorDetail(error)}`);
|
|
3915
|
+
if (!canFallback) {
|
|
3916
|
+
throw error;
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
}
|
|
3920
|
+
throw new Error(
|
|
3921
|
+
`Failed to findOrCreate sandbox across ${candidates.length} provider(s).
|
|
3922
|
+
` + errors.map((error) => `- ${error}`).join("\n")
|
|
3923
|
+
);
|
|
4601
3924
|
}
|
|
4602
|
-
/**
|
|
4603
|
-
* Explicitly configure the compute singleton
|
|
4604
|
-
*
|
|
4605
|
-
* @example
|
|
4606
|
-
* ```typescript
|
|
4607
|
-
* import { compute } from 'computesdk';
|
|
4608
|
-
*
|
|
4609
|
-
* compute.setConfig({
|
|
4610
|
-
* provider: 'e2b',
|
|
4611
|
-
* apiKey: 'computesdk_xxx',
|
|
4612
|
-
* e2b: { apiKey: 'e2b_xxx' }
|
|
4613
|
-
* });
|
|
4614
|
-
*
|
|
4615
|
-
* const sandbox = await compute.sandbox.create();
|
|
4616
|
-
* ```
|
|
4617
|
-
*/
|
|
4618
3925
|
setConfig(config) {
|
|
4619
|
-
|
|
4620
|
-
this.
|
|
4621
|
-
this.
|
|
3926
|
+
this.providers = resolveProviders(config);
|
|
3927
|
+
this.providerStrategy = config.providerStrategy ?? "priority";
|
|
3928
|
+
this.fallbackOnError = config.fallbackOnError ?? true;
|
|
3929
|
+
this.roundRobinCursor = 0;
|
|
3930
|
+
this.sandboxProviders.clear();
|
|
3931
|
+
this.snapshotProviders.clear();
|
|
4622
3932
|
}
|
|
4623
3933
|
};
|
|
4624
3934
|
var singletonInstance = new ComputeManager();
|
|
4625
3935
|
function computeFactory(config) {
|
|
4626
|
-
const gatewayConfig = createConfigFromExplicit(config);
|
|
4627
3936
|
const manager = new ComputeManager();
|
|
4628
|
-
manager
|
|
3937
|
+
manager.setConfig(config);
|
|
4629
3938
|
return manager;
|
|
4630
3939
|
}
|
|
4631
3940
|
var compute = new Proxy(
|
|
@@ -4648,33 +3957,15 @@ var compute = new Proxy(
|
|
|
4648
3957
|
0 && (module.exports = {
|
|
4649
3958
|
CommandExitError,
|
|
4650
3959
|
FileWatcher,
|
|
4651
|
-
GatewaySandbox,
|
|
4652
3960
|
MessageType,
|
|
4653
|
-
PROVIDER_AUTH,
|
|
4654
|
-
PROVIDER_DASHBOARD_URLS,
|
|
4655
|
-
PROVIDER_ENV_MAP,
|
|
4656
|
-
PROVIDER_ENV_VARS,
|
|
4657
|
-
PROVIDER_HEADERS,
|
|
4658
|
-
PROVIDER_NAMES,
|
|
4659
|
-
PROVIDER_PRIORITY,
|
|
4660
3961
|
Sandbox,
|
|
4661
3962
|
SignalService,
|
|
4662
|
-
TRIBUTARY_URL,
|
|
4663
3963
|
TerminalInstance,
|
|
4664
|
-
autoConfigureCompute,
|
|
4665
|
-
buildProviderHeaders,
|
|
4666
3964
|
buildSetupPayload,
|
|
4667
3965
|
compute,
|
|
4668
3966
|
decodeBinaryMessage,
|
|
4669
|
-
detectProvider,
|
|
4670
3967
|
encodeBinaryMessage,
|
|
4671
3968
|
encodeSetupPayload,
|
|
4672
|
-
|
|
4673
|
-
getProviderConfigFromEnv,
|
|
4674
|
-
getProviderHeaders,
|
|
4675
|
-
isCommandExitError,
|
|
4676
|
-
isGatewayModeEnabled,
|
|
4677
|
-
isProviderAuthComplete,
|
|
4678
|
-
isValidProvider
|
|
3969
|
+
isCommandExitError
|
|
4679
3970
|
});
|
|
4680
3971
|
//# sourceMappingURL=index.js.map
|