@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
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TerminalPane - Reusable xterm.js terminal pane.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from SystemManagerView so any team or panel can embed
|
|
5
|
+
* a terminal connected to a PTY process.
|
|
6
|
+
*
|
|
7
|
+
* Lifecycle:
|
|
8
|
+
* - Mount: creates Terminal + FitAddon, registers SSE listeners
|
|
9
|
+
* - `spawn()` call or autoSpawn: starts a CLI process via the terminal API
|
|
10
|
+
* - Unmount: kills PTY, disposes terminal
|
|
11
|
+
*/
|
|
12
|
+
import React, { useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
13
|
+
import { FitAddon } from '@xterm/addon-fit';
|
|
14
|
+
import { WebLinksAddon } from '@xterm/addon-web-links';
|
|
15
|
+
import { Terminal } from '@xterm/xterm';
|
|
16
|
+
|
|
17
|
+
import { api } from '@renderer/api';
|
|
18
|
+
import { cn } from '@renderer/lib/utils';
|
|
19
|
+
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Types
|
|
22
|
+
// =============================================================================
|
|
23
|
+
|
|
24
|
+
export interface TerminalSpawnOptions {
|
|
25
|
+
command: string;
|
|
26
|
+
args: string[];
|
|
27
|
+
cwd: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface TerminalPaneProps {
|
|
31
|
+
/** Extra class names for the container */
|
|
32
|
+
className?: string;
|
|
33
|
+
/** Called after a PTY is spawned successfully */
|
|
34
|
+
onSpawned?: (ptyId: string) => void;
|
|
35
|
+
/** Called when the PTY exits */
|
|
36
|
+
onExit?: (ptyId: string, exitCode: number) => void;
|
|
37
|
+
/** Auto-spawn config. When provided, auto-spawns on mount. */
|
|
38
|
+
autoSpawn?: TerminalSpawnOptions;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TerminalPaneRef {
|
|
42
|
+
spawn: (options: TerminalSpawnOptions) => Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// =============================================================================
|
|
46
|
+
// TerminalPane
|
|
47
|
+
// =============================================================================
|
|
48
|
+
|
|
49
|
+
export const TerminalPane = React.forwardRef<TerminalPaneRef, TerminalPaneProps>(
|
|
50
|
+
function TerminalPane({ className, onSpawned, onExit, autoSpawn }, ref) {
|
|
51
|
+
const hostRef = useRef<HTMLDivElement>(null);
|
|
52
|
+
const terminalRef = useRef<Terminal | null>(null);
|
|
53
|
+
const fitAddonRef = useRef<FitAddon | null>(null);
|
|
54
|
+
const ptyIdRef = useRef<string | null>(null);
|
|
55
|
+
const spawnedRef = useRef(false);
|
|
56
|
+
|
|
57
|
+
const fitTerminal = useCallback(() => {
|
|
58
|
+
try {
|
|
59
|
+
fitAddonRef.current?.fit();
|
|
60
|
+
if (ptyIdRef.current && terminalRef.current) {
|
|
61
|
+
api.terminal.resize(ptyIdRef.current, terminalRef.current.cols, terminalRef.current.rows);
|
|
62
|
+
}
|
|
63
|
+
} catch {
|
|
64
|
+
// xterm fit can throw when the element is not measurable yet
|
|
65
|
+
}
|
|
66
|
+
}, []);
|
|
67
|
+
|
|
68
|
+
// Expose spawn method via ref
|
|
69
|
+
useImperativeHandle(ref, () => ({
|
|
70
|
+
spawn: async (options: TerminalSpawnOptions) => {
|
|
71
|
+
// Kill existing PTY if any
|
|
72
|
+
if (ptyIdRef.current) {
|
|
73
|
+
try { await api.terminal.kill(ptyIdRef.current); } catch {}
|
|
74
|
+
ptyIdRef.current = null;
|
|
75
|
+
}
|
|
76
|
+
// Clear stale terminal content before spawning new process
|
|
77
|
+
terminalRef.current?.clear();
|
|
78
|
+
try {
|
|
79
|
+
const ptyId = await api.terminal.spawn(options);
|
|
80
|
+
ptyIdRef.current = ptyId;
|
|
81
|
+
spawnedRef.current = true;
|
|
82
|
+
fitTerminal();
|
|
83
|
+
onSpawned?.(ptyId);
|
|
84
|
+
} catch (err) {
|
|
85
|
+
terminalRef.current?.writeln(
|
|
86
|
+
`\x1b[31m[Failed to spawn: ${err instanceof Error ? err.message : String(err)}]\x1b[0m`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
}), [fitTerminal, onSpawned]);
|
|
91
|
+
|
|
92
|
+
// Create terminal instance
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
const host = hostRef.current;
|
|
95
|
+
if (!host) return;
|
|
96
|
+
|
|
97
|
+
const term = new Terminal({
|
|
98
|
+
cursorBlink: true,
|
|
99
|
+
convertEol: true,
|
|
100
|
+
fontFamily: 'JetBrains Mono, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
101
|
+
fontSize: 13,
|
|
102
|
+
lineHeight: 1.28,
|
|
103
|
+
theme: {
|
|
104
|
+
background: 'var(--color-surface)',
|
|
105
|
+
foreground: 'var(--color-text)',
|
|
106
|
+
cursor: 'var(--color-text)',
|
|
107
|
+
selectionBackground: 'var(--color-border-emphasis)',
|
|
108
|
+
black: 'var(--color-surface-sidebar)',
|
|
109
|
+
red: '#f87171',
|
|
110
|
+
green: '#86efac',
|
|
111
|
+
yellow: '#fde68a',
|
|
112
|
+
blue: 'var(--color-accent)',
|
|
113
|
+
magenta: '#d8b4fe',
|
|
114
|
+
cyan: '#67e8f9',
|
|
115
|
+
white: 'var(--color-text)',
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const fitAddon = new FitAddon();
|
|
120
|
+
term.loadAddon(fitAddon);
|
|
121
|
+
term.loadAddon(new WebLinksAddon());
|
|
122
|
+
term.open(host);
|
|
123
|
+
terminalRef.current = term;
|
|
124
|
+
fitAddonRef.current = fitAddon;
|
|
125
|
+
fitTerminal();
|
|
126
|
+
|
|
127
|
+
// SSE listeners
|
|
128
|
+
const dataDispose = api.terminal.onData((_event, ptyId, data) => {
|
|
129
|
+
if (ptyId === ptyIdRef.current) term.write(data);
|
|
130
|
+
});
|
|
131
|
+
const exitDispose = api.terminal.onExit((_event, ptyId, exitCode) => {
|
|
132
|
+
if (ptyId === ptyIdRef.current) {
|
|
133
|
+
term.writeln(`\r\n\x1b[90m[process exited with code ${exitCode}]\x1b[0m`);
|
|
134
|
+
onExit?.(ptyId, exitCode);
|
|
135
|
+
ptyIdRef.current = null;
|
|
136
|
+
spawnedRef.current = false;
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Input forwarding
|
|
141
|
+
const inputDispose = term.onData((data) => {
|
|
142
|
+
if (ptyIdRef.current) api.terminal.write(ptyIdRef.current, data);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Resize observer
|
|
146
|
+
const resizeObserver = new ResizeObserver(() => fitTerminal());
|
|
147
|
+
resizeObserver.observe(host);
|
|
148
|
+
|
|
149
|
+
return () => {
|
|
150
|
+
dataDispose();
|
|
151
|
+
exitDispose();
|
|
152
|
+
inputDispose.dispose();
|
|
153
|
+
resizeObserver.disconnect();
|
|
154
|
+
if (ptyIdRef.current) {
|
|
155
|
+
void api.terminal.kill(ptyIdRef.current).catch(() => {});
|
|
156
|
+
}
|
|
157
|
+
term.dispose();
|
|
158
|
+
terminalRef.current = null;
|
|
159
|
+
fitAddonRef.current = null;
|
|
160
|
+
ptyIdRef.current = null;
|
|
161
|
+
};
|
|
162
|
+
}, [fitTerminal, onExit]);
|
|
163
|
+
|
|
164
|
+
// Auto-spawn
|
|
165
|
+
// Two issues combined to prevent the CLI from ever spawning:
|
|
166
|
+
// 1. React StrictMode mounts → unmounts → remounts. The first mount set
|
|
167
|
+
// spawnedRef = true and started a 200ms timer; cleanup cleared the timer
|
|
168
|
+
// but NOT the ref. The second mount saw spawnedRef === true → skipped.
|
|
169
|
+
// 2. The parent passes an inline object literal as autoSpawn, producing a
|
|
170
|
+
// new reference each render. With the raw object in deps, every render
|
|
171
|
+
// re-ran the effect, whose cleanup cleared the timeout. spawnedRef was
|
|
172
|
+
// already true, so the retry path was blocked.
|
|
173
|
+
// Fix: reset spawnedRef in cleanup so StrictMode remount can retry, and use
|
|
174
|
+
// a stable string key derived from autoSpawn content instead of the object.
|
|
175
|
+
const autoSpawnKey = autoSpawn
|
|
176
|
+
? `${autoSpawn.command}\0${autoSpawn.args.join(',')}\0${autoSpawn.cwd}`
|
|
177
|
+
: undefined;
|
|
178
|
+
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
if (!autoSpawnKey || spawnedRef.current) return;
|
|
181
|
+
spawnedRef.current = true;
|
|
182
|
+
|
|
183
|
+
const spawnOpts = autoSpawn!;
|
|
184
|
+
|
|
185
|
+
const doSpawn = async () => {
|
|
186
|
+
try {
|
|
187
|
+
const ptyId = await api.terminal.spawn(spawnOpts);
|
|
188
|
+
ptyIdRef.current = ptyId;
|
|
189
|
+
fitTerminal();
|
|
190
|
+
onSpawned?.(ptyId);
|
|
191
|
+
} catch (err) {
|
|
192
|
+
terminalRef.current?.writeln(
|
|
193
|
+
`\x1b[31m[Failed to spawn: ${err instanceof Error ? err.message : String(err)}]\x1b[0m`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const timer = setTimeout(doSpawn, 200);
|
|
199
|
+
return () => {
|
|
200
|
+
clearTimeout(timer);
|
|
201
|
+
spawnedRef.current = false;
|
|
202
|
+
};
|
|
203
|
+
// autoSpawnKey is a stable primitive; autoSpawn is captured via closure.
|
|
204
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
205
|
+
}, [autoSpawnKey, fitTerminal, onSpawned]);
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<div className={cn('size-full overflow-hidden', className)}>
|
|
209
|
+
<div ref={hostRef} className="size-full" />
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
);
|
|
@@ -961,7 +961,7 @@ const InstalledBanner = ({
|
|
|
961
961
|
disabled={isBusy}
|
|
962
962
|
className="flex items-center gap-1 rounded-md border px-2 py-[3px] text-[10px] font-medium transition-colors hover:bg-white/5 disabled:opacity-50"
|
|
963
963
|
style={{
|
|
964
|
-
borderColor: 'rgba(
|
|
964
|
+
borderColor: 'rgba(99, 102, 241, 0.45)',
|
|
965
965
|
color: '#93c5fd',
|
|
966
966
|
}}
|
|
967
967
|
title={`更新 Claude Code 到 v${cliStatus.latestVersion ?? 'latest'}`}
|
|
@@ -1405,7 +1405,7 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|
|
1405
1405
|
>
|
|
1406
1406
|
<div className="flex items-center justify-between">
|
|
1407
1407
|
<div className="flex items-center gap-2">
|
|
1408
|
-
<Loader2 className="size-4 shrink-0 animate-spin text-
|
|
1408
|
+
<Loader2 className="size-4 shrink-0 animate-spin text-indigo-600 dark:text-indigo-400" />
|
|
1409
1409
|
<span className="text-sm" style={{ color: 'var(--color-text-secondary)' }}>
|
|
1410
1410
|
正在下载 {runtimeDisplayName}...
|
|
1411
1411
|
</span>
|
|
@@ -1423,12 +1423,12 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|
|
1423
1423
|
{downloadTotal > 0 ? (
|
|
1424
1424
|
<div
|
|
1425
1425
|
className="h-full rounded-full transition-all duration-300"
|
|
1426
|
-
style={{ width: `${downloadProgress}%`, backgroundColor: '#
|
|
1426
|
+
style={{ width: `${downloadProgress}%`, backgroundColor: '#6366f1' }}
|
|
1427
1427
|
/>
|
|
1428
1428
|
) : (
|
|
1429
1429
|
<div
|
|
1430
1430
|
className="h-full w-1/3 animate-pulse rounded-full"
|
|
1431
|
-
style={{ backgroundColor: '#
|
|
1431
|
+
style={{ backgroundColor: '#6366f1' }}
|
|
1432
1432
|
/>
|
|
1433
1433
|
)}
|
|
1434
1434
|
</div>
|
|
@@ -1445,7 +1445,7 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|
|
1445
1445
|
style={{ borderColor: styles.border, backgroundColor: styles.bg }}
|
|
1446
1446
|
>
|
|
1447
1447
|
<div className="flex items-center gap-3">
|
|
1448
|
-
<Loader2 className="size-4 shrink-0 animate-spin text-
|
|
1448
|
+
<Loader2 className="size-4 shrink-0 animate-spin text-indigo-600 dark:text-indigo-400" />
|
|
1449
1449
|
<span className="text-sm" style={{ color: 'var(--color-text-secondary)' }}>
|
|
1450
1450
|
{label}
|
|
1451
1451
|
</span>
|
|
@@ -1463,7 +1463,7 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|
|
1463
1463
|
style={{ borderColor: styles.border, backgroundColor: styles.bg }}
|
|
1464
1464
|
>
|
|
1465
1465
|
<div className="flex items-center gap-3">
|
|
1466
|
-
<Loader2 className="size-4 shrink-0 animate-spin text-
|
|
1466
|
+
<Loader2 className="size-4 shrink-0 animate-spin text-indigo-600 dark:text-indigo-400" />
|
|
1467
1467
|
<span className="text-sm" style={{ color: 'var(--color-text-secondary)' }}>
|
|
1468
1468
|
正在安装 {runtimeDisplayName}...
|
|
1469
1469
|
</span>
|
|
@@ -1559,7 +1559,7 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|
|
1559
1559
|
onClick={handleInstall}
|
|
1560
1560
|
disabled={isBusy}
|
|
1561
1561
|
className="flex items-center justify-center gap-1.5 rounded-md px-4 py-2 text-sm font-medium text-white transition-colors disabled:opacity-50"
|
|
1562
|
-
style={{ backgroundColor: '#
|
|
1562
|
+
style={{ backgroundColor: '#6366f1' }}
|
|
1563
1563
|
>
|
|
1564
1564
|
<Download className="size-4" />
|
|
1565
1565
|
{cliLaunchIssue ? `重新安装 ${runtimeDisplayName}` : `安装 ${runtimeDisplayName}`}
|
|
@@ -7,7 +7,7 @@ import React from 'react';
|
|
|
7
7
|
|
|
8
8
|
import { RecentProjectsSection } from '@features/recent-projects/renderer';
|
|
9
9
|
import { useStore } from '@renderer/store';
|
|
10
|
-
import {
|
|
10
|
+
import { Sparkles, Users, Workflow } from 'lucide-react';
|
|
11
11
|
import { useShallow } from 'zustand/react/shallow';
|
|
12
12
|
|
|
13
13
|
const HIGHLIGHT_HARNESSES = [
|
|
@@ -19,16 +19,6 @@ const HIGHLIGHT_HARNESSES = [
|
|
|
19
19
|
'DeepSeek / IM',
|
|
20
20
|
];
|
|
21
21
|
|
|
22
|
-
const HIGHLIGHT_CHANNELS = [
|
|
23
|
-
'Feishu',
|
|
24
|
-
'Slack',
|
|
25
|
-
'Discord',
|
|
26
|
-
'DingTalk',
|
|
27
|
-
'WeCom',
|
|
28
|
-
'Telegram',
|
|
29
|
-
'Webhook / API',
|
|
30
|
-
];
|
|
31
|
-
|
|
32
22
|
export const DashboardView = (): React.JSX.Element => {
|
|
33
23
|
const { openTeamsTab, openSettingsTab, teams, teamsLoading } = useStore(
|
|
34
24
|
useShallow((state) => ({
|
|
@@ -58,8 +48,7 @@ export const DashboardView = (): React.JSX.Element => {
|
|
|
58
48
|
Hermit:一人公司的 AI 团队控制台
|
|
59
49
|
</h1>
|
|
60
50
|
<p className="mt-2 text-sm text-text-secondary">
|
|
61
|
-
几乎覆盖所有主流
|
|
62
|
-
Harness,支持全渠道接入,把团队编排、消息协作、任务推进和运行状态放在同一个工作台。
|
|
51
|
+
几乎覆盖所有主流 Harness,把团队编排、消息协作、任务推进和运行状态放在同一个工作台。
|
|
63
52
|
</p>
|
|
64
53
|
</div>
|
|
65
54
|
<div className="grid gap-4 px-6 py-5 md:grid-cols-3">
|
|
@@ -82,21 +71,14 @@ export const DashboardView = (): React.JSX.Element => {
|
|
|
82
71
|
</div>
|
|
83
72
|
<div className="rounded-lg border border-border bg-surface px-4 py-3">
|
|
84
73
|
<div className="mb-2 inline-flex items-center gap-1.5 text-xs font-medium text-text-secondary">
|
|
85
|
-
<
|
|
86
|
-
|
|
74
|
+
<Sparkles className="size-3.5" />
|
|
75
|
+
会话洞察
|
|
87
76
|
</div>
|
|
88
77
|
<p className="text-xs text-text-muted">
|
|
89
|
-
|
|
78
|
+
汇总本地会话、任务、消息和 Token 使用情况,帮助你判断团队执行状态。
|
|
90
79
|
</p>
|
|
91
|
-
<div className="mt-3
|
|
92
|
-
|
|
93
|
-
<span
|
|
94
|
-
key={channel}
|
|
95
|
-
className="rounded-md border border-border bg-surface-overlay px-2 py-1 text-[11px] text-text-secondary"
|
|
96
|
-
>
|
|
97
|
-
{channel}
|
|
98
|
-
</span>
|
|
99
|
-
))}
|
|
80
|
+
<div className="mt-3 rounded-md border border-border bg-surface-overlay px-2.5 py-2 text-[11px] text-text-muted">
|
|
81
|
+
会话记录 → 使用统计 → 身份识别 → 导出复盘
|
|
100
82
|
</div>
|
|
101
83
|
</div>
|
|
102
84
|
<div className="rounded-lg border border-border bg-surface px-4 py-3">
|
|
@@ -130,7 +112,7 @@ export const DashboardView = (): React.JSX.Element => {
|
|
|
130
112
|
<p className="mt-1 text-xs text-text-muted">
|
|
131
113
|
首次使用会看到空白首页。按下面步骤配置后,就会出现团队和项目内容。
|
|
132
114
|
</p>
|
|
133
|
-
<div className="mt-4 grid gap-3 md:grid-cols-
|
|
115
|
+
<div className="mt-4 grid gap-3 md:grid-cols-2">
|
|
134
116
|
<button
|
|
135
117
|
type="button"
|
|
136
118
|
onClick={() => openSettingsTab('harness')}
|
|
@@ -140,21 +122,12 @@ export const DashboardView = (): React.JSX.Element => {
|
|
|
140
122
|
<p className="mt-1 text-sm font-medium text-text">配置 Harness</p>
|
|
141
123
|
<p className="mt-1 text-xs text-text-muted">连接 Claude/Codex/Gemini 等运行时</p>
|
|
142
124
|
</button>
|
|
143
|
-
<button
|
|
144
|
-
type="button"
|
|
145
|
-
onClick={() => openSettingsTab('channels')}
|
|
146
|
-
className="rounded-lg border border-border bg-surface px-3 py-3 text-left transition-colors hover:bg-surface-overlay"
|
|
147
|
-
>
|
|
148
|
-
<p className="text-[11px] font-medium text-text-muted">第 2 步</p>
|
|
149
|
-
<p className="mt-1 text-sm font-medium text-text">配置渠道</p>
|
|
150
|
-
<p className="mt-1 text-xs text-text-muted">接入飞书/Slack/Telegram/Webhook</p>
|
|
151
|
-
</button>
|
|
152
125
|
<button
|
|
153
126
|
type="button"
|
|
154
127
|
onClick={openTeamsTab}
|
|
155
128
|
className="rounded-lg border border-border bg-surface px-3 py-3 text-left transition-colors hover:bg-surface-overlay"
|
|
156
129
|
>
|
|
157
|
-
<p className="text-[11px] font-medium text-text-muted">第
|
|
130
|
+
<p className="text-[11px] font-medium text-text-muted">第 2 步</p>
|
|
158
131
|
<p className="mt-1 text-sm font-medium text-text">创建团队并启动</p>
|
|
159
132
|
<p className="mt-1 text-xs text-text-muted">设置工作目录后即可开始分发任务</p>
|
|
160
133
|
</button>
|
|
@@ -31,25 +31,15 @@ import { useStore } from '@renderer/store';
|
|
|
31
31
|
import { createLoadingMultimodelCliStatus } from '@renderer/store/slices/cliInstallerSlice';
|
|
32
32
|
import {
|
|
33
33
|
filterExtensionStoreProviders,
|
|
34
|
-
formatCliExtensionCapabilityStatus,
|
|
35
34
|
getVisibleMultimodelProviders,
|
|
36
35
|
isMultimodelRuntimeStatus,
|
|
37
36
|
} from '@renderer/utils/multimodelProviderVisibility';
|
|
38
37
|
import { resolveProjectPathById } from '@renderer/utils/projectLookup';
|
|
39
38
|
import { refreshCliStatusForCurrentMode } from '@renderer/utils/refreshCliStatus';
|
|
40
39
|
import { getRuntimeDisplayName } from '@renderer/utils/runtimeDisplayName';
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
AlertTriangle,
|
|
44
|
-
Info,
|
|
45
|
-
Loader2,
|
|
46
|
-
Puzzle,
|
|
47
|
-
RefreshCw,
|
|
48
|
-
Sliders,
|
|
49
|
-
} from 'lucide-react';
|
|
40
|
+
import { AlertTriangle, Info, Loader2, Puzzle, RefreshCw } from 'lucide-react';
|
|
50
41
|
import { useShallow } from 'zustand/react/shallow';
|
|
51
42
|
|
|
52
|
-
import { EnvVarPanel } from './env/EnvVarPanel';
|
|
53
43
|
import { PluginsPanel } from './plugins/PluginsPanel';
|
|
54
44
|
import { StoreExtensionToast } from './common/ExtensionToast';
|
|
55
45
|
import { ExtensionsSubTabTrigger } from './ExtensionsSubTabTrigger';
|
|
@@ -81,7 +71,7 @@ const ProviderCapabilityCardSkeleton = ({
|
|
|
81
71
|
</Badge>
|
|
82
72
|
</div>
|
|
83
73
|
<div className="mt-2 flex flex-wrap gap-1.5">
|
|
84
|
-
{Array.from({ length:
|
|
74
|
+
{Array.from({ length: 4 }, (_, index) => (
|
|
85
75
|
<span
|
|
86
76
|
key={index}
|
|
87
77
|
className="h-7 w-28 animate-pulse rounded-md border border-border bg-surface"
|
|
@@ -118,12 +108,6 @@ const EXTENSION_SUB_TABS = [
|
|
|
118
108
|
icon: Puzzle,
|
|
119
109
|
description: 'Claude Code 私有扩展,增强运行时的能力与集成。',
|
|
120
110
|
},
|
|
121
|
-
{
|
|
122
|
-
value: 'env-vars' as const,
|
|
123
|
-
label: '环境变量',
|
|
124
|
-
icon: Sliders,
|
|
125
|
-
description: '管理运行时环境变量,启动 agent 时自动注入。',
|
|
126
|
-
},
|
|
127
111
|
] as const;
|
|
128
112
|
|
|
129
113
|
export const ExtensionStoreView = (): React.JSX.Element => {
|
|
@@ -215,7 +199,6 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
215
199
|
[extensionsTabProjectId, projects, repositoryGroups]
|
|
216
200
|
);
|
|
217
201
|
const projectPath = resolvedProject?.path ?? null;
|
|
218
|
-
const projectLabel = resolvedProject?.name ?? null;
|
|
219
202
|
const subTabs = EXTENSION_SUB_TABS;
|
|
220
203
|
|
|
221
204
|
useEffect(() => {
|
|
@@ -238,11 +221,7 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
238
221
|
bootstrapCliStatus,
|
|
239
222
|
fetchCliStatus,
|
|
240
223
|
});
|
|
241
|
-
}, [
|
|
242
|
-
bootstrapCliStatus,
|
|
243
|
-
fetchCliStatus,
|
|
244
|
-
multimodelEnabled,
|
|
245
|
-
]);
|
|
224
|
+
}, [bootstrapCliStatus, fetchCliStatus, multimodelEnabled]);
|
|
246
225
|
|
|
247
226
|
const isRefreshing = effectiveCliStatusLoading;
|
|
248
227
|
const cliStatusBanner = useMemo(() => {
|
|
@@ -264,7 +243,7 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
264
243
|
<div>
|
|
265
244
|
<p className="text-sm font-medium text-text">正在检查扩展运行时可用性</p>
|
|
266
245
|
<p className="mt-0.5 text-xs text-text-muted">
|
|
267
|
-
|
|
246
|
+
扩展需要配置好的运行时来管理插件和提供商连接。
|
|
268
247
|
</p>
|
|
269
248
|
</div>
|
|
270
249
|
</div>
|
|
@@ -321,101 +300,7 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
321
300
|
);
|
|
322
301
|
}
|
|
323
302
|
|
|
324
|
-
|
|
325
|
-
return (
|
|
326
|
-
<div className="bg-surface/70 mx-4 mt-3 rounded-md border border-border px-4 py-3">
|
|
327
|
-
<div className="flex items-start gap-3">
|
|
328
|
-
<Info className="mt-0.5 size-4 shrink-0 text-text-secondary" />
|
|
329
|
-
<div className="min-w-0 flex-1">
|
|
330
|
-
<p className="text-sm font-medium text-text">多模型运行时能力</p>
|
|
331
|
-
<p className="mt-0.5 text-xs text-text-muted">
|
|
332
|
-
不同区域支持的提供商可能不同。只有运行时明确声明支持时,MCP 与技能能力才会显示。
|
|
333
|
-
</p>
|
|
334
|
-
</div>
|
|
335
|
-
</div>
|
|
336
|
-
{visibleProviders.length > 0 && (
|
|
337
|
-
<div className="mt-3 grid gap-2 md:grid-cols-2">
|
|
338
|
-
{visibleProviders.map((provider) => {
|
|
339
|
-
const providerLoading = cliProviderStatusLoading[provider.providerId] === true;
|
|
340
|
-
if (
|
|
341
|
-
isProviderCapabilityCardLoading(provider, providerLoading) ||
|
|
342
|
-
isCodexSnapshotPending(provider, codexSnapshotPending)
|
|
343
|
-
) {
|
|
344
|
-
return (
|
|
345
|
-
<ProviderCapabilityCardSkeleton
|
|
346
|
-
key={provider.providerId}
|
|
347
|
-
providerId={provider.providerId}
|
|
348
|
-
displayName={provider.displayName}
|
|
349
|
-
/>
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const statusTone = provider.authenticated
|
|
354
|
-
? 'border-emerald-500/30 bg-emerald-500/5 text-emerald-300'
|
|
355
|
-
: provider.supported
|
|
356
|
-
? 'border-amber-500/30 bg-amber-500/5 text-amber-300'
|
|
357
|
-
: 'border-border bg-surface-raised text-text-muted';
|
|
358
|
-
const statusLabel = provider.authenticated
|
|
359
|
-
? '已连接'
|
|
360
|
-
: provider.supported
|
|
361
|
-
? '需要设置'
|
|
362
|
-
: '不支持';
|
|
363
|
-
const extensionCapabilities = getCliProviderExtensionCapabilities(provider);
|
|
364
|
-
|
|
365
|
-
return (
|
|
366
|
-
<div
|
|
367
|
-
key={provider.providerId}
|
|
368
|
-
className={`rounded-md border px-3 py-2 ${statusTone}`}
|
|
369
|
-
>
|
|
370
|
-
<div className="flex items-center justify-between gap-2">
|
|
371
|
-
<div className="min-w-0">
|
|
372
|
-
<p className="inline-flex items-center gap-2 text-sm font-medium">
|
|
373
|
-
<ProviderBrandLogo
|
|
374
|
-
providerId={provider.providerId}
|
|
375
|
-
className="size-4 shrink-0"
|
|
376
|
-
/>
|
|
377
|
-
<span>{provider.displayName}</span>
|
|
378
|
-
</p>
|
|
379
|
-
<p className="truncate text-[11px] text-text-muted">
|
|
380
|
-
{provider.statusMessage ?? provider.backend?.label ?? '可配置'}
|
|
381
|
-
</p>
|
|
382
|
-
</div>
|
|
383
|
-
<Badge variant="outline" className="shrink-0">
|
|
384
|
-
{statusLabel}
|
|
385
|
-
</Badge>
|
|
386
|
-
</div>
|
|
387
|
-
<div className="mt-2 flex flex-wrap gap-1.5 text-[11px]">
|
|
388
|
-
<Badge variant="secondary">
|
|
389
|
-
MCP: {formatCliExtensionCapabilityStatus(extensionCapabilities.mcp.status)}
|
|
390
|
-
</Badge>
|
|
391
|
-
<Badge variant="secondary">
|
|
392
|
-
技能:{extensionCapabilities.skills.ownership}
|
|
393
|
-
</Badge>
|
|
394
|
-
</div>
|
|
395
|
-
</div>
|
|
396
|
-
);
|
|
397
|
-
})}
|
|
398
|
-
</div>
|
|
399
|
-
)}
|
|
400
|
-
</div>
|
|
401
|
-
);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return (
|
|
405
|
-
<div className="mx-4 mt-3 flex items-start gap-3 rounded-md border border-emerald-500/30 bg-emerald-500/5 px-4 py-3">
|
|
406
|
-
<Info className="mt-0.5 size-4 shrink-0 text-emerald-300" />
|
|
407
|
-
<div>
|
|
408
|
-
<p className="text-sm font-medium text-emerald-300">{runtimeDisplayName} 已就绪</p>
|
|
409
|
-
<p className="mt-0.5 text-xs text-text-muted">
|
|
410
|
-
可以从此页面管理 MCP 服务器与技能
|
|
411
|
-
{effectiveCliStatus.installedVersion
|
|
412
|
-
? `,使用 ${runtimeDisplayName} ${effectiveCliStatus.installedVersion}`
|
|
413
|
-
: ''}
|
|
414
|
-
.
|
|
415
|
-
</p>
|
|
416
|
-
</div>
|
|
417
|
-
</div>
|
|
418
|
-
);
|
|
303
|
+
return null;
|
|
419
304
|
}, [
|
|
420
305
|
cliProviderStatusLoading,
|
|
421
306
|
codexSnapshotPending,
|
|
@@ -425,7 +310,7 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
425
310
|
]);
|
|
426
311
|
|
|
427
312
|
// Browser mode guard
|
|
428
|
-
if (!api.plugins
|
|
313
|
+
if (!api.plugins) {
|
|
429
314
|
return (
|
|
430
315
|
<div className="flex flex-1 items-center justify-center">
|
|
431
316
|
<div className="text-center">
|
|
@@ -469,7 +354,7 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
469
354
|
)}
|
|
470
355
|
{/* Active sessions warning */}
|
|
471
356
|
{hasOngoingSessions && (
|
|
472
|
-
<div className="mb-4 flex items-center gap-2 rounded-md border border-
|
|
357
|
+
<div className="mb-4 flex items-center gap-2 rounded-md border border-indigo-500/30 bg-indigo-500/5 px-4 py-3 text-sm text-indigo-400">
|
|
473
358
|
<Info className="size-4 shrink-0" />
|
|
474
359
|
正在运行的会话需要重启后才会应用扩展变更。
|
|
475
360
|
</div>
|
|
@@ -510,10 +395,6 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
|
|
510
395
|
cliStatusLoading={effectiveCliStatusLoading}
|
|
511
396
|
/>
|
|
512
397
|
</TabsContent>
|
|
513
|
-
|
|
514
|
-
<TabsContent value="env-vars" className="mt-0 pt-4">
|
|
515
|
-
<EnvVarPanel projectPath={projectPath} />
|
|
516
|
-
</TabsContent>
|
|
517
398
|
</Tabs>
|
|
518
399
|
</div>
|
|
519
400
|
</div>
|
|
@@ -5,7 +5,7 @@ import { Info } from 'lucide-react';
|
|
|
5
5
|
import type { LucideIcon } from 'lucide-react';
|
|
6
6
|
|
|
7
7
|
interface ExtensionsSubTabTriggerProps {
|
|
8
|
-
value: 'plugins'
|
|
8
|
+
value: 'plugins';
|
|
9
9
|
label: string;
|
|
10
10
|
description: string;
|
|
11
11
|
icon: LucideIcon;
|
|
@@ -44,10 +44,10 @@ const TOAST_STYLES: Record<
|
|
|
44
44
|
iconColor: 'text-amber-400',
|
|
45
45
|
},
|
|
46
46
|
info: {
|
|
47
|
-
bg: 'bg-
|
|
48
|
-
border: 'border-
|
|
47
|
+
bg: 'bg-indigo-500/10',
|
|
48
|
+
border: 'border-indigo-500/30',
|
|
49
49
|
icon: Info,
|
|
50
|
-
iconColor: 'text-
|
|
50
|
+
iconColor: 'text-indigo-400',
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
|
|
@@ -11,7 +11,7 @@ interface SourceBadgeProps {
|
|
|
11
11
|
export const SourceBadge = ({ source }: SourceBadgeProps): React.JSX.Element => {
|
|
12
12
|
if (source === 'official') {
|
|
13
13
|
return (
|
|
14
|
-
<Badge className="border-
|
|
14
|
+
<Badge className="border-indigo-500/30 bg-indigo-500/10 text-indigo-400" variant="outline">
|
|
15
15
|
Official
|
|
16
16
|
</Badge>
|
|
17
17
|
);
|