@yancyyu/openhermit 1.6.37 → 1.6.39

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 (205) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-krO5vQxX.js +58 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-DYT3bwFR.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-Dbt_EU-e.js → _basePickBy-B7kSYPxr.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-DWo68sXI.js → _baseUniq-CnjxqwAk.js} +1 -1
  5. package/dist-renderer/assets/{arc-DXH1iZQK.js → arc-CLeZuINP.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-cjffS2Qr.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-BKdZF02Y.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-CN27pqaI.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
  9. package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-CXPCI7g_.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-BGAXQZRC.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-TPDaA_KQ.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-D1ADe_tq.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-Beimtg3a.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-OjNBu854.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-DinqvbH8.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-BfFtlPSZ.js → chunk-TZMSLE5B-Ds1hInvp.js} +1 -1
  18. package/dist-renderer/assets/classDiagram-2ON5EDUG-CBYCBVRl.js +1 -0
  19. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-CBYCBVRl.js +1 -0
  20. package/dist-renderer/assets/clone-DcMF6Psb.js +1 -0
  21. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-D9z9Dgt7.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-n1g-DhEE.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-BvxFq-BE.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-wVnJuwza.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-B707WJQw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-C-_1dGHs.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CMTSi3H6.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-DZ0bNrAA.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-DNVfGooQ.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
  30. package/dist-renderer/assets/{graph-865j_tM_.js → graph-CsoEwUhS.js} +1 -1
  31. package/dist-renderer/assets/{index-C_F9N5x-.js → index-BWPWmJNo.js} +1 -1
  32. package/dist-renderer/assets/{index-LwDIsXJN.js → index-Bu2R-Se7.js} +586 -740
  33. package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
  34. package/dist-renderer/assets/{index-DuUaf8at.js → index-D-3KgskL.js} +1 -1
  35. package/dist-renderer/assets/{index-BTx1nc4T.js → index-DGEBzLNT.js} +1 -1
  36. package/dist-renderer/assets/{index-2EW-eu3q.js → index-NhHNs2Oo.js} +1 -1
  37. package/dist-renderer/assets/{index-4dEMStJj.js → index-h17WuEyf.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-CyqtElLq.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-BvjQ0Hm0.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-CJJ-k0zT.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
  41. package/dist-renderer/assets/{layout-CnV6rQAG.js → layout-C3XWrpwo.js} +1 -1
  42. package/dist-renderer/assets/{linear-Cw3UQgyX.js → linear-OEEcn8KN.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-C5tDaGSK.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-CiIpPsau.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-C3gtowNj.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-CXBTrAnU.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-wziX77xG.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-sYqopcrj.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
  49. package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
  50. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-Bl1-0_Cp.js → stateDiagram-FKZM4ZOC-B2FY5qqi.js} +1 -1
  51. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DcoMiR8H.js +1 -0
  52. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-CIRjJUBo.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
  53. package/dist-renderer/assets/{treemap-GDKQZRPO-CVPuNe1n.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
  54. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-3nT9yHwp.js → xychartDiagram-PRI3JC2R-J6VVJzRq.js} +1 -1
  55. package/dist-renderer/index.html +20 -53
  56. package/package.json +25 -18
  57. package/src/main/ipc/extensions.ts +30 -50
  58. package/src/main/server.ts +890 -247
  59. package/src/main/services/extensions/ExtensionFacadeService.ts +4 -56
  60. package/src/main/services/extensions/catalog/PluginCatalogService.ts +4 -2
  61. package/src/main/services/extensions/library/McpLibraryService.ts +243 -0
  62. package/src/main/services/session-intelligence/ConversationTelemetryService.ts +1101 -0
  63. package/src/main/services/session-intelligence/LocalSessionScanner.ts +512 -0
  64. package/src/main/services/session-intelligence/SessionUsageParser.ts +4 -4
  65. package/src/main/services/session-intelligence/UsageTelemetryService.ts +14 -1
  66. package/src/main/services/system-manager/SystemManagerConfigService.ts +122 -0
  67. package/src/main/services/system-manager/SystemManagerPtyService.ts +233 -0
  68. package/src/main/services/system-manager/WorkflowPromptService.ts +75 -0
  69. package/src/main/services/teams-mvp/TaskDispatchService.ts +32 -8
  70. package/src/main/services/teams-mvp/TeamProvisioningService.ts +39 -2
  71. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +22 -4
  72. package/src/main/utils/teamProjectResolution.ts +15 -0
  73. package/src/renderer/App.tsx +8 -4
  74. package/src/renderer/api/httpClient.ts +174 -38
  75. package/src/renderer/api/providers.ts +23 -2
  76. package/src/renderer/assets/participant-avatars/01.svg +3 -0
  77. package/src/renderer/assets/participant-avatars/02.svg +3 -0
  78. package/src/renderer/assets/participant-avatars/03.svg +3 -0
  79. package/src/renderer/assets/participant-avatars/04.svg +3 -0
  80. package/src/renderer/assets/participant-avatars/05.svg +3 -0
  81. package/src/renderer/assets/participant-avatars/06.svg +3 -0
  82. package/src/renderer/assets/participant-avatars/07.svg +3 -0
  83. package/src/renderer/assets/participant-avatars/08.svg +3 -0
  84. package/src/renderer/assets/participant-avatars/09.svg +3 -0
  85. package/src/renderer/assets/participant-avatars/10.svg +3 -0
  86. package/src/renderer/assets/participant-avatars/11.svg +3 -0
  87. package/src/renderer/assets/participant-avatars/12.svg +3 -0
  88. package/src/renderer/assets/participant-avatars/13.svg +3 -0
  89. package/src/renderer/components/common/TerminalPane.tsx +213 -0
  90. package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
  91. package/src/renderer/components/extensions/ExtensionStoreView.tsx +12 -221
  92. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  93. package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
  94. package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
  95. package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
  96. package/src/renderer/components/extensions/plugins/PluginCard.tsx +10 -2
  97. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +40 -22
  98. package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
  99. package/src/renderer/components/layout/PaneContent.tsx +8 -1
  100. package/src/renderer/components/layout/Sidebar.tsx +11 -54
  101. package/src/renderer/components/layout/SortableTab.tsx +20 -31
  102. package/src/renderer/components/layout/TabBar.tsx +1 -1
  103. package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
  104. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
  105. package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
  106. package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
  107. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
  108. package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
  109. package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
  110. package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
  111. package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
  112. package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
  113. package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
  114. package/src/renderer/components/schedules/calendar/index.ts +2 -0
  115. package/src/renderer/components/schedules/calendar/types.ts +44 -0
  116. package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
  117. package/src/renderer/components/settings/SettingsView.tsx +30 -35
  118. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
  119. package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
  120. package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
  121. package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
  122. package/src/renderer/components/settings/sections/CliStatusSection.tsx +71 -112
  123. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  124. package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
  125. package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
  126. package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
  127. package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
  128. package/src/renderer/components/settings/sections/index.ts +0 -1
  129. package/src/renderer/components/sidebar/SidebarSessions.tsx +182 -4
  130. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
  131. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +39 -4
  132. package/src/renderer/components/splash/splashScene.ts +121 -929
  133. package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
  134. package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
  135. package/src/renderer/components/tasks/TasksView.tsx +112 -134
  136. package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
  137. package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
  138. package/src/renderer/components/team/TeamDetailView.tsx +325 -114
  139. package/src/renderer/components/team/TeamListView.tsx +108 -123
  140. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +2 -2
  141. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
  142. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
  143. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
  144. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +17 -15
  145. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
  146. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +7 -0
  147. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +1 -1
  148. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
  149. package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
  150. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
  151. package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
  152. package/src/renderer/components/team/members/MemberCard.tsx +14 -47
  153. package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
  154. package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
  155. package/src/renderer/components/team/messages/MessageComposer.tsx +8 -110
  156. package/src/renderer/components/team/messages/MessagesPanel.tsx +131 -114
  157. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +2 -2
  158. package/src/renderer/components/team/tools/AddMcpInline.tsx +57 -0
  159. package/src/renderer/components/team/tools/AddSkillInline.tsx +61 -0
  160. package/src/renderer/components/team/tools/McpChip.tsx +45 -0
  161. package/src/renderer/components/team/tools/SkillChip.tsx +35 -0
  162. package/src/renderer/components/team/tools/ToolsSection.tsx +556 -0
  163. package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
  164. package/src/renderer/index.css +39 -22
  165. package/src/renderer/index.html +17 -50
  166. package/src/renderer/store/index.ts +2 -1
  167. package/src/renderer/store/slices/scheduleSlice.ts +1 -1
  168. package/src/renderer/store/slices/teamSlice.ts +45 -168
  169. package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
  170. package/src/renderer/utils/memberHelpers.ts +5 -17
  171. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
  172. package/src/renderer/utils/providerSlashCommands.ts +0 -5
  173. package/src/renderer/utils/scheduleFormatters.ts +3 -1
  174. package/src/renderer/utils/teamMessageFiltering.ts +14 -1
  175. package/src/renderer/utils/teamModelAvailability.ts +18 -2
  176. package/src/shared/types/api.ts +121 -2
  177. package/src/shared/types/ccConnect.ts +2 -0
  178. package/src/shared/types/extensions/api.ts +9 -0
  179. package/src/shared/types/extensions/index.ts +4 -0
  180. package/src/shared/types/extensions/mcp.ts +41 -0
  181. package/src/shared/types/index.ts +3 -0
  182. package/src/shared/types/systemManager.ts +49 -0
  183. package/src/shared/types/team.ts +29 -0
  184. package/src/shared/types/terminal.ts +4 -2
  185. package/src/shared/utils/extensionNormalizers.ts +29 -0
  186. package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
  187. package/dist-renderer/assets/ProjectEditorOverlay-Va_Vz-zz.js +0 -52
  188. package/dist-renderer/assets/channel-5dJIx68e.js +0 -1
  189. package/dist-renderer/assets/classDiagram-2ON5EDUG-BMGXWJ2d.js +0 -1
  190. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-BMGXWJ2d.js +0 -1
  191. package/dist-renderer/assets/clone-D7FWfGY9.js +0 -1
  192. package/dist-renderer/assets/index-B2z_IyRH.css +0 -1
  193. package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
  194. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DOYYvDbi.js +0 -1
  195. package/src/main/services/extensions/catalog/GlamaMcpEnrichmentService.ts +0 -190
  196. package/src/main/services/extensions/catalog/McpCatalogAggregator.ts +0 -150
  197. package/src/main/services/extensions/catalog/OfficialMcpRegistryService.ts +0 -381
  198. package/src/main/services/extensions/install/McpInstallService.ts +0 -407
  199. package/src/main/services/extensions/state/McpInstallationStateService.ts +0 -42
  200. package/src/renderer/components/extensions/mcp/McpServerCard.tsx +0 -314
  201. package/src/renderer/components/extensions/mcp/McpServerDetailDialog.tsx +0 -765
  202. package/src/renderer/components/extensions/mcp/McpServersPanel.tsx +0 -593
  203. package/src/renderer/components/extensions/skills/SkillDetailDialog.tsx +0 -372
  204. package/src/renderer/components/extensions/skills/SkillImportDialog.tsx +0 -343
  205. package/src/renderer/components/extensions/skills/SkillsPanel.tsx +0 -659
@@ -10,9 +10,9 @@ import {
10
10
  } from 'react';
11
11
  import { Sheet, type SheetRef } from 'react-modal-sheet';
12
12
 
13
- import { api } from '@renderer/api';
14
13
  import { Badge } from '@renderer/components/ui/badge';
15
14
  import { Button } from '@renderer/components/ui/button';
15
+ import { MemberBadge } from '@renderer/components/team/MemberBadge';
16
16
  import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
17
17
  import { useStableTeamMentionMeta } from '@renderer/hooks/useStableTeamMentionMeta';
18
18
  import { useTeamMessagesExpanded } from '@renderer/hooks/useTeamMessagesExpanded';
@@ -20,6 +20,7 @@ import { useTeamMessagesRead } from '@renderer/hooks/useTeamMessagesRead';
20
20
  import { useStore } from '@renderer/store';
21
21
  import { selectTeamMessages } from '@renderer/store/slices/teamSlice';
22
22
  import { filterTeamMessages } from '@renderer/utils/teamMessageFiltering';
23
+ import { cn } from '@renderer/lib/utils';
23
24
  import { toMessageKey } from '@renderer/utils/teamMessageKey';
24
25
  import { shouldExcludeInboxTextFromReplyCandidates } from '@shared/utils/idleNotificationSemantics';
25
26
  import {
@@ -56,7 +57,6 @@ import type { TeamMessagesPanelMode } from '@renderer/types/teamMessagesPanelMod
56
57
  import type {
57
58
  AgentActionMode,
58
59
  CcSession,
59
- CcSessionDetail,
60
60
  InboxMessage,
61
61
  ResolvedTeamMember,
62
62
  TaskRef,
@@ -93,6 +93,8 @@ interface MessagesPanelProps {
93
93
  timeWindow: TimeWindow | null;
94
94
  /** Current lead session ID. */
95
95
  currentLeadSessionId?: string;
96
+ /** cc-connect sessions owned by the parent team detail view. */
97
+ sessions?: CcSession[];
96
98
  /** Pending replies tracker (shared with parent for MemberList). */
97
99
  pendingRepliesByMember: Record<string, number>;
98
100
  /** Update pending replies tracker. */
@@ -186,6 +188,7 @@ export const MessagesPanel = memo(function MessagesPanel({
186
188
  leadContextUpdatedAt,
187
189
  timeWindow,
188
190
  currentLeadSessionId,
191
+ sessions = [],
189
192
  pendingRepliesByMember,
190
193
  onPendingReplyChange,
191
194
  onMemberClick,
@@ -334,10 +337,8 @@ export const MessagesPanel = memo(function MessagesPanel({
334
337
  const [expandedItemKey, setExpandedItemKey] = useState<string | null>(
335
338
  initialSidebarStateRef.current.expandedItemKey
336
339
  );
337
- const [teamSessions, setTeamSessions] = useState<CcSession[]>([]);
338
- const [selectedSessionDetail, setSelectedSessionDetail] = useState<CcSessionDetail | null>(null);
339
- const [selectedSessionDetailLoading, setSelectedSessionDetailLoading] = useState(false);
340
340
  const [selectedSessionKey, setSelectedSessionKey] = useState<string | null>(null);
341
+ const [quickParticipantFilter, setQuickParticipantFilter] = useState<string | null>(null);
341
342
  const [messagesScrollTop, setMessagesScrollTop] = useState(
342
343
  initialSidebarStateRef.current.messagesScrollTop
343
344
  );
@@ -355,70 +356,25 @@ export const MessagesPanel = memo(function MessagesPanel({
355
356
  setMessagesCollapsed(initialSidebarStateRef.current.messagesCollapsed);
356
357
  setMessagesSearchBarVisible(initialSidebarStateRef.current.messagesSearchBarVisible);
357
358
  setExpandedItemKey(initialSidebarStateRef.current.expandedItemKey);
359
+ setSelectedSessionKey(null);
360
+ setQuickParticipantFilter(null);
358
361
  setMessagesScrollTop(initialSidebarStateRef.current.messagesScrollTop);
359
362
  setBottomSheetSnapIndex(initialSidebarStateRef.current.bottomSheetSnapIndex);
360
363
  }, [teamName]);
361
364
 
362
- useEffect(() => {
363
- let cancelled = false;
364
- void api.teams
365
- .getTeamSessions(teamName)
366
- .then((sessions) => {
367
- if (cancelled) return;
368
- const sortedSessions = [...sessions].sort(
369
- (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
370
- );
371
- setTeamSessions(sortedSessions);
372
- setSelectedSessionKey((current) => {
373
- if (current && sortedSessions.some((session) => session.sessionKey === current))
374
- return current;
375
- return sortedSessions[0]?.sessionKey ?? null;
376
- });
377
- })
378
- .catch(() => {
379
- if (!cancelled) {
380
- setTeamSessions([]);
381
- setSelectedSessionKey(null);
382
- }
383
- });
384
- return () => {
385
- cancelled = true;
386
- };
387
- // Refetch when the lead session id changes (e.g. a new session is spawned)
388
- // so the session list/selector reflects the updated id without a remount.
389
- }, [teamName, currentLeadSessionId]);
390
-
391
- const selectedSession = useMemo(
392
- () => teamSessions.find((session) => session.sessionKey === selectedSessionKey) ?? null,
393
- [selectedSessionKey, teamSessions]
365
+ const teamSessions = useMemo(
366
+ () =>
367
+ [...sessions].sort(
368
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
369
+ ),
370
+ [sessions]
394
371
  );
395
- const selectedIsHermitLocalSession =
396
- selectedSession?.platform === 'hermit' ||
397
- selectedSession?.sessionKey === `hermit:${teamName}:session`;
398
372
 
399
373
  useEffect(() => {
400
- if (!selectedSession || selectedIsHermitLocalSession) {
401
- setSelectedSessionDetail(null);
402
- setSelectedSessionDetailLoading(false);
403
- return;
404
- }
405
- let cancelled = false;
406
- setSelectedSessionDetailLoading(true);
407
- void api.teams
408
- .getSessionDetail(teamName, selectedSession.id, 200)
409
- .then((detail) => {
410
- if (!cancelled) setSelectedSessionDetail(detail);
411
- })
412
- .catch(() => {
413
- if (!cancelled) setSelectedSessionDetail(null);
414
- })
415
- .finally(() => {
416
- if (!cancelled) setSelectedSessionDetailLoading(false);
417
- });
418
- return () => {
419
- cancelled = true;
420
- };
421
- }, [selectedIsHermitLocalSession, selectedSession, teamName]);
374
+ setSelectedSessionKey((current) =>
375
+ current && teamSessions.some((session) => session.sessionKey === current) ? current : null
376
+ );
377
+ }, [teamSessions]);
422
378
 
423
379
  useEffect(() => {
424
380
  setTeamMessagesSidebarUiState(teamName, {
@@ -541,64 +497,127 @@ export const MessagesPanel = memo(function MessagesPanel({
541
497
  const newestFirst = (items: InboxMessage[]) =>
542
498
  [...items].sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
543
499
  if (!selectedSessionKey) return newestFirst(effectiveMessages);
544
- if (selectedSession && !selectedIsHermitLocalSession) {
545
- if (!selectedSessionDetail) {
546
- return [];
547
- }
548
- return [...selectedSessionDetail.history].reverse().map(
549
- (entry, index): InboxMessage => ({
550
- messageId: `${selectedSessionDetail.id}:${index}:${entry.timestamp}`,
551
- from: entry.role === 'user' ? 'user' : selectedSessionDetail.name || teamName,
552
- to: entry.role === 'user' ? selectedSessionDetail.name || teamName : 'user',
553
- text: entry.content,
554
- timestamp: entry.timestamp,
555
- read: true,
556
- source: entry.role === 'user' ? 'user_sent' : 'inbox',
557
- session: {
558
- id: selectedSessionDetail.id,
559
- key: selectedSessionDetail.sessionKey,
560
- platform: selectedSessionDetail.platform,
561
- title:
562
- selectedSession.title ||
563
- selectedSession.chatName ||
564
- selectedSession.userName ||
565
- selectedSession.sessionKey,
566
- chatName: selectedSession.chatName,
567
- userName: selectedSession.userName,
568
- },
569
- })
570
- );
571
- }
572
500
  return newestFirst(
573
- effectiveMessages.filter((message) => {
574
- return message.session?.key === selectedSessionKey;
575
- })
501
+ effectiveMessages.filter((message) => message.session?.key === selectedSessionKey)
576
502
  );
577
- }, [
578
- effectiveMessages,
579
- selectedIsHermitLocalSession,
580
- selectedSession,
581
- selectedSessionDetail,
582
- selectedSessionKey,
583
- teamName,
584
- ]);
503
+ }, [effectiveMessages, selectedSessionKey]);
504
+
505
+ const participantOptions = useMemo(() => {
506
+ const senderNames = new Set<string>();
507
+ for (const message of sessionScopedMessages) {
508
+ const sender = message.from?.trim();
509
+ if (sender) senderNames.add(sender);
510
+ }
511
+
512
+ const seen = new Set<string>();
513
+ const orderedSenders: string[] = [];
514
+ const addSender = (value: string | null | undefined) => {
515
+ const trimmed = value?.trim();
516
+ if (!trimmed || seen.has(trimmed) || !senderNames.has(trimmed)) return;
517
+ seen.add(trimmed);
518
+ orderedSenders.push(trimmed);
519
+ };
520
+
521
+ addSender('user');
522
+ for (const member of members) addSender(member.name);
523
+ for (const message of sessionScopedMessages) addSender(message.from);
524
+
525
+ return orderedSenders.slice(0, 24);
526
+ }, [members, sessionScopedMessages]);
527
+
528
+ useEffect(() => {
529
+ if (quickParticipantFilter && !participantOptions.includes(quickParticipantFilter)) {
530
+ setQuickParticipantFilter(null);
531
+ }
532
+ }, [participantOptions, quickParticipantFilter]);
533
+
534
+ const matchesParticipant = useCallback((message: InboxMessage, participant: string): boolean => {
535
+ return message.from?.trim() === participant;
536
+ }, []);
585
537
 
586
538
  const filteredMessages = useMemo(() => {
587
- return filterTeamMessages(sessionScopedMessages, {
539
+ const participantFiltered = quickParticipantFilter
540
+ ? sessionScopedMessages.filter((message) =>
541
+ matchesParticipant(message, quickParticipantFilter)
542
+ )
543
+ : sessionScopedMessages;
544
+ return filterTeamMessages(participantFiltered, {
588
545
  timeWindow,
589
546
  filter: messagesFilter,
590
547
  searchQuery: messagesSearchQuery,
591
548
  });
592
- }, [messagesFilter, messagesSearchQuery, sessionScopedMessages, timeWindow]);
549
+ }, [
550
+ matchesParticipant,
551
+ messagesFilter,
552
+ messagesSearchQuery,
553
+ quickParticipantFilter,
554
+ sessionScopedMessages,
555
+ timeWindow,
556
+ ]);
557
+
558
+ const setParticipantFilter = useCallback((name: string | null) => {
559
+ setQuickParticipantFilter(name);
560
+ }, []);
561
+
562
+ const participantFilterBar = (
563
+ <div className="flex items-center gap-1 overflow-x-auto pb-1 text-[11px]">
564
+ <button
565
+ type="button"
566
+ className={cn(
567
+ 'shrink-0 rounded-full border px-2 py-0.5 transition-colors',
568
+ quickParticipantFilter === null
569
+ ? 'border-blue-500/40 bg-blue-500/10 text-blue-500'
570
+ : 'border-[var(--color-border)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]'
571
+ )}
572
+ onClick={() => setParticipantFilter(null)}
573
+ >
574
+ 全部成员
575
+ </button>
576
+ {participantOptions.map((participant) => (
577
+ <button
578
+ key={participant}
579
+ type="button"
580
+ className={cn(
581
+ 'shrink-0 rounded-full border px-2 py-0.5 transition-colors',
582
+ quickParticipantFilter === participant
583
+ ? 'border-blue-500/40 bg-blue-500/10 text-blue-500'
584
+ : 'border-[var(--color-border)] text-[var(--color-text-muted)] hover:text-[var(--color-text)]'
585
+ )}
586
+ onClick={() =>
587
+ setParticipantFilter(quickParticipantFilter === participant ? null : participant)
588
+ }
589
+ >
590
+ <MemberBadge
591
+ name={participant === 'user' ? '用户' : participant}
592
+ size="sm"
593
+ hideAvatar
594
+ disableHoverCard
595
+ />
596
+ </button>
597
+ ))}
598
+ </div>
599
+ );
593
600
 
594
601
  const activityTimelineMessages = useMemo(() => {
595
- return filterTeamMessages(sessionScopedMessages, {
602
+ const participantFiltered = quickParticipantFilter
603
+ ? sessionScopedMessages.filter((message) =>
604
+ matchesParticipant(message, quickParticipantFilter)
605
+ )
606
+ : sessionScopedMessages;
607
+ return filterTeamMessages(participantFiltered, {
596
608
  includePassiveIdlePeerSummariesWhenNoiseHidden: true,
597
609
  timeWindow,
598
610
  filter: messagesFilter,
599
611
  searchQuery: messagesSearchQuery,
600
612
  });
601
- }, [messagesFilter, messagesSearchQuery, sessionScopedMessages, timeWindow]);
613
+ }, [
614
+ matchesParticipant,
615
+ messagesFilter,
616
+ messagesSearchQuery,
617
+ quickParticipantFilter,
618
+ sessionScopedMessages,
619
+ timeWindow,
620
+ ]);
602
621
 
603
622
  const replyCandidateMessages = useMemo(
604
623
  () =>
@@ -773,6 +792,10 @@ export const MessagesPanel = memo(function MessagesPanel({
773
792
  toTeam,
774
793
  text: description,
775
794
  messageId: optimisticMessageId,
795
+ sessionKey:
796
+ selectedSessionKey && selectedSessionKey !== '__unassigned__'
797
+ ? selectedSessionKey
798
+ : undefined,
776
799
  });
777
800
  } catch (error) {
778
801
  const rawMessage = error instanceof Error ? error.message : '跨团队任务派发失败';
@@ -935,13 +958,11 @@ export const MessagesPanel = memo(function MessagesPanel({
935
958
  sendWarning={sendMessageWarning}
936
959
  sendDebugDetails={sendMessageDebugDetails}
937
960
  lastResult={lastSendMessageResult}
938
- sessions={teamSessions}
939
- selectedSessionKey={selectedSessionKey}
940
- onSessionChange={setSelectedSessionKey}
941
961
  textareaRef={composerTextareaRef}
942
962
  onSend={handleSend}
943
963
  onDispatchTask={handleDispatchTaskToTeam}
944
964
  />
965
+ {participantFilterBar}
945
966
  <StatusBlock
946
967
  members={members}
947
968
  tasks={tasks}
@@ -1132,13 +1153,11 @@ export const MessagesPanel = memo(function MessagesPanel({
1132
1153
  sendWarning={sendMessageWarning}
1133
1154
  sendDebugDetails={sendMessageDebugDetails}
1134
1155
  lastResult={lastSendMessageResult}
1135
- sessions={teamSessions}
1136
- selectedSessionKey={selectedSessionKey}
1137
- onSessionChange={setSelectedSessionKey}
1138
1156
  textareaRef={composerTextareaRef}
1139
1157
  onSend={handleSend}
1140
1158
  onDispatchTask={handleDispatchTaskToTeam}
1141
1159
  />
1160
+ {participantFilterBar}
1142
1161
  <StatusBlock
1143
1162
  members={members}
1144
1163
  tasks={tasks}
@@ -1420,13 +1439,11 @@ export const MessagesPanel = memo(function MessagesPanel({
1420
1439
  sendWarning={sendMessageWarning}
1421
1440
  sendDebugDetails={sendMessageDebugDetails}
1422
1441
  lastResult={lastSendMessageResult}
1423
- sessions={teamSessions}
1424
- selectedSessionKey={selectedSessionKey}
1425
- onSessionChange={setSelectedSessionKey}
1426
1442
  textareaRef={composerTextareaRef}
1427
1443
  onSend={handleSend}
1428
1444
  onDispatchTask={handleDispatchTaskToTeam}
1429
1445
  />
1446
+ {participantFilterBar}
1430
1447
  </div>
1431
1448
  </div>
1432
1449
  <div className="shrink-0 px-3 pt-2">
@@ -20,7 +20,7 @@ interface ScheduleStatusBadgeProps {
20
20
  }
21
21
 
22
22
  export const ScheduleStatusBadge = ({ status }: ScheduleStatusBadgeProps): React.JSX.Element => {
23
- const config = SCHEDULE_STATUS_CONFIG[status];
23
+ const config = SCHEDULE_STATUS_CONFIG[status] ?? { label: status, className: 'bg-zinc-500/15 text-zinc-400 border-zinc-500/20' };
24
24
  return (
25
25
  <span
26
26
  className={`inline-flex items-center rounded-full border px-1.5 py-0.5 text-[10px] font-medium ${config.className}`}
@@ -50,6 +50,6 @@ interface RunStatusBadgeProps {
50
50
  }
51
51
 
52
52
  export const RunStatusBadge = ({ status }: RunStatusBadgeProps): React.JSX.Element => {
53
- const config = RUN_STATUS_CONFIG[status];
53
+ const config = RUN_STATUS_CONFIG[status] ?? { label: status, className: 'text-zinc-400' };
54
54
  return <span className={`text-[10px] font-medium ${config.className}`}>{config.label}</span>;
55
55
  };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * AddMcpInline — creates a reusable global MCP template from a team context.
3
+ */
4
+
5
+ import { useState } from 'react';
6
+
7
+ import { Button } from '@renderer/components/ui/button';
8
+ import { McpLibraryEntryDialog } from '@renderer/components/extensions/mcp/McpLibraryEntryDialog';
9
+
10
+ import type { McpLibraryEntry } from '@shared/types/extensions';
11
+
12
+ interface AddMcpInlineProps {
13
+ onAdded: (entry: McpLibraryEntry) => void;
14
+ onCancel: () => void;
15
+ }
16
+
17
+ export const AddMcpInline = ({ onAdded, onCancel }: AddMcpInlineProps): React.JSX.Element => {
18
+ const [dialogOpen, setDialogOpen] = useState(true);
19
+
20
+ const handleSaved = (entry: McpLibraryEntry): void => {
21
+ setDialogOpen(false);
22
+ onAdded(entry);
23
+ };
24
+
25
+ const handleClose = (): void => {
26
+ setDialogOpen(false);
27
+ onCancel();
28
+ };
29
+
30
+ return (
31
+ <>
32
+ <div className="flex items-center gap-2 rounded-md border border-dashed border-[var(--color-border)] px-2 py-2">
33
+ <div className="min-w-0 flex-1 text-xs text-[var(--color-text-muted)]">
34
+ 先保存一个全局模板,随后可为当前项目填写独立实例名和参数。
35
+ </div>
36
+ <Button
37
+ variant="outline"
38
+ size="sm"
39
+ className="h-7 gap-1 text-xs"
40
+ onClick={() => setDialogOpen(true)}
41
+ >
42
+ 添加模板
43
+ </Button>
44
+ <Button variant="ghost" size="sm" onClick={onCancel} className="h-7 text-xs">
45
+ 取消
46
+ </Button>
47
+ </div>
48
+
49
+ <McpLibraryEntryDialog
50
+ open={dialogOpen}
51
+ entry={null}
52
+ onClose={handleClose}
53
+ onSaved={handleSaved}
54
+ />
55
+ </>
56
+ );
57
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * AddSkillInline — inline compact form for adding a skill.
3
+ * Opens the existing SkillEditorDialog in create mode.
4
+ */
5
+
6
+ import { useState } from 'react';
7
+
8
+ import { Button } from '@renderer/components/ui/button';
9
+ import { SkillEditorDialog } from '@renderer/components/extensions/skills/SkillEditorDialog';
10
+
11
+ interface AddSkillInlineProps {
12
+ projectPath: string | null;
13
+ projectLabel?: string | null;
14
+ onAdded: () => void;
15
+ onCancel: () => void;
16
+ }
17
+
18
+ export const AddSkillInline = ({
19
+ projectPath,
20
+ projectLabel,
21
+ onAdded,
22
+ onCancel,
23
+ }: AddSkillInlineProps): React.JSX.Element => {
24
+ const [editorOpen, setEditorOpen] = useState(true);
25
+
26
+ const handleClose = () => {
27
+ setEditorOpen(false);
28
+ onCancel();
29
+ };
30
+
31
+ const handleSaved = () => {
32
+ setEditorOpen(false);
33
+ onAdded();
34
+ };
35
+
36
+ return (
37
+ <div className="flex items-center gap-2">
38
+ <Button
39
+ variant="outline"
40
+ size="sm"
41
+ className="h-7 gap-1 text-xs"
42
+ onClick={() => setEditorOpen(true)}
43
+ >
44
+ 创建新 Skill
45
+ </Button>
46
+ <Button variant="ghost" size="sm" onClick={onCancel} className="h-7 text-xs">
47
+ 取消
48
+ </Button>
49
+
50
+ <SkillEditorDialog
51
+ open={editorOpen}
52
+ onClose={handleClose}
53
+ onSaved={handleSaved}
54
+ mode="create"
55
+ projectPath={projectPath ?? null}
56
+ projectLabel={projectLabel ?? null}
57
+ detail={null}
58
+ />
59
+ </div>
60
+ );
61
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * McpChip — compact chip for an installed MCP server.
3
+ * Shows server name, status dot, and remove button on hover.
4
+ */
5
+
6
+ import { X } from 'lucide-react';
7
+
8
+ import type { InstalledMcpEntry, McpServerDiagnostic } from '@shared/types/extensions';
9
+
10
+ interface McpChipProps {
11
+ entry: InstalledMcpEntry;
12
+ diagnostic?: McpServerDiagnostic;
13
+ onRemove: (entry: InstalledMcpEntry) => void;
14
+ }
15
+
16
+ export const McpChip = ({ entry, diagnostic, onRemove }: McpChipProps): React.JSX.Element => {
17
+ // Default to green ("connected"). Only show a problem color when diagnostics
18
+ // explicitly report a failure or an auth requirement; absent/unknown status
19
+ // (e.g. diagnostics endpoint unavailable) is treated as healthy.
20
+ const statusColor =
21
+ diagnostic?.status === 'failed'
22
+ ? 'bg-red-500'
23
+ : diagnostic?.status === 'needs-authentication'
24
+ ? 'bg-amber-500'
25
+ : 'bg-emerald-500';
26
+
27
+ return (
28
+ <div className="group inline-flex items-center gap-1.5 rounded-full bg-[var(--color-bg-secondary)] px-2.5 py-1 text-xs transition-colors hover:bg-[var(--color-bg-secondary-hover)]">
29
+ <span
30
+ className={`size-2 shrink-0 rounded-full ${statusColor}`}
31
+ title={diagnostic?.status ?? 'unknown'}
32
+ />
33
+ <span className="max-w-[120px] truncate text-[var(--color-text)]">{entry.name}</span>
34
+ <button
35
+ type="button"
36
+ className="shrink-0 rounded-full p-0.5 opacity-0 transition-opacity hover:bg-red-500/20 group-hover:opacity-100"
37
+ onClick={() => onRemove(entry)}
38
+ aria-label={`从当前项目移除 MCP 实例 ${entry.name}`}
39
+ title="移除项目实例"
40
+ >
41
+ <X size={10} className="text-[var(--color-text-muted)] hover:text-red-400" />
42
+ </button>
43
+ </div>
44
+ );
45
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * SkillChip — compact chip for a skill.
3
+ * Shows skill name, scope badge, and remove button on hover.
4
+ */
5
+
6
+ import { X } from 'lucide-react';
7
+
8
+ import type { SkillCatalogItem } from '@shared/types/extensions';
9
+
10
+ interface SkillChipProps {
11
+ skill: SkillCatalogItem;
12
+ onRemove: (skill: SkillCatalogItem) => void;
13
+ }
14
+
15
+ export const SkillChip = ({ skill, onRemove }: SkillChipProps): React.JSX.Element => {
16
+ return (
17
+ <div className="group inline-flex items-center gap-1.5 rounded-full bg-[var(--color-bg-secondary)] px-2.5 py-1 text-xs transition-colors hover:bg-[var(--color-bg-secondary-hover)]">
18
+ <span className="max-w-[120px] truncate text-[var(--color-text)]">{skill.name}</span>
19
+ {skill.scope && (
20
+ <span className="rounded bg-blue-500/20 px-1 py-0.5 text-[10px] text-blue-400">
21
+ {skill.scope === 'project' ? '项目' : '用户'}
22
+ </span>
23
+ )}
24
+ <button
25
+ type="button"
26
+ className="shrink-0 rounded-full p-0.5 opacity-0 transition-opacity hover:bg-red-500/20 group-hover:opacity-100"
27
+ onClick={() => onRemove(skill)}
28
+ aria-label={`从当前团队禁用 ${skill.name}`}
29
+ title="从当前团队禁用"
30
+ >
31
+ <X size={10} className="text-[var(--color-text-muted)] hover:text-red-400" />
32
+ </button>
33
+ </div>
34
+ );
35
+ };