dsh-plugin-long-term-memory
已验证dsh-plugin-long-term-memory · v1.1.3 · MIT
Long-term memory and self-learning plugin for DeepSeek Harness (DSH) - observe, learn, and remember across sessions. Also supports OpenCode.
安装
dsh plugin add dsh-plugin-long-term-memory 用 dsh --profile default --dump-config 确认 layer 已生效 —— 参见安装指南。
源码
发布到 npm 但没有公开仓库。安装前请检查包内容。
标签
作者
说明文档
DSH 长期记忆插件
观测、学习、记忆。为 DeepSeek Harness (DSH) 打造的自进化记忆系统,同时也支持 OpenCode。
这个插件让 AI 助手拥有跨会话记忆能力——它会观测你的工具使用方式、提炼行为模式(「本能」),并在对话中召回相关记忆,提供上下文感知的智能辅助。
核心能力
功能概览
| 能力 | 说明 |
|---|---|
| 工具观测 | 自动捕获每次工具调用的输入和输出,记录行为数据 |
| 模式提炼 | 结合统计分析和语义分析,自动发现你的工作习惯和偏好 |
| 记忆注入 | 在对话中自动召回相关记忆,并注入到系统提示中 |
| 规则进化 | 高置信度的行为模式会自动生成 auto-evolved.md 规则文件 |
| 对话持久化 | 将完整对话历史存入 LanceDB,支持后续检索和分析 |
| 项目隔离 | 记忆按项目作用域隔离,避免跨项目污染 |
双记忆系统
┌────────────────────────────────────┐ ┌────────────────────────────────────┐
│ Instinct 系统(行为记忆) │ │ Memory 系统(知识记忆) │
├────────────────────────────────────┤ ├────────────────────────────────────┤
│ 数据来源:工具调用观测记录 │ │ 数据来源:用户与 AI 的对话内容 │
│ 提炼方式:统计 + AI 语义分析 │ │ 提炼方式:AI 语义判断 │
│ 存储格式:instincts.jsonl │ │ 存储格式:memories.jsonl │
│ 作用范围:全局(所有项目共享) │ │ 作用范围:项目级(含全局记忆) │
│ 生命周期:置信度演化 + 衰减 │ │ 生命周期:按类型 TTL 过期 │
│ 注入方式:auto-evolved.md │ │ 注入方式:会话预加载 + 实时召回 │
└────────────────────────────────────┘ └────────────────────────────────────┘
安装与使用
DSH 插件命令安装(推荐)
npx @deepseek-ai/dsh plugin --profile web add dsh-plugin-long-term-memory@latest
一条命令完成安装与注册:DSH 加载 bundle 时自动读取包内
dsh.bundle.patch声明的 cordis.patch.yml,将插件挂载为 profile layer。无需手动在项目根创建cordis.yml或指向构建产物路径。
验证安装:
npx @deepseek-ai/dsh plugin --profile web list
关于 peer dep 警告:DSH 自身的 web profile 自带
@deepseek-ai/[email protected],期望的[email protected]与本插件用[email protected]期望的[email protected]不兼容。pnpm 会同时装两个 minor-rc 版本(无害),最终日志里会出现Conflicting peer dependencies。这是 DSH 生态自身的版本漂移,与本插件无关——dsh web仍可正常启动,本插件按[email protected]的 API 编写,无法也不应降级。 此外apache-arrow@17的 bin 路径已从.cjs改为.js/.mjs,pnpm 的Failed to create bin at ... arrow2csv是无害警告(不影响 lancedb 运行时 require)。
- 配置文件:
~/.config/dsh/long-term-memory.jsonc(首次启动自动生成模板) - 数据目录:默认
~/.local/share/dsh/long-term-memory/ - 验证加载:
export LONG_TERM_MEMORY_DEBUG=1后启动 DSH,查看~/.local/share/dsh/long-term-memory/plugin.log应出现plugin loaded (tools + hooks + prompt registered) - 沙箱兼容:若终端沙箱(TRAE/EDR)拦截
~/.dsh写入,可用HOME=$PWD/.fake-home npx @deepseek-ai/dsh plugin --profile web add dsh-plugin-long-term-memory@latest临时重定向
已知限制:DSH preview API 易变(锁
@deepseek-ai/[email protected]);turn/end触发的本能分析带 5 分钟防抖。
从源码构建
git clone https://github.com/yuqiangcn/dsh-plugin-long-term-memory.git
cd dsh-plugin-long-term-memory
pnpm install
pnpm build:dsh
OpenCode — 兼容
本插件也保留了 OpenCode 入口(src/index.ts),与 DSH 共享同一套引擎。
pnpm build
配置方式与 DSH 侧类似,配置文件位于 ~/.config/opencode/opencode-plugin-long-term-memory.jsonc。
配置方式
插件支持两种配置方式:
| 方式 | 适用场景 | 难度 |
|---|---|---|
| 什么都不配 | 想快速体验,默认 TF-IDF + 全功能开 | ⭐ |
| JSONC 配置文件(推荐) | 日常使用,团队统一配置 | ⭐⭐ |
配置文件位置
DSH 侧:
~/.config/dsh/long-term-memory.jsonc
OpenCode 侧:
~/.config/opencode/opencode-plugin-long-term-memory.jsonc
- Linux/macOS 遵循 XDG 规范,可用
XDG_CONFIG_HOME环境变量覆盖基目录 - JSONC 格式(支持
//注释、尾随逗号、${ENV_VAR}环境变量引用) - 任何字段缺失或类型错误 → 降级到默认值 + error 日志,不影响插件启动
顶层字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
dataDir |
string | ~/.local/share/dsh/long-term-memory |
数据存储目录。更改后旧数据不自动迁移,需手动复制 |
observationEnabled |
bool | true |
开启工具观测。记录每次工具调用的输入/输出到 observations.jsonl |
autoInject |
bool | true |
自动将相关记忆注入系统提示(会话预加载 + 实时召回) |
autoAnalyze |
bool | true |
会话结束后自动分析行为模式,生成 Instinct |
autoExtractMemory |
bool | false |
从对话内容自动提炼记忆。需要配置 ai 块 |
semanticAnalysis |
bool | false |
启用 LLM 语义分析提炼行为模式。需要配置 ai 块 |
maxRecallCount |
number | 5 |
每次对话最多召回多少条记忆 |
recallThreshold |
number | 0.3 |
召回最低相似度(0=不召回,1=完全匹配) |
injectPosition |
enum | "system" |
注入位置:"system" 注入系统提示 / "user" 注入用户消息 |
statisticalMinOccurrences |
number | 3 |
行为模式最少出现几次才被统计检测为 Instinct |
analyticsEnabled |
bool | true |
启用 Analytics 埋点。memory_analytics 工具可生成质量报告 |
ai |
object | - | AI 模型配置(控制语义分析 / 记忆提炼 / 沉淀整理)。见下 |
embedding |
object | - | Embedding 配置(控制语义检索质量)。不配则用本地 TF-IDF(零依赖)。见下 |
autoMaterialize |
object | - | 项目知识沉淀配置(把决策/Bug/模式沉淀到 docs/)。见下 |
ai 块 — AI 模型配置
控制三个 AI 行为:语义分析、记忆提炼、沉淀整理。只要开启 semanticAnalysis 或 autoExtractMemory 或 autoMaterialize.organization.enabled,就必须配置此块。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
provider |
enum | "openai" |
"openai" / "zhipu"(智谱,国内推荐)/ "custom"(OpenAI 兼容端点) |
model |
string | "gpt-4o-mini" |
模型名。OpenAI 例:gpt-4o-mini / gpt-4o;智谱例:glm-4-flash / glm-4-plus |
apiKey |
string | - | API key。建议用 "${ENV_VAR}" 引用环境变量 |
baseUrl |
string | - | 自定义端点。custom 必填;openai/zhipu 留空则用默认值 |
temperature |
number | - | 生成温度(0-2)。建议 0.1-0.3 保持稳定 |
maxTokens |
number | - | 最大输出 tokens |
embedding 块 — 向量嵌入配置
控制语义检索质量。留空 = 本地 TF-IDF(关键词匹配,零依赖)。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
provider |
enum | "openai" |
"openai" / "zhipu" / "custom" |
model |
string | "text-embedding-3-small" |
模型名 |
apiKey |
string | - | API key。写法同 ai 块 |
baseUrl |
string | - | 自定义端点。custom 必填 |
dimensions |
number | - | 输出向量维度。仅智谱 embedding-3 有效(256/512/1024/2048) |
autoMaterialize 块 — 项目知识沉淀配置
把高价值记忆(决策 / 项目 / Bug / 模式)沉淀到 docs/project-context.md,作为团队共享文档。
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mode |
enum | "assisted" |
"disabled" 纯手动 / "assisted" 会话结束提示候选(默认) / "auto" 满足阈值自动写入 |
types |
array | ["decision", "project", "bug", "pattern"] |
允许沉淀的记忆类型。不能包含 user / profile / feedback(隐私保护) |
thresholds.minConfidence |
number | 0.85 |
auto 模式的最低置信度门槛 |
thresholds.minAccessCount |
number | 3 |
auto 模式的最低访问次数门槛 |
output.path |
string | "docs/project-context.md" |
输出文件路径(相对项目根目录) |
output.autoGeneratedMark |
string | "[Auto-generated]" |
自动生成条目的前缀标记 |
organization.enabled |
bool | true |
是否用 LLM 整理。关闭后直接拼接。需要 ai 块 |
organization.temperature |
number | 0.2 |
LLM 整理温度 |
autoReferenceInAgents |
bool | true |
沉淀成功后是否在项目根 AGENTS.md 中追加 ## Project Knowledge 章节 |
完整配置示例
最小可用(啥都不配):
{}
推荐配置(语义检索 + 自动沉淀,国内环境):
{
"dataDir": "~/.local/share/dsh/long-term-memory",
"observationEnabled": true,
"autoInject": true,
"autoAnalyze": true,
"semanticAnalysis": true,
"autoExtractMemory": true,
"maxRecallCount": 5,
"recallThreshold": 0.3,
"ai": {
"provider": "zhipu",
"model": "glm-4-flash",
"apiKey": "${ZHIPU_API_KEY}",
"temperature": 0.2
},
"embedding": {
"provider": "zhipu",
"model": "embedding-3",
"apiKey": "${ZHIPU_API_KEY}",
"dimensions": 1024
},
"autoMaterialize": {
"mode": "assisted",
"types": ["decision", "project", "bug", "pattern"],
"autoReferenceInAgents": true
}
}
海外环境(OpenAI):
{
"ai": {
"provider": "openai",
"model": "gpt-4o-mini",
"apiKey": "${OPENAI_API_KEY}"
},
"embedding": {
"provider": "openai",
"model": "text-embedding-3-small",
"apiKey": "${OPENAI_API_KEY}"
}
}
常见坑点
apiKey用"${ENV_VAR}":插件启动时同步解析,环境变量没设 →undefined→ 请求失败并打 error 日志。建议用direnv/.env/1Password CLI管理- 开了
semanticAnalysis/autoExtractMemory但没配ai块:AI 调用会失败,相关功能静默失效(不报错也不生效) - 改了
dataDir旧数据不迁移:需要手动复制旧目录下的memories/observations/instincts/dialogues.lance/到新目录 - Embedding 模型换了后旧记忆不兼容:新模型的向量维度和旧的可能不同,旧记忆会自动 fallback TF-IDF 检索
- LanceDB 对话表维度固定:
dialogues.lance表的embedding维度是建表时定的。换 Embedding 模型后,需要删除~/.local/share/dsh/long-term-memory/dialogues.lance/让插件重建 - Monorepo 项目标识冲突:多个子包共用 git remote,会被识别为同一个项目。插件支持自动检测 monorepo 并生成
rootId:leafName的作用域 ID - JSONC 字段类型写错:插件不会崩溃,会打 error 日志并降级默认值
提供的工具
安装后,插件会注册以下工具供 AI 使用:
| 工具 | 用途 |
|---|---|
memory_save |
将知识、偏好或决策保存到长期记忆。支持 scope 参数指定作用域 |
memory_search |
搜索已存储的记忆内容 |
memory_list |
列出所有记忆(可按类型过滤) |
memory_delete |
按 ID 删除指定记忆 |
memory_restore |
恢复软删除的记忆(30 天内可恢复) |
memory_set_scope |
在 monorepo 中切换子包作用域;独立项目中传入项目名可确认当前项目作用域 |
memory_status |
查看系统状态、当前作用域与配置 |
memory_open |
打开 MEMORY.md 摘要文件 |
memory_demo |
保存测试记忆并验证端到端管道 |
memory_analytics |
生成记忆质量报告(命中率、误存候选) |
instinct_list |
查看已学习的行为模式 |
memory_analyze |
手动触发行为模式分析 |
memory_evolve |
从高置信度模式生成进化规则 |
memory_export_rules |
将学习到的规则导出到 AGENTS.md(人工审核+确认) |
memory_materialize |
预览项目知识候选清单 |
memory_materialize_stage |
暂存候选记忆,返回 id+摘要清单;含内容级重复预检 |
memory_materialize_apply |
写入选中的记忆到 docs/project-context.md |
memory_materialize_discard |
清空 staging 区 |
架构设计
┌──────────────────────────────────────────────────────────────┐
│ 宿主适配层 │
├──────────────────────────────────────────────────────────────┤
│ ┌───────────────────┐ ┌───────────────────────────────┐ │
│ │ DSH (Cordis) │ │ OpenCode (Hooks) │ │
│ │ src/dsh/ │ │ src/index.ts │ │
│ └────────┬──────────┘ └────────┬──────────────────────┘ │
│ │ │ │
│ └───────────┬───────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 引擎层 (共享) │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │ │
│ │ │ 观测引擎 │─▶│ 本能引擎 │─▶│ 记忆引擎 │ │ │
│ │ │(observation) │ │ (instinct) │ │ (memory) │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────┘ │ │
│ │ │ │ │ │ │
│ │ ▼ ▼ ▼ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │ │
│ │ │observations │ │ instincts │ │ memories │ │ │
│ │ │ .jsonl │ │ .jsonl │ │ .jsonl │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────┘ │ │
│ │ │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ dialogue-store.ts (LanceDB 向量表) │ │ │
│ │ │ └─ 持久化对话历史 │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
文件结构
src/
├── index.ts # OpenCode 插件入口(兼容)
├── dsh/
│ ├── index.ts # DSH Cordis 插件入口(主入口)
│ ├── tools.ts # 工具注册(DSH DSL)
│ ├── hooks.ts # 事件桥接
│ └── prompt.ts # 系统提示注入
├── observation-engine.ts # 观测引擎:Hook 捕获 + 会话追踪
├── instinct-engine.ts # 本能引擎:模式提炼(统计 + AI 语义)
├── memory-engine.ts # 记忆引擎:召回 + 上下文注入
├── memory-store.ts # 存储层:JSONL + TF-IDF/Embedding + 检索
├── dialogue-store.ts # LanceDB 向量表:对话历史持久化
├── embedding-provider.ts # 可插拔 Embedding 层(TF-IDF / Remote / Local)
├── ai-provider.ts # 声明式 AI/Embedding 配置 → fetch 调用函数
├── config-loader.ts # 独立配置加载器(JSONC → Zod 校验)
├── project-utils.ts # 项目标识符推断
├── materializer.ts # 项目知识沉淀(docs/project-context.md)
├── agents-exporter.ts # 规则导出到 AGENTS.md
├── analytics.ts # 埋点与质量报告
└── logger.ts # 日志系统
Monorepo 作用域
插件会自动检测 git 仓库下的 package.json 数量。若存在多个被 git 追踪的 package.json,则视为 monorepo:
- 项目 ID 格式:
rootId:leafName,例如acme:acme-web、acme:acme-shared - 根作用域:
rootId(如acme)下的记忆可被所有子包召回 - 子包作用域:
rootId:leafName下的记忆默认只在该子包召回 - 全局作用域:不绑定 project 的记忆在所有项目召回
显式切换
memory_set_scope name=acme-web
独立(非 monorepo)项目中没有子包概念,作用域始终是项目自身。传入项目名(如 package.json 的 name)即可确认并锁定当前项目作用域:
memory_set_scope name=wallet-h5
memory_save 的 scope 参数
| 取值 | 含义 |
|---|---|
current |
写入当前作用域(默认) |
leaf |
写入当前子包作用域(同 current) |
root |
强制写入根作用域,所有子包共享 |
global |
不绑定 project,全局共享 |
Embedding 提供者
插件支持三种语义检索后端,默认使用本地 TF-IDF(零依赖)。
| 提供者 | 配置方式 | 适用场景 | 维度 |
|---|---|---|---|
| TF-IDF(默认) | 无需配置 | 零依赖、隐私安全、关键词匹配 | 词汇维度 |
| 远程 API | 配置文件 embedding 块(推荐) |
语义质量最优 | 模型决定 |
| 本地模型 | 预留接口 | 未来接入 transformers.js / ollama | 模型决定 |
方式一:配置文件(推荐)
{
"embedding": {
"provider": "openai" | "zhipu" | "custom",
"model": "...",
"apiKey": "明文key 或 ${ENV_VAR}",
"baseUrl": "...", // 可选,custom 必填
"dimensions": 1024 // 可选,仅 zhipu embedding-3 有效
}
}
1. OpenAI
{
"embedding": {
"provider": "openai",
"model": "text-embedding-3-small",
"apiKey": "${OPENAI_API_KEY}"
}
}
2. 智谱 AI(Zhipu)— 中国大陆友好
{
"embedding": {
"provider": "zhipu",
"model": "embedding-3",
"apiKey": "${ZHIPU_API_KEY}",
"dimensions": 1024
}
}
默认端点:https://open.bigmodel.cn/api/paas/v4/embeddings,自动路由。
3. Custom(任何 OpenAI-compatible 端点)
{
"embedding": {
"provider": "custom",
"model": "any-model",
"apiKey": "${CUSTOM_API_KEY}",
"baseUrl": "https://my-proxy.example.com/v1"
}
}
如何选择
| 场景 | 推荐 |
|---|---|
| 不想折腾,关键词匹配够用 | 啥都不配(默认 TF-IDF) |
| 国内 + 中文场景 | 智谱 embedding-3(国内访问稳、价格便宜) |
| 海外 + 追求质量 | OpenAI text-embedding-3-small |
| 企业内部代理 / 私有部署 | Custom + baseUrl 指向代理 |
数据存储
所有数据均存储在本地数据目录(默认 ~/.local/share/dsh/long-term-memory/,可通过 dataDir 配置):
| 文件/目录 | 内容 |
|---|---|
memories/memories.jsonl |
知识记忆(含可选的 _embedding 稠密向量) |
observations/observations.jsonl |
工具调用观测记录 |
instincts/instincts.jsonl |
行为模式(本能) |
dialogues.lance/ |
LanceDB 向量表:对话历史 |
auto-evolved.md |
自动生成的高置信度规则 |
隐私说明:默认情况下所有数据保存在本地,不需要任何云服务。只有显式配置远程 Embedding API 时才会向外部发送数据。
技术栈
- 运行时: Bun(构建) / Node.js ≥ 22.19(DSH 加载)
- 语言: TypeScript 5.8.2(严格模式)
- Schema: Zod 4.1.8
- 向量数据库: LanceDB 0.30.x
- 宿主框架: Cordis 4.0.1(DSH)/ @opencode-ai/plugin(OpenCode 兼容)
开发
# 安装依赖
pnpm install
# 类型检查
pnpm typecheck # npx tsc --noEmit
# 构建 DSH 插件(主入口)
pnpm build:dsh # bun build src/dsh/index.ts --outdir dist-dsh --target node
# 构建 OpenCode 插件(兼容)
pnpm build # bun build src/index.ts --outdir dist --target bun
# 开发运行
pnpm dev # bun run src/index.ts
重要:生产构建使用
bun build。tsc仅用于类型检查(--noEmit),不要用它编译代码。
项目级上下文隔离
记忆系统支持项目级作用域隔离:
- 自动推断:从当前目录自动推断项目标识
- 优先级:git remote URL → package.json name → 目录名
- 检索过滤:
searchMemories优先召回同项目记忆(分数 +0.15 提升)- 全局记忆 +0.05,跨项目 +0
- 同项目不足 topK 时自动 fallback 跨项目 + 全局
- 配置覆盖:
defaultProject?: string可覆盖自动推断(用于 monorepo 子包)
项目知识沉淀
高价值的项目知识可以通过 memory_materialize_* 工具沉淀到 docs/project-context.md,作为团队共享的可读文档。
三步流程
# 1️⃣ 暂存:列出所有候选
memory_materialize_stage
# 2️⃣ 选你想沉淀的
memory_materialize_apply ids=["mem_xxx", "mem_zzz"]
# 3️⃣ (可选)不想沉淀了?清空 staging
memory_materialize_discard
重复预检(团队协作防护)
memory_materialize_stage 阶段会自动做内容级相似度预检,使用字符级 3-gram + Jaccard 相似度,零外部依赖:
similarity ≥ 0.7→🔴 strong match(强烈建议排除)0.5 ≤ similarity < 0.7→🟡 warning match(关注)
隐私保护
docs/project-context.md 通常提交到 git 并团队共享,因此个人类型不允许沉淀:
| 类型 | 是否允许沉淀 | 原因 |
|---|---|---|
decision project bug pattern |
✅ 允许 | 项目相关知识 |
workflow tool-usage reference |
✅ 允许 | 项目相关行为/资源 |
custom |
✅ 允许 | 兜底类型 |
user profile feedback |
❌ 禁止 | 隐私泄露风险 |
许可
MIT