- REST(同步 + stream:true)与 WS 两条入口同形解析 documents:只收服务端存储名(形态 + 真实存在 + 嗅探 MIME + 本地 URL + 大小),客户端谎报 mime/url/size 一律被服务端覆盖 ⇒ 不重开 SSRF 面(有「真实可命中 URL,命中次数 0」的用例钉住)。 - 拒绝口径对齐 S1:超过 5 条 → 400 too_many_documents(且先于任何 FS 访问);形态非法/穿越/不存在 → 404 document_not_found。 - 挂载:一回合一条 RoleUser 消息,文档部件追加其后(纯附件回合不塞空文本块,空文本会被 provider 拒)。 - 修 S2 移交的两处静默吞掉:session_transcript 用 history.DecodeDocument 把 h.Document 还原为部件(坏列带来源 WARN 不静默、也不卡会话);session_tail 的 messagesEmpty 计入 ContentTypeDocument(纯附件不再被判空回合)。 - 拆文件/拆函数(AGENTS:文件≤500 行、函数≤80 行):new chat_documents.go(rest.go 原 499/500 行塞不下)、handleChat 尾段 54 行原样搬成 submitChatTurn(handleChat 90→40 行),ws_hub 增 documents 依赖(与既有 envResolver 同接法)。 - 主会话独立验收(隔离 worktree = 当前 HEAD + 仅 B 的文件 ⇒ 正是 A+B 合流态):build/vet 绿、全树 59 包 0 FAIL、13 条新用例 PASS、linux/darwin 交叉编译绿;变异独立复现(摘掉条数上限判定 ⇒ 红)。 - 主会话补的测试钉子:TestMaxChatDocumentsMatchesDesign —— 原条数用例是用常量自身算输入条数的,改常量它照样绿(实测 5→1000 全包仍绿);补钉后改 10 时新钉子红、旧用例仍绿。
51 lines
1.8 KiB
Go
51 lines
1.8 KiB
Go
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
|
||
}
|