@yancyyu/openhermit 1.6.36 → 1.6.38

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 (91) hide show
  1. package/dist-renderer/assets/{ProjectEditorOverlay-B_QAoeaA.js → ProjectEditorOverlay-lJZi-9Hp.js} +1 -1
  2. package/dist-renderer/assets/{TeamGraphOverlay-PB9luAZU.js → TeamGraphOverlay-ZEDfZyHb.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-Dfzcp_Ry.js → _basePickBy-CIhniz70.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-B5u2Yiq2.js → _baseUniq-cKAW4Q8I.js} +1 -1
  5. package/dist-renderer/assets/{arc-DElOI7qz.js → arc-YmNsoDXW.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-Cf6f4tCu.js → architectureDiagram-VXUJARFQ-DHEls2sX.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-FJUdo9Ry.js → blockDiagram-VD42YOAC-Bpwf1Sbg.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-BvJQS9lb.js → c4Diagram-YG6GDRKO-B0IaQ4w5.js} +1 -1
  9. package/dist-renderer/assets/channel-yIlSKy0e.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-n-SGLbin.js → chunk-4BX2VUAB-DLk-hcFc.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-Dwle9tlA.js → chunk-55IACEB6-1XRmX_Zm.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-Dic8YxQz.js → chunk-B4BG7PRW-1waH1DAD.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-3n5jC1jk.js → chunk-DI55MBZ5-BqpZBtrN.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-BqizUB3O.js → chunk-FMBD7UC4-Bly7vVym.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-JRDmD8o9.js → chunk-QN33PNHL-Ci2QWBAs.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-BxFpQw92.js → chunk-QZHKN3VN-YCqFW7d-.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-ByqPwtW9.js → chunk-TZMSLE5B-B0xGXInl.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +1 -0
  20. package/dist-renderer/assets/clone-BTNuUva-.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-CVztr86T.js → cose-bilkent-S5V4N54A-DxcFNQKT.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-CIui920O.js → dagre-6UL2VRFP-DPo_RfZY.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-CyL8-bgb.js → diagram-PSM6KHXK-U3hQsFe4.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-CM_67YoY.js → diagram-QEK2KX5R-OrwrAy0V.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-DtrtPSGg.js → diagram-S2PKOQOG-CXATPWVw.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-bOICzF9d.js → erDiagram-Q2GNP2WA-B0e8AfMF.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CJV1g9Hr.js → flowDiagram-NV44I4VS-CXfzA4jJ.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CXbhDo09.js → ganttDiagram-JELNMOA3-CMr08qVl.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vbXopTpS.js → gitGraphDiagram-V2S2FVAM-vYFHpPmy.js} +1 -1
  30. package/dist-renderer/assets/{graph-CY2T-j4q.js → graph-DOe5j8dH.js} +1 -1
  31. package/dist-renderer/assets/{index-Dv7q-OB0.js → index-B2Dy7M2G.js} +1 -1
  32. package/dist-renderer/assets/index-Bi6nrZ4z.css +1 -0
  33. package/dist-renderer/assets/{index-CpyChjme.js → index-BySQS7AB.js} +1 -1
  34. package/dist-renderer/assets/{index-S-i9egm8.js → index-C_okzZXP.js} +1 -1
  35. package/dist-renderer/assets/{index-Mrh4pTHw.js → index-CzWxVCRL.js} +1 -1
  36. package/dist-renderer/assets/{index-Dn-BpzSm.js → index-V7dAKPqd.js} +571 -607
  37. package/dist-renderer/assets/{index-C9ONRXVI.js → index-VJ-MM9xa.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-BNg14AdU.js → infoDiagram-HS3SLOUP-D_WubR0B.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-2_PkPCiu.js → journeyDiagram-XKPGCS4Q-w9ca-1TI.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-DjTx7qoU.js → kanban-definition-3W4ZIXB7-Jg9p6_pN.js} +1 -1
  41. package/dist-renderer/assets/{layout-DZlHGGN0.js → layout-B-z3y17c.js} +1 -1
  42. package/dist-renderer/assets/{linear-DnlOm48z.js → linear-D-RTX5UW.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-B-nrgt7V.js → mindmap-definition-VGOIOE7T-CDQmHOYP.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-BToJFvWR.js → pieDiagram-ADFJNKIX-D_odsQL7.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-C0qoxXvH.js → quadrantDiagram-AYHSOK5B-BRsmYWSA.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-DCKGwsGN.js → requirementDiagram-UZGBJVZJ-ChNE_BOV.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-CS6JCcu7.js → sankeyDiagram-TZEHDZUN-C8FtpwKc.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-C9pAWoSR.js → sequenceDiagram-WL72ISMW-DmLCzNcc.js} +1 -1
  49. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-BTTX_v1m.js → stateDiagram-FKZM4ZOC-WJBm4bhu.js} +1 -1
  50. package/dist-renderer/assets/{stateDiagram-v2-4FDKWEC3-BHk97lQJ.js → stateDiagram-v2-4FDKWEC3-_m6iPPUR.js} +1 -1
  51. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-CSWCEzCQ.js → timeline-definition-IT6M3QCI-BXs_hOJs.js} +1 -1
  52. package/dist-renderer/assets/{treemap-GDKQZRPO-CmiIc68g.js → treemap-GDKQZRPO-o04MA0G9.js} +1 -1
  53. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-DhwSTphI.js → xychartDiagram-PRI3JC2R-Czj69XRd.js} +1 -1
  54. package/dist-renderer/index.html +2 -2
  55. package/package.json +2 -2
  56. package/src/main/ipc/extensions.ts +29 -50
  57. package/src/main/server.ts +17 -26
  58. package/src/main/services/extensions/ExtensionFacadeService.ts +2 -51
  59. package/src/main/services/extensions/library/McpLibraryService.ts +243 -0
  60. package/src/main/services/session-intelligence/UsageTelemetryService.ts +14 -1
  61. package/src/main/services/teams-mvp/TaskDispatchService.ts +32 -7
  62. package/src/renderer/api/httpClient.ts +108 -22
  63. package/src/renderer/components/extensions/ExtensionStoreView.tsx +6 -96
  64. package/src/renderer/components/extensions/plugins/PluginCard.tsx +8 -0
  65. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +13 -8
  66. package/src/renderer/components/team/TeamDetailView.tsx +15 -0
  67. package/src/renderer/components/team/tools/AddMcpInline.tsx +47 -0
  68. package/src/renderer/components/team/tools/AddSkillInline.tsx +61 -0
  69. package/src/renderer/components/team/tools/McpChip.tsx +42 -0
  70. package/src/renderer/components/team/tools/SkillChip.tsx +35 -0
  71. package/src/renderer/components/team/tools/ToolsSection.tsx +208 -0
  72. package/src/shared/types/extensions/api.ts +9 -0
  73. package/src/shared/types/extensions/index.ts +4 -0
  74. package/src/shared/types/extensions/mcp.ts +41 -0
  75. package/src/shared/utils/extensionNormalizers.ts +22 -0
  76. package/dist-renderer/assets/channel-DnbgZg0A.js +0 -1
  77. package/dist-renderer/assets/classDiagram-2ON5EDUG-BAD4p014.js +0 -1
  78. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BAD4p014.js +0 -1
  79. package/dist-renderer/assets/clone-CRX5ZTPd.js +0 -1
  80. package/dist-renderer/assets/index-B2z_IyRH.css +0 -1
  81. package/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +0 -190
  82. package/src/main/services/extensions/catalog/McpCatalogAggregator.ts +0 -150
  83. package/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +0 -381
  84. package/src/main/services/extensions/install/McpInstallService.ts +0 -407
  85. package/src/main/services/extensions/state/McpInstallationStateService.ts +0 -42
  86. package/src/renderer/components/extensions/mcp/McpServerCard.tsx +0 -314
  87. package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +0 -765
  88. package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +0 -593
  89. package/src/renderer/components/extensions/skills/SkillDetailDialog.tsx +0 -372
  90. package/src/renderer/components/extensions/skills/SkillImportDialog.tsx +0 -343
  91. package/src/renderer/components/extensions/skills/SkillsPanel.tsx +0 -659
@@ -1,343 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- import { api } from '@renderer/api';
4
- import { Button } from '@renderer/components/ui/button';
5
- import {
6
- Dialog,
7
- DialogContent,
8
- DialogDescription,
9
- DialogFooter,
10
- DialogHeader,
11
- DialogTitle,
12
- } from '@renderer/components/ui/dialog';
13
- import { Input } from '@renderer/components/ui/input';
14
- import { Label } from '@renderer/components/ui/label';
15
- import {
16
- Select,
17
- SelectContent,
18
- SelectItem,
19
- SelectTrigger,
20
- SelectValue,
21
- } from '@renderer/components/ui/select';
22
- import { useStore } from '@renderer/store';
23
- import { SKILL_ROOT_DEFINITIONS } from '@shared/utils/skillRoots';
24
- import { FileSearch, FolderOpen, X } from 'lucide-react';
25
-
26
- import { getSuggestedSkillFolderNameFromPath } from './skillFolderNameUtils';
27
- import { resolveSkillProjectPath } from './skillProjectUtils';
28
- import { SkillReviewDialog } from './SkillReviewDialog';
29
- import { validateSkillFolderName, validateSkillImportSourceDir } from './skillValidationUtils';
30
-
31
- import type { SkillReviewPreview, SkillRootKind } from '@shared/types/extensions';
32
-
33
- function getFriendlyImportError(message: string): string {
34
- if (message.includes('valid skill file')) {
35
- return '这个文件夹还不像一个技能目录。需要包含 SKILL.md、Skill.md 或 skill.md 文件。';
36
- }
37
- if (message.includes('symbolic links')) {
38
- return '此文件夹包含符号链接。请导入真实文件,而不是链接。';
39
- }
40
- if (message.includes('too many files')) {
41
- return '这个技能文件夹文件过多,无法一次导入。请移除多余文件后重试。';
42
- }
43
- if (message.includes('too large')) {
44
- return '这个技能文件夹过大,无法安全导入。请精简大型素材后重试。';
45
- }
46
- if (message.includes('Invalid folder name')) {
47
- return '请选择更简单的目标文件夹名称,可使用字母、数字、点、短横线或下划线。';
48
- }
49
- if (message.includes('must be a directory')) {
50
- return '请选择要导入的文件夹,而不是单个文件。';
51
- }
52
- return message;
53
- }
54
-
55
- interface SkillImportDialogProps {
56
- open: boolean;
57
- projectPath: string | null;
58
- projectLabel: string | null;
59
- onClose: () => void;
60
- onImported: (skillId: string | null) => void;
61
- }
62
-
63
- export const SkillImportDialog = ({
64
- open,
65
- projectPath,
66
- projectLabel,
67
- onClose,
68
- onImported,
69
- }: SkillImportDialogProps): React.JSX.Element => {
70
- const previewSkillImport = useStore((s) => s.previewSkillImport);
71
- const applySkillImport = useStore((s) => s.applySkillImport);
72
-
73
- const [sourceDir, setSourceDir] = useState('');
74
- const [folderName, setFolderName] = useState('');
75
- const [folderNameEdited, setFolderNameEdited] = useState(false);
76
- const [scope, setScope] = useState<'user' | 'project'>('user');
77
- const [rootKind, setRootKind] = useState<SkillRootKind>('hermit');
78
- const [preview, setPreview] = useState<SkillReviewPreview | null>(null);
79
- const [reviewOpen, setReviewOpen] = useState(false);
80
- const [reviewLoading, setReviewLoading] = useState(false);
81
- const [importLoading, setImportLoading] = useState(false);
82
- const [mutationError, setMutationError] = useState<string | null>(null);
83
-
84
- useEffect(() => {
85
- if (!open) return;
86
- setSourceDir('');
87
- setFolderName('');
88
- setFolderNameEdited(false);
89
- setScope(projectPath ? 'project' : 'user');
90
- setRootKind(projectPath ? 'claude' : 'hermit');
91
- setPreview(null);
92
- setReviewOpen(false);
93
- setReviewLoading(false);
94
- setImportLoading(false);
95
- setMutationError(null);
96
- }, [open, projectPath]);
97
-
98
- useEffect(() => {
99
- if (open) {
100
- return;
101
- }
102
-
103
- setPreview(null);
104
- setReviewOpen(false);
105
- setReviewLoading(false);
106
- setImportLoading(false);
107
- setMutationError(null);
108
- }, [open]);
109
-
110
- useEffect(() => {
111
- if (!open || folderNameEdited) {
112
- return;
113
- }
114
- setFolderName(sourceDir.trim() ? getSuggestedSkillFolderNameFromPath(sourceDir) : '');
115
- }, [folderNameEdited, open, sourceDir]);
116
-
117
- useEffect(() => {
118
- if (open && scope === 'project' && !projectPath) {
119
- setScope('user');
120
- }
121
- }, [open, projectPath, scope]);
122
-
123
- useEffect(() => {
124
- if (open && scope === 'user' && rootKind !== 'hermit') {
125
- setRootKind('hermit');
126
- } else if (open && scope === 'project' && rootKind === 'hermit') {
127
- setRootKind('claude');
128
- }
129
- }, [open, rootKind, scope]);
130
-
131
- const visibleRootDefinitions =
132
- scope === 'user'
133
- ? SKILL_ROOT_DEFINITIONS.filter((definition) => definition.rootKind === 'hermit')
134
- : SKILL_ROOT_DEFINITIONS.filter((definition) => definition.rootKind !== 'hermit');
135
-
136
- async function handleChooseFolder(): Promise<void> {
137
- const selected = await api.config.selectFolders();
138
- const first = selected[0];
139
- if (!first) return;
140
- setSourceDir(first);
141
- }
142
-
143
- async function handleReview(): Promise<void> {
144
- const normalizedSourceDir = sourceDir.trim();
145
- const normalizedFolderName = folderName.trim();
146
- const sourceDirError = validateSkillImportSourceDir(sourceDir);
147
- if (sourceDirError) {
148
- setMutationError(sourceDirError);
149
- return;
150
- }
151
-
152
- const folderNameError =
153
- normalizedFolderName.length > 0 ? validateSkillFolderName(normalizedFolderName) : null;
154
- if (folderNameError) {
155
- setMutationError(folderNameError);
156
- return;
157
- }
158
-
159
- setReviewLoading(true);
160
- setMutationError(null);
161
- try {
162
- const nextPreview = await previewSkillImport({
163
- sourceDir: normalizedSourceDir,
164
- folderName: normalizedFolderName || undefined,
165
- scope,
166
- rootKind,
167
- projectPath: resolveSkillProjectPath(scope, projectPath),
168
- });
169
- setPreview(nextPreview);
170
- setReviewOpen(true);
171
- } catch (error) {
172
- setMutationError(
173
- getFriendlyImportError(error instanceof Error ? error.message : '检查导入变更失败')
174
- );
175
- } finally {
176
- setReviewLoading(false);
177
- }
178
- }
179
-
180
- async function handleConfirmImport(): Promise<void> {
181
- const normalizedSourceDir = sourceDir.trim();
182
- const normalizedFolderName = folderName.trim();
183
-
184
- setImportLoading(true);
185
- setMutationError(null);
186
- try {
187
- const detail = await applySkillImport({
188
- sourceDir: normalizedSourceDir,
189
- folderName: normalizedFolderName || undefined,
190
- scope,
191
- rootKind,
192
- projectPath: resolveSkillProjectPath(scope, projectPath),
193
- reviewPlanId: preview?.planId,
194
- });
195
- setReviewOpen(false);
196
- onImported(detail?.item.id ?? null);
197
- onClose();
198
- } catch (error) {
199
- setMutationError(
200
- getFriendlyImportError(error instanceof Error ? error.message : '导入技能失败')
201
- );
202
- } finally {
203
- setImportLoading(false);
204
- }
205
- }
206
-
207
- return (
208
- <>
209
- <Dialog open={open} onOpenChange={(next) => !next && onClose()}>
210
- <DialogContent className="gap-0 overflow-hidden p-0">
211
- <div className="flex max-h-[85vh] min-h-0 flex-col">
212
- <DialogHeader className="border-b border-border px-6 py-5">
213
- <DialogTitle>导入技能</DialogTitle>
214
- <DialogDescription>
215
- 选择已有技能文件夹,检查将要复制的内容,然后导入到支持的技能位置。
216
- </DialogDescription>
217
- </DialogHeader>
218
-
219
- <div className="min-h-0 flex-1 overflow-y-auto px-6 py-5">
220
- <div className="space-y-5">
221
- <section className="space-y-1">
222
- <h3 className="text-sm font-semibold text-text">1. 选择技能文件夹</h3>
223
- <p className="text-sm text-text-muted">
224
- 请选择已包含 `SKILL.md`、`Skill.md` 或 `skill.md` 文件的文件夹。
225
- </p>
226
- </section>
227
- <div className="space-y-2">
228
- <Label htmlFor="skill-import-source">源文件夹</Label>
229
- <div className="flex gap-2">
230
- <Input
231
- id="skill-import-source"
232
- value={sourceDir}
233
- onChange={(event) => setSourceDir(event.target.value)}
234
- />
235
- <Button variant="outline" onClick={() => void handleChooseFolder()}>
236
- <FolderOpen className="mr-1.5 size-3.5" />
237
- 浏览
238
- </Button>
239
- </div>
240
- </div>
241
-
242
- <div className="space-y-2">
243
- <Label htmlFor="skill-import-folder">目标文件夹名称</Label>
244
- <Input
245
- id="skill-import-folder"
246
- value={folderName}
247
- onChange={(event) => {
248
- setFolderNameEdited(true);
249
- setFolderName(event.target.value);
250
- }}
251
- placeholder="默认使用源文件夹名称"
252
- />
253
- </div>
254
-
255
- <section className="space-y-1">
256
- <h3 className="text-sm font-semibold text-text">2. 选择存放位置</h3>
257
- <p className="text-sm text-text-muted">
258
- 个人技能会在所有地方生效;项目技能只会出现在一个代码库中。
259
- </p>
260
- </section>
261
- <div className="grid gap-3 md:grid-cols-2">
262
- <div className="space-y-2">
263
- <Label htmlFor="skill-import-scope">谁可以使用</Label>
264
- <Select
265
- value={scope}
266
- onValueChange={(value) => setScope(value as 'user' | 'project')}
267
- >
268
- <SelectTrigger id="skill-import-scope">
269
- <SelectValue />
270
- </SelectTrigger>
271
- <SelectContent>
272
- <SelectItem value="user">个人</SelectItem>
273
- <SelectItem value="project" disabled={!projectPath}>
274
- {projectPath ? `项目:${projectLabel ?? projectPath}` : '项目不可用'}
275
- </SelectItem>
276
- </SelectContent>
277
- </Select>
278
- </div>
279
-
280
- <div className="space-y-2">
281
- <Label htmlFor="skill-import-root">存储位置</Label>
282
- <Select
283
- value={rootKind}
284
- onValueChange={(value) => setRootKind(value as SkillRootKind)}
285
- >
286
- <SelectTrigger id="skill-import-root">
287
- <SelectValue />
288
- </SelectTrigger>
289
- <SelectContent>
290
- {visibleRootDefinitions.map((definition) => (
291
- <SelectItem key={definition.rootKind} value={definition.rootKind}>
292
- {definition.rootKind === 'hermit'
293
- ? '~/.hermit/skills'
294
- : `${definition.directoryName}/skills`}
295
- </SelectItem>
296
- ))}
297
- </SelectContent>
298
- </Select>
299
- </div>
300
- </div>
301
-
302
- {mutationError && (
303
- <div className="rounded-md border border-red-500/30 bg-red-500/5 p-3 text-sm text-red-400">
304
- {mutationError}
305
- </div>
306
- )}
307
- </div>
308
- </div>
309
-
310
- <div className="sticky bottom-0 z-10 flex flex-wrap items-center gap-3 border-t border-border bg-surface px-6 py-4 shadow-[0_-8px_24px_rgba(0,0,0,0.08)]">
311
- <Button variant="outline" onClick={onClose}>
312
- <X className="mr-1.5 size-3.5" />
313
- 取消
314
- </Button>
315
- <p className="min-w-64 flex-1 text-sm text-text-muted">
316
- 请先检查复制的文件,然后在下一步确认导入。
317
- </p>
318
- <Button
319
- onClick={() => void handleReview()}
320
- disabled={!sourceDir.trim() || reviewLoading || importLoading}
321
- >
322
- <FileSearch className="mr-1.5 size-3.5" />
323
- {reviewLoading ? '准备中...' : '检查并导入'}
324
- </Button>
325
- </div>
326
- </div>
327
- </DialogContent>
328
- </Dialog>
329
-
330
- <SkillReviewDialog
331
- open={reviewOpen}
332
- preview={preview}
333
- loading={importLoading}
334
- error={mutationError}
335
- onClose={() => setReviewOpen(false)}
336
- onConfirm={() => void handleConfirmImport()}
337
- confirmLabel="导入技能"
338
- reviewLabel="正在导入此技能"
339
- backLabel="返回导入"
340
- />
341
- </>
342
- );
343
- };