feat(runtime): IM 主人私聊补历史转录(与 Web 主会话同源:抽共享 transcript 包 + OwnerEnvFor 单入口)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

This commit is contained in:
AskaEth committed 2026-10-05 11:36:18 +08:00
1 parent df8fc660c0
commit 9b903a89bc
14 files changed
+676 -181

No files matched your search

+10 -3
View File
@@ -232,7 +232,8 @@ func inboundTargetFor(sess session.Session, platform string) inboundTarget {
// runInboundTurn 为被放行的消息驱动 agent 轮次:解析
// 路由目标、把消息携带的文件类附件**落库并挂成文档部件**
// (design/24 §3;切片 M1)、把图片媒体内联成 data: URI 部件挂上既有视觉链路
// (切片 IM-IMG;design/24 §4.2 末)、构建模型可见的消息列表、在轮次之前持久化入站
// (切片 IM-IMG;design/24 §4.2 末)、构建模型可见的消息列表(主人私聊车道上再前置主会话的
// 历史转录,见 transcript.go),在轮次之前持久化入站
// 用户消息**连同它们的 `document` 引用列与 `image` 列**(因此即使渠道回复失败它也已落地,
// 客户端也有附件芯片与图片可看),并在轮次之后把抽取结论补回同一列,运行
// 循环并把结果交给 deliverReply。
@@ -258,11 +259,13 @@ func (b *Bridge) runInboundTurn(ctx context.Context, msg adapter.UnifiedMessage,
// 镜像进主会话时取主会话的绑定,否则取账号的
// 渠道级绑定,再否则取全局默认;群聊或
// 陌生人会话强制使用默认角色。
runEnv := loop.SessionEnv{ActorEnv: sess.Env(), MemWritable: sess.MemWritable}
runEnv.PersonaID = b.resolvePersona(ctx, sess, target, adapterName(a))
runEnv := turnEnv(sess, target, b.resolvePersona(ctx, sess, target, adapterName(a)))
senderName := senderDisplayName(msg, actor)
loopMsgs := b.buildLoopMessages(ctx, text, runEnv, actor, senderName, msg)
// 附件/图片先挂到**本回合的**用户消息上(attachInboundContent 认列表里第一条
// RoleUser),再前置历史转录 —— 顺序反过来会把附件挂到转录里的旧用户消息上。
attachInboundContent(loopMsgs, attachments, images)
loopMsgs = b.seedTurnTranscript(ctx, target, loopMsgs)
// 附件引用与图片必须同批落进用户消息各自的列(design/24 §2.4 / design/16 §4.4):
// 只把部件挂在内存里的模型可见消息上,客户端读到的那条消息就是一片空白 —— 附件芯片
@@ -368,6 +371,10 @@ func deviceIDFor(msg adapter.UnifiedMessage) string {
// 入站内容摄取的产物(已落库的文档部件、内联成 data: URI 的图片部件,以及两条路上
// 「读不到」的诚实提示行)由 attachInboundContent(inbound_content.go)挂到**同一条
// RoleUser 消息**上 —— 用户内容只进用户角色消息是项目红线。
//
// 历史转录**不在本函数里**:它由 seedTurnTranscript(transcript.go)在本函数返回之后
// 前置到列表最前面,与网关编排器的播种同序(转录在前、本次消息在后)。因此本函数只负责
// **本回合自己的**消息(来源行 + 当次用户消息),受限车道的形状在有无转录时保持一致。
func (b *Bridge) buildLoopMessages(_ context.Context, text string, env loop.SessionEnv, actor adapter.Actor, senderName string, src adapter.UnifiedMessage) []model.Message {
msg := userTurnMessage(text)
thirdParty := env.Restricted() && !actor.IsOwner() && senderName != ""