🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

常驻记忆 assassinhhy/dsh-memory

DeepSeek Harness
assassinhhy11 天前有提交已提供中文文档扫描:含敏感能力

为会话注入用户画像与长期记忆,支持检索与整理

30.4/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add assassinhhy/dsh-memory
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · chat
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 11 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 30 处,展示前 30 条)
  • 读取本地文件
    packages/dsh-memory/index.js:207
    const userText = await readFile(fileFor(root, 'user'), 'utf8').catch((error) => error?.code === 'ENOENT' ? '' : Promise.reject(error))
  • 读取本地文件
    packages/dsh-memory/index.js:208
    const memoryText = await readFile(fileFor(root, 'memory'), 'utf8').catch((error) => error?.code === 'ENOENT' ? '' : Promise.reject(error))
  • 执行外部命令固定命令
    packages/dsh-memory/index.js:515
    if (process.platform === 'win32') spawn('explorer.exe', [root], { detached: true, stdio: 'ignore', windowsHide: false }).unref()
  • 发起网络请求
    packages/dsh-memory/lib/client.js:213
    fetch('/dsh-memory/state', { cache: 'no-store', credentials: 'same-origin' })
  • 发起网络请求
    packages/dsh-memory/lib/client.js:234
    return fetch(path, init)
  • 发起网络请求
    packages/dsh-memory/lib/client.js:245
    fetch('/dsh-memory/entry', {
  • 发起网络请求
    packages/dsh-memory/lib/client.js:260
    fetch('/dsh-memory/entry', {
  • 发起网络请求
    packages/dsh-memory/src/client.src.js:211
    fetch('/dsh-memory/state', { cache: 'no-store', credentials: 'same-origin' })
  • 发起网络请求
    packages/dsh-memory/src/client.src.js:232
    return fetch(path, init)
  • 发起网络请求
    packages/dsh-memory/src/client.src.js:243
    fetch('/dsh-memory/entry', {
  • 发起网络请求
    packages/dsh-memory/src/client.src.js:258
    fetch('/dsh-memory/entry', {
  • 读取本地文件
    packages/dsh-memory/src/consolidate.js:193
    return await readFile(file, 'utf8')
  • 写入本地文件
    packages/dsh-memory/src/consolidate.js:201
    await mkdir(dirname(file), { recursive: true })
  • 写入本地文件
    packages/dsh-memory/src/consolidate.js:203
    await writeFile(tmp, content, 'utf8')
  • 写入本地文件
    packages/dsh-memory/src/consolidate.js:205
    await rename(tmp, file)
  • 删除本地文件
    packages/dsh-memory/src/consolidate.js:208
    await rm(tmp, { force: true })
  • 删除本地文件
    packages/dsh-memory/src/consolidate.js:211
    await rm(file, { force: true })
  • 写入本地文件
    packages/dsh-memory/src/consolidate.js:212
    await rename(tmp, file)
  • 读取本地文件
    packages/dsh-memory/src/consolidate.js:265
    names = await readdir(reviewDir())
  • 发起网络请求
    packages/dsh-memory/src/embed.js:47
    env.fetch = (url, init) => undici.fetch(url, { ...init, dispatcher })
  • 写入本地文件
    packages/dsh-memory/src/index-db.js:81
    if (file !== ':memory:') await mkdir(dirname(file), { recursive: true })
  • 写入本地文件
    packages/dsh-memory/src/store.js:48
    await mkdir(dirname(file), { recursive: true })
  • 写入本地文件
    packages/dsh-memory/src/store.js:50
    await writeFile(tmp, content, 'utf8')
  • 写入本地文件
    packages/dsh-memory/src/store.js:52
    await rename(tmp, file)
  • 删除本地文件
    packages/dsh-memory/src/store.js:55
    await rm(tmp, { force: true })
  • 删除本地文件
    packages/dsh-memory/src/store.js:58
    await rm(file, { force: true })
  • 写入本地文件
    packages/dsh-memory/src/store.js:59
    await rename(tmp, file)
  • 读取本地文件
    packages/dsh-memory/src/store.js:65
    return await readFile(file, 'utf8')
  • 读取本地文件
    packages/dsh-memory/src/store.js:145
    names = await readdir(archiveDir())
  • 读取本地文件
    packages/dsh-memory/src/store.js:172
    names = await readdir(dir)
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

为 DeepSeek Harness 提供 Hermes 风格的有界长期记忆插件(USER/MEMORY、本地 bge-m3、每周整合)

README

由 DeepSeek 最新模型翻译生成
dsh-memory DeepSeek Harness 的有界常驻记忆插件。USER.md 与 MEMORY.md 在新会话开头冻结注入;日记只检索、不常驻。全文以 Markdown 为准,SQLite 只是可重建的索引。 兼容 DeepSeek Harness >=0.2.1-0 <0.3.0(见 packages/dsh-memory/package.json 的 engines.dsh)。插件不改写 AGENTS.md,不读不写 .credentials.yaml,也不改 LLM provider 或默认模型。 功能 - 常驻记忆:USER.md(画像、偏好、禁忌,2000 字符)与 MEMORY.md(环境、约定、踩坑,8000 字符)。超限整次拒绝,不截断。 - 日记:journal/YYYY-MM-DD.md,按 Asia/Shanghai 分日。只参与检索。 - 工具:写入、按 id 或锚点改删、列出、混合检索、置顶、重建索引、立刻周整理,以及包装官方 sessionQuery 的 session_search。 - 回合整理:默认每 6 个已完成回合,用当前会话的模型决定追加、更新、删除或不动。失败只记日志。 - 衰减:检索先融合全文和向量,再按使用情况重排。置顶不衰减。衰减不删除任何文件。
展开完整文档(README 剩余 1 节)
dsh-memory

DeepSeek Harness 的有界常驻记忆插件。USER.md 与 MEMORY.md 在新会话开头冻结注入;日记只检索、不常驻。全文以 Markdown 为准,SQLite 只是可重建的索引。

兼容 DeepSeek Harness >=0.2.1-0 <0.3.0(见 packages/dsh-memory/package.json 的 engines.dsh)。插件不改写 AGENTS.md,不读不写 .credentials.yaml,也不改 LLM provider 或默认模型。

功能

- 常驻记忆:USER.md(画像、偏好、禁忌,2000 字符)与 MEMORY.md(环境、约定、踩坑,8000 字符)。超限整次拒绝,不截断。
- 日记:journal/YYYY-MM-DD.md,按 Asia/Shanghai 分日。只参与检索。
- 工具:写入、按 id 或锚点改删、列出、混合检索、置顶、重建索引、立刻周整理,以及包装官方 sessionQuery 的 session_search。
- 回合整理:默认每 6 个已完成回合,用当前会话的模型决定追加、更新、删除或不动。失败只记日志。
- 衰减:检索先融合全文和向量,再按使用情况重排。置顶不衰减。衰减不删除任何文件。
- 周整理:用默认模型看条目摘要,写出合并、归档、晋升、冲突四类建议。建议必须人工同意后才执行。
- 设置页:设置 → 记忆。可看占用和条目、改半衰期、处理建议、恢复归档、打开目录、重建索引。

安装

需要本机已有 dsh 命令,并且 pnpm 在 PATH 上。dsh plugin 会把参数转给 pnpm。把下面的 web 换成你的 profile 名。

克隆后按本地目录安装

仓库根目录不是插件包。可安装的包在 packages/dsh-memory,入口 index.js 和设置页 lib/client.js 已经提交,克隆后不必先构建。

本地目录是 link: 安装。插件自己的依赖(@huggingface/transformers、undici)要装在包目录里,Node 才能从链接目录解析到它们。该目录带有 package-lock.json:

git clone https://github.com/assassinhhy/dsh-memory.git
cd dsh-memory/packages/dsh-memory
npm install
cd ../..
dsh plugin --profile web add ./packages/dsh-memory

Windows 上把最后一步写成 dsh plugin --profile web add .\packages\dsh-memory。

从 GitHub 安装

裸的 github:assassinhhy/dsh-memory 指向仓库根。根目录没有 package.json,这样装不上。包在子目录,用 pnpm 的 path: 参数:

dsh plugin --profile web add "github:assassinhhy/dsh-memory#path:/packages/dsh-memory"

要锁定某次提交时,把完整 SHA 和子目录写在同一个说明符里(& 需要引号):

dsh plugin --profile web add "github:assassinhhy/dsh-memory#<commit>&path:/packages/dsh-memory"

package.json 没有 prepare 脚本。git 安装拿到的就是已提交的 index.js 和 lib/client.js,不需要为构建单独放行脚本。依赖由 pnpm 按该包的 dependencies 安装。

npm 上的同名包不是这个插件

本仓库没有发布到 npm。registry 上的 dsh-memory@0.1.0 是另一位维护者的不同项目(描述为不含向量模型的 SQLite 记忆)。dsh plugin add dsh-memory 会装到那个包。请使用上面的本地目录,或带 path: 的 GitHub 说明符。

桌面 profile

desktop 经常被桌面应用占用,命令行可能改不了它。打开 DeepSeek Harness → 插件 → 添加插件,填入克隆目录下 packages/dsh-memory 的完整路径,安装并启用。这一步做一次即可。之后这个目录仍是链接,改代码并重启就会读到新文件。

可选:Windows 安装脚本

scripts/Install-DshMemory.ps1 面向已经有一份 DeepSeek Harness 源码树 的环境。它会:

1. 运行 node scripts/build.mjs,重新生成 packages/dsh-memory/lib/client.js
2. 在 packages/dsh-memory 里用 pnpm 安装插件依赖
3. 把目标 profile 的 package.json、cordis.patch.yml、pnpm-lock.yaml 备份为 .bak-mem-<时间戳>
4. 在 Harness 源码根执行 pnpm dsh plugin --profile <profile> add <clone>/packages/dsh-memory

.\scripts\Install-DshMemory.ps1 -DshRoot <Harness 源码目录> -Profiles web

省略 -DshRoot 时,脚本把本仓库的上一级目录当作 Harness 源码根。-Profiles 默认是 desktop,web。desktop 不会被脚本修改,只打印 packages/dsh-memory 的路径,供上面的「添加插件」使用。

-Proxy 默认是 http://127.0.0.1:7890,-Registry 默认是 https://registry.npmmirror.com。不使用这组代理和镜像时,传入你自己的值。脚本不改 LLM provider,也不碰 .credentials.yaml。

只有 dsh 命令、没有 Harness 源码树时,用上面的 dsh plugin add,不必跑这个脚本。

桌面版与 sharp 版本

桌面版 Harness 自带一份 sharp。若某个插件(例如本插件依赖的 @huggingface/transformers)捎带了另一个版本的 sharp,它会先把同名 libvips-.dll 加载进进程;Windows 对同名 DLL 只认第一次加载的那份,于是 Harness 自己那份 sharp 缺函数,报 ERR_DLOPEN_FAILED: The specified procedure could not be found——图片读写全废(含生成图回传进对话)。

本包用 "overrides": { "sharp": "0.35.5" } 把版本对齐到 Harness 自带的那份。Harness 升级更换 sharp 版本时,这里的 override 要跟着改。

装好之后

重启 DeepSeek Harness。新开会话才会带上记忆快照。设置 → 记忆 可以确认插件已加载。

改了 packages/dsh-memory/src/client.src.js 之后,在仓库根运行 node scripts/build.mjs(需要 Node 20 或更新),再重启。

数据目录

记忆根目录是 DSH_HOME 下的 memory/。未设置 DSH_HOME 时,用当前用户主目录里的 .dsh:

| 系统 | 默认路径 |
| macOS / Linux | ~/.dsh/memory |
| Windows | %USERPROFILE%\.dsh\memory |

设置了 DSH_HOME 时,路径是 %DSH_HOME%\memory(Windows)或 $DSH_HOME/memory。AGENTS.md 和 .credentials.yaml 在 memory/ 旁边,本插件不读写它们。

| 路径 | 上限 | 作用 |
| USER.md | 2000 字符 | 画像、偏好、禁忌。会话开头冻结注入 |
| MEMORY.md | 8000 字符 | 环境、约定、踩坑。同上 |
| journal/YYYY-MM-DD.md | 按日不限 | 日记。只检索,不常驻 |
| archive/YYYY-MM.md | 不限 | 归档。可恢复,不是删除 |
| review/YYYY-Www.json 与同名 .md | — | 周整理建议。.json 是事实来源 |
| index.sqlite | — | FTS5 trigram、向量缓存、entry_meta。删掉会重建 |
| models/ | — | bge-m3 权重。不进 git |
| session-index.sqlite | — | 官方 sessionQuery 的持久索引 |

字符按 JavaScript 的 string.length(UTF-16 码元)计算,常用汉字算 1。上限含条目标记,按整文件计。

已有的 USER.md / MEMORY.md 不会被清空。工具只追加带 id 的条目,或按你给出的 id / 锚点修改、删除。手改 Markdown 是合法的;下一次新会话才进入提示词。本会话里的快照保持不变,以免打掉 prompt cache。

条目模型:每个 - / * / + 列表项(含更深缩进的续行和子项)是一条独立条目,id 形如 l-xxxxxxxxxx;其余散文按空行分成块,id 形如 p-xxxxxxxxxx;工具写入的条目带 dsh-mem 标记,id 形如 e-xxxxxxxx:

记住我默认用 pnpm

l- / p- 是内容哈希(规范化文本的 sha256 前 10 位):插入、删除、改写别的条目都不影响它的 id。同一文档里重复文本用后缀区分(l-xxxx 与 l-xxxx~2)。改写某条后它自己的 id 会跟着内容变,返回里会给 id=旧 → 新;使用计数、置顶等元数据跟着迁移,不会变成孤儿行。只有改到的那条换字节,其余原样不动。

memory_list 一行一条:- l-… [item] 12字 📌 预览。

遗留别名 unfenced 仍可整段替换未标记正文(v0.1.0 语义,会按标记条目重组文件);日常请改用 l- / p- id,那样更精准。

疑似密钥、token、私钥或密码赋值会整段拒绝。错误只说明检测种类,不回显原文。

工具

| 工具 | 作用 |
| memory_add | 写入 user / memory / journal。返回 id、受影响条目和改动 diff |
| memory_replace | 按 id 或唯一原文锚点修改。返回 id=旧 → 新 和 diff。改动算「用过」 |
| memory_remove | 按 id 或锚点删除(永久)。返回被删 id、受影响条目和 diff |
| memory_list | 一行一条(l- / p- / e- id、字数、置顶、预览),外加字符占用。省略 target 时列出 USER 与 MEMORY |
| memory_search | FTS5 trigram + 本地 bge-m3,RRF 融合后再按衰减重排。含日记,id 与 list 一致,结果带 score / last_used |
| memory_pin | 置顶或取消置顶。USER.md 条目默认置顶 |
| memory_consolidate | 立刻跑一次周整理,只产出建议 |
| memory_reindex | 从 Markdown 重建索引 |
| session_search | 包装 ctx.sessionQuery。同一工作区,不含本会话 |

写操作的返回都带 id(替换带旧→新)、affectedIds 和一段只覆盖受影响条目的 unified diff(过长会截断并注明)。任何成功路径都不会出现 id=null。

写入主机名、端口、路径、域名、IP、账号这类稳定关键事实后,如果目标条目还没置顶,会多一行 💡 像是稳定关键事实(端口/路径…),建议 memory_pin id=…。只是建议,不会自动置顶;密钥/token 不算关键事实(本来就会被拒绝)。
超出上限时整次拒绝,不截断,并给出三组具体建议(每组带 id、字数、预览、原因):挪去日记(一次性事件、进度、日期叙事)、合并相似(三元组 Jaccard)、精简最长。结尾估算「挪走这些后可释放约 N 字,足以写入本次 M 字」。置顶条目不会被建议挪走,正在写的那条也不会。只建议,不自动删除、合并或挪动。

session_search 不自建会话全文索引。插件的 cordis.patch.yml 把 session-query-sqlite 的 openAt 从 never 改成 first-search,从而能搜到 DSH_HOME/sessions 里的旧 JSONL,索引落在 memory/session-index.sqlite。权限与官方工具一致:没有 cwd 不能跨会话;目标会话必须属于当前工作区。profile 自己的 cordis.patch.yml 若把该行又写回 never,以 profile 为准,工具会说明原因。

回合整理

默认每 6 个已完成回合,用当前会话的模型看最近对话,决定 ADD / UPDATE / DELETE / NOOP。这不是每条消息都抽一次。失败只记日志,不打断对话。

回合整理决定 DELETE 时不会硬删,而是把条目归档到 archive/YYYY-MM.md(l- / p- / e- 都支持),可在设置页恢复;归档失败就整条放弃,不会退回成删除。memory_remove 与设置页的「删除(不可恢复)」仍是永久删除。

设置 → 记忆 可以关掉(autoReview),或把间隔 reviewEvery 改成 1–100。

衰减排序

检索命中先按 RRF 融合,再按使用情况重排:

score = rrf × decay × (1 + log2(1 + use_count) × 0.25)
decay = 0.5 ^ (距上次使用的天数 / 半衰期)

默认半衰期:USER.md 60 天、MEMORY.md 60 天、journal 21 天。使用加成 useBoost 默认 0.25。置顶条目的 decay 为 1。衰减只影响排序,不删除任何东西。

「用过」指:memory_search 的结果进入回复上下文,或 memory_replace 改了这条。会话开头的整文件注入不算。

周整理

每周用当前默认模型看条目摘要(不含日记全文;每条摘录约 160 字),产出四类建议:

| 类型 | 含义 | 同意之后 |
| merge | 重复条目合并 | 保留一个 id 并改写,其余归档 |
| stale | 长期未用,建议归档 | 搬进归档,可恢复 |
| promote | 日记里的事实值得常驻 | 按建议写入 USER 或 MEMORY |
| conflict | 互相矛盾 | 列出两边;统一说法可编辑后再同意 |

- 启动时若距上次整理超过 7 天(consolidateDays)且 autoConsolidate 为开,会自动跑一次。也可以在设置页点「立即整理」,或调用 memory_consolidate。
- 建议写入 review/YYYY-Www.json 和同名 .md,带 key 和处理状态。周次按 Asia/Shanghai 的 ISO 周。
- 每条都要人工同意、拒绝,或编辑后同意。可以一键全部拒绝。未处理的建议不会自动执行。
- 置顶条目只会出现在 merge / conflict 里,不会进入 stale。
- 归档搬进 archive/YYYY-MM.md。设置页可以恢复。合并或晋升若会超过字符上限,整条拒绝并说明没有截断。

设置

打开 设置 → 记忆。这一页可以:

- 查看 USER.md / MEMORY.md 的字符占用
- 开关自动回合整理,修改每 N 轮
- 查看向量模型状态(就绪、下载中或失败)
- 打开记忆目录、重建索引、刷新
- 浏览条目:最后使用、使用次数、衰减分、置顶、归档(可恢复,含列表项与散文块)、编辑、删除(不可恢复)
- 修改衰减参数:USER / MEMORY / 日记半衰期,以及使用加成
- 处理整理建议:同意、拒绝、编辑后同意、一键全部拒绝;查看上次与下次整理时间;立即整理
- 在归档区恢复条目

插件配置里还有这些默认值(当前页面没有单独的开关):embed 默认开,vectorWaitMs 默认 2000,autoConsolidate 默认开,consolidateDays 默认 7,consolidateBatchChars 默认 6000。

向量模型在第一次需要时下载 Xenova/bge-m3 的 q8 ONNX(约 570MB)到 memory/models/。设置了 HTTPS_PROXY 或 HTTP_PROXY 时,下载走该代理;都未设置时,下载器会尝试 http://127.0.0.1:7890。代理不可用或权重还没下完时,memory_search 先返回全文结果,并标明向量未就绪。权重不进 git。

测试

在仓库根目录、使用带 node:sqlite 的 Node 运行(DeepSeek Harness 自带的运行时即可;本仓库在 Node 26 上验证过 FTS5 trigram):

node --test tests/*.test.js
node scripts/smoke-memory.mjs
node scripts/smoke-m2.mjs

覆盖字符上限、整段拒绝密钥、快照冻结、检索融合排序、工作区权限边界、衰减公式与置顶不衰减、使用计数、手改 Markdown 后的元数据对齐、整理建议 schema、置顶不进 stale、归档可恢复、超限拒绝,以及条目模型(split 规则、id 稳定性、l- 字节级改删、锚点返回非空 id、diff 内容、元数据迁移、list/search id 一致、unfenced 兼容)、稳定关键事实识别与置顶建议、超限分组建议与释放估算、回合整理 DELETE 走可恢复归档(含 l- / p- 归档与恢复)。这些测试使用临时目录。smoke-m2.mjs 在结束时核对正式记忆文件的字节没有变化;它的模型调用是 mock,不会打真实 API。

可选:node scripts/smoke-embed.mjs 会把 bge-m3 权重下载到当前 DSH_HOME/memory/models(或 ~/.dsh/memory/models)。它不改写 USER.md、MEMORY.md 或 AGENTS.md。

非目标

不做 Dreaming、知识图谱、每条消息抽取、云端 embedding、自动晋升、自动删除、自动置顶、自动合并、超限自动腾挪。周整理只产出建议;衰减只改变排序。

许可

MIT
预览分享卡片长什么样 ↓assassinhhy/dsh-memory
分享 · DeepSeek Harness Hub
assassinhhy/dsh-memory

为会话注入用户画像与长期记忆,支持检索与整理

这是你的仓库?认领条目

回到顶部