dsh-second-brain(第二大脑载入器)
English README · 中文说明
> 让 DeepSeek Harness 每次开新会话时,自动带着你的第二大脑画像与当前状态。
> 只读 · 零写入 · 有硬上限 · 零依赖。
> 标签:记忆 · 工作流 · 本地优先 · 隐私优先 · DSH 插件。
@xianshu/dsh-second-brain 是一个 DeepSeek Harness(DSH)宿主插件。它在每一次会话装配提示词时,
把一个有硬上限、带时间戳的第二大脑快照(身份 + 状态指纹 + 未决项计数 + 指针与边界)注入进去。
一句话:新会话不该从零开始——它开局就该知道「本实例是谁」,以及「真状态在哪」。
【第二大脑 · 弦枢 · 开局注入块】(只读快照,非现况;勿回写本块)
脑根:C:\Users\you\.dsh\brain
指纹:version=v0.1.0 state_seq=120 git_backed=true last_export=2026-10-06T20:51:29+08:00
永久记忆 @2026-10-06T10:17:54.099Z
未决项:25 条
## 一、我是谁
- **名**:…(身份、岗位、脑根、代际指针)
指针:完整状态跑 `sb.cmd look`;未决项见 ledger.md;失败模式见 failures.md。
边界:本块为快照。若与现读文件冲突,以现读为准。
(以上为作者实例的真实产出,仅作格式示例;弦枢 是作者 DSH 实例的代号,脑根路径已改为通用写法。)
它解决什么问题
不同 agent 平台的「跨会话记忆」供给并不一样:
| 平台 | 跨会话记忆 |
|---|---|
| 部分 AI 工作台 / IDE | 平台自带记忆目录,切换对话无缝 |
| DeepSeek Harness | 没有该机制 —— 每个新会话开局都是一张白纸 |
于是你精心维护的第二大脑在磁盘上只是一个孤立仓库:只有"谁记得去读它"才有用。
本插件补的正是这一环,而且补在唯一每次都会跑的地方——提示词装配。
★ 顺带一个设计立场:每个实例的记忆本就该不同。本插件注入的是「你自己的」画像,
不是一份人人相同的公共文本——若各实例记忆相同,则毋须多实例。
它做什么
- 每个新会话都注入。 挂点:
ctx.systemPrompt.context({ name, order, text }),
宿主将该贡献物化为 durable user-role snapshot。 - 永远新鲜。
text取函数形态 ⇒ 每次装配现读脑状态;state_seq变了,下一次装配就能看到。 - 有硬上限。
maxChars是硬顶,注入块不可能无界膨胀进你的上下文窗口
(代码默认 1000;随包 patch 装的是 1300)。 - Fail-loud。 上限低于
300(页眉+页脚都装不下)时,插件拒绝注册并打印理由,
而不是静默丢掉「指针」或「以现读为准」边界行。 - 只读、零写入。 全程
readFileSync,永不写脑。 - 零依赖。 纯 ESM,Node ≥ 18,无构建步骤、无 postinstall 脚本。
安装
四条路,按前置条件从少到多排列——第一条既不需要 git,也不需要 github.com。
| 路线 | 怎么做 | 需要什么 |
|---|---|---|
| A · npm(推荐) | 设置 → 插件 → 添加插件 → @xianshu/dsh-second-brain |
能连上 npm registry —— 不需 git、不需 github.com |
| B · 目录 | 下载 Release 的 .zip → 解压 → 添加插件填解压后的文件夹路径 |
只需能下载这个 zip |
| C · 本地克隆 | git clone 本仓 → 添加插件时填克隆出的文件夹路径 |
git |
| D · GitHub 源 | 添加插件时填 github:DiaryOfUranus/dsh-second-brain |
git 在 PATH 里,且 github.com:443 与 codeload.github.com 可通 |
★ 装完须重启 DSH——插件模块在 boot 时加载;宿主运行中改文件不会热重载(实测)。
入口是走通的(实测,不是宣称)
路线 A 在一台 git 不在 PATH、且 github.com:443 不通的 Windows 主机上端到端走通——
也就是当初旧入口失败的那台机器:
$ pnpm add @xianshu/dsh-second-brain # npm 官方源
+ @xianshu/dsh-second-brain 0.1.5 ✅
$ pnpm add @xianshu/dsh-second-brain # npmmirror 淘宝源也供得上
+ @xianshu/dsh-second-brain 0.1.5 ✅
$ node -e "import('@xianshu/dsh-second-brain')"
name=second-brain-xianshu inject=["systemPrompt"] ✅
$ node node_modules/@xianshu/dsh-second-brain/test/probe-block.mjs
结论: 48/48 PASS ✅
路线 B 另测:pnpm link:<解压目录> 能正确解析包名、cordis.patch.yml 在、按包名导入并对真脑
构建出 844 字符的注入块。
为什么 D 排在最后(实测,不是推测)
github: 这种写法由包管理器解析,而它会去调 git:
$ pnpm add github:DiaryOfUranus/dsh-second-brain
[ERROR] Command failed: git ls-remote "https://github.com/DiaryOfUranus/dsh-second-brain.git" HEAD
'git' 不是内部或外部命令,也不是可运行的程序或批处理文件
Windows 实测(2026-10-06):git 不在 PATH 时立刻失败;把 git 加回 PATH 后仍失败于
Failed to connect to github.com:443 after 21075 ms。固定完整 commit SHA 也绕不开——pnpm 对
github: 一律走 git fetcher。而 A、B 两条路完全不碰这些。
> 更正说明:v0.1.4 的 Release 说明、以及 v0.1.4 附件包内的 README,曾推荐裸 github: 写法且
> 未写明前置条件。以本节为准。
bundle 契约
无论走哪条路,bundle 都由 package.json → dsh.bundle.patch → cordis.patch.yml 声明,插入一行:
- insert:
- id: second-brain-xianshu
name: '@xianshu/dsh-second-brain'
config:
brainRoot: !!js process.env.DEEPSEEK_BRAIN
maxChars: 1300
order: 200
验证是否生效(两路,任选)
- 开一个新会话,问它:「你开局收到什么第二大脑信息?」——答得出即为注入生效。
- 或看 DSH 日志是否有:
[second-brain-xianshu] ✅ 注入已注册:name=xianshu-second-brain order=200 块长=NNN 字符
配置项
| 键 | 默认 | 含义 |
|---|---|---|
brainRoot |
~/.dsh/brain(或 $DEEPSEEK_BRAIN) |
脑根目录 |
maxChars |
1000(随包 patch 为 1300) |
注入块硬上限;下限 300 |
order |
200 |
在系统提示词中的层序 |
inject |
开 | 置 false(或环境变量 DSH_SB_INJECT=0)可关而不卸 |
装 = 开。 v0.1.0 曾默认关,实测已证本末倒置:GUI 的安装动作本身即为 consent;
「装了却默认不生效」属多此一举。要关,必须显式关。
它读哪些文件(只读)
<脑根>/VERSION.json → version、state_seq、git_backed、last_export_at(指纹)
<脑根>/MEMORY-PERMANENT.md → 取「一、我是谁」「三、我怎么干活」两节,按条目边界裁剪
<脑根>/ledger.md → 只数 `- [ ]` 条数,不读正文(控体积)
文件缺失则优雅降级:块里写明"未找到",而不是抛异常。
安全姿态(三重)
三条明确保证,默认全部取最紧:
- 有界——
maxChars硬顶。注入块会跟着每一次请求走,无界注入就是一个迟早爆的上下文 bug。 - 只读——只读打开,永不写脑;插件不碰会话生命周期(不 inject
agents/sessions)。 - 诚实——块自己声明"这是快照,非现况",自带 mtime 与
state_seq供新会话判断新鲜度,
并明写"若与现读文件冲突,以现读为准"。
另有一道自指腐化防线:注入块不得被脑读回当作事实来源。一个系统若把自己的产出当外部输入,
就会腐烂;时间戳与边界行就是解药。
事故留痕(v0.1.0 → v0.1.1,实测)
症状:作者装好并重启后开新会话 ⇒ 开局无任何第二大脑内容。
诊断(实测):DSH_SB_INJECT 在 shell/用户级注册表三处皆为空 ⇒ inject 恒 false
⇒ 插件按设计拒绝注入;且桌面版进程不由 shell 派生,由插件自己设其环境变量这条路实际不可达。
根因(设计之误):把"装不装"(作者在 GUI 已决定)与"装了是否生效"混成一道开关。
修法:装 = 开,关须显式。并补两处:
① 删掉 ctx.effect?.(() => dispose)——context() 自身返回 disposer 且框架已按调用上下文自动注销,
旧写法既冗余、又因 ctx.effect 不存在而静默无效;
② 注册成功时打印块长,让"是否生效"一眼可判,不靠猜。
三态实测:①默认 ⇒ 注册 ✅ ②inject:false ⇒ 不注册 ✅ ③maxChars:120 ⇒ REFUSED ✅。
可复算验收 —— 自己跑一遍
node test/probe-block.mjs
探针在临时目录里自建一个合成脑(fixture),断言任何上限下都必须成立的不变式:
块长 ≤ 上限、指针行与边界行存活、身份与指纹在场、脑根不存在时降级不抛、
maxChars < 300 必须大声拒绝。不需要任何个人数据。
想直接探你自己的真脑:
SB_BRAIN="$HOME/.dsh/brain" node test/probe-block.mjs
兼容性
- 宿主:DeepSeek Harness 桌面版(宿主侧插件,无客户端/UI 代码)。
- 运行时:Node ≥ 18,ESM。零依赖、无构建、无 postinstall。
- 用到的契约:
ctx.systemPrompt.context({ name, order, text })与ctx.logger。
已知边界(如实列)
- 指针行里的
sb.cmd look是作者本机脑 CLI 的名字,对别人只是惰性文本;
把指针做成可配置项是计划,不是已发版的能力。 - 压缩按精确的中文标题取两节(
一、我是谁、三、我怎么干活);两节都没找到时(例如脑文件用
其他语言写),退化为整文件按条目边界裁剪。可配置的节名列表在计划中。 - 注入块自身的标签是中文(
脑根/指纹/边界…);插件与你的语言无关,但其他语种的标签映射
尚未发布。 - 多实例并发未压测(本插件是纯函数、无共享状态,理论上无碍,但未实测)。
- 仅在 DSH 0.2.x 宿主线上验证过;其他版本请先确认
ctx.systemPrompt.context仍存在。
变更记录
v0.1.4 是首次公开发布。发布前的验收探针逮出两条"静默丢内容"缺陷,均已修复并
带回回归用例:
- 目标节恰是文件最后一节时被静默丢弃——旧版尾锚写作
\Z,而 JS 正则里\Z不是"串尾",
而是字面量Z; - 脑根路径极长遇上很紧的上限时,会把「指针」与「以现读为准」边界行切掉。
相关仓库
- second-brain-framework —— 开源第二大脑
框架与治理工具集,负责造出本插件要加载的那些脑文件。
框架 = 脑的结构;本插件 = 载入器。
许可
MIT © 天王星日记 / DiaryOfUranus —— 见 LICENSE。