dsh-plugin-capabilities 0.3.8 → 0.3.9
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 +3 -3
- package/lib/client.js +96 -13
- package/lib/client.js.map +2 -2
- package/lib/index.js +175 -8
- package/lib/index.js.map +2 -2
- package/package.json +1 -1
- package/src/agents.test.ts +47 -1
- package/src/agents.ts +59 -8
- package/src/client/MarketTab.tsx +23 -7
- package/src/client/McpTab.tsx +69 -4
- package/src/client/index.ts +7 -4
- package/src/client/locales.ts +14 -4
- package/src/mcp.test.ts +70 -2
- package/src/mcp.ts +78 -0
- package/src/routes.ts +81 -6
package/README.md
CHANGED
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
|
|
28
28
|
「MCP」页管理 profile patch 中的 MCP 服务器行,每行对应一个 `@deepseek-ai/dsh-mcp-client` 实例。stdio 服务器填写命令与参数,streamable-http 服务器填写 URL,编辑、停用、移除都在页面上完成。YAML 读写采用文档级 API,文件中的其他行与注释不受影响。新行写在一个 `- insert:` 块里——加载器只会挂载 insert 形式的行,裸的 `- id:` 条目是对已有行的覆盖,目标不存在时会被跳过;0.1.3 之前写入的裸行会在下一次保存时自动迁入 insert 块。0.3.7 起,若 `cordis.patch.yml` 本身存在语法错误(多见于手工编辑失误),页面会直接报出文件完整路径与出错行列,并且不写入任何内容;此前这种文件会在保存时抛出内部的 "Document with errors cannot be stringified",让人无从下手。
|
|
29
29
|
|
|
30
|
-
服务器行不只存在于 profile 里。dsh 还有一层全局补丁(`DSH_HOME/cordis.patch.yml`),对这台机器上的所有 profile 生效,组合时排在 profile 层之后、同名 id 以全局为准。0.3.8 起,「MCP」页把两层合在一起展示:每行带「全局」或「当前 profile」标记,两层出现同名 id 时 profile
|
|
30
|
+
服务器行不只存在于 profile 里。dsh 还有一层全局补丁(`DSH_HOME/cordis.patch.yml`),对这台机器上的所有 profile 生效,组合时排在 profile 层之后、同名 id 以全局为准。0.3.8 起,「MCP」页把两层合在一起展示:每行带「全局」或「当前 profile」标记,两层出现同名 id 时 profile 行会注明自己不生效。添加服务器时可以选择写入哪一层,编辑、停用、移除也都落在该行所在的层。每行还有「检查」和「复制到另一层」两个动作:检查不启动服务器——stdio 行在 PATH 里确认命令真实存在(带 Windows 可执行扩展名),http 行发一个短超时的 GET,任何 HTTP 状态都算可达(MCP 端点对普通 GET 回 405 是正常的);复制把整行配置搬去另一层,不用删了重配。全局文件损坏不会连累整个页面:profile 行照常列出,顶部横幅单独报出全局文件的路径与出错行列。
|
|
31
31
|
|
|
32
32
|
添加或编辑服务器时,表单下方有「完整格式与快速填充」区:一边是随表单实时更新的完整 YAML 行(和保存后落进 `cordis.patch.yml` 的一模一样),另一边是等价的 `mcpServers` JSON 写法,可以直接抄去别的工具。反过来也行——把 Claude Code 配置、官方文档或任意 JSON 粘进输入框,点「解析并填充」,服务器名、命令、参数、环境变量、URL、请求头都会自动填好,`{"mcpServers": {...}}` 包装、裸条目、dsh 行三种形状都认。
|
|
33
33
|
|
|
34
|
-
也可以从其他 agent 导入:一键扫描 Claude Code(`~/.claude.json`、`~/.claude/settings.json
|
|
34
|
+
也可以从其他 agent 导入:一键扫描 Claude Code(`~/.claude.json`、`~/.claude/settings.json`)、Codex(`~/.codex/config.toml`)、Cursor(`~/.cursor/mcp.json`)与 Gemini CLI(`~/.gemini/settings.json`)的 MCP 配置,弹窗里先选写入当前 profile 还是全局层,勾选所需条目后转成服务器行。弹窗按来源分组,各自带数量与「全选」;stdio 与 http 两种传输都会处理(Gemini 的 SSE 条目除外,dsh 的客户端不支持),已存在的同名服务器置灰跳过。需要注意的是,Claude 配置里的 `${VAR}` 环境变量引用按字面值导入,如有需要请在导入后手动改回。
|
|
35
35
|
|
|
36
36
|
MCP 行的变更需要重启 dsh 才会进入组合。MCP 页头部有常驻的「重启」按钮,变更后无需离开界面:在 [DSH Desktop](https://github.com/qinyre/dsh-Desktop) 中由桌面壳层重启受监督的 sidecar,完成后窗口自动重载;直接运行 `dsh web` 时插件会拉起一个替代进程再退出自身,页面在恢复后自动刷新——若启动时端口是随机的,按横幅提示在终端查看新地址。重启会中断正在进行的回合,点击后会先弹出确认。
|
|
37
37
|
|
|
@@ -41,7 +41,7 @@ MCP 行的变更需要重启 dsh 才会进入组合。MCP 页头部有常驻的
|
|
|
41
41
|
|
|
42
42
|

|
|
43
43
|
|
|
44
|
-
「市场」页分两栏:「技能市场」是精选的技能仓库(Anthropic 官方技能集、Superpowers 工作流集等),点「安装」走的就是上文 GitHub 仓库的下载解包流程,装完立即出现在「技能」页;「MCP 市场」是一份精选服务器列表(官方 filesystem/memory/git 等,加上 context7
|
|
44
|
+
「市场」页分两栏:「技能市场」是精选的技能仓库(Anthropic 官方技能集、Superpowers 工作流集等),点「安装」走的就是上文 GitHub 仓库的下载解包流程,装完立即出现在「技能」页;「MCP 市场」是一份精选服务器列表(官方 filesystem/memory/git 等,加上 context7 这类常用第三方),点「添加」直接写入一条服务器行,和手工添加完全等价,写入哪一层(当前 profile 还是全局)跟随列表上方的生效范围选择。0.3.0 起点开条目可以看详情:技能仓库列出里面具体有哪些技能,MCP 服务器列出启动命令、需要的环境变量和提供的工具,不必再去 GitHub 主页。列表数据来自[本插件仓库](https://github.com/qinyre/dsh-plugin-capabilities)的在线索引(`market/*.json`),离线时自动回退到包内快照;需要 API 密钥的服务器会在卡片上标出环境变量名,装好后到 MCP 列表里补填即可。已安装的条目可以直接卸载:技能仓库走仓库移除,MCP 行走服务器删除(该行在全局层就删全局层的)。
|
|
45
45
|
|
|
46
46
|
## 安装
|
|
47
47
|
|
package/lib/client.js
CHANGED
|
@@ -187,6 +187,7 @@ function MarketTab(props) {
|
|
|
187
187
|
const [servers, setServers] = (0, import_react.useState)(null);
|
|
188
188
|
const [source, setSource] = (0, import_react.useState)("remote");
|
|
189
189
|
const [busyId, setBusyId] = (0, import_react.useState)(null);
|
|
190
|
+
const [mcpScope, setMcpScope] = (0, import_react.useState)("profile");
|
|
190
191
|
const [outcome, setOutcome] = (0, import_react.useState)(null);
|
|
191
192
|
const [confirmUninstall, setConfirmUninstall] = (0, import_react.useState)(null);
|
|
192
193
|
const [detail, setDetail] = (0, import_react.useState)(null);
|
|
@@ -239,7 +240,7 @@ function MarketTab(props) {
|
|
|
239
240
|
setBusyId(server.id);
|
|
240
241
|
setOutcome(null);
|
|
241
242
|
try {
|
|
242
|
-
await market.installMcp(server.id);
|
|
243
|
+
await market.installMcp(server.id, mcpScope);
|
|
243
244
|
setOutcome({ ok: true, text: t("restartNeeded") });
|
|
244
245
|
refreshMcp();
|
|
245
246
|
} catch (error) {
|
|
@@ -259,7 +260,7 @@ function MarketTab(props) {
|
|
|
259
260
|
setOutcome({ ok: true, text: t("rootRemoved") });
|
|
260
261
|
refreshSkills();
|
|
261
262
|
} else {
|
|
262
|
-
await mcp.remove(target.id,
|
|
263
|
+
await mcp.remove(target.id, target.scope);
|
|
263
264
|
setOutcome({ ok: true, text: t("restartNeeded") });
|
|
264
265
|
refreshMcp();
|
|
265
266
|
}
|
|
@@ -326,6 +327,23 @@ function MarketTab(props) {
|
|
|
326
327
|
] }),
|
|
327
328
|
segment === "mcp" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
328
329
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dpc-intro", children: t("marketMcpIntro") }),
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dpc-cardRow", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: 8 }, children: [
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("scopeLabel") }),
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
333
|
+
"select",
|
|
334
|
+
{
|
|
335
|
+
className: "dpc-select",
|
|
336
|
+
style: { width: "auto" },
|
|
337
|
+
value: mcpScope,
|
|
338
|
+
disabled: busyId !== null,
|
|
339
|
+
onChange: (event) => setMcpScope(event.target.value),
|
|
340
|
+
children: [
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "profile", children: t("scopeProfile") }),
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "global", children: t("scopeGlobal") })
|
|
343
|
+
]
|
|
344
|
+
}
|
|
345
|
+
)
|
|
346
|
+
] }) }),
|
|
329
347
|
servers === null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dpc-empty", children: t("loading") }),
|
|
330
348
|
servers !== null && servers.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dpc-empty", children: t("marketEmpty") }),
|
|
331
349
|
servers !== null && servers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "dpc-cards", children: servers.map((server) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "dpc-card", onClick: () => setDetail({ kind: "mcp", id: server.id }), children: [
|
|
@@ -350,7 +368,7 @@ function MarketTab(props) {
|
|
|
350
368
|
void mcp.list().then(
|
|
351
369
|
(body) => {
|
|
352
370
|
const row = body.servers.find((item) => item.serverName === server.id);
|
|
353
|
-
if (row !== void 0) setConfirmUninstall({ kind: "mcp", id: row.id, name: server.id });
|
|
371
|
+
if (row !== void 0) setConfirmUninstall({ kind: "mcp", id: row.id, name: server.id, scope: row.scope });
|
|
354
372
|
},
|
|
355
373
|
(error) => setOutcome({ ok: false, text: `${t("failed")}: ${String(error.message ?? error)}` })
|
|
356
374
|
);
|
|
@@ -382,7 +400,7 @@ function MarketTab(props) {
|
|
|
382
400
|
(body) => {
|
|
383
401
|
const row = body.servers.find((item) => item.serverName === detailServer.id);
|
|
384
402
|
if (row !== void 0) {
|
|
385
|
-
setConfirmUninstall({ kind: "mcp", id: row.id, name: title(detailServer) });
|
|
403
|
+
setConfirmUninstall({ kind: "mcp", id: row.id, name: title(detailServer), scope: row.scope });
|
|
386
404
|
setDetail(null);
|
|
387
405
|
}
|
|
388
406
|
},
|
|
@@ -454,8 +472,8 @@ var import_react2 = require("react");
|
|
|
454
472
|
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
455
473
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
456
474
|
function importGroups(items) {
|
|
457
|
-
const label = (agent) => agent === "claude-code" ? "Claude Code" : agent === "codex" ? "Codex" : agent;
|
|
458
|
-
const order = ["claude-code", "codex"];
|
|
475
|
+
const label = (agent) => agent === "claude-code" ? "Claude Code" : agent === "codex" ? "Codex" : agent === "cursor" ? "Cursor" : agent === "gemini" ? "Gemini CLI" : agent;
|
|
476
|
+
const order = ["claude-code", "codex", "cursor", "gemini"];
|
|
459
477
|
const agents = [...new Set(items.map((item) => item.server.agent))].sort((a, b2) => {
|
|
460
478
|
const rank = (agent) => {
|
|
461
479
|
const at2 = order.indexOf(agent);
|
|
@@ -595,6 +613,8 @@ function McpTab(props) {
|
|
|
595
613
|
const [reload, setReload] = (0, import_react2.useState)(0);
|
|
596
614
|
const [pasteJson, setPasteJson] = (0, import_react2.useState)("");
|
|
597
615
|
const [pasteError, setPasteError] = (0, import_react2.useState)(null);
|
|
616
|
+
const [checks, setChecks] = (0, import_react2.useState)({});
|
|
617
|
+
const [importScope, setImportScope] = (0, import_react2.useState)("profile");
|
|
598
618
|
const openImport = async () => {
|
|
599
619
|
setImportOpen(true);
|
|
600
620
|
setImportItems(null);
|
|
@@ -616,7 +636,7 @@ function McpTab(props) {
|
|
|
616
636
|
const items = importItems.filter((item) => item.checked && !item.existing).map((item) => ({ agent: item.server.agent, name: item.server.name }));
|
|
617
637
|
setBusy(true);
|
|
618
638
|
try {
|
|
619
|
-
const body = await injected.applyImport(items);
|
|
639
|
+
const body = await injected.applyImport(items, importScope);
|
|
620
640
|
const failed = body.results.filter((item) => !item.ok);
|
|
621
641
|
setOutcome(failed.length === 0 ? { ok: true, text: t("restartNeeded") } : { ok: false, text: `${t("failed")}: ${failed.map((item) => `${item.name} (${item.error})`).join(", ")}` });
|
|
622
642
|
setImportOpen(false);
|
|
@@ -755,6 +775,29 @@ function McpTab(props) {
|
|
|
755
775
|
setConfirmRow(null);
|
|
756
776
|
}
|
|
757
777
|
};
|
|
778
|
+
const doCheck = async (row) => {
|
|
779
|
+
const key = `${row.scope}/${row.id}`;
|
|
780
|
+
setChecks((current) => ({ ...current, [key]: "busy" }));
|
|
781
|
+
try {
|
|
782
|
+
const result = await injected.check(row.id, row.scope);
|
|
783
|
+
setChecks((current) => ({ ...current, [key]: result }));
|
|
784
|
+
} catch (error) {
|
|
785
|
+
setChecks((current) => ({ ...current, [key]: { ok: false, detail: String(error instanceof Error ? error.message : error) } }));
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
const doCopy = async (row) => {
|
|
789
|
+
setBusy(true);
|
|
790
|
+
try {
|
|
791
|
+
const toScope = row.scope === "global" ? "profile" : "global";
|
|
792
|
+
await injected.copy(row.id, row.scope, toScope);
|
|
793
|
+
setOutcome({ ok: true, text: t("restartNeeded") });
|
|
794
|
+
reloadList(true);
|
|
795
|
+
} catch (error) {
|
|
796
|
+
setOutcome({ ok: false, text: `${t("failed")}: ${String(error instanceof Error ? error.message : error)}` });
|
|
797
|
+
} finally {
|
|
798
|
+
setBusy(false);
|
|
799
|
+
}
|
|
800
|
+
};
|
|
758
801
|
const doRestart = () => {
|
|
759
802
|
setRestartConfirm(false);
|
|
760
803
|
setRestarting(true);
|
|
@@ -827,8 +870,19 @@ function McpTab(props) {
|
|
|
827
870
|
] }),
|
|
828
871
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-cardDesc", children: row.transport === "stdio" ? `${row.command ?? ""} ${(row.args ?? []).join(" ")}` : row.url ?? "" }),
|
|
829
872
|
row.shadowed === true && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-formError", children: t("shadowedByGlobal") }),
|
|
873
|
+
(() => {
|
|
874
|
+
const check = checks[`${row.scope}/${row.id}`];
|
|
875
|
+
if (check === void 0) return null;
|
|
876
|
+
if (check === "busy") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-cardDesc", children: t("checkRunning") });
|
|
877
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: check.ok ? "dpc-cardDesc" : "dpc-formError", children: [
|
|
878
|
+
check.ok ? `\u2713 ${t("checkOk")}` : `\u2717 ${t("checkFail")}`,
|
|
879
|
+
check.detail !== void 0 && ` \xB7 ${check.detail}`
|
|
880
|
+
] });
|
|
881
|
+
})(),
|
|
830
882
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dpc-cardRow", children: [
|
|
831
883
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dpc-spacer" }),
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => void doCheck(row), children: t("checkLabel") }),
|
|
885
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => void doCopy(row), children: t("copyToOther") }),
|
|
832
886
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => void doToggle(row), children: t("toggle") }),
|
|
833
887
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => openEdit(row), children: t("edit") }),
|
|
834
888
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "ghost", size: "sm", disabled: busy, onClick: () => setConfirmRow(row), children: t("delete") })
|
|
@@ -991,6 +1045,23 @@ function McpTab(props) {
|
|
|
991
1045
|
className: "dpc-modalWide",
|
|
992
1046
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dpc-form", children: [
|
|
993
1047
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-intro", style: { margin: 0 }, children: t("importIntro") }),
|
|
1048
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dpc-cardRow", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: 8 }, children: [
|
|
1049
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: t("scopeLabel") }),
|
|
1050
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1051
|
+
"select",
|
|
1052
|
+
{
|
|
1053
|
+
className: "dpc-select",
|
|
1054
|
+
style: { width: "auto" },
|
|
1055
|
+
value: importScope,
|
|
1056
|
+
disabled: busy,
|
|
1057
|
+
onChange: (event) => setImportScope(event.target.value),
|
|
1058
|
+
children: [
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "profile", children: t("scopeProfile") }),
|
|
1060
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "global", children: t("scopeGlobal") })
|
|
1061
|
+
]
|
|
1062
|
+
}
|
|
1063
|
+
)
|
|
1064
|
+
] }) }),
|
|
994
1065
|
importItems === null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-empty", children: t("loading") }),
|
|
995
1066
|
importItems !== null && importItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "dpc-empty", children: t("importEmpty") }),
|
|
996
1067
|
importItems !== null && importItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dpc-importScroll", children: importGroups(importItems).map((group) => {
|
|
@@ -4496,6 +4567,11 @@ var zh = {
|
|
|
4496
4567
|
scopeHint: "\u5168\u5C40\uFF1A\u5199\u5165 DSH_HOME/cordis.patch.yml\uFF0C\u5BF9\u672C\u673A\u6240\u6709 profile \u751F\u6548\uFF1B\u5F53\u524D profile\uFF1A\u53EA\u5F71\u54CD\u672C profile\u3002",
|
|
4497
4568
|
shadowedByGlobal: "\u5168\u5C40\u5C42\u5B58\u5728\u540C\u540D id\uFF0C\u6B64\u884C\u4E0D\u751F\u6548",
|
|
4498
4569
|
globalLayerError: "\u5168\u5C40\u914D\u7F6E\uFF08DSH_HOME/cordis.patch.yml\uFF09\u8BFB\u53D6\u5931\u8D25\uFF0C\u5168\u5C40\u670D\u52A1\u5668\u6682\u672A\u663E\u793A\uFF1A",
|
|
4570
|
+
checkLabel: "\u68C0\u67E5",
|
|
4571
|
+
checkRunning: "\u68C0\u67E5\u4E2D\u2026",
|
|
4572
|
+
checkOk: "\u68C0\u67E5\u901A\u8FC7",
|
|
4573
|
+
checkFail: "\u68C0\u67E5\u672A\u901A\u8FC7",
|
|
4574
|
+
copyToOther: "\u590D\u5236\u5230\u53E6\u4E00\u5C42",
|
|
4499
4575
|
serverName: "\u670D\u52A1\u5668\u540D\uFF08\u5DE5\u5177\u540D\u524D\u7F00\uFF09",
|
|
4500
4576
|
transport: "\u4F20\u8F93\u65B9\u5F0F",
|
|
4501
4577
|
transportStdio: "stdio\uFF08\u672C\u5730\u547D\u4EE4\uFF09",
|
|
@@ -4512,7 +4588,7 @@ var zh = {
|
|
|
4512
4588
|
removeWarn: "\u5C06\u4ECE\u914D\u7F6E\u4E2D\u79FB\u9664\u8FD9\u4E00\u884C\uFF0C\u91CD\u542F dsh \u540E\u5176\u5DE5\u5177\u4E0D\u518D\u51FA\u73B0\u3002",
|
|
4513
4589
|
emptyMcp: "\u8FD8\u6CA1\u6709\u914D\u7F6E MCP \u670D\u52A1\u5668",
|
|
4514
4590
|
importServers: "\u4ECE\u5176\u4ED6 Agent \u5BFC\u5165",
|
|
4515
|
-
importIntro: "\u626B\u63CF Claude Code\uFF08~/.claude.json\uFF09\
|
|
4591
|
+
importIntro: "\u626B\u63CF Claude Code\uFF08~/.claude.json\uFF09\u3001Codex\uFF08~/.codex/config.toml\uFF09\u3001Cursor\uFF08~/.cursor/mcp.json\uFF09\u4E0E Gemini CLI\uFF08~/.gemini/settings.json\uFF09\u7684 MCP \u670D\u52A1\u5668\u914D\u7F6E\uFF0C\u52FE\u9009\u540E\u5BFC\u5165\u5230\u6240\u9009\u8303\u56F4\u3002",
|
|
4516
4592
|
importEmpty: "\u6CA1\u6709\u53D1\u73B0\u53EF\u5BFC\u5165\u7684 MCP \u670D\u52A1\u5668",
|
|
4517
4593
|
importSelectAll: "\u5168\u9009",
|
|
4518
4594
|
importExisting: "\u5DF2\u5B58\u5728",
|
|
@@ -4538,7 +4614,7 @@ var zh = {
|
|
|
4538
4614
|
marketSkills: "\u6280\u80FD\u5E02\u573A",
|
|
4539
4615
|
marketMcp: "MCP \u5E02\u573A",
|
|
4540
4616
|
marketSkillsIntro: "\u5B89\u88C5\u6280\u80FD\u4ED3\u5E93\uFF08GitHub \u4E0B\u8F7D\u89E3\u5305\uFF0C\u5B9E\u65F6\u8FDB\u5165\u626B\u63CF\u76EE\u5F55\uFF09\uFF1B\u5DF2\u5B89\u88C5\u7684\u4ED3\u5E93\u53EF\u5728\u300C\u6280\u80FD\u300D\u9875\u7BA1\u7406\u3002",
|
|
4541
|
-
marketMcpIntro: "\u6DFB\u52A0 MCP \u670D\u52A1\u5668\u884C\uFF08\
|
|
4617
|
+
marketMcpIntro: "\u6DFB\u52A0 MCP \u670D\u52A1\u5668\u884C\uFF08\u4E0A\u65B9\u53EF\u9009\u5199\u5165\u5F53\u524D profile \u8FD8\u662F\u5168\u5C40\u5C42\uFF0C\u6DFB\u52A0\u540E\u9700\u91CD\u542F\u751F\u6548\uFF09\uFF1B\u9700\u8981\u5BC6\u94A5\u7684\u670D\u52A1\u5728\u5B89\u88C5\u540E\u4E8E\u5217\u8868\u4E2D\u8865\u586B\u73AF\u5883\u53D8\u91CF\u3002",
|
|
4542
4618
|
marketEmpty: "\u5E02\u573A\u5217\u8868\u4E3A\u7A7A\u6216\u4E0D\u53EF\u7528",
|
|
4543
4619
|
marketOffline: "\u5728\u7EBF\u7D22\u5F15\u4E0D\u53EF\u8FBE\uFF0C\u5F53\u524D\u5C55\u793A\u5305\u5185\u5FEB\u7167\uFF08\u53EF\u80FD\u4E0E\u6700\u65B0\u5217\u8868\u6709\u5DEE\u5F02\uFF09\u3002",
|
|
4544
4620
|
marketSkillCount: "{n} \u4E2A\u6280\u80FD",
|
|
@@ -4634,6 +4710,11 @@ var en = {
|
|
|
4634
4710
|
scopeHint: "Global writes DSH_HOME/cordis.patch.yml and applies to every profile on this machine; this profile writes the current profile only.",
|
|
4635
4711
|
shadowedByGlobal: "a global row with the same id wins \u2014 this row has no effect",
|
|
4636
4712
|
globalLayerError: "Failed to read the global layer (DSH_HOME/cordis.patch.yml); global servers are hidden:",
|
|
4713
|
+
checkLabel: "Check",
|
|
4714
|
+
checkRunning: "Checking\u2026",
|
|
4715
|
+
checkOk: "OK",
|
|
4716
|
+
checkFail: "Failed",
|
|
4717
|
+
copyToOther: "Copy to other layer",
|
|
4637
4718
|
serverName: "Server name (tool name prefix)",
|
|
4638
4719
|
transport: "Transport",
|
|
4639
4720
|
transportStdio: "stdio (local command)",
|
|
@@ -4650,7 +4731,7 @@ var en = {
|
|
|
4650
4731
|
removeWarn: "Removes the row from its configuration; its tools disappear after the next dsh restart.",
|
|
4651
4732
|
emptyMcp: "No MCP servers configured yet",
|
|
4652
4733
|
importServers: "Import from other agents",
|
|
4653
|
-
importIntro: "Scans Claude Code (~/.claude.json)
|
|
4734
|
+
importIntro: "Scans the MCP server configs of Claude Code (~/.claude.json), Codex (~/.codex/config.toml), Cursor (~/.cursor/mcp.json), and Gemini CLI (~/.gemini/settings.json); selected entries land in the scope picked below.",
|
|
4654
4735
|
importEmpty: "No importable MCP servers found",
|
|
4655
4736
|
importSelectAll: "Select all",
|
|
4656
4737
|
importExisting: "already here",
|
|
@@ -4676,7 +4757,7 @@ var en = {
|
|
|
4676
4757
|
marketSkills: "Skills market",
|
|
4677
4758
|
marketMcp: "MCP market",
|
|
4678
4759
|
marketSkillsIntro: "Installs skill repositories (GitHub download, live catalog); manage installed ones on the Skills tab.",
|
|
4679
|
-
marketMcpIntro: "Adds MCP server rows (
|
|
4760
|
+
marketMcpIntro: "Adds MCP server rows (pick the target layer \u2014 this profile or global \u2014 above; restart to apply). Servers needing keys get their environment filled in on the row after install.",
|
|
4680
4761
|
marketEmpty: "Market list is empty or unavailable",
|
|
4681
4762
|
marketOffline: "Online index unreachable \u2014 showing the bundled snapshot, which may lag behind.",
|
|
4682
4763
|
marketSkillCount: "{n} skills",
|
|
@@ -4726,8 +4807,10 @@ function apply2(ctx) {
|
|
|
4726
4807
|
save: (input) => post("/dsh-plugin-capabilities/mcp/save", input),
|
|
4727
4808
|
toggle: (id, disabled, scope) => post("/dsh-plugin-capabilities/mcp/toggle", { id, disabled, scope }),
|
|
4728
4809
|
remove: (id, scope) => post("/dsh-plugin-capabilities/mcp/remove", { id, scope }),
|
|
4810
|
+
check: (id, scope) => post("/dsh-plugin-capabilities/mcp/check", { id, scope }),
|
|
4811
|
+
copy: (id, scope, toScope) => post("/dsh-plugin-capabilities/mcp/copy", { id, scope, toScope }),
|
|
4729
4812
|
scanImport: () => fetchJson("/dsh-plugin-capabilities/import/scan"),
|
|
4730
|
-
applyImport: (items) => post("/dsh-plugin-capabilities/import/apply", { items }),
|
|
4813
|
+
applyImport: (items, scope) => post("/dsh-plugin-capabilities/import/apply", { items, scope }),
|
|
4731
4814
|
restart: async () => {
|
|
4732
4815
|
if (window.dshDesktop !== void 0) {
|
|
4733
4816
|
window.dshDesktop.restartSidecar?.();
|
|
@@ -4744,7 +4827,7 @@ function apply2(ctx) {
|
|
|
4744
4827
|
skillsIndex: () => fetchJson("/dsh-plugin-capabilities/market/skills"),
|
|
4745
4828
|
mcpIndex: () => fetchJson("/dsh-plugin-capabilities/market/mcp"),
|
|
4746
4829
|
installSkillRepo: (url) => post("/dsh-plugin-capabilities/market/skills/install", { url }),
|
|
4747
|
-
installMcp: (id) => post("/dsh-plugin-capabilities/market/mcp/install", { id }),
|
|
4830
|
+
installMcp: (id, scope) => post("/dsh-plugin-capabilities/market/mcp/install", { id, scope }),
|
|
4748
4831
|
removeRoot: skillsInjected.removeRoot
|
|
4749
4832
|
};
|
|
4750
4833
|
ctx.slots.inject("settings.section", () => {
|