feat(chat-workflow): port bash sandbox tool + wire experimental_context (PR 4, slim)

Merged
SW
6mo ago
+615-30

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 bash tool with input schema, cwd resolution, timeout/truncation, and detached support.
    • Introduced AgentContext, isAgentContext, and getSandbox(); tools reconnect via connectVercel(state) per call.
    • Added buildRecoupExecEnv() to inject RECOUP_ORG_ID for foreground execs only.
    • Added buildAgentTools() returning { bash } for streamText({ tools }).
    • Updated runAgentStep to pass experimental_context, register tools, and set stopWhen: CHAT_AGENT_STOP_WHEN; handleChatWorkflowStream builds agentContext from session.sandbox_state, DEFAULT_WORKING_DIRECTORY, and derived recoupOrgId.
  • Refactors

    • Extracted CHAT_AGENT_STOP_WHEN (111) in lib/chat/const.ts; used by both /api/chat and workflow to let a single turn cover model → tool → result → model.
    • Removed dangerous-command approval and needsApproval from bash.
    • Removed token from context; no recoupAccessToken exposure.
    • Tightened isAgentContext validation; split prior utils into AgentContext.ts, isAgentContext.ts, getSandbox.ts.