# @dafantong01/dsh-memory-palace 中文文档

规范地址：https://npmcn.com/package/%40dafantong01/dsh-memory-palace/

版本：0\.3\.11
npm 元数据更新时间：2026-11-10T18:31:15.330Z
中文译文更新时间：2026-11-11T08:34:39.970Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40dafantong01/dsh-memory-palace
原文对照：https://npmcn.com/package/%40dafantong01/dsh-memory-palace/?lang=original
项目主页：https://github.com/dafantong01/dsh-memory-palace#readme
源码仓库：https://github.com/dafantong01/dsh-memory-palace

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：1.1 MB，18 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- Node.js 要求：^22\.19\.0 \|\| \>=24\.0\.0
- 运行依赖：2 个
- 首次发布：2026-10-24T09:21:08.409Z
- 最新版本发布：2026-11-10T18:31:15.124Z
- 近 30 天下载量：5542（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：29（近 12 个月 29 个）

## 中文简介

本地长期记忆：在上下文压力升高时归档较早的整轮原文，压缩后可读回；支持 identity / user 板块 / rules / memories 四板块分级注入、项目档案与项目热记忆、记忆家族与根转移、手动注入、20K 长文分段、tag 关联检索。数据都保存在当前工作区，不依赖外部记忆服务。

## 安装

```sh
npm install @dafantong01/dsh-memory-palace
```

也可以使用：`pnpm add @dafantong01/dsh-memory-palace`、`yarn add @dafantong01/dsh-memory-palace`、`bun add @dafantong01/dsh-memory-palace`

## README

# 记忆宫殿（dsh-memory-palace）

把会话原文按「一轮对话」为单位、分类归档到**当前工作区**的 `memory-palace/` 目录。 目的：在 DSH 自动压缩之前，先把较早的完整原文落到磁盘，压缩后还能查回原话。

> **0.3.11 发布版**：本地长期记忆。归档较早的整轮原文，提供四板块分级注入、项目档案与项目热记忆、项目档案家族共用、记忆家族与根转移、摘要关键词定位与候选翻页、手动注入、20K 分段、tag 关联检索、归档触发快路径与压缩恢复；数据都在当前工作区。 0.3.11 新增项目档案附件：独立附件框、单附件切换、系统选择器/手动路径挂载、外部文件不复制、最多 5 个；同时修复统计与全量校验并发。 0.1.x 的归档基础说明仍适用。

## 功能总览

-   **热记忆四板块**：`identity`（角色自我）、`user 板块`（用户画像）、`rules`（规则铁律）、`memories`（关键记忆）。
-   **分级注入**：`mind-seal` 每轮；`important` 每 5 轮 / 10k 输出 token；`normal` 每 12 轮 / 30k；`minor` 压缩后一次。共享计数器，受总预算约束。
-   **项目档案**：会话级 Markdown 文档，支持新建/编辑/启用/停用/归档/取消归档/软删除；启用档案进入小型注入清单，停用档案可按需读取，归档档案模型只得到错误；正文按 20K 分段加载。
-   **项目档案筛选**：列表按启用/停用/归档过滤，分页前生效；选择写入会话配置，重启后保留，不影响家族共用查询。
-   **项目档案附件**：每篇档案独立附件框，一次显示一个；最多 5 个，`<` `>` 与页码切换；支持系统选择器、手动路径和 http(s) 网页链接；外部文件只挂路径、不复制、不限大小，删除只摘索引；文件丢失显示“（已丢失）”。
-   **项目热记忆**：按 `projectLabel` 绑定项目档案，可挂任意板块；项目启用才注入，停用/归档不注入、不占预算；每个会话独立存储，同名项目可并存，支持显式跨读。
-   **记忆家族**：母归属/子会话/脱离/让位/解散/根转移；母归属可单独修改家族显示名，不改文件夹与成员；子会话的全局热记忆只读，但可以拥有自己的项目热记忆；长记忆互读；文件锁、journal、选举、根转移与旧根只读。
-   **项目档案家族共用**：项目档案可授权全家族只读；拥有者控制启停、共用与归档，成员不能改；共享的项目热记忆跟随拥有者档案状态；独立会话不能启用共用；空根家族可显式接管，让位后未选举前可撤销让位。
-   **自动捕获**：严格命令式只负责识别，由模型按语义写入对应板块；非命令式由模型自行判断；规则只进候选。
-   **手动注入**：页签条目可「立即注入」；下一轮注入带【手动注入】段。
-   **检索关联**：项目档案检索命中后，按同项目或共享 tag 自动补最多 3 条相关文档。
-   **归档快路径**：压力超阈值时只用 tokenMeter 触发，检测不再全量解码日志；真正归档时才解码校验。
-   **轮次摘要索引**：`palace_turns`、轮次统计、窗口探测、自动检查与手动归档规划更快；索引不可用时自动重建，归档正文仍用完整轮次。
-   **轮次双摘要**：`palace_turns` 每轮同时显示用户与助手摘要，助手最多 200 字，便于判断归档类别。
-   **全量校验**：页签可手动重新检查会话日志并校正轮次索引与统计；可能耗时几十秒，不阻塞其他页签。
-   **摘要定位**：`palace_summary(keyword=...)` 先扫月度摘要，返回年月/类别/轮次；本会话未命中时可按配置回退家族、全库搜、询问用户，或仅停在候选摘要。候选按段取：每月最多 1–6 段（默认 3），用本地词法打分排序，整段摘要返回；每页最多 3 个月，月数上限 = 保底月数 + 增量（0–18），用返回的 `candidateCursor` 翻页。
-   **彻底压缩时的归档**：勾选「归档后彻底压缩」并手动归档时，除最后 `archiveTailTurns`（默认 2）轮外全部归档；不勾选仍按原保留窗口。
-   **缓存自检**：只统计缓存实际追加/重建，每 20 次写入做一次全量解码校准（可调 10–100）；重建后自动清理 manifest 未引用的旧 chunk；成功写入后顺带清理超过 24 小时的崩溃临时文件。
-   **检查/安装更新**：页签检查更新；安装更新需用户确认，失败可回退。
-   **本地优先**：归档、热记忆、项目档案、家族状态都在当前工作区 `memory-palace/`；不依赖外部记忆服务。

## 安装

```powershell
dsh plugin --profile <profile> add @dafantong01/dsh-memory-palace
```

安装后重启 DSH，在会话页签打开「记忆宫殿」，给会话命名后才会归档。

## 已知限制

-   不做 embedding；检索是关键词/时间召回，口语化或跨义描述可能搜不到。
-   不自动注入项目档案全文；按需用 `memory_doc_search` / `memory_doc_read`。
-   归档、项目文档、热记忆的写锁以单 DSH 实例为前提；多实例不做强一致保证。
-   可与其他记忆工具并存；迁移前先备份并人工抽查。
-   UI 的提示位置、原位编辑、保存后排序属于已知低优先级体验项。

## 工作方式

1.  **触发检查**：每 `checkEveryTurns` 轮（默认 5），在回合收尾处检查一次。要同时满足两道门：
    -   **压力门**：上下文占用 ≥ `triggerPressure`（默认 60%）× 窗口。 占用取 **DSH 自己的计量** `ctx.tokenMeter.measure(session).totalTokens`——压缩后它会回落； 拿不到计量服务时才退回「日志轮次累加」，并在提示里标注「日志估算」。
    -   **批量门**：可归档轮数 ≥ `minBatchTurns`（默认 10）**或** 可归档文本量 ≥ 无需归档量 × `batchByteFraction`（默认 50%）
2.  **提醒**：两道门都过，插件注入一条极短提示，请模型调用归档工具（`enableSteer:false` 可关掉，关掉就没有自动归档）。
3.  **分类（逐轮判断）**：模型逐轮决定每轮属于哪个类别，用 `segments` 提交： `[{category, fromTurn, toTurn}, …]`。同一类别可以拆成多段，最后合并成一个文件； 每个 turn 只能归一类，区间不许重叠。
4.  **保留**：`无需归档的近期文本量 = 窗口 × retainFraction`（默认 12%），比这更新的轮次不动。 取整轮粒度、严格不超过该上限；只有单轮本身就超上限时，至少保留最后 1 轮。 12% 的用意：压得比 DSH 压缩尾部（约 16%）更小，压缩时不会碰到你还没归档的近期内容。
5.  **写入**：插件从会话日志逐字取出每个类别的轮次，按时间正序写进该类别**一个文件**（超 `maxFileBytes` 才分卷）。模型不复述内容，不会截断或改写。
6.  **覆盖去重**：已归档轮次记在 `.state.json` 的 `archivedRanges`；新请求先把已覆盖的轮次剔掉，只写剩下的。
7.  **归档后压缩**：`compactAfterArchive` **默认关**。`compactNow()` 不接受范围参数，压多少由 DSH 自己决定， 可能压掉尚未归档的近期轮次（原文仍在会话日志里，可再归档）。默认不动它。

## 目录与文件名（会话级隔离）

```
<当前工作区>/
  memory-palace/
    .namespaces.json       # 会话ID → 文件夹名 的映射（插件维护）
    config.json            # 新会话的默认值（旧版遗留，仅作默认）
    <文件夹>/              # 记忆名：英文（大小写均可）+数字/空格/下划线/连字符
      config.json          # 本会话自己的开关/参数/记忆名
      .state.json          # 本会话水位、已归档区间
      index.jsonl          # 本会话的归档索引（路径相对本文件夹）
      <YYYY-MM>/           # 月份容器：归档时按归档年月找/建
        _summary.md        # 该月摘要：只追加，每段对应一次归档里的一个类别
        <category>/
          <前缀>-<category>-<YYYYMMDD-HHmmss>.md
```

-   **文件夹名 = 页签里填的「记忆命名」**：英文（大小写均可）、数字、空格、下划线、连字符，≤32 位；**首尾不能有空格**，中文与路径分隔符会被拒绝。
-   没命名时用会话ID，且**不产生任何记忆文件**（只建 config/state）。
-   在页签里改名并保存 → 文件夹**就地改名**，索引里的路径是相对的，不需要跟着改。
-   **文件夹即归属**：`memory-palace/<你的文件夹>/` 里的文件都属于那个会话；文件名前缀只是历史署名，不代表归属。
-   **摘要每月一份**：`<YYYY-MM>/_summary.md`，只追加；同一次归档里每个类别写一段，段头是「归档时间 · 对话时间范围 · \[类别\] 轮次范围」。
    -   月份按**该批对话首轮的时间**归属：10-31 深夜、11-01 才归档的对话仍落进 `2026-10/`。
    -   文件头注明 `turn = 日志事件序号`（含系统指令、插件注入、工具调用），不是“第几条消息”。
-   一次归档调用里，同一类别的所有轮次进同目录下的**一个文件**（超 `maxFileBytes` 才按轮分卷 `-p1/-p2`）。
-   不同类别 = 不同文件，即使来自同一次调用。
-   同秒冲突自动加 `-2`。分类目录强制英文小写。

### 从旧结构迁移

早期版本用过不同的目录结构。迁移脚本只用于本项目早期数据，**不包含在发布包中**；新用户从 0.1.0 开始使用无需迁移。

当前采用的结构是 `<会话>/<YYYY-MM>/<category>/`。

## 工具

| 工具 | 作用 |
| --- | --- |
| `palace_archive` | 归档轮次。**未命名会话会拒绝**。用 `segments` 逐段给类别：`[{category, fromTurn, toTurn}, …]`；并用 `summaries=[{category, text}, …]` 给**每个类别**写一段只概述该类别本次轮次的话（逐段追加到当月 `_summary.md`）。单类别时可用 `summary` 代替。可传 `selfName` 作文件名前缀。**超出保留边界或已归档的轮次会直接报错**（防止模型估错轮次号） |
| `palace_turns` | 列**轮次清单**：`turn` 号 + 发言者 + 开头 70 字，用于归档前确认每轮内容。`turn` 是日志事件序号（含系统指令/插件 steer/纯工具轮），**不要用“第几条消息”换算** |
| `palace_summary` | 读**月度摘要**：不指定 `month` 时列出最近几个月（摘要末尾预览 + 归档文件数）；`month=YYYY-MM` 返回该月摘要全文；`category` 只看该月某类段落；`append` + `fromTurn/toTurn` 可给**还没归档的近况**补写一段摘要 |
| `palace_search` | 检索归档。默认**只查本会话**；`namespace` 查别的会话、`all:true` 扫全部命名空间（结果标来源）、`category` 只查某类。`keyword` 支持空格分隔的多关键词（AND，引号包短语）。默认**按轮聚合**（每轮一条代表命中 + 该轮命中数），`limitTurns` 控制轮数（默认取 `searchTurnLimit`\=12）；`groupByTurn=false` 回原始命中行（旧 `limit` 语义）。片段约 220 字符，总输出上限 8K，文件读失败会跳过并注明。**只搜归档正文，不搜 `_summary.md`**（摘要里的概述性说法要用 `palace_summary` 读）；但原文 **0 命中**时会自动回查摘要并标注「摘要不是轮次」，可用 `includeSummary:true` 强制追加 |
| `palace_read` | 读归档。`fromTurn/toTurn` 返**完整原文**；`path` 可省略（按轮次自动找文件），也接受 search 的「文件夹/…」路径；可传 `namespace`。末尾附一行**回链**（提取 turn 引用/文件名/工具名，自动提取仅供参考） |
| `palace_config` | 查看/修改**本会话**配置（`get` 会同时返回 effective / 工作区默认 / 本会话配置） |

### 检索四步法（为省 token 设计）

```
0) 不知道在哪个月：palace_summary(limit=6)
   → 每月摘要末尾预览；找到大致年月
0b) palace_summary(month="2026-10")
   → 该月全部摘要段落（哪次归档、讲了什么）
1) palace_search(keyword="事故教训", limit=3)
   → 约 1 千字符：命中位置 + 轮次 + 行号 + 文件路径
2) palace_read(fromTurn=48, toTurn=48)
   → 该轮完整原文（思考、工具调用、返回都在）
```

-   单次读取默认上限 **60,000 字符**（约一本书的三分之一），硬上限也是 6 万。
-   单轮超过 6 万字符时，返回前 6 万并提示 `用 offset=N 继续`，可分段读完整个大轮（实测 12.7 万字符分 3 段读完）。
-   不给轮次、也不给 path 时只返回文件开头 6 万字符，并提示按轮次精确取。

## 开关（会话级，fail-closed）

真正生效要同时满足（现在收成**一个统一门** `gateState()`，页签会显示“为什么没生效”）：

1.  **全局总闸** `enabled`（默认开，只是允许插件工作）
2.  **本会话开关**：`memory-palace/<文件夹>/config.json` 里 `enabled: true`，新会话缺省为关
3.  **已命名**：记忆名为空时，即使开了开关也**不归档**（只建文件夹和配置）
4.  **自动提示**：`injectNotice` / `enableSteer` 任一关掉 → 工具仍可用，但不会主动 steer（页签会写明）
5.  **会话可见性**：`palace_archive` 被 capability-panel 关掉的会话整块静默

`GET /memory-palace-api` 额外返回 `gate: { active, steer, reasons[] }` 与 `events`（最近 20 条插件事件：归档/检索失败/门关闭等），页签直接展示，不用解压会话日志。

### 三个入口

-   聊天框 **`/palace on`**（`off` 关闭，`status` 查看）
-   页签「记忆回廊」里的滑块
-   让模型调用 `palace_config`

都只改**当前会话自己**那份配置——不碰 profile、不用重启。

## 会话页签（GUI）

会话头部会多一个「记忆回廊」页签，按**当前会话**显示与修改：

-   开关滑块（绿色=已开启、灰色=已关闭）
-   本会话文件夹（`memory-palace/<名字>`；未命名时显示会话ID并提示不会归档）
-   「记忆命名」输入框：保存即**改名文件夹**；只接受英文（大小写）/数字/空格/下划线/连字符、首尾不能空格；与同工作区其他会话重名会被拒绝
-   估算窗口 tokens（只读，自动探测）
-   触发阈值 %（滑块 + 输入框联动）
-   检查频率、最小归档批量、批量兜底阈值 %、无需归档比例 %
-   无需归档的近期文本量（只读，窗口 × 比例为 token 数）
-   单文件上限 MB
-   自动提示、收录深度思考、归档后压缩
-   最近 20 条归档列表

数据来自宿主路由 `GET/POST /memory-palace-api`（`kind: exact`；DSH 的 `/api` 是 RPC 通道，不能占用）。 非活跃会话通过会话日志头部的 `session` 事件取 `cwd`，不依赖 agent 是否在运行。

## 项目档案附件

项目档案详情下方是独立附件框，只显示当前档案的附件，不混进正文。

-   一次显示一个附件，`<` `>` 切换，页码标出第几个 / 共几个
-   最多 5 个；圆形按钮：添加、删除、用系统默认程序打开
-   添加方式：系统文件选择器，或手动输入本地绝对路径
-   网页链接：只接受 `http://` / `https://`，点击用系统默认浏览器打开；删除只摘索引，不访问或修改网页
-   外部文件只挂路径，不复制、不限单文件大小；删除只移除索引
-   图片按需加载；非图片显示图标与文件名；文件被改名或移走后显示“（已丢失）”，不能打开
-   同一路径、同一链接或同一内容不能重复挂载

附件索引写在 `_docs/assets/<文档 ID>/attachments.json`，不写进档案正文，档案 `rev` 不因附件变化递增。

## 配置分层

1.  **全局默认**：插件配置（profile 级，volatile）。
2.  **工作区默认**：`<工作区>/memory-palace/config.json`，只作为新会话的初始值。
3.  **本会话配置**：`memory-palace/<文件夹>/config.json`，页签与 `/palace` 实际改的是这份。
4.  **按会话开关**：capability-panel 里关掉 `palace_archive`。

可被工作区覆盖：`enabled`、`triggerPressure`、`retainFraction`、`batchByteFraction`、`retainBytes`、 `maxFileBytes`、`checkEveryTurns`、`minBatchTurns`、`selfNameSlug`、`includeReasoning`、 `compactAfterArchive`、`injectNotice`。

## 配置项

| 项 | 默认 | 说明 |
| --- | --- | --- |
| `enabled` | true | 全局总闸 |
| `triggerPressure` | 0.6 | 压力门：历史估算 ÷ 窗口 |
| `retainFraction` | 0.12 | 无需归档比例，占窗口比例（0.02–0.5，建议 < 16%） |
| `batchByteFraction` | 0.5 | 批量门兜底：可归档量达到无需归档量的该比例即放行 |
| `minBatchTurns` | 10 | 批量门：可归档轮数 |
| `checkEveryTurns` | 5 | 每几轮检查一次 |
| `maxFileBytes` | 5000000 | 单文件上限（十进制 MB，5,000,000 = 5.0 MB），超出按轮分卷 |
| `selfNameSlug` | assistant | 文件名前缀（与「记忆命名」无关，可分开设置） |
| `rootDirName` | memory-palace | 根目录名 |
| `includeReasoning` | true | 归档是否收录思考原文 |
| `compactAfterArchive` | false | 归档后是否触发压缩（默认关，见上） |
| `enableSteer` | true | 是否注入归档提醒 |
| `injectNotice` | true | 是否注入提示 |
| `enabledWorkspaces` | \[\] | 额外工作区白名单 |
| `enabledSessions` | \[\] | 额外会话白名单 |
| `contextWindowTokens` | 自动 | **只读**：从日志 `request/context` 探测，进程内缓存 |
| `searchTurnLimit` | 12 | `palace_search` 按轮聚合时默认返回多少轮（1–30 整数，服务端也校验） |
| `groupByTurn` | true | `palace_search` 是否默认按轮聚合（false 回原始命中行） |
| `recallStrength` | low | 回忆强度：`off` / `low` / `medium` / `high` / `forced`（见下节） |
| `recallBudgetRounds` | 1 | **建议预算**：最多几轮（1–5 整数，仅 high/forced 出现；插件不强制执行） |
| `recallBudgetKeywords` | 1 | **建议预算**：每轮最多几个关键词（1–5 整数；插件不强制执行） |
| `recursionMaxDepth/Width` | — | 旧键，等价于上面两个；读写时保持同步，仅为兼容保留 |
| `retainTurns` | — | **已废弃**：保留窗口只按比例算；写入时会被忽略并清理 |

会话配置里额外有 `name`（记忆命名，默认空）；会话开关是会话配置里的 `enabled`。

## 回忆强度（五档）

| 档位 | 行为 |
| --- | --- |
| `off` 关 | **只归档，不读记忆**；不注入任何回忆/摘要提示 |
| `low` 低 | 只归档，**不主动注入任何提示**；模型仍可自己调用 `palace_*` 工具读记忆 |
| `medium` 中 | 平时静默；**仅在上下文压缩后**前置注入一次「去读最近归档摘要」的指引（请求前生效，不产生第二条回复）；不递归 |
| `high` 高 | 同 medium，并**允许**模型主动递归检索，受 `recallBudgetRounds/Keywords` 预算约束（预算只是建议，插件不强制执行） |
| `forced` 强制 | 每条用户消息后发一条检索指令（`[记忆回廊·系统注入]` 标记）；没有可检索线索时允许跳过；没有归档时插件返回「归档记忆为空」，模型必须如实回答，不得编造 |

补充规则：

-   **启动时不注入**：重启后会话历史本身就在上下文里，“上一轮聊到哪”不需要摘要补；只在**压缩后**注入一次归档摘要。
-   **medium/high 不是“每轮读摘要”**：它们在压缩前完全静默，只有压缩后那一条前置指引；如果用户以为中档会一直主动回忆，那是误解。
-   **压缩后只注入“去读哪份摘要”的指引（硬触发）**：监听 `session/event` 的 `compaction/end`；每次上下文压缩完成后，下轮请求组装前注入一条**简短指引**（不注入摘要全文），要求先调 `palace_summary(month=…)` 读最近年月的归档摘要，再继续。月份取自**实际存在摘要的最新月份**（不是日历当前月，跨年也不会指向空月份）；该月摘要不足 500 token 时，指引会额外给出上一个月的调用方式。优先级：**系统压缩摘要优先，它没覆盖到的内容用归档摘要补充**。这条指引是普通上下文消息，下次压缩自然消失——**不会每轮重复强调**。
-   **事件失效是静默的**：`session/event` 属于首方内部用法，DSH 升级若改名不会报错、只会不收事件。插件会在“最近事件”里记 `compaction-detected` 与 `recall-after-compaction`，页签看不到这两条就说明链路没通。
-   **预算是提示不是硬约束**：递归由模型执行，插件只把上限写进指令；超了要模型自己收敛。
-   **强制档有成本**：每条消息多一次检索往返，长会话里 token 消耗明显。
-   **强制档会多一条回复**：steer 是后置注入的独立消息，宿主必然为它起一轮，所以可能出现“主回答 + 一条简短的检索说明”。这是注入方式的固有成本，插件无法消除；v0.2 计划改成请求前注入。注入消息带 `[记忆回廊·系统注入]` 前缀和 `source.kind='dsh-memory-palace'`，便于识别。
-   所有档位都**不改变归档行为**（`off` 也照常归档原文）。

## 可靠性

-   **原子写**：归档文件、`.state.json`、`config.json` 都是先写临时文件再 rename。
-   **数据优先**：归档先写文件、再写摘要、最后写状态（摘要失败时 state 未更新，重试不会变成“已归档过”）；索引追加失败写进 `.pending-index.jsonl`，下次归档前自动补写；追加前会补换行，避免半行粘连。
-   **边界语义**：保留边界 `boundary = 0` 表示“全部在保留区、暂不可归档”，不是“无限制”；且**永远不归档最后一轮**（可能正在生成）。
-   **覆盖集以索引为准**：判断“已归档”时按 `index.jsonl` 里真实存在的行展开，不用 `archivedThroughTurn` 单点最大值，避免区间空洞被填平。
-   **不重复**：覆盖去重（区间剔除）+ 同秒 `-2` 兜底。
-   **索引容错**：读 `index.jsonl` 前会剥掉 UTF-8 BOM（旧文件可能带 BOM，按行 parse 会全失败）。
-   **读取限制**：`palace_read` 只能读本命名空间（或 legacy 根）下的归档，`.state.json`/`config.json`/`index.jsonl`/`.namespaces.json` 直接拒绝。
-   **可观测**：`.state.json` 记 `lastCheckTurn / lastCheckAt / lastPressure / lastArchiveRange`，`/palace status` 可见。
-   **解码缓存**：按日志 `mtime + size` 缓存（最多 8 个会话）。
-   **失败静默**：钩子内 catch，不阻塞对话。

## 依赖与失败策略

-   读 DSH 的 `.zstd` 日志需要 `fzstd`（多帧解压；Node zlib 只解第一帧）。
-   注册一个 systemPrompt 段（order 160）用于常驻检索指引，并注册一个压缩后注入的动态上下文；不监听 `agent/pre-step`，避免与其他插件抢接缝。

## 兼容性

-   需要 `ctx.tools.register`、`agent/turn-stopping`、`agent.steer`、`ctx.webServer.register`、`ctx.compaction`（可选）。
-   日志按 DSH v4（`session.v4.jsonl.zstd`）解析；格式变了会少条目而不是报错。

## 图片、文件与联网结果

-   图片/文件**不存字节**：只写一行占位符（`[图片 sha256:… 1024×768｜…]`），删了附件也不会崩。
-   联网搜索结果按工具返回文本归档，单块截断 40 万字符；用户/助手文本与思考各截断 20 万字符。

## 安装

**从 npm 安装（推荐）**

```
dsh plugin --profile <profile> add @dafantong01/dsh-memory-palace
```

**从 GitHub 安装（钉 commit，避免拉到未发布的中间状态）**

```
dsh plugin --profile <profile> add github:dafantong01/dsh-memory-palace#<commit>
```

**从本地 tgz 安装**

```
dsh plugin --profile <profile> add @dafantong01/dsh-memory-palace
```

装好后在 profile 的 `dsh.profile.bundles` 里确认有 `@dafantong01/dsh-memory-palace`，然后重启 DSH。

> pnpm 对 `file:` 依赖会做 junction；如果插件树激活失败，检查 `node_modules/@dafantong01/dsh-memory-palace` 是否是真实目录。

## 兼容性与权限

-   **DSH 版本**：`engines.dsh` 为 `>=0.2.1-rc.2 <0.3.0-0`，低于或高于此范围时市场会标记不兼容。
-   **运行时权限**：插件在你的 DSH 进程内运行，权限等同你本人：
    -   读 `$DSH_HOME/sessions/` 下的会话日志（归档原文来源）
    -   读写当前工作区的 `memory-palace/`
    -   注册一个本地 HTTP 路由 `GET/POST /memory-palace-api`（仅本机回环）
-   **不联网**：不请求任何外部服务，数据全部留在本机。
-   **不存附件字节**：图片/文件只记占位符与哈希，原文件删除也不影响归档。

## 常见问题

-   **页签显示「session not found」**：路由拿不到该会话的 `cwd`，通常是日志被移走。
-   **`/palace status` 显示未开启**：工作区 `config.json` 缺 `enabled:true`。
-   **一直不触发**：检查压力是否到阈值、可归档区间是否为空（近期内容都在保留区内）。

## 常驻提示词

插件常驻一段 systemPrompt（order 160，约 60 token）：

> 本工作区有 memory-palace 归档。需要更早的细节、旧决定、被压缩掉的历史，或用户问起“之前说过什么”时， 先用 `palace_search` 定位，再用 `palace_read` 按轮次取原文；不要凭印象编造过去的事。

工具描述也配合写成“先用它定位”。

## 按类别分段归档

模型逐轮判断类别，用一次调用提交多段：

```json
palace_archive({
  "segments": [
    { "category": "dsh-plugin-dev", "fromTurn": 112, "toTurn": 114 },
    { "category": "bug-report",     "fromTurn": 115, "toTurn": 115 },
    { "category": "dsh-plugin-dev", "fromTurn": 116, "toTurn": 116 }
  ]
})
```

-   同一类别拆多段 → 合并写进**一个文件**，轮次顺序不变
-   每个 turn 只能归一类，区间重叠会报错
-   文件头会写实际轮次：连续 `turn 113–114`，跳号 `turn 113, 114, 116, 128`（4 轮，不连续）
-   索引行对不连续区间额外记 `turns: [...]`
-   归档正文的轮次标题改用 `## TURN n · 时间`，避免正文里“引用了旧归档标题”时把 `palace_read` 的切片切错；老文件仍按 `## 第 n 轮 ·` 兼容解析

* * *

## English

A DSH plugin that archives older conversation turns, verbatim, into a workspace-local `memory-palace/` directory before context compaction — then lets the model search and read them back later.

**Why**: DSH compacts long contexts; after compaction the original wording is gone. This plugin keeps it on disk, searchable.

**Install**

```
dsh plugin --profile <profile> add @dafantong01/dsh-memory-palace
```

or pin a commit:

```
dsh plugin --profile <profile> add github:dafantong01/dsh-memory-palace#<commit>
```

Restart DSH afterwards. Enable per session via the Memory Palace tab or `/palace on`.

**What it does**

-   Archives turns by category when context pressure crosses a threshold; never rewrites or truncates text.
-   Stores `memory-palace/<session>/<YYYY-MM>/_summary.md` plus `<category>/<file>.md`.
-   Tools: `palace_archive`, `palace_summary`, `palace_search`, `palace_read`, `palace_turns`, `palace_config`.
-   Five recall levels (`off` / `low` / `medium` / `high` / `forced`); after compaction it asks the model to read the latest month's archive summary.
-   Per-session configuration; data stays in the workspace.

**Requirements**

-   DSH `>=0.2.1-rc.2 <0.3.0-0`.
-   Runs inside your DSH process with your permissions: reads local session logs under `$DSH_HOME/sessions/`, reads/writes `memory-palace/` in the current workspace, and registers a loopback HTTP route `/memory-palace-api`.
-   No network calls, no attached-file bytes stored (placeholders with hashes only).

**License**: MIT.

## Plugin-page metadata (release check)

DSH reads a plugin's plugin-page title and description through Node's package exports: `@scope/pkg/locale/en.json` and `@scope/pkg/package.json`. If those subpaths are not exported, the plugin page shows only the raw package name.

Before publishing, keep both in `package.json`:

```json
"exports": {
  "./package.json": "./package.json",
  "./locale/*.json": "./locale/*.json"
},
"files": ["lib", "locale", "cordis.patch.yml", "README.md", "LICENSE", "..."],
```

`locale/en.json` and `locale/zh.json` must both contain:

```json
{ "meta": { "title": "...", "description": "..." } }
```

Verify:

```bash
# from the repo (checks fields and files)
node scripts/check-meta.mjs .

# from a profile directory, with this script copied OUTSIDE the package
node check-meta.mjs @dafantong01/dsh-memory-palace
```

Run the installed-package form before every release; the source form only checks fields, not Node resolution.

## 常见问题

### @dafantong01/dsh-memory-palace 是什么？

本地长期记忆：在上下文压力升高时归档较早的整轮原文，压缩后可读回；支持 identity / user 板块 / rules / memories 四板块分级注入、项目档案与项目热记忆、记忆家族与根转移、手动注入、20K 长文分段、tag 关联检索。数据都保存在当前工作区，不依赖外部记忆服务。

### 如何安装 @dafantong01/dsh-memory-palace？

在项目目录运行 npm install @dafantong01/dsh-memory-palace，或使用 pnpm add / yarn add / bun add。

### @dafantong01/dsh-memory-palace 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/dafantong01\_\_dsh-memory-palace 是否存在。

### @dafantong01/dsh-memory-palace 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @dafantong01/dsh-memory-palace 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js ^22\.19\.0 \|\| \>=24\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @dafantong01/dsh-memory-palace 可以商用吗？

@dafantong01/dsh-memory-palace 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @dafantong01/dsh-memory-palace 的下载量有多少？

根据 npm 官方下载统计，@dafantong01/dsh-memory-palace 在 2026/10/11 – 2026/11/09 这 30 天内被下载 5,542 次，日均约 185 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @dafantong01/dsh-memory-palace 还在维护吗？

最新版本 0\.3\.11 发布于 2026/11/11（今天）；至今共发布 29 个版本，其中过去 12 个月发布了 29 个；首次发布于 2026/10/24。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

