pi-search-tools

LLM-driven web search and content extraction extension for Pi — Tavily, Exa, Anysearch, Gemini, DeepSeek, Jina, and Firecrawl.

Packages

Package details

extension

Install pi-search-tools from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-search-tools
Package
pi-search-tools
Version
1.1.1
Published
Jul 8, 2026
Downloads
999/mo · 871/wk
Author
huanghui-dev
License
MIT
Types
extension
Size
100.8 KB
Dependencies
0 dependencies · 4 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

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

README

Pi Search Tools

中文版

LLM-driven web search and content extraction extension for Pi. The extension does not classify queries or auto-select providers. Instead, each provider declares its specialty via metadata (searchHint/fetchHint), and the calling LLM picks the best provider via the provider parameter, guided by dynamically-generated promptGuidelines.


Providers

Provider Search Fetch Notes
Tavily General web search + crawl/map/research (SimpleQA SOTA 93.3%)
Exa Semantic/academic search, freshness-driven queries
Serper Fast Google Search API wrapper for organic search
iFlow Optimized for Chinese queries, news, and localized content extraction
Anysearch Structured vertical search (finance, academic, security, travel)
Gemini Google Search Grounding API
DeepSeek DeepSeek's server-side search tool via its Anthropic-compatible API
Jina JS rendering, PDF support, frequency-limited, zero-setup (no API key required)
Firecrawl Full Playwright rendering, strongest JS support, quota-limited

Project Structure

pi-search-tools/
├── index.ts                           # Pi extension entry point (re-exports src/index.ts)
├── src/
│   ├── index.ts                       # Extension registration logic
│   ├── config.ts                      # Config file parser (~/.pi/pi-search-tools/config.json)
│   ├── commands.ts                    # Interactive /search-tools API key setup
│   ├── utils.ts                       # Result dedup, SSRF guard, retry/timeout, memory cache
│   ├── web-search.ts                  # web_search tool with dynamic provider routing
│   ├── web-fetch.ts                   # web_fetch tool with SSRF protection + content extraction
│   └── providers/                     # REST API clients + provider metadata
│       ├── index.ts                   # Factory, dynamic helpers, promptGuidelines aggregation
│       ├── types.ts                   # Provider interface + META types
│       ├── tavily.ts                  # Tavily API adapter
│       ├── exa.ts                     # Exa API adapter
│       ├── serper.ts                  # Serper API adapter (Google Search wrapper)
│       ├── iflow.ts                   # iFlow API adapter (Chinese optimization)
│       ├── anysearch.ts               # Anysearch API adapter (vertical search)
│       ├── gemini.ts                  # Gemini API adapter (Google Search Grounding)
│       ├── deepseek.ts                # DeepSeek API adapter (Server-side search grounding)
│       ├── jina.ts                    # Jina reader adapter (SSE-aware, zero-setup)
│       └── firecrawl.ts              # Firecrawl API adapter
├── test/                              # Native TypeScript unit tests (80 tests)
│   ├── providers.test.ts              # META consistency + dynamic enum/chain generation
│   ├── prompt-guidelines.test.ts      # promptGuidelines aggregation correctness
│   ├── factory.test.ts                # Provider factory + apiKeyRequired behavior
│   ├── execute.test.ts                # Search/fetch execution flow + this-binding regression
│   ├── gemini.test.ts                 # Gemini API request, parsing, redirection timeouts
│   ├── deepseek.test.ts               # DeepSeek API stream parsing + custom model tests
│   ├── jina-fetch.test.ts            # Jina SSE parsing + dedup
│   ├── config.test.ts                 # API key masking and resolution priority
│   ├── dedup.test.ts                  # URL deduplication
│   └── utils.test.ts                  # SSRF, SafeMemoryCache, fetchWithTimeout/Retry
└── package.json

Installation

pi install npm:pi-search-tools

Configuration

Interactive Setup

/search-tools

Select a provider and enter its API key.

Environment Variables

Set provider API keys in your environment (takes precedence over config file):

  • TAVILY_API_KEY
  • EXA_API_KEY
  • SERPER_API_KEY
  • IFLOW_API_KEY
  • ANYSEARCH_API_KEY
  • GEMINI_API_KEY
  • DEEPSEEK_API_KEY
  • DEEPSEEK_SEARCH_MODEL (Optional; customize the model used for search, defaults to deepseek-v4-flash)
  • JINA_API_KEY
  • FIRECRAWL_API_KEY

Routing

LLM-Driven Routing

The extension does not classify queries. The calling LLM chooses a provider via the provider parameter:

# General search → Tavily (fastest)
web_search({ query: "React 19 features", provider: "tavily" })

# Academic search → Exa (semantic, freshness-driven)
web_search({ query: "transformer architecture paper", provider: "exa" })

# Stock/CVE → Anysearch + vertical
web_search({ query: "AAPL", provider: "anysearch", vertical: "finance.us_stock" })
web_search({ query: "CVE-2025-12345", provider: "anysearch", vertical: "security.scan" })

If you omit provider, a cost-priority fallback chain is tried automatically:

  • Search: Tavily → Exa → Serper → iFlow → Anysearch → Gemini → Deepseek
  • Fetch: Tavily → Jina → Exa → Anysearch → Firecrawl → iFlow

When you explicitly specify a provider and it fails, the extension does not fall back — it returns the error to the LLM, respecting the LLM's choice.


Architecture

Design decisions are documented in the repository:

  • CONTEXT.md — domain glossary and canonical terminology
  • docs/adr/ — architecture decision records (LLM routing, single interface, Jina search exclusion, Anysearch retention)

Testing

npm run test

80 tests covering META consistency, chain generation, promptGuidelines aggregation, factory behavior, execution flow, SSE parsing, config resolution, dedup, and SSRF protection.


Development

  • Linter & Formatter: Biome, tab indentation (width 3)
  • TypeScript: strict mode
  • Check: npm run check
  • Test: npm test

License

MIT