8.4 KiB
DashScope 风格兼容对话 API v1 Spec
| 项 | 内容 |
|---|---|
| 状态 | Implemented |
| 日期 | 2026-09-05 |
| 负责人 | fire-safety-ymd 后端 |
| 需求来源 | 复用既有客户端的 /api/v1/apps/{app_id}/completion、xtoken 与 event: result 契约 |
1. 背景
既有用户端按照 DashScope Application HTTP 形式调用固定应用路径,并以 SSE result 事件读取 output.session_id、finish_reason 和 text。本项目原生 /api/chat 的请求体与事件名称不同。为避免客户端一次性重写,本 checkpoint 在同一 Chat Service 之上增加一个受限兼容适配层,并保留原生接口。
本契约参考阿里云官方 Application API 的路径、input.prompt、input.session_id 和 SSE 结果外形,但不是 DashScope 全量代理或完整复刻。
2. 目标
- 新增可选的
POST /api/v1/apps/{app_id}/completion。 - 接收既有客户端的
xtoken、input.prompt、可选input.session_id和parameters空对象。 - 返回
event: resultSSE;首个事件提供会话 ID,严格成功事件以finish_reason: "stop"终止。 - 复用
/api/chat的会话容量、TTL、同会话并发排斥、SuperAgent 严格完成判定和错误分类。 - Nginx 只终止 TLS、限制路径、限流并反代本 Go 服务,不保存或注入任何应用 Secret。
3. 非目标与兼容边界
- 不移除或改变原生
POST /api/chat。 - 不实现 DashScope 的
messages、biz_params、文件、图像、知识库、思考过程或任意parameters。 - 不代理到 DashScope,也不把兼容
app_id当成真正的 SuperAgent Profile ID。 - 不向客户端暴露 Provider Session、Run、Trace、工具参数/结果或半截回答。
- 不提供非流式 JSON 模式;即使请求未带
X-DashScope-SSE: enable,本兼容路径也始终返回 SSE,以匹配现有客户端。 parameters.incremental_output仅为输入兼容而接受。v1 只有严格完成后的一个正文结果,因此true与false不改变正文分片方式。- 静态
xtoken只用于受控联调,不是最终用户身份或动态授权。
4. 配置与路由
| 环境变量 | 默认值 | 说明 |
|---|---|---|
FIRE_SAFETY_CHAT_COMPAT_APP_ID |
空 | 非空时注册兼容路径;1 至 128 个 ASCII 字母、数字、下划线或连字符 |
FIRE_SAFETY_CHAT_AUTH_TOKEN |
空 | 兼容路径期望的 xtoken;默认至少 32 个可打印 ASCII 字符,兼容开关开启时允许已交付的旧短凭证 |
FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN |
false |
仅为已交付旧客户端短凭证的受控测试/迁移临时兼容开关;新环境不得开启 |
兼容路径只有在 FIRE_SAFETY_CHAT_ENABLED=true 且 App ID 非空时注册。App ID 是用于路径匹配的公开标识,不是 Secret;不匹配的路径返回 404。
FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN 默认为 false。只有在旧客户端已经拿到、且无法立即更换的短 xtoken 时,才可在受控测试或迁移窗口显式设置为 true。无论开关取值如何,Chat 凭证都必须非空、不超过 4096 字节,并且每个字符都在 ASCII 0x21-0x7e 范围内(不得包含空格、控制字符或 Unicode);开关同时适用于原生 /api/chat 的 Bearer 和本兼容路径的 xtoken,不放宽 MCP Token 至少 32 个可打印 ASCII 字符的门禁。Chat、SuperAgent Open API 和 MCP 三种凭证仍必须使用不同值。凭证轮换完成后必须恢复 false,新环境不得开启该开关。开关启用时,服务启动日志会记录不含 Secret 的安全 warning,便于后续清理。
5. 请求契约
POST /api/v1/apps/fire-safety-public-app/completion
xtoken: <FIRE_SAFETY_CHAT_AUTH_TOKEN>
Content-Type: application/json
Accept: text/event-stream
{
"input": {
"prompt": "杨家盘瞭望哨 3 公里内的水源?"
},
"parameters": {}
}
后续轮次把前一轮成功响应的 output.session_id 放回 input:
{
"input": {
"prompt": "再说明这些候选的限制",
"session_id": "conv_..."
},
"parameters": {
"incremental_output": true
},
"debug": {}
}
约束:
input.prompt必填,非空,并服从现有消息大小上限。input.session_id只能是本服务此前返回的本地会话 ID;服务端仍负责映射 Provider Session。parameters可省略、为空对象,或只包含布尔型incremental_output。debug可省略或只能是空对象。- 未知字段、
null、错误类型、尾随 JSON 和超大请求体均拒绝。 - 兼容 DTO 不接收用户身份、角色、区域、租户、Provider Session 或 metadata。
6. 成功 SSE
Prepare 成功后先发送会话事件。finish_reason 的初始值按官方示例使用字符串 "null",不是 JSON null:
id: 1
event: result
:HTTP_STATUS/200
data: {"output":{"session_id":"conv_...","finish_reason":"null"},"usage":{},"request_id":"..."}
只有 SuperAgent Adapter 同时验证最终内容、成功 run.completed 和顶层 end 后,才发送终止事件:
id: 2
event: result
:HTTP_STATUS/200
data: {"output":{"session_id":"conv_...","finish_reason":"stop","text":"..."},"usage":{"models":[{"input_tokens":12,"output_tokens":34,"model_id":"qwen-plus-latest"}]},"request_id":"..."}
- 两个事件的
session_id和request_id必须相同。 session_id是本地随机会话 ID,不是 Provider Session。model_id在上游未提供有效模型名时省略;token 数量是当前 Provider 返回的单轮聚合值。- 等待期间每 15 秒可发送不含业务数据的 SSE comment heartbeat。
- 客户端只有看到
event: result且output.finish_reason == "stop"才能把本轮视为成功。
7. 错误
SSE 开始前使用 HTTP 状态和 DashScope 风格安全 JSON:
{"code":"CHAT_AUTH_INVALID","message":"Chat authentication failed.","request_id":"..."}
SSE 开始后的失败发送 event: error,只包含稳定 code、通用 message、request ID 和本地 session ID;不发送 finish_reason: "stop",也不返回任何已接收的部分回答。
沿用原生 Chat 的主要状态:400 输入错误、401 token 错误、403 Origin 错误、404 App/会话不存在、409 会话忙、503 容量不足,以及 502/504 上游失败或超时。
8. CORS、Nginx 与 Secret
- 浏览器 Origin 必须精确出现在
FIRE_SAFETY_CHAT_ALLOWED_ORIGINS;不允许*或 credentials。 - 预检只允许
POST以及Content-Type、xtoken、X-DashScope-SSE、X-Request-ID。 - Nginx 示例只公开精确兼容路径、
/mcp和可选/health,其余路径返回 404。 - Nginx 不比较或注入
xtoken、SuperAgent Open API Key、MCP Bearer 或数据库凭证;Header 原样交给 Go 验证。 - 对话 SSE 必须关闭代理缓冲、缓存、gzip 和上游自动重试,并让代理超时覆盖 Chat 总运行时限。
9. 验收标准
- Given App ID 未配置,When 请求兼容路径,Then 路由返回 404,原生
/api/chat行为不变。 - Given App ID 或
xtoken错误,When 请求,Then 在读取问题和调用 SuperAgent 前拒绝。 - Given
FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN未开启,When 已交付的旧xtoken少于 32 个字符,Then 服务启动配置校验失败。 - Given
FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN=true,When 旧短xtoken用于受控测试/迁移,Then 兼容入口允许该凭证但仍执行非空、4096 字节上限和 ASCII0x21-0x7e校验,并记录不含 Secret 的安全 warning;MCP Token 的至少 32 字符门禁不变。 - Given 首轮请求成功,When 读取 SSE,Then 先收到字符串
"null"会话事件,再收到同会话"stop"最终正文。 - Given 后续请求携带成功返回的
session_id,When 调用,Then 复用同一服务端会话映射。 - Given Provider 流失败,When SSE 已开始,Then 收到安全
error,不收到部分正文或stop。 - Given Nginx 配置生效,When 请求未列出的路径,Then 不会转发到 Go 或外部 DashScope。
10. 协议来源
- Alibaba Cloud Model Studio Application API reference
- Call a Model Studio application by using an API
外部文档会演进;本项目以本 Spec 和自动化测试定义的受限兼容子集为准。