feat: connect conversations with Magic Notes
Let users retain useful assistant replies or complete conversations without leaving their chat workflow. Preview and edit captured text, choose an existing note or atomically create a note with its first entry, and return to the source conversation or message from saved records. Add an application-scoped Notes workbar tab with title/body search and quick text appends. Preserve drafts across conversation switches and guard closing, replacement and disabling. Schema 48 stores optional source metadata without rewriting file-backed bodies; source deletion retains the saved note. Older clients cannot reopen an upgraded database without a pre-upgrade backup. Release note: 可将助手回答或完整会话预览、编辑后加入魔法笔记,并从笔记返回原会话或消息。右侧快速笔记支持搜索和追加文字,切换会话保留草稿;采集本身不调用模型,保存后自动评论仍遵循已有设置。 Validation: isolated HEAD-based candidate passed 22 files / 930 focused tests, plus 20 gateway tests after including its create-result fixture adjustment. Real Electron App/preload/IPC/SQLite acceptance passed for all 502 historical messages, exact-entry/source navigation, native keyboard input in a 214px panel, reopen and source-deletion retention, with zero capture model calls. Repository lint and web TypeScript passed. Cached whitespace and secret-pattern checks passed; native-client changes and unrelated IPC extraction are excluded. Validation limits: the isolated source tree reuses installed node_modules, where a parallel task upgraded DSH from the committed 0.1.2-rc.1 to 0.1.7-rc.2. Full typecheck reports 14 DSH errors in three unchanged files; the full-suite attempt with --bail=1 also fails in deepseek-harness-host.test.ts. These are not all-green repository or release-package results. Earlier execution-time full suite failures and fixture repairs remain recorded in the feature progress doc.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
# 助手工作栏
|
||||
|
||||
助手工作栏统一承载本机与远程执行空间、Task、成果、文件、浏览器和终端等持续工作界面。
|
||||
助手工作栏统一承载本机与远程执行空间、Task、成果、文件、浏览器、终端和笔记等持续工作界面。
|
||||
|
||||
“笔记”为应用级、可关闭的单实例 Tab,新布局默认不打开。它提供搜索、浏览和快速追加文字,
|
||||
与主页面魔法笔记共用存储;会话采集、来源跳转与草稿规则由
|
||||
[魔法笔记文档](../magic-notes/README.md)维护。该应用已接入并通过真实 Electron 验收;
|
||||
全仓验证未全绿,聚焦复跑与执行时失败见[笔记验证进度](../magic-notes/progress.md)。
|
||||
|
||||
## 文档导航
|
||||
|
||||
|
||||
@@ -86,6 +86,7 @@ Runtime
|
||||
资源监控
|
||||
成果
|
||||
文档
|
||||
笔记
|
||||
```
|
||||
|
||||
- 应用不得根据当前项目、会话、Runtime、主机或探测结果无提示地增删能力目录项。
|
||||
@@ -96,6 +97,7 @@ Runtime
|
||||
Conversation、Job、Run 或心跳事项。
|
||||
- 当前能力、连接、数据和空状态可以动态变化。
|
||||
- 能力不可用时,目录项或已打开面板显示原因、影响和可执行的配置或切换入口,不能只通过隐藏表示。
|
||||
- 笔记遵循魔法笔记的业务启用设置,启用时提供应用级单实例 Tab,禁用前处理草稿,禁用后移除入口和实例;取消主侧栏常驻不影响工作栏可用性。采集与来源规则见[魔法笔记逻辑设计](../magic-notes/logic-design.md)。
|
||||
- 用户可以在设置中调整目录顺序;恢复默认布局恢复标准目录与默认打开面板,不强制打开全部能力。
|
||||
- 浏览器、终端及其他声明为多实例的能力可以创建多个实例,每个实例拥有独立身份和范围绑定。
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
### 3.1 工作栏应用
|
||||
|
||||
工作栏应用是可以在助手工作栏中打开的一个能力,例如任务中心、工作区、浏览器、成果或
|
||||
终端。每项应用通过统一注册表声明:
|
||||
终端、笔记。每项应用通过统一注册表声明:
|
||||
|
||||
- 稳定应用 ID。
|
||||
- 用户可见名称、图标和说明。
|
||||
@@ -54,7 +54,8 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
- 当前不可用时的原因和修复入口。
|
||||
|
||||
目录中的应用可发现性与实例是否已经打开相互独立。应用不可用时保留入口并说明原因,不以
|
||||
隐藏代替状态。
|
||||
隐藏代替状态。笔记遵循其业务启用设置:关闭魔法笔记时隐藏目录入口并移除对应 Tab,
|
||||
关闭前处理草稿,规则见[会话联动逻辑](../magic-notes/logic-design.md)。
|
||||
|
||||
注册表字段如下:
|
||||
|
||||
@@ -76,14 +77,15 @@ SSH 连接池,但尚不存在工作栏应用实例模型、终端 IPC、终端
|
||||
`defaultOpen`、`required` 和 `closable` 不互相推导。例如浏览器默认打开但不是必需实例;任务
|
||||
中心和工作区既默认打开又必须存在。`required` 不表示锁定顺序,顺序只由 `reorderable` 控制。
|
||||
|
||||
当前五个应用的 `visibleAcrossContextSwitches` 均为 `true`。该属性记录应用目录的显示策略,
|
||||
当前六个应用的 `visibleAcrossContextSwitches` 均为 `true`。该属性记录应用目录的显示策略,
|
||||
不改变内容归属,也不授予其他会话的 MCP 访问权限;当前没有使用 `false` 的应用,尚未实现
|
||||
按上下文隐藏 Tab 的策略。
|
||||
|
||||
浏览器在创建时绑定当前 Conversation;切换会话后仍保留原 Tab、选中状态和页面,导航操作
|
||||
继续使用原 `targetRef.conversationId`。此时新建浏览器才绑定新会话。默认或旧布局中尚未绑定
|
||||
的浏览器在首次使用时绑定活动会话,此后不再随会话切换改绑。终端同样保留创建时执行目标;
|
||||
任务中心、工作区和成果的内容继续跟随当前项目。
|
||||
任务中心、工作区和成果的内容继续跟随当前项目。笔记使用应用级范围,选择与草稿不随项目或
|
||||
会话切换,不接受 `targetRef`;重启仅恢复工作栏 Tab 描述,不恢复笔记选择和草稿。
|
||||
|
||||
### 3.2 工作栏 Tab 实例
|
||||
|
||||
@@ -218,6 +220,7 @@ stdio fallback。首期远程终端随 SSH Channel 结束,不提供跨 SSH 或
|
||||
| 浏览器 | `multiple` | 当前 Conversation | 是,一个实例 | 否 | 是 | 是 | 每次创建新 Tab |
|
||||
| 成果 | `single` | 当前项目 | 是 | 否 | 是 | 是 | 聚焦已有 Tab |
|
||||
| 终端 | `multiple` | 当前项目 | 否 | 否 | 是 | 是 | 每次创建新 Tab |
|
||||
| 笔记 | `single` | 应用级 | 否 | 否 | 是 | 是 | 聚焦已有 Tab |
|
||||
|
||||
实例策略、默认状态和可关闭策略都是应用注册数据,不能分散硬编码在多个点击处理器中。
|
||||
|
||||
|
||||
@@ -26,9 +26,26 @@ context and protects unsaved editor changes. A successful save followed by no
|
||||
further edits does not prompt again on return. Narrow note layouts use an index
|
||||
drawer and bounded bottom AI pane.
|
||||
|
||||
Conversation capture and the compact Notes workbar panel are implemented. Users
|
||||
can preview and edit one assistant response or the complete conversation text,
|
||||
then append it to an existing note or create a note with its first entry. Quick
|
||||
notes opens the same panel for search, browsing and text appends. Saved entries
|
||||
carry structured conversation sources with return navigation. The panel and full
|
||||
workspace share storage and change notifications; drafts remain in App memory.
|
||||
Real Electron acceptance passed through the App UI, production preload, IPC and
|
||||
SQLite. Repository validation is not all green; the [progress record](./progress.md)
|
||||
separates focused passes, repaired schema fixtures and execution-time failures.
|
||||
|
||||
## Documents
|
||||
|
||||
- [Technical design](./technical-design.md): file storage, schema 38 migration,
|
||||
- [Conversation integration PRD](./prd.md): scope and acceptance for
|
||||
conversation capture and the compact workbar panel.
|
||||
- [Conversation integration logic](./logic-design.md): capture boundaries, source
|
||||
lifetime, panel state, draft protection and application availability.
|
||||
- [Conversation integration UI](./ui-design.md): implemented entry points, compact
|
||||
panel, capture preview and source navigation, following the root UI system.
|
||||
- [Technical design](./technical-design.md): file storage, schema 38 body migration,
|
||||
schema 48 source metadata, desktop search and atomic initial-entry creation,
|
||||
backup boundaries, database notifications, process boundaries, canvas and AI
|
||||
contracts, refresh lifecycle and regression coverage.
|
||||
- [Progress](./progress.md): implementation and validation evidence.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# 会话联动逻辑设计
|
||||
|
||||
状态:已按当前实现核对,验证进度见 [progress.md](./progress.md)。需求编号来自 [PRD](./prd.md)。
|
||||
|
||||
## 内容与来源
|
||||
|
||||
FR-2、FR-3:单条采集读取所选助手消息的非空正文;整段采集先加载该会话完整历史,再按消息顺序收录用户和助手的非空正文,保留角色分隔。预览建立后,切换会话或收到新消息不会替换正文及来源标识。生成中的消息不可采集,停止或失败后已有正文可保存,单条预览注明回答未完成。整个会话正在生成时禁用整段采集,提示等待完成或停止生成。
|
||||
|
||||
首版按文字保存,保留原始 Markdown 文本、换行和代码文本,不承诺还原聊天渲染效果。推理、工具调用日志、系统提示、附件二进制和图片不进入正文;预览持续说明保存范围。用户可编辑预览,来源仍指向本次采集的会话。读取完整会话失败时不以屏幕上已有消息代替。
|
||||
|
||||
FR-5:来源独立于可编辑正文。单条来源包含会话和消息标识;整段来源包含会话标识、此次收录的消息标识及采集时间。预览使用采集时的会话标题和项目名称;保存时主进程校验消息归属,并以当时数据库中的会话标题和项目名称写入来源,无项目时显示全局。若预览期间源会话或消息已删除,保存失败并保留预览。保存完成后,修改或删除源消息不回写笔记正文和来源。
|
||||
|
||||
点击来源时读取完整会话。消息不存在但会话仍在时打开会话并提示“原消息已不存在”;确认会话不存在后保留来源文字,并在当前来源条禁用跳转。其他读取失败显示可重试错误。打开未渲染的来源消息时扩大聊天历史显示范围,再滚动定位并聚焦。编辑笔记正文不移除来源;删除笔记不影响源会话。
|
||||
|
||||
## 面板与草稿
|
||||
|
||||
FR-1、FR-4:笔记应用为可关闭、可排序的单实例工作栏 Tab,新布局默认不打开。再次触发入口激活现有 Tab;笔记选择属于应用级状态,切换项目或会话不改写它。列表按置顶优先、最近更新时间排列,搜索匹配标题与记录文字,同一笔记只显示一次。当前应用会话内保留最近选择,重启不恢复笔记选择或草稿。该笔记已删除时回到列表,清除失效保存目标并保留待保存文字。
|
||||
|
||||
FR-2、FR-3:面板有浏览、采集编辑、保存中三个状态。触发采集进入编辑态;选择目标只改变写入位置;明确点击“加入笔记”才写入。每次提交新增一条记录,不覆盖旧记录。新建目标时先填写标题,会话标题作为可修改默认值;提交一次创建笔记和首条记录,取消不遗留空笔记。普通“新建笔记”仍可显式创建空笔记。
|
||||
|
||||
保存中禁用重复提交和面板离开操作,结果返回后可再次操作。成功后清除本次草稿,显示响应返回的新增记录;失败保留预览、标题和目标。目标已删除时提示重新选择。容量校验使用现有文字记录限制,超限由用户缩减正文后重试;一次提交始终对应一条完整记录。
|
||||
|
||||
关闭 Tab、返回面板列表、从面板打开完整工作区、禁用应用或以另一条采集替换草稿前,显示“继续编辑 / 放弃草稿并切换”确认。普通主页面、项目和会话切换以及隐藏工作栏保留 App 持有的草稿及来源。取消采集只在正文或标题相对预览初值有修改时确认;未修改预览可直接取消。完整工作区自身的编辑草稿仍由其离开确认保护。
|
||||
|
||||
FR-6:成功写入触发现有通知刷新视图;面板重新挂载或工作栏重新展开时读取最新数据。面板挂载期间保留搜索词;笔记选择和草稿由 App 保留,不受搜索响应或后台刷新覆盖。既有记录编辑继续使用原修订号处理冲突。此处同步仅指本机共享存储的视图更新。
|
||||
|
||||
## 启用与评论
|
||||
|
||||
FR-1~FR-4:遵循魔法笔记应用的启用状态。禁用时隐藏会话采集、快速笔记及工作栏目录入口,并移除笔记 Tab;禁用前处理草稿。外部设置变更要求禁用时,选择继续编辑会尝试恢复启用设置,失败显示设置错误。应用未常驻不影响快速入口或工作栏可用性。设置继续由应用中心管理。
|
||||
|
||||
会话采集和快速追加本身不调用模型。保存后沿用现有 AI 评论模式;只有已有设置要求保存后自动评论时才触发,失败不撤销保存,也不自动重新追加。
|
||||
|
||||
## 完整性检查
|
||||
|
||||
当前实现覆盖首次创建、追加、取消、重复点击、写入失败、目标删除、来源删除、跨会话切换及刷新与草稿的关系。完整历史读取、来源定位和存储接口已接入;产品范围无待决项。真实 Electron 已验证采集、保存、定位、窄面板键盘操作和持久化,具体范围见进展记录。全仓测试和类型检查仍有执行时记录的失败,聚焦复跑通过不等于全仓通过。
|
||||
@@ -0,0 +1,32 @@
|
||||
# 魔法笔记与会话联动
|
||||
|
||||
状态:会话联动前后端已实现,真实 Electron 验收通过;全仓验证未全绿。聚焦结果、fixture 修复后复跑及执行时的全仓失败见 [progress.md](./progress.md)。
|
||||
|
||||
## 目标与范围
|
||||
|
||||
用户在阅读回答时,可将内容保存到已有笔记或新笔记,并从笔记返回原会话。会话界面提供文字预览和保存位置选择,与已有 Agent 笔记工具共用存储。
|
||||
|
||||
独立工作区继续承载完整编辑、画布、待办和 AI 评论;右侧笔记面板提供浏览和快速追加。笔记仍属于全局,不因入口所在项目改变归属。
|
||||
|
||||
## 功能要求
|
||||
|
||||
| 编号 | 要求 |
|
||||
| --- | --- |
|
||||
| FR-1 | 右侧助手工作栏增加“笔记”应用,支持搜索、打开已有笔记、新建笔记、查看记录摘要、快速追加文字,以及打开对应完整工作区。 |
|
||||
| FR-2 | 助手消息操作栏提供“加入笔记”,打开可编辑预览,用户选择已有笔记或新建后明确提交。 |
|
||||
| FR-3 | 会话标题的更多菜单提供“保存当前对话到笔记”,按触发时的会话内容生成预览,保存为目标笔记中的一条记录。 |
|
||||
| FR-4 | 左侧底部提供“快速笔记”,侧栏收起时由聊天页头提供同名图标入口;打开右侧面板并恢复当前应用会话中最近选择的笔记,首次使用显示列表。此入口不隐式保存当前对话。 |
|
||||
| FR-5 | 从会话保存的记录保留结构化来源,显示会话名称、所属项目(如有)和采集时间,支持返回原会话及单条来源消息。源会话删除后保留笔记内容。 |
|
||||
| FR-6 | 面板、完整工作区和 Agent 写入使用同一份笔记数据,成功写入后更新已打开视图,同时保护未保存草稿。 |
|
||||
|
||||
首版不包含自动总结、自动分类、自动选择保存目标、选中文本采集、多条消息勾选、附件文件复制或跨设备同步。“总结后加入”和选区采集作为后续扩展,不预留不可用按钮。
|
||||
|
||||
## 产品验收
|
||||
|
||||
- 首次使用且没有笔记时,可从一条助手回答创建笔记并保存首条记录;已有笔记时可搜索并追加,原记录保持不变。
|
||||
- 保存当前对话包含未在屏幕上渲染的历史正文;预览范围明确,超出容量时提示缩减内容,不静默截断。
|
||||
- 保存成功后显示目标笔记并定位新增记录;取消不写入,失败保留内容和目标供重试。
|
||||
- 从来源条可返回对应会话;会话已删除时显示“原会话已不存在”,已保存正文仍可阅读和编辑。
|
||||
- 面板追加后完整工作区可见,Agent 修改后面板可见;后台刷新和切换会话不覆盖未保存文字。
|
||||
|
||||
状态与内容范围见 [逻辑设计](./logic-design.md),入口和操作细节见 [界面设计](./ui-design.md),接口与存储见 [技术设计](./technical-design.md#conversation-integration)。
|
||||
@@ -1,5 +1,78 @@
|
||||
# Magic Notes Progress
|
||||
|
||||
## 2026-09-26: Conversation Capture and Compact Notes Panel
|
||||
|
||||
- FR-1/FR-4: `notes` is an application-scoped optional singleton in the workbar.
|
||||
The compact panel supports title/body search, browsing, text appends and full
|
||||
workspace navigation. Quick notes uses the same tab; app enablement controls
|
||||
availability independently of sidebar pinning.
|
||||
- FR-2/FR-3: Assistant-message and conversation-header actions open editable text
|
||||
previews. Whole-conversation capture loads complete history. App owns drafts
|
||||
and selection; close, replacement and disable actions use the draft guard.
|
||||
Success focuses the returned entry ID; failed saves retain input.
|
||||
- FR-5: Schema 48 adds nullable source metadata. Main validates message ownership
|
||||
and resolves display labels at save time. Panel and workspace share source
|
||||
navigation, including missing-message and missing-conversation handling.
|
||||
- FR-6: Desktop search, preload/IPC and note-level SQL results are connected.
|
||||
Creating a note with initial content commits note/entry membership in one
|
||||
transaction. Both views use existing change notifications; file reconciliation
|
||||
and workspace optimistic revisions retain their existing boundaries. See
|
||||
[the implemented contract](./technical-design.md#conversation-integration).
|
||||
|
||||
Validation reported by implementation subagents in this session:
|
||||
|
||||
| Scope | Reported result | Evidence boundary |
|
||||
| --- | --- | --- |
|
||||
| Backend focused checks | 362 tests passed | Subagent handoff; not a repository-wide result |
|
||||
| Frontend focused checks | 8 files / 592 tests passed | Subagent handoff; not real Electron acceptance |
|
||||
| Web TypeScript and lint | Passed | Subagent handoff; does not establish full-repository typecheck/lint |
|
||||
|
||||
The coordinating agent subsequently reported real Electron acceptance passing.
|
||||
[magic-notes-capture.electron.test.ts](../../../tests/magic-notes-capture.electron.test.ts)
|
||||
and its [Main driver](../../../tests/support/magic-notes-capture-main.ts) /
|
||||
[renderer](../../../tests/support/magic-notes-capture-renderer.tsx) mount the real
|
||||
App UI and use production preload, registered IPC and SQLite/file storage.
|
||||
Unrelated services use test dependencies; the renderer bridge is not replaced.
|
||||
|
||||
- Saving an assistant response to an existing note retains its earlier entry;
|
||||
whole-conversation capture creates a new note with its first entry.
|
||||
- All 502 historical messages are compared verbatim in the preview and saved
|
||||
content, including history initially outside the rendered timeline.
|
||||
- Full-workspace navigation locates the exact saved entry; source navigation
|
||||
restores the conversation and focuses the source message. The coordinating
|
||||
agent also reports source-history expansion coverage.
|
||||
- Native Electron keyboard input covers returning to the list, opening a note
|
||||
and appending text in a measured 214px panel, without horizontal overflow.
|
||||
- SQLite close/reopen preserves both notes. Deleting the source conversation
|
||||
retains their saved content and source metadata. Model calls: **0**.
|
||||
|
||||
The combined Electron, `canvas-ipc.integration`, `MagicNotesPanel` and
|
||||
`ChatTimeline` run passed **4 files / 70 tests**. Lint and web TypeScript passed.
|
||||
This validates the App capture path in a test Electron window with isolated data;
|
||||
it does not establish release-package or cross-platform acceptance.
|
||||
|
||||
Repository validation and subsequent fixture repairs:
|
||||
|
||||
| Check | Result at execution time | Follow-up |
|
||||
| --- | --- | --- |
|
||||
| `npm test` | 457 files / 5,359 cases: 5,272 passed, 4 failed, 83 skipped | No all-green full-suite rerun reported |
|
||||
| Three schema-fixture failures | Activity-history and two worker fixture variants omitted `DROP COLUMN source_json` when reconstructing old schemas | Fixed; the five-file regression run below passed |
|
||||
| Remaining test failure | `tests/build-release.test.ts`: missing DSH resources | Unrelated to notes; not fixed in this validation pass |
|
||||
| Full-repository typecheck | Failed on parallel SSH mocks missing `forwardLoopback`, an IPC native-terminal fixture referencing undefined `terminalManager`, and mismatched arguments in `obsidian-runtime-acceptance` | Execution-time findings; later concurrent changes may alter them |
|
||||
|
||||
After fixture repairs, **5 files / 58 tests passed**:
|
||||
`src/main/assistant/activity-history-io.test.ts`,
|
||||
`tests/assistant-storage-worker.test.ts`,
|
||||
`src/main/assistant/assistant-storage-upgrade.test.ts`,
|
||||
`src/main/magic-notes/magic-note-storage.test.ts` and
|
||||
`src/main/magic-notes/canvas-ipc.integration.test.ts`.
|
||||
This focused rerun does not replace the failed full-suite/typecheck results.
|
||||
|
||||
Status: **implemented; real Electron acceptance passed; repository validation is
|
||||
not all green**. Results above come from the session handoffs, not a rerun by this
|
||||
documentation task. Later fixes require their own verification evidence; older
|
||||
Electron/full-suite results below do not validate this integration.
|
||||
|
||||
## 2026-09-24: Resizable Todo List and Collapsible Note Groups
|
||||
|
||||
- Todo list/detail uses a 1px divider with a transparent 9px pointer target and
|
||||
|
||||
@@ -449,6 +449,124 @@ These note tools run in the desktop gateway. Remote gbagent ACP sessions
|
||||
currently inject only the image MCP server, so this change requires no
|
||||
daemon implementation update.
|
||||
|
||||
## Conversation Integration
|
||||
|
||||
The desktop API and renderer integration are implemented. Scope and behavior
|
||||
are owned by the [PRD](./prd.md), [logic design](./logic-design.md) and
|
||||
[UI design](./ui-design.md). Real Electron acceptance passed; focused results,
|
||||
fixture repairs and non-green repository checks are recorded in [progress](./progress.md).
|
||||
|
||||
### Workbar and Capture
|
||||
|
||||
`WORKBAR_APP_DEFINITIONS` registers `notes` as an optional, closable, reorderable
|
||||
singleton with application scope, no `targetRef` and `defaultOpen: false`.
|
||||
`RightAssistantSidebar` opens or activates it through the existing
|
||||
[workbar tab model](../assistant-workbar/terminal-tabs-prd.md), and removes it when
|
||||
Magic Notes is disabled. Sidebar pinning does not control this availability.
|
||||
`MagicNotesPanel` renders the compact view; `WorkbarShell` supplies the shared tab
|
||||
controls. The footer shortcut and collapsed-sidebar chat-header shortcut both
|
||||
activate the same instance.
|
||||
|
||||
`App.captureToNote` receives the message identity from `ChatTimeline`, or calls
|
||||
`ensureConversationHistory` for whole-conversation capture. It freezes text and
|
||||
source IDs before opening the preview and waits for queued conversation persistence
|
||||
so Main can validate newly completed messages. Whole-conversation text includes
|
||||
nonempty user/assistant bodies with role headings. It excludes reasoning, tool
|
||||
logs and attachment binaries, and rejects streaming conversations.
|
||||
|
||||
`useMagicNoteDraft` lives in App and owns the draft, selected note, saving state
|
||||
and one shared confirmation promise. Selection and drafts survive panel remounts
|
||||
and conversation/project switches, but are not persisted across app restarts.
|
||||
The guard rejects leaving while saving and confirms discarding pending input;
|
||||
explicit cancellation compares text/title with their initial preview values.
|
||||
Application disablement and tab closing call the same guard. Workspace navigation
|
||||
also passes through the full workspace's existing leave check.
|
||||
|
||||
`capturedNoteContent` converts text into v1 Quill string inserts, preserving
|
||||
newlines and adding the terminal newline when needed. It splits inserts at the
|
||||
200,000-code-unit operation limit without splitting surrogate pairs; the complete
|
||||
record still passes the shared rich-content schema. Markdown stays literal text.
|
||||
No summarization or attachment copying runs during capture. New-note titles are
|
||||
limited to 100 characters. A synchronous submission ref prevents duplicate writes.
|
||||
|
||||
`magicNotes.create({ title, content?, source? })` returns `MagicNoteCreateResult`,
|
||||
with `createdEntryId` when initial content exists. `createMagicNote` inserts the
|
||||
note, first entry, source and derived todos inside one SQLite transaction; failure
|
||||
leaves no committed empty note and sends no success notification. This atomicity
|
||||
applies to database membership; filesystem writes retain the reconciliation
|
||||
boundary in [File Storage and Writes](#file-storage-and-writes).
|
||||
`magicNotes.createEntry({ noteId, content, source? })` always returns the exact
|
||||
`createdEntryId`. The panel uses that ID to scroll, focus and briefly highlight the
|
||||
new record. Opening the full workspace passes `{noteId, entryId?, requestId}` into
|
||||
its existing guarded note-navigation path.
|
||||
|
||||
`magicNotes.search({ query, limit? })` is exposed by `DesktopApi`, preload and
|
||||
`magic-notes:search`. Trusted-sender and shared-schema validation precede
|
||||
`AssistantDatabase.searchMagicNoteSummaries`. The trimmed query has a 1,000-character
|
||||
limit; result limits are 1-200, defaulting to 200. The panel requests 100 results
|
||||
and debounces nonempty queries by 180 ms. SQL searches note titles or indexed entry
|
||||
text using `EXISTS`, so each note occurs once before `LIMIT`. Empty queries list
|
||||
notes; ordering is pinned first, then updated time and row ID descending.
|
||||
`%`, `_` and backslashes are escaped for literal matching. Agent `note_search`
|
||||
retains its separate entry-level output and 1-100 limit.
|
||||
|
||||
### Source Metadata
|
||||
|
||||
`magicNoteSourceSchema` defines `kind` (`message` or `conversation`),
|
||||
`conversationId`, nonempty unique `messageIds`, ISO `capturedAt`,
|
||||
`conversationTitle`, and optional `projectId` / `projectName`. A message source
|
||||
requires exactly one message ID. Create/create-entry inputs accept `source`;
|
||||
note creation requires initial content when source is supplied. Entry reads
|
||||
return it independently of editable content, while update inputs cannot replace it.
|
||||
|
||||
The IPC helper `resolveMagicNoteSource` loads the stored conversation and verifies
|
||||
that every message ID belongs to it; a single-message source must identify an
|
||||
assistant message. It replaces renderer-supplied title/project labels with current
|
||||
database values while retaining the supplied capture time and IDs. Preview labels
|
||||
therefore describe capture time, but stored labels describe save time. Missing
|
||||
source rows reject creation; later source deletion does not block note reads or edits.
|
||||
|
||||
Schema 48 adds nullable `magic_note_entries.source_json` in a transaction and
|
||||
advances `PRAGMA user_version`. Existing entries read without a source. It adds no
|
||||
conversation foreign key or deletion cascade, and does not rewrite file-backed
|
||||
bodies. Schema 38 remains the historical body migration. Structure-only upgrade
|
||||
does not independently trigger body conversion or VACUUM; see the
|
||||
[database migration guide](../../development/database-migrations.md). Coordinated
|
||||
SQLite/files backups include the source metadata.
|
||||
|
||||
`MagicNoteSource` is shared by panel summaries and workspace records. Its callback
|
||||
`App.openNoteSource` reads `conversations.get`, then navigates through the workspace
|
||||
leave guard. Message navigation increases the mounted timeline range before
|
||||
scrolling and focusing. A missing message opens its conversation with a notice;
|
||||
a confirmed missing conversation disables that source bar's jump buttons. Other
|
||||
read errors remain retryable. No deleted-source flag is stored.
|
||||
|
||||
### Refresh and Validation
|
||||
|
||||
Both views use the same Main store and `magic-notes:changed` notification. The
|
||||
panel reloads search and selected detail when active, and ignores superseded
|
||||
responses. Search/loading state belongs to the mounted panel; input and selected
|
||||
note belong to App. A deleted selected note clears the selection and matching
|
||||
target ID while preserving draft text. Read and save failures have local recovery
|
||||
feedback. The full workspace retains its existing revision and dirty-editor rules.
|
||||
|
||||
After a successful save, only `after-save-auto` starts entry analysis using the
|
||||
returned `createdEntryId` and configured comment format. Analysis errors notify
|
||||
without undoing the save or recreating the entry. Other comment modes perform no
|
||||
panel analysis.
|
||||
|
||||
Regression cases are in `MagicNotesPanel.test.tsx`, `App.test.tsx`,
|
||||
`ChatTimeline.test.tsx`, `MagicNotesWorkspace.test.tsx`, workbar contract tests,
|
||||
database/storage tests and production preload/IPC integration tests.
|
||||
`tests/magic-notes-capture.electron.test.ts` mounts the real App with production
|
||||
preload and capture IPC, backed by SQLite/files. It validates existing/new-note
|
||||
saves, verbatim 502-message history, workspace/source navigation, native keyboard
|
||||
input in a narrow panel, database reopen and retention after source deletion,
|
||||
with zero model calls. Failed writes and external refresh retain their focused
|
||||
regression coverage; this Electron result does not claim every failure path.
|
||||
Repository test/typecheck failures and repaired migration fixtures are documented
|
||||
separately in [progress](./progress.md).
|
||||
|
||||
## Validation
|
||||
|
||||
- `magic-note-storage.test.ts` uses real files and SQLite for migration equality,
|
||||
@@ -476,6 +594,6 @@ daemon implementation update.
|
||||
coverage includes portal placement, keyboard navigation, dismissal, delete
|
||||
confirmation, target selection, revision failures and draft preservation.
|
||||
|
||||
Schema 38 and the file layout above govern current persistence; refresh
|
||||
Schema 48 adds source metadata to the schema 38 file-backed body layout; refresh
|
||||
notifications need no separate storage or network service. Dated validation
|
||||
results and remaining repository checks are owned by [progress](./progress.md).
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# 会话联动界面设计
|
||||
|
||||
状态:已接入前端,真实 Electron 验收通过;全仓验证未全绿,结果见 [progress.md](./progress.md)。遵循根目录 [UI-DESIGN.md](../../../UI-DESIGN.md),需求和行为分别由 [PRD](./prd.md) 与 [逻辑设计](./logic-design.md)定义。独立工作区布局继续由根文档 13.7 节维护。
|
||||
|
||||
## 入口
|
||||
|
||||
| 位置 | 文案与动作 |
|
||||
| --- | --- |
|
||||
| 助手工作栏“+”菜单 | 增加“笔记”,打开或激活单个笔记 Tab。 |
|
||||
| 助手消息底部,复制旁 | 图标按钮“加入笔记”,进入该消息的采集预览。 |
|
||||
| 会话标题更多菜单 | “保存当前对话到笔记”,加载完整历史后进入整段采集预览;生成、采集加载或保存期间禁用。 |
|
||||
| 左侧底部,应用中心与设置操作组上方 | “快速笔记”,打开面板;侧栏收起时在聊天页头显示带同名提示的图标。 |
|
||||
| 面板笔记标题旁 | “在完整工作区打开”,进入当前笔记;有待保存文字时先处理草稿。 |
|
||||
|
||||
左侧主导航中的“魔法笔记”继续打开独立工作区,两处入口通过名称说明不同目的。快速笔记不读取文本选区,不根据选区改变动作。
|
||||
|
||||
## 紧凑面板
|
||||
|
||||
面板按单列显示列表或笔记详情,不嵌入完整工作区的三栏布局。搜索位于列表顶部,“新建笔记”在列表之后;笔记行显示标题、置顶状态、两行摘要和更新时间。无笔记时提供新建动作;搜索无结果时保留搜索词并允许创建。
|
||||
|
||||
详情顶部提供返回列表、笔记标题、全局范围标识和打开完整工作区。中间以可滚动记录摘要供浏览,每条文字摘要最多显示前 600 个字符,画布显示首页缩略图及页数;记录按钮可在完整工作区定位该记录。底部提供快速追加文字输入区与“加入笔记”按钮,画布编辑、待办管理和 AI 评论阅读仍在完整工作区。
|
||||
|
||||
从会话触发时,面板切到采集编辑视图:
|
||||
|
||||
```text
|
||||
加入笔记
|
||||
来自:项目 / 会话标题 · 单条回答或当前对话
|
||||
保存范围:用户与助手正文,不含推理、工具日志和附件文件
|
||||
|
||||
待加入内容
|
||||
[可编辑文字预览]
|
||||
|
||||
保存到
|
||||
[搜索或选择已有笔记]
|
||||
[新建笔记 → 标题输入]
|
||||
|
||||
[取消] [加入笔记]
|
||||
```
|
||||
|
||||
范围说明随单条或整段来源调整。预览初始包含完整待保存文字,可滚动编辑。新建目标标题默认取会话标题前 100 个字符,可修改;已有目标与新建目标使用共享 `SegmentedControl` 切换。采集内容为空或超限、缺少目标、新建标题为空或超限时就地提示,并禁用保存;普通新建允许创建空笔记。
|
||||
|
||||
读取失败显示就地重试按钮;保存失败保留输入并在提交区显示错误,用户可再次点击“加入笔记”。成功通过应用通知反馈,切回目标笔记详情,滚动定位、聚焦并高亮新增记录约 2.4 秒。仅“保存后自动评论”模式发起后续分析,分析失败另行通知,已保存内容保留。
|
||||
|
||||
## 来源与可访问性
|
||||
|
||||
记录摘要和完整工作区的已保存记录均显示“来自会话”来源条,内容含保存时标题、项目及采集时间。单条来源提供返回会话和定位原消息按钮,整段来源提供返回会话按钮。点击后确认原会话不存在才显示对应文案并禁用跳转;其他错误提供就地重试。来源条与正文分开,编辑正文时仍可识别来源。
|
||||
|
||||
Tab 使用工作栏现有的共享页签、焦点和关闭模式。搜索有持久标签,列表用可键盘访问的按钮;打开采集后聚焦预览,取消返回触发按钮,触发按钮已不可见时尝试返回会话标题菜单按钮。新建标题出现后聚焦输入框。面板中的 Escape 取消当前草稿,或从详情返回列表;需要放弃输入时先显示草稿确认。确认框初始聚焦“继续编辑”,限制 Tab 焦点范围,Escape 保留草稿并关闭确认。
|
||||
|
||||
面板服从工作栏现有宽度和停靠规则,以单列切换列表、详情和采集编辑。按钮组可换行,文字摘要保留换行并折行长文本;Markdown 和代码以原始文字显示。头部与快速追加区固定,中间内容独立滚动;完整预览输入区可纵向调整大小。配色、按钮、焦点环、通知和确认使用共享组件与令牌。真实 Electron 已在实测 214px 面板验证无横向溢出,以及原生键盘返回列表、打开笔记和追加保存。
|
||||
Reference in New Issue
Block a user