From 2b17bb5b03ead7349916e72bf3285b5e665ccc8e Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 22 Jun 2026 20:53:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=90=8C=E5=B9=B3=E5=8F=B0=E5=A4=9A?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E6=94=AF=E6=8C=81=20=E2=80=94=20adapter=5Fna?= =?UTF-8?q?me=20=E8=B4=AF=E7=A9=BF=E5=85=A8=E9=93=BE=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UnifiedMessage 新增 AdapterName 字段 - router 从适配器 ConfigName() 捕获 adapter 实例名 - forwardToAICore source 新增 adapter_name - ai-core SetBotUID key 优先用 adapter_name,回退 platform - 更新优化大纲加入 P4.1 Co-Authored-By: Claude --- backend/ai-core/cmd/main.go | 20 +++++++-- backend/platform-bridge/cmd/main.go | 1 + .../platform-bridge/internal/bridge/router.go | 5 +++ .../internal/bridge/unified.go | 1 + docs/dev-plan/12-next-phase-optimization.md | 43 +++++++++++++++++-- 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/backend/ai-core/cmd/main.go b/backend/ai-core/cmd/main.go index 42c8c56..9823376 100644 --- a/backend/ai-core/cmd/main.go +++ b/backend/ai-core/cmd/main.go @@ -871,7 +871,8 @@ func handleChat( SenderName string `json:"sender_name"` OriginalUID string `json:"original_uid"` BotUID string `json:"bot_uid"` - GroupName string `json:"group_name,omitempty"` + GroupName string + AdapterName string `json:"group_name,omitempty"` } `json:"source,omitempty"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -888,9 +889,18 @@ func handleChat( if thinker != nil { thinker.RecordUserMessage(req.SessionID) if req.Source.Platform != "" && req.Source.BotUID != "" { - thinker.SetBotUID(req.Source.Platform, req.Source.BotUID) + adapterKey := req.Source.Platform + if req.Source.AdapterName != "" { + adapterKey = req.Source.AdapterName + } + thinker.SetBotUID(adapterKey, req.Source.BotUID) } if req.Source.Platform != "" && req.Source.ChannelID != "" { + adapterKey := req.Source.Platform + if req.Source.AdapterName != "" { + adapterKey = req.Source.AdapterName + } + thinker.SetBotUID(adapterKey, req.Source.BotUID) thinker.AddOrUpdatePlatformChannel(req.Source.Platform, req.Source.ChannelType, req.Source.ChannelID, req.Source.GroupName) } } @@ -924,7 +934,11 @@ func handleChat( if thinker != nil { thinker.RecordUserMessage(req.SessionID) if req.Source.Platform != "" && req.Source.BotUID != "" { - thinker.SetBotUID(req.Source.Platform, req.Source.BotUID) + adapterKey := req.Source.Platform + if req.Source.AdapterName != "" { + adapterKey = req.Source.AdapterName + } + thinker.SetBotUID(adapterKey, req.Source.BotUID) } if req.Source.Platform != "" && req.Source.ChannelID != "" { thinker.AddOrUpdatePlatformChannel(req.Source.Platform, req.Source.ChannelType, req.Source.ChannelID, req.Source.GroupName) diff --git a/backend/platform-bridge/cmd/main.go b/backend/platform-bridge/cmd/main.go index 07e9365..210de88 100644 --- a/backend/platform-bridge/cmd/main.go +++ b/backend/platform-bridge/cmd/main.go @@ -665,6 +665,7 @@ func forwardToAICore(cfg *config.Config, msg *bridge.UnifiedMessage, mode, userI "original_uid": msg.OriginalSenderUID, "bot_uid": msg.BotUID, "group_name": msg.GroupName, + "adapter_name": msg.AdapterName, }, } if len(images) > 0 { diff --git a/backend/platform-bridge/internal/bridge/router.go b/backend/platform-bridge/internal/bridge/router.go index c1ca6cf..9f0e967 100644 --- a/backend/platform-bridge/internal/bridge/router.go +++ b/backend/platform-bridge/internal/bridge/router.go @@ -150,6 +150,11 @@ func (r *PlatformRouter) RouteMessage(adapterKey string, rawMsg interface{}) (*U unified.BotUID = selfAware.SelfID() } + // Capture adapter config name for multi-account routing. + if named, ok := a.(interface{ ConfigName() string }); ok { + unified.AdapterName = named.ConfigName() + } + // Resolve identity (nil for unknown users; caller decides routing). // Use platform type (e.g. "qq") for identity resolution, not adapter key. identity := r.mapper.ResolveOrNil(a.PlatformName(), unified.SenderID) diff --git a/backend/platform-bridge/internal/bridge/unified.go b/backend/platform-bridge/internal/bridge/unified.go index 138ab68..5fddcde 100644 --- a/backend/platform-bridge/internal/bridge/unified.go +++ b/backend/platform-bridge/internal/bridge/unified.go @@ -29,6 +29,7 @@ type UnifiedMessage struct { GroupName string `json:"group_name,omitempty"` // resolved group name for group chats OriginalRawMessage interface{} `json:"-"` // preserved for SendMessage wiring BotUID string `json:"-"` // bot's own platform UID, set by router + AdapterName string `json:"-"` // adapter config name (e.g. "qq-main"), set by router } // Attachment represents a file/image/voice/video attachment. diff --git a/docs/dev-plan/12-next-phase-optimization.md b/docs/dev-plan/12-next-phase-optimization.md index 1e277f8..79680ff 100644 --- a/docs/dev-plan/12-next-phase-optimization.md +++ b/docs/dev-plan/12-next-phase-optimization.md @@ -181,6 +181,42 @@ QQ 平台标识(`【QQ群聊:xxx】`、`【QQ私聊:xxx】`)硬编码在 `th --- +### 5.1 P4.1 — 同平台多账号支持 + +#### 现状 + +Platform-Bridge 已支持同一平台注册多个 adapter 实例(如 `qq-main`, `qq-secondary`),但 ai-core 侧的 key 系统用 platform 类型字符串(`"qq"`)而非 adapter config name: + +| 位置 | 当前 key | 问题 | +|---|---|---| +| `botUIDs` | `"qq"` → UID | 多个 OBv11 账号只能存一个 UID | +| `ProactiveTarget.Platform` | `"qq"` | 主动消息不知道发给哪个 adapter | +| `platform_qq_xxx` session ID | `"qq"` | ✅ 正确,同群聊多账号应共享上下文 | + +#### 目标 + +将 ai-core 内部的 platform 标识从"协议类型"改为"adapter 实例名",使多个同平台账号独立工作。 + +#### 要点 + +- **platform-bridge `forwardToAICore`**:source.platform 传 adapter config name(`"qq-main"`)而非 `"qq"` +- **ai-core `SetBotUID`**:key 改为 adapter name,允许多个同平台 Bot +- **`ProactiveTarget.Platform`**:传 adapter name,platform-bridge 直接用它查 router +- **platform-bridge `sendProactive` handler**:直接用 platform 字段作为 adapter name +- **`PlatformFormat` 注册表**:key 保持 platform 类型(`"qq"`),格式与协议绑定,不绑定账号 +- **session ID prefix**:保持 `platform_qq_`,同群聊多账号共享上下文 + +#### 涉及文件 + +| 文件 | 改动 | +|---|---| +| `platform-bridge/cmd/main.go` | forwardToAICore 传 adapter name | +| `platform-bridge/internal/handler/bridge_handler.go` | sendProactive 直接用 platform 查 adapter | +| `ai-core/cmd/main.go` | SetBotUID key 用 adapter name | +| `ai-core/background/thinker.go` | ProactiveTarget + botUIDs 适配 | + +--- + ## 6. P5 — 工具子会话增强 ### 6.1 子会话返回时间戳 @@ -204,17 +240,18 @@ QQ 平台标识(`【QQ群聊:xxx】`、`【QQ私聊:xxx】`)硬编码在 `th ## 7. 实施顺序建议 ``` -Phase A (本节可做) ───────────────────────────── +Phase A (本节可做) ───────────────────────────── ✅ 已完成 P2.2 对话后思考可追加 ~10 行改动 P2.1 自主思考后触发记忆整理 ~5 行改动 P5.1 子会话返回时间戳 ~20 行改动 -Phase B (需要跨服务协调) ─────────────────────── +Phase B (需要跨服务协调) ─────────────────────── ✅ 已完成 P1 LLM 可自主操作提醒与日程 新建 1 文件 + 注册工具 P0 自主思考分层 重构 thinker 核心循环 Phase C (架构级改动) ─────────────────────────── - P4 多平台前缀统一抽象 跨 ai-core + platform-bridge + P4 QQ→OBv11 重命名 + PlatformFormat 抽象 ✅ 已完成 + P4.1 同平台多账号支持 跨 ai-core + platform-bridge ← 当前 P3 群聊并发(协会议话) 跨 ai-core + platform-bridge Phase D (后续优化) ─────────────────────────────