Repository navigation
feat: reference pricing, peak billing, fold cache, native typert channel and dashboard (0.5.0) - #5
Merged
Merged
Conversation
…dashboard Adds the reference price table (generated from opencode Zen + DeepSeek by scripts/gen-prices.mjs) and one resolution ladder in resolvePrice: user custom price, confirmed match, literal id, variant, fuzzy. Peak/off-peak billing follows the official DeepSeek rule (Beijing 09-12 and 14-18, Mon-Fri, excluding Chinese public holidays) against a generated holiday table. Persists the per-session fold result so a restart hydrates instead of re-reading the whole history: 0.08 s warm, against 12.5 s of pure inflate for 404 MB. It never prunes, because a partial listing once deleted 257 of 258 valid entries. Replaces the dynamic-plugin source endpoint with a native typert Remote face and keeps connection.fetch as the always-on fallback. Backfill starts on the first query rather than at activation. The cache-loading window is the only moment a loading state can be seen, and starting it from apply put that window before anyone opens the panel; the read-triggers-write trade-off is documented in docs/native-transport.md. The dashboard shows reference cost wherever a period is summarised, including the hover cards of the trend chart (bar and line) and the yearly heatmap: one TipRows serves all three, and only the rows that exist in the legend carry a colour swatch — 参考成本 and 调用次数 keep a colourless spacer so the labels still line up.
219 tests plus a 75-check build-artifact gate. Several pin the connections a refactor can quietly break, because that failure mode leaves both halves green on their own: - the model table renders the host's `unpriced` verdict instead of re-deriving it from `tokens > 0 && cost == 0` (how a model the user priced at 0 read 未定价); - the loading skeleton takes its card count from the same slot table as the dashboard (it was hard-coded to five while the row had six); - the on-demand scan stays wired to the query handler, and activation must not call runBackfill again; - the three chart hover cards share one TipRows whose cost comes from the host bucket, and only legend-backed rows carry a colour swatch. fold-parity compares our event fold against a recording of the official tokenUsage projection taken from the shipped asar. Each gate was mutation-checked: breaking the thing it guards turns it red.
docs/native-transport.md records the two L2 gaps with their counter-proofs (the settings nav icon and the fetch fallback), the fold-cache bypass with the three facts that justify keeping it, and the read-triggers-write trade-off the on-demand scan introduced. CHANGELOG carries one 0.5.0 entry. The local 0.4.1-0.4.8 iterations and the 0.5.1/0.5.2 bumps are folded into it: they were never releases, only local iterations and a workaround for replacing a same-version file: dependency. README's module map lists the modules that exist, and its install section records what was measured: a same-version file: dependency cannot be replaced in this profile (pnpm resolves from the store by the lockfile integrity), and replacing files under a running host is not an option — at 02:00 on 2026-10-31 a hand copy into node_modules was followed 0.8 s later by a host exit with 0xC0000005.
The holiday generator recorded the directory it derived the year span from (`session store (C:\Users\...\sessions)`) into `coverage.basis`. That string ships inside the package, so it leaked the maintainer's home directory — and the weekly CI run, which has no session store, would rewrite it to `calendar default` and back on every regeneration. The span still comes from the session store; only the recorded label is now environment-neutral (`session store` / `calendar default`). A gate in tests/holiday-years.test.js rejects an absolute path in the generated file.
- Replace image.png / image-1.png with the 0.5.0 dashboard (overview, then the tooltip / heatmap / model table). - Add screenshots.json so the plugin market reads these two images straight from this repository instead of extracting them from the README. - README: state the verified engines range (>=0.2.1-rc.3, verified on rc.4) and the composer-dock requirement; CHANGELOG: fold in the 0.4.0 merge (dock pill kept), the current test count (224) and the generated-path fix.
The `lib/` build-output rule matches every directory named lib, so scripts/lib/holiday-years.mjs was silently ignored and never committed. Local runs passed because the file sits on disk; on a clean CI checkout tests/holiday-years.test.js failed with ERR_MODULE_NOT_FOUND, taking its eight cases down with it. Negate the rule for scripts/lib and add the helper.
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个 PR 做了什么
给
dsh-plugin-usage增加参考定价体系、峰谷计价、折叠缓存与原生 typert 通道,并把设置页的用量面板补齐到可用状态。分支已 rebase 到最新main(0.4.0,输入区成本 pill),该 pill 原样保留。净改动 51 文件 / +9431 −417,按层分成 6 个提交(feat / test / docs / fix / docs / build)。与 0.4.0 的关系
src/client/index.js(dock 的 CSS 与本次的定价弹窗 CSS)、package.json(版本 + 新增dsh-client-ui-conversation注入)、CHANGELOG.md。解析时两边都保留:dock 的CostPill、注册与tests/client-dock.test.js随基线留下,定价弹窗与新的apply逻辑共存。0.4.x迭代(含本地标为 0.4.0 的定价改造)并入0.5.0 说明与文末附录,不再出现两个 0.4.0。
主要能力
scripts/gen-prices.mjs生成),查询只走
resolvePrice一个阶梯:用户自定义价 → 用户确认的匹配 → 字面命中 → 变体(
-free/-fast/-1017)→ 模糊。四态(精确/模糊/未匹配/自定义)由宿主给出,客户端不再二次解释——此前两处词表各自维护,一处写错就让所有精确命中显示成「未匹配」。
09:00–12:00、14:00–18:00为峰时,排除中国大陆法定节假日;节假表随用量数据年份顺延,未公布年份显式标注而不是静默丢表。
仅读取+解压就 12.5 s)。签名 = 折叠规则版本 + 节假表版本,损坏一律降级全量扫;
不做 prune(部分列表时 prune 曾删掉 257/258 条有效缓存)。
connection.fetch的/api/usage/*常驻兜底;实际通道随响应返回(channel字段),便于核对。参考成本,三处共用同一个
TipRows;只有"图例里真有这一项"的行(输入/输出/总 Token)带色块,参考成本与调用次数保留无色占位以维持对齐。读屏的
barAria/hmTitle带同一份{cost}。screenshots.json,插件市场按仓库里的声明取图(不再从 README 猜)。
两个需要说明的设计决定
startBackfillOnDemand)。此前在apply里开扫,而缓存加载只需 0.78 s(冷缓存 ~12 s)——窗口永远发生在用户打开面板之前,代码里有加载态、
屏幕上一次都看不见。代价是"读请求触发写",权衡与边界写在
docs/native-transport.md§3。backfill状态驱动:统计未完成期间整段骨架 + 确定进度条(宽度 =
done/total),不先给半份会往上爬的数字;尊重prefers-reduced-motion。测试
npm test224 项(宿主行为 + 客户端槽位/加载态/定价接线门 + dock 契约)tests/dialog.test.cjs75 项(在构建产物上跑真实 bundle + 假宿主)npm run verify:typert(官方 loader 校验 4 个端点)/npm run verify:remote(7/7)其中几条门是"接线门"而非行为门,专门抓
两半各自都对的回归:模型表必须渲染宿主的unpriced判定(不得自行重算)、骨架卡片数必须与统计卡槽位同源、按需扫描必须仍接在查询处理器上。变异验证过:删掉调用点/改回旧写法都会立即变红。
另外修掉一处会随包发布的本机路径:节假日历生成物的
coverage.basis不再写入维护者的C:\Users\…\sessions,只保留session store/calendar default,并加门防止回归。兼容性
engines.dsh为>=0.2.1-rc.3 <0.3.0,dsh.verifiedAgainst为0.2.1-rc.4(两个契约门都在rc.4 上重跑过)。输入区 pill 需要 0.2.1 的
conversation.composer.dock;0.2.0 缺该 slot 时注入失败只告警,不影响设置页。证书与取证对象写在
docs/native-transport.md。