From 0414d527b9d9d53a2701ed7ab7153643e9588286 Mon Sep 17 00:00:00 2001 From: HaneWari Date: Thu, 22 Oct 2026 23:34:23 +0800 Subject: [PATCH 1/2] Add Token Meter Board (token-meter-board) Mini App A local, read-only token-usage dashboard for MiniMax Code. It reads the runtime's own per-call usage table and observability logs, so it shows the numbers the client actually recorded rather than an estimate reconstructed from session transcript files. - Usage trend with per-model stacked bars and cache-hit-rate / output-speed curves; five detail tables (per-model, daily, a 12-column per-call ledger, a turn-level conversation table, session ranking). - Output speed uses the same basis as the client interface: Sigma output tokens / Sigma decode duration, time-weighted, with P50/P90. - Every call is paired with its own decode and request durations. The pairing rule was verified against a token-signature ground truth over 16,723 calls with zero mismatches. - No Python, no extra process in the normal path, no third-party runtime code except a vendored copy of Chart.js (MIT, full licence text included). - Strictly read-only: no files written, no network, no telemetry. Query parameters are an explicit per-endpoint allow-list. Includes the English README with the required "## Tested environment" and "## Data & access" sections, a Chinese README, an Apache-2.0 LICENSE, a synthetic-data preview image, and a validation record. --- README.md | 10 + README.zh-CN.md | 10 + .../.minimax-plugin/plugin.json | 18 + plugins/hanewari/token-meter-board/LICENSE | 192 +++ plugins/hanewari/token-meter-board/README.md | 163 +++ .../token-meter-board/README.zh-CN.md | 163 +++ .../token-meter-board/docs/preview.png | Bin 0 -> 297624 bytes .../token-meter-board/docs/validation.md | 64 + plugins/hanewari/token-meter-board/icon.png | Bin 0 -> 1574 bytes .../miniapp/client/index.html | 1187 +++++++++++++++++ .../miniapp/client/vendor/LICENSE-chartjs.txt | 31 + .../miniapp/client/vendor/chart.umd.min.js | 20 + .../token-meter-board/miniapp/miniapp.json | 20 + .../miniapp/node/lib/common.mjs | 707 ++++++++++ .../miniapp/node/lib/db-child.mjs | 53 + .../miniapp/node/lib/facts.mjs | 210 +++ .../miniapp/node/lib/queries.mjs | 454 +++++++ .../miniapp/node/lib/trend.mjs | 247 ++++ .../miniapp/node/miniapp-api.ts | 109 ++ .../token-meter-board/miniapp/node/server.mjs | 306 +++++ .../hanewari/token-meter-board/package.json | 6 + 21 files changed, 3970 insertions(+) create mode 100644 plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json create mode 100644 plugins/hanewari/token-meter-board/LICENSE create mode 100644 plugins/hanewari/token-meter-board/README.md create mode 100644 plugins/hanewari/token-meter-board/README.zh-CN.md create mode 100644 plugins/hanewari/token-meter-board/docs/preview.png create mode 100644 plugins/hanewari/token-meter-board/docs/validation.md create mode 100644 plugins/hanewari/token-meter-board/icon.png create mode 100644 plugins/hanewari/token-meter-board/miniapp/client/index.html create mode 100644 plugins/hanewari/token-meter-board/miniapp/client/vendor/LICENSE-chartjs.txt create mode 100644 plugins/hanewari/token-meter-board/miniapp/client/vendor/chart.umd.min.js create mode 100644 plugins/hanewari/token-meter-board/miniapp/miniapp.json create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/miniapp-api.ts create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/server.mjs create mode 100644 plugins/hanewari/token-meter-board/package.json diff --git a/README.md b/README.md index 9298aab0..1eb53358 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ The MiniMax Code Agent communicates through the host MCP client. Business reques | [AI Office](plugins/cristinamadureira353-svg/ai-office/) | Manage five model-powered employees in a pixel office: client tasks, chats, breaks, meetings and quota-aware offline states; uses your own API keys | [最爱双皮奶](https://github.com/cristinamadureira353-svg) | | [Token Usage Board](plugins/amszuidas/mcode-token-usage-board/) | Explore local Token usage by date, model, and session, including input, output, and cache usage | [amszuidas](https://github.com/amszuidas) | | [Token Usage Board](plugins/yanhy2000/mcode-usage-monitor/) | Watch local Token usage, output speed, and cache hit rate in near real time; filter by time range, model, and session | [yanhy2000](https://github.com/yanhy2000) | +| [Token Meter Board](plugins/hanewari/token-meter-board/) | Live local Token usage with a per-call ledger, turn-level conversations, and output speed on the same basis as the client UI; reads the runtime's own usage table and logs, no Python | [HaneWari](https://github.com/HaneWari) | | [Model Manager](plugins/ocoomber/openrouter-model-manager/) | Browse, search, and enable/disable models in your `~/.minimax/config.yaml` with instant save, bulk actions, one-click undo, and automatic backups | [ocoomber](https://github.com/ocoomber) | | [Self-drive Route Planner](plugins/hanzijie/self-drive-route-planner/) | **Official plugin** for planning driving routes with place search, route alternatives, demo mode, and Xiaohongshu 3:4 itinerary cards | [HanZijie](https://github.com/HanZijie) | | [Git Commit Tree](plugins/microbiosis/git-tree/) | Inspect a local Git repo's commit history with a swim-lane graph, branches/tags, commit detail, and per-file change stats; persisted filter preferences and optional auto-refresh | [Microbiosis](https://github.com/Microbiosis) | @@ -94,6 +95,15 @@ The preview uses synthetic data. The app interface is currently in Chinese. See +
+Preview: Token Meter Board + +![Token Meter Board showing usage trends with synthetic data](plugins/hanewari/token-meter-board/docs/preview.png) + +The preview uses synthetic data. The app interface is currently in Chinese. See its [README](plugins/hanewari/token-meter-board/README.md) for data access, counting rules, and compatibility notes. + +
+
Preview: Git Commit Tree diff --git a/README.zh-CN.md b/README.zh-CN.md index 17946852..fb92e15d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -62,6 +62,7 @@ MiniMax Code Agent 通过宿主 MCP 客户端与 MiniApp 协作。业务请求 | [AI 事务所](plugins/cristinamadureira353-svg/ai-office/README.zh-CN.md) | 五位真实模型员工的像素事务所:接单、聊天、休息和开会,额度耗尽时角色暂停;使用玩家自己的 API Key | [最爱双皮奶](https://github.com/cristinamadureira353-svg) | | [Token 用量看板](plugins/amszuidas/mcode-token-usage-board/README.zh-CN.md) | 按时间、模型和会话查看本机 Token 用量,包含输入、输出和缓存用量 | [amszuidas](https://github.com/amszuidas) | | [Token 用量看板](plugins/yanhy2000/mcode-usage-monitor/README.zh-CN.md) | 近实时查看本机 Token 用量、输出速度与缓存命中率,可按时间范围、模型和会话筛选 | [yanhy2000](https://github.com/yanhy2000) | +| [Token 仪表盘](plugins/hanewari/token-meter-board/README.zh-CN.md) | 本机 Token 用量实时看板:逐次调用台账、对话明细(turn 级)、与客户端界面同口径的输出速率;直读运行时用量表与观测日志,无需 Python | [HaneWari](https://github.com/HaneWari) | | [模型管理器](plugins/ocoomber/openrouter-model-manager/README.zh-CN.md) | 浏览、搜索并启用/停用 `~/.minimax/config.yaml` 中的模型,支持即时保存、批量操作、一键撤销和自动备份 | [ocoomber](https://github.com/ocoomber) | | [自驾规划](plugins/hanzijie/self-drive-route-planner/README.zh-CN.md) | 【官方插件】规划自驾路线、地点搜索、候选算路与小红书 3:4 行程图;支持演示模式 | [HanZijie](https://github.com/HanZijie) | | [Git 提交树](plugins/microbiosis/git-tree/README.zh-CN.md) | 查看本机 Git 仓库的提交历史:泳道提交图、分支/标签、提交详情与文件改动统计,支持筛选偏好持久化与可选自动刷新 | [Microbiosis](https://github.com/Microbiosis) | @@ -94,6 +95,15 @@ MiniMax Code Agent 通过宿主 MCP 客户端与 MiniApp 协作。业务请求
+
+预览:Token 仪表盘 + +![Token 仪表盘,使用合成数据展示用量趋势](plugins/hanewari/token-meter-board/docs/preview.png) + +预览使用合成数据,应用界面目前为中文。数据访问范围、统计口径和兼容性说明见作品 [README](plugins/hanewari/token-meter-board/README.zh-CN.md)。 + +
+
预览:Git 提交树 diff --git a/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json b/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json new file mode 100644 index 00000000..99d53428 --- /dev/null +++ b/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json @@ -0,0 +1,18 @@ +{ + "schemaVersion": 1, + "name": "token-meter-board", + "displayName": "Token 仪表盘", + "version": "1.9.0", + "description": "本机 MiniMax Code 的实时 token 用量仪表盘:用量趋势、逐次调用台账、每轮对话明细、缓存命中率与输出速率。输出速率采用与产品内界面一致的 Σ输出 ÷ Σdecode 时间加权口径,并附 P50/P90 供分布参考。除本地内置的 Chart.js 外无第三方依赖,全程只读本机数据、不出网。", + "author": "HaneWari", + "icon": "icon.png", + "category": "Code", + "exampleQueries": [ + "打开 Token 仪表盘", + "查看我的模型用量趋势", + "哪个自定义模型的缓存命中率最高?" + ], + "apps": [], + "mcpServers": [], + "skills": [] +} diff --git a/plugins/hanewari/token-meter-board/LICENSE b/plugins/hanewari/token-meter-board/LICENSE new file mode 100644 index 00000000..82538ec5 --- /dev/null +++ b/plugins/hanewari/token-meter-board/LICENSE @@ -0,0 +1,192 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + Copyright 2026 HaneWari + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/plugins/hanewari/token-meter-board/README.md b/plugins/hanewari/token-meter-board/README.md new file mode 100644 index 00000000..aa928819 --- /dev/null +++ b/plugins/hanewari/token-meter-board/README.md @@ -0,0 +1,163 @@ +# Token Meter Board + +English | [简体中文](README.zh-CN.md) + +A near-real-time token-usage dashboard for MiniMax Code, running entirely on your own machine. It reads the runtime's own per-call ledger and observability logs, so the numbers it shows are the ones the client actually recorded — not an estimate reconstructed from transcript files. + +Author: [HaneWari](https://github.com/HaneWari) · Version: `1.9.0` · License: [Apache-2.0](LICENSE) + +![Token Meter Board, synthetic data](docs/preview.png) + +*The preview uses synthetic sessions and usage data. The app interface is currently in Chinese.* + +## What you get + +- **Usage trend** — stacked bars per model, with the cache-hit-rate and output-speed curves drawn on top. Buckets adapt from minutes to hours to days as the window grows. +- **Five detail tables** — per-model breakdown, daily totals, a 12-column **per-call ledger**, a **conversation (turn) table**, and a session ranking. +- **Conversation detail** — one row per question you asked. The row shows your own message text, the outcome, wall-clock duration, how many model calls the turn took, the tokens, and the rate. A turn that is still running is marked as unfinished and grows live — you do **not** have to close the session first. +- **Per-call ledger** — every single model call with its exact timestamp, model, all five token classes, output speed, whole-request speed, decode duration, request duration, and status code. +- **Time windows** — last hour / today / last 7 days / last 30 days, or any custom start and end. The time bar is laid out in two rows so the native date picker can never cover the *Apply* button, and pressing Enter inside a time field applies the window too. +- **5-second auto refresh** with a manual refresh button. Switching a window never blanks the tables and never waits: the previous window stays on screen until the new values arrive, and a late response from an older window is discarded rather than overwriting the newer one. + +## Why this one + +Most token boards answer "how much did I spend". This one also answers "where did it go, and is the number I am looking at the number the client shows?". + +- **It reads the ledger, not the transcripts.** Numbers come from the runtime's own per-call usage table plus the observability logs, not from reconstructing usage out of session transcript files. A transcript file carries one aggregate usage block per assistant message and no timing information at all, so a board that reads it cannot see the calls that are missing from the transcripts — and it can never show a per-call speed, because the transcript has no timings. Measured on a reference machine against a transcript-based board, that board reported about **48% fewer calls and 66% fewer cache-read tokens** overall, and the gap swung between **0% and 98% from day to day**. The cause is not a per-message aggregation rule: some sessions leave no transcript file at all, and a transcript-based board simply cannot see them. +- **The output speed matches the client.** Output speed is `Σ output tokens ÷ Σ decode duration` — the decode phase only, from the first token to the end of the stream — which is the same basis the MiniMax Code interface uses. The whole-request speed is shown next to it as a comparison column, so you can see how much of each call was spent waiting for the first token. A speed computed over the whole request instead reports a number roughly **1.6–2.1× lower** and does not line up with the interface. +- **Every call is matched to its own timings.** The board pairs each usage row with the assistant message that carries that call's decode and request durations. It does not match by nearest timestamp and it does not match by position: both go wrong as soon as one turn contains an assistant row that is not a model call (context compaction writes one), which shifts the whole turn. The pairing rule used here was verified against a token-signature ground truth over 16,723 calls with **zero** mismatches. +- **Totals add up to five terms.** `total = input + output + reasoning + cacheRead + cacheWrite`. Boards that stop at three terms silently drop cache writes and reasoning tokens. +- **Turn-level granularity.** One question becomes one row, with the call count and the tokens that question actually cost. Nothing has to be closed or archived first. +- **No Python, no extra process, no dependency.** Pure Node, no third-party runtime code except a vendored copy of Chart.js. Another board in this ecosystem requires Python 3.8+ and spawns a Python process per query. +- **Milliseconds, not seconds.** After the caching rework in v1.7.0 a full page refresh went from ~8.5 s to tens of milliseconds. On a reference machine with a ~17,000-row message table, a full page refresh takes ~50 ms, switching to a 7-day window ~40 ms, and the first query in a fresh process ~1.3 s (it has to scan the message table once). +- **Strictly read-only.** The Mini App writes nothing, sends nothing, and has no telemetry. No account, no API key, no configuration. + +## How this compares with the other token boards + +The Mini App gallery already lists two token boards. They are good at what they do, and they solve a slightly different problem: + +| | Token Meter Board (this one) | `mcode-token-usage-board` | `mcode-usage-monitor` | +| --- | --- | --- | --- | +| Source of truth | Runtime usage table + observability logs | Session transcript files (`messages.jsonl`) | Runtime database, read through Python 3.8+ | +| Per-call timings | Yes — decode, request, status code per call | No — transcripts carry no timings | Partly — per-request speed | +| Per-call ledger | Yes, 12 columns | No | Recent requests | +| Conversation (turn) table with your own words | Yes | No | No | +| Needs Python | No | No | Yes | +| Extra process per query | No | No | Yes | +| Auto refresh | 5 s | 60 s | 5 s / 10 s / 30 s | +| Layout | Fixed, dense | Fixed | Draggable, user-editable card layout | + +The practical difference: if you want to know **where the tokens went in a specific conversation**, or to audit **one specific call** (its decode duration, its request duration, its HTTP status), only this board shows it — and it can do so without re-deriving anything from transcript files. If you prefer a freely rearrangeable card layout, `mcode-usage-monitor` is the one to look at. + +## Install + +Copy this entire directory into the MiniMax Code data directory. By default `` is `.minimax` in your home folder (`~/.minimax`), so the default path is: + +```text +/plugins/token-meter-board/ +``` + +| System | Target path | +| --- | --- | +| Windows | `C:\Users\\.minimax\plugins\token-meter-board` | +| macOS | `/Users//.minimax/plugins/token-meter-board` | +| Linux | `/home//.minimax/plugins/token-meter-board` | + +Keep the hidden `.minimax-plugin` directory — the plugin is recognised by it. If you set a custom data directory (`MINIMAX_DATA_DIR`), use that directory's `plugins/` folder instead. + +Restart MiniMax Code, confirm the plugin is enabled, then open **Token 仪表盘** (Token Meter Board), or just ask the Agent to open it. + +## Use it + +Pick a window (preset or custom), and read the trend, the KPI strip, and the five tables below it. Model chips filter the charts and tables; the sessions ranking and the daily table have their own independent range selectors, so changing the main window never disturbs them. The page refreshes every 5 seconds, and the refresh button forces an immediate reload. + +Example prompts, and what you get back: + +- **"打开 Token 仪表盘"** → the dashboard opens on the current window. +- **"查看我的模型用量趋势"** → the trend chart with the per-model stacked bars, the cache-hit-rate curve and the output-speed curve. +- **"哪个自定义模型的缓存命中率最高?"** → the per-model table with the cache hit rate per provider and model. + +The board also offers **让 Agent 分析此窗口** (let the Agent analyse this window): it appends the current window's totals, call count, cache hit rate and output speed to the chat input so you can ask follow-up questions about the same numbers you were just looking at. + +## Data & access + +**Files read (read-only, never modified):** + +| Path | Used for | +| --- | --- | +| `/v2/sqlite/runtime-state.sqlite` | The per-call usage ledger and the assistant/user message rows (decode timings, finish reason, message text). Opened with `node:sqlite` in read-only mode. | +| `/v2/observability/logs/runtime-*.log` | Provider, model, and response status, correlated per turn. The usage table itself does not store the model name, so the logs are what make custom (BYOK) providers show up as themselves instead of "unknown". | +| `/config.yaml` | Provider and model display names, so the tables read "MiniMax-M3.1-Flash" rather than a raw id. | + +The location is resolved from the Host-provided `context.dataDir` (the active MiniMax Code data directory), falling back to `~/.minimax`. **These paths and the column layout of the runtime database are not a published API** — they are the client's internal storage, so a future client release may change them. When that happens the board shows an explicit error instead of an empty dashboard. + +**What the page displays.** The dashboard renders real local data, which means a screenshot of it can contain: + +- **Your own message text** — the conversation table shows the first **200 characters** of each turn's user message. The full text is never loaded: it is truncated inside the database query, so it never enters the app's memory and never reaches the browser. +- **Session titles and session ids**, and the **absolute workspace path** of each session (shown in the session ranking's tooltip). +- **Model and provider names**, including the names of your own custom (BYOK) providers. + +Everything stays on the machine and on the page. If you plan to share a screenshot, remember that your own questions and your local folder names are in it. + +**Nothing is written.** No files are created or modified, no data leaves the machine, and there is no telemetry. The only cache lives in the process memory of the running Mini App. The page stores exactly one thing in your browser's `localStorage`: the theme choice, under the key `tmb-theme`. Nothing else is persisted. + +**Network:** none. The Mini App serves one page on `127.0.0.1` and answers its own API routes. It never contacts a remote host, and it makes no request other than to its own origin. The query parameters it accepts are an explicit allow-list per endpoint — anything else, including anything that looks like a data-directory override, is dropped before the query runs. + +**Subprocess:** normally none. If the host's Node runtime does not expose `node:sqlite`, the Mini App re-runs the identical read-only queries in a child process. It first tries `node` from `PATH`, and only if that executable does not exist does it fall back to the runtime's own executable launched with `ELECTRON_RUN_AS_NODE=1`. The query mode and parameters are passed as an argv array — never through a shell — and the child prints one JSON document on stdout and exits. + +**Node.js:** the in-process path needs `node:sqlite`, which is unflagged from Node.js 23.4. The bundled runtime used for testing is Node.js v24.18.0. If neither the in-process runtime nor the child process has it, the board reports the requirement instead of failing silently. + +## Metrics + +| Metric | Definition | +| --- | --- | +| Total tokens | `input + output + reasoning + cacheRead + cacheWrite` | +| Cache hit rate | `cacheRead / (cacheRead + input)` — the share of the prompt that came from cache. Cache writes are not in the denominator. | +| Output speed | `Σ output tokens ÷ Σ decode duration`, weighted by time. Single call: `output tokens ÷ decode duration` (first token → end of stream). P50 and P90 are shown alongside. | +| Whole-request speed | `output tokens ÷ request_duration_ms` (request sent → end of stream). The difference against output speed is the first-token wait and queueing. | +| Conversation (turn) | One user message plus however many model calls the agent needed before answering. Duration is wall-clock span and is shown for information only; it does not enter the rate calculation. | + +Calls whose decode duration exceeds the request duration are excluded from the speed aggregate (that combination means the first token arrived before the request was sent — a timestamp artefact that would otherwise inflate the denominator). They are still listed individually in the ledger. A turn that is still in flight is marked unfinished and its rate is computed from what has arrived so far. + +The client interface shows its own figure over its own live session. The board uses the same formula on a window you choose, so once the windows are not identical the two can differ by a fraction of a percent (0.3%–3.0% measured on a reference machine). + +## Tested environment + +- MiniMax Code Desktop **3.1.4** (build 186), Windows 11 (10.0.22631, x64) +- Bundled Node.js **v24.18.0**, `node:sqlite` available +- Verified in the desktop client: plugin install, window switching, custom start/end windows, per-call ledger, live turn growth, auto refresh, light and dark themes, and the error path when the runtime database is missing. +- macOS and Linux are **not** verified. Nothing in the code is platform-specific — the data paths are resolved from `context.dataDir` — but treat the other platforms as untested. + +The full validation record for this release — package checker result, the per-call pairing regression numbers, the injection test, and a same-machine performance A/B — is in [`docs/validation.md`](docs/validation.md). + +## Limitations + +- This is a **local observation tool**, not an invoice. Billing and quota are the product's own "usage" page, which is computed server-side and may catch up later. +- Numbers cover what the client recorded locally. Usage on another machine, or usage from a client that was never running locally, is not visible here. +- The runtime database and the observability log format are internal to the client and can change without notice. +- The client writes one aggregate usage block per assistant message into its transcript files, but the per-call usage table is the authoritative record used here. If the runtime ever stops writing a usage row for a call, that call cannot be shown. + +## Third-party components + +- [Chart.js](https://www.chartjs.org/) v4.4.3 — vendored at `miniapp/client/vendor/chart.umd.min.js` for offline use. MIT License, © Chart.js Contributors. The full licence text ships with the package at `miniapp/client/vendor/LICENSE-chartjs.txt`. + +## Source layout + +```text +miniapp/ + client/index.html The whole page: markup, styles, and the client script + client/vendor/ Chart.js (MIT), vendored for offline use + client/vendor/LICENSE-chartjs.txt Full MIT licence text for the vendored copy + node/server.mjs HTTP server, routing, and the subprocess fallback + node/lib/common.mjs Data-dir resolution, config catalog, log enrichment, metrics + node/lib/facts.mjs Incremental message-fact cache (SQL-side JSON extraction) + node/lib/queries.mjs Window, summary, session, daily, call, and turn queries + node/lib/trend.mjs Window resolution and bucketing + node/lib/db-child.mjs Query runner for the subprocess fallback +``` + +No build step is required: the page and the Node service are used as they are. + +## License + +[Apache-2.0](LICENSE) — see the file for the full text. The vendored Chart.js copy keeps its own MIT licence, reproduced in `miniapp/client/vendor/LICENSE-chartjs.txt`. diff --git a/plugins/hanewari/token-meter-board/README.zh-CN.md b/plugins/hanewari/token-meter-board/README.zh-CN.md new file mode 100644 index 00000000..74a8bf4c --- /dev/null +++ b/plugins/hanewari/token-meter-board/README.zh-CN.md @@ -0,0 +1,163 @@ +# Token 仪表盘 + +[English](README.md) | 简体中文 + +本机 MiniMax Code 的实时 token 用量看板。读的是运行时自己的**逐次调用台账**与观测日志,所以展示的就是客户端真实记录的数字,而不是从会话文件里反推出来的估算值。 + +作者:[HaneWari](https://github.com/HaneWari) · 版本:`1.9.0` · 许可证:[Apache-2.0](LICENSE) + +![Token 仪表盘,使用合成数据](docs/preview.png) + +*预览中的会话与用量均为合成数据。应用界面为中文。* + +## 能看到什么 + +- **用量趋势** —— 按模型堆叠的柱状图,缓存命中率与输出速率两条曲线叠绘在柱状图之上。窗口拉长时分桶自动从分钟级过渡到小时级、天级。 +- **五张明细表** —— 模型明细、每日统计、12 列的**逐次调用台账**、**对话明细(turn 级)**、会话用量排行。 +- **对话明细** —— 你每次提问占一行:用户消息原文、状态、挂钟时长、这一轮消耗了几次模型调用、五类 token、速率。**正在进行中的一轮会实时增长并标记为「未收尾」,无需关闭会话。** +- **逐次调用台账** —— 每一次模型调用都有一行:精确时间、模型、五类 token、输出速率、全程速率、decode 时长、请求全程、状态码。 +- **时间窗口** —— 近 1 小时 / 今天 / 近 7 天 / 近 30 天,或自定义起止时间。时间栏排成两行,保证原生日期选择器向下弹出时不会盖住「应用」按钮;在时间框里按 Enter 同样能应用。 +- **5 秒自动刷新**(也可手动点「刷新」)。切换窗口时旧数据留在屏幕上不空表,新值到达即替换;晚到的旧窗口响应会被丢弃,不会覆盖新窗口。 + +## 为什么是这一个 + +同类看板大多只回答「我花了多少」。这个看板同时回答「花到哪去了」,以及「我看到的这个数,是不是客户端自己显示的那个数」。 + +- **读台账,不读会话文件。** 数据来自运行时自己的逐次用量表和观测日志,而不是从会话记录文件里反推。会话记录文件里每条 assistant 消息只带一段汇总用量、且完全没有计时信息,所以读它的看板既看不到那些根本没写进会话文件的调用,也永远给不出「每一次调用」的速度——因为文件里没有计时。实测对照(参考机器,同机对比一款读会话文件的看板):它整体**少报约 48% 的调用、少报约 66% 的缓存读 token**,且按天在 **0%~98%** 之间剧烈波动。根因不是「一消息一聚合」这类统计规则,而是**部分会话根本没留下会话文件**,读文件的看板无从看到。 +- **输出速率与客户端同口径。** 输出速率取 `Σ输出 tokens ÷ Σdecode 时长` —— 只算首 token 到流结束的解码段,与 MiniMax Code 界面显示一致。全程速率作为对照列并排给出,可以直接看出每次调用有多少时间耗在等首 token 上。若改用请求全程计算,得到的数字会低约 **1.6~2.1 倍**,且与界面数字对不上。 +- **每次调用都配回自己的计时。** 看板把每条用量行与携带该次调用 decode / 请求全程时长的那条 assistant 消息配对,既不按时间就近匹配、也不按下标顺序匹配——这两种方式只要一个 turn 里混进一条「不是模型调用」的 assistant 行(上下文压缩就会写这种行)就会整轮错位。此处的配对规则已用 token 签名做真值、在 **16,723 次调用上逐条核对,错配 0 条**。 +- **总 token 算满五项。** `总 = 输入 + 输出 + 推理 + 缓存读 + 缓存写`。只算三项的看板会悄悄漏掉缓存写与推理 token。 +- **turn 级粒度。** 一次提问就是一行,带这一轮实际花掉的调用次数与 token,不需要等会话结束或归档。 +- **不装 Python、不起额外进程、无第三方依赖。** 纯 Node,除了一份本地化的 Chart.js 之外没有第三方运行时代码。同生态里另一款看板需要 Python 3.8+,并且每次查询都要拉起一个 Python 进程。 +- **毫秒级,不是秒级。** v1.7.0 的缓存重构之后,整页刷新从约 8.5 秒降到几十毫秒。在 1.7 万行消息表的参考机器上:整页刷新约 **50 毫秒**,切到 7 天窗口约 **40 毫秒**,全新进程里的第一次查询约 **1.3 秒**(那次必须把消息表扫一遍)。 +- **严格只读。** 不写任何文件、不发任何请求、无遥测。无需账号、无需 API Key、无需任何配置。 + +## 与另外两款 token 看板的差别 + +官方 Mini App 目录里已经收录了两款 token 看板,各有所长,解决的也略有不同: + +| | Token 仪表盘(本款) | `mcode-token-usage-board` | `mcode-usage-monitor` | +| --- | --- | --- | --- | +| 数据来源 | 运行时用量表 + 观测日志 | 会话记录文件(`messages.jsonl`) | 运行时数据库,经 Python 3.8+ 读取 | +| 逐次调用计时 | 有 —— 每次调用的 decode、请求全程、状态码 | 无 —— 会话文件里没有计时 | 部分有 —— 每次请求的速度 | +| 逐次调用台账 | 有,12 列 | 无 | 只有近期请求列表 | +| 带用户原文的对话(turn)明细 | 有 | 无 | 无 | +| 需要 Python | 否 | 否 | 是 | +| 每次查询另起进程 | 否 | 否 | 是 | +| 自动刷新 | 5 秒 | 60 秒 | 5 秒 / 10 秒 / 30 秒 | +| 布局 | 固定、信息密集 | 固定 | 可拖拽重排的卡片布局 | + +实际差别在于:如果你想知道**某一次具体对话的 token 花在哪**,或者要**核对某一次具体调用**(它的 decode 时长、请求全程、HTTP 状态码),只有本款看板能给——而且不必再去从会话文件里反推。若你更看重自由重排的卡片布局,那 `mcode-usage-monitor` 更合适。 + +## 安装 + +把整个目录复制到 MiniMax Code 数据目录下。默认 `` 是用户主目录下的 `.minimax`(即 `~/.minimax`),默认路径为: + +```text +/plugins/token-meter-board/ +``` + +| 系统 | 目标路径 | +| --- | --- | +| Windows | `C:\Users\<用户名>\.minimax\plugins\token-meter-board` | +| macOS | `/Users/<用户名>/.minimax/plugins/token-meter-board` | +| Linux | `/home/<用户名>/.minimax/plugins/token-meter-board` | + +复制时不要漏掉隐藏的 `.minimax-plugin` 目录 —— 插件靠它被识别。若设置了自定义数据目录(`MINIMAX_DATA_DIR`),请放进该目录的 `plugins/` 下。 + +装完重启 MiniMax Code,确认插件已启用,然后打开 **Token 仪表盘**,或在对话里让 Agent 打开。 + +## 使用 + +选一个时间窗口(预设或自定义),然后看趋势图、KPI 与下方五张表。模型 chips 可同时筛选图表与表格;会话排行与每日统计各自带独立的时间范围选择器,改主窗口不会牵连它们。页面每 5 秒自动刷新,也可手动点「刷新」。 + +示例提问与对应结果: + +- **「打开 Token 仪表盘」** → 直接打开当前窗口的看板。 +- **「查看我的模型用量趋势」** → 按模型堆叠的趋势图,含缓存命中率曲线与输出速率曲线。 +- **「哪个自定义模型的缓存命中率最高?」** → 模型明细表,逐 provider / 模型给出缓存命中率。 + +看板还带一个 **「让 Agent 分析此窗口」** 按钮:把当前窗口的总量、调用次数、缓存命中率与输出速率填进聊天输入框,你可以对着刚看过的同一份数字继续追问。 + +## 数据与访问 + +**读取的文件(只读,绝不修改):** + +| 路径 | 用途 | +| --- | --- | +| `/v2/sqlite/runtime-state.sqlite` | 逐次调用用量台账,以及 assistant / user 消息行(decode 计时、结束原因、消息原文)。用 `node:sqlite` 以只读模式打开。 | +| `/v2/observability/logs/runtime-*.log` | provider、模型与响应状态,按 turn 关联。用量表本身不存模型名,日志正是自定义(BYOK)provider 能显示成自己的名字而不是 "unknown" 的原因。 | +| `/config.yaml` | provider 与模型的显示名,让表格显示 "MiniMax-M3.1-Flash" 而不是内部 id。 | + +路径由 Host 注入的 `context.dataDir`(当前 MiniMax Code 数据目录)解析,缺失时回退到 `~/.minimax`。**这些路径和运行时数据库的表结构都不是公开 API**,属于客户端内部存储,未来版本可能变化。真发生变化时看板会给出明确报错,而不是给你一张空表。 + +**页面上会显示什么。** 看板渲染的是本机真实数据,所以一张截图里可能包含: + +- **你自己提问的原文** —— 对话明细会显示每一轮用户消息的**前 200 字**。原文不会被完整读取:截断发生在数据库查询内部,原文既不进入应用内存,也不会传到浏览器。 +- **会话标题与会话 id**,以及每个会话的**工作区绝对路径**(显示在会话排行的悬浮提示里)。 +- **模型与 provider 名称**,包含你自己接入的自定义(BYOK)provider 名称。 + +这些内容都留在本机与这个页面上。若打算分享截图,请记得里面也有你自己的提问和本机目录名。 + +**不写任何东西。** 不创建也不修改文件,数据不出本机,无遥测。缓存只存在于 Mini App 进程的内存里。浏览器 `localStorage` 里只存一样东西:主题选择,键名 `tmb-theme`。此外不落任何数据。 + +**网络:** 无。Mini App 只在 `127.0.0.1` 上提供一个页面并响应自己的 API 路由,从不访问任何远端主机,除自身源外不发起任何请求。API 接受的查询参数是**逐端点白名单**:其余参数(含任何试图指定数据目录的参数)在进入查询前就会被丢弃。 + +**子进程:** 通常没有。若宿主 Node 运行时没有暴露 `node:sqlite`,Mini App 会用子进程重跑完全相同的只读查询:先尝试 `PATH` 上的 `node`,只有该可执行文件不存在时才回退到用 `ELECTRON_RUN_AS_NODE=1` 拉起自身可执行文件。查询模式与参数以 argv 数组传入,**绝不经过 shell**;子进程向 stdout 输出一个 JSON 文档后退出。 + +**Node.js:** 进程内路径需要 `node:sqlite`(Node.js 23.4 起不再需要 flag)。测试时随附的运行时是 Node.js v24.18.0。若进程内运行时与子进程都没有它,看板会明确报出这个要求,而不是静默失败。 + +## 指标口径 + +| 指标 | 定义 | +| --- | --- | +| 总 tokens | `输入 + 输出 + 推理 + 缓存读 + 缓存写` | +| 缓存命中率 | `缓存读 ÷ (缓存读 + 输入)`,即提示词中命中缓存的比例;缓存写不计入分母。 | +| 输出速率 | `Σ输出 tokens ÷ Σdecode 时长`,按耗时加权。单次调用为 `输出 tokens ÷ decode 时长`(首 token → 流结束),并附 P50 / P90。 | +| 请求全程速率 | `输出 tokens ÷ request_duration_ms`(发起请求 → 流结束)。与输出速率的差值即首字等待与排队。 | +| 对话明细(turn) | 一条用户消息 + 模型为给出回答所需的若干次调用。时长为挂钟跨度,仅作展示,不参与速率计算。 | + +decode 时长超过请求时长的调用不计入速率聚合(这种组合等价于首 token 早于请求发起,属于时间戳异常,留着会灌大分母),但仍会逐条列在台账里。进行中的 turn 标记为「未收尾」,速率按已到达的部分计算。 + +客户端界面显示的是它自己那一段实时会话上的数字;看板用同一套公式算你选定的窗口,所以两边窗口不一致时会有千分之几的差异(参考机器实测 0.3%~3.0%)。 + +## 已验证环境 + +- MiniMax Code 桌面端 **3.1.4**(build 186),Windows 11(10.0.22631,x64) +- 随附 Node.js **v24.18.0**,`node:sqlite` 可用 +- 已在桌面端验证:插件安装、窗口切换、自定义起止时间、逐次调用台账、对话明细实时增长、自动刷新、明暗双主题,以及运行时数据库缺失时的报错路径。 +- macOS 与 Linux **未验证**。代码里没有平台相关逻辑(数据路径由 `context.dataDir` 解析),但请把其他平台视为未测。 + +本版的完整验收记录——包检查结果、逐次配对的回归数字、注入复测,以及同机性能 A/B——见 [`docs/validation.md`](docs/validation.md)。 + +## 局限 + +- 这是**本地观测工具,不是账单**。计费与额度以产品内「用量」页为准,那个数字来自服务端统计,可能存在延迟。 +- 这里只覆盖客户端在本机记录到的用量。在别的机器上、或客户端从未在本机运行过的用量,这里看不到。 +- 运行时数据库与观测日志的格式是客户端内部实现,可能随时变化。 +- 客户端会往会话文件里写每条 assistant 消息的汇总用量,但逐次用量表才是这里的权威来源。若运行时某次调用没写用量行,那次调用就无法呈现。 + +## 第三方组件 + +- [Chart.js](https://www.chartjs.org/) v4.4.3 —— 本地化打包在 `miniapp/client/vendor/chart.umd.min.js` 以便离线使用。MIT 许可证,© Chart.js Contributors。许可证全文随包附带在 `miniapp/client/vendor/LICENSE-chartjs.txt`。 + +## 源码结构 + +```text +miniapp/ + client/index.html 整个页面:结构、样式与前端脚本 + client/vendor/ 本地打包的 Chart.js(MIT) + client/vendor/LICENSE-chartjs.txt 本地这份 Chart.js 的 MIT 许可证全文 + node/server.mjs HTTP 服务、路由与子进程回退 + node/lib/common.mjs 数据目录解析、config 目录、日志增强、指标计算 + node/lib/facts.mjs 增量消息事实缓存(SQL 侧 JSON 提取) + node/lib/queries.mjs 窗口、汇总、会话、每日、调用与 turn 查询 + node/lib/trend.mjs 窗口解析与分桶 + node/lib/db-child.mjs 子进程回退用的查询执行器 +``` + +无需构建:页面与 Node 服务直接使用。 + +## 许可证 + +[Apache-2.0](LICENSE) —— 全文见文件。本地打包的 Chart.js 保留其自身的 MIT 许可证,全文见 `miniapp/client/vendor/LICENSE-chartjs.txt`。 diff --git a/plugins/hanewari/token-meter-board/docs/preview.png b/plugins/hanewari/token-meter-board/docs/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..427102002aa7e129040fb73f31319c9df877cbcc GIT binary patch literal 297624 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Ⱦ>KyZ}twQ9s}iy1Je$~0O+J@tNM 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%0D`&3^R(bHwp<@s?XR31(|GQtR(hzO6A=u<8R9 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 literal 0 HcmV?d00001 diff --git a/plugins/hanewari/token-meter-board/docs/validation.md b/plugins/hanewari/token-meter-board/docs/validation.md new file mode 100644 index 00000000..47cc64ca --- /dev/null +++ b/plugins/hanewari/token-meter-board/docs/validation.md @@ -0,0 +1,64 @@ +# 验收说明 / Validation notes + +本页记录本包提交官方 Mini App 市场前的自检结果,供审阅者复核。所有数字均来自本机实测。 + +## 包检查(官方校验器) + +用官方仓 `MiniMax-AI/MiniMax-Code-MiniApps` 的 `scripts/validate.mjs` 直接检查本包目录: + +```text +token-meter-board: 0 errors, 1 warning + warning ENTRY_STDOUT writes to stdout, which belongs to the Host; log through context.logger instead (miniapp/node/lib/db-child.mjs) +``` + +**关于 `ENTRY_STDOUT` 这条 warning**:它命中的是 `miniapp/node/lib/db-child.mjs`,而不是 Host 的入口 `miniapp/node/server.mjs`。该文件是我们自己 spawn 出来的子进程执行器(宿主运行时没有 `node:sqlite` 时才走这条路),它把查询结果写进 stdout,**父进程从这条管道读回来**——是父子进程之间的 IPC,不是宿主进程的输出通道;宿主的入口从未写 stdout(校验器对入口的判定是 error 级,此处并未触发)。 + +校验器的规则是静态扫描:`/\b(?:console\.(?:log|info|debug|dir|table)|process\.stdout\.write)\s*\(/u`,无法区分「宿主入口的 stdout」与「我们自己拉起的子进程的 stdout」。因此这条 warning 属于**可解释的误报**,按官方仓既有的处理方式(参见 `plugins/webguhui/minimax-photo/docs/validation.md`)**保留并在此说明,不修改检查器、也不隐藏代码**。该子进程路径在有 `node:sqlite` 的运行时里不会启用。 + +## 回归测试 + +对照 `assistant` 消息的 `usage.{input_tokens,output_tokens,cache_read}` 与用量行 `raw` 同名字段建立**无歧义配对真值**,再逐条核对看板给出的每次调用的 decode / 请求全程时长: + +| 窗口 | 核对调用数 | 错配 | +| --- | --- | --- | +| 近 30 天 | 16787 | **0** | +| 近 7 天 | 11043 | **0** | +| 今天 | 1701 | **0** | +| 窗口起点落在某个 turn 中段 | 6515 | **0** | + +修复前的同口径测量为:按下标配对错配 **22.5%**(3770/16723),即每 4~5 次调用就有 1 次显示的是**上一通**的 decode 与速率。 + +状态码匹配同法核对:日志行在用量行之后落盘,按时间就近匹配会落到上一通的日志行(实测 2220 次失手**全部**偏上一通);改为取「该 turn 中第一条时刻不早于本次调用起点的日志行」后,可判定的 10124 条**命中率 100%**。 + +其余逐条通过的项目: + +- **`dataDir` 注入**:`/api/*` 传入 `?dataDir=<他处路径>` 后返回的仍是宿主数据目录的数据(调用数、输出 token 逐字段一致);紧接着发出的、不带 `dataDir` 的正常请求也未被污染;`/api/health` 报告的 `dataDir` 仍是宿主目录。全部 7 个端点逐个比对,注入前后响应完全一致。 +- **对话明细计数**:`counts`(已完成 / 未收尾 / 进行中)之和等于 `totalTurns`,在 `days=7/limit=50`、`days=30/limit=10`、`days=1/limit=500` 三种组合下均成立(修复前只统计被 `limit` 截断后的部分)。 +- **用户消息预览**:全部 ≤ 200 字(库内原文最长 52262 字),截断在 SQL 内完成,原文不进入应用内存。 + +## 性能 + +同机同法 A/B(同一台机器交替运行 v1.8.0 与 v1.9.0,各端点连续 5 次取中位数、缓存已热): + +| 场景 | v1.8.0 | v1.9.0 | +| --- | --- | --- | +| 冷启动(进程内首次查询) | 1279 ms | 1350 ms | +| `/api/window?days=1` | 9 ms | **8 ms** | +| `/api/window?days=7` | 57 ms | **41 ms** | +| `/api/window?days=30` | 65 ms | **59 ms** | +| `/api/calls?days=1` | 4 ms | **3 ms** | +| `/api/turns?days=1` | 5 ms | **3 ms** | +| `/api/sessions?days=30` | 24 ms | **20 ms** | +| `/api/daily?days=7` | 19 ms | **17 ms** | +| 整页刷新(页面发出的 5 个请求) | 55 ms | **51 ms** | + +各项持平或略快,无退化。冷启动 +5% 来自消息事实扫描里多做的两次 JSON 取值(判断该行是否为模型调用、对用户消息做 `substr` 截断);冷启动本身随机器负载在 0.9~1.4 s 之间浮动。 + +## 已验证环境 + +- MiniMax Code 桌面端 **3.1.4**(build 186),Windows 11(10.0.22631,x64) +- 随附 Node.js **v24.18.0**,`node:sqlite` 可用 +- 已在桌面端验证:插件安装、窗口切换、自定义起止时间、逐次调用台账、对话明细实时增长、自动刷新、明暗双主题,以及运行时数据库缺失时的报错路径 +- macOS 与 Linux **未验证**:代码里没有平台相关逻辑(数据路径由 `context.dataDir` 解析),但请把其他平台视为未测 + +`docs/preview.png` 使用合成数据实拍,界面为中文。 diff --git a/plugins/hanewari/token-meter-board/icon.png b/plugins/hanewari/token-meter-board/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..299a26cbf5c1427dffa9cd575cf721307d570765 GIT binary patch literal 1574 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrV7=|>;uumf=gr;N9Fb5F_7BDH zN*t40jx3m@A#jD`h{82~A;W#9hIKB=6V;QM-fp_!Iw3Du_^7z>7spdwD|5UT=(0U- z4vcs42{>&0A!&-l#UFng7Vv9zUfN`Qd~;|s@7+uz9O)JMQ;7Q z+VlNc*1f)P;(=w;neIK@5%Dq?bm#T^{r{9*@ia!gnj^~T2}4Q1*Th_Vu`>}GpIDCO z#4fN@Vt4rd)BClU(Q~fW#@QT3`o97jTK?xMOo;EM)AkEGZ>^la!>4}Tg|#orV!ID- z4G8cmi29Kul*I@Nov(+hUWIHbj*XAkN|#&6e?ev6^ZSxvcK?~yFA_-*H<;a0#(2g^ zzl72KdH~l2CW&?ibaY*)m{GcGsq4HCVQW8`+3MMAA9>%$$6x1gcEXjIh6=|UTHH*2 zPm^w)+0I})`*&FN5&Nu1Y+r6yc*L8(Sa9m$yrfKZ#~fa1&NHPdC8Y+RdyG?WF};29 zt~O0_E62oyX%mAzpJu)CiI9%EV`HT-k0aLM2a{@p^XrK&uP*%0esO=1w)UU=+zCGMvNmy= z|6P>ouW5@p2v)su`cxCfV?$ymt*7pfdX*%ncOdCuPzej4`!;F|NW(R z>9S1?D}6X`#NYh7GVkf}bgjz@`%TThovQS5e3ma}8>P8_foSNz|MS*u5I(ouy{)ZH zDAVlt_qYF?TCQcTsM{ODK6ko9)iJH7$x{Rh??u)A%=k6?)3WE!yQWM!akgaN_W!DX z-#&jmHN3X`^}*WR`-q(SpO3zY`t01fRdCqjHPcc83_B1GbPU2zNIsfpf)(T$7XRi5-O#h75#2n`^6HJMF!qC&lGw+h(&G*h? zk*k_rMVov+YqaeSTOYYZzjSt0F6+COd#ca&eqZ;_rtH&`lb%gyI!#lfHFBb5N}kls z$lZDCNY^>py$dH>z2A9YX;J*2GNpMejVH=I&vYJ{xB2|{X>r$mYq=dibJoiERAfK) zQ9W)K_T5@<--_8kB%7Wkzk0OuD!*pi4Mquhsb5FS-xaZWR zZ|9tq^y-Rf{wEFBD;u8QSW~|%f9dnxxlsofN1ZNZ>HPit!>su-YkBth3z|N4bh|s- zYxS08(KkMRy%ipDKxc+#k7En7+RrklI~Sdmo1bg6`PiN0n#CTy2vIV@izrM+Ju?Ht m|NpbhtN4MXJsYT)XJ&Z(ZtAoneFio_5e83JKbLh*2~7YK=FPVN literal 0 HcmV?d00001 diff --git a/plugins/hanewari/token-meter-board/miniapp/client/index.html b/plugins/hanewari/token-meter-board/miniapp/client/index.html new file mode 100644 index 00000000..0873ef04 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/client/index.html @@ -0,0 +1,1187 @@ + + + + + +Token 仪表盘 + + + + + +

+
+
+

Token 仪表盘

+
连接中…
+
+
+ + + + +
+
+ +
+
+
+ +
+ +
+
+
开始
+
→
+
结束
+ +
+ +
+ +
+
--
总 tokens
+
--
调用次数
+
--
缓存命中率
cacheRead / (cacheRead + input)
+
--tok/s
token 输出速率
中位数
+
--
活跃模型
+
+ +
+
+ +
+
+
用量构成
+
+ + +
+
+
+
+ +
加载中…
+
+
+
+
+
+ +
+
+
模型明细(当前窗口)
+
+
+ + + + + + +
提供商 / 模型调用输入输出缓存读缓存写总 tokens速率 (tok/s)命中率
加载中…
+
+ +
+ +
+
+
每日统计
+
+ +
+
+
+ + + + + + +
日期调用输入输出推理缓存读缓存写总 tokens速率 (tok/s)命中率主要模型
加载中…
+
+ +
+ +
+
+
调用日志(当前窗口)
+
+ +
+
+
+ + + + + + +
时间模型输入输出推理缓存读缓存写速率 (tok/s)全程速率decode请求全程状态码
加载中…
+
+ +
+ +
+
+
对话明细(每次提问)
+
+ +
+
+
+ + + + + +
开始时间用户消息状态时长调用输出总 tokens速率 (tok/s)命中率会话主要模型
加载中…
+
+ +
+ +
+
+
会话用量排行
+
+ + +
+
+
+ + + + + +
会话Agent调用总 tokens速率 (tok/s)命中率主要模型最后活动
加载中…
+
+ +
+ +
+ 口径:总 tokens = 输入 + 输出 + 推理 + 缓存读 + 缓存写;命中率 = 缓存读 / (缓存读 + 输入);输出速率 = 输出 tokens ÷ decode 时长(首 token 到流结束),与 MiniMax Code 界面显示完全一致,窗口内按耗时加权;调用日志另列请求全程速率(发起请求→流结束,含首字等待);对话明细以一次提问(turn)为单位,用户发出消息后模型经若干次调用直至给出最终回答即为一次,实时读取、无需关闭会话,其时长为挂钟跨度、不参与速率计算。数据来自本机 runtime 用量记录(sqlite + 日志按 turn 补全 + config.yaml 显示名),只读。 +
+
+
+ + + + diff --git a/plugins/hanewari/token-meter-board/miniapp/client/vendor/LICENSE-chartjs.txt b/plugins/hanewari/token-meter-board/miniapp/client/vendor/LICENSE-chartjs.txt new file mode 100644 index 00000000..69cb529a --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/client/vendor/LICENSE-chartjs.txt @@ -0,0 +1,31 @@ +MIT License + +Copyright (c) 2024 Chart.js Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- + +This file covers the vendored copy of Chart.js at +`miniapp/client/vendor/chart.umd.min.js` (Chart.js v4.4.3, obtained from the +`chart.js@4.4.3` npm distribution, file `dist/chart.umd.js`). + +Chart.js itself is not part of this project's own source; it is redistributed +unmodified under the terms above so that the Mini App works offline and without +installing anything. diff --git a/plugins/hanewari/token-meter-board/miniapp/client/vendor/chart.umd.min.js b/plugins/hanewari/token-meter-board/miniapp/client/vendor/chart.umd.min.js new file mode 100644 index 00000000..c0f9743e --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/client/vendor/chart.umd.min.js @@ -0,0 +1,20 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Original file: /npm/chart.js@4.4.3/dist/chart.umd.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! + * Chart.js v4.4.3 + * https://www.chartjs.org + * (c) 2024 Chart.js Contributors + * Released under the MIT License + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";var t=Object.freeze({__proto__:null,get Colors(){return Go},get Decimation(){return Qo},get Filler(){return ma},get Legend(){return ya},get SubTitle(){return ka},get Title(){return Ma},get Tooltip(){return Ba}});function e(){}const i=(()=>{let t=0;return()=>t++})();function s(t){return null==t}function n(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.slice(0,7)&&"Array]"===e.slice(-6)}function o(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}function a(t){return("number"==typeof t||t instanceof Number)&&isFinite(+t)}function r(t,e){return a(t)?t:e}function l(t,e){return void 0===t?e:t}const h=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:+t/e,c=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function d(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function u(t,e,i,s){let a,r,l;if(n(t))if(r=t.length,s)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;at,x:t=>t.x,y:t=>t.y};function v(t){const e=t.split("."),i=[];let s="";for(const t of e)s+=t,s.endsWith("\\")?s=s.slice(0,-1)+".":(i.push(s),s="");return i}function M(t,e){const i=y[e]||(y[e]=function(t){const e=v(t);return t=>{for(const i of e){if(""===i)break;t=t&&t[i]}return t}}(e));return i(t)}function w(t){return t.charAt(0).toUpperCase()+t.slice(1)}const k=t=>void 0!==t,S=t=>"function"==typeof t,P=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function D(t){return"mouseup"===t.type||"click"===t.type||"contextmenu"===t.type}const C=Math.PI,O=2*C,A=O+C,T=Number.POSITIVE_INFINITY,L=C/180,E=C/2,R=C/4,I=2*C/3,z=Math.log10,F=Math.sign;function V(t,e,i){return Math.abs(t-e)t-e)).pop(),e}function N(t){return!isNaN(parseFloat(t))&&isFinite(t)}function H(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function j(t,e,i){let s,n,o;for(s=0,n=t.length;sl&&h=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function et(t,e,i){i=i||(i=>t[i]1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const it=(t,e,i,s)=>et(t,i,s?s=>{const n=t[s][e];return nt[s][e]et(t,i,(s=>t[s][e]>=i));function nt(t,e,i){let s=0,n=t.length;for(;ss&&t[n-1]>i;)n--;return s>0||n{const i="_onData"+w(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function rt(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(ot.forEach((e=>{delete t[e]})),delete t._chartjs)}function lt(t){const e=new Set(t);return e.size===t.length?t:Array.from(e)}const ht="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function ct(t,e){let i=[],s=!1;return function(...n){i=n,s||(s=!0,ht.call(window,(()=>{s=!1,t.apply(e,i)})))}}function dt(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const ut=t=>"start"===t?"left":"end"===t?"right":"center",ft=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,gt=(t,e,i,s)=>t===(s?"left":"right")?i:"center"===t?(e+i)/2:e;function pt(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=J(Math.min(it(r,l,h).lo,i?s:it(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?J(Math.max(it(r,a.axis,c,!0).hi+1,i?0:it(e,l,a.getPixelForValue(c),!0).hi+1),n,s)-n:s-n}return{start:n,count:o}}function mt(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}class xt{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=ht.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,"progress")),n.length||(i.running=!1,this._notify(s,i,t,"complete"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}}var bt=new xt; +/*! + * @kurkle/color v0.3.2 + * https://github.com/kurkle/color#readme + * (c) 2023 Jukka Kurkela + * Released under the MIT License + */function _t(t){return t+.5|0}const yt=(t,e,i)=>Math.max(Math.min(t,i),e);function vt(t){return yt(_t(2.55*t),0,255)}function Mt(t){return yt(_t(255*t),0,255)}function wt(t){return yt(_t(t/2.55)/100,0,1)}function kt(t){return yt(_t(100*t),0,100)}const St={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},Pt=[..."0123456789ABCDEF"],Dt=t=>Pt[15&t],Ct=t=>Pt[(240&t)>>4]+Pt[15&t],Ot=t=>(240&t)>>4==(15&t);function At(t){var e=(t=>Ot(t.r)&&Ot(t.g)&&Ot(t.b)&&Ot(t.a))(t)?Dt:Ct;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const Tt=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function Lt(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Et(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function Rt(t,e,i){const s=Lt(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function It(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e>16&255,o>>8&255,255&o]}return t}(),Ht.transparent=[0,0,0,0]);const e=Ht[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}const $t=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const Yt=t=>t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055,Ut=t=>t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4);function Xt(t,e,i){if(t){let s=It(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=Ft(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function qt(t,e){return t?Object.assign(e||{},t):t}function Kt(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=Mt(t[3]))):(e=qt(t,{r:0,g:0,b:0,a:1})).a=Mt(e.a),e}function Gt(t){return"r"===t.charAt(0)?function(t){const e=$t.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=e[8]?vt(t):yt(255*t,0,255)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?vt(i):yt(i,0,255)),s=255&(e[4]?vt(s):yt(s,0,255)),n=255&(e[6]?vt(n):yt(n,0,255)),{r:i,g:s,b:n,a:o}}}(t):Bt(t)}class Zt{constructor(t){if(t instanceof Zt)return t;const e=typeof t;let i;var s,n,o;"object"===e?i=Kt(t):"string"===e&&(o=(s=t).length,"#"===s[0]&&(4===o||5===o?n={r:255&17*St[s[1]],g:255&17*St[s[2]],b:255&17*St[s[3]],a:5===o?17*St[s[4]]:255}:7!==o&&9!==o||(n={r:St[s[1]]<<4|St[s[2]],g:St[s[3]]<<4|St[s[4]],b:St[s[5]]<<4|St[s[6]],a:9===o?St[s[7]]<<4|St[s[8]]:255})),i=n||jt(t)||Gt(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=qt(this._rgb);return t&&(t.a=wt(t.a)),t}set rgb(t){this._rgb=Kt(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${wt(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):void 0;var t}hexString(){return this._valid?At(this._rgb):void 0}hslString(){return this._valid?function(t){if(!t)return;const e=It(t),i=e[0],s=kt(e[1]),n=kt(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${wt(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):void 0}mix(t,e){if(t){const i=this.rgb,s=t.rgb;let n;const o=e===n?.5:e,a=2*o-1,r=i.a-s.a,l=((a*r==-1?a:(a+r)/(1+a*r))+1)/2;n=1-l,i.r=255&l*i.r+n*s.r+.5,i.g=255&l*i.g+n*s.g+.5,i.b=255&l*i.b+n*s.b+.5,i.a=o*i.a+(1-o)*s.a,this.rgb=i}return this}interpolate(t,e){return t&&(this._rgb=function(t,e,i){const s=Ut(wt(t.r)),n=Ut(wt(t.g)),o=Ut(wt(t.b));return{r:Mt(Yt(s+i*(Ut(wt(e.r))-s))),g:Mt(Yt(n+i*(Ut(wt(e.g))-n))),b:Mt(Yt(o+i*(Ut(wt(e.b))-o))),a:t.a+i*(e.a-t.a)}}(this._rgb,t._rgb,e)),this}clone(){return new Zt(this.rgb)}alpha(t){return this._rgb.a=Mt(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=_t(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return Xt(this._rgb,2,t),this}darken(t){return Xt(this._rgb,2,-t),this}saturate(t){return Xt(this._rgb,1,t),this}desaturate(t){return Xt(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=It(t);i[0]=Vt(i[0]+e),i=Ft(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function Jt(t){if(t&&"object"==typeof t){const e=t.toString();return"[object CanvasPattern]"===e||"[object CanvasGradient]"===e}return!1}function Qt(t){return Jt(t)?t:new Zt(t)}function te(t){return Jt(t)?t:new Zt(t).saturate(.5).darken(.1).hexString()}const ee=["x","y","borderWidth","radius","tension"],ie=["color","borderColor","backgroundColor"];const se=new Map;function ne(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=se.get(i);return s||(s=new Intl.NumberFormat(t,e),se.set(i,s)),s}(e,i).format(t)}const oe={values:t=>n(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n="scientific"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=z(Math.abs(o)),r=isNaN(a)?1:Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),ne(t,s,l)},logarithmic(t,e,i){if(0===t)return"0";const s=i[e].significand||t/Math.pow(10,Math.floor(z(t)));return[1,2,3,5,10,15].includes(s)||e>.8*i.length?oe.numeric.call(this,t,e,i):""}};var ae={formatters:oe};const re=Object.create(null),le=Object.create(null);function he(t,e){if(!e)return t;const i=e.split(".");for(let e=0,s=i.length;et.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>te(e.backgroundColor),this.hoverBorderColor=(t,e)=>te(e.borderColor),this.hoverColor=(t,e)=>te(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0,includeInvisible:!1},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.drawActiveElementsOnTop=!0,this.describe(t),this.apply(e)}set(t,e){return ce(this,t,e)}get(t){return he(this,t)}describe(t,e){return ce(le,t,e)}override(t,e){return ce(re,t,e)}route(t,e,i,s){const n=he(this,t),a=he(this,i),r="_"+e;Object.defineProperties(n,{[r]:{value:n[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[r],e=a[s];return o(t)?Object.assign({},e,t):l(t,e)},set(t){this[r]=t}}})}apply(t){t.forEach((t=>t(this)))}}var ue=new de({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}},[function(t){t.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0}),t.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),t.set("animations",{colors:{type:"color",properties:ie},numbers:{type:"number",properties:ee}}),t.describe("animations",{_fallback:"animation"}),t.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}})},function(t){t.set("layout",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}})},function(t){t.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",clip:!0,grace:0,grid:{display:!0,lineWidth:1,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1},border:{display:!0,dash:[],dashOffset:0,width:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:ae.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),t.route("scale.ticks","color","","color"),t.route("scale.grid","color","","borderColor"),t.route("scale.border","color","","borderColor"),t.route("scale.title","color","","color"),t.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t&&"dash"!==t}),t.describe("scales",{_fallback:"scale"}),t.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t})}]);function fe(){return"undefined"!=typeof window&&"undefined"!=typeof document}function ge(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function pe(t,e,i){let s;return"string"==typeof t?(s=parseInt(t,10),-1!==t.indexOf("%")&&(s=s/100*e.parentNode[i])):s=t,s}const me=t=>t.ownerDocument.defaultView.getComputedStyle(t,null);function xe(t,e){return me(t).getPropertyValue(e)}const be=["top","right","bottom","left"];function _e(t,e,i){const s={};i=i?"-"+i:"";for(let n=0;n<4;n++){const o=be[n];s[o]=parseFloat(t[e+"-"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}const ye=(t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot);function ve(t,e){if("native"in t)return t;const{canvas:i,currentDevicePixelRatio:s}=e,n=me(i),o="border-box"===n.boxSizing,a=_e(n,"padding"),r=_e(n,"border","width"),{x:l,y:h,box:c}=function(t,e){const i=t.touches,s=i&&i.length?i[0]:t,{offsetX:n,offsetY:o}=s;let a,r,l=!1;if(ye(n,o,t.target))a=n,r=o;else{const t=e.getBoundingClientRect();a=s.clientX-t.left,r=s.clientY-t.top,l=!0}return{x:a,y:r,box:l}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const Me=t=>Math.round(10*t)/10;function we(t,e,i,s){const n=me(t),o=_e(n,"margin"),a=pe(n.maxWidth,t,"clientWidth")||T,r=pe(n.maxHeight,t,"clientHeight")||T,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=t&&ge(t);if(o){const t=o.getBoundingClientRect(),a=me(o),r=_e(a,"border","width"),l=_e(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=pe(a.maxWidth,o,"clientWidth"),n=pe(a.maxHeight,o,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||T,maxHeight:n||T}}(t,e,i);let{width:h,height:c}=l;if("content-box"===n.boxSizing){const t=_e(n,"border","width"),e=_e(n,"padding");h-=e.width+t.width,c-=e.height+t.height}h=Math.max(0,h-o.width),c=Math.max(0,s?h/s:c-o.height),h=Me(Math.min(h,a,l.maxWidth)),c=Me(Math.min(c,r,l.maxHeight)),h&&!c&&(c=Me(h/2));return(void 0!==e||void 0!==i)&&s&&l.height&&c>l.height&&(c=l.height,h=Me(Math.floor(c*s))),{width:h,height:c}}function ke(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=Math.floor(t.height),t.width=Math.floor(t.width);const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const Se=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};fe()&&(window.addEventListener("test",null,e),window.removeEventListener("test",null,e))}catch(t){}return t}();function Pe(t,e){const i=xe(t,e),s=i&&i.match(/^(\d+)(\.\d+)?px$/);return s?+s[1]:void 0}function De(t){return!t||s(t.size)||s(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function Ce(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function Oe(t,e,i,s){let o=(s=s||{}).data=s.data||{},a=s.garbageCollect=s.garbageCollect||[];s.font!==e&&(o=s.data={},a=s.garbageCollect=[],s.font=e),t.save(),t.font=e;let r=0;const l=i.length;let h,c,d,u,f;for(h=0;hi.length){for(h=0;h0&&t.stroke()}}function Re(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.xe.top-i&&t.y0&&""!==r.strokeColor;let c,d;for(t.save(),t.font=a.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]),s(e.rotation)||t.rotate(e.rotation),e.color&&(t.fillStyle=e.color),e.textAlign&&(t.textAlign=e.textAlign),e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,r),c=0;ct[0])){const o=i||t;void 0===s&&(s=ti("_fallback",t));const a={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:o,_fallback:s,_getTarget:n,override:i=>je([i,...t],e,o,s)};return new Proxy(a,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>qe(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=ti(Ue(o,t),i),void 0!==n)return Xe(t,n)?Je(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>ei(t).includes(e),ownKeys:t=>ei(t),set(t,e,i){const s=t._storage||(t._storage=n());return t[e]=s[e]=i,delete t._keys,!0}})}function $e(t,e,i,s){const a={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:Ye(t,s),setContext:e=>$e(t,e,i,s),override:n=>$e(t.override(n),e,i,s)};return new Proxy(a,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>qe(t,e,(()=>function(t,e,i){const{_proxy:s,_context:a,_subProxy:r,_descriptors:l}=t;let h=s[e];S(h)&&l.isScriptable(e)&&(h=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t);let l=e(o,a||s);r.delete(t),Xe(t,l)&&(l=Je(n._scopes,n,t,l));return l}(e,h,t,i));n(h)&&h.length&&(h=function(t,e,i,s){const{_proxy:n,_context:a,_subProxy:r,_descriptors:l}=i;if(void 0!==a.index&&s(t))return e[a.index%e.length];if(o(e[0])){const i=e,s=n._scopes.filter((t=>t!==i));e=[];for(const o of i){const i=Je(s,n,t,o);e.push($e(i,a,r&&r[t],l))}}return e}(e,h,t,l.isIndexable));Xe(e,h)&&(h=$e(h,a,r&&r[e],l));return h}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function Ye(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:S(i)?i:()=>i,isIndexable:S(s)?s:()=>s}}const Ue=(t,e)=>t?t+w(e):e,Xe=(t,e)=>o(e)&&"adapters"!==t&&(null===Object.getPrototypeOf(e)||e.constructor===Object);function qe(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e)||"constructor"===e)return t[e];const s=i();return t[e]=s,s}function Ke(t,e,i){return S(t)?t(e,i):t}const Ge=(t,e)=>!0===t?e:"string"==typeof t?M(e,t):void 0;function Ze(t,e,i,s,n){for(const o of e){const e=Ge(i,o);if(e){t.add(e);const o=Ke(e._fallback,i,n);if(void 0!==o&&o!==i&&o!==s)return o}else if(!1===e&&void 0!==s&&i!==s)return null}return!1}function Je(t,e,i,s){const a=e._rootScopes,r=Ke(e._fallback,i,s),l=[...t,...a],h=new Set;h.add(s);let c=Qe(h,l,i,r||i,s);return null!==c&&((void 0===r||r===i||(c=Qe(h,l,r,c,s),null!==c))&&je(Array.from(h),[""],a,r,(()=>function(t,e,i){const s=t._getTarget();e in s||(s[e]={});const a=s[e];if(n(a)&&o(i))return i;return a||{}}(e,i,s))))}function Qe(t,e,i,s,n){for(;i;)i=Ze(t,e,i,s,n);return i}function ti(t,e){for(const i of e){if(!i)continue;const e=i[t];if(void 0!==e)return e}}function ei(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}function ii(t,e,i,s){const{iScale:n}=t,{key:o="r"}=this._parsing,a=new Array(s);let r,l,h,c;for(r=0,l=s;re"x"===t?"y":"x";function ai(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=q(o,n),l=q(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function ri(t,e="x"){const i=oi(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=ni(t,0);for(a=0;a!t.skip))),"monotone"===e.cubicInterpolationMode)ri(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o0===t||1===t,di=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*O/i),ui=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*O/i)+1,fi={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*E),easeOutSine:t=>Math.sin(t*E),easeInOutSine:t=>-.5*(Math.cos(C*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>ci(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>ci(t)?t:di(t,.075,.3),easeOutElastic:t=>ci(t)?t:ui(t,.075,.3),easeInOutElastic(t){const e=.1125;return ci(t)?t:t<.5?.5*di(2*t,e,.45):.5+.5*ui(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-fi.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*fi.easeInBounce(2*t):.5*fi.easeOutBounce(2*t-1)+.5};function gi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function pi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:"middle"===s?i<.5?t.y:e.y:"after"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function mi(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=gi(t,n,i),r=gi(n,o,i),l=gi(o,e,i),h=gi(a,r,i),c=gi(r,l,i);return gi(h,c,i)}const xi=/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/,bi=/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/;function _i(t,e){const i=(""+t).match(xi);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}const yi=t=>+t||0;function vi(t,e){const i={},s=o(e),n=s?Object.keys(e):e,a=o(t)?s?i=>l(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of n)i[t]=yi(a(t));return i}function Mi(t){return vi(t,{top:"y",right:"x",bottom:"y",left:"x"})}function wi(t){return vi(t,["topLeft","topRight","bottomLeft","bottomRight"])}function ki(t){const e=Mi(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function Si(t,e){t=t||{},e=e||ue.font;let i=l(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let s=l(t.style,e.style);s&&!(""+s).match(bi)&&(console.warn('Invalid font style specified: "'+s+'"'),s=void 0);const n={family:l(t.family,e.family),lineHeight:_i(l(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:l(t.weight,e.weight),string:""};return n.string=De(n),n}function Pi(t,e,i,s){let o,a,r,l=!0;for(o=0,a=t.length;oi&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function Ci(t,e){return Object.assign(Object.create(t),e)}function Oi(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function Ai(t,e){let i,s;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,s=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=s)}function Ti(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function Li(t){return"angle"===t?{between:Z,compare:K,normalize:G}:{between:tt,compare:(t,e)=>t-e,normalize:t=>t}}function Ei({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function Ri(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=Li(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=Li(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;hb||l(n,x,p)&&0!==r(n,x),v=()=>!b||0===r(o,p)||l(o,x,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==x&&(b=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(Ei({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,x=p));return null!==_&&g.push(Ei({start:_,end:d,loop:u,count:a,style:f})),g}function Ii(t,e){const i=[],s=t.segments;for(let n=0;nn&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return Fi(t,[{start:a,end:r,loop:o}],i,e);return Fi(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r{t[a](e[i],n)&&(o.push({element:t,datasetIndex:s,index:l}),r=r||t.inRange(e.x,e.y,n))})),s&&!r?[]:o}var Xi={evaluateInteractionItems:Hi,modes:{index(t,e,i,s){const n=ve(e,t),o=i.axis||"x",a=i.includeInvisible||!1,r=i.intersect?ji(t,n,o,s,a):Yi(t,n,o,!1,s,a),l=[];return r.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=r[0].index,i=t.data[e];i&&!i.skip&&l.push({element:i,datasetIndex:t.index,index:e})})),l):[]},dataset(t,e,i,s){const n=ve(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;let r=i.intersect?ji(t,n,o,s,a):Yi(t,n,o,!1,s,a);if(r.length>0){const e=r[0].datasetIndex,i=t.getDatasetMeta(e).data;r=[];for(let t=0;tji(t,ve(e,t),i.axis||"xy",s,i.includeInvisible||!1),nearest(t,e,i,s){const n=ve(e,t),o=i.axis||"xy",a=i.includeInvisible||!1;return Yi(t,n,o,i.intersect,s,a)},x:(t,e,i,s)=>Ui(t,ve(e,t),"x",i.intersect,s),y:(t,e,i,s)=>Ui(t,ve(e,t),"y",i.intersect,s)}};const qi=["left","top","right","bottom"];function Ki(t,e){return t.filter((t=>t.pos===e))}function Gi(t,e){return t.filter((t=>-1===qi.indexOf(t.pos)&&t.box.axis===e))}function Zi(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Ji(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!qi.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o{s[t]=Math.max(e[t],i[t])})),s}return s(t?["left","right"]:["top","bottom"])}function ss(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;ot.box.fullSize)),!0),s=Zi(Ki(e,"left"),!0),n=Zi(Ki(e,"right")),o=Zi(Ki(e,"top"),!0),a=Zi(Ki(e,"bottom")),r=Gi(e,"x"),l=Gi(e,"y");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:Ki(e,"chartArea"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;u(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),f=Object.assign({},n);ts(f,ki(s));const g=Object.assign({maxPadding:f,w:o,h:a,x:n.left,y:n.top},n),p=Ji(l.concat(h),d);ss(r.fullSize,g,d,p),ss(l,g,d,p),ss(h,g,d,p)&&ss(l,g,d,p),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(g),os(r.leftAndTop,g,d,p),g.x+=g.w,g.y+=g.h,os(r.rightAndBottom,g,d,p),t.chartArea={left:g.left,top:g.top,right:g.left+g.w,bottom:g.top+g.h,height:g.h,width:g.w},u(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(g.w,g.h,{left:0,top:0,right:0,bottom:0})}))}};class rs{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class ls extends rs{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}updateConfig(t){t.options.animation=!1}}const hs="$chartjs",cs={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},ds=t=>null===t||""===t;const us=!!Se&&{passive:!0};function fs(t,e,i){t&&t.canvas&&t.canvas.removeEventListener(e,i,us)}function gs(t,e){for(const i of t)if(i===e||i.contains(e))return!0}function ps(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||gs(i.addedNodes,s),e=e&&!gs(i.removedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function ms(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{let e=!1;for(const i of t)e=e||gs(i.removedNodes,s),e=e&&!gs(i.addedNodes,s);e&&i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const xs=new Map;let bs=0;function _s(){const t=window.devicePixelRatio;t!==bs&&(bs=t,xs.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function ys(t,e,i){const s=t.canvas,n=s&&ge(s);if(!n)return;const o=ct(((t,e)=>{const s=n.clientWidth;i(t,e),s{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||o(i,s)}));return a.observe(n),function(t,e){xs.size||window.addEventListener("resize",_s),xs.set(t,e)}(t,o),a}function vs(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){xs.delete(t),xs.size||window.removeEventListener("resize",_s)}(t)}function Ms(t,e,i){const s=t.canvas,n=ct((e=>{null!==t.ctx&&i(function(t,e){const i=cs[t.type]||t.type,{x:s,y:n}=ve(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t);return function(t,e,i){t&&t.addEventListener(e,i,us)}(s,e,n),n}class ws extends rs{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute("height"),n=t.getAttribute("width");if(t[hs]={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",ds(n)){const e=Pe(t,"width");void 0!==e&&(t.width=e)}if(ds(s))if(""===t.style.height)t.height=t.width/(e||2);else{const e=Pe(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e[hs])return!1;const i=e[hs].initial;["height","width"].forEach((t=>{const n=i[t];s(n)?e.removeAttribute(t):e.setAttribute(t,n)}));const n=i.style||{};return Object.keys(n).forEach((t=>{e.style[t]=n[t]})),e.width=e.width,delete e[hs],!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:ps,detach:ms,resize:ys}[e]||Ms;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:vs,detach:vs,resize:vs}[e]||fs)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return we(t,e,i,s)}isAttached(t){const e=t&&ge(t);return!(!e||!e.isConnected)}}function ks(t){return!fe()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?ls:ws}var Ss=Object.freeze({__proto__:null,BasePlatform:rs,BasicPlatform:ls,DomPlatform:ws,_detectPlatform:ks});const Ps="transparent",Ds={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=Qt(t||Ps),n=s.valid&&Qt(e||Ps);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class Cs{constructor(t,e,i,s){const n=e[i];s=Pi([t.to,s,n,t.from]);const o=Pi([t.from,n,s]);this._active=!0,this._fn=t.fn||Ds[t.type||typeof o],this._easing=fi[t.easing]||fi.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=Pi([t.to,e,s,t.from]),this._from=Pi([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t{const a=t[s];if(!o(a))return;const r={};for(const t of e)r[t]=a[t];(n(a.properties)&&a.properties||[s]).forEach((t=>{t!==s&&i.has(t)||i.set(t,r)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if("$"===l.charAt(0))continue;if("options"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new Cs(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(bt.add(this._chart,i),!0):void 0}}function As(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function Ts(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n0||!i&&e<0)return n.index}return null}function zs(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;ti[t].axis===e)).shift()}function Vs(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i],void 0!==e[s]._visualValues&&void 0!==e[s]._visualValues[i]&&delete e[s]._visualValues[i]}}}const Bs=t=>"reset"===t||"none"===t,Ws=(t,e)=>e?t:Object.assign({},t);class Ns{static defaults={};static datasetElementType=null;static dataElementType=null;constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.supportsDecimation=!1,this.$context=void 0,this._syncList=[],this.datasetElementType=new.target.datasetElementType,this.dataElementType=new.target.dataElementType,this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=Es(t.vScale,t),this.addElements(),this.options.fill&&!this.chart.isPluginEnabled("filler")&&console.warn("Tried to use the 'fill' option without the 'Filler' plugin enabled. Please import and register the 'Filler' plugin and make sure it is not disabled in the options")}updateIndex(t){this.index!==t&&Vs(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>"x"===t?e:"r"===t?s:i,n=e.xAxisID=l(i.xAxisID,Fs(t,"x")),o=e.yAxisID=l(i.yAxisID,Fs(t,"y")),a=e.rAxisID=l(i.rAxisID,Fs(t,"r")),r=e.indexAxis,h=e.iAxisID=s(r,n,o,a),c=e.vAxisID=s(r,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(h),e.vScale=this.getScaleForId(c)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&rt(this._data,this),t._stacked&&Vs(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(o(e)){const t=this._cachedMeta;this._data=function(t,e){const{iScale:i,vScale:s}=e,n="x"===i.axis?"x":"y",o="x"===s.axis?"x":"y",a=Object.keys(t),r=new Array(a.length);let l,h,c;for(l=0,h=a.length;l0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=s,i._sorted=!0,d=s;else{d=n(s[t])?this.parseArrayData(i,s,t,e):o(s[t])?this.parseObjectData(i,s,t,e):this.parsePrimitiveData(i,s,t,e);const a=()=>null===c[l]||f&&c[l]t&&!e.hidden&&e._stacked&&{keys:Ts(i,!0),values:null})(e,i,this.chart),h={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:c,max:d}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(r);let u,f;function g(){f=s[u];const e=f[r.axis];return!a(f[t.axis])||c>e||d=0;--u)if(!g()){this.updateRangeFromParsed(h,t,f,l);break}return h}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,o;for(s=0,n=e.length;s=0&&tthis.getContext(i,s,e)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(Ws(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new Os(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||Bs(t)||this.chart._animationsDisabled}_getSharedOptions(t,e){const i=this.resolveDataElementOptions(t,e),s=this._sharedOptions,n=this.getSharedOptions(i),o=this.includeOptions(e,n)||n!==s;return this.updateSharedOptions(n,e,i),{sharedOptions:n,includeOptions:o}}updateElement(t,e,i,s){Bs(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!Bs(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}function js(t,e){const i=t.options.ticks,n=function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),o=Math.min(i.maxTicksLimit||n,n),a=i.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;io)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;nn)return e}return Math.max(n,1)}(a,e,o);if(r>0){let t,i;const n=r>1?Math.round((h-l)/(r-1)):null;for($s(e,c,d,s(n)?0:l-n,l),t=0,i=r-1;t"top"===e||"left"===e?t[e]+i:t[e]-i,Us=(t,e)=>Math.min(e||t,t);function Xs(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;oa+r)))return h}function Ks(t){return t.drawTicks?t.tickLength:0}function Gs(t,e){if(!t.display)return 0;const i=Si(t.font,e),s=ki(t.padding);return(n(t.text)?t.text.length:1)*i.lineHeight+s.height}function Zs(t,e,i){let s=ut(t);return(i&&"right"!==e||!i&&"right"===e)&&(s=(t=>"left"===t?"right":"right"===t?"left":t)(s)),s}class Js extends Hs{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=r(t,Number.POSITIVE_INFINITY),e=r(e,Number.NEGATIVE_INFINITY),i=r(i,Number.POSITIVE_INFINITY),s=r(s,Number.NEGATIVE_INFINITY),{min:r(t,i),max:r(e,s),minDefined:a(t),maxDefined:a(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const a=this.getMatchingVisibleMetas();for(let r=0,l=a.length;rs?s:i,s=n&&i>s?i:s,{min:r(i,r(s,i)),max:r(s,r(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}getLabelItems(t=this.chart.chartArea){return this._labelItems||(this._labelItems=this._computeLabelItems(t))}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){d(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=Di(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=J(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Ks(t.grid)-e.padding-Gs(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=Y(Math.min(Math.asin(J((h.highest.height+6)/o,-1,1)),Math.asin(J(a/r,-1,1))-Math.asin(J(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){d(this.options.afterCalculateLabelRotation,[this])}afterAutoSkip(){}beforeFit(){d(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=Gs(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Ks(n)+o):(t.height=this.maxHeight,t.width=Ks(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=$(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l="top"!==a&&"x"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):"start"===n?d=e.width:"end"===n?c=t.width:"inner"!==n&&(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;"start"===n?(i=0,s=t.height):"end"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){d(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,i;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,i=t.length;e{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n({width:r[t]||0,height:l[t]||0});return{first:P(0),last:P(e-1),widest:P(k),highest:P(S),widths:r,heights:l}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return Q(this._alignToPixels?Ae(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&ta*s?a/i:r/s:r*s0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:n,position:a,border:r}=s,h=n.offset,c=this.isHorizontal(),d=this.ticks.length+(h?1:0),u=Ks(n),f=[],g=r.setContext(this.getContext()),p=g.display?g.width:0,m=p/2,x=function(t){return Ae(i,t,p)};let b,_,y,v,M,w,k,S,P,D,C,O;if("top"===a)b=x(this.bottom),w=this.bottom-u,S=b-m,D=x(t.top)+m,O=t.bottom;else if("bottom"===a)b=x(this.top),D=t.top,O=x(t.bottom)-m,w=b+m,S=this.top+u;else if("left"===a)b=x(this.right),M=this.right-u,k=b-m,P=x(t.left)+m,C=t.right;else if("right"===a)b=x(this.left),P=t.left,C=x(t.right)-m,M=b+m,k=this.left+u;else if("x"===e){if("center"===a)b=x((t.top+t.bottom)/2+.5);else if(o(a)){const t=Object.keys(a)[0],e=a[t];b=x(this.chart.scales[t].getPixelForValue(e))}D=t.top,O=t.bottom,w=b+m,S=w+u}else if("y"===e){if("center"===a)b=x((t.left+t.right)/2);else if(o(a)){const t=Object.keys(a)[0],e=a[t];b=x(this.chart.scales[t].getPixelForValue(e))}M=b-m,k=M-u,P=t.left,C=t.right}const A=l(s.ticks.maxTicksLimit,d),T=Math.max(1,Math.ceil(d/A));for(_=0;_0&&(o-=s/2)}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}x.push({label:v,font:P,textOffset:O,options:{rotation:m,color:i,strokeColor:o,strokeWidth:h,textAlign:f,textBaseline:A,translation:[M,w],backdrop:d}})}return x}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-$(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align?i="right":"inner"===e.align&&(i="inner"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return"left"===e?s?(l=this.right+n,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l+=a)):(l=this.right-o,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l=this.left)):"right"===e?s?(l=this.left+n,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l-=a)):(l=this.left+o,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l=this.right)):r="right",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return"left"===e||"right"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:"top"===e||"bottom"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:s,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+"AxisID",s=[];let n,o;for(n=0,o=e.length;n{const s=i.split("."),n=s.pop(),o=[t].concat(s).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");ue.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&ue.describe(e,t.descriptors)}(t,o,i),this.override&&ue.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in ue[s]&&(delete ue[s][i],this.override&&delete re[i])}}class tn{constructor(){this.controllers=new Qs(Ns,"datasets",!0),this.elements=new Qs(Hs,"elements"),this.plugins=new Qs(Object,"plugins"),this.scales=new Qs(Js,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):u(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=w(t);d(i["before"+s],[],i),e[t](i),d(i["after"+s],[],i)}_getRegistryForType(t){for(let e=0;et.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,"stop"),this._notify(s(i,e),t,"start")}}function nn(t,e){return e||!1!==t?!0===t?{}:t:null}function on(t,{plugin:e,local:i},s,n){const o=t.pluginScopeKeys(e),a=t.getOptionScopes(s,o);return i&&e.defaults&&a.push(e.defaults),t.createResolver(a,n,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function an(t,e){const i=ue.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function rn(t){if("x"===t||"y"===t||"r"===t)return t}function ln(t,...e){if(rn(t))return t;for(const s of e){const e=s.axis||("top"===(i=s.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.length>1&&rn(t[0].toLowerCase());if(e)return e}var i;throw new Error(`Cannot determine type of '${t}' axis. Please provide 'axis' or 'position' option.`)}function hn(t,e,i){if(i[e+"AxisID"]===t)return{axis:e}}function cn(t,e){const i=re[t.type]||{scales:{}},s=e.scales||{},n=an(t.type,e),a=Object.create(null);return Object.keys(s).forEach((e=>{const r=s[e];if(!o(r))return console.error(`Invalid scale configuration for scale: ${e}`);if(r._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${e}`);const l=ln(e,r,function(t,e){if(e.data&&e.data.datasets){const i=e.data.datasets.filter((e=>e.xAxisID===t||e.yAxisID===t));if(i.length)return hn(t,"x",i[0])||hn(t,"y",i[0])}return{}}(e,t),ue.scales[r.type]),h=function(t,e){return t===e?"_index_":"_value_"}(l,n),c=i.scales||{};a[e]=b(Object.create(null),[{axis:l},r,c[l],c[h]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,o=i.indexAxis||an(n,e),r=(re[n]||{}).scales||{};Object.keys(r).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,o),n=i[e+"AxisID"]||e;a[n]=a[n]||Object.create(null),b(a[n],[{axis:e},s[n],r[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];b(e,[ue.scales[e.type],ue.scale])})),a}function dn(t){const e=t.options||(t.options={});e.plugins=l(e.plugins,{}),e.scales=cn(t,e)}function un(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const fn=new Map,gn=new Set;function pn(t,e){let i=fn.get(t);return i||(i=e(),fn.set(t,i),gn.add(i)),i}const mn=(t,e,i)=>{const s=M(e,i);void 0!==s&&t.add(s)};class xn{constructor(t){this._config=function(t){return(t=t||{}).data=un(t.data),dn(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=un(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),dn(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return pn(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return pn(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return pn(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return pn(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>mn(r,t,e)))),e.forEach((t=>mn(r,s,t))),e.forEach((t=>mn(r,re[n]||{},t))),e.forEach((t=>mn(r,ue,t))),e.forEach((t=>mn(r,le,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),gn.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,re[e]||{},ue.datasets[e]||{},{type:e},ue,le]}resolveNamedOptions(t,e,i,s=[""]){const o={$shared:!0},{resolver:a,subPrefixes:r}=bn(this._resolverCache,t,s);let l=a;if(function(t,e){const{isScriptable:i,isIndexable:s}=Ye(t);for(const o of e){const e=i(o),a=s(o),r=(a||e)&&t[o];if(e&&(S(r)||_n(r))||a&&n(r))return!0}return!1}(a,e)){o.$shared=!1;l=$e(a,i=S(i)?i():i,this.createResolver(t,i,r))}for(const t of e)o[t]=l[t];return o}createResolver(t,e,i=[""],s){const{resolver:n}=bn(this._resolverCache,t,i);return o(e)?$e(n,e,void 0,s):n}}function bn(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:je(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},s.set(n,o)}return o}const _n=t=>o(t)&&Object.getOwnPropertyNames(t).some((e=>S(t[e])));const yn=["top","bottom","left","right","chartArea"];function vn(t,e){return"top"===t||"bottom"===t||-1===yn.indexOf(t)&&"x"===e}function Mn(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function wn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),d(i&&i.onComplete,[t],e)}function kn(t){const e=t.chart,i=e.options.animation;d(i&&i.onProgress,[t],e)}function Sn(t){return fe()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const Pn={},Dn=t=>{const e=Sn(t);return Object.values(Pn).filter((t=>t.canvas===e)).pop()};function Cn(t,e,i){const s=Object.keys(t);for(const n of s){const s=+n;if(s>=e){const o=t[n];delete t[n],(i>0||s>e)&&(t[s+i]=o)}}}function On(t,e,i){return t.options.clip?t[i]:e[i]}class An{static defaults=ue;static instances=Pn;static overrides=re;static registry=en;static version="4.4.3";static getChart=Dn;static register(...t){en.add(...t),Tn()}static unregister(...t){en.remove(...t),Tn()}constructor(t,e){const s=this.config=new xn(e),n=Sn(t),o=Dn(n);if(o)throw new Error("Canvas is already in use. Chart with ID '"+o.id+"' must be destroyed before the canvas with ID '"+o.canvas.id+"' can be reused.");const a=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||ks(n)),this.platform.updateConfig(s);const r=this.platform.acquireContext(n,a.aspectRatio),l=r&&r.canvas,h=l&&l.height,c=l&&l.width;this.id=i(),this.ctx=r,this.canvas=l,this.width=c,this.height=h,this._options=a,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new sn,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=dt((t=>this.update(t)),a.resizeDelay||0),this._dataChanges=[],Pn[this.id]=this,r&&l?(bt.listen(this,"complete",wn),bt.listen(this,"progress",kn),this._initialize(),this.attached&&this.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:n,_aspectRatio:o}=this;return s(t)?e&&o?o:n?i/n:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}get registry(){return en}_initialize(){return this.notifyPlugins("beforeInit"),this.options.responsive?this.resize():ke(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins("afterInit"),this}clear(){return Te(this.canvas,this.ctx),this}stop(){return bt.stop(this),this}resize(t,e){bt.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?"resize":"attach";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,ke(this,a,!0)&&(this.notifyPlugins("resize",{size:o}),d(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){u(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=ln(t,i),n="r"===s,o="x"===s;return{options:i,dposition:n?"chartArea":o?"bottom":"left",dtype:n?"radialLinear":o?"category":"linear"}})))),u(n,(e=>{const n=e.options,o=n.id,a=ln(o,n),r=l(n.type,e.dtype);void 0!==n.position&&vn(n.position,a)===vn(e.dposition)||(n.position=e.dposition),s[o]=!0;let h=null;if(o in i&&i[o].type===r)h=i[o];else{h=new(en.getScale(r))({id:o,type:r,ctx:this.ctx,chart:this}),i[h.id]=h}h.init(n,t)})),u(s,((t,e)=>{t||delete i[e]})),u(i,(t=>{as.configure(this,t,t.options),as.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;te.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext()),s=this._animationsDisabled=!i.animation;if(this._updateScales(),this._checkEventBindings(),this._updateHiddenIndices(),this._plugins.invalidate(),!1===this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const n=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let o=0;for(let t=0,e=this.data.datasets.length;t{t.reset()})),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(Mn("z","_idx"));const{_active:a,_lastEvent:r}=this;r?this._eventHandler(r,!0):a.length&&this._updateHoverStyles(a,a,!0),this.render()}_updateScales(){u(this.scales,(t=>{as.removeBox(this,t)})),this.ensureScalesHaveIDs(),this.buildOrUpdateScales()}_checkEventBindings(){const t=this.options,e=new Set(Object.keys(this._listeners)),i=new Set(t.events);P(e,i)&&!!this._responsiveListeners===t.responsive||(this.unbindEvents(),this.bindEvents())}_updateHiddenIndices(){const{_hiddenIndices:t}=this,e=this._getUniformDataChanges()||[];for(const{method:i,start:s,count:n}of e){Cn(t,s,"_removeElements"===i?-n:n)}}_getUniformDataChanges(){const t=this._dataChanges;if(!t||!t.length)return;this._dataChanges=[];const e=this.data.datasets.length,i=e=>new Set(t.filter((t=>t[0]===e)).map(((t,e)=>e+","+t.splice(1).join(",")))),s=i(0);for(let t=1;tt.split(","))).map((t=>({method:t[1],start:+t[2],count:+t[3]})))}_updateLayout(t){if(!1===this.notifyPlugins("beforeLayout",{cancelable:!0}))return;as.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],u(this.boxes,(t=>{i&&"chartArea"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins("afterLayout")}_updateDatasets(t){if(!1!==this.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let t=0,e=this.data.datasets.length;t=0;--e)this._drawDataset(t[e]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=function(t,e){const{xScale:i,yScale:s}=t;return i&&s?{left:On(i,e,"left"),right:On(i,e,"right"),top:On(s,e,"top"),bottom:On(s,e,"bottom")}:e}(t,this.chartArea),o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetDraw",o)&&(s&&Ie(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&ze(e),o.cancelable=!1,this.notifyPlugins("afterDatasetDraw",o))}isPointInArea(t){return Re(t,this.chartArea,this._minPadding)}getElementsAtEventForMode(t,e,i,s){const n=Xi.modes[e];return"function"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=Ci(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?"show":"hide",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);k(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),bt.remove(this),t=0,e=this.data.datasets.length;t{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};u(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s("attach",a),this.attached=!0,this.resize(),i("resize",n),i("detach",o)};o=()=>{this.attached=!1,s("resize",n),this._stop(),this._resize(0,0),i("attach",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){u(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},u(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?"set":"remove";let n,o,a,r;for("dataset"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller["_"+s+"DatasetHoverStyle"]()),a=0,r=t.length;a{const i=this.getDatasetMeta(t);if(!i)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:i.data[e],index:e}}));!f(i,e)&&(this._active=i,this._lastEvent=null,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}isPluginEnabled(t){return 1===this._plugins._cache.filter((e=>e.plugin.id===t)).length}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0,inChartArea:this.isPointInArea(t)},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins("beforeEvent",i,s))return;const n=this._handleEvent(t,e,i.inChartArea);return i.cancelable=!1,this.notifyPlugins("afterEvent",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e,i){const{_active:s=[],options:n}=this,o=e,a=this._getActiveElements(t,s,i,o),r=D(t),l=function(t,e,i,s){return i&&"mouseout"!==t.type?s?e:t:null}(t,this._lastEvent,i,r);i&&(this._lastEvent=null,d(n.onHover,[t,a,this],this),r&&d(n.onClick,[t,a,this],this));const h=!f(a,s);return(h||e)&&(this._active=a,this._updateHoverStyles(a,s,e)),this._lastEvent=l,h}_getActiveElements(t,e,i,s){if("mouseout"===t.type)return[];if(!i)return e;const n=this.options.hover;return this.getElementsAtEventForMode(t,n.mode,n,s)}}function Tn(){return u(An.instances,(t=>t._plugins.invalidate()))}function Ln(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}class En{static override(t){Object.assign(En.prototype,t)}options;constructor(t){this.options=t||{}}init(){}formats(){return Ln()}parse(){return Ln()}format(){return Ln()}add(){return Ln()}diff(){return Ln()}startOf(){return Ln()}endOf(){return Ln()}}var Rn={_date:En};function In(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;et-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(k(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;sMath.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,s):e[i.axis]=i.parse(t,s),e}function Fn(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;ht.x,i="left",s="right"):(e=t.base"spacing"!==t,_indexable:t=>"spacing"!==t&&!t.startsWith("borderDash")&&!t.startsWith("hoverBorderDash")};static overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i,color:s}}=t.legend.options;return e.labels.map(((e,n)=>{const o=t.getDatasetMeta(0).controller.getStyle(n);return{text:e,fillStyle:o.backgroundColor,strokeStyle:o.borderColor,fontColor:s,lineWidth:o.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(n),index:n}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}}}};constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let n,a,r=t=>+i[t];if(o(i[t])){const{key:t="value"}=this._parsing;r=e=>+M(i[e],t)}for(n=t,a=t+e;nZ(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>Z(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(E,c,u),x=g(C,h,d),b=g(C+E,c,u);s=(p-x)/2,n=(m-b)/2,o=-(p+x)/2,a=-(m+b)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(u,d,r),x=(i.width-o)/f,b=(i.height-o)/g,_=Math.max(Math.min(x,b)/2,0),y=c(this.options.radius,_),v=(y-Math.max(y*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=p*y,this.offsetY=m*y,s.total=this.calculateTotal(),this.outerRadius=y-v*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-v*l,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/O)}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,{sharedOptions:f,includeOptions:g}=this._getSharedOptions(e,s);let p,m=this._getRotation();for(p=0;p0&&!isNaN(t)?O*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=ne(e._parsed[t],i.options.locale);return{label:s[t]||"",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s{const o=t.getDatasetMeta(0).controller.getStyle(n);return{text:e,fillStyle:o.backgroundColor,strokeStyle:o.borderColor,fontColor:s,lineWidth:o.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(n),index:n}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=ne(e._parsed[t].r,i.options.locale);return{label:s[t]||"",value:n}}parseObjectData(t,e,i,s){return ii.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}getMinMax(){const t=this._cachedMeta,e={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY};return t.data.forEach(((t,i)=>{const s=this.getParsed(i).r;!isNaN(s)&&this.chart.getDataVisibility(i)&&(se.max&&(e.max=s))})),e}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.options.animation,r=this._cachedMeta.rScale,l=r.xCenter,h=r.yCenter,c=r.getIndexAngle(0)-.5*C;let d,u=c;const f=360/this.countVisibleElements();for(d=0;d{!isNaN(this.getParsed(i).r)&&this.chart.getDataVisibility(i)&&e++})),e}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?$(this.resolveDataElementOptions(t,e).angle||i):0}}var Yn=Object.freeze({__proto__:null,BarController:class extends Ns{static id="bar";static defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}};static overrides={scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};parsePrimitiveData(t,e,i,s){return Fn(t,e,i,s)}parseArrayData(t,e,i,s){return Fn(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===n.axis?a:r,h="x"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;dt.controller.options.grouped)),o=i.options.stacked,a=[],r=t=>{const i=t.controller.getParsed(e),n=i&&i[t.vScale.axis];if(s(n)||isNaN(n))return!0};for(const i of n)if((void 0===e||!r(i))&&((!1===o||-1===a.indexOf(i.stack)||void 0===o&&void 0===i.stack)&&a.push(i.stack),i.index===t))break;return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n=i?1:-1)}(u,e,r)*a,f===r&&(x-=u/2);const t=e.getPixelForDecimal(0),s=e.getPixelForDecimal(1),o=Math.min(t,s),h=Math.max(t,s);x=Math.max(Math.min(x,h),o),d=x+u,i&&!c&&(l._stacks[e.axis]._visualValues[n]=e.getValueForPixel(d)-e.getValueForPixel(x))}if(x===e.getPixelForValue(r)){const t=F(u)*e.getLineWidthForValue(r)/2;x+=t,u-=t}return{size:u,base:x,head:d,center:d+u/2}}_calculateBarIndexPixels(t,e){const i=e.scale,n=this.options,o=n.skipNull,a=l(n.maxBarThickness,1/0);let r,h;if(e.grouped){const i=o?this._getStackCount(t):e.stackCount,l="flex"===n.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart.data.labels||[],{xScale:s,yScale:n}=e,o=this.getParsed(t),a=s.getLabelForValue(o.x),r=n.getLabelForValue(o.y),l=o._custom;return{label:i[t]||"",value:"("+a+", "+r+(l?", "+l:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a}=this._cachedMeta,{sharedOptions:r,includeOptions:l}=this._getSharedOptions(e,s),h=o.axis,c=a.axis;for(let d=e;d0&&this.getParsed(e-1);for(let i=0;i<_;++i){const g=t[i],_=x?g:{};if(i=b){_.skip=!0;continue}const v=this.getParsed(i),M=s(v[f]),w=_[u]=a.getPixelForValue(v[u],i),k=_[f]=o||M?r.getBasePixel():r.getPixelForValue(l?this.applyStack(r,v,l):v[f],i);_.skip=isNaN(w)||isNaN(k)||M,_.stop=i>0&&Math.abs(v[u]-y[u])>m,p&&(_.parsed=v,_.raw=h.data[i]),d&&(_.options=c||this.resolveDataElementOptions(i,g.active?"active":n)),x||this.updateElement(g,i,_,n),y=v}}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}},PieController:class extends jn{static id="pie";static defaults={cutout:0,rotation:0,circumference:360,radius:"100%"}},PolarAreaController:$n,RadarController:class extends Ns{static id="radar";static defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}};static overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}parseObjectData(t,e,i,s){return ii.bind(this)(t,e,i,s)}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,"resize"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this._cachedMeta.rScale,o="reset"===s;for(let a=e;a0&&this.getParsed(e-1);for(let c=e;c0&&Math.abs(i[f]-_[f])>x,m&&(p.parsed=i,p.raw=h.data[c]),u&&(p.options=d||this.resolveDataElementOptions(c,e.active?"active":n)),b||this.updateElement(e,c,p,n),_=i}this.updateSharedOptions(d,n,c)}getMaxOverflow(){const t=this._cachedMeta,e=t.data||[];if(!this.options.showLine){let t=0;for(let i=e.length-1;i>=0;--i)t=Math.max(t,e[i].size(this.resolveDataElementOptions(i))/2);return t>0&&t}const i=t.dataset,s=i.options&&i.options.borderWidth||0;if(!e.length)return s;const n=e[0].size(this.resolveDataElementOptions(0)),o=e[e.length-1].size(this.resolveDataElementOptions(e.length-1));return Math.max(s,n,o)/2}}});function Un(t,e,i,s){const n=vi(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return J(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:J(n.innerStart,0,a),innerEnd:J(n.innerEnd,0,a)}}function Xn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function qn(t,e,i,s,n,o){const{x:a,y:r,startAngle:l,pixelMargin:h,innerRadius:c}=e,d=Math.max(e.outerRadius+s+i-h,0),u=c>0?c+s+i+h:0;let f=0;const g=n-l;if(s){const t=((c>0?c-s:0)+(d>0?d-s:0))/2;f=(g-(0!==t?g*t/(t+s):g))/2}const p=(g-Math.max(.001,g*d-i/C)/d)/2,m=l+p+f,x=n-p-f,{outerStart:b,outerEnd:_,innerStart:y,innerEnd:v}=Un(e,u,d,x-m),M=d-b,w=d-_,k=m+b/M,S=x-_/w,P=u+y,D=u+v,O=m+y/P,A=x-v/D;if(t.beginPath(),o){const e=(k+S)/2;if(t.arc(a,r,d,k,e),t.arc(a,r,d,e,S),_>0){const e=Xn(w,S,a,r);t.arc(e.x,e.y,_,S,x+E)}const i=Xn(D,x,a,r);if(t.lineTo(i.x,i.y),v>0){const e=Xn(D,A,a,r);t.arc(e.x,e.y,v,x+E,A+Math.PI)}const s=(x-v/u+(m+y/u))/2;if(t.arc(a,r,u,x-v/u,s,!0),t.arc(a,r,u,s,m+y/u,!0),y>0){const e=Xn(P,O,a,r);t.arc(e.x,e.y,y,O+Math.PI,m-E)}const n=Xn(M,m,a,r);if(t.lineTo(n.x,n.y),b>0){const e=Xn(M,k,a,r);t.arc(e.x,e.y,b,m-E,k)}}else{t.moveTo(a,r);const e=Math.cos(k)*d+a,i=Math.sin(k)*d+r;t.lineTo(e,i);const s=Math.cos(S)*d+a,n=Math.sin(S)*d+r;t.lineTo(s,n)}t.closePath()}function Kn(t,e,i,s,n){const{fullCircles:o,startAngle:a,circumference:r,options:l}=e,{borderWidth:h,borderJoinStyle:c,borderDash:d,borderDashOffset:u}=l,f="inner"===l.borderAlign;if(!h)return;t.setLineDash(d||[]),t.lineDashOffset=u,f?(t.lineWidth=2*h,t.lineJoin=c||"round"):(t.lineWidth=h,t.lineJoin=c||"bevel");let g=e.endAngle;if(o){qn(t,e,i,s,g,n);for(let e=0;en?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+E,s-E),t.closePath(),t.clip()}(t,e,g),o||(qn(t,e,i,s,g,n),t.stroke())}function Gn(t,e,i=e){t.lineCap=l(i.borderCapStyle,e.borderCapStyle),t.setLineDash(l(i.borderDash,e.borderDash)),t.lineDashOffset=l(i.borderDashOffset,e.borderDashOffset),t.lineJoin=l(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=l(i.borderWidth,e.borderWidth),t.strokeStyle=l(i.borderColor,e.borderColor)}function Zn(t,e,i){t.lineTo(i.x,i.y)}function Jn(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=nr&&o>r;return{count:s,start:l,loop:e.loop,ilen:h(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[b(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[b(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(ig&&(g=i),m=(x*m+e)/++x):(_(),t.lineTo(e,i),u=s,x=0,f=g=i),p=i}_()}function eo(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?to:Qn}const io="function"==typeof Path2D;function so(t,e,i,s){io&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),Gn(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=eo(e);for(const r of n)Gn(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class no extends Hs{static id="line";static defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0};static defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};static descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||"monotone"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;hi(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=zi(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=Ii(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?pi:t.tension||"monotone"===t.cubicInterpolationMode?mi:gi}(i);let l,h;for(l=0,h=o.length;l"borderDash"!==t};circumference;endAngle;fullCircles;innerRadius;outerRadius;pixelMargin;startAngle;constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps(["x","y"],i),{angle:n,distance:o}=X(s,{x:t,y:e}),{startAngle:a,endAngle:r,innerRadius:h,outerRadius:c,circumference:d}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),u=(this.options.spacing+this.options.borderWidth)/2,f=l(d,r-a)>=O||Z(n,a,r),g=tt(o,h+u,c+u);return f&&g}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/4,n=(e.spacing||0)/2,o=e.circular;if(this.pixelMargin="inner"===e.borderAlign?.33:0,this.fullCircles=i>O?Math.floor(i/O):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();const a=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(a)*s,Math.sin(a)*s);const r=s*(1-Math.sin(Math.min(C,i||0)));t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor,function(t,e,i,s,n){const{fullCircles:o,startAngle:a,circumference:r}=e;let l=e.endAngle;if(o){qn(t,e,i,s,l,n);for(let e=0;e("string"==typeof e?(i=t.push(e)-1,s.unshift({index:i,label:e})):isNaN(e)&&(i=null),i))(t,e,i,s);return n!==t.lastIndexOf(e)?i:n}function po(t){const e=this.getLabels();return t>=0&&ts=e?s:t,a=t=>n=i?n:t;if(t){const t=F(s),e=F(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=0===n?1:Math.abs(.05*n);a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let i=this.getTickLimit();i=Math.max(2,i);const n=function(t,e){const i=[],{bounds:n,step:o,min:a,max:r,precision:l,count:h,maxTicks:c,maxDigits:d,includeBounds:u}=t,f=o||1,g=c-1,{min:p,max:m}=e,x=!s(a),b=!s(r),_=!s(h),y=(m-p)/(d+1);let v,M,w,k,S=B((m-p)/g/f)*f;if(S<1e-14&&!x&&!b)return[{value:p},{value:m}];k=Math.ceil(m/S)-Math.floor(p/S),k>g&&(S=B(k*S/g/f)*f),s(l)||(v=Math.pow(10,l),S=Math.ceil(S*v)/v),"ticks"===n?(M=Math.floor(p/S)*S,w=Math.ceil(m/S)*S):(M=p,w=m),x&&b&&o&&H((r-a)/o,S/1e3)?(k=Math.round(Math.min((r-a)/S,c)),S=(r-a)/k,M=a,w=r):_?(M=x?a:M,w=b?r:w,k=h-1,S=(w-M)/k):(k=(w-M)/S,k=V(k,Math.round(k),S/1e3)?Math.round(k):Math.ceil(k));const P=Math.max(U(S),U(M));v=Math.pow(10,s(l)?P:l),M=Math.round(M*v)/v,w=Math.round(w*v)/v;let D=0;for(x&&(u&&M!==a?(i.push({value:a}),Mr)break;i.push({value:t})}return b&&u&&w!==r?i.length&&V(i[i.length-1].value,r,mo(r,y,t))?i[i.length-1].value=r:i.push({value:r}):b&&w!==r||i.push({value:w}),i}({maxTicks:i,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return"ticks"===t.bounds&&j(n,this,"value"),t.reverse?(n.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),n}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return ne(t,this.chart.options.locale,this.options.ticks.format)}}class bo extends xo{static id="linear";static defaults={ticks:{callback:ae.formatters.numeric}};determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=a(t)?t:0,this.max=a(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=$(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}const _o=t=>Math.floor(z(t)),yo=(t,e)=>Math.pow(10,_o(t)+e);function vo(t){return 1===t/Math.pow(10,_o(t))}function Mo(t,e,i){const s=Math.pow(10,i),n=Math.floor(t/s);return Math.ceil(e/s)-n}function wo(t,{min:e,max:i}){e=r(t.min,e);const s=[],n=_o(e);let o=function(t,e){let i=_o(e-t);for(;Mo(t,e,i)>10;)i++;for(;Mo(t,e,i)<10;)i--;return Math.min(i,_o(t))}(e,i),a=o<0?Math.pow(10,Math.abs(o)):1;const l=Math.pow(10,o),h=n>o?Math.pow(10,n):0,c=Math.round((e-h)*a)/a,d=Math.floor((e-h)/l/10)*l*10;let u=Math.floor((c-d)/Math.pow(10,o)),f=r(t.min,Math.round((h+d+u*Math.pow(10,o))*a)/a);for(;f=10?u=u<15?15:20:u++,u>=20&&(o++,u=2,a=o>=0?1:a),f=Math.round((h+d+u*Math.pow(10,o))*a)/a;const g=r(t.max,f);return s.push({value:g,major:vo(g),significand:u}),s}class ko extends Js{static id="logarithmic";static defaults={ticks:{callback:ae.formatters.logarithmic,major:{enabled:!0}}};constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=xo.prototype.parse.apply(this,[t,e]);if(0!==i)return a(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=a(t)?Math.max(0,t):null,this.max=a(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this._zero&&this.min!==this._suggestedMin&&!a(this._userMin)&&(this.min=t===yo(this.min,0)?yo(this.min,-1):yo(this.min,0)),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t;i===s&&(i<=0?(n(1),o(10)):(n(yo(i,-1)),o(yo(s,1)))),i<=0&&n(yo(s,-1)),s<=0&&o(yo(i,1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=wo({min:this._userMin,max:this._userMax},this);return"ticks"===t.bounds&&j(e,this,"value"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?"0":ne(t,this.chart.options.locale,this.options.ticks.format)}configure(){const t=this.min;super.configure(),this._startValue=z(t),this._valueRange=z(this.max)-z(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(z(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function So(t){const e=t.ticks;if(e.display&&t.display){const t=ki(e.backdropPadding);return l(e.font&&e.font.size,ue.font.size)+t.height}return 0}function Po(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:tn?{start:e-i,end:e}:{start:e,end:e+i}}function Do(t){const e={l:t.left+t._padding.left,r:t.right-t._padding.right,t:t.top+t._padding.top,b:t.bottom-t._padding.bottom},i=Object.assign({},e),s=[],o=[],a=t._pointLabels.length,r=t.options.pointLabels,l=r.centerPointLabels?C/a:0;for(let u=0;ue.r&&(r=(s.end-e.r)/o,t.r=Math.max(t.r,e.r+r)),n.starte.b&&(l=(n.end-e.b)/a,t.b=Math.max(t.b,e.b+l))}function Oo(t,e,i){const s=t.drawingArea,{extra:n,additionalAngle:o,padding:a,size:r}=i,l=t.getPointPosition(e,s+n+a,o),h=Math.round(Y(G(l.angle+E))),c=function(t,e,i){90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e);return t}(l.y,r.h,h),d=function(t){if(0===t||180===t)return"center";if(t<180)return"left";return"right"}(h),u=function(t,e,i){"right"===i?t-=e:"center"===i&&(t-=e/2);return t}(l.x,r.w,d);return{visible:!0,x:l.x,y:c,textAlign:d,left:u,top:c,right:u+r.w,bottom:c+r.h}}function Ao(t,e){if(!e)return!0;const{left:i,top:s,right:n,bottom:o}=t;return!(Re({x:i,y:s},e)||Re({x:i,y:o},e)||Re({x:n,y:s},e)||Re({x:n,y:o},e))}function To(t,e,i){const{left:n,top:o,right:a,bottom:r}=i,{backdropColor:l}=e;if(!s(l)){const i=wi(e.borderRadius),s=ki(e.backdropPadding);t.fillStyle=l;const h=n-s.left,c=o-s.top,d=a-n+s.width,u=r-o+s.height;Object.values(i).some((t=>0!==t))?(t.beginPath(),He(t,{x:h,y:c,w:d,h:u,radius:i}),t.fill()):t.fillRect(h,c,d,u)}}function Lo(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,O);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;ot,padding:5,centerPointLabels:!1}};static defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"};static descriptors={angleLines:{_fallback:"grid"}};constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){const t=this._padding=ki(So(this.options)/2),e=this.width=this.maxWidth-t.width,i=this.height=this.maxHeight-t.height;this.xCenter=Math.floor(this.left+e/2+t.left),this.yCenter=Math.floor(this.top+i/2+t.top),this.drawingArea=Math.floor(Math.min(e,i)/2)}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=a(t)&&!isNaN(t)?t:0,this.max=a(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/So(this.options))}generateTickLabels(t){xo.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=d(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:""})).filter(((t,e)=>this.chart.getDataVisibility(e)))}fit(){const t=this.options;t.display&&t.pointLabels.display?Do(this):this.setCenterPoint(0,0,0,0)}setCenterPoint(t,e,i,s){this.xCenter+=Math.floor((t-e)/2),this.yCenter+=Math.floor((i-s)/2),this.drawingArea-=Math.min(this.drawingArea/2,Math.max(t,e,i,s))}getIndexAngle(t){return G(t*(O/(this._pointLabels.length||1))+$(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if(s(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if(s(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t=0;n--){const e=t._pointLabelItems[n];if(!e.visible)continue;const o=s.setContext(t.getPointLabelContext(n));To(i,o,e);const a=Si(o.font),{x:r,y:l,textAlign:h}=e;Ne(i,t._pointLabels[n],r,l+a.lineHeight/2,a,{color:o.color,textAlign:h,textBaseline:"middle"})}}(this,o),s.display&&this.ticks.forEach(((t,e)=>{if(0!==e||0===e&&this.min<0){r=this.getDistanceFromCenterForValue(t.value);const i=this.getContext(e),a=s.setContext(i),l=n.setContext(i);!function(t,e,i,s,n){const o=t.ctx,a=e.circular,{color:r,lineWidth:l}=e;!a&&!s||!r||!l||i<0||(o.save(),o.strokeStyle=r,o.lineWidth=l,o.setLineDash(n.dash),o.lineDashOffset=n.dashOffset,o.beginPath(),Lo(t,i,a,s),o.closePath(),o.stroke(),o.restore())}(this,a,r,o,l)}})),i.display){for(t.save(),a=o-1;a>=0;a--){const s=i.setContext(this.getPointLabelContext(a)),{color:n,lineWidth:o}=s;o&&n&&(t.lineWidth=o,t.strokeStyle=n,t.setLineDash(s.borderDash),t.lineDashOffset=s.borderDashOffset,r=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),l=this.getPointPosition(a,r),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(l.x,l.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign="center",t.textBaseline="middle",this.ticks.forEach(((s,a)=>{if(0===a&&this.min>=0&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=Si(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=ki(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}Ne(t,s.label,0,-n,l,{color:r.color,strokeColor:r.textStrokeColor,strokeWidth:r.textStrokeWidth})})),t.restore()}drawTitle(){}}const Ro={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},Io=Object.keys(Ro);function zo(t,e){return t-e}function Fo(t,e){if(s(e))return null;const i=t._adapter,{parser:n,round:o,isoWeekday:r}=t._parseOpts;let l=e;return"function"==typeof n&&(l=n(l)),a(l)||(l="string"==typeof n?i.parse(l,n):i.parse(l)),null===l?null:(o&&(l="week"!==o||!N(r)&&!0!==r?i.startOf(l,o):i.startOf(l,"isoWeek",r)),+l)}function Vo(t,e,i,s){const n=Io.length;for(let o=Io.indexOf(t);o=e?i[s]:i[n]]=!0}}else t[e]=!0}function Wo(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a=0&&(e[l].major=!0);return e}(t,s,n,i):s}class No extends Js{static id="time";static defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",callback:!1,major:{enabled:!1}}};constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e={}){const i=t.time||(t.time={}),s=this._adapter=new Rn._date(t.adapters.date);s.init(e),b(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:Fo(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||"day";let{min:s,max:n,minDefined:o,maxDefined:r}=this.getUserBounds();function l(t){o||isNaN(t.min)||(s=Math.min(s,t.min)),r||isNaN(t.max)||(n=Math.max(n,t.max))}o&&r||(l(this._getLabelBounds()),"ticks"===t.bounds&&"labels"===t.ticks.source||l(this.getMinMax(!1))),s=a(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=a(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s="labels"===i.source?this.getLabelTimestamps():this._generate();"ticks"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=nt(s,n,this.max);return this._unit=e.unit||(i.autoSkip?Vo(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=Io.length-1;o>=Io.indexOf(i);o--){const i=Io[o];if(Ro[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return Io[i?Io.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&"year"!==this._unit?function(t){for(let e=Io.indexOf(t)+1,i=Io.length;e+t.value)))}initOffsets(t=[]){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=J(s,0,o),n=J(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||Vo(n.minUnit,e,i,this._getLabelCapacity(e)),a=l(s.ticks.stepSize,1),r="week"===o&&n.isoWeekday,h=N(r)||!0===r,c={};let d,u,f=e;if(h&&(f=+t.startOf(f,"isoWeek",r)),f=+t.startOf(f,h?"day":o),t.diff(i,e,o)>1e5*a)throw new Error(e+" and "+i+" are too far apart with stepSize of "+a+" "+o);const g="data"===s.ticks.source&&this.getDataTimestamps();for(d=f,u=0;d+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}format(t,e){const i=this.options.time.displayFormats,s=this._unit,n=e||i[s];return this._adapter.format(t,n)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.ticks.callback;if(o)return d(o,[t,e,i],this);const a=n.time.displayFormats,r=this._unit,l=this._majorUnit,h=r&&a[r],c=l&&a[l],u=i[e],f=l&&c&&u&&u.major;return this._adapter.format(t,s||(f?c:h))}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=it(t,"pos",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=it(t,"time",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}var jo=Object.freeze({__proto__:null,CategoryScale:class extends Js{static id="category";static defaults={ticks:{callback:po}};constructor(t){super(t),this._startValue=void 0,this._valueRange=0,this._addedLabels=[]}init(t){const e=this._addedLabels;if(e.length){const t=this.getLabels();for(const{index:i,label:s}of e)t[i]===s&&t.splice(i,1);this._addedLabels=[]}super.init(t)}parse(t,e){if(s(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:J(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:go(i,t,l(e,t),this._addedLabels),i.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);"ticks"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){return po.call(this,t)}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return"number"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}},LinearScale:bo,LogarithmicScale:ko,RadialLinearScale:Eo,TimeScale:No,TimeSeriesScale:class extends No{static id="timeseries";static defaults=No.defaults;constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=Ho(e,this.min),this._tableRange=Ho(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;ot-e))}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(Ho(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return Ho(this._table,i*this._tableRange+this._minPos,!0)}}});const $o=["rgb(54, 162, 235)","rgb(255, 99, 132)","rgb(255, 159, 64)","rgb(255, 205, 86)","rgb(75, 192, 192)","rgb(153, 102, 255)","rgb(201, 203, 207)"],Yo=$o.map((t=>t.replace("rgb(","rgba(").replace(")",", 0.5)")));function Uo(t){return $o[t%$o.length]}function Xo(t){return Yo[t%Yo.length]}function qo(t){let e=0;return(i,s)=>{const n=t.getDatasetMeta(s).controller;n instanceof jn?e=function(t,e){return t.backgroundColor=t.data.map((()=>Uo(e++))),e}(i,e):n instanceof $n?e=function(t,e){return t.backgroundColor=t.data.map((()=>Xo(e++))),e}(i,e):n&&(e=function(t,e){return t.borderColor=Uo(e),t.backgroundColor=Xo(e),++e}(i,e))}}function Ko(t){let e;for(e in t)if(t[e].borderColor||t[e].backgroundColor)return!0;return!1}var Go={id:"colors",defaults:{enabled:!0,forceOverride:!1},beforeLayout(t,e,i){if(!i.enabled)return;const{data:{datasets:s},options:n}=t.config,{elements:o}=n;if(!i.forceOverride&&(Ko(s)||(a=n)&&(a.borderColor||a.backgroundColor)||o&&Ko(o)))return;var a;const r=qo(t);s.forEach(r)}};function Zo(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{configurable:!0,enumerable:!0,writable:!0,value:e})}}function Jo(t){t.data.datasets.forEach((t=>{Zo(t)}))}var Qo={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void Jo(t);const n=t.width;t.data.datasets.forEach(((e,o)=>{const{_data:a,indexAxis:r}=e,l=t.getDatasetMeta(o),h=a||e.data;if("y"===Pi([r,t.options.indexAxis]))return;if(!l.controller.supportsDecimation)return;const c=t.scales[l.xAxisID];if("linear"!==c.type&&"time"!==c.type)return;if(t.options.parsing)return;let{start:d,count:u}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=J(it(e,o.axis,a).lo,0,i-1)),s=h?J(it(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(l,h);if(u<=(i.threshold||4*n))return void Zo(e);let f;switch(s(a)&&(e._data=h,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":f=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;cu&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(h,d,u,n,i);break;case"min-max":f=function(t,e,i,n){let o,a,r,l,h,c,d,u,f,g,p=0,m=0;const x=[],b=e+i-1,_=t[e].x,y=t[b].x-_;for(o=e;og&&(g=l,d=o),p=(m*p+a.x)/++m;else{const i=o-1;if(!s(c)&&!s(d)){const e=Math.min(c,d),s=Math.max(c,d);e!==u&&e!==i&&x.push({...t[e],x:p}),s!==u&&s!==i&&x.push({...t[s],x:p})}o>0&&i!==u&&x.push(t[i]),x.push(a),h=e,m=0,f=g=l,c=d=u=o}}return x}(h,d,u,n);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=f}))},destroy(t){Jo(t)}};function ta(t,e,i,s){if(s)return;let n=e[t],o=i[t];return"angle"===t&&(n=G(n),o=G(o)),{property:t,start:n,end:o}}function ea(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function ia(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function sa(t,e){let i=[],s=!1;return n(t)?(s=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=ea(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new no({points:i,options:{tension:0},_loop:s,_fullLoop:s}):null}function na(t){return t&&!1!==t.fill}function oa(t,e,i){let s=t[e].fill;const n=[e];let o;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!a(s))return s;if(o=t[s],!o)return!1;if(o.visible)return s;n.push(s),s=o.fill}return!1}function aa(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=l(i&&i.target,i);void 0===s&&(s=!!e.backgroundColor);if(!1===s||null===s)return!1;if(!0===s)return"origin";return s}(t);if(o(s))return!isNaN(s.value)&&s;let n=parseFloat(s);return a(n)&&Math.floor(n)===n?function(t,e,i,s){"-"!==t&&"+"!==t||(i=e+i);if(i===e||i<0||i>=s)return!1;return i}(s[0],e,n,i):["origin","start","end","stack","shape"].indexOf(s)>=0&&s}function ra(t,e,i){const s=[];for(let n=0;n=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&i.fill&&da(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;na(i)&&da(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;na(s)&&"beforeDatasetDraw"===i.drawTime&&da(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const xa=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=t.pointStyleWidth||Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class ba extends Hs{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=d(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=Si(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=xa(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,s,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign="left",n.textBaseline="middle";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const{itemWidth:p,itemHeight:m}=function(t,e,i,s,n){const o=function(t,e,i,s){let n=t.text;n&&"string"!=typeof n&&(n=n.reduce(((t,e)=>t.length>e.length?t:e)));return e+i.size/2+s.measureText(n).width}(s,t,e,i),a=function(t,e,i){let s=t;"string"!=typeof e.text&&(s=_a(e,i));return s}(n,s,e.lineHeight);return{itemWidth:o,itemHeight:a}}(i,e,n,t,s);o>0&&u+m+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:m},d=Math.max(d,p),u+=m+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:n}}=this,o=Oi(n,this.left,this.width);if(this.isHorizontal()){let n=0,a=ft(i,this.left+s,this.right-this.lineWidths[n]);for(const r of e)n!==r.row&&(n=r.row,a=ft(i,this.left+s,this.right-this.lineWidths[n])),r.top+=this.top+t+s,r.left=o.leftForLtr(o.x(a),r.width),a+=r.width+s}else{let n=0,a=ft(i,this.top+t+s,this.bottom-this.columnSizes[n].height);for(const r of e)r.col!==n&&(n=r.col,a=ft(i,this.top+t+s,this.bottom-this.columnSizes[n].height)),r.top=a,r.left+=this.left+s,r.left=o.leftForLtr(o.x(r.left),r.width),a+=r.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){if(this.options.display){const t=this.ctx;Ie(t,this),this._draw(),ze(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:n,labels:o}=t,a=ue.color,r=Oi(t.rtl,this.left,this.width),h=Si(o.font),{padding:c}=o,d=h.size,u=d/2;let f;this.drawTitle(),s.textAlign=r.textAlign("left"),s.textBaseline="middle",s.lineWidth=.5,s.font=h.string;const{boxWidth:g,boxHeight:p,itemHeight:m}=xa(o,d),x=this.isHorizontal(),b=this._computeTitleHeight();f=x?{x:ft(n,this.left+c,this.right-i[0]),y:this.top+c+b,line:0}:{x:this.left+c,y:ft(n,this.top+b+c,this.bottom-e[0].height),line:0},Ai(this.ctx,t.textDirection);const _=m+c;this.legendItems.forEach(((y,v)=>{s.strokeStyle=y.fontColor,s.fillStyle=y.fontColor;const M=s.measureText(y.text).width,w=r.textAlign(y.textAlign||(y.textAlign=o.textAlign)),k=g+u+M;let S=f.x,P=f.y;r.setWidth(this.width),x?v>0&&S+k+c>this.right&&(P=f.y+=_,f.line++,S=f.x=ft(n,this.left+c,this.right-i[f.line])):v>0&&P+_>this.bottom&&(S=f.x=S+e[f.line].width+c,f.line++,P=f.y=ft(n,this.top+b+c,this.bottom-e[f.line].height));if(function(t,e,i){if(isNaN(g)||g<=0||isNaN(p)||p<0)return;s.save();const n=l(i.lineWidth,1);if(s.fillStyle=l(i.fillStyle,a),s.lineCap=l(i.lineCap,"butt"),s.lineDashOffset=l(i.lineDashOffset,0),s.lineJoin=l(i.lineJoin,"miter"),s.lineWidth=n,s.strokeStyle=l(i.strokeStyle,a),s.setLineDash(l(i.lineDash,[])),o.usePointStyle){const a={radius:p*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},l=r.xPlus(t,g/2);Ee(s,a,l,e+u,o.pointStyleWidth&&g)}else{const o=e+Math.max((d-p)/2,0),a=r.leftForLtr(t,g),l=wi(i.borderRadius);s.beginPath(),Object.values(l).some((t=>0!==t))?He(s,{x:a,y:o,w:g,h:p,radius:l}):s.rect(a,o,g,p),s.fill(),0!==n&&s.stroke()}s.restore()}(r.x(S),P,y),S=gt(w,S+g+u,x?S+k:this.right,t.rtl),function(t,e,i){Ne(s,i.text,t,e+m/2,h,{strikethrough:i.hidden,textAlign:r.textAlign(i.textAlign)})}(r.x(S),P,y),x)f.x+=k+c;else if("string"!=typeof y.text){const t=h.lineHeight;f.y+=_a(y,t)+c}else f.y+=_})),Ti(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=Si(e.font),s=ki(e.padding);if(!e.display)return;const n=Oi(t.rtl,this.left,this.width),o=this.ctx,a=e.position,r=i.size/2,l=s.top+r;let h,c=this.left,d=this.width;if(this.isHorizontal())d=Math.max(...this.lineWidths),h=this.top+l,c=ft(t.align,c,this.right-d);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);h=l+ft(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const u=ft(a,c,c+d);o.textAlign=n.textAlign(ut(a)),o.textBaseline="middle",o.strokeStyle=e.color,o.fillStyle=e.color,o.font=i.string,Ne(o,e.text,u,h,i)}_computeTitleHeight(){const t=this.options.title,e=Si(t.font),i=ki(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(tt(t,this.left,this.right)&&tt(e,this.top,this.bottom))for(n=this.legendHitBoxes,i=0;it.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o,useBorderRadius:a,borderRadius:r}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const l=t.controller.getStyle(i?0:void 0),h=ki(l.borderWidth);return{text:e[t.index].label,fillStyle:l.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:l.borderCapStyle,lineDash:l.borderDash,lineDashOffset:l.borderDashOffset,lineJoin:l.borderJoinStyle,lineWidth:(h.width+h.height)/4,strokeStyle:l.borderColor,pointStyle:s||l.pointStyle,rotation:l.rotation,textAlign:n||l.textAlign,borderRadius:a&&(r||l.borderRadius),datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class va extends Hs{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const s=n(i.text)?i.text.length:1;this._padding=ki(i.padding);const o=s*Si(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=o:this.width=o}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:n,options:o}=this,a=o.align;let r,l,h,c=0;return this.isHorizontal()?(l=ft(a,i,n),h=e+t,r=n-i):("left"===o.position?(l=i+t,h=ft(a,s,e),c=-.5*C):(l=n-t,h=ft(a,e,s),c=.5*C),r=s-e),{titleX:l,titleY:h,maxWidth:r,rotation:c}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=Si(e.font),s=i.lineHeight/2+this._padding.top,{titleX:n,titleY:o,maxWidth:a,rotation:r}=this._drawArgs(s);Ne(t,e.text,0,0,i,{color:e.color,maxWidth:a,rotation:r,textAlign:ut(e.align),textBaseline:"middle",translation:[n,o]})}}var Ma={id:"title",_element:va,start(t,e,i){!function(t,e){const i=new va({ctx:t.ctx,options:e,chart:t});as.configure(t,i,e),as.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;as.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;as.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const wa=new WeakMap;var ka={id:"subtitle",start(t,e,i){const s=new va({ctx:t.ctx,options:i,chart:t});as.configure(t,s,i),as.addBox(t,s),wa.set(t,s)},stop(t){as.removeBox(t,wa.get(t)),wa.delete(t)},beforeUpdate(t,e,i){const s=wa.get(t);as.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Sa={average(t){if(!t.length)return!1;let e,i,s=new Set,n=0,o=0;for(e=0,i=t.length;et+e))/s.size,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i-1?t.split("\n"):t}function Ca(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Oa(t,e){const i=t.chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=Si(e.bodyFont),h=Si(e.titleFont),c=Si(e.footerFont),d=o.length,f=n.length,g=s.length,p=ki(e.padding);let m=p.height,x=0,b=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(b+=t.beforeBody.length+t.afterBody.length,d&&(m+=d*h.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),b){m+=g*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(b-g)*l.lineHeight+(b-1)*e.bodySpacing}f&&(m+=e.footerMarginTop+f*c.lineHeight+(f-1)*e.footerSpacing);let _=0;const y=function(t){x=Math.max(x,i.measureText(t).width+_)};return i.save(),i.font=h.string,u(t.title,y),i.font=l.string,u(t.beforeBody.concat(t.afterBody),y),_=e.displayColors?a+2+e.boxPadding:0,u(s,(t=>{u(t.before,y),u(t.lines,y),u(t.after,y)})),_=0,i.font=c.string,u(t.footer,y),i.restore(),x+=p.width,{width:x,height:m}}function Aa(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h="center";return"center"===s?h=n<=(r+l)/2?"left":"right":n<=o/2?h="left":n>=a-o/2&&(h="right"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return"left"===t&&n+o+a>e.width||"right"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h="center"),h}function Ta(t,e,i){const s=i.yAlign||e.yAlign||function(t,e){const{y:i,height:s}=e;return it.height-s/2?"bottom":"center"}(t,i);return{xAlign:i.xAlign||e.xAlign||Aa(t,e,i,s),yAlign:s}}function La(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=wi(a);let g=function(t,e){let{x:i,width:s}=t;return"right"===e?i-=s:"center"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return"top"===e?s+=i:s-="bottom"===e?n+i:n/2,s}(e,l,h);return"center"===l?"left"===r?g+=h:"right"===r&&(g-=h):"left"===r?g-=Math.max(c,u)+n:"right"===r&&(g+=Math.max(d,f)+n),{x:J(g,0,s.width-e.width),y:J(p,0,s.height-e.height)}}function Ea(t,e,i){const s=ki(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-s.right:t.x+s.left}function Ra(t){return Pa([],Da(t))}function Ia(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}const za={beforeTitle:e,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(s>0&&e.dataIndex{const e={before:[],lines:[],after:[]},n=Ia(i,t);Pa(e.before,Da(Fa(n,"beforeLabel",this,t))),Pa(e.lines,Fa(n,"label",this,t)),Pa(e.after,Da(Fa(n,"afterLabel",this,t))),s.push(e)})),s}getAfterBody(t,e){return Ra(Fa(e.callbacks,"afterBody",this,t))}getFooter(t,e){const{callbacks:i}=e,s=Fa(i,"beforeFooter",this,t),n=Fa(i,"footer",this,t),o=Fa(i,"afterFooter",this,t);let a=[];return a=Pa(a,Da(s)),a=Pa(a,Da(n)),a=Pa(a,Da(o)),a}_createItems(t){const e=this._active,i=this.chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;at.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),u(l,(e=>{const i=Ia(t.callbacks,e);s.push(Fa(i,"labelColor",this,e)),n.push(Fa(i,"labelPointStyle",this,e)),o.push(Fa(i,"labelTextColor",this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Sa[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Oa(this,i),a=Object.assign({},t,e),r=Ta(this.chart,i,a),l=La(i,a,r,this.chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this.chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=wi(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,x,b,_,y;return"center"===n?(_=u+g/2,"left"===s?(p=d,m=p-o,b=_+o,y=_-o):(p=d+f,m=p+o,b=_-o,y=_+o),x=p):(m="left"===s?d+Math.max(r,h)+o:"right"===s?d+f-Math.max(l,c)-o:this.caretX,"top"===n?(b=u,_=b-o,p=m-o,x=m+o):(b=u+g,_=b+o,p=m+o,x=m-o),y=b),{x1:p,x2:m,x3:x,y1:b,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=Oi(i.rtl,this.x,this.width);for(t.x=Ea(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline="middle",o=Si(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r0!==t))?(t.beginPath(),t.fillStyle=n.multiKeyBackground,He(t,{x:e,y:g,w:h,h:l,radius:r}),t.fill(),t.stroke(),t.fillStyle=a.backgroundColor,t.beginPath(),He(t,{x:i,y:g+1,w:h-2,h:l-2,radius:r}),t.fill()):(t.fillStyle=n.multiKeyBackground,t.fillRect(e,g,h,l),t.strokeRect(e,g,h,l),t.fillStyle=a.backgroundColor,t.fillRect(i,g+1,h-2,l-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=Si(i.bodyFont);let d=c.lineHeight,f=0;const g=Oi(i.rtl,this.x,this.width),p=function(i){e.fillText(i,g.x(t.x+f),t.y+d/2),t.y+=d+n},m=g.textAlign(o);let x,b,_,y,v,M,w;for(e.textAlign=o,e.textBaseline="middle",e.font=c.string,t.x=Ea(this,m,i),e.fillStyle=i.bodyColor,u(this.beforeBody,p),f=a&&"right"!==m?"center"===o?l/2+h:l+2+h:0,y=0,M=s.length;y0&&e.stroke()}_updateAnimationTarget(t){const e=this.chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Sa[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Oa(this,t),a=Object.assign({},i,this._size),r=Ta(e,t,a),l=La(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}_willRender(){return!!this.opacity}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=ki(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),Ai(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),Ti(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this.chart.getDatasetMeta(t);if(!i)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!f(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this._ignoreReplayEvents=!0,this.update(!0))}handleEvent(t,e,i=!0){if(e&&this._ignoreReplayEvents)return!1;this._ignoreReplayEvents=!1;const s=this.options,n=this._active||[],o=this._getActiveElements(t,n,e,i),a=this._positionChanged(o,t),r=e||!f(o,n)||a;return r&&(this._active=o,(s.enabled||s.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),r}_getActiveElements(t,e,i,s){const n=this.options;if("mouseout"===t.type)return[];if(!s)return e.filter((t=>this.chart.data.datasets[t.datasetIndex]&&void 0!==this.chart.getDatasetMeta(t.datasetIndex).controller.getParsed(t.index)));const o=this.chart.getElementsAtEventForMode(t,n.mode,n,i);return n.reverse&&o.reverse(),o}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Sa[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}var Ba={id:"tooltip",_element:Va,positioners:Sa,afterInit(t,e,i){i&&(t.tooltip=new Va({chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip;if(e&&e._willRender()){const i={tooltip:e};if(!1===t.notifyPlugins("beforeTooltipDraw",{...i,cancelable:!0}))return;e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i)}},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i,e.inChartArea)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,boxPadding:0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:za},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]};return An.register(Yn,jo,fo,t),An.helpers={...Wi},An._adapters=Rn,An.Animation=Cs,An.Animations=Os,An.animator=bt,An.controllers=en.controllers.items,An.DatasetController=Ns,An.Element=Hs,An.elements=fo,An.Interaction=Xi,An.layouts=as,An.platforms=Ss,An.Scale=Js,An.Ticks=ae,Object.assign(An,Yn,jo,fo,t,Ss),An.Chart=An,"undefined"!=typeof window&&(window.Chart=An),An})); +//# sourceMappingURL=chart.umd.js.map diff --git a/plugins/hanewari/token-meter-board/miniapp/miniapp.json b/plugins/hanewari/token-meter-board/miniapp/miniapp.json new file mode 100644 index 00000000..54b1b5ce --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/miniapp.json @@ -0,0 +1,20 @@ +{ + "schemaVersion": 1, + "artifacts": { + "client": [ + "./miniapp/client" + ], + "node": [ + "./miniapp/node" + ] + }, + "runtime": { + "kind": "process", + "entry": "./miniapp/node/server.mjs", + "lifecycle": "on-demand" + }, + "surface": { + "path": "/" + }, + "mcpEndpoints": [] +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs new file mode 100644 index 00000000..1f3289f5 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs @@ -0,0 +1,707 @@ +// token-meter shared helpers: data-dir resolution, catalog parsing, log enrichment, metrics. +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; +import { createRequire } from 'node:module'; +import { getFactsStore, syncFacts, assistantCallsForTurn, turnMetaForTurn, factsStats } from './facts.mjs'; + +export const SQLITE_REQUIREMENT = + 'token-meter requires Node.js 23.4+ (24 LTS recommended) so that the built-in node:sqlite module is available without flags.'; + +// node:sqlite is unflagged only on Node.js >= 23.4. Load it lazily so that an +// unsupported runtime gets a clear tool error instead of a process crash. +let sqliteModule; +let sqliteError; +function loadSqlite() { + if (sqliteModule === undefined && sqliteError === undefined) { + try { + sqliteModule = createRequire(import.meta.url)('node:sqlite'); + } catch (err) { + sqliteModule = null; + sqliteError = err; + } + } + return { sqlite: sqliteModule, error: sqliteError ?? null }; +} + +export function resolveDataDir(env = process.env) { + if (env.MINIMAX_DATA_DIR && fs.existsSync(env.MINIMAX_DATA_DIR)) { + return path.resolve(env.MINIMAX_DATA_DIR); + } + if (env.PLUGIN_DATA) { + // /v2/plugin-data// -> dataDir is four levels up. + const candidate = path.resolve(env.PLUGIN_DATA, '..', '..', '..', '..'); + if (fs.existsSync(path.join(candidate, 'v2'))) return candidate; + } + return path.join(os.homedir(), '.minimax'); +} + +export function dbPath(dataDir) { + return path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); +} + +// Open the runtime state database read-only. +// Returns { db, error }: exactly one of the two is non-null. +export function openDb(dataDir) { + const { sqlite, error: sqliteErr } = loadSqlite(); + if (!sqlite) { + return { db: null, error: `${SQLITE_REQUIREMENT} (${sqliteErr?.code || sqliteErr?.message || 'node:sqlite unavailable'})` }; + } + const file = dbPath(dataDir); + if (!fs.existsSync(file)) { + return { db: null, error: `runtime state database not found at ${file} — is this a MiniMax Code data directory with recorded usage?` }; + } + try { + return { db: new sqlite.DatabaseSync(file, { readOnly: true }), error: null }; + } catch (err) { + return { db: null, error: `failed to open runtime state database read-only: ${err.message}` }; + } +} + +// The message fact store is shared per runtime database, so every query in this +// process reuses the same extraction instead of re-parsing the message table. +export function factsStore(dataDir) { + return getFactsStore(dataDir); +} + +// Snapshot of the message-fact cache, for the health endpoint. +export { factsStats }; + +// Query raw usage rows in [startMs, endMs] ascending by ts. +export function queryUsageRows(db, startMs, endMs) { + return db + .prepare( + `SELECT session_id, agent_name, turn_id, model, ts, + input_tokens, output_tokens, reasoning_tokens, + cache_read_tokens, cache_write_tokens, cost_usd + FROM local_runtime_token_usage + WHERE ts >= ? AND ts <= ? + ORDER BY ts`, + ) + .all(startMs, endMs); +} + +export function dayKey(ms) { + const d = new Date(ms); + const y = d.getFullYear(); + const m = String(d.getMonth() + 1).padStart(2, '0'); + const dd = String(d.getDate()).padStart(2, '0'); + return `${y}-${m}-${dd}`; +} + +export function clampInt(value, min, max, fallback) { + const n = Number.parseInt(value, 10); + if (Number.isNaN(n)) return fallback; + return Math.min(max, Math.max(min, n)); +} + +// Resolve a query window. Either explicit startDate/endDate (YYYY-MM-DD, inclusive, +// local time) or `days` = trailing N days including today. +export function resolveWindow({ days, startDate, endDate } = {}, now = Date.now()) { + if (startDate) { + const start = new Date(`${startDate}T00:00:00`); + const endBase = endDate ? new Date(`${endDate}T23:59:59.999`) : new Date(start.getTime() + 86400000 - 1); + if (Number.isNaN(start.getTime()) || Number.isNaN(endBase.getTime())) { + throw new Error(`invalid startDate/endDate: ${startDate} ${endDate || ''}`.trim()); + } + const startMs = start.getTime(); + const endMs = Math.min(endBase.getTime(), now); + if (endMs < startMs) throw new Error('window end is before start'); + return { startMs, endMs, label: `${dayKey(startMs)}..${dayKey(endMs)}` }; + } + const n = clampInt(days ?? 1, 1, 90, 1); + const todayStart = new Date(); + todayStart.setHours(0, 0, 0, 0); + const startMs = todayStart.getTime() - (n - 1) * 86400000; + return { startMs, endMs: now, label: n === 1 ? dayKey(startMs) : `${dayKey(startMs)}..${dayKey(now)}` }; +} + +// --- config.yaml catalog (provider/model display names) ---------------------- + +function unquote(value) { + const v = value.trim(); + if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) { + return v.slice(1, -1); + } + return v; +} + +// Minimal line-based YAML reader targeting only the provider sections we need. +// Returns { providers: Map, modelNames: Map<'providerId/modelId', name>, +// modelToProvider: Map }. +// +// The catalog is read from the same config.yaml on every query, so it is cached +// per (mtime, size) and only re-parsed when the file actually changes. +let catalogCache = null; + +export function loadCatalog(dataDir) { + const file = path.join(dataDir, 'config.yaml'); + let stamp = null; + try { + const st = fs.statSync(file); + stamp = `${st.mtimeMs}:${st.size}`; + } catch { + stamp = null; + } + if (catalogCache && catalogCache.stamp === stamp) return catalogCache.catalog; + const catalog = parseCatalog(file); + catalogCache = { stamp, catalog }; + return catalog; +} + +function parseCatalog(file) { + const providers = new Map(); + const modelNames = new Map(); + const modelToProvider = new Map(); + let text; + try { + text = fs.readFileSync(file, 'utf8'); + } catch { + return { providers, modelNames, modelToProvider }; + } + try { + // ctx: null | { section: 'custom'|'builtin', providerId, providerIndent, inModels, modelId, modelIndent } + let ctx = null; + for (const rawLine of text.split('\n')) { + if (!rawLine.trim() || rawLine.trimStart().startsWith('#')) continue; + const indent = rawLine.length - rawLine.trimStart().length; + const line = rawLine.trim(); + + if (indent === 0) { + if (line === 'custom_provider:') { + ctx = { section: 'custom', providerId: null, providerIndent: -1, inModels: false, modelId: null }; + } else if (line === 'provider:') { + ctx = { section: 'builtin', providerId: null, providerIndent: -1, inModels: false, modelId: null }; + } else if (!line.startsWith('-')) { + ctx = null; // left the provider sections + } + continue; + } + if (!ctx) continue; + + // Provider entry: " provider-c582e6:" or " minimax:" + if (ctx.providerId === null || indent <= ctx.providerIndent) { + const m = line.match(/^([A-Za-z0-9._-]+):\s*$/); + if (m && indent >= 2) { + ctx.providerId = m[1]; + ctx.providerIndent = indent; + ctx.inModels = false; + ctx.modelId = null; + if (!providers.has(ctx.providerId)) { + providers.set(ctx.providerId, { name: ctx.providerId, kind: ctx.section }); + } + continue; + } + } + if (!ctx.providerId) continue; + + const kv = line.match(/^([A-Za-z0-9._-]+):\s*(.*)$/); + if (!kv) continue; + const [, key, rest] = kv; + + if (key === 'models' && rest === '') { + ctx.inModels = true; + ctx.modelId = null; + ctx.modelIndent = -1; + continue; + } + if (!ctx.inModels && key === 'name' && rest) { + providers.get(ctx.providerId).name = unquote(rest); + continue; + } + if (ctx.inModels) { + if (ctx.modelId === null || indent <= ctx.modelIndent) { + const mm = line.match(/^([A-Za-z0-9._-]+):\s*$/); + if (mm) { + ctx.modelId = mm[1]; + ctx.modelIndent = indent; + modelToProvider.set(ctx.modelId, ctx.providerId); + continue; + } + } + if (ctx.modelId && key === 'name' && rest) { + modelNames.set(`${ctx.providerId}/${ctx.modelId}`, unquote(rest)); + } + } + } + } catch { + // tolerate partial catalog + } + return { providers, modelNames, modelToProvider }; +} + +// --- runtime log enrichment (turn_id -> provider/model, per-call status) ----- +// +// Log files rotate hourly: runtime-YYYYMMDDHH.log (local time). Select files by +// filename hour intersecting the window (plus 1h look-behind for stragglers), +// so coverage spans the whole window instead of just the newest few files. +// Each llm_response_identifiers line contributes one call record with its own +// timestamp and response_status; a turn produces one line per LLM call. + +const LOG_LINE_TS = /^\[(\d{2}):(\d{2}):(\d{2})\.(\d{3})\]/; + +// Log files rotate hourly and are append-only, so a file whose (mtime, size) is +// unchanged still holds exactly the same records. Caching per file means a +// window switch re-reads only the hour currently being written instead of +// rescanning every hour of the window — that was ≈750 ms on a one-week window. +const logFileCache = new Map(); // absolute path -> { stamp, records } +const LOG_FILE_CACHE_MAX = 256; // bound the memory of a long-running runtime + +function stampOf(st) { + return `${st.mtimeMs}:${st.size}`; +} + +function parseLogFile(file, maxBytesPerFile) { + const records = []; + let text; + try { + const st = fs.statSync(file); + const fd = fs.openSync(file, 'r'); + try { + const start = st.size > maxBytesPerFile ? st.size - maxBytesPerFile : 0; + const buf = Buffer.alloc(st.size - start); + fs.readSync(fd, buf, 0, buf.length, start); + text = buf.toString('utf8'); + } finally { + fs.closeSync(fd); + } + } catch { + return null; + } + for (const line of text.split('\n')) { + const i = line.indexOf('llm_response_identifiers '); + if (i < 0) continue; + const j = line.indexOf('{', i); + if (j < 0) continue; + let obj; + try { + obj = JSON.parse(line.slice(j)); + } catch { + continue; // partial tail line or unexpected shape + } + if (!obj || !obj.turn_id) continue; + const tm = line.slice(0, i).match(LOG_LINE_TS); + // Seconds since local midnight. The capture groups are strings, so they + // must be coerced explicitly — `a + tm[3]` would concatenate instead of add. + const ts = tm + ? Number(tm[1]) * 3600 + Number(tm[2]) * 60 + Number(tm[3]) + Number(tm[4]) / 1000 + : null; + records.push({ + turn_id: obj.turn_id, + provider: obj.provider || null, + model: obj.model || null, + status: typeof obj.response_status === 'number' ? obj.response_status : null, + ts, + }); + } + return records; +} + +export function loadTurnEnrichment(dataDir, windowStartMs, options = {}) { + const maxBytesPerFile = options.maxBytesPerFile ?? 12 * 1024 * 1024; + const now = options.now ?? Date.now(); + const map = new Map(); + const dir = path.join(dataDir, 'v2', 'observability', 'logs'); + let names; + try { + names = fs.readdirSync(dir).filter((f) => /^runtime-\d+\.log$/.test(f)); + } catch { + return { map, filesScanned: 0 }; + } + const firstHour = new Date(windowStartMs - 3600000); + firstHour.setMinutes(0, 0, 0); + let filesScanned = 0; + for (const name of names) { + const m = name.match(/^runtime-(\d{4})(\d{2})(\d{2})(\d{2})\.log$/); + if (!m) continue; + const fileHourMs = new Date(+m[1], +m[2] - 1, +m[3], +m[4]).getTime(); + if (fileHourMs < firstHour.getTime() || fileHourMs > now + 3600000) continue; + const p = path.join(dir, name); + let stamp = null; + try { + stamp = stampOf(fs.statSync(p)); + } catch { + continue; + } + const cached = logFileCache.get(p); + let records; + if (cached && cached.stamp === stamp) { + records = cached.records; + } else { + const parsed = parseLogFile(p, maxBytesPerFile); + if (!parsed) continue; + records = parsed; + logFileCache.set(p, { stamp, records }); + while (logFileCache.size > LOG_FILE_CACHE_MAX) { + const oldest = logFileCache.keys().next().value; + if (oldest === p) break; + logFileCache.delete(oldest); + } + } + filesScanned += 1; + // The log line carries a wall-clock time; the file name carries the hour it + // belongs to, so the absolute timestamp is the file's day base plus that. + const dayBase = new Date(+m[1], +m[2] - 1, +m[3]).getTime(); + for (const rec of records) { + if (!map.has(rec.turn_id)) map.set(rec.turn_id, { provider: null, model: null, calls: [] }); + const entry = map.get(rec.turn_id); + if (!entry.provider && rec.provider) entry.provider = rec.provider; + if (!entry.model && rec.model) entry.model = rec.model; + entry.calls.push({ ts: rec.ts == null ? null : dayBase + rec.ts * 1000, status: rec.status }); + } + } + for (const entry of map.values()) entry.calls.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0)); + return { map, filesScanned }; +} + +// --- row identity + metrics --------------------------------------------------- + +export function resolveRowIdentity(row, enrichment, catalog) { + let model = row.model || null; + let provider = null; + const hit = row.turn_id ? enrichment.get(row.turn_id) : null; + if (hit) { + provider = hit.provider || null; + model = model || hit.model || null; + } + let providerId = null; + let custom = false; + if (provider && provider.startsWith('custom_provider:')) { + providerId = provider.slice('custom_provider:'.length); + custom = true; + } else if (provider) { + providerId = provider; + custom = catalog.providers.get(providerId)?.kind === 'custom'; + } + if (!providerId && model && catalog.modelToProvider.has(model)) { + providerId = catalog.modelToProvider.get(model); + custom = catalog.providers.get(providerId)?.kind === 'custom'; + provider = custom ? `custom_provider:${providerId}` : providerId; + } + const modelKey = providerId && model ? `${providerId}/${model}` : null; + return { + provider: provider || 'unknown', + providerId: providerId || 'unknown', + model: model || '(unknown)', + custom, + providerName: (providerId && catalog.providers.get(providerId)?.name) || provider || 'unknown', + modelName: (modelKey && catalog.modelNames.get(modelKey)) || model || '(unknown)', + }; +} + +export function emptyMetrics() { + return { + calls: 0, + inputTokens: 0, + outputTokens: 0, + reasoningTokens: 0, + cacheReadTokens: 0, + cacheWriteTokens: 0, + totalTokens: 0, + cacheHitRate: null, + costUsd: 0, + }; +} + +export function addRow(m, r) { + m.calls += 1; + m.inputTokens += r.input_tokens || 0; + m.outputTokens += r.output_tokens || 0; + m.reasoningTokens += r.reasoning_tokens || 0; + m.cacheReadTokens += r.cache_read_tokens || 0; + m.cacheWriteTokens += r.cache_write_tokens || 0; + m.costUsd += r.cost_usd || 0; +} + +export function finalize(m) { + m.totalTokens = m.inputTokens + m.outputTokens + m.reasoningTokens + m.cacheReadTokens + m.cacheWriteTokens; + const denom = m.inputTokens + m.cacheReadTokens; + m.cacheHitRate = denom > 0 ? Math.round((m.cacheReadTokens / denom) * 10000) / 10000 : null; + m.costUsd = Math.round(m.costUsd * 1e6) / 1e6; + return m; +} + +export function sortGroups(groups) { + return groups.sort((a, b) => { + if (a.custom !== b.custom) return a.custom ? -1 : 1; + return b.totalTokens - a.totalTokens; + }); +} + +// --- per-call ledger (usage rows joined with message timing + log status) ---- +// +// local_runtime_token_usage never stores the model and has no call duration. +// One side source completes the picture: assistant message rows +// (local_runtime_message_rows.data_json) carry the very timings MiniMax Code +// itself uses for pi_llm_tokens_per_second — usage.request_duration_ms (request +// start → stream end) and usage.decode_duration_ms (first token → stream end) — +// plus finish_reason. Log lines additionally carry response_status. +// +// Pairing: inside a turn the runtime writes two records per call — the usage +// row is stamped when the call STARTS, and the matching assistant message is +// written when that call ENDS. So the message that belongs to a call that +// started at T is the FIRST message of that turn written at or after T: every +// earlier message of the turn was written before this call started. +// +// That rule replaces the old "the i-th message pairs with the i-th usage row", +// because the message sequence also holds rows that are not model calls at +// all — context compaction writes an assistant row with no usage block (490 +// of the 17,214 assistant messages on this machine). Counting those as calls +// shifted a whole turn by one, so 22.5% of the calls reported the PREVIOUS +// call's decode duration and rate. With the "first message at or after the +// call start" rule all 16,723 measurable calls pair correctly (0 errors), and +// it stays correct when the query window starts in the middle of a turn. +// +// There is deliberately no upper bound on how long a single call may take — +// see the interleaving invariant in buildCallLedger. + +// Bring the in-memory fact store up to date with the database, then hand it +// back. Extracting the message facts is the expensive part of a query, so it +// happens once per process and only picks up newly appended rows afterwards. +export function syncMessageFacts(db, dataDir, options = {}) { + const store = factsStore(dataDir); + syncFacts(store, db, options); + return store; +} + +// Assistant call timings per turn, keyed `${session_id}|${turn_id}`. +// The facts come from the shared store, so this no longer touches the +// message table at all. +export function loadAssistantCallDetails(rows, store) { + const byTurn = new Map(); // key `${session_id}|${turn_id}` -> [{ts, decodeMs, requestMs, finishReason}] + for (const r of rows) { + if (!r.turn_id) continue; + const key = `${r.session_id}|${r.turn_id}`; + if (byTurn.has(key)) continue; + const list = assistantCallsForTurn(store, r.turn_id); + if (list) byTurn.set(key, list); + } + return byTurn; +} + +// Per-turn message metadata for the conversation table. +// +// A turn is exactly one user message followed by however many model calls the +// agent needed before answering, so it is the natural unit for "one thing the +// user asked" — and it is readable from the database the instant the first +// usage row of that turn lands, with no hook and no waiting for the session +// to close. Verified on this machine: 26 turns today, 24 carrying exactly one +// user message, 0 carrying more than one, and all 26 ending on an assistant +// message. +export function loadTurnMessageMeta(rows, store) { + const meta = new Map(); // turn_id -> {userTs, userPreview, lastTs, finishReason, assistantCount} + for (const r of rows) { + if (!r.turn_id || meta.has(r.turn_id)) continue; + const m = turnMetaForTurn(store, r.turn_id); + if (m) meta.set(r.turn_id, m); + } + return meta; +} + +// Build one ledger entry per usage row, ordered by ts. +// +// Pairing (see the header comment for the full invariant): +// - the assistant message is the first message of the turn written at or +// after the call started; +// - the log line is the first llm_response_identifiers record of the turn +// written at or after the call started, and not after the next call of +// the same turn started. +// +// rate = output_tokens / decode_duration. +// +// Validity is the interleaving invariant, not an absolute duration limit: a call +// cannot finish before it starts, and cannot finish after the *next* call in the +// same turn has already started. An absolute cap would reject legitimate long +// calls (a 9-minute run) and push the pairing back onto nearest-neighbour matching, +// which shifts every following row by one — so there is deliberately no upper +// bound on how long a single call may take. + +export function buildCallLedger(rows, enrichment, assistantByTurn, catalog) { + const ledger = []; + const msgCursor = new Map(); // turn key -> next assistant message index + const logCursor = new Map(); // turn key -> next log record index + for (let i = 0; i < rows.length; i += 1) { + const row = rows[i]; + const id = resolveRowIdentity(row, enrichment, catalog); + const key = `${row.session_id}|${row.turn_id}`; + const next = rows[i + 1]; + // The next call of the SAME turn bounds the interval this call owns. + const boundTs = next && next.turn_id === row.turn_id ? next.ts : null; + + // --- assistant message (decode / request timing, finish reason) --- + let msg = null; + const list = row.turn_id ? assistantByTurn.get(key) : null; + if (list && list.length) { + const from = msgCursor.get(key) || 0; + for (let j = from; j < list.length; j += 1) { + const c = list[j]; + // written before this call started — belongs to an earlier call + if (c.ts == null || c.ts < row.ts) continue; + msg = c; + msgCursor.set(key, j + 1); + break; + } + } + + // --- log line (response status) --- + // The runtime writes the llm_response_identifiers line a moment AFTER the + // usage row is stamped (measured: +443 ms … +194 s, median +2.6 s), so a + // nearest-time match walks BACKWARDS and lands on the PREVIOUS call's + // line: of 2220 measured mismatches, every single one was off by one in + // that direction. The matching record is the first one at or after this + // call's start. + let statusHit = null; + const enrichEntry = row.turn_id ? enrichment.get(row.turn_id) : null; + if (enrichEntry && enrichEntry.calls.length) { + const from = logCursor.get(key) || 0; + for (let j = from; j < enrichEntry.calls.length; j += 1) { + const c = enrichEntry.calls[j]; + if (c.ts == null || c.ts < row.ts) continue; + // written after the next call of this turn started — that one owns it + if (boundTs != null && c.ts > boundTs) break; + statusHit = c; + logCursor.set(key, j + 1); + break; + } + } + const status = statusHit ? statusHit.status : null; + const decodeMs = msg ? msg.decodeMs : null; + const requestMs = msg ? msg.requestMs : null; + const output = row.output_tokens || 0; + const succeeded = status == null || status === 200; // a recorded usage row implies a completed call + // Headline rate: identical to the desktop UI's tokens/s — output tokens ÷ decode + // duration (first token → stream end), the span during which tokens actually arrive. + const rate = succeeded && decodeMs > 0 && output > 0 ? Math.round((output / (decodeMs / 1000)) * 100) / 100 : null; + // Whole-request reference (output ÷ request_duration_ms); the gap between the two + // is time-to-first-token plus queueing. + const requestRate = + succeeded && requestMs > 0 && output > 0 ? Math.round((output / (requestMs / 1000)) * 100) / 100 : null; + ledger.push({ + ts: row.ts, + sessionId: row.session_id, + agentName: row.agent_name || null, + turnId: row.turn_id || null, + // identity (from resolveRowIdentity) + provider: id.provider, + providerId: id.providerId, + model: id.model, + custom: id.custom, + providerName: id.providerName, + modelName: id.modelName, + // snake_case token fields keep addRow() compatibility + input_tokens: row.input_tokens || 0, + output_tokens: row.output_tokens || 0, + reasoning_tokens: row.reasoning_tokens || 0, + cache_read_tokens: row.cache_read_tokens || 0, + cache_write_tokens: row.cache_write_tokens || 0, + cost_usd: row.cost_usd || 0, + decodeMs, + requestMs, + finishReason: msg ? msg.finishReason : null, + status, + rate, + requestRate, + }); + } + return ledger; +} + +export function buildLedgerWithDb(db, rows, enrichment, catalog, store) { + return buildCallLedger(rows, enrichment, loadAssistantCallDetails(rows, store), catalog); +} + +// --- rate aggregation --------------------------------------------------------- +// +// The rate shown by MiniMax Code's own UI lives in the desktop bundle and is +// computed as tokensPerSecond = Σ outputTokens / Σ decodeDurationMs over a set of +// calls — i.e. decode-based (first token → stream end) and time-weighted, NOT the +// arithmetic mean of per-call rates. We reproduce exactly that so the board and +// the chat UI agree, and keep the whole-request rate as the reference column +// (their difference is time-to-first-token plus queueing). +// +// `decode > request` is a CONSISTENCY guard, not a truncation detector. +// decode = completed − firstToken and request = completed − requestStarted, so +// decode > request is exactly firstTokenTime < requestStartedAt: the first +// token "arrived" before the request was sent. That cannot happen inside one +// coherent call — the two stamps must come from different attempts. Measured +// on this machine it shows up only on finish_reason='toolUse', where the +// request timer gets re-stamped on the tool-call continuation: 6 of 2674 timed +// calls (0.22%), overshooting by 0.25–2.1s against 3.8–56s requests. Such a +// decode is longer than physically possible and would pad the aggregate's +// denominator, so it is skipped; the per-call value is still shown. +// +// NOTE this is NOT what catches the degenerate sub-second decode spans. Those +// run ~100ms against a multi-second request, so decode < request and they pass +// straight through — they inflate the rate instead, which is a separate known +// property of the runtime's timing (see README). + +export function collectDecodeRates(calls) { + const out = []; + for (const c of calls) { + if (typeof c.rate !== 'number') continue; + if (c.decodeMs != null && c.requestMs != null && c.decodeMs > c.requestMs) continue; + out.push(c.rate); + } + return out; +} + +function round2(v) { + return Math.round(v * 100) / 100; +} + +export function percentile(sorted, p) { + if (!sorted.length) return null; + const idx = Math.min(sorted.length - 1, Math.max(0, Math.round((sorted.length - 1) * p))); + return sorted[idx]; +} + +function describe(values) { + if (!values.length) return null; + const sorted = values.slice().sort((a, b) => a - b); + return { + mean: round2(sorted.reduce((s, v) => s + v, 0) / sorted.length), + p50: round2(percentile(sorted, 0.5)), + p90: round2(percentile(sorted, 0.9)), + max: round2(sorted[sorted.length - 1]), + n: sorted.length, + }; +} + +// MiniMax Code UI basis: Σ output tokens ÷ Σ decode duration. +function weightedRate(calls, msKey, rateKey) { + let tokens = 0; + let ms = 0; + for (const c of calls) { + if (typeof c[rateKey] !== 'number') continue; + if (msKey === 'decodeMs' && c.decodeMs != null && c.requestMs != null && c.decodeMs > c.requestMs) continue; + tokens += c.output_tokens || 0; + ms += c[msKey] || 0; + } + return ms > 0 ? round2(tokens / (ms / 1000)) : null; +} + +// The headline metric: identical to the desktop UI's tokens/s figure. +export function rateStats(calls) { + const d = describe(collectDecodeRates(calls)); + const weighted = weightedRate(calls, 'decodeMs', 'rate'); + return d ? { ...d, weighted } : null; +} + +// Whole-request reference rate (output ÷ request_duration_ms). +export function requestRateStats(calls) { + const values = []; + for (const c of calls) if (typeof c.requestRate === 'number') values.push(c.requestRate); + const d = describe(values); + const weighted = weightedRate(calls, 'requestMs', 'requestRate'); + return d ? { ...d, weighted } : null; +} + +export function meanCallRate(calls) { + return rateStats(calls)?.weighted ?? null; +} + +export function countRatedCalls(calls) { + let n = 0; + for (const c of calls) if (typeof c.rate === 'number') n += 1; + return n; +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs new file mode 100644 index 00000000..ac075c3d --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs @@ -0,0 +1,53 @@ +// token-meter-board child-process fallback dispatcher. +// Spawned by server.mjs only when the Mini App runtime lacks node:sqlite: +// node db-child.mjs +// Prints exactly one JSON document on stdout; exits non-zero on failure. +import { resolveDataDir } from './common.mjs'; +import { buildTrendResult, resolveTrendWindow } from './trend.mjs'; +import { querySummary, querySessions, queryDaily, queryWindow, queryCalls, queryTurns } from './queries.mjs'; + +function run(mode, params) { + const dataDir = params?.dataDir || resolveDataDir(); + const now = Date.now(); + switch (mode) { + case 'trend': { + const { startMs, endMs } = resolveTrendWindow( + { startAt: params?.startAt, endAt: params?.endAt, days: params?.days }, + now, + ); + return buildTrendResult({ + dataDir, + startMs, + endMs, + bucket: params?.bucket, + fillEmpty: params?.fillEmpty, + now, + }); + } + case 'window': + return queryWindow({ ...params, dataDir }, now); + case 'summary': + return querySummary({ ...params, dataDir }, now); + case 'sessions': + return querySessions({ ...params, dataDir }, now); + case 'daily': + return queryDaily({ ...params, dataDir }, now); + case 'calls': + return queryCalls({ ...params, dataDir }, now); + case 'turns': + return queryTurns({ ...params, dataDir }, now); + default: + throw new Error(`unknown mode: ${mode}`); + } +} + +try { + const [, , mode, paramsJson] = process.argv; + const params = paramsJson ? JSON.parse(paramsJson) : {}; + const result = run(mode, params); + process.stdout.write(JSON.stringify(result)); + process.exit(0); +} catch (err) { + process.stdout.write(JSON.stringify({ error: String(err?.message || err), code: err?.code || null })); + process.exit(1); +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs new file mode 100644 index 00000000..55f0fe20 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs @@ -0,0 +1,210 @@ +// token-meter message fact store. +// +// WHY THIS EXISTS +// The runtime database stores every message as a row in local_runtime_message_rows, +// and that table has NO index on turn_id — so any lookup by turn is a full table +// scan. The payloads are whole conversation turns (≈350 MB of JSON on a busy +// machine), while the board only needs four scalars per assistant message: +// decode duration, request duration, finish reason, plus the turn's user-message +// preview. +// +// Pulling data_json into JS and JSON.parse()-ing it measured ≈2.8 s per scan; +// extracting the same scalars inside SQLite measured ≈0.6 s. Doing that twice +// per endpoint (once for call timings, once for turn metadata) and again for +// every endpoint and every window is what made the board feel stuck when the +// query window changed. +// +// So the facts are extracted once, in rowid order, and kept in memory. Later +// scans only pick up the rows appended since the last one (`id > watermark`), +// which is what makes switching the query window instant. The rowid scan seeks +// the INTEGER PRIMARY KEY directly, so it costs nothing but the new rows. +// +// Rows are append-only in this runtime (the table holds immutable source rows +// and the state changes live in a separate diff journal), so a rowid-keyed +// cache cannot drift in practice. A full re-extract still runs periodically as +// a safety net in case a row is ever rewritten in place. + +import path from 'node:path'; + +// Re-extract everything this often, so a rewritten row can never be missed. +const REVERIFY_MS = 10 * 60 * 1000; + +// How much of the user's own message is kept for the conversation table. +// Applied inside SQLite with substr(), so the full text (up to ~52 k chars on +// this machine) is never carried into JS memory — only the first 200 +// characters are. +const USER_PREVIEW_CHARS = 200; + +// CASE (not AND) is deliberate: SQLite evaluates CASE lazily, so the inner +// json_type/json_extract calls only run on rows that are valid JSON. An +// expression like `json_valid(x) AND json_type(x, ...)` is not guaranteed to +// short-circuit and would raise "malformed JSON" on a bad row. +function jsonField(path, kind) { + return `CASE WHEN json_valid(data_json) THEN CASE WHEN json_type(data_json,'${path}') ${kind} THEN json_extract(data_json,'${path}') END END`; +} + +const FACT_SQL = ` + SELECT id, session_id, role, turn_id, created_at_ms, + ${jsonField('$.usage', "= 'object'")} AS has_usage, + ${jsonField('$.usage.decode_duration_ms', "IN ('integer','real')")} AS decode_ms, + ${jsonField('$.usage.request_duration_ms', "IN ('integer','real')")} AS request_ms, + ${jsonField('$.finish_reason', "= 'text'")} AS finish_reason, + substr(${jsonField('$.msg_content', "= 'text'")}, 1, ${USER_PREVIEW_CHARS}) AS msg_preview + FROM local_runtime_message_rows + WHERE id > ? + ORDER BY id`; + +// One store per runtime database file. +const stores = new Map(); + +function createStore() { + return { + byTurn: new Map(), // turn_id -> entry + watermark: 0, // highest rowid already extracted + extractedRows: 0, + lastSyncAt: 0, + lastVerifyAt: 0, + everScanned: false, + }; +} + + +export function getFactsStore(dataDir) { + const key = path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); + let store = stores.get(key); + if (!store) { + store = createStore(); + stores.set(key, store); + } + return store; +} + +function applyRow(store, row) { + const turnId = row.turn_id; + if (!turnId) return; + let entry = store.byTurn.get(turnId); + if (!entry) { + entry = { + sessionId: row.session_id, + maxTs: null, + calls: new Map(), // rowid -> call fact (assistant messages that carry a usage block) + assistantCount: 0, // every assistant row, including the ones that are not model calls + users: new Map(), // rowid -> user message fact + }; + store.byTurn.set(turnId, entry); + } + if (row.created_at_ms != null && (entry.maxTs == null || row.created_at_ms > entry.maxTs)) { + entry.maxTs = row.created_at_ms; + } + if (row.role === 'assistant') { + entry.assistantCount += 1; + // Only an assistant message that carries a usage block is a MODEL CALL. + // The runtime also writes assistant rows for non-call events — context + // compaction, for instance (490 of 17,214 such rows on this machine). + // Counting those as calls shifts every later pairing in the turn by one, + // which made a whole turn report the previous call's decode duration and + // rate. They are counted for "did the agent answer?" but never paired. + if (row.has_usage) { + entry.calls.set(row.id, { + ts: row.created_at_ms, + decodeMs: row.decode_ms, + requestMs: row.request_ms, + finishReason: row.finish_reason, + }); + } + } else if (row.role === 'user') { + entry.users.set(row.id, { ts: row.created_at_ms, preview: row.msg_preview }); + } +} + +// Pull in every row appended since the last extraction. A full re-extract +// happens on the first sync and then every REVERIFY_MS, so the store always +// converges on the current contents of the table. +export function syncFacts(store, db, options = {}) { + const now = options.now ?? Date.now(); + const full = !store.everScanned || now - store.lastVerifyAt >= REVERIFY_MS; + if (full) { + store.byTurn.clear(); + store.watermark = 0; + } + let rows = 0; + let maxId = store.watermark; + const stmt = db.prepare(FACT_SQL); + for (const row of stmt.iterate(store.watermark)) { + rows += 1; + if (row.id > maxId) maxId = row.id; + applyRow(store, row); + } + store.watermark = maxId; + store.extractedRows += rows; + store.lastSyncAt = now; + store.everScanned = true; + if (full) store.lastVerifyAt = now; + return { rows, full, watermark: store.watermark, turns: store.byTurn.size }; +} + +// Model calls of a turn, oldest first — the same order the original query +// produced (ORDER BY created_at_ms), with the rowid as a stable tie-breaker. +// Only messages that carry a usage block are returned: those are the calls +// the runtime recorded in local_runtime_token_usage, and they are what the +// per-call ledger pairs against. +export function assistantCallsForTurn(store, turnId) { + const entry = store.byTurn.get(turnId); + if (!entry || entry.calls.size === 0) return null; + const out = [...entry.calls.values()].sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0)); + return out; +} + +// Per-turn message metadata for the conversation table. +// +// A turn is exactly one user message followed by however many model calls the +// agent needed before answering, so it is the natural unit for "one thing the +// user asked" — and it is readable from the database the instant the first +// usage row of that turn lands, with no hook and no waiting for the session +// to close. Verified on this machine: 26 turns today, 24 carrying exactly one +// user message, 0 carrying more than one, and all 26 ending on an assistant +// message. +export function turnMetaForTurn(store, turnId) { + const entry = store.byTurn.get(turnId); + if (!entry) return null; + let userTs = null; + let userPreview = null; + for (const u of entry.users.values()) { + if (u.ts == null) continue; + if (userTs == null || u.ts < userTs || (u.ts === userTs && u.preview != null && userPreview == null)) { + userTs = u.ts; + userPreview = u.preview != null ? u.preview : userPreview; + } + } + // The finish reason of the last MODEL CALL that carries one. Non-call + // assistant rows (compaction) are deliberately excluded: they carry a + // finish_reason of their own, and reading it would report a still-running + // turn as "completed". + const calls = assistantCallsForTurn(store, turnId); + let finishReason = null; + if (calls) { + for (let i = calls.length - 1; i >= 0; i -= 1) { + if (calls[i].finishReason != null) { + finishReason = calls[i].finishReason; + break; + } + } + } + return { + userTs, + userPreview, + lastTs: entry.maxTs, + finishReason, + assistantCount: entry.assistantCount, + }; +} + +export function factsStats(store) { + return { + turns: store.byTurn.size, + extractedRows: store.extractedRows, + watermark: store.watermark, + lastSyncAt: store.lastSyncAt, + lastVerifyAt: store.lastVerifyAt, + }; +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs new file mode 100644 index 00000000..6cb9a387 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs @@ -0,0 +1,454 @@ +// token-meter-board query layer: windowed usage aggregations shared by the HTTP +// routes (in-process) and the child-process fallback (db-child.mjs). All reads +// are read-only against the MiniMax Code runtime state. +// +// Rate methodology (v1.5): token 输出速率 与 MiniMax Code 界面同口径 —— +// 单次成功调用为 输出 tokens ÷ decode 时长(首 token 到流结束,取自 assistant +// 消息的 usage.decode_duration_ms);跨调用的聚合一律为 Σ输出 ÷ Σdecode 耗时 +//(时间加权),不使用逐次算术平均。没有 decode 记录的老数据不参与,避免被口径 +// 外的数值稀释。decode > request 的调用不计入聚合:它等价于首 token 早于请求发起, +// 说明两个时间戳来自不同尝试(实测仅出现在 finish=toolUse,2674 次里 6 次), +// 其 decode 物理上不可能更长,会灌大分母。逐次值仍照常展示。 +import fs from 'node:fs'; +import { + openDb, + queryUsageRows, + loadCatalog, + loadTurnEnrichment, + buildLedgerWithDb, + loadTurnMessageMeta, + syncMessageFacts, + meanCallRate, + rateStats, + requestRateStats, + countRatedCalls, + emptyMetrics, + addRow, + finalize, + sortGroups, + dayKey, + clampInt, +} from './common.mjs'; +import { resolveTrendWindow, buildTrendFromContext } from './trend.mjs'; + +export const NOTES = [ + 'cacheHitRate = cacheReadTokens / (cacheReadTokens + inputTokens),表示提示词中命中缓存的比例;cacheWriteTokens 不计入分母。', + 'totalTokens = input + output + reasoning + cacheRead + cacheWrite。', + 'token 输出速率(token/s)与 MiniMax Code 界面显示的口径完全一致:单次调用的 输出 tokens ÷ decode 时长(首 token 到流结束),窗口值为 Σ输出 ÷ Σdecode 耗时(按耗时加权),并附 P50/P90 供分布参考。', + 'costUsd 为 runtime 记录值;自定义套餐/订阅类提供商通常为 0,不代表实际账单。', + '请求全程速率(对照列)= 输出 tokens ÷ request_duration_ms(发起请求到流结束),与输出速率的差值即首字等待与排队;decode > request 的调用(首 token 早于请求发起、时间戳来自不同尝试)不计入输出速率聚合,逐次值仍展示。', + 'model 字段由 runtime 日志 llm_response_identifiers 按 turn 补全(按小时文件名覆盖整个窗口);仍为 unknown 的记录早于日志保留期。', + '对话明细:每行是一次完整对话,即用户发送一条消息后,模型经过若干次调用直至给出最终回答(turn_id 即该单位);实时读取,无需等待会话结束。状态分为已完成(末条 finish_reason=stop)、未收尾(末条仍为 toolUse 等)与进行中(尚无 assistant 消息)。', + '对话明细会显示该轮用户消息原文的前 200 字,仅在本机页面内展示,不出网、不落盘。', + '统计范围限于本机 runtime 数据库当前保留的数据;早于该保留期的历史不会出现在本表中。', +]; + +// Open the DB and load the window rows plus the per-call ledger (identity, +// decode timing, response status). +// +// The derived context is cached for a few seconds, so the endpoints that +// describe the same window — trend, call log and conversation list — share one +// scan instead of each repeating it. That is what keeps a window switch from +// queueing three expensive passes behind each other. +// +// The cache key includes the data directory: the same time window against two +// different runtime databases is two different contexts, and keying on the +// window alone would let one answer the other. +const CONTEXT_TTL_MS = 3000; +const contextCache = new Map(); + +function contextKey(dataDir, startMs, endMs) { + return `${dataDir}|${startMs}|${endMs}`; +} + +function loadSessionTitles(db) { + const titles = new Map(); + try { + for (const r of db.prepare('SELECT session_id, title, agent_name, workspace_dir FROM local_runtime_sessions').all()) { + titles.set(r.session_id, r); + } + } catch { + // titles optional + } + return titles; +} + +export function openContext(dataDir, startMs, endMs, now = Date.now()) { + const key = contextKey(dataDir, startMs, endMs); + const hit = contextCache.get(key); + if (hit && now - hit.at < CONTEXT_TTL_MS) return hit.ctx; + + const { db, error } = openDb(dataDir); + if (!db) { + const err = new Error(error || `runtime state database unavailable under ${dataDir}`); + err.code = 'NO_DB'; + throw err; + } + try { + const rows = queryUsageRows(db, startMs, endMs); + const catalog = loadCatalog(dataDir); + const { map: enrichment, filesScanned } = loadTurnEnrichment(dataDir, startMs, { now }); + // Message facts are extracted once per process and reused; this only picks + // up rows appended since the last query. + const store = syncMessageFacts(db, dataDir, { now }); + const ledger = buildLedgerWithDb(db, rows, enrichment, catalog, store); + const turnMeta = loadTurnMessageMeta(rows, store); + const titles = loadSessionTitles(db); + const meta = { + dataDir, + window: { + label: `${dayKey(startMs)}..${dayKey(endMs)}`, + start: new Date(startMs).toISOString(), + end: new Date(endMs).toISOString(), + }, + rows: rows.length, + rateMeasured: countRatedCalls(ledger), + rate: rateStats(ledger), + requestRate: requestRateStats(ledger), + logFilesScanned: filesScanned, + turnsEnriched: enrichment.size, + generatedAt: new Date(now).toISOString(), + }; + const ctx = { rows, catalog, enrichment, ledger, turnMeta, titles, filesScanned, dataDir, meta }; + contextCache.set(key, { at: now, ctx }); + if (contextCache.size > 32) { + const oldest = contextCache.keys().next().value; + if (oldest !== key) contextCache.delete(oldest); + } + return ctx; + } finally { + db.close(); + } +} + +export function groupByModel(ctx) { + const groups = new Map(); + const total = emptyMetrics(); + let unknownRows = 0; + for (const call of ctx.ledger) { + if (call.model === '(unknown)') unknownRows += 1; + const key = `${call.provider}|${call.model}`; + if (!groups.has(key)) { + groups.set(key, { + provider: call.provider, + providerName: call.providerName, + model: call.model, + modelName: call.modelName, + custom: call.custom, + metrics: emptyMetrics(), + callList: [], + }); + } + const g = groups.get(key); + addRow(g.metrics, call); + g.callList.push(call); + addRow(total, call); + } + const byModel = sortGroups( + [...groups.values()].map((g) => ({ + ...g, + ...finalize(g.metrics), + outputRate: meanCallRate(g.callList), + metrics: undefined, + callList: undefined, + })), + ); + return { byModel, total: finalize(total), unknownRows }; +} + +function summaryFromContext(ctx) { + const { byModel, total, unknownRows } = groupByModel(ctx); + return { + window: ctx.meta.window, + total: { ...total, outputRate: meanCallRate(ctx.ledger), rate: rateStats(ctx.ledger), rateMeasured: ctx.meta.rateMeasured }, + byModel, + unknownRows, + notes: NOTES, + meta: ctx.meta, + }; +} + +// summary: window (startAt/endAt minute precision, or days) grouped by provider/model. +export function querySummary({ dataDir, startAt, endAt, days }, now = Date.now()) { + const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + return summaryFromContext(ctx); +} + +// window: trend + summary over a single DB/log scan (one enrichment pass). +export function queryWindow({ dataDir, startAt, endAt, days, bucket, fillEmpty }, now = Date.now()) { + const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + const trend = buildTrendFromContext(ctx, { startMs, endMs, bucket, fillEmpty, now }); + const summary = summaryFromContext(ctx); + return { trend, summary }; +} + +// calls: the per-call ledger for the window, newest first (调用日志). +export function queryCalls({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { + const lim = clampInt(limit, 1, 1000, 200); + const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 1 }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + const calls = ctx.ledger + .slice() + .sort((a, b) => b.ts - a.ts) + .slice(0, lim) + .map((c) => ({ + ts: c.ts, + time: new Date(c.ts).toISOString(), + sessionId: c.sessionId, + agentName: c.agentName, + turnId: c.turnId, + provider: c.provider, + providerName: c.providerName, + model: c.model, + modelName: c.modelName, + custom: c.custom, + inputTokens: c.input_tokens, + outputTokens: c.output_tokens, + reasoningTokens: c.reasoning_tokens, + cacheReadTokens: c.cache_read_tokens, + cacheWriteTokens: c.cache_write_tokens, + totalTokens: + c.input_tokens + c.output_tokens + c.reasoning_tokens + c.cache_read_tokens + c.cache_write_tokens, + decodeMs: c.decodeMs, + requestMs: c.requestMs, + status: c.status, + finishReason: c.finishReason, + outputRate: c.rate, + requestRate: c.requestRate, + })); + return { + window: ctx.meta.window, + calls, + totalCalls: ctx.ledger.length, + rateMeasured: ctx.meta.rateMeasured, + rate: ctx.meta.rate, + requestRate: ctx.meta.requestRate, + notes: NOTES, + meta: ctx.meta, + }; +} + +// turns: one row per conversation — a single user message plus however many +// model calls the agent needed before answering. Read live from the database, so +// it works while the conversation is still running and never waits for SessionEnd. +// +// Rate uses the same basis as the KPI (Σoutput ÷ Σdecode); wall-clock span is +// reported separately as 时长 and is deliberately NOT used as the denominator, +// otherwise a long conversation with a slow tail would read as a slow model. +export function queryTurns({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { + const lim = clampInt(limit, 1, 500, 120); + const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 1 }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + const byTurn = new Map(); + for (const call of ctx.ledger) { + if (!call.turnId) continue; + if (!byTurn.has(call.turnId)) { + byTurn.set(call.turnId, { + total: emptyMetrics(), + calls: [], + firstTs: call.ts, + lastCallTs: call.ts, + groups: new Map(), + sessionId: call.sessionId, + agentName: call.agentName || null, + }); + } + const t = byTurn.get(call.turnId); + t.firstTs = Math.min(t.firstTs, call.ts); + t.lastCallTs = Math.max(t.lastCallTs, call.ts); + addRow(t.total, call); + t.calls.push(call); + const gk = `${call.provider}|${call.model}`; + if (!t.groups.has(gk)) { + t.groups.set(gk, { + provider: call.provider, + providerName: call.providerName, + model: call.model, + modelName: call.modelName, + custom: call.custom, + metrics: emptyMetrics(), + callList: [], + }); + } + const g = t.groups.get(gk); + addRow(g.metrics, call); + g.callList.push(call); + } + + const allTurns = [...byTurn.entries()] + .map(([turnId, t]) => { + const meta = ctx.turnMeta.get(turnId) || null; + const startedMs = meta?.userTs != null ? Math.min(meta.userTs, t.firstTs) : t.firstTs; + const endedMs = meta?.lastTs != null ? meta.lastTs : null; + const finished = endedMs != null && (meta?.assistantCount || 0) > 0; + let status = 'pending'; + if (finished) status = meta.finishReason === 'stop' ? 'completed' : 'unfinished'; + const models = sortGroups( + [...t.groups.values()].map((g) => ({ + ...g, + ...finalize(g.metrics), + outputRate: meanCallRate(g.callList), + metrics: undefined, + callList: undefined, + })), + ); + const metrics = finalize(t.total); + return { + turnId, + sessionId: t.sessionId, + sessionTitle: ctx.titles.get(t.sessionId)?.title || null, + agentName: t.agentName, + startedAt: new Date(startedMs).toISOString(), + endedAt: endedMs != null ? new Date(endedMs).toISOString() : null, + durationMs: endedMs != null ? endedMs - startedMs : null, + status, + finishReason: meta?.finishReason || null, + userPreview: meta?.userPreview || null, + ...metrics, + outputRate: meanCallRate(t.calls), + rate: rateStats(t.calls), + byModel: models, + }; + }) + .sort((a, b) => (a.startedAt < b.startedAt ? 1 : -1)); + + // The status breakdown covers EVERY turn in the window, not only the rows + // that survive the `limit` slice. Counting the slice instead made the + // headline ("本次窗口共 N 次对话(已完成 X · 未收尾 Y · 进行中 Z)") add up + // to less than N as soon as the window held more turns than the limit. + const counts = { completed: 0, unfinished: 0, pending: 0 }; + for (const t of allTurns) counts[t.status] = (counts[t.status] || 0) + 1; + + const turns = allTurns.slice(0, lim); + + return { + window: ctx.meta.window, + turns, + totalTurns: byTurn.size, + counts, + notes: NOTES, + meta: ctx.meta, + }; +} + +// sessions: per-session aggregation over the window, newest activity first. +// outputRate = the session's weighted decode rate (Σ output ÷ Σ decode). +export function querySessions({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { + const lim = clampInt(limit, 1, 50, 10); + const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 30 }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + const bySession = new Map(); + for (const call of ctx.ledger) { + if (!bySession.has(call.sessionId)) { + bySession.set(call.sessionId, { + total: emptyMetrics(), + firstTs: call.ts, + lastTs: call.ts, + groups: new Map(), + calls: [], + agentName: call.agentName || null, + }); + } + const s = bySession.get(call.sessionId); + s.firstTs = Math.min(s.firstTs, call.ts); + s.lastTs = Math.max(s.lastTs, call.ts); + addRow(s.total, call); + s.calls.push(call); + const gk = `${call.provider}|${call.model}`; + if (!s.groups.has(gk)) { + s.groups.set(gk, { + provider: call.provider, + providerName: call.providerName, + model: call.model, + modelName: call.modelName, + custom: call.custom, + metrics: emptyMetrics(), + callList: [], + }); + } + const g = s.groups.get(gk); + addRow(g.metrics, call); + g.callList.push(call); + } + const sessions = [...bySession.entries()] + .map(([sessionId, s]) => { + const info = ctx.titles.get(sessionId); + const models = sortGroups( + [...s.groups.values()].map((g) => ({ + ...g, + ...finalize(g.metrics), + outputRate: meanCallRate(g.callList), + metrics: undefined, + callList: undefined, + })), + ); + const metrics = finalize(s.total); + return { + sessionId, + title: info?.title || null, + agentName: s.agentName || info?.agent_name || null, + workspaceDir: info?.workspace_dir || null, + firstActivity: new Date(s.firstTs).toISOString(), + lastActivity: new Date(s.lastTs).toISOString(), + ...metrics, + outputRate: meanCallRate(s.calls), + rate: rateStats(s.calls), + byModel: models, + }; + }) + .sort((a, b) => (a.lastActivity < b.lastActivity ? 1 : -1)) + .slice(0, lim); + return { window: ctx.meta.window, sessions, notes: NOTES, meta: ctx.meta }; +} + +// daily: day x model aggregation over the trailing N days. +// outputRate = the day's weighted decode rate (Σ output ÷ Σ decode). +export function queryDaily({ dataDir, days }, now = Date.now()) { + const n = clampInt(days, 1, 90, 7); + const { startMs, endMs } = resolveTrendWindow({ days: n }, now); + const ctx = openContext(dataDir, startMs, endMs, now); + const byDay = new Map(); + for (const call of ctx.ledger) { + const key = dayKey(call.ts); + if (!byDay.has(key)) byDay.set(key, { total: emptyMetrics(), groups: new Map(), calls: [] }); + const day = byDay.get(key); + addRow(day.total, call); + day.calls.push(call); + const gk = `${call.provider}|${call.model}`; + if (!day.groups.has(gk)) { + day.groups.set(gk, { + provider: call.provider, + providerName: call.providerName, + model: call.model, + modelName: call.modelName, + custom: call.custom, + metrics: emptyMetrics(), + callList: [], + }); + } + const g = day.groups.get(gk); + addRow(g.metrics, call); + g.callList.push(call); + } + const daysOut = [...byDay.entries()] + .sort(([a], [b]) => (a < b ? -1 : 1)) + .map(([day, v]) => { + const total = finalize(v.total); + return { + day, + total: { ...total, outputRate: meanCallRate(v.calls), rate: rateStats(v.calls) }, + byModel: sortGroups( + [...v.groups.values()].map((g) => ({ + ...g, + ...finalize(g.metrics), + outputRate: meanCallRate(g.callList), + metrics: undefined, + callList: undefined, + })), + ), + }; + }); + return { window: ctx.meta.window, days: daysOut, notes: NOTES, meta: ctx.meta }; +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs new file mode 100644 index 00000000..a3f044aa --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs @@ -0,0 +1,247 @@ +// token-meter trend pipeline: window parsing, bucket picking, and bucketed +// per-model usage series. buildTrendFromContext lets callers combine the trend +// with other aggregations over a single DB/log scan; buildTrendResult keeps +// the standalone one-shot behavior. +import { + resolveDataDir, + openDb, + clampInt, + queryUsageRows, + loadCatalog, + loadTurnEnrichment, + resolveRowIdentity, + emptyMetrics, + addRow, + finalize, + buildLedgerWithDb, + syncMessageFacts, + meanCallRate, + rateStats, + requestRateStats, + countRatedCalls, +} from './common.mjs'; + +export function parseLocalDateTime(value) { + const m = String(value || '') + .trim() + .match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?/); + if (!m) return null; + const d = new Date(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +(m[6] || 0), 0); + return Number.isNaN(d.getTime()) ? null : d.getTime(); +} + +export function resolveTrendWindow(args, now = Date.now()) { + if (args?.startAt) { + const startMs = parseLocalDateTime(args.startAt); + const endRaw = args.endAt ? parseLocalDateTime(args.endAt) : now; + if (startMs == null || endRaw == null) { + throw new Error('invalid startAt/endAt; expect local "YYYY-MM-DDTHH:MM"'); + } + const endMs = Math.min(endRaw, now); + if (endMs <= startMs) throw new Error('endAt must be after startAt'); + return { startMs, endMs }; + } + const days = clampInt(args?.days, 1, 90, 7); + const todayStart = new Date(); + todayStart.setHours(0, 0, 0, 0); + // Second-level quantisation keeps a rolling window stable, so repeated + // queries inside the same second share one cached context instead of + // rebuilding the scan for every request. + return { startMs: todayStart.getTime() - (days - 1) * 86400000, endMs: Math.floor(now / 1000) * 1000 }; +} + +export function pickBucket(startMs, endMs, requested) { + const spanMin = (endMs - startMs) / 60000; + let bucket = requested && requested !== 'auto' ? requested : spanMin <= 360 ? 'minute' : spanMin <= 7 * 24 * 60 ? 'hour' : 'day'; + // keep bucket count manageable + const spanMs = Math.max(endMs - startMs, 1); + const approx = (b) => Math.ceil(spanMs / (b === 'minute' ? 60000 : b === 'hour' ? 3600000 : 86400000)); + if (approx(bucket) > 600) bucket = bucket === 'minute' ? 'hour' : 'day'; + return bucket; +} + +export function bucketFloor(ts, bucket) { + const d = new Date(ts); + if (bucket === 'minute') d.setSeconds(0, 0); + else if (bucket === 'hour') d.setMinutes(0, 0, 0); + else d.setHours(0, 0, 0, 0); + return d.getTime(); +} + +export function bucketLabel(ms, bucket, multiDay) { + const d = new Date(ms); + const p = (n) => String(n).padStart(2, '0'); + if (bucket === 'day') return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`; + if (multiDay) return `${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`; + return `${p(d.getHours())}:${p(d.getMinutes())}`; +} + +const MAX_TREND_MODELS = 5; + +function round2(v) { + return Math.round(v * 100) / 100; +} + +// Build the trend result from an already-open query context. +// ctx: { rows, catalog, enrichment (Map), ledger, dataDir, filesScanned }. +// ledger entries are per-call records (identity + tokens + decode rate) built +// by common.buildCallLedger; when absent it is derived from rows for +// backward compatibility (rates then stay null). +export function buildTrendFromContext(ctx, { startMs, endMs, bucket: requestedBucket, fillEmpty: fillArg, now = Date.now() }) { + const bucket = pickBucket(startMs, endMs, requestedBucket); + const { rows, catalog, enrichment } = ctx; + const ledger = ctx.ledger || rows.map((row) => ({ ...row, ...resolveRowIdentity(row, enrichment, catalog), ts: row.ts, rate: null })); + const dir = ctx.dataDir; + const filesScanned = ctx.filesScanned ?? 0; + + // rank models by total tokens (ledger entries already carry resolved identity) + const byModelTotals = new Map(); + let unknownRows = 0; + for (const call of ledger) { + if (call.model === '(unknown)') unknownRows += 1; + const key = `${call.provider}|${call.model}`; + if (!byModelTotals.has(key)) byModelTotals.set(key, { id: call, tokens: 0 }); + byModelTotals.get(key).tokens += + (call.input_tokens || 0) + (call.output_tokens || 0) + (call.reasoning_tokens || 0) + (call.cache_read_tokens || 0) + (call.cache_write_tokens || 0); + } + const ranked = [...byModelTotals.entries()].sort((a, b) => { + if (a[1].id.custom !== b[1].id.custom) return a[1].id.custom ? -1 : 1; + return b[1].tokens - a[1].tokens; + }); + const topKeys = ranked.slice(0, MAX_TREND_MODELS).map(([k]) => k); + const modelList = ranked.slice(0, MAX_TREND_MODELS).map(([key, v]) => ({ + key, + model: v.id.model, + modelName: v.id.modelName, + providerName: v.id.providerName, + custom: v.id.custom, + totalTokens: v.tokens, + })); + const hasOther = ranked.length > MAX_TREND_MODELS; + if (hasOther) { + modelList.push({ + key: '__other__', + model: '(other)', + modelName: '其他模型', + providerName: '', + custom: false, + totalTokens: ranked.slice(MAX_TREND_MODELS).reduce((s, [, v]) => s + v.tokens, 0), + }); + } + + // bucket aggregation + const multiDay = endMs - startMs > 24 * 3600000; + const buckets = new Map(); + const kpi = emptyMetrics(); + const seriesKeys = hasOther ? [...topKeys, '__other__'] : topKeys; + for (const call of ledger) { + addRow(kpi, call); + const bStart = bucketFloor(call.ts, bucket); + if (!buckets.has(bStart)) { + buckets.set(bStart, { totals: emptyMetrics(), perModel: new Map(), rateOut: 0, rateDecodeMs: 0, rated: 0 }); + } + const b = buckets.get(bStart); + addRow(b.totals, call); + // Accumulate the UI basis directly (Σoutput ÷ Σdecode) instead of averaging + // per-call rates: the arithmetic mean is wrecked by the few calls the runtime + // times with a sub-second decode span, and it disagreed with the headline KPI. + // The inconsistent-timing exclusion mirrors common.collectDecodeRates/weightedRate. + if ( + typeof call.rate === 'number' && + !(call.decodeMs != null && call.requestMs != null && call.decodeMs > call.requestMs) + ) { + b.rateOut += call.output_tokens || 0; + b.rateDecodeMs += call.decodeMs || 0; + b.rated += 1; + } + const modelKey = `${call.provider}|${call.model}`; + const key = topKeys.includes(modelKey) ? modelKey : '__other__'; + const rowTotal = + (call.input_tokens || 0) + (call.output_tokens || 0) + (call.reasoning_tokens || 0) + (call.cache_read_tokens || 0) + (call.cache_write_tokens || 0); + b.perModel.set(key, (b.perModel.get(key) || 0) + rowTotal); + } + + const fillEmpty = fillArg !== false; + let starts; + if (fillEmpty) { + const stepMs = bucket === 'minute' ? 60000 : bucket === 'hour' ? 3600000 : 86400000; + starts = []; + // Day buckets align to local midnight; stepping from the floored start keeps + // minute/hour buckets aligned to wall-clock boundaries as well. + for (let ms = bucketFloor(startMs, bucket), end = bucketFloor(endMs, bucket); ms <= end; ms += stepMs) { + starts.push(ms); + if (starts.length > 1000) break; // safety, pickBucket already caps at ~600 + } + } else { + starts = [...buckets.keys()].sort((a, b) => a - b); + } + const labels = starts.map((ms) => bucketLabel(ms, bucket, multiDay)); + const tokensByModel = {}; + for (const key of seriesKeys) tokensByModel[key] = []; + const cacheHitRate = []; + const outputRate = []; + const calls = []; + const totalTokens = []; + for (const ms of starts) { + const b = buckets.get(ms); + if (b) finalize(b.totals); + for (const key of seriesKeys) tokensByModel[key].push(b?.perModel.get(key) || 0); + cacheHitRate.push(b ? b.totals.cacheHitRate : null); + // Σoutput ÷ Σdecode for the calls in this bucket — same basis as the headline + // KPI and the desktop UI; null when nothing measured, so the chart leaves a gap + // instead of a misleading zero + outputRate.push(b && b.rated > 0 && b.rateDecodeMs > 0 ? round2(b.rateOut / (b.rateDecodeMs / 1000)) : null); + calls.push(b ? b.totals.calls : 0); + totalTokens.push(b ? b.totals.totalTokens : 0); + } + finalize(kpi); + kpi.outputRate = meanCallRate(ledger); + kpi.rate = rateStats(ledger); + kpi.requestRate = requestRateStats(ledger); + kpi.rateMeasured = countRatedCalls(ledger); + + return { + window: { + start: new Date(startMs).toISOString(), + end: new Date(endMs).toISOString(), + bucket, + bucketCount: starts.length, + fillEmpty, + }, + kpis: { ...kpi, activeModels: ranked.length }, + models: modelList, + series: { labels, bucketStarts: starts, tokensByModel, cacheHitRate, outputRate, calls, totalTokens }, + unknownRows, + meta: { + dataDir: dir, + rows: rows.length, + logFilesScanned: filesScanned, + turnsEnriched: enrichment.size, + generatedAt: new Date(now).toISOString(), + }, + }; +} + +// Standalone trend query: opens its own context, aggregates, closes. +export function buildTrendResult({ dataDir, startMs, endMs, bucket, fillEmpty, now = Date.now() }) { + const dir = dataDir || resolveDataDir(); + const { db, error } = openDb(dir); + if (!db) { + const err = new Error(error || `runtime state database unavailable under ${dir}`); + err.code = 'NO_DB'; + throw err; + } + try { + const rows = queryUsageRows(db, startMs, endMs); + const catalog = loadCatalog(dir); + const { map: enrichment, filesScanned } = loadTurnEnrichment(dir, startMs, { now }); + const store = syncMessageFacts(db, dir, { now }); + const ledger = buildLedgerWithDb(db, rows, enrichment, catalog, store); + return buildTrendFromContext( + { rows, catalog, enrichment, ledger, dataDir: dir, filesScanned }, + { startMs, endMs, bucket, fillEmpty, now }, + ); + } finally { + db.close(); + } +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/miniapp-api.ts b/plugins/hanewari/token-meter-board/miniapp/node/miniapp-api.ts new file mode 100644 index 00000000..7a0e0fd3 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/miniapp-api.ts @@ -0,0 +1,109 @@ +/** + * Agent-facing Mini App runtime authoring declarations. + * + * Copy this file into a generated plugin for type checking. It contains no Host implementation; + * the Host injects runtime values through start(context). + * Keep the .ts filename: Electron packaging excludes .d.ts files from dependency assets. + */ +export type JsonPrimitive = null | boolean | number | string; +export type JsonValue = JsonPrimitive | JsonObject | readonly JsonValue[]; +export type JsonObject = { readonly [key: string]: JsonValue }; + +declare const HOST_CONNECTOR_TOOL_REF: unique symbol; +export type HostConnectorToolRef = string & { + readonly [HOST_CONNECTOR_TOOL_REF]: 'HostConnectorToolRef'; +}; + +export interface HostConnectorTool { + readonly toolRef: HostConnectorToolRef; + readonly provider: string; + readonly name: string; + readonly description?: string; + readonly inputSchema: JsonValue; + readonly outputSchema?: JsonValue; +} + +export interface HostConnectorListResult { + readonly tools: readonly HostConnectorTool[]; + readonly partial: boolean; +} + +export interface HostConnectorCallOptions { + readonly signal?: AbortSignal; +} + +export interface HostConnectorCallResult { + readonly invocationId: string; + /** + * Raw provider result; it is not normalized by the Host and may be an object, array, or primitive. + * A single text-block array is one provider shape, not a global Host transport contract. + * Decode only a probe-observed envelope; preserve every other value, including direct strings. + */ + readonly value: JsonValue; +} + +export interface HostConnectorClient { + /** Candidate-safe inventory only; available before and after activation. */ + list(options?: HostConnectorCallOptions): Promise; + /** Activation-only business dispatch; call from request handling, never start(context). */ + call( + toolRef: HostConnectorToolRef, + arguments_: JsonObject, + options?: HostConnectorCallOptions, + ): Promise; +} + +export type HostConnectorErrorDisposition = + | 'not_dispatched' + | 'provider_reported' + | 'unknown_after_dispatch'; + +export type HostConnectorErrorCode = + | 'TOOL_REF_STALE' + | 'SERVICE_RESTARTED' + | 'REQUEST_CANCELLED' + | 'CONNECTOR_TIMEOUT' + | 'INVALID_ARGUMENTS' + | 'CONNECTOR_PROVIDER_ERROR' + | 'CONNECTOR_UNAVAILABLE' + | 'CONNECTOR_OUTCOME_UNKNOWN'; + +export interface HostConnectorError extends Error { + readonly code: HostConnectorErrorCode; + readonly disposition: HostConnectorErrorDisposition; + readonly retryable: boolean; + readonly invocationId?: string; + readonly diagnostic?: { + readonly issues: readonly { + readonly path: string; + readonly constraint: string; + readonly limit?: number; + }[]; + }; +} + +export interface MiniAppLogger { + debug(message: string, fields?: JsonObject): void; + info(message: string, fields?: JsonObject): void; + warn(message: string, fields?: JsonObject): void; + error(message: string, fields?: JsonObject): void; +} + +export interface MiniAppLifecycle { + dispose(): void | Promise; +} + +export interface MiniAppContext { + readonly pluginId: string; + readonly pluginRoot: string; + readonly dataDir: string; + readonly listen: Readonly<{ readonly host: '127.0.0.1'; readonly port: number }>; + readonly signal: AbortSignal; + readonly logger: MiniAppLogger; + readonly hostConnector?: HostConnectorClient; +} + +export interface MiniAppModule { + /** Resolve only after the listener accepts connections and every route is installed. */ + start(context: MiniAppContext): Promise; +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/server.mjs b/plugins/hanewari/token-meter-board/miniapp/node/server.mjs new file mode 100644 index 00000000..2bf16e4b --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/server.mjs @@ -0,0 +1,306 @@ +// @ts-check +// token-meter-board Mini App Node entry: serves the dashboard page and the +// read-only usage query API. Data comes from the local MiniMax Code runtime +// state (sqlite + observability logs + config.yaml); all queries are read-only. +import fs from 'node:fs'; +import http from 'node:http'; +import path from 'node:path'; +import { spawn } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; +import { resolveDataDir, openDb, factsStore, factsStats } from './lib/common.mjs'; +import { resolveTrendWindow, buildTrendResult } from './lib/trend.mjs'; +import { querySummary, querySessions, queryDaily, queryWindow, queryCalls, queryTurns } from './lib/queries.mjs'; + +/** @typedef {import('./miniapp-api.js').MiniAppContext} MiniAppContext */ +/** @typedef {import('./miniapp-api.js').MiniAppLifecycle} MiniAppLifecycle */ + +const HERE = path.dirname(fileURLToPath(import.meta.url)); +const CHILD_PATH = path.join(HERE, 'lib', 'db-child.mjs'); + +// Locate the MiniMax Code data directory. In the Mini App runtime neither +// MINIMAX_DATA_DIR nor PLUGIN_DATA is guaranteed, so first walk up from the +// Host-injected plugin data dir looking for the runtime database, then fall +// back to the shared resolution chain (env override, PLUGIN_DATA, ~/.minimax). +function resolveAppDataDir(contextDataDir) { + const envDir = process.env.MINIMAX_DATA_DIR; + if (envDir && fs.existsSync(envDir)) return path.resolve(envDir); + let dir = contextDataDir ? path.resolve(contextDataDir) : null; + for (let i = 0; dir && i < 8; i += 1) { + if (fs.existsSync(path.join(dir, 'v2', 'sqlite', 'runtime-state.sqlite'))) return dir; + const parent = path.dirname(dir); + if (parent === dir) break; + dir = parent; + } + return resolveDataDir(); +} + +function isSqliteUnavailable(err) { + return Boolean(err && err.code === 'NO_DB' && /node:sqlite/.test(err.message || '')); +} + +/** + * @param {MiniAppContext} context + * @returns {Promise} + */ +export async function start(context) { + const dataDir = resolveAppDataDir(context.dataDir); + const children = new Set(); + // null = untried, false = in-process works, true = must use child fallback. + let childMode = null; + + // NOTE the spread order: `...p` first, `dataDir` last. The data directory is + // resolved by the Host and must never be overridable by a request, so it is + // applied AFTER the caller-supplied parameters on purpose. + const MODES = { + window: (p) => queryWindow({ ...p, dataDir }), + trend: (p) => { + const now = Date.now(); + const { startMs, endMs } = resolveTrendWindow( + { startAt: p.startAt, endAt: p.endAt, days: p.days }, + now, + ); + return buildTrendResult({ dataDir, startMs, endMs, bucket: p.bucket, fillEmpty: p.fillEmpty, now }); + }, + summary: (p) => querySummary({ ...p, dataDir }), + sessions: (p) => querySessions({ ...p, dataDir }), + daily: (p) => queryDaily({ ...p, dataDir }), + calls: (p) => queryCalls({ ...p, dataDir }), + turns: (p) => queryTurns({ ...p, dataDir }), + }; + + function runChild(mode, params) { + return new Promise((resolve, reject) => { + const args = [CHILD_PATH, mode, JSON.stringify({ ...params, dataDir })]; + const trySpawn = (cmd, env) => { + const child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, env }); + children.add(child); + let out = ''; + let errBuf = ''; + let settled = false; + const finish = (fn, value) => { + if (settled) return; + settled = true; + clearTimeout(timer); + children.delete(child); + fn(value); + }; + const timer = setTimeout(() => { + child.kill('SIGKILL'); + finish(reject, new Error('query timed out')); + }, 30000); + child.stdout.setEncoding('utf8'); + child.stdout.on('data', (c) => { + if (out.length < 16 * 1024 * 1024) out += c; + }); + child.stderr.setEncoding('utf8'); + child.stderr.on('data', (c) => { + if (errBuf.length < 4096) errBuf += c; + }); + child.on('error', (e) => { + if (settled) return; + if (e && e.code === 'ENOENT' && cmd === 'node') { + // No system node on PATH: retry the runtime's own executable as plain Node. + children.delete(child); + clearTimeout(timer); + settled = true; + trySpawn(process.execPath, { ...process.env, ELECTRON_RUN_AS_NODE: '1' }); + return; + } + finish(reject, e); + }); + child.on('close', (code) => { + let body; + try { + body = JSON.parse(out); + } catch { + finish(reject, new Error(`query helper failed (exit ${code}): ${errBuf.slice(0, 300) || 'no output'}`)); + return; + } + if (code !== 0) { + const err = new Error(body.error || `query helper exit ${code}`); + err.code = body.code || null; + finish(reject, err); + return; + } + finish(resolve, body); + }); + }; + trySpawn('node', process.env); + }); + } + + async function runQuery(mode, params) { + if (childMode !== true) { + try { + const result = MODES[mode](params); + childMode = false; + return result; + } catch (err) { + if (!isSqliteUnavailable(err)) throw err; + childMode = true; + context.logger.warn('token_meter_board.sqlite_fallback', { reason: err.message }); + } + } + return runChild(mode, params); + } + + function health() { + const dbFile = path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); + const dbExists = fs.existsSync(dbFile); + let sqliteInProcess = false; + let usageRows = null; + if (dbExists) { + const { db } = openDb(dataDir); + if (db) { + sqliteInProcess = true; + try { + usageRows = db.prepare('SELECT COUNT(*) c FROM local_runtime_token_usage').get().c; + } catch { + usageRows = null; + } + db.close(); + } + } + const store = factsStore(dataDir); + return { + ok: true, + now: Date.now(), + runtime: { + node: process.version, + sqliteInProcess, + queryMode: childMode === true ? 'child' : 'in-process', + }, + dataDir, + dbExists, + usageRows, + facts: factsStats(store), + }; + } + + const clientEntry = await fs.promises.readFile( + path.join(context.pluginRoot, 'miniapp', 'client', 'index.html'), + ); + const chartJs = await fs.promises.readFile( + path.join(context.pluginRoot, 'miniapp', 'client', 'vendor', 'chart.umd.min.js'), + ); + + const API_ROUTES = { + '/api/window': 'window', + '/api/trend': 'trend', + '/api/summary': 'summary', + '/api/sessions': 'sessions', + '/api/daily': 'daily', + '/api/calls': 'calls', + '/api/turns': 'turns', + }; + + // Query parameters are an ALLOW-LIST, not a pass-through. Anything the page + // does not send is dropped here, so a crafted query string can never reach + // the query layer with a key it does not expect — most importantly it can + // never carry a `dataDir` (the database location) or any other internal + // option into the query functions. + const API_PARAMS = { + window: ['startAt', 'endAt', 'days', 'bucket', 'fillEmpty'], + trend: ['startAt', 'endAt', 'days', 'bucket', 'fillEmpty'], + summary: ['startAt', 'endAt', 'days'], + sessions: ['startAt', 'endAt', 'days', 'limit'], + daily: ['days'], + calls: ['startAt', 'endAt', 'days', 'limit'], + turns: ['startAt', 'endAt', 'days', 'limit'], + }; + + const server = http.createServer((request, response) => { + void (async () => { + try { + const url = new URL(request.url ?? '/', 'http://miniapp.local'); + if (request.method !== 'GET') { + response.writeHead(405, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: 'method_not_allowed' })); + return; + } + if (url.pathname === '/' || url.pathname === '/index.html') { + response.writeHead(200, { 'content-type': 'text/html; charset=utf-8', 'cache-control': 'no-store' }); + response.end(clientEntry); + return; + } + if (url.pathname === '/vendor/chart.umd.min.js') { + response.writeHead(200, { + 'content-type': 'application/javascript; charset=utf-8', + 'cache-control': 'public, max-age=86400', + }); + response.end(chartJs); + return; + } + if (url.pathname === '/api/health') { + response.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); + response.end(JSON.stringify(health())); + return; + } + const mode = API_ROUTES[url.pathname]; + if (mode) { + const allowed = API_PARAMS[mode] || []; + const params = {}; + for (const key of allowed) { + if (!url.searchParams.has(key)) continue; + params[key] = url.searchParams.get(key); + } + if (params.fillEmpty != null) params.fillEmpty = params.fillEmpty !== 'false'; + try { + const result = await runQuery(mode, params); + response.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); + response.end(JSON.stringify(result)); + } catch (err) { + const status = err && err.code === 'NO_DB' ? 503 : 400; + response.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); + response.end(JSON.stringify({ error: String(err?.message || err) })); + } + return; + } + response.writeHead(404, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: 'not_found' })); + } catch (err) { + try { + response.writeHead(500, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: String(err?.message || err) })); + } catch { + // socket already gone + } + } + })(); + }); + + await new Promise((resolve, reject) => { + const onError = (error) => reject(error); + server.once('error', onError); + server.listen(context.listen.port, context.listen.host, () => { + server.off('error', onError); + resolve(); + }); + }); + context.logger.info('token_meter_board.listening'); + + let disposed = false; + const dispose = async () => { + if (disposed) return; + disposed = true; + context.signal.removeEventListener('abort', onAbort); + for (const child of children) { + try { + child.kill('SIGKILL'); + } catch { + // already gone + } + } + children.clear(); + // drop keep-alive client connections so close() settles promptly + server.closeIdleConnections?.(); + await new Promise((resolve) => server.close(() => resolve())); + }; + const onAbort = () => { + void dispose(); + }; + context.signal.addEventListener('abort', onAbort, { once: true }); + if (context.signal.aborted) await dispose(); + + return { dispose }; +} diff --git a/plugins/hanewari/token-meter-board/package.json b/plugins/hanewari/token-meter-board/package.json new file mode 100644 index 00000000..aab6b8dc --- /dev/null +++ b/plugins/hanewari/token-meter-board/package.json @@ -0,0 +1,6 @@ +{ + "mcode": { + "schemaVersion": 2, + "miniApp": "./miniapp/miniapp.json" + } +} From 46494d9d326e0231dd533b76b3c31998b333f023 Mon Sep 17 00:00:00 2001 From: HaneWari Date: Sat, 24 Oct 2026 00:48:23 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(token-meter-board):=20=E5=8F=AA?= =?UTF-8?q?=E8=AF=BB=E4=BC=9A=E8=AF=9D=E8=AE=B0=E5=BD=95=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=AF=B9=E5=AE=BF=E4=B8=BB=E5=86=85=E9=83=A8=E5=AD=98?= =?UTF-8?q?=E5=82=A8=E7=9A=84=E5=85=A8=E9=83=A8=E8=AE=BF=E9=97=AE=EF=BC=88?= =?UTF-8?q?2.0.0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按评审意见(changes requested)把整条数据路径拿掉。 社区插件不能打开 MiniMax Code 的内部数据库,读写都不允许。本版不再访问: - v2/sqlite/runtime-state.sqlite - v2/observability/logs/ - config.yaml 数据源改为客户端为用户自己的对话写下的会话记录: v2/sessions/**/messages.jsonl + manifest.json。路径解析与画廊里已合入的 mcode-token-usage-board 同一套(自 context.dataDir 向上找 v2/sessions, 回落 ~/.minimax),标题规则也一致(首条用户消息前 80 字,剥离 system reminder)。 删除 lib/common.mjs、lib/trend.mjs、lib/facts.mjs、lib/db-child.mjs。 包内不再 import node:sqlite,不再派生任何子进程。随子进程回退一起消失的 ENTRY_STDOUT warning 自然消失:官方校验器现为 0 errors / 0 warnings。 新增 lib/sessions.mjs:按文件字节游标 + 首部哈希增量解析,message_id 全局去重, 扫描游标原子写入插件自己的 dataDir。重写 lib/queries.mjs 与 server.mjs: 逐端点参数白名单、loopback Host/Origin 校验(参照 repo-xray)、报错文案路径脱敏。 因此失去的能力(如实说明):会话记录里没有耗时,也没有工作区路径。 - 取消输出速率与 P50/P90 - 会话排行不再有绝对工作区路径 - 取消每轮用户消息前 200 字预览 - 模型显示名改用 transcript 里的原始模型 id 保留并改进:token 用量、缓存命中率、按模型分布、按天趋势、逐次调用台账、 对话明细与会话排行。对话状态改由 stopReason 推导(stop=已完成 / toolUse=未收尾 / aborted=已中止 / 无调用=进行中),KPI 增加「对话次数」。 扫描游标持久化后,全量扫描约 2.0 秒,之后每次增量刷新约 170 毫秒。 覆盖率改为同窗对比:会话记录 8,422 次调用 / 1,133,235,393 tokens 对内部账本 13,124 次 / 2,099,198,213 tokens,覆盖率 64.2% / 54.0%;缺口是被压缩掉的调用, 且账本自身保留期更短(最早一行 2026-09-28)。 README(中英)重写 Data & access 并与真实行为对齐,根 README 作品表格那一行 同步更新;docs/validation.md 重写为 2.0.0 验证记录,含评审意见逐条对照表; docs/preview.png 重新截取(合成数据,无速率列)。 --- README.md | 2 +- README.zh-CN.md | 2 +- .../.minimax-plugin/plugin.json | 4 +- plugins/hanewari/token-meter-board/README.md | 141 +-- .../token-meter-board/README.zh-CN.md | 197 ++-- .../token-meter-board/docs/preview.png | Bin 297624 -> 107513 bytes .../token-meter-board/docs/validation.md | 197 +++- .../miniapp/client/index.html | 205 ++-- .../miniapp/node/lib/common.mjs | 707 -------------- .../miniapp/node/lib/db-child.mjs | 53 -- .../miniapp/node/lib/facts.mjs | 210 ----- .../miniapp/node/lib/queries.mjs | 876 +++++++++--------- .../miniapp/node/lib/sessions.mjs | 771 +++++++++++++++ .../miniapp/node/lib/trend.mjs | 247 ----- .../token-meter-board/miniapp/node/server.mjs | 353 +++---- 15 files changed, 1769 insertions(+), 2196 deletions(-) delete mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs delete mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs delete mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs create mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/sessions.mjs delete mode 100644 plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs diff --git a/README.md b/README.md index 1eb53358..2d60757e 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The MiniMax Code Agent communicates through the host MCP client. Business reques | [AI Office](plugins/cristinamadureira353-svg/ai-office/) | Manage five model-powered employees in a pixel office: client tasks, chats, breaks, meetings and quota-aware offline states; uses your own API keys | [最爱双皮奶](https://github.com/cristinamadureira353-svg) | | [Token Usage Board](plugins/amszuidas/mcode-token-usage-board/) | Explore local Token usage by date, model, and session, including input, output, and cache usage | [amszuidas](https://github.com/amszuidas) | | [Token Usage Board](plugins/yanhy2000/mcode-usage-monitor/) | Watch local Token usage, output speed, and cache hit rate in near real time; filter by time range, model, and session | [yanhy2000](https://github.com/yanhy2000) | -| [Token Meter Board](plugins/hanewari/token-meter-board/) | Live local Token usage with a per-call ledger, turn-level conversations, and output speed on the same basis as the client UI; reads the runtime's own usage table and logs, no Python | [HaneWari](https://github.com/HaneWari) | +| [Token Meter Board](plugins/hanewari/token-meter-board/) | Live local Token usage with a per-call ledger and turn-level conversations; reads only the session records the client writes for your own conversations, never the runtime's internal database | [HaneWari](https://github.com/HaneWari) | | [Model Manager](plugins/ocoomber/openrouter-model-manager/) | Browse, search, and enable/disable models in your `~/.minimax/config.yaml` with instant save, bulk actions, one-click undo, and automatic backups | [ocoomber](https://github.com/ocoomber) | | [Self-drive Route Planner](plugins/hanzijie/self-drive-route-planner/) | **Official plugin** for planning driving routes with place search, route alternatives, demo mode, and Xiaohongshu 3:4 itinerary cards | [HanZijie](https://github.com/HanZijie) | | [Git Commit Tree](plugins/microbiosis/git-tree/) | Inspect a local Git repo's commit history with a swim-lane graph, branches/tags, commit detail, and per-file change stats; persisted filter preferences and optional auto-refresh | [Microbiosis](https://github.com/Microbiosis) | diff --git a/README.zh-CN.md b/README.zh-CN.md index fb92e15d..6e238707 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -62,7 +62,7 @@ MiniMax Code Agent 通过宿主 MCP 客户端与 MiniApp 协作。业务请求 | [AI 事务所](plugins/cristinamadureira353-svg/ai-office/README.zh-CN.md) | 五位真实模型员工的像素事务所:接单、聊天、休息和开会,额度耗尽时角色暂停;使用玩家自己的 API Key | [最爱双皮奶](https://github.com/cristinamadureira353-svg) | | [Token 用量看板](plugins/amszuidas/mcode-token-usage-board/README.zh-CN.md) | 按时间、模型和会话查看本机 Token 用量,包含输入、输出和缓存用量 | [amszuidas](https://github.com/amszuidas) | | [Token 用量看板](plugins/yanhy2000/mcode-usage-monitor/README.zh-CN.md) | 近实时查看本机 Token 用量、输出速度与缓存命中率,可按时间范围、模型和会话筛选 | [yanhy2000](https://github.com/yanhy2000) | -| [Token 仪表盘](plugins/hanewari/token-meter-board/README.zh-CN.md) | 本机 Token 用量实时看板:逐次调用台账、对话明细(turn 级)、与客户端界面同口径的输出速率;直读运行时用量表与观测日志,无需 Python | [HaneWari](https://github.com/HaneWari) | +| [Token 仪表盘](plugins/hanewari/token-meter-board/README.zh-CN.md) | 本机 Token 用量实时看板:逐次调用台账、对话明细(turn 级);只读客户端为你的对话写下的会话记录,不打开运行时内部数据库 | [HaneWari](https://github.com/HaneWari) | | [模型管理器](plugins/ocoomber/openrouter-model-manager/README.zh-CN.md) | 浏览、搜索并启用/停用 `~/.minimax/config.yaml` 中的模型,支持即时保存、批量操作、一键撤销和自动备份 | [ocoomber](https://github.com/ocoomber) | | [自驾规划](plugins/hanzijie/self-drive-route-planner/README.zh-CN.md) | 【官方插件】规划自驾路线、地点搜索、候选算路与小红书 3:4 行程图;支持演示模式 | [HanZijie](https://github.com/HanZijie) | | [Git 提交树](plugins/microbiosis/git-tree/README.zh-CN.md) | 查看本机 Git 仓库的提交历史:泳道提交图、分支/标签、提交详情与文件改动统计,支持筛选偏好持久化与可选自动刷新 | [Microbiosis](https://github.com/Microbiosis) | diff --git a/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json b/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json index 99d53428..46eaa5a5 100644 --- a/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json +++ b/plugins/hanewari/token-meter-board/.minimax-plugin/plugin.json @@ -2,8 +2,8 @@ "schemaVersion": 1, "name": "token-meter-board", "displayName": "Token 仪表盘", - "version": "1.9.0", - "description": "本机 MiniMax Code 的实时 token 用量仪表盘:用量趋势、逐次调用台账、每轮对话明细、缓存命中率与输出速率。输出速率采用与产品内界面一致的 Σ输出 ÷ Σdecode 时间加权口径,并附 P50/P90 供分布参考。除本地内置的 Chart.js 外无第三方依赖,全程只读本机数据、不出网。", + "version": "2.0.0", + "description": "本机 MiniMax Code 的 token 用量仪表盘:用量趋势、逐次调用台账、每轮对话明细与缓存命中率。只读客户端自己写下的会话记录(v2/sessions 下的 transcript),不打开 runtime 内部数据库、不扫观测日志、不读配置文件,全程不出网、不派生子进程。", "author": "HaneWari", "icon": "icon.png", "category": "Code", diff --git a/plugins/hanewari/token-meter-board/README.md b/plugins/hanewari/token-meter-board/README.md index aa928819..869668d4 100644 --- a/plugins/hanewari/token-meter-board/README.md +++ b/plugins/hanewari/token-meter-board/README.md @@ -2,9 +2,9 @@ English | [简体中文](README.zh-CN.md) -A near-real-time token-usage dashboard for MiniMax Code, running entirely on your own machine. It reads the runtime's own per-call ledger and observability logs, so the numbers it shows are the ones the client actually recorded — not an estimate reconstructed from transcript files. +A near-real-time token-usage dashboard for MiniMax Code, running entirely on your own machine. It reads the session records the client writes for your own conversations — the same source the official gallery's token-usage board uses — and nothing else. It never opens the runtime's internal database, its observability logs or its configuration file. -Author: [HaneWari](https://github.com/HaneWari) · Version: `1.9.0` · License: [Apache-2.0](LICENSE) +Author: [HaneWari](https://github.com/HaneWari) · Version: `2.0.0` · License: [Apache-2.0](LICENSE) ![Token Meter Board, synthetic data](docs/preview.png) @@ -12,42 +12,64 @@ Author: [HaneWari](https://github.com/HaneWari) · Version: `1.9.0` · License: ## What you get -- **Usage trend** — stacked bars per model, with the cache-hit-rate and output-speed curves drawn on top. Buckets adapt from minutes to hours to days as the window grows. -- **Five detail tables** — per-model breakdown, daily totals, a 12-column **per-call ledger**, a **conversation (turn) table**, and a session ranking. -- **Conversation detail** — one row per question you asked. The row shows your own message text, the outcome, wall-clock duration, how many model calls the turn took, the tokens, and the rate. A turn that is still running is marked as unfinished and grows live — you do **not** have to close the session first. -- **Per-call ledger** — every single model call with its exact timestamp, model, all five token classes, output speed, whole-request speed, decode duration, request duration, and status code. +- **Usage trend** — stacked bars per model with the cache-hit-rate curve drawn on top. Buckets adapt from minutes to hours to days as the window grows. +- **Five detail tables** — per-model breakdown, daily totals, a **per-call ledger**, a **conversation (turn) table**, and a session ranking. +- **Conversation detail** — one row per question you asked. The row shows the session it belongs to, whether it is finished, how many model calls the turn took, and the tokens. A turn that is still running is marked as running and grows live — you do **not** have to close the session first. +- **Per-call ledger** — every model call with its timestamp, model, all four token classes and how the call ended. - **Time windows** — last hour / today / last 7 days / last 30 days, or any custom start and end. The time bar is laid out in two rows so the native date picker can never cover the *Apply* button, and pressing Enter inside a time field applies the window too. - **5-second auto refresh** with a manual refresh button. Switching a window never blanks the tables and never waits: the previous window stays on screen until the new values arrive, and a late response from an older window is discarded rather than overwriting the newer one. -## Why this one +## What it reads, and what that costs + +The board reads one kind of file: + +```text +/v2/sessions///
//messages.jsonl +``` + +Each line of a transcript is one message. An assistant message carries the token counts the runtime recorded for that call: + +```json +{ "role": "assistant", "model": "MiniMax-M3.1-Flash", "timestamp": 1792769579471, + "stopReason": "toolUse", + "usage": { "input": 1204, "output": 331, "cacheRead": 61044, "cacheWrite": 0, "totalTokens": 62579 } } +``` + +That is enough for everything this board shows: token usage, model distribution, daily trend, per-call detail, turn grouping and turn status. -Most token boards answer "how much did I spend". This one also answers "where did it go, and is the number I am looking at the number the client shows?". +Two things the transcripts do **not** carry, and therefore two things this board does not show: -- **It reads the ledger, not the transcripts.** Numbers come from the runtime's own per-call usage table plus the observability logs, not from reconstructing usage out of session transcript files. A transcript file carries one aggregate usage block per assistant message and no timing information at all, so a board that reads it cannot see the calls that are missing from the transcripts — and it can never show a per-call speed, because the transcript has no timings. Measured on a reference machine against a transcript-based board, that board reported about **48% fewer calls and 66% fewer cache-read tokens** overall, and the gap swung between **0% and 98% from day to day**. The cause is not a per-message aggregation rule: some sessions leave no transcript file at all, and a transcript-based board simply cannot see them. -- **The output speed matches the client.** Output speed is `Σ output tokens ÷ Σ decode duration` — the decode phase only, from the first token to the end of the stream — which is the same basis the MiniMax Code interface uses. The whole-request speed is shown next to it as a comparison column, so you can see how much of each call was spent waiting for the first token. A speed computed over the whole request instead reports a number roughly **1.6–2.1× lower** and does not line up with the interface. -- **Every call is matched to its own timings.** The board pairs each usage row with the assistant message that carries that call's decode and request durations. It does not match by nearest timestamp and it does not match by position: both go wrong as soon as one turn contains an assistant row that is not a model call (context compaction writes one), which shifts the whole turn. The pairing rule used here was verified against a token-signature ground truth over 16,723 calls with **zero** mismatches. -- **Totals add up to five terms.** `total = input + output + reasoning + cacheRead + cacheWrite`. Boards that stop at three terms silently drop cache writes and reasoning tokens. -- **Turn-level granularity.** One question becomes one row, with the call count and the tokens that question actually cost. Nothing has to be closed or archived first. -- **No Python, no extra process, no dependency.** Pure Node, no third-party runtime code except a vendored copy of Chart.js. Another board in this ecosystem requires Python 3.8+ and spawns a Python process per query. -- **Milliseconds, not seconds.** After the caching rework in v1.7.0 a full page refresh went from ~8.5 s to tens of milliseconds. On a reference machine with a ~17,000-row message table, a full page refresh takes ~50 ms, switching to a 7-day window ~40 ms, and the first query in a fresh process ~1.3 s (it has to scan the message table once). -- **Strictly read-only.** The Mini App writes nothing, sends nothing, and has no telemetry. No account, no API key, no configuration. +- **No timings.** There is no decode duration and no request duration in a transcript, so there is no token speed to compute. Output speed is gone in this version, and the page says so instead of showing an empty column. +- **No paths.** A transcript has no workspace directory, so the session ranking shows no absolute path. -## How this compares with the other token boards +Two more things the board deliberately does not show, even though the data would allow it: -The Mini App gallery already lists two token boards. They are good at what they do, and they solve a slightly different problem: +- **No message text.** The conversation table identifies a turn by its session, not by your own words. The per-turn preview of the first 200 characters of your message is gone. +- **No model display names.** A transcript records the raw model id, so the tables show `MiniMax-M3.1-Flash` rather than a name looked up in the client's configuration file. -| | Token Meter Board (this one) | `mcode-token-usage-board` | `mcode-usage-monitor` | +## Coverage: what the transcripts do not keep + +Session records are not a complete accounting of what the client did. When a long conversation is compacted, the runtime replaces the compacted part of the transcript with a summary, and the calls inside that part are no longer in any `messages.jsonl`. + +On the reference machine used for development (measured 2026-10-23), the board counted **8,640 calls across 151 sessions**, covering everything from 2026-06-17 onwards. The client's own internal ledger — which this board does not read — held **13,124** calls over the window it keeps (2026-09-28 onwards). + +Restricting both sides to the **same window** (2026-09-28 onwards): + +| | Session records | Internal ledger | Coverage | | --- | --- | --- | --- | -| Source of truth | Runtime usage table + observability logs | Session transcript files (`messages.jsonl`) | Runtime database, read through Python 3.8+ | -| Per-call timings | Yes — decode, request, status code per call | No — transcripts carry no timings | Partly — per-request speed | -| Per-call ledger | Yes, 12 columns | No | Recent requests | -| Conversation (turn) table with your own words | Yes | No | No | -| Needs Python | No | No | Yes | -| Extra process per query | No | No | Yes | -| Auto refresh | 5 s | 60 s | 5 s / 10 s / 30 s | -| Layout | Fixed, dense | Fixed | Draggable, user-editable card layout | +| Calls | 8,422 | 13,124 | **64.2%** | +| Total tokens | 1,133,235,393 | 2,099,198,213 | **54.0%** | + +The difference is calls that were compacted out, not calls that were mis-counted. It works the other way round too: the ledger's earliest row is 2026-09-28, more than three months after the transcripts begin — **the ledger itself has passed its retention window**, and those 220 calls survive only in the session records. -The practical difference: if you want to know **where the tokens went in a specific conversation**, or to audit **one specific call** (its decode duration, its request duration, its HTTP status), only this board shows it — and it can do so without re-deriving anything from transcript files. If you prefer a freely rearrangeable card layout, `mcode-usage-monitor` is the one to look at. +So: **these numbers are what your session records still contain, not a bill.** The client's own "usage" page remains the authoritative figure for billing and quota, and it is computed server-side. + +## Why this one + +- **It only reads your own session records.** No internal database, no observability logs, no client configuration. The same source the official gallery's `mcode-token-usage-board` uses — with two additions on top: a **per-call ledger** and a **turn-level table with live status**. +- **Incremental, not re-read.** A full scan of every transcript on the reference machine is ~344 MiB of JSON. The reader keeps a byte cursor per file and only parses what was appended since the last scan, so a full scan costs about **2.0 seconds** while each later refresh costs about **170 ms**. The cursor is persisted in the plugin's own data directory, so even a cold start of the Mini App resumes instead of re-reading everything. +- **No Python, no extra process, no dependency.** Pure Node, no third-party runtime code except a vendored copy of Chart.js. The subprocess fallback that the previous version needed for `node:sqlite` is gone with the database. +- **Strictly local.** The Mini App serves one page on `127.0.0.1` and answers its own API routes. It never contacts a remote host, and it makes no request other than to its own origin. ## Install @@ -74,10 +96,10 @@ Pick a window (preset or custom), and read the trend, the KPI strip, and the fiv Example prompts, and what you get back: - **"打开 Token 仪表盘"** → the dashboard opens on the current window. -- **"查看我的模型用量趋势"** → the trend chart with the per-model stacked bars, the cache-hit-rate curve and the output-speed curve. -- **"哪个自定义模型的缓存命中率最高?"** → the per-model table with the cache hit rate per provider and model. +- **"查看我的模型用量趋势"** → the trend chart with the per-model stacked bars and the cache-hit-rate curve. +- **"哪个模型消耗最多?"** → the per-model table with calls, tokens and cache hit rate per model. -The board also offers **让 Agent 分析此窗口** (let the Agent analyse this window): it appends the current window's totals, call count, cache hit rate and output speed to the chat input so you can ask follow-up questions about the same numbers you were just looking at. +The board also offers **让 Agent 分析此窗口** (let the Agent analyse this window): it appends the current window's totals, call count, cache hit rate and turn count to the chat input so you can ask follow-up questions about the same numbers you were just looking at. ## Data & access @@ -85,57 +107,57 @@ The board also offers **让 Agent 分析此窗口** (let the Agent analyse this | Path | Used for | | --- | --- | -| `/v2/sqlite/runtime-state.sqlite` | The per-call usage ledger and the assistant/user message rows (decode timings, finish reason, message text). Opened with `node:sqlite` in read-only mode. | -| `/v2/observability/logs/runtime-*.log` | Provider, model, and response status, correlated per turn. The usage table itself does not store the model name, so the logs are what make custom (BYOK) providers show up as themselves instead of "unknown". | -| `/config.yaml` | Provider and model display names, so the tables read "MiniMax-M3.1-Flash" rather than a raw id. | +| `/v2/sessions/**/messages.jsonl` | The transcript of every session: token counts per model call, model id, timestamp, turn id and stop reason. | +| `/v2/sessions/**/manifest.json` | The session id of a session directory. | + +Nothing else is read. The runtime's internal database (`v2/sqlite/runtime-state.sqlite`), its observability logs (`v2/observability/logs/`) and its configuration file (`config.yaml`) are **not** opened, in any mode. -The location is resolved from the Host-provided `context.dataDir` (the active MiniMax Code data directory), falling back to `~/.minimax`. **These paths and the column layout of the runtime database are not a published API** — they are the client's internal storage, so a future client release may change them. When that happens the board shows an explicit error instead of an empty dashboard. +The location is resolved from the Host-provided `context.dataDir` (the active MiniMax Code data directory), falling back to `~/.minimax`. **The transcript layout is not a published API** — it is the client's own storage, so a future client release may change it. When that happens the board shows an explicit error instead of an empty dashboard. **What the page displays.** The dashboard renders real local data, which means a screenshot of it can contain: -- **Your own message text** — the conversation table shows the first **200 characters** of each turn's user message. The full text is never loaded: it is truncated inside the database query, so it never enters the app's memory and never reaches the browser. -- **Session titles and session ids**, and the **absolute workspace path** of each session (shown in the session ranking's tooltip). -- **Model and provider names**, including the names of your own custom (BYOK) providers. +- **Session titles** — the first 80 characters of your first message in that session, with injected system reminders removed. The same rule the official gallery's token-usage board uses. The message body itself is never loaded, and no per-turn preview is shown. +- **Session ids** and model ids. -Everything stays on the machine and on the page. If you plan to share a screenshot, remember that your own questions and your local folder names are in it. +Everything stays on the machine and on the page. If you plan to share a screenshot, remember that your own first question and your model list are in it. -**Nothing is written.** No files are created or modified, no data leaves the machine, and there is no telemetry. The only cache lives in the process memory of the running Mini App. The page stores exactly one thing in your browser's `localStorage`: the theme choice, under the key `tmb-theme`. Nothing else is persisted. +**What is written.** Exactly one file: a scan cursor at `/session-scan-state.json`, written atomically (temp file + rename) when transcripts changed. It holds file paths, session ids, session titles and per-call counters so that a restart resumes instead of re-reading every transcript. It is a cache: deleting it only costs one full rescan. The page stores exactly one thing in your browser's `localStorage`: the theme choice, under the key `tmb-theme`. -**Network:** none. The Mini App serves one page on `127.0.0.1` and answers its own API routes. It never contacts a remote host, and it makes no request other than to its own origin. The query parameters it accepts are an explicit allow-list per endpoint — anything else, including anything that looks like a data-directory override, is dropped before the query runs. +**Network:** none. The Mini App serves one page on `127.0.0.1` and answers its own API routes. It never contacts a remote host, and it makes no request other than to its own origin. The query parameters it accepts are an explicit allow-list per endpoint — anything else, including anything that looks like a data-directory override, is dropped before the query runs. Requests whose `Host` header does not name the loopback interface, or whose `Origin` header does not name this listener, are refused with 403. -**Subprocess:** normally none. If the host's Node runtime does not expose `node:sqlite`, the Mini App re-runs the identical read-only queries in a child process. It first tries `node` from `PATH`, and only if that executable does not exist does it fall back to the runtime's own executable launched with `ELECTRON_RUN_AS_NODE=1`. The query mode and parameters are passed as an argv array — never through a shell — and the child prints one JSON document on stdout and exits. +**Subprocess:** none. No process is spawned, and no shell is used. -**Node.js:** the in-process path needs `node:sqlite`, which is unflagged from Node.js 23.4. The bundled runtime used for testing is Node.js v24.18.0. If neither the in-process runtime nor the child process has it, the board reports the requirement instead of failing silently. +**Node.js:** any Node.js that ships `node:fs/promises` and `node:http` — no experimental flag and no native module is needed. The bundled runtime used for testing is Node.js v24.18.0. ## Metrics | Metric | Definition | | --- | --- | -| Total tokens | `input + output + reasoning + cacheRead + cacheWrite` | +| Total tokens | `input + output + cacheRead + cacheWrite` — the four classes a transcript records. There is no reasoning class in a transcript, so it is not part of the sum. | | Cache hit rate | `cacheRead / (cacheRead + input)` — the share of the prompt that came from cache. Cache writes are not in the denominator. | -| Output speed | `Σ output tokens ÷ Σ decode duration`, weighted by time. Single call: `output tokens ÷ decode duration` (first token → end of stream). P50 and P90 are shown alongside. | -| Whole-request speed | `output tokens ÷ request_duration_ms` (request sent → end of stream). The difference against output speed is the first-token wait and queueing. | -| Conversation (turn) | One user message plus however many model calls the agent needed before answering. Duration is wall-clock span and is shown for information only; it does not enter the rate calculation. | +| Conversation (turn) | One user message plus however many model calls the agent needed before answering. | +| Turn status | From the stop reason of the turn's last model call: `stop` → completed, `toolUse` → unfinished, `aborted` → aborted, no model call yet → running. | +| Calls | One assistant message that carries a usage block. Calls that were compacted out of a transcript are not visible. | -Calls whose decode duration exceeds the request duration are excluded from the speed aggregate (that combination means the first token arrived before the request was sent — a timestamp artefact that would otherwise inflate the denominator). They are still listed individually in the ledger. A turn that is still in flight is marked unfinished and its rate is computed from what has arrived so far. +The same message can appear in more than one transcript when a session is rebuilt, so calls are de-duplicated by their message id. -The client interface shows its own figure over its own live session. The board uses the same formula on a window you choose, so once the windows are not identical the two can differ by a fraction of a percent (0.3%–3.0% measured on a reference machine). +The client interface shows its own figure over its own live session. The board uses the transcript records on a window you choose, so the two can differ: the interface counts what the runtime recorded, the board counts what the transcripts still contain. ## Tested environment - MiniMax Code Desktop **3.1.4** (build 186), Windows 11 (10.0.22631, x64) -- Bundled Node.js **v24.18.0**, `node:sqlite` available -- Verified in the desktop client: plugin install, window switching, custom start/end windows, per-call ledger, live turn growth, auto refresh, light and dark themes, and the error path when the runtime database is missing. +- Bundled Node.js **v24.18.0** +- Verified in the desktop client: plugin install, window switching, custom start/end windows, per-call ledger, live turn growth, auto refresh, light and dark themes, and the error path when no session records are found. - macOS and Linux are **not** verified. Nothing in the code is platform-specific — the data paths are resolved from `context.dataDir` — but treat the other platforms as untested. -The full validation record for this release — package checker result, the per-call pairing regression numbers, the injection test, and a same-machine performance A/B — is in [`docs/validation.md`](docs/validation.md). +The full validation record for this release — package checker result, the coverage measurement against the internal ledger, and a same-machine performance measurement — is in [`docs/validation.md`](docs/validation.md). ## Limitations - This is a **local observation tool**, not an invoice. Billing and quota are the product's own "usage" page, which is computed server-side and may catch up later. -- Numbers cover what the client recorded locally. Usage on another machine, or usage from a client that was never running locally, is not visible here. -- The runtime database and the observability log format are internal to the client and can change without notice. -- The client writes one aggregate usage block per assistant message into its transcript files, but the per-call usage table is the authoritative record used here. If the runtime ever stops writing a usage row for a call, that call cannot be shown. +- Numbers cover what your session records still contain. Calls that were compacted out of a transcript, and usage on another machine, are not visible here. +- The transcript format is internal to the client and can change without notice. If the layout changes, the board reports that instead of showing zeros. +- No token speed and no workspace paths, for the reasons above. ## Third-party components @@ -148,12 +170,9 @@ miniapp/ client/index.html The whole page: markup, styles, and the client script client/vendor/ Chart.js (MIT), vendored for offline use client/vendor/LICENSE-chartjs.txt Full MIT licence text for the vendored copy - node/server.mjs HTTP server, routing, and the subprocess fallback - node/lib/common.mjs Data-dir resolution, config catalog, log enrichment, metrics - node/lib/facts.mjs Incremental message-fact cache (SQL-side JSON extraction) - node/lib/queries.mjs Window, summary, session, daily, call, and turn queries - node/lib/trend.mjs Window resolution and bucketing - node/lib/db-child.mjs Query runner for the subprocess fallback + node/server.mjs HTTP server, routing, the loopback guard + node/lib/sessions.mjs Transcript reader: incremental parse, de-duplication, aggregation + node/lib/queries.mjs Window, trend, summary, session, daily, call and turn queries ``` No build step is required: the page and the Node service are used as they are. diff --git a/plugins/hanewari/token-meter-board/README.zh-CN.md b/plugins/hanewari/token-meter-board/README.zh-CN.md index 74a8bf4c..42eb89f9 100644 --- a/plugins/hanewari/token-meter-board/README.zh-CN.md +++ b/plugins/hanewari/token-meter-board/README.zh-CN.md @@ -2,56 +2,78 @@ [English](README.md) | 简体中文 -本机 MiniMax Code 的实时 token 用量看板。读的是运行时自己的**逐次调用台账**与观测日志,所以展示的就是客户端真实记录的数字,而不是从会话文件里反推出来的估算值。 +一个跑在你自己机器上的 MiniMax Code token 用量看板。它只读客户端为**你自己的对话**写下的会话记录——和官方画廊里那块 token 用量看板同一个数据源——别的什么都不读:不打开 runtime 的内部数据库、不扫观测日志、不读配置文件。 -作者:[HaneWari](https://github.com/HaneWari) · 版本:`1.9.0` · 许可证:[Apache-2.0](LICENSE) +作者:[HaneWari](https://github.com/HaneWari) · 版本:`2.0.0` · 许可:[Apache-2.0](LICENSE) -![Token 仪表盘,使用合成数据](docs/preview.png) +![Token 仪表盘(合成数据)](docs/preview.png) -*预览中的会话与用量均为合成数据。应用界面为中文。* +*预览图使用合成会话与用量数据。界面目前是中文。* -## 能看到什么 +## 你能看到什么 -- **用量趋势** —— 按模型堆叠的柱状图,缓存命中率与输出速率两条曲线叠绘在柱状图之上。窗口拉长时分桶自动从分钟级过渡到小时级、天级。 -- **五张明细表** —— 模型明细、每日统计、12 列的**逐次调用台账**、**对话明细(turn 级)**、会话用量排行。 -- **对话明细** —— 你每次提问占一行:用户消息原文、状态、挂钟时长、这一轮消耗了几次模型调用、五类 token、速率。**正在进行中的一轮会实时增长并标记为「未收尾」,无需关闭会话。** -- **逐次调用台账** —— 每一次模型调用都有一行:精确时间、模型、五类 token、输出速率、全程速率、decode 时长、请求全程、状态码。 -- **时间窗口** —— 近 1 小时 / 今天 / 近 7 天 / 近 30 天,或自定义起止时间。时间栏排成两行,保证原生日期选择器向下弹出时不会盖住「应用」按钮;在时间框里按 Enter 同样能应用。 -- **5 秒自动刷新**(也可手动点「刷新」)。切换窗口时旧数据留在屏幕上不空表,新值到达即替换;晚到的旧窗口响应会被丢弃,不会覆盖新窗口。 +- **用量趋势** —— 按模型堆叠的柱状图,上面叠一条缓存命中率曲线。窗口拉长时,桶会自动从分钟切成小时、再切成天。 +- **五张明细表** —— 模型明细、每日统计、**逐次调用台账**、**对话(turn)明细**、会话用量排行。 +- **对话明细** —— 你每问一次就是一行:所属会话、是否收尾、这一轮用了几次模型调用、用了多少 token。还在进行中的对话会标成"进行中"并实时增长——**不需要**先关掉会话。 +- **逐次调用台账** —— 每一次模型调用:时间、模型、四类 token、这次调用怎么结束的。 +- **时间窗口** —— 近 1 小时 / 今天 / 近 7 天 / 近 30 天,或任意自定义起止时间。时间条排成两行,原生日期选择器不会挡住"应用"按钮;在时间输入框里按回车同样生效。 +- **5 秒自动刷新**,另有手动刷新按钮。切换窗口不会让表格空白、也不会干等:旧数据会一直留在屏幕上直到新值到达,迟到的旧窗口响应会被丢弃,不会覆盖更新的结果。 -## 为什么是这一个 +## 它读什么,以及这意味着什么 -同类看板大多只回答「我花了多少」。这个看板同时回答「花到哪去了」,以及「我看到的这个数,是不是客户端自己显示的那个数」。 +看板只读一种文件: -- **读台账,不读会话文件。** 数据来自运行时自己的逐次用量表和观测日志,而不是从会话记录文件里反推。会话记录文件里每条 assistant 消息只带一段汇总用量、且完全没有计时信息,所以读它的看板既看不到那些根本没写进会话文件的调用,也永远给不出「每一次调用」的速度——因为文件里没有计时。实测对照(参考机器,同机对比一款读会话文件的看板):它整体**少报约 48% 的调用、少报约 66% 的缓存读 token**,且按天在 **0%~98%** 之间剧烈波动。根因不是「一消息一聚合」这类统计规则,而是**部分会话根本没留下会话文件**,读文件的看板无从看到。 -- **输出速率与客户端同口径。** 输出速率取 `Σ输出 tokens ÷ Σdecode 时长` —— 只算首 token 到流结束的解码段,与 MiniMax Code 界面显示一致。全程速率作为对照列并排给出,可以直接看出每次调用有多少时间耗在等首 token 上。若改用请求全程计算,得到的数字会低约 **1.6~2.1 倍**,且与界面数字对不上。 -- **每次调用都配回自己的计时。** 看板把每条用量行与携带该次调用 decode / 请求全程时长的那条 assistant 消息配对,既不按时间就近匹配、也不按下标顺序匹配——这两种方式只要一个 turn 里混进一条「不是模型调用」的 assistant 行(上下文压缩就会写这种行)就会整轮错位。此处的配对规则已用 token 签名做真值、在 **16,723 次调用上逐条核对,错配 0 条**。 -- **总 token 算满五项。** `总 = 输入 + 输出 + 推理 + 缓存读 + 缓存写`。只算三项的看板会悄悄漏掉缓存写与推理 token。 -- **turn 级粒度。** 一次提问就是一行,带这一轮实际花掉的调用次数与 token,不需要等会话结束或归档。 -- **不装 Python、不起额外进程、无第三方依赖。** 纯 Node,除了一份本地化的 Chart.js 之外没有第三方运行时代码。同生态里另一款看板需要 Python 3.8+,并且每次查询都要拉起一个 Python 进程。 -- **毫秒级,不是秒级。** v1.7.0 的缓存重构之后,整页刷新从约 8.5 秒降到几十毫秒。在 1.7 万行消息表的参考机器上:整页刷新约 **50 毫秒**,切到 7 天窗口约 **40 毫秒**,全新进程里的第一次查询约 **1.3 秒**(那次必须把消息表扫一遍)。 -- **严格只读。** 不写任何文件、不发任何请求、无遥测。无需账号、无需 API Key、无需任何配置。 +```text +/v2/sessions///
//messages.jsonl +// /v2/sessions///
//manifest.json +// +// The runtime's internal database, its observability logs and its +// configuration file are deliberately NOT read. A community Mini App must not +// open Host-internal stores, not even read-only, so every number on this +// board is derived from the session records the runtime writes for the user's +// own conversations. +// +// WHAT THE SESSION RECORDS CONTAIN +// +// message.role user | assistant | toolResult | custom | compactionSummary +// message.timestamp epoch ms +// message.model model id reported by the provider +// message.usage { input, output, cacheRead, cacheWrite, totalTokens, cost } +// message.stopReason "stop" | "toolUse" | "aborted" | ... +// record.turn_id one user question and the assistant calls that answer it +// record.message_id stable id, used to de-duplicate +// +// The records do NOT carry request or decode durations, so this board cannot +// show token rates, and they do not carry workspace paths, so it never shows +// one. +// +// SCANNING +// +// A full scan of every session file on this machine is ~320 MiB of JSON. The +// reader therefore keeps a per-file cursor (byte offset + head hash) and only +// parses the bytes appended since the previous scan. The cursor is persisted +// in the plugin's own `context.dataDir`, so a restart resumes instead of +// re-reading everything. + +import fsp from 'node:fs/promises'; +import path from 'node:path'; +import os from 'node:os'; +import crypto from 'node:crypto'; + +const STATE_FILE = 'session-scan-state.json'; +const STATE_VERSION = 1; +const HEAD_BYTES = 4096; +const SAVE_THROTTLE_MS = 15000; + +/** stopReason codes kept compact in the persisted state. */ +const STOP_CODES = { stop: 1, toolUse: 2, aborted: 3 }; +const STOP_NAMES = { 1: 'stop', 2: 'toolUse', 3: 'aborted' }; + +// --------------------------------------------------------------------------- +// path helpers +// --------------------------------------------------------------------------- + +/** @param {string} dir */ +async function isDirectory(dir) { + try { + return (await fsp.stat(dir)).isDirectory(); + } catch { + return false; + } +} + +/** + * Locate the active runtime's session-record directory. + * + * The Host-provided `context.dataDir` lives inside the active data root (for + * example `/v2/plugin-data/`), so walking up from it finds + * the root that is actually in use. This is the same resolution the official + * gallery's token-usage board uses. + * + * @param {import('./miniapp-api.js').MiniAppContext} context + * @returns {Promise} + */ +export async function resolveSessionsRoot(context) { + const envDir = process.env.MINIMAX_DATA_DIR; + if (envDir) { + const candidate = path.join(envDir, 'v2', 'sessions'); + if (await isDirectory(candidate)) return candidate; + } + let dir = context.dataDir ? path.resolve(context.dataDir) : null; + for (let i = 0; dir && i < 10; i += 1) { + const candidate = path.join(dir, 'v2', 'sessions'); + if (await isDirectory(candidate)) return candidate; + const parent = path.dirname(dir); + if (parent === dir) break; + dir = parent; + } + return path.join(os.homedir(), '.minimax', 'v2', 'sessions'); +} + +/** + * Collect every `messages.jsonl` under the session root. + * The layout is `/YYYY/MM/DD//`, but the walk also accepts + * other depths so a future runtime layout still works. + * @param {string} root + */ +async function collectSessionFiles(root) { + /** @type {string[]} */ + const found = []; + /** @type {{dir: string, depth: number}[]} */ + const queue = [{ dir: root, depth: 0 }]; + while (queue.length) { + const current = queue.shift(); + if (!current) break; + let entries; + try { + entries = await fsp.readdir(current.dir, { withFileTypes: true }); + } catch { + continue; + } + for (const entry of entries) { + const full = path.join(current.dir, entry.name); + if (entry.isDirectory()) { + if (current.depth < 5) queue.push({ dir: full, depth: current.depth + 1 }); + continue; + } + if (entry.name === 'messages.jsonl') found.push(full); + } + } + return found.sort(); +} + +/** + * Read a session id from the manifest that sits next to the transcript. + * @param {string} dir + */ +async function readSessionId(dir) { + try { + const raw = await fsp.readFile(path.join(dir, 'manifest.json'), 'utf8'); + const manifest = JSON.parse(raw); + if (typeof manifest?.sessionId === 'string' && manifest.sessionId) return manifest.sessionId; + } catch { + // manifest is optional + } + return null; +} + +const SYSTEM_REMINDER_RE = /[\s\S]*?<\/system-reminder>/g; +const TITLE_MAX = 80; + +/** + * Derive a short human-readable session title from the first user text. + * Mirrors the official gallery's token-usage board: only the first text block + * of the first user message, with injected system reminders removed. + * @param {any} message + */ +function titleFromUserMessage(message) { + const content = Array.isArray(message?.content) ? message.content : []; + for (const block of content) { + if (block?.type !== 'text' || typeof block.text !== 'string') continue; + const cleaned = block.text.replace(SYSTEM_REMINDER_RE, '').replace(/\s+/g, ' ').trim(); + if (cleaned) return cleaned.length > TITLE_MAX ? `${cleaned.slice(0, TITLE_MAX)}…` : cleaned; + } + return null; +} + +/** @param {unknown} value */ +function num(value) { + return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : 0; +} + +/** + * The runtime records `cost` either as a number or as a breakdown object + * (`{ input, output, cacheRead, cacheWrite, total }`); the object form is what + * this runtime writes. + * @param {unknown} value + */ +function costValue(value) { + if (typeof value === 'number') return num(value); + if (value && typeof value === 'object') return num(/** @type {any} */ (value).total); + return 0; +} + +// --------------------------------------------------------------------------- +// file parsing +// --------------------------------------------------------------------------- + +/** + * @typedef {Object} CallFact + * @property {string} id message id + * @property {number} ts epoch ms + * @property {string} model + * @property {string} turn turn id ('' when the record has none) + * @property {number} input + * @property {number} output + * @property {number} cacheRead + * @property {number} cacheWrite + * @property {number} total + * @property {number} cost + * @property {number} stop stopReason code + */ + +/** + * @typedef {Object} TurnFact + * @property {number} user + * @property {number} assistant + * @property {number} firstTs + * @property {number} lastTs + * @property {number} lastStop + * @property {number} lastStopTs + */ + +/** + * @typedef {Object} FileFact + * @property {string} path + * @property {number} size + * @property {number} mtimeMs + * @property {number} offset bytes already consumed + * @property {string} head hash of the first bytes, detects rewrites + * @property {string} sessionId + * @property {string} title + * @property {CallFact[]} calls + * @property {Map} turns + */ + +/** + * Read the first bytes of a file and hash them, so a rewritten transcript is + * detected even when it only grew. + * @param {string} file + */ +async function readHeadHash(file) { + let handle; + try { + handle = await fsp.open(file, 'r'); + const buf = Buffer.allocUnsafe(HEAD_BYTES); + const { bytesRead } = await handle.read(buf, 0, HEAD_BYTES, 0); + return crypto.createHash('sha1').update(buf.subarray(0, bytesRead)).digest('hex').slice(0, 16); + } catch { + return ''; + } finally { + await handle?.close().catch(() => {}); + } +} + +/** + * Read a byte range of a file. + * @param {string} file + * @param {number} start + * @param {number} length + */ +async function readRange(file, start, length) { + if (length <= 0) return Buffer.alloc(0); + let handle; + try { + handle = await fsp.open(file, 'r'); + const buf = Buffer.allocUnsafe(length); + const { bytesRead } = await handle.read(buf, 0, length, start); + return buf.subarray(0, bytesRead); + } catch { + return Buffer.alloc(0); + } finally { + await handle?.close().catch(() => {}); + } +} + +/** + * Parse the text of one transcript into calls and per-turn counters. + * @param {string} text + * @param {Map} turns mutated in place + * @param {{id: string, ts: number, model: string, turn: string, input: number, output: number, cacheRead: number, cacheWrite: number, total: number, cost: number, stop: number}[]} calls mutated in place + */ +function parseTranscript(text, turns, calls) { + const lines = text.split('\n'); + for (const line of lines) { + if (!line.trim()) continue; + /** @type {any} */ + let record; + try { + record = JSON.parse(line); + } catch { + continue; + } + const message = record?.message; + if (!message || typeof message !== 'object') continue; + const turn = typeof record.turn_id === 'string' ? record.turn_id : ''; + const ts = typeof message.timestamp === 'number' ? message.timestamp : 0; + + let turnFact = turn ? turns.get(turn) : undefined; + if (turn && !turnFact) { + turnFact = { user: 0, assistant: 0, firstTs: 0, lastTs: 0, lastStop: 0, lastStopTs: 0 }; + turns.set(turn, turnFact); + } + if (turnFact) { + if (ts && (!turnFact.firstTs || ts < turnFact.firstTs)) turnFact.firstTs = ts; + if (ts && ts > turnFact.lastTs) turnFact.lastTs = ts; + } + + if (message.role === 'user') { + if (turnFact) turnFact.user += 1; + continue; + } + if (message.role !== 'assistant') continue; + if (turnFact) turnFact.assistant += 1; + + const stopCode = STOP_CODES[message.stopReason] ?? 0; + if (turnFact && ts >= turnFact.lastStopTs) { + turnFact.lastStop = stopCode; + turnFact.lastStopTs = ts; + } + + const usage = message.usage; + if (!usage || typeof usage !== 'object') continue; + calls.push({ + id: typeof record.message_id === 'string' && record.message_id ? record.message_id : `${message.responseId ?? ''}:${ts}:${calls.length}`, + ts, + model: typeof message.model === 'string' && message.model ? message.model : '(unknown)', + turn, + input: num(usage.input), + output: num(usage.output), + cacheRead: num(usage.cacheRead), + cacheWrite: num(usage.cacheWrite), + total: num(usage.totalTokens), + cost: costValue(usage.cost), + stop: stopCode, + }); + } +} + +// --------------------------------------------------------------------------- +// the store +// --------------------------------------------------------------------------- + +export class SessionStore { + /** @param {import('./miniapp-api.js').MiniAppContext} context */ + constructor(context) { + this.context = context; + /** @type {string} */ + this.root = ''; + /** @type {Map} */ + this.files = new Map(); + this.scannedAt = 0; + this.scanMs = 0; + this.lastError = ''; + /** @type {Promise | null} */ + this.scanning = null; + this.lastSaveAt = 0; + this.dirty = false; + this.statePath = path.join(context.dataDir, STATE_FILE); + this.ready = false; + } + + /** Load the persisted cursor, if one is usable. */ + async init() { + this.root = await resolveSessionsRoot(this.context); + try { + const raw = await fsp.readFile(this.statePath, 'utf8'); + const state = JSON.parse(raw); + if (state?.version === STATE_VERSION && state.root === this.root && Array.isArray(state.files)) { + for (const entry of state.files) { + /** @type {FileFact} */ + const file = { + path: entry.p, + size: entry.size | 0, + mtimeMs: entry.mtimeMs | 0, + offset: entry.offset | 0, + head: typeof entry.head === 'string' ? entry.head : '', + sessionId: typeof entry.sessionId === 'string' ? entry.sessionId : '', + title: typeof entry.title === 'string' ? entry.title : '', + calls: [], + turns: new Map(), + }; + for (const c of entry.calls ?? []) { + file.calls.push({ + id: c[0], + ts: c[1], + model: c[2], + turn: c[3], + input: c[4], + output: c[5], + cacheRead: c[6], + cacheWrite: c[7], + total: c[8], + cost: c[9], + stop: c[10], + }); + } + for (const t of entry.turns ?? []) { + file.turns.set(t[0], { user: t[1], assistant: t[2], firstTs: t[3], lastTs: t[4], lastStop: t[5], lastStopTs: t[6] }); + } + this.files.set(file.path, file); + } + } + } catch { + // no usable snapshot; the first scan reads everything + } + this.ready = true; + } + + /** + * Refresh the file set and parse whatever changed. + * Concurrent callers share one scan. + */ + async scan() { + if (this.scanning) return this.scanning; + this.scanning = this.#scanInner().finally(() => { + this.scanning = null; + }); + return this.scanning; + } + + async #scanInner() { + const started = Date.now(); + let files = []; + try { + files = await collectSessionFiles(this.root); + } catch (error) { + this.lastError = 'sessions_root_unreadable'; + this.scannedAt = Date.now(); + this.scanMs = Date.now() - started; + return; + } + this.lastError = ''; + + const seen = new Set(); + for (const file of files) { + seen.add(file); + await this.#updateFile(file); + } + for (const known of [...this.files.keys()]) { + if (!seen.has(known)) this.files.delete(known); + } + this.scannedAt = Date.now(); + this.scanMs = Date.now() - started; + this.dirty = true; + await this.save(); + } + + /** + * Parse one transcript, reusing the previous cursor when the file only grew. + * @param {string} file + */ + async #updateFile(file) { + let stat; + try { + stat = await fsp.stat(file); + } catch { + this.files.delete(file); + return; + } + if (!stat.isFile()) return; + + const previous = this.files.get(file); + const head = await readHeadHash(file); + const canResume = Boolean( + previous && + previous.head === head && + stat.size >= previous.size && + previous.offset <= stat.size, + ); + + /** @type {CallFact[]} */ + const calls = []; + /** @type {Map} */ + const turns = new Map(); + let title = ''; + let offset = 0; + + if (canResume && previous) { + calls.push(...previous.calls); + for (const [key, value] of previous.turns) turns.set(key, { ...value }); + title = previous.title; + const tail = await readRange(file, previous.offset, stat.size - previous.offset); + const text = tail.toString('utf8'); + const lastBreak = text.lastIndexOf('\n'); + if (lastBreak >= 0) { + const complete = text.slice(0, lastBreak + 1); + parseTranscript(complete, turns, calls); + offset = previous.offset + Buffer.byteLength(complete, 'utf8'); + } else { + // A single trailing line with no newline: it may still be growing. + // Parse it, and only accept it when it is valid JSON. + const before = calls.length; + parseTranscript(text, turns, calls); + const grew = calls.length > before; + offset = grew ? previous.offset + Buffer.byteLength(text, 'utf8') : previous.offset; + } + } else { + const whole = await readRange(file, 0, stat.size); + const text = whole.toString('utf8'); + const lastBreak = text.lastIndexOf('\n'); + const complete = lastBreak >= 0 ? text.slice(0, lastBreak + 1) : text; + parseTranscript(complete, turns, calls); + offset = Buffer.byteLength(complete, 'utf8'); + // a transcript whose last line has no newline is still complete + if (lastBreak < 0) offset = stat.size; + } + + const sessionId = (await readSessionId(path.dirname(file))) ?? ''; + if (!title) { + // The title comes from the first user text in this transcript. + title = await this.#extractTitle(file); + } + + this.files.set(file, { + path: file, + size: stat.size, + mtimeMs: stat.mtimeMs, + offset, + head, + sessionId, + title, + calls, + turns, + }); + } + + /** + * Read the first user text of a transcript for a session title. + * Only the head of the file is inspected. + * @param {string} file + */ + async #extractTitle(file) { + try { + const head = await readRange(file, 0, 256 * 1024); + const text = head.toString('utf8'); + for (const line of text.split('\n')) { + if (!line.trim()) continue; + /** @type {any} */ + let record; + try { + record = JSON.parse(line); + } catch { + continue; + } + const message = record?.message; + if (!message || message.role !== 'user') continue; + const title = titleFromUserMessage(message); + if (title) return title; + } + } catch { + // no title available + } + return ''; + } + + /** Persist the cursor, throttled so an active session does not thrash disk. */ + async save(force = false) { + if (!this.dirty) return; + const now = Date.now(); + if (!force && now - this.lastSaveAt < SAVE_THROTTLE_MS) return; + this.lastSaveAt = now; + this.dirty = false; + /** @type {any[]} */ + const files = []; + for (const file of this.files.values()) { + files.push({ + p: file.path, + size: file.size, + mtimeMs: file.mtimeMs, + offset: file.offset, + head: file.head, + sessionId: file.sessionId, + title: file.title, + calls: file.calls.map((c) => [c.id, c.ts, c.model, c.turn, c.input, c.output, c.cacheRead, c.cacheWrite, c.total, c.cost, c.stop]), + turns: [...file.turns.entries()].map(([k, v]) => [k, v.user, v.assistant, v.firstTs, v.lastTs, v.lastStop, v.lastStopTs]), + }); + } + const payload = JSON.stringify({ version: STATE_VERSION, root: this.root, savedAt: now, files }); + const temp = `${this.statePath}.tmp`; + try { + await fsp.mkdir(path.dirname(this.statePath), { recursive: true }); + await fsp.writeFile(temp, payload, 'utf8'); + await fsp.rename(temp, this.statePath); + } catch (error) { + this.lastError = 'state_write_failed'; + await fsp.rm(temp, { force: true }).catch(() => {}); + } + } + + /** + * Aggregate every call inside a window. + * + * The same message can appear in more than one transcript (a rebuilt session + * copies its earlier messages), so calls are de-duplicated by message id. + * + * @param {number} startMs + * @param {number} endMs + */ + aggregate(startMs, endMs) { + /** @type {Map} */ + const byDay = new Map(); + /** @type {Map} */ + const byModel = new Map(); + /** @type {Map} */ + const bySession = new Map(); + /** @type {Map} */ + const byTurn = new Map(); + const seenIds = new Set(); + const calls = []; + let totalCalls = 0; + let input = 0; + let output = 0; + let cacheRead = 0; + let cacheWrite = 0; + let total = 0; + let cost = 0; + + const emptyBucket = () => ({ + calls: 0, + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + total: 0, + cost: 0, + firstTs: 0, + lastTs: 0, + }); + + for (const file of this.files.values()) { + const sessionId = file.sessionId || file.path; + for (const call of file.calls) { + if (call.ts < startMs || call.ts > endMs) continue; + if (seenIds.has(call.id)) continue; + seenIds.add(call.id); + totalCalls += 1; + input += call.input; + output += call.output; + cacheRead += call.cacheRead; + cacheWrite += call.cacheWrite; + total += call.total; + cost += call.cost; + calls.push(call); + + const day = dayKey(call.ts); + let bucket = byDay.get(day); + if (!bucket) { + bucket = { ...emptyBucket(), models: new Map() }; + byDay.set(day, bucket); + } + addTo(bucket, call); + bucket.models.set(call.model, (bucket.models.get(call.model) ?? 0) + call.total); + + let modelBucket = byModel.get(call.model); + if (!modelBucket) { + modelBucket = emptyBucket(); + byModel.set(call.model, modelBucket); + } + addTo(modelBucket, call); + + let sessionBucket = bySession.get(sessionId); + if (!sessionBucket) { + sessionBucket = { ...emptyBucket(), sessionId, title: file.title || '', turns: new Set(), models: new Map() }; + bySession.set(sessionId, sessionBucket); + } + addTo(sessionBucket, call); + sessionBucket.models.set(call.model, (sessionBucket.models.get(call.model) ?? 0) + call.total); + if (call.turn) sessionBucket.turns.add(call.turn); + + if (call.turn) { + let turnBucket = byTurn.get(call.turn); + if (!turnBucket) { + const fact = file.turns.get(call.turn); + turnBucket = { + turnId: call.turn, + sessionId, + title: file.title || '', + calls: 0, + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + total: 0, + cost: 0, + firstTs: call.ts, + lastTs: call.ts, + lastStop: fact?.lastStop ?? 0, + lastStopTs: fact?.lastStopTs ?? 0, + models: new Set(), + userMessages: fact?.user ?? 0, + assistantMessages: fact?.assistant ?? 0, + }; + byTurn.set(call.turn, turnBucket); + } + addTo(turnBucket, call); + turnBucket.models.add(call.model); + if (call.ts < turnBucket.firstTs) turnBucket.firstTs = call.ts; + if (call.ts > turnBucket.lastTs) turnBucket.lastTs = call.ts; + if (call.ts >= turnBucket.lastStopTs) { + turnBucket.lastStop = call.stop; + turnBucket.lastStopTs = call.ts; + } + if (!turnBucket.title && file.title) turnBucket.title = file.title; + } + } + } + + // Turns that have a user message but no assistant call yet are still + // running; they are not part of `byTurn` because no call was counted. + for (const file of this.files.values()) { + for (const [turnId, fact] of file.turns) { + if (byTurn.has(turnId)) continue; + if (fact.user <= 0) continue; + if (fact.lastTs < startMs || fact.firstTs > endMs) continue; + byTurn.set(turnId, { + turnId, + sessionId: file.sessionId || file.path, + title: file.title || '', + calls: 0, + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + total: 0, + cost: 0, + firstTs: fact.firstTs, + lastTs: fact.lastTs, + lastStop: fact.lastStop, + lastStopTs: fact.lastStopTs, + models: new Set(), + userMessages: fact.user, + assistantMessages: fact.assistant, + }); + } + } + + return { + calls, + totals: { calls: totalCalls, input, output, cacheRead, cacheWrite, total, cost }, + byDay, + byModel, + bySession, + byTurn, + }; + } + + /** A short, non-identifying description of the scan, for the health view. */ + describe() { + let calls = 0; + let turns = 0; + for (const file of this.files.values()) { + calls += file.calls.length; + turns += file.turns.size; + } + return { + files: this.files.size, + calls, + turns, + scannedAt: this.scannedAt, + scanMs: this.scanMs, + }; + } +} + +/** @param {any} bucket @param {CallFact} call */ +function addTo(bucket, call) { + bucket.calls += 1; + bucket.input += call.input; + bucket.output += call.output; + bucket.cacheRead += call.cacheRead; + bucket.cacheWrite += call.cacheWrite; + bucket.total += call.total; + bucket.cost += call.cost; + if (!bucket.firstTs || call.ts < bucket.firstTs) bucket.firstTs = call.ts; + if (call.ts > bucket.lastTs) bucket.lastTs = call.ts; +} + +/** Local-time day key. */ +export function dayKey(ms) { + const d = new Date(ms); + const y = d.getFullYear(); + const m = String(d.getMonth() + 1).padStart(2, '0'); + const dd = String(d.getDate()).padStart(2, '0'); + return `${y}-${m}-${dd}`; +} + +/** Human label for a stopReason code. */ +export function stopName(code) { + return STOP_NAMES[code] || ''; +} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs deleted file mode 100644 index a3f044aa..00000000 --- a/plugins/hanewari/token-meter-board/miniapp/node/lib/trend.mjs +++ /dev/null @@ -1,247 +0,0 @@ -// token-meter trend pipeline: window parsing, bucket picking, and bucketed -// per-model usage series. buildTrendFromContext lets callers combine the trend -// with other aggregations over a single DB/log scan; buildTrendResult keeps -// the standalone one-shot behavior. -import { - resolveDataDir, - openDb, - clampInt, - queryUsageRows, - loadCatalog, - loadTurnEnrichment, - resolveRowIdentity, - emptyMetrics, - addRow, - finalize, - buildLedgerWithDb, - syncMessageFacts, - meanCallRate, - rateStats, - requestRateStats, - countRatedCalls, -} from './common.mjs'; - -export function parseLocalDateTime(value) { - const m = String(value || '') - .trim() - .match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?/); - if (!m) return null; - const d = new Date(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +(m[6] || 0), 0); - return Number.isNaN(d.getTime()) ? null : d.getTime(); -} - -export function resolveTrendWindow(args, now = Date.now()) { - if (args?.startAt) { - const startMs = parseLocalDateTime(args.startAt); - const endRaw = args.endAt ? parseLocalDateTime(args.endAt) : now; - if (startMs == null || endRaw == null) { - throw new Error('invalid startAt/endAt; expect local "YYYY-MM-DDTHH:MM"'); - } - const endMs = Math.min(endRaw, now); - if (endMs <= startMs) throw new Error('endAt must be after startAt'); - return { startMs, endMs }; - } - const days = clampInt(args?.days, 1, 90, 7); - const todayStart = new Date(); - todayStart.setHours(0, 0, 0, 0); - // Second-level quantisation keeps a rolling window stable, so repeated - // queries inside the same second share one cached context instead of - // rebuilding the scan for every request. - return { startMs: todayStart.getTime() - (days - 1) * 86400000, endMs: Math.floor(now / 1000) * 1000 }; -} - -export function pickBucket(startMs, endMs, requested) { - const spanMin = (endMs - startMs) / 60000; - let bucket = requested && requested !== 'auto' ? requested : spanMin <= 360 ? 'minute' : spanMin <= 7 * 24 * 60 ? 'hour' : 'day'; - // keep bucket count manageable - const spanMs = Math.max(endMs - startMs, 1); - const approx = (b) => Math.ceil(spanMs / (b === 'minute' ? 60000 : b === 'hour' ? 3600000 : 86400000)); - if (approx(bucket) > 600) bucket = bucket === 'minute' ? 'hour' : 'day'; - return bucket; -} - -export function bucketFloor(ts, bucket) { - const d = new Date(ts); - if (bucket === 'minute') d.setSeconds(0, 0); - else if (bucket === 'hour') d.setMinutes(0, 0, 0); - else d.setHours(0, 0, 0, 0); - return d.getTime(); -} - -export function bucketLabel(ms, bucket, multiDay) { - const d = new Date(ms); - const p = (n) => String(n).padStart(2, '0'); - if (bucket === 'day') return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`; - if (multiDay) return `${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`; - return `${p(d.getHours())}:${p(d.getMinutes())}`; -} - -const MAX_TREND_MODELS = 5; - -function round2(v) { - return Math.round(v * 100) / 100; -} - -// Build the trend result from an already-open query context. -// ctx: { rows, catalog, enrichment (Map), ledger, dataDir, filesScanned }. -// ledger entries are per-call records (identity + tokens + decode rate) built -// by common.buildCallLedger; when absent it is derived from rows for -// backward compatibility (rates then stay null). -export function buildTrendFromContext(ctx, { startMs, endMs, bucket: requestedBucket, fillEmpty: fillArg, now = Date.now() }) { - const bucket = pickBucket(startMs, endMs, requestedBucket); - const { rows, catalog, enrichment } = ctx; - const ledger = ctx.ledger || rows.map((row) => ({ ...row, ...resolveRowIdentity(row, enrichment, catalog), ts: row.ts, rate: null })); - const dir = ctx.dataDir; - const filesScanned = ctx.filesScanned ?? 0; - - // rank models by total tokens (ledger entries already carry resolved identity) - const byModelTotals = new Map(); - let unknownRows = 0; - for (const call of ledger) { - if (call.model === '(unknown)') unknownRows += 1; - const key = `${call.provider}|${call.model}`; - if (!byModelTotals.has(key)) byModelTotals.set(key, { id: call, tokens: 0 }); - byModelTotals.get(key).tokens += - (call.input_tokens || 0) + (call.output_tokens || 0) + (call.reasoning_tokens || 0) + (call.cache_read_tokens || 0) + (call.cache_write_tokens || 0); - } - const ranked = [...byModelTotals.entries()].sort((a, b) => { - if (a[1].id.custom !== b[1].id.custom) return a[1].id.custom ? -1 : 1; - return b[1].tokens - a[1].tokens; - }); - const topKeys = ranked.slice(0, MAX_TREND_MODELS).map(([k]) => k); - const modelList = ranked.slice(0, MAX_TREND_MODELS).map(([key, v]) => ({ - key, - model: v.id.model, - modelName: v.id.modelName, - providerName: v.id.providerName, - custom: v.id.custom, - totalTokens: v.tokens, - })); - const hasOther = ranked.length > MAX_TREND_MODELS; - if (hasOther) { - modelList.push({ - key: '__other__', - model: '(other)', - modelName: '其他模型', - providerName: '', - custom: false, - totalTokens: ranked.slice(MAX_TREND_MODELS).reduce((s, [, v]) => s + v.tokens, 0), - }); - } - - // bucket aggregation - const multiDay = endMs - startMs > 24 * 3600000; - const buckets = new Map(); - const kpi = emptyMetrics(); - const seriesKeys = hasOther ? [...topKeys, '__other__'] : topKeys; - for (const call of ledger) { - addRow(kpi, call); - const bStart = bucketFloor(call.ts, bucket); - if (!buckets.has(bStart)) { - buckets.set(bStart, { totals: emptyMetrics(), perModel: new Map(), rateOut: 0, rateDecodeMs: 0, rated: 0 }); - } - const b = buckets.get(bStart); - addRow(b.totals, call); - // Accumulate the UI basis directly (Σoutput ÷ Σdecode) instead of averaging - // per-call rates: the arithmetic mean is wrecked by the few calls the runtime - // times with a sub-second decode span, and it disagreed with the headline KPI. - // The inconsistent-timing exclusion mirrors common.collectDecodeRates/weightedRate. - if ( - typeof call.rate === 'number' && - !(call.decodeMs != null && call.requestMs != null && call.decodeMs > call.requestMs) - ) { - b.rateOut += call.output_tokens || 0; - b.rateDecodeMs += call.decodeMs || 0; - b.rated += 1; - } - const modelKey = `${call.provider}|${call.model}`; - const key = topKeys.includes(modelKey) ? modelKey : '__other__'; - const rowTotal = - (call.input_tokens || 0) + (call.output_tokens || 0) + (call.reasoning_tokens || 0) + (call.cache_read_tokens || 0) + (call.cache_write_tokens || 0); - b.perModel.set(key, (b.perModel.get(key) || 0) + rowTotal); - } - - const fillEmpty = fillArg !== false; - let starts; - if (fillEmpty) { - const stepMs = bucket === 'minute' ? 60000 : bucket === 'hour' ? 3600000 : 86400000; - starts = []; - // Day buckets align to local midnight; stepping from the floored start keeps - // minute/hour buckets aligned to wall-clock boundaries as well. - for (let ms = bucketFloor(startMs, bucket), end = bucketFloor(endMs, bucket); ms <= end; ms += stepMs) { - starts.push(ms); - if (starts.length > 1000) break; // safety, pickBucket already caps at ~600 - } - } else { - starts = [...buckets.keys()].sort((a, b) => a - b); - } - const labels = starts.map((ms) => bucketLabel(ms, bucket, multiDay)); - const tokensByModel = {}; - for (const key of seriesKeys) tokensByModel[key] = []; - const cacheHitRate = []; - const outputRate = []; - const calls = []; - const totalTokens = []; - for (const ms of starts) { - const b = buckets.get(ms); - if (b) finalize(b.totals); - for (const key of seriesKeys) tokensByModel[key].push(b?.perModel.get(key) || 0); - cacheHitRate.push(b ? b.totals.cacheHitRate : null); - // Σoutput ÷ Σdecode for the calls in this bucket — same basis as the headline - // KPI and the desktop UI; null when nothing measured, so the chart leaves a gap - // instead of a misleading zero - outputRate.push(b && b.rated > 0 && b.rateDecodeMs > 0 ? round2(b.rateOut / (b.rateDecodeMs / 1000)) : null); - calls.push(b ? b.totals.calls : 0); - totalTokens.push(b ? b.totals.totalTokens : 0); - } - finalize(kpi); - kpi.outputRate = meanCallRate(ledger); - kpi.rate = rateStats(ledger); - kpi.requestRate = requestRateStats(ledger); - kpi.rateMeasured = countRatedCalls(ledger); - - return { - window: { - start: new Date(startMs).toISOString(), - end: new Date(endMs).toISOString(), - bucket, - bucketCount: starts.length, - fillEmpty, - }, - kpis: { ...kpi, activeModels: ranked.length }, - models: modelList, - series: { labels, bucketStarts: starts, tokensByModel, cacheHitRate, outputRate, calls, totalTokens }, - unknownRows, - meta: { - dataDir: dir, - rows: rows.length, - logFilesScanned: filesScanned, - turnsEnriched: enrichment.size, - generatedAt: new Date(now).toISOString(), - }, - }; -} - -// Standalone trend query: opens its own context, aggregates, closes. -export function buildTrendResult({ dataDir, startMs, endMs, bucket, fillEmpty, now = Date.now() }) { - const dir = dataDir || resolveDataDir(); - const { db, error } = openDb(dir); - if (!db) { - const err = new Error(error || `runtime state database unavailable under ${dir}`); - err.code = 'NO_DB'; - throw err; - } - try { - const rows = queryUsageRows(db, startMs, endMs); - const catalog = loadCatalog(dir); - const { map: enrichment, filesScanned } = loadTurnEnrichment(dir, startMs, { now }); - const store = syncMessageFacts(db, dir, { now }); - const ledger = buildLedgerWithDb(db, rows, enrichment, catalog, store); - return buildTrendFromContext( - { rows, catalog, enrichment, ledger, dataDir: dir, filesScanned }, - { startMs, endMs, bucket, fillEmpty, now }, - ); - } finally { - db.close(); - } -} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/server.mjs b/plugins/hanewari/token-meter-board/miniapp/node/server.mjs index 2bf16e4b..8dcdb8ae 100644 --- a/plugins/hanewari/token-meter-board/miniapp/node/server.mjs +++ b/plugins/hanewari/token-meter-board/miniapp/node/server.mjs @@ -1,182 +1,105 @@ // @ts-check -// token-meter-board Mini App Node entry: serves the dashboard page and the -// read-only usage query API. Data comes from the local MiniMax Code runtime -// state (sqlite + observability logs + config.yaml); all queries are read-only. +// token-meter-board Mini App Node entry. +// +// Serves the dashboard page and a read-only JSON API. Every number the page +// shows is derived from the runtime's own session records +// (`/v2/sessions/**/messages.jsonl`), read by lib/sessions.mjs. +// +// The runtime's internal database, its observability logs and its Host +// configuration are NOT opened: a community Mini App must not touch +// Host-internal stores. The consequence is honest and visible on the page: +// the session records carry token counts, model ids and stop reasons, but no +// durations and no workspace paths, so this board shows neither a token rate +// nor a path. + import fs from 'node:fs'; import http from 'node:http'; import path from 'node:path'; -import { spawn } from 'node:child_process'; import { fileURLToPath } from 'node:url'; -import { resolveDataDir, openDb, factsStore, factsStats } from './lib/common.mjs'; -import { resolveTrendWindow, buildTrendResult } from './lib/trend.mjs'; -import { querySummary, querySessions, queryDaily, queryWindow, queryCalls, queryTurns } from './lib/queries.mjs'; +import { + ensureScanned, + queryCalls, + queryDaily, + queryHealth, + queryModels, + querySessions, + queryTurns, + queryWindow, + resetStore, + saveStore, +} from './lib/queries.mjs'; /** @typedef {import('./miniapp-api.js').MiniAppContext} MiniAppContext */ /** @typedef {import('./miniapp-api.js').MiniAppLifecycle} MiniAppLifecycle */ const HERE = path.dirname(fileURLToPath(import.meta.url)); -const CHILD_PATH = path.join(HERE, 'lib', 'db-child.mjs'); +const LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '::1']); -// Locate the MiniMax Code data directory. In the Mini App runtime neither -// MINIMAX_DATA_DIR nor PLUGIN_DATA is guaranteed, so first walk up from the -// Host-injected plugin data dir looking for the runtime database, then fall -// back to the shared resolution chain (env override, PLUGIN_DATA, ~/.minimax). -function resolveAppDataDir(contextDataDir) { - const envDir = process.env.MINIMAX_DATA_DIR; - if (envDir && fs.existsSync(envDir)) return path.resolve(envDir); - let dir = contextDataDir ? path.resolve(contextDataDir) : null; - for (let i = 0; dir && i < 8; i += 1) { - if (fs.existsSync(path.join(dir, 'v2', 'sqlite', 'runtime-state.sqlite'))) return dir; - const parent = path.dirname(dir); - if (parent === dir) break; - dir = parent; +/** + * The Host header must name this machine (a DNS-rebound name is refused), and + * a browser Origin, when sent, must be this listener: http, a loopback host + * and our port. The page itself is same-origin. + * @param {import('node:http').IncomingMessage} request + * @param {number} port + */ +function isLoopbackRequest(request, port) { + const host = request.headers.host; + if (host !== undefined && !LOOPBACK_HOSTS.has(hostnameOf(host))) return false; + const origin = request.headers.origin; + if (origin === undefined) return true; + let url; + try { + url = new URL(origin); + } catch { + return false; // includes "null" (sandboxed iframes, file://) } - return resolveDataDir(); + const originPort = Number(url.port || (url.protocol === 'https:' ? 443 : 80)); + return url.protocol === 'http:' && LOOPBACK_HOSTS.has(hostnameOf(url.host)) && originPort === port; } -function isSqliteUnavailable(err) { - return Boolean(err && err.code === 'NO_DB' && /node:sqlite/.test(err.message || '')); +/** @param {string} hostHeader */ +function hostnameOf(hostHeader) { + const h = hostHeader.trim().toLowerCase(); + const bracketed = /^\[([^\]]*)\]/.exec(h); + if (bracketed) return bracketed[1]; + const colon = h.lastIndexOf(':'); + return colon === -1 ? h : h.slice(0, colon); } +/** + * Strip anything that looks like an absolute path out of a message that is + * about to be sent to the page. The Host logger keeps the original, so + * diagnostics are not lost — only the page sees the redacted form. + * @param {string} message + */ +export function redactPaths(message) { + return message + .replace(/\b[A-Za-z]:[\\/][^\s"'`)]*/g, '') + .replace(/\/(?:[\w.-]+\/)+[\w.-]*/g, '') + .slice(0, 200); +} + +/** + * Query parameters are an ALLOW-LIST, not a pass-through: a crafted query + * string can never reach the query layer with a key it does not expect. + * @type {Record} + */ +const API_PARAMS = { + window: ['startAt', 'endAt', 'days', 'bucket'], + trend: ['startAt', 'endAt', 'days', 'bucket'], + summary: ['startAt', 'endAt', 'days'], + models: ['startAt', 'endAt', 'days'], + sessions: ['startAt', 'endAt', 'days', 'limit'], + daily: ['startAt', 'endAt', 'days'], + turns: ['startAt', 'endAt', 'days', 'limit'], + calls: ['startAt', 'endAt', 'days', 'limit'], +}; + /** * @param {MiniAppContext} context * @returns {Promise} */ export async function start(context) { - const dataDir = resolveAppDataDir(context.dataDir); - const children = new Set(); - // null = untried, false = in-process works, true = must use child fallback. - let childMode = null; - - // NOTE the spread order: `...p` first, `dataDir` last. The data directory is - // resolved by the Host and must never be overridable by a request, so it is - // applied AFTER the caller-supplied parameters on purpose. - const MODES = { - window: (p) => queryWindow({ ...p, dataDir }), - trend: (p) => { - const now = Date.now(); - const { startMs, endMs } = resolveTrendWindow( - { startAt: p.startAt, endAt: p.endAt, days: p.days }, - now, - ); - return buildTrendResult({ dataDir, startMs, endMs, bucket: p.bucket, fillEmpty: p.fillEmpty, now }); - }, - summary: (p) => querySummary({ ...p, dataDir }), - sessions: (p) => querySessions({ ...p, dataDir }), - daily: (p) => queryDaily({ ...p, dataDir }), - calls: (p) => queryCalls({ ...p, dataDir }), - turns: (p) => queryTurns({ ...p, dataDir }), - }; - - function runChild(mode, params) { - return new Promise((resolve, reject) => { - const args = [CHILD_PATH, mode, JSON.stringify({ ...params, dataDir })]; - const trySpawn = (cmd, env) => { - const child = spawn(cmd, args, { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, env }); - children.add(child); - let out = ''; - let errBuf = ''; - let settled = false; - const finish = (fn, value) => { - if (settled) return; - settled = true; - clearTimeout(timer); - children.delete(child); - fn(value); - }; - const timer = setTimeout(() => { - child.kill('SIGKILL'); - finish(reject, new Error('query timed out')); - }, 30000); - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (c) => { - if (out.length < 16 * 1024 * 1024) out += c; - }); - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (c) => { - if (errBuf.length < 4096) errBuf += c; - }); - child.on('error', (e) => { - if (settled) return; - if (e && e.code === 'ENOENT' && cmd === 'node') { - // No system node on PATH: retry the runtime's own executable as plain Node. - children.delete(child); - clearTimeout(timer); - settled = true; - trySpawn(process.execPath, { ...process.env, ELECTRON_RUN_AS_NODE: '1' }); - return; - } - finish(reject, e); - }); - child.on('close', (code) => { - let body; - try { - body = JSON.parse(out); - } catch { - finish(reject, new Error(`query helper failed (exit ${code}): ${errBuf.slice(0, 300) || 'no output'}`)); - return; - } - if (code !== 0) { - const err = new Error(body.error || `query helper exit ${code}`); - err.code = body.code || null; - finish(reject, err); - return; - } - finish(resolve, body); - }); - }; - trySpawn('node', process.env); - }); - } - - async function runQuery(mode, params) { - if (childMode !== true) { - try { - const result = MODES[mode](params); - childMode = false; - return result; - } catch (err) { - if (!isSqliteUnavailable(err)) throw err; - childMode = true; - context.logger.warn('token_meter_board.sqlite_fallback', { reason: err.message }); - } - } - return runChild(mode, params); - } - - function health() { - const dbFile = path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); - const dbExists = fs.existsSync(dbFile); - let sqliteInProcess = false; - let usageRows = null; - if (dbExists) { - const { db } = openDb(dataDir); - if (db) { - sqliteInProcess = true; - try { - usageRows = db.prepare('SELECT COUNT(*) c FROM local_runtime_token_usage').get().c; - } catch { - usageRows = null; - } - db.close(); - } - } - const store = factsStore(dataDir); - return { - ok: true, - now: Date.now(), - runtime: { - node: process.version, - sqliteInProcess, - queryMode: childMode === true ? 'child' : 'in-process', - }, - dataDir, - dbExists, - usageRows, - facts: factsStats(store), - }; - } - const clientEntry = await fs.promises.readFile( path.join(context.pluginRoot, 'miniapp', 'client', 'index.html'), ); @@ -184,34 +107,14 @@ export async function start(context) { path.join(context.pluginRoot, 'miniapp', 'client', 'vendor', 'chart.umd.min.js'), ); - const API_ROUTES = { - '/api/window': 'window', - '/api/trend': 'trend', - '/api/summary': 'summary', - '/api/sessions': 'sessions', - '/api/daily': 'daily', - '/api/calls': 'calls', - '/api/turns': 'turns', - }; - - // Query parameters are an ALLOW-LIST, not a pass-through. Anything the page - // does not send is dropped here, so a crafted query string can never reach - // the query layer with a key it does not expect — most importantly it can - // never carry a `dataDir` (the database location) or any other internal - // option into the query functions. - const API_PARAMS = { - window: ['startAt', 'endAt', 'days', 'bucket', 'fillEmpty'], - trend: ['startAt', 'endAt', 'days', 'bucket', 'fillEmpty'], - summary: ['startAt', 'endAt', 'days'], - sessions: ['startAt', 'endAt', 'days', 'limit'], - daily: ['days'], - calls: ['startAt', 'endAt', 'days', 'limit'], - turns: ['startAt', 'endAt', 'days', 'limit'], - }; - const server = http.createServer((request, response) => { void (async () => { try { + if (!isLoopbackRequest(request, context.listen.port)) { + response.writeHead(403, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: 'forbidden' })); + return; + } const url = new URL(request.url ?? '/', 'http://miniapp.local'); if (request.method !== 'GET') { response.writeHead(405, { 'content-type': 'application/json; charset=utf-8' }); @@ -231,39 +134,51 @@ export async function start(context) { response.end(chartJs); return; } + + const now = Date.now(); if (url.pathname === '/api/health') { + const body = await queryHealth(context, now); response.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); - response.end(JSON.stringify(health())); + response.end(JSON.stringify(body)); return; } - const mode = API_ROUTES[url.pathname]; - if (mode) { - const allowed = API_PARAMS[mode] || []; - const params = {}; - for (const key of allowed) { - if (!url.searchParams.has(key)) continue; - params[key] = url.searchParams.get(key); - } - if (params.fillEmpty != null) params.fillEmpty = params.fillEmpty !== 'false'; - try { - const result = await runQuery(mode, params); - response.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); - response.end(JSON.stringify(result)); - } catch (err) { - const status = err && err.code === 'NO_DB' ? 503 : 400; - response.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); - response.end(JSON.stringify({ error: String(err?.message || err) })); - } + + /** @type {Record Promise>} */ + const handlers = { + window: (args) => queryWindow(context, args, now), + trend: async (args) => (await queryWindow(context, args, now)).trend, + summary: async (args) => (await queryWindow(context, args, now)).summary, + models: (args) => queryModels(context, args, now), + sessions: (args) => querySessions(context, args, now), + daily: (args) => queryDaily(context, args, now), + turns: (args) => queryTurns(context, args, now), + calls: (args) => queryCalls(context, args, now), + }; + const handler = handlers[url.pathname.replace(/^\/api\//, '')]; + if (!handler) { + response.writeHead(404, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: 'not_found' })); return; } - response.writeHead(404, { 'content-type': 'application/json; charset=utf-8' }); - response.end(JSON.stringify({ error: 'not_found' })); + + const allowed = API_PARAMS[url.pathname.replace(/^\/api\//, '')] ?? []; + /** @type {Record} */ + const params = {}; + for (const key of allowed) { + if (!url.searchParams.has(key)) continue; + params[key] = url.searchParams.get(key) ?? ''; + } + const body = await handler(params); + response.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }); + response.end(JSON.stringify(body)); } catch (err) { - try { - response.writeHead(500, { 'content-type': 'application/json; charset=utf-8' }); - response.end(JSON.stringify({ error: String(err?.message || err) })); - } catch { - // socket already gone + const message = String(err?.message || err); + context.logger.warn('token_meter_board.request_error', { reason: message.slice(0, 120) }); + if (!response.headersSent) { + response.writeHead(400, { 'content-type': 'application/json; charset=utf-8' }); + response.end(JSON.stringify({ error: redactPaths(message) })); + } else { + response.end(); } } })(); @@ -274,7 +189,7 @@ export async function start(context) { server.once('error', onError); server.listen(context.listen.port, context.listen.host, () => { server.off('error', onError); - resolve(); + resolve(undefined); }); }); context.logger.info('token_meter_board.listening'); @@ -284,17 +199,17 @@ export async function start(context) { if (disposed) return; disposed = true; context.signal.removeEventListener('abort', onAbort); - for (const child of children) { - try { - child.kill('SIGKILL'); - } catch { - // already gone - } + // Persist the scan cursor so the next start resumes instead of re-reading + // every transcript. + try { + await ensureScanned(context, Date.now()); + await saveStore(true); + } catch { + // the cursor is a cache; losing it only costs a full rescan } - children.clear(); - // drop keep-alive client connections so close() settles promptly + resetStore(); server.closeIdleConnections?.(); - await new Promise((resolve) => server.close(() => resolve())); + await new Promise((resolve) => server.close(() => resolve(undefined))); }; const onAbort = () => { void dispose();
//messages.jsonl +``` + +transcript 的每一行是一条消息。assistant 消息带着 runtime 为这次调用记下的 token 数: + +```json +{ "role": "assistant", "model": "MiniMax-M3.1-Flash", "timestamp": 1792769579471, + "stopReason": "toolUse", + "usage": { "input": 1204, "output": 331, "cacheRead": 61044, "cacheWrite": 0, "totalTokens": 62579 } } +``` + +这就够算出这个看板展示的一切:token 用量、模型分布、按天趋势、逐次调用明细、对话归组与对话状态。 + +而 transcript **不含**两样东西,所以这个看板也**不展示**两样东西: + +- **没有耗时。** transcript 里没有 decode 耗时、也没有请求耗时,因此算不出 token 速率。本版本不再提供输出速率,页面会直接说明,而不是留一列空值。 +- **没有路径。** transcript 里没有工作区目录,所以会话排行里没有任何绝对路径。 -## 与另外两款 token 看板的差别 +另外两样即使数据里有、看板也**故意不展示**: -官方 Mini App 目录里已经收录了两款 token 看板,各有所长,解决的也略有不同: +- **不展示消息正文。** 对话明细用所属会话来标识一轮,而不是你的原话。每轮用户消息前 200 字的预览已经移除。 +- **不展示模型显示名。** transcript 只记录原始模型 id,所以表里写的是 `MiniMax-M3.1-Flash`,而不是去客户端配置文件里查出来的名字。 -| | Token 仪表盘(本款) | `mcode-token-usage-board` | `mcode-usage-monitor` | +## 覆盖率:transcript 并没有留下全部 + +会话记录不是客户端全部动作的完整账本。长对话被压缩(compaction)时,runtime 会把被压缩的那一段 transcript 换成一段摘要,那一段里的调用就**不在任何** `messages.jsonl` 里了。 + +在开发用的参考机器上(2026-10-23 实测),看板数到 **151 个会话、8,640 次调用**,覆盖 2026-06-17 至今;而客户端自己的内部账本——也就是这个看板**不去读**的那份——在它自己保留的窗口(2026-09-28 至今)里有 **13,124** 次调用。 + +把两边限制在**同一个窗口**(2026-09-28 至今)里比: + +| | 会话记录 | 内部账本 | 覆盖率 | | --- | --- | --- | --- | -| 数据来源 | 运行时用量表 + 观测日志 | 会话记录文件(`messages.jsonl`) | 运行时数据库,经 Python 3.8+ 读取 | -| 逐次调用计时 | 有 —— 每次调用的 decode、请求全程、状态码 | 无 —— 会话文件里没有计时 | 部分有 —— 每次请求的速度 | -| 逐次调用台账 | 有,12 列 | 无 | 只有近期请求列表 | -| 带用户原文的对话(turn)明细 | 有 | 无 | 无 | -| 需要 Python | 否 | 否 | 是 | -| 每次查询另起进程 | 否 | 否 | 是 | -| 自动刷新 | 5 秒 | 60 秒 | 5 秒 / 10 秒 / 30 秒 | -| 布局 | 固定、信息密集 | 固定 | 可拖拽重排的卡片布局 | +| 调用次数 | 8,422 | 13,124 | **64.2%** | +| token 总量 | 1,133,235,393 | 2,099,198,213 | **54.0%** | -实际差别在于:如果你想知道**某一次具体对话的 token 花在哪**,或者要**核对某一次具体调用**(它的 decode 时长、请求全程、HTTP 状态码),只有本款看板能给——而且不必再去从会话文件里反推。若你更看重自由重排的卡片布局,那 `mcode-usage-monitor` 更合适。 +差的就是被压缩掉的那些调用,不是统计口径错了。反过来也有:账本最早的一行是 2026-09-28,比会话记录晚三个多月——**它自己已经过了保留期**,那段时间的 220 次调用只剩会话记录还留着。 + +所以:**这些数字是"你的会话记录里还留着多少",不是账单。** 计费与配额仍以客户端自己的"用量"页面为准,那是服务端算的。 + +## 为什么是这块看板 + +- **只读你自己的会话记录。** 不碰内部数据库、不扫观测日志、不读客户端配置。和官方画廊的 `mcode-token-usage-board` 同一个数据源,多两样东西:**逐次调用台账**,以及**带实时状态的对话(turn)表**。 +- **增量读取,而不是每次重读。** 参考机器上全部 transcript 约 **344 MiB** JSON。读取器为每个文件记住字节游标,只解析上次之后新追加的内容:一次全量扫描约 **2.0 秒**,而之后的每次刷新只要 **170 毫秒**左右。游标存在插件自己的数据目录里,所以连 Mini App 冷启动都是接着上次继续,而不是从头再读一遍。 +- **不需要 Python,不拉子进程,没有额外依赖。** 纯 Node,除了一份内置的 Chart.js 副本外没有第三方运行时代码。上一版为了 `node:sqlite` 准备的子进程回退,随着数据库一起没了。 +- **完全本机。** Mini App 在 `127.0.0.1` 上只提供自己那一页和它自己的 API 路由,不访问任何远端主机,除了自己的源之外不发任何请求。 ## 安装 -把整个目录复制到 MiniMax Code 数据目录下。默认 `` 是用户主目录下的 `.minimax`(即 `~/.minimax`),默认路径为: +把整个目录复制进 MiniMax Code 数据目录。默认 `` 是用户主目录下的 `.minimax`(`~/.minimax`),默认路径是: ```text /plugins/token-meter-board/ @@ -59,105 +81,102 @@ | 系统 | 目标路径 | | --- | --- | -| Windows | `C:\Users\<用户名>\.minimax\plugins\token-meter-board` | -| macOS | `/Users/<用户名>/.minimax/plugins/token-meter-board` | -| Linux | `/home/<用户名>/.minimax/plugins/token-meter-board` | +| Windows | `C:\Users\<你>\.minimax\plugins\token-meter-board` | +| macOS | `/Users/<你>/.minimax/plugins/token-meter-board` | +| Linux | `/home/<你>/.minimax/plugins/token-meter-board` | -复制时不要漏掉隐藏的 `.minimax-plugin` 目录 —— 插件靠它被识别。若设置了自定义数据目录(`MINIMAX_DATA_DIR`),请放进该目录的 `plugins/` 下。 +务必带上隐藏的 `.minimax-plugin` 目录——插件靠它被识别。如果你设过自定义数据目录(`MINIMAX_DATA_DIR`),请放到那个目录下的 `plugins/` 里。 -装完重启 MiniMax Code,确认插件已启用,然后打开 **Token 仪表盘**,或在对话里让 Agent 打开。 +重启 MiniMax Code,确认插件已启用,然后打开 **Token 仪表盘**,或者直接让 Agent 帮你打开。 ## 使用 -选一个时间窗口(预设或自定义),然后看趋势图、KPI 与下方五张表。模型 chips 可同时筛选图表与表格;会话排行与每日统计各自带独立的时间范围选择器,改主窗口不会牵连它们。页面每 5 秒自动刷新,也可手动点「刷新」。 +选一个窗口(预设或自定义),然后看趋势、KPI 条和下面五张表。模型筛选条同时作用于图表和表格;会话排行与每日统计各有自己独立的范围选择器,改主窗口不会影响它们。页面每 5 秒刷新一次,刷新按钮可立即重载。 -示例提问与对应结果: +几个示例提问与对应结果: -- **「打开 Token 仪表盘」** → 直接打开当前窗口的看板。 -- **「查看我的模型用量趋势」** → 按模型堆叠的趋势图,含缓存命中率曲线与输出速率曲线。 -- **「哪个自定义模型的缓存命中率最高?」** → 模型明细表,逐 provider / 模型给出缓存命中率。 +- **"打开 Token 仪表盘"** → 在当前窗口打开看板。 +- **"查看我的模型用量趋势"** → 按模型堆叠的趋势图与缓存命中率曲线。 +- **"哪个模型消耗最多?"** → 模型明细表,含每个模型的调用数、token 与缓存命中率。 -看板还带一个 **「让 Agent 分析此窗口」** 按钮:把当前窗口的总量、调用次数、缓存命中率与输出速率填进聊天输入框,你可以对着刚看过的同一份数字继续追问。 +看板还提供 **让 Agent 分析此窗口**:把当前窗口的总量、调用次数、缓存命中率与对话数追加到聊天输入框,方便你对着刚看到的同一组数字继续追问。 ## 数据与访问 -**读取的文件(只读,绝不修改):** +**读取的文件(只读,从不修改):** | 路径 | 用途 | | --- | --- | -| `/v2/sqlite/runtime-state.sqlite` | 逐次调用用量台账,以及 assistant / user 消息行(decode 计时、结束原因、消息原文)。用 `node:sqlite` 以只读模式打开。 | -| `/v2/observability/logs/runtime-*.log` | provider、模型与响应状态,按 turn 关联。用量表本身不存模型名,日志正是自定义(BYOK)provider 能显示成自己的名字而不是 "unknown" 的原因。 | -| `/config.yaml` | provider 与模型的显示名,让表格显示 "MiniMax-M3.1-Flash" 而不是内部 id。 | +| `/v2/sessions/**/messages.jsonl` | 每个会话的 transcript:每次模型调用的 token 数、模型 id、时间戳、turn id、结束方式。 | +| `/v2/sessions/**/manifest.json` | 会话目录对应的 session id。 | + +**别的什么都不读。** runtime 的内部数据库(`v2/sqlite/runtime-state.sqlite`)、观测日志(`v2/observability/logs/`)、配置文件(`config.yaml`)**都不会被打开**,任何模式都不会。 -路径由 Host 注入的 `context.dataDir`(当前 MiniMax Code 数据目录)解析,缺失时回退到 `~/.minimax`。**这些路径和运行时数据库的表结构都不是公开 API**,属于客户端内部存储,未来版本可能变化。真发生变化时看板会给出明确报错,而不是给你一张空表。 +路径从宿主注入的 `context.dataDir`(当前生效的 MiniMax Code 数据目录)解析,找不到时回落到 `~/.minimax`。**transcript 的目录结构不是公开 API**——它是客户端自己的存储,未来的客户端版本可能改变它。真变了的时候,看板会明确报错,而不是给你一块空白的看板。 -**页面上会显示什么。** 看板渲染的是本机真实数据,所以一张截图里可能包含: +**页面上会显示什么。** 看板渲染的是本机真实数据,所以截图里可能出现: -- **你自己提问的原文** —— 对话明细会显示每一轮用户消息的**前 200 字**。原文不会被完整读取:截断发生在数据库查询内部,原文既不进入应用内存,也不会传到浏览器。 -- **会话标题与会话 id**,以及每个会话的**工作区绝对路径**(显示在会话排行的悬浮提示里)。 -- **模型与 provider 名称**,包含你自己接入的自定义(BYOK)provider 名称。 +- **会话标题** —— 该会话里你第一条消息的前 80 个字符,注入的 system reminder 会被去掉。这条规则与官方画廊的 token 用量看板一致。消息正文不会被加载,也不展示任何逐轮预览。 +- **会话 id 与模型 id。** -这些内容都留在本机与这个页面上。若打算分享截图,请记得里面也有你自己的提问和本机目录名。 +数据全部留在本机与页面上。如果打算分享截图,请记得里面会有你自己的第一条提问和模型列表。 -**不写任何东西。** 不创建也不修改文件,数据不出本机,无遥测。缓存只存在于 Mini App 进程的内存里。浏览器 `localStorage` 里只存一样东西:主题选择,键名 `tmb-theme`。此外不落任何数据。 +**会写入什么。** 只有一个文件:扫描游标 `<插件数据目录>/session-scan-state.json`,在 transcript 发生变化时原子写入(先写临时文件再改名)。里面是文件路径、会话 id、会话标题与逐次调用的计数,好让下次启动接着走而不是从头再读一遍。它只是缓存:删掉它最多多花一次全量扫描。页面在你的浏览器 `localStorage` 里只存一样东西:主题选择,键名 `tmb-theme`。 -**网络:** 无。Mini App 只在 `127.0.0.1` 上提供一个页面并响应自己的 API 路由,从不访问任何远端主机,除自身源外不发起任何请求。API 接受的查询参数是**逐端点白名单**:其余参数(含任何试图指定数据目录的参数)在进入查询前就会被丢弃。 +**网络:** 无。Mini App 只在 `127.0.0.1` 上提供自己那一页和自己的 API 路由,不访问任何远端主机,除了自己的源之外不发任何请求。它接受的查询参数是逐端点显式白名单——其他任何东西(包括任何看起来像数据目录覆盖的参数)在进入查询层之前就被丢弃。`Host` 头不指向回环地址、或 `Origin` 头不指向本监听端口的请求,一律以 403 拒绝。 -**子进程:** 通常没有。若宿主 Node 运行时没有暴露 `node:sqlite`,Mini App 会用子进程重跑完全相同的只读查询:先尝试 `PATH` 上的 `node`,只有该可执行文件不存在时才回退到用 `ELECTRON_RUN_AS_NODE=1` 拉起自身可执行文件。查询模式与参数以 argv 数组传入,**绝不经过 shell**;子进程向 stdout 输出一个 JSON 文档后退出。 +**子进程:** 无。不派生任何进程,也不使用 shell。 -**Node.js:** 进程内路径需要 `node:sqlite`(Node.js 23.4 起不再需要 flag)。测试时随附的运行时是 Node.js v24.18.0。若进程内运行时与子进程都没有它,看板会明确报出这个要求,而不是静默失败。 +**Node.js:** 任何自带 `node:fs/promises` 与 `node:http` 的 Node.js 即可——不需要实验特性开关,也不需要原生模块。测试时使用的内置运行时是 Node.js v24.18.0。 ## 指标口径 | 指标 | 定义 | | --- | --- | -| 总 tokens | `输入 + 输出 + 推理 + 缓存读 + 缓存写` | -| 缓存命中率 | `缓存读 ÷ (缓存读 + 输入)`,即提示词中命中缓存的比例;缓存写不计入分母。 | -| 输出速率 | `Σ输出 tokens ÷ Σdecode 时长`,按耗时加权。单次调用为 `输出 tokens ÷ decode 时长`(首 token → 流结束),并附 P50 / P90。 | -| 请求全程速率 | `输出 tokens ÷ request_duration_ms`(发起请求 → 流结束)。与输出速率的差值即首字等待与排队。 | -| 对话明细(turn) | 一条用户消息 + 模型为给出回答所需的若干次调用。时长为挂钟跨度,仅作展示,不参与速率计算。 | +| 总 tokens | `输入 + 输出 + 缓存读 + 缓存写`——transcript 记录的四类。transcript 里没有"推理"这一类,因此不在求和内。 | +| 缓存命中率 | `缓存读 / (缓存读 + 输入)`——提示词里命中缓存的比例。缓存写不进分母。 | +| 对话(turn) | 一条用户消息,加上 Agent 在回答它之前所做的若干次模型调用。 | +| 对话状态 | 取该轮最后一次模型调用的结束方式:`stop` → 已完成,`toolUse` → 未收尾,`aborted` → 已中止,还没有模型调用 → 进行中。 | +| 调用次数 | 带 usage 块的 assistant 消息条数。已被压缩出 transcript 的调用看不到。 | -decode 时长超过请求时长的调用不计入速率聚合(这种组合等价于首 token 早于请求发起,属于时间戳异常,留着会灌大分母),但仍会逐条列在台账里。进行中的 turn 标记为「未收尾」,速率按已到达的部分计算。 +会话被重建时,同一条消息可能出现在多个 transcript 里,所以调用按 message id 全局去重。 -客户端界面显示的是它自己那一段实时会话上的数字;看板用同一套公式算你选定的窗口,所以两边窗口不一致时会有千分之几的差异(参考机器实测 0.3%~3.0%)。 +客户端界面显示的是它自己当前会话的数字。看板用的是你所选窗口内的 transcript 记录,两者可能不一致:界面统计的是 runtime 记下的全部调用,看板统计的是 transcript 里仍然留着的那些。 -## 已验证环境 +## 测试环境 -- MiniMax Code 桌面端 **3.1.4**(build 186),Windows 11(10.0.22631,x64) -- 随附 Node.js **v24.18.0**,`node:sqlite` 可用 -- 已在桌面端验证:插件安装、窗口切换、自定义起止时间、逐次调用台账、对话明细实时增长、自动刷新、明暗双主题,以及运行时数据库缺失时的报错路径。 -- macOS 与 Linux **未验证**。代码里没有平台相关逻辑(数据路径由 `context.dataDir` 解析),但请把其他平台视为未测。 +- MiniMax Code Desktop **3.1.4**(build 186)、Windows 11(10.0.22631,x64) +- 内置 Node.js **v24.18.0** +- 已在桌面客户端中验证:插件安装、窗口切换、自定义起止窗口、逐次调用台账、对话实时增长、自动刷新、明暗主题,以及找不到会话记录时的报错路径。 +- macOS 与 Linux **未**验证。代码中没有平台相关逻辑——数据路径由 `context.dataDir` 解析——但仍请把其他平台当作未测。 -本版的完整验收记录——包检查结果、逐次配对的回归数字、注入复测,以及同机性能 A/B——见 [`docs/validation.md`](docs/validation.md)。 +本版本的完整验证记录——包校验器结果、与内部账本的覆盖率测量、同机性能测量——见 [`docs/validation.md`](docs/validation.md)。 ## 局限 -- 这是**本地观测工具,不是账单**。计费与额度以产品内「用量」页为准,那个数字来自服务端统计,可能存在延迟。 -- 这里只覆盖客户端在本机记录到的用量。在别的机器上、或客户端从未在本机运行过的用量,这里看不到。 -- 运行时数据库与观测日志的格式是客户端内部实现,可能随时变化。 -- 客户端会往会话文件里写每条 assistant 消息的汇总用量,但逐次用量表才是这里的权威来源。若运行时某次调用没写用量行,那次调用就无法呈现。 +- 这是**本机观察工具**,不是账单。计费与配额以产品自己的"用量"页面为准,那是服务端计算的,可能滞后。 +- 数字只覆盖你的会话记录里仍然留存的内容。被压缩掉的调用、以及别的机器上的用量,在这里都看不到。 +- transcript 格式是客户端内部实现,可能随时改变。结构一变,看板会如实报告,而不是显示一堆 0。 +- 没有 token 速率,也没有工作区路径,原因如上。 ## 第三方组件 -- [Chart.js](https://www.chartjs.org/) v4.4.3 —— 本地化打包在 `miniapp/client/vendor/chart.umd.min.js` 以便离线使用。MIT 许可证,© Chart.js Contributors。许可证全文随包附带在 `miniapp/client/vendor/LICENSE-chartjs.txt`。 +- [Chart.js](https://www.chartjs.org/) v4.4.3 —— 以离线副本形式内置于 `miniapp/client/vendor/chart.umd.min.js`。MIT 许可,© Chart.js Contributors。完整许可文本随包提供,见 `miniapp/client/vendor/LICENSE-chartjs.txt`。 ## 源码结构 ```text miniapp/ - client/index.html 整个页面:结构、样式与前端脚本 - client/vendor/ 本地打包的 Chart.js(MIT) - client/vendor/LICENSE-chartjs.txt 本地这份 Chart.js 的 MIT 许可证全文 - node/server.mjs HTTP 服务、路由与子进程回退 - node/lib/common.mjs 数据目录解析、config 目录、日志增强、指标计算 - node/lib/facts.mjs 增量消息事实缓存(SQL 侧 JSON 提取) - node/lib/queries.mjs 窗口、汇总、会话、每日、调用与 turn 查询 - node/lib/trend.mjs 窗口解析与分桶 - node/lib/db-child.mjs 子进程回退用的查询执行器 + client/index.html 整个页面:结构、样式与前端脚本 + client/vendor/ 内置的 Chart.js(MIT),供离线使用 + client/vendor/LICENSE-chartjs.txt 内置 Chart.js 副本的完整 MIT 许可文本 + node/server.mjs HTTP 服务、路由、回环地址校验 + node/lib/sessions.mjs transcript 读取器:增量解析、去重、聚合 + node/lib/queries.mjs 窗口、趋势、总览、会话、每日、调用与对话查询 ``` -无需构建:页面与 Node 服务直接使用。 +不需要任何构建步骤:页面与 Node 服务直接使用。 -## 许可证 +## 许可 -[Apache-2.0](LICENSE) —— 全文见文件。本地打包的 Chart.js 保留其自身的 MIT 许可证,全文见 `miniapp/client/vendor/LICENSE-chartjs.txt`。 +[Apache-2.0](LICENSE)——完整文本见该文件。内置的 Chart.js 副本保留其自己的 MIT 许可,文本见 `miniapp/client/vendor/LICENSE-chartjs.txt`。 diff --git a/plugins/hanewari/token-meter-board/docs/preview.png b/plugins/hanewari/token-meter-board/docs/preview.png index 427102002aa7e129040fb73f31319c9df877cbcc..b08540907c5e3f342bb9a87c892cf9911a63bd99 100644 GIT binary patch literal 107513 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 z z;N07`r;8|=jid20S>vW*o3+$S%=%Yp8o(QUxZ|)zK}E^6nYwPC^R=4N3*;HJ`kKZ; z+iIXdP0SJf9A6YeNn1$B|A@*8vS^%FKprVx`O$xd4h!KH!Eo}Y8@a$;k&;76bD+@4c(aO$t9v~Ipbkp^ z_|~r!Gs=p69^gIr1`-Nh#$>088*(jXHD%7!#h@f*?SzFokzuBIZzO|Kvivg;4#T%= z^Do~E7Wj0$+jE2GIFmmK8iZ^^EgLkMD@kY?yO&4akS?#?YHOyjmPB&Z0Xo}^1DRj+ zxKU;5n`uci%td$Izq3liJaR2JS26u$lochEJ=Dtszl(hO@EaT9)Od6?PfgfwpXL+L zx&q*C;69zwvT@2R%soh7!5^t^lY}D&^)I z$r*ocV~D&$$4F9HIn~vgqDzu5pvl{Loq!Fl$uIG^py1RRF0*!wr+nt`N7F(gr$vB? zt@p0)wv1J=piYpIokf9cA#)EsZgG0TAS7^?kgxeYiPDkeUcI{VVCfZXVe=`mn0Np_ zv#+|}L+snsYtY8ka~Cid{ucVxC#+X;S@WS@s$D!#i>cE1TfLDf!Io{Jk#tQ;Wuh8M zvHoZC*?4Is<6h-q=L*nN*9Le~;aq~Teax=UN`R_!i!BY``CFTiN@<}w*rCILs5PB{ z6J^8Sc#{G{tft|>wqHVr2|1b_1Bw1%-}ZKw)`At&bUBtv2t#wf+=MzEpxsd`{`LoZ zdE97I?w|s*!+7K1(5IPA=#|$YU0)yk6cqj?_s+~FjoD8ia4KcD{^xLhsrN>OhdfTb z4$8QwZ%+i;#M~rpUU)b1dh?na-_1m>efJXX_LhXE;PDh5D*doZQt^S3$g0!|eawRS zgu3rEmU&~rN|~mC3R@uE)Fbk(3XR_-!nTmdA5#Qkog5{!*%I$>4h+d(zi~9uiOxVx zQ9vH&NWRDf3}XNZ0kE|yXTi35EnWntE9TM>QDtA*pyKSBDQMc)UcZJ_;-PMk(jk2G zWt@-RRQyW&w={PVs-)bT;fSr?-Tp?&rNY6hnwHs zL7z-DE8kF(8zjRF?W#We%K{Y5$>XPaN9mN2?)JcmDwxlSU>h|i_6qWdAdA_3zH%|g zblUtu;wdg_iAa+ zLP0{lG(%wbm=rBBv3|P`q$0}w@y+30_jlO7h`H}z`ad&5@T7&H_VCwz~y}*9_2gxpA zN#EK5{Ag<6lEp4)*jb!2VwUi;mA*ARH(3>A$}o;Ry2|cM1Ye!0Z7qZ1~&Z zz|0Z;zZe{m!hfiz-?SKP_6KOgfC-8qVDMVC-W`ewSl~4Fw;c|BhJU@+Z?KT{QM?nt zs0MK3Xd1@HuhvY7k&__LN*a zU)<2BH}G}vU?2jI2UvoPRpF1}hWzz6_55u(iG+-7x7iOWDWMJ(@Lt~eu)DjPjvM68 zaQ7zg3GdZ58Vu~s=ntc{&Oioxs01mgupB7Bi4|~d+10u8+<~P3ix2;d08hcog0TTO zkUqBiLSN{N!--yiqx0A~Ssa$<2?avsT5Et=d8N&rp zLwc^K<*WatPb*_G8{lzC!ns>qN##0BapYoTQ_TOwK2pN%>Q$p3BpRc%X0tvqM1OYS*Z1pBbx=|Gd znhK}l9{NO)Ra1B2nh0Y4rWv`VHI%z)jvD!=={^^eaP9S$no6R0Y^WXoO`RVp+;P%r zUIXy`#p>P83Dkwf>cpCRi+!7LyO>j6!gKS}^Hc&GuVUdJ8)!gJ09x>!1BzQ8l4h+A zHmVy{5;Zk@J;B#=$ftDedWX;iN0@<()y;~VZ>n451fgWixk5{)UKva`qV*loPtMz8 za4vv;{I1Q;dgSi^Web(}2OzB;LvUjD?XZlQM^cX5_Y9d=mbO0g0*<0cQO^UHc-e2# z^S>*fO^r>)15lSNDWb?Ju)UFvc<~x*m3fsFkN>wWv0_Gmn^HTd6vIghv@?s4H)Y zVK9zII}3?ds@YnSmL$1Di5EgU;LWbW9wV7@W|vLpvy9I3nPQ^3Icvz=q!MXfL4I;s z)A9QA0#73PN_(v^+B$(yQdPsOa)O!Vrv-IY3qDsU6InV$|3lW!zm=^B0ZwiR2tLgy z3%;wDcXCoSWaxFc(S>gAIoNELHw-gez=!UxQ#sXA-9nV%P-2>l@U^VI9)Pfc-C4FM z<kvznR%_IgJUcd7YZWHw+qhZoVDm}>i*mQjfOCfWD7!|mu`URBID)_j;m7IS zt|JpWY+}1A6L=_QQMRzCb)4FvRGy4$BgE#Cg`BExs#!rFxHXrK`p z`YY*ESySidv&VI|KV5lHQ|qClx;w@dAFdR2f2?37syyh$F*!^fh`F^Mou5{&d zYq#xDy>G(WeGCCu{dE)`I0kQTwwYtVCfyAJ+?Saq88(xyOIp9^bz6vhL)d)dCpc$*x2TN-UsOZ7%E}>ji;jv6Whl0 zqfk#rR~aFyXxgRL)dWsfeyWZdyIkrFJA?Fv&o)+lr_Hc+bZX@;u9LF$JVu)v=r#KbXQS$5klUS=ee{H!d#41y2U z@%2jx?^f!pc&TI(IpaB1U-~LH*2KgFKRLisp{|azdI8D^Ph|TrxlfzHn!Ap6r#Bi^;>p7xqm1yGc)HZyv--&w{-nF zF8-|uXnt09Jln>l+uK{2_UJWVB>J43oCo(-9)akn=5e@Yq$6l(=s1r>VSX~-^`uCJ zhnMjiZS#(YOkQYC+u3=3`<#r$Z>)wkGbuTFaA=5%nmSgOmX0nRC0s7Xn56~XNDqzz z46Mvro0}9g1ia=mZChKpwzjMovO^e|PKN%t_4V~W2Yv$NY|bzX0hM7b;FMiC7IR)m z%y||J9dLk-i7CfZ>Q*MohY%*yVBSlJ-^d53NUWvO8!%6*9(BR&X%A;-6%hoevIs(a z$PPm!75IG8!B+ z7RO|vaietKeCfMp=lrq&G>!r= X=QgZ0)HC5K7OR=*Dlpw`ki}xug8AAqU|<<8j8&0 zy_JaGp0`BXb=Sb`~OKY0<26MiJgJd>{n&FRA zxZ>^?Ul(rOTKZFH4!JG{^H6Ub|HTDp+4Q#^GmxJ<=?SVjV9P^d%`dq2R!~-(jeNIb zVb`-*7!CqCUL_Rii7q^Ct9F>&F5(QR;IN;)yR^1B*P==`bi2!b^ruS7L>;@Dylqubu=tI^08_CTx?{x4v9itogVTM-^;${TVG#5ug8WLao`#iqdPMMhMYd z>>YvdnFW)3qb5^>z#cgwc3?c>(dAC&ihS3yw`V$Kmmd2SQAFYIzOjH_Mg`k}sKMK}}=E-!m5(d^4lSR}cdlm`H#vddeC9jkK(uQJf|!ou z)No;6E5ubZ)|S6DmtHdO!|_txu-vC+HN9^*=>=jat;h5j~9-ogLcQ{cu1j|h}Yo#n{j5H7FALnx{K!kHm z7~Gayj)<+Rs`xkm$+!q#TdtfT;V)_M^WIW9EZQ;lV79M$9J+RHTB2C7hCeznDp|D= zG`;(fh={o8n&*qyqiQy<4u>RA<4|>f8-feQ_&VS%~?%rWEKIA$i|T% zhlC7E9B(M%x-(>((aM4*A<%8lza$aMB3=-mVsRLh?}l{kSMED*;OK@qUC_q45KG08 z>Om!q5zR8Oj(JhAu^6_F`Em=iwjKQZ?86gvr_Uec*y4sb)7su8b~e}5Jo>C-y=83~ z5utEi!qE}`A`@1FMS#A;HIGt0d#S&ybBk{x`DeodEll}&$J8LdN3M(OZ%+aDQC3zq z-o!RPq}{K~4k#LK#VqxY%Pr^M|1!0>cy!5EHRH>%vW#rpA8qZbZoy|+^PJ7GM>2n% zq`5<%==tf;40^bCSk-@59V@xMdAm;zaeCy(_fy=Fv^)V&f3URi7BW>%19A4ACP^Il!os=5*0U)=A0xI1!dvu7r5 zjhZjd+c&F~6tY@(vhgD*UWjpnE^7uRsEUO&Gc4C;)+<6-Y^g&v^FtUMOjZV$DCqJ} zIA&ABj{(%bPT|_l@2k#5oi?E%E1-ww#qU(mgBj0DwrXTSE+HbM#rwNC=WUgB#f91< zDuOA%W5jeWX*;pp!Liz zX&oa6ChDcA=~dsJ`ci@_=Q>)#)YW7?Czc> zU9@j5RFcEBNDpr=e%7*#g(N@f>b}wv-2LFP7n5u4W~i4Ms={kwi5O;YtPU}=@K|EM zzkWL$&(ZXpoonWd?`NnEfB8{1*hjLOWDbm6m`LNdrL2r}JFmqi+hs*$_a{3SdH!UH zpMm2W>25B~ZR_O0@p^btOO@)3d$Nhp-xtA91 z8){TRTz0}F!Va_Oh?K}LD=RgF#FjE!DUb>|#15%97(U7}VIdy~ErJYU1z#O=Mq!+n z<*T4Or*1YDmSj-jHFv}*{?tD1oSb|EtQcYWK^}is40JhtcXv)UwtM23t1M0z0~20V z8{eLV^2MiEndSM3`pVnv{%ZHR_rZ>#!?pya{EmMTzEQTAyRkepxnJUMY!XZxcnQ=dyZpt;V_t{UU>Z;0Qrzt2+H17Li z(j+OdP5a~&U*b$0KB6#E4z*uRD-M;}sN#uu>sGrytmWah;=rq&0RMkgC)JM@~y zw42|{+^eeWEM?aSZy++lWX5#33M7S0A0Q?-v>tv?;bJJpo$;b_k?GzmHVHACbvg=| zn-Rs#o-oWDokv&LSk#7J&I

lv^t=P$MNAC~IaSHtUW#bZAfV5e>nEnRZLmT04uy-(7euTlmls{M!4o(0(dg zMJ|um)m59BB#rIpdT|y`Nh=PceKyK@Qof0YSvE~UX@zh&vSyfZ-6xzC-=(#6HhLT( zYi+6HQ}xFA;gyAk@o=vbAq3aiOsWHw;l@BP)Iro0l zrsgs&S_bf)bcxFiQ$3#ozmA8X zP>76geSWl9&WEb=oDYA_%Wf2(}Us_ji@43IqNbCQ((a&-O`kkk0PE*t3{$+vfdJIbY z+}zxIHt#nOfl#Jtf`a7zFjy-gNXM`DO_sS!NJ@eRe=Fl#{*?5WhPg%^teNRtMo0`}~ zTmrrb^C0*UhU@ARBWDAXlYq+P%QZDvsPMx>L!qIen;RQISrptJt_g$?!U$2cQCKlv zaxnrgfCKVn@XcDUq3sJ8(ZGL^|b*b0C+W^RuI&Q$xG9iX6jvecLKIzm8py+=I)_-j7yqV5sUp>Fg z%8QJS)u={<$-bkrQSVt{`utnKlNFUtQ`}l$iT$8W?i3~n=6rg)3vd|HwmL!%OtNj z1M&8$q~zMq-#_HGr^gN0nAyJ`=?CmAhp!I9QIMTN(2-s$n}wtDF;kebR;$Aep||<8 zyHK%I!+j?mo4)H?M|bG;_BLwM<@CP6NUHlu+u{57zVu_q*Nsa@YikHPI8OK$dKoX& zkEa|zH=20jjYO(zkKr^XS{?BrAb9@#CcQ_NoyAdI9~1pnWjPj9Jl?vAi;iAW(9jVt zsL`wXcaI}K#FO@O;Qre;&j$xZto$m_*-nl@9;Gxfu_MOI3NgN_5xI#Yq)tvhh(52DDx^FcTf35jv`dSMG+oLF zX-MuRmz$m<9c1u9e~F%iKi4>=%MB$`8Q-1MW71S={lvvahKBN2%=2&7xUO%B-$9Xi zdyWd29qw7Uu4}Dd_TYMq&Rl0-PMn7&oCZHUyiK6zJYsV?Q*ZT9 z$Z1?+U8vyeiy}H$xS7)5YR4TjAta zY~XLS7=#5bFEQOugPDosg;nON^0jm~ObC3@2_GuE-Mf)mSB~u)gM&pw2#IJmipAuB zn*1KRE*?r9csEghL(B?nig}2>uPyFSDE_(;x4;Qf4%#jM*YroDDm!k#X}W1UU?8V-bg9fLh+SUP&;PK z5aGW0dfAHLZH$!E6BUK3UP^jhovpF)cnAb+6uh8-Utz%!?Q%b~ljuty_EaVA0gaFS zT78%zGa8f|Af{qQfOS9ZdSBU_5*3aU`wm><$qn*~vVj;D>f~beIW! z(ep*Lg$Sr#26!#EoA~l}VieRk0rAKa$@zB<2RG9f7n2`wAI@6tTUIaKpLz+{ zL`C`slVGrYJx5dN$V0$g5N?!nMXB0djR?b#sQW#QZUp=l3Ew3$WTAP5u}eSX7Saje3)!bN|saQzSpKqKgX-@O!0Mn_xKiSJU$o-B%1GR;ud} z*f4Q}o%f`T4Ou6ePx|&|fPKsLv1t;^Mdk185bT2TKOTP|vcZ9eZYezJOn;U)ZvgwewWy3QlET7s4R)BJWVjv=KfxXKu}GgW zBQ1gb)a$(-Jt~6EpxmEl-lbg+T^i_rCVXynp}Y>XKr2v~KU;ZHv>VV<1SzfP%lof1 z6b!7nAtlQwV=)r#QLOG>mxd)qU2j|^TP)?G7(Ly!dw&Km2`5x(|1+x{m+bhnd}Zjl zZG|4Lu$P=>@OddEn&yFd;dmG}>-q%BX~k(a1i}|UYEbSsvp3JzH1foIs`953f-QPY zSB+}9(`ND3+XuTMmr47C4Qy_Ak2yIOqIAnZs4$*}cQPhOGPDh!D9$OP(7K&EBvYn% z7y1L3=W$$2ud_wdSWiB$DKj!Mk}pk8O~Jy!QBbC;h1=lN&wS$#0!2TY|16|3sH$n!L4!z1|~!+#4? z>vx!sYPUR>Y9hU@*d)ui?9}k%=SYZpu*aE;vfgL(v&l59q}#%;fvqh+LIdU3?!v%H zti5RFw~%Xsp=b!%C|vU8$tftvza)K~82JKb<=W!<*m_>n?C!_0o#`h*IqN{X|+Z0(Y&P zE7p3|c9GVaXfQPS(IvClYK#!=DS0u z<9R2v_IgS#G|ElvoKQtxs)gt=0&Z(Yr+vbeS#c~Y^mCVm?n-t4-R^}4Yh?a<(G6EU z{gdRA?2!&^6xvn^%+SL_=52WhcBb~;X4t`=%=OhD@uiYmG=A)jgo*N3 z0uzhZ@jDw?uG^$8s@t5GvB42j++S(TG`STTLQ~7UwO8t|F?VY+5o>VAsPRzbX#E~y zu$0p3__l)vNd{6~0Gs65!C~v^PGP6>Bf#Rt=#*jzEwKzK8bA+^EeszYN%<7 zY7-8WPN;wKfZJM3zlPJUyHT}Ba;PuBwz{a;A^W_odCS#2G_}DjKb)DgsJg%D`%GX# zi!mrQS4aWnZV_j4t}YVnDv+yr+jVfCRtO{ifcw-~)SG8_w$jXc&uk!1Y|T-YbK-H= zsO;NT%WL9b!4^*o}m#rer(<>FLwtCXq`u6O89 zzXHu;M|Den{ha3mRiWpMW=p|&%ZCyL1>`}omE-2B^~GFcC-NYhBT9$oT~+Vr!;TQ_ zM3Boz3+%V;di^DoeJzEq=7y$61Et9HzE$vBPaHZiWBGHMuJo58#NqS>R*h9lS{GlXSh zoroyN-f3{&R?&T(gMZ)TOpbi_M)#o8V0~S-ZF=ChA%veVVDtXz4L%s&J6+`MZ3Z(r zU#Fimcjos)KfuP-hn{B>Z4`}{FtA5{r#)y+XzKo{v`2e6wnf?gFdM@FLk^~dFN;d8 zySZIBxizgyANft;&vzmqz6A5M<@+xN2{#o2q*WX5FjpLB9UlQs;NsE^ov{OeK~q!J zKRsIu_nTK&)BmEf?*Abr;tA4;seK8n>FdQP|0Bi{=vz!ayt{0H<6_4@7aDWx@Vnor zmNx$Y0C+<5sTm6(MclIMdZ;21#$r|e_Z%gI*}BuGhX=3PW#`9(xd}MVx}}@R|Aaj$ z8wW5G6C)!Tk$t5Yb@>V}++m&bWrbKwxGqFOaY2EAhUl0&CrC;vM@ag)AB2Wz6HYurdRv5oe0>pC8U8jc}@f$)S#L%yhYlA0wrh`He^yuZBj;;R68yFTg!9 zx`c|j=Dl=I)h>CB60G&g5za^tTp*kQK<;tVd2FZSIN`dzpdj-&nv!Pgcl}1&-LHXg zKpn0FNm8qpopvn2eXc?lB(qW4gp7$_Ngn$1o16G7TBENqNMwPO`U$=wdVn4W>__(d zoR<6?xjkr7kV_Bh8;gu#+gHj5uMI{(Ssep%#c_QK=q#GIpdQY$=~v*cAxN#Goc~Fl5+?P%S1<%mL7{{R*&v*8b<_< z!%!i^ad4#dP){GHNdXo3El$hK$;nJtB$HZby>ziD>i%4(;s-EmWd4}7hM}QL5fDiQ z1#Bg1yVB0gW5D~KWordcNERW@S5f7qc=HQ_?0ZrG+1of~%o>jVIS-XrP!P?mq)Q&` z?VS7OoMFciB5$SK0#CZ-QtbCtLvXHjRW zRsf0h*He&tY@N*gpnOSSM5hvhXII$9b&*6XT`a^|=>^PsBIEyD+?_aPW^`L1Ef9Uh$vDO0v2joMqDl8HK!kTK40|QY@vJjYlT?U^M_fEqgxSu{4v-^{;=P=4S;Q!G zzbCOl?8sl?iC0(SxH{i9piYxP&;5rO@6dUbQvc6uYyMZYIsd!=e-R33wKb7)%=Cq5j^)p2t9^=d8M%XicX6LSgS`|cctt5QngcY2!Qqt=;ZJL^VGX-?kOB`V`bz71+7j`9xRT=d(3lP zudiqn1N7%hYR%sj5BfH@y>*(|WtfOR9~LPke~JPM9U)*o@yu>4{Bpg4x=y}%8Gdt| z-zN`njtIai^+UNr4g)O-X0bj9$Rh1&2t$qtP@!G_Ca(Ar@%i|b; zBo${|Iy!h?$jjeB^9|Mc4Gjt!Y7G~225D|zX#UOpdaQQ`NYgV1Z4wdb&6Hld-K;`p zqi!*q)=6q$Zra1c&wtI}Y+czZL4$lQDo>;1-vWeD04F1GLjn+8hcj>RqC+IW`#Fw& zN|)pVvyL%9Rb|6JO{W?#Tb-AYp`H4tju|hA2&rM#Q5g?Cc zY~#pe+T$vm-5&iY6rBSg#BI^5fh7nab!b}ZeqfFvqsEC81c~s{Z};|E%1>c;s{*7s zB3mM(=8D>=EOsV}JA3WBO!`~T5R`b?o{{A`5An8M$34zX8ZHu-f%$fm zj;~N)5uXXKY#NtLrYDbQPpOdi=*dr0n_^=z&ovY1nV85!IS|16)5Ky*U7v1q8Q@gL zcR*RSO~!-NO0Ex z!4urw-Q5Z97J_sL)&vjk5TtRJ#v!;njWw>pr^xU9zIkWOH|x%wxochiVXf-wI$d?@ zJZC?9@8=vZAgH%Jx$jJQ#+l3G4&Ew=ryN}=GQM0yNOy=4lCq?klLY<6GpVCu8+S+O$lS-09A#qQjq7+u>@tVWI5Q29KKNZznSF5AcV)}+^5wSe=!gKvs~mzkpGANKelH@^9UQ}({pSt~ zXhCN5+rB4!dLZ(_(^+4xsAFNGA;WQwTL_+^F|XF=w!c3e7EO!Lt9lxE<@vCnTNG^+ zBS8AyW8~0aio@2z0y2e{9bM43N6pK_W3(@5T~JgMv!a+KL03#P4)V+SOiD$jn;I0< z0fjoG3*2O?(nuD?=2>T-&;C&zQwKB$!M4F^6ok}vJv~ltlBTkJ-R49Yvn@n}VLA2! zGz3$m@U<5&%crNxz!&&*adDDk^_oM&x>qh`WYc}je zChDd$SquJDPWRtn046;0zoFR1k9qQ0$5j$CaKxAuc*elr2W%in{vZ8+o%a%m%U@h} zKxFRmTSf6~yl;M_qCelncJ%(MFp|XyXlfk2Y*m5}4>wE*Wh;v(^|+1@d-|WvLAZqo zsTjNL{sR7hsPpItH`j4!R^)V^S_A=p8c_<;?RCxA;(Y&o*n>g&Q+up~$NHX+<|o*7 zevr&R{e~!hlmYAf-}5TtI&wBFW>fwsC(|b)N4{Z7-Xr8+KhOJiXhWD&%eR zU6%+UU_!$nj+?t&w~!b^nr~GPhew%cI4z`(2?;4in;(&xiLmMYyCf6)eol;{@SQdo z{Irn>;z!&CbZm~Gzu{6s+T5E=<;h$g(cn70x-g7Fm`;j-gFid<=uc_2N_!QKv-6h- zWUrdsoO6oaPtFUWI9EMvLu^p$m z=x+D5U-m`+N)!X1jVV8belSPfX<#l$=my>%-4q8*qB%7uG!OQM#=820^yf+UiNf^N z{?aX(cW`~R(TDN}%_p_bfQ!k@I`~W%PY5-XM4af-|3nd><7S+Z(SOiwrZ3i5PfM#Z zI0r_=_l~C&*;<~SC?DSfUCMMtbcpP82Wk2-wk%&5zpkCDD-A2rr+AY2G#1Fc5k2Y7 zFmMi30T4?4R5&M<=Rw!)Q_It_)ULp2ADUm>vg?)3rBCCqdyG@eL`Uxf7IoH*)>0px)xB_u!@VUHy}W! zrb4$m5PyCBN~7!y<5e;elAUBntmRQ83-gTlXA*_ul@(Vh5ekaA85%RQ;&>8_Z&7F( zYKumL6f7G|Pu{J_=7yFH1ar{C^oWz2^QkqSAbd~HF%r+>vqF2nw7IcSr+W|>Xmip~ zemF2T=9~nmauZubaaoPGQrX|SLNE!?(asn`0F3qh`R6^&o8GT-8VXV$V`HIEaoG9Z z-rm_+JSF@8px;~Oh#{b>s_hY`Nrri!DjyUwKN1z2LpnKW;)DpGT4m`(e^4#7RlHs= z*(Hj+K~}da@BVZ|DA)5hFs(Y}ti59y@k5YBCIb*nU0v7q2m0g8M`6wp3*XK+k=fT= zKIVw!;tPuvTKrD5K#eyba+>^;8!kX>qDO@l-u6o{u*`a;^$WeS zrV?BCDW4*t4r6&fa%F)*9@G!A>NV-_@_p*b`Q~Btss}KE0G@#a5~38CbNvaHMepDA zGOL9P6UBbU(Lhxv_V4{NZf0;|p`??Doy_Dqlj_Z_&8LB8i42?1uAzBeUs4}&heHyPj;^k`P~R76PE7Y(GTl?`l*+Y-{3N>4k)POqQ_p=aI98Ez|`?kd64h$Er-5LfJKXX=1YUQVXHHx zZ+DLgM*xlmQ<4laP%E9$Gfct6y9o#2H%#GO$bV7DVHoN=D&*p>mM-l{g*XdLgTS4> zjq*ks|MJ&?a5Oa3-8!pVrY!D$xIvUJu`IZCDyLlXJcv5~SvTVB^cS@V9hD?+I}hr%qi12E{-AAmK+WyAZ0A$SQBUy`9g9DvXcGNLf7jcxmK#q=o3?Y)Fjzkuq~8iH*WI(U z`ftq+#8m})CP=G$I!~#?Ze1_&6FwlYFWv6tUG>Eu{>s$4P&E4wE$V*u8$d&v%i7?(4TAt^u(hN_^%X=U8w}|^A;XB~ATKTza ziatypUJSZg+>P2yKia7R&OUwo@uGo60UdP3pz?uwaHMakre%BIMeytR^vLPn*d-yXKEFif6;2Q7a(^h-f4m-t)I}z4?!LsdN zXqH_x@sOdXe=*tap9!3Vkc0fR*@C(P{ccdrc<|L!m0NDIKa*v-vH z<5WOOQ~*XHRPSs>JpsLP!SnG%NsGrBzv|iRVT?jyV9P+ea|Emq|MXY5@mQLBIiowokw)61h3F*3|i_ ztO<<4jJxwTi6tq-6>1mbk9AJ#ckn619`8E8=EKg{3cZp4VcMzX5wl&KQ`OTWLi*F# zumt!tBedlw@&OB+oZPaYe@i1k?OjcH@CgXGo@_Mw2~8dWcT6Su-ox(ml>57%$}?ws zw}uOmrFwTD2Y%b8dw@bKp*m`6x+UTkj}oq%Ppk61$p*NKDdUGPuP*y+ zBDP=9ya)lNZa}~Fy_luh#FpX(sN+Wl`Ps9(SYt}#cm>$ta1JHOjACa`GHN&N8tv_p4z=xb)dIqhlcP{acs>_Hz@g z>?e;CH9$GDO0SGLSD6iPgy+IDreoLJqyx-5uaHcHIQ8*`jPk^QUidD()OvY*P!jKtd0u^D z_d|vBAr~d*vkbL89v!$9aQ&=9Any;H>tDVo>(imzmx-r!GI4S$9O0%8b-RjV2k0$j z^+a*9P>dc#z*ERG_LXse;Dj4U!mDqj){vgxDi@M*M1ep{uG5QvmDPNKcHB%}O4c0T z3PeAo0IIgEmX;BCK1zl$pt5qE29EGP9MmY3C>s1H44)u;Uqz{P$hbXA1)?_}3E@49 ze_=qVWQFd1!dmTB$E`-5sXKN7Z6b6jk4C-`|j`W>O-x?Y1`r`Cr}fd6$hWNcR1N&tKxz@~?QV zwxa72uSuaHucN*91`{~vB;S9aShieR)SVTP3tSG zay8R;={RK6C)9o}h@tdpsqFzsN%EM24@(gUl4%S*D@gu{-L;cPcxjyXa87b~& zTMdbcQF>+kvtuP!X8RR7hRibT;J4gcjAWISRh4>H-zDf0)|rz>wAJ%5=|l;{P!o2m zg;l56PYW1N3tDFh|5ic5E-;1 zE~MNL&C5&{pJ!T##wwnffCmswP(`*__Wpi#sc{1{GYFe@)CjkE6f?!R+P0gT%9;Wd zdi(?dCs!e0dIFp7M$$`l(!=EZiZ&PQTm5yJf>UpS-E26wGyt=e`g_*;L6B>_S}0=n zdX?5d5px~R7he}K&vA+tvvb0F+gYJEn&u>&q`yxa;+Hk)L=f}9-scrW zT}sj?fG$?Fi=KV6y}kWQ3qA1))cDej#0n$UQHfO58Q^z#SjpmX`K@NX0dD_f&O3zM7$%`AD|kO#izrNT*_HB&XN zpLzF@%J(hb6ba|3k8ty+wFdVk9`MTedXK+-3+FXMF;3R(h9iO&j`D_<_qr$5!WAze5fIBf}9*sCbS=H<@ug>#c=akAn3A?2}n zB2mfIQ2gU*eV_K9#5%U!H=ohB&b*PHEU-VU4#CHUj~x6i58&B!(*oHI@3;0~eg5-) z`xGo9&!2q~fB&a1p>L0oQ-CiqMcG8Tq4GM+A_sFTbh-H^NvIic@X7%5+={v;#ti*I;kf!{gxL7!`?eA@J+boaxVd=11waI-cvA^~nz#WH0y$M3s z-=4O`0<2J-n7J2AaXhISR88@x`o{>jNJLy1cgg@C%O6$io7>{TLtB;`ccIoYphaPz z#i_o2xzbN`_Q~<2ayXh_8FX?D4-YhX?B%%;G;wvf%vgJ4+rsDK23guM2(<+O@=Lfp&x0kcri@-`AeA%KS;KLco}yG?2Zv5Fg;41?VC z+tj^X_RH1U)(b$Ez@>BWZGMVC45a-Czux>%c{tggeAGIwE)VwV1=Ey+YvXb259=uo zFCX^UN6__xc8d8_wYN32%2KZoo(MU*Jd$7mmIu4LV+P)``npQHm)EMF^sN_7*w<4| z{qrWW=jll%m(cI7j6!qF>QBtQ##XF~JyS?hF7u7y@4p-U^Yd?qQu3Si*IoNLJ7J+2 z2eB$D*}o)DwPwfuSR1Kk8Zc*clR?!r&1F>Pwm!ob8pl5uHu^^?RmPP zfba|Lc}SbxxUc8QL4T@3xhxEpV^6VaYk0q};2Ws=TKh@Kui4D@wyt0o6%#;t7)3$~ zoEOh3@jvNL^uL|hJ=Mrp{SArJs^RGnS_y}r)UwFIo&Kc*G?ZC$2# z;oY2&@gJeuVO<}9{XihAdhD?AiL2J(VYw@bQyjHNgS{#FV*>+jkEnLVZN+LF`2Sz< z$v_B0Xd^dkbUs|#q;KWRH_w(PsJhD-(!XyLnkfE7S!O%w=q??7axV4|<-qes`aQ={Se~U-Il9AGqsVsgk(5igadpIa}-QowUop@{1xptdYn%i1cwRSs+ z?eko5Ca>}2;fUqNgP$=V;Sm#mtgJkh>2JAou<+uYyiM&N9%iOhDKs7Cj!#fgJh6Eg z2XUj*F+zoIhKbYge0a(LPq$z*`*~xl_M^ER2chIGfVdH2)h;d{C|M^sgi^BhC7}_p zG8=H4t37?FHjB!#|IXX8;$b4<%VKPG?G3;6vx27qIRCWmJZ+nHzgH)1go!nL^!wFQ~ zS~vkt(BL1x$?PyjG*^v4m1RJ{t;n@E=?7c`|5U!vw#a^T9(-6u=1vrL!@^{DX

)COp~XMdW|$7Z~sG`OZL~1c5Aj7Tl0)q?k95(G_tL^Zxb4nUDPG zN>E*xBNb2~04Qq3DP$IM+0Ic-4dyU>&vW#-nT5vM;_9Qmk;zKf!ufaUmmI!Z6P5MF zhiW^9yB#{#SDR0{mu@?OvtSNhj1H&F3GBML?!&q~rJGx2cMg}O6Dm7Z3y3_BSM)GM zpXo_y$w-hMU43yaeNV4mqX>_9nF)$gP3~wVYSDji0SBwA@2p6C0Q3N;vr>+p?be)Q-&Fy%s5RJza6_9N3XqLj*+nGGImlWem_)m_b<6e40*(<*1w$`gKiIYuFZ z{L%Kb6nynSGl93UXgp?AOEdNLz{2e%&p9ZWT^WFtgsutzzV()&eHBQ<02MhLQD$*K zRbT($+)J$?Gt`kviahQ)&8w-{lPE9L?00-;JD5ZzThKE49zzoj9HNxMw~&g_P1P4J z6ESHSNl6(_zn?AlWwWbM+u5#JDl)0=a)~Dr0CiA=$Yxy4423%8jk8aTk^wUe&gMVP zjaZH^acuU^KnzCs6@(ez0Ecty){k-U@Vt9t=;s$GI1}aX2Dbc7!W68bRHXIBp`s; zN6R93|0ft=(*_0@2#H9Y>N~8~$8tvmZ}#G53@Vs^-zETg@jo=Znhd$j#T9fgLuU`F zO#>~f86&|bTxft#-w56wg~&QJy3{!MSLfs~9+xi!fk3<%+^#0;cMQV(C2ct-Mc zVsddEBM!I`W0Hnais@Mc7em#zHu3M)b(uG)HzO*>G)H8BRG|97sDTd+zA7WTOy}m_ zsxoWftFyX;?mp*o;WG5Xjy+Tx=olDMl9QFu4O2OQdPM_YS2JsC<(;jB4L-pAGzA!$ zbVYA&S}W5fl`9#UnPU`M|E%2>sU-k*1m^?0*~%gKo$#9DG7T%{gc? z7C4kbCwKxvGmwE0PXd7E$LJd7c7QPaihwcsB|KfjhF z0qU8VuJCtK;!=|OK38VtO4Ry$P-%4&d0@#Jo!0xMmX=}{7Z+qdG5y{SV8KDk&X{o_ z`q~(S@V{L*cmLh>-uqydpN)+bt&79g$U@cFZ81(D4iPTzOHKr(WT1H1-4*s<8I zg?b&({%Go!3Fv)9{pLx+%->$cZI~$Qg%YMv477G9&f(CBQVr`Rem_yE*ERB~4yw1= z%a45poRC)%6ciK_^X9P>FS%hu`f5A7m0l}~^E!d|^Dhe+TUson_8$ znO)eInb8c!X20cKFSRWkByb?cq^UQRtPn?GGw^Y0zwHJ_muuF>yVy8Mzt}$-rb#Cv zKpEB4>>vp8x3idk97;uojM5q%yz*?G0VS*zHi3(ttZQscuoCJ}ihwh!^#1ep}!>K^*|@kawCH;-G%-5lgAy-1ZQD<2<2zPc*Zl!~+u zjXi}&jGef4o>)zdks$63dfyHcsg{h1vR=+vlg`f73ZO2;sa5K|goh5H6;BxVmJdLd z=bo4+5iwjvZm=um(rOu!t#F&iMdwhnFvuh&CD-HB`kAP8JgZP9N{Pc-6kGU%qlLBZ zh1-Z8$%}H_dvYF>=8p^%B+S3iqTXvb>}8!aQ#sf&UL~aX7U~@f$M5G((SPb!$aWU9 zJ+PK$cjtV3O~9=cbp%LAV|DZ3!lU;YbLn>0V&pU$QwUL>eILQlGuF+{ng)*y_Ul} zucmzhO^#JSQ~u;l#I4>7m4;Nzs#sPKG4%b3WEq~l2#L~r$z$Xo9%#}>#9)yT;->tP zG^HKNK6QI{x%?>An!S51P~AC4i=9GTuUnQM?MzGM5X0Z^(O3Y&DOOkOPpzzI zZca39rCQR2{K)>^1U#)KnNp_a`agPw&ttYVqz9G6u5@Z1zY5$1@;l1!-^bN=_S?k7 z(h;ZM>Gk8}QL6auCNcoi2t+RoXhTyFU5b~DJ}!$o`SN)R_a8!cvs3}^IYuo)H3?|x zi1h2g!JXp+rWi(@h$wOYFNo8h$}vxiaUdHYwM^!>vAzQr+J_oo6sByxFezuM`W&f` zw6NFB<-;aZIt321&^eN?ILn&vcpj}gxf@LLxywjwU=L#3%Qp7e`|muzB0OyxV|2~r z;l#JfIa~+Z-%G!8i;D#rNZsxX&1jmrlL6}Gs9kgu% z$HIbN+b0gr4n8ri%Kk{^$ic;R5k`3uKRAvr)A`m)1byh)Yktakdy;lByOOam7%R#G zP#&7|J=w!VEj7wM3EWh1%nYe133lt{VHl`Qud1~*F*$7pIC0=UleEeNo$q3|-F+6g zIXTVjEM(x$q3^EZGuB`c2}62z)2rsTj9|bcn}(kcp7`BcZ+-D8qCa#YETOcE9YHGvrw{=JC{B@wE|Uj&!goq4hK36DKFTkBeSJDr6(S!m7suTzm~uL`3Hz$|ccr%ybMg9p0CVt=|NE zr0h#v6RE4vq46`FrC^IBq7+jFz51!%xqerP?r=YcAt-dydkn+(-ltZ36nLl5Q|aHc zhI10+yVeUcvBUB`>W#Zyre_o!#-PSYz7A)PQNHBS5mX}~}^(E&y$1^vg^SMl+- zXQWlQIpA9cp!4lshiLDB^n{J;&WRWvi)`yxwQdj*M0Nivr z4sdZfmxSg_bv5|!!ns8!$7jtY9%1F+rD;}tcxh=PFzfN0oiK<8#e+c7Xf^O(D@t{o zM2#!CT;RP|vow_!@#!aOrWJp{b|u=h%Q`V2h@aU|ve#^N!8pI~0FI30RiSQ~=J5jO z#du0}g=XHrCrSw%jJt1mr+U;16~o?p8u1^Bb$fo)+M_Uzir5FNilyAmni>>1=^~bm z6|tp11juctDKFmeZYHPPY`NLl2GLxV{DF$QT5!=A1YlX^>Xpz`Ty#;Jq!&7 zgFT9%2(cW%;tOxv=$>SXp#L?aQ%3*)^=s{6vXigm(j#e@Fa*i>F_+z4PbjE+HdeE&| zLWLMKzJilVhN4}V!zSME(Kh|~Aj8IyJ0Fh?;V`=0kXulysV==ZTNqscSgZs_?%YBQ+a_XGrm7O7}%9c zh%rZa$a5TM?NukGN5aivBQxdcB1KYk7hy^Ow-ubM{8e-xM~ns6N!~3b==T^o&jNqh z{dREt6&}b~O3^edU;#}@o&u%SO)M|INkFzH@H>K?AE2iURS#kqWo_NLysBhh=c?C{ zlT&I@ne-iX)yPWD?v97o4GmE=1I`nlw6Lw6$?b}d@hH;PJ^iYy3w0Z zo6wq<8TSQ)G}^q*!PJ98JXqa615P!4>_SXz0#DXxj@ad zKOdgr-Y*bxnNrTjMoT?oC8JF3rKohWGdHUZqZeM@-9|4BpOs~mXW7-XBp6mHQyA!`%Yp5=Cd}IbWaSoVWwha>Mk{Y+d!gQ!a0pv^lQ^T zGsxA~=z+lQ+`0($hNVA}JRvptMX98Fme4_ua;O6~g=wO#!;zLW(@8dth`=HP&MT<+ z@PKlaeQAS_GV1H1Ywwpnp|6;j=DL-vUS2pmv=&)eha&}puEv=OC!}rZInUkwwHFly zM(_N#DZ}mF#k)MH>|Zanrv4Cq9kKEJaQk;6BVSHyi_|x_f)cD09#u_wvSvx_mZ&4lfr(3wF}$)LTE*eruM=5SlNGrs=W0^_x#&+2OQbm#C0K^ zuive77sA0dtUiJ7Sx!%%zAfnFtoIqecz@{j-#l1=!-J^mO8i%|jj^7rt7@pyeYn1kjbL7> z#gSQR15b*H5tvq6d)HgxqTseMJ3Sd%i%~v(GjvW_sahIl}GL0L5r=ffvpdm;lh`_*;-eqd;Wk$ z|K9PuGj_NGUuWIts?H|+iVCSQU5drq=JYy`W{ZV3dvzJpwToU%qo_xOd6N?;6?Xyq zymwn-$s{gKPnW-5)G(ms{KTMt#Z=#)qd$brro_PRw(u?DBK-couu-7BAcAnhA~)*B^97CKr2#>_P=er>I^rzhhDNS~JdKJnte2Rd0;#l=r>(X!R%zvzQJoEi*< zUG9jM?Yi4VWQaerTsfz_SgL{xj_sRO*I(_l>KIJidN(`K4qL-Jyr2@HX zIRdfHMIIeMRG&z`Q72>>a&X-)RJ5`&{_L_}r<(1mfb#N1<`w8BS#ZC+UO|W3PR$pt zljS!$=S-Arxs#fsAXTlvh|{pyuW)f8Us8&E(F)OOxic3(gGJ7E)-4J$DBfTUP#9e0+AgAWIyga8>dZ6Nc`WIgSngclj?;Z> zi%6-sC1ri_8gqWvQb)aN(A+IJQkJISsLL@B@?kA~qhP{#nwl(uZ}r#E=JRSfVI^OT zFY#%~gemC=q3KzL$Bxv55M(U3LbkjI&y6DSg=e^N_oeVE`C`QF+K0v7@XhJ$YvUP* zZQ%|)mYX=q5uM?44LdG%K_406Ke2dw#Pkpxua1J5GDv{cjYS7{xOh4`TQj7)186h6TUX>l6_5uj1B&vDFn-9p>9eW5~t5aL^aE$dDO76 z_p6>Wgz5wu;HAt6NJ{A|xjC3x>@mUlN0~TNbbx$q%bVj5(8l27p$r?qyI$pMnxAJBx0xLmX2+>g>bFIR zYQ7;qXdYd^y9))Y$2-1M@-5CuaImzLPSIE47n-+cgB}pdU*TD|nSLoHZTCw> z1(UBX)On3c?-QqJ?)0gd+*pUV6}??QFtSYTcJEHUBqoODn_CxNrtSTH#$i`1B2i_y z@78=Q0)KzwSK#>8<*Btr!~{lCYbm$5lr+b96k7lol+_#8soR(3Q{_eLhJ`X+s$l^+ zpVpY%<|!XiGu`*hbg;Blu9kVY)}R-j1}WOKmQ<}i zDcN7Awya*K*WOfu{d~+5l@{w9ihliKWhaj+eZg5y=%y!g)+bK&^*I{-6FWAq8!5%E zBurZbv=xY%F($h$>wvw;gwlxCrxU1+iu5ai*5IH7meBHB7C; zW7uUy&SN_!M0GyRb8H2Tk zMH|uNij9h9bW4|y3Uj|-_c9O7nNj(qG*BgT>L7ub%OeN=868IcvJzhl`!esV7L{f{ z|BC#UI_Tx=(uCV#dccbM&54|#S*c~>FvUUJVoAEXd)yyNLy-0ydC^NxcMlUQnkdiq z3p(m_DPe9xXo_w}3g%?HKr20dba(Zk+*#_r1IiK?g;vp&n+2WPc}9IsO^FKBjVWyk zHb^@wy2Oq>AExf`{s&>5V{VHVxC+~fQ2RyEXiDf8@P7LgTIoi9iPB{qNpugO z*US$}VvTx#7`AV+pKbeL-xe7|>Y3kSwXHi5LEziDd!x{@Y_MRstiac5NkEJ+bZj-H zwWQ6fU%YK^u5^j9YxY%JZm*=?o*g+oQ; zu1GPJ;X13>7QRa22tIOltHC!#S_t-r!|U=ZRihX)Z^-$w^0LF{;aZ+2RBZ0LQ_3}GH3G~u@UN0So9|!G* zDg@U(QwbBT=@V5SC*I)HHit`rBc@V>=GEZaI<2?d{g%Iy zPgN#2>PhxUjjbRYD7c((`kXFyqq7rsiJ$si(K8T|kj5Nqt$^q9cvOic-2NJ6ZA!(3 zu4Sw?`f+cmgtE?A`YO5yUriKoz}$(7!p;N<5p8Nq;L|T!N6Xq{Ji(@LfjJ0uO|53@ zM$I+o51U!2ViN1@#+)CpIody5fPLVcFXKF9;Onga*xN!zcEaelK*b2tXnBYiRlyz0 zi!k&ti!pSGvs&<^i3Gz=%>o`_vQJEBC!^m7f)sS`Ic>}C--;5;+rF4hqE_A#k>7Be zZ)b+0xJV#jlX5j}wAr6lo!!Ka=13XA;y#OWSFA1D)R7xZpI>KIbHKxOFVfY~^coi} zzfRe^?Fx-LDHFcUI&hY)9I(v!9dM&v6{~-*61f;PbFYz!H{Ccg88U~NFocZn74&V& zBbR%)U}FZIh5}gr_GDdxZl_ubp2o#t!M1Ap7<>M~B z%c5wEg61Kw*Ss&?HL5t1#x>)L9zZ9GQ=L{EPnoC0Ki-v17;!tB zM*J39-Q+&7Q@$VYH3a+aD;cm9b#@~}U487j1{+5{iUl$!53H9jM{ic@AJz98*A@EQ zB}pNS3(oyL%y~u3VzbR|Bj@Efyj!LDnZmCmG4?!;IbU?S^L9+B3JLo5b8BaVqZj!v z)`N0;q*ke{%-~<@64|p8W84}O<;z}b%Vdi?H+*xkuHuSarIJCGI%FcyLxSi>pVP~p ziZjBKL$Ie0Ewx(}>x&%qM4IhlOpVFw*p<=0r#j!}>}3`XG_SimOuK1h{b5?hI+UP_ z!e+l=3c_{#YtsmenGa)qMYZ$oYJ32&NQ@*^GPS^#?b`b2w(?F?{#j2K7r>57XI%;RMLv_|V32w-TXBc?Kuxkjy;^j~zUdA+ldWr9xYLe1%rthegk(wc-2t)ubI>J*SB zuH;uLjpkA@twdw%AjN@cd78xgr=sO6@;^%L*DoO&`WECeudz;+6h~`NvJVd_)@Y4m zxcFQ*j=Zvhxte)D#l?da8xA%54OEB|HkS(7O>+p7%I68muhM;vFTH2=-9Q!eo`;D^Rsmn63>)oC2hrUOT2^o zC8=X#5rh7*)xIjKry>5=RBDV4KlCKx5SCUKxi z8!IiLMFI<5Cb>+kVaSVYGY~elEdRKzuQ>5Q$SXu*-GG6mGc?>5IM6 z09h9xenXItZQSuGd8tugLOfr<)L7!PLhx-P_q47co#*e1-uX%j=z7^qlb+Rl9hY-8 z0&>B`pQPVu{r_Y(Wb&EhOxoAKRvfF{yZ*hY$Ss_b{m|5VAL-cB)_2}kCzUl?wH$@PQeDx=a*Ds^oGH|zcLXl)@R|K zzG%g=HkQ?134SJXb|J5h&nY(5X-7$NThBzG@*133Zy!l(_&-p=o1Sa3kH^?*5JD)xaUdAZUY2sJnZ|Op-6S)-Plxs$DT_jDV@j)+a zTAC=6Vd=|U?!&fTCX)eNm~^Q#Q_pxWq&LlWufb5z-2PsU&2?6TSnw4Hz0<8YCrIyX z=#yFXC$F_VYod1M#LR>3xz1VbWb$$(oJ%`&!4m$;*3U;V;=ITWyXVE4a;B|LJO}G{ z?L_(KITo7+t9A;llDQLj<13Eq%~+i&da5QCtWZXCJhuUYPJYA6Oy(>-_1{y`Klf%3 z4(`{iDx6V{h}n{iks@`l4MZDq^F3p3hnK-S5qE-08#8Yj9OTW>7bt;MDI*I}rC$AA z;iuD@XYYj^8+mPd7E@@V{MoeSWy#Ah1CFp_ZEh#yW8#+e%ZrJyX9Doz=^Qhw|wAcQO_l0}>UeXz2b%8#kLht3LD}FsE~uI$UG#W;YGm-WiFt5^tpTkpJ@Jp^c8X!RjWdV1ypACfpG(`BN2d(_`Z&D_*E(B! z%xZz_LN^Y{OP}_$RM{W{4@DFS&6Q*0yMz3!YRE-?*=?NdyrDQ9aSx+J7T5{6b^oZOdd{`fwSI<2J*^q}Q8gpLOz}B#|r5 z)!?PZ;Owsw3G#!17SlJwe|GKUk0>2->*<8~ny3$u_A7c4ZTso^2L_t;%cZ&HUm?XL z2e~6t>rfhqXKrok>|r_M@jajvTUjbDuI5WKuF;0%$bW34to3}LhzW%ge(;F_Cv)dr zX{DmwuvKT1Og~4E5&h@^2kf{EEUR%aOle&Uv=w!koql$NUfq8!Q3r^0@v(VNGULPv z9({}mn!wq>zkvV8CGc}?KK=lfi+KDF8DfruM=bb>5gEqcIs=67Tbu28*03vD&Sj!(M87`${jX4qx!cO=y<{Cc=ShZ#k$JmP>KU(36`7Zht3t2(c zOL{s$aqTcOGczkIYtNP>7g&iJ`1reF*ZQ%fVQk(|a0eC9&#^eRC}0U(V6VT7j0}y( zD>(i)=H5CeuI6hOjVE|;hakaS6Wlep4;C!A`(Pmi2yPh&?m9ROE&+nO4Kld94=#7e z`+M*C>QtSobMANR)}4R$%$}azy?a*o?q~H{&jYU0D_vPx866!Z=Cv!R26a8n{FRoL zmYmGU$QbvPO(FdT5x@E5-ToRPAPW~4K~|9O%2hBX_)Z}e1 z>b_`)jye;B_L+m5o7?BlpPigkbL;=^3S&AsIj#NfS?(PiT(5vX)~u=d?rro&0itit zNY%JBH~!i2{3>bmL-Fxz2fD|A@Bc54wS72<48Fj?K!h;eUoi#*nG_;Hvk&RTGfqxU zH8nMaXhT(16$6#&Bbz-JZRTf$5|XHBTQMU2L|C}&v9X`uo0^%K?K-){A(+0Ys0iQU zH3*PJ$(eU{c1})C`nLLcd(ZuNh4k|A!o?quxTxo%GfWVQcKdE+0EpazTymzI`8Mg> z`1p7^SjO;X|1Uh<$IBKXG$mwEDUW|N#a}AtmT;lJ$+azSYVx+R`LyykBKJvcG#3F8 zyAhxkJ8zdR8*v-BxVU3HGF*SHpeFjWgc#PNeW`5I>pyR=tgI|7q;FmP+vNXhLj7My zJlenSx&O7)TF?s`th5|UDkH$F@0E=R(7$8JCQ2r)$6fbhyBk*rc7M7mLW)jpYNo#XS6xk&b1mLa*}2NHt7t-covh*j=`4I4%zIBm zUNJd&z5F}n+>fVZ%+cfDvH~^+ureX2J2A0LR{4MtXX)ymqK`N_`wDN9q$FD#HZLIL z`+EXK-=3ybRO<(q^dHXY<2UC(yarNn>T~5fLvSMu7jb~jmx=mV&xP;C?mLFxVm)>* z{ht_psi>L*E4+P!k}E~ON$|^$Ns_h3vX}UJV#YUyvxNo;A}Y^XP52onV)yK=3s2p& zp+^?G{rEf(H-xGnF?as0ob{@5BW8{4O}?yk;>0t7)IYvyU7Dv=Cbl+vn4mDR6fWx1g}u4&583 zuTTZwi&;~irtT1Z+Q}D)74M0kiNRs?JFRa_y0 zlH5HT=?@k9blesQF)CKw6xp+~bgVC;8$1yNPd<&G}my3-gW- z^4&av2M#D>jfSr_tIuk~w>W0&>A$os9}UB7KUHjV0FU@1(janSf)JL%;NA8%7$u2K z!KuDQZE;0SY+G7ck>WS4yUw(whX}}+*Ke}OUz{?#=bkFM&8veq=z+jefW6(BjkWE3 zUhC|aS6yw}snWYx^MwS#?jyDNqO))C?<5~PkvAmZfMV`pizXyQppieSV8e~7d^;R< zz+1l!-_6z$t9OqRFnccLD~<6`ZDgsgm-)_FX|Z%k@VjdxTo;eqH4}dH-o}5W<^wEeK1_nvUMG_)#h+26bxM)aCWx=hF7ZIT4~1zOF5Zlj^WWAf1x z`nHcxGkNmDhVx(X&%V-)+$Thi@+ZWxqL?t))7&5A;l&Q>p4_vojj}q2%4L}0PsyU5 zS6}zCRJq!O1oSZlynivN_1S+WV0C>$r=isxcZ^J~k3fMoyOiereXGD}bYv?tOP5c1 zfowU;GUlnk<`QtOMyvl(`Mvl~U6aSQ<=?+k4e@stgGmHhrgXiSE}^LVdp9DpF94XM z*}1OlD`a9NT2@Cjf~i;2A)6Q6x_lXA0u9p4v&$`+Pz4o17AkyV=F0vpW5Aon3+}`5 zgfhvY*&u82C@W%!A@jVir6B1}Uh88IMf0U_77PfLm<@PflOF1P6QoKBL#@VI_<;ZM z`+!~41>6Ip^i9Ox%I*#kg5c=8-C}>Or6s^Tp z?<|9(a&~@UDAm>rLnnwWf{2exYDH4YEfP()vD>Dt8ohaS##SJb(s-!A94dWV2OnJ6 zP#`;WO#Ap)RSp&+>3?+45NJw(+}9vPYSmlIS(If4O5@Rqe8`^#FQI1WBO`?N zPlPsA*%WvT?I{J~;}a$=1i$#q-zUnF%s)$t|9xh)|G$*Cd)YzCtR$GZ;GLVT%duJ*)2Yy+6e_+(-Ba4yAHi_B_}* z2ousnlg4l9uKCPrwV49fu%hJ8J?D}h2zBIKy6A4acaM~)Hp5ed)6V)n#Z+$y=3j-vU^3P(=}L%CTlu7>$C&(YnTuZPe$-%$$gMEaQ+;|zU_4)*8juMr$Uz_ z6^_4N9KEC*_Iy|-GVkkvL&++L7mx-lS|8*cp!`zsMS`D|jMu!$NkIKucwLq?CzwlB zqcn(>fE5y5CYpK`hHuzJvw7)H8zqesa}(KmGM=g=2yy<(I5Re(86S!M%01N}^PL%@ z80hQmZ#A%(S)Io^5+&YzJp8@6qKovT{7&Pj2cd>x{poN2R2BIVYrX}7cx>+_P+4-g z%vd=em$Ss@5Xr)3_x-Klva`Y;v(?1F_^j6OA~W5)=I3amVRcTo`5njBvf;>$;bV6@ z$$*xk*ZycqEL22)6teSSqpPefAKu33)Ar_F*HKWeFK*EYeWG~ry^rXH+#YS9KJ!tS zEyW9tv_Id=ET*2A_4eg{S(9=P)-uC7{b^{Tmtr?pm#N+xe@F}x(JHn1;P6>j!pwW| zn73I;aKY&{_edD7Ri|oOf%xL2H2|H&Vst@|-f!i%Kk*+5l!Ezs-^&QC$)SAopMKNF z>qH^ZO6qd_OP!owI%H}mw5*)F?0q;~nr3d+n%!NRu8kdnvF*#kgYr()%G_kMTWssH zZ@M(;xlws~cTuJWUcn-@4EB^!+<3QqCson#dwWtizeAWO!rz9^P18^t&}poG8L6_f zMDaY9^l6oU7N705^c7j3(8LSNM|dJM>s!f;x$n90rE-w5yi@W|NfEkh>RiKU8(@i+ z{8nr}`3N#wJYM@rB)(EHaxKY@B;nnIR!dXX*H52u=HOpm+%>0xbamf!RF#HU_-SL8 z9yK~{e3wIU>U&TZgnOi_F7U>N9~bq>%RvPya|1@q9EX~&vw$asCAsgj$y;RduXAU{ z)P0XNkeJDi@6S%*i?Bk-_BMOX_sQ7@sKBTbg-cb(^`ur)M-=&oxATW1Hj{_^_eE|I zH!ZmzM{Otu%E>}%6>a;2ma&E7>Lgv8GHZNWb0p-@X3w}6Ipr|<)91!)seLVF)XjlY zuTe1Zmh)oyH9_$j)HY&}+5p|}o_;)54-ev1~bGx|54goQiBbJ|n4y<^m3YRfJWN(W;!@WUxBRdoa z$?S+IeO>4E2{7qS?{h9Jma%v=YboK@0`>Z1O~&77GJBZe4Xi<5s@zyAmIXVG!GYYF|hgt)!>dzwqA4QgvKbAm<+t?5@IRDh#R?T_Vo1k@8Dc3CBc`VrX zUyc=WrZ1JJL1CEokfk+i`GiqGHs@5>momxyJZyP;Xm z0M%W`m|cq^igyz-IlQx8c`hYHAMQhWJ`W5P5Vw@M&@pG*tB|rvT^M7`Q&3HoBKMHQ zK+1(l(fzPoDU`ZdvVpHhCYfh7y&nosST#b}yTqH|2|yp$jeLOP@}ET8sBxJ(0ti@c zA}N(wPM%K5;7aw-zPOrFGIlYl4yCg&$HMw&SI)*tXKUTm!O%H?exh%i4={5w;s1l! zOU&H5j<;^?V&`kh(k!k*mNVZrv(|^&pOq(J__jCgvTs==1BrJQXfeE5jhjxCF>XJb zXl=PEjQL_A4}k7qL$c|Hdd=;AdcU>8Ly(6b(ScA2w76zr zUitlU$a%-SJyEOI#wjB+Omnh`6CY^rZJ)0m>5!ZSn(3Q0^#oHkbV^R@Ni2vL7=8*6 z#4%8hWtCl@2;OaFH5b(nW3uY-fBqV3uF1MpEiF<&EabeB0`xAq=ks>=H7&!i=9$0S zQDRI7RxS^K=gkdr>%N6o=B|hEO@h%{ExAC_JfkvK3r-YDFhrOB%H;KGIYwlFD1p#} z0dH(A;MZD_twr{xhTVlKL`e7@TRu2V`VvKn8U=xDsww_l>U-m&Br>5j(74jV9Mg#P zF0y9N^31~0i+s}cMO|Tw^YcoWt2==_TQD`+LLh;a{Xlu+gdL%v9QzH+!l4L;ahoPDA@FDcc3tM2PG=nWZ`SJj-r22PW4(413gBN zPm(E29ny8W3JAzdLDwRHQ+uM!i_?ML^%3N$l;zHz+`+GZ_ncVv2WlDIZV%;?B|yc# z9sLv)DfsBz)Ip##%0ZJhRD3jI&r%dhCN`yd^=JQ5#tUmtc6afb(JpagG-}kO?b`29Jj8<|j-%iHgHir5852p81H8zZb z<372Hsca0^HR$OhLc6|jT;>v*S^@d>Jg9Z)_pm7rO9LX7g!1t2^5ZPH6LEs$a*>p>V)6-K(p(clV4 zJM{7a?k=L)elKU(uMm~fZBGm{tf~IaaEMs4c^=klt-c6`F!O`?BGY34Vucm603G5; zI#OnVJ-1-?Oa_m9vvQbomg0ta^{vdgNx7di+iNhI)Ymqp$zxO^US6uVZ>5lE=9W^s z*TF2e0~}{fxu>y%<=7%XFavA-*fD;GZflv)&v4&-IH9O2>f}SM^KKF`c}vk)s%OA= z%|IsR?@?f7luU#2(s|3oeJK~|V@~0l?V|jaiwVVR{P!Kj#wZIvD(}_H1C_1TAr$9? zKN;zzLYpaE@#Xv~tMtC2lZ*gz@%&cRJjd0P&{{JgI+mUMg{ywz#5~ddpW=H7*kt*| z0Fjv(AKWt}cUNwzaC_e~DJdwpW5M^;NmYMYy$P(7q9!5vabi5~|9qD!dAqtLm0vud zkHjx`wehtW^BTMDSKwjEA?b&54Hg5S6sh;`h^7eLsF^ADX&jpoP|{s`4462pA)JBx z^R`d)&z^HoMh|gikDIEj=KtXL@31nHMNWVJuP=ZwakTK{aNEc7+x)A6iu{(_BgAu& z`8`sC2o=Sc;ec~5lY4KA)3QNxl-cDo8y7+lxN!72^B~8CL&9ixzx3n|Hy}})p#)+( zS{i659J{ov1$f$An(&KFc9|u6cM`-6o|3uRQ-Ig`!a$=6qcvM^SB}KQ9c%~$zkB6) zyTFsU;}7P5`Jm5Q!$-ZuJ2*slbLO_d?ZnlEhEyzlDTDGe^DRdtT`cDwD6^8)zK1pR z=L>Axt%dfZqhHG^mjRMt5|%I^l{<}4JO6cYe&d(EP<{uyF;2Q&H98Lc|66S8?UU#t z1VQnWXrVE#cRBrZPu^)9e?Vlp*j3s*LgyzA)c;-YY^_re0=fOYST7+NnI`(u&#xmC z!Pt*ikCjgNOP2Zno)5V8+m}b5pj1@ZZlHdNG?lQ&w)QR$0(&ETgx~;a{)>Y1jppDL z=Jx^}&eDADQ-urDi3rc(oZ9BD6>Jiy&8!iNvIukAn~{pT_pi9;F-=2w4OdIUD|82H zXYaSY&$O-Ak6-Y&eX-Sjl>lk3b3LQZX+24`g26vsW>{K!l^ly|Ns$hEz( z<^)z}E}Av(%H|tslF-J*50}yo+1UT^vsKN<-6v!+#s?l#)l` zN&4(&jt#r5@0Q(a_z9`sgPI)B9?G3ExU4>U`Usz_y*3v?tTL-lxO_J=_^bxKFL)Op zMXV&O-D~y*abofXrj+Z?I+?AOZ(uFi26lGP%8$%Z{7y$#KBM?_*?*RHRgom|{m3y+QzfjsuiZx^oYcTz4!KOsBT{NW!y+sy_J6;l9>v?_hc_7K>FfiRu@Y=8QKQvZW+IAQz^m0R6uR8oEO>2B78NI zl8WQj$mlNp)0%cGq+cJtdB>4|zHJZMxcA_4*P8jg)zc-M2o;)F```sg_Vcz+PK)$77oKkfD-tr4CIs{=J6eknxCkiPhi7qH*$ zwd>YmDy4&EJn7lUKRBE_J?g2BL6GaVqYd-DnsPY%e1_U^Fx4hNY>LT8zkj_coYfqncBbdCyzxb#p?6^86UwVv*$^GS>?UxSp0l%IqHeIdbMq7$g2Ji^RRCMxOeKlC5(#L(s9DjY-`uJC!PxERUJrwW%UO|-X;BKAG> zN)uIa!|%B6Z&kSUw_^_@=acgl>c+WC2Ggf#OMciZG3JmxYkw2m&`ieJH%9cSY5us9 zLCFLRg=N=Yy(~1Cb^cRBBg<$MOf~T9n`^n@_vnpp4fE3IR_~K*SSBy4&v6T%gHKz? z9ynTmw|9)rj-OEV(=ku(A8-Y<{Mb-ygk!jck2V#Pp$*#2Yo&DwDwep)dt!mBQ(J2_ z_$P+tN=imGrs)Q!NJAoTIpZPQ^h}9W^py@&>t7Z#IKZDGo7c7~0}~^rbI2`QLy>5) z4h3)O=uSIXCurWPZ9t1ixnt>J28KK5)8?05W0dGnvB&x1Mq!6(7Ia(>WnL`C3axsM zP4;a7v#f~H(U;f@kEyAV(iv4y$Q}u*U`@V_5>mW1GHXLBZ-2)~=H26wzB=Nmy z8ombEdd*hff_)5cld1yo?9_>gV`j$t>q|Wh?a@PEWgV6GavB6TD-OGy%Y8M}=eTzK z`z>vK=&Rbb;Q8fBuX#JF40}7@dEHumJFqLwH0=DWrtN$>+J3o8mT^u(qtByeUtQRe zr$}s~1{xlfyZV7-&fRU>9Ish7x#$HT4y%PZ?yCTLC*50|9UT)CDkq54x#!U; z;5gD9-9^o{c1otfk<$Sn3zf)Nht@>W&WIhgLKn^p&>*_rXB9$;B8HX8`tD)-?BQ=Y zZdxvpMiWi7uS|wc4FY8h6(&fNiD0=eebevggdeIGe+e{#SE}}_;KB!sm#g>J@-GF2 znNsvUbo@_*M>i0sGMzL&DD$~Zv2)*woAly#xHIISKWnE0Joq;6$n3UbHl+6{eoDvi z8kSGahSGeQdT!-c*OANPtyz$LdwN4{XpNd6m-}nMa&eJkw4FKmY@lCX$XaWXusa)wee6YF4+{&Qa3wZPz%45Os$k6OKfSpmX(AJLroUTm(4 zeg%Et-C|)vfTVem7%K1@Y5um@>|IIhC^sz1pTzx8a7sCU&D3yOqhEkVABn68(f}di}ooL8D!3B?ch+Pc6Jqs#j z5h%)lS_-PfeGOQfuY(z0%YM$BsTRs=gT3TFC>;A?KWOEc0o8HIYft4ZP&%w#`1S*a zU{-);9vCRi&*JXJ=D6nT=_b^Hqu9HekH;*sr)z8Hi4UQFOz~Q3_hkxH6~gAiBME`6 zx5=aS%+>cdu*g>dzs2Vb0;{ufbB{>VW|@nnB#Yr)vkrhhnc?7FgQR2#JF!pxY_(YV z{tS+2S#2cK(DvrW&}aEZ-%XHO82-&g@Xj8*Isfo=$t34rSUPiD;eJL#JO(aBH zqsu`?B>u0CSnKoqWz1?7O?dsY>DrKem?CsL&_CD>$bFinQPiR2dIh!PAbXK7sAF(r zX?X{mX}Hmbb$*XyfvKm3 zeXSeEZrNb4H~??**2NqgGeVVqZ0lTZgTJm`b2B(ViN5V=0rs@zN?XA;f8E9Zg3zqh zm&~gqF8nnXk98DDxE3%(5M|Fjp`Okx-Q)$iZc)V=^YEcHSP*KJ^>Vr(NsE z9!fl_5adW$Io)TZe}lDL2w#4cj3cs>zKCh0&w2XWKf9A@5cz=7?M6WquYwN9pqKd8 z?j`=q4+!naM>tomSN%7d2vC8Y)6L`n7|c$X0a6 z-{6tnYy@6Ky#Cv@{40g@Q&+UAbzj>$yL$?L%omz6q+4F-sDp3n%sQ@JZ;&W zY|BpdQujJt5I>H`N?Wd{N^RU#x8ECh9p!RRcWZ(5i$XdIcz87`w7 z7Nw0PDa?e$S`*fn-jC7nh9&Hr=_&dlvLAD=EBbqi2P(^KhT9zM?Bgt`+~vPX240lV z*TpegE;yCr0T^jzQ)F3EV3!;Mtr3+DJYZvI)PS6Z{7I$ovOh`{c|CgoWG6?w+*bGB zX-d%4z=cJIv{6Gm^4&5)Qua=qTe^QNaij6k5)~QOiSCWoMJy)jJ&&6+FmMfHdG0EXkGCrO>uSIt^vm0}-1t zh_~My8(f2pM!8ilh{$Bztfwl0y@CbE=GqNc)Z8(soz(;@ep60ds;A-?-&BCnPhRfD z6p)BAW(zcK-=egY$sQZGRc$Z16AAWh=iHh@l>+msdC&=OT1&vj!xagXu^}8!GC_nu9gb+buiEOX^CIA$3-g@R@7M%Focu17~5wb?*fx<_PG4{ac8`NyioX7}dAuMIJL0rfZ9brU$vbmn_k)Y}z?3l;Yfj|-Dc zlkrA|phNW?a7Y9Bu3C7jiJFy5@rla>@12GpS(0ejtI566O8?QAC8rwvp&ibMLuR$^ zAFtHVpBnuto7&Zdy^VP-)9bNydo|K1?v;$qh0!&z1V0Dz2wF8u93WzN1pE+bXkTCA z`&y*Wyz#7tdz2LwM>tpb9`qnUbpq*vn?D;fg{PNKe68!3@6KBgmUMHqQv*;%+M+p> zh1_?ePHQOnN5tfL&;|She5UWfCU(UmaH>%ZBC;);Ri{Y*07>NZPL z8rM|a)molyR|m3AZXKp}Y2dMJbYsn^PIArT#+3cQz!5fa&5KTIk1++9&v=7$q6k*F@Re`3ARt zePJW-&6MMjm*0?`y6KZinYwVqJ&g}2CJU`~2M^S?a8$PG^e>2KLO4Pzmp^xG=zCD)VX){9??8Vel%k|+qhU-R?i;b7Uq^X14l)bh2xT+XW zjlLrmK2d~b?^$j=iF6|t$XH#jpa&sa^`>K?tjljsKZ~axikV9o9rL%LBdcO-*6QwZ zJ6e>@xUMb5%p<`l@wDsK&2xSnhU`fj$x&hi1|UMhfUwVv5JG`#s}fvZ&LDGLunH;m zq@hZFr_+}X`4M1=cD@0!#;OE7ChTMK*;a!O`DQ{YVtl|R$$W&ZnnkGk{ea1tiMYWx zZ1S=d`?t;4D&t6Hh@EH}AnPq5m+pTarO2=4x)1pBg8VF)bXvJF=>xv9g=%u@Pf_AN0PrInlx&8r|H2XZv)~uL6)a0YRTT~LIXUvaNKHMa!430rsG{^GcAr&|& z4#?V-97l2J9u&Na>p?$ia3BQQr$afsRG!7Ax^9q)?u-c0??9^WM&-Lx9Pq30!U;P} zBoflHiS`3{-|R)T>aMUdY$1k5Wg~#F<95%>7cjG6t$IM|z0a-ByMV0vFDpf5A4RFVV;zdlJ>Pi`a-y)bvA5n6$0k08VEiK6gij4uIfl=lThDjq|BhEKFJ4F}mZelpI zhVwRws%LV(0NpJ@p++_s816dAGl?yy`<3?O5qHIT2L@44e+2zFHYso}x(TNW}153F~!-03Z3f^4Zsn z@&NTv`IJGHB!y5&_S8vhymw7>h?g(@iQU{js}KKMZ+G(ri|vR0h2}psj`J9c!jX27 z3ObrhS{h^OHW6LEi(;>gQ6#UVm1R&eF_5txp5D7sorX=+-7Nb zlOidKg!cAz26FY1m>A}*jzBclZ?VPJ)E2wKoDi&EMNG*pTk%bsDfMw3VWypw9~Uv6 zNfX704<&M%4;{{J^p2iE-7YFKSAKgf4|jH?bJfm6?H`=7H8O%m#I8Ogq#39|oI4y#3v$OLpqip7S)g7V(95b$tR$~p!l41VO}=5k zse);wnD_|0Fc7iaWQxjMk$MpD?->Y7v5M>-!*J-%#FoUtF@&n>;Iu$C|R)M-BS8=MyfD8Kz+F%gC`bEX242+I==wdNJ1!qP-R#4lpem>dh`^v-8%}Wb zbrW3lrfpOeS8SBH*R0u6xJ%gImE1bwSZ@S>X6cM+`W2c}a^{HKJK8(&Sy9k+zO_2> z2Xn#IyDm*I8+`>hNUikOJXtykI7pAM(MhnrMb-G#`*rXN@K4i~w`Ux{uG$o5>U>5Q z8n-KWXr()*#Lczf>aeqLSKA<@$p{tj+^%Kf1&E)!y1Rz~vC)GORJ|{rc%P=wyfvGa#%jnB_N-Ci=EuAG6vy#UESr&BS1ULwN6 zWX!y>x2@CU-Og-`)~UXl76Cv!!3>Km2{I%)mi*(~?wvgmAHmoEZT?f5f};sJrE>0iogaU*s+LWeK@&v9qP1~C$!{VV zAe89Mc_KCOuP?xc!}=YquN_1 zb;BRVl>Y1luxN478SK|Jrf}Y0H%I-MH*^ueF*eycnxFLA@bz{1EZ%x#v{x>JjRqxo z);^|QsN&i^Ut_=&fdLx~?hWJA8J)z&{+%Y*Wulq9o2u9HPAO9ICZS4a^aG8tW;rk9 zCw6A3$@QkTaXD}Dtbw64hmdJ^1a{$-cLC$xt;)fX3{NutQ<_~opwAu>Ytb7AYW$dHT8lV%_Ph&TGCrxJd4vjfq- ziF%OY^-Z-eR(&ogsXt!qACQkrwuAnp__b-TC~^texZ=_z#0SQt-#Hg6EYyf;ItbyW z>-_X%>B-5C<4E)7FHeQt^Y~ugHjwW5+;45s4uXYkPFiwoEeozJc2vT=VA9~_v-o2Z zdA>!Kq$xw3UFjs4ecAS%4aBv&0KH3#UkLkR?k=&x>K8nV*}?)64`iy|mVaD!(^P9D6rQ zP9=r)me_mfljLts${K_|);uQ$S+f(TR-Y6DXQVUlMFrd2y>;x*nm#UxMHI71oovaX zY_Q>8L7ekf|9q!2tqwBfV0frw@gFU;n7V~~WY5z}4@!}GGVAJpE2@mg4soe>!*;!b zp^3ljqRCb?3~kyPx?s&GGV5EfdJhiQvP-Qi9@D|s(?nIH3`=U-CKpI+3~36;kx4@6H$~fk53A;D3Kc}l z*4qWc%3M0{Bl=%;{uz(dbpOIcUeo7DyQn-s)^QU%-MDF+yvp(mv8g=5XFfDA*mJorB3dAX|}Dx4oW(z2!~g zL%*nqBXZ)6B0$7GRRx;A?)}vqc-f_Qh?oOvBM*I1mLxv$en`T-(AB~80DfJ0h9;s^ z_Q$LgsJBmfQ+Qfs)#>2s)3}NE%EK=I{3_ewx;G%x4!5Tn;`bn(d>~wO&^Fnf87ry} z8`ITy?+iFpAjDkN+&ql14DL@|`8^-`nl-nxuPj_}w=krD@WuDYqeP1jh7Bu?dQKVI zZAXM&riE(#sBo`Ub_F!P$??>EI`(*nE*CrNZ!I4QdJe%06)^JCdj71ri&sp&VN;tY z%c3S3P8~`W1mud$LD$1cT6zlyD3i{L4M4dG3K=# z;Lp<|&C@_aqI|p!A9N->e2lJNe>$H3Bj_c^W7@>5%bNwVV|dxDVI`18ccAt0i+kgT zeJXMCH$kw7^FYb^r<=3tqE%X#lDg~W4QHTq2#Mo3Q_@oc`f%1L{`_xop{;jEq{0_4!(_<@->u^|BJC?1~kd*#Ul- zupZ9gJ(L1-y7WcSRWvT-`u$^|*yeT*f?4-xW+CQglbYlB<8XMN9W)?mf zZ5sYASFPgNgC(q}hb6{@xrjM?>c*V^S-7O)_a<@hQrZ5!J1_seT`3-wfsO9IhtmW= zplcPegvi{;_PgZRyO=`5eO=U+^*9SVUB5K6t45x9`%H{?W}y%|G31TiZytrQ%N;ZL zYowV=6LPlayepLz^flhw%zlDslZVffrdVDC!j-Zs`pn8Jun_%ClD6@f&d;qT_H%mA z(PoiaKq4DIX$V*Q^KL2H{eC?q0nQ>!D-n;wj2Va3Svx{PM@`pQ*_?+Roq$mep*=ZX z$gebC?U$rM8e?GNSwX;g$WedR{WdxEy*oC93k-g(G00p@Qm)X$t8=wTsLTth2h}!? z!1n?I+k<7(SX07q1&YuLl7v*17NDCfOa3mHi~V|#8xICHDT~c?6War@2tJORXXzCC zc}+;SR56>rA?wRV*PMW+^TYV5c_vDX9>qL&>mz^QUm=GiLy zfLINTeo{YYO40I5B}hByPl;*mG=q36zVhgn_Z~BrL#r76B`kerH>gxAROwH~8mZ5L ztJEA1t(SkXGeS4S zrz@BR6oBT(9z*($@)nku(?tpl0znm3J|x7E_HJYt#&CMOW~bvgvmo8J*Y<}4EF z4jO}nefzIU;Mpk$%r^hqP)C5<-a9}FizC)9Tr=B9+A)!E0Mb(T35oi zcDA)@W;NT#K45n)V%ky?xrL^km>c7aT;3>zu zpZ_T?1UxH%KtL*gSq{!qP(PV^PzKZxOcxJEx3#nLy@OBvy{j}(US8h$`8gsJ|K{Q_tU;suX=Zgz&H1F3A*qnJ z_N(u%*K-(;Epat}xW9XiL8hmpQ@CrPJmDom=OUb0@jG1L?dtOPVxhVowfzM z=3v2pto{hK7hRl+rg+!49jI?sotwMf6GK&LA8qm2y}#3<+kT+RntrD2z*b4$;eIFJ zeR&i|tHi_0`#17<50fyq=eI-l%&~X0|n#}Bd?^SmGsQyOdKG5&|2HX7RQe$U>4RQn6Na7OMH59h`_2Rpo1TFl-$Au ztygo?AK^@#pO!~MO9L-^`XRbtm%1s_N`9Qyt|NfrP-KMRf=G}#{6LiOaQmXDyviEtCsQ=g_Gn)g5{N}G)pqZwBWb5bF(69e z%h31JFrC)dzx(-W_AGis><18XZ2iJ_+e!%5%ky{y1B_a}Vs8Yc2f{&?G>BvpN5Sb1 zq~e|bU9O+4Hd=c1eUD5%bxL}|u0!n@yB1sAD&6T}vlAvYT*pbp&QGed#kjQ{`GrH} zv^(`hE}{V<%rafUMWwxw7}8x4FNGSA?Y z?mU*);NzIH#CIUPXQWfz)I!Y77CdP-;NRbS35z*f?;WL|kuugJ=6eA@cd05sMYM_N zD|_Q`Vkf@ShEihD-W5TzIw|vE*lE7cJvBdWb8`EFQZHT<2Q!Vh5FuLMyCe73o78Zm zbv!DfpKTO^-y;SR{bzT3d5max#;1HH`4rv%VhK4yCzrXwb-RFLu^T)ZL*E#&NU$4Cvd+%9$#kH>W zd0$rnA#u!zp*~XtFHv}S(XQ*WjG{)x;9Pty{u|&?zkh?%dZtVoq)~X=TNMoO!U2=d zpX&N0IZgbRNT=KI6ua>@f>GuU4BB8=|Dlcmi9Q`Vi1cCqr{4jO*UEr=%-!TR0U}ua zK3k@gp%N-ugzJ)=XRwG~2X*AphuMCWOKPGU2)jxHo#~#md~#?uks5m7W&GOhW<2n4 zwEIS@)%eR$vnwGQL?BxI))Jz7I8-8RL#0wrpy)GD)7O*n{3NTNlpfH%1cPCD><{LkW4GXXTly!{=|6u^5mJo>A~Y!1{Mb6XQWR_#TD}$H0zQX&I2MS zVVCagvb6J5%Y z^hYxcSs2MNW?&_a-)PFV$_aOVMr%XiA)2Vi1MgsAm~=!HBOGQB6R7q+ACWS;TpppAvh*tG%$)l-x+;v)`oPuw^jLqV zSS0O>XJy63e~qZc?BU_zkLpcMU;Z31Pg|;wC%t55KnH5$V^XSH*pG||Tj<@WaXvdU zgY{8lYG#H3NB04c@EJIV=9QF`WMySV^HEz{d-dNVu8oIBbA3IZQp)$EkES>of?u8k z*^lqaU-yLpNhd>n9^%}M;EgpkQh)&q`~^sdQ+fdQ6EH77T~wsU`Ptm8M_DXr@|@(W z=d-&K-a$tf*MJFO^3%j2g-dgP+Fsk<{`eRMV#Rrrf>HsFe z5lvvSFp0hb47fib1l9ktFpCc_F{$JKarl4ze{0M9e_bBV^zr=kSAANV;OeozBBX4g zuE2}`qC3YJRp)9f8qhKcbG+G2NysWQAakDfoDaFhXV@YYJX1Z4b25uv#j!ahd~z>kmeSGea}-r z7mIhTU8$poJ}hc(V6Nvom1;>4>@ z*VF_VRhH(qWOD>L>t4R;l{IcT9-^A7zg(FAW=D<&v=bIoYO}Vcp<1>6abBA}`r`9t zfjE|@WaRq7bk?QXOPN807=;y_$HNAguoUv^0fQa-nNrEE#>6g)phjyHqH8%pVCJp5 zH8}`TgI<2H2QQL6YBF%`NU~~)_t*$W-xz*6H-Fr)#ZwgY;4R?;R|ZbU><#CAg#SL1 z3wik7;`Iu=NNSkr6ZmpCDee->DTDpmjjF|S3mK(>I{il1RIaa!tvs|h8b4>An(^{U#Git*OVBq&{tLiM5C8IEu(q(eAMR!r~SoN)=ui8!o#iB zaJ>cxL~i5WQP++E5$wj{XP)x*H#lv;CngWjUUDlNBco=Xh8gi*TBPI6T=*KSwpEF% za@a+SeXzyeQJrM#l|Y~@)PJFg&3*^jl0)8IO1<Y|_*?w%#_yo_4qkrhElt0k2 zE4G^5vd8Ap=m79-H9^}o$~IJWNR4At1c?n*t^P}6&;=3UIpG=Z{a>fgajjtkK4v&e zH@>Z;|DjAs@Yty%=s88-l!~5dH`*<` zo)xTap7pr)>hRM`kqo*n(@ny8;V+fVq10F|6{}oXoZ~SiLJN4Qg_o6NB4`8CW4ToGodf zt%tsKE{-*;Ot~#oX-%jlctTPo$0@De8X*rV)Bic*N!d|NF~GFjtHgEdjc7s{x1Lm# zbU`e=Qpzu<)ZSZmHtaoy3y+OB*0AYsJqf9jBHk|WtDIiA=RwiH((w(uQi^#xV|1uU zI1hfkQX3u|B*0Gh$~}Hps6dB8A(1D-HF0v+9FrMA%{e2wM)=Yssh1p8k66Sk85`Ss z=kS!Y`2_tQS`IF5Lv)JxCwc^R=h#J0XwiPXr=#M7hE^3uE@Q1MLPjbq3e=-YN+?*} zJaojui^bgq_NO2Yb+Z&odU%5 z$NXK$U*UExZ(qgljZ;(W!0$ElVN&)PB>K-Y?+uqaiUS=N(9+b11bwrt9_0b;u zY#bZjxWM~)uJRc&1MYQI2sDgw?1n7#qaYP z?2cL$g1Vf9LL=56bWz?z^L+HEHZR}*2X&TWpAO;qO3-oKx37k7JSJcqG!GY%&`q~v z-Hp8EA8g|#V7kdZsd+YmI(Q#$_ihjN>MPiv_z z9TpOAkX<|es1^qV3h~@v^Jxl5`0O~WxLya@FYd34oipdvmj7qb;5_)So(FZf_3Lx} z;redZmCZAK{z)~~;ApZB5Pwc}nTD%sEVBDe_K%RvqKXpHE^<$j8wrMQ4?B!OaS059 zFP)G+vT-aFvty!NT^6e?JN)6P7hl)Yg2{=2p?~wX58jnT(Y(AjC}7?e-}Y@S?!-H{ zW%6O?4!r%?T7EJP0JPI_?-^DPe&yd&lQLDC;`-!Ioi#hgb1RfD01OUw zu{v`r)L9MB%oUU_(pENZCxhVB>*8<=l#rXa7d$5cM}xc~>Sx1)2-b7ky%h4C!hMw9 zK*vu!mcE2S<lm|lL1HV*k&^G?Y=nW6_QkpS|||r=idt!PmwlF|787^Qpt6EKeVvkP-;G& zMbA81nno>AoPI#xu(&c4vXOdSAA)9TlXboQYuBl?MZnowF=-=KFzV6GIxY(->w!sX z`vytM3j)+4>JgWh4sYly->!nj5tF6vM!gOF{YDq#rGg`BZ$D`fP3Gor34B;<(aIu4 z->yJRh-$0u3S7|niK?EzTN^24jZD+AN|ouhWMWjEIeXd-)ncB>IzmmGWQNnnJ8>JV zt$3ueBK$4W?i=SbwX{kvz6%374Pxsc1+GUEnk1@|-DZm}icd*O&Amzws~XU)s+T4r z%Xd{qV>ZdhP5PQ9neC*6ZmD`4tZuv2fF5qo+GN3m(loq38;KYa5c*yD@foQQGUaL- z#f=?uWj>#q#ZKU<*PA|k)!#B{K+Gc};VOjgBMpIA_s_;UuZ$M3OowZ(y!l~I9M8r5 zf=fqk@bINU{tK0Fe7{`*TV_1O-F5KMZ!$k2RpJ#qSImaaJTrsMyh;uukx(M&yt0{@ z>9Y}#D;3eg)dXILF-BPFKmB)>)Qm{ z+TF1Mv8F~lg#6*sQ)#k?Au9>FPCfZ3-V0vDfET$?@!^>v?Stn|EUWoe#WK; ze`f=OR(sZbT=%m~_c)#tc{T4-B=@7+_z8X;tN5R*N)5;f|I;{36B-ixhMKi0@@@{x z9r!8g*tojPucT<#X!OEXh|pd!|Ffr&I&-{bSB})VIg68vbn2Wj#=HZzlQ6}LpF}Y( zkke4viANX9EXzqex99EkX$B1r+GaSDjB4Rp1*}z^Nmu1A0#ONw<{6kOhPae(-8PUt zjNQiD&u)(m1DK$;Z-j4{%-bY8cYUhZTBgLRX-D*4C0v-^CKJ(1gwUzkdn zqj_5yI62kk^DKRFHZ_&pVL|zSnk@oti)Ns{%#V~%Q>m}j9TEkjqzIYsTbFPf_K@sJ zGmwfK-5wj56>X%3c-w{k*wH0qZ7rVo&}uKIAv*3f0aIgCOWH3d#v%^Q68q*%tiYt= zg#Ky>Ljn9Kk3VbmFcB%c{ch;hQL%^36D;O@zeL6NNrXP^B~5EmLd^b}&GWMStWKCk z36L;izc)|Wb&sbDd9#}m**3V4&afz7J*cF~obcjBZv8q`)UzfrbVr)K|0)Y<#Nopi zH|WoUlfv(kKMEQ7@W|bmUqGO8x;UQ)SR18Q^C#b}Nt8rWFuwyX^n>Dg_k9Xr-Q`Vo zkbJj7LVJMs&ywrGzi5&F@ey44$ZvR90k}6B8XSl$`}`hmwD-H0d4D4!6!!f1>t=lP zuc)~H$H#oLd*Xm1X^x8BQ(sQf2){f06|hk>*1c}Yz;0jfz=N*fh(3hg) z82Jf1rLn{Dz&_3Eg?-3gS?_5Sp5M^BP20Za5}+WZB<3pRRnyb4EPb$Ozqhj_b3IZZ zS2gLWJVMM8Q6OkD2z%qV+!xeX$XEJe`=Z8_^&aZM+iJ$ihmSd8PGh%UtZkG&>B^J2 zQ6r!X5In$MZrH}X#wOy?(AFY$>{H1+S}^yKqtV)lVM_0h4q8|N*73|~LQRs%$KRGS z(>IZ7L`-X?Sy*pdH}nO6+(=$E+?EU7n8Kt1aZGQkK68HBooub>pRP-+$p3|mECyLLYFW#bB98AjVJ?Fr%ZZKz`Tja zivnZh9>&NJ{h9DrcO)eu^uVB6>#u6BV_`4LS<&NoVTC(>h&n;jkO zUdFxCcQaK;4pR)<^5_*4ja&C)pNwZ3+pQa(!2|q$gr2S=SJ$9P;qPC6=3|#jfOW&C z3i!DgYTvLvlhjoSu1J=FYc_Ky1)V4BYNcu?1=El&%H{N1c&PH6tJ&;B7hMfMylwwR!v0YP#din{`PP;5^HWJ5LpLsU6lmeeu1; zD+xo^sHN!O2NGfme%dh;S1KOO@W#Xi59Gq&2hOS3+oPC8&x?L4%HpRKS}w{}*>Ui)2`^R; z8f{QNv6K%5P7CDPvHHfKoV(ukzbKwM+}8{v7G^*FCPIL8ey~c>^hgS`Li3&8JwLW4 z-QJ$L*b@}X%ko`BR^tylAsfSq=~*t_P4ix1Om(_on9m?g1fponxNT096dg78mqP?Ir@xfan5bDI9|{Npi1SA$aeZ! z_J%`GJ_BN|r}yr}TrM|V46PsFJEprH{M$3M`-{|#AC()~v57V?Dpvax+_t51WFA)w zB^7?%8?!TNm}-oSKL$m4<`@-(C|CA0M(wc8Ofptfu9xQ<@4$)We2wRZ9l_LV7VX_Q zX$A%!zfDip|1FhjT80B4Rde)$ot1ebN^j)WD@0$^_Mi+$yR{LOf%{+OQpM!^glEO2 z?Lx5zgNb=lxz=;F)(Nfom#!BKof1sTh=G1HVsScs`$dr2SC?(5!cM!>klFE)uwwAS zrxS<039Ic|nKRqg%rb5@neKvfrHl9Qt8X%pivsYR%k))2lBEU$CO_#q#*zBwz8KX~ z=?^68x&)^<>1bR<;d?_EVG}faBjC`dsk%{LS4Ab}1xCg&8Ts zi{&dJJtNz;f|7HoD~C!?(28qgoPL%Pw202xh)d+YCWI-)qB2 zSYCR3>Xb6%_b|CN>~3#@e-YkwCaf<%qLF|wu4-vfq*aq@?n2>QaQ`V~!$zCEq^cPWJzTawPPj~)g0 z?!C==({hkoim1f^`@%Qzlv#(FDUz5Nni$C6o+k^`2Zh!TZWOn5^yJJ6_(+ z#2iUv&I81APLHi0r`axA%l_nuA?5x~$0595Xs*E}%`FvAv4!ENN>~-W{2J&X(VENG zTe^irjVfxh=AUeH&x4Bgp3rjC9uI#hUS=zAK#EQw$x{|(V(|C}aiKY7ou7_fH~NgZ zyqexrN^d&MT~*T&nXopfZKxAk-*j+?l_zfJuUB8+*jh-t?WwKQ*66m4w`qtw`NF+6 zH3d!roj*RsnkT^$dIyd9-%7YN$bBT`@v*fwX3nfG%liZr7QgXTmGK}9vgJ&z*HRAB z^Q&!N+fKZgc-y$x0WqmIG17dx4l2tej&bRS)`So2&rnro5)dL?lHT^u_tbW=C zPcNP!)8f(?$*prMFCT2p=uNXps6jH=*F@yG8;#4J? z88)NgatO|!S3R$HcL+K*>E?-&rB3Mpo)sWXmAOnOLCX@+*nV|^7^o&ifG#N?<3dT{f>Pv zAMPgph+4e%Rlp%5BxrR>LYC2o!%q)m`zaebUaOo}(-~b}C&CdrTH9Ul7sig0%0lPY z%DgwLZA!IRs|z!&s4V%(Mey0jZO~*;<3k*UH6RbHS3#|V7cFINQc^9ymyMi&?jFIz zy~3}#Mr#_~sqpd6W}eiVo2(5g{b9f)@tPGV0oMT^zX|D`*7%=(<4$G-k8V0LwX zyI21iqN^lIbr}Gw;{&X(g_w~iy7s{|h0k?e;mH|6JUdvB-;Z&OWDCVN!_HvPo9 zK4Hp8>t1eEZCtssuj9F2ZrsY+;YDm=REe}dGe}a;ER0fmLZN>HQD|mrcHuEUrQdr? zIJ;@RBr_(*5b~}@^TyfpRj73Gy)1KEVtf5<38t9cT_?hyh5AdB;eXsUNTm?u4$}&i znODxA;o|`>N)JoT`BW($Hq0pL&Ib-C3e9Kgvb%zLDzkR9DD6iDW-MU1Dt+_{XR}$& z*XG`8J551$BB}DqSLpkPgNIX(qxhZ~_IiZo*9#S@^W*^97J5zr<5EP?{^edSF{zNg zaE6SI&17crsagwSZ}kW=UWoT0i$Dp#+-$s&^Cfuj-;`npZU^C{HUl97fFNhe&Yjh5( zv%fnKs;-P5NeszMXxkhQJXjt)U?HHbpt5K-=?n3^$d7Snwv{Z)V|kM!bXx3QdYAc z+Zs1oiYx1kV>NF{KN2_uHuLuLe^^C>cr{V@FlyY zZ{NOI(c-;n=m>E&#nUj|q^d+rY&@AVAZ=vPCI>fOrA6=etolY; zfgnCwNPW8Ns?;nk8Rml@!;HDyn&1$en`%iz>N2xItQAE5myp@I zFa%eig8YBz0$?3eOAi$uOhuzwifWZ?lvhAVeA*YRl;=BYOImzV))%+NZfc{|EX`)0 zoq!as>cROKg*CW)%(hvJ!YPLBhLf49UEo_zPxkwMQwKk}K9`I-4f(ltbRkJmS9K8E zXuWJ1!Q;wYyom>M#ZzkV*DFx4Z7jUn@|OOUKGzu?x4VaabYh}r*YM52Js3i?;&Da8 zCWWXtPR7tI%uMk2@v@R;%_7MSL8^3|-+T&jH@dIsSe#M^^~pLrPTU!_PE&i-#74A- zLji1KLT{JVg^loo&WBxjc&SooX;p$CE&hUK;9w*F=U2q+wj8i2MQ@4}@OBgVZmeg5 zxjQcnZAr+oAkT!22A6!u#)3A%YuNl|Xyy<8vb$`1VGdL(L;qOSdt3g}IN_c>Lgy z2ofG_$Z@O)U|74!X|)1)df}%~ieMCG})z^SXt) zbXtRLT^82RrR+w~n7BTx2li}3RP6h13P#&lI={Rtb_ja{2jbB>k!0(;%o8Q3wpSJ6 zCb&CKD#|pfN{)zu<>4Im@1l`6E|3QHkF%42#vCEf`$8XZ8HhXuwv4{&3SlA^qx}?c z)iUBlhpfSVP+JX0YTTa2;Doeq7*j;>y$Ll%E0a$IDJdz_{4OkY*(+puu;lE-cC7jnZI(m$MZ&Ne+cloI*gu=Yg3SM@7}1d5|IxDD z5BeV-3$-4ILm+u~o)2$CadB|~+9Meek{@G#g>i6W02TxO{>P4$|L&LpS9(*&zBkyz zAqBDK(v&}5>4~t|I{$2J&rL|mT^n{MjR~bXJ`T(X{$Rm+M_f%o+@9C_w_seUu5P>@ zwLMyfmfT5^wiHX4k1Pf_NhoVQS#7b*w>DQl1Bex6km6$)apl^E zaGl387e~jGE?>{Gy;5lhOrbHd%cU9Sc{%|N&m4cd&{vwuwJ};lsJ|j{pl+}^d{miMH%j9ZD%Yb?ku49mhnY)X+vz!RL7UX5vKWsWWjrg>^OMJ#F8VK- z(pIq))uYDD+kzifw0<&}1l8oV?p(aLd_r+CS%iU%qGP>*BGb2>CM|YATqW0q+t&V- zR3%nhCBJV$OirFGr(w349_)U$+>SLGdHT`J+u(I#{$rAap}d;(W7ya{V`v$;La9P{ zycG%-X<7SLr++k1cij4p-G2Q}Zk21o+yom~%C0SAE_1_O?810uG-0kG{ z#fh*QIC-M$yG;_TdmJZXol$m$2V=nt8>o8YDE8t}Jo`*k6UxmZlqnu7vmi1rT|G=8 z#o(+&R<4tVC9uA!ceopM)G%$W6>!F)u z=%D~s{b6yPwPnJvA51QcsHy9WVBbUow$SDIM0X3-fSwl=i74Uz! z2j)Ff{z1CB0jw%H^!ZY@Tbni>ujO6GF~wa}s@MFK887b>Eh3N`3?}1Wz@lph9f#jJ zUMwIuD@3Z2r?~vtRjed=P|Y8@@LhA*)~BD$H*1WoH%BobK}~Z0ilfX=A6SbFN>KWj z5>=kjPSQTh@G!6DhKtDC?K5HX+Z~OE+~5G`^F4%+JqV7P zNrVNv1L64h(>D~TLy?ZV?oN~$Vqtn?P|mDFOK^ z#zs@tdx=3Xrl3+v$F9)SUE zFK6w}fi%%B9**=$BOB#s(^20F#CrPl(xq7AY zj$5gno28^&WEFNX`X2BP{zD@`G8xWUyQn{QHElkoGw#+UR8;gOe2uvBVnJBZQ9ssm z;6I%t-_3m;g8D6M4vZosr6)^f`O2{uxsrzbue#@wq_XntYpr!!<-7b#7}*$QH(v>1 z5SLhX2vl;lX7<_vgk`uoNx!I|83Y~5=6zqS*h~+9aIz%Mj zuN4w%uyxF1xtTsvcpKD`R5}48dKN>vi@jk3>4y-wcsW*hKYOi$otX<3#8Lz4C%?6i z-BrClX>^@%c#y=PV{@D=+6Ce`-)A7=d*07-zSm06@fuWT$_4II4{ZC{%M4!tHp@Le z&~1U+;s;`Ng7yduGRTiIXPAV{3Bm&=Ng-E}FPRttUAAE4mKl zKYx^as-Z)6zJf@nYhR(bG;eIoog@D3Gl5*FoAn_B3oqc=XT`$pl;5&X*SAEEJSV3u zoqt^v^}~aQog5>Cz!}T!L*$KnKmP4Cap@l6ElZv`P5+A3mp}UZoC!G+Wh`m%%jK*3 z5)&iCT8T$UyxUKOW?S!^u*{$ofiTCIoz#-F`}bf^?ioJUT4TQ--ag}Jj=`9I=_}R% z(`)9fb+D|+KPa@!{$szl$`Ho%MOdQ}E3U=2nasAlaYr>Bemk-yV5;1?Z1AV>y>Kl- z>d9Po=!}WicoS9c!6-|&G#$)gs9DeASnMWTtQUZf0>9~vu zCW>Bpa>rM%)z;k7GeMNQOt;=~xxzJra#25uxy7{Aq&^!P*@KPWmaAQ7k)M-(iND0W z$aJ*o*W586Yl6eREr)I6;rf{}jy`j(LX)!=3M*-wa(9pc`x27s-i6lyE zhTk0O%vYce+*&oB8_QlUjD&UA4fM1+x4c4r5`sGKX1P_fX^wN2|8Vp(iv4`~{L+%_ z_)Y2Hnp;+sv1eIA|6ISolBn`ZBFBL+TiPW0KAj)jJ?fajRr%sw5(5WZ3F;s~oEvsY z)P$~6s`ch%R*|a*U=CLdZ0)3SXxER{^TCtXiQCIu+iT4u$K8yk{w9a#upoxl#%;A~ zJw*>q{4QC~{l@?Y7sqqjH>#TQ-y?GTxj4k&d+vUN;AVSiTcB5M{nM+&3BN#Oo=q^M zOG)&4W-y+Hf?iaY9kpl7HWqB!@Ag?@dte}a_`&X2=C_+*!kRw{pTl@qY*inpm9qym zJlu?xJofzP*TQEZakvStvbc4%@@o^8rViONSkd=r0aw01e7kU1dg}dT*WKpVo8feI z8jk3h7$wIx(MDPz&5xOUFDpm9PeSN8{>aP+`r0Fd3h-#?EWUoS#LwQaFy{;Nu}by% zz=PJV&5Mntu4u@?`>ma&L4BwqEo+pnshu|SzZ@z*uy%z#El{`N+V$_0IcRvLlk&lKgmS+!YVI$4KmM?~SPh57F6uB# zN08}+M;zrpH(dt)RDUP40=GP_OJrKr$(}NA`a4%u6NED2H zTb-ZD@yVJsg0z3PzjSdkF{l{r26UUy#sSmv{5oz_@;X|U@a|hBIM7USK*o9bNy+JG zxT-SkxbDmYa%`J?F2|-etNIPOS9-IY&$Mej zva`jWf#a$_;jYt`lA zqVczAD$*VX_k6`?n_p1=ol@6yQY9%`Z*tPB1~9>}qxh(W5q&qmA2L$54U5*uYs{zU-i9Q)M{>&CyWk7vK0GO z#_DQ^r74|No7C&|tK51#ug7KY_UPL;^0ABDHB*pR`A0{hxTCQUU&CZoXxt}L|2Y}3|~p1 z;zF~Y5W3Y_Yvc5x2FHEy_Kn8`AVP>h) zwFh%_H2w%R1ucA3Yr-D*4_`o&jfx);24wn$J4rclg|ML&)e}~;N^=s#_prxwe$7Y% zI@)OFXAlk_2%TcDLZ#*fUR~kzfEqlY*e0Sboe06fAc*M0>IvQLt1Bffp!<@IKb=uG zMe!!e79x{o$`v{0dHdZnECBg%dcHOuj_w*&;Vw%wfmSr_l0egSao*51l1le=e^VW4rqTqB}~3M5dn>wj*G zBwO>sGDmHiOl!X=%HJZ&5z{z(fM(3HDYo?LVV0|u5&NE}*;nl%`I5H=ufm@kfr0=4 z6G3>$SB017OxHNWSjban*WAPJ({1yHT|7b0g|>=h`u2wBhNA-ojZ^Mktzw9+aqW(T zdwp;k4ei`TY*7#qhsyX%89G6Hyr1!)vo$DHUF7l7+d31HtNb9*jJ08|E2&Q%^LnDN$ zonNz=o*MSE(n8g^`sygul1(Q$z7O6LEnnI`&Kw`_WPt7&WILJ7qBeZj&&&?PuBv=OFVPl?+d!?OGm;ca04OHDQBB$>9|YJ zy>Db*A1(9uAt9G3-^f7xaGT^-$Gne4WO};ee7Tf7nJuXEFA{Rvq+OoY#oK}9vjc)| zooDp9%LS98>U6PJzcKAKLi}`FRhvTfcFUi8)Ku=t7tS|ZjXT*p67CZOVqqaFH;l^ex5_bEw7wwW<3vNY*!Y5F0z(eL8? zZC&|7juz?MrWzAv{9rRzeX}V!IgtZ48r8YL%CZ9|gbGxD)*szW|LHjD*+}f{kq4}; zfYl(#5w%?cG`95-&=joL<_^HLWHW&7-|Fa56^&&7ci)R3;?DPy3B>Bv56@naI_)2Z zt+^=%Xy9+9X^LxitJhg5$(&djI&$31m%Kwb}dvtlDX8aGr1;z`4ynj|OA zB<08&7z8CdoIzZBw{vU^b$G(?`s$3|3?FqKI2f$U(b`K_A6|Mt2cX% zoR5F1u#AlD6YG);a*H@}rN{lr^M4D1qr|h*pZq8pi0k70#FyM&l!NQX2TZO;Wzv~0 zJ-DyPi+vWeTfdet?|C{_Qm!V!AGLZr1%SfelA96n6!5>;r0%?*tNu#wC{-gpvHfnH zp?9x!p6skTxUmphly^aI@H*6k;$EYTJ1=`mkj|Hpok z|1%*cP^WB%yAoMmAHFL6B9&#RWjaW)E)Sw*#Z1u;N<0{tEy_$T{&;E z-*a){w2EDe-zJ>4hLW|Qm()BC9Lm`+WQaSE;RIM!W_Wj{RIMl z=KaO}{{CB8QOH80lVWb;PQqPQQM8}ZChuwP$i9F}aM`_#kk+`kI2=mB^ErD#ndiXu zUz9)E-qRCAe*KUF#gUOeLX+@dk3Hmb*!&G3Zj%OHcTghQAFa>k=H@mw26}n`yxNkl zMQ5W_ z=tcZRVxe&%>?U=FgCv4q{`~6h?w)USq5^p`A?8~4_N+&6?*NX#h`c-iq3xNtqd%tf zbaZqo1Q2~ubjZfsPvzZ@|Dwcbv+Z~(cMru?0%S}7zaED&l>zVEE1#kCe!LQ3c5OVibpWOXhf0_;Q&dd!?)Hrem}Km8KSXMP9S3-^wbsk?W{_W&x59W&xE;99HOKhqj+D?)#TDIg#~ zCFuNe#qO`>3ie~?9j8%y!yaAnq?(kDwszPHKAJ1cK+Lmkrk%51#z(vbY2ffozc$7H-$)hd>v+PjY?ksu1w6 zcd-oM`<0ZIdLrQ(_hZXAv;2Xk@53H*bkX$a$@2PfL|f^bER~=1R3@clc2zV!J=fk78cu=m;4?+@E-*y=ZD4#Ml>Xk z?pnS#Cf!vdH#hf#!pi!3(qzhZG-d`4{ut81H-0R%fEr?5ZfgI{MLnbV;ah5>JCanX zKE+fuV(Brm<2?-p>&57`t`U9e$<;t_^@)qEo=1XJq)kW~(fS$Ft?H!QYi{MEp`%|{ zM02e9CtPv~LyZRz~OB&>&=iK0cGZY3I0MDIe&jRWl*9^@ze|Pd$EG z1qL(QjQ0cV*bwa7G0-@R;P4%*O^0hAM&#Zz7v`2~zu$ zTe%~f-oFQQia&WsShbr)a@2lO3Q!x15w?WL&*(tsRBM^v@Q*Dg$jwz|n7Etn(X!of zb^?oz44yaD4uVl(1X9`Ru+(R>CX=74CT}#HyosSL-$TAacHe7CJJb%b2vg8Qx9T){ z5{zbP7t+X^UQiJBJ-(}b?OcmU;aNSOtznj@gmCQ=GMm8RNWE3CJVvU%$bB)3k9kFl ztnSPyY(AWX_@;UId}jh;Hw#~wcW$^CYs8@ugc8XDk0p9CZ;V*j^s68)A9UY`$W1RQ zQ0{!(lQEfU5F30~*I(vJ7cn87n5L+UddcK9Vz~6hM3?Ak!l0=Tu7j@SEZBYBGS^1# zRON1J80TztQOr`^qFkYyr(@&e&hQVZ&y>C>ec$(1j9+(9tFm;5xq*9ckH9w9+H{^3 z>J{-pD6<4rQJ6TBOl>)p>;2$+-?>u7$0v}}Wu;F1_`X}7Nr4(RlM~XvuC6@Y$#}QR z%peUUj`A_8n{XMi#~8nvUz#9*5HVYgF{Ai61&<@)rwC7*0HvIEw%aw5LCI&K8V1~P z;isYf=XZI}(_;ytp(IE46N>){<^GJ(=jzC&djog`UG}9YsGiAhCYoPrt84U1)3Kgy zzAckLn|8AUX}v|3g~lsM`LtdP z*_epXdp-LoM>6jH#l?`9dk4rJ05$`*r;4<}-5lmsb4KqLqYo0~)NF{AelZtFTm;)E;`Q6bwOdrlnvZ~XzJ=k!%uLvFKIap*;3-ke@?_GQ@u7@ z#hDzwn;JOt&y^%5w6kQz*ROv$DE9MIktcCBVjHvjaddzt$r-VneBJ%lFKiq=@@r2i zNx8WbIdUboKKoO$A4J)vhhPF#c55!-W7Bl#_bA&N<9o%uEY_Ibr>Po3CLZeBz9BuA zb7d-_`1Qq8@~!`;F>Nf zSU9ZVP3w~j3(QLwTi&_P*bmg?IDgSXe1DKGVz>UOX2 z`GEu#{sz;nlA|2qr0b$gIt|6sPCoSd);MniEgv16JM^_Qd-pu)opda}#Zhc5Yop9C z*uB^3hq=wTr<`GLb?2wekV9T97$bJ7*8atpGgkiBsfNrSfg#iNBdC`jx3QTQ0JEVV zBt*fUd;&aPG#({%P7M~c%Lxp;f63`df9TOW5o79v&fYqGoJG&^8vXa(`Fnr0dc#kM zcjm@EXu3*RIPSzNJ<$2RjvFQgzpUY3)V%1czJ+k-urEGl^O|RMwijwLWLt9;U6V9T zCNu>rY2Zrq)oM)JaI*={Lj>)Vc1ys#8)q0n&!|CpNjf{SLZE%ubjhvydRN+P***=# z#!RCpmC!8fpl>!%*GgH%LAFvraE5q7+bz$4FP_7?cH+0Lv@h^BUTOHv!ADlRGORky zRyqn= z78$!c3=!J`fSJn~2`r6vC(}$trt%6G#59CMmp%siUjd9A?;<5yNH z3VOxT*fs`kU#=)#%oo4jf7!LFQ-SyZb@cnY8U5*t0M;XPX5M>--b68XhS&Y=`i=aH zj)&8CbM~h%fL#a>oEBDAF>h(VeYLzR!C42y(x|E7{)zz1+FkNaXsu z8UN!VYSj;?xczrmQi1YlWXU`GGgDK%K-dhCH|#Nh4Yf)A0671f7qELzkdp>Z4i3K+ zHG||5PEVnCc8$cx2fJ-2KnW3%wc`sQfJ|?E&*nXB1v*U^*k|D3Fc7LqEH>;m-nBqEQ(t0ENS#9^Vapn-sZU?n9)lz@Ohv;S^0kidVBa4wDf-2sBKm(Xzf+y3kG11Q)7 z{qN2X5({Br1w9}j_w1B-Ug>^)l#smSKy?=cTpS!G*V$5h3#6GobuDLW)I_cl3#c&`+qn9U8kJ5;)wh`F_r{cLxH%k9akGlmW#~ld;sz6m-7$ z_+XG&Zm0}BB=26bZhEbcUbOeE0WiJ*j>Zc*2_OAU`4=gB`d#e4GzW|zXKD^E+v}hQ zAe2v-XQqqLgcCmySF!$|?A=)=^c<%^X!Vj&j7Hv}?#Uvd&Z(EDVZfQ$N5}Va_Nn3?g}wQkJjlxlxlX#g*HZ^Ka5EMR9+n?NAn#V1~&Z zOce9PW5ev6!~L>W_X_=UYFF>%i+ca{Mdc*nKhDO4iZZs~2NV|~`9^PJvjPN!03<0Q zsN$Y|k>i%FE86{ScGO&!=97Eb{d_^zdHTapNI4P(mBt@Ba)X+P=ta1WDE#tl+_gJA z@DjSPFkAxEPzdXElq}1-^||Lgd9y5!jk$N(qtzHWQQ?Y|#B{6fqv8F6)9Gj; z-iCpf7ncD820W-w|6k4iN3b7&`}e=U|NBrh03O-pe?JE~;Ps2({-^KXCVQAcarpo1 ze9S1b!1%vE8}fkp|JA9{->4n6R+(au9)KZ4A&N+%X}$cjBj9eE{|%0Ju+ke`3k;$6 zx+5Jqd0A!U*si?*e1zAqS4Fl@&G?782+#aI!1<1}yV`hvFEQSt??mBY0+A zSwnkJ4ppL(OkA`)^vK_^tx8)0SP38;NG0rW?wrK#CJ^Xz3=&Dpd`BlXaO_8HED6G;d~ zR1k9Y(iP}8rt_wZ{8jJwmy_)5q=JUV>u(VF4VPt|di4$P7|a77mV+C@mRaFn>#Ew98k~tAsvANW>CQAQt8l z`3}}d#x$L-+Cp`b*(W2fP;dJJ1{vGci7qIVb1udyVo+|YwAv}hg5M&3T4wSxhoe}+^ zYHKU2PJzTyZ3On$)B+U-4Vu#VP&GrHh{2TkkA!ll`^@Lf&jPC`MWUCz>#zGm;>MBQ zAfYfr+;+$7uW52R2T?Y@`@HYlrZi5u30=okkmt?LflIF)BeyGP<)72k5#dr`QIg5k zZ1cePxC#5Id$aFt+GPP*-|m)J^x}e2{_po?-`G=1 zUigaIDAJU)ZEq*y=$MC|w;*)*SvQr1(~eZt2H(%ZMBpr@Uw{kdXV#HRdH!WPT@^LG zoXU-dzLYwj>z$Ik_UppTm#@n@-uJsH?B176`5LX_@-uBe%0>?wmRd&(fbZ3*6+f)$ zJ9L5MPV48RxZe9II5PZx>x7r@%`koKRJ@BElS4=00J7(73E<;3avca%M2*$*53=9q z2`%9Isy;^-?!OCl3nf`e5CK7`qc-o5FbLtSgANjS*rAMuH;i#=d>rJM?e+DQd6b79 zG`-{sMIo@8Q#2;#QDB(@EVJ??9VnbcQUn1ya3}UU@75U93HqcMoZ**=EO;Z+e*KG_ z5R0MDb&Q&+=BS8xFXwlqIKTG%!|+Sp-|?sBXLHz?No*`=#^##Z5P@mw7+a zgxy+vh^D5dMvh|AbB7jF-2D^pclE8WdiI`N;$tN#(z?|>5=kKp(O(oa#se2C02RMy4CB}_Bd{^L2e z1d12JpzsRCK5(VwdvVwoEkKUumQ|ElC9feb zfI~6)rTB>x3KAAxQdBjm6GtMMWD8QTD6_EK)A1gNNHH07%bk&eG?E4x8i8JdN68or zTM0TcQBob_oDJev%0gyUZLe_ytqv3MpYq~6CX;9XZL%n3T$JksLP1>WbuvXkv@m>kci1ykxzR}CEeBMvGjLfl{> zL#^STpQ$~(@OrniF>c>G@_L^Gn%U_e{YB4wEpGa==)Udy>v^Ce@&iT*| zj?5DBfEKV#+~@nyFGjmVR_Ss7QPm_qzcviCOUHtE=+v!rMJ;+c!|EOG;}R zqD@woWmo(ND#_Eaf8v7MUj@l0mHIA%#xxyr+UkOZWX`0K?x!$jNgiqy z%;W$qpgyjGct0IHd!cC9r;r-NYUPp1vIvmmy(AozW4g!&xE*U-$9)?AHZZS;V0|G9 zp$%=N4gg4BDEF$iUAcj(FwP){N5w0iq2c2%WA!kIH^a(=cYQ&!E~m(O&OXL146-x1 z7{M?t4W;Y&d*!!C+j7!b@3~YgIujz%F!oCgcHYRfXT31&)p(__fqaJ?fa3q zylVUS+|pwJ*gc=;AaoXxi_YoV+r*~ci)B+@_|Gi?9mOWPj>lMdISh+8fO+IchIp{vsYgWZeRs_71`K zLe5sCVkJYHc8=R3gAx-1Qp3T42^~G1kOw;|jRG6WOfL^bAMop}p)7M=cgV zLSVJr^3e99`ft30$ur*rO5;=5{jP?$JJzYq9T)tHJ^WX?LS9!*sQGS+@K^164`U~7 zoJd806pY(X8soP7&b?%CBH^!nUUuS0Du`aWBWb7()moX`pa`z(z)H3f}eK zkXR_+sLG4Y z5Y|va z&w}?hJYLafjR)TLZ0Zy!xByV;Lvq2SpReiZJAV_Es@ibg_v;Y_8AYyPDK* zig_0_FQ2X7BAZ%4XH=4Pou{qXN}{q6FyCk6&%94#h}N>N13}xJ$Dt{dA?Q8_Z{vD4 zTU!Z}P+Np+XSCaYjcl1e&LACVZR z9~Z$OZ%W4~6%mBJ_B>tvI>(l3O!Iy?QswUH-kpQrP|`DAHu_rD_1!8%uvkp#eH{uK zq(B^AfV?0U8`3v^ZTl@PN7-=wfu0)3tiiL#LG_4!!sX^I&T@XjUo_^E9H!r^?Vfee&GnA9KwsSF979sOS|AW*5$ zB2%s;JFxmGB4J966$ z;b5e^qRLI!dWFdFC}y4O*7=xOp4aO<=elK`h6Cs2YZGt@4A#E-Dl5O?bPBk9=5?Pe zoqS*Bf7!H3J7xsg%=jA+)&#g@=j17>?tlTwv|ji;)n)nojtoSe?s@^hce%MFNLN#< zC(E;)4-Jq)x9Ixz`-rmQ6^81$UwnTWIx)w)*LnH4w2G>_n2&!f5c7Y)_;YmPm_svV z*;JGyKVW5Oy8AZ!JUgv-?qznoN?0ijvI(-7M0LUXQvi+9GscQ17463M3FM+Jwm0LX z-O52DZMT~Z9|Z-8o>0j8=gQf%vPm0F9 zna{NZZ6HO>MqFbnI)Mx!m0qSFbD&IU0P%X3A37?sA|UOcA>X@gqr)<#o}_pcagLE5 zfgVC}EL=|ljwnqk-YS~U`u=(z!nTv-Z~dHx_+a05sahn7#}Ex1y>vbIN9Qnal*q*T zqdpVEfesBO2`~R3pYTzwZC)!jzqxOq6pCE*85EFC1X`=yOoE38x6sblVxEWU(l1MAoBNg25sU<)&v`g@=jN9SQm zzqJ~Fj+2N;cvrsO*at(S2?P&TpiPzUTvB#l#14+iLR61ePD%3&-`@M~SEed}%H?-K zCieM=&Cv4_s-*7^=;wR&-)GJ2klTJ+?nV=0K^s;d1LVJV*HGcxoKn5-cRf1?WeyX} zd~dU^D9|R+e7~guHR~{xsmKmygJz>||KSUVM27}DZ{ka9Ylq}6n+2Y=p0A`l&V($aDr z$zElKl4fje(706>nJEdhy(%Py`-}ZBGv^_u{UIcgf#+efj&?@*`kU42iT8UshEd@; z_j$TGm{e^u(a>sxJVnp30psk1b$KaOv%JFl(9(d)v^j8J$3`6Z7GPZ)1Uc4FPNlkK z?=wVAZ?oF%1am@W?O37&EGk?;6t<3o<^Gh>tK;MG>3-hR!{C5kGg9Bo18|UsNvHm$ zlaOUbFlv0mGYxz3xn8v{{*!r> z|LY-n>^QwNwx`*Jie>hBJny4)1dMV?#j^8Z2>WNwAC0qH4=^q7URDmsGGia9StlEY z{v=HrOYw+c7A1@4Vkw@1g}iW?AN!XKbI=xFHrTq=okz7qZd+#fUvWlm8{I|Jg#bBH zNM~uK_tIHD|2+ut9{-`2aNoruH|59Snwg6DHB?7TNKK2}n5P;%BE zlSNtk)V;Uu=U8>UmtPiL>lru(UcuNvu9_Yu^~7!y75$ieS-QJYO{ql_*QT_!+)tU2$U;Z;<>Z?O z6$TM~j?zj7EGXGiN0LYv&+7ZPlId$U<)}|WM^AgUB6-7 zVsUKqs`Zi*l$!4LpS^cFzaNR{bUshv{b*E46ymNdws`*Bjv9m{hG(*WyHaa>6s<28 ztLfgh&~H3OO#800_t-Glm$9QBs%R&I<$j)9g+W0mL!;MG0Py(^#$8dnUZ(^g4R6)& zMAJWkfQYC&4(c<)3k`l_HaK(;fkZ7{X}beF5ThI_U;QOu(cwzpv}8 z-#)isNl``Jv^9Ok&3a)7Wn|z#50`u2Hu2e5!c+ppD{U8Y4?tPktooJx@Lp!p_!UV) zzmMH|p;h&sudT+&;%r{_`Qxe%w?e17whiASkLb(h*774W`KPVMhc7hCPu3JhXL zla51tEyj(jmv7z$x&kb-RCg2x2ZH3O3yqm7ChxgBCitB-*Mr;m=`s$GmMlzQid=E^ zMC71bGUZo~>TAz9DrqV$cvm%b)C}VbBLKsLtAnnL*Ah-Tw~l_YgI_9tB2M!$sdREK z5tRi~O{$BU;5A{s`vE_|;?uIDu+Z?=8*cM*#1Vg2Jf71@W#D1uY5P86tu$TgQ_z(t zY$Y}x6h4A6v9>qr;ME`Tri~_#Q%oqV#RfJ>5D|hPZJ^%I8iVAN|tyX8vk%i0Gt6z8( zv&#{?&zW9LBgd%-?eg(9I!s^ru313(Sla1V{}iMLY$~p489CCwl=k(qa6d^l3$i;w znTRR-c_+Tz<2g8=rpASB*L5B+RiyWEeJRh={TlY%J)N+A^I4|bHjQ2i#5L!1SbN-R zyCoJgj!CK%yQ~s`fEk?5nrP885?*lZOqu}1ite`)^}Ox17)j*MNFJ%aO#gPE zmRqa&(0%=NFqji|N7s4D&i|^b+7W`p%7C-OLy1&^q1jDWdwN)7L|t`XEz-}z#A$D@ zro24kPErsVm`_DThH~p&{C#rY%j>@S=@y>Y=raD(Xle1er;Lry!@fVXx2E%w8WJmE zu(I-&?9{tfW%S>2&%REmp+0Q~h07+$7cT#=ve1jew9eG6)aKdl-KPcvPGKCg0YG_X zD3p-C<-<%8KZb7e-QM_;&T(*G8M_;%1)3S$QU##=Xztk~djBXZ-_SPn(wupT5>Q^i zG~-Ayv0iUztFFsuuX11*AelGiP)KqEoE{-KN?Mw92{f>h0uUPBybpP zd6#~W8Y^f8=l}MwQ@=5TkvGFiKHO)FhknE}$huq> z8gPqrPet(w6_deS3XQDZqr)VzQ&V0MntoQjc?|C@?_pFGwrK2H| z7%+6gp0I43?{}|Lk8haT9^Ly$@8-+e?qAROBNmkZJAs;M^XgBcijFc;!b}ec1Y{}b zx#0IfF?3LY`P@AcFe~E2>x2U#11>R2&J;Sb(FKL}TgZBC&pz?>xU)S%LBx|E-&fib z_SK8CY=?T+-O%^jQ-q;b<=#=e6I-{;#Rqh-qF=HBSRsN!{{i zd~C9uzvUANYOT+a{YO9xz6D?Xz5MrvWIieVWQeNj7>&A9jqPE*Sob<~`8M{Q(m zBWl%B7QzrlF*{vn@?BV*%Yd=J01WYNZM&*d(REv9u*`PPmYFLIgia|qSjKX5Fon0VjE(&f=hmQS$6DD1f`oycnGJnd#_D@W-D0@M0PgKv|B5c(b(3J{O}Tk~ zSpJ=Y&OS)>Vd&rk4Rk-4f>{<6(ZLK%2ys&6w)s$FoaraKTw*M06L1`7{W58zl{Zaa zp`)E5FDxu8t_eO|3Mmjs04;QJE${PIVg}QXwZvMce75}%W##sFW+3|LbX4j}z_F%xRlg&rjdShV7WLYRIC9{el;x6+!O(}yZ25s|Lp#U#>O7Q#^Fg~F z-_(6qZg|N47)tw-&!PQr!^j@0)x2Y5bwq-HYWq;iN_&%6SB1{Q!J^it$7#b;zxc)B z_;yy7ayB6wE)0&vx`L8oZy^&a{qmgrf3<)GhZFsC6%*CBfFfL`14N;+hknobqTq-V z%JET{R$QqXZKc#>L{i_2l^*`)Ry~i!4(wXCBADZqfO@nDFxC0JMf8%e-+!3?1jlDL zM$RPEyscKem&RP$z|+4U%uyjv-Kocp6fCoKWwyWhq|s7Op#}IIqhbDzr+1!2@9`DQ z`6T^*Xq4a7n7^;_``&%>`hLd)ipHA4k|a|x$Oivw+AwG{HeFkBUN__mNfc?9mhUu| zcWs8~;HQb@(zg$Pcd%g(SY?B7f;y|_#GJ97RYM|)FaF+%jpko zu56spjXgQj7Px^*nTZ4844weq_&mqQoxJnz5_{QC;{O<})4d@rpC^0jeHxzLaD6D1 z_q&>UUjE*H-`?b2Y3Q4nvFdG14Y!vvVNjg-6|g>28EL+fM~H@kp3Ql4|5kpaK{@M z^7`W35Tq0t4Nu)K6D%Jt6&DjW+DATU+baOg(zc*P1j9%mt*oq|0#b22Nvo)%hR+#uuP%=8fQ*R?;b?*nX zR=Ll0cpUOcfK6R#2X0*z2N*fPHaq)4xQJz&Th6&TZ`$0vddg9C8_0hF!iP(N{>MlZA8xtKTBpk7Mma9+0N6Ifxk59PLR~^&ze>mjs z?Y`EXKnV~7X1{EOD4Ccj%mq`(U~Pd;BK?>G+-E_5KMW}7N0V6PIK`V6`QU;IMw(MomlcPwS|5YjtX=l(NT98n!~d)T}$0L=M~2*2Xc%-xcCiVlD;tx??9B%6u) zTOvP6)7s=8+M9zt({EdvnWNa8S-E>b%3=OoyGy_M&s8=#Ym1>8r(Hq2H?(aqIR?G# z+0;G`5bFltuON=3Ri^hQf^52wS?ipT5CMuznQQCq{~$D5x$21WE5)V^7-s(e2Z+%Q z#sHf-?KJEOM3^Hn;{eKD|LxQh_8s##w6_Q=-Elpv9Y$RjiM;>X|{WMuw-Zd<%FW0P;{2d%F1-;mM5mo1eYTUNAA7< zq8B+CwnLmw*47tly>E-c@RMld9Lq0{cD~F^Ooko$iNH*MA*^h11)-Cy2dDgCjCU{Q z?ZITML+33UhzR5k=efMZ0^n;;fu`GDwMNr@q3Avkgzj~pe+ddhAyB~#2@(oYxNu6x_ z-8?D!(n*4pVk(K7nlh1au~DgFEEAbY1!D2Rqp1j-lJb=H;TKj$cXR<#*}Z`YbLKt8 zQ28k2@);FQj$%j{bsS1xLvK4IwDcW*tUUO7Bl9Nt&C4YSk8L%Wyp zU7ZYv!})-v&d0(*(`jZbR6U!MGwK9oC)n90(VN}yfgE8 zCOlvq^D(bzavH-0G0N&^Gk2Ly{-_}k7yohQH z!6?vVVG&W{`)?a7Q+bxo&n)-%16Bw{0H^u87aq>9Xt_`CIC!ifGI>GajQ5eger2ZI zd5O{8LV@@R990uAYzVpwgTxHQ!qJS|x1O9QPTG^Nz+?L{@Wg362e>j?ya@eFoY8|e zq-rPAGU4C5>Dk^_WwyJ?b)mBc(598bQ`2Ycx#Z+iH>)0hZhx-py~N`9)yd!9G5wt* z`+7eh3uwkGD>D-z18?N4gOsFLWupcS8)>^xJprjfdt9qZ7gaB`pxZ|%j^OPerxfX zfO(kyP|(4=u>Cm_A2jr)+FXW$imJh}$v?+_@iPcn+E^)&axceX^%SnQ&I~~ql%k-k zsIc-k)vcp(W2cikw}Xxtr68G^hGKy%!@#(?{JBW90JJhwq+^qII4~#E>>_U@dTl9X zsi~c;L#*V^o-%PxH*&JDzrMJsqCp4t4WSy5i3(8;j^#hr!W-`KWLGz-}gfo3k|W4n2UlGqm(tM zfi~iAK|CaZ#7(UWzWQ!W%mAWg+A|b;NJAM}Qz!G{CNJwZ7*cK6eS(AP+UhP9hx|JF z0w*Aa(Og~ac)~l1Bm8q*tbQOtW6BD;#wZ?$$Aqt~TYVT>1u{vCgIc?Cr-0MKJI&vO zQVct!igC?u&LJje4@b0A&3J1b@x^E<#$4zJFM*I$pEf#zn4R=RiEIIT0rLI+U9#-yos7}u?#v|qX$i{BA{-ZRW zEb)k|)Y^JE*jtJ4(ImCpH1KdZgyjC7tz1M}4}MT&D=Aya0;}>C+VYtUEfP@ACMidz zi}*k8=GC2U*<{@P+>L0crA|QaVqOsBhGiS*{|X0&JjP^zC)^X8>}%L5u{?6)M2McZ z{k}tCv1_}Z)>^EVOG`_8sD0U!mGY(mKI^T$-8X+yX|)J~(US{}Qak1ap$?Sic~;m3j?5_NR2-iDy>pog3H|HjW@%#?Qb^?C#A6vW^A=c3UgL0r{@0V~1X@*Lkt$ ziM&>$dmjzCwSANqk}WqBm3jKO1!SG}+eLT$$^JDdSj{ z&LtIYNOUXr`6z43^KCaG!^ShY%Cq&3j{%#VpN*qgM6pjUVyI3gMxTyNZDl2Ke-1Q~ zm8Kes9U}M~+gxB4YSdLKD8(UwpC;}?&!V4vWTDLZ<_4vaI-kHyvc3JFSjyO0e!X+S zJrCBvK1zr8G+C*P*4EZNl*@*#=ZLyU|1Csca98@XGtiNucapm|AOc_L#zD!uwZ2bI zZM>CG(?Gbj$c_v~rJ|_|$%=b2QKivTfN?*&2!yc@MuK;8t88iNY}XI0dGD;0(`izn zv2yKy+Ti+-nPv6|1K+NKU0uwCmu6RYH8(fo)IE+Em*ok`n0s3IsFLwE_b&cwHkb5S zoZ6&?=J;Y2hC;QWOOw1j$07(U^IcWq_S@0-V_==EdJBCkHL?(G8CRoOZ#fqb$>EJr z(swdDFfK7OJ}$I(v%97^khHgEV2S`L;R+RX8Rs#kGJvG+pN?0GPfW2=hJbg4Q;a3g z6iNdByC6_D7p1Y93hbHzDN3MQ<^qfvs|;C;gBZV<^)dRR*C%SMDIDf2!jBx+Lt`&5 zGvhfyV{isQiG>p5{?ucT!bTc07r>{W0c>ZY+F$YvWb$0`x6ZLDf!RAhKq zY%G}j$!8P&mc&crSX!>JU+M@g`DJ??a8;2kQ;w($IyvZG(sz){U_0_YRs!mg29=<;W?&aOIq+#_LDVoqDyonrX zU{@rfcx)3llts=pci%MMh1pJNTwG;_L4aW_OnnUKzEEhH7On3P}& z0RiVc5)PrBwaLM#YoP4$nK*|+JF|+WV5&+&-`+)MTVBRoux^>UNSpG)I}8pgzSKyX zl63h#Wc-{sB<5^?Eui45^-lk1>z zvNDk*CkW(Gu787G9_oM~oUX00n)=dH zI%_U-eTk)`nP7+eFnD?!LM6n&Gl$HS-E3~1@5JQi)1i|YJ=C$z4H*C`?%6SJDIBJHMH9Q-2mf=og*m#2^egSSGd(i~)=g@g#p_R_1=W(Hx(2im|qg5<6(b>(eeh z&aB-{+@PTL&I0Ctw!1Yunz`Wo1D?}KYQ8<KEc(EDw}qiiF#g@vw+Mb^?*`}eJ~6D*=R(I#x$SOK@`~? z3-&L=&cP6B_=F9vtfH=II!BDCD(`w2eN92C;P@-e6t)FGImAi{t|aNw&b7tJQUVMF z_CxLgfO`eESgXA|MN>ZBAUUJ{!ObH#r3zIt3MyEku}X*CYcA=ccMOR%_;B&3&@rF9 zFlTs8D1tdl7nYQhck4Kf)U7~&g2p_(RSZ0g05mf-9Y&;aLk_a6D4^g;5|}U??g9tT+du#rl#_PS`VqwyDs9 zx(qknnR{`0hXFY0z`+gLq1lboQY~i2rL%^RvK@-1K)q10XiEw3tg{eU(!6m1>7i=6 zW1=L+wdHBt$fu6Y)!AOa(Wj@TNeDIHj4puZy#7Su3H z-wI=f#pFslMTPx+LWP859U@WEAdIudEK$y-axg()5$~o(%pm2>ivMIv0+Gx$HvFKZ zH;sB~mccbV$(Fh8zq#96KcL_lW2UZDqJ)vvx-tMl@JvV&<{`=7q!qS_Q8oN5{g^ah zUKO^DS?Tap5EdKGIl&y`z=T`mOf4x^9m6S`+>vm5YjzZYya~`T| zCS}e(Iu@J=Yhrv4h+(NHSxL<^6EB8DWx|O85#B<(c0Ia~(LV5JNgt+_6+~hiC(GT{AL+79;ON^|9yQTv;|rZxzQwpuzg{JK=*J57L>#lt4tGXUtB&!02jt%`AEe28?el|Xo-0=gtfXpETNd> zHlL7zlH;EU5tF-=pc$_<+scN`$@IF=aEy;fl0D%oL&{T%;?PF|PxqY+NDQk7?!&;x zB#Mp)SJbu!5P&M6>(J?PJGK$K-HK{#G}C8Fj5b4v{mDQbzbC%*(h3FIlVAOt0Ac+k zb>6(>G%y0jY|Pcf(XC60ZG|9Unn;v945Flmg1tU23wX>J{EP*GamX@;E1)J#Y-aPdTAtwmB+ zGXB>0tqmd`sK@-Imv+G)Td=~nJ9KbS#);e@7U^GSqo zk|}dCNTec^nXs{_evfRVk)hp+6kT9mrQ4+r4I3+p+Go(f$;+7=@wAnY95^;4_P(Vf zt7z>$FiFnFz*LZr+#F9JAUh8k3WUl1Fxn*+x{)4{kU8zGKX7JW8uBjE;Uf(-%UBwJj7X?HAI%Q0Tzx(;u&=*;WYdor zVhY(sMcpK=qSK#z91r9mB)3HlroK!8U?7rhEHyR0d5f^%PL%c?wVsr?hl`7@aO#O- z)|4(2QZ&&?rETysk9;;oUbUx`t|Y3)mL!dSbiCUeNYc{O**WE&ss0(bYA6jbjcaX| zlhBAdOLYo!dw5mp4{#)_fMNQzLQWbHP$;0v+TO;Vjp7pM(LX)eCdcG7HlZ=(ZwYFO zqM~*HNy|-UCWH?)G;&a0QFk2ZgX~~q(6uU~8J~2u%s|xc$dvQ9)}GF2%Hm)=j8;jC zKt50^Y>~V1mP|wqiO;o$7h^TES6eZGZM%62;SuW28lBiAHGfm@;^AHy+<(hSY4LJ+ zWV#;qmSqw+A(@2$ye8n~_0>TdQV~>Bq$u<{5$M=g?X;@n?V`c)1F4^PI960!jQlT#B16j6yUPg}sbaXm;SkNIJ7ZE*erc z)J_%MBmyVx1~wMlh*@thbQevkgw>@&$@tmcd@3Y9eCZ)_4ySyOd}uh-*vEMzCC`p? zj=P$ek+qX&nMx!G8JW0eu4C=t^hYn*03Fs?cStf( z)n?>jc=ZoKV1bdUs@n%Q=g=6BoUWg7*cP|;D!H9e#ww-8^cB@9jHtA>St-eCP+W%_ zlxW)=V48-G-p zs!K31Nkh`r!CqV)g+q2u_r^yf$U`xAXl}l#HYfVbf;jLgOWoXvzbNU;8|rOcRM}}< z(#^%!8yNjipj#s|=LGELC0107VR{McvYxx3o7)mFLzHq9%uF?O+PzK$s0+de$h?Lf z$H&l1&TwL4W57*PYm@%H%6>xpeZAo4&`M?^zORLD?cuxbd;-fd=QB?BRejXO$Fp{JCBe`0Nk z4TaIpb@ccBw8Q<`XjX>yF4?tlggp*n8InnONvM)wVydG_1gsx*O=iz zIj=NOdkQPdO^=7QNvLoox!H-%j7y9R4GI>dYKu#mZ>ocIbB%s!@_lmg6Q7WTtTOTU z$H=(hoTx6+W6I)d&n~fp9!auDAr*aF1-BLg#I@Dc8yg!D>GXBgD}m9@WI^4ReFNv< z$qEBbp$180EzU}ww||u((T0#BmE};c^-o3^1U(f%7u)jedb1Zp@(w~66kDfbDs3Gz zshBIPTh)WRRN}lK#e*sOO+rCL_z-4dCRt%ZaY^_C&ek$4&|z_8C~MXEO_l8Dq4ckn z!fsl^$y7qYV3MQ^wU&%W{yrgJmu_*)t(H1rdCyv6zL?7RE22q z5ci~TuguJ0qmJFQ2+%lo(SFBrz|Z3}^~2k*2ufK1i*BP3{x#nMGQvb{V&OzYKyEnO zeKAF!q2wphyz%iC@u%?>UE)@2LGF{$JeIRr+E3e(?iMvLLqet~NF|vI3k^6)nT8C6 zF{)(kF9jJzp-l*QF0`6vc^ACPpICNt7weJ?t*pAuBpW`>Mly0k3$yG^{E|=(rl=ao zJ+lfE46MRb;zeRyYIt(afM^%Yfbt9zX>9c6%MBNT5=&96$IF~>%?(@70&}LHP@H(M zJb#10=K?paMIt^8YV>+Jg@eM|m{w<2PG5qCh z77&DJEC#Jom&H7@TwCBN24)-^+Q=e!SY&KxjFAZA_n8P`rN8rrDTJ^CR70!Six%E(j@GB7S+NNmJA zEUoX?nbm4^hu*mX?0^te;U)wjC#p2|WR5u8jV)%J;NkmRVaP{yp=qWFNQE3B!TK8( zyrg|-Nhae6p4mpuTY1Y8$Ho#9+V_p1( z26)UY`=bLN#5x_&=%q2mppmg}s8z}dcEhblr@^rZW#oIAJ5rU#LZnH-@tNTU6v+!T zb>pn~n=Re!2!i4L=_JO3)#qYCD1W)wTcQMF5S<)J8!1-O_9!#L#OWVG6S;p_sn3u=!T>Fgqc4-ip=I$+ z#wMBKYh*2}IIKV43?vvO91QdAiW_Ioo8K#VSY;@*ZpT&hc$%a!?fx!GwADQhW+W^WNc z+mdL8$Hm>OrAw1|ebGf!Ijp2COiU;OXele$bZKeRAP?$tN#QO&W1%CJ(?jx zF6vi2pe**p0Wwn>os?=_J(`K;Hk|`;I=W}yw-KUbF)Ldq8`eTz3+zr?)g?EB9y9_0 zu{5X|zTCBUr-J)AUKJw?D>y<$72)O_D>n@5#q9seN_~DWJLv_0jg}WSDwCWTyO()n z3qkeQw>CHC>EziaJT)ff_^%f5Bzrmm@gJ82{MRLcmH0EOs-%IfJzrSi7H9kC8=OPO z$cMY=W-YKHids}uNaeFbhlr}8HuMB_W_30=V2~nII?muTVlK6})>HPA0xjZ)D+uj7 z(5}8!Jl!Kk%E`?90Z!A&eyZTCz;yQHsYVVwY~ykQB>_rN`G2gvRa{%k_Xk?Tin~K` zC|=x)yA^kLCwK}R+@ZL;7A;UL5GYb8?oM!m1b64A=luTn`99n{&1Yw3&+M_a)_0la zRMcF}Lp;-j>-n_jhqjBVi=zlHCm2Z#${VD5QIqla68tV+gfCAxBxArNPd6~?0g ztjlu$7;RLTQ3}%#!NQ4MHyGYo<7@k#?LnQC-5_!+a!lWFgZ}xFm1~ZE`2Z0x&g**& zSj^Mc&Kf;gempSMh5E#sqx~Q`MX3DLSUMKP?^?2S_iLg=iBVys>{3LuU?60zpjJg$ z=8mNfFvDkg=2u;`bfWtC)plDW9HSQ~{T<(T&Du_1thEh$0oQI#exw|m&r_$^O zdlBg6m_-BwzI+C$dheRoaX4c^(qPcc;Od55WNV49b?sZ^jn+U{mi2~qE#wie^7&x{ zDN)1^NGZ=_6z@OZk7zF+D3wVph#?r-8XLH|kkgC>!5=!NvyB`I+oZfly;b(ZV9Yl)CmK z5g;lfO*=_1|M=)=p8`{9JVm{f2)XE0QvYci03|=kB-`dh*oy@(&sLxe54t@&Q<5R? z!H>mSXHbGpu`n&ll-U=SJEsaljjX_NbU7MTL68J*5f=^4udN7VuJezXd%x!ok^-1X zBM>{seXPtZ%6TmM96K=ikGuPR?4oGyx|XjDfo=hci+8zhN#SSLYxJTC%SI|AWk%gk zG4?FA=9@zbJ05g+B$Sk7oSGEfUleM4kM^7dgvoY~yco2K7V>m*S&!E0!Q<&1t9~?k ziM;r7c)k#cc~>%2CTC2Q+pQ(}FwOrIuaCn$QV^zsf6hA~c9IPuHDzNVvHrd!L@>(p z8!}=yRy)IkhnGVLk`LKzo7l5Pnd5w=w_+NrUUM{S8!2f>_hsI<&p0@(gLDXQf<<$)|U&Rj@+TPey{jfq|95I(p2EU9ph@L@RU2Q{0L4j+ch>?dNkmRFZ z@Zq2SIR@f7jzINIxxStEI-1QS*4@Jv{t~e{t3*-nR(yZcaSLj$liHGE zb>PsueHSQYf`UHvQRj}1cG@~&D%tw{*f;fdR3F^bq`X1)N2+Y+>^5qebyHLzV0UM1 z5SlSu{Dg<45nZdB((EwMJeJn)brPJkqu8%W9p^dUe2E=y4?9pmg|fS$D_{UMp1Qj~ z1iom1_{)Qt`xPrV9h?*OqVut=91EIi+M7WE;_CZFw`PO;_M$$fy5-+%iG;e{xGpwP zI3G$XyK0)6j!wlB3|nmnd$7_MF8XLcCY z=v^RGNh_ZGcNH7of%oyzHk~4BYEXdmIjvmx)9jU5NOTd8EC&fear+2m7s2U*f%7W< z#`93LXqDlQHpv#{w8$ocX|e;mIwl7*TWGLj0v}as+X^oyR<0IvbP6ZSuywt{kfc*h z0H>L@hi#Nvi6_tO9Fj0|bdtkOy5eG~uiK<=UUJ7X(^49Mn!f?S6GJ`&eJhD8CWhcQ z_i>fudt$PI($OBX-s&?KB9L<$;bypVOS^~)ipK6?4_SipL`YEWT<2xc-GS>skT@?N zGr+iZVUn{#Sx%q92!Y@oH}?d2e&^!>sp8KG*Q!rk$}W`XuyC9i>?F&1T^l3s-O~|- z#?-uC5ysM=9EEKi-5d?|1 z`*hbqASZl(--~qq9vX{qtlfGZib^8n5AvUwjoo`!+Jyz3<$oOJbUDUNcC^VP;B%^s zi z#ZLmUKD5;+3ww48C*EzeLm>fyeJgGPt%1v4oJ&UyI9Zia6`v)0MerZqutiu(Njw*{ zeSvN36yjn2q+D72eYM9etu&$LaFr*X&XVN%i}1@LO0Iu!YDl}6ToFg!V5V8dQd=u;;-<)5trKNB02J77G_eru~f^U}NXgBInlk~GnNUnPE} zG+cw8APdzr7M*S>h@gY(%L3%)vLf@5-c$oVDrG9cN=Bg%*>n#;{WqNxlUCMqu~MEt zd>?9gc|hZf?M=CQ$ccS6P)l0hcM3}e`XPxlut$#mH_{?kI}m+cbv;1UTT<-7N8>EXG6*H*<`D{L?fRW8D)|L5TkuiSoge3mg_Xr; zakIdO?g`f~?)NK2t!Ybw`MmPk9eXndeby!IVi;v=dkzv= zZa#Ql#;95EKr@AhKI=@8nve?FmI=kJMZh>(-t`h-h`wakY6=M8vPx_7YEEqw#sz7`KuGdo@ceCE*S{ry!G!YAnN z!MTvQ7o{vL z_`nC%RDzq19|t4vV5CV-S1TTPgWP=|<+3L){jUD*vr|t+L7~j$mP|yed95Zlr7iTL zcpM<1unQuY8JS$Tu@_KcB;B(;bm2?4%yK)t9k9hlprVeJ(it6{b)!|&(ekp)E4j+b zAbAeD@5g>yyb2X0i&t|hsWm2ay8fdJ)VaaRZ@oXm+x_)3(zjWAj!r5eR3>G8686c2 z6$eAfad_(>+?4Zul?n{dW6;yD;w}C5mkec_$WDjUf ze*Ofi*xAX+)$LY-z{WQXk;V3>3m|xe7E|!M+FD;?oqU2A((I(_VgbYPYp<*U^Ekm%(mFR-(dqYDe!|N}-@6#jnA?Y5=z57u#hOx> zF6ALA1yeXlE~1~H&F9stud7wxRTn?VdRr!-p)*>~6f?rZgb?RubdOXv%2Et8b;g$& zH+rGehXYhybaJMBbr=vGh4bcBqGijkG`G^dBuF(#4BV*>w~B?h{n{P*s44|vo$3*^F>jzEmU3*c+{|)uUT04Ly6ghbP%*T*T=K~gU zL@%LDZHU^ugE6bHB6$7=;aiZ`QN-|Y~o3~wL=o+q^5tyF#KDk ze__XcA2deP?sJUzU#Dd}1T_wO?rkzMG858o;hil>V_E8T+QN4KHz;zmSRUoZMaSR| zMBzbf7+44N-2&-WccJ>}|5Y#yy;UbXcz3E^?kk*-SIIKmZF)+*KO$L?ox>Qd?Ku;8 z@$la~|C%YR{Mg^OJvG@L4$8f5#qBKzHL&X@PV zn1A=rKQROrO4C0PPzekJpRUr4ngvBfwmja<3JeI`JUjt!j*Yqkp8DfRX%heJm+%Dq z6bnp5n}WZCtUrVET69Sr3z;fqY9F|!8?tl)s~pFb_!CCHnO}C~b zw$v!G5sT~JD^n@Xecj99VU$iQpSB}M`^lgE-~F&_NQ=|$TX!Y~Zw=&!6)NV05P?AbUC6aDvWDxu^6+93fqkbDUZ zcyOQ9+sznu3Vzph5e743;SV#p(#t5pJTM#_@{GB*c$x0|e{TZa9X3LCV`1;(4yI+2 z;1AVC?adt>j}rNR@ZJ<2kEkn9O$K51Bj)~hu=vWTmSu6so41SjE~Uk zP|!szS1wf$g-K=vm-4iLMCf~l=jnaXDl^fV&#GJA@uZ+26uRw|mjH9?Q2ek+UcHi+ z>&>W@31Ut@MB(G|@LJ;7E!$z0@0he>nQjL{LGP(WFkP_zcJZrgEoeT_=mh*2uh_uw z{Eg<4!aw&$^i2*9ywgZ7dOsW+A0LN-SA{8D{hVb)ZUW8$gDeT5eoG|Tz<&B`r~uc9 zQZR~$=fYObU_BR<{^0FJ#~bfEU%@ zS$TCry>#;{vGZyC1>`$AHIN)iVi$!`Uq9)%Wdu)M{z%HEkGW6FYnS~lQj@LPx zJwE=+LP9d08{2sO0_L%cxPbIjBJvv6XqoEm9&Gmk2B48wa3Tc?IwpF!XDBvbMuv{z zC(X%a5uC&^vx+T0j?K<9*qZO-T&jo*!|Ka~svr}O>ik6P&&~0#k8?^$bLim+OaSZV zsmZ1C3hOVa@;Bl0fiKs`KUi{SYpHX%Ml`J1KaRPA>uZu2plhx6o!FQAy4=AcS5D;N zINb4uEW3ZyTRr4KvT%O8yLQ3n(814P>-YoTcsj8#8&6jWZOlQqfR{bs_YypENrrO( zHMV6aoV%Re;8P*P`ntw2@(t3qmqdqgEhAkn)^d6NyV1}hKpMx#MivNk;lLBsmQ3ZM z?<-?vWQ$BjXb+ipgiLa8@+E&g$eAtmeZ%mEbg9{QJhH#qaG*^bk~vH`4p8gk9|+!# za|@G|!Mm`)(df1naxJK}ABKNDYo_nE|eB0f&)9YLX$fx;K%d|dElL`U}A#ip0A zZ1n`{tz`B5Mn8g)J9`(jT*o;zC4EM-_Uek-m($537Up#t%jrnT=sVQ3`*WC|e;Jws z_=s#cE5OA)x*nNPEPyEajw_zfD4=P1ZHo6ZD(Z9Hx>(r2}z8owg^=q%(Co-oeJo*odt4KQd9gkQ|UG?oR0kEtr<-R}Sg`3SPIn#j-` zHxJ8aS}K12DWkSxs#;y8;l_O7@(f~-5cqUx>eds+d$va=WF6CWKE&MK0@mg!!1`#; zs;dKbaS6f7&dLyO#cJhQ!7OjKdkA;bD(;F zuj=NVrrD*RoQ95G$@ ze#R@8ulrYHE+RKZ{;m7o>}hLXArdW1FE_jSih&+ZKVu}d0_PRGZZ*Vn{_!-?GtwAP z?7H6dAu2*YA=_Sz**Fp)#X1VN!7}r*vcmtgxvzau{=?7DMxU8Wx?X($uq|p1% zvhx{b`O0Q={klp^E2X7vUt2wQ$NVe158X1;je*L@>Ts63!t5<6IX?ctxPWC&|9F0~ zN9*J0KS9!Gf9R-Ke77J)JYlmF(g~8^9Nkdl-^4tl(HNoJJyHSemh`xD%ocXpSVo7H zZ0nX>u9%nEIjYFL!2mf{u>Hf*bNWHd)#ac3DaZjnvNx$`~qM5;o1Ea6}k zN00j`F7>XO2}~u(9yJv(RwU`xN4(XfIOzh;P!Xm`e4lq4N_+LETHU$AqBvlSh3)Uc zzFLQH8YPU6Q7pEY0Z~B$`1AoB+&9T#vV_BCAD553+CO_JmuMzAc}0X! znJ0fp%3-zbzCgkq%VPFkw5ZEZT<4^r_yoc@S!-yY`ueg+_Qv z%8@Y*2afd`!TNW#+95L2*!>xHv%s5?u8XY4*bt!pSF{*AF8BKEzCZ64lWW`Tq^IZR z?e9l@{byJZiF2KOcr&^;r($gQpRbdVUYb00zsaq!cY+@>DFY9~1;lPg3t#S_k}yIe zcZiiDu0`*60k;*?9O5F2vFZ|^yW(_X0HdjjO7v(XL}W7 zo>eIc1=F02%zmxSY8Y9e4VpF!o^{dkbnCf_0$`xWl@s96O-zc6f@w+EYpj1SWTpx+ z$j}N45|AY45#y>_kLQv`s~Gj+!4WTq{x?f{ajxbHsrOGi7~{%=Q5dUOeNrbCl}nnl zdHle|EQIS((q?HQ&VHA7W7w%v04S{>xeCP|89KHU3Vl{(#iY1oxCda&+QZ(?qb)BZ zMSz)W)j58QlU^tp$71WJuP<*{b|HoZ4Y#gu0b5^T0p8zL93w4D?0YQI1OW}MMk$9Q z8*en5?A&UWuk;Y~P$p{$xh!>t;__Rq@)pIn;@X?X!TV#(jiX(7dq~giuR8-pnc)YM z9dKV*Cap*$n8Rz(>Y_Qz4fhzbR#DUx5CfO|_6!+e8lt_Dts{1GXe{0b4L~Jwpb9)QQZ%_G?Lh(JY-9%hdm;h6NRP@JI?%uX^ z8F90sb4FtHQv^mDk0(NnUQveH8QEd{FHeXtPvbvyzu8*$Trj0Il{I*@ilKp=ek|h_ z!9UeTS8G7=N!D!76Qep|_r_BmMk$UsyV!t8Z4SkCGLbB5c+?ng$x9Ls<@~10@YwB* zNm-g!PNFJG{&STecas8X;dpNiX~{;^jg9<6K8>#QEd zuw9L`N1um6pEQl1pP87u9XnURBin)(#@6+?F}{}kG@W2_qm*EV%anvYpQ`q_`5@Z1 z9Y@%Czy{vB=9vv#n%{RLi_zFUh()6vR~nCwb;Qgzv+Z~tFBZv_&E@IUP!C-GAjYYR zBc3ucPOYUpsP~PK?;IN6?0ca&5blNegNOOTkaNu?KH~$!ZeJ4QH6=CeJs0fj8Hxca zj(7t~znsZaK__juc$R+v)vOG{7#gj@pb9T<0c?wDVg<@3c=P3Sn}zN4c)3Bq?RYaM zZaVoD9wLYGu`nZtcq%ru6!OyEsr7RBn6px|^P)S?-*CAUCL6zhLPCUE zhVhddji%=fP3J!olT&gLL<~p%7K{XbEH-e->kc1cgGP*~Iy{)5?x+9O{%3;I99VcZ z*CB0+@5OWT6=~XGYfVwLry5nL)UauWq?xw2G3h>2oggjEqNEeoMYL<|xAmlUEbL1) z#VtmL)jiytVpzBCrx}oEU{x%lTx>lB3h0Zr=!4k_j9vIVyTMEkYgC;{S$#GKiSj{w zbHfRetyDXd%uq9fAuN^n;cPXlee7{Bw2$r>j(Mwrh`fbF>$z3C3dFRIN7Ite# z8>vD`I>^U)V5f-xapAixqUAq0ghr21@wsFdLy>dKE>4U81?-v@Lx zBrF1E*9QWkQBbbuPWE|s#XuJ3j&GusV;KBQJVM^Es9jCedJ|!@XX4KUQ%M(!=9|p6 zeGtOkOv1Y87Yq#;<=1J8r(sz*ob&HR4=IN}o-Q(!rrA*VdWA@=P+KP!9Ot$iik*PP zB-if$1cLtw&4|xhd+FL0y}7D;V!YPrS_VCQe%HR;NGkfNA*Qb+Y?Va z=5?%FbY@{J8s>v!Wf?Vf%$6S9Sljb_thv^8;)C^J&aGkinB7q9RBHN|{UW%u$V!eN z?EV~by~E6Aa>T+c#7`E9T+V0&xZfRag?ko>v9rfxvVNSrTXh0P^u|&XVBCdA%tlsL z8e-8+MklOHAP9Kw%mUC;m*{rl0y`JUXA&nH+<=ExbPmqBqu;)?JL`z_Zb?hE6>`ab zIj*GpeZL;0+)gSbf9$dtsAdSdA5t8?(e}PcaP?#3WBM0y$=Le^<=feuy)JCdDxC17 z>=Hi`o}n(BH})6!<~MA+wIM1!K9sB1*~L=7Cn;O@jrg_Jbcz}l71zvuWf=@kSKhB0Yxpc ztu5%NnFIo0iB4H=cqr1_bgtdkTUm{;xb*W6ELLc%OK%nQ1BGnOs1`C+1Rp){+EHlZ zi01*rJ3RE_$IZ_&nYjR{BJsu$u&Yb7&j`otW1@l!@HB=}ul4DQ^69X&fult}<;&0k zhVToxysjO_obYu|QYhf=R`KC&P@|r<4M$2|Zhl46bB*x}#^DNg z<7pCeZCh<)ePv~tfV;zN1v z#-{5!jFGz@Z@Lb$9PYA$jUx6$66%Npu`J|h?XS|h!1d)BKLTo1S8MDwg=aSY6nj6f~gLqzn6waTv8CEBguWR)jf9*2R@3b zZ${4II7j`d1inoEqOnG_l4an&V%5Z z@nI){Mw@P+`(GL_%ddYiaX1~r$jwVcmb;B5v8MA&;0w;yPmJH1Kcgx0_=vXP9;ztI zQ5HRM&rrYcNC)8wJ$@WoA)Rncax&Ur)1!PZ-i$&3*P;Ro&fd|Ps=M>t0q6$wrZ2Vo z`I`Wi-xm#(B&;*c8!9PP@T+qVv!bexMVboZvQK zi4H-ltG_Zu1^#~2FCaEql>CYBH&)TX96MjUI7KC1n>4Et1%6NzIsadQZe`ywUnF3p ztwut?b7HT|7Z-cu&(e?N%;mQ^RbKo{4N#BYjebMkKw(jDmt|it?w{|w4SCiNIitp> ze>-@!-V?0m4IRNrdG+<$-tB?Z!uhuzeb)VxK`+r-3vmW~ z(ggZ5J|HK`y(_B?+K&OSMQ_f$9R3G5BT_5T6mbaF|WdRnt9D>>=u5oMKeq4^fB<>Msu^j|P^iO25K!gukQGKq&Pn=z1}Exu5UF6pJk@fhRl>0bVQZ1oZ`q z*~T;$!2~7#IJZ<)+B-jrjPCw8t3VCF(AZW|N%pLq-fsQc4)(kk7EcQ(t))%6rf>^5k8H@ResZvxc%7vm#im7uqxuT0e_!q@s-`f|-%kMtm&)_}4$gjFFn;>o?*pCs~!XW-Zg*?JChG!Eo&DYUGHX{syVtI4KJu02=O!4?~e z_E%rAt|_H{cyjVGmEP&Go9n&e+8gKV>r3cmS>4!ZF<%SmdfZ`$!C+LAxo8rQHnTXO zQhGPttFo(#Pw>XCp3&jj1H_PVv6mi`=ks~r3+V6uejJJCQHW7hLJi~4MsI|HzCJP) z2h9D;|Eow#E=XBA^6Faa@_+E^UkD@l^#QJ)`Y?Qs;Cp5F`u{X<>nXN)+!LDrUvza4 z?pM-0<>ZVk|7p;ko#3`1cGJ!}4jl2){-z|Bpp$N&$>17o_;~+`fdld1BLON*skDPj zSz8kM82q?%GHjKV2O!a!t%*Jtf-(p%?AJXSC)!(4`M)hNIgmXyFm?^`r1jF^$#!P( zLsl2K$>(w2bz3)nSD)raMG3ycew}El-*|n^iMAEO?eTZ#{}Tltgg_CaLK5ElFd_?W zoQyKxb!t9QC7YIIY>BM0!hIR6cMjinCGwH^ndgk_wM8Qg|0==0et_%6^f~(fZqrYB zd%ryL?+7p=;9`3%Y}%o3Hp?9)>Nq3_Pzw_*#rt=vPJ`YRI=|n@QB1NV>h~}SL!dX0 zB@U;OPby-Z-g7EVIRFI|j=#y_n)802@&);?F7p=>W+;g1orMxpZYQknR|!XdR@q>K zaNMf4L#&%0I&1KaB@tpN-oKf?Zr6j<_?k>(%>rhS#(!ojp<3yPeJk)`g1_ce9HG#8 zC}<-Q(^W*t2ksjEHlCZ5DsMgKOQ8_uLp9-MpU>eb5H&v|E;Rv zJNI%jvaj=j?|y;g(a1CT2EQNU#`6zo3J=e1j+jQOUA#?%>qEx38_!}Xk^fGM>u2~q zlEY=hr*cR``GneU?Ijt^$~i|&My5S7hHVqf%F3fc45LIp*hahmuo5Xnoi&CnGZ}{| z1!F?fQs*XjlX|yE9|QgFTKio=$^zN#qa3duiI|vCoRsDT)4OcP7;OQuH#Cx3_*&^l zUWumh{1%2WjD{&r)Y6l3J((2h)Ph??8iUrj3Gh5Q859_@6?gV2#7gQtvDpc@PP~iy zgT1=6MYjD>yMb@|W8tchcr1F}Y}Ta>E}=mC%X%VQ`R14&TFjmBS}AJ8tqe82X4J{~ z?HuWz=&_6|$2THrUsu^<-9BLbSadA%sb+`WJdBpdX}`!4BF+nBc0uV?2ab=fz@b>^ zQPSx(ZoG$(WlpJ4Z4MxKZqThv=o5i)9=qe>PoZDZFbZy$*_%a{t?WEKRPmbSwU6~a zJ(x9uoD7erq4@^0*Q#u@w!byU?)r)z)6VRRwjz`*bHhC!Zxchmo#9(0=e^Lf0v{C< z@-JHDDFb@qU4uU;3I7tz#|_~Bospia=Hb6o39Pr3WLR04ROKrR_w#zT{;`R##Be8u z-8+HyHq*rW12t9&scboAwpc;ZXLO_K%*BqeKD-19qVos={H^Jvs}1pd`?M(YNnUQT zx77v?60O`~U*4VVc{Al$7`SKgar5qB!Yn0{RW_i1FXk~3xXvw-6B;@A(I|(RIQIP; z8xZ!xs14_HiG6iy#vtbhRigG3VQZ?jTYuDi zhn#L62X+*3qDa1OnFRU+wqD!gdKwM4K5pGWe)h=3_8)aU>@WkhoVRo{0v`xZjB{1d zi#s3VUQRHx`RT|wwYbh}?-It18`TI>{o!|F{>?nizMLp09*@JM*3HV#z0|cAa~FR~ znIh&nz%bY(cClsSw?B^|PJP*rz7L1!3_z5dTT@5J1_8fi*~rk4 zMSf~;&(_nksmaP$LPA1Z{54hI$<6%S9Ab#LM5Gx}eSLjcSXdJ6)y)m1poi__Ah8A9 z;Gv+P03I)?rX~)~IGC%b#P@DgeE&`?76d0mrDbI#;p!$PYsvsp++1a4<++C0Om*bKprD}p`}<_rsJ@#DR%mrKOWi#1bX{C|`V$uy002k` zN4a<uarM-6Srp`yE~rm(z1+6E{KQxP9?rr1W35ya}(DEhLDS+)dc#ZdNbxpyj58W~3K+K**4V zTe!du4Haz|ok=;uS^g)nuBWd>m-{CjYG7!$i~sI%YE%179Q{bggM%2;sp#V$ zKpoPzqyF)ic|I|34V&5ivd$UIz>UuEhpvu+&rly?K0KWEgX_BLQHNVAiv(t#hq7#n z)*FrVzS7nkQOz@;^6ne$EkK?Rba&ng(`j+h&}Rpd&Juao!;oKzVbCjL$a%V{b@TPP zIf>!mbVSh z)h=J%l#(+COPRi7CZET^XK$^8KXXRpbUFdY-iu86fv4>eu0t(>mp!?t3qs5G)+Xm0 zHfgj0XSi!CTz&6)JVVq!n%8cO+`T-lj1#tzwxnILw;y#&14_mN?#s!|p)_K*SLDNc z*P}?uF=F@G`8&e5`3Z-l?}twSrtdAtqNMzQKw=BHy$!=7?DUjlS6D#cE{CvfBS&xe zY;^}Kcd{r6LBU43B~ce-Svw#@#30Yf##Co2ub_*iCwomPWvdmk=fQ&I-r?WEI$%E-#1zJK3g zd?Iwxk(`wUa^D%6oK%-qKR-Xm!NrBULE^j*YiMjtXEi9ZTUuW?b#^{pSkMIm+wn*E zcNZ5I+uGV{YHCuZa&mHtim20vc{n)KG&C$`w+)*e^_-oZRaFxPw)7gUN1L6N1qB7G zBe?oIj9uK^+04V{ySc%wjwnb;Ndx!K-g5NAlP(5ytwm>THMugD!iN(T6=h^(#9+zW zuj}r99*ls>t?XcLfBx`fYrl!Ck+}p`(kOmwA!`;}!Tobfz|yvUSX5FZE& z5Sv(XNygpbJHCLp^BAz8Fh=zaFjectN-Yv}bamueHw$+M0LBSB|Qbe%Z4fkh^p z>Z+#{tcmp}a+Uk+^d$LGhC7d+^NRQ3gcnY|0{0qQTwc0f9*16lz8v2)za*8Lf6Un8izFV& z&UL#gmCrW5?JxYH&tG*KKD)Xmd>RAGd&(Ij?vc~DLU3^I@{7Mst_!@o>(XTJIG!|l zdVF54eFEH>WJxdP_%b5b>#Vg_IQ3q@nEl5DxUyF7W(hm*2F_LJM4yK8yDkG;j9Ly; z{k7g|Eg!>kmuR8qCXNIT1e`@wId^UBUyUnu$Y>R#vbAqbb(~^4KO~swcy0%5wzI$N zNzSw1lH=;E=w{tsFr3_X*Lm%lxUba(yqHk7-6a^j)b)_(r=>6^TzX?*)DPD_^bMs< z)~(+B7VBE9ht`%q-wdi6fe#Yc<5oOiOA96e2gzcqKgNMOPk}ExlHP{xB?mgBt&r=0 z2fw-2>5^VI89YJMSmMbxYg{)r{!d@FWRM;tKDPK(CJRq+tk?n0lh2NI1f$ccG3LQd zrDh`q&G;<=jAiC9gE*03Mg{1h+TfAfvK5?Z?xj*!cLhN*VlqgnUTiteMX#m%h+v>j zr{(6kIqlf9^PORvu^eJjQXz*q7KuO0E?toM`4-E;q~PG-loY&BH8`D=l$4~!(feU4 zZf9rr<;xd14ebd-MM6U2b6F)reusmD(|;qln={;ylbN|VIXSt!4D)ISxVs;~U^XKe zW(d{}d+b6&?aj?zH^-2(vojqdPc8VlhGz{mBhu!{8W|ZeIosO@N7M5S~HQ zuBNK03Jiw$4Zx`}d{FlG_HTmzVHw7VkevSM%J0aduA?&#H?*s1|D9!LcO;>wsaXO8 zRaRKw?w(%L6`8LQ zC1mn>(>vQ&qE!i&RdkiwOKP-{>G;TMPnDs=?Av>ZeH8&)An&vmSussc{CEGFOt4YF z$*`fvPHbWJ%c!2mfNN-E+p7p-&{!mvsG-4zymAVxrKSBM-Kv~`%^PUdWO{cX5o#!v z!RhTR;X8~aSuUbIVB&Y?jabN5XA_EsQL)0oO>5M^IBa~@2by$^MZJ0Un!a!E^q&qU zMq%%|Cc~Cy;+@-|-08;JU^Cj8Uv1NO)VoQ~+m4`k_+EYU^sLH$748A_cvDhqKV0{c z(6+Ri5B8kc@bErfzWuJ+S!AzcQnO(@@Mj`!27yawucn>3xw)^ee|`phCvyRbNjD^X z7_h;kH8o0%5p|Phd)jJzkgafpIr^8jCF06f>zrOWMBD#)t)RX<9QgRcPmke(c5~x4 z`)kDW@yd-QMtYw0oF@&uB7&E^eF!<-t!!Ra&>lZH)MLWXOap7d&gpqt9KW_f8(Uc0 z*r1u`zRX>h7nEtwx82Nn@U+RBD^rt0=n+Fmo92-AkH!#AR|mKKCEohb>$&H)?~t^; zs}rE-NswxdVeUr2AW>Wam#zU^I>*JuRo#oRi1im;TRfZ|6^K_IS8-j8H%Ya59word z&rO{AVzRs&qm=cUXuvJ=&Mi2r?Q81ve5<0OF>v&KteU+-hbHLoK<_>0n}|y0dnc~i zwtzd`=?(RM$5sC9Wb2&~3>d$tXFR0kB0u|J!cM2-7ZD#fH%Gsv-kc{yp|OaOo{kP( zDynGVUknTGuLp8j6Lpx)WQ?9ejE$|oy!4Py5)=}OiHSiF-#a`!JU*r{`AI-Yd2;0k zJ2)V+=r(nIy1&Y~xV*eP!}mi$K}nf{pL~fwaP}Gq1X^2{^=_QreMP1!pUzB8ot>TC zxwvC2okLTSPvTZ4H947ISg;+PvW&IM;6VInVd|_$%!pPa#pU{RvHKmBvq@cS{Cs$_%()kR`DoY{acM( zKtWP#JhsN~Pe=C0E5w{flJSSWbQkA1*H2gZS5(g7pA@7Ab4E=&5ukoDpG2+5af34& zZ5Q8|SokUiMw)KAGL+NbSL6Q^nm3qb1*epz_i&IhoWEQ?lgpeuxK?O$1!Fn3!?z&_ zOGVYycZL|SyNL4156Pd2qMi-Qjkc9De!-D@oAk)u9vM(nHQI0G5RE#`OSYF5Ivq!- ziH9=%B-(Ir&mQ3De0!77$^XS&u^R8dZhC|bjjDthkM|E+BSq*36k5FZbk%LUit|tx z|L4ic?vmIAJc9g-3GzW~Wu?(}z!BX=*I5|SP3#wx@0AYEtX1h``ZtZy#|5U|GC=7f zrD9yJ;>n=jixyD75D1MpB^?F}qtZTVJDmZ`rqPO;?2-BVhi>X z3^f!t`RKUBr>QQ$G4zWNj%JBh#9`Dm8fopq^`$c3AB!j5yp3}xzbvy%D#vdOmfN_~ zA6fK6RhuFfz3o_-IF99(e<;rt)i*KF2kiIKbKHiy++w7iISqUdraO5%qlM>GBH7*~8goK1* zIaF3QjW>Cg)WRv0|M5zjzrR16*@JK40isjrATv%sN7c{+Z#uUmEUjLRq`%f^X=%CO*bGm54D(?Q*$3riXJ;oRxxfKnZapVRvAh#2RHZSK~+>U> ziR(C+7v$>WF4gbP`oMbwBE&CoUe*w>@T_HE;t^sPLC8u;lT#1;nTGd1_8xMUcifyP zP#SX>5{e)ri}(OUvw$kGTQon0#k}9O{2hH@#cV~|{TlG?QMZU|&A~`D!|0P3de?KW@Ui@G{xBzga4#4vDH>qi^)HIZ{SIz2o#Ah)4$lEoRJ)AK%ipqigyzQb zUUMBPrbbZ@t|*g)Hp1B;e$X}#G1p0t6F!pb|JTKMqX>W9+~@hiJ- zZV8Q-HkiR%L1Is*owM_4$B(10(MbiEcSpt}AMY1gEoe#h<29u+T-)B6!QHp-xEf`L zus+4;$^fT8*vVp>mL){|b;O}Hsi6^wb=2qSY}ka}!9 z;N(n*J@?^U67%`w*^esgRYFt%-FTbc;Kd(iu26(nV&3u)auH$*e>7-jZbk~(_H)n+m8b$=TT??pqlGudP&7aI*-P&IfJ zn^(?o$kFVyPe*k0tAVDbrmpV7%#5bGx?AO&q#Qsm2V4##WYNXKh-h(!RFda3yZ;{+ zP+5sLJ23$d`j(oK;&C;rV}QD?sdeQCmY0`@!y+55x0=#YDoqigJhy3yiJaWr+`PQJ zqWQQ~KV3I^IyyQe)weL&W9=Ormb(I99zb5|c)KH+T*AV_dBW(uKNJd0W6^sTT3qsJ z<%zc7)wQa$iNhz?)=c#Em!_t^7#V>r2XU$pp*|fsMUe$a5%kB*}h1+prjgjpvI;FgH$kS_bx8q28H))dRXKQAG zBRdzRgvjgPYft;$G20F7YcG(4dp2>8)1lX0)~YI{j$-929M=3+6#J9G8?Fa`Ghen7 zO6NU61E2jZc$$O|ia2{BvYDB)gWV{AM?wBpV14TmN77}|dZGDM_w-_imv|!xuU_7E z6BB)Jblu!Z#)+o@dKoH+P?3o@5Ii2i!KLfBFRQR3iTMO(qekTge6r!UTRkt&doB!c zecE*iC@`Ef^vc}FmLdq;T|8m6e4uPUIR>X1B~9~kPML>t_dCcwNxKcBJ=0So@+ApV zFm(uQ&&&2LcW_eVG6g%!nuA0RZ{j{kjW!@#M~Tnik~zE|DDib{==Lo7ttOyCf^v5= z^-BwtzAXKUk3S&c5q%lrX^e`T)LmO0vUcfrjfQyl zOnvtr5MT&pF#>TjG1;wk`oo0@*#pGym7~^;2Vs##w&**=;p&ElhPt}C1_loJgC!~M zV>F3!va%7Q)}#~^$1qq-R8)QV%ohy}I{Aa+V^J;l=J3}8HoW@1=GvbdtgY$)AKKn3 zE{<;b0!>1YKp?ogyE_3A+banr_d-twdwQ3a;lb((aa}+Jw8_Q9r<{JIlo^_XR3w0&U(B;!^pQIAybi^W% zmYQn7hNK?27sHd5l|@QK)NC_B>A*kraPRfeGN!S)*{G2R5mnW+9e}E;st||=B6rr* z)HI$g#6?5%89QX5-ln;+G51%3bJV&_Lf^bf;Bnh36k`51{98r;d3r#k0+y3)ndy7- z>iA(|TA54W@jQ?^K(j}|$i%@}mr?qsv_#&TS|$2Dtp8$!Fl5*QQ>V z+i}e|am;aIgaidA7c2g~LXvlqRJpL*&<`sRX&!P90}Qep3h=ke*88kfzNx@TeZhog zdyjzk0VOXkuUtK!rW}Y$ogdDp$4Ki`pOJ-1Yztc3mv0J{FVjj+pY)^yCZhoR<8|qR z?{SsBK4La=?XBGZS>=Jqd<8o&H=aeqUb70zQPFS~=3 zcjnpO>J@`=&__HTYlq8-NwPFemhSG2l)zE$FUKxsI{=~W68o2V6KIN|+>`{5^L178 zi?M*Eb$4n#uDz*WB`Tgl{9C%Pul3r?tMkCUO)687dgi8sT(E5VIBTp`phSa}=eMrA zNirt|)quj1KL9t&$()R~7bkRNmfA47GGQky#V+4kRH?|o0@p_|IM2!5!aW1aOeqSI zC4$%>#XsW>2U+udK)*U(ojg%vH5QmK(sS2PPHJ;eQ4AOuhx;xe8w5!9lE%~`pzx58 z5a8k5y`O|8z6hcyEH*A~U~tfgK%N)T$f5)eha>dDIGLFdWNQZphe|{Y!o2YN_dkFu z2pBwmcs(#M5Em0;o5eWd=HYSk`}gm)wY7?y@ZZGov9UBE2oqKO8ChAPyu3xsJ6AJ^ z$X|gT5sX;N%4^~y3bEMHda|9nNYLI^WyqtkaB!%qsReAt3Ly&nsyI-YR*p_|5El4V z4^L0?g;{2@u28LNw~VcSXXvkP9X+h^t4!W8$+htewJ95%aa=r$ zQ=s?(eDo>46JXo5P?1U0=tI5~=a=*qi9DJ8cd8hx{7Z4Lwl!90{cbR9JCa9}i=!0B z_0JIS$5#TbB-ER42kxdG`{=RUkd=Km^bDSM)hM+$V#na{(gbCvc0_^q?%dAA$0xdW z_Aj(W8q-wIciFJ#{Zq-8fzFp(Z5wyy!=1_~)BDvG_{ZZ~U)_a=rfT>@vr`&FJvMpV zx0hXa=jY2?s`lsm{EzUhO0jTsFg&5tW+}`Om07;O**MXW|D!?cOR+tPPSeuZ!3(*f zVBK{!Bn9T$YYFpZ4eT#WVsnaj@V`ENu_wsLsypk2j@CkM<}16g362z|7nWm|oSD_c zG)&KqPsLd>+01Rr+aJ`!7aH{@NEQt|Z?)AkeZ%n(GC4KR$3m#>6<)^6Sq<0ZRY zH|b2zq80(&8GKwj4zMhqvLf1jxPhLr*OL3h*T7a6vOQjq|d^YFB#?(c!D(< z24CNwWX4_2RsSImxCohi1~@>WEede+X;LkvY5w~9dK@W4Ebp*9nwFm4?EiQZiN_R2 zCE10*&BesTBqbpo9ez)D=OB=^jg9BtUmD(AfR0Xs%|srhxX*hEQGNyn1|FWt)7u*3 z)+yH<1Xgf&cZXP;1an_U+ltcYB9=fct*II_NO^gAMg}oL)*j)O4Z1!B1R|!OrlzJP zO9x^PVr@D&I0%40$Pz~I4j@=D2&a-~!2jXOF6ZaS*jVg0w2x1ErRK3Pk1Z2~N9gEl zc0fuaqoSgMK>tSm{JFTiMC2*jfro@Faa)InDSu1~m7Ph>|=Cl|9fU%QD|`dHc6 zK2)@=)_q||rpuDFd!mS7w)Qa-uf7e6;MBq*_Z@c6epW;j7;jG3^VTJm6xK~*Bo#TA*&>sFfY@-OEnr-&)Zc_D7(VeJDS#i)i zlGT(Rh#QVdy!XCuZ$3ubt0+?^(XaDqQaBu`{-nu$U&n{S^>|jl=%M)55(FacC&v&_ znbuM4fH;pAs31yD{}C)k_GB>>tl4mPgPzkpjDRpN^>)lR9EGKEaY)D2*2Ous+vCYs z07l#n&#Q*DY@C-{(`v^8U%yM4c->n`h2`(^JK;SBWUPG}4sOK|m1Vd-&BlEW3M0+w zWA1o5hM2`kHRtm-D0f`vw>$Z}&KU}nD6a;K*w;xEIOh*V18^5J*D%I&-LEl)U_RH| z(htp*CKm(OT%Ao7pX`s@j6ZsBG9?(=`>_fibeS*>|7jliWEOMHyg|<@oa=zf zj}5Nper2Z#k;&=??G}!o?HZrVwdGQ#Ha0f)_VyH5g3%BZB}BdU{pIfM-Xt9&0AgZd zs?)44DtbeMPeeo%8AyB2Y68tgki>omA>rZTvX2;c`5~4i?_$mz$0b#p-=qQo$BC_7 zRwHTGCo5tsERj5d&Z`|$Q&U6yxvaSFiwhra#0&rg$x!-Rh=iKdX}u z!ra?a4Fj?fa4~U6W2#nCRl( z@}iR2nV_r(cW@lK|7Zkq?oS0C4f`j%r~9?~`JN9ABQ1HJ6c+N2fx)*DuNkuzDqbQ2 zc-pYFG!vzl;z^*KIjqx*P4)|UqH^Zr2r-6FORqk!sE0;Md7ZR*i`}MJf!E2gO1adP;BVI(1|G8JfCx*L>+-%CFWDk0!*h}f(Uq37LNXhn zeJ>?v#<8<~(EQb$b~=Q!BS8xwAdsa)^l}^zrASiLoK;!bb(rVB?S@UD-+FiMvdVaz z@Ob+%UH7Bf=rV_$uIXWS+;Dla_kzH_mr-bTrHz)?+ReuMR`-4Sv+reT`Pep>F&@A9 zou-Y&9efxRK*Z8JotKYnFx$n2-jD;<&fQy#598$O9nw@YD78^m_a~XR#zNv3GzeV= zo#2G^qt%BE3W%>nj{eZEr*A-j(_CC! z#P2C7kE`@+X>r8_AmAsN#mj(OLt$0;UNb4$W zVezc@4m&6I<>i=)vH%7QaF!Sz4nvn|8vhK=7N-$OLq>9YfTr4XoB!jBU512x>gcnZ zre@<$jkbXOqN6H$WCG6BEIb{Z#;$MoJ^fb5vS|_Y9=KYRwvVesA8`J&CLjg3Uwp+VbJH(pU1MQg3T0O4_%u_rz1GB0x3w& z+YF{Eql@R)*_V>WWv6D+BqwTi5-&lXb~DSnlH{dP)`IuCw~$5)@;Y5rTF_pi^q-x8 zc7Lv7(EW6}k>I^P@nC;H#rC^F2V_R4tUU_6?Se~%jxjkk;P|)_*V#FxX0YsG8Ik2W z@^M7Dq2uJqf&c7>fVCxWk$)Pu;l=mcd(@6zkde)QvkM#OaVGo^GU6t#W{zmAVv}NUyC1z@kA{xB@-xoeKz4U z29aX@WE*YU5NG2ioaHyqoWAaV_?S$@Xa|Ob0~!Bnyllch|E?`&MgY>hm`ki(3kuMD zY&T;qpWys=IT{F~Ycj~6O-6c%FWv4cL7T$W46k0v)0E8c$6{L;=pKp|=3EZFr5ioY zA*R)?!7lliHpE1auueWwr!t+QC8t!>2v&H-PY}8H-Q)wxkLr``L@jh0T7m7jTbtJ} zl>-<5oB{rQEdM=-Mur)G3MgJ@9q*3y>}mA|9BOEz-0dZ{af1g3GE=RskyGJOM;ORA#y|VU)u$kyzhUOmWJ`nd6e!WOpwO7 zN=qY^%Ob_Ht6#%OG5coHB%5*gE&HP-XwfG9fo9SY-UDP;qrwz44W2rvAgd-IxDYU4dP&F zm23(-au@w5IFZ*8b|IIa=I`akm(>I`Itmi~*R~-V3xnlo9lKZ+hu*ue z%r+|eDGA!KlCdU&|LrFw8P|agAT*0+;AoB=)&Cv+JN0F+Nc#U(SE?o*{Xey)Pi!ck z|92g)8Z5B?e;tO~YW>OI{O=Td^(ufphR4tD-^SUta&_ zd98}575PNg*BgTE_^|6wh^v86gx1ee6H?GC%c`+359}HL4=fA=!h(Wx{Ho(3mh4mC*9K4m zNLj3kIYi>7t!u>AcBxDF-%BgmEeY~-xQyaRNflx*KmMMmML|bcAEvz(lZpTzmf9gY zA0eKs!f9u}rO0vB1G1ZE z{lWQ2{2XVJxKi^?s%Si_had_xY*Rh*G z5&3d9R#pu%q|Ylj<}sTa8{7lflmGepy!zW?9^<$qsLCfO*o1IRRaJ*SX?Qlos%Mpc zmie#Z)2GURdM|lO?F`KwnZSsTnm6%gc{wu_7`T4f2d zr4n<=7PI_rjQ8M8o(jHFd=gY%shi|wwX=vAPqr{oee>c6Z=i)#DqR3^_wo;{fElJA zmNMw+wf@!0+S%gp#7oYsCRVqGQrv)>pfXExr(k)<=CwZBUezxzKx9j$)SvvX#xvI* z^T?fyC2u~w6f|FQ`mDb0Dq{%e;u>o(XX%Kxy(7^tR9YHxpLu`cf1fn_R4WlvL`}>P^(CbPy44ThZ}1#wyrc# zQ;~!&%g03WZ1@DGd zeG*>7S*S9)uC}SMA%zBzLXJ?~YYIqSTvBY)FPr(86_(;r-qlbpyd^-?;vOW38r){7 zqyz=FBy^?35t+J;&8Dl`5mh=A-8kRET4>6ocs_KFpzUz?OKwz|nfN`Y&~&!slB#UsD&R3T&c^Wp|uK(_!_wGpHc6lWj1 zE60m!1I+$-eNZotMVgSf7Jrr9q2@k(!r%_^xg1mXOqp|d=)y`~qvhndh0Nv$CV486ss9q(l50a9rerkE$m*N2b=_?=lbsSts1ao5sA~36}pWT z8Ju>AI8N?ZEEd0Z*}1j5DF=|?D|FD?w;nDptQ2WK{IX%TC`FI9_aelxS=Y=w6{J`@uc0UI0<_hw1%*oT& zuuSB_7sw{M1bz;rJ+|NV)TO?I+;2+jsa~TDlevTisoWUUiA%VE59igM{Er zyt;289o(m9+0kp9JbX1>o9cRI+=5x?gH~E-`zyT(8_~m~Lp{X4%IH}Bh2PnMquvlo zC$FH9@3P+x*L9-t5N6ko?OD|0$H2!`Xqzh zWUwxz)GONTgOkY=Fy#auAaLDN+aWQ;fUD&-l7}5Rvgh#(2qYIRfcblhH`NuJ>P4)@ zNd`Qb}|cXF%$W=_uGcD^RN@yw_Iwe`~;OZo@m`CTec7<>}+X7)_(HNDNuXxIMwV2!Z*E33GX)=&7# zEaj8lYj;MEAIN65Lm%@3%H)RVIE0Cod8T|;;Jc7qJ`kI$<4&VmNC|ZtWN?V36E*%I z{kqT0^r`MMl-skmrkCS`gzIcEWdz?zTQKvxW1pvooxviOz%{e!%>B@;(WdE#eE&=5 z(&7P@&iBe0|Az&1aK8Mwm1K8XGpv_3UL#`ae2rwbYuc$U3a`4HAcygA#ECUonQw%8 zhf8EGs98hYseCt1%yTVF2642oBSWw!_f5)Hz06*)hCRj4q`K$;q?EvfJMIdq^9TFw7ov%-N+4~c^jql zC(G*`C@qKOcl0b7&q{36olHF^-s6=+)WBvZ~3Bt~d+E&P!C za2#uFq!8JO8?WyL)kWKj<6$9TTybi9*{NrGKc*110Ur4#_QXNe+1vBuT0r1Bji~V6 z5^qywe3^PT^M`u-{eVEA*VdSi9W4t12af;;B}O+xWlc54f{MVCE009CJ~Q!Ot%nuA zrQ<`PmFCt(k*|}C!ZZp*j{%-bE9tq5(~ZGN8vAeASP$_7RituYSje#+NX}iSabrTO z?X5kt%uNg;_kXej-FIHuAv?-MplyF!v72leHxb>7+qQ6gA`miZ_q^Ubbt=x9TW)tn z?Kkzh&fSgQ-$406uKgA249n}am}>K|WvZtBIjIe9XS3ODB7%(cqh05J-|xq3SB5T# z?EctYy&q6L2EtV#r!a|=EqBiQheMM3%f!#d`-d*ur_OtsG9?W={%6a9M5nr{m%@ID zYuq`lJR~OI&du)W@N1<=0pTUj^`0?Pg$z1eUsKPQYC17lp%8W{yI)Npi9WofWSx_@ zQpFP_dMhc-@RMC@YHc97$l46qY5T*GzC|c`6}7H`?mn(K4-cgXjoc>Z9Xz-FqDeiw z9r{me7M{MBC=6>301)C1!k^B^raDxGq8RAR{StHPaGM6I6DrM&4&b~}(?IyibisUq z#;{3CQO0D$K~4Nnug)#HFd=aNL(b(AESJxCp60U-IqUOXZaVD2*2lHe^L~FO(C>wv zXtNiEgu#;e`pLohXj%=(aU1T(sg&CG2QZ!II~V_flH~dgvenksC8`aROAvvs$mZn) zak?t0%vWskebVjVD~bJ>IOlQLX3^On_INsl)6bia)>)&qA;&JA3u@%TjBiWr=;ZQK zQvZ=^s$@+`Kw@FV+T5;kK?;RE?Uty+UTjTFkvEwcs|Ooz#lKGusf}8t#rj}UW@SBS zs^Wa$O6<>y!f0lHev00APpcYYDUWl29wr?+-H&A=MG}b{PUeQ?OK`jPR=q(xQ2W@^ zs1=?cxSnD@)I_f-vyulzeABM)#b!KyoCa)7)}u7KbFkGyTSm&RI&Bu+6wCJyy`EX< z@M~~zQuV1IPiHXG%>LPodMDqb)#$;>p2iRn^No9FNP8`DVK31a_koRiJ|=bI7xyOUcU>gw0ywB zaWJowjEz~qO6xu=hN%9}aZl%$L#_$``GP^U*7NoDK=C*?dD2WG6Tjh6Cs-IMjl@4=*0<^;_B3her=Yf5H;}%bHa|CY;UkOis*6^(I z!ZV9;FS@rax0v3@^cW})qR{>@PP_26LA2zOAw4fwW(AuGRPMi<`S^Tu!dsN7BpkQY z^mM4I{L7pimqBrf06vlH)8Ci3?Aja62MJV*(J(Y?by~z=!^$kNOiPvcdO(ssXvqRl zUE#TfP))4H5fF$R{eD!`(KAU-N$Vp~KU@y%`(3ph$`FOqDyyXQQ$35Hm6V5UUBfXp zDd{2^B6fzPFwk0bZ};nKf6_I7HS{-UPs6tm7fGi7TX!)4{DU~JYg6Q1MN z+X1Wq>QHLV)*>ct0rX)~6*Sz&`c=P+%3H~0o%sTiEGY%=lPMyzluncvUzI2e-`by< zi%gp1%>PV(@4<<4h})Co9}Caq0OYb~KmHkkImsYYbBr!#+-q(hq5cb+Q`--}U6ZxV z%m8s2;P-!&xJA-sCV#Z2`Cacfe=gkj*w&lwYW3RKGab%Q#=%Qo#rfGeh76P{kO_RL z@=ARd&1`)=cPo)84x^PYuD2Oza0UyvIgQ(4m^@sDz3jX};=^I~+U(!;&~*{-P{D6_zxu~`AQVhi2O(_9!btwv>s&Jd->!g#WmCEHmCxfp_J*lAYKlC+Vd=u(22QibGF%JiO%%hf>eE!g!kzW zT8zi<%Ud37wK72$#&iM1D0h z&}{?j@fzyXa1th>e1gPT9A_wHgtq#wzcF zYqfWU!Ji^5oSSvZ<%+ByCyD8zQ<05RifQ5!Hf3(eES>*$uDW#~QLAW{_cR@JH2vu% z3#=&8j_gpz#LEKVs1&<|nmAPMr!V`A74WN~dpWDa7Y@cS zh}g5*zxyvsN|LV7Aq&+H{Uc^ymW<+|@V%8fijaA^&3sz0C^LkXWKlxQ=C+~}g>K)C z!&*kJ*|X1LnS;fUL5n(e=veHcNl&p?omGFYIG2G78z`yQc)VNV!Dz6L= zcc7ziRd!}RzdsTex2j%>P+sQqlyZSivynwcIkMwB#QSm(trPnvxcT{erHL8Q*Ceg! zrBVNofL{gnb1giItnQAW%S8hiCv&f2uN3uC@jrnN4+jcI5 zDtA9Q!qM<-ThwyC(Lm8u@?fx@VsiH?dV(bFc%B9zd-^+g;8|j820eU94kif$Njy=E-bZon7w% zE#UJFV;5>VEI3b=tGS=(5tXIzy#5=Um5=-#Vlbe={eqGLX%qV<{z*fDqZjWZEi;KhsTz`qG%kM zxNU-zOgZSw>43n`iHGT$!5iE+dPh0%4YB;zzP|;DP4qg`4wuameuJvlKp=RnO+-+u zYr`ctvhO)laT1gw$WZ=O&-~n}ka&HNei)`Nhp~ zoF^w8ei5F^8 zI(2+WxE1xfO)3+CM@|f4qEM({PP-t#{|=~YelG`@kIV? z&lP{ewYt;twv}e8+9n+9ovGI6NS0VZKND<2b%V7Zfe`LrOO|-;0|sh6C4pYWn*~+^ zhEwG{KP}6tL%wA{4nSV`N2PkR<*$mP-F1}x3#1*0U zwr)hi?;%y7f67@3+S!j2gKX@4lTN$KtiGvr6TzeET*IxEP=$tabChpEqtzy+{N{~s zCGuOrO;r${F0NZEKeik4@k+bz%lEFTQJ!*arK_`NgDC8#<}W7a!0AX5EO>!kPDINg zJ&?j>KXi9cE8UVbe*rlE+jKI7t&K~g;|B3GSqZelGe!TVArN17ctKnZ{#zTHfq^i* zF$|0nSy$;M$sc5ub-4@uelj8I9?t~!YKo-;vF*N)zm%SO$`E8 zO(x=pt{(0kN+B0>!L!7V6gFn_)Fnh8EHnNhzePK?#%+nwwr3cmRRc z3IB%${2myBdX4m%mfFN5CX8NP>%@dCT19*6!L7gGdXO`^Fu^J*sTCPuSVwS(k`>u;hwV_h6S`X}hG6uei32S73 zM5hdCW^?Tp*_Bf2k2qO&?(0i-SB9ACoEEu^?ILAZTAIzJLLl%qWhPmgnm?^h_OcFL zUeDY6n9KjPnK9AJLYv3(_+ElBCde{~>x{pZ8hc#+Ob#@miJdRLvpv~Hz`*Tm!QmZE zeVIEW5{^?_rkSgCD$d108tj?xiKLFW*S0Vw*u3DqBClEEb#4u~36rOem)#jX6mBqB z=+29_OgYVhW>0>WA^MV?{WwiCP+*F%4b#6Ldojrr3+&sQ^yl5EM(Ca^r-2RYYkNsN zje)w7^ct$GPk|Db6?3jz)!Jood$Xq65oG12Jh#)H5?Mx@Xy~%ShD_E_DnD2IZ_2oq z$asxiPRHSVX}2%O`W6OYWz>B4<7uW`*c$6F%R3!jD5koUB|UqM3FTU&rDB|plqM}e z2q=s4BQclJk?D8I1x&7GY(^Z!2zj|koOk`UPUUm)YbM_2C=Kq^dE4zu zu_>~TfO^#6WulrMtijLz=~L zzV+hg2V@T`Keu+Z-1e`fOr)BwE2y!@d|vveY9F5WGiyjgx**eR6eCJU{!`VS%f917 z<5TZ=6jil{&7SY+KESeNsVYrq=`##qE8m0T)AJcaBuJJL&s-BY=h=;+>zwQ=?pZYyO z*h;{m$yY;Dxek&mT|3i5I2p?IVaq;n*8hG`_d>xs zUHJEalN(5fAxGfMm7pyPzIfZh$_6o8Q!1CNg0$OCrTW!Tf?t21L`Hi|^j=@XTUqn& zKh+4`ugB}?n?JvQ{lzj0xlzAYRE%l48Me05Ozh9jbi*?qDE)qrHLlA6+o7Csp_fwy$+hZV1Pr{+IyqagB0FD0HaLo3=rvSPbqTvYH{b6~> zTF+6mxwdgisH@{F5mXM9%l|%ndeU-JBx8HU!*X?qMG#XY!mlvc()ZL$0*g=(hNN`mYB~oGmI=6)>xQ zPV!FX_4pOTm(8r%VLeg*VY$wCnjm=)>yMJ67I!840^jcCZBwLn9wA8n5&!qGy_n5x! zb?kTk2EPeR78wWlch60sDU*EIZGSAYqZug#?da~P`L3VqNtzLE zz$9-m3?-{<4Nba8gFP998^8xudVg z2CQ7{n{{;k6yCag#PNiV-9L@+akaVniH$VDGvR7VP7wQB-D1iHh5=Xo^hhET_h;-s zRs}Az(_9_9HxT=86JHsheWk#01!~d#93Ho;D5>kcZM zBNY3a6OQ*6{?!0;&?J*zUPfT188%$fLo8c|S zAju7Ho=@3lmqB!WWl8_@g)Vqrn;(0fquzP^kq9>d7l*V98ImLN)qH?=NaP|QG}Y!t z-94kgM=A<}w{wU+6`B$tHKm&CYnc+V&=_nGQl3?K2yRyYxU3u>!$H|_Z0z$mdRxtu z*rOb|ZdFC6qdm(Qtx|k!yZL~%p9A7!lMyg%ap;|*pn>~J^H#A0aqy+rNV=cxPt}e# z#BGkd5)1-#+RV2*mbLIXAKw|`c2f*g6v+w3dtru`m!|=aK)A)0!Va%_Hrr_%w9v!+ zO~CE&yytzxAq$;ZkUJ6lx@)ksW~rLEREmDrR8Bjlljm>~ZWNRsy+*D%Rx{K#^>kq2 zJe}Y$DS;<{bA&xc@>6siCdh>*aO(nMalvn3#bp)fE#0Utz4SI#CnIYcSS_yXHsKboZ<^K5`IzY{z_(ji8rL4uFwLMaY7*P(wfM3l=GPK_^ z0-C#6%St~Q=S@eRaQi7i;(}d^Y-d}=Fa%FDb)5fBWp7k+!L*Zzv%%Y^f2!XNZ()ho zB@d0Oijfv4&2~DUp8RQ3ZSO>XmxRGlsuzFK;Nhuhg*1@F%tKP)v(Ut4cN`HumBrRKOz6Z~Y9&ig>6Z*>ve6eNoE&Da?0Leu;r0S{q0un@mjBN3XDHs4 z$J8$qwq1Zbn4IO_E4i5tec@?k)C7^J8vdj;X_4Gk^0#*4Px+6N~ zEHD2FNhuycvZ(naRouWY{8}*vJ{(!q(J+@7wGpZnx6KHo@SUE8DCvgw5{Uou9e}bS z>v3c0tL3JU42@{odhGE?ZJ)NWhbfSeyeqr4Kdn~jHMKi4JlO_e=ahWCwN1wk)#sMv zDif8#W_3Ul_(Faf8sOs=e>555KhmP!mX@^&94h~QGVZ3Ka<2RgXmZ$ZD#{vP*<{}#tq@nI z>Ui-$ZbEbOF<(4S^Ljiwc{lugL$UQ^4;DMw zDq!`l@`bHGkLdc=VM*fVM*B>knY!mz0$ zC7MbnL%XoyW8lhDDzb_C@E1b7H#mUGWqzA(Fl#F7k*)0gZ!T3gy?ySD=Wwnu176Gf z#p71*R)M&rg;wZr@`PxGe9keij1Ku?yGsB`Pg3m_Us(JV%d!WK+;UnMiyr*^J-mPd zEeliyKRGU2&8YSzJNq3et7Mdv2wm|7=#2FU95(L|iSn1q-@Y!(aot&Sii{gm(Kdl! zhfhPdwa3D(_Ahc~_3FAvJ;=l4RJv{od7mGM>JRB`^S7TR=W!EB@?KJWk$u*DmmlqEIhXqKJ#2V;T znYi3HiYE&|t=i(9^e_51Fh8$w8?(&=doqQd4q`Az2puODOmU?47dpdZbNTO!S7(5~ ztmlsNE^opwTYL~HrJ*j7c%kG`B@;cL{h&k_az^38`BW`F%jxf)OQ12Z%&Hc0QCSJ2 zfX+9JmW;Kv)sCL7&UP$S6&Cg(7(gRnD3|2P;;oIn@q?=RM>fHUyk?8uo8^uRl(eK- z;ME-;W9-4vw&b-(#ti3DQwMqYuKjCUvb8i%a%|aVB|*sJL15TNH|Z)1k!51wQn&=^C`F^n!OL2n}!O~SKZRES4D($w<1ZC^VQ3Z#j$XZBlN;u;(0&_!#~o=RF` zT0bLI9uCdS5aH)|Odzz`v*)%+n@^{Fm17%%uk>x8rGA3^`+*3}Qes9{sUp2Q1vuNf zf2Sr74vDwVsHlwC`|~g%`TSIzT&lLWrJr`zD0Vs!uAb>bR@T*GtIbV>Gh5RJ>v*~8 zXxzrnw8`=A{ym!UrQkK&Kn4qu$D^Nh_hQoaDMZ3y>o*??y#bAK?BUarSibPfB1+YR z#n1Nx#znTGVE>m{I|t9%3ey#$_^()TC-+NB;PI%>3jBVTe=shE<_=23TB=Nh-N*7U z)KB&fJ$7aT)1HA=liK5*)TaF&z||a)dJ}*^+$|I%fVj%sv%h)TTAjpCZX)E%&>UVn z>}*idh@2#Aqs>@gbnRrjrt1lSc|Bf{g3Bfc<0*?HmH3E_&J)DnTgEozVO*5iLi3W! zly3xZszi;K4oxlyahO~PLMfCXK_UDcRJ?PE!%~GkjT-?lsw;c%c>;x+)OUT{%W{p3 z46xaq6P4+p1vWBxD_2G>0Z$ehwLJ+zO8_UT3W+y&t%@uee;;B*ejY|>bBtIUgW3u! z`)Vl^@uxMK{4URTVc#ad?-l(c_!dzH5;=o8eHyPt3}w(Ga2qnDHPKEFJb&m_Johwn zSF_F;&Zs<;6Q0Nh*ZmD6asGIIYja`jS3K&7Yd*$3#ti8p=r8ldi0=^#BdJ%eL{hT; zNMNk(0yLV42ybC3z5HIl2CjGUCnj|a); zIF&?gl<0)I`)r`UbXydaGir9s(IRWUHxc}1a<{In{_Jm6TM~|k`K5}Q?KVGtc{k*w z!=>jpak877#b)wtvm%3r_SJm@H18S0#okYCoC28RRRM%rsMag7Az{9jovp6JjE8ya z?RAT(ldbY8mBl39$@DJKsYFz;Hd?hy`olAAB(o-TEMer)DOiFNkmnED@*YLO&N=r3 z?)h8^ZTsR%sT#ATde5hgY9EYYEHqYAHO^uyWcx{Ks_VY$aQBBSLy8A?4)oHn2_gck zHmQ;!9jvZ$Y=l;Yqu0SRQ_-{E;}9i@4DSFzu9tL_M7~yL{lz`gNq&2!A@p{8Jkt1z zyCiE}yF|!_@s|Z@%Qt8iG|%UvQ)Ef!vf!imx+4%MH5R3=(7<|lbHsX_wn8ILP5LV- zG1btdqkg=brB4~6l?VCpfOwrzWlZQHhO+qP}n)*jpTo%3Ft zxbOe+M_@l9eu-+5XXQ$9schShADS^kd~H@_6ReL_a;!=?R?c zlVRS??&-w#+fo}k6|!nu=wUd2BCHY9-bCC=W3%@n#32BSSf45j;rOs&9ISIuqIVBqqBUkqry=&4P50zi? zJKP9SBwcPa32-P_f>dLUWF&F%xqqECRCjy2$jC{DvD(Qfi}+l3Buk}CzuQQplRS}b z6IPhXzJ-)tx7*CDjT`=f#-y*a%ql0Oz^sUDt=eoeSg&%ge5fm+08!ljdd^N=EF3#z z;E|uMk<;}wzo_{wE1}1q7aYNT?QPhSN#nA#`PS}a8!AQAl~GLWHs}u)kT9iMQ7btg z@H5bln>%r-*FXJyH!I%HCD8HGK~-$@K%uE9H~75w+E(v)_G2V|yi6bA+B>Ieg9fJadzfc|)Y>{{+4(?YmNxgswJB_LLG=yV-bYTB;394AqbMPn`yund>p z-4F0!sZzh4KhUuvFI#+wVJItaHX2_!&T?gL9rQPj`#mgaYux$cZCQ<+TVG&kp| zFu`$sq=o6NuV`ynNE=icr=s0#?YBrt$wrS9)aZGdi_oZ;m9<#Wp{3mpY*n)}4W=d} zrxc}LQ=f#v2NgG61Tqp;;|y5MK2IwH!k!hzpjA{Xd%E)8&E<~3Tx>Rr)jmVi%QKW9 zl~q0@r6%OUy&Z-a|&Yc>i+y5JX@QEgVCd^oSPqf0@w|x z$o-RO-q`jiI#_0L*=tFelrr;mdBZd?n1YBP!{l^zOB84r_;~qvKBzdPlvl1g3mbNJ4E1&k4;O&pno8 zII=R6Gs?^BDwj$av?3`rGL zWt2lTHv9rhbMgdFzVv4+VpmE*B{u13+zufAd6-s*7qD91hh;Gc2A^C(qq6*(iVj#y zux610Gi6Y&UAMg(6KTP!-O_SMQ0Z6QKIsbg5euAU=8^X}Q&6hPYmkKJ^)qmrBz^-(%jqC5z+UVezA~fLDlfmKqGu#> z0-V6-;iJ{xEk0{cF_WvSpxmacg&7~>4waY1JE8*XTp+i69qwq@^PBW2KZ93-$!mIt zCfr1r#T$UIBRBCerGv$n5K}J9<~1&<|9yjB`_;(p4WQ2C9S&lLm^5VeCvfM{_hTxL zEJYl%G;V`|NdN1z8FtF(P~dOqXKL|{&w{NM42ZZIsSAG+9>DA45VQ%x`4{Q zuG|yRVeR_v-N$$w%F^??r1F|wlBMCfp>e?ne__|9Vjr1u^RoZR5Z(u9a{vEm)!Jqt zVMj94ZMF$wH`VcJ1AdDGe5EKt)*3588Tk>*Y7ZlyZjqirzhA)jfRpHVPke@!Rhn{U z;3?w)pFu|hHx!Y_^7TqGSrmudV-zhbz@|tpNs3~qDg&E{{PCLw?vvlZHVmkU4yGn{ zOdmSTi{Ooh(WIZLufTnb`zMX-Rchmb!TouqMT#uq-<39+i2O_TZ>Hrv+}MY#z5mz$ zlofN?$08${${?a#|F4GsSG>fNcidk4E#PIR>8QKbWqD@+D*#`BDlEx_ne_N7a;>#< zm-Tt_Tjb+vcr!YEUYuwm9t4IQ5n!)#ekb#OM^&Y`)Ahi_c`z*t(}x%(&X4i!Xr)v2S3!HJb) zB$Nw2suL;I33||Qw0b(Q+6sr~91|9SFapR>arANFS)gZ-Q14;*o#*^qGy#_RW)BQf z`rqp~lcWWee9GyXF^G}~R4g7IY)6xev!gMuCK>p`wrFfN@%q)3Gz!mg-F!Nzm@lG? zNX=OB0n%`FaI?`7#U4O_zg{L6i~6R9_|kId*Zz2Xl0ql+T_Twro2%;n(Mr6RV2JmE z$Hm?-z_Lh4=i_RJJBZ=Pc}^rKoXTouS`6B%lFjEMhbL8gT~41IZG#%w_3cueZo2N4 zciCbc>}TMC0h9CJB!GE_`~qHfp2+*o&UQ`%cpPR}Gqvgu?=ehXj+1R|b!yibR2R;! zn$`^8SbX%fPqLBEyXE4BiEwV`I&)zh2c}ZmSL!S+nVH&4^0b&VQ~Wt*AQCs>?ENP^j=2z(M?~i#P${RcD-wDsw9n z;SCKrS6qsETn{(gImh!HjJg`hBhk}=%z~AUo&-qQYz{7r_UHbB3ZcC_4$5CTJ+5=a zk(U6e+&ox@>>s%<@A}?fE^WJj$A}Z0Us=Y2@4a&;p{Z74t@L|DaYu|ZW{hyuBGOpx z=XD}j@|`0eCms^i5h~!=-d(*#wNffzkV|jr?Gc%73Qg)UcWZCg_7eJ#XKZf9)`ydn zJadXjkRAa3KWoR68AdM66@P@8ojW;EDXJH}pJQPmjsIc+Zs@hNPDXuoqUXh}9$$0( zbt4=j$0LQhRy$C+ZC(_l#~RXOG}m<6yF0dO`jwzrhKU6J{Sg-3xA*G{n1@=3(P-#? z;4PKGN+m@^!pzF8AUj@HPkwnYf9P0uf3&+I+6M`ogY+;%@zun#-1lF{g-z^h17fjR z%5ubZyFU|M>z;WUYh!e#HB8v!m?R6-FERx%NO zMT~NJb7%T8H<&9pTkgp^$8gPOZ%%6FAC%4c6XBhAeT{W^@pe%AV?^ERanR4peShIp ze3j95J410(`@QRHt=HJcAKbWWkUTr4uYSL{|yZKW%N~sr;FY%Y(C?Sj!(Cn9x2f{-=pp`6YeG`HW!X* z*z!dIZRf349!d=S*9&lAOs8jX22;YEo_j|o;J?N!@H-c@c(wh^Q1NKG(_l9%Qi(~#?#ASEp|f;#^`)AL594^1RndBanaJ*Q2!f}( zDW&QGJ22K@C(J}29$!tquGZGo&H>;qH>d;blfZzPR6JETf8WwjSVO z%p$mBL=%TLb&PPrIU&P(2tp-t&1M`PF_L5s4<2fgCUUr{vf_^#(~I@U-whvyGI-Le)MLQ|^+=or9#H49Jvl*SD!Y-3#XAr3$Gn82VN7lSh1Kv1!Ao45!_ z6s`;}4n(jj%Nqaj)S297O|IIn)9lNcujG`Qqx65xKd-(;r@;@Va>+G2N#H@^bsE#5 z7ep&%((@0%0pkV%*hXnf=UyI;G)*gwXm$@kozr+e-~|A}9G5D!5DEv>GO zTM9k*6p_~vXJugE#@d`Hx4ppb!EJihVA0vAmpfAZ>nV4AQ>ysN$eq*rJ)a!FY6Amr zE&%}TPx=xaEX3|nxtJD5t_x34Q!_JaRD=4A9nI}oDO6jx0aF{wj#;z-NpDZX_7#06 zpidztB7sh=$r_tcGTHa^h=42938;b${DU`P?1`24XR}=k2dw3BEow|LJTaT8}-l6C4!~9B+cy z?Y(Rays4WdE7WS+N4GE|zOTawWcM?&#+e}jK)#ud-@OoQrGA)=^Vrh2rzqFm+U;#| zx0#IY{c2e{Gd4Qw@sY_gw>X@#mS!i^fZ3(1rANC(y*flTe~SbNLFvMC92;JHG$uFw z%(Yy>Sr=S~eYey+V*<9@YyCvqt**Ygki+EXdRwvCNpJxGk($*%bdU)@PXHYFYkp~( ziVZdc_C}4y$FX;)%Ynn?;_HRj-fc_q>PDQB;dL(!z6$7$s4uU`pp(f&H( zg82|rpKjJk+79Fc6}i}%d1sKQFbBvVR(_0#qFmwY{&noK!@~Ro$LEtiIlBoK+o?X! z#Qj;Z(se(~NHC@M@AhP{L~U23(~)=9_xg~i;ww7idO^3mg!3NlqT?R$Nd z4mzHWx0Aq~R5!Dwyu#-0ab5fJ4GN8cAD-NEQUd3G&=HM)`LeM93=HdHc!n4YK0Cbg z1=p@iujPa6L>3w(OWC_@eqGrqL?1oofI&)CzJR$=-FbgY#MgJtW>vSx406-@dhujE zL$>?-H$l*u*Cfrw0EgjV!;D7VHzpz#XBM$#CQ;A=I(a9klo>ZJ&yHxoVWE= zbbRW5OH_TpTD9dCACm38b49q@_34+~5Bq*}o6LE(uiVJX!8u!$)_#Ry>)7 z22Inv@y^qalI~i!I#%xhP^VT&3@4Cu7NWPvB1Cv62{5lBA}zYI@()T z)kSdR!V1q?wPY(xT06&N_q}s6y*hX*dRYoL%)T7(biFWXog8w62FfToQQ#^j#l_6z z^quKx3r-e&J}$*GF&^R&iup@!e*?#cXbtf1%=LSG^1;K<*T?b6}bP! z_XP|ZJV;nsV0UWRmG*h}?a5ZT|6wF{w;B1GhGafnb=RdIj(1mIR;%OE21o1X(uRiJ z{q4s0*Vx+^$F?E~1{Ok?HIp>a?uUFIXs~{NKUF40EJKO>*yp2idOdX}JH3k91l-m| zxB$2y@s$TvMeiN#5A#&JHL1d!TH?tk)yccn;l?uEXFXdfQMjCKY4;$KbamQzo|J7a zNptqw)O*Cm(%9iR!>XS)0GZAY*xA41s`3xsU?>LSc8`M;ZpX`^ z$EUY1E7=8>?f$lpEh~cDMS#G(o%tjS+HwsVCZZnC-XH9b53(-e!+QHHYbU29eSMnD zE)LuD^vl`H>T4zGpU=eduOnk}PU+|+MA$5!Cohig4}+S2kuj{6Z$|mpf0s?#)vAPa z(-p}ZD?)K|#2%}fejUE!&@;InQf!kn)`C=45T&vG2@;!x!P%>D{QuUREEaEQ!4tzh zM>Kqp@p)okYxTA_)Br2YQU6?xo`|iuB4?-MNNc&7PUyV9`F``Rw)8yEm1bQL%uDso;A>h%y zcZ+EV%cLOefj$YlJsm^{LmpSMkv53J-i~`F9)_pRb&ky#rXU7zm|r|Dq{4>B>Ka@$0)lZkn~q`rV=@UJLzj%$hR zgXEL>&>`Y4Evrx_D>mu&APM0Y>S4U#`ha%G}ms1GXIcDdZ|TnE%Nzo6dGSXna!j~s6OFl?A^=*pYH z1k`MXhFpqQ-|bwCa2cfxCDoUfW%G*@$?gfv_gU-jh)_K-}9I_C~bTaWALz8 z>1xPPsWd99V%>dJhd{sTV7`4I(+WPi7+U^P#EC8e1Av zjV*9MF8K=a+K%3+Lm@%B&YkV;`6}w zO{2T2p1W$;=n%iBx^pQ8-f$EsED`{%kQ_tl%AO+>Q2{hE)YQV(azfkt)T`N@yPL5q zhZb8^g6jjo1QS)G2|&JFGLCc)u7IVHWp$lLEQZ?*U!>hbpKsk`CgmXm43E?DIl#%< zF5B%??(~6n_6JaK%+et5*qL66D$gRvQzGnuV(n;Tul1XQ&0qwg-7r zLpPpbk0z)7tlbY1qj8bcu77QbAr%PV@8FYS$%e6#kf|OwJP+ zH|>4%M5}Xg5(!l60QhiFu6F3^Wg`BjhokPNWI^Tme`6A=eZ<>sK7jyDO_`^yNKjy0 zL98qw@XS5(=(FGn~mYrbBuY9Dz6 z-Jfzuk*hV;*hb6~?-zTXzq5|Sb9ayI{-bl3&892RY=C7igVFUkfhC*E#`d$m41%4V zlTcf2-|}yLHD-4A>rxi58z-yjY<*K#r4R2{AqO5nLRdh_tDH&P4tDD8O^czG!S~Bg z`1>vzJP_Sh7jKmkBl%ApJSj6`*zTJF%`&6?{d8hv zXRiMI%mCVt&SZAS?LFVm8@q_(ZNMDurS#i@=V8UkQfxW%A?*;p*`UeiHP`E0<8#EH-{z(o_7u#^u}d z+0w$r>QaABba16mRugd~<~QE5@_XJI; zowt`0f$FXFFTQ=Lr+&|YzRYN-iY<*_1i5m}4AD(BIH*(l+E6oDe4{2l?nkJ5=93KI z2(u4O=XCU5_8PCsj06ZP_#&s}+3s?O)AEYm)_jHn*NG={`_;jLjJ(ey5UicAH!rSV z@nz)TC$v4uS{?1xotBzxKJD8-3y*#z@m1&D*QvXB;P^4$1i5Yi@T2=9({Oy^0Ab)) zSZpuPe9z(BeGw()AO!6x@1Lu^ll6l5>{ko>7~33(^tQ@Qp^KWbRZ{&NIU*j#4R$A! zPJ~>J6!QM~vTZ7&)k2^Yw#Yk6mlB4jxvAu1fxIHMp zNUbhxfj%>@XTz^FA?fv=z|Zma3-3~&->?vsj$zhynPHJK z!eh6>4wIAB`x2G@DGP%F8(b*rubQ#&4l0c;jJ zM3wjRW=cgyp(0v|meh@|rs`KAU#ArXvm^2CO*0L;yd($ zt!tG?YgUjkM~We!6qbeyTnN13Z8uDK5VKUE`2`^7u~hB#=W{oW^0L_jnV6fC3uk9% zN1B-VZKBrwwR%4k%chU0*Mwgvm7_%i!ABPAM zlqA-qBItSyR6oZq3h^h|@H3(t(ca_VH1N#`f9c7J4NjS2gKlJz)^-OAGHg02YNu+4H zz`Rr@x&iN$bjI$}siPL%>)@WGvE$`VY;yGbI`_hIH5KbPb*2|*r!$$Z_@dxo=`68n z7t#m;A2n0kV&XeqJvF5A2=myDKOC8d>gNN{e~f{{YPSa`RhbIVZ;yQj9U$23W5I?T z5XsOeN$(-M<8{KrfRCOjW4EnkQbw1Z!Q0L`KSjGcdnDDz0f|aKfw$s2u`&DU9&kig}8|5$fWU*Zp^B>aNdIvEndYjgOhf*??3k9aV%1)#a|# zdDqs|5mbXH8lASK3Da;4DOJhdD(x&FDsu{7XK$MK#O*Gw4u2guDV|ohqJr#9P~us~ z-|<$-b~l?3opuhpb4HL38t(N`iQL2ch62QFv!>Nd!e$LlKx<_(PA+aog({osQqBDG zM7rE8&bFtI=!^*Q{f$(q+TQn?_q$Nb6eBcK5D(F>F4}LI+#?p7A8zCUX<~vT?;j`+1~s2GOZqG%l1P34gI)$ zZRKb}eJckrLRQB)WBEkuLgbo@L4*}tkE7;RCC9OfOP55u!ctn1ukXtljqX8wPXCw~ zZ31XP(V8HAj-18L5rjW#6~~JedQlC)oT4pZ78c79?bt=_9N_sns;6P8xH{zc1t>PV z+q|xqpOaIcU&)z2fc?XZwyet)NqFs)GtIrTddX3G}zHBH0#JJlsh!8bjsRrw(WxPuSEC(xw{J z=Hkq5ZH)mBDF_TqEJV*TeFZj-azm;9G(vL+WVzKL+afvs%*BN}Ae2FcV&g_GU&Do@ z+r;96JGUp(B`uZ8U|r{j_WqwW9MbG>T8;OuCJ=()=IV7Aff&10Dd51y_rSA8PvIG! zR~oZmbf}VqsHN}QUhU~MyaV-4*V8a6&NB%83ZM}PYDo%TB%MGC5?An-?su$r2rZ7= z_j@v!XcwX(5J4rG>Niu*6h0=ct?H`pU9BZ_r~_QeAo-JzzRU{?5x$*SFHCFKwy&XNNdX6>6yPM-M_ zN4NH`Y>noI`(aTUPRF~ctdD*?pVmanx~60j#SQh2h&fAJ?LWS48}_l%aBi+Cwo3IB ztlq33+(f_|V7(r2uvxwz3zgGyd{QaqjsZFBpL%}q=gbGWx*UI%hq1VBkl~rUSqqYD zy>D}6W_VaQx7m0zH9YE4$g!(v?6MgH@oif`h5Tg=tevS~I~a(<>b5#wLg5lWIy3%V zxDLXe0fX3X_ulcFLgZhm<-lVW`h=UL;la{_@l&2)4hw1cR}gLf%lbQuJA`x^XD0#X z^f+cshm9VBP3_h4)29}}-qPiM!8W2GHi`}~_K=mt_c~4Y0zU~}f0cI~!w$bW*8Yzw} zJ*;efwp3Hi=Wse39mN(NzuxU`&0JAuVD)}~np|8qYM72hMe-d&v!$hBQ*$L>;{gpy z^2k>rui!E5`M-(w`oFPPfV<|8k68BDxFe3^i(vc_OuI)+1~In1y~@zd(?}Z`Y!Wrx zD;G1hLNWKYLRWL@#n%@K-HpLWC~$Y!n(Zz^S0f7^fIg3mLqA=yL*3=0I?K9?0Ywbdst*P{7xP$7FsLn*+vxnJ-qwS+zqvx&fy#s{n z=cibQ;f#Rw)4BTf{L5P3?zz9u1*7GU%08Qa!N zd`voXkO9}M$KqVh6iFi~rPzmNc%ty*=hJfjHD~FXx!1SYP{ko2po`sD>gpCv3_=Z_ zt_obbTr5EC#i0K4%=g1$xlYKz$b8c5R&t{FQ7Vxdq4+7DO*pzgr@-3E(m+3{I@!42 z)cj$GqWYZ?7%3uG=g%tXJ@hv4f@N82#Rx8cwZ{Nr4Bd0ePf~nSFP)SOKuFY=#C^Z# zQ4lP+fp4_B1;Lrq6|XFss{vz>)cjmgZI7~LVOy!1SMbv5WzAKwH=!J#Z?*DImUu3p zCZ3SJ;e0{i7tY4uK0x^akjn{L&3b?d%cvM>s<8-Z$= zfVlBDSrkhTLj}~3SQl-peP1X55RgElld_Eh1tiC8W$WHD!&A3z?tcE3Yvf8+GfG2k zp(^gk;S}PTgW(5@Y}t&*%UtOr1ab+RL_-^6q|>u736uuHb!t^|8Z=)p+%63rN*9r4 zducknL3$8jPxr}*V_-9j7DAj5wa;P-#Nip#%%vVt1w~TIKgX=~i~>4u9I36?Dy%U( z&eI)vy7W#toOvE^4gOJyUKj3^ie1U|wwxGpabJPU;ZEoQ-~kdmhx6eb$$Px|7jOx~ zej{i;bKzdh`g~|!&I!TEA*2am@Opfa6`wMQyk&#*kmb^$_W1PTUX;9-`MxG{J*sr! z>WKfMIJh3C`Jw-NLqq2&t@(eRe@FH}MQ6)@55fQY(l7Y$Kks<{J0t>}Pej$TLGf)z zJhFEPy#ezn|I&7XjD7+Ctl|G#(fyIeS0npZkEl~{(e^73eDR@>Ey{(-yXsN(pU>@a z2>cezLh#WKLRFpyWtx1M1cP9E+?8rKaSY#$zOD^__2kn26$;2|e|*ZrurcsThob6f zmxlTlFrbYD$$kLxuRdLSin7rgp2x=A$tMa6hSf)5-nfQ-^Ztpt!=uA29i=gYQTQ(w zaLK~->SOOV4dI`Ke$P3vUR9;of0`i{#P5m^UF1-|0tld%Gr}*$OMkBc1)t-$UcIfqUa`MJpZtTs+DZVZn zTF;pnPyR@*s=4Q77kEDarP3fV^z4j$y%o}g&1jYlvHAgc`u4(8JuJ}PjitG~`# zX_~_BzU2=#_D&HQ+|%p($0%M(?dQTxU5xLA;zyzB3Jc430!n_Ut?=(;ismIuuy^^J z4e4&}PAwZ*fFMm}a1Ykw1N&{1lffq7Z1AO5Xh*i%TCgW+bmrRpt6}_S^{qApb(SS1 z2!B!+ah9FzCJ+F9^7vLLAgAw3vPujNKV%ob#{eePtVYtDOzw*N=84``5GY@YBUGfa z-+2}x>NmUx1LloA2+6;(!DHsk>=zW@Zcdf5Nof+6AUi@;9STM1{YuT+xf5>$!*|p^ z!r1^;8Y);`4L1Bduh)h9oq?}rnjJ5X*V*lk53J`X9P&;ru80C1Ub2))!#Rzi0hAw? zmFRC4ip~xUOj{zIhM5gr;##qMoL?ynj(k<$4~RhS$5we1nC&F87(RRi1=fW`Xi~a6 zB=^l7renaAwyH)VHXoHyKx5d_Z^cC*I>5la0!9=46`|YM79{)8vzE)p@(6g^^4Ftg z|2Q^SIXaqtR<(IV`al>{A2}%zZeLajm(Yt`{}Qgb)83}30(NyP+AXc7zB-d@DI!v1 zbN@p&@cI6(qRFMCrxx1t9q%`%wmA)dyG{KE=wIKXL{C>^a?Rhw>r7b)Brzi^N`rD1 z;ywp)>zkYFrllM5nxNAtb1N^PBsMmt>d>#1pQTdzJ?ewS(Wa$Om!1dg(z-C%wbR?f zJk_e@bIg2FSC&*s6DbqbzQJTg_2@mdD1TdgR(Ka@x9SdietaRP{Rn7KnXBe(X#6TJ zWP}Qf{3Vbsc5VihSlgouC+n~G7ky|UBE@>Yc9j~-ki>0jQpDh6p+;R(=>sIBwzm4@ z?$*m5V7L|m95J%@OVkm zbQ(4Y;T`|IxM^YdN@ZA9MPp8#k9uH+f?+i9kLr!{_a50Ym1T$qj<3C*x`g!|I#z_} zEdjZoziT!GVat`_(?$q=$P3+u=BT|lAkqhrg2+|O;5*_P5 z?dgAMn6%ht67W(^rnq^>GYHDsp4Roj?)%uC)6%+}<(f02Q z3Ljup5c)YGVWU5!qnDeB-yX6t0wB1UdC-u#sH7~Nk8WMg(Lw%{iUDnn>~|yD&C1Fs zxn7f6gqnW5mgcWBaWQDEbtRswk(!v`XxN)uS61VNpgK)KOV2!~b3I7;Ds}Tc4H#I# zMbE&xD{8_$LtPCL8ED&un3NhEeJy7zfrhV$vm2nP&kUs;+&Ps?dPIxnQv9CFnE(l* z+H2|hfOf7Lln%B-afuR54XS!m)OP7wrd7D6bI(8kpyS$o*^gTSu!RO40T%Q!SE#M3 z(4eCWHGv0JbZC?{s>~q72B-(Qu%9WTm4I;k{`D#ORc`s#4T6Qn#zw8)@Rcp*%PLJi z)b!kyd0OiC0S z09hlAmMFkoms(JYmG&rjMBR}xEBHB~Cy!ehAn-U>En3CbZ?8qq9W9A>p%-BibxF4J z7_Fi&^r+QR!hkJ5BYH;khvo|4?@m z$f*2TJVt_c(z9)q`8a)%m{7mE0EnbW%guZKK6P3nbxr)K(+@C;WJZbH>B05E+@N^D zvp=tAiV{Cd5Wh4D@h3aH4k%vfPsXfaYC%7i=nbIQ9OJ+^{wtgV`_MQB&9{M-1)X;D z`^VfgbXAQPN1F3xERR6SkQ&J|A4IIXgV3)1YqoPv;VeByhFdBH<5#wPaemv;&GYys z`0U2e_rT-rVw`R9Rg87x4D>UTz-T)zo-v~5hIk96ffI1TvCJu;Nj+_%HS`;|$A>eN zGsX-U?a_M^*=n0ATT4Hz3{DPAC>}LAVDZM?BsBr&eIi2UYoCR&8SZC822pe_vK)+Zu^jIzH3R38A}@XcW*%O8U#f1I@aMx; zEp*()%d9GiC_*(IiZHl3*5qkZucsDRgf>xkUV?}n>FI-9#^U(-P>+U}b42yR&~zEX z-Ic0%65qK!P-8~NSmWJKfrOS1IDD))ipOjX3BxuvMXIX`#+-^v?AG&4^r%f$Te@Wo zHHo8Sgwesm%GaFG%qz#xqT41T`wkH-m=Gl={lOoFguvRgsvNFHa-Jb01JBJLP$+tQ z?hcd-R>PB5wyCt_{Td+<}F1BBY6-|=?@Y#Q$H zsmO7$H~XkKr|+lpc}VBz2O(I(lp(ywSE76PuxGepU_o&V>QmIjoJNL;OtcCb;)hNn z0f*-*jC2UdID8BYtlYhAH2{?K@Nt3$T&0#Rw_{4V&bH1X1wqsm79FESWO`xK^XY%T zk-F0iLQgwPKp1*yJ)PR-5(ABL{|rT9+t!N$)w~Np%psGQxR^}0 z%~v7#T9!-G7d9t>d*;INsK~rAwq6GJuJIfi1t#5N?xI`vJWk-36ZvF-m2rZ zjzAaaqG3Iyx~6Sq9s?jrU0ZZZ-MnH{q7fR67P$dO=uk)R^|K8o6sc@k9eA0z4Syk;VE*3f8B zjdnG&3C<^GH_Nq?V?P}VlgxY9NZ_wo2I-Xct@6C+B9kU)6r&wMN)LA9aTnF z(%xP5t=?MriXMpmu62}X;Vjll^sv*YF!#pkv&iV!{+J|LGT}xEg{47pK{#J)z`?ZE zHXvLqVhs*mvxy8n7mse2kT{n@rLqOT${M7~$&;4MupNq`hoFr`PTL1)kSTaq$hU+l z1WaI5EBV|=fi`(s70fFlgd!;4P8FL8`A(TJRuXA+S9%K+^lrsj)XFse0dU^l)gdD7 z6v*KMN%;Bj@x41vnvN~jnY+p+QVZWTZ(63Po5OK=D{RBVCy!>0mW35~L3Dh%ve^M5 z<%;7;XJ`&pd?O@;l_UdRI>U(!fGT)sFpxh@mcd@yC8W?s-tj(6vo7bw2Gt_DfZ1zb z1f>#vl2p3nE*&GV)0y~X6vYnXXfBb&%LAOIE+RZG;7=C3x;KA&rJ6c4l%lB%n;0Lj5+)+ZNXl#~Wj@$mllul`l6R-KhMm_ADx~i*+BByIe z%(v{%$q)>i^N)$Ot8sOx1@Uj-IFC$<^#|-7c+nxNLt)> z;Fwfzo1Aedq{10yGjM!#!Gb(#)c^fZbnSN|H&auzRDM9=IHU*8;3m!}!Bbd0r8E5! za4n3hngl5HXekf@sxe|&RIY&+Y*yZ>J*fiR!DCqvb?VfaAZCV^=`m9UMH+Yox>jLO zynqkDOi$Rrvm=`v=W|)aH%novZeeFe*V>Ro!YqAVEE?#A058$$W?^TF77V28PSlVpXkn)G;_#(hpwm`fC*{TSzR*6)i zkVlgMW|ix^roU)VnnF>2S3C7<4En^)@we!Vr%PgZSG0j0I`SI7eAHw-N)i3FM}y9D zDW17~RO*O@F^;vj$(6E{A`OiU^&rW$9K$@vwA&su(`eUe{_r-a5m>eFa{~r!S1{7j zZiNX`NnJG*0%^4<7OXaOeX|PC8B1mXprP$eo|inL^l|7<#VST^^1w-PTTgqld48Mn zC|}4!-~w-!?Uvq_p0kn6xMsjzIHA(HEhzj2ZHVBjD$wg=_i59b*{e;6Aq*Fp3i_yy zhFm&=oC!G#19eOsxftkKznmpVIaxo1OuE|@tp(n1^_7?7U&$rMz+tfz5-F#r1(Xv} zMC#HY%$-@Jxq5S7WS@frIED`wD#3ywi|HD(#;F^+#%)8&l@tiV_Be9%r%@}B%p5w) zPh*vX^s2@nN7Ryy)#v^6@bGX$9C&r*x%+#}W4#TXQ%kU5U;~Nh**X3tt33Y~3%Hi6 zrnMO3=H@k5a7fQU#mQm4q8X_yS$o7TGdcj{_y;jN#g2BeYP`b9%2IQz=nSKI8RODp zFemT%ij=npAUKT>Vw|i}Pf8G*ZGsF=?2@XxJPDHw6QZ4c#WThg5*k{hppzg;0zjjZ zx@!tZ1-1Uihnm3x844c9UL_UO`9325)4fsM2&7SNsN6`>Gpay{30-tc-flw#_Lvhg zh)}preX7yl-%pX7d^~C##ffoUn8EHX59a(NGD zkjPNakVAEq+uN{^mp6Ub>EvDBw+eZus=AcI6A`@Lp_9rDcheaw^X`BVf_I=6cl(9|uw>@xWzk;*e_0 zsL_sQ`@HeaqmqKF@XHX@#hJ<9{p9r$ybATfIlP&Ds+xOb3<;7A7M61jIWtEe^`_K9 zLr;(T+<#nn9^pK<$v!gk?7Df;Ntq~M@ocHsD-(VPHw*pD^5~glhKG}>zOzk3%p`WQ zqDf=!5ck(bmbPZa2puCk2E6*qDZKHGo3%&DEn-+292|Pc&ZTfgA?Gwq7<@0tzh2$> zX2b$eOw3f+0TLX!L+dqHzGZZ7R$ zU7`%BViRNhFN9N}h42ApfMX5=+!u*jIw$}@)j%z#OXY_YL|b1BB?wLwL>O<;pl(^N zeH4POHhF3CSsEJpo^fHHaT%!PR}k!%kwC!6llqEMW|L(j}|D2YSNf*%4TyJU_K zrQYdlU{t5LW=l9a_IUWcU?IV401S-D^X2g#^A1-rp{5N>r79%}f6pDM)Hr+wQn6q& zNvUrw8*iOVf};RiypVw2`xeefqP^^7a2Wj*x~ZfbTxE8<*_k?a$ZVhO@q*89-kcV< zUiTI&E411PDjS=P8U2HMX;dl;^VT@5qzyVt1x`@F#BIzp%(mL#9BpEcz(vncdAXxL z+1Edg(UP(rjwaoouNWA(Y{08(_4XmQ)$$tH+(d$$j&5+hqsA-k?E)8;&xPH{b$33Y zB2^r;H#ofTubC5@HBTzySq2#~z@Hu-%i2_B0w!Hw-pvh>^n^;L+1G1ii{c8$NI5zL zuqsEqtX|cu>FbLjHdu3025_E*k)sN&!C1mM*nkOkal!_ZFQP>ep@5@%^cpcpyc~_# zmHD*6=HxuC6?FSpffMQUA`l(8pOc$GTjR^Cmj+e__vGSk+bE{3AaQY~87xw!pO=v# zUHjXsSH@SWFbhpcNCzyns=Vs-X;Xkz2g}L5ta)6$i#Kz_?2L4EY^|)PVTwQSu1InL z3FV3B^XL~vo`sfE$p9K+%ra{cvbQu>M)@K;9(mt@`e0$^#-_NWP0HAhL+~95qKD(N zFxxX5+a<4IW)V-1)%6$HC&&oURpmm>QVAX|CQ&FgRM zM_E2ZPPm$JC!E8?Q2hv68WIf$Yzdb351y@aTaWlqsCN4V{XGsz}8n;w`e2#Xl zOmky}t?gACV~U-yf43Vz@x0`{$F%_JfkdiH*;uD#KbutB*oSV}w1(Gb)Db#!+%0MR zjdl<(&@VIJm%n{MAa@UIjhew}tUS6>$fiZ0zIl9giy?qSNvQQ=S#h30$jHW3jLdxd zBN~7p)Hkgq67%*oK2WobXTa60p&9LyJs`K{x2sG?LV`jh8OQ(-KYYwuFKy-)Rc(G{ zQm9q2HXy%Mm89uFrgtMM_|u`<1SSY>`9G|^Ra9Kf7A>4FxCBUWcY?dS6Qpr>cW+!1 z+zC#j!D-yx9U6Cc2_D?x=bU`!f4*bfTTeB*t7_LS+pA{PniKDLY{OM)>jkSQEN=Wy z7ycMmW9OQ#FRm-}!6*a~9yK~w;kmQ*@&HEYYd2n^i8($yQ$bF=Di(xe;Zgbm>}}5^ z)%Rm-VR}W~(&-?vHxlAm7!m3-2Xp+ixtWE7z4?O$I>P$iCHX$d)ur?TpOTNvMxzzX z@K3tbO9W98X-nlV;#tDU)n3NymA?@`#?k!d*t;94la+QyCqbsuO3j)^3iZ}G+{)?z--vO{n56Q4I?^Z=XW?@V*rZE!{e9-~3mLH$0v zIkmNrrq|C(ck5Ik4z?o&GhSZv^7XCHL7G{lbEoad=Jy>rq>4*Rve?W&`8&{Gpw@$< zZCTezcpG3whwv^^J*BS)_)m@kPkqG1T>H;aea7I9Z*_lxX#y|g?XtdpNs_F4D^3Ve zAEx|r$iI*IE^vNajiEet@U2`KrBJoFp@+0{sEF6j)ZO#@D!Z0#L60Bgl(iPQj#s*6 zl|;CgKTk$k2PR23#`VcZQ0`Z_1+MXx2kwybM}{Uo+n(=ekzsX@oBw?OIS)@@owxgkZfk!w@Dk)o$Jq)wS%bFeQdcB{I=X1ajb z*oe+6YzB`LX<^H(y4sXP?e>Aj=yh?|k=sB4wO=%;Pn%z2>AYIrpRaJR?FIEwA~fV^TCiWA$4pCB)nh)U&hk3KJq|!u8oK}3zSYkOC&`wjuxlH} zzId`T^|foC<-D#abOT)}K#~P0NgkmEaB(O-f_|4cyP%P?dt5Vi>l#*NC(wdK*Qi|t zKZr;Ub+?%de2 z>Lv09*zq25^kNj+-~rAB-S|KLLL)>>xlN{Jz^z`LGH)qzaI_^mTGUxR`W|YtxFFK` zLfRd4>n7;)ZO)l9X=IlLjUY^^K!!idvN(So_N&4mL3lh3r?HyM)kTnuuvSk|tU`!v ze_(`6YdBhuW5bWn4wPAC!wOWV)ykt9Qh|b0I`vI~>WUlIv^k;CCe){G-nZ5)=n7^w zRj@rp19~Vb?SZbDg3>MqVc(}m=Mp=<3#mo$iHT6C9mm_>YoXbU&5EEOcWrw1abyv-Gb0|5KtyHO6#t>*odK*l^aULf;{w@|o**lPJt%Tnsd(h> z*mtfHGAFi1AJ(S8COg&h&(^Yb19!)gZh`_%k0;;is+$sgHDTAvzcSPF59~8@jYw-( ziX6+O&7pkOA{xT^lN@((aWdcIr(~=-a8^^Bfrn36G)|9dGnYJtCV5JYSB~~!7S&9P znk#~`{(Q8V&6|&J$vDZ)_E2DK118M!Mms6BZL9lp<-`;{CWQpkfpr;fQAAtZWPx7G zva;-S^uD#CM)fHjTsQR9?c~Wd{KoKD<#|1awfK=UoqRB~=VQ_SKbJ`!F~g0&!2>?fW~%+3{EnUmuD<0ye!97DO8&sd486DHpzw*DL% z$}y%;t3@8FcJCtUWF}uom(JOft`Z->mOPWViDZ5PPAzYhN2D1o$LATQ!By%E6SUh z9J2Hka#%%)#(5mQCi8Of`U$NjOffK6c;M*ryJSg$*gSl*3KtVjIuTOC2#4ht_}?Ga zcdJ(T=G0&&4IE70epmC^1yc=L1<3}6nU$j;LA;(!7_~)uWai?H;X4_*u9^ef9akkU z%VS3VxTWiDia7f8$g03e@O+tQ2`G4xTxpN#Nq#966z1P_y3FIl)r1hdAF^muAKw|Fb#jmfkfK zN9r9`p^+)6MU^{9r~ZXQo3ZcRzdYB_d`Z5%f`uN*Wz|YO@mD6>(&z{5f3}-UaMhXyN1?ghR!Hz+s*rOQXM*S3;0Q zf2FRX5@#QxCLh&#Q+c5L_?fk|z6F&tJT)|}j^`fPh3aJKC!DrFuU0SV&vkln zKHAUmSM6?md_wy=w;DiRCY9Ozz`)lhfzh)gpWM|46b3hx&d_9{Moi3UX6UsNmo!4c zYWl7w0Qd|m5@1;13R-v=e3#2@&boj2rA>YGvh&ZuJ3WIh z?2_whxbeB;c(axBIFHdsXOeGdKPXZIar)F2^BXI58w{F{nnxJ@YfGQIH+0Pw=sNG( z=qmG*ni9W7#HWh0{P^bwG;AO<&jBbM$eYuu=X*A42umRRr9S_|*xMlO{N{KjP~kVw z{*CY1yI)NU<0j@%?#Vfo2^wNf529bo(y{hOaNvQ`q}sn|JOwk*$7oW(X0--HISy@*rMR?En@6?|*Mib^K#nxOTd+}?| zM0exz)QEE#tjxV(v?Zda!ynzoJ$@+qc@~5P?|vUTWdj)5=T8S%-`?}&m!JT~s8rw~ zFv!rZm@R~0;aPFjq#5mP8I6t*C7Jnlj2gTmt%jw2I;!J5 zMKE~gnOL0nKJsCs*6~MSfbe=YL>i-AK?q( zz1WZ>2>VZiso53%o%A-&YJ#M8Tzms{XMHJp9H~>i%qU6=G2D0!kC|6z@e$gRq&lXb zhWMu#HIn-Jh34c+x_t@Vl#nEa;nk={b>Kx;kMqEub$N*B#n|TR7hNSaikg~_T{ujY zcC@ahg;J6!J>dD5I}c{_45R!Z50Qa~##BR-B54_zWXb)&np?7~Uubh`6c+eJGjUb^ zvs>$POGM|yrpf(L_p^&(r1R>Nlb1GL_z}KWDz!j5Yw4#~lus?EhmIA*8;O8*2O)tR3ll-$6cQ?*R6tWwJAdnO_AUWtp{M)89I>ys=K+(n3 zZ8TjGqlX^kQ&4f>_)laEK+X%j?6^xH(U2!2ix6{|EWLQjPgc|X#);JJn`s)RyfG`2AY03tUR(x*GY@Ht zC@N}Q>ugb;o>W)V4bZg~mCu3beFYWfc9e&fAp;&0pdsWbW04VL%)?BjrD%~;rt>3x zg;IGRO@gO&Q-U&&kbv?>I%)O0N1HM@!?YbgEz%b^l9SP(Rf0#(IUvTm1{rv-x3txq;@dySxqF_Y zrjz61Z*bXuQKmYXR?VuO*zf@yv4b+fr!L~nEsZ>UK5JR4?!YANfuHKe)@}u@V1%M? z70y+0IOL6j3CL4i1!MR7!`IHB$v(x$%^%~pb%G5z4GtRwt!tF-6(`n!3ew9v+js65 z%kHmB#9pO`Ibs%s!@2oCo;oWjwTw5FCw5YCi_|UGZA_Lq6qQ=<8-}c57E_a zQnJoLwjAM_>eAXkow&ndd4WsUaVISm;Ad(1n0G1h8bY}9sgsg`!aXp5rlhq|7GJK# z_0Z9`#hAU_-y^GQfe7Y5<_z_uYLSpOuEUzMB=yF3e&QMz=aQ+!_ObR9@KlAdf#xDc z`V>|f<=qex$mO~G?gdg%RzHZWbyn9e5#pd{-N2ITVRCpzZbfNppKYy&3ky?a#lv8F zkInuKi==NLs=UsEANVS>9hdl_+sNlpN; z@-&<4moelWHO;TO)e<#zk##M(j6w9&I9{=qRS*2pq^7Bs6000pjd7W%NEUEqQvDd{ z+pf1z@hRAMeg16ulB|=dknb{LjT?Vr-|Kmv%Q_SV#k~Wns8F(U0C!#Oq%i&1YIFXi zsCo_Qs|BZpdh$NzTwZgrgQws-b6^BM4fN^!>gprUE%6?&d;b6ki$INYHs|;Do`rz+N$GW7+GOH=yN+P3(Jk8_v7(;S~%tDC#43&LvFhb#`F66&eRT>P0= zl^4$Nv&WpbbQSVi{Ip=G#!H-2+`UHPA6z*VZ3nP5JbiVX&Pu!D3|1%e_YZhrz$)}( zl(nWmDha6;N2#E4Z0$_!3~l8twEa5xZ`7%9qo{O)UDXP*OreWRwlo{6bE?TWPo)+? z*^O2rzgI8C+{$@2qfaWz=}?05v`%Ok$-T%DbQZ#g-o0v$L~G3bb%1k!MyzWJ8gtq# zm$AuXp1-7o;RYbF5g{J-t!WzU^(mS5wL9fi*H{m8nOVbda3rBrdzq}_V5b#TQ5eW6 z^l@6C4#I1VjxyH|6~M-Ov2WIw;2lLk$;Rbx56_@|4(J!_rqIAUw$_aZZr-|sqtiL2 zP0sxhwKWQnTDl&PQN6uJ)#{!`{{dfOQ$|au2M<4|qEr?_<^)2ULgA`PO4UO?bvXPJ zQgQEd5%buxH>5d222(&ukBj*Y=g@;Xjke6Pg4XR3+lh9UEzMmcaepwyes!JhSVl%LL{0USkZor!*2LlOY;kc~-TCahu@dTEXe2hOVpFCh2ccDL zABm>jgyvRkkBH7)!u7;#Uw({+gJQKC;Cd5?3FmM0aMr4LpnTh z=wz5Hs!v$}X4sbd4~?cG_HPwjgtz&gwhJ8oD5WWHDip^(?IfsTlECcp`u|UrQ&7g1FLphR|k#W>)f#)y?S^H z&*42$<79wbueQ~t$sP`Fx2QQt#Yjr3GNp(!JIh^G#x{_n_{r8;SjLQdd)QQ5qKQxz zQdL@9sEOnOHL9hnlm7@s+8dDXjcOf`P1vGTGp&a`5GzMXz@iobs8MP0cOh5Yw<`y$#d@W=4p#}1uy zbXRcHImSQ+if9WvHP4Gyl?ZIjbd~L`?hIzS(?azG|U z?o%wM{(AT14a=x;C_)+pg*n)of;}hnZOnW)w|J{s*Iu)RD6`=Vh~?y_oIM~g%C;Q5CAv-d4;Z)1yXf!GX^ zgzKq5L5n>Vxls-}y?Wu-t7RRxn;UbsLsf3!%mGP_M6}}K60E@&mfpT}DR#pkIdUS% ztSZ)wFfIO7bWGSl;cb9*@3hI)Rq4#t`uxC|K+;mwD2N)k*xwFBud8S<(I~JoNB{A# zml!8a#-k`I*l=x&hmWiUz9=;*KdoPTND|c~-H1RNVr3nUiYvvWd)4mAz1z-BnzUA$Zj3yAY=?DLn&M8X^PG}1ud3RmWu>tN0W7^rY6key z1G%`MqZj;^%w6h#ELM(zf5JewXXZZSt zI#-P}xmXx1^=B0mvFJ|#0fBxj^|8s_S(!xTYHprGE1RRUtKT3wG7QsM3g}=gsUk-y zZ;i_Fpsc8}vPuLmB>n_>(7vP_daJOC2EfEuO(KL&o(P1eg-Di5(GCPw%opnUVu^Mi z#?1x!%`DrnZWMr$mP{Mjk;+mK`Fho-xwwvP?M{x&;DaqBHH?>581JG$IYn$WY!ZS5 zKkHcq^b$A5KJl>5zwctsW8g%MG?dKj^rNvTUe92FGvL&hV5-HS+ zq%yTtfWYYt2n9MT+ovxe)#V|ElD=|PTC=^Ⱦ>KyZ}twQ9s}iy1Je$~0O+J@tNM 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%0D`&3^R(bHwp<@s?XR31(|GQtR(hzO6A=u<8R9 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 diff --git a/plugins/hanewari/token-meter-board/docs/validation.md b/plugins/hanewari/token-meter-board/docs/validation.md index 47cc64ca..d124adce 100644 --- a/plugins/hanewari/token-meter-board/docs/validation.md +++ b/plugins/hanewari/token-meter-board/docs/validation.md @@ -2,63 +2,188 @@ 本页记录本包提交官方 Mini App 市场前的自检结果,供审阅者复核。所有数字均来自本机实测。 -## 包检查(官方校验器) +**2.0.0 相对 1.9.0 的唯一主题:去掉对宿主内部存储的全部访问。** +1.9.0 从 `context.dataDir` 向上定位并打开了 MiniMax Code 的内部数据库,同时扫描观测日志、读取宿主 `config.yaml`。2.0.0 把这整条数据路径拿掉,改读客户端为**用户自己的对话**写下的会话记录。 + +--- + +## 一、评审意见逐条对照 + +评审结论为 `changes requested`,7 条内联意见。下面逐条列出 2.0.0 的处理方式。 + +| # | 评审意见(原文要点) | 评审定位 | 2.0.0 的处理 | +| --- | --- | --- | --- | +| 1 | `DatabaseSync` 直接打开了 MiniMax Code 的内部数据库,"只读模式不能作为例外" | `common.mjs:55` | **整个 `lib/common.mjs` 已删除**。包内不再有任何 `import ... from 'node:sqlite'`,回归测试对此有静态断言。 | +| 2 | 从插件 `dataDir` 向上查找并定位宿主内部数据库文件,"请去掉整条数据路径" | `server.mjs:29` | 向上查找的目标从数据库文件改为**会话记录目录** `v2/sessions`(与画廊 `mcode-token-usage-board` 同一套解析),数据库定位逻辑整段移除。 | +| 3 | 全表扫描宿主内部库的消息行,并取出用户消息前 200 字 | `facts.mjs:53` | **整个 `lib/facts.mjs` 已删除**。逐轮消息预览已从页面移除,对话表改用「所属会话」标识一轮。 | +| 4 | 从宿主内部库的会话表读取 `title` / `workspace_dir`;绝对工作区路径不应经插件 API 带出 | `queries.mjs:67` | 不再读宿主库。会话标题改取 transcript 中**首条用户消息的前 80 字**(与画廊同规则),会话 id 与模型 id 除外,**页面上没有任何绝对路径**。 | +| 5 | 观测日志属于宿主内部存储,"请与内部库访问一并移除" | `common.mjs:304` | 不再访问。模型显示名改用 transcript 里记录的原始模型 id,不再去别处补齐。 | +| 6 | 整文件读取宿主 `config.yaml`(可能含自定义 provider 配置) | `common.mjs:138` | 不再读取。 | +| 7 | 建议:`/api/health` 返回了绝对 `dataDir`,"请只返回 basename,或省略该字段" | `server.mjs:173` | 已改为 basename:`sessionsDir: "sessions"`。查询 `meta` 不再携带任何路径字段。 | +| 8 | 建议:报错文案里的绝对路径应脱敏 | `common.mjs:52` | 入口统一走 `redactPaths()`,页面收到的错误文案中绝对路径被替换为 ``;完整原文只进 Host 自己的日志。 | +| 9 | 建议:参考已有插件对 loopback `Host`(以及 `Origin`)的检查,降低 DNS rebinding 风险 | — | 已加 `isLoopbackRequest()`,与画廊 `plugins/yujiachen-y/repo-xray` 的实现逐行同款。 | +| 10 | `ENTRY_STDOUT` warning 可以保留;若整条子进程读库路径随红线一起删掉,warning 也会自然消失 | — | `lib/db-child.mjs` 已删除,warning 自然消失。**当前校验结果是 0 error 0 warning。** | + +### 为什么数据源换成会话记录 + +评审明确建议"例如画廊里已有、基于会话记录文件的做法"。本包采用的就是这一条: + +- 画廊里已合入的 `plugins/amszuidas/mcode-token-usage-board` 读的就是 `v2/sessions/**/messages.jsonl` + `manifest.json`; +- 路径解析方式一致:从宿主注入的 `context.dataDir` 向上找 `v2/sessions`,找不到时回落到 `~/.minimax`; +- 标题规则一致:取首条用户消息的前 80 字并剥离注入的 system reminder。 + +### 因此失去的能力(如实说明) + +会话记录里**没有**耗时,也**没有**工作区路径,所以 2.0.0 相应地取消了: + +- 输出速率、请求全程速率、P50/P90(原口径依赖 decode 耗时,transcript 里没有); +- 会话排行里的绝对工作区路径 tooltip; +- 每轮用户消息前 200 字预览; +- 来自 `config.yaml` 的模型显示名(表里写原始模型 id)。 + +保留的是:token 用量、缓存命中率、按模型分布、按天趋势、逐次调用台账、对话(turn)明细与对话状态、会话排行。**对话状态改由 transcript 的 `stopReason` 推导**(`stop` → 已完成,`toolUse` → 未收尾,`aborted` → 已中止,尚无模型调用 → 进行中)。 + +--- + +## 二、包检查(官方校验器) 用官方仓 `MiniMax-AI/MiniMax-Code-MiniApps` 的 `scripts/validate.mjs` 直接检查本包目录: ```text -token-meter-board: 0 errors, 1 warning - warning ENTRY_STDOUT writes to stdout, which belongs to the Host; log through context.logger instead (miniapp/node/lib/db-child.mjs) +token-meter-board: OK ``` -**关于 `ENTRY_STDOUT` 这条 warning**:它命中的是 `miniapp/node/lib/db-child.mjs`,而不是 Host 的入口 `miniapp/node/server.mjs`。该文件是我们自己 spawn 出来的子进程执行器(宿主运行时没有 `node:sqlite` 时才走这条路),它把查询结果写进 stdout,**父进程从这条管道读回来**——是父子进程之间的 IPC,不是宿主进程的输出通道;宿主的入口从未写 stdout(校验器对入口的判定是 error 级,此处并未触发)。 +**0 error、0 warning。** 1.9.0 时的 `ENTRY_STDOUT` warning(`lib/db-child.mjs` 写 stdout)随该文件删除而消失;不再需要"可解释的误报"说明。 -校验器的规则是静态扫描:`/\b(?:console\.(?:log|info|debug|dir|table)|process\.stdout\.write)\s*\(/u`,无法区分「宿主入口的 stdout」与「我们自己拉起的子进程的 stdout」。因此这条 warning 属于**可解释的误报**,按官方仓既有的处理方式(参见 `plugins/webguhui/minimax-photo/docs/validation.md`)**保留并在此说明,不修改检查器、也不隐藏代码**。该子进程路径在有 `node:sqlite` 的运行时里不会启用。 +--- -## 回归测试 +## 三、红线回归守卫 -对照 `assistant` 消息的 `usage.{input_tokens,output_tokens,cache_read}` 与用量行 `raw` 同名字段建立**无歧义配对真值**,再逐条核对看板给出的每次调用的 decode / 请求全程时长: +除了包校验器,回归脚本里另有一条针对评审红线的**静态断言**:直接扫描随包发布的运行时代码(`server.mjs`、`lib/sessions.mjs`、`lib/queries.mjs`、`client/index.html`),以下路径形态的字符串必须一处都不出现: -| 窗口 | 核对调用数 | 错配 | -| --- | --- | --- | -| 近 30 天 | 16787 | **0** | -| 近 7 天 | 11043 | **0** | -| 今天 | 1701 | **0** | -| 窗口起点落在某个 turn 中段 | 6515 | **0** | +```text +v2/sqlite runtime-state node:sqlite DatabaseSync +v2/observability config.yaml workspace_dir +workspaceDir userPreview +``` + +守卫用的 needle 是**路径形态**而不是普通词,所以源码里"我们不读观测日志"这类说明性注释不会误触发。 + +### 端到端回归(`tmb-v2-test.mjs`) + +对本机真实会话记录跑完整 HTTP 流程,全部通过: -修复前的同口径测量为:按下标配对错配 **22.5%**(3770/16723),即每 4~5 次调用就有 1 次显示的是**上一通**的 decode 与速率。 +| 检查 | 结果 | +| --- | --- | +| `/api/health` 200,`source = session-records` | PASS | +| `/api/health` 不含绝对路径(`sessionsDir = "sessions"`) | PASS | +| 扫描到 > 100 个 transcript 文件、> 5000 次调用 | PASS | +| `/api/window` 的 tokens / calls / turns 均非零,模型分布存在 | PASS | +| 模型名中无数据库相关串 | PASS | +| `/api/models`、`/api/sessions`、`/api/daily`、`/api/turns`、`/api/calls` 均 200 | PASS | +| 以上 5 个端点的响应体均不含绝对路径 | PASS | +| 非回环 `Host` → **403**;回环 `Host` → **200** | PASS | +| 未知查询参数(含 `?dataDir=C:\Windows`)被丢弃,不进入查询层 | PASS | +| 增量重扫 < 1500 ms(实测 **147–172 ms**) | PASS | +| 扫描游标落在插件 `dataDir` 内(1.46 MiB) | PASS | +| 上述 9 条"无禁用引用"静态断言 | PASS | +| 报错文案脱敏:`` 替换生效,400 响应体无绝对路径 | PASS | -状态码匹配同法核对:日志行在用量行之后落盘,按时间就近匹配会落到上一通的日志行(实测 2220 次失手**全部**偏上一通);改为取「该 turn 中第一条时刻不早于本次调用起点的日志行」后,可判定的 10124 条**命中率 100%**。 +--- -其余逐条通过的项目: +## 四、覆盖率:会话记录里还剩多少 -- **`dataDir` 注入**:`/api/*` 传入 `?dataDir=<他处路径>` 后返回的仍是宿主数据目录的数据(调用数、输出 token 逐字段一致);紧接着发出的、不带 `dataDir` 的正常请求也未被污染;`/api/health` 报告的 `dataDir` 仍是宿主目录。全部 7 个端点逐个比对,注入前后响应完全一致。 -- **对话明细计数**:`counts`(已完成 / 未收尾 / 进行中)之和等于 `totalTurns`,在 `days=7/limit=50`、`days=30/limit=10`、`days=1/limit=500` 三种组合下均成立(修复前只统计被 `limit` 截断后的部分)。 -- **用户消息预览**:全部 ≤ 200 字(库内原文最长 52262 字),截断在 SQL 内完成,原文不进入应用内存。 +会话记录不是完整账本。长对话被压缩(compaction)时,被压缩的那一段会被换成摘要,其中的调用就**不在任何** `messages.jsonl` 里了。 -## 性能 +测量方式:左边用**插件自己的读取器**(`SessionStore`)数,与看板显示的数字完全一致;右边打开客户端的内部账本**仅用于测量**(这段脚本不属于插件、也不会随包发布)。两边限制在**同一个时间窗**内比较——内部账本有自己的保留期,最早一行比会话记录晚三个多月,直接拿全量会话记录去比会高估缺口。 -同机同法 A/B(同一台机器交替运行 v1.8.0 与 v1.9.0,各端点连续 5 次取中位数、缓存已热): +参考机器实测(2026-10-23): -| 场景 | v1.8.0 | v1.9.0 | +**左侧 —— 会话记录(看板读到的)** + +| 项 | 值 | +| --- | --- | +| transcript 文件数 | 162 | +| 总体积 | 343.8 MiB | +| 调用次数(按 message id 全局去重) | 8,640 | +| 对话(turn)数 | 417 | +| 会话数 | 151 | +| 覆盖时间 | 2026-06-17 → 2026-10-23 | + +**右侧 —— 内部账本(仅参考,插件不读)** + +| 项 | 值 | +| --- | --- | +| 记录行数 | 13,124 | +| 会话数 | 121 | +| 覆盖时间 | 2026-09-28 → 2026-10-23(更早的行已被账本自己丢弃) | + +**同窗对比(2026-09-28 → 2026-10-23)** + +| | 会话记录 | 内部账本 | 覆盖率 | +| --- | --- | --- | --- | +| 调用次数 | 8,422 | 13,124 | **64.2%** | +| token 总量 | 1,133,235,393 | 2,099,198,213 | **54.0%** | + +缺口是**被压缩掉的调用**,不是统计口径错误。反方向也有:账本最早一行是 2026-09-28,那之前的 **220 次调用只剩会话记录还留着**——内部账本自己的保留期更短。 + +> 这些数字是"你的会话记录里还留着多少",**不是账单**。计费与配额以客户端自己的"用量"页面为准。 + +--- + +## 五、性能 + +同机、真实 HTTP 端到端实测(参考机器,162 个文件 / 343.8 MiB): + +| 场景 | 耗时 | +| --- | --- | +| 服务启动(不触发扫描) | 26 ms | +| **冷启动后第一个查询**(全量扫描所有 transcript) | **1,957 ms** | +| 增量重扫(3 秒 TTL 过期后的下一次刷新) | **168 ms** | +| TTL 命中(3 秒内的重复请求) | 3 ms | +| 新窗口的聚合构建 | 17 ms | + +各端点(聚合已就绪): + +| 端点 | 耗时 | 响应体 | | --- | --- | --- | -| 冷启动(进程内首次查询) | 1279 ms | 1350 ms | -| `/api/window?days=1` | 9 ms | **8 ms** | -| `/api/window?days=7` | 57 ms | **41 ms** | -| `/api/window?days=30` | 65 ms | **59 ms** | -| `/api/calls?days=1` | 4 ms | **3 ms** | -| `/api/turns?days=1` | 5 ms | **3 ms** | -| `/api/sessions?days=30` | 24 ms | **20 ms** | -| `/api/daily?days=7` | 19 ms | **17 ms** | -| 整页刷新(页面发出的 5 个请求) | 55 ms | **51 ms** | +| `/api/window?days=7` | 12 ms | 3,855 B | +| `/api/trend?days=7` | 17 ms | 2,766 B | +| `/api/summary?days=7` | 7 ms | 1,068 B | +| `/api/models?days=30` | 9 ms | 3,082 B | +| `/api/sessions?days=30&limit=50` | 11 ms | 24,416 B | +| `/api/daily?days=30` | 12 ms | 9,057 B | +| `/api/turns?days=7&limit=100` | 7 ms | 52,927 B | +| `/api/calls?days=1&limit=200` | 2 ms | 55,708 B | + +扫描游标 `session-scan-state.json`:**1.46 MiB**。 + +**关于增量读取。** 读取器为每个文件记住字节游标与首部哈希,只解析上次之后新追加的内容。上面 168 ms 是**真实的增量重扫**(已在 3 秒 TTL 之外计时);3 ms 那一行是 TTL 命中,什么都没重扫——两者不是一回事,不应混用。1.9.0 时代 README 里写的"一次刷新 2 毫秒"其实是 TTL 命中被当成了刷新成本,本版已按实测改正。 + +全量扫描 1,957 ms 是**冷启动的一次性代价**:游标写在插件自己的数据目录里,因此 Mini App 重启后也是接着上次继续,不会每次从头再读一遍。 + +--- + +## 六、数据与访问(摘要) + +| 项 | 实际情况 | +| --- | --- | +| 读取的文件 | `/v2/sessions/**/messages.jsonl`、`/v2/sessions/**/manifest.json`(**只读**) | +| 不再读取 | `v2/sqlite/runtime-state.sqlite`、`v2/observability/logs/`、`config.yaml` —— 任何模式都不会打开 | +| 写入的文件 | 仅 `<插件数据目录>/session-scan-state.json`(扫描游标,原子写入:先写临时文件再改名) | +| 网络 | 无。不访问任何远端主机,除了自己的源之外不发任何请求 | +| 子进程 | 无。不派生任何进程,不使用 shell | +| 查询参数 | 逐端点显式白名单;未列出的键在进入查询层之前就被丢弃 | +| Host / Origin | `Host` 头不指向回环地址、或 `Origin` 头不指向本监听端口 → **403** | +| 错误文案 | 绝对路径在出页面之前被替换为 `` | -各项持平或略快,无退化。冷启动 +5% 来自消息事实扫描里多做的两次 JSON 取值(判断该行是否为模型调用、对用户消息做 `substr` 截断);冷启动本身随机器负载在 0.9~1.4 s 之间浮动。 +--- -## 已验证环境 +## 七、已验证环境 - MiniMax Code 桌面端 **3.1.4**(build 186),Windows 11(10.0.22631,x64) -- 随附 Node.js **v24.18.0**,`node:sqlite` 可用 -- 已在桌面端验证:插件安装、窗口切换、自定义起止时间、逐次调用台账、对话明细实时增长、自动刷新、明暗双主题,以及运行时数据库缺失时的报错路径 -- macOS 与 Linux **未验证**:代码里没有平台相关逻辑(数据路径由 `context.dataDir` 解析),但请把其他平台视为未测 +- 随附 Node.js **v24.18.0**;本版本只用 `node:fs/promises` 与 `node:http`,不需要实验特性开关或原生模块 +- 已在桌面客户端中验证:插件安装、窗口切换、自定义起止窗口、逐次调用台账、对话明细实时增长、自动刷新、明暗双主题,以及找不到会话记录时的报错路径 +- macOS 与 Linux **未验证**:代码中没有平台相关逻辑(数据路径由 `context.dataDir` 解析),但请把其他平台视为未测 `docs/preview.png` 使用合成数据实拍,界面为中文。 diff --git a/plugins/hanewari/token-meter-board/miniapp/client/index.html b/plugins/hanewari/token-meter-board/miniapp/client/index.html index 0873ef04..6c987622 100644 --- a/plugins/hanewari/token-meter-board/miniapp/client/index.html +++ b/plugins/hanewari/token-meter-board/miniapp/client/index.html @@ -18,7 +18,7 @@ --mcode-chart-1:#0094fc; --mcode-chart-2:#2ea6a4; --mcode-chart-3:#e0932f; --mcode-chart-4:#d0567a; --mcode-chart-5:#6c5ce7; --mcode-chart-6:#8a9a5b; --mcode-chart-grid:#ececf1; --mcode-chart-axis:#9a9aa3; - --tmb-line-hit:#059669; --tmb-line-rate:#c026d3; + --tmb-line-hit:#059669; } @media (prefers-color-scheme: dark) { :root:not([data-theme='light']) { @@ -30,7 +30,7 @@ --mcode-chart-1:#3ea6ff; --mcode-chart-2:#45c0bd; --mcode-chart-3:#e5a84d; --mcode-chart-4:#e0709a; --mcode-chart-5:#8b7cf0; --mcode-chart-6:#a3b877; --mcode-chart-grid:#2a2a31; --mcode-chart-axis:#6e6e77; - --tmb-line-hit:#34d399; --tmb-line-rate:#e879f9; + --tmb-line-hit:#34d399; } } [data-theme='light'] { @@ -42,7 +42,7 @@ --mcode-chart-1:#0094fc; --mcode-chart-2:#2ea6a4; --mcode-chart-3:#e0932f; --mcode-chart-4:#d0567a; --mcode-chart-5:#6c5ce7; --mcode-chart-6:#8a9a5b; --mcode-chart-grid:#ececf1; --mcode-chart-axis:#9a9aa3; - --tmb-line-hit:#059669; --tmb-line-rate:#c026d3; + --tmb-line-hit:#059669; } [data-theme='dark'] { --mcode-bg:#171717; --mcode-bg-secondary:#1c1c1c; --mcode-surface:#262626; @@ -198,7 +198,6 @@ .hit { color: var(--mcode-success); } .hit.mid { color: var(--mcode-warning); } .hit.low { color: var(--mcode-danger); } -.rate-warn { color: var(--mcode-warning); } /* footer + toast */ .page-foot { font-size: 12px; color: var(--mcode-text-subtle); line-height: 1.7; margin-top: 4px; } @@ -256,7 +255,7 @@

Token 仪表盘

--
总 tokens
--
调用次数
--
缓存命中率
cacheRead / (cacheRead + input)
-
--tok/s
token 输出速率
中位数
+
--
对话次数
一次提问 = 一个 turn
--
活跃模型
@@ -268,7 +267,6 @@

Token 仪表盘

用量构成
-
@@ -288,10 +286,10 @@

Token 仪表盘

- - + + - +
提供商 / 模型调用输入输出缓存读缓存写总 tokens速率 (tok/s)命中率模型调用输入输出缓存读缓存写总 tokens命中率
加载中…
加载中…
@@ -309,10 +307,10 @@

Token 仪表盘

- - + + - +
日期调用输入输出推理缓存读缓存写总 tokens速率 (tok/s)命中率主要模型日期调用输入输出缓存读缓存写总 tokens命中率主要模型
加载中…
加载中…
@@ -330,10 +328,10 @@

Token 仪表盘

- - + + - +
时间模型输入输出推理缓存读缓存写速率 (tok/s)全程速率decode请求全程状态码时间模型输入输出缓存读缓存写总 tokens结束方式
加载中…
加载中…
@@ -351,9 +349,9 @@

Token 仪表盘

- + - +
开始时间用户消息状态时长调用输出总 tokens速率 (tok/s)命中率会话主要模型开始时间会话状态调用输出总 tokens命中率主要模型
加载中…
加载中…
@@ -374,16 +372,16 @@

Token 仪表盘

- + - +
会话Agent调用总 tokens速率 (tok/s)命中率主要模型最后活动会话调用总 tokens命中率主要模型最后活动
加载中…
加载中…
- 口径:总 tokens = 输入 + 输出 + 推理 + 缓存读 + 缓存写;命中率 = 缓存读 / (缓存读 + 输入);输出速率 = 输出 tokens ÷ decode 时长(首 token 到流结束),与 MiniMax Code 界面显示完全一致,窗口内按耗时加权;调用日志另列请求全程速率(发起请求→流结束,含首字等待);对话明细以一次提问(turn)为单位,用户发出消息后模型经若干次调用直至给出最终回答即为一次,实时读取、无需关闭会话,其时长为挂钟跨度、不参与速率计算。数据来自本机 runtime 用量记录(sqlite + 日志按 turn 补全 + config.yaml 显示名),只读。 + 口径:总 tokens = 输入 + 输出 + 缓存读 + 缓存写;命中率 = 缓存读 / (缓存读 + 输入);对话明细以一次提问(turn)为单位,实时读取、无需关闭会话。数据源:MiniMax Code 自己写下的会话记录文件(v2/sessions/**/messages.jsonl),只读;不打开宿主内部数据库、观测日志与配置,因此本页不提供 token 速率、也不显示任何工作区路径。
@@ -399,20 +397,7 @@

Token 仪表盘

function fmtLocal(iso) { var x = new Date(iso); return x.getFullYear() + '-' + pad(x.getMonth() + 1) + '-' + pad(x.getDate()) + ' ' + pad(x.getHours()) + ':' + pad(x.getMinutes()); } function fmtTime(iso) { var x = new Date(iso); return pad(x.getMonth() + 1) + '-' + pad(x.getDate()) + ' ' + pad(x.getHours()) + ':' + pad(x.getMinutes()); } function fmtTimeSec(ms) { var x = new Date(ms); return pad(x.getHours()) + ':' + pad(x.getMinutes()) + ':' + pad(x.getSeconds()); } -function fmtDur(ms) { - if (ms < 0) ms = 0; - var m = Math.round(ms / 60000); - if (m < 60) return m + 'm'; - var h = Math.floor(m / 60); - if (h < 24) return h + 'h' + pad(m % 60) + 'm'; - return Math.floor(h / 24) + 'd' + (h % 24) + 'h'; -} function pct(v) { return v == null ? '--' : (v * 100).toFixed(1) + '%'; } -function rateFmt(v) { - if (v == null) return '--'; - if (v >= 100) return String(Math.round(v)); - return (Math.round(v * 10) / 10).toFixed(1); -} function hitClass(v) { return v == null ? '' : v >= 0.8 ? 'hit' : v >= 0.5 ? 'hit mid' : 'hit low'; } function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; } function cssVar(name) { return getComputedStyle(document.documentElement).getPropertyValue(name).trim(); } @@ -463,7 +448,6 @@

Token 仪表盘

var followNow = true; var hiddenModels = new Set(); var showHit = true; -var showRate = true; function windowMs() { var start = new Date($('win-start').value).getTime(); @@ -502,7 +486,6 @@

Token 仪表盘

var parts = [ { label: '输入', value: kpis.inputTokens, color: cssVar('--mcode-chart-1') }, { label: '输出', value: kpis.outputTokens, color: cssVar('--mcode-chart-2') }, - { label: '推理', value: kpis.reasoningTokens, color: cssVar('--mcode-chart-5') }, { label: '缓存读', value: kpis.cacheReadTokens, color: cssVar('--mcode-chart-3') }, { label: '缓存写', value: kpis.cacheWriteTokens, color: cssVar('--mcode-chart-6') } ]; @@ -618,7 +601,6 @@

Token 仪表盘

}); // 曲线专用配色:与模型柱色系(chart-1..6)完全错开 var hitColor = cssVar('--tmb-line-hit'); - var rateColor = cssVar('--tmb-line-rate'); if (showHit) { datasets.push({ type: 'line', label: '缓存命中率', data: d.series.cacheHitRate, @@ -626,13 +608,6 @@

Token 仪表盘

pointRadius: 2.5, spanGaps: false, tension: 0.35, yAxisID: 'y1', order: 1 }); } - if (showRate) { - datasets.push({ - type: 'line', label: '输出速率', data: d.series.outputRate, - borderColor: rateColor, backgroundColor: rateColor, borderWidth: 2, - borderDash: [5, 3], pointRadius: 2, spanGaps: false, tension: 0.35, yAxisID: 'y2', order: 1 - }); - } if (!datasets.length) { if (chart) { chart.destroy(); chart = null; } setChartState('已隐藏所有展示元素,点击上方筛选恢复'); @@ -660,9 +635,6 @@

Token 仪表盘

if (ctx.dataset.yAxisID === 'y1') { return ' 缓存命中率: ' + (ctx.parsed.y == null ? '--' : (ctx.parsed.y * 100).toFixed(1) + '%'); } - if (ctx.dataset.yAxisID === 'y2') { - return ' 输出速率: ' + rateFmt(ctx.parsed.y) + ' tok/s'; - } return ' ' + ctx.dataset.label + ': ' + fmt.format(ctx.parsed.y) + ' tokens'; }, footer: function (items) { var i = items[0].dataIndex; return '调用 ' + d.series.calls[i] + ' 次 · 合计 ' + fmt.format(d.series.totalTokens[i]); } @@ -674,8 +646,7 @@

Token 仪表盘

y: { stacked: true, grid: { color: gridColor }, border: { display: false }, ticks: { color: axisColor, callback: function (v) { return compact(v); } } }, // grace 给命中率轴顶部留出余量,避免接近 100% 的曲线贴到绘图区顶边; // 超出 100% 的刻度不标注文字 - y1: { display: showHit, position: 'right', min: 0, grace: '8%', grid: { display: false }, border: { display: false }, ticks: { color: axisColor, callback: function (v) { return v <= 1.0001 ? (v * 100).toFixed(0) + '%' : ''; } } }, - y2: { display: showRate, position: 'right', min: 0, offset: true, grid: { display: false }, border: { display: false }, ticks: { color: axisColor, callback: function (v) { return compact(v) + '/s'; } } } + y1: { display: showHit, position: 'right', min: 0, grace: '8%', grid: { display: false }, border: { display: false }, ticks: { color: axisColor, callback: function (v) { return v <= 1.0001 ? (v * 100).toFixed(0) + '%' : ''; } } } } } }); @@ -693,14 +664,8 @@

Token 仪表盘

$('kpi-calls').textContent = fmt.format(d.kpis.calls); $('kpi-calls-sub').textContent = d.series.totalTokens.length ? '峰值 ' + compact(Math.max.apply(null, d.series.totalTokens.concat([0]))) + ' / 桶' : ''; $('kpi-hit').textContent = pct(d.kpis.cacheHitRate); - var rs = d.kpis.rate || {}; - var qs = d.kpis.requestRate || {}; - $('kpi-rate').textContent = rateFmt(rs.weighted != null ? rs.weighted : d.kpis.outputRate); - $('kpi-rate-sub').textContent = 'Σ输出÷Σdecode · P50 ' + rateFmt(rs.p50) + ' · N=' + fmt.format(rs.n || 0); - $('kpi-rate-sub').title = '口径与 MiniMax Code 界面一致:输出 tokens ÷ decode 时长(首 token 到流结束),窗口内按耗时加权(Σ输出 ÷ Σ耗时)。\n' + - (rs.n || 0) + '/' + fmt.format(d.kpis.calls) + ' 次可测,加权 ' + rateFmt(rs.weighted) + - '、P50 ' + rateFmt(rs.p50) + '、P90 ' + rateFmt(rs.p90) + '、峰值 ' + rateFmt(rs.max) + ' tok/s。\n' + - '对照:请求全程速率(发起请求→流结束,含首字等待)加权 ' + rateFmt(qs.weighted) + ' tok/s。'; + $('kpi-turns').textContent = fmt.format(d.kpis.turns || 0); + $('kpi-turns-sub').textContent = '覆盖 ' + fmt.format(d.kpis.sessions || 0) + ' 个会话'; $('kpi-models').textContent = d.kpis.activeModels; $('kpi-models-sub').textContent = d.models.map(function (m) { return m.modelName; }).join(' · '); @@ -709,9 +674,9 @@

Token 仪表盘

renderModelChips(d); $('trend-foot').textContent = - '来源:本机 runtime 用量记录(sqlite + 日志补全)' + - (d.unknownRows > 0 ? ' · ' + d.unknownRows + ' 条未识别模型(早于日志保留期)' : '') + - ' · 命中率 = cacheRead / (cacheRead + input) · 速率 = 桶内成功调用的加权速率(Σ输出 ÷ Σdecode),无调用的桶不绘制'; + '来源:本机会话记录文件(v2/sessions/**/messages.jsonl,只读)' + + ' · 命中率 = cacheRead / (cacheRead + input)' + + ' · 会话记录不含调用耗时,因此本页不提供 token 速率'; rebuildChart(d); } @@ -732,18 +697,16 @@

Token 仪表盘

} function tdNum(v) { return el('td', null, fmt.format(v)); } -function tdRate(v) { return el('td', null, rateFmt(v)); } function tdHit(v) { return el('td', hitClass(v), pct(v)); } function renderModels(d) { sectionError('models-err', null); - fillTable('models-body', 9, d.byModel, function (g) { + fillTable('models-body', 8, d.byModel, function (g) { var tr = el('tr'); var name = el('td', 'name'); var title = el('span', null, g.modelName); - title.title = g.provider + ' / ' + g.model; + title.title = g.model; name.appendChild(title); - name.appendChild(el('span', 'sub', g.providerName + (g.custom ? ' · 自定义接入' : ''))); tr.appendChild(name); tr.appendChild(tdNum(g.calls)); tr.appendChild(tdNum(g.inputTokens)); @@ -751,7 +714,6 @@

Token 仪表盘

tr.appendChild(tdNum(g.cacheReadTokens)); tr.appendChild(tdNum(g.cacheWriteTokens)); tr.appendChild(tdNum(g.totalTokens)); - tr.appendChild(tdRate(g.outputRate)); tr.appendChild(tdHit(g.cacheHitRate)); return tr; }, '该窗口内没有用量记录'); @@ -762,74 +724,39 @@

Token 仪表盘

} /* 调用日志:逐次调用明细(当前窗口,新的在前) */ +var STOP_LABEL = { 1: '正常结束', 2: '工具调用', 3: '已中止' }; + function renderCalls(d) { sectionError('calls-err', null); - fillTable('calls-body', 12, d.calls, function (c) { + fillTable('calls-body', 8, d.calls, function (c) { var tr = el('tr'); var time = el('td', null, fmtTimeSec(c.ts)); - time.title = c.time + ' · turn ' + (c.turnId || '--'); + time.title = c.time + (c.turnId ? ' · turn ' + c.turnId : ''); tr.appendChild(time); var name = el('td', 'name'); - var title = el('span', null, c.modelName); - title.title = c.provider + ' / ' + c.model; - name.appendChild(title); - if (c.custom) name.appendChild(el('span', 'tag', '自定义')); + name.appendChild(el('span', null, c.modelName)); tr.appendChild(name); tr.appendChild(tdNum(c.inputTokens)); tr.appendChild(tdNum(c.outputTokens)); - tr.appendChild(tdNum(c.reasoningTokens)); tr.appendChild(tdNum(c.cacheReadTokens)); tr.appendChild(tdNum(c.cacheWriteTokens)); - var rateCell = tdRate(c.outputRate); - rateCell.title = c.decodeMs != null - ? '输出 ' + fmt.format(c.outputTokens) + ' tokens ÷ decode ' + fmt.format(c.decodeMs) + 'ms(首 token → 流结束)——与 MiniMax Code 界面同口径' - : '该调用无 decode 计时(老数据),不参与速率统计'; - if (c.decodeMs != null && c.requestMs != null && c.decodeMs > c.requestMs) { - // decode > request 等价于首 token 早于请求发起:时间戳来自不同尝试,不计入速率聚合 - rateCell.classList.add('rate-warn'); - rateCell.title = - '该调用的两个时间戳不自洽(decode ' + fmt.format(c.decodeMs) + 'ms > request ' + fmt.format(c.requestMs) + - 'ms,等价于首 token 早于请求发起),通常出现在工具调用续传;不计入速率聚合,逐次值仅供核查。'; - } - tr.appendChild(rateCell); - var reqCell = tdRate(c.requestRate); - reqCell.title = c.requestMs != null - ? '输出 tokens ÷ 请求全程 ' + fmt.format(c.requestMs) + 'ms(含首字等待与排队)' - : ''; - tr.appendChild(reqCell); - var decCell = el('td', null, c.decodeMs != null ? (c.decodeMs / 1000).toFixed(1) + 's' : '--'); - decCell.title = c.decodeMs != null ? '模型实际输出耗时 ' + fmt.format(c.decodeMs) + 'ms' : ''; - tr.appendChild(decCell); - var durCell = el('td', null, c.requestMs != null ? (c.requestMs / 1000).toFixed(1) + 's' : '--'); - durCell.title = c.requestMs != null - ? '请求全程 ' + fmt.format(c.requestMs) + 'ms' + (c.decodeMs != null ? ',其中 decode ' + fmt.format(c.decodeMs) + 'ms' : '') - : ''; - tr.appendChild(durCell); - var st = el('td', c.status == null ? null : c.status === 200 ? 'hit' : 'hit low', c.status == null ? '—' : String(c.status)); - tr.appendChild(st); + tr.appendChild(tdNum(c.totalTokens)); + tr.appendChild(el('td', null, STOP_LABEL[c.stopReason] || '—')); return tr; }, '该窗口内没有调用记录'); } function renderSessions(d) { sectionError('sess-err', null); - fillTable('sess-body', 8, d.sessions, function (s) { + fillTable('sess-body', 6, d.sessions, function (s) { var tr = el('tr'); var name = el('td', 'name'); var title = el('span', null, s.title || s.sessionId); - title.title = s.sessionId + (s.workspaceDir ? '\n' + s.workspaceDir : ''); + title.title = s.sessionId; name.appendChild(title); - if (s.title) name.appendChild(el('span', 'sub', s.sessionId.slice(0, 12) + '…')); tr.appendChild(name); - tr.appendChild(el('td', null, s.agentName || '--')); tr.appendChild(tdNum(s.calls)); tr.appendChild(tdNum(s.totalTokens)); - var rateCell = tdRate(s.outputRate); - rateCell.title = '该会话成功调用的加权速率(Σ输出 ÷ Σdecode)'; - if (s.rate && s.rate.n) { - rateCell.appendChild(el('span', 'sub', 'Σ ' + rateFmt(s.rate.weighted) + ' · P50 ' + rateFmt(s.rate.p50))); - } - tr.appendChild(rateCell); tr.appendChild(tdHit(s.cacheHitRate)); var models = el('td', 'name'); models.appendChild(el('span', null, topModelNames(s.byModel, 2) || '--')); @@ -842,22 +769,15 @@

Token 仪表盘

function renderDaily(d) { sectionError('daily-err', null); var rows = d.days.slice().reverse(); // newest day first - fillTable('daily-body', 11, rows, function (day) { + fillTable('daily-body', 9, rows, function (day) { var tr = el('tr'); tr.appendChild(el('td', null, day.day)); tr.appendChild(tdNum(day.total.calls)); tr.appendChild(tdNum(day.total.inputTokens)); tr.appendChild(tdNum(day.total.outputTokens)); - tr.appendChild(tdNum(day.total.reasoningTokens)); tr.appendChild(tdNum(day.total.cacheReadTokens)); tr.appendChild(tdNum(day.total.cacheWriteTokens)); tr.appendChild(tdNum(day.total.totalTokens)); - var rateCell = tdRate(day.total.outputRate); - rateCell.title = '当天成功调用的加权速率(Σ输出 ÷ Σdecode)'; - if (day.total.rate && day.total.rate.n) { - rateCell.appendChild(el('span', 'sub', 'Σ ' + rateFmt(day.total.rate.weighted) + ' · P50 ' + rateFmt(day.total.rate.p50))); - } - tr.appendChild(rateCell); tr.appendChild(tdHit(day.total.cacheHitRate)); var models = el('td', 'name'); models.appendChild(el('span', null, topModelNames(day.byModel, 2) || '--')); @@ -870,6 +790,7 @@

Token 仪表盘

completed: { text: '已完成', cls: 'ok' }, unfinished: { text: '未收尾', cls: 'warn' }, pending: { text: '进行中', cls: 'live' }, + aborted: { text: '已中止', cls: 'warn' } }; function renderTurns(d) { @@ -878,43 +799,25 @@

Token 仪表盘

var summary = '本次窗口共 ' + d.totalTurns + ' 次对话(已完成 ' + (counts.completed || 0) + ' · 未收尾 ' + (counts.unfinished || 0) + ' · 进行中 ' + (counts.pending || 0) + ')'; - fillTable('turn-body', 11, d.turns, function (t) { + fillTable('turn-body', 8, d.turns, function (t) { var tr = el('tr'); tr.appendChild(el('td', null, fmtTime(t.startedAt))); - // the user's own words — this is the point of the table - var msg = el('td', 'name'); - var text = (t.userPreview || '').replace(/\s+/g, ' ').trim(); - msg.appendChild(el('span', null, text || '(无用户消息记录)')); - if (text.length > 60) msg.firstChild.title = text; - tr.appendChild(msg); + var sess = el('td', 'name'); + sess.appendChild(el('span', null, t.sessionTitle || t.sessionId)); + sess.firstChild.title = t.sessionId; + tr.appendChild(sess); var st = TURN_STATUS[t.status] || { text: t.status, cls: '' }; var stCell = el('td'); stCell.appendChild(el('span', 'tag ' + st.cls, st.text)); - if (t.finishReason) stCell.title = '末条 finish_reason = ' + t.finishReason; tr.appendChild(stCell); - tr.appendChild(el('td', null, t.durationMs == null ? '--' : fmtDur(t.durationMs))); tr.appendChild(tdNum(t.calls)); tr.appendChild(tdNum(t.outputTokens)); tr.appendChild(tdNum(t.totalTokens)); - - var rateCell = tdRate(t.outputRate); - rateCell.title = '与界面同口径:该次对话内 Σ输出 tokens ÷ Σdecode 时长(不含等待与工具执行)'; - tr.appendChild(rateCell); - if (t.rate && t.rate.n) { - var sub = el('div', 'sub', 'P50 ' + t.rate.p50 + ' · ' + t.rate.n + ' 次'); - rateCell.appendChild(sub); - } - tr.appendChild(tdHit(t.cacheHitRate)); - var sess = el('td', 'name'); - sess.appendChild(el('span', null, t.sessionTitle || t.sessionId.slice(0, 12) + '…')); - sess.firstChild.title = t.sessionId; - tr.appendChild(sess); - var models = el('td', 'name'); models.appendChild(el('span', null, topModelNames(t.byModel || [], 2) || '--')); tr.appendChild(models); @@ -981,7 +884,7 @@

Token 仪表盘

} catch (e) { if (!isCurrent('sessions', ticket)) return; sectionError('sess-err', '会话排行加载失败:' + e.message); - fillTable('sess-body', 8, [], null, '加载失败'); + fillTable('sess-body', 6, [], null, '加载失败'); } } async function refreshDaily() { @@ -993,7 +896,7 @@

Token 仪表盘

} catch (e) { if (!isCurrent('daily', ticket)) return; sectionError('daily-err', '每日统计加载失败:' + e.message); - fillTable('daily-body', 11, [], null, '加载失败'); + fillTable('daily-body', 9, [], null, '加载失败'); } } async function refreshTurns() { @@ -1007,7 +910,7 @@

Token 仪表盘

} catch (e) { if (!isCurrent('turns', ticket)) return; sectionError('turn-err', '对话明细加载失败:' + e.message); - fillTable('turn-body', 11, [], null, '加载失败'); + fillTable('turn-body', 8, [], null, '加载失败'); } } async function refreshCalls() { @@ -1021,7 +924,7 @@

Token 仪表盘

} catch (e) { if (!isCurrent('calls', ticket)) return; sectionError('calls-err', '调用日志加载失败:' + e.message); - fillTable('calls-body', 12, [], null, '加载失败'); + fillTable('calls-body', 8, [], null, '加载失败'); } } @@ -1036,14 +939,13 @@

Token 仪表盘

async function refreshHealth() { try { var h = await api('/api/health'); - if (!h.dbExists) { - showWinError('未找到本机 runtime 用量数据库(该 Mini App 需要在记录过用量的 MiniMax Code 数据目录上运行)。'); - return; - } $('page-foot').textContent = - '口径:总 tokens = 输入 + 输出 + 推理 + 缓存读 + 缓存写;命中率 = 缓存读 / (缓存读 + 输入);输出速率 = 输出 tokens ÷ decode 时长(首 token 到流结束,MiniMax Code 同口径);对话明细以一次提问(turn)为单位,实时读取、无需关闭会话。' + - '数据源:runtime sqlite(' + fmt.format(h.usageRows == null ? 0 : h.usageRows) + ' 行,只读)· Node ' + h.runtime.node + - (h.runtime.queryMode === 'child' ? ' · 子进程查询' : '') + '。'; + '口径:总 tokens = 输入 + 输出 + 缓存读 + 缓存写;命中率 = 缓存读 / (缓存读 + 输入);对话明细以一次提问(turn)为单位,实时读取、无需关闭会话。' + + '数据源:MiniMax Code 自己写下的会话记录文件(v2/sessions/**/messages.jsonl,只读;本次已扫描 ' + fmt.format(h.files) + ' 个文件 / ' + + fmt.format(h.calls) + ' 次调用)。不打开宿主内部数据库、观测日志与配置,因此本页不提供 token 速率、也不显示任何工作区路径。'; + if (!h.files) { + showWinError('未找到本机会话记录文件:该 Mini App 需要运行在写过会话的本机 MiniMax Code 数据目录上。'); + } } catch (e) { // health is advisory only } @@ -1139,7 +1041,6 @@

Token 仪表盘

/* line toggle chips */ bindLineToggle('flt-hit', function () { return showHit; }, function (v) { showHit = v; }); -bindLineToggle('flt-rate', function () { return showRate; }, function (v) { showRate = v; }); /* ---------- ask agent ---------- */ (function setupAskAgent() { @@ -1156,7 +1057,7 @@

Token 仪表盘

var text = '请分析我在 ' + label + ' 的 token 用量(token-meter 数据)' + (kpis ? ':总 tokens ' + fmt.format(kpis.totalTokens) + '、调用 ' + fmt.format(kpis.calls) + ' 次、缓存命中率 ' + pct(kpis.cacheHitRate) + - '、输出速率 ' + rateFmt(kpis.outputRate) + ' tok/s。重点看看缓存命中率是否还有优化空间,以及哪个模型消耗最多。' + '、对话 ' + fmt.format(kpis.turns || 0) + ' 次。重点看看缓存命中率是否还有优化空间,以及哪个模型消耗最多。' : '。'); btn.disabled = true; try { diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs deleted file mode 100644 index 1f3289f5..00000000 --- a/plugins/hanewari/token-meter-board/miniapp/node/lib/common.mjs +++ /dev/null @@ -1,707 +0,0 @@ -// token-meter shared helpers: data-dir resolution, catalog parsing, log enrichment, metrics. -import fs from 'node:fs'; -import path from 'node:path'; -import os from 'node:os'; -import { createRequire } from 'node:module'; -import { getFactsStore, syncFacts, assistantCallsForTurn, turnMetaForTurn, factsStats } from './facts.mjs'; - -export const SQLITE_REQUIREMENT = - 'token-meter requires Node.js 23.4+ (24 LTS recommended) so that the built-in node:sqlite module is available without flags.'; - -// node:sqlite is unflagged only on Node.js >= 23.4. Load it lazily so that an -// unsupported runtime gets a clear tool error instead of a process crash. -let sqliteModule; -let sqliteError; -function loadSqlite() { - if (sqliteModule === undefined && sqliteError === undefined) { - try { - sqliteModule = createRequire(import.meta.url)('node:sqlite'); - } catch (err) { - sqliteModule = null; - sqliteError = err; - } - } - return { sqlite: sqliteModule, error: sqliteError ?? null }; -} - -export function resolveDataDir(env = process.env) { - if (env.MINIMAX_DATA_DIR && fs.existsSync(env.MINIMAX_DATA_DIR)) { - return path.resolve(env.MINIMAX_DATA_DIR); - } - if (env.PLUGIN_DATA) { - // /v2/plugin-data// -> dataDir is four levels up. - const candidate = path.resolve(env.PLUGIN_DATA, '..', '..', '..', '..'); - if (fs.existsSync(path.join(candidate, 'v2'))) return candidate; - } - return path.join(os.homedir(), '.minimax'); -} - -export function dbPath(dataDir) { - return path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); -} - -// Open the runtime state database read-only. -// Returns { db, error }: exactly one of the two is non-null. -export function openDb(dataDir) { - const { sqlite, error: sqliteErr } = loadSqlite(); - if (!sqlite) { - return { db: null, error: `${SQLITE_REQUIREMENT} (${sqliteErr?.code || sqliteErr?.message || 'node:sqlite unavailable'})` }; - } - const file = dbPath(dataDir); - if (!fs.existsSync(file)) { - return { db: null, error: `runtime state database not found at ${file} — is this a MiniMax Code data directory with recorded usage?` }; - } - try { - return { db: new sqlite.DatabaseSync(file, { readOnly: true }), error: null }; - } catch (err) { - return { db: null, error: `failed to open runtime state database read-only: ${err.message}` }; - } -} - -// The message fact store is shared per runtime database, so every query in this -// process reuses the same extraction instead of re-parsing the message table. -export function factsStore(dataDir) { - return getFactsStore(dataDir); -} - -// Snapshot of the message-fact cache, for the health endpoint. -export { factsStats }; - -// Query raw usage rows in [startMs, endMs] ascending by ts. -export function queryUsageRows(db, startMs, endMs) { - return db - .prepare( - `SELECT session_id, agent_name, turn_id, model, ts, - input_tokens, output_tokens, reasoning_tokens, - cache_read_tokens, cache_write_tokens, cost_usd - FROM local_runtime_token_usage - WHERE ts >= ? AND ts <= ? - ORDER BY ts`, - ) - .all(startMs, endMs); -} - -export function dayKey(ms) { - const d = new Date(ms); - const y = d.getFullYear(); - const m = String(d.getMonth() + 1).padStart(2, '0'); - const dd = String(d.getDate()).padStart(2, '0'); - return `${y}-${m}-${dd}`; -} - -export function clampInt(value, min, max, fallback) { - const n = Number.parseInt(value, 10); - if (Number.isNaN(n)) return fallback; - return Math.min(max, Math.max(min, n)); -} - -// Resolve a query window. Either explicit startDate/endDate (YYYY-MM-DD, inclusive, -// local time) or `days` = trailing N days including today. -export function resolveWindow({ days, startDate, endDate } = {}, now = Date.now()) { - if (startDate) { - const start = new Date(`${startDate}T00:00:00`); - const endBase = endDate ? new Date(`${endDate}T23:59:59.999`) : new Date(start.getTime() + 86400000 - 1); - if (Number.isNaN(start.getTime()) || Number.isNaN(endBase.getTime())) { - throw new Error(`invalid startDate/endDate: ${startDate} ${endDate || ''}`.trim()); - } - const startMs = start.getTime(); - const endMs = Math.min(endBase.getTime(), now); - if (endMs < startMs) throw new Error('window end is before start'); - return { startMs, endMs, label: `${dayKey(startMs)}..${dayKey(endMs)}` }; - } - const n = clampInt(days ?? 1, 1, 90, 1); - const todayStart = new Date(); - todayStart.setHours(0, 0, 0, 0); - const startMs = todayStart.getTime() - (n - 1) * 86400000; - return { startMs, endMs: now, label: n === 1 ? dayKey(startMs) : `${dayKey(startMs)}..${dayKey(now)}` }; -} - -// --- config.yaml catalog (provider/model display names) ---------------------- - -function unquote(value) { - const v = value.trim(); - if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) { - return v.slice(1, -1); - } - return v; -} - -// Minimal line-based YAML reader targeting only the provider sections we need. -// Returns { providers: Map, modelNames: Map<'providerId/modelId', name>, -// modelToProvider: Map }. -// -// The catalog is read from the same config.yaml on every query, so it is cached -// per (mtime, size) and only re-parsed when the file actually changes. -let catalogCache = null; - -export function loadCatalog(dataDir) { - const file = path.join(dataDir, 'config.yaml'); - let stamp = null; - try { - const st = fs.statSync(file); - stamp = `${st.mtimeMs}:${st.size}`; - } catch { - stamp = null; - } - if (catalogCache && catalogCache.stamp === stamp) return catalogCache.catalog; - const catalog = parseCatalog(file); - catalogCache = { stamp, catalog }; - return catalog; -} - -function parseCatalog(file) { - const providers = new Map(); - const modelNames = new Map(); - const modelToProvider = new Map(); - let text; - try { - text = fs.readFileSync(file, 'utf8'); - } catch { - return { providers, modelNames, modelToProvider }; - } - try { - // ctx: null | { section: 'custom'|'builtin', providerId, providerIndent, inModels, modelId, modelIndent } - let ctx = null; - for (const rawLine of text.split('\n')) { - if (!rawLine.trim() || rawLine.trimStart().startsWith('#')) continue; - const indent = rawLine.length - rawLine.trimStart().length; - const line = rawLine.trim(); - - if (indent === 0) { - if (line === 'custom_provider:') { - ctx = { section: 'custom', providerId: null, providerIndent: -1, inModels: false, modelId: null }; - } else if (line === 'provider:') { - ctx = { section: 'builtin', providerId: null, providerIndent: -1, inModels: false, modelId: null }; - } else if (!line.startsWith('-')) { - ctx = null; // left the provider sections - } - continue; - } - if (!ctx) continue; - - // Provider entry: " provider-c582e6:" or " minimax:" - if (ctx.providerId === null || indent <= ctx.providerIndent) { - const m = line.match(/^([A-Za-z0-9._-]+):\s*$/); - if (m && indent >= 2) { - ctx.providerId = m[1]; - ctx.providerIndent = indent; - ctx.inModels = false; - ctx.modelId = null; - if (!providers.has(ctx.providerId)) { - providers.set(ctx.providerId, { name: ctx.providerId, kind: ctx.section }); - } - continue; - } - } - if (!ctx.providerId) continue; - - const kv = line.match(/^([A-Za-z0-9._-]+):\s*(.*)$/); - if (!kv) continue; - const [, key, rest] = kv; - - if (key === 'models' && rest === '') { - ctx.inModels = true; - ctx.modelId = null; - ctx.modelIndent = -1; - continue; - } - if (!ctx.inModels && key === 'name' && rest) { - providers.get(ctx.providerId).name = unquote(rest); - continue; - } - if (ctx.inModels) { - if (ctx.modelId === null || indent <= ctx.modelIndent) { - const mm = line.match(/^([A-Za-z0-9._-]+):\s*$/); - if (mm) { - ctx.modelId = mm[1]; - ctx.modelIndent = indent; - modelToProvider.set(ctx.modelId, ctx.providerId); - continue; - } - } - if (ctx.modelId && key === 'name' && rest) { - modelNames.set(`${ctx.providerId}/${ctx.modelId}`, unquote(rest)); - } - } - } - } catch { - // tolerate partial catalog - } - return { providers, modelNames, modelToProvider }; -} - -// --- runtime log enrichment (turn_id -> provider/model, per-call status) ----- -// -// Log files rotate hourly: runtime-YYYYMMDDHH.log (local time). Select files by -// filename hour intersecting the window (plus 1h look-behind for stragglers), -// so coverage spans the whole window instead of just the newest few files. -// Each llm_response_identifiers line contributes one call record with its own -// timestamp and response_status; a turn produces one line per LLM call. - -const LOG_LINE_TS = /^\[(\d{2}):(\d{2}):(\d{2})\.(\d{3})\]/; - -// Log files rotate hourly and are append-only, so a file whose (mtime, size) is -// unchanged still holds exactly the same records. Caching per file means a -// window switch re-reads only the hour currently being written instead of -// rescanning every hour of the window — that was ≈750 ms on a one-week window. -const logFileCache = new Map(); // absolute path -> { stamp, records } -const LOG_FILE_CACHE_MAX = 256; // bound the memory of a long-running runtime - -function stampOf(st) { - return `${st.mtimeMs}:${st.size}`; -} - -function parseLogFile(file, maxBytesPerFile) { - const records = []; - let text; - try { - const st = fs.statSync(file); - const fd = fs.openSync(file, 'r'); - try { - const start = st.size > maxBytesPerFile ? st.size - maxBytesPerFile : 0; - const buf = Buffer.alloc(st.size - start); - fs.readSync(fd, buf, 0, buf.length, start); - text = buf.toString('utf8'); - } finally { - fs.closeSync(fd); - } - } catch { - return null; - } - for (const line of text.split('\n')) { - const i = line.indexOf('llm_response_identifiers '); - if (i < 0) continue; - const j = line.indexOf('{', i); - if (j < 0) continue; - let obj; - try { - obj = JSON.parse(line.slice(j)); - } catch { - continue; // partial tail line or unexpected shape - } - if (!obj || !obj.turn_id) continue; - const tm = line.slice(0, i).match(LOG_LINE_TS); - // Seconds since local midnight. The capture groups are strings, so they - // must be coerced explicitly — `a + tm[3]` would concatenate instead of add. - const ts = tm - ? Number(tm[1]) * 3600 + Number(tm[2]) * 60 + Number(tm[3]) + Number(tm[4]) / 1000 - : null; - records.push({ - turn_id: obj.turn_id, - provider: obj.provider || null, - model: obj.model || null, - status: typeof obj.response_status === 'number' ? obj.response_status : null, - ts, - }); - } - return records; -} - -export function loadTurnEnrichment(dataDir, windowStartMs, options = {}) { - const maxBytesPerFile = options.maxBytesPerFile ?? 12 * 1024 * 1024; - const now = options.now ?? Date.now(); - const map = new Map(); - const dir = path.join(dataDir, 'v2', 'observability', 'logs'); - let names; - try { - names = fs.readdirSync(dir).filter((f) => /^runtime-\d+\.log$/.test(f)); - } catch { - return { map, filesScanned: 0 }; - } - const firstHour = new Date(windowStartMs - 3600000); - firstHour.setMinutes(0, 0, 0); - let filesScanned = 0; - for (const name of names) { - const m = name.match(/^runtime-(\d{4})(\d{2})(\d{2})(\d{2})\.log$/); - if (!m) continue; - const fileHourMs = new Date(+m[1], +m[2] - 1, +m[3], +m[4]).getTime(); - if (fileHourMs < firstHour.getTime() || fileHourMs > now + 3600000) continue; - const p = path.join(dir, name); - let stamp = null; - try { - stamp = stampOf(fs.statSync(p)); - } catch { - continue; - } - const cached = logFileCache.get(p); - let records; - if (cached && cached.stamp === stamp) { - records = cached.records; - } else { - const parsed = parseLogFile(p, maxBytesPerFile); - if (!parsed) continue; - records = parsed; - logFileCache.set(p, { stamp, records }); - while (logFileCache.size > LOG_FILE_CACHE_MAX) { - const oldest = logFileCache.keys().next().value; - if (oldest === p) break; - logFileCache.delete(oldest); - } - } - filesScanned += 1; - // The log line carries a wall-clock time; the file name carries the hour it - // belongs to, so the absolute timestamp is the file's day base plus that. - const dayBase = new Date(+m[1], +m[2] - 1, +m[3]).getTime(); - for (const rec of records) { - if (!map.has(rec.turn_id)) map.set(rec.turn_id, { provider: null, model: null, calls: [] }); - const entry = map.get(rec.turn_id); - if (!entry.provider && rec.provider) entry.provider = rec.provider; - if (!entry.model && rec.model) entry.model = rec.model; - entry.calls.push({ ts: rec.ts == null ? null : dayBase + rec.ts * 1000, status: rec.status }); - } - } - for (const entry of map.values()) entry.calls.sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0)); - return { map, filesScanned }; -} - -// --- row identity + metrics --------------------------------------------------- - -export function resolveRowIdentity(row, enrichment, catalog) { - let model = row.model || null; - let provider = null; - const hit = row.turn_id ? enrichment.get(row.turn_id) : null; - if (hit) { - provider = hit.provider || null; - model = model || hit.model || null; - } - let providerId = null; - let custom = false; - if (provider && provider.startsWith('custom_provider:')) { - providerId = provider.slice('custom_provider:'.length); - custom = true; - } else if (provider) { - providerId = provider; - custom = catalog.providers.get(providerId)?.kind === 'custom'; - } - if (!providerId && model && catalog.modelToProvider.has(model)) { - providerId = catalog.modelToProvider.get(model); - custom = catalog.providers.get(providerId)?.kind === 'custom'; - provider = custom ? `custom_provider:${providerId}` : providerId; - } - const modelKey = providerId && model ? `${providerId}/${model}` : null; - return { - provider: provider || 'unknown', - providerId: providerId || 'unknown', - model: model || '(unknown)', - custom, - providerName: (providerId && catalog.providers.get(providerId)?.name) || provider || 'unknown', - modelName: (modelKey && catalog.modelNames.get(modelKey)) || model || '(unknown)', - }; -} - -export function emptyMetrics() { - return { - calls: 0, - inputTokens: 0, - outputTokens: 0, - reasoningTokens: 0, - cacheReadTokens: 0, - cacheWriteTokens: 0, - totalTokens: 0, - cacheHitRate: null, - costUsd: 0, - }; -} - -export function addRow(m, r) { - m.calls += 1; - m.inputTokens += r.input_tokens || 0; - m.outputTokens += r.output_tokens || 0; - m.reasoningTokens += r.reasoning_tokens || 0; - m.cacheReadTokens += r.cache_read_tokens || 0; - m.cacheWriteTokens += r.cache_write_tokens || 0; - m.costUsd += r.cost_usd || 0; -} - -export function finalize(m) { - m.totalTokens = m.inputTokens + m.outputTokens + m.reasoningTokens + m.cacheReadTokens + m.cacheWriteTokens; - const denom = m.inputTokens + m.cacheReadTokens; - m.cacheHitRate = denom > 0 ? Math.round((m.cacheReadTokens / denom) * 10000) / 10000 : null; - m.costUsd = Math.round(m.costUsd * 1e6) / 1e6; - return m; -} - -export function sortGroups(groups) { - return groups.sort((a, b) => { - if (a.custom !== b.custom) return a.custom ? -1 : 1; - return b.totalTokens - a.totalTokens; - }); -} - -// --- per-call ledger (usage rows joined with message timing + log status) ---- -// -// local_runtime_token_usage never stores the model and has no call duration. -// One side source completes the picture: assistant message rows -// (local_runtime_message_rows.data_json) carry the very timings MiniMax Code -// itself uses for pi_llm_tokens_per_second — usage.request_duration_ms (request -// start → stream end) and usage.decode_duration_ms (first token → stream end) — -// plus finish_reason. Log lines additionally carry response_status. -// -// Pairing: inside a turn the runtime writes two records per call — the usage -// row is stamped when the call STARTS, and the matching assistant message is -// written when that call ENDS. So the message that belongs to a call that -// started at T is the FIRST message of that turn written at or after T: every -// earlier message of the turn was written before this call started. -// -// That rule replaces the old "the i-th message pairs with the i-th usage row", -// because the message sequence also holds rows that are not model calls at -// all — context compaction writes an assistant row with no usage block (490 -// of the 17,214 assistant messages on this machine). Counting those as calls -// shifted a whole turn by one, so 22.5% of the calls reported the PREVIOUS -// call's decode duration and rate. With the "first message at or after the -// call start" rule all 16,723 measurable calls pair correctly (0 errors), and -// it stays correct when the query window starts in the middle of a turn. -// -// There is deliberately no upper bound on how long a single call may take — -// see the interleaving invariant in buildCallLedger. - -// Bring the in-memory fact store up to date with the database, then hand it -// back. Extracting the message facts is the expensive part of a query, so it -// happens once per process and only picks up newly appended rows afterwards. -export function syncMessageFacts(db, dataDir, options = {}) { - const store = factsStore(dataDir); - syncFacts(store, db, options); - return store; -} - -// Assistant call timings per turn, keyed `${session_id}|${turn_id}`. -// The facts come from the shared store, so this no longer touches the -// message table at all. -export function loadAssistantCallDetails(rows, store) { - const byTurn = new Map(); // key `${session_id}|${turn_id}` -> [{ts, decodeMs, requestMs, finishReason}] - for (const r of rows) { - if (!r.turn_id) continue; - const key = `${r.session_id}|${r.turn_id}`; - if (byTurn.has(key)) continue; - const list = assistantCallsForTurn(store, r.turn_id); - if (list) byTurn.set(key, list); - } - return byTurn; -} - -// Per-turn message metadata for the conversation table. -// -// A turn is exactly one user message followed by however many model calls the -// agent needed before answering, so it is the natural unit for "one thing the -// user asked" — and it is readable from the database the instant the first -// usage row of that turn lands, with no hook and no waiting for the session -// to close. Verified on this machine: 26 turns today, 24 carrying exactly one -// user message, 0 carrying more than one, and all 26 ending on an assistant -// message. -export function loadTurnMessageMeta(rows, store) { - const meta = new Map(); // turn_id -> {userTs, userPreview, lastTs, finishReason, assistantCount} - for (const r of rows) { - if (!r.turn_id || meta.has(r.turn_id)) continue; - const m = turnMetaForTurn(store, r.turn_id); - if (m) meta.set(r.turn_id, m); - } - return meta; -} - -// Build one ledger entry per usage row, ordered by ts. -// -// Pairing (see the header comment for the full invariant): -// - the assistant message is the first message of the turn written at or -// after the call started; -// - the log line is the first llm_response_identifiers record of the turn -// written at or after the call started, and not after the next call of -// the same turn started. -// -// rate = output_tokens / decode_duration. -// -// Validity is the interleaving invariant, not an absolute duration limit: a call -// cannot finish before it starts, and cannot finish after the *next* call in the -// same turn has already started. An absolute cap would reject legitimate long -// calls (a 9-minute run) and push the pairing back onto nearest-neighbour matching, -// which shifts every following row by one — so there is deliberately no upper -// bound on how long a single call may take. - -export function buildCallLedger(rows, enrichment, assistantByTurn, catalog) { - const ledger = []; - const msgCursor = new Map(); // turn key -> next assistant message index - const logCursor = new Map(); // turn key -> next log record index - for (let i = 0; i < rows.length; i += 1) { - const row = rows[i]; - const id = resolveRowIdentity(row, enrichment, catalog); - const key = `${row.session_id}|${row.turn_id}`; - const next = rows[i + 1]; - // The next call of the SAME turn bounds the interval this call owns. - const boundTs = next && next.turn_id === row.turn_id ? next.ts : null; - - // --- assistant message (decode / request timing, finish reason) --- - let msg = null; - const list = row.turn_id ? assistantByTurn.get(key) : null; - if (list && list.length) { - const from = msgCursor.get(key) || 0; - for (let j = from; j < list.length; j += 1) { - const c = list[j]; - // written before this call started — belongs to an earlier call - if (c.ts == null || c.ts < row.ts) continue; - msg = c; - msgCursor.set(key, j + 1); - break; - } - } - - // --- log line (response status) --- - // The runtime writes the llm_response_identifiers line a moment AFTER the - // usage row is stamped (measured: +443 ms … +194 s, median +2.6 s), so a - // nearest-time match walks BACKWARDS and lands on the PREVIOUS call's - // line: of 2220 measured mismatches, every single one was off by one in - // that direction. The matching record is the first one at or after this - // call's start. - let statusHit = null; - const enrichEntry = row.turn_id ? enrichment.get(row.turn_id) : null; - if (enrichEntry && enrichEntry.calls.length) { - const from = logCursor.get(key) || 0; - for (let j = from; j < enrichEntry.calls.length; j += 1) { - const c = enrichEntry.calls[j]; - if (c.ts == null || c.ts < row.ts) continue; - // written after the next call of this turn started — that one owns it - if (boundTs != null && c.ts > boundTs) break; - statusHit = c; - logCursor.set(key, j + 1); - break; - } - } - const status = statusHit ? statusHit.status : null; - const decodeMs = msg ? msg.decodeMs : null; - const requestMs = msg ? msg.requestMs : null; - const output = row.output_tokens || 0; - const succeeded = status == null || status === 200; // a recorded usage row implies a completed call - // Headline rate: identical to the desktop UI's tokens/s — output tokens ÷ decode - // duration (first token → stream end), the span during which tokens actually arrive. - const rate = succeeded && decodeMs > 0 && output > 0 ? Math.round((output / (decodeMs / 1000)) * 100) / 100 : null; - // Whole-request reference (output ÷ request_duration_ms); the gap between the two - // is time-to-first-token plus queueing. - const requestRate = - succeeded && requestMs > 0 && output > 0 ? Math.round((output / (requestMs / 1000)) * 100) / 100 : null; - ledger.push({ - ts: row.ts, - sessionId: row.session_id, - agentName: row.agent_name || null, - turnId: row.turn_id || null, - // identity (from resolveRowIdentity) - provider: id.provider, - providerId: id.providerId, - model: id.model, - custom: id.custom, - providerName: id.providerName, - modelName: id.modelName, - // snake_case token fields keep addRow() compatibility - input_tokens: row.input_tokens || 0, - output_tokens: row.output_tokens || 0, - reasoning_tokens: row.reasoning_tokens || 0, - cache_read_tokens: row.cache_read_tokens || 0, - cache_write_tokens: row.cache_write_tokens || 0, - cost_usd: row.cost_usd || 0, - decodeMs, - requestMs, - finishReason: msg ? msg.finishReason : null, - status, - rate, - requestRate, - }); - } - return ledger; -} - -export function buildLedgerWithDb(db, rows, enrichment, catalog, store) { - return buildCallLedger(rows, enrichment, loadAssistantCallDetails(rows, store), catalog); -} - -// --- rate aggregation --------------------------------------------------------- -// -// The rate shown by MiniMax Code's own UI lives in the desktop bundle and is -// computed as tokensPerSecond = Σ outputTokens / Σ decodeDurationMs over a set of -// calls — i.e. decode-based (first token → stream end) and time-weighted, NOT the -// arithmetic mean of per-call rates. We reproduce exactly that so the board and -// the chat UI agree, and keep the whole-request rate as the reference column -// (their difference is time-to-first-token plus queueing). -// -// `decode > request` is a CONSISTENCY guard, not a truncation detector. -// decode = completed − firstToken and request = completed − requestStarted, so -// decode > request is exactly firstTokenTime < requestStartedAt: the first -// token "arrived" before the request was sent. That cannot happen inside one -// coherent call — the two stamps must come from different attempts. Measured -// on this machine it shows up only on finish_reason='toolUse', where the -// request timer gets re-stamped on the tool-call continuation: 6 of 2674 timed -// calls (0.22%), overshooting by 0.25–2.1s against 3.8–56s requests. Such a -// decode is longer than physically possible and would pad the aggregate's -// denominator, so it is skipped; the per-call value is still shown. -// -// NOTE this is NOT what catches the degenerate sub-second decode spans. Those -// run ~100ms against a multi-second request, so decode < request and they pass -// straight through — they inflate the rate instead, which is a separate known -// property of the runtime's timing (see README). - -export function collectDecodeRates(calls) { - const out = []; - for (const c of calls) { - if (typeof c.rate !== 'number') continue; - if (c.decodeMs != null && c.requestMs != null && c.decodeMs > c.requestMs) continue; - out.push(c.rate); - } - return out; -} - -function round2(v) { - return Math.round(v * 100) / 100; -} - -export function percentile(sorted, p) { - if (!sorted.length) return null; - const idx = Math.min(sorted.length - 1, Math.max(0, Math.round((sorted.length - 1) * p))); - return sorted[idx]; -} - -function describe(values) { - if (!values.length) return null; - const sorted = values.slice().sort((a, b) => a - b); - return { - mean: round2(sorted.reduce((s, v) => s + v, 0) / sorted.length), - p50: round2(percentile(sorted, 0.5)), - p90: round2(percentile(sorted, 0.9)), - max: round2(sorted[sorted.length - 1]), - n: sorted.length, - }; -} - -// MiniMax Code UI basis: Σ output tokens ÷ Σ decode duration. -function weightedRate(calls, msKey, rateKey) { - let tokens = 0; - let ms = 0; - for (const c of calls) { - if (typeof c[rateKey] !== 'number') continue; - if (msKey === 'decodeMs' && c.decodeMs != null && c.requestMs != null && c.decodeMs > c.requestMs) continue; - tokens += c.output_tokens || 0; - ms += c[msKey] || 0; - } - return ms > 0 ? round2(tokens / (ms / 1000)) : null; -} - -// The headline metric: identical to the desktop UI's tokens/s figure. -export function rateStats(calls) { - const d = describe(collectDecodeRates(calls)); - const weighted = weightedRate(calls, 'decodeMs', 'rate'); - return d ? { ...d, weighted } : null; -} - -// Whole-request reference rate (output ÷ request_duration_ms). -export function requestRateStats(calls) { - const values = []; - for (const c of calls) if (typeof c.requestRate === 'number') values.push(c.requestRate); - const d = describe(values); - const weighted = weightedRate(calls, 'requestMs', 'requestRate'); - return d ? { ...d, weighted } : null; -} - -export function meanCallRate(calls) { - return rateStats(calls)?.weighted ?? null; -} - -export function countRatedCalls(calls) { - let n = 0; - for (const c of calls) if (typeof c.rate === 'number') n += 1; - return n; -} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs deleted file mode 100644 index ac075c3d..00000000 --- a/plugins/hanewari/token-meter-board/miniapp/node/lib/db-child.mjs +++ /dev/null @@ -1,53 +0,0 @@ -// token-meter-board child-process fallback dispatcher. -// Spawned by server.mjs only when the Mini App runtime lacks node:sqlite: -// node db-child.mjs -// Prints exactly one JSON document on stdout; exits non-zero on failure. -import { resolveDataDir } from './common.mjs'; -import { buildTrendResult, resolveTrendWindow } from './trend.mjs'; -import { querySummary, querySessions, queryDaily, queryWindow, queryCalls, queryTurns } from './queries.mjs'; - -function run(mode, params) { - const dataDir = params?.dataDir || resolveDataDir(); - const now = Date.now(); - switch (mode) { - case 'trend': { - const { startMs, endMs } = resolveTrendWindow( - { startAt: params?.startAt, endAt: params?.endAt, days: params?.days }, - now, - ); - return buildTrendResult({ - dataDir, - startMs, - endMs, - bucket: params?.bucket, - fillEmpty: params?.fillEmpty, - now, - }); - } - case 'window': - return queryWindow({ ...params, dataDir }, now); - case 'summary': - return querySummary({ ...params, dataDir }, now); - case 'sessions': - return querySessions({ ...params, dataDir }, now); - case 'daily': - return queryDaily({ ...params, dataDir }, now); - case 'calls': - return queryCalls({ ...params, dataDir }, now); - case 'turns': - return queryTurns({ ...params, dataDir }, now); - default: - throw new Error(`unknown mode: ${mode}`); - } -} - -try { - const [, , mode, paramsJson] = process.argv; - const params = paramsJson ? JSON.parse(paramsJson) : {}; - const result = run(mode, params); - process.stdout.write(JSON.stringify(result)); - process.exit(0); -} catch (err) { - process.stdout.write(JSON.stringify({ error: String(err?.message || err), code: err?.code || null })); - process.exit(1); -} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs deleted file mode 100644 index 55f0fe20..00000000 --- a/plugins/hanewari/token-meter-board/miniapp/node/lib/facts.mjs +++ /dev/null @@ -1,210 +0,0 @@ -// token-meter message fact store. -// -// WHY THIS EXISTS -// The runtime database stores every message as a row in local_runtime_message_rows, -// and that table has NO index on turn_id — so any lookup by turn is a full table -// scan. The payloads are whole conversation turns (≈350 MB of JSON on a busy -// machine), while the board only needs four scalars per assistant message: -// decode duration, request duration, finish reason, plus the turn's user-message -// preview. -// -// Pulling data_json into JS and JSON.parse()-ing it measured ≈2.8 s per scan; -// extracting the same scalars inside SQLite measured ≈0.6 s. Doing that twice -// per endpoint (once for call timings, once for turn metadata) and again for -// every endpoint and every window is what made the board feel stuck when the -// query window changed. -// -// So the facts are extracted once, in rowid order, and kept in memory. Later -// scans only pick up the rows appended since the last one (`id > watermark`), -// which is what makes switching the query window instant. The rowid scan seeks -// the INTEGER PRIMARY KEY directly, so it costs nothing but the new rows. -// -// Rows are append-only in this runtime (the table holds immutable source rows -// and the state changes live in a separate diff journal), so a rowid-keyed -// cache cannot drift in practice. A full re-extract still runs periodically as -// a safety net in case a row is ever rewritten in place. - -import path from 'node:path'; - -// Re-extract everything this often, so a rewritten row can never be missed. -const REVERIFY_MS = 10 * 60 * 1000; - -// How much of the user's own message is kept for the conversation table. -// Applied inside SQLite with substr(), so the full text (up to ~52 k chars on -// this machine) is never carried into JS memory — only the first 200 -// characters are. -const USER_PREVIEW_CHARS = 200; - -// CASE (not AND) is deliberate: SQLite evaluates CASE lazily, so the inner -// json_type/json_extract calls only run on rows that are valid JSON. An -// expression like `json_valid(x) AND json_type(x, ...)` is not guaranteed to -// short-circuit and would raise "malformed JSON" on a bad row. -function jsonField(path, kind) { - return `CASE WHEN json_valid(data_json) THEN CASE WHEN json_type(data_json,'${path}') ${kind} THEN json_extract(data_json,'${path}') END END`; -} - -const FACT_SQL = ` - SELECT id, session_id, role, turn_id, created_at_ms, - ${jsonField('$.usage', "= 'object'")} AS has_usage, - ${jsonField('$.usage.decode_duration_ms', "IN ('integer','real')")} AS decode_ms, - ${jsonField('$.usage.request_duration_ms', "IN ('integer','real')")} AS request_ms, - ${jsonField('$.finish_reason', "= 'text'")} AS finish_reason, - substr(${jsonField('$.msg_content', "= 'text'")}, 1, ${USER_PREVIEW_CHARS}) AS msg_preview - FROM local_runtime_message_rows - WHERE id > ? - ORDER BY id`; - -// One store per runtime database file. -const stores = new Map(); - -function createStore() { - return { - byTurn: new Map(), // turn_id -> entry - watermark: 0, // highest rowid already extracted - extractedRows: 0, - lastSyncAt: 0, - lastVerifyAt: 0, - everScanned: false, - }; -} - - -export function getFactsStore(dataDir) { - const key = path.join(dataDir, 'v2', 'sqlite', 'runtime-state.sqlite'); - let store = stores.get(key); - if (!store) { - store = createStore(); - stores.set(key, store); - } - return store; -} - -function applyRow(store, row) { - const turnId = row.turn_id; - if (!turnId) return; - let entry = store.byTurn.get(turnId); - if (!entry) { - entry = { - sessionId: row.session_id, - maxTs: null, - calls: new Map(), // rowid -> call fact (assistant messages that carry a usage block) - assistantCount: 0, // every assistant row, including the ones that are not model calls - users: new Map(), // rowid -> user message fact - }; - store.byTurn.set(turnId, entry); - } - if (row.created_at_ms != null && (entry.maxTs == null || row.created_at_ms > entry.maxTs)) { - entry.maxTs = row.created_at_ms; - } - if (row.role === 'assistant') { - entry.assistantCount += 1; - // Only an assistant message that carries a usage block is a MODEL CALL. - // The runtime also writes assistant rows for non-call events — context - // compaction, for instance (490 of 17,214 such rows on this machine). - // Counting those as calls shifts every later pairing in the turn by one, - // which made a whole turn report the previous call's decode duration and - // rate. They are counted for "did the agent answer?" but never paired. - if (row.has_usage) { - entry.calls.set(row.id, { - ts: row.created_at_ms, - decodeMs: row.decode_ms, - requestMs: row.request_ms, - finishReason: row.finish_reason, - }); - } - } else if (row.role === 'user') { - entry.users.set(row.id, { ts: row.created_at_ms, preview: row.msg_preview }); - } -} - -// Pull in every row appended since the last extraction. A full re-extract -// happens on the first sync and then every REVERIFY_MS, so the store always -// converges on the current contents of the table. -export function syncFacts(store, db, options = {}) { - const now = options.now ?? Date.now(); - const full = !store.everScanned || now - store.lastVerifyAt >= REVERIFY_MS; - if (full) { - store.byTurn.clear(); - store.watermark = 0; - } - let rows = 0; - let maxId = store.watermark; - const stmt = db.prepare(FACT_SQL); - for (const row of stmt.iterate(store.watermark)) { - rows += 1; - if (row.id > maxId) maxId = row.id; - applyRow(store, row); - } - store.watermark = maxId; - store.extractedRows += rows; - store.lastSyncAt = now; - store.everScanned = true; - if (full) store.lastVerifyAt = now; - return { rows, full, watermark: store.watermark, turns: store.byTurn.size }; -} - -// Model calls of a turn, oldest first — the same order the original query -// produced (ORDER BY created_at_ms), with the rowid as a stable tie-breaker. -// Only messages that carry a usage block are returned: those are the calls -// the runtime recorded in local_runtime_token_usage, and they are what the -// per-call ledger pairs against. -export function assistantCallsForTurn(store, turnId) { - const entry = store.byTurn.get(turnId); - if (!entry || entry.calls.size === 0) return null; - const out = [...entry.calls.values()].sort((a, b) => (a.ts ?? 0) - (b.ts ?? 0)); - return out; -} - -// Per-turn message metadata for the conversation table. -// -// A turn is exactly one user message followed by however many model calls the -// agent needed before answering, so it is the natural unit for "one thing the -// user asked" — and it is readable from the database the instant the first -// usage row of that turn lands, with no hook and no waiting for the session -// to close. Verified on this machine: 26 turns today, 24 carrying exactly one -// user message, 0 carrying more than one, and all 26 ending on an assistant -// message. -export function turnMetaForTurn(store, turnId) { - const entry = store.byTurn.get(turnId); - if (!entry) return null; - let userTs = null; - let userPreview = null; - for (const u of entry.users.values()) { - if (u.ts == null) continue; - if (userTs == null || u.ts < userTs || (u.ts === userTs && u.preview != null && userPreview == null)) { - userTs = u.ts; - userPreview = u.preview != null ? u.preview : userPreview; - } - } - // The finish reason of the last MODEL CALL that carries one. Non-call - // assistant rows (compaction) are deliberately excluded: they carry a - // finish_reason of their own, and reading it would report a still-running - // turn as "completed". - const calls = assistantCallsForTurn(store, turnId); - let finishReason = null; - if (calls) { - for (let i = calls.length - 1; i >= 0; i -= 1) { - if (calls[i].finishReason != null) { - finishReason = calls[i].finishReason; - break; - } - } - } - return { - userTs, - userPreview, - lastTs: entry.maxTs, - finishReason, - assistantCount: entry.assistantCount, - }; -} - -export function factsStats(store) { - return { - turns: store.byTurn.size, - extractedRows: store.extractedRows, - watermark: store.watermark, - lastSyncAt: store.lastSyncAt, - lastVerifyAt: store.lastVerifyAt, - }; -} diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs index 6cb9a387..8cd6c5a6 100644 --- a/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/queries.mjs @@ -1,454 +1,494 @@ -// token-meter-board query layer: windowed usage aggregations shared by the HTTP -// routes (in-process) and the child-process fallback (db-child.mjs). All reads -// are read-only against the MiniMax Code runtime state. +// @ts-check +// token-meter-board queries. // -// Rate methodology (v1.5): token 输出速率 与 MiniMax Code 界面同口径 —— -// 单次成功调用为 输出 tokens ÷ decode 时长(首 token 到流结束,取自 assistant -// 消息的 usage.decode_duration_ms);跨调用的聚合一律为 Σ输出 ÷ Σdecode 耗时 -//(时间加权),不使用逐次算术平均。没有 decode 记录的老数据不参与,避免被口径 -// 外的数值稀释。decode > request 的调用不计入聚合:它等价于首 token 早于请求发起, -// 说明两个时间戳来自不同尝试(实测仅出现在 finish=toolUse,2674 次里 6 次), -// 其 decode 物理上不可能更长,会灌大分母。逐次值仍照常展示。 -import fs from 'node:fs'; -import { - openDb, - queryUsageRows, - loadCatalog, - loadTurnEnrichment, - buildLedgerWithDb, - loadTurnMessageMeta, - syncMessageFacts, - meanCallRate, - rateStats, - requestRateStats, - countRatedCalls, - emptyMetrics, - addRow, - finalize, - sortGroups, - dayKey, - clampInt, -} from './common.mjs'; -import { resolveTrendWindow, buildTrendFromContext } from './trend.mjs'; +// Every number comes from the session records read by lib/sessions.mjs. There +// is no runtime database, no observability log and no Host configuration in +// this file, and therefore no token rate and no workspace path: the session +// records do not carry durations or paths. +// +// A call is identified by its message id and de-duplicated globally, because a +// rebuilt session copies its earlier messages into the new session file. -export const NOTES = [ - 'cacheHitRate = cacheReadTokens / (cacheReadTokens + inputTokens),表示提示词中命中缓存的比例;cacheWriteTokens 不计入分母。', - 'totalTokens = input + output + reasoning + cacheRead + cacheWrite。', - 'token 输出速率(token/s)与 MiniMax Code 界面显示的口径完全一致:单次调用的 输出 tokens ÷ decode 时长(首 token 到流结束),窗口值为 Σ输出 ÷ Σdecode 耗时(按耗时加权),并附 P50/P90 供分布参考。', - 'costUsd 为 runtime 记录值;自定义套餐/订阅类提供商通常为 0,不代表实际账单。', - '请求全程速率(对照列)= 输出 tokens ÷ request_duration_ms(发起请求到流结束),与输出速率的差值即首字等待与排队;decode > request 的调用(首 token 早于请求发起、时间戳来自不同尝试)不计入输出速率聚合,逐次值仍展示。', - 'model 字段由 runtime 日志 llm_response_identifiers 按 turn 补全(按小时文件名覆盖整个窗口);仍为 unknown 的记录早于日志保留期。', - '对话明细:每行是一次完整对话,即用户发送一条消息后,模型经过若干次调用直至给出最终回答(turn_id 即该单位);实时读取,无需等待会话结束。状态分为已完成(末条 finish_reason=stop)、未收尾(末条仍为 toolUse 等)与进行中(尚无 assistant 消息)。', - '对话明细会显示该轮用户消息原文的前 200 字,仅在本机页面内展示,不出网、不落盘。', - '统计范围限于本机 runtime 数据库当前保留的数据;早于该保留期的历史不会出现在本表中。', -]; +import { SessionStore, dayKey } from './sessions.mjs'; -// Open the DB and load the window rows plus the per-call ledger (identity, -// decode timing, response status). -// -// The derived context is cached for a few seconds, so the endpoints that -// describe the same window — trend, call log and conversation list — share one -// scan instead of each repeating it. That is what keeps a window switch from -// queueing three expensive passes behind each other. -// -// The cache key includes the data directory: the same time window against two -// different runtime databases is two different contexts, and keying on the -// window alone would let one answer the other. -const CONTEXT_TTL_MS = 3000; -const contextCache = new Map(); +/** @typedef {import('./miniapp-api.js').MiniAppContext} MiniAppContext */ + +/** How long an aggregate stays valid before it is rebuilt. */ +const AGGREGATE_TTL_MS = 3000; +/** How often the transcript files are re-read. */ +const SCAN_TTL_MS = 3000; + +/** @type {SessionStore | null} */ +let store = null; -function contextKey(dataDir, startMs, endMs) { - return `${dataDir}|${startMs}|${endMs}`; +/** + * @param {MiniAppContext} context + * @returns {SessionStore} + */ +export function getStore(context) { + if (!store) store = new SessionStore(context); + return store; } -function loadSessionTitles(db) { - const titles = new Map(); - try { - for (const r of db.prepare('SELECT session_id, title, agent_name, workspace_dir FROM local_runtime_sessions').all()) { - titles.set(r.session_id, r); - } - } catch { - // titles optional - } - return titles; +/** Reset the module-level store (used by tests and on dispose). */ +export function resetStore() { + store = null; } -export function openContext(dataDir, startMs, endMs, now = Date.now()) { - const key = contextKey(dataDir, startMs, endMs); - const hit = contextCache.get(key); - if (hit && now - hit.at < CONTEXT_TTL_MS) return hit.ctx; +/** + * Persist the scan cursor so the next start resumes instead of re-reading + * every transcript. + * @param {boolean} force + */ +export async function saveStore(force = true) { + if (store) await store.save(force); +} - const { db, error } = openDb(dataDir); - if (!db) { - const err = new Error(error || `runtime state database unavailable under ${dataDir}`); - err.code = 'NO_DB'; - throw err; - } - try { - const rows = queryUsageRows(db, startMs, endMs); - const catalog = loadCatalog(dataDir); - const { map: enrichment, filesScanned } = loadTurnEnrichment(dataDir, startMs, { now }); - // Message facts are extracted once per process and reused; this only picks - // up rows appended since the last query. - const store = syncMessageFacts(db, dataDir, { now }); - const ledger = buildLedgerWithDb(db, rows, enrichment, catalog, store); - const turnMeta = loadTurnMessageMeta(rows, store); - const titles = loadSessionTitles(db); - const meta = { - dataDir, - window: { - label: `${dayKey(startMs)}..${dayKey(endMs)}`, - start: new Date(startMs).toISOString(), - end: new Date(endMs).toISOString(), - }, - rows: rows.length, - rateMeasured: countRatedCalls(ledger), - rate: rateStats(ledger), - requestRate: requestRateStats(ledger), - logFilesScanned: filesScanned, - turnsEnriched: enrichment.size, - generatedAt: new Date(now).toISOString(), - }; - const ctx = { rows, catalog, enrichment, ledger, turnMeta, titles, filesScanned, dataDir, meta }; - contextCache.set(key, { at: now, ctx }); - if (contextCache.size > 32) { - const oldest = contextCache.keys().next().value; - if (oldest !== key) contextCache.delete(oldest); - } - return ctx; - } finally { - db.close(); - } +/** + * Make sure the transcripts are read up to date. + * @param {MiniAppContext} context + * @param {number} now + */ +export async function ensureScanned(context, now = Date.now()) { + const current = getStore(context); + if (!current.ready) await current.init(); + if (now - current.scannedAt > SCAN_TTL_MS) await current.scan(); + return current; } -export function groupByModel(ctx) { - const groups = new Map(); - const total = emptyMetrics(); - let unknownRows = 0; - for (const call of ctx.ledger) { - if (call.model === '(unknown)') unknownRows += 1; - const key = `${call.provider}|${call.model}`; - if (!groups.has(key)) { - groups.set(key, { - provider: call.provider, - providerName: call.providerName, - model: call.model, - modelName: call.modelName, - custom: call.custom, - metrics: emptyMetrics(), - callList: [], - }); - } - const g = groups.get(key); - addRow(g.metrics, call); - g.callList.push(call); - addRow(total, call); +/** @param {unknown} value */ +export function clampInt(value, min, max, fallback) { + const n = Number.parseInt(String(value ?? ''), 10); + if (Number.isNaN(n)) return fallback; + return Math.min(max, Math.max(min, n)); +} + +/** + * Parse a local "YYYY-MM-DDTHH:MM" stamp. + * @param {unknown} value + */ +export function parseLocalDateTime(value) { + const m = String(value ?? '') + .trim() + .match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?/); + if (!m) return null; + const d = new Date(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +(m[6] || 0), 0); + return Number.isNaN(d.getTime()) ? null : d.getTime(); +} + +/** + * Resolve a query window: an explicit local start/end pair, or a trailing + * number of days that includes today. + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown}} args + * @param {number} now + */ +export function resolveWindow(args = {}, now = Date.now()) { + const startMs = parseLocalDateTime(args.startAt); + if (startMs != null) { + const endRaw = args.endAt != null ? parseLocalDateTime(args.endAt) : now; + if (endRaw == null) throw new Error('invalid endAt; expect local "YYYY-MM-DDTHH:MM"'); + const endMs = Math.min(endRaw, now); + if (endMs <= startMs) throw new Error('endAt must be after startAt'); + return { startMs, endMs, label: `${dayKey(startMs)}..${dayKey(endMs)}` }; } - const byModel = sortGroups( - [...groups.values()].map((g) => ({ - ...g, - ...finalize(g.metrics), - outputRate: meanCallRate(g.callList), - metrics: undefined, - callList: undefined, - })), - ); - return { byModel, total: finalize(total), unknownRows }; + const days = clampInt(args.days ?? 7, 1, 400, 7); + const todayStart = new Date(now); + todayStart.setHours(0, 0, 0, 0); + const start = todayStart.getTime() - (days - 1) * 86400000; + return { startMs: start, endMs: now, label: days === 1 ? dayKey(start) : `${dayKey(start)}..${dayKey(now)}` }; } -function summaryFromContext(ctx) { - const { byModel, total, unknownRows } = groupByModel(ctx); - return { - window: ctx.meta.window, - total: { ...total, outputRate: meanCallRate(ctx.ledger), rate: rateStats(ctx.ledger), rateMeasured: ctx.meta.rateMeasured }, - byModel, - unknownRows, - notes: NOTES, - meta: ctx.meta, - }; +/** + * @param {number} startMs + * @param {number} endMs + * @param {unknown} requested + */ +export function pickBucket(startMs, endMs, requested) { + const spanMin = (endMs - startMs) / 60000; + let bucket = requested && requested !== 'auto' ? String(requested) : spanMin <= 360 ? 'minute' : spanMin <= 7 * 24 * 60 ? 'hour' : 'day'; + const spanMs = Math.max(endMs - startMs, 1); + const approx = (b) => Math.ceil(spanMs / (b === 'minute' ? 60000 : b === 'hour' ? 3600000 : 86400000)); + if (approx(bucket) > 600) bucket = bucket === 'minute' ? 'hour' : 'day'; + return bucket; } -// summary: window (startAt/endAt minute precision, or days) grouped by provider/model. -export function querySummary({ dataDir, startAt, endAt, days }, now = Date.now()) { - const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - return summaryFromContext(ctx); +/** + * @param {number} ts + * @param {string} bucket + */ +export function bucketFloor(ts, bucket) { + const d = new Date(ts); + if (bucket === 'minute') d.setSeconds(0, 0); + else if (bucket === 'hour') d.setMinutes(0, 0, 0); + else d.setHours(0, 0, 0, 0); + return d.getTime(); } -// window: trend + summary over a single DB/log scan (one enrichment pass). -export function queryWindow({ dataDir, startAt, endAt, days, bucket, fillEmpty }, now = Date.now()) { - const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - const trend = buildTrendFromContext(ctx, { startMs, endMs, bucket, fillEmpty, now }); - const summary = summaryFromContext(ctx); - return { trend, summary }; +/** + * @param {number} ms + * @param {string} bucket + * @param {boolean} multiDay + */ +export function bucketLabel(ms, bucket, multiDay) { + const d = new Date(ms); + const p = (n) => String(n).padStart(2, '0'); + if (bucket === 'day') return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`; + if (multiDay) return `${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`; + return `${p(d.getHours())}:${p(d.getMinutes())}`; } -// calls: the per-call ledger for the window, newest first (调用日志). -export function queryCalls({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { - const lim = clampInt(limit, 1, 1000, 200); - const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 1 }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - const calls = ctx.ledger - .slice() - .sort((a, b) => b.ts - a.ts) - .slice(0, lim) - .map((c) => ({ - ts: c.ts, - time: new Date(c.ts).toISOString(), - sessionId: c.sessionId, - agentName: c.agentName, - turnId: c.turnId, - provider: c.provider, - providerName: c.providerName, - model: c.model, - modelName: c.modelName, - custom: c.custom, - inputTokens: c.input_tokens, - outputTokens: c.output_tokens, - reasoningTokens: c.reasoning_tokens, - cacheReadTokens: c.cache_read_tokens, - cacheWriteTokens: c.cache_write_tokens, - totalTokens: - c.input_tokens + c.output_tokens + c.reasoning_tokens + c.cache_read_tokens + c.cache_write_tokens, - decodeMs: c.decodeMs, - requestMs: c.requestMs, - status: c.status, - finishReason: c.finishReason, - outputRate: c.rate, - requestRate: c.requestRate, - })); - return { - window: ctx.meta.window, - calls, - totalCalls: ctx.ledger.length, - rateMeasured: ctx.meta.rateMeasured, - rate: ctx.meta.rate, - requestRate: ctx.meta.requestRate, - notes: NOTES, - meta: ctx.meta, - }; +/** Cache the aggregate for the current window. */ +/** @type {{key: string, at: number, agg: any}} */ +let aggregateCache = { key: '', at: 0, agg: null }; + +/** + * @param {SessionStore} current + * @param {number} startMs + * @param {number} endMs + * @param {number} now + */ +function aggregateCached(current, startMs, endMs, now) { + const key = `${startMs}|${endMs}|${current.scannedAt}`; + if (aggregateCache.key === key && now - aggregateCache.at < AGGREGATE_TTL_MS) return aggregateCache.agg; + const agg = current.aggregate(startMs, endMs); + aggregateCache = { key, at: now, agg }; + return agg; } -// turns: one row per conversation — a single user message plus however many -// model calls the agent needed before answering. Read live from the database, so -// it works while the conversation is still running and never waits for SessionEnd. -// -// Rate uses the same basis as the KPI (Σoutput ÷ Σdecode); wall-clock span is -// reported separately as 时长 and is deliberately NOT used as the denominator, -// otherwise a long conversation with a slow tail would read as a slow model. -export function queryTurns({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { - const lim = clampInt(limit, 1, 500, 120); - const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 1 }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - const byTurn = new Map(); - for (const call of ctx.ledger) { - if (!call.turnId) continue; - if (!byTurn.has(call.turnId)) { - byTurn.set(call.turnId, { - total: emptyMetrics(), - calls: [], - firstTs: call.ts, - lastCallTs: call.ts, - groups: new Map(), - sessionId: call.sessionId, - agentName: call.agentName || null, - }); - } - const t = byTurn.get(call.turnId); - t.firstTs = Math.min(t.firstTs, call.ts); - t.lastCallTs = Math.max(t.lastCallTs, call.ts); - addRow(t.total, call); - t.calls.push(call); - const gk = `${call.provider}|${call.model}`; - if (!t.groups.has(gk)) { - t.groups.set(gk, { - provider: call.provider, - providerName: call.providerName, - model: call.model, - modelName: call.modelName, - custom: call.custom, - metrics: emptyMetrics(), - callList: [], - }); +/** @param {any} bucket */ +function hitRate(bucket) { + const denom = (bucket.cacheRead || 0) + (bucket.input || 0); + if (!denom) return null; + return (bucket.cacheRead || 0) / denom; +} + +/** @param {number} ms */ +function isoLocal(ms) { + if (!ms) return ''; + const d = new Date(ms); + const p = (n) => String(n).padStart(2, '0'); + return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`; +} + +/** + * A turn's status, derived from the stop reason of its last assistant call. + * @param {any} turn + */ +function turnStatus(turn) { + if (turn.calls === 0) return 'pending'; + if (turn.lastStop === 3) return 'aborted'; + if (turn.lastStop === 2) return 'unfinished'; + if (turn.lastStop === 1) return 'completed'; + return 'unfinished'; +} + +/** + * The window view: KPIs, a per-model share and a bucketed trend. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown, bucket?: unknown, fillEmpty?: unknown}} args + * @param {number} now + */ +export async function queryWindow(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); + const bucket = pickBucket(startMs, endMs, args.bucket); + const multiDay = dayKey(startMs) !== dayKey(endMs); + + /** @type {Map} */ + const buckets = new Map(); + const ensureBucket = (ts) => { + const key = String(bucketFloor(ts, bucket)); + let entry = buckets.get(key); + if (!entry) { + entry = { + key, + label: bucketLabel(bucketFloor(ts, bucket), bucket, multiDay), + calls: 0, + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + total: 0, + cost: 0, + models: new Map(), + }; + buckets.set(key, entry); } - const g = t.groups.get(gk); - addRow(g.metrics, call); - g.callList.push(call); + return entry; + }; + for (const call of agg.calls) { + const entry = ensureBucket(call.ts); + entry.calls += 1; + entry.input += call.input; + entry.output += call.output; + entry.cacheRead += call.cacheRead; + entry.cacheWrite += call.cacheWrite; + entry.total += call.total; + entry.cost += call.cost; + entry.models.set(call.model, (entry.models.get(call.model) ?? 0) + call.total); } - const allTurns = [...byTurn.entries()] - .map(([turnId, t]) => { - const meta = ctx.turnMeta.get(turnId) || null; - const startedMs = meta?.userTs != null ? Math.min(meta.userTs, t.firstTs) : t.firstTs; - const endedMs = meta?.lastTs != null ? meta.lastTs : null; - const finished = endedMs != null && (meta?.assistantCount || 0) > 0; - let status = 'pending'; - if (finished) status = meta.finishReason === 'stop' ? 'completed' : 'unfinished'; - const models = sortGroups( - [...t.groups.values()].map((g) => ({ - ...g, - ...finalize(g.metrics), - outputRate: meanCallRate(g.callList), - metrics: undefined, - callList: undefined, - })), - ); - const metrics = finalize(t.total); - return { - turnId, - sessionId: t.sessionId, - sessionTitle: ctx.titles.get(t.sessionId)?.title || null, - agentName: t.agentName, - startedAt: new Date(startedMs).toISOString(), - endedAt: endedMs != null ? new Date(endedMs).toISOString() : null, - durationMs: endedMs != null ? endedMs - startedMs : null, - status, - finishReason: meta?.finishReason || null, - userPreview: meta?.userPreview || null, - ...metrics, - outputRate: meanCallRate(t.calls), - rate: rateStats(t.calls), - byModel: models, - }; - }) - .sort((a, b) => (a.startedAt < b.startedAt ? 1 : -1)); + const ordered = [...buckets.values()].sort((a, b) => Number(a.key) - Number(b.key)); + const models = [...agg.byModel.entries()] + .map(([model, bucketValue]) => ({ + key: model, + model, + modelName: model, + providerName: '', + custom: false, + totalTokens: bucketValue.total, + })) + .sort((a, b) => b.totalTokens - a.totalTokens); + const topModels = models.slice(0, 6); - // The status breakdown covers EVERY turn in the window, not only the rows - // that survive the `limit` slice. Counting the slice instead made the - // headline ("本次窗口共 N 次对话(已完成 X · 未收尾 Y · 进行中 Z)") add up - // to less than N as soon as the window held more turns than the limit. - const counts = { completed: 0, unfinished: 0, pending: 0 }; - for (const t of allTurns) counts[t.status] = (counts[t.status] || 0) + 1; + const labels = ordered.map((b) => b.label); + const tokensByModel = {}; + for (const model of topModels) { + tokensByModel[model.key] = ordered.map((b) => b.models.get(model.key) ?? 0); + } + const cacheHitRate = ordered.map((b) => { + const denom = b.cacheRead + b.input; + return denom ? b.cacheRead / denom : null; + }); - const turns = allTurns.slice(0, lim); + const totals = agg.totals; + return { + trend: { + window: { start: new Date(startMs).toISOString(), end: new Date(endMs).toISOString(), bucket }, + meta: { rows: totals.calls, generatedAt: now }, + kpis: { + totalTokens: totals.total, + calls: totals.calls, + cacheHitRate: hitRate(totals), + activeModels: agg.byModel.size, + inputTokens: totals.input, + outputTokens: totals.output, + cacheReadTokens: totals.cacheRead, + cacheWriteTokens: totals.cacheWrite, + turns: agg.byTurn.size, + sessions: agg.bySession.size, + cost: totals.cost, + }, + models: topModels, + series: { + labels, + tokensByModel, + cacheHitRate, + calls: ordered.map((b) => b.calls), + totalTokens: ordered.map((b) => b.total), + }, + unknownRows: 0, + }, + summary: { + byModel: [...agg.byModel.entries()] + .map(([model, bucketValue]) => ({ + model, + modelName: model, + provider: '', + providerName: '', + custom: false, + calls: bucketValue.calls, + inputTokens: bucketValue.input, + outputTokens: bucketValue.output, + cacheReadTokens: bucketValue.cacheRead, + cacheWriteTokens: bucketValue.cacheWrite, + totalTokens: bucketValue.total, + cacheHitRate: hitRate(bucketValue), + })) + .sort((a, b) => b.totalTokens - a.totalTokens), + }, + }; +} +/** + * Per-model breakdown for the window. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown}} args + * @param {number} now + */ +export async function queryModels(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); return { - window: ctx.meta.window, - turns, - totalTurns: byTurn.size, - counts, - notes: NOTES, - meta: ctx.meta, + byModel: [...agg.byModel.entries()] + .map(([model, bucketValue]) => ({ + model, + modelName: model, + provider: '', + providerName: '', + custom: false, + calls: bucketValue.calls, + inputTokens: bucketValue.input, + outputTokens: bucketValue.output, + cacheReadTokens: bucketValue.cacheRead, + cacheWriteTokens: bucketValue.cacheWrite, + totalTokens: bucketValue.total, + cacheHitRate: hitRate(bucketValue), + })) + .sort((a, b) => b.totalTokens - a.totalTokens), }; } -// sessions: per-session aggregation over the window, newest activity first. -// outputRate = the session's weighted decode rate (Σ output ÷ Σ decode). -export function querySessions({ dataDir, startAt, endAt, days, limit }, now = Date.now()) { - const lim = clampInt(limit, 1, 50, 10); - const { startMs, endMs } = resolveTrendWindow({ startAt, endAt, days: days ?? 30 }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - const bySession = new Map(); - for (const call of ctx.ledger) { - if (!bySession.has(call.sessionId)) { - bySession.set(call.sessionId, { - total: emptyMetrics(), - firstTs: call.ts, - lastTs: call.ts, - groups: new Map(), - calls: [], - agentName: call.agentName || null, - }); - } - const s = bySession.get(call.sessionId); - s.firstTs = Math.min(s.firstTs, call.ts); - s.lastTs = Math.max(s.lastTs, call.ts); - addRow(s.total, call); - s.calls.push(call); - const gk = `${call.provider}|${call.model}`; - if (!s.groups.has(gk)) { - s.groups.set(gk, { - provider: call.provider, - providerName: call.providerName, - model: call.model, - modelName: call.modelName, - custom: call.custom, - metrics: emptyMetrics(), - callList: [], - }); - } - const g = s.groups.get(gk); - addRow(g.metrics, call); - g.callList.push(call); - } - const sessions = [...bySession.entries()] - .map(([sessionId, s]) => { - const info = ctx.titles.get(sessionId); - const models = sortGroups( - [...s.groups.values()].map((g) => ({ - ...g, - ...finalize(g.metrics), - outputRate: meanCallRate(g.callList), - metrics: undefined, - callList: undefined, - })), - ); - const metrics = finalize(s.total); - return { - sessionId, - title: info?.title || null, - agentName: s.agentName || info?.agent_name || null, - workspaceDir: info?.workspace_dir || null, - firstActivity: new Date(s.firstTs).toISOString(), - lastActivity: new Date(s.lastTs).toISOString(), - ...metrics, - outputRate: meanCallRate(s.calls), - rate: rateStats(s.calls), - byModel: models, - }; - }) - .sort((a, b) => (a.lastActivity < b.lastActivity ? 1 : -1)) - .slice(0, lim); - return { window: ctx.meta.window, sessions, notes: NOTES, meta: ctx.meta }; +/** + * Sessions ranked by usage. Only the session id and its own title are shown: + * no workspace path is ever read, so none can be shown. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown, limit?: unknown}} args + * @param {number} now + */ +export async function querySessions(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); + const limit = clampInt(args.limit ?? 50, 1, 500, 50); + const rows = [...agg.bySession.values()] + .map((session) => ({ + sessionId: session.sessionId, + title: session.title || session.sessionId, + calls: session.calls, + inputTokens: session.input, + outputTokens: session.output, + cacheReadTokens: session.cacheRead, + cacheWriteTokens: session.cacheWrite, + totalTokens: session.total, + cacheHitRate: hitRate(session), + turns: session.turns.size, + firstActivity: new Date(session.firstTs).toISOString(), + lastActivity: new Date(session.lastTs).toISOString(), + byModel: [...session.models.entries()] + .sort((a, b) => b[1] - a[1]) + .map(([model, tokens]) => ({ model, modelName: model, totalTokens: tokens })), + })) + .sort((a, b) => b.totalTokens - a.totalTokens) + .slice(0, limit); + return { sessions: rows }; } -// daily: day x model aggregation over the trailing N days. -// outputRate = the day's weighted decode rate (Σ output ÷ Σ decode). -export function queryDaily({ dataDir, days }, now = Date.now()) { - const n = clampInt(days, 1, 90, 7); - const { startMs, endMs } = resolveTrendWindow({ days: n }, now); - const ctx = openContext(dataDir, startMs, endMs, now); - const byDay = new Map(); - for (const call of ctx.ledger) { - const key = dayKey(call.ts); - if (!byDay.has(key)) byDay.set(key, { total: emptyMetrics(), groups: new Map(), calls: [] }); - const day = byDay.get(key); - addRow(day.total, call); - day.calls.push(call); - const gk = `${call.provider}|${call.model}`; - if (!day.groups.has(gk)) { - day.groups.set(gk, { - provider: call.provider, - providerName: call.providerName, - model: call.model, - modelName: call.modelName, - custom: call.custom, - metrics: emptyMetrics(), - callList: [], - }); - } - const g = day.groups.get(gk); - addRow(g.metrics, call); - g.callList.push(call); +/** + * One row per local day. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown}} args + * @param {number} now + */ +export async function queryDaily(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); + const rows = [...agg.byDay.entries()] + .sort((a, b) => (a[0] < b[0] ? -1 : 1)) + .map(([day, bucketValue]) => ({ + day, + total: { + calls: bucketValue.calls, + inputTokens: bucketValue.input, + outputTokens: bucketValue.output, + cacheReadTokens: bucketValue.cacheRead, + cacheWriteTokens: bucketValue.cacheWrite, + totalTokens: bucketValue.total, + cacheHitRate: hitRate(bucketValue), + }, + byModel: [...bucketValue.models.entries()] + .sort((a, b) => b[1] - a[1]) + .map(([model, tokens]) => ({ model, modelName: model, totalTokens: tokens })), + })); + return { days: rows }; +} + +/** + * One row per conversation turn. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown, limit?: unknown}} args + * @param {number} now + */ +export async function queryTurns(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); + const limit = clampInt(args.limit ?? 100, 1, 1000, 100); + const rows = [...agg.byTurn.values()] + .sort((a, b) => b.lastTs - a.lastTs) + .slice(0, limit); + const counts = { completed: 0, unfinished: 0, pending: 0, aborted: 0 }; + for (const turn of agg.byTurn.values()) { + const status = turnStatus(turn); + if (counts[status] != null) counts[status] += 1; } - const daysOut = [...byDay.entries()] - .sort(([a], [b]) => (a < b ? -1 : 1)) - .map(([day, v]) => { - const total = finalize(v.total); - return { - day, - total: { ...total, outputRate: meanCallRate(v.calls), rate: rateStats(v.calls) }, - byModel: sortGroups( - [...v.groups.values()].map((g) => ({ - ...g, - ...finalize(g.metrics), - outputRate: meanCallRate(g.callList), - metrics: undefined, - callList: undefined, - })), - ), - }; - }); - return { window: ctx.meta.window, days: daysOut, notes: NOTES, meta: ctx.meta }; + return { + turns: rows.map((turn) => ({ + turnId: turn.turnId, + sessionId: turn.sessionId, + sessionTitle: turn.title || turn.sessionId, + status: turnStatus(turn), + startedAt: new Date(turn.firstTs).toISOString(), + finishedAt: new Date(turn.lastTs).toISOString(), + calls: turn.calls, + inputTokens: turn.input, + outputTokens: turn.output, + cacheReadTokens: turn.cacheRead, + cacheWriteTokens: turn.cacheWrite, + totalTokens: turn.total, + cacheHitRate: hitRate(turn), + byModel: [...turn.models].map((model) => ({ model, modelName: model })), + })), + counts, + totalTurns: agg.byTurn.size, + }; +} + +/** + * One row per call, newest first. + * @param {MiniAppContext} context + * @param {{startAt?: unknown, endAt?: unknown, days?: unknown, limit?: unknown}} args + * @param {number} now + */ +export async function queryCalls(context, args, now = Date.now()) { + const current = await ensureScanned(context, now); + const { startMs, endMs } = resolveWindow(args, now); + const agg = aggregateCached(current, startMs, endMs, now); + const limit = clampInt(args.limit ?? 200, 1, 2000, 200); + const rows = [...agg.calls] + .sort((a, b) => b.ts - a.ts) + .slice(0, limit); + return { + calls: rows.map((call) => ({ + ts: call.ts, + time: isoLocal(call.ts), + turnId: call.turn, + sessionId: '', + model: call.model, + modelName: call.model, + provider: '', + custom: false, + inputTokens: call.input, + outputTokens: call.output, + cacheReadTokens: call.cacheRead, + cacheWriteTokens: call.cacheWrite, + totalTokens: call.total, + stopReason: call.stop, + })), + }; +} + +/** + * A short description of the scan. No absolute path is returned. + * @param {MiniAppContext} context + * @param {number} now + */ +export async function queryHealth(context, now = Date.now()) { + const current = await ensureScanned(context, now); + const info = current.describe(); + return { + ok: true, + now, + source: 'session-records', + sessionsDir: current.root ? current.root.split(/[\\/]/).pop() : '', + files: info.files, + calls: info.calls, + turns: info.turns, + scannedAt: info.scannedAt, + scanMs: info.scanMs, + runtime: { node: process.version }, + }; } diff --git a/plugins/hanewari/token-meter-board/miniapp/node/lib/sessions.mjs b/plugins/hanewari/token-meter-board/miniapp/node/lib/sessions.mjs new file mode 100644 index 00000000..13a39cf3 --- /dev/null +++ b/plugins/hanewari/token-meter-board/miniapp/node/lib/sessions.mjs @@ -0,0 +1,771 @@ +// @ts-check +// token-meter-board session-record reader. +// +// DATA SOURCE — and the only one: +// +// /v2/sessions///