dsh-knowledge-canvas
Knowledge base as a canvas in the right sidebar: notes are nodes, and nine tools let the model read, write, link and remove them. A node can carry pictures and documents, and reading one returns their text — Office files extracted in place — while pictures can be handed over as images.
Install
dsh plugin --profile web add dsh-knowledge-canvas
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-knowledge-canvas
[English](README.md) · 简体中文 · [使用手册](MANUAL.md)
给 DeepSeek Harness 的知识库:模型靠判断去取,而不是靠相似度。
主要功能
- 知识画布:编辑节点、父子关系和关联线,支持四种布局与节点尺寸调整。
- 收起与查找:折叠暂时不用的分支,搜索时展开目标路径;长文可滚动,缩成标题后可悬停预览。
- 分层注入:知识库设置全文或按需默认方式,单个节点可覆盖。
- 改动审核:查看模型新增、修改、删除的内容,以及节点读写调用记录。
- 日记与回复:按会话保存日记,以日记本视图阅读,并从侧栏回复。
- 节点附件:存放图片和文件,按工作区选择按需或必须读取附件。
[完整使用手册](MANUAL.md) · [版本变更记录](CHANGELOG.md) · GitHub Releases
问题
你把一件事讲清楚了,下一段对话它还是不知道 —— 或者更糟,它以为知道,而那条已经过时了。
这不是上下文长度的问题。在一个工作区里实测过:
$ node report-kb-use.mjs 50 tool call(s) in the log, 1 session(s) 写 13 次(ops / …) 读 1 次(read-animation) ⚠ 先写后读:第一次写入之前没有读过
写进去 13 次,读出来 1 次 —— 而那次读的还是另一个库。知识被记录了,而没有被用。记录是免费的:模型顺手就写了。用才是难的 —— 要用它,得先知道它存在,还得知道哪一条现在还算数。
它哪里不一样
这不是"带搜索框的笔记应用"。四个决定,其余都是它们的推论。
一、触发器行,而不是向量索引
每个节点正文的最后一行写它什么时候适用:
什么时候该想起它:<这个节点适用的情形>
按需模式下,系统提示携带标题、层级和触发器等索引信息,正文由模型调用工具读取;全文模式则会注入正文。触发器的作用是:
- 没有嵌入、没有向量库、没有相似度阈值。 检索是模型在判断,而它判断的依据是一句人写的话
- 一个节点能不能被找到,取决于写它的人有没有说清"什么时候"。 这就是全部的赌注:知识库难的不是存,是被查阅;而被查阅是写法的性质
- 没写的节点会被标出来。 索引里显示
(无触发器),而写工具在你写下的那一刻就告诉你 —— 因为一个全是找不到的节点的库,看起来和一个健康的库一模一样
二、索引是一棵树,不是一堆片段
父子关系本身是信息 ——"这条属于那个主题"。索引按层级展开,所以模型读到的是一套结构,而不是一把碎片。一个全是平级的库也是好库;而一个什么都不挂在任何东西下面的库,通常是失误。
三、审核标记在每一种模式下都保留
模型做的每处改动带 [新增] / [修改] / [已废弃],直到你审过。全文注入时也保留 —— 而那正是最容易丢的地方,也确实丢过:一个测试会话发现它分不出哪些段落还没被审。
四、它会告诉你到底有没有用
report-kb-use.mjs 读插件的 activity.log,回答:这个会话里读了几次、写了几次、以及第一次写入之前有没有读过。上面"问题"里那个数字就是这么来的 —— 也是这个插件不声称任何它没量过的东西的原因。
装
npm(推荐):包名 dsh-knowledge-canvas,在 DSH 的「添加插件」里填它。
手动安装时,在对应profile目录执行 pnpm add dsh-knowledge-canvas@latest,还必须将 dsh-knowledge-canvas 加入该profile的 dsh.profile.bundles(保留已有条目)。仅加入dependencies不会应用插件补丁。安装或升级后重启DSH。
从源码:
// profiles/desktop/package.json
"dependencies": { "dsh-knowledge-canvas": "link:<仓库路径>" },
"dsh": { "profile": { "bundles": [ ..., "dsh-knowledge-canvas" ] } }
本仓库、发布包与前端模块注册名均使用 dsh-knowledge-canvas。内部 Cordis id、标签页标识、路由及数据目录保留旧标识以兼容现有数据;不要把这些内部标识当成安装包名。
面板上能做什么
认位置
位置 · 是什么
顶上那排 · 搜索框、已读计数、刷新
每个库一行 · 标题、已读进度、一个开关(这个会话读不读它)、⋯ 菜单(改名、删除、颜色、导出)
画布工具栏 · 缩放、适应、宽度(整库默认宽度,不是单个节点)、形状、颜色、布局
左下「定位到…」 · 输入 id 直接跳到那个节点,不用肉眼找
手势
动作 · 结果
单击节点 · 打开编辑器;再点一次关闭
Enter / 空格(聚焦时) · 同上,键盘可达
Shift+Enter · 开始连线;在目标上按 Enter 完成
拖动节点 · 移动;位置写进 layout.json
按住约 0.26 秒再拖 · 画关联线(橙色),不是改父子关系
Alt + 拖动节点 · 把目标变成它的父节点(灰线)
右键节点 · 菜单:新建子节点 / 看修改历史
右键空白画布 · 菜单:新建父节点(顶层)
拖出画布到输入框 · 把这个节点交给对话
节点右下角三个把手 · 改宽、改高、同时改
节点宽高有三层含义:这个节点的宽度 → 整库默认宽度 → 画布缩放。工具栏那个「宽度」改的是第二层。
视图与布局
四种布局:分层、放射、阶梯、紧凑。切换布局重算默认摆放,手动位置仍由你控制。
点标题箭头或右键菜单可折叠子树;嵌套折叠会保留,搜索、定位和未读跳转会展开目标的祖先路径。工具栏支持全部展开,以及主动整理可见节点。折叠只改变画布显示,不限制模型读取或注入。
长文正文可独立滚动,并提供编辑入口。缩小到只显示标题时,悬停或聚焦节点会出现阅读预览。
模型工具
工具 · 用途
knowledge_read · 读一个库或一个节点;不给 base 时列出所有库
knowledge_create_base · 建库,自带一个根节点。建完立刻可用,不需要再 knowledge_select
knowledge_write_node · 写或改一个节点。返回里带着刚建出来的节点 id,可以直接拿它当 parent
knowledge_link · 连两个节点,必须写一句"为什么相关",那句注释会出现在对方的视图里
knowledge_unlink · 断开一条关联;节点不动,只去掉那条虚线
knowledge_remove_node · 标记移除(不删数据,可还原)
knowledge_select · 开关某个库对本会话是否可见
knowledge_remove_base · 把一个库标记为移除(可恢复,不是删文件)
knowledge_show_images · 把一个节点挂的图片作为图片交给模型(按需模式下可单独调用;必须读取模式随节点返回图片)
为什么是这个形状:模型拿到的东西必须可核对。每个节点的正文最后一行写「什么时候该想起它:…」,那一行被抽出来放大纲里 —— 所以模型按场景匹配,而不是按向量相似度猜。它读错了,你能在画布上直接看见并改掉。
设置:按工作区
设置 → 知识库,每个工作区一块:
- 这个工作区的路径(一眼确认你在改哪个)
- 记录调用过程 —— 打开后模型每调一次工具都会记一条,面板顶上显示「正在检索 n3(知识库插件的教程)」。默认关。
- 每个库一个 按需索引 / 全文注入 选择(前者给标题和要点,后者把正文也塞进去);
面板上那一行的开关是另一件事:这个会话读不读它
每个库有全文或按需的默认方式,单个节点可在编辑器或右键菜单中选择覆盖或跟随默认。覆写按工作区共享,仅作用于所选节点。按需索引仍有上下文成本;全文额度和超额行为见[使用手册](MANUAL.md)。附件读取策略独立设置。
工作区列表 = 会话里出现过的目录 ∪ 磁盘上有 .dsh-knowledge/ 的目录。后者从 $DSH_HOME/sessions/ 的目录名还原(那里每个会话一个目录,名字就是工作区路径,分隔符换成了 -),所以重启之后不会只剩一个工作区。
日记模式(可选)
给不想整理笔记、只想有人记得的人。面板顶上打开,按会话生效。
打开之后,那个会话在聊到一个段落时会自己写一篇 —— 写到属于它自己的那个库,不按天,也不在别的会话里写。
- 每个会话一份
diary-<哈希>.json。开关是会话级的,数据也是:同工作区的另一个会话既看不到它,也读不到它。 - 落盘是密文(AES-256-GCM)。模型
cat那个文件只会看到 base64。 - 提示词只给约定,不给口吻。 人设由你的预设决定,插件不替你写信。
日记默认以日记本视图打开,支持按月目录、前后篇切换和修改记录;需要编辑时可切回画布。书页底部可直接回复,回复会连同该篇的正文节选送入当前会话,不替换聊天输入框中的草稿。回复记录与日记正文分开保存。
它不做什么
边界比功能更该写清楚:
- 不是聊天记录。 它不自动记录对话,只记你或模型显式写进去的东西。
- 不同步到云端。 全部在
<工作区>/.dsh-knowledge/下,普通 JSON,可以用记事本打开、提交进 git、整个拷走。没有账号、没有服务器。 - 日记的加密挡的是"顺手看见",不是"想读的人"。 密钥由库名派生,读过这份源码的人可以解开。要挡住会翻文件的模型,需要密钥不落盘(口令或系统凭据),那是另一个设计。
- 不替你写人设。 日记模式注入的是一段写作约定,不是语气。
- 不做全文检索。 搜索框搜的是标题和正文的子串,没有倒排索引,也没有向量。
文件长在哪
<工作区>/.dsh-knowledge/ ├── <库 id>.json 每个库一个文件:节点、连线、seed 指纹 ├── selection.json 这个工作区默认读哪些库、怎么注入、记录调用过程 ├── layout.json 位置、宽度、形状、颜色 ├── .sessions/<id>.json 这一个会话自己的开关(含日记) └── activity.log 工具调用记录(仅当「记录调用过程」打开)
- 宿主(
index.js、lib/*)负责:注入点、工具、路由、种子教程、日记约定。 - 面板(
client.js)负责:画布、手势、编辑器、设置页。它直接读这些 JSON 文件,不走宿主的接口 —— 所以"面板看不到某个库"时,先查它自己读到了什么,而不是查宿主。 - 大纲在每次模型调用前组装,只放标题、要点和触发行;正文要模型主动
knowledge_read。
给改代码的人
npm run check:all跑四样:标识符、精灵图宽高比、公开树检查、以及存储/路由/工具三层断言(数目以运行输出为准)。- 改了手势,就改教程里对应那句(
lib/seed.js顶层的操作表),否则教程会描述一个不存在的操作。 - 旧工作区的教程按内容认(谁的节点 id 与种子重合过半,谁就是教程),不是按文件名 —— 这一条是被三个工作区用三种文件名教育出来的。
第一次用
① 装完重启一次 → 侧边栏出现「知识库」 ② 展开「怎么用这个知识库」→ 那就是教程,讲的就是这个面板 ③ 随便找一段对话,跟模型说:"把刚才的结论写进知识库" → 它会调 knowledge_write_node,节点出现在画布上 ④ 在画布上拖动它、给它连一条线、改一遍正文 ⑤ 下一段对话里问它一件旧事 —— 如果它读了,面板顶上会出现「正在检索 xxx(id)」 (这需要先在设置里打开「记录调用过程」)
判断它有没有用的那个数字:node report-kb-use.mjs —— 它数日志里"写了几次、读了几次",以及第一次写入之前有没有读过。
常见问题
面板里看不到某个库。
先看那个库的开关,再看你所在的会话有没有自己的开关(面板顶上「开关作用于 默认 / 仅本会话」)。会话级的列表是一份快照;新建的库会被自动补进去,但手工关掉的不会自己回来。
日记在别的会话里也能看见。
不该。日记按会话隔离,四层都过滤:大纲、面板、工具、以及提示词。如果还看得见,查那个会话的 .sessions/<id>.json 里 diary 是不是 true —— 那份文件属于那个会话,它看见了就是它开着。
改完代码没生效。
分两半:改的是 `client.
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::16,最后更新 2026-11-01