feat(notify): IM 路由的主动消息也在非前台补浏览器通知(契约 v0.74)
主人裁定 C 的必然推论:她该不该提醒我,与后端走了哪条路由无关。P0 如实报回的缺口 = 通知只挂在 proactive_message 帧上,而 auto 提示在有已连接 IM 渠道时优先走 IM ⇒ 最常发生的路径恰恰不弹。 判据(先查现状、不猜):行字段**区分不出**主动推送与普通回复(已用真库证据排除 platform/adapterId/turnId 反推)⇒ 新增**结构化的正向声明**:帧顶 data.proactive === true,只由主动推送那条通道打(gateway.BroadcastProactivePersisted);普通路径永远传 false。 - 后端:channelbridge 抽出唯一写入口径 persistMain + 新增 proactive_notify 接缝;gateway 抽出 broadcastPersisted(msg, proactive) 两入口共用 - 前端:handlers/proactive-notice.ts 两条帧路共用同一套提醒运行时(有界去重 + 降级说明 + DOM/Notification 取值);message.ts 读到判据才走提醒 - 对照断言(必须有):普通 IM 回复/主人提问/显式 proactive:false ⇒ **0 通知、3 气泡**(不误伤) - 变异实测:去掉非主动保护 / 跨两路去重失效 / 前台也弹 / IM 不发判据帧 / 普通广播带判据 ⇒ 5 条全部打红 - 契约 v0.74(纯增量:message_persisted 新增可选 proactive:true) - 边界(如实):判据**不落库**(翻历史不弹提醒,也不得从行字段反推);落库失败时不发判据帧(无权威 id 的帧前端整帧丢弃)
This commit is contained in:
1 parent
a6cb44b8a8
commit
f4adf0b526
13 files changed
+652
-122
No files matched your search
@@ -92,6 +92,24 @@ func (s *Server) SendProactive(ctx context.Context, msg adapter.UnifiedMessage)
|
||||
return s.hub.SendProactive(ctx, msg)
|
||||
}
|
||||
|
||||
// BroadcastProactivePersisted 把一条**刚落进主会话的主动消息**广播为**带结构化判据**的
|
||||
// `message_persisted` 帧(切片 P0b)。判据就是帧顶的 `proactive:true`:它是「她主动说的
|
||||
// 话」在线上唯一的标记,客户端据此走与 `proactive_message` **同一套**提醒逻辑(非前台才
|
||||
// 补一发通知,同一条只提醒一次),于是「她该不该提醒我」**与后端走了哪条路由无关**
|
||||
// (主人 2026-10-05 裁定 C)。
|
||||
//
|
||||
// 它由 IM 桥的主动推送在**落库之后**调用(组合根接线 SetOnProactivePersisted)。为什么
|
||||
// 需要它:IM 路由过去只发普通 `message_persisted`,而浏览器通知挂在 `proactive_message`
|
||||
// 上 ⇒ 走 IM 的主动消息一条都不弹;偏偏 `auto` 提示在主人有已连接 IM 渠道时优先走 IM
|
||||
// ⇒ 实际最可能发生的路径恰恰不弹。
|
||||
//
|
||||
// 判据为什么不会误伤普通消息:只有主动推送这条通道会调用本函数,普通消息(Web 回合 /
|
||||
// IM 回复 / IM 镜像)走的仍是 BroadcastPersisted,那条路径**永不**往帧顶放该键。
|
||||
// 帧类型仍是 `message_persisted`,因此角色门(design/11 §7.1)与普通持久化帧逐字相同。
|
||||
func (s *Server) BroadcastProactivePersisted(msg history.Message) {
|
||||
s.broadcastPersisted(msg, true)
|
||||
}
|
||||
|
||||
// proactivePayloadFrom 把 UnifiedMessage 投影为消毒后的线上载荷。
|
||||
// persisted 是刚落库的主会话消息(未接线历史存储或落库失败时为零值),
|
||||
// 它的 id/时间戳随之进入载荷,使客户端能把实时气泡对齐到历史行。
|
||||
|
||||
Reference in new issue
Block a user