fix(channelbridge): IM 入站附件引用写进落库的用户消息(安卓报的 P0)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

根因:摄取结果只挂到「内存里的模型可见消息」(inbound.go 的 attachInboundAttachments),
落库时只传了 text、history.Message 没有 Document 字段 ⇒ 该列恒空 ⇒ 读侧 omitempty
导致 documents 键整个缺席 ⇒ 任何客户端只看到一条空消息。Web 侧不这样,是因为
gateway/session_persist.go 有 messageTextImageDocument 把 ContentTypeDocument 部件编码进该列
—— IM 路径缺的就是同一步。
修法:inboundAttachments.documentColumn() 复用 history.EncodeDocuments 同一口径写出该列;
persistToMain/persistIsolated 增 document 参数并返回刚落库的消息;新增两段式第二段
persistTurnDocumentStatus 按 id 回写抽取结论(只补结论、按存储名匹配、匹配不到原样留),
与 gateway/session_document_status.go 逐字对齐。
契约零扩张:无新端点/帧/字段;0 附件 ⇒ 列空 ⇒ 键省略;形状即 web 的同一结构体。
测试 6 条(含元素 JSON 逐字断言、unreadable 带 reason、被拒不编造芯片、群聊隔离分支、
真循环端到端);变异两条(还原挂载 / 关闭结论回写)⇒ 各 4 条红。
This commit is contained in:
AskaEth committed 2026-10-05 08:10:21 +08:00
1 parent f8f2e9c54c
commit 679cee04f7
7 files changed
+606 -19

No files matched your search

+3 -1
View File
@@ -236,7 +236,9 @@ func (b *Bridge) mentionsTriggerWord(text string) bool {
// 收到该消息的账号适配器,日志因此带上适配器配置标签。
// 它是最小打扰路径中「登记」的那一侧。
func (b *Bridge) registerSilenced(ctx context.Context, msg adapter.UnifiedMessage, actor adapter.Actor, sess session.Session, a adapter.PlatformAdapter) {
b.persistIsolated(ctx, history.RoleUser, msg.Content, deviceIDFor(msg), sess, msg.Platform, senderDisplayName(msg, actor), adapterName(a))
// 被静默的消息不摄取附件(摄取在闸门之后),因此这一列恒为空 ——
// 绝不写一条指向不存在文件的引用。
b.persistIsolated(ctx, history.RoleUser, msg.Content, "", deviceIDFor(msg), sess, msg.Platform, senderDisplayName(msg, actor), adapterName(a))
b.log.Debug("non-owner message silenced, registered only",
"platform", msg.Platform, "channel", msg.ChannelID, "session", sess.SessionID)
}