@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
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Reproduction harness for the user-reported create-team bug:
3
+ * "输入中文 → 英文自动出 → 团队名称已存在 → 英文框红 → 但还能创建"
4
+ *
5
+ * Static analysis says the symptom (English-box red + create still possible) is
6
+ * impossible in a single render, because `isBindProjectTaken` both red-flags the
7
+ * box AND disables the create button. So the only way the user can see red and
8
+ * still create is a TRANSIENT flicker driven by the background `fetchTeams()`
9
+ * refresh (TeamListView schedules one at +1200ms / +3500ms). These tests pin
10
+ * the dialog's behavior across that refresh with the user's REAL team data.
11
+ */
12
+ import React, { act } from 'react';
13
+ import { createRoot } from 'react-dom/client';
14
+
15
+ import { afterEach, describe, expect, it, vi } from 'vitest';
16
+
17
+ import { CreateTeamDialog } from '../CreateTeamDialog';
18
+
19
+ // Live, mutable draft state so a test can "type" by mutating teamName between
20
+ // rerenders — mirroring how a real user types while a background refresh fires.
21
+ const draftState = vi.hoisted(() => ({
22
+ teamName: '',
23
+ customCwd: '/tmp/project',
24
+ }));
25
+
26
+ vi.mock('@renderer/hooks/useCreateTeamDraft', () => ({
27
+ useCreateTeamDraft: () => ({
28
+ teamName: draftState.teamName,
29
+ setTeamName: (v: string) => {
30
+ draftState.teamName = v;
31
+ },
32
+ cwdMode: 'custom' as const,
33
+ setCwdMode: () => undefined,
34
+ selectedProjectPath: '',
35
+ setSelectedProjectPath: () => undefined,
36
+ customCwd: draftState.customCwd,
37
+ setCustomCwd: () => undefined,
38
+ teamColor: '',
39
+ setTeamColor: () => undefined,
40
+ isLoaded: true,
41
+ clearDraft: () => undefined,
42
+ }),
43
+ }));
44
+
45
+ vi.mock('@renderer/hooks/useTheme', () => ({ useTheme: () => ({ isLight: false }) }));
46
+ vi.mock('@renderer/lib/utils', () => ({
47
+ cn: (...args: Array<unknown>): string =>
48
+ args.filter((a): a is string => typeof a === 'string' && a.length > 0).join(' '),
49
+ }));
50
+ vi.mock('@renderer/utils/pathNormalize', () => ({ normalizePath: (p: string) => p }));
51
+ vi.mock('@shared/utils/ephemeralProjectPath', () => ({ isEphemeralProjectPath: () => false }));
52
+ vi.mock('@renderer/api', () => ({ api: { getProjects: async () => [] } }));
53
+ vi.mock('@renderer/api/providers', () => ({
54
+ providersApi: { list: async () => ({ providers: [] }) },
55
+ }));
56
+ vi.mock('@renderer/components/ui/button', () => ({
57
+ Button: ({
58
+ children,
59
+ onClick,
60
+ disabled,
61
+ }: {
62
+ children: React.ReactNode;
63
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
64
+ disabled?: boolean;
65
+ }) =>
66
+ React.createElement(
67
+ 'button',
68
+ { type: 'button', onClick, disabled: Boolean(disabled), 'data-testid': 'btn' },
69
+ children
70
+ ),
71
+ }));
72
+ vi.mock('@renderer/components/ui/dialog', () => ({
73
+ Dialog: ({ children }: { children: React.ReactNode }) =>
74
+ React.createElement(React.Fragment, null, children),
75
+ DialogContent: ({ children }: { children: React.ReactNode }) =>
76
+ React.createElement('div', null, children),
77
+ DialogDescription: ({ children }: { children: React.ReactNode }) =>
78
+ React.createElement('div', null, children),
79
+ DialogFooter: ({ children }: { children: React.ReactNode }) =>
80
+ React.createElement('div', null, children),
81
+ DialogHeader: ({ children }: { children: React.ReactNode }) =>
82
+ React.createElement('div', null, children),
83
+ DialogTitle: ({ children }: { children: React.ReactNode }) =>
84
+ React.createElement('div', null, children),
85
+ }));
86
+ vi.mock('@renderer/components/ui/input', () => ({
87
+ Input: (props: Record<string, unknown>) =>
88
+ React.createElement('input', {
89
+ id: props.id as string,
90
+ value: (props.value as string) ?? '',
91
+ onChange: props.onChange as React.ChangeEventHandler<HTMLInputElement>,
92
+ className: props.className as string,
93
+ placeholder: props.placeholder as string,
94
+ 'data-testid': props.id === 'team-bind-project' ? 'bind-project' : props.id,
95
+ }),
96
+ }));
97
+ vi.mock('@renderer/components/ui/label', () => ({
98
+ Label: ({ children }: { children: React.ReactNode }) =>
99
+ React.createElement('label', null, children),
100
+ }));
101
+ vi.mock('../../HarnessCards', () => ({ AGENT_TYPE_LABELS: {} as Record<string, string> }));
102
+ vi.mock('../../HarnessSelect', () => ({ HarnessSelect: () => React.createElement('div') }));
103
+ vi.mock('../ProjectPathSelector', () => ({
104
+ ProjectPathSelector: () => React.createElement('div'),
105
+ }));
106
+
107
+ interface RenderHandle {
108
+ host: HTMLDivElement;
109
+ rerender: (props: Record<string, unknown>) => Promise<void>;
110
+ unmount: () => Promise<void>;
111
+ }
112
+
113
+ async function renderDialog(props: Record<string, unknown>): Promise<RenderHandle> {
114
+ vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
115
+ const host = document.createElement('div');
116
+ document.body.appendChild(host);
117
+ const root = createRoot(host);
118
+ const renderOnce = async (p: Record<string, unknown>) => {
119
+ await act(async () => {
120
+ root.render(React.createElement(CreateTeamDialog, p as never));
121
+ await Promise.resolve();
122
+ });
123
+ };
124
+ await renderOnce(props);
125
+ return {
126
+ host,
127
+ rerender: (p) => renderOnce(p),
128
+ unmount: async () => {
129
+ await act(async () => {
130
+ root.unmount();
131
+ await Promise.resolve();
132
+ });
133
+ },
134
+ };
135
+ }
136
+
137
+ // The user's REAL team data (read live from ~/.hermit/teams/*/team.json). Kept in sync
138
+ // with disk so the regression guard reflects reality, not a stale snapshot — the bug is a
139
+ // flicker that only surfaces against the actual collision context the user hits. Note the
140
+ // real data even carries non-ASCII bindProjects (汇报/产品经理团队/hermit开发) and a duplicate
141
+ // 'my-project'; the auto-slug must stay collision-free against all of it.
142
+ const REAL_BIND_PROJECTS = [
143
+ '汇报',
144
+ '产品经理团队',
145
+ 'hermit开发',
146
+ '212121-og3z',
147
+ '222-11io',
148
+ 'aads-e487',
149
+ 'boss-1sxv',
150
+ 'my-project',
151
+ 'team-2kclb4',
152
+ 'team-aztc',
153
+ 'team-jcve',
154
+ ];
155
+ const REAL_DISPLAY_NAMES = [
156
+ '汇报',
157
+ '产品经理团队',
158
+ 'hermit开发',
159
+ '212121',
160
+ '你好222',
161
+ '测试aads',
162
+ 'boss',
163
+ 'Helm Loop',
164
+ 'my-project',
165
+ '爬虫',
166
+ '呜呜呜欧',
167
+ '测试',
168
+ ];
169
+
170
+ const baseProps = (
171
+ existingBindProjects: string[],
172
+ existingDisplayNames: string[]
173
+ ): Record<string, unknown> => ({
174
+ open: true,
175
+ canCreate: true,
176
+ provisioningErrorsByTeam: {},
177
+ clearProvisioningError: () => undefined,
178
+ existingTeamNames: [],
179
+ existingBindProjects,
180
+ existingDisplayNames,
181
+ provisioningTeamNames: [],
182
+ activeTeams: [],
183
+ onClose: () => undefined,
184
+ onCreate: async () => undefined,
185
+ onOpenTeam: () => undefined,
186
+ });
187
+
188
+ const findCreateButton = (host: HTMLElement): HTMLButtonElement | null =>
189
+ Array.from(host.querySelectorAll<HTMLButtonElement>('button')).find((b) =>
190
+ b.textContent?.includes('创建数字员工')
191
+ ) ?? null;
192
+
193
+ const bindProjectInput = (host: HTMLElement): HTMLInputElement | null =>
194
+ host.querySelector<HTMLInputElement>('[data-testid="bind-project"]');
195
+ const nameInput = (host: HTMLElement): HTMLInputElement | null =>
196
+ host.querySelector<HTMLInputElement>('#team-name');
197
+
198
+ describe('CreateTeamDialog — Chinese-name repro (user-reported bug)', () => {
199
+ afterEach(() => {
200
+ document.body.innerHTML = '';
201
+ draftState.teamName = '';
202
+ draftState.customCwd = '/tmp/project';
203
+ });
204
+
205
+ it('a fresh Chinese name never shows "已存在" and the box is never red', async () => {
206
+ draftState.teamName = '全新员工甲';
207
+ const { host, unmount } = await renderDialog(baseProps(REAL_BIND_PROJECTS, REAL_DISPLAY_NAMES));
208
+
209
+ expect(host.textContent).not.toContain('该名称已存在');
210
+ expect(host.textContent).not.toContain('该项目标识已存在');
211
+ expect(bindProjectInput(host)?.className ?? '').not.toContain('field-error-border');
212
+ expect(nameInput(host)?.className ?? '').not.toContain('field-error-border');
213
+ expect(findCreateButton(host)?.disabled).toBe(false);
214
+
215
+ await unmount();
216
+ });
217
+
218
+ it('does NOT flicker "已存在" when the background refresh repopulates the list', async () => {
219
+ // Frame 1: dialog open, teams not yet loaded (empty list), user already typed.
220
+ draftState.teamName = '全新员工甲';
221
+ const { host, rerender, unmount } = await renderDialog(baseProps([], []));
222
+
223
+ expect(host.textContent).not.toContain('该名称已存在');
224
+ expect(host.textContent).not.toContain('该项目标识已存在');
225
+ expect(findCreateButton(host)?.disabled).toBe(false);
226
+
227
+ // Frame 2: background fetchTeams() at +1200ms delivers the full real list.
228
+ await rerender(baseProps(REAL_BIND_PROJECTS, REAL_DISPLAY_NAMES));
229
+
230
+ expect(host.textContent).not.toContain('该名称已存在');
231
+ expect(host.textContent).not.toContain('该项目标识已存在');
232
+ expect(bindProjectInput(host)?.className ?? '').not.toContain('field-error-border');
233
+ expect(nameInput(host)?.className ?? '').not.toContain('field-error-border');
234
+ expect(findCreateButton(host)?.disabled).toBe(false);
235
+
236
+ await unmount();
237
+ });
238
+
239
+ it('auto-slug stays collision-free across many distinct Chinese names (no reshuffle red)', async () => {
240
+ const { rerender, host, unmount } = await renderDialog(
241
+ baseProps(REAL_BIND_PROJECTS, REAL_DISPLAY_NAMES)
242
+ );
243
+
244
+ for (const name of ['一号员工', '二号员工', '三号员工', '四号员工', '呜呜呜欧']) {
245
+ draftState.teamName = name;
246
+ await rerender(baseProps(REAL_BIND_PROJECTS, REAL_DISPLAY_NAMES));
247
+ expect(host.textContent).not.toContain('该项目标识已存在');
248
+ expect(bindProjectInput(host)?.className ?? '').not.toContain('field-error-border');
249
+ }
250
+
251
+ await unmount();
252
+ });
253
+ });
@@ -0,0 +1,91 @@
1
+ const FEISHU_LARK_KEYS = new Set(['feishu', 'lark']);
2
+
3
+ export function readStringRecord(value: unknown): Record<string, string> {
4
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return {};
5
+ return Object.fromEntries(
6
+ Object.entries(value as Record<string, unknown>)
7
+ .map(([key, entry]) => [key.trim(), typeof entry === 'string' ? entry.trim() : ''] as const)
8
+ .filter(([key, entry]) => key.length > 0 && entry.length > 0)
9
+ );
10
+ }
11
+
12
+ export function getFeishuLarkAllowValue(record: Record<string, string>): string {
13
+ return record.lark ?? record.feishu ?? '';
14
+ }
15
+
16
+ function getFeishuLarkWriteKey(record: Record<string, string>): 'feishu' | 'lark' {
17
+ if (record.lark !== undefined) return 'lark';
18
+ if (record.feishu !== undefined) return 'feishu';
19
+ return 'feishu';
20
+ }
21
+
22
+ function hasFeishuLarkKey(record: Record<string, string>): boolean {
23
+ return record.feishu !== undefined || record.lark !== undefined;
24
+ }
25
+
26
+ export function withFeishuLarkAllowValue(
27
+ base: Record<string, string>,
28
+ value: string
29
+ ): Record<string, string> {
30
+ const source = readStringRecord(base);
31
+ const next = { ...source };
32
+ const trimmed = value.trim();
33
+ const aliasKey = getFeishuLarkWriteKey(source);
34
+
35
+ delete next.feishu;
36
+ delete next.lark;
37
+
38
+ if (trimmed) {
39
+ next[aliasKey] = trimmed;
40
+ }
41
+
42
+ return next;
43
+ }
44
+
45
+ export function buildFeishuLarkAllowUpdatePayload(
46
+ base: Record<string, string>,
47
+ value: string
48
+ ): Record<string, string> | undefined {
49
+ const source = readStringRecord(base);
50
+ const next = withFeishuLarkAllowValue(source, value);
51
+ const trimmed = value.trim();
52
+
53
+ if (trimmed) return next;
54
+
55
+ if (hasFeishuLarkKey(source)) {
56
+ return {
57
+ ...next,
58
+ feishu: '',
59
+ lark: '',
60
+ };
61
+ }
62
+
63
+ return undefined;
64
+ }
65
+
66
+ export function buildPlatformAllowUpdatePayload(
67
+ base: Record<string, string>,
68
+ values: Record<string, string>
69
+ ): Record<string, string> | undefined {
70
+ const source = readStringRecord(base);
71
+ const next = readStringRecord(values);
72
+
73
+ const keys = new Set([...Object.keys(source), ...Object.keys(values)]);
74
+ const changed = [...keys].some((key) => (source[key] ?? '') !== (next[key] ?? ''));
75
+
76
+ return changed ? next : undefined;
77
+ }
78
+
79
+ export function omitEmptyAllowMap(
80
+ record: Record<string, string>
81
+ ): Record<string, string> | undefined {
82
+ return Object.keys(record).length > 0 ? record : undefined;
83
+ }
84
+
85
+ export function hasFeishuLarkDeleteMarker(value: unknown): boolean {
86
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
87
+ return Object.entries(value as Record<string, unknown>).some(
88
+ ([key, entry]) =>
89
+ FEISHU_LARK_KEYS.has(key.trim()) && (typeof entry !== 'string' || entry.trim().length === 0)
90
+ );
91
+ }
@@ -93,7 +93,7 @@ export function analyzeTeammateRuntimeCompatibility({
93
93
  blocksSubmission: false,
94
94
  checking: false,
95
95
  title: '已切换为进程内成员运行',
96
- message: `当前团队会通过 ${getProviderLabel(leadProviderId)} 负责人会话启动成员,不再依赖 tmux。`,
96
+ message: `当前 Loop runtime 会通过 ${getProviderLabel(leadProviderId)} Loop Lead 会话启动成员,不再依赖 tmux。`,
97
97
  details: ['自定义 CLI 参数里的 --teammate-mode tmux 会被忽略,并改为 in-process。'],
98
98
  tmuxDetail: null,
99
99
  memberWarningById: {},
@@ -196,4 +196,45 @@ describe('KanbanTaskCard change badge', () => {
196
196
  await Promise.resolve();
197
197
  });
198
198
  });
199
+
200
+ it('renders in-progress tasks as agent-controlled without manual action buttons', async () => {
201
+ vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
202
+ const host = document.createElement('div');
203
+ document.body.appendChild(host);
204
+ const root = createRoot(host);
205
+
206
+ await act(async () => {
207
+ root.render(
208
+ React.createElement(KanbanTaskCard, {
209
+ task: baseTask,
210
+ teamName: 'my-team',
211
+ columnId: 'in_progress',
212
+ hasReviewers: true,
213
+ compact: false,
214
+ taskMap: new Map(),
215
+ memberColorMap: new Map([['alice', 'blue']]),
216
+ onRequestReview: noop,
217
+ onApprove: noop,
218
+ onRequestChanges: noop,
219
+ onMoveBackToDone: noop,
220
+ onStartTask: noop,
221
+ onCompleteTask: noop,
222
+ onCancelTask: noop,
223
+ onDeleteTask: noop,
224
+ onViewChanges: noop,
225
+ })
226
+ );
227
+ await Promise.resolve();
228
+ });
229
+
230
+ expect(host.textContent).toContain('Agent 处理中');
231
+ expect(host.querySelector('[aria-label="完成"]')).toBeNull();
232
+ expect(host.querySelector('[aria-label="取消任务 task-1"]')).toBeNull();
233
+ expect(host.querySelector('[aria-label="删除任务"]')).toBeNull();
234
+
235
+ await act(async () => {
236
+ root.unmount();
237
+ await Promise.resolve();
238
+ });
239
+ });
199
240
  });
@@ -3,7 +3,6 @@ import { memo, useCallback, useMemo, useRef, useState } from 'react';
3
3
  import { MemberBadge } from '@renderer/components/team/MemberBadge';
4
4
  import { UnreadCommentsBadge } from '@renderer/components/team/UnreadCommentsBadge';
5
5
  import { Button } from '@renderer/components/ui/button';
6
- import { Popover, PopoverContent, PopoverTrigger } from '@renderer/components/ui/popover';
7
6
  import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip';
8
7
  import { useTheme } from '@renderer/hooks/useTheme';
9
8
  import { useUnreadCommentCount } from '@renderer/hooks/useUnreadCommentCount';
@@ -23,7 +22,6 @@ import {
23
22
  Play,
24
23
  Send,
25
24
  Trash2,
26
- XCircle,
27
25
  } from 'lucide-react';
28
26
 
29
27
  import type { DispatchMeta } from '@shared/types/team';
@@ -63,8 +61,26 @@ const DISPATCH_STATUS_STYLE: Record<string, { bg: string; text: string; label: s
63
61
  text: 'text-yellow-600 dark:text-yellow-400',
64
62
  label: '已派发',
65
63
  },
66
- received: { bg: 'bg-indigo-500/15', text: 'text-indigo-600 dark:text-indigo-400', label: '已接收' },
67
- in_progress: { bg: 'bg-indigo-500/15', text: 'text-indigo-600 dark:text-indigo-400', label: '执行中' },
64
+ pending_accept: {
65
+ bg: 'bg-yellow-500/15',
66
+ text: 'text-yellow-600 dark:text-yellow-400',
67
+ label: '待启动',
68
+ },
69
+ received: {
70
+ bg: 'bg-yellow-500/15',
71
+ text: 'text-yellow-600 dark:text-yellow-400',
72
+ label: '待启动',
73
+ },
74
+ accepted: {
75
+ bg: 'bg-indigo-500/15',
76
+ text: 'text-indigo-600 dark:text-indigo-400',
77
+ label: '已启动',
78
+ },
79
+ in_progress: {
80
+ bg: 'bg-indigo-500/15',
81
+ text: 'text-indigo-600 dark:text-indigo-400',
82
+ label: '执行中',
83
+ },
68
84
  completed: {
69
85
  bg: 'bg-emerald-500/15',
70
86
  text: 'text-emerald-600 dark:text-emerald-400',
@@ -75,18 +91,26 @@ const DISPATCH_STATUS_STYLE: Record<string, { bg: string; text: string; label: s
75
91
  text: 'text-emerald-600 dark:text-emerald-400',
76
92
  label: '已同步',
77
93
  },
94
+ rejected: { bg: 'bg-red-500/15', text: 'text-red-600 dark:text-red-400', label: '已拒绝' },
78
95
  failed: { bg: 'bg-red-500/15', text: 'text-red-600 dark:text-red-400', label: '失败' },
79
96
  };
80
97
 
81
- const DispatchBadge = ({ meta }: { meta: DispatchMeta }): React.JSX.Element => {
98
+ const DispatchBadge = ({
99
+ meta,
100
+ teamName,
101
+ }: {
102
+ meta: DispatchMeta;
103
+ teamName: string;
104
+ }): React.JSX.Element => {
82
105
  const style = DISPATCH_STATUS_STYLE[meta.status] ?? DISPATCH_STATUS_STYLE.dispatched;
83
- const target = meta.targetTeam;
106
+ const direction =
107
+ meta.targetTeam === teamName ? `来自 ${meta.originTeam}` : `发往 ${meta.targetTeam}`;
84
108
  return (
85
109
  <span
86
110
  className={`mt-1 inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium ${style.bg} ${style.text}`}
87
111
  >
88
112
  <Send size={10} />
89
- {style.label} {target}
113
+ {style.label} · {direction}
90
114
  </span>
91
115
  );
92
116
  };
@@ -160,63 +184,6 @@ const TruncatedTitle = ({
160
184
  );
161
185
  };
162
186
 
163
- const CancelTaskButton = ({
164
- taskId,
165
- onConfirm,
166
- }: {
167
- taskId: string;
168
- onConfirm: (taskId: string) => void;
169
- }): React.JSX.Element => {
170
- const [open, setOpen] = useState(false);
171
-
172
- return (
173
- <Popover open={open} onOpenChange={setOpen}>
174
- <Tooltip>
175
- <TooltipTrigger asChild>
176
- <PopoverTrigger asChild>
177
- <Button
178
- variant="destructive"
179
- size="icon"
180
- className="size-6 rounded-full shadow-sm"
181
- aria-label={`取消任务 ${taskId}`}
182
- onClick={(e) => e.stopPropagation()}
183
- >
184
- <XCircle size={11} />
185
- </Button>
186
- </PopoverTrigger>
187
- </TooltipTrigger>
188
- <TooltipContent side="top">取消</TooltipContent>
189
- </Tooltip>
190
- <PopoverContent
191
- className="w-56 p-3"
192
- side="top"
193
- align="start"
194
- onClick={(e) => e.stopPropagation()}
195
- >
196
- <p className="mb-3 text-xs text-[var(--color-text-secondary)]">
197
- 将此任务移回“待处理”并通知团队吗?
198
- </p>
199
- <div className="flex gap-2">
200
- <Button
201
- variant="destructive"
202
- size="sm"
203
- className="flex-1"
204
- onClick={() => {
205
- setOpen(false);
206
- onConfirm(taskId);
207
- }}
208
- >
209
- 确认
210
- </Button>
211
- <Button variant="outline" size="sm" className="flex-1" onClick={() => setOpen(false)}>
212
- 保持不变
213
- </Button>
214
- </div>
215
- </PopoverContent>
216
- </Popover>
217
- );
218
- };
219
-
220
187
  interface TaskActionIconButtonProps {
221
188
  label: string;
222
189
  icon: React.ReactNode;
@@ -263,7 +230,6 @@ export const KanbanTaskCard = memo(
263
230
  memberColorMap,
264
231
  onStartTask,
265
232
  onCompleteTask,
266
- onCancelTask,
267
233
  onScrollToTask,
268
234
  onTaskClick,
269
235
  onViewChanges,
@@ -307,7 +273,7 @@ export const KanbanTaskCard = memo(
307
273
  </span>
308
274
  ) : null}
309
275
  <UnreadCommentsBadge unreadCount={unreadCount} totalCount={task.comments?.length ?? 0} />
310
- {onDeleteTask ? (
276
+ {onDeleteTask && task.status !== 'in_progress' ? (
311
277
  <TaskActionIconButton
312
278
  label="删除任务"
313
279
  icon={<Trash2 size={11} />}
@@ -369,7 +335,9 @@ export const KanbanTaskCard = memo(
369
335
  {REVIEW_STATE_DISPLAY.needsFix.label}
370
336
  </span>
371
337
  ) : null}
372
- {task.dispatchMeta ? <DispatchBadge meta={task.dispatchMeta} /> : null}
338
+ {task.dispatchMeta ? (
339
+ <DispatchBadge meta={task.dispatchMeta} teamName={teamName} />
340
+ ) : null}
373
341
  {compact && <TruncatedTitle text={task.subject} className="mt-1" />}
374
342
  </div>
375
343
 
@@ -435,25 +403,12 @@ export const KanbanTaskCard = memo(
435
403
  ) : null}
436
404
 
437
405
  {columnId === 'in_progress' ? (
438
- isScheduleTask ? (
439
- <div className="flex min-w-0 flex-1 items-center gap-1.5">
440
- <Loader2 size={11} className="animate-spin text-emerald-400" />
441
- <span className="whitespace-nowrap text-[11px] text-emerald-400">执行中</span>
442
- </div>
443
- ) : (
444
- <>
445
- <TaskActionIconButton
446
- label="完成"
447
- icon={<CheckCircle2 size={11} />}
448
- className="border-emerald-500/40 text-emerald-400 hover:bg-emerald-500/10 hover:text-emerald-300"
449
- onClick={(e) => {
450
- e.stopPropagation();
451
- onCompleteTask(task.id);
452
- }}
453
- />
454
- <CancelTaskButton taskId={task.id} onConfirm={onCancelTask} />
455
- </>
456
- )
406
+ <div className="flex min-w-0 flex-1 items-center gap-1.5">
407
+ <Loader2 size={11} className="animate-spin text-emerald-400" />
408
+ <span className="whitespace-nowrap text-[11px] text-emerald-400">
409
+ {isScheduleTask ? '执行中' : 'Agent 处理中'}
410
+ </span>
411
+ </div>
457
412
  ) : null}
458
413
  </div>
459
414