@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,151 @@
1
+ import type { ToolApprovalSettings } from '@shared/types/team';
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Safe bash command prefixes — commands that never need manual approval
5
+ // ---------------------------------------------------------------------------
6
+
7
+ const SAFE_PREFIXES: readonly string[] = [
8
+ // Version control
9
+ 'git ',
10
+ 'git\t',
11
+ // Package managers
12
+ 'pnpm ',
13
+ 'npm ',
14
+ 'npx ',
15
+ 'yarn ',
16
+ // File inspection (read-only)
17
+ 'ls',
18
+ 'cat ',
19
+ 'head ',
20
+ 'tail ',
21
+ 'wc ',
22
+ 'less ',
23
+ 'more ',
24
+ // Output
25
+ 'echo ',
26
+ 'printf ',
27
+ // System info
28
+ 'pwd',
29
+ 'whoami',
30
+ 'hostname',
31
+ 'date',
32
+ 'uname',
33
+ // Search & find (read-only)
34
+ 'find ',
35
+ 'grep ',
36
+ 'rg ',
37
+ 'fd ',
38
+ 'ag ',
39
+ // Directory & file info
40
+ 'tree ',
41
+ 'which ',
42
+ 'type ',
43
+ 'file ',
44
+ // Text processing (read-only)
45
+ 'diff ',
46
+ 'sort ',
47
+ 'uniq ',
48
+ 'tr ',
49
+ 'cut ',
50
+ // Path utilities
51
+ 'basename ',
52
+ 'dirname ',
53
+ 'realpath ',
54
+ 'readlink ',
55
+ // Environment
56
+ 'env',
57
+ 'printenv',
58
+ // Scripting one-liners (read-only)
59
+ 'node -e',
60
+ 'node --eval',
61
+ 'python -c',
62
+ 'python3 -c',
63
+ ];
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // Dangerous patterns — these OVERRIDE safe prefixes and always need approval
67
+ // ---------------------------------------------------------------------------
68
+
69
+ const DANGEROUS_PATTERNS: readonly RegExp[] = [
70
+ /\brm\s/, // rm (with space to avoid false positives like "rmdir" intent)
71
+ /\brm$/, // bare "rm" at end
72
+ /\bsudo\b/,
73
+ /\bchmod\b/,
74
+ /\bchown\b/,
75
+ /\bcurl\b.*\|\s*(ba)?sh/,
76
+ /\bwget\b.*\|\s*(ba)?sh/,
77
+ /\bmkfs\b/,
78
+ /\bdd\b/,
79
+ /\bkill\b/,
80
+ /\bkillall\b/,
81
+ /\bpkill\b/,
82
+ />\s*\//, // redirect to absolute path root
83
+ /\beval\b/,
84
+ /\bexec\b/,
85
+ /\bformat\b/,
86
+ /\bshutdown\b/,
87
+ /\breboot\b/,
88
+ ];
89
+
90
+ // ---------------------------------------------------------------------------
91
+ // File edit tools that can be auto-allowed
92
+ // ---------------------------------------------------------------------------
93
+
94
+ const FILE_EDIT_TOOLS = new Set(['Edit', 'Write', 'NotebookEdit']);
95
+
96
+ // ---------------------------------------------------------------------------
97
+ // Public API
98
+ // ---------------------------------------------------------------------------
99
+
100
+ export interface AutoAllowResult {
101
+ autoAllow: boolean;
102
+ reason?: string;
103
+ }
104
+
105
+ /**
106
+ * Determines whether a tool call should be auto-allowed based on user settings.
107
+ *
108
+ * Logic:
109
+ * 1. File edit tools — auto-allow if `autoAllowFileEdits` is enabled
110
+ * 2. Bash commands — check dangerous patterns FIRST (always block),
111
+ * then check safe prefixes (auto-allow if `autoAllowSafeBash` is enabled)
112
+ * 3. Everything else — requires manual approval
113
+ */
114
+ export function shouldAutoAllow(
115
+ settings: ToolApprovalSettings,
116
+ toolName: string,
117
+ toolInput: Record<string, unknown>
118
+ ): AutoAllowResult {
119
+ // Auto-allow ALL tools (overrides everything)
120
+ if (settings.autoAllowAll) {
121
+ return { autoAllow: true, reason: 'auto_allow_all' };
122
+ }
123
+
124
+ // File edit auto-allow
125
+ if (settings.autoAllowFileEdits && FILE_EDIT_TOOLS.has(toolName)) {
126
+ return { autoAllow: true, reason: 'auto_allow_category' };
127
+ }
128
+
129
+ // Safe bash auto-allow
130
+ if (settings.autoAllowSafeBash && toolName === 'Bash') {
131
+ const command = typeof toolInput.command === 'string' ? toolInput.command.trim() : '';
132
+ if (!command) return { autoAllow: false };
133
+
134
+ // Dangerous patterns override safe prefixes — check FIRST
135
+ for (const pattern of DANGEROUS_PATTERNS) {
136
+ if (pattern.test(command)) {
137
+ return { autoAllow: false };
138
+ }
139
+ }
140
+
141
+ // Check safe prefixes
142
+ for (const prefix of SAFE_PREFIXES) {
143
+ const trimmedPrefix = prefix.trimEnd();
144
+ if (command === trimmedPrefix || command.startsWith(prefix)) {
145
+ return { autoAllow: true, reason: 'auto_allow_category' };
146
+ }
147
+ }
148
+ }
149
+
150
+ return { autoAllow: false };
151
+ }
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo, useRef, useState } from 'react';
1
+ import React, { useEffect, useMemo } from 'react';
2
2
 
3
3
  import { TooltipProvider } from '@renderer/components/ui/tooltip';
4
4
 
@@ -18,14 +18,6 @@ import type { Tab } from './types/tabs';
18
18
  const PERSIST_KEY = 'hermit:lastTeam';
19
19
  const DEFAULT_APP_PATH = '/teams';
20
20
 
21
- function safeDecodeURIComponent(value: string): string {
22
- try {
23
- return decodeURIComponent(value);
24
- } catch {
25
- return value;
26
- }
27
- }
28
-
29
21
  function getActiveTabFromLayout(activeTabId: string | null, paneLayout: PaneLayout): Tab | null {
30
22
  if (!activeTabId) return null;
31
23
  for (const pane of paneLayout.panes) {
@@ -57,6 +49,8 @@ function buildPathForTab(activeTab: Tab | null): string {
57
49
  return '/tasks';
58
50
  case 'dashboard':
59
51
  return '/dashboard';
52
+ case 'society':
53
+ return '/society';
60
54
  case 'session': {
61
55
  if (!activeTab.projectId || !activeTab.sessionId) return DEFAULT_APP_PATH;
62
56
  return `/session/${encodeURIComponent(activeTab.projectId)}/${encodeURIComponent(activeTab.sessionId)}`;
@@ -115,93 +109,20 @@ function useTabPathPersistence() {
115
109
  activeTabId: s.activeTabId,
116
110
  paneLayout: s.paneLayout,
117
111
  }));
118
- const [routeReady, setRouteReady] = useState(false);
119
- const didInitialRouteRestoreRef = useRef(false);
120
-
121
- useEffect(() => {
122
- if (didInitialRouteRestoreRef.current) return;
123
- didInitialRouteRestoreRef.current = true;
124
-
125
- const pathname = window.location.pathname;
126
- const segments = pathname
127
- .split('/')
128
- .map((segment) => segment.trim())
129
- .filter((segment) => segment.length > 0)
130
- .map(safeDecodeURIComponent);
131
- const state = useStore.getState();
132
-
133
- if (segments.length === 0) {
134
- setRouteReady(true);
135
- return;
136
- }
137
-
138
- const [route, arg1, arg2] = segments;
139
- switch (route) {
140
- case 'team':
141
- if (arg1) state.openTeamTab(arg1);
142
- break;
143
- case 'teams':
144
- state.openTeamsTab();
145
- break;
146
- case 'system-manager':
147
- void state.openSystemManager();
148
- break;
149
- case 'settings':
150
- state.openSettingsTab();
151
- break;
152
- case 'extensions':
153
- state.openExtensionsTab();
154
- break;
155
- case 'schedules':
156
- state.openSchedulesTab();
157
- break;
158
- case 'tasks':
159
- state.openTasksTab();
160
- break;
161
- case 'dashboard':
162
- state.openDashboard();
163
- break;
164
- case 'session':
165
- if (arg1 && arg2) {
166
- state.navigateToSession(arg1, arg2);
167
- }
168
- break;
169
- case 'notifications':
170
- state.openTab({ type: 'notifications', label: '通知' });
171
- break;
172
- case 'graph':
173
- if (arg1) {
174
- state.openTab({ type: 'graph', label: arg1, teamName: arg1 });
175
- }
176
- break;
177
- case 'report':
178
- if (arg1 && arg2) {
179
- state.openTab({
180
- type: 'report',
181
- label: 'Session Report',
182
- projectId: arg1,
183
- sessionId: arg2,
184
- });
185
- }
186
- break;
187
- default:
188
- break;
189
- }
190
-
191
- setRouteReady(true);
192
- }, []);
193
112
 
194
113
  const activeTab = useMemo(
195
114
  () => getActiveTabFromLayout(activeTabId, paneLayout),
196
115
  [activeTabId, paneLayout]
197
116
  );
198
117
 
118
+ // The initial route is restored before first render (main.tsx →
119
+ // restoreInitialRoute), so this hook only keeps the URL in sync as the active
120
+ // tab changes. No post-mount restore, no routeReady gate.
199
121
  useEffect(() => {
200
- if (!routeReady) return;
201
122
  const nextPath = buildPathForTab(activeTab);
202
123
  if (window.location.pathname === nextPath) return;
203
124
  window.history.replaceState(null, '', nextPath);
204
- }, [activeTab, routeReady]);
125
+ }, [activeTab]);
205
126
  }
206
127
 
207
128
  declare global {
@@ -215,6 +136,7 @@ declare global {
215
136
  const SPLASH_MIN_DURATION_MS = 2800;
216
137
  const SPLASH_ENHANCED_HOLD_MS = 800;
217
138
  const SPLASH_FADE_MS = 480;
139
+ const SPLASH_ROUTE_RESTORE_FADE_MS = 120;
218
140
  const SPLASH_REDUCED_MIN_DURATION_MS = 600;
219
141
  const SPLASH_REDUCED_HOLD_MS = 200;
220
142
  const SPLASH_REDUCED_FADE_MS = 180;
@@ -240,9 +162,22 @@ export const App = (): React.JSX.Element => {
240
162
  const enhancedStartedAt = window.__claudeTeamsSplashEnhancedStartedAt ?? performance.now();
241
163
  const elapsed = performance.now() - startedAt;
242
164
  const enhancedElapsed = performance.now() - enhancedStartedAt;
243
- const minDuration = reducedMotion ? SPLASH_REDUCED_MIN_DURATION_MS : SPLASH_MIN_DURATION_MS;
244
- const enhancedHold = reducedMotion ? SPLASH_REDUCED_HOLD_MS : SPLASH_ENHANCED_HOLD_MS;
245
- const fadeDuration = reducedMotion ? SPLASH_REDUCED_FADE_MS : SPLASH_FADE_MS;
165
+ const routeRestored = window.location.pathname !== '/' && window.location.pathname !== '';
166
+ const minDuration = routeRestored
167
+ ? 0
168
+ : reducedMotion
169
+ ? SPLASH_REDUCED_MIN_DURATION_MS
170
+ : SPLASH_MIN_DURATION_MS;
171
+ const enhancedHold = routeRestored
172
+ ? 0
173
+ : reducedMotion
174
+ ? SPLASH_REDUCED_HOLD_MS
175
+ : SPLASH_ENHANCED_HOLD_MS;
176
+ const fadeDuration = routeRestored
177
+ ? SPLASH_ROUTE_RESTORE_FADE_MS
178
+ : reducedMotion
179
+ ? SPLASH_REDUCED_FADE_MS
180
+ : SPLASH_FADE_MS;
246
181
  const avatarReadyMaxWait = reducedMotion
247
182
  ? SPLASH_REDUCED_AVATAR_READY_MAX_WAIT_MS
248
183
  : SPLASH_AVATAR_READY_MAX_WAIT_MS;
@@ -21,6 +21,8 @@ import type {
21
21
  BoardTaskLogStreamSummary,
22
22
  CcSession,
23
23
  CcSessionDetail,
24
+ LoopSessionRequest,
25
+ LoopSessionResponse,
24
26
  ClaudeMdFileInfo,
25
27
  ClaudeRootFolderSelection,
26
28
  ClaudeRootInfo,
@@ -34,12 +36,14 @@ import type {
34
36
  CrossTeamAPI,
35
37
  CrossTeamMessage,
36
38
  CrossTeamSendResult,
39
+ DiscoverableWorker,
37
40
  ElectronAPI,
38
41
  FileChangeEvent,
39
42
  GlobalTask,
40
43
  HttpServerAPI,
41
44
  HttpServerStatus,
42
45
  KanbanColumnId,
46
+ LoopAssetsSnapshot,
43
47
  MachineProfile,
44
48
  MachineRuntimeProcess,
45
49
  MemberFullStats,
@@ -108,6 +112,12 @@ import type { AgentConfig } from '@shared/types/api';
108
112
  import type { CliProviderStatus } from '@shared/types/cliInstaller';
109
113
  import type { EditorAPI, ProjectAPI, WorkspaceListResponse } from '@shared/types/editor';
110
114
  import type {
115
+ CapabilityCommandPromptRequest,
116
+ CapabilityCommandPromptResult,
117
+ CapabilityPackExportRequest,
118
+ CapabilityPackImportRequest,
119
+ CapabilityPackListResult,
120
+ CapabilityPackMutationResult,
111
121
  EnrichedPlugin,
112
122
  InstalledMcpEntry,
113
123
  McpCatalogItem,
@@ -240,8 +250,8 @@ export class HttpAPIClient implements ElectronAPI {
240
250
  return JSON.parse(text, (key, value) => HttpAPIClient.reviveDates(key, value)) as T;
241
251
  }
242
252
 
243
- private async get<T>(path: string): Promise<T> {
244
- const { controller, timeout } = this.createTimeoutController(10_000);
253
+ private async get<T>(path: string, timeoutMs = 10_000): Promise<T> {
254
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
245
255
  try {
246
256
  const res = await fetch(`${this.baseUrl}${path}`, { signal: controller.signal });
247
257
  return this.parseJson<T>(res);
@@ -250,8 +260,8 @@ export class HttpAPIClient implements ElectronAPI {
250
260
  }
251
261
  }
252
262
 
253
- private async post<T>(path: string, body?: unknown): Promise<T> {
254
- const { controller, timeout } = this.createTimeoutController(10_000);
263
+ private async post<T>(path: string, body?: unknown, timeoutMs = 10_000): Promise<T> {
264
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
255
265
  try {
256
266
  const res = await fetch(`${this.baseUrl}${path}`, {
257
267
  method: 'POST',
@@ -280,8 +290,8 @@ export class HttpAPIClient implements ElectronAPI {
280
290
  }
281
291
  }
282
292
 
283
- private async del<T>(path: string, body?: unknown): Promise<T> {
284
- const { controller, timeout } = this.createTimeoutController(10_000);
293
+ private async del<T>(path: string, body?: unknown, timeoutMs = 10_000): Promise<T> {
294
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
285
295
  try {
286
296
  const res = await fetch(`${this.baseUrl}${path}`, {
287
297
  method: 'DELETE',
@@ -295,8 +305,8 @@ export class HttpAPIClient implements ElectronAPI {
295
305
  }
296
306
  }
297
307
 
298
- private async put<T>(path: string, body?: unknown): Promise<T> {
299
- const { controller, timeout } = this.createTimeoutController(10_000);
308
+ private async put<T>(path: string, body?: unknown, timeoutMs = 10_000): Promise<T> {
309
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
300
310
  try {
301
311
  const res = await fetch(`${this.baseUrl}${path}`, {
302
312
  method: 'PUT',
@@ -310,8 +320,8 @@ export class HttpAPIClient implements ElectronAPI {
310
320
  }
311
321
  }
312
322
 
313
- private async patch<T>(path: string, body?: unknown): Promise<T> {
314
- const { controller, timeout } = this.createTimeoutController(10_000);
323
+ private async patch<T>(path: string, body?: unknown, timeoutMs = 10_000): Promise<T> {
324
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
315
325
  try {
316
326
  const res = await fetch(`${this.baseUrl}${path}`, {
317
327
  method: 'PATCH',
@@ -325,8 +335,8 @@ export class HttpAPIClient implements ElectronAPI {
325
335
  }
326
336
  }
327
337
 
328
- private async delete<T>(path: string): Promise<T> {
329
- const { controller, timeout } = this.createTimeoutController(10_000);
338
+ private async delete<T>(path: string, timeoutMs = 10_000): Promise<T> {
339
+ const { controller, timeout } = this.createTimeoutController(timeoutMs);
330
340
  try {
331
341
  const res = await fetch(`${this.baseUrl}${path}`, {
332
342
  method: 'DELETE',
@@ -535,11 +545,11 @@ export class HttpAPIClient implements ElectronAPI {
535
545
  work_dir?: string;
536
546
  agent_type?: string;
537
547
  }
538
- ): Promise<{ message: string; restart_required: boolean }> => {
539
- const res = await this.post<{
548
+ ): Promise<{ message: string; restart_required: boolean; restart_handled?: boolean }> => {
549
+ const res = await this.postLong<{
540
550
  ok: boolean;
541
- data: { message: string; restart_required: boolean };
542
- }>(`/api/projects/${encodeURIComponent(projectName)}/add-platform`, body);
551
+ data: { message: string; restart_required: boolean; restart_handled?: boolean };
552
+ }>(`/api/projects/${encodeURIComponent(projectName)}/add-platform`, body, 120_000);
543
553
  return res.data;
544
554
  },
545
555
  };
@@ -1093,11 +1103,25 @@ export class HttpAPIClient implements ElectronAPI {
1093
1103
  };
1094
1104
 
1095
1105
  teams: TeamsAPI = {
1096
- list: async (): Promise<TeamSummary[]> => this.get<TeamSummary[]>('/api/teams'),
1106
+ list: async (): Promise<TeamSummary[]> => this.get<TeamSummary[]>('/api/teams', 30_000),
1097
1107
  ensureSystemManager: async (): Promise<SystemManagerSummary> =>
1098
1108
  this.post<SystemManagerSummary>('/api/system-manager/ensure'),
1099
1109
  getData: async (teamName: string): Promise<TeamViewSnapshot> =>
1100
- this.get<TeamViewSnapshot>(`/api/teams/${encodeURIComponent(teamName)}/data`),
1110
+ this.get<TeamViewSnapshot>(`/api/teams/${encodeURIComponent(teamName)}/data`, 30_000),
1111
+ getLoopAssets: async (teamName: string): Promise<LoopAssetsSnapshot> =>
1112
+ this.get<LoopAssetsSnapshot>(
1113
+ `/api/teams/${encodeURIComponent(teamName)}/loop-assets`,
1114
+ 30_000
1115
+ ),
1116
+ createLoopSession: async (
1117
+ teamName: string,
1118
+ request: LoopSessionRequest
1119
+ ): Promise<LoopSessionResponse> =>
1120
+ this.postLong<LoopSessionResponse>(
1121
+ `/api/teams/${encodeURIComponent(teamName)}/loop-session`,
1122
+ request,
1123
+ 30_000
1124
+ ),
1101
1125
  getTaskChangePresence: async (): Promise<
1102
1126
  Record<string, 'has_changes' | 'no_changes' | 'unknown'>
1103
1127
  > => {
@@ -1395,7 +1419,15 @@ export class HttpAPIClient implements ElectronAPI {
1395
1419
  teamName: string,
1396
1420
  config: TeamUpdateConfigRequest
1397
1421
  ): Promise<TeamConfig> => {
1398
- return this.put(`/api/teams/${encodeURIComponent(teamName)}/config`, config);
1422
+ const result = await this.put<TeamConfig>(
1423
+ `/api/teams/${encodeURIComponent(teamName)}/config`,
1424
+ config,
1425
+ 120_000
1426
+ );
1427
+ if (result.ccSyncError) {
1428
+ throw new Error(`配置已保存到本地,但同步到运行时失败:${result.ccSyncError}`);
1429
+ }
1430
+ return result;
1399
1431
  },
1400
1432
  addTaskComment: async (
1401
1433
  teamName: string,
@@ -1477,7 +1509,9 @@ export class HttpAPIClient implements ElectronAPI {
1477
1509
  },
1478
1510
  restartMember: async (teamName: string, memberName: string): Promise<void> => {
1479
1511
  await this.post(
1480
- `/api/teams/${encodeURIComponent(teamName)}/members/${encodeURIComponent(memberName)}/restart`
1512
+ `/api/teams/${encodeURIComponent(teamName)}/members/${encodeURIComponent(memberName)}/restart`,
1513
+ undefined,
1514
+ 30_000
1481
1515
  );
1482
1516
  },
1483
1517
  skipMemberForLaunch: async (teamName: string, memberName: string): Promise<void> => {
@@ -1654,6 +1688,28 @@ export class HttpAPIClient implements ElectronAPI {
1654
1688
  this.get<CrossTeamMessage[]>(`/api/cross-team/outbox/${encodeURIComponent(teamName)}`),
1655
1689
  };
1656
1690
 
1691
+ workers = {
1692
+ list: () => this.get<{ workers: DiscoverableWorker[] }>('/api/workers'),
1693
+ invoke: (
1694
+ workerId: string,
1695
+ request: {
1696
+ fromTeam?: string;
1697
+ text: string;
1698
+ summary?: string;
1699
+ sessionName?: string;
1700
+ reuse?: boolean;
1701
+ sessionKey?: string;
1702
+ }
1703
+ ) =>
1704
+ this.postLong<{
1705
+ ok: boolean;
1706
+ worker: DiscoverableWorker;
1707
+ session: CcSession;
1708
+ reused: boolean;
1709
+ messageSent: boolean;
1710
+ }>(`/api/workers/${encodeURIComponent(workerId)}/invoke`, request, 30_000),
1711
+ };
1712
+
1657
1713
  // Collaboration board API
1658
1714
  collab = {
1659
1715
  getBoard: () => this.get<{ tasks: CollabTask[] }>('/api/collab/board'),
@@ -2015,14 +2071,19 @@ export class HttpAPIClient implements ElectronAPI {
2015
2071
  if (forceRefresh) params.set('forceRefresh', 'true');
2016
2072
  const qs = params.toString();
2017
2073
  const result = await this.get<{ success: boolean; data?: EnrichedPlugin[]; error?: string }>(
2018
- `/api/extensions/plugins${qs ? `?${qs}` : ''}`
2074
+ `/api/extensions/plugins${qs ? `?${qs}` : ''}`,
2075
+ // Catalog assembly scans local installs + remote registries (GitHub),
2076
+ // which routinely exceeds the default 10s — match the team-endpoint
2077
+ // 30s budget so the Extensions store doesn't time out on first open.
2078
+ 30_000
2019
2079
  );
2020
2080
  if (!result.success) throw new Error(result.error ?? 'Failed to get plugins');
2021
2081
  return result.data ?? [];
2022
2082
  },
2023
2083
  getReadme: async (pluginId: string) => {
2024
2084
  const result = await this.get<{ success: boolean; data?: string | null; error?: string }>(
2025
- `/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme`
2085
+ `/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme`,
2086
+ 30_000
2026
2087
  );
2027
2088
  if (!result.success) throw new Error(result.error ?? 'Failed to get readme');
2028
2089
  return result.data ?? null;
@@ -2178,6 +2239,47 @@ export class HttpAPIClient implements ElectronAPI {
2178
2239
  },
2179
2240
  };
2180
2241
 
2242
+ capabilityPacks = {
2243
+ list: async () => {
2244
+ const result = await this.get<{
2245
+ success: boolean;
2246
+ data?: CapabilityPackListResult;
2247
+ error?: string;
2248
+ }>('/api/extensions/capability-packs');
2249
+ if (!result.success)
2250
+ return { packs: [], warnings: result.error ? [result.error] : [], rootDir: '' };
2251
+ return result.data ?? { packs: [], warnings: [], rootDir: '' };
2252
+ },
2253
+ importPack: async (request: CapabilityPackImportRequest) => {
2254
+ const result = await this.post<{
2255
+ success: boolean;
2256
+ data?: CapabilityPackMutationResult;
2257
+ error?: string;
2258
+ }>('/api/extensions/capability-packs/import', request);
2259
+ if (!result.success) throw new Error(result.error ?? 'Import capability pack failed');
2260
+ return result.data ?? { pack: null, warnings: [] };
2261
+ },
2262
+ exportPack: async (request: CapabilityPackExportRequest) => {
2263
+ const result = await this.post<{
2264
+ success: boolean;
2265
+ data?: CapabilityPackMutationResult;
2266
+ error?: string;
2267
+ }>('/api/extensions/capability-packs/export', request);
2268
+ if (!result.success) throw new Error(result.error ?? 'Export capability pack failed');
2269
+ return result.data ?? { pack: null, warnings: [] };
2270
+ },
2271
+ getCommandPrompt: async (request: CapabilityCommandPromptRequest) => {
2272
+ const result = await this.post<{
2273
+ success: boolean;
2274
+ data?: CapabilityCommandPromptResult;
2275
+ error?: string;
2276
+ }>('/api/extensions/capability-packs/command-prompt', request);
2277
+ if (!result.success) throw new Error(result.error ?? 'Load capability command failed');
2278
+ if (!result.data) throw new Error('Load capability command failed');
2279
+ return result.data;
2280
+ },
2281
+ };
2282
+
2181
2283
  skills = {
2182
2284
  list: async (projectPath?: string) => {
2183
2285
  const params = new URLSearchParams();
@@ -2305,44 +2407,22 @@ export class HttpAPIClient implements ElectronAPI {
2305
2407
  getConfig: () => this.get('/api/system-manager/config'),
2306
2408
  updateConfig: (patch) => this.put('/api/system-manager/config', patch),
2307
2409
  listWorkflowPrompts: (folder) => this.post('/api/system-manager/workflows/list', { folder }),
2308
- readWorkflowPrompt: (_folder, id) => this.post('/api/system-manager/workflows/read', { id }),
2410
+ readWorkflowPrompt: (folder, id) =>
2411
+ this.post('/api/system-manager/workflows/read', { folder, id }),
2309
2412
  };
2310
2413
 
2311
2414
  // ---------------------------------------------------------------------------
2312
- // Terminal (HTTP/SSE-backed browser mode)
2415
+ // Terminal (system/default terminal)
2313
2416
  // ---------------------------------------------------------------------------
2314
2417
 
2315
2418
  terminal: TerminalAPI = {
2316
- spawn: async (options = {}): Promise<string> => {
2317
- const result = await this.post<{ ptyId: string }>('/api/terminal/spawn', options);
2318
- return result.ptyId;
2319
- },
2320
- write: (ptyId: string, data: string): void => {
2321
- void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/write`, { data });
2322
- },
2323
- resize: (ptyId: string, cols: number, rows: number): void => {
2324
- void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/resize`, { cols, rows });
2325
- },
2326
- kill: async (ptyId: string): Promise<void> => {
2327
- await this.del(`/api/terminal/${encodeURIComponent(ptyId)}`);
2328
- },
2329
- openExternal: async (options: { command: string; args?: string[]; cwd?: string }): Promise<void> => {
2419
+ openExternal: async (options: {
2420
+ command: string;
2421
+ args?: string[];
2422
+ cwd?: string;
2423
+ }): Promise<void> => {
2330
2424
  await this.post('/api/terminal/open-external', options);
2331
2425
  },
2332
- onData: (callback): (() => void) =>
2333
- this.addEventListener('terminal:data', (data: unknown) => {
2334
- const event = data as { ptyId?: string; data?: string };
2335
- if (event.ptyId && typeof event.data === 'string') {
2336
- callback(null, event.ptyId, event.data);
2337
- }
2338
- }),
2339
- onExit: (callback): (() => void) =>
2340
- this.addEventListener('terminal:exit', (data: unknown) => {
2341
- const event = data as { ptyId?: string; exitCode?: number };
2342
- if (event.ptyId && typeof event.exitCode === 'number') {
2343
- callback(null, event.ptyId, event.exitCode);
2344
- }
2345
- }),
2346
2426
  };
2347
2427
 
2348
2428
  // ---------------------------------------------------------------------------
@@ -5,11 +5,7 @@
5
5
  * cc-connect sidecar is the source of truth for provider/channel management.
6
6
  */
7
7
 
8
- import type {
9
- CCSwitchListResponse,
10
- GlobalProvider,
11
- ProviderPresetsResponse,
12
- } from '@shared/types/providers';
8
+ import type { GlobalProvider, ProviderPresetsResponse } from '@shared/types/providers';
13
9
 
14
10
  function stringifyProviderPatch(patch: Partial<GlobalProvider>): string {
15
11
  return JSON.stringify(patch, (_key, value: unknown) => (value === undefined ? null : value));
@@ -45,7 +41,7 @@ async function request<T>(path: string, init?: RequestInit & { timeoutMs?: numbe
45
41
  if (!contentType.includes('json') || !text.trim().startsWith('{')) {
46
42
  throw new Error(
47
43
  `Provider API ${path} 返回了非 JSON 响应 (HTTP ${res.status})。` +
48
- '请检查 cc-connect 是否正在运行且支持该端点。'
44
+ '请检查 cc-connect 是否正在运行且支持该端点。'
49
45
  );
50
46
  }
51
47
 
@@ -53,7 +49,9 @@ async function request<T>(path: string, init?: RequestInit & { timeoutMs?: numbe
53
49
  try {
54
50
  json = JSON.parse(text) as typeof json;
55
51
  } catch (e) {
56
- throw new Error(`Provider API ${path} 返回了无效 JSON: ${e instanceof Error ? e.message : String(e)}`);
52
+ throw new Error(
53
+ `Provider API ${path} 返回了无效 JSON: ${e instanceof Error ? e.message : String(e)}`
54
+ );
57
55
  }
58
56
 
59
57
  if (!res.ok || json.ok === false) {
@@ -86,13 +84,4 @@ export const providersApi = {
86
84
  timeoutMs: 20_000,
87
85
  });
88
86
  },
89
- listCCSwitch(): Promise<CCSwitchListResponse> {
90
- return request('/providers/cc-switch');
91
- },
92
- importCCSwitch(names: string[]): Promise<{ imported: string[]; skipped: string[] }> {
93
- return request('/providers/cc-switch', {
94
- method: 'POST',
95
- body: JSON.stringify({ names }),
96
- });
97
- },
98
87
  };