feat(runtime): 文档摄取①(抽取器 + sidecar + 装配期 resolveDocuments)(design/24 S3-A)
- 抽取器零新依赖纯函数:UTF-8 清洗、CSV/TSV 行数列名摘要、64K rune 安全截断;PDF/Office/二进制走哨兵错误诚实拒绝(不引解析库)。 - sidecar:<DataDir>/extracted/<存储名>.txt,首行紧凑 JSON 元数据 + 正文;临时文件 + rename 原子落定;只抽一次(删原文件仍出正文);版本不匹配/坏缓存重抽。 - 装配期 resolveDocuments(resolveImages 同位,每步对模型可见视图注入):清单恒在(解析器缺席/报错也在)、截断带续读游标、失败诚实标记 + status=unreadable、回合继续;文档部件永不抵达编码器(负例钉住)。 - 修 S2 移交的两处静默吞掉:checkpoint 比较键纳入文档引用、compactor token 估算计入文档部件(不是免费的)。 - 主会话独立验收:隔离 worktree(HEAD + 本切片)build/vet 绿、全树 59 包 0 FAIL、linux/amd64 + darwin/arm64 交叉编译绿、documents+loop 两包 167 条 PASS;变异独立复现(resolveDocuments 短路 ⇒ 3 条红,含「文档部件仍抵达下游」)。
This commit is contained in:
1 parent
834ef3683e
commit
a8851dc0a2
12 files changed
+2008
-7
No files matched your search
@@ -173,18 +173,24 @@ func lastUserMessageKey(messages []model.Message) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// userMessageKey 返回一条用户消息的比对键:文本与图片引用按出现顺序拼接。
|
||||
// 纯图片消息(无文本)因此也能区分——只比文本会把「用户刚发的一张图」判成
|
||||
// 空键而漏判。角色与说话人不进键:这里只问「是不是同一条用户输入」。
|
||||
// userMessageKey 返回一条用户消息的比对键:文本、图片引用与文档引用按出现顺序
|
||||
// 拼接。纯图片消息(无文本)因此也能区分——只比文本会把「用户刚发的一张图」判成
|
||||
// 空键而漏判;纯文档消息同理:客户端「超限走文件」发的就是一条只有附件的消息,
|
||||
// 漏掉它会让续接判定在附件回合上失准(design/24 §9.5 移交的静默吞掉)。角色与
|
||||
// 说话人不进键:这里只问「是不是同一条用户输入」。
|
||||
func userMessageKey(m model.Message) string {
|
||||
var b strings.Builder
|
||||
for _, part := range m.Content {
|
||||
if part.Type == model.ContentTypeImage {
|
||||
switch part.Type {
|
||||
case model.ContentTypeImage:
|
||||
b.WriteString("\x00img:")
|
||||
b.WriteString(part.ImageURL)
|
||||
continue
|
||||
case model.ContentTypeDocument:
|
||||
b.WriteString("\x00doc:")
|
||||
b.WriteString(part.DocumentName)
|
||||
default:
|
||||
b.WriteString(part.Text)
|
||||
}
|
||||
b.WriteString(part.Text)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
Reference in new issue
Block a user