Files
云服务部-叶林立andDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> f9a7f743dd feat: 接入 Pi 内置 codemode,并修复全面审查发现的问题
- codemode:Tool Search 常驻(alwaysEnabled)、权限 allow(嵌套调用仍逐个过权限门)、
  tools.jsonc 登记使用规则;RTK 跳过 parentToolCallId 嵌套调用,避免丢失 bash
  structuredContent;Tool Search 目录过滤 hidden / codemode(script-only)exposure;
  扩展加载测试加载 builtin:codemode 并断言其常驻激活
- 搜索 key 不再经命令行参数传递:search-auth.mjs 改为 --set-stdin(先读校验再加锁),
  configure.sh 交互输入经管道、非交互用 --<provider> -
- CodeGraph 客户端监听子进程 stdin error,避免 EPIPE 未处理导致崩溃
- 移除 PI_TOOL_SEARCH/HERMES_MEMORY/RTK_CONFIG_PATH 环境变量入口,测试改用工厂 configPath 注入
- pi-subagents 固定 vitest / coverage-istanbul 4.1.10,修复 npm ls 版本冲突
- 补 pi-web-search / pi-worktree UPSTREAM.md 与 pi-minimal-footer AGENTS.md,
  files 白名单补齐并加测试;.codegraph/.gitignore 移出跟踪
- detect_kitty 优先识别官方安装目录

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

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-21 23:18:34 -07:00

48 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. `max_results` defaults to 8 and is clamped to 1–20. 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.
`max_characters` defaults to 20,000 and is clamped to 1–100,000 per page;
oversized fetch output is further bounded by pi-overflow downstream.
## 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 via its hidden interactive prompt or `scripts/search-auth.mjs
--set-stdin` reading the key from stdin — a key is never accepted as a
command-line argument (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.