You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(eve)!: make the Upstash Box sandbox backend actually usable (#6)
* refactor(eve)!: sandbox config is Box's BoxConfig (drop vcpus/networkPolicy knobs)
The `upstash()` sandbox backend invented Vercel-shaped config (`resources.vcpus`,
runtime strings like "node24", an Eve-shaped `networkPolicy`) that didn't match
Upstash Box. Take the real `@upstash/box` `BoxConfig` verbatim instead.
- `UpstashBackendConfig = Omit<BoxConfig, "networkPolicy">` — pass `runtime`,
`size`, `apiKey`, `keepAlive`, `initCommand`, `env`, `skills`, `mcpServers`,
`timeout`, … exactly as you would to `Box.create({...})`. Removed the
`resources.vcpus`→size mapping and the runtime-string coercion (use Box's
`Runtime`/`BoxSize` directly).
- `networkPolicy` is no longer a config knob: egress is enforced deny-all
atomically at creation (folded into `boxConfig()`, dropping the extra
post-create `updateNetworkPolicy` round-trips) and opened only per-session via
Eve's `use({ networkPolicy })`. Reworked the live egress test to open via the
session `use()` flow.
- Updated the eve README, eve-demo sandbox, and docstring examples; folded into
the pending harden-tenant-isolation changeset.
* fix(eve): reuse prewarmed Box snapshots via Redis; bridge /workspace path
Two sandbox bugs surfaced running an agent against Upstash Box.
1. Two boxes were created and the first (prewarmed) one was unused — its seed
files never reached the session. `prewarm` (build/startup) recorded the
template snapshot only in an in-memory map, which `create` (a different
process, per request) can't see; Box has no static snapshot lookup, so create
always fell back to a fresh, empty `Box.create`. Store `templateKey → snapshotId`
in a durable Redis registry (`agentkit:sandbox:template:<name>:<templateKey>`,
`redis` defaults to `Redis.fromEnv()`) so create restores the prewarmed
snapshot. `prewarm` also no longer builds a throwaway box when there's nothing
to bake (no seed files / bootstrap), and stale-snapshot restores fall back to
a fresh box.
2. The agent ran `find /workspace …` but Box sessions live in `/workspace/home`
(`/workspace` is off-limits). Eve hardcodes `/workspace` as its tool root, so
the backend now bridges it to `/workspace/home` in both `resolvePath` (file
ops) and raw commands (exported `toBoxPath` / `rewriteWorkspacePaths`).
Config gains optional `redis`/`templatePrefix` (stripped before `Box.create`).
Added offline path-bridge tests and a live Box+Redis test proving a second
backend instance reuses the prewarmed snapshot. Updated README, docstrings,
CLAUDE.md, and the changeset.
* fix(eve): reuse one Box per session; fix dispose/keepAlive; URL-safe path rewrite
Running an agent against Box created a new box on every session open (the logs
showed three "opening sandbox session" per turn).
- `create` now reattaches to the box from `input.existingMetadata.boxId`
(`Box.get`) before falling back to the template snapshot or a fresh box. Eve
re-opens a session many times per turn and hands back the box id we record in
`captureState`, so without this every open spun a new box.
- `dispose` is now a no-op (matching Eve's Vercel backend): the box must survive
for the next open to reattach. The old `dispose` called `box.pause()`, which
THROWS for keep-alive boxes ("Keep-alive boxes cannot be paused"), so it both
failed and defeated reuse.
- `keepAlive` now defaults to `false` (Box's pause-based idle lifecycle): idle
boxes auto-pause and are reaped, so a no-op dispose doesn't leak. `true` opts
into an always-running box the caller manages.
- `rewriteWorkspacePaths` is now URL-safe: a lookbehind stops it rewriting
`/workspace` inside URLs/relative paths (e.g. `curl host/workspace/x`), while
still mapping genuine `/workspace` path tokens to `/workspace/home`.
Added live tests for box reuse across opens and for the URL-safe rewrite; live
tests now delete boxes explicitly since dispose no longer does. Updated README,
docstrings, CLAUDE.md, and the changeset.
Copy file name to clipboardExpand all lines: .changeset/harden-tenant-isolation.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,9 @@ Tenant-isolation hardening, a type-safe reactive search index, and a consistent
12
12
-`AgentMemory` requires a non-empty `userId` on every call (no silent shared bucket) and rejects a `:` in `userId`; `add`/`recall` take a single object param.
13
13
-`ToolCache` keys are `<prefix>:<userId>:<toolName>:<hash>` — scoped per user, then per tool; `userId`/`toolName` are rejected if they contain `:`.
14
14
-`createRateLimit`/`createRateLimitAuth` require an explicit `limiter` (removed `limit`/`window`); eve's `createRateLimitAuth` requires `identifier` (no implicit global bucket) and counts only `POST` requests, so a turn (a message `POST` plus its follow-up stream `GET`) is charged once, not twice.
15
-
- The eve sandbox denies network egress by default.
15
+
- The eve sandbox denies network egress by default. Its `upstash()` backend config is now the `@upstash/box``BoxConfig` passed through verbatim (`runtime`/`size`/`apiKey`/`keepAlive`/`initCommand`/`env`/`skills`/…) plus an optional `redis`/`templatePrefix` — the invented `resources.vcpus` hint and runtime-string coercion (`"node24"`) are removed (use `runtime`/`size` as Box expects), and `networkPolicy` is no longer a config knob (egress is governed by the deny-all default plus per-session `use({ networkPolicy })`).
16
+
- The eve sandbox now reuses prewarmed Box snapshots correctly: the `templateKey → snapshotId` map is stored in a durable Redis registry (Box has no static snapshot lookup, and `prewarm`/`create` run in different processes), so `create` restores the prewarmed template instead of spinning a fresh, empty box. `prewarm` builds no box when there's nothing to bake. It also bridges Eve's `/workspace` root to Box's `/workspace/home` working directory in both file ops and raw commands, so the agent's `find`/`grep`/file tools hit the right directory.
17
+
- The eve sandbox now reuses one box per conversation instead of creating a new box on every session open: `create` reattaches to the box from `existingMetadata` (Eve re-opens a session many times per turn) and `dispose` no longer tears the box down. `keepAlive` defaults to `false` (Box's pause-based idle lifecycle), so idle boxes are auto-paused/reaped rather than leaked.
0 commit comments