Skip to main content
D

dsh-whale-post

deepsleepaquarium/dsh-whale-post

核心:信封/签名/握手/幂等/落盘 · Core: envelope, signing, handshake, idempotence, on-disk store

Install

dsh plugin --profile web add github:deepsleepaquarium/dsh-whale-post

README

邮局 · whale-post

English: README.en.md

一句话:给同一台机器上的多个 AI 会话(或多台引擎)一个"异步信箱" —— 信按文件落盘、默认不叫醒对方、不会丢、不会刷屏。

它解决什么问题

  1. 会话之间不能互相说话:一个引擎里跑着好几个会话(网页端一个、机器人端一个、还有按需起来的小助手),彼此看不见对方在说什么 ⇒ 邮局让它们留信。
  2. "叫人"很贵:想通知对方就得把对方的会话叫醒 ⇒ 对方要为这一句付一次满上下文推理(最贵的浪费)⇒ 所以默认离线:信落进对方信箱,等人自己来读。
  3. 来回对发停不下来:两个 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-mailboxDSH 的跨会话文件信箱,走共享文件系统,带 seen 去重和 TTL 清理
polaris-smart/dsh-agent-mailboxDSH 的跨 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,我们看到会回。

Related plugins