@tzyc/dsh-model-visibility 1.10.3 → 1.12.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.
@@ -1,11 +1,9 @@
1
1
  /**
2
- * Token-usage strip with the one-click exports.
2
+ * Token-usage strip with the two CSV exports.
3
3
  *
4
- * The strip renders the ledger's today/week/month/total buckets and links the
5
- * two CSV endpoints. It is an inner piece of the settings section: the section
6
- * supplies the translator and the usage store instance.
7
- *
8
- * @module client-src/usage-view
4
+ * One line, four numbers, two icon-sized buttons: the strip is context, not
5
+ * the point of the page, so it must not push the model list down. Exact
6
+ * numbers live in the tooltip; the visible figure is the total.
9
7
  */
10
8
 
11
9
  const React = require('react')
@@ -15,15 +13,22 @@ import { API } from './constants.mjs'
15
13
  import { formatTokens } from './pure.mjs'
16
14
  import { useSource } from './hooks.mjs'
17
15
 
18
- /** Render one [in, out] window as "输入 x · 输出 y". */
19
- function rangeText(range, t) {
20
- if (!Array.isArray(range) || range.every((value) => value === 0)) return t('usage.none')
16
+ /** Total of one bucket tuple (input + output + cache read + cache write). */
17
+ function totalOf(range) {
18
+ if (!Array.isArray(range)) return 0
19
+ return range.reduce((sum, value) => sum + (Number.isFinite(value) ? value : 0), 0)
20
+ }
21
+
22
+ /** Detail line for one window: input / output / cache split. */
23
+ function detailOf(range, t) {
24
+ if (!Array.isArray(range) || totalOf(range) === 0) return t('usage.none')
21
25
  const input = (range[0] ?? 0) + (range[2] ?? 0) + (range[3] ?? 0)
22
26
  const output = range[1] ?? 0
23
- return t('usage.range', {
27
+ return t('usage.detail', {
24
28
  input: formatTokens(input),
25
29
  output: formatTokens(output),
26
- total: formatTokens(input + output),
30
+ cacheRead: formatTokens(range[2] ?? 0),
31
+ cacheWrite: formatTokens(range[3] ?? 0),
27
32
  })
28
33
  }
29
34
 
@@ -32,6 +37,7 @@ function download(href) {
32
37
  const anchor = document.createElement('a')
33
38
  anchor.href = href
34
39
  anchor.rel = 'noopener'
40
+ anchor.download = ''
35
41
  document.body.appendChild(anchor)
36
42
  anchor.click()
37
43
  anchor.remove()
@@ -42,71 +48,69 @@ export function UsageToolbar({ usage, t, features }) {
42
48
  const supported = features.length === 0 || features.includes('usage')
43
49
  const ranges = state.snapshot?.ranges
44
50
  const computing = state.snapshot?.computing === true
51
+
52
+ if (!supported) {
53
+ return h('div', { className: 'mvp_usage mvp_usage--off' }, t('usage.hostStale'))
54
+ }
55
+
56
+ const windows = [
57
+ ['today', 'usage.today', 'usage.todayTitle'],
58
+ ['week', 'usage.week', 'usage.weekTitle'],
59
+ ['month', 'usage.month', 'usage.monthTitle'],
60
+ ['total', 'usage.total', 'usage.totalTitle'],
61
+ ]
62
+
45
63
  return h(
46
64
  'div',
47
- { className: 'mvp_usage' + (supported ? '' : ' mvp_usage--off') },
65
+ { className: 'mvp_usage' },
48
66
  h(
49
- 'div',
50
- { className: 'mvp_usageHead' },
51
- h('span', { className: 'mvp_usageTitle' }, t('usage.title')),
67
+ 'span',
68
+ { className: 'mvp_usageLabel' },
69
+ t('usage.title'),
52
70
  computing ? h('span', { className: 'mvp_usageComputing' }, t('usage.computing')) : null,
53
- h(
54
- 'span',
55
- { className: 'mvp_usageActions' },
56
- h(
57
- 'button',
58
- {
59
- type: 'button',
60
- className: 'mvp_button',
61
- title: t('usage.exportUsageTitle'),
62
- onClick: () => download(`${API}/export?type=usage`),
63
- },
64
- t('usage.exportUsage'),
65
- ),
71
+ ),
72
+ h(
73
+ 'span',
74
+ { className: 'mvp_usageRanges' },
75
+ windows.map(([key, labelKey, titleKey]) =>
66
76
  h(
67
- 'button',
77
+ 'span',
68
78
  {
69
- type: 'button',
70
- className: 'mvp_button',
71
- title: t('usage.exportModelsTitle'),
72
- onClick: () => download(`${API}/export?type=models`),
79
+ key,
80
+ className: 'mvp_stat' + (key === 'total' ? ' mvp_stat--total' : ''),
81
+ title: t(titleKey) + '\n' + detailOf(ranges?.[key], t),
73
82
  },
74
- t('usage.exportModels'),
83
+ h('span', { className: 'mvp_statLabel' }, t(labelKey)),
84
+ h('span', { className: 'mvp_statValue' }, formatTokens(totalOf(ranges?.[key]))),
75
85
  ),
76
86
  ),
77
87
  ),
78
- supported
79
- ? h(
80
- 'div',
81
- { className: 'mvp_usageRanges' },
82
- h(
83
- 'span',
84
- { className: 'mvp_stat', title: t('usage.todayTitle') },
85
- h('span', { className: 'mvp_statLabel' }, t('usage.today')),
86
- h('span', { className: 'mvp_statValue' }, rangeText(ranges?.today, t)),
87
- ),
88
- h(
89
- 'span',
90
- { className: 'mvp_stat', title: t('usage.weekTitle') },
91
- h('span', { className: 'mvp_statLabel' }, t('usage.week')),
92
- h('span', { className: 'mvp_statValue' }, rangeText(ranges?.week, t)),
93
- ),
94
- h(
95
- 'span',
96
- { className: 'mvp_stat', title: t('usage.monthTitle') },
97
- h('span', { className: 'mvp_statLabel' }, t('usage.month')),
98
- h('span', { className: 'mvp_statValue' }, rangeText(ranges?.month, t)),
99
- ),
100
- h(
101
- 'span',
102
- { className: 'mvp_stat mvp_stat--total', title: t('usage.totalTitle') },
103
- h('span', { className: 'mvp_statLabel' }, t('usage.total')),
104
- h('span', { className: 'mvp_statValue' }, rangeText(ranges?.total, t)),
105
- ),
106
- )
107
- : h('div', { className: 'mvp_usageHint' }, t('usage.hostStale')),
88
+ h(
89
+ 'span',
90
+ { className: 'mvp_usageActions' },
91
+ h(
92
+ 'button',
93
+ {
94
+ type: 'button',
95
+ className: 'mvp_button mvp_button--quiet',
96
+ title: t('usage.exportUsageTitle'),
97
+ onClick: () => download(`${API}/export?type=usage`),
98
+ },
99
+ t('usage.exportUsage'),
100
+ ),
101
+ h(
102
+ 'button',
103
+ {
104
+ type: 'button',
105
+ className: 'mvp_button mvp_button--quiet',
106
+ title: t('usage.exportModelsTitle'),
107
+ onClick: () => download(`${API}/export?type=models`),
108
+ },
109
+ t('usage.exportModels'),
110
+ ),
111
+ ),
108
112
  state.error !== null
109
- ? h('div', { className: 'mvp_usageHint mvp_usageHint--warn' }, state.error)
113
+ ? h('span', { className: 'mvp_usageHint mvp_usageHint--warn' }, state.error)
110
114
  : null,
111
115
  )
112
116
  }