feat(chat-workflow): port bash sandbox tool + wire experimental_context (PR 4, slim)
Merged
SW
6mo ago+615+615+012345678901234567890123456789-30-30-01234567890123456789
Summary
Slim PR 4 of the open-agents → api port. Ports the `bash` sandbox tool from open-agents and wires it through the workflow via streamText's `experimental_context`. Proves the entire tool-execution machinery works end-to-end.
Scope held deliberately small — one tool + wiring — so the wire-up is reviewable in isolation. Remaining 10 tools (read, write, grep, glob, todo, task, ask_user_question, skill, fetch + composite-tool infra) port in follow-up PRs.
New code
- `lib/agent/tools/utils.ts` — AgentContext type, `isAgentContext` guard, `getSandbox()` that reconnects via `connectVercel(state)` per call
- `lib/agent/tools/buildRecoupExecEnv.ts` — `{ RECOUP_ACCESS_TOKEN, RECOUP_ORG_ID }` env builder
- `lib/agent/tools/bashTool.ts` — port adapted to api's Sandbox interface. Injects recoup env on foreground execs only (detached processes outlive the prompt → no token leak)
- `lib/agent/buildAgentTools.ts` — factory returning the agent's tool record (one-line append for future tools)
Wire-up
- `runAgentStep` accepts `agentContext`, passes to `streamText({ experimental_context })`. Uses `stopWhen: stepCountIs(25)` so streamText drives the tool-call loop internally — no outer workflow loop needed
- `handleChatWorkflowStream` derives `recoupOrgId` from `session.clone_url` via `extractOrgId`, builds `AgentContext` with `session.sandbox_state` + `validated.authToken`, passes to `start(workflow)`
Tests
- 23 new unit tests (utils, buildRecoupExecEnv, bashTool, factory)
- Full suite: 2978/2978 pass (+23)
- Lint clean
- Production build succeeds (was the bottleneck in PR 3)
- E2E preview verification pending (will post in a follow-up comment once deploy lands)
🤖 Generated with Claude Code
Summary by cubic
Ports the bash sandbox tool and threads agent context through streamText’s experimental_context to enable end-to-end tool execution in the chat workflow. Uses a shared CHAT_AGENT_STOP_WHEN so the model completes the tool loop before replying.
-
New Features
- Added
bashtool with input schema, cwd resolution, timeout/truncation, anddetachedsupport. - Introduced
AgentContext,isAgentContext, andgetSandbox(); tools reconnect viaconnectVercel(state)per call. - Added
buildRecoupExecEnv()to injectRECOUP_ORG_IDfor foreground execs only. - Added
buildAgentTools()returning{ bash }forstreamText({ tools }). - Updated
runAgentStepto passexperimental_context, register tools, and setstopWhen: CHAT_AGENT_STOP_WHEN;handleChatWorkflowStreambuildsagentContextfromsession.sandbox_state,DEFAULT_WORKING_DIRECTORY, and derivedrecoupOrgId.
- Added
-
Refactors
- Extracted
CHAT_AGENT_STOP_WHEN(111) inlib/chat/const.ts; used by both/api/chatand workflow to let a single turn cover model → tool → result → model. - Removed dangerous-command approval and
needsApprovalfrombash. - Removed token from context; no
recoupAccessTokenexposure. - Tightened
isAgentContextvalidation; split prior utils intoAgentContext.ts,isAgentContext.ts,getSandbox.ts.
- Extracted