Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/). 中文版见 [CHANGELOG_ZH.md](./CHANGELOG_ZH.md).

## [1.1.8] - 2026-10-21

### Fixed

- **DSH 0.2.x compatibility (plugin admission gate)** — DSH 0.2.1-rc.2 only loads a plugin when `package.json` declares `engines.dsh`, or when every `peerDependencies` range whose package name is `@deepseek-ai/dsh` / `@deepseek-ai/dsh-*` matches the running DSH runtime version. 1.1.7 declared all four DSH client peers with `>=0.1.0-rc.6 <0.2.0`, so startup was denied with the user-visible warning `dsh-usage-chart@1.1.7 与 DSH 0.2.1-rc.2 不兼容(要求 @deepseek-ai/dsh-client-locale >=0.1.0-rc.6 <0.2.0, ...)…`. The peer ranges now cover both client-SDK generations:
- `@deepseek-ai/dsh-client-locale`, `@deepseek-ai/dsh-client-ui-conversation`, and `@deepseek-ai/dsh-client-ui-slots` widened from `>=0.1.0-rc.6 <0.2.0` to `>=0.1.0-rc.6 <0.3.0-0`. The `-0` upper bound matters because DSH compares ranges with `includePrerelease`: it still admits 0.2.x prereleases (like 0.2.1-rc.2) but keeps future 0.3.0 prereleases out.
- The retired `@deepseek-ai/dsh-client-runtime` peer is removed. DSH 0.2.x replaced it with the `dsh-client-modules` module system (plus `dsh-client-ui-renderer`, the `dsh-client-ui-session` standard kit, and `dsh-client-store`); its last published version was `0.1.1-rc.2`, so no 0.2.x-compatible release exists.
- DSH 0.1.x stays supported on the code level: the 0.1.x paths (`provenance`, `assistant/chunk`, string `user/message.source`) are kept, and the APIs the plugin uses are the same on both lines. The 0.2.1-rc.2 side was verified against the installed app bundle and the published 0.2.1-rc.2 package typings: slots `conversation.composer.dock` and `conversation.chat.assistant-actions` still exist and render; session-scope standard props still deliver `useSession` / `sessionId` / `useProjection` (ui-session) and `useChat` (ui-chat); `useChat` snapshots still expose `legacy.nodes`; the `tokenUsage` / `contextPressure` / `contextBreakdown` projections keep their fields; `ctx.locale.getLocale()` / `subscribe` and `ctx.slots.inject` / `register` are unchanged; and the host `webServer.register` / `sessions.get` / `snapshotEvents` / `credentials.resolve` services are unchanged. No live 0.1.x install was re-run after `dsh-client-runtime` left `dsh.client.inject`.
- **Assistant-node model identity on DSH 0.2.x** — the assistant-node model identity now also reads the 0.2.x `providerMetadata` field. The DSH 0.1.x `provenance` source is still preferred when present, and `requestConfig` remains the last-resort fallback, so model labels and per-message cost attribution no longer lose the model on 0.2.x.
- **Self-contained client type declarations** — the emitted client `.d.ts` files no longer import the retired `@deepseek-ai/dsh-client-runtime` package. Type-checking the plugin in a 0.2.x-only DSH tree can no longer fail on a dangling import of a package DSH no longer ships; 0.1.x trees keep working as before.
- **DSH 0.2.x session-log vocabulary** — DSH 0.2.x dropped `assistant/chunk` events and folds streaming usage into `assistant/message` (`usage` + `stream`). The host fold now follows the official token-meter accounting on these logs:
- Message usage comes from `data.usage`, falling back to the last usage record in `stream`.
- Failed or retried requests, which 0.2.x persists only as `assistant/attempt` with usage inside `stream`, are counted in totals and per-round costs, and each attempt is billed separately across retry boundaries.
- TTFT is the first token-bearing stream record: structural `block-start` / `usage` / `finish` records and empty fragments are skipped, while raw `*-delta` chunks and name-bearing tool-call fragments count even when their argument text is empty.
- Output TPS divides output tokens by the summed streaming time of each `assistant/message` / `assistant/attempt`, so tool execution and the wait between steps no longer drag it down; a turn whose output arrives as a single fragment reports no TPS. Logs without a stream timeline keep the 0.1.x anchors (first usage sample → turn end).
- `user/message.source` changed from a string to a `{ kind }` object. `user` and `user-*` map to `human`, goal/continuation and agent kinds keep their name, and other runtime injections such as `tool-jobs` become `agent.<kind>`, so the input-source label no longer shows them as human.

### Tests

- New manifest tests assert the widened peer ranges, that the retired `@deepseek-ai/dsh-client-runtime` peer/inject entry is gone, and that the built client bundle and published client type declarations no longer reference the retired package. New fold tests feed DSH 0.2.x-shaped logs (no `assistant/chunk`, `assistant/message` / `assistant/attempt` with `usage` + `stream`, object `user/message.source`) and assert totals, stream-only usage, TTFT from token-bearing records (raw delta chunks, name-bearing tool-call fragments), TPS over streaming time across steps, failed-attempt and retry billing, and source normalization; the retired-runtime check now scans every published client `.d.ts`; a client test covers the `provenance` → `providerMetadata` → `requestConfig` model fallback. `npm run verify` passes (typecheck + build + `node --test`, all 55 tests). The compatibility surface was checked against the installed DSH 0.2.1-rc.2 app bundle and the published 0.2.1-rc.2 package typings, and a headless-browser smoke test of a DSH 0.2.1-rc.2 Web instance loaded the linked 1.1.8 build: the boot graph included the plugin, the dock indicator rendered live usage/cost against a real session (zh copy through the `locale` service) and the expanded panel rendered session totals, context breakdown and the token projections, with no plugin console errors.

## [1.1.7] - 2026-09-24

### Fixed
Expand Down
21 changes: 21 additions & 0 deletions CHANGELOG_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
本文件记录本项目所有重要变更。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。英文版见 [CHANGELOG.md](./CHANGELOG.md)。

## [1.1.8] - 2026-10-21

### 修复

- **兼容 DSH 0.2.x(插件准入校验)**——DSH 0.2.1-rc.2 在启动时执行插件准入校验:除非 `package.json` 声明了 `engines.dsh`,否则所有包名为 `@deepseek-ai/dsh` 或 `@deepseek-ai/dsh-*` 的 `peerDependencies` 范围都必须匹配当前运行的 DSH 运行时版本。1.1.7 的 4 个 DSH client peer 都声明为 `>=0.1.0-rc.6 <0.2.0`,因此启动时被拒绝,并给出用户可见警告:`dsh-usage-chart@1.1.7 与 DSH 0.2.1-rc.2 不兼容(要求 @deepseek-ai/dsh-client-locale >=0.1.0-rc.6 <0.2.0, ...)…`。现在 peer 范围同时覆盖两代 client SDK:
- `@deepseek-ai/dsh-client-locale`、`@deepseek-ai/dsh-client-ui-conversation`、`@deepseek-ai/dsh-client-ui-slots` 的 peer 范围由 `>=0.1.0-rc.6 <0.2.0` 放宽为 `>=0.1.0-rc.6 <0.3.0-0`。上界带 `-0` 是因为 DSH 以 `includePrerelease` 比较范围:这样仍接受 0.2.x 预发布(如 0.2.1-rc.2),但不会把未来的 0.3.0 预发布提前放行。
- 移除已退役的 `@deepseek-ai/dsh-client-runtime` peer。DSH 0.2.x 用 `dsh-client-modules` 模块系统(以及 `dsh-client-ui-renderer`、`dsh-client-ui-session` 标准套件与 `dsh-client-store`)取代了它;该包最后发布的版本为 `0.1.1-rc.2`,不存在兼容 0.2.x 的版本。
- 在代码层面继续支持 DSH 0.1.x:保留 0.1.x 的 `provenance`、`assistant/chunk` 与字符串型 `user/message.source` 路径,插件使用的接口在两条线上一致。0.2.1-rc.2 侧已对照本机安装的应用包与已发布的 0.2.1-rc.2 包类型声明核实:`conversation.composer.dock`、`conversation.chat.assistant-actions` 槽位仍存在且正常渲染;会话作用域标准属性仍提供 `useSession` / `sessionId` / `useProjection`(ui-session)与 `useChat`(ui-chat);`useChat` 快照仍暴露 `legacy.nodes`;`tokenUsage` / `contextPressure` / `contextBreakdown` 投影字段不变;`ctx.locale.getLocale()` / `subscribe` 与 `ctx.slots.inject` / `register` 未变;宿主 `webServer.register` / `sessions.get` / `snapshotEvents` / `credentials.resolve` 服务未变。把 `dsh-client-runtime` 移出 `dsh.client.inject` 后,未在 0.1.x 上重新做实机安装测试。
- **适配 DSH 0.2.x 的助手节点模型识别**——助手节点的模型标识新增读取 0.2.x 的 `providerMetadata` 字段;存在 DSH 0.1.x 的 `provenance` 字段时仍优先使用,`requestConfig` 继续作为最后回退,0.2.x 下模型名称与逐条消息成本归因不再丢失。
- **client 类型声明自包含**——生成的 client `.d.ts` 不再 import 已退役的 `@deepseek-ai/dsh-client-runtime` 包。在仅安装 0.2.x 的 DSH 环境做类型检查时,不会再因悬空导入(DSH 已不再提供该包)而失败;0.1.x 环境行为保持不变。
- **适配 DSH 0.2.x 会话日志词汇**——DSH 0.2.x 移除了 `assistant/chunk` 事件,流式用量合并进 `assistant/message`(`usage` + `stream`)。宿主折叠现按官方 token-meter 的口径处理这类日志:
- 消息用量取 `data.usage`,缺席时回退到 `stream` 里最后一条 usage 记录。
- 0.2.x 把失败/重试的请求只记为 `assistant/attempt`(用量内嵌在 `stream` 中),这些用量现在也计入会话总量与每轮成本,重试前后的每次尝试分别计费。
- TTFT 取流里首个携带 token 的记录:跳过 `block-start` / `usage` / `finish` 等结构记录与空片段;原始 `*-delta` chunk 与带工具名的 tool-call 片段即使参数为空也算 token。
- 输出吞吐 = 输出 token ÷ 各条 `assistant/message` / `assistant/attempt` 流式时长之和,不再被工具执行与步骤间等待拉低;整轮输出只有一个片段时不报吞吐。没有流时间线的日志沿用 0.1.x 口径(首个 usage 样本 → 轮次结束)。
- `user/message.source` 由字符串改为 `{ kind }` 对象:`user` 与 `user-*` 归为 `human`,目标续跑与 Agent 类来源保留原名,`tool-jobs` 等其他运行时注入记为 `agent.<kind>`,来源标签不再把它们显示为人工。

### 测试

- 新增 manifest 测试断言放宽后的 peer 范围、退役的 `@deepseek-ai/dsh-client-runtime` peer/inject 条目已移除,以及构建后的 client bundle 与发布的 client 类型声明均不再引用该退役包。新增折叠测试喂入 DSH 0.2.x 形状的日志(无 `assistant/chunk`、`assistant/message` / `assistant/attempt` 带 `usage` + `stream`、`user/message.source` 为对象),断言 token 汇总、仅在流中的用量、由携带 token 的记录(原始 delta chunk、带工具名的 tool-call 片段)推导的 TTFT、跨步骤按流式时长计算的 TPS、失败尝试与重试计费,以及来源归一化;退役 runtime 检查改为扫描全部发布的 client `.d.ts`;另有 client 测试覆盖 `provenance` → `providerMetadata` → `requestConfig` 模型回退。`npm run verify` 全部通过(typecheck + build + `node --test`,共 55 项测试)。兼容面已对照本机安装的 DSH 0.2.1-rc.2 应用包与已发布的 0.2.1-rc.2 包类型声明核实;并在 DSH 0.2.1-rc.2 Web 实例上用 headless 浏览器完成加载冒烟测试:boot 图中包含本插件,输入框下方指示器在真实会话上渲染出实时用量/成本(经 `locale` 服务显示中文),展开面板渲染出会话汇总、上下文构成与投影数据,且无插件控制台错误。

## [1.1.7] - 2026-09-24

### 修复
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ environment variables — see the README's development section for the table.

## Compatibility

This plugin follows DSH 0.1.x Host/Client bundle conventions. Changes to injected services, slots, module-loader externals, or `cordis.patch.yml` must include an installation smoke test against a clean Web profile.
This plugin supports DSH 0.1.x and 0.2.x Host/Client bundle conventions; its peer ranges cover both. `@deepseek-ai/dsh-client-runtime` was retired in DSH 0.2.0 — do not reintroduce imports, build externals, or peer entries for it. Changes to injected services, slots, module-loader externals, or `cordis.patch.yml` must include an installation smoke test against a clean Web profile.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Click ▸ to open the dashboard panel:
- **Cost estimation** — Estimated from official list prices (CNY/USD dual-currency per 1M tokens, peak/off-peak tiers) with verified source date; supports user override via `pricing.json`; unpriced models are explicitly tagged.
- **Session-cost aggregation (v1.1.7)** — Adds the host's per-round costs using each round's model and billing tier. While a new round is in progress, the indicator and panel share the fetched history plus a marked estimate for new tokens, then refresh the history after token updates pause. The model label follows the same current-history/live-node priority in both places.
- **DSH 0.1.2+ and themed docks (v1.1.7)** — Reads conversation nodes from the independent `chat` source on newer DSH versions, with a legacy session-snapshot fallback; keeps the expanded panel anchored when a theme creates a fixed-position containing block.
- **DSH 0.2.x client-SDK compatibility (v1.1.8)** — Declares client peer ranges spanning both DSH 0.1.x and 0.2.x (tested against 0.2.1-rc.2) so DSH 0.2.x's plugin admission gate accepts the plugin at startup; the retired `@deepseek-ai/dsh-client-runtime` peer is gone, and the assistant-node model identity now also reads the 0.2.x `providerMetadata` field (0.1.x `provenance` still preferred when present, `requestConfig` kept as the last fallback).
- **Peak / off-peak tiered billing (v1.0.1)** — Peak hours (Beijing time Monday–Friday 09:00–12:00 and 14:00–18:00, UTC 01:00–04:00 and 06:00–10:00) billed at 2× the off-peak rate; all other hours and weekends billed at off-peak rates; rounds bill automatically based on start time (or conservative peak if unknown); live red/green tag in the panel header.
- **Official dual-currency list pricing (v1.0.1)** — Builtin official CNY and USD prices directly used according to the active display currency — **no FX conversion applied to costs** (matching official billing); "Refresh rate" updates only the informational "1 USD ≈ X CNY" reference note.
- **Multi-currency display (v0.3 / v1.0.1)** — One-click toggle between USD and CNY (persisted in localStorage); indicator, panel, chart, and badges all follow.
Expand All @@ -48,10 +49,10 @@ Click ▸ to open the dashboard panel:
| Token usage | DSH official adapter session projections (`tokenUsage` / `contextPressure`) | ✅ Official real-time data |
| Cost | Official list price (builtin + optional `pricing.json` override, CNY/USD dual-currency / 1M tokens, peak/off-peak tiers) × reported usage | ⚠️ Estimate, not invoice; resolved via Host `/pricing` snapshot |
| Display currency | Host `/meta` config; costs directly calculated in selected currency list price | ✅ Official dual-currency list price |
| Per-round history | Host session log fold (`/usage`): duration / TTFT / TPS / model attribution / **input source attribution** / end reason / per-round cost | ✅ Official event stream fold |
| Per-round history | Host session log fold (`/usage`): duration / TTFT / TPS / model attribution / **input source attribution** / end reason / per-round cost. DSH 0.2.x derives TTFT/TPS from `assistant/message.stream`; 0.1.x falls back to chunk/usage anchors | ✅ Official event stream fold |
| Context & compaction | Official `contextBreakdown` / `contextPressure` projections + Host `compaction/*` event fold | ✅ Official projections + event fold |
| Balance | Official `GET https://api.deepseek.com/user/balance` | ✅ Official real-time data |
| Model name | Adapter request provenance / `request/context` | ✅ Official real-time data |
| Model name | Adapter `providerMetadata` (DSH 0.2.x) / request provenance / `request/context` (DSH 0.1.x) | ✅ Official real-time data |

## Tech stack

Expand All @@ -74,11 +75,11 @@ dsh plugin --profile web add dsh-usage-chart # installs and registers the prof
dsh web --profile web # starts DSH Web (stop it first if already running)
```

To update after 1.1.7 is published: pnpm may print `Already up to date` when already installed — use an **explicit version** (recommended) or **remove then re-add**:
To update after 1.1.8 is published: pnpm may print `Already up to date` when already installed — use an **explicit version** (recommended) or **remove then re-add**:

```sh
# Option ①: pin the target version explicitly
dsh plugin --profile web add dsh-usage-chart@1.1.7
dsh plugin --profile web add dsh-usage-chart@1.1.8
# Option ②: remove, then re-add (back to latest)
dsh plugin --profile web remove dsh-usage-chart
dsh plugin --profile web add dsh-usage-chart
Expand Down Expand Up @@ -191,6 +192,9 @@ A: `npx @deepseek-ai/dsh` runs transiently and installs no global command. Run `
**Q: Install shows `WARN missing peer react@^18.2.0`?**
A: Harmless — react is provided by the DSH Web platform in the browser; the profile does not need it. Plugin ≥ 0.1.1 marks react as an optional peer.

**Q: DSH 0.2.x warns `dsh-usage-chart@1.1.7 与 DSH 0.2.1-rc.2 不兼容(要求 @deepseek-ai/dsh-client-locale >=0.1.0-rc.6 <0.2.0, ...)…` — is the plugin incompatible?**
A: That warning comes from DSH 0.2.x's **plugin admission gate**, not from a damaged DSH install and not from data loss: DSH refuses to load a plugin whose `@deepseek-ai/dsh*` peer ranges do not match the running runtime version, and plugin 1.1.x declared 0.1.x-only ranges. Upgrade the plugin to **≥ 1.1.8** (`dsh plugin --profile web add dsh-usage-chart@1.1.8`), then restart `dsh web` and reload the DSH Web page if it was already open. DSH itself was not damaged and no session data, costs, or credentials were lost — the plugin simply was not loaded.

**Q: The balance still shows `–` / "not configured" after setting the API key in the web UI?**
A: Make sure the plugin is ≥ 0.1.1, then restart `dsh web`. As a stopgap, set `DEEPSEEK_API_KEY` or `config.apiKey`.

Expand Down Expand Up @@ -280,7 +284,7 @@ dsh-usage-chart/

| Component | Supported |
|---|---|
| DSH | ≥ 0.1.0-rc.6, built against the 0.1.x API; adapts to the `dsh-session` `snapshotEvents()` API — `Session.events` was removed in `0.1.2-rc.1`, so the `/usage` route reads events via `snapshotEvents()` with a legacy `events` fallback |
| DSH | ≥ 0.1.0-rc.6, including 0.2.x (tested against 0.2.1-rc.2); peer ranges cover both the 0.1.x and 0.2.x client SDKs (v1.1.8), and the `/usage` route reads events via the `dsh-session` `snapshotEvents()` API with a legacy `events` fallback (`Session.events` was removed in `0.1.2-rc.1`) |
| Node.js | ≥ 20 |
| Web UI | React 18 / `conversation.composer.dock` + `conversation.chat.assistant-actions` |
| OS | macOS, Linux, Windows (pure JavaScript, no native dependencies) |
Expand Down
Loading
Loading