@linxin666/dsh-usage 0.4.5 → 0.4.6

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The Whale-yuan voucher (鲸元券): the DeepSeek official family's retained
3
- * ledger totals stamped onto the banknote artwork as a denomination, ready
2
+ * The Whale-yuan voucher (鲸元券): the mint family's retained ledger totals
3
+ * stamped onto the banknote artwork as a denomination, ready
4
4
  * to save or share. The canvas copy is deliberately locale-neutral (digits,
5
5
  * latin captions, ISO dates) so the exported image needs no dictionary;
6
6
  * everything user-facing around it lives in the section's locales. The pure
@@ -11,11 +11,11 @@
11
11
  import type { UsageWindowSummary } from '../core/types.ts';
12
12
  /** The facts stamped onto one voucher. */
13
13
  export interface VoucherData {
14
- /** DeepSeek official family total tokens over the retained window. */
14
+ /** Mint family (DeepSeek official + MiMo) total tokens over the retained window. */
15
15
  tokens: number;
16
16
  /** Provider calls that reported usage. */
17
17
  calls: number;
18
- /** Fold-time spend estimate in CNY (the only priced family). */
18
+ /** Fold-time spend estimate in CNY; only the priced family contributes. */
19
19
  cost: number;
20
20
  /** Retained window bounds (local date keys, inclusive). */
21
21
  from: string;
@@ -28,12 +28,30 @@ export declare function faceValue(tokens: number): number;
28
28
  /** Local calendar day (`YYYY-MM-DD`) for an epoch ms timestamp. */
29
29
  export declare function formatDay(ms: number): string;
30
30
  /**
31
- * Sum the DeepSeek official family rows out of a usage window (both the
32
- * `deepseek` catalog alias and the live `deepseek-official` route fold into
33
- * one voucher). Undefined when the window is absent (older host) or the
34
- * family has no usage — a zero-token note mints nothing.
31
+ * Provider route ids minted beside the DeepSeek official family: the MiMo
32
+ * gateway, which a profile may run as its default route and which the ledger
33
+ * records under its own route id. The bank counts the tokens a profile spends,
34
+ * not only the ones DeepSeek bills. Route ids rather than adapter families
35
+ * because minting is an accounting decision that must never widen the
36
+ * credential or probing paths — the same split `isDeepSeekProviderRoute()`
37
+ * keeps against `adapterFor()` (issue #1772). An empty list mints exactly the
38
+ * official family, which is how a profile that never runs MiMo behaves.
35
39
  */
36
- export declare function deepseekVoucherData(window: UsageWindowSummary | undefined): VoucherData | undefined;
40
+ export declare const EXTRA_MINT_ROUTE_IDS: readonly string[];
41
+ /** Whether one provider route's ledger rows mint whale yuan. */
42
+ export declare function mintsWhaleYuan(provider: string): boolean;
43
+ /**
44
+ * Sum the mint family's rows out of a usage window: the whole DeepSeek
45
+ * official family (the `deepseek` catalog alias, the live `deepseek-official`
46
+ * route and the signed-in `deepseek-account` route all fold into one voucher)
47
+ * plus {@link EXTRA_MINT_ROUTE_IDS}. Undefined when the window is absent
48
+ * (older host) or the family has no usage — a zero-token note mints nothing.
49
+ *
50
+ * Only the priced family contributes `cost`: MiMo ships no price book, so it
51
+ * mints tokens and calls while the spend line keeps reporting the official
52
+ * family's fold-time estimate (and the observed-balance watch above it).
53
+ */
54
+ export declare function voucherData(window: UsageWindowSummary | undefined): VoucherData | undefined;
37
55
  /** Banknote denomination: full digits with thousands separators. */
38
56
  export declare function formatDenomination(value: number): string;
39
57
  /** Deterministic serial number flavor: the face value mod 1e9, zero-padded. */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@linxin666/dsh-usage",
3
3
  "description": "Usage statistics plugin for the dsh web GUI: per-provider balance and coding-plan quota detection plus a live token usage ledger, with a compact price glance card above the sidebar's Settings row",
4
- "version": "0.4.5",
4
+ "version": "0.4.6",
5
5
  "icon": "icon.svg",
6
6
  "type": "module",
7
7
  "engines": {
@@ -87,7 +87,7 @@
87
87
  "url": "https://github.com/zhu1090093659/dsh-web.git"
88
88
  },
89
89
  "scripts": {
90
- "build": "tsc -p tsconfig.build.json && tsdown",
90
+ "build": "tsc -b tsconfig.build.json && tsdown",
91
91
  "watch": "tsdown --watch",
92
92
  "test": "vitest run",
93
93
  "typecheck": "tsc --noEmit && tsc -p tsconfig.test.json --pretty false"
@@ -15,7 +15,7 @@ import { t } from './locales.ts'
15
15
  import styles from './usage.module.css'
16
16
  import { isDeepSeekProviderRoute } from '../core/adapters.ts'
17
17
  import { deepseekPeriodAt } from '../core/pricing.ts'
18
- import { deepseekVoucherData, drawVoucher, faceValue, formatDay, formatDenomination, loadVoucherArt } from './voucher.ts'
18
+ import { voucherData, drawVoucher, faceValue, formatDay, formatDenomination, loadVoucherArt } from './voucher.ts'
19
19
  import type { ObservedSpendView, ProviderSnapshotView, UsageDayView, UsageOverviewView, UsageProviderSummary, UsageTokenTotals, UsageWindowSummary } from '../core/types.ts'
20
20
 
21
21
  /** The settings fields this section edits (immediate-apply semantics). */
@@ -550,18 +550,18 @@ function totalOf(totals: UsageTokenTotals): number {
550
550
  }
551
551
 
552
552
  /**
553
- * The Token 银行 card: the DeepSeek official family's retained-ledger usage
554
- * minted onto the whale-yuan note at 1,000,000 tokens per whale yuan. The
555
- * window is the whole retained ledger by default (the host's aggregate,
556
- * falling back to the 30-day trend when an older host serves no `all`) or the
557
- * single day the user picked; the spend line prefers the official balance
558
- * watch (whole window only) and falls back to the fold-time estimate; the
559
- * artwork draw failure degrades to an error line and never takes the section
560
- * down.
553
+ * The Token 银行 card: the mint family's (DeepSeek official + MiMo)
554
+ * retained-ledger usage minted onto the whale-yuan note at 1,000,000 tokens
555
+ * per whale yuan. The window is the whole retained ledger by default (the
556
+ * host's aggregate, falling back to the 30-day trend when an older host serves
557
+ * no `all`) or the single day the user picked; the spend line prefers the
558
+ * official balance watch (whole window only) and falls back to the fold-time
559
+ * estimate, which only the priced family feeds; the artwork draw failure
560
+ * degrades to an error line and never takes the section down.
561
561
  */
562
562
  function VoucherCard(props: { window?: UsageWindowSummary; observedSpend?: ObservedSpendView; loading?: boolean; error?: string }): ReactNode {
563
563
  const { window: ledger, observedSpend, loading, error } = props
564
- const data = deepseekVoucherData(ledger)
564
+ const data = voucherData(ledger)
565
565
  const canvasRef = useRef<HTMLCanvasElement | null>(null)
566
566
  const [drawError, setDrawError] = useState<string | undefined>(undefined)
567
567
  const dataKey = data === undefined ? '' : `${data.from}|${data.to}|${data.tokens}|${data.calls}|${data.cost}`
@@ -57,8 +57,8 @@ export const zh = {
57
57
  'usage.config.pollIntervalSec': '轮询间隔(秒)',
58
58
  'usage.config.saveFailed': '保存失败:设置未被接受。',
59
59
  'usage.bank.title': '鲸元券',
60
- 'usage.bank.hint': '官方 API 每消耗 100 万 tokens 铸造 1 鲸元;保存或分享这张票券。',
61
- 'usage.bank.noUsage': '暂无 DeepSeek 官方用量数据(统计自插件启用起)',
60
+ 'usage.bank.hint': 'DeepSeek 官方 API 与 MiMo 每消耗 100 万 tokens 铸造 1 鲸元;保存或分享这张票券。',
61
+ 'usage.bank.noUsage': '暂无 DeepSeek 官方 / MiMo 用量数据(统计自插件启用起)',
62
62
  'usage.bank.minted': '累计铸造 {minted} 鲸元({tokens} tokens)',
63
63
  'usage.bank.spend.observed': '官方余额实测花费 ¥{cost}(自 {since} 起)',
64
64
  'usage.bank.spend.estimated': '消费估算:约 ¥{cost}',
@@ -124,8 +124,8 @@ export const en: Record<UsageKey, string> = {
124
124
  'usage.config.pollIntervalSec': 'Poll interval (seconds)',
125
125
  'usage.config.saveFailed': 'Save failed: the deployment did not accept the setting.',
126
126
  'usage.bank.title': 'Whale-yuan voucher',
127
- 'usage.bank.hint': 'Every 1,000,000 tokens spent on the official API mint one whale yuan; save or share the note.',
128
- 'usage.bank.noUsage': 'No official DeepSeek usage yet (counting starts when the plugin is enabled)',
127
+ 'usage.bank.hint': 'Every 1,000,000 tokens spent on the DeepSeek official API or on MiMo mint one whale yuan; save or share the note.',
128
+ 'usage.bank.noUsage': 'No DeepSeek official or MiMo usage yet (counting starts when the plugin is enabled)',
129
129
  'usage.bank.minted': 'Minted {minted} whale yuan ({tokens} tokens)',
130
130
  'usage.bank.spend.observed': 'Spent ¥{cost} observed on the official balance (watching since {since})',
131
131
  'usage.bank.spend.estimated': 'Estimated spend: about ¥{cost}',
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The Whale-yuan voucher (鲸元券): the DeepSeek official family's retained
3
- * ledger totals stamped onto the banknote artwork as a denomination, ready
2
+ * The Whale-yuan voucher (鲸元券): the mint family's retained ledger totals
3
+ * stamped onto the banknote artwork as a denomination, ready
4
4
  * to save or share. The canvas copy is deliberately locale-neutral (digits,
5
5
  * latin captions, ISO dates) so the exported image needs no dictionary;
6
6
  * everything user-facing around it lives in the section's locales. The pure
@@ -16,11 +16,11 @@ import { VOUCHER_ART_DATA_URL } from './voucher-art.generated.ts'
16
16
 
17
17
  /** The facts stamped onto one voucher. */
18
18
  export interface VoucherData {
19
- /** DeepSeek official family total tokens over the retained window. */
19
+ /** Mint family (DeepSeek official + MiMo) total tokens over the retained window. */
20
20
  tokens: number
21
21
  /** Provider calls that reported usage. */
22
22
  calls: number
23
- /** Fold-time spend estimate in CNY (the only priced family). */
23
+ /** Fold-time spend estimate in CNY; only the priced family contributes. */
24
24
  cost: number
25
25
  /** Retained window bounds (local date keys, inclusive). */
26
26
  from: string
@@ -44,21 +44,43 @@ export function formatDay(ms: number): string {
44
44
  }
45
45
 
46
46
  /**
47
- * Sum the DeepSeek official family rows out of a usage window (both the
48
- * `deepseek` catalog alias and the live `deepseek-official` route fold into
49
- * one voucher). Undefined when the window is absent (older host) or the
50
- * family has no usage — a zero-token note mints nothing.
47
+ * Provider route ids minted beside the DeepSeek official family: the MiMo
48
+ * gateway, which a profile may run as its default route and which the ledger
49
+ * records under its own route id. The bank counts the tokens a profile spends,
50
+ * not only the ones DeepSeek bills. Route ids rather than adapter families
51
+ * because minting is an accounting decision that must never widen the
52
+ * credential or probing paths — the same split `isDeepSeekProviderRoute()`
53
+ * keeps against `adapterFor()` (issue #1772). An empty list mints exactly the
54
+ * official family, which is how a profile that never runs MiMo behaves.
51
55
  */
52
- export function deepseekVoucherData(window: UsageWindowSummary | undefined): VoucherData | undefined {
56
+ export const EXTRA_MINT_ROUTE_IDS: readonly string[] = ['mimo']
57
+
58
+ /** Whether one provider route's ledger rows mint whale yuan. */
59
+ export function mintsWhaleYuan(provider: string): boolean {
60
+ return isDeepSeekProviderRoute(provider) || EXTRA_MINT_ROUTE_IDS.includes(provider)
61
+ }
62
+
63
+ /**
64
+ * Sum the mint family's rows out of a usage window: the whole DeepSeek
65
+ * official family (the `deepseek` catalog alias, the live `deepseek-official`
66
+ * route and the signed-in `deepseek-account` route all fold into one voucher)
67
+ * plus {@link EXTRA_MINT_ROUTE_IDS}. Undefined when the window is absent
68
+ * (older host) or the family has no usage — a zero-token note mints nothing.
69
+ *
70
+ * Only the priced family contributes `cost`: MiMo ships no price book, so it
71
+ * mints tokens and calls while the spend line keeps reporting the official
72
+ * family's fold-time estimate (and the observed-balance watch above it).
73
+ */
74
+ export function voucherData(window: UsageWindowSummary | undefined): VoucherData | undefined {
53
75
  if (window === undefined) return undefined
54
76
  let tokens = 0
55
77
  let calls = 0
56
78
  let cost = 0
57
79
  for (const row of window.providers) {
58
- if (!isDeepSeekProviderRoute(row.provider)) continue
80
+ if (!mintsWhaleYuan(row.provider)) continue
59
81
  tokens += totalTokens(row.totals)
60
82
  calls += row.totals.calls
61
- cost += row.totals.cost
83
+ if (isDeepSeekProviderRoute(row.provider)) cost += row.totals.cost
62
84
  }
63
85
  if (tokens <= 0) return undefined
64
86
  return { tokens, calls, cost, from: window.from, to: window.to }