@noob-stupid/dsh-plugin-console 0.3.20 → 0.3.24-beta.2

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-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:76px;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:176px;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)}";
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-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)}";
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");
@@ -42,6 +42,12 @@ window.__ModuleLoader__.load({
42
42
  restartBtn: "pc_restartBtn",
43
43
  relaunchFloat: "pc_relaunchFloat",
44
44
  aiToggle: "pc_aiToggle",
45
+ aiEmpower: "pc_aiEmpower",
46
+ compCard: "pc_compCard",
47
+ compDrop: "pc_compDrop",
48
+ compDropRow: "pc_compDropRow",
49
+ compDropUrl: "pc_compDropUrl",
50
+ compToggle: "pc_compToggle",
45
51
  sourcesFloat: "pc_sourcesFloat",
46
52
  modeFloat: "pc_modeFloat",
47
53
  trashBtn: "pc_trashBtn",
@@ -137,6 +143,7 @@ window.__ModuleLoader__.load({
137
143
  githubLoggedIn: "已登录 GitHub:",
138
144
  githubCornerOut: "未登录 GitHub",
139
145
  hubUpdateAvailable: "下载更新",
146
+ cleanResiduals: "清理残余备份",
140
147
  searchInstalledPlaceholder: "搜索已安装插件(名称或 id)",
141
148
  extraFilter: "已装",
142
149
  extraFilterAll: "全部",
@@ -170,6 +177,36 @@ window.__ModuleLoader__.load({
170
177
  aiConsentApprove: "同意,继续(可能产生费用)",
171
178
  aiConsentDecline: "取消",
172
179
  aiFallbackLabel: "AI 兜底",
180
+ aiEmpowerLabel: "AI 赋能",
181
+ aiEmpowerTitle: "AI 赋能:读文档自动规划并部署组件;识别到服务器类组件后自动加启动/停止按钮",
182
+ aiEmpowerSrcTitle: "输入要部署的组件(npm 包名或 GitHub 仓库,如 Noob-stupid/dsh-plugin-hub 或 @noob-stupid/dsh-plugin-console)",
183
+ aiEmpowerPlanTitle: "AI 赋能部署计划",
184
+ aiEmpowerType: "类型",
185
+ aiEmpowerTypeMapping: { "pure-plugin": "纯插件", "service": "服务器组件", "config-only": "仅配置" },
186
+ aiEmpowerSteps: "执行步骤(可勾选)",
187
+ aiEmpowerRun: "执行所选步骤",
188
+ aiEmpowerCancel: "取消",
189
+ aiEmpowerWaiting: "等待 AI 分析文档并生成计划(约 1-5 分钟,会调用 DeepSeek API,可能产生费用)…",
190
+ aiEmpowerExecuting: "AI 赋能执行中…",
191
+ aiEmpowerDone: "AI 赋能部署完成",
192
+ aiEmpowerFail: "AI 赋能失败",
193
+ aiEmpowerLogs: "执行日志",
194
+ aiEmpowerComponents: "已识别的服务器组件",
195
+ compStart: "启动",
196
+ compStop: "停止",
197
+ compStatus: "状态",
198
+ compOpen: "打开",
199
+ compRunning: "运行中",
200
+ compStopped: "未运行",
201
+ compHealthy: "健康",
202
+ compUnhealthy: "不健康",
203
+ compRefresh: "刷新组件状态",
204
+ compDropTitle: "展开所有服务器,点击打开网址",
205
+ compNoUrl: "暂无网址",
206
+ compCollapseTitle: "收缩组件卡片",
207
+ compExpandTitle: "展开组件卡片",
208
+ compActionDone: "{action}:{name}",
209
+ noComponents: "暂无已识别的服务器组件(用 AI 赋能部署后自动出现)",
173
210
  aiFallbackTitle: "关闭后:常规通道失败将直接取消安装,不再调用模型 API(零费用)",
174
211
  aiFallbackOff: "已按设置关闭 AI 兜底,本次安装已取消(零费用)",
175
212
  aiConsentRemember: "以后不再提醒(自动同意 AI 兜底,可能产生费用;可随时在插件市场页面最底部恢复提醒)",
@@ -251,6 +288,10 @@ window.__ModuleLoader__.load({
251
288
  skillDeleteConfirm: "确认删除技能「{name}」?",
252
289
  skillDeletedMsg: "技能已删除",
253
290
  skillsEmpty: "技能库为空(自动收录 agent-skills / claude-skills / dsh-skill topic 仓库)",
291
+ skillsEmptyHint: "这里的「已安装技能」只统计用户技能目录(~/.dsh/skills);插件自带的技能(如 openviking-memory)随插件在技能中心提供,不在本列表",
292
+ pluginSkillsTitle: "插件自带技能",
293
+ pluginSkillTag: "插件自带",
294
+ pluginSkillsHint: "由已安装插件提供、只读展示;如需在会话中调用,直接使用技能名即可(如 openviking-memory)",
254
295
  skillSystemTag: "系统",
255
296
  skillSystemTitle: "系统自带技能(~/.dsh/skills/.system 等保留目录),禁止删除",
256
297
  skillDisable: "停用",
@@ -372,6 +413,7 @@ window.__ModuleLoader__.load({
372
413
  loadingDetails: "Reading details…",
373
414
  githubLoggedIn: "GitHub signed in: ",
374
415
  hubUpdateAvailable: "Download update",
416
+ cleanResiduals: "Clean residual backups",
375
417
  githubCornerOut: "Not signed in to GitHub",
376
418
  searchInstalledPlaceholder: "Search installed plugins (name or id)",
377
419
  extraFilter: "Installed",
@@ -406,6 +448,36 @@ window.__ModuleLoader__.load({
406
448
  aiConsentApprove: "Agree, continue (may incur costs)",
407
449
  aiConsentDecline: "Cancel",
408
450
  aiFallbackLabel: "AI fallback",
451
+ aiEmpowerLabel: "AI Empower",
452
+ aiEmpowerTitle: "AI Empower: read docs, plan and deploy a component automatically; server-type components get start/stop buttons",
453
+ aiEmpowerSrcTitle: "Component to deploy (npm package or GitHub repo)",
454
+ aiEmpowerPlanTitle: "AI Empower deployment plan",
455
+ aiEmpowerType: "Type",
456
+ aiEmpowerTypeMapping: { "pure-plugin": "Pure plugin", "service": "Server component", "config-only": "Config only" },
457
+ aiEmpowerSteps: "Steps to execute (selectable)",
458
+ aiEmpowerRun: "Run selected steps",
459
+ aiEmpowerCancel: "Cancel",
460
+ aiEmpowerWaiting: "AI is analyzing the docs and drafting the plan (1-5 min, calls DeepSeek API, may incur costs)…",
461
+ aiEmpowerExecuting: "AI Empower executing…",
462
+ aiEmpowerDone: "AI Empower deployment finished",
463
+ aiEmpowerFail: "AI Empower failed",
464
+ aiEmpowerLogs: "Execution log",
465
+ aiEmpowerComponents: "Detected server components",
466
+ compStart: "Start",
467
+ compStop: "Stop",
468
+ compStatus: "Status",
469
+ compOpen: "Open",
470
+ compRunning: "Running",
471
+ compStopped: "Stopped",
472
+ compHealthy: "Healthy",
473
+ compUnhealthy: "Unhealthy",
474
+ compRefresh: "Refresh component status",
475
+ compDropTitle: "Expand to open all server URLs",
476
+ compNoUrl: "No URL yet",
477
+ compCollapseTitle: "Collapse server card",
478
+ compExpandTitle: "Expand server card",
479
+ compActionDone: "{action}: {name}",
480
+ noComponents: "No server components yet (they appear after an AI Empower deployment)",
409
481
  aiFallbackTitle: "When off: if regular channels fail, the install is cancelled directly without calling the model API (zero cost)",
410
482
  aiFallbackOff: "AI fallback is disabled by your setting; this install was cancelled (zero cost)",
411
483
  aiConsentRemember: "Don't ask again (auto-approve the AI fallback, may incur costs; restore reminders anytime at the very bottom of the market)",
@@ -487,6 +559,10 @@ window.__ModuleLoader__.load({
487
559
  skillDeleteConfirm: "Remove skill「{name}」?",
488
560
  skillDeletedMsg: "Skill removed",
489
561
  skillsEmpty: "Skill library is empty (auto-collected from agent-skills / claude-skills / dsh-skill topic repos)",
562
+ skillsEmptyHint: "This list only counts user skills (~/.dsh/skills); plugin-provided skills (e.g. openviking-memory) appear in the Skill Center, not here",
563
+ pluginSkillsTitle: "Plugin-provided skills",
564
+ pluginSkillTag: "Plugin",
565
+ pluginSkillsHint: "Provided by installed plugins, read-only; invoke by skill name (e.g. openviking-memory)",
490
566
  skillSystemTag: "System",
491
567
  skillSystemTitle: "System-owned skill (~/.dsh/skills/.system etc.), cannot be removed",
492
568
  skillDisable: "Disable",
@@ -602,6 +678,8 @@ window.__ModuleLoader__.load({
602
678
  if (!response.ok) throw new Error("GitHub 请求失败 (HTTP " + response.status + ")");
603
679
  return response.json();
604
680
  }
681
+ /** 对路径中的每一段做百分号编码,保留 "/" 作为分隔符,防止特殊字符篡改目标 URL。 */
682
+ const encodePathSegments = (value) => String(value).split("/").map(encodeURIComponent).join("/");
605
683
  /** raw 文件多通道竞速:官方直连 + 常见 gh 镜像,谁先成功用谁;非 GitHub 平台走对应 raw 地址。 */
606
684
  const RAW_CANDIDATES = [
607
685
  (repo, branch, file) => `${GITHUB_RAW}/${repo}/${branch}/${file}`,
@@ -610,6 +688,9 @@ window.__ModuleLoader__.load({
610
688
  (repo, branch, file) => `https://mirror.ghproxy.com/https://raw.githubusercontent.com/${repo}/${branch}/${file}`,
611
689
  ];
612
690
  async function fetchRawText(repo, branch, file, source = "github") {
691
+ repo = encodePathSegments(repo);
692
+ branch = encodePathSegments(branch);
693
+ file = encodePathSegments(file);
613
694
  if (source === "gitee") {
614
695
  try {
615
696
  const res = await fetch(`https://gitee.com/${repo}/raw/${branch}/${file}`, { signal: AbortSignal.timeout(15000) });
@@ -647,8 +728,13 @@ window.__ModuleLoader__.load({
647
728
  function summarizeSkillFrontmatter(text) {
648
729
  const fm = text.startsWith("---") ? text.slice(3, text.indexOf("\n---", 3)) : "";
649
730
  if (fm === "") return null;
731
+ const KEY_PATTERNS = {
732
+ name: /^name:\s*(.*)$/mu,
733
+ description: /^description:\s*(.*)$/mu,
734
+ whenToUse: /^whenToUse:\s*(.*)$/mu,
735
+ };
650
736
  const pick = (key) => {
651
- const m = fm.match(new RegExp("^" + key + ":\\s*(.*)$", "mu"));
737
+ const m = fm.match(KEY_PATTERNS[key]);
652
738
  if (!m) return "";
653
739
  const first = m[1].trim();
654
740
  if (first.startsWith("|")) {
@@ -843,6 +929,7 @@ window.__ModuleLoader__.load({
843
929
  });
844
930
  // 已安装技能清单(~/.dsh/skills),[{name, dir|file}],用于技能条目「已装」标记与已安装区展示
845
931
  const [installedSkills, setInstalledSkills] = react.useState([]);
932
+ const [pluginSkills, setPluginSkills] = react.useState([]);
846
933
  // 原始页面标题(AI 授权标题闪烁后恢复用)
847
934
  const originalTitleRef = react.useRef("");
848
935
  // 技能删除两步确认:存待确认技能名
@@ -928,7 +1015,132 @@ window.__ModuleLoader__.load({
928
1015
  const [aiFallback, setAiFallback] = react.useState(() => {
929
1016
  try { return localStorage.getItem("pc-ai-fallback-v2") !== "off"; } catch { return true; }
930
1017
  });
1018
+ // AI 赋能:来源输入 / 计划确认 / 执行进度
1019
+ const [aiOpen, setAiOpen] = react.useState(false);
1020
+ const [aiSource, setAiSource] = react.useState("");
1021
+ const [aiJob, setAiJob] = react.useState(null);
1022
+ const [aiSelected, setAiSelected] = react.useState({});
1023
+ const [aiRunning, setAiRunning] = react.useState(false);
1024
+ // 服务器组件清单(AI 赋能注册的服务型组件)
1025
+ const [comps, setComps] = react.useState([]);
1026
+ const [compBusy, setCompBusy] = react.useState(null);
1027
+ const [compDropOpen, setCompDropOpen] = react.useState(false);
1028
+ const [compCollapsed, setCompCollapsed] = react.useState(() => {
1029
+ try { return localStorage.getItem("pc-comp-collapsed") === "1"; } catch { return false; }
1030
+ });
1031
+ const sectionRef = react.useRef(null);
1032
+ const [compCardTop, setCompCardTop] = react.useState(null);
1033
+ function measureCompCardTop() {
1034
+ const host = sectionRef.current;
1035
+ if (!host) return;
1036
+ const secTop = host.getBoundingClientRect().top;
1037
+ let top = secTop;
1038
+ let node = host.parentElement;
1039
+ while (node) {
1040
+ const r = node.getBoundingClientRect();
1041
+ if (r.height > 10 && r.height <= 1600) {
1042
+ if (r.top < top - 28) { top = r.top; break; }
1043
+ if (r.top > top + 2) break;
1044
+ }
1045
+ node = node.parentElement;
1046
+ }
1047
+ setCompCardTop(`${Math.max(8, Math.round(top))}px`);
1048
+ }
1049
+ async function refreshComps() {
1050
+ try {
1051
+ const data = await call("/plugin-console/components", {});
1052
+ if (data && data.ok === true) setComps(data.components ?? []);
1053
+ else setComps([]);
1054
+ } catch { setComps([]); }
1055
+ window.setTimeout(measureCompCardTop, 50);
1056
+ }
1057
+ async function aiPoll(jobId) {
1058
+ try {
1059
+ const data = await call("/plugin-console/ai-empower/status", { jobId });
1060
+ if (data && data.ok === true) {
1061
+ setAiJob(data);
1062
+ if (data.status === "running") {
1063
+ window.setTimeout(() => aiPoll(jobId), 2500);
1064
+ return;
1065
+ }
1066
+ if (data.status === "plan-ready") {
1067
+ const sel = {};
1068
+ for (const s of data.steps ?? []) sel[s.index] = true;
1069
+ setAiSelected(sel);
1070
+ }
1071
+ setAiRunning(false);
1072
+ refreshComps();
1073
+ }
1074
+ } catch (error) {
1075
+ setAiJob((prev) => ({ ...(prev ?? {}), status: "failed", error: error.message }));
1076
+ setAiRunning(false);
1077
+ }
1078
+ }
1079
+ function openAiFor(source) {
1080
+ setAiSource(String(source ?? ""));
1081
+ setAiJob(null);
1082
+ setAiRunning(false);
1083
+ setAiOpen(true);
1084
+ }
1085
+ async function aiStartPlan() {
1086
+ const source = aiSource.trim();
1087
+ if (source === "") return;
1088
+ setAiJob(null);
1089
+ setAiRunning(true); try {
1090
+ const data = await call("/plugin-console/ai-empower/plan", { source });
1091
+ if (data && data.ok === true) { setAiJob({ jobId: data.jobId, source, status: "running", stage: "planning" }); aiPoll(data.jobId); }
1092
+ else { setAiRunning(false); setMessage(t("failed") + ":" + (data?.error ?? "未知")); }
1093
+ } catch (error) {
1094
+ setAiRunning(false);
1095
+ setMessage(t("failed") + ":" + friendlyGithubError(error).message);
1096
+ }
1097
+ }
1098
+ async function aiRun() {
1099
+ if (aiJob === null || aiJob.status !== "plan-ready") return;
1100
+ const steps = (aiJob.steps ?? []).map((s) => s.index).filter((i) => aiSelected[i]);
1101
+ setAiRunning(true);
1102
+ try {
1103
+ await call("/plugin-console/ai-empower/run", { jobId: aiJob.jobId, steps });
1104
+ aiPoll(aiJob.jobId);
1105
+ } catch (error) {
1106
+ setAiRunning(false);
1107
+ setMessage(t("failed") + ":" + friendlyGithubError(error).message);
1108
+ }
1109
+ }
1110
+ async function aiCancel() {
1111
+ if (aiJob === null) return;
1112
+ try { await call("/plugin-console/ai-empower/cancel", { jobId: aiJob.jobId }); } catch {}
1113
+ setAiRunning(false);
1114
+ await aiPoll(aiJob.jobId).catch(() => {});
1115
+ }
1116
+ async function compAction(id, action) {
1117
+ setCompBusy(id);
1118
+ try {
1119
+ const data = await call("/plugin-console/component/" + action, { id });
1120
+ setMessage(t("compActionDone").replace("{action}", t(action === "start" ? "compStart" : "compStop")).replace("{name}", data?.name ?? id));
1121
+ } catch (error) {
1122
+ setMessage(t("failed") + ":" + error.message);
1123
+ }
1124
+ setCompBusy(null);
1125
+ refreshComps();
1126
+ }
1127
+ async function compStatusOne(id) {
1128
+ setCompBusy(id);
1129
+ try {
1130
+ const data = await call("/plugin-console/component/status", { id });
1131
+ if (data && data.ok === true) {
1132
+ setMessage(data.running ? (data.healthy ? t("compHealthy") : t("compUnhealthy")) + ":" + (data.name ?? id) : t("compStopped") + ":" + (data.name ?? id));
1133
+ }
1134
+ } catch (error) {
1135
+ setMessage(t("failed") + ":" + error.message);
1136
+ }
1137
+ setCompBusy(null);
1138
+ refreshComps();
1139
+ }
931
1140
  const aiAutoDeclinedRef = react.useRef({});
1141
+ react.useEffect(() => {
1142
+ if (state.status === "ready") { refreshComps(); window.setTimeout(measureCompCardTop, 120); }
1143
+ }, [state.status]);
932
1144
  // 已关闭的失败提示(用户点 × 后不再显示,服务重启后重置)
933
1145
  const [dismissedFailures, setDismissedFailures] = react.useState({});
934
1146
  // 软件源管理
@@ -999,7 +1211,10 @@ window.__ModuleLoader__.load({
999
1211
  // 挂载时拉取已安装技能清单(技能条目「已装」标记用)
1000
1212
  react.useEffect(() => {
1001
1213
  call("/plugin-console/skills-installed").then(
1002
- (data) => { if (data && Array.isArray(data.skills)) setInstalledSkills(data.skills); },
1214
+ (data) => {
1215
+ if (data && Array.isArray(data.skills)) setInstalledSkills(data.skills);
1216
+ if (data && Array.isArray(data.pluginSkills)) setPluginSkills(data.pluginSkills);
1217
+ },
1003
1218
  () => {},
1004
1219
  );
1005
1220
  }, []);
@@ -1070,15 +1285,26 @@ window.__ModuleLoader__.load({
1070
1285
  };
1071
1286
  run();
1072
1287
  }, [market, state]);
1073
- // Hub 自身更新检测:只在远程 npm 有更新时显示按钮
1288
+ // Hub 自身更新检测:semver 比较,且识别 beta/next 测试版(本地已是测试版最新则不提示)
1074
1289
  react.useEffect(() => {
1075
1290
  if (state.status !== "ready") return;
1076
1291
  const current = state.data.selfVersion ?? null;
1077
1292
  if (!current) return;
1293
+ const ver = (v) => {
1294
+ try {
1295
+ const m = String(v).match(/^(\d+)\.(\d+)\.(\d+)/);
1296
+ return m ? Number(m[1]) * 1000000 + Number(m[2]) * 1000 + Number(m[3]) : 0;
1297
+ } catch { return 0; }
1298
+ };
1078
1299
  call("/plugin-console/check-update", { packageName: "@noob-stupid/dsh-plugin-console" }).then(
1079
1300
  (data) => {
1080
- if (data && data.error === null && typeof data.latest === "string" && data.latest !== current) {
1081
- setSelfUpdate({ latest: data.latest });
1301
+ if (data && data.error === null) {
1302
+ const candidates = [data.latest, data.next, data.beta].filter((v) => typeof v === "string" && v !== "");
1303
+ let better = null;
1304
+ for (const v of candidates) {
1305
+ if (ver(v) > ver(current) && (better === null || ver(v) > ver(better))) better = v;
1306
+ }
1307
+ setSelfUpdate(better === null ? null : { latest: better });
1082
1308
  } else {
1083
1309
  setSelfUpdate(null);
1084
1310
  }
@@ -1770,7 +1996,13 @@ window.__ModuleLoader__.load({
1770
1996
  className: styles.toggle,
1771
1997
  disabled: (updateCheck !== null && updateCheck.status === "checking") || installing === entry.moduleName,
1772
1998
  onClick: () => checkUpdate(entry),
1773
- }, updateCheck !== null && updateCheck.status === "checking" ? t("checkingUpdate") : t("checkUpdate"))) : null,
1999
+ }, updateCheck !== null && updateCheck.status === "checking" ? t("checkingUpdate") : t("checkUpdate")),
2000
+ el("button", {
2001
+ type: "button",
2002
+ className: styles.toggle,
2003
+ title: t("aiEmpowerTitle"),
2004
+ onClick: () => openAiFor(String(entry.moduleName ?? entry.repo ?? "")),
2005
+ }, t("aiEmpowerLabel"))) : null,
1774
2006
  updateCheck !== null && updateCheck.status === "ready"
1775
2007
  ? (updateCheck.error
1776
2008
  ? el("p", { className: styles.status, "data-error": "true" }, t("updateCheckFailed") + ":" + updateCheck.error)
@@ -1955,6 +2187,12 @@ window.__ModuleLoader__.load({
1955
2187
  disabled: repoInfo !== null && repoInfo.status === "loading" && repoInfo.repo === item.fullName,
1956
2188
  onClick: () => inspect(item),
1957
2189
  }, t("view")),
2190
+ el("button", {
2191
+ type: "button",
2192
+ className: styles.toggle,
2193
+ title: t("aiEmpowerTitle"),
2194
+ onClick: () => openAiFor(item.fullName),
2195
+ }, t("aiEmpowerLabel")),
1958
2196
  // 技能条目(技能市场模式 / 技能索引数据):走技能安装通道(clone → ~/.dsh/skills)
1959
2197
  item.skillTopics !== undefined
1960
2198
  ? (() => {
@@ -2130,10 +2368,88 @@ window.__ModuleLoader__.load({
2130
2368
  && (frameworkStatus.status === "done" || frameworkStatus.status === "failed")
2131
2369
  && (() => { try { return localStorage.getItem("pc-fw-dismiss-terminal") === frameworkStatus.status; } catch { return false; } })();
2132
2370
  const fwShowCard = frameworkStatus !== null && frameworkStatus.status !== "idle" && !fwStatusDismissed && !fwTerminalDismissed;
2133
- return el("section", { className: styles.section, "aria-busy": state.status === "loading" },
2371
+ return el("section", { ref: sectionRef, className: styles.section, "aria-busy": state.status === "loading" },
2134
2372
  state.status === "ready" && state.data.compat && !state.data.compat.supported
2135
2373
  ? el("p", { className: styles.message, "data-error": "true" }, state.data.compat.notice)
2136
2374
  : null,
2375
+ state.status === "ready" && comps.length > 0 && details === null && repoInfo === null
2376
+ ? el("button", {
2377
+ type: "button",
2378
+ className: styles.compToggle,
2379
+ style: compCardTop !== null ? { top: compCardTop, left: compCollapsed ? "8px" : "336px" } : { left: compCollapsed ? "8px" : "336px" },
2380
+ title: t(compCollapsed ? "compExpandTitle" : "compCollapseTitle"),
2381
+ "aria-label": t(compCollapsed ? "compExpandTitle" : "compCollapseTitle"),
2382
+ onClick: () => setCompCollapsed((v) => {
2383
+ const next = !v;
2384
+ try { localStorage.setItem("pc-comp-collapsed", next ? "1" : "0"); } catch {}
2385
+ return next;
2386
+ }),
2387
+ }, compCollapsed ? "▶" : "◀")
2388
+ : null,
2389
+ state.status === "ready" && comps.length > 0 && !compCollapsed && details === null && repoInfo === null
2390
+ ? el("div", { className: styles.compCard, style: compCardTop !== null ? { top: compCardTop } : undefined },
2391
+ el("div", { className: styles.rowTop },
2392
+ el("strong", { className: styles.name }, t("aiEmpowerComponents") + "(" + comps.length + ")"),
2393
+ el("button", { type: "button", className: styles.toggle, onClick: refreshComps }, t("compRefresh")),
2394
+ comps.length > 1
2395
+ ? el("button", { type: "button", className: styles.toggle, "data-active": compDropOpen ? "true" : "false", title: t("compDropTitle"), onClick: () => setCompDropOpen((v) => !v) }, compDropOpen ? "▴" : "▾")
2396
+ : null),
2397
+ compDropOpen && comps.length > 1
2398
+ ? el("div", { className: styles.compDrop },
2399
+ comps.map((c) =>
2400
+ el("button", { key: c.id, type: "button", className: styles.compDropRow, onClick: () => { if (c.uiUrl) window.open(c.uiUrl, "_blank", "noopener"); } },
2401
+ el("span", null, c.name + "(" + t(c.running ? "compRunning" : "compStopped") + ")"),
2402
+ el("span", { className: styles.compDropUrl }, c.uiUrl ?? t("compNoUrl")))))
2403
+ : null,
2404
+ comps.map((c) =>
2405
+ el("div", { key: c.id, className: styles.rowTop, style: { flexWrap: "wrap" } },
2406
+ el("strong", { className: styles.name, style: { flex: "1 1 auto" } }, c.name),
2407
+ el("span", { className: styles.tag, "data-enabled": c.running ? "true" : "false" }, c.running ? t("compRunning") : t("compStopped")),
2408
+ (c.running && c.healthy !== null) ? el("span", { className: styles.tag, "data-enabled": c.healthy ? "true" : "false" }, c.healthy ? t("compHealthy") : t("compUnhealthy")) : null,
2409
+ el("div", { className: styles.rowTop },
2410
+ el("button", { type: "button", className: styles.toggle, disabled: c.running || compBusy === c.id, onClick: () => compAction(c.id, "start") }, t("compStart")),
2411
+ el("button", { type: "button", className: styles.toggle, disabled: !c.running || compBusy === c.id, onClick: () => compAction(c.id, "stop") }, t("compStop")),
2412
+ el("button", { type: "button", className: styles.toggle, disabled: compBusy === c.id, onClick: () => compStatusOne(c.id) }, t("compStatus")),
2413
+ el("button", { type: "button", className: styles.toggle, disabled: !c.uiUrl, title: c.uiUrl ?? "", onClick: () => { if (c.uiUrl) window.open(c.uiUrl, "_blank", "noopener"); } }, t("compOpen"))))))
2414
+ : null,
2415
+ aiOpen
2416
+ ? el("div", { className: styles.modalBackdrop },
2417
+ el("div", { className: styles.modalCard, style: { maxWidth: 560 } },
2418
+ el("div", { className: styles.rowTop, style: { justifyContent: "space-between" } },
2419
+ el("strong", { className: styles.name }, t("aiEmpowerLabel")),
2420
+ el("button", { type: "button", className: styles.trashBtn, style: { fontSize: 14, padding: "4px 8px" }, title: t("closeModal"), "aria-label": t("closeModal"), onClick: () => setAiOpen(false) }, "✕")),
2421
+ aiJob === null || (aiJob.status === "running" && aiJob.stage === "planning")
2422
+ ? el("div", { style: { flexDirection: "column", gap: "10px", display: "flex" } },
2423
+ el("section", null,
2424
+ el("input", { type: "text", placeholder: t("aiEmpowerSrcTitle"), value: aiSource, disabled: aiRunning, onChange: (event) => setAiSource(event.currentTarget.value), onKeyDown: (event) => { if (event.key === "Enter" && !aiRunning) aiStartPlan(); }, style: { width: "100%", boxSizing: "border-box", font: "inherit", padding: "6px 10px", borderRadius: 8, border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-1)", color: "var(--dsw-alias-label-primary)" } }),
2425
+ el("div", { className: styles.rowTop },
2426
+ el("button", { type: "button", className: styles.toggle, disabled: aiRunning || aiSource.trim() === "", onClick: aiStartPlan }, t("aiEmpowerLabel")),
2427
+ aiRunning ? el("span", { className: styles.message }, t("aiEmpowerWaiting")) : null)))
2428
+ : aiJob.status === "plan-ready"
2429
+ ? el("div", { style: { flexDirection: "column", gap: "10px", display: "flex" } },
2430
+ el("div", { className: styles.rowTop },
2431
+ el("strong", { className: styles.name }, (aiJob.displayName ?? aiJob.source) + ":"),
2432
+ el("span", { className: styles.tag }, t("aiEmpowerType") + ":" + (t("aiEmpowerTypeMapping")[aiJob.type] ?? aiJob.type ?? "?"))),
2433
+ aiJob.summary ? el("p", { className: styles.message }, aiJob.summary) : null,
2434
+ (aiJob.servers ?? []).length > 0
2435
+ ? el("p", { className: styles.message }, (aiJob.servers ?? []).map((s) => (s.name ?? "?") + (s.port ? "(端口 " + s.port + ")" : "")).join("、"))
2436
+ : null,
2437
+ el("strong", { className: styles.name }, t("aiEmpowerSteps")),
2438
+ el("div", { style: { flexDirection: "column", gap: "6px", display: "flex", maxHeight: 220, overflowY: "auto" } },
2439
+ (aiJob.steps ?? []).map((s) =>
2440
+ el("label", { key: s.index, className: styles.consentRemember, style: { alignItems: "flex-start" } },
2441
+ el("input", { type: "checkbox", checked: aiSelected[s.index] === true, onChange: (event) => setAiSelected((prev) => ({ ...prev, [s.index]: event.currentTarget.checked })) }),
2442
+ el("span", null, (s.index + 1) + ". [" + s.action + "] " + (s.description ?? "") + (s.path ? " → " + s.path : "")))),
2443
+ el("div", { className: styles.rowTop },
2444
+ el("button", { type: "button", className: styles.toggle, onClick: aiRun }, t("aiEmpowerRun")),
2445
+ el("button", { type: "button", className: styles.toggle, onClick: () => { setAiJob(null); setAiRunning(false); } }, t("aiEmpowerCancel")))))
2446
+ : el("div", { style: { flexDirection: "column", gap: "10px", display: "flex" } },
2447
+ el("p", { className: styles.message, "data-error": aiJob.status === "failed" ? "true" : undefined }, aiJob.status === "done" ? t("aiEmpowerDone") : aiJob.status === "failed" ? t("aiEmpowerFail") + ":" + (aiJob.error ?? "?") : t("aiEmpowerExecuting") + "(" + (aiJob.progress?.done ?? 0) + "/" + (aiJob.progress?.total ?? "?") + ")"),
2448
+ el("pre", { style: { maxHeight: 200, overflow: "auto", whiteSpace: "pre-wrap", wordBreak: "break-all", background: "var(--dsw-alias-bg-layer-2)", border: "1px solid var(--dsw-alias-border-l2)", borderRadius: 8, padding: 8, fontSize: 11, margin: 0, fontFamily: "inherit" } }, aiJob.logText ?? ""),
2449
+ el("div", { className: styles.rowTop },
2450
+ (aiJob.status === "running") ? el("button", { type: "button", className: styles.toggle, onClick: aiCancel }, t("aiEmpowerCancel")) : null,
2451
+ el("button", { type: "button", className: styles.toggle, onClick: () => { setAiJob(null); } }, t("closeModal"))))))
2452
+ : null,
2137
2453
  state.status === "ready" && state.data.framework && state.data.framework.upgraded === true && !frameworkNoticeDismissed
2138
2454
  ? el("div", { className: styles.messageRow },
2139
2455
  el("p", { className: styles.message }, t("frameworkUpgradeNotice").replace("{from}", state.data.framework.from ?? "?").replace("{to}", state.data.framework.version ?? "?").replace("{dir}", state.data.framework.backupDir ?? "").replace("{patch}", state.data.framework.patchApplied === true ? t("frameworkPatchApplied") : t("frameworkPatchSkipped") + (state.data.framework.patchNote ? ":" + state.data.framework.patchNote : ""))),
@@ -2153,6 +2469,20 @@ window.__ModuleLoader__.load({
2153
2469
  },
2154
2470
  }, t("relaunchBtn"))
2155
2471
  : null,
2472
+ el("button", {
2473
+ type: "button",
2474
+ style: { position: "fixed", left: 12, bottom: 12, zIndex: 1000, opacity: 0.75 },
2475
+ title: t("cleanResiduals"),
2476
+ onClick: () => {
2477
+ setMessage(t("cleanResiduals") + "…");
2478
+ call("/plugin-console/clean-residuals", {}).then(
2479
+ (data) => {
2480
+ if (data && data.ok === true) setMessage(t("cleanResiduals") + ":" + (data.count === 0 ? "无残余" : "已清理 " + data.count + " 项"));
2481
+ },
2482
+ (error) => setMessage(t("failed") + ":" + friendlyGithubError(error).message),
2483
+ );
2484
+ },
2485
+ }, "🧹 " + t("cleanResiduals")),
2156
2486
  fwShowCard
2157
2487
  ? el("div", { className: styles.detail },
2158
2488
  el("div", { className: styles.rowTop },
@@ -2255,6 +2585,15 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
2255
2585
  return next;
2256
2586
  }),
2257
2587
  }, t("aiFallbackLabel")),
2588
+ el("button", {
2589
+ type: "button",
2590
+ className: styles.aiEmpower,
2591
+ "data-busy": aiRunning ? "true" : "false",
2592
+ "data-active": aiOpen ? "true" : "false",
2593
+ title: t("aiEmpowerTitle"),
2594
+ "aria-label": t("aiEmpowerLabel"),
2595
+ onClick: () => setAiOpen((v) => !v),
2596
+ }, t("aiEmpowerLabel")),
2258
2597
  el("button", {
2259
2598
  type: "button",
2260
2599
  className: styles.sourcesFloat,
@@ -2445,9 +2784,22 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
2445
2784
  )
2446
2785
  : null),
2447
2786
  mode === "skills"
2448
- ? (installedSkills.length === 0
2449
- ? el("p", { className: styles.status }, t("skillsEmpty"))
2450
- : el("ul", { className: styles.list }, installedSkills.map((sk) =>
2787
+ ? (installedSkills.length === 0 && pluginSkills.length === 0
2788
+ ? el("p", { className: styles.status, "data-error": "false" }, t("skillsEmpty") + "。" + t("skillsEmptyHint"))
2789
+ : el("div", { style: { flexDirection: "column", gap: 8, display: "flex" } },
2790
+ pluginSkills.length > 0
2791
+ ? el("div", { className: styles.detail },
2792
+ el("strong", { className: styles.name }, t("pluginSkillsTitle") + "(" + pluginSkills.length + ")"),
2793
+ el("p", { className: styles.status }, t("pluginSkillsHint")),
2794
+ el("ul", { className: styles.list }, pluginSkills.map((sk) =>
2795
+ el("li", { key: sk.name, className: styles.row },
2796
+ el("div", { className: styles.rowTop },
2797
+ el("code", { className: styles.name }, sk.name),
2798
+ el("span", { className: styles.tag, "data-system": "true" }, t("pluginSkillTag") + (sk.provider ? " · " + sk.provider : ""))),
2799
+ sk.description ? el("p", { className: styles.desc }, sk.description) : null))))
2800
+ : null,
2801
+ installedSkills.length > 0
2802
+ ? el("ul", { className: styles.list }, installedSkills.map((sk) =>
2451
2803
  el("li", { key: sk.name, className: styles.row },
2452
2804
  el("div", { className: styles.rowTop },
2453
2805
  el("code", { className: styles.name }, sk.name),
@@ -2480,7 +2832,8 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
2480
2832
  title: t("skillDelete"),
2481
2833
  "aria-label": t("skillDelete"),
2482
2834
  onClick: () => setConfirmSkillDelete(sk.name),
2483
- }, "✕"))))))
2835
+ }, "✕")))))
2836
+ : null))
2484
2837
  : (state.status === "loading"
2485
2838
  ? el("p", { className: styles.status }, t("loading"))
2486
2839
  : state.status === "error"