前言¶
在 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或 CLIingest,或在面板触发 reindex。 - 检索命中只应驱动是否调用
open;不要把 snippet 当作唯一事实来源。
结尾¶
dsh-mem 把 DSH 会话日志变成可丢弃、可重建的 SQLite FTS 索引,用 <sessionId>#seq=<n> 指针和原文切片满足「本地、零依赖、可复核」的记忆需求。若要浏览插件摘要与分类,可打开社区目录页;若要安装命令、配置键与 CLI 全貌,以 GitHub README 为准。