dsh-liuhen
Verifieddsh-liuhen · v0.1.2 · MIT · Web UI
留痕 Trace — 可核对的 AI 记忆:索引、溯源、自动注入(默认关)、可选日记。
Install
dsh plugin add dsh-liuhen Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Creators
Readme
留痕 · dsh-liuhen
可核对的 AI 记忆。 它记得你说过什么,而且你能核对它记对了没有。
八块面板
面板每 30 秒自己刷新一次(页面在后台时不刷,切回来立刻补一次),不用关掉重开。
- 我是谁 — 你交代过的、希望它一直记得的事(装好后助手会自己写一次,见下)
- 我要写的日记 — 给主人的 / 给自己的,可选,默认关
- 今天的账本 — 只记今天,打开面板前先增量回填,不差 5 分钟
- 我亲手写的自省 — 由模型手写,没有自动生成、没有定时任务,只显示今天;有就写,没有就不写,空着不算欠账
- 我对主人的承诺 — 一份本机清单
- 仓库(完整原文) — 按天点开,从新到旧;每条原话旁边挂着批注,话和批注在同一条上
- 索引保留 — 索引按保留期归档(换个地方躺着),不删。没有「遗忘」这个功能
- 装着我的小盒子 — 一键打包:索引、完整原文、自省、日记、承诺、设置(放最底下,搬家才用)
第一次见面:它自己写「我是谁」
装好之后,助手下一次开口时系统提示里会多一段 [留痕 · 第一次见面]:
「我是谁」还空着,缺名字和一段自我介绍——这块是你自己的,不该等用户来写。
它调一次 trace_intro(name + text)就写好了,不用你先教它你是谁。
- 不预置人设:名字由它自己取,插件只提示、不代填
- 已经有内容时不覆盖;要改带
replace: true,旧内容先备份成liuhen/identity.bak-<时间> - 写的是它自己,不是你的信息;你的那部分在「关于你」,由你自己填
- 填完提示就消失,不会每轮都念;这段不跟注入开关绑,它是一次性设置提示
注入分两档
- 简洁档(默认):身份 + 关于你 + 日记状态 + 最近
briefRows条(默认 12)。实测约 2000 字。 - 完整档:按
days取当天/多天全量,不裁字。实测约 5100 字,且随当天对话继续变长。
选完整档要认一件事:注入块在系统提示一侧,越长越容易挤掉有效上下文。
maxChars / maxLines 是兜底闸,写成大于 0 才生效(0 = 不限)。
注入时会剥掉我复述的原文(inject.stripQuoted,默认开):我旧回复里的
代码块、> 引用行、超过 10 字的 「」/“”/『』 长引文都不进注入,
只留我自己的话;用户说的话原样不动。这一层是减面,不是清零——
对方把话写成普通段落、我又原样抄进正文时,认不出来。
注入了没有,有凭据。 每次真把内容附加到系统提示,插件会写一行
$DSH_HOME/liuhen/inject-state.json:时间、字数、行数、档位,不含内容。
面板「注入」那块会显示「上一轮 07:41:真注入了 1610 字 / 12 行(简洁档)」,
或者「没注入——开关关着」。生成失败也会记成 reason: "error",不再静默跳过。
预览不算凭据:预览走 dryRun,不看开关,关着也能预览出内容。
仓库(vault):索引短,仓库全
- 索引是摘要:每条只留 200 字,快、小,用来"翻"
- 仓库是原文:
$DSH_HOME/vault/<日期>.jsonl,一行一条,不折空白、不截断 - 写入只有一条路:回填时顺手落一份(不双写、不另起进程,避免"索引有、仓库没有"这种不报错的错)
- 读取给助手三个口子:
vault_read(某天原文)、vault_find(全仓库搜词)、vault_open(session+seq 精确取) trace_verify在会话文件被清之后会退到仓库——痕迹不依赖sessions/活着- 面板上点得开:设置里「仓库」那一块,列出有哪几天、多少条、几条批注;点某天就能翻原文,20 条一页,带「更早的」
- 话和批注绑在一起:一句原话上可以挂四种痕迹,各自独立、同种只挂一次
trace_feel(say, feel)= 感受(老的f/fs字段照样认)trace_ink(say, kind, text):kind取hes(犹豫)/why(当时的权衡)/unsaid(没说出口的)/feel(感受)- 存在那条记录的
b数组里({ k, x, t }),和原话同一条,读仓库时一起出来;面板上按颜色分开显示 - 没有就不挂,空着也是记录;不补历史(当时没记的,后来补就是编的)
- 找原话的顺序:一模一样 → 以它开头 → 包含它的最短一条(防挂到"复述自己"的那条上)
- 小盒子会连仓库一起打包,并把
pet-memory/(名字、承诺、跨会话汇总、交接信)带上;箱子里有一张00-读我.txt说明三层关系- 打的时候会脱敏(B 方案):姓名保留,生日、学校、籍贯/住址在包里那份副本上换成
[已隐去];磁盘原件一个字不改 - 按日期补打:
exportBox({ date: 'YYYY-MM-DD' })只装那天的原文,索引截到那天 - 打完往共享目录放一份:手机是
/storage/emulated/0/DSHBox,电脑(Windows / macOS)是下载文件夹 - ⚠️ 这个包里有完整原文(明文)。落到共享目录后,同一台机器上别的程序也读得到;
pet-memory/里还有个人信息。存好,别随手转出去
- 打的时候会脱敏(B 方案):姓名保留,生日、学校、籍贯/住址在包里那份副本上换成
隐私
- 零网络请求:插件自身不发起任何请求
- 只写本机:
$DSH_HOME/liuhen/,文件 600、目录 700(建目录时显式 chmod,不靠 umask) - 写接口只收本机面板:POST 必须是
application/json且同源,请求体上限 1MB - 仓库去重:读的时候按
session:seq去重并合并批注;scripts/dedupe-vault.js可以把文件里的重复物理收掉(加--write才写) - 注入可关:自动注入默认关闭;打开前可以预览将注入什么
- 不删:
retention.keepDays到期只归档到archive/,字节一个不少;没有遗忘接口 - 脱敏:手机号、邮箱、身份证、密钥、长数字串在注入与展示前替换为占位
- 承诺清单只认一份:有
pet-memory/承诺清单.md就用它,没有才用插件自己的liuhen/promises.md - 诚实的边界:脱敏挡不住自然语言里的隐私,它只能降低风险,不能消除
安装
dsh plugin --profile web add dsh-liuhen
电脑上也能用(0.1.2 起)
同一份插件,Windows / macOS / 手机都跑,不用装 7-Zip 之类的东西:
- 打包不再调
zip命令:自己拼 zip 容器(lib/zip.js,只用 Node 自带的zlib)。 0.1.1 在电脑上会报打包失败:spawnSync zip ENOENT,根就在这儿。 - 面板「打开」不再调
unzip -l:直接读 zip 的中央目录,中文文件名按 UTF-8 原样读回来。 - 共享目录按平台走(
lib/platform.js):手机 →/storage/emulated/0/DSHBox; Windows →%USERPROFILE%\Downloads;macOS →~/Downloads。面板文案也跟着换, 电脑上不会再写「存到手机」。 - 打包是可复现的:同一天同样的数据,打两次
sha256一样(目录条目固定时间戳, 脱敏后把 mtime 拨回去)——面板上那个 sha 才有核对的意义。
在电脑上验一遍(lib/*.js 改了必须重启一次 DSH,面板的 HMR 管不到服务端):
# 1. 重启 DSH 后,打开面板 → 小盒子 → 「打一份小盒子」
# 2. 没有红灯、出现「已放进下载文件夹:C:\Users\<你>\Downloads\留痕-YYYY-MM-DD.zip」即通过
# 3. 解压那个 zip,看中文名是否正常、00-读我.txt 第 20 行左右有没有「去向:」
# 4. 自检(可选,Windows 上也能跑):node scripts/selfcheck.js → 82/82
0.1.2(小更新,不是第二版)
- 电脑分支:打包与列清单不再依赖系统的
zip/unzip命令(Windows 上两者都没有), 改成lib/zip.js自己读写;lib/platform.js管共享目录与文案 - 打包结果可复现:同一天同样的数据两次打包 sha256 一致
- 包里补回目录条目(含空目录),解出来的结构跟打进去的一致
/summary多带一个where字段(os/kind/dir/label/word), 面板据此说「手机」还是「下载文件夹」- 自检 76 → 82 条:新增跨平台 4 条(手机路径、电脑路径、面板文案、zip 中文名往返)
0.1.1(小更新,不是第二版)
- 面板每 30 秒自动刷新,不用关掉重开
- 注入记账:
liuhen/inject-state.json+ 面板显示上一轮到底注入了没有 - 「我是谁」第一次见面由助手自己写(新工具
trace_intro),面板补了名字输入框, 正文不再只认以-开头的行,写好了也能再「编辑」 - 自检脚本修掉两处写死日期的假失败
许可
MIT