@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
@@ -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,
@@ -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
  };
@@ -1098,6 +1108,20 @@ export class HttpAPIClient implements ElectronAPI {
1098
1108
  this.post<SystemManagerSummary>('/api/system-manager/ensure'),
1099
1109
  getData: async (teamName: string): Promise<TeamViewSnapshot> =>
1100
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,
@@ -1656,6 +1688,28 @@ export class HttpAPIClient implements ElectronAPI {
1656
1688
  this.get<CrossTeamMessage[]>(`/api/cross-team/outbox/${encodeURIComponent(teamName)}`),
1657
1689
  };
1658
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
+
1659
1713
  // Collaboration board API
1660
1714
  collab = {
1661
1715
  getBoard: () => this.get<{ tasks: CollabTask[] }>('/api/collab/board'),
@@ -2017,14 +2071,19 @@ export class HttpAPIClient implements ElectronAPI {
2017
2071
  if (forceRefresh) params.set('forceRefresh', 'true');
2018
2072
  const qs = params.toString();
2019
2073
  const result = await this.get<{ success: boolean; data?: EnrichedPlugin[]; error?: string }>(
2020
- `/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
2021
2079
  );
2022
2080
  if (!result.success) throw new Error(result.error ?? 'Failed to get plugins');
2023
2081
  return result.data ?? [];
2024
2082
  },
2025
2083
  getReadme: async (pluginId: string) => {
2026
2084
  const result = await this.get<{ success: boolean; data?: string | null; error?: string }>(
2027
- `/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme`
2085
+ `/api/extensions/plugins/${encodeURIComponent(pluginId)}/readme`,
2086
+ 30_000
2028
2087
  );
2029
2088
  if (!result.success) throw new Error(result.error ?? 'Failed to get readme');
2030
2089
  return result.data ?? null;
@@ -2180,6 +2239,47 @@ export class HttpAPIClient implements ElectronAPI {
2180
2239
  },
2181
2240
  };
2182
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
+
2183
2283
  skills = {
2184
2284
  list: async (projectPath?: string) => {
2185
2285
  const params = new URLSearchParams();
@@ -2307,44 +2407,22 @@ export class HttpAPIClient implements ElectronAPI {
2307
2407
  getConfig: () => this.get('/api/system-manager/config'),
2308
2408
  updateConfig: (patch) => this.put('/api/system-manager/config', patch),
2309
2409
  listWorkflowPrompts: (folder) => this.post('/api/system-manager/workflows/list', { folder }),
2310
- 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 }),
2311
2412
  };
2312
2413
 
2313
2414
  // ---------------------------------------------------------------------------
2314
- // Terminal (HTTP/SSE-backed browser mode)
2415
+ // Terminal (system/default terminal)
2315
2416
  // ---------------------------------------------------------------------------
2316
2417
 
2317
2418
  terminal: TerminalAPI = {
2318
- spawn: async (options = {}): Promise<string> => {
2319
- const result = await this.post<{ ptyId: string }>('/api/terminal/spawn', options);
2320
- return result.ptyId;
2321
- },
2322
- write: (ptyId: string, data: string): void => {
2323
- void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/write`, { data });
2324
- },
2325
- resize: (ptyId: string, cols: number, rows: number): void => {
2326
- void this.post(`/api/terminal/${encodeURIComponent(ptyId)}/resize`, { cols, rows });
2327
- },
2328
- kill: async (ptyId: string): Promise<void> => {
2329
- await this.del(`/api/terminal/${encodeURIComponent(ptyId)}`);
2330
- },
2331
- 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> => {
2332
2424
  await this.post('/api/terminal/open-external', options);
2333
2425
  },
2334
- onData: (callback): (() => void) =>
2335
- this.addEventListener('terminal:data', (data: unknown) => {
2336
- const event = data as { ptyId?: string; data?: string };
2337
- if (event.ptyId && typeof event.data === 'string') {
2338
- callback(null, event.ptyId, event.data);
2339
- }
2340
- }),
2341
- onExit: (callback): (() => void) =>
2342
- this.addEventListener('terminal:exit', (data: unknown) => {
2343
- const event = data as { ptyId?: string; exitCode?: number };
2344
- if (event.ptyId && typeof event.exitCode === 'number') {
2345
- callback(null, event.ptyId, event.exitCode);
2346
- }
2347
- }),
2348
2426
  };
2349
2427
 
2350
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
  };
@@ -0,0 +1,81 @@
1
+ import React from 'react';
2
+
3
+ import { MessageCircle, QrCode, Sparkles, Users } from 'lucide-react';
4
+
5
+ const COMMUNITY_QR_IMAGE = '/chat-community-qr.jpg';
6
+
7
+ export const CommunityChatView = (): React.JSX.Element => {
8
+ return (
9
+ <div className="relative flex-1 overflow-auto bg-surface">
10
+ <div
11
+ className="pointer-events-none absolute inset-x-0 top-0 h-[520px] bg-[radial-gradient(ellipse_80%_50%_at_50%_-20%,rgba(132,204,22,0.14),transparent)]"
12
+ aria-hidden="true"
13
+ />
14
+
15
+ <div className="relative mx-auto flex min-h-full max-w-5xl flex-col px-8 py-12">
16
+ <section className="overflow-hidden rounded-2xl border border-border bg-surface-raised shadow-sm">
17
+ <div className="border-b border-border bg-gradient-to-br from-lime-500/15 via-emerald-500/10 to-transparent px-8 py-8">
18
+ <div className="mb-3 inline-flex items-center gap-2 rounded-full border border-lime-500/25 bg-lime-500/10 px-3 py-1 text-[11px] font-medium text-lime-300">
19
+ <MessageCircle className="size-3.5" />
20
+ Chat / 交流圈
21
+ </div>
22
+ <h1 className="text-3xl font-semibold tracking-tight text-text">加入 Yancy 的朋友们</h1>
23
+ <p className="mt-3 max-w-2xl text-sm leading-6 text-text-secondary">
24
+ 扫码加入「野生想法」交流圈,聊 Loop Engineering、Agent
25
+ Teams、自动化工作台和一人公司的实践。
26
+ </p>
27
+ </div>
28
+
29
+ <div className="grid gap-8 px-8 py-8 lg:grid-cols-[minmax(0,1fr)_360px]">
30
+ <div className="space-y-4">
31
+ <div className="rounded-xl border border-border bg-surface px-5 py-4">
32
+ <div className="mb-2 flex items-center gap-2 text-sm font-medium text-text">
33
+ <Users className="size-4 text-lime-400" />
34
+ 适合谁加入
35
+ </div>
36
+ <p className="text-sm leading-6 text-text-muted">
37
+ 如果你正在用 Claude Code / Hermit / 多 Agent 团队做真实项目,或者想交流 AI
38
+ 自动化、产品工程和独立创造,这里会持续分享实验和想法。
39
+ </p>
40
+ </div>
41
+
42
+ <div className="rounded-xl border border-border bg-surface px-5 py-4">
43
+ <div className="mb-2 flex items-center gap-2 text-sm font-medium text-text">
44
+ <Sparkles className="size-4 text-emerald-400" />
45
+ 你可以期待
46
+ </div>
47
+ <ul className="space-y-2 text-sm leading-6 text-text-muted">
48
+ <li>• Hermit / OpenHermit 的功能讨论和使用反馈</li>
49
+ <li>• Agent 团队、Loop、Workflow 的实践案例</li>
50
+ <li>• 一人公司、自动化研发和产品想法交流</li>
51
+ </ul>
52
+ </div>
53
+
54
+ <div className="rounded-xl border border-lime-500/20 bg-lime-500/5 px-5 py-4 text-sm leading-6 text-lime-100/90">
55
+ 备注:该二维码来自飞书 / Lark 圈子,仅限企业内部成员加入;如果扫码不可用,请联系
56
+ Yancy 获取新的邀请方式。
57
+ </div>
58
+ </div>
59
+
60
+ <div className="rounded-2xl border border-border bg-surface px-5 py-5 text-center">
61
+ <div className="mb-3 inline-flex items-center gap-2 text-sm font-medium text-text">
62
+ <QrCode className="size-4 text-lime-400" />
63
+ 扫码加入
64
+ </div>
65
+ <div className="rounded-2xl border border-border bg-white p-3 shadow-sm">
66
+ <img
67
+ src={COMMUNITY_QR_IMAGE}
68
+ alt="Yancy 的朋友们交流圈二维码"
69
+ className="mx-auto aspect-square w-full rounded-xl object-cover"
70
+ />
71
+ </div>
72
+ <p className="mt-4 text-xs leading-5 text-text-muted">
73
+ 打开飞书 / Lark 扫一扫,加入「Yancy 的朋友们 · 野生想法」。
74
+ </p>
75
+ </div>
76
+ </div>
77
+ </section>
78
+ </div>
79
+ </div>
80
+ );
81
+ };