给 DSH 的本地优先跨会话记忆:每轮自动沉淀 + 空闲自动整理 + 按需注入。数据全在本地…
30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/13 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查有告警:未发布到 npm registry,仅可从源码安装。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add eighteentang/dsh-plugin-memory-lite该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · chat
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 18 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意未发布到 npm registry,仅可从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-plugin-memory-lite(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/12 22:43:21
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 70 处,展示前 44 条)
- 写入本地文件index.js:51
appendFileSync( - 读取本地文件index.js:129
const raw = readFileSync(REGISTRY_FILE, 'utf8'); - 写入本地文件index.js:145
mkdirSync(dirname(REGISTRY_FILE), { recursive: true }); - 写入本地文件index.js:146
writeFileSync(REGISTRY_FILE, JSON.stringify({ version: 1, stores: list.slice(-50) }, null, 1), 'utf8'); - 读取本地文件index.js:190
} else if (!existsSync(dbPath)) { - 写入本地文件index.js:225
mkdirSync(dir, { recursive: true, mode: 0o700 }); - 读取本地文件index.js:298
return typeof cwd === 'string' && cwd.trim() && existsSync(cwd) ? cwd : null; - 读取本地文件index.js:316
if (!existsSync(join(dir, 'memory.db'))) return; - 读取本地文件index.js:332
if (config.globalMemory && existsSync(join(gdir, 'memory.db'))) { - 读取本地文件index.js:349
if (existsSync(root)) { - 发起网络请求client/client.js:344
const res = await fetch(`${API}${path}`, init); - 写入本地文件lib/storage.js:201
mkdirSync(dir, { recursive: true, mode: 0o700 }); - 写入本地文件lib/storage.js:205
chmodSync(dbPath, 0o600); - 写入本地文件lib/storage.js:597
mkdirSync(archiveDir, { recursive: true }); - 写入本地文件lib/storage.js:599
appendFileSync(file, rows.map((r) => JSON.stringify(r)).join('\n') + '\n', 'utf8'); - 读取本地文件lib/storage.js:916
const base = workspaceRoot && existsSync(workspaceRoot) ? workspaceRoot : null; - 读取本地文件lib/persona.js:41
if (!existsSync(file)) continue; - 读取本地文件lib/persona.js:43
out[slot] = readFileSync(file, 'utf8').replace(/^ FEFF/, ''); - 读取本地文件lib/persona.js:44
out.mtimes[slot] = statSync(file).mtimeMs; - 写入本地文件lib/persona.js:62
mkdirSync(dir, { recursive: true }); - 读取本地文件lib/persona.js:70
if (existsSync(file)) { - 写入本地文件lib/persona.js:73
mkdirSync(bdir, { recursive: true }); - 写入本地文件lib/persona.js:75
copyFileSync(file, backup); - 写入本地文件lib/persona.js:83
writeFileSync(tmp, body, 'utf8'); - 写入本地文件lib/persona.js:84
renameSync(tmp, file); - 读取本地文件lib/persona.js:88
return { ok: true, file, backup, bytes: Buffer.byteLength(body, 'utf8'), mtime: statSync(file).mtimeMs }; - 写入本地文件lib/backup.js:53
mkdirSync(join(logFile, '..'), { recursive: true }); - 写入本地文件lib/backup.js:54
appendFileSync(logFile, `${new Date().toISOString()} [${level}] ${msg}\n`, 'utf8'); - 读取本地文件lib/backup.js:67
if (!existsSync(file)) return { ok: false, reason: '文件不存在' }; - 读取本地文件lib/backup.js:68
const size = statSync(file).size; - 读取本地文件lib/backup.js:94
if (!existsSync(dir)) return []; - 读取本地文件lib/backup.js:95
return readdirSync(dir) - 读取本地文件lib/backup.js:97
.map((f) => ({ name: f, path: join(dir, f), mtime: statSync(join(dir, f)).mtimeMs, size: statSync(join(dir, f)).size })) - 写入本地文件lib/backup.js:122
mkdirSync(dir, { recursive: true, mode: 0o700 }); - 读取本地文件lib/backup.js:133
if (existsSync(tmpFile)) rmSync(tmpFile, { force: true }); - 删除本地文件lib/backup.js:133
if (existsSync(tmpFile)) rmSync(tmpFile, { force: true }); - 删除本地文件lib/backup.js:138
try { if (existsSync(tmpFile)) rmSync(tmpFile, { force: true }); } catch { } - 删除本地文件lib/backup.js:161
try { if (existsSync(`${tmpFile}${side}`)) rmSync(`${tmpFile}${side}`, { force: true }); } catch { } - 删除本地文件lib/backup.js:168
try { if (existsSync(tmpFile)) rmSync(tmpFile, { force: true }); } catch { } - 写入本地文件lib/backup.js:175
renameSync(tmpFile, file); - 写入本地文件lib/backup.js:176
try { chmodSync(file, 0o600); } catch { } - 删除本地文件lib/backup.js:180
try { if (existsSync(tmpFile)) rmSync(tmpFile, { force: true }); } catch { } - 删除本地文件lib/backup.js:204
unlinkSync(v.path); - 写入本地文件lib/backup.js:228
try { mkdirSync(dir, { recursive: true, mode: 0o700 }); } catch { return { ok: false, reason: '备份目录不可用' }; }
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 跨会话记忆结论
- 本地SQLite存储
- 按需注入记忆
README
由 DeepSeek 最新模型翻译生成dsh-plugin-memory-lite
给 DSH 的本地优先跨会话记忆:每轮自动沉淀,空闲时自动整理,需要时按需注入。
数据全部存在本地 SQLite 文件里 —— 不联网、不上传、不依赖任何外部记忆服务。
它解决什么
DSH 的会话本身是有记忆边界的:换一个会话、或者一次压缩(compact)之后,之前聊过的结论就找不回来了。你得反复重新交代「我们用两层架构」「那个坑别再踩」。
这个插件在后台做三件事:
| 层 | 做什么 | 什么时候 | 成本 |
| 日志层 | 每轮结束把对话原样追加到本地 | 自动,每轮 | 零模型调用 |
| 长期条目层 | 把日志里的结论蒸馏成「记忆条目」 | 你点「立即整理」时(也可开启空闲自动) | 每次一次模型调用 |
| 注入层 | 把你这句话相关的记忆作为独立消息追加到对话尾部 | 自动,每轮 | 零成本 |
日志层永远不进提示词 —— 只有蒸馏后的条目才会被注入。
否则上下文预算和前缀缓存都会被日志淹没。
日志层存的不是「逐字原样」:落盘前会剔掉宿主注入的系统样板(<system-reminder> 里的用户全局 AGENTS.md 等),也会去掉与前文重复的部分(实测 10 轮对话曾因此写出 804 KB,相邻两条有 6/9 对是「后一条完整包含前一条」)。没有内容的轮次干脆不记。
展开完整文档(README 剩余 1 节)
dsh-plugin-memory-lite 给 DSH 的本地优先跨会话记忆:每轮自动沉淀,空闲时自动整理,需要时按需注入。 数据全部存在本地 SQLite 文件里 —— 不联网、不上传、不依赖任何外部记忆服务。 它解决什么 DSH 的会话本身是有记忆边界的:换一个会话、或者一次压缩(compact)之后,之前聊过的结论就找不回来了。你得反复重新交代「我们用两层架构」「那个坑别再踩」。 这个插件在后台做三件事: | 层 | 做什么 | 什么时候 | 成本 | | 日志层 | 每轮结束把对话原样追加到本地 | 自动,每轮 | 零模型调用 | | 长期条目层 | 把日志里的结论蒸馏成「记忆条目」 | 你点「立即整理」时(也可开启空闲自动) | 每次一次模型调用 | | 注入层 | 把你这句话相关的记忆作为独立消息追加到对话尾部 | 自动,每轮 | 零成本 | 日志层永远不进提示词 —— 只有蒸馏后的条目才会被注入。 否则上下文预算和前缀缓存都会被日志淹没。 日志层存的不是「逐字原样」:落盘前会剔掉宿主注入的系统样板(<system-reminder> 里的用户全局 AGENTS.md 等),也会去掉与前文重复的部分(实测 10 轮对话曾因此写出 804 KB,相邻两条有 6/9 对是「后一条完整包含前一条」)。没有内容的轮次干脆不记。 安装 命令行: dsh plugin --profile <你的profile名> add github:eighteentang/dsh-plugin-memory-lite#v1.3.0 或者在界面里装(不用命令行):侧边栏 「插件」→「添加插件」,把地址贴进去。 那个输入框接受包名、Git 地址、压缩包、本地绝对路径四类写法: | 贴什么 | 结果 | | https://github.com/eighteentang/dsh-plugin-memory-lite#v1.3.0 | ✅ 装指定版本(推荐) | | https://github.com/eighteentang/dsh-plugin-memory-lite | ✅ 跟随主分支 | | github:eighteentang/dsh-plugin-memory-lite#v1.3.0 | ✅ 同上两种写法都行 | ⚠ 别贴 Releases 页的地址。 …/releases/tag/v1.3.0 会被直接拒绝(提示 a URL must point at a git repository or a tarball)—— 它只认仓库根地址或压缩包链接;版本要写成 #v1.3.0 拼在根地址后面。同理 …/tree/main 这类网页地址也不行。 这几条不是猜的:宿主侧的解析函数 parseInstallSpec 曾被抽出来逐例跑过(那是开发者本机的诊断脚本,不随仓库发布 —— 见下方「关于本仓库不含开发工具」)。 装完后重启客户端,设置页会出现 「记忆控制」。 #v1.3.0 是版本钉子 —— 钉住版本避免「装到一半上游改了」。 去掉 #… 就是跟随主分支(自动拿到新改动,也自动拿到新 bug)。 全部版本见 CHANGELOG.md;升级就是先卸载再装新版(DSH 的插件目前不支持自动更新)。 开发期用 link: 装(link:D:/path/to/memory-lite)也是支持的,但必须保留 peerDependencies,否则插件的包解析会失败。 怎么用 平时不用管 - 每轮对话结束,它自动把这一轮记下来(不花模型额度) - 每句用户消息到达时,它按关键词找相关记忆,注入到对话尾部 - 整理成条目默认要你手动点(避免「没打招呼就花额度」)。 想让它自己长出来,把 autoDistill 设成 true —— 那样空闲 30 分钟后会自动整理(每天最多 4 次,见下面配置)。 想手动做点什么 设置页 →「记忆控制」分成上下两块: - 上面两个文本框:人设设定 / 工作规范与行为准则 想写什么就写什么 —— 没有任何格式要求(不用标题、不用 markdown)。 两块内容存在插件自己的两个文件里: $DSH_HOME/memory-lite/persona/persona.md ← 人设设定 $DSH_HOME/memory-lite/persona/rules.md ← 工作规范与行为准则 它们被注入成 system prompt 的一段(位置紧跟框架自己的人设段)—— 所以是 每一轮都生效,不像记忆库那样靠召回(规范类的东西「这轮没命中」就等于静默失效)。 保存后下一轮立刻生效,不用重启;写前自动备份到同目录的 backup/。 代价:它们随插件走 —— 插件停用/卸载,人设与准则就不生效了。 - 下面是长期记忆列表:搜索、按状态筛选、改状态(在用 / 已完成 / 已停用)、点「立即整理」。 列表是一行一条、行行等高(层级 · 项目 · 标题 · 敏感 · 用过N次 · 状态), 不展示正文 —— 标题/项目太长会省略号截断,鼠标悬停看全文。 「用过几次」显示成 3×(悬停会说明「被自动注入过 3 次」,– 表示还没用过)。 想手动记一条记忆:直接在对话里说(memory_note),比在界面上敲更快、还能带上上下文。 - 对 DSH 说(这些是模型可见的工具): - 「记住:这个项目用两层记忆架构」→ memory_note - 「搜一下我之前说过关于注入的东西」→ memory_search - 「把那条标记成已完成」→ memory_update - 「忘了那条吧」→ memory_forget(删除需要你点头,走审批) 用户级记忆(跨工作区) 有些事跟哪个项目无关:你是谁、做什么工作、说什么语言、跨项目的工作约定。 这类东西写进某个工作区,就只有那个项目能召回 —— 所以要显式写进用户级库: $DSH_HOME/memory-lite/global/memory.db ← 用户级(跨工作区) <工作区>/.dsh-memory/memory.db ← 该工作区自己的(默认) - 怎么写:对话里说「记住(跨工作区):我在深圳,做产品运营」→ 我用 memory_note 带 scope="user" 写进用户级库。默认是当前工作区,我不会靠 project 字段猜。 - 怎么起作用:每轮召回时「当前工作区 + 用户级」一起搜、合并排序,同分时工作区优先;同一条记忆只出现一次(按内容判重,不是按 id)。 - 不会拖累提示词:合并后仍受 injectMaxItems 那一个名额上限管,用户级记忆写多少条都不会让每轮注入变长。 - 不进常驻索引段:索引段只有 4096 B,容量留给工作区条目(所以用户级条目是靠「按需召回」生效,不是像人设那样每轮都在)。 - 面板:设置页 →「记忆控制」的库下拉里会多一项「用户级(跨工作区)」,可以像别的库一样看、搜、改状态。 还要更"永远在场"的?那是人设/工作规范两个文本框的活(它们每轮都注入)。 分工:每轮都必须遵守的规则 → 那两个框;换个项目还需要的事实 → 用户级库;跟这个项目有关的事 → 工作区库。 三种状态 | 状态 | 含义 | 之后会怎样 | | 在用 | 内容有效,可能被召回 | 正常参与注入与检索 | | 已完成 | 这件事做完了(todo 完成、话题达成目标) | 内容仍然有效,仍可被搜到与召回 | | 已停用 | 这条不再正确或不再需要(过时、被取代、写错了) | 不再被注入,但仍可搜到、可随时恢复 | 数据在哪 <工作区>/.dsh-memory/memory.db ← 记忆库(每个工作区一个) <工作区>/.dsh-memory/archive/ ← 日志溢出后的归档(jsonl) $DSH_HOME/memory-lite/global/ ← 用户级库(跨工作区,见上一节) $DSH_HOME/memory-lite/persona/ ← 人设 / 工作规范两个文本框的内容 $DSH_HOME/memory-lite/workspaces.json ← 库 → 工作区 的注册表 删除记忆:三种方式,按彻底程度 1. 设置页把条目改成「已停用」—— 不注入了,但还在库里(推荐,可恢复) 2. 用 memory_forget 工具删单条 —— 需要审批 3. 直接删 .dsh-memory/ 目录 —— 全部记忆消失,不可恢复 配置 在 profile 的 cordis.patch.yml 里给插件加 config: - id: memory-lite name: dsh-plugin-memory-lite config: autoCapture: true # 每轮自动落日志(不花额度) autoRecall: true # 每轮按关键词注入(不花额度) autoDistill: false # 空闲自动整理 —— 默认关(会花模型额度) distillIdleMinutes: 30 # 开启 autoDistill 时:多久没说话才算"空闲" distillMinIntervalMinutes: 30 # 开启 autoDistill 时:两次整理之间的最小间隔 distillMaxPerDay: 4 # 开启 autoDistill 时:每天最多整理几次(成本硬上限) injectMaxItems: 3 # 单次最多注入几条 injectMaxChars: 2000 # 单次注入的字符上限 crossWorkspaceSearch: true # 允许跨工作区检索 distillProvider: '' # 留空 = 用会话默认模型 distillModel: '' 关于花额度:默认 autoDistill: false —— 日志照记,但只有你点「立即整理」时才会调用模型。 想让它自己长出来就把 autoDistill 设成 true,那时上面三个 distill 参数才生效(空闲多久算闲 / 冷却 / 每天上限)。 设计上的几个刻意选择 这些都是踩过坑之后定下来的,改动前请先读 AGENTS.md: - 注入只走长期层。日志层永不进提示词,否则前缀缓存失效、上下文预算被淹。 - 注入是"只追加":作为独立消息追加在本轮已领取消息之后,不改写已有历史。 - 不重复注入:同一会话里已注入过的条目不再注入;压缩后重置这个记录并补回常驻记忆。 - 敏感内容 fail-closed:sensitive 在写入时算一次并落列,注入时只读列。 注入路径上再判断,等于把 fail-closed 变成 fail-open(判断代码出错就注入了)。 - 删除走审批:memory_forget 声明为破坏性工具,转人工确认。 - 超预算的日志留到下次:不"发都没发出去却记成处理过了"——那会永久丢内容。 - 蒸馏输入先剔系统样板,再取头尾:日志一条 = 一整轮,里面夹着宿主注入的 <system-reminder>(用户全局 AGENTS.md 等)。实测 10 条真实日志里有 7 条的 "前 1500 字"逐字相同 —— 不剔样板的话,模型看到的不是"这一轮发生了什么",而是同一段样板。剔完再按 头 40% + 尾 60% 取样(结论在尾部)。 - 常驻索引段每条只列 20 字:这段每轮都在 system prompt 里,中文 1 字 = 3 B。 实测 33 条时它已占到 4096 B 预算的 83.8%(每行 123 B)→ 只装得下约 33 条,再多就会静默掉出提示词。截到 20 字后约能装 49 条。别指望"回填标题"来救容量 —— 回填的标题同样会被截断,额外容量是 0。 已知限制 - 检索是关键词级的,不是语义向量检索。中文查询按连续串与子串匹配,所以换个说法可能搜不到(用 memory_search 时尽量带上你当时用的词)。 - 每个工作区一个库,默认只搜当前工作区;跨工作区要显式 scope="all"。 - 日志层有容量上限(每会话约 200 条),超出会先写归档文件再删库内行(不静默丢)。 - 空闲自动整理依赖宿主进程活着 —— 客户端关着的时候不会整理。 关于本仓库不含开发工具 本仓库只有插件本身(index.js / lib/ / client/ / locale/ / 图标 / 补丁 / README / LICENSE)。 校验器(verify-.mjs)、诊断脚本(diag-*.mjs)、迁移脚本与发布助手不在仓库里,它们只在开发者本机(原因:那些脚本含开发机的绝对路径与个人数据位置,不该跟着插件发给别人;这也是本项目的一贯纪律 —— 开发产物不进用户包)。 如果你想自己验证这个插件的行为,用它的运行时表现验:装完之后在设置页看「记忆控制」,或者用 memory_stats / memory_search 这些工具直接问它。 真机行为才是判据。 许可 MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
eighteentang/dsh-plugin-memory-lite
给 DSH 的本地优先跨会话记忆:每轮自动沉淀 + 空闲自动整理 + 按需注入。数据全在本地…
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,462已汉化DSH
73
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,848已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,246已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
DS Bot 是一个基于 DeepSeek Harness简称 dsh的 bot 插件,插件将 dsh 改造为 bot…
★ 4,717已汉化DSH
71.1
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,711已汉化DSH
71.1