@yancyyu/openhermit 1.6.38 → 1.6.40
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/dist-renderer/assets/ProjectEditorOverlay-CemDOX-3.js +58 -0
- package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-hPY770Db.js} +1 -1
- package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-BHHrJT1i.js} +1 -1
- package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CWErBtke.js} +1 -1
- package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-C_o2_Uv8.js} +1 -1
- package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-DUW0LI3t.js} +1 -1
- package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-CWbCE9hQ.js} +1 -1
- package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-BjLadrfV.js} +1 -1
- package/dist-renderer/assets/channel-DyP9YlCF.js +1 -0
- package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-CPnvjZl9.js} +1 -1
- package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-OlL47yXQ.js} +1 -1
- package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-DTasjbm8.js} +1 -1
- package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-C5_Xaqkk.js} +1 -1
- package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-NdoM4DMR.js} +1 -1
- package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-C8Fybejy.js} +1 -1
- package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-E98TYFXJ.js} +1 -1
- package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-h4lFgkIq.js} +1 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-BqffFTae.js +1 -0
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BqffFTae.js +1 -0
- package/dist-renderer/assets/clone-MPcKWs2O.js +1 -0
- package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-DtQ7fkrs.js} +1 -1
- package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-CN-nL_z4.js} +1 -1
- package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DVJtqmm-.js} +1 -1
- package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-DlxHxyXh.js} +1 -1
- package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-7dpzO6x6.js} +1 -1
- package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-GP1TqsHi.js} +1 -1
- package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-C7ZLETuH.js} +1 -1
- package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-CvPB68dH.js} +1 -1
- package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5yOm3w7.js} +1 -1
- package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-smeyY1YZ.js} +1 -1
- package/dist-renderer/assets/{index-BySQS7AB.js → index-BJx8XvG1.js} +1 -1
- package/dist-renderer/assets/{index-C_okzZXP.js → index-CQaXUAua.js} +1 -1
- package/dist-renderer/assets/{index-VJ-MM9xa.js → index-CajRpxO2.js} +1 -1
- package/dist-renderer/assets/{index-V7dAKPqd.js → index-ChG4rE-E.js} +587 -705
- package/dist-renderer/assets/index-DUd0uw9C.css +32 -0
- package/dist-renderer/assets/{index-CzWxVCRL.js → index-IhmXZWqf.js} +1 -1
- package/dist-renderer/assets/{index-B2Dy7M2G.js → index-x_JkoDRH.js} +1 -1
- package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-D-hWRQGY.js} +1 -1
- package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-Bb6W8rUG.js} +1 -1
- package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-CnHdUX0q.js} +1 -1
- package/dist-renderer/assets/{layout-B-z3y17c.js → layout-pqss_zkI.js} +1 -1
- package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-B1mFITNh.js} +1 -1
- package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-DTD9q7-D.js} +1 -1
- package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-Df3mhrn7.js} +1 -1
- package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-B1FZ09vH.js} +1 -1
- package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-aEO78thZ.js} +1 -1
- package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-6Ui--jp-.js} +1 -1
- package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-DF4Q1cAM.js} +1 -1
- package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
- package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-BqA2BI8C.js} +1 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Cs2ZtUD2.js +1 -0
- package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DoOkw_A8.js} +1 -1
- package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DUe26QdD.js} +1 -1
- package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-BKCnj5Xn.js} +1 -1
- package/dist-renderer/index.html +20 -53
- package/package.json +25 -18
- package/src/main/ipc/extensions.ts +2 -1
- package/src/main/server.ts +873 -221
- package/src/main/services/extensions/ExtensionFacadeService.ts +2 -5
- package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
- package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
- package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
- package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
- package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
- package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
- package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
- package/src/main/services/teams-mvp/TaskDispatchService.ts +5 -6
- package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
- package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
- package/src/main/utils/teamProjectResolution.ts +15 -0
- package/src/renderer/App.tsx +8 -4
- package/src/renderer/api/httpClient.ts +68 -18
- package/src/renderer/api/providers.ts +23 -2
- package/src/renderer/assets/participant-avatars/01.svg +3 -0
- package/src/renderer/assets/participant-avatars/02.svg +3 -0
- package/src/renderer/assets/participant-avatars/03.svg +3 -0
- package/src/renderer/assets/participant-avatars/04.svg +3 -0
- package/src/renderer/assets/participant-avatars/05.svg +3 -0
- package/src/renderer/assets/participant-avatars/06.svg +3 -0
- package/src/renderer/assets/participant-avatars/07.svg +3 -0
- package/src/renderer/assets/participant-avatars/08.svg +3 -0
- package/src/renderer/assets/participant-avatars/09.svg +3 -0
- package/src/renderer/assets/participant-avatars/10.svg +3 -0
- package/src/renderer/assets/participant-avatars/11.svg +3 -0
- package/src/renderer/assets/participant-avatars/12.svg +3 -0
- package/src/renderer/assets/participant-avatars/13.svg +3 -0
- package/src/renderer/components/chat/ChatHistoryItem.tsx +1 -1
- package/src/renderer/components/chat/items/SubagentItem.tsx +2 -2
- package/src/renderer/components/chat/viewers/MermaidDiagram.tsx +2 -2
- package/src/renderer/components/common/ErrorBoundary.tsx +1 -1
- package/src/renderer/components/common/TerminalPane.tsx +213 -0
- package/src/renderer/components/dashboard/CliStatusBanner.tsx +7 -7
- package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
- package/src/renderer/components/extensions/ExtensionStoreView.tsx +7 -126
- package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
- package/src/renderer/components/extensions/common/ExtensionToast.tsx +3 -3
- package/src/renderer/components/extensions/common/SourceBadge.tsx +1 -1
- package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
- package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
- package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
- package/src/renderer/components/extensions/plugins/CategoryChips.tsx +1 -1
- package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
- package/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx +2 -2
- package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
- package/src/renderer/components/extensions/skills/SkillEditorDialog.tsx +1 -1
- package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
- package/src/renderer/components/layout/PaneContent.tsx +8 -1
- package/src/renderer/components/layout/PaneResizeHandle.tsx +2 -2
- package/src/renderer/components/layout/Sidebar.tsx +13 -56
- package/src/renderer/components/layout/SortableTab.tsx +22 -33
- package/src/renderer/components/layout/TabBar.tsx +1 -1
- package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
- package/src/renderer/components/report/sections/CostSection.tsx +2 -2
- package/src/renderer/components/report/sections/InsightsSection.tsx +1 -1
- package/src/renderer/components/runtime/ProviderRuntimeBackendSelector.tsx +2 -2
- package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
- package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
- package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
- package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
- package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
- package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
- package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
- package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
- package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
- package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
- package/src/renderer/components/schedules/calendar/index.ts +2 -0
- package/src/renderer/components/schedules/calendar/types.ts +44 -0
- package/src/renderer/components/search/CommandPalette.tsx +4 -4
- package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
- package/src/renderer/components/settings/SettingsView.tsx +30 -35
- package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
- package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
- package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
- package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
- package/src/renderer/components/settings/sections/CliStatusSection.tsx +72 -113
- package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
- package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
- package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
- package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
- package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
- package/src/renderer/components/settings/sections/index.ts +0 -1
- package/src/renderer/components/sidebar/SessionFiltersPopover.tsx +1 -1
- package/src/renderer/components/sidebar/SessionItem.tsx +3 -3
- package/src/renderer/components/sidebar/SidebarSessions.tsx +184 -6
- package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
- package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +40 -5
- package/src/renderer/components/splash/splashScene.ts +121 -929
- package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
- package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
- package/src/renderer/components/tasks/TasksView.tsx +112 -134
- package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
- package/src/renderer/components/team/ClaudeLogsFilterPopover.tsx +1 -1
- package/src/renderer/components/team/ClaudeLogsPanel.tsx +1 -1
- package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
- package/src/renderer/components/team/ProcessesSection.tsx +2 -2
- package/src/renderer/components/team/TaskTooltip.tsx +2 -2
- package/src/renderer/components/team/TeamDetailView.tsx +319 -123
- package/src/renderer/components/team/TeamListFilterPopover.tsx +1 -1
- package/src/renderer/components/team/TeamListView.tsx +109 -124
- package/src/renderer/components/team/TeamSessionsSection.tsx +6 -6
- package/src/renderer/components/team/UnreadCommentsBadge.tsx +1 -1
- package/src/renderer/components/team/activity/ActivityItem.tsx +9 -9
- package/src/renderer/components/team/activity/ActivityTimeline.tsx +5 -5
- package/src/renderer/components/team/activity/LeadThoughtsGroup.tsx +3 -3
- package/src/renderer/components/team/activity/ReplyQuoteBlock.tsx +4 -4
- package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +4 -4
- package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
- package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
- package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
- package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +18 -16
- package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
- package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +8 -1
- package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +5 -5
- package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
- package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +6 -6
- package/src/renderer/components/team/dialogs/SkipPermissionsCheckbox.tsx +6 -6
- package/src/renderer/components/team/dialogs/StatusHistoryTimeline.tsx +1 -1
- package/src/renderer/components/team/dialogs/TaskAttachments.tsx +1 -1
- package/src/renderer/components/team/dialogs/TaskCommentInput.tsx +6 -6
- package/src/renderer/components/team/dialogs/TaskCommentsSection.tsx +4 -4
- package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +3 -3
- package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
- package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
- package/src/renderer/components/team/editor/EditorFileTree.tsx +4 -4
- package/src/renderer/components/team/editor/EditorSearchPanel.tsx +1 -1
- package/src/renderer/components/team/editor/MarkdownSplitView.tsx +1 -1
- package/src/renderer/components/team/editor/NewFileDialog.tsx +1 -1
- package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +1 -1
- package/src/renderer/components/team/editor/SearchInFilesPanel.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
- package/src/renderer/components/team/kanban/KanbanFilterPopover.tsx +4 -4
- package/src/renderer/components/team/kanban/KanbanSearchInput.tsx +1 -1
- package/src/renderer/components/team/kanban/KanbanSortPopover.tsx +5 -5
- package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +4 -4
- package/src/renderer/components/team/members/MemberCard.tsx +14 -47
- package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
- package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
- package/src/renderer/components/team/members/MemberDraftRow.tsx +1 -1
- package/src/renderer/components/team/members/MemberStatsTab.tsx +2 -2
- package/src/renderer/components/team/members/MemberWorkspaceTab.tsx +1 -1
- package/src/renderer/components/team/messages/MessageComposer.tsx +10 -112
- package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +1 -1
- package/src/renderer/components/team/messages/MessagesPanel.tsx +136 -119
- package/src/renderer/components/team/review/ChangeReviewDialog.tsx +1 -1
- package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +3 -3
- package/src/renderer/components/team/sidebar/TeamSidebarRail.tsx +4 -4
- package/src/renderer/components/team/tasks/TaskRow.tsx +1 -1
- package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
- package/src/renderer/components/team/tools/McpChip.tsx +6 -3
- package/src/renderer/components/team/tools/SkillChip.tsx +3 -3
- package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
- package/src/renderer/components/ui/MemberSelect.tsx +2 -2
- package/src/renderer/components/ui/MentionSuggestionList.tsx +2 -2
- package/src/renderer/components/ui/MentionableTextarea.tsx +3 -3
- package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
- package/src/renderer/index.css +56 -39
- package/src/renderer/index.html +17 -50
- package/src/renderer/store/index.ts +2 -1
- package/src/renderer/store/slices/scheduleSlice.ts +1 -1
- package/src/renderer/store/slices/teamSlice.ts +45 -168
- package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
- package/src/renderer/utils/memberHelpers.ts +5 -17
- package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
- package/src/renderer/utils/providerSlashCommands.ts +0 -5
- package/src/renderer/utils/scheduleFormatters.ts +3 -1
- package/src/renderer/utils/teamMessageFiltering.ts +14 -1
- package/src/renderer/utils/teamModelAvailability.ts +18 -2
- package/src/shared/types/api.ts +121 -2
- package/src/shared/types/ccConnect.ts +2 -0
- package/src/shared/types/index.ts +3 -0
- package/src/shared/types/systemManager.ts +49 -0
- package/src/shared/types/team.ts +29 -0
- package/src/shared/types/terminal.ts +4 -2
- package/src/shared/utils/extensionNormalizers.ts +15 -8
- package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
- package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
- package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
- package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
- package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
- package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
- package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
- package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
- package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-_m6iPPUR.js +0 -1
|
@@ -1,25 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
* ToolsSection — per-worker
|
|
3
|
-
*
|
|
1
|
+
/*
|
|
2
|
+
* ToolsSection — per-worker capabilities management.
|
|
3
|
+
* MCP uses a cc-switch style model: global templates create project instances.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
7
|
|
|
8
|
+
import { api } from '@renderer/api';
|
|
8
9
|
import { confirm } from '@renderer/components/common/ConfirmDialog';
|
|
10
|
+
import { Button } from '@renderer/components/ui/button';
|
|
11
|
+
import { Input } from '@renderer/components/ui/input';
|
|
12
|
+
import { McpLibraryEnableDialog } from '@renderer/components/extensions/mcp/McpLibraryEnableDialog';
|
|
9
13
|
import { useStore } from '@renderer/store';
|
|
10
|
-
import { Plus, Wrench } from 'lucide-react';
|
|
14
|
+
import { Plus, RefreshCw, Wrench } from 'lucide-react';
|
|
11
15
|
|
|
12
16
|
import { AddMcpInline } from './AddMcpInline';
|
|
13
17
|
import { AddSkillInline } from './AddSkillInline';
|
|
14
18
|
import { McpChip } from './McpChip';
|
|
15
19
|
import { SkillChip } from './SkillChip';
|
|
16
20
|
|
|
21
|
+
import type { McpLibraryEntry, SkillCatalogItem } from '@shared/types/extensions';
|
|
22
|
+
|
|
17
23
|
interface ToolsSectionProps {
|
|
18
24
|
teamName: string;
|
|
19
25
|
projectPath: string | null;
|
|
20
26
|
harnessType?: string;
|
|
21
27
|
}
|
|
22
28
|
|
|
29
|
+
function summarizeMcp(entry: McpLibraryEntry): string {
|
|
30
|
+
if (entry.installSpec.type === 'stdio') {
|
|
31
|
+
return `stdio · ${entry.installSpec.npmPackage}${entry.installSpec.npmVersion ? `@${entry.installSpec.npmVersion}` : ''}`;
|
|
32
|
+
}
|
|
33
|
+
return `${entry.installSpec.transportType} · ${entry.installSpec.url}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
23
36
|
export const ToolsSection = ({
|
|
24
37
|
teamName,
|
|
25
38
|
projectPath,
|
|
@@ -32,30 +45,46 @@ export const ToolsSection = ({
|
|
|
32
45
|
const mcpFetchInstalled = useStore((s) => s.mcpFetchInstalled);
|
|
33
46
|
const runMcpDiagnostics = useStore((s) => s.runMcpDiagnostics);
|
|
34
47
|
const fetchSkillsCatalog = useStore((s) => s.fetchSkillsCatalog);
|
|
48
|
+
const fetchSkillDetail = useStore((s) => s.fetchSkillDetail);
|
|
49
|
+
const applySkillImport = useStore((s) => s.applySkillImport);
|
|
50
|
+
const previewSkillImport = useStore((s) => s.previewSkillImport);
|
|
35
51
|
const uninstallMcpServer = useStore((s) => s.uninstallMcpServer);
|
|
36
52
|
const deleteSkill = useStore((s) => s.deleteSkill);
|
|
53
|
+
const skillDetailsById = useStore((s) => s.skillsDetailsById);
|
|
37
54
|
|
|
38
55
|
// ── Local state ──
|
|
39
56
|
const [addingMcp, setAddingMcp] = useState(false);
|
|
40
57
|
const [addingSkill, setAddingSkill] = useState(false);
|
|
58
|
+
const [mcpLibrary, setMcpLibrary] = useState<McpLibraryEntry[]>([]);
|
|
59
|
+
const [userSkills, setUserSkills] = useState<SkillCatalogItem[]>([]);
|
|
60
|
+
const [libraryLoading, setLibraryLoading] = useState(false);
|
|
61
|
+
const [libraryError, setLibraryError] = useState<string | null>(null);
|
|
62
|
+
const [selectedMcpTemplate, setSelectedMcpTemplate] = useState<McpLibraryEntry | null>(null);
|
|
63
|
+
const [importingMcpTemplates, setImportingMcpTemplates] = useState(false);
|
|
64
|
+
const [enablingSkillId, setEnablingSkillId] = useState<string | null>(null);
|
|
65
|
+
const [mcpSearch, setMcpSearch] = useState('');
|
|
66
|
+
const [skillSearch, setSkillSearch] = useState('');
|
|
67
|
+
const [showAllMcp, setShowAllMcp] = useState(false);
|
|
68
|
+
const [showAllSkills, setShowAllSkills] = useState(false);
|
|
69
|
+
const [applyNotice, setApplyNotice] = useState<string | null>(null);
|
|
41
70
|
|
|
42
71
|
// ── Derived data ──
|
|
43
72
|
const mcpServers = useMemo(
|
|
44
|
-
() => (projectPath ? mcpByPath[projectPath] ?? [] : []),
|
|
45
|
-
[mcpByPath, projectPath]
|
|
73
|
+
() => (projectPath ? (mcpByPath[projectPath] ?? []) : []),
|
|
74
|
+
[mcpByPath, projectPath]
|
|
46
75
|
);
|
|
47
76
|
// Diagnostics are stored keyed by `getMcpDiagnosticKey(name, scope)`, but the
|
|
48
77
|
// scope is not always present (e.g. the text-mode CLI parser omits it), so the
|
|
49
78
|
// scoped key can't be reconstructed reliably from an installed entry. Index by
|
|
50
79
|
// server name instead — chip rows already assume names are unique per project.
|
|
51
80
|
const diagnosticByName = useMemo(() => {
|
|
52
|
-
const record = projectPath ? diagnosticsByPath[projectPath] ?? {} : {};
|
|
81
|
+
const record = projectPath ? (diagnosticsByPath[projectPath] ?? {}) : {};
|
|
53
82
|
return Object.fromEntries(Object.values(record).map((d) => [d.name, d] as const));
|
|
54
83
|
}, [diagnosticsByPath, projectPath]);
|
|
55
84
|
|
|
56
85
|
// Deduplicate skills by name (same skill may appear from multiple roots)
|
|
57
86
|
const skills = useMemo(() => {
|
|
58
|
-
const raw = projectPath ? skillsByPath[projectPath] ?? [] : [];
|
|
87
|
+
const raw = projectPath ? (skillsByPath[projectPath] ?? []) : [];
|
|
59
88
|
const seen = new Set<string>();
|
|
60
89
|
return raw.filter((skill) => {
|
|
61
90
|
const key = skill.name.toLowerCase();
|
|
@@ -65,6 +94,54 @@ export const ToolsSection = ({
|
|
|
65
94
|
});
|
|
66
95
|
}, [skillsByPath, projectPath]);
|
|
67
96
|
|
|
97
|
+
const installedMcpNames = useMemo(
|
|
98
|
+
() => new Set(mcpServers.map((entry) => entry.name.toLowerCase())),
|
|
99
|
+
[mcpServers]
|
|
100
|
+
);
|
|
101
|
+
const installedSkillNames = useMemo(
|
|
102
|
+
() => new Set(skills.map((skill) => skill.name.toLowerCase())),
|
|
103
|
+
[skills]
|
|
104
|
+
);
|
|
105
|
+
const availableMcpLibrary = useMemo(() => {
|
|
106
|
+
const query = mcpSearch.trim().toLowerCase();
|
|
107
|
+
return mcpLibrary.filter((entry) => {
|
|
108
|
+
if (!query) return true;
|
|
109
|
+
return [entry.name, entry.description ?? '', summarizeMcp(entry)]
|
|
110
|
+
.join(' ')
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.includes(query);
|
|
113
|
+
});
|
|
114
|
+
}, [mcpLibrary, mcpSearch]);
|
|
115
|
+
const availableUserSkills = useMemo(() => {
|
|
116
|
+
const query = skillSearch.trim().toLowerCase();
|
|
117
|
+
return userSkills.filter((skill) => {
|
|
118
|
+
if (installedSkillNames.has(skill.name.toLowerCase())) return false;
|
|
119
|
+
if (!query) return true;
|
|
120
|
+
return [skill.name, skill.description ?? '', skill.folderName]
|
|
121
|
+
.join(' ')
|
|
122
|
+
.toLowerCase()
|
|
123
|
+
.includes(query);
|
|
124
|
+
});
|
|
125
|
+
}, [installedSkillNames, skillSearch, userSkills]);
|
|
126
|
+
const visibleMcpLibrary = showAllMcp ? availableMcpLibrary : availableMcpLibrary.slice(0, 6);
|
|
127
|
+
const visibleUserSkills = showAllSkills ? availableUserSkills : availableUserSkills.slice(0, 6);
|
|
128
|
+
const refreshLibraries = useCallback(async (): Promise<void> => {
|
|
129
|
+
setLibraryLoading(true);
|
|
130
|
+
setLibraryError(null);
|
|
131
|
+
try {
|
|
132
|
+
const [libraryEntries, globalSkills] = await Promise.all([
|
|
133
|
+
api.mcpRegistry?.libraryList?.() ?? Promise.resolve([]),
|
|
134
|
+
api.skills?.list?.() ?? Promise.resolve([]),
|
|
135
|
+
]);
|
|
136
|
+
setMcpLibrary(libraryEntries);
|
|
137
|
+
setUserSkills(globalSkills);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
setLibraryError(err instanceof Error ? err.message : '加载全局能力库失败');
|
|
140
|
+
} finally {
|
|
141
|
+
setLibraryLoading(false);
|
|
142
|
+
}
|
|
143
|
+
}, []);
|
|
144
|
+
|
|
68
145
|
// ── Fetch data on mount ──
|
|
69
146
|
useEffect(() => {
|
|
70
147
|
if (projectPath) {
|
|
@@ -72,75 +149,215 @@ export const ToolsSection = ({
|
|
|
72
149
|
runMcpDiagnostics(projectPath).catch(() => {});
|
|
73
150
|
fetchSkillsCatalog(projectPath).catch(() => {});
|
|
74
151
|
}
|
|
75
|
-
|
|
152
|
+
void refreshLibraries();
|
|
153
|
+
}, [projectPath, mcpFetchInstalled, runMcpDiagnostics, fetchSkillsCatalog, refreshLibraries]);
|
|
76
154
|
|
|
77
155
|
// ── Handlers ──
|
|
78
156
|
const handleRemoveMcp = useCallback(
|
|
79
157
|
(entry: { name: string; scope: string }) => {
|
|
80
158
|
void (async () => {
|
|
81
159
|
const confirmed = await confirm({
|
|
82
|
-
title: '
|
|
83
|
-
message:
|
|
84
|
-
confirmLabel: '
|
|
160
|
+
title: '移除 MCP 项目实例',
|
|
161
|
+
message: `确认从当前项目移除 MCP 实例「${entry.name}」?全局模板不会被删除。`,
|
|
162
|
+
confirmLabel: '移除实例',
|
|
85
163
|
cancelLabel: '取消',
|
|
86
164
|
variant: 'danger',
|
|
87
165
|
});
|
|
88
166
|
if (!confirmed) return;
|
|
89
|
-
uninstallMcpServer('', entry.name, entry.scope, projectPath ?? undefined)
|
|
167
|
+
uninstallMcpServer('', entry.name, entry.scope, projectPath ?? undefined)
|
|
168
|
+
.then(() => {
|
|
169
|
+
setApplyNotice('MCP 实例已移除;正在运行的数字员工需要重启后才会卸载该能力。');
|
|
170
|
+
})
|
|
171
|
+
.catch(() => {});
|
|
90
172
|
})();
|
|
91
173
|
},
|
|
92
|
-
[uninstallMcpServer, projectPath]
|
|
174
|
+
[uninstallMcpServer, projectPath]
|
|
93
175
|
);
|
|
94
176
|
|
|
95
177
|
const handleRemoveSkill = useCallback(
|
|
96
178
|
(skill: { id: string; name: string }) => {
|
|
97
179
|
void (async () => {
|
|
98
180
|
const confirmed = await confirm({
|
|
99
|
-
title: '
|
|
100
|
-
message:
|
|
101
|
-
confirmLabel: '
|
|
181
|
+
title: '禁用 Skill',
|
|
182
|
+
message: `确认从当前团队禁用 Skill「${skill.name}」?全局 Skill 仍会保留。`,
|
|
183
|
+
confirmLabel: '禁用',
|
|
102
184
|
cancelLabel: '取消',
|
|
103
185
|
variant: 'danger',
|
|
104
186
|
});
|
|
105
187
|
if (!confirmed) return;
|
|
106
|
-
deleteSkill({ skillId: skill.id, projectPath: projectPath ?? undefined })
|
|
188
|
+
deleteSkill({ skillId: skill.id, projectPath: projectPath ?? undefined })
|
|
189
|
+
.then(() => {
|
|
190
|
+
setApplyNotice('Skill 已禁用;正在运行的数字员工需要重启后才会卸载该能力。');
|
|
191
|
+
})
|
|
192
|
+
.catch(() => {});
|
|
107
193
|
})();
|
|
108
194
|
},
|
|
109
|
-
[deleteSkill, projectPath]
|
|
195
|
+
[deleteSkill, projectPath]
|
|
110
196
|
);
|
|
111
197
|
|
|
112
|
-
const
|
|
113
|
-
|
|
198
|
+
const handleMcpTemplateAdded = useCallback(
|
|
199
|
+
(entry: McpLibraryEntry) => {
|
|
200
|
+
setAddingMcp(false);
|
|
201
|
+
setMcpLibrary((prev) => {
|
|
202
|
+
const next = prev.filter((item) => item.id !== entry.id);
|
|
203
|
+
return [entry, ...next];
|
|
204
|
+
});
|
|
205
|
+
setSelectedMcpTemplate(entry);
|
|
206
|
+
void refreshLibraries();
|
|
207
|
+
},
|
|
208
|
+
[refreshLibraries]
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const handleMcpInstanceAdded = useCallback(() => {
|
|
212
|
+
setSelectedMcpTemplate(null);
|
|
114
213
|
if (projectPath) {
|
|
115
214
|
mcpFetchInstalled(projectPath).catch(() => {});
|
|
116
215
|
runMcpDiagnostics(projectPath).catch(() => {});
|
|
117
216
|
}
|
|
118
|
-
|
|
217
|
+
void refreshLibraries();
|
|
218
|
+
}, [projectPath, mcpFetchInstalled, runMcpDiagnostics, refreshLibraries]);
|
|
219
|
+
|
|
220
|
+
const handleImportMcpTemplates = useCallback(() => {
|
|
221
|
+
void (async () => {
|
|
222
|
+
if (!api.mcpRegistry?.libraryImport) {
|
|
223
|
+
setLibraryError('MCP 模板导入 API 不可用');
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
setImportingMcpTemplates(true);
|
|
227
|
+
setLibraryError(null);
|
|
228
|
+
try {
|
|
229
|
+
const result = await api.mcpRegistry.libraryImport({
|
|
230
|
+
projectPath: projectPath ?? undefined,
|
|
231
|
+
});
|
|
232
|
+
await refreshLibraries();
|
|
233
|
+
setApplyNotice(
|
|
234
|
+
`已从现有 MCP 配置导入模板:新增 ${result.imported.length} 个,跳过 ${result.skipped.length} 个。`
|
|
235
|
+
);
|
|
236
|
+
} catch (err) {
|
|
237
|
+
setLibraryError(err instanceof Error ? err.message : '导入现有 MCP 配置失败');
|
|
238
|
+
} finally {
|
|
239
|
+
setImportingMcpTemplates(false);
|
|
240
|
+
}
|
|
241
|
+
})();
|
|
242
|
+
}, [projectPath, refreshLibraries]);
|
|
119
243
|
|
|
120
244
|
const handleSkillAdded = useCallback(() => {
|
|
121
245
|
setAddingSkill(false);
|
|
122
246
|
if (projectPath) {
|
|
123
247
|
fetchSkillsCatalog(projectPath).catch(() => {});
|
|
124
248
|
}
|
|
125
|
-
|
|
249
|
+
void refreshLibraries();
|
|
250
|
+
}, [projectPath, fetchSkillsCatalog, refreshLibraries]);
|
|
251
|
+
|
|
252
|
+
const enableSkillFromLibrary = useCallback(
|
|
253
|
+
async (skill: SkillCatalogItem): Promise<void> => {
|
|
254
|
+
if (!projectPath) return;
|
|
255
|
+
setEnablingSkillId(skill.id);
|
|
256
|
+
try {
|
|
257
|
+
await fetchSkillDetail(skill.id);
|
|
258
|
+
const detail =
|
|
259
|
+
useStore.getState().skillsDetailsById[skill.id] ?? skillDetailsById[skill.id];
|
|
260
|
+
const sourceDir = detail?.item.skillDir ?? skill.skillDir;
|
|
261
|
+
const preview = await previewSkillImport({
|
|
262
|
+
sourceDir,
|
|
263
|
+
scope: 'project',
|
|
264
|
+
rootKind: skill.rootKind,
|
|
265
|
+
projectPath,
|
|
266
|
+
folderName: skill.folderName,
|
|
267
|
+
});
|
|
268
|
+
await applySkillImport({
|
|
269
|
+
sourceDir,
|
|
270
|
+
scope: 'project',
|
|
271
|
+
rootKind: skill.rootKind,
|
|
272
|
+
projectPath,
|
|
273
|
+
folderName: skill.folderName,
|
|
274
|
+
reviewPlanId: preview.planId,
|
|
275
|
+
});
|
|
276
|
+
await fetchSkillsCatalog(projectPath);
|
|
277
|
+
setApplyNotice('Skill 已启用;正在运行的数字员工需要重启后才会加载新能力。');
|
|
278
|
+
} finally {
|
|
279
|
+
setEnablingSkillId(null);
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
[
|
|
283
|
+
applySkillImport,
|
|
284
|
+
fetchSkillDetail,
|
|
285
|
+
fetchSkillsCatalog,
|
|
286
|
+
previewSkillImport,
|
|
287
|
+
projectPath,
|
|
288
|
+
skillDetailsById,
|
|
289
|
+
]
|
|
290
|
+
);
|
|
126
291
|
|
|
127
292
|
if (!projectPath) {
|
|
128
293
|
return (
|
|
129
294
|
<div className="flex items-center gap-2 px-1 py-2 text-xs text-[var(--color-text-muted)]">
|
|
130
295
|
<Wrench size={12} />
|
|
131
|
-
<span
|
|
296
|
+
<span>需要关联项目目录才能管理能力</span>
|
|
132
297
|
</div>
|
|
133
298
|
);
|
|
134
299
|
}
|
|
135
300
|
|
|
136
301
|
return (
|
|
137
|
-
<div className="flex flex-col gap-
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
<span>MCP 工具</span>
|
|
142
|
-
<span className="text-[10px]">({mcpServers.length})</span>
|
|
302
|
+
<div className="flex flex-col gap-4 px-1 py-2">
|
|
303
|
+
{libraryError ? (
|
|
304
|
+
<div className="rounded-md border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-xs text-amber-300">
|
|
305
|
+
{libraryError}
|
|
143
306
|
</div>
|
|
307
|
+
) : null}
|
|
308
|
+
|
|
309
|
+
{applyNotice ? (
|
|
310
|
+
<div className="rounded-md border border-indigo-500/30 bg-indigo-500/10 px-2 py-1.5 text-xs text-indigo-300">
|
|
311
|
+
{applyNotice}
|
|
312
|
+
</div>
|
|
313
|
+
) : null}
|
|
314
|
+
|
|
315
|
+
<div className="flex items-center justify-between gap-2">
|
|
316
|
+
<div className="text-[11px] text-[var(--color-text-muted)]">
|
|
317
|
+
当前项目管理 MCP 实例;全局库只提供可复用模板。先导入/新建模板,再添加为项目实例。
|
|
318
|
+
</div>
|
|
319
|
+
<div className="flex items-center gap-1">
|
|
320
|
+
<Button
|
|
321
|
+
variant="ghost"
|
|
322
|
+
size="sm"
|
|
323
|
+
className="h-6 px-2 text-[11px]"
|
|
324
|
+
disabled={importingMcpTemplates}
|
|
325
|
+
onClick={handleImportMcpTemplates}
|
|
326
|
+
>
|
|
327
|
+
{importingMcpTemplates ? '导入中...' : '导入现有 MCP'}
|
|
328
|
+
</Button>
|
|
329
|
+
<Button
|
|
330
|
+
variant="ghost"
|
|
331
|
+
size="sm"
|
|
332
|
+
className="h-6 px-2 text-[11px]"
|
|
333
|
+
onClick={() => void refreshLibraries()}
|
|
334
|
+
>
|
|
335
|
+
<RefreshCw className={libraryLoading ? 'mr-1 size-3 animate-spin' : 'mr-1 size-3'} />
|
|
336
|
+
刷新
|
|
337
|
+
</Button>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
{/* MCP capabilities */}
|
|
342
|
+
<div className="flex flex-col gap-2 rounded-lg border border-[var(--color-border-subtle)] bg-white/[0.015] p-2">
|
|
343
|
+
<div className="flex items-center justify-between gap-2">
|
|
344
|
+
<div className="flex items-center gap-1.5 text-[11px] font-medium text-[var(--color-text-muted)]">
|
|
345
|
+
<span>MCP 实例</span>
|
|
346
|
+
<span className="text-[10px]">
|
|
347
|
+
已配置实例 {mcpServers.length} · 模板 {mcpLibrary.length}
|
|
348
|
+
</span>
|
|
349
|
+
</div>
|
|
350
|
+
<Button
|
|
351
|
+
variant="ghost"
|
|
352
|
+
size="sm"
|
|
353
|
+
className="h-6 px-2 text-[11px]"
|
|
354
|
+
onClick={() => setAddingMcp(true)}
|
|
355
|
+
>
|
|
356
|
+
<Plus size={10} className="mr-1" />
|
|
357
|
+
新建模板
|
|
358
|
+
</Button>
|
|
359
|
+
</div>
|
|
360
|
+
|
|
144
361
|
<div className="flex flex-wrap items-center gap-1.5">
|
|
145
362
|
{mcpServers.map((entry) => (
|
|
146
363
|
<McpChip
|
|
@@ -150,56 +367,187 @@ export const ToolsSection = ({
|
|
|
150
367
|
onRemove={handleRemoveMcp}
|
|
151
368
|
/>
|
|
152
369
|
))}
|
|
153
|
-
{
|
|
154
|
-
<
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
370
|
+
{mcpServers.length === 0 ? (
|
|
371
|
+
<span className="text-xs text-[var(--color-text-muted)]">
|
|
372
|
+
当前项目还没有配置 MCP 实例。
|
|
373
|
+
</span>
|
|
374
|
+
) : null}
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
{addingMcp ? (
|
|
378
|
+
<AddMcpInline onAdded={handleMcpTemplateAdded} onCancel={() => setAddingMcp(false)} />
|
|
379
|
+
) : null}
|
|
380
|
+
|
|
381
|
+
<div className="space-y-1.5">
|
|
382
|
+
<div className="text-[10px] uppercase tracking-wide text-[var(--color-text-muted)]">
|
|
383
|
+
从模板添加
|
|
384
|
+
</div>
|
|
385
|
+
<Input
|
|
386
|
+
value={mcpSearch}
|
|
387
|
+
onChange={(event) => setMcpSearch(event.target.value)}
|
|
388
|
+
placeholder="搜索 MCP 模板..."
|
|
389
|
+
className="h-7 text-xs"
|
|
390
|
+
/>
|
|
391
|
+
{availableMcpLibrary.length > 0 ? (
|
|
392
|
+
<div className="flex flex-col gap-1.5">
|
|
393
|
+
{visibleMcpLibrary.map((entry) => (
|
|
394
|
+
<div
|
|
395
|
+
key={entry.id}
|
|
396
|
+
className="flex items-center justify-between gap-2 rounded-md border border-[var(--color-border-subtle)] px-2 py-1.5"
|
|
397
|
+
>
|
|
398
|
+
<div className="min-w-0">
|
|
399
|
+
<div className="truncate text-xs text-[var(--color-text)]">{entry.name}</div>
|
|
400
|
+
<div className="truncate text-[10px] text-[var(--color-text-muted)]">
|
|
401
|
+
{summarizeMcp(entry)}
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
<Button
|
|
405
|
+
variant="outline"
|
|
406
|
+
size="sm"
|
|
407
|
+
className="h-6 px-2 text-[11px]"
|
|
408
|
+
onClick={() => setSelectedMcpTemplate(entry)}
|
|
409
|
+
>
|
|
410
|
+
从模板添加
|
|
411
|
+
</Button>
|
|
412
|
+
</div>
|
|
413
|
+
))}
|
|
414
|
+
{availableMcpLibrary.length > 6 ? (
|
|
415
|
+
<Button
|
|
416
|
+
variant="ghost"
|
|
417
|
+
size="sm"
|
|
418
|
+
className="h-6 justify-start px-2 text-[11px]"
|
|
419
|
+
onClick={() => setShowAllMcp((value) => !value)}
|
|
420
|
+
>
|
|
421
|
+
{showAllMcp ? '收起' : `显示全部 ${availableMcpLibrary.length} 个模板`}
|
|
422
|
+
</Button>
|
|
423
|
+
) : null}
|
|
424
|
+
</div>
|
|
160
425
|
) : (
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
426
|
+
<div className="flex flex-col gap-2 rounded-md border border-dashed border-[var(--color-border)] px-2 py-2 text-xs text-[var(--color-text-muted)]">
|
|
427
|
+
<span>全局 MCP 模板库暂无可添加项。可以从现有 MCP 配置导入,或新建模板。</span>
|
|
428
|
+
<div className="flex flex-wrap gap-2">
|
|
429
|
+
<Button
|
|
430
|
+
variant="outline"
|
|
431
|
+
size="sm"
|
|
432
|
+
className="h-6 px-2 text-[11px]"
|
|
433
|
+
disabled={importingMcpTemplates}
|
|
434
|
+
onClick={handleImportMcpTemplates}
|
|
435
|
+
>
|
|
436
|
+
{importingMcpTemplates ? '导入中...' : '导入现有 MCP'}
|
|
437
|
+
</Button>
|
|
438
|
+
<Button
|
|
439
|
+
variant="ghost"
|
|
440
|
+
size="sm"
|
|
441
|
+
className="h-6 px-2 text-[11px]"
|
|
442
|
+
onClick={() => setAddingMcp(true)}
|
|
443
|
+
>
|
|
444
|
+
新建模板
|
|
445
|
+
</Button>
|
|
446
|
+
</div>
|
|
447
|
+
</div>
|
|
169
448
|
)}
|
|
170
449
|
</div>
|
|
171
450
|
</div>
|
|
172
451
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
452
|
+
<McpLibraryEnableDialog
|
|
453
|
+
open={Boolean(selectedMcpTemplate)}
|
|
454
|
+
entry={selectedMcpTemplate}
|
|
455
|
+
projectPath={projectPath}
|
|
456
|
+
installedServers={mcpServers}
|
|
457
|
+
harnessType={harnessType}
|
|
458
|
+
onClose={() => setSelectedMcpTemplate(null)}
|
|
459
|
+
onEnabled={handleMcpInstanceAdded}
|
|
460
|
+
/>
|
|
461
|
+
|
|
462
|
+
{/* Skill capabilities */}
|
|
463
|
+
<div className="flex flex-col gap-2 rounded-lg border border-[var(--color-border-subtle)] bg-white/[0.015] p-2">
|
|
464
|
+
<div className="flex items-center justify-between gap-2">
|
|
465
|
+
<div className="flex items-center gap-1.5 text-[11px] font-medium text-[var(--color-text-muted)]">
|
|
466
|
+
<span>Skill 能力</span>
|
|
467
|
+
<span className="text-[10px]">
|
|
468
|
+
已启用 {skills.length} · 全局 {userSkills.length}
|
|
469
|
+
</span>
|
|
470
|
+
</div>
|
|
471
|
+
<Button
|
|
472
|
+
variant="ghost"
|
|
473
|
+
size="sm"
|
|
474
|
+
className="h-6 px-2 text-[11px]"
|
|
475
|
+
onClick={() => setAddingSkill(true)}
|
|
476
|
+
>
|
|
477
|
+
<Plus size={10} className="mr-1" />
|
|
478
|
+
新建 Skill
|
|
479
|
+
</Button>
|
|
178
480
|
</div>
|
|
481
|
+
|
|
179
482
|
<div className="flex flex-wrap items-center gap-1.5">
|
|
180
483
|
{skills.map((skill) => (
|
|
181
|
-
<SkillChip
|
|
182
|
-
key={skill.id}
|
|
183
|
-
skill={skill}
|
|
184
|
-
onRemove={handleRemoveSkill}
|
|
185
|
-
/>
|
|
484
|
+
<SkillChip key={skill.id} skill={skill} onRemove={handleRemoveSkill} />
|
|
186
485
|
))}
|
|
187
|
-
{
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
486
|
+
{skills.length === 0 ? (
|
|
487
|
+
<span className="text-xs text-[var(--color-text-muted)]">
|
|
488
|
+
当前团队还没有启用 Skill。
|
|
489
|
+
</span>
|
|
490
|
+
) : null}
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
{addingSkill ? (
|
|
494
|
+
<AddSkillInline
|
|
495
|
+
projectPath={projectPath}
|
|
496
|
+
projectLabel={teamName}
|
|
497
|
+
onAdded={handleSkillAdded}
|
|
498
|
+
onCancel={() => setAddingSkill(false)}
|
|
499
|
+
/>
|
|
500
|
+
) : null}
|
|
501
|
+
|
|
502
|
+
<div className="space-y-1.5">
|
|
503
|
+
<div className="text-[10px] uppercase tracking-wide text-[var(--color-text-muted)]">
|
|
504
|
+
从全局 Skill 启用
|
|
505
|
+
</div>
|
|
506
|
+
<Input
|
|
507
|
+
value={skillSearch}
|
|
508
|
+
onChange={(event) => setSkillSearch(event.target.value)}
|
|
509
|
+
placeholder="搜索 Skill..."
|
|
510
|
+
className="h-7 text-xs"
|
|
511
|
+
/>
|
|
512
|
+
{availableUserSkills.length > 0 ? (
|
|
513
|
+
<div className="flex flex-col gap-1.5">
|
|
514
|
+
{visibleUserSkills.map((skill) => (
|
|
515
|
+
<div
|
|
516
|
+
key={skill.id}
|
|
517
|
+
className="flex items-center justify-between gap-2 rounded-md border border-[var(--color-border-subtle)] px-2 py-1.5"
|
|
518
|
+
>
|
|
519
|
+
<div className="min-w-0">
|
|
520
|
+
<div className="truncate text-xs text-[var(--color-text)]">{skill.name}</div>
|
|
521
|
+
<div className="truncate text-[10px] text-[var(--color-text-muted)]">
|
|
522
|
+
{skill.description || skill.folderName}
|
|
523
|
+
</div>
|
|
524
|
+
</div>
|
|
525
|
+
<Button
|
|
526
|
+
variant="outline"
|
|
527
|
+
size="sm"
|
|
528
|
+
className="h-6 px-2 text-[11px]"
|
|
529
|
+
disabled={enablingSkillId === skill.id}
|
|
530
|
+
onClick={() => void enableSkillFromLibrary(skill)}
|
|
531
|
+
>
|
|
532
|
+
{enablingSkillId === skill.id ? '启用中...' : '启用'}
|
|
533
|
+
</Button>
|
|
534
|
+
</div>
|
|
535
|
+
))}
|
|
536
|
+
{availableUserSkills.length > 6 ? (
|
|
537
|
+
<Button
|
|
538
|
+
variant="ghost"
|
|
539
|
+
size="sm"
|
|
540
|
+
className="h-6 justify-start px-2 text-[11px]"
|
|
541
|
+
onClick={() => setShowAllSkills((value) => !value)}
|
|
542
|
+
>
|
|
543
|
+
{showAllSkills ? '收起' : `显示全部 ${availableUserSkills.length} 个 Skill`}
|
|
544
|
+
</Button>
|
|
545
|
+
) : null}
|
|
546
|
+
</div>
|
|
194
547
|
) : (
|
|
195
|
-
<
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
className="inline-flex items-center gap-1 rounded-full border border-dashed border-[var(--color-border)] px-2 py-1 text-xs text-[var(--color-text-muted)] transition-colors hover:border-[var(--color-text-muted)] hover:text-[var(--color-text)]"
|
|
199
|
-
>
|
|
200
|
-
<Plus size={10} />
|
|
201
|
-
添加
|
|
202
|
-
</button>
|
|
548
|
+
<div className="rounded-md border border-dashed border-[var(--color-border)] px-2 py-2 text-xs text-[var(--color-text-muted)]">
|
|
549
|
+
全局 Skill 暂无可启用项。可以先创建用户级 Skill,再在团队中启用。
|
|
550
|
+
</div>
|
|
203
551
|
)}
|
|
204
552
|
</div>
|
|
205
553
|
</div>
|
|
@@ -150,7 +150,7 @@ export const MemberSelect = ({
|
|
|
150
150
|
>
|
|
151
151
|
<span className="text-[var(--color-text-muted)]">未分配</span>
|
|
152
152
|
{value === null ? (
|
|
153
|
-
<Check size={12} className="ml-auto shrink-0 text-
|
|
153
|
+
<Check size={12} className="ml-auto shrink-0 text-indigo-400" />
|
|
154
154
|
) : null}
|
|
155
155
|
</CommandPrimitive.Item>
|
|
156
156
|
) : null}
|
|
@@ -196,7 +196,7 @@ export const MemberSelect = ({
|
|
|
196
196
|
</span>
|
|
197
197
|
) : null}
|
|
198
198
|
{isSelected ? (
|
|
199
|
-
<Check size={12} className="ml-auto shrink-0 text-
|
|
199
|
+
<Check size={12} className="ml-auto shrink-0 text-indigo-400" />
|
|
200
200
|
) : null}
|
|
201
201
|
</CommandPrimitive.Item>
|
|
202
202
|
);
|
|
@@ -165,7 +165,7 @@ export const MentionSuggestionList = ({
|
|
|
165
165
|
) : isFile ? (
|
|
166
166
|
<FileIcon fileName={s.name} className="size-3.5" />
|
|
167
167
|
) : isTask ? (
|
|
168
|
-
<Hash size={13} className="shrink-0 text-
|
|
168
|
+
<Hash size={13} className="shrink-0 text-indigo-500 dark:text-indigo-400" />
|
|
169
169
|
) : isCommand ? (
|
|
170
170
|
<Command size={13} className="shrink-0 text-amber-500 dark:text-amber-400" />
|
|
171
171
|
) : isSkill ? (
|
|
@@ -190,7 +190,7 @@ export const MentionSuggestionList = ({
|
|
|
190
190
|
className={isFileOrFolder ? 'truncate' : 'font-medium'}
|
|
191
191
|
style={
|
|
192
192
|
isTask
|
|
193
|
-
? { color: 'var(--color-link, #
|
|
193
|
+
? { color: 'var(--color-link, #818cf8)' }
|
|
194
194
|
: isCommand
|
|
195
195
|
? { color: 'rgb(245 158 11)' }
|
|
196
196
|
: isSkill
|
|
@@ -309,8 +309,8 @@ function parseSegments(
|
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
// Default fallback color for mentions without a team color
|
|
312
|
-
const DEFAULT_MENTION_BG = 'rgba(
|
|
313
|
-
const DEFAULT_MENTION_TEXT = '#
|
|
312
|
+
const DEFAULT_MENTION_BG = 'rgba(99, 102, 241, 0.15)';
|
|
313
|
+
const DEFAULT_MENTION_TEXT = '#818cf8';
|
|
314
314
|
const URL_BADGE_BG = 'var(--url-badge-bg)';
|
|
315
315
|
const URL_BADGE_BORDER = 'var(--url-badge-border)';
|
|
316
316
|
const URL_BADGE_TEXT = 'var(--url-badge-text)';
|
|
@@ -1235,7 +1235,7 @@ export const MentionableTextarea = React.forwardRef<HTMLTextAreaElement, Mention
|
|
|
1235
1235
|
style={
|
|
1236
1236
|
seg.encoded
|
|
1237
1237
|
? {
|
|
1238
|
-
backgroundColor: 'rgba(
|
|
1238
|
+
backgroundColor: 'rgba(99, 102, 241, 0.15)',
|
|
1239
1239
|
color: PROSE_LINK,
|
|
1240
1240
|
// Only vertical padding (doesn't affect inline text flow).
|
|
1241
1241
|
// No horizontal padding/margin/box-shadow spread to avoid
|