Skip to content
dsh.fish
Bundle

dsh-project-memory

Project-level persistent memory plugin for deepseek-harness — auditable Markdown memory files with load / upsert / finalize / forget tools.

Source
JasperGuWP
stars
2 stars
License
MIT
Updated
Updated 9 hours ago

Readme

# dsh-project-memory

deepseek-harness 的「项目级持久记忆」插件:让模型跨会话读写**当前项目** `memory/` 目录下的可审计 Markdown 记忆文件——落盘为普通文本,可 git 审计 / diff,不依赖模型内部上下文。

> 通用、零外部依赖:不预置任何项目知识,装到哪个项目就服务于哪个项目。

## 工具

四个工具,名字均可用 `toolPrefix` 加前缀:

| 工具 | 作用 |
|---|---|
| `memory_load_context` | 会话/任务开始加载相关记忆;关键词检索 + 全量 `catalog` 清单 |
| `memory_upsert` | 仅在用户明确要求「记住 / 以后都按这个来」时写入或更新一条记忆 |
| `memory_finalize` | 任务收尾把结论沉淀为一条 reference 记忆(固定文件,避免文件膨胀) |
| `memory_forget` | 遗忘:删除正文文件 + 对应索引行(保护 `MEMORY.md` 与 `reference.md`) |

## 特性

- **文件即记忆**:`memory/MEMORY.md`(纯索引)+ `memory/*.md`(正文)。
- **索引格式**:`- [类别] 主题:一句话摘要 → 文件名.md`
- **敏感信息拦截**:token / cookie / password / 密钥 / JWT / .env 命中即拒存(返回 `ok:false`)。
- **工作区感知根目录**:优先 `sandboxPolicy.resolve({ session })`(会话 cwd),回退 `config.memoryRoot` → `process.cwd()`。
- **检索**:中英分词 + 多字段 + 正文 + 新鲜度加权;`catalog` 可当「列记忆」用。
- **防膨胀**:`maxReferenceEntries` 给 reference 设上限,自动裁最旧。

## 安装

### 方式 A:一键安装(Bundle,推荐)

本仓库是一个 dsh Bundle(`package.json` 声明了 `dsh.bundle.patch`)。其他用户用 `dsh plugin` 直接装到自己的 profile:

```sh
# Git 源(锁定 commit 更稳)
dsh plugin --profile web add github:<owner>/dsh-project-memory#<sha>

# 或 npm(若已 pnpm publish)
dsh plugin --profile web add dsh-project-memory

# 或 tarball(pnpm pack 产物)
dsh plugin --profile web add ./dsh-project-memory-0.1.0.tgz
```

装完**重启 dsh 进程**生效(node 半侧无热加载)。插件零外部依赖、无构建步骤,git 源装上即可用;若 pnpm 对 git 依赖提示 `allowBuilds`,按提示在 profile 的 `pnpm-workspace.yaml` 加一行后重跑。

校验 / 移除:

```sh
dsh --profile web --dump-config | grep -A2 project-memory
dsh plugin --profile web remove dsh-project-memory
```

### 方式 B:手动本地插件(不打包也行)

插件是零依赖的单文件 `.ts`,不走包管理也可以:

1. 下载 `memory-plugin.ts` 到本机。
2. 在你 profile 的 `cordis.patch.yml` 加一行(`name` 用绝对路径):

```yml
- insert:
    - id: project-memory
      name: '/absolute/path/to/memory-plugin.ts'
      # config:
      #   toolPrefix: ''            # 需要命名空间时,如 'proj_' → proj_memory_upsert
      #   memoryRoot: ./memory      # 默认 = 会话工作区 /memory
      #   maxReferenceEntries: 200  # reference.md 最多保留条数
```

3. 重启 dsh。

## 配置

| 键 | 默认 | 说明 |
|---|---|---|
| `memoryRoot` | 会话工作区 `/memory` | 记忆根目录(绝对或相对,相对按会话工作区解析) |
| `indexFilename` | `MEMORY.md` | 索引文件名 |
| `referenceFilename` | `reference.md` | 收尾沉淀固定文件名 |
| `toolPrefix` | `''` | 工具名与 systemPrompt 节名的前缀 |
| `maxReferenceEntries` | 无限制 | reference.md 最多保留条数,超出裁最旧 |

## 触发规则(插件会自动注入为系统提示节)

- 会话/任务开始:`memory_load_context` 载入相关记忆。
- 仅当用户明确要求「记住 / 以后都按这个来 / 以后都这样做」:`memory_upsert`。
- 非平凡任务收尾:`memory_finalize` 沉淀一条。
- 过期或被取代的记忆:`memory_forget` 删除。
- 绝不存密钥:写工具会拒绝并返回 `ok:false`。

## 30 秒验证

1. 会话 A:`记住:这个项目用 pnpm 打包。` → 确认调用了 `memory_upsert` 且成功。
2. 会话 B(新会话,勿复制 A 的对话):`这个项目怎么打包?` → 确认调用了 `memory_load_context` 并复述 pnpm。

## 兼容性

- 测试于 deepseek-harness(Node ≥ 22)。Bundle 入口为预编译 `memory-plugin.js`;本地 `.ts` 方式(方式 B)由 Node 原生 type-stripping 加载(开发环境 tsx)。
- **零外部依赖**:运行期只 `import node:fs / node:path`;`defineTool`、`Context` 等均已内联/本地化,因此本地插件、Bundle、user preset 任一形态都能直接加载,不会踩 `@deepseek-ai/*` 解析不到的 `ERR_MODULE_NOT_FOUND`。

## License

[MIT](./LICENSE)

Install

dsh plugin --profile web add github:JasperGuWP/dsh-project-memory

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source