- Inicio
- Plugins
- Sesiones y mensajes
- dsh-whale-post (bus)
dsh-whale-post (bus)
deepsleepaquarium/dsh-whale-post/packages/bus
Correo entre sesiones de DeepSeek Harness basado en archivos: cada carta se sella con HMAC y una huella criptográfica del cuerpo, y los destinatarios se resuelven mediante una interfaz de registro. Funciona primero sin conexión, por lo que una carta no entregada espera en el buzón en lugar de perderse.
Instalar
dsh plugin --profile web add github:deepsleepaquarium/dsh-whale-postEste plugin se encuentra en el subdirectorio packages/bus del repositorio.
README
邮局 · whale-post
English: README.en.md
一句话:给同一台机器上的多个 AI 会话(或多台引擎)一个"异步信箱" —— 信按文件落盘、默认不叫醒对方、不会丢、不会刷屏。
它解决什么问题
- 会话之间不能互相说话:一个引擎里跑着好几个会话(网页端一个、机器人端一个、还有按需起来的小助手),彼此看不见对方在说什么 ⇒ 邮局让它们留信。
- "叫人"很贵:想通知对方就得把对方的会话叫醒 ⇒ 对方要为这一句付一次满上下文推理(最贵的浪费)⇒ 所以默认离线:信落进对方信箱,等人自己来读。
- 来回对发停不下来:两个 AI 客气起来能对发到天亮 ⇒ 回环闸(同一对 N 分钟内限封数/链深限跳/纯回执拒发)+配额闸(多发一封=多烧一份钱)。
用了以后什么效果
- 一句话原则:离线=主力;在线=应急储备 —— 离线配额大、不占其它桶、不会一下堆满对方的会话窗口、离线用完了还有在线兜底;在线要攒着(在线的先打光,真急事就只能"咬牙掏钱"发加急 —— 越额按费率计费(费率可配置))。
- 信只会晚到,不会不到:收件人没有活体会话 ⇒ "不投也不消费" ⇒ 信原样留在信箱里,对方下次开工一拉就全到(这条在实际使用中验证过)。
- 跨引擎:谁跑在哪个引擎上、哪个模型上,都无所谓 —— 信箱是盘上的目录。
- 不刷屏,也不会没人看:两档判据 —— 默认离线;正在来回协作 ⇒ 在线优先;非急件攒到 ≈3 封 ⇒ "离 3 在 1"(≈3 封离线 ∶ 1 封在线 —— 那一封在线的用处是"来收信"的铃:离线信箱不会丢信,但会被忙人忘掉);出事/停摆/要对方当刻动手 ⇒ 一律在线、不受比例约束。详见
docs/FOR-AGENTS.md。 - 省钱:配额按"单位"算,越额就当场拒发并给出非零退出码 —— 不悄悄降级。
- 换得掉:名单、类型表、投递策略、闸,全是插件接口 ⇒ 你可以只换掉其中一件(比如把名单从 JSON 换成数据库)。
快速开始
最快的一次试跑(不用 clone、不用 npm install —— 就这四步)
先起一个干净的临时邮局(不碰你机器上的任何东西),再让它跑起来:
# 0) 先备名单 —— 不备的话,下面 send 会报"未知收件人"
# (离线件不必握手 —— 它本来就在"落在信箱里等人来收";【在线】件要握手 )
# (另外:【组名】要名单里有定义,【人名】要已在名单里 —— 这条对离线件也管 )
mkdir whale-mail && cd whale-mail
printf '%s' '{"apiVersion":1,"members":[{"id":"alice"},{"id":"bob"}],"groups":{"all":["alice","bob"]}}' > roster.json
# 1) 握手(在线件没握过手会拒发;离线件不看握手 )
npx -y dsh-whale-post-cli@0.6.1 hello --as alice --root .
npx -y dsh-whale-post-cli@0.6.1 hello --as bob --root .
# 2) 发一封(默认离线 ⇒ 信落在对方信箱里,不叫醒任何人 )
npx -y dsh-whale-post-cli@0.6.1 send --as alice --to bob --subject 'hi' --body 'first letter' --root .
# 3) 收信(投出去/留下来,都由这一句决定 )
npx -y dsh-whale-post-cli@0.6.1 pump --as bob --root .
跑完你会看到(下面是真跑出来的输出):
已投递 …-alice-0001-… → bob(seq 1)【离线(落在对方信箱,不唤醒)】
投递策略:kept(留在信箱里等人来收)
配额(offline 桶):今日 1/80 条
OK …-alice-0001-….msg.json :: [离线] alice → bob:《hi》
| first letter
--root . 指的是信箱根=当前目录 —— inbox//seen//ack//hello/ 都在里面。
判据看退出码:0 过 / 2 拒发 / 1 没料到的错。
在仓内开发(要改源码就走这条)
dsh plugin --profile <profile> add link:/abs/path/to/dsh-whale-post
npm install # 仓内要先装一次(把六个插件链进 node_modules;否则 CLI 找不到兄弟件)
node packages/cli/index.js selftest # 看退出码
# 其余命令与上面 npx 那几行完全一样,把 `npx -y dsh-whale-post-cli@0.6.1` 换成
# `node packages/cli/index.js` 即可(记得同样先备 roster.json )
装法、接线、接口表、配置项表、写插件规范 ⇒ 见 docs/INSTALL.md;
给 AI 体看的用法纪律 ⇒ 见 docs/FOR-AGENTS.md。
现状
主体(基础版)= bus + roster + types + cli
这四件合起来就是一个能用的邮局 —— 留信、收信、认人、认类型都齐:
| 件 | 它管什么 | 详细说明 |
|---|---|---|
dsh-whale-post-bus | 核心:信封/摘要+HMAC 签名/握手/幂等/落盘 | packages/bus/README.md |
dsh-whale-post-roster | 谁在名单里(含成员属性) | packages/roster/README.md |
dsh-whale-post-types | 信是什么类型 | packages/types/README.md |
dsh-whale-post-cli | 命令行(不是插件) | packages/cli/README.md |
其余都是插件(可换、可加、可不要)
它们各自的说明写在各自的 README 里 —— 主体这一页不重复讲:
| 插件 | 它加什么 | 详细说明 |
|---|---|---|
dsh-whale-post-deliver | 投递策略:离线留着等人/在线投出去;接真引擎的探针在这里 | packages/deliver/README.md |
dsh-whale-post-gate | 闸:配额与计费 + 回环闸 | packages/gate/README.md |
dsh-whale-post-verify | 安全校验:验签 + 白名单(默认禁用) | packages/verify/README.md |
在 DSH 插件商店里的状态 ⇒ docs/SHOP.md(在 —— 而且是自动的;只是缺 cli/verify 且停在 0.1.x)。
接手继续做 ⇒ docs/HANDOFF.md(现在什么状态 + 下一步做什么 + 先读哪几篇)。
怎么发一个新版本 ⇒ docs/RELEASE.md(步骤 + 为什么 —— 发布是不可逆的,宁慢勿错)。
怎么把它们接起来 ⇒ docs/INSTALL.md;组合示例 ⇒ example/。
别的
- 一把跑完自测:
node scripts/selftest-all.mjs—— 退出码 0 = 七件全过 + 跨包一致(条数由它自己打出来,不写死)。 - 并发抢号:已测(2026-10-10)——
node scripts/racetest.mjs:12 路真子进程同时send⇒ 退出码全 0 + 每个seq全唯一;它还会重放"state被写倒退"(把nextSeq写回 1 ⇒ 新信仍拿新号)。 它还测了并发记账(2026-10-10 加,而这条抓出过一个真 bug): 12 路真子进程各往同一个配额台账里记一笔 ⇒ 正好 12 条,一条不丢 —— 台账原来是"读 → 改 → 写回" ⇒ 12 路只活下来 8/9/10 条(而配额台账是钱,且它没有任何兜底); 现在每笔记一个增量文件("各写各的" —— 设计文档给ack用的就是这一手)⇒ 一条都不许丢。共 11 条判据。 那条"截断路径"已经补成判据了(2026-10-10):seen状态数组会被slice(-2000)截断 —— 而判"读过没有"有两道保险:state.seen数组(会被截)+seen/<我>/<id>.msg.json那个文件(永不被截)。 判据造的是最狠的现场:把状态数组截空、把同一封信放回信箱 ⇒ 必须仍判重复; 而负向证明:只去掉existsSync那一路 ⇒ 判据立刻红。 - 跨包一致性(2026-10-10 加):
node scripts/xcheck.mjs—— 六项(摘要/签名域/MAC/老字段/日界/"名字说真话"); 它盯的是**"同一件事在两件里各算一份、结果还相等吗"**(我们在这形状上栽过两次)。 - 每件都过三关:能加载 + 能跑 + 跑错会红(光跑自测不算,必须真启一遍 ⇒ 验收规格见
docs/ACCEPTANCE.md)。 - 版本口径:
0.6.1已发上 npm(上面那几行npx装的就是它,已按docs/RELEASE.md第 2 步真装验收过)。 ⓘ npm 的 registry 有几分钟同步延迟 ⇒ 刚发完那一会儿可能还装不到@0.6.1—— 装不到就先用@0.3.0(它也在 npm 上、也真能跑)。 - 要钉哪个 tag:钉
v0.6.1(0.1.x装进真引擎会六个插件全部加载不上); 接口带apiVersion,类型可以随时扩充(加类型不用动核心)。逐版改了什么、为什么 ⇒ 见CHANGELOG.md。 - 装法已在真引擎上实测过 —— 而那次实测抓到一个致命 bug(已修):
六件全部
failed to apply(apply()里读了ctx.whale属性,而真 Cordis 里读它要先inject); 而--dump-config完全看不出来(它只组配置树、不跑apply())。 ⇒ 现在只ctx.provide(...)+ 运行时ctx.get(...),并钉了一条静态判据。细节与坑 ⇒docs/INSTALL.md§六。
它不是什么
- 不是聊天室:没有实时推送、没有已读回执焦虑(异步信箱)。
- 不是 RPC:不保证对方立刻处理(保证的是信不丢)。
- 不是分布式队列:它假设同一台机器(同一份盘);跨机器要靠共享目录。
和引擎自带的"子代理/团队"是什么关系(不是竞品)
很多引擎已经能派子代理(或"团队功能")⇒ 常见一问是「那还要你这个干嘛」。答:
| 引擎自带的子代理/团队 | 本仓(邮局) | |
|---|---|---|
| 管什么 | 此刻的并行(同一进程树里派出去、同步等结果、用完即弃) | 此刻不在一起时的传递 |
| 范围 | 同一个引擎 | 跨引擎/跨设备/跨会话 |
| 身份 | 无(都是主会话的分身) | 有 —— 钥匙 + 名单;每设备一把,冒名验不过 |
| 留痕 | 不落盘(这一轮结束就没了) | 信落盘,seen/ 永久留档 |
| 同步性 | 同步等待 | 异步 —— "只会晚到,不会不到" |
| 代价 | 烧同一个账号的额度 | 配额制 + 默认离线 ⇒ 省粮;离线件不占别的桶 |
一句话:子代理是"你的手",邮局是"我们之间的路"。 判据一句:"我现在就要它做" ⇒ 用子代理;"它现在可能不在" ⇒ 用邮局。
和同类项目比,它特别在哪
同类的东西已经有不少。写这个仓库之前我们查过一圈(2026-10-10),最近的几个:
| 项目 | 它是什么 |
|---|---|
avivsinai/agent-message-queue | 文件式的本地 agent 间消息队列,Maildir 风格,Go 写的 |
@yuanchilin/dsh-mailbox | DSH 的跨会话文件信箱,走共享文件系统,带 seen 去重和 TTL 清理 |
polaris-smart/dsh-agent-mailbox | DSH 的跨 agent 信箱插件,桥接 agent-mailbox |
它们解决的是同一类问题:让几个 agent 能互相留话。我们多做了三件事:
- 不该叫醒的不叫醒。 默认离线,信落盘;叫醒对方等于让对方付一次满上下文推理,那是最贵的浪费。 除了"默认离线",还有三处会各自把一封在线信压成"按离线寄达"并明说:名册把某人钉成只收离线、 对方自己声明了只收离线、或者此刻正在它声明的勿扰时段里。
- 叫多了会被闸住。 回环闸管住"同一对在 N 分钟内发太多""转发链太深""纯回执来回发"; 配额闸管住"今天发超了"。越额当场拒发、给非零退出码,不静默降级—— 悄悄降级比拒发危险得多,因为它让人以为信已经发出去了。
- 送不到也不假装送到了。 收件人此刻没有读者,就不投也不消费,信原样留在信箱里, 对方下次开工一拉就全到。一句话:信只会晚到,不会不到。
另外两件是我们顺手做的:身份与验签(HMAC 签名 + 名册白名单,默认关,开了才验), 以及跨设备(投到远端信箱、取回来、回执也镜像回来)。
该说的短处也说清楚:agent-message-queue 的生态比我们大得多,也支持更多引擎;
@yuanchilin/dsh-mailbox 有一个 /mailbox 交互界面,我们只有命令行。
我们的星少、也没进任何官方目录(@deepseek-ai 那个 scope 下是官方组件,我们不在其中)。
如果你只想要"能发信",用哪个都行;如果你在意"别把对方的会话烧醒、别把额度刷爆、别丢信",
那这三件是我们和它们最大的差别。
三条设计取舍(都写明了为什么)
| 取舍 | 为什么 |
|---|---|
| 默认离线 | 叫醒对方=让对方付一次满上下文推理;默认省下它 |
| 只投活体,不活就"不投也不消费" | 怕丢信 ⇒ 宁可信晚到(信留信箱,人来了再给) |
| 拒发就是拒发(不静默降级) | 悄悄降级=让人以为发出去了 ⇒ 最危险(我们踩过"急件写成 ONLINE 就永远叫不醒人") |
目录
packages/bus/ packages/roster/ packages/types/
packages/deliver/ packages/gate/ packages/verify/ packages/cli/
example/ docs/ CHANGELOG.md
许可:MIT。本仓为独立实现(未使用任何无许可代码)。
关于这个账号
讨论和修改都留在提交记录和 issue 里。
我们拿它做各种东西,whale-post 是其中做得最久的一个:一开始只是想让几个跑在同一台机器上的程序
能互相留个话,后来慢慢长成了一套完整的东西。有问题欢迎开 issue,我们看到会回。
Plugins relacionados
dsh-web-ui (dsh-chat-recovery)
zhu1090093659/dsh-web-ui
billion-context
ranxianglei/billion-context
dsh-synapse
liangmianya/dsh-synapse
dsh-chat-import
nwflower/dsh-chat-import