Files
goodbuddy/docs/features/document-processing/logic-design.md
T
mesalogo a3b7a27045 fix: preserve drafts, canvas edits, and remote Continue tools
Keep paragraph formatting and checklist todos when removing canvas pages,
and preserve accepted undo/redo history after oversized input is rejected.
Merge restored queued text into the latest conversation draft and retain
image delivery when OCR returns image references and generated warnings only.

Deliver session MCP servers to bridged remote Continue Execute while keeping
Ask read-only and preserving local model-profile isolation. Add regression
coverage and update feature documentation. Correct stale conversation-limit
and forced-color assertions and the measured Electron layout test deadline.

Validation: 4,826 tests passed, 67 skipped; full typecheck and lint passed.
Current-source Linux x64 Execute/Ask/Execute MCP delivery passed, using 10
real text-provider requests and no image-provider requests. Image generation
itself was not exercised. Staged whitespace checks passed before commit.

Release note: 修复恢复队列时覆盖新输入、画布删页丢失清单格式及超限输入清空撤销历史的问题;图片 OCR 无正文时保留原图发送方式,远程 Continue Execute 正确保留会话 MCP 工具。
2026-09-19 23:09:48 +08:00

176 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HTTP OCR 逻辑设计
需求来源为 [PRD](./prd.md#13-http-paddleocr-vl-扩展规划),场景验收见
[User Stories](./user-stories.md)。当前生产机制及与设计的差异见[实现说明](./implementation.md),
逐项验证见[进度](./progress.md#2026-09-19-实现与验证)。以下规则保留需求追溯职责。
## 输入路由
L-I1(FR-I1、FR-I2、FR-I4;US-I1、US-I2、US-I3、US-I6):先区分用户操作与输入类型,
再判断实际生效的模型及 Runtime 能力。显式提取图片文字使用已保存 OCR 配置,优先于普通
图片直传分支,也不受文档快速工作流的隐式跳过规则影响。
| 输入或操作 | 处理 |
| --- | --- |
| 普通聊天图片,实际支持图片输入 | 作为图片请求发送,不调用 OCR |
| 普通聊天图片,实际不支持或能力未确认 | 明确提示提取文字或切换视觉模型,不静默 OCR,不声称已发送图片 |
| 明确提取图片文字 | 调用配置的 OCR;模型视觉能力不影响此操作 |
| PDF、Office | 沿用文档原生解析与按需 OCR 工作流 |
| 知识库图片文字提取及索引 | 由知识库工作流决定,不读取聊天模型视觉开关作为路由依据 |
L-I2(FR-I3、FR-I5;US-I1、US-I4、US-I7):原图与请求副本分开,缩放、转码不覆盖原图。
纯图片无解析正文及清单前置条件;显式 OCR 产物关联回原附件。文档图片保存与模型请求选择
分别处理,只有明确选入请求且满足实际能力、数量和容量限制的图片才进入模型输入。
L-I3(FR-I2、FR-I3;US-I3、US-I11):附件身份、原始名称与来源不因 OCR 改变,发送方式
单独记录为图片或提取文字。只有 OCR 返回非空可靠文字且结果保存成功,才切到提取文字;
显示名派生为“原文件名 · 提取文字”。提取文字模式只拼入文本,不同时传原图或把解析中
提取的其他图片自动附加。失败、取消、空文字保持原方式;用户可显式切回图片并重新校验
能力。图片引用及解析器生成的缺图警告不算提取文字,即使同时保存了其他有效图片也不例外。
重试采用当前已保存 OCR 设置,开始时说明来源;旧结果在新结果成功前保持可用。
## 选图与发送
L-I4(FR-I5;US-I7、US-I8、US-I9):预览待添加选择是短期 UI 状态,目标草稿的附件引用
才是“已附加”的依据。进入预览默认零选择,切页签保留选择,关闭清空未添加选择。已附加
项不能靠取消勾选移除,必须明确执行移除操作。测试预览不提供添加入口。
添加提交包含明确的目标会话及来源结果 imageId 集合,提交时冻结目标,不根据异步完成时
活动会话改归属。Main 确认目标可编辑、源资源仍存在、数量与容量可接受后复制到会话所有
的稳定文件资产,再保存草稿引用;任一复制或保存失败回滚本批新副本,保留原选择与草稿。
无有效目标时必须先选择或新建会话,不隐式创建或采用第一个会话。活动回复不阻止下一条
草稿编辑,但仍遵循已有 Runtime/模型选择锁定规则。
以“目标草稿 + 来源结果 ID + imageId”判断重复添加;来源结果 ID 只标识实际解析产物,
不引入结果版本历史。同一草稿存在该图片引用时返回已有附件,不重复占用容量或位置。
移除后可再次添加;发送后新草稿可再次添加。重解析生成新结果和图片 ID,不自动替换
已附加副本。父文档与副本没有级联删除关系,来源关联用于说明及跳转,不作为副本存活条件。
L-I5(FR-I1、FR-I5、FR-H9;US-I2、US-I8、US-I10):选图和发送沿用 PRD 第 3.2.1 节
现有附件限制。父文档和每张图片分别占一个附件位置;现有基线为每消息 8 个附件、Main
16 个上下文项目及 12 MiB 暂存内容上限。实现从同一共享契约读取这些值,不在预览、IPC
或 Provider 中定义独立的“选图上限”。图片副本使用既有图片请求转码路径,原始资产大小
与请求副本大小分开计算,不能把尚未选中的全部插图计入本次发送容量。
选图批次先去掉已附加项再整批校验;超限全部拒绝并保留选择,不沿用文件粘贴入口的截取
剩余位置行为。发送前重新读取完整草稿并校验,不依赖添加时的剩余位置。文本父附件只
拼入一次,不为每个图片副本重复加入父文档正文;模型正文仅附简短来源信息及图片输入。
仅图片父文档仍作为来源附件保留并计入附件数量,但不生成空 text context;同批至少有一张
从该结果选出的图片(或其显式 OCR 文字)才可携带它发送,否则提示选择图片或移除该文档。
能力判定取本次实际模型与实际 Runtime 消费路径的交集。添加时显示能力问题但允许保存
待修复草稿,发送和入队接受前必须通过校验;未知能力不能当作支持。切换模型/Runtime、
恢复队列及真正开始执行时重新校验。队列能力失配转为可恢复失败并保留资源,用户可恢复
到草稿修正或切换到支持的配置后重试;队列内容不会静默转文字或丢图。不以工具拿到图片
引用代替聊天模型收到图片的证据,也不因模型支持视觉而隐式调用 OCR。
## 来源与选项
L-H1(FR-H1、FR-H2;US-H1、US-H2、US-H8):每次解析开始时读取并冻结已保存的来源、
地址和选项。选择 HTTP 后只检查 HTTP 配置;本地模型状态不再是 HTTP 的前置条件。
HTTP 失败不触发本地下载或切换。快速工作流优先于 OCR 设置,仍不运行 OCR。
L-H5(FR-H11、FR-H12;US-H12):来源切换保留各自配置,测试要求先保存;解析结果记录
本次 Provider 与生效选项,不含凭据。查看已存结果不触发解析,修改配置不改写旧结果。
配置为设备级共享值;项目、会话和知识库范围决定结果归属,不创建独立 OCR 配置。应用中心
的本机推理监控启用、常驻与窗口开关不决定 OCR 来源或可用性。HTTP 来源不依赖本地监控
入口和模型加载状态。菜单及设置直达返回规则见 [入口与职责](./ui-design.md#11-入口与职责)
(FR-H1、FR-H12、FR-I5;US-H16)。
L-H2(FR-H4;US-H4、US-H9):高级布尔项使用“服务默认 / 开启 / 关闭”语义。
服务默认省略字段,不将未知默认值写成 `false`。`markdownIgnoreLabels` 使用三种状态:
省略表示服务默认,空数组表示不排除标签,非空数组表示明确排除的标签集合。保存设置
不得把空数组归一为缺省。任务内选项不随用户中途修改设置变化。
自定义过滤的正向“保留”开关与排除集合取反映射。首次进入自定义且无旧值时从全部保留
开始,明确显示此初始值;不猜测服务默认。已有自定义排除列表在切换模式后保留,未知或
不常用标签也必须呈现并保留,不能保存时丢弃。默认保存结果引用的图片;过滤使图片不再
被正文引用时才可不提交对应图片。过滤设置不控制模型自动选图。
## 页面与图片
L-H3(FR-H2、FR-H5、FR-H7;US-H2、US-H5、US-H8):页面定位来自输入任务的原始页号。
单页图片请求可确定其 PDF 页号或 PPTX 幻灯片号;整份 PDF 请求在核对返回数量和顺序后
映射到原始页号,不依赖此次部署缺失的 `page_index`。不连续 OCR 页不能直接跨页合表。
重组输出保留 `sourcePages` 集合,无法恢复对应关系时报告失败,不能猜测唯一页号。
L-H4(FR-H3;US-H3、US-H7):以“文档 + 原始页 + 页内图片键”关联图片。只处理有界、
可解码的内联图片,不下载服务返回 URL。Markdown 中的 `![]()` 和 HTML `img src` 均须
映射到保存后的受管资源;表格 HTML 需要既有安全渲染处理。模型正文与向量索引不混入
Base64。筛除页眉图等内容时,对应图片只有仍被结果引用才需要提交。
## 结果与失败
| 条件 | 处理规则 | 关联 |
| --- | --- | --- |
| 原生文本可靠且未要求 OCR | 直接使用原生结果,不探测 HTTP | FR-H2 / US-H2 |
| HTTP 与图片保存完成 | 提交逐页内容、图片引用和诊断;置信度缺失就省略 | FR-H3、FR-H7 / US-H1、US-H3 |
| 自动聊天 OCR 失败且有可靠原生文字 | 沿用既有原生文字回退,并标明未完成 OCR 页 | FR-H6 / US-H6 |
| 自动聊天已取得文字但部分图片失败 | 保留文字和具体缺图警告;缺图引用改成文字说明 | FR-H3、FR-H6 / US-H7 |
| 自动聊天跨页重组失败,但逐页结果可用 | 保留原逐页正文、图片及页码,显示重组失败和部分结果;不使用映射不明的重组内容 | FR-H5、FR-H6 / US-H5、US-H6 |
| 知识库完整索引或高保真缺页、缺图、重组失败 | 本次失败,不替换已有成功结果;允许重试 | FR-H3、FR-H5、FR-H6 / US-H3、US-H5、US-H7 |
| 用户取消解析或应用关闭 | 中止客户端请求,不启动后续任务,仅清理本次无有效引用的临时资源;草稿、已发送、已入队引用的资源保留 | FR-H6、FR-H9 / US-H6、US-H10、US-I5 |
| 无文字但有已保存的有效插图 | 结果为仅图片,可预览并按 L-I4 选择;聊天父文档无可发送文本,知识库不生成空 chunk,不标为文本索引成功 | FR-H3、FR-H7、FR-I5 / US-H3、US-I7 |
| 无文字且无有效图片 | 失败,保留原件供重试,不能标为空成功 | FR-H6 / US-H15 |
请求状态按“准备、请求、校验、保存、完成”推进,提交前可进入失败或取消;资源及引用已
提交后按完成结算,迟到取消不删除结果。
HTTP 中止不保证服务端 GPU 推理立刻停止;本部署没有探测服务端取消接口。
L-H8(FR-H6、FR-H9、FR-H12;US-H6、US-H14、US-H15):任务运行状态与结果完整程度
分开。已保存结果可为完整、部分或仅图片,当前任务另有运行、失败、取消或中断状态。
打开旧结果时可以同时显示本次重解析失败,不能用单一 status 覆盖旧结果。
自动聊天允许的可靠文本回退必须将缺页/缺图范围和警告随文本传给模型;知识库完整索引
及高保真严格失败。快速索引只按所选原生策略完成,不因用户明确禁用 OCR 而假称漏页
已经识别。仅图片的知识库结果可保存供预览和选图,但显示“无可索引文字”,不算索引成功。
已有可检索结果重解析后变成仅图片时,不以空索引替换旧结果,本次报告无可索引文字并保留
旧结果;首次导入没有旧结果时可保留图片资产和该状态。
首次批次导入失败或取消沿用批次回滚,失败摘要保留可重试信息但不是草稿附件。重解析
失败不删除已有附件。任务取消通过同一 operationId/AbortSignal 传播,取消后的迟到响应
不提交结果;应用退出停止后续请求,重启将未完成任务显示为中断,不恢复 HTTP 调用。
有受管原件则手动重试;原件尚未保存则重新选择。重启仅根据数据库现有引用清理无主暂存,
无需记录逐页持久运行日志。
## 资源归属
L-H6(FR-H8、FR-H9、FR-I3;US-H10、US-H11、US-I4、US-I5):草稿资源暂存于应用目录;
发送被接受及队列记录持久化前,文档完成原文件、解析正文、图片的持久化及会话关联,纯图片
完成原图持久化及关联。失败保留草稿供重试,不标为已发送。
恢复队列读取持久化附件引用;取消生成不删除已提交资源。移除草稿附件、取消解析或批次失败
只清理本次无有效引用的资源。启动、退出或定时清理不得一律删除临时目录;可恢复草稿引用
的文件须继续可用。删除会话只释放其归属和引用,无其他有效引用时才删除文件。
L-H7(FR-H10、FR-H11;US-H11、US-H13):知识库文档独立持有正文、chunks 和图片关系,
两种来源模式的派生资源均归应用管理。删除文档或来源时按有效引用清理;外部原文件不属于
派生资源清理范围。聊天和知识库重解析均先完成新结果及必要资源保存,再替换引用;失败或
取消清理新暂存,旧结果保持可用。旧资源仅在替换成功且无引用时回收。
已发送消息及已接受队列的正文、选图、发送方式和资源引用冻结。历史消息“再次解析”产生
新草稿附件,不修改消息;草稿重解析成功仅更新草稿引用,其他有效引用保持原结果。修改队列
附件须先恢复整条输入到草稿,再重解析或改变发送方式,不额外复制一条仍待发送的输入。队列
恢复到草稿时先保存草稿引用再移除队列引用,失败保持队列。队列删除只释放该项引用;
取消正在生成的回复保留已发送输入。会话删除和项目删除均使用同一引用清理规则。
目标已有草稿时,将恢复文字以空行追加、附件按来源去重合并,提交前校验合并后的数量与
容量;超限则保留队列及原草稿,提示先发送或整理草稿,不覆盖已有输入。
恢复等待期间允许继续编辑;文字追加到恢复完成时该会话的最新草稿,不覆盖期间的输入,
也不复活已清空的旧文字。切换会话不会改变原恢复目标。
L-H9(FR-I5、FR-H9、FR-H10;US-I8、US-I9):从聊天或知识库选出的图片在添加成功时
已是会话独立副本,其来源名称、定位和源 ID 随附件保存。来源删除或重解析不删除副本,
来源跳转失效不妨碍打开原图和发送。移除父文档只解除父文档引用,移除副本只解除该图片
引用。草稿、消息、队列、分支等已有有效引用共同决定是否清理文件;不为跨库引用建立
全局去重或资源保活服务。知识库与聊天原资产各自清理,复制时失败只回滚本批新资源。
## 完整性检查
来源选择、缺省值、正向过滤、混合页、图片键、完整/部分/仅图片结果、失败取消、原图保存、
显式 OCR 发送方式、选图幂等、目标选择、共享限额、发送入队、重解析及清理均已有确定规则。
组件和布局见 [UI 设计](./ui-design.md),逐项验收见其完整矩阵;这些范围没有留待后续产品
决策的选图缺口。
实际直连和托管 OpenCode 图片消费、扫描 PDF 与跨页合表示例已取得真实证据,见进度。
其他 Runtime、本地 OCR 各平台和部署高级模型的本轮验证范围仍需分别核对。
模型声明与接口成功不替代效果测试;跨页整理默认关闭,失败明确报告。