feat(web,desktop): coding agents read the web through the planning model's own hosted search and page read (one runtime 4/n)

Merged
DA
6d ago
+335-41

One-agent-runtime migration, PR 4 (docs/proposals/one-agent-runtime.md §5, Decision 2: "The hosted search_web and read_web_page for every role, on Luke's key and metered").

What

The planning model and its worker searched the web with Luke's hosted pair (public-research.ts):

  • search_web: one OpenAI Responses call on Luke's key. The query is screened for anything shaped like a credential and must be one line of public words. It answers found only with at least one cited public URL, and it's budgeted per turn and counted on the account's meter.
  • read_web_page: a GET of one public URL that refuses private, loopback, link-local and reserved addresses, budgeted per turn.

Coding agents and their workers used eve's provider-run web_search and web_fetch instead, with none of that screening, budget or count. Now every role uses the hosted pair:

  • Tool files. coder/tools/search_web.ts and read_web_page.ts, plus the worker's own two, replace the four web_search/web_fetch files. Each calls the edge door runResearchTool (coder/host.ts) under the agent's admission (admit for the agent, admitDelegated for the worker). The door runs CoderHost.research, which builds the same ResearchCall the brain does: the turn's budget, Luke's OpenAI access (researchOpenAiOf, the brain's own model), and the account's meter.
  • CoderHostSeams.research(userId) supplies that access and the meter.
  • CODER_TOOL and WORKER_TOOL_NAMES name search_web and read_web_page.
  • Old transcripts keep reading. RETIRED_CODER_TOOL keeps web_search and web_fetch in CODER_TOOL_SET, so a transcript written before reads back unchanged. The desktop still draws those rows, and the brain's summary of an agent (coding-agent-tools.ts) still names them.
  • Context estimate. context-estimate.ts now counts the pair's declarations among the authored tools, since they're no longer provider-run.
  • Prompts. The coder's and its worker's instructions name the pair and the rule the planning worker already had: never put the repository's code, names or paths into a query.
  • Desktop. tool-call-model.ts draws search_web by its query and read_web_page by the page's name, with its text as the body.

Tests

  • tests/coder-host.test.ts, new: a coding agent's search on a deployment with no key is refused in the hosted search's own words. A page read of https://127.0.0.1/admin is refused as not public and never fetched.
  • tests/coder-agent.test.ts: the authored tools, plus the retired names and the integrations' calls, are exactly the writer's tool set, and no retired name is authored.
  • tool-call-model.test.ts, new: the hosted pair draws as web reads.
  • The web suite (154 files, 1,316 tests) and src/renderer/planning pass. The offline brain and coder evals pass against a local Postgres; the coder eval builds the root with the new tool files. Lint and repository checks pass.

CI could not verify the Mac UI: CI builds nothing for the Mac, and ./scripts/verify.sh was not run (LUKE-159 is the manual Mac pass). The only desktop change is the two new rows' words, covered by the model test.

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review