# metaso-service

> 秘塔 AI 搜索（metaso.cn）**免登录**搜索对话服务：`POST /v1/chat/completions`
> 对齐 OpenAI Chat Completions，带 `citations` 与 `reasoning_content` 扩展。
> 本文件给 LLM/Agent 读；人类入口：`/`（HTML 落地页）。

## 先读（危险项 / 额度）

- **匿名额度按「出口 IP × 时间窗口」计（实测 ~13 发/窗口）**：烧干回 4001，同出口重试无效；服务端已内置自动恢复（换出口/换身份/换 TLS 指纹），调用方按下方错误表归因即可。
- `metaso:deepresearch` 匿名额度**必然拒绝**（帧 4001）—— 需上游登录态或官方 API。
- **鉴权：未启用** —— 当前部署未配置 `METASO_API_KEYS`，chat 端点开放（仅限回环/内网使用）。
- 单一 search 型对话面：**不接受图片输入**，无思考开关；多轮请传完整历史（匿名上游不落库上下文，服务端已做 flatten）。

## 端点

| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| POST | `/v1/chat/completions` | 开放 | 搜索对话；`"stream": true` 走 SSE；`"dry_run": true` 干跑不触上游 |
| GET | `/v1/models` | 免 | 模型清单（未启用时返回空清单） |
| GET | `/health` | 免 | 就绪度 + 身份/出口/传输/闸门诊断（脱敏） |
| GET | `/llms.txt` | 免 | 本文件 |
| GET | `/` | 免 | HTML 落地页 |

## 能力表（注册 6 项，本部署可用 6 项）

| 模型 | 说明 | mode | experimental | 备注 |
|---|---|---|---|---|
| `metaso:search` | 秘塔 AI 搜索 · 深入 | detail | 否 | 默认形态；一次约 8~15s |
| `metaso:concise` | 秘塔 AI 搜索 · 简洁 | concise | 否 | — |
| `metaso:research` | 秘塔 AI 搜索 · 研究 | research | 否 | — |
| `metaso:scholar` | 秘塔 AI 搜索 · 学术 | detail | 否 | — |
| `metaso:video` | 秘塔 AI 搜索 · 视频 | detail | 否 | — |
| `metaso:deepresearch` | 秘塔 AI 搜索 · 深度研究 | strong-research | 是 | 匿名额度必然拒绝（4001），需登录态或官方 API 额度 |

## 最小可用调用

```bash
curl -s -X POST /v1/chat/completions -H 'content-type: application/json' \
  -d '{"model":"metaso:search","messages":[{"role":"user","content":"今天有什么大新闻"}]}'

# 非流式返回：choices[0].message.content + citations + upstream 统计
# 流式：data: {chat.completion.chunk} … data: [DONE]
```

## 错误表（从 app/errors.py 异常类派生，杜绝幽灵码）

归因规则：`retryable=true` → 退避后重试同一请求；`false` → 改参/换模型/等窗口自愈。

| HTTP | code | type | retryable | 含义 |
|---|---|---|---|---|
| 400 | `invalid_request_error` | invalid_request_error | 否 | 请求参数错误（模型名未知 / messages 形态不对 / 带图片输入）。 |
| 401 | `invalid_api_key` | authentication_error | 否 | 缺失/无效 API key（METASO_API_KEYS 配置了才启用鉴权）。 |
| 429 | `upstream_quota_exhausted` | rate_limit_error | 否 | 4001：出口窗口烧干。同出口重试无效 —— 换出口（池）/ 等窗口自愈。 |
| 429 | `upstream_rate_limited` | rate_limit_error | 是 | 429：无票即拒 / 窗口抖动。退避可解（自动身份会换新重试一次）。 |
| 502 | `upstream_unavailable` | api_error | 否 | 上游不可达 / 非 2xx 非 429 非 WAF（含连接失败、-500、5xx）。 |
| 503 | `capability_unavailable` | service_unavailable_error | 否 | 上游未启用（默认关）：宁可 503 明说，也不假装可用。 |
| 503 | `cooldown_active` | service_unavailable_error | 否 | 本服务自己的闸门冷却期（对上游静默，避免持续施压）。 |
| 503 | `upstream_risk_control` | service_unavailable_error | 否 | WAF HTML 挑战 / 风控页。重试只会延长封锁。 |

## 链接

- 上游契约与全部实测取证：`docs/UPSTREAM.md`（§11.6 频控两层模型 + 出口地理层 + TLS 指纹层）
- 仓库：`rsfree/metaso`（公开）
- 版本：0.1.0
