AI学习 · dsh-learn-skills
一个跑在 DeepSeek Harness 输入区的学习插件。 把「收集 → 提炼 → 关联 → 升级 → 沉淀 → 复用」做成有交互引导、有预设管理、有审核入库、能给自己体检的运行时能力,而不只是一叠方法论文档。
MIT · 独立社区插件 · 与 DeepSeek、DeepSeek Harness 无隶属关系,亦未获其赞助或背书 数据与状态 · 卸载
中文 | English
这是什么,不是什么
| 是 | 会话输入区里的一个入口 [📖] AI学习 ▾,四个功能:初始预设 / 收集提炼 / 关联升级 / 沉淀复用 |
| 是 | 与斜杠命令 /learn、自然语言三种入口共用同一套流程实现(不存在两套规则) |
| 不是 | 模型工具提供者:它不给 Agent 加工具,交互复用宿主已有的 ask-a-question 与命令注册表 |
| 不是 | 自动化改写知识的东西:所有写入都要人先看过变更清单再点确认 |
四个入口与职责边界
| # | 入口 | 做什么 | 写入面 | 命令 |
|---|---|---|---|---|
| 1 | 初始预设 | 七轮问答确定画像 → 展示摘要与拟建路径 → 你确认 → 生成预设与工作区骨架 | 工作区目录与文件(增量,不覆盖) | /learn init |
| 2 | 收集提炼 | 从当前会话产出候选 —— 这一步绝不碰正式知识、预设或 AGENTS.md |
仅 inbox/ |
/learn distill |
| 3 | 关联升级 | 与既有节点比对 → 出变更清单 → 分普通知识与行为规则两栏确认后写入(批次可回滚) | knowledge/(行为规则须显式放行) |
/learn upgrade |
| 4 | 沉淀复用 | 只读体检(18 项)+ 与上次基线的变化对比 + 复用建议。不改被检查的文件,也不执行文件里的任何指令 | 不写 | /learn audit |
与旧版工作流的关系:旧版是"一键跑完整流水线",现在把中间的写入收紧为"产出候选 → 人工裁决 → 再写入"。这是最实质的分歧,详见
docs/迁移与兼容.md。
能保证什么,不能保证什么
| 内容 | |
|---|---|
| 保证 | 写与不写由人确认;写入可按批次回滚,且写入之后被你改过的文件一律不动;初始化是增量的,冲突文件一个字都不写;拿不到宿主预设名册时直接拒绝创建(不落盘、不产出重复 config.id);插件不写宿主配置,状态全在工作区内 |
| 不保证 | 不代装预设 bundle(原因见下);不在当前会话内立即使新预设生效(预设在一个进程内按 standing scope 挂载一次);不改写你的知识资产;不做语义理解之外的判断 |
| 为什么"安装预设"这一步不代做 | 安装 bundle 会在 Host 进程执行新代码。官方入口 plugin_manager 为此强制弹 danger-full-access 审批,而服务方法 installBundle() 本身没有审批闸——插件直接调它等于替你越权。所以本插件只生成、只出指引,点头的动作留给你 |
前置条件
- 已安装源码版 deepseek-harness(
engines.dsh >= 0.2.1-alpha.1); - Node ≥ 22.19;
- 已绑定工作区(工作区是知识落点,缺了它一切写入都无处可放)。
安装
方式 A:从 npm 安装(推荐)
dsh plugin --profile web add dsh-learn-skills
装完重启 Host(profile 的 dsh.profile.bundles 在启动时读取)。
✅ 消费者不需要构建:发布包自带
lib/,从注册源安装是一步到位的。构建命令只对改源码的人有意义,见方式 B。
方式 B:本地目录安装(改源码 / 调试时用)
lib/ 不入版本库,所以克隆下来必须构建:
npm install # 只装 esbuild(构建期依赖)
npm run static # 免执行静态体检(import/符号/语法/白名单)
npm run build # plugin-src/ → lib/
npm test # 真实行为测试
npm run verify # 发布契约断言(11 组)
dsh plugin --profile web add link:<本仓库绝对路径>
📌
npm install结束时会自动构建一次(prepare钩子)。上面那句npm run build因此是幂等的复跑,不是必做步骤——保留它是为了让"构建"在流程里显式可见。
检查装载是否成功
- 输入区工具行出现
[📖] AI学习 ▾(在「工作区内修改」控件右侧); - 斜杠菜单里出现
/learn; /learn help列出四个入口。
想撤掉它:见卸载。
快速开始:从零生成并启用一个预设
装好不等于能用。四步的落点是一个已经装进名册、能在新会话里选中的预设。
- 给什么输入 —— 一个名字,以及「职业 | 面向什么 | 期望达到什么」三段式一条文本。
- 做什么操作 —— 点
[📖] AI学习 ▾→ 初始预设 → 走完七问(每题可返回修改)→ 看完摘要与拟建路径 → 点「确认创建」 → 按提示自己安装生成的 bundle。 - 结果出现在哪 —— 工作区被增量补齐;预设本体落在
<工作区>/.dsh/preset-bundles/<预设 id>/(恰好两件:package.json+cordis.patch.yml);界面给出结构自证与安装指引。 - 怎样判断符合预期 —— 装完 bundle 后新建会话,在预设选择器里能看到你起的名字;输入区出现
[📖] AI学习 ▾。旧会话里看不到新预设是正常现象(预设按 standing scope 挂载一次,不热更新)。
日常使用
主线,端到端。 干完一段活 → 收集提炼(产出候选)→ 关联升级(看变更清单、分别确认普通知识与行为规则)→ 沉淀复用(只读体检,看与上次基线的变化)。
第二次及以后的最短路径。 知识库已就绪时,后三项会先识别已有知识库:识别到就直接用,识别不到才引导你先做「初始预设」。
三种触发方式,同一套实现:① 输入区按钮 [📖] AI学习 ▾;② 斜杠命令 /learn;③ 自然语言(由工作区技能引导到同一套流程)。不存在两套规则。
执行中的两条保证:重复点击不会产生并发写入(同一工作区同时只允许一个流程,第二次会被明确拒绝);取消后不再启动后续写入步骤,已完成的步骤如实汇报。
斜杠命令
/learn help 列出四入口
/learn init 七轮问答(确认创建要在界面上点)
/learn distill 从当前会话产出候选
/learn upgrade [批次号] 出变更清单 / 写入
/learn audit 只读体检
/learn rollback <批次号> 回滚某个变更批次
/learn rollback <批次号> --dry-run 只列出将要删除/还原的文件,不做任何改动
需要"确认"的步骤(创建预设、写入变更)在命令侧用 --confirm 表达,但默认路径是界面上确认——因为要让人先看清变更清单。
自然语言
插件不拥有模型工具,所以"自然语言入口"由工作区技能 learn-* 承担:你直接说「帮我初始化学习体系」「把这次会话里的内容提炼成候选」,Agent 读技能后调用同一套流程。
七个问题问了什么
前两题固定,第 3 题起由模型逐轮现场生成(每轮带上已采集的全部信息、剩余轮次与已问话题);模型不可用时逐轮回退到硬编码题库,流程不中断。
| # | 主题 | 要点 |
|---|---|---|
| 1 | 名字 | 自由输入;空值/长度/保留名/非法字符都校验;重名请你换名,不覆盖也不替你改名 |
| 2 | 身份 · 面向 · 期望 | 三段式一条文本:职业 | 面向什么 | 期望达到什么;只填一段就只当职业,其余保持未知;不索要单位/真名等无关信息 |
| 3 | 关注方向 | 模型按你的三参数出题;降级时按「场景池 → 职业池 → 通用池」三级匹配给 7 个方向 +「其他,请输入」;支持多选与自定义 |
| 4 | 学习目标与典型任务 | 模型按上下文出题;降级时围绕固定主题给候选与自定义 |
| 5 | 当前基础与实际困难 | 同上 |
| 6 | 学习方式与输出偏好 | 同上 |
| 7 | 最想先解决的一件事 | 模型出题;降级时给"越快越好/先打基础/固定节奏"等候选——这一项决定先做什么、后做什么 |
设计上刻意的三件事:未填写 = 未知(跳过项是 null 并标注"未知 —— 未填写",不编造画像);推荐就是推荐(措辞是"可能关注",不伪称统计结论;每题可返回修改,改前置答案时后续题天然重算);模型只定题面,落库槽位固定(答案写进哪个画像字段由插件固定,避免模型绕过"未填写=未知"的归一化而静默丢数据)。
七题结束后展示:画像摘要 / 预设定位 / 知识框架草案 / 拟创建或修改的路径清单,然后你才能点「确认创建」。创建完给出结构自证与安装指引:
# ① 终端一行(最省事)
dsh plugin --profile web add link:<刚生成的那个 bundle 目录>
# ② 或在「创造模式」会话里让 Agent 调 plugin_manager(会弹审批卡)
# action=install_bundle, target=<该目录>
# 复核:plugin_manager 的 list_plugins(找 preset-<id> 行)或 GUI「设置 → Agent 预设」看是否进名册
⚠️ 预设在一个进程内按 standing scope 挂载一次。新预设不会在当前会话即时生效——本插件不宣称热更新。 ⚠️ bundle 目录在工作区内,它是活的:宿主重启时按预设 id 在当前配置里解析,定义缺失的会话会被拒绝恢复。所以不要删也不要移动它。
🗑 要删掉一个预设("干净删除"四步):见
docs/删除预设.md。先记住三件事:① 新版没有"删除预设"按钮(设置页只能查看/选择/设为默认),能删的是它所在的那个 bundle;② 卸载之后还要删<工作区>/.dsh/preset-bundles/<id>/目录,并清掉known.json里的占用(否则同名重建会拿到-2后缀);③ 同包多预设时不能卸整包。
🧭 身份判据来自宿主名册:
init会先读ctx.agentPresets.list()再判重——新架构里预设身份=声明行里的config.id,而注册表不扫描目录(一份组合包可以声明很多个预设)。名册读不到时直接拒绝创建(ROSTER_UNAVAILABLE,一个文件都不写)——宁可不出件,也不出一个与既有预设重复的config.id(官方原话:「重复的 preset ID 会导致声明加载失败」)。
工作区结构
AGENTS.md 工作区原则与知识入口(精炼、稳定)
index/ 外部原始材料(保留来源与原文)
inbox/ 标准化材料、待审核候选、提炼批次
knowledge/
framework.md 正式知识体系的唯一总索引
nodes/ 正式知识节点
data/ 待分析数据(不默认转为知识或长期记忆)
task/ 学习任务、执行状态与待办
reports/ 体检报告、复盘与变化记录
.dsh/
skills/ 工作区技能
learn-skills/ 本插件状态:批次账 / 体检基线 / 变更日志 / 断点
preset-bundles/ 本插件生成的预设 bundle(★删它会连带废掉对应预设)
关于 skills/:默认不与 .dsh/skills/ 重复存技能。宿主的 skill-filesystem 只扫 <工作区>/.dsh/skills;根目录下的 skills/ 不会被加载。若确有需要独立分发的技能,请用 .agents/skills 并在文档里写明用途。
增量迁移既有工作区
初始化是增量的,绝不清空:目录不存在才建;文件内容相同 → 跳过;内容不同 → 标为 conflict 并一个字都不写,在结果里明确告诉你哪个文件被挡下了、为什么;重复运行幂等。
数据与状态
全部状态都在工作区内的 .dsh/learn-skills/,不写宿主配置:
| 文件 | 内容 | 寿命 |
|---|---|---|
session.json |
单次流程的断点(可取消、可续办) | 流程结束即清 |
batches.json |
已处理批次账 + 内容指纹("不重复创建候选"的判据) | 长期 |
audit.json |
上次成功保存的体检基线 | 长期(只增) |
known.json |
已分配过的节点 id 与预设占用 | 长期(不回收) |
changes/<批次>.json |
变更日志(回滚依据;含写入前内容) | 长期 |
预设本体落在 <工作区>/.dsh/preset-bundles/<预设 id>/。目录名可用 config.presetDir 改,整个根也可用 config.presetRoot(绝对路径)覆盖。
回滚
/learn rollback <批次号> 执行回滚
/learn rollback <批次号> --dry-run 只看计划,不动手
- 新建的节点被删除,更新过的被还原;
- 写入之后被你改过的文件一律不动,并列入"跳过"如实上报——回滚不会变成第二次覆盖;
- 结果里带每个文件的绝对路径;
- 若日志里的绝对路径与当前工作区不符(工作区搬过家、或日志被人改过),会记入
tampered并明确提示——但仍按相对路径执行,不会卡住你的回滚。
配置
cordis.patch.yml 里的全部字段都有中文注释。默认值的关键两条:
allowWrite: true # 总闸。关掉后四项功能变纯只读(初始预设只出预览)
allowBehaviorRules: false # 行为规则(预设提示词 / AGENTS.md / 技能)默认不放行
第二条是刻意的:一条知识被认可,不会自动变成长期指令。会影响 Agent 行为的那类变更,必须由人显式打开这个开关,才会在「关联升级」的确认里被执行。
语义增强(双轨并存 + 冲突标记)
默认关闭:
allowModelSemantics: false # 打开后:提炼会把会话原文发给模型做语义判定
semanticBatchSize: 8 # 一次调用判多少条(越大越省,延迟越高)
semanticBudgetMs: 60000 # 总预算;用尽即停,剩余候选走基线轨
为什么默认关:打开后会话原文会发给模型。会话里可能有客户信息、平台账号线索、内部报价——这是数据出站,属合规红线,故默认不启用。
它做什么:给「收集提炼」加一条语义轨——模型判定每条候选的类型、以及它与已有节点的关系(new/supplement/correction/conflict/duplicate/supersede/unverified),并给出 why(依据哪几个字得出的)。
为什么不覆盖基线:模型输出不可复现——同一份内容两次提炼可能给不同判定。若覆盖基线,就会出现"同一知识两次入库分类不同 → 版本号无故 +1 → 索引抖动",留痕与可回溯性当场失效。所以双轨并存:
| 轨 | 谁产生 | 可复现 | 落盘字段 |
|---|---|---|---|
| 基线轨 | 关键词正则 + 词面重合 | ✅ | type / relations(confidence: 'heuristic') |
| 语义轨 | 模型 | ❌ | typeSemantic / relationsSemantic(confidence: 'model')+ why |
两轨一致时不产生额外字段;不一致时并排显示并标 typeDivergence / relationsDivergence,审核面板会把模型建议明确标注为「模型」——最终判定仍由你裁决。
降级纪律:没有模型 / 超时 / 输出不是合法 JSON / 超预算 ⇒ 静默回退基线轨,候选照常产出。两个如实标注:语义增强部分生效时(达到预算或某批失败),界面与批次文件都会标明"未跑完";批次文件里的 semantic 摘要记录几次调用、几处分歧,便于事后回溯。模型输出一律严格校验、绝不修补——编造的候选 id、非法 type/relation 一律丢弃。
排错
装完看不到 [📖] AI学习 ▾
| 检查 | 说明 |
|---|---|
| 重启 Host 了吗 | ★ 最常见的原因。dsh.profile.bundles 在启动时读取 |
| 装对 profile 了吗 | 必须是 --profile web(客户端半侧只在 web profile 注册) |
| 包真的在吗 | dsh plugin --profile web list,或直接看 profile 的 bundles 列表 |
菜单能弹,但点了报 HTTP 404(形如 transport failure for /api/dsh-learn-skills: HTTP 404)
根因:HTTP RPC 端点没注册上。connection 服务属 Web 运行时那一层,在插件 apply() 那一刻可能尚未就绪 ⇒ 注册机会被错过。本插件不把 connection 写进静态 inject(那会让插件在无 Web 运行时的部署里整体 inactive),而是挂到它就绪之后再注册;npm run verify 的对应断言专门钉住这一点。若你确实看到这个 404,把 ~/.dsh/ 下宿主日志里 learn-skills 相关行发出来。
点「初始预设」立刻报"无法读取宿主预设名册" —— 这是刻意设计:拿不到名册就无法保证不生成重复的 config.id,宁可不落盘。此时其余三个入口不受影响。
点「确认创建」后提示"尚未安装" —— 这也是刻意的:见上文「为什么安装这一步不代做」。照提示跑那行 dsh plugin --profile web add link:<该目录>。
「收集提炼」产出为空或候选很少
| 原因 | 判据 |
|---|---|
| 本次会话内容被判为噪声 | 寒暄、空内容不计入(宁可漏判) |
| 这段消息已被处理过 | 会标 alreadyProcessed,不重复创建 |
| 会话历史不完整 | 报告里会标"部分范围";historyComplete: false 说明发生过 replace 压缩 |
| 上限截断 | stats 里如实反映,不静默丢失 |
想确认"模型到底有没有在工作" —— 判据只有一条:宿主日志里的
第 N 题未由模型生成,已回退到通用候选:<原因>。看到它就说明那一轮是降级跑的。别用"问题看起来够具体"当判据——硬编码兜底候选里也有具体选项。
选中预设就报 unknown prompt variable "{{cwd}}" —— 这是旧版生成器生成的预设,不是宿主坏了。新架构只注册 provider / model 两个提示词变量,未注册变量在插值时直接抛错;工作目录改由 working-directory 服务作为运行时上下文注入。修法二选一:重建(删掉该预设目录后重新走「初始预设」)或手改(cordis.patch.yml 里删掉 suffix: Your working directory is {{cwd}}. 整行;工作目录 {{cwd}}, → 工作目录见运行时上下文,)。体检会自己点出这类文件与行号(告警 PRESET_PROMPT_VARIABLE)。
npm run check 报"缺少必需文件"或断言失败 —— 先看它具体报哪一组(11 组每组对应一个真实失败模式)。最常见的一类是 lib/ 与 plugin-src/ 不同步:npm run build && npm run verify。
卸载
第一步:摘掉插件
dsh plugin --profile web remove dsh-learn-skills
或走 GUI:设置 → 插件,找到它移除。改完重启 Host。 卸载只是"不再装载",不会删你的数据。
第二步(可选):清掉插件留下的状态
| 路径 | 内容 | 删掉的后果 |
|---|---|---|
<工作区>/.dsh/learn-skills/ |
批次账 / 体检基线 / 变更日志 / 断点 / known.json |
丢"上次基线"与回滚依据;知识节点本身不受影响 |
<工作区>/.dsh/preset-bundles/<预设 id>/ |
本插件生成的预设本体 | ⚠️ 会连带废掉对应预设(宿主重启时解析不到定义,该预设的会话会被拒绝恢复) |
🗑 要删预设请走四步法,不要直接删目录:关行确认 → 卸包 → 删目录 → 清
known.json占用。同包多预设时不能卸整包(会带走同包里所有预设)。见docs/删除预设.md。
第三步:你的知识库不会被删**
AGENTS.md / index/ / inbox/ / knowledge/ / data/ / task/ / reports/ 都是你的资产,插件从不删它们。
只想回滚写入而不是整体卸载?用
/learn rollback <批次号>——它只还原本插件写过的,且写入之后被你改过的文件一律不动。
兼容性:要求、已验证、仍未确认
- 要求 —— Node ≥ 22.19;DSH
>= 0.2.1-alpha.1(该版本起提示词变量只注册provider/model,工作目录改由运行时上下文注入);客户端半侧只在webprofile 注册。 - 已验证 —— 四个入口与
/learn命令在该 DSH 版本上可用;npm run check的 11 组契约断言可跑通;增量初始化、批次回滚、体检基线均已实测。 - 仍未确认 —— 跨更大范围的 DSH 版本矩阵未系统验证;模型语义轨的判定稳定性未检验(同一份内容两次判定是否收敛尚未实测)。
开发
npm run static # 免执行静态体检(import/符号/语法/白名单)
npm run build # 构建(宿主半侧复制 + 客户端 esbuild 打包 + 装载层自证)
npm test # node --test:真实行为测试(真跑文件系统)
npm run verify # 11 组发布契约断言
npm run check # ★ 上面四步一次跑完:static → build → test → verify
npm run inspect # 产物体检
架构约定(与生态基准件 dsh-dingtalk-connector 对位):
plugin-src/是唯一真源,lib/是产物,改产物会被下次构建覆盖;- 宿主半侧只用 Node 内置模块与宿主运行时提供的包,不得把
@deepseek-ai/dsh-*写进依赖节(运行包用模块局部 Symbol 做 key,装第二份物理副本会破坏 Host 查找); - 客户端半侧只能引 react 系(平台冻结模块表),第三方依赖一律不许进;
- 客户端产物必须由 wrapper 把 bundle 嵌进
__ModuleLoader__.load的 factory 内部——放在外面会在脚本顶层执行到require("react"),整个/plugins拼接 bundle 会全灭。
反馈
遇到问题或想要新功能,提一个 issue。报问题时写上 DSH 版本和插件版本(版本看包清单或 CHANGELOG.md,本文不重复记录)。
插件把启动诊断写进 ~/.dsh/learn-skills-boot.log,贴最后几行通常就能定位;贴之前先删掉密钥和隐私信息。
许可
MIT,见 LICENSE。作者 yiyunet。与 DeepSeek、DeepSeek Harness 无隶属关系,亦未获其赞助或背书。
No comments yet. Be the first to write one.