# @deepseek-ai/dsh-client-ui-openrouter-usage English | [中文](README.zh.md) OpenRouter spend surface plugin, browser half: the per-session 会话费用 readout (`CostDock`) in the `conversation.composer.dock` strip (order 5, right after the shipped stats line) plus the account 余额 badge (`BalanceBadge`) at the sidebar foot (`sidebar.footer.action`). `CostDock` reads the durable `openRouterCost` projection (seeded by the history tail page, updated by `session/projection` frames), showing `会话费用 $X.XX` only once a step actually priced — no zero-cost group. An unknown-pricing step count surfaces in a tooltip so the figure's coverage stays visible. `CostDock` therefore owns no store, refresh chain, or event listener. `BalanceBadge` is account-global, so it is not a session projection: the slot inject face carries a `snapshot()` callback that polls the host `ctx.remote.openRouterUsage.snapshot()` Remote on a 60s interval and drives local state. In the collapsed rail it renders only the balance marker; in the wide column a labeled pill. Unknown or absent figures render the empty placeholder. Both entries render nothing before real data exists, so an assembly without the OpenRouter gateway or key costs no layout. The `/client` exports are the plugin body (`apply`/`inject`), the `CostDock`/`BalanceBadge` components, and the injected face types. ## Model Experience Indirectly, none. Neither the cost readout nor the balance badge injects any model context; they are pure client-side read models over the `openRouterCost` projection and the `openRouterUsage` Remote snapshot. The agent loop and all prompts are unchanged. #### KV Cache effect None. Cost derives from existing logged usage events and balance is a fetched account figure; neither is a new model-visible input. ## Known Limitations and Deferred Work - **Priced as of the fold** — `CostDock` renders whatever the durable projection holds; figures for already-folded history reflect the pricing table at fold time (see `dsh-openrouter-usage`). - **Polled, not pushed** — `BalanceBadge` polls the host snapshot; there is no `openRouterUsage` forwarded-event channel, so the figure updates on the poll interval rather than instantly.