architecture overview - WangYajun369/ai-writing-platform GitHub Wiki
架构总览
适用版本:
1.7.0| 最后核对:2026-09-05TimeWrite(MirageInk / 智写时光)运行时为双进程模型:WebView 前端 + Rust Core。 v1.1 起 Agent 已由 Python 外部子进程迁移为 Rust 原生引擎(见 Agent 引擎架构), 不再存在独立的 Agent 进程与 9877/9876 桥接端口。
系统架构:双进程模型
TimeWrite 运行时包含 2 个进程。Rust 是唯一的数据拥有者(SQLite 独占),前端只通过 IPC 访问数据。
┌─────────────────────────────────────────────────────────────┐
│ 进程 1:WebView 前端(React 19 + TypeScript + TailwindCSS 4) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ pages/ components/ stores/ │ │
│ │ 书库/编辑器/设置 业务域组件 Zustand + Jotai │ │
│ │ └──────────────┼──────────────┘ │ │
│ │ lib/tauri-bridge.ts(唯一 IPC 入口,17 个 API) │ │
│ └───────────────────────┼───────────────────────────────┘ │
└──────────────────────────┼──────────────────────────────────┘
│ Tauri IPC(invoke / event)
┌──────────────────────────┼──────────────────────────────────┐
│ 进程 2:Rust Core(Tauri v2) │
│ ┌───────────────────────┴───────────────────────────────┐ │
│ │ commands/ 26 个模块(book/volume/chapter/snapshot/ │ │
│ │ world_card/ai/agent/io/image/window/ │ │
│ │ project/task/tag/subtask/attachment/...) │ │
│ │ service/ 业务编排:事务边界 + SQL 审计日志 │ │
│ │ repository/ 数据访问:纯 SQL,无业务逻辑 │ │
│ │ db/ r2d2 连接池 + SQLite WAL + FTS5 │ │
│ │ commands/agent/ Rust 原生 Agent 引擎 │ │
│ │ (engine/prompts/tools/memory/skills) │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
历史演进:v1.0 曾为三进程架构(Rust + Python FastAPI Agent @9877 + tiny_http Bridge @9876), v1.1 已将 Agent 引擎整体内嵌 Rust,
agent/目录与src-tauri/src/python/一并移除。
端口分配
| 端口 | 服务 | 说明 |
|---|---|---|
| 11434 | Ollama(可选) | 本地模型(AI 对话本地服务商) |
| 1420 | Vite 开发服务器 | 仅开发模式 |
原 Agent 服务(9877)与 Bridge(9876)端口已随 Python Agent 移除,不再占用。
Agent 引擎(v1.2 内嵌于 Rust)
Agent 自动化能力由 src-tauri/src/commands/agent/ 提供,无外部进程、无需 Python 环境:
| 模块 | 职责 |
|---|---|
engine.rs |
SSE 流式 ReAct 工具循环(run_skill + 任务取消),调用云端模型 API |
prompts.rs |
4 个技能(writing/analysis/research/polish)的 System Prompt + 动态场景提示 |
tools.rs |
6 个数据库工具(读章节/摘要/分页/章节列表/世界观搜索/整书上下文) |
memory.rs |
memories 表存取:CRUD、关键词检索、规则式记忆提取、旧库迁移 |
skills.rs |
IPC 命令层:execute_agent_skill / cancel_agent_skill + 记忆管理命令 |
Agent 执行时直接调用同一 Rust 进程内的 repository 层查询 SQLite(不再经 HTTP 回调),
流式输出通过 Tauri 事件 agent-stream-chunk 推送前端。详见 Agent 引擎架构。
核心设计原则
1. 关注点分离
| 层 | 职责 |
|---|---|
| 前端 | UI 渲染、用户交互、状态管理 |
| Rust 后端 | 数据持久化、业务逻辑、AI 集成(对话/RAG/Agent 引擎) |
| 桥接层 | 类型安全的 IPC 封装(tauri-bridge.ts 是唯一 invoke 入口;Agent 调用为例外,见下) |
约定例外:
useAgent.ts/AgentMemoryPanel.tsx直接invoke('execute_agent_skill')等 Agent 命令(未走tauri-bridge.ts封装),与「唯一入口」约定不一致,列为待重构项。
2. 单向数据流
用户操作 → React 组件 → Zustand Action → tauri-bridge.invoke()
→ Rust 命令 → service(事务)→ repository(SQL)→ SQLite
→ 返回结果 → 更新状态 → 重新渲染
3. 实时事件流
Rust 命令 → app.emit('ai-stream-chunk') → 前端 listen() → 更新 AI 消息
Agent 引擎 → app.emit('agent-stream-chunk') → 前端 listen() → 更新 Agent 消息(RAF 缓冲)
Rust 命令 → app.emit('debug-log') → 调试窗口 listen() → 追加日志
窗口关闭 → app.emit('agent-status-changed') → 前端 listen() → 显示退出遮罩(status=closing)
4. 数据主权
- Rust 独占写权限:所有数据库写操作必须经 Rust
- 前端零直连:前端不接触 SQL,只通过 IPC
- Agent 与数据同进程:工具调用直接走 repository 层,无跨进程回调,天然规避写锁竞争
分层设计(Rust 侧)
commands/ IPC 命令层 —— 参数校验、调用 service、返回 DTO(无 SQL)
service/ 业务编排层 —— 事务边界、业务规则、SQL 审计日志(emit_sql_log)
repository/ 数据访问层 —— 纯 SQL 操作,接受 &Connection,无业务逻辑
db/ 连接与 Schema —— r2d2 连接池、幂等迁移、FTS5 触发器、索引
各层职责边界在对应 mod.rs 注释中有明确约定,例如 repository 层「不依赖 Tauri State / AppHandle,不包含任何业务逻辑」。
数据库设计
24 张业务表 + 2 张 FTS5 虚拟表(另含 sqlite-vec 动态 chunks_vec 镜像表)
| 表 | 关键字段 | 说明 |
|---|---|---|
books |
title, author, cover_image, word_count, daily_target, outline, deleted_at | 书籍元信息,软删除 |
volumes |
book_id (FK), title, sort_order, deleted_at | 卷,软删除 |
chapters |
book_id (FK), volume_id (FK SET NULL), content_html, word_count, status, summary, outline, deleted_at | 章节,软删除 + AI 总结 |
snapshots |
chapter_id (FK), content_html, type ('auto'/'milestone'), label | 版本快照 |
world_cards |
book_id (FK), type(6 类), content_html, tags, vectorized | 世界观卡片 |
embeddings |
source_type, source_id, embedding (BLOB), model | 向量索引,UNIQUE(source_type, source_id) |
memories |
book_id, skill_type, memory_type, content, keywords, relevance_score, last_hit_at | Agent 记忆(v1.1 起并入主库;v1.6 补 last_hit_at 供过期清理) |
diaries |
diary_date (UNIQUE), content_html, word_count, keywords, created_at, updated_at | 日记(每天至多一篇) |
schedules |
schedule_date, content, done (0/1), created_at, updated_at | 旧个人日程(v1.5.0 起仅供数据迁移) |
vocab_words |
word (UNIQUE), phonetic, meanings JSON, example / example_zh, details_json(AI 精讲缓存), ease_factor / repetitions / interval_days / queue / due_at, status (learning/mastered/suspended) | 生词本 + SM-2 记忆参数(v1.4.0) |
vocab_reviews |
word_id (FK), rating (0-3), interval_days, reviewed_at | 复习日志(v1.4.0) |
projects |
name, color, icon, status(active/completed/archived), plan_start_date, plan_end_date, pinned, deleted_at | 任务项目(v1.5.0) |
tasks |
project_id (FK), title, status(todo/doing/done), priority, due_time, planned_today, completion_summary, deleted_at | 任务卡(v1.5.0) |
tags / task_tags |
标签 + 任务标签关联 | 任务标签(v1.5.0) |
task_meta |
key-value | 模块元数据 / 提醒偏好(v1.5.0) |
task_subtasks |
task_id (FK), title, done | 子任务(v1.5.0) |
attachments |
task_id (FK), file_name, file_type, local_path | 附件(v1.5.0) |
task_activity_logs |
task_id / project_id, action, summary | 操作日志(v1.5.0) |
task_templates |
name, project_id, title, priority, due_offset_days, subtask_titles | 任务模板(v1.5.0) |
project_milestones |
project_id (FK), name, status, due_date | 项目里程碑(v1.5.0) |
writing_stats |
book_id (FK, 级联删除), stat_date, words | 按日净增字数(v1.6.0,衍生展示表,不纳入备份导出) |
chapters_fts |
FTS5(unicode61) | 章节全文搜索,由 3 个触发器自动同步 |
world_cards_fts |
FTS5(unicode61) | 世界观全文搜索,由 3 个触发器自动同步 |
技术要点
- r2d2 连接池(max_size=10,超时 10s,空闲 300s,最长存活 1800s)
- 每连接
PRAGMA foreign_keys=ON; journal_mode=WAL - 幂等迁移:
safe_add_column()检测 duplicate column 后跳过;memories 表启动时自动建表 + 索引 - 软删除统一使用
deleted_at时间戳,配合回收站机制 - FTS5 由 INSERT/UPDATE/DELETE 三触发器增量维护,启动时无需重建索引
IPC 模块映射
前端 tauri-bridge.ts 暴露 17 个 API 对象,完整命令清单见 IPC 命令速查。
| API 模块 | Rust 源文件 | 功能 |
|---|---|---|
bookApi |
commands/book.rs |
书籍 CRUD + 封面 + 回收站 |
volumeApi |
commands/volume.rs |
卷管理 |
chapterApi |
commands/chapter.rs |
章节 CRUD + 自动保存 + 总结/大纲 |
snapshotApi |
commands/snapshot.rs |
版本快照 |
worldCardApi |
commands/world_card.rs |
世界观卡片 + FTS5 搜索 |
diaryApi |
commands/diary.rs |
日记按月/全部摘要、全文读写与删除 |
scheduleApi |
commands/schedule.rs |
旧个人日程按日/按月读写(v1.5.0 起仅供迁移) |
vocabApi |
commands/vocab.rs |
生词本 CRUD + SM-2 复习 + 统计(v1.4.0) |
dictApi |
commands/vocab_dict.rs |
离线词典查询 / 导入 / AI 释义(v1.4.0) |
ttsApi |
commands/tts.rs |
豆包语音合成(v1.4.0) |
aiApi |
commands/ai/ |
流式对话 + RAG + Embedding(预留)+ 总结 |
importExportApi |
commands/io/ |
导入导出 + 加密备份 |
imageApi |
commands/image.rs |
图片压缩与裁剪 |
windowApi |
commands/window/manager.rs |
独立窗口开关(8 类窗口) |
debugApi |
commands/window/{debug,validate}.rs |
调试控制台 + 数据库校验 |
systemApi |
commands/system_check.rs |
运行环境自检 |
taskCardApi |
commands/{project,task,tag,task_meta,subtask,attachment,activity,template,reminder,migrate}.rs |
任务卡·项目管理全量命令(v1.5.0) |
| Agent(组件直接 invoke) | commands/agent/skills.rs |
execute_agent_skill / cancel_agent_skill / 记忆 CRUD(4 个) |
v1.1 起原
get_agent_status/start_agent/stop_agent(启停外部 Python 进程)已移除。
Tauri 插件
| 插件 | 用途 |
|---|---|
tauri-plugin-http |
AI API 请求 |
tauri-plugin-dialog |
原生文件选择对话框 |
tauri-plugin-fs |
文件系统读写 |
tauri-plugin-shell |
Shell 命令执行 |
tauri-plugin-updater |
应用自动更新 |
tauri-plugin-deep-link |
URL Scheme 唤起(com.ukcoder.timewrite://) |
tauri-plugin-notification |
系统通知(任务卡到期 / 逾期提醒,v1.5.0) |
主题系统
基于 HSL CSS 变量实现,定义于 src/styles/theme.css。
两个独立维度:
| 维度 | 取值 | 说明 |
|---|---|---|
基础主题 theme |
light / dark / system |
system 跟随操作系统 |
护眼模式 eyeCareMode |
off / warm / green |
暖黄色 / 豆沙绿 |
CSS 类组合由两者叠加而成(.eyecare-warm、.dark.eyecare-green 等),共 6 种视觉组合。
| 关闭护眼 | 暖黄 warm |
豆沙绿 green |
|
|---|---|---|---|
亮色 light |
标准亮色 | 暖黄亮色 | 豆沙绿亮色 |
暗色 dark |
标准暗色 | 暖黄暗色 | 豆沙绿暗色 |
跟随系统(system)时基础主题由操作系统决定,再叠加护眼模式。
独立窗口系统
通过 URL 参数路由到 8 种独立窗口,窗口开关状态跨窗口共享:
| 窗口 | URL 参数 | 开关状态 |
|---|---|---|
| 世界观资料库 | ?worldwin=1 |
worldWindowOpenAtom(Jotai) |
| 版本历史 | ?historywin=1 |
historyWindowOpenAtom(Jotai) |
| 章节总结 | ?summarywin=1 |
summaryWindowOpenAtom(Jotai) |
| AI 工具箱 | ?aitoolboxwin=1 |
aiToolboxWindowOpenAtom(Jotai) |
| 调试控制台 | ?debugwin=1 |
debugWindowOpenAtom(Jotai) |
| 英语字典·生词本 | ?vocabwin=1 |
plugins/dictionary/windowState.ts(插件,v1.4.0) |
| 任务卡·项目管理 | ?taskswin=1 |
plugins/taskCards/windowState.ts(插件,v1.5.0) |
| 看日记 | ?diarybookwin=1 |
由 windowApi.openDiaryBookWindow() 打开(v1.5.0) |
components/app/AppInit.tsx 充当「窗口路由器」,根据 URL 参数决定渲染哪个窗口页面;前 5 种开关在 uiAtoms.ts,插件窗口开关在各自插件 windowState.ts,跨窗口通过 Tauri 事件同步(如 tasks-data-updated / tasks-window-closed)。
相关文档
| 主题 | 文档 |
|---|---|
| Agent 引擎(Rust 原生) | Agent 引擎架构 |
| AI 对话 / RAG / 总结 | AI 模块架构 |
| 目录结构与分层细节 | 项目结构 |
| 每个模块的实现细节 | 代码架构深度分析 |
| 全部 IPC 命令 | IPC 命令速查 |
| 已知问题与改进项 | 优化报告 |