@boti-ormandi/pi-web

Native web search and secure public-URL fetch tools for pi using pi-managed OpenAI Codex or Anthropic subscription OAuth.

Packages

Package details

extension

Install @boti-ormandi/pi-web from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@boti-ormandi/pi-web
Package
@boti-ormandi/pi-web
Version
0.4.1
Published
Jul 22, 2026
Downloads
239/mo · 176/wk
Author
boti-ormandi
License
MIT
Types
extension
Size
161 KB
Dependencies
6 dependencies · 4 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-web

Native web_search and secure public-URL web_fetch tools for the pi coding agent.

pi-web reuses the subscription OAuth sessions already managed by pi:

  • OpenAI Codex through the openai-codex provider.
  • Anthropic Claude through the anthropic provider.

It does not read credential files, accept API keys, register replacement providers, or fall back to environment credentials. Model-backed requests are sent only to the fixed first-party provider origins after the active canonical model and OAuth snapshot have passed strict trust checks.

Requirements

  • Node.js >=22.19.0.
  • pi >=0.80.10.
  • A pi-managed OAuth login for any model-backed provider route you select.

A no-prompt local fetch can work without either provider being logged in.

Install

Install from npm through pi:

pi install npm:@boti-ormandi/pi-web

For local development, point pi at a checkout:

{
	"extensions": ["/absolute/path/to/pi-web"]
}

Place that in ~/.pi/agent/settings.json or a project's .pi/settings.json, then reload or restart pi.

Tools

web_search

Searches the public web through one subscription provider route.

{
	query: string;
	provider?: "openai-codex" | "anthropic";
	allowed_domains?: string[];
	blocked_domains?: string[];
}

Rules:

  • query must contain at least two characters.
  • provider is optional. The literal value auto is not accepted in tool JSON; omit the field to use configured or automatic routing.
  • allowed_domains and blocked_domains are mutually exclusive after empty arrays are normalized away.
  • Domain entries must be lowercase IDNA hostnames. Schemes, credentials, paths, ports, wildcards, and IP literals are rejected.
  • A domain filter matches the named domain and its subdomains.
  • URL is the only guaranteed source field. Title and snippet are optional.

Filtered searches fail closed: pi-web requires structured public source URLs, verifies every source against the requested filter, and omits unverified provider prose. Unfiltered searches may return useful provider text even when no structured sources are present.

web_fetch

Retrieves one public HTTP(S) URL. With no prompt, it returns bounded retrieved text. With a prompt, it processes only verified retrieved content.

{
	url: string;
	prompt?: string;
	provider?: "openai-codex" | "anthropic";
}

prompt is trimmed. Empty or whitespace-only prompts are treated as omitted and never trigger subscription processing.

Returned metadata can include the final URL, title, content kind, PDF page count, and explicit source/input/answer truncation flags. Model IDs, costs, cache state, account metadata, encrypted provider state, and native response references are not stable tool details.

Routing

Provider precedence for model-backed work is:

  1. The tool's explicit provider.
  2. The global config provider when it is not auto.
  3. The automatic candidate sequence resolved for the current invocation.

Explicit selection is strict. Automatic routing may advance to another provider only after a pre-semantic resolution, OAuth, catalog, or capability failure. Once native search, native open, or grounded processing is dispatched, that provider owns the result or error; pi-web never switches providers after semantic commitment.

Search and prompted fetch

Active trusted OAuth model Automatic candidate order
OpenAI Codex Active Codex, then inactive Anthropic
Anthropic Active Anthropic, then inactive Codex
Neither Inactive Codex, then inactive Anthropic

The active model is observed on every tool invocation. Active trusted models are used directly rather than replaced by a catalog choice.

No-prompt fetch

No-prompt retrieval intentionally has a different algorithm:

  • Explicit/configured Codex: resolve Codex OAuth, perform native open, and require retrieval proof.
  • Explicit/configured Anthropic: retrieve locally. No Anthropic auth lookup or Anthropic request occurs.
  • Automatic: use native Codex only when the active model is trusted Codex with an OAuth snapshot; otherwise retrieve locally immediately.

No-prompt fetch never performs inactive-provider fallback.

Provider behavior

OpenAI Codex

  • Search uses the fixed ChatGPT Codex native search endpoint.
  • An active trusted Codex model is used directly.
  • Inactive Codex selection performs a fresh fixed-protocol catalog preflight, then chooses an exact trusted pi model deterministically.
  • Fetch uses native open. Prompted fetch requires native retrieval proof before a separate ordinary Codex processing request.
  • The processing request uses the same model and receives only bounded retrieved text plus the normalized prompt.

Anthropic

  • Search uses Anthropic's native server-side web search tool through the accepted subscription compatibility envelope.
  • The active trusted Anthropic model is used directly. Inactive fallback is the exact trusted claude-haiku-4-5 model when present.
  • Fetch retrieval is local. Prompted fetch retrieves and extracts first, then performs ordinary grounded Anthropic processing.
  • Retrieval or extraction failure occurs before OAuth resolution and makes no Anthropic request.
  • No-prompt Anthropic fetch is entirely local.

Configuration

pi-web has one durable config file:

~/.pi/agent/extensions/pi-web/config.json

Schema and default:

{
	"provider": "auto"
}

Accepted values are auto, openai-codex, and anthropic. provider is the only permitted key. Missing files and {} resolve to auto; malformed JSON, extra keys, legacy multi-key configuration, arrays, null, and other primitives produce an observable configuration error.

There is no project-local pi-web config, environment-variable override, or pi CLI flag.

Public-URL security boundary

Local retrieval uses a one-shot direct-IP HTTP/HTTPS connector rather than a global reusable fetch client.

  • Only public http: and https: URLs are accepted.
  • Credentials, fragments, non-default ports, and private or special-use IP space are rejected.
  • Every DNS answer is validated; mixed public/private answers fail closed.
  • The connected peer address must match the validated pinned address before a request is sent.
  • Original HTTP Host and TLS SNI are preserved while the connection remains pinned to the validated IP.
  • Every redirect is re-resolved and revalidated. HTTPS downgrade is rejected.
  • Caller-provided headers, proxy routing, compression, connection reuse, and private-address escape switches are not supported.
  • Deadlines, redirect count, response bytes, extraction work, provider input, and returned output are bounded.
  • Abort signals propagate through network retrieval, HTML extraction, and PDF page processing.

This is a public-web tool, not a local-network browser or authenticated scraper.

/web-status

/web-status is the only slash command added by pi-web. It reports separate snapshot predictions for:

  • Search.
  • Prompted fetch.
  • No-prompt fetch.

The command may inspect the active model, registry snapshots, OAuth-status snapshots, validated config, and public version information. It does not refresh auth, resolve credentials, contact provider or catalog endpoints, write files, or display credentials, account IDs, or native provider state.

Its output distinguishes active trusted routes, inactive catalog/fallback preflight, local retrieval, and the fact that request-time OAuth is still required.

Output and UI

Collapsed tool rows show the selected route, source/content summary, and any truncation state. Expanded rows show normalized source metadata and bounded previews. Preview clipping is renderer-only: the full bounded tool result is still returned to the agent.

Model-visible output also includes explicit markers when provider text, source lists, retrieved text, grounded-processing input, or the final answer was truncated.

Clean-break migration

Version 0.4.0 replaces the earlier Anthropic-only configurable product with the strict native OAuth contract above. Removed surfaces include model/tier controls, alternate fetch backends, generic provider routing, project and environment configuration layers, caches, citation replay, cost display, and legacy slash commands.

See CHANGELOG.md for the complete migration table. Legacy cache files, when present, are left untouched and are neither read nor deleted.

Development

npm install
npm run typecheck
npm test
npm run test:package

npm test runs deterministic schema, config, trust, routing, provider, transport, extraction, status, tool-output, and renderer tests.

npm run test:package packs the exact npm artifact, rejects private or test material from the tarball, installs it with the minimum and newest tested pi host packages against TypeBox 1.1.38 and the newest tested stable TypeBox <2. It loads the extension under Node 22.19.0 and the current Node runtime. The verification uses isolated temporary homes and does not read the user's pi credentials or configuration.

Live provider calls are not required for unit, package, or release acceptance. The Codex native protocol has separate completed live evidence; Anthropic uses the accepted historical working baseline and deterministic compatibility fixtures.

License

MIT. See LICENSE.