# dsh-memories

[English](README.md)

**DeepSeek Harness 的双账本跨会话记忆插件。**

设计灵感来自 OpenAI 开源编码代理 Codex 的记忆管线。`dsh-memories` 让同一项目里的每个新会话都能读到两本自动维护的活账本：

| 账本 | 文件 | 回答的问题 |
|---|---|---|
| 长期事实 | `.dsh/memories/MEMORY.md` | 这个项目的规矩是什么？用户偏好什么？踩过哪些坑？ |
| 项目进度 | `.dsh/memories/PROGRESS.md` | 做到哪了？已完成什么？正在做什么？接下来做什么？ |

两本账都由插件在后台自动维护，并在每个新会话开始时自动注入 AI 视野——不需要你反复交代背景。

## 功能特性

- **自动提炼** —— 每个新会话触发（30 分钟节流），后台细读**同项目**近 14 天的旧会话（每轮最多 2 篇），一次 LLM 调用同时产出：
  - 稳定**事实**：偏好 / 项目 / 环境 / 经验 四类
  - **进度推进**：完成 / 进行中 / 下一步
- **严格空转门控** —— 一次性任务细节、代码正文、机密绝不入账；无可记内容时整篇跳过（输出 NONE）
- **LLM 整合** —— 草稿合并重写为干净、去重、分节的正式账本；每次重写前自动留 `.bak` 备份
- **召回注入** —— 账本内容随系统提示进入每个新会话（小账全文内联，大账给摘要 + 文件指针）
- **衰减** —— 整理时清除超过 30 天未再确认且未钉住（pinned）的陈旧条目
- **模型工具 + 斜杠命令** —— `remember` / `update_progress` 工具让 AI 主动记账；`/remember` `/progress` `/memories` 给人直接控制权
- **失败自愈** —— 模型调用失败不落任何标记，下轮自动重试，不会留下半成品

## 环境要求

部署需提供标准宿主平面服务：

`fs` · `llm` · `sessionQuery` · `systemPrompt` · `tools` · `commands` · `sandboxPolicy`

（全部来自默认 `dsh-base` 组装；已在 dsh 0.1.0-rc.9 实测）

## 安装

### 方式 0 —— 一行命令安装（推荐）

```bash
dsh plugin --profile web add dsh-memories
```

插件管理器会读取本仓库自带的 `cordis.patch.yml`，自动完成接线。需要发布了 bundle manifest 的版本——当前 npm 上的 0.1.2 还没有，下次发布前请先用方式 A。

### 方式 A —— npm 包装入 profile

```bash
cd ~/.dsh/profiles/web            # 你实际运行的 profile
npm install <git 地址或 tarball>   # 包会进入 ./node_modules
```

然后在 `~/.dsh/profiles/web/cordis.patch.yml` 追加一行。**用相对路径指向入口文件**——这是 pnpm 管理 profile 下被验证可行的引用方式（patch 行里的裸包名不可靠）：

```yaml
- insert:
    - id: dsh-memories
      name: './node_modules/dsh-memories/lib/index.js'
```

也可以走 npm 原生方式：在 profile 的 `package.json` 里把 `"dsh-memories": "*"` 加入 `dependencies`、把 `"dsh-memories"` 加入 `dsh.profile.bundles`，然后 `pnpm install`，无需 patch 行。

### 方式 B —— 直接拷贝文件夹

把整个仓库文件夹复制到 `~/.dsh/profiles/web/node_modules/dsh-memories`，再按上面加同样的 patch 行。

重启 DSH 一次即完成。之后插件随启动加载，全程静默工作。

> 如果你之前用过本插件的动态版本（cordis_define 创建的 mem-*），重启前请先移除它，避免工具重复注册。

## 使用

日常无需任何操作。需要直接控制时：

| 命令 / 工具 | 效果 |
|---|---|
| `/remember <事实>` | 向当前项目的长期记忆追加一条并触发整理 |
| `/memories` | 状态总览：已处理数、草稿文件、账本预览、最近错误 |
| `/memories rescan` | 立刻重新扫描最近对话 |
| `/memories reset` | 清空"已处理登记"，让近期对话重新被提炼 |
| `/progress` | 查看 PROGRESS.md |
| `/progress <说明>` | 手动补记一条进度 |
| 模型工具 `remember(fact, category?, pinned?)` | AI 在对话中主动沉淀稳定事实 |
| 模型工具 `update_progress(completed?, doing?, next?)` | AI 在里程碑处更新进度账本 |

自然语言也可以：直接说"帮我记住：……"，AI 会调用同样的工具。

### 数据放在哪

```
<你的项目>/.dsh/memories/
├── MEMORY.md          # 整理后的长期事实（四节：偏好/项目/环境/经验）
├── MEMORY.md.bak      # 上一次版本备份
├── PROGRESS.md        # 项目进度（已完成 / 进行中 / 下一步）
├── PROGRESS.md.bak
└── raw/               # 未整理的草稿（_manual.md、_progress.md、各会话提取笔记）
```

全部是纯 Markdown——随时打开看、随手改、可以 git diff。

## 运作原理

```
新会话 ──▶ 扫描（同工作区、≤14天、每轮≤2篇）
                │
                ▼
        提炼（每篇一次 LLM 调用）
        ├─ facts[]      → raw/<会话>.md
        └─ progress{}   → raw/_progress.md
                │
                ▼
        整理（每本账一次 LLM 调用）
        ├─ MEMORY.md    ← 合并去重 + 30天衰减 + 四节归类
        └─ PROGRESS.md  ← 已完成 / 进行中 / 下一步 + 日期
                │
                ▼
下个会话 ◀── 召回段注入系统提示
```

提炼 prompt 强制严格 JSON 输出（数组或 NONE）、限制条目长度、禁止机密、跳过不足 400 字的琐碎会话。整理 prompt 强制章节格式与篇幅预算（事实 ≤100 行、进度 ≤60 行）。

## 已知边界与路线图

- **按项目隔离** —— 每个工作区独立账本。Codex 式全局用户账（`~/.codex/memories` 那种）规划通过 `globalDir` 配置实现
- 提炼只读消息文字，不含工具调用载荷
- 进度整合的 60 行预算是指令约束而非硬性保证
- 提示词目前面向中文场景，欢迎 PR 补充英文变体

## License

MIT