@goodandready/dsh-subscriptions 0.6.71 โ 0.6.82
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 +13 -0
- package/README.ru.md +13 -0
- package/README.zh.md +13 -0
- package/lib/accounts-view.js +101 -5
- package/lib/accounts.js +150 -11
- package/lib/adapter.js +3 -0
- package/lib/alerts.js +35 -0
- package/lib/analytics.js +31 -2
- package/lib/billing.js +99 -0
- package/lib/blob.js +18 -0
- package/lib/capabilities.js +208 -0
- package/lib/client.js +944 -828
- package/lib/config-schema.js +46 -4
- package/lib/diagnostic-wizard.js +2 -5
- package/lib/diagnostics.js +2 -2
- package/lib/doctor.js +163 -0
- package/lib/error-buffer.js +2 -2
- package/lib/forecast.js +56 -0
- package/lib/headless-auth.js +379 -0
- package/lib/history.js +36 -0
- package/lib/http.js +26 -4
- package/lib/index.js +98 -11
- package/lib/instructions.js +138 -0
- package/lib/jwt.js +84 -17
- package/lib/loopback.js +3 -2
- package/lib/mask.js +16 -0
- package/lib/oauth-pending.js +12 -0
- package/lib/pricing.js +89 -0
- package/lib/refs.js +2 -0
- package/lib/reset-clock.js +55 -0
- package/lib/rotate.js +18 -4
- package/lib/routes/accounts.js +203 -0
- package/lib/routes/oauth.js +44 -2
- package/lib/routes/proxy.js +14 -0
- package/lib/routes/status.js +99 -5
- package/lib/scope-inspector.js +51 -0
- package/lib/stream-rotate.js +31 -10
- package/lib/updater.js +21 -0
- package/lib/vault-sync.js +412 -0
- package/lib/vault.js +1 -1
- package/lib/vendor-factory.js +6 -2
- package/lib/vendors/antigravity.js +11 -2
- package/lib/vendors/claude.js +56 -8
- package/lib/vendors/codex.js +34 -6
- package/lib/vendors/copilot-cli.js +8 -1
- package/lib/vendors/ernie.js +9 -2
- package/lib/vendors/grok.js +66 -6
- package/lib/vendors/jetbrains.js +133 -13
- package/lib/vendors/perplexity.js +148 -17
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -4,6 +4,7 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} }
|
|
5
5
|
var exports = module.exports
|
|
6
6
|
const React = require('react')
|
|
7
|
+
const h = React.createElement
|
|
7
8
|
|
|
8
9
|
// Modular translator: shared by component subscriptions and helpers.
|
|
9
10
|
let t = (key) => key
|
|
@@ -22,12 +23,12 @@ window.__ModuleLoader__.load({
|
|
|
22
23
|
}
|
|
23
24
|
render() {
|
|
24
25
|
if (this.state.hasError) {
|
|
25
|
-
return
|
|
26
|
+
return h(
|
|
26
27
|
"div",
|
|
27
28
|
{ style: { padding: "12px", border: "1px solid var(--dsw-alias-state-error-primary)", borderRadius: "8px", background: "var(--dsw-alias-bg-layer-2)", margin: "8px 0", fontSize: "13px" } },
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
h("div", { style: { fontWeight: 600, color: "var(--dsw-alias-state-error-primary)", marginBottom: "4px" } }, "Subscriptions UI error"),
|
|
30
|
+
h("div", { style: { color: "var(--dsw-alias-label-secondary)", fontSize: "12px", marginBottom: "8px" } }, String(this.state.error && this.state.error.message || this.state.error || "Unknown error")),
|
|
31
|
+
h("button", {
|
|
31
32
|
className: "dsub-mini",
|
|
32
33
|
onClick: () => this.setState({ hasError: false, error: null })
|
|
33
34
|
}, "Retry")
|
|
@@ -39,168 +40,8 @@ window.__ModuleLoader__.load({
|
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
const CSS =
|
|
42
|
-
'.dsub-card{list-style:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;transition:border-color .16s,background .16s}' +
|
|
43
|
-
'.
|
|
44
|
-
'.dsub-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}' +
|
|
45
|
-
'.dsub-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}' +
|
|
46
|
-
'.dsub-header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}' +
|
|
47
|
-
'.dsub-headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}' +
|
|
48
|
-
'.dsub-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}' +
|
|
49
|
-
'.dsub-description{color:var(--dsw-alias-label-secondary);font-size:13px}' +
|
|
50
|
-
'.dsub-chev{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}' +
|
|
51
|
-
'.dsub-chevOpen{transform:rotate(180deg)}' +
|
|
52
|
-
'.dsub-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:12px}' +
|
|
53
|
-
'.dsub-block{margin-top:10px}' +
|
|
54
|
-
'.dsub-group{margin-top:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:0 14px}' +
|
|
55
|
-
'.dsub-group[open]{padding-bottom:6px}' +
|
|
56
|
-
'.dsub-groupHead{cursor:pointer;font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);padding:10px 0;list-style:none}' +
|
|
57
|
-
'.dsub-groupHead::-webkit-details-marker{display:none}' +
|
|
58
|
-
'.dsub-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:8px}' +
|
|
59
|
-
'.dsub-grow{flex:1 1 180px;min-width:140px}' +
|
|
60
|
-
'.dsub-helpBox{margin-top:8px;padding:12px 14px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font-size:12px;line-height:1.6}' +
|
|
61
|
-
'.dsub-helpHead{display:flex;align-items:center;justify-content:space-between;font-weight:600;margin-bottom:8px;color:var(--dsw-alias-brand-primary)}' +
|
|
62
|
-
'.dsub-helpStep{margin-bottom:6px;color:var(--dsw-alias-label-primary)}' +
|
|
63
|
-
'.dsub-btnActive{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground);border-color:var(--dsw-alias-brand-primary)}' +
|
|
64
|
-
'.dsub-h{font-size:13.5px;font-weight:600;color:var(--dsw-alias-label-primary)}' +
|
|
65
|
-
'.dsub-sub{font-size:12px;color:var(--dsw-alias-label-secondary)}' +
|
|
66
|
-
'.dsub-dim{font-size:11.5px;color:var(--dsw-alias-label-tertiary)}' +
|
|
67
|
-
'.dsub-mini{appearance:none;font:inherit;font-size:12px;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
|
|
68
|
-
'.dsub-mini:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
|
|
69
|
-
'.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}' +
|
|
70
|
-
'.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
|
|
71
|
-
'.dsub-hint{overflow-wrap:anywhere;word-break:break-word;max-width:100%}' +
|
|
72
|
-
'.dsub-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 12px;font-size:12.5px;font-weight:500;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}' +
|
|
73
|
-
'.dsub-btn:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}' +
|
|
74
|
-
'.dsub-inp{height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 8px;font-size:12px;min-width:180px}' +
|
|
75
|
-
'.dsub-inp:focus{outline:none;border-color:var(--dsw-alias-brand-primary)}' +
|
|
76
|
-
'.dsub-box{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px;margin-top:8px;background:var(--dsw-alias-bg-layer-2)}' +
|
|
77
|
-
'.dsub-cooldown{display:inline-block;padding:2px 6px;border-radius:4px;background:var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-bg-layer-1);font-size:11px;font-weight:600}' +
|
|
78
|
-
'.dsub-bar{position:relative;height:6px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden;flex:1;min-width:80px}' +
|
|
79
|
-
'.dsub-barFill{height:100%;border-radius:3px;background:var(--dsw-alias-state-success-primary);transition:width .2s}' +
|
|
80
|
-
'.dsub-barWarn .dsub-barFill{background:var(--dsw-alias-state-warn-primary)}' +
|
|
81
|
-
'.dsub-barFull .dsub-barFill{background:var(--dsw-alias-state-error-primary)}' +
|
|
82
|
-
'.dsub-barRow{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary)}' +
|
|
83
|
-
'.dsub-manual{display:flex;flex-direction:column;gap:6px;margin-top:4px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l2)}' +
|
|
84
|
-
'.dsub-verify{font-size:12px;color:var(--dsw-alias-state-warn-primary)}' +
|
|
85
|
-
'.dsub-verify a{color:var(--dsw-alias-brand-primary)}' +
|
|
86
|
-
'.dsub-pill{display:inline-flex;align-items:center;gap:7px;height:28px;padding:0 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 1px 3px color-mix(in srgb, black 15%, transparent),inset 0 1px 0 color-mix(in srgb, white 6%, transparent);transition:all .16s ease;user-select:none}' +
|
|
87
|
-
'.dsub-pill:hover{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-tertiary);transform:translateY(-1px);box-shadow:0 3px 8px color-mix(in srgb, black 25%, transparent),inset 0 1px 0 color-mix(in srgb, white 10%, transparent)}' +
|
|
88
|
-
'.dsub-pill:active{transform:translateY(0)}' +
|
|
89
|
-
'.dsub-pillTag{padding:1px 5px;border-radius:4px;font-size:10.5px;font-weight:700;letter-spacing:.02em;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary)}' +
|
|
90
|
-
'.dsub-led{width:7px;height:7px;border-radius:50%;flex:none;transition:all .2s ease}' +
|
|
91
|
-
'.dsub-ledOk{background:var(--dsw-alias-state-success-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-success-primary) 70%,transparent)}' +
|
|
92
|
-
'.dsub-ledWarn{background:var(--dsw-alias-state-warn-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-warn-primary) 70%,transparent)}' +
|
|
93
|
-
'.dsub-ledBad{background:var(--dsw-alias-state-error-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-error-primary) 70%,transparent)}' +
|
|
94
|
-
'.dsub-ledOff{background:var(--dsw-alias-label-tertiary)}' +
|
|
95
|
-
'.dsub-toast-container{position:fixed;top:16px;right:16px;z-index:10030;display:flex;flex-direction:column;gap:8px;pointer-events:none}' +'.dsub-toast{pointer-events:auto;min-width:280px;max-width:400px;padding:10px 14px;border-radius:10px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);box-shadow:0 8px 24px color-mix(in srgb,black 40%,transparent);display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12px;line-height:1.4;animation:dsubFadeIn .2s ease-out}' +'.dsub-toast-warn{border-color:var(--dsw-alias-state-warn-primary)}' +'.dsub-toast-bad{border-color:var(--dsw-alias-state-error-primary)}' +'.dsub-toast-ok{border-color:var(--dsw-alias-state-success-primary)}' +'.dsub-toast-close{background:none;border:none;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:14px;padding:0 2px}' +'.dsub-toast-close:hover{color:var(--dsw-alias-label-primary)}' +
|
|
96
|
-
'.dsub-modalWrap{position:fixed;inset:0;z-index:10020;display:grid;place-items:center;background:color-mix(in srgb, black 65%, transparent);backdrop-filter:blur(10px);animation:dsubFadeIn .16s ease-out}' +
|
|
97
|
-
'.dsub-modal{width:min(520px,94vw);max-height:min(85vh,720px);overflow-y:auto;border:1px solid var(--dsw-alias-border-l1);border-radius:16px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);box-shadow:0 24px 64px color-mix(in srgb, black 60%, transparent),0 0 0 1px color-mix(in srgb, white 7%, transparent);padding:20px;animation:dsubScaleIn .18s cubic-bezier(.16,1,.3,1)}' +
|
|
98
|
-
'@keyframes dsubFadeIn{from{opacity:0}to{opacity:1}}' +
|
|
99
|
-
'@keyframes dsubScaleIn{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}' +
|
|
100
|
-
'.dsub-modalHead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-bottom:14px;border-bottom:1px solid var(--dsw-alias-border-l2)}' +
|
|
101
|
-
'.dsub-modalTitleWrap{display:flex;align-items:center;gap:10px}' +
|
|
102
|
-
'.dsub-modalIcon{width:30px;height:30px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);display:grid;place-items:center;color:var(--dsw-alias-brand-primary);font-size:14px}' +
|
|
103
|
-
'.dsub-modalBadge{font-size:11px;font-weight:600;padding:2px 7px;border-radius:10px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary)}' +
|
|
104
|
-
'.dsub-heroCard{margin-top:14px;padding:14px 16px;border-radius:12px;background:linear-gradient(135deg,var(--dsw-alias-bg-layer-2) 0%,var(--dsw-alias-bg-layer-3) 100%);border:1px solid var(--dsw-alias-border-l1);box-shadow:inset 0 1px 0 color-mix(in srgb, white 5%, transparent)}' +
|
|
105
|
-
'.dsub-heroHead{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}' +
|
|
106
|
-
'.dsub-heroTitle{font-size:14px;font-weight:700;display:flex;align-items:center;gap:6px}' +
|
|
107
|
-
'.dsub-heroModel{font-size:11.5px;color:var(--dsw-alias-label-secondary);font-family:ui-monospace,monospace}' +
|
|
108
|
-
'.dsub-select{appearance:none;height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 24px 0 8px;font-size:12px;cursor:pointer}' +
|
|
109
|
-
'.dsub-details{margin-top:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:8px 12px;background:var(--dsw-alias-bg-layer-2)}' +
|
|
110
|
-
'.dsub-summary{cursor:pointer;font-weight:600;font-size:12.5px;color:var(--dsw-alias-label-secondary);user-select:none}' +
|
|
111
|
-
'.dsub-summary:hover{color:var(--dsw-alias-label-primary)}' +
|
|
112
|
-
'.dsub-header-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:8px 0 12px;margin-bottom:8px;border-bottom:1px solid var(--dsw-alias-border-l2)}' +
|
|
113
|
-
'.dsub-badge{font-size:12px;padding:3px 10px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);display:inline-flex;align-items:center;gap:5px;font-weight:500}' +
|
|
114
|
-
'.dsub-badge-ok{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}' +
|
|
115
|
-
'.dsub-badge-warn{border-color:var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 10%,transparent)}' +
|
|
116
|
-
'.dsub-badge-bad{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}' +
|
|
117
|
-
'.dsub-badge-neutral{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}' +
|
|
118
|
-
'.dsub-section-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;display:flex;flex-direction:column;gap:10px;margin-top:12px}' +
|
|
119
|
-
'.dsub-section-title{font-size:14.5px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;justify-content:space-between;gap:8px}' +
|
|
120
|
-
'.dsub-section-desc{font-size:12px;color:var(--dsw-alias-label-secondary);margin-top:-4px;line-height:1.4}' +
|
|
121
|
-
'.dsub-grid-2{display:grid;grid-template-columns:repeat(auto-fit, minmax(200px, 1fr));gap:10px}' +
|
|
122
|
-
'.dsub-stat-box{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);display:flex;flex-direction:column;gap:3px}' +
|
|
123
|
-
'.dsub-stat-val{font-size:16.5px;font-weight:700;color:var(--dsw-alias-label-primary)}' +
|
|
124
|
-
'.dsub-stat-lbl{font-size:11.5px;color:var(--dsw-alias-label-secondary)}' +
|
|
125
|
-
'.dsub-chart-wrap{display:flex;align-items:flex-end;gap:3px;height:52px;padding:6px 0;margin-top:8px;border-bottom:1px solid var(--dsw-alias-border-l3)}' +
|
|
126
|
-
'.dsub-chart-bar{flex:1;background:var(--dsw-alias-brand-primary);border-radius:2px 2px 0 0;min-height:3px;transition:height .2s ease;opacity:0.85;cursor:pointer}' +
|
|
127
|
-
'.dsub-chart-bar:hover{opacity:1;background:var(--dsw-alias-state-success-primary)}' +
|
|
128
|
-
'.dsub-chart-labels{display:flex;justify-content:space-between;font-size:10px;color:var(--dsw-alias-label-secondary);margin-top:3px}' +
|
|
129
|
-
'.dsub-alert-ok{padding:8px 12px;border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent);color:var(--dsw-alias-state-success-primary);font-size:12.5px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary) 25%,transparent)}' +
|
|
130
|
-
'.dsub-alert-bad{padding:8px 12px;border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary);font-size:12.5px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 25%,transparent)}' +
|
|
131
|
-
'.dsub-btn-primary{background:var(--dsw-alias-label-primary) !important;color:var(--dsw-alias-bg-layer-3) !important;border-color:transparent !important;font-weight:600}' +
|
|
132
|
-
'.dsub-btn-primary:hover:not(:disabled){opacity:0.9}' +
|
|
133
|
-
'.dsub-model-grid{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}' +
|
|
134
|
-
'.dsub-model-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;border-radius:6px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);font-size:11.5px;color:var(--dsw-alias-label-primary)}' +
|
|
135
|
-
'.dsub-model-chip code{font-family:ui-monospace,monospace;font-weight:600}' +
|
|
136
|
-
'.dsub-model-tag{font-size:10px;padding:1px 4px;border-radius:3px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:600}' +
|
|
137
|
-
'.dsub-trace-box{padding:8px 12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);margin-top:8px;font-size:12px}' +
|
|
138
|
-
'.dsub-trace-row{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:4px 0;border-bottom:1px solid var(--dsw-alias-border-l3)}' +
|
|
139
|
-
'.dsub-trace-row:last-child{border-bottom:none}' +
|
|
140
|
-
'.dsub-model-status-available{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 12%,transparent)}' +
|
|
141
|
-
'.dsub-model-status-degraded{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 12%,transparent)}' +
|
|
142
|
-
'.dsub-model-status-quarantined{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)}' +
|
|
143
|
-
'.dsub-model-status-cooldown{color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent)}' +
|
|
144
|
-
'.dsub-model-status-exhausted{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)}' +
|
|
145
|
-
'.dsub-model-status-unconfigured{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-3)}' +
|
|
146
|
-
'.dsub-heroBars{display:flex;flex-direction:column;gap:8px;margin-top:10px}' +
|
|
147
|
-
'.dsub-barLabelRow{display:flex;justify-content:space-between;font-size:11.5px;color:var(--dsw-alias-label-secondary);margin-bottom:3px}' +
|
|
148
|
-
'.dsub-barTrack{height:6px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}' +
|
|
149
|
-
'.dsub-barFillGrad{height:100%;border-radius:3px;transition:width .3s ease}' +
|
|
150
|
-
'.dsub-panel-box{margin-top:10px;padding:12px 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);display:flex;flex-direction:column;gap:8px}' +
|
|
151
|
-
'.dsub-panel-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 5%,transparent)}' +
|
|
152
|
-
'.dsub-panel-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;justify-content:space-between}' +
|
|
153
|
-
'.dsub-panel-desc{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.4}' +
|
|
154
|
-
'.dsub-usage-grid{display:flex;flex-direction:column;gap:8px;margin-top:4px}' +
|
|
155
|
-
'.dsub-usage-card{display:flex;flex-direction:column;gap:5px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1)}' +
|
|
156
|
-
'.dsub-usage-head{display:flex;justify-content:space-between;align-items:center;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary)}' +
|
|
157
|
-
'.dsub-usage-track{width:100%;height:8px;border-radius:999px;background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);overflow:hidden}' +
|
|
158
|
-
'.dsub-usage-fill{height:100%;border-radius:999px;transition:width .3s ease}' +
|
|
159
|
-
'.dsub-usage-meta{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--dsw-alias-label-secondary)}' +
|
|
160
|
-
'.dsub-tag-ok{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 30%,transparent);color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}' +
|
|
161
|
-
'.dsub-tag-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 40%,transparent);color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}' +
|
|
162
|
-
'.dsub-tag-bad{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}' +
|
|
163
|
-
'.dsub-slot-meta-row{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:12px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l2);font-size:12px}' +
|
|
164
|
-
'.dsub-ref-tag{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--dsw-alias-label-secondary)}' +
|
|
165
|
-
'.dsub-ref-tag code{padding:2px 6px;border-radius:4px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);font-family:ui-monospace,monospace;color:var(--dsw-alias-label-primary);font-size:11px}' +
|
|
166
|
-
'.dsub-speed-tag{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent);padding:2px 8px;border-radius:6px;font-weight:500;border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 20%,transparent)}' +
|
|
167
|
-
'.dsub-btn-danger{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent)!important;color:var(--dsw-alias-state-error-primary)!important}' +
|
|
168
|
-
'.dsub-btn-danger:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)!important}' +
|
|
169
|
-
'.dsub-poolTitle{margin-top:16px;margin-bottom:8px;font-size:11.5px;font-weight:700;color:var(--dsw-alias-label-secondary);text-transform:uppercase;letter-spacing:.05em}' +
|
|
170
|
-
'.dsub-accountCard{display:flex;align-items:center;gap:12px;padding:10px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);margin-top:6px;transition:border-color .15s,background .15s}' +
|
|
171
|
-
'.dsub-accountCard:hover{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-tertiary)}' +
|
|
172
|
-
'.dsub-brandBadge{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;font-size:12px;font-weight:700;flex-shrink:0}' +
|
|
173
|
-
'.dsub-brandCodex{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 15%,transparent);color:var(--dsw-alias-state-success-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary) 30%,transparent)}' +
|
|
174
|
-
'.dsub-brandClaude{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,transparent)}' +
|
|
175
|
-
'.dsub-brandGrok{background:color-mix(in srgb,var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary)) 15%,transparent);color:var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary));border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary)) 30%,transparent)}' +
|
|
176
|
-
'.dsub-brandAgy{background:color-mix(in srgb,var(--dsw-alias-brand-primary) 15%,transparent);color:var(--dsw-alias-brand-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 30%,transparent)}' +
|
|
177
|
-
'.dsub-brandOllama{background:color-mix(in srgb,var(--dsw-alias-label-tertiary) 15%,transparent);color:var(--dsw-alias-label-secondary);border:1px solid color-mix(in srgb,var(--dsw-alias-label-tertiary) 30%,transparent)}' +
|
|
178
|
-
'.dsub-brandKimi{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,transparent)}' +
|
|
179
|
-
'.dsub-brandGlm{background:color-mix(in srgb,var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary)) 15%,transparent);color:var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary));border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary)) 30%,transparent)}' +
|
|
180
|
-
'.dsub-planBadge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;background:color-mix(in srgb,var(--dsw-alias-brand-primary) 15%,transparent);color:var(--dsw-alias-brand-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 30%,transparent);margin-left:6px}' +
|
|
181
|
-
|
|
182
|
-
'.dsub-accInfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}' +
|
|
183
|
-
'.dsub-accNameRow{display:flex;align-items:center;justify-content:space-between;gap:8px}' +
|
|
184
|
-
'.dsub-accName{font-size:13px;font-weight:600}' +
|
|
185
|
-
'.dsub-accStatusTag{font-size:10.5px;font-weight:600;padding:1px 6px;border-radius:4px}' +
|
|
186
|
-
'.dsub-statusOk{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 15%,transparent);color:var(--dsw-alias-state-success-primary)}' +
|
|
187
|
-
'.dsub-statusWarn{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary)}' +
|
|
188
|
-
'.dsub-statusBad{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent);color:var(--dsw-alias-state-error-primary)}' +
|
|
189
|
-
'.dsub-statusOff{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-tertiary)}' +
|
|
190
|
-
'.dsub-modalFoot{display:flex;align-items:center;justify-content:space-between;margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2)}' +
|
|
191
|
-
'.dsub-btnPrimary{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:600;background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground);border:0;cursor:pointer;transition:opacity .15s}' +
|
|
192
|
-
'.dsub-btnPrimary:hover{opacity:.9}' +
|
|
193
|
-
'.dsub-btnSec{display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:7px;font-size:11.5px;font-weight:500;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;text-decoration:none;transition:all .15s}' +
|
|
194
|
-
'.dsub-btnSec:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-tertiary)}' +
|
|
195
|
-
'.dsub-cq{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary);padding:0 6px}' +
|
|
196
|
-
'.dsub-cqBar{position:relative;width:40px;height:5px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}' +
|
|
197
|
-
'.dsub-cqBarFill{height:100%;border-radius:3px;background:var(--dsw-alias-state-success-primary)}' +
|
|
198
|
-
'.dsub-cqBarWarn .dsub-cqBarFill{background:var(--dsw-alias-state-warn-primary)}' +
|
|
199
|
-
'.dsub-cqBarFull .dsub-cqBarFill{background:var(--dsw-alias-state-error-primary)}' +
|
|
200
|
-
'.dsub-cqB{font-variant-numeric:tabular-nums;font-weight:600;color:var(--dsw-alias-label-primary)}' +
|
|
201
|
-
'.dsub-diag{font:11px/1.5 ui-monospace,SFMono-Regular,monospace;max-height:260px;overflow:auto;white-space:pre-wrap;word-break:break-word;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary)}'
|
|
202
|
-
|
|
203
|
-
const cssId = 'dsh-subscriptions/settings.module.css'
|
|
43
|
+
".dsub-card{list-style:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;transition:border-color .16s,background .16s}.dsub-card:hover{border-color:var(--dsw-alias-label-dimmed)}.dsub-cardOpen{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}.dsub-header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.dsub-header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.dsub-headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.dsub-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.dsub-description{color:var(--dsw-alias-label-secondary);font-size:13px}.dsub-chev{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.dsub-chevOpen{transform:rotate(180deg)}.dsub-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:12px}.dsub-block{margin-top:10px}.dsub-group{margin-top:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:0 14px}.dsub-group[open]{padding-bottom:6px}.dsub-groupHead{cursor:pointer;font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);padding:10px 0;list-style:none}.dsub-groupHead::-webkit-details-marker{display:none}.dsub-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-top:8px}.dsub-grow{flex:1 1 180px;min-width:140px}.dsub-helpBox{margin-top:8px;padding:12px 14px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font-size:12px;line-height:1.6}.dsub-helpHead{display:flex;align-items:center;justify-content:space-between;font-weight:600;margin-bottom:8px;color:var(--dsw-alias-brand-primary)}.dsub-helpStep{margin-bottom:6px;color:var(--dsw-alias-label-primary)}.dsub-btnActive{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground);border-color:var(--dsw-alias-brand-primary)}.dsub-h{font-size:13.5px;font-weight:600;color:var(--dsw-alias-label-primary)}.dsub-sub{font-size:12px;color:var(--dsw-alias-label-secondary)}.dsub-dim{font-size:11.5px;color:var(--dsw-alias-label-tertiary)}.dsub-mini{appearance:none;font:inherit;font-size:12px;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;padding:3px 8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}.dsub-mini:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}.dsub-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}.dsub-bad{font-size:12px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;word-break:break-word;max-width:100%}.dsub-hint{overflow-wrap:anywhere;word-break:break-word;max-width:100%}.dsub-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:5px 12px;font-size:12.5px;font-weight:500;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);transition:all .15s}.dsub-btn:hover{background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-dimmed)}.dsub-inp{height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 8px;font-size:12px;min-width:180px}.dsub-inp:focus{outline:none;border-color:var(--dsw-alias-brand-primary)}.dsub-box{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px;margin-top:8px;background:var(--dsw-alias-bg-layer-2)}.dsub-cooldown{display:inline-block;padding:2px 6px;border-radius:4px;background:var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-bg-layer-1);font-size:11px;font-weight:600}.dsub-bar{position:relative;height:6px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden;flex:1;min-width:80px}.dsub-barFill{height:100%;border-radius:3px;background:var(--dsw-alias-state-success-primary);transition:width .2s}.dsub-barWarn .dsub-barFill{background:var(--dsw-alias-state-warn-primary)}.dsub-barFull .dsub-barFill{background:var(--dsw-alias-state-error-primary)}.dsub-barRow{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary)}.dsub-manual{display:flex;flex-direction:column;gap:6px;margin-top:4px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l2)}.dsub-verify{font-size:12px;color:var(--dsw-alias-state-warn-primary)}.dsub-verify a{color:var(--dsw-alias-brand-primary)}.dsub-pill{display:inline-flex;align-items:center;gap:7px;height:28px;padding:0 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:12px;font-weight:600;cursor:pointer;box-shadow:0 1px 3px color-mix(in srgb,black 15%,transparent),inset 0 1px 0 color-mix(in srgb,white 6%,transparent);transition:all .16s ease;user-select:none}.dsub-pill:hover{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-tertiary);transform:translateY(-1px);box-shadow:0 3px 8px color-mix(in srgb,black 25%,transparent),inset 0 1px 0 color-mix(in srgb,white 10%,transparent)}.dsub-pill:active{transform:translateY(0)}.dsub-pillTag{padding:1px 5px;border-radius:4px;font-size:10.5px;font-weight:700;letter-spacing:.02em;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary)}.dsub-led{width:7px;height:7px;border-radius:50%;flex:none;transition:all .2s ease}.dsub-ledOk{background:var(--dsw-alias-state-success-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-success-primary) 70%,transparent)}.dsub-ledWarn{background:var(--dsw-alias-state-warn-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-warn-primary) 70%,transparent)}.dsub-ledBad{background:var(--dsw-alias-state-error-primary);box-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-state-error-primary) 70%,transparent)}.dsub-ledOff{background:var(--dsw-alias-label-tertiary)}.dsub-toast-container{position:fixed;top:16px;right:16px;z-index:10030;display:flex;flex-direction:column;gap:8px;pointer-events:none}.dsub-toast{pointer-events:auto;min-width:280px;max-width:400px;padding:10px 14px;border-radius:10px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);box-shadow:0 8px 24px color-mix(in srgb,black 40%,transparent);display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12px;line-height:1.4;animation:dsubFadeIn .2s ease-out}.dsub-toast-warn{border-color:var(--dsw-alias-state-warn-primary)}.dsub-toast-bad{border-color:var(--dsw-alias-state-error-primary)}.dsub-toast-ok{border-color:var(--dsw-alias-state-success-primary)}.dsub-toast-close{background:none;border:none;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:14px;padding:0 2px}.dsub-toast-close:hover{color:var(--dsw-alias-label-primary)}.dsub-modalWrap{position:fixed;inset:0;z-index:10020;display:grid;place-items:center;background:color-mix(in srgb,black 65%,transparent);backdrop-filter:blur(10px);animation:dsubFadeIn .16s ease-out}.dsub-modal{width:min(520px,94vw);max-height:min(85vh,720px);overflow-y:auto;border:1px solid var(--dsw-alias-border-l1);border-radius:16px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);box-shadow:0 24px 64px color-mix(in srgb,black 60%,transparent),0 0 0 1px color-mix(in srgb,white 7%,transparent);padding:20px;animation:dsubScaleIn .18s cubic-bezier(.16,1,.3,1)}@keyframes dsubFadeIn{from{opacity:0}to{opacity:1}}@keyframes dsubScaleIn{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}.dsub-modalHead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding-bottom:14px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsub-modalTitleWrap{display:flex;align-items:center;gap:10px}.dsub-modalIcon{width:30px;height:30px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);display:grid;place-items:center;color:var(--dsw-alias-brand-primary);font-size:14px}.dsub-modalBadge{font-size:11px;font-weight:600;padding:2px 7px;border-radius:10px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary)}.dsub-heroCard{margin-top:14px;padding:14px 16px;border-radius:12px;background:linear-gradient(135deg,var(--dsw-alias-bg-layer-2) 0%,var(--dsw-alias-bg-layer-3) 100%);border:1px solid var(--dsw-alias-border-l1);box-shadow:inset 0 1px 0 color-mix(in srgb,white 5%,transparent)}.dsub-heroHead{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.dsub-heroTitle{font-size:14px;font-weight:700;display:flex;align-items:center;gap:6px}.dsub-heroModel{font-size:11.5px;color:var(--dsw-alias-label-secondary);font-family:ui-monospace,monospace}.dsub-select{appearance:none;height:30px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 24px 0 8px;font-size:12px;cursor:pointer}.dsub-details{margin-top:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:8px 12px;background:var(--dsw-alias-bg-layer-2)}.dsub-summary{cursor:pointer;font-weight:600;font-size:12.5px;color:var(--dsw-alias-label-secondary);user-select:none}.dsub-summary:hover{color:var(--dsw-alias-label-primary)}.dsub-header-bar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:8px 0 12px;margin-bottom:8px;border-bottom:1px solid var(--dsw-alias-border-l2)}.dsub-badge{font-size:12px;padding:3px 10px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);display:inline-flex;align-items:center;gap:5px;font-weight:500}.dsub-badge-ok{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}.dsub-badge-warn{border-color:var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 10%,transparent)}.dsub-badge-bad{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}.dsub-badge-neutral{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.dsub-section-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;padding:14px 16px;display:flex;flex-direction:column;gap:10px;margin-top:12px}.dsub-section-title{font-size:14.5px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;justify-content:space-between;gap:8px}.dsub-section-desc{font-size:12px;color:var(--dsw-alias-label-secondary);margin-top:-4px;line-height:1.4}.dsub-grid-2{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px}.dsub-stat-box{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);display:flex;flex-direction:column;gap:3px}.dsub-stat-val{font-size:16.5px;font-weight:700;color:var(--dsw-alias-label-primary)}.dsub-stat-lbl{font-size:11.5px;color:var(--dsw-alias-label-secondary)}.dsub-chart-wrap{display:flex;align-items:flex-end;gap:3px;height:52px;padding:6px 0;margin-top:8px;border-bottom:1px solid var(--dsw-alias-border-l3)}.dsub-chart-bar{flex:1;background:var(--dsw-alias-brand-primary);border-radius:2px 2px 0 0;min-height:3px;transition:height .2s ease;opacity:0.85;cursor:pointer}.dsub-chart-bar:hover{opacity:1;background:var(--dsw-alias-state-success-primary)}.dsub-chart-labels{display:flex;justify-content:space-between;font-size:10px;color:var(--dsw-alias-label-secondary);margin-top:3px}.dsub-alert-ok{padding:8px 12px;border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent);color:var(--dsw-alias-state-success-primary);font-size:12.5px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary) 25%,transparent)}.dsub-alert-bad{padding:8px 12px;border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);color:var(--dsw-alias-state-error-primary);font-size:12.5px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 25%,transparent)}.dsub-btn-primary{background:var(--dsw-alias-label-primary) !important;color:var(--dsw-alias-bg-layer-3) !important;border-color:transparent !important;font-weight:600}.dsub-btn-primary:hover:not(:disabled){opacity:0.9}.dsub-model-grid{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.dsub-model-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 8px;border-radius:6px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);font-size:11.5px;color:var(--dsw-alias-label-primary)}.dsub-model-chip code{font-family:ui-monospace,monospace;font-weight:600}.dsub-model-tag{font-size:10px;padding:1px 4px;border-radius:3px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:600}.dsub-trace-box{padding:8px 12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);margin-top:8px;font-size:12px}.dsub-trace-row{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:4px 0;border-bottom:1px solid var(--dsw-alias-border-l3)}.dsub-trace-row:last-child{border-bottom:none}.dsub-model-status-available{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 12%,transparent)}.dsub-model-status-degraded{color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 12%,transparent)}.dsub-model-status-quarantined{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)}.dsub-model-status-cooldown{color:var(--dsw-alias-state-business-primary);background:color-mix(in srgb,var(--dsw-alias-state-business-primary) 12%,transparent)}.dsub-model-status-exhausted{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)}.dsub-model-status-unconfigured{color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-3)}.dsub-heroBars{display:flex;flex-direction:column;gap:8px;margin-top:10px}.dsub-barLabelRow{display:flex;justify-content:space-between;font-size:11.5px;color:var(--dsw-alias-label-secondary);margin-bottom:3px}.dsub-barTrack{height:6px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}.dsub-barFillGrad{height:100%;border-radius:3px;transition:width .3s ease}.dsub-panel-box{margin-top:10px;padding:12px 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);display:flex;flex-direction:column;gap:8px}.dsub-panel-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 40%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 5%,transparent)}.dsub-panel-title{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;justify-content:space-between}.dsub-panel-desc{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.4}.dsub-usage-grid{display:flex;flex-direction:column;gap:8px;margin-top:4px}.dsub-usage-card{display:flex;flex-direction:column;gap:5px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1)}.dsub-usage-head{display:flex;justify-content:space-between;align-items:center;font-size:12px;font-weight:500;color:var(--dsw-alias-label-primary)}.dsub-usage-track{width:100%;height:8px;border-radius:999px;background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);overflow:hidden}.dsub-usage-fill{height:100%;border-radius:999px;transition:width .3s ease}.dsub-usage-meta{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--dsw-alias-label-secondary)}.dsub-tag-ok{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 30%,transparent);color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}.dsub-tag-warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 40%,transparent);color:var(--dsw-alias-state-warn-primary);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}.dsub-tag-bad{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent);color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent);padding:1px 7px;border-radius:999px;font-size:11px;font-weight:600;border-style:solid;border-width:1px}.dsub-slot-meta-row{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:12px;padding-top:10px;border-top:1px solid var(--dsw-alias-border-l2);font-size:12px}.dsub-ref-tag{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--dsw-alias-label-secondary)}.dsub-ref-tag code{padding:2px 6px;border-radius:4px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);font-family:ui-monospace,monospace;color:var(--dsw-alias-label-primary);font-size:11px}.dsub-speed-tag{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent);padding:2px 8px;border-radius:6px;font-weight:500;border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 20%,transparent)}.dsub-btn-danger{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,transparent)!important;color:var(--dsw-alias-state-error-primary)!important}.dsub-btn-danger:hover:not(:disabled){background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent)!important}.dsub-poolTitle{margin-top:16px;margin-bottom:8px;font-size:11.5px;font-weight:700;color:var(--dsw-alias-label-secondary);text-transform:uppercase;letter-spacing:.05em}.dsub-accountCard{display:flex;align-items:center;gap:12px;padding:10px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);margin-top:6px;transition:border-color .15s,background .15s}.dsub-accountCard:hover{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-label-tertiary)}.dsub-brandBadge{width:32px;height:32px;border-radius:8px;display:grid;place-items:center;font-size:12px;font-weight:700;flex-shrink:0}.dsub-brandCodex{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 15%,transparent);color:var(--dsw-alias-state-success-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-success-primary) 30%,transparent)}.dsub-brandClaude{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,transparent)}.dsub-brandGrok{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary)) 15%,transparent);color:var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary));border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary)) 30%,transparent)}.dsub-brandAgy{background:color-mix(in srgb,var(--dsw-alias-brand-primary) 15%,transparent);color:var(--dsw-alias-brand-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 30%,transparent)}.dsub-brandOllama{background:color-mix(in srgb,var(--dsw-alias-label-tertiary) 15%,transparent);color:var(--dsw-alias-label-secondary);border:1px solid color-mix(in srgb,var(--dsw-alias-label-tertiary) 30%,transparent)}.dsub-brandKimi{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,transparent)}.dsub-brandGlm{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary)) 15%,transparent);color:var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary));border:1px solid color-mix(in srgb,var(--dsw-alias-state-business-primary,var(--dsw-alias-brand-primary)) 30%,transparent)}.dsub-planBadge{display:inline-flex;align-items:center;padding:1px 6px;border-radius:4px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;background:color-mix(in srgb,var(--dsw-alias-brand-primary) 15%,transparent);color:var(--dsw-alias-brand-primary);border:1px solid color-mix(in srgb,var(--dsw-alias-brand-primary) 30%,transparent);margin-left:6px}.dsub-accInfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.dsub-accNameRow{display:flex;align-items:center;justify-content:space-between;gap:8px}.dsub-accName{font-size:13px;font-weight:600}.dsub-accStatusTag{font-size:10.5px;font-weight:600;padding:1px 6px;border-radius:4px}.dsub-statusOk{background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 15%,transparent);color:var(--dsw-alias-state-success-primary)}.dsub-statusWarn{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent);color:var(--dsw-alias-state-warn-primary)}.dsub-statusBad{background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent);color:var(--dsw-alias-state-error-primary)}.dsub-statusOff{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-tertiary)}.dsub-modalFoot{display:flex;align-items:center;justify-content:space-between;margin-top:16px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2)}.dsub-btnPrimary{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:8px;font-size:12px;font-weight:600;background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground);border:0;cursor:pointer;transition:opacity .15s}.dsub-btnPrimary:hover{opacity:.9}.dsub-btnSec{display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:7px;font-size:11.5px;font-weight:500;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);border:1px solid var(--dsw-alias-border-l2);cursor:pointer;text-decoration:none;transition:all .15s}.dsub-btnSec:hover{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-tertiary)}.dsub-cq{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary);padding:0 6px}.dsub-cqBar{position:relative;width:40px;height:5px;border-radius:3px;background:var(--dsw-alias-bg-layer-1);overflow:hidden}.dsub-cqBarFill{height:100%;border-radius:3px;background:var(--dsw-alias-state-success-primary)}.dsub-cqBarWarn .dsub-cqBarFill{background:var(--dsw-alias-state-warn-primary)}.dsub-cqBarFull .dsub-cqBarFill{background:var(--dsw-alias-state-error-primary)}.dsub-cqB{font-variant-numeric:tabular-nums;font-weight:600;color:var(--dsw-alias-label-primary)}.dsub-diag{font:11px/1.5 ui-monospace,SFMono-Regular,monospace;max-height:260px;overflow:auto;white-space:pre-wrap;word-break:break-word;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary)}";
|
|
44
|
+
const cssId = 'dsh-subscriptions/settings.module.css'
|
|
204
45
|
if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="' + cssId + '"]')) {
|
|
205
46
|
const tag = document.createElement('style')
|
|
206
47
|
tag.textContent = CSS
|
|
@@ -210,155 +51,21 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
210
51
|
document.head.appendChild(tag)
|
|
211
52
|
}
|
|
212
53
|
|
|
213
|
-
// Card strings live in the locale registry: a separate package translates
|
|
214
|
-
// them without touching this plugin's code. English is the default,
|
|
215
|
-
// and the fallback when no translation exists.
|
|
216
54
|
const NS = 'dsh-subscriptions'
|
|
217
55
|
// Plugins page row seat (DSH 0.1.6-alpha.2): key = '<package name>#<row id>'.
|
|
218
56
|
const PKG = '@goodandready/dsh-subscriptions'
|
|
219
57
|
const ROW_ID = 'dsh-subscriptions'
|
|
220
58
|
const ROW_CONFIG_KEY = PKG + '#' + ROW_ID
|
|
221
59
|
|
|
222
|
-
|
|
223
|
-
codex: {
|
|
224
|
-
title: "OpenAI / ChatGPT Codex",
|
|
225
|
-
stepsEn: [
|
|
226
|
-
"1. Log in via CLI on server: run \"codex login\" in terminal.",
|
|
227
|
-
"2. Click \"๐ฅ From CLI\" to auto-import ~/.codex/auth.json.",
|
|
228
|
-
"3. Or click \"Device Login\" above and enter the code at auth.openai.com.",
|
|
229
|
-
],
|
|
230
|
-
stepsZh: [
|
|
231
|
-
"1. ๅจๆๅกๅจไธ้่ฟ CLI ็ปๅฝ๏ผๅจ็ป็ซฏ่ฟ่ก \"codex login\"ใ",
|
|
232
|
-
"2. ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" ่ชๅจ่ฏปๅ ~/.codex/auth.jsonใ",
|
|
233
|
-
"3. ๆ่
็นๅปไธๆน็ \"่ฎพๅค็ ็ปๅฝ\" (Device Login) ๅนถๅจ auth.openai.com ่พๅ
ฅไปฃ็ ใ",
|
|
234
|
-
],
|
|
235
|
-
link: "https://chatgpt.com",
|
|
236
|
-
},
|
|
237
|
-
claude: {
|
|
238
|
-
title: "Claude Code",
|
|
239
|
-
stepsEn: [
|
|
240
|
-
"1. Run \"claude login\" in server console.",
|
|
241
|
-
"2. Click \"๐ฅ From CLI\" โ plugin will import ~/.claude/credentials.json.",
|
|
242
|
-
"3. Or paste your Session Token / API Key from Anthropic Console and click \"Save token\".",
|
|
243
|
-
],
|
|
244
|
-
stepsZh: [
|
|
245
|
-
"1. ๅจๆๅกๅจๆงๅถๅฐ่ฟ่ก \"claude login\"ใ",
|
|
246
|
-
"2. ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" โ ๆไปถๅฐ่ชๅจๅฏผๅ
ฅ ~/.claude/credentials.jsonใ",
|
|
247
|
-
"3. ๆ่
ไป Anthropic ๆงๅถๅฐๅคๅถๆจ็ Session Token ๆ API Key ๅนถ็นๅป \"ไฟๅญไปค็\"ใ",
|
|
248
|
-
],
|
|
249
|
-
link: "https://console.anthropic.com/settings/keys",
|
|
250
|
-
},
|
|
251
|
-
cursor: {
|
|
252
|
-
title: "Cursor IDE",
|
|
253
|
-
stepsEn: [
|
|
254
|
-
"1. Auto CLI: if Cursor is used on server, click \"๐ฅ From CLI\" (reads from ~/.cursor/cli-config.json).",
|
|
255
|
-
"2. Manual: open Cursor Settings (Connect button or link below), copy your session token or API key.",
|
|
256
|
-
"3. Paste it into the input field and click \"Save token\".",
|
|
257
|
-
],
|
|
258
|
-
stepsZh: [
|
|
259
|
-
"1. CLI ่ชๅจๅฏผๅ
ฅ๏ผ่ฅๆๅกๅจๅฎ่ฃ
ไบ Cursor๏ผ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" (่ฏปๅ่ช ~/.cursor/cli-config.json)ใ",
|
|
260
|
-
"2. ๆๅจๅฏผๅ
ฅ๏ผๆๅผ Cursor ่ฎพ็ฝฎ้กต้ข๏ผ็นๅป่ฟๆฅๆไธๆน้พๆฅ๏ผ๏ผๅคๅถ WorkOS ไผ่ฏไปค็ๆ API ๅฏ้ฅใ",
|
|
261
|
-
"3. ๅฐๅ
ถ็ฒ่ดดๅฐ่พๅ
ฅๆกไธญๅนถ็นๅป \"ไฟๅญไปค็\"ใ",
|
|
262
|
-
],
|
|
263
|
-
link: "https://cursor.com/settings",
|
|
264
|
-
},
|
|
265
|
-
antigravity: {
|
|
266
|
-
title: "Google Antigravity / Gemini",
|
|
267
|
-
stepsEn: [
|
|
268
|
-
"1. Easiest way: click \"๐ฅ From CLI\" โ server already has active token in ~/.gemini/antigravity-cli/antigravity-oauth-token.",
|
|
269
|
-
"2. Clicking \"๐ฅ From CLI\" instantly loads fresh credentials.",
|
|
270
|
-
"3. Manual: paste session JSON or OAuth tokens and click \"Save token\".",
|
|
271
|
-
"Note: \"Connect\" button requires custom Google client_id in plugin settings; use \"๐ฅ From CLI\" for seamless login!",
|
|
272
|
-
],
|
|
273
|
-
stepsZh: [
|
|
274
|
-
"1. ๆจ่ๆนๅผ๏ผ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" โ ๆๅกๅจๅทฒไฟๅญ ~/.gemini/antigravity-cli/antigravity-oauth-token ไผ่ฏใ",
|
|
275
|
-
"2. ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" ๅฏๅณๆถๅ ่ฝฝๆๆฐ็ๅญๆฎไธ refresh_tokenใ",
|
|
276
|
-
"3. ๆๅจ่พๅ
ฅ๏ผๅฐไผ่ฏ JSON ๆ OAuth access_token/refresh_token ็ฒ่ดด่ณ่พๅ
ฅๆกๅนถไฟๅญใ",
|
|
277
|
-
"ๆณจ๏ผ\"่ฟๆฅ\" ๆ้ฎ้่ฆ่ชๅฎไน Google OAuth Client ID๏ผๆจ่็ดๆฅไฝฟ็จ \"๐ฅ ไป CLI ๅฏผๅ
ฅ\"๏ผ",
|
|
278
|
-
],
|
|
279
|
-
link: "https://antigravity.google",
|
|
280
|
-
},
|
|
281
|
-
kimi: {
|
|
282
|
-
title: "Moonshot Kimi",
|
|
283
|
-
stepsEn: [
|
|
284
|
-
"1. Open Moonshot developer console (link below or click Connect).",
|
|
285
|
-
"2. Generate and copy your API Key (sk-...).",
|
|
286
|
-
"3. Paste it into the input field and click \"Save token\".",
|
|
287
|
-
"4. Or click \"๐ฅ From CLI\" if ~/.kimi-code is configured.",
|
|
288
|
-
],
|
|
289
|
-
stepsZh: [
|
|
290
|
-
"1. ๆๅผ Moonshot ๅผๅ่
ๆงๅถๅฐ๏ผ็นๅปไธๆน้พๆฅๆ็นๅป่ฟๆฅ๏ผใ",
|
|
291
|
-
"2. ๅๅปบๅนถๅคๅถๆจ็ API ๅฏ้ฅ (sk-...)ใ",
|
|
292
|
-
"3. ๅฐๅฏ้ฅ็ฒ่ดดๅฐๆงฝไฝ่พๅ
ฅๆกไธญๅนถ็นๅป \"ไฟๅญไปค็\"ใ",
|
|
293
|
-
"4. ๅฆๆ้
็ฝฎไบ Kimi Code CLI๏ผไนๅฏ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" (~/.kimi-code)ใ",
|
|
294
|
-
],
|
|
295
|
-
link: "https://platform.moonshot.cn/console/api-keys",
|
|
296
|
-
},
|
|
297
|
-
glm: {
|
|
298
|
-
title: "Zhipu GLM (Z.AI)",
|
|
299
|
-
stepsEn: [
|
|
300
|
-
"1. Open Zhipu BigModel API Keys center (link below or click Connect).",
|
|
301
|
-
"2. Copy your GLM API Key.",
|
|
302
|
-
"3. Paste it into the input field and click \"Save token\".",
|
|
303
|
-
"4. Or click \"๐ฅ From CLI\" if ZCode CLI is installed (~/.zcode).",
|
|
304
|
-
],
|
|
305
|
-
stepsZh: [
|
|
306
|
-
"1. ๆๅผๆบ่ฐฑ AI ๅผๆพๅนณๅฐ๏ผ็นๅปไธๆน้พๆฅๆ็นๅป่ฟๆฅ๏ผใ",
|
|
307
|
-
"2. ๅคๅถๆจ็ GLM API ๅฏ้ฅใ",
|
|
308
|
-
"3. ็ฒ่ดดๅฐ่พๅ
ฅๆกไธญๅนถ็นๅป \"ไฟๅญไปค็\"ใ",
|
|
309
|
-
"4. ่ฅๅทฒๅฎ่ฃ
ZCode CLI (~/.zcode)๏ผ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" ๅณๅฏ่ชๅจๅฏผๅ
ฅใ",
|
|
310
|
-
],
|
|
311
|
-
link: "https://bigmodel.cn/usercenter/proj-mgmt/apikeys",
|
|
312
|
-
},
|
|
313
|
-
grok: {
|
|
314
|
-
title: "xAI Grok",
|
|
315
|
-
stepsEn: [
|
|
316
|
-
"1. Click \"Device Login\" (or \"Connect\") on the slot card.",
|
|
317
|
-
"2. A one-time code will appear on the card.",
|
|
318
|
-
"3. Open https://accounts.x.ai/oauth2/device, enter the code, and approve access for your xAI account.",
|
|
319
|
-
"4. The plugin automatically captures tokens and enables Grok models.",
|
|
320
|
-
"5. Or click \"๐ฅ From CLI\" (~/.grok/auth.json) / paste an xAI API Key.",
|
|
321
|
-
],
|
|
322
|
-
stepsZh: [
|
|
323
|
-
"1. ็นๅปๅก็ไธ็ \"่ฎพๅค็ ็ปๅฝ\" (Device Login) ๆ \"่ฟๆฅ\"ใ",
|
|
324
|
-
"2. ็้ขๅฐๅฑ็คบไธๆฌกๆง่ฎพๅคๆๆ็ ใ",
|
|
325
|
-
"3. ๆๅผ https://accounts.x.ai/oauth2/device๏ผ่พๅ
ฅไปฃ็ ๏ผๅนถไธบๆจๆฅๆ Grok ่ฎข้
็ xAI ่ดฆๆทๆๆใ",
|
|
326
|
-
"4. ๆๆๆๅๅ๏ผๆไปถไผ่ชๅจๆ่ทไผ่ฏๅนถๆฟๆดป Grok ๅฎๆนๆจกๅใ",
|
|
327
|
-
"5. ๆ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" (~/.grok/auth.json) / ็ดๆฅ็ฒ่ดด xAI API ๅฏ้ฅใ",
|
|
328
|
-
],
|
|
329
|
-
link: "https://accounts.x.ai/oauth2/device",
|
|
330
|
-
},
|
|
331
|
-
kiro: {
|
|
332
|
-
title: "AWS Kiro",
|
|
333
|
-
stepsEn: [
|
|
334
|
-
"1. Click \"๐ฅ From CLI\" to import from ~/.kiro/credentials.json.",
|
|
335
|
-
"2. Or paste KIRO_API_KEY and click \"Save token\".",
|
|
336
|
-
],
|
|
337
|
-
stepsZh: [
|
|
338
|
-
"1. ็นๅป \"๐ฅ ไป CLI ๅฏผๅ
ฅ\" ไป ~/.kiro/credentials.json ๆ ~/.aws/sso ๅฏผๅ
ฅๅญๆฎใ",
|
|
339
|
-
"2. ๆ็ดๆฅ็ฒ่ดด KIRO_API_KEY ๅนถ็นๅป \"ไฟๅญไปค็\"ใ",
|
|
340
|
-
],
|
|
341
|
-
link: "https://aws.amazon.com",
|
|
342
|
-
},
|
|
343
|
-
copilot: {
|
|
344
|
-
title: "GitHub Copilot",
|
|
345
|
-
stepsEn: [
|
|
346
|
-
"1. Click \"Device Login\" (or \"Connect\") on the slot card.",
|
|
347
|
-
"2. A one-time code will appear on the card.",
|
|
348
|
-
"3. Open https://github.com/login/device, enter the code, and approve access for your GitHub account with Copilot subscription.",
|
|
349
|
-
"4. The plugin automatically captures tokens and enables Copilot models.",
|
|
350
|
-
],
|
|
351
|
-
stepsZh: [
|
|
352
|
-
"1. ็นๅปๅก็ไธ็ \"่ฎพๅค็ ็ปๅฝ\" (Device Login) ๆ \"่ฟๆฅ\"ใ",
|
|
353
|
-
"2. ็้ขๅฐๅฑ็คบไธๆฌกๆง่ฎพๅคๆๆ็ ใ",
|
|
354
|
-
"3. ๅจๆต่งๅจๆๅผ https://github.com/login/device ่พๅ
ฅไปฃ็ ๏ผๅนถไธบๆจๆฅๆ Copilot ่ฎข้
็ GitHub ่ดฆๆทๆๆใ",
|
|
355
|
-
"4. ๆๆๆๅๅ๏ผๆไปถไผ่ชๅจๆ่ทไผ่ฏๅนถๆฟๆดป GitHub Copilot ๅฎๆนๆจกๅใ",
|
|
356
|
-
],
|
|
357
|
-
link: "https://github.com/login/device",
|
|
358
|
-
},
|
|
359
|
-
}
|
|
60
|
+
let INSTRUCTIONS = {};
|
|
360
61
|
|
|
361
62
|
const en = {
|
|
63
|
+
"syncModels": "Sync Models",
|
|
64
|
+
"syncModelsTitle": "Discover and synchronize available models from vendor API",
|
|
65
|
+
"modelsSynced": "Models synchronized",
|
|
66
|
+
"doctorDiagnosis": "Doctor Verdict",
|
|
67
|
+
"recommendation": "Recommendation",
|
|
68
|
+
"pingTitle": "Measure network latency to provider API",
|
|
362
69
|
"notConnected": "Not connected",
|
|
363
70
|
"verifyAccount": "Verify account",
|
|
364
71
|
"coolingDown": "Cooling down",
|
|
@@ -447,6 +154,24 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
447
154
|
"recentErrorsDesc": "Last 20 runtime failures across model streams and providers (sanitized).",
|
|
448
155
|
"recentErrorsClear": "Clear Log",
|
|
449
156
|
"recentErrorsEmpty": "No recent errors recorded",
|
|
157
|
+
"atRestEncrypted": "Encrypted at Rest (AES-256-GCM)",
|
|
158
|
+
"atRestEncryptedTitle": "Credentials are protected at rest with master key encryption.",
|
|
159
|
+
"maxConcurrencySlotTitle": "Max parallel streams for this account slot (default: 1)",
|
|
160
|
+
"concurrencyQueueHint": "Active and queued parallel requests for this account",
|
|
161
|
+
"activeStreams": "active",
|
|
162
|
+
"queuedStreams": "queued",
|
|
163
|
+
"pacingRunwayHint": "Estimated time before quota exhausts at current pace",
|
|
164
|
+
"runwayPrefix": "Runway",
|
|
165
|
+
"billingAlertHint": "Billing status notice from provider",
|
|
166
|
+
"renewalHint": "Subscription billing cycle renewal date",
|
|
167
|
+
"valueDeliveredHint": "Equivalent official API cost of consumed tokens vs subscription price",
|
|
168
|
+
"capabilitiesHint": "Subscription capabilities, context window and model features",
|
|
169
|
+
"orPasteVaultPayload": "or paste vault payload below",
|
|
170
|
+
"workspaceTitle": "Organization / Workspace",
|
|
171
|
+
"workspaceSelect": "Select active organization/workspace",
|
|
172
|
+
"personalWorkspace": "Personal Default",
|
|
173
|
+
"windowResetsAt": "Window resets at",
|
|
174
|
+
"quotaRecovery": "Quota recovery",
|
|
450
175
|
"toastCooldownRecovered": "is now available (cooldown expired)",
|
|
451
176
|
"modelsCatalogTitle": "Curated Subscription Models",
|
|
452
177
|
"modelsCatalogDesc": "Available model catalog across active subscriptions in DeepSeek Harness.",
|
|
@@ -558,6 +283,11 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
558
283
|
"instructionsTitle": "How to obtain token",
|
|
559
284
|
"close": "Close",
|
|
560
285
|
"reconnectRequired": "Reconnect required",
|
|
286
|
+
"reconnectNow": "Re-authenticate now",
|
|
287
|
+
"scopeWarning": "OAuth scope warning",
|
|
288
|
+
"reconnectScope": "Re-grant scopes",
|
|
289
|
+
"sessionRevokedBadge": "Revoked / Expired",
|
|
290
|
+
"sessionRevokedWarning": "Session expired / revoked โ re-authorization required",
|
|
561
291
|
"manualTitle": "If the browser did not come back",
|
|
562
292
|
"updateChecking": "Checking updatesโฆ",
|
|
563
293
|
"updateUpToDate": "Up to date",
|
|
@@ -602,6 +332,19 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
602
332
|
"toastReleased": "Account active and healthy",
|
|
603
333
|
"toastQuotaWarning": "Quota threshold exceeded",
|
|
604
334
|
"enableToasts": "In-app toast alerts",
|
|
335
|
+
"headlessTip": "Headless / Remote Server?",
|
|
336
|
+
"headlessSshCommand": "SSH Port Forward Command:",
|
|
337
|
+
"headlessCopySsh": "Copy SSH Command",
|
|
338
|
+
"headlessCopied": "Copied!",
|
|
339
|
+
"headlessScanQr": "Scan with Mobile to Authenticate:",
|
|
340
|
+
"vaultSyncTitle": "Automated Remote Vault Sync",
|
|
341
|
+
"vaultSyncPush": "Sync Now (Push)",
|
|
342
|
+
"vaultSyncPull": "Sync Now (Pull)",
|
|
343
|
+
"vaultSyncPushOk": "Vault successfully pushed to remote storage",
|
|
344
|
+
"vaultSyncPullOk": "Vault successfully pulled and merged from remote storage",
|
|
345
|
+
"vaultSyncBackend": "Backend:",
|
|
346
|
+
"vaultSyncLastPush": "Last Push:",
|
|
347
|
+
"vaultSyncLastPull": "Last Pull:",
|
|
605
348
|
"groupQueue": "Concurrency & Request Queue",
|
|
606
349
|
"enableQueue": "Enable request queue",
|
|
607
350
|
"enableQueueHint": "Queue excess requests when account hits concurrency limit instead of failing with 429",
|
|
@@ -649,6 +392,12 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
649
392
|
};
|
|
650
393
|
|
|
651
394
|
const zh = {
|
|
395
|
+
"syncModels": "ๅๆญฅๆจกๅ",
|
|
396
|
+
"syncModelsTitle": "ไปๆๅกๅ API ๅฎๆถๅ็ฐๅนถๅๆญฅๅฏ็จๆจกๅๅ่กจ",
|
|
397
|
+
"modelsSynced": "ๆจกๅๅทฒๅๆญฅ",
|
|
398
|
+
"doctorDiagnosis": "่ฏๆญ็ป่ฎบ",
|
|
399
|
+
"recommendation": "ไฟฎๅคๅปบ่ฎฎ",
|
|
400
|
+
"pingTitle": "ๆต่ฏๅฐๆๅกๅ API ็็ฝ็ปๅพ่ฟๅปถ่ฟ",
|
|
652
401
|
"notConnected": "ๆช่ฟๆฅ",
|
|
653
402
|
"verifyAccount": "้่ฆ้ช่ฏ่ดฆๆท",
|
|
654
403
|
"coolingDown": "ๅทๅด็ญๅพ
ไธญ",
|
|
@@ -737,6 +486,24 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
737
486
|
"recentErrorsDesc": "ๆ่ฟ 20 ๆกๆตๅผไผ ่พไธ API ่ฐ็จๅคฑ่ดฅ่ฎฐๅฝ๏ผๅทฒ่ฑๆ๏ผใ",
|
|
738
487
|
"recentErrorsClear": "ๆธ
็ฉบ่ฎฐๅฝ",
|
|
739
488
|
"recentErrorsEmpty": "ๆๆ ้่ฏฏ่ฎฐๅฝ",
|
|
489
|
+
"atRestEncrypted": "้ๆๅญๅจๅ ๅฏ (AES-256-GCM)",
|
|
490
|
+
"atRestEncryptedTitle": "ๅญๆฎๅทฒ้่ฟไธปๅฏ้ฅ่ฟ่ก้ๆ AES-256-GCM ๅ ๅฏไฟๆคใ",
|
|
491
|
+
"maxConcurrencySlotTitle": "ๅฝๅ่ดฆๆทๆงฝไฝๆๅคงๅนถๅ่ฏทๆฑๆฐ๏ผ้ป่ฎค๏ผ1๏ผ",
|
|
492
|
+
"concurrencyQueueHint": "ๅฝๅ่ดฆๆทๆงฝไฝ่ฟ่กไธญไธๆ้ไธญ็ๅนถๅ่ฏทๆฑ",
|
|
493
|
+
"activeStreams": "ๆดป่ท",
|
|
494
|
+
"queuedStreams": "ๆ้ไธญ",
|
|
495
|
+
"pacingRunwayHint": "ๅฝๅ่ฐ็จ้ๅบฆไธ็้ข่ฎกๅฉไฝๅฏ็จๆถ้ด",
|
|
496
|
+
"runwayPrefix": "ๅฏ็จๆถ้ฟ",
|
|
497
|
+
"billingAlertHint": "ๆๅกๅ่ดฆๅ็ถๆๆ็คบ",
|
|
498
|
+
"renewalHint": "่ฎข้
่ดฆๅๅจๆ็ปญ่ดนๆฅๆ",
|
|
499
|
+
"valueDeliveredHint": "ๆถ่ Token ๅฏนๅบ็ๅฎๆน API ไปทๅผๅฏนๆฏ่ฎข้
่ดน็จ",
|
|
500
|
+
"capabilitiesHint": "่ฎข้
่ดฆๅทๆจกๅไธไธๆ็ชๅฃไธ็นๆ็นๆง",
|
|
501
|
+
"orPasteVaultPayload": "ๆๅจไธๆน็ฒ่ดดไฟ้ฉๅบๆๆฌ",
|
|
502
|
+
"workspaceTitle": "ๅทฅไฝๅบไธ็ป็ป",
|
|
503
|
+
"workspaceSelect": "้ๆฉ็ๆ็ๅทฅไฝๅบๆ็ป็ป",
|
|
504
|
+
"personalWorkspace": "ไธชไบบ้ป่ฎค",
|
|
505
|
+
"windowResetsAt": "้ขๅบฆ้็ฝฎไบ",
|
|
506
|
+
"quotaRecovery": "้ขๅบฆๆขๅค",
|
|
740
507
|
"toastCooldownRecovered": "ๅทฒ่งฃ้คๅทๅดๆขๅคๅฏ็จ",
|
|
741
508
|
"modelsCatalogTitle": "็ฒพ้่ฎข้
ๆจกๅ",
|
|
742
509
|
"modelsCatalogDesc": "ๅฝๅ DeepSeek Harness ๆดป่ท่ฎข้
ไธๅฏ็จๆจกๅไธ่งใ",
|
|
@@ -848,6 +615,11 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
848
615
|
"instructionsTitle": "่ทๅไปค็ๆๅผ",
|
|
849
616
|
"close": "ๅ
ณ้ญ",
|
|
850
617
|
"reconnectRequired": "้่ฆ้ๆฐ่ฟๆฅ",
|
|
618
|
+
"reconnectNow": "็ซๅณ้ๆฐ่ฎค่ฏ",
|
|
619
|
+
"scopeWarning": "OAuthๆ้่ๅด่ญฆๅ",
|
|
620
|
+
"reconnectScope": "้ๆฐๆๆๆ้",
|
|
621
|
+
"sessionRevokedBadge": "ๅทฒๅคฑๆ / ่ฟๆ",
|
|
622
|
+
"sessionRevokedWarning": "ไผ่ฏๅทฒ่ฟๆๆๅคฑๆ โ ้่ฆ้ๆฐๆๆ",
|
|
851
623
|
"manualTitle": "่ฅๆต่งๅจๆช่ฝ่ชๅจ่ทณ่ฝฌๅ่ฐ",
|
|
852
624
|
"updateChecking": "ๆฃๆฅๆดๆฐไธญโฆ",
|
|
853
625
|
"updateUpToDate": "ๅทฒๆฏๆๆฐ็ๆฌ",
|
|
@@ -889,6 +661,19 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
889
661
|
"releaseQuarantineTitle": "็ซๅณ่งฃ้ค่ดฆๆท้็ฆป็ถๆ",
|
|
890
662
|
"resetsIn": "้็ฝฎๅ่ฎกๆถ",
|
|
891
663
|
"toastQuarantined": "่ดฆๆท่ฟๅ
ฅ้็ฆปๆ",
|
|
664
|
+
"headlessTip": "ๆ ๅคด็ฏๅข / ่ฟ็จๆๅกๅจ๏ผ",
|
|
665
|
+
"headlessSshCommand": "SSH ็ซฏๅฃ่ฝฌๅๅฝไปค๏ผ",
|
|
666
|
+
"headlessCopySsh": "ๅคๅถ SSH ๅฝไปค",
|
|
667
|
+
"headlessCopied": "ๅทฒๅคๅถ๏ผ",
|
|
668
|
+
"headlessScanQr": "ไฝฟ็จๆๆบๆซๆไปฅ็ปๅฝ๏ผ",
|
|
669
|
+
"vaultSyncTitle": "่ฟ็จๅ ๅฏไฟ็ฎกๅบ่ชๅจๅๆญฅ",
|
|
670
|
+
"vaultSyncPush": "็ซๅณๅๆญฅ (ๆจ้)",
|
|
671
|
+
"vaultSyncPull": "็ซๅณๅๆญฅ (ๆๅ)",
|
|
672
|
+
"vaultSyncPushOk": "ไฟ็ฎกๅบๅทฒๆๅๆจ้ๅฐ่ฟ็จๅญๅจ",
|
|
673
|
+
"vaultSyncPullOk": "ๅทฒไป่ฟ็จๅญๅจๆๅๅนถๅๅนถไฟ็ฎกๅบ",
|
|
674
|
+
"vaultSyncBackend": "ๅญๅจๅ็ซฏ๏ผ",
|
|
675
|
+
"vaultSyncLastPush": "ไธๆฌกๆจ้๏ผ",
|
|
676
|
+
"vaultSyncLastPull": "ไธๆฌกๆๅ๏ผ",
|
|
892
677
|
"toastReleased": "่ดฆๆทๅทฒ่งฃ้ค้็ฆปๆขๅคไฝฟ็จ",
|
|
893
678
|
"toastQuotaWarning": "้ขๅบฆ้ข่ญฆ",
|
|
894
679
|
"enableToasts": "ๅบ็จๅ
ๅผน็ชๆ้",
|
|
@@ -965,6 +750,11 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
965
750
|
else if (p.indexOf('team') >= 0) label = 'Team'
|
|
966
751
|
else if (p.indexOf('plus') >= 0) label = 'Plus'
|
|
967
752
|
else if (p.indexOf('enterp') >= 0) label = 'Enterprise'
|
|
753
|
+
} else if (provider === 'claude') {
|
|
754
|
+
if (p.indexOf('enterp') >= 0) label = 'Enterprise'
|
|
755
|
+
else if (p.indexOf('team') >= 0) label = 'Team'
|
|
756
|
+
else if (p.indexOf('max') >= 0) label = 'Max'
|
|
757
|
+
else if (p.indexOf('pro') >= 0) label = 'Pro'
|
|
968
758
|
} else if (provider === 'grok') {
|
|
969
759
|
if (p.indexOf('super') >= 0) label = 'SuperGrok'
|
|
970
760
|
else if (p.indexOf('plus') >= 0) label = 'X Premium+'
|
|
@@ -976,8 +766,12 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
976
766
|
label = 'Coding Plan'
|
|
977
767
|
} else if (provider === 'glm') {
|
|
978
768
|
label = '150% Boost'
|
|
769
|
+
} else if (provider === 'perplexity') {
|
|
770
|
+
label = 'Pro'
|
|
771
|
+
} else if (provider === 'jetbrains') {
|
|
772
|
+
label = 'AI Assistant'
|
|
979
773
|
}
|
|
980
|
-
return label ?
|
|
774
|
+
return label ? h('span', { className: 'dsub-planBadge' }, label) : null
|
|
981
775
|
}
|
|
982
776
|
|
|
983
777
|
function formatRelativeReset(resetAt, lang, now) {
|
|
@@ -1005,22 +799,27 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1005
799
|
const ms = (props.resetAt || 0) - now
|
|
1006
800
|
if (ms <= 0) return null
|
|
1007
801
|
const total = Math.floor(ms / 1000)
|
|
802
|
+
const d = new Date(props.resetAt)
|
|
803
|
+
const pad = (n) => String(n).padStart(2, '0')
|
|
804
|
+
const timeStr = pad(d.getHours()) + ':' + pad(d.getMinutes())
|
|
805
|
+
const relStr = formatRelativeReset(props.resetAt, t('lang'), now)
|
|
1008
806
|
if (total > 3600) {
|
|
1009
|
-
return
|
|
1010
|
-
t('
|
|
807
|
+
return h('span', { className: 'dsub-sub', style: { fontVariantNumeric: 'tabular-nums' } },
|
|
808
|
+
'โณ ' + t('windowResetsAt') + ' ' + timeStr + ' (' + relStr + ')')
|
|
1011
809
|
}
|
|
1012
810
|
const m = Math.floor(total / 60)
|
|
1013
811
|
const sec = total % 60
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
t('resetLabel') + ' ' + pad(m) + ':' + pad(sec))
|
|
812
|
+
return h('span', { className: 'dsub-sub', style: { fontVariantNumeric: 'tabular-nums' } },
|
|
813
|
+
'โณ ' + t('windowResetsAt') + ' ' + timeStr + ' (' + relStr + ' ยท ' + pad(m) + ':' + pad(sec) + ')')
|
|
1017
814
|
}
|
|
1018
815
|
|
|
1019
816
|
function badgeFor(account, t) {
|
|
1020
817
|
if (!account || !account.configured) return t('notConnected')
|
|
818
|
+
if (account.isRevoked) return t('sessionRevokedBadge')
|
|
1021
819
|
if (account.validationUrl) return t('verifyAccount')
|
|
1022
820
|
// Issue 303: a quarantined account says why it is parked.
|
|
1023
821
|
if (account.quarantineReason && account.quarantineUntil && account.quarantineUntil > Date.now()) {
|
|
822
|
+
if (account.quarantineReason === 'SESSION_REVOKED' || account.quarantineReason === 'REVOKED') return t('sessionRevokedBadge')
|
|
1024
823
|
return account.quarantineReason === 'VERIFY' ? t('verifyAccount') : String(account.quarantineReason)
|
|
1025
824
|
}
|
|
1026
825
|
if (account.cooldownUntil && account.cooldownUntil > Date.now()) {
|
|
@@ -1045,8 +844,8 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1045
844
|
ChevronIcon = null
|
|
1046
845
|
}
|
|
1047
846
|
function FallbackChevron(props) {
|
|
1048
|
-
return
|
|
1049
|
-
|
|
847
|
+
return h('svg', { className: props.className, width: 14, height: 14, viewBox: '0 0 14 14', fill: 'none' },
|
|
848
|
+
h('path', { d: 'M3.5 5.25L7 8.75l3.5-3.5', stroke: 'currentColor', 'stroke-width': 1.5, 'stroke-linecap': 'round', 'stroke-linejoin': 'round' }),
|
|
1050
849
|
)
|
|
1051
850
|
}
|
|
1052
851
|
const Chevron = ChevronIcon || FallbackChevron
|
|
@@ -1172,6 +971,53 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1172
971
|
const [smoke, setSmoke] = React.useState({ testing: false, result: null })
|
|
1173
972
|
const [updater, setUpdater] = React.useState({ checking: false, updating: false, status: null, message: '' })
|
|
1174
973
|
const [backupModal, setBackupModal] = React.useState(null)
|
|
974
|
+
const [vaultSyncInfo, setVaultSyncInfo] = React.useState(null)
|
|
975
|
+
const [vaultSyncLoading, setVaultSyncLoading] = React.useState(false)
|
|
976
|
+
const [headlessInfo, setHeadlessInfo] = React.useState({})
|
|
977
|
+
const [copiedSsh, setCopiedSsh] = React.useState({})
|
|
978
|
+
|
|
979
|
+
const loadVaultSyncStatus = () => {
|
|
980
|
+
fetch('/dsh-subscriptions/vault/sync/status')
|
|
981
|
+
.then((r) => r.json())
|
|
982
|
+
.then((d) => { if (d && d.ok) setVaultSyncInfo(d.status) })
|
|
983
|
+
.catch(() => {})
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const doVaultSyncPush = async () => {
|
|
987
|
+
setBackupErr(''); setBackupInfo(''); setVaultSyncLoading(true)
|
|
988
|
+
try {
|
|
989
|
+
const res = await fetch('/dsh-subscriptions/vault/sync/push', {
|
|
990
|
+
method: 'POST',
|
|
991
|
+
headers: { 'Content-Type': 'application/json' },
|
|
992
|
+
})
|
|
993
|
+
const d = await res.json().catch(() => ({}))
|
|
994
|
+
if (!res.ok || !d.ok) throw new Error((d.error && d.error.message) || ('HTTP ' + res.status))
|
|
995
|
+
setBackupInfo(t('vaultSyncPushOk'))
|
|
996
|
+
if (d.status) setVaultSyncInfo(d.status)
|
|
997
|
+
} catch (e) {
|
|
998
|
+
setBackupErr(cleanErrorMessage(e.message || e))
|
|
999
|
+
}
|
|
1000
|
+
setVaultSyncLoading(false)
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
const doVaultSyncPull = async () => {
|
|
1004
|
+
setBackupErr(''); setBackupInfo(''); setVaultSyncLoading(true)
|
|
1005
|
+
try {
|
|
1006
|
+
const res = await fetch('/dsh-subscriptions/vault/sync/pull', {
|
|
1007
|
+
method: 'POST',
|
|
1008
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1009
|
+
})
|
|
1010
|
+
const d = await res.json().catch(() => ({}))
|
|
1011
|
+
if (!res.ok || !d.ok) throw new Error((d.error && d.error.message) || ('HTTP ' + res.status))
|
|
1012
|
+
setBackupInfo(t('vaultSyncPullOk') + (d.result ? ' (' + d.result.slotCount + ' slots)' : ''))
|
|
1013
|
+
if (d.status) setVaultSyncInfo(d.status)
|
|
1014
|
+
if (d.accounts) setAccounts(d.accounts)
|
|
1015
|
+
await reload()
|
|
1016
|
+
} catch (e) {
|
|
1017
|
+
setBackupErr(cleanErrorMessage(e.message || e))
|
|
1018
|
+
}
|
|
1019
|
+
setVaultSyncLoading(false)
|
|
1020
|
+
}
|
|
1175
1021
|
const [backupPass, setBackupPass] = React.useState('')
|
|
1176
1022
|
const [backupData, setBackupData] = React.useState('')
|
|
1177
1023
|
const [backupErr, setBackupErr] = React.useState('')
|
|
@@ -1246,7 +1092,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1246
1092
|
const url = URL.createObjectURL(blob)
|
|
1247
1093
|
const a = document.createElement('a')
|
|
1248
1094
|
a.href = url
|
|
1249
|
-
a.download = 'dsh-subscriptions-
|
|
1095
|
+
a.download = 'dsh-subscriptions-vault.enc'
|
|
1250
1096
|
document.body.appendChild(a)
|
|
1251
1097
|
a.click()
|
|
1252
1098
|
document.body.removeChild(a)
|
|
@@ -1309,6 +1155,45 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1309
1155
|
.catch(() => {})
|
|
1310
1156
|
}
|
|
1311
1157
|
|
|
1158
|
+
const doPing = async (provider, index) => {
|
|
1159
|
+
try {
|
|
1160
|
+
const res = await fetch('/dsh-subscriptions/ping', {
|
|
1161
|
+
method: 'POST',
|
|
1162
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1163
|
+
body: JSON.stringify({ provider, index }),
|
|
1164
|
+
})
|
|
1165
|
+
const d = await res.json()
|
|
1166
|
+
if (d && d.ok) {
|
|
1167
|
+
setAccounts((accs) => accs.map((a) => (a.provider === provider && a.index === index) ? Object.assign({}, a, { lastPingMs: d.latencyMs, latencyGrade: d.latencyGrade, lastDoctorVerdict: null }) : a))
|
|
1168
|
+
setInfo('๐ถ Ping: ' + d.latencyMs + 'ms (' + d.latencyGrade + ')')
|
|
1169
|
+
} else if (d && d.doctor) {
|
|
1170
|
+
setAccounts((accs) => accs.map((a) => (a.provider === provider && a.index === index) ? Object.assign({}, a, { lastPingMs: d.latencyMs, latencyGrade: d.latencyGrade, lastDoctorVerdict: d.doctor }) : a))
|
|
1171
|
+
setErr('๐ฉบ ' + d.doctor.title)
|
|
1172
|
+
}
|
|
1173
|
+
} catch (e) {
|
|
1174
|
+
setErr(cleanErrorMessage(e.message || e))
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
const doSyncModels = async (provider, index) => {
|
|
1179
|
+
try {
|
|
1180
|
+
const res = await fetch('/dsh-subscriptions/accounts/sync-models', {
|
|
1181
|
+
method: 'POST',
|
|
1182
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1183
|
+
body: JSON.stringify({ provider, index }),
|
|
1184
|
+
})
|
|
1185
|
+
const d = await res.json()
|
|
1186
|
+
if (d && d.ok) {
|
|
1187
|
+
setAccounts((accs) => accs.map((a) => (a.provider === provider && a.index === index) ? Object.assign({}, a, { availableModels: d.models }) : a))
|
|
1188
|
+
setInfo('โ ' + (t('modelsSynced') || 'Models synced') + ': ' + d.count + ' models')
|
|
1189
|
+
} else {
|
|
1190
|
+
setErr('โ ' + ((d && d.doctor && d.doctor.title) || (d && d.error && d.error.message) || 'Sync failed'))
|
|
1191
|
+
}
|
|
1192
|
+
} catch (e) {
|
|
1193
|
+
setErr(cleanErrorMessage(e.message || e))
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1312
1197
|
const runSmokeTest = async (provider, index) => {
|
|
1313
1198
|
setSmoke({ testing: true, result: null })
|
|
1314
1199
|
try {
|
|
@@ -1376,15 +1261,15 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1376
1261
|
// #81: settings snapshot status - never render phantom inputs before the
|
|
1377
1262
|
// config snapshot arrives, and offer a retry when the store is unavailable.
|
|
1378
1263
|
if (!draft) {
|
|
1379
|
-
return
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
err ?
|
|
1264
|
+
return h('div', { className: 'dsub-wrap' },
|
|
1265
|
+
h('div', { className: 'dsub-row' },
|
|
1266
|
+
h('span', { className: 'dsub-sub' }, err ? t('settingsUnavailable') : t('settingsLoading')),
|
|
1267
|
+
err ? h('button', {
|
|
1383
1268
|
type: 'button', className: 'dsub-mini',
|
|
1384
1269
|
onClick: () => { setErr(''); reload().catch((e) => setErr(String(e && e.message || e))) },
|
|
1385
1270
|
}, t('settingsRetry')) : null,
|
|
1386
1271
|
),
|
|
1387
|
-
err ?
|
|
1272
|
+
err ? h('div', { className: 'dsub-bad' }, err) : null,
|
|
1388
1273
|
)
|
|
1389
1274
|
}
|
|
1390
1275
|
|
|
@@ -1424,6 +1309,8 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1424
1309
|
const res = await fetch('/dsh-subscriptions/oauth/start?provider=' + encodeURIComponent(provider) + '&index=' + encodeURIComponent(index), { cache: 'no-store' })
|
|
1425
1310
|
const data = await res.json().catch(() => ({}))
|
|
1426
1311
|
if (!res.ok) throw new Error((data.error && data.error.message) || ('HTTP ' + res.status))
|
|
1312
|
+
const key = provider + ':' + index
|
|
1313
|
+
if (data.headless) setHeadlessInfo((m) => Object.assign({}, m, { [key]: data.headless }))
|
|
1427
1314
|
if (data.url) window.open(data.url, '_blank', 'noopener')
|
|
1428
1315
|
}
|
|
1429
1316
|
|
|
@@ -1439,6 +1326,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1439
1326
|
})
|
|
1440
1327
|
const data = await res.json().catch(() => ({}))
|
|
1441
1328
|
if (!res.ok) throw new Error((data.error && data.error.message) || ('HTTP ' + res.status))
|
|
1329
|
+
if (data.headless) setHeadlessInfo((m) => Object.assign({}, m, { [key]: data.headless }))
|
|
1442
1330
|
setDevice((m) => Object.assign({}, m, { [key]: { state: data.state, userCode: data.userCode, authUrl: data.authUrl, intervalMs: data.intervalMs || 5000, status: 'pending' } }))
|
|
1443
1331
|
}
|
|
1444
1332
|
|
|
@@ -1601,6 +1489,22 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1601
1489
|
setTokenDraft((d) => Object.assign({}, d, { [provider + ':' + index]: '' }))
|
|
1602
1490
|
}
|
|
1603
1491
|
|
|
1492
|
+
const switchOrg = async (provider, index, organizationId) => {
|
|
1493
|
+
setErr('')
|
|
1494
|
+
try {
|
|
1495
|
+
const res = await fetch('/dsh-subscriptions/accounts/switch-organization', {
|
|
1496
|
+
method: 'POST',
|
|
1497
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1498
|
+
body: JSON.stringify({ provider, index, organizationId }),
|
|
1499
|
+
})
|
|
1500
|
+
const data = await res.json().catch(() => ({}))
|
|
1501
|
+
if (!res.ok) throw new Error((data.error && data.error.message) || ('HTTP ' + res.status))
|
|
1502
|
+
if (data.accounts) setAccounts(data.accounts)
|
|
1503
|
+
} catch (e) {
|
|
1504
|
+
setErr(cleanErrorMessage(e.message || e))
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1604
1508
|
const addSlot = (provider) => {
|
|
1605
1509
|
const used = slots.filter((s) => s.provider === provider).map((s) => s.index)
|
|
1606
1510
|
let index = 1
|
|
@@ -1617,45 +1521,45 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1617
1521
|
|
|
1618
1522
|
const connectedCount = accounts.filter((a) => a.configured).length
|
|
1619
1523
|
|
|
1620
|
-
return
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1524
|
+
return h('div', { className: 'dsub-wrap' },
|
|
1525
|
+
h('div', { className: 'dsub-header-bar' },
|
|
1526
|
+
h('div', { className: 'dsub-row', style: { marginTop: 0 } },
|
|
1527
|
+
h('span', {
|
|
1624
1528
|
className: 'dsub-badge ' + (hostPing.ok ? 'dsub-badge-ok' : 'dsub-badge-bad')
|
|
1625
1529
|
}, hostPing.ok
|
|
1626
1530
|
? (hostPing.latencyMs != null ? 'Host online (' + hostPing.latencyMs + ' ms)' : t('hostOnline'))
|
|
1627
1531
|
: t('hostOffline')
|
|
1628
1532
|
),
|
|
1629
|
-
|
|
1533
|
+
h('span', {
|
|
1630
1534
|
className: 'dsub-badge ' + (connectedCount > 0 ? 'dsub-badge-ok' : 'dsub-badge-warn')
|
|
1631
1535
|
}, connectedCount > 0
|
|
1632
1536
|
? (connectedCount + ' ' + t('subsLogged'))
|
|
1633
1537
|
: t('subsNotLogged')
|
|
1634
1538
|
),
|
|
1635
|
-
|
|
1539
|
+
h('span', {
|
|
1636
1540
|
className: 'dsub-badge dsub-badge-neutral'
|
|
1637
1541
|
}, 'Pool: ' + accounts.length + ' accounts'),
|
|
1638
1542
|
updater.status && updater.status.updateAvailable
|
|
1639
|
-
?
|
|
1543
|
+
? h('span', { className: 'dsub-badge dsub-badge-warn' },
|
|
1640
1544
|
'โฌ ' + t('updateAvailable') + ' (v' + (updater.status.latestVersion || '') + ')'
|
|
1641
1545
|
)
|
|
1642
1546
|
: (updater.status && updater.status.currentVersion
|
|
1643
|
-
?
|
|
1547
|
+
? h('span', { className: 'dsub-badge dsub-badge-neutral' },
|
|
1644
1548
|
'v' + updater.status.currentVersion
|
|
1645
1549
|
)
|
|
1646
1550
|
: null
|
|
1647
1551
|
),
|
|
1648
1552
|
),
|
|
1649
|
-
|
|
1553
|
+
h('div', { className: 'dsub-row', style: { marginTop: 0, gap: '8px' } },
|
|
1650
1554
|
updater.status && updater.status.updateAvailable && updater.status.canAutoUpdate
|
|
1651
|
-
?
|
|
1555
|
+
? h('button', {
|
|
1652
1556
|
type: 'button',
|
|
1653
1557
|
className: 'dsub-mini dsub-btn-primary',
|
|
1654
1558
|
disabled: updater.updating,
|
|
1655
1559
|
onClick: () => performUpdate(),
|
|
1656
1560
|
}, updater.updating ? t('updating') : (t('updateNow') + ' โ v' + updater.status.latestVersion))
|
|
1657
1561
|
: null,
|
|
1658
|
-
|
|
1562
|
+
h('button', {
|
|
1659
1563
|
type: 'button',
|
|
1660
1564
|
className: 'dsub-mini',
|
|
1661
1565
|
disabled: smoke.testing,
|
|
@@ -1663,69 +1567,69 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1663
1567
|
}, smoke.testing ? t('smokeTesting') : t('runSmoke')),
|
|
1664
1568
|
),
|
|
1665
1569
|
),
|
|
1666
|
-
updater.message ?
|
|
1570
|
+
updater.message ? h('div', {
|
|
1667
1571
|
className: updater.message.includes(t('updateSuccessRestart')) ? 'dsub-alert-ok' : 'dsub-alert-bad',
|
|
1668
1572
|
style: { marginBottom: '12px' }
|
|
1669
1573
|
}, updater.message) : null,
|
|
1670
|
-
smoke.result ?
|
|
1574
|
+
smoke.result ? h('div', {
|
|
1671
1575
|
className: smoke.result.ok ? 'dsub-alert-ok' : 'dsub-alert-bad',
|
|
1672
1576
|
style: { marginBottom: '12px' }
|
|
1673
1577
|
}, smoke.result.ok
|
|
1674
1578
|
? ('๐ข ' + t('smokeOk') + ': ' + (smoke.result.provider || 'Provider').toUpperCase() + ' ยท ' + (smoke.result.latencyMs != null ? smoke.result.latencyMs + ' ms' : 'OK') + (smoke.result.label ? ' (' + smoke.result.label + ')' : ''))
|
|
1675
1579
|
: ('โ ' + t('smokeFail') + ': ' + (smoke.result.error && (smoke.result.error.message || smoke.result.error.code) || 'Unknown error'))
|
|
1676
1580
|
) : null,
|
|
1677
|
-
telemetry && telemetry.totalRequests > 0 ?
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1581
|
+
telemetry && telemetry.totalRequests > 0 ? h('div', { className: 'dsub-grid-2', style: { marginBottom: '14px' } },
|
|
1582
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1583
|
+
h('div', { className: 'dsub-stat-val' }, telemetry.successRequests + ' / ' + telemetry.totalRequests),
|
|
1584
|
+
h('div', { className: 'dsub-stat-lbl' }, t('statsRequests')),
|
|
1681
1585
|
),
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1586
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1587
|
+
h('div', { className: 'dsub-stat-val' }, (telemetry.avgLatencyMs || 0) + ' ms'),
|
|
1588
|
+
h('div', { className: 'dsub-stat-lbl' }, t('statsLatency')),
|
|
1685
1589
|
),
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1590
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1591
|
+
h('div', { className: 'dsub-stat-val' }, (telemetry.successRate || 100) + '%'),
|
|
1592
|
+
h('div', { className: 'dsub-stat-lbl' }, t('statsSuccessRate')),
|
|
1689
1593
|
),
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1594
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1595
|
+
h('div', { className: 'dsub-stat-val' }, (telemetry.cacheHitPercent || 0) + '%'),
|
|
1596
|
+
h('div', { className: 'dsub-stat-lbl' }, t('cacheHitRate')),
|
|
1693
1597
|
),
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1598
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1599
|
+
h('div', { className: 'dsub-stat-val' }, telemetry.lastRequestAt ? Math.round((Date.now() - telemetry.lastRequestAt) / 60000) + 'm ago' : 'โ'),
|
|
1600
|
+
h('div', { className: 'dsub-stat-lbl' }, t('statsLastActivity')),
|
|
1697
1601
|
),
|
|
1698
1602
|
) : null,
|
|
1699
|
-
(analytics && (analytics.totalRequests > 0 || (analytics.hourly && analytics.hourly.some(function(b) { return b.requests > 0 })))) || (queueStats && (queueStats.totalActive > 0 || queueStats.totalQueued > 0)) ?
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1603
|
+
(analytics && (analytics.totalRequests > 0 || (analytics.hourly && analytics.hourly.some(function(b) { return b.requests > 0 })))) || (queueStats && (queueStats.totalActive > 0 || queueStats.totalQueued > 0)) ? h('details', { className: 'dsub-group', open: true, style: { marginBottom: '14px' } },
|
|
1604
|
+
h('summary', { className: 'dsub-groupHead' }, '๐ ' + t('analyticsTitle')),
|
|
1605
|
+
h('div', { className: 'dsub-sub', style: { marginTop: '4px' } }, t('analyticsDesc')),
|
|
1606
|
+
h('div', { className: 'dsub-grid-2', style: { marginTop: '10px' } },
|
|
1607
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1608
|
+
h('div', { className: 'dsub-stat-val' }, ((analytics && analytics.cache && analytics.cache.cacheHitRate) || 0) + '%'),
|
|
1609
|
+
h('div', { className: 'dsub-stat-lbl' }, t('cacheHitRate') + (analytics && analytics.cache ? ' (' + (analytics.cache.cacheReadTokens || 0).toLocaleString() + ' tok)' : '')),
|
|
1706
1610
|
),
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1611
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1612
|
+
h('div', { className: 'dsub-stat-val' }, (analytics && analytics.performance && analytics.performance.ttft && analytics.performance.ttft.avgMs != null ? analytics.performance.ttft.avgMs + ' ms' : 'โ')),
|
|
1613
|
+
h('div', { className: 'dsub-stat-lbl' }, t('ttftMetric') + (analytics && analytics.performance && analytics.performance.ttft && analytics.performance.ttft.p95Ms != null ? ' ยท p95 ' + analytics.performance.ttft.p95Ms + ' ms' : '')),
|
|
1710
1614
|
),
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1615
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1616
|
+
h('div', { className: 'dsub-stat-val' }, (analytics && analytics.performance && analytics.performance.tps && analytics.performance.tps.avg != null ? analytics.performance.tps.avg + ' tok/s' : 'โ')),
|
|
1617
|
+
h('div', { className: 'dsub-stat-lbl' }, t('speedMetric') + (analytics && analytics.performance && analytics.performance.tps && analytics.performance.tps.p95 != null ? ' ยท p95 ' + analytics.performance.tps.p95 : '')),
|
|
1714
1618
|
),
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1619
|
+
h('div', { className: 'dsub-stat-box' },
|
|
1620
|
+
h('div', { className: 'dsub-stat-val' }, (queueStats ? queueStats.totalActive : 0) + ' / ' + (queueStats ? queueStats.totalQueued : 0)),
|
|
1621
|
+
h('div', { className: 'dsub-stat-lbl' }, t('queueActive') + ' / ' + t('queueWaiting') + (queueStats && queueStats.metrics && queueStats.metrics.totalOverflowed ? ' ยท ' + queueStats.metrics.totalOverflowed + ' ' + t('queueRejected') : '')),
|
|
1718
1622
|
),
|
|
1719
1623
|
),
|
|
1720
1624
|
analytics && Array.isArray(analytics.hourly) && analytics.hourly.length ? (function() {
|
|
1721
1625
|
var maxReq = Math.max.apply(Math, [1].concat(analytics.hourly.map(function(b) { return b.requests || 0 })))
|
|
1722
|
-
return
|
|
1723
|
-
|
|
1724
|
-
|
|
1626
|
+
return h('div', { style: { marginTop: '12px' } },
|
|
1627
|
+
h('div', { style: { fontSize: '11.5px', fontWeight: 600, color: 'var(--dsw-alias-label-secondary)' } }, t('activity24h')),
|
|
1628
|
+
h('div', { className: 'dsub-chart-wrap' },
|
|
1725
1629
|
analytics.hourly.map(function(b, idx) {
|
|
1726
1630
|
var pct = Math.max(4, Math.round(((b.requests || 0) / maxReq) * 100))
|
|
1727
1631
|
var title = b.label + ': ' + b.requests + ' req (' + b.cacheReadTokens + ' cached tok, ' + b.errorCount + ' err)'
|
|
1728
|
-
return
|
|
1632
|
+
return h('div', {
|
|
1729
1633
|
key: idx,
|
|
1730
1634
|
className: 'dsub-chart-bar',
|
|
1731
1635
|
style: {
|
|
@@ -1738,19 +1642,19 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1738
1642
|
})
|
|
1739
1643
|
})
|
|
1740
1644
|
),
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1645
|
+
h('div', { className: 'dsub-chart-labels' },
|
|
1646
|
+
h('span', null, '-24h'),
|
|
1647
|
+
h('span', null, '-18h'),
|
|
1648
|
+
h('span', null, '-12h'),
|
|
1649
|
+
h('span', null, '-6h'),
|
|
1650
|
+
h('span', null, 'Now'),
|
|
1747
1651
|
),
|
|
1748
1652
|
)
|
|
1749
1653
|
})() : null,
|
|
1750
|
-
analytics && Array.isArray(analytics.forecast) && analytics.forecast.some(function(f) { return f.willExhaustBeforeReset || (f.burnRateTokensPerHour > 0 && f.hoursToExhaustion != null && f.hoursToExhaustion < 72) }) ?
|
|
1751
|
-
|
|
1654
|
+
analytics && Array.isArray(analytics.forecast) && analytics.forecast.some(function(f) { return f.willExhaustBeforeReset || (f.burnRateTokensPerHour > 0 && f.hoursToExhaustion != null && f.hoursToExhaustion < 72) }) ? h('div', { style: { marginTop: '12px' } },
|
|
1655
|
+
h('div', { style: { fontSize: '11.5px', fontWeight: 600, color: 'var(--dsw-alias-state-warn-primary)', marginBottom: '6px' } }, 'โ ๏ธ ' + t('forecastTitle')),
|
|
1752
1656
|
analytics.forecast.filter(function(f) { return f.willExhaustBeforeReset || (f.burnRateTokensPerHour > 0 && f.hoursToExhaustion != null && f.hoursToExhaustion < 72) }).map(function(f, idx) {
|
|
1753
|
-
return
|
|
1657
|
+
return h('div', { key: idx, className: 'dsub-alert-bad', style: { marginBottom: '6px' } },
|
|
1754
1658
|
(f.provider ? f.provider.toUpperCase() : 'LLM') + ' (' + (f.label || f.ref) + '): ' +
|
|
1755
1659
|
(f.willExhaustBeforeReset ? t('forecastExhaustWarning') : (t('forecastRunway') + ': ~' + f.hoursToExhaustion + 'h')) +
|
|
1756
1660
|
' ยท ' + t('forecastBurnRate') + ': ' + f.burnRateTokensPerHour.toLocaleString() + ' tok/h'
|
|
@@ -1758,128 +1662,128 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1758
1662
|
})
|
|
1759
1663
|
) : null,
|
|
1760
1664
|
) : null,
|
|
1761
|
-
telemetry && Array.isArray(telemetry.recentDecisions) && telemetry.recentDecisions.length ?
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1665
|
+
telemetry && Array.isArray(telemetry.recentDecisions) && telemetry.recentDecisions.length ? h('details', { className: 'dsub-group', style: { marginBottom: '14px' } },
|
|
1666
|
+
h('summary', { className: 'dsub-groupHead' }, '๐งญ ' + t('rotationDecisionsTitle')),
|
|
1667
|
+
h('div', { className: 'dsub-sub', style: { marginTop: '4px' } }, t('rotationDecisionsDesc')),
|
|
1668
|
+
h('div', { className: 'dsub-trace-box' },
|
|
1765
1669
|
telemetry.recentDecisions.map((dec, idx) => {
|
|
1766
1670
|
const reasonBadge = dec.cascaded ? ('๐ ' + t('rotationCascaded')) : (dec.decisionReason === 'cache_pinned' ? ('๐ ' + t('cachePinnedBadge')) : (dec.decisionReason === 'session_pinned' ? '๐ Pinned' : ('โก ' + dec.decisionReason)))
|
|
1767
|
-
return
|
|
1768
|
-
|
|
1769
|
-
dec.provider ?
|
|
1770
|
-
|
|
1771
|
-
dec.model ?
|
|
1671
|
+
return h('div', { key: idx, className: 'dsub-trace-row' },
|
|
1672
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: '6px' } },
|
|
1673
|
+
dec.provider ? h('span', { className: 'dsub-brand dsub-brand-' + dec.provider, style: { fontSize: '9px', padding: '1px 4px' } }, dec.provider.toUpperCase()) : null,
|
|
1674
|
+
h('span', { style: { fontWeight: 600 } }, dec.ref || 'โ'),
|
|
1675
|
+
dec.model ? h('code', { style: { fontSize: '11px', opacity: 0.8 } }, dec.model) : null,
|
|
1772
1676
|
),
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1677
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
|
|
1678
|
+
h('span', { className: 'dsub-model-tag' }, reasonBadge),
|
|
1679
|
+
h('span', { style: { fontSize: '10.5px', opacity: 0.6 } }, dec.attemptsCount > 1 ? (dec.attemptsCount + ' ' + t('rotationAttempts')) : ('1 ' + t('rotationAttempt'))),
|
|
1776
1680
|
),
|
|
1777
1681
|
)
|
|
1778
1682
|
})
|
|
1779
1683
|
),
|
|
1780
1684
|
) : null,
|
|
1781
|
-
accounts && accounts.length ?
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1685
|
+
accounts && accounts.length ? h('details', { className: 'dsub-group', open: true, style: { marginBottom: '14px' } },
|
|
1686
|
+
h('summary', { className: 'dsub-groupHead' }, '๐ ' + (t('healthMatrix') || 'Health Matrix & Quota Runway')),
|
|
1687
|
+
h('div', { style: { padding: '8px 0', overflowX: 'auto' } },
|
|
1688
|
+
h('table', { style: { width: '100%', fontSize: '12px', borderCollapse: 'collapse' } },
|
|
1689
|
+
h('thead', null,
|
|
1690
|
+
h('tr', { style: { borderBottom: '1px solid var(--dsw-alias-border-l2)', textAlign: 'left', opacity: 0.7 } },
|
|
1691
|
+
h('th', { style: { padding: '6px' } }, t('healthAccount')),
|
|
1692
|
+
h('th', { style: { padding: '6px' } }, t('healthScore')),
|
|
1693
|
+
h('th', { style: { padding: '6px' } }, t('healthLatency')),
|
|
1694
|
+
h('th', { style: { padding: '6px' } }, t('healthStatus')),
|
|
1695
|
+
h('th', { style: { padding: '6px' } }, t('healthQuota')),
|
|
1792
1696
|
),
|
|
1793
1697
|
),
|
|
1794
|
-
|
|
1698
|
+
h('tbody', null,
|
|
1795
1699
|
accounts.map((acc, idx) => {
|
|
1796
1700
|
const sc = acc.healthScore != null ? acc.healthScore : 100
|
|
1797
1701
|
const healthColor = sc >= 80 ? 'var(--dsw-alias-state-success-primary)' : (sc >= 50 ? 'var(--dsw-alias-state-warn-primary)' : 'var(--dsw-alias-state-error-primary)')
|
|
1798
1702
|
const isQ = acc.status === 'quarantine' || (acc.quarantineUntil && Number(acc.quarantineUntil) > Date.now())
|
|
1799
1703
|
const statusLabel = isQ ? ('โ ' + t('healthQuarantine')) : (acc.status === 'probing' ? ('๐ก ' + t('healthWarmup')) : (acc.configured ? ('๐ข ' + t('healthActive')) : ('โช ' + t('healthIdle'))))
|
|
1800
1704
|
const pct = acc.usagePercent != null ? Math.round(acc.usagePercent) : null
|
|
1801
|
-
return
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1705
|
+
return h('tr', { key: (acc.ref || acc.provider + acc.index || idx), style: { borderBottom: '1px solid var(--dsw-alias-border-l3)' } },
|
|
1706
|
+
h('td', { style: { padding: '6px', fontWeight: 600 } }, (acc.provider ? acc.provider.toUpperCase() : 'LLM') + ' #' + (acc.index || 1) + (acc.label ? ' (' + acc.label + ')' : '')),
|
|
1707
|
+
h('td', { style: { padding: '6px', color: healthColor } }, sc + '%'),
|
|
1708
|
+
h('td', { style: { padding: '6px' } }, acc.latencyMs ? acc.latencyMs + ' ms' : 'โ'),
|
|
1709
|
+
h('td', { style: { padding: '6px' } }, statusLabel),
|
|
1710
|
+
h('td', { style: { padding: '6px' } }, pct != null ? (pct + '% used') : 'โ'),
|
|
1807
1711
|
)
|
|
1808
1712
|
}),
|
|
1809
1713
|
),
|
|
1810
1714
|
),
|
|
1811
1715
|
),
|
|
1812
1716
|
) : null,
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1717
|
+
h('div', { className: 'dsub-block' },
|
|
1718
|
+
h('div', { className: 'dsub-h' }, t('title')),
|
|
1719
|
+
h('div', { className: 'dsub-sub' },
|
|
1816
1720
|
t('intro')),
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1721
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1722
|
+
h('summary', { className: 'dsub-groupHead' }, t('groupAuth')),
|
|
1723
|
+
h('label', { className: 'dsub-row' },
|
|
1724
|
+
h('input', {
|
|
1821
1725
|
type: 'checkbox',
|
|
1822
1726
|
checked: !!draft.useWebCallback,
|
|
1823
1727
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { useWebCallback: e.target.checked })),
|
|
1824
1728
|
}),
|
|
1825
|
-
|
|
1729
|
+
h('span', null, t('useOrigin')),
|
|
1826
1730
|
),
|
|
1827
|
-
|
|
1731
|
+
h('div', { className: 'dsub-sub' },
|
|
1828
1732
|
t('useOriginHint')),
|
|
1829
|
-
|
|
1830
|
-
|
|
1733
|
+
h('label', { className: 'dsub-row' },
|
|
1734
|
+
h('input', {
|
|
1831
1735
|
type: 'checkbox',
|
|
1832
1736
|
checked: !!draft.autoLoopback,
|
|
1833
1737
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { autoLoopback: e.target.checked })),
|
|
1834
1738
|
}),
|
|
1835
|
-
|
|
1739
|
+
h('span', null, t('autoLoopback')),
|
|
1836
1740
|
),
|
|
1837
|
-
|
|
1741
|
+
h('div', { className: 'dsub-sub' },
|
|
1838
1742
|
t('autoLoopbackHint')),
|
|
1839
1743
|
),
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1744
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1745
|
+
h('summary', { className: 'dsub-groupHead' }, t('groupPrivacy')),
|
|
1746
|
+
h('label', { className: 'dsub-row' },
|
|
1747
|
+
h('input', {
|
|
1844
1748
|
type: 'checkbox',
|
|
1845
1749
|
checked: !!draft.privacyMask,
|
|
1846
1750
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { privacyMask: e.target.checked })),
|
|
1847
1751
|
}),
|
|
1848
|
-
|
|
1752
|
+
h('span', null, t('privacyMask')),
|
|
1849
1753
|
),
|
|
1850
|
-
|
|
1754
|
+
h('div', { className: 'dsub-sub' },
|
|
1851
1755
|
t('privacyMaskHint')),
|
|
1852
|
-
|
|
1853
|
-
|
|
1756
|
+
h('label', { className: 'dsub-row' },
|
|
1757
|
+
h('input', {
|
|
1854
1758
|
type: 'checkbox',
|
|
1855
1759
|
checked: !!draft.hideDeprecatedModels,
|
|
1856
1760
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { hideDeprecatedModels: e.target.checked })),
|
|
1857
1761
|
}),
|
|
1858
|
-
|
|
1762
|
+
h('span', null, t('hideDeprecated')),
|
|
1859
1763
|
),
|
|
1860
|
-
|
|
1764
|
+
h('div', { className: 'dsub-sub' },
|
|
1861
1765
|
t('hideDeprecatedHint')),
|
|
1862
1766
|
),
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1767
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1768
|
+
h('summary', { className: 'dsub-groupHead' }, t('groupRotation')),
|
|
1769
|
+
h('div', { className: 'dsub-row' },
|
|
1770
|
+
h('span', { className: 'dsub-h' }, t('composerQuota')),
|
|
1771
|
+
h('select', {
|
|
1868
1772
|
className: 'dsub-select',
|
|
1869
1773
|
value: draft.composerQuota || 'percent',
|
|
1870
1774
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { composerQuota: e.target.value })),
|
|
1871
1775
|
},
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1776
|
+
h('option', { value: 'off' }, t('composerQuotaOff')),
|
|
1777
|
+
h('option', { value: 'percent' }, t('composerQuotaPercent')),
|
|
1778
|
+
h('option', { value: 'bar' }, t('composerQuotaBar')),
|
|
1779
|
+
h('option', { value: 'forecast' }, t('composerQuotaForecast')),
|
|
1876
1780
|
),
|
|
1877
1781
|
),
|
|
1878
|
-
|
|
1782
|
+
h('div', { className: 'dsub-sub' },
|
|
1879
1783
|
t('composerQuotaHint')),
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1784
|
+
h('div', { className: 'dsub-row' },
|
|
1785
|
+
h('span', { className: 'dsub-h' }, t('expiryNotifyDays')),
|
|
1786
|
+
h('input', {
|
|
1883
1787
|
type: 'number',
|
|
1884
1788
|
className: 'dsub-inp',
|
|
1885
1789
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -1889,23 +1793,23 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1889
1793
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { expiryNotifyDays: Number(e.target.value) || 0 })),
|
|
1890
1794
|
}),
|
|
1891
1795
|
),
|
|
1892
|
-
|
|
1796
|
+
h('div', { className: 'dsub-sub' },
|
|
1893
1797
|
t('expiryNotifyDaysHint')),
|
|
1894
1798
|
),
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1799
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1800
|
+
h('summary', { className: 'dsub-groupHead' }, '๐ฆ ' + t('groupQueue')),
|
|
1801
|
+
h('label', { className: 'dsub-row' },
|
|
1802
|
+
h('input', {
|
|
1899
1803
|
type: 'checkbox',
|
|
1900
1804
|
checked: draft.enableQueue !== false,
|
|
1901
1805
|
onChange: function(e) { setDraft(function(d) { return Object.assign({}, d, { enableQueue: e.target.checked }) }) },
|
|
1902
1806
|
}),
|
|
1903
|
-
|
|
1807
|
+
h('span', null, t('enableQueue')),
|
|
1904
1808
|
),
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1809
|
+
h('div', { className: 'dsub-sub' }, t('enableQueueHint')),
|
|
1810
|
+
h('div', { className: 'dsub-row' },
|
|
1811
|
+
h('span', { className: 'dsub-h' }, t('accountMaxConcurrency')),
|
|
1812
|
+
h('input', {
|
|
1909
1813
|
type: 'number',
|
|
1910
1814
|
className: 'dsub-inp',
|
|
1911
1815
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -1915,10 +1819,10 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1915
1819
|
onChange: function(e) { setDraft(function(d) { return Object.assign({}, d, { accountMaxConcurrency: Math.max(1, Number(e.target.value) || 2) }) }) },
|
|
1916
1820
|
}),
|
|
1917
1821
|
),
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1822
|
+
h('div', { className: 'dsub-sub' }, t('accountMaxConcurrencyHint')),
|
|
1823
|
+
h('div', { className: 'dsub-row' },
|
|
1824
|
+
h('span', { className: 'dsub-h' }, t('maxQueueSize')),
|
|
1825
|
+
h('input', {
|
|
1922
1826
|
type: 'number',
|
|
1923
1827
|
className: 'dsub-inp',
|
|
1924
1828
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -1928,10 +1832,10 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1928
1832
|
onChange: function(e) { setDraft(function(d) { return Object.assign({}, d, { maxQueueSize: Math.max(1, Number(e.target.value) || 20) }) }) },
|
|
1929
1833
|
}),
|
|
1930
1834
|
),
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1835
|
+
h('div', { className: 'dsub-sub' }, t('maxQueueSizeHint')),
|
|
1836
|
+
h('div', { className: 'dsub-row' },
|
|
1837
|
+
h('span', { className: 'dsub-h' }, t('queueTimeoutSec')),
|
|
1838
|
+
h('input', {
|
|
1935
1839
|
type: 'number',
|
|
1936
1840
|
className: 'dsub-inp',
|
|
1937
1841
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -1941,52 +1845,52 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1941
1845
|
onChange: function(e) { setDraft(function(d) { return Object.assign({}, d, { queueTimeoutMs: Math.max(1, Number(e.target.value) || 30) * 1000 }) }) },
|
|
1942
1846
|
}),
|
|
1943
1847
|
),
|
|
1944
|
-
|
|
1848
|
+
h('div', { className: 'dsub-sub' }, t('queueTimeoutSecHint')),
|
|
1945
1849
|
),
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1850
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1851
|
+
h('summary', { className: 'dsub-groupHead' }, t('groupProvider')),
|
|
1852
|
+
h('label', { className: 'dsub-row' },
|
|
1853
|
+
h('input', {
|
|
1950
1854
|
type: 'checkbox',
|
|
1951
1855
|
checked: !!draft.codexFastMode,
|
|
1952
1856
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { codexFastMode: e.target.checked })),
|
|
1953
1857
|
}),
|
|
1954
|
-
|
|
1858
|
+
h('span', null, t('codexFastMode')),
|
|
1955
1859
|
),
|
|
1956
|
-
|
|
1860
|
+
h('div', { className: 'dsub-sub' },
|
|
1957
1861
|
t('codexFastModeHint')),
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1862
|
+
h('div', { className: 'dsub-row' },
|
|
1863
|
+
h('span', { className: 'dsub-h' }, t('codexVerbosity')),
|
|
1864
|
+
h('select', {
|
|
1961
1865
|
className: 'dsub-select',
|
|
1962
1866
|
value: draft.codexVerbosity || 'default',
|
|
1963
1867
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { codexVerbosity: e.target.value })),
|
|
1964
1868
|
},
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1869
|
+
h('option', { value: 'default' }, t('codexVerbosityDefault')),
|
|
1870
|
+
h('option', { value: 'low' }, t('codexVerbosityLow')),
|
|
1871
|
+
h('option', { value: 'medium' }, t('codexVerbosityMedium')),
|
|
1872
|
+
h('option', { value: 'high' }, t('codexVerbosityHigh')),
|
|
1969
1873
|
),
|
|
1970
1874
|
),
|
|
1971
|
-
|
|
1875
|
+
h('div', { className: 'dsub-sub' },
|
|
1972
1876
|
t('codexVerbosityHint')),
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1877
|
+
h('div', { className: 'dsub-row' },
|
|
1878
|
+
h('span', { className: 'dsub-h' }, t('copilotMode')),
|
|
1879
|
+
h('select', {
|
|
1976
1880
|
className: 'dsub-select',
|
|
1977
1881
|
value: draft.copilotMode || 'auto',
|
|
1978
1882
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { copilotMode: e.target.value })),
|
|
1979
1883
|
},
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1884
|
+
h('option', { value: 'auto' }, t('copilotModeAuto')),
|
|
1885
|
+
h('option', { value: 'cli' }, t('copilotModeCli')),
|
|
1886
|
+
h('option', { value: 'web' }, t('copilotModeWeb')),
|
|
1983
1887
|
),
|
|
1984
1888
|
),
|
|
1985
|
-
|
|
1889
|
+
h('div', { className: 'dsub-sub' },
|
|
1986
1890
|
t('copilotModeHint')),
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1891
|
+
h('div', { className: 'dsub-row' },
|
|
1892
|
+
h('span', { className: 'dsub-h' }, t('copilotCliPath')),
|
|
1893
|
+
h('input', {
|
|
1990
1894
|
className: 'dsub-input',
|
|
1991
1895
|
type: 'text',
|
|
1992
1896
|
value: draft.copilotCliPath || '',
|
|
@@ -1994,30 +1898,30 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
1994
1898
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { copilotCliPath: e.target.value })),
|
|
1995
1899
|
}),
|
|
1996
1900
|
),
|
|
1997
|
-
|
|
1901
|
+
h('div', { className: 'dsub-sub' },
|
|
1998
1902
|
t('copilotCliPathHint')),
|
|
1999
1903
|
),
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
1904
|
+
h('details', { className: 'dsub-group', open: true },
|
|
1905
|
+
h('summary', { className: 'dsub-groupHead' }, t('groupFallback')),
|
|
1906
|
+
h('label', { className: 'dsub-row' },
|
|
1907
|
+
h('input', {
|
|
2004
1908
|
type: 'checkbox',
|
|
2005
1909
|
checked: !!draft.ollamaFallback,
|
|
2006
1910
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { ollamaFallback: e.target.checked })),
|
|
2007
1911
|
}),
|
|
2008
|
-
|
|
1912
|
+
h('span', null, t('ollamaFallback')),
|
|
2009
1913
|
),
|
|
2010
|
-
|
|
1914
|
+
h('div', { className: 'dsub-sub' },
|
|
2011
1915
|
t('ollamaFallbackHint')),
|
|
2012
|
-
draft.ollamaFallback ?
|
|
2013
|
-
|
|
1916
|
+
draft.ollamaFallback ? h('div', { className: 'dsub-row' },
|
|
1917
|
+
h('input', {
|
|
2014
1918
|
type: 'text',
|
|
2015
1919
|
className: 'dsub-inp dsub-grow',
|
|
2016
1920
|
placeholder: 'http://localhost:11434',
|
|
2017
1921
|
value: draft.ollamaBaseUrl || '',
|
|
2018
1922
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { ollamaBaseUrl: e.target.value })),
|
|
2019
1923
|
}),
|
|
2020
|
-
|
|
1924
|
+
h('input', {
|
|
2021
1925
|
type: 'text',
|
|
2022
1926
|
className: 'dsub-inp dsub-grow',
|
|
2023
1927
|
placeholder: 'llama3:latest',
|
|
@@ -2026,10 +1930,10 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2026
1930
|
}),
|
|
2027
1931
|
) : null,
|
|
2028
1932
|
),
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1933
|
+
h('details', { className: 'dsub-group' },
|
|
1934
|
+
h('summary', { className: 'dsub-groupHead' }, '๐ฏ ' + t('modelsCatalogTitle')),
|
|
1935
|
+
h('div', { className: 'dsub-sub', style: { marginTop: '4px' } }, t('modelsCatalogDesc')),
|
|
1936
|
+
h('div', { className: 'dsub-model-grid' },
|
|
2033
1937
|
(Array.isArray(modelsCatalog) && modelsCatalog.length ? modelsCatalog : [
|
|
2034
1938
|
{ id: 'gpt-4o', contextLabel: '128k', capabilities: ['vision'], pool: { status: 'available' } },
|
|
2035
1939
|
{ id: 'o1 / o3-mini', contextLabel: '200k', capabilities: ['reasoning'], pool: { status: 'available' } },
|
|
@@ -2068,22 +1972,22 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2068
1972
|
}
|
|
2069
1973
|
}
|
|
2070
1974
|
|
|
2071
|
-
return
|
|
2072
|
-
m.provider ?
|
|
2073
|
-
|
|
2074
|
-
tags.length ?
|
|
2075
|
-
|
|
1975
|
+
return h('div', { key: (m.id || idx) + '_' + idx, className: 'dsub-model-chip' },
|
|
1976
|
+
m.provider ? h('span', { className: 'dsub-brand dsub-brand-' + m.provider, style: { fontSize: '9px', padding: '1px 4px' } }, m.provider.toUpperCase()) : null,
|
|
1977
|
+
h('code', null, m.name || m.id),
|
|
1978
|
+
tags.length ? h('span', { className: 'dsub-model-tag' }, tags.join(' ยท ')) : null,
|
|
1979
|
+
h('span', { className: 'dsub-model-tag ' + statusClass }, poolLabel),
|
|
2076
1980
|
)
|
|
2077
1981
|
})
|
|
2078
1982
|
),
|
|
2079
1983
|
),
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
1984
|
+
h('details', { className: 'dsub-group' },
|
|
1985
|
+
h('summary', { className: 'dsub-groupHead' }, '๐ง ' + t('reasoningEffortTitle')),
|
|
1986
|
+
h('div', { className: 'dsub-sub', style: { marginTop: '4px' } }, t('reasoningEffortDesc')),
|
|
1987
|
+
h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '10px' } },
|
|
2084
1988
|
['off', 'low', 'medium', 'high', 'max'].map((lvl) => {
|
|
2085
1989
|
const label = lvl === 'off' ? t('reasoningLevelOff') : (lvl.charAt(0).toUpperCase() + lvl.slice(1))
|
|
2086
|
-
return
|
|
1990
|
+
return h('span', {
|
|
2087
1991
|
key: lvl,
|
|
2088
1992
|
className: 'dsub-model-tag',
|
|
2089
1993
|
style: { padding: '4px 10px', fontSize: '12px', cursor: 'default' }
|
|
@@ -2091,12 +1995,12 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2091
1995
|
})
|
|
2092
1996
|
)
|
|
2093
1997
|
),
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1998
|
+
h('details', { className: 'dsub-details' },
|
|
1999
|
+
h('summary', { className: 'dsub-summary' }, t('advancedSettings')),
|
|
2000
|
+
h('div', { className: 'dsub-block' },
|
|
2001
|
+
h('div', { className: 'dsub-row' },
|
|
2002
|
+
h('span', { className: 'dsub-h' }, t('cooldownMs')),
|
|
2003
|
+
h('input', {
|
|
2100
2004
|
type: 'number',
|
|
2101
2005
|
className: 'dsub-inp',
|
|
2102
2006
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -2106,10 +2010,10 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2106
2010
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { cooldownMs: (Number(e.target.value) || 10) * 60000 })),
|
|
2107
2011
|
}),
|
|
2108
2012
|
),
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2013
|
+
h('div', { className: 'dsub-sub' }, t('cooldownMsHint')),
|
|
2014
|
+
h('div', { className: 'dsub-row' },
|
|
2015
|
+
h('span', { className: 'dsub-h' }, t('probeIntervalMin')),
|
|
2016
|
+
h('input', {
|
|
2113
2017
|
type: 'number',
|
|
2114
2018
|
className: 'dsub-inp',
|
|
2115
2019
|
style: { width: '80px', minWidth: '80px' },
|
|
@@ -2119,34 +2023,34 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2119
2023
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { probeIntervalMin: Number(e.target.value) || 15 })),
|
|
2120
2024
|
}),
|
|
2121
2025
|
),
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2026
|
+
h('div', { className: 'dsub-sub' }, t('probeIntervalMinHint')),
|
|
2027
|
+
h('label', { className: 'dsub-row' },
|
|
2028
|
+
h('input', {
|
|
2125
2029
|
type: 'checkbox',
|
|
2126
2030
|
checked: draft.notifyLimits !== false,
|
|
2127
2031
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { notifyLimits: e.target.checked })),
|
|
2128
2032
|
}),
|
|
2129
|
-
|
|
2033
|
+
h('span', null, t('notifyLimits')),
|
|
2130
2034
|
),
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2035
|
+
h('div', { className: 'dsub-sub' }, t('notifyLimitsHint')),
|
|
2036
|
+
h('label', { className: 'dsub-row', style: { marginTop: 10 } },
|
|
2037
|
+
h('input', {
|
|
2134
2038
|
type: 'checkbox',
|
|
2135
2039
|
checked: Boolean(draft.cascadingFallback),
|
|
2136
2040
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { cascadingFallback: e.target.checked })),
|
|
2137
2041
|
}),
|
|
2138
|
-
|
|
2042
|
+
h('span', null, t('cascadingFallback')),
|
|
2139
2043
|
),
|
|
2140
|
-
|
|
2141
|
-
Boolean(draft.cascadingFallback) ?
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2044
|
+
h('div', { className: 'dsub-sub' }, t('cascadingFallbackHint')),
|
|
2045
|
+
Boolean(draft.cascadingFallback) ? h('div', { style: { marginTop: 8, padding: '8px 12px', background: 'var(--dsw-alias-bg-layer-2)', borderRadius: 8 } },
|
|
2046
|
+
h('div', { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 } }, t('cascadingFallbackOrder')),
|
|
2047
|
+
h('div', { className: 'dsub-sub', style: { marginBottom: 8 } }, t('cascadingFallbackOrderHint')),
|
|
2048
|
+
h('div', { style: { display: 'flex', flexDirection: 'column', gap: 4 } },
|
|
2145
2049
|
(Array.isArray(draft.cascadingFallbackOrder) && draft.cascadingFallbackOrder.length ? draft.cascadingFallbackOrder : (providers.length ? providers : ['antigravity', 'claude', 'codex', 'grok', 'copilot', 'cursor'])).map((p, idx, arr) => {
|
|
2146
|
-
return
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
idx > 0 ?
|
|
2050
|
+
return h('div', { key: p, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 8px', background: 'var(--dsw-alias-bg-layer-1)', borderRadius: 6, fontSize: 12 } },
|
|
2051
|
+
h('span', null, (idx + 1) + '. ' + p.toUpperCase()),
|
|
2052
|
+
h('div', { style: { display: 'flex', gap: 4 } },
|
|
2053
|
+
idx > 0 ? h('button', {
|
|
2150
2054
|
type: 'button', className: 'dsub-mini', style: { padding: '1px 6px', fontSize: 10 },
|
|
2151
2055
|
onClick: () => {
|
|
2152
2056
|
const next = arr.slice()
|
|
@@ -2156,7 +2060,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2156
2060
|
setDraft((d) => Object.assign({}, d, { cascadingFallbackOrder: next }))
|
|
2157
2061
|
}
|
|
2158
2062
|
}, 'โฒ') : null,
|
|
2159
|
-
idx < arr.length - 1 ?
|
|
2063
|
+
idx < arr.length - 1 ? h('button', {
|
|
2160
2064
|
type: 'button', className: 'dsub-mini', style: { padding: '1px 6px', fontSize: 10 },
|
|
2161
2065
|
onClick: () => {
|
|
2162
2066
|
const next = arr.slice()
|
|
@@ -2172,62 +2076,62 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2172
2076
|
)
|
|
2173
2077
|
) : null,
|
|
2174
2078
|
),
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2079
|
+
h('div', { className: 'dsub-row', style: { marginTop: 12 } },
|
|
2080
|
+
h('label', { style: { display: 'flex', flexDirection: 'column', gap: 4 } },
|
|
2081
|
+
h('span', { style: { fontWeight: 600 } }, t('rotationStrategy')),
|
|
2082
|
+
h('span', { className: 'dsub-sub' }, t('rotationStrategyHint')),
|
|
2083
|
+
h('select', {
|
|
2180
2084
|
className: 'dsub-select',
|
|
2181
2085
|
value: draft.rotationStrategy || 'round-robin',
|
|
2182
2086
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { rotationStrategy: e.target.value })),
|
|
2183
2087
|
style: { maxWidth: 320, marginTop: 4 }
|
|
2184
2088
|
},
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2089
|
+
h('option', { value: 'round-robin' }, t('rotationRoundRobin')),
|
|
2090
|
+
h('option', { value: 'least-loaded' }, t('rotationLeastLoaded')),
|
|
2091
|
+
h('option', { value: 'priority' }, t('rotationPriority')),
|
|
2188
2092
|
),
|
|
2189
2093
|
),
|
|
2190
2094
|
),
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2095
|
+
h('div', { className: 'dsub-row', style: { marginTop: 12 } },
|
|
2096
|
+
h('label', { style: { display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer' } },
|
|
2097
|
+
h('input', {
|
|
2194
2098
|
type: 'checkbox',
|
|
2195
2099
|
checked: draft.enableSoftFailureSentinel !== false,
|
|
2196
2100
|
onChange: (e) => setDraft((d) => Object.assign({}, d, { enableSoftFailureSentinel: e.target.checked })),
|
|
2197
2101
|
}),
|
|
2198
|
-
|
|
2102
|
+
h('span', null, t('softFailureSentinel')),
|
|
2199
2103
|
),
|
|
2200
|
-
|
|
2104
|
+
h('div', { className: 'dsub-sub' }, t('softFailureSentinelHint')),
|
|
2201
2105
|
),
|
|
2202
2106
|
),
|
|
2203
2107
|
),
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2108
|
+
h('div', { className: 'dsub-block' },
|
|
2109
|
+
h('div', { className: 'dsub-row' },
|
|
2110
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: () => runWizard(null, null, null, false) }, '๐ฉบ ' + t('wizardAll')),
|
|
2111
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: genDiag }, t('diagGenerate')),
|
|
2112
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: runAnalyzeSession }, analyzingCache ? 'โฆ' : t('cacheAnalyze')),
|
|
2113
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: () => { setBackupModal('export'); setBackupErr(''); setBackupInfo(''); loadVaultSyncStatus() } }, '๐ ' + t('backupExport')),
|
|
2114
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: () => { setBackupModal('import'); setBackupErr(''); setBackupInfo(''); loadVaultSyncStatus() } }, '๐ฅ ' + t('backupImport')),
|
|
2115
|
+
h('a', { href: 'https://github.com/GooDAnDReaDY/dsh-subscriptions/issues', target: '_blank', rel: 'noopener noreferrer', className: 'dsub-mini' }, t('diagIssues')),
|
|
2212
2116
|
),
|
|
2213
|
-
|
|
2214
|
-
sessionAnalysis ?
|
|
2117
|
+
h('div', { className: 'dsub-sub' }, t('diagHint')),
|
|
2118
|
+
sessionAnalysis ? h('div', { className: 'dsub-sub', style: { marginTop: '6px', fontWeight: 500 } },
|
|
2215
2119
|
t('cacheHitRate') + ': ' + sessionAnalysis.weightedCacheHitPercent + '% ยท ' +
|
|
2216
2120
|
t('tokensSaved') + ': ' + sessionAnalysis.savedTokens + ' / ' + sessionAnalysis.totalTokens
|
|
2217
2121
|
) : null,
|
|
2218
|
-
diag ?
|
|
2219
|
-
|
|
2122
|
+
diag ? h('div', { className: 'dsub-row' },
|
|
2123
|
+
h('button', {
|
|
2220
2124
|
type: 'button', className: 'dsub-mini',
|
|
2221
2125
|
onClick: () => { try { navigator.clipboard.writeText(diag) } catch { /* clipboard write error */ } },
|
|
2222
2126
|
}, t('diagCopy')),
|
|
2223
|
-
|
|
2127
|
+
h('pre', { className: 'dsub-diag' }, diag),
|
|
2224
2128
|
) : null,
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2129
|
+
h('details', { className: 'dsub-details', style: { marginTop: 12 } },
|
|
2130
|
+
h('summary', { className: 'dsub-summary' }, 'โ ๏ธ ' + t('recentErrors')),
|
|
2131
|
+
h('div', { className: 'dsub-block' },
|
|
2132
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 } },
|
|
2133
|
+
h('span', { className: 'dsub-sub' }, t('recentErrorsDesc')),
|
|
2134
|
+
h('button', {
|
|
2231
2135
|
type: 'button', className: 'dsub-mini',
|
|
2232
2136
|
onClick: async () => {
|
|
2233
2137
|
await fetch('/dsh-subscriptions/diagnostics/errors/clear', { method: 'POST' }).catch(() => {})
|
|
@@ -2236,79 +2140,79 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2236
2140
|
}, t('recentErrorsClear'))
|
|
2237
2141
|
),
|
|
2238
2142
|
(diagReport && Array.isArray(diagReport.recentErrors) && diagReport.recentErrors.length ? diagReport.recentErrors : []).length === 0
|
|
2239
|
-
?
|
|
2240
|
-
:
|
|
2241
|
-
(diagReport.recentErrors || []).map((err, i) =>
|
|
2143
|
+
? h('div', { className: 'dsub-dim', style: { padding: 8 } }, t('recentErrorsEmpty'))
|
|
2144
|
+
: h('div', { style: { display: 'flex', flexDirection: 'column', gap: 6 } },
|
|
2145
|
+
(diagReport.recentErrors || []).map((err, i) => h('div', {
|
|
2242
2146
|
key: i,
|
|
2243
2147
|
style: { padding: '6px 10px', background: 'var(--dsw-alias-bg-layer-2)', borderRadius: 6, fontSize: 11.5, borderLeft: '3px solid var(--dsw-alias-state-error-primary)' }
|
|
2244
2148
|
},
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2149
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 2 } },
|
|
2150
|
+
h('span', { style: { fontWeight: 600 } }, (err.provider || 'unknown').toUpperCase() + (err.model ? ' ยท ' + err.model : '')),
|
|
2151
|
+
h('span', { className: 'dsub-dim' }, (err.ts || '').slice(11, 19))
|
|
2248
2152
|
),
|
|
2249
|
-
|
|
2250
|
-
err.code ?
|
|
2251
|
-
err.status ?
|
|
2252
|
-
|
|
2153
|
+
h('div', { style: { display: 'flex', gap: 6, alignItems: 'center' } },
|
|
2154
|
+
err.code ? h('span', { className: 'dsub-pillTag', style: { background: 'color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent)', color: 'var(--dsw-alias-state-error-primary)' } }, err.code) : null,
|
|
2155
|
+
err.status ? h('span', { className: 'dsub-dim' }, 'HTTP ' + err.status) : null,
|
|
2156
|
+
h('span', { style: { opacity: 0.9, wordBreak: 'break-word' } }, err.message)
|
|
2253
2157
|
)
|
|
2254
2158
|
))
|
|
2255
2159
|
)
|
|
2256
2160
|
)
|
|
2257
2161
|
),
|
|
2258
|
-
wizardModal ?
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2162
|
+
wizardModal ? h('div', { className: 'dsub-modalWrap', onClick: (e) => { if (e.target === e.currentTarget) setWizardModal(null) } },
|
|
2163
|
+
h('div', { className: 'dsub-modal' },
|
|
2164
|
+
h('div', { className: 'dsub-modalHead' },
|
|
2165
|
+
h('div', { className: 'dsub-modalTitleWrap' },
|
|
2166
|
+
h('div', { className: 'dsub-modalIcon' }, '๐ฉบ'),
|
|
2167
|
+
h('div', null,
|
|
2168
|
+
h('div', { style: { fontWeight: 700, fontSize: '15px' } }, t('wizardTitle')),
|
|
2169
|
+
h('div', { style: { fontSize: '11.5px', opacity: 0.7 } },
|
|
2266
2170
|
wizardModal.provider && wizardModal.provider !== 'all' ? (wizardModal.provider.toUpperCase() + ' #' + wizardModal.index + (wizardModal.ref ? ' (' + wizardModal.ref + ')' : '')) : t('wizardAll')
|
|
2267
2171
|
),
|
|
2268
2172
|
),
|
|
2269
2173
|
),
|
|
2270
|
-
|
|
2174
|
+
h('button', { type: 'button', className: 'dsub-mini', onClick: () => setWizardModal(null) }, 'โ ' + t('closeModal')),
|
|
2271
2175
|
),
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2176
|
+
h('div', { style: { marginTop: '14px' } },
|
|
2177
|
+
h('label', { className: 'dsub-row', style: { marginBottom: '10px' } },
|
|
2178
|
+
h('input', {
|
|
2275
2179
|
type: 'checkbox',
|
|
2276
2180
|
checked: !!wizardModal.includeNetwork,
|
|
2277
2181
|
onChange: (e) => runWizard(wizardModal.provider === 'all' ? null : wizardModal.provider, wizardModal.index, wizardModal.ref, e.target.checked),
|
|
2278
2182
|
}),
|
|
2279
|
-
|
|
2183
|
+
h('span', { style: { fontSize: '12px' } }, t('wizardIncludeNetwork')),
|
|
2280
2184
|
),
|
|
2281
|
-
wizardModal.loading ?
|
|
2282
|
-
wizardModal.error ?
|
|
2283
|
-
wizardModal.report ?
|
|
2284
|
-
|
|
2285
|
-
|
|
2185
|
+
wizardModal.loading ? h('div', { className: 'dsub-alert-ok', style: { marginBottom: '12px' } }, 'โณ ' + t('wizardRunning')) : null,
|
|
2186
|
+
wizardModal.error ? h('div', { className: 'dsub-alert-bad', style: { marginBottom: '12px' } }, wizardModal.error) : null,
|
|
2187
|
+
wizardModal.report ? h('div', null,
|
|
2188
|
+
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px' } },
|
|
2189
|
+
h('span', {
|
|
2286
2190
|
className: 'dsub-badge ' + (wizardModal.report.overallStatus === 'healthy' ? 'dsub-badge-ok' : (wizardModal.report.overallStatus === 'degraded' ? 'dsub-badge-warn' : 'dsub-badge-bad'))
|
|
2287
2191
|
}, (wizardModal.report.overallStatus === 'healthy' ? '๐ข ' + t('wizardHealthy') : (wizardModal.report.overallStatus === 'degraded' ? '๐ก ' + t('wizardDegraded') : '๐ด ' + t('wizardFailing')))),
|
|
2288
|
-
|
|
2192
|
+
h('span', { style: { fontSize: '11.5px', opacity: 0.7 } },
|
|
2289
2193
|
wizardModal.report.summary.passed + ' passed ยท ' + wizardModal.report.summary.warnings + ' warn ยท ' + wizardModal.report.summary.failed + ' fail'
|
|
2290
2194
|
),
|
|
2291
2195
|
),
|
|
2292
|
-
|
|
2196
|
+
h('div', { className: 'dsub-trace-box', style: { marginBottom: '12px' } },
|
|
2293
2197
|
wizardModal.report.steps.map((st, idx) => {
|
|
2294
2198
|
const icon = st.status === 'pass' ? 'โ
' : (st.status === 'warn' ? 'โ ๏ธ' : (st.status === 'fail' ? 'โ' : 'โช'))
|
|
2295
2199
|
const color = st.status === 'pass' ? 'var(--dsw-alias-state-success-primary)' : (st.status === 'warn' ? 'var(--dsw-alias-state-warn-primary)' : (st.status === 'fail' ? 'var(--dsw-alias-state-error-primary)' : 'var(--dsw-alias-label-secondary)'))
|
|
2296
|
-
return
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
st.latencyMs != null ?
|
|
2200
|
+
return h('div', { key: idx, className: 'dsub-trace-row' },
|
|
2201
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
|
|
2202
|
+
h('span', null, icon),
|
|
2203
|
+
h('span', { style: { fontWeight: 600 } }, st.name),
|
|
2204
|
+
st.latencyMs != null ? h('span', { style: { fontSize: '10px', opacity: 0.6 } }, st.latencyMs + 'ms') : null,
|
|
2301
2205
|
),
|
|
2302
|
-
|
|
2206
|
+
h('span', { style: { fontSize: '11px', color: color } }, st.message),
|
|
2303
2207
|
)
|
|
2304
2208
|
})
|
|
2305
2209
|
),
|
|
2306
|
-
wizardModal.report.recommendations && wizardModal.report.recommendations.length ?
|
|
2307
|
-
|
|
2308
|
-
wizardModal.report.recommendations.map((rec, rIdx) =>
|
|
2210
|
+
wizardModal.report.recommendations && wizardModal.report.recommendations.length ? h('div', { style: { marginBottom: '12px' } },
|
|
2211
|
+
h('div', { style: { fontSize: '11.5px', fontWeight: 600, color: 'var(--dsw-alias-state-warn-primary)', marginBottom: '4px' } }, '๐ก ' + t('wizardRecommendations')),
|
|
2212
|
+
wizardModal.report.recommendations.map((rec, rIdx) => h('div', { key: rIdx, className: 'dsub-alert-bad', style: { marginBottom: '4px', fontSize: '11.5px' } }, rec))
|
|
2309
2213
|
) : null,
|
|
2310
|
-
|
|
2311
|
-
|
|
2214
|
+
h('div', { style: { display: 'flex', justifyContent: 'flex-end', gap: '8px', marginTop: '10px' } },
|
|
2215
|
+
h('button', {
|
|
2312
2216
|
type: 'button',
|
|
2313
2217
|
className: 'dsub-mini',
|
|
2314
2218
|
onClick: () => {
|
|
@@ -2321,61 +2225,106 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2321
2225
|
),
|
|
2322
2226
|
),
|
|
2323
2227
|
) : null,
|
|
2324
|
-
backupModal ?
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2228
|
+
backupModal ? h('div', { className: 'dsub-panel-box', style: { marginTop: '10px' } },
|
|
2229
|
+
h('div', { className: 'dsub-panel-title' },
|
|
2230
|
+
h('span', null, backupModal === 'export' ? ('๐ ' + t('backupExportTitle')) : ('๐ฅ ' + t('backupImportTitle'))),
|
|
2231
|
+
h('button', {
|
|
2328
2232
|
type: 'button',
|
|
2329
2233
|
className: 'dsub-mini',
|
|
2330
2234
|
onClick: () => { setBackupModal(null); setBackupPass(''); setBackupData(''); setBackupErr(''); setBackupInfo('') }
|
|
2331
2235
|
}, 'โ ' + t('closeModal'))
|
|
2332
2236
|
),
|
|
2333
|
-
|
|
2237
|
+
h('div', { className: 'dsub-panel-desc' },
|
|
2334
2238
|
backupModal === 'export' ? t('backupExportHint') : t('backupImportHint')
|
|
2335
2239
|
),
|
|
2336
|
-
|
|
2337
|
-
backupModal === 'import' ?
|
|
2240
|
+
h('div', { style: { display: 'flex', flexDirection: 'column', gap: '8px', marginTop: '8px' } },
|
|
2241
|
+
backupModal === 'import' ? h('div', { className: 'dsub-row', style: { gap: '8px', alignItems: 'center' } },
|
|
2242
|
+
h('input', {
|
|
2243
|
+
type: 'file',
|
|
2244
|
+
accept: '.enc,.txt',
|
|
2245
|
+
className: 'dsub-mini',
|
|
2246
|
+
style: { maxWidth: '220px' },
|
|
2247
|
+
onChange: (e) => {
|
|
2248
|
+
const f = e.target.files && e.target.files[0]
|
|
2249
|
+
if (!f) return
|
|
2250
|
+
const reader = new window.FileReader()
|
|
2251
|
+
reader.onload = (evt) => {
|
|
2252
|
+
if (evt.target && evt.target.result) setBackupData(String(evt.target.result))
|
|
2253
|
+
}
|
|
2254
|
+
reader.readAsText(f)
|
|
2255
|
+
},
|
|
2256
|
+
}),
|
|
2257
|
+
h('span', { className: 'dsub-sub' }, t('orPasteVaultPayload'))
|
|
2258
|
+
) : null,
|
|
2259
|
+
backupModal === 'import' ? h('textarea', {
|
|
2338
2260
|
className: 'dsub-diag',
|
|
2339
2261
|
style: { width: '100%', height: '80px', fontFamily: 'monospace', fontSize: '11px' },
|
|
2340
2262
|
placeholder: t('backupPayloadPlaceholder'),
|
|
2341
2263
|
value: backupData,
|
|
2342
2264
|
onChange: (e) => setBackupData(e.target.value),
|
|
2343
2265
|
}) : null,
|
|
2344
|
-
|
|
2345
|
-
|
|
2266
|
+
h('div', { className: 'dsub-row' },
|
|
2267
|
+
h('input', {
|
|
2346
2268
|
type: 'password',
|
|
2347
2269
|
className: 'dsub-grow',
|
|
2348
2270
|
placeholder: t('backupPassphrase'),
|
|
2349
2271
|
value: backupPass,
|
|
2350
2272
|
onChange: (e) => setBackupPass(e.target.value),
|
|
2351
2273
|
}),
|
|
2352
|
-
backupModal === 'export' ?
|
|
2274
|
+
backupModal === 'export' ? h('button', {
|
|
2353
2275
|
type: 'button',
|
|
2354
2276
|
className: 'dsub-mini',
|
|
2355
2277
|
disabled: backupLoading || !backupPass || backupPass.length < 12,
|
|
2356
2278
|
onClick: doExportBackup,
|
|
2357
|
-
}, backupLoading ? 'โฆ' : t('backupExportAction')) :
|
|
2279
|
+
}, backupLoading ? 'โฆ' : t('backupExportAction')) : h('button', {
|
|
2358
2280
|
type: 'button',
|
|
2359
2281
|
className: 'dsub-mini',
|
|
2360
2282
|
disabled: backupLoading || !backupPass || !backupData,
|
|
2361
2283
|
onClick: doImportBackup,
|
|
2362
2284
|
}, backupLoading ? 'โฆ' : t('backupImportAction'))
|
|
2363
2285
|
),
|
|
2364
|
-
backupErr ?
|
|
2365
|
-
backupInfo ?
|
|
2366
|
-
(backupModal === 'export' && backupData) ?
|
|
2367
|
-
|
|
2286
|
+
backupErr ? h('div', { className: 'dsub-bad' }, backupErr) : null,
|
|
2287
|
+
backupInfo ? h('div', { className: 'dsub-ok' }, backupInfo) : null,
|
|
2288
|
+
(backupModal === 'export' && backupData) ? h('div', { className: 'dsub-row' },
|
|
2289
|
+
h('button', {
|
|
2368
2290
|
type: 'button',
|
|
2369
2291
|
className: 'dsub-mini',
|
|
2370
2292
|
onClick: () => { try { navigator.clipboard.writeText(backupData) } catch { /* ignore */ } },
|
|
2371
2293
|
}, t('diagCopy')),
|
|
2372
|
-
|
|
2294
|
+
h('button', {
|
|
2373
2295
|
type: 'button',
|
|
2374
2296
|
className: 'dsub-mini',
|
|
2375
2297
|
onClick: downloadBackupFile,
|
|
2376
2298
|
}, t('backupDownload')),
|
|
2377
|
-
|
|
2378
|
-
) : null
|
|
2299
|
+
h('pre', { className: 'dsub-diag', style: { maxHeight: '60px', overflow: 'hidden', textOverflow: 'ellipsis' } }, backupData)
|
|
2300
|
+
) : null,
|
|
2301
|
+
h('div', {
|
|
2302
|
+
className: 'dsub-panel-box',
|
|
2303
|
+
style: { marginTop: 10, padding: '10px 12px', borderTop: '1px solid var(--dsw-alias-border-l2)' }
|
|
2304
|
+
},
|
|
2305
|
+
h('div', { className: 'dsub-panel-title' },
|
|
2306
|
+
h('span', null, 'โ๏ธ ' + t('vaultSyncTitle')),
|
|
2307
|
+
h('div', { style: { display: 'flex', gap: 6 } },
|
|
2308
|
+
h('button', {
|
|
2309
|
+
type: 'button',
|
|
2310
|
+
className: 'dsub-mini',
|
|
2311
|
+
disabled: vaultSyncLoading,
|
|
2312
|
+
onClick: doVaultSyncPush,
|
|
2313
|
+
}, vaultSyncLoading ? 'โฆ' : t('vaultSyncPush')),
|
|
2314
|
+
h('button', {
|
|
2315
|
+
type: 'button',
|
|
2316
|
+
className: 'dsub-mini',
|
|
2317
|
+
disabled: vaultSyncLoading,
|
|
2318
|
+
onClick: doVaultSyncPull,
|
|
2319
|
+
}, vaultSyncLoading ? 'โฆ' : t('vaultSyncPull'))
|
|
2320
|
+
)
|
|
2321
|
+
),
|
|
2322
|
+
vaultSyncInfo ? h('div', { className: 'dsub-sub', style: { marginTop: 4 } },
|
|
2323
|
+
t('vaultSyncBackend') + ' ' + (vaultSyncInfo.backend || 'webdav') + ' ยท ' +
|
|
2324
|
+
t('vaultSyncLastPush') + ' ' + (vaultSyncInfo.lastPushAt ? new Date(vaultSyncInfo.lastPushAt).toLocaleTimeString() : 'never') + ' ยท ' +
|
|
2325
|
+
t('vaultSyncLastPull') + ' ' + (vaultSyncInfo.lastPullAt ? new Date(vaultSyncInfo.lastPullAt).toLocaleTimeString() : 'never')
|
|
2326
|
+
) : null
|
|
2327
|
+
)
|
|
2379
2328
|
)
|
|
2380
2329
|
) : null,
|
|
2381
2330
|
),
|
|
@@ -2383,40 +2332,50 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2383
2332
|
const rows = slots
|
|
2384
2333
|
.map((slot, i) => ({ slot: slot, i: i }))
|
|
2385
2334
|
.filter((row) => row.slot.provider === prov.id)
|
|
2386
|
-
return
|
|
2387
|
-
|
|
2335
|
+
return h('div', { className: 'dsub-block', key: prov.id },
|
|
2336
|
+
h('div', { className: 'dsub-h' }, prov.name),
|
|
2388
2337
|
rows.map((row) => {
|
|
2389
2338
|
const account = accountOf(row.slot.provider, row.slot.index)
|
|
2390
2339
|
const key = row.slot.provider + ':' + row.slot.index
|
|
2391
2340
|
const on = !!account.configured
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2341
|
+
const avatarEl = (account.avatarUrl ? h('img', {
|
|
2342
|
+
src: account.avatarUrl,
|
|
2343
|
+
alt: account.email || account.label || 'Avatar',
|
|
2344
|
+
className: 'dsub-avatar',
|
|
2345
|
+
onError: (e) => { e.target.style.display = 'none' },
|
|
2346
|
+
}) : (account.email ? h('span', {
|
|
2347
|
+
className: 'dsub-avatar dsub-avatar-initials',
|
|
2348
|
+
title: account.email,
|
|
2349
|
+
}, (account.email.charAt(0) || '?').toUpperCase()) : null))
|
|
2350
|
+
return h('div', { className: 'dsub-card', key: key },
|
|
2351
|
+
h('div', { className: 'dsub-row', style: { alignItems: 'center' } },
|
|
2352
|
+
avatarEl,
|
|
2353
|
+
h('input', {
|
|
2395
2354
|
className: 'dsub-grow',
|
|
2396
2355
|
value: row.slot.label || '',
|
|
2397
|
-
placeholder: account.label || (t('accountLabel') + ' ' + row.slot.index),
|
|
2356
|
+
placeholder: account.email || account.label || (t('accountLabel') + ' ' + row.slot.index),
|
|
2398
2357
|
onChange: (e) => {
|
|
2399
2358
|
const next = slots.slice()
|
|
2400
2359
|
next[row.i] = Object.assign({}, next[row.i], { label: e.target.value })
|
|
2401
2360
|
setSlots(next)
|
|
2402
2361
|
},
|
|
2403
2362
|
}),
|
|
2404
|
-
|
|
2405
|
-
normalizePlanBadge(row.slot.provider, account.plan || (account.quota && account.quota.plan)),
|
|
2406
|
-
|
|
2363
|
+
h('span', { className: 'dsub-badge' + (account.isRevoked ? ' dsub-badge-bad' : (account.validationUrl ? ' dsub-badge-warn' : (on ? ' dsub-badge-on' : ''))) }, badgeFor(account, t)),
|
|
2364
|
+
normalizePlanBadge(row.slot.provider, account.plan || account.paidTierName || (account.quota && account.quota.plan)),
|
|
2365
|
+
h('button', {
|
|
2407
2366
|
type: 'button', className: 'dsub-mini',
|
|
2408
2367
|
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2409
2368
|
}, on ? t('reconnect') : t('connect')),
|
|
2410
|
-
((row.slot.provider === 'codex' || row.slot.provider === 'copilot' || row.slot.provider === 'grok') ?
|
|
2369
|
+
((row.slot.provider === 'codex' || row.slot.provider === 'copilot' || row.slot.provider === 'grok') ? h('button', {
|
|
2411
2370
|
type: 'button', className: 'dsub-mini',
|
|
2412
2371
|
onClick: () => deviceStartLogin(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2413
2372
|
}, t('deviceLogin')) : null),
|
|
2414
|
-
|
|
2373
|
+
h('button', {
|
|
2415
2374
|
type: 'button', className: 'dsub-mini',
|
|
2416
2375
|
disabled: !on,
|
|
2417
2376
|
onClick: () => logout(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2418
2377
|
}, t('disconnect')),
|
|
2419
|
-
|
|
2378
|
+
h('button', {
|
|
2420
2379
|
type: 'button', className: 'dsub-mini',
|
|
2421
2380
|
disabled: checking[key],
|
|
2422
2381
|
title: t('smokeDesc'),
|
|
@@ -2427,30 +2386,47 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2427
2386
|
if (!r) return null;
|
|
2428
2387
|
var cls = r.ok ? 'dsub-badge-ok' : 'dsub-badge-bad';
|
|
2429
2388
|
var txt = r.ok ? ('โ ' + (r.latencyMs != null ? r.latencyMs + 'ms' : 'OK')) : ('โ ' + ((r.error && (r.error.code || r.error.message)) || 'FAIL'));
|
|
2430
|
-
return
|
|
2389
|
+
return h('span', { className: 'dsub-badge ' + cls, style: { marginLeft: 4 }, title: r.ok ? t('testConnectionSuccess') : ((r.error && r.error.message) || 'fail') }, txt);
|
|
2431
2390
|
})(),
|
|
2432
|
-
|
|
2391
|
+
(account && account.lastPingMs != null ? (function(){
|
|
2392
|
+
var ms = account.lastPingMs;
|
|
2393
|
+
var grade = account.latencyGrade || (ms < 250 ? 'good' : (ms < 750 ? 'fair' : 'poor'));
|
|
2394
|
+
var cls = grade === 'good' ? 'dsub-badge-ok' : (grade === 'fair' ? 'dsub-badge-warn' : 'dsub-badge-bad');
|
|
2395
|
+
return h('span', {
|
|
2396
|
+
className: 'dsub-badge ' + cls,
|
|
2397
|
+
style: { marginLeft: 4, cursor: 'pointer' },
|
|
2398
|
+
title: 'Latency: ' + ms + 'ms (' + grade + '). Click to test.',
|
|
2399
|
+
onClick: () => doPing(row.slot.provider, row.slot.index),
|
|
2400
|
+
}, '๐ถ ' + ms + 'ms');
|
|
2401
|
+
})() : null),
|
|
2402
|
+
h('button', {
|
|
2403
|
+
type: 'button',
|
|
2404
|
+
className: 'dsub-mini',
|
|
2405
|
+
title: t('syncModelsTitle'),
|
|
2406
|
+
onClick: () => doSyncModels(row.slot.provider, row.slot.index),
|
|
2407
|
+
}, '๐ ' + t('syncModels')),
|
|
2408
|
+
h('button', {
|
|
2433
2409
|
type: 'button', className: 'dsub-mini',
|
|
2434
2410
|
title: t('wizardTitle'),
|
|
2435
2411
|
onClick: () => runWizard(row.slot.provider, row.slot.index, row.slot.ref, false),
|
|
2436
2412
|
}, '๐ฉบ ' + t('wizardButton')),
|
|
2437
2413
|
|
|
2438
|
-
(account && account.quarantineUntil && Number(account.quarantineUntil) > Date.now() ?
|
|
2439
|
-
|
|
2414
|
+
(account && account.quarantineUntil && Number(account.quarantineUntil) > Date.now() ? h(React.Fragment, null,
|
|
2415
|
+
h('button', {
|
|
2440
2416
|
type: 'button', className: 'dsub-mini', title: t('probeWarmupTitle'),
|
|
2441
2417
|
disabled: checking[key],
|
|
2442
2418
|
onClick: () => doProbeQuarantine(row.slot.provider, row.slot.index, false),
|
|
2443
2419
|
}, checking[key] ? t('checking') : ('๐ ' + t('probeWarmupNow'))),
|
|
2444
|
-
|
|
2420
|
+
h('button', {
|
|
2445
2421
|
type: 'button', className: 'dsub-mini', title: t('releaseQuarantineTitle'),
|
|
2446
2422
|
disabled: checking[key],
|
|
2447
2423
|
onClick: () => doProbeQuarantine(row.slot.provider, row.slot.index, true),
|
|
2448
2424
|
}, ('โ ' + t('releaseQuarantine'))),
|
|
2449
|
-
) : (on ?
|
|
2425
|
+
) : (on ? h('button', {
|
|
2450
2426
|
type: 'button', className: 'dsub-mini', title: t('quarantineParkTitle'),
|
|
2451
2427
|
onClick: () => doParkQuarantine(row.slot.provider, row.slot.index, 3600000),
|
|
2452
2428
|
}, ('โธ ' + t('quarantinePark'))) : null)),
|
|
2453
|
-
|
|
2429
|
+
h('button', {
|
|
2454
2430
|
type: 'button', className: 'dsub-mini', title: t('removeSlot'),
|
|
2455
2431
|
onClick: () => {
|
|
2456
2432
|
const slot = row.slot
|
|
@@ -2460,55 +2436,105 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2460
2436
|
},
|
|
2461
2437
|
}, '\u00d7'),
|
|
2462
2438
|
),
|
|
2463
|
-
(account && account.quarantineUntil && Number(account.quarantineUntil) > Date.now()) ?
|
|
2464
|
-
|
|
2439
|
+
(account && account.quarantineUntil && Number(account.quarantineUntil) > Date.now()) ? h('div', { className: 'dsub-row', style: { marginTop: 4 } },
|
|
2440
|
+
h('span', { className: 'dsub-sub', style: { color: 'var(--dsw-alias-state-error-primary)', fontVariantNumeric: 'tabular-nums' } },
|
|
2465
2441
|
'โ ' + (account.quarantineReason || 'QUARANTINE') + ' ยท ' + t('resetsIn') + ' ' + formatRelativeReset(account.quarantineUntil, t('lang'), Date.now())
|
|
2466
2442
|
),
|
|
2467
|
-
) : (account && account.quota && account.quota.resetAt && Number(account.quota.resetAt) > Date.now()) ?
|
|
2468
|
-
|
|
2443
|
+
) : (account && (account.resetAt || (account.quota && account.quota.resetAt)) && Number(account.resetAt || account.quota.resetAt) > Date.now()) ? h('div', { className: 'dsub-row', style: { marginTop: 4 } },
|
|
2444
|
+
h(ResetCountdown, { resetAt: account.resetAt || account.quota.resetAt }),
|
|
2469
2445
|
) : null,
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2446
|
+
h('div', { className: 'dsub-manual' },
|
|
2447
|
+
h('span', { className: 'dsub-sub' }, t('manualTitle')),
|
|
2448
|
+
h('div', { className: 'dsub-row' },
|
|
2449
|
+
h('input', {
|
|
2474
2450
|
className: 'dsub-grow',
|
|
2475
2451
|
value: paste[key] || '',
|
|
2476
2452
|
placeholder: t('pastePlaceholder'),
|
|
2477
2453
|
onChange: (e) => setPaste((p) => Object.assign({}, p, { [key]: e.target.value })),
|
|
2478
2454
|
}),
|
|
2479
|
-
|
|
2455
|
+
h('button', {
|
|
2480
2456
|
type: 'button', className: 'dsub-mini',
|
|
2481
2457
|
onClick: () => complete(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2482
2458
|
}, t('submitCode')),
|
|
2483
2459
|
),
|
|
2484
|
-
|
|
2485
|
-
|
|
2460
|
+
(headlessInfo[key] ? h('div', {
|
|
2461
|
+
className: 'dsub-panel-box',
|
|
2462
|
+
style: { marginTop: 6, padding: '8px 12px', background: 'var(--dsw-alias-bg-layer-2)' }
|
|
2463
|
+
},
|
|
2464
|
+
h('div', { style: { fontWeight: 600, fontSize: '11px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
|
|
2465
|
+
h('span', null, '๐ ' + t('headlessTip')),
|
|
2466
|
+
h('button', {
|
|
2467
|
+
type: 'button',
|
|
2468
|
+
className: 'dsub-mini',
|
|
2469
|
+
onClick: () => {
|
|
2470
|
+
try {
|
|
2471
|
+
navigator.clipboard.writeText(headlessInfo[key].sshTunnelCommand)
|
|
2472
|
+
setCopiedSsh((m) => Object.assign({}, m, { [key]: true }))
|
|
2473
|
+
setTimeout(() => setCopiedSsh((m) => Object.assign({}, m, { [key]: false })), 2000)
|
|
2474
|
+
} catch { /* ignore */ }
|
|
2475
|
+
}
|
|
2476
|
+
}, copiedSsh[key] ? ('โ ' + t('headlessCopied')) : ('๐ ' + t('headlessCopySsh')))
|
|
2477
|
+
),
|
|
2478
|
+
h('div', { style: { fontFamily: 'monospace', fontSize: '11px', margin: '4px 0', wordBreak: 'break-all' } },
|
|
2479
|
+
headlessInfo[key].sshTunnelCommand
|
|
2480
|
+
),
|
|
2481
|
+
headlessInfo[key].svgDataUrl ? h('div', { style: { marginTop: 6, textAlign: 'center' } },
|
|
2482
|
+
h('div', { className: 'dsub-sub', style: { marginBottom: 4 } }, t('headlessScanQr')),
|
|
2483
|
+
h('img', {
|
|
2484
|
+
src: headlessInfo[key].svgDataUrl,
|
|
2485
|
+
alt: 'QR Code',
|
|
2486
|
+
style: { width: '130px', height: '130px', borderRadius: '4px', background: '#fff', padding: '4px' }
|
|
2487
|
+
})
|
|
2488
|
+
) : null
|
|
2489
|
+
) : null),
|
|
2490
|
+
h('div', { className: 'dsub-row', style: { justifyContent: 'space-between' } },
|
|
2491
|
+
h('button', {
|
|
2486
2492
|
type: 'button',
|
|
2487
2493
|
className: 'dsub-mini',
|
|
2488
2494
|
title: t('importLocalCliTitle'),
|
|
2489
2495
|
style: { display: 'inline-flex', alignItems: 'center', gap: 6, fontWeight: 600 },
|
|
2490
2496
|
onClick: () => importLocalCli(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2491
2497
|
}, t('importLocalCli')),
|
|
2492
|
-
|
|
2498
|
+
h('button', {
|
|
2493
2499
|
type: 'button',
|
|
2494
2500
|
className: 'dsub-mini' + (openHelp[key] ? ' dsub-btnActive' : ''),
|
|
2495
2501
|
title: t('howToGetTokenTitle'),
|
|
2496
2502
|
onClick: (e) => { if (e) { e.preventDefault(); e.stopPropagation(); } setOpenHelp((h) => Object.assign({}, h, { [key]: !h[key] })); },
|
|
2497
2503
|
}, t('howToGetToken')),
|
|
2498
2504
|
),
|
|
2499
|
-
|
|
2500
|
-
|
|
2505
|
+
h('div', { className: 'dsub-row' },
|
|
2506
|
+
h('input', {
|
|
2501
2507
|
className: 'dsub-grow',
|
|
2502
2508
|
value: tokenDraft[key] || '',
|
|
2503
2509
|
placeholder: t('importTokenPlace'),
|
|
2504
2510
|
onChange: (e) => setTokenDraft((d) => Object.assign({}, d, { [key]: e.target.value })),
|
|
2505
2511
|
}),
|
|
2506
|
-
|
|
2512
|
+
h('button', {
|
|
2507
2513
|
type: 'button', className: 'dsub-mini',
|
|
2508
2514
|
title: t('importToken'),
|
|
2509
2515
|
onClick: () => importToken(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2510
2516
|
}, t('importToken')),
|
|
2511
2517
|
),
|
|
2518
|
+
(account && account.lastDoctorVerdict ? (function(){
|
|
2519
|
+
var doc = account.lastDoctorVerdict;
|
|
2520
|
+
return h('div', {
|
|
2521
|
+
className: 'dsub-helpBox',
|
|
2522
|
+
style: {
|
|
2523
|
+
marginTop: 6,
|
|
2524
|
+
padding: '8px 12px',
|
|
2525
|
+
borderLeft: '3px solid var(--dsw-alias-brand-primary)',
|
|
2526
|
+
background: 'var(--dsw-alias-bg-layer-2)',
|
|
2527
|
+
},
|
|
2528
|
+
},
|
|
2529
|
+
h('div', { style: { fontWeight: 600, color: 'var(--dsw-alias-label-primary)', display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 } },
|
|
2530
|
+
'๐ฉบ ' + doc.title
|
|
2531
|
+
),
|
|
2532
|
+
h('div', { style: { fontSize: 12, color: 'var(--dsw-alias-label-secondary)', marginBottom: 4 } }, doc.details),
|
|
2533
|
+
h('div', { style: { fontSize: 12, color: 'var(--dsw-alias-brand-primary)', fontWeight: 500 } },
|
|
2534
|
+
'๐ก ' + (t('recommendation') || 'Recommendation') + ': ' + doc.recommendation
|
|
2535
|
+
)
|
|
2536
|
+
);
|
|
2537
|
+
})() : null),
|
|
2512
2538
|
(openHelp[key] ? (function renderInlineHelp(){
|
|
2513
2539
|
const prov = row.slot.provider;
|
|
2514
2540
|
const info = (typeof INSTRUCTIONS !== 'undefined' && INSTRUCTIONS[prov]) || {
|
|
@@ -2519,10 +2545,10 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2519
2545
|
// Determine language safely from current locale (fallback to zh if Chinese or en)
|
|
2520
2546
|
const isZh = t('instructionsTitle').indexOf('่ทๅ') >= 0 || t('close') === 'ๅ
ณ้ญ';
|
|
2521
2547
|
const steps = (isZh && info.stepsZh) ? info.stepsZh : (info.stepsEn || []);
|
|
2522
|
-
return
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2548
|
+
return h('div', { className: 'dsub-helpBox' },
|
|
2549
|
+
h('div', { className: 'dsub-helpHead' },
|
|
2550
|
+
h('span', null, 'โน๏ธ ' + info.title + ' โ ' + t('instructionsTitle')),
|
|
2551
|
+
h('button', {
|
|
2526
2552
|
type: 'button', className: 'dsub-mini',
|
|
2527
2553
|
style: { padding: '1px 6px', fontSize: 11 },
|
|
2528
2554
|
onClick: (e) => {
|
|
@@ -2531,9 +2557,9 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2531
2557
|
},
|
|
2532
2558
|
}, 'โ')
|
|
2533
2559
|
),
|
|
2534
|
-
steps.map((st, i) =>
|
|
2535
|
-
info.link ?
|
|
2536
|
-
|
|
2560
|
+
steps.map((st, i) => h('div', { key: i, className: 'dsub-helpStep' }, st)),
|
|
2561
|
+
info.link ? h('div', { style: { marginTop: 8 } },
|
|
2562
|
+
h('a', {
|
|
2537
2563
|
href: info.link,
|
|
2538
2564
|
target: '_blank',
|
|
2539
2565
|
rel: 'noopener noreferrer',
|
|
@@ -2543,8 +2569,8 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2543
2569
|
) : null
|
|
2544
2570
|
);
|
|
2545
2571
|
})() : null),
|
|
2546
|
-
|
|
2547
|
-
|
|
2572
|
+
h('div', { className: 'dsub-row' },
|
|
2573
|
+
h('input', {
|
|
2548
2574
|
className: 'dsub-grow',
|
|
2549
2575
|
value: row.slot.proxyUrl || '',
|
|
2550
2576
|
placeholder: t('proxyPlaceholder'),
|
|
@@ -2554,17 +2580,37 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2554
2580
|
setSlots(next)
|
|
2555
2581
|
},
|
|
2556
2582
|
}),
|
|
2557
|
-
|
|
2583
|
+
h('button', {
|
|
2558
2584
|
type: 'button', className: 'dsub-mini',
|
|
2559
2585
|
disabled: checking['proxy:' + key],
|
|
2560
2586
|
onClick: () => doProxyCheck(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2561
2587
|
}, checking['proxy:' + key] ? '\u2026' : t('proxyCheck')),
|
|
2588
|
+
h('span', {
|
|
2589
|
+
style: { fontSize: '11px', color: 'var(--dsw-alias-label-secondary)', display: 'inline-flex', alignItems: 'center', gap: '3px' },
|
|
2590
|
+
title: t('maxConcurrencySlotTitle')
|
|
2591
|
+
},
|
|
2592
|
+
'โก',
|
|
2593
|
+
h('input', {
|
|
2594
|
+
type: 'number',
|
|
2595
|
+
min: 1,
|
|
2596
|
+
max: 20,
|
|
2597
|
+
style: { width: '44px', padding: '1px 4px', fontSize: '11px', textAlign: 'center' },
|
|
2598
|
+
value: row.slot.maxConcurrency !== undefined ? row.slot.maxConcurrency : 1,
|
|
2599
|
+
title: t('maxConcurrencySlotTitle'),
|
|
2600
|
+
onChange: (e) => {
|
|
2601
|
+
const next = slots.slice()
|
|
2602
|
+
const val = parseInt(e.target.value, 10)
|
|
2603
|
+
next[row.i] = Object.assign({}, next[row.i], { maxConcurrency: isNaN(val) ? 1 : Math.max(1, val) })
|
|
2604
|
+
setSlots(next)
|
|
2605
|
+
},
|
|
2606
|
+
})
|
|
2607
|
+
),
|
|
2562
2608
|
),
|
|
2563
2609
|
(function(){
|
|
2564
2610
|
var r = proxyRes[key]
|
|
2565
2611
|
if (!r) return null
|
|
2566
2612
|
var txt = r.ok ? (t('proxyOk') + ' ' + r.latencyMs + 'ms' + (r.viaProxy ? '' : ' (direct)')) : (t('proxyFail') + ': ' + ((r.error && r.error.message) || ''))
|
|
2567
|
-
return
|
|
2613
|
+
return h('div', { className: r.ok ? 'dsub-ok' : 'dsub-bad' }, txt)
|
|
2568
2614
|
})(),
|
|
2569
2615
|
),
|
|
2570
2616
|
(function devicePanel(){
|
|
@@ -2572,18 +2618,18 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2572
2618
|
if (!d) return null
|
|
2573
2619
|
var txt = d.status === 'authorized' ? t('deviceAuthorized') : (d.status === 'expired' ? t('deviceExpired') : t('devicePending'))
|
|
2574
2620
|
var cls = d.status === 'authorized' ? 'dsub-ok' : (d.status === 'expired' ? 'dsub-bad' : 'dsub-verify')
|
|
2575
|
-
return
|
|
2576
|
-
|
|
2577
|
-
d.status === 'pending' ?
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2621
|
+
return h('div', { className: 'dsub-verify' },
|
|
2622
|
+
h('div', { className: cls }, txt),
|
|
2623
|
+
d.status === 'pending' ? h(React.Fragment, null,
|
|
2624
|
+
h('div', { style: { fontSize: '2em', fontWeight: 700, letterSpacing: '0.15em', margin: '4px 0' } }, d.userCode),
|
|
2625
|
+
h('div', { className: 'dsub-row' },
|
|
2626
|
+
h('button', {
|
|
2581
2627
|
type: 'button', className: 'dsub-mini',
|
|
2582
2628
|
onClick: () => { try { navigator.clipboard.writeText(d.userCode) } catch { /* clipboard write error */ } },
|
|
2583
2629
|
}, t('deviceCopy')),
|
|
2584
|
-
|
|
2630
|
+
h('a', { href: d.authUrl, target: '_blank', rel: 'noopener noreferrer', className: 'dsub-mini' }, t('verifyLink')),
|
|
2585
2631
|
),
|
|
2586
|
-
|
|
2632
|
+
h('div', { className: 'dsub-sub' }, t('deviceHint')),
|
|
2587
2633
|
) : null,
|
|
2588
2634
|
)
|
|
2589
2635
|
})(),
|
|
@@ -2598,63 +2644,86 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2598
2644
|
return code
|
|
2599
2645
|
}
|
|
2600
2646
|
if (st.phase !== 'confirm') {
|
|
2601
|
-
return
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2647
|
+
return h('div', { className: 'dsub-panel-box' },
|
|
2648
|
+
h('div', { className: 'dsub-panel-title' },
|
|
2649
|
+
h('span', null, 'โก ' + t('resetCredits')),
|
|
2650
|
+
h('button', {
|
|
2605
2651
|
type: 'button',
|
|
2606
2652
|
className: 'dsub-mini',
|
|
2607
2653
|
disabled: st.phase === 'loading',
|
|
2608
2654
|
onClick: () => resetPrepare(row.slot.provider, row.slot.index, key).catch((e) => setErr(String(e && e.message || e))),
|
|
2609
2655
|
}, st.phase === 'loading' ? 'โฆ' : t('resetCreditsAction'))
|
|
2610
2656
|
),
|
|
2611
|
-
|
|
2657
|
+
h('div', { className: 'dsub-panel-desc' }, t('resetCreditsHint'))
|
|
2612
2658
|
)
|
|
2613
2659
|
}
|
|
2614
2660
|
var ready = now >= st.readyAt
|
|
2615
2661
|
var secs = Math.max(0, Math.ceil((st.readyAt - now) / 1000))
|
|
2616
|
-
return
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2662
|
+
return h('div', { className: 'dsub-panel-box dsub-panel-warn' },
|
|
2663
|
+
h('div', { className: 'dsub-panel-title' },
|
|
2664
|
+
h('span', null, 'โ ๏ธ ' + t('resetCredits')),
|
|
2665
|
+
h('span', { className: 'dsub-tag-ok' }, t('resetAvailable') + ': ' + st.availableCount)
|
|
2620
2666
|
),
|
|
2621
|
-
st.creditExpiresAt ?
|
|
2667
|
+
st.creditExpiresAt ? h('div', { className: 'dsub-panel-desc' },
|
|
2622
2668
|
t('resetExpires') + ': ' + new Date(st.creditExpiresAt).toLocaleString()
|
|
2623
2669
|
) : null,
|
|
2624
|
-
|
|
2625
|
-
|
|
2670
|
+
h('label', { className: 'dsub-row', style: { cursor: 'pointer', margin: '4px 0' } },
|
|
2671
|
+
h('input', {
|
|
2626
2672
|
type: 'checkbox',
|
|
2627
2673
|
checked: !!st.ack,
|
|
2628
2674
|
onChange: (e) => setReset((m) => Object.assign({}, m, { [key]: Object.assign({}, st, { ack: e.target.checked }) })),
|
|
2629
2675
|
}),
|
|
2630
|
-
|
|
2676
|
+
h('span', { style: { fontSize: '12px', fontWeight: 500 } }, t('resetAck')),
|
|
2631
2677
|
),
|
|
2632
|
-
|
|
2633
|
-
|
|
2678
|
+
h('div', { className: 'dsub-row', style: { gap: '8px' } },
|
|
2679
|
+
h('button', {
|
|
2634
2680
|
type: 'button',
|
|
2635
2681
|
className: 'dsub-mini dsub-btn-danger',
|
|
2636
2682
|
disabled: !st.ack || !ready || !!st.busy,
|
|
2637
2683
|
onClick: () => resetConsume(key).catch((e) => setErr(String(e && e.message || e))),
|
|
2638
2684
|
}, st.busy ? t('resetBusy') : (ready ? t('resetGo') : (t('resetWait') + ' ' + secs + 's'))),
|
|
2639
|
-
!ready && !st.busy ?
|
|
2640
|
-
st.ack && ready ?
|
|
2641
|
-
|
|
2685
|
+
!ready && !st.busy ? h('span', { className: 'dsub-sub' }, t('resetWait') + ' ' + secs + 's') : null,
|
|
2686
|
+
st.ack && ready ? h('span', { className: 'dsub-ok', style: { fontSize: '12px', fontWeight: 600 } }, 'โ ' + t('resetReady')) : null,
|
|
2687
|
+
h('button', {
|
|
2642
2688
|
type: 'button',
|
|
2643
2689
|
className: 'dsub-mini',
|
|
2644
2690
|
style: { marginLeft: 'auto' },
|
|
2645
2691
|
onClick: () => setReset((m) => Object.assign({}, m, { [key]: { phase: 'idle' } })),
|
|
2646
2692
|
}, t('cancel'))
|
|
2647
2693
|
),
|
|
2648
|
-
st.result ?
|
|
2649
|
-
st.error ?
|
|
2694
|
+
st.result ? h('div', { className: 'dsub-ok', style: { fontWeight: 600 } }, resultText(st.result)) : null,
|
|
2695
|
+
st.error ? h('div', { className: 'dsub-bad' }, st.error) : null,
|
|
2650
2696
|
)
|
|
2651
2697
|
})() : null),
|
|
2652
|
-
account.accountNotice ?
|
|
2653
|
-
account.
|
|
2654
|
-
|
|
2655
|
-
|
|
2698
|
+
account.accountNotice ? h('div', { className: 'dsub-verify' }, account.accountNotice) : null,
|
|
2699
|
+
account.scopeWarning ? h('div', { className: 'dsub-scope-banner' },
|
|
2700
|
+
h('span', { style: { color: 'var(--dsw-alias-state-warn-primary)' } }, 'โ ๏ธ ' + t('scopeWarning') + ': ' + account.scopeWarning),
|
|
2701
|
+
h('button', {
|
|
2702
|
+
type: 'button',
|
|
2703
|
+
className: 'dsub-mini',
|
|
2704
|
+
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2705
|
+
}, '๐ ' + t('reconnectScope'))
|
|
2706
|
+
) : null,
|
|
2707
|
+
(account.isRevoked || account.authWarning) ? h('div', { className: 'dsub-bad dsub-row', style: { alignItems: 'center', justifyContent: 'space-between', gap: '8px', marginBottom: '6px' } },
|
|
2708
|
+
h('span', null, 'โ ' + (account.authWarning || t('sessionRevokedWarning'))),
|
|
2709
|
+
h('button', {
|
|
2710
|
+
type: 'button',
|
|
2711
|
+
className: 'dsub-mini dsub-btn-primary',
|
|
2712
|
+
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2713
|
+
}, '๐ ' + t('reconnectNow'))
|
|
2714
|
+
) : null,
|
|
2715
|
+
account.refreshError ? h('div', { className: 'dsub-bad dsub-row', style: { alignItems: 'center', justifyContent: 'space-between', gap: '8px' } },
|
|
2716
|
+
h('span', null, t('reconnectRequired') + ': ' + account.refreshError),
|
|
2717
|
+
h('button', {
|
|
2718
|
+
type: 'button',
|
|
2719
|
+
className: 'dsub-mini dsub-btn-primary',
|
|
2720
|
+
onClick: () => connect(row.slot.provider, row.slot.index).catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2721
|
+
}, '๐ ' + t('reconnectNow'))
|
|
2722
|
+
) : null,
|
|
2723
|
+
(function(){ var r=checkRes[key]; if(!r) return null; var txt=r.ok ? ('ok ' + (r.email||'')) : ('fail ' + (r.error && r.error.message || '')); var cls=r.ok ? 'dsub-ok' : 'dsub-bad'; var q=r.quota; if(q && q.remaining!=null) txt += ' quota:'+q.remaining+(q.limit!=null?'/'+q.limit:''); return h('div', {className: cls}, txt) })(),
|
|
2724
|
+
account.validationUrl ? h('div', { className: 'dsub-verify' },
|
|
2656
2725
|
t('verifyPrefix'),
|
|
2657
|
-
|
|
2726
|
+
h('a', { href: account.validationUrl, target: '_blank', rel: 'noopener noreferrer' }, t('verifyLink')),
|
|
2658
2727
|
t('verifySuffix'),
|
|
2659
2728
|
) : null,
|
|
2660
2729
|
(function usageLimitsBlock(){
|
|
@@ -2680,18 +2749,18 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2680
2749
|
var p = Math.min(100, Math.max(0, Math.round(pct)))
|
|
2681
2750
|
var tagCls = p >= 90 ? 'dsub-tag-bad' : (p >= 70 ? 'dsub-tag-warn' : 'dsub-tag-ok')
|
|
2682
2751
|
var fillBg = p >= 90 ? 'var(--dsw-alias-state-error-primary)' : (p >= 70 ? 'var(--dsw-alias-state-warn-primary)' : 'var(--dsw-alias-state-success-primary)')
|
|
2683
|
-
return
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2752
|
+
return h('div', { key: label, className: 'dsub-usage-card' },
|
|
2753
|
+
h('div', { className: 'dsub-usage-head' },
|
|
2754
|
+
h('span', null, label),
|
|
2755
|
+
h('span', { className: tagCls }, p + '%')
|
|
2687
2756
|
),
|
|
2688
|
-
|
|
2689
|
-
|
|
2757
|
+
h('div', { className: 'dsub-usage-track' },
|
|
2758
|
+
h('div', {
|
|
2690
2759
|
className: 'dsub-usage-fill',
|
|
2691
2760
|
style: { width: p + '%', background: fillBg }
|
|
2692
2761
|
})
|
|
2693
2762
|
),
|
|
2694
|
-
detail ?
|
|
2763
|
+
detail ? h('div', { className: 'dsub-usage-meta' }, detail) : null
|
|
2695
2764
|
)
|
|
2696
2765
|
}
|
|
2697
2766
|
|
|
@@ -2703,18 +2772,18 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2703
2772
|
if (idx === 0 && account.requests && w.usedPercent < 100) {
|
|
2704
2773
|
var rem = 100 - w.usedPercent
|
|
2705
2774
|
var est = Math.floor(rem / (w.usedPercent / account.requests))
|
|
2706
|
-
if (est > 0) extra =
|
|
2775
|
+
if (est > 0) extra = h('span', null, t('forecast') + ' ' + est)
|
|
2707
2776
|
}
|
|
2708
|
-
var resetElem = w.resetAt ?
|
|
2777
|
+
var resetElem = w.resetAt ? h(ResetCountdown, { key: 'reset-' + idx, resetAt: w.resetAt }) : null
|
|
2709
2778
|
var extraContent = (resetElem && extra)
|
|
2710
|
-
?
|
|
2779
|
+
? h('span', { className: 'dsub-row', style: { gap: '6px' } }, resetElem, extra)
|
|
2711
2780
|
: (resetElem || extra)
|
|
2712
2781
|
items.push(renderItem(windowLabel(w), w.usedPercent, extraContent))
|
|
2713
2782
|
}
|
|
2714
2783
|
})
|
|
2715
2784
|
}
|
|
2716
2785
|
if (hasQuota) {
|
|
2717
|
-
items.push(renderItem(t('quota'), q.usedPercent, q.resetAt ?
|
|
2786
|
+
items.push(renderItem(t('quota'), q.usedPercent, q.resetAt ? h(ResetCountdown, { key: 'reset', resetAt: q.resetAt }) : null))
|
|
2718
2787
|
} else if (hasUsagePct) {
|
|
2719
2788
|
items.push(renderItem(t('quota'), account.usagePercent, null))
|
|
2720
2789
|
}
|
|
@@ -2726,18 +2795,33 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2726
2795
|
if (m >= 1) agoStr = m + 'm ' + (t('close') === 'ๅ
ณ้ญ' ? 'ๅ' : 'ago')
|
|
2727
2796
|
}
|
|
2728
2797
|
|
|
2729
|
-
return
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
agoStr ?
|
|
2798
|
+
return h('div', { className: 'dsub-panel-box' },
|
|
2799
|
+
h('div', { className: 'dsub-panel-title' },
|
|
2800
|
+
h('span', null, '๐ ' + t('usageLimitsTitle')),
|
|
2801
|
+
agoStr ? h('span', { className: 'dsub-sub' }, agoStr) : null
|
|
2733
2802
|
),
|
|
2734
|
-
|
|
2803
|
+
h('div', { className: 'dsub-usage-grid' }, items)
|
|
2735
2804
|
)
|
|
2736
2805
|
})(),
|
|
2737
|
-
((account.paidTierName || account.ref || (telemetry && telemetry.accounts && telemetry.accounts[account.ref])) ?
|
|
2738
|
-
account.
|
|
2739
|
-
|
|
2740
|
-
account.
|
|
2806
|
+
((account.email || account.plan || account.paidTierName || account.ref || (telemetry && telemetry.accounts && telemetry.accounts[account.ref])) ? h('div', { className: 'dsub-slot-meta-row' },
|
|
2807
|
+
account.email ? h('span', { className: 'dsub-sub' },
|
|
2808
|
+
h('strong', null, '๐ค '),
|
|
2809
|
+
account.email
|
|
2810
|
+
) : null,
|
|
2811
|
+
(account.plan || account.paidTierName) ? h('span', { className: 'dsub-sub' },
|
|
2812
|
+
h('strong', null, t('plan') + ': '),
|
|
2813
|
+
account.plan || account.paidTierName
|
|
2814
|
+
) : null,
|
|
2815
|
+
(account.organizations && account.organizations.length > 0) ? h('span', { className: 'dsub-sub', style: { display: 'inline-flex', alignItems: 'center', gap: 4 } },
|
|
2816
|
+
h('strong', null, '๐ข ' + t('workspaceTitle') + ':'),
|
|
2817
|
+
h('select', {
|
|
2818
|
+
className: 'dsub-select',
|
|
2819
|
+
style: { padding: '1px 6px', fontSize: '12px' },
|
|
2820
|
+
value: account.selectedOrgId || '',
|
|
2821
|
+
onChange: (e) => switchOrg(account.provider, account.index, e.target.value),
|
|
2822
|
+
},
|
|
2823
|
+
account.organizations.map((org) => h('option', { key: org.id, value: org.id }, org.name + (org.role ? ' (' + org.role + ')' : '')))
|
|
2824
|
+
)
|
|
2741
2825
|
) : null,
|
|
2742
2826
|
(function(){
|
|
2743
2827
|
const accTelem = telemetry && telemetry.accounts && telemetry.accounts[account.ref]
|
|
@@ -2748,31 +2832,63 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2748
2832
|
if (accTelem.avgTps != null) parts.push(accTelem.avgTps + ' t/s')
|
|
2749
2833
|
else if (accTelem.lastTps != null) parts.push(accTelem.lastTps + ' t/s')
|
|
2750
2834
|
if (parts.length === 0) return null
|
|
2751
|
-
return
|
|
2835
|
+
return h('span', { className: 'dsub-speed-tag', title: t('speedMetricsHint') },
|
|
2752
2836
|
'โก ' + parts.join(' ยท ')
|
|
2753
2837
|
)
|
|
2754
2838
|
})(),
|
|
2755
|
-
account.
|
|
2756
|
-
|
|
2757
|
-
|
|
2839
|
+
(account.activeStreams > 0 || account.queuedStreams > 0) ? h('span', { className: 'dsub-ref-tag', title: t('concurrencyQueueHint') },
|
|
2840
|
+
account.activeStreams > 0 ? ('โก ' + account.activeStreams + ' ' + t('activeStreams')) : null,
|
|
2841
|
+
(account.activeStreams > 0 && account.queuedStreams > 0) ? ' ยท ' : null,
|
|
2842
|
+
account.queuedStreams > 0 ? ('โณ ' + account.queuedStreams + ' ' + t('queuedStreams')) : null
|
|
2843
|
+
) : null,
|
|
2844
|
+
account.runwayText ? h('span', {
|
|
2845
|
+
className: 'dsub-ref-tag',
|
|
2846
|
+
style: {
|
|
2847
|
+
color: account.pacingStatus === 'critical' ? 'var(--dsw-alias-state-error-primary)' : (account.pacingStatus === 'elevated' ? 'var(--dsw-alias-state-warn-primary)' : 'var(--dsw-alias-state-success-primary)'),
|
|
2848
|
+
},
|
|
2849
|
+
title: t('pacingRunwayHint')
|
|
2850
|
+
}, 'โฑ๏ธ ' + t('runwayPrefix') + ': ' + account.runwayText) : null,
|
|
2851
|
+
(account.valueDelivered && account.valueDelivered.equivalentCost > 0) ? h('span', {
|
|
2852
|
+
className: 'dsub-speed-tag',
|
|
2853
|
+
title: t('valueDeliveredHint')
|
|
2854
|
+
}, '๐ ' + account.valueDelivered.formattedCost + ' (' + account.valueDelivered.roiLabel + ' ROI)') : null,
|
|
2855
|
+
(account.billing && account.billing.badgeText) ? h('span', {
|
|
2856
|
+
className: 'dsub-ref-tag',
|
|
2857
|
+
style: { color: 'var(--dsw-alias-state-error-primary)', fontWeight: 600 },
|
|
2858
|
+
title: account.billing.warning || t('billingAlertHint')
|
|
2859
|
+
}, 'โ ๏ธ ' + account.billing.badgeText) : null,
|
|
2860
|
+
(!account.billing?.badgeText && account.renewalCountdown) ? h('span', {
|
|
2861
|
+
className: 'dsub-ref-tag',
|
|
2862
|
+
title: t('renewalHint')
|
|
2863
|
+
}, '๐
' + account.renewalCountdown) : null,
|
|
2864
|
+
(account.capabilities && Array.isArray(account.capabilities.tags) && account.capabilities.tags.length > 0) ? h('span', {
|
|
2865
|
+
className: 'dsub-ref-tag',
|
|
2866
|
+
title: t('capabilitiesHint')
|
|
2867
|
+
}, 'โก ' + account.capabilities.tags.join(' ยท ')) : null,
|
|
2868
|
+
account.isEncryptedAtRest ? h('span', { className: 'dsub-ref-tag', title: t('atRestEncryptedTitle') },
|
|
2869
|
+
'๐ ' + t('atRestEncrypted')
|
|
2870
|
+
) : null,
|
|
2871
|
+
account.ref ? h('span', { className: 'dsub-ref-tag' },
|
|
2872
|
+
h('span', null, t('storedAs')),
|
|
2873
|
+
h('code', null, account.ref)
|
|
2758
2874
|
) : null
|
|
2759
2875
|
) : null),
|
|
2760
2876
|
)
|
|
2761
2877
|
}),
|
|
2762
|
-
|
|
2878
|
+
h('button', {
|
|
2763
2879
|
type: 'button', className: 'dsub-mini',
|
|
2764
2880
|
onClick: () => addSlot(prov.id),
|
|
2765
2881
|
}, t('addAccount')),
|
|
2766
2882
|
)
|
|
2767
2883
|
}),
|
|
2768
|
-
|
|
2769
|
-
|
|
2884
|
+
h('div', { className: 'dsub-foot' },
|
|
2885
|
+
h('button', {
|
|
2770
2886
|
type: 'button', className: 'dsub-save',
|
|
2771
2887
|
onClick: () => save().catch((e) => setErr(cleanErrorMessage(e.message || e))),
|
|
2772
2888
|
}, t('save')),
|
|
2773
|
-
saved ?
|
|
2774
|
-
info ?
|
|
2775
|
-
err ?
|
|
2889
|
+
saved ? h('span', { className: 'dsub-ok' }, t('saved')) : null,
|
|
2890
|
+
info ? h('span', { className: 'dsub-ok' }, info) : null,
|
|
2891
|
+
err ? h('span', { className: 'dsub-bad' }, err) : null,
|
|
2776
2892
|
),
|
|
2777
2893
|
)
|
|
2778
2894
|
}
|
|
@@ -2786,29 +2902,29 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2786
2902
|
// Row seat (plugins.row.config): the host page draws title/icon/crumb and the
|
|
2787
2903
|
// padding, so the summary is a one-liner and the page drops our card chrome.
|
|
2788
2904
|
if (props && props.view === 'summary') {
|
|
2789
|
-
return
|
|
2905
|
+
return h('div', { className: 'dsub-description' }, cardT('cardIntro'))
|
|
2790
2906
|
}
|
|
2791
2907
|
// Check host snapshot status (#408, #459): loading, unavailable, or error
|
|
2792
2908
|
if (props && props.status === 'loading') {
|
|
2793
|
-
return
|
|
2909
|
+
return h(page ? 'div' : 'li', {
|
|
2794
2910
|
className: page ? 'dsub-page' : 'dsub-card',
|
|
2795
2911
|
},
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2912
|
+
h('div', { className: 'dsub-header', style: { cursor: 'default' } },
|
|
2913
|
+
h('div', { className: 'dsub-headText' },
|
|
2914
|
+
h('div', { className: 'dsub-name' }, cardT('title')),
|
|
2915
|
+
h('div', { className: 'dsub-description' }, cardT('loading') || cardT('settingsLoading') || 'Loadingโฆ'),
|
|
2800
2916
|
),
|
|
2801
2917
|
)
|
|
2802
2918
|
)
|
|
2803
2919
|
}
|
|
2804
2920
|
if (props && props.status === 'unavailable') {
|
|
2805
|
-
return
|
|
2921
|
+
return h(page ? 'div' : 'li', {
|
|
2806
2922
|
className: page ? 'dsub-page' : 'dsub-card',
|
|
2807
2923
|
},
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2924
|
+
h('div', { className: 'dsub-header', style: { cursor: 'default' } },
|
|
2925
|
+
h('div', { className: 'dsub-headText' },
|
|
2926
|
+
h('div', { className: 'dsub-name' }, cardT('title')),
|
|
2927
|
+
h('div', { className: 'dsub-description', style: { color: 'var(--dsw-alias-state-warn-primary)' } },
|
|
2812
2928
|
cardT('unavailable') || cardT('settingsUnavailable') || 'Settings are unavailable',
|
|
2813
2929
|
),
|
|
2814
2930
|
),
|
|
@@ -2816,37 +2932,37 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
2816
2932
|
)
|
|
2817
2933
|
}
|
|
2818
2934
|
if (props && props.status === 'error') {
|
|
2819
|
-
return
|
|
2935
|
+
return h(page ? 'div' : 'li', {
|
|
2820
2936
|
className: page ? 'dsub-page' : 'dsub-card',
|
|
2821
2937
|
},
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2938
|
+
h('div', { className: 'dsub-header', style: { cursor: 'default' } },
|
|
2939
|
+
h('div', { className: 'dsub-headText' },
|
|
2940
|
+
h('div', { className: 'dsub-name' }, cardT('title')),
|
|
2941
|
+
h('div', { className: 'dsub-description', style: { color: 'var(--dsw-alias-state-error-primary)' } },
|
|
2826
2942
|
(props.error && (props.error.message || String(props.error))) || cardT('error') || cardT('settingsError') || 'Settings error',
|
|
2827
2943
|
),
|
|
2828
2944
|
),
|
|
2829
2945
|
)
|
|
2830
2946
|
)
|
|
2831
2947
|
}
|
|
2832
|
-
return
|
|
2948
|
+
return h(page ? 'div' : 'li', {
|
|
2833
2949
|
className: page ? 'dsub-page' : 'dsub-card' + (open ? ' dsub-cardOpen' : ''),
|
|
2834
2950
|
},
|
|
2835
|
-
|
|
2951
|
+
h('button', {
|
|
2836
2952
|
type: 'button',
|
|
2837
2953
|
className: 'dsub-header',
|
|
2838
2954
|
style: page ? { display: 'none' } : undefined,
|
|
2839
2955
|
onClick: () => setOpen(!open),
|
|
2840
2956
|
'aria-expanded': page ? true : open,
|
|
2841
2957
|
},
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2958
|
+
h('div', { className: 'dsub-headText' },
|
|
2959
|
+
h('div', { className: 'dsub-name' }, cardT('title')),
|
|
2960
|
+
h('div', { className: 'dsub-description' }, cardT('cardIntro')),
|
|
2845
2961
|
),
|
|
2846
|
-
|
|
2962
|
+
h(Chevron, { className: 'dsub-chev' + (open ? ' dsub-chevOpen' : '') }),
|
|
2847
2963
|
),
|
|
2848
|
-
(page || open) ?
|
|
2849
|
-
|
|
2964
|
+
(page || open) ? h('div', { className: 'dsub-body' },
|
|
2965
|
+
h(ErrorBoundary, null, h(SubsSection, props)),
|
|
2850
2966
|
) : null,
|
|
2851
2967
|
)
|
|
2852
2968
|
}
|
|
@@ -3024,21 +3140,21 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3024
3140
|
const cls = state.remaining <= 10 ? ' dsub-cqBarFull' : (state.remaining <= 30 ? ' dsub-cqBarWarn' : '')
|
|
3025
3141
|
var value = null
|
|
3026
3142
|
if (state.mode === 'percent') {
|
|
3027
|
-
value =
|
|
3143
|
+
value = h('span', { className: 'dsub-cqB' }, Math.round(state.remaining) + '%')
|
|
3028
3144
|
} else if (state.mode === 'bar') {
|
|
3029
|
-
value =
|
|
3030
|
-
|
|
3145
|
+
value = h('span', { className: 'dsub-cqBar' + cls },
|
|
3146
|
+
h('span', { className: 'dsub-cqBarFill', style: { width: Math.min(100, Math.max(0, state.remaining)) + '%' } }))
|
|
3031
3147
|
} else if (state.mode === 'forecast') {
|
|
3032
3148
|
var est = state.est
|
|
3033
|
-
if (!est || est.status === 'calibrating') value =
|
|
3034
|
-
else if (est.status === 'idle') value =
|
|
3149
|
+
if (!est || est.status === 'calibrating') value = h('span', { className: 'dsub-cqB' }, t('fcCalibrating'))
|
|
3150
|
+
else if (est.status === 'idle') value = h('span', { className: 'dsub-cqB' }, t('fcIdle'))
|
|
3035
3151
|
else {
|
|
3036
3152
|
var secs = est.runwaySeconds || 0
|
|
3037
3153
|
var txt = secs >= 3600 ? ('~' + (Math.round((secs / 3600) * 10) / 10) + t('fcHours')) : ('~' + Math.max(1, Math.round(secs / 60)) + t('fcMinutes'))
|
|
3038
|
-
value =
|
|
3154
|
+
value = h('span', { className: 'dsub-cqB' }, txt)
|
|
3039
3155
|
}
|
|
3040
3156
|
} else return null
|
|
3041
|
-
return
|
|
3157
|
+
return h('span', { className: 'dsub-cq', title: t('forecast') + ' ยท ' + state.active.provider }, value)
|
|
3042
3158
|
}
|
|
3043
3159
|
|
|
3044
3160
|
// #83: SUBS(N) pill in the session header with a pool health LED and
|
|
@@ -3255,23 +3371,23 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3255
3371
|
const primPct = primaryWin && primaryWin.usedPercent != null ? Math.round(primaryWin.usedPercent) : (a.usagePercent != null ? Math.round(a.usagePercent) : 0)
|
|
3256
3372
|
const secPct = secWin && secWin.usedPercent != null ? Math.round(secWin.usedPercent) : null
|
|
3257
3373
|
|
|
3258
|
-
return
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
a.fastMode ?
|
|
3374
|
+
return h('div', { className: 'dsub-heroCard' },
|
|
3375
|
+
h('div', { className: 'dsub-heroHead' },
|
|
3376
|
+
h('div', { className: 'dsub-heroTitle' },
|
|
3377
|
+
h('span', { className: 'dsub-brandBadge ' + b.cls, style: { width: 24, height: 24, fontSize: 11 } }, b.icon),
|
|
3378
|
+
h('span', null, (a.provider ? a.provider.toUpperCase() : 'LLM') + (a.index ? ' #' + a.index : '')),
|
|
3379
|
+
a.fastMode ? h('span', { className: 'dsub-pillTag', style: { background: 'color-mix(in srgb,var(--dsw-alias-state-warn-primary) 15%,transparent)', color: 'var(--dsw-alias-state-warn-primary)' } }, 'โก FAST 1.5x') : null,
|
|
3264
3380
|
),
|
|
3265
|
-
|
|
3381
|
+
h('span', { className: 'dsub-heroModel' }, a.model || 'active model'),
|
|
3266
3382
|
),
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3383
|
+
h('div', { className: 'dsub-heroBars' },
|
|
3384
|
+
h('div', null,
|
|
3385
|
+
h('div', { className: 'dsub-barLabelRow' },
|
|
3386
|
+
h('span', { style: { fontWeight: 600 } }, ((primaryWin && primaryWin.label) ? primaryWin.label + ' window' : t('subs5hWindow')) + (primaryWin && primaryWin.resetAt ? ' (' + formatRelativeReset(primaryWin.resetAt, t('lang'), now) + ')' : '')),
|
|
3387
|
+
h('span', { style: { fontVariantNumeric: 'tabular-nums', fontWeight: 600 } }, primPct + '% ' + t('subsUsed') + ' (' + (100 - primPct) + '% ' + t('subsFree') + ')'),
|
|
3272
3388
|
),
|
|
3273
|
-
|
|
3274
|
-
|
|
3389
|
+
h('div', { className: 'dsub-barTrack' },
|
|
3390
|
+
h('div', {
|
|
3275
3391
|
className: 'dsub-barFillGrad',
|
|
3276
3392
|
style: {
|
|
3277
3393
|
width: Math.min(100, Math.max(0, primPct)) + '%',
|
|
@@ -3280,13 +3396,13 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3280
3396
|
}),
|
|
3281
3397
|
),
|
|
3282
3398
|
),
|
|
3283
|
-
secWin ?
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3399
|
+
secWin ? h('div', null,
|
|
3400
|
+
h('div', { className: 'dsub-barLabelRow' },
|
|
3401
|
+
h('span', null, ((secWin.label || '7d') + ' window') + (secWin && secWin.resetAt ? ' (' + formatRelativeReset(secWin.resetAt, t('lang'), now) + ')' : '')),
|
|
3402
|
+
h('span', { style: { fontVariantNumeric: 'tabular-nums' } }, secPct + '%'),
|
|
3287
3403
|
),
|
|
3288
|
-
|
|
3289
|
-
|
|
3404
|
+
h('div', { className: 'dsub-barTrack' },
|
|
3405
|
+
h('div', {
|
|
3290
3406
|
className: 'dsub-barFillGrad',
|
|
3291
3407
|
style: {
|
|
3292
3408
|
width: Math.min(100, Math.max(0, secPct)) + '%',
|
|
@@ -3345,19 +3461,19 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3345
3461
|
else { statusClass = 'dsub-statusOk'; statusText = (pct != null ? pct + '% ยท ' : '') + t('subsLogged') }
|
|
3346
3462
|
}
|
|
3347
3463
|
|
|
3348
|
-
return
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
isActiveThis ?
|
|
3355
|
-
a.proxy ?
|
|
3464
|
+
return h('div', { className: 'dsub-accountCard', key: i },
|
|
3465
|
+
h('div', { className: 'dsub-brandBadge ' + b.cls }, b.icon),
|
|
3466
|
+
h('div', { className: 'dsub-accInfo' },
|
|
3467
|
+
h('div', { className: 'dsub-accNameRow' },
|
|
3468
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6 } },
|
|
3469
|
+
h('span', { className: 'dsub-accName' }, a.provider.toUpperCase() + (a.index ? ' #' + a.index : '')),
|
|
3470
|
+
isActiveThis ? h('span', { className: 'dsub-pillTag', style: { background: 'color-mix(in srgb,var(--dsw-alias-state-success-primary) 15%,transparent)', color: 'var(--dsw-alias-state-success-primary)' } }, 'ACTIVE') : null,
|
|
3471
|
+
a.proxy ? h('span', { className: 'dsub-dim', title: a.proxy }, '๐ proxy') : null,
|
|
3356
3472
|
),
|
|
3357
|
-
|
|
3473
|
+
h('span', { className: 'dsub-accStatusTag ' + statusClass, role: 'status', 'aria-live': 'polite' }, statusText),
|
|
3358
3474
|
),
|
|
3359
|
-
(isLogged && pct != null) ?
|
|
3360
|
-
|
|
3475
|
+
(isLogged && pct != null) ? h('div', { className: 'dsub-barTrack', style: { marginTop: 4, height: 4 } },
|
|
3476
|
+
h('div', {
|
|
3361
3477
|
className: 'dsub-barFillGrad',
|
|
3362
3478
|
style: {
|
|
3363
3479
|
width: Math.min(100, Math.max(0, pct)) + '%',
|
|
@@ -3369,49 +3485,49 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3369
3485
|
)
|
|
3370
3486
|
})
|
|
3371
3487
|
|
|
3372
|
-
return
|
|
3373
|
-
toasts.length > 0 ?
|
|
3374
|
-
toasts.map((toast) =>
|
|
3375
|
-
|
|
3376
|
-
|
|
3488
|
+
return h(React.Fragment, null,
|
|
3489
|
+
toasts.length > 0 ? h('div', { className: 'dsub-toast-container' },
|
|
3490
|
+
toasts.map((toast) => h('div', { className: 'dsub-toast ' + toast.cls, key: toast.id },
|
|
3491
|
+
h('span', null, toast.message),
|
|
3492
|
+
h('button', {
|
|
3377
3493
|
type: 'button',
|
|
3378
3494
|
className: 'dsub-toast-close',
|
|
3379
3495
|
onClick: () => dismissToast(toast.id),
|
|
3380
3496
|
}, "\u00d7"),
|
|
3381
3497
|
))
|
|
3382
3498
|
) : null,
|
|
3383
|
-
|
|
3499
|
+
h('button', {
|
|
3384
3500
|
type: 'button',
|
|
3385
3501
|
className: 'dsub-pill',
|
|
3386
3502
|
'aria-expanded': state.open ? 'true' : 'false',
|
|
3387
3503
|
title: t('subsPill') + ': ' + (n > 0 ? (n + ' ' + t('connected')) : t('notConnected')),
|
|
3388
3504
|
onClick: () => setState((s) => Object.assign({}, s, { open: !s.open })),
|
|
3389
3505
|
},
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3506
|
+
h('span', { className: 'dsub-led ' + led }),
|
|
3507
|
+
h('span', null, pillText),
|
|
3508
|
+
h('span', { style: { fontSize: 9, opacity: 0.6, marginLeft: 2 } }, 'โผ'),
|
|
3393
3509
|
),
|
|
3394
|
-
state.open ?
|
|
3510
|
+
state.open ? h('div', {
|
|
3395
3511
|
className: 'dsub-modalWrap',
|
|
3396
3512
|
onClick: (e) => { if (e.target === e.currentTarget) setState((s) => Object.assign({}, s, { open: false })) },
|
|
3397
3513
|
},
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3514
|
+
h('div', { className: 'dsub-modal', role: 'dialog', 'aria-modal': 'true', 'aria-label': t('subsModalTitle') },
|
|
3515
|
+
h('div', { className: 'dsub-modalHead' },
|
|
3516
|
+
h('div', { className: 'dsub-modalTitleWrap' },
|
|
3517
|
+
h('div', { className: 'dsub-modalIcon' }, 'โก'),
|
|
3518
|
+
h('div', null,
|
|
3519
|
+
h('div', { style: { fontWeight: 700, fontSize: 15 } }, t('subsModalTitle')),
|
|
3520
|
+
h('div', { className: 'dsub-dim' }, n + ' of ' + total + ' ' + t('connected')),
|
|
3405
3521
|
),
|
|
3406
3522
|
),
|
|
3407
|
-
|
|
3408
|
-
|
|
3523
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 6 } },
|
|
3524
|
+
h('button', {
|
|
3409
3525
|
type: 'button',
|
|
3410
3526
|
className: 'dsub-mini',
|
|
3411
3527
|
title: t('subsRefresh'),
|
|
3412
3528
|
onClick: () => pull(),
|
|
3413
3529
|
}, state.loading ? 'โฆ' : '๐'),
|
|
3414
|
-
|
|
3530
|
+
h('button', {
|
|
3415
3531
|
type: 'button',
|
|
3416
3532
|
className: 'dsub-mini',
|
|
3417
3533
|
autoFocus: true,
|
|
@@ -3421,11 +3537,11 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3421
3537
|
),
|
|
3422
3538
|
),
|
|
3423
3539
|
renderActiveHero(),
|
|
3424
|
-
|
|
3425
|
-
rows.length ? rows :
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3540
|
+
h('div', { className: 'dsub-poolTitle' }, t('subsPoolTitle')),
|
|
3541
|
+
rows.length ? rows : h('div', { className: 'dsub-sub', style: { padding: '12px 0' } }, t('subsNotLogged')),
|
|
3542
|
+
h('div', { className: 'dsub-modalFoot' },
|
|
3543
|
+
h('span', { className: 'dsub-dim' }, 'DSH Subscriptions'),
|
|
3544
|
+
h('a', {
|
|
3429
3545
|
className: 'dsub-btnSec',
|
|
3430
3546
|
href: '#',
|
|
3431
3547
|
onClick: (e) => {
|
|
@@ -3466,7 +3582,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3466
3582
|
order: 15,
|
|
3467
3583
|
locale: NS,
|
|
3468
3584
|
},
|
|
3469
|
-
() =>
|
|
3585
|
+
() => h(ErrorBoundary, null, h(SubsPill, { t, ctx })),
|
|
3470
3586
|
),
|
|
3471
3587
|
)
|
|
3472
3588
|
}, 'dsh-subscriptions: subs pill')
|
|
@@ -3482,7 +3598,7 @@ const cssId = 'dsh-subscriptions/settings.module.css'
|
|
|
3482
3598
|
order: 5,
|
|
3483
3599
|
locale: NS,
|
|
3484
3600
|
},
|
|
3485
|
-
() =>
|
|
3601
|
+
() => h(ErrorBoundary, null, h(ComposerQuota, { t })),
|
|
3486
3602
|
),
|
|
3487
3603
|
)
|
|
3488
3604
|
}, 'dsh-subscriptions: composer quota')
|