@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.
Files changed (243) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-CemDOX-3.js +58 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-hPY770Db.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-BHHrJT1i.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CWErBtke.js} +1 -1
  5. package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-C_o2_Uv8.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-DUW0LI3t.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-CWbCE9hQ.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-BjLadrfV.js} +1 -1
  9. package/dist-renderer/assets/channel-DyP9YlCF.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-CPnvjZl9.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-OlL47yXQ.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-DTasjbm8.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-C5_Xaqkk.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-NdoM4DMR.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-C8Fybejy.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-E98TYFXJ.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.js → chunk-TZMSLE5B-h4lFgkIq.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-BqffFTae.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BqffFTae.js +1 -0
  20. package/dist-renderer/assets/clone-MPcKWs2O.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DxcFNQKT.js → cose-bilkent-S5V4N54A-DtQ7fkrs.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-CN-nL_z4.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DVJtqmm-.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-DlxHxyXh.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-7dpzO6x6.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-GP1TqsHi.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-C7ZLETuH.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-CvPB68dH.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5yOm3w7.js} +1 -1
  30. package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-smeyY1YZ.js} +1 -1
  31. package/dist-renderer/assets/{index-BySQS7AB.js → index-BJx8XvG1.js} +1 -1
  32. package/dist-renderer/assets/{index-C_okzZXP.js → index-CQaXUAua.js} +1 -1
  33. package/dist-renderer/assets/{index-VJ-MM9xa.js → index-CajRpxO2.js} +1 -1
  34. package/dist-renderer/assets/{index-V7dAKPqd.js → index-ChG4rE-E.js} +587 -705
  35. package/dist-renderer/assets/index-DUd0uw9C.css +32 -0
  36. package/dist-renderer/assets/{index-CzWxVCRL.js → index-IhmXZWqf.js} +1 -1
  37. package/dist-renderer/assets/{index-B2Dy7M2G.js → index-x_JkoDRH.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-D-hWRQGY.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-Bb6W8rUG.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-CnHdUX0q.js} +1 -1
  41. package/dist-renderer/assets/{layout-B-z3y17c.js → layout-pqss_zkI.js} +1 -1
  42. package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-B1mFITNh.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-DTD9q7-D.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-Df3mhrn7.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-B1FZ09vH.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-aEO78thZ.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-6Ui--jp-.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-DF4Q1cAM.js} +1 -1
  49. package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
  50. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.js → stateDiagram-FKZM4ZOC-BqA2BI8C.js} +1 -1
  51. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Cs2ZtUD2.js +1 -0
  52. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-BXs_hOJs.js → timeline-definition-IT6M3QCI-DoOkw_A8.js} +1 -1
  53. package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DUe26QdD.js} +1 -1
  54. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.js → xychartDiagram-PRI3JC2R-BKCnj5Xn.js} +1 -1
  55. package/dist-renderer/index.html +20 -53
  56. package/package.json +25 -18
  57. package/src/main/ipc/extensions.ts +2 -1
  58. package/src/main/server.ts +873 -221
  59. package/src/main/services/extensions/ExtensionFacadeService.ts +2 -5
  60. package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
  61. package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
  62. package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
  63. package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
  64. package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
  65. package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
  66. package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
  67. package/src/main/services/teams-mvp/TaskDispatchService.ts +5 -6
  68. package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
  69. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
  70. package/src/main/utils/teamProjectResolution.ts +15 -0
  71. package/src/renderer/App.tsx +8 -4
  72. package/src/renderer/api/httpClient.ts +68 -18
  73. package/src/renderer/api/providers.ts +23 -2
  74. package/src/renderer/assets/participant-avatars/01.svg +3 -0
  75. package/src/renderer/assets/participant-avatars/02.svg +3 -0
  76. package/src/renderer/assets/participant-avatars/03.svg +3 -0
  77. package/src/renderer/assets/participant-avatars/04.svg +3 -0
  78. package/src/renderer/assets/participant-avatars/05.svg +3 -0
  79. package/src/renderer/assets/participant-avatars/06.svg +3 -0
  80. package/src/renderer/assets/participant-avatars/07.svg +3 -0
  81. package/src/renderer/assets/participant-avatars/08.svg +3 -0
  82. package/src/renderer/assets/participant-avatars/09.svg +3 -0
  83. package/src/renderer/assets/participant-avatars/10.svg +3 -0
  84. package/src/renderer/assets/participant-avatars/11.svg +3 -0
  85. package/src/renderer/assets/participant-avatars/12.svg +3 -0
  86. package/src/renderer/assets/participant-avatars/13.svg +3 -0
  87. package/src/renderer/components/chat/ChatHistoryItem.tsx +1 -1
  88. package/src/renderer/components/chat/items/SubagentItem.tsx +2 -2
  89. package/src/renderer/components/chat/viewers/MermaidDiagram.tsx +2 -2
  90. package/src/renderer/components/common/ErrorBoundary.tsx +1 -1
  91. package/src/renderer/components/common/TerminalPane.tsx +213 -0
  92. package/src/renderer/components/dashboard/CliStatusBanner.tsx +7 -7
  93. package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
  94. package/src/renderer/components/extensions/ExtensionStoreView.tsx +7 -126
  95. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  96. package/src/renderer/components/extensions/common/ExtensionToast.tsx +3 -3
  97. package/src/renderer/components/extensions/common/SourceBadge.tsx +1 -1
  98. package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
  99. package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
  100. package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
  101. package/src/renderer/components/extensions/plugins/CategoryChips.tsx +1 -1
  102. package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
  103. package/src/renderer/components/extensions/plugins/PluginDetailDialog.tsx +2 -2
  104. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
  105. package/src/renderer/components/extensions/skills/SkillEditorDialog.tsx +1 -1
  106. package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
  107. package/src/renderer/components/layout/PaneContent.tsx +8 -1
  108. package/src/renderer/components/layout/PaneResizeHandle.tsx +2 -2
  109. package/src/renderer/components/layout/Sidebar.tsx +13 -56
  110. package/src/renderer/components/layout/SortableTab.tsx +22 -33
  111. package/src/renderer/components/layout/TabBar.tsx +1 -1
  112. package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
  113. package/src/renderer/components/report/sections/CostSection.tsx +2 -2
  114. package/src/renderer/components/report/sections/InsightsSection.tsx +1 -1
  115. package/src/renderer/components/runtime/ProviderRuntimeBackendSelector.tsx +2 -2
  116. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
  117. package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
  118. package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
  119. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
  120. package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
  121. package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
  122. package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
  123. package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
  124. package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
  125. package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
  126. package/src/renderer/components/schedules/calendar/index.ts +2 -0
  127. package/src/renderer/components/schedules/calendar/types.ts +44 -0
  128. package/src/renderer/components/search/CommandPalette.tsx +4 -4
  129. package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
  130. package/src/renderer/components/settings/SettingsView.tsx +30 -35
  131. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
  132. package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
  133. package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
  134. package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
  135. package/src/renderer/components/settings/sections/CliStatusSection.tsx +72 -113
  136. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  137. package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
  138. package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
  139. package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
  140. package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
  141. package/src/renderer/components/settings/sections/index.ts +0 -1
  142. package/src/renderer/components/sidebar/SessionFiltersPopover.tsx +1 -1
  143. package/src/renderer/components/sidebar/SessionItem.tsx +3 -3
  144. package/src/renderer/components/sidebar/SidebarSessions.tsx +184 -6
  145. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
  146. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +40 -5
  147. package/src/renderer/components/splash/splashScene.ts +121 -929
  148. package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
  149. package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
  150. package/src/renderer/components/tasks/TasksView.tsx +112 -134
  151. package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
  152. package/src/renderer/components/team/ClaudeLogsFilterPopover.tsx +1 -1
  153. package/src/renderer/components/team/ClaudeLogsPanel.tsx +1 -1
  154. package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
  155. package/src/renderer/components/team/ProcessesSection.tsx +2 -2
  156. package/src/renderer/components/team/TaskTooltip.tsx +2 -2
  157. package/src/renderer/components/team/TeamDetailView.tsx +319 -123
  158. package/src/renderer/components/team/TeamListFilterPopover.tsx +1 -1
  159. package/src/renderer/components/team/TeamListView.tsx +109 -124
  160. package/src/renderer/components/team/TeamSessionsSection.tsx +6 -6
  161. package/src/renderer/components/team/UnreadCommentsBadge.tsx +1 -1
  162. package/src/renderer/components/team/activity/ActivityItem.tsx +9 -9
  163. package/src/renderer/components/team/activity/ActivityTimeline.tsx +5 -5
  164. package/src/renderer/components/team/activity/LeadThoughtsGroup.tsx +3 -3
  165. package/src/renderer/components/team/activity/ReplyQuoteBlock.tsx +4 -4
  166. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +4 -4
  167. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
  168. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
  169. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
  170. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +18 -16
  171. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
  172. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +8 -1
  173. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +5 -5
  174. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
  175. package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +6 -6
  176. package/src/renderer/components/team/dialogs/SkipPermissionsCheckbox.tsx +6 -6
  177. package/src/renderer/components/team/dialogs/StatusHistoryTimeline.tsx +1 -1
  178. package/src/renderer/components/team/dialogs/TaskAttachments.tsx +1 -1
  179. package/src/renderer/components/team/dialogs/TaskCommentInput.tsx +6 -6
  180. package/src/renderer/components/team/dialogs/TaskCommentsSection.tsx +4 -4
  181. package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +3 -3
  182. package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
  183. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
  184. package/src/renderer/components/team/editor/EditorFileTree.tsx +4 -4
  185. package/src/renderer/components/team/editor/EditorSearchPanel.tsx +1 -1
  186. package/src/renderer/components/team/editor/MarkdownSplitView.tsx +1 -1
  187. package/src/renderer/components/team/editor/NewFileDialog.tsx +1 -1
  188. package/src/renderer/components/team/editor/ProjectEditorOverlay.tsx +1 -1
  189. package/src/renderer/components/team/editor/SearchInFilesPanel.tsx +1 -1
  190. package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
  191. package/src/renderer/components/team/kanban/KanbanFilterPopover.tsx +4 -4
  192. package/src/renderer/components/team/kanban/KanbanSearchInput.tsx +1 -1
  193. package/src/renderer/components/team/kanban/KanbanSortPopover.tsx +5 -5
  194. package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +4 -4
  195. package/src/renderer/components/team/members/MemberCard.tsx +14 -47
  196. package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
  197. package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
  198. package/src/renderer/components/team/members/MemberDraftRow.tsx +1 -1
  199. package/src/renderer/components/team/members/MemberStatsTab.tsx +2 -2
  200. package/src/renderer/components/team/members/MemberWorkspaceTab.tsx +1 -1
  201. package/src/renderer/components/team/messages/MessageComposer.tsx +10 -112
  202. package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +1 -1
  203. package/src/renderer/components/team/messages/MessagesPanel.tsx +136 -119
  204. package/src/renderer/components/team/review/ChangeReviewDialog.tsx +1 -1
  205. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +3 -3
  206. package/src/renderer/components/team/sidebar/TeamSidebarRail.tsx +4 -4
  207. package/src/renderer/components/team/tasks/TaskRow.tsx +1 -1
  208. package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
  209. package/src/renderer/components/team/tools/McpChip.tsx +6 -3
  210. package/src/renderer/components/team/tools/SkillChip.tsx +3 -3
  211. package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
  212. package/src/renderer/components/ui/MemberSelect.tsx +2 -2
  213. package/src/renderer/components/ui/MentionSuggestionList.tsx +2 -2
  214. package/src/renderer/components/ui/MentionableTextarea.tsx +3 -3
  215. package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
  216. package/src/renderer/index.css +56 -39
  217. package/src/renderer/index.html +17 -50
  218. package/src/renderer/store/index.ts +2 -1
  219. package/src/renderer/store/slices/scheduleSlice.ts +1 -1
  220. package/src/renderer/store/slices/teamSlice.ts +45 -168
  221. package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
  222. package/src/renderer/utils/memberHelpers.ts +5 -17
  223. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
  224. package/src/renderer/utils/providerSlashCommands.ts +0 -5
  225. package/src/renderer/utils/scheduleFormatters.ts +3 -1
  226. package/src/renderer/utils/teamMessageFiltering.ts +14 -1
  227. package/src/renderer/utils/teamModelAvailability.ts +18 -2
  228. package/src/shared/types/api.ts +121 -2
  229. package/src/shared/types/ccConnect.ts +2 -0
  230. package/src/shared/types/index.ts +3 -0
  231. package/src/shared/types/systemManager.ts +49 -0
  232. package/src/shared/types/team.ts +29 -0
  233. package/src/shared/types/terminal.ts +4 -2
  234. package/src/shared/utils/extensionNormalizers.ts +15 -8
  235. package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
  236. package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
  237. package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
  238. package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
  239. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
  240. package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
  241. package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
  242. package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
  243. 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(59, 130, 246, 0.45)',
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-blue-600 dark:text-blue-400" />
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: '#3b82f6' }}
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: '#3b82f6' }}
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-blue-600 dark:text-blue-400" />
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-blue-600 dark:text-blue-400" />
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: '#3b82f6' }}
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 { PlugZap, Sparkles, Users, Workflow } from 'lucide-react';
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
- <PlugZap className="size-3.5" />
86
- 渠道接入
74
+ <Sparkles className="size-3.5" />
75
+ 会话洞察
87
76
  </div>
88
77
  <p className="text-xs text-text-muted">
89
- 统一托管企业 IM、社区渠道和 Webhook/API,消息流和任务流自动对齐。
78
+ 汇总本地会话、任务、消息和 Token 使用情况,帮助你判断团队执行状态。
90
79
  </p>
91
- <div className="mt-3 flex flex-wrap gap-1.5">
92
- {HIGHLIGHT_CHANNELS.map((channel) => (
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-3">
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">第 3 步</p>
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 { getCliProviderExtensionCapabilities } from '@shared/utils/providerExtensionCapabilities';
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: 3 }, (_, index) => (
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
- 扩展需要配置好的运行时来管理 MCP 服务器、技能和提供商连接。
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
- if (isMultimodel) {
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 && !api.mcpRegistry && !api.skills) {
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-blue-500/30 bg-blue-500/5 px-4 py-3 text-sm text-blue-400">
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' | 'mcp-servers' | 'skills' | 'env-vars';
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-blue-500/10',
48
- border: 'border-blue-500/30',
47
+ bg: 'bg-indigo-500/10',
48
+ border: 'border-indigo-500/30',
49
49
  icon: Info,
50
- iconColor: 'text-blue-400',
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-blue-500/30 bg-blue-500/10 text-blue-400" variant="outline">
14
+ <Badge className="border-indigo-500/30 bg-indigo-500/10 text-indigo-400" variant="outline">
15
15
  Official
16
16
  </Badge>
17
17
  );