API 参考
先看这一句:这份文档不是 API 的完整定义,
完整定义在 trove serve 自带的 /v1/docs。
这一页给的是分类、鉴权方式与场景示例——手抄一遍端点必然与代码脱节。
活文档在哪
服务启动后打开 http://<host>:<port>/v1/docs,那是 FastAPI
自动生成的 OpenAPI 界面:每个端点的参数、请求体、响应模型都在那里,
且随代码实时更新。
所有路由都在 /v1 前缀下。后端是纯 JSON API,不托管页面
(前端由独立容器发布,nginx 反代 /v1)。
鉴权
认证走 Bearer token。依赖分几个层次,按需叠加:
| 依赖 | 作用 |
|---|---|
| get_current_user | 解析 token → 用户 |
| require_admin | 要求 admin 角色 |
| require_scope | 要求 token 带某个 scope(如 query) |
| require_datasource | 校验对该数据源的授权 |
| check_api_rate | 限流与日配额 |
deps.py:78 get_current_user deps.py:125 require_admin deps.py:187 require_datasource
注意有两类端点不走用户鉴权,这是刻意的:
| 端点 | 为什么免鉴权 |
|---|---|
| /v1/health | 探活必须能被编排系统直接调用 |
| /v1/metrics | 抓取端通常不便于携带用户 token |
flowchart TB
REQ["请求 /v1/…"]:::entry --> K{"端点"}:::entry
K -- "普通端点" --> D1["get_current_user
token → 用户"]:::gate
D1 --> D2["require_admin / require_scope
按需叠加"]:::gate
D2 --> D3["require_datasource
数据源授权"]:::gate
D3 --> D4["check_api_rate
限流与日配额"]:::gate
D4 --> H["业务处理"]:::exec
K -- "探活 / 指标" --> FREE["/v1/health · /v1/metrics
免鉴权:编排与抓取端不便携带 token"]:::entry
classDef entry fill:#71717a14,stroke:#71717a59,stroke-width:1px;
classDef gate fill:#f59e0b14,stroke:#f59e0b99,stroke-width:1.5px;
classDef exec fill:#14b8a614,stroke:#14b8a699,stroke-width:1.5px;
端点分类
对话
| 端点 | 说明 |
|---|---|
| POST /v1/chat | 流式对话(SSE) |
| POST /v1/sessions/{id}/resume | HITL 恢复——把确认结果送回图上继续 |
| GET /v1/sessions… | 会话列表、详情、历史 |
chat.py:234 chat chat.py:187 resume sse.py:39 sse_response
对话是流式的,用的是标准的 Server-Sent Events,但没有依赖
sse-starlette——一个几十行的辅助函数就够了。
「恢复」这个端点值得注意:HITL 暂停后,图是真的停在那个检查点上, 恢复不是重新跑一遍,而是从断点继续。
元数据与目录
| 端点 | 说明 |
|---|---|
| GET /v1/catalog/datasources | 可见的数据源列表 |
| GET /v1/catalog/tables | 表清单 |
| GET /v1/catalog/tables/{table_name} | 表详情 |
| GET /v1/catalog/tables/{table_name}/ddl | 建表语句 |
知识库
| 端点 | 说明 |
|---|---|
| GET /v1/kb/status | KB 状态 |
| GET /v1/kb/rules | 规则列表 |
| POST /v1/kb/lessons | 提交教训(写入即 pending) |
| GET /v1/kb/examples/pending | 待确认示例 |
| POST /v1/kb/lessons/confirm | 确认教训 |
注意「提交教训」这个端点的语义:它是用户反馈通道, 写进去的条目默认 pending,不会立刻影响检索。见知识库 · 门禁。
语义层
| 端点 | 说明 |
|---|---|
| POST /v1/semantic/query | 声明式查询——严格契约,未声明即 422 |
| GET /v1/admin/semantic/{name} | 语义模型详情(管理端,按数据源名寻址) |
| GET /v1/admin/semantic/{name}/history | 变更历史 |
| POST /v1/admin/semantic/{name}/drafts… | 草案的创建 / 批准 / 驳回 |
semantic.py:269 drafts semantic_query.py:139 semantic/query
POST /v1/semantic/query 与对话链路走同一个语义层,但契约更严:
遇到软 MISS 不降级,直接返回 422。理由见
语义层 · 声明式 API——
程序调用方无法判断哪些部分是权威的、哪些是模型补的。
管理端
| 分组 | 内容 |
|---|---|
| /v1/admin/users | 用户与 token |
| /v1/admin/datasources | 数据源注册、测试、KB 初始化;…/kb/distill-history 从历史蒸馏(202 长任务) |
| /v1/admin/actions | 行动模板与提案;…/proposals/batch 批量批准 / 驳回(逐条结果) |
| /v1/admin/jobs | 定时任务 CRUD 与运行历史 |
| /v1/admin/skills | Skills 草案、确认、tier |
| /v1/admin/drift | 漂移检测与处置 |
| /v1/admin/decisions | 决策规则 |
| /v1/admin/audit | 审计日志;/refusal-report 拒绝频率报表(窗口天数为参) |
| /v1/admin/memory… | 画像与偏好草稿 |
管理端路由只在存在真实认证组件时才挂载(auth / admin / jobs / skills / decisions / drift 六个)——这是 fail-closed 的一部分。语义模型那一组(/v1/admin/semantic/*)挂在门外,但它的每一条路由都依赖 require_admin,所以挡人的是那条依赖,不是挂载开关;认证被显式关掉(NullAuth)时,所有请求本来就以本地管理员身份运行。
关于 CORS
后端没有 CORSMiddleware。这不是遗漏:
- 生产形态下前端与
/v1同源(nginx 反代)。 - 开发形态下由 Vite dev server 代理
/v1到后端。
两种形态下浏览器视角都没有跨域。如果你想把前端部署到另一个域名, 需要在网关层处理,而不是期望后端开 CORS 头——当前后端不会发那些头。