feat(channelbridge): 出站语音结论落 voice 列并挂出站 Media(M58)
- voice.Ref 增 SourceTTS 与 FallbackReason,Validate/IsZero/validSource 同步 - 出站成功:INSERT -> 补写 voice 列 -> notify(首帧即带 voice) - 出站降级:source=tts + status=failed + fallbackReason,正文原样 - 首条气泡挂出站 Media(新开条目,不复制 target.Media) - gateway historyVoice 投影 fallbackReason - 新增 outbound_voice.go 与整链 e2e 测试(含变异打红验证时序)
This commit is contained in:
1 parent
281b27b496
commit
462f007ec1
13 files changed
+755
-44
No files matched your search
@@ -77,12 +77,12 @@ func (b *Bridge) notifyPersisted(msg history.Message) {
|
||||
// (inbound_documents_persist.go 的两段式)。未装配历史存储时为空操作,
|
||||
// 因此桥接器在没有存储的情况下行为不变。
|
||||
//
|
||||
// 写入本身走 persistMain(与主动推送同一个写入口径),通知走普通通道 notifyPersisted。
|
||||
// **主动推送不经过本函数**:它直接调 persistMain,并额外走 notifyProactive 追加一条带
|
||||
// 写入本身走 persistMainWith(与主动推送同一个写入口径),通知走普通通道 notifyPersisted。
|
||||
// **主动推送不经过本函数**:它直接调 persistMainWith,并额外走 notifyProactive 追加一条带
|
||||
// 结构化判据的帧(切片 P0b)—— 因此带判据的帧只可能来自主动推送,**普通消息的帧永远
|
||||
// 不带它**。
|
||||
func (b *Bridge) persistToMain(ctx context.Context, role, content, mood, document, image, platform, deviceID, adapterID, turnID string) history.Message {
|
||||
return b.persistMain(ctx, mainRow(role, content, mood, document, image, platform, deviceID, adapterID, turnID), b.notifyPersisted)
|
||||
return b.persistMainWith(ctx, mainRow(role, content, mood, document, image, platform, deviceID, adapterID, turnID), b.notifyPersisted)
|
||||
}
|
||||
|
||||
// mainRow 构造一条写进 Web 主会话的行。它只写一次字段清单:persistToMain 与
|
||||
@@ -94,13 +94,16 @@ func mainRow(role, content, mood, document, image, platform, deviceID, adapterID
|
||||
}
|
||||
}
|
||||
|
||||
// persistMain 是「写进主会话」的**唯一**写入口径:persistToMain(普通消息)与
|
||||
// 主动推送(proactive.go)共用它,因此两条路的存储语义逐字一致 —— 未接线历史存储
|
||||
// 时空操作并返回零值、写库失败 WARN 并返回零值(绝不谎称已落库)、成功则返回刚落库的
|
||||
// 完整消息。**差别只在 notify**:那是「这条要不要通知实时通道」的接缝,由调用方给出
|
||||
// —— 普通消息传 notifyPersisted(`message_persisted` / `channel_persisted`),主动推送
|
||||
// 传 notifyProactive(带结构化判据的同一类帧,切片 P0b)。nil 表示本次写入不通知。
|
||||
func (b *Bridge) persistMain(ctx context.Context, msg history.Message, notify func(history.Message)) history.Message {
|
||||
// persistMainWith 是「写进主会话」的**唯一**写入口径(与 persistIsolatedWith 同一手法):
|
||||
// persistToMain(普通消息)、主动推送(proactive.go)与入站/出站语音那条「先写 `voice` 列、
|
||||
// 再广播」的路径共用它,因此几条路的存储语义逐字一致 —— 未接线历史存储时空操作并返回零值、
|
||||
// 写库失败 WARN 并返回零值(绝不谎称已落库)、成功则返回刚落库的完整消息。
|
||||
//
|
||||
// **差别只在 notify**:那是「这条要不要通知实时通道、以及先写列还是先广播」的接缝,由调用方
|
||||
// 给出 —— 普通消息传 notifyPersisted(`message_persisted` / `channel_persisted`),主动推送
|
||||
// 传 notifyProactive(带结构化判据的同一类帧,切片 P0b),语音传 persistVoiceFirstNotify
|
||||
// (先写 `voice` 列再广播,M44 首帧纪律)。nil 表示本次写入不通知。
|
||||
func (b *Bridge) persistMainWith(ctx context.Context, msg history.Message, notify func(history.Message)) history.Message {
|
||||
if b.history == nil {
|
||||
return history.Message{}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user