pi-deepseek-search-tools0.1.1
DeepSeek Search & Fetch for Pi: deepseek_search for live web results via the official POST /v1/tools/search API and deepseek_fetch for full-page Markdown via POST /v1/tools/fetch. Requires a DeepSeek API key (DEEPSEEK_API_KEY or /deepseek-setup).
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-deepseek-search-tools
pi-deepseek-search-tools is a Pi Coding Agent extension with two direct tools backed by the official DeepSeek Search & Fetch API:
POST https://api.deepseek.com/v1/tools/search (structured web results)
POST https://api.deepseek.com/v1/tools/fetch (full-page Markdown)
deepseek_search— one query per call, returning ranked titles, exact URLs, per-item site/date/authority/rerank metadata, and bounded snippets/summaries.deepseek_fetch— one HTTP/HTTPS URL per call, returning the page title and clean Markdown.
Use it proactively when an answer depends on current or externally verifiable information: documentation, news, prices, products, papers, comparisons, fact-checking. It is not a replacement for Pi's local file or shell tools.
中文说明:这是一个面向 Pi Coding Agent 的 DeepSeek 联网搜索扩展,只使用官方 Search/Fetch API(
POST /v1/tools/search与POST /v1/tools/fetch)。必须配置 DeepSeek API key(无匿名模式):export DEEPSEEK_API_KEY=sk-...或在 Pi 内运行/deepseek-setup。
Core capabilities
- General web search as bounded Markdown (≤12,000 chars per call; snippets ≤500 chars, summaries ≤1,000 chars, optional
content≤2,000 chars per result — usedeepseek_fetchfor full pages). - Only the official Search request fields are exposed:
query,count(1–50, default 10),ori_question,localization,need_content. There are nodomain/sub_domain/batch parameters — they do not exist in the DeepSeek Search API. - DeepSeek query operators pass through in
query:site:/-site:, leading-,"quoted phrases",lang:xx,yy,after:/before:(year or full date). - Result metadata (
site_name,date,authority0–4,rerank_score0–3) is rendered per item so the model can weigh source quality; URL-less items are never given a fabricated citation. - Duplicate results are removed before rendering (normalized URL match, or near-identical title via character-bigram similarity ≥0.85).
deepseek_fetchreturns**Source**+ title + Markdown body, capped at 50,000 characters. The vendor's backslash-escaped ASCII punctuation (\#,\.,\[,\|…) is unescaped back to real Markdown.- Local bounded reading for fetched pages:
offset/limit/find_text/refreshover a five-minute in-memory session cache (16 entries, ~1M chars). These parameters never leave the plugin. - Compact Pi TUI rendering (collapsed by default, expandable).
Requirements
A DeepSeek API key is required — the API has no anonymous mode and returns HTTP 401 without one.
Installation
From a checkout of this repository:
# Load the extension for the current Pi invocation only
pi -e .
# Install the local directory as a Pi package
pi install .
API key configuration
Configuration priority is:
DEEPSEEK_API_KEY environment variable
> <agent dir>/deepseek.json (deepseekApiKey | deepseek_api_key | apiKey)
> <agent dir>/settings.json (deepseekApiKey | deepseek_api_key)
> <agent dir>/auth.json (deepseek.key when type is "api_key")
Set the environment variable in your shell or CI environment:
export DEEPSEEK_API_KEY="sk-..."
Or create ~/.pi/agent/deepseek.json:
{
"deepseekApiKey": "sk-..."
}
~/.pi/agent is Pi's default agent directory. If PI_CODING_AGENT_DIR is set, the extension reads the config files from that directory instead. Config files are only read — except deepseek.json, which /deepseek-setup writes with your confirmation.
Pi commands
/deepseek-setup
Opens an interactive prompt and saves the key to <agent dir>/deepseek.json. The new key is used by subsequent calls without restarting Pi, unless a non-empty DEEPSEEK_API_KEY remains set; the environment variable always takes precedence.
/deepseek-status
Shows the configuration path and reports only 已配置 (configured) or 未配置 (not configured). It does not display the key or a key prefix.
postinstall behavior
The npm package includes a postinstall script:
- In an interactive terminal, it may ask for an API key when none is configured. Press Enter to skip.
- In a non-interactive installation, it prints setup guidance; installation still succeeds.
- If npm lifecycle scripts are disabled (
npm install --ignore-scripts), the script does not run.
Tool reference
deepseek_search
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | Yes | One search intent, 1–128 characters, not all whitespace. Query operators pass through: site:, -site:, -term, -"phrase", "phrase", lang:, after:, before:. |
count |
integer | No | Results to return, 1–50; the API default is 10. |
ori_question |
string | No | The user's original question (1–128 chars) to improve query understanding. |
localization |
string | No | An IP address used to localize results. |
need_content |
boolean | No | Return each result's page content (bounded to 2,000 chars/item locally). Default false. |
{"query": "DeepSeek V4 release notes", "count": 5}
{"query": "DeepSeek site:github.com OR site:huggingface.co lang:en after:2026", "count": 10}
deepseek_fetch
| Parameter | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | http:// or https:// URL with a host, no embedded username/password, at most 8,192 characters. |
Optional local reading parameters (never sent to the DeepSeek API):
| Parameter | Description |
|---|---|
offset |
Non-negative UTF-16 code-unit position in the complete fetched text, including Source/title. |
limit |
Fragment size, 1–50,000 characters; default 6,000 for enhanced reads. |
find_text |
First exact, case-sensitive literal match with nearby context. Cannot be combined with offset. |
refresh |
Fetch again instead of reusing the five-minute session cache. |
{"url": "https://example.com/article", "find_text": "Attention", "limit": 4000}
Enhanced results report source URL, fetch time, cache hit, original-text range, next offset, and explicit no_match/end_of_text status.
Returned results
Search returns ## Search Results (n results) followed by numbered items carrying the exact title/url pair, a **Meta** line (site_name · date · authority · rerank score), and the summary (falling back to snippet). With need_content: true, a bounded **Content** block is appended per item. A search with no matches returns (0 results).
Fetch returns **Source**: <url> followed by ## <title> and the page content as Markdown.
Each tool result carries structured details: isError, auth mode (configured/unconfigured), requestId when upstream provides one, and fetch reading metadata. Details never contain the API key.
Errors propagate as tool errors: DeepSeek API error <status>: <message> parsed from the OpenAI-compatible error envelope, with credential-shaped strings redacted. Per the official guide, HTTP 408/429/5xx responses and connection-level transport failures are retried once after a 300 ms backoff (honoring Retry-After up to 2 s); other 4xx responses are never retried. Cancellations and timeouts propagate via AbortSignal.
Security
- Never commit API keys to Git, source files, examples, or issue reports.
- Error text is sanitized before surfacing:
sk-…tokens andBearerheaders are redacted, and HTTP 402 balance errors are replaced with a fixed message instead of echoing upstream text. - The fetch URL contract is enforced locally before any network call: http/https only, a host is required, embedded credentials are rejected, and the 8,192-character limit applies. Fetch requests go only to
https://api.deepseek.com— target content is fetched server-side by DeepSeek. - The configuration file stores the key locally as plain JSON; protect access to your Pi agent directory.
- Pi extensions execute with the user's permissions. Review the source before installation.
- This extension makes network requests to
https://api.deepseek.com/v1/tools/searchandhttps://api.deepseek.com/v1/tools/fetchonly when one of the tools is called. It does not make a network request merely by loading the extension.
Coexisting with pi-anysearch
This package registers only deepseek_search and deepseek_fetch, so it does not collide with anysearch/anysearch_extract or other search tools. Use deepseek_search when you want DeepSeek's in-house index (notably strong Chinese-language coverage); keep anysearch for anonymous fallback and vertical domains.
Development and verification
npm install --ignore-scripts
npm test
DEEPSEEK_API_KEY=sk-... npm run test:e2e # real endpoints; key required
# Preserve previous evidence: choose a directory that does not exist
DEEPSEEK_E2E_OUTPUT_DIR=.evidence/e2e-NEW npm run test:e2e
npm test runs the deterministic mocked-fetch suite; real network checks are explicit so credentials, balance, and connectivity cannot make the default test command flaky:
test/deepseek.test.ts— mocked-fetch coverage for tool registration and schema surface (official fields only), request assembly, response field parsing, bounded Markdown rendering, deduplication, error-envelope propagation with credential redaction, retry classification (transport codes, 408/429/5xx,Retry-After), URL validation, Markdown unescaping, fetch-reader cache/paging/find behavior, and the key-resolution order.test/e2e.test.ts— real-endpoint checks for a stable-fact search, tool-level execution,example.comfetch with unescaped-Markdown verification, fetch-reader caching, fault injection (one synthetic transport failure retried against the live service), and a deliberately invalid key proving 401 surfaces as a failure rather than a skip. Each passing scenario stores redacted raw evidence under.evidence/; unreachable networks are skipped with an explicit reason — credential and HTTP business errors always fail.
For a temporary local Pi run:
pi -e .
Links
License
MIT, as declared in package.json.