首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >有钱人才敢用的DeepSeek Harness 插件:dsh-i-am-rich

有钱人才敢用的DeepSeek Harness 插件:dsh-i-am-rich

作者头像
深蓝studyzy
发布于 2026-10-11 09:54:07
发布于 2026-10-11 09:54:07
1050
举报
文章被收录于专栏:深蓝居深蓝居

一、段子的原样复刻

这个插件的灵感,来自那个关于「有钱」的经典段子:

等咱有了钱,喝豆浆吃油条。豆浆买两碗,喝一碗,倒一碗!油条买两根,吃一根,扔一根!

我认为这个段子的笑点从来不在「有钱」,而在浪费被摆到明面上——买两碗就是为了倒一碗,倒掉的那碗才是主角。这个插件做的事情,就是把段子逐句翻译成 LLM 调用:

段子

插件

豆浆买两碗

每次模型请求真的发两份

喝一碗

第一份正常返回给 agent loop,是你真正在用的回复

倒一碗

第二份完整收完,然后直接扔掉

想蘸白糖蘸白糖

discardedCopies 想扔几份扔几份

——

侧边栏状态条如实显示今日 / 本月 / 累计倒掉了多少

不过这里有两处刻意的坚持,我想特别说明一下,因为它们决定了这个项目到底是个玩具还是个作品:

  1. 倒掉的那碗是真的倒了。 第二份请求真的通过网络发出、真的被 provider 计费、内容真的被丢弃。不模拟、不估算、不假装——段子的笑点建立在「真花了钱」之上,插件也必须是真花钱。
  2. 倒掉的那碗要数清楚。 段子里没人统计倒了多少,这个插件偏要统计,而且只用 provider 自己报告的 usage,一个 token 都不编。

一句话概括这个项目的设计纲领:行为是段子,账本是账本。 花两倍的钱是玩笑,把这两倍的钱如实记下来不是。


二、它长什么样

装好之后,你的侧边栏左下角、用户名正上方,会多出一行:

代码语言:javascript
复制
💰 今日浪费 2249万Token

鼠标移上去,展开成三行:

代码语言:javascript
复制
💰 今日浪费 2249万Token
💰 本月浪费 2249万Token
💰 累计浪费 8400万Token
Clipboard_Screenshot_1791623749
Clipboard_Screenshot_1791623749

关于显示,有两个细节值得一提:

  • 数字按中文的数量级习惯缩放(万/亿),英文环境则自动切换成 K/M/B。悬停的 tooltip 里永远有带千分位的精确整数——缩放只是呈现选择,账本才是记录。
  • 图标用 💰 不用 🪙。 那枚「硬币」在 Apple 字体里偏银色,看上去像代币;钱袋的金黄色才对得上主题。

不想摆阔了?配置里一行 enabled: false,今天豆浆只买一碗:插件还在加载,状态条还在,但不再花钱。


三、千万富翁与亿万富翁:倒豆浆有两种倒法

同样是倒掉一碗,倒法有讲究。插件的 fortune 配置有两档,区别只有一个:第二份请求的提示词前缀一不一样——也就是它能不能蹭到 provider 的提示词缓存。

档位

第二份请求

缓存

计费

千万富翁

与原请求完全相同

通常命中

按缓存读取价(折扣价)

亿万富翁

system prompt 开头多一行当前时间戳

必然不命中

按全价(缓存写入)

原理是这样的:provider 的提示词缓存按前缀匹配。两份请求前缀逐字相同时,第二份直接复用第一份写好的缓存条目,走折扣价;只要最前面那段文字不同,整条前缀就对不上,第二份按全价重新计费。时间戳天然满足「每次都不同」,所以两份重复请求之间也蹭不到彼此的缓存——这就是亿万富翁更烧钱的全部机制,实现上只是给副本的 system 消息头部加一行 [i-am-rich] <ISO 时间戳>。

Clipboard_Screenshot_1791624091
Clipboard_Screenshot_1791624091

【注意】档位在状态条展开面板顶部选择,写入 profile 配置(带文件锁、校验与失败回滚),重启后仍生效;写入失败时单选框停在实际生效的那一档——显示与真实行为不一致,正是这个插件要防的事。


四、账本只记真金白银,状态条只数全价 token

账本和状态条是两件事,这一点最近被明确地分开了。

账本如实落盘四个桶:新输入、输出、缓存读取、缓存写入——provider 报什么记什么,一个不少。

状态条只统计两个数字:缓存未命中的输入 + 生成的输出。 原因很直白:缓存命中部分按折扣价计费,往往比全价低一个数量级——千万富翁档的副本每个 token 几乎不花钱;缓存写入则是输入前缀本身入仓,不是副本新「说」出来的东西。把这两类算进「浪费」,会虚捧数字而不代表真实的挥霍。

这里有一个关键点:倒豆浆的账要记全,但摆出来炫耀的,得是按全价买单的那部分。


五、认真聊聊架构

如果这是个只会烧钱的玩具,博客到这里就该结束了。但我一直认为,这个插件真正值得看的,是它如何用做支付系统的态度做一个玩笑。它是一个「双面插件」,一个包编译出两个产物,由两个世界分别加载。接下来,我们来看看它的具体实现。

5.1 Host 半边(Node):在水瀑布上放一道双保险

插件挂载在 DSH 的 llm/stream waterfall 上。每次请求经过时,它调用 next() 两次:一次是真实请求,照常返回给 agent loop;其余的每份交给 burn()——把流完整 drain 到最后一个 chunk,只留下 provider 报告的用量,内容全部丢弃。

亿万富翁档是个例外:副本必须带着被改过的前缀出发,next() 不接受参数(它只会重放闭包里的那一个请求),所以副本改走 ctx.llm.stream() 重新派发,并用一张 WeakSet 按对象身份让「自己派发的那份」直接穿透,否则会无限递归。

几个值得说的细节:

  • 重复请求是并发的真请求,不是串行的复读。它和原请求同时在途,占用真实的并发额度——这就是「倒掉的那碗」。
  • 重复流中途死了也算钱。 失败前 provider 已经计费的用量会被如实记下,outcome 标为 failed。诚实账本的原则是:钱花了就记,不管这碗豆浆倒没倒干净。
  • provider 没报 usage 的调用单独计为「未报告用量的调用」,绝不冒充 Token 数。
  • 副本必须克隆,绝不改原请求。 loop 构造的请求是 deep-freeze 的,原地改会直接抛异常,而且会污染真实那一轮正在用的请求——克隆后原请求 bit-for-bit 不变,有测试断言。

5.2 账本:独立目录,按月 JSONL,仅追加

浪费记录写在 ~/.dsh/i-am-rich/waste-YYYY-MM.jsonl,每月一个文件,一行一次丢弃:

代码语言:javascript
复制
{"v":1,"wasteId":"…","provider":"deepseek","model":"…","outcome":"discarded","day":"2026-10-10","usage":{"inputTokens":100,"outputTokens":20}}

刻意不写进 dsh 的会话日志——段子归段子,账本不该混进别人的日志里。

崩溃安全交给文件系统:单行 O_APPEND 在本地文件系统上实际原子,最坏留下末尾半行;读取端跳过解析失败的行,一个月里的一个坏行不会吞掉其余的账。账本按单实例设计,不做跨进程加锁——诚实地承认边界,而不是假装解决了不存在的问题。

5.3 纯函数内核:src/waste.ts

所有算术——按天折叠、三个口径求和、万/亿 vs K/M/B 的量级缩放——都在一个零依赖的纯函数模块里。不需要 Host,不需要 cordis,测试就是普通函数调用。

5.4 时钟的正确归属:一个被认真对待的哲学问题

「今天」和「本月」取决于谁在什么时候问。如果把区间选择做在 Host 的持久化投影里,重放(replay)时算出的「今天」就会漂移。

所以架构是:Host 只发布按天的账本(无时钟的 fold),拥有时钟的客户端负责选取区间。 持久化的计算因此严格可复现,而日历区间依然正确。跨月、跨年、非法日期键的边界都有测试锁死——2025-12-31 不会计入本月,去年同月同日不算「今日」,格式非法的日期只计入「累计」。

5.5 Client 半边(浏览器):CJS 包进 ModuleLoader

lib/client.js 以 CJS 形式包裹在 window.__ModuleLoader__.load({ id, factory }) 里——浏览器内核物化工厂函数,不执行 ESM。状态条组件注册进 sidebar.footer.action 槽位(由 ui-sidebar 声明),落在账号按钮正上方,字号、内边距、配色逐条对齐用户名的样式——它是用户名的同级控件,不是注脚。

组件只用 inline styles 不用 CSS 文件,因为 tsc 不会把 .css 拷进产物。数据不经过会话 store:挂载即拉取一次账本,之后每 15 秒轮询,标签页重新可见时补一次。轮询失败时保留最后一次成功的数据并在 tooltip 里注明「账本暂不可用」——冻结的数字必须让人看出来是冻结的,绝不静默清零。

这里还有一个反直觉但很对的决策:状态条从挂载那一刻就显示,没有记录时显示 0。 因为一个什么都不渲染的侧边栏条目,和一个加载失败的插件在界面上完全一样——「没有记录就不渲染」会让你永远分不清「已正确挂载」和「没挂上」。


六、一个不严肃插件里的严肃事故史

这个项目的注释和测试里,记录着四个真实踩过的坑,每一个都值得写进任何插件系统的文档。我把它们分享出来,希望能帮到同样在写 DSH 插件的朋友。

坑一:inject 没声明,状态条永远显示 0。 cordis 在已激活的插件上读取未声明 inject 的服务会抛异常而不是返回 undefined。当时的代码用 try/catch 把这个异常当成「宿主没有 Web 客户端」吞掉了——于是 /api 路由根本没注册,可账本文件却被正常写入。两种情况的界面表现完全一样,这个 bug 静默了很久。修复方式是把 connection 声明进 inject:读取合法,且 cordis 会等服务就绪才调用 apply,顺带消除了启动时序竞争。现在有一个测试用真实的 cordis fiber 复现那条异常。

坑二:槽位名写错,插件「装了但看不见」。 注册到一个没有任何 bundle 声明的槽位,slots.inject 既不报错也不渲染——和加载失败完全无法区分。槽位名最终是从 ui-sidebar 自己的声明表里逐字抄来的。

坑三:最关键的测试数的是 adapter 调用次数。 invokes the underlying adapter twice 这条测试数的是 adapter 被实际调用的次数——只有这个断言能证明真的发出了第二份请求,测下游监听器数量是证明不了的。这是整个测试套件的定海神针。

坑四:测试的绿灯是「结构性」的。 亿万富翁档在真实 harness 里崩溃,本地测试却全绿——因为所有用例都在裸 new Context() 上手工赋值 ctx.llm,而裸 context 不是代理,读取既不抛异常、也不进服务注册表,恰好把两条真实路径(fiber proxy 的抛错语义、注册表解析)都结构性错过了。修复后补的测试把 apply 跑进真实的 cordis fiber、让 llm 从注册表 provide——用例的形状必须贴着运行时的形状,绿了才算数。


七、谁该装这个插件?

诚实地说:没有人「需要」它。 它不省钱、不省时、不提升任何指标。

但如果你符合以下任何一条,它会让你微笑:

  • 你想找一个真实、可跑、非 toy 的 DSH 插件范例——waterfall hook、双产物构建、槽位注入、/api 路由、按月 JSONL 账本、纯函数内核 + 全边界测试,一整套插件开发的全部要素都在这一个包里,而且每个 why 都写在注释里;
  • 你在研究「如何认真地做账」——无时钟投影、provider 自报用量、崩溃半行容错、冻结可见,这些原则放到任何计费场景都成立;
  • 或者,你只是想每天看着侧边栏上那行「💰 今日浪费 2249万Token」,体会一下倒豆浆的快乐。

八、安装

目前尚未发布到 npm,从源码安装:

代码语言:javascript
复制
git clone https://github.com/studyzy/dsh-i-am-rich.git
cd dsh-i-am-rich
pnpm install && pnpm run build
dsh plugin --profile <你的 profile> add link:/path/to/dsh-i-am-rich

然后把插件行合进 profile:

代码语言:javascript
复制
- insert:
    - id: i-am-rich
      name: '@studyzy/dsh-i-am-rich'

如果安装过程中遇到问题,欢迎到 GitHub Issues 反馈。


九、总结与思考

写这个插件的过程中,我一直在想一个问题:当一个功能的存在理由是荒谬的,工程上的正确还重要吗?

我的答案是:正因为行为是荒谬的,账本才必须是精确的。每一行 JSONL 都是真实发生的浪费,每一个数字都来自 provider 亲手报的用量,每一次故障都被测试复现并锁死。段子的部分交给段子,其余的部分,用做基础设施的态度做完。

毕竟,真正的有钱人,倒掉的每一碗豆浆都有账可查。

欢迎在评论区聊聊你的看法,或者去 GitHub 仓库 提 Issue、点 Star——如果你也喜欢这种「认真地做一件不正经的事」,我会很高兴。


参考资源:

温馨提示:discardedCopies 是自然数,没有上限。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 一、段子的原样复刻
  • 二、它长什么样
  • 三、千万富翁与亿万富翁:倒豆浆有两种倒法
  • 四、账本只记真金白银,状态条只数全价 token
  • 五、认真聊聊架构
    • 5.1 Host 半边(Node):在水瀑布上放一道双保险
    • 5.2 账本:独立目录,按月 JSONL,仅追加
    • 5.3 纯函数内核:src/waste.ts
    • 5.4 时钟的正确归属:一个被认真对待的哲学问题
    • 5.5 Client 半边(浏览器):CJS 包进 ModuleLoader
  • 六、一个不严肃插件里的严肃事故史
  • 七、谁该装这个插件?
  • 八、安装
  • 九、总结与思考
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档