feat(pi-web-search): 搜索凭据迁移到 Pi auth.json

三个搜索 key 改为 auth.json 中的 tavily/exa/keenable api_key 凭据,
pi-web-search/auth.ts 复刻上游 resolve-config-value 语义(!command、
$VAR 插值、credential env 优先、$$/$! 转义)并在每次调用时读取,
进程环境变量与 search.env 不再被直接读取。search_config.sh 重写为
scripts/search-auth.mjs 的薄封装:加锁原子写、权限 600、保留其他
凭据条目,支持 --migrate 从旧 search.env 一次性导入。

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
云服务部-叶林立
2026-10-19 20:39:13 -07:00
co-authored by Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent ee1e6999d7
commit 0c9823ef5c
20 changed files with 909 additions and 335 deletions
+11 -5
View File
@@ -15,16 +15,22 @@ Unified web search and fetch for Pi. The main model only ever sees two tools —
Plain `fetch` calls — no MCP adapter, no upstream extension wrappers:
- `clients/tavily.ts` — `POST api.tavily.com/search|extract`, Bearer key.
Requires `TAVILY_API_KEY`.
Requires a `tavily` credential.
- `clients/keenable.ts` — `api.keenable.ai`, keyless `/public` endpoints by
default, `KEENABLE_API_KEY` raises rate limits. Adapted from
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. `EXA_API_KEY` optional (`x-api-key` header).
on session expiry. An `exa` credential is optional (`x-api-key` header).
Keys are loaded from `~/.config/my-pi/search.env` by `extensions/search-config.ts`
(written by `search_config.sh`); explicit environment variables win.
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"`). `search_config.sh`
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