@jxgame2020/dsh-token-quota 0.1.14 → 0.1.16

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 CHANGED
@@ -170,7 +170,7 @@ window.__ModuleLoader__.load({
170
170
  }
171
171
  //#endregion
172
172
  //#region \0dsh-css:/Users/jxgame/Desktop/works/deepseek-harness-package/dsh-token-quota/packages/token-quota/src/client/TokenQuotaPanel.module.css.mjs
173
- 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;border-radius:12px;flex-direction:column;width:320px;max-height:min(72vh,560px);display:flex;position:fixed;top:56px;right:12px;overflow:hidden;box-shadow:0 8px 28px #0000002e}.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_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}.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}.NPLLIq_copyBtn:hover{background:var(--dsw-alias-bg-layer-3,#00000014)}.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_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:280px;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_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_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}";
173
+ 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_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_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:280px;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_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_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}";
174
174
  const tagId = "@jxgame2020/dsh-token-quota/TokenQuotaPanel.module.css";
175
175
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
176
176
  const tag = document.createElement("style");
@@ -180,86 +180,90 @@ window.__ModuleLoader__.load({
180
180
  document.head.appendChild(tag);
181
181
  }
182
182
  var TokenQuotaPanel_module_css_default = {
183
+ "logSearch": "NPLLIq_logSearch",
184
+ "logPager": "NPLLIq_logPager",
185
+ "versionNew": "NPLLIq_versionNew",
186
+ "upgradeBannerText": "NPLLIq_upgradeBannerText",
187
+ "rowMeta": "NPLLIq_rowMeta",
188
+ "upgradeBanner": "NPLLIq_upgradeBanner",
189
+ "upgradeCommand": "NPLLIq_upgradeCommand",
183
190
  "dialogTitle": "NPLLIq_dialogTitle",
184
- "dialog": "NPLLIq_dialog",
185
- "logPagerControls": "NPLLIq_logPagerControls",
186
- "fillWarn": "NPLLIq_fillWarn",
187
- "header": "NPLLIq_header",
188
- "logDialog": "NPLLIq_logDialog",
189
- "panel": "NPLLIq_panel",
190
- "resetRow": "NPLLIq_resetRow",
191
- "logScroll": "NPLLIq_logScroll",
191
+ "upgradeHint": "NPLLIq_upgradeHint",
192
192
  "dialogHeader": "NPLLIq_dialogHeader",
193
- "logPager": "NPLLIq_logPager",
194
- "logDayCol": "NPLLIq_logDayCol",
195
- "tabLabel": "NPLLIq_tabLabel",
196
- "noticeError": "NPLLIq_noticeError",
197
- "bar": "NPLLIq_bar",
198
- "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
199
- "dialogClose": "NPLLIq_dialogClose",
193
+ "save": "NPLLIq_save",
194
+ "fillOver": "NPLLIq_fillOver",
195
+ "body": "NPLLIq_body",
196
+ "dialogActions": "NPLLIq_dialogActions",
197
+ "logClearBtn": "NPLLIq_logClearBtn",
198
+ "row": "NPLLIq_row",
199
+ "input": "NPLLIq_input",
200
+ "logPagerInfo": "NPLLIq_logPagerInfo",
201
+ "logClearDialog": "NPLLIq_logClearDialog",
202
+ "logClearDate": "NPLLIq_logClearDate",
203
+ "dialog": "NPLLIq_dialog",
204
+ "logHeader": "NPLLIq_logHeader",
205
+ "collapse": "NPLLIq_collapse",
206
+ "selectBtn": "NPLLIq_selectBtn",
207
+ "subtitle": "NPLLIq_subtitle",
200
208
  "copyBtn": "NPLLIq_copyBtn",
201
- "switch": "NPLLIq_switch",
209
+ "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
210
+ "fullNotice": "NPLLIq_fullNotice",
211
+ "dialogBody": "NPLLIq_dialogBody",
212
+ "header": "NPLLIq_header",
213
+ "monitorHint": "NPLLIq_monitorHint",
202
214
  "logPagerPages": "NPLLIq_logPagerPages",
215
+ "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
203
216
  "version": "NPLLIq_version",
204
- "tabIcon": "NPLLIq_tabIcon",
205
- "dialogSection": "NPLLIq_dialogSection",
217
+ "rowHeader": "NPLLIq_rowHeader",
206
218
  "controls": "NPLLIq_controls",
219
+ "monitorRow": "NPLLIq_monitorRow",
220
+ "tab": "NPLLIq_tab",
221
+ "logDayCol": "NPLLIq_logDayCol",
222
+ "logScroll": "NPLLIq_logScroll",
223
+ "radioRow": "NPLLIq_radioRow",
224
+ "fillWarn": "NPLLIq_fillWarn",
207
225
  "resetSelect": "NPLLIq_resetSelect",
208
- "dialogActions": "NPLLIq_dialogActions",
209
- "fillIdle": "NPLLIq_fillIdle",
210
- "headerActions": "NPLLIq_headerActions",
211
- "monitorHint": "NPLLIq_monitorHint",
212
- "body": "NPLLIq_body",
213
- "currentBadge": "NPLLIq_currentBadge",
214
- "logPagerInfo": "NPLLIq_logPagerInfo",
215
- "checkBtn": "NPLLIq_checkBtn",
226
+ "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
227
+ "logPagerControls": "NPLLIq_logPagerControls",
216
228
  "monitorList": "NPLLIq_monitorList",
217
- "input": "NPLLIq_input",
218
- "upgradeBannerText": "NPLLIq_upgradeBannerText",
219
- "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
220
- "headerText": "NPLLIq_headerText",
221
- "logClearDate": "NPLLIq_logClearDate",
222
- "logClearBtn": "NPLLIq_logClearBtn",
223
- "logHeader": "NPLLIq_logHeader",
224
- "dialogLabel": "NPLLIq_dialogLabel",
229
+ "logTable": "NPLLIq_logTable",
230
+ "dialogSection": "NPLLIq_dialogSection",
231
+ "dialogBtn": "NPLLIq_dialogBtn",
232
+ "title": "NPLLIq_title",
233
+ "checkErrorHint": "NPLLIq_checkErrorHint",
234
+ "resetRow": "NPLLIq_resetRow",
225
235
  "notice": "NPLLIq_notice",
226
- "logUsedCol": "NPLLIq_logUsedCol",
227
- "collapse": "NPLLIq_collapse",
228
- "upgradeHint": "NPLLIq_upgradeHint",
229
- "monitorName": "NPLLIq_monitorName",
230
236
  "logPagerBtn": "NPLLIq_logPagerBtn",
231
- "fillOver": "NPLLIq_fillOver",
232
- "upgradeBanner": "NPLLIq_upgradeBanner",
233
- "rowHeader": "NPLLIq_rowHeader",
234
- "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
235
- "upgradeCommand": "NPLLIq_upgradeCommand",
236
- "logModelCol": "NPLLIq_logModelCol",
237
+ "headerActions": "NPLLIq_headerActions",
238
+ "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
239
+ "checkBtn": "NPLLIq_checkBtn",
240
+ "panelDim": "NPLLIq_panelDim",
241
+ "panelDimStrong": "NPLLIq_panelDimStrong",
242
+ "noticeError": "NPLLIq_noticeError",
243
+ "monitorName": "NPLLIq_monitorName",
244
+ "switch": "NPLLIq_switch",
245
+ "settingsBtn": "NPLLIq_settingsBtn",
237
246
  "rowName": "NPLLIq_rowName",
238
- "logClearDialog": "NPLLIq_logClearDialog",
239
- "save": "NPLLIq_save",
240
- "upgradeClose": "NPLLIq_upgradeClose",
241
- "rowMeta": "NPLLIq_rowMeta",
242
- "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
243
- "versionNew": "NPLLIq_versionNew",
244
- "subtitle": "NPLLIq_subtitle",
245
- "gearBtn": "NPLLIq_gearBtn",
246
247
  "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
247
- "settingsBtn": "NPLLIq_settingsBtn",
248
- "row": "NPLLIq_row",
249
- "selectBtn": "NPLLIq_selectBtn",
250
- "radioRow": "NPLLIq_radioRow",
251
- "dialogBtn": "NPLLIq_dialogBtn",
248
+ "dialogClose": "NPLLIq_dialogClose",
249
+ "logUsedCol": "NPLLIq_logUsedCol",
250
+ "dialogOverlay": "NPLLIq_dialogOverlay",
251
+ "gearBtn": "NPLLIq_gearBtn",
252
+ "fillIdle": "NPLLIq_fillIdle",
253
+ "tabIcon": "NPLLIq_tabIcon",
254
+ "upgradeClose": "NPLLIq_upgradeClose",
255
+ "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
256
+ "currentBadge": "NPLLIq_currentBadge",
252
257
  "logToolbar": "NPLLIq_logToolbar",
253
- "logSearch": "NPLLIq_logSearch",
254
- "dialogBody": "NPLLIq_dialogBody",
255
- "checkErrorHint": "NPLLIq_checkErrorHint",
258
+ "bar": "NPLLIq_bar",
259
+ "dialogLabel": "NPLLIq_dialogLabel",
260
+ "panel": "NPLLIq_panel",
261
+ "headerText": "NPLLIq_headerText",
256
262
  "upgradeCommands": "NPLLIq_upgradeCommands",
257
- "dialogOverlay": "NPLLIq_dialogOverlay",
258
- "monitorRow": "NPLLIq_monitorRow",
259
- "title": "NPLLIq_title",
260
- "tab": "NPLLIq_tab",
261
- "fullNotice": "NPLLIq_fullNotice",
262
- "logTable": "NPLLIq_logTable"
263
+ "copyBtnDone": "NPLLIq_copyBtnDone",
264
+ "logModelCol": "NPLLIq_logModelCol",
265
+ "tabLabel": "NPLLIq_tabLabel",
266
+ "logDialog": "NPLLIq_logDialog"
263
267
  };
264
268
  //#endregion
265
269
  //#region lib/types/client/TokenQuotaPanel.js
@@ -350,6 +354,13 @@ window.__ModuleLoader__.load({
350
354
  const [collapsed, setCollapsed] = (0, react.useState)(false);
351
355
  const [drafts, setDrafts] = (0, react.useState)({});
352
356
  const [editingKey, setEditingKey] = (0, react.useState)(null);
357
+ const [hovered, setHovered] = (0, react.useState)(false);
358
+ const [inputActive, setInputActive] = (0, react.useState)(false);
359
+ const [copiedCmd, setCopiedCmd] = (0, react.useState)(null);
360
+ const copyTimerRef = (0, react.useRef)(null);
361
+ const [upgradeFlash, setUpgradeFlash] = (0, react.useState)(false);
362
+ const flashTimerRef = (0, react.useRef)(null);
363
+ const prevUpgradeRef = (0, react.useRef)(null);
353
364
  const [panelPos, setPanelPos] = (0, react.useState)(loadPanelPos);
354
365
  const [settingsPos, setSettingsPos] = (0, react.useState)(null);
355
366
  const [logPos, setLogPos] = (0, react.useState)(null);
@@ -390,6 +401,37 @@ window.__ModuleLoader__.load({
390
401
  (0, react.useEffect)(() => {
391
402
  if (sessionId !== void 0) load(sessionId);
392
403
  }, [sessionId, load]);
404
+ (0, react.useEffect)(() => {
405
+ const onFocusIn = (event) => {
406
+ const target = event.target;
407
+ const isInput = target !== null && (target.matches("input, textarea, [contenteditable=\"true\"]") || target.closest("input, textarea, [contenteditable=\"true\"]") !== null);
408
+ setInputActive(isInput);
409
+ };
410
+ window.addEventListener("focusin", onFocusIn);
411
+ return () => {
412
+ window.removeEventListener("focusin", onFocusIn);
413
+ };
414
+ }, []);
415
+ (0, react.useEffect)(() => {
416
+ const latest = upgrade?.latestVersion ?? null;
417
+ if (latest !== null && prevUpgradeRef.current !== latest) {
418
+ setCollapsed(false);
419
+ setUpgradeFlash(true);
420
+ if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);
421
+ flashTimerRef.current = window.setTimeout(() => {
422
+ setUpgradeFlash(false);
423
+ flashTimerRef.current = null;
424
+ }, 2500);
425
+ }
426
+ prevUpgradeRef.current = latest;
427
+ return () => {};
428
+ }, [upgrade]);
429
+ (0, react.useEffect)(() => {
430
+ return () => {
431
+ if (flashTimerRef.current !== null) clearTimeout(flashTimerRef.current);
432
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
433
+ };
434
+ }, []);
393
435
  const rows = (0, react.useMemo)(() => mergeModelRows(groups, snapshot, current), [
394
436
  groups,
395
437
  snapshot,
@@ -433,6 +475,16 @@ window.__ModuleLoader__.load({
433
475
  document.body.removeChild(el);
434
476
  }
435
477
  };
478
+ /** Copy an upgrade command and show per-button success feedback. */
479
+ const copyUpgradeCommand = (cmd) => {
480
+ copyToClipboard(cmd);
481
+ setCopiedCmd(cmd);
482
+ if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
483
+ copyTimerRef.current = window.setTimeout(() => {
484
+ setCopiedCmd(null);
485
+ copyTimerRef.current = null;
486
+ }, 1600);
487
+ };
436
488
  (0, react.useEffect)(() => {
437
489
  if (!logOpen) return;
438
490
  let cancelled = false;
@@ -483,14 +535,21 @@ window.__ModuleLoader__.load({
483
535
  setLimit(row.key, parsed);
484
536
  };
485
537
  const visibleRows = rows.filter((row) => isMonitoredKey(row.key) || row.current);
538
+ const panelDimClass = hovered || upgradeFlash ? "" : inputActive ? TokenQuotaPanel_module_css_default.panelDimStrong : TokenQuotaPanel_module_css_default.panelDim;
486
539
  return (0, react_jsx_runtime.jsxs)("div", {
487
540
  ref: panelRef,
488
- className: TokenQuotaPanel_module_css_default.panel,
541
+ className: `${TokenQuotaPanel_module_css_default.panel}${panelDimClass !== "" ? ` ${panelDimClass}` : ""}`,
489
542
  style: panelPos !== null ? {
490
543
  left: panelPos.x,
491
544
  top: panelPos.y,
492
545
  right: "auto"
493
546
  } : void 0,
547
+ onPointerEnter: () => {
548
+ setHovered(true);
549
+ },
550
+ onPointerLeave: () => {
551
+ setHovered(false);
552
+ },
494
553
  children: [
495
554
  (0, react_jsx_runtime.jsxs)("div", {
496
555
  className: TokenQuotaPanel_module_css_default.header,
@@ -506,13 +565,13 @@ window.__ModuleLoader__.load({
506
565
  title: t("upgradeAvailableHint"),
507
566
  children: [
508
567
  "v",
509
- "0.1.14",
568
+ "0.1.16",
510
569
  " → v",
511
570
  upgrade.latestVersion
512
571
  ]
513
572
  }) : (0, react_jsx_runtime.jsxs)("span", {
514
573
  className: TokenQuotaPanel_module_css_default.version,
515
- children: ["v", "0.1.14"]
574
+ children: ["v", "0.1.16"]
516
575
  })]
517
576
  }), (0, react_jsx_runtime.jsx)("div", {
518
577
  className: TokenQuotaPanel_module_css_default.subtitle,
@@ -566,7 +625,7 @@ window.__ModuleLoader__.load({
566
625
  children: fullNotice
567
626
  }),
568
627
  upgrade !== null && !upgradeDismissed && (0, react_jsx_runtime.jsxs)("div", {
569
- className: TokenQuotaPanel_module_css_default.upgradeBanner,
628
+ className: `${TokenQuotaPanel_module_css_default.upgradeBanner}${upgradeFlash ? ` ${TokenQuotaPanel_module_css_default.upgradeBannerFlash}` : ""}`,
570
629
  role: "alert",
571
630
  children: [
572
631
  (0, react_jsx_runtime.jsx)("div", {
@@ -582,11 +641,11 @@ window.__ModuleLoader__.load({
582
641
  children: cmd
583
642
  }), (0, react_jsx_runtime.jsx)("button", {
584
643
  type: "button",
585
- className: TokenQuotaPanel_module_css_default.copyBtn,
644
+ className: `${TokenQuotaPanel_module_css_default.copyBtn}${copiedCmd === cmd ? ` ${TokenQuotaPanel_module_css_default.copyBtnDone}` : ""}`,
586
645
  onClick: () => {
587
- copyToClipboard(cmd);
646
+ copyUpgradeCommand(cmd);
588
647
  },
589
- children: t("copy")
648
+ children: copiedCmd === cmd ? t("copied") : t("copy")
590
649
  })]
591
650
  }, cmd))
592
651
  }),
@@ -1112,6 +1171,7 @@ window.__ModuleLoader__.load({
1112
1171
  upgradeAvailableHint: "有新版本可用",
1113
1172
  upgradeAvailable: "发现新版本 v{version},请在终端执行以下命令升级:",
1114
1173
  copy: "复制",
1174
+ copied: "已复制 ✓",
1115
1175
  upgradeHint: "升级后请重启 dsh web 并刷新浏览器页面",
1116
1176
  checkUpdatesLabel: "自动检查更新",
1117
1177
  checkUpdatesNow: "立即检查",
@@ -1176,6 +1236,7 @@ window.__ModuleLoader__.load({
1176
1236
  upgradeAvailableHint: "A new version is available",
1177
1237
  upgradeAvailable: "A new version v{version} is available. Run one of the following commands in your terminal to upgrade:",
1178
1238
  copy: "Copy",
1239
+ copied: "Copied ✓",
1179
1240
  upgradeHint: "After upgrading, restart dsh web and refresh the browser",
1180
1241
  checkUpdatesLabel: "Check for updates automatically",
1181
1242
  checkUpdatesNow: "Check now",
@@ -1404,7 +1465,8 @@ window.__ModuleLoader__.load({
1404
1465
  bound?.setUpgrade(snapshot.upgrade ?? null);
1405
1466
  bound?.setUpgradeError(snapshot.upgradeError ?? null);
1406
1467
  actOnFull(snapshot);
1407
- if (snapshot.upgrade === null) bound?.setLastCheckResult(snapshot.upgradeError !== null ? "error" : "up-to-date");
1468
+ if (snapshot.upgrade !== null) bound?.setDialogOpen(false);
1469
+ else bound?.setLastCheckResult(snapshot.upgradeError !== null ? "error" : "up-to-date");
1408
1470
  }
1409
1471
  bound?.setCheckingUpdates(false);
1410
1472
  setTimeout(() => {
package/lib/index.js CHANGED
@@ -406,7 +406,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
406
406
  return this.upgradeCheck;
407
407
  }
408
408
  async doRefreshUpgrade() {
409
- const current = "0.1.14";
409
+ const current = "0.1.16";
410
410
  let latest;
411
411
  try {
412
412
  const response = await fetch(REGISTRY_LATEST_URL, {
@@ -90,6 +90,20 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
90
90
  const [collapsed, setCollapsed] = useState(false);
91
91
  const [drafts, setDrafts] = useState({});
92
92
  const [editingKey, setEditingKey] = useState(null);
93
+ // Hover / focus state for the translucent-while-idle behaviour: the panel
94
+ // dims when the mouse is away (and especially while typing in the composer)
95
+ // so the chat content behind it stays readable; hovering restores it.
96
+ const [hovered, setHovered] = useState(false);
97
+ const [inputActive, setInputActive] = useState(false);
98
+ // Copy-button feedback: which command was just copied (label flips to
99
+ // 「已复制」for a moment so the click is perceivable).
100
+ const [copiedCmd, setCopiedCmd] = useState(null);
101
+ const copyTimerRef = useRef(null);
102
+ // Flash state for the upgrade banner: armed when a NEW latest version shows
103
+ // up (either from a manual check or a periodic poll).
104
+ const [upgradeFlash, setUpgradeFlash] = useState(false);
105
+ const flashTimerRef = useRef(null);
106
+ const prevUpgradeRef = useRef(null);
93
107
  // Draggable placements: the panel persists across reloads; the dialogs
94
108
  // start centered (null) and remember where they were dragged to.
95
109
  const [panelPos, setPanelPos] = useState(loadPanelPos);
@@ -137,6 +151,46 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
137
151
  if (sessionId !== undefined)
138
152
  load(sessionId);
139
153
  }, [sessionId, load]);
154
+ // Track whether any text input (composer, search, dialogs) currently has
155
+ // focus, so the panel can dim while the user types elsewhere.
156
+ useEffect(() => {
157
+ const onFocusIn = (event) => {
158
+ const target = event.target;
159
+ const isInput = target !== null && (target.matches('input, textarea, [contenteditable="true"]')
160
+ || target.closest('input, textarea, [contenteditable="true"]') !== null);
161
+ setInputActive(isInput);
162
+ };
163
+ window.addEventListener('focusin', onFocusIn);
164
+ return () => { window.removeEventListener('focusin', onFocusIn); };
165
+ }, []);
166
+ // When a NEW latest version appears (manual check or periodic poll):
167
+ // expand the panel (it may be collapsed), force it opaque, and flash the
168
+ // upgrade banner a few times so the discovery is unmissable.
169
+ useEffect(() => {
170
+ const latest = upgrade?.latestVersion ?? null;
171
+ if (latest !== null && prevUpgradeRef.current !== latest) {
172
+ setCollapsed(false);
173
+ setUpgradeFlash(true);
174
+ if (flashTimerRef.current !== null)
175
+ clearTimeout(flashTimerRef.current);
176
+ flashTimerRef.current = window.setTimeout(() => {
177
+ setUpgradeFlash(false);
178
+ flashTimerRef.current = null;
179
+ }, 2500);
180
+ }
181
+ prevUpgradeRef.current = latest;
182
+ return () => {
183
+ // Keep the timer across re-renders; cleared only on unmount.
184
+ };
185
+ }, [upgrade]);
186
+ useEffect(() => {
187
+ return () => {
188
+ if (flashTimerRef.current !== null)
189
+ clearTimeout(flashTimerRef.current);
190
+ if (copyTimerRef.current !== null)
191
+ clearTimeout(copyTimerRef.current);
192
+ };
193
+ }, []);
140
194
  const rows = useMemo(() => mergeModelRows(groups, snapshot, current), [groups, snapshot, current]);
141
195
  // All directory models, flattened for the monitoring picker.
142
196
  const allModels = useMemo(() => groups.flatMap(group => group.models.map((model) => ({
@@ -180,6 +234,17 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
180
234
  document.body.removeChild(el);
181
235
  }
182
236
  };
237
+ /** Copy an upgrade command and show per-button success feedback. */
238
+ const copyUpgradeCommand = (cmd) => {
239
+ void copyToClipboard(cmd);
240
+ setCopiedCmd(cmd);
241
+ if (copyTimerRef.current !== null)
242
+ clearTimeout(copyTimerRef.current);
243
+ copyTimerRef.current = window.setTimeout(() => {
244
+ setCopiedCmd(null);
245
+ copyTimerRef.current = null;
246
+ }, 1600);
247
+ };
183
248
  // Fetch the usage log whenever the log dialog opens. Kept ABOVE the
184
249
  // collapsed early-return: every hook must run on every render, otherwise
185
250
  // React unmounts the component the moment the panel collapses (the old
@@ -220,9 +285,15 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
220
285
  setLimit(row.key, parsed);
221
286
  };
222
287
  const visibleRows = rows.filter(row => isMonitoredKey(row.key) || row.current);
223
- return (_jsxs("div", { ref: panelRef, className: css.panel, style: panelPos !== null ? { left: panelPos.x, top: panelPos.y, right: 'auto' } : undefined, children: [_jsxs("div", { className: css.header, onPointerDown: (event) => { beginDrag(event, panelRef.current, applyPanelPos); }, children: [_jsxs("div", { className: css.headerText, children: [_jsxs("div", { className: css.title, children: [t('title'), __TOKEN_QUOTA_VERSION__ !== undefined && __TOKEN_QUOTA_VERSION__ !== '' && (upgrade !== null
288
+ // The panel dims when the pointer is away; dimming is stronger while the
289
+ // user is typing in an input elsewhere so the text behind stays readable.
290
+ // While the upgrade banner flashes, the panel is forced opaque.
291
+ const panelDimClass = hovered || upgradeFlash
292
+ ? ''
293
+ : inputActive ? css.panelDimStrong : css.panelDim;
294
+ return (_jsxs("div", { ref: panelRef, className: `${css.panel}${panelDimClass !== '' ? ` ${panelDimClass}` : ''}`, style: panelPos !== null ? { left: panelPos.x, top: panelPos.y, right: 'auto' } : undefined, onPointerEnter: () => { setHovered(true); }, onPointerLeave: () => { setHovered(false); }, children: [_jsxs("div", { className: css.header, onPointerDown: (event) => { beginDrag(event, panelRef.current, applyPanelPos); }, children: [_jsxs("div", { className: css.headerText, children: [_jsxs("div", { className: css.title, children: [t('title'), __TOKEN_QUOTA_VERSION__ !== undefined && __TOKEN_QUOTA_VERSION__ !== '' && (upgrade !== null
224
295
  ? (_jsxs("span", { className: `${css.version} ${css.versionNew}`, title: t('upgradeAvailableHint'), children: ["v", __TOKEN_QUOTA_VERSION__, " \u2192 v", upgrade.latestVersion] }))
225
- : (_jsxs("span", { className: css.version, children: ["v", __TOKEN_QUOTA_VERSION__] })))] }), _jsx("div", { className: css.subtitle, children: t('subtitle') })] }), _jsxs("div", { className: css.headerActions, onPointerDown: (event) => { event.stopPropagation(); }, children: [_jsx("button", { type: "button", className: css.settingsBtn, onClick: () => { actions.setLogOpen(true); }, children: t('logs') }), _jsx("button", { type: "button", className: css.settingsBtn, onClick: openSettings, children: t('settings') }), _jsx("button", { type: "button", className: css.collapse, onClick: () => { setCollapsed(true); }, children: t('collapse') })] })] }), _jsxs("div", { className: css.body, children: [loading && _jsx("div", { className: css.notice, children: t('loading') }), error !== null && _jsx("div", { className: css.noticeError, children: error }), fullNotice !== null && (_jsx("div", { className: css.fullNotice, role: "alert", children: fullNotice })), upgrade !== null && !upgradeDismissed && (_jsxs("div", { className: css.upgradeBanner, role: "alert", children: [_jsx("div", { className: css.upgradeBannerText, children: t('upgradeAvailable').replace('{version}', upgrade.latestVersion) }), _jsx("div", { className: css.upgradeCommands, children: upgrade.commands.map(cmd => (_jsxs("div", { className: css.upgradeCommandRow, children: [_jsx("code", { className: css.upgradeCommand, children: cmd }), _jsx("button", { type: "button", className: css.copyBtn, onClick: () => { void copyToClipboard(cmd); }, children: t('copy') })] }, cmd))) }), _jsx("div", { className: css.upgradeHint, children: t('upgradeHint') }), _jsx("button", { type: "button", className: css.upgradeClose, onClick: () => { actions.setUpgradeDismissed(true); }, "aria-label": t('close'), children: "\u00D7" })] })), !loading && error === null && visibleRows.length === 0 && (_jsx("div", { className: css.notice, children: monitored !== null && monitored.length === 0 ? t('noMonitored') : t('waiting') })), visibleRows.map((row) => {
296
+ : (_jsxs("span", { className: css.version, children: ["v", __TOKEN_QUOTA_VERSION__] })))] }), _jsx("div", { className: css.subtitle, children: t('subtitle') })] }), _jsxs("div", { className: css.headerActions, onPointerDown: (event) => { event.stopPropagation(); }, children: [_jsx("button", { type: "button", className: css.settingsBtn, onClick: () => { actions.setLogOpen(true); }, children: t('logs') }), _jsx("button", { type: "button", className: css.settingsBtn, onClick: openSettings, children: t('settings') }), _jsx("button", { type: "button", className: css.collapse, onClick: () => { setCollapsed(true); }, children: t('collapse') })] })] }), _jsxs("div", { className: css.body, children: [loading && _jsx("div", { className: css.notice, children: t('loading') }), error !== null && _jsx("div", { className: css.noticeError, children: error }), fullNotice !== null && (_jsx("div", { className: css.fullNotice, role: "alert", children: fullNotice })), upgrade !== null && !upgradeDismissed && (_jsxs("div", { className: `${css.upgradeBanner}${upgradeFlash ? ` ${css.upgradeBannerFlash}` : ''}`, role: "alert", children: [_jsx("div", { className: css.upgradeBannerText, children: t('upgradeAvailable').replace('{version}', upgrade.latestVersion) }), _jsx("div", { className: css.upgradeCommands, children: upgrade.commands.map(cmd => (_jsxs("div", { className: css.upgradeCommandRow, children: [_jsx("code", { className: css.upgradeCommand, children: cmd }), _jsx("button", { type: "button", className: `${css.copyBtn}${copiedCmd === cmd ? ` ${css.copyBtnDone}` : ''}`, onClick: () => { copyUpgradeCommand(cmd); }, children: copiedCmd === cmd ? t('copied') : t('copy') })] }, cmd))) }), _jsx("div", { className: css.upgradeHint, children: t('upgradeHint') }), _jsx("button", { type: "button", className: css.upgradeClose, onClick: () => { actions.setUpgradeDismissed(true); }, "aria-label": t('close'), children: "\u00D7" })] })), !loading && error === null && visibleRows.length === 0 && (_jsx("div", { className: css.notice, children: monitored !== null && monitored.length === 0 ? t('noMonitored') : t('waiting') })), visibleRows.map((row) => {
226
297
  const state = barStateOf(row);
227
298
  const pct = row.limit > 0 ? Math.min(100, Math.round((row.used / row.limit) * 100)) : 0;
228
299
  const barClass = state === 'over'
@@ -254,7 +254,12 @@ export function apply(ctx) {
254
254
  bound?.setUpgrade(snapshot.upgrade ?? null);
255
255
  bound?.setUpgradeError(snapshot.upgradeError ?? null);
256
256
  actOnFull(snapshot);
257
- if (snapshot.upgrade === null) {
257
+ if (snapshot.upgrade !== null) {
258
+ // A new version was found: close the settings dialog so the
259
+ // flashing upgrade banner in the panel is immediately visible.
260
+ bound?.setDialogOpen(false);
261
+ }
262
+ else {
258
263
  // No newer version known: distinguish "checked OK, up to date"
259
264
  // from "check failed" via the host-provided error message.
260
265
  bound?.setLastCheckResult(snapshot.upgradeError !== null ? 'error' : 'up-to-date');
@@ -61,6 +61,7 @@ export declare const zh: {
61
61
  upgradeAvailableHint: string;
62
62
  upgradeAvailable: string;
63
63
  copy: string;
64
+ copied: string;
64
65
  upgradeHint: string;
65
66
  checkUpdatesLabel: string;
66
67
  checkUpdatesNow: string;
@@ -127,6 +128,7 @@ export declare const en: {
127
128
  upgradeAvailableHint: string;
128
129
  upgradeAvailable: string;
129
130
  copy: string;
131
+ copied: string;
130
132
  upgradeHint: string;
131
133
  checkUpdatesLabel: string;
132
134
  checkUpdatesNow: string;
@@ -61,6 +61,7 @@ export const zh = {
61
61
  upgradeAvailableHint: '有新版本可用',
62
62
  upgradeAvailable: '发现新版本 v{version},请在终端执行以下命令升级:',
63
63
  copy: '复制',
64
+ copied: '已复制 ✓',
64
65
  upgradeHint: '升级后请重启 dsh web 并刷新浏览器页面',
65
66
  checkUpdatesLabel: '自动检查更新',
66
67
  checkUpdatesNow: '立即检查',
@@ -125,6 +126,7 @@ export const en = {
125
126
  upgradeAvailableHint: 'A new version is available',
126
127
  upgradeAvailable: 'A new version v{version} is available. Run one of the following commands in your terminal to upgrade:',
127
128
  copy: 'Copy',
129
+ copied: 'Copied ✓',
128
130
  upgradeHint: 'After upgrading, restart dsh web and refresh the browser',
129
131
  checkUpdatesLabel: 'Check for updates automatically',
130
132
  checkUpdatesNow: 'Check now',
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.14",
4
+ "version": "0.1.16",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },