fix: 消息日志增强 + 历史消息抑制 + SSE实时追踪 + 群聊上下文优化

- 日志:收/发消息均显示群名称,管理员显示真实QQ昵称而非"开拓者"
- 历史消息:服务重启后NapCat回放的历史消息不再触发回复,静默注入上下文
- 消息时间戳:转发给AI时附带【消息时间: HH:MM:SS (XmXs前)】标记
- ♪ 分割符:QQ消息支持♪作为句子断点
- AI-Core SSE端点:全链路追踪实时推送,ethend不再5秒轮询
- 群聊上下文:AI-Core明确被告知消息来自群聊,以实际发送者为主语

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 11:49:36 +08:00
parent 677385ec17
commit 3ad728406e
13 changed files with 587 additions and 156 deletions
+48
View File
@@ -52,6 +52,8 @@ func (cl *CallLogger) log(r CallRecord) {
if cl.size < cl.capacity {
cl.size++
}
broadcastCall(r)
}
func (cl *CallLogger) get(limit int) []CallRecord {
@@ -72,3 +74,49 @@ func (cl *CallLogger) get(limit int) []CallRecord {
}
return result
}
// --- SSE subscriber system ---
type callSubscriber struct {
ch chan CallRecord
done chan struct{}
}
var (
callSubscribers []*callSubscriber
callSubscribersMu sync.RWMutex
)
// SubscribeCalls returns a channel that receives new CallRecords and a done channel.
func SubscribeCalls() (<-chan CallRecord, <-chan struct{}) {
ch := make(chan CallRecord, 20)
done := make(chan struct{})
callSubscribersMu.Lock()
callSubscribers = append(callSubscribers, &callSubscriber{ch: ch, done: done})
callSubscribersMu.Unlock()
return ch, done
}
// UnsubscribeCalls removes a subscriber. Safe to call multiple times.
func UnsubscribeCalls(ch <-chan CallRecord) {
callSubscribersMu.Lock()
defer callSubscribersMu.Unlock()
for i, s := range callSubscribers {
if s.ch == ch {
close(s.done)
callSubscribers = append(callSubscribers[:i], callSubscribers[i+1:]...)
return
}
}
}
func broadcastCall(r CallRecord) {
callSubscribersMu.RLock()
defer callSubscribersMu.RUnlock()
for _, s := range callSubscribers {
select {
case s.ch <- r:
default:
}
}
}