状态管理
OpenCowork 基于 Zustand 的状态分层、持久化和边界划分。
状态管理 / State Management
OpenCowork 的渲染进程使用 Zustand + Immer 组织状态。总体思路是:
- 业务实体尽量和 SQLite 对齐
- 运行时状态留在内存或本地持久化 store
- 外部连接和配置通过专门 store 管理
- 复杂状态按域拆分,而不是堆在一个全局 store 里
核心 store / Core stores
| Store | 作用 | 持久化 |
|---|---|---|
chat-store | 项目、会话、消息、模式、工作目录、活动会话 | SQLite + IPC |
agent-store | Agent loop、工具调用、审批、子代理、usage | 本地持久化 |
task-store | 会话级任务面板 / Steps | SQLite |
plan-store | Plan Mode 的计划文件与状态 | SQLite |
team-store | Team Runtime、成员、任务、消息 | 本地持久化 + runtime JSON |
provider-store | provider / model / auth 配置 | 配置存储 |
settings-store | 全局设置、代理、语言、Web 搜索、工作目录 | settings.json |
app-plugin-store | 图像、浏览器、桌面控制插件配置 | 配置存储 |
channel-store | 消息平台插件实例、自动回复状态 | 本地持久化 |
mcp-store | MCP server 配置与连接状态 | 本地持久化 + mcp-servers.json |
cron-store | Cron jobs、run history、日志 | SQLite |
ssh-store | SSH groups、connections、远程上下文 | 本地持久化 + SQLite |
resources-store | agents / commands / prompts / skills catalog | IPC + filesystem |
goal-store | Session goal / budget / progress | SQLite |
辅助 store / Supporting stores
还有一些专门的状态 store,用来承载局部 UI 或辅助流程:
ui-store:界面布局、右侧面板、浏览器面板、预览面板、模式切换notify-store:通知窗口状态terminal-store:终端会话状态git-store:Git 相关状态draw-store/image-edit-store:生成与编辑图像状态translate-store:翻译工作流状态background-session-store:后台会话状态input-draft-store:输入框草稿quota-store:用量或额度提示
持久化方式 / Persistence
常见组合有三种:
- SQLite:适合会话、消息、任务、计划、Cron、SSH、Wiki、Goal 这类可查询业务数据。
- ipcStorage / configStorage:适合配置类、跨窗口同步类状态。
- 纯内存:适合短生命周期 UI 状态。
create<State>()(
persist(
immer((set, get) => ({ /* ... */ })),
{
name: 'store-name',
storage: createJSONStorage(() => ipcStorage)
}
)
)状态边界 / State boundaries
| 边界 | 原则 |
|---|---|
| 会话实体 | 由 chat-store 和数据库同步,避免单纯靠内存 |
| 运行态 | agent-store 保留流式文本、工具调用、审批与子代理状态 |
| 外部连接 | channel / MCP / SSH 各有独立 store |
| 配置 | settings-store、provider-store、app-plugin-store、channel-store |
| 视图 | ui-store 处理布局和面板,不承担业务逻辑 |
你在代码里会看到什么 / What to expect in code
- Store 通常只做单一职责。
- 复杂动作会分成
load / update / clear / sync几组方法。 - 很多 store 会用 IPC 做“写入后落盘”,但不会阻塞 UI。
- 业务层尽量依赖 store 暴露的方法,而不是直接读写底层存储。