package gateway import "git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model" // 本文件拥有会话编排器的对话尾部辅助件 // (design/15 §2.2/§4):续跑所依据的有界窗口,以及 // 防止空洞回合把会话标记为忙碌的空判定。它们是 // 作用于 []model.Message 的纯函数,与状态机分开 // 放置,使编排器文件保持小。 // boundedTail 返回最后 maxTail 条消息的全新副本,使续跑 // 保持增量且有界(design/15 §2.2、§4),且绝不与输入 // 切片或另一个状态的尾部共享底层数组。 func (o *Orchestrator) boundedTail(msgs []model.Message) []model.Message { if len(msgs) <= o.maxTail { return append([]model.Message(nil), msgs...) } out := make([]model.Message, o.maxTail) copy(out, msgs[len(msgs)-o.maxTail:]) return out } // messagesEmpty 报告回合是否不携带可用文本、图片或文档,使 // 编排器不会因空洞消息把会话标记为忙碌。文档部件同样算内容: // 「只带附件」的回合是真实回合,不该被判空(design/24 §9.5)。 func (o *Orchestrator) messagesEmpty(msgs []model.Message) bool { for _, m := range msgs { for _, c := range m.Content { if c.Type == model.ContentTypeText && c.Text != "" { return false } if c.Type == model.ContentTypeImage && c.ImageURL != "" { return false } if c.Type == model.ContentTypeDocument && c.DocumentName != "" { return false } } } return true } // concatMessages 返回合并 a 与 b 的新切片(绝不复用 a 或 b // 的底层数组),因此续跑尾部可以安全地交给并发运行。 func concatMessages(a []model.Message, b ...model.Message) []model.Message { out := make([]model.Message, 0, len(a)+len(b)) out = append(out, a...) out = append(out, b...) return out }