@jxgame2020/dsh-token-quota 0.1.43 → 0.1.44

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
@@ -132,7 +132,7 @@ window.__ModuleLoader__.load({
132
132
  d.transcribe = settings;
133
133
  },
134
134
  setUpgrade: (d, upgrade) => {
135
- const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.43" ? upgrade : null;
135
+ const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.44" ? upgrade : null;
136
136
  if (d.upgrade === null || d.upgrade.latestVersion !== normalized?.latestVersion) d.upgradeDismissed = false;
137
137
  d.upgrade = normalized;
138
138
  },
@@ -252,7 +252,7 @@ window.__ModuleLoader__.load({
252
252
  }
253
253
  //#endregion
254
254
  //#region \0dsh-css:/Users/jxgame/Desktop/works/deepseek-harness-package/dsh-token-quota/packages/token-quota/src/client/TokenQuotaPanel.module.css.mjs
255
- const css$1 = ".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;flex-wrap:wrap;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_notesBar{flex-wrap:wrap;flex:100%;align-items:center;gap:4px;padding:2px 0 0;display:flex}.NPLLIq_noteChip{width:20px;height:20px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;font-size:11px;line-height:1;transition:color .12s,border-color .12s;display:inline-flex}.NPLLIq_noteChip:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.NPLLIq_noteChipOpen{color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew{width:22px;height:20px;color:var(--dsw-alias-label-secondary);border:1px dashed var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;transition:color .12s,border-color .12s;display:inline-flex;position:relative}.NPLLIq_noteNew:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_noteNewPlus{color:inherit;font-size:10px;font-weight:700;line-height:1;position:absolute;bottom:-2px;right:-1px}.NPLLIq_noteWin{z-index:60;pointer-events:auto;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 24px #00000038}.NPLLIq_noteWinCollapsed{height:auto!important}.NPLLIq_noteWinBar{background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;flex:none;align-items:center;gap:4px;padding:4px 6px;display:flex}.NPLLIq_noteWinBar:active{cursor:grabbing}.NPLLIq_noteWinGripBar{color:var(--dsw-alias-label-secondary);opacity:.7;flex:none;font-size:10px}.NPLLIq_noteWinTitleText{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;padding:1px 2px;font-size:11px;font-weight:600;overflow:hidden}.NPLLIq_noteWinTitle{min-width:0;color:var(--dsw-alias-label-primary);background:0 0;border:1px solid #0000;border-radius:4px;outline:none;flex:1;padding:1px 2px;font-size:11px;font-weight:600}.NPLLIq_noteWinTitle:hover{border-color:var(--dsw-alias-border-l1)}.NPLLIq_noteWinTitle:focus{background:var(--dsw-alias-bg-overlay);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteWinBtn{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_noteWinBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.NPLLIq_noteWinText{box-sizing:border-box;width:100%;min-height:0;color:var(--dsw-alias-label-primary);resize:none;background:0 0;border:none;outline:none;flex:1;padding:6px 8px;font-family:inherit;font-size:11px;line-height:1.5}.NPLLIq_noteWinResize{cursor:nwse-resize;background:linear-gradient(135deg, transparent 0 45%, var(--dsw-alias-border-l2) 45% 55%, transparent 55% 70%, var(--dsw-alias-border-l2) 70% 80%, transparent 80%);width:14px;height:14px;position:absolute;bottom:0;right:0}.NPLLIq_noteMenuBackdrop{z-index:100;pointer-events:auto;position:fixed;inset:0}.NPLLIq_noteMenu{z-index:101;pointer-events:auto;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;min-width:96px;padding:4px;display:flex;position:fixed;box-shadow:0 8px 24px #0000003d}.NPLLIq_noteMenuItem{text-align:left;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:5px;padding:5px 8px;font-size:11px}.NPLLIq_noteMenuItem:hover{background:var(--dsw-alias-bg-layer-2)}.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_balanceToggle{margin-left:auto}.NPLLIq_balanceToggleOpen{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceWin{z-index:1199;background:var(--dsw-alias-bg-layer-2);width:280px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;border-radius:12px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 24px #00000029}.NPLLIq_balanceWinHeader{border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-3);user-select:none;align-items:center;gap:6px;padding:6px 8px 6px 12px;display:flex}.NPLLIq_balanceWinTitle{flex:1;font-size:12px;font-weight:600;line-height:1}.NPLLIq_balanceWinBody{font-variant-numeric:tabular-nums;padding:6px 10px 10px;font-size:11px}.NPLLIq_balanceRowHeader{border-bottom:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);grid-template-columns:1fr auto 20px;align-items:center;gap:6px;padding:3px 2px;font-weight:600;display:grid}.NPLLIq_balanceSortBtn{all:unset;cursor:pointer;color:inherit;border-radius:4px;padding:1px 2px;font-size:10px;font-weight:600}.NPLLIq_balanceSortBtn:hover{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRefreshAll{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceRefreshAll:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRefreshAll:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_balanceRow{grid-template-columns:1fr auto 20px;align-items:center;gap:6px;padding:3px 2px;display:grid}.NPLLIq_balanceRow+.NPLLIq_balanceRow{border-top:1px dashed var(--dsw-alias-border-l1)}.NPLLIq_balanceRowName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-weight:500;overflow:hidden}.NPLLIq_balanceRowValue{text-align:right;font-weight:600}.NPLLIq_balanceRowRefresh{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceRowRefresh:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRowRefresh:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_balanceValueOk{color:var(--dsw-alias-label-primary)}.NPLLIq_balanceValueLow{color:var(--dsw-alias-state-warn-primary)}.NPLLIq_balanceValueError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_balanceStateHint{color:var(--dsw-alias-label-secondary);font-style:italic;font-weight:500}.NPLLIq_balanceStateError{color:var(--dsw-alias-state-error-primary);font-weight:500}.NPLLIq_balanceLastLine{border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);margin-top:6px;padding-top:5px;font-size:10px}.NPLLIq_balanceBar{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:center;gap:6px;padding:5px 12px;font-size:11px;display:flex}.NPLLIq_balanceBarText{text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;min-width:0;font-weight:600;display:inline-flex;overflow:hidden}.NPLLIq_balanceBarBadge{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border-radius:4px;flex:none;padding:0 4px;font-size:10px;font-weight:600}.NPLLIq_balanceBarDim{color:var(--dsw-alias-label-secondary);font-weight:500}.NPLLIq_balanceBarLow{color:var(--dsw-alias-state-warn-primary)}.NPLLIq_balanceBarError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_balanceBarRefresh{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceBarRefresh:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceBarRefresh:disabled{opacity:.4;cursor:not-allowed}.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;pointer-events:auto;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;pointer-events:auto;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}";
255
+ const css$1 = ".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;flex-wrap:wrap;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_notesBar{flex-wrap:wrap;flex:100%;align-items:center;gap:4px;padding:2px 0 0;display:flex}.NPLLIq_noteChip{width:20px;height:20px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;font-size:11px;line-height:1;transition:color .12s,border-color .12s;display:inline-flex}.NPLLIq_noteChip:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.NPLLIq_noteChipOpen{color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew{width:22px;height:20px;color:var(--dsw-alias-label-secondary);border:1px dashed var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;transition:color .12s,border-color .12s;display:inline-flex;position:relative}.NPLLIq_noteNew:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_noteNewPlus{color:inherit;font-size:10px;font-weight:700;line-height:1;position:absolute;bottom:-2px;right:-1px}.NPLLIq_noteWin{z-index:60;pointer-events:auto;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 24px #00000038}.NPLLIq_noteWinCollapsed{height:auto!important}.NPLLIq_noteWinBar{background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;flex:none;align-items:center;gap:4px;padding:4px 6px;display:flex}.NPLLIq_noteWinBar:active{cursor:grabbing}.NPLLIq_noteWinGripBar{color:var(--dsw-alias-label-secondary);opacity:.7;flex:none;font-size:10px}.NPLLIq_noteWinTitleText{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;padding:1px 2px;font-size:11px;font-weight:600;overflow:hidden}.NPLLIq_noteWinTitle{min-width:0;color:var(--dsw-alias-label-primary);background:0 0;border:1px solid #0000;border-radius:4px;outline:none;flex:1;padding:1px 2px;font-size:11px;font-weight:600}.NPLLIq_noteWinTitle:hover{border-color:var(--dsw-alias-border-l1)}.NPLLIq_noteWinTitle:focus{background:var(--dsw-alias-bg-overlay);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteWinBtn{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_noteWinBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.NPLLIq_noteWinText{box-sizing:border-box;width:100%;min-height:0;color:var(--dsw-alias-label-primary);resize:none;background:0 0;border:none;outline:none;flex:1;padding:6px 8px;font-family:inherit;font-size:11px;line-height:1.5}.NPLLIq_noteWinResize{cursor:nwse-resize;background:linear-gradient(135deg, transparent 0 45%, var(--dsw-alias-border-l2) 45% 55%, transparent 55% 70%, var(--dsw-alias-border-l2) 70% 80%, transparent 80%);width:14px;height:14px;position:absolute;bottom:0;right:0}.NPLLIq_noteMenuBackdrop{z-index:100;pointer-events:auto;position:fixed;inset:0}.NPLLIq_noteMenu{z-index:101;pointer-events:auto;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;min-width:96px;padding:4px;display:flex;position:fixed;box-shadow:0 8px 24px #0000003d}.NPLLIq_noteMenuItem{text-align:left;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:5px;padding:5px 8px;font-size:11px}.NPLLIq_noteMenuItem:hover{background:var(--dsw-alias-bg-layer-2)}.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_balanceToggle{margin-left:auto}.NPLLIq_balanceToggleOpen{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceWin{z-index:1199;background:var(--dsw-alias-bg-layer-2);width:280px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;border-radius:12px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 24px #00000029}.NPLLIq_balanceWinHeader{border-bottom:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-3);user-select:none;align-items:center;gap:6px;padding:6px 8px 6px 12px;display:flex}.NPLLIq_balanceWinTitle{flex:1;font-size:12px;font-weight:600;line-height:1}.NPLLIq_balanceWinBody{font-variant-numeric:tabular-nums;padding:6px 10px 10px;font-size:11px}.NPLLIq_balanceRowHeader{border-bottom:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);grid-template-columns:1fr auto 20px;align-items:center;gap:6px;padding:3px 2px;font-weight:600;display:grid}.NPLLIq_balanceSortBtn{all:unset;cursor:pointer;color:inherit;border-radius:4px;padding:1px 2px;font-size:10px;font-weight:600}.NPLLIq_balanceSortBtn:hover{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRefreshAll{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceRefreshAll:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRefreshAll:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_balanceRow{grid-template-columns:1fr auto 20px;align-items:center;gap:6px;padding:3px 2px;display:grid}.NPLLIq_balanceRow+.NPLLIq_balanceRow{border-top:1px dashed var(--dsw-alias-border-l1)}.NPLLIq_balanceRowName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-weight:500;overflow:hidden}.NPLLIq_balanceRowValue{text-align:right;font-weight:600}.NPLLIq_balanceRowRefresh{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceRowRefresh:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceRowRefresh:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_balanceValueOk{color:var(--dsw-alias-label-primary)}.NPLLIq_balanceValueLow{color:var(--dsw-alias-state-warn-primary)}.NPLLIq_balanceValueError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_balanceStateHint{color:var(--dsw-alias-label-secondary);font-style:italic;font-weight:500}.NPLLIq_balanceStateError{color:var(--dsw-alias-state-error-primary);font-weight:500}.NPLLIq_balanceLastLine{border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);margin-top:6px;padding-top:5px;font-size:10px}.NPLLIq_balanceBar{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;justify-content:space-between;align-items:center;gap:6px;padding:5px 12px;font-size:11px;display:flex}.NPLLIq_balanceBarText{text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;min-width:0;font-weight:600;display:inline-flex;overflow:hidden}.NPLLIq_balanceBarBadge{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border-radius:4px;flex:none;padding:0 4px;font-size:10px;font-weight:600}.NPLLIq_balanceBarDim{color:var(--dsw-alias-label-secondary);font-weight:500}.NPLLIq_balanceBarLow{color:var(--dsw-alias-state-warn-primary)}.NPLLIq_balanceBarError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_balanceBarRefresh{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_balanceBarRefresh:hover:not(:disabled){color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_balanceBarRefresh:disabled{opacity:.4;cursor:not-allowed}.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;pointer-events:auto;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;pointer-events:auto;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}.NPLLIq_keyRow{align-items:center;gap:8px;margin-top:6px;display:flex}.NPLLIq_keySaveBtn{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;border-radius:4px;flex:none;padding:4px 10px;font-size:12px}.NPLLIq_keySaveBtn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_keySaveBtn:disabled{opacity:.5;cursor:not-allowed}.NPLLIq_keyBadgeOk,.NPLLIq_keyBadgeOff{white-space:nowrap;border-radius:999px;padding:3px 7px;font-size:11px;line-height:1}.NPLLIq_keyBadgeOk{color:var(--dsw-alias-state-success-primary,#2f9e44);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#2f9e44) 14%, transparent)}.NPLLIq_keyBadgeOff{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2,#0000000f)}.NPLLIq_keyError{word-break:break-word;color:var(--dsw-alias-state-error-primary,#e03131);margin-top:4px;font-size:11px;line-height:1.4}";
256
256
  const tagId$1 = "@jxgame2020/dsh-token-quota/TokenQuotaPanel.module.css";
257
257
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
258
258
  const tag = document.createElement("style");
@@ -262,142 +262,147 @@ window.__ModuleLoader__.load({
262
262
  document.head.appendChild(tag);
263
263
  }
264
264
  var TokenQuotaPanel_module_css_default = {
265
- "dialogActions": "NPLLIq_dialogActions",
266
- "balanceValueOk": "NPLLIq_balanceValueOk",
267
- "logTable": "NPLLIq_logTable",
268
- "noteWinBar": "NPLLIq_noteWinBar",
269
- "row": "NPLLIq_row",
270
- "noteMenu": "NPLLIq_noteMenu",
271
- "dialogTabActive": "NPLLIq_dialogTabActive",
272
- "header": "NPLLIq_header",
265
+ "tabIcon": "NPLLIq_tabIcon",
266
+ "copyBtn": "NPLLIq_copyBtn",
267
+ "balanceBarDim": "NPLLIq_balanceBarDim",
268
+ "selectBtn": "NPLLIq_selectBtn",
269
+ "radioRow": "NPLLIq_radioRow",
270
+ "tab": "NPLLIq_tab",
271
+ "rowHeader": "NPLLIq_rowHeader",
272
+ "logModelCol": "NPLLIq_logModelCol",
273
+ "balanceRowName": "NPLLIq_balanceRowName",
274
+ "dialogSection": "NPLLIq_dialogSection",
275
+ "dialogOverlay": "NPLLIq_dialogOverlay",
276
+ "headerText": "NPLLIq_headerText",
277
+ "balanceStateHint": "NPLLIq_balanceStateHint",
273
278
  "noteMenuBackdrop": "NPLLIq_noteMenuBackdrop",
274
- "noteWin": "NPLLIq_noteWin",
275
- "currentBadge": "NPLLIq_currentBadge",
276
- "body": "NPLLIq_body",
277
- "balanceWin": "NPLLIq_balanceWin",
279
+ "balanceWinHeader": "NPLLIq_balanceWinHeader",
280
+ "balanceRowHeader": "NPLLIq_balanceRowHeader",
278
281
  "noteWinResize": "NPLLIq_noteWinResize",
279
- "settingsDialog": "NPLLIq_settingsDialog",
280
- "settingsBtn": "NPLLIq_settingsBtn",
281
- "logUsedCol": "NPLLIq_logUsedCol",
282
- "balanceToggle": "NPLLIq_balanceToggle",
283
- "balanceRow": "NPLLIq_balanceRow",
284
- "balanceStateError": "NPLLIq_balanceStateError",
285
- "fillIdle": "NPLLIq_fillIdle",
286
- "balanceSortBtn": "NPLLIq_balanceSortBtn",
287
- "monitorList": "NPLLIq_monitorList",
288
- "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
289
- "noticeError": "NPLLIq_noticeError",
290
- "panelDimStrong": "NPLLIq_panelDimStrong",
291
- "dialogLabel": "NPLLIq_dialogLabel",
292
- "logDayCol": "NPLLIq_logDayCol",
293
- "noteWinCollapsed": "NPLLIq_noteWinCollapsed",
282
+ "notice": "NPLLIq_notice",
283
+ "panel": "NPLLIq_panel",
284
+ "logPagerPages": "NPLLIq_logPagerPages",
285
+ "keyBadgeOff": "NPLLIq_keyBadgeOff",
294
286
  "noteWinGripBar": "NPLLIq_noteWinGripBar",
295
- "controls": "NPLLIq_controls",
296
- "noteWinText": "NPLLIq_noteWinText",
297
- "dialogTab": "NPLLIq_dialogTab",
298
- "logPagerInfo": "NPLLIq_logPagerInfo",
299
- "logModelCol": "NPLLIq_logModelCol",
300
- "balanceBarBadge": "NPLLIq_balanceBarBadge",
301
- "rowMeta": "NPLLIq_rowMeta",
302
- "rowHeader": "NPLLIq_rowHeader",
303
- "noteMenuItem": "NPLLIq_noteMenuItem",
304
- "dialogTabs": "NPLLIq_dialogTabs",
305
- "logClearDate": "NPLLIq_logClearDate",
306
- "noteNew": "NPLLIq_noteNew",
287
+ "checkErrorHint": "NPLLIq_checkErrorHint",
288
+ "logTable": "NPLLIq_logTable",
289
+ "dialogLabel": "NPLLIq_dialogLabel",
290
+ "noteChipOpen": "NPLLIq_noteChipOpen",
307
291
  "balanceLastLine": "NPLLIq_balanceLastLine",
308
- "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
309
- "copyBtnDone": "NPLLIq_copyBtnDone",
310
- "panelDim": "NPLLIq_panelDim",
311
- "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
312
- "tab": "NPLLIq_tab",
313
- "logPagerBtn": "NPLLIq_logPagerBtn",
314
- "balanceBarDim": "NPLLIq_balanceBarDim",
315
- "resetSelect": "NPLLIq_resetSelect",
316
- "dialogBody": "NPLLIq_dialogBody",
317
- "headerActions": "NPLLIq_headerActions",
318
- "balanceBarLow": "NPLLIq_balanceBarLow",
319
- "balanceRowValue": "NPLLIq_balanceRowValue",
320
- "dialogHint": "NPLLIq_dialogHint",
321
- "tabIcon": "NPLLIq_tabIcon",
322
- "selectBtn": "NPLLIq_selectBtn",
323
- "switch": "NPLLIq_switch",
324
- "panel": "NPLLIq_panel",
325
- "fillOver": "NPLLIq_fillOver",
326
- "subtitle": "NPLLIq_subtitle",
327
- "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
328
- "balanceValueLow": "NPLLIq_balanceValueLow",
329
- "notice": "NPLLIq_notice",
292
+ "monitorList": "NPLLIq_monitorList",
293
+ "logSearch": "NPLLIq_logSearch",
294
+ "bar": "NPLLIq_bar",
295
+ "balanceRefreshAll": "NPLLIq_balanceRefreshAll",
296
+ "save": "NPLLIq_save",
330
297
  "balanceBar": "NPLLIq_balanceBar",
331
- "dialogHeader": "NPLLIq_dialogHeader",
332
- "balanceWinHeader": "NPLLIq_balanceWinHeader",
333
- "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
334
- "upgradeClose": "NPLLIq_upgradeClose",
335
- "rowName": "NPLLIq_rowName",
336
- "noteWinTitleText": "NPLLIq_noteWinTitleText",
337
- "copyBtn": "NPLLIq_copyBtn",
338
- "rowDragging": "NPLLIq_rowDragging",
339
- "noteChipOpen": "NPLLIq_noteChipOpen",
298
+ "balanceSortBtn": "NPLLIq_balanceSortBtn",
340
299
  "balanceWinTitle": "NPLLIq_balanceWinTitle",
341
- "upgradeCommand": "NPLLIq_upgradeCommand",
342
- "balanceStateHint": "NPLLIq_balanceStateHint",
300
+ "logClearBtn": "NPLLIq_logClearBtn",
301
+ "noteWinBar": "NPLLIq_noteWinBar",
302
+ "logClearDialog": "NPLLIq_logClearDialog",
303
+ "noteMenu": "NPLLIq_noteMenu",
304
+ "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
305
+ "monitorHint": "NPLLIq_monitorHint",
306
+ "resetSelect": "NPLLIq_resetSelect",
307
+ "subtitle": "NPLLIq_subtitle",
308
+ "rowDropTarget": "NPLLIq_rowDropTarget",
309
+ "settingsBtnActive": "NPLLIq_settingsBtnActive",
310
+ "notesBar": "NPLLIq_notesBar",
311
+ "upgradeCommands": "NPLLIq_upgradeCommands",
312
+ "logDayCol": "NPLLIq_logDayCol",
313
+ "balanceStateError": "NPLLIq_balanceStateError",
343
314
  "upgradeHint": "NPLLIq_upgradeHint",
344
- "checkErrorHint": "NPLLIq_checkErrorHint",
345
- "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
346
- "balanceToggleOpen": "NPLLIq_balanceToggleOpen",
347
- "fullNotice": "NPLLIq_fullNotice",
315
+ "controls": "NPLLIq_controls",
316
+ "input": "NPLLIq_input",
348
317
  "noteChip": "NPLLIq_noteChip",
349
- "balanceValueError": "NPLLIq_balanceValueError",
318
+ "logPagerBtn": "NPLLIq_logPagerBtn",
319
+ "logDialog": "NPLLIq_logDialog",
320
+ "dialogHeader": "NPLLIq_dialogHeader",
350
321
  "monitorName": "NPLLIq_monitorName",
351
- "noteWinBtn": "NPLLIq_noteWinBtn",
322
+ "noteWinCollapsed": "NPLLIq_noteWinCollapsed",
323
+ "panelDimStrong": "NPLLIq_panelDimStrong",
324
+ "header": "NPLLIq_header",
325
+ "switch": "NPLLIq_switch",
326
+ "balanceBarBadge": "NPLLIq_balanceBarBadge",
327
+ "fillIdle": "NPLLIq_fillIdle",
328
+ "balanceBarLow": "NPLLIq_balanceBarLow",
329
+ "gearBtn": "NPLLIq_gearBtn",
330
+ "dialogBtn": "NPLLIq_dialogBtn",
331
+ "dialogTabs": "NPLLIq_dialogTabs",
332
+ "currentBadge": "NPLLIq_currentBadge",
333
+ "rowDragging": "NPLLIq_rowDragging",
334
+ "fillWarn": "NPLLIq_fillWarn",
352
335
  "balanceRowRefresh": "NPLLIq_balanceRowRefresh",
353
- "resetRow": "NPLLIq_resetRow",
354
- "logSearch": "NPLLIq_logSearch",
355
- "monitorHint": "NPLLIq_monitorHint",
336
+ "body": "NPLLIq_body",
337
+ "title": "NPLLIq_title",
338
+ "keyRow": "NPLLIq_keyRow",
339
+ "versionNew": "NPLLIq_versionNew",
340
+ "noteWinText": "NPLLIq_noteWinText",
341
+ "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
342
+ "balanceToggleOpen": "NPLLIq_balanceToggleOpen",
343
+ "upgradeBannerText": "NPLLIq_upgradeBannerText",
356
344
  "logPagerControls": "NPLLIq_logPagerControls",
357
- "save": "NPLLIq_save",
358
- "logClearDialog": "NPLLIq_logClearDialog",
359
- "tabLabel": "NPLLIq_tabLabel",
360
- "balanceRefreshAll": "NPLLIq_balanceRefreshAll",
345
+ "balanceWin": "NPLLIq_balanceWin",
346
+ "noteWin": "NPLLIq_noteWin",
361
347
  "noteNewPlus": "NPLLIq_noteNewPlus",
362
- "balanceWinBody": "NPLLIq_balanceWinBody",
363
- "collapse": "NPLLIq_collapse",
364
- "dialogSection": "NPLLIq_dialogSection",
365
- "dialogClose": "NPLLIq_dialogClose",
366
- "balanceRowName": "NPLLIq_balanceRowName",
367
- "dialog": "NPLLIq_dialog",
368
- "upgradeCommands": "NPLLIq_upgradeCommands",
348
+ "rowDrag": "NPLLIq_rowDrag",
369
349
  "logPager": "NPLLIq_logPager",
370
- "fillWarn": "NPLLIq_fillWarn",
371
- "rowDropTarget": "NPLLIq_rowDropTarget",
372
- "dialogOverlay": "NPLLIq_dialogOverlay",
350
+ "balanceValueError": "NPLLIq_balanceValueError",
351
+ "upgradeBanner": "NPLLIq_upgradeBanner",
352
+ "collapse": "NPLLIq_collapse",
353
+ "copyBtnDone": "NPLLIq_copyBtnDone",
354
+ "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
373
355
  "checkBtn": "NPLLIq_checkBtn",
374
- "notesBar": "NPLLIq_notesBar",
375
- "dialogBtn": "NPLLIq_dialogBtn",
376
- "radioRow": "NPLLIq_radioRow",
377
- "balanceBarText": "NPLLIq_balanceBarText",
378
- "monitorRow": "NPLLIq_monitorRow",
379
- "balanceRowHeader": "NPLLIq_balanceRowHeader",
380
- "noteWinTitle": "NPLLIq_noteWinTitle",
381
- "upgradeBannerText": "NPLLIq_upgradeBannerText",
382
- "balanceBarRefresh": "NPLLIq_balanceBarRefresh",
383
- "logToolbar": "NPLLIq_logToolbar",
356
+ "dialogTabActive": "NPLLIq_dialogTabActive",
357
+ "noteWinTitleText": "NPLLIq_noteWinTitleText",
358
+ "keyBadgeOk": "NPLLIq_keyBadgeOk",
359
+ "keyError": "NPLLIq_keyError",
360
+ "settingsBtn": "NPLLIq_settingsBtn",
361
+ "dialog": "NPLLIq_dialog",
362
+ "noteMenuItem": "NPLLIq_noteMenuItem",
363
+ "balanceRow": "NPLLIq_balanceRow",
364
+ "balanceValueLow": "NPLLIq_balanceValueLow",
384
365
  "balanceBarError": "NPLLIq_balanceBarError",
366
+ "rowMeta": "NPLLIq_rowMeta",
367
+ "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
368
+ "balanceToggle": "NPLLIq_balanceToggle",
369
+ "balanceBarText": "NPLLIq_balanceBarText",
370
+ "balanceWinBody": "NPLLIq_balanceWinBody",
371
+ "noteNew": "NPLLIq_noteNew",
372
+ "logUsedCol": "NPLLIq_logUsedCol",
373
+ "logPagerInfo": "NPLLIq_logPagerInfo",
374
+ "rowName": "NPLLIq_rowName",
375
+ "dialogActions": "NPLLIq_dialogActions",
376
+ "balanceValueOk": "NPLLIq_balanceValueOk",
377
+ "settingsDialog": "NPLLIq_settingsDialog",
385
378
  "version": "NPLLIq_version",
386
- "upgradeBanner": "NPLLIq_upgradeBanner",
379
+ "upgradeClose": "NPLLIq_upgradeClose",
380
+ "balanceRowValue": "NPLLIq_balanceRowValue",
381
+ "fillOver": "NPLLIq_fillOver",
382
+ "panelDim": "NPLLIq_panelDim",
383
+ "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
384
+ "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
385
+ "row": "NPLLIq_row",
386
+ "tabLabel": "NPLLIq_tabLabel",
387
+ "dialogHint": "NPLLIq_dialogHint",
388
+ "dialogClose": "NPLLIq_dialogClose",
387
389
  "logHeader": "NPLLIq_logHeader",
388
390
  "logScroll": "NPLLIq_logScroll",
389
- "bar": "NPLLIq_bar",
390
- "gearBtn": "NPLLIq_gearBtn",
391
- "headerText": "NPLLIq_headerText",
392
- "input": "NPLLIq_input",
393
- "logDialog": "NPLLIq_logDialog",
394
- "versionNew": "NPLLIq_versionNew",
395
- "logPagerPages": "NPLLIq_logPagerPages",
396
- "logClearBtn": "NPLLIq_logClearBtn",
391
+ "monitorRow": "NPLLIq_monitorRow",
397
392
  "dialogTitle": "NPLLIq_dialogTitle",
398
- "settingsBtnActive": "NPLLIq_settingsBtnActive",
399
- "title": "NPLLIq_title",
400
- "rowDrag": "NPLLIq_rowDrag"
393
+ "balanceBarRefresh": "NPLLIq_balanceBarRefresh",
394
+ "noteWinBtn": "NPLLIq_noteWinBtn",
395
+ "logToolbar": "NPLLIq_logToolbar",
396
+ "keySaveBtn": "NPLLIq_keySaveBtn",
397
+ "upgradeCommand": "NPLLIq_upgradeCommand",
398
+ "resetRow": "NPLLIq_resetRow",
399
+ "headerActions": "NPLLIq_headerActions",
400
+ "dialogTab": "NPLLIq_dialogTab",
401
+ "dialogBody": "NPLLIq_dialogBody",
402
+ "fullNotice": "NPLLIq_fullNotice",
403
+ "noticeError": "NPLLIq_noticeError",
404
+ "logClearDate": "NPLLIq_logClearDate",
405
+ "noteWinTitle": "NPLLIq_noteWinTitle"
401
406
  };
402
407
  //#endregion
403
408
  //#region lib/types/client/TokenQuotaPanel.js
@@ -535,13 +540,18 @@ window.__ModuleLoader__.load({
535
540
  * @param props - composed slot props.
536
541
  * @returns the panel element tree.
537
542
  */
538
- function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, useStore, actions, useSessions }) {
543
+ function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, checkTranscribeKey, saveTranscribeKey, useStore, actions, useSessions }) {
539
544
  const [collapsed, setCollapsed] = (0, react.useState)(false);
540
545
  const [drafts, setDrafts] = (0, react.useState)({});
541
546
  const [editingKey, setEditingKey] = (0, react.useState)(null);
542
547
  const [hovered, setHovered] = (0, react.useState)(false);
543
548
  const [inputActive, setInputActive] = (0, react.useState)(false);
544
549
  const [settingsTab, setSettingsTab] = (0, react.useState)("quota");
550
+ const [keyDraft, setKeyDraft] = (0, react.useState)("");
551
+ const [keyConfigured, setKeyConfigured] = (0, react.useState)(null);
552
+ const [keySaving, setKeySaving] = (0, react.useState)(false);
553
+ const [keySaved, setKeySaved] = (0, react.useState)(false);
554
+ const [keyError, setKeyError] = (0, react.useState)(null);
545
555
  const [dragKey, setDragKey] = (0, react.useState)(null);
546
556
  const [dropKey, setDropKey] = (0, react.useState)(null);
547
557
  const storedNotes = useStore((s) => s.notes);
@@ -729,6 +739,44 @@ window.__ModuleLoader__.load({
729
739
  (0, react.useEffect)(() => {
730
740
  if (sessionId !== void 0) load(sessionId);
731
741
  }, [sessionId, load]);
742
+ (0, react.useEffect)(() => {
743
+ if (settingsTab !== "transcribe") return;
744
+ const ref = transcribe.apiKeyEnv;
745
+ if (ref === "") return;
746
+ let cancelled = false;
747
+ checkTranscribeKey(ref).then((configured) => {
748
+ if (!cancelled) {
749
+ setKeyConfigured(configured);
750
+ setKeySaved(false);
751
+ }
752
+ });
753
+ return () => {
754
+ cancelled = true;
755
+ };
756
+ }, [
757
+ settingsTab,
758
+ transcribe.apiKeyEnv,
759
+ checkTranscribeKey
760
+ ]);
761
+ /**
762
+ * Write the staged transcription key through the credential seam, then
763
+ * re-read presence. The secret is never read back, so the badge reflects
764
+ * what the Host reports rather than what was typed.
765
+ */
766
+ const saveKey = () => {
767
+ const ref = transcribe.apiKeyEnv;
768
+ if (ref === "" || keyDraft === "") return;
769
+ setKeySaving(true);
770
+ setKeyError(null);
771
+ saveTranscribeKey(ref, keyDraft).then((result) => {
772
+ setKeySaving(false);
773
+ if (result.ok) {
774
+ setKeyDraft("");
775
+ setKeyConfigured(true);
776
+ setKeySaved(true);
777
+ } else setKeyError(result.error ?? t("transcribeKeyFailed"));
778
+ });
779
+ };
732
780
  (0, react.useEffect)(() => {
733
781
  const onFocusIn = (event) => {
734
782
  const target = event.target;
@@ -1068,13 +1116,13 @@ window.__ModuleLoader__.load({
1068
1116
  title: t("upgradeAvailableHint"),
1069
1117
  children: [
1070
1118
  "v",
1071
- "0.1.43",
1119
+ "0.1.44",
1072
1120
  " → v",
1073
1121
  upgrade.latestVersion
1074
1122
  ]
1075
1123
  }) : (0, react_jsx_runtime.jsxs)("span", {
1076
1124
  className: TokenQuotaPanel_module_css_default.version,
1077
- children: ["v", "0.1.43"]
1125
+ children: ["v", "0.1.44"]
1078
1126
  })]
1079
1127
  })
1080
1128
  }),
@@ -1738,6 +1786,50 @@ window.__ModuleLoader__.load({
1738
1786
  className: TokenQuotaPanel_module_css_default.dialogHint,
1739
1787
  children: t("transcribeApiKeyEnvHint")
1740
1788
  }),
1789
+ (0, react_jsx_runtime.jsxs)("label", {
1790
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1791
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("transcribeKeyLabel") }), (0, react_jsx_runtime.jsx)("input", {
1792
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1793
+ type: "password",
1794
+ autoComplete: "off",
1795
+ value: keyDraft,
1796
+ placeholder: keyConfigured === true ? t("transcribeKeyPlaceholderSet") : t("transcribeKeyPlaceholder"),
1797
+ onChange: (event) => {
1798
+ setKeyDraft(event.target.value);
1799
+ setKeySaved(false);
1800
+ setKeyError(null);
1801
+ },
1802
+ onKeyDown: (event) => {
1803
+ if (event.key === "Enter") {
1804
+ event.preventDefault();
1805
+ saveKey();
1806
+ }
1807
+ }
1808
+ })]
1809
+ }),
1810
+ (0, react_jsx_runtime.jsx)("div", {
1811
+ className: TokenQuotaPanel_module_css_default.dialogHint,
1812
+ children: t("transcribeKeyHint")
1813
+ }),
1814
+ (0, react_jsx_runtime.jsxs)("div", {
1815
+ className: TokenQuotaPanel_module_css_default.keyRow,
1816
+ children: [(0, react_jsx_runtime.jsx)("button", {
1817
+ type: "button",
1818
+ className: TokenQuotaPanel_module_css_default.keySaveBtn,
1819
+ disabled: keyDraft === "" || keySaving,
1820
+ onClick: () => {
1821
+ saveKey();
1822
+ },
1823
+ children: keySaving ? t("transcribeKeySaving") : t("transcribeKeySave")
1824
+ }), (0, react_jsx_runtime.jsx)("span", {
1825
+ className: keyConfigured === true ? TokenQuotaPanel_module_css_default.keyBadgeOk : TokenQuotaPanel_module_css_default.keyBadgeOff,
1826
+ children: keySaved ? t("transcribeKeySaved") : keyConfigured === true ? t("transcribeKeyConfigured") : t("transcribeKeyMissing")
1827
+ })]
1828
+ }),
1829
+ keyError !== null && (0, react_jsx_runtime.jsx)("div", {
1830
+ className: TokenQuotaPanel_module_css_default.keyError,
1831
+ children: keyError
1832
+ }),
1741
1833
  (0, react_jsx_runtime.jsxs)("label", {
1742
1834
  className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1743
1835
  children: [(0, react_jsx_runtime.jsx)("span", { children: t("transcribeModelLabel") }), (0, react_jsx_runtime.jsx)("input", {
@@ -2890,13 +2982,13 @@ window.__ModuleLoader__.load({
2890
2982
  document.head.appendChild(tag);
2891
2983
  }
2892
2984
  var mic_module_css_default = {
2893
- "micPulse": "KCoVpa_micPulse",
2894
2985
  "micErr": "KCoVpa_micErr",
2895
2986
  "micErrTip": "KCoVpa_micErrTip",
2987
+ "micBtn": "KCoVpa_micBtn",
2896
2988
  "micRec": "KCoVpa_micRec",
2897
2989
  "micBusy": "KCoVpa_micBusy",
2898
- "micBtn": "KCoVpa_micBtn",
2899
- "micWrap": "KCoVpa_micWrap"
2990
+ "micWrap": "KCoVpa_micWrap",
2991
+ "micPulse": "KCoVpa_micPulse"
2900
2992
  };
2901
2993
  //#endregion
2902
2994
  //#region lib/types/client/mic.js
@@ -3088,8 +3180,18 @@ window.__ModuleLoader__.load({
3088
3180
  transcribeEnabledHint: "在对话框右上角显示麦克风按钮",
3089
3181
  transcribeBaseURLLabel: "接口地址",
3090
3182
  transcribeBaseURLHint: "OpenAI 兼容的转录接口 base URL",
3091
- transcribeApiKeyEnvLabel: "API Key 环境变量",
3092
- transcribeApiKeyEnvHint: "存有 API Key 的凭证变量名(在 Models 页或 credentials 配置)",
3183
+ transcribeApiKeyEnvLabel: "凭证名称",
3184
+ transcribeApiKeyEnvHint: "密钥在凭证库中保存的名称,一般无需修改",
3185
+ transcribeKeyLabel: "API Key",
3186
+ transcribeKeyHint: "在此填入密钥并点「保存」,密钥会写入 DSH 凭证库(保存后不会回显)",
3187
+ transcribeKeyPlaceholder: "粘贴 API Key",
3188
+ transcribeKeyPlaceholderSet: "已配置,填入新值可覆盖",
3189
+ transcribeKeySave: "保存",
3190
+ transcribeKeySaving: "保存中…",
3191
+ transcribeKeySaved: "已保存",
3192
+ transcribeKeyConfigured: "已配置",
3193
+ transcribeKeyMissing: "未配置",
3194
+ transcribeKeyFailed: "保存失败",
3093
3195
  transcribeModelLabel: "模型",
3094
3196
  transcribeModelHint: "语音转文本模型名",
3095
3197
  reorderHint: "拖动排序",
@@ -3217,8 +3319,18 @@ window.__ModuleLoader__.load({
3217
3319
  transcribeEnabledHint: "Show a mic button in the top-right of the composer",
3218
3320
  transcribeBaseURLLabel: "Base URL",
3219
3321
  transcribeBaseURLHint: "OpenAI-compatible transcription endpoint base URL",
3220
- transcribeApiKeyEnvLabel: "API key env var",
3221
- transcribeApiKeyEnvHint: "Credential variable name holding the API key (Models page or credentials)",
3322
+ transcribeApiKeyEnvLabel: "Credential name",
3323
+ transcribeApiKeyEnvHint: "Name the key is stored under in the credential store; usually unchanged",
3324
+ transcribeKeyLabel: "API key",
3325
+ transcribeKeyHint: "Paste the key here and press Save — it is written to the DSH credential store and never read back",
3326
+ transcribeKeyPlaceholder: "Paste API key",
3327
+ transcribeKeyPlaceholderSet: "Configured — enter a new value to replace",
3328
+ transcribeKeySave: "Save",
3329
+ transcribeKeySaving: "Saving…",
3330
+ transcribeKeySaved: "Saved",
3331
+ transcribeKeyConfigured: "Configured",
3332
+ transcribeKeyMissing: "Not configured",
3333
+ transcribeKeyFailed: "Save failed",
3222
3334
  transcribeModelLabel: "Model",
3223
3335
  transcribeModelHint: "Speech-to-text model name",
3224
3336
  reorderHint: "Drag to reorder",
@@ -3328,7 +3440,8 @@ window.__ModuleLoader__.load({
3328
3440
  "locale",
3329
3441
  "settingsScope",
3330
3442
  "remote",
3331
- "remote.session"
3443
+ "remote.session",
3444
+ "remote.credentials"
3332
3445
  ];
3333
3446
  /**
3334
3447
  * Client plugin body: poll the Host snapshot route, run the full-quota
@@ -3666,6 +3779,36 @@ window.__ModuleLoader__.load({
3666
3779
  scope.set("transcribe", settings);
3667
3780
  };
3668
3781
  /**
3782
+ * Read whether the transcription credential reference currently holds a key,
3783
+ * so the settings page can show 已配置 / 未配置 without ever reading the
3784
+ * secret back (the wire carries it in one direction only).
3785
+ */
3786
+ const checkTranscribeKey = async (ref) => {
3787
+ try {
3788
+ const result = await ctx.remote.credentials.describe([ref]);
3789
+ if (!result.ok) return false;
3790
+ return result.value[ref]?.configured === true;
3791
+ } catch {
3792
+ return false;
3793
+ }
3794
+ };
3795
+ /**
3796
+ * Store the transcription API key through the credential seam, so it lives
3797
+ * in the same credential store the Host resolves from — the user never has
3798
+ * to edit a file by hand.
3799
+ */
3800
+ const saveTranscribeKey = async (ref, value) => {
3801
+ try {
3802
+ await ctx.remote.credentials.set(ref, value);
3803
+ return { ok: true };
3804
+ } catch (error) {
3805
+ return {
3806
+ ok: false,
3807
+ error: error instanceof Error ? error.message : String(error)
3808
+ };
3809
+ }
3810
+ };
3811
+ /**
3669
3812
  * Send a recorded audio blob to the Host, which forwards it to the
3670
3813
  * configured OpenAI-compatible transcription endpoint. Resolves with the
3671
3814
  * recognised text.
@@ -3819,7 +3962,9 @@ window.__ModuleLoader__.load({
3819
3962
  saveNotes,
3820
3963
  setBalanceSettings,
3821
3964
  refreshBalance,
3822
- setTranscribeSettings
3965
+ setTranscribeSettings,
3966
+ checkTranscribeKey,
3967
+ saveTranscribeKey
3823
3968
  };
3824
3969
  };
3825
3970
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({
package/lib/index.js CHANGED
@@ -651,7 +651,7 @@ var TokenQuotaService = class TokenQuotaService extends Service {
651
651
  return this.upgradeCheck;
652
652
  }
653
653
  async doRefreshUpgrade() {
654
- const current = "0.1.43";
654
+ const current = "0.1.44";
655
655
  let latest;
656
656
  try {
657
657
  const response = await fetch(REGISTRY_LATEST_URL, {
@@ -38,6 +38,13 @@ export interface TokenQuotaPanelInjected {
38
38
  setMusicOnlyCurrentSession: (only: boolean) => void;
39
39
  /** Persist the voice transcription settings (endpoint, key ref, model). */
40
40
  setTranscribeSettings: (settings: TokenQuotaTranscribeSettings) => void;
41
+ /** Read whether the transcription credential reference currently holds a key. */
42
+ checkTranscribeKey: (ref: string) => Promise<boolean>;
43
+ /** Store the transcription API key through the credential seam. */
44
+ saveTranscribeKey: (ref: string, value: string) => Promise<{
45
+ ok: boolean;
46
+ error?: string;
47
+ }>;
41
48
  /** Ask the Host to check the registry right now, then refresh the snapshot. */
42
49
  checkUpdatesNow: () => void;
43
50
  /** Ask the Host to clear log entries before a date, then refresh the log. */
@@ -50,5 +57,5 @@ export type TokenQuotaPanelComponentProps = PropsRuntime<'shell.overlay'> & Prop
50
57
  * @param props - composed slot props.
51
58
  * @returns the panel element tree.
52
59
  */
53
- export declare function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, useStore, actions, useSessions, }: TokenQuotaPanelComponentProps): import("react").JSX.Element;
60
+ export declare function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, checkTranscribeKey, saveTranscribeKey, useStore, actions, useSessions, }: TokenQuotaPanelComponentProps): import("react").JSX.Element;
54
61
  //# sourceMappingURL=TokenQuotaPanel.d.ts.map
@@ -149,7 +149,7 @@ function loadPanelPos() {
149
149
  * @param props - composed slot props.
150
150
  * @returns the panel element tree.
151
151
  */
152
- export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, useStore, actions, useSessions, }) {
152
+ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setBalanceSettings, refreshBalance, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, setTranscribeSettings, checkTranscribeKey, saveTranscribeKey, useStore, actions, useSessions, }) {
153
153
  const [collapsed, setCollapsed] = useState(false);
154
154
  const [drafts, setDrafts] = useState({});
155
155
  const [editingKey, setEditingKey] = useState(null);
@@ -160,6 +160,13 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
160
160
  const [inputActive, setInputActive] = useState(false);
161
161
  // Active settings-dialog tab: quota limits vs. live-music vs. misc.
162
162
  const [settingsTab, setSettingsTab] = useState('quota');
163
+ // Transcription API-key editor: the staged secret (never read back from the
164
+ // Host), whether the Host already holds one, and the last save outcome.
165
+ const [keyDraft, setKeyDraft] = useState('');
166
+ const [keyConfigured, setKeyConfigured] = useState(null);
167
+ const [keySaving, setKeySaving] = useState(false);
168
+ const [keySaved, setKeySaved] = useState(false);
169
+ const [keyError, setKeyError] = useState(null);
163
170
  // Drag-to-reorder state for the model rows: the key being dragged and
164
171
  // the key currently hovered as the drop target.
165
172
  const [dragKey, setDragKey] = useState(null);
@@ -381,6 +388,47 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
381
388
  if (sessionId !== undefined)
382
389
  load(sessionId);
383
390
  }, [sessionId, load]);
391
+ // Ask the Host whether the transcription credential reference already holds
392
+ // a key, so the settings page can show 已配置 / 未配置. The secret itself is
393
+ // never readable over the wire — only presence is.
394
+ useEffect(() => {
395
+ if (settingsTab !== 'transcribe')
396
+ return;
397
+ const ref = transcribe.apiKeyEnv;
398
+ if (ref === '')
399
+ return;
400
+ let cancelled = false;
401
+ void checkTranscribeKey(ref).then((configured) => {
402
+ if (!cancelled) {
403
+ setKeyConfigured(configured);
404
+ setKeySaved(false);
405
+ }
406
+ });
407
+ return () => { cancelled = true; };
408
+ }, [settingsTab, transcribe.apiKeyEnv, checkTranscribeKey]);
409
+ /**
410
+ * Write the staged transcription key through the credential seam, then
411
+ * re-read presence. The secret is never read back, so the badge reflects
412
+ * what the Host reports rather than what was typed.
413
+ */
414
+ const saveKey = () => {
415
+ const ref = transcribe.apiKeyEnv;
416
+ if (ref === '' || keyDraft === '')
417
+ return;
418
+ setKeySaving(true);
419
+ setKeyError(null);
420
+ void saveTranscribeKey(ref, keyDraft).then((result) => {
421
+ setKeySaving(false);
422
+ if (result.ok) {
423
+ setKeyDraft('');
424
+ setKeyConfigured(true);
425
+ setKeySaved(true);
426
+ }
427
+ else {
428
+ setKeyError(result.error ?? t('transcribeKeyFailed'));
429
+ }
430
+ });
431
+ };
384
432
  // Track whether any text input (composer, search, dialogs) currently has
385
433
  // focus, so the panel can dim while the user types elsewhere.
386
434
  useEffect(() => {
@@ -818,7 +866,18 @@ export function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored,
818
866
  hour: reset?.hour ?? 0,
819
867
  minute: Number(event.target.value),
820
868
  });
821
- }, children: Array.from({ length: 12 }, (_, i) => i * 5).map(minute => (_jsxs("option", { value: minute, children: [String(minute).padStart(2, '0'), " \u5206"] }, minute))) })] })] }), _jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: dimWhenIdle, onChange: (event) => { setDimWhenIdle(event.target.checked); } }), _jsx("span", { children: t('dimWhenIdleLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('dimWhenIdleHint') })] })] })), settingsTab === 'music' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: musicEnabled, onChange: (event) => { setMusicEnabled(event.target.checked); } }), _jsx("span", { children: t('musicLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('musicHint') })] }), musicEnabled && (_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('musicVolume') }), _jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: musicVolume, onChange: (event) => { setMusicVolume(Number(event.target.value)); } })] }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('musicStyle') }), _jsxs("select", { value: musicStyle, onChange: (event) => { setMusicStyle(event.target.value); }, children: [_jsx("option", { value: "major", children: t('musicStyleMajor') }), _jsx("option", { value: "minor", children: t('musicStyleMinor') }), _jsx("option", { value: "pentatonic", children: t('musicStylePentatonic') })] })] }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: musicOnlyCurrentSession, onChange: (event) => { setMusicOnlyCurrentSession(event.target.checked); } }), _jsx("span", { children: t('musicOnlyCurrentSessionLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('musicOnlyCurrentSessionHint') })] }))] })), settingsTab === 'transcribe' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: transcribe.enabled, onChange: (event) => { setTranscribeSettings({ ...transcribe, enabled: event.target.checked }); } }), _jsx("span", { children: t('transcribeEnabledLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeEnabledHint') })] }), transcribe.enabled && (_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeBaseURLLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.baseURL, onChange: (event) => { setTranscribeSettings({ ...transcribe, baseURL: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeBaseURLHint') }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeApiKeyEnvLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.apiKeyEnv, onChange: (event) => { setTranscribeSettings({ ...transcribe, apiKeyEnv: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeApiKeyEnvHint') }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeModelLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.model, onChange: (event) => { setTranscribeSettings({ ...transcribe, model: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeModelHint') })] }))] })), settingsTab === 'other' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("div", { className: css.checkUpdatesRow, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: checkUpdates, onChange: (event) => { setCheckUpdates(event.target.checked); } }), _jsx("span", { children: t('checkUpdatesLabel') })] }), _jsx("button", { type: "button", className: css.checkBtn, disabled: checkingUpdates, onClick: checkUpdatesNow, children: checkingUpdates
869
+ }, children: Array.from({ length: 12 }, (_, i) => i * 5).map(minute => (_jsxs("option", { value: minute, children: [String(minute).padStart(2, '0'), " \u5206"] }, minute))) })] })] }), _jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: dimWhenIdle, onChange: (event) => { setDimWhenIdle(event.target.checked); } }), _jsx("span", { children: t('dimWhenIdleLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('dimWhenIdleHint') })] })] })), settingsTab === 'music' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: musicEnabled, onChange: (event) => { setMusicEnabled(event.target.checked); } }), _jsx("span", { children: t('musicLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('musicHint') })] }), musicEnabled && (_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('musicVolume') }), _jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: musicVolume, onChange: (event) => { setMusicVolume(Number(event.target.value)); } })] }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('musicStyle') }), _jsxs("select", { value: musicStyle, onChange: (event) => { setMusicStyle(event.target.value); }, children: [_jsx("option", { value: "major", children: t('musicStyleMajor') }), _jsx("option", { value: "minor", children: t('musicStyleMinor') }), _jsx("option", { value: "pentatonic", children: t('musicStylePentatonic') })] })] }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: musicOnlyCurrentSession, onChange: (event) => { setMusicOnlyCurrentSession(event.target.checked); } }), _jsx("span", { children: t('musicOnlyCurrentSessionLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('musicOnlyCurrentSessionHint') })] }))] })), settingsTab === 'transcribe' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: transcribe.enabled, onChange: (event) => { setTranscribeSettings({ ...transcribe, enabled: event.target.checked }); } }), _jsx("span", { children: t('transcribeEnabledLabel') })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeEnabledHint') })] }), transcribe.enabled && (_jsxs("div", { className: css.dialogSection, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeBaseURLLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.baseURL, onChange: (event) => { setTranscribeSettings({ ...transcribe, baseURL: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeBaseURLHint') }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeApiKeyEnvLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.apiKeyEnv, onChange: (event) => { setTranscribeSettings({ ...transcribe, apiKeyEnv: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeApiKeyEnvHint') }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeKeyLabel') }), _jsx("input", { className: css.resetSelect, type: "password", autoComplete: "off", value: keyDraft, placeholder: keyConfigured === true ? t('transcribeKeyPlaceholderSet') : t('transcribeKeyPlaceholder'), onChange: (event) => {
870
+ setKeyDraft(event.target.value);
871
+ setKeySaved(false);
872
+ setKeyError(null);
873
+ }, onKeyDown: (event) => {
874
+ if (event.key === 'Enter') {
875
+ event.preventDefault();
876
+ saveKey();
877
+ }
878
+ } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeKeyHint') }), _jsxs("div", { className: css.keyRow, children: [_jsx("button", { type: "button", className: css.keySaveBtn, disabled: keyDraft === '' || keySaving, onClick: () => { saveKey(); }, children: keySaving ? t('transcribeKeySaving') : t('transcribeKeySave') }), _jsx("span", { className: keyConfigured === true ? css.keyBadgeOk : css.keyBadgeOff, children: keySaved
879
+ ? t('transcribeKeySaved')
880
+ : keyConfigured === true ? t('transcribeKeyConfigured') : t('transcribeKeyMissing') })] }), keyError !== null && _jsx("div", { className: css.keyError, children: keyError }), _jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("span", { children: t('transcribeModelLabel') }), _jsx("input", { className: css.resetSelect, type: "text", value: transcribe.model, onChange: (event) => { setTranscribeSettings({ ...transcribe, model: event.target.value }); } })] }), _jsx("div", { className: css.dialogHint, children: t('transcribeModelHint') })] }))] })), settingsTab === 'other' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: css.dialogSection, children: [_jsxs("div", { className: css.checkUpdatesRow, children: [_jsxs("label", { className: css.checkUpdatesLabel, children: [_jsx("input", { type: "checkbox", checked: checkUpdates, onChange: (event) => { setCheckUpdates(event.target.checked); } }), _jsx("span", { children: t('checkUpdatesLabel') })] }), _jsx("button", { type: "button", className: css.checkBtn, disabled: checkingUpdates, onClick: checkUpdatesNow, children: checkingUpdates
822
881
  ? t('checkingUpdates')
823
882
  : lastCheckResult === 'up-to-date'
824
883
  ? t('checkUpToDate')
@@ -12,7 +12,7 @@ const TOKEN_QUOTA_NAMESPACE = 'token-quota';
12
12
  /** Snapshot pull cadence in milliseconds. */
13
13
  const POLL_INTERVAL_MS = 3000;
14
14
  /** Required services: slot registry, sessions, locale, settings scope, and the Host remote faces. */
15
- export const inject = ['slots', 'sessions', 'locale', 'settingsScope', 'remote', 'remote.session'];
15
+ export const inject = ['slots', 'sessions', 'locale', 'settingsScope', 'remote', 'remote.session', 'remote.credentials'];
16
16
  /**
17
17
  * Client plugin body: poll the Host snapshot route, run the full-quota
18
18
  * strategy, wire the injected face (directory load, limit write, model
@@ -418,6 +418,36 @@ export function apply(ctx) {
418
418
  bound?.setTranscribeSettings(settings);
419
419
  void scope.set('transcribe', settings);
420
420
  };
421
+ /**
422
+ * Read whether the transcription credential reference currently holds a key,
423
+ * so the settings page can show 已配置 / 未配置 without ever reading the
424
+ * secret back (the wire carries it in one direction only).
425
+ */
426
+ const checkTranscribeKey = async (ref) => {
427
+ try {
428
+ const result = await ctx.remote.credentials.describe([ref]);
429
+ if (!result.ok)
430
+ return false;
431
+ return result.value[ref]?.configured === true;
432
+ }
433
+ catch {
434
+ return false;
435
+ }
436
+ };
437
+ /**
438
+ * Store the transcription API key through the credential seam, so it lives
439
+ * in the same credential store the Host resolves from — the user never has
440
+ * to edit a file by hand.
441
+ */
442
+ const saveTranscribeKey = async (ref, value) => {
443
+ try {
444
+ await ctx.remote.credentials.set(ref, value);
445
+ return { ok: true };
446
+ }
447
+ catch (error) {
448
+ return { ok: false, error: error instanceof Error ? error.message : String(error) };
449
+ }
450
+ };
421
451
  /**
422
452
  * Send a recorded audio blob to the Host, which forwards it to the
423
453
  * configured OpenAI-compatible transcription endpoint. Resolves with the
@@ -572,7 +602,7 @@ export function apply(ctx) {
572
602
  setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle,
573
603
  setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession,
574
604
  setModelOrder, saveNotes, setBalanceSettings, refreshBalance,
575
- setTranscribeSettings,
605
+ setTranscribeSettings, checkTranscribeKey, saveTranscribeKey,
576
606
  };
577
607
  };
578
608
  ctx.slots.inject('shell.overlay', () => ctx.slots.register({
@@ -39,6 +39,16 @@ export declare const zh: {
39
39
  transcribeBaseURLHint: string;
40
40
  transcribeApiKeyEnvLabel: string;
41
41
  transcribeApiKeyEnvHint: string;
42
+ transcribeKeyLabel: string;
43
+ transcribeKeyHint: string;
44
+ transcribeKeyPlaceholder: string;
45
+ transcribeKeyPlaceholderSet: string;
46
+ transcribeKeySave: string;
47
+ transcribeKeySaving: string;
48
+ transcribeKeySaved: string;
49
+ transcribeKeyConfigured: string;
50
+ transcribeKeyMissing: string;
51
+ transcribeKeyFailed: string;
42
52
  transcribeModelLabel: string;
43
53
  transcribeModelHint: string;
44
54
  reorderHint: string;
@@ -170,6 +180,16 @@ export declare const en: {
170
180
  transcribeBaseURLHint: string;
171
181
  transcribeApiKeyEnvLabel: string;
172
182
  transcribeApiKeyEnvHint: string;
183
+ transcribeKeyLabel: string;
184
+ transcribeKeyHint: string;
185
+ transcribeKeyPlaceholder: string;
186
+ transcribeKeyPlaceholderSet: string;
187
+ transcribeKeySave: string;
188
+ transcribeKeySaving: string;
189
+ transcribeKeySaved: string;
190
+ transcribeKeyConfigured: string;
191
+ transcribeKeyMissing: string;
192
+ transcribeKeyFailed: string;
173
193
  transcribeModelLabel: string;
174
194
  transcribeModelHint: string;
175
195
  reorderHint: string;
@@ -37,8 +37,18 @@ export const zh = {
37
37
  transcribeEnabledHint: '在对话框右上角显示麦克风按钮',
38
38
  transcribeBaseURLLabel: '接口地址',
39
39
  transcribeBaseURLHint: 'OpenAI 兼容的转录接口 base URL',
40
- transcribeApiKeyEnvLabel: 'API Key 环境变量',
41
- transcribeApiKeyEnvHint: '存有 API Key 的凭证变量名(在 Models 页或 credentials 配置)',
40
+ transcribeApiKeyEnvLabel: '凭证名称',
41
+ transcribeApiKeyEnvHint: '密钥在凭证库中保存的名称,一般无需修改',
42
+ transcribeKeyLabel: 'API Key',
43
+ transcribeKeyHint: '在此填入密钥并点「保存」,密钥会写入 DSH 凭证库(保存后不会回显)',
44
+ transcribeKeyPlaceholder: '粘贴 API Key',
45
+ transcribeKeyPlaceholderSet: '已配置,填入新值可覆盖',
46
+ transcribeKeySave: '保存',
47
+ transcribeKeySaving: '保存中…',
48
+ transcribeKeySaved: '已保存',
49
+ transcribeKeyConfigured: '已配置',
50
+ transcribeKeyMissing: '未配置',
51
+ transcribeKeyFailed: '保存失败',
42
52
  transcribeModelLabel: '模型',
43
53
  transcribeModelHint: '语音转文本模型名',
44
54
  reorderHint: '拖动排序',
@@ -166,8 +176,18 @@ export const en = {
166
176
  transcribeEnabledHint: 'Show a mic button in the top-right of the composer',
167
177
  transcribeBaseURLLabel: 'Base URL',
168
178
  transcribeBaseURLHint: 'OpenAI-compatible transcription endpoint base URL',
169
- transcribeApiKeyEnvLabel: 'API key env var',
170
- transcribeApiKeyEnvHint: 'Credential variable name holding the API key (Models page or credentials)',
179
+ transcribeApiKeyEnvLabel: 'Credential name',
180
+ transcribeApiKeyEnvHint: 'Name the key is stored under in the credential store; usually unchanged',
181
+ transcribeKeyLabel: 'API key',
182
+ transcribeKeyHint: 'Paste the key here and press Save — it is written to the DSH credential store and never read back',
183
+ transcribeKeyPlaceholder: 'Paste API key',
184
+ transcribeKeyPlaceholderSet: 'Configured — enter a new value to replace',
185
+ transcribeKeySave: 'Save',
186
+ transcribeKeySaving: 'Saving…',
187
+ transcribeKeySaved: 'Saved',
188
+ transcribeKeyConfigured: 'Configured',
189
+ transcribeKeyMissing: 'Not configured',
190
+ transcribeKeyFailed: 'Save failed',
171
191
  transcribeModelLabel: 'Model',
172
192
  transcribeModelHint: 'Speech-to-text model name',
173
193
  reorderHint: 'Drag to reorder',
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.43",
4
+ "version": "0.1.44",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -43,7 +43,8 @@
43
43
  },
44
44
  "scripts": {
45
45
  "bundle": "tsdown",
46
- "watch": "tsdown --watch"
46
+ "watch": "tsdown --watch",
47
+ "smoke": "node tools/smoke-client.mjs"
47
48
  },
48
49
  "files": [
49
50
  "lib/index.js",
@@ -168,4 +169,4 @@
168
169
  "optional": true
169
170
  }
170
171
  }
171
- }
172
+ }