Skip to content

feat: update mcode-usage-monitor to 1.3.0 and add a usage-query skill - #12

Merged
MyPrototypeWhat merged 6 commits into
MiniMax-AI:mainfrom
yanhy2000:update-mcode-usage-monitor-1.3.0
Oct 8, 2026
Merged

MyPrototypeWhat merged 6 commits into
MiniMax-AI:mainfrom
yanhy2000:update-mcode-usage-monitor-1.3.0

Conversation

@yanhy2000

@yanhy2000 yanhy2000 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Updates plugins/yanhy2000/mcode-usage-monitor/ from 1.2.0 to 1.3.0. Plugin ID, package layout, data sources and privacy behaviour are unchanged.

What changed

Filtering

  • The model and session lists now cross-filter each other: each list narrows to what the other side selected, and shows its full range list when the other side is set to all. This stops a session from looking like it used several models at once.
  • A selection that the other filter temporarily hides is kept instead of being dropped, and the dropdown reports how many are hidden.
  • Select-all is dimmed only when everything is selected, invert is always available, and selecting nothing is allowed (the page then shows zero data).

Interface

  • Icon-only header controls (theme, refresh interval, manual refresh). Every card can be collapsed and expanded, and the layout editor reorders or removes both the KPI tiles and the cards, remembering the arrangement.
  • The model comparison card gained an empty state; the recent-calls table escapes its values; toasts no longer cover the header icons; Esc closes dropdown panels.

Agent skill (new)

  • The package now ships one Agent skill, skills/usage-query/. It teaches the Agent to locate and run the bundled data backend (miniapp/node/api.py), so usage questions — "how many tokens did this chat use?", "which model do I use most?" — can be answered directly without opening the dashboard first. It documents the parameters, the JSON field map, the counting rules, and failure handling, and points back to the dashboard when charts or hands-on filtering are wanted.
  • exampleQueries was rewritten to cover four entry points: opening the dashboard, this conversation's usage, a specific time range, and a per-model question.
  • README.md / README.zh-CN.md document the skill and add it to the verified list.

Robustness

  • Dropdown panels are no longer rebuilt by auto-refresh while open, so a click in progress is not lost.
  • Data loading is decoupled from the chart library: KPI tiles and the table render immediately, charts follow once ECharts is ready (bounded wait).
  • fetch has an in-flight guard and a 35 s abort, so slow queries no longer pile up and a hung connection cannot block refresh.
  • Preferences are written atomically and serialized; the query cache has a size cap; keep-alive timeouts are raised to avoid a 5 s idle-close race.
  • Python is probed as python then py -3, and a missing SQLite JSON1 extension is reported together with its SQLite version.
  • Snapshot fallback no longer leaks temporary directories; unused payload fields were removed.

Test environment

  • MiniMax Code desktop 3.1.0 on Windows (10.0.26200, x64), Python 3.10.10 / SQLite 3.39.4, Node.js 24.18. The dashboard and the bundled skill were re-tested on this release.
  • npm run validate on this branch: 0 errors, 2 warnings (explained below).
  • Backend: cross-filtering verified against /api/data — selecting models narrows the session list to the sessions that used them while the model list stays complete, selecting sessions narrows the model list the same way, per-session totals match a single-session query, and the explicit empty selection returns zero rows.
  • Frontend, in a browser: hidden selections survive later checkbox changes and the hidden-count hint appears; a dropdown stays interactive across an auto-refresh; Esc closes panels; the model comparison empty state renders; the footer shows the version injected from plugin.json; prefs.json stays valid after repeated filter changes.
  • Agent skill: verified end to end on this machine by asking usage questions in a conversation — the Agent finds the backend, runs the documented command, and answers from the JSON. The field names in SKILL.md were checked against the real payload (today: 881 calls, 16 sessions, 147.1M tokens, 97.8% cache hit rate).
  • Preview image regenerated from a synthetic local database (a fabricated runtime-state.sqlite plus fabricated messages.jsonl files, injected through MINIMAX_DATA_DIR). It contains no real session records, project names or personal data.
  • Diff checked before pushing: no secrets, no real data, no local paths.

Not verified: macOS and Linux; the py -3 probe fallback (the primary python command is available here); a Python build without the SQLite JSON1 extension; and the keep-alive / fetch-abort fixes are preventive — they were not reproduced under sustained load.

Warnings

npm run validate reports two README_HEADING_MISSING warnings:

warning README_HEADING_MISSING README.md should contain the heading "## Tested environment"
warning README_HEADING_MISSING README.md should contain the heading "## Data & access"

This package's README has used ## Data access and counting and ## Source and verification since 1.1.0 and carries the same information. The headings were left as they are to keep the README stable across releases; happy to rename them to the example's wording if you prefer.


中文摘要:mcode-usage-monitor 由 1.2.0 更新至 1.3.0。模型与会话筛选改为互相牵制(各侧只列出另一侧所选范围内出现过的项),被另一侧暂时隐藏的已选项不再丢失;顶栏改为图标按钮并加入编辑布局;新增内置技能 usage-query,Agent 可直接调用包内数据后端回答用量问题,不必先打开看板,示例问法同步覆盖打开看板 / 本对话用量 / 时间范围 / 模型维度四类;同时修复下拉被自动刷新打断、取数依赖图表库、请求堆积、偏好写入非原子等问题。插件 ID、数据来源与隐私行为不变,预览图已用合成数据重新生成。已在 Windows 桌面端 3.1.0 正式版实测(看板与内置技能均通过);macOS/Linux 与部分防御性改动未验证。


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

- Cross-filter the model and session lists: each list narrows to what the
  other side selected, and shows the full range list when the other side is
  set to all
- Keep selections that the other filter temporarily hides, and report how
  many are hidden inside the dropdown
- Pause dropdown rebuilding while a panel is open, so auto refresh no longer
  interrupts a click in progress
- Decouple data loading from ECharts: KPI tiles and tables render right away
  and charts are drawn once the library is ready (bounded wait)
- Add an in-flight guard with a 35s abort, so slow queries stop piling up and
  a hung connection cannot block refresh
- Fix the snapshot fallback leaking temporary directories; drop the unused
  ledger payload and dead response fields
- Write the preferences file atomically and serialize read-modify-write; cap
  the query cache; lengthen keep-alive timeouts; probe python/py -3
- Probe the SQLite JSON1 extension at startup and report an actionable error
- Add an empty state to the model comparison card, escape recent-call table
  values, keep toasts from covering the header icons, close dropdowns on Esc
Regenerated from the synthetic local database: 515M tokens, 16 sessions and
5 models, showing the 1.3.0 icon-only header and the layout editing entry.
Same capture spec as before: 642 CSS px wide at 2x, light theme, last 24 hours.
- skills/usage-query/SKILL.md: how to locate and run the bundled data backend
  (miniapp/node/api.py) to query local token usage, plus the JSON field map,
  counting rules and failure handling; it points back to the dashboard for charts
  and hands-on filtering
- plugin.json: declare the skill, and rewrite exampleQueries to cover opening the
  dashboard, this conversation's usage, a specific time range, and a per-model
  question
- README.md / README.zh-CN.md: document the skill and add "the Agent answers usage
  questions from the data backend" to the verified list
- Version stays 1.3.0
With a non-zero input the hit rate is necessarily below 100%, but rounding to
two decimals turned 99.99x% into 100%. Both the overview and the per-model
figures now go through pct_hit_rate(), which caps at 99.99 whenever input > 0
and only returns 100 for fabricated data with a zero input. The per-model
figure previously kept one decimal and had the same latent issue.

@MyPrototypeWhat MyPrototypeWhat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢更新!1.3.0 的交叉筛选和布局编辑思路很清楚。我在本地拉了这个分支,npm run check 通过;另外用一个合成的 sqlite 跑了 api.py,交叉筛选、__none__ 全不选和 99.99% 封顶都和描述一致。有几处想请你看看:

需要修改

  1. 在途闸会吞掉筛选变更后的那次加载(miniapp/client/index.html:713,详见行内评论):筛选或时间范围变化时,如果恰好有一轮自动刷新还没返回,新的 load() 会被直接丢掉,页面显示的是旧筛选的数据;在手动刷新模式下会一直停在旧数据。
  2. 新增的子进程命令没有在 README 里披露(miniapp/node/server.mjs:12-25,详见行内评论):py -3 回退和启动时的 --version 探测是这次新加的,docs/security.md 要求 "Disclose every command in the README"。
  3. 技能文档在 macOS/Linux 上给的命令不对(skills/usage-query/SKILL.md:30、46–50、84,详见行内评论):示例统一写的是 python,但服务端在非 Windows 上先试 python3,而 macOS 默认没有 python 命令。

建议(可选)

  • server.mjs:25 的 pickPython() 在模块加载时同步执行 spawnSync,最坏情况会阻塞两次 5 秒超时,而且页面还没查询就先起了进程。可以考虑改成第一次查询时再异步探测,并缓存结果。
  • "全不选"目前有 null、[]、'none'(偏好)、'__none__'(URL 和 CLI)几种表示,分散在 index.html、server.mjs、api.py 三处,以后改语义要动好几个地方。统一成一种哨兵值或一个小结构会更好维护。
  • startKpiDrag 和 startCardDrag 的拖拽处理几乎一样,可以抽成一个公共函数。KPI_KEYS 和 PREF_KPIS 这两份列表也可以考虑像 __VERSION__ 那样由服务端注入,省得手动同步。

再次感谢,有问题随时交流~

Comment thread plugins/yanhy2000/mcode-usage-monitor/miniapp/client/index.html Outdated
Comment thread plugins/yanhy2000/mcode-usage-monitor/miniapp/node/server.mjs Outdated
Comment thread plugins/yanhy2000/mcode-usage-monitor/skills/usage-query/SKILL.md Outdated
必改三项

index.html
- 拆开 load() 与 reload()。用户改筛选或时间范围走 reload(),取消在途请求
  并改发最新 URL;自动刷新、首次进入、手动刷新仍走 load(),在途则跳过——
  这几处 URL 相同,打断在途查询没有收益,查询慢于刷新间隔时反而永远出不来
  数据。请求带 seq,只有最新一次的结果上屏,被取代或超时的旧请求不再弹提示。
  原来在途闸直接 return,会吞掉变更后的那次加载,页面停在旧筛选的数据上。
- 空选三态(null=全部 / 空数组=空选 / 数组=具体选择)的翻译收敛到 selParam(),
  原来散在 apiUrl() 两行里。

README.md / README.zh-CN.md
- 新增 Processes 一节,按 docs/security.md 的 "Disclose every command in the
  README" 披露两类命令:首次查询时的 --version 探测(按平台候选顺序)与每次
  查询的 <cmd> miniapp/node/api.py --range … --models … --sessions …。

skills/usage-query/SKILL.md
- 改为先给按平台的 Python 候选表(Windows python → py -3;macOS/Linux
  python3 → python),示例统一用 <python> 占位。原来只在一处提了 Windows,
  macOS 上照着 python 调用会直接失败。

建议两项

server.mjs
- pickPython() 改为首次查询时用 execFile 异步探测并缓存结果,不再在模块加载
  时同步 spawnSync(最坏阻塞两次 5s 超时,而此时页面还没发起任何查询)。
- 注入 __KPI_KEYS__ / __CARD_IDS__,与 __VERSION__ 同一机制:客户端的卡片与
  KPI 白名单不再与 /api/prefs 校验各写一份。占位符未替换直接报错而非白屏。

index.html / server.mjs / api.py
- 拖拽排序合并为 startSortDrag + moveInOrder,KPI 方块与卡片共用,差异只留
  容器选择器、id 属性、前后判定和落位回调四处。合并时对齐了一处行为:卡片在
  落回自己或空白时也清掉候选目标,原先会按上一次的有效目标落位。
- 空选哨兵 __none__ 在三处各自提为同名常量并互相注明。

验证
- npm run validate:0 errors, 2 warnings(仍是 PR 描述里说明的两个
  README_HEADING_MISSING)。
- 浏览器实测:KPI 拖拽与卡片拖拽落位正确;时间范围 7d→1h 快速连切后页面
  跟到 1h 数据,旧结果未覆盖新结果;全不选返回 0 数据、重新勾选恢复;无
  console 报错,无失败请求。
- 未验证:macOS 与 Linux;快速连点筛选时客户端确实取消旧请求这一点只从
  最终显示的数据推断,没有抓包确认 abort。
@yanhy2000

Copy link
Copy Markdown
Contributor Author

修改需求与建议均已改好,提交在 836a23f

  1. 在途闸拆成了 load() / reload()。改筛选、切时间范围走 reload(),取消在途请求、直接发最新的;自动刷新和首次加载还是 load(),在途就跳过(URL 一样,没必要打断)。加了序号,只有最新一次的结果会上屏,被取代的旧请求不再弹提示了。
  2. README 加了 Processes 一节,启动时的 --version 探测和每次查询的 api.py 命令都列上了。
  3. SKILL.md 改成先给按平台的候选顺序,示例统一用 占位,macOS 上不会再照着 python 调用直接失败了。

关于建议部分:

  1. pickPython() 挪到第一次查询时异步探测并缓存,不再卡在模块加载。
  2. 拖拽抽成了 startSortDrag + moveInOrder,KPI 和卡片共用一份。
  3. KPI_KEYS / CARD_IDS 改由 server.mjs 注入,跟 VERSION 一个机制。哨兵值先在三个文件里各提成了同名常量,没动偏好文件格式。

已在本地跑npm run validate与实装测试验证

@MyPrototypeWhat MyPrototypeWhat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢这么快就改好了!我在本地拉了 836a23f 复测,npm run check 通过:

  • 在途闸:自动刷新或手动刷新在途时改筛选、切范围,渲染的都是最新选择,被取代的请求不再弹提示;真正的网络失败和 35s 超时仍有提示。
  • README 的 Processes 一节和实际执行的命令一致。
  • SKILL.md 的跨平台说明没问题。
  • 异步探测在并发首查时只探测一次。

需要修改

  1. 拖拽往后挪会多挪一格(miniapp/client/index.html:1131-1134,详见行内评论):moveInOrder 在去掉被拖项之前就取了目标的下标,KPI 方块和卡片往后拖都会落到目标的下一位;往前拖不受影响。这是这次合并拖拽代码时引入的,之前的两份实现都是对的。

建议(可选)

  • reload() 目前只取消了浏览器端的请求,被取消的查询仍会在服务端串行队列里跑完,新查询排在它后面。查询慢时,切换筛选的等待其实没有缩短。可以考虑在请求 close 时结束对应的子进程,或者跳过还没开始的排队项。不改也不影响正确性。

改完这一处我这边就没有其他问题了,谢谢!

Comment thread plugins/yanhy2000/mcode-usage-monitor/miniapp/client/index.html Outdated
yanhy2000 added a commit to yanhy2000/MiniMax-Code-MiniApps that referenced this pull request Oct 8, 2026
第二轮评审两项

index.html
- moveInOrder 改为先 filter 再取下标。原先下标取自原列表,被拖项排在目标前面
  时,去掉它之后目标会前移一位,往后拖就多挪一格(如 KPI 把「总量」拖到
  「输出」前会落成 input,output,total);往前拖不受影响。这是上一轮合并拖拽
  代码时引入的,合并前的两份实现都没有这个问题。

server.mjs
- 客户端断开(如 reload() 取消旧请求)时放弃对应查询:还在排队的直接跳过、
  不再起进程,已在跑的结束子进程,新查询不用排在死请求后面。缓存条目带等待
  计数,多个请求共享同一条查询时全部断开才取消;取消后同 key 重查正常。

自测发现两处

index.html
- 整行卡片(含窄屏单列布局)的拖拽落位改为按上下半区判定,半宽并排卡片仍按
  左右半区(落位到同行内)。原先 overEl 必然是鼠标下方的元素,"跨行按上下
  半区"是死代码,实际恒按左右半区判定;拖拽手柄在卡片右上角,鼠标停在右半
  区时整行卡片会一直判"落此卡片之后"。
- 工具图例改为自绘 HTML 色块:内联占比、悬停 title 带次数、点击切换该工具在
  环上的显示,状态不随定时刷新重置。原 ECharts 滚动图例的翻页按钮配色不跟
  主题(深色下近不可见),翻页与选中状态每 5s 被 setOption 重建清掉。

验证
- npm run validate:0 errors, 2 warnings(仍是 PR 描述里说明的两个
  README_HEADING_MISSING)。
- moveInOrder 断言 8 用例(含评审给的 KPI/卡片复现场景);落位判定断言 9
  用例(整行展开/收起、半宽左右、窄屏单列)。
- 假 context 拉起 server.mjs + api.py 实测:真实查询约 550ms,在 100ms 处
  断开后紧跟的新查询 540ms 完成(不取消则约 1s),被杀子进程无残留,同 key
  重查正常。
- 浏览器实测:工具色块切换隐藏后经历自动刷新状态保持、再点恢复;console 无
  报错。
…ol legend

- Drag reorder took the target index before removing the dragged item, so
  dragging an item backward landed it one slot too far. Filter first, then
  take the index.
- When the browser drops a request (filter change, timeout), the server now
  skips the query if it is still queued and terminates the subprocess if it
  already started, so newer queries no longer wait behind dead ones.
- Full-row cards judged drop before/after by the left/right half of the card;
  the vertical branch could never run because the cursor is always inside the
  hovered card. Full-row cards now use vertical halves, half-width cards keep
  the horizontal rule.
- The tools card legend is now plain HTML chips instead of the ECharts scroll
  legend: the pager icons did not follow the theme, and both the page position
  and the selection were reset on every refresh. Chips show each share inline
  and toggle a tool on click.
@yanhy2000
yanhy2000 force-pushed the update-mcode-usage-monitor-1.3.0 branch from ac22f58 to 3d54f95 Compare October 8, 2026 09:23
@yanhy2000

Copy link
Copy Markdown
Contributor Author

两处都改好了,提交至 3d54f95

  1. moveInOrder 改成先 filter 再取下标,往前往后都对齐目标了,已经过实装后测试。
  2. 服务端也加了取消:请求断开时,还在排队的直接跳过,已经跑起来的就结束子进程,新查询不用再排在死请求后面。多个请求共用同一条查询时按等待计数,全断了才取消。

另外这次自测还发现两个问题一起修了:整行卡片的拖拽前后判定实际一直在按左右半区算(跨行分支是死代码),会导致手感很奇怪,目前改成按上下半区判定;工具卡片的滚动图例翻页按钮配色不跟主题、翻页和选中状态每 5s 被刷新清掉,换成了自绘色块图例,直接内联显示占比、点击切换工具显示。

@MyPrototypeWhat MyPrototypeWhat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢这几轮细致的修改!我在本地拉了 3d54f95 复测,npm run check 通过:

  • 拖拽排序:KPI 方块和卡片往前、往后拖都落在正确位置;整行卡片按上下半区、半宽卡片按左右半区判定,宽屏和单列布局下都正常。
  • 服务端取消:排队中断开的查询不再起进程;运行中断开会结束子进程,后面的查询马上开始;多个请求共用一条查询时,只断开一个不影响另一个拿结果,全部断开才取消;取消后同一查询再请求能拿到完整结果,没有异常日志或残留进程。
  • 工具图例:占比正确,点击切换后经过自动刷新状态也保持;工具名会被转义;浅色、深色主题下显示都正常。

一个不阻塞的小点(可选):server.mjs:275 被取消的旧查询稍后 reject 时会按 key 删掉缓存里已经换上的新查询,导致同一查询紧接着再请求时会重复跑一遍。改成 if (cache.get(key) === entry) cache.delete(key); 就可以了。

辛苦了!

@MyPrototypeWhat
MyPrototypeWhat merged commit f8ba764 into MiniMax-AI:main Oct 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants