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
9f6243a729
commit
28afa11aeb
13 files changed
+755
-44
No files matched your search
@@ -193,15 +193,31 @@ func (b *Bridge) deliverReply(ctx context.Context, msg adapter.UnifiedMessage, a
|
||||
if res != nil {
|
||||
mood = res.Mood
|
||||
}
|
||||
// 出站语音(design/25 §7.1):先把结算结论折成 voice 列事实,再让落库那条路走
|
||||
// 「INSERT → 写 voice 列 → notify」(M44 首帧纪律)—— 与入站语音共用同一份
|
||||
// persistVoiceFirstNotify,因此首帧上就带着 `voice`,客户端不必等重连。
|
||||
ref, hasVoice := b.outboundVoiceRef(resultVoice(res))
|
||||
notify := b.notifyPersisted
|
||||
if hasVoice {
|
||||
notify = b.persistVoiceFirstNotify(ref)
|
||||
}
|
||||
// 持久化助手回复(主人私聊 → 主会话 + message_persisted
|
||||
// 广播;受限 → 隔离日志 + channel_persisted 广播),随后
|
||||
// 送回渠道。
|
||||
if target.private {
|
||||
b.persistToMain(ctx, history.RoleAssistant, reply, mood, "", "", target.platform, deviceIDFor(msg), adapterName(a), turnID)
|
||||
b.persistMainWith(ctx, mainRow(history.RoleAssistant, reply, mood, "", "", target.platform, deviceIDFor(msg), adapterName(a), turnID), notify)
|
||||
} else {
|
||||
b.persistIsolated(ctx, history.RoleAssistant, reply, "", "", "", sess, msg.Platform, "", adapterName(a), turnID)
|
||||
b.persistIsolatedWith(ctx, isolatedRow(history.RoleAssistant, reply, "", "", "", sess, msg.Platform, "", adapterName(a), turnID), notify)
|
||||
}
|
||||
if err := b.sendReply(ctx, msg, a, reply); err != nil {
|
||||
// 音频只在合成成功、且盘上那份副本读得回来时才挂上;读不回来就诚实退回纯文本
|
||||
// (正文照发,WARN 已由 outboundVoiceMedia 记下)。
|
||||
var voiceMedia *adapter.Media
|
||||
if hasVoice {
|
||||
if md, ok := b.outboundVoiceMedia(msg, ref); ok {
|
||||
voiceMedia = &md
|
||||
}
|
||||
}
|
||||
if err := b.sendReplyVoice(ctx, msg, a, reply, voiceMedia); err != nil {
|
||||
if errors.Is(err, adapter.ErrUnsupported) {
|
||||
b.log.Debug("channel does not support outbound reply, skipped",
|
||||
"platform", msg.Platform, "session", target.sessionID)
|
||||
|
||||
Reference in new issue
Block a user