@jxgame2020/dsh-token-quota 0.1.31 → 0.1.32
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/lib/client.js +200 -116
- package/lib/index.js +5 -2
- package/lib/types/client/TokenQuotaPanel.d.ts +3 -1
- package/lib/types/client/TokenQuotaPanel.js +46 -9
- package/lib/types/client/index.js +7 -0
- package/lib/types/client/locales.d.ts +2 -0
- package/lib/types/client/locales.js +2 -0
- package/lib/types/client/store.d.ts +16 -2
- package/lib/types/client/store.js +36 -3
- package/lib/types/index.js +4 -1
- package/lib/types/types.d.ts +6 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -37,6 +37,7 @@ window.__ModuleLoader__.load({
|
|
|
37
37
|
onFull: "stop",
|
|
38
38
|
checkUpdates: true,
|
|
39
39
|
dimWhenIdle: false,
|
|
40
|
+
order: [],
|
|
40
41
|
musicEnabled: false,
|
|
41
42
|
musicVolume: .5,
|
|
42
43
|
musicStyle: "pentatonic",
|
|
@@ -82,6 +83,9 @@ window.__ModuleLoader__.load({
|
|
|
82
83
|
setDimWhenIdle: (d, dimWhenIdle) => {
|
|
83
84
|
d.dimWhenIdle = dimWhenIdle;
|
|
84
85
|
},
|
|
86
|
+
setOrder: (d, order) => {
|
|
87
|
+
d.order = order;
|
|
88
|
+
},
|
|
85
89
|
setMusicEnabled: (d, enabled) => {
|
|
86
90
|
d.musicEnabled = enabled;
|
|
87
91
|
},
|
|
@@ -95,7 +99,7 @@ window.__ModuleLoader__.load({
|
|
|
95
99
|
d.musicOnlyCurrentSession = only;
|
|
96
100
|
},
|
|
97
101
|
setUpgrade: (d, upgrade) => {
|
|
98
|
-
const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.
|
|
102
|
+
const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.32" ? upgrade : null;
|
|
99
103
|
if (d.upgrade === null || d.upgrade.latestVersion !== normalized?.latestVersion) d.upgradeDismissed = false;
|
|
100
104
|
d.upgrade = normalized;
|
|
101
105
|
},
|
|
@@ -157,9 +161,11 @@ window.__ModuleLoader__.load({
|
|
|
157
161
|
* @param groups - advisory provider groups of the current session.
|
|
158
162
|
* @param snapshot - latest quota snapshot, or null before the first one.
|
|
159
163
|
* @param current - current model selection reported by the Host.
|
|
160
|
-
* @
|
|
164
|
+
* @param order - user's drag-to-reorder preference (model keys); listed keys
|
|
165
|
+
* come first in that exact order, the rest follow in catalog order.
|
|
166
|
+
* @returns rows in display order.
|
|
161
167
|
*/
|
|
162
|
-
function mergeModelRows(groups, snapshot, current) {
|
|
168
|
+
function mergeModelRows(groups, snapshot, current, order = []) {
|
|
163
169
|
const entryByKey = new Map((snapshot?.entries ?? []).map((entry) => [entry.key, entry]));
|
|
164
170
|
const rows = /* @__PURE__ */ new Map();
|
|
165
171
|
for (const group of groups) for (const model of group.models) {
|
|
@@ -187,11 +193,33 @@ window.__ModuleLoader__.load({
|
|
|
187
193
|
current: current !== null && current.provider === entry.provider && current.model === entry.model
|
|
188
194
|
});
|
|
189
195
|
}
|
|
190
|
-
|
|
196
|
+
const rank = new Map(order.map((key, index) => [key, index]));
|
|
197
|
+
return [...rows.values()].sort((left, right) => {
|
|
198
|
+
const leftRank = rank.get(left.key);
|
|
199
|
+
const rightRank = rank.get(right.key);
|
|
200
|
+
if (leftRank !== void 0 && rightRank !== void 0) return leftRank - rightRank;
|
|
201
|
+
if (leftRank !== void 0) return -1;
|
|
202
|
+
if (rightRank !== void 0) return 1;
|
|
203
|
+
return left.key.localeCompare(right.key);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Move one key to another key's position, returning the full reordered key
|
|
208
|
+
* list (the shape persisted in the settings document's `order`).
|
|
209
|
+
*/
|
|
210
|
+
function reorderKeys(keys, from, to) {
|
|
211
|
+
const next = [...keys];
|
|
212
|
+
const fromIndex = next.indexOf(from);
|
|
213
|
+
const toIndex = next.indexOf(to);
|
|
214
|
+
if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex) return next;
|
|
215
|
+
const [moved] = next.splice(fromIndex, 1);
|
|
216
|
+
if (moved === void 0) return next;
|
|
217
|
+
next.splice(toIndex, 0, moved);
|
|
218
|
+
return next;
|
|
191
219
|
}
|
|
192
220
|
//#endregion
|
|
193
221
|
//#region \0dsh-css:/Users/jxgame/Desktop/works/deepseek-harness-package/dsh-token-quota/packages/token-quota/src/client/TokenQuotaPanel.module.css.mjs
|
|
194
|
-
const css = ".NPLLIq_panel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;z-index:40;opacity:1;border-radius:12px;flex-direction:column;width:320px;max-height:min(72vh,560px);transition:opacity .18s;display:flex;position:fixed;top:56px;right:12px;overflow:hidden;box-shadow:0 8px 28px #0000002e}.NPLLIq_panelDim{opacity:.55}.NPLLIq_panelDimStrong{opacity:.3}.NPLLIq_header{border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:flex-start;gap:8px;padding:10px 12px;display:flex}.NPLLIq_header:active{cursor:grabbing}.NPLLIq_headerText{flex-direction:column;gap:2px;min-width:0;display:flex}.NPLLIq_title{color:var(--dsw-alias-label-primary);align-items:baseline;gap:6px;font-size:13px;font-weight:600;display:flex}.NPLLIq_version{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:10px;font-weight:500}.NPLLIq_versionNew{color:var(--dsw-alias-status-warning-foreground,#b56900);background:var(--dsw-alias-status-warning-background,#fff6d7);cursor:default;border-radius:4px;padding:1px 6px}.NPLLIq_subtitle{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_collapse{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_collapse:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_body{padding:4px 0;overflow-y:auto}.NPLLIq_row{border-bottom:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:6px;padding:8px 12px;display:flex}.NPLLIq_rowHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.NPLLIq_rowName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;font-size:12px;font-weight:500;display:inline-flex;overflow:hidden}.NPLLIq_currentBadge{color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-state-success-primary);border-radius:8px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_rowMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.NPLLIq_bar{background:var(--dsw-alias-bg-layer-1);border-radius:3px;height:6px;overflow:hidden}.NPLLIq_fillIdle{background:var(--dsw-alias-brand-primary);height:100%;transition:width .2s}.NPLLIq_fillWarn{background:var(--dsw-alias-state-warn-primary);height:100%;transition:width .2s}.NPLLIq_fillOver{background:var(--dsw-alias-state-error-primary);height:100%;transition:width .2s}.NPLLIq_controls{align-items:center;gap:6px;display:flex}.NPLLIq_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-primary);border-radius:6px;flex:1;padding:4px 8px;font-size:11px}.NPLLIq_input::placeholder{color:var(--dsw-alias-label-secondary)}.NPLLIq_save,.NPLLIq_switch{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px;font-size:11px}.NPLLIq_save:hover,.NPLLIq_switch:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2)}.NPLLIq_switch:disabled{opacity:.5;cursor:default}.NPLLIq_notice,.NPLLIq_noticeError{color:var(--dsw-alias-label-secondary);padding:10px 12px;font-size:12px}.NPLLIq_noticeError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_tab{background:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay);pointer-events:auto;cursor:pointer;z-index:90;border-radius:10px;align-items:center;gap:6px;padding:9px 14px;font-size:12px;font-weight:600;display:inline-flex;position:fixed;top:56px;right:12px;box-shadow:0 6px 20px #00000040}.NPLLIq_tab:hover{filter:brightness(1.08)}.NPLLIq_tabIcon{font-size:12px;line-height:1}.NPLLIq_tabLabel{white-space:nowrap}.NPLLIq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.NPLLIq_settingsBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_settingsBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_settingsBtnActive{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2,#0000000f);box-shadow:inset 0 0 0 1px var(--dsw-alias-brand-primary);font-weight:700}.NPLLIq_selectBtn{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_selectBtn:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_gearBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;margin-left:6px;padding:0 2px;font-size:12px;line-height:1}.NPLLIq_gearBtn:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_fullNotice{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;margin:6px 12px;padding:8px 10px;font-size:12px}.NPLLIq_upgradeBanner{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-divider-1,#0000001a);border-radius:8px;margin:6px 12px;padding:10px 30px 10px 10px;font-size:12px;position:relative}@keyframes NPLLIq_upgradeBannerFlash{0%,to{border-color:var(--dsw-alias-divider-1,#0000001a);box-shadow:0 0 #f0a02000}50%{border-color:var(--dsw-alias-status-warning-foreground,#b56900);box-shadow:0 0 0 5px #f0a02073}}.NPLLIq_upgradeBannerFlash{border-color:var(--dsw-alias-status-warning-foreground,#b56900);animation:.6s ease-in-out 4 NPLLIq_upgradeBannerFlash}.NPLLIq_upgradeBannerText{margin-bottom:6px;font-weight:600}.NPLLIq_upgradeCommands{flex-direction:column;gap:4px;display:flex}.NPLLIq_upgradeCommandRow{align-items:center;gap:6px;display:flex}.NPLLIq_upgradeCommand{background:var(--dsw-alias-bg-layer-2,#0000000a);white-space:nowrap;border-radius:4px;flex:1;min-width:0;padding:4px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;overflow-x:auto}.NPLLIq_copyBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;flex:none;padding:3px 8px;font-size:11px;transition:transform 80ms,background .12s,color .12s}.NPLLIq_copyBtn:hover{background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_copyBtn:active{transform:scale(.92)}.NPLLIq_copyBtnDone{background:var(--dsw-alias-status-success-background,#14963c1f);border-color:var(--dsw-alias-status-success-foreground,#0a7d32);color:var(--dsw-alias-status-success-foreground,#0a7d32);font-weight:600}.NPLLIq_upgradeHint{color:var(--dsw-alias-label-secondary);margin-top:6px;font-size:11px}.NPLLIq_upgradeClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;font-size:16px;line-height:1;position:absolute;top:4px;right:6px}.NPLLIq_upgradeClose:hover{background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary)}.NPLLIq_checkUpdatesRow{justify-content:space-between;align-items:center;gap:12px;display:flex}.NPLLIq_checkUpdatesLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.NPLLIq_checkUpdatesLabel input{margin:0}.NPLLIq_checkUpdatesLabel input[type=range]{min-width:90px;accent-color:var(--dsw-alias-brand-primary);flex:1}.NPLLIq_checkUpdatesLabel select{background:var(--dsw-alias-bg-layer-2,#0000000a);min-width:90px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-divider-1,#00000026);border-radius:4px;flex:1;padding:2px 4px;font-size:12px}.NPLLIq_checkBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;text-align:center;border-radius:4px;flex:none;min-width:72px;padding:4px 10px;font-size:12px}.NPLLIq_checkBtn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_checkBtn:disabled{opacity:.6;cursor:default}.NPLLIq_checkErrorHint{color:var(--dsw-alias-state-error-primary,#c00);background:var(--dsw-alias-state-error-background,#ff00000f);border:1px solid var(--dsw-alias-state-error-border,#b4000040);word-break:break-all;border-radius:6px;margin-top:8px;padding:6px 8px;font-size:11px;line-height:1.4}.NPLLIq_dialog{z-index:100;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;gap:12px;width:430px;max-width:94vw;max-height:80vh;padding:14px;display:flex;position:fixed;top:50%;left:50%;overflow-y:auto;transform:translate(-50%,-50%);box-shadow:0 8px 28px #00000040}.NPLLIq_dialogTabs{border-bottom:1px solid var(--dsw-alias-divider-1,#00000014);gap:2px;margin:-6px -14px 0;padding:0 14px;display:flex}.NPLLIq_dialogTab{appearance:none;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px 8px;font-size:12px}.NPLLIq_dialogTab:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_dialogTabActive{color:var(--dsw-alias-brand-primary);border-bottom-color:var(--dsw-alias-brand-primary);font-weight:600}.NPLLIq_settingsDialog{height:min(560px,80vh)}.NPLLIq_dialogTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.NPLLIq_dialogSection{flex-direction:column;gap:6px;display:flex}.NPLLIq_dialogLabel{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500}.NPLLIq_monitorHint{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_dialogHint{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:11px;line-height:1.4}.NPLLIq_monitorList{flex-direction:column;gap:2px;max-height:180px;display:flex;overflow-y:auto}.NPLLIq_monitorRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:2px 4px;font-size:12px;display:flex}.NPLLIq_monitorRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_monitorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.NPLLIq_radioRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:3px 4px;font-size:12px;display:flex}.NPLLIq_radioRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_dialogActions{justify-content:flex-end;gap:6px;display:flex}.NPLLIq_dialogBtn,.NPLLIq_dialogBtnPrimary{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:6px;padding:4px 12px;font-size:11px}.NPLLIq_dialogBtn{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.NPLLIq_dialogBtnPrimary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay)}.NPLLIq_dialogHeader{z-index:2;background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:center;gap:8px;margin:-14px -14px 0;padding:14px 14px 8px;display:flex;position:sticky;top:-14px}.NPLLIq_dialogHeader:active{cursor:grabbing}.NPLLIq_dialogClose{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;font-size:18px;line-height:1;display:flex}.NPLLIq_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_resetRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.NPLLIq_resetSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:3px 6px;font-size:12px}.NPLLIq_logTable{border-collapse:collapse;width:100%;font-size:11px}.NPLLIq_logTable th{text-align:left;color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);padding:4px 6px;font-weight:500}.NPLLIq_logTable td{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;padding:4px 6px}.NPLLIq_logDayCol{white-space:nowrap;color:var(--dsw-alias-label-secondary)}.NPLLIq_logModelCol{text-overflow:ellipsis;white-space:nowrap;max-width:160px;overflow:hidden}.NPLLIq_logUsedCol{text-align:right}.NPLLIq_logDialog{gap:0;width:380px;max-height:min(72vh,480px);padding:0}.NPLLIq_logHeader{background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:14px 14px 8px;display:flex}.NPLLIq_logHeader:active{cursor:grabbing}.NPLLIq_logScroll{flex:1;min-height:0;padding:0 14px 14px;overflow:auto}.NPLLIq_logToolbar{flex:1;align-items:center;gap:6px;display:flex}.NPLLIq_logSearch{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);min-width:0;color:var(--dsw-alias-label-primary);border-radius:4px;flex:1;padding:3px 6px;font-size:11px}.NPLLIq_logSearch:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}.NPLLIq_logClearBtn{border:1px solid var(--dsw-alias-state-error-border,#b400004d);color:var(--dsw-alias-state-error-primary,#c00);cursor:pointer;white-space:nowrap;background:0 0;border-radius:4px;flex:none;padding:3px 8px;font-size:11px}.NPLLIq_logClearBtn:hover{background:var(--dsw-alias-state-error-background,#ff00000f)}.NPLLIq_logPager{border-top:1px solid var(--dsw-alias-divider-1,#00000014);background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-secondary);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 14px;font-size:11px;display:flex}.NPLLIq_logPagerInfo{white-space:nowrap}.NPLLIq_logPagerControls{align-items:center;gap:4px;display:flex}.NPLLIq_logPagerBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:24px;height:24px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;font-size:13px;line-height:1}.NPLLIq_logPagerBtn:disabled{opacity:.4;cursor:default}.NPLLIq_logPagerPages{text-align:center;min-width:50px;color:var(--dsw-alias-label-secondary)}.NPLLIq_logPageSizeSelect{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;padding:2px 4px;font-size:11px}.NPLLIq_dialogOverlay{z-index:100001;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.NPLLIq_logClearDialog{gap:0;width:320px;padding:16px}.NPLLIq_dialogBody{color:var(--dsw-alias-label-secondary);margin:6px 0 10px;font-size:12px;line-height:1.5}.NPLLIq_logClearDate{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:100%;color:var(--dsw-alias-label-primary);border-radius:6px;margin-bottom:12px;padding:6px 8px;font-size:13px}.NPLLIq_logClearDate:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}";
|
|
222
|
+
const css = ".NPLLIq_panel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;z-index:40;opacity:1;border-radius:12px;flex-direction:column;width:320px;max-height:min(72vh,560px);transition:opacity .18s;display:flex;position:fixed;top:56px;right:12px;overflow:hidden;box-shadow:0 8px 28px #0000002e}.NPLLIq_panelDim{opacity:.55}.NPLLIq_panelDimStrong{opacity:.3}.NPLLIq_header{border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:flex-start;gap:8px;padding:10px 12px;display:flex}.NPLLIq_header:active{cursor:grabbing}.NPLLIq_headerText{flex-direction:column;gap:2px;min-width:0;display:flex}.NPLLIq_title{color:var(--dsw-alias-label-primary);align-items:baseline;gap:6px;font-size:13px;font-weight:600;display:flex}.NPLLIq_version{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:10px;font-weight:500}.NPLLIq_versionNew{color:var(--dsw-alias-status-warning-foreground,#b56900);background:var(--dsw-alias-status-warning-background,#fff6d7);cursor:default;border-radius:4px;padding:1px 6px}.NPLLIq_subtitle{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_collapse{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_collapse:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_body{padding:4px 0;overflow-y:auto}.NPLLIq_row{border-bottom:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:6px;padding:8px 12px;display:flex}.NPLLIq_rowHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.NPLLIq_rowDrag{cursor:grab;color:var(--dsw-alias-label-secondary);user-select:none;border-radius:4px;flex:none;margin-right:2px;padding:2px 3px;font-size:11px;line-height:1}.NPLLIq_rowDrag:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_rowDrag:active{cursor:grabbing}.NPLLIq_rowDragging{opacity:.45}.NPLLIq_rowDropTarget{box-shadow:inset 0 2px 0 var(--dsw-alias-brand-primary)}.NPLLIq_rowName{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;align-items:center;gap:6px;font-size:12px;font-weight:500;display:inline-flex;overflow:hidden}.NPLLIq_currentBadge{color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-state-success-primary);border-radius:8px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_rowMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.NPLLIq_bar{background:var(--dsw-alias-bg-layer-1);border-radius:3px;height:6px;overflow:hidden}.NPLLIq_fillIdle{background:var(--dsw-alias-brand-primary);height:100%;transition:width .2s}.NPLLIq_fillWarn{background:var(--dsw-alias-state-warn-primary);height:100%;transition:width .2s}.NPLLIq_fillOver{background:var(--dsw-alias-state-error-primary);height:100%;transition:width .2s}.NPLLIq_controls{align-items:center;gap:6px;display:flex}.NPLLIq_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-primary);border-radius:6px;flex:1;padding:4px 8px;font-size:11px}.NPLLIq_input::placeholder{color:var(--dsw-alias-label-secondary)}.NPLLIq_save,.NPLLIq_switch{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px;font-size:11px}.NPLLIq_save:hover,.NPLLIq_switch:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2)}.NPLLIq_switch:disabled{opacity:.5;cursor:default}.NPLLIq_notice,.NPLLIq_noticeError{color:var(--dsw-alias-label-secondary);padding:10px 12px;font-size:12px}.NPLLIq_noticeError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_tab{background:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay);pointer-events:auto;cursor:pointer;z-index:90;border-radius:10px;align-items:center;gap:6px;padding:9px 14px;font-size:12px;font-weight:600;display:inline-flex;position:fixed;top:56px;right:12px;box-shadow:0 6px 20px #00000040}.NPLLIq_tab:hover{filter:brightness(1.08)}.NPLLIq_tabIcon{font-size:12px;line-height:1}.NPLLIq_tabLabel{white-space:nowrap}.NPLLIq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.NPLLIq_settingsBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_settingsBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_settingsBtnActive{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2,#0000000f);box-shadow:inset 0 0 0 1px var(--dsw-alias-brand-primary);font-weight:700}.NPLLIq_selectBtn{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_selectBtn:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_gearBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;margin-left:6px;padding:0 2px;font-size:12px;line-height:1}.NPLLIq_gearBtn:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_fullNotice{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;margin:6px 12px;padding:8px 10px;font-size:12px}.NPLLIq_upgradeBanner{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-divider-1,#0000001a);border-radius:8px;margin:6px 12px;padding:10px 30px 10px 10px;font-size:12px;position:relative}@keyframes NPLLIq_upgradeBannerFlash{0%,to{border-color:var(--dsw-alias-divider-1,#0000001a);box-shadow:0 0 #f0a02000}50%{border-color:var(--dsw-alias-status-warning-foreground,#b56900);box-shadow:0 0 0 5px #f0a02073}}.NPLLIq_upgradeBannerFlash{border-color:var(--dsw-alias-status-warning-foreground,#b56900);animation:.6s ease-in-out 4 NPLLIq_upgradeBannerFlash}.NPLLIq_upgradeBannerText{margin-bottom:6px;font-weight:600}.NPLLIq_upgradeCommands{flex-direction:column;gap:4px;display:flex}.NPLLIq_upgradeCommandRow{align-items:center;gap:6px;display:flex}.NPLLIq_upgradeCommand{background:var(--dsw-alias-bg-layer-2,#0000000a);white-space:nowrap;border-radius:4px;flex:1;min-width:0;padding:4px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;overflow-x:auto}.NPLLIq_copyBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;flex:none;padding:3px 8px;font-size:11px;transition:transform 80ms,background .12s,color .12s}.NPLLIq_copyBtn:hover{background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_copyBtn:active{transform:scale(.92)}.NPLLIq_copyBtnDone{background:var(--dsw-alias-status-success-background,#14963c1f);border-color:var(--dsw-alias-status-success-foreground,#0a7d32);color:var(--dsw-alias-status-success-foreground,#0a7d32);font-weight:600}.NPLLIq_upgradeHint{color:var(--dsw-alias-label-secondary);margin-top:6px;font-size:11px}.NPLLIq_upgradeClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;font-size:16px;line-height:1;position:absolute;top:4px;right:6px}.NPLLIq_upgradeClose:hover{background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary)}.NPLLIq_checkUpdatesRow{justify-content:space-between;align-items:center;gap:12px;display:flex}.NPLLIq_checkUpdatesLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.NPLLIq_checkUpdatesLabel input{margin:0}.NPLLIq_checkUpdatesLabel input[type=range]{min-width:90px;accent-color:var(--dsw-alias-brand-primary);flex:1}.NPLLIq_checkUpdatesLabel select{background:var(--dsw-alias-bg-layer-2,#0000000a);min-width:90px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-divider-1,#00000026);border-radius:4px;flex:1;padding:2px 4px;font-size:12px}.NPLLIq_checkBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;text-align:center;border-radius:4px;flex:none;min-width:72px;padding:4px 10px;font-size:12px}.NPLLIq_checkBtn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_checkBtn:disabled{opacity:.6;cursor:default}.NPLLIq_checkErrorHint{color:var(--dsw-alias-state-error-primary,#c00);background:var(--dsw-alias-state-error-background,#ff00000f);border:1px solid var(--dsw-alias-state-error-border,#b4000040);word-break:break-all;border-radius:6px;margin-top:8px;padding:6px 8px;font-size:11px;line-height:1.4}.NPLLIq_dialog{z-index:100;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;gap:12px;width:430px;max-width:94vw;max-height:80vh;padding:14px;display:flex;position:fixed;top:50%;left:50%;overflow-y:auto;transform:translate(-50%,-50%);box-shadow:0 8px 28px #00000040}.NPLLIq_dialogTabs{border-bottom:1px solid var(--dsw-alias-divider-1,#00000014);gap:2px;margin:-6px -14px 0;padding:0 14px;display:flex}.NPLLIq_dialogTab{appearance:none;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px 8px;font-size:12px}.NPLLIq_dialogTab:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_dialogTabActive{color:var(--dsw-alias-brand-primary);border-bottom-color:var(--dsw-alias-brand-primary);font-weight:600}.NPLLIq_settingsDialog{height:min(560px,80vh)}.NPLLIq_dialogTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.NPLLIq_dialogSection{flex-direction:column;gap:6px;display:flex}.NPLLIq_dialogLabel{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500}.NPLLIq_monitorHint{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_dialogHint{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:11px;line-height:1.4}.NPLLIq_monitorList{flex-direction:column;gap:2px;max-height:180px;display:flex;overflow-y:auto}.NPLLIq_monitorRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:2px 4px;font-size:12px;display:flex}.NPLLIq_monitorRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_monitorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.NPLLIq_radioRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:3px 4px;font-size:12px;display:flex}.NPLLIq_radioRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_dialogActions{justify-content:flex-end;gap:6px;display:flex}.NPLLIq_dialogBtn,.NPLLIq_dialogBtnPrimary{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:6px;padding:4px 12px;font-size:11px}.NPLLIq_dialogBtn{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.NPLLIq_dialogBtnPrimary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay)}.NPLLIq_dialogHeader{z-index:2;background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:center;gap:8px;margin:-14px -14px 0;padding:14px 14px 8px;display:flex;position:sticky;top:-14px}.NPLLIq_dialogHeader:active{cursor:grabbing}.NPLLIq_dialogClose{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;font-size:18px;line-height:1;display:flex}.NPLLIq_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_resetRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.NPLLIq_resetSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:3px 6px;font-size:12px}.NPLLIq_logTable{border-collapse:collapse;width:100%;font-size:11px}.NPLLIq_logTable th{text-align:left;color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);padding:4px 6px;font-weight:500}.NPLLIq_logTable td{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;padding:4px 6px}.NPLLIq_logDayCol{white-space:nowrap;color:var(--dsw-alias-label-secondary)}.NPLLIq_logModelCol{text-overflow:ellipsis;white-space:nowrap;max-width:160px;overflow:hidden}.NPLLIq_logUsedCol{text-align:right}.NPLLIq_logDialog{gap:0;width:380px;max-height:min(72vh,480px);padding:0}.NPLLIq_logHeader{background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:14px 14px 8px;display:flex}.NPLLIq_logHeader:active{cursor:grabbing}.NPLLIq_logScroll{flex:1;min-height:0;padding:0 14px 14px;overflow:auto}.NPLLIq_logToolbar{flex:1;align-items:center;gap:6px;display:flex}.NPLLIq_logSearch{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);min-width:0;color:var(--dsw-alias-label-primary);border-radius:4px;flex:1;padding:3px 6px;font-size:11px}.NPLLIq_logSearch:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}.NPLLIq_logClearBtn{border:1px solid var(--dsw-alias-state-error-border,#b400004d);color:var(--dsw-alias-state-error-primary,#c00);cursor:pointer;white-space:nowrap;background:0 0;border-radius:4px;flex:none;padding:3px 8px;font-size:11px}.NPLLIq_logClearBtn:hover{background:var(--dsw-alias-state-error-background,#ff00000f)}.NPLLIq_logPager{border-top:1px solid var(--dsw-alias-divider-1,#00000014);background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-secondary);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 14px;font-size:11px;display:flex}.NPLLIq_logPagerInfo{white-space:nowrap}.NPLLIq_logPagerControls{align-items:center;gap:4px;display:flex}.NPLLIq_logPagerBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:24px;height:24px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;font-size:13px;line-height:1}.NPLLIq_logPagerBtn:disabled{opacity:.4;cursor:default}.NPLLIq_logPagerPages{text-align:center;min-width:50px;color:var(--dsw-alias-label-secondary)}.NPLLIq_logPageSizeSelect{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;padding:2px 4px;font-size:11px}.NPLLIq_dialogOverlay{z-index:100001;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.NPLLIq_logClearDialog{gap:0;width:320px;padding:16px}.NPLLIq_dialogBody{color:var(--dsw-alias-label-secondary);margin:6px 0 10px;font-size:12px;line-height:1.5}.NPLLIq_logClearDate{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:100%;color:var(--dsw-alias-label-primary);border-radius:6px;margin-bottom:12px;padding:6px 8px;font-size:13px}.NPLLIq_logClearDate:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}";
|
|
195
223
|
const tagId = "@jxgame2020/dsh-token-quota/TokenQuotaPanel.module.css";
|
|
196
224
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
197
225
|
const tag = document.createElement("style");
|
|
@@ -201,96 +229,99 @@ window.__ModuleLoader__.load({
|
|
|
201
229
|
document.head.appendChild(tag);
|
|
202
230
|
}
|
|
203
231
|
var TokenQuotaPanel_module_css_default = {
|
|
204
|
-
"
|
|
232
|
+
"subtitle": "NPLLIq_subtitle",
|
|
233
|
+
"headerActions": "NPLLIq_headerActions",
|
|
205
234
|
"bar": "NPLLIq_bar",
|
|
206
|
-
"
|
|
207
|
-
"
|
|
208
|
-
"
|
|
209
|
-
"
|
|
235
|
+
"collapse": "NPLLIq_collapse",
|
|
236
|
+
"tabLabel": "NPLLIq_tabLabel",
|
|
237
|
+
"rowMeta": "NPLLIq_rowMeta",
|
|
238
|
+
"dialog": "NPLLIq_dialog",
|
|
239
|
+
"panelDimStrong": "NPLLIq_panelDimStrong",
|
|
240
|
+
"settingsBtn": "NPLLIq_settingsBtn",
|
|
241
|
+
"settingsDialog": "NPLLIq_settingsDialog",
|
|
242
|
+
"controls": "NPLLIq_controls",
|
|
210
243
|
"resetRow": "NPLLIq_resetRow",
|
|
211
|
-
"
|
|
212
|
-
"
|
|
213
|
-
"
|
|
214
|
-
"
|
|
244
|
+
"fillOver": "NPLLIq_fillOver",
|
|
245
|
+
"upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
|
|
246
|
+
"radioRow": "NPLLIq_radioRow",
|
|
247
|
+
"rowHeader": "NPLLIq_rowHeader",
|
|
248
|
+
"fillIdle": "NPLLIq_fillIdle",
|
|
249
|
+
"logTable": "NPLLIq_logTable",
|
|
250
|
+
"fullNotice": "NPLLIq_fullNotice",
|
|
251
|
+
"rowDragging": "NPLLIq_rowDragging",
|
|
252
|
+
"dialogBody": "NPLLIq_dialogBody",
|
|
253
|
+
"logDialog": "NPLLIq_logDialog",
|
|
254
|
+
"rowDropTarget": "NPLLIq_rowDropTarget",
|
|
255
|
+
"checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
|
|
256
|
+
"dialogTabs": "NPLLIq_dialogTabs",
|
|
257
|
+
"resetSelect": "NPLLIq_resetSelect",
|
|
258
|
+
"logUsedCol": "NPLLIq_logUsedCol",
|
|
215
259
|
"fillWarn": "NPLLIq_fillWarn",
|
|
260
|
+
"selectBtn": "NPLLIq_selectBtn",
|
|
261
|
+
"versionNew": "NPLLIq_versionNew",
|
|
262
|
+
"dialogTab": "NPLLIq_dialogTab",
|
|
263
|
+
"dialogTitle": "NPLLIq_dialogTitle",
|
|
264
|
+
"dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
|
|
265
|
+
"logHeader": "NPLLIq_logHeader",
|
|
266
|
+
"rowDrag": "NPLLIq_rowDrag",
|
|
267
|
+
"monitorHint": "NPLLIq_monitorHint",
|
|
268
|
+
"body": "NPLLIq_body",
|
|
269
|
+
"rowName": "NPLLIq_rowName",
|
|
216
270
|
"noticeError": "NPLLIq_noticeError",
|
|
217
271
|
"upgradeCommandRow": "NPLLIq_upgradeCommandRow",
|
|
218
|
-
"logDialog": "NPLLIq_logDialog",
|
|
219
|
-
"dialogLabel": "NPLLIq_dialogLabel",
|
|
220
|
-
"settingsBtn": "NPLLIq_settingsBtn",
|
|
221
272
|
"dialogHeader": "NPLLIq_dialogHeader",
|
|
222
|
-
"
|
|
223
|
-
"
|
|
224
|
-
"upgradeBanner": "NPLLIq_upgradeBanner",
|
|
225
|
-
"logScroll": "NPLLIq_logScroll",
|
|
226
|
-
"logDayCol": "NPLLIq_logDayCol",
|
|
227
|
-
"logPager": "NPLLIq_logPager",
|
|
228
|
-
"upgradeCommands": "NPLLIq_upgradeCommands",
|
|
229
|
-
"fillOver": "NPLLIq_fillOver",
|
|
273
|
+
"logClearBtn": "NPLLIq_logClearBtn",
|
|
274
|
+
"logPagerInfo": "NPLLIq_logPagerInfo",
|
|
230
275
|
"checkUpdatesRow": "NPLLIq_checkUpdatesRow",
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
"
|
|
234
|
-
"
|
|
235
|
-
"version": "NPLLIq_version",
|
|
276
|
+
"dialogLabel": "NPLLIq_dialogLabel",
|
|
277
|
+
"header": "NPLLIq_header",
|
|
278
|
+
"logPager": "NPLLIq_logPager",
|
|
279
|
+
"copyBtn": "NPLLIq_copyBtn",
|
|
236
280
|
"input": "NPLLIq_input",
|
|
237
|
-
"
|
|
238
|
-
"
|
|
281
|
+
"logClearDialog": "NPLLIq_logClearDialog",
|
|
282
|
+
"logClearDate": "NPLLIq_logClearDate",
|
|
283
|
+
"upgradeClose": "NPLLIq_upgradeClose",
|
|
284
|
+
"dialogBtn": "NPLLIq_dialogBtn",
|
|
239
285
|
"logPageSizeSelect": "NPLLIq_logPageSizeSelect",
|
|
240
|
-
"
|
|
241
|
-
"settingsBtnActive": "NPLLIq_settingsBtnActive",
|
|
242
|
-
"versionNew": "NPLLIq_versionNew",
|
|
243
|
-
"dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
|
|
244
|
-
"dialogTabActive": "NPLLIq_dialogTabActive",
|
|
245
|
-
"copyBtn": "NPLLIq_copyBtn",
|
|
246
|
-
"headerActions": "NPLLIq_headerActions",
|
|
247
|
-
"logSearch": "NPLLIq_logSearch",
|
|
248
|
-
"checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
|
|
249
|
-
"dialogTab": "NPLLIq_dialogTab",
|
|
286
|
+
"logScroll": "NPLLIq_logScroll",
|
|
250
287
|
"upgradeHint": "NPLLIq_upgradeHint",
|
|
251
|
-
"
|
|
252
|
-
"
|
|
288
|
+
"logModelCol": "NPLLIq_logModelCol",
|
|
289
|
+
"gearBtn": "NPLLIq_gearBtn",
|
|
290
|
+
"monitorName": "NPLLIq_monitorName",
|
|
291
|
+
"dialogOverlay": "NPLLIq_dialogOverlay",
|
|
292
|
+
"currentBadge": "NPLLIq_currentBadge",
|
|
293
|
+
"upgradeBannerText": "NPLLIq_upgradeBannerText",
|
|
294
|
+
"switch": "NPLLIq_switch",
|
|
295
|
+
"logToolbar": "NPLLIq_logToolbar",
|
|
296
|
+
"logSearch": "NPLLIq_logSearch",
|
|
297
|
+
"logDayCol": "NPLLIq_logDayCol",
|
|
298
|
+
"dialogTabActive": "NPLLIq_dialogTabActive",
|
|
299
|
+
"row": "NPLLIq_row",
|
|
300
|
+
"upgradeBanner": "NPLLIq_upgradeBanner",
|
|
301
|
+
"headerText": "NPLLIq_headerText",
|
|
253
302
|
"title": "NPLLIq_title",
|
|
254
|
-
"
|
|
255
|
-
"
|
|
256
|
-
"
|
|
257
|
-
"
|
|
258
|
-
"
|
|
303
|
+
"dialogSection": "NPLLIq_dialogSection",
|
|
304
|
+
"logPagerControls": "NPLLIq_logPagerControls",
|
|
305
|
+
"settingsBtnActive": "NPLLIq_settingsBtnActive",
|
|
306
|
+
"version": "NPLLIq_version",
|
|
307
|
+
"tab": "NPLLIq_tab",
|
|
308
|
+
"dialogHint": "NPLLIq_dialogHint",
|
|
259
309
|
"dialogClose": "NPLLIq_dialogClose",
|
|
260
|
-
"
|
|
261
|
-
"
|
|
262
|
-
"
|
|
263
|
-
"
|
|
264
|
-
"
|
|
265
|
-
"
|
|
266
|
-
"
|
|
267
|
-
"logUsedCol": "NPLLIq_logUsedCol",
|
|
268
|
-
"monitorName": "NPLLIq_monitorName",
|
|
310
|
+
"panel": "NPLLIq_panel",
|
|
311
|
+
"tabIcon": "NPLLIq_tabIcon",
|
|
312
|
+
"logPagerPages": "NPLLIq_logPagerPages",
|
|
313
|
+
"panelDim": "NPLLIq_panelDim",
|
|
314
|
+
"copyBtnDone": "NPLLIq_copyBtnDone",
|
|
315
|
+
"monitorList": "NPLLIq_monitorList",
|
|
316
|
+
"logPagerBtn": "NPLLIq_logPagerBtn",
|
|
269
317
|
"monitorRow": "NPLLIq_monitorRow",
|
|
270
|
-
"dialogBtn": "NPLLIq_dialogBtn",
|
|
271
318
|
"dialogActions": "NPLLIq_dialogActions",
|
|
272
|
-
"
|
|
273
|
-
"selectBtn": "NPLLIq_selectBtn",
|
|
274
|
-
"logPagerBtn": "NPLLIq_logPagerBtn",
|
|
319
|
+
"notice": "NPLLIq_notice",
|
|
275
320
|
"upgradeCommand": "NPLLIq_upgradeCommand",
|
|
276
|
-
"row": "NPLLIq_row",
|
|
277
|
-
"currentBadge": "NPLLIq_currentBadge",
|
|
278
|
-
"monitorList": "NPLLIq_monitorList",
|
|
279
|
-
"tabLabel": "NPLLIq_tabLabel",
|
|
280
|
-
"fillIdle": "NPLLIq_fillIdle",
|
|
281
321
|
"checkErrorHint": "NPLLIq_checkErrorHint",
|
|
282
|
-
"dialogTitle": "NPLLIq_dialogTitle",
|
|
283
|
-
"monitorHint": "NPLLIq_monitorHint",
|
|
284
|
-
"tabIcon": "NPLLIq_tabIcon",
|
|
285
|
-
"panel": "NPLLIq_panel",
|
|
286
|
-
"resetSelect": "NPLLIq_resetSelect",
|
|
287
322
|
"checkBtn": "NPLLIq_checkBtn",
|
|
288
|
-
"
|
|
289
|
-
"
|
|
290
|
-
"rowMeta": "NPLLIq_rowMeta",
|
|
291
|
-
"logToolbar": "NPLLIq_logToolbar",
|
|
292
|
-
"fullNotice": "NPLLIq_fullNotice",
|
|
293
|
-
"dialogSection": "NPLLIq_dialogSection"
|
|
323
|
+
"upgradeCommands": "NPLLIq_upgradeCommands",
|
|
324
|
+
"save": "NPLLIq_save"
|
|
294
325
|
};
|
|
295
326
|
//#endregion
|
|
296
327
|
//#region lib/types/client/TokenQuotaPanel.js
|
|
@@ -377,13 +408,15 @@ window.__ModuleLoader__.load({
|
|
|
377
408
|
* @param props - composed slot props.
|
|
378
409
|
* @returns the panel element tree.
|
|
379
410
|
*/
|
|
380
|
-
function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
|
|
411
|
+
function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
|
|
381
412
|
const [collapsed, setCollapsed] = (0, react.useState)(false);
|
|
382
413
|
const [drafts, setDrafts] = (0, react.useState)({});
|
|
383
414
|
const [editingKey, setEditingKey] = (0, react.useState)(null);
|
|
384
415
|
const [hovered, setHovered] = (0, react.useState)(false);
|
|
385
416
|
const [inputActive, setInputActive] = (0, react.useState)(false);
|
|
386
417
|
const [settingsTab, setSettingsTab] = (0, react.useState)("quota");
|
|
418
|
+
const [dragKey, setDragKey] = (0, react.useState)(null);
|
|
419
|
+
const [dropKey, setDropKey] = (0, react.useState)(null);
|
|
387
420
|
const [copiedCmd, setCopiedCmd] = (0, react.useState)(null);
|
|
388
421
|
const copyTimerRef = (0, react.useRef)(null);
|
|
389
422
|
const [upgradeFlash, setUpgradeFlash] = (0, react.useState)(false);
|
|
@@ -409,6 +442,7 @@ window.__ModuleLoader__.load({
|
|
|
409
442
|
const onFull = useStore((s) => s.onFull);
|
|
410
443
|
const checkUpdates = useStore((s) => s.checkUpdates);
|
|
411
444
|
const dimWhenIdle = useStore((s) => s.dimWhenIdle);
|
|
445
|
+
const order = useStore((s) => s.order);
|
|
412
446
|
const musicEnabled = useStore((s) => s.musicEnabled);
|
|
413
447
|
const musicVolume = useStore((s) => s.musicVolume);
|
|
414
448
|
const musicStyle = useStore((s) => s.musicStyle);
|
|
@@ -464,15 +498,27 @@ window.__ModuleLoader__.load({
|
|
|
464
498
|
if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
|
|
465
499
|
};
|
|
466
500
|
}, []);
|
|
467
|
-
const rows = (0, react.useMemo)(() => mergeModelRows(groups, snapshot, current), [
|
|
501
|
+
const rows = (0, react.useMemo)(() => mergeModelRows(groups, snapshot, current, order), [
|
|
468
502
|
groups,
|
|
469
503
|
snapshot,
|
|
470
|
-
current
|
|
504
|
+
current,
|
|
505
|
+
order
|
|
471
506
|
]);
|
|
472
|
-
const allModels = (0, react.useMemo)(() =>
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
507
|
+
const allModels = (0, react.useMemo)(() => {
|
|
508
|
+
const list = groups.flatMap((group) => group.models.map((model) => ({
|
|
509
|
+
key: `${group.id}/${model.id}`,
|
|
510
|
+
name: model.name
|
|
511
|
+
})));
|
|
512
|
+
const rank = new Map(order.map((key, index) => [key, index]));
|
|
513
|
+
return list.sort((left, right) => {
|
|
514
|
+
const leftRank = rank.get(left.key);
|
|
515
|
+
const rightRank = rank.get(right.key);
|
|
516
|
+
if (leftRank !== void 0 && rightRank !== void 0) return leftRank - rightRank;
|
|
517
|
+
if (leftRank !== void 0) return -1;
|
|
518
|
+
if (rightRank !== void 0) return 1;
|
|
519
|
+
return left.key.localeCompare(right.key);
|
|
520
|
+
});
|
|
521
|
+
}, [groups, order]);
|
|
476
522
|
const isMonitoredKey = (key) => monitored === null || monitored.includes(key);
|
|
477
523
|
const filteredLogEntries = (0, react.useMemo)(() => {
|
|
478
524
|
if (log === null) return [];
|
|
@@ -597,13 +643,13 @@ window.__ModuleLoader__.load({
|
|
|
597
643
|
title: t("upgradeAvailableHint"),
|
|
598
644
|
children: [
|
|
599
645
|
"v",
|
|
600
|
-
"0.1.
|
|
646
|
+
"0.1.32",
|
|
601
647
|
" → v",
|
|
602
648
|
upgrade.latestVersion
|
|
603
649
|
]
|
|
604
650
|
}) : (0, react_jsx_runtime.jsxs)("span", {
|
|
605
651
|
className: TokenQuotaPanel_module_css_default.version,
|
|
606
|
-
children: ["v", "0.1.
|
|
652
|
+
children: ["v", "0.1.32"]
|
|
607
653
|
})]
|
|
608
654
|
}), (0, react_jsx_runtime.jsx)("div", {
|
|
609
655
|
className: TokenQuotaPanel_module_css_default.subtitle,
|
|
@@ -716,40 +762,69 @@ window.__ModuleLoader__.load({
|
|
|
716
762
|
const barClass = state === "over" ? TokenQuotaPanel_module_css_default.fillOver : state === "warn" ? TokenQuotaPanel_module_css_default.fillWarn : TokenQuotaPanel_module_css_default.fillIdle;
|
|
717
763
|
const editing = editingKey === row.key;
|
|
718
764
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
719
|
-
className: TokenQuotaPanel_module_css_default.row
|
|
765
|
+
className: `${TokenQuotaPanel_module_css_default.row}${dragKey === row.key ? ` ${TokenQuotaPanel_module_css_default.rowDragging}` : ""}${dropKey === row.key && dragKey !== row.key ? ` ${TokenQuotaPanel_module_css_default.rowDropTarget}` : ""}`,
|
|
766
|
+
onDragOver: (event) => {
|
|
767
|
+
if (dragKey === null || dragKey === row.key) return;
|
|
768
|
+
event.preventDefault();
|
|
769
|
+
setDropKey(row.key);
|
|
770
|
+
},
|
|
771
|
+
onDrop: (event) => {
|
|
772
|
+
event.preventDefault();
|
|
773
|
+
if (dragKey !== null && dragKey !== row.key) setModelOrder(reorderKeys(rows.map((r) => r.key), dragKey, row.key));
|
|
774
|
+
setDragKey(null);
|
|
775
|
+
setDropKey(null);
|
|
776
|
+
},
|
|
777
|
+
onDragEnd: () => {
|
|
778
|
+
setDragKey(null);
|
|
779
|
+
setDropKey(null);
|
|
780
|
+
},
|
|
720
781
|
children: [
|
|
721
782
|
(0, react_jsx_runtime.jsxs)("div", {
|
|
722
783
|
className: TokenQuotaPanel_module_css_default.rowHeader,
|
|
723
|
-
children: [
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
784
|
+
children: [
|
|
785
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
786
|
+
className: TokenQuotaPanel_module_css_default.rowDrag,
|
|
787
|
+
draggable: true,
|
|
788
|
+
title: t("reorderHint"),
|
|
789
|
+
onDragStart: (event) => {
|
|
790
|
+
setDragKey(row.key);
|
|
791
|
+
event.dataTransfer.effectAllowed = "move";
|
|
792
|
+
event.dataTransfer.setData("text/plain", row.key);
|
|
793
|
+
},
|
|
794
|
+
children: "⠿"
|
|
795
|
+
}),
|
|
796
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
797
|
+
className: TokenQuotaPanel_module_css_default.rowName,
|
|
798
|
+
title: row.key,
|
|
799
|
+
children: [
|
|
800
|
+
row.name,
|
|
801
|
+
row.current && (0, react_jsx_runtime.jsx)("span", {
|
|
802
|
+
className: TokenQuotaPanel_module_css_default.currentBadge,
|
|
803
|
+
children: t("current")
|
|
804
|
+
}),
|
|
805
|
+
sessionId !== void 0 && !row.current && (0, react_jsx_runtime.jsx)("button", {
|
|
806
|
+
type: "button",
|
|
807
|
+
className: TokenQuotaPanel_module_css_default.selectBtn,
|
|
808
|
+
onClick: () => {
|
|
809
|
+
selectModel(sessionId, row.provider, row.model);
|
|
810
|
+
},
|
|
811
|
+
children: t("select")
|
|
812
|
+
})
|
|
813
|
+
]
|
|
814
|
+
}),
|
|
815
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
816
|
+
className: TokenQuotaPanel_module_css_default.rowMeta,
|
|
817
|
+
children: [row.limit > 0 ? `${formatTokens(row.used)} / ${formatTokens(row.limit)}` : `${formatTokens(row.used)} · ${t("unlimited")}`, (0, react_jsx_runtime.jsx)("button", {
|
|
733
818
|
type: "button",
|
|
734
|
-
className: TokenQuotaPanel_module_css_default.
|
|
819
|
+
className: TokenQuotaPanel_module_css_default.gearBtn,
|
|
820
|
+
title: t("setLimitHint"),
|
|
735
821
|
onClick: () => {
|
|
736
|
-
|
|
822
|
+
setEditingKey(editing ? null : row.key);
|
|
737
823
|
},
|
|
738
|
-
children:
|
|
739
|
-
})
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
className: TokenQuotaPanel_module_css_default.rowMeta,
|
|
743
|
-
children: [row.limit > 0 ? `${formatTokens(row.used)} / ${formatTokens(row.limit)}` : `${formatTokens(row.used)} · ${t("unlimited")}`, (0, react_jsx_runtime.jsx)("button", {
|
|
744
|
-
type: "button",
|
|
745
|
-
className: TokenQuotaPanel_module_css_default.gearBtn,
|
|
746
|
-
title: t("setLimitHint"),
|
|
747
|
-
onClick: () => {
|
|
748
|
-
setEditingKey(editing ? null : row.key);
|
|
749
|
-
},
|
|
750
|
-
children: "⚙"
|
|
751
|
-
})]
|
|
752
|
-
})]
|
|
824
|
+
children: "⚙"
|
|
825
|
+
})]
|
|
826
|
+
})
|
|
827
|
+
]
|
|
753
828
|
}),
|
|
754
829
|
(0, react_jsx_runtime.jsx)("div", {
|
|
755
830
|
className: TokenQuotaPanel_module_css_default.bar,
|
|
@@ -1918,6 +1993,7 @@ window.__ModuleLoader__.load({
|
|
|
1918
1993
|
settingsTabQuota: "限额设置",
|
|
1919
1994
|
settingsTabMusic: "音乐设置",
|
|
1920
1995
|
settingsTabOther: "其它",
|
|
1996
|
+
reorderHint: "拖动排序",
|
|
1921
1997
|
monitorLabel: "监控模型",
|
|
1922
1998
|
monitorHint: "未勾选的模型不显示、不计入用量、不受限额限制",
|
|
1923
1999
|
monitorAll: "全部",
|
|
@@ -1999,6 +2075,7 @@ window.__ModuleLoader__.load({
|
|
|
1999
2075
|
settingsTabQuota: "Quota",
|
|
2000
2076
|
settingsTabMusic: "Music",
|
|
2001
2077
|
settingsTabOther: "Other",
|
|
2078
|
+
reorderHint: "Drag to reorder",
|
|
2002
2079
|
monitorLabel: "Monitored models",
|
|
2003
2080
|
monitorHint: "Unchecked models are hidden, not metered, and never capped",
|
|
2004
2081
|
monitorAll: "All",
|
|
@@ -2250,6 +2327,7 @@ window.__ModuleLoader__.load({
|
|
|
2250
2327
|
bound?.setSettings(lastMonitored, lastOnFull);
|
|
2251
2328
|
bound?.setCheckUpdates(doc?.checkUpdates ?? true);
|
|
2252
2329
|
bound?.setDimWhenIdle(doc?.dimWhenIdle ?? false);
|
|
2330
|
+
bound?.setOrder(Array.isArray(doc?.order) ? doc.order : []);
|
|
2253
2331
|
bound?.setReset(lastReset);
|
|
2254
2332
|
const musicSettings = musicDefaults(doc?.music);
|
|
2255
2333
|
lastOnlyCurrentSession = musicSettings.onlyCurrentSession;
|
|
@@ -2330,6 +2408,11 @@ window.__ModuleLoader__.load({
|
|
|
2330
2408
|
bound?.setDimWhenIdle(enabled);
|
|
2331
2409
|
scope.set("dimWhenIdle", enabled);
|
|
2332
2410
|
};
|
|
2411
|
+
/** Persist the drag-to-reorder display order of model rows. */
|
|
2412
|
+
const setModelOrder = (order) => {
|
|
2413
|
+
bound?.setOrder(order);
|
|
2414
|
+
scope.set("order", order);
|
|
2415
|
+
};
|
|
2333
2416
|
const setMusicEnabled = (enabled) => {
|
|
2334
2417
|
const doc = scope.getSnapshot().value;
|
|
2335
2418
|
const current = musicDefaults(doc?.music);
|
|
@@ -2442,7 +2525,8 @@ window.__ModuleLoader__.load({
|
|
|
2442
2525
|
setMusicEnabled,
|
|
2443
2526
|
setMusicVolume,
|
|
2444
2527
|
setMusicStyle,
|
|
2445
|
-
setMusicOnlyCurrentSession
|
|
2528
|
+
setMusicOnlyCurrentSession,
|
|
2529
|
+
setModelOrder
|
|
2446
2530
|
};
|
|
2447
2531
|
};
|
|
2448
2532
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
package/lib/index.js
CHANGED
|
@@ -214,6 +214,7 @@ const TOKEN_QUOTA_SETTINGS_SCHEMA = z.object({
|
|
|
214
214
|
]).default("stop"),
|
|
215
215
|
checkUpdates: z.boolean().default(true),
|
|
216
216
|
dimWhenIdle: z.boolean().default(false),
|
|
217
|
+
order: z.array(z.string()).default([]),
|
|
217
218
|
reset: z.any().default(null),
|
|
218
219
|
music: z.object({
|
|
219
220
|
enabled: z.boolean().default(TOKEN_QUOTA_DEFAULT_MUSIC.enabled),
|
|
@@ -281,7 +282,8 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
281
282
|
onFull: "stop",
|
|
282
283
|
checkUpdates: true,
|
|
283
284
|
dimWhenIdle: false,
|
|
284
|
-
music: { ...TOKEN_QUOTA_DEFAULT_MUSIC }
|
|
285
|
+
music: { ...TOKEN_QUOTA_DEFAULT_MUSIC },
|
|
286
|
+
order: []
|
|
285
287
|
});
|
|
286
288
|
/** Whether update checks are enabled (mirrors the settings document). */
|
|
287
289
|
checkUpdates = true;
|
|
@@ -334,6 +336,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
334
336
|
onFull: doc.onFull === "switchPriority" ? "switchAll" : doc.onFull ?? "stop",
|
|
335
337
|
checkUpdates: doc.checkUpdates ?? true,
|
|
336
338
|
dimWhenIdle: doc.dimWhenIdle ?? false,
|
|
339
|
+
order: Array.isArray(doc.order) ? doc.order : [],
|
|
337
340
|
reset: doc.reset ?? void 0,
|
|
338
341
|
music: {
|
|
339
342
|
enabled: doc.music?.enabled ?? TOKEN_QUOTA_DEFAULT_MUSIC.enabled,
|
|
@@ -515,7 +518,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
|
|
|
515
518
|
return this.upgradeCheck;
|
|
516
519
|
}
|
|
517
520
|
async doRefreshUpgrade() {
|
|
518
|
-
const current = "0.1.
|
|
521
|
+
const current = "0.1.32";
|
|
519
522
|
let latest;
|
|
520
523
|
try {
|
|
521
524
|
const response = await fetch(REGISTRY_LATEST_URL, {
|
|
@@ -20,6 +20,8 @@ export interface TokenQuotaPanelInjected {
|
|
|
20
20
|
setCheckUpdates: (enabled: boolean) => void;
|
|
21
21
|
/** Persist whether the panel dims while the pointer is away / typing. */
|
|
22
22
|
setDimWhenIdle: (enabled: boolean) => void;
|
|
23
|
+
/** Persist the drag-to-reorder display order of model rows. */
|
|
24
|
+
setModelOrder: (order: string[]) => void;
|
|
23
25
|
/** Toggle the live music output (requires a user gesture to start audio). */
|
|
24
26
|
setMusicEnabled: (enabled: boolean) => void;
|
|
25
27
|
/** Change the live-music master volume 0..1. */
|
|
@@ -40,5 +42,5 @@ export type TokenQuotaPanelComponentProps = PropsRuntime<'shell.overlay'> & Prop
|
|
|
40
42
|
* @param props - composed slot props.
|
|
41
43
|
* @returns the panel element tree.
|
|
42
44
|
*/
|
|
43
|
-
export declare function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions, }: TokenQuotaPanelComponentProps): import("react").JSX.Element;
|
|
45
|
+
export declare function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions, }: TokenQuotaPanelComponentProps): import("react").JSX.Element;
|
|
44
46
|
//# sourceMappingURL=TokenQuotaPanel.d.ts.map
|
|
@@ -10,7 +10,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
10
10
|
* callbacks.
|
|
11
11
|
*/
|
|
12
12
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
-
import { mergeModelRows } from "./store.js";
|
|
13
|
+
import { mergeModelRows, reorderKeys } from "./store.js";
|
|
14
14
|
import css from './TokenQuotaPanel.module.css';
|
|
15
15
|
/** Compact a token count for display. */
|
|
16
16
|
function formatTokens(n) {
|
|
@@ -86,7 +86,7 @@ function loadPanelPos() {
|
|
|
86
86
|
* @param props - composed slot props.
|
|
87
87
|
* @returns the panel element tree.
|
|
88
88
|
*/
|
|
89
|
-
export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions, }) {
|
|
89
|
+
export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions, }) {
|
|
90
90
|
const [collapsed, setCollapsed] = useState(false);
|
|
91
91
|
const [drafts, setDrafts] = useState({});
|
|
92
92
|
const [editingKey, setEditingKey] = useState(null);
|
|
@@ -97,6 +97,10 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
|
|
|
97
97
|
const [inputActive, setInputActive] = useState(false);
|
|
98
98
|
// Active settings-dialog tab: quota limits vs. live-music vs. misc.
|
|
99
99
|
const [settingsTab, setSettingsTab] = useState('quota');
|
|
100
|
+
// Drag-to-reorder state for the model rows: the key being dragged and
|
|
101
|
+
// the key currently hovered as the drop target.
|
|
102
|
+
const [dragKey, setDragKey] = useState(null);
|
|
103
|
+
const [dropKey, setDropKey] = useState(null);
|
|
100
104
|
// Copy-button feedback: which command was just copied (label flips to
|
|
101
105
|
// 「已复制」for a moment so the click is perceivable).
|
|
102
106
|
const [copiedCmd, setCopiedCmd] = useState(null);
|
|
@@ -131,6 +135,7 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
|
|
|
131
135
|
const onFull = useStore(s => s.onFull);
|
|
132
136
|
const checkUpdates = useStore(s => s.checkUpdates);
|
|
133
137
|
const dimWhenIdle = useStore(s => s.dimWhenIdle);
|
|
138
|
+
const order = useStore(s => s.order);
|
|
134
139
|
const musicEnabled = useStore(s => s.musicEnabled);
|
|
135
140
|
const musicVolume = useStore(s => s.musicVolume);
|
|
136
141
|
const musicStyle = useStore(s => s.musicStyle);
|
|
@@ -198,12 +203,27 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
|
|
|
198
203
|
clearTimeout(copyTimerRef.current);
|
|
199
204
|
};
|
|
200
205
|
}, []);
|
|
201
|
-
const rows = useMemo(() => mergeModelRows(groups, snapshot, current), [groups, snapshot, current]);
|
|
202
|
-
// All directory models, flattened for the monitoring picker
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
206
|
+
const rows = useMemo(() => mergeModelRows(groups, snapshot, current, order), [groups, snapshot, current, order]);
|
|
207
|
+
// All directory models, flattened for the monitoring picker — same drag
|
|
208
|
+
// order as the panel rows so both lists read identically.
|
|
209
|
+
const allModels = useMemo(() => {
|
|
210
|
+
const list = groups.flatMap(group => group.models.map((model) => ({
|
|
211
|
+
key: `${group.id}/${model.id}`,
|
|
212
|
+
name: model.name,
|
|
213
|
+
})));
|
|
214
|
+
const rank = new Map(order.map((key, index) => [key, index]));
|
|
215
|
+
return list.sort((left, right) => {
|
|
216
|
+
const leftRank = rank.get(left.key);
|
|
217
|
+
const rightRank = rank.get(right.key);
|
|
218
|
+
if (leftRank !== undefined && rightRank !== undefined)
|
|
219
|
+
return leftRank - rightRank;
|
|
220
|
+
if (leftRank !== undefined)
|
|
221
|
+
return -1;
|
|
222
|
+
if (rightRank !== undefined)
|
|
223
|
+
return 1;
|
|
224
|
+
return left.key.localeCompare(right.key);
|
|
225
|
+
});
|
|
226
|
+
}, [groups, order]);
|
|
207
227
|
const isMonitoredKey = (key) => monitored === null || monitored.includes(key);
|
|
208
228
|
// Log dialog: filter by search, then paginate.
|
|
209
229
|
const filteredLogEntries = useMemo(() => {
|
|
@@ -309,7 +329,24 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
|
|
|
309
329
|
? css.fillWarn
|
|
310
330
|
: css.fillIdle;
|
|
311
331
|
const editing = editingKey === row.key;
|
|
312
|
-
return (_jsxs("div", { className: css.row
|
|
332
|
+
return (_jsxs("div", { className: `${css.row}${dragKey === row.key ? ` ${css.rowDragging}` : ''}${dropKey === row.key && dragKey !== row.key ? ` ${css.rowDropTarget}` : ''}`, onDragOver: (event) => {
|
|
333
|
+
if (dragKey === null || dragKey === row.key)
|
|
334
|
+
return;
|
|
335
|
+
event.preventDefault();
|
|
336
|
+
setDropKey(row.key);
|
|
337
|
+
}, onDrop: (event) => {
|
|
338
|
+
event.preventDefault();
|
|
339
|
+
if (dragKey !== null && dragKey !== row.key) {
|
|
340
|
+
setModelOrder(reorderKeys(rows.map(r => r.key), dragKey, row.key));
|
|
341
|
+
}
|
|
342
|
+
setDragKey(null);
|
|
343
|
+
setDropKey(null);
|
|
344
|
+
}, onDragEnd: () => { setDragKey(null); setDropKey(null); }, children: [_jsxs("div", { className: css.rowHeader, children: [_jsx("span", { className: css.rowDrag, draggable: true, title: t('reorderHint'), onDragStart: (event) => {
|
|
345
|
+
setDragKey(row.key);
|
|
346
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
347
|
+
// Firefox only starts a drag when some data is set.
|
|
348
|
+
event.dataTransfer.setData('text/plain', row.key);
|
|
349
|
+
}, children: "\u283F" }), _jsxs("span", { className: css.rowName, title: row.key, children: [row.name, row.current && _jsx("span", { className: css.currentBadge, children: t('current') }), sessionId !== undefined && !row.current && (_jsx("button", { type: "button", className: css.selectBtn, onClick: () => { selectModel(sessionId, row.provider, row.model); }, children: t('select') }))] }), _jsxs("span", { className: css.rowMeta, children: [row.limit > 0
|
|
313
350
|
? `${formatTokens(row.used)} / ${formatTokens(row.limit)}`
|
|
314
351
|
: `${formatTokens(row.used)} · ${t('unlimited')}`, _jsx("button", { type: "button", className: css.gearBtn, title: t('setLimitHint'), onClick: () => { setEditingKey(editing ? null : row.key); }, children: "\u2699" })] })] }), _jsx("div", { className: css.bar, children: _jsx("div", { className: barClass, style: { width: `${pct}%` } }) }), editing && (_jsxs("div", { className: css.controls, children: [_jsx("input", { className: css.input, type: "number", min: 0, step: 10000, placeholder: t('limitPlaceholder'), value: drafts[row.key] ?? '', onChange: (event) => { setDrafts(prev => ({ ...prev, [row.key]: event.target.value })); }, onKeyDown: (event) => { if (event.key === 'Enter')
|
|
315
352
|
commitLimit(row); } }), _jsx("button", { type: "button", className: css.save, onClick: () => { commitLimit(row); }, children: t('save') })] }))] }, row.key));
|
|
@@ -250,6 +250,7 @@ export function apply(ctx) {
|
|
|
250
250
|
bound?.setSettings(lastMonitored, lastOnFull);
|
|
251
251
|
bound?.setCheckUpdates(doc?.checkUpdates ?? true);
|
|
252
252
|
bound?.setDimWhenIdle(doc?.dimWhenIdle ?? false);
|
|
253
|
+
bound?.setOrder(Array.isArray(doc?.order) ? doc.order : []);
|
|
253
254
|
bound?.setReset(lastReset);
|
|
254
255
|
const musicSettings = musicDefaults(doc?.music);
|
|
255
256
|
lastOnlyCurrentSession = musicSettings.onlyCurrentSession;
|
|
@@ -332,6 +333,11 @@ export function apply(ctx) {
|
|
|
332
333
|
bound?.setDimWhenIdle(enabled);
|
|
333
334
|
void scope.set('dimWhenIdle', enabled);
|
|
334
335
|
};
|
|
336
|
+
/** Persist the drag-to-reorder display order of model rows. */
|
|
337
|
+
const setModelOrder = (order) => {
|
|
338
|
+
bound?.setOrder(order);
|
|
339
|
+
void scope.set('order', order);
|
|
340
|
+
};
|
|
335
341
|
const setMusicEnabled = (enabled) => {
|
|
336
342
|
const doc = scope.getSnapshot().value;
|
|
337
343
|
const current = musicDefaults(doc?.music);
|
|
@@ -449,6 +455,7 @@ export function apply(ctx) {
|
|
|
449
455
|
load, setLimit, selectModel, setMonitored, setOnFull, setReset,
|
|
450
456
|
setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle,
|
|
451
457
|
setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession,
|
|
458
|
+
setModelOrder,
|
|
452
459
|
};
|
|
453
460
|
};
|
|
454
461
|
ctx.slots.inject('shell.overlay', () => ctx.slots.register({
|
|
@@ -28,6 +28,7 @@ export declare const zh: {
|
|
|
28
28
|
settingsTabQuota: string;
|
|
29
29
|
settingsTabMusic: string;
|
|
30
30
|
settingsTabOther: string;
|
|
31
|
+
reorderHint: string;
|
|
31
32
|
monitorLabel: string;
|
|
32
33
|
monitorHint: string;
|
|
33
34
|
monitorAll: string;
|
|
@@ -111,6 +112,7 @@ export declare const en: {
|
|
|
111
112
|
settingsTabQuota: string;
|
|
112
113
|
settingsTabMusic: string;
|
|
113
114
|
settingsTabOther: string;
|
|
115
|
+
reorderHint: string;
|
|
114
116
|
monitorLabel: string;
|
|
115
117
|
monitorHint: string;
|
|
116
118
|
monitorAll: string;
|
|
@@ -28,6 +28,7 @@ export const zh = {
|
|
|
28
28
|
settingsTabQuota: '限额设置',
|
|
29
29
|
settingsTabMusic: '音乐设置',
|
|
30
30
|
settingsTabOther: '其它',
|
|
31
|
+
reorderHint: '拖动排序',
|
|
31
32
|
monitorLabel: '监控模型',
|
|
32
33
|
monitorHint: '未勾选的模型不显示、不计入用量、不受限额限制',
|
|
33
34
|
monitorAll: '全部',
|
|
@@ -109,6 +110,7 @@ export const en = {
|
|
|
109
110
|
settingsTabQuota: 'Quota',
|
|
110
111
|
settingsTabMusic: 'Music',
|
|
111
112
|
settingsTabOther: 'Other',
|
|
113
|
+
reorderHint: 'Drag to reorder',
|
|
112
114
|
monitorLabel: 'Monitored models',
|
|
113
115
|
monitorHint: 'Unchecked models are hidden, not metered, and never capped',
|
|
114
116
|
monitorAll: 'All',
|
|
@@ -50,6 +50,11 @@ export interface TokenQuotaPanelState {
|
|
|
50
50
|
checkUpdates: boolean;
|
|
51
51
|
/** Whether the panel dims while the pointer is away / while typing. */
|
|
52
52
|
dimWhenIdle: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Preferred display order of model keys, written by dragging panel rows.
|
|
55
|
+
* Keys not listed keep their catalog order after the listed ones.
|
|
56
|
+
*/
|
|
57
|
+
order: string[];
|
|
53
58
|
/** Live music settings (mirrored from the settings document). */
|
|
54
59
|
musicEnabled: boolean;
|
|
55
60
|
musicVolume: number;
|
|
@@ -97,6 +102,8 @@ export type TokenQuotaPanelActions = {
|
|
|
97
102
|
setSettings: (d: TokenQuotaPanelState, monitored: string[] | null, onFull: TokenQuotaFullAction) => void;
|
|
98
103
|
setCheckUpdates: (d: TokenQuotaPanelState, checkUpdates: boolean) => void;
|
|
99
104
|
setDimWhenIdle: (d: TokenQuotaPanelState, dimWhenIdle: boolean) => void;
|
|
105
|
+
/** Replace the drag-to-reorder model display order. */
|
|
106
|
+
setOrder: (d: TokenQuotaPanelState, order: string[]) => void;
|
|
100
107
|
setMusicEnabled: (d: TokenQuotaPanelState, enabled: boolean) => void;
|
|
101
108
|
setMusicVolume: (d: TokenQuotaPanelState, volume: number) => void;
|
|
102
109
|
setMusicStyle: (d: TokenQuotaPanelState, style: TokenQuotaMusicStyle) => void;
|
|
@@ -131,7 +138,14 @@ export declare function createTokenQuotaPanelStore(): EngineStoreHandle<TokenQuo
|
|
|
131
138
|
* @param groups - advisory provider groups of the current session.
|
|
132
139
|
* @param snapshot - latest quota snapshot, or null before the first one.
|
|
133
140
|
* @param current - current model selection reported by the Host.
|
|
134
|
-
* @
|
|
141
|
+
* @param order - user's drag-to-reorder preference (model keys); listed keys
|
|
142
|
+
* come first in that exact order, the rest follow in catalog order.
|
|
143
|
+
* @returns rows in display order.
|
|
144
|
+
*/
|
|
145
|
+
export declare function mergeModelRows(groups: readonly ModelProviderGroup[], snapshot: TokenQuotaSnapshot | null, current: ModelSelection | null, order?: readonly string[]): ModelQuotaRow[];
|
|
146
|
+
/**
|
|
147
|
+
* Move one key to another key's position, returning the full reordered key
|
|
148
|
+
* list (the shape persisted in the settings document's `order`).
|
|
135
149
|
*/
|
|
136
|
-
export declare function
|
|
150
|
+
export declare function reorderKeys(keys: readonly string[], from: string, to: string): string[];
|
|
137
151
|
//# sourceMappingURL=store.d.ts.map
|
|
@@ -28,6 +28,7 @@ export function createTokenQuotaPanelStore() {
|
|
|
28
28
|
onFull: 'stop',
|
|
29
29
|
checkUpdates: true,
|
|
30
30
|
dimWhenIdle: false,
|
|
31
|
+
order: [],
|
|
31
32
|
musicEnabled: false,
|
|
32
33
|
musicVolume: 0.5,
|
|
33
34
|
musicStyle: 'pentatonic',
|
|
@@ -57,6 +58,7 @@ export function createTokenQuotaPanelStore() {
|
|
|
57
58
|
setSettings: (d, monitored, onFull) => { d.monitored = monitored; d.onFull = onFull; },
|
|
58
59
|
setCheckUpdates: (d, checkUpdates) => { d.checkUpdates = checkUpdates; },
|
|
59
60
|
setDimWhenIdle: (d, dimWhenIdle) => { d.dimWhenIdle = dimWhenIdle; },
|
|
61
|
+
setOrder: (d, order) => { d.order = order; },
|
|
60
62
|
setMusicEnabled: (d, enabled) => { d.musicEnabled = enabled; },
|
|
61
63
|
setMusicVolume: (d, volume) => { d.musicVolume = volume; },
|
|
62
64
|
setMusicStyle: (d, style) => { d.musicStyle = style; },
|
|
@@ -104,9 +106,11 @@ export function createTokenQuotaPanelStore() {
|
|
|
104
106
|
* @param groups - advisory provider groups of the current session.
|
|
105
107
|
* @param snapshot - latest quota snapshot, or null before the first one.
|
|
106
108
|
* @param current - current model selection reported by the Host.
|
|
107
|
-
* @
|
|
109
|
+
* @param order - user's drag-to-reorder preference (model keys); listed keys
|
|
110
|
+
* come first in that exact order, the rest follow in catalog order.
|
|
111
|
+
* @returns rows in display order.
|
|
108
112
|
*/
|
|
109
|
-
export function mergeModelRows(groups, snapshot, current) {
|
|
113
|
+
export function mergeModelRows(groups, snapshot, current, order = []) {
|
|
110
114
|
const entryByKey = new Map((snapshot?.entries ?? []).map(entry => [entry.key, entry]));
|
|
111
115
|
const rows = new Map();
|
|
112
116
|
for (const group of groups) {
|
|
@@ -137,6 +141,35 @@ export function mergeModelRows(groups, snapshot, current) {
|
|
|
137
141
|
current: current !== null && current.provider === entry.provider && current.model === entry.model,
|
|
138
142
|
});
|
|
139
143
|
}
|
|
140
|
-
|
|
144
|
+
// Drag preference first (in its own order), everything else after it,
|
|
145
|
+
// alphabetically — so a newly discovered model still lands somewhere stable.
|
|
146
|
+
const rank = new Map(order.map((key, index) => [key, index]));
|
|
147
|
+
return [...rows.values()].sort((left, right) => {
|
|
148
|
+
const leftRank = rank.get(left.key);
|
|
149
|
+
const rightRank = rank.get(right.key);
|
|
150
|
+
if (leftRank !== undefined && rightRank !== undefined)
|
|
151
|
+
return leftRank - rightRank;
|
|
152
|
+
if (leftRank !== undefined)
|
|
153
|
+
return -1;
|
|
154
|
+
if (rightRank !== undefined)
|
|
155
|
+
return 1;
|
|
156
|
+
return left.key.localeCompare(right.key);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Move one key to another key's position, returning the full reordered key
|
|
161
|
+
* list (the shape persisted in the settings document's `order`).
|
|
162
|
+
*/
|
|
163
|
+
export function reorderKeys(keys, from, to) {
|
|
164
|
+
const next = [...keys];
|
|
165
|
+
const fromIndex = next.indexOf(from);
|
|
166
|
+
const toIndex = next.indexOf(to);
|
|
167
|
+
if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex)
|
|
168
|
+
return next;
|
|
169
|
+
const [moved] = next.splice(fromIndex, 1);
|
|
170
|
+
if (moved === undefined)
|
|
171
|
+
return next;
|
|
172
|
+
next.splice(toIndex, 0, moved);
|
|
173
|
+
return next;
|
|
141
174
|
}
|
|
142
175
|
//# sourceMappingURL=store.js.map
|
package/lib/types/index.js
CHANGED
|
@@ -202,6 +202,8 @@ const TOKEN_QUOTA_SETTINGS_SCHEMA = z.object({
|
|
|
202
202
|
checkUpdates: z.boolean().default(true),
|
|
203
203
|
// Client-side appearance preference; the host only stores it.
|
|
204
204
|
dimWhenIdle: z.boolean().default(false),
|
|
205
|
+
// Drag-to-reorder: display order of model keys, written by the panel.
|
|
206
|
+
order: z.array(z.string()).default([]),
|
|
205
207
|
// `reset` is a user-facing preference outside the validated surface: the
|
|
206
208
|
// panel writes it and the host validates the shape at runtime. `z.any` with
|
|
207
209
|
// a null default keeps it out of the strict fields above.
|
|
@@ -273,7 +275,7 @@ export class TokenQuotaService extends Service {
|
|
|
273
275
|
history = {};
|
|
274
276
|
limits = {};
|
|
275
277
|
monitored = undefined;
|
|
276
|
-
settingsSource = () => ({ limits: {}, monitored: [], onFull: 'stop', checkUpdates: true, dimWhenIdle: false, music: { ...TOKEN_QUOTA_DEFAULT_MUSIC } });
|
|
278
|
+
settingsSource = () => ({ limits: {}, monitored: [], onFull: 'stop', checkUpdates: true, dimWhenIdle: false, music: { ...TOKEN_QUOTA_DEFAULT_MUSIC }, order: [] });
|
|
277
279
|
/** Whether update checks are enabled (mirrors the settings document). */
|
|
278
280
|
checkUpdates = true;
|
|
279
281
|
/** Cached upgrade availability; recomputed by {@link refreshUpgrade}. */
|
|
@@ -337,6 +339,7 @@ export class TokenQuotaService extends Service {
|
|
|
337
339
|
onFull: doc.onFull === 'switchPriority' ? 'switchAll' : (doc.onFull ?? 'stop'),
|
|
338
340
|
checkUpdates: doc.checkUpdates ?? true,
|
|
339
341
|
dimWhenIdle: doc.dimWhenIdle ?? false,
|
|
342
|
+
order: Array.isArray(doc.order) ? doc.order : [],
|
|
340
343
|
reset: doc.reset ?? undefined,
|
|
341
344
|
music: {
|
|
342
345
|
enabled: doc.music?.enabled ?? TOKEN_QUOTA_DEFAULT_MUSIC.enabled,
|
package/lib/types/types.d.ts
CHANGED
|
@@ -143,6 +143,12 @@ export interface TokenQuotaSettings {
|
|
|
143
143
|
* an attached MIDI output. Off by default.
|
|
144
144
|
*/
|
|
145
145
|
music: TokenQuotaMusicSettings;
|
|
146
|
+
/**
|
|
147
|
+
* Preferred display order of model keys (`provider/model`), set by dragging
|
|
148
|
+
* rows in the panel. Keys not listed here keep their catalog order after the
|
|
149
|
+
* listed ones. Empty by default (pure catalog/alphabetical order).
|
|
150
|
+
*/
|
|
151
|
+
order: string[];
|
|
146
152
|
}
|
|
147
153
|
/** Token-quota plugin configuration. */
|
|
148
154
|
export interface TokenQuotaConfig {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jxgame2020/dsh-token-quota",
|
|
3
3
|
"description": "Daily per-model token quota accounting, enforcement, and a floating quota panel for the DeepSeek Harness — a fully self-contained plugin (no core-Harness wiring, no generated RPC contract)",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.32",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|