feat: IM平台列 + deviceID标识 + 会话持久化完善
- agent-96: chat_messages 加 platform 列(迁移0004) + IM主人私聊落主会话web(带platform) + 前端按平台过滤契约 + message_persisted 带 platform(复用 BroadcastPersisted) - agent-97: chat_messages 加 device_id 列(迁移0005) + history.Message.DeviceID + Web发消息带deviceId(localStorage getClientId) + IM persistToMain 带 deviceID + 前端气泡展示 SourceLabel + 修主会话基础2个bug(fn scanMessage语法/DDL缺列) - design/16 §4.4(平台) + §4.5(deviceID) 已入档 - 实机: POST /chat 带 deviceId 读回 user/assistant 均带 deviceId+platform; 后端 build/vet/test 绿 + 前端 build 绿 - 红线: 身份靠 actor 元数据; 禁止 shell 读 .env(JWT冒烟由主会话跑)
This commit is contained in:
1 parent
1bf60c1ae4
commit
37e98ec584
26 files changed
+828
-116
No files matched your search
+17
-6
@@ -23,12 +23,12 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/persona/loader"
|
||||
personareg "git.yeij.top/AskaEth/Cyrene_v2/internal/persona/registry"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/platform"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/agent"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/capacity"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/embedding"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/exec"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/guardrail"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/knowledge"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
|
||||
@@ -426,6 +426,12 @@ func (a *app) wireAuxiliary() error {
|
||||
}
|
||||
a.sessions = sess
|
||||
|
||||
hist, herr := history.NewStore(context.Background(), a.db, a.log)
|
||||
if herr != nil {
|
||||
return fmt.Errorf("history store: %w", herr)
|
||||
}
|
||||
a.history = hist
|
||||
|
||||
automation, err := automations.NewService(automations.Config{}, automations.Deps{
|
||||
Bus: a.bus,
|
||||
Loop: a.loop,
|
||||
@@ -481,6 +487,7 @@ func (a *app) wireChannels() error {
|
||||
Loop: a.loop,
|
||||
Sessions: a.sessions,
|
||||
Owner: a.owner,
|
||||
History: a.history,
|
||||
})
|
||||
if berr != nil {
|
||||
return fmt.Errorf("channel bridge: %w", berr)
|
||||
@@ -512,11 +519,9 @@ func (a *app) wireFrontend() error {
|
||||
a.log.Warn("audit store unavailable, falling back to in-memory", "error", aerr)
|
||||
auditStore = nil
|
||||
}
|
||||
hist, herr := history.NewStore(context.Background(), a.db, a.log)
|
||||
if herr != nil {
|
||||
return fmt.Errorf("history store: %w", herr)
|
||||
}
|
||||
a.history = hist
|
||||
// a.history is built in wireAuxiliary so both the channel bridge (wireChannels)
|
||||
// and the gateway share the same persistent store. History was a no-op dependency
|
||||
// before the IM path, so nothing downstream depends on its creation order change.
|
||||
gw, err := gateway.New(a.cfg, gateway.Deps{
|
||||
Log: logger.WithSource(a.log, "gateway"),
|
||||
Auth: jwt,
|
||||
@@ -543,6 +548,12 @@ func (a *app) wireFrontend() error {
|
||||
return fmt.Errorf("gateway: %w", err)
|
||||
}
|
||||
gw.SetVoice(a.voice)
|
||||
if a.channelBridge != nil {
|
||||
// Route the channel bridge's owner-private persisted messages into the same
|
||||
// `message_persisted` broadcast the orchestrator uses, so the Web client mirrors
|
||||
// IM messages with one, uniform frame (design/16 §4.4).
|
||||
a.channelBridge.SetOnPersisted(a.gw.BroadcastPersisted)
|
||||
}
|
||||
a.gw = gw
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user