Files
my-pi/pi-web-search
云服务部-叶林立andDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> 2aa1be0b54 feat: 组合包配置以包内 config/ 为唯一来源,并新增受保护写入人工审批
配置统一:权限策略、硬防御、Tool Search、提示词封面以及新迁入的
RTK、pi-compaction、pi-worktree、pi-hermes-memory 配置全部由扩展
直接读取已安装组合包内的 config/,pi install / pi update 即完成部署;
删除 rebuild-bundle-config.mjs 与 bundle-manifest.json,my-pi/ 只保留
日志与缓存。update.sh 成功升级后将默认 git 来源的已安装副本
reset 回发布版本。AGENTS.md 新增「组合包配置原则」。

脚本整合:search_config.sh / ssh_config.sh 合并为 configure.sh
search|ssh;install.sh / update.sh 共享函数抽到 scripts/lib.sh,远程
安装器改为先下载到临时文件再执行,下载失败可被检测。

权限:hard-guards 新增 protectedWrites,写入 Pi 凭据/设置、已安装
组合包与扩展目录、pi-ssh 凭据库时一律人工确认(跳过 AutoReview、
yolo 与 Session grant,无 UI 时拒绝);放行 ls、LSP 查询、ctx 只读、
web_search、Chrome 只读与 git 只读命令,skill_manage 改为 ask。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-20 01:05:31 -07:00
..

pi-web-search

Unified web search and fetch for Pi. The main model only ever sees two tools — web_search and web_fetch — provider selection happens inside the extension.

  • web_search(query, max_results?, site?, published_after?, published_before?, depth?) routes each query to Tavily, Exa, or Keenable using the session's current main model (ctx.model + ctx.modelRegistry.complete), guided by per-provider rules. Results include details.provider / details.routedBy for debugging.
  • web_fetch(urls, max_characters?) always reads pages via Exa (web_fetch_exa), degrading silently to Keenable then Tavily.

Providers (clients/)

Plain fetch calls — no MCP adapter, no upstream extension wrappers:

  • clients/tavily.ts — POST api.tavily.com/search|extract, Bearer key. Requires a tavily credential.
  • clients/keenable.ts — api.keenable.ai, keyless /public endpoints by default, a keenable credential raises rate limits. Adapted from @keenable/pi-search.
  • clients/exa.ts — JSON-RPC over mcp.exa.ai/mcp (Streamable HTTP): initialize once, cache mcp-session-id, tools/call per request, re-init on session expiry. An exa credential is optional (x-api-key header).

Keys live in Pi's auth.json as one api_key credential per provider (tavily, exa, keenable), read by auth.ts with upstream resolution semantics — literal values, $VAR/${VAR} interpolation, and !command indirection (e.g. "!op read op://Vault/Tavily/key"). configure.sh search writes them (atomically, mode 600, preserving all other entries); process environment variables are not read directly — use "key": "$TAVILY_API_KEY" to indirect through env. KEENABLE_API_URL stays env-only, or can be stored in the keenable credential's env map.

Routing

router.ts asks the current model to answer with exactly one provider name, given a prompt containing the per-provider strengths and the query's requested filters. Decisions are cached per session (LRU, 32 entries). Failure paths are deterministic: an unroutable answer or a dead provider falls back across the remaining available providers — never a heuristic choice over the model.