feat(v1.8.0): 稳定性修复 + AI Agent 体验增强

稳定性修复:

- 修复 cache.py SQLite 连接泄漏(contextlib.closing 包装)

- 修复 fetch.py requests stream=True 连接泄漏(try/finally resp.close())

- RETRYABLE_STATUS 新增 403,激活 UA fallback 切换逻辑

- --cache-stats 移至实例解析前,无需实例即可查询

- classify_error 从错误消息提取 HTTP 状态码,正确分类 E_AUTH/E_RATE_LIMIT

- --stream 与 --queries-file 互斥检查,违规报 E_INPUT

- batch 退出码语义统一(0=有结果 / 1=全部错误 / 2=全部空结果)

AI Agent 体验增强:

- 错误码体系完善:E_CONFIG/E_AUTH/E_NETWORK/E_RATE_LIMIT/E_PARSE/E_EMPTY/E_INPUT/E_INTERNAL

- recovery_hint 恢复提示字段,AI Agent 可程序化决策恢复策略

- stream 模式新增 error 事件类型(含 error_code + recovery_hint)

- 进度事件扩展:instance_try/instance_ok/instance_fail

- batch 模式统一 schema(status 字段区分 success/failed)

- JSON 输出含 schema_version 字段确保版本兼容

测试与文档:

- 测试覆盖:330 -> 352

- SKILL.md / README.md 同步更新
This commit is contained in:
2026-08-01 19:02:44 +08:00
parent dea899143d
commit fb9b2af45f
12 changed files with 871 additions and 131 deletions
+36 -19
View File
@@ -55,36 +55,47 @@ AI 调用后,stdout 输出网页正文(text/html/markdown 三种格式),
| exit 1 | 失败 | 致命错误(所有实例不可用、参数错误等) |
| exit 2 | 空结果 | 搜索成功但无结果 |
**错误处理**`--format json` 模式下,错误以 JSON 输出到 stdout(非 stderr),格式为 `{"error": "...", "error_code": "E_NETWORK", "exit_code": 1, "query": "..."}`AI 可程序化捕获。
**错误处理**`--format json` 模式下,错误以 JSON 输出到 stdout(非 stderr),格式为 `{"error": "...", "error_code": "E_NETWORK", "recovery_hint": "...", "exit_code": 1, "query": "..."}`AI 可程序化捕获并按 `recovery_hint` 采取恢复行动
**错误码体系**`error_code` 字段):
**错误码体系**`error_code` + `recovery_hint` 字段):
| 错误码 | 含义 | AI 恢复策略 |
|--------|------|-------------|
| `E_CONFIG` | 配置错误(无实例) | 提示用户设置 `-i` / `SEARXNG_INSTANCE` |
| `E_AUTH` | 认证失败(401/403 | 检查 token/凭证 |
| `E_NETWORK` | 网络错误(连接失败、5xx) | 重试切换实例/代理 |
| `E_RATE_LIMIT` | 限流(429 | 等待重试 |
| `E_PARSE` | 解析错误 | 检查实例 JSON 支持 |
| `E_INPUT` | 输入错误(参数/文件) | 修正参数 |
| `E_INTERNAL` | 内部错误 | 报告 bug |
| 错误码 | 含义 | recovery_hint(节选) |
|--------|------|----------------------|
| `E_CONFIG` | 配置错误(无实例) | 设置 `-i`/`SEARXNG_INSTANCE`/配置文件 |
| `E_AUTH` | 认证失败(401/403 | 检查凭证、token 过期与权限 |
| `E_NETWORK` | 网络错误(连接失败、5xx) | 重试退避、切换实例、检查代理 |
| `E_RATE_LIMIT` | 限流(429 | 等待重试、降低频率、分散负载 |
| `E_PARSE` | 解析错误 | 切换实例、切换 `--method` |
| `E_EMPTY` | 空结果(exit 2) | 调整查询词、扩大 `--time-range`/`--categories` |
| `E_INPUT` | 输入错误(参数/文件) | 检查语法、标志组合、文件路径 |
| `E_INTERNAL` | 内部错误 | 用 `--verbose` 重跑并报告 |
### 流式输出与进度事件(AI 高级用法)
**`--stream`**JSON Lines 流式输出,每条结果一行 JSON,AI 可增量处理:
```
{"type": "result", "result": {"title": "...", "url": "..."}}
{"type": "done", "count": 10, "query": "..."}
{"type": "done", "schema_version": "1.0", "count": 10, "query": "..."}
```
搜索失败时输出 error 事件(含 `recovery_hint`):
```
{"type": "error", "error": "...", "error_code": "E_AUTH", "recovery_hint": "Verify credentials...", "query": "..."}
```
注意:`--stream` 仅在单查询 + `--format json` 下有效;与 `--queries-file` 或非 json 格式同用会立即报 `E_INPUT`
**`--progress`**:进度事件流(JSON Lines 到 stderr),AI 可实时跟踪执行:
```
{"event": "start", "query": "...", "instances": 2}
{"event": "instance_try", "url": "https://inst1.example.com", "attempt": 1}
{"event": "instance_ok", "url": "https://inst1.example.com", "latency": 0.342, "results": 10}
{"event": "instance_fail", "url": "https://inst2.example.com", "error": "HTTP 503", "error_code": "E_NETWORK"}
{"event": "cache_hit", "query": "...", "ttl": 30}
{"event": "fetch_ok", "url": "...", "chars": 12345}
{"event": "done", "results": 10, "query": "..."}
```
**`--dump-schema`**:输出当前版本的 JSON Schema 到 stdout 并退出,AI 可程序化发现字段名与类型,无需解析文档。
```bash
# AI 推荐用法:流式输出 + 进度事件
python scripts/search.py -q "research" -i https://your-instance --stream --progress
@@ -94,7 +105,7 @@ python scripts/search.py -q "research" -i https://your-instance --stream --progr
### 前置条件
- Python 3.8+
- Python 3.8+3.11+ 开箱即用;3.8-3.10 使用 `searxng.toml` 配置需 `pip install tomli`
- 一个 SearXNG 实例 URL(自建或受信任的实例)
### 安装
@@ -105,9 +116,13 @@ git clone https://git.metona.cn/MetonaTeam/searxng-use-cli.git
无需安装依赖。`search.py` 仅使用 Python 标准库,开箱即用。
可选安装(提升 `fetch.py` 抓取质量)
可选安装:
```bash
# 提升 fetch.py 抓取质量(HTTP 连接池 + HTML 解析)
pip install requests beautifulsoup4
# Python 3.8-3.10 使用 searxng.toml 配置文件时需要(3.11+ 内置 tomllib
pip install tomli
```
### 配置实例
@@ -248,10 +263,12 @@ python scripts/fetch.py -u https://example.com \
**工程**
- 共享 `common.py`(统一重试/字符集/认证/日志)
- 结构化日志(`--verbose` / `--quiet`
- 结构化错误码(`E_NETWORK` / `E_AUTH` / `E_RATE_LIMIT` 等)
- JSON Lines 流式输出(`--stream`
- 进度事件(`--progress`JSON Lines 到 stderr
- 330 个单元+集成测试
- 结构化错误码 + `recovery_hint` 恢复建议`E_NETWORK` / `E_AUTH` / `E_RATE_LIMIT` 等)
- JSON 输出含 `schema_version` 字段,`--dump-schema` 输出 JSON Schema 文档
- JSON Lines 流式输出(`--stream`,含 `error` 事件类型
- 进度事件(`--progress`,含 `instance_try`/`instance_ok`/`instance_fail`JSON Lines 到 stderr
- batch 模式统一 schema`status` 字段区分成功/失败)
- 352 个单元+集成测试
## 跨 Agent 兼容性
@@ -279,7 +296,7 @@ pip install pytest
pytest -q
```
330 个测试覆盖:缓存操作、认证解析、域名过滤、Markdown 转换、搜索逻辑、集成流程、日志配置、HTML 回退、自动抓取、健康检查、输出格式化、实例解析、并行搜索、CLI 端到端、错误码分类、流式输出、进度事件、配置文件认证。
352 个测试覆盖:缓存操作、认证解析、域名过滤、Markdown 转换、搜索逻辑、集成流程、日志配置、HTML 回退、自动抓取、健康检查、输出格式化、实例解析、并行搜索、CLI 端到端、错误码分类、流式输出、进度事件、配置文件认证、schema_version、recovery_hint、batch 统一 schema、--dump-schema
## 项目结构