feat: IM式跨端实时同步——message_persisted 广播 + 前端按id去重追加
- history.Store 新增 AppendFull(返回含 id/createdAt 的完整消息),Append 签名不变 - session_orchestrator 加可空 OnPersisted;persistUserMessages/persistAssistantReply 落库后回调广播 - server.go newOrchestrator 接 OnPersisted → hub.broadcast message_persisted(thinking 剥除) - 前端 ws.ts 加 message_persisted case(仅 activeSessionId 匹配才处理);appendOrUpdateMessage 升级为 id 精确upsert+内容/时间归一 - 实测:双 WS,A stream 发消息,B 免刷新收到 user+assistant 各1条(count=2 PASS) - 红线: 身份仍靠 actor 元数据,不靠提示词;用户/助手消息、本端/异端统一路径
This commit is contained in:
1 parent
bcc53d68f3
commit
1bf60c1ae4
9 files changed
+260
-38
No files matched your search
@@ -109,6 +109,10 @@ type MemoryStore interface {
|
||||
// endpoints answer with a clear 501.
|
||||
type HistoryStore interface {
|
||||
Append(ctx context.Context, msg history.Message) error
|
||||
// AppendFull persists msg like Append but returns the complete stored message
|
||||
// (with the assigned id/timestamp) so the orchestrator can broadcast it for
|
||||
// cross-end realtime sync (design/16 §4.2).
|
||||
AppendFull(ctx context.Context, msg history.Message) (history.Message, error)
|
||||
List(ctx context.Context, sessionID string, before int64, limit int) ([]history.Message, error)
|
||||
Recent(ctx context.Context, sessionID string, n int) ([]history.Message, error)
|
||||
DeleteSession(ctx context.Context, sessionID string) error
|
||||
@@ -455,6 +459,15 @@ func newOrchestrator(s *Server) *Orchestrator {
|
||||
Emit: func(sessionID, typ string, data map[string]any) {
|
||||
s.hub.broadcast(wsEvent{Type: typ, SessionID: sessionID, Data: data})
|
||||
},
|
||||
OnPersisted: func(msg history.Message) {
|
||||
// Broadcast the complete message so every browser of the same account
|
||||
// appends it without a manual refresh (design/16 §4.2). The frontend
|
||||
// dedups by the backend-generated id, and thinking is stripped to stay
|
||||
// consistent with the WS history replay (design/16 §6).
|
||||
wire := toHistoryMessage(msg)
|
||||
wire.Thinking = ""
|
||||
s.hub.broadcast(wsEvent{Type: "message_persisted", SessionID: msg.SessionID, Data: map[string]any{"message": wire}})
|
||||
},
|
||||
Log: s.log,
|
||||
History: s.history,
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user