配置统一:权限策略、硬防御、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>
2.2 KiB
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 includedetails.provider/details.routedByfor 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 atavilycredential.clients/keenable.ts—api.keenable.ai, keyless/publicendpoints by default, akeenablecredential raises rate limits. Adapted from@keenable/pi-search.clients/exa.ts— JSON-RPC overmcp.exa.ai/mcp(Streamable HTTP):initializeonce, cachemcp-session-id,tools/callper request, re-init on session expiry. Anexacredential is optional (x-api-keyheader).
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.