@fonlan/dsh-gitmemo
v0.3.1
Published
Git-backed long-term memory for DeepSeek Harness: a local .mem git repo (single main branch, immutable entries, structured commit messages) with mem_search / mem_read / mem_write / mem_delete / mem_replace tools and fully automatic legacy migration (no CL
Maintainers
Readme
dsh-gitmemo
English | 简体中文
基于 Git 的 DeepSeek Harness (dsh) 长期记忆插件 —— 一个镜像
GitMemo 功能的 Cordis 插件。根 Agent 会把已完成任务的结论以
不可变 markdown 条目存入项目根目录的本地 .mem Git 仓库(单一 main 分支 + 结构化提交信息),
并在开始新任务前先搜索既往记忆。唯一依赖是 Git,日常使用完全无需手动记忆命令。
核心特性
- 极其简单 —— 安装后日常任务无需任何手动记忆命令
- 全自动 —— 根 Agent 在正常任务流程中自动执行
search/read/write/delete/replace - 纯本地、可离线 —— 记忆存于本地
.memGit 仓库,无云端依赖 - 仅依赖 Git —— 除
gitCLI 外无任何运行时依赖 - 省 token —— 通过
mem_search复用既有结论;子代理既不携带工作流规则也不携带工具 schema - 条目不可变 —— 每次写入都创建新文件;更正用
mem_replace(一个提交同时删除旧文件、新增新文件),作废用mem_delete - 结构化搜索 —— commit message 携带
GitMemo-*trailers(keywords、digest、search-text 投影);搜索只对 commit message 执行git log --grep --fixed-strings,绝不扫描条目正文 - 可审计 —— 每次记忆操作都是
.memGit 历史中的一次提交;被替换/删除的条目仍可按哈希读取 - 崩溃安全 —— write/delete/replace 在修改条目前先写事务 journal;迁移另用 sibling swap journal,目录交换中断后会在自动初始化前恢复
- 单分支 ——
.mem永远停留在main;代码分支/SHA 只作为条目元数据记录
插件提供的内容
| 内容 | 说明 |
| --- | --- |
| mem_search | 搜索记忆:keywords(1–12 个关键词数组,建议中英文同义词)、skip + snapshot(稳定分页)。每次最多返回 20 条带 summary / keywords / matched_keywords 的评分结果 |
| mem_read | 按创建/替换提交哈希读取一条记忆的完整 markdown(历史哈希仍可读) |
| mem_write | 存储任务结论:title + summary + keywords(2–12)+ content(front matter 由引擎生成),可选 related_branches / related_paths。每个不可变文件对应一个 ADD 提交 |
| mem_delete | 作废无替代结论(需要 commit_hash + reason) |
| mem_replace | 一个原子提交内更正旧结论(D 旧文件 + A 新文件)—— 禁止先删后写 |
| 作用域规则 | 工作流规则与五个工具只在 agent/created 时注册进根 Agent(delegationDepth === 0);子代理两者皆无 |
安装
需要 dsh ≥ 0.1.0-rc.6 与 git CLI。
从 npm 仓库(发布后):
dsh plugin --profile web add @fonlan/dsh-gitmemo从本地源码目录(开发/未发布):
dsh plugin --profile web add /path/to/dsh-gitmemo然后重启对应的 dsh profile(例如重启 dsh web 进程)。插件注册在宿主平面,该 profile 下每个新
根 Agent 会话都能看到这些工具与规则。
配置
bundle patch 自带合理默认值,可在 profile 的 cordis.patch.yml 中覆盖:
- id: dsh-gitmemo
config:
searchLimit: 20 # 每次 mem_search 返回的最大条数(每页大小)
lockTimeoutMs: 30000 # 跨进程锁等待超时
projectRoot: null # 可选:显式项目根目录(默认取会话工作目录)记忆存放位置与格式
.mem 仓库位于调用会话工作区的项目根目录(git rev-parse --show-toplevel,找不到时退回
工作目录;显式配置 projectRoot 优先)。仓库结构:
.mem/
├── .git/
├── .gitmemo-format # schema 版本标记,如 "2"
└── entries/ # 每个活跃记忆一个不可变文件
└── <utc-ms>-<digest-prefix>-<slug>.md.mem初始化在自己的main分支上;初始化时把.mem/与锁文件路径写入父仓库的.git/info/exclude(绝不写入受版本控制的.gitignore),且当父仓库已跟踪.mem内容时拒绝初始化。- 每次写入都用独占创建生成全新文件(绝不覆盖),以带结构化 trailers 的 ADD 提交落库,并把代码 分支/SHA/相关路径记录在条目 front matter 中。
整个记忆可以用普通 git 命令查看:
git -C .mem log --oneline
git -C .mem show <commit-hash>Agent 工作流(常驻规则,仅根 Agent)
- 开工前 —— 搜索。 仓库相关任务开始前提取 1–12 个中英文关键词 →
mem_search。纯闲聊和通用问答无需搜索。 - 结果预筛。 根据
title/summary/keywords/score/matched_keywords最多mem_read5 条最相关记忆;用skip+ 返回的snapshot翻页。 - 会话结束检查点 —— 唯一的写入路径。 对话即将结束时,
mem_write每一条已完成、与仓库 相关、且结论有价值/可复用(或用户明确要求记住)但还没有记忆的任务。绝不重复写已存在的条目。 纯问答、未完成任务、与仓库无关的工作、纯操作性的 git 动作一律不写。 - 用户更正。 已存结论过时且有替代结论 →
mem_replace(禁止先 delete 再 write);结论作废且无 替代 → 带reason的mem_delete。 - 子代理结果。 是否形成一条会话级记忆,由根 Agent 汇总后决定。
开发
npm install
npm run build # tsc → lib/
npm test # 构建 + 引擎/插件/迁移单元测试(node:test)目录结构
dsh-gitmemo/
├── package.json # npm 包;dsh.bundle.patch 接入 profile 层;bin: dsh-gitmemo
├── cordis.patch.yml # 组合层:dsh-gitmemo 行
├── src/
│ ├── index.ts # Cordis 插件:仅根 Agent 的 mem_* 工具 + 工作流片段
│ ├── mem.ts # 核心引擎(协议、锁/journal、搜索、write/read/delete/replace)
│ ├── migrate.ts # 旧格式迁移(dry-run/apply、backup refs、CAS 交换)
│ └── cli.ts # `dsh-gitmemo migrate` CLI 入口
├── lib/ # 构建产物(已提交,供 file:/git 安装使用)
└── test/mem.test.mjs # 引擎 + 插件 + 迁移单元测试License
MIT
