Changelog
September 19, 2026 · View on GitHub
All notable changes to this project are documented here. The format follows Keep a Changelog and the project uses Semantic Versioning. 中文版见 CHANGELOG_ZH.md.
[1.1.6] - 2026-09-19
Fixed
- Host pricing file source lifecycle (
pricing.jsonoverride & change watcher) — PR #10:- Fixed premature disposal of
filePricingSourceduring plugin registration:ctx.effect(() => fileSource.dispose(), ...)calleddispose()synchronously while building the fiber and registeredundefinedas the cleanup handler, aborting initial asynchronous file loading and disabling the file change watcher. Resolved by returning a disposer function:ctx.effect(() => () => fileSource.dispose(), ...). - Updated test mocks in
tests/core.test.mjs,tests/pricing.test.mjs, andtests/rounds.test.mjsto properly track and execute Cordis effect disposers inafter(). - Added regression test covering the
/pricingroute with userpricing.jsonoverrides enabled at startup.
- Fixed premature disposal of
[1.1.5] - 2026-09-12
Changed
- DeepSeek official pricing update (2026-09-10) &
deepseek-flashsupport — PR #8:- New
deepseek-flashmodel pricing: Updated builtin pricing according to the official DeepSeek pricing table (verified 2026-09-10). The newdeepseek-flashrates are:- Off-peak (Beijing Mon–Fri non-peak & weekends): CNY 1.0 / 0.02 / 4.0 per 1M tokens (cache-miss input / cache-hit input / output); USD 0.15 / 0.003 / 0.6 per 1M tokens.
- Peak (Beijing Mon–Fri 09:00–12:00 & 14:00–18:00): CNY 2.0 / 0.04 / 8.0 per 1M tokens; USD 0.30 / 0.006 / 1.2 per 1M tokens.
- Backward compatibility for legacy model names:
deepseek-v4-flashanddeepseek-v4-flash-vision-expare mapped todeepseek-flashinBUILTIN_PRICINGso historical session logs continue resolving without falling back to unknown-model estimates. - Fallback pricing: Default unlisted model fallback (
FALLBACK_PRICING) now points to the newdeepseek-flashpricing. - Docs & test synchronization: Updated custom
pricing.jsonexample inREADME.mdandREADME_ZH.md(verifiedAt: 1788998400000), and aligned test cases acrosstests/core.test.mjs,tests/pricing.test.mjs, andtests/rounds.test.mjs(BUILTIN_VERIFIED_ATset to2026-09-10T00:00:00Z).
- New
[1.1.4] - 2026-09-08
Fixed
dsh-session >= 0.1.2-rc.1compatibility (snapshotEvents()) — PR #7:dsh-sessionremoved its publiceventsproperty in0.1.2-rc.1(replaced by thesnapshotEvents()method); the/usageroute then threwTypeError: events is not iterable, whichdsh-host-webserverwrapped as a bare400empty response, and the per-round chart disappeared (the client fell back to the empty observed-rounds path). Reproduced live ondsh-session 0.1.2-rc.1:/usage?session=<loaded>returned an empty400while/usage?session=<unknown>returned the plugin404JSON and folding the same log offline succeeded — confirming the crash was only the new runtime API shape. The host now reads events via capability detection — preferssession.snapshotEvents()when the function is present and falls back to the legacysession.events ?? [](so a missing API can never crash the route again). The vendoredSessionEventLiketype adds thetimefield (Unix epoch ms) and aSessionHandleshape (optionalevents+ optionalsnapshotEvents) soSessionStoreService.get()/list()stay valid across both API generations. Verified against the upstreamdeepseek-harnesssource:Session.eventswas removed from0.1.2-alpha.4onward (official architecture note2026-08-21-session-log-read-intent); the installed0.1.0-rc.6still exposesevents, so the fallback path remains covered.- Test coverage for the new
snapshotEvents()access path: addedtests/rounds.test.mjs→/usage route prefers snapshotEvents() when the new API is present, mocking a session handle that exposes onlysnapshotEvents()(itsget events()throws, proving the route never reads the removed property), assertstimeis consumed (duration/peak billing) and thatsnapshotEvents()wins when both APIs are present.
[1.1.2] - 2026-08-26
Improved & Fixed
- Compact 2-Column Hover Tooltip & Overflow Elimination:
- Height Reduction: Redesigned
.duc-chart-tooltipinto a compact 2-column grid (2×2 token breakdown + 2-column metadata pairs), reducing card height from ~280px to ~120px (>55% reduction). - Top-Aligned Positioning: Adjusted placement from
top: 20pxtotop: 2px(240px width), ensuring the hover card stays strictly within the 132px chart boundary and never expands container scroll height or triggers popover scrollbars.
- Height Reduction: Redesigned
[1.1.1] - 2026-08-26
Improved & Fixed
- Compact Panel UI & Vertical Overflow Elimination:
- Height Reduction: Tightened
.duc-sectionvertical padding from12pxto8px, compacted.duc-cellpadding from8px 9pxto5px 8px, reduced bar heights and line-heights. Overall panel height shrinks from ~800px to ~560px (~170px reduction), allowing the full dashboard to fit comfortably in viewport without vertical scrolling. - Removed Redundant Legend: Eliminated the duplicate 4-color legend row in the "Session Usage" section (values are already labeled in the 4 grid cards above; chart legend remains intact in the per-round section).
- Lightweight Compaction Empty State: When no compaction has occurred, the placeholder row is omitted to save vertical space; compaction details are shown only when compactions exist.
- SVG Chart Height Optimization: Reduced
RoundBarsbaseline height from96pxto76px(canvas height reduced from166pxto132px), keeping all scroll arrows, duration lines, anomaly markers, and hover tooltips aligned and legible. - Robustness Defense: Added fallback defaults for missing
currencyparameter ('cny') and safe optional chaining onround.costinRoundBars.
- Height Reduction: Tightened
[1.1.0] - 2026-08-26
Milestone release: Context Explainability & Compaction Diagnostics. Turns "why context grows, which round got compacted, how many tokens were freed, and how much the summarize step cost" into an interpretable view (dock indicator + dedicated panel diagnostics section), alongside user/message input source attribution.
Added
- Context & Compaction Diagnostics Section: added a dedicated diagnostics section in the panel showing System Prompt, Tools Schema, and Message History token counts and percentage breakdown, complete with a multi-segment color bar (system blue, tools amber, messages green) and an explicit heuristic-approximation note based on the official
contextBreakdownprojection. - Compaction Lifecycle Folding & Cost Accounting: host-side
foldCompactions(src/usage/compactions.ts) parsescompaction/start,compaction/summary,compaction/prune, andcompaction/endevents from session logs, tracking shadowed token count, shadowed range/seqs, round attribution, summarize model, and dual-currency summarize cost (peak/off-peak tier aware). - Compaction Timeline & Savings: the diagnostics section summarizes total freed tokens and total compaction occurrences, listing each compaction record (round, freed tokens, summarize cost).
- Context Occupancy Recommendations: actionable recommendations based on
contextPressureoccupancy (≥75% suggests starting a new session or trimming large file injections; ≥90% warns of imminent context exhaustion). - Segmented Dock Pressure Bar: consumes official
contextBreakdownprojection to render system (blue), tools (amber), and messages (green) multi-segment bars on the composer dock indicator with detailed tooltip percentages, smoothly falling back to single-color bar when breakdown is unavailable. - Per-Round User Source Attribution:
foldRoundscapturesuserSource(human,agent.inject,continuation) fromuser/messageevents and displays the attribution badge in the chart tooltip explainer card. - New Exports:
foldCompactionsfunction andCompactionRecordtype.
[1.0.2] - 2026-08-26
Fixed
- Weekend off-peak tier rule:
isPeakHourandtierAtnow take day-of-week into account — peak hours strictly apply to Monday through Friday 09:00–12:00 and 14:00–18:00 (Beijing time / UTC+8); all hours on Saturday and Sunday are now correctly classified as off-peak (leisure/discount period). - Builtin pricing coverage: added
deepseek-v4-flash-vision-expto builtin pricing table (identical pricing to flash); updatedBUILTIN_VERIFIED_ATto2026-08-26.
[1.0.1] - 2026-08-17
Billing updated to the latest DeepSeek pricing (official pricing pages, fetched 2026-08-17): prices are now quoted in two currencies — CNY (Chinese page) and USD (English page) — per 1M tokens with peak / off-peak tiers — peak hours (Beijing time 09:00–12:00 and 14:00–18:00, i.e. UTC 01:00–04:00 and 06:00–10:00) are billed at 2× the off-peak rate.
Added
- Peak/off-peak tiered billing: the builtin price table stores both
peakandoffPeakunit prices per model; each round's cost is billed with the tier of its start time (tierAtresolves Beijing time = UTC+8). Unknown timestamps fall back to the peak tier (conservative estimate). - Official dual-currency pricing: each tier carries both the official CNY quote and the official USD quote; costs are computed with the list price of the selected display currency — no FX conversion, consistent with the official bill. The CNY/USD toggle now drives the indicator, the panel, the chart cost view and the cost badge.
pricing.jsonnow accepts the dual-currency tiered shape{ "peak": { "cny": {…}, "usd": {…} }, "offPeak": {…} }; legacy shapes are still accepted (single-currency tiers or the flat shape are treated as CNY, with USD derived at the default rate 6.76).- New exports:
costSplitAt,tierAt,isPeakHour,formatCny, and theCostCurrency/PriceTier/PriceTierId/BucketPricestypes. - The cost note in the panel now shows both tiers: e.g. cache-miss input
1.5/3.0(off-peak/peak) in the selected currency. - Live billing-tier tag: the panel's session-usage header shows a red (peak) / green (off-peak) tag for the current billing period (Beijing time, auto-flips at hour boundaries), and each round's tooltip shows its own billing tier.
- Per-round cost always visible: in the cost chart view every bar shows its own cost value (not only the current round), and the observed-rounds fallback (no host history) now derives per-round cost client-side from the
/pricingsnapshot + per-turn model/start time, so the cost view works even without host history.
Changed
- Builtin list price updated to the official prices (flash: CNY off-peak 1.5 / 0.05 / 4.5, peak 3.0 / 0.10 / 9.0; USD off-peak 0.22 / 0.007 / 0.66, peak 0.44 / 0.014 / 1.32; pro: CNY off-peak 4.5 / 0.15 / 13.5, peak 9.0 / 0.30 / 27.0; USD off-peak 0.66 / 0.022 / 1.98, peak 1.32 / 0.044 / 3.96 — miss input / hit input / output);
BUILTIN_VERIFIED_ATupdated to 2026-08-17. - Cost computation is now currency-parameterized:
costSplit(usage, pricing, tier, currency)andcostSplitAt(usage, pricing, timeMs, currency)return a currency-neutralCostSplit(input/cacheRead/output/total) in the requested currency.formatMoney/formatPricePerMdrop the FX-rate parameter (amounts are already in the display currency);toDisplayAmountis removed.estimateCostkeeps returning{ cny, estimated }(official CNY prices). foldRoundsbills each round with the tier of itsturn/starttime (fallback:turn/end, then peak) and publishes bothcnyandusdcost splits in the/usagepayload, so the client can switch currencies without re-deriving.- The FX rate (
config.cnyPerUsd,/rate, "Refresh rate") is now informational only ("1 USD ≈ X CNY" note); costs never depend on it for official models.
Fixed
- The old builtin table (single-currency USD, flat price) no longer matched the official tiered billing in either currency, so costs were stale; the whole pipeline now follows the current official pricing pages (CNY + USD).
[1.0.0] - 2026-08-15
First complete release — the in-session usage interpreter is feature-complete (per-round chart with full-history horizontal scroll + cost/timing/anomaly explainer + multi-currency costs with live rates + account balance).
Changed
- Per-round chart no longer truncates to the latest 12 rounds: all rounds render into a horizontally scrollable area with a fixed slim bar width (30px), so bars stay constant-width and never look crowded. It auto-scrolls to the latest round, and arrow buttons + edge fades appear when content overflows; the scrollbar is slimmed down.
- Per-bar value labels adapt to density: in scrollable (dense) mode only the current round keeps its top-of-bar value (details stay in the hover explainer card); otherwise overly long labels (e.g.
$0.0013,123.4K) are elided so neighbouring labels never overlap. - Chart minimum width adapts to the panel width: short histories fill/center without stretching bar widths; the tooltip follows the active bar across scrolling (content coordinate − scroll offset, clamped to the visible area).
Fixed
- The tooltip could not be positioned correctly once the chart could scroll; it now tracks the bar precisely at any scroll position.
- Short histories could overflow on narrow panels; the adaptive minimum width removes the needless scroll.
- The balance no-key test now isolates
$DEEPSEEK_API_KEY, so the suite passes on hosts that have the key in the environment; added coverage for the env fallback itself.
[0.3.0] - 2026-08-15
Added
- Cost display currency:
config.currency('usd' | 'cny') andconfig.cnyPerUsd(default 6.76); costs render in the chosen currency. - USD/CNY toggle in the cost section; the choice is remembered in the browser (localStorage).
- Rate-refresh button: fetches the latest USD→CNY rate through the new same-origin
/dsh-usage-chart/rateproxy (config.fxUrl) and re-estimates immediately. /dsh-usage-chart/metaroute serving display-currency config to the client.
Changed
- Per-model price notes follow the display currency and show the applied rate (e.g.
CNY(1 USD ≈ 6.76 CNY)).
Fixed
- Resilient rate refresh: falls back to a built-in FX source (frankfurter.dev) when the default (open.er-api.com) is unreachable or blocked; the last successful rate is persisted, so offline refreshes keep the previous rate instead of the fixed default.
- Client slots register via
ctx.slots.inject(wait for declaration), fixingslot "…" is not declaredwhen loader order changes.
[0.2.0] - 2026-08-15## [0.2.0] - 2026-08-15
Added
- Per-round cost explainability (v0.2, see
docs/ROADMAP.md): the host fold (RoundFold,src/usage/rounds.ts) now derives per-round duration (turn/start → turn/end), TTFT (start → first usage sample), output throughput (tokens/s), model attribution (request/context→request/header→ cross-round carry-forward), end reason, and a per-round cost split (input / cache-read / output × unit price). - Pricing governance:
src/pricing.tsis split into a pure math module (pricing/calc.ts, bundled by both halves) and a host-onlyPricingSourceseam (pricing/source.ts— builtin list with a verification date + user-overridepricing.jsonfile adapter with change watching) plus aPricingResolver(pricing/resolve.ts, priority file > builtin > fallback, unknown models explicitly marked). New/dsh-usage-chart/pricingroute exposes the resolved snapshot — the client's only price input (ADR 2); the old bundled pricing constants no longer drift from host resolution. /usageroute now returnsrounds(with cost/timing/model/endReason) instead of bareturns(foldTurnUsagekept as a v0.1-compatible wrapper).- RoundBars cost view: a third chart mode stacks bars by cost (bucket × unit
price); a duration polyline overlays bar tops; anomalously expensive rounds
(relative to the previous N rounds,
src/client/diagnose/anomaly.ts) get a warning marker with attributed reason chips; a per-round cache-hit mini tick sits under the baseline; the tooltip became an explainer card (tokens + cost + model + duration + TTFT + TPS + cache hit + end reason + anomaly chips). - Cost badge: a dismissible
≈ \$0.00xxbadge per assistant message (conversation.chat.assistant-actionsslot, data from the host/usagehistory). - Dock context pressure bar: slim
contextPressurebar in the indicator (green → amber → red as occupancy rises). - Tests:
tests/rounds.test.mjs(fold timing/TTFT/TPS/model/cost + route),tests/pricing.test.mjs(resolver priority, file source with temp dir, unknown marking + route),tests/anomaly.test.mjs(spike flagging and attribution); 28 tests pass vianpm run verify. - Configuration: optional
config.pricingFileoverrides the default$DSH_HOME/data/dsh-usage-chart/pricing.json(falls back to~/.dsh/...).
Fixed
- Cost estimates are now single-sourced: real-time indicator cost and panel cost both
consume the
/pricingsnapshot; the price source, verification date, and unknown-model marker are shown in the panel. - Panel cost resolution now prefers the host fold's authoritative model attribution (ADR 1) over snapshot provenance, which can be absent for older sessions — the price source previously showed a spurious "fallback estimate" in that case.
Upgrade note
- Restart
dsh webafter upgrading to 0.2.0. The Host process caches plugin code in memory (no hot reload): the new/dsh-usage-chart/pricingroute and therounds-shaped/dsh-usage-chart/usageresponse are only served after a restart. Until then the indicator silently omits the cost segment and the panel shows "Price snapshot unavailable".
[0.1.1] - 2026-08-14
Added
- Balance queries now resolve the DeepSeek API key through the DSH credentials service
(
ctx.get('credentials')), so a key configured in the web UI (Settings → Models) or in.credentials.yamlworks without an environment variable or plugin config.
Fixed
- Install warning
missing peer react@^18.2.0(react is provided by the DSH web platform; the peer is now marked optional). - Docs: document uninstall/cleanup steps in the README.
[0.1.0] - 2026-08-14
Added
- Composer usage indicator and expandable SVG dashboard.
- Session token, cache, context-pressure, model, and estimated-cost views.
- Per-turn usage chart with total/mix views, hover and keyboard tooltips, and a highlighted current-round band; host-side per-turn aggregation from the session log.
- Host-side DeepSeek balance proxy.
- Full zh/en localization: the indicator, dashboard, charts, and balance views follow
the DSH in-app Language setting through the
localeservice (dictionaries registered under thedsh-usage-chartnamespace; browser language only seeds the initial value). - Release metadata, bilingual documentation, CI, contribution/security policies, and
portable visual probe scripts (
scripts/*.mjs). - Privacy-safe README demo screenshot with fictional usage values and no account data.
Fixed
- Light-mode readability: indicator, panel, and SVG charts now use DSH theme tokens
(
--dsw-alias-label-*/--dsw-alias-bg-*) and theme static palette colors, so text and chart segments stay legible in both light and dark appearances.
Security
- Restrict Host JSON routes to same-origin GET requests.
- Require HTTPS for custom API endpoints, except loopback HTTP proxies.
- Validate token-usage samples before aggregation.