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

会话记忆开关 Fyue7/dsh-memory-optin

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

按会话决定是否写入全局记忆,默认不记录

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · chat
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 23 天前
档位由哪些信号合成

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

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

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 10 处,展示前 10 条)
  • 发起网络请求
    client/index.js:45
    return fetch(API + '/' + action, {
  • 读取本地文件
    lib/store.js:23
    if (!existsSync(file)) return {};
  • 读取本地文件
    lib/store.js:24
    const raw = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/store.js:42
    if (!existsSync(file)) return [];
  • 读取本地文件
    lib/store.js:43
    const lines = readFileSync(file, 'utf8').split('\n').filter((line) => line.trim() !== '');
  • 写入本地文件
    lib/store.js:73
    mkdirSync(dirname(sessionsFile), { recursive: true });
  • 写入本地文件
    lib/store.js:75
    writeFileSync(tmp, JSON.stringify(sessions, null, 2), 'utf8');
  • 写入本地文件
    lib/store.js:76
    renameSync(tmp, sessionsFile);
  • 写入本地文件
    lib/store.js:128
    mkdirSync(dirname(memoryFile), { recursive: true });
  • 写入本地文件
    lib/store.js:129
    appendFileSync(memoryFile, `${JSON.stringify(record)}\n`, 'utf8');
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-home-paths@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-session@deepseek-ai/dsh-llm@deepseek-ai/dsh-commands@deepseek-ai/dsh-host-webserver@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 按会话控制记忆写入
  • 默认不写入全局记忆
  • 输入框按钮切换

给 DSH 加一个会话级的记忆开关:每个对话由你决定要不要进全局记忆,默认不进。输入框工具行里的按钮 + 跨会话摘要注入。非官方插件。

README

由 DeepSeek 最新模型翻译生成
dsh-memory-optin 给 DSH 加一个开关,决定「这个对话要不要进全局记忆」,就放在输入框工具行里、权限选择器旁边。 默认不进:你不点它,这个对话就不会被写进任何地方。 装上它 把本仓库克隆到任意路径,然后在 DSH 的插件管理里按 file: 路径安装成 bundle——安装目标写 file:<你的路径>/dsh-memory-optin,装完重启 DSH。 手动做法等价于两步:往目标配置档的 package.json 里加依赖 "dsh-memory-optin": "file:<你的路径>/dsh-memory-optin",再把 dsh-memory-optin 加进同一个文件的 dsh.profile.bundles 数组,然后 pnpm install 并重启。 装好后输入框工具行左侧会多一个「💤 记忆」按钮,默认不亮。 它做什么 | 方向 | 行为 | | 读(注入) | 每轮把全局记忆里最近的若干条挂进请求尾部的 runtime-context 快照,任何会话都能读到 | | 写(捕获) | 只有你打开开关的会话才会被记账;写进去的是模型压缩过的一行行结论,不是原始对话 | 开关状态按会话保存,重启后还在。 三个开关入口 1. 输入框里的记忆按钮(主入口)——💤 记忆 = 不进;点一下变 🧠 记忆·开。
展开完整文档(README 剩余 1 节)
dsh-memory-optin

给 DSH 加一个开关,决定「这个对话要不要进全局记忆」,就放在输入框工具行里、权限选择器旁边。
默认不进:你不点它,这个对话就不会被写进任何地方。

装上它

把本仓库克隆到任意路径,然后在 DSH 的插件管理里按 file: 路径安装成 bundle——安装目标写 file:<你的路径>/dsh-memory-optin,装完重启 DSH。

手动做法等价于两步:往目标配置档的 package.json 里加依赖 "dsh-memory-optin": "file:<你的路径>/dsh-memory-optin",再把 dsh-memory-optin 加进同一个文件的 dsh.profile.bundles 数组,然后 pnpm install 并重启。

装好后输入框工具行左侧会多一个「💤 记忆」按钮,默认不亮。

它做什么

| 方向 | 行为 |
| 读(注入) | 每轮把全局记忆里最近的若干条挂进请求尾部的 runtime-context 快照,任何会话都能读到 |
| 写(捕获) | 只有你打开开关的会话才会被记账;写进去的是模型压缩过的一行行结论,不是原始对话 |

开关状态按会话保存,重启后还在。

三个开关入口

1. 输入框里的记忆按钮(主入口)——💤 记忆 = 不进;点一下变 🧠 记忆·开。
2. /memory 命令——/memory on|off|status|list。
3. 配置文件——enabled 关掉就是整个插件不注入也不生效。

数据在哪

~/.dsh/dsh-memory-optin/
├── sessions.json 每个会话的开关(默认关,没打开过就不写) └── memory.jsonl 全局记忆,一行一条 JSON

memory.jsonl 一行长这样:

{"at":1791479200000,"sessionId":"session-xxxx","text":"- 决定了用插件而不是 skill 实现全局记忆"}

想清空记忆就直接删 memory.jsonl;想撤销某个会话的开关就编辑 sessions.json。

摘要怎么来的

回合收尾时把本轮攒下的对话交给模型压成最多三条、每条一行的结论。
触发点挂在 session/event 的 turn/end 上——那是本插件里唯一有硬证据能收到的事件(openviking 靠它攒了几千条待写);agent/turn-stopping 只当兜底。两者都调同一个
flushTurn(),缓冲取走即删,所以重复触发幂等。

这一趟故意不阻塞回合收尾——一发即忘,失败只记日志,不让你为记忆多等时间。

模型路由复用本会话真实用过的那一条(从 agent/request 拿到),拿不到就退回默认模型。

出问题时看哪里

POST /memory-optin/api/debug 会吐出链路各步的计数:

{"build":"diag-1","enabledIds":[],"seenSessionIds":[],"buffers":[],"routes":[],
"diagnostics":{"events":0,"userMessages":0,"assistantMessages":0,"turnStopping":0,
"summarizeAttempts":0,"summarizeFailures":0,"lastError":""}}

断在哪一步一目了然:events 为 0 就是事件根本没收到;assistantMessages 为 0 是过滤条件写错了; summarizeFailures 非 0 就看 lastError。build 是"进程有没有加载到你改的那份代码"的探针,详见下一节。

改这个插件时注意(踩过的坑)

DSH 那份 pnpm-workspace.yaml 设了 nodeLinker: hoisted,于是本地 file: 依赖不是软链,而是硬链接拷贝。改完源码有两步,缺一步就会对着旧代码调半天:

node tools/sync.mjs # 1. 把 lib/ 和 client/ 同步进运行时那份拷贝
2. 完全退出并重开 DSH —— 进程里已加载的 ESM 模块不会被换掉

判断自己是不是在对着旧代码:/memory-optin/api/debug 返回的 build 字段。
它跟源码里那个常量对得上,才说明进程真的换了模块。只重启不同步、或者只同步不重启,两种情况都会让你看到旧行为,而且没有任何报错。

配置项

| 键 | 默认 | 说明 |
| enabled | true | 整个插件总开关 |
| injectLimit | 6 | 每轮注入几条最近的记忆;0 = 不注入 |
| injectMaxChars | 1200 | 注入段字符上限 |
| summarize | turn | turn = 每轮收尾摘要一次;off = 只攒不摘 |
| summarizeMaxInputChars | 8000 | 单次摘要的输入字符上限 |

实现要点(给自己以后看)

- 为什么必须是插件:开关要长在输入框里(客户端槽位)、状态要跨会话落盘、捕获与注入要分别挂在 session/event 和 systemPrompt 上。这三件事里没有一件是 skill、纯提示词或一个工具函数能做的。
- 开关不用会话投影:投影没有写入 API,apply 还必须是同步纯函数,装不下一次鼠标点击。
所以状态由插件自己持有、按 sessionId 落盘。
- 客户端往 conversation.input.left 注册;该槽位的 standardProps 里有 sessionId。
- 客户端与宿主之间走宿主自己的两个 POST 路由(/memory-optin/api/state、/set),不碰 typert/Remote 那一套。
- 捕获的事件:user/message(只收 source.kind === 'user' 的,注入的 AGENTS.md 之类不算)与 assistant/message(只取 text 块)。

已知边界

- 摘要质量取决于模型;想把关就设 summarize: off,然后自己在对话里说「记住…」——但此时插件只负责攒,不负责挑。
- 注入走 systemPrompt.context,不能挪回 systemPrompt.section。section 是请求头部,而记忆块每写一条就变一次:实测它落在系统提示词第 2058 字(约 1152 token),后面压着 4.6 万字的工具 schema 和整段对话,一变就全部作废 —— 那一次请求命中率 0.4%,单次能把一个 49.6 万 token 的请求整段重算。挂到请求尾部的 context 之后,头部逐字不变,写入只影响尾巴。
- 进提示词的记忆文本要过 sanitizeBraces:宿主会对 section/context 文本做 {{变量}} 插值,一个没注册的引用就会让组装抛错、会话直接不可用。
- 注入永远是开的(除非 enabled: false)。这是有意的:记忆只写不读等于没有。
- 记忆是纯文本追加,没有向量检索、没有去重。条目多了以后注入的是最近 N 条,不是最相关的 N 条。真正需要相关性时再上检索。
预览分享卡片长什么样 ↓Fyue7/dsh-memory-optin
分享 · DeepSeek Harness Hub
Fyue7/dsh-memory-optin

按会话决定是否写入全局记忆,默认不记录

回到顶部