Files
dsh-context/tests/client/setup.ts
T
Bowen Liang 7cf9284362 feat(stats): estimate session cost from models.dev prices
Replace the hardcoded DeepSeek rate table with a client-fetched price
book: @opencode-ai/models reads the models.dev registry once per page
load, every entry is re-proved at the boundary, and a failed fetch
degrades to a dash + note with backed-off automatic retries.

- cost totals rekey per (provider, model); only DeepSeek splits a
  pricing period (peak windows at list price, all other hours half
  price) — every other provider bills everything at list price
- provider ids resolve through a shared rename table (deepseek-official,
  kimi-coding, minimax-cn, zai-coding-cn) with verbatim passthrough for
  unmapped ids; model ids match exactly, case-insensitively, or by
  suffix (k3 -> kimi-k3), ambiguous matches price nothing
- CNY display converts at the fixed 1 CNY = 0.15 USD; the tooltip lists
  per-1M rates for the models the session billed, with peak|off-peak
  pairs and the DeepSeek note shown on DeepSeek sessions only
- stateVersion 18: cached rows refold from the log, which rebuilds the
  new cost keys and periods
2026-09-13 00:35:03 +08:00

18 lines
920 B
TypeScript

// Client project setup: React 18 `act` requires this flag to flush effects
// synchronously in tests; every jsdom spec shares the real React runtime.
;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
import { resetModelPrices, setModelPricesLoader } from '../../src/client/modelPrices'
// jsdom does not implement scrollIntoView; the plugin calls it when focusing
// a browser row. A no-op polyfill stands in for the platform (layout-free).
if (typeof Element !== 'undefined' && Element.prototype.scrollIntoView === undefined) {
Element.prototype.scrollIntoView = () => {}
}
// The model-price store starts DORMANT in tests: its loader resolves never,
// so no spec ever reaches the network. Specs that need prices inject their
// own loader (resetModelPrices + setModelPricesLoader, see modelPrices.spec).
resetModelPrices()
setModelPricesLoader(() => new Promise(() => {}))