package channelbridge import ( "context" "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history" ) // This file holds the channelbridge's chat-history persistence hooks (design/16 // §4.4): an owner private chat is routed INTO the single main web session and // tagged with the channel platform, then broadcast so the Web client mirrors it // without a refresh. Kept separate from channelbridge.go so the bridge's inbound // pipeline file stays under the module size bound. // SetOnPersisted wires (or replaces) the transport hook called after an // owner-private message is persisted into the main web session. The gateway is // built after the bridge in the composition root, so the hook is attached post-New // through this setter; it is a no-op-safe call and is safe for concurrent use with // in-flight processing. func (b *Bridge) SetOnPersisted(fn func(history.Message)) { b.mu.Lock() defer b.mu.Unlock() b.onPersisted = fn } // notifyPersisted hands a just-persisted message to the transport hook when one is // wired, so the gateway can broadcast `message_persisted` for cross-end sync. func (b *Bridge) notifyPersisted(msg history.Message) { b.mu.RLock() fn := b.onPersisted b.mu.RUnlock() if fn != nil { fn(msg) } } // persistToMain writes one message into the main web session with an explicit source // platform and client deviceID, then notifies the transport hook so Web clients receive // a `message_persisted` event without a refresh (design/16 §4.4). deviceID is the // concrete client that sent the message (design/16 §4.5) — e.g. "weixin-ilink:conf0:wx_uid" // for IM. It is a no-op when no history store is wired, so the bridge runs unchanged // without storage. func (b *Bridge) persistToMain(ctx context.Context, role, content, platform, deviceID string) { if b.history == nil { return } full, err := b.history.AppendFull(ctx, history.Message{ SessionID: history.MainSessionID, Role: role, Content: content, Platform: platform, DeviceID: deviceID, }) if err != nil { b.log.Warn("persist main session", "err", err, "role", role, "platform", platform, "device_id", deviceID) return } b.notifyPersisted(full) }