Skip to content

feat(packages): 为 usage 增加输出 token 趋势指令#895

Open
Procyon-Nan wants to merge 2 commits into
ChatLunaLab:v1-devfrom
Procyon-Nan:feat/usage-tokens-command
Open

feat(packages): 为 usage 增加输出 token 趋势指令#895
Procyon-Nan wants to merge 2 commits into
ChatLunaLab:v1-devfrom
Procyon-Nan:feat/usage-tokens-command

Conversation

@Procyon-Nan
Copy link
Copy Markdown
Contributor

@Procyon-Nan Procyon-Nan commented Jun 1, 2026

概览

  • chatluna-usage 增加 tokens 指令,支持 dayweekmonthall 范围参数,以及可选插件用量明细
  • 基于 chatluna_usage 表生成 token 用量统计,包含累计 token、累计请求、TPM、RPM
  • 图表同时展示总 token、输入 token、输出 token 三条趋势线,并提供颜色图例
  • 新增 puppeteer HTML/SVG 图表渲染,支持浅色和深色主题,可在插件配置中切换
  • puppeteer 作为可选服务接入;未启用时仍返回文字统计并提示需要启用 puppeteer

验证

  • yarn workspace @root/chatluna-koishi fast-build extension-usage

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new "tokens" command to visualize ChatLuna token usage trends and plugin breakdowns, rendering charts via Puppeteer. Feedback highlights a potential call stack overflow risk in "index.ts" when using "Math.max" with the spread operator on large datasets. Additionally, in "renderer.ts", it is recommended to make the "__dirname" resolution safer for ESM environments and to delete temporary HTML files immediately in the "finally" block rather than using a delayed "setTimeout" to prevent disk clutter and memory leaks.

Comment thread packages/extension-usage/src/index.ts
Comment thread packages/extension-usage/src/renderer.ts Outdated
Comment thread packages/extension-usage/src/renderer.ts Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

Review limit reached

@Procyon-Nan, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 minutes and 21 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 00233307-34a3-4dbc-832c-54ce4709028c

📥 Commits

Reviewing files that changed from the base of the PR and between fb89391 and 60f01e2.

📒 Files selected for processing (2)
  • packages/extension-usage/src/index.ts
  • packages/extension-usage/src/renderer.ts

Walkthrough

新增 token 消耗趋势功能:定义报表数据结构、在控制台注册 /tokens 命令以生成报表并可选渲染图表,提供 SVG 绘制与 HTML 模板并通过 Puppeteer 截图输出图片。

变更

Token Trend 趋势图渲染功能

Layer / File(s) Summary
数据契约与配置
packages/extension-usage/src/index.ts
新增 TokenRangeTokenPointPluginUsageTokenReport 接口;Config 新增 tokensTheme 字段;inject.optional 添加 puppeteer
报表生成与命令集成
packages/extension-usage/src/index.ts
添加区间别名与格式化函数;实现 tokenReport(range, withPlugins)chatluna_usage 读取并构建 TokenReport;注册 /tokens 命令,解析参数、返回文本统计并在可用时调用 renderTokenTrend 输出图片。
渲染引擎、图表与模板
packages/extension-usage/src/renderer.ts, packages/extension-usage/resources/token-trend/template.html
实现模板填充与 HTML 安全转义;monotonePath 生成单调三次曲线;chart 绘制网格、折线、面积与点;pluginCard 生成插件明细 HTML;renderTokenTrend 写临时 HTML、通过 Puppeteer 打开并截图;新增 HTML 模板与主题样式。

序列图

sequenceDiagram
  participant User
  participant TokensCommand as /tokens 命令
  participant tokenReport
  participant Database as chatluna_usage
  participant renderTokenTrend
  participant Puppeteer

  User->>TokensCommand: 触发 /tokens [range] [plugin]
  TokensCommand->>tokenReport: 请求 TokenReport(range, withPlugins)
  tokenReport->>Database: 查询 chatluna_usage
  Database-->>tokenReport: 返回记录
  tokenReport-->>TokensCommand: 返回 TokenReport
  TokensCommand->>renderTokenTrend: 请求渲染(若有 Puppeteer)
  renderTokenTrend->>Puppeteer: 打开本地 HTML, 等待字体, 截图 .stage
  Puppeteer-->>renderTokenTrend: 返回图片 buffer
  TokensCommand-->>User: 发送图片
Loading

代码审查工作量估计

🎯 3 (中等) | ⏱️ ~25 分钟

白兔献礼带妙笔,
token 趋势画成图,
曲线平滑连高低,
Puppeteer 快手截屏归,
从库到屏一条龙,ChatLuna 更明晰 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 标题准确总结了主要变更:为 chatluna-usage 添加 token 趋势输出指令。标题具体、清晰且与变更集高度相关。
Description check ✅ Passed PR 描述详细阐述了变更内容,包括新增指令、统计功能、图表展示、主题支持和可选服务接入,与变更集完全相关。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- 在 chatluna-usage 中新增 tokens 指令,支持 day、week、month、all 统计范围及插件明细参数。

- 基于 chatluna_usage 表聚合 total、input、output token 与请求峰值,按不同范围生成分桶趋势数据。

- 新增 puppeteer HTML 图表渲染模板,支持浅色和深色主题以及颜色图例。

- 将 puppeteer 声明为可选依赖服务,未启用时保留文字统计输出。
@Procyon-Nan Procyon-Nan force-pushed the feat/usage-tokens-command branch from 1efe8d3 to fb89391 Compare June 1, 2026 11:11
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/extension-usage/src/index.ts (1)

469-488: range === 'all' 会全表扫描,建议加上观测/治理手段。

rangealltime = { $lt: end },相当于把 chatluna_usage 全表拉进内存再聚合。随着记录增长,单次 tokens -a 可能造成明显的内存与延迟峰值。表上已有 createdAt 索引,但无范围过滤时索引无济于事。可考虑:为 all 设定一个上限时间窗(或最大行数),或在数据库侧做聚合统计而非全量取回。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/extension-usage/src/index.ts` around lines 469 - 488, The
tokenReport method currently sets time = { $lt: end } for range === 'all',
causing a full-table fetch of chatluna_usage by createdAt; change tokenReport to
avoid full-table scans by applying a sensible cap or DB-side aggregation: either
compute a start = end - MAX_TOKEN_REPORT_WINDOW (configurable, e.g. using Time
constants) or add a limit/aggregation in the database query (e.g. request
aggregated token sums or top-N rows instead of pulling all records) before
calling createTokenReport; ensure the change references tokenReport,
createTokenReport, chatluna_usage, createdAt and use a configurable MAX_ROWS or
MAX_WINDOW so future growth is governed and include a warning/log when the “all”
request is capped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/extension-usage/src/index.ts`:
- Around line 469-488: The tokenReport method currently sets time = { $lt: end }
for range === 'all', causing a full-table fetch of chatluna_usage by createdAt;
change tokenReport to avoid full-table scans by applying a sensible cap or
DB-side aggregation: either compute a start = end - MAX_TOKEN_REPORT_WINDOW
(configurable, e.g. using Time constants) or add a limit/aggregation in the
database query (e.g. request aggregated token sums or top-N rows instead of
pulling all records) before calling createTokenReport; ensure the change
references tokenReport, createTokenReport, chatluna_usage, createdAt and use a
configurable MAX_ROWS or MAX_WINDOW so future growth is governed and include a
warning/log when the “all” request is capped.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f33ed7f6-cc8e-48e0-acb4-596d7be53841

📥 Commits

Reviewing files that changed from the base of the PR and between 2229393 and 1efe8d3.

⛔ Files ignored due to path filters (1)
  • packages/extension-usage/package.json is excluded by !**/*.json
📒 Files selected for processing (3)
  • packages/extension-usage/resources/token-trend/template.html
  • packages/extension-usage/src/index.ts
  • packages/extension-usage/src/renderer.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/extension-usage/src/index.ts`:
- Line 66: The assignment to variable from mixes a ternary and nullish
coalescing without grouping, which triggers prettier; update the expression in
index.ts so the conditional is wrapped in parentheses (i.e., parenthesize the
RHS ternary so the nullish coalescing binds as intended) for the declaration
using range, sorted, start and end.

In `@packages/extension-usage/src/renderer.ts`:
- Around line 240-244: Compute dirname without referencing __dirname at
evaluation time: replace the current __dirname?.length check with a safe runtime
check like typeof __dirname !== 'undefined' ? __dirname :
path.dirname(fileURLToPath(import.meta.url)), and then build templatePath using
path.resolve(dirname, '..', 'resources', 'token-trend', 'template.html') (use
path.dirname(fileURLToPath(import.meta.url)) for ESM) so that the resolved
templatePath points to
packages/extension-usage/resources/token-trend/template.html rather than
src/resources/..., referencing the existing symbols __dirname,
fileURLToPath(import.meta.url), dirname, templatePath, and path.resolve to
locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 38469b34-be9c-432c-a787-978f51cfda8c

📥 Commits

Reviewing files that changed from the base of the PR and between 1efe8d3 and fb89391.

⛔ Files ignored due to path filters (1)
  • packages/extension-usage/package.json is excluded by !**/*.json
📒 Files selected for processing (3)
  • packages/extension-usage/resources/token-trend/template.html
  • packages/extension-usage/src/index.ts
  • packages/extension-usage/src/renderer.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/extension-usage/resources/token-trend/template.html

Comment thread packages/extension-usage/src/index.ts Outdated
Comment thread packages/extension-usage/src/renderer.ts
- 调整 chatluna-usage tokens 报表中 TPM 与 RPM 的计算方式,在统计循环内维护单分钟峰值,避免大量分钟桶通过参数展开传入 Math.max。

- 修复 token 趋势图渲染模块在 ESM 环境下的目录解析逻辑,使用 import.meta.url 时转换为所在目录。

- 调整 puppeteer 渲染临时 HTML 的清理时机,在渲染流程结束后立即删除临时文件,避免延迟定时器残留。
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.

1 participant