Second review pass on the outbound proxy work.
The installed dispatcher was undici's EnvHttpProxyAgent, which reuses the HTTP
proxy for `https:` whenever no HTTPS proxy is present. That is exactly the state
this package resolves after refusing a SOCKS or malformed URL the user named for
`https:`, so the scheme the diagnostic reported as direct was tunnelled anyway.
The dispatcher is now an Agent whose per-origin factory calls `proxyForUrl`, so
routing and `proxyForUrl` cannot disagree by parsing the same list twice.
`childProxyEnv` returned only the names the user exported, which left a child
Node direct whenever the proxy came from `ALL_PROXY` or from cordis.yml — Node's
`NODE_USE_ENV_PROXY` reads neither — and stripped the merged loopback bypass so
the child sent its own localhost traffic to the proxy. A scheme the user named
in either casing still reaches the child exactly as written; one they named in
neither now carries the resolved value, and the bypass list is always the merged
one.
A nested install (the plugin mounted over the launcher's policy) recorded the
outer policy's published values as the user's, then cleared the record on
disposal, so every later child inherited the normalization instead. The record
now belongs to the outermost install and is restored, not dropped.
`web_fetch` read the active policy twice — once to skip address pinning, again
inside the transport — so a disposal landing between the two reads produced an
unpinned direct connection to a host nothing validated. One snapshot now decides
both.
Also: the node:http proxy test asserted a route the engines range does not always
have, and the gate could not see undici bound through `await import('undici')`,
the form this repository actually uses.
description, kind
| description | kind |
|---|---|
| Package map for the web access capability family: the search/fetch service, its provider backends, and the model-facing tools that consume them. | package-group |
web/ — web access capability family
English | 中文
Summary
The web/ group gives the harness web access — searching the web and fetching URLs — through one provider-neutral service (ctx.web) and the backends and tools that use it. A deployment mounts one or more backends — Exa, Perplexity, or DeepSeek for search, anonymous HTTP(S) for fetch — and the service picks a usable provider per operation, so the model-facing tools stay stable while backends come and go. Six packages split the family: the web/ service that owns provider selection and errors, three search backends, one fetch backend, and tool-web/, which exposes web_search and web_fetch to the model. The group owns web access only: no browsing or extraction, no per-URL policy, and each backend keeps its own resource caps. Search and fetch deliberately share one service so selection, cancellation, errors, and configuration have a single owner.
Table of Contents
Packages
Six packages play the web roles; the subsystem reference owns the exhaustive vocabulary and contracts.
| Package | Role | ctx key |
|---|---|---|
web/ |
Search/fetch service: search and fetch URLs through interchangeable backends, one selection and error policy | ctx.web |
web-search-exa/ |
Searches the web through Exa | registers on ctx.web |
web-search-perplexity/ |
Searches the web through Perplexity | registers on ctx.web |
web-search-deepseek/ |
Searches the web through DeepSeek native search | registers on ctx.web |
web-fetch-http/ |
Fetches public HTTP(S) pages anonymously | registers on ctx.web |
tool-web/ |
Exposes web_search and web_fetch to the model |
registers on ctx.tools |
Related documentation
Start with the subsystem reference for the shared vocabulary, then the design decision behind the single provider-selection service.
- Web subsystem — the search/fetch requests and results, provider availability,
WebError, and public-address enforcement. - Web capability seam decision — why search and fetch share one provider-selection service.
Dev Note
Working context for maintainers — click to expand
None.