An open API service indexing awesome lists of open source software.

https://github.com/code-yeongyu/pi-websearch

Provider-backed web search tool for pi-coding-agent with config-gated activation, TUI status, and source-aware results.
https://github.com/code-yeongyu/pi-websearch

brave coding-agent exa perplexity pi-coding-agent pi-extension pi-package serper tavily typescript web-search websearch

Last synced: 23 days ago
JSON representation

Provider-backed web search tool for pi-coding-agent with config-gated activation, TUI status, and source-aware results.

Awesome Lists containing this project

README

          

# pi-websearch

Provider-backed `web_search` tool for pi. It starts with zero configuration: OpenAI and Anthropic sessions defer silently to senpi's built-in provider-native web search, while other providers use the built-in DuckDuckGo HTML backend unless a config file overrides it.

## Tool Schema

The public tool schema matches free-code:

```json
{
"query": "The search query to use",
"allowed_domains": ["example.com"],
"blocked_domains": ["spam.example.com"]
}
```

Only `query` is required. `allowed_domains` and `blocked_domains` are mutually exclusive for a single tool call. Result limits are configured per provider, not exposed in the tool schema.

## Configuration

The loader checks these files in order:

1. `.pi/websearch.json` in the current project
2. `~/websearch.json`
3. `~/.pi/websearch.json`

No config file is required for the default backend. For non-native providers, pi-websearch uses DuckDuckGo's HTML endpoint (`https://html.duckduckgo.com/html/`) because it is free and does not require an API key. Create a config file only when you want a different backend or routing policy.

Example override:

```json
{
"backend": "perplexity",
"apiKey": "pplx-...",
"maxResults": 8,
"allowedDomains": ["docs.example.com"]
}
```

Legacy configs that use `"provider"` instead of `"backend"` continue to work.

Multiple provider entries enable fallback and routing:

```json
{
"strategy": "priority",
"fallback": true,
"auto": true,
"providers": [
{
"id": "brave-search",
"provider": "brave",
"apiKey": "",
"priority": 10,
"maxResults": 8
},
{
"id": "exa-search",
"provider": "exa",
"apiKey": "",
"priority": 10,
"maxResults": 8
}
]
}
```

### Native auto-route

If the active model provider is `openai` or `anthropic`, pi-websearch registers no startup warning and defers to senpi's built-in `openai-web-search` or `anthropic-web-search` extension. Those built-ins wire the provider-native tool directly into supported model requests, so this extension only handles non-native providers and explicit override configs.

When `auto` is `true` (the default) and the active pi model exposes a server-hosted search tool, the extension prepends an implicit `{ id: "native", ... }` entry that reuses the model's resolved API key via `ExtensionContext.modelRegistry.getApiKeyAndHeaders`. The native entry tries first; on failure or when the model does not match, the configured providers handle the search. Disable with `"auto": false` if you want only the explicit `providers` list.

Models that activate native routing (Q1 2026):

- `openai`: `gpt-5.5`, `gpt-5.5-fast`, `gpt-4.1`, `gpt-4.1-mini`, `gpt-4o`, `gpt-4o-mini` (excludes `gpt-4.1-nano`, `gpt-5-codex`, `gpt-5.1-codex`).
- `anthropic`: `claude-opus-4-*`, `claude-sonnet-4-*`.
- `xai`: any `grok-*`.
- `perplexity`: any `sonar*` (search is intrinsic to Sonar models).
- `z-ai` or `zai`: any `glm-*`.
- `openrouter`: any `/` whose `` and `` match one of the rows above (for example `openai/gpt-5.5` or `anthropic/claude-opus-4-7`).

The native entry inherits `model.baseUrl` from `ExtensionContext.model`, so any local gateway override registered in the pi model registry is honored. The endpoint path is appended automatically: if `baseUrl` already ends with `/v1`, only the resource segment is added; otherwise `/v1/` is appended.

Routing strategies:

- `priority`: try lower `priority` values first, falling back in order when `fallback` is `true`.
- `round-robin`: rotate the first provider per search; optional `weight` repeats entries in the rotation.
- `fill-first`: collect unique results across providers until the requested result count is filled.

Supported providers:

- `duckduckgo-html`: DuckDuckGo HTML search endpoint. Requires no `apiKey`; used as the zero-config default.
- `exa`: direct Exa search. Requires `apiKey`.
- `tavily`: direct Tavily search. Requires `apiKey`.
- `brave`: Brave Search API. Requires `apiKey`.
- `serper`: Serper Google search API. Requires `apiKey`.
- `google-cse`: Google Custom Search JSON API. Requires `apiKey` and `searchEngineId`.
- `z-ai`: Z.ai web search endpoint. Requires `apiKey`.
- `openai`: OpenAI Responses API hosted `web_search` tool. Requires `apiKey`.
- `codex`: OpenAI Responses API hosted `web_search` tool. Requires `apiKey`.
- `anthropic`: Anthropic Messages API with server `web_search_20250305` tool. Requires `apiKey`.
- `perplexity`: Perplexity Search API. Requires `apiKey`.
- `xai`: xAI Responses API hosted `web_search` tool. Requires `apiKey`.

Provider-specific optional fields include `id`, `baseUrl`, `model`, `maxResults`, `priority`, `weight`, `searchContextSize`, `codexMode`, `allowedDomains`, `blockedDomains`, and `userLocation` where supported. `baseUrl` is supported for every provider and must be a public HTTPS URL without embedded credentials.

Tool text and TUI output include the selected provider entry, routing strategy, and fallback attempts so the agent can see which provider produced the result.

## Commands

```bash
npm test
npm run typecheck
npm run check
pi -e ./src/index.ts
```

Inside pi, run `/websearch status` to inspect activation state.

## Related

- [senpi](https://github.com/code-yeongyu/senpi) — the fork/runtime these extensions are extracted from.
- [Ultraworkers Discord](https://discord.gg/PUwSMR9XNk) — community link from the senpi README.
- [Dori](https://sisyphuslabs.ai) — the product powered by senpi under the hood.