dsh-todo-panel
把记忆银行的待办页(todos.md)搬进 DSH 左侧栏 —— 侧栏底部常驻一份列表,
点一下就能把某条待办「接着做」的意思填进输入框。
它做什么
| 位置 | 插槽 | 行为 |
|---|---|---|
| 侧栏底部 | sidebar.footer.action |
常驻待办列表,默认展开,点标题可折叠;点条目 → 填进输入框 |
| 侧栏按钮行 | sidebar.panellist |
一个「待办」小图标,点开主区域大面板 |
| 主区域 | main(key = dsh-todo-panel) |
同一批待办,但能看全 detail(截断到 180 字) |
| 对话输入区 | conversation.input.dock |
渲染 null 的"桥",只为拿 session 作用域的 inputActions.setDraft |
三个视图共享同一份 store(useSyncExternalStore),刷新是同步的。
数据新鲜度:侧栏那块是常驻的,页面不重载就一直显示同一份快照 —— 2026-09-18 实测踩到:
在别处改完 todos.md(勾掉一条),面板上那条已完成的还在,主人点了它,发出的是
「继续做这条待办:<已完成的那条>」。现在两个时机主动重取:① 折叠后重新展开
② 页面重新可见 / 窗口获得焦点;删除成功与手动「刷新」也会更新 store。
删除(唯一会写盘的动作)
条目上的 × / 「删除」按钮 → 二次确认之后才真删。安全设计:
- 定位不用序号:
t1/t2/…是按顺序生成的,前文一增删就错位。请求带的是 源文件行号 + 该行原文,host 两者都校验,对不上就回「文件已变,请刷新」, 绝不猜着删。 - 删前备份整份原文件 →
todos.md.bak-<本地时间戳>(本机时区,不是 UTC)。 - 保持原形态:BOM 与 CRLF/LF 原样保留;原子写(先写临时文件再 rename)。
除删除之外全部只读;改待办也可以照旧直接改文件(或 cli.mjs remember --page todos.md)。
已知副作用
点面板条目会往输入框填「继续做这条待办:<标题>」—— 这句会被记忆银行的 HEUR 当成新待办抓进
inbox.md(2026-09-18 实测连抓两次,已清)。根因是 HEUR 按关键词匹配、分不出「陈述」与
「操作痕迹」。缓解办法:在 ingest 侧加一条忽略规则(前缀 继续做这条待办:)—— 已记入
E:\2\_dsh_memory\repos\e-2\pages\todos.md 的待办,已于同日修掉。
修法(2026-09-18):在 bank.mjs 的 scoreCandidate() 加第 ⑦ 条「界面回填」规则 —— 命中前缀
继续做这条待办: 扣 0.6 分(0.65 → 0.05,远低于门槛 0.5);并在 test.mjs 第 11 节加三条断言
守护它(挡得住回填 + 不误伤真待办)。
数据源
默认读 E:\2\_dsh_memory\repos\e-2\pages\todos.md,可用环境变量 DSH_TODO_FILE 覆盖。
解析约定跟 bank.mjs 的 indexList 对齐,保证「面板显示的」和「开场注入的」是同一套真相:
## 标题→ 分段- [ ] 条目→ 条目(- [x]跳过,交给tidy归档)> ...→ 全部跳过(那是"细节备查"区)---以下 → 全部跳过
四条外部契约(改代码前先看这几条)
sidebar.panellist条目的id必须与main插槽的key完全一致。 侧栏点击走ctx.layout.selectPanel(id),而LayoutController.selectPanel会校验entries("main").some(e => e.options.key === id)—— 对不上会抛main panel "..." is not registered。- 填输入框靠
conversation.input.dock这个 session 作用域插槽下发inputActions(官方在uiSession.provide({ props: ["inputActions"] })里声明)。 所以「桥」组件必须注册在会话作用域的插槽里才拿得到 props。 - 侧栏底部为什么塞得下:
sidebar.footer.action是 list 型且本机无人占用。容器链是.footArea{flex:none}→.footerActions{width:100%;display:flex},而会话列表所在的.regionArea{flex:1;min-height:0;overflow:hidden}—— 所以底部这块变高时会自动压缩 会话列表,不会溢出。列表自身的maxHeight: min(40vh, 300px)是兜底,别去掉。 - 新增插件必须走 bundle 层(本包
cordis.patch.yml的insert); profile 用户层的cordis.patch.yml只能覆盖/禁用,不能新增。
改动怎么生效(2026-09-18 实测,别再瞎猜)
- 新增插件本身通常不用重启:本机
zh_pro的hot-mount.js会监听 profile manifest 并运行时挂载(日志打[deepseek-harness-zh_pro] 热挂载: <包名>,在logs\harness.log)。 但它只接受纯id/nameinsert 行的 bundle patch。 - 改 host 半边(
src/index.js):不会自动重载 —— hot-mount 只管「新增/移除插件」,管不了「已有插件的代码变了」。实测:改完再GET新路由得到 404、POST得到 405(=路由没注册)⇒ 必须重启 DSH。 - 改 client 半边(
lib/client.js):host 会自动重新生成 bundle(实测 rev 从1f87a7227120751b→dcdd7996165d),但已打开的页面不会自动重载 —— 按 F5 刷新即可。 - 验证 host 有没有把新 bundle 发出去:抓首页
/?token=<harness.log 里dsh web:那行的 token>, 取出plugins/??dsh-todo-panel/client.js&rev=...,再直接 fetch 那个 URL 搜特征串。 ⚠️ 单敲/plugins/<包名>/client.js必然 404 —— 真实 URL 是??组合式。
安装 / 卸载
安装:本目录在 profiles\web\.local-bundles\dsh-todo-panel(junction → 本目录),
profiles\web\package.json 的 dependencies 加 link: 条目、dsh.profile.bundles 加 "dsh-todo-panel"。
卸载:把上面两处删掉(或还原 package.json.bak-<时间戳>),重启 DSH 即可 ——
插件不写任何自己的状态文件。
No comments yet. Be the first to write one.