Skip to content

Feat/update nextjs 16.2#168

Open
recoupableorg wants to merge 20 commits intovercel-labs:mainfrom
recoupable:feat/update-nextjs-16.2
Open

Feat/update nextjs 16.2#168
recoupableorg wants to merge 20 commits intovercel-labs:mainfrom
recoupable:feat/update-nextjs-16.2

Conversation

@recoupableorg
Copy link
Copy Markdown

No description provided.

sweetmantech and others added 20 commits February 9, 2026 06:42
Replace the in-memory bash interpreter with Vercel Sandbox (Firecracker
microVMs) for the server-side AI agent. Source files are uploaded to the
VM via writeFiles(). Browser-side terminal still uses just-bash/browser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
/home/user is not writable inside the VM, causing writeFiles to fail
with "Cannot mkdir: Permission denied".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gate the terminal behind Privy login so users must authenticate before
interacting. The access token is sent as a Bearer token with every
/api/agent request, and the API route returns 401 if the header is missing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Privy authentication to website example
Remove all legacy just-bash interpreter code (src/, tests, configs, CI
workflows, examples/bash-agent, examples/custom-command) and promote
examples/website to the repository root. This repo is now solely the
Recoup Bash website.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix package.json import path in terminal-content.ts (was ../../../../, now ../../)
- Remove generate script that depended on legacy repo files (README.md, LICENSE, AGENTS.npm.md)
- Remove pnpm generate from dev and build commands
- terminal-content.ts is now a static file with baked-in content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…p-bash-move-exampleswebsite-to-root-of-the-project

Move examples/website to root of project
The `finally` block was calling `sandbox.stop()` immediately when
`createAgentUIStreamResponse` returned, before the client consumed
the stream. This killed the sandbox before any agent tool calls
could execute, causing all bash commands to fail with
"[Tool Error] Tool execution error".

Now uses a TransformStream wrapper with `pipeTo().finally()` to
ensure sandbox cleanup happens after streaming completes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…t-commands-failing-is-this-an-env-error

fix: defer sandbox cleanup until stream completes
* feat: load sandbox from Recoup API snapshot

Use snapshot-based sandbox creation when available, eliminating the file
upload step. Falls back to fresh sandbox + file upload when no snapshot
exists or on any failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract sandbox creation into lib/sandbox/createNewSandbox.ts

Move snapshot resolution, sandbox creation, and file upload fallback
logic out of the route handler into a dedicated module (SRP).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: delegate sandbox creation to Recoup API

Instead of fetching a snapshot_id and creating sandboxes directly,
call POST /api/sandboxes on the Recoup API which handles snapshot
resolution internally, then connect via Sandbox.get().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use env-based API URL to match Recoup-Chat pattern

Switch between prod and test Recoup API based on NEXT_PUBLIC_VERCEL_ENV,
matching the pattern in Recoup-Chat. Preview deployments now correctly
hit test-recoup-api.vercel.app instead of production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add timing logs to identify latency bottleneck

Log elapsed time for each step: POST /api/sandboxes, Sandbox.get,
createBashTool, and fallback paths. Will help diagnose the 20s gap
between sandbox creation and first bash execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: skip tool discovery in createBashTool with static prompt

Tool discovery runs `ls /usr/bin ...` in the sandbox which takes ~34s
due to sandbox warm-up after snapshot restore. Provide a static
toolPrompt to skip discovery entirely — the available tools on a
node22 sandbox are always the same.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: always upload source files regardless of sandbox source

The snapshot contains the user's Recoup Sandbox content, not the
just-bash/bash-tool source files. Write agent data files to the
sandbox in all cases so the agent can explore the source code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* revert: skip file upload when using snapshot sandbox

Only upload source files in the fallback path (fresh sandbox).
Snapshot sandboxes should have the needed files pre-baked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: warm up sandbox after snapshot restore

Run a no-op command (true) right after Sandbox.get() to absorb the
snapshot cold-start latency during setup rather than during the
agent's first tool call. This eliminates the long pause users see
after the first bash command appears on screen.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: create snapshot sandbox locally instead of via Sandbox.get

Use GET /api/sandboxes to fetch the snapshot_id, then create the
sandbox locally with Sandbox.create({ source: { type: "snapshot" } })
instead of POST + Sandbox.get(). This tests whether the 33s cold
start was caused by cross-project Sandbox.get() vs local creation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove dev timing logs and unused createSandbox

Clean up all [timing] console.log statements and the warm-up command.
Remove unused lib/recoup-api/createSandbox.ts (replaced by getSnapshotId).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add /new page with fresh sandbox for performance comparison

- /new page uses /api/agent/new which creates a fresh Sandbox.create()
  + file upload (no snapshot) for A/B comparison against snapshot path
- Terminal and agent-command accept configurable agentEndpoint prop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add git to static tool prompt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract shared agent logic into lib to follow DRY

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract shared TerminalPage component for auth boilerplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract handleAgentRequest to DRY route boilerplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: centralize AGENT_DATA_DIR in constants

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename createNewSandbox to createSnapshotSandbox

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract readSourceFiles into its own lib file

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use POST /api/sandboxes + Sandbox.get for snapshot sandbox

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: save sandbox snapshot before stopping after agent session

Replicates the snapshot-saving pattern from Recoup-Tasks so sandbox
state is preserved between sessions. After the agent stream finishes,
we call sandbox.snapshot() and PATCH /api/sandboxes with the snapshotId
before calling sandbox.stop().

Also adds CLAUDE.md with project-specific guidance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract handleAgentRequest into its own file (SRP)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use next/server after() to keep function alive for snapshot save

The previous fire-and-forget pattern in .finally() was racing against
Vercel's serverless function shutdown. The function would terminate
before sandbox.snapshot() and the PATCH call could complete, so
snapshots were never persisted. Using after() tells Vercel to keep
the function alive until the snapshot save finishes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: check for sandbox snapshot on login and trigger setup if missing

Adds useSetupSandbox hook that runs once after Privy authentication.
Checks GET /api/sandboxes for existing snapshots, and if none exist,
fires POST /api/sandboxes/setup in the background to provision a
GitHub repo + snapshot before the user starts using the terminal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: use usePrivy directly inside useSetupSandbox hook

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use NEXT_PUBLIC_VERCEL_ENV for Recoup API URL

Matches the existing pattern in lib/recoup-api/ — uses production URL
in prod and test URL otherwise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract RECOUP_API_URL into lib/consts.ts

Deduplicates the env-based URL logic from three files into a single
shared constant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: check for snapshot_id and github_repo before skipping setup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: read snapshot_id and github_repo from top-level response

These are top-level fields on the GET /api/sandboxes response, not
nested inside the sandboxes array.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract fetch calls into getSandboxes and setupSandbox libs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
refactor: make AGENTS.md source of truth, CLAUDE.md as symlink
Upgrades Next.js from 16.2.0-canary.26 to 16.2.1 (stable release). No
breaking changes per release notes — promotes from canary to stable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 21, 2026

Someone is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants