English | [中文](README.md)

# dsh-session-cost

A DeepSeek Harness (dsh) web plugin that shows the **current session's DeepSeek API cost** as a small chip beside the composer input.

## Features

- **Live session cost** — a chip in the `conversation.input.right` slot (left of the model selector) shows the current session's DeepSeek API spend (¥), refreshed every 5 seconds.
- **Strict model gate** — the chip only appears when the session's current model is DeepSeek; other models (MiniMax, Kimi, …) are never priced and never enter the statistics.
- **Hover popover** — a project-styled card with:
  - a session cost breakdown **table**: input (cache miss) / cache hit / output × tokens × effective rate = amount;
  - today's DSH usage: DeepSeek spend across local DSH sessions for today (Beijing time);
  - account balance: read from the DSH credential `DEEPSEEK_API_KEY` via the official `user/balance` endpoint.
- **Official pricing engine** — every `assistant/message` event is priced by its own timestamp against the official DeepSeek pricing timeline, including the 2026-08-17 peak/off-peak policy (Beijing 09:00–12:00 / 14:00–18:00 peak, half price otherwise), and covering history from before this plugin was installed.
- **Performance friendly** — session log replays are cached by log revision (a 5-second poll costs one stat, not a re-decompress); today/balance refresh on their own 60-second cadence.

## Install

```sh
dsh plugin --profile web add @phynez_1103/dsh-session-cost
```

> ⚠️ **Note**: this plugin's npm package name is **scoped: `@phynez_1103/dsh-session-cost`**. The unscoped `dsh-session-cost` package on npm ([ChengChe106/dsh-session-cost](https://github.com/ChengChe106/dsh-session-cost)) is a different, same-named plugin, unrelated to this repo — `dsh plugin add dsh-session-cost` installs that one, not this one.

Or install straight from the GitHub repo:

```sh
dsh plugin --profile web add github:Lzh3070/dsh-session-cost
```

Or from the Gitee mirror (faster in mainland China):

```sh
dsh plugin --profile web add https://gitee.com/lzh10602042_gitee/dsh-session-cost/repository/archive/master.zip
```

Restart the dsh web service and hard-refresh the browser (Ctrl+Shift+R).

First use: configure `DEEPSEEK_API_KEY` in Settings → Models (used for the balance and today's total; without it the balance shows `--`, session cost still works).

## Screenshot

The chip (`¥0.12`) beside the composer input, with the hover popover:

![session cost screenshot](Snipaste.png)

Popover contents example:

```
当前会话花费 ¥6.55
  项目        数量      单价        金额
  输入(未命中) 3.5M     ¥1.000/M   ¥3.49
  缓存命中    111.8M    ¥0.020/M   ¥2.24
  输出      410.5K     ¥2.00/M    ¥0.821
──────────────────────────────
  今日(DSH)          ¥0.356
  账户余额          ¥197.66
```

## Pricing

Built-in official DeepSeek policy timeline (CNY per 1M tokens):

| Model | Stage | Input (miss) | Cache hit | Output |
| --- | --- | --- | --- | --- |
| deepseek-v4-flash | current (since 2026-05-22) | 1 | 0.02 | 2 |
| deepseek-v4-flash | peak (since 2026-08-17) | 3 | 0.1 | 9 |
| deepseek-v4-flash | off-peak (since 2026-08-17) | 1.5 | 0.05 | 4.5 |
| deepseek-v4-pro | current (since 2026-05-22) | 3 | 0.025 | 6 |
| deepseek-v4-pro | peak (since 2026-08-17) | 9 | 0.3 | 27 |
| deepseek-v4-pro | off-peak (since 2026-08-17) | 4.5 | 0.15 | 13.5 |

The table lives in `OFFICIAL_PRICING_POLICIES` in `lib/index.js`; append entries to the `since` timeline when the official pricing changes.

## Structure

```
cordis.patch.yml   inserts the plugin row into the host composition
dsh.plugin.json    plugin metadata (entry id + client platform)
lib/index.js       host entry: SessionCostRuntime (TypertRemoteService) +
                   official pricing engine + strict Typert manifest
lib/client.js      single-file client bundle (ModuleLoader handshake):
                   composer cost chip + hover popover (class component)
lib/invariant.js   invariants companion entry
```

## Data flow

- Host `sessionCost(sessionId)`: replays the persisted session log via `sessionPersistence.readRaw`, prices every message, cached by log revision.
- Host `accountSummary()`: replays all sessions for today's (Beijing) DeepSeek usage; reads `DEEPSEEK_API_KEY` from DSH credentials for the official `user/balance` call.
- Client: registered in the `conversation.input.right` slot, 5s session poll + 60s account cadence + hover popover.

## License

MIT. The pricing engine is ported from [dsh-deepseek-quota](https://github.com/yingjunnan/dsh-deepseek-quota) (MIT, itself ported from [bpc-oss/dsh-web-billing](https://github.com/bpc-oss/dsh-web-billing), MIT).
