@noob-stupid/dsh-plugin-console 0.3.27 → 0.3.29

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
@@ -6,7 +6,7 @@ window.__ModuleLoader__.load({
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
8
  //#region styles
9
- const css = ".pc_section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:14px;display:flex}.pc_section h3{margin:0;font-size:13px;font-weight:600;line-height:20px}.pc_message{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px;margin:0}.pc_messageRow{display:flex;align-items:center;gap:10px}.pc_spinner{width:14px;height:14px;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:pcspin 1s linear infinite;flex:none}@keyframes pcspin{to{transform:rotate(360deg)}}.pc_message[data-error=true]{color:var(--dsw-alias-state-error-primary)}.pc_list{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none;display:grid}.pc_row{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;min-width:0;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_rowTop{align-items:center;gap:8px;display:flex}.pc_name{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.pc_tag{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:16px;flex:none}.pc_tag[data-enabled=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_tag[data-user=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_tag[data-pending=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_status[data-pending=true]{color:var(--dsw-alias-state-warning-primary)}.pc_toggle[data-pending=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_tag[data-skill=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_tag[data-system=true]{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}.pc_tag[data-disabled=true]{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.pc_tag[data-suite=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_tag[data-error=true]{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.pc_tabGroup{display:inline-flex;gap:4px;align-items:center}.pc_meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;gap:6px;display:flex;align-items:center}.pc_phase[data-phase=failed]{color:var(--dsw-alias-state-error-primary)}.pc_phase[data-phase=active]{color:var(--dsw-alias-state-success-primary)}.pc_toggle{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:4px 12px;align-self:flex-start}.pc_toggle:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary)}.pc_toggle:disabled{opacity:.5;cursor:default}.pc_search{gap:8px;display:flex}.pc_search input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;flex:1;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;outline:none;padding:0 12px;font-size:13px}.pc_search input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}.pc_search button{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:0 14px;font-size:13px}.pc_search button:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_market{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}.pc_item{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;min-width:0;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_itemTop{align-items:center;gap:8px;display:flex}.pc_itemTop a{color:var(--dsw-alias-state-business-primary);font-size:13px;font-weight:600;text-decoration:none;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pc_stars{color:var(--dsw-alias-label-tertiary);font-size:11px;flex:none}.pc_desc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:0}.pc_item button{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:3px 10px;align-self:flex-start;font-size:12px}.pc_item button:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary)}.pc_item button:disabled{opacity:.5;cursor:default}.pc_detail{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_status{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:0}.pc_note{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;margin:0}.pc_marketHead{display:flex;align-items:center;justify-content:space-between;gap:10px}.pc_descWrap{flex-direction:column;display:flex}.pc_installedHead{display:flex;align-items:center;gap:10px}.pc_backTopWrap{position:fixed;top:56px;right:20px;z-index:100;display:flex;flex-direction:column;gap:8px}.pc_backTop{width:34px;height:34px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:rgba(22,27,34,.72);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);cursor:pointer;backdrop-filter:blur(4px);opacity:.7}.pc_backTop:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_descTopbar{display:flex;justify-content:flex-end;margin:2px 0}.pc_ghpill{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 10px;font-size:11px;line-height:18px}.pc_ghpill[data-on=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_extraBtn{opacity:.75;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:4px 10px;font-size:12px;line-height:16px;flex:none;transition:opacity .15s ease,border-color 1.5s ease,color 1.5s ease}.pc_extraBtn:hover{opacity:1}.pc_extraBtn[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_extraBtn[data-flash=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_view{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:2px 10px;font-size:12px;line-height:18px;flex:none}.pc_floatPanel{position:fixed;left:20px;top:50%;transform:translateY(-50%);width:340px;max-height:75vh;overflow-y:auto;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);z-index:50;flex-direction:column;gap:8px;display:flex}.pc_refresh{position:sticky;bottom:14px;align-self:flex-end;margin-top:8px;z-index:60;opacity:.45;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_refresh:hover{opacity:.9}.pc_date{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;flex:none}.pc_searchInner{position:relative;flex:1;display:flex;align-items:center;min-width:0}.pc_searchInner input{padding-right:32px;width:100%}.pc_starBtn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:13px;line-height:1;padding:4px 8px;border-radius:6px;opacity:.75;transition:opacity .15s ease;flex:none}.pc_starBtn:hover{opacity:1}.pc_starBtn[data-active=true]{opacity:1;color:var(--dsw-alias-state-business-primary)}.pc_restartBtn{position:fixed;right:20px;top:50%;transform:translateY(-50%);z-index:60;opacity:.45;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_restartBtn:hover{opacity:.9}.pc_relaunchFloat{position:fixed;left:20px;top:50%;transform:translateY(-50%);z-index:70;opacity:.85;border:1px solid var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_relaunchFloat:hover{opacity:1}.pc_aiToggle{position:fixed;right:20px;top:20px;z-index:70;opacity:.45;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_aiToggle:hover{opacity:.9}.pc_aiToggle[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_sourcesFloat{position:fixed;right:20px;top:104px;z-index:70;opacity:.85;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_sourcesFloat:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_modeFloat{position:fixed;right:20px;top:204px;z-index:70;opacity:.85;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_modeFloat:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_modeFloat[data-mode=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_trashBtn{border:0;background:0 0;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:12px;line-height:16px;padding:2px 6px;flex:none;display:flex;align-items:center;border-radius:6px;transition:color .15s ease}.pc_trashBtn:hover{color:var(--dsw-alias-state-error-primary)}.pc_consentRemember{display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;color:var(--dsw-alias-label-secondary);cursor:pointer}.pc_modalBackdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:center;justify-content:center}.pc_modalCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:12px;padding:16px 18px;max-width:420px;width:calc(100% - 48px);flex-direction:column;gap:10px;display:flex;box-shadow:0 12px 32px rgba(0,0,0,.25)}.pc_ghpill{background:0 0;cursor:pointer}.pc_ghwrap{position:relative;display:inline-flex}.pc_sourceMenu{position:absolute;right:0;top:calc(100% + 6px);z-index:90;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:4px;flex-direction:column;display:flex;min-width:120px;box-shadow:0 8px 24px rgba(0,0,0,.18)}.pc_sourceOpt{border:0;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:6px 10px;text-align:left;font-size:12px;line-height:16px}.pc_sourceOpt[data-active=true]{color:var(--dsw-alias-state-business-primary);font-weight:600}.pc_sourceOpt:hover{background:var(--dsw-alias-bg-layer-3)}.pc_aiEmpower{position:fixed;right:20px;top:48px;z-index:70;opacity:.45;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_aiEmpower:hover{opacity:.9}.pc_aiEmpower[data-busy=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_aiEmpower[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_compCard{position:fixed;left:8px;top:20px;width:320px;max-height:70vh;overflow-y:auto;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);z-index:45;flex-direction:column;gap:8px;display:flex}.pc_compCard .pc_rowTop{flex-wrap:wrap}.pc_compCard .pc_toggle{padding:3px 8px;font-size:11px}.pc_compCard[data-hidden=true]{display:none}.pc_compDrop{background:rgba(24,28,34,.92);backdrop-filter:blur(6px);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:4px;box-shadow:0 8px 24px rgba(0,0,0,.35);flex-direction:column;display:flex;gap:2px}.pc_compDropRow{border:0;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:6px 8px;text-align:left;font-size:12px;line-height:16px;flex-direction:column;display:flex;gap:2px}.pc_compDropRow:hover{background:var(--dsw-alias-bg-layer-2)}.pc_compDropUrl{color:var(--dsw-alias-label-tertiary);font-size:11px;word-break:break-all}.pc_compToggle{position:fixed;left:336px;top:20px;z-index:46;opacity:.55;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:rgba(22,27,34,.72);font:inherit;cursor:pointer;width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;line-height:1;backdrop-filter:blur(4px);transition:opacity .15s ease}.pc_compToggle:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_toolbarMain{position:fixed;right:70px;top:20px;z-index:71;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:border-color .15s ease}.pc_toolbarMain:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_toolbarMain[data-active=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_toolbarGroup{position:fixed;right:70px;top:56px;z-index:70;flex-direction:column;gap:8px;display:flex;transform-origin:top right;animation:pcDrawerIn .3s cubic-bezier(.34,1.56,.64,1)}@keyframes pcDrawerIn{from{opacity:0;transform:translateX(28px) scale(.94)}to{opacity:1;transform:translateX(0) scale(1)}}.pc_toolItem{opacity:.85;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_toolItem:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_toolItem[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_toolItem[data-mode=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_switch{width:34px;height:18px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);position:relative;cursor:pointer;flex:none;transition:background .15s ease,border-color .15s ease}.pc_switch:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_switch[data-on=true]{background:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}.pc_switchKnob{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;transition:left .15s ease}.pc_switch[data-on=true] .pc_switchKnob{left:18px}.pc_aiSpinner{width:12px;height:12px;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:pcspin 1s linear infinite;flex:none}.pc_aiSpinBtn{position:fixed;right:152px;top:20px;z-index:71;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px}.pc_aiSpinBtn:hover{border-color:var(--dsw-alias-state-business-primary)}";
9
+ const css = ".pc_section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:14px;display:flex}.pc_section h3{margin:0;font-size:13px;font-weight:600;line-height:20px}.pc_message{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px;margin:0}.pc_messageRow{display:flex;align-items:center;gap:10px}.pc_spinner{width:14px;height:14px;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:pcspin 1s linear infinite;flex:none}@keyframes pcspin{to{transform:rotate(360deg)}}.pc_message[data-error=true]{color:var(--dsw-alias-state-error-primary)}.pc_list{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none;display:grid}.pc_row{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;min-width:0;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_rowTop{align-items:center;gap:8px;display:flex}.pc_name{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.pc_tag{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-size:11px;line-height:16px;flex:none}.pc_tag[data-enabled=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_tag[data-user=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_tag[data-pending=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_status[data-pending=true]{color:var(--dsw-alias-state-warning-primary)}.pc_toggle[data-pending=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_tag[data-skill=true]{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_tag[data-system=true]{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}.pc_tag[data-disabled=true]{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.pc_tag[data-suite=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_tag[data-error=true]{border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.pc_tabGroup{display:inline-flex;gap:4px;align-items:center}.pc_meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;gap:6px;display:flex;align-items:center}.pc_phase[data-phase=failed]{color:var(--dsw-alias-state-error-primary)}.pc_phase[data-phase=active]{color:var(--dsw-alias-state-success-primary)}.pc_toggle{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:4px 12px;align-self:flex-start}.pc_toggle:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary)}.pc_toggle:disabled{opacity:.5;cursor:default}.pc_search{gap:8px;display:flex}.pc_search input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);height:34px;flex:1;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;outline:none;padding:0 12px;font-size:13px}.pc_search input:focus-visible{border-color:var(--dsw-alias-state-business-primary)}.pc_search button{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:0 14px;font-size:13px}.pc_search button:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_market{flex-direction:column;gap:10px;margin:0;padding:0;list-style:none;display:flex}.pc_item{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;min-width:0;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_itemTop{align-items:center;gap:8px;display:flex}.pc_itemTop a{color:var(--dsw-alias-state-business-primary);font-size:13px;font-weight:600;text-decoration:none;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pc_stars{color:var(--dsw-alias-label-tertiary);font-size:11px;flex:none}.pc_desc{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:0}.pc_item button{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:3px 10px;align-self:flex-start;font-size:12px}.pc_item button:hover:not(:disabled){border-color:var(--dsw-alias-state-business-primary)}.pc_item button:disabled{opacity:.5;cursor:default}.pc_detail{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:10px 12px;flex-direction:column;gap:6px;display:flex}.pc_status{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;margin:0}.pc_note{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;margin:0}.pc_marketHead{display:flex;align-items:center;justify-content:space-between;gap:10px}.pc_descWrap{flex-direction:column;display:flex}.pc_installedHead{display:flex;align-items:center;gap:10px}.pc_backTopWrap{position:fixed;top:56px;right:20px;z-index:100;display:flex;flex-direction:column;gap:8px}.pc_backTop{width:34px;height:34px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;background:rgba(22,27,34,.72);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);cursor:pointer;backdrop-filter:blur(4px);opacity:.7}.pc_backTop:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_descTopbar{display:flex;justify-content:flex-end;margin:2px 0}.pc_ghpill{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 10px;font-size:11px;line-height:18px}.pc_ghpill[data-on=true]{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary)}.pc_extraBtn{opacity:.75;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:4px 10px;font-size:12px;line-height:16px;flex:none;transition:opacity .15s ease,border-color 1.5s ease,color 1.5s ease}.pc_extraBtn:hover{opacity:1}.pc_extraBtn[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_extraBtn[data-flash=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_view{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0;font:inherit;cursor:pointer;border-radius:6px;padding:2px 10px;font-size:12px;line-height:18px;flex:none}.pc_floatPanel{position:fixed;left:20px;top:50%;transform:translateY(-50%);width:340px;max-height:75vh;overflow-y:auto;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);z-index:50;flex-direction:column;gap:8px;display:flex}.pc_refresh{position:sticky;bottom:14px;align-self:flex-end;margin-top:8px;z-index:60;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_refresh:hover{opacity:.9}.pc_date{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;flex:none}.pc_searchInner{position:relative;flex:1;display:flex;align-items:center;min-width:0}.pc_searchInner input{padding-right:32px;width:100%}.pc_starBtn{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:13px;line-height:1;padding:4px 8px;border-radius:6px;opacity:.75;transition:opacity .15s ease;flex:none}.pc_starBtn:hover{opacity:1}.pc_starBtn[data-active=true]{opacity:1;color:var(--dsw-alias-state-business-primary)}.pc_restartBtn{position:fixed;right:20px;top:50%;transform:translateY(-50%);z-index:60;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:transparent;font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_restartBtn:hover{opacity:.9}.pc_relaunchFloat{position:fixed;left:20px;top:50%;transform:translateY(-50%);z-index:70;opacity:.85;border:1px solid var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_relaunchFloat:hover{opacity:1}.pc_aiToggle{position:fixed;right:20px;top:20px;z-index:70;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_aiToggle:hover{opacity:1}.pc_aiToggle[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_sourcesFloat{position:fixed;right:20px;top:104px;z-index:70;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_sourcesFloat:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_modeFloat{position:fixed;right:20px;top:204px;z-index:70;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_modeFloat:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_modeFloat[data-mode=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_trashBtn{border:0;background:0 0;color:var(--dsw-alias-label-tertiary);cursor:pointer;font-size:12px;line-height:16px;padding:2px 6px;flex:none;display:flex;align-items:center;border-radius:6px;transition:color .15s ease}.pc_trashBtn:hover{color:var(--dsw-alias-state-error-primary)}.pc_consentRemember{display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;color:var(--dsw-alias-label-secondary);cursor:pointer}.pc_modalBackdrop{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;display:flex;align-items:center;justify-content:center}.pc_modalCard{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:12px;padding:16px 18px;max-width:420px;width:calc(100% - 48px);flex-direction:column;gap:10px;display:flex;box-shadow:0 12px 32px rgba(0,0,0,.25)}.pc_ghpill{background:0 0;cursor:pointer}.pc_ghwrap{position:relative;display:inline-flex}.pc_sourceMenu{position:absolute;right:0;top:calc(100% + 6px);z-index:90;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);border-radius:8px;padding:4px;flex-direction:column;display:flex;min-width:120px;box-shadow:0 8px 24px rgba(0,0,0,.18)}.pc_sourceOpt{border:0;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:6px 10px;text-align:left;font-size:12px;line-height:16px}.pc_sourceOpt[data-active=true]{color:var(--dsw-alias-state-business-primary);font-weight:600}.pc_sourceOpt:hover{background:var(--dsw-alias-bg-layer-3)}.pc_aiEmpower{position:fixed;right:20px;top:48px;z-index:70;opacity:1;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_aiEmpower:hover{opacity:.9}.pc_aiEmpower[data-busy=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_aiEmpower[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_compCard{position:fixed;left:8px;top:20px;width:320px;max-height:70vh;overflow-y:auto;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;padding:12px;box-shadow:0 8px 24px rgba(0,0,0,.18);z-index:45;flex-direction:column;gap:8px;display:flex}.pc_compCard .pc_rowTop{flex-wrap:wrap}.pc_compCard .pc_toggle{padding:3px 8px;font-size:11px}.pc_compCard[data-hidden=true]{display:none}.pc_compDrop{background:rgba(24,28,34,.92);backdrop-filter:blur(6px);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:4px;box-shadow:0 8px 24px rgba(0,0,0,.35);flex-direction:column;display:flex;gap:2px}.pc_compDropRow{border:0;background:0 0;color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:6px;padding:6px 8px;text-align:left;font-size:12px;line-height:16px;flex-direction:column;display:flex;gap:2px}.pc_compDropRow:hover{background:var(--dsw-alias-bg-layer-2)}.pc_compDropUrl{color:var(--dsw-alias-label-tertiary);font-size:11px;word-break:break-all}.pc_compToggle{position:fixed;left:336px;top:20px;z-index:46;opacity:.55;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:rgba(22,27,34,.72);font:inherit;cursor:pointer;width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;line-height:1;backdrop-filter:blur(4px);transition:opacity .15s ease}.pc_compToggle:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_toolbarMain{position:fixed;right:70px;top:20px;z-index:71;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:border-color .15s ease}.pc_toolbarMain:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_toolbarMain[data-active=true]{border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_toolbarGroup{position:fixed;right:70px;top:56px;z-index:70;flex-direction:column;gap:8px;display:flex;transform-origin:top right;animation:pcDrawerIn .3s cubic-bezier(.34,1.56,.64,1)}@media (max-width:1160px){.pc_toolbarMain{top:104px}.pc_toolbarGroup{top:140px}.pc_aiToggle{top:104px}.pc_aiEmpower{top:132px}.pc_sourcesFloat{top:188px}.pc_modeFloat{top:288px}}@keyframes pcDrawerIn{from{opacity:0;transform:translateX(28px) scale(.94)}to{opacity:1;transform:translateX(0) scale(1)}}.pc_toolItem{opacity:.85;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);font:inherit;cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;transition:opacity .15s ease}.pc_toolItem:hover{opacity:1;border-color:var(--dsw-alias-state-business-primary)}.pc_toolItem[data-active=true]{opacity:1;border-color:var(--dsw-alias-state-business-primary);color:var(--dsw-alias-state-business-primary)}.pc_toolItem[data-mode=true]{opacity:1;border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary)}.pc_switch{width:34px;height:18px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);position:relative;cursor:pointer;flex:none;transition:background .15s ease,border-color .15s ease}.pc_switch:hover{border-color:var(--dsw-alias-state-business-primary)}.pc_switch[data-on=true]{background:var(--dsw-alias-state-success-primary);border-color:var(--dsw-alias-state-success-primary)}.pc_switchKnob{position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;transition:left .15s ease}.pc_switch[data-on=true] .pc_switchKnob{left:18px}.pc_aiSpinner{width:12px;height:12px;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:pcspin 1s linear infinite;flex:none}.pc_aiSpinBtn{position:fixed;right:152px;top:20px;z-index:71;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;border-radius:8px;padding:6px 10px;display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px}.pc_aiSpinBtn:hover{border-color:var(--dsw-alias-state-business-primary)}";
10
10
  const tagId = "@noob-stupid/dsh-plugin-console/PluginConsoleTab.css";
11
11
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
12
12
  const tag = document.createElement("style");
@@ -114,6 +114,8 @@ window.__ModuleLoader__.load({
114
114
  familyCollapse: "收起",
115
115
  familyUpdate: "全家桶版本检测",
116
116
  familyCheckUpdate: "批量检测更新",
117
+ familyUpdateBtn: "更新",
118
+ familyCheckUpdateTip: "检测到新版本后此处出现「更新」按钮,点击开始整包更新(含子包版本对齐与适配校验)",
117
119
  adaptUnlockBtn: "已适配,立即解锁",
118
120
  adaptUnlockHint: "已安装版本经源码扫描确认适配当前框架:立即移除禁用块并解锁启用",
119
121
  adaptUnlockDone: "已适配解锁:刷新后该行可正常启用",
@@ -429,6 +431,8 @@ window.__ModuleLoader__.load({
429
431
  familyCollapse: "Collapse",
430
432
  familyUpdate: "Family version check",
431
433
  familyCheckUpdate: "Check all",
434
+ familyUpdateBtn: "Update",
435
+ familyCheckUpdateTip: "When a newer version is detected this Update button appears; click to start the full-family update (subpackage alignment + adapt check)",
432
436
  adaptUnlockBtn: "Adapted - unlock now",
433
437
  adaptUnlockHint: "Installed version passed the source scan for the current framework: unlock immediately",
434
438
  adaptUnlockDone: "Unlocked: refresh and the row is enabled",
@@ -1007,6 +1011,7 @@ window.__ModuleLoader__.load({
1007
1011
  const [restartHint, setRestartHint] = react.useState(false);
1008
1012
  const [jobs, setJobs] = react.useState({});
1009
1013
  const [familyCollapsed, setFamilyCollapsed] = react.useState({});
1014
+ const [familyCheck, setFamilyCheck] = react.useState({});
1010
1015
  const [query, setQuery] = react.useState(() => {
1011
1016
  try { return localStorage.getItem("pc-market-query") ?? ""; } catch { return ""; }
1012
1017
  });
@@ -1149,6 +1154,16 @@ window.__ModuleLoader__.load({
1149
1154
  const [toolbarOpen, setToolbarOpen] = react.useState(() => {
1150
1155
  try { return localStorage.getItem("pc-toolbar-open") === "1"; } catch { return false; }
1151
1156
  });
1157
+ // 功能包位置:长按拖动,持久化 localStorage(每次打开沿用上次位置)
1158
+ const [toolbarPos, setToolbarPos] = react.useState(() => {
1159
+ try {
1160
+ const v = JSON.parse(localStorage.getItem("pc-toolbar-pos") || "null");
1161
+ if (v && Number.isFinite(v.left) && Number.isFinite(v.top)) return { left: v.left, top: v.top };
1162
+ } catch {}
1163
+ return null;
1164
+ });
1165
+ const [dragPos, setDragPos] = react.useState(null);
1166
+ const dragRef = react.useRef({ long: null, active: false, justDragged: false, grabX: 0, grabY: 0, base: null });
1152
1167
  const [repoLandOn, setRepoLandOn] = react.useState(() => {
1153
1168
  try { return localStorage.getItem("pc-repo-land") === "1"; } catch { return false; }
1154
1169
  });
@@ -2287,12 +2302,15 @@ window.__ModuleLoader__.load({
2287
2302
  if (m.startsWith("@deepseek-ai/")) return null;
2288
2303
  return pkgRootOf(m);
2289
2304
  };
2290
- const familyCounts = new Map();
2305
+ const familyCounts = new Map(); // root → Set(moduleName):仅按不同子包名聚合;同一包的重复行不算全家桶(2026-09-06 i18n 重复行事故)
2291
2306
  for (const entry of (state.status === "ready" ? state.data.entries : [])) {
2292
2307
  const root = famRootOf(entry);
2293
2308
  if (root === null) continue;
2294
- familyCounts.set(root, (familyCounts.get(root) ?? 0) + 1);
2309
+ const set = familyCounts.get(root) ?? new Set();
2310
+ set.add(String(entry.moduleName ?? ""));
2311
+ familyCounts.set(root, set);
2295
2312
  }
2313
+ const familySize = (root) => (familyCounts.get(root)?.size ?? 0);
2296
2314
  const familyCards = filteredEntries.map((entry) => {
2297
2315
  const familyRoot = String(entry.moduleName ?? "").startsWith("@deepseek-ai/") ? null : pkgRootOf(entry.moduleName);
2298
2316
  void familyRoot;
@@ -2401,7 +2419,7 @@ window.__ModuleLoader__.load({
2401
2419
  el("strong", { className: styles.name, title: entry.moduleName }, (() => {
2402
2420
  const famRoot = famRootOf(entry);
2403
2421
  const mn = String(entry.moduleName ?? "");
2404
- return famRoot !== null && (familyCounts.get(famRoot) ?? 0) > 1 && mn.startsWith(famRoot + "/")
2422
+ return famRoot !== null && familySize(famRoot) > 1 && mn.startsWith(famRoot + "/")
2405
2423
  ? mn.slice(famRoot.length + 1)
2406
2424
  : moduleShortName(entry.moduleName);
2407
2425
  })()),
@@ -2484,12 +2502,12 @@ window.__ModuleLoader__.load({
2484
2502
  const familySeen = new Set();
2485
2503
  for (const entry of filteredEntries) {
2486
2504
  const root = famRootOf(entry);
2487
- if (root === null || (familyCounts.get(root) ?? 0) <= 1 || familySeen.has(root)) continue;
2505
+ if (root === null || familySize(root) <= 1 || familySeen.has(root)) continue;
2488
2506
  familySeen.add(root);
2489
2507
  familyHeaders.push(el("div", { key: "family-" + root, className: styles.detail, style: { border: "1px solid var(--dsw-alias-state-business-primary)", borderRadius: 10, padding: "8px 12px", gridColumn: "1 / -1" } },
2490
2508
  el("div", { className: styles.rowTop, style: { alignItems: "center" } },
2491
2509
  el("strong", { className: styles.name, style: { flex: "0 1 auto", minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, title: root }, root.replace(/^@[^/]+\//u, "").replace(/^dsh-/u, "")),
2492
- el("span", { className: styles.tag, "data-user": "true" }, t("familyTag") + " · " + (familyCounts.get(root) ?? 0) + " " + t("familySubs")),
2510
+ el("span", { className: styles.tag, "data-user": "true" }, t("familyTag") + " · " + familySize(root) + " " + t("familySubs")),
2493
2511
  el("button", {
2494
2512
  type: "button",
2495
2513
  className: styles.toggle,
@@ -2503,11 +2521,26 @@ window.__ModuleLoader__.load({
2503
2521
  onClick: () => {
2504
2522
  setMessage(t("checkingUpdate"));
2505
2523
  call("/plugin-console/check-update", { packageName: root }).then(
2506
- (d) => setMessage(t("familyUpdate") + ":" + root + " " + (d?.latest ?? "?") + (d?.migrate && d.migrate.compatible ? " → " + d.migrate.to + " v" + d.migrate.latest : "") + (d?.error ? "(" + d.error + ")" : "")),
2524
+ (d) => {
2525
+ const installed = state.status === "ready"
2526
+ ? (state.data.entries.find((e) => e.moduleName === root) ?? {}).version ?? null
2527
+ : null;
2528
+ setFamilyCheck((prev) => ({ ...prev, [root]: { latest: d?.latest ?? null, installed } }));
2529
+ setMessage(t("familyUpdate") + ":" + root + " " + (d?.latest ?? "?") + (d?.migrate && d.migrate.compatible ? " → " + d.migrate.to + " v" + d.migrate.latest : "") + (d?.error ? "(" + d.error + ")" : ""));
2530
+ },
2507
2531
  (e) => setMessage(t("failed") + ":" + friendlyGithubError(e).message),
2508
2532
  );
2509
2533
  },
2510
2534
  }, t("familyCheckUpdate")),
2535
+ familyCheck[root] && familyCheck[root].latest !== null && familyCheck[root].latest !== familyCheck[root].installed
2536
+ ? el("button", {
2537
+ type: "button",
2538
+ className: styles.toggle,
2539
+ style: { whiteSpace: "nowrap", flexShrink: 0 },
2540
+ title: t("familyCheckUpdateTip"),
2541
+ onClick: () => startJob("", root, "github", "plugin", true),
2542
+ }, t("familyUpdateBtn") + " " + familyCheck[root].latest)
2543
+ : null,
2511
2544
  el("button", {
2512
2545
  type: "button",
2513
2546
  className: styles.toggle,
@@ -2517,7 +2550,9 @@ window.__ModuleLoader__.load({
2517
2550
  if (!window.confirm(t("familyUnlockAllConfirm"))) return;
2518
2551
  call("/plugin-console/adapt-unlock-all", { root }).then(
2519
2552
  (d) => {
2520
- setMessage(t("familyUnlockAllDone") + ":" + (d.unlocked ?? []).length + " 行" + (Array.isArray(d.kept) && d.kept.length > 0 ? ";保留 " + d.kept.length + " 行(未通过校验)" : ""));
2553
+ const unlockedCount = (d?.unlocked ?? []).length;
2554
+ if (unlockedCount === 0 && typeof d?.note === "string") { setMessage(d.note); return; }
2555
+ setMessage(t("familyUnlockAllDone") + ":" + unlockedCount + " 行" + (Array.isArray(d?.kept) && d.kept.length > 0 ? ";保留 " + d.kept.length + " 行(未通过校验)" : ""));
2521
2556
  window.setTimeout(() => window.location.reload(), 1500);
2522
2557
  },
2523
2558
  (e) => setMessage(t("failed") + ":" + friendlyGithubError(e).message),
@@ -2533,7 +2568,7 @@ window.__ModuleLoader__.load({
2533
2568
  const e = filteredEntries[i];
2534
2569
  if (e === undefined) { nonFamilyCards.push(card); return; }
2535
2570
  const root = famRootOf(e);
2536
- if (root === null || (familyCounts.get(root) ?? 0) <= 1) { nonFamilyCards.push(card); return; }
2571
+ if (root === null || familySize(root) <= 1) { nonFamilyCards.push(card); return; }
2537
2572
  if (!familySections.has(root)) familySections.set(root, { head: familyHeaders.find((h) => h && h.key === "family-" + root) ?? null, cards: [] });
2538
2573
  familySections.get(root).cards.push(card);
2539
2574
  });
@@ -3098,14 +3133,62 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
3098
3133
  "data-active": toolbarOpen ? "true" : "false",
3099
3134
  title: t(toolbarOpen ? "toolbarCloseTitle" : "toolbarOpenTitle"),
3100
3135
  "aria-label": t("toolbarLabel"),
3101
- onClick: () => setToolbarOpen((v) => {
3102
- const next = !v;
3103
- try { localStorage.setItem("pc-toolbar-open", next ? "1" : "0"); } catch {}
3104
- return next;
3105
- }),
3136
+ style: (dragPos ?? toolbarPos) !== null
3137
+ ? { left: (dragPos ?? toolbarPos).left, top: (dragPos ?? toolbarPos).top, right: "auto", touchAction: "none", userSelect: "none" }
3138
+ : { touchAction: "none", userSelect: "none" },
3139
+ onPointerDown: (e) => {
3140
+ const cur = dragPos ?? toolbarPos ?? { left: Math.max(8, window.innerWidth - 70 - 110), top: 20 };
3141
+ dragRef.current.grabX = e.clientX - cur.left;
3142
+ dragRef.current.grabY = e.clientY - cur.top;
3143
+ dragRef.current.base = cur;
3144
+ dragRef.current.active = false;
3145
+ dragRef.current.justDragged = false;
3146
+ try { e.currentTarget.setPointerCapture?.(e.pointerId); } catch {}
3147
+ dragRef.current.long = window.setTimeout(() => {
3148
+ dragRef.current.active = true;
3149
+ setDragPos(cur);
3150
+ }, 450);
3151
+ },
3152
+ onPointerMove: (e) => {
3153
+ if (!dragRef.current.active) return;
3154
+ const w = window.innerWidth;
3155
+ const h = window.innerHeight;
3156
+ const bw = e.currentTarget.offsetWidth || 96;
3157
+ const bh = e.currentTarget.offsetHeight || 30;
3158
+ const left = Math.max(8, Math.min(w - bw - 8, e.clientX - dragRef.current.grabX));
3159
+ const top = Math.max(8, Math.min(h - bh - 8, e.clientY - dragRef.current.grabY));
3160
+ setDragPos({ left, top });
3161
+ },
3162
+ onPointerUp: () => {
3163
+ if (dragRef.current.long !== null) { window.clearTimeout(dragRef.current.long); dragRef.current.long = null; }
3164
+ if (dragRef.current.active) {
3165
+ const p = dragPos;
3166
+ if (p !== null) {
3167
+ try { localStorage.setItem("pc-toolbar-pos", JSON.stringify(p)); } catch {}
3168
+ setToolbarPos(p);
3169
+ }
3170
+ dragRef.current.active = false;
3171
+ dragRef.current.justDragged = true;
3172
+ window.setTimeout(() => { dragRef.current.justDragged = false; }, 300);
3173
+ setDragPos(null);
3174
+ }
3175
+ },
3176
+ onPointerCancel: () => {
3177
+ if (dragRef.current.long !== null) { window.clearTimeout(dragRef.current.long); dragRef.current.long = null; }
3178
+ dragRef.current.active = false;
3179
+ setDragPos(null);
3180
+ },
3181
+ onClick: (e) => {
3182
+ if (dragRef.current.justDragged) { e.preventDefault(); dragRef.current.justDragged = false; return; }
3183
+ setToolbarOpen((v) => {
3184
+ const next = !v;
3185
+ try { localStorage.setItem("pc-toolbar-open", next ? "1" : "0"); } catch {}
3186
+ return next;
3187
+ });
3188
+ },
3106
3189
  }, t("toolbarLabel") + (toolbarOpen ? " ▾" : " ▸")),
3107
3190
  toolbarOpen
3108
- ? el("div", { className: styles.toolbarGroup },
3191
+ ? el("div", { className: styles.toolbarGroup, style: (dragPos ?? toolbarPos) !== null ? { left: (dragPos ?? toolbarPos).left, top: (dragPos ?? toolbarPos).top + 36, right: "auto" } : undefined },
3109
3192
  el("button", {
3110
3193
  type: "button",
3111
3194
  className: styles.toolItem,
package/lib/index.js CHANGED
@@ -179,26 +179,37 @@ function baseDirOf(baseUrl) {
179
179
  * (2026-09-04 教训:@openviking/dsh-memory-plugin 因此被 heal 误判模块缺失并自动禁用)——
180
180
  * fallback 直接查 node_modules 物理路径。
181
181
  */
182
- function resolvePackageJson(pkgName, baseDir) {
182
+ function resolvePackageJson(pkgName, baseDir, fallbackBase) {
183
183
  const name = packageNameOf(pkgName)
184
184
  try {
185
185
  return createRequire(join(baseDir, 'package.json')).resolve(`${name}/package.json`)
186
186
  } catch {}
187
187
  const parts = String(name).split('/')
188
188
  const candidate = join(baseDir, 'node_modules', ...parts, 'package.json')
189
- return existsSync(candidate) ? candidate : null
189
+ if (existsSync(candidate)) return candidate
190
+ // issue #15:npm 全局安装 dsh 时 ctx.baseUrl 落在框架安装树(而非 profile node_modules),
191
+ // 官方 @deepseek-ai/* 恰好可见、第三方插件全部解析失败 → 详情/版本/仓库全空。
192
+ // 回退到 profile 目录(fallbackBase)再试一次。
193
+ if (typeof fallbackBase === 'string' && fallbackBase !== '' && fallbackBase !== baseDir) {
194
+ try {
195
+ return createRequire(join(fallbackBase, 'package.json')).resolve(`${name}/package.json`)
196
+ } catch {}
197
+ const candidate2 = join(fallbackBase, 'node_modules', ...parts, 'package.json')
198
+ if (existsSync(candidate2)) return candidate2
199
+ }
200
+ return null
190
201
  }
191
202
 
192
203
  /** 已加载插件的包元信息缓存(安装日期/版本/仓库),60 秒 TTL。 */
193
204
  const pkgMetaCache = new Map()
194
205
  const PKG_META_TTL = 60000
195
- function entryPkgMeta(moduleName, baseUrl) {
206
+ function entryPkgMeta(moduleName, baseUrl, profileDir) {
196
207
  if (typeof moduleName !== 'string' || moduleName.startsWith('cordis:')) return null
197
208
  const hit = pkgMetaCache.get(moduleName)
198
209
  if (hit !== undefined && Date.now() - hit.at < PKG_META_TTL) return hit
199
210
  const meta = { at: Date.now(), installDate: null, version: null, repository: null }
200
211
  try {
201
- const pkgPath = resolvePackageJson(moduleName, baseDirOf(baseUrl))
212
+ const pkgPath = resolvePackageJson(moduleName, baseDirOf(baseUrl), profileDir ?? null)
202
213
  if (pkgPath === null) throw new Error('not found')
203
214
  const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
204
215
  // 安装日期:优先 curl 通道写入的 .dsh-installed-at 标记(真实安装时刻);
@@ -1061,7 +1072,7 @@ function backupProfileSnapshot(profileDir, version, ctx) {
1061
1072
  try { copyFileSync(join(profileDir, 'package.json'), join(dir, 'profile-package.json')) } catch {}
1062
1073
  try {
1063
1074
  const plugins = listEntries(ctx).map((e) => {
1064
- const meta = entryPkgMeta(e.moduleName, ctx.baseUrl ?? 'file:///')
1075
+ const meta = entryPkgMeta(e.moduleName, ctx.baseUrl ?? 'file:///', profileDirOf(ctx))
1065
1076
  return { rowId: e.rowId, moduleName: e.moduleName, enabled: e.enabled, version: meta?.version ?? null, installDate: meta?.installDate ?? null }
1066
1077
  })
1067
1078
  writeFileSync(join(dir, 'plugins.json'), JSON.stringify(plugins, null, 2), 'utf8')
@@ -1106,6 +1117,15 @@ function findPatchPath(ctx) {
1106
1117
  return defaultPatchPath()
1107
1118
  }
1108
1119
 
1120
+ /** profile 根目录(resolvePackageJson 的 fallbackBase 用;失败返回 null)。 */
1121
+ function profileDirOf(ctx) {
1122
+ try {
1123
+ return dirname(findPatchPath(ctx))
1124
+ } catch {
1125
+ return null
1126
+ }
1127
+ }
1128
+
1109
1129
  /** 读取补丁文件并扫描:停用块与 insert 行的 id。 */
1110
1130
  async function readPatchState(patchPath) {
1111
1131
  let text = ''
@@ -1187,10 +1207,10 @@ function summarizeReadme(text) {
1187
1207
  }
1188
1208
 
1189
1209
  /** 读取一个已加载插件的 package.json 元信息与 README 摘要。 */
1190
- async function readPluginDetails(moduleName, baseUrl) {
1210
+ async function readPluginDetails(moduleName, baseUrl, profileDir) {
1191
1211
  if (typeof moduleName !== 'string' || moduleName.startsWith('cordis:')) return { meta: null, readme: null }
1192
1212
  try {
1193
- const pkgPath = resolvePackageJson(moduleName, baseDirOf(baseUrl))
1213
+ const pkgPath = resolvePackageJson(moduleName, baseDirOf(baseUrl), profileDir ?? null)
1194
1214
  if (pkgPath === null) throw new Error('not found')
1195
1215
  const pkg = JSON.parse(await readFile(pkgPath, 'utf8'))
1196
1216
  const meta = {
@@ -2146,8 +2166,8 @@ async function githubReleaseInstall(profileDir, repo, packageName) {
2146
2166
  * 读已装包的 bundle patch → 检查每个 insert 引用的包是否存在 → 缺失补装(pnpm/curl)→
2147
2167
  * 仍缺则在用户 patch 层自动禁用该行(防崩兜底)+ 返回报告供面板提示。
2148
2168
  */
2149
- async function ensureBundlePatchIntegrity(profileDir, pkgName, userPatchPath) {
2150
- const report = { checked: 0, installed: [], disabled: [], missing: [] }
2169
+ async function ensureBundlePatchIntegrity(profileDir, pkgName, userPatchPath, transientAllow = []) {
2170
+ const report = { checked: 0, installed: [], disabled: [], missing: [], pending: [] }
2151
2171
  try {
2152
2172
  const pkgJsonPath = join(profileDir, 'node_modules', pkgName, 'package.json')
2153
2173
  if (!existsSync(pkgJsonPath)) return report
@@ -2179,6 +2199,12 @@ async function ensureBundlePatchIntegrity(profileDir, pkgName, userPatchPath) {
2179
2199
  // 无版本约束补装会覆盖框架正确版本导致服务崩溃——见 backfillMissingDeps 注释)
2180
2200
  if (/^@deepseek-ai\//u.test(ref.name)) continue
2181
2201
  if (existsSync(join(profileDir, 'node_modules', ref.name))) continue
2202
+ // 2026-09-06 加固:本次作业刚完成版本同步的包(transientAllow)此刻缺失=更新中途的瞬时态
2203
+ // (pnpm 原子替换/替换失败窗口),不应按"缺失→自动禁用"处理——跳过本次判定,下次校验时再检查。
2204
+ if (transientAllow.includes(ref.name)) {
2205
+ report.pending.push(ref.name)
2206
+ continue
2207
+ }
2182
2208
  let ok = false
2183
2209
  try {
2184
2210
  await pnpmInstall(profileDir, ref.name, registries[0], 60000)
@@ -3877,7 +3903,7 @@ async function runInstallJob(job, ctx) {
3877
3903
  let ghRepo = typeof job.repo === 'string' && job.repo !== '' && job.repo.includes('/') ? job.repo : null
3878
3904
  if (ghRepo === null) {
3879
3905
  try {
3880
- const meta = entryPkgMeta(name, ctx.baseUrl ?? 'file:///')
3906
+ const meta = entryPkgMeta(name, ctx.baseUrl ?? 'file:///', profileDirOf(ctx))
3881
3907
  const repoUrl = typeof meta?.repository === 'string' ? meta.repository : (meta?.repository && typeof meta.repository === 'object' ? meta.repository.url : null)
3882
3908
  const m = typeof repoUrl === 'string' ? repoUrl.replace(/^git\+/u, '').match(/github\.com[/:]([^/]+\/[^/]+?)(?:\.git)?$/u) : null
3883
3909
  if (m) ghRepo = m[1]
@@ -3983,13 +4009,15 @@ async function runInstallJob(job, ctx) {
3983
4009
  job.bundleNote = (job.bundleNote ? job.bundleNote + ';' : '') + `子包版本对齐:更新 ${synced.length} 个(${synced.join('、')})`
3984
4010
  }
3985
4011
  } catch {}
3986
- // 聚合包完整性保障(防崩):bundle patch 引用的包缺失 → 补装;仍缺自动禁用该行
4012
+ // 聚合包完整性保障(防崩):bundle patch 引用的包缺失 → 补装;仍缺自动禁用该行。
4013
+ // 本次作业刚同步过版本的包(syncedNames)处于更新瞬时态,跳过"缺失自动禁用"判定。
3987
4014
  try {
3988
- const integrity = await ensureBundlePatchIntegrity(profileDir, installedName, patchPath)
4015
+ const integrity = await ensureBundlePatchIntegrity(profileDir, installedName, patchPath, [...syncedNames, installedName])
3989
4016
  if (integrity.checked > 0) {
3990
4017
  job.bundleNote = `聚合包完整性:检查 ${integrity.checked} 个引用`
3991
4018
  + (integrity.installed.length > 0 ? `,补装 ${integrity.installed.length} 个(${integrity.installed.join('、')})` : '')
3992
4019
  + (integrity.disabled.length > 0 ? `,自动禁用缺失行 ${integrity.disabled.length} 个(${integrity.disabled.join('、')})` : '')
4020
+ + (integrity.pending.length > 0 ? `,本次已同步包跳过缺失判定 ${integrity.pending.length} 个(${integrity.pending.join('、')})` : '')
3993
4021
  + (integrity.missing.length > 0 ? `,仍缺失 ${integrity.missing.join('、')}(网络恢复后建议重新更新)` : '')
3994
4022
  }
3995
4023
  } catch {}
@@ -3999,11 +4027,26 @@ async function runInstallJob(job, ctx) {
3999
4027
  if (adapt !== null && adapt.ran === true) job.compatNote = adapt.note
4000
4028
  } catch {}
4001
4029
  job.stage = 'configuring'
4030
+ // 2026-09-06 事故(i18n 更新变重复行):@linxin666/dsh-i18n 声明了 dsh.bundle.patch,
4031
+ // 更新流程按「bundle 安装规则」把它追加进 bundles → 与全家桶内的 web-ui-i18n 行(同包)重复。
4032
+ // 防护:该包已被现有行提供 → 只更新包,不注册任何新行/bundle。
4033
+ const alreadyServed = listEntries(ctx).some((e) => String(e.moduleName).startsWith(installedName)
4034
+ || String(e.moduleName) === installedName
4035
+ || packageNameOf(e.moduleName) === installedName)
4002
4036
  if (await detectBundleOnly(profileDir, installedName)) {
4003
4037
  // 官方 dsh plugin add 行为:声明 dsh.bundle 的包追加为 profile bundle 层,
4004
4038
  // 其 cordis.patch.yml 在下次启动时参与组合(含皮肤包与 web-ui-settings 这类有入口的包)
4005
- await addBundleToManifest(profileDir, installedName)
4006
- job.bundle = true
4039
+ if (!alreadyServed) {
4040
+ await addBundleToManifest(profileDir, installedName)
4041
+ job.bundle = true
4042
+ } else {
4043
+ job.bundleNote = (job.bundleNote ? job.bundleNote + ';' : '') + `${installedName} 已由已安装聚合包提供,仅更新包本身,不再注册重复行`
4044
+ }
4045
+ job.status = 'done'
4046
+ return
4047
+ }
4048
+ if (alreadyServed) {
4049
+ job.note = `${installedName} 已由已安装条目提供,仅更新包本身,不重复注册`
4007
4050
  job.status = 'done'
4008
4051
  return
4009
4052
  }
@@ -4110,7 +4153,7 @@ async function handle(ctx, req, res) {
4110
4153
  }
4111
4154
  } catch {}
4112
4155
  const entries = listEntries(ctx).map((entry) => {
4113
- const meta = entryPkgMeta(entry.moduleName, ctx.baseUrl ?? 'file:///')
4156
+ const meta = entryPkgMeta(entry.moduleName, ctx.baseUrl ?? 'file:///', profileDirOf(ctx))
4114
4157
  return {
4115
4158
  ...entry,
4116
4159
  userDisabled: patch.disables.includes(entry.rowId),
@@ -4301,7 +4344,7 @@ async function handle(ctx, req, res) {
4301
4344
  return
4302
4345
  }
4303
4346
  const moduleName = entry.options.name
4304
- const details = await readPluginDetails(moduleName, ctx.baseUrl ?? 'file:///')
4347
+ const details = await readPluginDetails(moduleName, ctx.baseUrl ?? 'file:///', profileDirOf(ctx))
4305
4348
  sendJson(res, 200, { ok: true, entryId, rowId: rowIdOf(ctx, entryId), moduleName, ...details })
4306
4349
  return
4307
4350
  }
@@ -4897,7 +4940,8 @@ async function handle(ctx, req, res) {
4897
4940
  const profileDir = dirname(patchPath)
4898
4941
  const targets = (pending?.pending ?? []).filter((p) => (p.status ?? 'pending') === 'pending' && (p.moduleName === root || String(p.moduleName).startsWith(root + '/')))
4899
4942
  if (targets.length === 0) {
4900
- sendError(res, 404, '该全家桶没有待适配行(或已全部解锁)')
4943
+ // 无待适配行=全部已适配/已解锁,属正常状态:返回友好提示而非错误(点击「一键启用已适配」不应报"操作失败")
4944
+ sendJson(res, 200, { ok: true, unlocked: [], kept: [], note: '该全家桶没有待适配行(已全部适配/解锁),无需操作' })
4901
4945
  return
4902
4946
  }
4903
4947
  const fwVer = typeof pending.frameworkVersion === 'string' ? pending.frameworkVersion : '?'
@@ -4985,7 +5029,7 @@ async function handle(ctx, req, res) {
4985
5029
  // 覆盖 dsh-plugin-console(本面板)这类"源码在 GitHub、npm 上不存在"的宿主插件。
4986
5030
  let fallbackError = err instanceof Error ? err.message : String(err)
4987
5031
  try {
4988
- const meta = entryPkgMeta(packageName, ctx.baseUrl ?? 'file:///')
5032
+ const meta = entryPkgMeta(packageName, ctx.baseUrl ?? 'file:///', profileDirOf(ctx))
4989
5033
  const repo = typeof meta?.repository === 'string'
4990
5034
  ? meta.repository.replace(/^git\+/u, '').replace(/\.git$/u, '')
4991
5035
  : (meta?.repository && typeof meta.repository === 'object' ? meta.repository.url : null)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noob-stupid/dsh-plugin-console",
3
- "version": "0.3.27",
3
+ "version": "0.3.29",
4
4
  "description": "DSH plugin management panel & marketplace: one-click enable/disable, multi-source market (GitHub/Gitee/custom), static-index market (500+ plugins / 300 skills), skills, suites, and one-click framework upgrade.",
5
5
  "repository": {
6
6
  "type": "git",