@tzyc/dsh-model-visibility 1.10.1 → 1.10.3
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.md +1 -1
- package/client-src/catalog-store.mjs +5 -2
- package/client.js +110 -50
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](package.json)
|
|
11
11
|
[](test)
|
|
12
|
-
[](https://github.com/TZYCeng/dsh-model-visibility/releases)
|
|
13
13
|
[](https://awesome-dsh-plugin.com/p/TZYCeng/dsh-model-visibility/)
|
|
14
14
|
|
|
15
15
|
</div>
|
|
@@ -85,7 +85,10 @@ export function createCatalog(ctx) {
|
|
|
85
85
|
groups: Array.isArray(value.groups) ? value.groups : [],
|
|
86
86
|
failures: Array.isArray(value.failures) ? value.failures : [],
|
|
87
87
|
providers: Array.isArray(value.providers) ? value.providers : [],
|
|
88
|
-
|
|
88
|
+
// The section reads `state.learned` (the learned-snapshot meta with
|
|
89
|
+
// its feature flags); this store is its only source, so the field
|
|
90
|
+
// name must stay in lock-step with lib/model-info.js's response.
|
|
91
|
+
learned: value.learned && typeof value.learned === 'object' ? value.learned : null,
|
|
89
92
|
error: null,
|
|
90
93
|
detailsError: null,
|
|
91
94
|
source: 'host',
|
|
@@ -102,7 +105,7 @@ export function createCatalog(ctx) {
|
|
|
102
105
|
groups: value.groups,
|
|
103
106
|
failures: value.failures,
|
|
104
107
|
providers: [],
|
|
105
|
-
|
|
108
|
+
learned: null,
|
|
106
109
|
error: null,
|
|
107
110
|
detailsError: detail,
|
|
108
111
|
source: 'catalog',
|
package/client.js
CHANGED
|
@@ -26,7 +26,7 @@ window.__ModuleLoader__.load({
|
|
|
26
26
|
define("catalog-store", function (require, module, exports) {
|
|
27
27
|
const { API } = require("constants")
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
function createCatalog(ctx) {
|
|
30
30
|
const listeners = new Set()
|
|
31
31
|
let state = {
|
|
32
32
|
status: 'idle',
|
|
@@ -111,7 +111,10 @@ window.__ModuleLoader__.load({
|
|
|
111
111
|
groups: Array.isArray(value.groups) ? value.groups : [],
|
|
112
112
|
failures: Array.isArray(value.failures) ? value.failures : [],
|
|
113
113
|
providers: Array.isArray(value.providers) ? value.providers : [],
|
|
114
|
-
|
|
114
|
+
// The section reads `state.learned` (the learned-snapshot meta with
|
|
115
|
+
// its feature flags); this store is its only source, so the field
|
|
116
|
+
// name must stay in lock-step with lib/model-info.js's response.
|
|
117
|
+
learned: value.learned && typeof value.learned === 'object' ? value.learned : null,
|
|
115
118
|
error: null,
|
|
116
119
|
detailsError: null,
|
|
117
120
|
source: 'host',
|
|
@@ -128,7 +131,7 @@ window.__ModuleLoader__.load({
|
|
|
128
131
|
groups: value.groups,
|
|
129
132
|
failures: value.failures,
|
|
130
133
|
providers: [],
|
|
131
|
-
|
|
134
|
+
learned: null,
|
|
132
135
|
error: null,
|
|
133
136
|
detailsError: detail,
|
|
134
137
|
source: 'catalog',
|
|
@@ -178,7 +181,7 @@ window.__ModuleLoader__.load({
|
|
|
178
181
|
* answers 404 and the editor stays hidden behind the `overrides` feature
|
|
179
182
|
* flag.
|
|
180
183
|
*/
|
|
181
|
-
|
|
184
|
+
function createOverrides() {
|
|
182
185
|
const listeners = new Set()
|
|
183
186
|
let state = { status: 'idle', entries: [], available: null, error: null }
|
|
184
187
|
let inflight = null
|
|
@@ -304,7 +307,7 @@ window.__ModuleLoader__.load({
|
|
|
304
307
|
* so the client only polls and prints. An older Host answers 404 and the
|
|
305
308
|
* strip renders its "host is stale" hint.
|
|
306
309
|
*/
|
|
307
|
-
|
|
310
|
+
function createUsageApi() {
|
|
308
311
|
const listeners = new Set()
|
|
309
312
|
let state = { status: 'idle', snapshot: null, error: null }
|
|
310
313
|
let inflight = null
|
|
@@ -382,7 +385,7 @@ window.__ModuleLoader__.load({
|
|
|
382
385
|
* keeps the run in memory, so the store just mirrors its snapshots and keeps
|
|
383
386
|
* one 2 s poll alive while a sweep is running (or being observed).
|
|
384
387
|
*/
|
|
385
|
-
|
|
388
|
+
function createVerifyApi() {
|
|
386
389
|
const listeners = new Set()
|
|
387
390
|
let state = { status: 'idle', snapshot: null, error: null }
|
|
388
391
|
let inflight = null
|
|
@@ -489,6 +492,11 @@ window.__ModuleLoader__.load({
|
|
|
489
492
|
}
|
|
490
493
|
}
|
|
491
494
|
|
|
495
|
+
|
|
496
|
+
exports.createCatalog = createCatalog
|
|
497
|
+
exports.createOverrides = createOverrides
|
|
498
|
+
exports.createUsageApi = createUsageApi
|
|
499
|
+
exports.createVerifyApi = createVerifyApi
|
|
492
500
|
})
|
|
493
501
|
|
|
494
502
|
// -------------------------------------------------------- checker-view
|
|
@@ -535,7 +543,7 @@ window.__ModuleLoader__.load({
|
|
|
535
543
|
}
|
|
536
544
|
}
|
|
537
545
|
|
|
538
|
-
|
|
546
|
+
function VerifyPanel({ verify, catalog, t, canUse }) {
|
|
539
547
|
const state = useSource(verify)
|
|
540
548
|
const [pick, setPick] = React.useState(readPick)
|
|
541
549
|
const [message, setMessage] = React.useState(null)
|
|
@@ -715,6 +723,8 @@ window.__ModuleLoader__.load({
|
|
|
715
723
|
)
|
|
716
724
|
}
|
|
717
725
|
|
|
726
|
+
|
|
727
|
+
exports.VerifyPanel = VerifyPanel
|
|
718
728
|
})
|
|
719
729
|
|
|
720
730
|
// -------------------------------------------------------- composer-filter
|
|
@@ -736,7 +746,7 @@ window.__ModuleLoader__.load({
|
|
|
736
746
|
* model stays listed even while hidden, because the shipped trigger
|
|
737
747
|
* resolves its label from this same catalog.
|
|
738
748
|
*/
|
|
739
|
-
|
|
749
|
+
function patchDirectoryStore(store, form) {
|
|
740
750
|
const readBase = store.getSnapshot.bind(store)
|
|
741
751
|
const subscribeBase = store.subscribe.bind(store)
|
|
742
752
|
const originalGet = store.getSnapshot
|
|
@@ -823,7 +833,7 @@ window.__ModuleLoader__.load({
|
|
|
823
833
|
* owning the trigger, the Model / Effort rows, and third-party menu
|
|
824
834
|
* enhancements such as the reasoning-effort slider.
|
|
825
835
|
*/
|
|
826
|
-
|
|
836
|
+
function installComposerFilter(scope, form) {
|
|
827
837
|
const models = scope.modelDirectories
|
|
828
838
|
const original = models.directoryFor
|
|
829
839
|
if (typeof original !== 'function') return
|
|
@@ -873,23 +883,26 @@ window.__ModuleLoader__.load({
|
|
|
873
883
|
|
|
874
884
|
/* ----------------------------------------------------- settings page */
|
|
875
885
|
|
|
886
|
+
|
|
887
|
+
exports.patchDirectoryStore = patchDirectoryStore
|
|
888
|
+
exports.installComposerFilter = installComposerFilter
|
|
876
889
|
})
|
|
877
890
|
|
|
878
891
|
// -------------------------------------------------------- constants
|
|
879
892
|
define("constants", function (require, module, exports) {
|
|
880
893
|
/** Dictionary namespace owned by this plugin. */
|
|
881
|
-
|
|
894
|
+
const NS = 'model-visibility'
|
|
882
895
|
/** Host entry id from cordis.patch.yml; also the settings namespace. */
|
|
883
|
-
|
|
896
|
+
const ENTRY = 'model-visibility'
|
|
884
897
|
/** Config field persisted by the Host settings document. */
|
|
885
|
-
|
|
898
|
+
const FIELD = 'hidden'
|
|
886
899
|
/** Settings section id. */
|
|
887
|
-
|
|
900
|
+
const SECTION_ID = 'model-visibility'
|
|
888
901
|
/**
|
|
889
902
|
* Same-origin route the Host half registers through `connection.fetch`.
|
|
890
903
|
* Resolved against the page base so a reverse-proxy prefix is preserved.
|
|
891
904
|
*/
|
|
892
|
-
|
|
905
|
+
const API = (() => {
|
|
893
906
|
if (typeof document === 'undefined') return '/api/dsh-model-visibility'
|
|
894
907
|
try {
|
|
895
908
|
return new URL('api/dsh-model-visibility', document.baseURI).pathname
|
|
@@ -898,11 +911,17 @@ window.__ModuleLoader__.load({
|
|
|
898
911
|
}
|
|
899
912
|
})()
|
|
900
913
|
|
|
914
|
+
|
|
915
|
+
exports.NS = NS
|
|
916
|
+
exports.ENTRY = ENTRY
|
|
917
|
+
exports.FIELD = FIELD
|
|
918
|
+
exports.SECTION_ID = SECTION_ID
|
|
919
|
+
exports.API = API
|
|
901
920
|
})
|
|
902
921
|
|
|
903
922
|
// -------------------------------------------------------- css
|
|
904
923
|
define("css", function (require, module, exports) {
|
|
905
|
-
|
|
924
|
+
const CSS = `
|
|
906
925
|
.mvp_page{box-sizing:border-box;width:100%;height:100%;min-height:0;flex-direction:column;display:flex;overflow-y:auto;padding-bottom:24px}
|
|
907
926
|
.mvp_head{flex:none;flex-direction:column;gap:6px;padding:4px 0 14px;display:flex}
|
|
908
927
|
.mvp_title{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;font-weight:500;line-height:24px}
|
|
@@ -1151,11 +1170,13 @@ window.__ModuleLoader__.load({
|
|
|
1151
1170
|
|
|
1152
1171
|
`
|
|
1153
1172
|
|
|
1173
|
+
|
|
1174
|
+
exports.CSS = CSS
|
|
1154
1175
|
})
|
|
1155
1176
|
|
|
1156
1177
|
// -------------------------------------------------------- dict
|
|
1157
1178
|
define("dict", function (require, module, exports) {
|
|
1158
|
-
|
|
1179
|
+
const DICT = {
|
|
1159
1180
|
zh: {
|
|
1160
1181
|
'nav': '模型显示',
|
|
1161
1182
|
'page.title': '模型显示',
|
|
@@ -1582,30 +1603,32 @@ window.__ModuleLoader__.load({
|
|
|
1582
1603
|
'provider.account': 'DeepSeek Account',
|
|
1583
1604
|
},
|
|
1584
1605
|
}
|
|
1606
|
+
|
|
1607
|
+
exports.DICT = DICT
|
|
1585
1608
|
})
|
|
1586
1609
|
|
|
1587
1610
|
// -------------------------------------------------------- format
|
|
1588
1611
|
define("format", function (require, module, exports) {
|
|
1589
1612
|
const { FIELD } = require("constants")
|
|
1590
1613
|
|
|
1591
|
-
|
|
1614
|
+
function keyOf(provider, model) {
|
|
1592
1615
|
return provider + '/' + model
|
|
1593
1616
|
}
|
|
1594
1617
|
|
|
1595
|
-
|
|
1618
|
+
function hiddenSetOf(snapshot) {
|
|
1596
1619
|
const value = snapshot && snapshot.value
|
|
1597
1620
|
const list = value && Array.isArray(value[FIELD]) ? value[FIELD] : []
|
|
1598
1621
|
return new Set(list)
|
|
1599
1622
|
}
|
|
1600
1623
|
|
|
1601
|
-
|
|
1624
|
+
function providerLabel(group, t) {
|
|
1602
1625
|
return group.id === 'deepseek-account' ? t('provider.account') : group.name
|
|
1603
1626
|
}
|
|
1604
1627
|
|
|
1605
|
-
|
|
1628
|
+
const COLLAPSE_KEY = 'dsh-model-visibility:collapsed-groups:v1'
|
|
1606
1629
|
|
|
1607
1630
|
/** Group ids whose model lists the page keeps collapsed. */
|
|
1608
|
-
|
|
1631
|
+
function readCollapsedGroups() {
|
|
1609
1632
|
try {
|
|
1610
1633
|
const raw = window.localStorage.getItem(COLLAPSE_KEY)
|
|
1611
1634
|
if (raw === null) return new Set()
|
|
@@ -1616,7 +1639,7 @@ window.__ModuleLoader__.load({
|
|
|
1616
1639
|
}
|
|
1617
1640
|
}
|
|
1618
1641
|
|
|
1619
|
-
|
|
1642
|
+
function persistCollapsedGroups(collapsed) {
|
|
1620
1643
|
try {
|
|
1621
1644
|
window.localStorage.setItem(COLLAPSE_KEY, JSON.stringify(Array.from(collapsed)))
|
|
1622
1645
|
} catch (_error) {
|
|
@@ -1625,14 +1648,14 @@ window.__ModuleLoader__.load({
|
|
|
1625
1648
|
}
|
|
1626
1649
|
}
|
|
1627
1650
|
|
|
1628
|
-
|
|
1651
|
+
function countModels(groups) {
|
|
1629
1652
|
let total = 0
|
|
1630
1653
|
for (const group of groups || []) total += (group.models || []).length
|
|
1631
1654
|
return total
|
|
1632
1655
|
}
|
|
1633
1656
|
|
|
1634
1657
|
/** Human context size: 1048576 → "1M", 128000 → "128K". */
|
|
1635
|
-
|
|
1658
|
+
function formatContext(tokens) {
|
|
1636
1659
|
if (!Number.isFinite(tokens) || tokens <= 0) return null
|
|
1637
1660
|
if (tokens >= 1_000_000) return Math.round(tokens / 100_000) / 10 + 'M'
|
|
1638
1661
|
if (tokens >= 1_000) return Math.round(tokens / 100) / 10 + 'K'
|
|
@@ -1640,7 +1663,7 @@ window.__ModuleLoader__.load({
|
|
|
1640
1663
|
}
|
|
1641
1664
|
|
|
1642
1665
|
/** Effort display names in catalog order. */
|
|
1643
|
-
|
|
1666
|
+
function effortNames(reasoning) {
|
|
1644
1667
|
const efforts = reasoning && Array.isArray(reasoning.efforts) ? reasoning.efforts : []
|
|
1645
1668
|
const names = []
|
|
1646
1669
|
for (const effort of efforts) {
|
|
@@ -1652,7 +1675,7 @@ window.__ModuleLoader__.load({
|
|
|
1652
1675
|
}
|
|
1653
1676
|
|
|
1654
1677
|
/** Display name of the default effort, or null when none is published. */
|
|
1655
|
-
|
|
1678
|
+
function defaultEffortName(reasoning) {
|
|
1656
1679
|
if (!reasoning || typeof reasoning.defaultEffort !== 'string') return null
|
|
1657
1680
|
const efforts = Array.isArray(reasoning.efforts) ? reasoning.efforts : []
|
|
1658
1681
|
const found = efforts.find((effort) => effort !== null && effort.id === reasoning.defaultEffort)
|
|
@@ -1662,85 +1685,110 @@ window.__ModuleLoader__.load({
|
|
|
1662
1685
|
}
|
|
1663
1686
|
|
|
1664
1687
|
/** Localized name of one input modality. */
|
|
1665
|
-
|
|
1688
|
+
function modalityLabel(id, t) {
|
|
1666
1689
|
const key = 'modality.' + id
|
|
1667
1690
|
const label = t(key)
|
|
1668
1691
|
return label === key ? id : label
|
|
1669
1692
|
}
|
|
1670
1693
|
|
|
1671
1694
|
/** Localized provenance label ("adapter", "relay model list", …). */
|
|
1672
|
-
|
|
1695
|
+
function sourceLabel(source, t) {
|
|
1673
1696
|
const key = 'source.' + (source || 'unknown')
|
|
1674
1697
|
const label = t(key)
|
|
1675
1698
|
return label === key ? t('source.unknown') : label
|
|
1676
1699
|
}
|
|
1677
1700
|
|
|
1678
1701
|
/** Per-field provenance recorded by the Host. */
|
|
1679
|
-
|
|
1702
|
+
function sourceOf(model, field) {
|
|
1680
1703
|
const sources = model && model.sources
|
|
1681
1704
|
return sources && typeof sources[field] === 'string' ? sources[field] : 'unknown'
|
|
1682
1705
|
}
|
|
1683
1706
|
|
|
1684
1707
|
/** Catalog and name heuristics are completed values, not declarations. */
|
|
1685
|
-
|
|
1708
|
+
function isInferredSource(source) {
|
|
1686
1709
|
return source === 'catalog' || source === 'inferred'
|
|
1687
1710
|
}
|
|
1688
1711
|
|
|
1689
1712
|
/** Kind with a safe fallback for records from an older Host. */
|
|
1690
|
-
|
|
1713
|
+
function kindOf(model) {
|
|
1691
1714
|
return model && typeof model.kind === 'string' && model.kind !== '' ? model.kind : 'chat'
|
|
1692
1715
|
}
|
|
1693
1716
|
|
|
1694
1717
|
/** Filter bucket: chat / image / video / other. */
|
|
1695
|
-
|
|
1718
|
+
function bucketOf(kind) {
|
|
1696
1719
|
if (kind === 'image') return 'image'
|
|
1697
1720
|
if (kind === 'video') return 'video'
|
|
1698
1721
|
if (kind === 'chat') return 'chat'
|
|
1699
1722
|
return 'other'
|
|
1700
1723
|
}
|
|
1701
1724
|
|
|
1702
|
-
|
|
1725
|
+
function isGenerationKind(kind) {
|
|
1703
1726
|
return kind === 'image' || kind === 'video' || kind === 'audio'
|
|
1704
1727
|
}
|
|
1705
1728
|
|
|
1706
1729
|
/** Resolution tier advertised in the model id ("-4k", "2K"). */
|
|
1707
|
-
|
|
1730
|
+
function resolutionOf(model) {
|
|
1708
1731
|
const text = String((model && model.id) || '')
|
|
1709
1732
|
const match = /(?:^|[-_/])(4k|2k|8k|uhd|hd)(?:$|[-_/])/i.exec(text)
|
|
1710
1733
|
return match === null ? null : match[1].toUpperCase()
|
|
1711
1734
|
}
|
|
1712
1735
|
|
|
1713
1736
|
/** "文本 / 图像" for one modality array. */
|
|
1714
|
-
|
|
1737
|
+
function modalityNames(modalities, t) {
|
|
1715
1738
|
return (Array.isArray(modalities) ? modalities : []).map((id) => modalityLabel(id, t)).join(' / ')
|
|
1716
1739
|
}
|
|
1717
1740
|
|
|
1718
1741
|
/** Input modalities the manual editor can declare, in display order. */
|
|
1719
|
-
|
|
1742
|
+
const OVERRIDE_MODALITIES = ['text', 'image', 'audio', 'video', 'file']
|
|
1720
1743
|
|
|
1721
1744
|
/** Effort levels the manual editor can declare, in display order. */
|
|
1722
|
-
|
|
1745
|
+
const OVERRIDE_EFFORTS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']
|
|
1723
1746
|
|
|
1724
1747
|
/** Localized name of one effort id. */
|
|
1725
|
-
|
|
1748
|
+
function effortLabel(id, t) {
|
|
1726
1749
|
const key = 'effort.' + id
|
|
1727
1750
|
const label = t(key)
|
|
1728
1751
|
return label === key ? id : label
|
|
1729
1752
|
}
|
|
1730
1753
|
|
|
1731
1754
|
/** Identity of a manual override entry; same shape as the row key. */
|
|
1732
|
-
|
|
1755
|
+
function overrideKeyOf(entry) {
|
|
1733
1756
|
return entry ? keyOf(entry.provider, entry.model) : null
|
|
1734
1757
|
}
|
|
1735
1758
|
|
|
1736
1759
|
/** Model fields whose provenance can be manual. */
|
|
1737
|
-
|
|
1760
|
+
function manualFieldsOf(model) {
|
|
1738
1761
|
const sources = model && model.sources ? model.sources : {}
|
|
1739
1762
|
return ['kind', 'reasoning', 'context', 'modalities'].filter(
|
|
1740
1763
|
(field) => sources[field] === 'manual',
|
|
1741
1764
|
)
|
|
1742
1765
|
}
|
|
1743
1766
|
|
|
1767
|
+
|
|
1768
|
+
exports.keyOf = keyOf
|
|
1769
|
+
exports.hiddenSetOf = hiddenSetOf
|
|
1770
|
+
exports.providerLabel = providerLabel
|
|
1771
|
+
exports.COLLAPSE_KEY = COLLAPSE_KEY
|
|
1772
|
+
exports.readCollapsedGroups = readCollapsedGroups
|
|
1773
|
+
exports.persistCollapsedGroups = persistCollapsedGroups
|
|
1774
|
+
exports.countModels = countModels
|
|
1775
|
+
exports.formatContext = formatContext
|
|
1776
|
+
exports.effortNames = effortNames
|
|
1777
|
+
exports.defaultEffortName = defaultEffortName
|
|
1778
|
+
exports.modalityLabel = modalityLabel
|
|
1779
|
+
exports.sourceLabel = sourceLabel
|
|
1780
|
+
exports.sourceOf = sourceOf
|
|
1781
|
+
exports.isInferredSource = isInferredSource
|
|
1782
|
+
exports.kindOf = kindOf
|
|
1783
|
+
exports.bucketOf = bucketOf
|
|
1784
|
+
exports.isGenerationKind = isGenerationKind
|
|
1785
|
+
exports.resolutionOf = resolutionOf
|
|
1786
|
+
exports.modalityNames = modalityNames
|
|
1787
|
+
exports.OVERRIDE_MODALITIES = OVERRIDE_MODALITIES
|
|
1788
|
+
exports.OVERRIDE_EFFORTS = OVERRIDE_EFFORTS
|
|
1789
|
+
exports.effortLabel = effortLabel
|
|
1790
|
+
exports.overrideKeyOf = overrideKeyOf
|
|
1791
|
+
exports.manualFieldsOf = manualFieldsOf
|
|
1744
1792
|
})
|
|
1745
1793
|
|
|
1746
1794
|
// -------------------------------------------------------- hooks
|
|
@@ -2078,13 +2126,13 @@ window.__ModuleLoader__.load({
|
|
|
2078
2126
|
*/
|
|
2079
2127
|
|
|
2080
2128
|
/** Number of one bucket's token sum, guarding partial buckets. */
|
|
2081
|
-
|
|
2129
|
+
function bucketTotalOf(buckets) {
|
|
2082
2130
|
if (!Array.isArray(buckets)) return 0
|
|
2083
2131
|
return buckets.reduce((sum, value) => sum + (Number.isFinite(value) ? value : 0), 0)
|
|
2084
2132
|
}
|
|
2085
2133
|
|
|
2086
2134
|
/** 1234567 → "1.2M"; 4096 → "4.1K"; 0/undefined → "0". */
|
|
2087
|
-
|
|
2135
|
+
function formatTokens(value) {
|
|
2088
2136
|
const tokens = Number.isFinite(value) ? value : 0
|
|
2089
2137
|
if (tokens >= 1_000_000) {
|
|
2090
2138
|
const millions = Math.round((tokens / 100_000)) / 10
|
|
@@ -2098,14 +2146,14 @@ window.__ModuleLoader__.load({
|
|
|
2098
2146
|
}
|
|
2099
2147
|
|
|
2100
2148
|
/** Local-calendar `YYYY-MM-DD` stamp used by the ledger's day buckets. */
|
|
2101
|
-
|
|
2149
|
+
function dayKeyOf(time) {
|
|
2102
2150
|
const date = new Date(Number.isFinite(time) ? time : Date.now())
|
|
2103
2151
|
if (Number.isNaN(date.getTime())) return ''
|
|
2104
2152
|
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
|
|
2105
2153
|
}
|
|
2106
2154
|
|
|
2107
2155
|
/** First day (Monday) of the local ISO week of `time`. */
|
|
2108
|
-
|
|
2156
|
+
function weekKeyOf(time) {
|
|
2109
2157
|
const date = new Date(Number.isFinite(time) ? time : Date.now())
|
|
2110
2158
|
const weekday = (date.getDay() + 6) % 7
|
|
2111
2159
|
date.setDate(date.getDate() - weekday)
|
|
@@ -2113,7 +2161,7 @@ window.__ModuleLoader__.load({
|
|
|
2113
2161
|
}
|
|
2114
2162
|
|
|
2115
2163
|
/** Local calendar month prefix of `time`. */
|
|
2116
|
-
|
|
2164
|
+
function monthPrefixOf(time) {
|
|
2117
2165
|
return dayKeyOf(time).slice(0, 7)
|
|
2118
2166
|
}
|
|
2119
2167
|
|
|
@@ -2124,7 +2172,7 @@ window.__ModuleLoader__.load({
|
|
|
2124
2172
|
* simpler pass (visibility only). Inputs are the loaded groups plus the five
|
|
2125
2173
|
* filter axes; output keeps the group objects in order with only kept models.
|
|
2126
2174
|
*/
|
|
2127
|
-
|
|
2175
|
+
function computeFilteredGroups(groups, { filter = 'all', query = '', multimodalOnly = false, reasoningOnly = false, minContext = 0 } = {}) {
|
|
2128
2176
|
const normalized = String(query ?? '').trim().toLowerCase()
|
|
2129
2177
|
const filtered = []
|
|
2130
2178
|
for (const group of groups ?? []) {
|
|
@@ -2159,14 +2207,14 @@ window.__ModuleLoader__.load({
|
|
|
2159
2207
|
}
|
|
2160
2208
|
|
|
2161
2209
|
/** Counts per kind bucket for the whole list. */
|
|
2162
|
-
|
|
2210
|
+
function countKinds(models) {
|
|
2163
2211
|
const counts = { chat: 0, image: 0, video: 0, other: 0 }
|
|
2164
2212
|
for (const model of models ?? []) counts[bucket(model)] += 1
|
|
2165
2213
|
return counts
|
|
2166
2214
|
}
|
|
2167
2215
|
|
|
2168
2216
|
/** Checker-model candidates from a loaded catalog state. */
|
|
2169
|
-
|
|
2217
|
+
function checkerRoutesOf(groups) {
|
|
2170
2218
|
const routes = []
|
|
2171
2219
|
for (const group of groups ?? []) {
|
|
2172
2220
|
if (group === null || typeof group !== 'object') continue
|
|
@@ -2177,7 +2225,7 @@ window.__ModuleLoader__.load({
|
|
|
2177
2225
|
}
|
|
2178
2226
|
|
|
2179
2227
|
/** Compact label + tooltip for one provider probe diagnostic. */
|
|
2180
|
-
|
|
2228
|
+
function probeOf(state, group, t) {
|
|
2181
2229
|
const list = Array.isArray(state.providers) ? state.providers : []
|
|
2182
2230
|
const diagnostic = list.find((item) => item && item.id === group.id)
|
|
2183
2231
|
if (diagnostic === undefined) return null
|
|
@@ -2207,6 +2255,16 @@ window.__ModuleLoader__.load({
|
|
|
2207
2255
|
return { label: t('group.probeSkipped'), title: details }
|
|
2208
2256
|
}
|
|
2209
2257
|
|
|
2258
|
+
|
|
2259
|
+
exports.bucketTotalOf = bucketTotalOf
|
|
2260
|
+
exports.formatTokens = formatTokens
|
|
2261
|
+
exports.dayKeyOf = dayKeyOf
|
|
2262
|
+
exports.weekKeyOf = weekKeyOf
|
|
2263
|
+
exports.monthPrefixOf = monthPrefixOf
|
|
2264
|
+
exports.computeFilteredGroups = computeFilteredGroups
|
|
2265
|
+
exports.countKinds = countKinds
|
|
2266
|
+
exports.checkerRoutesOf = checkerRoutesOf
|
|
2267
|
+
exports.probeOf = probeOf
|
|
2210
2268
|
})
|
|
2211
2269
|
|
|
2212
2270
|
// -------------------------------------------------------- settings-section
|
|
@@ -3040,7 +3098,7 @@ window.__ModuleLoader__.load({
|
|
|
3040
3098
|
anchor.remove()
|
|
3041
3099
|
}
|
|
3042
3100
|
|
|
3043
|
-
|
|
3101
|
+
function UsageToolbar({ usage, t, features }) {
|
|
3044
3102
|
const state = useSource(usage)
|
|
3045
3103
|
const supported = features.length === 0 || features.includes('usage')
|
|
3046
3104
|
const ranges = state.snapshot?.ranges
|
|
@@ -3114,6 +3172,8 @@ window.__ModuleLoader__.load({
|
|
|
3114
3172
|
)
|
|
3115
3173
|
}
|
|
3116
3174
|
|
|
3175
|
+
|
|
3176
|
+
exports.UsageToolbar = UsageToolbar
|
|
3117
3177
|
})
|
|
3118
3178
|
|
|
3119
3179
|
// -------------------------------------------------------- entry
|