跳过主要内容
V

dsh-memory-archive

vv5v5/dsh-memory-archive

面向 DeepSeek Harness 的记忆库 + 提示词查看器:把被压缩折叠掉的内容重新变得取得到——浏览历史会话或 Tavern 周目归档(摘要、原文、状态)并全文检索;逐轮查看模型真正收到的提示词,列出每个 system 段落的顺序、字数、偏移、哈希与可变性,附装配地图、注册表导出,以及段落为空或日志读不出时的如实诊断。可选一键生成 RP preset。

安装

dsh plugin --profile web add github:vv5v5/dsh-memory-archive

README

dsh-memory-archive · 记忆库

不发明记忆,只把 DSH 已经压掉的东西重新变得「取得到」。

DSH 的上下文压缩compaction-basic)本来就在把旧内容折叠出模型可见面。 本插件不重写压缩、不重写摘要、不建第二份存储、不改 DSH 本体一行,只补三件事:

  1. 取用 —— 被折叠的内容一直都在会话日志里,缺的是一个够得着的入口(面板 / 检索 / 每轮注入);
  2. 如实标注 —— 每条内容标明它此刻是 current(还在模型可见面)/ shadowed已被压出上下文)/ log-only(本来就不上面);
  3. RP 的那一小套 —— 剧情笔记写入、最近几楼、第一轮保留、角色卡后处理指令、RP 专用压缩后端与压缩后收纳。

配套的两个独立插件(都是可选的,本仓库不含它们的代码): pmp-dsh-tavern(角色卡 / 世界书 / 周目 / ST 预设)与 dsh-anima-rag(向量 + BM25 检索、回响、向量面板那半边)。


它现在能干什么(如实标注)

能力状态
记忆库面板:摘要 / 原文 / 剧情大纲 / 向量 四档 + 设置
提示词查看器:每次模型请求真正发出的全文(system 段地图、段级偏移、点开看该段正文、消息流)
剧情笔记写入memory_write 工具,写进本会话周目的 .roleplay-memory/(⛔ 只写周目目录)
预部署资料:把要预置的文件放进工作区根 .roleplay-memory/ ⇒ 新周目开局就读得到(只读、所有周目共享;见下)
每轮注入mt:memoryProtocol · mt:memoryHome · rp:firstRound · mt:lastFloors
角色卡后处理指令(PHI):从 system 段挪成「玩家消息之后」的一条 user 消息(默认开)
RP 压缩后端:中文归档指令(mt-compaction-rp.js,由本仓库生成、挂进预设目录)
压缩后自动收纳 + 孤儿清理(摘要进库、账本防重、被删切片的对账与隔离)
OOC 两席:输入栏的「OOC」前缀按钮 + 划词「质疑」
一个 skillrp-assistant(带三份可查资料,见下)
自带的 RP 预设preset/(组装 + 模块 + 压缩后端),node preset/install.mjs --apply 铺到预设目录✅ 可选,随包发布;模块从本仓现场取 ⇒ 预设与插件不各自漂移
两种根:会话模式(零依赖)/ 工作区模式(需 pmp-dsh-tavern
预设生成 / 写入面(detect · apply · rollback · provision · backups · pack)已退役(2026-09-19 用户口径:「不用保持了」)—— 预设目录现在自己维护,本插件不再替你改
状态子系统state-bridge 子包 + state:card 段 + 5 个状态工具)已剥离(2026-09-20)—— 状态改由周目笔记 state.md 承载,模型按文件开头写的要求自己维护

安装

# 从 GitHub
dsh plugin --profile <你的 profile 名> add github:vv5v5/dsh-memory-archive

# 或本地目录(开发用)
dsh plugin --profile <你的 profile 名> add ./dsh-memory-archive

装完重启一次宿主:浏览器半侧的 bundle 是宿主启动时组装的。

附带的 RP 预设(可选)

本包自带一份「角色扮演」预设(preset/:组装文件 + 几个模块 + RP 专用压缩后端)。 它的描述里写明「由 dsh-memory-archive 提供」 —— 预设列表里同名的那份是社区预设,认描述就能分开。 它不会自动生效(DSH 的预设是文件系统型的),要铺一次:

node <profile>/node_modules/dsh-memory-archive/preset/install.mjs          # dry-run:先看会写什么
node <profile>/node_modules/dsh-memory-archive/preset/install.mjs --apply  # 真写(默认 roleplay 目录)

细节、依赖与限制见 preset/README.md

本包没有构建步骤 —— lib/ 里就是可直接运行的 JS(react 由 DSH 平台的模块 seed 表提供)。

依赖

功能依赖
记忆库(会话模式)/ 提示词查看器 / 工具与注入零依赖 —— 原版 DSH 纯净环境即可用
工作区模式、剧情笔记目录、剧情大纲、向量页签的体检行需要 pmp-dsh-tavern可选,未装时相关入口置灰并说明原因)
检索注入(anima:memory)、回响、向量页签的动作需要 dsh-anima-rag可选

两者在 package.json 里都是 optional peer,不会被强制安装。


两种根模式

记忆库要能在两种环境里用,而它们的「根」根本不是同一种东西 —— 所以根是一个可切换的模式

会话模式(默认)工作区模式
一条手动选定的 DSH 会话Tavern 工作区里某个周目的 archive/
数据来源DSH 自己的会话事件日志(精确读,不触发索引重建)归档文件(floors/ summaries/ .roleplay-memory/
能看到该会话的全部事件,含已被压缩出上下文的那些归档契约覆盖的那些:原文 / 摘要 / 剧情笔记
依赖pmp-dsh-tavern

「手动选择」是刻意的 —— 「哪条会话算记忆」是用户的语义判断,不做自动推断。


面板

侧边栏底部两个入口:记忆库(齿轮)与 Agent 编辑器(只读检视组装)。输入栏里还有两席(OOC)。

记忆库 → 四档 + 设置

  • 摘要 —— 按楼序拼接成长文,从头读到尾;
  • 原文 —— 按需懒加载:每条的 surface 如实标记(current / shadowed / log-only),未发给模型的楼层如实标注;
  • 剧情大纲 —— 本会话周目 .roleplay-memory/ 里的笔记(index.md / state.md / characters.md / world.md …),内容需手动确认才展开;展开后两处落点各一行(本会话周目目录 / 跨周目共用那份),各自标「在 · N 份」或「还没有」,并各带一个按钮:打开文件夹 / 创建并打开(周目目录还没建 ⇒ 先建再开)/ 打开工作区根(共用那份还没建 ⇒ 打开工作区根让你自己放,⛔ 我们不替社区预设建目录);
  • 向量 —— 本库(dsh-memory)的体检行 + 两行库(向量 / BM25,各带 ⚠缺失 / 重建 / 删除)+ 一个「参与检索」开关;动作走一张请求单,由 dsh-anima-rag 在该周目会话的下一轮开始前执行,回执写回来(lib/vector-panel.js);
  • 设置 —— 根模式与根选择、向量检索 API(向量模型与重排模型各一套「接口地址 / 模型名 / 密钥」,两个密钥都只写不读、可各自清空)、提示词模板(压缩指令 / 收纳占位)、各项开关。

会话、周目、角色都显示真名而不是 id;三级回退(title → 周目反查 → 8 位截断 id)各级如实标注来源任何情况下都不显示完整 UUID

Agent 编辑器(只读)

当前会话所用 preset 的段 / 插件 / order 清单(每项一句「谁注入 · order · 作用」)、段级偏移、 「面板值 vs preset 实际值是否一致」(不一致就明说「面板改了也不会生效」)。v5 起零写入,连备份目录都不建。


每轮往提示词里注了什么(RP)

口径:会话优先,认不出来的会话当新会话(2026-09-20)。「哪个周目」按这个会话在 Tavern catalog.json/timeline.json 里归入的那个算;认不出(新开的会话还没被 Tavern 认领 / 不是 Tavern 的会话) ⇒ 没有周目:下面凡是要"某个周目"的,一律不注入memory_write直接报错。 会话若同时被两个周目引用 ⇒ 判给它是 rootSessionId 的那个(顺序无关);两个都不是根才按 catalog 顺序。 面板里那个「工作区根」只是查看用的视图(手动选根看别的周目照旧),⛔ 不决定注入写哪儿。 顶栏会并排显示两件事:当前根:…(视图)+ 本会话:…(生效;未归入时是红字)。

预部署(新周目开局就带上下文):把要预置的文件(角色设定 / 世界书 / 写作规矩一类)放进 工作区根下的 <工作区根>/.roleplay-memory/ —— <memoryHome> 段会把它列出来(只读), 模型开局就读得到;⛔ 它不是写的地方(各周目的笔记仍只写自己周目目录,免得串味)。 为什么只能提前放到这儿:周目目录名里带新建时才知道的 UUIDplaythrough-<uuid>)。

段名作用开关(插件 config.json
mt:memoryProtocol告诉模型什么时候该主动去检索历史常开
mt:memoryHome告诉模型剧情笔记写在哪个目录常开
rp:firstRound第一轮原文钉住(每轮在场、永不进可压区间)keepFirstRound.enabled
mt:lastFloors本会话上下文还短时,把本档案最近几楼的原文当历史喂进去lastFloors.enabled · count · maxChars
anima:memory检索到的历史(<recalledMemories> + <immediateHistory>)—— dsh-anima-rag见那个插件
(PHI)角色卡的后处理指令:从 system 段挪成玩家消息之后的 user 消息phiAsMessage.enabled,默认

★ PHI 是唯一一处故意写进会话历史的注入(其余全走「不写历史」的缝):因为 DSH 的 system 段无法实现文末注入, 只能拿 user 消息模拟。代价是它在每轮之间会积累 ⇒ 提示词查看器里标红显示不计楼层,记忆库不收录它。


配置存在哪

<DSH_HOME 或 ~/.dsh>/dsh-memory-archive/config.json

权限 0600(里面有 API 密钥)、原子写(临时文件 + rename)、读坏不崩(回落默认值并如实报错)。 密钥只在本机:不进 git、不进日志、不经任何响应体回显(宿主只回 keySet 与末 4 位提示)。

主要键:rootMode · root · retrieval{url,model,key,rerankUrl,rerankModel,rerankKey,chatEnabled} · prompts{compaction,placeholder,compactionJailbreak} · keepFirstRound · echo · lastFloors · memoryWrite · phiAsMessage · autoCollect · summarize · v3


宿主接口

全部为同源 HTTP,两条前缀路由在宿主启动时同步注册(ctx.effect 管生命周期,热重载不留野路由):

前缀内容
/dsh-memory-archive/api配置读写、会话精确读、/templates(提示词模板)、/sessions/session/events/collect/*(收纳)、/playthrough/*(周目目录与打开文件夹)、/vector/state + /vector/action(向量页签)、/retrieval/test(向量与重排发一次最小请求)、/agent + /agent/card(s)(装配只读检视与角色卡阅读)、/sections*(段表与正文)
/dsh-memory-archive/prompt提示词查看器的数据面:/health/api/sessions/api/session/api/part

拿不到的服务一律降级并说明ok:false + 可读 code),⛔ 不抛、⛔ 不 500、面板不白屏。


设计要点

完整思路见 docs/DESIGN.zh.md。四条:

  1. 能用原生机制就用原生机制 —— 「隐藏旧楼层」= surface replace 遮蔽,而 append-only 事件日志是真相源 ⇒ 任何遮蔽都可逆
  2. 不建第二份存储 —— 压缩只是把内容移出模型可见面,没从日志或索引里删掉。缺的从来不是存储,是取用
  3. 注入只走「不写历史」的缝 —— 只用 systemPrompt.section()system-prompt/assemble 瀑布;⛔ 不用 systemPrompt.context()(它是 durable user-role 快照,长对话里等于每轮追加一条);
  4. 一件事只有一个写者 —— 向量库归 dsh-anima-rag(面板只读状态 + 写请求单);预设目录归用户(本插件已退役写入面);剧情笔记归模型(走 memory_write)。

已知限制(如实)

#限制说明
1surface 可能为 null平台版本不同或读取路径降级时如实填 null绝不猜测
2工作区模式依赖 pmp-dsh-tavern未安装时相关入口置灰并说明,不会崩溃
3本插件不生成摘要摘要由压缩产出(RP 压缩后端写 compaction/summary),本插件只把它收进库
4「压缩指令」保存的是文本它由预设目录里的压缩后端读取(mt-compaction-rp.js,用 _materialize-preset-modules.mjs 铺盘)
5状态不再有独立子系统由周目笔记 state.md 承载,模型自己维护;⛔ 没有优先级更高的"状态工具"
6向量库的写入动作要等一轮面板点动作 = 写一张请求单,由 dsh-anima-rag下一次装配执行(面板会显示进度与回执)
7未归入周目的会话什么都拿不到口径如此(⛔ 不继承上一轮的绑定):笔记路径、最近几楼、回响、检索、最近总结全停,memory_write 报可读错。先在 Tavern 里给它开/选一个周目(经 Tavern「与 X 新开周目」开的会话从一开始就有周目)。顶栏与「向量」档都会如实标出来

开发

npm run check   # node --check lib/index.js && node --check lib/client.js
  • lib/index.js —— 宿主半侧:配置存储 + 同源 HTTP API + 每轮注入 + 自动收纳 + skill 注册;
  • lib/client.js —— 浏览器半侧:工厂形式 CJS,只 require('react')无 JSX、无需构建
  • lib/prompt-viewer.js —— 提示词查看器宿主半侧;
  • lib/vector-panel.js —— 向量页签宿主半侧(读状态快照 / 写请求单);
  • preset-modules/ —— 挂进预设目录的那几个模块的(含由生成器产出的压缩后端);
  • skill/rp-assistant/ —— 那一个 skill 的正文与资料。

改完记得:_sync-plugin-deploy.mjs --apply(同步到部署副本)→ 换进程重启 → 自检台全量跑一遍。

许可与署名

  • 许可证:Attribution-NonCommercial 4.0 International(CC BY-NC 4.0),SPDX 标识符 CC-BY-NC-4.0; 完整法律文本与 NOTICE 见 LICENSE
  • Copyright (c) 2026 dsh-memory-archive contributors

移植来源与署名(按上游要求保留)

项目内容
原项目anima-rag
原作者Ellinav
原项目地址https://github.com/Ellinav/anima-rag
原项目许可Attribution-NonCommercial 4.0 International(CC BY-NC 4.0)
移植许可经原作者 Ellinav 许可后移植

场景限制(移植许可的条件)

  • 仅限个人学习与非商业性用途;
  • 禁止闭源商用,禁止转为付费插件/服务;
  • 不重新分发任何预置私域数据。

第三方许可与出处

  • 派生自:DeepSeek Harness 官方 compaction-basic(压缩指令模板取自其 summarize 钩子) —— MIT,Copyright (c) 2026 DeepSeek;本作品中该部分保留原始 MIT 声明
  • 移植/派生自anima-rag(作者 Ellinav) —— CC BY-NC 4.0;本作品随之整体以 CC BY-NC 4.0 授权。
  • 互操作/致谢(⛔ 是互操作,不是派生):pmp-dsh-taverndsh-anima-rag —— 均为 MIT;本作品不包含它们的任何代码,只与其配合工作。

相关插件