Eurybia Frontend API(Ask + Plaza)· 供 didotxyz 团队
本文档是给 didotxyz 团队对接 Ask 圆桌对话 + Plaza 端点的唯一规范(2026-09-20 收口统一 API 平台)。 原
/api/frontend/*免鉴权路径已迁移:/api/frontend/ask/*→/v1/ask/*,/api/frontend/plaza/*→/v1/data/frontend/plaza/*。 需要X-API-Key的单轮 KOL 问答端点见ask-api-quickstart;统一鉴权/限流规则见gateway。
Base URL
https://api.eurybia.xyz
鉴权与跨域
- 鉴权:所有请求带
X-API-Key请求头(didotxyz 的 key 不变,随平台统一鉴权)。缺失/无效 →401,无路径权限 →403,限流/日配额超限 →429(详见gateway)。 - CORS 白名单:浏览器跨域调用时,仅白名单域名被放行。默认白名单
eurybia.xyz/di.xyz(含www.与http变体),配置在app/core/config.py的cors_allow_origins(环境变量同名可覆盖,逗号分隔)。 - 非浏览器调用(curl / 服务端)不受 CORS 限制,直接请求即可。
- 模型固定:所有 Ask 端点服务端固定使用
deepseek-flash,请求体无 model 字段,客户端不可选模型。 - 调用额度:Ask 端点无限流、不限额、不扣点(服务端不记账,扣点/积分由 DI 后台自管)。Plaza 另有每小时发帖限流(见注意事项)。
一、Ask —— KOL 圆桌讨论(拆解 + 三轮 + 思考模式)
0. 问题拆解(含可选澄清)
POST /v1/ask/decompose
Content-Type: application/json
请求体
{
"q": "BTC 现在还能上车吗?",
"idempotency_key": "可选,复用它作为 conversation_id(幂等)"
}
响应
{
"data": {
"standard_question": "发生美国降息事件时,BTC 将如何反应?",
"asset": "BTC",
"event": "美国降息",
"subject": "价格走势",
"period": null,
"clarify_question": "...",
"conversation_id": "a0dc3708..."
}
}
asset:用户问题中涉及的具体资产/市场/赛道(如 BTC、ETH、meme 币、DeFi)。🔴 保留用户明确提到的标的,不泛化不丢失;无明确标的时为null。clarify_question:非null时前端应展示输入框让用户补充说明,补充后带原始问题 + 说明重新调用本端点;null表示无需澄清。conversation_id:本轮对话唯一 ID。传idempotency_key则复用它(同一请求重试不会生成新记录)。字符串原样透传,不做任何规范化:带不带横线的 UUID 都原样存储、原样返回;不传idempotency_key时服务端生成 32 位无横线 hex(uuid4().hex)。- 本端点会写入
didotxyz.public.ask_conversations(含asset列,status=in_progress)。 - 🔴 幂等:相同
idempotency_key重复调用 → 复用同一conversation_id,不重调模型、不重复计费,响应带"cached": true。
1. 列出可用 KOL
GET /v1/ask/kols[?embed_avatar=true]
响应
{
"data": [
{"handle": "SexyMichill", "display_name": "Michill💕", "avatar": "https://...", "profile": "..."},
{"handle": "cz_binance", "display_name": "CZ 🔶 BNB", "avatar": "https://...", "profile": "..."}
]
}
embed_avatar:可选布尔。默认false→avatar返回 pbs 直链(链接形式);true→avatar返回 data URI(data:image/...;base64,...,图片内嵌,由服务端缓存兜底避免 pbs 404)。前端<img src={avatar}>两种形式都能直接渲染。handle规则:目录返回 X 上的真实 handle(原始大小写),如PhyrexNi、100trillionUSD、saylor。所有端点接收 handle 参数时大小写不敏感(服务端内部按小写规范化查找);round1/round2/selected_kols里回传的 handle 是前端传入的原值(通常即目录返回值)。
2. 搜索 KOL
GET /v1/ask/kols/search?q=<关键词>
q:关键词,对 handle / display_name / profile 模糊匹配(大小写不敏感)embed_avatar:可选布尔,同/ask/kols(默认 pbs 直链,true返回 data URI)。- 响应
{"data": [{"handle": ..., "display_name": ..., "avatar": ..., "profile": ...}]}(最多 20 条)
3. 自动挑选 KOL
GET /v1/ask/match?q=<问题>[&exclude=handle1,handle2]
q:问题(1~2000 字符,需 URL 编码)exclude:可选,逗号分隔的 handle,排除已选 KOL(换一组 / 替换时用)
响应
{"data": {"selected": [
{"handle": "PhyrexNi", "display_name": "Phyrex", "avatar": "https://...", "reason": "擅长链上数据,能提供 BTC 走势判断", "available": true}
]}}
selected 为 3 个对象,按相关性排序;reason 为推荐理由。
4. 第一轮:KOL 流式回答(含思考过程)
GET /v1/ask/stream/{handle}?q=<问题>&conversation_id=<会话ID>
handle:KOL 真实 handle(原始大小写,如PhyrexNi/saylor;大小写不敏感,服务端按小写规范化查找)conversation_id:🔴 必填,decompose 返回的会话 ID。- 返回
text/plain流式响应,先流式输出思考过程,再流式输出正文。协议见 §流式协议。 - 幂等:该 KOL 第一轮已答过(round1 里有)→ 模拟打字机直接返回缓存(不重调模型),流式格式不变。
5. 第二轮:KOL 流式点评其他 KOL(含思考)
POST /v1/ask/comment/{handle}
Content-Type: application/json
请求体
{
"q": "BTC 现在还能上车吗?",
"conversation_id": "a0dc3708...(decompose 返回的 id,必填)",
"others": [
{"handle": "cz_binance", "display_name": "CZ 🔶 BNB", "answer": "..."},
{"handle": "naval", "display_name": "Naval", "answer": "..."}
]
}
conversation_id:🔴 必填,decompose 返回的会话 ID。others:其他 KOL 的第一轮回答列表(不含自己)- 返回
text/plain流式响应(思考 + 评论正文) - 幂等:该 KOL 第二轮已评过(round2 里有)→ 模拟打字机直接返回缓存(不重调模型)。
6. 第三轮:主持人基于事实的结构化报告(含思考)
POST /v1/ask/conclude/v2
Content-Type: application/json
请求体
{
"q": "BTC 现在还能上车吗?",
"conversation_id": "a0dc3708...(decompose 返回的 id,必填)",
"round1": [
{"handle": "saylor", "display_name": "Saylor", "answer": "..."},
{"handle": "cz_binance", "display_name": "CZ 🔶 BNB", "answer": "..."}
],
"round2": [
{"handle": "saylor", "display_name": "Saylor", "comment": "..."},
{"handle": "cz_binance", "display_name": "CZ 🔶 BNB", "comment": "..."}
]
}
- 返回
text/plain流式响应:思考过程 + JSON 报告(见 §流式协议)。 - 主持人为 didotxyz 人设,总结时注入事实包:top 10 新闻(3 天)+ FRED 宏观数据(3 天发布,含最新值/上期值/环比)。
- 🔴 证据搜集时机:事实包由服务端在 conclude/v2 阶段拉取,且不是按本次问题做定向检索——而是「最近 3 天通用 top 事实」(新闻按评分取 top 10、FRED 取 3 天发布的核心指标)。第一轮
stream与第二轮comment不做任何检索,纯靠 KOL 人设 + 问题生成。 - 流式结束后服务端后台写入
ask_conversations.conclusion(status=completed)。 - 🔴 幂等:相同
conversation_id重复调用 → 直接返回缓存的完整报告(不重调模型、不重复计费),流式响应为一条{t:c}完整 JSON +{t:done}。 - 当前端点为
/ask/conclude/v2。
报告 JSON 结构(流式 content 拼合后解析,9 字段)
{
"long_conclusion": "综合结论长文…",
"stage_impacts": [{"stage": "短期", "impact": "...", "evidence": [{"text": "引用描述", "source": "Cointelegraph", "url": "https://...", "time": "2026-09-02"}]}],
"kol_summaries": [{"handle": "saylor", "position": "..."}],
"consensus": ["共识点1"],
"divergence": ["分歧点1"],
"facts": [{"fact": "...", "evidence": [{"text": "引用描述", "source": "FRED H.15", "url": "https://fred.stlouisfed.org/series/DGS10", "time": "2026-09-01"}]}],
"inferences": [{"inference": "...", "confidence": 65, "risk": "..."}],
"assumptions": ["假设1"],
"unknowns": ["未知点1"]
}
stage_impacts[].evidence与facts[].evidence是对象数组{text, source, url, time}:text引用描述、source来源名、url原文/数据链接(可点击)、time数据/发布日期(YYYY-MM-DD,新闻为发布时间,FRED 为数据日期)。url/time无对应值时为null。- 前端渲染建议:
url非空时把text包成<a href=url target=_blank>,否则纯文本;time可跟在链接后以小字展示。
6.5 按 conversation_id 查询对话状态(断网/关页面后找回)
GET /v1/ask/history/{conversation_id}
- 根据 decompose 返回的
conversation_id查询一次对话的状态与最终结论。 - 不存在返回 404(
{"detail":{"code":"NOT_FOUND","message":"..."}})。
响应
{
"data": {
"conversation_id": "a0dc3708...",
"status": "completed",
"raw_question": "BTC 现在还能上车吗?",
"standard_question": "...",
"asset": "BTC",
"event": "...",
"subject": "...",
"period": null,
"selected_kols": [{"handle": "saylor"}],
"round1": [{"handle": "...", "display_name": "...", "answer": "..."}],
"round2": [{"handle": "...", "display_name": "...", "comment": "..."}],
"conclusion": { ... 完整报告对象 ... },
"error_code": null,
"created_at": "2026-09-04T00:00:00",
"updated_at": "2026-09-04T00:01:30"
}
}
status:in_progress(生成中)|failed(已中断,带error_code)|completed(已写入 conclusion)。error_code:失败时的结构化原因(如CONCLUDE_EMPTY/CONCLUDE_INVALID_JSON/CLIENT_ABORT),非 failed 时为null。- 前端进入时按
conversation_id查一次:completed直接渲染 conclusion,failed提示“已中断”并可选展示 error_code,in_progress提示“生成中”,不存在提示重做。
响应 headers(200 / 404 均带)
content-type: application/json; charset=utf-8
X-Request-Id: <32 位 hex>
X-Request-Id 每次请求随机生成,仅用于日志关联,无幂等语义(幂等靠 conversation_id)。
三态样例
-
completed(HTTP 200)—— 完整字段见上方响应示例,status="completed",round1/round2/conclusion非空。 -
in_progress(HTTP 200)—— decompose 已落库、尚未 conclude 的典型形态:
{
"data": {
"conversation_id": "0cd565ae1dc34d2ea059f08b2a5a6ea6",
"status": "in_progress",
"raw_question": "怎么看 meme 币的这波行情?",
"standard_question": "发生 meme 币这波行情时,投资者将如何反应?",
"asset": "meme 币",
"event": "这波行情",
"subject": "投资者",
"period": null,
"selected_kols": [],
"round1": [],
"round2": [],
"conclusion": null,
"error_code": null,
"created_at": "2026-09-09T06:38:19.787194",
"updated_at": "2026-09-09T06:38:19.787194"
}
}
failed(HTTP 200)—— 中断/失败,error_code说明原因:
{
"data": {
"conversation_id": "f42e5d61-660a-4645-9477-ea58e94c0df4",
"status": "failed",
"raw_question": "如果结构性机会浮现,会对加密市场产生什么影响?",
"error_code": "CLIENT_ABORT",
"round1": [ ... 已保存的部分发言 ... ],
"round2": [],
"conclusion": null
}
}
404 NOT_FOUND(HTTP 404)—— conversation_id 不存在:
{"detail": {"code": "NOT_FOUND", "message": "conversation not found: <id>"}}
conclusion 语义边界:conclusion 只含第三轮(最终)结构化报告(9 字段),不含第一/二轮正文。四阶段完整记录在同一次响应的其他字段,无需额外接口:
| 阶段 | 字段 | 格式 |
|---|---|---|
| 问题拆解 | standard_question / asset / event / subject / period | 字符串,可为 null |
| KOL 选择 | selected_kols | [{"handle": "..."}] |
| 第一轮回答 | round1 | [{"handle","display_name","answer"}] |
| 第二轮评论 | round2 | [{"handle","display_name","comment"}] |
| 第三轮总结 | conclusion | 9 字段报告对象,或 null |
conclusion内的 evidence 在facts[].evidence与stage_impacts[].evidence,每条为{text, source, url, time};inferences[].confidence为 0~1 小数、inferences[].risk为风险观察。- 主动标记中断:
POST /v1/ask/abort,body{conversation_id, error_code?}(error_code可选,默认CLIENT_ABORT)。前端确认放弃时调用,把对话标记为failed。 - 客户端断开不影响生成:
stream/comment/conclude/v2的生成与转发已解耦,客户端断开只停止转发、生成会继续跑完并落库。用户断网/关浏览器后,回头查 history 能拿到完整结果(与是否在线无关)。 - 仅当模型空输出/报告 JSON 解析失败时才标记
failed(CONCLUDE_EMPTY/CONCLUDE_INVALID_JSON);客户端断开不再是失败原因。 - 时间格式:
created_at/updated_at为 ISO 字符串(YYYY-MM-DDTHH:MM:SS.microseconds,无时区后缀);evidence 里的time随源保留原样(新闻YYYY-MM-DDTHH:MM:SS,FREDYYYY-MM-DD)。
7. 简化版:一键自动问答(非流式)
GET /v1/ask/auto?q=<问题>[&handles=saylor,cz_binance]
- 自动挑选 1~3 个 KOL 并一次性返回回答(非流式、无思考过程)
handles:可选,逗号分隔的 handle,传了则跳过自动匹配
响应
{
"data": {
"selected": ["saylor", "cz_binance"],
"answers": [
{"handle": "saylor", "display_name": "Michael Saylor", "in_scope": true, "answer": "..."},
{"handle": "cz_binance", "display_name": "CZ 🔶 BNB", "in_scope": true, "answer": "..."}
]
}
}
8. 简化版:单 KOL 问答(非流式)
GET /v1/ask/{handle}?q=<问题>
- 与指定 KOL 单轮对话,非流式、无思考过程
- 响应:
{"data": {"handle": "...", "display_name": "...", "in_scope": true|false, "answer": "..."}} in_scope=false时answer固定为「问题超出回答范围」
二、Plaza —— KOL 新闻评论 timeline
帖子列表(分页)
GET /v1/data/frontend/plaza/posts?limit=20&offset=0
| 参数 | 说明 |
|---|---|
limit | 每页条数,默认 20,范围 1~200 |
offset | 偏移量(分页) |
响应
{
"data": [
{
"id": 711,
"handle": "saylor",
"display_name": "Michael Saylor",
"avatar": "https://...",
"post_text": "Bitcoin is Digital Capital...",
"news_id": 600410539,
"news_title": "Multicoin Capital 近9小时将2170万美元HYPE转入Coinbase Prime",
"news_source": "PANews RSS",
"news_link": "https://...",
"news_time": "2026-09-02T01:14:00",
"created_at": "2026-09-02T01:14:00"
}
],
"count": 20,
"total": 715
}
total用于判断是否还有更多(offset + count < total)created_at为 UTC 时间(无时区 ISO 字符串,前端需按 UTC 解析)
流式协议
第一轮 / 第二轮 / 第三轮端点均返回 text/plain 流,每行一个 JSON 对象(\n 分隔):
{"t":"r","d":"思考增量"}
{"t":"c","d":"正文增量"}
{"t":"e","code":"EMPTY_CONTENT","d":"错误信息","retryable":true}
{"t":"done"}
t | 含义 |
|---|---|
r | 思考过程增量(reasoning_content) |
c | 正文增量(content)。第一/二轮为纯文本;第三轮为 JSON 报告的片段 |
e | 错误(d 为错误描述,code 为稳定错误码,retryable 为是否可重试,出现后流即结束) |
done | 正常结束标记(只出现在 c 正文非空时) |
- 思考过程先于正文到达;前端通常先流式展示思考(小字),思考结束后折叠,再展示正文。
- 客户端需按行缓冲解析(最后一个 chunk 可能不含完整行,需保留到下一 chunk 拼接)。
错误码与重试
错误行含 retryable 布尔字段,前端只看这个字段决定是否重试,无需理解每个 code:
| code | 触发 | retryable | 前端动作 |
|---|---|---|---|
EMPTY_CONTENT | 模型空输出(不说话) | ✅ | 同一 conversation_id 自动重试(空结果未落库,会重新调模型) |
TIMEOUT / REQUEST_ERROR | 超时 / 断连 | ✅ | 自动重试 |
DEEPSEEK_HTTP_429 / DEEPSEEK_HTTP_5xx | 限流 / 服务端错 | ✅ | 退避后重试 |
CONTENT_RISK | 400 Content Exists Risk(前文含敏感词) | ❌ | 停止,并短路整个 conversation |
DEEPSEEK_HTTP_4xx(其他) | 格式 / 鉴权 / 余额 | ❌ | 显示错误 |
API_KEY_MISSING / INTERNAL_ERROR | 配置 / 未知 | ❌ | 显示错误 |
重试规则:retryable=true 时,用同一个 conversation_id 重试(幂等缓存只在"已成功落库"时命中,失败未落库会重新调模型)。建议最多重试 2 次,429 加 1s 退避。
⚠️ 幂等缓存返回的 JSON 键顺序可能不同:命中缓存时,后端返回的是 json.dumps 重新序列化的 JSON,键顺序可能与首次流式输出不同(字节不同、语义相同)。前端应 json.loads 后处理,不要对 content 字符串做精确比较。
🔴 CONTENT_RISK 是短路信号:它表示前文(round1 其他 KOL 的回答)含有敏感词,不是当前 KOL 偶发失败。重试会重复发送同一段被污染的前文,必继续 400。前端收到后应:
- 停止当前流;
- 标记该 conversation 为 risk,不再发起后续任何调用(其余 KOL 的 round2、conclude 都跳过);
- UI 提示"该话题涉及敏感内容,无法继续生成",引导用户换问题重开。
错误响应(非流式端点)
非流式端点(decompose / match / kols/search / auto / 单KOL)的参数错误返回结构化 detail:
{"detail": {"code": "EMPTY_Q", "message": "q must not be empty"}}
| code | 说明 |
|---|---|
EMPTY_Q | q 缺失或为空 |
INVALID_BODY | 请求体字段类型非法(如 round1/exclude 非数组) |
UNKNOWN_KOL | 未知 KOL handle |
三轮编排流程(前端参考)
decompose → match(可换一组,可删除/搜索添加)→ [第一轮:并发 stream 每位 KOL] → [第二轮:并发 comment 每位 KOL] → [第三轮:conclude/v2]
decompose得到conversation_id+ 拆解结果;若clarify_question非空则让用户补充后重拆match得到 3 位 KOL(含reason);前端可「换一组」(match + exclude)或「删除 + 搜索添加」stream并发流式回答每位 KOL(第一轮)- 若
selected.length > 1,进入第二轮:comment并发点评(others= 其余 KOL 的第一轮回答) - 第三轮
conclude/v2输入 = 第一轮全部回答 + 第二轮全部评论 +conversation_id - 思考模式:第一/二轮
reasoning_effort=low;第三轮(主持人)也为low(控制耗时 < 30s)
注意事项
- 超时:完整三轮对话实测约 15~30s(主持人思考已降为 low);客户端超时建议 ≥ 120s,流式读取期间注意代理
read_timeout(服务端 nginxapi.eurybia.xyz已设 300s)。 - 流式缓冲:nginx
api.eurybia.xyz已开proxy_buffering off(2026-09-07),流式内容逐步输出(首字节 < 1s,思考→正文按真实生成节奏逐行到达),前端可据此驱动头像发言/文字/动效动画。 - 并发:全部 LLM 端点(Ask 流式 + Ask 非流式 + Plaza 生成)均已改为异步实现(httpx,不占线程池),单实例可承受数百并发(实测 200 并发全成功,首字节延迟中位 1.5s);实际瓶颈在 DeepSeek 服务端(Flash 并发上限 2500)。
- 语言跟随:回答语言与提问语言一致——中文提问用中文回答,英文提问用英文回答(覆盖第一/二/三轮,含思考过程与总结)。
- Plaza 限流:KOL 池扩容后,Plaza 每个 KOL 每小时最多发 1 条,且只对「足够重要」的新闻发帖(宁缺毋滥);
plaza/posts每小时新增条数会相应减少。 - 不缓存:每次调用独立生成。
- 免责:KOL 回答与总结均为 AI 人设生成,不构成投资建议。
变更记录
| 日期 | 变更 | 对接影响 |
|---|---|---|
| 2026-09-20 | 🔴 统一 API 平台收口:base URL 换 https://api.eurybia.xyz;路径 /api/frontend/ask/* → /v1/ask/*、/api/frontend/plaza/* → /v1/data/frontend/plaza/*;鉴权从 keyless 改为统一 X-API-Key(key 已签发,didotxyz 侧不用换) | 🔴 破坏性(必须切新 base URL + 路径 + 加 key 头;旧 /api/frontend/* 路径保留过渡) |
| 2026-09-02 | Ask 非流式端点(match/auto/单KOL)+ Plaza 生成异步化,全部 LLM 端点不再占用线程池 | 无(接口契约不变) |
| 2026-09-02 | 新增语言跟随:中文提问→中文回答,英文提问→英文回答 | 无(新增能力,不破坏现有调用) |
| 2026-09-02 | 移除 KOL 回答中的 DYOR/NFA 免责词要求 | 轻微(回答不再强制带 DYOR/NFA,前端无需处理) |
| 2026-09-03 | KOL 池扩容:9 → 45 个(新增 19 个人类 crypto/财经 KOL + 17 个中文 KOL) | 无(/ask/kols 返回更多,match 可选范围更大) |
| 2026-09-03 | Plaza 限流:每个 KOL 每小时最多发 1 条,只对「足够重要」的新闻发帖 | 轻微(Plaza 帖子密度下降) |
| 2026-09-03 | Ask 流程重构:新增 decompose(含 clarify + idempotency_key)、kols/search、kols/reselect;match 返回对象数组(含 reason);conclude 替换为 conclude/v2(9 字段结构化报告) | 🔴 破坏性(match 响应结构变更、conclude 已移除) |
| 2026-09-03 | Ask 全面 review 12 项修复:conclude 写库改 BackgroundTask、错误码结构化(EMPTY_Q/INVALID_BODY/UNKNOWN_KOL)、decompose 幂等、fred 查询优化(target_series 先筛 + popularity 入 GROUP BY)、建表去重、前端删除/添加 KOL + clarify 交互 + 重试不闪回 | 无(接口契约不变,新增 idempotency_key 可选参数) |
| 2026-09-03 | 主持人思考 reasoning_effort 由 high 降回 low(控制单轮 < 30s);max_tokens 6000→12000;新增 EMPTY_CONTENT 空正文检测 | 无(流式新增 code 字段,前端可据此重试) |
| 2026-09-03 | decompose 新增 asset 字段(标的/市场),避免拆解丢失用户所问市场;对话表加 asset 列 | 轻微(decompose 响应新增字段,老客户端忽略即可;不影响现有字段) |
| 2026-09-04 | conclude/v2 的 evidence 从字符串改为对象数组 {text, source, url}(URL 可点击,来自新闻 link / FRED 系列页);新增 GET /ask/history/{conversation_id}(断网找回状态与结论) | 🔴 破坏性(evidence 结构变更,前端需适配新格式);新增端点不影响现有调用 |
| 2026-09-07 | evidence 增加 time 字段(YYYY-MM-DD,新闻发布时间/FRED 数据日期);nginx /api/frontend/ 开 proxy_buffering off 修复流式缓冲(此前首字节约 9.7s、内容挤在一起) | 轻微(evidence 新增字段,老客户端忽略即可);流式节奏修复,前端可跟随真实进度 |
| 2026-09-09 | 文档补全:模型固定说明、Ask 无限流不限额、handle 原始大小写规则、conversation_id 原样透传、证据搜集时机(仅 conclude 阶段、非定向检索)、history 三态样例 + headers、conclusion 四阶段字段映射、无取消端点说明 | 无(文档补全,接口契约不变) |
| 2026-09-11 | conversation_id 贯穿四阶段 + 阶段级幂等:stream/comment/conclude 必填 conversation_id(stream 走 query 参数,comment/conclude 走 JSON body);重复请求命中缓存直接返回(stream/comment 模拟打字机,conclude 返回完整报告),不重调模型不重复计费 | 🔴 破坏性(stream/comment/conclude 缺 conversation_id 返回 400 MISSING_CONVERSATION_ID) |
| 2026-09-13 | 流式错误行新增 retryable 字段(前端据此决定是否重试);新增 CONTENT_RISK 错误码(400 Content Exists Risk,前文含敏感词,前端应短路整个 conversation) | 轻微(错误行新增字段,老客户端忽略即可;建议前端按 retryable 自动重试、CONTENT_RISK 短路) |
| 2026-09-13 | history 三态:新增 failed 状态 + error_code 字段;conclude 失败自动标 failed;新增 POST /ask/abort 主动标记中断 | 轻微(history 响应新增字段;前端可区分「生成中」与「已中断」) |
| 2026-09-13 | 语言约束增强:四阶段(decompose/stream/comment/conclude)全部跟随用户语言,英文提问最高优先级禁汉字 | 无(输出语言更稳定,英文任务不再偶发混入中文) |
| 2026-09-13 | 生成与转发解耦:stream/comment/conclude/v2 客户端断开后后台继续生成完并落库(断网/关浏览器不再导致任务中断,history 必有完整结果) | 无(行为增强;客户端断开不再是失败原因,DI 无需为断线做重试/补生成) |