DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Mimo Usage — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
M

dsh-mimo-usage

Mimo Usage

模型选择器旁的 mi 标志和配额环,以及 MiMo 使用详情标签页(计费类型、计划配额、按会话归因、费用估算)。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:upcyan/dsh-mimo-usage#435d728fe86f9da5636b00e6b89c1a0e2cad7d49
README兼容性版本
额度环用量摘要卡移动端

兼容性与来源证明

Mimo Usage 以 dsh-mimo-usage 发布,当前版本为 0.2.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/9/27

版本

0.2.1stable
2026/9/27
0.1.5stable
2026/9/27
0.1.4stable
2026/9/27
查看其余 1 个版本收起版本
0.1.2stable
2026/9/27

相关插件

正在加载相关插件…

最新版
0.2.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
周下载
0
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 models-usage 分类下经过校验的插件。

Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Client Ui Model Capabilities@linxin666/dsh-client-ui-model-capabilities为自定义 pi-ai 提供商声明每个模型的能力(图像输入和推理力度),可直接在 Models 设置卡片中编辑;写入官方 llm-pi-ai 设置命名空间,不更改 DSH 源代码。Codex Subscriptiondsh-codex-subscription通过 OAuth 在 DeepSeek Harness 中使用 ChatGPT 和 Codex 订阅,支持配额管理、安全重置、网页搜索、图像和快速模式Plugin@opencode2dsh/dsh-plugin供 DeepSeek Harness (DSH) 使用的免费 OpenCode Zen 模型:原生 dsh-llm 适配器插件,无需 API 密钥。

README

dsh-mimo-usage

DeepSeek Harness 插件:MiMo 额度胶囊(位置可配置)+ MiMo 用量详情页(当前模型计费类型、使用量、收费、用量统计、用量预测、内置 Cookie 配置)。

阅读约定:文中的具体路径(/vol1/...)、地址(127.0.0.1:3081、<NAS>:3080) 来自 fnOS NAS 部署环境,替换成你自己的即可。Cookie 相关内容只出现字段名 (api-platform_serviceToken / userId),不含任何真实凭据;插件也从不把 Cookie 回传给浏览器,只存在本机 settings.yaml。

功能

入口显示内容说明
额度环mi logo + 用量环环内嵌小米 logo,环画套餐剩余百分比;按量计费没有总量 → 只画空环(不画误导性的 0%/100%)。位置可配置(见下)
点击额度环用量摘要卡计费类型、剩余额度/会话 tokens、本月已用、套餐总量、请求次数、当前模型,底部有「查看详情」入口
详情页MiMo 用量 tab当前模型、计费类型、本会话 MiMo 用量(按渠道归属)、今日/历史用量、收费估算、用量趋势与预测,页面底部可配置 Cookie 等
额度环点击弹出用量摘要卡移动端(390px)
额度环用量摘要卡移动端

会话余额按渠道归属(重要)

一个会话可以换过模型,所以 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/i 匹配,与额度环可见性同规则) 只统计 MiMo 归属部分,三种情形都有明确交代:

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

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

顺带修掉一个费用高估 bug:早期版本用整会话的 input/output 乘 MiMo 单价, 会话换过模型时会把别的渠道的消耗也算成 MiMo 花费。

只在用 MiMo 模型时显示

额度环绑定的是 MiMo 通道,因此只在当前模型属于 MiMo 时渲染(与 dsh-codebuddy 的 codebuddyUsageVisible 同一机制:读会话投影 modelSelection 的 next/lastUsed.provider,用 /mimo/i 宽松匹配)。

用别的 provider(如 codebuddy)时整个环不渲染 —— 否则会出现"明明没用 MiMo 却在报 MiMo 额度"的误导。详情页此时会在模型卡下标注「当前模型属于 X,不是 MiMo, 下面的套餐额度是 MiMo 账号级的」。

读不到 provider 时保持显示(宁可多显示,也不因读取失败而静默关掉功能)。 投影不可用时用 /summary 的 provider 兜底。

尺寸与外观

对齐 dsh-codebuddy 的用量环,两者并排时大小一致(改前请先核对 codebuddy 是否也变了):

项值对应 codebuddy
环直径26Progress type="circle" width={26}
环宽3strokeWidth={3}
中心 logo12CodeBuddyLogo size={12}
环底圈--dsw-alias-border-l3orbitStroke
环进度--dsw-alias-label-tertiarystroke
logo 底色--dsw-alias-brand-primaryvariant="mono" 的 tileFill
起点rotate(-90) 12 点方向顺时针Semi 默认

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

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

胶囊位置(可配置)

在「MiMo 用量」页底部的配置表单里选择,保存即生效(无需重启):

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

用量摘要卡(点击环弹出)的位置:无论胶囊在哪个座位,弹层都用 createPortal 挂到 document.body,再按锚点位置与视口空间自动摆位 —— 水平越界就左移、贴顶就翻到下方、resize/滚动时重算、内容过高时内部滚动。

这样彻底避免了"弹窗跑到屏幕外 / 被父容器 overflow 裁掉": 祖先的裁剪上下文不再影响它,且任何视口尺寸(含 320px 极窄、 800×360 横屏)下都完整可见。平台自己的 Tooltip 原语也是这个做法。

工具栏自动换行(可配置)

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

移动端竖屏适配

窄屏(<640px,竖屏手机)自动切换布局:

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

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

Cookie 配置入口(在「MiMo 用量」页内)

打开 MiMo 用量 标签页,拉到底部即可看到 MiMo 额度配置:

字段作用
MiMo 控制台 Cookie官方接口鉴权;留空 = 保持不变,勾选「清除已保存的 Cookie」可清掉
本地兜底套餐总量未配 Cookie 时用于估算剩余的月度总量(tokens)
额度胶囊位置见上表
允许输入框工具栏自动换行见上节

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

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

这个 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: <你的 Cookie>" https://platform.xiaomimimo.com/api/v1/tokenPlan/detail
# → {"code":0,"data":{"planCode":"lite:year","currentPeriodEnd":"2027-09-04 23:59:59",...}}
curl -H "cookie: <你的 Cookie>" https://platform.xiaomimimo.com/api/v1/tokenPlan/usage
# → {"code":0,"data":{"monthUsage":{"percent":0.1186,"items":[{"name":"month_total_token",...}]}}}

粘贴

Cookie 是几百字符的长串,输入框支持:

  • Ctrl+V / 右键粘贴 —— 输入框是 type="text"(不是 password), 粘贴不受浏览器对密码字段的额外限制,且内容可见便于核对
  • 「粘贴」按钮 —— 走 navigator.clipboard.readText(),Ctrl+V 失效时兜底 (无权限/非安全上下文会提示手动粘贴)
  • 显式 onPaste 处理:受控 input 在部分宿主下不派发 onChange,会表现为"粘不上"

获取 Cookie 的步骤(表单内也有提示):

  1. 登录 https://platform.xiaomimimo.com(余额页或控制台任意页均可)
  2. DevTools → Network → 任一 /api/v1 请求 → Headers → 复制完整 Cookie 请求头
  3. 确认包含 api-platform_serviceToken 与 userId,整段粘贴进表单并保存

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

接口路径与 fnOS 网关前缀(重要)

插件宿主路由是 /dsh-mimo-usage/*,刻意不用 /api/*。

为什么不用 /api

DSH 核心对 /api 前缀有一条严格的 Host/Origin fence (dsh-client-connection 的 isTrustedApiRequest):

  1. Host 必须是 loopback(localhost / 127.x),或是启动参数 --trusted-host 列出的 authority
  2. 且 Origin.host 必须完全等于 Host

经 fnOS 网关(https://<NAS>:3080)访问时 Host 被改写成 127.0.0.1:3081、 而浏览器发的 Origin 是 https://<NAS>:3080 → 第 2 条永不成立 → 一律 403。

非 /api 前缀没有这层 fence。

必须补 __FNOS_GATEWAY_PREFIX__(否则 405 / 404)

fnOS 网关(/vol1/@appcenter/dsh-fnos/gateway.js)把整个页面挂在 /app/dsh-fnos/dsh/ 下,并做三件事(handleGuide → proxyGuideDsh):

  1. 转发前剥掉前缀:/app/dsh-fnos/dsh/x → /x
  2. 改写 HTML:<base href="/"> → <base href="/app/dsh-fnos/dsh/">
  3. 在 <head> 注入 <script>globalThis.__FNOS_GATEWAY_PREFIX__="/app/dsh-fnos/dsh"</script>

关键坑:<base href> 对以 / 开头的绝对路径无效。 所以插件直接 fetch("/dsh-mimo-usage/summary") 会打到 https://<NAS>:3080/dsh-mimo-usage/summary —— 没有前缀,网关走无前缀分支原样转发,落到 core 的未注册路径上:

  • POST → @deepseek-ai/dsh-host-frontend-static 的 fallback seat 返回 405 且空 body(if (req.method !== "GET" && req.method !== "HEAD"))
  • GET → 404

平台对官方客户端模块是用 patch-dsh.mjs 逐个打补丁的 (dsh-client-connection / dsh-api-gateway / dsh-client-hmr / dsh-client-file-upload / dsh-client-ui-deliverables / dsh-session-log-export), 第三方插件不在名单里,必须自己处理。

本插件的做法(client.js 的 gatewayPath()):

function gatewayPath(path) {
  let prefix = "";
  try {
    if (typeof globalThis !== "undefined" && typeof globalThis.__FNOS_GATEWAY_PREFIX__ === "string") {
      prefix = globalThis.__FNOS_GATEWAY_PREFIX__;
    }
  } catch { /* 忽略 */ }
  return prefix.replace(/\/+$/, "") + path;   // 去尾斜杠,避免 //
}

每次发送时求值(不是模块加载时):前缀由 HTML 内联脚本注入, 而本脚本同为启动清单成员,执行顺序不保证。

环境__FNOS_GATEWAY_PREFIX__实际请求路径
直连 http://127.0.0.1:3081undefined/dsh-mimo-usage/summary
经网关 https://<NAS>:3080/app/dsh-fnos/dsh/app/dsh-fnos/dsh/dsh-mimo-usage/summary

写插件的通用建议:任何插件自己的 HTTP 路由都要套一层 gatewayPath(), 否则只在直连时能用、经网关必挂。诊断通道尤其要注意 —— 它正是用来排查"装了没生效"的,自己先被网关挡掉就白搭。

端点一览

端点方法用途
/dsh-mimo-usage/summaryGET额度与用量汇总(?refresh=1 绕过缓存)
/dsh-mimo-usage/sessionGET指定会话的 token 用量(?id=<sessionId>)
/dsh-mimo-usage/settingsGET / POST读取 / 保存配置(Cookie 等)
/dsh-mimo-usage/pingPOST浏览器半自诊断回传(随 /summary 的 client 字段吐出)

单位说明:Token Plan 用 Credits

小米 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% 时官方会短信+邮件提醒

⚠️ 官方 percent 是比值(0~1),不是百分数

tokenPlan/usage 返回的 percent 是 0~1 的比值,必须 ×100 才是百分比 (实测:used/limit = 4725102737/49200000000 = 0.096038,接口回 percent: 0.0960)。 控制台前端的换算是 Math.min(100, Math.max(0, 100 * e)), 所以 0.0960 在官网显示为 9.6%。本插件 toPercent() 采用同一口径; 早期版本直接把它当百分数显示,「本月已用」只有真实值的 1/100 (0.096 被显示成 0.10%)。回归用例见 check.mjs 第 6 节。

数据来源(官方接口优先,本地统计兜底)

  1. 官方接口优先(需 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)
  2. 本地估算兜底(Cookie 未配置或接口失败):

    • 聚合 $DSH_HOME/token-usage/usage-*.jsonl 的本月用量
    • 除以 mimo.planTotalTokens(默认 5 亿/月)得剩余百分比
    • 详情页顶部标注"本地估算(官方接口不可用)"
  3. 内置会话统计(token-usage/ 目录缺失时的兜底):

    • token-usage/ 与 ctx.tokenUsageCounter 都由 dsh-token-usage-counter 提供; 该插件未装进 profile 时目录根本不存在。旧行为是把 ENOENT: no such file or directory, 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 每 60s 重复扫描不会把用量翻倍。

计费类型判定(自动推断,可覆盖)

判定顺序(billingTypeFor(),回归用例见 check.mjs):

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

  2. provider 的 API 地址 baseURL(billingTypeFromBaseURL(),从 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(如 xiaomi-token-plan-cn)→ Token Plan 套餐

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

  5. 其余 provider → 按量计费(pay-as-you-go)

本机这条路由叫 mimo、地址是 token-plan-cn.xiaomimimo.com,所以判 Token Plan 套餐。 早期版本只认 provider 名里的 token-plan 字面量,于是恒判成按量, 胶囊因此显示「会话 tokens」而不是套餐剩余百分比。

「当前模型」从哪读(影响计费判定的输入)

判定用的 provider/model 不是「最近一次请求用过的」,而是 「当前选中的」 —— 顺序如下(createModelTracker):

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

⚠ ① 必须在 ② 之前。 早期只有 ②~④,于是:在 UI 里把模型切到 MiMo 但还没发消息时,仍按旧模型判定 → 显示"按量付费",而模型选择器已经是 MiMo。 这个顺序是有语义的(agent-default-model 必须优先于事件流)。

单价:按量模型用 mimo.pricing.<provider/model>(元/百万 tokens),未配置用 fallbackPrice。Token Plan 套餐内调用不额外收费。

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

安装

标准方式(仓库发布到 GitHub / npm 后):

dsh plugin --profile web add <你的仓库或包名>

下文其余部分是本工作区的 fnOS NAS 部署实录(含路径与环境前置), 替换为你自己的环境即可,插件本身的行为不依赖这些路径。

两个环境前置条件(都与插件本身无关):

  1. 必须显式设置 DSH_HOME —— dsh 未设该变量时回退到 ~/.dsh, 从 fnOS 的 root 登录 shell 直接跑会把插件装进 /root/.dsh/profiles/web 而非应用真正使用的 $DSH_HOME/profiles/web,表现为"安装成功但界面无变化"。
  2. 可能需要 --config.minimumReleaseAge=0 —— pnpm 11 默认启用 24 小时 "最小发布年龄"供应链检查;若 lockfile 里有刚发布的包(如 dshmarket@1.58.0), install 会在校验阶段被拦下,而这个参数可临时放宽该策略。
export DSH_HOME=/vol1/@apphome/fn-deepseek-harness
export HOME=/vol1/@appshare/fn-deepseek-harness   # 与 fnOS 应用一致,共用同一个 pnpm store
cd /vol1/1000/deepseek_harness/fnos

# 从本地目录安装
dsh plugin --profile web add ./dsh-mimo-usage --config.minimumReleaseAge=0

# 或从 tgz(跨机器分发推荐)
dsh plugin --profile web add ./dsh-mimo-usage-0.2.1.tgz --config.minimumReleaseAge=0

安装后重启 dsh web,再刷新浏览器(F5)使新 boot graph 生效。

验证真的落盘(第一条无输出即为装错位置):

P="$DSH_HOME/profiles/web"
grep '"dsh-mimo-usage"' "$P/package.json"
ls -la "$P/node_modules/dsh-mimo-usage"
dsh --profile web --dump-config | grep -A3 "mimo-usage"   # 应打印 id: mimo-usage

profile 目录对受限用户只读时需用有写权限的账号执行。

配置

编辑 $DSH_HOME/profiles/web/cordis.patch.yml,在 mimo-usage 条目下:

- insert:
    - id: mimo-usage
      name: dsh-mimo-usage
      config:
        mimo:
          cookie: "api-platform_serviceToken=xxx; userId=yyy; ..."   # 官方接口 Cookie
          planTotalTokens: 500000000                                  # 本地兜底套餐总量
          billingTypeOverrides:
            xiaomi-token-plan-cn: token-plan
            deepseek-official/deepseek-chat: payg
          pricing:
            fallbackPrice: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }
            "deepseek-official/deepseek-chat": { input: 2, output: 8, cacheRead: 0.5, cacheWrite: 0 }

视觉路由(可选,默认关闭)

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

为什么需要它:平台按模型的 inputModalities 硬拦截图片附件 —— dsh-api-session-controller 会抛 MODEL_DOES_NOT_SUPPORT_IMAGES(Model "x" does not support image input)。 该值最终来自 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) 的路径寻址 (providers.<p>.models[<i>].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(那是主开关管的)。自检里有一条专门的断言盯着这个边界。

结构

  • host.js — 宿主插件:注册 /api/dsh-mimo-usage/* 路由(balance / tokenPlan / usage / summary),Cookie 调官方接口,失败回退本地 usage 日志聚合;顺带注册 /mimo 斜杠命令与 mimo_usage 工具供模型查询。
  • client.js — 浏览器 bundle(__ModuleLoader__ 工厂格式,仅依赖平台共享 react,无构建步骤):
    • conversation.session.header.actions 槽位(order 30,位于 jobs/trajectory 标签之后)→ mimo额度 胶囊
    • conversation.view 槽位(id mimo-usage,label "MiMo 用量")→ 详情页 tab
  • package.json — 声明 dsh.bundle(空 patch)+ dsh.client(web 平台)
  • cordis.patch.yml — 自激活层(含默认配置与 Cookie 配置说明)

更新频率

  • 胶囊挂载 / 切换会话 / 点击 / 页面从后台切回 → 立即刷新
  • 每 60 秒静默刷新一次(官方接口或本地聚合,有请求但低频)
  • 空闲时无定时器轮询(除 60s 这一条)

手动安装(profile 目录只读时)

若 dsh plugin add 因权限失败,可让有写权限的账号执行:

# 1. 把包放进 profile node_modules
cp -r dsh-mimo-usage "$DSH_HOME/profiles/web/node_modules/dsh-mimo-usage"

# 2. 在 profile package.json 的 dependencies 加一行
#    "dsh-mimo-usage": "file:./node_modules/dsh-mimo-usage"

# 3. 追加 bundles
#    "dsh.profile.bundles" 末尾加 "dsh-mimo-usage"

# 4. 追加 patch(或依赖 cordis.patch.yml 自带 insert——见下方说明)
#    若插件的 cordis.patch.yml 被自动叠加,则无需手动改 profile cordis.patch.yml

由于本插件的 cordis.patch.yml 自带 - insert 行,安装进 node_modules 并加入 bundles 后,patchReload: live 会在下次启动自动应用,无需手动编辑 profile 的 cordis.patch.yml。

计费口径

  • Token Plan 套餐:套餐内调用不额外扣费,只消耗套餐 token 配额;胶囊/详情页显示剩余百分比
  • 按量计费:按 provider/model 单价估算收费(元/百万 tokens),缓存命中按 cacheRead 单价
  • 估算值仅供参考,实际扣费以小米 MiMo 官方账单为准

装了没生效?自诊断

浏览器里"看不到胶囊 / 没有详情页"这种问题,服务端是看不到的。所以浏览器半边每走一个节点 就向宿主 POST /dsh-mimo-usage/ping 报一次到,GET /summary 的 client 字段直接读结果:

curl -s "http://127.0.0.1:3081/dsh-mimo-usage/summary" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['data']['client'])"
client.stage含义 / 下一步
null浏览器压根没跑到新代码:硬刷新(Ctrl+Shift+R);若 host.js 是刚改的,先重启 dsh web(/ping 是 host 侧路由)
module-loaded脚本已执行但工厂没被调 → fiber 没激活,去「设置 → 插件」看该行状态(failed / pending (waiting for services: …))
factory工厂调了但 apply 没跑 → fiber 还在 pending 或 apply 抛错,看浏览器控制台
apply-enteredapply 开跑但没到 applied → 中途抛错,控制台搜 [dsh-mimo-usage]
applied前端注册完成(registered 列出注册的槽位、pillPosition 为当前胶囊位置),仍看不到就是渲染层/槽位层问题
skipped / skipped-duplicate被包名守卫或重复装载兜底主动收手(entryName 会一并回传)

同一 origin 下往往有多个标签页(工具页 / 对话页)各自报到,最近 20 条时序与页面路径都在 clientLog 里(每条带 path、hash、at):

curl -s "http://127.0.0.1:3081/dsh-mimo-usage/summary" \
  | python3 -c "import json,sys;print(json.load(sys.stdin)['data']['clientLog'])"

path/clientLog 是 host 侧字段:host.js 更新后要重启 dsh web 才有, 旧 host 会直接丢掉多出来的字段(不会报错)。

相关自检(离线,不碰运行中的服务):

node check-client.mjs   # 用 mock ctx 离线跑 client 的 apply(110 项)

历史 bug:apply() 里曾有一条严格相等的包名守卫 (entryName !== "dsh-mimo-usage" → return)。宿主一旦用别名装载, 整颗插件会静默消失 —— 胶囊 + 详情页一起没了,且一行日志都没有。 现在只在名字明确属于别的插件时才跳过(并打 console.warn + probe("skipped")), 重复装载则靠 slots.entriesOfSlot 兜底。

维护提示

  • 改 client.js 后:客户端 HMR 自动更新,刷新页面必生效

  • 改 host.js 后:热重载不会生效(Node ESM 缓存),必须重启 dsh web —— 实测 patchReload: live 只管 patch 层,不动已加载模块的代码

  • 改完先跑三个验证脚本(都不需要重启、不碰运行中的服务):

    cd /vol1/1000/deepseek_harness/fnos/dsh-mimo-usage
    node check.mjs          # 127 项静态 + 单元回归(含七项 bug 回归 + 网关前缀 + 当前模型优先级)
    node check-client.mjs   # 110 项:离线跑 apply + 环/logo/可见性/Cookie 粘贴/归属/i18n/弹层几何
    DSH_HOME=/vol1/@appdata/dsh-fnos/dsh-home \
      MIMO_COOKIE="$(python3 -c "import yaml;print(yaml.safe_load(open('$DSH_HOME/settings.yaml'))['dsh-mimo-usage']['mimo']['cookie'])")" \
      node verify-fix.mjs   # 端到端:起假 Cordis 上下文 → 打真实官方接口 → 校验 /summary /session /mimo /ping
    
  • 部署同步(profile 里的安装副本是解包后的目录,不是软链):

    P="$DSH_HOME/profiles/web/node_modules/dsh-mimo-usage"
    cp -f host.js "$P/host.js"        # 沙箱为 workspace-write 时需要更高权限
    

    同步后仍需重启 dsh web 才会被读进 Node 进程。