@daweifu/capability-menu 0.1.4 → 0.1.5
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.en.md +72 -87
- package/README.md +74 -89
- package/cordis.patch.yml +7 -0
- package/lib/client.d.ts +15 -3
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +710 -442
- package/lib/locations.js +168 -5
- package/lib/locations.js.map +1 -1
- package/lib/patch-file.js +33 -3
- package/lib/patch-file.js.map +1 -1
- package/lib/policy.js +3 -0
- package/lib/policy.js.map +1 -1
- package/lib/registry.js +53 -10
- package/lib/registry.js.map +1 -1
- package/lib/search.js +4 -4
- package/lib/search.js.map +1 -1
- package/lib/server/remote.js +7 -0
- package/lib/server/remote.js.map +1 -1
- package/lib/types/locations.d.ts +2 -0
- package/lib/types/locations.d.ts.map +1 -1
- package/lib/types/patch-file.d.ts.map +1 -1
- package/lib/types/policy.d.ts +2 -0
- package/lib/types/policy.d.ts.map +1 -1
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/search.d.ts +2 -2
- package/lib/types/server/remote.d.ts +2 -0
- package/lib/types/server/remote.d.ts.map +1 -1
- package/package.json +37 -21
package/lib/client.js
CHANGED
|
@@ -3,9 +3,97 @@ var module = { exports: {} };
|
|
|
3
3
|
var exports = module.exports;
|
|
4
4
|
|
|
5
5
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
6
|
+
//#region \0rolldown/runtime.js
|
|
7
|
+
var __create = Object.create;
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
12
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
15
|
+
key = keys[i];
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
17
|
+
get: ((k) => from[k]).bind(null, key),
|
|
18
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
24
|
+
value: mod,
|
|
25
|
+
enumerable: true
|
|
26
|
+
}) : target, mod));
|
|
27
|
+
//#endregion
|
|
6
28
|
let react = require("react");
|
|
7
29
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
30
|
+
_deepseek_ai_dsh_client_ui_primitives = __toESM(_deepseek_ai_dsh_client_ui_primitives, 1);
|
|
8
31
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
//#region src/client/settings-nav-icon.ts
|
|
33
|
+
/** Replace the settings shell's fallback gear with dsh's shared list glyph. */
|
|
34
|
+
const NAV_ICON_MARKER = "data-capability-menu-nav-icon";
|
|
35
|
+
const NAV_ROW_SELECTOR = "[role=\"dialog\"] nav button";
|
|
36
|
+
const NAV_ICON_SIZE = 16;
|
|
37
|
+
/** The geometry of dsh-client-ui-primitives' IconFlatListOutlineMedium. */
|
|
38
|
+
function flatListMaskUrl() {
|
|
39
|
+
return `data:image/svg+xml,${encodeURIComponent("<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"#000\" stroke-linecap=\"round\" stroke-width=\"1.3\"><path d=\"M6 3.5h7.5M6 8h7.5M6 12.5h7.5\"/><path d=\"M2.6 3.5h.01M2.6 8h.01M2.6 12.5h.01\"/></svg>")}`;
|
|
40
|
+
}
|
|
41
|
+
function navIconCss(maskUrl) {
|
|
42
|
+
return [
|
|
43
|
+
`[${NAV_ICON_MARKER}] > svg { display: none; }`,
|
|
44
|
+
`[${NAV_ICON_MARKER}]::before {`,
|
|
45
|
+
" content: \"\";",
|
|
46
|
+
" flex: none;",
|
|
47
|
+
` width: ${NAV_ICON_SIZE}px;`,
|
|
48
|
+
` height: ${NAV_ICON_SIZE}px;`,
|
|
49
|
+
" background-color: currentColor;",
|
|
50
|
+
` -webkit-mask: url("${maskUrl}") center / ${NAV_ICON_SIZE}px ${NAV_ICON_SIZE}px no-repeat;`,
|
|
51
|
+
` mask: url("${maskUrl}") center / ${NAV_ICON_SIZE}px ${NAV_ICON_SIZE}px no-repeat;`,
|
|
52
|
+
"}"
|
|
53
|
+
].join("\n");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The current settings.section slot has no icon option. Match this plugin's
|
|
57
|
+
* localized nav label and replace only its fallback gear, as dsh-market does.
|
|
58
|
+
*/
|
|
59
|
+
function installSettingsNavIcon(ctx, resolveLabel) {
|
|
60
|
+
if (typeof document === "undefined") return;
|
|
61
|
+
ctx.effect(() => {
|
|
62
|
+
const style = document.createElement("style");
|
|
63
|
+
style.dataset.plugin = "capability-menu";
|
|
64
|
+
style.dataset.pluginCss = "capability-menu/settings-nav-icon";
|
|
65
|
+
style.textContent = navIconCss(flatListMaskUrl());
|
|
66
|
+
document.head.appendChild(style);
|
|
67
|
+
let disposed = false;
|
|
68
|
+
let scheduled = false;
|
|
69
|
+
const sync = () => {
|
|
70
|
+
scheduled = false;
|
|
71
|
+
if (disposed) return;
|
|
72
|
+
const wanted = resolveLabel().trim();
|
|
73
|
+
for (const row of document.querySelectorAll(NAV_ROW_SELECTOR)) if (wanted.length > 0 && row.textContent?.trim() === wanted) row.setAttribute(NAV_ICON_MARKER, "");
|
|
74
|
+
else row.removeAttribute(NAV_ICON_MARKER);
|
|
75
|
+
};
|
|
76
|
+
const schedule = () => {
|
|
77
|
+
if (scheduled || disposed) return;
|
|
78
|
+
scheduled = true;
|
|
79
|
+
queueMicrotask(sync);
|
|
80
|
+
};
|
|
81
|
+
sync();
|
|
82
|
+
const observer = new MutationObserver(schedule);
|
|
83
|
+
observer.observe(document.body, {
|
|
84
|
+
childList: true,
|
|
85
|
+
subtree: true,
|
|
86
|
+
characterData: true
|
|
87
|
+
});
|
|
88
|
+
return () => {
|
|
89
|
+
disposed = true;
|
|
90
|
+
observer.disconnect();
|
|
91
|
+
for (const row of document.querySelectorAll(`[${NAV_ICON_MARKER}]`)) row.removeAttribute(NAV_ICON_MARKER);
|
|
92
|
+
style.remove();
|
|
93
|
+
};
|
|
94
|
+
}, "capability-menu: settings nav icon");
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
9
97
|
//#region node_modules/.pnpm/zod@4.5.2/node_modules/zod/v4/core/util.js
|
|
10
98
|
function getEnumValues(entries) {
|
|
11
99
|
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
@@ -5190,6 +5278,18 @@ function superRefine(fn, params) {
|
|
|
5190
5278
|
* namespace and exports a `TYPERT_REMOTE` contribution that the browser
|
|
5191
5279
|
* plugin mounts via `ctx.remote.$mount(...)`.
|
|
5192
5280
|
*/
|
|
5281
|
+
/**
|
|
5282
|
+
* Bridge Typert's codec field rename across DSH 0.1 and 0.2. Older remotes
|
|
5283
|
+
* read `schema`; the 0.2 protocol lazily calls `create()`.
|
|
5284
|
+
*/
|
|
5285
|
+
function strictCodec(typeSymbol, schema) {
|
|
5286
|
+
return {
|
|
5287
|
+
mode: "strict",
|
|
5288
|
+
typeSymbol,
|
|
5289
|
+
schema,
|
|
5290
|
+
create: () => schema
|
|
5291
|
+
};
|
|
5292
|
+
}
|
|
5193
5293
|
const stringRecord$schema = record(string(), string());
|
|
5194
5294
|
const mcpLocation$schema = object({
|
|
5195
5295
|
id: string().readonly(),
|
|
@@ -5296,11 +5396,7 @@ const TYPERT_REMOTE = {
|
|
|
5296
5396
|
method: "getConfig",
|
|
5297
5397
|
invocation: { kind: "direct" },
|
|
5298
5398
|
parameters: [],
|
|
5299
|
-
result:
|
|
5300
|
-
mode: "strict",
|
|
5301
|
-
typeSymbol: "Record<string, unknown>",
|
|
5302
|
-
schema: record(string(), unknown())
|
|
5303
|
-
},
|
|
5399
|
+
result: strictCodec("Record<string, unknown>", record(string(), unknown())),
|
|
5304
5400
|
sourceLocation: {
|
|
5305
5401
|
file: "src/server/remote.ts",
|
|
5306
5402
|
line: 61,
|
|
@@ -5317,17 +5413,9 @@ const TYPERT_REMOTE = {
|
|
|
5317
5413
|
name: "partial",
|
|
5318
5414
|
wire: "partial",
|
|
5319
5415
|
source: "json",
|
|
5320
|
-
codec:
|
|
5321
|
-
mode: "strict",
|
|
5322
|
-
typeSymbol: "Record<string, unknown>",
|
|
5323
|
-
schema: record(string(), unknown())
|
|
5324
|
-
}
|
|
5416
|
+
codec: strictCodec("Record<string, unknown>", record(string(), unknown()))
|
|
5325
5417
|
}],
|
|
5326
|
-
result:
|
|
5327
|
-
mode: "strict",
|
|
5328
|
-
typeSymbol: "void",
|
|
5329
|
-
schema: _undefined()
|
|
5330
|
-
},
|
|
5418
|
+
result: strictCodec("void", _undefined()),
|
|
5331
5419
|
sourceLocation: {
|
|
5332
5420
|
file: "src/server/remote.ts",
|
|
5333
5421
|
line: 67,
|
|
@@ -5341,11 +5429,7 @@ const TYPERT_REMOTE = {
|
|
|
5341
5429
|
method: "classifyAll",
|
|
5342
5430
|
invocation: { kind: "direct" },
|
|
5343
5431
|
parameters: [],
|
|
5344
|
-
result:
|
|
5345
|
-
mode: "strict",
|
|
5346
|
-
typeSymbol: "@daweifu/capability-menu#CapabilityRow",
|
|
5347
|
-
schema: array(capabilityRow$schema)
|
|
5348
|
-
},
|
|
5432
|
+
result: strictCodec("@daweifu/capability-menu#CapabilityRow", array(capabilityRow$schema)),
|
|
5349
5433
|
sourceLocation: {
|
|
5350
5434
|
file: "src/server/remote.ts",
|
|
5351
5435
|
line: 73,
|
|
@@ -5359,11 +5443,7 @@ const TYPERT_REMOTE = {
|
|
|
5359
5443
|
method: "refresh",
|
|
5360
5444
|
invocation: { kind: "direct" },
|
|
5361
5445
|
parameters: [],
|
|
5362
|
-
result:
|
|
5363
|
-
mode: "strict",
|
|
5364
|
-
typeSymbol: "void",
|
|
5365
|
-
schema: _undefined()
|
|
5366
|
-
},
|
|
5446
|
+
result: strictCodec("void", _undefined()),
|
|
5367
5447
|
sourceLocation: {
|
|
5368
5448
|
file: "src/server/remote.ts",
|
|
5369
5449
|
line: 84,
|
|
@@ -5380,27 +5460,15 @@ const TYPERT_REMOTE = {
|
|
|
5380
5460
|
name: "id",
|
|
5381
5461
|
wire: "id",
|
|
5382
5462
|
source: "json",
|
|
5383
|
-
codec:
|
|
5384
|
-
mode: "strict",
|
|
5385
|
-
typeSymbol: "string",
|
|
5386
|
-
schema: string()
|
|
5387
|
-
}
|
|
5463
|
+
codec: strictCodec("string", string())
|
|
5388
5464
|
}, {
|
|
5389
5465
|
name: "relPath",
|
|
5390
5466
|
wire: "relPath",
|
|
5391
5467
|
source: "json",
|
|
5392
5468
|
acceptsUndefined: true,
|
|
5393
|
-
codec:
|
|
5394
|
-
mode: "strict",
|
|
5395
|
-
typeSymbol: "string",
|
|
5396
|
-
schema: string().optional()
|
|
5397
|
-
}
|
|
5469
|
+
codec: strictCodec("string", string().optional())
|
|
5398
5470
|
}],
|
|
5399
|
-
result:
|
|
5400
|
-
mode: "strict",
|
|
5401
|
-
typeSymbol: "@daweifu/capability-menu#SkillFileEntry[]",
|
|
5402
|
-
schema: array(skillFileEntry$schema).optional()
|
|
5403
|
-
},
|
|
5471
|
+
result: strictCodec("@daweifu/capability-menu#SkillFileEntry[]", array(skillFileEntry$schema).optional()),
|
|
5404
5472
|
sourceLocation: {
|
|
5405
5473
|
file: "src/server/remote.ts",
|
|
5406
5474
|
line: 85,
|
|
@@ -5417,26 +5485,14 @@ const TYPERT_REMOTE = {
|
|
|
5417
5485
|
name: "id",
|
|
5418
5486
|
wire: "id",
|
|
5419
5487
|
source: "json",
|
|
5420
|
-
codec:
|
|
5421
|
-
mode: "strict",
|
|
5422
|
-
typeSymbol: "string",
|
|
5423
|
-
schema: string()
|
|
5424
|
-
}
|
|
5488
|
+
codec: strictCodec("string", string())
|
|
5425
5489
|
}, {
|
|
5426
5490
|
name: "relPath",
|
|
5427
5491
|
wire: "relPath",
|
|
5428
5492
|
source: "json",
|
|
5429
|
-
codec:
|
|
5430
|
-
mode: "strict",
|
|
5431
|
-
typeSymbol: "string",
|
|
5432
|
-
schema: string()
|
|
5433
|
-
}
|
|
5493
|
+
codec: strictCodec("string", string())
|
|
5434
5494
|
}],
|
|
5435
|
-
result:
|
|
5436
|
-
mode: "strict",
|
|
5437
|
-
typeSymbol: "string",
|
|
5438
|
-
schema: string().optional()
|
|
5439
|
-
},
|
|
5495
|
+
result: strictCodec("string", string().optional()),
|
|
5440
5496
|
sourceLocation: {
|
|
5441
5497
|
file: "src/server/remote.ts",
|
|
5442
5498
|
line: 91,
|
|
@@ -5453,17 +5509,9 @@ const TYPERT_REMOTE = {
|
|
|
5453
5509
|
name: "id",
|
|
5454
5510
|
wire: "id",
|
|
5455
5511
|
source: "json",
|
|
5456
|
-
codec:
|
|
5457
|
-
mode: "strict",
|
|
5458
|
-
typeSymbol: "string",
|
|
5459
|
-
schema: string()
|
|
5460
|
-
}
|
|
5512
|
+
codec: strictCodec("string", string())
|
|
5461
5513
|
}],
|
|
5462
|
-
result:
|
|
5463
|
-
mode: "strict",
|
|
5464
|
-
typeSymbol: "@daweifu/capability-menu#ToolDetail",
|
|
5465
|
-
schema: toolDetail$schema.optional()
|
|
5466
|
-
},
|
|
5514
|
+
result: strictCodec("@daweifu/capability-menu#ToolDetail", toolDetail$schema.optional()),
|
|
5467
5515
|
sourceLocation: {
|
|
5468
5516
|
file: "src/server/remote.ts",
|
|
5469
5517
|
line: 79,
|
|
@@ -5477,11 +5525,7 @@ const TYPERT_REMOTE = {
|
|
|
5477
5525
|
method: "getCatalogDocs",
|
|
5478
5526
|
invocation: { kind: "direct" },
|
|
5479
5527
|
parameters: [],
|
|
5480
|
-
result:
|
|
5481
|
-
mode: "strict",
|
|
5482
|
-
typeSymbol: "@daweifu/capability-menu#CatalogDocs",
|
|
5483
|
-
schema: catalogDocs$schema
|
|
5484
|
-
},
|
|
5528
|
+
result: strictCodec("@daweifu/capability-menu#CatalogDocs", catalogDocs$schema),
|
|
5485
5529
|
sourceLocation: {
|
|
5486
5530
|
file: "src/server/remote.ts",
|
|
5487
5531
|
line: 104,
|
|
@@ -5495,11 +5539,7 @@ const TYPERT_REMOTE = {
|
|
|
5495
5539
|
method: "listLocations",
|
|
5496
5540
|
invocation: { kind: "direct" },
|
|
5497
5541
|
parameters: [],
|
|
5498
|
-
result:
|
|
5499
|
-
mode: "strict",
|
|
5500
|
-
typeSymbol: "@daweifu/capability-menu#McpLocation[]",
|
|
5501
|
-
schema: array(mcpLocation$schema)
|
|
5502
|
-
},
|
|
5542
|
+
result: strictCodec("@daweifu/capability-menu#McpLocation[]", array(mcpLocation$schema)),
|
|
5503
5543
|
sourceLocation: {
|
|
5504
5544
|
file: "src/server/remote.ts",
|
|
5505
5545
|
line: 193,
|
|
@@ -5516,17 +5556,9 @@ const TYPERT_REMOTE = {
|
|
|
5516
5556
|
name: "input",
|
|
5517
5557
|
wire: "input",
|
|
5518
5558
|
source: "json",
|
|
5519
|
-
codec:
|
|
5520
|
-
mode: "strict",
|
|
5521
|
-
typeSymbol: "@daweifu/capability-menu#McpInput",
|
|
5522
|
-
schema: mcpInput$schema
|
|
5523
|
-
}
|
|
5559
|
+
codec: strictCodec("@daweifu/capability-menu#McpInput", mcpInput$schema)
|
|
5524
5560
|
}],
|
|
5525
|
-
result:
|
|
5526
|
-
mode: "strict",
|
|
5527
|
-
typeSymbol: "string",
|
|
5528
|
-
schema: string()
|
|
5529
|
-
},
|
|
5561
|
+
result: strictCodec("string", string()),
|
|
5530
5562
|
sourceLocation: {
|
|
5531
5563
|
file: "src/server/remote.ts",
|
|
5532
5564
|
line: 199,
|
|
@@ -5543,17 +5575,9 @@ const TYPERT_REMOTE = {
|
|
|
5543
5575
|
name: "id",
|
|
5544
5576
|
wire: "id",
|
|
5545
5577
|
source: "json",
|
|
5546
|
-
codec:
|
|
5547
|
-
mode: "strict",
|
|
5548
|
-
typeSymbol: "string",
|
|
5549
|
-
schema: string()
|
|
5550
|
-
}
|
|
5578
|
+
codec: strictCodec("string", string())
|
|
5551
5579
|
}],
|
|
5552
|
-
result:
|
|
5553
|
-
mode: "strict",
|
|
5554
|
-
typeSymbol: "boolean",
|
|
5555
|
-
schema: boolean()
|
|
5556
|
-
},
|
|
5580
|
+
result: strictCodec("boolean", boolean()),
|
|
5557
5581
|
sourceLocation: {
|
|
5558
5582
|
file: "src/server/remote.ts",
|
|
5559
5583
|
line: 205,
|
|
@@ -5570,26 +5594,14 @@ const TYPERT_REMOTE = {
|
|
|
5570
5594
|
name: "id",
|
|
5571
5595
|
wire: "id",
|
|
5572
5596
|
source: "json",
|
|
5573
|
-
codec:
|
|
5574
|
-
mode: "strict",
|
|
5575
|
-
typeSymbol: "string",
|
|
5576
|
-
schema: string()
|
|
5577
|
-
}
|
|
5597
|
+
codec: strictCodec("string", string())
|
|
5578
5598
|
}, {
|
|
5579
5599
|
name: "input",
|
|
5580
5600
|
wire: "input",
|
|
5581
5601
|
source: "json",
|
|
5582
|
-
codec:
|
|
5583
|
-
mode: "strict",
|
|
5584
|
-
typeSymbol: "@daweifu/capability-menu#McpUpdateInput",
|
|
5585
|
-
schema: mcpUpdateInput$schema
|
|
5586
|
-
}
|
|
5602
|
+
codec: strictCodec("@daweifu/capability-menu#McpUpdateInput", mcpUpdateInput$schema)
|
|
5587
5603
|
}],
|
|
5588
|
-
result:
|
|
5589
|
-
mode: "strict",
|
|
5590
|
-
typeSymbol: "boolean",
|
|
5591
|
-
schema: boolean()
|
|
5592
|
-
},
|
|
5604
|
+
result: strictCodec("boolean", boolean()),
|
|
5593
5605
|
sourceLocation: {
|
|
5594
5606
|
file: "src/server/remote.ts",
|
|
5595
5607
|
line: 211,
|
|
@@ -5603,11 +5615,7 @@ const TYPERT_REMOTE = {
|
|
|
5603
5615
|
method: "listSkillLocations",
|
|
5604
5616
|
invocation: { kind: "direct" },
|
|
5605
5617
|
parameters: [],
|
|
5606
|
-
result:
|
|
5607
|
-
mode: "strict",
|
|
5608
|
-
typeSymbol: "@daweifu/capability-menu#SkillLocation[]",
|
|
5609
|
-
schema: array(skillLocation$schema)
|
|
5610
|
-
},
|
|
5618
|
+
result: strictCodec("@daweifu/capability-menu#SkillLocation[]", array(skillLocation$schema)),
|
|
5611
5619
|
sourceLocation: {
|
|
5612
5620
|
file: "src/server/remote.ts",
|
|
5613
5621
|
line: 229,
|
|
@@ -5624,33 +5632,46 @@ const TYPERT_REMOTE = {
|
|
|
5624
5632
|
name: "dir",
|
|
5625
5633
|
wire: "dir",
|
|
5626
5634
|
source: "json",
|
|
5627
|
-
codec:
|
|
5628
|
-
mode: "strict",
|
|
5629
|
-
typeSymbol: "string",
|
|
5630
|
-
schema: string()
|
|
5631
|
-
}
|
|
5635
|
+
codec: strictCodec("string", string())
|
|
5632
5636
|
}, {
|
|
5633
5637
|
name: "projectPath",
|
|
5634
5638
|
wire: "projectPath",
|
|
5635
5639
|
source: "json",
|
|
5636
5640
|
acceptsUndefined: true,
|
|
5637
|
-
codec:
|
|
5638
|
-
mode: "strict",
|
|
5639
|
-
typeSymbol: "string",
|
|
5640
|
-
schema: string().optional()
|
|
5641
|
-
}
|
|
5641
|
+
codec: strictCodec("string", string().optional())
|
|
5642
5642
|
}],
|
|
5643
|
-
result:
|
|
5644
|
-
mode: "strict",
|
|
5645
|
-
typeSymbol: "string",
|
|
5646
|
-
schema: string()
|
|
5647
|
-
},
|
|
5643
|
+
result: strictCodec("string", string()),
|
|
5648
5644
|
sourceLocation: {
|
|
5649
5645
|
file: "src/server/remote.ts",
|
|
5650
5646
|
line: 252,
|
|
5651
5647
|
column: 3
|
|
5652
5648
|
}
|
|
5653
5649
|
},
|
|
5650
|
+
{
|
|
5651
|
+
id: "@daweifu/capability-menu#capabilityPolicy/importSkillFromGitHub",
|
|
5652
|
+
service: "capabilityPolicy",
|
|
5653
|
+
namespace: "capabilityPolicy",
|
|
5654
|
+
method: "importSkillFromGitHub",
|
|
5655
|
+
invocation: { kind: "direct" },
|
|
5656
|
+
parameters: [{
|
|
5657
|
+
name: "url",
|
|
5658
|
+
wire: "url",
|
|
5659
|
+
source: "json",
|
|
5660
|
+
codec: strictCodec("string", string())
|
|
5661
|
+
}, {
|
|
5662
|
+
name: "projectPath",
|
|
5663
|
+
wire: "projectPath",
|
|
5664
|
+
source: "json",
|
|
5665
|
+
acceptsUndefined: true,
|
|
5666
|
+
codec: strictCodec("string", string().optional())
|
|
5667
|
+
}],
|
|
5668
|
+
result: strictCodec("string", string()),
|
|
5669
|
+
sourceLocation: {
|
|
5670
|
+
file: "src/server/remote.ts",
|
|
5671
|
+
line: 263,
|
|
5672
|
+
column: 3
|
|
5673
|
+
}
|
|
5674
|
+
},
|
|
5654
5675
|
{
|
|
5655
5676
|
id: "@daweifu/capability-menu#capabilityPolicy/removeSkillLocation",
|
|
5656
5677
|
service: "capabilityPolicy",
|
|
@@ -5661,27 +5682,15 @@ const TYPERT_REMOTE = {
|
|
|
5661
5682
|
name: "name",
|
|
5662
5683
|
wire: "name",
|
|
5663
5684
|
source: "json",
|
|
5664
|
-
codec:
|
|
5665
|
-
mode: "strict",
|
|
5666
|
-
typeSymbol: "string",
|
|
5667
|
-
schema: string()
|
|
5668
|
-
}
|
|
5685
|
+
codec: strictCodec("string", string())
|
|
5669
5686
|
}, {
|
|
5670
5687
|
name: "entryDir",
|
|
5671
5688
|
wire: "entryDir",
|
|
5672
5689
|
source: "json",
|
|
5673
5690
|
acceptsUndefined: true,
|
|
5674
|
-
codec:
|
|
5675
|
-
mode: "strict",
|
|
5676
|
-
typeSymbol: "string",
|
|
5677
|
-
schema: string().optional()
|
|
5678
|
-
}
|
|
5691
|
+
codec: strictCodec("string", string().optional())
|
|
5679
5692
|
}],
|
|
5680
|
-
result:
|
|
5681
|
-
mode: "strict",
|
|
5682
|
-
typeSymbol: "boolean",
|
|
5683
|
-
schema: boolean()
|
|
5684
|
-
},
|
|
5693
|
+
result: strictCodec("boolean", boolean()),
|
|
5685
5694
|
sourceLocation: {
|
|
5686
5695
|
file: "src/server/remote.ts",
|
|
5687
5696
|
line: 258,
|
|
@@ -5698,17 +5707,9 @@ const TYPERT_REMOTE = {
|
|
|
5698
5707
|
name: "name",
|
|
5699
5708
|
wire: "name",
|
|
5700
5709
|
source: "json",
|
|
5701
|
-
codec:
|
|
5702
|
-
mode: "strict",
|
|
5703
|
-
typeSymbol: "string",
|
|
5704
|
-
schema: string()
|
|
5705
|
-
}
|
|
5710
|
+
codec: strictCodec("string", string())
|
|
5706
5711
|
}],
|
|
5707
|
-
result:
|
|
5708
|
-
mode: "strict",
|
|
5709
|
-
typeSymbol: "string",
|
|
5710
|
-
schema: string()
|
|
5711
|
-
},
|
|
5712
|
+
result: strictCodec("string", string()),
|
|
5712
5713
|
sourceLocation: {
|
|
5713
5714
|
file: "src/server/remote.ts",
|
|
5714
5715
|
line: 259,
|
|
@@ -5726,39 +5727,23 @@ const TYPERT_REMOTE = {
|
|
|
5726
5727
|
name: "name",
|
|
5727
5728
|
wire: "name",
|
|
5728
5729
|
source: "json",
|
|
5729
|
-
codec:
|
|
5730
|
-
mode: "strict",
|
|
5731
|
-
typeSymbol: "string",
|
|
5732
|
-
schema: string()
|
|
5733
|
-
}
|
|
5730
|
+
codec: strictCodec("string", string())
|
|
5734
5731
|
},
|
|
5735
5732
|
{
|
|
5736
5733
|
name: "dir",
|
|
5737
5734
|
wire: "dir",
|
|
5738
5735
|
source: "json",
|
|
5739
|
-
codec:
|
|
5740
|
-
mode: "strict",
|
|
5741
|
-
typeSymbol: "string",
|
|
5742
|
-
schema: string()
|
|
5743
|
-
}
|
|
5736
|
+
codec: strictCodec("string", string())
|
|
5744
5737
|
},
|
|
5745
5738
|
{
|
|
5746
5739
|
name: "entryDir",
|
|
5747
5740
|
wire: "entryDir",
|
|
5748
5741
|
source: "json",
|
|
5749
5742
|
acceptsUndefined: true,
|
|
5750
|
-
codec:
|
|
5751
|
-
mode: "strict",
|
|
5752
|
-
typeSymbol: "string",
|
|
5753
|
-
schema: string().optional()
|
|
5754
|
-
}
|
|
5743
|
+
codec: strictCodec("string", string().optional())
|
|
5755
5744
|
}
|
|
5756
5745
|
],
|
|
5757
|
-
result:
|
|
5758
|
-
mode: "strict",
|
|
5759
|
-
typeSymbol: "boolean",
|
|
5760
|
-
schema: boolean()
|
|
5761
|
-
},
|
|
5746
|
+
result: strictCodec("boolean", boolean()),
|
|
5762
5747
|
sourceLocation: {
|
|
5763
5748
|
file: "src/server/remote.ts",
|
|
5764
5749
|
line: 264,
|
|
@@ -5772,11 +5757,7 @@ const TYPERT_REMOTE = {
|
|
|
5772
5757
|
method: "catalogVersion",
|
|
5773
5758
|
invocation: { kind: "direct" },
|
|
5774
5759
|
parameters: [],
|
|
5775
|
-
result:
|
|
5776
|
-
mode: "strict",
|
|
5777
|
-
typeSymbol: "number",
|
|
5778
|
-
schema: number()
|
|
5779
|
-
},
|
|
5760
|
+
result: strictCodec("number", number()),
|
|
5780
5761
|
sourceLocation: {
|
|
5781
5762
|
file: "src/server/remote.ts",
|
|
5782
5763
|
line: 317,
|
|
@@ -5816,15 +5797,52 @@ function unwrapMessage(result) {
|
|
|
5816
5797
|
* still followed by an authoritative one.
|
|
5817
5798
|
*/
|
|
5818
5799
|
let lastSnapshot;
|
|
5800
|
+
/** Short grace period for host tools that register just after the section mounts. */
|
|
5801
|
+
const EMPTY_SNAPSHOT_RETRY_DELAYS = [
|
|
5802
|
+
250,
|
|
5803
|
+
500,
|
|
5804
|
+
1e3,
|
|
5805
|
+
1500
|
|
5806
|
+
];
|
|
5819
5807
|
/** The previously loaded snapshot, when this page session has one. */
|
|
5820
5808
|
function cachedSnapshot() {
|
|
5821
5809
|
return lastSnapshot;
|
|
5822
5810
|
}
|
|
5823
|
-
/**
|
|
5824
|
-
async function
|
|
5825
|
-
|
|
5811
|
+
/** Read one authoritative classification list without changing the view cache. */
|
|
5812
|
+
async function readSnapshot(remote) {
|
|
5813
|
+
return { rows: unwrap(await remote.classifyAll(), "capabilityPolicy.classifyAll") };
|
|
5814
|
+
}
|
|
5815
|
+
/** Remember a snapshot after its contents are ready to replace the current view. */
|
|
5816
|
+
function rememberSnapshot(snapshot) {
|
|
5817
|
+
lastSnapshot = snapshot;
|
|
5826
5818
|
return lastSnapshot;
|
|
5827
5819
|
}
|
|
5820
|
+
/**
|
|
5821
|
+
* Load the classification list, retrying an empty result briefly because
|
|
5822
|
+
* built-in tools can register just after the settings section mounts.
|
|
5823
|
+
* Non-empty results remain authoritative and return immediately.
|
|
5824
|
+
*/
|
|
5825
|
+
async function loadSnapshot(remote, retryDelays = EMPTY_SNAPSHOT_RETRY_DELAYS) {
|
|
5826
|
+
let snapshot = await readSnapshot(remote);
|
|
5827
|
+
for (const delayMs of retryDelays) {
|
|
5828
|
+
if (snapshot.rows.length > 0) break;
|
|
5829
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
5830
|
+
snapshot = await readSnapshot(remote);
|
|
5831
|
+
}
|
|
5832
|
+
return rememberSnapshot(snapshot);
|
|
5833
|
+
}
|
|
5834
|
+
/** Wait briefly for an MCP's tools to enter the host catalog after registration. */
|
|
5835
|
+
async function waitForMcpTools(remote, serverName, retryDelays) {
|
|
5836
|
+
const prefix = `mcp__${serverName}__`;
|
|
5837
|
+
const hasServerTools = (snapshot) => snapshot.rows.some((row) => row.kind === "tool" && row.id.startsWith(prefix));
|
|
5838
|
+
let snapshot = await readSnapshot(remote);
|
|
5839
|
+
if (hasServerTools(snapshot)) return snapshot;
|
|
5840
|
+
for (const delayMs of retryDelays) {
|
|
5841
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
5842
|
+
snapshot = await readSnapshot(remote);
|
|
5843
|
+
if (hasServerTools(snapshot)) return snapshot;
|
|
5844
|
+
}
|
|
5845
|
+
}
|
|
5828
5846
|
//#endregion
|
|
5829
5847
|
//#region src/client/LocationModal.tsx
|
|
5830
5848
|
/**
|
|
@@ -5870,6 +5888,11 @@ textarea.lm-input{resize:vertical;font-family:var(--dsw-font-markdown-code-block
|
|
|
5870
5888
|
annotates and takes the caption colour so it does not read as another label. */
|
|
5871
5889
|
.lm-hint{grid-column:2;margin:0;font-size:11px;line-height:16px;color:var(--dsw-alias-label-caption)}
|
|
5872
5890
|
.lm-error{margin:0;font-size:12px;color:#b3261e;word-break:break-word}
|
|
5891
|
+
.lm-progress{display:flex;align-items:center;gap:8px;margin:0;font-size:12px;line-height:20px;color:var(--dsw-alias-label-secondary)}
|
|
5892
|
+
.lm-spinner{width:12px;height:12px;flex:none;border:2px solid var(--dsw-alias-border-l2);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:lm-spin .8s linear infinite}
|
|
5893
|
+
@keyframes lm-spin{to{transform:rotate(360deg)}}
|
|
5894
|
+
@media(prefers-reduced-motion:reduce){.lm-spinner{animation-duration:2s}}
|
|
5895
|
+
.mc-tab:disabled,.mc-preview-close:disabled{cursor:default;opacity:.6}
|
|
5873
5896
|
.lm-actions{display:flex;gap:8px;justify-content:flex-end;padding:4px 0 0}
|
|
5874
5897
|
/* Removal is irreversible, so it takes over the action row for one confirmation
|
|
5875
5898
|
step: the message states the consequence, then the buttons act. */
|
|
@@ -5909,8 +5932,9 @@ function LocationModal(props) {
|
|
|
5909
5932
|
const { remote, t, defaultKind = "mcp", editMcp, editSkill, onClose, onChanged } = props;
|
|
5910
5933
|
const editing = editMcp !== void 0 || editSkill !== void 0;
|
|
5911
5934
|
const [subTab, setSubTab] = (0, react.useState)(editSkill !== void 0 ? "skill" : editMcp !== void 0 ? "mcp" : defaultKind);
|
|
5912
|
-
const [
|
|
5935
|
+
const [errors, setErrors] = (0, react.useState)({});
|
|
5913
5936
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
5937
|
+
const [progressMessage, setProgressMessage] = (0, react.useState)(null);
|
|
5914
5938
|
/**
|
|
5915
5939
|
* Which action is waiting for confirmation, if any. Two need one: 移除, and
|
|
5916
5940
|
* 保存 on an entry that is a real directory — repointing unlinks the entry
|
|
@@ -5948,31 +5972,49 @@ function LocationModal(props) {
|
|
|
5948
5972
|
t
|
|
5949
5973
|
]);
|
|
5950
5974
|
/** Run a mutation; on success close and ask the parent to re-pull. */
|
|
5951
|
-
const submit = (0, react.useCallback)(async (action, noticeFor) => {
|
|
5975
|
+
const submit = (0, react.useCallback)(async (action, noticeFor, progress, registeredMcp) => {
|
|
5952
5976
|
if (busy) return;
|
|
5953
5977
|
setBusy(true);
|
|
5978
|
+
setProgressMessage(progress ?? null);
|
|
5979
|
+
setErrors((prev) => {
|
|
5980
|
+
const next = { ...prev };
|
|
5981
|
+
delete next[subTab];
|
|
5982
|
+
return next;
|
|
5983
|
+
});
|
|
5954
5984
|
try {
|
|
5955
5985
|
const changed = await action();
|
|
5956
5986
|
if (changed === false) throw new Error(t("entryNotFound"));
|
|
5957
|
-
|
|
5958
|
-
|
|
5987
|
+
setErrors((prev) => {
|
|
5988
|
+
const next = { ...prev };
|
|
5989
|
+
delete next[subTab];
|
|
5990
|
+
return next;
|
|
5991
|
+
});
|
|
5992
|
+
onChanged(noticeFor?.(changed), registeredMcp);
|
|
5959
5993
|
onClose();
|
|
5960
5994
|
} catch (e) {
|
|
5961
|
-
|
|
5995
|
+
setErrors((prev) => ({
|
|
5996
|
+
...prev,
|
|
5997
|
+
[subTab]: String(e)
|
|
5998
|
+
}));
|
|
5962
5999
|
} finally {
|
|
5963
6000
|
setBusy(false);
|
|
6001
|
+
setProgressMessage(null);
|
|
5964
6002
|
}
|
|
5965
6003
|
}, [
|
|
5966
6004
|
busy,
|
|
5967
6005
|
onChanged,
|
|
5968
6006
|
onClose,
|
|
6007
|
+
subTab,
|
|
5969
6008
|
t
|
|
5970
6009
|
]);
|
|
5971
6010
|
const submitMcp = (0, react.useCallback)(() => {
|
|
5972
6011
|
const trimmedTimeout = timeoutSec.trim();
|
|
5973
6012
|
const timeoutMs = trimmedTimeout.length === 0 ? void 0 : Math.round(Number(trimmedTimeout) * 1e3);
|
|
5974
6013
|
if (timeoutMs !== void 0 && !Number.isFinite(timeoutMs)) {
|
|
5975
|
-
|
|
6014
|
+
setErrors((prev) => ({
|
|
6015
|
+
...prev,
|
|
6016
|
+
mcp: t("timeoutInvalid")
|
|
6017
|
+
}));
|
|
5976
6018
|
return;
|
|
5977
6019
|
}
|
|
5978
6020
|
const parsedEnv = fromLines(env);
|
|
@@ -5993,7 +6035,7 @@ function LocationModal(props) {
|
|
|
5993
6035
|
submit(async () => editMcp !== void 0 ? unwrapMessage(await remote.updateLocation(editMcp.id, common)) : unwrapMessage(await remote.addLocation({
|
|
5994
6036
|
serverName: serverName.trim(),
|
|
5995
6037
|
...common
|
|
5996
|
-
})));
|
|
6038
|
+
})), void 0, void 0, editMcp?.serverName ?? serverName.trim());
|
|
5997
6039
|
}, [
|
|
5998
6040
|
submit,
|
|
5999
6041
|
remote,
|
|
@@ -6010,8 +6052,13 @@ function LocationModal(props) {
|
|
|
6010
6052
|
t
|
|
6011
6053
|
]);
|
|
6012
6054
|
const submitSkill = (0, react.useCallback)(() => {
|
|
6055
|
+
const source = skillDir.trim();
|
|
6013
6056
|
const asked = skillRoot === "project" ? projectPath.trim() : void 0;
|
|
6014
|
-
submit(async () =>
|
|
6057
|
+
submit(async () => {
|
|
6058
|
+
if (editSkill !== void 0) return unwrapMessage(await remote.updateSkillLocation(editSkill.name, source, editSkill.entryDir));
|
|
6059
|
+
if (/^https?:\/\//i.test(source)) return unwrapMessage(await remote.importSkillFromGitHub(source, asked));
|
|
6060
|
+
return unwrapMessage(await remote.addSkillLocation(source, asked));
|
|
6061
|
+
}, (result) => editSkill !== void 0 ? t("skillRepointed", { dir: source }) : t("skillRegisteredAt", { path: String(result) }), editSkill === void 0 && /^https:\/\//i.test(source) ? t("githubImporting") : void 0);
|
|
6015
6062
|
}, [
|
|
6016
6063
|
submit,
|
|
6017
6064
|
remote,
|
|
@@ -6087,7 +6134,7 @@ function LocationModal(props) {
|
|
|
6087
6134
|
if (needsSaveConfirm) setConfirm("save");
|
|
6088
6135
|
else onSubmit();
|
|
6089
6136
|
},
|
|
6090
|
-
children: editing ? t("save") : t("register")
|
|
6137
|
+
children: progressMessage !== null ? t("importing") : editing ? t("save") : t("register")
|
|
6091
6138
|
}), editing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6092
6139
|
type: "button",
|
|
6093
6140
|
className: "lm-btn lm-btn--danger",
|
|
@@ -6098,7 +6145,7 @@ function LocationModal(props) {
|
|
|
6098
6145
|
});
|
|
6099
6146
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6100
6147
|
className: "mc-preview-mask",
|
|
6101
|
-
onClick: onClose,
|
|
6148
|
+
onClick: busy ? void 0 : onClose,
|
|
6102
6149
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6103
6150
|
className: "mc-preview",
|
|
6104
6151
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -6111,6 +6158,7 @@ function LocationModal(props) {
|
|
|
6111
6158
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6112
6159
|
type: "button",
|
|
6113
6160
|
className: "mc-preview-close",
|
|
6161
|
+
disabled: busy,
|
|
6114
6162
|
onClick: onClose,
|
|
6115
6163
|
children: t("previewClose")
|
|
6116
6164
|
})]
|
|
@@ -6127,6 +6175,7 @@ function LocationModal(props) {
|
|
|
6127
6175
|
className: "mc-tab",
|
|
6128
6176
|
"aria-selected": subTab === "mcp",
|
|
6129
6177
|
"data-active": subTab === "mcp" ? "true" : void 0,
|
|
6178
|
+
disabled: busy,
|
|
6130
6179
|
onClick: () => setSubTab("mcp"),
|
|
6131
6180
|
children: t("mcpServers")
|
|
6132
6181
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -6135,6 +6184,7 @@ function LocationModal(props) {
|
|
|
6135
6184
|
className: "mc-tab",
|
|
6136
6185
|
"aria-selected": subTab === "skill",
|
|
6137
6186
|
"data-active": subTab === "skill" ? "true" : void 0,
|
|
6187
|
+
disabled: busy,
|
|
6138
6188
|
onClick: () => setSubTab("skill"),
|
|
6139
6189
|
children: t("skillDirs")
|
|
6140
6190
|
})]
|
|
@@ -6142,222 +6192,234 @@ function LocationModal(props) {
|
|
|
6142
6192
|
}),
|
|
6143
6193
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6144
6194
|
className: "lm-body",
|
|
6145
|
-
children: [
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
className: "lm-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
children: t("
|
|
6195
|
+
children: [
|
|
6196
|
+
errors[subTab] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6197
|
+
className: "lm-error",
|
|
6198
|
+
children: errors[subTab]
|
|
6199
|
+
}),
|
|
6200
|
+
progressMessage !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
6201
|
+
className: "lm-progress",
|
|
6202
|
+
role: "status",
|
|
6203
|
+
"aria-live": "polite",
|
|
6204
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6205
|
+
className: "lm-spinner",
|
|
6206
|
+
"aria-hidden": "true"
|
|
6207
|
+
}), progressMessage]
|
|
6208
|
+
}),
|
|
6209
|
+
subTab === "mcp" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6210
|
+
className: "lm-block",
|
|
6211
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6212
|
+
className: "lm-form",
|
|
6213
|
+
children: [
|
|
6214
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6215
|
+
className: "lm-field",
|
|
6216
|
+
children: [
|
|
6217
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6218
|
+
className: "lm-label",
|
|
6219
|
+
children: t("transport")
|
|
6220
|
+
}),
|
|
6221
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
6222
|
+
className: "lm-input",
|
|
6223
|
+
value: transport,
|
|
6224
|
+
onChange: (e) => setTransport(e.target.value === "stdio" ? "stdio" : "streamable-http"),
|
|
6225
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6226
|
+
value: "stdio",
|
|
6227
|
+
children: t("transportStdio")
|
|
6228
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6229
|
+
value: "streamable-http",
|
|
6230
|
+
children: t("transportHttp")
|
|
6231
|
+
})]
|
|
6232
|
+
}),
|
|
6233
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6234
|
+
className: "lm-hint",
|
|
6235
|
+
children: transport === "stdio" ? t("transportHintStdio") : t("transportHintHttp")
|
|
6236
|
+
})
|
|
6237
|
+
]
|
|
6238
|
+
}),
|
|
6239
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6240
|
+
className: "lm-field",
|
|
6241
|
+
children: [
|
|
6242
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6243
|
+
className: "lm-label",
|
|
6244
|
+
children: t("serverName")
|
|
6245
|
+
}),
|
|
6246
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6247
|
+
className: "lm-input",
|
|
6248
|
+
value: serverName,
|
|
6249
|
+
disabled: editMcp !== void 0,
|
|
6250
|
+
onChange: (e) => setServerName(e.target.value)
|
|
6251
|
+
}),
|
|
6252
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6253
|
+
className: "lm-hint",
|
|
6254
|
+
children: t("serverNameImmutable")
|
|
6255
|
+
})
|
|
6256
|
+
]
|
|
6257
|
+
}),
|
|
6258
|
+
transport === "stdio" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6259
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6260
|
+
className: "lm-field",
|
|
6261
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6262
|
+
className: "lm-label",
|
|
6263
|
+
children: t("command")
|
|
6264
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6265
|
+
className: "lm-input",
|
|
6266
|
+
value: command,
|
|
6267
|
+
onChange: (e) => setCommand(e.target.value)
|
|
6170
6268
|
})]
|
|
6171
6269
|
}),
|
|
6172
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6173
|
-
className: "lm-
|
|
6174
|
-
children:
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
className: "lm-label",
|
|
6183
|
-
children: t("serverName")
|
|
6270
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6271
|
+
className: "lm-field",
|
|
6272
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6273
|
+
className: "lm-label",
|
|
6274
|
+
children: t("args")
|
|
6275
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6276
|
+
className: "lm-input",
|
|
6277
|
+
value: args,
|
|
6278
|
+
onChange: (e) => setArgs(e.target.value)
|
|
6279
|
+
})]
|
|
6184
6280
|
}),
|
|
6185
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
6186
|
-
className: "lm-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6281
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6282
|
+
className: "lm-field",
|
|
6283
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6284
|
+
className: "lm-label",
|
|
6285
|
+
children: t("cwd")
|
|
6286
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6287
|
+
className: "lm-input",
|
|
6288
|
+
value: cwd,
|
|
6289
|
+
onChange: (e) => setCwd(e.target.value)
|
|
6290
|
+
})]
|
|
6190
6291
|
}),
|
|
6191
|
-
|
|
6192
|
-
className: "lm-
|
|
6193
|
-
children:
|
|
6292
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6293
|
+
className: "lm-field",
|
|
6294
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6295
|
+
className: "lm-label",
|
|
6296
|
+
children: t("env")
|
|
6297
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
6298
|
+
className: "lm-input",
|
|
6299
|
+
rows: 3,
|
|
6300
|
+
value: env,
|
|
6301
|
+
onChange: (e) => setEnv(e.target.value)
|
|
6302
|
+
})]
|
|
6194
6303
|
})
|
|
6195
|
-
]
|
|
6196
|
-
}),
|
|
6197
|
-
transport === "stdio" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6198
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6304
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6199
6305
|
className: "lm-field",
|
|
6200
6306
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6201
6307
|
className: "lm-label",
|
|
6202
|
-
children: t("
|
|
6308
|
+
children: t("url")
|
|
6203
6309
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6204
6310
|
className: "lm-input",
|
|
6205
|
-
value:
|
|
6206
|
-
onChange: (e) =>
|
|
6311
|
+
value: url,
|
|
6312
|
+
onChange: (e) => setUrl(e.target.value)
|
|
6207
6313
|
})]
|
|
6208
|
-
}),
|
|
6314
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6315
|
+
className: "lm-field",
|
|
6316
|
+
children: [
|
|
6317
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6318
|
+
className: "lm-label",
|
|
6319
|
+
children: t("headers")
|
|
6320
|
+
}),
|
|
6321
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
6322
|
+
className: "lm-input",
|
|
6323
|
+
rows: 4,
|
|
6324
|
+
value: headers,
|
|
6325
|
+
onChange: (e) => setHeaders(e.target.value)
|
|
6326
|
+
}),
|
|
6327
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6328
|
+
className: "lm-hint",
|
|
6329
|
+
children: t("headersHint")
|
|
6330
|
+
})
|
|
6331
|
+
]
|
|
6332
|
+
})] }),
|
|
6209
6333
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6210
6334
|
className: "lm-field",
|
|
6211
6335
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6212
6336
|
className: "lm-label",
|
|
6213
|
-
children: t("
|
|
6337
|
+
children: t("timeout")
|
|
6214
6338
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6215
6339
|
className: "lm-input",
|
|
6216
|
-
value:
|
|
6217
|
-
|
|
6340
|
+
value: timeoutSec,
|
|
6341
|
+
placeholder: "60",
|
|
6342
|
+
onChange: (e) => setTimeoutSec(e.target.value)
|
|
6218
6343
|
})]
|
|
6219
6344
|
}),
|
|
6345
|
+
renderActions(() => void submitMcp())
|
|
6346
|
+
]
|
|
6347
|
+
})
|
|
6348
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6349
|
+
className: "lm-block",
|
|
6350
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6351
|
+
className: "lm-form",
|
|
6352
|
+
children: [
|
|
6220
6353
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6221
6354
|
className: "lm-field",
|
|
6222
|
-
children: [
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6355
|
+
children: [
|
|
6356
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6357
|
+
className: "lm-label",
|
|
6358
|
+
children: t("skillRoot")
|
|
6359
|
+
}),
|
|
6360
|
+
editSkill !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6361
|
+
className: "lm-input",
|
|
6362
|
+
value: t(editSkill.root === "project" ? "skillRootProject" : "skillRootUser"),
|
|
6363
|
+
disabled: true
|
|
6364
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
6365
|
+
className: "lm-input",
|
|
6366
|
+
value: skillRoot,
|
|
6367
|
+
onChange: (e) => setSkillRoot(e.target.value === "project" ? "project" : "user"),
|
|
6368
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6369
|
+
value: "user",
|
|
6370
|
+
children: t("skillRootUser")
|
|
6371
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6372
|
+
value: "project",
|
|
6373
|
+
children: t("skillRootProject")
|
|
6374
|
+
})]
|
|
6375
|
+
}),
|
|
6376
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6377
|
+
className: "lm-hint",
|
|
6378
|
+
children: skillRoot === "project" || editSkill?.root === "project" ? t("skillRootHintProject") : t("skillRootHintUser")
|
|
6379
|
+
})
|
|
6380
|
+
]
|
|
6230
6381
|
}),
|
|
6231
6382
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6232
6383
|
className: "lm-field",
|
|
6233
|
-
children: [
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
}),
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
]
|
|
6271
|
-
})] }),
|
|
6272
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6273
|
-
className: "lm-field",
|
|
6274
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6275
|
-
className: "lm-label",
|
|
6276
|
-
children: t("timeout")
|
|
6277
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6278
|
-
className: "lm-input",
|
|
6279
|
-
value: timeoutSec,
|
|
6280
|
-
placeholder: "60",
|
|
6281
|
-
onChange: (e) => setTimeoutSec(e.target.value)
|
|
6282
|
-
})]
|
|
6283
|
-
}),
|
|
6284
|
-
renderActions(() => void submitMcp())
|
|
6285
|
-
]
|
|
6286
|
-
})
|
|
6287
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6288
|
-
className: "lm-block",
|
|
6289
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6290
|
-
className: "lm-form",
|
|
6291
|
-
children: [
|
|
6292
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6293
|
-
className: "lm-field",
|
|
6294
|
-
children: [
|
|
6295
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6296
|
-
className: "lm-label",
|
|
6297
|
-
children: t("skillRoot")
|
|
6298
|
-
}),
|
|
6299
|
-
editSkill !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6300
|
-
className: "lm-input",
|
|
6301
|
-
value: t(editSkill.root === "project" ? "skillRootProject" : "skillRootUser"),
|
|
6302
|
-
disabled: true
|
|
6303
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
6304
|
-
className: "lm-input",
|
|
6305
|
-
value: skillRoot,
|
|
6306
|
-
onChange: (e) => setSkillRoot(e.target.value === "project" ? "project" : "user"),
|
|
6307
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6308
|
-
value: "user",
|
|
6309
|
-
children: t("skillRootUser")
|
|
6310
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
6311
|
-
value: "project",
|
|
6312
|
-
children: t("skillRootProject")
|
|
6313
|
-
})]
|
|
6314
|
-
}),
|
|
6315
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6316
|
-
className: "lm-hint",
|
|
6317
|
-
children: skillRoot === "project" || editSkill?.root === "project" ? t("skillRootHintProject") : t("skillRootHintUser")
|
|
6318
|
-
})
|
|
6319
|
-
]
|
|
6320
|
-
}),
|
|
6321
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6322
|
-
className: "lm-field",
|
|
6323
|
-
children: [
|
|
6324
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6325
|
-
className: "lm-label",
|
|
6326
|
-
children: t("skillDirPath")
|
|
6327
|
-
}),
|
|
6328
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6329
|
-
className: "lm-input",
|
|
6330
|
-
value: skillDir,
|
|
6331
|
-
onChange: (e) => setSkillDir(e.target.value)
|
|
6332
|
-
}),
|
|
6333
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6334
|
-
className: "lm-hint",
|
|
6335
|
-
children: t("skillDirHint")
|
|
6336
|
-
})
|
|
6337
|
-
]
|
|
6338
|
-
}),
|
|
6339
|
-
editSkill === void 0 && skillRoot === "project" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6340
|
-
className: "lm-field",
|
|
6341
|
-
children: [
|
|
6342
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6343
|
-
className: "lm-label",
|
|
6344
|
-
children: t("skillProjectPath")
|
|
6345
|
-
}),
|
|
6346
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6347
|
-
className: "lm-input",
|
|
6348
|
-
value: projectPath,
|
|
6349
|
-
onChange: (e) => setProjectPath(e.target.value)
|
|
6350
|
-
}),
|
|
6351
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6352
|
-
className: "lm-hint",
|
|
6353
|
-
children: t("skillProjectPathHint")
|
|
6354
|
-
})
|
|
6355
|
-
]
|
|
6356
|
-
}),
|
|
6357
|
-
renderActions(() => void submitSkill())
|
|
6358
|
-
]
|
|
6384
|
+
children: [
|
|
6385
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6386
|
+
className: "lm-label",
|
|
6387
|
+
children: t("skillDirPath")
|
|
6388
|
+
}),
|
|
6389
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6390
|
+
className: "lm-input",
|
|
6391
|
+
value: skillDir,
|
|
6392
|
+
onChange: (e) => setSkillDir(e.target.value)
|
|
6393
|
+
}),
|
|
6394
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6395
|
+
className: "lm-hint",
|
|
6396
|
+
children: t("skillDirHint")
|
|
6397
|
+
})
|
|
6398
|
+
]
|
|
6399
|
+
}),
|
|
6400
|
+
editSkill === void 0 && skillRoot === "project" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6401
|
+
className: "lm-field",
|
|
6402
|
+
children: [
|
|
6403
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6404
|
+
className: "lm-label",
|
|
6405
|
+
children: t("skillProjectPath")
|
|
6406
|
+
}),
|
|
6407
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6408
|
+
className: "lm-input",
|
|
6409
|
+
value: projectPath,
|
|
6410
|
+
onChange: (e) => setProjectPath(e.target.value)
|
|
6411
|
+
}),
|
|
6412
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6413
|
+
className: "lm-hint",
|
|
6414
|
+
children: t("skillProjectPathHint")
|
|
6415
|
+
})
|
|
6416
|
+
]
|
|
6417
|
+
}),
|
|
6418
|
+
renderActions(() => void submitSkill())
|
|
6419
|
+
]
|
|
6420
|
+
})
|
|
6359
6421
|
})
|
|
6360
|
-
|
|
6422
|
+
]
|
|
6361
6423
|
})
|
|
6362
6424
|
]
|
|
6363
6425
|
})
|
|
@@ -6504,15 +6566,6 @@ function splitSkillGroups(skills) {
|
|
|
6504
6566
|
globalSkills
|
|
6505
6567
|
};
|
|
6506
6568
|
}
|
|
6507
|
-
/**
|
|
6508
|
-
* The sub-tab the Skills panel actually shows: the requested one, unless it is
|
|
6509
|
-
* 预设技能 while no preset ships skills. That tab does not exist then, and a
|
|
6510
|
-
* selection left on it must not survive — deployed presets are re-scanned on
|
|
6511
|
-
* every refresh, so the tab can disappear under the operator.
|
|
6512
|
-
*/
|
|
6513
|
-
function resolveSkillTab(selected, groups) {
|
|
6514
|
-
return selected === "preset" && groups.presetSkills.length === 0 ? "global" : selected;
|
|
6515
|
-
}
|
|
6516
6569
|
/** Rows in one tier. Counts the *displayed* rows, not the whole catalog. */
|
|
6517
6570
|
function countByClass(rows, cls) {
|
|
6518
6571
|
return rows.reduce((n, row) => row.class === cls ? n + 1 : n, 0);
|
|
@@ -6615,6 +6668,8 @@ function canRevalidate(gate) {
|
|
|
6615
6668
|
* with flat skill rows carrying the same clickable class
|
|
6616
6669
|
* chip plus a directory tree / file preview
|
|
6617
6670
|
*/
|
|
6671
|
+
const chevronIcons = _deepseek_ai_dsh_client_ui_primitives;
|
|
6672
|
+
const IconTriangleRightFill = chevronIcons.IconTriangleRightFillMedium ?? chevronIcons.IconTriangleRightFill14;
|
|
6618
6673
|
const CLASS_KEYS = [
|
|
6619
6674
|
"resident",
|
|
6620
6675
|
"on-demand",
|
|
@@ -6637,11 +6692,20 @@ const CSS_ID = "capability-menu-section-css";
|
|
|
6637
6692
|
const CSS = `
|
|
6638
6693
|
.mc-section{display:flex;flex-direction:column;gap:12px;color:var(--dsw-alias-label-primary)}
|
|
6639
6694
|
.mc-heading{margin:0;font-size:18px;font-weight:600}
|
|
6695
|
+
.mc-heading-row{display:flex;align-items:baseline;gap:8px;min-width:0;flex-wrap:wrap}
|
|
6696
|
+
.mc-heading-meta{display:flex;align-items:baseline;gap:8px;min-width:0}
|
|
6697
|
+
.mc-feedback-link{margin-left:auto;flex:none;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:20px;white-space:nowrap;text-decoration:none}
|
|
6698
|
+
.mc-feedback-link:hover,.mc-feedback-link:focus-visible{color:#527a9c;text-decoration:underline;text-underline-offset:3px}
|
|
6699
|
+
.mc-feedback-link:focus-visible{outline:2px solid #527a9c;outline-offset:2px;border-radius:2px}
|
|
6700
|
+
body[data-ds-dark-theme] .mc-feedback-link:hover,body[data-ds-dark-theme] .mc-feedback-link:focus-visible{color:#96b6d1}
|
|
6701
|
+
body[data-ds-dark-theme] .mc-feedback-link:focus-visible{outline-color:#96b6d1}
|
|
6702
|
+
.mc-package-name{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px}
|
|
6640
6703
|
.mc-desc{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px}
|
|
6641
6704
|
/* 说明行右侧放只读文档入口:把它从头部的计数行挪出来,计数多(Tools 常驻 ·
|
|
6642
6705
|
167)时那一行不再因此折行。 */
|
|
6643
6706
|
.mc-desc-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
6644
6707
|
.mc-desc-row .mc-desc{flex:1 1 auto;min-width:0}
|
|
6708
|
+
.mc-version{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:20px;white-space:nowrap}
|
|
6645
6709
|
.mc-summary{display:flex;gap:12px;flex-wrap:wrap;justify-content:flex-end;align-items:center;padding-bottom:8px}
|
|
6646
6710
|
.mc-catalog-btn{border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;line-height:20px;padding:0 10px;cursor:pointer;white-space:nowrap}
|
|
6647
6711
|
.mc-catalog-btn:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -6738,7 +6802,7 @@ body[data-ds-dark-theme] .mc-count--disabled{color:#b8abad}
|
|
|
6738
6802
|
.mc-error p{margin:0}
|
|
6739
6803
|
.mc-error p.mc-error-hint{margin-top:8px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}
|
|
6740
6804
|
.mc-error-actions{display:flex;justify-content:flex-end;margin-top:10px}
|
|
6741
|
-
.mc-notice{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-secondary);font-size:13px}
|
|
6805
|
+
.mc-notice{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;color:var(--dsw-alias-label-secondary);font-size:13px}
|
|
6742
6806
|
.mc-skill{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden;background:var(--dsw-alias-bg-layer-1)}
|
|
6743
6807
|
.mc-skill-row{box-sizing:border-box;display:flex;align-items:center;gap:10px;width:100%;min-width:0;padding:10px 12px;background:0 0;border:0;color:inherit;font:inherit;text-align:left;cursor:pointer}
|
|
6744
6808
|
.mc-skill-row:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -6772,7 +6836,13 @@ body[data-ds-dark-theme] .mc-count--disabled{color:#b8abad}
|
|
|
6772
6836
|
.mc-preview-title{font-size:13px;line-height:20px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
|
|
6773
6837
|
.mc-preview-close{flex:none;padding:2px 8px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer}
|
|
6774
6838
|
.mc-preview-close:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
6775
|
-
.mc-preview-body{overflow:auto;flex:1 1 auto;min-height:0;padding:14px 16px;
|
|
6839
|
+
.mc-preview-body{overflow:auto;flex:1 1 auto;min-height:0;padding:14px 16px;color:var(--dsw-alias-label-primary)}
|
|
6840
|
+
.mc-preview-body>pre,.mc-preview-plain{margin:0;font-family:var(--dsw-font-markdown-code-block-font-family);font-size:12px;line-height:20px;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
6841
|
+
.mc-tool-description{padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--dsw-alias-border-l1)}
|
|
6842
|
+
.mc-frontmatter{width:100%;margin:0 0 20px;border-collapse:collapse;table-layout:fixed;font-size:13px;line-height:20px}
|
|
6843
|
+
.mc-frontmatter th,.mc-frontmatter td{padding:8px 10px;border-bottom:1px solid var(--dsw-alias-border-l1);vertical-align:top;text-align:left}
|
|
6844
|
+
.mc-frontmatter th{width:130px;font-weight:500;color:var(--dsw-alias-label-secondary)}
|
|
6845
|
+
.mc-frontmatter td{color:var(--dsw-alias-label-primary);overflow-wrap:anywhere;white-space:pre-wrap}
|
|
6776
6846
|
.mc-preview-hint{padding:16px;text-align:center;font-size:13px;color:var(--dsw-alias-label-tertiary)}
|
|
6777
6847
|
`;
|
|
6778
6848
|
if (typeof document !== "undefined" && document.querySelector(`style[data-css-id="${CSS_ID}"]`) === null) {
|
|
@@ -6781,6 +6851,78 @@ if (typeof document !== "undefined" && document.querySelector(`style[data-css-id
|
|
|
6781
6851
|
tag.textContent = CSS;
|
|
6782
6852
|
document.head.appendChild(tag);
|
|
6783
6853
|
}
|
|
6854
|
+
/** Reuse dsh's safe Markdown renderer in tool descriptions and skill files. */
|
|
6855
|
+
function MarkdownPreview(props) {
|
|
6856
|
+
const { text, t } = props;
|
|
6857
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
|
|
6858
|
+
text,
|
|
6859
|
+
labels: {
|
|
6860
|
+
code: {
|
|
6861
|
+
copyLabel: t("markdownCopy"),
|
|
6862
|
+
copiedLabel: t("markdownCopied"),
|
|
6863
|
+
toolbarLabels: {
|
|
6864
|
+
codeLabel: t("markdownCode"),
|
|
6865
|
+
wrapLabel: t("markdownWrap"),
|
|
6866
|
+
unwrapLabel: t("markdownUnwrap")
|
|
6867
|
+
}
|
|
6868
|
+
},
|
|
6869
|
+
footnotes: t("markdownFootnotes")
|
|
6870
|
+
}
|
|
6871
|
+
});
|
|
6872
|
+
}
|
|
6873
|
+
/** Parse the simple property lines shown by GitHub above a Markdown document. */
|
|
6874
|
+
function parseFrontmatterProperties(source) {
|
|
6875
|
+
const properties = [];
|
|
6876
|
+
for (const line of source.split(/\r?\n/)) {
|
|
6877
|
+
const field = /^([A-Za-z0-9_.-]+):(?:[ \t]*(.*))?$/.exec(line);
|
|
6878
|
+
if (field !== null) {
|
|
6879
|
+
properties.push({
|
|
6880
|
+
name: field[1],
|
|
6881
|
+
value: field[2] ?? ""
|
|
6882
|
+
});
|
|
6883
|
+
continue;
|
|
6884
|
+
}
|
|
6885
|
+
const continuation = /^\s+(.+)$/.exec(line);
|
|
6886
|
+
if (continuation !== null && properties.length > 0) {
|
|
6887
|
+
const last = properties[properties.length - 1];
|
|
6888
|
+
last.value = last.value.length === 0 ? continuation[1] : `${last.value}\n${continuation[1]}`;
|
|
6889
|
+
}
|
|
6890
|
+
}
|
|
6891
|
+
return properties.map((property) => ({
|
|
6892
|
+
...property,
|
|
6893
|
+
value: property.value.trimEnd()
|
|
6894
|
+
}));
|
|
6895
|
+
}
|
|
6896
|
+
/** Split YAML properties from the Markdown body. */
|
|
6897
|
+
function splitMarkdownFrontmatter(text) {
|
|
6898
|
+
const match = /^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/.exec(text);
|
|
6899
|
+
if (match === null) return { body: text };
|
|
6900
|
+
return {
|
|
6901
|
+
frontmatter: parseFrontmatterProperties(match[1] ?? ""),
|
|
6902
|
+
body: text.slice(match[0].length)
|
|
6903
|
+
};
|
|
6904
|
+
}
|
|
6905
|
+
function MarkdownFilePreview(props) {
|
|
6906
|
+
const { frontmatter, body } = splitMarkdownFrontmatter(props.text);
|
|
6907
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [frontmatter !== void 0 && frontmatter.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("table", {
|
|
6908
|
+
className: "mc-frontmatter",
|
|
6909
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: frontmatter.map((property) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
6910
|
+
scope: "row",
|
|
6911
|
+
children: property.name
|
|
6912
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: property.value })] }, property.name)) })
|
|
6913
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownPreview, {
|
|
6914
|
+
text: body,
|
|
6915
|
+
t: props.t
|
|
6916
|
+
})] });
|
|
6917
|
+
}
|
|
6918
|
+
/**
|
|
6919
|
+
* Which build of the plugin is on screen. Several rounds of "is my profile
|
|
6920
|
+
* running the version I just installed?" had to be answered by grepping
|
|
6921
|
+
* `node_modules`, because the panel said nothing about itself. The value is
|
|
6922
|
+
* inlined by `tsdown` (see `src/client/env.d.ts`).
|
|
6923
|
+
*/
|
|
6924
|
+
const PLUGIN_VERSION = "0.1.5";
|
|
6925
|
+
const PLUGIN_TITLE = `capability-menu v${PLUGIN_VERSION}`;
|
|
6784
6926
|
/**
|
|
6785
6927
|
* dsh's skill source labels, shown on rows this plugin cannot edit — so "why is
|
|
6786
6928
|
* there no 编辑 button" has a visible answer. Labels that name one directory are
|
|
@@ -6831,6 +6973,8 @@ function CapabilitySection(props) {
|
|
|
6831
6973
|
});
|
|
6832
6974
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
6833
6975
|
const [notice, setNotice] = (0, react.useState)(null);
|
|
6976
|
+
const [retryMcp, setRetryMcp] = (0, react.useState)(null);
|
|
6977
|
+
const queuedMcpRefresh = (0, react.useRef)(null);
|
|
6834
6978
|
const [openServers, setOpenServers] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
6835
6979
|
const [activeTab, setActiveTab] = (0, react.useState)("tools");
|
|
6836
6980
|
const reload = (0, react.useCallback)(async () => {
|
|
@@ -6866,6 +7010,7 @@ function CapabilitySection(props) {
|
|
|
6866
7010
|
const refreshCatalog = (0, react.useCallback)(async () => {
|
|
6867
7011
|
if (refreshing) return;
|
|
6868
7012
|
setRefreshing(true);
|
|
7013
|
+
setRetryMcp(null);
|
|
6869
7014
|
try {
|
|
6870
7015
|
if (remote !== void 0) unwrap(await remote.refresh(), "capabilityPolicy.refresh");
|
|
6871
7016
|
await reload();
|
|
@@ -6882,6 +7027,61 @@ function CapabilitySection(props) {
|
|
|
6882
7027
|
reload,
|
|
6883
7028
|
t
|
|
6884
7029
|
]);
|
|
7030
|
+
/**
|
|
7031
|
+
* A new MCP row is persisted before dsh applies it and registers its tools.
|
|
7032
|
+
* Wait for that asynchronous host reload instead of taking one snapshot too
|
|
7033
|
+
* early and requiring the operator to leave and reopen this settings page.
|
|
7034
|
+
*/
|
|
7035
|
+
const refreshRegisteredMcp = (0, react.useCallback)(async (serverName) => {
|
|
7036
|
+
if (refreshing) {
|
|
7037
|
+
queuedMcpRefresh.current = serverName;
|
|
7038
|
+
return;
|
|
7039
|
+
}
|
|
7040
|
+
if (remote === void 0) return;
|
|
7041
|
+
setRefreshing(true);
|
|
7042
|
+
setRetryMcp(null);
|
|
7043
|
+
try {
|
|
7044
|
+
unwrap(await remote.refresh(), "capabilityPolicy.refresh");
|
|
7045
|
+
const snapshot = await waitForMcpTools(remote, serverName, [
|
|
7046
|
+
250,
|
|
7047
|
+
500,
|
|
7048
|
+
750,
|
|
7049
|
+
1e3,
|
|
7050
|
+
1e3,
|
|
7051
|
+
1e3,
|
|
7052
|
+
1e3,
|
|
7053
|
+
1e3,
|
|
7054
|
+
1e3
|
|
7055
|
+
]);
|
|
7056
|
+
if (snapshot !== void 0) {
|
|
7057
|
+
setState({
|
|
7058
|
+
status: "ready",
|
|
7059
|
+
snapshot: rememberSnapshot(snapshot)
|
|
7060
|
+
});
|
|
7061
|
+
setNotice(null);
|
|
7062
|
+
setRetryMcp(null);
|
|
7063
|
+
} else {
|
|
7064
|
+
setNotice(t("mcpToolsPending", { name: serverName }));
|
|
7065
|
+
setRetryMcp(serverName);
|
|
7066
|
+
}
|
|
7067
|
+
} catch (e) {
|
|
7068
|
+
console.error("[capability-menu] MCP refresh failed:", e);
|
|
7069
|
+
setNotice(t("refreshFailed"));
|
|
7070
|
+
setRetryMcp(serverName);
|
|
7071
|
+
} finally {
|
|
7072
|
+
setRefreshing(false);
|
|
7073
|
+
}
|
|
7074
|
+
}, [
|
|
7075
|
+
refreshing,
|
|
7076
|
+
remote,
|
|
7077
|
+
t
|
|
7078
|
+
]);
|
|
7079
|
+
(0, react.useEffect)(() => {
|
|
7080
|
+
if (refreshing || queuedMcpRefresh.current === null) return;
|
|
7081
|
+
const serverName = queuedMcpRefresh.current;
|
|
7082
|
+
queuedMcpRefresh.current = null;
|
|
7083
|
+
refreshRegisteredMcp(serverName);
|
|
7084
|
+
}, [refreshing, refreshRegisteredMcp]);
|
|
6885
7085
|
const toggleServer = (0, react.useCallback)((server) => {
|
|
6886
7086
|
setOpenServers((prev) => {
|
|
6887
7087
|
const next = new Set(prev);
|
|
@@ -7048,9 +7248,15 @@ function CapabilitySection(props) {
|
|
|
7048
7248
|
})
|
|
7049
7249
|
]
|
|
7050
7250
|
}),
|
|
7051
|
-
notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7251
|
+
notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7052
7252
|
className: "mc-notice",
|
|
7053
|
-
children: notice
|
|
7253
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: notice }), retryMcp !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7254
|
+
type: "button",
|
|
7255
|
+
className: "mc-catalog-btn",
|
|
7256
|
+
disabled: refreshing,
|
|
7257
|
+
onClick: () => void refreshRegisteredMcp(retryMcp),
|
|
7258
|
+
children: t("retry")
|
|
7259
|
+
})]
|
|
7054
7260
|
}),
|
|
7055
7261
|
state.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadyBody, {
|
|
7056
7262
|
remote,
|
|
@@ -7063,13 +7269,14 @@ function CapabilitySection(props) {
|
|
|
7063
7269
|
onToggleServer: toggleServer,
|
|
7064
7270
|
onCycle: cycleClass,
|
|
7065
7271
|
onRefresh: () => void refreshCatalog(),
|
|
7272
|
+
onRefreshMcp: (serverName) => void refreshRegisteredMcp(serverName),
|
|
7066
7273
|
onNotice: setNotice
|
|
7067
7274
|
})
|
|
7068
7275
|
]
|
|
7069
7276
|
});
|
|
7070
7277
|
}
|
|
7071
7278
|
function ReadyBody(props) {
|
|
7072
|
-
const { remote, snapshot, openServers, busy, activeTab, t, onTabChange, onToggleServer, onCycle, onRefresh, onNotice } = props;
|
|
7279
|
+
const { remote, snapshot, openServers, busy, activeTab, t, onTabChange, onToggleServer, onCycle, onRefresh, onRefreshMcp, onNotice } = props;
|
|
7073
7280
|
/** Name filter, shared by both tabs: it narrows whichever list is shown. */
|
|
7074
7281
|
const [filter, setFilter] = (0, react.useState)("");
|
|
7075
7282
|
const nameFilter = compileNameFilter(filter);
|
|
@@ -7081,13 +7288,7 @@ function ReadyBody(props) {
|
|
|
7081
7288
|
const { servers, skills } = groupRows(shownRows);
|
|
7082
7289
|
const { presetSkills, presetGroups, projectSkills, globalSkills } = splitSkillGroups(skills);
|
|
7083
7290
|
const [skillTab, setSkillTab] = (0, react.useState)("global");
|
|
7084
|
-
const
|
|
7085
|
-
presetSkills,
|
|
7086
|
-
presetGroups,
|
|
7087
|
-
projectSkills,
|
|
7088
|
-
globalSkills
|
|
7089
|
-
});
|
|
7090
|
-
const statRows = activeTab === "tools" ? shownRows.filter((r) => r.kind === "tool") : activeSkillTab === "project" ? projectSkills : activeSkillTab === "preset" ? presetSkills : globalSkills;
|
|
7291
|
+
const statRows = activeTab === "tools" ? shownRows.filter((r) => r.kind === "tool") : skillTab === "project" ? projectSkills : skillTab === "preset" ? presetSkills : globalSkills;
|
|
7091
7292
|
const summary = CLASS_KEYS.map((cls) => ({
|
|
7092
7293
|
cls,
|
|
7093
7294
|
count: countByClass(statRows, cls)
|
|
@@ -7226,9 +7427,33 @@ function ReadyBody(props) {
|
|
|
7226
7427
|
}
|
|
7227
7428
|
}, [remote]);
|
|
7228
7429
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
7229
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
7230
|
-
className: "mc-heading",
|
|
7231
|
-
children:
|
|
7430
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7431
|
+
className: "mc-heading-row",
|
|
7432
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7433
|
+
className: "mc-heading-meta",
|
|
7434
|
+
children: [
|
|
7435
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
7436
|
+
className: "mc-heading",
|
|
7437
|
+
children: t("title")
|
|
7438
|
+
}),
|
|
7439
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7440
|
+
className: "mc-package-name",
|
|
7441
|
+
children: t("packageName")
|
|
7442
|
+
}),
|
|
7443
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7444
|
+
className: "mc-version",
|
|
7445
|
+
title: PLUGIN_TITLE,
|
|
7446
|
+
children: ["v", PLUGIN_VERSION]
|
|
7447
|
+
})
|
|
7448
|
+
]
|
|
7449
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
7450
|
+
className: "mc-feedback-link",
|
|
7451
|
+
href: "https://github.com/PKUfudawei/dsh-capability-menu",
|
|
7452
|
+
target: "_blank",
|
|
7453
|
+
rel: "noopener noreferrer",
|
|
7454
|
+
"aria-label": t("feedback"),
|
|
7455
|
+
children: t("feedback")
|
|
7456
|
+
})]
|
|
7232
7457
|
}),
|
|
7233
7458
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7234
7459
|
className: "mc-desc-row",
|
|
@@ -7327,7 +7552,7 @@ function ReadyBody(props) {
|
|
|
7327
7552
|
}
|
|
7328
7553
|
},
|
|
7329
7554
|
children: [
|
|
7330
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
7555
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTriangleRightFill, {
|
|
7331
7556
|
size: 12,
|
|
7332
7557
|
className: `mc-chevron${open ? " mc-chevron--open" : ""}`
|
|
7333
7558
|
}),
|
|
@@ -7422,7 +7647,7 @@ function ReadyBody(props) {
|
|
|
7422
7647
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7423
7648
|
role: "tabpanel",
|
|
7424
7649
|
hidden: activeTab !== "skills",
|
|
7425
|
-
className:
|
|
7650
|
+
className: `mc-panel${skills.length > 0 ? " mc-panel--tight" : ""}`,
|
|
7426
7651
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7427
7652
|
className: "mc-panel-inner",
|
|
7428
7653
|
children: skills.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -7439,8 +7664,8 @@ function ReadyBody(props) {
|
|
|
7439
7664
|
type: "button",
|
|
7440
7665
|
role: "tab",
|
|
7441
7666
|
className: "mc-tab",
|
|
7442
|
-
"aria-selected":
|
|
7443
|
-
"data-active":
|
|
7667
|
+
"aria-selected": skillTab === "global",
|
|
7668
|
+
"data-active": skillTab === "global" ? "true" : void 0,
|
|
7444
7669
|
onClick: () => setSkillTab("global"),
|
|
7445
7670
|
children: t("globalSkills")
|
|
7446
7671
|
}),
|
|
@@ -7448,23 +7673,23 @@ function ReadyBody(props) {
|
|
|
7448
7673
|
type: "button",
|
|
7449
7674
|
role: "tab",
|
|
7450
7675
|
className: "mc-tab",
|
|
7451
|
-
"aria-selected":
|
|
7452
|
-
"data-active":
|
|
7676
|
+
"aria-selected": skillTab === "project",
|
|
7677
|
+
"data-active": skillTab === "project" ? "true" : void 0,
|
|
7453
7678
|
onClick: () => setSkillTab("project"),
|
|
7454
7679
|
children: t("projectSkills")
|
|
7455
7680
|
}),
|
|
7456
|
-
|
|
7681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7457
7682
|
type: "button",
|
|
7458
7683
|
role: "tab",
|
|
7459
7684
|
className: "mc-tab",
|
|
7460
|
-
"aria-selected":
|
|
7461
|
-
"data-active":
|
|
7685
|
+
"aria-selected": skillTab === "preset",
|
|
7686
|
+
"data-active": skillTab === "preset" ? "true" : void 0,
|
|
7462
7687
|
onClick: () => setSkillTab("preset"),
|
|
7463
7688
|
children: t("presetSkills")
|
|
7464
7689
|
})
|
|
7465
7690
|
]
|
|
7466
7691
|
})
|
|
7467
|
-
}),
|
|
7692
|
+
}), skillTab === "global" ? globalSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
7468
7693
|
skills: globalSkills,
|
|
7469
7694
|
remote,
|
|
7470
7695
|
busy,
|
|
@@ -7476,7 +7701,7 @@ function ReadyBody(props) {
|
|
|
7476
7701
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7477
7702
|
className: "mc-empty",
|
|
7478
7703
|
children: t("emptyGlobalSkills")
|
|
7479
|
-
}) :
|
|
7704
|
+
}) : skillTab === "project" ? projectSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
7480
7705
|
skills: projectSkills,
|
|
7481
7706
|
remote,
|
|
7482
7707
|
busy,
|
|
@@ -7488,7 +7713,7 @@ function ReadyBody(props) {
|
|
|
7488
7713
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7489
7714
|
className: "mc-empty",
|
|
7490
7715
|
children: t("emptyProjectSkills")
|
|
7491
|
-
}) : presetGroups.map(([preset, group]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7716
|
+
}) : presetGroups.length > 0 ? presetGroups.map(([preset, group]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7492
7717
|
className: "mc-skill-group",
|
|
7493
7718
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7494
7719
|
className: "mc-skill-group-title",
|
|
@@ -7503,7 +7728,10 @@ function ReadyBody(props) {
|
|
|
7503
7728
|
onEditSkill: openSkillEdit,
|
|
7504
7729
|
onAdoptSkill: adoptSkill
|
|
7505
7730
|
})]
|
|
7506
|
-
}, preset))
|
|
7731
|
+
}, preset)) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7732
|
+
className: "mc-empty",
|
|
7733
|
+
children: t("emptyPresetSkills")
|
|
7734
|
+
})] })
|
|
7507
7735
|
})
|
|
7508
7736
|
}),
|
|
7509
7737
|
toolDetail !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -7533,16 +7761,24 @@ function ReadyBody(props) {
|
|
|
7533
7761
|
className: "mc-preview-hint",
|
|
7534
7762
|
children: toolDetail.message
|
|
7535
7763
|
}),
|
|
7536
|
-
toolDetail.status === "ready" && toolDetail.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7764
|
+
toolDetail.status === "ready" && toolDetail.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7537
7765
|
className: "mc-preview-body",
|
|
7538
|
-
children:
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7766
|
+
children: [toolDetail.detail.description.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7767
|
+
className: "mc-tool-description",
|
|
7768
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownPreview, {
|
|
7769
|
+
text: toolDetail.detail.description,
|
|
7770
|
+
t
|
|
7771
|
+
})
|
|
7772
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
7773
|
+
className: "mc-preview-plain",
|
|
7774
|
+
children: JSON.stringify({
|
|
7775
|
+
type: "function",
|
|
7776
|
+
function: {
|
|
7777
|
+
name: toolDetail.detail.name,
|
|
7778
|
+
parameters: toolDetail.detail.parameters
|
|
7779
|
+
}
|
|
7780
|
+
}, null, 2)
|
|
7781
|
+
})]
|
|
7546
7782
|
})
|
|
7547
7783
|
]
|
|
7548
7784
|
})
|
|
@@ -7558,8 +7794,9 @@ function ReadyBody(props) {
|
|
|
7558
7794
|
setEditMcp(void 0);
|
|
7559
7795
|
setEditSkill(void 0);
|
|
7560
7796
|
},
|
|
7561
|
-
onChanged: (notice) => {
|
|
7562
|
-
|
|
7797
|
+
onChanged: (notice, refreshMcpServer) => {
|
|
7798
|
+
if (refreshMcpServer !== void 0) onRefreshMcp(refreshMcpServer);
|
|
7799
|
+
else onRefresh();
|
|
7563
7800
|
if (notice !== void 0) onNotice(notice);
|
|
7564
7801
|
}
|
|
7565
7802
|
}),
|
|
@@ -7764,7 +8001,7 @@ function SkillList(props) {
|
|
|
7764
8001
|
}),
|
|
7765
8002
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7766
8003
|
className: "mc-tree-icon",
|
|
7767
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
8004
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTriangleRightFill, {
|
|
7768
8005
|
size: 10,
|
|
7769
8006
|
className: `mc-chevron${open ? " mc-chevron--open" : ""}`
|
|
7770
8007
|
})
|
|
@@ -7828,7 +8065,7 @@ function SkillList(props) {
|
|
|
7828
8065
|
}
|
|
7829
8066
|
},
|
|
7830
8067
|
children: [
|
|
7831
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
8068
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTriangleRightFill, {
|
|
7832
8069
|
size: 12,
|
|
7833
8070
|
className: `mc-chevron${open ? " mc-chevron--open" : ""}`
|
|
7834
8071
|
}),
|
|
@@ -7960,9 +8197,15 @@ function SkillList(props) {
|
|
|
7960
8197
|
onClick: () => setPreview(null),
|
|
7961
8198
|
children: t("previewClose")
|
|
7962
8199
|
})]
|
|
7963
|
-
}), preview.content !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
8200
|
+
}), preview.content !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7964
8201
|
className: "mc-preview-body",
|
|
7965
|
-
children: preview.
|
|
8202
|
+
children: /\.md$/i.test(preview.relPath) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownFilePreview, {
|
|
8203
|
+
text: preview.content,
|
|
8204
|
+
t
|
|
8205
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
8206
|
+
className: "mc-preview-plain",
|
|
8207
|
+
children: preview.content
|
|
8208
|
+
})
|
|
7966
8209
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7967
8210
|
className: "mc-preview-hint",
|
|
7968
8211
|
children: preview.error ?? "…"
|
|
@@ -7989,6 +8232,8 @@ async function apply(ctx) {
|
|
|
7989
8232
|
const zh = {
|
|
7990
8233
|
nav: "能力菜单",
|
|
7991
8234
|
title: "能力菜单",
|
|
8235
|
+
packageName: "capability-menu",
|
|
8236
|
+
feedback: "反馈 ↗",
|
|
7992
8237
|
desc: "管理工具与技能的 常驻 / 按需 / 禁用 三档分类。",
|
|
7993
8238
|
resident: "Resident(常驻上下文)",
|
|
7994
8239
|
"on-demand": "On-demand(按需发现)",
|
|
@@ -8004,6 +8249,7 @@ async function apply(ctx) {
|
|
|
8004
8249
|
presetSkills: "预设技能",
|
|
8005
8250
|
emptyGlobalSkills: "暂无全局技能",
|
|
8006
8251
|
emptyProjectSkills: "暂无项目技能",
|
|
8252
|
+
emptyPresetSkills: "暂无预设技能",
|
|
8007
8253
|
filterByName: "按名字、分组或正则过滤…",
|
|
8008
8254
|
filterHint: "忽略大小写。匹配工具/技能名、MCP server、技能来源标签与预设 id;也可以直接写正则,例如 cordis|ptc 或 /^mcp__dbx/。",
|
|
8009
8255
|
filterNoMatch: "没有匹配的能力(清空过滤框可恢复完整列表)",
|
|
@@ -8016,9 +8262,16 @@ async function apply(ctx) {
|
|
|
8016
8262
|
cycleHint: "点击标签切换分类(按需 → 禁用 → 常驻)",
|
|
8017
8263
|
notPreviewable: "该文件不是可预览的文本文件",
|
|
8018
8264
|
previewClose: "关闭",
|
|
8265
|
+
markdownCode: "代码",
|
|
8266
|
+
markdownWrap: "自动换行",
|
|
8267
|
+
markdownUnwrap: "不换行",
|
|
8268
|
+
markdownCopy: "复制",
|
|
8269
|
+
markdownCopied: "已复制",
|
|
8270
|
+
markdownFootnotes: "脚注",
|
|
8019
8271
|
detailNotFound: "未找到该工具的详情",
|
|
8020
8272
|
cycleOverridden: "分类未生效:{count} 个能力被更高优先级规则覆盖(如通配规则),可移除对应通配规则后重试",
|
|
8021
8273
|
refreshFailed: "刷新失败,请查看日志",
|
|
8274
|
+
mcpToolsPending: "已注册「{name}」,但暂未加载出工具。请检查连接和认证后点刷新。",
|
|
8022
8275
|
retry: "重试",
|
|
8023
8276
|
carrierFailureHint: "请求未到达服务端:浏览器与 dsh 之间的连接已断开(Failed to fetch 属传输层失败,服务端方法未执行)。若刚重启过 dsh web,请先硬刷新页面(Ctrl/Cmd+Shift+R)再重试。",
|
|
8024
8277
|
registerCapability: "注册能力",
|
|
@@ -8054,20 +8307,22 @@ async function apply(ctx) {
|
|
|
8054
8307
|
skillSourceHint: "该技能由 dsh 从其它根发现,不在本插件管理的技能目录里,因此没有「编辑」。",
|
|
8055
8308
|
skillFromPreset: "来自预设 {preset}",
|
|
8056
8309
|
skillFromPresetHint: "该技能随 agent preset 分发,只对挂载了该预设的会话可见;不能纳入管理(那会把它软链进全局技能根,对所有会话生效)。",
|
|
8310
|
+
githubImporting: "正在从 GitHub 获取并校验 Skill,完成后会自动注册…",
|
|
8311
|
+
importing: "导入中…",
|
|
8057
8312
|
skillUnmanaged: "未纳入管理",
|
|
8058
8313
|
sourceCustom: "自定义技能目录",
|
|
8059
8314
|
sourceBundled: "随 dsh 预置",
|
|
8060
8315
|
adoptSkill: "纳入管理",
|
|
8061
8316
|
adoptSkillHint: "把它软链进 dsh 的技能根目录(默认 ~/.dsh/skills),内容不动;之后就能编辑与移除了。",
|
|
8062
8317
|
adoptSkillTitle: "纳入管理「{name}」?",
|
|
8063
|
-
skillDirHint: "
|
|
8318
|
+
skillDirHint: "支持本机目录或公开 GitHub HTTPS 技能链接。GitHub 导入会校验 SKILL.md,并只保留对应技能目录;运行 dsh 的机器需安装 Git。技能名取自 SKILL.md。",
|
|
8064
8319
|
serverName: "serverName",
|
|
8065
|
-
serverNameImmutable: "
|
|
8320
|
+
serverNameImmutable: "名称用于工具 ID 和权限规则,注册后不可更改。",
|
|
8066
8321
|
transport: "传输方式",
|
|
8067
8322
|
transportStdio: "stdio(本地子进程)",
|
|
8068
8323
|
transportHttp: "streamable-http(HTTP MCP 端点)",
|
|
8069
8324
|
transportHintStdio: "由客户端将该 MCP server 作为子进程启动,JSON-RPC 报文经标准输入 / 输出交换。",
|
|
8070
|
-
transportHintHttp: "
|
|
8325
|
+
transportHintHttp: "客户端通过支持 POST/GET 的 MCP 端点连接。",
|
|
8071
8326
|
command: "命令",
|
|
8072
8327
|
args: "参数(空格分隔)",
|
|
8073
8328
|
cwd: "工作目录",
|
|
@@ -8087,6 +8342,8 @@ async function apply(ctx) {
|
|
|
8087
8342
|
const en = {
|
|
8088
8343
|
nav: "Capability Management",
|
|
8089
8344
|
title: "Capability Management",
|
|
8345
|
+
packageName: "capability-menu",
|
|
8346
|
+
feedback: "Feedback ↗",
|
|
8090
8347
|
desc: "Manage the Resident / On-demand / Disabled classification of tools and skills.",
|
|
8091
8348
|
resident: "Resident",
|
|
8092
8349
|
"on-demand": "On-demand",
|
|
@@ -8102,6 +8359,7 @@ async function apply(ctx) {
|
|
|
8102
8359
|
presetSkills: "Preset skills",
|
|
8103
8360
|
emptyGlobalSkills: "No global skills",
|
|
8104
8361
|
emptyProjectSkills: "No project skills",
|
|
8362
|
+
emptyPresetSkills: "No preset skills",
|
|
8105
8363
|
filterByName: "Filter by name, group, or regex…",
|
|
8106
8364
|
filterHint: "Case-insensitive. Matches tool/skill names, MCP servers, skill source labels and preset ids; a regular expression works too, e.g. cordis|ptc or /^mcp__dbx/.",
|
|
8107
8365
|
filterNoMatch: "No capability matches (clear the filter to see the full list)",
|
|
@@ -8114,9 +8372,16 @@ async function apply(ctx) {
|
|
|
8114
8372
|
cycleHint: "Click a tag to cycle its classification (On-demand → Disabled → Resident)",
|
|
8115
8373
|
notPreviewable: "This file is not a previewable text file",
|
|
8116
8374
|
previewClose: "Close",
|
|
8375
|
+
markdownCode: "Code",
|
|
8376
|
+
markdownWrap: "Wrap",
|
|
8377
|
+
markdownUnwrap: "Unwrap",
|
|
8378
|
+
markdownCopy: "Copy",
|
|
8379
|
+
markdownCopied: "Copied",
|
|
8380
|
+
markdownFootnotes: "Footnotes",
|
|
8117
8381
|
detailNotFound: "Tool detail not found",
|
|
8118
8382
|
cycleOverridden: "Classification not applied: {count} capability(ies) overridden by a higher-priority rule (e.g. a wildcard). Remove the matching wildcard rule and retry.",
|
|
8119
8383
|
refreshFailed: "Refresh failed; see the log",
|
|
8384
|
+
mcpToolsPending: "\"{name}\" is registered, but its tools have not loaded yet. Check its connection and authentication, then refresh.",
|
|
8120
8385
|
retry: "Retry",
|
|
8121
8386
|
carrierFailureHint: "The request never reached the server: the browser connection to dsh is broken (\"Failed to fetch\" is a transport failure, so no server method ran). If dsh web was just restarted, hard-refresh the page (Ctrl/Cmd+Shift+R) and retry.",
|
|
8122
8387
|
registerCapability: "Register capability",
|
|
@@ -8152,20 +8417,22 @@ async function apply(ctx) {
|
|
|
8152
8417
|
skillSourceHint: "dsh found this skill in another root, not in a skill directory this plugin manages, so there is no Edit button.",
|
|
8153
8418
|
skillFromPreset: "From preset {preset}",
|
|
8154
8419
|
skillFromPresetHint: "This skill ships with an agent preset and is visible only to sessions that mount it. It cannot be adopted (adopting would link it into the global skill root, making it apply to every session).",
|
|
8420
|
+
githubImporting: "Fetching and validating the Skill from GitHub… It will register automatically when complete.",
|
|
8421
|
+
importing: "Importing…",
|
|
8155
8422
|
skillUnmanaged: "Not managed here",
|
|
8156
8423
|
sourceCustom: "custom skill dirs",
|
|
8157
8424
|
sourceBundled: "bundled with dsh",
|
|
8158
8425
|
adoptSkill: "Adopt",
|
|
8159
8426
|
adoptSkillHint: "Link it into dsh's skill root (default ~/.dsh/skills); the content is untouched, and it becomes editable and removable.",
|
|
8160
8427
|
adoptSkillTitle: "Adopt \"{name}\"?",
|
|
8161
|
-
skillDirHint: "
|
|
8428
|
+
skillDirHint: "Enter a local directory or a public GitHub HTTPS skill URL. Imports validate SKILL.md and keep only the selected skill directory. Git must be installed on the machine running dsh. The skill name comes from SKILL.md.",
|
|
8162
8429
|
serverName: "serverName",
|
|
8163
|
-
serverNameImmutable: "
|
|
8430
|
+
serverNameImmutable: "The name is locked after registration because tool IDs and permission rules use it.",
|
|
8164
8431
|
transport: "Transport",
|
|
8165
8432
|
transportStdio: "stdio (local subprocess)",
|
|
8166
8433
|
transportHttp: "streamable-http (HTTP MCP endpoint)",
|
|
8167
8434
|
transportHintStdio: "The client launches the MCP server as a subprocess and exchanges JSON-RPC messages over its standard input and output.",
|
|
8168
|
-
transportHintHttp: "
|
|
8435
|
+
transportHintHttp: "Connect through the MCP endpoint URL (supports POST and GET).",
|
|
8169
8436
|
command: "Command",
|
|
8170
8437
|
args: "Args (space separated)",
|
|
8171
8438
|
cwd: "Working directory",
|
|
@@ -8195,6 +8462,7 @@ async function apply(ctx) {
|
|
|
8195
8462
|
console.error("[capability-menu] $mount failed:", error);
|
|
8196
8463
|
}
|
|
8197
8464
|
const t = ctx.locale.bind(NS);
|
|
8465
|
+
installSettingsNavIcon(ctx, () => t("nav"));
|
|
8198
8466
|
const remote = () => {
|
|
8199
8467
|
try {
|
|
8200
8468
|
return ctx.get("remote.capabilityPolicy");
|