@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,372 +0,0 @@
1
- import { useEffect, useState } from 'react';
2
-
3
- import { api } from '@renderer/api';
4
- import { CodeBlockViewer } from '@renderer/components/chat/viewers/CodeBlockViewer';
5
- import { MarkdownViewer } from '@renderer/components/chat/viewers/MarkdownViewer';
6
- import {
7
- AlertDialog,
8
- AlertDialogAction,
9
- AlertDialogCancel,
10
- AlertDialogContent,
11
- AlertDialogDescription,
12
- AlertDialogFooter,
13
- AlertDialogHeader,
14
- AlertDialogTitle,
15
- } from '@renderer/components/ui/alert-dialog';
16
- import { Badge } from '@renderer/components/ui/badge';
17
- import { Button } from '@renderer/components/ui/button';
18
- import {
19
- Dialog,
20
- DialogContent,
21
- DialogDescription,
22
- DialogHeader,
23
- DialogTitle,
24
- } from '@renderer/components/ui/dialog';
25
- import { useStore } from '@renderer/store';
26
- import { formatSkillRootKind, getSkillAudienceLabel } from '@shared/utils/skillRoots';
27
- import { AlertTriangle, ExternalLink, FolderOpen, Info, Pencil, Trash2 } from 'lucide-react';
28
- import { useShallow } from 'zustand/react/shallow';
29
-
30
- import { resolveSkillProjectPath } from './skillProjectUtils';
31
-
32
- import type { SkillValidationIssue } from '@shared/types/extensions';
33
-
34
- interface SkillDetailDialogProps {
35
- skillId: string | null;
36
- open: boolean;
37
- onClose: () => void;
38
- projectPath: string | null;
39
- onEdit: () => void;
40
- onDeleted: () => void;
41
- }
42
-
43
- export const SkillDetailDialog = ({
44
- skillId,
45
- open,
46
- onClose,
47
- projectPath,
48
- onEdit,
49
- onDeleted,
50
- }: SkillDetailDialogProps): React.JSX.Element => {
51
- const fetchSkillDetail = useStore((s) => s.fetchSkillDetail);
52
- const deleteSkill = useStore((s) => s.deleteSkill);
53
- const detail = useStore(useShallow((s) => (skillId ? s.skillsDetailsById[skillId] : undefined)));
54
- const loading = useStore((s) =>
55
- skillId ? (s.skillsDetailLoadingById[skillId] ?? false) : false
56
- );
57
- const detailError = useStore((s) =>
58
- skillId ? (s.skillsDetailErrorById[skillId] ?? null) : null
59
- );
60
- const [deleteLoading, setDeleteLoading] = useState(false);
61
- const [deleteError, setDeleteError] = useState<string | null>(null);
62
- const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
63
-
64
- useEffect(() => {
65
- if (!open || !skillId) return;
66
- void fetchSkillDetail(
67
- skillId,
68
- detail?.item.scope
69
- ? resolveSkillProjectPath(detail.item.scope, projectPath, detail.item.projectRoot)
70
- : (projectPath ?? undefined)
71
- ).catch(() => undefined);
72
- }, [detail?.item.projectRoot, detail?.item.scope, fetchSkillDetail, open, projectPath, skillId]);
73
-
74
- useEffect(() => {
75
- if (!open) {
76
- setDeleteError(null);
77
- setDeleteLoading(false);
78
- setDeleteConfirmOpen(false);
79
- }
80
- }, [open]);
81
-
82
- const item = detail?.item;
83
- const effectiveProjectPath = item
84
- ? resolveSkillProjectPath(item.scope, projectPath, item.projectRoot)
85
- : (projectPath ?? undefined);
86
- const issuesTone = item?.issues.length ? getIssuesTone(item.issues) : null;
87
-
88
- function formatScopeLabel(scope: 'user' | 'project'): string {
89
- return scope === 'project' ? '仅当前项目' : '你的个人技能';
90
- }
91
-
92
- function formatInvocationLabel(invocationMode: 'auto' | 'manual-only'): string {
93
- return invocationMode === 'manual-only' ? '仅在你明确要求时运行。' : '匹配任务时自动运行。';
94
- }
95
-
96
- function getIssuesTone(issues: SkillValidationIssue[]): {
97
- className: string;
98
- title: string;
99
- Icon: typeof AlertTriangle;
100
- } {
101
- const informationalOnly = issues.every((issue) => issue.severity === 'info');
102
- if (informationalOnly) {
103
- return {
104
- className: 'border-blue-500/30 bg-blue-500/5',
105
- title: '此技能包含随附脚本',
106
- Icon: Info,
107
- };
108
- }
109
-
110
- return {
111
- className: 'border-amber-500/30 bg-amber-500/5',
112
- title: '使用前请仔细检查此技能',
113
- Icon: AlertTriangle,
114
- };
115
- }
116
-
117
- async function handleDelete(): Promise<void> {
118
- if (!item) return;
119
- setDeleteLoading(true);
120
- setDeleteError(null);
121
- try {
122
- await deleteSkill({
123
- skillId: item.id,
124
- projectPath: effectiveProjectPath,
125
- });
126
- setDeleteConfirmOpen(false);
127
- onDeleted();
128
- } catch (error) {
129
- setDeleteError(error instanceof Error ? error.message : '删除技能失败');
130
- } finally {
131
- setDeleteLoading(false);
132
- }
133
- }
134
-
135
- return (
136
- <Dialog open={open} onOpenChange={(next) => !next && onClose()}>
137
- <DialogContent className="max-w-4xl">
138
- <DialogHeader>
139
- <DialogTitle>{item?.name ?? '技能详情'}</DialogTitle>
140
- <DialogDescription>
141
- {item?.description ?? '查看已发现的技能元数据和原始说明。'}
142
- </DialogDescription>
143
- </DialogHeader>
144
-
145
- {(loading || (open && skillId && detail === undefined)) && (
146
- <p className="text-sm text-text-muted">正在加载技能详情...</p>
147
- )}
148
-
149
- {!loading && detailError && (
150
- <div className="space-y-3 rounded-md border border-red-500/30 bg-red-500/5 p-4 text-sm text-red-400">
151
- <p>{detailError}</p>
152
- {skillId && (
153
- <Button
154
- variant="outline"
155
- size="sm"
156
- onClick={() => {
157
- void fetchSkillDetail(skillId, effectiveProjectPath).catch(() => undefined);
158
- }}
159
- >
160
- 重试
161
- </Button>
162
- )}
163
- </div>
164
- )}
165
-
166
- {!loading && !detailError && detail === null && (
167
- <div className="rounded-md border border-red-500/30 bg-red-500/5 p-4 text-sm text-red-400">
168
- 无法加载此技能。
169
- </div>
170
- )}
171
-
172
- {!loading && detail && item && (
173
- <div className="space-y-4">
174
- {deleteError && (
175
- <div className="rounded-md border border-red-500/30 bg-red-500/5 p-3 text-sm text-red-400">
176
- {deleteError}
177
- </div>
178
- )}
179
- <div className="flex flex-wrap items-center gap-2">
180
- <Badge variant="outline">{formatScopeLabel(item.scope)}</Badge>
181
- <Badge variant="outline">存储于 {formatSkillRootKind(item.rootKind)}</Badge>
182
- <Badge variant="outline">{getSkillAudienceLabel(item.rootKind)}</Badge>
183
- <Badge variant="secondary">
184
- {item.invocationMode === 'manual-only' ? '手动使用' : '自动使用'}
185
- </Badge>
186
- {item.flags.hasScripts && <Badge variant="destructive">包含脚本</Badge>}
187
- {item.flags.hasReferences && <Badge variant="secondary">参考资料</Badge>}
188
- {item.flags.hasAssets && <Badge variant="secondary">资源文件</Badge>}
189
- </div>
190
-
191
- {item.issues.length > 0 && (
192
- <div className={`space-y-2 rounded-md border p-4 ${issuesTone?.className ?? ''}`}>
193
- <p
194
- className={`text-sm font-medium ${
195
- issuesTone?.Icon === Info
196
- ? 'text-blue-700 dark:text-blue-300'
197
- : 'text-amber-700 dark:text-amber-300'
198
- }`}
199
- >
200
- {issuesTone?.title}
201
- </p>
202
- {item.issues.map((issue, index) => (
203
- <div
204
- key={`${issue.code}-${index}`}
205
- className={`flex gap-2 text-sm ${
206
- issue.severity === 'info'
207
- ? 'text-blue-700 dark:text-blue-300'
208
- : 'text-amber-700 dark:text-amber-300'
209
- }`}
210
- >
211
- {issue.severity === 'info' ? (
212
- <Info className="mt-0.5 size-4 shrink-0" />
213
- ) : (
214
- <AlertTriangle className="mt-0.5 size-4 shrink-0" />
215
- )}
216
- <span>{issue.message}</span>
217
- </div>
218
- ))}
219
- </div>
220
- )}
221
-
222
- <div className="grid gap-3 rounded-lg border border-border p-4 md:grid-cols-3">
223
- <div className="space-y-1">
224
- <p className="text-xs font-medium uppercase tracking-wide text-text-muted">
225
- 谁可以使用
226
- </p>
227
- <p className="text-sm text-text">{formatScopeLabel(item.scope)}</p>
228
- </div>
229
- <div className="space-y-1">
230
- <p className="text-xs font-medium uppercase tracking-wide text-text-muted">
231
- 如何使用
232
- </p>
233
- <p className="text-sm text-text">{formatInvocationLabel(item.invocationMode)}</p>
234
- </div>
235
- <div className="space-y-1">
236
- <p className="text-xs font-medium uppercase tracking-wide text-text-muted">
237
- 随附内容
238
- </p>
239
- <p className="text-sm text-text">
240
- {[
241
- item.flags.hasReferences ? '参考资料' : null,
242
- item.flags.hasScripts ? '脚本' : null,
243
- item.flags.hasAssets ? '资源文件' : null,
244
- ]
245
- .filter(Boolean)
246
- .join('、') || '仅技能说明'}
247
- </p>
248
- </div>
249
- </div>
250
-
251
- <div className="flex flex-wrap gap-2">
252
- <Button variant="secondary" size="sm" onClick={onEdit}>
253
- <Pencil className="mr-1.5 size-3.5" />
254
- 编辑技能
255
- </Button>
256
- <Button
257
- variant="outline"
258
- size="sm"
259
- onClick={() => setDeleteConfirmOpen(true)}
260
- disabled={deleteLoading}
261
- >
262
- <Trash2 className="mr-1.5 size-3.5" />
263
- {deleteLoading ? '正在删除...' : '删除'}
264
- </Button>
265
- </div>
266
-
267
- <div className="grid gap-4 xl:grid-cols-[minmax(0,1fr)_320px]">
268
- <div className="min-w-0 rounded-lg border border-border p-4">
269
- <MarkdownViewer
270
- content={detail.body || detail.rawContent}
271
- baseDir={item.skillDir}
272
- bare
273
- copyable
274
- />
275
- </div>
276
-
277
- <div className="space-y-4">
278
- <div className="rounded-lg border border-border p-3 text-sm text-text-secondary">
279
- <div className="space-y-2">
280
- <p className="font-medium text-text">存储位置</p>
281
- <p className="break-all text-xs text-text-muted">{item.skillDir}</p>
282
- </div>
283
-
284
- {detail.scriptFiles.length > 0 && (
285
- <div className="mt-4 space-y-1">
286
- <p className="font-medium text-text">脚本</p>
287
- {detail.scriptFiles.map((file) => (
288
- <p key={file} className="text-xs text-text-muted">
289
- {file}
290
- </p>
291
- ))}
292
- </div>
293
- )}
294
-
295
- {detail.referencesFiles.length > 0 && (
296
- <div className="mt-4 space-y-1">
297
- <p className="font-medium text-text">参考资料</p>
298
- {detail.referencesFiles.map((file) => (
299
- <p key={file} className="text-xs text-text-muted">
300
- {file}
301
- </p>
302
- ))}
303
- </div>
304
- )}
305
-
306
- {detail.assetFiles.length > 0 && (
307
- <div className="mt-4 space-y-1">
308
- <p className="font-medium text-text">资源文件</p>
309
- {detail.assetFiles.map((file) => (
310
- <p key={file} className="text-xs text-text-muted">
311
- {file}
312
- </p>
313
- ))}
314
- </div>
315
- )}
316
- </div>
317
-
318
- <details className="rounded-lg border border-border p-3 text-sm text-text-secondary">
319
- <summary className="cursor-pointer font-medium text-text">高级文件详情</summary>
320
- <div className="mt-3 space-y-3">
321
- <div className="flex flex-wrap gap-2">
322
- <Button
323
- variant="outline"
324
- size="sm"
325
- onClick={() => void api.showInFolder(item.skillFile)}
326
- >
327
- <FolderOpen className="mr-1.5 size-3.5" />
328
- 打开文件夹
329
- </Button>
330
- <Button
331
- variant="outline"
332
- size="sm"
333
- onClick={() => void api.openPath(item.skillFile, effectiveProjectPath)}
334
- >
335
- <ExternalLink className="mr-1.5 size-3.5" />
336
- 打开 SKILL.md
337
- </Button>
338
- </div>
339
- <CodeBlockViewer
340
- fileName={item.skillFile}
341
- content={detail.rawContent}
342
- maxHeight="max-h-72"
343
- />
344
- </div>
345
- </details>
346
- </div>
347
- </div>
348
- </div>
349
- )}
350
- </DialogContent>
351
-
352
- <AlertDialog open={deleteConfirmOpen} onOpenChange={setDeleteConfirmOpen}>
353
- <AlertDialogContent>
354
- <AlertDialogHeader>
355
- <AlertDialogTitle>删除技能?</AlertDialogTitle>
356
- <AlertDialogDescription>
357
- {item
358
- ? `删除“${item.name}”并移入废纸篓?需要时可以稍后从废纸篓恢复。`
359
- : '删除此技能并移入废纸篓?'}
360
- </AlertDialogDescription>
361
- </AlertDialogHeader>
362
- <AlertDialogFooter>
363
- <AlertDialogCancel disabled={deleteLoading}>取消</AlertDialogCancel>
364
- <AlertDialogAction onClick={() => void handleDelete()} disabled={deleteLoading}>
365
- {deleteLoading ? '正在删除...' : '删除技能'}
366
- </AlertDialogAction>
367
- </AlertDialogFooter>
368
- </AlertDialogContent>
369
- </AlertDialog>
370
- </Dialog>
371
- );
372
- };