@yancyyu/openhermit 1.6.42 → 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-DlFQ6mai.js → ProjectEditorOverlay-C98qSs7-.js} +1 -1
  4. package/dist-renderer/assets/{TeamGraphOverlay-D2TPMPGR.js → TeamGraphOverlay-CsBbZwcL.js} +1 -1
  5. package/dist-renderer/assets/{_basePickBy-Cmd0RHLQ.js → _basePickBy-ZOyLWjMK.js} +1 -1
  6. package/dist-renderer/assets/{_baseUniq-BI_iy8ea.js → _baseUniq-DBb726rt.js} +1 -1
  7. package/dist-renderer/assets/{arc-NzW2mjTP.js → arc-CdiTaR_R.js} +1 -1
  8. package/dist-renderer/assets/{architectureDiagram-VXUJARFQ-Bzq85AYv.js → architectureDiagram-VXUJARFQ-Cz3sc5TH.js} +1 -1
  9. package/dist-renderer/assets/{blockDiagram-VD42YOAC-D1PvYS-b.js → blockDiagram-VD42YOAC-DE4c-KJ3.js} +1 -1
  10. package/dist-renderer/assets/{c4Diagram-YG6GDRKO-D49RKzPC.js → c4Diagram-YG6GDRKO-CmTMDTrV.js} +1 -1
  11. package/dist-renderer/assets/channel-KTpqi9eT.js +1 -0
  12. package/dist-renderer/assets/{chunk-4BX2VUAB-fmI_MQmQ.js → chunk-4BX2VUAB-rhHy3tFl.js} +1 -1
  13. package/dist-renderer/assets/{chunk-55IACEB6-Xsv9RCXZ.js → chunk-55IACEB6-fLZBzuo_.js} +1 -1
  14. package/dist-renderer/assets/{chunk-B4BG7PRW-BE1KO8Um.js → chunk-B4BG7PRW-DOzxQhim.js} +1 -1
  15. package/dist-renderer/assets/{chunk-DI55MBZ5-tqJ7Mv7f.js → chunk-DI55MBZ5-COQCcXC5.js} +1 -1
  16. package/dist-renderer/assets/{chunk-FMBD7UC4-DMD45MVJ.js → chunk-FMBD7UC4-IKU9U_Y4.js} +1 -1
  17. package/dist-renderer/assets/{chunk-QN33PNHL-DOhGrz-q.js → chunk-QN33PNHL-D6WV154X.js} +1 -1
  18. package/dist-renderer/assets/{chunk-QZHKN3VN-D8yDgJdD.js → chunk-QZHKN3VN-D90_2DQp.js} +1 -1
  19. package/dist-renderer/assets/{chunk-TZMSLE5B-BcsEDu7A.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-DlSqGHMX.js → cose-bilkent-S5V4N54A-6WiK6U2P.js} +1 -1
  24. package/dist-renderer/assets/{dagre-6UL2VRFP-BTT9tSAx.js → dagre-6UL2VRFP-DF4MMuTn.js} +1 -1
  25. package/dist-renderer/assets/{diagram-PSM6KHXK-Du-U-mK2.js → diagram-PSM6KHXK-CcF1eZ7E.js} +1 -1
  26. package/dist-renderer/assets/{diagram-QEK2KX5R-jFdHeKas.js → diagram-QEK2KX5R-DYlOVPQB.js} +1 -1
  27. package/dist-renderer/assets/{diagram-S2PKOQOG-DKLNK2bu.js → diagram-S2PKOQOG-BHXWsZOP.js} +1 -1
  28. package/dist-renderer/assets/{erDiagram-Q2GNP2WA-CZxHgIIo.js → erDiagram-Q2GNP2WA-GjmuBx8d.js} +1 -1
  29. package/dist-renderer/assets/{flowDiagram-NV44I4VS-v4XStCD0.js → flowDiagram-NV44I4VS-BuS7YVHk.js} +1 -1
  30. package/dist-renderer/assets/{ganttDiagram-JELNMOA3-DJjD_BEL.js → ganttDiagram-JELNMOA3-3Teu5tAa.js} +1 -1
  31. package/dist-renderer/assets/{gitGraphDiagram-V2S2FVAM-BNy-jr03.js → gitGraphDiagram-V2S2FVAM-BiLdCYu5.js} +1 -1
  32. package/dist-renderer/assets/{graph-DDTrn6je.js → graph-CDP_R8ct.js} +1 -1
  33. package/dist-renderer/assets/{index-BBp78BAu.js → index-BSZdT-g-.js} +1 -1
  34. package/dist-renderer/assets/{index-eotrJaYy.js → index-BhWvMqsz.js} +1 -1
  35. package/dist-renderer/assets/{index-D8_B-cfs.js → index-C2_AupSj.js} +1 -1
  36. package/dist-renderer/assets/{index-BQrwHZ-k.js → index-C5ujiwAR.js} +580 -588
  37. package/dist-renderer/assets/index-CIS2CTK9.css +1 -0
  38. package/dist-renderer/assets/{index-CRKQSG9S.js → index-CVNjLwkq.js} +1 -1
  39. package/dist-renderer/assets/{index-DR6Wz52b.js → index-CwG3se0q.js} +1 -1
  40. package/dist-renderer/assets/{infoDiagram-HS3SLOUP-DqnOsuza.js → infoDiagram-HS3SLOUP-DLHUFo72.js} +1 -1
  41. package/dist-renderer/assets/{journeyDiagram-XKPGCS4Q-DTobaO1d.js → journeyDiagram-XKPGCS4Q-BE07RpJD.js} +1 -1
  42. package/dist-renderer/assets/{kanban-definition-3W4ZIXB7-HbwVOvWc.js → kanban-definition-3W4ZIXB7-DDHZy4NB.js} +1 -1
  43. package/dist-renderer/assets/{layout--VYmTcw2.js → layout-5nA5wUxO.js} +1 -1
  44. package/dist-renderer/assets/{linear-BsJh89Mr.js → linear-BtF1i2qN.js} +1 -1
  45. package/dist-renderer/assets/{mindmap-definition-VGOIOE7T-BZqUZePd.js → mindmap-definition-VGOIOE7T-Z1Ui9Sqy.js} +1 -1
  46. package/dist-renderer/assets/{pieDiagram-ADFJNKIX-B1q_nH6P.js → pieDiagram-ADFJNKIX-LCjxckWv.js} +1 -1
  47. package/dist-renderer/assets/{quadrantDiagram-AYHSOK5B-UD8QhSEu.js → quadrantDiagram-AYHSOK5B-BOwKjSco.js} +1 -1
  48. package/dist-renderer/assets/{requirementDiagram-UZGBJVZJ-BA_i7Nw8.js → requirementDiagram-UZGBJVZJ-pChP8Znd.js} +1 -1
  49. package/dist-renderer/assets/{sankeyDiagram-TZEHDZUN-CMTnX-2d.js → sankeyDiagram-TZEHDZUN-DifZ2qpo.js} +1 -1
  50. package/dist-renderer/assets/{sequenceDiagram-WL72ISMW-BQXDB615.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-BAsPXy6X.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-BdasmVkC.js → timeline-definition-IT6M3QCI-CPgokIo8.js} +1 -1
  55. package/dist-renderer/assets/{treemap-GDKQZRPO-BkKQqIui.js → treemap-GDKQZRPO-DAVqSR9L.js} +1 -1
  56. package/dist-renderer/assets/{xychartDiagram-PRI3JC2R-EAlPHOdx.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 +1709 -534
  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 +679 -74
  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 +115 -37
  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 +143 -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 +156 -83
  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 +41 -5
  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-Ch7JrfUu.js +0 -1
  274. package/dist-renderer/assets/classDiagram-2ON5EDUG-z9I4AnFy.js +0 -1
  275. package/dist-renderer/assets/classDiagram-v2-WZHVMYZB-z9I4AnFy.js +0 -1
  276. package/dist-renderer/assets/clone-Dfi1Jx6l.js +0 -1
  277. package/dist-renderer/assets/index-iyjkpSus.css +0 -32
  278. package/dist-renderer/assets/stateDiagram-v2-4FDKWEC3-DTUIBfce.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
@@ -130,8 +130,8 @@ export const SendMessageDialog = ({
130
130
  const canAttach = supportsAttachments && canAddMore;
131
131
  const attachmentRestrictionReason = !supportsAttachments
132
132
  ? !isLeadRecipient
133
- ? '文件只能发送给团队负责人'
134
- : '团队在线时才能添加文件'
133
+ ? '文件只能发送给 Loop Lead'
134
+ : 'Loop runtime 在线时才能添加文件'
135
135
  : undefined;
136
136
 
137
137
  const [pendingAutoClose, setPendingAutoClose] = useState(false);
@@ -273,7 +273,7 @@ export const SendMessageDialog = ({
273
273
  );
274
274
 
275
275
  const showFileRestrictionError = useCallback(() => {
276
- setFileRestrictionError(attachmentRestrictionReason ?? '文件只能发送给团队负责人');
276
+ setFileRestrictionError(attachmentRestrictionReason ?? '文件只能发送给 Loop Lead');
277
277
  window.clearTimeout(fileRestrictionTimerRef.current);
278
278
  fileRestrictionTimerRef.current = window.setTimeout(() => {
279
279
  setFileRestrictionError(null);
@@ -354,8 +354,10 @@ export const SendMessageDialog = ({
354
354
  />
355
355
 
356
356
  <DialogHeader>
357
- <DialogTitle>发送消息</DialogTitle>
358
- <DialogDescription>向团队成员发送一条私信。</DialogDescription>
357
+ <DialogTitle>下发 Loop 指令</DialogTitle>
358
+ <DialogDescription>
359
+ 向 runtime 成员下发 Loop 指令或协作请求,用于推进当前工作。
360
+ </DialogDescription>
359
361
  </DialogHeader>
360
362
 
361
363
  <div className="grid gap-4 py-2">
@@ -372,7 +374,7 @@ export const SendMessageDialog = ({
372
374
 
373
375
  <div className="grid gap-2">
374
376
  <div className="flex items-center gap-2">
375
- <Label htmlFor="smd-message">消息内容</Label>
377
+ <Label htmlFor="smd-message">Loop 指令</Label>
376
378
  {isLeadRecipient ? (
377
379
  <>
378
380
  <input
@@ -400,7 +402,7 @@ export const SendMessageDialog = ({
400
402
  </TooltipTrigger>
401
403
  <TooltipContent side="top">
402
404
  {!isTeamAlive
403
- ? '团队在线时才能添加文件'
405
+ ? 'Loop runtime 在线时才能添加文件'
404
406
  : !canAddMore
405
407
  ? '已达到附件上限'
406
408
  : '添加文件(支持粘贴或拖拽)'}
@@ -416,7 +418,7 @@ export const SendMessageDialog = ({
416
418
  error={attachmentError ?? fileRestrictionError}
417
419
  onDismissError={clearAttachmentError}
418
420
  disabled={attachmentsBlocked}
419
- disabledHint="仅在团队在线且接收人为团队负责人时支持附件。请移除附件或切换接收人。"
421
+ disabledHint="仅在 Loop runtime 在线且接收人为 Loop Lead 时支持附件。请移除附件或切换接收人。"
420
422
  />
421
423
 
422
424
  <div className={quote ? 'flex flex-col' : 'contents'}>
@@ -469,7 +471,7 @@ export const SendMessageDialog = ({
469
471
  <MentionableTextarea
470
472
  id="smd-message"
471
473
  className={quote ? 'rounded-t-none' : undefined}
472
- placeholder="输入消息...(回车发送)"
474
+ placeholder="输入 Loop 指令...(回车发送)"
473
475
  value={textDraft.value}
474
476
  onValueChange={textDraft.setValue}
475
477
  suggestions={mentionSuggestions}
@@ -492,7 +494,7 @@ export const SendMessageDialog = ({
492
494
  onClick={handleSubmit}
493
495
  >
494
496
  <Send size={12} />
495
- {sending ? '发送中...' : '发送'}
497
+ {sending ? '下发中...' : '下发'}
496
498
  </button>
497
499
  }
498
500
  footerRight={
@@ -799,7 +799,7 @@ export const TaskDetailDialog = ({
799
799
  );
800
800
  })()
801
801
  : null}
802
- {onDeleteTask && currentTask ? (
802
+ {onDeleteTask && currentTask && currentTask.status !== 'in_progress' ? (
803
803
  <Button
804
804
  variant="ghost"
805
805
  size="sm"
@@ -828,7 +828,7 @@ export const TaskDetailDialog = ({
828
828
  <HelpCircle size={14} />
829
829
  {currentTask.needsClarification === 'user'
830
830
  ? '等待你补充说明'
831
- : '等待团队负责人补充说明'}
831
+ : '等待 Loop Lead 补充说明'}
832
832
  </span>
833
833
  <Button
834
834
  variant="ghost"
@@ -0,0 +1,399 @@
1
+ /**
2
+ * CreateTeamDialog — bindProject (项目标识) invariant tests.
3
+ *
4
+ * Regression guard for the false "该项目标识已存在" red-box flicker. The
5
+ * auto-generated ASCII identifier must be collision-free against
6
+ * `existingBindProjects` in EVERY rendered frame, so:
7
+ * - the "该项目标识已存在" error never appears for an auto value, and
8
+ * - the create button is never disabled by a phantom collision.
9
+ *
10
+ * The real `bindProjectSlug` generator is exercised (not mocked) so this
11
+ * validates the dialog ↔ generator integration end to end.
12
+ */
13
+ import React, { act } from 'react';
14
+ import { createRoot } from 'react-dom/client';
15
+
16
+ import { afterEach, describe, expect, it, vi } from 'vitest';
17
+
18
+ import { generateBindProject } from '@renderer/utils/bindProjectSlug';
19
+
20
+ import { CreateTeamDialog } from '../CreateTeamDialog';
21
+
22
+ // ── Mutable draft state (hoisted so the mocked hook can read it) ────────────
23
+ const draftState = vi.hoisted(() => ({
24
+ teamName: '产品助手',
25
+ cwdMode: 'custom' as 'project' | 'custom',
26
+ customCwd: '/tmp/project',
27
+ }));
28
+
29
+ vi.mock('@renderer/hooks/useCreateTeamDraft', () => ({
30
+ useCreateTeamDraft: () => ({
31
+ teamName: draftState.teamName,
32
+ setTeamName: () => undefined,
33
+ cwdMode: draftState.cwdMode,
34
+ setCwdMode: () => undefined,
35
+ selectedProjectPath: '',
36
+ setSelectedProjectPath: () => undefined,
37
+ customCwd: draftState.customCwd,
38
+ setCustomCwd: () => undefined,
39
+ teamColor: '',
40
+ setTeamColor: () => undefined,
41
+ isLoaded: true,
42
+ clearDraft: () => undefined,
43
+ }),
44
+ }));
45
+
46
+ vi.mock('@renderer/hooks/useTheme', () => ({
47
+ useTheme: () => ({ isLight: false }),
48
+ }));
49
+
50
+ vi.mock('@renderer/lib/utils', () => ({
51
+ cn: (...args: Array<unknown>): string =>
52
+ args.filter((a): a is string => typeof a === 'string' && a.length > 0).join(' '),
53
+ }));
54
+
55
+ vi.mock('@renderer/utils/pathNormalize', () => ({
56
+ normalizePath: (p: string) => p,
57
+ }));
58
+
59
+ vi.mock('@shared/utils/ephemeralProjectPath', () => ({
60
+ isEphemeralProjectPath: () => false,
61
+ }));
62
+
63
+ vi.mock('@renderer/api', () => ({
64
+ api: { getProjects: async () => [] },
65
+ }));
66
+
67
+ vi.mock('@renderer/api/providers', () => ({
68
+ providersApi: { list: async () => ({ providers: [] }) },
69
+ }));
70
+
71
+ vi.mock('@renderer/components/ui/button', () => ({
72
+ Button: ({
73
+ children,
74
+ onClick,
75
+ disabled,
76
+ }: {
77
+ children: React.ReactNode;
78
+ onClick?: React.MouseEventHandler<HTMLButtonElement>;
79
+ disabled?: boolean;
80
+ }) =>
81
+ React.createElement(
82
+ 'button',
83
+ { type: 'button', onClick, disabled: Boolean(disabled), 'data-testid': 'btn' },
84
+ children
85
+ ),
86
+ }));
87
+
88
+ vi.mock('@renderer/components/ui/dialog', () => ({
89
+ Dialog: ({ children }: { children: React.ReactNode }) =>
90
+ React.createElement(React.Fragment, null, children),
91
+ DialogContent: ({ children }: { children: React.ReactNode }) =>
92
+ React.createElement('div', null, children),
93
+ DialogDescription: ({ children }: { children: React.ReactNode }) =>
94
+ React.createElement('div', null, children),
95
+ DialogFooter: ({ children }: { children: React.ReactNode }) =>
96
+ React.createElement('div', null, children),
97
+ DialogHeader: ({ children }: { children: React.ReactNode }) =>
98
+ React.createElement('div', null, children),
99
+ DialogTitle: ({ children }: { children: React.ReactNode }) =>
100
+ React.createElement('div', null, children),
101
+ }));
102
+
103
+ vi.mock('@renderer/components/ui/input', () => ({
104
+ Input: (props: Record<string, unknown>) =>
105
+ React.createElement('input', {
106
+ id: props.id as string,
107
+ value: (props.value as string) ?? '',
108
+ onChange: props.onChange as React.ChangeEventHandler<HTMLInputElement>,
109
+ className: props.className as string,
110
+ placeholder: props.placeholder as string,
111
+ 'data-testid': props.id === 'team-bind-project' ? 'bind-project' : undefined,
112
+ }),
113
+ }));
114
+
115
+ vi.mock('@renderer/components/ui/label', () => ({
116
+ Label: ({ children }: { children: React.ReactNode }) =>
117
+ React.createElement('label', null, children),
118
+ }));
119
+
120
+ vi.mock('../../HarnessCards', () => ({
121
+ AGENT_TYPE_LABELS: {} as Record<string, string>,
122
+ }));
123
+
124
+ vi.mock('../../HarnessSelect', () => ({
125
+ HarnessSelect: () => React.createElement('div'),
126
+ }));
127
+
128
+ vi.mock('../ProjectPathSelector', () => ({
129
+ ProjectPathSelector: () => React.createElement('div'),
130
+ }));
131
+
132
+ // ── Helpers ─────────────────────────────────────────────────────────────────
133
+
134
+ interface RenderHandle {
135
+ host: HTMLDivElement;
136
+ root: ReturnType<typeof createRoot>;
137
+ rerender: (props: Record<string, unknown>) => Promise<void>;
138
+ unmount: () => Promise<void>;
139
+ }
140
+
141
+ async function renderDialog(props: Record<string, unknown>): Promise<RenderHandle> {
142
+ vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
143
+ const host = document.createElement('div');
144
+ document.body.appendChild(host);
145
+ const root = createRoot(host);
146
+
147
+ const renderOnce = async (p: Record<string, unknown>) => {
148
+ await act(async () => {
149
+ root.render(React.createElement(CreateTeamDialog, p as never));
150
+ await Promise.resolve();
151
+ });
152
+ };
153
+
154
+ await renderOnce(props);
155
+
156
+ return {
157
+ host,
158
+ root,
159
+ rerender: (p) => renderOnce(p),
160
+ unmount: async () => {
161
+ await act(async () => {
162
+ root.unmount();
163
+ await Promise.resolve();
164
+ });
165
+ },
166
+ };
167
+ }
168
+
169
+ const baseProps = (existingBindProjects: string[]): Record<string, unknown> => ({
170
+ open: true,
171
+ canCreate: true,
172
+ provisioningErrorsByTeam: {},
173
+ clearProvisioningError: () => undefined,
174
+ existingTeamNames: [],
175
+ existingBindProjects,
176
+ provisioningTeamNames: [],
177
+ activeTeams: [],
178
+ onClose: () => undefined,
179
+ onCreate: async () => undefined,
180
+ onOpenTeam: () => undefined,
181
+ });
182
+
183
+ const findCreateButton = (host: HTMLElement): HTMLButtonElement | null => {
184
+ const buttons = Array.from(host.querySelectorAll<HTMLButtonElement>('button'));
185
+ return buttons.find((b) => b.textContent?.includes('创建数字员工')) ?? null;
186
+ };
187
+
188
+ const findBindProjectInput = (host: HTMLElement): HTMLInputElement | null =>
189
+ host.querySelector<HTMLInputElement>('[data-testid="bind-project"]');
190
+
191
+ describe('CreateTeamDialog bindProject invariant', () => {
192
+ afterEach(() => {
193
+ document.body.innerHTML = '';
194
+ draftState.teamName = '产品助手';
195
+ draftState.cwdMode = 'custom';
196
+ draftState.customCwd = '/tmp/project';
197
+ });
198
+
199
+ it('auto-generated id is collision-free and never shows "该项目标识已存在"', async () => {
200
+ // Simulate a prior worker that already took the deterministic id for this name.
201
+ const takenId = generateBindProject(draftState.teamName, new Set());
202
+ const expectedNext = generateBindProject(draftState.teamName, new Set([takenId]));
203
+
204
+ const { host, unmount } = await renderDialog(baseProps([takenId]));
205
+
206
+ const input = findBindProjectInput(host);
207
+ expect(input, 'bind-project input rendered').not.toBeNull();
208
+ expect(input?.value).toBe(expectedNext);
209
+ expect(host.textContent).not.toContain('该项目标识已存在');
210
+
211
+ const createBtn = findCreateButton(host);
212
+ expect(createBtn, 'create button rendered').not.toBeNull();
213
+ expect(createBtn?.disabled).toBe(false);
214
+
215
+ await unmount();
216
+ });
217
+
218
+ it('does NOT flicker "已存在" when the existing list loads after mount', async () => {
219
+ // Teams load asynchronously: dialog first opens with an empty list, then the
220
+ // list populates with an id that collides with the just-generated one. The
221
+ // derived bindProject must jump straight to a free slot in the same render
222
+ // — no transient "已存在" frame is ever produced.
223
+ const { host, rerender, unmount } = await renderDialog(baseProps([]));
224
+
225
+ const firstInput = findBindProjectInput(host);
226
+ const firstValue = firstInput?.value ?? '';
227
+ expect(firstValue).toBe(generateBindProject(draftState.teamName, new Set()));
228
+ expect(host.textContent).not.toContain('该项目标识已存在');
229
+
230
+ // Now the list populates with exactly the id that was just generated.
231
+ await rerender(baseProps([firstValue]));
232
+
233
+ const settledInput = findBindProjectInput(host);
234
+ const expectedAfterLoad = generateBindProject(draftState.teamName, new Set([firstValue]));
235
+ expect(settledInput?.value).toBe(expectedAfterLoad);
236
+ expect(host.textContent).not.toContain('该项目标识已存在');
237
+ expect(findCreateButton(host)?.disabled).toBe(false);
238
+
239
+ await unmount();
240
+ });
241
+
242
+ it('uses the deterministic id when there is no collision', async () => {
243
+ const { host, unmount } = await renderDialog(baseProps([]));
244
+
245
+ const expected = generateBindProject(draftState.teamName, new Set());
246
+ expect(findBindProjectInput(host)?.value).toBe(expected);
247
+ expect(host.textContent).not.toContain('该项目标识已存在');
248
+
249
+ await unmount();
250
+ });
251
+
252
+ it('blocks create when the display name already exists', async () => {
253
+ const { host, unmount } = await renderDialog({
254
+ ...baseProps([]),
255
+ existingDisplayNames: [draftState.teamName],
256
+ });
257
+
258
+ // Same name as an existing worker → red error on the name field, create disabled.
259
+ expect(host.textContent).toContain('该名称已存在,请换一个');
260
+ const nameInput = host.querySelector<HTMLInputElement>('#team-name');
261
+ expect(nameInput?.className).toContain('border-[var(--field-error-border)]');
262
+ expect(findCreateButton(host)?.disabled).toBe(true);
263
+
264
+ await unmount();
265
+ });
266
+
267
+ it('allows create when the display name is unique', async () => {
268
+ const { host, unmount } = await renderDialog({
269
+ ...baseProps([]),
270
+ existingDisplayNames: ['其他不重名的员工'],
271
+ });
272
+
273
+ expect(host.textContent).not.toContain('该名称已存在,请换一个');
274
+ expect(findCreateButton(host)?.disabled).toBe(false);
275
+
276
+ await unmount();
277
+ });
278
+
279
+ it('does NOT flash "该名称已存在" mid-create when the name lands in the list', async () => {
280
+ // Regression: clicking create updates the parent team list, so the
281
+ // just-created name momentarily appears in existingDisplayNames while the
282
+ // dialog still renders the name step. The duplicate-name red box must stay
283
+ // hidden throughout the in-flight create — no one-frame flicker right
284
+ // before the success screen.
285
+ let resolveCreate: (() => void) | undefined;
286
+ const onCreate = vi.fn(
287
+ () =>
288
+ new Promise<void>((resolve) => {
289
+ resolveCreate = resolve;
290
+ })
291
+ );
292
+
293
+ const { host, rerender, unmount } = await renderDialog({
294
+ ...baseProps([]),
295
+ existingDisplayNames: [],
296
+ onCreate,
297
+ });
298
+
299
+ // Click create on a unique name → enters submitting state, onCreate pending.
300
+ const createBtn = findCreateButton(host);
301
+ expect(createBtn, 'create button rendered').not.toBeNull();
302
+ await act(async () => {
303
+ createBtn?.click();
304
+ await Promise.resolve();
305
+ });
306
+
307
+ // Button now reads "创建中..." → proves isSubmitting === true mid-create.
308
+ const submittingBtn = Array.from(host.querySelectorAll('button')).find((b) =>
309
+ b.textContent?.includes('创建中')
310
+ );
311
+ expect(submittingBtn, 'create entered submitting state').toBeTruthy();
312
+
313
+ // Parent now reports the just-created name as existing (store caught up).
314
+ await rerender({
315
+ ...baseProps([]),
316
+ existingDisplayNames: [draftState.teamName],
317
+ onCreate,
318
+ });
319
+
320
+ // No flicker: the duplicate-name red box must NOT appear mid-create.
321
+ expect(host.textContent).not.toContain('该名称已存在');
322
+
323
+ // Finish the create → success step. setStep('done') is batched with
324
+ // setIsSubmitting(false) inside createLocalTeam's success block, so the
325
+ // name step unmounts atomically: the just-created name (now in the list)
326
+ // never re-renders the name field, and "该名称已存在" never surfaces.
327
+ await act(async () => {
328
+ resolveCreate?.();
329
+ await Promise.resolve();
330
+ await Promise.resolve();
331
+ });
332
+ expect(host.textContent).toContain('数字员工已创建成功');
333
+ expect(host.textContent).not.toContain('该名称已存在');
334
+
335
+ await unmount();
336
+ });
337
+
338
+ it('opens the JUST-CREATED team, not a regenerated id, after the list refreshes', async () => {
339
+ // Regression: after create succeeds the parent's fetchTeams() refresh adds
340
+ // the just-created slug to existingBindProjects. The live `bindProject`
341
+ // re-derives (its candidate is now taken) and the numeric-counter fallback
342
+ // landed on an UNRELATED existing team's slug (e.g. "team-2"), so the done
343
+ // step's "打开数字员工" button opened the WRONG team. The dialog must capture
344
+ // the slug actually used at creation and open THAT one.
345
+ const createdSlug = generateBindProject(draftState.teamName, new Set());
346
+ // What the live derivation would regenerate to once `createdSlug` is taken:
347
+ // the counter walk lands on "team-2" (an unrelated existing team's slug).
348
+ const regeneratedAfterRefresh = generateBindProject(
349
+ draftState.teamName,
350
+ new Set([createdSlug])
351
+ );
352
+ expect(regeneratedAfterRefresh).not.toBe(createdSlug);
353
+
354
+ const onCreate = vi.fn(async () => undefined);
355
+ const onOpenTeam = vi.fn();
356
+
357
+ const { host, rerender, unmount } = await renderDialog({
358
+ ...baseProps([]),
359
+ onCreate,
360
+ onOpenTeam,
361
+ });
362
+
363
+ // Create the team with the unique auto slug → success step.
364
+ const createBtn = findCreateButton(host);
365
+ expect(createBtn, 'create button rendered').not.toBeNull();
366
+ await act(async () => {
367
+ createBtn?.click();
368
+ await Promise.resolve();
369
+ await Promise.resolve();
370
+ await Promise.resolve();
371
+ });
372
+ expect(onCreate).toHaveBeenCalledTimes(1);
373
+ expect(onCreate).toHaveBeenCalledWith(expect.objectContaining({ teamName: createdSlug }));
374
+ expect(host.textContent).toContain('数字员工已创建成功');
375
+
376
+ // Parent list refreshes and now reports the just-created slug as existing.
377
+ await rerender({
378
+ ...baseProps([createdSlug]),
379
+ onCreate,
380
+ onOpenTeam,
381
+ });
382
+
383
+ // The done step's "open" button must use the captured created slug, not the
384
+ // regenerated counter value that collides with an unrelated existing team.
385
+ const openBtn = Array.from(host.querySelectorAll('button')).find((b) =>
386
+ b.textContent?.includes('打开数字员工')
387
+ );
388
+ expect(openBtn, 'open button rendered in done step').toBeTruthy();
389
+ await act(async () => {
390
+ openBtn?.click();
391
+ await Promise.resolve();
392
+ });
393
+
394
+ expect(onOpenTeam).toHaveBeenCalledTimes(1);
395
+ expect(onOpenTeam.mock.calls[0][0]).toBe(createdSlug);
396
+
397
+ await unmount();
398
+ });
399
+ });