dsh-reflect
当你纠正模型时,一键把这条纠正变成永久规则(全局或当前项目),下次自动生效。
English | 中文
dsh-reflect 是 DeepSeek Harness (dsh) 的插件,借鉴 claude-reflect 的核心思路(纠正 → 确认 → 永久规则),并按 dsh 的 Cordis 插件体系重新实现。
- 永不静默写入:任何规则落盘前都会弹出确认条,由你决定保存到全局、当前项目、编辑后保存,或跳过。
- 两条触发路径:显式
remember:前缀直达确认流程;短提示的自动检测(中文优先)经便宜模型分类后弹出确认条。 - 立即生效 + 原生兼容:确认后规则立刻注入当前会话;同时写入
AGENTS.md的标记段,新会话由 dsh 原生的dsh-agent-instructions加载,即使停用插件也继续生效。 - 纯 Markdown 存储:规则保存在人类可读、可手改、可进 Git 的
AGENTS.md中。
安装
# 已发布 npm 包后(推荐)
dsh plugin --profile web add dsh-reflect
# 或从本地检出安装
git clone https://github.com/caimc21069065-prog/dsh-reflect.git
cd dsh-reflect && npm install && npm run build
dsh plugin --profile web add ./dsh-reflect
安装后重启 dsh web 即生效,无需任何预配置。要求 dsh >=0.2.1-rc.2(Node 20.3+)。
使用
显式触发(F1)
remember: 本项目用 pnpm,不要用 npm
消息不会以原文发给模型,而是直接弹出确认条(若确认界面不可用或内容疑似密钥,消息同样被消费,但会注入一条警告说明未保存的原因——绝不会静默消失):
┌──────────────────────────────────────────────────┐
│ 把这条纠正保存为永久规则? │
│ 保存后写入 AGENTS.md,并在之后的会话自动生效。 │
│ │
│ ○ 保存到全局 写入 ~/.dsh/AGENTS.md │
│ ○ 保存到当前项目 写入 ./AGENTS.md │
│ ○ 编辑后保存… 先修改规则文本 │
│ ○ 跳过 本次不保存 │
└──────────────────────────────────────────────────┘
选择「编辑后保存…」会进入第二轮:修改规则文本 + 选择作用域。普通情况下一次点击即可保存(成功指标:≤ 2 次点击)。
自动检测(F2)
发送一条短纠正(默认 ≤ 500 字符),例如:
不要用 npm,用 pnpm
消息照常发给模型;同时插件异步用当前会话的模型路由做一次分类({ is_rule, rule, scope_hint, confidence })。判定为可复用规则且置信度达到阈值(默认 0.7)时,弹出同款确认条——不阻塞模型回答。
立即生效(F6)
确认保存后,插件立刻向当前会话注入一条带 dsh-reflect 来源的 system-reminder 消息,模型从下一个请求开始遵守该规则;无需重启。
配置
在 profile 的 patch 行或用户层 cordis.patch.yml 中覆盖(均有默认值,零配置可用):
- name: dsh-reflect
config:
autoDetect: true # 关闭后仅保留 remember: 显式路径
detectMaxChars: 500 # 参与自动检测的最大提示长度
detectPatternGate: false # 开启后先做纠正措辞正则初筛,省一次分类调用(可能降低召回)
detectTimeoutMs: 8000 # 分类模型超时
confidenceThreshold: 0.7 # 弹出确认条的最低置信度
classifierProvider: '' # 留空复用当前会话模型路由(建议配一个便宜模型控制成本)
classifierModel: ''
rememberPrefixes: ['remember:', '记住:', '记住:']
globalAgentsFile: '' # 留空为 $DSH_HOME/AGENTS.md(默认 ~/.dsh/AGENTS.md)
projectAgentsFile: AGENTS.md
locale: zh # 确认条文案语言
存储格式
规则写入目标文件的独立标记段,与文件其余内容互不干扰:
<!-- dsh-reflect: learned rules -->
## Learned rules
- 本项目使用 pnpm,不使用 npm
- 价格一律用分(cents)表示,不要用元
<!-- end dsh-reflect -->
- 去重:同一规则(忽略大小写与多余空白)不会重复写入。
- 手工编辑:标记段之间可自由增删改;启动后的会话不追踪外部修改,新会话读取最新内容。
- 保护:标记不配对(损坏)时拒绝自动写入并记录错误,绝不盲写整个文件。
- 写入:经 dsh 文件系统服务的版本守卫做读-改-写,与人类/模型的并发编辑竞争时自动重试。
降级行为
| 场景 | 行为 |
|---|---|
| 分类模型不可用 / 超时 / 输出非法 | 静默跳过该候选,不打断会话 |
| 分类进行中又收到新候选 | 排队(同一 agent 保留最新一条),当前分类结束后自动处理 |
| 确认 UI 不可用(headless)或应答被取消 | 触发消息被消费,同时注入一条「规则未保存」的警告通知,并记录日志——绝不静默吞掉 |
| 用户开始新的对话输入 | 未应答的自动检测确认卡自动作废(避免旧卡片悬挂误导) |
remember: 内容疑似密钥 / 保存前编辑引入密钥 |
拒绝写入并注入警告通知,绝不落盘 |
| 规则已存在(重复保存) | 不重复写入,注入「已存在」提示 |
| 目标文件标记段损坏 / 写入失败 | 拒绝盲写并注入提示,logger.error 记录原因 |
| 确认语 / slash 命令 / 过长提示 | 不进入检测 |
| 并发写入竞争(版本过期) | 自动重读重试;权限等确定性失败立即报错 |
设计决策(对应需求文档 §13 开放问题)
- 注入时机:不注册常驻 system-prompt 段。新会话的 AGENTS.md 由 dsh 原生
dsh-agent-instructions作为工作区指令加载;当前会话用一次性agent.inject()通知。二者叠加会导致规则重复注入,因此 MVP 刻意二选一:会话内即时通知 + 跨会话原生加载。 - 确认 UI:复用
ctx.userQuestions.ask()的通用问题卡片(四个选项 + 自定义输入),不自绘 Web 组件,避免依赖未公开的 Slots API。 - 项目作用域:以
ctx.workingDirectory的会话有效目录为准(<cwd>/AGENTS.md),与 dsh 的目录语义一致。 - 多 profile:规则文件是全局/项目两级路径,天然跨 profile 共享;插件本身随 profile 安装。
- 远程(SSH)会话:文件写入走会话的
ctx.fsprovider。项目作用域随之落到远端项目目录(符合直觉);全局作用域则会写到远端机器的~/.dsh/AGENTS.md——这与 dsh 原生dsh-agent-instructions读取全局链的方式一致,但多机 SSH 用户的全局规则会分散在各自远端主机上,需要知晓这一点。 - 成本:默认配置下自动检测用会话主模型路由,每条短消息多一次小调用;建议把
classifierProvider/classifierModel配成便宜模型,或开启detectPatternGate正则初筛。子代理收到的用户消息也会触发一次分类(确认阶段会被DELEGATED_CALLER拦下),这部分成本暂无法用公开 API 提前规避。
开发
npm install
npm run typecheck # tsc --noEmit(对齐已发布的 dsh 类型)
npm test # vitest:规则段/检测/确认流程/存储/真实 Cordis 挂载
npm run build # 输出 lib/(ESM,.ts 导入自动改写为 .js)
源码结构:
src/index.ts 插件入口:pre-step 拦截 + inbox 检测 + 保存编排
src/confirm.ts 确认条流程(userQuestions 两轮问答)
src/storage.ts ctx.fs 读-改-写(版本守卫 + 重试)
src/rules.ts 标记段解析/插入/去重(纯函数)
src/detect.ts 快速过滤 + 分类器提示词/JSON 解析(纯函数)
src/notice.ts 立即生效通知消息(dsh-reflect source kind)
src/config.ts Schemastery 配置模式
src/text.ts 消息文本提取与 remember: 前缀匹配
范围(Non-goals)
MVP 只做「纠正 → 确认 → 永久规则」一条链路:不做通用记忆、历史扫描、skill 生成、多记忆后端、团队同步。参见需求文档 dsh-reflect-requirements.md。
License
MIT
No comments yet. Be the first to write one.