@itookit/dsht 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -1,3 +1,3 @@
1
1
  # Git blob hashes of the reviewed bilingual pair.
2
- README.md: 8f9296caa5de076cfc7541ff372a5ce0712e9181
3
- README.zh.md: c78f46e20d2cca7fbda700e810234872016e69a7
2
+ README.md: 2ee216f6c15212f4025b5a6f893b721f57b0a89f
3
+ README.zh.md: 7d2db96e581c08759e446a18966ead68458980f2
package/README.md CHANGED
@@ -359,7 +359,7 @@ The client reads complete histories in the background on connection, every 60 se
359
359
 
360
360
  The bundled CNY rates were checked against the [official pricing page](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/) on 2026-09-10. Beijing weekday peak windows are 09:00–12:00 and 14:00–18:00; other times use half-price rates. Flash peak cache-miss-input/cache-hit-input/output rates are ¥2/¥0.04/¥8 per million tokens and Pro rates are ¥9/¥0.30/¥27; the current model name is `deepseek-flash`, and older Flash names keep those same rates. The provider has announced that from 2026-09-14T12:00+08:00 it serves `deepseek-v4-pro` from Flash and bills it at Flash rates, which the bundled entry records so that date does not overstate Pro usage. Separate cache writes use the uncached-input rate. An exact configured model price takes priority; otherwise `deepseek-official` names containing `pro` (case-insensitive) use Pro and all other names use Flash, including temporary model aliases. Other providers require explicit entries.
361
361
 
362
- The default price validity starts at Beijing midnight on the verification date; this is a local estimate policy, not a claim about the official effective date. Earlier usage needs historical price entries. The recorded assistant settlement timestamp selects the rate; requests spanning a tariff boundary may differ from the invoice because the official page does not specify their attribution. Images use provider-reported tokens. Cached priced requests retain their price version when configuration changes; previously unpriced requests can be priced on a later scan.
362
+ The default price validity starts at Beijing midnight on the verification date; this is a local estimate policy, not a claim about the official effective date. Earlier usage needs historical price entries. The recorded assistant settlement timestamp selects the rate; requests spanning a tariff boundary may differ from the invoice because the official page does not specify their attribution. Images use provider-reported tokens. Every scan reprices stored requests from the current configuration, so correcting a price version also corrects earlier totals; a request that no entry covered is priced once an entry covers its settlement date.
363
363
 
364
364
  On first interactive launch, the client creates `~/.config/dsht/prices.json` (or `$XDG_CONFIG_HOME/dsht/prices.json`). `DSHT_CONFIG_DIR` overrides that directory. The JSON array contains price versions with `id`, `provider`, `model`, `currency: "CNY"`, `source`, inclusive `from`, optional exclusive `until`, `timezone`, weekday numbers (`0` Sunday), minute-of-day `windows`, and `peak`/`offPeak` rates named `input`, `cacheRead`, `cacheWrite`, `output`, per million tokens. To update prices, close the old interval with `until` and append a new version with a unique ID and matching `from`; overlapping intervals are rejected. Restart to load configuration changes. Price discovery is manual; the TUI does not scrape prices during startup.
365
365
 
@@ -377,7 +377,7 @@ This repository publishes one public package, `@itookit/dsht`, from the `mushuan
377
377
 
378
378
  | Field | Value |
379
379
  | --- | --- |
380
- | Name and version | `@itookit/dsht` `0.2.0` |
380
+ | Name and version | `@itookit/dsht` `0.2.1` |
381
381
  | Executable | `dsht`, or `npx @itookit/dsht` without installing |
382
382
  | Library entries | `@itookit/dsht` and `@itookit/dsht/auth` |
383
383
  | Author | lizlok@gmail.com |
@@ -399,7 +399,7 @@ npm publish --access public
399
399
 
400
400
  `publishConfig.access` is `public`, which a scoped package needs to be installable without a paid plan; the flag is therefore part of the package rather than of the publish command. An account with two-factor authentication publishes with a live code, `npm publish --otp=<code>`; the code is checked at the final request, after the typecheck, suite, and build have already run.
401
401
 
402
- Later releases run in `.github/workflows/publish.yml`, which publishes from a version tag with [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC) and provenance, so no publish token is stored. Configure it once at `npmjs.com` → `@itookit/dsht` → Settings → Trusted Publisher → GitHub Actions with organization or user `mushuanli`, repository `dsht`, workflow filename `publish.yml`, and allowed action `npm publish`. Trusted publishing cannot create a package, so the first version is published by hand; after that, `npm version 0.2.1 && git push --follow-tags` releases.
402
+ Later releases run in `.github/workflows/publish.yml`, which publishes from a version tag with [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC) and provenance, so no publish token is stored. Configure it once at `npmjs.com` → `@itookit/dsht` → Settings → Trusted Publisher → GitHub Actions with organization or user `mushuanli`, repository `dsht`, workflow filename `publish.yml`, and allowed action `npm publish`. Trusted publishing cannot create a package, so the earliest versions were published by hand; a later release pushes the matching tag, for example `npm version 0.2.2 && git push --follow-tags`.
403
403
 
404
404
  The workflow packs without publishing when started manually, and refuses a tag that disagrees with `package.json`. See the official [scoped publishing guide](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/) and [npx documentation](https://docs.npmjs.com/cli/npm-exec/). Registry publication is not part of the local validation performed for this repository.
405
405
 
package/README.zh.md CHANGED
@@ -359,7 +359,7 @@ Slash 命令在选择器和对话输入框中均可使用。输入 `/` 会显示
359
359
 
360
360
  内置人民币价格于 2026-09-10 根据[官方价格页](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/)核对。北京时间工作日 09:00–12:00、14:00–18:00 为高峰,其余时段半价。Flash 高峰未命中输入/缓存命中输入/输出为每百万 token ¥2/¥0.04/¥8,Pro 为 ¥9/¥0.30/¥27;当前模型名为 `deepseek-flash`,旧 Flash 名称沿用同一费率。供应方已公告自北京时间 2026-09-14 12:00 起将 `deepseek-v4-pro` 交由 Flash 服务并按 Flash 价格计费,内置条目已记录该变更,避免此后高估 Pro 用量。单列的缓存写入按未命中输入价计算。配置中的精确模型价格优先;否则 `deepseek-official` 模型名包含 `pro`(不区分大小写)时按 Pro 计价,其余名称包括临时别名均按 Flash 计价。其他供应商需要显式配置。
361
361
 
362
- 默认价格有效期从核对日期的北京时间零点开始,这是本地估算规则,不代表官方价格生效日期。更早用量需要补充历史价格版本。程序按助手请求结算记录的时间选择单价;官方未说明跨时段请求的归属,因此边界附近的估算可能与账单不同。图片使用供应商报告的 token 数。已计价请求保留原价格版本,不随配置修改重新套价;未计价请求可以在后续扫描时补算。
362
+ 默认价格有效期从核对日期的北京时间零点开始,这是本地估算规则,不代表官方价格生效日期。更早用量需要补充历史价格版本。程序按助手请求结算记录的时间选择单价;官方未说明跨时段请求的归属,因此边界附近的估算可能与账单不同。图片使用供应商报告的 token 数。每次扫描都按当前配置重新计算已存请求,因此修正价格版本会一并修正此前的小计;此前没有任何条目覆盖的请求,会在条目覆盖其结算日期后被计价。
363
363
 
364
364
  首次交互启动会创建 `~/.config/dsht/prices.json`(或 `$XDG_CONFIG_HOME/dsht/prices.json`),可用 `DSHT_CONFIG_DIR` 覆盖目录。JSON 数组中的价格版本包含 `id`、`provider`、`model`、`currency: "CNY"`、`source`、包含起点的 `from`、可选且不含终点的 `until`、`timezone`、星期数字 `weekdays`(`0` 为周日)、日内分钟区间 `windows`,以及 `peak`/`offPeak` 下每百万 token 的 `input`、`cacheRead`、`cacheWrite`、`output` 单价。调价时用 `until` 结束旧区间,再添加唯一 ID 且 `from` 衔接的新版本;程序拒绝重叠区间。重启后读取配置修改;价格由用户维护,启动时不抓取网页价格。
365
365
 
@@ -377,7 +377,7 @@ Slash 命令在选择器和对话输入框中均可使用。输入 `/` 会显示
377
377
 
378
378
  | 字段 | 值 |
379
379
  | --- | --- |
380
- | 名称与版本 | `@itookit/dsht` `0.2.0` |
380
+ | 名称与版本 | `@itookit/dsht` `0.2.1` |
381
381
  | 可执行命令 | `dsht`,不安装时用 `npx @itookit/dsht` |
382
382
  | 库入口 | `@itookit/dsht` 和 `@itookit/dsht/auth` |
383
383
  | 作者 | lizlok\@gmail.com |
@@ -399,7 +399,7 @@ npm publish --access public
399
399
 
400
400
  `publishConfig.access` 为 `public`;scoped 包需要它才能被公开安装,因此该设置放在包里而不是每次发布命令上。启用两步验证的账号需用即时验证码发布:`npm publish --otp=<验证码>`;验证码在最后一次请求时校验,此时类型检查、测试和构建均已执行完毕。
401
401
 
402
- 后续版本由 `.github/workflows/publish.yml` 发布:它以版本 tag 触发,使用 [trusted publishing](https://docs.npmjs.com/trusted-publishers)(OIDC)并生成 provenance,不保存任何发布 token。需在 `npmjs.com` → `@itookit/dsht` → Settings → Trusted Publisher → GitHub Actions 一次性配置:组织或用户 `mushuanli`、仓库 `dsht`、工作流文件名 `publish.yml`、允许动作 `npm publish`。Trusted publishing 无法创建包,因此首个版本需手工发布;之后执行 `npm version 0.2.1 && git push --follow-tags` 即可发布。
402
+ 后续版本由 `.github/workflows/publish.yml` 发布:它以版本 tag 触发,使用 [trusted publishing](https://docs.npmjs.com/trusted-publishers)(OIDC)并生成 provenance,不保存任何发布 token。需在 `npmjs.com` → `@itookit/dsht` → Settings → Trusted Publisher → GitHub Actions 一次性配置:组织或用户 `mushuanli`、仓库 `dsht`、工作流文件名 `publish.yml`、允许动作 `npm publish`。Trusted publishing 无法创建包,因此最早的版本需手工发布;之后的版本推送对应 tag 即可发布,例如 `npm version 0.2.2 && git push --follow-tags`。
403
403
 
404
404
  手动触发时该工作流只打包不发布,并拒绝与 `package.json` 不一致的 tag。参见官方 [scoped 发布指南](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/)和 [npx 文档](https://docs.npmjs.com/cli/npm-exec/)。Registry 发布不属于本仓库已执行的本地验证。
405
405
 
package/dist/cost.js CHANGED
@@ -196,7 +196,6 @@ export class CostLedger {
196
196
  async replace(sessionId, cut, events) {
197
197
  if ((this.sessions.get(sessionId)?.cut ?? -2) > cut)
198
198
  return;
199
- const old = new Map(this.sessions.get(sessionId)?.charges.map(c => [c.key, c]));
200
199
  const charges = [];
201
200
  const inheritedCut = Math.max(-1, ...events.filter(e => e.type === 'session/end-seed' && object(e.data).inherited === true).map(e => Number(e.seq)));
202
201
  let route = {};
@@ -227,15 +226,9 @@ export class CostLedger {
227
226
  const key = charges[index]?.key ?? String(e.seq);
228
227
  if (!usage && charges[index]?.usage)
229
228
  continue;
230
- const previous = old.get(key);
231
- if (previous?.amount !== undefined && previous.time === time && previous.provider === provider && previous.model === model
232
- && usage && previous.usage && Object.keys(usage).every(k => usage[k] === previous.usage[k])) {
233
- charges[index] = previous;
234
- last = { turn: d.turn, step: d.step, index };
235
- continue;
236
- }
237
- const reusable = previous?.price && previous.provider === provider && previous.model === model ? [previous.price] : this.prices;
238
- const selected = time === undefined ? lowestPrice(reusable, provider, model) : priceAt(reusable, provider, model, time);
229
+ // Every scan reprices from the current configuration, so correcting prices.json updates
230
+ // stored totals instead of leaving the version an earlier scan happened to apply.
231
+ const selected = time === undefined ? lowestPrice(this.prices, provider, model) : priceAt(this.prices, provider, model, time);
239
232
  const estimate = usage && selected ? (usage.input * selected.rates.input + usage.output * selected.rates.output + usage.cacheRead * selected.rates.cacheRead + usage.cacheWrite * selected.rates.cacheWrite) / 1e6 : undefined;
240
233
  const amount = estimate !== undefined && Number.isFinite(estimate) ? estimate : undefined;
241
234
  charges[index] = { key, time, provider, model, usage, price: selected?.price, amount,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itookit/dsht",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Remote-first TUI for DeepSeek Harness with SSH-friendly mobile access and request-level cost tracking",
6
6
  "engines": {