对齐 Wolai 侧栏体验并收拢设计入库
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# [recycle] AI Tool Cutover Matrix
|
||||
|
||||
> 更新时间:2026-04-16
|
||||
>
|
||||
> 目标:建立 `builtins` 到 Rust Tool registry 的一一对应矩阵,并明确每个工具当前的割接状态。
|
||||
|
||||
## 1. 结论
|
||||
|
||||
- 本文覆盖 `docsServerTools`、`mediaServerTools`、`mindmapServerTools`、`onlyofficeServerTools`、`registryBuiltins` 与 `ai-agent/run` 的一一对应关系。
|
||||
- `docs_search`、`docs_read` 已进入 Rust tool runtime;`ai-agent/run` 在 Convex 模式下直接通过 `executeRustBridgeTool(...)` 执行,`docsServerTools` 仅保留非 Convex / 兼容 fallback。
|
||||
- `search_web`、`image_read`、`slash_run` 已进入 Rust tool registry,TS 仅保留最小 transport 壳或数据加载壳。
|
||||
- `asset_extract_outline`、`asset_to_mindmap`、`oo_*` 继续保留 TS transport / 产品编排边界,但 `asset_to_mindmap` 的真正导图写入已收口到 Rust `mindmap_apply_ops`。
|
||||
- AI 工具链的运行态证据已经补齐:`wolai-frontend/src/lib/ai-agent/runtime/runAgent.test.ts` 已验证 `docs_search -> docs_read` 的 runtime 调用顺序与事件流。
|
||||
|
||||
## 2. 一一对应矩阵
|
||||
|
||||
| builtin tool | Rust toolset | Rust tool name | 当前状态 | 说明 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `search_web` | `toolset.readonly` | `search_web` | `RUST_OWNER` | 联网检索已完全切到 Rust runtime,TS route 只保留 transport 壳。 |
|
||||
| `image_read` | `toolset.media_read` | `image_read` | `RUST_OWNER` | 图片/附件 OCR 结果已由 Rust runtime 统一归一化,TS 仅负责最小 transport 取数。 |
|
||||
| `slash_run` | `toolset.slash_write` | `slash_run` | `RUST_OWNER` | Rust 负责命令解析与结果标准化,TS 只保留创建/重命名 transport 写壳。 |
|
||||
| `docs_search` | `toolset.docs_read` | `docs_search` | `RUST_OWNER` | Convex 主链已改为 Rust runtime 执行搜索与结果归一化,TS 仅负责拉取搜索数据集 transport。 |
|
||||
| `docs_read` | `toolset.docs_read` | `docs_read` | `RUST_OWNER` | Convex 主链已改为 Rust runtime 执行裁剪与结果归一化,TS 仅负责读取目标文档 transport。 |
|
||||
| `rag_lightrag_query` | `toolset.rag_read` | `rag_lightrag_query` | `TS_TRANSPORT_KEEP` | 依赖外部 LightRAG 服务,不在本轮切换主线。 |
|
||||
| `asset_extract_outline` | `toolset.onlyoffice_read` | `asset_extract_outline` | `TS_TRANSPORT_KEEP` | 仍需附件下载和 MinerU 解析,长期保留 TS transport / 外部服务编排。 |
|
||||
| `asset_to_mindmap` | `toolset.onlyoffice_write` | `asset_to_mindmap` | `TS_TRANSPORT_KEEP` | 附件大纲提取仍依赖 TS/MinerU,但真正的导图写入已经改走 Rust `mindmap_apply_ops`。 |
|
||||
| `oo_get_selection` | `toolset.onlyoffice_editor` | `oo_get_selection` | `TS_TRANSPORT_KEEP` | 客户端插件内执行,Web 侧只做回传。 |
|
||||
| `oo_replace_selection` | `toolset.onlyoffice_editor` | `oo_replace_selection` | `TS_TRANSPORT_KEEP` | 客户端插件内执行,Web 侧只做回传。 |
|
||||
| `oo_insert_text` | `toolset.onlyoffice_editor` | `oo_insert_text` | `TS_TRANSPORT_KEEP` | 客户端插件内执行,Web 侧只做回传。 |
|
||||
| `oo_insert_html` | `toolset.onlyoffice_editor` | `oo_insert_html` | `TS_TRANSPORT_KEEP` | 客户端插件内执行,Web 侧只做回传。 |
|
||||
| `oo_insert_image` | `toolset.onlyoffice_editor` | `oo_insert_image` | `TS_TRANSPORT_KEEP` | 客户端插件内执行,Web 侧只做回传。 |
|
||||
|
||||
## 3. Rust registry 对照
|
||||
|
||||
- `toolset.readonly`:`search_web`
|
||||
- `toolset.media_read`:`image_read`
|
||||
- `toolset.slash_write`:`slash_run`
|
||||
- `toolset.docs_read`:`docs_search`、`docs_read`
|
||||
- `toolset.rag_read`:`rag_lightrag_query`
|
||||
- `toolset.onlyoffice_read`:`asset_extract_outline`
|
||||
- `toolset.onlyoffice_write`:`asset_to_mindmap`
|
||||
- `toolset.onlyoffice_editor`:`oo_*`
|
||||
|
||||
## 4. 本轮 cutover 结果
|
||||
|
||||
本轮已完成:
|
||||
|
||||
- 以 `ai-agent/run` 为统一入口,对齐 `registryBuiltins` 与服务端 builtin 实现,避免再长出第二套工具分发表。
|
||||
- 把 `docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run` 接到 Rust tool runtime,并在代码侧绑定里冻结为 Rust owner。
|
||||
- 把 `asset_to_mindmap` 收口为“TS 提纲提取 + Rust 导图写入”的明确边界,不再保留模糊的 `TS_COMPAT_PENDING` 口径。
|
||||
- 保留 `oo_*`、`client-tool-result`、`asset_extract_outline` 这类长期 `TS_TRANSPORT_KEEP` / 产品编排壳。
|
||||
|
||||
## 5. 后续维护边界
|
||||
|
||||
- `docsServerTools` 继续只服务于非 Convex / fallback 模式,不再承担 Convex 主链真执行。
|
||||
- `asset_extract_outline` 若未来要继续 Rust 化,应只处理解析链迁移,不涉及当前 Rust tool runtime 的 owner 边界回退。
|
||||
- `asset_to_mindmap` 若未来继续下沉,可进一步把“大纲转导图 ops”的编排逻辑迁入 Rust;在此之前,它已经是明确的 `TS_TRANSPORT_KEEP`。
|
||||
- `oo_*` 继续保持客户端插件边界,只通过 `/api/ai-agent/client-tool-result` 回传结果。
|
||||
|
||||
## 6. 第一批 TS_LEGACY_DELETE 清单
|
||||
|
||||
以下旧面已经满足“先停写、再切调用方、最后删除”的文档准备条件,应纳入第一批 `TS_LEGACY_DELETE`:
|
||||
|
||||
- `documents/create-child`
|
||||
- `documents/embed`
|
||||
- `documents/empty-trash`
|
||||
- `documents/purge`
|
||||
- `documents/template`
|
||||
- `mindmap-trash/empty`
|
||||
- `builtins/**`
|
||||
|
||||
删除原则:
|
||||
|
||||
- `documents/create-child`、`documents/embed`、`documents/empty-trash`、`documents/purge`、`documents/template` 仅允许保留 route transport 壳,不再保留 route 内私有业务逻辑。
|
||||
- `mindmap-trash/empty` 需要在确认 Rust tool/runtime 与统一失败落账稳定后,删除 TS 旧实现。
|
||||
- `builtins/**` 中已经被 Rust tool runtime 接管的服务端真入口,应先收口到 `ai-agent/run` 或 Rust runtime,再物理删除 legacy helper。
|
||||
@@ -0,0 +1,132 @@
|
||||
# [recycle] Mindmap 与 OnlyOffice 当前边界说明
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 主仓:`/mnt/Data1T/mnote`
|
||||
|
||||
## 1. Mindmap 当前主链
|
||||
|
||||
### 1.1 主组件与嵌入链路
|
||||
|
||||
- 主组件:`/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx`
|
||||
- BlockNote 注册入口:`/mnt/Data1T/mnote/wolai-frontend/src/components/editor/schema.ts`
|
||||
- 独立全屏页:`/mnt/Data1T/mnote/wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx`
|
||||
|
||||
当前事实:
|
||||
|
||||
- `MindmapBlockView` 同时服务文档内嵌块与独立全屏页。
|
||||
- 独立页通过 `editorStub` 复用同一组件,不额外复制第二套思维导图主壳。
|
||||
- 文档内嵌与独立页共用同一套工具栏、侧栏、导航器、缩略图与上下文菜单子组件。
|
||||
|
||||
### 1.2 数据入口与 ops 边界
|
||||
|
||||
- 本地读写入口:`/mnt/Data1T/mnote/wolai-frontend/src/lib/mindmap/mindmapLocalStore.ts`
|
||||
- 节点操作入口:`/mnt/Data1T/mnote/wolai-frontend/src/lib/mindmap/mindmapOps.ts`
|
||||
- 页面 API:
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/mindmap/[docId]/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/route.ts`
|
||||
|
||||
当前拆分:
|
||||
|
||||
- 前端交互状态保留在 `MindmapBlock.tsx` 及其子组件内。
|
||||
- 本体数据读写由 `mindmapLocalStore.ts` 提供本地文件落盘兼容接口。
|
||||
- 节点增删改、引用、注释、链接等操作由 `mindmapOps.ts` 统一描述为 `MindmapOp`。
|
||||
- 页面 API 当前通过 Convex `api.mindmaps.*` 承接 `get/put/restore/purge`,保留现有前端形态不变。
|
||||
- 当前 Mindmap API 已补统一元信息口径:
|
||||
- `pageId = documentId`
|
||||
- `attachmentId = mindmapId`
|
||||
- `workspaceId` 统一来自页面归属工作区
|
||||
- `requestId/traceId` 统一从请求头透传或在路由侧兜底生成
|
||||
|
||||
### 1.3 后续 adapter 目标
|
||||
|
||||
后续若进入 Rust adapter,只抽象以下边界,不复制历史仓 UI:
|
||||
|
||||
- 节点树结构
|
||||
- 节点引用 `refs`
|
||||
- 节点操作日志 `MindmapOp`
|
||||
- mindmap 与 page/block 的绑定关系
|
||||
|
||||
## 2. OnlyOffice 当前主链
|
||||
|
||||
### 2.1 页面与 API 边界
|
||||
|
||||
- 页面入口:
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/onlyoffice/page.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/onlyoffice/OnlyOfficeClientPage.tsx`
|
||||
- 页面侧面板:
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/onlyoffice/OnlyOfficeAiAgentPanel.tsx`
|
||||
- API 边界:
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/sign/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/proxy/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/callback/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/forcesave/route.ts`
|
||||
|
||||
当前拆分:
|
||||
|
||||
- `page.tsx` 负责页面级早期 DOM 补丁与容器加载。
|
||||
- `OnlyOfficeClientPage.tsx` 负责编辑器初始化、内部请求改写、代理地址适配与 callback URL 组装。
|
||||
- `sign` 负责 JWT 签名。
|
||||
- `proxy` 负责同源代理与回源 URL 安全限制。
|
||||
- `callback` 负责保存回写存储。
|
||||
- `forcesave` 负责触发文档服务器强制保存。
|
||||
|
||||
### 2.2 与正文和附件的关系
|
||||
|
||||
- Office 文件入口仍来自 `MediaBlock`:`/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MediaBlock.tsx`
|
||||
- 正文里只保留附件块与跳转入口,不在 BlockNote 内直接运行 OnlyOffice 编辑器。
|
||||
- OnlyOffice 编辑器继续在独立 `/onlyoffice` 页面运行。
|
||||
- 当前 OnlyOffice 已稳定使用:
|
||||
- `documentId` 作为页面业务标识
|
||||
- `assetId` 作为附件业务标识
|
||||
- 页面归属仍由文档/附件在 Convex 中的 `workspace_id` 与 `document_id` 决定
|
||||
|
||||
## 2.5 与 Mindmap 对齐后的共享标识口径
|
||||
|
||||
- 页面标识:
|
||||
- Mindmap 使用 `pageId/documentId`
|
||||
- OnlyOffice 使用 `documentId`
|
||||
- 附件标识:
|
||||
- Mindmap 使用 `attachmentId/mindmapId`
|
||||
- OnlyOffice 使用 `assetId`
|
||||
- 页面归属:
|
||||
- 两者都以 Convex 中的 `workspace_id + document_id` 作为最终归属真相
|
||||
- 追踪字段:
|
||||
- Mindmap API 已返回 `requestId/traceId`
|
||||
- OnlyOffice 页面当前通过查询参数与调试上下文持有 `assetId/documentId/userId`,后续若接入统一 Rust adapter,继续沿用同一页面/附件口径
|
||||
|
||||
### 2.3 静态资源边界
|
||||
|
||||
- 根目录静态资源保留在 `/mnt/Data1T/mnote/src/components/onlyoffice/`
|
||||
- 当前已确认存在:
|
||||
- `onlyoffice-web-apps/`
|
||||
- `onlyoffice-plugins/`
|
||||
- `onlyoffice-data/`
|
||||
|
||||
这些目录继续保留为运行所需静态资源、插件和数据目录,不做迁移式替换。
|
||||
|
||||
### 2.4 后续 adapter 目标
|
||||
|
||||
后续若进入 Rust adapter,只抽象以下边界:
|
||||
|
||||
- 对象解析与附件定位
|
||||
- 签名生成
|
||||
- callback 写回
|
||||
- forcesave 触发
|
||||
- 代理回源请求
|
||||
|
||||
## 3. 历史仓禁止误复制范围
|
||||
|
||||
以下历史仓路径只作为参考,不进入主仓主线:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/app/documents/[id]/mindmap/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/documents/[id]/office/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/components/sidebar/sidebar.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/onlyoffice/page.tsx`
|
||||
|
||||
约束:
|
||||
|
||||
- 不复制第二套对象页壳。
|
||||
- 不复制第二套 sidebar 壳。
|
||||
- `adapter-onlyoffice`、`adapter-mindmap` 继续作为后置实现项,而不是本阶段直接迁入主线。
|
||||
@@ -0,0 +1,48 @@
|
||||
# [recycle] Phase 8 Cutover Log 2026-04-15
|
||||
|
||||
## 概要
|
||||
|
||||
- 完成 Phase 8 收口,Rust 已成为 mnote 的唯一业务执行平面。
|
||||
- 完成 `task-036` 到 `task-044`,并清空 harness 中全部历史失败/待办状态。
|
||||
- ONLYOFFICE 已升级到 `9.3.1`,真实页面打开、插件桥、callback、forcesave 回归通过。
|
||||
|
||||
## 本轮关键变更
|
||||
|
||||
### 1. 页面与对象主链
|
||||
|
||||
- 页面旧面 `documents/create-child`、`documents/embed`、`documents/empty-trash`、`documents/purge`、`documents/template` 已收口到统一 adapter,route 仅保留 transport。
|
||||
- Mindmap 剩余旧面已接到 Rust mindmap adapter/tool,AI/Mindmap 写链失败态开始统一落账。
|
||||
- OnlyOffice sign/proxy/callback/forcesave 已固定为 `TS_TRANSPORT_KEEP`,对象规则与 session/sign/proxy/callback 准备由 Rust adapter 持有。
|
||||
|
||||
### 2. AI 工具面
|
||||
|
||||
- `search_web`、`image_read`、`slash_run` 已切到 Rust Tool runtime 主路径。
|
||||
- `ai-agent/run` 不再保留 `search_web` 的 TS fallback。
|
||||
- `mediaServerTools`、`slashServerTools` 已收缩为 transport helper,不再作为私有真入口。
|
||||
|
||||
### 3. 统一观测与状态语义
|
||||
|
||||
- 已补 workspace 级 bridge 总览查询。
|
||||
- 已补失败态、冲突态、补偿态第一批统一落账。
|
||||
- `bridge-log/runtime` 与页面主写链、AI/Mindmap 写链的状态语义开始对齐。
|
||||
|
||||
### 4. 文档与清单
|
||||
|
||||
- 已更新 `rust-kernel-cutover-v1.md`。
|
||||
- 已更新 `release-readiness-source-audit.md`。
|
||||
- 已更新 `rust-kernel-backport-phase-checklist.md`。
|
||||
- 已更新 `rust-kernel-missing-targets.md`。
|
||||
- 已新增 `rust-kernel-legacy-delete-list.md`。
|
||||
- 已更新 `ai-tool-cutover-matrix.md`。
|
||||
|
||||
## 当前结论
|
||||
|
||||
可以使用下面这句统一口径:
|
||||
|
||||
> Rust 已成为 mnote 的唯一业务执行平面;Web route 只保留 transport、auth、session、streaming、proxy 与 callback 壳。
|
||||
|
||||
## 后续建议
|
||||
|
||||
- 执行第一批 `TS_LEGACY_DELETE` 的物理删除。
|
||||
- 继续压缩 `builtins/**` 中剩余的 TS 兼容实现。
|
||||
- 对 OnlyOffice、Mindmap 和 AI 工具链做一轮发布前运行态回归复核。
|
||||
@@ -0,0 +1,193 @@
|
||||
# [recycle] 发布前源代码审计
|
||||
|
||||
> 更新时间:2026-04-16
|
||||
>
|
||||
> 审计范围:`/mnt/Data1T/mnote`
|
||||
|
||||
## 1. Bridge 入口与日志回查
|
||||
|
||||
### 1.1 最小查询与写入入口
|
||||
|
||||
当前已确认的 bridge 主线入口:
|
||||
|
||||
- 查询:
|
||||
- `src/app/api/documents/content/route.ts`
|
||||
- `src/app/api/documents/meta/route.ts`
|
||||
- `src/app/api/sidebar/route.ts`
|
||||
- 写入:
|
||||
- `src/app/api/documents/title/route.ts`
|
||||
- `src/app/api/documents/stats/route.ts`
|
||||
- `src/app/api/documents/options/route.ts`
|
||||
- `src/app/api/documents/save/route.ts`
|
||||
- `src/app/api/blocks/patch/route.ts`
|
||||
- `src/app/api/onlyoffice/callback/route.ts`
|
||||
|
||||
### 1.2 日志与事件落账
|
||||
|
||||
当前已确认:
|
||||
|
||||
- `src/lib/documents/metadata-command-adapter.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||||
- `src/lib/documents/save-command-adapter.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||||
- `src/app/api/blocks/patch/route.ts` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||||
- `src/lib/documents/media-asset-command-adapter.ts` 会在 ONLYOFFICE callback 成功写回后尝试复用同一 bridge log 落账
|
||||
- `src/lib/documents/bridge-log.ts` 会同时写入:
|
||||
- `bridgeLogs.recordCommandLog`
|
||||
- `bridgeLogs.recordDomainEvent`
|
||||
- 回查入口:
|
||||
- `src/app/api/bridge/request/route.ts -> bridgeLogs.listByRequest`
|
||||
- `src/app/api/bridge/trace/route.ts -> bridgeLogs.listByTrace`
|
||||
|
||||
结论:
|
||||
|
||||
- bridge 的最小查询、最小写入、日志生成、事件生成和错误返回已经形成源码闭环。
|
||||
|
||||
## 2. 保存口径审计
|
||||
|
||||
当前正文与页面元信息主写链如下:
|
||||
|
||||
- `documents.save -> api.documents.updateContent`
|
||||
- `documents.title.update -> api.documents.updateTitle`
|
||||
- `documents.stats.update -> api.documents.updateStats`
|
||||
- `documents.options.update -> api.documents.updateOptions`
|
||||
- `blocks.patch -> 读取文档内容后回写 api.documents.updateContent`
|
||||
|
||||
OnlyOffice 写回:
|
||||
|
||||
- `src/app/api/onlyoffice/callback/route.ts -> media.assets.replace_storage -> api.mediaAssets.replaceStorageFromUpload`
|
||||
|
||||
结论:
|
||||
|
||||
- 页面正文、页面元信息、块补丁与 OnlyOffice 附件写回最终都以 Convex mutation 为主事实写入点。
|
||||
- 当前未发现把页面/块主真相改写到 `mnote-rust`、本地缓存目录或其他派生目录的主写链。
|
||||
|
||||
## 3. `trace_id` / `request_id` / `workspace_id` / `page_id` 一致性
|
||||
|
||||
### 3.1 前端与 route
|
||||
|
||||
- `buildDocumentBridgeContext()` 统一生成 `requestId`、`traceId`、`workspaceId`
|
||||
- `buildDocumentBridgeContextWithActor()` 可为 ONLYOFFICE callback 这类无用户 cookie 的服务端回调显式注入 `actor/source`
|
||||
- `buildDocumentCommandEnvelope()` 统一挂载 `commandId`、`target.pageId`
|
||||
- `documents.title/stats/options/save` 均将 `normalizedDocumentId` 作为 `target.pageId`
|
||||
- `onlyoffice/callback` 会把 `asset.document_id` 作为 `target.pageId`,并透传 `workspaceId`
|
||||
|
||||
### 3.2 日志落账
|
||||
|
||||
- `recordBridgeCommandArtifacts()` 使用同一 `context.requestId`、`context.traceId`
|
||||
- `workspaceId` 统一取 `target.workspaceId` 或 `context.workspaceId`
|
||||
- `targetPageId` 统一落到 command log
|
||||
- domain event payload 同时记录 `request_id`、`trace_id`、`command_id`、`command_name`
|
||||
|
||||
### 3.3 当前辅助验证
|
||||
|
||||
- `src/lib/documents/bridge.test.ts` 已覆盖:
|
||||
- `target.pageId = doc_1`
|
||||
- `executeSaveBridgeCommand` 成功路径会调用 `recordBridgeCommandArtifacts`
|
||||
- 返回结果保留 `req_1`、`trace_1`
|
||||
- `src/app/api/onlyoffice/callback/route.test.ts` 已覆盖:
|
||||
- callback 成功路径会调用 `executeMediaAssetWritebackBridgeCommand`
|
||||
- `storageId`、`assetId`、`documentId`、`workspaceId` 会进入 `media.assets.replace_storage` envelope
|
||||
|
||||
结论:
|
||||
|
||||
- `trace_id`、`request_id`、`workspace_id`、`page_id` 在 route、adapter、bridge log、回查入口之间已有统一口径。
|
||||
|
||||
## 4. 禁止事项复查
|
||||
|
||||
### 4.1 不双仓并行
|
||||
|
||||
- 主仓脚本与文档已统一指向 `/mnt/Data1T/mnote`
|
||||
- `wolai-frontend/src`、`wolai-frontend/convex`、`rust/` 下未发现直接依赖 `/mnt/Data1T/mnote-rust` 的运行时代码路径
|
||||
|
||||
### 4.2 不跨仓链接
|
||||
|
||||
- 排除 `node_modules`、`.next`、`.venv`、`rust/target` 等构建产物后,主仓源码范围内未发现跨仓符号链接
|
||||
|
||||
### 4.3 不复制第二套产品前端壳
|
||||
|
||||
- 主仓保留的是既有 `wolai-frontend` 主壳
|
||||
- 历史仓对象页壳与第二套 sidebar 仅在文档中被标记为禁止误复制范围
|
||||
|
||||
### 4.4 不把对象页壳 / diagnostics / smoke 页带入主线
|
||||
|
||||
- 当前主仓 `wolai-frontend/src/app` 下未发现新增的 `diagnostic` / `smoke` 页面目录
|
||||
- 历史仓相关页面已在边界文档中明确列入禁止误复制清单
|
||||
|
||||
### 4.5 不散落多个 Rust 源码根
|
||||
|
||||
- 主仓顶层 `Cargo.toml` 仅存在 `rust/Cargo.toml`
|
||||
- 其余 crate `Cargo.toml` 均位于 `rust/crates/*`
|
||||
|
||||
## 5. 运行态复核结果与最终结论
|
||||
|
||||
本审计只能关闭源码可验证项,但截至 2026-04-16,发布前运行态复核已经补齐五条直接证据:
|
||||
|
||||
- 已复跑 `scripts/task019-document-ui-regression.js`,文档页标题、正文、保存、刷新、回查链通过。
|
||||
- 已复跑 `scripts/task021-mindmap-ui-regression.js`,Mindmap 全屏页的新增子节点、删除子节点、保存链、刷新回查与 `requestId/traceId` 元信息同步通过。
|
||||
- 已复跑 `scripts/task022-onlyoffice-ui-regression.js`,ONLYOFFICE `9.3.1` 基线下的打开、插件桥、callback 写回、forcesave 与 `storage_id` 变化通过。
|
||||
- 已通过 `pnpm exec vitest run src/lib/ai-agent/runtime/runAgent.test.ts`,补齐 `docs_search -> docs_read` 的 AI runtime 调用证据。
|
||||
- 已通过 `bash /mnt/Data1T/mnote/rust/scripts/task049-cli-smoke.sh`,补齐 CLI 主链的最小真实执行验收。
|
||||
|
||||
当前已不再存在阻塞发布的 CLI / AI 运行态尾项。
|
||||
|
||||
补充核验结果:
|
||||
|
||||
- `cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -p bridge-runtime` 已通过。
|
||||
- `wolai-frontend` 相关定向 `eslint` 当前无 error,仅剩仓库既有 warnings,不构成本轮发布阻塞。
|
||||
|
||||
仍然要求环境满足的前置条件:
|
||||
|
||||
- 浏览器回归环境可访问 `http://127.0.0.1:3000`
|
||||
- `MNOTE_ONLYOFFICE_PROBE_DOCX=/tmp/mnote-onlyoffice-probe/probe.docx` 可用
|
||||
- 已登录态可通过 `/auth` 或测试账号快速登录建立
|
||||
|
||||
## 6. 旧 TS 执行面割接清单
|
||||
|
||||
当前源码审计之外,还需要看“哪些 TS route 还能留,哪些只是历史兼容”。
|
||||
|
||||
本轮已新增:
|
||||
|
||||
- `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
|
||||
|
||||
该文档已把主仓当前执行面明确分成四类:
|
||||
|
||||
- `RUST_OWNER`
|
||||
- `TS_TRANSPORT_KEEP`
|
||||
- `TS_COMPAT_PENDING`
|
||||
- `TS_LEGACY_DELETE`
|
||||
|
||||
其中当前仍需要长期观察但不再构成主链阻塞的旧面主要包括:
|
||||
|
||||
- `src/app/api/documents/embed/route.ts`
|
||||
- `src/app/api/mindmap-ai/**`
|
||||
|
||||
其中页面旧面在 2026-04-16 的最终口径如下:
|
||||
|
||||
- `src/app/api/documents/create-child/route.ts` 已改走 `documents.create`
|
||||
- `src/app/api/documents/empty-trash/route.ts` 已改走 `documents.emptyTrashByWorkspace`
|
||||
- `src/app/api/documents/purge/route.ts` 已改走 `documents.purge`
|
||||
- `src/app/api/documents/template/route.ts` 已改走 `documents.template`
|
||||
- `src/app/api/documents/embed/route.ts` 已改走 `documents.save`,但目标页面插入位与 `pageReference` block 组装仍在 TS,因此继续按 `TS_COMPAT_PENDING` / 产品编排壳维护
|
||||
- `src/app/api/mindmap/[docId]/route.ts` 与 `src/app/api/mindmap/[docId]/[mindmapId]/route.ts` 的 `DELETE/PATCH` 已改走 `mindmaps.delete/restore/purge`
|
||||
- `src/app/api/mindmap-trash/empty/route.ts` 已改走 `mindmaps.emptyTrashByWorkspace`
|
||||
- `src/app/api/blocks/*` 现网主链实际统一走 `src/lib/blocks/block-command-adapter.ts`;`src/lib/documents/block-command-adapter.ts` 应视为遗留兼容 helper,而非现网主执行面
|
||||
- `src/app/api/ai-agent/run/route.ts` 的核心工具主链现在已经统一走 Rust tool runtime:`docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run` 不再保留 TS 真执行兜底
|
||||
|
||||
结论:
|
||||
|
||||
- 当前可以说“Rust 已成为 mnote 的主业务执行平面”。
|
||||
- 仍保留的 TS 路径只剩 `TS_TRANSPORT_KEEP`、少量 `TS_COMPAT_PENDING` 产品编排壳与冻结的 `TS_LEGACY_DELETE` 清单。
|
||||
- 第一批 `TS_LEGACY_DELETE` 已不再阻塞这轮 release readiness;它们现在的要求是“保持纯壳 / 冻结 helper,不允许反向长出新的业务规则”。
|
||||
|
||||
最终 release readiness 口径:
|
||||
|
||||
- 若按源码审计口径:可以说明“Rust 已成为 mnote 的唯一业务执行平面”,同时明确仍保留 `TS_TRANSPORT_KEEP` 与少量产品编排壳。
|
||||
- 若按完整发布口径:文档页、Mindmap、OnlyOffice、AI runtime、CLI smoke 的 Phase 8 scoped gate 已闭合,可以给出最终完成结论。
|
||||
- 后续维护口径:剩余 `TS_TRANSPORT_KEEP` / `TS_LEGACY_DELETE` 只属于长期清理与边界维护,不再构成第二套业务执行平面。
|
||||
|
||||
补记:
|
||||
|
||||
- 2026-04-15 已复跑 `scripts/task019-document-ui-regression.js`,确认文档页标题、正文、保存与刷新回查通过。
|
||||
- 2026-04-15 已复跑 `scripts/task021-mindmap-ui-regression.js`,确认新增/删除节点、保存链、刷新回查与 `requestId` / `traceId` 元信息同步通过。
|
||||
- 2026-04-15 已复跑 `scripts/task022-onlyoffice-ui-regression.js`,在升级后的 ONLYOFFICE `9.3.1` 基线上确认 `oo_insert_text` 插件桥、`同步保存`、callback 写回与 `storage_id` 变化仍然通过;本次 callback 最终写回已不再由 route 直接调用 `api.mediaAssets.replaceStorageFromUpload`,而是先经 `media.assets.replace_storage` bridge 命令再落到 Convex。
|
||||
- 2026-04-16 已通过 `src/lib/ai-agent/runtime/runAgent.test.ts`,确认 `docs_search -> docs_read` 的运行态工具链顺序、事件流与结果归一化闭合。
|
||||
- 2026-04-16 已通过 `rust/scripts/task049-cli-smoke.sh`,确认 `sidebar/page/block/search/tool/mindmap` 主链 CLI 真实执行闭合。
|
||||
@@ -0,0 +1,85 @@
|
||||
# [recycle] Rust 回迁资产审计清单
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 主仓:`/mnt/Data1T/mnote`
|
||||
|
||||
## 1. 本轮已确认的主仓 Rust 资产
|
||||
|
||||
### 1.1 Workspace 根
|
||||
|
||||
- `rust/Cargo.toml`
|
||||
- `rust/Cargo.lock`
|
||||
|
||||
### 1.2 已并入主线的 crate
|
||||
|
||||
- `rust/crates/core-domain/`
|
||||
- `rust/crates/core-protocol/`
|
||||
- `rust/crates/event-log/`
|
||||
- `rust/crates/storage-convex-bridge/`
|
||||
- `rust/crates/index-fts/`
|
||||
|
||||
### 1.3 已并入主线的 Rust 设计文档
|
||||
|
||||
- `rust/design/INDEX.md`
|
||||
- `rust/design/core/01-domain-model-v0.md`
|
||||
- `rust/design/core/02-command-query-tool-protocol-v0.md`
|
||||
- `rust/design/core/03-storage-event-indexing-v0.md`
|
||||
- `rust/design/core/04-onlyoffice-integration-boundary-v0.md`
|
||||
|
||||
### 1.4 本轮新增的主仓设计文档
|
||||
|
||||
- `design/rust-kernel-backport-plan.md`
|
||||
- `design/rust-kernel-backport-phase-checklist.md`
|
||||
- `design/rust-single-repo-maintenance-boundary.md`
|
||||
- `design/mindmap-onlyoffice-boundary.md`
|
||||
- `design/sidebar-rust-query-target.md`
|
||||
|
||||
## 2. 当前仍未并入主线的目录
|
||||
|
||||
以下目录当前未在主仓 `rust/` 内出现,仍保持后置状态:
|
||||
|
||||
- `rust/crates/adapter-onlyoffice/`
|
||||
- `rust/crates/adapter-mindmap/`
|
||||
- `rust/crates/adapter-legacy-mnote/`
|
||||
- `rust/crates/mnote-cli/`
|
||||
- `rust/bridge/`
|
||||
- `rust/scripts/`
|
||||
- `rust/fixtures/`
|
||||
- `rust/tests/`
|
||||
|
||||
## 3. 已确认没有误带入的历史噪音
|
||||
|
||||
当前主仓 `rust/` 与根 `design/` 下未发现以下类型内容被直接带入主线:
|
||||
|
||||
- 第二套 Next 页面壳
|
||||
- 历史 `diagnostics` 页面
|
||||
- `smoke` 页面
|
||||
- 历史仓 `.next/`、`.tmp/` 产物目录
|
||||
- `adapter-*` 与 `mnote-cli` 实现目录
|
||||
|
||||
备注:
|
||||
|
||||
- `rust/target/` 为本地编译产物,不属于回迁设计资产。
|
||||
- 发布前若需进一步清理编译产物,应单独征得用户同意,不在本轮处理。
|
||||
|
||||
## 4. 主仓启动路径核对
|
||||
|
||||
当前可验证的主仓入口如下:
|
||||
|
||||
- 根目录热启动:`npm run desktop:hot`
|
||||
- 前端开发:`cd /mnt/Data1T/mnote/wolai-frontend && pnpm dev`
|
||||
- 后端开发:`cd /mnt/Data1T/mnote/wolai-backend && uvicorn app.main:app --reload --port 8000`
|
||||
- Rust 校验:`cargo --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml ...`
|
||||
|
||||
核对结果:
|
||||
|
||||
- 根 `package.json` 的仓库级脚本只指向 `scripts/*.js`
|
||||
- `scripts/desktop-hot.js` 只从主仓根目录解析 `.env.all`
|
||||
- `scripts/desktop-hot.js` 只调起 `wolai-frontend/` 与 `wolai-backend/`
|
||||
- `AGENTS.md` 的常用开发命令也全部指向 `/mnt/Data1T/mnote`
|
||||
|
||||
## 5. 当前结论
|
||||
|
||||
- 主仓已具备“只进入 `/mnt/Data1T/mnote` 就能找到前端、后端、Rust、OnlyOffice 相关入口”的文档与脚本口径。
|
||||
- 本轮新增目录与文档均位于主仓 `design/` 或既有 `rust/` 主线下,未把 `mnote-rust` 的历史页面壳或构建噪音带入主线。
|
||||
@@ -0,0 +1,399 @@
|
||||
# [recycle] Rust 内核总割接方案 v1
|
||||
|
||||
> 更新时间:2026-04-16
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-replacement-roadmap-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-missing-targets.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-phase-checklist.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/release-readiness-source-audit.md`
|
||||
|
||||
## 1. 目的
|
||||
|
||||
本文只回答一个问题:
|
||||
|
||||
> **什么时候可以宣布“Rust 已成为 mnote 唯一业务执行平面”,以及宣布前必须退役哪些旧 TS 执行面。**
|
||||
|
||||
这里的“退役”不等于“把所有 Next route 全删掉”。
|
||||
|
||||
真正要退役的是:
|
||||
|
||||
- TS route 内部承载的业务规则
|
||||
- TS 私有工具注册表里的第二套执行语义
|
||||
- 绕过 Rust command/query/tool 的直连 Convex 主链
|
||||
|
||||
允许长期保留的是:
|
||||
|
||||
- transport
|
||||
- auth
|
||||
- session
|
||||
- streaming
|
||||
- SSR / BFF
|
||||
- 第三方对象服务回调壳
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态定义
|
||||
|
||||
为了避免后续再出现“看起来迁了,实际上没迁”的模糊表述,本文统一使用下面四类状态。
|
||||
|
||||
### 2.1 `RUST_OWNER`
|
||||
|
||||
定义:
|
||||
|
||||
- 核心业务规则已经进入 Rust command/query/tool/runtime
|
||||
- TS route 只做参数校验、鉴权、HTTP 包装、Convex transport 或第三方请求转发
|
||||
|
||||
处理策略:
|
||||
|
||||
- 允许继续保留 route 壳
|
||||
- 不允许再往 route 内加业务规则
|
||||
|
||||
### 2.2 `TS_TRANSPORT_KEEP`
|
||||
|
||||
定义:
|
||||
|
||||
- 这条 route 本身不是业务真规则入口
|
||||
- 但因为浏览器会话、回调、上传下载、SSE、客户端桥等原因,需要长期保留在 Web 层
|
||||
|
||||
处理策略:
|
||||
|
||||
- 永久保留或长期保留
|
||||
- 只能承载 transport / session / proxy / callback
|
||||
|
||||
### 2.3 `TS_COMPAT_PENDING`
|
||||
|
||||
定义:
|
||||
|
||||
- 当前已经有部分 Rust 接缝
|
||||
- 但仍存在 TS 业务拼接、对象规则或直连 Convex 的旧执行逻辑
|
||||
|
||||
处理策略:
|
||||
|
||||
- 不能宣布总割接完成
|
||||
- 必须继续迁到 Rust 后,才能降级为 `RUST_OWNER` 或 `TS_TRANSPORT_KEEP`
|
||||
|
||||
### 2.4 `TS_LEGACY_DELETE`
|
||||
|
||||
定义:
|
||||
|
||||
- 该 route 或旧逻辑只服务于历史兼容、诊断、临时过渡或旧 UI
|
||||
- 一旦对应能力完成 Rust cutover 并切完调用方,就应删除
|
||||
|
||||
处理策略:
|
||||
|
||||
- 先停写
|
||||
- 再切调用
|
||||
- 最后物理删除
|
||||
|
||||
---
|
||||
|
||||
## 3. 当前总盘点
|
||||
|
||||
## 3.1 页面系统
|
||||
|
||||
### 已进入 `RUST_OWNER`
|
||||
|
||||
- `wolai-frontend/src/app/api/documents/meta/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/content/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/title/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/stats/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/options/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/save/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/create/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/move/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/delete/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/restore/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/duplicate/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/copy-tree/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/create-child/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/empty-trash/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/purge/route.ts`
|
||||
- `wolai-frontend/src/app/api/documents/template/route.ts`
|
||||
|
||||
判定依据:
|
||||
|
||||
- 已统一走 `buildDocument(Command|Query)Envelope`
|
||||
- 已切到共享 page/metadata/save adapter 或 `resolveRustBridge*`
|
||||
- route 只剩 transport、鉴权、参数整理与 HTTP 返回
|
||||
- `create-child` 已改为复用 `documents.create`
|
||||
- `template`、`empty-trash`、`purge` 已补齐 Rust runtime/transport 映射,不再由 `page-command-adapter.ts` 直接调用 Convex mutation
|
||||
|
||||
### 仍是 `TS_COMPAT_PENDING`
|
||||
|
||||
- `wolai-frontend/src/app/api/documents/embed/route.ts`
|
||||
|
||||
原因:
|
||||
|
||||
- `embed` 已不再直接调用 `api.documents.updateContent`,最终写入已改走 `documents.save`。
|
||||
- 但目标页面插入点计算、`pageReference` block 组装仍在 TS 侧完成,尚未进入独立 Rust command 面。
|
||||
- 因此它已经摆脱“直连 Convex mutation”的假完成状态,但还不能宣布为完全 `RUST_OWNER`。
|
||||
|
||||
处理结论:
|
||||
|
||||
- 页面旧面中,`create-child`、`template`、`empty-trash`、`purge` 已转为统一 Rust transport。
|
||||
- `embed` 仍是 Phase 8 前需要继续清理的剩余页面旧面。
|
||||
- 当前仍不可直接物理删除这些 route 文件,必须先切完调用方并确认不再承载 TS 内容编排。
|
||||
|
||||
---
|
||||
|
||||
## 3.2 块系统
|
||||
|
||||
### 已进入 `RUST_OWNER`
|
||||
|
||||
- `wolai-frontend/src/app/api/blocks/get/route.ts`
|
||||
- `wolai-frontend/src/app/api/blocks/patch/route.ts`
|
||||
- `wolai-frontend/src/app/api/blocks/move/route.ts`
|
||||
- `wolai-frontend/src/app/api/blocks/embed/route.ts`
|
||||
|
||||
判定依据:
|
||||
|
||||
- 现网 route 实际统一走 `wolai-frontend/src/lib/blocks/block-command-adapter.ts`
|
||||
- `patch/move/embed` 已通过 `documents.save` 主链落盘,不再依赖 route 内直连 Convex mutation
|
||||
- route 仅保留 transport、参数校验与 HTTP 返回
|
||||
|
||||
### 仍需冻结的兼容 helper
|
||||
|
||||
- `wolai-frontend/src/lib/documents/block-command-adapter.ts`
|
||||
|
||||
说明:
|
||||
|
||||
- 该文件当前不再是 `/api/blocks/*` 的主调用链。
|
||||
- 它仍保留旧桥接 helper 语义,因此需要明确按兼容层冻结,不能再被当成“现网主执行面”继续扩展。
|
||||
|
||||
### 可删的旧逻辑
|
||||
|
||||
- 旧 `loadBlocks/saveBlocks` 私有执行路径
|
||||
- 任何绕过共享 block adapter 的 AI 文档写入旧实现
|
||||
|
||||
处理结论:
|
||||
|
||||
- 块系统主链已经满足“route 保留、旧业务逻辑退役”的前提
|
||||
- 后续只允许在 Rust block ops 上继续扩展
|
||||
|
||||
---
|
||||
|
||||
## 3.3 查询聚合与观测
|
||||
|
||||
### 已进入 `RUST_OWNER`
|
||||
|
||||
- `wolai-frontend/src/app/api/sidebar/route.ts`
|
||||
- `wolai-frontend/src/app/api/search/documents/route.ts`
|
||||
- `wolai-frontend/src/app/api/bridge/request/route.ts`
|
||||
- `wolai-frontend/src/app/api/bridge/trace/route.ts`
|
||||
|
||||
### 仍是 `TS_TRANSPORT_KEEP`
|
||||
|
||||
- `wolai-frontend/src/app/api/search/recent/route.ts`
|
||||
|
||||
说明:
|
||||
|
||||
- `search/recent` 当前只承担“打开页面后写最近访问记录”的 side-effect,不再承担搜索召回
|
||||
- 它可以长期保留在 Web 层,但必须明确不是搜索业务真入口
|
||||
|
||||
### 当前仍缺
|
||||
|
||||
- workspace 级统一观测总览
|
||||
- 分页、按对象过滤、按状态过滤
|
||||
- 完整失败态和冲突态的全链路落账
|
||||
|
||||
---
|
||||
|
||||
## 3.4 AI 与工具面
|
||||
|
||||
### 已进入 `RUST_OWNER`
|
||||
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `doc_get`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `doc_find`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `doc_insert_blocks`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `doc_replace_range`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `docs_search`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `docs_read`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `search_web`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `image_read`
|
||||
- `wolai-frontend/src/app/api/ai-agent/run/route.ts` 中的 `slash_run`
|
||||
|
||||
说明:
|
||||
|
||||
- Convex 主链下,`ai-agent/run` 已直接通过 `executeRustBridgeTool(...)` 执行 `docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run`。
|
||||
- `docsServerTools` 当前只保留非 Convex / fallback 模式,不再承担 Convex 主链真执行。
|
||||
- `search_web`、`image_read`、`slash_run` 已切到 Rust Tool runtime,`ai-agent/run` 不再保留 TS 真执行兜底。
|
||||
|
||||
### 仍是 `TS_TRANSPORT_KEEP`
|
||||
|
||||
- `wolai-frontend/src/app/api/ai-agent/client-tool-result/route.ts`
|
||||
- `wolai-frontend/src/lib/ai-agent/tools/builtins/onlyoffice/onlyofficeServerTools.ts` 中的 `asset_extract_outline`
|
||||
- `wolai-frontend/src/lib/ai-agent/tools/builtins/onlyoffice/onlyofficeServerTools.ts` 中的 `asset_to_mindmap`
|
||||
- `wolai-frontend/src/lib/ai-agent/tools/builtins/onlyoffice/onlyofficeServerTools.ts` 中的 `oo_*`
|
||||
- `wolai-frontend/src/lib/ai-agent/tools/builtins/rag/**`
|
||||
|
||||
说明:
|
||||
|
||||
- `client-tool-result` 只负责浏览器内客户端工具回传,不承担业务决策。
|
||||
- `asset_extract_outline` 仍依赖附件下载与 MinerU 解析,因此长期保留 TS transport / 外部服务编排。
|
||||
- `asset_to_mindmap` 当前属于“TS 提纲提取 + Rust 导图写入”的明确编排边界:附件解析仍在 TS/MinerU,但导图应用已改走 Rust `mindmap_apply_ops`。
|
||||
- `oo_*` 继续保持客户端插件边界,不再尝试下沉为第二套服务端真执行入口。
|
||||
|
||||
### 仍是 `TS_COMPAT_PENDING`
|
||||
|
||||
- `wolai-frontend/src/app/api/mindmap-ai/agent/route.ts`
|
||||
- `wolai-frontend/src/app/api/mindmap-ai/assets/route.ts`
|
||||
- `wolai-frontend/src/app/api/mindmap-ai/expand-node/route.ts`
|
||||
- `wolai-frontend/src/app/api/mindmap-ai/outline-to-mindmap/route.ts`
|
||||
|
||||
处理结论:
|
||||
|
||||
- AI builtins 主链已经完成从 `TS_COMPAT_PENDING` 到 `RUST_OWNER` / `TS_TRANSPORT_KEEP` 的最终归类。
|
||||
- `mindmap-ai/**` 若继续保留,必须明确只是上层产品编排,不能成为对象规则真入口。
|
||||
- AI 工具矩阵与第一批旧面删除清单分别见:
|
||||
- `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/ai-tool-cutover-matrix.md`
|
||||
- `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md`
|
||||
|
||||
---
|
||||
|
||||
## 3.5 对象域
|
||||
|
||||
### Mindmap:已进入 `RUST_OWNER`
|
||||
|
||||
- `wolai-frontend/src/app/api/mindmap/[docId]/route.ts`
|
||||
- `wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/route.ts`
|
||||
|
||||
说明:
|
||||
|
||||
- `GET/POST` 之前已在 Rust query/command 主链上。
|
||||
- 2026-04-15 起,`DELETE` 与 `PATCH(action=restore|purge)` 也已补齐 Rust runtime/transport 映射,不再由 route 直接调用 Convex mutation。
|
||||
|
||||
### Mindmap:仍是 `TS_COMPAT_PENDING`
|
||||
|
||||
- `wolai-frontend/src/app/api/mindmap-ai/**`
|
||||
|
||||
### Mindmap:已进入 `RUST_OWNER` 的补充兼容入口
|
||||
|
||||
- `wolai-frontend/src/app/api/mindmap-trash/empty/route.ts`
|
||||
|
||||
说明:
|
||||
|
||||
- `mindmap-trash/empty` 现已切到 `mindmaps.emptyTrashByWorkspace` Rust runtime/transport。
|
||||
- 该 route 仍保留为 Web transport 壳,但不再直接持有 TS 真执行。
|
||||
|
||||
### OnlyOffice:已进入 `TS_TRANSPORT_KEEP`
|
||||
|
||||
- `wolai-frontend/src/app/api/onlyoffice/sign/route.ts`
|
||||
- `wolai-frontend/src/app/api/onlyoffice/proxy/route.ts`
|
||||
- `wolai-frontend/src/app/api/onlyoffice/callback/route.ts`
|
||||
- `wolai-frontend/src/app/api/onlyoffice/forcesave/route.ts`
|
||||
|
||||
说明:
|
||||
|
||||
- 这四条路由因为 JWT、proxy、下载上传、第三方回调等原因会长期保留
|
||||
- 但对象规则、session 边界、签名、回写准备、forcesave 计划已进入 Rust adapter
|
||||
|
||||
处理结论:
|
||||
|
||||
- OnlyOffice 当前不是“可删除 route”,而是“保留 route 壳、禁止再长业务规则”
|
||||
|
||||
---
|
||||
|
||||
## 4. Phase 8 Cutover Gate
|
||||
|
||||
只有下面四组 gate 同时满足,才能宣布“Rust 成为唯一业务执行平面”。
|
||||
|
||||
### Gate A:页面、块、查询主链全部 Rust 持有
|
||||
|
||||
要求:
|
||||
|
||||
- `documents.*` 主链不再存在 TS 业务路由
|
||||
- `blocks.*` 主链不再存在第二套执行逻辑
|
||||
- `search.documents`、`sidebar.dataset.list`、`bridge request/trace/command` 全部走 Rust query/runtime
|
||||
|
||||
### Gate B:对象域只保留 transport 壳
|
||||
|
||||
要求:
|
||||
|
||||
- Mindmap 主读写统一进入 Rust adapter
|
||||
- OnlyOffice 只保留签名、代理、回调、forcesave 等 transport 壳
|
||||
- 任何对象域规则都不再从 route 直连 Convex mutation 发展
|
||||
|
||||
### Gate C:AI 与 CLI 共用同一工具面
|
||||
|
||||
要求:
|
||||
|
||||
- `ai-agent/run` 不再为核心工具保留 `builtins/**` 私有真入口
|
||||
- CLI 与 AI 调用同一组 Rust `Tool`
|
||||
- `event_replay`、`index_rebuild`、`bridge_*_get` 这组观测/恢复命令对 CLI、AI、Web 等价可用
|
||||
- `docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run` 必须保持 `RUST_OWNER`
|
||||
|
||||
### Gate D:旧 TS 兼容面完成物理退役或明确降级
|
||||
|
||||
要求:
|
||||
|
||||
- `create-child`、`embed`、`empty-trash`、`purge`、`template`、`mindmap-trash/empty` 等旧接口要么迁入 Rust,要么标记为废弃并从 UI 脱钩
|
||||
- `mindmap-ai/**` 若继续保留,必须明确只是上层产品编排,不能成为对象规则真入口
|
||||
- 旧 `docTools` / `mindmapTools` / 页面私有写入胶水不再允许继续扩展
|
||||
|
||||
---
|
||||
|
||||
## 5. 允许删除与禁止删除
|
||||
|
||||
## 5.1 现在就禁止继续扩展的旧面
|
||||
|
||||
- `documents/create-child`
|
||||
- `documents/embed`
|
||||
- `documents/empty-trash`
|
||||
- `documents/purge`
|
||||
- `documents/template`
|
||||
- `mindmap-trash/empty`
|
||||
- `mindmap-ai/**` 私有写入逻辑
|
||||
- `ai-agent` 中非 Rust 的核心编辑工具真入口
|
||||
|
||||
规则:
|
||||
|
||||
- 这些路径可以暂时存在
|
||||
- 但不允许再加新业务逻辑
|
||||
- 第一批 `TS_LEGACY_DELETE` 冻结清单见 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md`
|
||||
|
||||
## 5.2 完成 cutover 后允许删除的旧面
|
||||
|
||||
- 上述旧接口本身
|
||||
- 被 Rust adapter 替代后的旧 `builtins/**` 服务端工具实现
|
||||
- 任何只为过渡期保留的直接 Convex 业务拼接 helper
|
||||
|
||||
当前已冻结的第一批删除对象:
|
||||
|
||||
- `documents/create-child`
|
||||
- `documents/embed`
|
||||
- `documents/empty-trash`
|
||||
- `documents/purge`
|
||||
- `documents/template`
|
||||
- `mindmap-trash/empty`
|
||||
- `builtins/**`
|
||||
|
||||
## 5.3 必须长期保留的壳
|
||||
|
||||
- `/api/onlyoffice/sign`
|
||||
- `/api/onlyoffice/proxy`
|
||||
- `/api/onlyoffice/callback`
|
||||
- `/api/onlyoffice/forcesave`
|
||||
- `/api/ai-agent/client-tool-result`
|
||||
- 其他承担 auth/session/streaming/proxy/callback 的 Web route
|
||||
|
||||
这些接口可以保留,但只能承担 Web transport 责任。
|
||||
|
||||
---
|
||||
|
||||
## 6. 最终宣布口径
|
||||
|
||||
只有当本文第 4 节四组 gate 在主链范围内同时满足时,才允许对外使用下面这句话:
|
||||
|
||||
> **Rust 已成为 mnote 的唯一业务执行平面;Web route 只保留 transport、auth、session、streaming、proxy、callback 与少量明确冻结的产品编排壳。**
|
||||
|
||||
截至 2026-04-16:
|
||||
|
||||
- `docs_search`、`docs_read`、`search_web`、`image_read`、`slash_run` 已满足 Gate C 的主链要求。
|
||||
- `bridge-log/runtime` 已补齐统一失败态、冲突态与补偿态的状态语义,页面主写链与 AI/Mindmap 写链已接入统一失败落账。
|
||||
- `mnote-cli` 已通过仓库内真实执行 smoke,CLI 与 AI 现在可以共用同一组 Rust Tool / runtime。
|
||||
- `TS_TRANSPORT_KEEP`、`TS_COMPAT_PENDING`、`TS_LEGACY_DELETE` 三类边界已经完成最终冻结,可作为后续发布与退役口径。
|
||||
|
||||
现在可以统一表述为:
|
||||
|
||||
> **Rust 已成为 mnote 的主业务执行平面;仍保留的 TS 代码只承担 transport、外部服务编排、客户端桥与冻结兼容壳责任。**
|
||||
@@ -0,0 +1,113 @@
|
||||
# [recycle] Rust 内核最终收尾详细清单
|
||||
|
||||
> 更新时间:2026-04-16
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/release-readiness-source-audit.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/ai-tool-cutover-matrix.md`
|
||||
|
||||
## 1. 当前结论
|
||||
|
||||
截至 2026-04-16,上一轮最终收尾里剩下的 CLI、AI runtime 与文档口径尾项已经闭合。
|
||||
|
||||
现在这份清单不再是“还缺什么”,而是给出最终关闭结果:
|
||||
|
||||
- 第一批 `TS_LEGACY_DELETE` 已经被压缩为“纯 transport 壳 / 冻结 helper / 明确删除清单”,不再允许继续长出第二套业务语义。
|
||||
- 页面、块、Mindmap、OnlyOffice 与 AI 工具主链已经完成最终收口,不再存在主链级别的“Rust 包装 + TS 真执行”假完成状态。
|
||||
- `mnote-cli` 已进入最小真实执行态,并且有可复跑的仓库内 smoke。
|
||||
- AI 工具矩阵里的 builtins 主链已经完成最终归类,不再保留模糊的 builtins 级 `TS_COMPAT_PENDING`。
|
||||
- 发布前运行态复核证据已经补齐,可以给出统一最终口径。
|
||||
|
||||
---
|
||||
|
||||
## 2. 尾项关闭结果
|
||||
|
||||
### 2.1 第一批 `TS_LEGACY_DELETE`
|
||||
|
||||
当前状态:已关闭为“冻结清单 + 纯壳边界”。
|
||||
|
||||
结果:
|
||||
|
||||
- `documents/create-child`、`documents/empty-trash`、`documents/purge`、`documents/template` 已进入统一 Rust transport / adapter 主链。
|
||||
- `mindmap-trash/empty` 已进入 Rust runtime / transport 主链。
|
||||
- `builtins/**` 中已被 Rust runtime 接管的服务端真入口,不再允许继续作为主执行面扩展。
|
||||
- `documents/embed` 与 `mindmap-ai/**` 这类仍保留的上层编排路径,必须按冻结边界维护,不能反向长出新的核心业务规则。
|
||||
|
||||
验收结论:第一批旧面已经不再阻塞“Rust 成为主业务执行平面”的宣布口径。
|
||||
|
||||
### 2.2 双路径执行清理
|
||||
|
||||
当前状态:已关闭。
|
||||
|
||||
结果:
|
||||
|
||||
- 页面主写链、块主写链、Mindmap 删除/恢复/清空回收站、OnlyOffice callback/forcesave 均已切到 Rust command/query/tool/runtime 主链。
|
||||
- 旧 TS 侧保留的仅是 transport、外部服务编排或历史兼容 helper,不再是现网主真执行入口。
|
||||
- `src/lib/documents/block-command-adapter.ts` 明确被冻结为遗留兼容 helper;现网 `/api/blocks/*` 统一走 `src/lib/blocks/block-command-adapter.ts`。
|
||||
|
||||
### 2.3 CLI 最小真实执行态
|
||||
|
||||
当前状态:已关闭。
|
||||
|
||||
结果:
|
||||
|
||||
- `mnote-cli` 新增并稳定支持 `--execute` 真实执行模式。
|
||||
- 已修复 `block patch --execute` 的块树回写形状问题,`block move --execute` 不再因为内容快照损坏而失败。
|
||||
- 仓库内最小 smoke 已扩展到:
|
||||
- `sidebar dataset`
|
||||
- `page get/create/title/save/move/delete/restore`
|
||||
- `block insert/patch/move/embed`
|
||||
- `search documents`
|
||||
- `tool run docs_search/docs_read`
|
||||
- `mindmap put/get/op`
|
||||
- 运行命令:`bash /mnt/Data1T/mnote/rust/scripts/task049-cli-smoke.sh`
|
||||
- 验收产物会落盘到 `/tmp/task049-cli-smoke-*`,便于失败后回查逐步 JSON 输出。
|
||||
|
||||
### 2.4 AI 工具矩阵收口
|
||||
|
||||
当前状态:已关闭。
|
||||
|
||||
结果:
|
||||
|
||||
- `docs_search`、`docs_read` 已进入 Rust tool runtime;Convex 主链下 `ai-agent/run` 直接通过 `executeRustBridgeTool(...)` 执行,`docsServerTools` 仅保留 fallback。
|
||||
- `search_web`、`image_read`、`slash_run` 持续保持 `RUST_OWNER`。
|
||||
- `asset_extract_outline`、`asset_to_mindmap`、`oo_*` 已明确归类为 `TS_TRANSPORT_KEEP`,不再保留 builtins 级 `TS_COMPAT_PENDING`。
|
||||
- `asset_to_mindmap` 的真正导图写入已收口到 Rust `mindmap_apply_ops`;TS 侧仅保留外部解析与编排壳。
|
||||
|
||||
### 2.5 发布前运行态复核
|
||||
|
||||
当前状态:已关闭。
|
||||
|
||||
截至 2026-04-16,已经具备以下运行态证据:
|
||||
|
||||
- 浏览器回归:`scripts/task019-document-ui-regression.js`
|
||||
- 浏览器回归:`scripts/task021-mindmap-ui-regression.js`
|
||||
- 浏览器回归:`scripts/task022-onlyoffice-ui-regression.js`
|
||||
- AI runtime 证据:`pnpm exec vitest run src/lib/ai-agent/runtime/runAgent.test.ts`
|
||||
- CLI 主链证据:`bash /mnt/Data1T/mnote/rust/scripts/task049-cli-smoke.sh`
|
||||
- Rust 执行层证据:`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p mnote-cli -p bridge-runtime`
|
||||
|
||||
补充说明:定向 `eslint` 当前无 error,仅剩仓库既有 warnings,不构成这轮收尾阻塞项。
|
||||
|
||||
---
|
||||
|
||||
## 3. 最终完成标准核对
|
||||
|
||||
现在已经同时满足下面几条:
|
||||
|
||||
- 第一批 `TS_LEGACY_DELETE` 已物理删除或明确冻结为不可扩展壳。
|
||||
- 仓库里不再存在主链级别的“Rust 包装 + TS 真执行”双路径假完成状态。
|
||||
- `mnote-cli` 已覆盖一批关键主链的真实执行,并具备仓库内可复跑 smoke。
|
||||
- AI 工具矩阵中的 builtins 主链已不再保留模糊的 `TS_COMPAT_PENDING`。
|
||||
- 发布前运行态复核已经重新通过。
|
||||
- 文档口径与代码现状可以统一到同一个最终结论。
|
||||
|
||||
---
|
||||
|
||||
## 4. 一句话结论
|
||||
|
||||
现在可以把最后一阶段的结论收口为:
|
||||
|
||||
> **Rust 已成为 mnote 的主业务执行平面;Web / TS 侧仅保留 transport、外部服务编排、客户端桥与明确冻结的兼容壳。**
|
||||
@@ -0,0 +1,73 @@
|
||||
# [recycle] Rust Kernel Legacy Delete List
|
||||
|
||||
> 目标:给 Phase 8 第一批 `TS_LEGACY_DELETE` 提供固定清单,先停写并切调用方,再删除已被 Rust 替代的 TS 真入口。
|
||||
|
||||
## 1. 第一批删除对象
|
||||
|
||||
- `documents/create-child`
|
||||
- `documents/embed`
|
||||
- `documents/empty-trash`
|
||||
- `documents/purge`
|
||||
- `documents/template`
|
||||
- `mindmap-trash/empty`
|
||||
- `builtins/**`
|
||||
|
||||
## 2. 删除前提
|
||||
|
||||
- 页面旧面必须已经切到统一 page adapter 或 lifecycle adapter,route 仅剩 transport。
|
||||
- AI 核心工具必须已经切到 Rust Tool runtime 或 `ai-agent/run` 统一入口,不能再由 `builtins/**` 私下持有真执行面。
|
||||
- 统一 bridge-log 必须能记录失败态、冲突态与补偿态,避免删除旧面后失去回查能力。
|
||||
|
||||
## 3. 删除策略
|
||||
|
||||
### 3.1 页面旧面
|
||||
|
||||
- `documents/create-child`
|
||||
- `documents/embed`
|
||||
- `documents/empty-trash`
|
||||
- `documents/purge`
|
||||
- `documents/template`
|
||||
|
||||
策略:
|
||||
|
||||
- 先冻结 route 内业务逻辑,确保所有调用方都走 adapter。
|
||||
- 保留 Web route 的 auth、参数校验和 HTTP transport。
|
||||
- 先继续清理 `page-command-adapter.ts` / `page-lifecycle-command-adapter.ts` 中残留的 TS 真执行。
|
||||
- 在前端调用方仍直接依赖这些 route,且 adapter 仍承载真实写入前,不得直接物理删除 route 文件。
|
||||
- 当 release audit 与 cutover gate 均确认无回退需求后,再物理删除历史 helper/分支。
|
||||
|
||||
### 3.2 Mindmap 旧面
|
||||
|
||||
- `mindmap-trash/empty`
|
||||
|
||||
策略:
|
||||
|
||||
- `mindmap-trash/empty` 现已切到 `mindmaps.emptyTrashByWorkspace` Rust runtime/transport。
|
||||
- 该 route 仍是兼容入口,但只保留 Web transport 壳,不再直接持有 TS 真执行。
|
||||
- 仍需确认 `task-042` 的失败/冲突/补偿落账和最终运行态回归稳定,再删除纯兼容分支。
|
||||
|
||||
### 3.3 AI 工具旧面
|
||||
|
||||
- `builtins/**`
|
||||
|
||||
策略:
|
||||
|
||||
- `search_web`、`image_read`、`slash_run` 这类已切到 Rust runtime 的工具,删除其服务端真入口,只保留必要 transport helper。
|
||||
- `client-tool-result` 与 `oo_*` 属于 `TS_TRANSPORT_KEEP`,不在本批物理删除范围。
|
||||
- `asset_extract_outline`、`asset_to_mindmap` 尚未完全 Rust 化,暂不从 `builtins/**` 整体删除,但必须禁止继续扩展新的私有真入口。
|
||||
|
||||
## 4. 当前结论
|
||||
|
||||
- 第一批 `TS_LEGACY_DELETE` 已完成清单冻结。
|
||||
- `documents/create-child`、`documents/embed`、`documents/empty-trash`、`documents/purge`、`documents/template`、`mindmap-trash/empty`、`builtins/**` 已被明确纳入 Phase 8 的旧面退役范围。
|
||||
- 截至 2026-04-15,这批对象中还没有可直接物理删除的 route 文件;当前可安全推进的是:
|
||||
- 把 route 固定为纯 transport 壳。
|
||||
- 把 adapter 内残留的 TS 真执行继续收口。
|
||||
- 为每个旧面补齐调用方清单与“可删前置条件”。
|
||||
- 其中页面旧面已完成第一轮收口:
|
||||
- `create-child` 已复用 `documents.create`
|
||||
- `template`、`empty-trash`、`purge` 已补齐 Rust runtime/transport 映射
|
||||
- `embed` 已切到 `documents.save`,但插入位计算与 `pageReference` block 组装仍在 TS
|
||||
- 因此页面旧面的主要残留已缩到 `wolai-frontend/src/lib/documents/page-command-adapter.ts` 中的 `embed` 内容编排,以及 `wolai-frontend/src/lib/documents/page-lifecycle-command-adapter.ts` 的历史兼容面。
|
||||
- `mindmap-trash/empty` 已不再由 route 直接调用 `api.mindmaps.emptyTrashByWorkspace`,但在调用方与最终运行态回归全部通过前,仍不满足物理删除条件。
|
||||
- 后续删除动作必须以 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md` 和 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/release-readiness-source-audit.md` 的最终 gate 为准。
|
||||
@@ -0,0 +1,110 @@
|
||||
# [recycle] mnote 单仓维护边界约定
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 主仓:`/mnt/Data1T/mnote`
|
||||
>
|
||||
> 历史仓:`/mnt/Data1T/mnote-rust`
|
||||
|
||||
## 1. 主结论
|
||||
|
||||
- 只保留 `/mnt/Data1T/mnote` 作为启动、规划、保存、验证的唯一主仓。
|
||||
- `/mnt/Data1T/mnote-rust` 只作为历史资产来源,不再承担主执行入口。
|
||||
- 任何新设计、执行清单、架构说明都优先写入 `/mnt/Data1T/mnote/design/` 或 `/mnt/Data1T/mnote/rust/design/`。
|
||||
|
||||
## 2. 主仓执行入口
|
||||
|
||||
- 根目录脚本入口只认 `/mnt/Data1T/mnote/package.json` 与 `/mnt/Data1T/mnote/scripts/`。
|
||||
- 当前 `package.json` 仅通过 `node scripts/*.js` 暴露仓库级入口,没有任何脚本要求先进入 `mnote-rust`。
|
||||
- 如需调用 Rust,统一使用 `cargo --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml ...`,不从历史仓发起 Cargo 命令。
|
||||
- 当前 `scripts/desktop-hot.js` 已固定从主仓根目录解析 `.env.all`,并以 `wolai-frontend/`、`wolai-backend/` 作为唯一联调入口。
|
||||
|
||||
## 3. `mnote-rust` 历史资料分类
|
||||
|
||||
### 3.1 核心规范
|
||||
|
||||
这些内容可作为协议与设计参考,但主线副本以 `/mnt/Data1T/mnote/rust/` 为准:
|
||||
|
||||
- `design/blueprint/`
|
||||
- `design/core/`
|
||||
- `crates/core-domain/`
|
||||
- `crates/core-protocol/`
|
||||
- `crates/event-log/`
|
||||
- `crates/storage-convex-bridge/`
|
||||
- `crates/index-fts/`
|
||||
|
||||
### 3.2 历史阶段
|
||||
|
||||
这些内容保留为阶段记录,不作为当前实现依据:
|
||||
|
||||
- `design/phases/**`
|
||||
- `design/execution/**`
|
||||
- `design/UI/**`
|
||||
- `design/mindmap/**`
|
||||
|
||||
### 3.3 参考实现
|
||||
|
||||
这些内容可用于盘点边界、提取协议或核对交互,但不能整块复制覆盖主仓:
|
||||
|
||||
- `app/**`
|
||||
- `components/**`
|
||||
- `lib/**`
|
||||
- `convex/**`
|
||||
- `infra/onlyoffice/**`
|
||||
- `crates/mnote-cli/`
|
||||
- `crates/adapter-onlyoffice/`
|
||||
- `crates/adapter-mindmap/`
|
||||
- `crates/adapter-legacy-mnote/`
|
||||
|
||||
### 3.4 错误方向
|
||||
|
||||
以下内容明确不进入主仓主线:
|
||||
|
||||
- 对象页壳与试验页:`app/page.tsx`、`app/onlyoffice/page.tsx`、`app/documents/**`
|
||||
- 第二套导航壳:`components/sidebar/sidebar.tsx`
|
||||
- 诊断与构建产物:`.next/diagnostics/**`、`.next/**`、`.tmp/**`
|
||||
- 仅用于历史 smoke/夹具的目录:`.tmp/phase7-test-fixtures/**`
|
||||
|
||||
## 4. 主仓默认不动目录
|
||||
|
||||
除非当前任务明确要求接线或修复,否则默认不扩写以下目录:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/`
|
||||
- `/mnt/Data1T/mnote/wolai-backend/`
|
||||
- `/mnt/Data1T/mnote/infra/convex/`
|
||||
- `/mnt/Data1T/mnote/src/components/onlyoffice/`
|
||||
- `/mnt/Data1T/mnote/recycle/`
|
||||
|
||||
## 5. 最小维护约定
|
||||
|
||||
### 5.1 Workspace 责任面
|
||||
|
||||
- 入口文件:`/mnt/Data1T/mnote/rust/Cargo.toml`、`/mnt/Data1T/mnote/rust/Cargo.lock`
|
||||
- 维护范围:`/mnt/Data1T/mnote/rust/crates/*`
|
||||
- 要求:新增 crate、依赖调整、共享协议变更,必须先在主仓 workspace 内完成,不得回写到历史仓再反向复制。
|
||||
|
||||
### 5.2 Bridge 责任面
|
||||
|
||||
- 入口文件:`/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/bridge.ts`
|
||||
- 相关边界:
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/metadata-command-adapter.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/save-command-adapter.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/**`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/convex/bridgeLogs.ts`
|
||||
- 要求:新 command/query 先收口协议边界,再决定是否继续下沉到 Rust crate。
|
||||
|
||||
### 5.3 接入链责任面
|
||||
|
||||
- C1 页面元信息:`src/app/(app)/documents/[id]/page.tsx`、`src/components/editor/document-content.tsx`
|
||||
- C2 Sidebar 聚合:`src/components/sidebar/**`、`src/hooks/use-convex-sidebar-data.ts`、`src/lib/sidebar-data.ts`
|
||||
- C3 正文保存:`src/components/editor/blocknote-editor.tsx`、`src/app/api/documents/save/route.ts`
|
||||
- Phase D 边界:`src/components/editor/blocks/MindmapBlock.tsx`、`src/app/onlyoffice/**`、`src/app/api/onlyoffice/**`
|
||||
- 要求:优先改主仓现有链路,不复制历史仓页面壳替换现实现。
|
||||
|
||||
## 6. 禁止误复制清单
|
||||
|
||||
- 不把 `mnote-rust` 当成新的主执行仓。
|
||||
- 不复制第二套 Next 前端壳、对象页壳、diagnostics 页、smoke 页进入主线。
|
||||
- 不通过软链接、硬链接、跨仓路径偷接来伪装“已迁移”。
|
||||
- 不在主仓根目录散落多个 Rust 源码根。
|
||||
@@ -0,0 +1,629 @@
|
||||
# [recycle] AI 前端精简方案 v1
|
||||
|
||||
> 更新时间:2026-04-15
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-final-closure-checklist.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/ai-tool-cutover-matrix.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
|
||||
|
||||
## 1. 目标
|
||||
|
||||
这份方案只回答一个问题:
|
||||
|
||||
> **当前网页前端中,AI 相关部分应该如何精简,才能真正降低加载负担,并把前端 AI 收口为“轻桥接层”。**
|
||||
|
||||
目标方向已经明确:
|
||||
|
||||
> **前端 AI 面板不再承担工具注册、工具编排、能力路由和执行框架,只保留为 Hermes API Server + mnote Rust 业务能力的轻桥接 UI。**
|
||||
|
||||
这意味着后续 AI 前端不再是一个“小型平台”,而只是:
|
||||
|
||||
- 收集上下文
|
||||
- 发送用户输入
|
||||
- 展示流式结果
|
||||
- 承接极少数浏览器专属 client tool
|
||||
|
||||
## 1.1 现状校准:当前真正已经落地的后端 AI 边界
|
||||
|
||||
在继续谈“前端该怎么精简”之前,必须先对齐一个事实:
|
||||
|
||||
> **当前本机已经有可核验的 Hermes Agent 与其官方 API Server 方案;同时 mnote 自己也已经有 Rust protocol/runtime 边界。后续前端 AI 应该桥接这两层,而不是自己继续承担平台层。**
|
||||
|
||||
当前已确认的 Hermes 事实:
|
||||
|
||||
- 本机 Hermes 安装目录:`/home/lix/.hermes`
|
||||
- Hermes 本体仓:`/home/lix/.hermes/hermes-agent`
|
||||
- 当前网关进程已在运行:`hermes gateway run --replace`
|
||||
- 官方文档已提供 OpenAI 兼容 API Server:
|
||||
- 启用方式:`API_SERVER_ENABLED=true`
|
||||
- 默认监听:`http://127.0.0.1:8642`
|
||||
- 入口:`/v1/chat/completions`、`/v1/responses`、`/health`
|
||||
|
||||
但当前本机状态也要说明白:
|
||||
|
||||
- Hermes gateway 在跑
|
||||
- Hermes API Server 当前还没有启用
|
||||
- mnote 前端当前也还没有接通 Hermes API Server
|
||||
|
||||
因此,现阶段不是“是否存在 Hermes”的问题,而是:
|
||||
|
||||
- **Hermes 已存在,但还没有接入 mnote Web AI 主链**
|
||||
- **mnote Rust 业务能力已存在,但还没有作为 Hermes 的统一业务工具面完全暴露**
|
||||
|
||||
当前 mnote 已能明确核验到的 Rust 业务边界是:
|
||||
|
||||
- `rust/crates/core-protocol/src/tool.rs`
|
||||
已定义 `ToolSpec`、`ToolSetSpec`、`ToolRegistry`,并冻结了 `toolset.readonly`、`toolset.media_read`、`toolset.doc_read`、`toolset.doc_write`、`toolset.mindmap_read`、`toolset.mindmap_write`、`toolset.onlyoffice_service`、`toolset.slash_write` 等基础集合。
|
||||
- `rust/crates/bridge-runtime/src/lib.rs`
|
||||
已提供统一 `RuntimeInput::{Tool, Query, Command}` 入口,支持 `plan`、`result`、`explain-plan`、`validateOnly`、`dryRun` 等运行模式,并输出统一计划结构。
|
||||
- `rust/crates/mnote-cli/README.md`
|
||||
已冻结 `tool run` 的 JSON 契约,说明 CLI 化目标已经开始按稳定协议推进。
|
||||
- `wolai-frontend/src/lib/documents/rust-runtime.ts`
|
||||
当前前端已经可以通过 `executeRustBridgeTool()` 直接调用 Rust `bridge-runtime`,说明 Web 并不是从零开始接 Rust。
|
||||
|
||||
结合 `ai-tool-cutover-matrix.md` 与 `run/route.ts`,当前可以按下面口径理解能力归属:
|
||||
|
||||
- 已有明确 Rust owner 或 Rust 主入口的能力:
|
||||
`search_web`、`image_read`、`slash_run`、`doc_*`、`mindmap_*`、`onlyoffice_* service`
|
||||
- 仍暂时保留在 TS transport 或兼容层的能力:
|
||||
`docs_search`、`docs_read`、`rag_lightrag_query`、`asset_extract_outline`、`asset_to_mindmap`、`oo_*`
|
||||
|
||||
因此,这份方案后续提到的“后移”应理解成:
|
||||
|
||||
- 先把前端收口到 Hermes bridge
|
||||
- 再把 mnote 业务能力通过 Rust 边界继续收口,并作为 Hermes 可调用能力暴露
|
||||
- 最终形成“Hermes 负责 agent runtime,Rust 负责 mnote 业务真执行面,前端只负责 UI 与 client bridge”的结构
|
||||
|
||||
## 1.2 推荐的最终分工
|
||||
|
||||
基于当前仓库和 Hermes 官方能力,推荐的长期结构不是单中心,而是双层分工:
|
||||
|
||||
### A. Hermes 负责什么
|
||||
|
||||
- agent loop
|
||||
- 通用 tool runtime
|
||||
- 多轮会话状态
|
||||
- OpenAI 兼容 API Server
|
||||
- 流式输出与工具调用事件
|
||||
- 通用记忆、skills、MCP、delegate 等 agent 能力
|
||||
|
||||
### B. mnote Rust 负责什么
|
||||
|
||||
- 文档、块、导图、OnlyOffice 等产品业务真执行
|
||||
- 统一 command/query/tool protocol
|
||||
- 审计、trace、request/command/event 口径
|
||||
- CLI 化与稳定 JSON 契约
|
||||
|
||||
### C. mnote Web 前端负责什么
|
||||
|
||||
- 输入框、聊天记录、SSE 展示
|
||||
- document/mindmap/onlyoffice context 采集
|
||||
- 少量浏览器专属 client tool
|
||||
- 必要的鉴权、会话映射和 client-tool-result 回传
|
||||
|
||||
### D. mnote 与 Hermes 的推荐衔接方式
|
||||
|
||||
当前更合理的方向不是让前端直接承接 Hermes 的全部能力,而是:
|
||||
|
||||
- 前端 -> mnote Next route
|
||||
- mnote Next route -> Hermes API Server
|
||||
- Hermes 在需要 mnote 业务操作时,再调用 mnote 暴露给它的 Rust 能力面
|
||||
|
||||
这层“mnote 暴露给 Hermes 的能力面”后续可以落在:
|
||||
|
||||
- MCP server
|
||||
- Hermes plugin/tool adapter
|
||||
- 或 mnote 自己维护的一层最小业务 bridge
|
||||
|
||||
但无论具体接法选哪一种,原则都应一致:
|
||||
|
||||
> **Hermes 不应复制一套 mnote 业务真逻辑;mnote Rust 才是产品业务真执行面。**
|
||||
|
||||
## 1.3 Hermes API Server 调用 mnote Rust 的最小业务桥
|
||||
|
||||
这部分是 task-058 的关键边界:先把“谁调用谁、调用什么、返回什么”说清楚,再决定后续是否补更重的适配层。
|
||||
|
||||
### 最小结论
|
||||
|
||||
Hermes API Server 不应直接接触前端 `/api/ai-agent/run` 的整套 TS 编排逻辑,而应通过一个非常窄的 mnote Rust 业务桥来调用真实能力。
|
||||
|
||||
这个桥只做三件事:
|
||||
|
||||
1. 接收 Hermes 的标准化 tool 调用请求
|
||||
2. 转换成 mnote Rust 的 `RuntimeInput`
|
||||
3. 返回 Rust 的 `plan` 或 `result`
|
||||
|
||||
### 推荐的桥接层级
|
||||
|
||||
- Hermes API Server
|
||||
负责 agent loop、tool 调度、流式输出与会话状态。
|
||||
- mnote Rust bridge
|
||||
负责把 Hermes 的 tool 调用映射到 `core-protocol` / `bridge-runtime`。
|
||||
- mnote 业务执行面
|
||||
负责文档、块、导图、OnlyOffice 等产品能力的真实读写。
|
||||
|
||||
### 最小接口边界
|
||||
|
||||
建议把 Hermes 可调用的 mnote 能力,先收敛成下面三类:
|
||||
|
||||
- `query`
|
||||
只读查询,例如 `page get`、`docs_search`、`docs_read`
|
||||
- `command`
|
||||
写入命令,例如 `block insert`
|
||||
- `tool`
|
||||
复用 Rust tool registry 的能力,例如 `doc_insert_blocks`、`doc_replace_range`
|
||||
|
||||
其中最优先的两条业务能力是:
|
||||
|
||||
- `page get` -> Rust query:`documents.content.get`
|
||||
- `block insert` -> Rust write/tool:`doc_insert_blocks`
|
||||
|
||||
### 当前仓库里已经存在的可复用接缝
|
||||
|
||||
- `rust/crates/core-protocol/src/tool.rs`
|
||||
已经冻结了 `ToolSpec`、`ToolSetSpec`、`ToolRegistry`,并且 `docs_search`、`docs_read`、`doc_insert_blocks` 都已经在工具注册表中。
|
||||
- `rust/crates/bridge-runtime/src/lib.rs`
|
||||
已经提供 `execute_runtime_input()`、`execute_runtime_query()`、`execute_query()`、`execute_command()`、`execute_tool_plan()`、`execute_tool_result()` 这些统一入口。
|
||||
- `rust/crates/core-protocol/src/query.rs`
|
||||
已经有 `GetPageContent`、`SearchDocuments`、`GetBlock` 等查询载体。
|
||||
- `rust/crates/core-protocol/src/command.rs`
|
||||
已经有 `CommandEnvelope` 和 `CommandResult`,说明命令执行结果口径是存在的。
|
||||
- `wolai-frontend/src/lib/documents/rust-runtime.ts`
|
||||
当前前端已经能把 JSON 输入交给 Rust bridge 进程,说明“进程级 Rust bridge”这条路是可复用的。
|
||||
|
||||
### 最小业务桥的推荐形态
|
||||
|
||||
建议 Hermes 侧只认识一个很窄的桥协议,避免再次长成一套前端平台层:
|
||||
|
||||
```text
|
||||
Hermes tool call
|
||||
-> mnote rust bridge input
|
||||
-> Rust plan/result
|
||||
-> Hermes tool result
|
||||
```
|
||||
|
||||
其中输入字段建议至少包含:
|
||||
|
||||
- `toolName`
|
||||
- `invocationKind`
|
||||
- `executionMode`
|
||||
- `args`
|
||||
- `workspaceId`
|
||||
- `target`
|
||||
- `actor`
|
||||
- `source`
|
||||
|
||||
输出字段建议至少包含:
|
||||
|
||||
- `ok`
|
||||
- `kind`
|
||||
- `plan` 或 `result`
|
||||
- `error`(失败时)
|
||||
|
||||
### 最小桥的落地原则
|
||||
|
||||
- 先支持只读桥接,再补写入桥接
|
||||
- 先接 `page get`,再接 `block insert`
|
||||
- 先复用现有 `bridge-runtime`,不要先重写新执行器
|
||||
- 不要让 Hermes 直接依赖前端 `run/route.ts` 的 builtin registry
|
||||
- 不要把能力定义重新散落到多个前端面板里
|
||||
|
||||
### 对当前前端的影响
|
||||
|
||||
前端后续只应保留:
|
||||
|
||||
- 场景上下文采集
|
||||
- SSE/UI 展示
|
||||
- 少量浏览器专属 client tool
|
||||
|
||||
前端不应继续承担:
|
||||
|
||||
- tool registry
|
||||
- tool policy
|
||||
- builtin 装配
|
||||
- provider 编排
|
||||
- Rust 能力路由
|
||||
|
||||
这意味着后续如果要继续减重,应该优先把 `Hermes API Server -> mnote Rust bridge` 这条线做清楚,而不是继续在 Web 里扩充 AI 平台逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前问题
|
||||
|
||||
## 2.1 当前不是一个 AI 面板,而是多套前端 AI 系统
|
||||
|
||||
当前仓库至少存在下面几套 AI UI:
|
||||
|
||||
- 全局 AI:`src/components/ai-agent/AiAgentPanel.tsx`
|
||||
- 全局 Host:`src/components/ai-agent/GlobalAiAgentHost.tsx`
|
||||
- 页面 AI:`src/components/editor/DocumentAiAgentPanel.tsx`
|
||||
- Mindmap AI:`src/components/editor/blocks/MindmapAiAgentPanel.tsx`
|
||||
- OnlyOffice AI:`src/components/onlyoffice/OnlyOfficeAiAgentPanel.tsx`
|
||||
|
||||
这些面板不只是视觉上重复,而是每一套都各自持有一大批前端状态和交互逻辑,例如:
|
||||
|
||||
- 对话 session/history
|
||||
- SSE 解析
|
||||
- tool logs
|
||||
- provider/model 选择
|
||||
- localStorage 持久化
|
||||
- 工具白名单/手动选择
|
||||
- codex mode
|
||||
- 中止/恢复交互
|
||||
|
||||
这会持续拉高:
|
||||
|
||||
- 前端代码体积
|
||||
- 客户端状态复杂度
|
||||
- 维护成本
|
||||
- 页面加载后的水合成本
|
||||
|
||||
## 2.2 `/api/ai-agent/run` 当前仍是前端侧 AI 编排中心
|
||||
|
||||
当前 `src/app/api/ai-agent/run/route.ts` 仍承担了大量本应属于统一后端 AI 服务的职责:
|
||||
|
||||
- scope -> toolset 映射
|
||||
- builtin registry 构建
|
||||
- allowed tools 解析
|
||||
- 各类 server tools 装配
|
||||
- codex 与本地/在线 provider 多分支逻辑
|
||||
- client tool bridge 协调
|
||||
- 一部分 Rust tool 执行接线
|
||||
- 一部分 TS builtin fallback
|
||||
|
||||
这意味着:
|
||||
|
||||
- 前端 Next route 仍然是 AI 平台层
|
||||
- AI 执行面没有完全后移
|
||||
- AI 相关复杂度还在 Web 进程里增长
|
||||
|
||||
## 2.3 builtin tool registry 仍保留为前端框架资产
|
||||
|
||||
当前仍保留:
|
||||
|
||||
- `src/lib/ai-agent/tools/registry.ts`
|
||||
- `src/lib/ai-agent/tools/builtins/registryBuiltins.ts`
|
||||
- `src/lib/ai-agent/runtime/runAgent.ts`
|
||||
- 多个 `create*ServerTools`
|
||||
|
||||
这说明:
|
||||
|
||||
- 前端不只是“调 AI”
|
||||
- 前端还在“定义 AI 能干什么、怎么调、怎么路由”
|
||||
|
||||
这与“前端只桥接 Hermes + mnote Rust”的方向相冲突。
|
||||
|
||||
## 2.4 当前 AI 能力边界仍分散在多个场景面板里
|
||||
|
||||
例如:
|
||||
|
||||
- 页面 AI 直接持有 `doc_*` 工具集合与文档快照
|
||||
- Mindmap AI 直接持有 mindmap tool 集与附件选择
|
||||
- OnlyOffice AI 直接持有 `oo_*` client tool 协议
|
||||
- 全局 AI 又有自己的 toolset chips 和 capability 展示
|
||||
|
||||
这意味着“场景上下文”与“工具编排”没有分离。
|
||||
|
||||
更合理的结构应该是:
|
||||
|
||||
- 场景只提供 context
|
||||
- agent 编排由 Hermes 决定
|
||||
- mnote 业务执行由 Rust 决定
|
||||
- 前端只负责 UI 与极少数 client capability
|
||||
|
||||
---
|
||||
|
||||
## 3. 精简总原则
|
||||
|
||||
## 3.1 前端 AI 只保留三类职责
|
||||
|
||||
后续前端 AI 只应保留:
|
||||
|
||||
### A. 轻 UI
|
||||
|
||||
- 输入框
|
||||
- 聊天记录
|
||||
- 流式输出
|
||||
- 打断/继续
|
||||
- 极少量面板开关
|
||||
|
||||
### B. 场景上下文采集
|
||||
|
||||
- 当前 documentId
|
||||
- 当前 mindmapId
|
||||
- 当前 onlyoffice 文件信息
|
||||
- 当前 selection/block snapshot
|
||||
|
||||
### C. 浏览器专属 client tool
|
||||
|
||||
例如:
|
||||
|
||||
- OnlyOffice 插件回调
|
||||
- 浏览器本地文件/剪贴板
|
||||
- 未来确实只能在浏览器执行的少数能力
|
||||
|
||||
除此之外,前端不应继续承担:
|
||||
|
||||
- tool registry
|
||||
- tool policy
|
||||
- builtin 分类
|
||||
- tool routing
|
||||
- AI orchestration
|
||||
- 多 provider 执行框架
|
||||
|
||||
## 3.2 AI 面板本身不再按功能域复制实现
|
||||
|
||||
最终应从“多个重面板”收口到:
|
||||
|
||||
- 一个通用 `AiBridgePanel`
|
||||
- 多个轻量 context adapter
|
||||
|
||||
即:
|
||||
|
||||
- `GlobalAiEntry`
|
||||
- `DocumentAiEntry`
|
||||
- `MindmapAiEntry`
|
||||
- `OnlyOfficeAiEntry`
|
||||
|
||||
这些 entry 只负责传不同 context,不再复制整套面板逻辑。
|
||||
|
||||
## 3.3 前端不再维护 AI 工具产品说明体系
|
||||
|
||||
像下面这些内容,不应再长期保留在前端:
|
||||
|
||||
- tool labels
|
||||
- tool chips
|
||||
- capability 展示矩阵
|
||||
- per-scope tool lists
|
||||
|
||||
这些都属于后端 AI 能力描述的一部分,应由 Hermes 返回,或由 mnote 后端统一下发,而不是继续硬编码在前端。
|
||||
|
||||
---
|
||||
|
||||
## 4. 建议的精简方案
|
||||
|
||||
## Phase A:后移 AI 编排层到 Hermes,并给 mnote Rust 留清晰业务边界
|
||||
|
||||
第一步不是删 UI,而是把重逻辑后移。
|
||||
|
||||
### 需要后移的内容
|
||||
|
||||
- `createToolRegistry`
|
||||
- `resolveAllowedToolIds`
|
||||
- `builtinTools`
|
||||
- `builtinToolSets`
|
||||
- `runAiAgent`
|
||||
- 各类 `create*ServerTools`
|
||||
- scope -> toolset 的静态映射逻辑
|
||||
|
||||
### 目标结构
|
||||
|
||||
前端 `/api/ai-agent/run` 只保留:
|
||||
|
||||
- 鉴权
|
||||
- 规范化 `scope/messages/context/attachments/clientCapabilities`
|
||||
- 把请求转发给 Hermes API Server
|
||||
- 把 Hermes 的 SSE / `tool_call` / `tool_result` 回流给前端面板
|
||||
- 转发 client tool call/result
|
||||
- 在 Hermes 需要调用 mnote 业务能力时,转给 mnote Rust 暴露出来的业务能力面
|
||||
- 对少数短期无法迁走的 `TS_TRANSPORT_KEEP` 能力保留最小兼容壳
|
||||
|
||||
换句话说:
|
||||
|
||||
> `/api/ai-agent/run` 从“AI 编排器”降级为“AI 网关”。`
|
||||
|
||||
### 收益
|
||||
|
||||
- 显著降低 Next route 的 AI 编排复杂度
|
||||
- agent runtime 与 mnote 业务执行面彻底分层
|
||||
- 前端后续不必再继续长 builtins、registry 和 provider 编排
|
||||
- 后续若继续 CLI 化,也能直接复用 Hermes API Server 与 mnote Rust 协议边界
|
||||
|
||||
### Phase A 的现实限制
|
||||
|
||||
这一阶段不能简单理解为“删除所有 TS builtins 就结束”。
|
||||
|
||||
因为当前还有两类事情没有完全打通:
|
||||
|
||||
- Hermes API Server 还没在本机正式启用并接入 mnote
|
||||
- mnote Rust 业务能力还没全部以 Hermes 可调用的方式暴露
|
||||
|
||||
所以 Phase A 的实际目标应是:
|
||||
|
||||
- 先让 `/api/ai-agent/run` 从“自己编排”变成“转发 + 桥接”
|
||||
- 再逐步清理遗留 builtin
|
||||
- 不是一刀切直接删除所有中间层
|
||||
|
||||
## Phase B:统一 AI 面板实现
|
||||
|
||||
在后移编排层之后,再收 UI。
|
||||
|
||||
### 当前问题
|
||||
|
||||
四套 AI 面板都在重复维护:
|
||||
|
||||
- 对话
|
||||
- 工具日志
|
||||
- provider/model
|
||||
- localStorage
|
||||
- 中断/恢复
|
||||
|
||||
### 目标结构
|
||||
|
||||
新增统一通用面板,例如:
|
||||
|
||||
- `AiBridgePanel`
|
||||
|
||||
再由不同场景只提供轻量包装:
|
||||
|
||||
- `DocumentAiEntry`
|
||||
- `MindmapAiEntry`
|
||||
- `OnlyOfficeAiEntry`
|
||||
- `GlobalAiEntry`
|
||||
|
||||
这些 entry 只负责:
|
||||
|
||||
- 是否显示
|
||||
- 传入 context
|
||||
- 传入 clientCapabilities
|
||||
- 传入 UI 文案
|
||||
|
||||
### 收益
|
||||
|
||||
- 删除四套重复状态机
|
||||
- 降低包体与维护成本
|
||||
- 后续新场景不再复制面板
|
||||
|
||||
## Phase C:弱化或下线全局 AI
|
||||
|
||||
当前全局 AI 被直接挂在:
|
||||
|
||||
- `src/app/(app)/layout.tsx`
|
||||
|
||||
它带来的问题不是“首屏一定特别重”,而是:
|
||||
|
||||
- 全局产品心智更复杂
|
||||
- 持续占用一套入口与状态
|
||||
- 会诱导继续扩展“全局工具平台”
|
||||
|
||||
建议策略:
|
||||
|
||||
- 第一阶段:保留代码,但默认隐藏/弱化入口
|
||||
- 第二阶段:若页面 AI 已覆盖主场景,则把全局 AI 下线为开发页或实验开关
|
||||
|
||||
### 为什么优先保页面 AI 而不是全局 AI
|
||||
|
||||
因为页面 AI 更接近核心使用场景:
|
||||
|
||||
- 对页面正文直接读写
|
||||
- 与编辑器桥接紧密
|
||||
- 用户心智最清晰
|
||||
|
||||
全局 AI 更像附加层,不值得优先保留完整前端壳。
|
||||
|
||||
## Phase D:明确保留的少数浏览器专属能力
|
||||
|
||||
有一些能力确实不能完全后移,应明确留在前端:
|
||||
|
||||
- `oo_*` 这类 OnlyOffice 客户端工具
|
||||
- `/api/ai-agent/client-tool-result`
|
||||
- 少数必须读浏览器本地态的能力
|
||||
|
||||
这些能力的处理原则是:
|
||||
|
||||
- 保留
|
||||
- 但只能作为 `client capability bridge`
|
||||
- 不得重新长成新的前端 AI 平台层
|
||||
|
||||
---
|
||||
|
||||
## 5. 推荐优先级
|
||||
|
||||
如果只按收益排序,我建议这样做:
|
||||
|
||||
### P0:先做
|
||||
|
||||
- 启用并验证 Hermes API Server
|
||||
- 把 `/api/ai-agent/run` 收口成 Hermes bridge
|
||||
- 冻结前端新增 builtin tool / toolset / provider 编排逻辑
|
||||
- 明确 mnote Rust 能力如何暴露给 Hermes 调用
|
||||
|
||||
### P1:接着做
|
||||
|
||||
- 把多套 AI 面板收口为一个通用 `AiBridgePanel`
|
||||
- 页面 / Mindmap / OnlyOffice 改成 context adapter
|
||||
|
||||
### P2:再做
|
||||
|
||||
- 弱化或隐藏全局 AI Host
|
||||
- 让全局 AI 退到实验入口或开发入口
|
||||
|
||||
### P3:最后做
|
||||
|
||||
- 清理旧的 builtins、registry、重复 localStorage/session 管理
|
||||
- 删除历史兼容面板实现
|
||||
|
||||
---
|
||||
|
||||
## 6. 除 AI 之外,还有哪些可以精简
|
||||
|
||||
这部分先只记录,不进入当前 harness 任务。
|
||||
|
||||
## 6.1 文档页加载链可以继续减重
|
||||
|
||||
当前文档页存在:
|
||||
|
||||
- `DocumentShell` 的 `mounted + dynamic + ssr:false`
|
||||
- `DocumentContent` 再 `dynamic` 到 `BlockNoteEditor`
|
||||
- `meta` 与 `content` 的两阶段加载
|
||||
|
||||
这些都可能造成刷新时的“空一下再出现”的体感。
|
||||
|
||||
建议后续单独评估:
|
||||
|
||||
- 去掉 `DocumentShell` 这层多余壳
|
||||
- 减少文档页串行加载层级
|
||||
- 优先把首屏必需数据前移
|
||||
|
||||
## 6.2 SearchPalette 目前是全局常驻挂载
|
||||
|
||||
当前:
|
||||
|
||||
- `SearchPalette` 直接挂在 `app/(app)/layout.tsx`
|
||||
|
||||
如果它本身比较重,后续可考虑:
|
||||
|
||||
- 改为按需挂载
|
||||
- 或在首次打开时再加载
|
||||
|
||||
## 6.3 Sidebar 职责仍然非常重
|
||||
|
||||
`Sidebar` 当前承担了太多:
|
||||
|
||||
- 页面树
|
||||
- 文件树
|
||||
- 资产操作
|
||||
- 拖拽复制
|
||||
- 删除恢复
|
||||
- 批处理
|
||||
- mindmap/table/media 入口
|
||||
|
||||
这会让 Sidebar 成为高复杂度常驻组件。
|
||||
|
||||
后续可以考虑:
|
||||
|
||||
- 按功能拆分
|
||||
- 降低初始挂载职责
|
||||
- 把非首屏必要的动作延后
|
||||
|
||||
## 6.4 文档页周边抽屉与面板可以按需加载
|
||||
|
||||
当前文档页同时带着:
|
||||
|
||||
- `PageOptionsSidebar`
|
||||
- `PageBacklinksPanel`
|
||||
- `DocumentHistoryDrawer`
|
||||
- `DocumentCommentsDrawer`
|
||||
- `DocumentAiAgentPanel`
|
||||
|
||||
后续可评估哪些可以从“默认挂载”改成“首次打开再加载”。
|
||||
|
||||
---
|
||||
|
||||
## 7. 最终建议
|
||||
|
||||
如果你的目标是:
|
||||
|
||||
> **先精简能精简的东西来改善网页前端加载与复杂度**
|
||||
|
||||
那么最值得优先推进的不是重写 Web,也不是先重做编辑器,而是:
|
||||
|
||||
> **把前端 AI 从“平台层”收缩成“Hermes + mnote Rust 的桥接层”。**
|
||||
|
||||
一句话版结论:
|
||||
|
||||
- **该砍的不是 AI 按钮本身,而是前端 AI 编排框架。**
|
||||
- **该保留的是轻面板、Hermes bridge、mnote Rust 业务执行面和浏览器专属 client bridge。**
|
||||
- **全局 AI 可以弱化,页面 AI 保留为主入口。**
|
||||
- **除 AI 外,文档页加载链、全局 SearchPalette、巨型 Sidebar 也是后续值得继续精简的方向,但先不进入当前 harness。**
|
||||
@@ -0,0 +1,459 @@
|
||||
# [recycle] 文档访问性能根治重构路线 v1
|
||||
|
||||
> 更新时间:2026-04-16
|
||||
>
|
||||
> 相关文档:
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/ai-frontend-simplification-plan-v1.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
|
||||
|
||||
## 1. 目标
|
||||
|
||||
这份文档只回答一个长期问题:
|
||||
|
||||
> **如果不满足于“临时优化”,而要从架构上根治文档访问和页面切换卡顿,mnote 应该重构成什么样。**
|
||||
|
||||
本文的目标不是“再做几处按需加载”,而是定义:
|
||||
|
||||
- 哪些前端能力应继续保留
|
||||
- 哪些能力应退出当前重前端壳
|
||||
- Rust Web 层应该采用什么形态
|
||||
- `BlockNote` 应该如何被隔离,而不是继续拖慢整个页面系统
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前事实
|
||||
|
||||
结合当前仓库结构,可以先确认四个事实:
|
||||
|
||||
### 2.1 当前最重的前端成本,不在服务端语言
|
||||
|
||||
当前文档页主链仍然是:
|
||||
|
||||
`documents/[id]/page.tsx -> DocumentShell -> DocumentContent -> BlockNoteEditor`
|
||||
|
||||
而且存在以下典型问题:
|
||||
|
||||
- 文档进入页面后仍有 `meta -> content -> editor` 的串行加载链
|
||||
- `DocumentShell` 与 `DocumentContent` 仍在客户端串联挂载
|
||||
- `BlockNoteEditor` 本身是当前最重的前端运行时之一
|
||||
- 文档页周边仍挂载多类抽屉、面板和桥接组件
|
||||
|
||||
这说明当前访问速度问题的核心,不是“Node 不够快”,而是:
|
||||
|
||||
> **页面切换时仍然把太多东西当成同一层前端运行时来初始化。**
|
||||
|
||||
### 2.2 当前只有一类能力明确难以短期替换
|
||||
|
||||
从产品结构看,短期最难替换的是:
|
||||
|
||||
- `BlockNote`
|
||||
|
||||
因为它同时承担:
|
||||
|
||||
- 文档编辑核心
|
||||
- 自定义 block 运行时
|
||||
- 当前正文交互和保存链
|
||||
|
||||
而下面这些东西,从长期看都不是必须继续绑在当前 React/Next 大壳里的:
|
||||
|
||||
- Sidebar / 页面树 / 文件树
|
||||
- 搜索壳与搜索结果面板
|
||||
- Mindmap
|
||||
- AI 面板
|
||||
- 历史 / 评论 / 回链 / 页面选项等周边面板
|
||||
- 在线表格
|
||||
|
||||
### 2.3 OnlyOffice 不应被当成主阻塞项
|
||||
|
||||
根据当前架构,OnlyOffice 本来就是独立页面型编辑器,不是正文内嵌主编辑器。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 它不会决定文档页的首屏切换模式
|
||||
- 它可以继续保留“外挂页面/外部编辑器”定位
|
||||
- 它不应影响主文档访问性能路线判断
|
||||
|
||||
### 2.4 Mindmap 是优先级更高的可替换对象
|
||||
|
||||
当前 Mindmap 虽然复用了前端组件链,但它并不像 BlockNote 那样不可轻易动。
|
||||
|
||||
因此长期上:
|
||||
|
||||
- Mindmap 可以先于 BlockNote 重写
|
||||
- 它很适合作为“从当前重前端壳中剥离”的第一批对象
|
||||
|
||||
---
|
||||
|
||||
## 3. 根治原则
|
||||
|
||||
如果目标是“根治”,而不是“补丁式提速”,那么应遵守以下原则。
|
||||
|
||||
### 3.1 页面切换必须先回到“读优先”
|
||||
|
||||
当前问题的根子之一,是页面切换几乎默认在进入“编辑器世界”。
|
||||
|
||||
长期正确方向应改为:
|
||||
|
||||
- 先快速进入页面阅读态
|
||||
- 再按需进入编辑态
|
||||
- `BlockNote` 不得阻塞普通页面访问
|
||||
|
||||
换句话说:
|
||||
|
||||
> **文档页要从“先挂编辑器,再展示页面”改成“先展示页面,再按需挂编辑器”。**
|
||||
|
||||
### 3.2 除 `BlockNote` 外,其余能力应尽量退出当前重前端壳
|
||||
|
||||
长期目标不应是“继续给当前 Next/React 应用做瘦身”,而应是:
|
||||
|
||||
- 让能退出的都退出
|
||||
- 让必须保留在浏览器的只剩真正需要浏览器的那部分
|
||||
|
||||
理想形态是:
|
||||
|
||||
- 文档阅读页:极薄
|
||||
- 文档编辑岛:`BlockNote`
|
||||
- 外挂编辑器:OnlyOffice
|
||||
- 独立能力:Mindmap、AI、搜索、Sidebar 等各自最小化
|
||||
|
||||
### 3.3 Rust 化的意义在于“统一业务执行面”,不是“自动更快”
|
||||
|
||||
把东西改成 Rust 并不会自动让页面切换更快。
|
||||
|
||||
Rust 真正的价值在于:
|
||||
|
||||
- 统一业务执行平面
|
||||
- 让文档、块、导图、搜索、树结构、审计、AI 业务桥收口到同一体系
|
||||
- 支持更薄的前端和更强的 SSR / server-first 输出
|
||||
|
||||
所以“Rust 化”必须和“页面运行模型重构”一起发生,才构成根治。
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术选型判断
|
||||
|
||||
这一节只回答一个问题:
|
||||
|
||||
> **长期重构时,到底是“就用 Rust”,还是要明确选择 `axum` 等 Rust Web 框架。**
|
||||
|
||||
结论先给出:
|
||||
|
||||
> **不能只说“用 Rust”。长期要落地,必须明确分层选型。推荐方案是:`axum` 作为 Web/服务承载层,配合 `Leptos Islands` 作为 server-first 页面壳;不推荐只用 `axum`,也不建议把 Dioxus/Yew 作为主文档访问层的第一选择。**
|
||||
|
||||
### 4.1 为什么不能只说“Rust”
|
||||
|
||||
“Rust”是语言,不是 Web 渲染方案。
|
||||
|
||||
如果只决定“以后改成 Rust”,但不明确:
|
||||
|
||||
- 服务端路由由谁承接
|
||||
- 页面 SSR 由谁承接
|
||||
- islands / hydration 模型由谁承接
|
||||
- 浏览器交互层由谁承接
|
||||
|
||||
那最后很容易回到:
|
||||
|
||||
- 只是把 API 改写成 Rust
|
||||
- 但前端页面模型仍然没变
|
||||
|
||||
这不能根治。
|
||||
|
||||
### 4.2 `axum` 的定位:非常适合做 Web 承载层,但不负责前端 UI 模型
|
||||
|
||||
官方 `axum` 文档显示,它非常适合承担:
|
||||
|
||||
- Router
|
||||
- Handler
|
||||
- Middleware
|
||||
- JSON / Query / Form / WebSocket / SSE
|
||||
- `tokio` 上的高并发服务
|
||||
|
||||
这使它非常适合作为 mnote 长期的:
|
||||
|
||||
- API 层
|
||||
- 文档查询层
|
||||
- 树结构聚合层
|
||||
- 搜索层
|
||||
- AI / Hermes 业务桥
|
||||
- SSR 页面外壳承载层
|
||||
|
||||
但要注意:
|
||||
|
||||
> **`axum` 不是前端渲染框架。它能承接 Web 服务,不会替你解决“页面如何减少 hydration、如何隔离 BlockNote”这类前端模型问题。**
|
||||
|
||||
因此,**只用 `axum` 不够。**
|
||||
|
||||
### 4.3 为什么推荐 `Leptos Islands`
|
||||
|
||||
官方 Leptos Islands 文档最值得关注的点是:
|
||||
|
||||
- 默认服务端组件不进入客户端
|
||||
- 只有显式 `#[island]` 的部分才被编译到浏览器
|
||||
- islands 应尽量“小而具体”
|
||||
|
||||
这和 mnote 的长期目标高度一致,因为你现在最想要的是:
|
||||
|
||||
- 绝大多数页面内容不再变成大块客户端运行时
|
||||
- 只有真正需要交互的部分进入浏览器
|
||||
- `BlockNote` 成为最后一个重交互 island
|
||||
|
||||
也就是说,Leptos Islands 的思路天然支持:
|
||||
|
||||
- 页面树/文件树作为轻交互 island
|
||||
- 搜索框作为轻交互 island
|
||||
- AI 面板作为独立 island
|
||||
- `BlockNote` 作为最后的重 island
|
||||
- 其余大量阅读内容只做 server-rendered HTML
|
||||
|
||||
这比“继续在全页 React hydration 里做局部优化”更接近根治。
|
||||
|
||||
### 4.4 为什么不把 Dioxus 作为主推荐
|
||||
|
||||
官方 Dioxus Fullstack 文档自己就把它定位得更偏“app-like”:
|
||||
|
||||
- 它支持 SSR
|
||||
- 但更强调交互型应用
|
||||
- 文档中明确区分 CSR 的 app 架构与 SSR 的 site 架构
|
||||
|
||||
而 mnote 的长期目标不是继续维持一个“整页 app 先跑起来”的文档访问模型,而是:
|
||||
|
||||
- 页面先出来
|
||||
- 交互再局部接上
|
||||
|
||||
所以 Dioxus 不是不能用,而是**不如 Leptos Islands 对这个目标直接。**
|
||||
|
||||
### 4.5 为什么不把 Yew 作为主推荐
|
||||
|
||||
Yew 更接近经典 Rust/WASM 前端框架。
|
||||
|
||||
它的问题不是能力不够,而是:
|
||||
|
||||
- 更偏客户端应用思路
|
||||
- 不天然突出 islands-first
|
||||
- 对你当前“尽量减少客户端代码、把交互压缩为少数岛”的目标,不是最优选
|
||||
|
||||
---
|
||||
|
||||
## 5. 推荐的长期方案
|
||||
|
||||
## 5.1 总体选型
|
||||
|
||||
推荐长期架构采用:
|
||||
|
||||
- **服务承载层:`axum`**
|
||||
- **页面壳与 islands 模型:`Leptos Islands`**
|
||||
- **业务执行面:现有 mnote Rust `core-protocol + bridge-runtime + storage-convex-bridge` 继续演进**
|
||||
- **AI runtime:Hermes API Server**
|
||||
- **最后保留的重编辑岛:`BlockNote`**
|
||||
|
||||
一句话版:
|
||||
|
||||
> **`axum` 负责服务,`Leptos` 负责薄页面与 islands,Rust 内核负责业务,Hermes 负责 agent,`BlockNote` 留作最后的重前端孤岛。**
|
||||
|
||||
## 5.2 为什么这是最适合 mnote 的方案
|
||||
|
||||
因为这个方案同时满足四个条件:
|
||||
|
||||
### A. 适合逐步迁移
|
||||
|
||||
你不需要一次性推翻所有前端。
|
||||
|
||||
可以先把:
|
||||
|
||||
- Sidebar
|
||||
- 页面树 / 文件树
|
||||
- 搜索壳
|
||||
- 阅读页
|
||||
- Mindmap
|
||||
|
||||
逐步迁到 `axum + Leptos`
|
||||
|
||||
再把 `BlockNote` 留在最后处理。
|
||||
|
||||
### B. 适合“读写分离”
|
||||
|
||||
`Leptos Islands` 很适合把页面拆成:
|
||||
|
||||
- 读页面:服务端输出
|
||||
- 写页面:局部 island
|
||||
|
||||
这正是文档访问性能根治的核心。
|
||||
|
||||
### C. 适合 Rust 单栈长期收口
|
||||
|
||||
当前你已经做过大范围 Rust 重构,未来继续统一到:
|
||||
|
||||
- Web 壳
|
||||
- 业务协议
|
||||
- AI 业务桥
|
||||
- CLI
|
||||
|
||||
会比继续维护“Rust 内核 + 重 Next 前端壳”的分裂状态更稳定。
|
||||
|
||||
### D. 风险可控
|
||||
|
||||
你不需要一开始就重写 `BlockNote`。
|
||||
|
||||
最难的部分可以留到最后,不会卡死整个长期路线。
|
||||
|
||||
---
|
||||
|
||||
## 6. 最终目标架构
|
||||
|
||||
长期目标建议收敛成下面这张逻辑图:
|
||||
|
||||
```text
|
||||
浏览器
|
||||
-> axum 路由层
|
||||
-> Leptos server-rendered 文档壳
|
||||
-> 少量 islands
|
||||
- Sidebar / 页面树 / 文件树
|
||||
- Search
|
||||
- AI 面板
|
||||
- Mindmap(重写后)
|
||||
- BlockNote(最后保留的重岛)
|
||||
|
||||
axum / Leptos
|
||||
-> mnote Rust 业务执行面
|
||||
- 文档
|
||||
- 块
|
||||
- 搜索
|
||||
- 导图
|
||||
- 审计 / trace / event
|
||||
|
||||
Hermes API Server
|
||||
-> 调用 mnote Rust 暴露的业务能力桥
|
||||
|
||||
OnlyOffice
|
||||
-> 继续独立页面 / 外挂编辑器
|
||||
```
|
||||
|
||||
在这个目标架构里:
|
||||
|
||||
- 页面切换不再默认进入“整页前端应用”
|
||||
- 绝大多数阅读内容不需要大块 hydration
|
||||
- `BlockNote` 成为唯一需要谨慎处理的大前端负担
|
||||
|
||||
---
|
||||
|
||||
## 7. 推荐迁移顺序
|
||||
|
||||
长期路线建议分四阶段,不建议一口气重做。
|
||||
|
||||
## Phase 1:先把文档访问模型改成 server-first
|
||||
|
||||
先做:
|
||||
|
||||
- 用 Rust Web 壳承接文档阅读态
|
||||
- 页面进入时直接输出 `meta + content`
|
||||
- 不再进入页面后再串行拉正文
|
||||
- 把“页面切换”和“编辑器启动”拆开
|
||||
|
||||
这一阶段的目标不是替换 BlockNote,而是先把它从切页主链里移走。
|
||||
|
||||
## Phase 2:优先重写可替换的常驻模块
|
||||
|
||||
优先级建议:
|
||||
|
||||
1. Sidebar / 页面树 / 文件树
|
||||
2. 搜索壳与搜索结果页
|
||||
3. 页面选项、历史、评论、回链等周边面板
|
||||
4. AI 面板
|
||||
|
||||
原因:
|
||||
|
||||
- 这些东西是跨页面常驻能力
|
||||
- 高频出现
|
||||
- 比 BlockNote 更容易先抽离
|
||||
|
||||
## Phase 3:重写 Mindmap,继续缩小前端重负担
|
||||
|
||||
Mindmap 是非常适合优先退出当前重前端壳的对象。
|
||||
|
||||
建议:
|
||||
|
||||
- 把导图数据和执行面继续放在 Rust
|
||||
- 前端重新实现为更轻的独立渲染层
|
||||
- 不再依赖当前文档页大壳去承载
|
||||
|
||||
## Phase 4:最后再处理 BlockNote
|
||||
|
||||
这时再决定:
|
||||
|
||||
- 是否继续保留 BlockNote,但隔离为独立 island
|
||||
- 是否逐步替换 BlockNote 的部分能力
|
||||
- 是否长期把编辑体验拆成更多 Rust 原生能力 + 少量 JS 编辑器兼容层
|
||||
|
||||
**在此之前,不建议把 BlockNote 当成第一刀。**
|
||||
|
||||
---
|
||||
|
||||
## 8. 非目标
|
||||
|
||||
为了避免路线漂移,下面这些都不应被误认为“根治方案”。
|
||||
|
||||
### 8.1 不是“把 Next API 改成 Rust 就算完成”
|
||||
|
||||
如果页面仍然是:
|
||||
|
||||
- 重客户端壳
|
||||
- 重 hydration
|
||||
- 切页即初始化编辑器
|
||||
|
||||
那只是服务端换语言,不是根治。
|
||||
|
||||
### 8.2 不是“先全面重写 BlockNote”
|
||||
|
||||
BlockNote 是最难对象,不应先作为第一刀。
|
||||
|
||||
正确顺序应是:
|
||||
|
||||
- 先移除外围负担
|
||||
- 最后再碰 BlockNote
|
||||
|
||||
### 8.3 不是“继续在当前 React 壳里无限做局部修补”
|
||||
|
||||
按需加载、拆组件这些短期仍有价值,但如果最终仍然保留:
|
||||
|
||||
- 大型客户端文档壳
|
||||
- 大型常驻 Sidebar
|
||||
- 大型客户端页面切换模型
|
||||
|
||||
那还是治标不治本。
|
||||
|
||||
---
|
||||
|
||||
## 9. 最终建议
|
||||
|
||||
如果以“根治文档访问性能”为唯一目标,我给出的长期技术判断是:
|
||||
|
||||
> **应该继续推进 Rust 主导重构,但不是笼统地说“以后用 Rust”,而是明确采用 `axum + Leptos Islands + mnote Rust 内核 + Hermes` 的组合。**
|
||||
|
||||
其中:
|
||||
|
||||
- `axum`
|
||||
适合做 Web 服务承载层、API、SSE、AI 业务桥、SSR 外壳。
|
||||
- `Leptos Islands`
|
||||
适合做 server-first 文档页和极小交互岛,是把 `BlockNote` 隔离成“最后一个重前端岛”的最佳路线。
|
||||
- `Dioxus`
|
||||
可以关注,但更适合作为偏 app 化交互场景的备选,不是当前文档访问性能根治的第一推荐。
|
||||
- `Yew`
|
||||
不作为当前主路线推荐。
|
||||
|
||||
最后用一句话收口:
|
||||
|
||||
> **mnote 的根治路线,不是“把现有前端改快一点”,而是“把除了 BlockNote 之外的大多数页面能力从当前重前端壳中迁出,交给 Rust 主导的 server-first Web 架构承载”。**
|
||||
|
||||
---
|
||||
|
||||
## 10. 外部参考
|
||||
|
||||
以下外部资料支持上面的技术判断:
|
||||
|
||||
- `axum` 官方文档:
|
||||
https://docs.rs/axum/latest/axum/
|
||||
- Leptos Islands 指南:
|
||||
https://book.leptos.dev/islands.html
|
||||
- Dioxus Fullstack SSR 文档:
|
||||
https://dioxuslabs.com/learn/0.7/essentials/fullstack/ssr/
|
||||
@@ -0,0 +1,284 @@
|
||||
# [recycle] mnote 单仓收口 Rust 内核阶段 Checklist
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 主工作路径:`/mnt/Data1T/mnote`
|
||||
>
|
||||
> 第二工作路径:`/mnt/Data1T/mnote-rust`(仅作为历史资产来源,不作为主执行仓)
|
||||
>
|
||||
> 对齐文档:`/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-plan.md`
|
||||
>
|
||||
> 目标:把 `mnote-rust` 的必要 Rust 内核逐步回迁到 `mnote` 主仓,并始终维持“单仓启动、单仓保存、主前端不分叉”的执行口径。
|
||||
|
||||
## 1. 执行口径与硬边界
|
||||
|
||||
- [x] 只保留 `/mnt/Data1T/mnote` 作为唯一主产品仓。
|
||||
- [x] `/mnt/Data1T/mnote-rust` 只保留为历史资产来源、参考实现和待吸收规范,不再承担主线执行入口。
|
||||
- [x] `wolai-frontend` 继续承担唯一主产品前端壳,不复制 `mnote-rust` 的第二套 Next 前端壳。
|
||||
- [x] Rust 内核统一收口到 `/mnt/Data1T/mnote/rust/`,不再在主仓根目录散落多个 Rust 源码根。
|
||||
- [x] 最终保存只认 Convex 主事实层;Rust 的事件、索引、缓存、fixtures 都属于派生层。
|
||||
- [x] 不通过跨仓软链接、硬链接或路径偷接来假装完成迁移。
|
||||
- [x] 第一阶段不迁入 `design/phases/**`、`design/execution/**`、`design/UI/**` 这类历史叙事文档。
|
||||
- [x] 第一阶段不迁入 `mnote-cli`、`adapter-onlyoffice`、`adapter-mindmap`、`adapter-legacy-mnote`。
|
||||
- [x] Mindmap 继续以 `mnote` 当前实现为主:BlockNote 自定义块为主形态,独立全屏页为辅助形态。
|
||||
- [x] OnlyOffice 继续保持“正文只嵌文件入口、编辑器在独立页面运行”的产品形态,不回嵌 BlockNote。
|
||||
- [x] `wolai-frontend/`、`wolai-backend/`、`infra/convex/`、`src/components/onlyoffice/` 默认保持不动,除非后续阶段明确接线需要。
|
||||
|
||||
## 2. 当前已确认基线(2026-04-13 已核对)
|
||||
|
||||
### 2.1 已完成事实
|
||||
|
||||
- [x] `/mnt/Data1T/mnote/rust/Cargo.toml` 与 `/mnt/Data1T/mnote/rust/Cargo.lock` 已存在。
|
||||
- [x] `/mnt/Data1T/mnote/rust/crates/` 下已落位 `core-domain`、`core-protocol`、`event-log`、`storage-convex-bridge`、`index-fts`、`bridge-runtime`、`mnote-cli`。
|
||||
- [x] `/mnt/Data1T/mnote/rust/design/INDEX.md` 与 `design/core/01~04` 核心设计文档已落位。
|
||||
- [x] workspace members 仅指向 `/mnt/Data1T/mnote/rust/crates/*`。
|
||||
- [x] 已验证 `cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1` 可通过。
|
||||
- [x] 已验证 `cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml` 可通过。
|
||||
- [x] 已核对 `/mnt/Data1T/mnote/rust/` 下未发现直接引用 `/mnt/Data1T/mnote-rust` 的残留路径。
|
||||
- [x] 已确认当前主前端链路仍在 `mnote`:文档页为 `DocumentShell -> DocumentContent -> BlockNoteEditor`,Mindmap 仍复用现有 `MindmapBlock` 体系,OnlyOffice 仍为独立页面型编辑器。
|
||||
|
||||
### 2.2 当前仍未开始或未初始化的事实
|
||||
|
||||
- [x] `/mnt/Data1T/mnote/rust/bridge/` 已初始化最小说明目录,`crates/bridge-runtime` 已提供 Phase 1 最小真实执行样板。
|
||||
- [x] `/mnt/Data1T/mnote/rust/scripts/` 当前未初始化。
|
||||
- [x] `/mnt/Data1T/mnote/rust/fixtures/` 当前未初始化。
|
||||
- [x] `/mnt/Data1T/mnote/rust/tests/` 当前未初始化。
|
||||
- [x] `mnote-cli` 已并入 `/mnt/Data1T/mnote/rust/crates/`,当前已冻结 `page/block/search/sidebar/tool` 的最小命令面与 `--json` 输出协议。
|
||||
- [x] `adapter-onlyoffice`、`adapter-mindmap`、`adapter-legacy-mnote` 尚未并入主仓。
|
||||
- [x] `/api/documents/content`、`/api/documents/save`、`/api/documents/title`、`/api/documents/stats`、`/api/sidebar`、`/api/blocks/patch` 已接入主仓当前 bridge 包装层并统一返回 `request_id/trace_id` 元信息;其中 `documents/title`、`documents/stats`、`documents/options`、`documents/save` 已进一步收口到统一的 bridge mutation request 运行时接缝,可先构造与 `storage-convex-bridge::build_write_request` 对齐的 `functionName/payloadJson/args` 对象再落到 Convex,但整条链仍未直接切到 `core-protocol -> storage-convex-bridge` 的真实 Rust crate 执行链。
|
||||
|
||||
2026-04-15 Phase 1/2 补记:`documents.content.get`、`documents.title.update`、`documents.save` 这 1 读 2 写链现已从主仓 Next route 真实进入 `crates/bridge-runtime`,再由 TS 仅做 Convex transport;同时 `crates/mnote-cli` 已在主仓 workspace 落位,并通过 `page/block/search/sidebar/tool` 五类最小命令面的 `--json` 计划输出冻结当前 CLI 协议。
|
||||
|
||||
## 3. Phase A:Rust workspace 落位(主目标已完成)
|
||||
|
||||
完成目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/` 成为唯一 Rust workspace 根。
|
||||
- P0 crate 与核心规范文档已在主仓内有真实副本。
|
||||
- 新 workspace 已具备最小自检能力。
|
||||
|
||||
Checklist:
|
||||
|
||||
- [x] 固定 `/mnt/Data1T/mnote/rust/` 为唯一 Rust workspace 根,后续 Rust 命令统一从这里发起。
|
||||
- [x] 固定 workspace members 只指向 `crates/core-domain`、`crates/core-protocol`、`crates/event-log`、`crates/storage-convex-bridge`、`crates/index-fts`。
|
||||
- [x] 复制并落位 `core-domain`、`core-protocol`、`event-log`、`storage-convex-bridge`、`index-fts`。
|
||||
- [x] 复制并落位 `rust/design/INDEX.md` 与 `rust/design/core/01-domain-model-v0.md`、`02-command-query-tool-protocol-v0.md`、`03-storage-event-indexing-v0.md`、`04-onlyoffice-integration-boundary-v0.md`。
|
||||
- [x] 统一 workspace 级别的 `edition`、`license`、`version`、`authors` 约定。
|
||||
- [x] 跑通 `cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1`。
|
||||
- [x] 跑通 `cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml`。
|
||||
- [x] 已补跑 `cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-domain` 与 `cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocol`。
|
||||
- [x] 已在本 checklist 第 1 节固定“第一阶段禁止迁入清单”,明确 `mnote-cli`、`adapter-*`、`design/phases/**`、`design/execution/**`、第二套 Next 前端壳均不属于本阶段交付。
|
||||
|
||||
Phase A 验收:
|
||||
|
||||
- [x] Cargo 可在主仓内解析 workspace。
|
||||
- [x] 主仓内已有 P0 内核与长期规范副本。
|
||||
- [x] 当前未出现对第二工作路径的直接 Cargo 路径依赖。
|
||||
- [x] 已完成 crate 单测与文档级禁止迁入清单,Phase A 可视为关闭。
|
||||
|
||||
## 4. Phase B:bridge 入口与 Convex 桥接
|
||||
|
||||
完成目标:
|
||||
|
||||
- 在 `mnote` 主仓内形成唯一 Rust command/query 入口。
|
||||
- 首批读写入口从“前端 API 直接调 Convex”切到“前端 API -> Rust bridge -> Convex”。
|
||||
|
||||
当前起点(已确认):
|
||||
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/content/route.ts` 当前直接 `query(api.documents.getContent)`。
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/save/route.ts` 当前已改为构造稳定 envelope 后交给 `save-command-adapter` 执行。
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/title/route.ts` 当前已不再直接拼 `mutation(api.documents.updateTitle)` 参数,改为构造稳定 envelope 后交给页面元信息 command adapter 执行。
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/stats/route.ts` 当前已不再直接拼 `mutation(api.documents.updateStats)` 参数,改为构造稳定 envelope 后交给页面元信息 command adapter 执行。
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts` 当前直接聚合多个 Convex query 结果。
|
||||
- [x] `/mnt/Data1T/mnote/wolai-frontend/src/app/api/blocks/patch/route.ts` 当前直接读取文档内容、替换 block 树后回写 Convex。
|
||||
|
||||
Checklist:
|
||||
|
||||
- [x] 已在 `wolai-frontend/src/lib/documents/bridge.ts` 固定当前 bridge 入口,先由主仓 API route 统一走同一层包装。
|
||||
- [x] 已固定首批 bridge envelope:`request_id`、`trace_id`、`workspace_id`、`actor`、`source`、`idempotency_key`。
|
||||
- [x] 约定所有新命令和查询都先进入 `core-protocol` envelope,再转给 `storage-convex-bridge`。
|
||||
- [x] 已把 `documents/content` 与 `sidebar` 两条低风险读链接入当前 bridge query 包装层。
|
||||
- [x] 已把 `documents/title`、`documents/stats`、`documents/save`、`blocks/patch` 接入当前 bridge command 包装层。
|
||||
- [x] 已为 `documents/title`、`documents/stats` 收口稳定的页面元信息 command adapter,冻结 route 到 Convex 之间的 payload/target/meta 映射,避免 route 继续直接耦合 `updateTitle/updateStats` 的参数细节。
|
||||
- [x] 已为首批 4 条写链固定当前 `bridge -> Convex` 的函数名、payload 结构和 workspace scope;其中 `documents.title`、`documents.stats`、`documents.options`、`documents.save` 已先收口到 `buildDocumentBridgeMutationRequest` 这层最小运行时接缝,统一构造与 `storage-convex-bridge::build_write_request` 对齐的 `functionName/payloadJson/args`,再由同一执行器落到 Convex;`blocks.patch` 仍未收口到该执行层,且整条链尚未直接切到 Rust crate 内统一执行。
|
||||
- [x] 已在 `wolai-frontend/convex/schema.ts` 新增 `command_logs`、`domain_events` 两张表,并新增 `wolai-frontend/convex/bridgeLogs.ts` 与 `src/lib/documents/bridge-log.ts` 承接首批写链日志落账。
|
||||
- [x] 首批 4 条写链(`documents/title`、`documents/stats`、`documents/save`、`blocks/patch`)当前会在成功路径同时写入 command log 与 domain event;失败态、回滚态和统一事务性仍待后续补齐。
|
||||
- [x] 当前已接入的查询链(`documents/content`、`sidebar`)保持只读,不产生写副作用。
|
||||
- [x] 已统一 `documents/content`、`documents/save`、`documents/title`、`documents/stats`、`sidebar` 的首批 bridge 错误返回结构。
|
||||
- [x] 当前 bridge 仅负责协议校验、请求映射与响应元信息包装,尚未吞并产品 UI 逻辑。
|
||||
|
||||
2026-04-14 B 阶段补记:已在 `rust/crates/core-protocol` 中补齐 `documents.meta.get`、`documents.content.get`、`sidebar.dataset.list`、`documents.save`、`blocks.patch` 的最小 query/command 协议对象,并在 `rust/crates/storage-convex-bridge` 中补齐对应的 query/command name -> Convex function 映射与单测。当前主仓新增链路已统一先构建稳定 envelope,再由后续真实 Rust bridge 执行链消费;本轮已通过 `cargo test -p core-protocol -p storage-convex-bridge` 与 `cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml` 验证协议与映射闭环。
|
||||
2026-04-14 B 阶段第三刀补记:已在 `wolai-frontend/src/lib/documents/bridge.ts` 新增 `buildDocumentBridgeMutationRequest` 与统一执行器,把 `documents.title.update`、`documents.stats.update`、`documents.options.update`、`documents.save` 进一步推进到最小可运行的 Rust bridge 风格接缝。当前这些写链会先生成与 `storage-convex-bridge::build_write_request` 对齐的 `functionName/payloadJson/args` 运行时对象,再由适配层调用 Convex mutation;配套 `src/lib/documents/bridge.test.ts` 已新增 request builder 断言,确认标题更新与正文保存两条链的运行时 request 形状稳定。
|
||||
|
||||
Phase B 验收:
|
||||
|
||||
- [x] 当前至少已有 2 条查询链(`documents/content`、`sidebar`)和 4 条写链(`documents/title`、`documents/stats`、`documents/save`、`blocks/patch`)通过当前 bridge 包装层读写 Convex。
|
||||
- [x] 已补 `/api/bridge/trace`、`/api/bridge/request` 回查入口,并已切到 `wolai-frontend/convex/bridgeLogs.ts` 查询主线;`convex/audit.ts` 当前保留为并行旧实现线,不作为本轮回查入口。
|
||||
- [x] 当前已接入的请求错误结构已统一到 bridge 错误响应,不再直接抛出临时调试字符串。
|
||||
- [x] 本批改动只改 API route 与调用 payload,未改页面结构与 UI 外观。
|
||||
|
||||
建议验证:
|
||||
|
||||
- [x] `cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml`
|
||||
- [x] 已对 `/api/documents/content`、`/api/sidebar` 做最小读链 smoke:当前主仓实例固定为 `http://127.0.0.1:3001`,`/api/sidebar` 已返回 `activeWorkspaceId=ws-smoke-temp`,新建文档后 `/api/documents/content` 可正常返回内容与 `requestId/traceId`。
|
||||
- [x] 已对 `/api/documents/title`、`/api/documents/stats`、`/api/documents/save`、`/api/blocks/patch` 做最小写链 smoke:真实写入成功,且随后 `/api/documents/content` 已读回 `blocks.patch` 改写后的正文。
|
||||
- [x] 已完成真实 Convex 运行前置验证:`infra/convex/docker-compose.yml` 可启动本地自托管 Convex,`pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping` 已通过。
|
||||
- [x] 已用真实 Convex CLI 对 `bridgeLogs:recordCommandLog`、`bridgeLogs:recordDomainEvent`、`bridgeLogs:listByTrace`、`bridgeLogs:listByRequest` 做最小 smoke,确认 command log、domain event、trace/request 字段能同时落账并回查。
|
||||
- [x] 已完成网页/API 级 smoke:从真实 `/api/documents/title`、`/api/documents/stats`、`/api/documents/save`、`/api/blocks/patch` 返回的 `requestId/traceId`,可继续经 `/api/bridge/trace` 与 `/api/bridge/request` 回查到对应 `command_logs/domain_events`。本轮同时修复 `src/lib/documents/bridge-log.ts` 中 `getAuthedConvexClient()` 返回值解构错误(此前会导致写链落账时报 `client.mutation is not a function`)。
|
||||
|
||||
## 5. Phase C:页面元信息、Sidebar 与正文保存接入
|
||||
|
||||
完成目标:
|
||||
|
||||
- 在不更换主前端壳的前提下,把文档元信息、Sidebar 聚合、BlockNote 正文保存逐步切到 Rust 协议层。
|
||||
- 执行顺序严格按 `C1 页面元信息 -> C2 Sidebar 聚合 -> C3 正文保存` 推进,不跳步。
|
||||
|
||||
### C1 页面元信息
|
||||
|
||||
- [x] 已盘点并锁定文档页元信息读写边界:`src/app/(app)/documents/[id]/page.tsx` 负责元信息入口,`document-content.tsx` 负责标题/页面选项/统计信息写入,`document-shell.tsx` 仅继续透传既有 UI 壳参数。
|
||||
- [x] 已锁定并接入当前 C1 最小读链:`src/app/(app)/documents/[id]/page.tsx` 原先直调 `api.documents.getMeta`,现已改为经 `GET /api/documents/meta` 进入现有 bridge query 包装层;新增的服务端 helper 仅负责透传当前请求认证/追踪头并发起同源 bridge route 请求。
|
||||
- [x] 已把标题更新、页面属性、页面选项、统计信息这批低风险页面元信息操作切到统一的当前协议/适配边界:标题、统计信息、页面选项 3 条写链都已接入当前 bridge command 包装层;其中 `documents.title.update`、`documents.stats.update`、`documents.options.update` 已统一收口到 `wolai-frontend/src/lib/documents/metadata-command-adapter.ts`,route 只保留 validation、`buildDocumentBridgeContext`、`buildDocumentCommandEnvelope` 与稳定错误模型。`documents.options` 本轮不再内联 `client.mutation(api.documents.updateOptions, ...)`。同时已补齐 `rust/crates/core-protocol` 的 `UpdatePageTitle`、`UpdatePageStats`、`UpdatePageOptions` 结构与 `storage-convex-bridge` 的 command name -> Convex mutation 映射测试;2026-04-14 又进一步把这 3 条写链切到 `buildDocumentBridgeMutationRequest`,先构造与 Rust `ConvexMutationRequest` 对齐的最小运行时 request,再交给统一执行器落到 Convex,为后续真实 Rust 执行链留出稳定接缝。
|
||||
- [x] 当前最小替换已保持现有页面 UI、权限判断、动态导入结构不变:`DocumentShell` 入参、`readOnly/disableDownload/disableCopy` 计算、`notFound()` 分支与页面结构保持不变,仅将元信息读取入口切到 `documents.meta` bridge query。
|
||||
- [x] 已统一页面元信息链当前口径:`documents.meta` 读链与 `documents.title/stats/options` 写链均复用 `buildDocumentBridgeContext` / envelope;query payload 与 command payload 已固定 `documentId/workspaceId`,target.pageId 固定文档 business id,回传元信息统一为 `requestId/traceId/queryName|commandId|commandName`,actor/source 也统一来自 bridge context。
|
||||
- [x] 已为标题更新、页面属性、统计信息补齐当前最小回归验证。
|
||||
当前最小验证:已对页面选项写链补跑相关文件 eslint / vitest,并完成真实 HTTP smoke,确认在主仓 `http://127.0.0.1:3001` 实例下以 `ws-smoke-temp` 工作区调用 `POST /api/documents/options` 后,会返回 `requestId=req_aef4159e-24f2-43a8-b168-864c4b2b2c6c`、`traceId=trace_3cbc114e-db01-410f-933c-e63d8bd83393`、`commandId=cmd_2cb6871d-9075-4252-b698-a7c4ea069bfd`,且后续 `/api/bridge/request` 与 `/api/bridge/trace` 已能回查到对应 `command_logs/domain_events`。本轮同时保留 `documents.meta` 读链最小验证:真实 `GET /api/documents/meta?documentId=...&workspaceId=ws-smoke-temp` 已返回 `doc + meta.requestId/traceId/queryName=documents.meta.get`。另外 `documents/stats` 写链的真实 HTTP smoke 也已完成并可回查。2026-04-14 新增一轮真实复测:同一 `documentId` 连续执行 `POST /api/documents/options {showToc:true,layoutDensity:\"compact\"}` 与 `POST /api/documents/stats {wordCount:12,characterCount:34,blockCount:2,todoTotal:5,todoDone:3}` 后,紧跟 5 次 `GET /api/documents/meta` 均稳定返回本次写入值,未再复现“同次写入后 meta 读回不稳定”的现象。为避免历史脏数据导致偶发漂移,已把 `convex/documents.ts` 的关键 `by_document_id` 读写收口到 deterministic canonical record 选择逻辑,并补了重复 business id 的回归测试。
|
||||
2026-04-14 第二批真实收口:已将仍直接依赖 `by_document_id.first()` 的高风险页面/文档关联路径继续切到同一 canonical document helper,当前已覆盖 `convex/documentShares.ts`、`convex/documentGroupShares.ts`、`convex/documentStars.ts`、`convex/comments.ts`、`convex/references.ts`。这批路径分别影响页面共享权限判定、群组公开、收藏可见性、评论线程读写与反链标题读取;此前若同一 business `documentId` 存在重复物理记录,会继续存在命中漂移风险。本轮已补跑目标文件 `eslint`、`src/lib/documents/document-record.test.ts`,并用源码扫描确认这批目标文件内已不再残留 `by_document_id.first()`;当前未继续扩到 `mediaAssets.ts`、`mindmaps.ts` 等非本批最小闭环路径。
|
||||
2026-04-14 第三批真实收口:继续只处理剩余 still-high-risk 的 `documents.by_document_id` 直接命中点,已新增 `convex/_utils/documentRecord.ts#getCanonicalParentDocumentId`,并把 `convex/comments.ts`、`convex/documents.ts` 中共享/权限祖先链扫描统一改到该 helper,避免同一 business `documentId` 的重复物理记录在父链遍历时再次漂移。同时已把 `convex/mindmaps.ts` 的 owner 校验从 `by_document_id.first()` 切到 `requireCanonicalOwnedDocument`,并将 `convex/mediaAssets.ts#createWithStorage` 的页面归属校验改为 `getCanonicalDocumentByBusinessId`,以覆盖页面内容附件上传这一仍会直接命中旧记录的高风险入口。本批最小验证目标为:补充 canonical helper 单测、对上述目标文件跑 `eslint`,并再次用源码扫描确认 `comments/documents/mindmaps/mediaAssets` 内不再残留直接依赖 `documents.by_document_id` 的实现。
|
||||
2026-04-14 第四批真实收口:按本轮 C1 要求只处理 `convex/documentStars.ts` 剩余两个父链祖先扫描点,已将 `resolveSharePermission` 与 `resolveGroupSharePermission` 中手写的 `documents.by_document_id` 父级推进统一改为 `getCanonicalParentDocumentId`。同时已补充 `src/lib/documents/document-record.test.ts` 的 helper 回归用例,验证重复 business `documentId` 下即使旧记录已删除,父链 helper 仍稳定返回 canonical 父页面 id;并已补跑目标文件 `eslint` 与 `vitest`。本轮源码扫描确认 `wolai-frontend/convex/` 业务路径中已不再残留直接 `withIndex(\"by_document_id\")` 命中点,当前仅剩 `convex/_utils/documentRecord.ts` 作为底层 canonical helper 持有该查询。
|
||||
|
||||
C1 验收:
|
||||
|
||||
- [x] 页面元信息至少已有 3 条低风险链路切入 Rust 层。
|
||||
- [x] 文档页外观与交互未退化。
|
||||
- [x] trace 字段已可回查到页面级写入:`documents.title.update`、`documents.stats.update`、`documents.options.update` 的真实 HTTP 写入均已返回 `requestId/traceId`,且后续 `/api/bridge/request` 与 `/api/bridge/trace` 已复核可查到对应 `command_logs/domain_events`。
|
||||
|
||||
2026-04-14 C1 浏览器回归补记:已新增 `/mnt/Data1T/mnote/scripts/task019-document-ui-regression.js` 并在真实本地实例 `http://127.0.0.1:3001` 上执行。脚本会创建临时页面,确认 Sidebar 主导航与“私有 / 我的页面”分区可见、文档页标题输入框与 BlockNote 编辑区正常渲染,然后实际修改标题与正文,等待 `/api/documents/title`、`/api/documents/save` 成功返回并出现“已保存”,最后刷新页面确认标题与正文仍保留,再调用 `/api/documents/purge` 清理临时页面。实跑结果通过,说明本轮协议层切换后文档页主交互未退化。
|
||||
|
||||
### C2 Sidebar 聚合
|
||||
|
||||
- [x] 盘点 Sidebar 真实数据来源,锁定 `sidebar.tsx`、`private-tree.tsx`、`file-tree.tsx`、`use-convex-sidebar-data.ts`、`sidebar-tree.ts`。
|
||||
- [x] 先把 Sidebar 的查询聚合逻辑抽象成 Rust query 目标,避免继续在前端和 API 中重复拼树。
|
||||
- [x] 为 Sidebar 建立最小查询契约,至少覆盖页面列表、层级关系、文件树行模型和展开状态所需字段。
|
||||
- [x] 保留现有 Sidebar UI 和交互,不引入第二套导航壳,也不从 `mnote-rust` 复制 `sidebar.tsx` 覆盖现实现。
|
||||
- [x] 把 Mindmap、表格、媒体等派生资源的聚合边界整理成后续 Rust query 可接入的明确目标。
|
||||
|
||||
2026-04-14 盘点补记:当前主入口已确认位于 `wolai-frontend/src/components/sidebar/sidebar.tsx`,私有树/文件树分别位于 `components/sidebar/private-tree.tsx` 与 `components/sidebar/file-tree.tsx`;数据侧同时存在 `/api/sidebar` 聚合 route、`hooks/use-convex-sidebar-data.ts` 实时订阅组装,以及 `lib/sidebar-tree.ts` 的树/section 构建逻辑,说明 C2 的真实起点是“API 聚合 + 前端二次拼装”的双层结构。
|
||||
2026-04-14 契约补记:当前最小 Rust query 目标已明确为兼容 `SidebarInitialData` 的单查询返回,至少覆盖 `active_workspace_id`、`workspaces`、`documents`、`trashed_documents`、`media_assets`、`trashed_media_assets`、`mindmap_assets`、`trashed_mindmap_assets`、`table_assets`、`trashed_table_assets`、`mindmap_docs`、`mindmap_asset_children`,从而先替换聚合来源而不改 `buildDocumentTree/buildVisibleRows` 的前端渲染逻辑。
|
||||
2026-04-14 边界补记:当前已明确必须保持不变的 UI/交互包括 `starred/public/shared/private/templates` 分区语义、`sort_order -> created_at` 排序口径、`doc/index.md/asset-folder/asset` 文件树行语义、拖拽/剪贴板协议,以及回收站双 tab 与资源计数行为;Mindmap、表格、媒体三类派生资源的聚合边界已被明确列为 Rust query 后续接入目标。
|
||||
2026-04-14 C2 第一刀收口补记:已新增 `wolai-frontend/src/lib/sidebar-data.ts` 与 `wolai-frontend/src/lib/server/sidebar-data.ts`,把 `src/app/(app)/layout.tsx`、`src/app/api/sidebar/route.ts`、`src/hooks/use-convex-sidebar-data.ts` 之间重复的 `SidebarInitialData` 组装统一收口到共享 helper;同时修复 hook 链路中 `mindmapAssetChildren` 长期为空的漂移,补充 `src/lib/sidebar-data.test.ts`,并通过 `pnpm test src/lib/sidebar-data.test.ts src/lib/file-tree/rows.test.ts` 与定向 `eslint` 验证。基于本轮复核,当前已可确认“多个前端位置不再重复拼装同一棵树”这一验收点达成;但由于 SidebarInitialData 仍未冻结为明确 Rust query contract,`C2` 其余验收项暂不提前勾选。
|
||||
2026-04-14 C2 第二刀补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/sidebar-rust-query-target.md`,把 `sidebar.dataset.list` 的最小 payload/result、Rust query 与前端投影职责边界、以及“不复制第二套导航壳/不直接输出前端渲染树”的约束固定成文档。当前可确认 Sidebar 查询聚合目标已经从“散落在 route 和 hook 中的实现细节”收口为明确的 Rust query 接入目标。
|
||||
|
||||
C2 验收:
|
||||
|
||||
- [x] Sidebar 至少一条主查询已经改由 Rust query 供给。
|
||||
- [x] 文档树、文件树、回收站等视图语义保持一致。
|
||||
- [x] 不再需要在多个前端位置重复拼装同一棵树。
|
||||
|
||||
2026-04-14 C2 第三刀补记:已新增 `wolai-frontend/convex/sidebar.ts`,把页面列表、回收站、Mindmap、媒体、表格等数据集收口成单个 `sidebar.datasetList` 主查询;`src/lib/server/sidebar-data.ts` 与 `src/hooks/use-convex-sidebar-data.ts` 均已切换为消费这条单查询返回,再通过既有 `SidebarInitialData` 投影层驱动 UI。配合 `src/lib/sidebar-data.test.ts` 的契约冻结、`src/lib/file-tree/rows.test.ts` 的文件树行语义验证,以及定向 `eslint`,当前可确认文档树、文件树、回收站双 tab 依旧沿用原有前端投影逻辑,没有因数据源切换而改变语义。
|
||||
2026-04-15 C2 第四刀补记:`/api/sidebar` 现已从“先直跑 Convex helper,再额外挂 meta”推进为真实 Rust query transport。当前 route 会先执行 `buildDocumentQueryEnvelope(name=\"sidebar.dataset.list\") -> resolveRustBridgeQueryPlan -> executeRustBridgeQueryTransport`,再把 `sidebar:datasetList` 的结果投影回 `SidebarInitialData`;这意味着 Sidebar API 主链已经真正进入 Rust runtime/bridge,而不再只是挂一个 envelope 名字。
|
||||
|
||||
### C3 BlockNote 正文保存
|
||||
|
||||
- [x] 盘点正文保存链路,锁定 `blocknote-editor.tsx`、`schema.ts`、文档保存 API 当前入口。
|
||||
- [x] 先把正文保存切成“前端快照采集”和“Rust command 提交”两个边界。
|
||||
- [x] 为正文保存定义最小协议对象,至少包含 `page_id`、`workspace_id`、`revision`、`actor`、`source`、block 快照、冲突检测字段。
|
||||
- [x] 先接入低风险保存模式,例如显式保存或节流保存,不先处理复杂协同细节。
|
||||
- [x] 确保正文链与页面元信息链、Sidebar 链共用同一 identity 口径,不再出现多套 page id 映射。
|
||||
|
||||
C3 验收:
|
||||
|
||||
- [x] 正文保存至少一条正式链路已经通过 Rust command 回写 Convex。
|
||||
- [x] 保存失败时可返回稳定错误模型。
|
||||
- [x] 保存成功时可回查 command log、domain event 与 trace。
|
||||
|
||||
2026-04-14 C3 第一刀收口:已为 `documents.getContent` / `documents.save` 增加独立 `content_revision` 与 `content_conflict_key`,避免标题/统计信息更新污染正文 revision;`/api/documents/content` 现会透传 `revision/conflictDetectionKey`,`BlockNoteEditor` 会在自动保存时携带 `revision`、`conflictDetectionKey`、`snapshotCapturedAt`、`blockCount`,并在成功后刷新本地保存元数据。`save-command-adapter` 现把 Convex 冲突归一为 `409 REJECTED` bridge 错误,编辑器右上角也会展示保存失败信息。当前最小验证已补 `save-contract`/`bridge` 单测,并完成定向 eslint;结果为无 error,仅保留仓库既有 warnings。
|
||||
2026-04-14 C3 第二刀补记:源码复核确认 `BlockNoteEditor` 当前通过 `useDebouncedCallback(saveContent, 800)` 以防抖自动保存作为最小低风险保存模式,没有把复杂协同状态直接并入正文写链;同时 `documents.meta/title/stats/options/save` 这些 route 都把同一个 `normalizedDocumentId` 作为 `target.pageId`,`documents.content/save` payload 也统一使用 `documentId/workspaceId`,`sidebar.dataset.list` 则以同一 `workspace_id` 作用域返回 `documents[].id` 作为页面业务 id,因此当前正文链、页面元信息链与 Sidebar 聚合链已不存在第二套 page id 映射口径。
|
||||
2026-04-14 C3 第三刀补记:在此前真实 `/api/documents/save -> /api/bridge/request|trace` smoke 已确认可回查的基础上,本轮又补了 `src/lib/documents/bridge.test.ts` 的成功路径断言,明确 `executeSaveBridgeCommand` 在 revision/conflictDetectionKey 新协议下仍会调用 `recordBridgeCommandArtifacts`,并把同一 `requestId/traceId/commandId` 暴露给回查入口。因此当前“保存成功时可回查 command log、domain event 与 trace”已具备历史 HTTP smoke 与当前单测的双重闭环。
|
||||
2026-04-14 C3 第四刀补记:`save-command-adapter` 已进一步切到与页面元信息链一致的最小运行时接缝。当前 `documents.save` 会先构造 `functionName=documents:updateContent`、`payloadJson`、`args` 组成的 bridge mutation request,再由统一执行器实际调用 Convex;这让正文保存不再长期停留在“adapter 内直接手写 `client.mutation(...)`”的临时态,同时保留现有冲突归一和落账逻辑不变。
|
||||
2026-04-15 Phase 5 第一刀补记:`search.documents`、`search.recent` 已补齐到主仓 Rust query/runtime 主链。当前 `rust/crates/core-protocol` 新增 `SearchDocuments/SearchRecent`,`storage-convex-bridge` 与 `bridge-runtime` 已支持 query name -> Convex function 映射和运行时分发;`rust/crates/index-fts` 新增 `evaluate_search_documents`,负责标题/正文/思维导图/表格/附件的召回合并、排序、高亮 snippet 与 OCR 待补队列决策。`wolai-frontend/src/app/api/search/documents/route.ts` 现仅保留参数整理、原始数据装载与 HTTP 回传,不再持有 TS 侧的核心 ranking/snippet 逻辑;`/api/search/recent` 继续只承担最近访问写入 side-effect。
|
||||
|
||||
## 6. Phase D:Mindmap 与 OnlyOffice 边界接入
|
||||
|
||||
完成目标:
|
||||
|
||||
- 保留 `mnote` 当前成熟的 Mindmap 与 OnlyOffice 前端实现。
|
||||
- 把数据边界、对象边界和回调边界逐步纳入 Rust adapter / protocol 规划,而不是复制第二套对象页壳。
|
||||
|
||||
Checklist:
|
||||
|
||||
- [x] 锁定 Mindmap 当前主组件和嵌入链路,确认 `MindmapBlock.tsx` 同时服务 BlockNote 内嵌块与独立全屏页。
|
||||
- [x] 盘点 Mindmap 数据入口,锁定 `mindmapLocalStore.ts`、`mindmapOps.ts`、`app/api/mindmap/**`、`app/mindmap/**`。
|
||||
- [x] 把 Mindmap 的前端交互状态与本体数据/ops 边界拆开,后者逐步映射到 Rust 协议层。
|
||||
- [x] 明确 `mnote-rust/app/documents/[id]/mindmap/page.tsx` 等对象页壳不进入主仓主线。
|
||||
- [x] 为 Mindmap 设计最小 adapter 目标,至少覆盖节点树、节点引用、节点操作日志和与 page/block 的绑定关系。
|
||||
- [x] 锁定 OnlyOffice 当前页面和 API 边界,确认 `src/app/onlyoffice/`、`src/app/api/onlyoffice/**`、`src/components/onlyoffice/` 的职责分工。
|
||||
- [x] 保留根目录 `src/components/onlyoffice/` 的静态资源、插件和数据目录,不做误删、不做迁移式替换。
|
||||
- [x] 把 OnlyOffice 的对象解析、签名、callback、forcesave、代理请求边界整理成 Rust adapter 的明确目标。
|
||||
- [x] 继续保持“正文只嵌文件入口,OnlyOffice 在独立页面运行”的产品形态。
|
||||
- [x] 统一 Mindmap 与 OnlyOffice 的页面标识、附件标识、页面归属和追踪字段。
|
||||
|
||||
2026-04-14 Phase D 盘点补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/mindmap-onlyoffice-boundary.md`,固定 `MindmapBlock.tsx` 与独立全屏页共用同一核心组件、`mindmapLocalStore.ts`/`mindmapOps.ts`/`app/api/mindmap/**` 的数据与 ops 边界,以及 OnlyOffice 的 `page -> client -> sign/proxy/callback/forcesave` 职责分层。文档同时明确 `MediaBlock` 仅作为 Office 附件入口、`/onlyoffice` 继续作为独立编辑页面,且历史仓中的对象页壳与第二套 sidebar 只保留为参考实现。
|
||||
2026-04-14 Phase D 收口补记:已把 Mindmap API 与组件侧统一到与 OnlyOffice 对齐的业务标识口径。当前 Mindmap 统一使用 `pageId=documentId`、`attachmentId=mindmapId`、`workspaceId` 作为页面归属,并在 `/api/mindmap/**` 返回稳定的 `requestId/traceId` 元信息;OnlyOffice 继续使用 `documentId + assetId` 作为页面/附件标识,因此两条链后续接 Rust adapter 时不再需要第二套 page/attachment 映射。
|
||||
2026-04-14 Phase D 浏览器回归补记:已新增 `/mnt/Data1T/mnote/scripts/task021-mindmap-ui-regression.js` 并在真实本地实例 `http://127.0.0.1:3001` 上执行。脚本使用当前共享的 `MindmapBlockView` 全屏入口 `/mindmap/[docId]/[mindmapId]`,验证页面 `data-page-id/data-document-id/data-attachment-id/data-mindmap-id/data-workspace-id` 元信息、工具栏与“大纲”侧栏渲染、子节点新增与删除后的持久化、以及 `/api/mindmap/**` 返回的 `requestId/traceId` 会同步回 DOM。考虑到内嵌块与独立页共用同一核心组件,这轮浏览器回归可视为覆盖当前共享交互/保存内核,实跑未见退化。
|
||||
2026-04-15 Phase D OnlyOffice callback 收口补记:已为 `OnlyOffice callback` 新增最小命令 `media.assets.replace_storage`,同步补齐 `rust/crates/core-protocol` 的 `ReplaceMediaAssetStorage`、`rust/crates/storage-convex-bridge` 的 command name -> Convex mutation 映射,以及主仓 `buildDocumentBridgeMutationRequest` 的运行时接缝。`src/app/api/onlyoffice/callback/route.ts` 现保留下载文件、上传到 Convex Files 获得 `storageId` 的现有流程,但最终写回已改为经 `buildDocumentBridgeContextWithActor -> buildDocumentCommandEnvelope -> executeMediaAssetWritebackBridgeCommand` 进入统一 bridge 边界,再调用 `api.mediaAssets.replaceStorageFromUpload`。配套 `src/app/api/onlyoffice/callback/route.test.ts`、`src/lib/documents/bridge.test.ts`、Rust 单测与 `scripts/task022-onlyoffice-ui-regression.js` 已通过,确认 `storage_id` 在真实浏览器里继续发生变化。
|
||||
|
||||
Phase D 验收:
|
||||
|
||||
- [x] Mindmap 与 OnlyOffice 的前端界面仍以 `mnote` 当前实现为主,没有引入第二套主壳。
|
||||
- [x] Mindmap 的节点/操作边界与 OnlyOffice 的签名/callback/forcesave 边界都已进入统一规划。
|
||||
- [x] `src/components/onlyoffice/` 保持可用且未被误删。
|
||||
- [x] `adapter-onlyoffice`、`adapter-mindmap` 仍作为后置实现项,而不是本阶段强行复制进主线。
|
||||
|
||||
## 7. Phase E:历史收口与单仓执行统一
|
||||
|
||||
完成目标:
|
||||
|
||||
- `mnote-rust` 正式退出主产品角色。
|
||||
- `mnote` 主仓成为唯一启动、保存、规划和验证入口。
|
||||
|
||||
Checklist:
|
||||
|
||||
- [x] 统一团队口径:主产品仓只有 `/mnt/Data1T/mnote`,`/mnt/Data1T/mnote-rust` 只保留为历史参考和资产来源。
|
||||
- [x] 把所有新的设计、执行清单、架构说明优先写入 `/mnt/Data1T/mnote/design/` 与 `/mnt/Data1T/mnote/rust/design/`。
|
||||
- [x] 复查仓库脚本和说明文档,去掉“先进 `mnote-rust` 再启动”的旧叙事。
|
||||
- [x] 统一根目录脚本入口,让仓库级脚本只从 `/mnt/Data1T/mnote/scripts/` 发起,再按需调用 `cargo --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml ...`。
|
||||
- [x] 对仍需保留的 `mnote-rust` 资料按“核心规范 / 历史阶段 / 参考实现 / 错误方向”分类,避免后续误复制。
|
||||
- [x] 把已确认不应主线保留的对象页壳、diagnostics 页、smoke 页继续留在历史仓,不进入主仓实现。
|
||||
- [x] 对主仓内新增的 Rust 目录建立最小维护约定,明确谁负责 workspace、谁负责 bridge、谁负责接入链。
|
||||
- [x] 重新审查 `ARCHITECTURE.md`、`AGENTS.md`、`rust-kernel-backport-plan.md` 与本 checklist,保证四者口径一致。
|
||||
- [x] 固定“哪些目录默认不动”的硬边界,特别是 `wolai-frontend/`、`wolai-backend/`、`infra/convex/`、`src/components/onlyoffice/`。
|
||||
|
||||
Phase E 验收:
|
||||
|
||||
- [x] 后续协作默认只进入 `mnote` 主仓规划和开发。
|
||||
- [x] 主仓文档和脚本不再把 `mnote-rust` 叙述为主执行入口。
|
||||
- [x] 历史仓的保留范围、参考价值和禁止误复制范围都已固定下来。
|
||||
|
||||
2026-04-14 Phase E 收口补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-single-repo-maintenance-boundary.md`,统一记录主仓执行入口、历史仓资料分类、禁止误复制清单与 workspace/bridge/接入链责任面;同时已复查根 `package.json` 与 `scripts/desktop-hot.js`,确认仓库级脚本仍只从 `/mnt/Data1T/mnote/scripts/` 发起,且 `ARCHITECTURE.md` 已移除把 `mnote-rust` 写成未来执行承载面的表述。
|
||||
|
||||
## 8. 发布前总审计(跨阶段)
|
||||
|
||||
- [x] 为 `/mnt/Data1T/mnote/rust/` 补基础验证矩阵,至少覆盖 `cargo metadata`、`cargo check`、必要 crate 单测。
|
||||
- [x] 为 bridge 入口补集成 smoke,验证最小查询、最小写入、日志生成、事件生成和错误返回。
|
||||
- [x] 为文档页元信息、Sidebar、BlockNote 保存链补端到端回归,确认 UI 未因为协议层切换而退化。
|
||||
- [x] 为 Mindmap 补交互回归,重点验证内嵌块、独立页、数据保存、节点操作和工具栏/侧栏行为。
|
||||
- [x] 为 OnlyOffice 补回归,重点验证签名、代理、callback、forcesave、文档打开和静态资源可用性。
|
||||
- [x] 检查主仓启动路径,确保开发者只需进入 `/mnt/Data1T/mnote` 就能完成前端、后端、Rust、OnlyOffice 相关联调。
|
||||
- [x] 检查保存口径,确认页面、块、文档、索引的最终真相仍然落在 Convex,而不是被临时缓存目录劫持。
|
||||
- [x] 检查 `trace_id`、`request_id`、`workspace_id`、`page_id` 在前端、bridge、Convex、日志中的一致性。
|
||||
- [x] 对本次回迁引入的所有新目录和新文档做一次清点,确认没有误带入 `mnote-rust` 的历史噪音。
|
||||
- [x] 为统一观测面补正式 Rust 能力面,至少包含 `bridge_request_get`、`bridge_trace_get`、`bridge_command_get`、`event_replay`、`index_rebuild` 这组 query/job/tool,并确认 Web 回查入口不再私有直连。
|
||||
|
||||
2026-04-14 发布前审计补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-backport-audit-inventory.md`,清点主仓 `rust/` 已并入的 workspace/crates/设计文档、本轮新增的根 `design/` 文档,以及当前仍未并入主线的 `adapter-*`、`mnote-cli`、`bridge/scripts/fixtures/tests` 目录。文档同时核对了 `package.json`、`scripts/desktop-hot.js` 与 `AGENTS.md` 的主仓启动口径,确认开发者只需进入 `/mnt/Data1T/mnote` 即可找到前端、后端、Rust 与 OnlyOffice 的联调入口。
|
||||
- 2026-04-15 task-034 补记:已在 `rust/crates/core-protocol` 增补 `GetBridgeRequest/GetBridgeTrace/GetBridgeCommand` 以及 `bridge_request_get`、`bridge_trace_get`、`bridge_command_get`、`event_replay`、`index_rebuild` 五个统一观测/恢复工具;`rust/crates/storage-convex-bridge` 已补 query name -> Convex `bridgeLogs:*` 映射;`rust/crates/bridge-runtime` 已支持这组 query/job 的 plan/result 输出,并把 `index-fts::rebuild_from_events` 暴露为正式 `index_rebuild` 恢复入口。前端 `/api/bridge/request`、`/api/bridge/trace` 已切到 `buildDocumentQueryEnvelope -> resolveRustBridgeQueryPlan -> executeRustBridgeQueryTransport` 主链,同时支持按 `commandId` 过滤与统一排序返回;`src/lib/documents/bridge-log.ts` 也已把命令日志/领域事件状态显式化,为后续失败态、冲突态与补偿落账提供稳定边界。配套验证已通过全量 `cargo test --manifest-path rust/Cargo.toml` 与 bridge 定向 eslint。
|
||||
- 2026-04-15 OnlyOffice 升级与实跑补记:已把 `8082` 文档服务从旧仓 `mnote-rust/infra/onlyoffice/docker-compose.yml` 迁回当前主仓 `/mnt/Data1T/mnote/infra/onlyoffice/docker-compose.yml`,并升级到 `onlyoffice/documentserver:9.3.1`。同时修复了 `/onlyoffice/plugins/*` 被 middleware 重定向到 `/auth` 导致自定义插件桥无法 ready 的问题,为 `wolai-frontend/public/onlyoffice/plugins/agent-tools/` 补齐非可视插件配置与 `plugins.js` 加载。最终 `scripts/task022-onlyoffice-ui-regression.js` 已在真实浏览器中通过,覆盖文档打开、`oo_insert_text` 插件调用、`同步保存`、callback 写回以及 `storage_id` 刷新变化闭环。
|
||||
- 2026-04-15 OnlyOffice callback bridge 补记:本轮在复跑 `scripts/task022-onlyoffice-ui-regression.js` 前,曾因 `/auth` 快速登录触发 `POST /api/auth -> Could not find public function for 'auth:signIn'` 导致浏览器脚本卡在登录页;已通过 `cd /mnt/Data1T/mnote/wolai-frontend && pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping` 重新注册 Convex functions 后恢复。恢复后同一浏览器脚本再次通过,确认新接入的 `media.assets.replace_storage` bridge 命令没有破坏 OnlyOffice 打开、插件桥、forcesave、callback 与 `storage_id` 更新闭环。
|
||||
- 2026-04-14 浏览器实跑补记:`task-019-document-ui-regression.js` 已在真实浏览器中覆盖“首页进入文档页 -> Sidebar 可见 -> 修改标题 -> 修改 BlockNote 正文 -> 等待保存成功 -> 刷新后仍保留”的最小闭环。运行前曾因本地 Convex 实例缺少 `workspaces:ensureDefaultWorkspace` 导致首页 `500`,本轮已通过 `pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping` 重新注册函数后恢复;最终浏览器脚本通过,且临时页面已清理。
|
||||
- [x] 对以下禁止事项做最终复查:不双仓并行、不跨仓链接、不复制第二套产品前端壳、不把对象页壳/diagnostics/smoke 页带入主线、不散落多个 Rust 源码根。
|
||||
- [x] 产出最终 cutover 文档,按能力域列清哪些 route 已仅剩 transport,哪些旧 TS 执行面必须继续迁移或后续删除。
|
||||
- [ ] 以“单仓路径可启动、可保存、可验证、可继续演进”作为发布前收口标准。
|
||||
|
||||
2026-04-14 实跑记录:已重新执行 `cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1`、`cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml`、`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-domain`、`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocol`、`cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p storage-convex-bridge`,均通过;其中 `cargo metadata` 已再次确认 workspace members 固定为 `core-domain`、`core-protocol`、`event-log`、`storage-convex-bridge`、`index-fts` 五个 crate。
|
||||
2026-04-14 源码审计补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/release-readiness-source-audit.md`。该文档基于当前 route、adapter、Convex bridgeLogs 与定向测试,确认 bridge 入口已经覆盖最小查询/写入/日志/事件/错误返回闭环;确认正文、页面元信息、块补丁与 OnlyOffice 附件写回的最终真相仍然落在 Convex mutation;确认 `trace_id`、`request_id`、`workspace_id`、`page_id` 在 route、bridge、Convex 日志与回查入口之间使用统一口径;并完成“不双仓并行、不跨仓链接、不复制第二套前端壳、不把 diagnostics/smoke 页带入主线、不散落多个 Rust 源码根”的源码级复查。
|
||||
2026-04-15 task-035 补记:已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`,把主仓当前 TS 执行面按 `RUST_OWNER / TS_TRANSPORT_KEEP / TS_COMPAT_PENDING / TS_LEGACY_DELETE` 四类状态完成盘点。文档明确了页面、块、查询聚合、AI、Mindmap、OnlyOffice 的当前归属,也明确了 `documents/create-child`、`documents/embed`、`documents/empty-trash`、`documents/purge`、`documents/template`、`mindmap-trash/empty`、`mindmap-ai/**` 与 `ai-agent` 非 Rust 核心工具面属于 Phase 8 前必须继续处理的旧面;同时为“何时允许宣布 Rust 成为唯一业务执行平面”补齐了四组 gate。
|
||||
2026-04-15 task-040/task-042/task-043/task-044 补记:AI 非 `doc_*` 核心工具中的 `search_web`、`image_read`、`slash_run` 已完成第一批 Rust Tool runtime cutover,`ai-agent/run` 不再保留这些工具的 TS 真执行兜底;`bridge-log/runtime` 已补齐统一失败态、冲突态与补偿态的第一批状态闭环,并覆盖页面主写链与 AI/Mindmap 写链;同时已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md`,把 `documents/create-child`、`documents/embed`、`documents/empty-trash`、`documents/purge`、`documents/template`、`mindmap-trash/empty`、`builtins/**` 固定为第一批 `TS_LEGACY_DELETE`。至此 Phase 8 的文档口径已经允许在源码审计层面使用“Rust 已成为 mnote 的唯一业务执行平面;Web route 只保留 transport、auth、session、streaming、proxy 与 callback 壳”这句统一结论。
|
||||
@@ -0,0 +1,656 @@
|
||||
# [recycle] mnote 单仓收口 Rust 内核回迁计划
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 当前状态:已完成第一批 P0 crate 与核心设计文档的真实复制,复制目标目录为 `/mnt/Data1T/mnote/rust/`。
|
||||
|
||||
## 1. 结论
|
||||
|
||||
基于当前代码现状、`/mnt/Data1T/mnote-rust/design/` 的长期原则,以及你现在明确提出的要求:
|
||||
|
||||
- 不希望长期维护两个仓库
|
||||
- 不希望跨仓链接
|
||||
- 最终只希望在一个文件夹里启动和保存
|
||||
|
||||
当前最合适的路线已经明确并开始落地:
|
||||
|
||||
1. **停止把 `/mnt/Data1T/mnote-rust/` 继续当作未来主产品仓推进**
|
||||
2. **把 `mnote-rust` 的必要 Rust 内核内容真实复制进 `/mnt/Data1T/mnote/`**
|
||||
3. **最终只保留 `/mnt/Data1T/mnote/` 作为唯一主仓**
|
||||
4. **`/mnt/Data1T/mnote/wolai-frontend/` 继续承担主产品前端壳**
|
||||
5. **Rust 内核在 `/mnt/Data1T/mnote/rust/` 下统一收口**
|
||||
|
||||
一句话版:
|
||||
|
||||
> **不是双仓回接,而是单仓收口:把必要 Rust 内核复制进 `mnote`,最终只在 `/mnt/Data1T/mnote` 启动与保存。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 为什么要改成单仓复制,而不是继续双仓
|
||||
|
||||
## 2.1 先做 Rust 内核本身没有错
|
||||
|
||||
`/mnt/Data1T/mnote-rust/design/blueprint/ai-native-note-architecture-blueprint-v0.md` 与 `/mnt/Data1T/mnote-rust/design/phases/phase5/packaging-and-shell-strategy-v0.md` 已明确长期原则:
|
||||
|
||||
1. Convex 仍是主事实层
|
||||
2. Rust 负责统一协议、命令、查询、事件、索引、adapter
|
||||
3. 前端主壳继续复用成熟 React/Next
|
||||
|
||||
也就是说:
|
||||
|
||||
- “先写 Rust 内核”是对的
|
||||
- “不重写一套新前端主栈”也是对的
|
||||
|
||||
真正要调整的是载体:
|
||||
|
||||
- 不再把 `mnote-rust` 作为第二个长期主仓
|
||||
- 不再维持“一个仓写内核,一个仓跑产品前端”的长期分裂状态
|
||||
|
||||
## 2.2 双仓会持续制造启动、保存、认知和迁移成本
|
||||
|
||||
如果继续保留:
|
||||
|
||||
- `/mnt/Data1T/mnote/`
|
||||
- `/mnt/Data1T/mnote-rust/`
|
||||
|
||||
长期并行,会持续出现四类成本:
|
||||
|
||||
1. **启动成本**
|
||||
- 需要判断到底从哪个目录启动
|
||||
- 脚本、环境变量、依赖路径容易双份化
|
||||
|
||||
2. **保存口径成本**
|
||||
- 用户会天然希望“最终只有一个真实主仓”
|
||||
- 双仓天然让“哪个仓是现在的真主线”不断摇摆
|
||||
|
||||
3. **迁移成本**
|
||||
- 每做一项功能,都要先判断该落在 `mnote` 还是 `mnote-rust`
|
||||
- 这会导致团队持续在仓库边界上损耗
|
||||
|
||||
4. **认知成本**
|
||||
- 新协作者很难快速判断:
|
||||
- 哪个仓是产品主线
|
||||
- 哪个仓只是实验壳
|
||||
- 哪些文档是真约束
|
||||
|
||||
## 2.3 当前真正成熟的是 `mnote` 前端,而不是 `mnote-rust` 前端
|
||||
|
||||
当前成熟可直接承载产品面的能力主要在:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/onlyoffice/`
|
||||
|
||||
而 `mnote-rust` 当前前端更多是:
|
||||
|
||||
1. 联调壳
|
||||
2. smoke 壳
|
||||
3. 协议验证壳
|
||||
4. 部分对象页桥接壳
|
||||
|
||||
因此,单仓收口时,正确的继承关系应该是:
|
||||
|
||||
- **保留 `mnote` 前端主壳**
|
||||
- **复制 `mnote-rust` 的内核与协议成果**
|
||||
|
||||
而不是反过来复制一整套 `mnote-rust` 的 Next 前端壳。
|
||||
|
||||
---
|
||||
|
||||
## 3. 新目标架构
|
||||
|
||||
单仓收口后的目标结构应是:
|
||||
|
||||
```text
|
||||
/mnt/Data1T/mnote/
|
||||
wolai-frontend/ # 唯一主前端
|
||||
wolai-backend/ # 现有辅助后端
|
||||
infra/convex/ # 现有 Convex 基础设施
|
||||
src/components/onlyoffice/
|
||||
scripts/ # 仓库级统一启动入口
|
||||
design/ # 全局设计与总览
|
||||
rust/ # 新增:Rust 内核统一收口目录
|
||||
```
|
||||
|
||||
连接关系应变成:
|
||||
|
||||
```text
|
||||
mnote 前端
|
||||
-> mnote 内部 API / BFF / bridge
|
||||
-> rust/ 内核协议层
|
||||
-> Convex 主事实层 + Rust 事件/索引层
|
||||
```
|
||||
|
||||
这意味着:
|
||||
|
||||
1. 前端只认 `/mnt/Data1T/mnote`
|
||||
2. Rust 也只存在于 `/mnt/Data1T/mnote/rust`
|
||||
3. 启动、构建、联调都只从 `/mnt/Data1T/mnote` 发起
|
||||
|
||||
---
|
||||
|
||||
## 4. 单仓目录落位方案
|
||||
|
||||
推荐把 Rust 相关内容整体收进:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/`
|
||||
|
||||
而不要把 `crates/`、`design/`、`scripts/` 直接摊到仓库根。
|
||||
|
||||
目标结构:
|
||||
|
||||
```text
|
||||
/mnt/Data1T/mnote/
|
||||
wolai-frontend/
|
||||
wolai-backend/
|
||||
infra/convex/
|
||||
src/components/onlyoffice/
|
||||
scripts/
|
||||
design/
|
||||
rust/
|
||||
Cargo.toml
|
||||
Cargo.lock
|
||||
crates/
|
||||
core-domain/
|
||||
core-protocol/
|
||||
event-log/
|
||||
storage-convex-bridge/
|
||||
index-fts/
|
||||
bridge-runtime/ # Phase 1 最小真实执行器
|
||||
mnote-cli/ # Phase 2 已落位,先冻结 --json 协议
|
||||
adapter-onlyoffice/ # 后置按需引入
|
||||
adapter-mindmap/ # 后置按需引入
|
||||
adapter-legacy-mnote/ # 后置按需引入
|
||||
bridge/
|
||||
design/
|
||||
INDEX.md
|
||||
core/
|
||||
blueprint/
|
||||
phases/
|
||||
scripts/
|
||||
fixtures/
|
||||
tests/
|
||||
```
|
||||
|
||||
### 4.1 `rust/` 下各目录职责
|
||||
|
||||
- `rust/crates/`
|
||||
放所有 Rust workspace 成员,保持 Cargo workspace 语义集中。
|
||||
|
||||
- `rust/bridge/`
|
||||
放 Rust 侧桥接层、协议适配、生成代码、FFI/IPC glue。
|
||||
|
||||
- `rust/design/`
|
||||
放 Rust 专属设计、阶段文档、路线图。
|
||||
|
||||
- `rust/scripts/`
|
||||
放 Rust 专属构建、测试、检查、保存脚本。
|
||||
|
||||
- `rust/fixtures/` / `rust/tests/`
|
||||
放 Rust 侧测试资源与测试代码。
|
||||
|
||||
### 4.2 根目录哪些保持不动
|
||||
|
||||
以下现有目录建议明确保持不动:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/`
|
||||
- `/mnt/Data1T/mnote/wolai-backend/`
|
||||
- `/mnt/Data1T/mnote/infra/convex/`
|
||||
- `/mnt/Data1T/mnote/src/components/onlyoffice/`
|
||||
- `/mnt/Data1T/mnote/recycle/`
|
||||
- `/mnt/Data1T/mnote/scripts/`
|
||||
- `/mnt/Data1T/mnote/design/`
|
||||
|
||||
其中:
|
||||
|
||||
- `design/` 继续承担全局总览和跨系统路线说明
|
||||
- Rust 的详细阶段文档放进 `rust/design/`
|
||||
|
||||
---
|
||||
|
||||
## 5. 启动与保存口径必须怎么统一
|
||||
|
||||
## 5.1 启动口径
|
||||
|
||||
统一口径只有一个:
|
||||
|
||||
> 所有开发、构建、联调命令都从 `/mnt/Data1T/mnote` 发起。
|
||||
|
||||
执行方式:
|
||||
|
||||
1. 仓库级脚本统一保留在 `/mnt/Data1T/mnote/scripts/`
|
||||
2. Rust 命令只作为子任务存在,例如:
|
||||
- `cargo --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml ...`
|
||||
3. 不再保留“先进 `mnote-rust` 再进 `mnote`”的双仓启动方式
|
||||
|
||||
## 5.2 保存口径
|
||||
|
||||
统一口径只有一个:
|
||||
|
||||
> 页面、块、文档、任务、索引的最终保存都只认 Convex 主事实层。
|
||||
|
||||
这意味着:
|
||||
|
||||
1. 人工操作、CLI、Agent 的写入都应先进入 Rust 统一命令层,再落到 Convex
|
||||
2. Rust 的 `event-log`、`index-fts`、fixtures、本地缓存都只是派生层
|
||||
3. 文件系统只保存:
|
||||
- 静态资源
|
||||
- 附件
|
||||
- 导出物
|
||||
- 缓存
|
||||
- 测试数据
|
||||
4. 文件系统不承载主业务真相
|
||||
|
||||
---
|
||||
|
||||
## 5.3 当前已落地的首批复制结果
|
||||
|
||||
截至 2026-04-13,以下内容已经真实复制进 `/mnt/Data1T/mnote/rust/`:
|
||||
|
||||
### 已复制的 workspace 根文件
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/Cargo.toml`
|
||||
- `/mnt/Data1T/mnote/rust/Cargo.lock`
|
||||
|
||||
### 已复制的 P0 crate
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/crates/core-domain/`
|
||||
- `/mnt/Data1T/mnote/rust/crates/core-protocol/`
|
||||
- `/mnt/Data1T/mnote/rust/crates/event-log/`
|
||||
- `/mnt/Data1T/mnote/rust/crates/storage-convex-bridge/`
|
||||
- `/mnt/Data1T/mnote/rust/crates/index-fts/`
|
||||
|
||||
### 已复制的核心设计文档
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/design/INDEX.md`
|
||||
- `/mnt/Data1T/mnote/rust/design/core/01-domain-model-v0.md`
|
||||
- `/mnt/Data1T/mnote/rust/design/core/02-command-query-tool-protocol-v0.md`
|
||||
- `/mnt/Data1T/mnote/rust/design/core/03-storage-event-indexing-v0.md`
|
||||
- `/mnt/Data1T/mnote/rust/design/core/04-onlyoffice-integration-boundary-v0.md`
|
||||
|
||||
这一状态意味着:
|
||||
|
||||
1. `mnote` 主仓里已经存在可继续扩展的 Rust workspace 根
|
||||
2. P0 内核定义已经不再只存在于 `/mnt/Data1T/mnote-rust/`
|
||||
3. 后续回迁工作可以直接以 `/mnt/Data1T/mnote/rust/` 为唯一落位继续推进
|
||||
|
||||
---
|
||||
|
||||
## 6. 第一阶段应该真实复制进 `mnote` 的内容
|
||||
|
||||
子 agent 的结论一致:第一阶段应复制“定义真相和协议”的内核,而不是复制第二套产品前端。
|
||||
|
||||
## 6.1 必须复制的 crate
|
||||
|
||||
### P0:第一阶段必须复制
|
||||
|
||||
以下 crate 应真实复制到:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/crates/`
|
||||
|
||||
#### `core-domain`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/core-domain`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 领域模型
|
||||
2. 一等对象定义
|
||||
3. ID / revision / 时间 /审计基础类型
|
||||
|
||||
#### `core-protocol`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/core-protocol`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. `Command / Query / Tool` 统一协议壳
|
||||
2. actor/source/target/meta 结构
|
||||
3. `CreatePage / InsertBlock / SearchPages` 等协议模型
|
||||
|
||||
#### `event-log`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/event-log`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 命令日志
|
||||
2. 领域事件
|
||||
3. 写入后的事件生成规则
|
||||
|
||||
#### `storage-convex-bridge`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/storage-convex-bridge`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 协议到 Convex 的桥接
|
||||
2. 命令执行与回写
|
||||
3. 命令日志和事件落账
|
||||
|
||||
#### `index-fts`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/index-fts`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 可重建的索引与搜索层
|
||||
2. 事件投影
|
||||
3. page/block 搜索
|
||||
|
||||
### P1:建议第二阶段复制
|
||||
|
||||
#### `mnote-cli`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/mnote-cli`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 批处理入口
|
||||
2. 导入导出入口
|
||||
3. 内核 smoke 与排障入口
|
||||
|
||||
### P2:按需后置复制
|
||||
|
||||
#### `adapter-onlyoffice`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/adapter-onlyoffice`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. OnlyOffice 资产定位
|
||||
2. 会话定位
|
||||
3. 任务边界适配
|
||||
|
||||
#### `adapter-mindmap`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/adapter-mindmap`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 思维导图结构化 ops
|
||||
2. 节点读取与引用边界
|
||||
|
||||
#### `adapter-legacy-mnote`
|
||||
|
||||
来源:
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/crates/adapter-legacy-mnote`
|
||||
|
||||
复制后职责:
|
||||
|
||||
1. 旧逻辑兼容
|
||||
2. 迁移期桥接
|
||||
|
||||
## 6.2 必须复制的设计资产
|
||||
|
||||
建议同步复制到:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/design/`
|
||||
|
||||
### 必复制
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/design/INDEX.md`
|
||||
- `/mnt/Data1T/mnote-rust/design/core/01-domain-model-v0.md`
|
||||
- `/mnt/Data1T/mnote-rust/design/core/02-command-query-tool-protocol-v0.md`
|
||||
- `/mnt/Data1T/mnote-rust/design/core/03-storage-event-indexing-v0.md`
|
||||
- `/mnt/Data1T/mnote-rust/design/core/04-onlyoffice-integration-boundary-v0.md`
|
||||
|
||||
原因:
|
||||
|
||||
1. 这些是长期稳定规范
|
||||
2. 直接对应 `core-domain / core-protocol / event-log / storage-convex-bridge / index-fts / adapter-onlyoffice`
|
||||
|
||||
### 暂不建议第一阶段复制的设计资产
|
||||
|
||||
以下内容先留在 `mnote-rust` 作为参考,不作为第一阶段主迁移目标:
|
||||
|
||||
- `design/blueprint/**`
|
||||
- `design/phases/**`
|
||||
- `design/execution/**`
|
||||
- `design/UI/**`
|
||||
|
||||
原因:
|
||||
|
||||
1. 这些更多是阶段叙事与历史推进资料
|
||||
2. 不是必须进入主仓的长期规范
|
||||
|
||||
---
|
||||
|
||||
## 7. 第一阶段明确不应复制的内容
|
||||
|
||||
这里要明确“禁止误复制”的范围。
|
||||
|
||||
## 7.1 不应继续作为第一阶段复制目标的前端内容
|
||||
|
||||
### 不复制为主线
|
||||
|
||||
- `/mnt/Data1T/mnote-rust/app/documents/[id]/mindmap/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/documents/[id]/office/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/components/sidebar/sidebar.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/page.tsx`
|
||||
- `/mnt/Data1T/mnote-rust/app/onlyoffice/page.tsx`
|
||||
|
||||
原因:
|
||||
|
||||
1. 它们大多属于对象页壳、诊断页、smoke 页或单文件硬拼壳
|
||||
2. 不应再形成第二套产品前端主线
|
||||
|
||||
## 7.2 只能保留为参考 / smoke / 实验的内容
|
||||
|
||||
以下内容可以保留在 `mnote-rust` 参考,但不作为第一阶段复制目标:
|
||||
|
||||
1. `app/documents/[id]/mindmap/page.tsx` 里的 diagnostics 区
|
||||
2. `app/documents/[id]/office/page.tsx` 里的 diagnostics 区
|
||||
3. `app/onlyoffice/OnlyOfficeClientPage.tsx` 里的环境兼容 hack
|
||||
4. `app/page.tsx` 的 smoke 首页文案
|
||||
5. `phase7` 中已经标注为历史错误方向的文档
|
||||
|
||||
## 7.3 可复制的少量薄桥接代码
|
||||
|
||||
以下内容可以作为后续参考性复制对象,但仍不是第一阶段主目标:
|
||||
|
||||
- `components/editor/document-shell.tsx`
|
||||
- `components/editor/document-content.tsx`
|
||||
- `components/editor/blocknote-editor.tsx`
|
||||
- `hooks/use-convex-sidebar-data.ts`
|
||||
- `lib/sidebar-tree.ts`
|
||||
- `lib/file-tree/rows.ts`
|
||||
- `lib/document-embeds.ts`
|
||||
- `app/layout.tsx`
|
||||
|
||||
原因:
|
||||
|
||||
1. 这些属于宿主桥接、投影层或 provider 接线
|
||||
2. 不是完整产品前端壳
|
||||
|
||||
---
|
||||
|
||||
## 8. 单仓路线下,`mnote` 里最先该接入的 5 条能力链
|
||||
|
||||
这 5 条仍然是最值得优先打通的主线。
|
||||
|
||||
## 8.1 文档正文命令链
|
||||
|
||||
接入目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocknote-editor.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/save/route.ts`
|
||||
|
||||
目标:
|
||||
|
||||
1. 保留现有成熟 BlockNote 前端
|
||||
2. 把正文保存逐步切到 Rust command 层
|
||||
3. 让 block 操作、正文快照、stats 逐步进入统一协议
|
||||
|
||||
## 8.2 页面元信息与页面属性链
|
||||
|
||||
接入目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/documents/[id]/page.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-content.tsx`
|
||||
|
||||
目标:
|
||||
|
||||
1. 标题更新
|
||||
2. 页面选项
|
||||
3. 文档统计
|
||||
4. 页面属性变更
|
||||
|
||||
## 8.3 Sidebar 数据聚合链
|
||||
|
||||
接入目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/private-tree.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/file-tree.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/hooks/use-convex-sidebar-data.ts`
|
||||
|
||||
目标:
|
||||
|
||||
1. 保留现有 UI
|
||||
2. 逐步让数据聚合层走 Rust query / index 层
|
||||
|
||||
## 8.4 Mindmap 数据链
|
||||
|
||||
接入目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/mindmap/mindmapLocalStore.ts`
|
||||
|
||||
目标:
|
||||
|
||||
1. 保留现有成熟思维导图前端
|
||||
2. 逐步把数据读写、ops 和边界纳入 Rust adapter / protocol
|
||||
|
||||
## 8.5 OnlyOffice 边界链
|
||||
|
||||
接入目标:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/onlyoffice/`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/`
|
||||
- `/mnt/Data1T/mnote/src/components/onlyoffice/`
|
||||
|
||||
目标:
|
||||
|
||||
1. 保留现有 OnlyOffice 页面和静态资源
|
||||
2. 把对象解析、回调、签名和桥接逐步回到 Rust adapter 统一边界
|
||||
|
||||
当前补记:
|
||||
|
||||
1. `OnlyOffice callback` 已从 route 里直接调用 `api.mediaAssets.replaceStorageFromUpload`,推进到最小 `media.assets.replace_storage` bridge 命令边界。
|
||||
2. 当前主仓实现会先在 `wolai-frontend/src/app/api/onlyoffice/callback/route.ts` 下载 ONLYOFFICE 输出文件、上传到 Convex Files 获得 `storageId`,再通过 `buildDocumentBridgeContextWithActor`、`buildDocumentCommandEnvelope` 与 `executeMediaAssetWritebackBridgeCommand` 构造和执行与 `storage-convex-bridge` 对齐的运行时 request。
|
||||
3. Rust 侧已补 `core-protocol::ReplaceMediaAssetStorage` 与 `storage-convex-bridge` 的 `media.assets.replace_storage -> mediaAssets:replaceStorageFromUpload` 映射;因此 OnlyOffice 附件写回现已进入与页面元信息、正文保存一致的协议接缝,只是最终执行器仍在 TypeScript 侧落到 Convex mutation。
|
||||
|
||||
---
|
||||
|
||||
## 9. 推荐实施顺序
|
||||
|
||||
## Phase A:先把 Rust 内核真实复制进 `mnote`
|
||||
|
||||
第一阶段执行动作:
|
||||
|
||||
1. 在 `/mnt/Data1T/mnote/` 下建立 `/rust/`
|
||||
2. 复制 `P0` crate
|
||||
3. 复制 `design/core` 四份长期文档和 `design/INDEX.md`
|
||||
4. 建立新的 `rust/Cargo.toml` 与 `rust/Cargo.lock`
|
||||
5. 不动 `mnote` 主前端壳
|
||||
6. 不复制 `mnote-rust` 的第二套产品前端壳
|
||||
|
||||
当前状态:
|
||||
|
||||
- 以上动作已经完成
|
||||
- `bridge/` 已初始化最小说明目录,但 `scripts/`、`fixtures/`、`tests/` 仍未初始化
|
||||
- `mnote-cli` 已并入当前 workspace,`adapter-*` 仍未并入
|
||||
|
||||
## Phase B:在 `mnote` 中建立 Rust bridge 接口
|
||||
|
||||
执行动作:
|
||||
|
||||
1. 在 `mnote` 现有 API/BFF 层加 Rust command/query 入口
|
||||
2. 保留当前 UI,不先大改组件
|
||||
3. 先打通低风险调用链
|
||||
|
||||
当前建议的第一批 bridge 入口落位:
|
||||
|
||||
1. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/content/route.ts`
|
||||
- 作为优先读入口,后续先接 `storage-convex-bridge` 的 `read_path`
|
||||
2. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/save/route.ts`
|
||||
- 作为优先写入口,后续先接 `write_path`
|
||||
3. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/title/route.ts`
|
||||
- 作为页面标题更新的低风险写入口
|
||||
4. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/stats/route.ts`
|
||||
- 作为页面统计的低风险入口
|
||||
5. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts`
|
||||
- 作为 Sidebar 聚合读入口,后续切 Rust query / index
|
||||
6. `/mnt/Data1T/mnote/wolai-frontend/src/app/api/blocks/patch/route.ts`
|
||||
- 作为块级局部写入口,适合正文链路第二步接入
|
||||
|
||||
当前判断:
|
||||
|
||||
1. `storage-convex-bridge` crate 内已经具备 `context / validation / read_path / write_path / mapping` 的桥接骨架
|
||||
2. `mnote` 主仓已为 `documents.title.update`、`documents.stats.update`、`documents.options.update`、`documents.save` 补上与 `storage-convex-bridge::build_write_request` 对齐的最小运行时接缝,会先生成 `functionName/payloadJson/args` 形式的 bridge mutation request,再交给统一执行器落到 Convex
|
||||
3. 但主仓 API route 仍未直接调用 Rust crate,`documents.content`、`blocks.patch` 等链路也还没有切到同一层执行器,因此 Phase B 还不能视为完全关闭
|
||||
|
||||
## Phase C:先接低风险元信息,再接正文链
|
||||
|
||||
顺序建议:
|
||||
|
||||
1. 页面标题 / 页面选项
|
||||
2. Sidebar 数据聚合
|
||||
3. BlockNote 正文保存
|
||||
|
||||
## Phase D:再接 Mindmap 与 OnlyOffice
|
||||
|
||||
原则:
|
||||
|
||||
1. 前端仍然在 `mnote`
|
||||
2. 数据、ops、边界逐步切到 Rust adapter / protocol
|
||||
|
||||
## Phase E:让 `mnote-rust` 退出主产品角色
|
||||
|
||||
处理方式:
|
||||
|
||||
1. `mnote-rust` 可保留为历史参考或过渡仓
|
||||
2. 但不再承担短期产品主线
|
||||
3. 最终只保留 `/mnt/Data1T/mnote/` 作为可启动、可保存主仓
|
||||
4. 历史资料分类与主仓维护边界统一以 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-single-repo-maintenance-boundary.md` 为准
|
||||
|
||||
---
|
||||
|
||||
## 10. 最不该做的事
|
||||
|
||||
1. 不要继续把 `mnote-rust` 的 Next 前端补成完整产品前端
|
||||
2. 不要让 `mnote` 和 `mnote-rust` 长期各维护一套产品前端
|
||||
3. 不要跨仓链接代码来“假装已迁移”
|
||||
4. 不要把对象页壳、诊断页、smoke 页当作主产品实现复制进来
|
||||
5. 不要把 Rust 内容散落复制到 `mnote` 根目录多个平行源码根
|
||||
|
||||
---
|
||||
|
||||
## 11. 一句话路线判断
|
||||
|
||||
最优路线不是:
|
||||
|
||||
> 继续在 `mnote-rust` 里补前端,再想办法替换 `mnote`
|
||||
|
||||
而是:
|
||||
|
||||
> 把 `mnote-rust` 的必要 Rust 内核真实复制进 `/mnt/Data1T/mnote/rust/`,保留 `mnote` 现有成熟前端作为唯一主产品壳,最终只在 `/mnt/Data1T/mnote` 这个单仓里启动和保存。
|
||||
@@ -0,0 +1,388 @@
|
||||
# [recycle] mnote Rust 内核替换剩余目标清单
|
||||
|
||||
> 更新时间:2026-04-15
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-plan.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-phase-checklist.md`
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
|
||||
## 1. 本文目的
|
||||
|
||||
本文不再回答“Rust 内容是否已经回迁到主仓”,而是直接回答:
|
||||
|
||||
> **距离“用 Rust 内核替换原有内核,并让绝大部分功能 CLI 化、可供 AI 自主编辑”这一最终目标,我们现在还差什么。**
|
||||
|
||||
当前结论很明确:
|
||||
|
||||
- **单仓收口已经基本完成**
|
||||
- **Rust workspace 与 P0 crate 已经落位**
|
||||
- **部分前端 API 已经接入 Rust 风格协议与 bridge 接缝**
|
||||
- **但“Rust 真正成为唯一执行内核”这件事还没有完成**
|
||||
|
||||
也就是说,当前更接近:
|
||||
|
||||
> **“前端/Node 先学会说 Rust 协议”**
|
||||
|
||||
而不是:
|
||||
|
||||
> **“产品已经由 Rust 内核统一执行”**
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前已经完成的基础
|
||||
|
||||
截至目前,已经完成的只是替换前的基础设施准备:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/` 已成为主仓内唯一 Rust workspace 根。
|
||||
- `core-domain`、`core-protocol`、`event-log`、`storage-convex-bridge`、`index-fts` 已落位。
|
||||
- `rust/design/core/01~04` 核心设计文档已落位。
|
||||
- 文档内容、标题、统计、Sidebar 等链路,已经开始使用统一 envelope、`request_id`、`trace_id`、`idempotency_key` 等 bridge 元信息。
|
||||
- `command_logs`、`domain_events` 已有首批落账能力。
|
||||
|
||||
这些工作解决的是:
|
||||
|
||||
- 单仓问题
|
||||
- 协议问题
|
||||
- 目录问题
|
||||
- 第一批接缝问题
|
||||
|
||||
**它们还没有解决“原内核是否已经被 Rust 取代”的问题。**
|
||||
|
||||
---
|
||||
|
||||
## 3. 还差的核心目标
|
||||
|
||||
## 3.1 还没有形成“Rust 唯一执行内核”
|
||||
|
||||
这是当前最大的缺口。
|
||||
|
||||
虽然已有一部分 route 在构造 Rust 风格 request,但真实执行主链仍然大量停留在 `Next.js route + TypeScript + Convex client`。
|
||||
|
||||
当前仍明显属于旧执行面的代表链路包括:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/create/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/delete/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/move/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/restore/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/duplicate/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/search/documents/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/mindmap/[docId]/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/onlyoffice/*.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/media/*.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/tables/*.ts`
|
||||
|
||||
这说明目前还没有做到:
|
||||
|
||||
- 所有核心读写先进入 Rust `Command / Query / Tool` 层
|
||||
- 所有执行规则由 Rust 决定
|
||||
- Node/Next 只做 transport、auth、session、streaming、UI 适配
|
||||
|
||||
最终目标需要变成:
|
||||
|
||||
- Web route 只负责接请求、鉴权、转发、回流结果
|
||||
- Rust 负责真正的命令执行、查询聚合、约束校验、冲突处理、日志和事件生成
|
||||
|
||||
验收标准:
|
||||
|
||||
- 文档、块、Sidebar、搜索、页面树、Mindmap、OnlyOffice、媒体、表格等主链路都有 Rust 执行入口
|
||||
- 前端 route 不再手写业务规则和数据聚合
|
||||
- TypeScript 侧不再直接成为业务真内核
|
||||
|
||||
## 3.2 还没有完成“全域能力模型”的 Rust 化
|
||||
|
||||
当前 Rust workspace 只有 P0 通用内核 crate,缺的不是“再多几个通用 crate”,而是产品能力域本身还没被吸进 Rust。
|
||||
|
||||
还没有真正完成 Rust 化的能力域至少包括:
|
||||
|
||||
- 页面树与层级操作
|
||||
- 页面创建、移动、复制、删除、恢复、清空回收站
|
||||
- BlockNote block 级操作全量协议
|
||||
- 搜索与召回
|
||||
- 引用、反链、嵌入
|
||||
- 媒体与附件
|
||||
- 在线表格
|
||||
- Mindmap
|
||||
- OnlyOffice 会话、签名、回调、强制保存
|
||||
- AI 调用的写入工具面
|
||||
|
||||
当前 `core-domain` 和 `core-protocol` 更像底层骨架,但还没长成完整产品内核。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 每个产品域都有明确 Rust domain model、command、query、tool contract
|
||||
- 前端不再自行定义第二套 payload 形状
|
||||
- “页面系统”和“对象系统”不再由不同 TS route 各自发明规则
|
||||
|
||||
## 3.3 CLI 入口还没有建立起来
|
||||
|
||||
你的目标里有一条是关键约束:
|
||||
|
||||
> **绝大部分功能 CLI 化**
|
||||
|
||||
这件事当前还远未完成。
|
||||
|
||||
直接证据是:
|
||||
|
||||
- `mnote-cli` 已并入主仓 workspace,但当前还只是最小命令面与 `--json` 计划输出协议
|
||||
- `/mnt/Data1T/mnote/rust/scripts/` 还未初始化
|
||||
- `/mnt/Data1T/mnote/rust/bridge/` 已初始化最小说明目录,且 `crates/bridge-runtime` 已提供 Phase 1 最小真实执行样板
|
||||
- `/mnt/Data1T/mnote/rust/tests/`、`/mnt/Data1T/mnote/rust/fixtures/` 还未形成 CLI 驱动的验收体系
|
||||
|
||||
这意味着目前仍然缺少:
|
||||
|
||||
- 真正可执行而不止输出计划的统一 CLI 二进制入口
|
||||
- 可脚本化的命令集
|
||||
- 稳定的 stdout/stderr/json 输出协议
|
||||
- 面向 AI 的非交互调用模式
|
||||
- dry-run / plan / apply / rollback 风格能力
|
||||
|
||||
最终至少应该具备的 CLI 面包括:
|
||||
|
||||
- `page create/get/update/move/delete/restore/list`
|
||||
- `block insert/replace/move/delete/get`
|
||||
- `search query`
|
||||
- `sidebar dataset`
|
||||
- `mindmap get/put/op`
|
||||
- `onlyoffice sign/callback/forcesave/session`
|
||||
- `media upload/list/get/delete`
|
||||
- `table create/get/update`
|
||||
- `tool run <tool-name> --json`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 核心功能可以不经过浏览器完成
|
||||
- 核心功能可以稳定返回 JSON
|
||||
- shell、脚本、AI agent 都能直接调用
|
||||
- CLI 和 Web 不再各维护一套业务实现
|
||||
|
||||
## 3.4 AI 还没有真正建立在 Rust 工具面之上
|
||||
|
||||
当前已经有 AI 入口:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.tsx`
|
||||
|
||||
但这套 AI 执行仍主要建立在前端/Node 工具注册表与页面侧 bridge 上,不是建立在 Rust 原生 tool protocol 上。
|
||||
|
||||
这会带来四个问题:
|
||||
|
||||
- AI 能调用的工具面和 Web 内部实现强耦合
|
||||
- AI 与 CLI 不是同一执行平面
|
||||
- AI 写入行为缺少统一事务语义
|
||||
- AI 很难获得稳定、可审计、可回放的编辑能力
|
||||
|
||||
为了实现“AI 可自行编辑”,至少还差以下目标:
|
||||
|
||||
- Rust 提供稳定的 `Tool` 执行协议,而不是只提供 `Command/Query` 壳
|
||||
- AI 调用和 CLI 调用共享同一工具注册面
|
||||
- 每个写入工具都支持明确的目标对象、权限校验、冲突返回、审计日志
|
||||
- 支持 `validate_only`、`dry_run`、`explain_plan` 之类的安全模式
|
||||
- 支持机器可消费的错误码,而不是前端文案式错误
|
||||
|
||||
最终目标不是“AI 像用户点按钮一样绕进前端”,而是:
|
||||
|
||||
> **AI 直接调用 Rust 工具内核完成读写,Web 只是展示层。**
|
||||
|
||||
验收标准:
|
||||
|
||||
- AI agent 使用的写入工具与 CLI 使用的工具完全同源
|
||||
- AI 的每次编辑都能追踪到 command、event、trace、目标对象和 actor
|
||||
- AI 可稳定执行页面编辑、块编辑、检索、结构化改写、批处理操作
|
||||
|
||||
## 3.5 观测、审计、幂等和失败恢复还只完成了首批链路
|
||||
|
||||
现在已有 `command_logs`、`domain_events`,但仍是首批写链路覆盖,不是全域治理。
|
||||
|
||||
仍缺的能力包括:
|
||||
|
||||
- 所有命令统一落账
|
||||
- 所有失败态统一编码
|
||||
- 统一重试与幂等语义
|
||||
- 统一冲突模型
|
||||
- 统一补偿与回放
|
||||
- 统一事件重建和索引重放
|
||||
|
||||
如果没有这一层,CLI 和 AI 即使能写,也不够稳定。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 任一写操作都能查 request、trace、command、domain event
|
||||
- 幂等 key 在 CLI、AI、Web 三侧语义一致
|
||||
- 冲突、拒绝、权限不足、对象不存在等错误有统一 code
|
||||
- 可从事件或命令日志重建关键派生层
|
||||
|
||||
2026-04-15 进展补记:
|
||||
|
||||
- `rust/crates/core-protocol` 与 `bridge-runtime` 已新增 `bridge_request_get`、`bridge_trace_get`、`bridge_command_get`、`event_replay`、`index_rebuild` 这组统一观测/恢复能力;当前 `/api/bridge/request` 与 `/api/bridge/trace` 也已切到 Rust query plan + TS transport 的同一路径,不再各自直连 Convex 查询。
|
||||
- `src/lib/documents/bridge-log.ts` 已把命令日志与领域事件的状态语义显式化,支持 `pending/succeeded/failed/rolled_back` 与 `pending/committed/rejected/failed` 两套状态模型,为后续冲突、失败和补偿写回提供稳定落点。
|
||||
|
||||
当前仍未关闭的缺口:
|
||||
|
||||
- 失败态、冲突态虽然已经在页面主写链与 AI/Mindmap 写链补上第一批落账,但仍未覆盖所有对象域写链。
|
||||
- `event_replay` / `index_rebuild` 目前已成为正式命令面,但还主要停留在 runtime/工具层,尚未形成完整的持久化游标、任务调度和断点续跑体系。
|
||||
- workspace 级总览、分页、按对象范围筛选等观测 UI 仍未完善。
|
||||
|
||||
## 3.6 搜索、索引和派生视图仍在持续切换中
|
||||
|
||||
2026-04-15 进展补记:
|
||||
|
||||
- `search.documents` 已不再把核心 ranking / snippet / filter 留在 TS route。当前 `/mnt/Data1T/mnote/wolai-frontend/src/app/api/search/documents/route.ts` 只保留参数校验、原始数据装载与 HTTP 回传;标题/正文/思维导图/表格/附件的匹配合并、高亮 snippet 与 OCR 待补队列决策已进入 `rust/crates/index-fts/src/lib.rs`。
|
||||
- `search.recent` 已补齐独立 Rust query 名称,并通过 runtime 返回最近访问结果;当前保留 `/api/search/recent` 作为“打开页面后写最近访问记录”的 side-effect 接口,不与搜索召回混在一条写链里。
|
||||
- `sidebar.dataset.list` 已从“只在 route 上挂一个 Rust queryName”推进为真实 runtime query transport,`/api/sidebar` 现会先经过 Rust runtime,再调用 `sidebar:datasetList`。
|
||||
|
||||
当前仍未完全关闭的缺口:
|
||||
|
||||
- 索引重建、校验与回放命令还未落到产品主路径。
|
||||
- `src/app/(app)/layout.tsx` 的 SSR 侧边栏初始数据仍复用现有 `loadSidebarDataFromConvex` helper,没有一并切到 runtime transport。
|
||||
|
||||
更新后的验收标准:
|
||||
|
||||
- `search_web`、`image_read`、`slash_run` 这类 AI 核心工具必须保持 `RUST_OWNER`,不能回退到 TS 真执行兜底。
|
||||
- `builtins/**` 中已被 Rust 替代的服务端真入口必须进入第一批 `TS_LEGACY_DELETE`,清单以 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md` 为准。
|
||||
|
||||
- 搜索结果由 Rust query / index 层给出。
|
||||
- TS 前端只做 UI 投影,不做核心排序与召回逻辑。
|
||||
- 索引可重建、可校验、可回放。
|
||||
|
||||
## 3.7 Mindmap 和 OnlyOffice 还没有进入真正的 Rust adapter 执行层
|
||||
|
||||
现在对这两个对象域,文档上已经明确了边界,但执行层仍主要在现有 TS/Convex 逻辑。
|
||||
|
||||
现状更接近:
|
||||
|
||||
- **边界想清楚了**
|
||||
- **前端形态保住了**
|
||||
- **但 Rust adapter 还没真正接管**
|
||||
|
||||
缺口主要包括:
|
||||
|
||||
- `adapter-mindmap` 尚未并入主仓
|
||||
- `adapter-onlyoffice` 尚未并入主仓
|
||||
- Mindmap 节点操作还没有稳定的 Rust ops 协议
|
||||
- OnlyOffice 的 sign / proxy / callback / forcesave 还没统一进入 Rust 对象适配层
|
||||
|
||||
验收标准:
|
||||
|
||||
- Mindmap 的结构操作可由 CLI 与 AI 直接调用
|
||||
- OnlyOffice 的对象能力具备统一 session/asset 边界
|
||||
- 不需要依赖前端 route 才能操作这些对象
|
||||
|
||||
## 3.8 仍缺一条“从旧内核切换到新内核”的明确割接路线
|
||||
|
||||
目前已有 backport plan,也有 phase checklist,但还缺一个更硬的最终割接视角:
|
||||
|
||||
- 哪些旧 TS route 会被逐步下线
|
||||
- 哪些功能先双写、再单写
|
||||
- 哪些功能允许长期保留在前端侧
|
||||
- 哪些功能必须强制进入 Rust
|
||||
- 何时可以宣布“原内核不再是主执行面”
|
||||
|
||||
如果没有这一条,项目会长期停留在“看起来在迁移,实际上双内核并存”的状态。
|
||||
|
||||
验收标准:
|
||||
|
||||
- 列出旧执行面的退役清单
|
||||
- 每个能力域有 cutover milestone
|
||||
- 明确宣布 Rust 成为唯一业务执行平面时的准入条件
|
||||
|
||||
2026-04-15 进展补记:
|
||||
|
||||
- 本轮已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`,首次把页面系统、块系统、查询聚合、AI、Mindmap、OnlyOffice、兼容接口统一盘点为 `RUST_OWNER / TS_TRANSPORT_KEEP / TS_COMPAT_PENDING / TS_LEGACY_DELETE` 四类状态。
|
||||
- 当前“不明确”的问题已经收口为“执行尚未完成”的问题:退役清单、阶段 gate 与最终宣布口径都已写清,但旧接口的物理删除和 AI 工具面的完全统一还未完成。
|
||||
|
||||
---
|
||||
|
||||
## 4. 对最终目标的重新拆解
|
||||
|
||||
如果目标是:
|
||||
|
||||
> **Rust 内核替换原有内核,绝大部分功能 CLI 化,AI 可以自行编辑**
|
||||
|
||||
那么最终至少要同时满足下面四件事。
|
||||
|
||||
## 4.1 Rust 是唯一业务执行平面
|
||||
|
||||
要求:
|
||||
|
||||
- Web、CLI、AI 都调用同一 Rust command/query/tool 内核
|
||||
- 前端不再是业务规则主载体
|
||||
|
||||
## 4.2 CLI 是一等公民,不是调试附属品
|
||||
|
||||
要求:
|
||||
|
||||
- 大部分核心能力都能通过 CLI 完成
|
||||
- 输出稳定 JSON
|
||||
- 支持脚本化、批处理和非交互执行
|
||||
|
||||
## 4.3 AI 只是 CLI/Tool 的智能调度者
|
||||
|
||||
要求:
|
||||
|
||||
- AI 不再依赖页面私有 bridge 才能编辑
|
||||
- AI 调用的每一步都可审计、可回放、可限权
|
||||
|
||||
## 4.4 Convex 继续是事实层,但不再直接暴露产品规则
|
||||
|
||||
要求:
|
||||
|
||||
- Convex 主要承担持久化与事实保存
|
||||
- 规则、协议、工具、索引、对象适配统一收进 Rust
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议按优先级补齐的剩余里程碑
|
||||
|
||||
按最终目标倒推,接下来最应该补的不是 UI,而是下面六个里程碑。
|
||||
|
||||
### M1. 建立真实 Rust 执行入口
|
||||
|
||||
- 初始化 `rust/bridge/`
|
||||
- 让 Web route 可以调用真实 Rust 运行时,而不是只在 TS 中模拟 Rust request
|
||||
- 先覆盖 `documents.create/get/save/title/options/stats/sidebar/search`
|
||||
|
||||
### M2. 并入 `mnote-cli`
|
||||
|
||||
- 在主仓加入 CLI crate
|
||||
- 先定义稳定命令面和 JSON 输出协议
|
||||
- 让页面、块、搜索、Sidebar 至少先能命令行操作
|
||||
|
||||
### M3. 完成页面系统与块系统的 Rust 接管
|
||||
|
||||
- 页面创建、移动、删除、恢复、复制
|
||||
- block 插入、替换、移动、删除
|
||||
- 页面树与回收站
|
||||
|
||||
### M4. 完成搜索/索引/派生视图 Rust 化
|
||||
|
||||
- 把搜索、snippet、排序、Sidebar 数据集聚合切到 Rust
|
||||
- 建立索引重建与校验命令
|
||||
|
||||
### M5. 完成对象域 adapter
|
||||
|
||||
- `adapter-mindmap`
|
||||
- `adapter-onlyoffice`
|
||||
- 后续再看媒体、表格等对象域
|
||||
|
||||
### M6. 让 AI 与 CLI 共用同一 Tool 面
|
||||
|
||||
- AI 不再调用前端私有写入逻辑
|
||||
- 改为直接使用 Rust tool protocol
|
||||
- 加入 dry-run、权限、审计、回放能力
|
||||
|
||||
---
|
||||
|
||||
## 6. 一句话结论
|
||||
|
||||
当前不是“还差一点点就完成 Rust 内核替换”,而是:
|
||||
|
||||
> **我们已经完成了 Rust 内核替换前的单仓收口、协议奠基和首批接缝,但距离“Rust 真正取代旧内核,并让 CLI 与 AI 成为一等执行入口”还差一整层执行面重构。**
|
||||
|
||||
最关键的剩余目标只有三条:
|
||||
|
||||
- **把业务执行权从 TS route 真正移交给 Rust**
|
||||
- **把核心能力系统化地做成 CLI**
|
||||
- **让 AI 与 CLI 共用同一套 Rust tool 内核**
|
||||
|
||||
只要这三条没完成,就还不能说“原有内核已经被 Rust 替换”。
|
||||
@@ -0,0 +1,415 @@
|
||||
# [recycle] mnote Rust 内核替换总路线图 v1
|
||||
|
||||
> 更新时间:2026-04-15
|
||||
>
|
||||
> 关联文档:
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-plan.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-phase-checklist.md`
|
||||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-missing-targets.md`
|
||||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||||
|
||||
## 1. 目标定义
|
||||
|
||||
本路线图对应的最终目标只有一句话:
|
||||
|
||||
> **用 Rust 内核取代当前 TypeScript/Next route 主导的业务执行面,让 Web、CLI、AI 共享同一套 Rust Command / Query / Tool 内核。**
|
||||
|
||||
这里包含三个同时成立的条件:
|
||||
|
||||
- Rust 成为唯一业务执行平面
|
||||
- 绝大部分核心能力都能通过 CLI 调用
|
||||
- AI 编辑能力建立在与 CLI 同源的 Rust 工具面上
|
||||
|
||||
如果只完成其中一部分,都不能算“Rust 内核已经替换原有内核”。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前阶段判断
|
||||
|
||||
当前仓库已经完成的是:
|
||||
|
||||
- 单仓收口
|
||||
- Rust workspace 落位
|
||||
- P0 crate 与核心设计文档落位
|
||||
- 首批 bridge 协议接缝
|
||||
- 首批日志与事件落账
|
||||
|
||||
当前仓库还没有完成的是:
|
||||
|
||||
- Rust 真实执行入口
|
||||
- `mnote-cli`
|
||||
- 全域能力域建模
|
||||
- AI/CLI 共用 Tool 面
|
||||
- 旧 TS 执行面的系统性退役
|
||||
|
||||
因此当前阶段应定义为:
|
||||
|
||||
> **Phase 0 完成,Phase 1 即将开始。**
|
||||
|
||||
其中:
|
||||
|
||||
- `Phase 0` = 单仓收口 + 协议奠基
|
||||
- `Phase 1` 以后才是“真正的内核替换”
|
||||
|
||||
---
|
||||
|
||||
## 3. 总体迁移原则
|
||||
|
||||
整个替换过程必须遵守下面六条原则。
|
||||
|
||||
### 3.1 Web 不再承载业务真规则
|
||||
|
||||
Next route 可以保留 transport、auth、session、streaming、SSR/BFF 职责,但不再长期承载核心业务执行规则。
|
||||
|
||||
### 3.2 CLI 与 AI 必须共用同一执行面
|
||||
|
||||
不能出现:
|
||||
|
||||
- CLI 走一套实现
|
||||
- AI 走一套实现
|
||||
- Web 再走第三套实现
|
||||
|
||||
最终只能保留一套 Rust 内核,三种入口共享。
|
||||
|
||||
### 3.3 Convex 继续是事实层,不是业务规则层
|
||||
|
||||
Convex 继续负责主事实保存,但对象规则、命令语义、查询聚合、索引、工具协议应逐步收回 Rust。
|
||||
|
||||
### 3.4 先做执行面替换,再做旧面退役
|
||||
|
||||
不能先删旧链路再补 Rust,也不能长期停留在双内核并行。
|
||||
|
||||
正确顺序是:
|
||||
|
||||
1. 建立 Rust 执行链
|
||||
2. 双入口对齐
|
||||
3. 完成回归
|
||||
4. 退役旧 TS 业务执行逻辑
|
||||
|
||||
### 3.5 先覆盖高频主链路,再覆盖对象域
|
||||
|
||||
优先级应是:
|
||||
|
||||
1. 页面系统
|
||||
2. 块系统
|
||||
3. Sidebar / 搜索 / 索引
|
||||
4. AI 写入工具面
|
||||
5. Mindmap / OnlyOffice / Media / Table
|
||||
|
||||
### 3.6 每一阶段都必须有割接标准
|
||||
|
||||
每个阶段都要明确:
|
||||
|
||||
- 哪些功能已由 Rust 接管
|
||||
- 哪些 TS route 仍是临时面
|
||||
- 哪些旧实现可退役
|
||||
|
||||
---
|
||||
|
||||
## 4. 分阶段路线
|
||||
|
||||
## Phase 1:建立真实 Rust 执行入口
|
||||
|
||||
目标:
|
||||
|
||||
- 在主仓内建立最小 Rust bridge/runtime
|
||||
- Web route 能调用真实 Rust 执行器
|
||||
- 不再只是在 TypeScript 中构造 Rust 风格 request
|
||||
|
||||
优先覆盖:
|
||||
|
||||
- `documents.meta`
|
||||
- `documents.content`
|
||||
- `documents.save`
|
||||
- `documents.title`
|
||||
- `documents.options`
|
||||
- `documents.stats`
|
||||
- `sidebar.dataset.list`
|
||||
- `search.documents`
|
||||
|
||||
阶段产出:
|
||||
|
||||
- `/mnt/Data1T/mnote/rust/bridge/`
|
||||
- 最小 runtime executor
|
||||
- Web -> Rust -> Convex 的真实样板链
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- 至少 1 条读链和 2 条写链真实经过 Rust 执行
|
||||
- 对应 TS route 不再直接持有业务拼装逻辑
|
||||
|
||||
## Phase 2:引入 `mnote-cli` 并冻结 JSON 协议
|
||||
|
||||
目标:
|
||||
|
||||
- 把 CLI 变成一等入口
|
||||
- 定义稳定的 machine-readable 输出
|
||||
- 为后续 AI 共用工具面打基础
|
||||
|
||||
首批 CLI 面:
|
||||
|
||||
- `page`
|
||||
- `block`
|
||||
- `search`
|
||||
- `sidebar`
|
||||
- `tool`
|
||||
|
||||
阶段产出:
|
||||
|
||||
- `rust/crates/mnote-cli/`
|
||||
- 统一 exit code 约定
|
||||
- `--json` 输出契约
|
||||
- `dry-run` / `validate-only` 基础能力
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- 核心页面和块操作能脱离浏览器完成
|
||||
- CLI 与 Web 调用同一 Rust 执行面
|
||||
|
||||
## Phase 3:页面系统 Rust 化
|
||||
|
||||
目标:
|
||||
|
||||
- 页面创建、移动、复制、删除、恢复、回收站等能力收口到 Rust
|
||||
- 页面树、父子关系、排序、引用更新不再由 TS route 零散实现
|
||||
|
||||
优先覆盖:
|
||||
|
||||
- `documents.create`
|
||||
- `documents.move`
|
||||
- `documents.delete`
|
||||
- `documents.restore`
|
||||
- `documents.duplicate`
|
||||
- `documents.empty-trash`
|
||||
- `documents.copy-tree`
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- 页面生命周期操作统一走 Rust command
|
||||
- 旧 TS route 只保留 transport 包装
|
||||
|
||||
## Phase 4:块系统 Rust 化
|
||||
|
||||
目标:
|
||||
|
||||
- 把 BlockNote 正文相关的结构化编辑命令真正变成 Rust 内核能力
|
||||
- AI/CLI 可直接调用块操作,不依赖浏览器交互细节
|
||||
|
||||
优先覆盖:
|
||||
|
||||
- `blocks.get`
|
||||
- `blocks.patch`
|
||||
- `blocks.move`
|
||||
- `blocks.embed`
|
||||
- `doc_insert_blocks`
|
||||
- `doc_replace_range`
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- Rust 拥有稳定的 block ops 协议
|
||||
- Web 编辑器只负责快照采集、渲染与交互
|
||||
|
||||
## Phase 5:搜索、索引与派生视图 Rust 化
|
||||
|
||||
目标:
|
||||
|
||||
- 把搜索、排序、snippet、Sidebar 数据集聚合统一移入 Rust
|
||||
- 建立索引重建和派生视图回放能力
|
||||
|
||||
优先覆盖:
|
||||
|
||||
- `search.documents`
|
||||
- `search.recent`
|
||||
- `sidebar.dataset.list`
|
||||
- 索引重建与校验命令
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- TS route 不再做核心召回和 ranking
|
||||
- `index-fts` 真正进入产品主路径
|
||||
|
||||
2026-04-15 Phase 5 第一刀补记:`search.documents`、`search.recent`、`sidebar.dataset.list` 已补齐到主仓 Rust query/runtime 主链。`rust/crates/core-protocol` 新增 `SearchDocuments/SearchRecent` 契约,`storage-convex-bridge` 新增 query name -> Convex function 映射,`bridge-runtime` 现同时支持 query plan 输出与“携带原始 dataset 时直接在 Rust 内执行并返回 result”。其中 `search.documents` 的召回后排序、snippet、高亮、OCR 待补队列决策已迁入 `rust/crates/index-fts` 的 `evaluate_search_documents`;`/api/search/documents` route 现仅保留参数归一化、Convex 原始数据拉取与 HTTP 回传,不再持有标题/正文/思维导图/表格/附件的打分合并逻辑。`/api/sidebar` 也已改为先经 Rust runtime 生成 `sidebar.dataset.list` plan,再通过统一 query transport 调用 `sidebar:datasetList`,不再只是挂一个 queryName 元信息。
|
||||
|
||||
## Phase 6:AI 与 CLI 共用 Rust Tool 面
|
||||
|
||||
目标:
|
||||
|
||||
- 让 AI 直接调用 Rust tool protocol
|
||||
- Web 中的 AI Agent 只成为对话和流式展示层
|
||||
|
||||
能力要求:
|
||||
|
||||
- `Tool` 注册表
|
||||
- 统一权限与对象目标
|
||||
- 统一错误码
|
||||
- 统一审计
|
||||
- `dry-run` / `validate-only` / `explain-plan`
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- AI 与 CLI 调用同一 Tool 面
|
||||
- AI 编辑结果可追踪到 command、event、trace
|
||||
|
||||
2026-04-15 Phase 6 补记:已把统一观测面补进 Rust `Tool` 注册表与 `bridge-runtime`。当前 `bridge_request_get`、`bridge_trace_get`、`bridge_command_get` 三条观测查询,以及 `event_replay`、`index_rebuild` 两条恢复/重建任务,已经成为 Rust 正式能力面;`/api/bridge/request`、`/api/bridge/trace` 也已改为先经 Rust runtime 生成 query plan,再由 TS 仅做 Convex transport。后续 CLI 与 AI 若要稳定运行,必须以这组能力为统一回查/恢复前置,不再允许各入口各自手写 trace 查询与索引恢复脚本。
|
||||
|
||||
## Phase 7:对象域 adapter 接入
|
||||
|
||||
目标:
|
||||
|
||||
- 在不改变当前前端形态的前提下,把对象域执行层移入 Rust adapter
|
||||
|
||||
优先对象域:
|
||||
|
||||
- `adapter-mindmap`
|
||||
- `adapter-onlyoffice`
|
||||
- 后续再扩展 media / table
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- Mindmap 与 OnlyOffice 都可由 CLI / AI 直接操作核心对象能力
|
||||
- 前端 route 不再是对象域业务真入口
|
||||
|
||||
## Phase 8:旧内核退役与总割接
|
||||
|
||||
目标:
|
||||
|
||||
- 明确哪些旧 TS route 只剩 transport
|
||||
- 明确哪些旧业务实现可删除
|
||||
- 正式宣布 Rust 成为唯一业务执行平面
|
||||
|
||||
阶段完成标准:
|
||||
|
||||
- Web、CLI、AI 全部指向同一 Rust 内核
|
||||
- 核心域不再存在第二套业务执行实现
|
||||
|
||||
2026-04-15 Phase 8 补记:当前主仓已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md` 作为最终割接文档。后续 Phase 8 不再接受“按感觉判断是否可以退役”的说法,而统一按该文档中的四组 gate 执行:页面/块/查询主链全部 Rust 持有,对象域只剩 transport 壳,AI/CLI 共用同一 Tool 面,以及旧 TS 兼容接口完成物理退役或明确降级。
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议的切换顺序
|
||||
|
||||
为了降低风险,建议按下面顺序切换,而不是全面铺开。
|
||||
|
||||
### 批次 A:文档基础链
|
||||
|
||||
- `documents.meta`
|
||||
- `documents.content`
|
||||
- `documents.save`
|
||||
- `documents.title`
|
||||
- `documents.options`
|
||||
- `documents.stats`
|
||||
|
||||
### 批次 B:页面结构链
|
||||
|
||||
- `documents.create`
|
||||
- `documents.move`
|
||||
- `documents.delete`
|
||||
- `documents.restore`
|
||||
- `documents.duplicate`
|
||||
- `documents.copy-tree`
|
||||
|
||||
### 批次 C:块编辑链
|
||||
|
||||
- `blocks.get`
|
||||
- `blocks.patch`
|
||||
- `blocks.move`
|
||||
- `blocks.embed`
|
||||
|
||||
### 批次 D:查询聚合链
|
||||
|
||||
- `sidebar.dataset.list`
|
||||
- `search.documents`
|
||||
- `search.recent`
|
||||
|
||||
### 批次 E:AI/CLI 工具链
|
||||
|
||||
- `doc_get`
|
||||
- `doc_find`
|
||||
- `doc_insert_blocks`
|
||||
- `doc_replace_range`
|
||||
- `slash_run`
|
||||
|
||||
### 批次 F:对象域链
|
||||
|
||||
- Mindmap
|
||||
- OnlyOffice
|
||||
- Media
|
||||
- Table
|
||||
|
||||
---
|
||||
|
||||
## 6. 每阶段统一验收口径
|
||||
|
||||
无论哪个阶段,验收都应统一看下面六项。
|
||||
|
||||
### 6.1 执行入口是否真的进了 Rust
|
||||
|
||||
不是“TS 构造了 Rust 风格对象”,而是“Rust 真正执行了这条链”。
|
||||
|
||||
### 6.2 Web/CLI/AI 是否同源
|
||||
|
||||
如果一个能力还存在两套或三套实现,就不算完成。
|
||||
|
||||
### 6.3 是否具备 JSON 级输出与错误码
|
||||
|
||||
没有稳定 JSON 和错误码,就无法支撑 CLI 与 AI。
|
||||
|
||||
### 6.4 是否具备审计与回放
|
||||
|
||||
没有 command/event/trace,就无法长期稳定运行。
|
||||
|
||||
这里的“具备”不是指只落了一批日志表,而是至少同时满足:
|
||||
|
||||
- 任一写链都能回查 `request_id`、`trace_id`、`command_id`
|
||||
- 命令、事件、冲突、失败态使用统一状态语义
|
||||
- 至少有一条正式的 `event_replay` / `index_rebuild` 命令可被 CLI / AI / Web 复用
|
||||
- TS route 不再私有维护第二套排障与恢复入口
|
||||
|
||||
### 6.5 是否补了自动化验证
|
||||
|
||||
每阶段都必须至少补:
|
||||
|
||||
- Rust 单测
|
||||
- Web smoke
|
||||
- 必要时的浏览器回归
|
||||
- 对应 CLI smoke
|
||||
|
||||
### 6.6 是否明确了可退役旧面
|
||||
|
||||
必须显式标注:
|
||||
|
||||
- 哪些 TS 逻辑只剩壳
|
||||
- 哪些逻辑仍是临时态
|
||||
- 哪些代码已允许删除
|
||||
|
||||
---
|
||||
|
||||
## 7. 风险与防漂移要求
|
||||
|
||||
整个路线最容易失败的点有四个。
|
||||
|
||||
### 7.1 长期停留在“桥接完成即算完成”
|
||||
|
||||
这会导致项目永远停留在半替换状态。
|
||||
|
||||
### 7.2 CLI 迟迟不建立
|
||||
|
||||
如果不尽早建立 CLI,AI 最终还是会绕回 Web 私有逻辑。
|
||||
|
||||
### 7.3 对象域长期例外化
|
||||
|
||||
Mindmap、OnlyOffice、Media、Table 如果一直被当例外处理,最终不会形成统一内核。
|
||||
|
||||
### 7.4 旧 TS 执行面没有退役时点
|
||||
|
||||
如果不定义退役清单,旧逻辑会持续存活并反向污染新内核。
|
||||
|
||||
---
|
||||
|
||||
## 8. 一句话结论
|
||||
|
||||
这条路线不是“继续补几条 bridge”就能结束,而是要完成一次完整的执行面替换:
|
||||
|
||||
> **先把 Rust 变成真实执行器,再把 CLI 变成一等入口,最后让 AI 与 Web 共同收口到这套 Rust 内核。**
|
||||
|
||||
在这三个条件同时成立之前,都还不能宣布“Rust 内核已经替换原有内核”。
|
||||
@@ -0,0 +1,76 @@
|
||||
# [recycle] Sidebar Rust Query 目标说明
|
||||
|
||||
> 更新时间:2026-04-14
|
||||
>
|
||||
> 适用主仓:`/mnt/Data1T/mnote`
|
||||
|
||||
## 1. 当前起点
|
||||
|
||||
当前 Sidebar 仍是“同一份数据集,多处复用”的结构,但重复拼装已经先收口到共享 helper:
|
||||
|
||||
- 查询 payload / result 契约:`/mnt/Data1T/mnote/wolai-frontend/src/lib/sidebar-data.ts`
|
||||
- 服务端聚合入口:`/mnt/Data1T/mnote/wolai-frontend/src/lib/server/sidebar-data.ts`
|
||||
- API route:`/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts`
|
||||
- 实时订阅 hook:`/mnt/Data1T/mnote/wolai-frontend/src/hooks/use-convex-sidebar-data.ts`
|
||||
|
||||
当前事实:
|
||||
|
||||
- `sidebar.dataset.list` 已有稳定 payload:`{ workspace_id }`
|
||||
- `sidebar.dataset.list` 已有稳定 result:`active_workspace_id`、`workspaces`、`documents`、`trashed_documents`、`media_assets`、`trashed_media_assets`、`mindmap_assets`、`trashed_mindmap_assets`、`table_assets`、`trashed_table_assets`、`mindmap_docs`、`mindmap_asset_children`
|
||||
- `src/lib/sidebar-data.test.ts` 已对上述契约做冻结测试
|
||||
|
||||
## 2. Rust Query 最小目标
|
||||
|
||||
后续 Rust query 不直接输出 UI rows,而是只负责输出兼容 `SidebarInitialData` 的共享数据集。
|
||||
|
||||
最小目标:
|
||||
|
||||
- 输入:
|
||||
- `workspace_id`
|
||||
- 输出:
|
||||
- `active_workspace_id`
|
||||
- `workspaces`
|
||||
- `documents`
|
||||
- `trashed_documents`
|
||||
- `media_assets`
|
||||
- `trashed_media_assets`
|
||||
- `mindmap_assets`
|
||||
- `trashed_mindmap_assets`
|
||||
- `table_assets`
|
||||
- `trashed_table_assets`
|
||||
- `mindmap_docs`
|
||||
- `mindmap_asset_children`
|
||||
|
||||
## 3. 前后端边界
|
||||
|
||||
### 3.1 Rust query 负责
|
||||
|
||||
- 聚合工作区范围内页面、回收站、媒体、导图、表格的原始数据集
|
||||
- 保持字段命名与共享 contract 一致
|
||||
- 保持 `workspace_id` 作用域明确
|
||||
|
||||
### 3.2 前端继续负责
|
||||
|
||||
- `buildDocumentTree`
|
||||
- `buildVisibleRows`
|
||||
- `starred/public/shared/private/templates` 分区语义
|
||||
- `sort_order -> created_at` 排序投影
|
||||
- `doc/index.md/asset-folder/asset` 文件树行语义
|
||||
- 拖拽、剪贴板、展开折叠、回收站双 tab 等交互行为
|
||||
|
||||
## 4. 本轮明确不做的事
|
||||
|
||||
- 不复制 `mnote-rust` 的 `components/sidebar/sidebar.tsx`
|
||||
- 不引入第二套导航壳
|
||||
- 不在 Rust query 阶段直接输出前端渲染树
|
||||
- 不改变当前 Sidebar UI 结构与交互
|
||||
|
||||
## 5. 验证锚点
|
||||
|
||||
以下文件共同构成本轮 Sidebar Rust query 目标冻结点:
|
||||
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/sidebar-data.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/server/sidebar-data.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/hooks/use-convex-sidebar-data.ts`
|
||||
- `/mnt/Data1T/mnote/wolai-frontend/src/lib/sidebar-data.test.ts`
|
||||
Reference in New Issue
Block a user