feat(agent): web.search / web.fetch via Brave Search (WEB-1)

- adapters/websearch: Brave client (X-Subscription-Token, error classes),
  result normalization with redaction/truncation, SSRF guard, HTML→text fetch
  (10s, 512KB, text/html|text/plain only)
- modules/websearch: 10-min PG cache (region websearch), cross-process
  per-minute limit, web.fetch allowlist = URLs from the caller's latest
  web.search; POST /websearch/test
- settings.agent.webSearch (key write-only → secret_ref); settings card
  under Agent; web.* offered to the model only when enabled, plus a system
  prompt rule; outputs marked untrusted
- capability count 27 → 29; e2e E13; runbook docs/runbook/websearch.md

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 00:14:08 +08:00
1 parent 40dd0e69e4
commit d53df25fc8
32 files changed
+1854 -39

No files matched your search

+2 -1
View File
@@ -43,7 +43,7 @@ const pingModule: ServerModule = {
};
describe("ServerModule 骨架", () => {
it("清单里是四个 W2 模块 + 文件管理 + Pi 上游 + 定时任务 + 全局搜索 + 浏览器 + MCP + 缓存 + 进程与健康(末尾),名字唯一", () => {
it("清单里是四个 W2 模块 + 文件管理 + Pi 上游 + 定时任务 + 全局搜索 + 浏览器 + MCP + 网页搜索 + 缓存 + 进程与健康(末尾),名字唯一", () => {
expect(SERVER_MODULES.map((m) => m.name)).toEqual([
"auth-settings",
"sources-identity",
@@ -55,6 +55,7 @@ describe("ServerModule 骨架", () => {
"search",
"browser",
"mcp",
"websearch",
"cache",
"system",
]);