fix(gateway,channelbridge,turnreply): p 标签半包写入侧规整(修「整条塌成一段」)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

裁定(已发安卓):**能修**,走**写入侧规整** —— 不指望模型输出、不动客户端。
- 新增 internal/runtime/turnreply/paragraph.go 的 NormalizeParagraphs:
  把未被 <p> 包裹的段落补上 <p>(按空行分段;<action>/<narration> 段也包进 <p>,
  与正确形态 <p><action>…</action>…</p> 一致)
- **幂等**守门断言:已完全包裹的文本逐字不变(防二次加工)
- 落点覆盖 Web 与 IM 两条落库路径(gateway/session_turn_reply.go、channelbridge/turnreply.go、
  proactive.go)⇒ 两边共用同一份规整文本 ⇒ **历史一次性变好、两个客户端零改动**、渲染口径不分叉
(测试与变异详见切片报告)
This commit is contained in:
AskaEth committed 2026-10-05 10:56:39 +08:00
1 parent d532eb3fcd
commit 5de708a560
17 files changed
+721 -46

No files matched your search

@@ -309,10 +309,12 @@ func TestOwnerPrivatePersistsToMainSessionWithPlatform(t *testing.T) {
recs[0].Mode != "chat" {
t.Fatalf("user record = %+v, want web/telegram/hello/telegram/chat", recs[0])
}
// 助手正文的落库内容是**规范形态**(写入侧段落包裹规整,见
// turnreply_paragraph_test.go):这里只关心归属字段,因此只要求包裹正确。
if recs[1].SessionID != history.MainSessionID || recs[1].Role != history.RoleAssistant ||
recs[1].Content != "微信回复" || recs[1].Platform != "telegram" || recs[1].AdapterID != "telegram" ||
recs[1].Content != "<p>微信回复</p>" || recs[1].Platform != "telegram" || recs[1].AdapterID != "telegram" ||
recs[1].Mode != "chat" {
t.Fatalf("assistant record = %+v, want web/telegram/微信回复/telegram/chat", recs[1])
t.Fatalf("assistant record = %+v, want web/telegram/<p>微信回复</p>/telegram/chat", recs[1])
}
// 每条已持久化的消息都交给了广播钩子。
if len(persisted) != 2 {
@@ -359,7 +361,7 @@ func TestOwnerPrivatePersistsToMainWithDeviceID(t *testing.T) {
if recs[0].Role != history.RoleUser || recs[0].Content != "hello" {
t.Fatalf("user record = %+v", recs[0])
}
if recs[1].Role != history.RoleAssistant || recs[1].Content != "微信回复" {
if recs[1].Role != history.RoleAssistant || recs[1].Content != "<p>微信回复</p>" {
t.Fatalf("assistant record = %+v", recs[1])
}
}