Repository navigation
feat(dev): set up the Cloud Agent sandbox for pnpm dev:start #7251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
eshurakov
wants to merge
35
commits into
main
Choose a base branch
from
kilo/tiny-chameleon-w2a
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
447382c
feat(dev): add Cloud Agent sandbox startup script
eshurakov 9082c33
fix(dev): preserve sandbox trust wrapper and bound compiler threads
eshurakov b283575
fix(dev): verify sandbox images and seed an offline test account
eshurakov 6e06b90
fix(dev): install Docker CLI and trust all sandbox image stages
eshurakov ab78819
feat(dev): persist browser setup and smoke-test sandbox login
eshurakov 921ab3d
fix(dev): bound sandbox setup waits and report image progress
eshurakov 7c237ed
fix(dev): enforce sandbox memory budgets and default to web stack
eshurakov cddb66f
fix(dev): avoid premature reclaim stalls within the hard memory cap
eshurakov 00f491d
fix(dev): rely on workload cap instead of restrictive Chromium flags
eshurakov 805d1d3
fix(dev): reserve enough web compile memory and batch browser smoke c…
eshurakov ddeb948
fix(dev): select the web heap budget by working directory
eshurakov 0e3b6ab
fix(dev): use the supported chrome browser engine name
eshurakov e7d6948
fix(dev): preserve resource wrappers through tmux service shells
eshurakov bf896aa
fix(dev): validate fresh test login and constrained builder configura…
eshurakov 8d0fad3
fix(dev): account for protected memory and recover stopped services
eshurakov 4e6629a
fix(dev): use heap-bounded webpack for sandbox web development
eshurakov b20016f
fix(dev): select webpack for filtered web package commands
eshurakov bc11ebc
fix(dev): consistently apply sufficient web heap within a six GiB cap
eshurakov f3bc0dc
fix(dev): reserve bounded capacity for the full web profile compile
eshurakov c99b43b
fix(dev): report sandbox startup memory admission requirements
eshurakov 41c51e0
fix(dev): fit default app budget within sandbox headroom
eshurakov 8fffb9a
fix(dev): smoke test lightweight landing and authenticated session
eshurakov 4d6ce05
fix(dev): explicitly assert seeded browser session authentication
eshurakov b68d970
fix(dev): require explicit browser authentication result before success
eshurakov 063d164
fix(dev): cap the startup workload at total sandbox memory minus the …
eshurakov 62dfa34
feat(dev): split sandbox setup from running the stack with pnpm dev:s…
eshurakov 572535c
fix(dev): keep values dev:start resolves when pnpm loads the sandbox env
eshurakov 9ef0295
fix(dev): release the BuildKit budget after each sandbox image build
eshurakov a924ee5
fix(dev): preserve a standalone pnpm binary before installing the wra…
eshurakov 7909ddc
fix(dev): resolve DNS for sandbox containers without IP forwarding
eshurakov f910993
feat(dev): let dev:start skip services with --without or KILO_DEV_WIT…
eshurakov 59b810b
fix(dev): redirect pinned sandbox DNS and skip unneeded agents services
eshurakov ff097ab
docs(dev): add cloud-agent-sandbox skill for the sandbox setup
eshurakov 8b4c0fe
docs(dev): document sandbox image readiness in cloud-agent-sandbox skill
eshurakov 5484173
feat(dev): prebuild Cloud Agent sandbox images during sandbox setup
eshurakov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| --- | ||
| name: cloud-agent-sandbox | ||
| description: Sets up and runs this monorepo inside a memory-constrained Kilo Cloud Agent sandbox with `.kilo/cloud-agent-setup.sh`. Use when working in a Cloud Agent sandbox, before starting local services there, after a sandbox restart, or when debugging the dev memory cap, Docker, DNS, fake login, agent-browser, or fake-LLM Cloud Agent sessions in the sandbox. | ||
| --- | ||
|
|
||
| # Cloud Agent sandbox | ||
|
|
||
| `.kilo/cloud-agent-setup.sh` prepares a Debian/Ubuntu Cloud Agent sandbox for | ||
| `pnpm dev:start`. It usually runs automatically when the machine starts. You can | ||
| run it at any time: reruns are safe and take about 20 s once the machine is set up. | ||
|
|
||
| Follow the `local-development` skill for ports, fake login, and service | ||
| management. This skill covers what is different in the sandbox. | ||
|
|
||
| ## Is setup done? | ||
|
|
||
| Sandbox restarts wipe Docker, the pnpm wrapper, the memory cgroup, and | ||
| `.wrangler/kilo-startup/`. The repository and `node_modules` survive. Check | ||
| before starting services: | ||
|
|
||
| ```bash | ||
| test -f .wrangler/kilo-startup/env \ | ||
| && grep -q kilo-cloud-agent-pnpm-wrapper "$(command -v pnpm)" \ | ||
| && docker info >/dev/null 2>&1 && echo ready | ||
| ``` | ||
|
|
||
| If this does not print `ready`, run setup from the repository root: | ||
|
|
||
| ```bash | ||
| bash .kilo/cloud-agent-setup.sh | ||
| ``` | ||
|
|
||
| A restarted machine takes about 6 minutes, mostly building the Cloud Agent | ||
| sandbox images; `node_modules` survives the restart. A rerun on a running | ||
| machine takes under 2 minutes, because images come from the build cache. A | ||
| machine without dependencies adds about 3 minutes for `pnpm install`. Setup stops at the first failure and prints | ||
| the line number. | ||
|
|
||
| ## What setup does | ||
|
|
||
| - Creates a memory cgroup for all dev workloads, capped at the sandbox memory | ||
| minus 2 GiB. Override the cap in MiB with `KILO_STARTUP_MEMORY_MB`; the | ||
| minimum is 3072. | ||
| - Installs Docker, Compose v2, tmux, Chromium, agent-browser, and dnsmasq. | ||
| Starts dockerd with its containers inside the cgroup and pulls images through | ||
| `mirror.gcr.io`. | ||
| - Installs a global `pnpm` wrapper. Inside this repository it moves the command | ||
| into the capped cgroup and loads `.wrangler/kilo-startup/env`. Outside the | ||
| repository it runs the real pnpm, saved at | ||
| `/usr/local/lib/kilo-cloud-agent/real-pnpm`, unchanged. | ||
| - Installs dependencies, creates `.env.local`, runs `pnpm test:db`, and seeds a | ||
| fake-login user with credits. | ||
| - Builds the eight Cloud Agent sandbox images by running `wrangler dev` for | ||
| `cloud-agent-next` on spare ports until `Container image(s) ready`. The log is | ||
| `.wrangler/kilo-startup/sandbox-images.log`. Skip this with | ||
| `KILO_STARTUP_SANDBOX_IMAGES=0`. | ||
| - It does not start the dev stack. | ||
|
|
||
| `.wrangler/kilo-startup/env` only sets defaults. Override a value by exporting | ||
| it before running pnpm. Do not edit the file: setup rewrites it. | ||
|
|
||
| ## Start services | ||
|
|
||
| Run every command from the repository root, so that pnpm is capped. | ||
|
|
||
| ```bash | ||
| pnpm dev:start --no-attach app # web app | ||
| pnpm dev:start --no-attach agents fake-llm # Cloud Agents with local fake inference | ||
| pnpm dev:status # services and ports | ||
| pnpm dev:stop | ||
| ``` | ||
|
|
||
| - `KILO_DEV_WITHOUT` in the env file skips agents services that fake-LLM sessions | ||
| on public repositories do not need: notifications, event-service, | ||
| webhook-agent-ingest, container-usage-meter, and git-token-service. That | ||
| leaves 7 services, about 3 GB when idle. Add services back with | ||
| `--without=<smaller list>`. `--without=` starts everything, but the full agents | ||
| stack does not fit in the cap. | ||
| - Expected warnings without those services: billing-heartbeat errors from the | ||
| skipped usage meter. GitHub-backed repositories need git-token-service and | ||
| GitHub App credentials, which the sandbox does not have. | ||
| - `--no-attach` returns once services are up: about 50 s for `app`. The first | ||
| page load compiles with Turbopack and takes about 30 s more. | ||
| - Wrangler rebuilds every sandbox image each time `cloud-agent-next` starts. | ||
| Images build in dockerd's own BuildKit, so unchanged images come from the | ||
| layer cache. Setup prebuilds them; without that, or after a Dockerfile change, | ||
| the build takes minutes. `cloud-agent-next` reports `up` before images are | ||
| ready, and sessions created meanwhile fail (`fetch failed` in the harness). | ||
| Wait for the build to finish: | ||
|
|
||
| ```bash | ||
| until grep -q 'Container image(s) ready' dev/logs/cloud-agent-next.log; do sleep 15; done | ||
| ``` | ||
| - `--reuse-running` currently refuses to reuse a session because the Stripe | ||
| forwarder is always skipped. Check `pnpm dev:status` instead. | ||
|
|
||
| ## Log in and use the browser | ||
|
|
||
| Setup seeds a verified user with credits. Its email is `KILO_TEST_USER_EMAIL` in | ||
| the env file. Shells outside the pnpm wrapper must load the env file first. It | ||
| also puts setup's `docker` wrapper on `PATH`, which keeps builds serialized and | ||
| inside the cap: | ||
|
|
||
| ```bash | ||
| source .wrangler/kilo-startup/env | ||
| agent-browser --session main open "http://localhost:3000/users/sign_in?fakeUser=$KILO_TEST_USER_EMAIL&callbackPath=/profile" | ||
| ``` | ||
|
|
||
| - Read the real port from `pnpm dev:status`. It is 3000 unless an offset applies. | ||
| - The env file points agent-browser at the installed Chromium with a 120 s | ||
| timeout. Confirm login with | ||
| `agent-browser --session main eval '(async () => (await (await fetch("/api/auth/session")).json()).user?.email)()'`. | ||
| - If a click fails because the element is covered, focus the input and use | ||
| `agent-browser press Enter`. | ||
| - Starting a Cloud Agent session from `/cloud` requires a connected GitHub or | ||
| GitLab provider, which the sandbox cannot set up. Create sessions with the | ||
| fake-LLM harness instead, then view them in the browser. | ||
|
|
||
| ## Fake-LLM Cloud Agent sessions | ||
|
|
||
| Start `agents fake-llm`, then follow `services/cloud-agent-next/test/e2e/README.md`. | ||
| Ports below are the defaults; check `pnpm dev:status`. | ||
|
|
||
| ```bash | ||
| WORKER_URL=http://localhost:8794 FAKE_LLM_URL=http://localhost:8811 \ | ||
| pnpm -s exec tsx services/cloud-agent-next/test/e2e/run.ts cold echo:hi | ||
| ``` | ||
|
|
||
| - Verified passing on the minimal stack: `cold echo:hi`, `cold-hot echo:hi`, | ||
| `chunked-streaming slow:5:50`, `queue-while-busy`, and | ||
| `--api=legacy cold-hot echo:legacy`. `llm-error boom` fails a retry-status | ||
| assertion that is unrelated to the sandbox. | ||
| - Each run leaves a sandbox container of about 750 MB until it stops for being | ||
| idle. Remove them between runs: | ||
| `docker rm -f $(docker ps -q --filter name=workerd-cloud-agent-next-dev-Sandbox)`. | ||
| - The first session after `dev:start` can fail model validation with a 503 | ||
| ("Model availability could not be verified"). Turbopack is still compiling | ||
| the validation route; retry once. | ||
| - To view harness sessions in the browser, set `E2E_USER_EMAIL` so runs reuse | ||
| one driver user. Mark that user verified, then fake-login as it and open | ||
| `/cloud/sessions`: | ||
|
|
||
| ```bash | ||
| docker compose -f dev/docker-compose.yml exec -T postgres psql -U postgres -d postgres -c \ | ||
| "UPDATE kilocode_users SET has_validation_stytch = true, completed_welcome_form = true WHERE google_user_email = '<driver email>'" | ||
| ``` | ||
|
|
||
| Sending a message to a harness session from the UI fails with | ||
| "Session not found". | ||
|
|
||
| ## Memory | ||
|
|
||
| The cap is a hard limit with no swap. When the workload nears it, the kernel | ||
| reclaims memory instead of killing processes: everything slows, and | ||
| `docker`, `tmux`, and `pnpm dev:stop` can hang. Check pressure with: | ||
|
|
||
| ```bash | ||
| cg=/sys/fs/cgroup/kilo-workloads/kilo-dev-$(basename "$PWD") | ||
| echo "$(( $(cat $cg/memory.current) / 1048576 )) MiB of $(( $(cat $cg/memory.max) / 1048576 )) MiB" | ||
| grep -E '^(high|max|oom_kill) ' $cg/memory.events | ||
| ``` | ||
|
|
||
| If the `high` or `max` count keeps rising, you are near the cap. Stop work you do | ||
| not need, remove idle sandbox containers, or start fewer services. Dev tooling is | ||
| heavy: wrangler and workerd use about 3 GB, and the pnpm parents and log filters | ||
| about 2 GB. | ||
|
|
||
| - Next.js dev (Turbopack) grows by 1 to 3 GB while compiling a route and gives | ||
| most of it back after about two minutes idle: 4.2 GB after login fell to | ||
| 2.8 GB, and 4.4 GB after `/cloud` fell to 2.0 GB. Opening many routes back to | ||
| back fills the cap before that happens. Pause between heavy routes. Next 16.3 | ||
| already defaults `experimental.turbopackMemoryEviction` to `auto`. | ||
| - High Redis, redis-http, or Postgres CPU means memory pressure, not load. Under | ||
| pressure, Redis used 6 s of user CPU and 1590 s of system CPU in 90 minutes: | ||
| the kernel kept evicting and re-reading its code pages. Compare with | ||
| `cat $cg/containers/*/cpu.stat`. Idle Redis without pressure uses under 1%. | ||
| - If Next.js is stuck above the cap, `pkill -9 -f '^[n]ext-server'`, then | ||
| `pnpm dev:restart nextjs`. | ||
|
|
||
| Run heavy commands such as builds, tests, and typechecks from inside the | ||
| repository, so that the wrapper caps them. pnpm outside the repository and | ||
| direct `node` or `npx` processes are not capped. | ||
|
|
||
| ## Docker networking and DNS | ||
|
|
||
| `/proc/sys` is read-only, so dockerd runs with `--ip-forward=false`: bridge | ||
| containers can reach only the host. Workerd also pins sandbox containers to | ||
| 1.1.1.1 and 8.8.8.8. Setup runs dnsmasq on the bridge gateway, 172.17.0.1, and | ||
| uses iptables to redirect all DNS from `docker0` to it. | ||
|
|
||
| A `git_network_failed` clone failure, or `Could not resolve host` inside a | ||
| sandbox, means this redirect is missing. Rerun setup, then check: | ||
|
|
||
| ```bash | ||
| iptables -t nat -S PREROUTING | grep 'dport 53' | ||
| pgrep -a dnsmasq | ||
| docker exec <sandbox container> git ls-remote https://github.com/octocat/Hello-World.git | ||
| ``` | ||
|
|
||
| ## Pitfalls | ||
|
|
||
| - `pkill -f next-server` also matches the shell that runs it. Use | ||
| `pkill -f '[n]ext-server'`. | ||
| - Do not prune Docker images or build cache. Rebuilding the Cloud Agent images | ||
| costs about 12 minutes. | ||
| - Lint setup changes with `shellcheck -S warning -e SC1090 .kilo/cloud-agent-setup.sh`. | ||
| Setup does not install ShellCheck; use `apt-get install -y shellcheck`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SUGGESTION: Rerun timing is now stale
This commit makes every
cloud-agent-setup.shrun startwrangler devand wait forContainer image(s) ready, which the new text below documents as taking "under 2 minutes" on a rerun. The earlier claim that reruns "take about 20 s once the machine is set up" no longer holds; update it so the two timings agree.Reply with
@kilocode-bot fix itto have Kilo Code address this issue.