Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
134 changes: 60 additions & 74 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# DeepChat 当前架构概览

本文档描述 `2026-04-20` 完成 main kernel refactor phase5 收口后的主架构。
本文档描述 `2026-05-28` 的主架构。当前目标不是再做一次全量 main-kernel rewrite,
而是维持 typed renderer-main boundary,并把新增能力接到既有 route/runtime owner 上。

## 主链路

Expand All @@ -10,111 +11,97 @@ flowchart LR
Client --> Bridge["window.deepchat / preload bridge"]
Bridge --> Contracts["shared/contracts routes + events"]
Contracts --> Routes["src/main/routes dispatcher"]
Routes --> Settings["settings handler"]
Routes --> Sessions["SessionService"]
Routes --> Chat["ChatService"]
Routes --> Providers["ProviderService"]
Settings --> Config["configPresenter"]
Sessions --> Ports["presenter-backed hot path ports"]
Chat --> Ports
Providers --> Ports
Routes --> Services["route services / handlers"]
Services --> Ports["presenter-backed ports"]
Ports --> AgentSession["agentSessionPresenter"]
Ports --> Llm["llmProviderPresenter"]
Ports --> Window["windowPresenter"]
AgentSession --> Runtime["agentRuntimePresenter"]
Runtime --> Tool["toolPresenter"]
Runtime --> SQLite["sqlitePresenter"]
Tool --> Mcp["mcpPresenter"]
Tool --> AgentTools["toolPresenter/agentTools"]
Llm --> Acp["llmProviderPresenter/acp"]
Ports --> Provider["llmProviderPresenter"]
Provider --> Acp["llmProviderPresenter/acp"]
```

主结论:

- migrated renderer boundary 先经过 `renderer/api`、`window.deepchat` 和 shared contracts,再进入 main。
- `src/main/routes/index.ts` 是 settings / sessions / chat / providers 这些 migrated path 的 typed dispatcher 和装配入口。
- 现有 presenter 仍然存在,但主要通过 `hotPathPorts` / `runtimePorts` 这样的窄 port 暴露给 route services。
- `SessionPresenter` 继续保留为 legacy 数据平面和导出边界,不再是 migrated chat hot path 的 owner。
- renderer 业务代码优先经过 `renderer/api/*Client`、`window.deepchat` 和 shared contracts。
- `src/main/routes/index.ts` 是 typed route dispatcher,并装配 settings、sessions、chat、
providers、models、config、MCP、plugins、skills、sync、browser、database security、
scheduled tasks 等 route。
- presenter 仍是 runtime owner,但 route services 只通过窄 port 或明确 client 依赖使用它们。
- `SessionPresenter` 仍保留为 legacy 数据访问、导出和兼容边界,不再是当前聊天主链路 owner。

## 模块职责

| 模块 | 位置 | 职责 |
| --- | --- | --- |
| `renderer/api` | `src/renderer/api/` | 为 settings / sessions / chat / providers 提供 typed renderer client |
| shared contracts | `src/shared/contracts/` | 维护 route registry、schema、typed event catalog |
| preload bridge | `src/preload/createBridge.ts` / `src/preload/index.ts` | 统一暴露 `window.deepchat.invoke/on` |
| main route runtime | `src/main/routes/` | typed route dispatch、settings handler、session/chat/provider services |
| presenter-backed ports | `src/main/routes/hotPathPorts.ts` / `src/main/presenter/runtimePorts.ts` | 把现有 presenter 收敛成 route service 可依赖的窄接口 |
| `renderer/api` | `src/renderer/api/` | typed renderer clients,吸收 bridge/channel 细节 |
| shared contracts | `src/shared/contracts/` | route registry、schema、typed event catalog |
| preload bridge | `src/preload/createBridge.ts` / `src/preload/index.ts` | 暴露 `window.deepchat.invoke/on` |
| main routes | `src/main/routes/` | typed route dispatch、services、handlers |
| hot path ports | `src/main/routes/hotPathPorts.ts` / `src/main/presenter/runtimePorts.ts` | route runtime 到 presenter 的最小接口 |
| `AgentSessionPresenter` | `src/main/presenter/agentSessionPresenter/` | session registry、window binding、legacy import、runtime delegation |
| `AgentRuntimePresenter` | `src/main/presenter/agentRuntimePresenter/` | 聊天 runtime、stream loop、tool interaction、message persistence |
| `ToolPresenter` | `src/main/presenter/toolPresenter/` | 工具定义聚合、调用路由、权限预检查 |
| `LLMProviderPresenter` | `src/main/presenter/llmProviderPresenter/` | provider 实例、stream state、model 管理、ACP provider helper |
| `SessionPresenter` | `src/main/presenter/sessionPresenter/` | legacy 会话数据访问、导出、历史兼容边界 |
| `AgentRuntimePresenter` | `src/main/presenter/agentRuntimePresenter/` | 聊天 loop、stream、tool interaction、message/session persistence |
| `ToolPresenter` | `src/main/presenter/toolPresenter/` | MCP tools 与本地 agent tools 聚合、权限预检查、调用路由 |
| `LLMProviderPresenter` | `src/main/presenter/llmProviderPresenter/` | provider 实例、model/runtime 管理、ACP helper、AI SDK runtime |
| `StartupWorkloadCoordinator` | `src/main/presenter/startupWorkloadCoordinator/` | startup/settings/floating 等目标的分阶段后台任务调度 |
| `RemoteControlPresenter` | `src/main/presenter/remoteControlPresenter/` | Telegram、Feishu/Lark、QQBot、Discord、WeChat iLink 远程控制 |
| `ScheduledTasksService` | `src/main/presenter/scheduledTasks/` | 一次性、每日、每周任务调度和 prompt/notify action dispatch |
| `DatabaseSecurityPresenter` | `src/main/presenter/databaseSecurityPresenter/` | SQLCipher 启用、改密、关闭、safeStorage/manual unlock |
| Spotlight search | `src/renderer/src/stores/ui/spotlight.ts` | 全局搜索、会话/消息跳转、设置导航和非破坏性 action |

## 当前分层

### 1. Renderer-main boundary
### 1. Renderer-Main Boundary

- `src/shared/contracts/routes*.ts` 与 `events*.ts` 是 migrated path 的唯一契约真源。
- `src/preload/createBridge.ts` 负责把 route invoke 和 typed event subscribe 统一暴露到 `window.deepchat`。
- `src/renderer/api/*Client.ts` 吸收 bridge 细节,组件和 store 不直接拼新的 raw channel 字符串。
- `src/shared/contracts/routes*.ts` 与 `events*.ts` 是 migrated path 的契约真源。
- `src/preload/createBridge.ts` 统一 route invoke 和 typed event subscribe。
- `src/renderer/api/*Client.ts` 是组件和 store 的默认入口。
- `src/renderer/api/legacy/**` 是唯一 legacy quarantine。当前保留 `presenters.ts`、
`presenterTransport.ts`、`runtime.ts` 三个兼容文件;新业务模块不应直接导入 legacy transport。

### 2. Main route runtime
### 2. Main Route Runtime

- `src/main/routes/index.ts` 根据 route registry 分发请求。
- settings 走 `settings handler + adapter`。
- sessions、chat、providers 分别走 `SessionService`、`ChatService`、`ProviderService`。
- `Scheduler` 统一承接 migrated chat path 上的 timeout、retry、cancel 语义。
- `SessionService`、`ChatService`、`ProviderService` 负责 migrated chat/session/provider hot path。
- `ProviderImportService` 负责外部 provider 配置扫描与应用。
- models routes 提供 model catalog、runtime list、config import/export、audio transcription。
- database security 与 scheduled tasks 已经是 typed route,renderer 通过专用 client 调用。

### 3. Presenter-backed runtime
### 3. Agent Runtime

- `createPresenterHotPathPorts()` 把 `agentSessionPresenter`、`configPresenter`、`llmProviderPresenter` 收敛成 route service 依赖的最小 port。
- `AgentSessionPresenter` 仍持有 session registry、window 绑定和 legacy import helper。
- `AgentRuntimePresenter` 继续拥有消息主循环、工具暂停恢复、消息持久化和增量 stream echo。
- `ToolPresenter`、`LLMProviderPresenter` 和 `mcpPresenter` 继续服务未迁移能力与 runtime 内部协作。
- `AgentSessionPresenter` 创建/恢复/激活 session,并把执行交给 `AgentRuntimePresenter`。
- `AgentRuntimePresenter` 拥有 stream loop、tool loop、pending input、manual/auto compaction、
message trace 和结构化消息持久化。
- `DeepChatMessageStore` 采用头表 + 结构化子表模型,并在读路径缺行时回退旧 JSON。
- 历史搜索使用 `deepchat_search_documents` 与 FTS5,FTS 不可用时回退 `LIKE`。
- Agent progress 使用 `agent-core/update_plan`、`chat.plan.updated` 和 renderer 浮层展示任务计划。

### 4. Compatibility boundary
### 4. Provider And Media Runtime

仍然保留但已降级为兼容职责的边界:
- `ModelType` 当前包含 chat、embedding、rerank、imageGeneration、videoGeneration、tts。
- OpenAI-compatible image/video generation 和 TTS 通过 model config、provider route meta、
AI SDK runtime 与消息渲染协作。
- 本地录音转写走 `ModelClient.transcribeAudio()` / `models.transcribeAudio`,由 provider runtime 完成。
- provider deeplink 与 provider config import 都会在写入前做 preview、校验、冲突处理和脱敏展示。

### 5. Compatibility Boundary

仍保留但只承担兼容职责:

- `src/main/presenter/agentSessionPresenter/legacyImportService.ts`
- 旧 `conversations/messages` 数据域,作为 import-only 与导出数据源
- `src/main/presenter/sessionPresenter/`,作为 main 内部 compatibility/data facade
- `src/main/eventbus.ts`,继续服务未迁移路径,但 migrated UI 通知优先走 typed events

## Phase 5 结论

- 本轮已经完成“边界稳定化 + 热路径减耦 + 可测试性提升”的目标。
- 当前不继续发起一次性全量 `main kernel` rewrite。
- 后续只在出现新的明确 hot path 收益时,再继续做 slice-driven typed-boundary migration。

## Post-P5 执行规则

`phase5` 收口不等于 renderer-main 已经完成单轨化。
- `src/main/eventbus.ts`,继续服务未迁移路径;migrated UI 通知优先走 typed events

当前后续工作的默认规则是:
## 防回归规则

- renderer 新功能优先走 `renderer/api/*Client` + `window.deepchat` + shared contracts
- `useLegacyPresenter()`、`window.electron`、`window.api` 只视为兼容路径,不再作为业务层默认入口
- `src/renderer/api/legacy/presenters.ts` 已退役,剩余 quarantine-only 入口固定为
`src/renderer/api/legacy/presenters.ts`
- renderer 业务模块不应再混用 typed client 与 legacy transport
- renderer legacy quarantine 目录固定为 `src/renderer/api/legacy/**`,不再允许创建第二个 quarantine 路径

单轨化的目标、阶段和 merge gate 见:

- [architecture/renderer-main-single-track/spec.md](./architecture/renderer-main-single-track/spec.md)
- [architecture/renderer-main-single-track/plan.md](./architecture/renderer-main-single-track/plan.md)
- [architecture/renderer-main-single-track/tasks.md](./architecture/renderer-main-single-track/tasks.md)

## 历史对照与防回归

- 历史架构文档见 [archives/legacy-agentpresenter-architecture.md](./archives/legacy-agentpresenter-architecture.md)
- 历史流程文档见 [archives/legacy-agentpresenter-flows.md](./archives/legacy-agentpresenter-flows.md)
- main kernel 边界回归由 `scripts/architecture-guard.mjs` 和 `docs/architecture/baselines/main-kernel-*.{md,json}` 追踪
- `scripts/architecture-guard.mjs` 负责固定 `src/renderer/api/legacy/**`、禁止业务层新增 direct legacy transport,并把 typed boundary 外的 legacy access 视为违规
- legacy agent cleanup 回归由 `scripts/agent-cleanup-guard.mjs` 追踪
- renderer-main 单轨化后续治理由 `docs/architecture/renderer-main-single-track/` 追踪
- 新 renderer-main 能力默认走 `renderer/api/*Client` + `window.deepchat` + shared contracts。
- legacy transport 只能留在 `src/renderer/api/legacy/**`,不新增第二个 quarantine 目录。
- `scripts/architecture-guard.mjs` 固定 quarantine 文件数、检测 direct legacy transport、
并读取 `docs/architecture/baselines/main-kernel-bridge-register.json`。
- `scripts/agent-cleanup-guard.mjs` 用于防止已退休 agent runtime 入口回流。

## 推荐阅读顺序

Expand All @@ -124,4 +111,3 @@ flowchart LR
4. [architecture/agent-system.md](./architecture/agent-system.md)
5. [architecture/tool-system.md](./architecture/tool-system.md)
6. [architecture/session-management.md](./architecture/session-management.md)

Loading