dsh-todo
DSH 侧边栏待办插件:零模型 token 消耗的待办面板。
- 入口:better-sidebar 右侧栏「待办」Tab(与 Files 等并列)—— 点右上角 better-sidebar 开关打开右侧栏即可见,tab 带未完成数角标
- 常驻红气泡:屏幕右缘中部悬浮「✓ n」(n=未完成数,n=0 隐藏),侧栏收起也能看到;点击自动展开右侧栏并聚焦待办 tab;侧栏已显示角标时气泡自动隐藏
- 跨标签提醒:① favicon 角标 —— 标签图标 = 原小鲸鱼底图 + 右上角红底白字数字(99+ 封顶),归零完整还原鲸鱼;② 标签页标题前缀「🔴n」;③ 浏览器系统通知(需点「开提醒」授权)—— 待办逾期/今天截止、或页面在后台时未完成数增加都会弹通知,点通知直达待办 tab;同一条只提醒一次
- 面板:tab 内即完整待办列表 —— 新建 / 完成 / 恢复 / 删除 / 优先级 P0-P3 / 截止时间 / 备注(默认全文展开,可手动收起)/ 逾期与今日提示 / 已完成折叠区;better-sidebar 不可用时自动回退为「右侧抽屉 + 红气泡」
- 排序:头部下拉切换 原版排序(逾期/今日置顶 → 按优先级 → 组内手动序,与旧桌面版一致)/ 按优先级 / 按截止 / 手动顺序;每行 ↑↓ 调整手动顺序(写回 sort_order,旧字段兼容)
- 高分辨率适配:面板基础字号 15px(标题 16 / 备注 14 / 输入 14),只影响待办区域,不动全局 UI
- 数据:每次变更立即写入工作区
desktop-todo/data/todos.json(原子写,UTF-8)
- AI 协同:agent 可直接读取该 JSON 文件写日报 / 周报,无需导出
架构
Browser (client.js) Node (index.mjs)
better-sidebar 待办 Tab ──────┐ /dsh-todo 路由(webServer)
(兜底:header 开关 + 抽屉)──┼─ fetch ─▶ 读写 <workspace>/desktop-todo/data/todos.json
零 token,纯浏览器 ↔ 同源 HTTP RPC workspaceRegistry 解析路径
依赖与兼容性
| 依赖 | 类型 | 说明 |
|---|
| DeepSeek Harness (DSH) | 运行环境 | 需要 dsh web 可运行;建议 DSH ≥ 0.1.0-rc.7(与 dsh-better-sidebar 的版本要求一致) |
dsh-better-sidebar | 可选(推荐) | 已装 → 待办显示为右侧栏 Tab(registerTab + badge 角标);未装 → 自动兜底为「右侧抽屉 + 右缘红气泡」,功能不缺失,只是入口形态不同 |
| npm 第三方依赖 | 零 | 仅用 node 内置模块(node:fs / node:path)与 DSH 服务(webServer / workspaceRegistry / slots / betterSidebar)—— 无 npm install 负担,GitHub 源安装 / 拷贝目录即用 |
为什么依赖声明为「可选」:兜底模式保证没有 better-sidebar 的机器(如公司内网)也能完整使用列表 / 抽屉 / 气泡 / 提醒。
架构速览(修改前先读)
Browser (client.js) Node (index.mjs)
├─ better-sidebar Tab「待办」────────┐ ├─ /dsh-todo 路由(GET 读 / POST write 原子写)
├─ shell.overlay 红气泡「✓ n」──────┼─fetch──▶├─ 数据:<workspace>/desktop-todo/data/todos.json
├─ favicon 鲸鱼+红角标 / 标题 🔴n │ └─ 缺文件时自动导入同目录 todo_export.json
└─ 浏览器系统通知(逾期/今日/后台新增)┘ 零 token:浏览器 ↔ 同源 HTTP,不经 LLM
client.js 模块职责(改 UI 按块定位)
- 状态/存储:
state / setState / subscribe / getSnapshot(多组件共享:open 开关、todos、saving/error)
- 数据通道:
load() / save() / mutate()(fetch /dsh-todo;mutate 整表写回)
- 提醒:
evaluateReminders()(逾期/今日截止/后台新增;notified 去重、lastNotifiedCount 节流)
- 角标:
updateTitle()(🔴n)、updateFavicon()(鲸鱼+红角标 canvas 合成)、better-sidebar badge + updateTab 同步
- UI:
TodoTabView(右侧栏 tab)/ TodoPanel(兜底抽屉)/ TodoBubble(红气泡)/ AddForm / TodoRow(备注默认展开、↑↓ 调序)/ 排序 sortMode(原版/优先级/截止/手动)
- 入口:
apply(ctx) —— 先探测 ctx.get("betterSidebar"),有则注册 tab,无则抽屉兜底;slots 为必需注入
index.mjs 职责(改数据层时读)
resolveDataFile():无 config → workspaceRegistry 首个 workspace + desktop-todo/data/todos.json
readTodos():缺文件自动导入 todo_export.json;兼容裸数组
writeJson():临时文件 + rename 原子写(AI 半路读也不会读到半写文件)
- 零第三方 import(仅
node:fs / node:path)
开发 / 改动流程
- 改
client.js(UI)或 index.mjs(数据层)
node --check client.js && node --check index.mjs
- 本机热重载:
dev_reload_package {"packageName": "dsh-todo"}(或重启 dsh web)
- 浏览器硬刷新验证 →
git add -A && git commit -m "..." && git push
开发坑备忘:本机 better-sidebar 的 loader 条目带 disabled 标记(聚合双挂载守卫),但 fiber 实际在跑 —— 注册 tab 前必须用 ctx.get("betterSidebar") 运行时探测,不能假定它一定存在。
数据文件
desktop-todo/data/todos.json(相对 DSH 首个 workspace 根目录),结构:
{
"version": 1,
"updatedAt": "2026-08-18T22:40:00.000Z",
"todos": [
{
"id": "t...",
"title": "示例待办",
"note": "",
"priority": 1,
"deadline": "2026-08-24 09:00",
"remind_offset_minutes": null,
"remind_sent": false,
"completed": false,
"completed_at": null,
"created_at": "2026-08-18 22:40:00",
"sort_order": 0
}
]
}
优先级:0=P0(红)1=P1(黄)2=P2(蓝)3=P3(灰)。旧字段名与迁移脚本兼容。
npm 源安装(已发布)
dsh plugin --profile web add dsh-todo
公司 / 新机器安装
独立插件,零第三方依赖。拷贝 dsh-todo-0.1.0.tgz 到目标机后:
dsh plugin --profile web add ./dsh-todo-0.1.0.tgz # 装完重启 dsh web + 硬刷新浏览器
或手动:解压到 ~/.dsh/profiles/web/node_modules/dsh-todo/,在 profile 的 package.json
里 dependencies 加 "dsh-todo": "file:./node_modules/dsh-todo"、dsh.profile.bundles
加 "dsh-todo",重启生效。详见 安装说明.md。
开发 / 安装
- 开发形态:
dev_install_package {"dir": "<本目录绝对路径>"}(热装配,免重启;重启后由 profile bundles 接管)
- 手动安装:把本包放入
~/.dsh/profiles/web/node_modules/dsh-todo/ 并在 profile 的 bundles 列表加入 dsh-todo
- 热重载:
dev_reload_package {"packageName": "dsh-todo"};UI 改动改 client.js 后 reload + 刷新浏览器即可
数据迁移
desktop-todo/migrate_to_json.py:旧 SQLite → todo_export.json
- 本插件首次启动(todos.json 不存在)会自动导入同目录
todo_export.json 的 todos
License
MIT