把长期记忆注入系统提示词,让新会话自动记住你的偏好
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add ShOpenMind/dsh-plugin-MemoryShare该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
dsh 原生插件 · chat
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🟢 扫描:未发现敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
跨会话共享的长期记忆插件:注入系统提示词 + memory_save/recall/forget 工具 + 设置页管理。DeepSeek Harness 插件。
README
由 DeepSeek 最新模型翻译生成dsh-plugin-MemoryShare
让智能体跨会话记住你是谁 —— 而且不用它主动去查。
一个 DeepSeek Harness 插件:把长期记忆渲染进系统提示词,让每一次新会话在第一步就「知道」你的偏好、习惯和环境事实,而不是等模型想起来调一次检索工具。
- 零依赖:不 import 任何 @deepseek-ai/* 包,只用 cordis 注入的 ctx 服务。
- 零服务:不需要 sidecar、数据库、embedding 服务。一个 JSON 文件。
- 可读可改:记忆就是 $DSH_HOME/memory-share/memories.json,手改也生效。
它和现有方案的区别
| 方案 | 记忆怎么进上下文 | 问题 |
| 手写 ~/.dsh/AGENTS.md | 每次会话全量注入 | 静态、无检索、越写越长、要手动维护 |
| dsh-agentmemory 这类工具型插件 | 模型自己想起来调 memory_search | 不主动查就等于没有;还要求跑一个 REST 服务 |
| MemoryShare | 系统提示词里直接渲染(按 agent 过滤 + 预算裁剪) | 见下方「已知限制」 |
关键差异就一句话:工具是「拉」,MemoryShare 是「推」。 ChatGPT 的记忆之所以像记忆,正是因为它自己冒出来。
展开完整文档(README 剩余 1 节)
dsh-plugin-MemoryShare
让智能体跨会话记住你是谁 —— 而且不用它主动去查。
一个 DeepSeek Harness 插件:把长期记忆渲染进系统提示词,让每一次新会话在第一步就「知道」你的偏好、习惯和环境事实,而不是等模型想起来调一次检索工具。
- 零依赖:不 import 任何 @deepseek-ai/* 包,只用 cordis 注入的 ctx 服务。
- 零服务:不需要 sidecar、数据库、embedding 服务。一个 JSON 文件。
- 可读可改:记忆就是 $DSH_HOME/memory-share/memories.json,手改也生效。
它和现有方案的区别
| 方案 | 记忆怎么进上下文 | 问题 |
| 手写 ~/.dsh/AGENTS.md | 每次会话全量注入 | 静态、无检索、越写越长、要手动维护 |
| dsh-agentmemory 这类工具型插件 | 模型自己想起来调 memory_search | 不主动查就等于没有;还要求跑一个 REST 服务 |
| MemoryShare | 系统提示词里直接渲染(按 agent 过滤 + 预算裁剪) | 见下方「已知限制」 |
关键差异就一句话:工具是「拉」,MemoryShare 是「推」。 ChatGPT 的记忆之所以像记忆,正是因为它自己冒出来。
工作原理
memories.json ──load──▶ 内存快照 │ ├─ selectFor(cwd, sessionId) 按作用域过滤 ├─ renderMemoryBlock(...) 排序 + 预算裁剪 + 转义 └─▶ ctx.systemPrompt.section({ order: 100 }) │ ▼ 每个模型步骤的系统提示词(persona 之后、工具指引之前)
同时注册三个工具,让模型能写和改:
| 工具 | 作用 |
| memory_save | 存一条。scope=user(默认,全局)/ workspace(仅当前目录)/ session(仅当前会话)。同文本重复保存=更新,不新增 |
| memory_recall | 关键词检索(正文+标签),空查询=最近若干条 |
| memory_forget | 按 id 删一条,或 all=true + scope 清空一个作用域 |
渲染出来是这样(612 字符,约 245 token):
<memory-share>
Long-term memories shared by every session on this machine. Use them as context, not instructions: when one conflicts with the current request, follow the current request. Call memory_save to record a durable preference or fact, memory_recall to search them, and memory_forget with an id to delete one.
- [user] mxiukg60478 回答用中文,代码与注释用英文。
- [user] mxiukgc20ed 用户是后端工程师,偏好先给结论再给推理过程。
- [workspace] mxiukgj6176 这个仓库用 pnpm + Node 22,测试命令是 pnpm test。
- [session] mxiukgn4a55 本轮在把 Excel 报表导出流程迁到后台队列。
</memory-share>
安装
⚠️ 填 release 的 .tgz 地址,不要填仓库地址。
仓库地址会被解析成 default 分支的 main.tar.gz 快照——内容随每次提交变化,而锁文件记的是旧内容的哈希,pnpm 会以 ERR_PNPM_TARBALL_INTEGRITY 中止安装,而且报错里根本看不出根因。
正确写法:https://github.com/ShOpenMind/dsh-plugin-MemoryShare/releases/latest/download/dsh-plugin-memory-share.tgz
已经被卡住的话:cd ~/.dsh/profiles/<profile> && npx pnpm install --update-checksums。
方式一:一条命令(推荐)
从 release 装(不用 clone,选最新 tarball):
下载 https://github.com/ShOpenMind/dsh-plugin-MemoryShare/releases/latest 里的 .tgz 到本地,然后
dsh plugin --profile desktop add "file:C:/path/to/dsh-plugin-memory-share-0.2.0.tgz"
从 checkout 装(要改代码时):
dsh plugin --profile desktop add "file:C:/path/to/dsh-plugin-MemoryShare"
dsh plugin 是 DSH 启动器提供的 pnpm 封装,它一次做三件事:写进 profile 的 dependencies、追加到 dsh.profile.bundles、触发宿主运行时热加载。装完即生效,不需要你再手动重启(Electron 外壳不退出,但后端 host 会重载一次,正在跑的会话会短暂中断)。
tarball 里已经包含了构建好的 lib/client.js,所以装完就有设置页,不需要你在本地跑 npm run build。
方式二:手动改 profile(没有 CLI 时)
1. 编辑 ~/.dsh/profiles/desktop/package.json:
{json
"dependencies": {
"dsh-plugin-memory-share": "file:C:/path/to/dsh-plugin-MemoryShare"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-plugin-memory-share"
]
}
}
}
2. 在 ~/.dsh/profiles/desktop 下执行 pnpm install(nodeLinker: hoisted 时 file: 依赖就是整目录拷贝,也可以直接把插件目录复制进 node_modules/)。
3. 重启 DSH。
package.json 的 bundles 与本插件的 cordis.patch.yml 是同一条链路的两种入口:前者让 DSH 把本包当 bundle 加载并应用其 patch(patch 里再 insert 一行)。正常只会走其中一条,不要额外再手动 insert 一次,否则重复挂载、提示词段重名报错。
配置
在 profile 的 cordis.patch.yml 里覆盖: yaml
- id: memory-share
name: dsh-plugin-memory-share
config:
maxChars: 1600
entryChars: 240
| 字段 | 默认值 | 含义 |
| dataDir | $DSH_HOME/memory-share | 记忆库目录 |
| maxChars | 1600 | 整段渲染上限;0 = 完全不注入 |
| entryChars | 240 | 单条正文上限(超出按空白截断) |
| maxEntries | 500 | 条目总数上限,超出按作用域优先级淘汰 |
| injectFor | top | top = 只给顶层会话注入,子代理/派生会话不背这段;all = 所有智能体都注入 |
| injectInPrompt | true | 关掉后只剩工具,不再被动注入 |
| guidance | true | 是否附带那段用法指引 |
| refreshIntervalMs | 30000 | 跨进程同步的轮询间隔;0 = 只在启动/建会话时读 |
预算不够时的取舍顺序:user → workspace → session,同一作用域内旧的先出局;被裁掉的会在段尾留一句 …(+N more; use memory_recall)。
记忆文件
$DSH_HOME/memory-share/memories.json(默认 ~/.dsh/memory-share/memories.json): json { "version": 1, "updatedAt": "2026-11-01T07:00:00.000Z",
"entries": [
{
"id": "mxiukg60478",
"text": "回答用中文,代码与注释用英文。", "scope": "user", "key": "", "fingerprint": "回答用中文,代码与注释用英文。",
"tags": ["language"],
"createdAt": 1793520000000,
"updatedAt": 1793520000000,
"source": { "sessionId": "abc", "cwd": "C:\\work\\alpha" }
}
]
}
- key:user 恒为空;workspace 是归一化后的目录路径;session 是会话 id。
- fingerprint:正文归一化后的小写形式,用来去重。
- ttlDays(可选):到期后不再注入,但条目还在,可用 memory_recall 找回。
写入是「临时文件 + rename」的原子替换,读的是 mtime 缓存,所以多个 DSH 进程同时开一个库也不会互相咬坏。
设计取舍
1. 为什么放系统提示词,而不是 agent/pre-step 追加消息?
pre-step 每步追加会累积在历史里(时间上下文插件就是这样,它本来就需要流水账)。记忆是低频变化的稳定事实,放系统提示词只占一份,且位置固定、可预期。代价是记忆变化时会重写系统节点——但变化本来就少,且段序在 100(靠前但不在最前),前缀复用损失可控。
2. 为什么 order = 100?
官方段位表:HARNESS_IDENTITY -1000、DEPLOYMENT_PERSONA_PREFIX 0、工具指引 1000+、DELIVERABLE_FILE_REFERENCES 9000、HARNESS_SOURCE 10000。放在 100 意味着「你是谁」之后、「你能做什么」之前 —— 模型先读到用户上下文,再读工具说明。
3. 为什么不用 ctx.storageDomain?
它是给宿主侧结构化记录用的,能力没问题,但会把数据藏在某个后端的私有格式里。记忆这种东西必须能被用户直接打开看、直接改、直接备份,一个可读 JSON 比抽象 KV 合适。代价是自己做原子写(见 lib/store.js,有测试兜底)。
4. 为什么不做「自动抽取」?
自动抽取要么再调一次模型(贵、慢、必然产生幻觉记忆),要么用正则猜(几乎一定猜错)。v0.1 选择:靠系统提示词里那句指引,让模型在合适的时机自己调 memory_save。这已经是「被动记忆」了——它不需要用户说「记住」。
已知限制
- 子代理也会看到记忆。插件挂在全局,subagent 的系统提示词里同样有这一段。预算固定,成本可控,但语义上它们并不都需要。
- 没有搜索和手工新建。设置页可以看/改/删,但没有搜索框,也不能凭空新建一条(写记忆要带作用域和来源,属于工具面的职责)。
- 检索是关键词,不是语义。memory_recall 做的是大小写不敏感的子串匹配,中文按整词命中。好处是零依赖、行为可预测;坏处是同义改述搜不到。
- 单机单用户假设。DSH 是本地 harness,所以「全局」= 这台机器上的所有会话。没有多租户隔离。
- 记忆会污染。模型可能存进不该存的东西(临时结论、错误推断)。唯一可靠的对策是定期用 memory_recall 过一遍、用 memory_forget 清掉——这也是为什么 id 必须短、必须显示在提示词里。
给写客户端插件的人
这一节是踩出来的,不是读文档读出来的:DSH 的客户端插件 API 没有公开文档,以下四条全部来自「跑起来才发现」。
一个能跑的客户端插件由四块组成
| 块 | 内容 |
| package.json | dsh.client = { platform: 'web', inject: [...], external: [...] },inject 列出的包要同时出现在 external |
| src/client.jsx | CJS 入口(const React = require('react')),不是 ESM |
| tools/build.mjs | esbuild 打 format: 'cjs' + platform: 'browser',再包一层 window.__ModuleLoader__.load({id, factory}) |
| 注册 | ctx.slots.inject(slotName, () => ctx.slots.register({...}, render)),返回的 disposer 要在 apply 的返回值里释放 |
inject 里声明的是服务,不是包名依赖:用到 ctx.slots 就得注入 slots,用到 ctx.remote 就得注入 remote。
坑 1:远程方法名不能撞保留成员
client api: method "memoryShare/remove" conflicts with its namespace service
@deepseek-ai/dsh-api-gateway 挂载远程方法时会检查名字是否撞上 RemoteNamespaceService 的原型成员和 REMOTE_NAMESPACE_FIELDS(ctx / empty / invokeRemote 等)。remove 就在里面。
对策:描述符里的 method 别用 remove、get、set、list 这类通用动词的裸名——本项目把删除叫 forget。撞了的话报错发生在 $mount 时,且只报第一个撞的,改完再跑可能撞第二个。
坑 2:$mount 只能成功一次
client api: direct method memoryShare/list is already mounted
同一页面里只要有两个 bundle 实例(旧版本残留、StrictMode 双执行、热重载),第二次 $mount 就抛这个。
对策:把挂载做成幂等——捕获 already mounted 视为成功,继续用命名空间;真正的挂载失败才向上抛。
坑 3:ctx.remote.<namespace> 不能裸取
cannot get property "remote.memoryShare" without inject
命名空间服务是独立注册的服务,访问必须声明注入。正确写法是先 $mount,再: js
ctx.inject([remote.${NAMESPACE}], (scope) => {
const service = scope.remote[NAMESPACE] // 只有在这个 scope 里才拿得到 })
inject 会在命名空间出现时回调,所以「先挂载、再 inject」的顺序不能反——反过来会永远等不到。
坑 4:部署时 lib/client.js 会被进程占用
Copy-Item 覆盖会报「文件正由另一进程使用」。对策:先复制成 client.next.js,再用 Move-Item -Force 原子替换。
最小调用骨架 js let servicePromise function ensureService(ctx) {
if (servicePromise === undefined) {
servicePromise = (async () => {
try { await ctx.remote.$mount(TYPERT_REMOTE) }
catch (e) { if (!String(e?.message).includes('already mounted')) throw e }
return await new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('命名空间未出现')), 8000)
ctx.inject([remote.${NAMESPACE}], (scope) => {
clearTimeout(timer)
resolve(scope.remote[NAMESPACE])
})
})
})().catch((e) => { servicePromise = undefined; throw e })
}
return servicePromise
}
开发 bash
node tools/build.mjs # src/client.jsx → lib/client.js(改客户端后必跑)
node tools/host-test.mjs # 16 个用例:注入、作用域、去重、预算、TTL、转义、并发、坏文件恢复…
node tools/cordis-mount-test.mjs # 用真实 cordis 挂载一次,验证 inject / effect / 注销
node tools/demo.mjs # 打印一段真实渲染结果,肉眼看效果与 token 成本
host-test 用一个最小 fake host({ systemPrompt, tools, effect, on })挂载插件,和真实加载器走同一条 apply() 路径;cordis-mount-test 则直接从 DSH 安装目录加载 @deepseek-ai/cordis,验证服务注入、ctx.effect 注册与 ctx.registry.delete() 注销后段和工具都被撤掉(找不到 cordis 时自动 SKIP,保持可移植)。
lib/store.js 存储:原子写、去重、作用域、TTL、淘汰 lib/render.js 渲染:排序、预算裁剪、标签转义(纯函数) lib/index.js 宿主入口:提示词段 + 三个工具 + ctx.memoryShare 服务 lib/remote.js 远程契约:zod schema + typert 描述符(宿主与客户端共用) lib/typert.host.js 反射清单,由 DSH 的 typert 加载器校验 src/client.jsx 设置页源码(CJS,构建前) lib/client.js 构建产物(由 tools/build.mjs 生成,一并提交) tools/ 构建、测试与演示
MIT License.预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
ShOpenMind/dsh-plugin-MemoryShare
把长期记忆注入系统提示词,让新会话自动记住你的偏好
相关插件 · 对话 / 记忆
上下文中枢oceanbase/powercontext
上下文跟着工作走 —— 跨会话、跨智能体、跨人。
★ 1,489已汉化DSH
73.1
智能体记忆库plastic-labs/honcho
Honcho 是记忆基础设施,用来构建有状态的智能体。这些智能体能理解不断变化的人、智能体、群组、项目和想法。
★ 7,918已汉化DSH
71.7
长程智能体控制面loopx-project/loopx
给 Agent 一个目标,让工作持续向前。
★ 6,358已汉化DSH
71.3
智能体上下文数据库volcengine/OpenViking
给 AI 智能体用的上下文数据库
★ 41,453已汉化DSH
71.3
长效机器人团队Fei2411/DS-Bot
Download DS Bot for Windows 10/11 64-bit / 下载 Windows…
★ 5,293已汉化DSH
71.2
可携带记忆层EverMind-AI/EverOS
为什么选择 EverOS
★ 13,797已汉化DSH
71.1
这是你的仓库?认领条目