@daweifu/capability-menu 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +217 -0
- package/README.md +104 -61
- package/cordis.patch.yml +31 -31
- package/lib/client.d.ts +33 -7
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +315 -97
- package/lib/index.js +2 -2
- package/lib/invoke.js +68 -96
- package/lib/invoke.js.map +1 -1
- package/lib/policy.js +224 -80
- package/lib/policy.js.map +1 -1
- package/lib/registry.js +183 -143
- package/lib/registry.js.map +1 -1
- package/lib/search.js +17 -8
- package/lib/search.js.map +1 -1
- package/lib/server/remote.js +87 -4
- package/lib/server/remote.js.map +1 -1
- package/lib/types/index.d.ts +2 -2
- package/lib/types/invoke.d.ts +7 -13
- package/lib/types/invoke.d.ts.map +1 -1
- package/lib/types/policy.d.ts +78 -55
- package/lib/types/policy.d.ts.map +1 -1
- package/lib/types/registry.d.ts +60 -23
- package/lib/types/registry.d.ts.map +1 -1
- package/lib/types/search.d.ts.map +1 -1
- package/lib/types/server/remote.d.ts +24 -3
- package/lib/types/server/remote.d.ts.map +1 -1
- package/package.json +19 -23
- package/lib/invariant.js +0 -22
- package/lib/invariant.js.map +0 -1
- package/lib/types/invariant.d.ts +0 -16
- package/lib/types/invariant.d.ts.map +0 -1
package/lib/client.js
CHANGED
|
@@ -5195,10 +5195,11 @@ const capabilityRow$schema = object({
|
|
|
5195
5195
|
kind: union([literal("tool"), literal("skill")]).readonly(),
|
|
5196
5196
|
name: string().readonly(),
|
|
5197
5197
|
server: string().optional().readonly(),
|
|
5198
|
+
source: string().optional().readonly(),
|
|
5198
5199
|
class: union([
|
|
5199
|
-
literal("
|
|
5200
|
-
literal("
|
|
5201
|
-
literal("
|
|
5200
|
+
literal("resident"),
|
|
5201
|
+
literal("on-demand"),
|
|
5202
|
+
literal("disabled")
|
|
5202
5203
|
]).readonly(),
|
|
5203
5204
|
classLabel: string().optional().readonly(),
|
|
5204
5205
|
mandatory: boolean().readonly()
|
|
@@ -5207,6 +5208,14 @@ const skillFileEntry$schema = object({
|
|
|
5207
5208
|
name: string().readonly(),
|
|
5208
5209
|
type: union([literal("file"), literal("directory")]).readonly()
|
|
5209
5210
|
});
|
|
5211
|
+
const catalogDocs$schema = object({
|
|
5212
|
+
policyYaml: string().readonly(),
|
|
5213
|
+
catalog: object({
|
|
5214
|
+
path: string().readonly(),
|
|
5215
|
+
content: string().readonly()
|
|
5216
|
+
}).optional().readonly(),
|
|
5217
|
+
catalogMissing: union([literal("disabled"), literal("read-failed")]).optional().readonly()
|
|
5218
|
+
});
|
|
5210
5219
|
const toolDetail$schema = object({
|
|
5211
5220
|
id: string().readonly(),
|
|
5212
5221
|
kind: union([literal("tool"), literal("skill")]).readonly(),
|
|
@@ -5219,7 +5228,8 @@ const toolDetail$schema = object({
|
|
|
5219
5228
|
origin: object({
|
|
5220
5229
|
provider: string().readonly(),
|
|
5221
5230
|
serverName: string().optional().readonly(),
|
|
5222
|
-
path: string().optional().readonly()
|
|
5231
|
+
path: string().optional().readonly(),
|
|
5232
|
+
source: string().optional().readonly()
|
|
5223
5233
|
}).readonly(),
|
|
5224
5234
|
tags: array(string()).readonly(),
|
|
5225
5235
|
stats: object({
|
|
@@ -5247,7 +5257,7 @@ const TYPERT_REMOTE = {
|
|
|
5247
5257
|
},
|
|
5248
5258
|
sourceLocation: {
|
|
5249
5259
|
file: "src/server/remote.ts",
|
|
5250
|
-
line:
|
|
5260
|
+
line: 60,
|
|
5251
5261
|
column: 3
|
|
5252
5262
|
}
|
|
5253
5263
|
},
|
|
@@ -5274,7 +5284,7 @@ const TYPERT_REMOTE = {
|
|
|
5274
5284
|
},
|
|
5275
5285
|
sourceLocation: {
|
|
5276
5286
|
file: "src/server/remote.ts",
|
|
5277
|
-
line:
|
|
5287
|
+
line: 66,
|
|
5278
5288
|
column: 3
|
|
5279
5289
|
}
|
|
5280
5290
|
},
|
|
@@ -5292,7 +5302,7 @@ const TYPERT_REMOTE = {
|
|
|
5292
5302
|
},
|
|
5293
5303
|
sourceLocation: {
|
|
5294
5304
|
file: "src/server/remote.ts",
|
|
5295
|
-
line:
|
|
5305
|
+
line: 72,
|
|
5296
5306
|
column: 3
|
|
5297
5307
|
}
|
|
5298
5308
|
},
|
|
@@ -5329,7 +5339,7 @@ const TYPERT_REMOTE = {
|
|
|
5329
5339
|
},
|
|
5330
5340
|
sourceLocation: {
|
|
5331
5341
|
file: "src/server/remote.ts",
|
|
5332
|
-
line:
|
|
5342
|
+
line: 84,
|
|
5333
5343
|
column: 3
|
|
5334
5344
|
}
|
|
5335
5345
|
},
|
|
@@ -5365,7 +5375,7 @@ const TYPERT_REMOTE = {
|
|
|
5365
5375
|
},
|
|
5366
5376
|
sourceLocation: {
|
|
5367
5377
|
file: "src/server/remote.ts",
|
|
5368
|
-
line:
|
|
5378
|
+
line: 90,
|
|
5369
5379
|
column: 3
|
|
5370
5380
|
}
|
|
5371
5381
|
},
|
|
@@ -5392,7 +5402,25 @@ const TYPERT_REMOTE = {
|
|
|
5392
5402
|
},
|
|
5393
5403
|
sourceLocation: {
|
|
5394
5404
|
file: "src/server/remote.ts",
|
|
5395
|
-
line:
|
|
5405
|
+
line: 78,
|
|
5406
|
+
column: 3
|
|
5407
|
+
}
|
|
5408
|
+
},
|
|
5409
|
+
{
|
|
5410
|
+
id: "@daweifu/capability-menu#capabilityPolicy/getCatalogDocs",
|
|
5411
|
+
service: "capabilityPolicy",
|
|
5412
|
+
namespace: "capabilityPolicy",
|
|
5413
|
+
method: "getCatalogDocs",
|
|
5414
|
+
invocation: { kind: "direct" },
|
|
5415
|
+
parameters: [],
|
|
5416
|
+
result: {
|
|
5417
|
+
mode: "strict",
|
|
5418
|
+
typeSymbol: "@daweifu/capability-menu#CatalogDocs",
|
|
5419
|
+
schema: catalogDocs$schema
|
|
5420
|
+
},
|
|
5421
|
+
sourceLocation: {
|
|
5422
|
+
file: "src/server/remote.ts",
|
|
5423
|
+
line: 100,
|
|
5396
5424
|
column: 3
|
|
5397
5425
|
}
|
|
5398
5426
|
}
|
|
@@ -5414,29 +5442,39 @@ async function loadSnapshot(remote) {
|
|
|
5414
5442
|
/**
|
|
5415
5443
|
* ⚠️ VERIFIED AGAINST REAL rc.8 CLIENT API.
|
|
5416
5444
|
*
|
|
5417
|
-
* React section for the
|
|
5418
|
-
* pattern (see `dsh-client-ui-settings-plugins`): two tabs (
|
|
5445
|
+
* React section for the 能力管理 settings tab. Follows the real dsh client
|
|
5446
|
+
* pattern (see `dsh-client-ui-settings-plugins`): two tabs (工具 / Skills)
|
|
5419
5447
|
* under one heading, each listing capabilities with a clickable class chip.
|
|
5420
5448
|
*
|
|
5421
5449
|
* Layout:
|
|
5422
|
-
* - summary strip → per-class counts for the active tab
|
|
5423
|
-
*
|
|
5424
|
-
* -
|
|
5450
|
+
* - summary strip → per-class counts for the active tab (Skills tab counts
|
|
5451
|
+
* its active 全局/项目 sub-tab)
|
|
5452
|
+
* - tabs → Tools | Skills (plugins-tab chrome)
|
|
5453
|
+
* - Tools tab → grouped by server, collapsible disclosure rows; the
|
|
5425
5454
|
* per-class count chip and each tool's class chip are
|
|
5426
|
-
* clickable to cycle
|
|
5427
|
-
*
|
|
5428
|
-
*
|
|
5455
|
+
* clickable to cycle Resident → On-demand → Disabled.
|
|
5456
|
+
* Harness-native tools (no real MCP server) share the
|
|
5457
|
+
* reserved `built-in` group, shown as 「系统内置」.
|
|
5458
|
+
* - Skills tab → sub-tabs 全局技能 / 项目技能 (always visible), each
|
|
5459
|
+
* with flat skill rows carrying the same clickable class
|
|
5460
|
+
* chip plus a directory tree / file preview
|
|
5429
5461
|
*/
|
|
5430
5462
|
const CLASS_KEYS = [
|
|
5431
|
-
"
|
|
5432
|
-
"
|
|
5433
|
-
"
|
|
5463
|
+
"resident",
|
|
5464
|
+
"on-demand",
|
|
5465
|
+
"disabled"
|
|
5434
5466
|
];
|
|
5435
|
-
/** Click-cycle order
|
|
5467
|
+
/** Click-cycle order on machine values (displayed as On-demand → Disabled → Resident). */
|
|
5436
5468
|
const NEXT_CLASS = {
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5469
|
+
"on-demand": "disabled",
|
|
5470
|
+
disabled: "resident",
|
|
5471
|
+
resident: "on-demand"
|
|
5472
|
+
};
|
|
5473
|
+
/** i18n keys for the short display labels, keyed by the machine class value. */
|
|
5474
|
+
const CLASS_SHORT_KEYS = {
|
|
5475
|
+
resident: "residentShort",
|
|
5476
|
+
"on-demand": "onDemandShort",
|
|
5477
|
+
disabled: "disabledShort"
|
|
5440
5478
|
};
|
|
5441
5479
|
/** Scoped stylesheet: injected once at module scope, like every official bundle. */
|
|
5442
5480
|
const CSS_ID = "capability-menu-section-css";
|
|
@@ -5445,24 +5483,33 @@ const CSS = `
|
|
|
5445
5483
|
.mc-heading{margin:0;font-size:18px;font-weight:600}
|
|
5446
5484
|
.mc-desc{margin:0;color:var(--dsw-alias-label-tertiary);font-size:13px}
|
|
5447
5485
|
.mc-summary{display:flex;gap:12px;flex-wrap:wrap;justify-content:flex-end;align-items:center;padding-bottom:8px}
|
|
5486
|
+
.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}
|
|
5487
|
+
.mc-catalog-btn:hover{border-color:var(--dsw-alias-border-l3);background:var(--dsw-alias-interactive-bg-hover)}
|
|
5488
|
+
.mc-catalog-tabs{padding:8px 16px 0}
|
|
5489
|
+
.mc-catalog-path{padding:8px 16px 0;margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary);word-break:break-all}
|
|
5448
5490
|
.mc-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;line-height:20px;white-space:nowrap}
|
|
5449
|
-
/*
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
.mc-dot
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5491
|
+
/* 三态圆点:常驻=实心、按需=半实心、禁用=圆环+斜杠(禁行标志)。
|
|
5492
|
+
形状区分之外仍保留色盲友好(蓝-黄轴):冷蓝=常驻、暖琥珀=按需、中性灰=禁用。
|
|
5493
|
+
三个状态都用内联 SVG 做 mask 绘制,保证 10px 下也是矢量正圆(避免 CSS
|
|
5494
|
+
border-radius 小尺寸的方圆变形);禁用不用空心圆:在「禁用 · 0」这类计数旁,
|
|
5495
|
+
空心圆容易被误读成数字 0。 */
|
|
5496
|
+
.mc-dot{position:relative;width:13px;height:13px;border-radius:50%;flex:none;box-sizing:border-box}
|
|
5497
|
+
.mc-dot--resident{--mc-dot:#527a9c;background:var(--mc-dot);-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='5.3' fill='%23000'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='5.3' fill='%23000'/%3E%3C/svg%3E") center/contain no-repeat}
|
|
5498
|
+
.mc-dot--on-demand{--mc-dot:#a57c33;background:var(--mc-dot);-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='4.6' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3Cpath d='M1.4 6 A4.6 4.6 0 0 1 10.6 6 Z' fill='%23000'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='4.6' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3Cpath d='M1.4 6 A4.6 4.6 0 0 1 10.6 6 Z' fill='%23000'/%3E%3C/svg%3E") center/contain no-repeat}
|
|
5499
|
+
.mc-dot--disabled{--mc-dot:#7e7477;background:var(--mc-dot);-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='4.6' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3Cline x1='3' y1='9' x2='9' y2='3' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Ccircle cx='6' cy='6' r='4.6' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3Cline x1='3' y1='9' x2='9' y2='3' stroke='%23000' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") center/contain no-repeat}
|
|
5500
|
+
body[data-ds-dark-theme] .mc-dot--resident{--mc-dot:#96b6d1}
|
|
5501
|
+
body[data-ds-dark-theme] .mc-dot--on-demand{--mc-dot:#d4b26b}
|
|
5502
|
+
body[data-ds-dark-theme] .mc-dot--disabled{--mc-dot:#b8abad}
|
|
5458
5503
|
/* 同上色系(低饱和灰调):仅文字着色,不加背景,浅/深主题各一档。 */
|
|
5459
|
-
.mc-chip--
|
|
5460
|
-
.mc-chip--
|
|
5461
|
-
.mc-chip--
|
|
5462
|
-
body[data-ds-dark-theme] .mc-chip--
|
|
5463
|
-
body[data-ds-dark-theme] .mc-chip--
|
|
5464
|
-
body[data-ds-dark-theme] .mc-chip--
|
|
5504
|
+
.mc-chip--resident{color:#527a9c}
|
|
5505
|
+
.mc-chip--on-demand{color:#a57c33}
|
|
5506
|
+
.mc-chip--disabled{color:#7e7477}
|
|
5507
|
+
body[data-ds-dark-theme] .mc-chip--resident{color:#96b6d1}
|
|
5508
|
+
body[data-ds-dark-theme] .mc-chip--on-demand{color:#d4b26b}
|
|
5509
|
+
body[data-ds-dark-theme] .mc-chip--disabled{color:#b8abad}
|
|
5465
5510
|
.mc-tabs{border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;align-items:flex-end;justify-content:space-between;gap:22px}
|
|
5511
|
+
/* Skills sub-tab bar (全局技能/项目技能): same underline chrome, no right-side summary. */
|
|
5512
|
+
.mc-subtabs{border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;align-items:flex-end;gap:22px}
|
|
5466
5513
|
.mc-tab-group{display:flex;align-items:flex-end;gap:22px}
|
|
5467
5514
|
.mc-tab{color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;padding:7px 1px 9px;font-size:13px;line-height:20px;position:relative}
|
|
5468
5515
|
.mc-tab:hover,.mc-tab[data-active=true]{color:var(--dsw-alias-label-primary)}
|
|
@@ -5483,12 +5530,12 @@ body[data-ds-dark-theme] .mc-chip--blocked{color:#b8abad}
|
|
|
5483
5530
|
.mc-count{font-size:11px;line-height:18px;padding:0 8px;border-radius:999px;border:1px solid transparent;font-family:inherit;cursor:pointer;display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
|
|
5484
5531
|
.mc-count:hover{border-color:var(--dsw-alias-border-l3)}
|
|
5485
5532
|
.mc-count:disabled{cursor:default;opacity:.6}
|
|
5486
|
-
.mc-count--
|
|
5487
|
-
.mc-count--
|
|
5488
|
-
.mc-count--
|
|
5489
|
-
body[data-ds-dark-theme] .mc-count--
|
|
5490
|
-
body[data-ds-dark-theme] .mc-count--
|
|
5491
|
-
body[data-ds-dark-theme] .mc-count--
|
|
5533
|
+
.mc-count--resident{color:#527a9c}
|
|
5534
|
+
.mc-count--on-demand{color:#a57c33}
|
|
5535
|
+
.mc-count--disabled{color:#7e7477}
|
|
5536
|
+
body[data-ds-dark-theme] .mc-count--resident{color:#96b6d1}
|
|
5537
|
+
body[data-ds-dark-theme] .mc-count--on-demand{color:#d4b26b}
|
|
5538
|
+
body[data-ds-dark-theme] .mc-count--disabled{color:#b8abad}
|
|
5492
5539
|
.mc-tools{border-top:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base)}
|
|
5493
5540
|
.mc-tool{display:flex;align-items:center;gap:10px;padding:7px 12px 7px 26px;font-size:13px;line-height:20px;cursor:pointer}
|
|
5494
5541
|
.mc-tool:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -5501,6 +5548,7 @@ body[data-ds-dark-theme] .mc-count--blocked{color:#b8abad}
|
|
|
5501
5548
|
.mc-empty{padding:16px;text-align:center;font-size:13px;color:var(--dsw-alias-label-tertiary);border:1px dashed var(--dsw-alias-border-l2);border-radius:8px}
|
|
5502
5549
|
.mc-error{padding:12px;border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;color:var(--dsw-alias-state-error-primary);font-size:13px}
|
|
5503
5550
|
.mc-error pre{margin:8px 0 0;white-space:pre-wrap;word-break:break-all;font-size:11px;color:var(--dsw-alias-label-tertiary)}
|
|
5551
|
+
.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}
|
|
5504
5552
|
.mc-skill{border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden;background:var(--dsw-alias-bg-layer-1)}
|
|
5505
5553
|
.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}
|
|
5506
5554
|
.mc-skill-row:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
@@ -5520,7 +5568,7 @@ body[data-ds-dark-theme] .mc-count--blocked{color:#b8abad}
|
|
|
5520
5568
|
.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}
|
|
5521
5569
|
.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}
|
|
5522
5570
|
.mc-preview-close:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
5523
|
-
.mc-preview-body{overflow:auto;padding:14px 16px;font-family:var(--dsw-font-markdown-code-block-font-family);font-size:12px;line-height:20px;white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-primary)}
|
|
5571
|
+
.mc-preview-body{overflow:auto;flex:1 1 auto;min-height:0;padding:14px 16px;font-family:var(--dsw-font-markdown-code-block-font-family);font-size:12px;line-height:20px;white-space:pre-wrap;word-break:break-all;color:var(--dsw-alias-label-primary)}
|
|
5524
5572
|
.mc-preview-hint{padding:16px;text-align:center;font-size:13px;color:var(--dsw-alias-label-tertiary)}
|
|
5525
5573
|
`;
|
|
5526
5574
|
if (typeof document !== "undefined" && document.querySelector(`style[data-css-id="${CSS_ID}"]`) === null) {
|
|
@@ -5529,6 +5577,10 @@ if (typeof document !== "undefined" && document.querySelector(`style[data-css-id
|
|
|
5529
5577
|
tag.textContent = CSS;
|
|
5530
5578
|
document.head.appendChild(tag);
|
|
5531
5579
|
}
|
|
5580
|
+
/** The reserved server key grouping harness-native (non-MCP) tools. */
|
|
5581
|
+
const BUILT_IN_SERVER = "built-in";
|
|
5582
|
+
/** Skills whose source root lives inside the current project. */
|
|
5583
|
+
const PROJECT_SOURCES = /* @__PURE__ */ new Set(["project-dsh", "project-agents"]);
|
|
5532
5584
|
function groupRows(rows) {
|
|
5533
5585
|
const byServer = /* @__PURE__ */ new Map();
|
|
5534
5586
|
const skills = [];
|
|
@@ -5537,7 +5589,7 @@ function groupRows(rows) {
|
|
|
5537
5589
|
skills.push(row);
|
|
5538
5590
|
continue;
|
|
5539
5591
|
}
|
|
5540
|
-
const server = row.server ??
|
|
5592
|
+
const server = row.server ?? BUILT_IN_SERVER;
|
|
5541
5593
|
const list = byServer.get(server);
|
|
5542
5594
|
if (list === void 0) byServer.set(server, [row]);
|
|
5543
5595
|
else list.push(row);
|
|
@@ -5557,6 +5609,7 @@ function CapabilitySection(props) {
|
|
|
5557
5609
|
const { remote, t, mountError, remoteKeys } = props;
|
|
5558
5610
|
const [state, setState] = (0, react.useState)({ status: "loading" });
|
|
5559
5611
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
5612
|
+
const [notice, setNotice] = (0, react.useState)(null);
|
|
5560
5613
|
const [openServers, setOpenServers] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
5561
5614
|
const [activeTab, setActiveTab] = (0, react.useState)("tools");
|
|
5562
5615
|
const reload = (0, react.useCallback)(async () => {
|
|
@@ -5599,24 +5652,28 @@ function CapabilitySection(props) {
|
|
|
5599
5652
|
const key = kind === "skill" ? "skills" : "tools";
|
|
5600
5653
|
const set = config[key];
|
|
5601
5654
|
const lists = {
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5655
|
+
resident: [],
|
|
5656
|
+
"on-demand": [],
|
|
5657
|
+
disabled: []
|
|
5605
5658
|
};
|
|
5606
5659
|
for (const cls of CLASS_KEYS) {
|
|
5607
5660
|
const raw = set && typeof set === "object" && !Array.isArray(set) ? set[cls] : void 0;
|
|
5608
5661
|
lists[cls] = Array.isArray(raw) ? raw.filter((x) => typeof x === "string") : [];
|
|
5609
5662
|
}
|
|
5610
|
-
const from = ids.map((id) => state.status === "ready" ? state.snapshot.rows.find((r) => r.id === id)?.class : void 0).find((c) => c !== void 0) ?? "
|
|
5663
|
+
const from = ids.map((id) => state.status === "ready" ? state.snapshot.rows.find((r) => r.id === id)?.class : void 0).find((c) => c !== void 0) ?? "on-demand";
|
|
5611
5664
|
const to = NEXT_CLASS[from];
|
|
5612
5665
|
for (const cls of CLASS_KEYS) lists[cls] = lists[cls].filter((id) => !ids.includes(id));
|
|
5613
5666
|
lists[to] = [...lists[to], ...ids];
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5667
|
+
const nextLists = {};
|
|
5668
|
+
for (const cls of CLASS_KEYS) nextLists[cls] = lists[cls];
|
|
5669
|
+
await remote.updateConfig({ [key]: nextLists });
|
|
5670
|
+
const next = await loadSnapshot(remote);
|
|
5671
|
+
setState({
|
|
5672
|
+
status: "ready",
|
|
5673
|
+
snapshot: next
|
|
5674
|
+
});
|
|
5675
|
+
const overridden = ids.filter((id) => next.rows.find((r) => r.id === id)?.class !== to);
|
|
5676
|
+
setNotice(overridden.length > 0 ? t("cycleOverridden", { count: overridden.length }) : null);
|
|
5620
5677
|
} catch (e) {
|
|
5621
5678
|
setState({
|
|
5622
5679
|
status: "error",
|
|
@@ -5627,9 +5684,9 @@ function CapabilitySection(props) {
|
|
|
5627
5684
|
}
|
|
5628
5685
|
}, [
|
|
5629
5686
|
remote,
|
|
5630
|
-
reload,
|
|
5631
5687
|
busy,
|
|
5632
|
-
state
|
|
5688
|
+
state,
|
|
5689
|
+
t
|
|
5633
5690
|
]);
|
|
5634
5691
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5635
5692
|
className: "mc-section",
|
|
@@ -5642,6 +5699,10 @@ function CapabilitySection(props) {
|
|
|
5642
5699
|
className: "mc-error",
|
|
5643
5700
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: state.message }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", { children: `mountError=${String(mountError)}\nremoteKeys=${String(remoteKeys)}` })]
|
|
5644
5701
|
}),
|
|
5702
|
+
notice !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5703
|
+
className: "mc-notice",
|
|
5704
|
+
children: notice
|
|
5705
|
+
}),
|
|
5645
5706
|
state.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadyBody, {
|
|
5646
5707
|
remote,
|
|
5647
5708
|
snapshot: state.snapshot,
|
|
@@ -5659,7 +5720,10 @@ function CapabilitySection(props) {
|
|
|
5659
5720
|
function ReadyBody(props) {
|
|
5660
5721
|
const { remote, snapshot, openServers, busy, activeTab, t, onTabChange, onToggleServer, onCycle } = props;
|
|
5661
5722
|
const { servers, skills } = groupRows(snapshot.rows);
|
|
5662
|
-
const
|
|
5723
|
+
const projectSkills = skills.filter((skill) => PROJECT_SOURCES.has(skill.source ?? ""));
|
|
5724
|
+
const globalSkills = skills.filter((skill) => !PROJECT_SOURCES.has(skill.source ?? ""));
|
|
5725
|
+
const [skillTab, setSkillTab] = (0, react.useState)("global");
|
|
5726
|
+
const statRows = activeTab === "tools" ? snapshot.rows.filter((r) => r.kind === "tool") : skillTab === "project" ? projectSkills : globalSkills;
|
|
5663
5727
|
const summary = CLASS_KEYS.map((cls) => ({
|
|
5664
5728
|
cls,
|
|
5665
5729
|
count: countByClass(statRows, cls)
|
|
@@ -5691,6 +5755,25 @@ function ReadyBody(props) {
|
|
|
5691
5755
|
});
|
|
5692
5756
|
}
|
|
5693
5757
|
}, [remote, t]);
|
|
5758
|
+
/** 能力目录弹层状态:查看三档策略配置 + 按需能力目录文件。 */
|
|
5759
|
+
const [catalogDocs, setCatalogDocs] = (0, react.useState)(null);
|
|
5760
|
+
const [catalogTab, setCatalogTab] = (0, react.useState)("policy");
|
|
5761
|
+
/** Fetch and show the two read-only catalog documents. */
|
|
5762
|
+
const openCatalogDocs = (0, react.useCallback)(async () => {
|
|
5763
|
+
setCatalogDocs({ status: "loading" });
|
|
5764
|
+
try {
|
|
5765
|
+
const docs = unwrap(await remote.getCatalogDocs(), "capabilityPolicy.getCatalogDocs");
|
|
5766
|
+
setCatalogDocs({
|
|
5767
|
+
status: "ready",
|
|
5768
|
+
docs
|
|
5769
|
+
});
|
|
5770
|
+
} catch (error) {
|
|
5771
|
+
setCatalogDocs({
|
|
5772
|
+
status: "error",
|
|
5773
|
+
message: String(error)
|
|
5774
|
+
});
|
|
5775
|
+
}
|
|
5776
|
+
}, [remote]);
|
|
5694
5777
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
5695
5778
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5696
5779
|
className: "mc-heading",
|
|
@@ -5723,20 +5806,25 @@ function ReadyBody(props) {
|
|
|
5723
5806
|
onClick: () => onTabChange("skills"),
|
|
5724
5807
|
children: t("skillsGroup")
|
|
5725
5808
|
})]
|
|
5726
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5809
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5727
5810
|
className: "mc-summary",
|
|
5728
|
-
children: summary.map(({ cls, count }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5811
|
+
children: [summary.map(({ cls, count }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5729
5812
|
className: `mc-chip mc-chip--${cls}`,
|
|
5730
5813
|
children: [
|
|
5731
5814
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5732
5815
|
className: `mc-dot mc-dot--${cls}`,
|
|
5733
5816
|
"aria-hidden": "true"
|
|
5734
5817
|
}),
|
|
5735
|
-
t(
|
|
5818
|
+
t(CLASS_SHORT_KEYS[cls]),
|
|
5736
5819
|
" · ",
|
|
5737
5820
|
count
|
|
5738
5821
|
]
|
|
5739
|
-
}, cls))
|
|
5822
|
+
}, cls)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5823
|
+
type: "button",
|
|
5824
|
+
className: "mc-catalog-btn",
|
|
5825
|
+
onClick: () => void openCatalogDocs(),
|
|
5826
|
+
children: t("viewCatalog")
|
|
5827
|
+
})]
|
|
5740
5828
|
})]
|
|
5741
5829
|
}),
|
|
5742
5830
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -5775,7 +5863,7 @@ function ReadyBody(props) {
|
|
|
5775
5863
|
}),
|
|
5776
5864
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5777
5865
|
className: "mc-server-name",
|
|
5778
|
-
children: server
|
|
5866
|
+
children: server === BUILT_IN_SERVER ? t("builtInGroup") : server
|
|
5779
5867
|
}),
|
|
5780
5868
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5781
5869
|
className: "mc-server-count",
|
|
@@ -5799,7 +5887,7 @@ function ReadyBody(props) {
|
|
|
5799
5887
|
className: `mc-dot mc-dot--${cls}`,
|
|
5800
5888
|
"aria-hidden": "true"
|
|
5801
5889
|
}),
|
|
5802
|
-
t(
|
|
5890
|
+
t(CLASS_SHORT_KEYS[cls]),
|
|
5803
5891
|
" ",
|
|
5804
5892
|
count
|
|
5805
5893
|
]
|
|
@@ -5861,13 +5949,49 @@ function ReadyBody(props) {
|
|
|
5861
5949
|
children: skills.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5862
5950
|
className: "mc-empty",
|
|
5863
5951
|
children: t("emptySkills")
|
|
5864
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
5865
|
-
|
|
5952
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5953
|
+
className: "mc-subtabs",
|
|
5954
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5955
|
+
className: "mc-tab-group",
|
|
5956
|
+
role: "tablist",
|
|
5957
|
+
"aria-label": t("skillsGroup"),
|
|
5958
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5959
|
+
type: "button",
|
|
5960
|
+
role: "tab",
|
|
5961
|
+
className: "mc-tab",
|
|
5962
|
+
"aria-selected": skillTab === "global",
|
|
5963
|
+
"data-active": skillTab === "global" ? "true" : void 0,
|
|
5964
|
+
onClick: () => setSkillTab("global"),
|
|
5965
|
+
children: t("globalSkills")
|
|
5966
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5967
|
+
type: "button",
|
|
5968
|
+
role: "tab",
|
|
5969
|
+
className: "mc-tab",
|
|
5970
|
+
"aria-selected": skillTab === "project",
|
|
5971
|
+
"data-active": skillTab === "project" ? "true" : void 0,
|
|
5972
|
+
onClick: () => setSkillTab("project"),
|
|
5973
|
+
children: t("projectSkills")
|
|
5974
|
+
})]
|
|
5975
|
+
})
|
|
5976
|
+
}), skillTab === "global" ? globalSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
5977
|
+
skills: globalSkills,
|
|
5866
5978
|
remote,
|
|
5867
5979
|
busy,
|
|
5868
5980
|
t,
|
|
5869
5981
|
onCycle
|
|
5870
|
-
})
|
|
5982
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5983
|
+
className: "mc-empty",
|
|
5984
|
+
children: t("emptyGlobalSkills")
|
|
5985
|
+
}) : projectSkills.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillList, {
|
|
5986
|
+
skills: projectSkills,
|
|
5987
|
+
remote,
|
|
5988
|
+
busy,
|
|
5989
|
+
t,
|
|
5990
|
+
onCycle
|
|
5991
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5992
|
+
className: "mc-empty",
|
|
5993
|
+
children: t("emptyProjectSkills")
|
|
5994
|
+
})] })
|
|
5871
5995
|
})
|
|
5872
5996
|
}),
|
|
5873
5997
|
toolDetail !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -5910,6 +6034,76 @@ function ReadyBody(props) {
|
|
|
5910
6034
|
})
|
|
5911
6035
|
]
|
|
5912
6036
|
})
|
|
6037
|
+
}),
|
|
6038
|
+
catalogDocs !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6039
|
+
className: "mc-preview-mask",
|
|
6040
|
+
onClick: () => setCatalogDocs(null),
|
|
6041
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6042
|
+
className: "mc-preview",
|
|
6043
|
+
onClick: (e) => e.stopPropagation(),
|
|
6044
|
+
children: [
|
|
6045
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6046
|
+
className: "mc-preview-head",
|
|
6047
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6048
|
+
className: "mc-preview-title",
|
|
6049
|
+
children: t("viewCatalog")
|
|
6050
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6051
|
+
type: "button",
|
|
6052
|
+
className: "mc-preview-close",
|
|
6053
|
+
onClick: () => setCatalogDocs(null),
|
|
6054
|
+
children: t("previewClose")
|
|
6055
|
+
})]
|
|
6056
|
+
}),
|
|
6057
|
+
catalogDocs.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6058
|
+
className: "mc-preview-hint",
|
|
6059
|
+
children: "…"
|
|
6060
|
+
}),
|
|
6061
|
+
catalogDocs.status === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6062
|
+
className: "mc-preview-hint",
|
|
6063
|
+
children: catalogDocs.message
|
|
6064
|
+
}),
|
|
6065
|
+
catalogDocs.status === "ready" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6066
|
+
className: "mc-subtabs mc-catalog-tabs",
|
|
6067
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6068
|
+
className: "mc-tab-group",
|
|
6069
|
+
role: "tablist",
|
|
6070
|
+
"aria-label": t("viewCatalog"),
|
|
6071
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6072
|
+
type: "button",
|
|
6073
|
+
role: "tab",
|
|
6074
|
+
className: "mc-tab",
|
|
6075
|
+
"aria-selected": catalogTab === "policy",
|
|
6076
|
+
"data-active": catalogTab === "policy" ? "true" : void 0,
|
|
6077
|
+
onClick: () => setCatalogTab("policy"),
|
|
6078
|
+
children: t("catalogPolicy")
|
|
6079
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6080
|
+
type: "button",
|
|
6081
|
+
role: "tab",
|
|
6082
|
+
className: "mc-tab",
|
|
6083
|
+
"aria-selected": catalogTab === "catalog",
|
|
6084
|
+
"data-active": catalogTab === "catalog" ? "true" : void 0,
|
|
6085
|
+
onClick: () => setCatalogTab("catalog"),
|
|
6086
|
+
children: t("catalogOnDemand")
|
|
6087
|
+
})]
|
|
6088
|
+
})
|
|
6089
|
+
}), catalogTab === "policy" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6090
|
+
className: "mc-catalog-path",
|
|
6091
|
+
children: t("catalogPolicyNote")
|
|
6092
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
6093
|
+
className: "mc-preview-body",
|
|
6094
|
+
children: catalogDocs.docs.policyYaml
|
|
6095
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [catalogDocs.docs.catalog !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6096
|
+
className: "mc-catalog-path",
|
|
6097
|
+
children: catalogDocs.docs.catalog.path
|
|
6098
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6099
|
+
className: "mc-catalog-path",
|
|
6100
|
+
children: t("catalogOnDemand")
|
|
6101
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
6102
|
+
className: "mc-preview-body",
|
|
6103
|
+
children: catalogDocs.docs.catalog?.content ?? (catalogDocs.docs.catalogMissing === "disabled" ? t("catalogDisabled") : t("catalogUnreadable"))
|
|
6104
|
+
})] })] })
|
|
6105
|
+
]
|
|
6106
|
+
})
|
|
5913
6107
|
})
|
|
5914
6108
|
] });
|
|
5915
6109
|
}
|
|
@@ -6125,7 +6319,7 @@ function SkillList(props) {
|
|
|
6125
6319
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6126
6320
|
className: `mc-dot mc-dot--${skill.class}`,
|
|
6127
6321
|
"aria-hidden": "true"
|
|
6128
|
-
}), t(
|
|
6322
|
+
}), t(CLASS_SHORT_KEYS[skill.class])]
|
|
6129
6323
|
})]
|
|
6130
6324
|
})
|
|
6131
6325
|
]
|
|
@@ -6180,59 +6374,83 @@ const inject = [
|
|
|
6180
6374
|
"locale",
|
|
6181
6375
|
"remote"
|
|
6182
6376
|
];
|
|
6183
|
-
/** Register the
|
|
6377
|
+
/** Register the 能力管理 section once `settings.section` is on the ledger. */
|
|
6184
6378
|
async function apply(ctx) {
|
|
6185
6379
|
const zh = {
|
|
6186
|
-
nav: "
|
|
6187
|
-
title: "
|
|
6188
|
-
desc: "
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6380
|
+
nav: "能力管理",
|
|
6381
|
+
title: "能力管理",
|
|
6382
|
+
desc: "管理工具与技能的 常驻 / 按需 / 禁用 三档分类。",
|
|
6383
|
+
resident: "Resident(常驻上下文)",
|
|
6384
|
+
"on-demand": "On-demand(按需发现)",
|
|
6385
|
+
disabled: "Disabled(禁用)",
|
|
6192
6386
|
kind: "类型",
|
|
6193
6387
|
class: "分类",
|
|
6194
6388
|
tool: "tool",
|
|
6195
6389
|
skill: "skill",
|
|
6196
6390
|
mandatory: "meta",
|
|
6197
6391
|
rules: "规则",
|
|
6198
|
-
toolsGroup: "
|
|
6392
|
+
toolsGroup: "Tools",
|
|
6199
6393
|
skillsGroup: "Skills",
|
|
6200
|
-
|
|
6394
|
+
builtInGroup: "系统内置",
|
|
6395
|
+
globalSkills: "全局技能",
|
|
6396
|
+
projectSkills: "项目技能",
|
|
6397
|
+
emptyGlobalSkills: "暂无全局技能",
|
|
6398
|
+
emptyProjectSkills: "暂无项目技能",
|
|
6399
|
+
emptyTools: "暂无工具",
|
|
6201
6400
|
emptySkills: "暂无 Skill",
|
|
6202
6401
|
toolCount: "{count} 个工具",
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6402
|
+
residentShort: "常驻",
|
|
6403
|
+
onDemandShort: "按需",
|
|
6404
|
+
disabledShort: "禁用",
|
|
6206
6405
|
cycleHint: "点击标签切换分类(按需 → 禁用 → 常驻)",
|
|
6207
6406
|
notPreviewable: "该文件不是可预览的文本文件",
|
|
6208
6407
|
previewClose: "关闭",
|
|
6209
|
-
detailNotFound: "未找到该工具的详情"
|
|
6408
|
+
detailNotFound: "未找到该工具的详情",
|
|
6409
|
+
cycleOverridden: "分类未生效:{count} 个能力被更高优先级规则覆盖(如通配规则),可移除对应通配规则后重试",
|
|
6410
|
+
viewCatalog: "查看能力目录",
|
|
6411
|
+
catalogPolicy: "三档策略配置",
|
|
6412
|
+
catalogOnDemand: "按需能力目录",
|
|
6413
|
+
catalogPolicyNote: "实时生成,只读;持久化入口为 cordis.patch.yml(未列出规则的能力默认常驻)",
|
|
6414
|
+
catalogDisabled: "按需能力目录未启用(catalogFile 为空)",
|
|
6415
|
+
catalogUnreadable: "按需能力目录文件读取失败"
|
|
6210
6416
|
};
|
|
6211
6417
|
const en = {
|
|
6212
|
-
nav: "Capability
|
|
6213
|
-
title: "Capability
|
|
6214
|
-
desc: "Manage the Resident / On-demand /
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6418
|
+
nav: "Capability Management",
|
|
6419
|
+
title: "Capability Management",
|
|
6420
|
+
desc: "Manage the Resident / On-demand / Disabled classification of tools and skills.",
|
|
6421
|
+
resident: "Resident",
|
|
6422
|
+
"on-demand": "On-demand",
|
|
6423
|
+
disabled: "Disabled",
|
|
6218
6424
|
kind: "kind",
|
|
6219
6425
|
class: "class",
|
|
6220
6426
|
tool: "tool",
|
|
6221
6427
|
skill: "skill",
|
|
6222
6428
|
mandatory: "meta",
|
|
6223
6429
|
rules: "rules",
|
|
6224
|
-
toolsGroup: "
|
|
6430
|
+
toolsGroup: "Tools",
|
|
6225
6431
|
skillsGroup: "Skills",
|
|
6226
|
-
|
|
6432
|
+
builtInGroup: "System built-in",
|
|
6433
|
+
globalSkills: "Global skills",
|
|
6434
|
+
projectSkills: "Project skills",
|
|
6435
|
+
emptyGlobalSkills: "No global skills",
|
|
6436
|
+
emptyProjectSkills: "No project skills",
|
|
6437
|
+
emptyTools: "No tools",
|
|
6227
6438
|
emptySkills: "No skills",
|
|
6228
6439
|
toolCount: "{count} tools",
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
cycleHint: "Click a tag to cycle its classification (On-demand →
|
|
6440
|
+
residentShort: "Resident",
|
|
6441
|
+
onDemandShort: "On-demand",
|
|
6442
|
+
disabledShort: "Disabled",
|
|
6443
|
+
cycleHint: "Click a tag to cycle its classification (On-demand → Disabled → Resident)",
|
|
6233
6444
|
notPreviewable: "This file is not a previewable text file",
|
|
6234
6445
|
previewClose: "Close",
|
|
6235
|
-
detailNotFound: "Tool detail not found"
|
|
6446
|
+
detailNotFound: "Tool detail not found",
|
|
6447
|
+
cycleOverridden: "Classification not applied: {count} capability(ies) overridden by a higher-priority rule (e.g. a wildcard). Remove the matching wildcard rule and retry.",
|
|
6448
|
+
viewCatalog: "View capability catalog",
|
|
6449
|
+
catalogPolicy: "Policy (effective)",
|
|
6450
|
+
catalogOnDemand: "On-demand catalog",
|
|
6451
|
+
catalogPolicyNote: "Generated live from the effective policy (read-only); persist via cordis.patch.yml. Capabilities without a rule default to Resident.",
|
|
6452
|
+
catalogDisabled: "On-demand catalog emission is disabled (catalogFile is empty).",
|
|
6453
|
+
catalogUnreadable: "Failed to read the on-demand catalog file."
|
|
6236
6454
|
};
|
|
6237
6455
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
6238
6456
|
zh,
|