@yancyyu/openhermit 1.6.41 → 1.6.43

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 (281) hide show
  1. package/README.md +98 -89
  2. package/bin/hermit.mjs +96 -0
  3. package/dist-renderer/assets/{ProjectEditorOverlay-Br0X83Jf.js → ProjectEditorOverlay-C98qSs7-.js} +1 -1
  4. package/dist-renderer/assets/{TeamGraphOverlay-DHMTbZPZ.js → TeamGraphOverlay-CsBbZwcL.js} +1 -1
  5. package/dist-renderer/assets/{_basePickBy-DzIiX7yH.js → _basePickBy-ZOyLWjMK.js} +1 -1
  6. package/dist-renderer/assets/{_baseUniq-6hZuzTLU.js → _baseUniq-DBb726rt.js} +1 -1
  7. package/dist-renderer/assets/{arc-CXgO6fx_.js → arc-CdiTaR_R.js} +1 -1
  8. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-DKWgtDHr.js → architectureDiagram-VXUJARFQ-Cz3sc5TH.js} +1 -1
  9. package/dist-renderer/assets/{blockDiagram-VD42YOAC-DOMUcC40.js → blockDiagram-VD42YOAC-DE4c-KJ3.js} +1 -1
  10. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-B_k2L7qX.js → c4Diagram-YG6GDRKO-CmTMDTrV.js} +1 -1
  11. package/dist-renderer/assets/channel-KTpqi9eT.js +1 -0
  12. package/dist-renderer/assets/{chunk-4BX2VUAB-BeD_ccFy.js → chunk-4BX2VUAB-rhHy3tFl.js} +1 -1
  13. package/dist-renderer/assets/{chunk-55IACEB6-ClZfkA5w.js → chunk-55IACEB6-fLZBzuo_.js} +1 -1
  14. package/dist-renderer/assets/{chunk-B4BG7PRW-5XluxXsn.js → chunk-B4BG7PRW-DOzxQhim.js} +1 -1
  15. package/dist-renderer/assets/{chunk-DI55MBZ5-BzIjjNVm.js → chunk-DI55MBZ5-COQCcXC5.js} +1 -1
  16. package/dist-renderer/assets/{chunk-FMBD7UC4-HgH3MK_H.js → chunk-FMBD7UC4-IKU9U_Y4.js} +1 -1
  17. package/dist-renderer/assets/{chunk-QN33PNHL-WeC5T3Ba.js → chunk-QN33PNHL-D6WV154X.js} +1 -1
  18. package/dist-renderer/assets/{chunk-QZHKN3VN-Cu1ApHfW.js → chunk-QZHKN3VN-D90_2DQp.js} +1 -1
  19. package/dist-renderer/assets/{chunk-TZMSLE5B-BOhlynJM.js → chunk-TZMSLE5B-BQEil57G.js} +1 -1
  20. package/dist-renderer/assets/classDiagram-2ON5EDUG-lpzulY5X.js +1 -0
  21. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-lpzulY5X.js +1 -0
  22. package/dist-renderer/assets/clone-CriGymY9.js +1 -0
  23. package/dist-renderer/assets/{cose-bilkent-S5V4N54A-DGZSihDQ.js → cose-bilkent-S5V4N54A-6WiK6U2P.js} +1 -1
  24. package/dist-renderer/assets/{dagre-6UL2VRFP-CnxwCbku.js → dagre-6UL2VRFP-DF4MMuTn.js} +1 -1
  25. package/dist-renderer/assets/{diagram-PSM6KHXK-DsIhoxdI.js → diagram-PSM6KHXK-CcF1eZ7E.js} +1 -1
  26. package/dist-renderer/assets/{diagram-QEK2KX5R-Cmh9KUF5.js → diagram-QEK2KX5R-DYlOVPQB.js} +1 -1
  27. package/dist-renderer/assets/{diagram-S2PKOQOG-CKxV456A.js → diagram-S2PKOQOG-BHXWsZOP.js} +1 -1
  28. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-EnvYjOjc.js → erDiagram-Q2GNP2WA-GjmuBx8d.js} +1 -1
  29. package/dist-renderer/assets/{flowDiagram-NV44I4VS-BmNeWY_A.js → flowDiagram-NV44I4VS-BuS7YVHk.js} +1 -1
  30. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-D30fyK-u.js → ganttDiagram-JELNMOA3-3Teu5tAa.js} +1 -1
  31. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-CrUNiYg1.js → gitGraphDiagram-V2S2FVAM-BiLdCYu5.js} +1 -1
  32. package/dist-renderer/assets/{graph-CY1gTfTb.js → graph-CDP_R8ct.js} +1 -1
  33. package/dist-renderer/assets/{index-CaEbzwAU.js → index-BSZdT-g-.js} +1 -1
  34. package/dist-renderer/assets/{index-D5K-SjBG.js → index-BhWvMqsz.js} +1 -1
  35. package/dist-renderer/assets/{index-9_hO4N1e.js → index-C2_AupSj.js} +1 -1
  36. package/dist-renderer/assets/{index-59r209c1.js → index-C5ujiwAR.js} +580 -588
  37. package/dist-renderer/assets/index-CIS2CTK9.css +1 -0
  38. package/dist-renderer/assets/{index-DMR9B1UP.js → index-CVNjLwkq.js} +1 -1
  39. package/dist-renderer/assets/{index-BC2hXmg_.js → index-CwG3se0q.js} +1 -1
  40. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-By_XUlcD.js → infoDiagram-HS3SLOUP-DLHUFo72.js} +1 -1
  41. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-BM1LJE9m.js → journeyDiagram-XKPGCS4Q-BE07RpJD.js} +1 -1
  42. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-DHIW3aTA.js → kanban-definition-3W4ZIXB7-DDHZy4NB.js} +1 -1
  43. package/dist-renderer/assets/{layout-DAKiL_Mo.js → layout-5nA5wUxO.js} +1 -1
  44. package/dist-renderer/assets/{linear-DwOaRYea.js → linear-BtF1i2qN.js} +1 -1
  45. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-b7bJ2cha.js → mindmap-definition-VGOIOE7T-Z1Ui9Sqy.js} +1 -1
  46. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-DxyL9Zr2.js → pieDiagram-ADFJNKIX-LCjxckWv.js} +1 -1
  47. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-CR33pHlF.js → quadrantDiagram-AYHSOK5B-BOwKjSco.js} +1 -1
  48. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-BAiSRSlh.js → requirementDiagram-UZGBJVZJ-pChP8Znd.js} +1 -1
  49. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-C8JmDjoa.js → sankeyDiagram-TZEHDZUN-DifZ2qpo.js} +1 -1
  50. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-c1d0Wi1m.js → sequenceDiagram-WL72ISMW-CJg-WYyY.js} +1 -1
  51. package/dist-renderer/assets/{splashScene-D0YB9uxm.js → splashScene-94xWCzLA.js} +1 -1
  52. package/dist-renderer/assets/{stateDiagram-FKZM4ZOC-nT8BiH2O.js → stateDiagram-FKZM4ZOC-DWHOoFdv.js} +1 -1
  53. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-CGYZOoMb.js +1 -0
  54. package/dist-renderer/assets/{timeline-definition-IT6M3QCI-DpoRepUA.js → timeline-definition-IT6M3QCI-CPgokIo8.js} +1 -1
  55. package/dist-renderer/assets/{treemap-GDKQZRPO-C41UJeIH.js → treemap-GDKQZRPO-DAVqSR9L.js} +1 -1
  56. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-KMjGARKN.js → xychartDiagram-PRI3JC2R-CCOcGbrD.js} +1 -1
  57. package/dist-renderer/chat-community-qr.jpg +0 -0
  58. package/dist-renderer/fonts/Agave-Bold.ttf +0 -0
  59. package/dist-renderer/fonts/Agave-Regular.ttf +0 -0
  60. package/dist-renderer/icon.png +0 -0
  61. package/dist-renderer/icon.rar +0 -0
  62. package/dist-renderer/index.html +3 -3
  63. package/package.json +21 -26
  64. package/src/features/worker-society/core/application/WorkerSocietyService.test.ts +802 -0
  65. package/src/features/worker-society/core/application/WorkerSocietyService.ts +428 -0
  66. package/src/features/worker-society/core/application/fakes.ts +101 -0
  67. package/src/features/worker-society/core/application/ports.ts +70 -0
  68. package/src/features/worker-society/core/domain/models/society.ts +141 -0
  69. package/src/features/worker-society/core/domain/policies/societyPolicies.test.ts +739 -0
  70. package/src/features/worker-society/core/domain/policies/societyPolicies.ts +496 -0
  71. package/src/features/worker-society/main/adapters/input/societyMcp.test.ts +317 -0
  72. package/src/features/worker-society/main/adapters/input/societyMcp.ts +257 -0
  73. package/src/features/worker-society/main/adapters/input/societyRoutes.test.ts +695 -0
  74. package/src/features/worker-society/main/adapters/input/societyRoutes.ts +194 -0
  75. package/src/features/worker-society/main/composition/societyComposition.test.ts +74 -0
  76. package/src/features/worker-society/main/composition/societyComposition.ts +70 -0
  77. package/src/features/worker-society/main/composition/workerSocietyPlugin.test.ts +69 -0
  78. package/src/features/worker-society/main/composition/workerSocietyPlugin.ts +67 -0
  79. package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.test.ts +132 -0
  80. package/src/features/worker-society/main/infrastructure/crossTeamMessageGateway.ts +84 -0
  81. package/src/features/worker-society/main/infrastructure/fsStores.test.ts +216 -0
  82. package/src/features/worker-society/main/infrastructure/fsStores.ts +113 -0
  83. package/src/features/worker-society/main/infrastructure/mergingProfileStore.test.ts +195 -0
  84. package/src/features/worker-society/main/infrastructure/mergingProfileStore.ts +96 -0
  85. package/src/features/worker-society/renderer/SocietyGraph.tsx +166 -0
  86. package/src/features/worker-society/renderer/SocietyNodeLabels.tsx +139 -0
  87. package/src/features/worker-society/renderer/SocietyNodeOverlay.tsx +339 -0
  88. package/src/features/worker-society/renderer/SocietyView.tsx +437 -0
  89. package/src/features/worker-society/renderer/index.ts +11 -0
  90. package/src/features/worker-society/renderer/societyApi.test.ts +259 -0
  91. package/src/features/worker-society/renderer/societyApi.ts +144 -0
  92. package/src/features/worker-society/renderer/societyGraphAdapter.test.ts +321 -0
  93. package/src/features/worker-society/renderer/societyGraphAdapter.ts +240 -0
  94. package/src/features/worker-society/renderer/societyOverlayActions.test.ts +57 -0
  95. package/src/features/worker-society/renderer/societyOverlayActions.ts +49 -0
  96. package/src/features/worker-society/renderer/societyStore.test.ts +218 -0
  97. package/src/features/worker-society/renderer/societyStore.ts +146 -0
  98. package/src/features/worker-society/renderer/societyViewUtils.test.ts +81 -0
  99. package/src/features/worker-society/renderer/societyViewUtils.ts +68 -0
  100. package/src/main/ipc/extensions.ts +27 -0
  101. package/src/main/server.ts +1731 -539
  102. package/src/main/services/ccConnect/CcConnectBridge.ts +26 -11
  103. package/src/main/services/ccConnect/CcConnectClient.ts +9 -2
  104. package/src/main/services/ccConnect/workDirReconcile.test.ts +57 -0
  105. package/src/main/services/ccConnect/workDirReconcile.ts +36 -0
  106. package/src/main/services/direct-cli/DirectCliSessionManager.test.ts +397 -0
  107. package/src/main/services/direct-cli/DirectCliSessionManager.ts +508 -0
  108. package/src/main/services/direct-cli/DirectCliSessionStore.test.ts +79 -0
  109. package/src/main/services/direct-cli/DirectCliSessionStore.ts +97 -0
  110. package/src/main/services/direct-cli/__tests__/directCliMessageId.test.ts +40 -0
  111. package/src/main/services/direct-cli/directCliMessageId.ts +21 -0
  112. package/src/main/services/direct-cli/index.ts +17 -0
  113. package/src/main/services/extensions/capability-packs/CapabilityPackLoaderService.ts +637 -0
  114. package/src/main/services/extensions/catalog/PluginCatalogService.ts +2 -2
  115. package/src/main/services/loop-assets/LoopAssetsScannerService.ts +657 -0
  116. package/src/main/services/runtime/providerAwareCliEnv.ts +33 -5
  117. package/src/main/services/session-intelligence/LocalSessionScanner.ts +156 -71
  118. package/src/main/services/session-intelligence/SessionUsageParser.ts +103 -8
  119. package/src/main/services/session-intelligence/UsageTelemetryService.ts +11 -0
  120. package/src/main/services/session-intelligence/__tests__/teamSessionListMapper.test.ts +104 -0
  121. package/src/main/services/session-intelligence/teamSessionListMapper.ts +78 -0
  122. package/src/main/services/system-manager/AdminLoopInitializer.ts +95 -0
  123. package/src/main/services/system-manager/BuiltinWorkflowSeeder.ts +744 -0
  124. package/src/main/services/system-manager/SystemManagerConfigService.ts +19 -1
  125. package/src/main/services/system-manager/WorkflowPromptService.ts +58 -5
  126. package/src/main/services/system-manager/__tests__/AdminLoopInitializer.test.ts +129 -0
  127. package/src/main/services/system-manager/__tests__/SystemManagerConfigService.test.ts +60 -0
  128. package/src/main/services/teams-mvp/CollaborationBoardService.ts +2 -0
  129. package/src/main/services/teams-mvp/OpsRunbookContext.ts +60 -0
  130. package/src/main/services/teams-mvp/TaskDispatchService.test.ts +305 -0
  131. package/src/main/services/teams-mvp/TaskDispatchService.ts +250 -131
  132. package/src/main/services/teams-mvp/TeamProvisioningService.ts +12 -2
  133. package/src/main/services/teams-mvp/TeamWorkspaceService.test.ts +207 -0
  134. package/src/main/services/teams-mvp/TeamWorkspaceService.ts +104 -51
  135. package/src/main/services/teams-mvp/index.ts +6 -0
  136. package/src/main/utils/externalPlatformSessionRouting.ts +92 -0
  137. package/src/main/utils/toolApprovalRules.ts +151 -0
  138. package/src/renderer/App.tsx +24 -89
  139. package/src/renderer/api/httpClient.ts +132 -52
  140. package/src/renderer/api/providers.ts +5 -16
  141. package/src/renderer/components/chat/CommunityChatView.tsx +81 -0
  142. package/src/renderer/components/dashboard/DashboardView.tsx +130 -84
  143. package/src/renderer/components/extensions/ExtensionStoreView.tsx +39 -5
  144. package/src/renderer/components/extensions/ExtensionsSubTabTrigger.tsx +2 -1
  145. package/src/renderer/components/extensions/capability-packs/CapabilityPacksPanel.tsx +170 -0
  146. package/src/renderer/components/layout/PaneContent.tsx +10 -2
  147. package/src/renderer/components/layout/SortableTab.tsx +4 -0
  148. package/src/renderer/components/layout/TabBarActions.tsx +13 -16
  149. package/src/renderer/components/runtime/ProviderRuntimeSettingsDialog.tsx +4 -135
  150. package/src/renderer/components/schedules/SchedulesView.tsx +22 -14
  151. package/src/renderer/components/schedules/calendar/CalendarEventBlock.tsx +7 -6
  152. package/src/renderer/components/settings/SettingsTabs.tsx +24 -21
  153. package/src/renderer/components/settings/SettingsView.tsx +22 -13
  154. package/src/renderer/components/settings/components/SettingRow.tsx +13 -5
  155. package/src/renderer/components/settings/components/SettingsSectionCard.tsx +53 -0
  156. package/src/renderer/components/settings/components/SettingsSectionHeader.tsx +10 -6
  157. package/src/renderer/components/settings/components/SettingsSelect.tsx +12 -9
  158. package/src/renderer/components/settings/components/SettingsToggle.tsx +6 -5
  159. package/src/renderer/components/settings/components/index.ts +1 -0
  160. package/src/renderer/components/settings/sections/AdvancedSection.tsx +78 -59
  161. package/src/renderer/components/settings/sections/CliStatusSection.tsx +32 -44
  162. package/src/renderer/components/settings/sections/ConfigEditorDialog.tsx +1 -1
  163. package/src/renderer/components/settings/sections/GeneralSection.tsx +216 -186
  164. package/src/renderer/components/settings/sections/PlatformsSection.tsx +25 -17
  165. package/src/renderer/components/settings/sections/TaskBusSection.tsx +63 -22
  166. package/src/renderer/components/sidebar/SidebarSessions.tsx +120 -80
  167. package/src/renderer/components/sidebar/SidebarTaskItem.tsx +1 -1
  168. package/src/renderer/components/splash/splashScene.ts +6 -2
  169. package/src/renderer/components/system-manager/SystemManagerView.tsx +169 -255
  170. package/src/renderer/components/tasks/TasksView.tsx +63 -37
  171. package/src/renderer/components/team/CcSessionsSection.tsx +124 -89
  172. package/src/renderer/components/team/HarnessBrandLogos.tsx +318 -0
  173. package/src/renderer/components/team/HarnessSelect.tsx +25 -26
  174. package/src/renderer/components/team/TeamDetailView.tsx +137 -153
  175. package/src/renderer/components/team/TeamEmptyState.tsx +9 -37
  176. package/src/renderer/components/team/TeamListView.tsx +144 -30
  177. package/src/renderer/components/team/__tests__/CcSessionsSection.hasLocalFile.test.tsx +128 -0
  178. package/src/renderer/components/team/activity/ActivityItem.tsx +21 -9
  179. package/src/renderer/components/team/activity/ActivityTimeline.tsx +2 -2
  180. package/src/renderer/components/team/dialogs/AdvancedCliSection.tsx +1 -1
  181. package/src/renderer/components/team/dialogs/CreateTaskDialog.tsx +13 -10
  182. package/src/renderer/components/team/dialogs/CreateTeamDialog.tsx +189 -57
  183. package/src/renderer/components/team/dialogs/EditTeamDialog.tsx +9 -157
  184. package/src/renderer/components/team/dialogs/LaunchTeamDialog.tsx +19 -15
  185. package/src/renderer/components/team/dialogs/PlatformBindingDialog.tsx +48 -10
  186. package/src/renderer/components/team/dialogs/PlatformManualForm.tsx +11 -12
  187. package/src/renderer/components/team/dialogs/PlatformSetupQR.tsx +39 -37
  188. package/src/renderer/components/team/dialogs/RuntimeConfigDialog.tsx +434 -64
  189. package/src/renderer/components/team/dialogs/SendMessageDialog.tsx +12 -10
  190. package/src/renderer/components/team/dialogs/TaskDetailDialog.tsx +2 -2
  191. package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.bindProject.test.tsx +399 -0
  192. package/src/renderer/components/team/dialogs/__tests__/CreateTeamDialog.chineseRepro.test.tsx +253 -0
  193. package/src/renderer/components/team/dialogs/platformAllowUtils.ts +91 -0
  194. package/src/renderer/components/team/dialogs/teammateRuntimeCompatibility.tsx +1 -1
  195. package/src/renderer/components/team/kanban/KanbanTaskCard.test.tsx +41 -0
  196. package/src/renderer/components/team/kanban/KanbanTaskCard.tsx +41 -86
  197. package/src/renderer/components/team/loop-console/LoopCommandComposer.tsx +310 -0
  198. package/src/renderer/components/team/loop-console/LoopConsolePanel.tsx +372 -0
  199. package/src/renderer/components/team/loop-console/loopSendIntent.test.ts +85 -0
  200. package/src/renderer/components/team/loop-console/loopSendIntent.ts +221 -0
  201. package/src/renderer/components/team/loop-console/useLeadSessionToolActivity.ts +74 -0
  202. package/src/renderer/components/team/loop-console/useLoopCommandSuggestions.ts +165 -0
  203. package/src/renderer/components/team/loop-console/useLoopConsoleController.ts +266 -0
  204. package/src/renderer/components/team/members/LeadModelRow.test.tsx +1 -1
  205. package/src/renderer/components/team/members/LeadModelRow.tsx +5 -3
  206. package/src/renderer/components/team/members/MemberDetailDialog.tsx +11 -0
  207. package/src/renderer/components/team/members/MemberDetailStats.tsx +13 -3
  208. package/src/renderer/components/team/members/MemberDraftRow.test.tsx +1 -1
  209. package/src/renderer/components/team/members/MemberDraftRow.tsx +1 -1
  210. package/src/renderer/components/team/members/MemberMessagesTab.tsx +2 -2
  211. package/src/renderer/components/team/members/MemberStatsTab.tsx +1 -1
  212. package/src/renderer/components/team/messages/MessageComposer.tsx +150 -44
  213. package/src/renderer/components/team/messages/MessagesFilterPopover.tsx +2 -2
  214. package/src/renderer/components/team/messages/MessagesPanel.tsx +34 -28
  215. package/src/renderer/components/team/schedule/CcCronScheduleDialog.tsx +6 -6
  216. package/src/renderer/components/team/taskLogs/ExactTaskLogCard.tsx +2 -2
  217. package/src/renderer/components/team/taskLogs/TaskLogStreamSection.tsx +1 -1
  218. package/src/renderer/components/terminal/TerminalPanel.tsx +2 -3
  219. package/src/renderer/components/ui/MentionableTextarea.tsx +5 -1
  220. package/src/renderer/constants/teamColors.ts +5 -5
  221. package/src/renderer/hooks/useExtensionsTabState.ts +1 -1
  222. package/src/renderer/hooks/useMentionDetection.ts +5 -1
  223. package/src/renderer/hooks/useProjectWorkflowCommands.ts +57 -0
  224. package/src/renderer/hooks/useTeamSuggestions.ts +2 -0
  225. package/src/renderer/index.css +19 -2
  226. package/src/renderer/main.tsx +7 -1
  227. package/src/renderer/store/index.ts +18 -1
  228. package/src/renderer/store/slices/extensionsSlice.ts +83 -0
  229. package/src/renderer/store/slices/tabSlice.ts +61 -0
  230. package/src/renderer/store/slices/teamSlice.ts +138 -9
  231. package/src/renderer/types/mention.ts +8 -0
  232. package/src/renderer/types/tabs.ts +3 -1
  233. package/src/renderer/utils/__tests__/bindProjectSlug.test.ts +69 -0
  234. package/src/renderer/utils/__tests__/groupTransformer.test.ts +148 -0
  235. package/src/renderer/utils/__tests__/initialRoute.test.ts +101 -0
  236. package/src/renderer/utils/__tests__/leadToolActivity.test.ts +124 -0
  237. package/src/renderer/utils/__tests__/mergeTeamMessages.test.ts +81 -0
  238. package/src/renderer/utils/__tests__/teamMessageFiltering.test.ts +213 -0
  239. package/src/renderer/utils/__tests__/teamMessageKey.test.ts +75 -0
  240. package/src/renderer/utils/__tests__/workflowCommandExecution.test.ts +173 -0
  241. package/src/renderer/utils/__tests__/workflowCommandSuggestions.test.ts +59 -0
  242. package/src/renderer/utils/bindProjectSlug.ts +57 -0
  243. package/src/renderer/utils/capabilityCommandExecution.ts +113 -0
  244. package/src/renderer/utils/initialRoute.ts +89 -0
  245. package/src/renderer/utils/leadToolActivity.ts +117 -0
  246. package/src/renderer/utils/loopShortcutSuggestions.ts +106 -0
  247. package/src/renderer/utils/mentionSuggestions.ts +1 -1
  248. package/src/renderer/utils/slashCommandRegistry.ts +231 -0
  249. package/src/renderer/utils/teamMentionDirective.ts +31 -0
  250. package/src/renderer/utils/workflowCommandExecution.ts +96 -0
  251. package/src/renderer/utils/workflowCommandSuggestions.ts +49 -0
  252. package/src/shared/types/api.ts +79 -4
  253. package/src/shared/types/ccConnect.ts +1 -0
  254. package/src/shared/types/extensions/api.ts +19 -0
  255. package/src/shared/types/extensions/capabilityPack.ts +118 -0
  256. package/src/shared/types/extensions/index.ts +29 -1
  257. package/src/shared/types/index.ts +6 -0
  258. package/src/shared/types/loopAssets.ts +54 -0
  259. package/src/shared/types/providers.ts +0 -16
  260. package/src/shared/types/systemManager.ts +26 -1
  261. package/src/shared/types/team.ts +43 -3
  262. package/src/shared/types/terminal.ts +2 -36
  263. package/src/shared/types/worker.test.ts +28 -0
  264. package/src/shared/types/worker.ts +3 -0
  265. package/src/shared/utils/__tests__/effortLevels.test.ts +88 -0
  266. package/src/shared/utils/__tests__/providerBackend.test.ts +88 -0
  267. package/src/shared/utils/__tests__/providerLaunchArgs.test.ts +220 -0
  268. package/src/shared/utils/claudeStreamJson.test.ts +187 -0
  269. package/src/shared/utils/claudeStreamJson.ts +153 -0
  270. package/src/shared/utils/providerLaunchArgs.ts +217 -0
  271. package/src/shared/utils/slashCommands.ts +10 -0
  272. package/src/types/node-pty.d.ts +8 -0
  273. package/dist-renderer/assets/channel-D0XS_akr.js +0 -1
  274. package/dist-renderer/assets/classDiagram-2ON5EDUG-D13Ffs0U.js +0 -1
  275. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-D13Ffs0U.js +0 -1
  276. package/dist-renderer/assets/clone-B1ZrxI1D.js +0 -1
  277. package/dist-renderer/assets/index-iyjkpSus.css +0 -32
  278. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-Dmibmlso.js +0 -1
  279. package/src/main/services/system-manager/SystemManagerPtyService.ts +0 -233
  280. package/src/renderer/components/common/TerminalPane.tsx +0 -213
  281. package/src/renderer/components/team/dialogs/useTeamEditForm.ts +0 -292
@@ -6,7 +6,7 @@
6
6
  * 改进:
7
7
  * - 分组:live 会话在上,inactive 在下
8
8
  * - 运行中和历史会话统一展示在团队详情中
9
- * - 点击会话行可展开最近历史消息
9
+ * - 点击会话行可展开最近历史动态
10
10
  */
11
11
 
12
12
  import { useCallback, useEffect, useState } from 'react';
@@ -28,8 +28,16 @@ import {
28
28
 
29
29
  import type { CcSession, CcSessionDetail } from '@shared/types';
30
30
 
31
- const SESSION_DETAIL_PAGE_SIZE = 12;
32
- const HISTORICAL_SESSION_PAGE_SIZE = 10;
31
+ const SESSION_DETAIL_PAGE_SIZE = 6;
32
+ const HISTORICAL_SESSION_PAGE_SIZE = 3;
33
+
34
+ function formatSessionDetailError(error: unknown): string {
35
+ const message = error instanceof Error ? error.message : String(error || '');
36
+ if (/session not found/i.test(message)) {
37
+ return '会话文件已不存在,请刷新会话列表';
38
+ }
39
+ return message || '加载会话历史失败';
40
+ }
33
41
 
34
42
  interface CcSessionsSectionProps {
35
43
  teamName: string;
@@ -281,6 +289,17 @@ function CcSessionRow({
281
289
  return;
282
290
  }
283
291
 
292
+ // cc-only sessions (e.g. a Feishu listening session with no local Claude
293
+ // JSONL yet) have no local detail to read — the detail endpoint would 404
294
+ // and surface a misleading "会话文件已不存在" (#20). Skip the fetch; the
295
+ // render branch shows an inline listening state instead.
296
+ if (session.hasLocalFile === false) {
297
+ setDetail(null);
298
+ setDetailError(null);
299
+ setLoadingDetail(false);
300
+ return;
301
+ }
302
+
284
303
  let cancelled = false;
285
304
  const isIncrementalLoad = historyLimit > SESSION_DETAIL_PAGE_SIZE;
286
305
  setDetailError(null);
@@ -294,7 +313,7 @@ function CcSessionRow({
294
313
  .catch((err) => {
295
314
  if (!cancelled) {
296
315
  setDetail(null);
297
- setDetailError(err instanceof Error ? err.message : '加载会话历史失败');
316
+ setDetailError(formatSessionDetailError(err));
298
317
  }
299
318
  })
300
319
  .finally(() => {
@@ -307,7 +326,7 @@ function CcSessionRow({
307
326
  return () => {
308
327
  cancelled = true;
309
328
  };
310
- }, [historyLimit, isExpanded, session.id, teamName]);
329
+ }, [historyLimit, isExpanded, session.hasLocalFile, session.id, teamName]);
311
330
 
312
331
  const handleLoadMoreHistory = useCallback(() => {
313
332
  if (loadingDetail || loadingMoreHistory || !hasMoreHistory) {
@@ -384,96 +403,112 @@ function CcSessionRow({
384
403
  </div>
385
404
  </button>
386
405
 
387
-
388
406
  {isExpanded && (
389
407
  <div className="px-3 pb-3">
390
- {loadingDetail && !detail && (
391
- <div className="rounded-lg bg-[var(--color-surface)] px-3 py-3">
392
- <div className="space-y-2">
393
- {[1, 2, 3].map((i) => (
394
- <div
395
- key={i}
396
- className="h-3 animate-pulse rounded bg-[var(--color-surface-raised)]"
397
- />
398
- ))}
399
- </div>
400
- </div>
401
- )}
402
- {detailError && !loadingDetail && (
403
- <div className="flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400">
404
- <AlertCircle size={13} className="shrink-0" />
405
- <span>{detailError}</span>
408
+ {session.hasLocalFile === false ? (
409
+ // cc-only session (e.g. Feishu listening, no local JSONL yet)
410
+ // no local history to show. Avoids the misleading
411
+ // "会话文件已不存在" 404 path (#20).
412
+ <div className="flex items-center gap-2 rounded-lg bg-[var(--color-surface)] px-3 py-2 text-xs text-[var(--color-text-muted)]">
413
+ <Radio size={13} className="shrink-0 animate-pulse text-emerald-400" />
414
+ <span>监听中,暂无本地历史</span>
406
415
  </div>
407
- )}
408
- {detail && (
409
- <div className="rounded-lg bg-[var(--color-surface)] p-2">
410
- {detail.history.length === 0 ? (
411
- <div className="px-2 py-3 text-xs text-[var(--color-text-muted)]">暂无消息</div>
412
- ) : (
413
- <>
414
- <div className="mb-2 flex items-center justify-between px-1 text-[10px] text-[var(--color-text-muted)]">
415
- <span>会话历史</span>
416
- <span>
417
- 已显示 {detail.history.length} / {detail.historyCount}
418
- </span>
416
+ ) : (
417
+ <>
418
+ {loadingDetail && !detail && (
419
+ <div className="rounded-lg bg-[var(--color-surface)] px-3 py-3">
420
+ <div className="space-y-2">
421
+ {[1, 2, 3].map((i) => (
422
+ <div
423
+ key={i}
424
+ className="h-3 animate-pulse rounded bg-[var(--color-surface-raised)]"
425
+ />
426
+ ))}
419
427
  </div>
420
- <div className="max-h-64 space-y-2 overflow-y-auto pr-1">
421
- {[...detail.history].reverse().map((msg, i) => {
422
- const isUserMessage = msg.role === 'user';
423
- return (
424
- <div
425
- key={`${msg.timestamp}-${i}`}
426
- className={`rounded-lg px-3 py-2 text-[11px] leading-relaxed ${
427
- isUserMessage
428
- ? 'bg-indigo-500/10 text-[var(--color-text)]'
429
- : 'bg-[var(--color-surface-raised)] text-[var(--color-text)]'
430
- }`}
431
- >
432
- <div className="mb-1 flex items-center gap-2">
433
- <span
434
- className={`shrink-0 text-[10px] font-medium ${
435
- isUserMessage ? 'text-indigo-400' : 'text-[var(--color-text-muted)]'
428
+ </div>
429
+ )}
430
+ {detailError && !loadingDetail && (
431
+ <div className="flex items-center gap-2 rounded-lg bg-red-500/10 px-3 py-2 text-xs text-red-400">
432
+ <AlertCircle size={13} className="shrink-0" />
433
+ <span>{detailError}</span>
434
+ </div>
435
+ )}
436
+ {detail && (
437
+ <div className="rounded-lg bg-[var(--color-surface)] p-2">
438
+ {detail.history.length === 0 ? (
439
+ <div className="px-2 py-3 text-xs text-[var(--color-text-muted)]">暂无动态</div>
440
+ ) : (
441
+ <>
442
+ <div className="mb-2 flex items-center justify-between px-1 text-[10px] text-[var(--color-text-muted)]">
443
+ <span>会话历史</span>
444
+ <span>
445
+ 已显示 {detail.history.length} / {detail.historyCount}
446
+ </span>
447
+ </div>
448
+ <div className="max-h-64 space-y-2 overflow-y-auto pr-1">
449
+ {[...detail.history].reverse().map((msg, i) => {
450
+ const isUserMessage = msg.role === 'user';
451
+ return (
452
+ <div
453
+ key={`${msg.timestamp}-${i}`}
454
+ className={`rounded-lg px-3 py-2 text-[11px] leading-relaxed ${
455
+ isUserMessage
456
+ ? 'bg-indigo-500/10 text-[var(--color-text)]'
457
+ : 'bg-[var(--color-surface-raised)] text-[var(--color-text)]'
436
458
  }`}
437
459
  >
438
- {isUserMessage ? '用户' : 'Agent'}
439
- </span>
440
- <span className="text-[10px] text-[var(--color-text-muted)] opacity-60">
441
- {formatMessageTime(msg.timestamp)}
442
- </span>
443
- </div>
444
- <div className="whitespace-pre-wrap break-words">
445
- {msg.content.slice(0, 500)}
446
- {msg.content.length > 500 ? '' : ''}
447
- </div>
460
+ <div className="mb-1 flex items-center gap-2">
461
+ <span
462
+ className={`shrink-0 text-[10px] font-medium ${
463
+ isUserMessage
464
+ ? 'text-indigo-400'
465
+ : 'text-[var(--color-text-muted)]'
466
+ }`}
467
+ >
468
+ {isUserMessage ? '用户' : 'Agent'}
469
+ </span>
470
+ <span className="text-[10px] text-[var(--color-text-muted)] opacity-60">
471
+ {formatMessageTime(msg.timestamp)}
472
+ </span>
473
+ </div>
474
+ <div className="whitespace-pre-wrap break-words">
475
+ {msg.content.slice(0, 500)}
476
+ {msg.content.length > 500 ? '…' : ''}
477
+ </div>
478
+ </div>
479
+ );
480
+ })}
481
+ </div>
482
+ {hasMoreHistory && (
483
+ <div className="mt-2 flex items-center justify-between gap-2 px-1">
484
+ <span className="text-[10px] text-[var(--color-text-muted)]">
485
+ 每次加载 {SESSION_DETAIL_PAGE_SIZE} 条
486
+ </span>
487
+ <button
488
+ type="button"
489
+ className="inline-flex items-center gap-1 rounded-full bg-[var(--color-surface-raised)] px-2.5 py-1 text-xs text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-text)] disabled:cursor-not-allowed disabled:opacity-50"
490
+ onClick={handleLoadMoreHistory}
491
+ disabled={loadingDetail || loadingMoreHistory}
492
+ >
493
+ {loadingMoreHistory ? (
494
+ <>
495
+ <Loader2 size={12} className="animate-spin" />
496
+ 加载中...
497
+ </>
498
+ ) : (
499
+ <>
500
+ 加载更早 ({Math.max(detail.historyCount - detail.history.length, 0)}
501
+ )
502
+ </>
503
+ )}
504
+ </button>
448
505
  </div>
449
- );
450
- })}
451
- </div>
452
- {hasMoreHistory && (
453
- <div className="mt-2 flex items-center justify-between gap-2 px-1">
454
- <span className="text-[10px] text-[var(--color-text-muted)]">
455
- 每次加载 {SESSION_DETAIL_PAGE_SIZE} 条
456
- </span>
457
- <button
458
- type="button"
459
- className="inline-flex items-center gap-1 rounded-full bg-[var(--color-surface-raised)] px-2.5 py-1 text-xs text-[var(--color-text-muted)] transition-colors hover:text-[var(--color-text)] disabled:cursor-not-allowed disabled:opacity-50"
460
- onClick={handleLoadMoreHistory}
461
- disabled={loadingDetail || loadingMoreHistory}
462
- >
463
- {loadingMoreHistory ? (
464
- <>
465
- <Loader2 size={12} className="animate-spin" />
466
- 加载中...
467
- </>
468
- ) : (
469
- <>加载更早 ({Math.max(detail.historyCount - detail.history.length, 0)})</>
470
- )}
471
- </button>
472
- </div>
506
+ )}
507
+ </>
473
508
  )}
474
- </>
509
+ </div>
475
510
  )}
476
- </div>
511
+ </>
477
512
  )}
478
513
  </div>
479
514
  )}
@@ -492,14 +527,14 @@ function buildSessionRecordMarkdown(session: CcSession, detail: CcSessionDetail)
492
527
  `- Status: ${detail.live ? 'live' : detail.active ? 'active' : 'inactive'}`,
493
528
  `- Created: ${detail.createdAt || session.createdAt}`,
494
529
  `- Updated: ${detail.updatedAt || session.updatedAt}`,
495
- `- Messages: ${detail.historyCount}`,
530
+ `- Loop events: ${detail.historyCount}`,
496
531
  '',
497
- '## Messages',
532
+ '## Loop events',
498
533
  '',
499
534
  ];
500
535
 
501
536
  if (detail.history.length === 0) {
502
- lines.push('_No messages._', '');
537
+ lines.push('_No Loop events._', '');
503
538
  return lines.join('\n');
504
539
  }
505
540
 
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Brand logos for harness runtimes that are not one of the four CliProviderId
3
+ * providers (anthropic / codex / gemini / opencode), which already live in
4
+ * {@link ProviderBrandLogo}.
5
+ *
6
+ * Each logo is a self-contained 24×24 inline SVG so the harness picker, settings
7
+ * list, and empty-state grid all render a recognisable brand mark instead of an
8
+ * emoji fallback.
9
+ */
10
+
11
+ import { useId } from 'react';
12
+
13
+ import type { CcAgentType } from '@shared/types/ccConnect';
14
+
15
+ type BrandLogoProps = Readonly<{
16
+ className?: string;
17
+ }>;
18
+
19
+ /** Cursor — the editor's signature pointer/arrow mark, monochrome on a dark tile. */
20
+ const CursorBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
21
+ const gradientId = useId();
22
+ return (
23
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
24
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
25
+ <path d="M7.6 6.2 16 11.1l-3.5.9a.6.6 0 0 0-.4.4l-.9 3.5L7.6 6.2Z" fill="#FFFFFF" />
26
+ <path d="M11.2 16.2 10.4 13l3.6-1 .8 3.3-3.6 1Z" fill="#FFFFFF" fillOpacity="0.55" />
27
+ <defs>
28
+ <linearGradient
29
+ id={gradientId}
30
+ x1="3"
31
+ y1="3"
32
+ x2="21"
33
+ y2="21"
34
+ gradientUnits="userSpaceOnUse"
35
+ >
36
+ <stop offset="0" stopColor="#2a2a2a" />
37
+ <stop offset="1" stopColor="#0a0a0a" />
38
+ </linearGradient>
39
+ </defs>
40
+ </svg>
41
+ );
42
+ };
43
+
44
+ /** Kimi (Moonshot) — crescent moon, blue→violet. */
45
+ const KimiBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
46
+ const gradientId = useId();
47
+ return (
48
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
49
+ <path d="M16.4 3.6a8.5 8.5 0 1 0 4 9.9 6.6 6.6 0 0 1-4-9.9Z" fill={`url(#${gradientId})`} />
50
+ <circle cx="18.4" cy="6.4" r="1.5" fill={`url(#${gradientId})`} />
51
+ <defs>
52
+ <linearGradient
53
+ id={gradientId}
54
+ x1="4"
55
+ y1="4"
56
+ x2="20"
57
+ y2="20"
58
+ gradientUnits="userSpaceOnUse"
59
+ >
60
+ <stop offset="0" stopColor="#6E8BFF" />
61
+ <stop offset="1" stopColor="#9B6BFF" />
62
+ </linearGradient>
63
+ </defs>
64
+ </svg>
65
+ );
66
+ };
67
+
68
+ /** Devin (Cognition) — bold geometric "D" node mark. */
69
+ const DevinBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
70
+ const gradientId = useId();
71
+ return (
72
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
73
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
74
+ <path
75
+ d="M8 6.5h4.2a5.5 5.5 0 0 1 0 11H8a.5.5 0 0 1-.5-.5V7A.5.5 0 0 1 8 6.5Zm2.2 3v5a.4.4 0 0 0 .4.4h1.5a2.9 2.9 0 0 0 0-5.8h-1.5a.4.4 0 0 0-.4.4Z"
76
+ fill="#FFFFFF"
77
+ />
78
+ <circle cx="9.6" cy="9.2" r="1.1" fill="#FFFFFF" fillOpacity="0.6" />
79
+ <defs>
80
+ <linearGradient
81
+ id={gradientId}
82
+ x1="3"
83
+ y1="3"
84
+ x2="21"
85
+ y2="21"
86
+ gradientUnits="userSpaceOnUse"
87
+ >
88
+ <stop offset="0" stopColor="#4F6FED" />
89
+ <stop offset="1" stopColor="#7A5AF8" />
90
+ </linearGradient>
91
+ </defs>
92
+ </svg>
93
+ );
94
+ };
95
+
96
+ /** Qoder — code-bracket "Q" on a purple tile. */
97
+ const QoderBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
98
+ const gradientId = useId();
99
+ return (
100
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
101
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
102
+ <path
103
+ d="M9.2 7.4 6.4 12l2.8 4.6"
104
+ fill="none"
105
+ stroke="#FFFFFF"
106
+ strokeWidth="1.7"
107
+ strokeLinecap="round"
108
+ strokeLinejoin="round"
109
+ />
110
+ <path
111
+ d="M14.8 7.4 17.6 12l-2.8 4.6"
112
+ fill="none"
113
+ stroke="#FFFFFF"
114
+ strokeWidth="1.7"
115
+ strokeLinecap="round"
116
+ strokeLinejoin="round"
117
+ />
118
+ <circle cx="12" cy="12" r="1.6" fill="#FFFFFF" />
119
+ <defs>
120
+ <linearGradient
121
+ id={gradientId}
122
+ x1="3"
123
+ y1="3"
124
+ x2="21"
125
+ y2="21"
126
+ gradientUnits="userSpaceOnUse"
127
+ >
128
+ <stop offset="0" stopColor="#8B5CF6" />
129
+ <stop offset="1" stopColor="#6D28D9" />
130
+ </linearGradient>
131
+ </defs>
132
+ </svg>
133
+ );
134
+ };
135
+
136
+ /** Pi (Inflection) — the π glyph on a dark rounded tile. */
137
+ const PiBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
138
+ const gradientId = useId();
139
+ return (
140
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
141
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
142
+ <path
143
+ d="M6.6 9h10.8M9.4 9c-.2 2 .0 4 .0 6.2 0 1-.5 1.6-1.3 1.6M14.6 9c.2 2 .0 4 .0 6.2 0 1 .5 1.6 1.3 1.6M12 9v8"
144
+ fill="none"
145
+ stroke="#F4F4F5"
146
+ strokeWidth="1.5"
147
+ strokeLinecap="round"
148
+ strokeLinejoin="round"
149
+ />
150
+ <defs>
151
+ <linearGradient
152
+ id={gradientId}
153
+ x1="3"
154
+ y1="3"
155
+ x2="21"
156
+ y2="21"
157
+ gradientUnits="userSpaceOnUse"
158
+ >
159
+ <stop offset="0" stopColor="#1f2937" />
160
+ <stop offset="1" stopColor="#0f172a" />
161
+ </linearGradient>
162
+ </defs>
163
+ </svg>
164
+ );
165
+ };
166
+
167
+ /** iFlow — lowercase "i" riding a flow wave, sky blue. */
168
+ const IFlowBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
169
+ const gradientId = useId();
170
+ return (
171
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
172
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
173
+ <circle cx="9" cy="6.6" r="1.3" fill="#FFFFFF" />
174
+ <path
175
+ d="M7.6 9.4h2.8v4.4c0 1.5.7 2.4 1.9 2.4"
176
+ fill="none"
177
+ stroke="#FFFFFF"
178
+ strokeWidth="1.7"
179
+ strokeLinecap="round"
180
+ strokeLinejoin="round"
181
+ />
182
+ <path
183
+ d="M13.5 13.2c1 0 1.6.9 2.7.9s1.7-.9 2.8-.9"
184
+ fill="none"
185
+ stroke="#FFFFFF"
186
+ strokeOpacity="0.8"
187
+ strokeWidth="1.5"
188
+ strokeLinecap="round"
189
+ strokeLinejoin="round"
190
+ />
191
+ <defs>
192
+ <linearGradient
193
+ id={gradientId}
194
+ x1="3"
195
+ y1="3"
196
+ x2="21"
197
+ y2="21"
198
+ gradientUnits="userSpaceOnUse"
199
+ >
200
+ <stop offset="0" stopColor="#38BDF8" />
201
+ <stop offset="1" stopColor="#0EA5E9" />
202
+ </linearGradient>
203
+ </defs>
204
+ </svg>
205
+ );
206
+ };
207
+
208
+ /** ACP (Agent Client Protocol) — linked nodes. */
209
+ const AcpBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
210
+ const gradientId = useId();
211
+ return (
212
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
213
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
214
+ <path
215
+ d="M8.2 8.2 12 12m3.8 3.8L12 12m0 0 3.8-3.8M12 12l-3.8 3.8"
216
+ stroke="#FFFFFF"
217
+ strokeOpacity="0.45"
218
+ strokeWidth="1.4"
219
+ strokeLinecap="round"
220
+ />
221
+ <circle cx="7.6" cy="7.6" r="2.1" fill="#FFFFFF" />
222
+ <circle cx="16.4" cy="7.6" r="2.1" fill="#FFFFFF" />
223
+ <circle cx="7.6" cy="16.4" r="2.1" fill="#FFFFFF" />
224
+ <circle cx="16.4" cy="16.4" r="2.1" fill="#FFFFFF" />
225
+ <defs>
226
+ <linearGradient
227
+ id={gradientId}
228
+ x1="3"
229
+ y1="3"
230
+ x2="21"
231
+ y2="21"
232
+ gradientUnits="userSpaceOnUse"
233
+ >
234
+ <stop offset="0" stopColor="#64748B" />
235
+ <stop offset="1" stopColor="#334155" />
236
+ </linearGradient>
237
+ </defs>
238
+ </svg>
239
+ );
240
+ };
241
+
242
+ /** Tmux — terminal tile with a split pane, signature green. */
243
+ const TmuxBrandLogo = ({ className }: BrandLogoProps): React.JSX.Element => {
244
+ const gradientId = useId();
245
+ return (
246
+ <svg viewBox="0 0 24 24" className={className} aria-hidden="true">
247
+ <rect x="1.25" y="1.25" width="21.5" height="21.5" rx="6" fill={`url(#${gradientId})`} />
248
+ <rect
249
+ x="5"
250
+ y="5"
251
+ width="14"
252
+ height="14"
253
+ rx="2"
254
+ fill="#0F1A17"
255
+ stroke="#2BB673"
256
+ strokeWidth="0.9"
257
+ />
258
+ <path d="M12 5.4v13.2" stroke="#2BB673" strokeWidth="0.9" strokeOpacity="0.6" />
259
+ <path
260
+ d="M7.2 9.2 9 11l-1.8 1.8"
261
+ fill="none"
262
+ stroke="#32D58B"
263
+ strokeWidth="1.3"
264
+ strokeLinecap="round"
265
+ strokeLinejoin="round"
266
+ />
267
+ <defs>
268
+ <linearGradient
269
+ id={gradientId}
270
+ x1="3"
271
+ y1="3"
272
+ x2="21"
273
+ y2="21"
274
+ gradientUnits="userSpaceOnUse"
275
+ >
276
+ <stop offset="0" stopColor="#1b2421" />
277
+ <stop offset="1" stopColor="#0a0f0d" />
278
+ </linearGradient>
279
+ </defs>
280
+ </svg>
281
+ );
282
+ };
283
+
284
+ interface HarnessBrandLogoProps {
285
+ readonly type: CcAgentType;
286
+ readonly className?: string;
287
+ }
288
+
289
+ /**
290
+ * Renders the brand logo for a harness runtime that is NOT one of the four
291
+ * CliProviderId providers. Returns null for provider-backed harnesses
292
+ * (claudecode/codex/gemini/opencode) — those use {@link ProviderBrandLogo}.
293
+ */
294
+ export const HarnessBrandLogo = ({
295
+ type,
296
+ className,
297
+ }: HarnessBrandLogoProps): React.JSX.Element | null => {
298
+ switch (type) {
299
+ case 'cursor':
300
+ return <CursorBrandLogo className={className} />;
301
+ case 'kimi':
302
+ return <KimiBrandLogo className={className} />;
303
+ case 'devin':
304
+ return <DevinBrandLogo className={className} />;
305
+ case 'qoder':
306
+ return <QoderBrandLogo className={className} />;
307
+ case 'pi':
308
+ return <PiBrandLogo className={className} />;
309
+ case 'iflow':
310
+ return <IFlowBrandLogo className={className} />;
311
+ case 'acp':
312
+ return <AcpBrandLogo className={className} />;
313
+ case 'tmux':
314
+ return <TmuxBrandLogo className={className} />;
315
+ default:
316
+ return null;
317
+ }
318
+ };
@@ -1,4 +1,3 @@
1
- import type { CcAgentType } from '@shared/types/ccConnect';
2
1
  import { ProviderBrandLogo } from '@renderer/components/common/ProviderBrandLogo';
3
2
  import {
4
3
  Select,
@@ -7,13 +6,17 @@ import {
7
6
  SelectTrigger,
8
7
  SelectValue,
9
8
  } from '@renderer/components/ui/select';
10
- import { ALL_AGENT_TYPES, AGENT_TYPE_LABELS } from './HarnessCards';
9
+
10
+ import { HarnessBrandLogo } from './HarnessBrandLogos';
11
+ import { AGENT_TYPE_LABELS, ALL_AGENT_TYPES } from './HarnessCards';
12
+
13
+ import type { CcAgentType } from '@shared/types/ccConnect';
11
14
 
12
15
  interface HarnessSelectProps {
13
- value: CcAgentType;
14
- onChange: (value: CcAgentType) => void;
15
- className?: string;
16
- id?: string;
16
+ readonly value: CcAgentType;
17
+ readonly onChange: (value: CcAgentType) => void;
18
+ readonly className?: string;
19
+ readonly id?: string;
17
20
  }
18
21
 
19
22
  const HARNESS_PROVIDER_MAP: Partial<
@@ -25,30 +28,26 @@ const HARNESS_PROVIDER_MAP: Partial<
25
28
  opencode: 'opencode',
26
29
  };
27
30
 
28
- function HarnessIcon({ type, className }: { type: CcAgentType; className?: string }) {
31
+ interface HarnessIconProps {
32
+ readonly type: CcAgentType;
33
+ readonly className?: string;
34
+ }
35
+
36
+ const HarnessIcon = ({ type, className }: HarnessIconProps): React.JSX.Element => {
29
37
  const providerId = HARNESS_PROVIDER_MAP[type];
30
38
  if (providerId) {
31
39
  return <ProviderBrandLogo providerId={providerId} className={className} />;
32
40
  }
33
- return <span className={className}>{EMOJI_FALLBACK[type]}</span>;
34
- }
35
-
36
- const EMOJI_FALLBACK: Record<CcAgentType, string> = {
37
- claudecode: '🤖',
38
- codex: '🔬',
39
- cursor: '💻',
40
- gemini: '💎',
41
- iflow: '🌊',
42
- kimi: '🌙',
43
- devin: '🧑‍💻',
44
- opencode: '🔓',
45
- qoder: '⚡',
46
- pi: '🥧',
47
- acp: '🔗',
48
- tmux: '🖥️',
41
+ // Brand logo for the non-provider harness runtimes (cursor, kimi, …, tmux).
42
+ return <HarnessBrandLogo type={type} className={className} />;
49
43
  };
50
44
 
51
- export function HarnessSelect({ value, onChange, className, id }: HarnessSelectProps) {
45
+ const HarnessSelect = ({
46
+ value,
47
+ onChange,
48
+ className,
49
+ id,
50
+ }: HarnessSelectProps): React.JSX.Element => {
52
51
  return (
53
52
  <Select value={value} onValueChange={(v) => onChange(v as CcAgentType)}>
54
53
  <SelectTrigger id={id} className={className}>
@@ -66,6 +65,6 @@ export function HarnessSelect({ value, onChange, className, id }: HarnessSelectP
66
65
  </SelectContent>
67
66
  </Select>
68
67
  );
69
- }
68
+ };
70
69
 
71
- export { HarnessIcon, HARNESS_PROVIDER_MAP, EMOJI_FALLBACK };
70
+ export { HARNESS_PROVIDER_MAP, HarnessIcon, HarnessSelect };