@cassius0924/dsh-usage-dashboard 0.7.0 → 0.8.0
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 +4 -1
- package/lib/client.js +484 -106
- package/lib/client.js.map +4 -4
- package/lib/types/client/context.d.ts +17 -2
- package/lib/types/client/index.d.ts +1 -1
- package/lib/types/client/layout-prefs.d.ts +56 -0
- package/lib/types/client/locales.d.ts +23 -16
- package/lib/types/client/store.d.ts +1 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/client/views.d.ts +1 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
name: () => name
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
var import_react7 = require("react");
|
|
29
30
|
|
|
30
31
|
// src/client/boundary.tsx
|
|
31
32
|
var import_react = require("react");
|
|
@@ -317,7 +318,7 @@ var zh = {
|
|
|
317
318
|
"delta.noBaseline": "\u65E0\u5BF9\u6BD4",
|
|
318
319
|
"delta.flat": "\u6301\u5E73",
|
|
319
320
|
"period.volume": "{tokens} tokens \xB7 {calls}",
|
|
320
|
-
"budget.unset": "\
|
|
321
|
+
"budget.unset": "\u672A\u8BBE\u7F6E\u6708\u5EA6\u9884\u7B97\u3002",
|
|
321
322
|
"budget.configure": "\u8BBE\u7F6E\u9884\u7B97",
|
|
322
323
|
"budget.over": "\u5DF2\u8D85\u9884\u7B97 \xA5{amount}",
|
|
323
324
|
"budget.forecastOver": "\u7167\u5F53\u524D\u901F\u5EA6\uFF0C\u9884\u8BA1\u8D85\u51FA \xA5{amount}",
|
|
@@ -340,7 +341,6 @@ var zh = {
|
|
|
340
341
|
"pricing.unit": "\u5355\u4F4D\uFF1A{currency} / \u767E\u4E07 tokens\u3002",
|
|
341
342
|
"pricing.splitNote": "\u9AD8\u5CF0\u65F6\u6BB5\u4E3A\u5317\u4EAC\u65F6\u95F4 {windows}\uFF08\u5468\u4E00\u81F3\u5468\u4E94\uFF09\uFF0C\u5176\u4F59\u4E3A\u95F2\u65F6\uFF08\u4EF7\u683C\u51CF\u534A\uFF09\uFF1B\u6BCF\u6761\u7528\u91CF\u6309\u53D1\u751F\u65F6\u523B\u751F\u6548\u7684\u5B98\u65B9\u4EF7\u683C\u4F30\u7B97\u3002",
|
|
342
343
|
"pricing.visionNote": "\u56FE\u7247\u6309\u5C3A\u5BF8\u6298\u7B97 token\uFF0C\u4E0E\u6587\u672C\u4E00\u5E76\u8BA1\u8D39\u3002",
|
|
343
|
-
"pricing.modelNote": "deepseek-v4-flash\u3001deepseek-v4-flash-vision-exp \u662F\u65E7\u6A21\u578B\u540D\uFF0C\u73B0\u7531 deepseek-flash \u627F\u63A5\u5E76\u6309 Flash \u4EF7\u8BA1\u8D39\uFF1B2026-09-14 12:00 \u8D77 deepseek-v4-pro \u7684\u8BF7\u6C42\u4E5F\u4F1A\u8DEF\u7531\u5230 V4.1-Flash\uFF0C\u6309 Flash \u4EF7\u8BA1\u8D39\u3002",
|
|
344
344
|
"pricing.unknown": "\u672A\u77E5\u6A21\u578B\u6309 deepseek-v4-pro \u8BA1\u4EF7\u3002",
|
|
345
345
|
"coverage.noRange": "\u6682\u65E0\u6709\u6548\u7528\u91CF\u65F6\u95F4",
|
|
346
346
|
"coverage.title": "\u7EDF\u8BA1\u8303\u56F4",
|
|
@@ -361,23 +361,19 @@ var zh = {
|
|
|
361
361
|
"export.modelCsv": "\u9010\u6A21\u578B CSV",
|
|
362
362
|
"export.fullJson": "\u5B8C\u6574 JSON",
|
|
363
363
|
"export.jsonHint": "\u542B\u56FE\u8868\u4E0E\u6392\u884C",
|
|
364
|
-
"cache.empty": "\
|
|
364
|
+
"cache.empty": "\u6682\u65E0\u7F13\u5B58\u547D\u4E2D\u6570\u636E\u3002",
|
|
365
365
|
"cache.rate": "\u7F13\u5B58\u547D\u4E2D\u7387",
|
|
366
366
|
"cache.saved": "\u5DF2\u8282\u7701\u8D39\u7528\uFF08\u4F30\u7B97\uFF09",
|
|
367
367
|
"cache.allMiss": "\u82E5\u5168\u90E8\u672A\u547D\u4E2D",
|
|
368
368
|
"cache.aria": "\u7F13\u5B58\u547D\u4E2D {hit}%\uFF0C\u672A\u547D\u4E2D {miss}%",
|
|
369
369
|
"cache.hitLegend": "\u7F13\u5B58\u547D\u4E2D {tokens}",
|
|
370
370
|
"cache.missLegend": "\u672A\u547D\u4E2D {tokens}\uFF08\u6309\u672A\u547D\u4E2D\u4EF7\u8BA1\u8D39\uFF09",
|
|
371
|
-
"
|
|
372
|
-
"cache.goodHint": "\u524D\u7F00\u7F13\u5B58\u628A\u91CD\u590D\u7684 prompt \u524D\u7F00\u6309\u547D\u4E2D\u4EF7\u8BA1\u8D39\uFF0C\u662F\u8FD9\u4EFD\u8D26\u5355\u4E0A\u6700\u5927\u7684\u7701\u94B1\u6760\u6746\u3002",
|
|
373
|
-
"peak.empty": "\u8FD8\u6CA1\u6709\u53EF\u6309\u65F6\u6BB5\u5F52\u7C7B\u7684\u7528\u91CF\u3002",
|
|
371
|
+
"peak.empty": "\u6682\u65E0\u7528\u91CF\u3002",
|
|
374
372
|
"peak.aria": "\u9AD8\u5CF0\u65F6\u6BB5 {peak}%\uFF0C\u95F2\u65F6 {offPeak}%",
|
|
375
373
|
"peak.peakLegend": "\u9AD8\u5CF0 {share}% \xB7 {tokens} tokens \xB7 {calls}",
|
|
376
374
|
"peak.offPeakLegend": "\u95F2\u65F6 {share}% \xB7 {tokens} tokens \xB7 {calls}",
|
|
377
375
|
"peak.shift": "\u82E5\u9AD8\u5CF0\u7528\u91CF\u90FD\u632A\u5230\u95F2\u65F6",
|
|
378
376
|
"peak.saving": "\u53EF\u7701 \xA5{amount}",
|
|
379
|
-
"peak.schedule": "\u9AD8\u5CF0\u65F6\u6BB5\u4E3A\u5317\u4EAC\u65F6\u95F4 {windows}\uFF08\u5468\u4E00\u81F3\u5468\u4E94\uFF09\uFF0C\u95F2\u65F6\u4EF7\u683C\u51CF\u534A\u3002",
|
|
380
|
-
"peak.activeHint": "\u628A\u6279\u91CF\u3001\u53EF\u5EF6\u540E\u7684\u4EFB\u52A1\u653E\u5230\u95F2\u65F6\u8DD1\uFF0C\u540C\u6837\u7684 token \u53EA\u8981\u4E00\u534A\u7684\u94B1\u3002",
|
|
381
377
|
"vision.empty": "{window}\u6CA1\u6709\u56FE\u7247\u8F93\u5165\u3002",
|
|
382
378
|
"vision.title": "\u56FE\u7247 / \u591A\u6A21\u6001\u7528\u91CF",
|
|
383
379
|
"vision.images": "\u56FE\u7247\u5F20\u6570",
|
|
@@ -385,7 +381,7 @@ var zh = {
|
|
|
385
381
|
"vision.cost": "\u4F30\u7B97\u8D39\u7528",
|
|
386
382
|
"vision.tokensShare": "\u5360\u8F93\u5165 {percent}%",
|
|
387
383
|
"vision.costShare": "\u5360\u8D39\u7528 {percent}%",
|
|
388
|
-
"vision.note": "\
|
|
384
|
+
"vision.note": "\u6309\u5B98\u65B9\u89C4\u5219\u4F30\u7B97\uFF0C\u5B9E\u9645\u4EE5\u63A5\u53E3\u8FD4\u56DE\u7684\u7528\u91CF\u4E3A\u51C6\u3002",
|
|
389
385
|
"vision.sessionsTitle": "\u56FE\u7247\u6700\u591A\u7684\u4F1A\u8BDD",
|
|
390
386
|
"vision.sessionRow": "{images} \u5F20 \xB7 \xA5{cost}",
|
|
391
387
|
"vision.dailyTitle": "{window} \xB7 \u6BCF\u5929\u56FE\u7247\u6570",
|
|
@@ -394,7 +390,7 @@ var zh = {
|
|
|
394
390
|
"sessions.empty": "\u8FD8\u6CA1\u6709\u4EA7\u751F\u8D39\u7528\u7684\u4F1A\u8BDD\u3002",
|
|
395
391
|
"sessions.detail": "{tokens} tokens \xB7 {calls} \xB7 {ago}",
|
|
396
392
|
"sessions.share": "\u5360 {percent}%",
|
|
397
|
-
"sessions.more": "\u5171 {count} \u4E2A\u4F1A\u8BDD\
|
|
393
|
+
"sessions.more": "\u5171 {count} \u4E2A\u4F1A\u8BDD\uFF0C\u663E\u793A\u6700\u8D35\u7684 {shown} \u4E2A\u3002",
|
|
398
394
|
"sessions.fallbackTitle": "\u4F1A\u8BDD {id}",
|
|
399
395
|
"models.empty": "\u8FD8\u6CA1\u6709\u53EF\u5F52\u7C7B\u7684\u6A21\u578B\u7528\u91CF\u3002",
|
|
400
396
|
"models.shareAria": "{name} \u5360\u603B\u8D39\u7528 {percent}%",
|
|
@@ -421,9 +417,9 @@ var zh = {
|
|
|
421
417
|
"chart.dimensionLabel": "\u5207\u6362\u56FE\u8868\u7EF4\u5EA6",
|
|
422
418
|
"chart.daily": "\u9010\u5929",
|
|
423
419
|
"chart.hourly": "\u9010\u5C0F\u65F6",
|
|
424
|
-
"chart.noWindowData": "{window}\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\
|
|
420
|
+
"chart.noWindowData": "{window}\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\u3002",
|
|
425
421
|
"chart.heatmapTitle": "\u8FD1\u4E00\u5E74 \xB7 \u6BCF\u65E5",
|
|
426
|
-
"chart.empty": "\u8FD8\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\u3002
|
|
422
|
+
"chart.empty": "\u8FD8\u6CA1\u6709\u7528\u91CF\u8BB0\u5F55\u3002",
|
|
427
423
|
"chart.hourPoint": "{hour} \u70B9",
|
|
428
424
|
"chart.tooltip": "{head} \xB7 {tokens} tokens \xB7 \xA5{cost} \xB7 {calls}",
|
|
429
425
|
"chart.less": "\u5C11",
|
|
@@ -489,7 +485,7 @@ var zh = {
|
|
|
489
485
|
"balance.overYear": "> 365 \u5929",
|
|
490
486
|
"balance.noRunway": "\u8FD1 {days} \u5929\u6CA1\u6709\u7528\u91CF\uFF0C\u65E0\u6CD5\u4F30\u7B97",
|
|
491
487
|
"balance.runwayTitle": "\u6309\u8FD1 {days} \u5929\u65E5\u5747 \xA5{cost} \u4F30\u7B97\uFF08\u542B\u65E0\u7528\u91CF\u7684\u65E5\u5B50\uFF1B\u4ECA\u5929\u5C1A\u672A\u8FC7\u5B8C\uFF09",
|
|
492
|
-
"balance.empty": "\u8BFB\u4E0D\u5230\u4F59\u989D\
|
|
488
|
+
"balance.empty": "\u8BFB\u4E0D\u5230\u4F59\u989D\uFF0C\u8BF7\u68C0\u67E5\u8D26\u53F7\u767B\u5F55\u6216 API Key \u540E\u5237\u65B0\u3002",
|
|
493
489
|
"sessionUsage.title": "\u5F53\u524D\u4F1A\u8BDD\u6D88\u8017",
|
|
494
490
|
"common.estimated": "\u8D39\u7528\u4E3A\u4F30\u7B97",
|
|
495
491
|
"sessionUsage.cost": "\u8D39\u7528",
|
|
@@ -497,7 +493,7 @@ var zh = {
|
|
|
497
493
|
"sessionUsage.calls": "\u8C03\u7528\u6B21\u6570",
|
|
498
494
|
"sessionUsage.range": "\u6D3B\u8DC3\u65F6\u95F4 {range}",
|
|
499
495
|
"sessionUsage.single": "{model} \xB7 \u8F93\u5165 {input} / \u8F93\u51FA {output} / \u7F13\u5B58 {cache}",
|
|
500
|
-
"sessionUsage.empty": "\u8FD9\u4E2A\u4F1A\u8BDD\u8FD8\u6CA1\u6709\
|
|
496
|
+
"sessionUsage.empty": "\u8FD9\u4E2A\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u7528\u91CF\u3002",
|
|
501
497
|
"overview.title": "\u6D88\u8017\u6982\u89C8",
|
|
502
498
|
"overview.today": "\u4ECA\u65E5",
|
|
503
499
|
"overview.month": "\u672C\u6708",
|
|
@@ -519,9 +515,9 @@ var zh = {
|
|
|
519
515
|
"links.status": "\u670D\u52A1\u72B6\u6001",
|
|
520
516
|
"settings.title": "\u8BBE\u7F6E",
|
|
521
517
|
"settings.widget": "\u5728\u5176\u4ED6\u9875\u9762\u663E\u793A\u53F3\u4E0B\u89D2\u60AC\u6D6E\u989D\u5EA6\u7A97\u53E3",
|
|
522
|
-
"settings.widgetHint": "\u989D\u5EA6\u9875\
|
|
518
|
+
"settings.widgetHint": "\u989D\u5EA6\u9875\u81EA\u52A8\u9690\u85CF\uFF1B\u5176\u4ED6\u9875\u9762\u6309\u4E0B\u65B9\u9009\u62E9\u663E\u793A\u3002",
|
|
523
519
|
"settings.widgetTabs": "\u5C55\u793A\u6D6E\u7A97\u7684\u9875\u9762",
|
|
524
|
-
"settings.widgetTabsHint": "\
|
|
520
|
+
"settings.widgetTabsHint": "\u5217\u8868\u4F1A\u968F\u5DF2\u5B89\u88C5\u7684\u9875\u9762\u81EA\u52A8\u66F4\u65B0\u3002",
|
|
525
521
|
"settings.widgetTabsEmpty": "\u5F53\u524D\u6CA1\u6709\u53EF\u914D\u7F6E\u7684\u4F1A\u8BDD\u9875\u9762\u3002",
|
|
526
522
|
"settings.lowBalance": "\u4F59\u989D\u9884\u8B66\u7EBF",
|
|
527
523
|
"settings.lowBalanceOn": "\u4F59\u989D\u4F4E\u4E8E {amount} {currency} \u65F6\uFF0C\u8FD9\u91CC\u548C\u60AC\u6D6E\u7A97\u90FD\u4F1A\u8F6C\u4E3A\u8B66\u793A\u8272\u3002\u586B 0 \u5173\u95ED\u3002",
|
|
@@ -529,6 +525,18 @@ var zh = {
|
|
|
529
525
|
"settings.monthlyBudget": "\u6708\u5EA6\u9884\u7B97",
|
|
530
526
|
"settings.monthlyBudgetOn": "\u6309\u5317\u4EAC\u65F6\u95F4\u81EA\u7136\u6708\u8DDF\u8E2A {amount} CNY \u9884\u7B97\uFF0C\u5E76\u5728\u6D88\u8017\u6982\u89C8\u9884\u6D4B\u6708\u5E95\u82B1\u8D39\u3002\u586B 0 \u5173\u95ED\u3002",
|
|
531
527
|
"settings.monthlyBudgetOff": "\u586B\u4E00\u4E2A\u5927\u4E8E 0 \u7684\u91D1\u989D\uFF0C\u6D88\u8017\u6982\u89C8\u4F1A\u663E\u793A\u8FDB\u5EA6\u4E0E\u6708\u5E95\u9884\u6D4B\u3002",
|
|
528
|
+
"settings.sidebarEntry": "\u4FA7\u8FB9\u680F\u989D\u5EA6\u5165\u53E3",
|
|
529
|
+
"settings.sidebarEntryHint": "\u5728\u4FA7\u8FB9\u680F\u9876\u90E8\u6216\u5E95\u90E8\u653E\u4E00\u4E2A\u300C\u989D\u5EA6\u300D\u5165\u53E3\uFF0C\u6253\u5F00\u8D26\u6237\u7EA7\u989D\u5EA6\u9875\u3002",
|
|
530
|
+
"settings.sidebarEntryOff": "\u5173\u95ED",
|
|
531
|
+
"settings.sidebarEntryTop": "\u9876\u90E8",
|
|
532
|
+
"settings.sidebarEntryBottom": "\u5E95\u90E8",
|
|
533
|
+
"settings.tabPosition": "\u300C\u989D\u5EA6\u300D\u6807\u7B7E\u4F4D\u7F6E",
|
|
534
|
+
"settings.tabPositionHint": "\u62D6\u52A8\u300C\u989D\u5EA6\u300D\u8C03\u6574\u6807\u7B7E\u4F4D\u7F6E\u3002",
|
|
535
|
+
"settings.tabDragAria": "\u62D6\u52A8\u300C\u989D\u5EA6\u300D\u8C03\u6574\u6807\u7B7E\u4F4D\u7F6E",
|
|
536
|
+
"settings.tabMoveEarlier": "\u524D\u79FB",
|
|
537
|
+
"settings.tabMoveLater": "\u540E\u79FB",
|
|
538
|
+
"panel.caption": "\u8D26\u6237\u7EA7 \xB7 \u8DE8\u5168\u90E8\u4F1A\u8BDD",
|
|
539
|
+
"panel.openAria": "\u6253\u5F00\u989D\u5EA6\u9875",
|
|
532
540
|
"widget.updatedNow": "\u521A\u521A\u66F4\u65B0",
|
|
533
541
|
"widget.stale": "{minutes} \u5206\u949F\u524D\u7684\u6570\u636E\uFF0C\u70B9 \u21BB \u66F4\u65B0",
|
|
534
542
|
"widget.loading": "\u67E5\u8BE2\u4E2D\u2026",
|
|
@@ -578,7 +586,7 @@ var en = {
|
|
|
578
586
|
"delta.noBaseline": "No baseline",
|
|
579
587
|
"delta.flat": "No change",
|
|
580
588
|
"period.volume": "{tokens} tokens \xB7 {calls}",
|
|
581
|
-
"budget.unset": "
|
|
589
|
+
"budget.unset": "No monthly budget set.",
|
|
582
590
|
"budget.configure": "Set budget",
|
|
583
591
|
"budget.over": "Over budget by \xA5{amount}",
|
|
584
592
|
"budget.forecastOver": "At this pace, \xA5{amount} over by month-end",
|
|
@@ -601,7 +609,6 @@ var en = {
|
|
|
601
609
|
"pricing.unit": "Unit: {currency} / million tokens. ",
|
|
602
610
|
"pricing.splitNote": "Peak periods are {windows} Beijing time, Monday to Friday; off-peak rates are half price. Each record is estimated at the official rates in force when it was written. ",
|
|
603
611
|
"pricing.visionNote": "Images are converted to tokens by size and charged together with text. ",
|
|
604
|
-
"pricing.modelNote": "deepseek-v4-flash and deepseek-v4-flash-vision-exp are legacy names, now served by deepseek-flash at Flash rates; from 2026-09-14 12:00 deepseek-v4-pro requests are routed to V4.1-Flash and billed at Flash rates. ",
|
|
605
612
|
"pricing.unknown": "Unknown models use deepseek-v4-pro rates.",
|
|
606
613
|
"coverage.noRange": "No valid usage timestamps",
|
|
607
614
|
"coverage.title": "Coverage",
|
|
@@ -622,23 +629,19 @@ var en = {
|
|
|
622
629
|
"export.modelCsv": "Model CSV",
|
|
623
630
|
"export.fullJson": "Full JSON",
|
|
624
631
|
"export.jsonHint": "Charts and rankings included",
|
|
625
|
-
"cache.empty": "No
|
|
632
|
+
"cache.empty": "No cache data yet.",
|
|
626
633
|
"cache.rate": "Cache hit rate",
|
|
627
634
|
"cache.saved": "Estimated savings",
|
|
628
635
|
"cache.allMiss": "Cost with no hits",
|
|
629
636
|
"cache.aria": "{hit}% cache hits, {miss}% misses",
|
|
630
637
|
"cache.hitLegend": "Cache hits {tokens}",
|
|
631
638
|
"cache.missLegend": "Misses {tokens} (charged at miss rate)",
|
|
632
|
-
"
|
|
633
|
-
"cache.goodHint": "Prefix caching charges repeated prompt prefixes at the hit rate, making it the largest saving lever on this bill.",
|
|
634
|
-
"peak.empty": "No usage can be classified by pricing period yet.",
|
|
639
|
+
"peak.empty": "No usage yet.",
|
|
635
640
|
"peak.aria": "{peak}% peak, {offPeak}% off-peak",
|
|
636
641
|
"peak.peakLegend": "Peak {share}% \xB7 {tokens} tokens \xB7 {calls}",
|
|
637
642
|
"peak.offPeakLegend": "Off-peak {share}% \xB7 {tokens} tokens \xB7 {calls}",
|
|
638
643
|
"peak.shift": "If all peak usage moved off-peak",
|
|
639
644
|
"peak.saving": "Save \xA5{amount}",
|
|
640
|
-
"peak.schedule": "Peak periods are {windows} Beijing time, Monday to Friday; off-peak rates are half price. ",
|
|
641
|
-
"peak.activeHint": "Run batch or delay-tolerant work off-peak to pay half as much for the same tokens.",
|
|
642
645
|
"vision.empty": "No image input in {window}.",
|
|
643
646
|
"vision.title": "Image / multimodal usage",
|
|
644
647
|
"vision.images": "Images",
|
|
@@ -646,7 +649,7 @@ var en = {
|
|
|
646
649
|
"vision.cost": "Estimated cost",
|
|
647
650
|
"vision.tokensShare": "{percent}% of input",
|
|
648
651
|
"vision.costShare": "{percent}% of cost",
|
|
649
|
-
"vision.note": "
|
|
652
|
+
"vision.note": "Estimated with the official rule; provider usage numbers are the source of truth.",
|
|
650
653
|
"vision.sessionsTitle": "Sessions with the most images",
|
|
651
654
|
"vision.sessionRow": "{images} images \xB7 \xA5{cost}",
|
|
652
655
|
"vision.dailyTitle": "{window} \xB7 images per day",
|
|
@@ -655,7 +658,7 @@ var en = {
|
|
|
655
658
|
"sessions.empty": "No sessions have incurred cost yet.",
|
|
656
659
|
"sessions.detail": "{tokens} tokens \xB7 {calls} \xB7 {ago}",
|
|
657
660
|
"sessions.share": "{percent}% of total",
|
|
658
|
-
"sessions.more": "{count} sessions
|
|
661
|
+
"sessions.more": "{count} sessions; showing the {shown} most expensive.",
|
|
659
662
|
"sessions.fallbackTitle": "Session {id}",
|
|
660
663
|
"models.empty": "No model usage can be classified yet.",
|
|
661
664
|
"models.shareAria": "{name} accounts for {percent}% of total cost",
|
|
@@ -682,9 +685,9 @@ var en = {
|
|
|
682
685
|
"chart.dimensionLabel": "Chart interval",
|
|
683
686
|
"chart.daily": "Daily",
|
|
684
687
|
"chart.hourly": "Hourly",
|
|
685
|
-
"chart.noWindowData": "No usage in {window}.
|
|
688
|
+
"chart.noWindowData": "No usage in {window}.",
|
|
686
689
|
"chart.heatmapTitle": "Last 12 months \xB7 daily",
|
|
687
|
-
"chart.empty": "No usage yet.
|
|
690
|
+
"chart.empty": "No usage yet.",
|
|
688
691
|
"chart.hourPoint": "{hour}:00",
|
|
689
692
|
"chart.tooltip": "{head} \xB7 {tokens} tokens \xB7 \xA5{cost} \xB7 {calls}",
|
|
690
693
|
"chart.less": "Less",
|
|
@@ -750,7 +753,7 @@ var en = {
|
|
|
750
753
|
"balance.overYear": "> 365 days",
|
|
751
754
|
"balance.noRunway": "No usage in the last {days} days, so runway cannot be estimated",
|
|
752
755
|
"balance.runwayTitle": "Based on \xA5{cost} average daily spend over the last {days} days (including idle days; today is incomplete)",
|
|
753
|
-
"balance.empty": "Balance is unavailable.
|
|
756
|
+
"balance.empty": "Balance is unavailable. Check your sign-in or API key, then refresh.",
|
|
754
757
|
"sessionUsage.title": "Current session spend",
|
|
755
758
|
"common.estimated": "Estimated cost",
|
|
756
759
|
"sessionUsage.cost": "Cost",
|
|
@@ -758,7 +761,7 @@ var en = {
|
|
|
758
761
|
"sessionUsage.calls": "Calls",
|
|
759
762
|
"sessionUsage.range": "Active {range}",
|
|
760
763
|
"sessionUsage.single": "{model} \xB7 input {input} / output {output} / cache {cache}",
|
|
761
|
-
"sessionUsage.empty": "No usage in this session yet.
|
|
764
|
+
"sessionUsage.empty": "No usage in this session yet.",
|
|
762
765
|
"overview.title": "Spend overview",
|
|
763
766
|
"overview.today": "Today",
|
|
764
767
|
"overview.month": "This month",
|
|
@@ -780,9 +783,9 @@ var en = {
|
|
|
780
783
|
"links.status": "Service status",
|
|
781
784
|
"settings.title": "Settings",
|
|
782
785
|
"settings.widget": "Show the floating balance widget on other views",
|
|
783
|
-
"settings.widgetHint": "
|
|
786
|
+
"settings.widgetHint": "Hidden on Usage; shown on the views selected below.",
|
|
784
787
|
"settings.widgetTabs": "Show widget on",
|
|
785
|
-
"settings.widgetTabsHint": "
|
|
788
|
+
"settings.widgetTabsHint": "Updates automatically as views are installed.",
|
|
786
789
|
"settings.widgetTabsEmpty": "There are no configurable conversation views right now.",
|
|
787
790
|
"settings.lowBalance": "Balance warning",
|
|
788
791
|
"settings.lowBalanceOn": "This page and the widget turn amber below {amount} {currency}. Enter 0 to disable.",
|
|
@@ -790,6 +793,18 @@ var en = {
|
|
|
790
793
|
"settings.monthlyBudget": "Monthly budget",
|
|
791
794
|
"settings.monthlyBudgetOn": "Track a {amount} CNY budget by Beijing calendar month and forecast month-end spend. Enter 0 to disable.",
|
|
792
795
|
"settings.monthlyBudgetOff": "Enter an amount above 0 to show progress and a month-end forecast.",
|
|
796
|
+
"settings.sidebarEntry": "Sidebar Usage entry",
|
|
797
|
+
"settings.sidebarEntryHint": "Add a Usage entry at the top or bottom of the sidebar; it opens the account-wide Usage page.",
|
|
798
|
+
"settings.sidebarEntryOff": "Off",
|
|
799
|
+
"settings.sidebarEntryTop": "Top",
|
|
800
|
+
"settings.sidebarEntryBottom": "Bottom",
|
|
801
|
+
"settings.tabPosition": "Usage tab position",
|
|
802
|
+
"settings.tabPositionHint": "Drag Usage to change its tab position.",
|
|
803
|
+
"settings.tabDragAria": "Drag Usage to change its tab position",
|
|
804
|
+
"settings.tabMoveEarlier": "Move earlier",
|
|
805
|
+
"settings.tabMoveLater": "Move later",
|
|
806
|
+
"panel.caption": "Account-wide \xB7 across all sessions",
|
|
807
|
+
"panel.openAria": "Open Usage",
|
|
793
808
|
"widget.updatedNow": "Updated just now",
|
|
794
809
|
"widget.stale": "Data from {minutes}m ago; press \u21BB to update",
|
|
795
810
|
"widget.loading": "Loading\u2026",
|
|
@@ -1353,6 +1368,27 @@ var quotaViewActiveStore = {
|
|
|
1353
1368
|
}
|
|
1354
1369
|
};
|
|
1355
1370
|
|
|
1371
|
+
// src/client/layout-prefs.ts
|
|
1372
|
+
var QUOTA_PANEL_ID = "quota";
|
|
1373
|
+
var isPlacement = (value) => value === "off" || value === "top" || value === "bottom";
|
|
1374
|
+
var sidebarEntryStore = createStore("layout.sidebarEntry", isPlacement, "off");
|
|
1375
|
+
var isTabIndex = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 50;
|
|
1376
|
+
var quotaTabIndexStore = createStore("layout.tabIndex", isTabIndex, 2);
|
|
1377
|
+
function clampTabIndex(index, count) {
|
|
1378
|
+
return Math.max(0, Math.min(index, Math.max(count, 0)));
|
|
1379
|
+
}
|
|
1380
|
+
function viewOrderForIndex(entries, index, selfId = "balance", fallback = 20) {
|
|
1381
|
+
const others = entries.filter((entry) => entry.options.id !== selfId);
|
|
1382
|
+
if (others.length === 0) return fallback;
|
|
1383
|
+
const clamped = clampTabIndex(index, others.length);
|
|
1384
|
+
const orderAt = (position) => others[position]?.options.order ?? 0;
|
|
1385
|
+
if (clamped === 0) return orderAt(0) - 10;
|
|
1386
|
+
if (clamped === others.length) return orderAt(others.length - 1) + 10;
|
|
1387
|
+
const previous = orderAt(clamped - 1);
|
|
1388
|
+
const next = orderAt(clamped);
|
|
1389
|
+
return previous >= next ? previous + 0.5 : (previous + next) / 2;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1356
1392
|
// src/client/dashboard.tsx
|
|
1357
1393
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1358
1394
|
var COMPOSER_FALLBACK_PX = 126;
|
|
@@ -1518,7 +1554,6 @@ function PricingNote(props) {
|
|
|
1518
1554
|
t("pricing.unit", { currency: pricing.currency }),
|
|
1519
1555
|
t("pricing.splitNote", { windows: pricing.peakWindows.join(t("common.listSeparator")) }),
|
|
1520
1556
|
t("pricing.visionNote"),
|
|
1521
|
-
t("pricing.modelNote"),
|
|
1522
1557
|
t("pricing.unknown")
|
|
1523
1558
|
] })
|
|
1524
1559
|
] })
|
|
@@ -1780,8 +1815,7 @@ function CacheCard(props) {
|
|
|
1780
1815
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-legend-swatch dq-legend-swatch--miss" }),
|
|
1781
1816
|
t("cache.missLegend", { tokens: fmtCompact(totals.input, locale) })
|
|
1782
1817
|
] })
|
|
1783
|
-
] })
|
|
1784
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-cache-foot", children: low ? t("cache.lowHint") : t("cache.goodHint") })
|
|
1818
|
+
] })
|
|
1785
1819
|
] });
|
|
1786
1820
|
}
|
|
1787
1821
|
function VisionCard(props) {
|
|
@@ -1863,11 +1897,7 @@ function PeakCard(props) {
|
|
|
1863
1897
|
fmt(split.offPeakEraCost),
|
|
1864
1898
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-peak-delta dq-peak-delta--save", children: t("peak.saving", { amount: fmt(shiftSaving) }) })
|
|
1865
1899
|
] })
|
|
1866
|
-
] }) })
|
|
1867
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "dq-peak-foot", children: [
|
|
1868
|
-
t("peak.schedule", { windows: pricing.peakWindows.join(t("common.listSeparator")) }),
|
|
1869
|
-
t("peak.activeHint")
|
|
1870
|
-
] })
|
|
1900
|
+
] }) })
|
|
1871
1901
|
] });
|
|
1872
1902
|
}
|
|
1873
1903
|
function agoText(ms, t) {
|
|
@@ -2118,6 +2148,11 @@ function BalanceDashboard(props) {
|
|
|
2118
2148
|
const [selectedModels, setSelectedModels] = (0, import_react4.useState)([]);
|
|
2119
2149
|
const [windowDays, setWindowDays] = (0, import_react4.useState)(usageWindowStore.get());
|
|
2120
2150
|
const [chartMetric, setChartMetric] = (0, import_react4.useState)(chartMetricStore.get());
|
|
2151
|
+
const [sidebarEntry, setSidebarEntry] = (0, import_react4.useState)(sidebarEntryStore.get());
|
|
2152
|
+
(0, import_react4.useEffect)(() => sidebarEntryStore.subscribe(() => setSidebarEntry(sidebarEntryStore.get())), []);
|
|
2153
|
+
const [tabDragging, setTabDragging] = (0, import_react4.useState)(false);
|
|
2154
|
+
const [tabDropTarget, setTabDropTarget] = (0, import_react4.useState)(null);
|
|
2155
|
+
const [retainedVision, setRetainedVision] = (0, import_react4.useState)(null);
|
|
2121
2156
|
const [runwayHovering, setRunwayHovering] = (0, import_react4.useState)(false);
|
|
2122
2157
|
const [runwayManuallyOpened, setRunwayManuallyOpened] = (0, import_react4.useState)(false);
|
|
2123
2158
|
const [remainingHovering, setRemainingHovering] = (0, import_react4.useState)(false);
|
|
@@ -2290,6 +2325,71 @@ function BalanceDashboard(props) {
|
|
|
2290
2325
|
setChartMetric(value);
|
|
2291
2326
|
chartMetricStore.set(value);
|
|
2292
2327
|
};
|
|
2328
|
+
const changeSidebarEntry = (value) => {
|
|
2329
|
+
setSidebarEntry(value);
|
|
2330
|
+
sidebarEntryStore.set(value);
|
|
2331
|
+
};
|
|
2332
|
+
const balanceTabIndex = viewTabs.findIndex((tab) => tab.id === "balance");
|
|
2333
|
+
const finalTabIndex = (target, after) => {
|
|
2334
|
+
const gap = after ? target + 1 : target;
|
|
2335
|
+
const dropped = balanceTabIndex >= 0 && gap > balanceTabIndex ? gap - 1 : gap;
|
|
2336
|
+
return Math.max(0, Math.min(dropped, Math.max(viewTabs.length - 1, 0)));
|
|
2337
|
+
};
|
|
2338
|
+
const endTabDrag = () => {
|
|
2339
|
+
setTabDragging(false);
|
|
2340
|
+
setTabDropTarget(null);
|
|
2341
|
+
};
|
|
2342
|
+
const previewTabDropTarget = (index) => {
|
|
2343
|
+
setTabDropTarget((prev) => prev === index ? prev : index);
|
|
2344
|
+
};
|
|
2345
|
+
const applyQuotaTabIndex = (index) => {
|
|
2346
|
+
const next = Math.max(0, Math.min(index, Math.max(viewTabs.length - 1, 0)));
|
|
2347
|
+
if (next === balanceTabIndex) return;
|
|
2348
|
+
quotaTabIndexStore.set(next);
|
|
2349
|
+
window.setTimeout(() => {
|
|
2350
|
+
const chip = document.querySelector(".dq-tab-chip--current");
|
|
2351
|
+
chip?.focus();
|
|
2352
|
+
}, 80);
|
|
2353
|
+
};
|
|
2354
|
+
const dropQuotaTab = (target, after) => {
|
|
2355
|
+
applyQuotaTabIndex(finalTabIndex(target, after));
|
|
2356
|
+
endTabDrag();
|
|
2357
|
+
};
|
|
2358
|
+
const onQuotaTabDragStart = (event) => {
|
|
2359
|
+
setTabDragging(true);
|
|
2360
|
+
event.dataTransfer.effectAllowed = "move";
|
|
2361
|
+
event.dataTransfer.setData("text/plain", "balance");
|
|
2362
|
+
};
|
|
2363
|
+
const onChipDragOver = (event, index) => {
|
|
2364
|
+
if (!tabDragging) return;
|
|
2365
|
+
event.preventDefault();
|
|
2366
|
+
event.stopPropagation();
|
|
2367
|
+
previewTabDropTarget(index);
|
|
2368
|
+
};
|
|
2369
|
+
const onChipDrop = (event, index) => {
|
|
2370
|
+
if (!tabDragging) return;
|
|
2371
|
+
event.preventDefault();
|
|
2372
|
+
event.stopPropagation();
|
|
2373
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
2374
|
+
dropQuotaTab(index, event.clientX > rect.left + rect.width / 2);
|
|
2375
|
+
};
|
|
2376
|
+
const onOrderDragOver = (event) => {
|
|
2377
|
+
if (!tabDragging) return;
|
|
2378
|
+
event.preventDefault();
|
|
2379
|
+
if (event.target === event.currentTarget) previewTabDropTarget(viewTabs.length - 1);
|
|
2380
|
+
};
|
|
2381
|
+
const onOrderDrop = (event) => {
|
|
2382
|
+
if (!tabDragging) return;
|
|
2383
|
+
event.preventDefault();
|
|
2384
|
+
if (event.target !== event.currentTarget) return;
|
|
2385
|
+
applyQuotaTabIndex(viewTabs.length - 1);
|
|
2386
|
+
endTabDrag();
|
|
2387
|
+
};
|
|
2388
|
+
const onQuotaTabKeyDown = (event) => {
|
|
2389
|
+
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
2390
|
+
event.preventDefault();
|
|
2391
|
+
applyQuotaTabIndex(balanceTabIndex + (event.key === "ArrowLeft" ? -1 : 1));
|
|
2392
|
+
};
|
|
2293
2393
|
const primary = balance !== null && balance.balances.length > 0 ? balance.balances[0] : null;
|
|
2294
2394
|
const recentDays = (usage?.daily ?? []).slice(-7);
|
|
2295
2395
|
const avgDailyCost = recentDays.length > 0 ? recentDays.reduce((sum, d) => sum + d.cost, 0) / recentDays.length : 0;
|
|
@@ -2300,6 +2400,26 @@ function BalanceDashboard(props) {
|
|
|
2300
2400
|
const runwayTitle = daysLeft === null ? t("balance.noRunway", { days: recentDays.length || 7 }) : t("balance.runwayTitle", { days: recentDays.length, cost: fmt(avgDailyCost) });
|
|
2301
2401
|
const activeWindow = usage?.windows.find((window2) => window2.days === windowDays) ?? null;
|
|
2302
2402
|
const activeWindowName = windowName(windowDays, t);
|
|
2403
|
+
const visionStats = activeWindow?.vision;
|
|
2404
|
+
const visionOpen = usage !== null && activeWindow !== null && visionStats !== void 0 && visionStats.images > 0 && Array.isArray(activeWindow.visionDaily) && Array.isArray(activeWindow.visionSessions);
|
|
2405
|
+
const visionPayload = (window2, stats, label) => ({
|
|
2406
|
+
vision: stats,
|
|
2407
|
+
daily: window2.visionDaily,
|
|
2408
|
+
sessions: window2.visionSessions,
|
|
2409
|
+
windowLabel: label,
|
|
2410
|
+
inputTokens: window2.totals.input,
|
|
2411
|
+
costTotal: window2.totals.cost
|
|
2412
|
+
});
|
|
2413
|
+
const liveVision = visionOpen && activeWindow !== null && visionStats !== void 0 ? visionPayload(activeWindow, visionStats, activeWindowName) : null;
|
|
2414
|
+
(0, import_react4.useEffect)(() => {
|
|
2415
|
+
if (visionOpen && activeWindow !== null && visionStats !== void 0) {
|
|
2416
|
+
setRetainedVision(visionPayload(activeWindow, visionStats, activeWindowName));
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
const timer = window.setTimeout(() => setRetainedVision(null), 320);
|
|
2420
|
+
return () => window.clearTimeout(timer);
|
|
2421
|
+
}, [visionOpen, activeWindow, activeWindowName]);
|
|
2422
|
+
const shownVision = visionOpen ? liveVision : retainedVision;
|
|
2303
2423
|
const dailyBars = (activeWindow?.daily ?? []).map((d) => ({
|
|
2304
2424
|
label: windowDays === 365 ? d.date.slice(5).replace("-", "/") : d.date.slice(8, 10),
|
|
2305
2425
|
value: chartMetricValue(chartMetric, d),
|
|
@@ -2524,34 +2644,6 @@ function BalanceDashboard(props) {
|
|
|
2524
2644
|
),
|
|
2525
2645
|
usage !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PricingNote, { pricing: usage.pricing })
|
|
2526
2646
|
] }),
|
|
2527
|
-
usage !== null && activeWindow !== null && activeWindow.vision !== void 0 && Array.isArray(activeWindow.visionDaily) && Array.isArray(activeWindow.visionSessions) ? (
|
|
2528
|
-
// 窗口内没有图片时整张卡不出现:一行「没有图片输入」不值得一个小节的位置。
|
|
2529
|
-
activeWindow.vision.images === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2530
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("vision.title") }),
|
|
2531
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2532
|
-
VisionCard,
|
|
2533
|
-
{
|
|
2534
|
-
vision: activeWindow.vision,
|
|
2535
|
-
daily: activeWindow.visionDaily,
|
|
2536
|
-
sessions: activeWindow.visionSessions,
|
|
2537
|
-
windowLabel: activeWindowName,
|
|
2538
|
-
inputTokens: activeWindow.totals.input,
|
|
2539
|
-
costTotal: activeWindow.totals.cost
|
|
2540
|
-
}
|
|
2541
|
-
)
|
|
2542
|
-
] })
|
|
2543
|
-
) : usage === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2544
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("vision.title") }),
|
|
2545
|
-
loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-usage-totals", children: [64, 88, 72].map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
|
|
2546
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w, h: 11 }),
|
|
2547
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 72, h: 20 })
|
|
2548
|
-
] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("vision.empty", { window: activeWindowName }) })
|
|
2549
|
-
] }) : (
|
|
2550
|
-
// Host serving a pre-vision payload (e.g. not restarted yet): hide the
|
|
2551
|
-
// whole card instead of leaving a titled shell — it reappears as soon
|
|
2552
|
-
// as the host half serves the new shape.
|
|
2553
|
-
null
|
|
2554
|
-
),
|
|
2555
2647
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card dq-card--primary", children: [
|
|
2556
2648
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card-head", children: [
|
|
2557
2649
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("usage.trendTitle") }),
|
|
@@ -2615,31 +2707,31 @@ function BalanceDashboard(props) {
|
|
|
2615
2707
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-legend-swatch", style: { background: s.color } }),
|
|
2616
2708
|
s.name
|
|
2617
2709
|
] }, s.key)) })
|
|
2618
|
-
] }) : barMode === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: dailyBars, height: 160, labelEvery: dailyLabelEvery, minWidth: dailyMinWidth }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: hourlyBars, height: 140, labelEvery: 3 })
|
|
2619
|
-
|
|
2620
|
-
|
|
2710
|
+
] }) : barMode === "daily" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: dailyBars, height: 160, labelEvery: dailyLabelEvery, minWidth: dailyMinWidth }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Bars, { data: hourlyBars, height: 140, labelEvery: 3 })
|
|
2711
|
+
] }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UsageSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("chart.empty") }),
|
|
2712
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-vision-inline", "data-open": visionOpen ? "true" : "false", "aria-hidden": !visionOpen, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-vision-inline-body", children: shownVision !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-chart-title", children: [
|
|
2714
|
+
t("vision.title"),
|
|
2715
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-chart-peak", children: shownVision.windowLabel })
|
|
2716
|
+
] }),
|
|
2717
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2718
|
+
VisionCard,
|
|
2719
|
+
{
|
|
2720
|
+
vision: shownVision.vision,
|
|
2721
|
+
daily: shownVision.daily,
|
|
2722
|
+
sessions: shownVision.sessions,
|
|
2723
|
+
windowLabel: shownVision.windowLabel,
|
|
2724
|
+
inputTokens: shownVision.inputTokens,
|
|
2725
|
+
costTotal: shownVision.costTotal
|
|
2726
|
+
}
|
|
2727
|
+
)
|
|
2728
|
+
] }) }) }),
|
|
2729
|
+
usage !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CoverageDiagnostics, { coverage: usage.coverage })
|
|
2621
2730
|
] }),
|
|
2622
2731
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2623
2732
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: t("chart.heatmapTitle"), children: t("heatmap.title") }),
|
|
2624
2733
|
usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Heatmap, { data: usage.heatmap }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HeatmapSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("chart.empty") })
|
|
2625
2734
|
] }),
|
|
2626
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2627
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("peak.title") }),
|
|
2628
|
-
usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeakCard, { split: usage.peakSplit, pricing: usage.pricing }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2629
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-peak-track" }),
|
|
2630
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-peak-figures", children: [
|
|
2631
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 120, h: 11 }),
|
|
2632
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 96, h: 20 })
|
|
2633
|
-
] })
|
|
2634
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("peak.empty") })
|
|
2635
|
-
] }),
|
|
2636
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2637
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("cache.title") }),
|
|
2638
|
-
usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CacheCard, { totals: usage.totals }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-cache-figures", children: [60, 96, 72].map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
|
|
2639
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w, h: 11 }),
|
|
2640
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 72, h: 20 })
|
|
2641
|
-
] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("cache.empty") })
|
|
2642
|
-
] }),
|
|
2643
2735
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2644
2736
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { caption: activeWindowName, children: t("models.title") }),
|
|
2645
2737
|
activeWindow !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ModelRanking, { models: modelList, totalCost: modelCostTotal, colorOf }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-rank", children: [0, 1].map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-rank-row", children: [
|
|
@@ -2656,6 +2748,25 @@ function BalanceDashboard(props) {
|
|
|
2656
2748
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 250, h: 11 })
|
|
2657
2749
|
] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("sessions.empty") })
|
|
2658
2750
|
] }),
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card-pair", children: [
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2753
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("peak.title") }),
|
|
2754
|
+
usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeakCard, { split: usage.peakSplit, pricing: usage.pricing }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-peak-track" }),
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-peak-figures", children: [
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 120, h: 11 }),
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 96, h: 20 })
|
|
2759
|
+
] })
|
|
2760
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("peak.empty") })
|
|
2761
|
+
] }),
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("cache.title") }),
|
|
2764
|
+
usage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CacheCard, { totals: usage.totals }) : loadingUsage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-cache-figures", children: [60, 96, 72].map((w, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-stat", children: [
|
|
2765
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w, h: 11 }),
|
|
2766
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Skel, { w: 72, h: 20 })
|
|
2767
|
+
] }, i)) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-empty", children: t("cache.empty") })
|
|
2768
|
+
] })
|
|
2769
|
+
] }),
|
|
2659
2770
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-card", children: [
|
|
2660
2771
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CardTitle, { children: t("settings.title") }),
|
|
2661
2772
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-links-title", children: t("links.title") }),
|
|
@@ -2723,9 +2834,67 @@ function BalanceDashboard(props) {
|
|
|
2723
2834
|
),
|
|
2724
2835
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { id: "dq-monthly-budget-hint", className: "dq-setting-hint", children: monthlyBudget > 0 ? t("settings.monthlyBudgetOn", { amount: fmt(monthlyBudget) }) : t("settings.monthlyBudgetOff") })
|
|
2725
2836
|
] })
|
|
2837
|
+
] }),
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-setting", children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { className: "dq-setting-label", htmlFor: "dq-sidebar-entry", children: t("settings.sidebarEntry") }),
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-setting-control", children: [
|
|
2841
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2842
|
+
"select",
|
|
2843
|
+
{
|
|
2844
|
+
id: "dq-sidebar-entry",
|
|
2845
|
+
className: "dq-select",
|
|
2846
|
+
value: sidebarEntry,
|
|
2847
|
+
onChange: (e) => changeSidebarEntry(e.target.value),
|
|
2848
|
+
children: [
|
|
2849
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "off", children: t("settings.sidebarEntryOff") }),
|
|
2850
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "top", children: t("settings.sidebarEntryTop") }),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "bottom", children: t("settings.sidebarEntryBottom") })
|
|
2852
|
+
]
|
|
2853
|
+
}
|
|
2854
|
+
),
|
|
2855
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dq-setting-hint", children: t("settings.sidebarEntryHint") })
|
|
2856
|
+
] })
|
|
2857
|
+
] }),
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-setting", children: [
|
|
2859
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "dq-setting-label", id: "dq-tab-order-label", children: t("settings.tabPosition") }),
|
|
2860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dq-setting-control", children: [
|
|
2861
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2862
|
+
"div",
|
|
2863
|
+
{
|
|
2864
|
+
className: "dq-tab-order",
|
|
2865
|
+
role: "group",
|
|
2866
|
+
"aria-labelledby": "dq-tab-order-label",
|
|
2867
|
+
"aria-describedby": "dq-tab-order-hint",
|
|
2868
|
+
onDragOver: onOrderDragOver,
|
|
2869
|
+
onDrop: onOrderDrop,
|
|
2870
|
+
children: viewTabs.map((tab, index) => {
|
|
2871
|
+
const current = tab.id === "balance";
|
|
2872
|
+
const dropTarget = tabDragging && !current && tabDropTarget === index;
|
|
2873
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2874
|
+
"span",
|
|
2875
|
+
{
|
|
2876
|
+
className: `dq-tab-chip${current ? " dq-tab-chip--current" : ""}${current && tabDragging ? " dq-tab-chip--dragging" : ""}${dropTarget ? " dq-tab-chip--drop-target" : ""}`,
|
|
2877
|
+
draggable: current,
|
|
2878
|
+
tabIndex: current ? 0 : void 0,
|
|
2879
|
+
role: current ? "button" : void 0,
|
|
2880
|
+
"aria-label": current ? t("settings.tabDragAria") : void 0,
|
|
2881
|
+
onDragStart: current ? onQuotaTabDragStart : void 0,
|
|
2882
|
+
onDragEnd: current ? endTabDrag : void 0,
|
|
2883
|
+
onDragOver: (event) => onChipDragOver(event, index),
|
|
2884
|
+
onDrop: (event) => onChipDrop(event, index),
|
|
2885
|
+
onKeyDown: current ? onQuotaTabKeyDown : void 0,
|
|
2886
|
+
children: tab.label
|
|
2887
|
+
},
|
|
2888
|
+
tab.id
|
|
2889
|
+
);
|
|
2890
|
+
})
|
|
2891
|
+
}
|
|
2892
|
+
),
|
|
2893
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { id: "dq-tab-order-hint", className: "dq-setting-hint", children: t("settings.tabPositionHint") })
|
|
2894
|
+
] })
|
|
2726
2895
|
] })
|
|
2727
2896
|
] }),
|
|
2728
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dq-footer", children: "@cassius0924/dsh-usage-dashboard v0.8.0" })
|
|
2729
2898
|
] });
|
|
2730
2899
|
}
|
|
2731
2900
|
|
|
@@ -2822,10 +2991,10 @@ var css = `
|
|
|
2822
2991
|
the input box \u2014 measured in dashboard.tsx as --dq-composer-w, capped at
|
|
2823
2992
|
the reading-column width so wide viewports are unchanged. */
|
|
2824
2993
|
.dq-balance{-webkit-text-size-adjust:100%;text-size-adjust:100%;box-sizing:border-box;width:100%;min-width:0;display:flex;flex-direction:column;gap:32px;padding:20px 24px 48px;max-width:min(860px,var(--dq-composer-w,860px));margin:0 auto;font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Helvetica Neue",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.5;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary,#1f2328);--dq-text-success:#1a7f37;--dq-text-success:color-mix(in oklab,var(--dsw-alias-state-success-primary,#2da44e) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);--dq-text-warn:#9a6700;--dq-text-warn:color-mix(in oklab,var(--dsw-alias-state-warn-primary,#bf8700) 52%,var(--dsw-alias-label-primary,#1f2328) 48%);}
|
|
2825
|
-
@media (max-width:620px){.dq-balance{max-width:100%;gap:24px;padding:16px 12px calc(var(--dq-composer-h,126px) + 16px)}.dq-card
|
|
2994
|
+
@media (max-width:620px){.dq-balance{max-width:100%;gap:24px;padding:16px 12px calc(var(--dq-composer-h,126px) + 16px)}.dq-card{padding:16px}.dq-card--hero{padding:0 16px}.dq-status-row{padding:0 16px}}
|
|
2826
2995
|
/* \u8F6E\u6B21 55\uFF1A\u53EA\u6709\u4E3B\u5361\u7247\u5E26\u6846\u3002\u6B21\u7EA7\u5206\u6790\u4E0E\u8BBE\u7F6E\u662F\u65E0\u6846\u5C0F\u8282\uFF0C\u9760 32px \u6BB5\u8DDD\u548C 13px \u4E3B\u8272\u6807\u9898\u5206\u7EC4\uFF1B
|
|
2827
2996
|
\u5DE6\u53F3 20px \u5185\u8FB9\u8DDD\u8BA9\u5B83\u4EEC\u7684\u6587\u5B57\u8FB9\u4E0E\u4E3B\u5361\u7247\u5185\u6587\u5BF9\u9F50\uFF0C\u6574\u9875\u53EA\u6709\u4E00\u6761\u6587\u5B57\u5DE6\u8FB9\u7EBF\u3002 */
|
|
2828
|
-
.dq-card{box-sizing:border-box;min-width:0;max-width:100%;padding:0
|
|
2997
|
+
.dq-card{box-sizing:border-box;min-width:0;max-width:100%;padding:20px;background:var(--dsw-alias-bg-layer-1,#ffffff);border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.10));border-radius:12px}
|
|
2829
2998
|
.dq-card-title{display:flex;align-items:baseline;flex-wrap:wrap;gap:4px 8px;font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary,#1f2328);margin:0 0 16px;letter-spacing:0;text-wrap:balance}
|
|
2830
2999
|
.dq-card-caption{font-size:12px;font-weight:400;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
2831
3000
|
.dq-card-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}
|
|
@@ -2839,9 +3008,10 @@ var css = `
|
|
|
2839
3008
|
\u6253\u5F00\u8FD9\u4E2A\u300C\u989D\u5EA6\u300Dtab \u65F6\u4E0A\u4E0B\u6587\u6700\u76F4\u63A5\u76F8\u5173\u7684\u6570\u5B57\uFF08\u8FD9\u4E2A tab \u6302\u5728\u5177\u4F53\u4F1A\u8BDD\u5185\u90E8\uFF0C\u89C1 DESIGN_NOTES\u300C\u4FE1\u606F\u5C42\u7EA7\u300D\uFF09\uFF0C
|
|
2840
3009
|
\u4E0D\u5C5E\u4E8E\u539F\u6709\u8D26\u6237\u5168\u5C40\u5C42\u7EA7 1-3 \u7684\u4EFB\u4F55\u4E00\u7EA7\uFF0C\u800C\u662F\u4E0E\u4E4B\u6B63\u4EA4\u7684\u53E6\u4E00\u4E2A\u7EF4\u5EA6\uFF0C\u4F46\u540C\u6837\u662F\u9996\u5C4F\u5FC5\u8BFB\uFF0C\u56E0\u6B64\u540C\u6837\u7ED9
|
|
2841
3010
|
primary \u6743\u91CD\uFF0C\u4E0D\u65B0\u5F00\u7B2C\u4E09\u6863\u3002 */
|
|
2842
|
-
.dq-card--primary{padding:20px;
|
|
3011
|
+
.dq-card--primary{padding:20px;border-color:var(--dsw-alias-border-l3,rgba(0,0,0,.12))}
|
|
2843
3012
|
/* \u4F59\u989D\u662F\u6574\u9875\u552F\u4E00\u7684 hero\uFF1A\u4E0D\u5957\u6846\uFF0C32px \u6570\u5B57\u72EC\u5360\u4E00\u6863\uFF0C\u8BA9\u5B83\u5728\u906E\u4F4F\u6587\u5B57\u65F6\u4ECD\u662F\u7B2C\u4E00\u773C\u3002 */
|
|
2844
|
-
.dq-card--hero{padding:0 20px}
|
|
3013
|
+
.dq-card--hero{padding:0 20px;background:transparent;border:0;border-radius:0}
|
|
3014
|
+
.dq-card-pair{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));gap:24px;min-width:0}
|
|
2845
3015
|
.dq-card--hero .dq-stat-label{font-size:13px;margin-bottom:2px}
|
|
2846
3016
|
.dq-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
|
|
2847
3017
|
.dq-card--hero .dq-balance-grid{align-items:stretch;gap:12px 48px}
|
|
@@ -2849,6 +3019,7 @@ var css = `
|
|
|
2849
3019
|
/* hero \u6570\u5B57\u4E0D\u753B\u70B9\u72B6\u4E0B\u5212\u7EBF\uFF0840px \u4E0B\u592A\u91CD\uFF09\uFF1B\u53EF\u70B9\u6027\u9760\u60AC\u505C\u5E95\u8272\u548C title \u63D0\u793A\u3002 */
|
|
2850
3020
|
.dq-card--hero details>summary{text-decoration:none;margin:-2px -6px;padding:2px 6px;border-radius:8px;transition:background .15s ease}
|
|
2851
3021
|
.dq-card--hero details>summary:hover,.dq-card--hero details[open]>summary{background:var(--dsw-alias-bg-layer-2,rgba(0,0,0,.05))}
|
|
3022
|
+
@media (max-width:620px){.dq-card{padding:16px}.dq-card--hero{padding:0 16px}}
|
|
2852
3023
|
.dq-window-switch{display:inline-flex;align-items:center;gap:2px;padding:2px;border-radius:8px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.08))}
|
|
2853
3024
|
.dq-window-btn{border:0;border-radius:6px;padding:4px 8px;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;white-space:nowrap;cursor:pointer;transition:background .15s ease,color .15s ease,box-shadow .15s ease}
|
|
2854
3025
|
.dq-window-btn:hover{color:var(--dsw-alias-label-primary,#1f2328)}
|
|
@@ -2993,7 +3164,6 @@ var css = `
|
|
|
2993
3164
|
.dq-peak-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-top:16px}
|
|
2994
3165
|
.dq-peak-delta{font-size:12px;font-weight:500;margin-left:8px;color:var(--dq-text-warn)}
|
|
2995
3166
|
.dq-peak-delta--save{color:var(--dq-text-success)}
|
|
2996
|
-
.dq-peak-foot{margin:12px 0 0;font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#59636e);text-wrap:pretty}
|
|
2997
3167
|
.dq-cache-figures{display:flex;flex-wrap:wrap;gap:12px 32px;margin-bottom:12px}
|
|
2998
3168
|
@media (max-width:620px){.dq-cache-figures{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 16px}.dq-cache-figures .dq-stat{min-width:0}}
|
|
2999
3169
|
.dq-muted-value{color:var(--dsw-alias-label-secondary,#59636e)!important;font-weight:500}
|
|
@@ -3198,6 +3368,77 @@ var css = `
|
|
|
3198
3368
|
.dq-refresh-icon{display:inline-block;line-height:1}
|
|
3199
3369
|
.dq-refresh-icon--spin{animation:dq-spin .9s linear infinite}
|
|
3200
3370
|
@keyframes dq-spin{to{transform:rotate(360deg)}}
|
|
3371
|
+
/* ============================================================================
|
|
3372
|
+
Host chrome: the \u300C\u989D\u5EA6\u300Dconversation view does not use the chat composer.
|
|
3373
|
+
The attribute is set by index.tsx only when the dashboard is mounted inside
|
|
3374
|
+
the conversation scrollport, so the account-wide panel never hides it.
|
|
3375
|
+
'!important' because the composer's slot anchor is a "display:contents"
|
|
3376
|
+
wrapper whose display we must beat regardless of host rule order.
|
|
3377
|
+
============================================================================ */
|
|
3378
|
+
html[data-dq-quota-view] [data-slot="conversation.composer"]{display:none!important}
|
|
3379
|
+
/* The narrow-viewport rule pads for the fixed composer; with it hidden there
|
|
3380
|
+
is nothing to clear, so fall back to the page's own bottom breathing room. */
|
|
3381
|
+
html[data-dq-quota-view] .dq-balance{padding-bottom:48px}
|
|
3382
|
+
/* ============================================================================
|
|
3383
|
+
Account-wide \u300C\u989D\u5EA6\u300Dpanel (the optional sidebar entry opens this main
|
|
3384
|
+
keyed panel). The dashboard keeps its own width/padding; the panel only
|
|
3385
|
+
supplies the page title row and the scrolling box the main column lacks.
|
|
3386
|
+
============================================================================ */
|
|
3387
|
+
/* Account-wide page frame: mirrors DSH's first-level pages (Plugins /
|
|
3388
|
+
Scheduled tasks) \u2014 full-height scroll box, 28px top inset on the heading,
|
|
3389
|
+
a 960px centred column, clamp(24px,4vw,48px) inline + 48px bottom insets and
|
|
3390
|
+
a 20px/28px/500 page title, so the three sibling entries line up. */
|
|
3391
|
+
.dq-panel{box-sizing:border-box;height:100%;min-height:0;overflow-y:auto;overflow-x:hidden;padding:0 clamp(24px,4vw,48px) 48px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-family:var(--dsw-font-family,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei","Helvetica Neue",Helvetica,Arial,sans-serif);font-size:13px;line-height:1.5}
|
|
3392
|
+
.dq-panel-head{box-sizing:border-box;display:flex;flex-direction:column;align-items:flex-start;gap:4px;width:100%;max-width:960px;margin:0 auto 32px;padding-top:28px}
|
|
3393
|
+
.dq-panel-title{margin:0;font-size:20px;font-weight:500;line-height:28px;color:var(--dsw-alias-label-primary,#1f2328)}
|
|
3394
|
+
.dq-panel-caption{font-size:13px;line-height:20px;color:var(--dsw-alias-label-secondary,#59636e)}
|
|
3395
|
+
.dq-panel .dq-balance{box-sizing:border-box;width:100%;max-width:960px;padding:0}
|
|
3396
|
+
/* macOS hiddenInset titlebar: the frame's top clearance keeps the heading
|
|
3397
|
+
below the window's top strip, matching the host's sibling pages. */
|
|
3398
|
+
[data-platform="darwin"] .dq-panel-head{padding-top:calc(28px + var(--dsh-frame-top-clearance,0px))}
|
|
3399
|
+
@media (max-width:620px){
|
|
3400
|
+
.dq-panel-head{padding-top:24px;margin-bottom:24px}
|
|
3401
|
+
.dq-panel .dq-balance{max-width:100%;padding:0}
|
|
3402
|
+
}
|
|
3403
|
+
/* Optional sidebar entry. Top placement joins the host's global-panel icon
|
|
3404
|
+
row (only the glyph is ours); bottom placement renders a row beside
|
|
3405
|
+
Settings, collapsing to a square rail button with the sidebar. */
|
|
3406
|
+
/* The glyph is an SVG matching the host's 16px stroke icons; color inherits
|
|
3407
|
+
from the sidebar row so selected/hover states stay the host's business. */
|
|
3408
|
+
.dq-side-icon{flex:none;display:block}
|
|
3409
|
+
.dq-side-entry{display:flex;align-items:center;gap:8px;box-sizing:border-box;width:100%;border:0;border-radius:8px;padding:7px 8px;background:transparent;color:var(--dsw-alias-label-secondary,#59636e);font:inherit;font-size:13px;line-height:1.3;text-align:left;cursor:pointer}
|
|
3410
|
+
.dq-side-entry:hover{background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.10));color:var(--dsw-alias-label-primary,#1f2328)}
|
|
3411
|
+
.dq-side-entry:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}
|
|
3412
|
+
.dq-side-entry[aria-pressed="true"]{color:var(--dsw-alias-label-primary,#1f2328)}
|
|
3413
|
+
.dq-side-entry--rail{justify-content:center;width:32px;height:32px;margin:0 auto;padding:0}
|
|
3414
|
+
.dq-side-entry-icon{flex:none;display:inline-flex;align-items:center;justify-content:center}
|
|
3415
|
+
.dq-side-entry-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
3416
|
+
/* ============================================================================
|
|
3417
|
+
Settings controls for the two layout preferences: a compact select and the
|
|
3418
|
+
draggable tab-order strip.
|
|
3419
|
+
============================================================================ */
|
|
3420
|
+
.dq-select{font:inherit;font-size:13px;line-height:1.3;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,rgba(0,0,0,.16));border-radius:8px;padding:5px 8px;min-width:96px;cursor:pointer}
|
|
3421
|
+
.dq-select:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}
|
|
3422
|
+
.dq-tab-order{display:flex;flex-wrap:wrap;align-items:center;gap:6px;box-sizing:border-box;max-width:100%;min-height:32px;padding:4px;border:1px dashed var(--dsw-alias-border-l2,rgba(0,0,0,.16));border-radius:8px;background:var(--dsw-alias-bg-layer-2,rgba(120,130,150,.06))}
|
|
3423
|
+
.dq-tab-chip{display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border:1px solid var(--dsw-alias-border-l1,rgba(0,0,0,.08));border-radius:999px;background:var(--dsw-alias-bg-overlay,#fff);color:var(--dsw-alias-label-secondary,#59636e);font-size:12px;line-height:1.4;white-space:nowrap}
|
|
3424
|
+
.dq-tab-chip--current{cursor:grab;color:var(--dsw-alias-label-primary,#1f2328);border-color:var(--dsw-alias-state-business-primary,#0969da);font-weight:600;user-select:none;-webkit-user-select:none;touch-action:none}
|
|
3425
|
+
.dq-tab-chip--current:active{cursor:grabbing}
|
|
3426
|
+
.dq-tab-chip--current:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#0969da);outline-offset:1px}
|
|
3427
|
+
.dq-tab-chip--dragging{opacity:.55}
|
|
3428
|
+
.dq-tab-chip--drop-target{border-style:dashed;border-color:var(--dsw-alias-state-business-primary,#0969da)}
|
|
3429
|
+
/* ============================================================================
|
|
3430
|
+
\u300C\u56FE\u7247 / \u591A\u6A21\u6001\u7528\u91CF\u300Dlives inside the usage-trend card. The grid-rows 0fr\u21921fr
|
|
3431
|
+
trick animates the section's real height as a window range makes it appear
|
|
3432
|
+
or disappear; opacity/translate make the change read as a reveal rather
|
|
3433
|
+
than a reflow. The body keeps 14px of top room in both states (clipped by
|
|
3434
|
+
the 0fr row when closed) so opening never jumps.
|
|
3435
|
+
============================================================================ */
|
|
3436
|
+
.dq-vision-inline{display:grid;grid-template-rows:0fr;margin-top:0;opacity:0;transform:translateY(-3px);overflow:hidden;transition:grid-template-rows .32s cubic-bezier(.22,1,.36,1),margin-top .32s cubic-bezier(.22,1,.36,1),opacity .2s ease,transform .32s cubic-bezier(.22,1,.36,1)}
|
|
3437
|
+
.dq-vision-inline[data-open="true"]{grid-template-rows:1fr;margin-top:24px;opacity:1;transform:none}
|
|
3438
|
+
.dq-vision-inline-body{min-height:0;overflow:hidden}
|
|
3439
|
+
.dq-vision-inline-body>.dq-chart-title{margin-top:0}
|
|
3440
|
+
.dq-vision-inline-body>.dq-chart-title{margin-top:0}
|
|
3441
|
+
|
|
3201
3442
|
@media (prefers-reduced-motion:reduce){
|
|
3202
3443
|
.dsh-quota-root,.dsh-quota-root *,
|
|
3203
3444
|
.dsh-quota-root *::before,.dsh-quota-root *::after,
|
|
@@ -3619,7 +3860,8 @@ function conversationViewsSource(slots) {
|
|
|
3619
3860
|
// src/client/index.tsx
|
|
3620
3861
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
3621
3862
|
var name = "dsh-usage-dashboard";
|
|
3622
|
-
var inject = ["slots", "locale"];
|
|
3863
|
+
var inject = ["slots", "locale", "layout"];
|
|
3864
|
+
var openQuotaTab = null;
|
|
3623
3865
|
function apply(ctx) {
|
|
3624
3866
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-usage-dashboard: browser dictionaries");
|
|
3625
3867
|
const t = ctx.locale.bind(NS);
|
|
@@ -3649,17 +3891,153 @@ function apply(ctx) {
|
|
|
3649
3891
|
},
|
|
3650
3892
|
({ t: slotT, sessionId, messageId }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, silent: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessageCost, { sessionId, messageId }) }) })
|
|
3651
3893
|
));
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3894
|
+
const QuotaView = ({ t: slotT, sessionId, openView }) => {
|
|
3895
|
+
(0, import_react7.useEffect)(() => {
|
|
3896
|
+
if (openView !== void 0) openQuotaTab = openView;
|
|
3897
|
+
}, [openView]);
|
|
3898
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BalanceDashboard, { sessionId, views }) }) });
|
|
3899
|
+
};
|
|
3900
|
+
ctx.effect(() => {
|
|
3901
|
+
let disposeView = null;
|
|
3902
|
+
const mount = () => {
|
|
3903
|
+
disposeView?.();
|
|
3904
|
+
disposeView = ctx.slots.inject("conversation.view", () => ctx.slots.register(
|
|
3905
|
+
{
|
|
3906
|
+
name: "conversation.view",
|
|
3907
|
+
id: "balance",
|
|
3908
|
+
order: viewOrderForIndex(ctx.slots.entries("conversation.view"), quotaTabIndexStore.get()),
|
|
3909
|
+
locale: NS,
|
|
3910
|
+
label: () => t("nav.quota")
|
|
3911
|
+
},
|
|
3912
|
+
// `conversation.view` is a session-scoped slot, so the host injects its
|
|
3913
|
+
// standard session props (including `sessionId`) alongside `t`; only the
|
|
3914
|
+
// fields this plugin needs are destructured, per the existing
|
|
3915
|
+
// "hand-write the minimal structural type" convention (see context.ts).
|
|
3916
|
+
// `sessionId` stays optional: BalanceDashboard renders the current-
|
|
3917
|
+
// session card only when it actually has one, never throws either way.
|
|
3918
|
+
QuotaView
|
|
3919
|
+
));
|
|
3920
|
+
};
|
|
3921
|
+
mount();
|
|
3922
|
+
const unsubscribe = quotaTabIndexStore.subscribe(() => {
|
|
3923
|
+
const restore = document !== void 0 && document.documentElement.hasAttribute("data-dq-quota-view");
|
|
3924
|
+
disposeView?.();
|
|
3925
|
+
disposeView = null;
|
|
3926
|
+
mount();
|
|
3927
|
+
if (restore) queueMicrotask(() => openQuotaTab?.("balance", "dsh-usage-dashboard:tab-order"));
|
|
3928
|
+
});
|
|
3929
|
+
return () => {
|
|
3930
|
+
unsubscribe();
|
|
3931
|
+
disposeView?.();
|
|
3932
|
+
};
|
|
3933
|
+
}, "dsh-usage-dashboard: quota tab registration");
|
|
3934
|
+
const QuotaPanel = ({ t: slotT }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dq-panel", children: [
|
|
3935
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "dq-panel-head", "data-window-drag": true, children: [
|
|
3936
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: "dq-panel-title", children: slotT("nav.quota") }),
|
|
3937
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-panel-caption", children: slotT("panel.caption") })
|
|
3938
|
+
] }),
|
|
3939
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LocaleProvider, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ErrorBoundary, { t: slotT, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BalanceDashboard, { views }) }) })
|
|
3940
|
+
] });
|
|
3941
|
+
const QuotaGlyph = ({ size, active }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3942
|
+
"svg",
|
|
3943
|
+
{
|
|
3944
|
+
className: "dq-side-icon",
|
|
3945
|
+
"data-active": active === true ? "true" : "false",
|
|
3946
|
+
width: size,
|
|
3947
|
+
height: size,
|
|
3948
|
+
viewBox: "0 0 16 16",
|
|
3949
|
+
fill: "none",
|
|
3950
|
+
stroke: "currentColor",
|
|
3951
|
+
strokeWidth: 1.1,
|
|
3952
|
+
strokeLinecap: "round",
|
|
3953
|
+
strokeLinejoin: "round",
|
|
3954
|
+
"aria-hidden": "true",
|
|
3955
|
+
focusable: "false",
|
|
3956
|
+
children: [
|
|
3957
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 3.3 8 8.7l4.5-5.4" }),
|
|
3958
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M8 8.7V13.2" }),
|
|
3959
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 10.2h9" }),
|
|
3960
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3.5 12.1h9" })
|
|
3961
|
+
]
|
|
3962
|
+
}
|
|
3963
|
+
);
|
|
3964
|
+
const QuotaFooterButton = ({ wide, t: slotT }) => {
|
|
3965
|
+
const [active, setActive] = (0, import_react7.useState)(() => ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID);
|
|
3966
|
+
(0, import_react7.useEffect)(() => {
|
|
3967
|
+
const sync = () => {
|
|
3968
|
+
setActive(ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID);
|
|
3969
|
+
};
|
|
3970
|
+
sync();
|
|
3971
|
+
return ctx.layout.panelInfo.subscribe(sync);
|
|
3972
|
+
}, []);
|
|
3973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
3974
|
+
"button",
|
|
3975
|
+
{
|
|
3976
|
+
type: "button",
|
|
3977
|
+
className: `dq-side-entry${wide ? "" : " dq-side-entry--rail"}`,
|
|
3978
|
+
title: slotT("panel.openAria"),
|
|
3979
|
+
"aria-label": slotT("nav.quota"),
|
|
3980
|
+
"aria-pressed": active,
|
|
3981
|
+
onClick: () => {
|
|
3982
|
+
ctx.layout.selectPanel(active ? null : QUOTA_PANEL_ID);
|
|
3983
|
+
},
|
|
3984
|
+
children: [
|
|
3985
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-side-entry-icon", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QuotaGlyph, { size: 16 }) }),
|
|
3986
|
+
wide && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "dq-side-entry-label", children: slotT("nav.quota") })
|
|
3987
|
+
]
|
|
3988
|
+
}
|
|
3989
|
+
);
|
|
3990
|
+
};
|
|
3991
|
+
ctx.effect(() => ctx.slots.inject("main", () => ctx.slots.register(
|
|
3992
|
+
{ name: "main", key: QUOTA_PANEL_ID, locale: NS },
|
|
3993
|
+
QuotaPanel
|
|
3994
|
+
)), "dsh-usage-dashboard: quota panel");
|
|
3995
|
+
ctx.effect(() => {
|
|
3996
|
+
let disposeEntry = null;
|
|
3997
|
+
const sync = () => {
|
|
3998
|
+
disposeEntry?.();
|
|
3999
|
+
disposeEntry = null;
|
|
4000
|
+
const placement = sidebarEntryStore.get();
|
|
4001
|
+
if (placement === "top") {
|
|
4002
|
+
disposeEntry = ctx.slots.inject("sidebar.panellist", () => ctx.slots.register(
|
|
4003
|
+
{ name: "sidebar.panellist", id: QUOTA_PANEL_ID, order: 1e3, label: () => t("nav.quota"), locale: NS },
|
|
4004
|
+
QuotaGlyph
|
|
4005
|
+
));
|
|
4006
|
+
return;
|
|
4007
|
+
}
|
|
4008
|
+
if (placement === "bottom") {
|
|
4009
|
+
disposeEntry = ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register(
|
|
4010
|
+
{ name: "sidebar.footer.action", id: "quota", order: 10, locale: NS },
|
|
4011
|
+
QuotaFooterButton
|
|
4012
|
+
));
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4015
|
+
if (ctx.layout.panelInfo.getSnapshot().activePanelId === QUOTA_PANEL_ID) ctx.layout.selectPanel(null);
|
|
4016
|
+
};
|
|
4017
|
+
sync();
|
|
4018
|
+
const unsubscribe = sidebarEntryStore.subscribe(sync);
|
|
4019
|
+
return () => {
|
|
4020
|
+
unsubscribe();
|
|
4021
|
+
disposeEntry?.();
|
|
4022
|
+
};
|
|
4023
|
+
}, "dsh-usage-dashboard: sidebar entry");
|
|
4024
|
+
ctx.effect(() => {
|
|
4025
|
+
let applied = false;
|
|
4026
|
+
const sync = () => {
|
|
4027
|
+
const root = document.querySelector(".dq-balance");
|
|
4028
|
+
const should = quotaViewActiveStore.get() && root !== null && root.closest("[data-conversation-scroll]") !== null;
|
|
4029
|
+
if (should === applied) return;
|
|
4030
|
+
applied = should;
|
|
4031
|
+
if (should) document.documentElement.setAttribute("data-dq-quota-view", "");
|
|
4032
|
+
else document.documentElement.removeAttribute("data-dq-quota-view");
|
|
4033
|
+
};
|
|
4034
|
+
sync();
|
|
4035
|
+
const unsubscribe = quotaViewActiveStore.subscribe(sync);
|
|
4036
|
+
return () => {
|
|
4037
|
+
unsubscribe();
|
|
4038
|
+
if (applied) document.documentElement.removeAttribute("data-dq-quota-view");
|
|
4039
|
+
};
|
|
4040
|
+
}, "dsh-usage-dashboard: composer visibility");
|
|
3663
4041
|
}
|
|
3664
4042
|
return module.exports; } });
|
|
3665
4043
|
//# sourceMappingURL=client.js.map
|