feat(pi): install Bun in cloud sandboxes (#6123)

Co-authored-by: Bill Leoutsakos <billleoutsakos@Bills-MacBook-Pro.local>
This commit is contained in:
Bill Leoutsakos
2026-07-31 12:45:13 -07:00
committed by GitHub
co-authored by Bill Leoutsakos
parent 5c29d833af
commit c0b19da782
4 changed files with 18 additions and 7 deletions
@@ -211,7 +211,7 @@ The one case neither layer can rescue is a *first* prompt that already exceeds t
### Create PR [#setup-cloud-pr]
Create PR runs in a sandbox image with the Pi CLI and git baked in.
Create PR runs in a sandbox image with the Pi CLI, Git, Node.js, and Bun baked in. Repository dependencies are not preinstalled; Pi can run `bun install` when a repository needs them.
1. **Enable sandbox execution.** On self-hosted Sim, set `E2B_ENABLED=true`, `E2B_API_KEY`, `E2B_PI_TEMPLATE_ID` (the Pi template id), and `NEXT_PUBLIC_E2B_ENABLED=true` (this reveals Create PR, Update PR, and Review Code in the UI). Build the template with `bun run apps/sim/scripts/build-pi-e2b-template.ts`. These modes stay hidden until `NEXT_PUBLIC_E2B_ENABLED` is set.
@@ -28,9 +28,10 @@ import { Daytona, Image } from '@daytona/sdk'
import { getErrorMessage } from '@sim/utils/errors'
import {
PI_APT,
PI_BUN_VERSION_ASSERT,
PI_GLOBAL_NPM_PACKAGES,
PI_NODE_MAJOR,
PI_NODE_VERSION_ASSERT,
PI_NPM,
PI_SANDBOX_CPU_COUNT,
PI_SANDBOX_MEMORY_GB,
} from '@/scripts/pi-sandbox-packages'
@@ -63,7 +64,8 @@ export const piImage = Image.base(BASE_IMAGE).runCommands(
// ships an older Node fails here rather than at the first agent run.
`apt-get update && curl -fsSL https://deb.nodesource.com/setup_${PI_NODE_MAJOR}.x | bash - && ${APT_PREFIX} nodejs && rm -rf /var/lib/apt/lists/* && ${PI_NODE_VERSION_ASSERT}`,
`apt-get update && ${APT_PREFIX} ${PI_APT.join(' ')} && rm -rf /var/lib/apt/lists/*`,
`npm install -g ${PI_NPM.join(' ')}`,
`npm install -g ${PI_GLOBAL_NPM_PACKAGES.join(' ')}`,
PI_BUN_VERSION_ASSERT,
// The clone target. E2B's base ships a world-writable /code; Pi writes to
// /workspace (cloud-review-tools.ts:14), so create it explicitly.
'mkdir -p /workspace'
+4 -2
View File
@@ -19,9 +19,10 @@
import { defaultBuildLogger, Template, waitForTimeout } from '@e2b/code-interpreter'
import {
PI_APT,
PI_BUN_VERSION_ASSERT,
PI_GLOBAL_NPM_PACKAGES,
PI_NODE_MAJOR,
PI_NODE_VERSION_ASSERT,
PI_NPM,
PI_SANDBOX_CPU_COUNT,
PI_SANDBOX_MEMORY_MB,
} from '@/scripts/pi-sandbox-packages'
@@ -38,7 +39,8 @@ const piTemplate = Template()
.fromTemplate('code-interpreter-v1')
.runCmd(INSTALL_NODE_COMMAND, { user: 'root' })
.aptInstall([...PI_APT])
.npmInstall([...PI_NPM], { g: true })
.npmInstall([...PI_GLOBAL_NPM_PACKAGES], { g: true })
.runCmd(PI_BUN_VERSION_ASSERT, { user: 'root' })
.setStartCmd(START_COMMAND, waitForTimeout(1_000))
async function main() {
+9 -2
View File
@@ -13,8 +13,12 @@
* owns the Pi block.
*/
/** Exact first-party Pi versions mirrored from bun.lock — image builds run npm independently. */
export const PI_NPM = [
/** Bun version mirrored from the root packageManager field. */
export const PI_BUN_VERSION = '1.3.13'
/** Exact global package versions mirrored from package.json and bun.lock. */
export const PI_GLOBAL_NPM_PACKAGES = [
`bun@${PI_BUN_VERSION}`,
'@earendil-works/pi-coding-agent@0.80.10',
'@earendil-works/pi-agent-core@0.80.10',
'@earendil-works/pi-ai@0.80.10',
@@ -51,6 +55,9 @@ export const PI_NODE_MAJOR = 22
export const PI_NODE_VERSION_ASSERT =
'node -e "const [major, minor] = process.versions.node.split(\'.\').map(Number); if (major < 22 || (major === 22 && minor < 19)) process.exit(1)"'
/** Fails the build loudly if the sandbox does not contain the repository's Bun version. */
export const PI_BUN_VERSION_ASSERT = `test "$(bun --version)" = "${PI_BUN_VERSION}"`
/**
* The review tools run `python3 /workspace/sim-review-tools.py`
* (`cloud-review-tools.ts:15`). E2B's `code-interpreter-v1` base ships Python, so