@local/dsh-knowledgenet
把本地知识图谱接进 DSH:一个节点就是一个 markdown 文件,节点之间记「前置依赖」,
用右侧栏的「知识库图谱」面板看全局、随手补点,用 kn_* 工具按需读取学习节点、按纪律写。
它是什么 / 不是什么
- 是:DSH 的一个插件。给每个工作区提供一个知识库(工作区里的
.dsh_knowledge/), 以及一组让模型读写这个知识库的工具。 - 不是:通用笔记软件,也不是把工作区变成"知识库工作区"的开关 —— 任何工作区都可以有知识库,
有没有完全由"目录里有没有
.dsh_knowledge/"决定。
存储格式(v3,一节点 = 一个 markdown)
<工作区>/.dsh_knowledge/
library.json { formatVersion: 3, libraryId, title, createdAt, storage: "single-file-markdown" }
Nodes/注意力机制.md ← 一个节点 = 一个文件
Nodes/注意力机制-2.md ← 允许同名,自动加后缀
graph.json { revision, edges: [ A → B + 为什么 + 出处 ] }
节点文件长这样 —— 头部是元数据,正文就是笔记本身:
---
id: 01M3NHE78B55MHMDQ9D192MXAM ← 唯一标识(ULID):**永不随标题或文件名变化**
title: 注意力机制
status: todo ← todo | learning | done
aliases: [Attention, 注意机制]
createdAt: 2026-09-29T03:00:00.000Z
updatedAt: 2026-09-29T03:05:00.000Z
rev: 2
---
这里是正文,随便写;用编辑器直接改也不会坏(front-matter 之后的都是正文)。
身份与名称彻底解耦
| 你做的事 | 结果 |
|---|---|
改 title: |
身份不变,关系不断 ✓ |
重命名文件(注意力机制.md → Attn.md) |
身份不变,关系不断 ✓(面板按 id 找) |
| 建两个同名节点 | 两个不同身份 ✓(标题.md / 标题-2.md) |
手工丢一个没有 front-matter 的 md 进 Nodes/ |
先给临时身份(adopted-…),首次写入时固化成正式 ULID ✓ |
不兼容老格式(v2)
老格式(一节点一个文件夹 + .meta/knowledgenet/node.json + 每个节点一份 relations.json)
已不再支持 ✓。遇到它时不给含糊结果,而是明确报错:
unsupported_format:这个知识库是老格式(formatVersion=2),当前版本只支持新格式…
请把 <库根> 整个删掉,然后在面板里点「知识库图谱」重新创建。
迁移方式:删掉那个目录 → 打开「知识库图谱」→ 自动建一个新的 v3 库(空库,不会动工作区其它文件)✓。
库 ↔ 工作区
- 任意工作区都可以有一个知识库,位置固定为
<工作区>/.dsh_knowledge/✓。 - 打开方式:右侧栏「知识库图谱」标签页(所有工作区都可见 ✓)。第一次打开若还没有库, 会静默创建一个(不弹窗、不问问题 ✓);已经有的直接显示。
- 会话 cwd 在库的子目录里也能向上找到库 ✓。
- 也可以在工作区之外用配置固定一个库(
cordis.patch.yml的libraryRoot)。
「看不到插件」是怎么做到的(隔离)
没有知识库的工作区:kn_* 工具对该会话被 restrict 移除、协议提示词渲染为空 ⇒
模型完全看不到插件 ✓。有知识库的工作区才可见 ✓,而且建库后当前会话立刻放开
(不用等下一个会话 ✓)。
工具
| 工具 | 作用 | 读写 |
|---|---|---|
kn_list_graph |
默认聚焦一跳;学习时可自主选择 overview 查询全库结构,正文不随结构返回 | 只读 |
kn_find_node |
按标题/别名查(判重、找复用) | 只读 |
kn_read_node |
分页读目标正文、理解标记和关系计数;关系显式请求 | 只读 |
kn_current_node |
查询活动视图聚焦、首轮入口或历史目标的身份与理解标记,不返回正文 | 只读 |
kn_enter_node / kn_back |
进入前置 / 返回上一层(学习栈) | 会话内状态 |
kn_write_note |
写正文(必须带 userConsent: true,且带内容指纹冲突守卫,绝不静默覆盖) |
写 |
kn_add_prerequisite |
记一条前置(必要时建点;命中相近候选会先要你确认) | 写 |
kn_propose_prerequisites |
一次提案多个前置(只写计划文件,不建点) | 写计划 |
kn_plan_status |
查提案状态(落地了哪些、有没有失败) | 只读 |
kn_status |
自诊断(路由是否注册、缓存/扫描指标、隔离判定留痕) | 只读 |
写入纪律(写进系统提示,模型必须遵守):搜索类请求不得调用写入工具;建点前必须说明并等你同意;
一轮最多一次 kn_add_prerequisite;要一次处理多个概念只能提案,落地只能由你在面板里点击。
笔记属于你本人(写进系统提示 + 工具硬闸门):节点正文是使用者记录自己想法的地方,
不是装解释/资料/摘要的框子 ⇒ 解释概念、回答问题、顺手"整理一下"都不是改笔记的理由。
模型只有在你明确要求、或明确同意某个具体改动时才写;写之前要先把"准备写什么、写进哪个节点"说清楚并等你点头。
kn_write_note 少了 userConsent: true 会被直接拒绝(文件一字不动),并回一句"先去问用户"。
换句话说:它只能在你点头之后才写得进去。
笔记用于参考,不是标准答案:插件要求模型把正文、标题和关系当作用户的学习记录,“已理解”也不证明记录正确。模型应核查与当前问题相关的说法,发现错误时指出具体内容、简短解释原因并给出修正;区分错误、简化表达和缺少限定条件。不确定时说明需要核实,分页未读完整时注意后续限定。纠错留在对话里,不自动改笔记、理解标记或依赖关系。kn_read_node 每页明确返回 note.contentRole: user_learning_record;这是一条回答策略和数据来源说明,不保证模型能够发现所有错误。详见 笔记参考与纠错策略。
界面
- 右侧栏「知识库图谱」:所有工作区可见 ✓。打开就是整张图的三维空间视图(默认视图), 头部工具栏是「重新整理 / 刷新 / 搜索」。
- 进入节点群(2026-10-30 改版):右键任意节点 → 菜单「进入节点群」⇒ 直接进入该节点所在的节点群视图
(只显示这个群的节点与关系;不弹"所有节点群供选择"的列表 ✗)。
进群之后头行出现「返回整张图」图标按钮,点它或按 Esc 就回到整张图 ✓;
每个群的视角按
库身份 + 群键分区缓存,互不串镜头 ✓(详见 整张图 + 节点群)。 - 建节点:面板空白处右键 → 菜单「创建独立节点」→ 输入名称。 新节点不与任何节点相连(是独立节点,和现有独立节点同属一个群)✓(不再有双击建点:那是右键菜单坏掉时的临时兜底,已移除 ✓)。
- 加前置:右键节点 → 「添加前置节点…」→ 弹窗只出现在图谱界面上方; 输入名称时,下面会列出知识库里已有的节点(按匹配度排序,点一下填进输入框,避免手敲出错/建重复 ✓)。
- 删依赖:右键连线 → 「删除这条依赖」。
- 删节点:右键节点 → 「删除当前节点」→ 确认后直接删掉那个
.md(不可恢复 ✓)。 节点就是一个文档,所以没有回收站、也没有墓碑:想留底就自己复制一份.md✓。 - 提案审阅:agent 提交的提案会自动弹出一个悬浮在聊天窗口上的弹窗(agent 一交完就出现:客户端每 2 秒自己拉一次,不等图的刷新 ✓)。 弹窗只有两个出口:勾选后点「创建选中的 N 条」(落地,弹窗立即消失 ✓)或点「取消这提案」(丢弃:弹窗立即消失、永久不再出现 ✓,并让宿主删掉计划文件 ✓;点 × / Esc / 点背景与「取消」同一语义)。 没有「稍后再说」,面板上也没有「待审提案」这种入口 ✓ —— 待审就等于你还没决定,所以下次打开还会弹 ✓。 落地后面板里只留一条10 秒的短暂回执(「已新建 N 个 · 撤销」,可点 × 立刻收起,到点自己消失 ✓ —— 不做长期占位的卡片)。 撤销会把这批新建的节点删掉 ✓(落地时它们是空节点,所以不会丢内容 ✓);回执消失后要撤掉那几个空节点,用图谱的「删除当前节点」即可。
- 节点笔记编辑器(右键节点或选中条上的「编辑笔记」打开):打开后以图谱区域内的留边弹窗显示,保留背景图谱和上方工具栏 ✓
(3D 图谱、状态灯、视角图、提示条一起让位 ✓;点 × 关闭即原样回来、镜头不重置 ✓),
面板够宽时正文收成一条居中的阅读栏 ✓(一行不会拖太长 ✓);
标题区按面板宽度排布:宽面板一行放下节点名与文档动作;窄面板将理解 / 对话 / 关系移到第二行,给长标题留出空间。没有模式切换,打开就是正文(所见即所得)。
正文比视口短时,下面那块空白也是编辑区 ✓:点它会落到一个末尾空段落(已经有空段落就直接用它,不无脑加空行 ✓)
⇒ 在那儿右键同样能弹出块菜单、插表格 / 公式(不再"点了没反应"✗)。
正文里右键 ⇒ 弹出块菜单 ✓(标题 / 列表 / 引用 / 表格 / 公式 / 图片 / 代码块…);+ 块手柄打开的是同一个菜单 ✓,
正文下方空白处右键也是它 ✓(追加到末尾)。条目来自 Crepe 官方
buildMenu快照 ⇒ 图标 / 文案 / 插入命令与旧斜杠菜单 同源 ✓(中文文案按插件词典,未收录的新条目用 Crepe 原文兜底 ✓)。菜单里只有块插入 ✓ (行内格式统一在"选中文字 → 浮动工具栏"里 ✓,不在右键菜单重复列一遍 ✗ —— 2026-10-22 用户反馈 ✓)。 表格单元格右键仍是表格操作菜单 ✓; 代码块 / 图片、编辑器里的浮动工具(工具栏 / 语言选择 / 表格菜单)以及已选中文字上不接管右键 ⇒ 保留浏览器原生菜单(复制源码 / 保存图片 / 复制文字 ✓);只读、初始化中也照旧给原生菜单 ✓。 输入/一律是普通字符 ✓,不再唤起菜单(Crepe 自带的斜杠触发已在构建期关掉 ✓,详见 块菜单改版)。 其余正文排版也跟随 DSH 的 Markdown 渲染 ✓(标题字号/字重/32-16px 外边距、段落 16px、列表间距与 marker、 链接颜色/字重/无下划线、分隔线 0.5px + 32px、加粗 600、图片圆角、首个/末个块外边距)✓;\n 列表序号/圆点与正文垂直居中(标记盒行高 = DSH base line-height ✓)。 字号/行高走 DSH 的--dsw-font-markdown-*token(跟随 DSH 内容字号设置 ✓)。 表格与代码块保留插件自己的设计 ✓(表头可辨识、代码块工具条;理由见 正文排版对齐)。 打开笔记更快了 ✓:不再固定等 200ms,而是按"代码块/公式 NodeView 真的渲染出来"判定, 纯文字笔记从 ~580ms 降到 ~307ms、含代码/公式从 ~590ms 降到 ~508ms(详见 打开速度优化); 打开笔记不再"一闪而逝" ✓:富编辑器的过渡首帧(代码块/公式还没换成正式渲染时就先画一遍 ✗) 在渲染稳定前隐藏,稳定后再淡入 ✓;加载提示会一直显示到内容真正就绪 ✓ (详见 首帧渲染)。 引用块样式与 DSH 的 Markdown 渲染对齐 ✓:2px 细竖线(--dsw-alias-label-caption)+ 14px 左内边距 + 正常正文色 ✓ (原来是 3px 粗线 + 整块文字变淡 ✗,用户实测"有点丑"✗;Crepe 自带的 4px 伪元素竖线已隐藏 ✓,只保留 DSH 这一条 ✓);空段落 / 空引用的输入提示也改成中文「输入内容…」✓ (Crepe 默认英文 "Please enter..." ✗,详见 引用块与输入提示)。 插入项后保留光标前后的原文 ✓:正文 / 标题里在右键处拆出中间的空段落、命令只改它,两侧文字与列表 / 引用结构都保留 ✓; 代码块 / 图片 / 表格这类拆不开的块则在这一块之后插空段落 ✓。 行内格式(2026-10-21 修复"看起来没生效" ✗;2026-10-22 第四轮按"和浮动工具栏重复"从右键菜单里删掉 ✓, 详见 行内格式修复): 行内代码样式与 DSH 正文的 Markdown 渲染一致 ✓(inline-flex/ 0.875em /0.5px细边 / 主题行内代码底色 / 小圆角 / 左右 5px 内边距 ✓,2026-10-22 用户要求)。 统一走「选中文字 → 浮动工具栏」 ✓ —— 右键菜单里不再重复列一遍行内格式项 ✗(用户反馈 ✓); 浮动工具栏提供 加粗 / 斜体 / 删除线 / 行内代码 / 行内公式 / 链接 / 清除文字格式 ✓, 这些动作绝不拆开段落 ✓、两侧文字原样保留 ✓;快捷键(Ctrl/⌘+B/I等)照旧可用 ✓。 链接弹的是中文输入框("粘贴链接…" ✓),粘贴 / 输入 URL 回车即插入 ✓。 「+ 添加前置节点」也并进了同一条工具栏 ✓(第 8 个按钮, 点它关系面板直接以选中原文预填打开 ✓)—— 原来它是一块贴着选区的独立浮钮,会和格式化工具栏 互相遮挡 ✗(2026-10-22 用户截图),现在选区旁只留一条工具栏 ✓。 工具栏图标改成主题文字色(原来用的边框色,截图里几乎看不见 ✗)✓;行内公式的编辑小浮窗也重新主题化了 ✓: 确认按钮按文字自适应宽度、不再把「完成」挤成竖排 ✗(用户截图 ✓),点「完成」后浮窗会自动收起、焦点回正文继续输入 ✓(不再一直挂着 ✗);选中文字时右键仍保留浏览器原生的复制 / 剪切菜单 ✓。 没有保存按钮:改完按Ctrl / ⌘ + S保存(提示挂在标题栏悬停里); 未保存时节点名右上角有个*,保存中转成「正在保存…」,保存失败与冲突另有提示条与重试入口 ✓。 快速输入后立即保存会读取编辑器的最新正文;没有改动时按保存快捷键不会弹出浏览器的“另存为”。 列表中Enter续写、空列表项再次Enter退出,Tab / Shift+Tab调整缩进;标题末尾Enter开始正文,Shift+Enter在段落内换行。 表格中Tab / Shift+Tab移动到下一格 / 上一格;最后一格按Tab新增正文行,表头保持不变。 表格里按Enter与Tab一致(2026-10-30 换行审核):提交当前格并进入下一格,最后一格新增一行;Shift+Enter回上一格 —— 不再把光标与后续输入挤到表格外(Markdown 单元格本身不能保存换行 ✓)。 想离开表格继续写:在最后一行按↓(或Ctrl / ⌘ + Enter、直接点表格下方)✓。 标题的换行也按 Markdown 能表达的方式处理:空标题里按Enter直接转成普通段落(不留一个看不见的空#✓); 标题里按Shift+Enter不再插入无法序列化的软换行(旧行为会存成title\\\nmore\n====✗),而是与Enter一样拆成下一块 ✓。 Shift+Enter 软换行后继续输入*/1./-/+仍会变成列表 ✓(2026-10-30 用户要求; 原生 Markdown 输入规则只在文本块开头生效 ✗):折行前的内容留在段落里,折行后的那一行转成列表项,光标直接进列表项 ✓。 列表项末尾按Enter、而这一项还有子列表时:新项出现在子列表之后 ✓,子列表留在原项里; 之后按 Backspace 删除新项也不会把子列表搬到别处/重新出现 ✓(旧行为是 ProseMirror 默认把子列表挂到新空项下 ✗)。Ctrl / ⌘ + Shift + V按纯文本粘贴,不解析剪贴板中的 HTML / Markdown,也不自动转成代码块;文字沿用光标处的格式,换行保留。 添加前置时输入框自动获得焦点;Esc关闭关系或对话浮层后回到入口。确认弹窗内Tab循环切换按钮,Enter执行当前聚焦的按钮;输入法组合期间不触发确认或关闭。 打开笔记就聚焦正文 ✓(2026-10-30 交互审核):打开后焦点直接在正文末尾,可以直接接着写,不用先点正文; 自动切到纯文本 / 把不支持的语法删干净后回正文时,焦点跟着换到新的编辑面;纯文本模式保存后焦点也回 textarea ✓。 「采用文件最新版本」的二次确认支持键盘:打开聚焦保守选项、Tab / Shift+Tab循环、Enter执行、Esc取消、输入法组合不误触, 关闭后焦点回触发按钮 / 正文;未保存三选一点「继续编辑」或保存失败收起弹窗后,焦点也回正文,可以直接继续写 ✓。 保存完成后光标与焦点留在原处 ✓:保存期间编辑器会短暂切只读(浏览器会把焦点移走 ✗), 现在结束后自动还给正文 ✓ —— 不用再用鼠标点一下才能继续写 ✓(前提:保存期间没把焦点点到别的控件 ✓)。 正文里若有富编辑器保不住的语法(原始 HTML、脚注、指令等)自动改用纯文本编辑、原文一字不动 ✓; 想回正文需显式点一次「仍要用正文编辑」,把那些语法删干净后会自动回正文 ✓。 提示按实际模式说 ✓:还在正文模式时只说明"这里有保不住的语法、保存时这一处可能被改写", 只有真的切到纯文本才说"已改用纯文本编辑"(不再"没切换却说切了"✗)。 代码块复制会带上块结构 ✓:点代码块的「复制」同时写入裸代码(粘到终端 / IDE 照旧 ✓)、 转义后的<pre><code>✓,以及本插件自己的一份载荷 ✓ —— 在本插件正文里粘贴时会还原成一个完整代码块(语言、缩进、空行、<iostream>一字不改 ✓, 一次撤销回到粘贴前 ✓);在已有代码块里粘贴仍然只插字符、不嵌套新块 ✓, 从别处复制的普通 Markdown / HTML(不包含代码)继续走原有粘贴 ✓。 手动选中复制 = 纯文本 ✓(2026-10-22 用户要求):在代码块 / 公式块里手动划选文字复制, 粘回来就是纯文本 ✓(不再自动还原成块 ✗);只有点右上角「复制」按钮才是结构化复制 ✓ (粘贴还原完整代码块 / 公式块 ✓)——两种复制语义互不串 ✓(详见 复制语义拆分)。 从别的应用复制代码粘进来(剪贴板只有纯文本 / 网页<pre>的情况)也会自动插成完整代码块 ✓, 不再被当成 Markdown 拆散(#include<iostream>不再变原始 HTML、不会因此整篇被踢进纯文本 ✗, 详见 粘贴与引用块健壮性)。 代码 / 公式块不再像 IDE ✓:活动行浅底只在聚焦时显示(点块外空白即消失 ✓); 选中文字时活动行灰条让位、点旁边任意区域(包括不可聚焦的标题区)选区都会折叠消失 ✓; 选中文字时也不会再出现 CodeMirror 默认的绿色"选中匹配"方块 ✓ (详见 代码块活动行与选中匹配)。 引用块能退出 ✓:光标在引用段落最前面按 Backspace(或最末尾按 Delete)⇒ 空引用直接删掉、 单段落引用拆掉引用壳但保留文字 ✓(不再有一条清不掉的竖条 ✗)。 - Mermaid 图块:正文里的
```mermaid围栏渲染成图(文件里仍只有围栏源码,**不落 SVG / HTML** ✓)。 打开笔记默认「只看结果」✓,图悬停出「复制为代码 / 下载图像」✓(下载优先 PNG,画不出来就退回 SVG ✓); 点「编辑源码」可改围栏内容 ✓。渲染失败时图的位置显示失败原因,源码照旧可编辑、可复制 ✓。 **公式块/预览型代码块**:插入后直接进源码编辑区 ✓,**首次输入不会把编辑区自动收起** ✓(只修"空块输入首字就切预览"这个上游行为 ✗,详见 公式块首字修复);面板在 shadow DOM 里也验证过 ✓(document.activeElement只是 host ⇒ 补丁按 shadow-aware 焦点判断 ✓);点「只看结果」才看渲染 ✓。 源码编辑区里Enter只换行;Ctrl / ⌘ + Enter退出块到下方正文段落 ✓。 退出时**不再多出一个空的<br />段落** ✓(2026-10-30 用户指定场景实测:多层嵌套列表下面放公式, 在公式编辑区按Ctrl+Enter曾留下一个空段落;修复后焦点直接落到正文,可直接继续写 ✓)。 **公式在「只看结果」状态下,从公式下方空白区域按 Backspace 不会删除公式** ✓(2026-10-30 用户要求): 会像「编辑源码」一样展开公式源码编辑栏、把光标放进公式;在公式上方段落末尾按Delete同理 ✓ (不再把公式删除或把后面的文字并进公式 ✗)。 **代码块 / 公式块的上下留白已收紧** ✓(用户实测"占据太宽"✗):外边距统一 8px ✓、代码块工具条 26px ✓; 公式块的「复制 / 只看结果 / 编辑源码」改成**悬停浮层** ✓(不再常驻占一行 ✗)—— 公式块从 ~88px 收到 ~31px ✓ (详见 紧凑块与保存焦点)。 语言列表里补了mermaid一项(没有语法高亮,纯文本编辑 ✓),新建块、粘贴含 mermaid 围栏的 Markdown 都可用 ✓。 浅色 / 深色、中文字体跟随宿主主题 token 与正文 ✓;一页多张图各自渲染、互不串 ✓。 **渲染器本体是按需加载的**(client.mermaid.js,见下):页面启动不再背 6.8 MB ✓, 第一次打开含图笔记时才从宿主路由取运行时 ✓;加载失败会明确提示「重启 DSH 或重装插件」✓。 源码里的%%{init}%%中themeCSS/htmlLabels会被收窄(防止外部资源 / HTML 标签 ✓), 其余 init 配置照旧生效 ✓。细节与实测见 设计记录。 - 打开有多快:读正文不再扫全库 ✓ —— 宿主按"节点身份 → 文件路径"的索引只读目标文件
(图谱/工具刚扫过的结果会直接喂给索引,所以通常一个文件都不多扫 ✓),
接口的格式检查也只看
library.json一个小文件 ✓(不再顺手加载整个图谱 ✗); 索引可以活很久 ✓(每次读都现场校验身份 + 一次readdir的目录变动检测 ✓), 建索引时每个文件只读头部 4KB ✓(只取 front-matter 的 id、不读整篇正文 ✓;头部不够会自动退回读整份 ✓), 冷启动的扫描与建索引都是有界并发 ✓(不再一个文件一次串行往返 ✓); 保存前仍然现场读磁盘文件比对指纹 ✓,缓存不参与判定 ✓。 界面上两段提示是分开的:读取阶段只说「正在读取笔记」,组件真的挂载后才说「正在准备编辑器」✓ (kn_status里status.docReads记宿主走了index/index-miss/full-scan与毫秒,status.noteApi记接口端到端耗时(含根目录解析与格式检查 ✓), 客户端记note-open-start / -loaded / -ready并带同一个 requestId ⇒ 两端可对齐 ✓, 卡在读盘还是卡在编辑器创建一眼可辨 ✓)。 - 保存 / 关闭 / 再打开:未保存时关闭或切节点会问一次,按钮写明动作(「保存并关闭」/「保存并切换」)✓; 保存确认后先同步落缓存、再通知离开 ⇒ 重新打开直接显示刚保存的正文, 不会再把自己的保存当成"文件在外部发生了变化"✓。"磁盘基线"与"编辑器快照"分开存: 宿主落盘会去掉末尾空白、编辑器输出会补回末尾换行,这类编辑器自己的写法不算未保存修改 ✓ (真的改了内容 —— 包括行首缩进与空行 —— 照旧算 ✓)。真冲突仍受保护,但默认只有一句话 +「比较修改」, 点开才分栏比较「我的修改」/「文件最新版本」,且只对差异行做局部标注 ✓。
- 表格:就是文档里的普通表格 —— 没有常驻的十字线 / 加号 / 行列抓手,划过单元格也不会点亮整行整列;
点击落的是原生文字插入光标(编辑器不再装虚拟光标,颜色跟随正文 ✓)。Crepe 自带的表格节点视图会
接管单元格点击、并异步地选中整段 ✗ —— 插件在事务派发这一层(所有选区变化的唯一漏斗 ✓)
把它改写成离点击最近的文字位置 ✓:点击后是折叠光标、输入只插入、原有文字不被替换 ✓,
也不会被上游那次
scrollIntoView()拽动正文 ✓。 光标进表格、或鼠标悬停表格时,表格角上会出现一个带文字的小入口「表格操作」✓(只读 / 保存中保留但禁用 ✓); 入口纵向跟着当前单元格 / 正文可见区走 ✓ —— 长表格往下滚时它不会留在早已滚出视口的表格顶部被裁掉 ✓ (表格整个滚出视口时明确收起 ✓,菜单也保证整块落在正文视口里 ✓)。 入口就贴在当前单元格的右上角 ✓,而且是在格子外面(纵向放在这一格上方、横向贴它的右边 ✓), 所以不会挡住你正在编辑的那一格 ✓;这一格就在可见区最顶上、上面也放不下时, 它会先退到"表格顶部之外",实在没地方才压回格子角上并收成 22px 小图标 ✓(尽量少挡 ✓, 仍然半透明、悬停显示「表格操作」✓)。 定位用的是正文表格本身 ✓ —— Crepe 在正文表格前面还放了一张隐藏的拖拽预览表, 按"块里第一张 table"取会拿到那张零尺寸的预览表、入口就永远不显示 ✓; 现在按"排除预览表 + 必须在 table-wrapper 里 + 必须有尺寸"过滤 ✓(有光标单元格时直接用它所在的表格 ✓), 收起时也会说明是「没找到正文表格 / 尺寸为零 / 滚出视口 / 放不下」哪一种 ✓; 多表格时鼠标悬停的那张优先 ✓,菜单打开期间锁定目标表格 ✗(不会跨表格误操作 ✓)。 表格在阅读栏里横向居中 ✓(短表格不再贴左 ✓;比可视宽度还宽时 auto 外边距按 0 处理, 仍然从左开始、由表格外层横向滚动 ✓,不会出现"左边那截滚不到"✓)。 点开才是完整菜单,一共十三条:上/下插行、左/右插列、左/中/右对齐、上移/下移本行、左移/右移本列、 删本行、删本列 ✓。移动是整体搬整行 / 整列(内容、对齐、列宽都跟着走,可撤销 ✓); 到边界、表头行、多行多列选择或有合并单元格时会禁用并写出原因 ✓。Esc 关掉并回到正文、键盘也能用 ✓ (面板跑在 Shadow DOM 里:判"点的是不是菜单内部"用composedPath+ 节点引用 ✓,点菜单项不会被当成点外面 ✓; 打开菜单会把焦点放进菜单 ✓,↑/↓ 与 Esc 才真正生效 ✓)。 多单元格选择的底纹是低对比的 10%,复制矩形区域照常可以 ✓,拖列宽的手柄也还在 ✓。 - 整张图 + 节点群:默认是完整的三维知识图;右键节点 → 「进入节点群」⇒ 空间直接切换到该节点所在的群 (不弹选择列表)。头行会出现「返回整张图」图标按钮;Esc 也可返回 (笔记编辑器开着时返回按钮禁用,避免未保存内容跟着切走 ✗)。 旧的「聚焦(二维)视图」没有复活 ✓。 点阵底纹:三维空间用 22px 网点 ✓(WebGL 画布透明清屏 ⇒ 点阵从画布后透出; 用户 2026-10-29 要求); 滚轮不再让视角前进 ✓(整套"滚轮 → 相机沿视线移动"逻辑已删 ✓),拖动旋转 / 平移照旧 ✓; 双击节点 = 只选中:不再把旋转中心搬过去,也不再放大/定位局部视图 ✓(2026-10-29 按用户要求删掉; 按 F 键仍可显式定位,那一次只动相机与朝向、不改球心); 旋转中心固定在图的几何中心 ✓(2026-10-30 修正:引擎初始取景发生在力导向收敛前, 现在每次布局收敛后会按收敛后的包围盒中心校准;用户手动操作过相机就不再抢 ✓, 详见 旋转中心修正); 取景按包围球定、旋转时不缩放 ✓(2026-10-30 最终口径):以"旋转过程中节点可能占据的 最大平面面积"为出发点,把整团节点看成包围球,让球投影圆直径 = 可用区域短边的 86% (落在用户要求的 80%–90% 内);球投影与旋转角度无关 ⇒ 旋转全程相机距离不变, 既不会一缩一放、任何角度也不会把节点转出画面 ✓。 缓存相机恢复 / 布局结算 / 侧栏拖宽时按同一公式复核一次距离 (详见 取景占比); 总视图里节点群收紧、群内留出间距 ✓(2026-10-30 用户截图):连通分量不再沿累计半径螺旋 越排越远,而是放在同一个紧凑薄壳上(大群略外、小群略内);同一张 21 节点图实测 整图包围半径 446 → 215、群中心最远 681 → 329、群内节点归一化间距约 2.1× ⇒ 相机拉得更近, 群间空白明显减少、群内标题不再挤在一起(详见 节点群间距); 右下角那张「视角位置图」(两张圆形投影图)也一并删除 ✓(用户要求,详见 空间视图删滚轮与位置图), 底部提示语已同步去掉"滚轮靠近"与"双击" ✓。 选中节点后左上角信息条只显示三项 ✓:名称 / 理解状态(只有已理解·未理解两态,与图谱着色同源) / 「编辑笔记」入口(用户 2026-10-29 要求,详见 节点信息条)。
后台开销(桌面端流畅度)
面板只在真的看得见时工作 ✓:
- 面板自身可见性由
IntersectionObserver判断:收起侧栏、被覆盖、零尺寸时 ⇒ 不取数、不渲染 (三维也不画;requestAnimationFrame也不跑 ✓); - 三维视图常驻挂载(可见性只做显隐)—— 反复销毁重建会丢 WebGL 上下文 ✗
(
panel.css的[data-visible]约定 ✓); - 切换标签页即卸载(
keepMounted: false)✓; - 取数有请求序号 +
AbortController:切换工作区/刷新时旧请求被取消,过期响应不会覆盖新数据 ✓; - 划词浮条先判断有没有选中文字,没有就一个请求都不发(普通点击、拖拽结束不再打扰宿主 ✓)。
- 划词浮条不另起一条浮层:宿主划词后本来就会弹「引用」,我们的「添加节点」直接挂进同一条浮层并排显示 (胶囊外观与「引用」一致 ✓、点外部 / Esc / 宿主收起它都跟着收 ✓);宿主没开浮层时才自己浮在选区上方 ✓ (见 设计记录)。
安全边界
- 库根必须存在、且写操作不越出库根(路径守卫,拒绝
..与绝对路径)。 - 写正文用内容指纹做乐观并发:外部编辑器改过就拒绝,并回传实际指纹。
- 关系写在
graph.json:加边幂等、自环与成环拒绝;删节点会摘掉它的边。 - 提案的落地/撤销只有界面能触发,agent 无法自己落地 ✓。
- 删除是彻底删除(无回收站、无墓碑文件);
Backup/与.knowledgenet/都已随该决定移除(老库里若还留着,可以手动删掉 ✓)。 - 旧格式(v2)库不会被动过:只会报
unsupported_format并告诉你怎么办 ✓。
安装
profile 的 cordis.patch.yml 插入本插件(@local/dsh-knowledgenet)。
插件零运行时依赖(第三方代码内联),安装时不执行任何脚本。
发布产物:index.js(宿主)、client.js(客户端主包)、client.mermaid.js(按需加载的 Mermaid 运行时 ✓)、
cordis.patch.yml、icon.svg、locale/*.json。
安装包只包含上面这些发布产物 ✓(package.json 的 files 白名单 ✓,实测 npm pack 只打 9 个文件 ✓)——
仓库里的 src/、tests/、scripts/、tools/、build.mjs、design/ 是开发内容 ✓,不会发到用户机器上 ✓
(所以它们留在 git 里不影响安装 ✓;要自己构建 / 跑测试见下面「开发」✓)。
开发
node build.mjs # 构建宿主 + 客户端 + 布局 Worker + Mermaid 运行时(四个产物)
node --test "tests/*.test.mjs" # 全部测试(当前 923 个,全绿)
node scripts/sync-vendor.mjs --check # 上游副本必须逐字节一致(77 个文件)
浏览器端到端测试(需要 DSH 源码/依赖仓库里的 playwright 与 rolldown):
$env:KN_PROJECT='D:/AppInstallation/DSH/deepseek-harness'
node --test tests/mermaid-note.browser.mjs # Mermaid 图块(14 个:图 / 复制 / 下载 / 输入保护 / 缓存 / 安全 / 运行时缺失)
node --test tests/current-note-focus.browser.mjs # 焦点与当前节点
node --test tests/block-menu.browser.mjs # 右键块菜单(真 client.js + 宿主 Menu 契约替身)
node --test tests/inline-format.browser.mjs # 行内格式(真实面板 UI:浮动工具栏 8 项 / 行内代码样式 / 复制语义 / 公式 / 链接 / 关系弹窗点外关闭)
node --test tests/block-robustness.browser.mjs # 粘贴/引用块健壮性(外部代码粘成代码块、空引用可删除、误判样本)
node --test tests/node-conversations.browser.mjs # 节点对话:侧栏标签恢复 / 历史实时更新 / 新建前置(输入后按 Enter)→ 打开笔记 → 创建对话 / 在资源管理器中显示(假 fetcher 记录 reveal-note 请求 ✓)
node --test tests/selection-bar.browser.mjs # 划词浮条与宿主「引用」共存:挂进同一条浮层 / 矩形不相交 / 同一套胶囊外观 / Esc / 跟随收起 / 宿主晚一帧 / 兜底定位
- 上游(
src/vendor/upstream/**)是逐字节冻结的开放格式实现:只读、不手改; 需要改行为时用build.mjs的 needle 补丁,或写在自己模块里。 - 单测直接用
node --test跑.ts源码 ⇒ 只能用 Node 类型剥离模式支持的语法(不要写构造参数属性 / enum / namespace /import =);tests/node-strip-syntax.test.mjs会扫全仓拦下新增违规 ✓。 - 类型体检:
node_modules/.bin/tsc --noEmit --ignoreDeprecations 6.0 -p tsconfig.json。 目前有约 85 条既有类型宽松(never、缺@types/node等)—— 建议当棘轮用: 只看你这次改动有没有引入新错误(它抓过"本地函数漏定义"这类构建不报、运行时才炸的问题 ✓)。
已知取舍 / 尚未实现
- 两个客户端产物:
client.js8.12 MB(回到加 Mermaid 之前的量级 ✓)- 按需加载的
client.mermaid.js3.43 MB(minified,gzip 916 KB)。实测(headless Chrome,5 轮中位数) 页面启动相对旧产物 +26.9 ms pluginReady / +14.7 ms 可交互(拆分前是 +454.5 / +474.0 ✓); 代价是每页首次开图多 ~0.21 s(运行时下载+求值),但「页面启动 → 第一张图」反而早 ~0.24 s ✓, 第二张图 / 再打开无差异,不开图的会话每页净赚约 0.43 s ✓。
- 按需加载的
- 新增宿主路由要宿主半重新加载(重启 DSH,或让插件重新 apply):
client.mermaid.js由 Host 半注册的/api/knowledgenet.mermaid.js提供(同源<script>+ 浏览器 cookie 通过/api鉴权围栏 ✓)。node build.mjs之后:客户端半刷新页面即可 ✓,宿主半必须重启 DSH ✓ (Host 模块走 ESM 缓存,重装插件不保证重新加载新模块 ✗;重启是可靠路径 ✓); 没重启时图块会显示「Mermaid 渲染运行时加载失败(请重启 DSH 或重装插件)」,源码仍可编辑 ✓。 安装包已把client.mermaid.js列进package.json.files✓(git/npm 安装不会漏 ✓)。 - Mermaid 下载:优先 PNG(2× 缩放、铺渲染时的主题底色 ✓);个别图元 / 老浏览器画不出来时
自动退回
.svg✓。先切主题再下载旧图也没问题:底色用的是渲染时记下的那一份 ✓。 - 正在编辑的 mermaid 块:图在失焦后才刷新(编辑中先让路,否则异步预览回填会把源码藏起来、 打断输入——真实浏览器实测过 ✗;失焦后立刻回焦继续打字也有保护 ✓)。这是有意取舍,不是"没实现"。
- Mermaid 主题兜底:宿主 token 若换用
oklch/color-mix等现代颜色语法, 渲染器会用 canvas 采样成 legacyrgb()再交给 mermaid ✓;万一采样不可用就退回内置浅色兜底 ✓ (图不会渲染失败,但配色可能朴素一点)。 - v2 兼容代码仍在源码里但不可达(
loadLibrary只认 v3)⇒ 可以整体删除,属机械清理。 - 一个工作区一个知识库(固定的
.dsh_knowledge/);多库、跨工作区共享尚未实现。 - 图谱面板与模型查询分别返回数据;模型节点页、边页和正文页可独立续读。
- 三维视图为上游实现(构建期补丁注入四元数 trackball);标签密度等仅有固定策略。
- 节点群的取舍:群按连通分量自动划分,不能另存自定义群名; 增删关系导致群合并/拆分时,会自动跟到当前节点所在的新群,找不到就退回整张图(不弹"群变了"的通知); 「独立节点」永远合并成一个群;「进入节点群」入口在节点右键菜单里 (在整张图上右键节点 ⇒ 直接进入该节点所在的群;群内不再显示这一条)。
笔记弹窗标题栏提供前置、被依赖列表;「+ 添加前置」已挪进「前置」弹窗里 ✓(使用频率不高 ⇒ 不占标题栏 ✓),
输入节点名后直接按 Enter 就会创建前置节点 ✓(等价于点「新建「x」并设为前置」✓;中文输入法选词时的 Enter 不会误建 ✓),
前置 / 被依赖弹窗点旁边空白或按 Esc 会自动关闭 ✓;正文选中文字后仍可从浮动工具栏直接创建前置节点 ✓。
标题栏最右侧的文件夹按钮 = 在资源管理器中显示当前 md 文档 ✓(关闭按钮左边;点击后由宿主半按 nodeId
解析当前文件路径,再调 DSH 的 sessionController.openWorkspacePath({ action: "reveal" }) ✓:Windows 资源管理器会
选中这个文件、macOS 用 Finder 定位;只定位、不打开不修改文件 ✓;失败在按钮旁给一句提示 ✓。为什么不从客户端直接调
Session Remote:编译型插件的客户端半拿不到 ctx.remote(实机诊断 no-remote ✗),详见 在资源管理器中显示)。
表格结构操作由单元格右键菜单进入,支持删除整张表格并撤销。
图片与理解标记
笔记图片通过插件保存到知识库的 image 目录(可通过 imageDir 调整),Markdown 记录相对路径。上传上限为 12 MiB;同名上传独占创建文件并自动加后缀,避免覆盖。空图注在解析时转换为空字符串,图片可以在保存后重新打开;显示时通过插件取图接口读取,再使用临时浏览器 URL,关闭编辑器会释放这些 URL。图片节点一插入就先把 src 换成 1×1 透明占位(childList 观察器,同一个微任务里完成),避免浏览器先拿相对路径去请求 dsh-app://app/image/… 而刷出一条 404、并闪一下裂图;真图取回来后再换成 blob: URL。
仅笔记编辑器标题栏提供“已理解/未理解”按钮,立即保存到库内 understanding.json,不改写笔记正文。图谱默认按理解标记着色:已理解为深绿色 #167346,未理解为浅灰色 #c6cbd0;图谱工具栏、左下角和节点右键菜单均不提供理解按钮。节点状态更新保留当前布局与相机,没有标记的节点按未理解处理。普通节点的屏幕半径固定为 6px,仅选中节点放大到 6.72px;远近通过连续的透明度和柔边表达。强调连线宽 1.2px,二维箭头约 5×4.5px。
节点正文只由人在这里编辑;模型要写正文必须先在对话里征得同意(见上面的「笔记属于你本人」)。
图片 API 集成验证:node --experimental-transform-types --test tests/note-images-api.integration.mjs(需要支持该选项的 Node)。它验证同名并发上传、磁盘字节和取图接口;常规状态与图片辅助逻辑测试为 tests/understanding.test.mjs 和 tests/note-images.test.mjs;原图预览的真实浏览器端到端测试为 tests/note-images.browser.mjs(需要 KN_PROJECT 指向 DSH 依赖仓库;宿主组件用严格照契约的替身注入模块表,组件本身由宿主仓库自己的测试覆盖)。
图片编辑器样式随插件完整打包,图注与缩放控件按需显示。图片缩放高度转换为等比例宽度,让窄窗口按正文宽度收缩;保存仍使用 Markdown 的比例值与库内相对路径。正文栏最宽 860px,面板里的宽图会被缩到约 40% 甚至更小,所以点一下图片会用宿主共享的原图预览(@deepseek-ai/dsh-client-ui-primitives 的 ImageLightbox,聊天与文档里的图片点开用的就是它)按窗口打开原图;它自己处理 Esc、点遮罩、× 关闭与焦点还原,并且用 --dsh-frame-chrome-top 避开 Windows 标题栏,右上角按钮不会被窗口控制按钮压住。代价是它按窗口等比缩放且不放大超过原图,没有 1:1 缩放(3200px 的图在 1920 窗口里约 48%,仍是正文 24% 的两倍)。普通 Markdown 节点首次保存时固化正式 ID,其理解标记同时保留。
节点对话
笔记标题栏的“对话 N”提供创建和历史选择。关联只保存在知识库的 node-conversations.json,对话本身不记录节点绑定。一条对话最多只出现在一个节点的历史里:DSH 会复用工作区里的空白会话 ⇒ 同一 sessionId 可能先后从两个节点“打开新对话”,宿主按最新一次显式认领归属,旧节点的旧记录读取时隐藏、不改写历史文件。从节点打开对话会等待目标侧栏存储可用,再恢复来源侧栏的标签及导航参数(属于别的会话的会话级资源标签不跟着走:典型是 DSH 的「修改审阅」dsh-resource://changes-review/session/<id>/…,它的摘要在宿主内存里、重启即失,重开只会刷 404),并保留笔记弹窗与最新草稿。创建关联、第一次消息、改名和归档会主动更新历史;已知空白对话隐藏,已归档项目按左侧栏筛选显示,确定已删除的对话隐藏。详见 节点对话说明、归属唯一修复 和 修复记录。
聚焦学习与节点对话
有库不代表所有对话都是学习任务。AI 根据当前对话自行决定是否查询本工作区的知识库,不要求特定关键词或模式按钮。学习问题可以先取得节点标题、别名、关系及理解标记,再按需读取当前节点、必要的关联节点和较远节点正文。结构只作为解释背景,不要求讲解整条路线,也不自动递归读取全部前置。已理解是用户自评;没有标记不代表完全不懂。必要的陌生基础先用直观语言解释,再回到当前疑问。
笔记标题栏“对话 N”只提供“打开新对话”和历史选择。打开时记录节点到对话的单向历史,不生成草稿、不附带正文、不自动发送消息。插件为首次请求提供一个临时入口线索,指导 AI 查询聚焦及结构;首轮结束或进入下一轮即失效,重新打开历史不产生入口线索。同一会话被另一个节点重新认领时,入口线索改指向最新认领的节点。它不写入 DSH 会话绑定字段,插件重启后不恢复此临时线索。
kn_current_node 默认依次查询活动界面中的笔记/实际图谱选择、首轮入口线索和此前学习目标;source: history 专门追问此前目标。自动布局指定的节点不作为实际选择。界面聚焦按会话、库根和视图实例同步;正常关闭/隐藏时清理,异常断连后租约到期清理。kn_read_node 的 role: background 用于补充材料,不替换历史学习目标;默认 role: target 保持旧调用兼容。
聚焦有效性观察整个插件面板,不依赖图谱标题栏或键盘焦点。切到聊天输入框、开发者工具或其他窗口,仍可见的笔记继续作为当前节点;隐藏、卸载或页面离开才撤销。宿主可通过会话持久元数据确认尚未装载会话的工作区,不读取聊天内容;三条来源都拿不到该会话工作区时以面板报的库为准(面板报的根必须先解析成真实知识库,聚焦仍只作用于该会话自身;会话库能解析、且确实是另一个库时依旧拒收)。聚焦上报失败记录在 kn_status 的 clientDiag 中,区域为 view-focus(拒收时把两个库根一起写进原因,一眼看出是"写法不同"还是"串库")。归属校验比较解析后的库根(工作区路径与 …/.dsh_knowledge 两种写法都认);精确查不到时按会话内最近活跃的视图回落、并用那个视图自己的库根去找节点 ⇒ 不再出现"面板里开着笔记却说没有当前节点"。无可靠当前节点时不能把库根或总览第一项当作用户当前节点。详见 当前笔记识别修复。
全库结构默认每页最多 200 个节点、400 条关系、24,000 个 JSON 字符,分别通过 structureMaxNodes、structureMaxEdges、structureMaxChars 配置;局部图仍使用 modelMaxNodes/modelMaxEdges。节点和关系独立分页,完成的一侧用对应总数作为偏移,续页传回 revision,结构变化时从零重查。笔记长度预算不变。聚焦租约 focusLeaseMs 默认 45,000 毫秒,最小 3,000 毫秒,客户端按宿主返回值每三分之一租约续期。
实现与验证见 结构上下文及聚焦学习优化,此前实现见 聚焦学习实现记录。配置默认值在插件中解析,不修改 DSH 本体、会话格式、普通工具或全局配置。DSH 原有文件工具仍可读取文件,因此这些策略不能保证模型绝不通过其他工具扫描知识库。
No comments yet. Be the first to write one.