@noob-stupid/dsh-plugin-console 0.3.21 → 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/README.md +20 -0
- package/README.zh.md +18 -0
- package/lib/client.js +349 -12
- package/lib/index.js +787 -8
- package/package.json +40 -36
package/README.md
CHANGED
|
@@ -6,6 +6,26 @@
|
|
|
6
6
|
|
|
7
7
|
# DSH Plugin Hub (dsh-plugin-hub)
|
|
8
8
|
|
|
9
|
+
> ## 🧪 v0.3.24-beta.1 — AI Empower open beta (2026-08-31)
|
|
10
|
+
>
|
|
11
|
+
> A new **AI Empower** feature is ready for public testing:
|
|
12
|
+
> give the Plugin Console a package name or GitHub repo, and the local AI reads its
|
|
13
|
+
> docs, drafts a **deployment plan** (install/write config/start service/health check),
|
|
14
|
+
> and — after your confirmation — executes it safely. Server-type components get an
|
|
15
|
+
> automatic control card (start/stop/status/open + dropdown).
|
|
16
|
+
>
|
|
17
|
+
> **Install the beta:**
|
|
18
|
+
> ```bash
|
|
19
|
+
> npm i -g @noob-stupid/dsh-plugin-console@beta
|
|
20
|
+
> # or in DSH: dsh plugin --profile web add @noob-stupid/dsh-plugin-console@beta
|
|
21
|
+
> ```
|
|
22
|
+
> **Try it:** Plugin Console → **AI 赋能** button (below the AI fallback toggle) →
|
|
23
|
+
> enter e.g. `OpenViking` → confirm the plan → watch it deploy.
|
|
24
|
+
>
|
|
25
|
+
> Known limits: docs-driven only (README quality matters); interactive/docker/login-based
|
|
26
|
+
> setups are not supported yet. Feedback: [GitHub Issues](https://github.com/Noob-stupid/dsh-plugin-hub/issues).
|
|
27
|
+
|
|
28
|
+
|
|
9
29
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
10
30
|
[](https://awesome-dsh-plugin.com)
|
|
11
31
|
[](https://github.com/Noob-stupid/dsh-plugin-hub/stargazers)
|
package/README.zh.md
CHANGED
|
@@ -6,6 +6,24 @@
|
|
|
6
6
|
|
|
7
7
|
# DSH 插件中心(dsh-plugin-hub)
|
|
8
8
|
|
|
9
|
+
> ## 🧪 v0.3.24-beta.1 — AI 赋能开放测试(2026-08-31)
|
|
10
|
+
>
|
|
11
|
+
> 全新 **AI 赋能** 功能开放测试:在插件控制台输入 npm 包名或 GitHub 仓库,
|
|
12
|
+
> 本地 AI 读取文档生成**部署计划**(安装/写配置/启动服务/健康检查),
|
|
13
|
+
> 你确认后安全执行;服务器类组件自动生成控制卡片(启动/停止/状态/打开 + 下拉)。
|
|
14
|
+
>
|
|
15
|
+
> **安装测试版:**
|
|
16
|
+
> ```bash
|
|
17
|
+
> npm i -g @noob-stupid/dsh-plugin-console@beta
|
|
18
|
+
> # 或在 DSH 中:dsh plugin --profile web add @noob-stupid/dsh-plugin-console@beta
|
|
19
|
+
> ```
|
|
20
|
+
> **体验入口:** 插件控制台 → 右上角 **AI 赋能** 按钮(AI 兜底按钮正下方)→
|
|
21
|
+
> 输入如 `OpenViking` → 确认计划 → 观看自动部署。
|
|
22
|
+
>
|
|
23
|
+
> **已知限制:** 文档驱动(依赖 README 质量);交互式安装 / docker / 需要登录授权的
|
|
24
|
+
> 组件暂不支持。反馈:[GitHub Issues](https://github.com/Noob-stupid/dsh-plugin-hub/issues)。
|
|
25
|
+
|
|
26
|
+
|
|
9
27
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
10
28
|
[](https://awesome-dsh-plugin.com)
|
|
11
29
|
[](https://github.com/Noob-stupid/dsh-plugin-hub/stargazers)
|
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",
|
|
@@ -171,6 +177,36 @@ window.__ModuleLoader__.load({
|
|
|
171
177
|
aiConsentApprove: "同意,继续(可能产生费用)",
|
|
172
178
|
aiConsentDecline: "取消",
|
|
173
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 赋能部署后自动出现)",
|
|
174
210
|
aiFallbackTitle: "关闭后:常规通道失败将直接取消安装,不再调用模型 API(零费用)",
|
|
175
211
|
aiFallbackOff: "已按设置关闭 AI 兜底,本次安装已取消(零费用)",
|
|
176
212
|
aiConsentRemember: "以后不再提醒(自动同意 AI 兜底,可能产生费用;可随时在插件市场页面最底部恢复提醒)",
|
|
@@ -252,6 +288,10 @@ window.__ModuleLoader__.load({
|
|
|
252
288
|
skillDeleteConfirm: "确认删除技能「{name}」?",
|
|
253
289
|
skillDeletedMsg: "技能已删除",
|
|
254
290
|
skillsEmpty: "技能库为空(自动收录 agent-skills / claude-skills / dsh-skill topic 仓库)",
|
|
291
|
+
skillsEmptyHint: "这里的「已安装技能」只统计用户技能目录(~/.dsh/skills);插件自带的技能(如 openviking-memory)随插件在技能中心提供,不在本列表",
|
|
292
|
+
pluginSkillsTitle: "插件自带技能",
|
|
293
|
+
pluginSkillTag: "插件自带",
|
|
294
|
+
pluginSkillsHint: "由已安装插件提供、只读展示;如需在会话中调用,直接使用技能名即可(如 openviking-memory)",
|
|
255
295
|
skillSystemTag: "系统",
|
|
256
296
|
skillSystemTitle: "系统自带技能(~/.dsh/skills/.system 等保留目录),禁止删除",
|
|
257
297
|
skillDisable: "停用",
|
|
@@ -408,6 +448,36 @@ window.__ModuleLoader__.load({
|
|
|
408
448
|
aiConsentApprove: "Agree, continue (may incur costs)",
|
|
409
449
|
aiConsentDecline: "Cancel",
|
|
410
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)",
|
|
411
481
|
aiFallbackTitle: "When off: if regular channels fail, the install is cancelled directly without calling the model API (zero cost)",
|
|
412
482
|
aiFallbackOff: "AI fallback is disabled by your setting; this install was cancelled (zero cost)",
|
|
413
483
|
aiConsentRemember: "Don't ask again (auto-approve the AI fallback, may incur costs; restore reminders anytime at the very bottom of the market)",
|
|
@@ -489,6 +559,10 @@ window.__ModuleLoader__.load({
|
|
|
489
559
|
skillDeleteConfirm: "Remove skill「{name}」?",
|
|
490
560
|
skillDeletedMsg: "Skill removed",
|
|
491
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)",
|
|
492
566
|
skillSystemTag: "System",
|
|
493
567
|
skillSystemTitle: "System-owned skill (~/.dsh/skills/.system etc.), cannot be removed",
|
|
494
568
|
skillDisable: "Disable",
|
|
@@ -604,6 +678,8 @@ window.__ModuleLoader__.load({
|
|
|
604
678
|
if (!response.ok) throw new Error("GitHub 请求失败 (HTTP " + response.status + ")");
|
|
605
679
|
return response.json();
|
|
606
680
|
}
|
|
681
|
+
/** 对路径中的每一段做百分号编码,保留 "/" 作为分隔符,防止特殊字符篡改目标 URL。 */
|
|
682
|
+
const encodePathSegments = (value) => String(value).split("/").map(encodeURIComponent).join("/");
|
|
607
683
|
/** raw 文件多通道竞速:官方直连 + 常见 gh 镜像,谁先成功用谁;非 GitHub 平台走对应 raw 地址。 */
|
|
608
684
|
const RAW_CANDIDATES = [
|
|
609
685
|
(repo, branch, file) => `${GITHUB_RAW}/${repo}/${branch}/${file}`,
|
|
@@ -612,6 +688,9 @@ window.__ModuleLoader__.load({
|
|
|
612
688
|
(repo, branch, file) => `https://mirror.ghproxy.com/https://raw.githubusercontent.com/${repo}/${branch}/${file}`,
|
|
613
689
|
];
|
|
614
690
|
async function fetchRawText(repo, branch, file, source = "github") {
|
|
691
|
+
repo = encodePathSegments(repo);
|
|
692
|
+
branch = encodePathSegments(branch);
|
|
693
|
+
file = encodePathSegments(file);
|
|
615
694
|
if (source === "gitee") {
|
|
616
695
|
try {
|
|
617
696
|
const res = await fetch(`https://gitee.com/${repo}/raw/${branch}/${file}`, { signal: AbortSignal.timeout(15000) });
|
|
@@ -649,8 +728,13 @@ window.__ModuleLoader__.load({
|
|
|
649
728
|
function summarizeSkillFrontmatter(text) {
|
|
650
729
|
const fm = text.startsWith("---") ? text.slice(3, text.indexOf("\n---", 3)) : "";
|
|
651
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
|
+
};
|
|
652
736
|
const pick = (key) => {
|
|
653
|
-
const m = fm.match(
|
|
737
|
+
const m = fm.match(KEY_PATTERNS[key]);
|
|
654
738
|
if (!m) return "";
|
|
655
739
|
const first = m[1].trim();
|
|
656
740
|
if (first.startsWith("|")) {
|
|
@@ -845,6 +929,7 @@ window.__ModuleLoader__.load({
|
|
|
845
929
|
});
|
|
846
930
|
// 已安装技能清单(~/.dsh/skills),[{name, dir|file}],用于技能条目「已装」标记与已安装区展示
|
|
847
931
|
const [installedSkills, setInstalledSkills] = react.useState([]);
|
|
932
|
+
const [pluginSkills, setPluginSkills] = react.useState([]);
|
|
848
933
|
// 原始页面标题(AI 授权标题闪烁后恢复用)
|
|
849
934
|
const originalTitleRef = react.useRef("");
|
|
850
935
|
// 技能删除两步确认:存待确认技能名
|
|
@@ -930,7 +1015,132 @@ window.__ModuleLoader__.load({
|
|
|
930
1015
|
const [aiFallback, setAiFallback] = react.useState(() => {
|
|
931
1016
|
try { return localStorage.getItem("pc-ai-fallback-v2") !== "off"; } catch { return true; }
|
|
932
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
|
+
}
|
|
933
1140
|
const aiAutoDeclinedRef = react.useRef({});
|
|
1141
|
+
react.useEffect(() => {
|
|
1142
|
+
if (state.status === "ready") { refreshComps(); window.setTimeout(measureCompCardTop, 120); }
|
|
1143
|
+
}, [state.status]);
|
|
934
1144
|
// 已关闭的失败提示(用户点 × 后不再显示,服务重启后重置)
|
|
935
1145
|
const [dismissedFailures, setDismissedFailures] = react.useState({});
|
|
936
1146
|
// 软件源管理
|
|
@@ -1001,7 +1211,10 @@ window.__ModuleLoader__.load({
|
|
|
1001
1211
|
// 挂载时拉取已安装技能清单(技能条目「已装」标记用)
|
|
1002
1212
|
react.useEffect(() => {
|
|
1003
1213
|
call("/plugin-console/skills-installed").then(
|
|
1004
|
-
(data) => {
|
|
1214
|
+
(data) => {
|
|
1215
|
+
if (data && Array.isArray(data.skills)) setInstalledSkills(data.skills);
|
|
1216
|
+
if (data && Array.isArray(data.pluginSkills)) setPluginSkills(data.pluginSkills);
|
|
1217
|
+
},
|
|
1005
1218
|
() => {},
|
|
1006
1219
|
);
|
|
1007
1220
|
}, []);
|
|
@@ -1072,15 +1285,26 @@ window.__ModuleLoader__.load({
|
|
|
1072
1285
|
};
|
|
1073
1286
|
run();
|
|
1074
1287
|
}, [market, state]);
|
|
1075
|
-
// Hub
|
|
1288
|
+
// Hub 自身更新检测:semver 比较,且识别 beta/next 测试版(本地已是测试版最新则不提示)
|
|
1076
1289
|
react.useEffect(() => {
|
|
1077
1290
|
if (state.status !== "ready") return;
|
|
1078
1291
|
const current = state.data.selfVersion ?? null;
|
|
1079
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
|
+
};
|
|
1080
1299
|
call("/plugin-console/check-update", { packageName: "@noob-stupid/dsh-plugin-console" }).then(
|
|
1081
1300
|
(data) => {
|
|
1082
|
-
if (data && data.error === null
|
|
1083
|
-
|
|
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 });
|
|
1084
1308
|
} else {
|
|
1085
1309
|
setSelfUpdate(null);
|
|
1086
1310
|
}
|
|
@@ -1772,7 +1996,13 @@ window.__ModuleLoader__.load({
|
|
|
1772
1996
|
className: styles.toggle,
|
|
1773
1997
|
disabled: (updateCheck !== null && updateCheck.status === "checking") || installing === entry.moduleName,
|
|
1774
1998
|
onClick: () => checkUpdate(entry),
|
|
1775
|
-
}, updateCheck !== null && updateCheck.status === "checking" ? t("checkingUpdate") : t("checkUpdate"))
|
|
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,
|
|
1776
2006
|
updateCheck !== null && updateCheck.status === "ready"
|
|
1777
2007
|
? (updateCheck.error
|
|
1778
2008
|
? el("p", { className: styles.status, "data-error": "true" }, t("updateCheckFailed") + ":" + updateCheck.error)
|
|
@@ -1957,6 +2187,12 @@ window.__ModuleLoader__.load({
|
|
|
1957
2187
|
disabled: repoInfo !== null && repoInfo.status === "loading" && repoInfo.repo === item.fullName,
|
|
1958
2188
|
onClick: () => inspect(item),
|
|
1959
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")),
|
|
1960
2196
|
// 技能条目(技能市场模式 / 技能索引数据):走技能安装通道(clone → ~/.dsh/skills)
|
|
1961
2197
|
item.skillTopics !== undefined
|
|
1962
2198
|
? (() => {
|
|
@@ -2132,10 +2368,88 @@ window.__ModuleLoader__.load({
|
|
|
2132
2368
|
&& (frameworkStatus.status === "done" || frameworkStatus.status === "failed")
|
|
2133
2369
|
&& (() => { try { return localStorage.getItem("pc-fw-dismiss-terminal") === frameworkStatus.status; } catch { return false; } })();
|
|
2134
2370
|
const fwShowCard = frameworkStatus !== null && frameworkStatus.status !== "idle" && !fwStatusDismissed && !fwTerminalDismissed;
|
|
2135
|
-
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" },
|
|
2136
2372
|
state.status === "ready" && state.data.compat && !state.data.compat.supported
|
|
2137
2373
|
? el("p", { className: styles.message, "data-error": "true" }, state.data.compat.notice)
|
|
2138
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,
|
|
2139
2453
|
state.status === "ready" && state.data.framework && state.data.framework.upgraded === true && !frameworkNoticeDismissed
|
|
2140
2454
|
? el("div", { className: styles.messageRow },
|
|
2141
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 : ""))),
|
|
@@ -2271,6 +2585,15 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
2271
2585
|
return next;
|
|
2272
2586
|
}),
|
|
2273
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")),
|
|
2274
2597
|
el("button", {
|
|
2275
2598
|
type: "button",
|
|
2276
2599
|
className: styles.sourcesFloat,
|
|
@@ -2461,9 +2784,22 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
2461
2784
|
)
|
|
2462
2785
|
: null),
|
|
2463
2786
|
mode === "skills"
|
|
2464
|
-
? (installedSkills.length === 0
|
|
2465
|
-
? el("p", { className: styles.status }, t("skillsEmpty"))
|
|
2466
|
-
: el("
|
|
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) =>
|
|
2467
2803
|
el("li", { key: sk.name, className: styles.row },
|
|
2468
2804
|
el("div", { className: styles.rowTop },
|
|
2469
2805
|
el("code", { className: styles.name }, sk.name),
|
|
@@ -2496,7 +2832,8 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
2496
2832
|
title: t("skillDelete"),
|
|
2497
2833
|
"aria-label": t("skillDelete"),
|
|
2498
2834
|
onClick: () => setConfirmSkillDelete(sk.name),
|
|
2499
|
-
}, "✕")))))
|
|
2835
|
+
}, "✕")))))
|
|
2836
|
+
: null))
|
|
2500
2837
|
: (state.status === "loading"
|
|
2501
2838
|
? el("p", { className: styles.status }, t("loading"))
|
|
2502
2839
|
: state.status === "error"
|