@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
@@ -1193,7 +1193,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
1193
1193
  const parts: string[] = [];
1194
1194
  if (providerChangeForcesFreshLeadContext && previousProviderId) {
1195
1195
  parts.push(
1196
- `提供商已从 ${getProviderLabel(previousProviderId)} 更改为 ${getProviderLabel(selectedProviderId)}。之前的负责人会话不会恢复,负责人会以全新上下文启动。`
1196
+ `提供商已从 ${getProviderLabel(previousProviderId)} 更改为 ${getProviderLabel(selectedProviderId)}。之前的 Lead 会话不会恢复,Lead 会以全新上下文启动。`
1197
1197
  );
1198
1198
  }
1199
1199
  const runtimeChange = runtimeChangeNoteByKey.get('lead');
@@ -1596,7 +1596,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
1596
1596
  if (!isLaunchMode) return [];
1597
1597
 
1598
1598
  const summary: string[] = [];
1599
- if (promptDraft.value.trim()) summary.push('负责人提示词');
1599
+ if (promptDraft.value.trim()) summary.push('Lead 指令');
1600
1600
  const worktreeMemberCount = effectiveMemberDrafts.filter(
1601
1601
  (member) => !member.removedAt && member.isolation === 'worktree'
1602
1602
  ).length;
@@ -1646,7 +1646,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
1646
1646
  if (!effectiveCwd) errors.push('必须填写工作目录');
1647
1647
  if (isSchedule) {
1648
1648
  if (!effectiveTeamName) errors.push('必须选择团队');
1649
- if (!promptDraft.value.trim()) errors.push('必须填写提示词');
1649
+ if (!promptDraft.value.trim()) errors.push('必须填写指令');
1650
1650
  if (!cronExpression.trim()) errors.push('必须填写 Cron 表达式');
1651
1651
  }
1652
1652
  return errors;
@@ -2052,7 +2052,8 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2052
2052
  </>
2053
2053
  ) : (
2054
2054
  <>
2055
- 通过 Agent CLI 启动数字员工 <span className="font-mono font-medium">{effectiveTeamName}</span>。
2055
+ 通过 Agent CLI 启动数字员工{' '}
2056
+ <span className="font-mono font-medium">{effectiveTeamName}</span>。
2056
2057
  </>
2057
2058
  )
2058
2059
  ) : isEditing ? (
@@ -2202,7 +2203,8 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2202
2203
  <div className="flex items-start gap-2">
2203
2204
  <AlertTriangle className="mt-0.5 size-3.5 shrink-0" />
2204
2205
  <p>
2205
- 团队负责人会启动一个新会话,不再恢复之前的上下文。已积累的会话记忆和对话历史将不可用。
2206
+ Lead
2207
+ 会启动一个新会话,不再恢复之前的上下文。已积累的会话记忆和运行历史将不可用。
2206
2208
  </p>
2207
2209
  </div>
2208
2210
  </div>
@@ -2392,9 +2394,9 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2392
2394
 
2393
2395
  <div className="rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] p-3">
2394
2396
  <div className="mb-2">
2395
- <p className="text-xs font-medium text-[var(--color-text)]">团队运行时</p>
2397
+ <p className="text-xs font-medium text-[var(--color-text)]">运行时</p>
2396
2398
  <p className="mt-0.5 text-[11px] text-[var(--color-text-muted)]">
2397
- Provider 作用于整个团队;成员只选择模型,默认继承这里的 provider。
2399
+ Provider 作用于整个循环;成员只选择模型,默认继承这里的 provider。
2398
2400
  </p>
2399
2401
  </div>
2400
2402
  <TeamModelSelector
@@ -2469,7 +2471,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2469
2471
  inheritModelSettingsByDefault
2470
2472
  lockProviderModel={syncModelsWithLead}
2471
2473
  forceInheritedModelSettings={syncModelsWithLead}
2472
- modelLockReason="该成员当前与团队负责人模型保持同步。关闭同步后可单独设置提供商、模型或推理强度。"
2474
+ modelLockReason="该成员当前与 Lead 模型保持同步。关闭同步后可单独设置提供商、模型或推理强度。"
2473
2475
  providerId={selectedProviderId}
2474
2476
  model={selectedModel}
2475
2477
  effort={(selectedEffort as EffortLevel) || undefined}
@@ -2495,7 +2497,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2495
2497
 
2496
2498
  <div className="space-y-1.5">
2497
2499
  <Label htmlFor="dialog-prompt" className="label-optional">
2498
- 给团队负责人的提示(可选)
2500
+ 给 Lead 的启动指令(可选)
2499
2501
  </Label>
2500
2502
  <MentionableTextarea
2501
2503
  id="dialog-prompt"
@@ -2509,7 +2511,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2509
2511
  chips={chipDraft.chips}
2510
2512
  onChipRemove={chipDraft.removeChip}
2511
2513
  onFileChipInsert={chipDraft.addChip}
2512
- placeholder="填写给团队负责人的说明..."
2514
+ placeholder="填写给 Lead 的循环目标、约束或启动说明..."
2513
2515
  footerRight={
2514
2516
  promptDraft.isSaved ? (
2515
2517
  <span className="text-[10px] text-[var(--color-text-muted)]">已保存</span>
@@ -2541,7 +2543,8 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2541
2543
  <p>
2542
2544
  提供商已从 {getProviderLabel(previousProviderId!)} 更改为{' '}
2543
2545
  {getProviderLabel(selectedProviderId)}
2544
- 。之前的负责人会话不会恢复,负责人会以全新上下文启动,以正确应用新的运行时。
2546
+ 。之前的 Lead 会话不会恢复,Lead
2547
+ 会以全新上下文启动,以正确应用新的运行时。
2545
2548
  </p>
2546
2549
  </div>
2547
2550
  </div>
@@ -2572,7 +2575,8 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2572
2575
  <div className="flex items-start gap-2">
2573
2576
  <AlertTriangle className="mt-0.5 size-3.5 shrink-0" />
2574
2577
  <p>
2575
- 团队负责人会启动一个新会话,不再恢复之前的上下文。已积累的会话记忆和对话历史将不可用。
2578
+ Lead
2579
+ 会启动一个新会话,不再恢复之前的上下文。已积累的会话记忆和运行历史将不可用。
2576
2580
  </p>
2577
2581
  </div>
2578
2582
  </div>
@@ -2594,7 +2598,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2594
2598
  ) : (
2595
2599
  <>
2596
2600
  <div className="space-y-1.5">
2597
- <Label htmlFor="dialog-prompt">提示词</Label>
2601
+ <Label htmlFor="dialog-prompt">定时指令</Label>
2598
2602
  <MentionableTextarea
2599
2603
  id="dialog-prompt"
2600
2604
  className="min-h-[100px] text-xs"
@@ -2607,7 +2611,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2607
2611
  chips={chipDraft.chips}
2608
2612
  onChipRemove={chipDraft.removeChip}
2609
2613
  onFileChipInsert={chipDraft.addChip}
2610
- placeholder="填写定时执行时给 Claude 的说明..."
2614
+ placeholder="填写定时触发后交给 Lead 的循环指令..."
2611
2615
  footerRight={
2612
2616
  promptDraft.isSaved ? (
2613
2617
  <span className="text-[10px] text-[var(--color-text-muted)]">已保存</span>
@@ -2615,7 +2619,7 @@ export const LaunchTeamDialog = (props: LaunchTeamDialogProps): React.JSX.Elemen
2615
2619
  }
2616
2620
  />
2617
2621
  <p className="text-[11px] text-[var(--color-text-muted)]">
2618
- 该提示词会传递给 <code className="font-mono">claude -p</code> 用于 one-shot
2622
+ 该指令会传递给 <code className="font-mono">claude -p</code> 用于 one-shot
2619
2623
  execution
2620
2624
  </p>
2621
2625
  </div>
@@ -1,4 +1,4 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useEffect, useMemo, useState } from 'react';
2
2
 
3
3
  import { Button } from '@renderer/components/ui/button';
4
4
  import {
@@ -92,11 +92,17 @@ const PLATFORM_OPTIONS: PlatformOption[] = [
92
92
 
93
93
  type BindingStep = 'platform' | 'qr' | 'form';
94
94
 
95
+ export interface PlatformBindingCompleteOptions {
96
+ restartHandled?: boolean;
97
+ }
98
+
95
99
  interface PlatformBindingContentProps {
96
100
  projectName: string;
97
101
  workDir: string;
98
102
  agentType: string;
99
- onComplete: () => void;
103
+ platformAllowFrom?: Record<string, string>;
104
+ platformAllowChat?: Record<string, string>;
105
+ onComplete: (options?: PlatformBindingCompleteOptions) => void;
100
106
  onCancel: () => void;
101
107
  }
102
108
 
@@ -104,6 +110,8 @@ export function PlatformBindingContent({
104
110
  projectName,
105
111
  workDir,
106
112
  agentType,
113
+ platformAllowFrom = {},
114
+ platformAllowChat = {},
107
115
  onComplete,
108
116
  onCancel,
109
117
  }: PlatformBindingContentProps): React.JSX.Element {
@@ -120,6 +128,26 @@ export function PlatformBindingContent({
120
128
  setStep(isQRPlatform(key) ? 'qr' : 'form');
121
129
  };
122
130
 
131
+ const initialFormValues = useMemo((): Record<string, unknown> => {
132
+ const meta = platformMeta[selectedPlatform];
133
+ const values: Record<string, unknown> = {};
134
+ const allowFrom =
135
+ selectedPlatform === 'lark'
136
+ ? (platformAllowFrom.lark ?? platformAllowFrom.feishu)
137
+ : platformAllowFrom[selectedPlatform];
138
+ const allowChat =
139
+ selectedPlatform === 'lark'
140
+ ? (platformAllowChat.lark ?? platformAllowChat.feishu)
141
+ : platformAllowChat[selectedPlatform];
142
+ if (allowFrom && meta?.fields.some((field) => field.key === 'allow_from')) {
143
+ values.allow_from = allowFrom;
144
+ }
145
+ if (allowChat && meta?.fields.some((field) => field.key === 'allow_chat')) {
146
+ values.allow_chat = allowChat;
147
+ }
148
+ return values;
149
+ }, [platformAllowChat, platformAllowFrom, selectedPlatform]);
150
+
123
151
  if (
124
152
  step === 'qr' &&
125
153
  (selectedPlatform === 'feishu' || selectedPlatform === 'lark' || selectedPlatform === 'weixin')
@@ -144,6 +172,7 @@ export function PlatformBindingContent({
144
172
  projectName={projectName}
145
173
  workDir={workDir}
146
174
  agentType={agentType}
175
+ initialValues={initialFormValues}
147
176
  onComplete={onComplete}
148
177
  onCancel={() => setStep('platform')}
149
178
  />
@@ -152,10 +181,11 @@ export function PlatformBindingContent({
152
181
 
153
182
  return (
154
183
  <div className="space-y-3 py-2">
155
- <div className="rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] px-3 py-2 text-xs text-[var(--color-text-muted)]">
156
- 绑定渠道是可选项,用于将数字员工暴露到飞书、微信等外部平台;不绑定也可以在本机直接运行。
157
- <br />
158
- <span className="text-amber-500">⚠️ 绑定新渠道后需要重启服务,将短暂中断所有正在运行的会话。</span>
184
+ <div className="bg-[var(--color-surface-raised)]/60 relative overflow-hidden rounded-xl border border-[var(--color-border-subtle)] px-3 py-2.5 text-xs text-[var(--color-text-muted)] shadow-sm shadow-black/10">
185
+ <div className="pointer-events-none absolute inset-x-6 top-0 h-px bg-gradient-to-r from-transparent via-[var(--color-accent-border)] to-transparent" />
186
+ <p>
187
+ 绑定渠道是可选项,用于将数字员工暴露到飞书、微信等外部平台;不绑定也可以在本机直接运行。
188
+ </p>
159
189
  </div>
160
190
  <div className="grid max-h-80 grid-cols-2 gap-2 overflow-y-auto">
161
191
  {PLATFORM_OPTIONS.map(({ key, label, color, icon }) => (
@@ -163,14 +193,18 @@ export function PlatformBindingContent({
163
193
  key={key}
164
194
  type="button"
165
195
  onClick={() => handlePlatformSelect(key)}
166
- className="flex items-center gap-2.5 rounded-xl border border-[var(--color-border)] bg-[var(--color-surface-raised)] p-3 text-left transition-all hover:border-[var(--color-border-emphasis)] hover:bg-[var(--color-accent)]/5"
196
+ className="group flex items-center gap-2.5 rounded-xl border border-[var(--color-border-subtle)] bg-[var(--color-surface-raised)] p-3 text-left shadow-sm shadow-black/5 transition-all duration-200 hover:-translate-y-0.5 hover:border-[var(--color-accent-border)] hover:bg-[var(--color-accent-soft)] hover:shadow-[0_10px_24px_rgba(0,0,0,0.18)]"
167
197
  >
168
- <div className={`h-9 w-9 rounded-lg ${color} flex shrink-0 items-center justify-center`}>
198
+ <div
199
+ className={`h-9 w-9 rounded-lg ${color} flex shrink-0 items-center justify-center`}
200
+ >
169
201
  {icon === 'qr' ? <Smartphone size={16} /> : <Settings2 size={16} />}
170
202
  </div>
171
203
  <div className="min-w-0">
172
204
  <div className="truncate text-sm font-medium text-[var(--color-text)]">{label}</div>
173
- <div className="text-[11px] text-[var(--color-text-muted)]">{icon === 'qr' ? '扫码绑定' : '手动配置'}</div>
205
+ <div className="text-[11px] text-[var(--color-text-muted)]">
206
+ {icon === 'qr' ? '扫码绑定' : '手动配置'}
207
+ </div>
174
208
  </div>
175
209
  </button>
176
210
  ))}
@@ -195,6 +229,8 @@ export function PlatformBindingDialog({
195
229
  projectName,
196
230
  workDir,
197
231
  agentType,
232
+ platformAllowFrom,
233
+ platformAllowChat,
198
234
  onComplete,
199
235
  onCancel,
200
236
  }: PlatformBindingDialogProps): React.JSX.Element {
@@ -204,7 +240,7 @@ export function PlatformBindingDialog({
204
240
  <DialogHeader>
205
241
  <DialogTitle className="text-sm">绑定渠道</DialogTitle>
206
242
  <DialogDescription className="text-xs">
207
- 可选:为当前数字员工选择外部平台渠道,绑定后通过 Hermit 对外接收消息。
243
+ 可选:为当前数字员工选择外部平台渠道,绑定后通过 Hermit 对外接收 Loop 指令。
208
244
  </DialogDescription>
209
245
  </DialogHeader>
210
246
  <PlatformBindingContent
@@ -212,6 +248,8 @@ export function PlatformBindingDialog({
212
248
  projectName={projectName}
213
249
  workDir={workDir}
214
250
  agentType={agentType}
251
+ platformAllowFrom={platformAllowFrom}
252
+ platformAllowChat={platformAllowChat}
215
253
  onComplete={onComplete}
216
254
  onCancel={onCancel}
217
255
  />
@@ -1,4 +1,4 @@
1
- import { useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import { Button } from '@renderer/components/ui/button';
3
3
  import { Input } from '@renderer/components/ui/input';
4
4
  import { Label } from '@renderer/components/ui/label';
@@ -13,7 +13,8 @@ interface Props {
13
13
  projectName: string;
14
14
  workDir: string;
15
15
  agentType: string;
16
- onComplete: () => void;
16
+ initialValues?: Record<string, unknown>;
17
+ onComplete: (options?: { restartHandled?: boolean }) => void;
17
18
  onCancel: () => void;
18
19
  }
19
20
 
@@ -23,15 +24,19 @@ export default function PlatformManualForm({
23
24
  projectName,
24
25
  workDir,
25
26
  agentType,
27
+ initialValues = {},
26
28
  onComplete,
27
29
  onCancel,
28
30
  }: Props) {
29
- const [values, setValues] = useState<Record<string, unknown>>({});
31
+ const [values, setValues] = useState<Record<string, unknown>>(initialValues);
30
32
  const [showAdvanced, setShowAdvanced] = useState(false);
31
33
  const [saving, setSaving] = useState(false);
32
- const [restarting, setRestarting] = useState(false);
33
34
  const [error, setError] = useState('');
34
35
 
36
+ useEffect(() => {
37
+ setValues(initialValues);
38
+ }, [initialValues, platformType]);
39
+
35
40
  const basicFields = meta.fields.filter((f) => f.group !== 'advanced');
36
41
  const advancedFields = meta.fields.filter((f) => f.group === 'advanced');
37
42
 
@@ -52,23 +57,17 @@ export default function PlatformManualForm({
52
57
  opts[f.key] = v;
53
58
  }
54
59
  }
55
- await api.ccSetup.addPlatform(projectName, {
60
+ const result = await api.ccSetup.addPlatform(projectName, {
56
61
  type: platformType,
57
62
  options: opts,
58
63
  work_dir: workDir,
59
64
  agent_type: agentType,
60
65
  });
61
- // Restart CC Connect to activate the new platform binding
62
- setRestarting(true);
63
- try {
64
- await api.ccSettings.restart();
65
- } catch { /* best effort */ }
66
- onComplete();
66
+ onComplete({ restartHandled: result.restart_handled === true });
67
67
  } catch (e: unknown) {
68
68
  setError(e instanceof Error ? e.message : String(e));
69
69
  } finally {
70
70
  setSaving(false);
71
- setRestarting(false);
72
71
  }
73
72
  };
74
73
 
@@ -2,15 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { QRCodeSVG } from 'qrcode.react';
3
3
  import { Button } from '@renderer/components/ui/button';
4
4
  import { api } from '@renderer/api';
5
- import {
6
- AlertCircle,
7
- CheckCircle2,
8
- Loader2,
9
- RefreshCw,
10
- RotateCcw,
11
- Smartphone,
12
- XCircle,
13
- } from 'lucide-react';
5
+ import { AlertCircle, CheckCircle2, Loader2, RefreshCw, Smartphone, XCircle } from 'lucide-react';
14
6
 
15
7
  type PlatformKind = 'feishu' | 'lark' | 'weixin';
16
8
  type Phase =
@@ -30,7 +22,7 @@ interface Props {
30
22
  projectName: string;
31
23
  workDir: string;
32
24
  agentType: string;
33
- onComplete: () => void;
25
+ onComplete: (options?: { restartHandled?: boolean }) => void;
34
26
  onCancel: () => void;
35
27
  }
36
28
 
@@ -98,7 +90,7 @@ export default function PlatformSetupQR({
98
90
  switch (res.status) {
99
91
  case 'completed':
100
92
  setPhase('saving');
101
- await api.ccSetup.feishuSave({
93
+ const saved = await api.ccSetup.feishuSave({
102
94
  project: projectName,
103
95
  app_id: res.app_id!,
104
96
  app_secret: res.app_secret!,
@@ -107,6 +99,13 @@ export default function PlatformSetupQR({
107
99
  work_dir: workDir,
108
100
  agent_type: agentType,
109
101
  });
102
+ if (saved.restart_required) {
103
+ setPhase('restarting');
104
+ await api.ccSettings.restart();
105
+ onComplete({ restartHandled: true });
106
+ pollingRef.current = false;
107
+ return;
108
+ }
110
109
  setPhase('completed');
111
110
  pollingRef.current = false;
112
111
  return;
@@ -167,7 +166,7 @@ export default function PlatformSetupQR({
167
166
  break;
168
167
  case 'confirmed':
169
168
  setPhase('saving');
170
- await api.ccSetup.weixinSave({
169
+ const saved = await api.ccSetup.weixinSave({
171
170
  project: projectName,
172
171
  token: pollRes.bot_token!,
173
172
  base_url: pollRes.base_url,
@@ -176,6 +175,12 @@ export default function PlatformSetupQR({
176
175
  work_dir: workDir,
177
176
  agent_type: agentType,
178
177
  });
178
+ if (saved.restart_required) {
179
+ setPhase('restarting');
180
+ await api.ccSettings.restart();
181
+ onComplete({ restartHandled: true });
182
+ return;
183
+ }
179
184
  setPhase('completed');
180
185
  return;
181
186
  case 'expired':
@@ -207,6 +212,13 @@ export default function PlatformSetupQR({
207
212
  startFlow();
208
213
  };
209
214
 
215
+ const handleComplete = (): void => {
216
+ if (phase === 'restarting') return;
217
+ setError('');
218
+ setPhase('restarting');
219
+ onComplete();
220
+ };
221
+
210
222
  const platformLabel = isFeishu ? '飞书 / Lark' : '微信 (ilink)';
211
223
  const scanHint = isFeishu ? '打开飞书 / Lark App 扫描二维码' : '打开微信扫描二维码';
212
224
 
@@ -259,38 +271,28 @@ export default function PlatformSetupQR({
259
271
  </>
260
272
  )}
261
273
 
262
- {phase === 'completed' && (
274
+ {(phase === 'completed' || phase === 'restarting') && (
263
275
  <div className="flex flex-col items-center gap-3 py-4">
264
- <CheckCircle2 size={48} className="text-green-500" />
276
+ {phase === 'restarting' ? (
277
+ <Loader2 size={48} className="animate-spin text-indigo-500" />
278
+ ) : (
279
+ <CheckCircle2 size={48} className="text-green-500" />
280
+ )}
265
281
  <p className="text-sm font-medium text-green-700 dark:text-green-400">平台绑定成功!</p>
266
- <p className="text-center text-xs text-gray-500">重启服务使新平台生效</p>
282
+ <p className="text-center text-xs text-gray-500">
283
+ {phase === 'restarting'
284
+ ? '正在重启服务并刷新平台长连接...'
285
+ : '下一步将统一重启服务并刷新平台长连接。'}
286
+ </p>
267
287
  <div className="flex gap-2">
268
- <Button
269
- variant="outline"
270
- onClick={async () => {
271
- try {
272
- await api.ccSettings.restart();
273
- setPhase('restarting');
274
- setTimeout(() => onComplete(), 3000);
275
- } catch (e: unknown) {
276
- setError(e instanceof Error ? e.message : String(e));
277
- }
278
- }}
279
- >
280
- <RotateCcw size={14} /> 立即重启
288
+ <Button onClick={handleComplete} disabled={phase === 'restarting'}>
289
+ {phase === 'restarting' && <Loader2 size={14} className="mr-1.5 animate-spin" />}
290
+ {phase === 'restarting' ? '正在重启...' : '重启并完成'}
281
291
  </Button>
282
- <Button onClick={onComplete}>稍后</Button>
283
292
  </div>
284
293
  </div>
285
294
  )}
286
295
 
287
- {phase === 'restarting' && (
288
- <div className="flex flex-col items-center gap-3 py-4">
289
- <Loader2 size={32} className="animate-spin text-indigo-500" />
290
- <p className="text-sm text-gray-600 dark:text-gray-400">正在重启服务...</p>
291
- </div>
292
- )}
293
-
294
296
  {phase === 'expired' && (
295
297
  <div className="flex flex-col items-center gap-3 py-4">
296
298
  <XCircle size={48} className="text-amber-500" />
@@ -321,7 +323,7 @@ export default function PlatformSetupQR({
321
323
  </div>
322
324
  )}
323
325
 
324
- {phase !== 'completed' && phase !== 'restarting' && (
326
+ {phase !== 'completed' && (
325
327
  <button
326
328
  onClick={onCancel}
327
329
  className="mt-2 text-xs text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"