Files
649c224f3c feat(web-search): add AI/ML API Toolbox with safe error reporting (#2465)
* feat(web-search): add AI/ML API Toolbox as an explicit search backend

Add an `aimlapi` web search provider that runs the AI/ML API Toolbox tool
`web/search` (POST https://tools.aimlapi.com/v1/tools/run). It reuses the
key the AI/ML API model provider already has (AIMLAPI_API_KEY, or the
route's OPENAI_API_KEY fallback while OPENAI_BASE_URL is the canonical
AI/ML API endpoint), so a user on that provider has nothing to paste.

Every run is billed to the user's AI/ML API balance, so the backend is
explicit-only: it is not in the auto chain, and an AIMLAPI_API_KEY alone
never routes searches through it. Each run carries max_cost_usd 0.025.

- Map output.results[] (url/title/snippet/published_at) onto search hits,
  prefixing the snippet with the publication date.
- Send allowed_domains as include_domains; apply both domain lists to the
  results like the other backends (the tool has no exclude field).
- Poll GET /v1/tools/runs/{id} after a 202 until the run ends, within the
  web search timeout; report is_error runs and HTTP error codes.
- Send the key and the X-AIMLAPI-Source / X-AIMLAPI-Partner-ID attribution
  headers only to tools.aimlapi.com, checked by exact hostname.
- /search aimlapi selects it only when the key is present and states the
  billing; /search key|remove-key aimlapi refuse, because saving
  AIMLAPI_API_KEY to the global env would also switch the model provider.
- Document the backend next to the other search providers.

* fix(web-search): never send a proxy profile's key to the AI/ML API Toolbox

An aimlapi provider profile that points at the user's own proxy exports
the proxy's credential as AIMLAPI_API_KEY, with
CLAUDE_CODE_PROVIDER_ROUTE_ID=aimlapi and OPENAI_BASE_URL set to the proxy.
The search provider returned AIMLAPI_API_KEY unconditionally, so
/search aimlapi would have sent that proxy credential to tools.aimlapi.com.

Resolve no key in that case: the backend reports itself as not
configured, /search aimlapi refuses the selection, and a search fails
with the not-configured error before any request is made.

* fix(web-search): link the published AI/ML API setup page from /search

The npm package does not ship docs/, so the /search key|remove-key aimlapi
message pointed at a path an installed user cannot open. Link the page on
GitHub instead and update the matching test expectation.

* fix(web-search): refuse redirects on Toolbox requests and pin the cost cap

Both Toolbox requests carry the key and the attribution headers, but the
hostname check only covered the first URL. Send them with redirect: 'error'
so no redirect hop can receive the headers, and assert that in the run and
poll tests plus a new test where a redirect fails after a single request.

Pin the documented $0.025 max_cost_usd in the request-body test instead of
comparing against the exported constant.

* fix(web-search): redact echoed AI/ML API credentials in search errors

* docs(web-search): describe the requested AI/ML API cost limit

* docs(web-search): clarify variable pricing and credential reuse

* fix(web-search): honor AI/ML API endpoint alias

* test(search): isolate provider credentials per test

* fix(web-search): reuse individual AI/ML API pool credentials

---------

Co-authored-by: Stan <stan@aimlapi.com>
Co-authored-by: Hugo <hugo@aimlapi.com>
2026-10-28 21:35:43 -07:00
..