the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add E2B provider support

+63 -4
+61 -4
apps/web/src/pages/settings/provider/Provider.tsx
··· 21 21 vercel: "Vercel API Token", 22 22 deno: "Deno Deploy Token", 23 23 sprites: "Sprites API Key", 24 + e2b: "E2B Access Token", 24 25 } as const; 25 26 26 27 type Provider = keyof typeof LABELS | "cloudflare" | "modal"; ··· 34 35 "deno", 35 36 "sprites", 36 37 "modal", 38 + "e2b", 37 39 ]), 38 40 apiKey: z.string().optional(), 39 41 organizationId: z.string().optional(), ··· 41 43 vercelTeamId: z.string().optional(), 42 44 tokenId: z.string().optional(), 43 45 tokenSecret: z.string().optional(), 46 + e2bAccessToken: z.string().optional(), 44 47 }) 45 48 .superRefine((data, ctx) => { 46 49 if ( 47 50 data.provider !== "cloudflare" && 48 51 data.provider !== "modal" && 52 + data.provider !== "e2b" && 49 53 !data.apiKey?.trim() 50 54 ) { 51 55 ctx.addIssue({ ··· 89 93 path: ["tokenSecret"], 90 94 }); 91 95 } 96 + if (data.provider === "e2b" && !data.e2bAccessToken?.trim()) { 97 + ctx.addIssue({ 98 + code: z.ZodIssueCode.custom, 99 + message: "E2B Access Token is required", 100 + path: ["e2bAccessToken"], 101 + }); 102 + } 92 103 }); 93 104 94 105 type FormValues = z.infer<typeof schema>; ··· 122 133 vercelTeamId: "", 123 134 tokenId: "", 124 135 tokenSecret: "", 136 + e2bAccessToken: "", 125 137 }, 126 138 }); 127 139 ··· 139 151 setValue("vercelTeamId", providerPref.vercelTeamId ?? ""); 140 152 setValue("tokenId", providerPref.redactedModalTokenId ?? ""); 141 153 setValue("tokenSecret", providerPref.redactedModalTokenSecret ?? ""); 154 + setValue("e2bAccessToken", providerPref.redactedE2bAccessToken ?? ""); 142 155 } 143 156 }, [preferences, setValue]); 144 157 ··· 195 208 values.tokenSecret.slice(-3) 196 209 : values.tokenSecret; 197 210 } 198 - } else if (values.apiKey?.includes("**") && values.provider !== "cloudflare") { 211 + } else if (values.provider === "e2b") { 212 + if (values.e2bAccessToken && !values.e2bAccessToken.includes("**")) { 213 + const sealed = sodium.cryptoBoxSeal( 214 + sodium.fromString(values.e2bAccessToken.trim()), 215 + sodium.fromHex(PUBLIC_KEY), 216 + ); 217 + pref.e2bAccessToken = sodium.toBase64( 218 + sealed, 219 + sodium.base64Variants.URLSAFE_NO_PADDING, 220 + ); 221 + pref.redactedE2bAccessToken = 222 + values.e2bAccessToken.length > 14 223 + ? values.e2bAccessToken.slice(0, 11) + 224 + "*".repeat(24) + 225 + values.e2bAccessToken.slice(-3) 226 + : values.e2bAccessToken; 227 + } 228 + } else if ( 229 + values.apiKey?.includes("**") && 230 + values.provider !== "cloudflare" 231 + ) { 199 232 if (values.provider !== "daytona" && values.provider !== "vercel") { 200 233 return; 201 234 } 202 235 } 203 236 204 - if (values.provider !== "modal" && values.apiKey && !values.apiKey.includes("**")) { 237 + if ( 238 + values.provider !== "modal" && 239 + values.provider !== "e2b" && 240 + values.apiKey && 241 + !values.apiKey.includes("**") 242 + ) { 205 243 const sealed = sodium.cryptoBoxSeal( 206 244 sodium.fromString(values.apiKey), 207 245 sodium.fromHex(PUBLIC_KEY), ··· 262 300 setValue("vercelTeamId", ""); 263 301 setValue("tokenId", ""); 264 302 setValue("tokenSecret", ""); 303 + setValue("e2bAccessToken", ""); 265 304 }} 266 305 className="select select-lg font-medium text-[15px]" 267 306 > ··· 273 312 <option value="deno">Deno Sandbox</option> 274 313 <option value="sprites">Sprites</option> 275 314 <option value="modal">Modal</option> 315 + <option value="e2b">E2B</option> 276 316 </select> 277 317 </div> 278 - {provider !== "cloudflare" && provider !== "modal" && ( 318 + {provider !== "cloudflare" && provider !== "modal" && provider !== "e2b" && ( 279 319 <div className="w-96"> 280 - <label className="label-text">{LABELS[provider as keyof typeof LABELS]}</label> 320 + <label className="label-text"> 321 + {LABELS[provider as keyof typeof LABELS]} 322 + </label> 281 323 <input 282 324 {...register("apiKey")} 283 325 type="text" ··· 336 378 </p> 337 379 )} 338 380 </div> 381 + </div> 382 + )} 383 + {provider === "e2b" && ( 384 + <div className="w-96 mt-4"> 385 + <label className="label-text">E2B Access Token</label> 386 + <input 387 + {...register("e2bAccessToken")} 388 + type="text" 389 + className="input input-lg font-medium text-[15px]" 390 + /> 391 + {errors.e2bAccessToken && ( 392 + <p className="text-error text-sm mt-1"> 393 + {errors.e2bAccessToken.message} 394 + </p> 395 + )} 339 396 </div> 340 397 )} 341 398 {provider === "modal" && (
+2
apps/web/src/types/preferences.ts
··· 17 17 redactedModalTokenId?: string; 18 18 modalTokenSecret?: string; 19 19 redactedModalTokenSecret?: string; 20 + e2bAccessToken?: string; 21 + redactedE2bAccessToken?: string; 20 22 $type: "io.pocketenv.sandbox.defs#sandboxProviderPref"; 21 23 }; 22 24