@yancyyu/openhermit 1.6.38 → 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 (188) hide show
  1. package/dist-renderer/assets/ProjectEditorOverlay-krO5vQxX.js +58 -0
  2. package/dist-renderer/assets/{TeamGraphOverlay-ZEDfZyHb.js → TeamGraphOverlay-DqhQzcTr.js} +1 -1
  3. package/dist-renderer/assets/{_basePickBy-CIhniz70.js → _basePickBy-B7kSYPxr.js} +1 -1
  4. package/dist-renderer/assets/{_baseUniq-cKAW4Q8I.js → _baseUniq-CnjxqwAk.js} +1 -1
  5. package/dist-renderer/assets/{arc-YmNsoDXW.js → arc-CLeZuINP.js} +1 -1
  6. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DHEls2sX.js → architectureDiagram-VXUJARFQ-QKtqaqdY.js} +1 -1
  7. package/dist-renderer/assets/{blockDiagram-VD42YOAC-Bpwf1Sbg.js → blockDiagram-VD42YOAC-BqdrzO_f.js} +1 -1
  8. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B0IaQ4w5.js → c4Diagram-YG6GDRKO-gwPlCxDC.js} +1 -1
  9. package/dist-renderer/assets/channel-DpMHF50r.js +1 -0
  10. package/dist-renderer/assets/{chunk-4BX2VUAB-DLk-hcFc.js → chunk-4BX2VUAB-C6XLurL4.js} +1 -1
  11. package/dist-renderer/assets/{chunk-55IACEB6-1XRmX_Zm.js → chunk-55IACEB6-Ds6quhEP.js} +1 -1
  12. package/dist-renderer/assets/{chunk-B4BG7PRW-1waH1DAD.js → chunk-B4BG7PRW-5UlA1_e9.js} +1 -1
  13. package/dist-renderer/assets/{chunk-DI55MBZ5-BqpZBtrN.js → chunk-DI55MBZ5-ywFrqIsY.js} +1 -1
  14. package/dist-renderer/assets/{chunk-FMBD7UC4-Bly7vVym.js → chunk-FMBD7UC4-C7ifUA17.js} +1 -1
  15. package/dist-renderer/assets/{chunk-QN33PNHL-Ci2QWBAs.js → chunk-QN33PNHL-BxGCo80U.js} +1 -1
  16. package/dist-renderer/assets/{chunk-QZHKN3VN-YCqFW7d-.js → chunk-QZHKN3VN-B2CuaZs6.js} +1 -1
  17. package/dist-renderer/assets/{chunk-TZMSLE5B-B0xGXInl.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-DxcFNQKT.js → cose-bilkent-S5V4N54A-Cz1GVtLp.js} +1 -1
  22. package/dist-renderer/assets/{dagre-6UL2VRFP-DPo_RfZY.js → dagre-6UL2VRFP-BrmR-P4h.js} +1 -1
  23. package/dist-renderer/assets/{diagram-PSM6KHXK-U3hQsFe4.js → diagram-PSM6KHXK-DbNjC5Rg.js} +1 -1
  24. package/dist-renderer/assets/{diagram-QEK2KX5R-OrwrAy0V.js → diagram-QEK2KX5R-qkRX5_Mq.js} +1 -1
  25. package/dist-renderer/assets/{diagram-S2PKOQOG-CXATPWVw.js → diagram-S2PKOQOG-CyL5rCv2.js} +1 -1
  26. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-B0e8AfMF.js → erDiagram-Q2GNP2WA-Dox3-bA5.js} +1 -1
  27. package/dist-renderer/assets/{flowDiagram-NV44I4VS-CXfzA4jJ.js → flowDiagram-NV44I4VS-BtkaxlDL.js} +1 -1
  28. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-CMr08qVl.js → ganttDiagram-JELNMOA3-Dhy_d9GK.js} +1 -1
  29. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-vYFHpPmy.js → gitGraphDiagram-V2S2FVAM-B5XRhIQA.js} +1 -1
  30. package/dist-renderer/assets/{graph-DOe5j8dH.js → graph-CsoEwUhS.js} +1 -1
  31. package/dist-renderer/assets/{index-BySQS7AB.js → index-BWPWmJNo.js} +1 -1
  32. package/dist-renderer/assets/{index-V7dAKPqd.js → index-Bu2R-Se7.js} +587 -705
  33. package/dist-renderer/assets/index-CnWV3BhG.css +32 -0
  34. package/dist-renderer/assets/{index-CzWxVCRL.js → index-D-3KgskL.js} +1 -1
  35. package/dist-renderer/assets/{index-VJ-MM9xa.js → index-DGEBzLNT.js} +1 -1
  36. package/dist-renderer/assets/{index-B2Dy7M2G.js → index-NhHNs2Oo.js} +1 -1
  37. package/dist-renderer/assets/{index-C_okzZXP.js → index-h17WuEyf.js} +1 -1
  38. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-D_WubR0B.js → infoDiagram-HS3SLOUP-hMGmNojH.js} +1 -1
  39. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-w9ca-1TI.js → journeyDiagram-XKPGCS4Q-DXV2rBDl.js} +1 -1
  40. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-Jg9p6_pN.js → kanban-definition-3W4ZIXB7-Bf99WLRy.js} +1 -1
  41. package/dist-renderer/assets/{layout-B-z3y17c.js → layout-C3XWrpwo.js} +1 -1
  42. package/dist-renderer/assets/{linear-D-RTX5UW.js → linear-OEEcn8KN.js} +1 -1
  43. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-CDQmHOYP.js → mindmap-definition-VGOIOE7T-Dpi3S2x4.js} +1 -1
  44. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-D_odsQL7.js → pieDiagram-ADFJNKIX-xTPPhtNx.js} +1 -1
  45. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-BRsmYWSA.js → quadrantDiagram-AYHSOK5B-euniyDlz.js} +1 -1
  46. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-ChNE_BOV.js → requirementDiagram-UZGBJVZJ-D9Uiw4kF.js} +1 -1
  47. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8FtpwKc.js → sankeyDiagram-TZEHDZUN-CySU4nED.js} +1 -1
  48. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-DmLCzNcc.js → sequenceDiagram-WL72ISMW-JVGpET6V.js} +1 -1
  49. package/dist-renderer/assets/splashScene-D0YB9uxm.js +17 -0
  50. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-WJBm4bhu.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-BXs_hOJs.js → timeline-definition-IT6M3QCI-DmycNUUe.js} +1 -1
  53. package/dist-renderer/assets/{treemap-GDKQZRPO-o04MA0G9.js → treemap-GDKQZRPO-DPq4gZuB.js} +1 -1
  54. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-Czj69XRd.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 +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/common/TerminalPane.tsx +213 -0
  88. package/src/renderer/components/dashboard/DashboardView.tsx +9 -36
  89. package/src/renderer/components/extensions/ExtensionStoreView.tsx +6 -125
  90. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +1 -1
  91. package/src/renderer/components/extensions/mcp/McpLibraryEnableDialog.tsx +305 -0
  92. package/src/renderer/components/extensions/mcp/McpLibraryEntryDialog.tsx +418 -0
  93. package/src/renderer/components/extensions/mcp/McpLibraryPanel.tsx +404 -0
  94. package/src/renderer/components/extensions/plugins/PluginCard.tsx +6 -6
  95. package/src/renderer/components/extensions/plugins/PluginsPanel.tsx +34 -21
  96. package/src/renderer/components/extensions/skills/SkillsLibraryPanel.tsx +335 -0
  97. package/src/renderer/components/layout/PaneContent.tsx +8 -1
  98. package/src/renderer/components/layout/Sidebar.tsx +11 -54
  99. package/src/renderer/components/layout/SortableTab.tsx +20 -31
  100. package/src/renderer/components/layout/TabBar.tsx +1 -1
  101. package/src/renderer/components/layout/TabContextMenu.tsx +1 -1
  102. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +768 -157
  103. package/src/renderer/components/schedules/SchedulesView.tsx +51 -462
  104. package/src/renderer/components/schedules/calendar/CalendarDayView.tsx +173 -0
  105. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +113 -0
  106. package/src/renderer/components/schedules/calendar/CalendarHeader.tsx +148 -0
  107. package/src/renderer/components/schedules/calendar/CalendarMonthView.tsx +142 -0
  108. package/src/renderer/components/schedules/calendar/CalendarWeekView.tsx +219 -0
  109. package/src/renderer/components/schedules/calendar/ScheduleCalendarBoard.tsx +41 -0
  110. package/src/renderer/components/schedules/calendar/TeamGanttView.tsx +405 -0
  111. package/src/renderer/components/schedules/calendar/computeOccurrences.ts +234 -0
  112. package/src/renderer/components/schedules/calendar/index.ts +2 -0
  113. package/src/renderer/components/schedules/calendar/types.ts +44 -0
  114. package/src/renderer/components/settings/SettingsTabs.tsx +50 -55
  115. package/src/renderer/components/settings/SettingsView.tsx +30 -35
  116. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +5 -1
  117. package/src/renderer/components/settings/components/SettingsSelect.tsx +5 -3
  118. package/src/renderer/components/settings/components/SettingsToggle.tsx +2 -2
  119. package/src/renderer/components/settings/sections/AdvancedSection.tsx +11 -42
  120. package/src/renderer/components/settings/sections/CliStatusSection.tsx +71 -112
  121. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  122. package/src/renderer/components/settings/sections/GeneralSection.tsx +11 -3
  123. package/src/renderer/components/settings/sections/HarnessSection.tsx +18 -14
  124. package/src/renderer/components/settings/sections/PlatformsSection.tsx +3 -3
  125. package/src/renderer/components/settings/sections/TaskBusSection.tsx +33 -40
  126. package/src/renderer/components/settings/sections/index.ts +0 -1
  127. package/src/renderer/components/sidebar/SidebarSessions.tsx +182 -4
  128. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +4 -4
  129. package/src/renderer/components/sidebar/WorkspaceBrowser.tsx +39 -4
  130. package/src/renderer/components/splash/splashScene.ts +121 -929
  131. package/src/renderer/components/system-manager/FolderBrowser.tsx +163 -0
  132. package/src/renderer/components/system-manager/SystemManagerView.tsx +351 -0
  133. package/src/renderer/components/tasks/TasksView.tsx +112 -134
  134. package/src/renderer/components/team/CcSessionsSection.tsx +431 -89
  135. package/src/renderer/components/team/CollapsibleTeamSection.tsx +17 -32
  136. package/src/renderer/components/team/TeamDetailView.tsx +319 -123
  137. package/src/renderer/components/team/TeamListView.tsx +108 -123
  138. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +2 -2
  139. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +84 -306
  140. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +259 -342
  141. package/src/renderer/components/team/dialogs/GlobalTaskDetailDialog.tsx +1 -1
  142. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +17 -15
  143. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +221 -0
  144. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +7 -0
  145. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +1 -1
  146. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +361 -0
  147. package/src/renderer/components/team/dialogs/platformMeta.ts +122 -11
  148. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +17 -5
  149. package/src/renderer/components/team/kanban/KanbanBoard.tsx +9 -9
  150. package/src/renderer/components/team/members/MemberCard.tsx +14 -47
  151. package/src/renderer/components/team/members/MemberDetailDialog.tsx +3 -95
  152. package/src/renderer/components/team/members/MemberDetailStats.tsx +50 -65
  153. package/src/renderer/components/team/messages/MessageComposer.tsx +8 -110
  154. package/src/renderer/components/team/messages/MessagesPanel.tsx +131 -114
  155. package/src/renderer/components/team/schedule/ScheduleStatusBadge.tsx +2 -2
  156. package/src/renderer/components/team/tools/AddMcpInline.tsx +27 -17
  157. package/src/renderer/components/team/tools/McpChip.tsx +6 -3
  158. package/src/renderer/components/team/tools/SkillChip.tsx +2 -2
  159. package/src/renderer/components/team/tools/ToolsSection.tsx +418 -70
  160. package/src/renderer/hooks/useExtensionsTabState.ts +3 -114
  161. package/src/renderer/index.css +39 -22
  162. package/src/renderer/index.html +17 -50
  163. package/src/renderer/store/index.ts +2 -1
  164. package/src/renderer/store/slices/scheduleSlice.ts +1 -1
  165. package/src/renderer/store/slices/teamSlice.ts +45 -168
  166. package/src/renderer/utils/claudeCodeOnlyProviders.ts +3 -10
  167. package/src/renderer/utils/memberHelpers.ts +5 -17
  168. package/src/renderer/utils/openCodeRuntimeDeliveryDiagnostics.ts +4 -2
  169. package/src/renderer/utils/providerSlashCommands.ts +0 -5
  170. package/src/renderer/utils/scheduleFormatters.ts +3 -1
  171. package/src/renderer/utils/teamMessageFiltering.ts +14 -1
  172. package/src/renderer/utils/teamModelAvailability.ts +18 -2
  173. package/src/shared/types/api.ts +121 -2
  174. package/src/shared/types/ccConnect.ts +2 -0
  175. package/src/shared/types/index.ts +3 -0
  176. package/src/shared/types/systemManager.ts +49 -0
  177. package/src/shared/types/team.ts +29 -0
  178. package/src/shared/types/terminal.ts +4 -2
  179. package/src/shared/utils/extensionNormalizers.ts +15 -8
  180. package/src/shared/utils/providerExtensionCapabilities.ts +2 -2
  181. package/dist-renderer/assets/ProjectEditorOverlay-lJZi-9Hp.js +0 -52
  182. package/dist-renderer/assets/channel-yIlSKy0e.js +0 -1
  183. package/dist-renderer/assets/classDiagram-2ON5EDUG-24fHez0s.js +0 -1
  184. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-24fHez0s.js +0 -1
  185. package/dist-renderer/assets/clone-BTNuUva-.js +0 -1
  186. package/dist-renderer/assets/index-Bi6nrZ4z.css +0 -1
  187. package/dist-renderer/assets/splashScene-C8lWNnm4.js +0 -1
  188. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-_m6iPPUR.js +0 -1
@@ -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
  };
@@ -1,46 +1,56 @@
1
1
  /**
2
- * AddMcpInline — opens CustomMcpServerDialog for adding a custom MCP server.
3
- * Refreshes parent list when dialog closes (install may have occurred).
2
+ * AddMcpInline — creates a reusable global MCP template from a team context.
4
3
  */
5
4
 
6
5
  import { useState } from 'react';
7
6
 
8
7
  import { Button } from '@renderer/components/ui/button';
9
- import { CustomMcpServerDialog } from '@renderer/components/extensions/mcp/CustomMcpServerDialog';
8
+ import { McpLibraryEntryDialog } from '@renderer/components/extensions/mcp/McpLibraryEntryDialog';
9
+
10
+ import type { McpLibraryEntry } from '@shared/types/extensions';
10
11
 
11
12
  interface AddMcpInlineProps {
12
- projectPath: string | null;
13
- harnessType: string;
14
- onAdded: () => void;
13
+ onAdded: (entry: McpLibraryEntry) => void;
15
14
  onCancel: () => void;
16
15
  }
17
16
 
18
- export const AddMcpInline = ({
19
- onAdded,
20
- onCancel,
21
- }: AddMcpInlineProps): React.JSX.Element => {
17
+ export const AddMcpInline = ({ onAdded, onCancel }: AddMcpInlineProps): React.JSX.Element => {
22
18
  const [dialogOpen, setDialogOpen] = useState(true);
23
19
 
24
- const handleClose = () => {
20
+ const handleSaved = (entry: McpLibraryEntry): void => {
21
+ setDialogOpen(false);
22
+ onAdded(entry);
23
+ };
24
+
25
+ const handleClose = (): void => {
25
26
  setDialogOpen(false);
26
- // Always refresh when dialog closes — install may have happened
27
- onAdded();
27
+ onCancel();
28
28
  };
29
29
 
30
30
  return (
31
31
  <>
32
- <div className="flex items-center gap-2">
33
- <Button variant="outline" size="sm" className="h-7 gap-1 text-xs" onClick={() => setDialogOpen(true)}>
34
- 添加自定义 MCP
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
+ 添加模板
35
43
  </Button>
36
44
  <Button variant="ghost" size="sm" onClick={onCancel} className="h-7 text-xs">
37
45
  取消
38
46
  </Button>
39
47
  </div>
40
48
 
41
- <CustomMcpServerDialog
49
+ <McpLibraryEntryDialog
42
50
  open={dialogOpen}
51
+ entry={null}
43
52
  onClose={handleClose}
53
+ onSaved={handleSaved}
44
54
  />
45
55
  </>
46
56
  );
@@ -26,14 +26,17 @@ export const McpChip = ({ entry, diagnostic, onRemove }: McpChipProps): React.JS
26
26
 
27
27
  return (
28
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 className={`size-2 shrink-0 rounded-full ${statusColor}`} title={diagnostic?.status ?? 'unknown'} />
29
+ <span
30
+ className={`size-2 shrink-0 rounded-full ${statusColor}`}
31
+ title={diagnostic?.status ?? 'unknown'}
32
+ />
30
33
  <span className="max-w-[120px] truncate text-[var(--color-text)]">{entry.name}</span>
31
34
  <button
32
35
  type="button"
33
36
  className="shrink-0 rounded-full p-0.5 opacity-0 transition-opacity hover:bg-red-500/20 group-hover:opacity-100"
34
37
  onClick={() => onRemove(entry)}
35
- aria-label={`删除 ${entry.name}`}
36
- title="点击删除"
38
+ aria-label={`从当前项目移除 MCP 实例 ${entry.name}`}
39
+ title="移除项目实例"
37
40
  >
38
41
  <X size={10} className="text-[var(--color-text-muted)] hover:text-red-400" />
39
42
  </button>
@@ -25,8 +25,8 @@ export const SkillChip = ({ skill, onRemove }: SkillChipProps): React.JSX.Elemen
25
25
  type="button"
26
26
  className="shrink-0 rounded-full p-0.5 opacity-0 transition-opacity hover:bg-red-500/20 group-hover:opacity-100"
27
27
  onClick={() => onRemove(skill)}
28
- aria-label={`删除 ${skill.name}`}
29
- title="点击删除"
28
+ aria-label={`从当前团队禁用 ${skill.name}`}
29
+ title="从当前团队禁用"
30
30
  >
31
31
  <X size={10} className="text-[var(--color-text-muted)] hover:text-red-400" />
32
32
  </button>