-
released this
2026-07-21 17:01:51 +08:00 | 2 commits to master since this releasev0.3.13 — 任务管理系统重构
概述
本次版本聚焦于详情栏 Tasks 面板、task_manager 工具、todo_write 工具三者的深度审查与重构。
通过源码级分析发现:todo_write 工具近乎零价值(无 UI 消费方、AI 无引导、clearSession 死代码)、task_manager 与 Tasks 面板数据流单向(Agent 写入后 UI 不刷新)、IPC 层缺越权防护(UPDATE/DELETE 无 session_id 校验)。本次重构系统性解决了这些问题。
工具数量变化:30 → 29(删除 todo_write)
修改文件:13 个(+114 / -280)
无破坏性数据变更:tasks 表 schema 不变,旧数据完全兼容。
一、问题背景与根因分析
1.1 详情栏 Tasks 面板
定位:DetailPanel.tsx 第 3 个 Tab,渲染 TaskList.tsx(386 行完整 CRUD 组件)。
数据源:SQLite
tasks表,通过 IPCtasks:list/create/update/delete读写。实际价值:✅ 有价值 — 提供用户主动管理任务的 UI。
致命缺陷:⚠️ 数据流单向 — TaskList 只在 3 种场景刷新(会话切换、用户主动 CRUD、组件 mount),没有任何 IPC 事件订阅。Agent 通过 task_manager 工具写入任务后,用户必须手动切到 Tasks Tab 才能看到变化。
1.2 task_manager 工具
定位:task-manager.ts — SQLite 持久化任务管理,6 种操作(create/update/list/complete/delete/get)。
与 Tasks 面板的关系:共享同一张
tasks表,但走两套独立代码路径:- Agent → task-manager.ts → DB
- UI → handlers.ts → DB
两套 CRUD 重复实现且行为不一致:
- ID 生成:工具用
task_${nanoid(12)},IPC 用task_${Date.now()}_${Math.random()} - 越权保护:工具 UPDATE/DELETE 都带
AND session_id = ?,IPC 层没有 - order_idx 处理:工具计算
MAX(order_idx)+1,IPC 用默认 0
AI 自动操作:❌ 否。System Prompt 完全工具无关,没有引导 AI 在复杂任务中调用 task_manager。
1.3 todo_write 工具
定位:todo.ts — 进程内静态 Map(按 sessionId 隔离),LRU 淘汰(max 50 sessions),5 种操作(create/update/list/complete/clear)。
与其他组件的联动:❌ 完全孤立。
- 不写 DB → Tasks 面板看不到
- 无 IPC 事件 → 前端无任何消费方
- 全项目 grep TodoWriteTool 外部调用 → 零匹配
致命问题:⚠️
clearSession是死代码 — todo.ts:81 定义了static clearSession(sessionId),注释说"供外部清理,如会话结束时",但全项目没有任何外部调用方。用户删除会话时,对应 TODO 内存不会被立即释放(只能等 LRU 触发淘汰),潜在内存泄漏。AI 自动操作:❌ 否。同样无 System Prompt 引导。
实际价值:❌ 近乎零价值 — 设计初衷是"会话内临时思考拆解",但:
- AI 不主动调用 → 数据永远为空
- 即使 AI 调用了 → 用户看不到(无 UI)
- 应用重启 → 全部丢失
- 与 task_manager 功能高度重叠 → LLM 难以判断何时用哪个
1.4 System Prompt 引导缺失
context-builder.ts 构建的 System Prompt 完全工具无关。全项目搜索
(use todo_write|call task_manager|复杂任务|分解|拆解|record progress)在 prompts 目录下零匹配。两个工具完全依赖 LLM 根据工具 description 字段自行判断是否使用 — 实测中 LLM 极少主动调用。
二、修复清单(5 项)
P1(立即修复):IPC 层 tasks:update/delete 补 session_id 越权防护
问题:IPC handler 的 UPDATE/DELETE 只按
id操作,没有AND session_id = ?,理论上恶意渲染进程可跨会话改任务。修复:
- handlers.ts —
tasks:update和tasks:delete签名补sessionId参数,WHERE 子句补AND session_id = ? - preload.ts — 桥接层
update/delete传 sessionId - global.d.ts — 类型签名补 sessionId
- TaskList.tsx — 调用方传 sessionId
验证点:构造跨会话 update/delete 请求 → 应返回失败或 0 rows affected。
P2(短期优化):task_manager 写入后广播 task:changed 事件 + TaskList 订阅刷新
问题:Agent 通过 task_manager 工具创建/更新任务后,UI 不会自动刷新,用户体验割裂。
修复(四点链路):
- 工具层注入回调:task-manager.ts — TaskManagerTool 构造函数新增
onTaskChanged?: (sessionId: string) => void回调参数;新增notifyChanged()方法;在 create/update/complete/delete 4 处写操作末尾触发 - 主进程广播:main.ts — 注册工具时传入回调,通过
BrowserWindow.getAllWindows().webContents.send('task:changed', sessionId)广播事件 - preload 暴露订阅:preload.ts — 新增
onTaskChanged(callback)方法,返回 unsubscribe 函数 - TaskList 订阅刷新:TaskList.tsx — 新增 useEffect 订阅,收到事件后判断 sessionId 是否匹配,匹配则
loadTasks(sessionId)
关键设计决策:工具层不直接依赖 Electron,通过回调注入保持分层清晰。
验证点:Agent 调 task_manager 创建任务 → Tasks 面板应自动刷新显示新任务。
P3(中期决策):删除 todo_write 工具
理由:
- 与 task_manager 功能重叠
- 无 UI 消费方
- AI 无引导
- clearSession 是死代码
- 应用重启数据全丢
清理范围:
- 删除 todo.ts 文件(244 行)
- 清理 index.ts 导出
- 清理 main.ts import 和注册
- 清理 permissions.ts 权限策略
- 更新 README.md 工具概览表
验证点:grep
TodoWriteTool零匹配,tsc 编译通过。P4(长期重构):统一 CRUD 实现
问题:task_manager 工具与 IPC handler 对同一张 tasks 表有两套 CRUD 实现,行为不一致(ID 生成、order_idx 计算、越权保护)。
修复策略(最小统一,未抽 Service 层避免过度工程):
- handlers.ts —
tasks:create改用nanoid(12)生成 ID(与工具一致) tasks:create补 order_idx 计算:MAX(同 session+parent 的 order_idx) + 1- NULL parent_id 边界正确处理:null 用
parent_id IS NULL,非 null 用parent_id = ?
未做的重构:未抽取 TaskService 共享层(避免过度工程),保持工具层和 IPC 层各自维护,但行为已对齐。
P5(可选增强):System Prompt 加任务管理工具引导
问题:AI 不知道何时该用 task_manager,也不知道 Tasks 面板的存在。
修复:context-builder.ts 的
buildCriticalReminders()新增第 6 条引导:6. For multi-step complex tasks (3+ steps), proactively use `task_manager` to break down and track progress — users will see task updates in the Tasks panel设计权衡:只加一条 CRITICAL REMINDERS,不增加大量 token 负担。
三、修改文件清单(13 个)
文件 改动类型 说明 task-manager.ts 修改 注入 onTaskChanged 回调 + 4 处写入后触发 handlers.ts 修改 IPC update/delete 补 sessionId + create 用 nanoid + order_idx main.ts 修改 注册时注入回调 + import BrowserWindow + 删除 TodoWriteTool preload.ts 修改 update/delete 传 sessionId + 新增 onTaskChanged 订阅 global.d.ts 修改 update/delete 签名补 sessionId + onTaskChanged 类型 TaskList.tsx 修改 新增 useEffect 订阅 + 调用方传 sessionId context-builder.ts 修改 buildCriticalReminders 加第 6 条引导 permissions.ts 修改 删除 todo_write 权限策略 index.ts 修改 删除 TodoWriteTool 导出 + 注释更新 README.md 修改 删除 todo_write 行 + task_manager 描述更新 todo.ts 删除 244 行 package.json 修改 版本号 0.3.12 → 0.3.13 package-lock.json 修改 版本号 0.3.12 → 0.3.13 变更统计:13 files changed, 114 insertions(+), 280 deletions(-)
四、工具数量变化
类别 v0.3.12 v0.3.13 变化 文件系统 7 7 - 文件编辑 2 2 - 搜索 2 2 - Git 4 4 - 开发工具 3 3 - 独立工具 4 3 -1(删除 todo_write) 数据库 1 1 - 内存 1 0 -1(todo_write) 网络 3 3 - 任务委派 1 1 - 合计 30 29 -1
五、关键设计权衡说明
5.1 工具层不依赖 Electron
TaskManagerTool 通过
onTaskChanged?: (sessionId: string) => void回调注入方式通知 UI,不直接 import BrowserWindow,保持工具层与 Electron 的分层清晰。这样工具可以独立测试,不依赖 Electron 运行时。5.2 P4 最小统一而非抽 Service 层
未抽取 TaskService 共享层(让工具和 IPC 都调用它),因为:
- 工具层需要
context.sessionId(来自 ToolExecutionContext),IPC 层从参数拿 sessionId,签名差异大 - 强行统一会引入适配层,增加复杂度
- 当前最小统一(nanoid + order_idx)已消除行为不一致
5.3 P5 引导简洁
只加一条 CRITICAL REMINDERS,不增加大量 token 负担。避免 System Prompt 膨胀影响 LLM 推理质量。
5.4 parent_id IS ? 的 SQLite 扩展行为
task_manager 工具用
parent_id IS ?(SQLite 扩展,null/非 null 统一处理),IPC handler 用显式分支(标准 SQL,更清晰)。两者行为完全一致,IPC 层的显式分支更易读、更标准。
六、验证
6.1 typecheck
npx tsc --noEmit退出码 0,无类型错误。6.2 人工审查
- ✅ P1 越权防护:IPC + preload + types + TaskList 调用方四点对齐
- ✅ P2 事件链路:工具 → main → preload → TaskList 四点完整
- ✅ P3 todo_write 清理:grep 零匹配
- ✅ P4 order_idx 计算:NULL 边界正确处理
- ✅ P5 Prompt 引导:语法正确
- ✅ 跨文件一致性:import + 导出 + 类型签名 + 调用方全链路一致
- ✅ 资源管理:subscribe 有 unsubscribe cleanup
- ✅ 越权防护:IPC 层 + 工具层双重校验
七、问题根因与修复对照表
问题 根因 修复方案 文件 IPC 越权 UPDATE/DELETE 无 session_id 校验 补 WHERE 子句 + 签名 handlers.ts, preload.ts, global.d.ts, TaskList.tsx UI 不刷新 工具写入后无事件广播 注入回调 + IPC 事件 + 订阅 task-manager.ts, main.ts, preload.ts, TaskList.tsx todo_write 零价值 功能重叠 + 无 UI + 死代码 删除工具 todo.ts, index.ts, main.ts, permissions.ts, README.md CRUD 不一致 两套实现 ID/order_idx 不同 统一 nanoid + order_idx 计算 handlers.ts AI 无引导 System Prompt 工具无关 加第 6 条 CRITICAL REMINDERS context-builder.ts
八、升级须知
8.1 兼容性
- ✅ 数据兼容:tasks 表 schema 不变,旧数据完全兼容,无需迁移
- ✅ API 兼容:IPC
tasks:list签名不变;tasks:update/tasks:delete签名变化(新增 sessionId 参数),但仅影响内部调用方(TaskList.tsx 已同步更新) - ⚠️ 工具变化:todo_write 工具被删除,如果有 Agent 旧会话正在使用 todo_write,会收到"工具不存在"的错误。建议重启应用开启新会话
8.2 建议测试场景
- UI 自动刷新:Agent 调 task_manager 创建任务 → Tasks 面板应自动刷新显示新任务
- 越权防护:构造跨会话 update/delete 请求 → 应返回失败
- order_idx 计算:UI 创建任务 → order_idx 应正确递增
- 订阅 cleanup:切换会话 → 旧订阅应取消,新会话订阅应生效
- 复杂任务引导:执行 3+ 步任务 → AI 应主动调用 task_manager 拆解
九、设计反思
本次重构的核心洞察是:工具的存在不等于价值,需要端到端的联动设计。
- todo_write 工具技术上没问题,但缺少 UI 消费方 + AI 引导 → 实际无人使用
- task_manager 工具实现完善,但缺少事件广播 → 用户体验割裂
- System Prompt 工具无关是好设计,但对关键工具需要适度引导
这三个问题都不是 bug,而是"设计完整性"的缺口。本次重构系统性补齐了这些缺口,让任务管理工具真正发挥价值。
完整代码差异:v0.3.12...v0.3.13
Downloads