upcyan/dsh-mimo-extension ↗★ 0

dsh-mimo-extension

展示 MiMo 额度环、套餐详情及费用估算 适合需要实时监控 MiMo 官方额度和套餐使用情况的用户。

包名
dsh-mimo-extension
兼容性
待验证
版本
0.9.0
许可证
MIT
最近更新
2026年9月28日

安装

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:upcyan/dsh-mimo-extension

配置

Cookie

填了 Cookie 才能读到官方额度。

字段作用
MiMo 控制台 Cookie官方接口鉴权。留空表示保持不变;勾「清除已保存的 Cookie」可清掉
本地兜底套餐总量没配 Cookie 时,用来估算月度总量的 tokens 数
额度胶囊位置见下
允许输入框工具栏自动换行见下
启用 MiMo 视觉路由见下

保存的值写进 $DSH_HOME/settings.yaml 的 dsh-mimo-extension 命名空间,优先级高于 cordis.patch.yml 里的 config(后者只作组成基线)。

这个 Cookie 是给套餐用的

同一个控制台 Cookie 打三个接口,Token Plan 的数据依赖它:

接口读什么归属
tokenPlan/detail套餐码、周期、是否过期Token Plan
tokenPlan/usage已用百分比、各项 itemsToken Plan
balance现金和赠金余额按量

套餐用户不填 Cookie,剩余百分比就读不到(两个 tokenPlan/* 都返回 401),只能退回本地估算。按量用户填了也只多一个 balance,按量本来就没有 tokenPlan/usage。

实测(2026-09-27,有效 Cookie):

curl -H "cookie: " https://platform.xiaomimimo.com/api/v1/tokenPlan/detail

# → {"code":0,"data":{"monthUsage":{"percent":0.1186,"items":[{"name":"month_total_token",...}]}}}

Cookie 是几百字符的长串,输入框支持 Ctrl+V、右键粘贴,另有一个「粘贴」按钮走 navigator.clipboard.readText() 兜底(无权限或非安全上下文会提示手动粘贴)。输入框是 type="text" 而非 password,粘贴不受浏览器对密码字段的限制,内容也能看见便于核对。

获取步骤(表单里也有):

  1. 登录
  2. DevTools → Network → 任一 /api/v1 请求 → Headers → 复制完整 Cookie 请求头
  3. 确认含 api-platform_serviceToken 与 userId,整段粘进表单保存

不用界面也行:写进 $DSH_HOME/.credentials.yaml 的 refs.MIMO_CONSOLE_COOKIE,或直接编辑 cordis.patch.yml 的 mimo.cookie。

Cookie 只存本机 settings.yaml,不回传给浏览器。读取接口只返回「是否已配置 + 来源」,输入框也不回显明文。

胶囊位置

在「MiMo 用量」页底部的表单里选,保存即生效:

取值位置说明
header标题行与「对话 / 轨迹」同一行的右侧动作区
toolbar(默认)输入框工具栏模型选择器旁,即 codebuddy 用量环的位置
above输入框上方独占一行,最不挤占其它工具
hidden不显示只留详情页

点击环弹出的摘要卡,不管胶囊在哪个座位都用 createPortal 挂到 document.body,再按锚点位置和视口空间摆位:水平越界就左移、贴顶就翻到下方、resize 和滚动时重算、内容过高时内部滚动。祖先的 overflow 裁不到它,320px 窄屏和 800×360 横屏下都完整可见。

工具栏自动换行

插件多了以后,输入区的工具图标会互相挤压重叠。表单里的「允许输入框工具栏自动换行」(默认开)注入的样式只作用于组内(_tools / _actions / 左右槽位容器),让图标在本组内折行,不动整行。整行是否换行由产品原生样式决定;装了 dsh-web-mobile-cyanmod 时会被它覆盖成 nowrap,两者可以叠加。关掉立即恢复官方默认。

视觉路由

在「MiMo 用量」页底部勾选「启用 MiMo 视觉路由(图像输入)」。

平台按模型的 inputModalities 拦图片附件,dsh-api-session-controller 会抛 MODEL_DOES_NOT_SUPPORT_IMAGES。这个值来自 llm-pi-ai 里每个模型的 input 字段。开启后插件把多模态模型的 input 写成 ["text","image"],图片就能发给它们。

只对平台目录声明支持图像的模型生效(数据来自 pi-ai 的 dist/providers/data/xiaomi*.json):

provider模型catalog 的 input本开关
xiaomi / xiaomi-token-plan-{cn,sgp,ams}mimo-v2.5["text","image"]写入
同上mimo-v2.5-pro["text"]不碰
xiaomimimo-v2.5-pro-ultraspeed["text"]不碰

不给纯文本模型撑腰是有意的:硬声明图像支持会把失败从"明确拒绝"变成"图片被上游静默丢弃",而后者用户以为发出去了。自建 provider(比如 mimo)也不在内置表里——它的模型清单由你自己声明,能力也该由你自己声明。

写入用 settings.mutate("llm-pi-ai", ops) 整条替换 models 数组,只改目标模型的 input,不重写整个 provider。已经是 ["text","image"] 就不写;关闭时去掉 image 并保留其它模态(空了补回 ["text"])。启动时会再同步一次,因为开关可能比写入活得久(插件重装、配置被改)。

写入失败会回显:POST /settings 回传 visionChanged / visionError,表单显示"已开启:``"或失败原因,不会只报"已保存"。

这是跨命名空间写入(改的是 llm-pi-ai)。平台 settings.write() 只校验命名空间已注册,不校验调用者归属,所以可行;但只读 provider 上会失败并报错。

子选项:同时为纯文本模型提供视觉能力

主开关下方还有一个「同时为纯文本模型提供视觉能力」,默认关,且主开关关时禁用。它额外给平台标为纯文本的小米模型声明图像输入:

provider模型catalog input
xiaomimimo-v2.5-pro、mimo-v2.5-pro-ultraspeed["text"]
xiaomi-token-plan-{cn,sgp,ams}mimo-v2.5-pro["text"]

这是越权声明:上游可能拒绝,也可能静默丢图(你未必收到报错,比明确报错更麻烦)。确认这些模型实际能读图时再开。

回收是精确的。两张模型清单(多模态 / 纯文本)各自决定自己去留,关掉子选项时只回收它加过的,不会删掉 catalog 本就给 mimo-v2.5 声明的 image——那归主开关管。

显示规则

只在用 MiMo 模型时显示

额度环绑在 MiMo 通道上,所以只在当前模型属于 MiMo 时渲染。读会话投影 modelSelection 的 next / lastUsed,与 dsh-codebuddy 的 codebuddyUsageVisible 同一机制。

判定以 API 地址为准,名字只作参考。平台内置 catalog 里的小米路由有两类命名:xiaomi(按量)和 xiaomi-token-plan-cn / -sgp / -ams(套餐),它们都不含 mimo;反过来,自建网关可以叫 mimo-xxx 却指向别家。所以:

  • 地址是 xiaomimimo.com 域名 → 是
  • 地址明确是别家 → 不是
  • 地址读不到 → 退回名字(provider 名含 mimo / xiaomi*,或模型名含 mimo)

用别的 provider(比如 codebuddy)时整个环不渲染,免得"明明没用 MiMo 却在报 MiMo 额度"。这时候详情页会在模型卡下标注「当前模型属于 X,不是 MiMo,下面的套餐额度是 MiMo 账号级的」。读不到 provider 时保持显示,宁多显示也不因读取失败静默关掉功能。

详情页可以设成「非 MiMo 时隐藏」:开启后不是 MiMo 就把整个 tab 收掉,切回 MiMo 自动恢复。默认关闭(一直显示)。

会话用量按渠道归属

一个会话可以换过模型,所以 session.totalTokens 不等于 MiMo 用量。实测某会话:

mimo/mimo-v2.6-flash          49,771,661 tokens / 367 calls
codebuddy/deepseek-v4.1-flash 89,081,411 tokens / 414 calls
─────────────────────────────────────────────────────────
总计                         138,853,072 tokens(其中 64% 不是 MiMo)

插件按 models[].provider 只统计 MiMo 归属的部分,三种情形都有交代:

情形显示
会话混用了多个渠道汇总只算 MiMo;下方列出各非 MiMo 渠道并声明「不计入上方汇总」;费用标注「估算」(分渠道明细只有总量、没有输入输出拆分,按 token 占比折算)
本会话完全没用 MiMo提示「本会话尚未使用 MiMo,会话用量为 0 是正常的」,并说明下方套餐额度是账号级的、与会话无关
无分渠道明细(老计数器或统计降级)标注「未细分渠道」,退回整体计数。不猜测,也不把数据抹成 0

明细表给非 MiMo 行加「不计入 MiMo」标记并弱化,另加 % 列显示各渠道占比。

早期版本用整会话的 input/output 乘 MiMo 单价算费用,会话换过模型时会把别的渠道的消耗也算进来,费用因此偏高。

尺寸与外观

额度环对齐 dsh-codebuddy 的用量环,两者并排时大小一致:

项值对应 codebuddy
环直径26Progress type="circle" width={26}
环宽3strokeWidth={3}
中心 logo12CodeBuddyLogo size={12}
环底圈--dsw-alias-border-l3orbitStroke
环进度--dsw-alias-label-tertiarystroke
logo 底色#ff6900(小米品牌橙)variant="brand" 的写死色
起点rotate(-90),12 点方向顺时针Semi 默认

尺寸不随窄屏或紧凑模式缩小,紧凑场景靠去掉内边距解决。配色用平台主题变量(dsh-web-frontend 定义),自动跟随主题。

logo 用固定品牌色而不是主题变量 --dsw-alias-brand-primary,因为本机主题把那变量定义成 #0f1115(近黑),环心会变成一团看不清的黑块。品牌 mark 保持品牌色,codebuddy 也这么干(它的 CodeBuddyLogo 在默认变体下写死 #6C4DFF,只有 mono 变体才用主题变量)。

codebuddy 用 @douyinfe/semi-ui 的 Progress,而 semi 不在平台 seed 表里(它自己打进了 6.5MB bundle)。本插件手写等价的 SVG 双圈,零依赖。mi logo 用 simple-icons 的 xiaomi 路径。

移动端竖屏

窄屏(<640px)自动切布局:

  • 详情页各卡片区从多列改单列堆叠,内边距与字号收窄
  • 按模型的表格外层可横向滚动,不撑破卡片
  • 用量柱状图降低柱高(60px → 46px)并允许横滚
  • 胶囊在窄屏隐藏文字,只留百分比或用量数值,避免挤压会话标题

宽屏(≥640px)保持多列自适应。横竖屏切换和窗口拖动都会实时重排。

数据与计费

数据来源

官方接口优先(需 Cookie):

  • GET https://platform.xiaomimimo.com/api/v1/balance — 余额 / 现金 / 赠金
  • GET https://platform.xiaomimimo.com/api/v1/tokenPlan/detail — planCode、currentPeriodEnd、expired
  • GET https://platform.xiaomimimo.com/api/v1/tokenPlan/usage — monthUsage{percent, items[{name, used, limit, percent}]},percent 需 ×100
  • 鉴权:请求头带 Cookie(含 api-platform_serviceToken 与 userId)

本地估算兜底(Cookie 没配或接口失败):

  • 聚合 $DSH_HOME/token-usage/usage-*.jsonl 的本月用量
  • 除以 mimo.planTotalTokens(默认 5 亿/月)得剩余百分比
  • 详情页顶部标注「本地估算(官方接口不可用)」

内置会话统计(token-usage/ 目录不存在时):

  • token-usage/ 和 ctx.tokenUsageCounter 都由 dsh-token-usage-counter 提供。该插件没装进 profile 时目录根本不存在,旧行为是把 ENOENT ... scandir '.../token-usage' 当错误抛出来,而且「今日/本月 tokens」「当前会话用量」永远是 0。
  • 现在目录缺失按「暂无记录」处理(local.ok=true, local.missing=true, local.note 说明原因),并由 createLocalUsageCounter() 直接读会话事件(assistant/message.data.usage)自建统计填上数值,来源标 local.source = "session-events"。
  • 口径是进程启动以来仍存活的会话,重启归零。它只读不落盘;一旦 dsh-token-usage-counter 装回来并有数据,仍以它的落盘数据为准。
  • 去重靠事件 seq,/session 每 60 秒重复扫描不会把用量翻倍。

计费类型判定

顺序如下(billingTypeFor()):

  1. mimo.billingTypeOverrides(provider/model 或 provider)—— 用户说了算

  2. provider 的 API 地址(从 llm-pi-ai 命名空间读)。小米两条通道的地址不同(pi-ai 官方目录 providers/*.json 实测):

    计费方式目录里的 providerbaseURL
    按量付费xiaomihttps://api.xiaomimimo.com/v1
    Token Planxiaomi-token-plan-cnhttps://token-plan-cn.xiaomimimo.com/v1
    Token Planxiaomi-token-plan-sgphttps://token-plan-sgp.xiaomimimo.com/v1
    Token Planxiaomi-token-plan-amshttps://token-plan-ams.xiaomimimo.com/v1

    地址含 token-plan → 套餐;是 xiaomimimo.com 其余子域 → 按量;读不到(自建网关、命名空间缺失)→ 继续往下。

  3. provider 名含 token-plan → 套餐

  4. provider 是小米通道但地址没读到 → 用官方 tokenPlan/detail 反证(summary.planStatus 四态):expired(已过期)或 none(官方明确无订阅)→ 按量;active / unknown(没配 Cookie、接口失败)→ 套餐

  5. 其余 provider → 按量

想强制某条路由按量(或反过来),写 billingTypeOverrides: { mimo: payg }。

单价按量模型用 mimo.pricing. (元/百万 tokens),没配则用 fallbackPrice。Token Plan 套餐内调用不额外收费。

「当前模型」从哪读

判定用的 provider / model 是当前选中的,不是最近一次请求用过的:

优先级来源语义
1agent-default-model 命名空间用户此刻选的是什么(切模型立即写入,与 UI 同源)
2session/event 的 request/header最近一次真的发过请求用的是什么
3落盘计数器快照历史
4内置统计快照历史
5空计费退化为 provider 命名约定

第 1 级必须在第 2 级之前。早期只有 2~4 级,于是在 UI 里把模型切到 MiMo 但还没发消息时,仍按旧模型判定,显示"按量付费"而模型选择器已经是 MiMo。这个顺序是有语义的。

数量单位

小米 Token Plan 的额度单位是 Credits,不是 tokens,也不是人民币;按量付费才是人民币余额,两者不通用:

  • 订阅套餐时 /api/v1/balance 恒为 0,这是正常的,详情页会标注说明

  • 官方换算(每百万 token 消耗的 Credits):

    模型缓存命中缓存未命中输出
    mimo-v2.6-pro2.5300600
    mimo-v2.6-flash2100200
    mimo-v2.5-pro2.5300600
    mimo-v2.52100200
  • 闲时 0.8 倍:北京时间 00:00–08:00 只扣 80%

  • 用量到 50% / 90% / 100% 时官方发短信和邮件

tokenPlan/usage 返回的 percent 是 0~1 的比值,要 ×100 才是百分比。实测 used/limit = 4725102737/49200000000 = 0.096038,接口回 percent: 0.0960;控制台前端的换算是 Math.min(100, Math.max(0, 100 * e)),所以官网显示 9.6%。本插件 toPercent() 用同一口径。早期版本直接当百分数显示,「本月已用」只有真实值的 1/100。

排查「装了没生效」

浏览器里看不到胶囊或详情页这类问题,服务端看不见。所以浏览器半边每走一个节点就往宿主 POST /dsh-mimo-extension/ping 报一次,从 /summary 的 client 字段读结果:


## 从 dsh-mimo-usage 升级

插件原名 `dsh-mimo-usage`,2026-09-27 改名为 `dsh-mimo-extension`,仓库和包名同步改了。

配置不用手工搬。启动时会自动把旧命名空间 `dsh-mimo-usage` 里的用户配置(含 Cookie、套餐总量、胶囊位置、各开关)迁移到 `dsh-mimo-extension` 段。迁移单向、幂等(新段已有配置就不覆盖),且**不删除旧段**,留作回滚依据,确认无误后可自行清理。

迁移只搬 `mimo` 子对象。旧段里手工加过其它字段的话需要自己处理。

profile 里的旧依赖(`file:dsh-mimo-usage-*.tgz`)不会自动消失,需要先 `dsh plugin remove dsh-mimo-usage` 再装新的。