dsh-mem:为 DSH 部署零依赖本地记忆层

前言

在 DeepSeek Harness(DSH)里做长会话、多轮任务时,模型往往只能依赖当前上下文窗口。把历史对话「摘要后塞回 prompt」会引入转述误差;接外部向量库或常驻服务又增加依赖与运维面。若你希望记忆可复核、可本地重建,且检索阶段只给出「去哪看」而不是替模型改写原文,就需要一种与 DSH 会话日志对齐的本地索引方案。dsh-mem 由社区维护者 cyanxi-eb 发布,归类为「记忆」类 DSH 插件,当前 GitHub 星标为 0;它在单机内用 SQLite FTS5 从 DSH 会话日志派生可复核指针,并遵守「只回指针 + 原文切片」的检索契约。

这是什么

dsh-mem 的定位是:零依赖本地记忆层——只回指针与原文切片,不摘要、不转述、不开端口、不常驻、不调 API。实现上只 import node:*(含 node:sqlite),无第三方运行时依赖;可选向量能力通过 optionalDependencies 预留,默认关闭。

插件通过 cordis.patch.yml 一行插入,向 DSH 注册五个工具:mem_search、mem_open、mem_ingest、mem_episodes、mem_stats。同一套逻辑也提供独立 CLI:dsh-mem <cmd>,与 node bin/dsh-mem.mjs <cmd> 等价,可在不启动 DSH 的情况下对纯文本做 ingest / search / open。

社区目录页:https://www.skillhub.cn/plugins/cyanxi-eb/dsh-mem;源码与说明:https://github.com/cyanxi-eb/dsh-mem。目录站点为社区生态索引,与 DeepSeek / 幻方无官方从属关系。

三条不变量

理解 dsh-mem 的行为,可以先看 README 里写明的三条不变量:

  • I1 原文永不改写:turn.text 是会话源记录 content[].text 的逐字镜像,只 INSERT OR IGNORE,永不 UPDATE。
  • I2 索引可丢弃:删除 .db 后重跑 ingest 可 100% 重建;不存在「只有库里才有」的事实。
  • I3 只回指针 + 原文切片:返回 (sessionId, seq) 与原文子串;不摘要、不补全、不推断。0 命中就返回 0。

README 中的红线同样值得遵守:检索结果只用来判断「要不要展开」,证据永远是 mem_open(或 CLI open)输出的原文。

核心功能

索引与检索(P0–P2)

0.2 版本 README 将能力分为多层:P0 查询切分在整句中文 0 命中时切成相邻 bigram 再 OR,且「先失败才切」;P1 事件层 episode 只存区间与指纹,不存摘要文本;P2 词面重排对 P0 候选集做字符 n-gram TF-IDF 余弦重排。向量层(P3)配置键已进 config,但当前 rerank:'embedding' 按 off 处理,缺模型时不假装可用。

插件 config 中 rerank 默认 'lexical';CLI 默认 'off',需显式 --rerank lexical 才与插件侧词面重排一致——这是为了 CLI 能与冻结的老实现逐字节对账。

隐私闸与迁移

入库前(非事后过滤)可配置 redact 正则替换与 excludePaths glob,跳过指定会话或文件。支持 NDJSON 导出 / 导入(schema dsh-mem/1),便于换机迁移;import 使用 INSERT OR IGNORE,幂等。

DSH 面板(0.2)

Web 端通过 dsh.client 加载 lib/client.js,在会话顶部页签「对话 | 轨迹 | 记忆库」中提供库健康、配置与 reindex 等能力;默认收起,展开后才请求 /dsh-mem/panel/state 等路由(契约见仓库 docs/PANEL-CONTRACT.md)。

安装与启用

作为 DSH 插件(推荐)

官方 README 给出的 GitHub 直装命令如下(须带 --profile):

dsh plugin --profile <profile> add github:cyanxi-eb/dsh-mem

资料中记录:在 DSH 0.2.1-rc.5 下实测安装成功,包落入 <DSH_HOME>/profiles/<profile>/node_modules/dsh-mem,dsh.profile.bundles 会自动包含 dsh-mem。装完后需重启 DSH,五个工具才会进入工具表,面板才会出现在「记忆库」页签。

前置注意:dsh plugin 会 spawn 裸 pnpm;若系统 PATH 中没有 pnpm,命令行可能报 'pnpm' is not recognized。可将 pnpm 加入 PATH,或改用宿主 GUI 的插件管理器。若 dsh 不在 PATH,可用 README 给出的 node "<DSH>/resources/app/dsh/node_modules/@deepseek-ai/dsh/lib/bin.js" plugin ... 形式调用。

运行环境:package.json 要求 Node >= 22;许可证 MIT;当前 package 版本 0.1.0。

独立 CLI

在仓库内可直接:

node bin/dsh-mem.mjs stats

README 说明 npm i -g dsh-mem 在发布到 npm 之后可用,并注明当前未发布。CLI 与插件共用 lib/core.mjs。

主要配置项

安装后可通过 patch 注入的默认 config(节选)调整行为;完整键名以 README 与 cordis.patch.yml 为准:

config:
  workspace: ''            # 空 = 按优先级链解析工作区
  storeDir: ''             # 空 = $DSH_HOME/mem
  excludePaths: []
  redact: []
  autoIngest: false        # 默认不自动索引,需显式触发
  rerank: 'lexical'
  rerankLexical: true
  episodeEnabled: true
  episodeClosureMinutes: 10
  episodeMaxChars: 4000
  embeddingEnabled: false

workspace 解析顺序(CLI 与插件共用 core.resolveWorkspace):配置 workspace > 宿主会话 cwd > process.cwd() > profile 目录。一工作区一库,库文件按 <hash8>-<目录名>.db 分片。

典型用法

下面步骤来自 README 的可复现示例,可按「先索引、再搜、再开原文」理解。

1、入库前隐私检查

先用 dry-run 看将入库多少条、命中 redact 多少、跳过哪些路径:

dsh-mem ingest --dry-run --redact 'sk-[A-Za-z0-9]{20,}' --exclude '*scratch*'

2、增量索引工作区会话

无 file 参数时重扫本工作区 DSH 会话;插件侧对应工具 mem_ingest:

dsh-mem ingest
dsh-mem ingest --all          # 忽略水位全量重扫

也可吃外部文本:

dsh-mem ingest --file <path> [--source <name>]

3、检索与展开原文

搜索返回指针与 ≤120 字 snippet;真正作证据的是 open:

dsh-mem search "Router Worker 分工" --k 8 [--rerank lexical] [--json]
dsh-mem open "07f38d2c-...-#seq=293" --context 2
dsh-mem open "07f38d2c-...#293-441"    # episode 区间,回区间全部原文

插件工具对应关系:mem_search(query, k)→ 命中列表;mem_open(pointer, context)→ 原文行;mem_stats / mem_episodes 查看库水位与 episode 区间。

4、迁移

dsh-mem export --out mem.ndjson
dsh-mem import mem.ndjson --dry-run
dsh-mem import mem.ndjson

5、自检

dsh-mem selftest

CLI 退出码:0 正常;1 用法;2 指针不存在;3 读不到输入;4 数据损坏。空库或目录不存在会非 0 退出并说明原因。

适用场景与注意

适合谁:希望在 DSH 工作区内本地检索历史对话、又不想引入外部 API 或常驻服务的开发者;需要可审计证据链(指针 → 原文)而非模型侧「记忆摘要」的场景;需要 NDJSON 导出、换机导入或入库前 redact 的团队流程。

务必注意:

  • 插件以当前 dsh 进程权限运行,安装前应阅读源码与 MIT 许可证,自行评估 redact / excludePaths 是否覆盖你的密钥与敏感路径。
  • 默认 autoIngest: false,不会悄悄建索引;首次使用需主动 mem_ingest 或 CLI ingest,或在面板触发 reindex。
  • 检索命中只应驱动是否调用 open;不要把 snippet 当作唯一事实来源。

结尾

dsh-mem 把 DSH 会话日志变成可丢弃、可重建的 SQLite FTS 索引,用 <sessionId>#seq=<n> 指针和原文切片满足「本地、零依赖、可复核」的记忆需求。若要浏览插件摘要与分类,可打开社区目录页;若要安装命令、配置键与 CLI 全貌,以 GitHub README 为准。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜