feat(chat): cut workflow POST over to recoup-api /api/chat/workflow
Closes #42.
Summary
All five backend cutover bundles landed on recoup-api (cross-validation evidence in monorepo PROGRESS.md). Wire format is byte-compatible with what this client emits and consumes today, so the flip is one URL constant + one new headers callback.
Changes
| File | What |
|---|---|
apps/web/lib/chat/chat-api-client.ts | CHAT_API_POST_PATH repointed from relative /api/chat → ${RECOUPABLE_API_BASE_URL}/api/chat/workflow. Reuses the existing prod/test split helper. |
apps/web/app/.../hooks/use-session-chat-runtime.ts | Added headers callback on AbortableChatTransport that attaches the Privy JWT as Authorization: Bearer ... so recoup-api's validateAuthContext accepts the cross-origin request. The same JWT continues to ride in the request body (recoupAccessToken field) — recoup-api uses that to populate the sandbox env's RECOUP_ACCESS_TOKEN (Bundle A.4 plumbing). |
Wire-format compatibility verified end-to-end
- ✅
message-metadatachunks (api PR #592) - ✅ task-tool async-generator yield sequence (api PR #594)
- ✅ Environment section + cwd in system prompt (api PR #597)
- ✅ Anthropic prompt cache control (api PR #599) — Bundle A.6 dropped Turn 2 cost ~72%
- ✅ Privy JWT → sandbox
RECOUP_ACCESS_TOKENenv (api PR #601) —recoup-apiskill curl examples now authenticate
Known partial degradation (NOT regressions blocking this PR, per direction)
| Why | |
|---|---|
| Stop button can't cancel a recoup-api workflow run | POST /api/chat/{chatId}/stop still routes to open-agents' own backend, but the run-id lives on recoup-api's Vercel Workflow runtime — open-agents' getRun(runId).cancel() can't reach it. Workflow keeps spending tokens until natural completion. |
| Refresh-mid-stream loses the in-flight message | GET /api/chat/{chatId}/stream still routes to open-agents — has no record of recoup-api's runs, returns null. |
Both unblock once the matching sub-routes are ported to recoup-api (separate effort).
Test plan
- Typecheck:
turbo typecheckclean across all workspaces - Lint:
bun run checkpasses - Smoke test on preview: send a fresh message → expect 200 stream from
recoup-api.vercel.app(notsandbox.recoupable.com/api/chat), text-deltas render, message-metadata cost badge appears - Follow-up turn: verify Anthropic cache reuse (turn 2 cost ~10× cheaper than turn 1)
- recoup-api skill: invoke
/recoup-api→ expect HTTP 200 + account_id (not "RECOUP_ACCESS_TOKEN is not set") - Tool calls: bash, task subagent, ask_user_question — all render in UI
- Known-broken paths (acknowledged): stop button + page-refresh-mid-stream
Rollback
Single-line revert of CHAT_API_POST_PATH in chat-api-client.ts.
🤖 Generated with Claude Code
Summary by cubic
Switched chat workflow POSTs, sandbox provisioning, and reconnect/status polling to recoup-api with Privy JWT auth, and stopped clobbering sandbox_state on cross‑project misses. Wire format is unchanged; stop and mid‑stream resume still hit the old backend and are temporarily degraded.
-
Refactors
- Repointed
CHAT_API_POST_PATHto${RECOUPABLE_API_BASE_URL}/api/chat/workflow;AbortableChatTransportaddsAuthorization: Bearer <Privy JWT>and keepsrecoupAccessTokenin the body. - Moved provisioning to
${RECOUPABLE_API_BASE_URL}/api/sandbox;createSandbox()now sends{ repoUrl, sessionId }, accepts an optional token, anduseSandboxCreate()fetches a fresh Privy token per call. - Repointed sandbox
reconnectandstatuspolling to${RECOUPABLE_API_BASE_URL}/api/sandbox/*withAuthorization: Bearer. - Removed
resolveSandboxCredentials()and its usages; dropped unusedbranch/isNewBranch/sandboxTypeparams fromcreateSandbox()and consumers. Added tests for sandbox creation request shape and auth header.
- Repointed
-
Bug Fixes
- Stopped writing hibernated/cleared
sandbox_stateon localdiff,files,files/content, andskillsroutes when a sandbox appears unavailable;recoup-apiremains the source of truth (routes still return 409).
- Stopped writing hibernated/cleared
Summary by CodeRabbit
-
New Features
- Cross-origin sandbox and chat calls now include optional Bearer token authorization and route to the external recoup-api endpoints.
-
Bug Fixes
- Improved sandbox credential resolution and ensured credentials are applied when present.
- Chat transport now sends authorization header for outbound requests when a token is available.
-
Tests
- Added tests covering credential resolution and sandbox creation request behavior.