@khorsheed/dsh-capability-catalog 0.1.95

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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +286 -0
  4. package/README.zh.md +138 -0
  5. package/cordis.patch.yml +8 -0
  6. package/lib/client.js +10100 -0
  7. package/lib/index.js +4022 -0
  8. package/lib/invariant.js +25 -0
  9. package/lib/mcpConnector-C2TbkPBY.js +69 -0
  10. package/lib/typert.host.d.ts +3 -0
  11. package/lib/typert.host.js +1417 -0
  12. package/lib/typert.remote-client.d.ts +68 -0
  13. package/lib/typert.remote-client.js +1136 -0
  14. package/lib/types/capabilities.d.ts +103 -0
  15. package/lib/types/capabilities.js +116 -0
  16. package/lib/types/channels.d.ts +41 -0
  17. package/lib/types/channels.js +75 -0
  18. package/lib/types/client/AddMcpDialog.d.ts +13 -0
  19. package/lib/types/client/AddMcpDialog.js +79 -0
  20. package/lib/types/client/AddSkillModal.d.ts +17 -0
  21. package/lib/types/client/AddSkillModal.js +138 -0
  22. package/lib/types/client/BundleFileTree.d.ts +7 -0
  23. package/lib/types/client/BundleFileTree.js +74 -0
  24. package/lib/types/client/CapabilityCatalogCard.d.ts +57 -0
  25. package/lib/types/client/CapabilityCatalogCard.js +479 -0
  26. package/lib/types/client/CredentialField.d.ts +14 -0
  27. package/lib/types/client/CredentialField.js +9 -0
  28. package/lib/types/client/McpCards.d.ts +13 -0
  29. package/lib/types/client/McpCards.js +12 -0
  30. package/lib/types/client/McpServerManageModal.d.ts +18 -0
  31. package/lib/types/client/McpServerManageModal.js +63 -0
  32. package/lib/types/client/MetadataRow.d.ts +10 -0
  33. package/lib/types/client/MetadataRow.js +6 -0
  34. package/lib/types/client/ModalShell.d.ts +16 -0
  35. package/lib/types/client/ModalShell.js +27 -0
  36. package/lib/types/client/ModeChips.d.ts +38 -0
  37. package/lib/types/client/ModeChips.js +42 -0
  38. package/lib/types/client/SchemaView.d.ts +11 -0
  39. package/lib/types/client/SchemaView.js +143 -0
  40. package/lib/types/client/SkillCards.d.ts +28 -0
  41. package/lib/types/client/SkillCards.js +43 -0
  42. package/lib/types/client/SkillDetailModal.d.ts +69 -0
  43. package/lib/types/client/SkillDetailModal.js +167 -0
  44. package/lib/types/client/ToolCards.d.ts +28 -0
  45. package/lib/types/client/ToolCards.js +52 -0
  46. package/lib/types/client/ToolDetailModal.d.ts +12 -0
  47. package/lib/types/client/ToolDetailModal.js +29 -0
  48. package/lib/types/client/icons.d.ts +26 -0
  49. package/lib/types/client/icons.js +10 -0
  50. package/lib/types/client/index.d.ts +21 -0
  51. package/lib/types/client/index.js +196 -0
  52. package/lib/types/client/locales.d.ts +392 -0
  53. package/lib/types/client/locales.js +395 -0
  54. package/lib/types/client/mcp-model.d.ts +24 -0
  55. package/lib/types/client/mcp-model.js +87 -0
  56. package/lib/types/client/mode-model.d.ts +108 -0
  57. package/lib/types/client/mode-model.js +140 -0
  58. package/lib/types/client/preset-display.d.ts +21 -0
  59. package/lib/types/client/preset-display.js +20 -0
  60. package/lib/types/client/settle.d.ts +40 -0
  61. package/lib/types/client/settle.js +57 -0
  62. package/lib/types/client/slots.d.ts +86 -0
  63. package/lib/types/client/slots.js +1 -0
  64. package/lib/types/envHint.d.ts +22 -0
  65. package/lib/types/envHint.js +76 -0
  66. package/lib/types/import.d.ts +106 -0
  67. package/lib/types/import.js +635 -0
  68. package/lib/types/index.d.ts +216 -0
  69. package/lib/types/index.js +739 -0
  70. package/lib/types/invariant.d.ts +16 -0
  71. package/lib/types/invariant.js +23 -0
  72. package/lib/types/mcpConnector.d.ts +24 -0
  73. package/lib/types/mcpConnector.js +73 -0
  74. package/lib/types/mcpStore.d.ts +68 -0
  75. package/lib/types/mcpStore.js +235 -0
  76. package/lib/types/mcpTools.d.ts +45 -0
  77. package/lib/types/mcpTools.js +125 -0
  78. package/lib/types/mcps.d.ts +64 -0
  79. package/lib/types/mcps.js +157 -0
  80. package/lib/types/modes.d.ts +65 -0
  81. package/lib/types/modes.js +97 -0
  82. package/lib/types/namespace.d.ts +9 -0
  83. package/lib/types/namespace.js +8 -0
  84. package/lib/types/official-tools.d.ts +3 -0
  85. package/lib/types/official-tools.js +44 -0
  86. package/lib/types/preset-scope.d.ts +105 -0
  87. package/lib/types/preset-scope.js +117 -0
  88. package/lib/types/remote.d.ts +48 -0
  89. package/lib/types/remote.js +120 -0
  90. package/lib/types/scoped-delivery.d.ts +243 -0
  91. package/lib/types/scoped-delivery.js +686 -0
  92. package/lib/types/scoped-edits.d.ts +90 -0
  93. package/lib/types/scoped-edits.js +234 -0
  94. package/lib/types/settings.d.ts +28 -0
  95. package/lib/types/settings.js +28 -0
  96. package/lib/types/shellEnv.d.ts +65 -0
  97. package/lib/types/shellEnv.js +232 -0
  98. package/lib/types/skills.d.ts +103 -0
  99. package/lib/types/skills.js +303 -0
  100. package/lib/types/tool-origin.d.ts +29 -0
  101. package/lib/types/tool-origin.js +30 -0
  102. package/lib/types/types.d.ts +315 -0
  103. package/lib/types/types.js +8 -0
  104. package/lib/types/zip.d.ts +24 -0
  105. package/lib/types/zip.js +80 -0
  106. package/locale/en.json +6 -0
  107. package/locale/zh.json +6 -0
  108. package/package.json +119 -0
  109. package/scripts/gen-official-tools.mts +52 -0
@@ -0,0 +1,395 @@
1
+ /**
2
+ * Dictionaries for the capability-catalog browser half.
3
+ * @module @khorsheed/dsh-capability-catalog/client
4
+ */
5
+ export const NS = 'capability-catalog';
6
+ export const zh = {
7
+ title: '工具与技能',
8
+ 'section.nav': '工具与技能',
9
+ intro: '当前实例中已注册的技能与工具。',
10
+ skillTab: '技能',
11
+ toolTab: '工具',
12
+ addSkill: '新增 Skill',
13
+ empty: '没有已注册的技能。',
14
+ loading: '加载中…',
15
+ loadFailed: '加载失败',
16
+ source: '来源',
17
+ provider: '提供者',
18
+ modelInvocable: '模型可调用',
19
+ whenToUse: '适用场景',
20
+ yes: '是',
21
+ no: '否',
22
+ userOnly: '仅用户',
23
+ builtin: '内置',
24
+ sourceProject: '项目',
25
+ sourceCustom: '自定义',
26
+ sourceUser: '用户',
27
+ toolOriginGuideLink: '为什么我的插件工具不在这里?',
28
+ toolOriginGuideTitle: '为什么我的插件工具不在这里?',
29
+ toolOriginGuideIntro: '工具要显示为「插件」,需要在注册前为它标记来源。你的插件工具没标,所以它按既有启发式暂显示为「内置」。把下面这段直接发给你的可编程 agent,它会按规范为你的工具标记。',
30
+ toolOriginGuideCopy: '请先阅读 docs/tool-origin-guide.md 的工具来源标记规范,然后帮我把我的插件工具在 ctx.tools.register 前都标记上 origin(channel: \'plugin\',owner 填对应包名),让它们显示在「工具与技能」的「插件」分类下。改完告诉我你标记了哪些工具。',
31
+ toolOriginGuideFooter: '点「复制」复制上面整段说明,发给你写这个插件的 agent 即可。',
32
+ skillOther: '其他',
33
+ delete: '删除',
34
+ confirmDelete: '确定要删除 skill',
35
+ viewDetail: '查看详情',
36
+ searchPlaceholder: '按名称或描述搜索…',
37
+ filterAll: '全部',
38
+ sortBy: '排序',
39
+ sortName: '名称',
40
+ sortUpdated: '最近更新',
41
+ noFilterMatch: '没有匹配的技能',
42
+ updated: '更新于',
43
+ /* Tool catalog. */
44
+ toolBuiltin: '内置',
45
+ toolPlugin: '插件',
46
+ toolParams: '参数',
47
+ toolNoParams: '无参数',
48
+ toolExpand: '展开更多',
49
+ toolCollapse: '收起',
50
+ toolSearchPlaceholder: '按名称 / 描述 / server 搜索…',
51
+ toolNoMatch: '没有匹配的工具',
52
+ toolOther: '其他',
53
+ paramsTree: '结构',
54
+ paramsJson: 'JSON',
55
+ copyJson: '复制 JSON',
56
+ paramRequired: '必填',
57
+ credentials: '凭据配置',
58
+ credentialsHint: '该 skill 的 metadata 声明了以下凭据,配置后模型可读取。',
59
+ envRefs: '引用的环境变量',
60
+ envRefsHint: '该 skill 的说明引用了以下变量;它们通常由运行环境或调用方提供,不在此页配置。',
61
+ configured: '已配置',
62
+ notConfigured: '未配置',
63
+ configuredReplace: '已配置——输入新值可替换',
64
+ credPlaceholder: '输入值',
65
+ save: '保存',
66
+ show: '显示',
67
+ hide: '隐藏',
68
+ saved: '已保存',
69
+ saveFailed: '保存失败',
70
+ viewSource: '查看源码',
71
+ bundleFiles: '包文件',
72
+ metadata: 'metadata',
73
+ copy: '复制',
74
+ copied: '已复制',
75
+ detailClose: '关闭',
76
+ addSkillHint: '上传 skill 包(zip/拖拽)或从源码仓库安装,将写入选定的 skill 根目录。',
77
+ addTabUpload: '文件上传',
78
+ addTabCommand: '命令安装',
79
+ addTabDir: '从本机目录',
80
+ dirLabel: '本机 skill 目录',
81
+ dirPlaceholder: '绝对路径,如 ~/.claude/skills 或 ~/my-skills',
82
+ dirHint: '选择一个包含 SKILL.md 的本机目录,自动解析其中可安装的 skill。',
83
+ browseDir: '选择目录',
84
+ dropTitle: '拖入 Skill 文件夹、ZIP 或 SKILL.md',
85
+ dropHint: '也可以点击选择文件',
86
+ commandLabel: '安装命令或已安装路径',
87
+ commandPlaceholder: 'npx skills add owner/repo --skill 名字,或填 owner/repo、github.com/owner/repo 链接、git URL、本机目录',
88
+ commandHint: '可整条粘贴 README 里的安装命令(含 --skill/-g 等参数);浏览器里复制的 GitHub 链接也能直接粘贴(可带仓库内路径,如 github.com/owner/repo/skills/名字),host 会被剥掉、路径只在该路径下查找。仓库/路径会克隆进受管根,避免装到 dsh 扫不到的目录。仓库含多个技能时必须用 --skill 指定,否则会报错列出可选项。',
89
+ listDir: '列出本机目录技能',
90
+ pickSkills: '选择要安装的技能',
91
+ noSkillsFound: '该目录里没有找到 skill(需含 SKILL.md)。',
92
+ addModelInvocable: '允许模型自动发现',
93
+ addModelInvocableHint: '开启后模型可在合适任务中自动使用;关闭后仅能通过 /{name} 调用。',
94
+ skillNamePlaceholder: '技能名',
95
+ noSkillRoots: '未找到本机 skill 根目录',
96
+ addRoot: '安装到',
97
+ rootUser: '个人 Skill 目录',
98
+ rootUserPath: '$DSH_HOME/skills',
99
+ rootProject: '项目 Skill 目录',
100
+ rootProjectPath: '.agents/skills(相对项目工作目录)',
101
+ addSubmit: '导入',
102
+ cancel: '取消',
103
+ close: '关闭',
104
+ addSuccess: '已添加 skill:',
105
+ addError: '添加失败',
106
+ readFailed: '文件读取失败',
107
+ addExistsTitle: '该技能已存在',
108
+ addExists: '已存在于目标目录,如继续导入将会覆盖原文件,请确认是否要继续。',
109
+ replace: '覆盖',
110
+ /* MCP management. */
111
+ addMcp: '新增 MCP',
112
+ mcpSection: 'MCP 服务器',
113
+ mcpServerEmpty: '还没有 MCP 服务器,点击右上角「新增 MCP」。',
114
+ mcpAddHint: '粘贴一个 MCP server 配置(mcp.json 中的一项,或仅含 command/url 的片段),会自动解析传输与凭据。',
115
+ mcpPastePlaceholder: '{"command":"npx","args":["-y","@amap/amap-maps-mcp-server"],"env":{"AMAP_MAPS_API_KEY":"sk-…"}}',
116
+ mcpServerName: '服务名',
117
+ mcpServerNamePlaceholder: 'server 名称,如 amap-maps',
118
+ mcpTransport: '传输',
119
+ mcpUnknown: '未知',
120
+ mcpEnabled: '启用',
121
+ mcpDisabled: '已停用',
122
+ mcpNotEnabled: '服务未启用,展开并启用后连接。',
123
+ mcpDiscover: '连接并发现工具',
124
+ mcpDiscovering: '连接中…',
125
+ mcpNoTools: '未发现工具',
126
+ mcpToolCount: '{n} 个工具',
127
+ mcpToolSearchPlaceholder: '搜索工具…',
128
+ mcpEnabledOf: '启用',
129
+ mcpTools: '工具',
130
+ mcpNoCreds: '无凭据',
131
+ mcpConfig: '配置',
132
+ mcpHeader: '请求头',
133
+ mcpEnv: '环境变量',
134
+ mcpUrl: 'URL',
135
+ mcpCommand: '命令',
136
+ mcpArgs: '参数',
137
+ mcpCwd: '工作目录',
138
+ mcpRemove: '移除',
139
+ mcpAdd: '添加',
140
+ mcpAddTitled: '新增 MCP 服务器',
141
+ mcpParseFailed: '无法识别该配置:需要一个 command(stdio)或 url(streamable-http) 的 server 片段。',
142
+ mcpCredBadge: '凭据',
143
+ mcpCredLabel: '检测到配置项:',
144
+ mcpNeedsCred: '该配置含凭据项,配置后将通过引用注入,不存明文。',
145
+ mcpReconnect: '重新连接',
146
+ mcpToolToggleHint: '单独控制是否启用该工具。',
147
+ mcpDiscoverHint: '连接该 server 并拉取工具列表。',
148
+ mcpEmptyTools: '该 server 尚未发现工具。',
149
+ mcpAddSuccess: '已添加 MCP 服务器:',
150
+ mcpRemoveConfirm: '移除该 MCP 服务器?',
151
+ scopeInfoLabel: '生效范围说明',
152
+ scopePresetTag: 'preset',
153
+ scopeAllPresets: '全部',
154
+ scopeSection: '生效的 preset',
155
+ scopeEvery: '所有 preset',
156
+ scopeHint: '勾选这个 skill 生效的 preset;一个都不勾表示所有模式可见。改的是 skill 自己的 frontmatter。',
157
+ scopeProvided: '该 skill 由插件「{provider}」提供:它在哪些模式生效取决于该插件挂在哪些预设的组合里,不能在这里单独限定。',
158
+ scopeBuiltin: '该 skill 由部署内置提供:生效模式跟随部署组合,不能在这里单独限定。',
159
+ scopeSave: '保存',
160
+ scopeSaving: '保存中…',
161
+ scopeSaved: '已保存',
162
+ scopeAdopt: '移入受管目录并可限定 preset',
163
+ scopeRelease: '释放回用户技能目录',
164
+ scopeConflict: '已拒绝投递:默认根里还有一份同名副本(迁移没完成的残留)',
165
+ scopeUnavailable: '此部署没有可用的 preset 名单,或受管投递未启用。',
166
+ scopeBroken: '加载失败',
167
+ scopeError: '操作失败',
168
+ scopeProbe: '这是发现/投递策略,不是权限边界;外部 agent(codex/claude/ACP)不覆盖。',
169
+ /* Mode view: which capabilities each agent preset loads. */
170
+ modeLabel: '模式',
171
+ modeHint: '切换查看的 Agent 预设;「全部模式」逐个读取后对比哪些工具/skill 出现在哪些模式里。首次对比会加载尚未挂载的预设。',
172
+ modeDefault: '默认',
173
+ modeAll: '全部模式(对比)',
174
+ modeIn: '出现在',
175
+ modeChipHint: '切换到该模式查看',
176
+ modeEvery: '全部模式 · {n}',
177
+ modeMore: '+{n}',
178
+ modeCollapse: '收起',
179
+ modeNone: '该部署里没有任何模式加载它。',
180
+ modeChipsCost: '(读取每个模式的能力面;未挂载过的预设会被组合一次)',
181
+ modeBusy: '正在读取该模式的会话插件…',
182
+ modeCompareNote: '对比 {n} 个模式 · 技能 {skills} · 工具 {tools}',
183
+ modeUnavailableNote: '{n} 个模式无法读取',
184
+ modeCompareCost: '对比会逐个加载每个模式的组合,未挂载过的预设可能要等一会。',
185
+ modeFallback: '该模式当前无法加载(组合失败或未挂载),下面显示的是全局层,不代表该模式实际可见范围。',
186
+ orphanManaged: '{n} 个受管 skill 未在任何模式生效',
187
+ orphanManagedHint: '它们的 preset 范围指向了本部署没有的 preset,或投递被同名副本拒绝。展开后可打开详情改范围或释放回用户技能目录。',
188
+ /* The four shipped presets publish no name; their copy resolves through these
189
+ * keys (mirrors the host's ui-agent-preset dictionary, same strings). */
190
+ presetStandardName: '标准模式',
191
+ presetStandardDescription: '处理代码、文件和资料,适合大多数任务。Agent 会按需使用检索、编辑和终端等工具。',
192
+ presetPtcName: 'PTC 模式',
193
+ presetPtcDescription: '包含标准模式的所有能力,更适合批量调用工具,并对结果进行筛选、整理、去重、统计或汇总的任务。',
194
+ presetMinimalName: '极简模式',
195
+ presetMinimalDescription: 'Agent 仅使用终端工具完成任务,适合测试和对比其基础表现。',
196
+ presetCordisName: '创造模式',
197
+ presetCordisDescription: '用对话定制 DSH:让 Agent 编写插件,添加新功能或界面;也能组合工具和提示词,创建自己的模式。',
198
+ /* Frontmatter metadata block. */
199
+ frontmatterMetadata: 'frontmatter metadata',
200
+ };
201
+ export const en = {
202
+ title: 'Tools & Skills',
203
+ 'section.nav': 'Tools & Skills',
204
+ intro: 'Skills and tools registered in this instance.',
205
+ skillTab: 'Skills',
206
+ toolTab: 'Tools',
207
+ addSkill: 'Add Skill',
208
+ empty: 'No skills registered.',
209
+ loading: 'Loading…',
210
+ loadFailed: 'Failed to load',
211
+ source: 'Source',
212
+ provider: 'Provider',
213
+ modelInvocable: 'Model-invocable',
214
+ whenToUse: 'When to use',
215
+ yes: 'Yes',
216
+ no: 'No',
217
+ userOnly: 'User only',
218
+ builtin: 'Built-in',
219
+ sourceProject: 'Project',
220
+ sourceCustom: 'Custom',
221
+ sourceUser: 'User',
222
+ toolOriginGuideLink: 'Why is my plugin tool not here?',
223
+ toolOriginGuideTitle: 'Why is my plugin tool not here?',
224
+ toolOriginGuideIntro: 'A tool shows as 插件 only if it declares its origin before being registered. Yours is untagged, so it currently falls back to 内置. Send the message below to your coding agent — it will tag your tools per the convention.',
225
+ toolOriginGuideCopy: 'Please read the tool-origin convention in docs/tool-origin-guide.md, then tag my plugin tools with their origin before ctx.tools.register (channel: \'plugin\', owner = the package name) so they show under 插件 in 工具与技能. Tell me which tools you tagged.',
226
+ toolOriginGuideFooter: 'Tap 复制 to copy the whole message to the agent that writes this plugin.',
227
+ skillOther: 'Other',
228
+ delete: 'Delete',
229
+ confirmDelete: 'Delete this skill',
230
+ viewDetail: 'View details',
231
+ searchPlaceholder: 'Search by name or description…',
232
+ filterAll: 'All',
233
+ sortBy: 'Sort',
234
+ sortName: 'Name',
235
+ sortUpdated: 'Recently updated',
236
+ noFilterMatch: 'No matching skills',
237
+ updated: 'Updated',
238
+ /* Tool catalog. */
239
+ toolBuiltin: 'Built-in',
240
+ toolPlugin: 'Plugin',
241
+ toolParams: 'Parameters',
242
+ toolNoParams: 'No parameters',
243
+ toolExpand: 'Expand',
244
+ toolCollapse: 'Collapse',
245
+ toolSearchPlaceholder: 'Search by name / description / server…',
246
+ toolNoMatch: 'No matching tools',
247
+ toolOther: 'Other',
248
+ paramsTree: 'Tree',
249
+ paramsJson: 'JSON',
250
+ copyJson: 'Copy JSON',
251
+ paramRequired: 'Required',
252
+ credentials: 'Credential config',
253
+ credentialsHint: 'The skill metadata declares these credentials; configure them so the model can read them.',
254
+ envRefs: 'Referenced environment variables',
255
+ envRefsHint: 'The skill description references these variables; they are typically provided by the runtime or caller and are not configured here.',
256
+ configured: 'Configured',
257
+ notConfigured: 'Not configured',
258
+ configuredReplace: 'Configured — enter a new value to replace',
259
+ credPlaceholder: 'Enter value',
260
+ save: 'Save',
261
+ show: 'Show',
262
+ hide: 'Hide',
263
+ saved: 'Saved',
264
+ saveFailed: 'Save failed',
265
+ viewSource: 'View source',
266
+ bundleFiles: 'Package files',
267
+ metadata: 'metadata',
268
+ copy: 'Copy',
269
+ copied: 'Copied',
270
+ detailClose: 'Close',
271
+ addSkillHint: 'Upload a skill archive (drag-drop) or install from a source repo into the selected skill root.',
272
+ addTabUpload: 'Upload',
273
+ addTabCommand: 'Install from source',
274
+ addTabDir: 'From directory',
275
+ dirLabel: 'Local skill directory',
276
+ dirPlaceholder: 'An absolute path, e.g. ~/.claude/skills or ~/my-skills',
277
+ dirHint: 'Pick a local directory containing SKILL.md skills; they are parsed automatically.',
278
+ browseDir: 'Choose directory',
279
+ dropTitle: 'Drop a skill folder, ZIP, or SKILL.md',
280
+ dropHint: 'You can also click to choose a file',
281
+ commandLabel: 'Install command or path',
282
+ commandPlaceholder: 'npx skills add owner/repo --skill name, or owner/repo, a github.com/owner/repo link, a git URL, a local path',
283
+ commandHint: 'Paste a README install command whole, flags included. A GitHub link copied out of a browser installs as-is too — an in-repo path (`github.com/owner/repo/skills/name`) is honoured, and the leading host is stripped rather than read as the owner. The repo/path is cloned into the managed root so it lands where dsh can scan it. When a repo carries several skills, --skill is required — otherwise the error lists them.',
284
+ listDir: 'List skills in dir',
285
+ pickSkills: 'Pick skills to install',
286
+ noSkillsFound: 'No skill (SKILL.md) found in that directory.',
287
+ addModelInvocable: 'Allow model auto-discovery',
288
+ addModelInvocableHint: 'When on, the model can use it automatically in suitable tasks; when off, only /{name} can invoke it.',
289
+ skillNamePlaceholder: 'skill',
290
+ noSkillRoots: 'No local skill roots found',
291
+ addRoot: 'Install to',
292
+ rootUser: 'Personal skill directory',
293
+ rootUserPath: '$DSH_HOME/skills',
294
+ rootProject: 'Project skill directory',
295
+ rootProjectPath: '.agents/skills (relative to project workdir)',
296
+ addSubmit: 'Add',
297
+ cancel: 'Cancel',
298
+ close: 'Close',
299
+ addSuccess: 'Added skill: ',
300
+ addError: 'Failed to add',
301
+ readFailed: 'Failed to read file',
302
+ addExistsTitle: 'This skill already exists',
303
+ addExists: 'already exists in the target root. Continuing to import will overwrite the original file. Please confirm and continue.',
304
+ replace: 'Replace',
305
+ /* MCP management. */
306
+ addMcp: 'Add MCP',
307
+ mcpSection: 'MCP servers',
308
+ mcpServerEmpty: 'No MCP servers yet — click "Add MCP" in the top-right.',
309
+ mcpAddHint: 'Paste one MCP server config (an entry of mcp.json, or a bare command/url snippet). It is parsed into a transport + credentials automatically.',
310
+ mcpPastePlaceholder: '{"command":"npx","args":["-y","@amap/amap-maps-mcp-server"],"env":{"AMAP_MAPS_API_KEY":"sk-…"}}',
311
+ mcpServerName: 'Server name',
312
+ mcpServerNamePlaceholder: 'server name, e.g. amap-maps',
313
+ mcpTransport: 'Transport',
314
+ mcpUnknown: 'Unknown',
315
+ mcpEnabled: 'Enabled',
316
+ mcpDisabled: 'Disabled',
317
+ mcpNotEnabled: 'Server not enabled; enable it to connect.',
318
+ mcpDiscover: 'Connect & discover tools',
319
+ mcpDiscovering: 'Connecting…',
320
+ mcpNoTools: 'No tools discovered',
321
+ mcpToolCount: '{n} tools',
322
+ mcpToolSearchPlaceholder: 'Search tools…',
323
+ mcpEnabledOf: 'enabled',
324
+ mcpTools: 'Tools',
325
+ mcpNoCreds: 'No credentials',
326
+ mcpConfig: 'Config',
327
+ mcpHeader: 'Headers',
328
+ mcpEnv: 'Env',
329
+ mcpUrl: 'URL',
330
+ mcpCommand: 'Command',
331
+ mcpArgs: 'Args',
332
+ mcpCwd: 'Cwd',
333
+ mcpRemove: 'Remove',
334
+ mcpAdd: 'Add',
335
+ mcpAddTitled: 'Add MCP server',
336
+ mcpParseFailed: 'Unrecognized config: a command (stdio) or url (streamable-http) snippet is required.',
337
+ mcpCredBadge: 'Credential',
338
+ mcpCredLabel: 'Detected config item:',
339
+ mcpNeedsCred: 'This config has credential items; they are injected by reference after configuration — never stored as plaintext.',
340
+ mcpReconnect: 'Reconnect',
341
+ mcpToolToggleHint: 'Control whether this specific tool is enabled.',
342
+ mcpDiscoverHint: 'Connect to this server and pull its tool list.',
343
+ mcpEmptyTools: 'No tools discovered for this server yet.',
344
+ mcpAddSuccess: 'Added MCP server: ',
345
+ mcpRemoveConfirm: 'Remove this MCP server?',
346
+ scopeInfoLabel: 'About the effective scope',
347
+ scopePresetTag: 'preset',
348
+ scopeAllPresets: 'all',
349
+ scopeSection: 'Effective presets',
350
+ scopeEvery: 'All presets',
351
+ scopeHint: 'Tick the presets this skill is delivered to; none ticked means every preset sees it. This edits the skill\'s own frontmatter.',
352
+ scopeProvided: 'This skill comes from the plugin "{provider}": which modes load it follows the plugin\'s row in each preset\'s composition, so its scope cannot be set here.',
353
+ scopeBuiltin: 'This skill ships with the deployment: its modes follow the deployment composition and cannot be set here.',
354
+ scopeSave: 'Save',
355
+ scopeSaving: 'Saving…',
356
+ scopeSaved: 'Saved',
357
+ scopeAdopt: 'Move into the managed root (preset-scoped)',
358
+ scopeRelease: 'Release back to the user skill root',
359
+ scopeConflict: 'Delivery refused: a same-named copy still exists in a default root',
360
+ scopeUnavailable: 'No preset roster is available in this deployment, or managed delivery is off.',
361
+ scopeBroken: 'Failed to load',
362
+ scopeError: 'Failed',
363
+ scopeProbe: 'A discovery/delivery policy, not an authorization boundary; external agents (codex/claude/ACP) are not covered.',
364
+ /* Mode view: which capabilities each agent preset loads. */
365
+ modeLabel: 'Mode',
366
+ modeHint: 'Switch the agent preset this grid reads; "All modes" reads every preset and compares which tools/skills appear in which modes. The first comparison composes presets nothing has mounted yet.',
367
+ modeDefault: 'default',
368
+ modeAll: 'All modes (compare)',
369
+ modeIn: 'In',
370
+ modeChipHint: 'Switch to this mode',
371
+ modeEvery: 'every mode · {n}',
372
+ modeMore: '+{n}',
373
+ modeCollapse: 'less',
374
+ modeNone: 'No mode in this deployment loads it.',
375
+ modeChipsCost: '(reads every mode\'s face; a preset nothing has mounted is composed once)',
376
+ modeBusy: 'Reading this mode\'s session plugins…',
377
+ modeCompareNote: 'Compared {n} modes · {skills} skills · {tools} tools',
378
+ modeUnavailableNote: '{n} mode(s) could not be read',
379
+ modeCompareCost: 'Comparing composes each mode in turn; a preset nothing has mounted yet can take a moment.',
380
+ modeFallback: 'This mode cannot be composed right now (or is not mounted), so the global layer is shown — it is not that mode\'s real visibility.',
381
+ orphanManaged: '{n} managed skill(s) load in no mode',
382
+ orphanManagedHint: 'Their preset scope names a preset this deployment does not supply, or delivery was refused by a duplicate copy. Expand to open a skill and change its scope or release it to the user skill root.',
383
+ /* The four shipped presets publish no name; their copy resolves through these
384
+ * keys (mirrors the host's ui-agent-preset dictionary, same strings). */
385
+ presetStandardName: 'Standard mode',
386
+ presetStandardDescription: 'Work with code, files, and information. Suitable for most tasks, with search, editing, terminal commands, and other tools available as needed.',
387
+ presetPtcName: 'PTC mode',
388
+ presetPtcDescription: 'Includes all Standard mode capabilities. Better suited to tasks that call tools in batches and then filter, organize, deduplicate, count, or summarize the results.',
389
+ presetMinimalName: 'Minimal mode',
390
+ presetMinimalDescription: 'The agent works using only a terminal tool. Useful for testing and comparing its basic performance.',
391
+ presetCordisName: 'Creator mode',
392
+ presetCordisDescription: 'Customize DSH through conversation. Let the agent write plugins that add features or UI, or combine tools and prompts to create your own mode.',
393
+ /* Frontmatter metadata block. */
394
+ frontmatterMetadata: 'frontmatter metadata',
395
+ };
@@ -0,0 +1,24 @@
1
+ import type { CapabilityCatalogSnapshot, CatalogMcpCredentialDecl, CatalogMcpServerConfig, CatalogMcpSnapshot, CatalogMcpTool, CatalogToolRow, McpTransport } from '@khorsheed/dsh-capability-catalog/types';
2
+ import type { CapabilityCatalogKey } from './locales.ts';
3
+ /** One merged MCP server group shown in the MCP section. `managed` servers are
4
+ * catalog-controlled (config + credentials + per-tool toggles); live-only ones
5
+ * are read-only snapshots of already-registered MCP tools. */
6
+ export interface McpGroup {
7
+ readonly serverName: string;
8
+ readonly transport: McpTransport | undefined;
9
+ readonly enabled: boolean;
10
+ readonly managed: boolean;
11
+ readonly config: CatalogMcpServerConfig | undefined;
12
+ readonly tools: readonly CatalogMcpTool[];
13
+ readonly liveTools: readonly CatalogToolRow[];
14
+ readonly credentials: readonly CatalogMcpCredentialDecl[];
15
+ readonly toolCount: number;
16
+ }
17
+ /** Fold the tool-graph MCP entries + the catalog's managed servers into one
18
+ * server-grouped list (catalog-managed wins over a same-name live group). */
19
+ export declare function buildMcpGroups(snapshot: CapabilityCatalogSnapshot | undefined, mcps: CatalogMcpSnapshot | null, query: string): McpGroup[];
20
+ /** Human label for a transport kind. */
21
+ export declare function transportLabel(t: (key: CapabilityCatalogKey) => string, transport: McpTransport): string;
22
+ /** Read-only JSON view of a server config, with secret values masked. */
23
+ export declare function configDisplay(config: CatalogMcpServerConfig): string;
24
+ //# sourceMappingURL=mcp-model.d.ts.map
@@ -0,0 +1,87 @@
1
+ import { maskSecret, SECRET_REF_PREFIX } from '../mcps.js';
2
+ /** Fold the tool-graph MCP entries + the catalog's managed servers into one
3
+ * server-grouped list (catalog-managed wins over a same-name live group). */
4
+ export function buildMcpGroups(snapshot, mcps, query) {
5
+ const q = query.trim().toLowerCase();
6
+ const groups = [];
7
+ const seen = new Set();
8
+ for (const server of mcps?.servers ?? []) {
9
+ if (q !== '' && !server.serverName.toLowerCase().includes(q))
10
+ continue;
11
+ const creds = (mcps?.credentials ?? []).filter((c) => c.ref.startsWith(`mcp.${server.serverName}.`));
12
+ const tools = mcps?.tools[server.serverName] ?? [];
13
+ groups.push({
14
+ serverName: server.serverName,
15
+ transport: server.transport,
16
+ enabled: server.enabled,
17
+ managed: true,
18
+ config: server,
19
+ tools,
20
+ liveTools: [],
21
+ credentials: creds,
22
+ toolCount: tools.length,
23
+ });
24
+ seen.add(server.serverName);
25
+ }
26
+ // Live-registered MCP tools (already in `ctx.tools`) folded by server. These
27
+ // are not catalog-managed, so they are read-only in the section.
28
+ const byServer = new Map();
29
+ for (const tool of snapshot?.tools ?? []) {
30
+ if (tool.channel !== 'mcp')
31
+ continue;
32
+ const s = tool.serverName ?? 'MCP';
33
+ const list = byServer.get(s);
34
+ if (list !== undefined)
35
+ list.push(tool);
36
+ else
37
+ byServer.set(s, [tool]);
38
+ }
39
+ for (const [serverName, live] of byServer) {
40
+ if (seen.has(serverName))
41
+ continue;
42
+ if (q !== '' && !serverName.toLowerCase().includes(q))
43
+ continue;
44
+ groups.push({
45
+ serverName,
46
+ transport: undefined,
47
+ enabled: true,
48
+ managed: false,
49
+ config: undefined,
50
+ tools: [],
51
+ liveTools: live,
52
+ credentials: [],
53
+ toolCount: live.length,
54
+ });
55
+ }
56
+ return groups.sort((a, b) => a.serverName.localeCompare(b.serverName));
57
+ }
58
+ /** Human label for a transport kind. */
59
+ export function transportLabel(t, transport) {
60
+ if (transport === 'stdio')
61
+ return 'stdio';
62
+ if (transport === 'streamable-http')
63
+ return 'streamable-http';
64
+ return t('mcpUnknown');
65
+ }
66
+ /** Mask any `secretRef:` markers in a URL for read-only display. */
67
+ function maskUrl(url) {
68
+ return url.replace(new RegExp(`${SECRET_REF_PREFIX}[A-Za-z0-9_.-]+`, 'g'), '·secretRef·');
69
+ }
70
+ /** Read-only JSON view of a server config, with secret values masked. */
71
+ export function configDisplay(config) {
72
+ const env = (config.env ?? []).map(([k, v]) => [k, maskSecret(v)]);
73
+ const headers = (config.headers ?? []).map(([k, v]) => [k, maskSecret(v)]);
74
+ const url = config.url !== undefined ? maskUrl(config.url) : undefined;
75
+ const masked = {
76
+ serverName: config.serverName,
77
+ transport: config.transport,
78
+ enabled: config.enabled,
79
+ ...(config.command !== undefined ? { command: config.command } : {}),
80
+ ...(config.args !== undefined ? { args: config.args } : {}),
81
+ ...(config.cwd !== undefined ? { cwd: config.cwd } : {}),
82
+ ...(url !== undefined ? { url } : {}),
83
+ ...(headers.length > 0 ? { headers } : {}),
84
+ ...(env.length > 0 ? { env } : {}),
85
+ };
86
+ return JSON.stringify(masked, null, 2);
87
+ }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The cross-mode comparison model: ONE grid built from every mode's face.
3
+ *
4
+ * The section answers two different questions with one grid. A mode-selected
5
+ * view shows what that mode loads; the comparison shows, for every capability
6
+ * the instance knows, the modes that load it — which is the question "这个工具
7
+ * 会在哪些模式下被加载?" and the reason the mode control exists at all.
8
+ *
9
+ * Two properties make the comparison trustworthy:
10
+ *
11
+ * - A capability's ROW is taken from the deployment default's face when the
12
+ * default mode also has it. Every mode registers its own instance of a tool
13
+ * (its own description, its own channel attribution), and picking whichever
14
+ * mode happened to be read first would make the card's prose depend on roster
15
+ * order. The default mode is the one the human sees everywhere else in the
16
+ * panel, so it wins whenever it can answer.
17
+ * - A mode that could not be read contributes NO modes-list and no rows; it is
18
+ * reported in `unavailable` instead. "Not loaded in this mode" and "this mode
19
+ * could not be read" are different claims, and a union that merged them would
20
+ * quietly understate where a capability is available.
21
+ *
22
+ * Pure over its input, so the unit tests need no renderer.
23
+ * @module @khorsheed/dsh-capability-catalog/client/mode-model
24
+ */
25
+ import type { CatalogModeFace, CatalogPresetOption, CatalogScopedSkillRow, CatalogSkillRow, CatalogToolRow } from '@khorsheed/dsh-capability-catalog/types';
26
+ /** One mode attributed to a capability, as a card's chip renders it. */
27
+ export interface CatalogModeChip {
28
+ readonly id: string;
29
+ /** The preset's display name, falling back to its id. */
30
+ readonly label: string;
31
+ readonly isDefault: boolean;
32
+ }
33
+ /**
34
+ * Resolve the mode ids a capability was found in into chips, in the order the
35
+ * ids arrive (the roster's own read order). An id the roster no longer supplies
36
+ * still renders — its own id is the only label left — because dropping it would
37
+ * hide a mode the comparison actually read.
38
+ * @param ids - mode ids, in roster order.
39
+ * @param options - the roster, for display names and the default marker.
40
+ * @returns one chip per id.
41
+ */
42
+ export declare function resolveModeChips(ids: readonly string[], options: readonly CatalogPresetOption[]): readonly CatalogModeChip[];
43
+ /** One mode's face that could not be read, and why. */
44
+ export interface UnavailableMode {
45
+ readonly preset: string;
46
+ /** The preset's display name, falling back to its id. */
47
+ readonly label: string;
48
+ readonly reason: string;
49
+ }
50
+ /**
51
+ * One managed skill that is delivered NOWHERE: scoped to preset ids no readable
52
+ * mode supplies, or refused by a duplicate-name conflict.
53
+ *
54
+ * These rows are the reason a mode-filtered grid needs a diagnostic surface at
55
+ * all. Every other managed skill is reachable by selecting a mode that loads it;
56
+ * these appear in no mode's face, so filtering alone would make them invisible —
57
+ * and an invisible managed skill cannot be released.
58
+ */
59
+ export interface OrphanManagedSkill {
60
+ readonly name: string;
61
+ readonly description: string;
62
+ readonly modelInvocable: boolean;
63
+ readonly userInvocable: boolean;
64
+ /** The preset ids its frontmatter declares (empty = every preset, i.e. not an orphan). */
65
+ readonly declared: readonly string[];
66
+ /** Declared ids the roster no longer supplies or cannot compose. */
67
+ readonly unreachable: readonly string[];
68
+ /** The default root already supplying this name, when delivery was refused. */
69
+ readonly conflict?: string;
70
+ }
71
+ /**
72
+ * Find the managed skills no readable mode can show.
73
+ *
74
+ * The judgement needs no faces: the delivery status already knows which preset
75
+ * ids a skill declares, which presets the roster supplies, and which of those
76
+ * failed to resolve a standing scope. A skill whose declared ids are ALL
77
+ * unreachable is in no mode's face by construction — and a conflicted one is
78
+ * excluded from delivery entirely, so its managed copy is in no face either.
79
+ *
80
+ * An UNSCOPED managed skill (no declared ids) is deliberately NOT an orphan: the
81
+ * delivery serves it to every preset through the global layer, so every mode
82
+ * shows it. Treating it as one would put a permanent, wrong diagnostic on screen.
83
+ * @param skills - the managed rows (`presetScopeStatus().skills`).
84
+ * @param presets - every preset the roster supplies.
85
+ * @param failedPresets - preset ids whose standing scope could not be resolved.
86
+ * @returns the orphan rows, name-sorted.
87
+ */
88
+ export declare function orphanManagedSkills(skills: readonly CatalogScopedSkillRow[], presets: readonly CatalogPresetOption[], failedPresets: readonly string[]): readonly OrphanManagedSkill[];
89
+ /** The comparison grid: the union of every readable mode, with attribution. */
90
+ export interface ModeComparison {
91
+ /** Union rows, name-sorted, one row per capability name. */
92
+ readonly skills: readonly CatalogSkillRow[];
93
+ readonly tools: readonly CatalogToolRow[];
94
+ /** Capability name → the mode ids that load it, in the order the roster read them. */
95
+ readonly skillModes: ReadonlyMap<string, readonly string[]>;
96
+ readonly toolModes: ReadonlyMap<string, readonly string[]>;
97
+ /** How many faces were in the union. */
98
+ readonly modes: number;
99
+ /** Faces that could not be read; excluded from the union entirely. */
100
+ readonly unavailable: readonly UnavailableMode[];
101
+ }
102
+ /**
103
+ * Fold every mode's face into one comparison grid.
104
+ * @param faces - the faces the host read, in roster order.
105
+ * @returns the union rows, the per-capability mode lists, and the unread modes.
106
+ */
107
+ export declare function buildModeComparison(faces: readonly CatalogModeFace[]): ModeComparison;
108
+ //# sourceMappingURL=mode-model.d.ts.map