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 工具。
This commit is contained in:
@@ -71,7 +71,7 @@ Main 仅在图片和会话引用持久化成功后发布完成事件。素材必
|
||||
| GoodBuddy Agent 远程适用 Runtime | 复用桌面与 Agent 通信及工具桥接,将请求绑定原会话,由 Main 调用图片模型 | 逐一验证实际支持的远程 Runtime,覆盖真实 Host 工具往返、生成编辑、本地与远程双向切换、断连及成果归属 |
|
||||
| 无工具能力的聊天模型 | 说明自动调用限制,可使用已有直连图片工作流 | 不解析普通文字伪装工具调用,不新增表单;Ask 不提交 |
|
||||
|
||||
本地 OpenCode、Continue 和 DeepSeek Harness 经内部 MCP gateway 注入;直连 Model 使用内置工具分发。远程通过 `main-image-tool-session.ts`、Agent 协议和 `image-tool-mcp.ts` 回到同一 Main 服务。现有 GoodBuddy Agent 的受管远程 Runtime 为 OpenCode,项目校验和 Runtime 创建均沿用此范围;共享契约包含其他 Runtime 不表示存在其远程执行路径。保留会话在目录清空时也刷新 MCP,Continue 准备失败时释放本次分配的令牌。工具发现成功或 Skill 注入成功不能代替真实生成与编辑。
|
||||
本地 OpenCode、Continue 和 DeepSeek Harness 经内部 MCP gateway 注入;直连 Model 使用内置工具分发。远程通过 `main-image-tool-session.ts`、Agent 协议和 `image-tool-mcp.ts` 回到同一 Main 服务。当前受管远程 Runtime 包括 OpenCode 和 Continue;Continue 模型桥的会话 MCP 交付及 Ask 边界见[远程 Runtime](../remote-host/technical-design.md#runtime)。保留会话在目录清空时也刷新 MCP,Continue 准备失败时释放本次分配的令牌。工具发现、无计费测试接收端往返或 Skill 注入成功不能代替真实生成与编辑。
|
||||
|
||||
Main 已接收的请求在桌面仍运行时独立于远程连接继续;未确认是否接收的请求不自动重放。聊天回合停止等待与用户取消图片是不同动作,须验证现有取消传播不会误杀 Main 图片请求。
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ src/main/context-manager.ts
|
||||
src/main/context-manager.test.ts
|
||||
src/main/conversation-attachment-storage.ts
|
||||
src/main/conversation-attachment-storage.test.ts
|
||||
src/main/document-extracted-text.ts
|
||||
src/main/document-extracted-text.test.ts
|
||||
src/main/document-parsing-service.ts
|
||||
src/main/document-parsing-service.test.ts
|
||||
src/main/document-parsing-settings-store.ts
|
||||
@@ -92,6 +94,7 @@ docs/features/document-processing/chat-attachments-technical-design.md
|
||||
docs/features/document-processing/implementation.md
|
||||
docs/features/document-processing/progress.md
|
||||
docs/features/document-processing/changed-paths.md
|
||||
docs/quality/recurring-defects.md
|
||||
```
|
||||
|
||||
`scripts/paddleocr-vl-probe.mjs` 和导航 README 原有未提交内容保留,本轮未修改。
|
||||
|
||||
@@ -54,6 +54,9 @@ HTTP 请求固定返回 Markdown 图片、关闭调试可视化。高级布尔
|
||||
会话资产的 `request.json` 保存已转换的请求内容,用于恢复内存 context;原件字节单独保存,
|
||||
缩放和 JPEG 请求副本不覆盖原图。提取图片文件使用 UUID 无扩展名,MIME 在清单记录。
|
||||
图片显式 OCR 后生成解析文件。切回原图保留已有结果,并重新进入图片能力校验。
|
||||
HTTP OCR、显式图片提取及结果完整程度共用 `hasExtractedDocumentText`;图片引用与生成的
|
||||
缺图警告只作预览/诊断,不算正文。无正文的显式提取失败并保留原草稿;有有效插图的文档
|
||||
结果仍可保存为仅图片,不因缺图警告改判为可发送文本。
|
||||
|
||||
`ConversationAttachmentStorage` 的专用 SQLite schema 1 保存描述、路径与
|
||||
`draft/message/queue/parsing` 引用,不在这些描述字段内存入原图 Base64。纯图片无需解析清单。
|
||||
@@ -85,7 +88,8 @@ Main 先保存资产,再保存草稿或接受队列;消息、分支建立独
|
||||
|
||||
队列保存接受时的附件和发送方式。入队、分发、实际执行分别检查图片能力。
|
||||
分发失败保留队列及可恢复错误,队列预览只读;“恢复到草稿”先合并并保存附件引用,
|
||||
再移除队列项,文字用空行追加,超限保持原队列。恢复后的文字由 Renderer 草稿管理。
|
||||
再移除队列项,文字用空行追加,超限保持原队列。Renderer 请求恢复时不传入旧草稿文本,
|
||||
收到队列正文后通过原会话的函数式状态更新追加到最新草稿,保留等待期间的编辑和清空。
|
||||
文件附件的启动恢复不再把提前保存的用户消息误认为 Runtime 已接受并删除队列。
|
||||
|
||||
## 界面与边界
|
||||
|
||||
@@ -26,7 +26,8 @@ L-I3(FR-I2、FR-I3;US-I3、US-I11):附件身份、原始名称与来源
|
||||
单独记录为图片或提取文字。只有 OCR 返回非空可靠文字且结果保存成功,才切到提取文字;
|
||||
显示名派生为“原文件名 · 提取文字”。提取文字模式只拼入文本,不同时传原图或把解析中
|
||||
提取的其他图片自动附加。失败、取消、空文字保持原方式;用户可显式切回图片并重新校验
|
||||
能力。重试采用当前已保存 OCR 设置,开始时说明来源;旧结果在新结果成功前保持可用。
|
||||
能力。图片引用及解析器生成的缺图警告不算提取文字,即使同时保存了其他有效图片也不例外。
|
||||
重试采用当前已保存 OCR 设置,开始时说明来源;旧结果在新结果成功前保持可用。
|
||||
|
||||
## 选图与发送
|
||||
|
||||
@@ -153,6 +154,8 @@ L-H7(FR-H10、FR-H11;US-H11、US-H13):知识库文档独立持有正文
|
||||
取消正在生成的回复保留已发送输入。会话删除和项目删除均使用同一引用清理规则。
|
||||
目标已有草稿时,将恢复文字以空行追加、附件按来源去重合并,提交前校验合并后的数量与
|
||||
容量;超限则保留队列及原草稿,提示先发送或整理草稿,不覆盖已有输入。
|
||||
恢复等待期间允许继续编辑;文字追加到恢复完成时该会话的最新草稿,不覆盖期间的输入,
|
||||
也不复活已清空的旧文字。切换会话不会改变原恢复目标。
|
||||
|
||||
L-H9(FR-I5、FR-H9、FR-H10;US-I8、US-I9):从聊天或知识库选出的图片在添加成功时
|
||||
已是会话独立副本,其来源名称、定位和源 ID 随附件保存。来源删除或重解析不删除副本,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 状态
|
||||
|
||||
当前状态以 [2026-09-19 实现与验证](#2026-09-19-实现与验证)、[附件操作布局复验](#2026-09-19-附件操作布局复验)及[全局浮层复验](#2026-09-19-全局浮层复验)为准。
|
||||
当前状态以 [2026-09-19 实现与验证](#2026-09-19-实现与验证)、[附件操作布局复验](#2026-09-19-附件操作布局复验)、[全局浮层复验](#2026-09-19-全局浮层复验)及[空正文与草稿恢复修正](#2026-09-19-空正文与草稿恢复修正)为准。
|
||||
以下至“菜单核对检查”的内容是实施前历史记录,保留原日期与原调用数。
|
||||
|
||||
2026-09-18:完成规划文档和独立 HTTP 探索脚本。FR-H1 至 FR-H12 均未完成生产实现,
|
||||
@@ -330,3 +330,31 @@ Worker 整体回收),是具体实现对比,保留原文。本次新增内
|
||||
最终 `npm test`:403 个文件通过、9 个跳过,4,793 项通过、67 项跳过,耗时 909.69 秒。
|
||||
`npm run typecheck`、`npm run lint` 及隔离目录的 Electron Vite 生产构建通过;
|
||||
相关文档的 48 个相对文件链接有效,`git diff --check` 通过。
|
||||
|
||||
## 2026-09-19 空正文与草稿恢复修正
|
||||
|
||||
对应 L-I3、L-H7、L-H8。修复前已复现:无识别文字、有效插图与缺图警告并存时,
|
||||
警告被当作正文,显式提取后请求没有原图;队列恢复等待期间输入的文字也会被旧草稿覆盖。
|
||||
实现和判定归属见[生产实现说明](./implementation.md),未增加持久状态或修改数据 schema。
|
||||
|
||||
- 解析、结果完整程度和 HTTP Provider 共用提取正文判定。8 个解析/存储/共享 UI 测试文件
|
||||
203 项通过,其中 loopback HTTP 回归覆盖缺图警告、正文存在与否及保存后的 `images-only`。
|
||||
- 生产 `App` 的 6 项回归通过,覆盖空草稿、已有草稿、恢复期间编辑、清空、失败及切换会话。
|
||||
IPC 响应由测试控制完成时机,不能称为完整桌面到 Main 的新增端到端验收。
|
||||
- 当前源码在隔离 Electron 中通过真实 `nativeImage`、HTTP 客户端、附件 SQLite/文件存储、
|
||||
`reparseDraft` 与 `enrichRequest` 复验:仅图片及图片加缺图警告均拒绝文字切换,
|
||||
草稿仍引用原附件,发往 Runtime 的请求保留一张图片;真实正文控制组仍切为文字发送。
|
||||
三次请求均发往本机合成 OCR 服务,外部 OCR/文本/图像 Provider 请求为 0。
|
||||
- 本轮 OCR 判断和草稿合并仍位于 Desktop,共用同一 Main 请求构造与 Renderer 草稿机制;
|
||||
没有远端 OCR 分支、Agent 协议或模型桥变更,不据此扩大远端视觉模型验收结论。
|
||||
|
||||
验证用的临时 fixture、Electron profile 和数据库已清理。首次 OCR 探针因临时目录的模块
|
||||
解析失败,调整启动器的依赖路径后通过;新会话切换测试最初遗漏全局队列读取,修正
|
||||
fixture 后通过。上述均为验证工具问题,不修改产品行为来满足错误 fixture。
|
||||
|
||||
合并画布与 Continue 修正后的 `npm test` 完整结束:405 个文件通过、9 个跳过,
|
||||
4,826 项通过、67 项跳过,耗时 982.48 秒,无失败。最终 `npm run typecheck`、
|
||||
`npm run lint` 及助手数据库 101 项单独复验均通过。会话列表测试更新为无 100 条截断的
|
||||
既定行为,共享高对比度测试检查全部 forced-colors 块;没有为旧断言恢复产品限制。
|
||||
隐藏 Electron 窗口的双帧等待实测令布局场景耗时约 63 秒,因此只把测试子进程期限从
|
||||
60 秒改为 90 秒,并对自有临时目录增加有界删除重试;完整布局断言未减少。
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# Magic Notes Progress
|
||||
|
||||
## 2026-09-19: Canvas Content and History Preservation
|
||||
|
||||
- Page-break deletion now removes only the embed, retaining existing paragraph
|
||||
terminators and checklist/heading formats. Mid-line insertion retains Quill's
|
||||
native paragraph split rather than guessing which newline is disposable.
|
||||
- Oversized input is rejected before the canvas-local History records it, then
|
||||
reverted with its inverse Delta. Accepted undo/redo and user selections survive;
|
||||
normal rich-text editors retain their original History module.
|
||||
- `npx vitest run tests/canvas-core.electron.test.ts src/renderer/src/magic-canvas`
|
||||
passed 35 tests across 5 files. Electron exercised actual Quill selection and history, then production
|
||||
SQLite/file create, update and reopen retained the same checklist todo.
|
||||
This uses Quill API edits in an isolated Electron window, not physical keyboard
|
||||
input or the full App/IPC save flow.
|
||||
- Focused ESLint for the four changed source/test files and `git diff --check`
|
||||
passed. The integrated full suite passed 4,826 tests with 67 skipped
|
||||
(405 files passed, 9 skipped); full typecheck and lint passed.
|
||||
The existing hidden-window layout scenario measured about 63 seconds, so its
|
||||
child deadline is now 90 seconds with bounded temporary-directory cleanup
|
||||
retries. All geometry, input and persistence assertions remain intact and passed.
|
||||
No model calls, persistence/schema changes, remote Runtime changes or commits.
|
||||
|
||||
## 2026-09-19: Canvas Image Import Size
|
||||
|
||||
- Raised the canvas image file limit to 20 MiB inclusive and updated its error
|
||||
|
||||
@@ -228,6 +228,13 @@ PDF text layer. `capturePages()` provides PNG data URLs for AI input, not a PNG
|
||||
download button. Undo/redo is per annotation page or Quill mode; page operations
|
||||
and PDF imports are not global undo steps.
|
||||
|
||||
Flow page-break removal and rejected-input history handling follow the
|
||||
[canvas editing and limit rules](../../../src/renderer/src/magic-canvas/README.md#editing-and-assets).
|
||||
`canvas-core.electron.test.ts` feeds the real Electron flow's before/after content
|
||||
into production `AssistantDatabase` create/update and reopen, checking that the
|
||||
derived checklist todo and its identity survive page-break removal. History
|
||||
coverage exercises accepted typing, rejected overflow, selection and redo.
|
||||
|
||||
The [canvas integration reference](../../../src/renderer/src/magic-canvas/README.md)
|
||||
owns core limits, import behavior and lifecycle details. Vite bundles Fabric,
|
||||
Quill, jsPDF, PDF.js workers and binary assets; PDF workers use explicit module
|
||||
|
||||
@@ -223,3 +223,30 @@ provider HTTP 请求计数在 Agent gateway 的外部 fetch 层完成。
|
||||
最终另复验项目选择、顶部清单和安装管理 3 文件、41 项通过;App 远程 Runtime 选择与
|
||||
继承 3 项通过。`npm run typecheck`、`npm run lint` 均通过。中文审校扫描阻断项为 0,
|
||||
复核项为测试列举、请求数分项与必要验收边界,按事实保留。
|
||||
|
||||
## 2026-09-19 Continue 会话 MCP 交付回归
|
||||
|
||||
模型桥 helper 原先把 Session MCP 写入原生配置,但独立模型 profile 生成分支只保留
|
||||
显式能力,导致 Execute 最终配置丢失 MCP。修复后通过 run options 传递会话 HTTP
|
||||
服务器;本机原生 MCP 隔离和 Ask 只读规则不变,具体机制见[Runtime](./technical-design.md#runtime)。
|
||||
`continue-acp-helper.test.ts` 联合运行实际 helper 与 adapter 配置生成器,覆盖初次交付、
|
||||
续接替换、Ask 排除、加载空列表以及本机 profile 不继承原生 MCP。
|
||||
|
||||
共享 Linux x64 Host 经 LAN 固定身份连接,使用保存的 GoodBuddy 凭据,当前源码 Agent、
|
||||
helper、adapter 与 CN 1.5.47 在专用目录运行。Main 受管 Runtime → Agent-owned ACP →
|
||||
Continue → Agent HTTP MCP → Main 工具桥往返通过;仅最末端图片服务替换为无计费
|
||||
测试接收端,校验输入并返回 `SAFE_MCP_ROUNDTRIP`,未连接图片 Provider。
|
||||
同一对话依次 Execute、Ask、Execute:两次 Execute 各实际调用工具一次,Ask 没有工具调用
|
||||
并回复 `ASK_NO_IMAGE_TOOL`;三次均正常终结。最终源码再次构建后完整重复该顺序。
|
||||
|
||||
首轮成功目录 `/root/tmp/gb-cn-runtime-2kQ7wc`,最终复验目录
|
||||
`/root/tmp/gb-cn-runtime-NNM89D`。每轮 5 次真实文本 Provider HTTP 请求,合计 **10 次**,
|
||||
全部 HTTP 200;每轮上限 6 次,单次最大输出 1,024 tokens,单 Prompt 验证超时 120 秒。
|
||||
图片 Provider 请求 **0 次**。此前一次测试目录权限错误在 Runtime 验证阶段退出,模型请求
|
||||
0 次;修正测试目录权限后通过,未放宽产品校验。每轮结束确认所属剩余进程 0,专用运行
|
||||
及上传目录已清理,原 Host 安装未修改。此验证不包含正式包安装、UI 点击或真实图片生成。
|
||||
|
||||
复查脚本位于上述本机临时目录:`mcp-host-build.cjs`、`mcp-host-run.cjs`,
|
||||
最终日志 `mcp-host-live.log`。专项 4 文件 38 项通过;改动文件 ESLint 和 Agent 类型检查
|
||||
通过。主任务随后完成合并后的 `npm test`:405 个文件通过、9 个跳过,4,826 项通过、
|
||||
67 项跳过,耗时 982.48 秒,无失败;最终完整类型检查与 lint 通过。
|
||||
|
||||
@@ -230,7 +230,13 @@ Composer Runtime 菜单显示 OpenCode、Continue 和管理入口,不显示直
|
||||
DeepSeek Harness。项目与历史会话保留 OC/CN 选择;不支持的旧 selection 恢复为项目
|
||||
默认值。Main 校验已安装 Runtime 身份与选择一致,按相应 CN/OC 模型 profile 建立模型桥。
|
||||
本机配置的 SKILL 包和 stdio MCP Server 不上传或分配给远程 Runtime;远程 ACP Session
|
||||
继续使用空 MCP Server 列表。Node.js、Python 等工具执行环境同样不修改或同步到 Host,
|
||||
仅接收当前请求由 Agent 管理的 HTTP MCP 能力(例如 Execute 图片工具),不继承本机原生
|
||||
MCP 配置。Continue helper 将 ACP Session 的服务器作为显式 `sessionMcpServers` 交给
|
||||
共享 `ContinueHostAdapter`,与模型桥配置一起生成最终配置;不先写入会被独立模型分支
|
||||
丢弃的原生配置。新建、加载和续接 Session 使用当前列表,空列表清除旧能力;Ask 在 helper
|
||||
和 adapter 两层均不注入这些 Execute 能力。本机独立模型 profile 仍不继承原生 MCP,
|
||||
既有知识库和自定义 MCP 的显式分配规则不变。
|
||||
Node.js、Python 等工具执行环境同样不修改或同步到 Host,
|
||||
完整边界见[工具执行环境](../local-tool-environment/README.md)。
|
||||
|
||||
### Ask
|
||||
|
||||
Reference in New Issue
Block a user