@max-null/dsh-skill-mcp-center 0.6.0 → 0.6.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/client.js +110 -59
- package/dist/service.d.ts +10 -0
- package/dist/service.js +40 -0
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -31,6 +31,17 @@ __export(index_exports, {
|
|
|
31
31
|
});
|
|
32
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
33
|
var import_react = require("react");
|
|
34
|
+
|
|
35
|
+
// client/skill-key.ts
|
|
36
|
+
var RUNTIME_KEY_PREFIX = "\0runtime:";
|
|
37
|
+
function skillKeyOf(skill) {
|
|
38
|
+
return skill.path === "" ? `${RUNTIME_KEY_PREFIX}${skill.name}` : skill.path;
|
|
39
|
+
}
|
|
40
|
+
function hasSkillFile(skill) {
|
|
41
|
+
return skill.path !== "";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// client/index.tsx
|
|
34
45
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
46
|
var CSS = `
|
|
36
47
|
.smc-title { font-size: 18px; font-weight: 600; line-height: 26px; color: var(--dsw-alias-label-primary); }
|
|
@@ -81,6 +92,10 @@ var CSS = `
|
|
|
81
92
|
.smc-toggle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; transition: left .15s; }
|
|
82
93
|
.smc-toggle.on::after { left: 21px; }
|
|
83
94
|
.smc-toggle:disabled { opacity: 0.4; cursor: default; }
|
|
95
|
+
.smc-skill-group { margin-bottom: 10px; }
|
|
96
|
+
.smc-skill-group-head { display: flex; align-items: baseline; gap: 6px; padding: 6px 2px 4px; font-size: 11px; font-weight: 600; letter-spacing: .04em; color: var(--dsw-alias-label-caption); }
|
|
97
|
+
.smc-skill-group-count { font-weight: 400; opacity: .7; }
|
|
98
|
+
.smc-skill-group-note { padding: 0 2px 6px; font-size: 11px; line-height: 1.5; color: var(--dsw-alias-label-caption); }
|
|
84
99
|
|
|
85
100
|
.smc-input { height: 34px; padding: 0 12px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l2); background: var(--dsw-alias-bg-layer-3); color: var(--dsw-alias-label-primary); font-size: 13px; line-height: 1.5; outline: none; font-family: inherit; }
|
|
86
101
|
.smc-input:focus { border-color: var(--dsw-alias-brand-primary); }
|
|
@@ -236,6 +251,11 @@ var zhDict = {
|
|
|
236
251
|
groupGlobal: "\u5168\u5C40",
|
|
237
252
|
groupWorkspace: "\u5DE5\u4F5C\u533A",
|
|
238
253
|
groupBundled: "\u5185\u7F6E\uFF08DSH \u5B98\u65B9\uFF09",
|
|
254
|
+
groupProject: "\u9879\u76EE\u7EA7",
|
|
255
|
+
groupUser: "\u7528\u6237\u7EA7",
|
|
256
|
+
groupPlugin: "\u63D2\u4EF6\u81EA\u5E26",
|
|
257
|
+
groupRuntime: "\u4EE3\u7801\u6CE8\u518C",
|
|
258
|
+
groupRuntimeNote: "\u7531\u63D2\u4EF6\u5728\u8FD0\u884C\u65F6\u6CE8\u518C\uFF0C\u4E0D\u53EF\u5728\u6B64\u7981\u7528",
|
|
239
259
|
readOnlyBadge: "\u5185\u7F6E\u53EA\u8BFB",
|
|
240
260
|
noMatch: "\u6CA1\u6709\u5339\u914D\u7684 skill",
|
|
241
261
|
detailPath: "\u8DEF\u5F84",
|
|
@@ -246,6 +266,7 @@ var zhDict = {
|
|
|
246
266
|
nsWorkspace: "\u5DE5\u4F5C\u533A",
|
|
247
267
|
noWorkspace: "\u672A\u9009\u62E9\u5DE5\u4F5C\u533A",
|
|
248
268
|
viewMd: "\u67E5\u770B SKILL.md",
|
|
269
|
+
noSkillFile: "\u65E0 SKILL.md",
|
|
249
270
|
hideMd: "\u6536\u8D77",
|
|
250
271
|
mdLoadFailed: "\u8BFB\u53D6\u5931\u8D25\uFF1A{e}",
|
|
251
272
|
refOpen: "\u6253\u5F00\u6587\u4EF6\u5F15\u7528",
|
|
@@ -295,6 +316,11 @@ var enDict = {
|
|
|
295
316
|
groupGlobal: "Global",
|
|
296
317
|
groupWorkspace: "Workspace",
|
|
297
318
|
groupBundled: "Built-in (DSH official)",
|
|
319
|
+
groupProject: "Project",
|
|
320
|
+
groupUser: "User",
|
|
321
|
+
groupPlugin: "Plugin-bundled",
|
|
322
|
+
groupRuntime: "Code-registered",
|
|
323
|
+
groupRuntimeNote: "Registered by a plugin at runtime; cannot be disabled here",
|
|
298
324
|
readOnlyBadge: "built-in read-only",
|
|
299
325
|
noMatch: "No matching skills",
|
|
300
326
|
detailPath: "path",
|
|
@@ -305,6 +331,7 @@ var enDict = {
|
|
|
305
331
|
nsWorkspace: "Workspace",
|
|
306
332
|
noWorkspace: "No workspace selected",
|
|
307
333
|
viewMd: "View SKILL.md",
|
|
334
|
+
noSkillFile: "no SKILL.md",
|
|
308
335
|
hideMd: "Hide",
|
|
309
336
|
mdLoadFailed: "Failed to read: {e}",
|
|
310
337
|
refOpen: "Open file reference",
|
|
@@ -456,13 +483,14 @@ function SkillView() {
|
|
|
456
483
|
);
|
|
457
484
|
};
|
|
458
485
|
const openMd = (s) => {
|
|
459
|
-
if (
|
|
486
|
+
if (!hasSkillFile(s)) return;
|
|
487
|
+
if (mdPath === skillKeyOf(s)) {
|
|
460
488
|
setMdPath(null);
|
|
461
489
|
setMdText(null);
|
|
462
490
|
setMdError(null);
|
|
463
491
|
return;
|
|
464
492
|
}
|
|
465
|
-
setMdPath(s
|
|
493
|
+
setMdPath(skillKeyOf(s));
|
|
466
494
|
setMdText(null);
|
|
467
495
|
setMdError(null);
|
|
468
496
|
void rpc("readSkill", { path: s.path }).then(
|
|
@@ -484,7 +512,7 @@ function SkillView() {
|
|
|
484
512
|
else other.push(s);
|
|
485
513
|
}
|
|
486
514
|
const renderCard = (s) => {
|
|
487
|
-
const open = expanded === s
|
|
515
|
+
const open = expanded === skillKeyOf(s);
|
|
488
516
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-card", children: [
|
|
489
517
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-card-head", children: [
|
|
490
518
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -495,7 +523,7 @@ function SkillView() {
|
|
|
495
523
|
"aria-expanded": open,
|
|
496
524
|
title: t("clickForDetail"),
|
|
497
525
|
onClick: () => {
|
|
498
|
-
setExpanded(open ? null : s
|
|
526
|
+
setExpanded(open ? null : skillKeyOf(s));
|
|
499
527
|
},
|
|
500
528
|
children: [
|
|
501
529
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-card-name", children: s.name }),
|
|
@@ -529,9 +557,9 @@ function SkillView() {
|
|
|
529
557
|
!s.modelInvocable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge disabled", children: t("modelDisabled") }),
|
|
530
558
|
!s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge disabled", children: t("readOnlyBadge") }),
|
|
531
559
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-spacer" }),
|
|
532
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "smc-btn", onClick: () => {
|
|
560
|
+
!hasSkillFile(s) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge disabled", children: t("noSkillFile") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "smc-btn", onClick: () => {
|
|
533
561
|
openMd(s);
|
|
534
|
-
}, children: mdPath === s
|
|
562
|
+
}, children: mdPath === skillKeyOf(s) ? t("hideMd") : t("viewMd") }),
|
|
535
563
|
s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
536
564
|
"button",
|
|
537
565
|
{
|
|
@@ -548,11 +576,11 @@ function SkillView() {
|
|
|
548
576
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-detail-row", children: [
|
|
549
577
|
t("detailPath"),
|
|
550
578
|
"\uFF1A",
|
|
551
|
-
s.path
|
|
579
|
+
hasSkillFile(s) ? s.path : t("noSkillFile")
|
|
552
580
|
] }),
|
|
553
|
-
mdPath === s
|
|
581
|
+
mdPath === skillKeyOf(s) && (mdError !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md-err", children: t("mdLoadFailed", { e: mdError }) }) : mdText === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md", children: t("loading") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MdWithRefs, { text: mdText }) }))
|
|
554
582
|
] })
|
|
555
|
-
] }, s
|
|
583
|
+
] }, skillKeyOf(s));
|
|
556
584
|
};
|
|
557
585
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
558
586
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-toolbar", children: [
|
|
@@ -835,6 +863,21 @@ function sourceLabel(source, short = false) {
|
|
|
835
863
|
const name = pkg.split("/").pop() ?? pkg;
|
|
836
864
|
return short ? name : `plugin \xB7 ${name}`;
|
|
837
865
|
}
|
|
866
|
+
var SKILL_GROUP_ORDER = ["project", "user", "plugin", "bundled", "runtime"];
|
|
867
|
+
var SKILL_GROUP_LABEL = {
|
|
868
|
+
project: "groupProject",
|
|
869
|
+
user: "groupUser",
|
|
870
|
+
plugin: "groupPlugin",
|
|
871
|
+
bundled: "groupBundled",
|
|
872
|
+
runtime: "groupRuntime"
|
|
873
|
+
};
|
|
874
|
+
function skillGroupOf(source) {
|
|
875
|
+
if (source === "project-dsh" || source === "project-agents") return "project";
|
|
876
|
+
if (source === "user-dsh" || source === "user-agents") return "user";
|
|
877
|
+
if (source.startsWith("plugin:")) return "plugin";
|
|
878
|
+
if (source === "bundled") return "bundled";
|
|
879
|
+
return "runtime";
|
|
880
|
+
}
|
|
838
881
|
function skillInNamespace(s, ns) {
|
|
839
882
|
if (ns === "all") return true;
|
|
840
883
|
if (ns === "global") {
|
|
@@ -877,6 +920,7 @@ function SidebarSkillTab({ visible, cwd }) {
|
|
|
877
920
|
);
|
|
878
921
|
};
|
|
879
922
|
const openMd = (path) => {
|
|
923
|
+
if (path === "") return;
|
|
880
924
|
if (mdPath === path) {
|
|
881
925
|
setMdPath(null);
|
|
882
926
|
setMdText(null);
|
|
@@ -927,57 +971,64 @@ function SidebarSkillTab({ visible, cwd }) {
|
|
|
927
971
|
k
|
|
928
972
|
)) })
|
|
929
973
|
] }),
|
|
930
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-sidebar-list", children: noWorkspace ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-empty", children: t("noWorkspace") }) : visibleItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-empty", children: q !== "" ? t("noMatch") : t("noSkills") }) :
|
|
931
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-
|
|
932
|
-
|
|
933
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className:
|
|
934
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-srv-name", children: s.name }),
|
|
935
|
-
!s.modelInvocable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge", children: t("modelDisabled") }),
|
|
936
|
-
!s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge", children: sourceLabel(s.source, true) }),
|
|
937
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
938
|
-
"button",
|
|
939
|
-
{
|
|
940
|
-
type: "button",
|
|
941
|
-
className: "smc-btn",
|
|
942
|
-
style: { height: 20, padding: "0 6px", fontSize: 11 },
|
|
943
|
-
onClick: () => {
|
|
944
|
-
openMd(s.path);
|
|
945
|
-
},
|
|
946
|
-
"aria-label": mdPath === s.path ? t("hideMd") : t("viewMd"),
|
|
947
|
-
children: mdPath === s.path ? t("hideMd") : "MD"
|
|
948
|
-
}
|
|
949
|
-
),
|
|
950
|
-
s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
951
|
-
"button",
|
|
952
|
-
{
|
|
953
|
-
type: "button",
|
|
954
|
-
className: "smc-btn danger",
|
|
955
|
-
style: { height: 20, padding: "0 6px", fontSize: 11 },
|
|
956
|
-
onClick: () => {
|
|
957
|
-
removeSkill(s);
|
|
958
|
-
},
|
|
959
|
-
"aria-label": t("deleteSkill"),
|
|
960
|
-
children: t("remove")
|
|
961
|
-
}
|
|
962
|
-
),
|
|
963
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
964
|
-
"button",
|
|
965
|
-
{
|
|
966
|
-
type: "button",
|
|
967
|
-
className: `smc-toggle${s.modelInvocable ? " on" : ""}`,
|
|
968
|
-
title: t("toggleModelVisible"),
|
|
969
|
-
onClick: () => {
|
|
970
|
-
void rpc("toggleSkill", { path: s.path }).then(() => {
|
|
971
|
-
load();
|
|
972
|
-
});
|
|
973
|
-
},
|
|
974
|
-
"aria-label": s.modelInvocable ? t("disable") : t("enable")
|
|
975
|
-
}
|
|
976
|
-
)
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-sidebar-list", children: noWorkspace ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-empty", children: t("noWorkspace") }) : visibleItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-empty", children: q !== "" ? t("noMatch") : t("noSkills") }) : SKILL_GROUP_ORDER.map((kind) => ({ kind, items: visibleItems.filter((s) => skillGroupOf(s.source) === kind) })).filter((group) => group.items.length > 0).map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-skill-group", children: [
|
|
975
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-skill-group-head", children: [
|
|
976
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t(SKILL_GROUP_LABEL[group.kind]) }),
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-skill-group-count", children: group.items.length })
|
|
977
978
|
] }),
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
979
|
+
group.kind === "runtime" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-skill-group-note", children: t("groupRuntimeNote") }),
|
|
980
|
+
group.items.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "smc-srv", title: `${s.description}
|
|
982
|
+
${s.path}`, children: [
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: `smc-dot${s.modelInvocable ? "" : " idle"}` }),
|
|
984
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-srv-name", children: s.name }),
|
|
985
|
+
!s.modelInvocable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge", children: t("modelDisabled") }),
|
|
986
|
+
!s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "smc-badge", children: sourceLabel(s.source, true) }),
|
|
987
|
+
hasSkillFile(s) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
988
|
+
"button",
|
|
989
|
+
{
|
|
990
|
+
type: "button",
|
|
991
|
+
className: "smc-btn",
|
|
992
|
+
style: { height: 20, padding: "0 6px", fontSize: 11 },
|
|
993
|
+
onClick: () => {
|
|
994
|
+
openMd(s.path);
|
|
995
|
+
},
|
|
996
|
+
"aria-label": mdPath === s.path ? t("hideMd") : t("viewMd"),
|
|
997
|
+
children: mdPath === s.path ? t("hideMd") : "MD"
|
|
998
|
+
}
|
|
999
|
+
),
|
|
1000
|
+
s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1001
|
+
"button",
|
|
1002
|
+
{
|
|
1003
|
+
type: "button",
|
|
1004
|
+
className: "smc-btn danger",
|
|
1005
|
+
style: { height: 20, padding: "0 6px", fontSize: 11 },
|
|
1006
|
+
onClick: () => {
|
|
1007
|
+
removeSkill(s);
|
|
1008
|
+
},
|
|
1009
|
+
"aria-label": t("deleteSkill"),
|
|
1010
|
+
children: t("remove")
|
|
1011
|
+
}
|
|
1012
|
+
),
|
|
1013
|
+
s.writable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1014
|
+
"button",
|
|
1015
|
+
{
|
|
1016
|
+
type: "button",
|
|
1017
|
+
className: `smc-toggle${s.modelInvocable ? " on" : ""}`,
|
|
1018
|
+
title: t("toggleModelVisible"),
|
|
1019
|
+
onClick: () => {
|
|
1020
|
+
void rpc("toggleSkill", { path: s.path }).then(() => {
|
|
1021
|
+
load();
|
|
1022
|
+
});
|
|
1023
|
+
},
|
|
1024
|
+
"aria-label": s.modelInvocable ? t("disable") : t("enable")
|
|
1025
|
+
}
|
|
1026
|
+
)
|
|
1027
|
+
] }),
|
|
1028
|
+
s.description !== "" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-srv-desc", children: s.description }),
|
|
1029
|
+
mdPath === s.path && (mdError !== null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md-err", children: t("mdLoadFailed", { e: mdError }) }) : mdText === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md", children: t("loading") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "smc-md", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MdWithRefs, { text: mdText }) }))
|
|
1030
|
+
] }, skillKeyOf(s)))
|
|
1031
|
+
] }, group.kind)) })
|
|
981
1032
|
] });
|
|
982
1033
|
}
|
|
983
1034
|
var inject = ["slots", "connection", "locale"];
|
package/dist/service.d.ts
CHANGED
|
@@ -163,6 +163,16 @@ export declare class SkillMcpService extends Service {
|
|
|
163
163
|
* bundled inside loaded plugin packages, and any configured official roots.
|
|
164
164
|
*/
|
|
165
165
|
listSkills(cwd?: string): Promise<SkillView[]>;
|
|
166
|
+
/**
|
|
167
|
+
* 补上「运行时注册」的 skill:`ctx.skills.register()` 注册的条目没有 SKILL.md,
|
|
168
|
+
* 磁盘扫描(本项目的主要取数方式)看不到它们——dsh-jubensha 的 DM 手册、office、
|
|
169
|
+
* genui 都属于这一类。用户因此报了「面板少了很多 skill」。
|
|
170
|
+
*
|
|
171
|
+
* skills 服务是**可选**的:web-app 宿主把它关掉(presets 拥有发现,没有全局层可列),
|
|
172
|
+
* 所以这里 feature-detect,拿不到就原样返回空,不改变既有行为。
|
|
173
|
+
* 这些条目没有可写的 SKILL.md,标成 `writable: false`——开关对它们没有意义。
|
|
174
|
+
*/
|
|
175
|
+
private runtimeOnlySkills;
|
|
166
176
|
/** Flip one disk-backed skill's model invocation by rewriting its SKILL.md frontmatter. */
|
|
167
177
|
toggleSkill(path: string): Promise<SkillView>;
|
|
168
178
|
/**
|
package/dist/service.js
CHANGED
|
@@ -268,8 +268,48 @@ export class SkillMcpService extends Service {
|
|
|
268
268
|
for (const dir of this.officialSkillDirs) {
|
|
269
269
|
skills.push(...await scanSkillRoot(dir, 'bundled', false, 'dsh-official'));
|
|
270
270
|
}
|
|
271
|
+
skills.push(...await this.runtimeOnlySkills(skills));
|
|
271
272
|
return skills;
|
|
272
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* 补上「运行时注册」的 skill:`ctx.skills.register()` 注册的条目没有 SKILL.md,
|
|
276
|
+
* 磁盘扫描(本项目的主要取数方式)看不到它们——dsh-jubensha 的 DM 手册、office、
|
|
277
|
+
* genui 都属于这一类。用户因此报了「面板少了很多 skill」。
|
|
278
|
+
*
|
|
279
|
+
* skills 服务是**可选**的:web-app 宿主把它关掉(presets 拥有发现,没有全局层可列),
|
|
280
|
+
* 所以这里 feature-detect,拿不到就原样返回空,不改变既有行为。
|
|
281
|
+
* 这些条目没有可写的 SKILL.md,标成 `writable: false`——开关对它们没有意义。
|
|
282
|
+
*/
|
|
283
|
+
async runtimeOnlySkills(diskBacked) {
|
|
284
|
+
const skills = this.ctx.get('skills');
|
|
285
|
+
if (skills === undefined)
|
|
286
|
+
return [];
|
|
287
|
+
let catalog;
|
|
288
|
+
try {
|
|
289
|
+
catalog = await skills.list();
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// 目录服务不可用不该让整个面板失败——磁盘那部分仍然有价值。
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
const known = new Set(diskBacked.map(skill => skill.name));
|
|
296
|
+
const extra = [];
|
|
297
|
+
for (const entry of catalog) {
|
|
298
|
+
if (known.has(entry.name))
|
|
299
|
+
continue;
|
|
300
|
+
extra.push({
|
|
301
|
+
name: entry.name,
|
|
302
|
+
description: entry.description,
|
|
303
|
+
source: 'runtime',
|
|
304
|
+
provider: entry.provider,
|
|
305
|
+
modelInvocable: entry.invocation.modelInvocable,
|
|
306
|
+
userInvocable: entry.invocation.userInvocable,
|
|
307
|
+
writable: false,
|
|
308
|
+
path: '',
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return extra;
|
|
312
|
+
}
|
|
273
313
|
/** Flip one disk-backed skill's model invocation by rewriting its SKILL.md frontmatter. */
|
|
274
314
|
async toggleSkill(path) {
|
|
275
315
|
let text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@max-null/dsh-skill-mcp-center",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Skill & MCP management center for DeepSeek Harness — manage skills and MCP servers in Settings, live MCP status in the sidebar",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|