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.

at main 177 lines 5.5 kB view raw
1import consola from "consola"; 2import { Sandbox } from "@pocketenv/sdk"; 3import connectToSandbox from "./ssh"; 4import { c } from "../theme"; 5import { expandRepo } from "../lib/expandRepo"; 6import encrypt from "../lib/sodium"; 7import redact from "../lib/redact"; 8import { configureSdk } from "../lib/sdk"; 9 10async function createSandbox( 11 name: string, 12 { 13 provider, 14 ssh, 15 base, 16 repo, 17 }: { 18 provider?: string; 19 ssh?: boolean; 20 base?: string; 21 repo?: string; 22 }, 23) { 24 await configureSdk(); 25 if (repo) repo = expandRepo(repo); 26 27 const providerOptions: Record<string, any> = {}; 28 29 if ( 30 ![ 31 "sprites", 32 "daytona", 33 "deno", 34 "vercel", 35 "cloudflare", 36 "modal", 37 "e2b", 38 "hopx", 39 "runloop", 40 "blaxel", 41 ].includes(provider ?? "cloudflare") 42 ) { 43 consola.error( 44 `Unsupported provider: ${provider}. Supported providers are: sprites, daytona, deno, vercel, modal, e2b, hopx, runloop, blaxel, cloudflare (default).`, 45 ); 46 process.exit(1); 47 } 48 49 if (provider === "sprites") { 50 const spriteToken = process.env.SPRITE_TOKEN; 51 if (!spriteToken) { 52 consola.error( 53 "SPRITE_TOKEN environment variable is required for Sprites provider.", 54 ); 55 process.exit(1); 56 } 57 providerOptions.spriteToken = await encrypt(spriteToken); 58 providerOptions.redactedSpriteToken = redact(spriteToken); 59 } 60 61 if (provider === "daytona") { 62 const daytonaApiKey = process.env.DAYTONA_API_KEY; 63 const daytonaOrganizationId = process.env.DAYTONA_ORGANIZATION_ID; 64 if (!daytonaApiKey || !daytonaOrganizationId) { 65 consola.error( 66 "DAYTONA_API_KEY and DAYTONA_ORGANIZATION_ID environment variables are required for Daytona provider.", 67 ); 68 process.exit(1); 69 } 70 providerOptions.daytonaApiKey = await encrypt(daytonaApiKey); 71 providerOptions.redactedDaytonaApiKey = redact(daytonaApiKey); 72 providerOptions.daytonaOrganizationId = daytonaOrganizationId; 73 } 74 75 if (provider === "deno") { 76 const denoDeployToken = process.env.DENO_DEPLOY_TOKEN; 77 if (!denoDeployToken) { 78 consola.error( 79 "DENO_DEPLOY_TOKEN environment variable is required for Deno provider.", 80 ); 81 process.exit(1); 82 } 83 providerOptions.denoDeployToken = await encrypt(denoDeployToken); 84 providerOptions.redactedDenoDeployToken = redact(denoDeployToken); 85 } 86 87 if (provider === "vercel") { 88 const vercelApiToken = process.env.VERCEL_API_TOKEN; 89 const vercelProjectId = process.env.VERCEL_PROJECT_ID; 90 const vercelTeamId = process.env.VERCEL_TEAM_ID; 91 if (!vercelApiToken || !vercelProjectId || !vercelTeamId) { 92 consola.error( 93 "VERCEL_API_TOKEN, VERCEL_PROJECT_ID and VERCEL_TEAM_ID environment variables are required for Vercel provider.", 94 ); 95 process.exit(1); 96 } 97 providerOptions.vercelApiToken = await encrypt(vercelApiToken); 98 providerOptions.redactedVercelApiToken = redact(vercelApiToken); 99 providerOptions.vercelProjectId = vercelProjectId; 100 providerOptions.vercelTeamId = vercelTeamId; 101 } 102 103 if (provider === "modal") { 104 const modalTokenId = process.env.MODAL_TOKEN_ID; 105 const modalTokenSecret = process.env.MODAL_TOKEN_SECRET; 106 if (!modalTokenId || !modalTokenSecret) { 107 consola.error( 108 "MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables are required for Modal provider.", 109 ); 110 process.exit(1); 111 } 112 providerOptions.modalTokenId = await encrypt(modalTokenId); 113 providerOptions.redactedModalTokenId = redact(modalTokenId); 114 providerOptions.modalTokenSecret = await encrypt(modalTokenSecret); 115 providerOptions.redactedModalTokenSecret = redact(modalTokenSecret); 116 } 117 118 if (provider === "e2b") { 119 const e2bApiKey = process.env.E2B_ACCESS_TOKEN || process.env.E2B_API_KEY; 120 if (!e2bApiKey) { 121 consola.error( 122 "E2B_API_KEY environment variable is required for E2B provider.", 123 ); 124 process.exit(1); 125 } 126 providerOptions.e2bApiKey = await encrypt(e2bApiKey); 127 providerOptions.redactedE2bApiKey = redact(e2bApiKey); 128 } 129 130 if (provider == "hopx") { 131 const hopxApiKey = process.env.HOPX_API_KEY; 132 if (!hopxApiKey) { 133 consola.error( 134 "HOPX_API_KEY environment variable is required for HopX provider.", 135 ); 136 process.exit(1); 137 } 138 providerOptions.hopxApiKey = await encrypt(hopxApiKey); 139 providerOptions.redactedHopxApiKey = redact(hopxApiKey); 140 } 141 142 if (provider == "runloop") { 143 const runloopApiKey = process.env.RUNLOOP_API_KEY; 144 if (!runloopApiKey) { 145 consola.error( 146 "RUNLOOP_API_KEY environment variable is required for RunLoop provider.", 147 ); 148 process.exit(1); 149 } 150 providerOptions.runloopApiKey = await encrypt(runloopApiKey); 151 providerOptions.redactedRunloopApiKey = redact(runloopApiKey); 152 } 153 154 try { 155 const sandbox = await Sandbox.create({ 156 name, 157 base: 158 base ?? 159 "at://did:plc:aturpi2ls3yvsmhc6wybomun/io.pocketenv.sandbox/openclaw", 160 provider: provider ?? "cloudflare", 161 repo, 162 providerOptions, 163 }); 164 if (!ssh) { 165 consola.success( 166 `Sandbox created successfully: ${c.primary(sandbox.data.name)}`, 167 ); 168 return; 169 } 170 await sandbox.waitUntilRunning(); 171 await connectToSandbox(sandbox.data.name); 172 } catch (error) { 173 consola.error(`Failed to create sandbox: ${error}`); 174 } 175} 176 177export default createSandbox;