- model 新增 ContentTypeDocument + Content 的四字段 + DocumentMessage 构造器 + ValidateDocumentParts(文档部件只允许 RoleUser,非 user ⇒ ErrDocumentOnNonUser,fail-loud)。 - 两个编码器入口(buildMessages / buildAnthropicMessages)对文档部件报 ErrBadRequest: 本期 document 永不抵达编码器,且绝不静默丢块。 - history:拆出 types.go(Message 增 Document 列),新增 document.go(DocumentRef 同时是 落库 JSON 与 DTO 形状,6 字段含 status ⇒ §4.4 的「读不到要可见」;坏列回 unreadable 不静默)。 - chat_messages 加 document 列(迁移 0015 + NewStore 幂等前滚);historyMessage.Document DTO; session_persist 的 messageTextImage → messageTextImageDocument(保留窄视图以免牵连 steer 配对)。 - 只落「引用 + 统计」,绝不落抽取正文(TestPersistedDocumentHoldsNoBody 把全部列拼起来扫正文)。 验收(主会话独立复跑,非自报):隔离 worktree(HEAD + 本切片)go build/vet 绿、 全树 58 包 0 FAIL、linux/amd64 + darwin/arm64 交叉编译绿、18 条 Document* 测试 PASS。 变异独立复现:ValidateDocumentParts 开头 return nil ⇒ 非 user 负例红。
20 lines
1.3 KiB
SQL
20 lines
1.3 KiB
SQL
-- 0015_chat_message_document: 给聊天消息挂上「文档引用」(design/24 §2.4)。
|
||
--
|
||
-- 「分享到 App · 超限走文件」把长文/文件做成服务端文档,再由 chat 以
|
||
-- document 引用它。这条消息需要在历史里看得见「她读过这个文件」,因此
|
||
-- chat_messages 增一列 document,存一个 JSON 小对象:
|
||
-- {name, mime, size, chars, truncated, status}
|
||
-- name 是服务端存储名(内容寻址、32 位十六进制)、mime 是服务端字节嗅探所得、
|
||
-- chars/truncated 是抽取统计、status 是抽取状态(extracted|listed|unreadable)。
|
||
--
|
||
-- 它**刻意只存引用与统计,绝不存抽取正文**:正文一旦落库,每翻一页历史都要
|
||
-- 背着它重传(G3 把 base64 原样落库的教训),而且附件正文是提示词注入面
|
||
-- (design/11 §10)。正文留在 <DataDir>/extracted 的 sidecar 里,装配期按
|
||
-- 引用读(design/24 §4.3:只抽一次,不每回合重算)。
|
||
--
|
||
-- 0003 的 chat_messages 表在此已存在,故 ALTER ADD COLUMN 是非破坏性的正确
|
||
-- 一步;全新库由 internal/runtime/history.NewStore 幂等地前滚(含该列)。
|
||
-- 表名沿用复数口径(援引 AGENTS §10 已登记的例外)。
|
||
|
||
ALTER TABLE chat_messages ADD COLUMN document TEXT NOT NULL DEFAULT '';
|