chore: align sqlite control plane architecture

- replace default Convex control-plane wording with Rust SQLite control-plane across architecture, AGENTS, Reasonix, and design docs

- retire root Convex functions source and deploy script into recycle while keeping explicit cloud/compat/sync-replica boundaries

- add control-plane migration guard/docs and keep CodeGraph refreshed after the SQLite control-plane cutover
This commit is contained in:
lix-2026
2026-05-22 17:45:22 +08:00
parent 531e845600
commit 47e224d419
79 changed files with 7634 additions and 2600 deletions
@@ -2,6 +2,8 @@
> 更新时间:2026-05-17
> 参考:`hermes-vscode-main` (ACP client) / `hermes-web-ui-0.5.18` (HTTP API)
>
> 2026-05-22 口径补充:本文是 ACP session runtime 增强的历史执行记录,当时曾选择根 `convex/` 作为 ACP-local runtime store。后续 `2-8` 已把默认 auth / ACP-Hermes runtime session / share / sync / AI policy 控制面替换为 Rust SQLite `control-plane`;根 `convex/` functions 源码已软删除到 `recycle/20260522-convex-runtime-retirement/convex/``scripts/run-convex-deploy.js` 已归档到同批 recycle 目录。下文中的 Convex store / 根 `convex/` 部署描述仅作为历史记录,不再是当前实现方向。
## 1. 当前状态
@@ -34,7 +36,7 @@
- mnote 自己产生的 tool audit、业务写入结果、artifact / page / tree 事实;
- 经单独架构决策确认后的 ACP 会话缓存或索引。
如果要把 mnote 的存储升级为跨 Hermes HTTP / ACP 的长期会话真源,必须先更新 `7-5` / `7-8` 的边界,而不能作为本计划的隐含前提。并且 mnote 是多用户系统,AI session 必须按用户、workspace、document 进行隔离;需要数据库时使用当前 Convex 底座,不新增 SQLite。
如果要把 mnote 的存储升级为跨 Hermes HTTP / ACP 的长期会话真源,必须先更新 `7-5` / `7-8` 的边界,而不能作为本计划的隐含前提。并且 mnote 是多用户系统,AI session 必须按用户、workspace、document 进行隔离;当前默认数据库边界已改为 Rust SQLite control-plane,不新增 Convex functions 作为默认 runtime store。
## 2. 参考实现分析
@@ -83,7 +85,7 @@
1. **会话持久化存储**
- 默认先建设 ACP-local runtime store / TTL cache,不改 Hermes HTTP 会话真相归属
- 持久化如需数据库,必须落到 Convex;不在 mnote-web 内新增 SQLite
- 持久化如需数据库,默认落到 Rust SQLite control-plane;不新增根 Convex functions 作为默认 runtime store
- 表结构先服务 `ACP_RUN_PAYLOADS` / `ACP_ACTIVE_RUNS` 的可靠生命周期,并且所有记录必须带 `userId` / `workspaceId` / `documentId` 作用域
- `sessions/messages` 如要保存完整聊天历史,必须先完成架构决策并标明只覆盖 ACP 路径还是统一覆盖 Hermes HTTP + ACP
@@ -157,20 +159,20 @@
## 4. 技术方案
### 4.0 当前 Convex 源目录口径
### 4.0 历史 Convex 源目录口径
当前仓库状态下:
- `infra/convex/` 只承载自托管 Convex backend/dashboard 的 Docker 与说明,不是 functions/schema 源目录;
- `wolai-frontend/convex/` 已不在当前工作区可读路径中,不能作为新的实现落点;
- `recycle/wolai-frontend/convex/` 只作为历史参考;
- 本轮执行在仓库根 `convex/` 建立 ACP-local runtime store 的最小 functions/schema,并让 `scripts/run-convex-deploy.js` 优先以仓库根作为 Convex CLI cwd。
- 本轮历史执行在仓库根 `convex/` 建立 ACP-local runtime store 的最小 functions/schema,并让 `scripts/run-convex-deploy.js` 优先以仓库根作为 Convex CLI cwd;当前这些源码和脚本已退役到 `recycle/20260522-convex-runtime-retirement/`
后续若要恢复完整业务 Convex functions,需要把历史 `recycle/wolai-frontend/convex/` 中仍需要的 documents/workspaces/media 等 functions 正式迁移到`convex/`,不能继续依赖已删除的 `wolai-frontend/` 路径
后续若要恢复 Convex cloud / compat source,必须先明确新的 cloud/compat 部署边界,再从 recycle 恢复必要 functions;不能把`convex/` 重新作为默认 active deploy source
### 4.1 存储方案
注意:以下结构是 Convex-backed ACP-local store 候选形状,不默认推翻 Hermes 持有聊天真相的既有边界。mnote-web 不新增 SQLite;多用户隔离字段是硬要求。
注意:以下结构是历史 Convex-backed ACP-local store 候选形状,不默认推翻 Hermes 持有聊天真相的既有边界。当前默认 store 已转向 Rust SQLite control-plane;多用户隔离字段是硬要求。
```rust
// sessions 记录
@@ -208,11 +210,11 @@ struct MessageRow {
### 4.2 现有代码改动范围
- **新增/修改** `convex/` 相关 schema / functions ACP-local session/runtime 记录、用户隔离查询、TTL 清理;`infra/convex/` 只负责自托管服务部署
- **历史项**:曾新增/修改根 `convex/` 相关 schema / functions,承接 ACP-local session/runtime 记录、用户隔离查询、TTL 清理;当前默认应改 Rust SQLite control-plane schema/API`infra/convex/` 只负责显式 cloud / compat 服务部署
- **修改** `acp_session_manager.rs` — 按架构决策写入 ACP-local 消息或只写 runtime/event 索引
- **修改** `hermes_client.rs` — 新增 session 管理 route handlers
- **修改** `routes/mod.rs` — 注册新 route
- **修改** Convex bridge / transport 调用点 — mnote-web 通过已有 Convex 底座读写 session/runtime 索引
- **修改** control-plane / compat transport 调用点 — mnote-web 默认通过 SQLite control-plane 读写 session/runtime 索引,Convex 只作为显式 legacy compat
### 4.3 与现有 bug 的关系
@@ -269,11 +271,11 @@ Phase CP2 用户体验)
### 6.2 先做后端持久化骨架
- [x] 为 ACP-local session/runtime store 设计 Convex schema,不新增 SQLite。
- [x] 在 Convex 中建 `sessions``messages` 或更小的 `runtimeRuns` / `runtimeEvents` 记录,补齐索引和权限过滤。
- 当前实现为根 `convex/schema.ts``acp_runtime_runs` / `acp_runtime_events`,以及 `convex/aiSessions.ts``upsertRuntimeRun/getRuntimeRun/listRuntimeRuns`
- [x] 历史阶段曾为 ACP-local session/runtime store 设计 Convex schema;当前默认已改为 SQLite control-plane。
- [x] 历史阶段曾在 Convex 中建 `sessions``messages` 或更小的 `runtimeRuns` / `runtimeEvents` 记录,补齐索引和权限过滤。
- 历史实现为根 `convex/schema.ts``acp_runtime_runs` / `acp_runtime_events`,以及 `convex/aiSessions.ts``upsertRuntimeRun/getRuntimeRun/listRuntimeRuns`;当前根 `convex/` 已退役
- [x]`ACP_RUN_PAYLOADS` / `ACP_ACTIVE_RUNS` 中必须保留的数据拆到持久化层或短 TTL 层。
- 当前 `create_run` 会把 ACP payload/runtime 写入 Convex内存 map 仍作为热路径保留,`stream_events` 不再消费删除 payload
- 历史阶段 `create_run` 会把 ACP payload/runtime 写入 Convex当前默认写入 SQLite control-plane,旧 Convex store 仅在显式 legacy compat 下使用
- [x]`create_run` 产出的 `sessionId``profile``traceId``runtime` 写入 `sessions` 记录。
- 当前写入目标为更小的 `acp_runtime_runs`,而不是完整聊天 `sessions` 真相表。
- [x]`stream_events` 的 ACP 路径里,按架构决策写入 `messages` 或 runtime/event 索引,不能把 Hermes HTTP 聊天真相复制进 mnote。
@@ -334,18 +336,18 @@ Phase CP2 用户体验)
### 2026-05-18
- 新增根 `convex/schema.ts``acp_runtime_runs` / `acp_runtime_events` 表和索引。
- 新增根 `convex/aiSessions.ts``upsertRuntimeRun``getRuntimeRun``listRuntimeRuns`,按 `userId` 校验 identity 作用域。
- 修改 `scripts/run-convex-deploy.js`:优先以仓库根 `convex/` 作为 Convex deploy cwd,避免继续指向已不存在的 `wolai-frontend/`
- 后续修正:根 `convex/`只包含 ACP session runtime store,不能直接覆盖完整本地 Convex 部署;`scripts/run-convex-deploy.js` 改为只有根 `convex/` 具备完整 schema 时才用根目录,否则继续使用现有完整 Convex 源。为保持本机 `3210` 部署完整,已将 `aiSessions.ts``acp_runtime_*` schema 同步到现有完整 Convex 源并重新部署
- 新增根 `convex/schema.ts``acp_runtime_runs` / `acp_runtime_events` 表和索引。(历史记录;当前已退役到 recycle)
- 新增根 `convex/aiSessions.ts``upsertRuntimeRun``getRuntimeRun``listRuntimeRuns`,按 `userId` 校验 identity 作用域。(历史记录;当前已退役到 recycle)
- 修改 `scripts/run-convex-deploy.js`:优先以仓库根 `convex/` 作为 Convex deploy cwd,避免继续指向已不存在的 `wolai-frontend/`(历史记录;当前脚本已退役到 recycle,`desktop:hot` / `dev:hot` 不部署 Convex
- 后续历史修正:根 `convex/`只包含 ACP session runtime store,不能直接覆盖完整本地 Convex 部署;`scripts/run-convex-deploy.js` 改为只有根 `convex/` 具备完整 schema 时才用根目录,否则继续使用现有完整 Convex 源。当前根 `convex/` 和该 deploy 脚本均已退役到 recycle
- 修改 `rust/crates/mnote-web/src/routes/hermes_client.rs`
- ACP `create_run` 写入 `aiSessions:upsertRuntimeRun`
- ACP `GET /client/sessions` 读取 `aiSessions:listRuntimeRuns`
- ACP `create_run` 写入 `aiSessions:upsertRuntimeRun`(历史 Convex store;当前默认 SQLite
- ACP `GET /client/sessions` 读取 `aiSessions:listRuntimeRuns`(历史 Convex store;当前默认 SQLite
- ACP `GET /client/sessions/{session_id}` 读取 runs/events
- ACP `POST /client/sessions/{session_id}/resume` 返回 Convex runtime history 恢复来源;
- ACP `DELETE /client/sessions/{session_id}``rename``auto-title` 写入 Convex store
- ACP `GET /client/sessions/search` 返回 Convex store 搜索摘要和 snippet
- ACP `stream_events` 将 SSE event 写入 `aiSessions:appendRuntimeEvent`
- ACP `POST /client/sessions/{session_id}/resume` 返回 runtime history 恢复来源;
- ACP `DELETE /client/sessions/{session_id}``rename``auto-title` 写入 runtime store
- ACP `GET /client/sessions/search` 返回 runtime store 搜索摘要和 snippet
- ACP `stream_events` 将 SSE event 写入 runtime event store
- `stream_events` 使用 clone lookup 保留 ACP payload,不再 `.remove(run_id)`
- 验证:
- `cd rust && cargo test -p mnote-web hermes_client_acp -- --nocapture`10 passed。
@@ -353,8 +355,8 @@ Phase CP2 用户体验)
- `cd rust && cargo test -p mnote-web acp_permission -- --nocapture`1 passed。
- `cd rust && cargo test -p mnote-web page_ai_uses_backend_acp_session_runtime_store -- --nocapture`1 passed。
- `cd rust && cargo test -p mnote-web acp_thought_delta_does_not_emit_message_delta -- --nocapture`1 passed。
- `node -c scripts/run-convex-deploy.js`通过
- `node scripts/run-convex-deploy.js`:部署入口已避免用根最小 `convex/` 覆盖完整本地 Convex schema`aiSessions.ts` 同步补到完整 Convex 源并部署到 `http://127.0.0.1:3210`,最终脚本验证为 `No indexes are deleted by this push`
- `node -c scripts/run-convex-deploy.js`历史验证通过;当前脚本已退役到 recycle
- `node scripts/run-convex-deploy.js`历史验证通过;当时部署入口已避免用根最小 `convex/` 覆盖完整本地 Convex schema。当前默认启动链路不再部署 Convex
- `node` 提取并 `new Function(SIDEBAR_TREE_JS)`:通过。
- `npx convex --version`1.39.1。
- `CONVEX_TMPDIR=/mnt/Data1T/mnote/.convex-tmp npx convex codegen --dry-run --typecheck try`:通过。