66 lines
3.0 KiB
Go
66 lines
3.0 KiB
Go
package channelbridge
|
||
|
||
// 本文件承载入站内容的**共享制品与挂载点**:文档路(inbound_documents.go)与图片路
|
||
// (inbound_images.go)各产出一份 `inboundContent`(要挂到用户回合上的部件 + 「读不到」的
|
||
// 诚实提示行),由 attachInboundContent 逐组挂到**同一条 RoleUser 消息**上。
|
||
//
|
||
// 为什么两条路共用一个制品类型而不是各写一份挂载循环:两者的产物形状逐字相同
|
||
// (部件 + 提示行),差别只在部件怎么来(文档:落库引用;图片:data: URI)与落哪一列
|
||
// (`document` / `image`)。写第二份循环只会让「挂在哪条消息上」「空文本部件绝不塞」
|
||
// 这类口径开始漂移 —— 而用户内容只进用户角色消息是项目红线,这份逻辑只该有一处。
|
||
|
||
import (
|
||
"strings"
|
||
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
|
||
)
|
||
|
||
// inboundContent 是一次入站内容摄取/内联的产物。
|
||
type inboundContent struct {
|
||
// parts 是要挂到 RoleUser 消息上的内容部件(文档部件,或 data: URI 图片部件)。
|
||
parts []model.Content
|
||
// notices 是「读不到」的诚实提示行,顺序与消息里的媒体顺序一致。
|
||
notices []string
|
||
}
|
||
|
||
// noticeText 把提示行拼成一段文本;没有提示时返回空串(调用方据此不塞空文本部件)。
|
||
func (c inboundContent) noticeText() string {
|
||
return strings.Join(c.notices, "\n")
|
||
}
|
||
|
||
// attachInboundContent 把入站内容制品挂到消息列表里的**用户回合**上(design/24 §3/§4.4):
|
||
// 部件与「读不到」的诚实提示行都只进 `RoleUser`,且挂在那条已构建好的用户消息上 ——
|
||
// 来源系统行、第三方边界、SenderName 等既有装配因此逐字不变(本切片不重排消息,只追加
|
||
// 部件)。
|
||
//
|
||
// groups 按给出顺序逐组追加(文档路先、图片路后),空组是空操作 —— 两条路互不影响:
|
||
// 同一条消息既带文档又带图片时,两条都挂得上,各自只贡献自己的部件与自己的提示行。
|
||
// 一个回合只有一条用户消息(buildLoopMessages 的既有形状),因此挂载点只有一处。
|
||
// 文本部件为空且既有文本也为空时**不塞空文本部件**(provider 会拒):部件本身或提示行
|
||
// 就是这条消息的内容。
|
||
func attachInboundContent(msgs []model.Message, groups ...inboundContent) {
|
||
idx := userTurnIndex(msgs)
|
||
if idx < 0 {
|
||
return
|
||
}
|
||
for _, g := range groups {
|
||
if len(g.parts) == 0 && len(g.notices) == 0 {
|
||
continue
|
||
}
|
||
msgs[idx].Content = append(msgs[idx].Content, g.parts...)
|
||
if notice := g.noticeText(); notice != "" {
|
||
msgs[idx].Content = append(msgs[idx].Content, model.Content{Type: model.ContentTypeText, Text: notice})
|
||
}
|
||
}
|
||
}
|
||
|
||
// userTurnIndex 返回消息列表里第一条 RoleUser 消息的下标(没有则 -1)。
|
||
func userTurnIndex(msgs []model.Message) int {
|
||
for i := range msgs {
|
||
if msgs[i].Role == model.RoleUser {
|
||
return i
|
||
}
|
||
}
|
||
return -1
|
||
}
|