@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,428 @@
1
+ /**
2
+ * Worker Society — 应用层自治引擎
3
+ *
4
+ * 把领域策略编排成可被 MCP 工具 / Fastify 路由 / 前端调用的 use case。
5
+ * 这是「worker 自治」替代「派单」的主路径:发布需求 → 自荐 → 选派 →
6
+ * 执行 → 交付 → 审核,全程无中心 dispatch,并持续积累声誉与关系。
7
+ *
8
+ * 依赖注入:所有副作用通过 ports,保证可单测。
9
+ */
10
+
11
+ import type {
12
+ PublishedNeed,
13
+ Relationship,
14
+ SocialEvent,
15
+ WorkerDiscoveryQuery,
16
+ WorkerProfile,
17
+ } from '../domain/models/society';
18
+ import { HUMAN_OPERATOR } from '../domain/models/society';
19
+ import {
20
+ applyReputationDelta,
21
+ autonomousVolunteers,
22
+ clampReputation,
23
+ computeFitScore,
24
+ discoverWorkers as discoverWorkersPolicy,
25
+ recordCollaboration,
26
+ reputationDeltaForOutcome,
27
+ requestRevision,
28
+ selectAssignee as selectAssigneePolicy,
29
+ transitionNeed,
30
+ volunteerFor,
31
+ } from '../domain/policies/societyPolicies';
32
+ import type { AutonomyOptions } from '../domain/policies/societyPolicies';
33
+ import type {
34
+ ClockPort,
35
+ MessageGateway,
36
+ NeedStore,
37
+ RelationshipStore,
38
+ SocialEventSink,
39
+ WorkerProfileStore,
40
+ } from './ports';
41
+
42
+ export interface RegisterProfileCommand {
43
+ workerId: string;
44
+ name: string;
45
+ kind?: 'composite' | 'atomic';
46
+ harness?: string;
47
+ capabilities?: WorkerProfile['capabilities'];
48
+ interests?: string[];
49
+ maxConcurrent?: number;
50
+ reputation?: number;
51
+ description?: string;
52
+ }
53
+
54
+ export interface PublishNeedCommand {
55
+ postedBy: string;
56
+ subject: string;
57
+ description?: string;
58
+ requiredCapabilities: string[];
59
+ priority?: number;
60
+ deadline?: string;
61
+ }
62
+
63
+ export interface Outcome {
64
+ ok: boolean;
65
+ reason?: string;
66
+ [k: string]: unknown;
67
+ }
68
+
69
+ export class WorkerSocietyService {
70
+ constructor(
71
+ private readonly profiles: WorkerProfileStore,
72
+ private readonly needs: NeedStore,
73
+ private readonly relationships: RelationshipStore,
74
+ private readonly messages: MessageGateway,
75
+ private readonly clock: ClockPort,
76
+ private readonly events?: SocialEventSink
77
+ ) {}
78
+
79
+ // ── 身份 / 发现 ──────────────────────────────────────────────────
80
+
81
+ /** 注册或更新一个 worker 社会档案。 */
82
+ async registerProfile(cmd: RegisterProfileCommand): Promise<WorkerProfile> {
83
+ const existing = await this.profiles.get(cmd.workerId);
84
+ const profile: WorkerProfile = {
85
+ workerId: cmd.workerId,
86
+ name: cmd.name,
87
+ kind: cmd.kind ?? 'composite',
88
+ harness: cmd.harness ?? existing?.harness,
89
+ capabilities: cmd.capabilities ?? existing?.capabilities ?? [],
90
+ interests: cmd.interests ?? existing?.interests ?? [],
91
+ // 夹取到 ≥1:maxConcurrent:0 会让 isAtCapacity(activeTaskCount>=maxConcurrent) 永真,
92
+ // worker 被自荐/选派闸门永久拒之门外(不可用由 status 建模,非 maxConcurrent:0)。
93
+ maxConcurrent: Math.max(1, cmd.maxConcurrent ?? existing?.maxConcurrent ?? 3),
94
+ activeTaskCount: existing?.activeTaskCount ?? 0,
95
+ // 输入边界即夹取到 [0,100]——与 applyReputationDelta 同一不变量,否则注册 150/-20 会持久化出界原值。
96
+ reputation: clampReputation(cmd.reputation ?? existing?.reputation ?? 50),
97
+ status: existing?.status ?? 'online',
98
+ description: cmd.description ?? existing?.description,
99
+ };
100
+ return this.profiles.upsert(profile);
101
+ }
102
+
103
+ async getProfile(workerId: string): Promise<WorkerProfile | undefined> {
104
+ return this.profiles.get(workerId);
105
+ }
106
+
107
+ /** 动态发现 worker(按能力过滤、声誉排序)。 */
108
+ async discoverWorkers(query: WorkerDiscoveryQuery = {}): Promise<WorkerProfile[]> {
109
+ const all = await this.profiles.list();
110
+ return discoverWorkersPolicy(all, query);
111
+ }
112
+
113
+ async getRelationships(): Promise<Relationship[]> {
114
+ return this.relationships.list();
115
+ }
116
+
117
+ // ── 广场生命周期 ────────────────────────────────────────────────
118
+
119
+ /** 发布一个需求到广场。 */
120
+ async publishNeed(cmd: PublishNeedCommand): Promise<{ need: PublishedNeed }> {
121
+ const now = this.clock.now();
122
+ const needId = `need-${randomId()}`;
123
+ const need: PublishedNeed = {
124
+ needId,
125
+ postedBy: cmd.postedBy,
126
+ subject: cmd.subject,
127
+ description: cmd.description,
128
+ requiredCapabilities: cmd.requiredCapabilities,
129
+ priority: cmd.priority ?? 5,
130
+ deadline: cmd.deadline,
131
+ status: 'open',
132
+ volunteers: [],
133
+ createdAt: now,
134
+ revisionCount: 0,
135
+ };
136
+ const saved = await this.needs.upsert(need);
137
+ this.emit({
138
+ type: 'need_published',
139
+ actors: [cmd.postedBy],
140
+ needId,
141
+ summary: `${cmd.postedBy} 发布需求:${cmd.subject}`,
142
+ });
143
+ return { need: saved };
144
+ }
145
+
146
+ /** worker 对需求自荐。 */
147
+ async volunteerFor(needId: string, workerId: string, note?: string): Promise<Outcome> {
148
+ const need = await this.needs.get(needId);
149
+ if (!need) return { ok: false, reason: 'need_not_found' };
150
+ const worker = await this.profiles.get(workerId);
151
+ if (!worker) return { ok: false, reason: 'worker_not_found' };
152
+
153
+ const rels = await this.relationships.list();
154
+ const outcome = volunteerFor(need, worker, this.clock.now(), rels);
155
+ if (!outcome.ok) return { ok: false, reason: outcome.reason };
156
+
157
+ await this.needs.upsert(outcome.need);
158
+ this.emit({
159
+ type: 'volunteered',
160
+ actors: [workerId, need.postedBy],
161
+ needId,
162
+ summary: `${worker.name} 自荐了「${need.subject}」(适配度 ${(outcome.volunteer!.fitScore * 100).toFixed(0)}%)`,
163
+ });
164
+ await this.messages
165
+ .send({
166
+ fromWorker: workerId,
167
+ toWorker: need.postedBy,
168
+ text: note
169
+ ? `${worker.name} 自荐了你的需求「${need.subject}」。备注:${note}`
170
+ : `${worker.name} 自荐了你的需求「${need.subject}」。`,
171
+ needId,
172
+ })
173
+ .catch(() => undefined);
174
+ return { ok: true, fitScore: outcome.volunteer!.fitScore };
175
+ }
176
+
177
+ /** 为需求选择最优自荐者并进入 assigned。 */
178
+ async selectAssignee(needId: string): Promise<Outcome> {
179
+ const need = await this.needs.get(needId);
180
+ if (!need) return { ok: false, reason: 'need_not_found' };
181
+ const all = await this.profiles.list();
182
+ const byId = new Map(all.map((w) => [w.workerId, w]));
183
+ const rels = await this.relationships.list();
184
+ const chosen = selectAssigneePolicy(need, byId, rels);
185
+ if (!chosen) return { ok: false, reason: 'no_eligible_volunteer' };
186
+
187
+ const t = transitionNeed(need, 'assigned', this.clock.now(), { assignee: chosen.workerId });
188
+ if (!t.ok) return { ok: false, reason: t.reason };
189
+ const saved = await this.needs.upsert(t.need);
190
+ // 自荐者被选中后,占用一个并发槽。
191
+ const w = byId.get(chosen.workerId);
192
+ if (w) await this.profiles.upsert({ ...w, activeTaskCount: w.activeTaskCount + 1 });
193
+ this.emit({
194
+ type: 'assigned',
195
+ actors: [chosen.workerId, saved.postedBy],
196
+ needId,
197
+ summary: `${chosen.workerId} 被选派执行「${saved.subject}」`,
198
+ });
199
+ await this.messages
200
+ .send({
201
+ fromWorker: saved.postedBy,
202
+ toWorker: chosen.workerId,
203
+ text: `你被选派执行需求「${saved.subject}」。完成后请调用 deliver_need 交付。`,
204
+ needId,
205
+ })
206
+ .catch(() => undefined);
207
+ return { ok: true, assignee: chosen.workerId };
208
+ }
209
+
210
+ /** 执行者开始执行。 */
211
+ async startNeed(needId: string, byWorker: string): Promise<Outcome> {
212
+ const need = await this.needs.get(needId);
213
+ if (!need) return { ok: false, reason: 'need_not_found' };
214
+ if (need.assignee !== byWorker) return { ok: false, reason: 'not_assignee' };
215
+ const t = transitionNeed(need, 'in_progress', this.clock.now());
216
+ if (!t.ok) return { ok: false, reason: t.reason };
217
+ await this.needs.upsert(t.need);
218
+ this.emit({
219
+ type: 'collaboration_started',
220
+ actors: [byWorker],
221
+ needId,
222
+ summary: `${byWorker} 开始执行「${need.subject}」`,
223
+ });
224
+ return { ok: true };
225
+ }
226
+
227
+ /** 执行者交付结果。 */
228
+ async deliverNeed(needId: string, result: string): Promise<Outcome> {
229
+ const need = await this.needs.get(needId);
230
+ if (!need) return { ok: false, reason: 'need_not_found' };
231
+ const t = transitionNeed(need, 'delivered', this.clock.now(), { result });
232
+ if (!t.ok) return { ok: false, reason: t.reason };
233
+ await this.needs.upsert(t.need);
234
+ this.emit({
235
+ type: 'delivered',
236
+ actors: [need.assignee ?? '?', need.postedBy],
237
+ needId,
238
+ summary: `${need.assignee} 交付了「${need.subject}」`,
239
+ });
240
+ return { ok: true };
241
+ }
242
+
243
+ /** 审核通过 → 关闭,并奖励声誉 + 强化关系。 */
244
+ async acceptDelivery(needId: string): Promise<Outcome> {
245
+ const need = await this.needs.get(needId);
246
+ if (!need) return { ok: false, reason: 'need_not_found' };
247
+ const t = transitionNeed(need, 'closed', this.clock.now());
248
+ if (!t.ok) return { ok: false, reason: t.reason };
249
+ await this.needs.upsert(t.need);
250
+
251
+ if (need.assignee) await this.reward(need.assignee, need.postedBy, true, needId);
252
+ // 释放并发槽。
253
+ const w = await this.profiles.get(need.assignee ?? '');
254
+ if (w)
255
+ await this.profiles.upsert({ ...w, activeTaskCount: Math.max(0, w.activeTaskCount - 1) });
256
+
257
+ this.emit({
258
+ type: 'closed',
259
+ actors: [need.postedBy, need.assignee ?? '?'],
260
+ needId,
261
+ summary: `「${need.subject}」审核通过,协作完成`,
262
+ });
263
+ return { ok: true };
264
+ }
265
+
266
+ /** 审核退回 → 重做;记录一次未成功协作,声誉小幅下降。 */
267
+ async requestRevision(needId: string): Promise<Outcome> {
268
+ const need = await this.needs.get(needId);
269
+ if (!need) return { ok: false, reason: 'need_not_found' };
270
+ const t = requestRevision(need, this.clock.now());
271
+ if (!t.ok) return { ok: false, reason: t.reason };
272
+ await this.needs.upsert(t.need);
273
+ if (need.assignee) await this.reward(need.assignee, need.postedBy, false, needId);
274
+ this.emit({
275
+ type: 'delivered',
276
+ actors: [need.postedBy, need.assignee ?? '?'],
277
+ needId,
278
+ summary: `「${need.subject}」被退回重做(第 ${t.need.revisionCount} 次)`,
279
+ });
280
+ return { ok: true, escalated: t.reason === 'revision_limit_exceeded' };
281
+ }
282
+
283
+ async cancelNeed(needId: string): Promise<Outcome> {
284
+ const need = await this.needs.get(needId);
285
+ if (!need) return { ok: false, reason: 'need_not_found' };
286
+ const t = transitionNeed(need, 'cancelled', this.clock.now());
287
+ if (!t.ok) return { ok: false, reason: t.reason };
288
+ await this.needs.upsert(t.need);
289
+ // 释放执行者并发槽:assigned→cancelled 是合法转换,selectAssignee 已占用一槽,
290
+ // 不释放则 activeTaskCount 永久虚高,最终 isAtCapacity 误判、worker 接不了新活。
291
+ // open→cancelled 无 assignee,get('') 返回 undefined 自然跳过。
292
+ const w = await this.profiles.get(need.assignee ?? '');
293
+ if (w)
294
+ await this.profiles.upsert({ ...w, activeTaskCount: Math.max(0, w.activeTaskCount - 1) });
295
+ return { ok: true };
296
+ }
297
+
298
+ /** 扫描过期未分配的需求,标记 expired。返回处理数量。 */
299
+ async expireNeeds(): Promise<number> {
300
+ const now = this.clock.now();
301
+ const nowMs = Date.parse(now);
302
+ const open = await this.needs.listOpen();
303
+ let n = 0;
304
+ for (const need of open) {
305
+ if (need.deadline && Date.parse(need.deadline) < nowMs) {
306
+ const t = transitionNeed(need, 'expired', now);
307
+ if (t.ok) {
308
+ await this.needs.upsert(t.need);
309
+ n += 1;
310
+ }
311
+ }
312
+ }
313
+ return n;
314
+ }
315
+
316
+ /**
317
+ * 自治驱动一轮:扫描广场上所有 open 需求,让匹配的 worker 主动自荐。
318
+ * 返回本轮实际产生的自荐次数。这是「worker 自治」替代「派单」的运行时入口——
319
+ * 可由定时器、MCP 工具或前端按钮触发,全程无中心调度。
320
+ *
321
+ * 决策由纯策略 autonomousVolunteers 给出;此处只负责拉取快照、落库自荐、计数。
322
+ * 每个决策都通过 volunteerFor 走标准路径,复用其校验与事件/消息副作用。
323
+ */
324
+ async runAutonomyTick(opts: AutonomyOptions = {}): Promise<number> {
325
+ const [openNeeds, workers, relationships] = await Promise.all([
326
+ this.needs.listOpen(),
327
+ this.profiles.list(),
328
+ this.relationships.list(),
329
+ ]);
330
+ const decisions = autonomousVolunteers(openNeeds, workers, relationships, opts);
331
+ let applied = 0;
332
+ for (const d of decisions) {
333
+ const r = await this.volunteerFor(d.needId, d.workerId);
334
+ if (r.ok) applied += 1;
335
+ }
336
+ return applied;
337
+ }
338
+
339
+ /**
340
+ * 自治选派(去中心化):扫描所有「仍有自荐者、尚未选派」的 open 需求,
341
+ * 逐一按适配度选出最优自荐者并进入 assigned。返回本轮选派次数。
342
+ *
343
+ * 与 runAutonomyTick 配合构成完整自治回路:先让 worker 自发投标(volunteer),
344
+ * 待竞争充分后再由适配度择优(select)——全程无中心 dispatcher 人工指派。
345
+ * 复用 selectAssignee 的标准路径(占用并发槽、发事件、发消息)。
346
+ */
347
+ async autoSelectPending(): Promise<number> {
348
+ const open = await this.needs.listOpen();
349
+ let selected = 0;
350
+ for (const need of open) {
351
+ if (need.volunteers.length === 0) continue;
352
+ const r = await this.selectAssignee(need.needId);
353
+ if (r.ok) selected += 1;
354
+ }
355
+ return selected;
356
+ }
357
+
358
+ // ── 社交消息 ────────────────────────────────────────────────────
359
+
360
+ /** worker 自由发送一条社交消息(非任务交付);仅投递消息 + 发事件,不变更声誉/关系。 */
361
+ async sendSocialMessage(fromWorker: string, toWorker: string, text: string): Promise<Outcome> {
362
+ const from = await this.profiles.get(fromWorker);
363
+ // HUMAN_OPERATOR('user')不是注册 worker,但作为人类操作者必须允许发送——
364
+ // 否则图谱 overlay 的「发消息」(from='user')会被静默丢弃。
365
+ if (!from && fromWorker !== HUMAN_OPERATOR) return { ok: false, reason: 'worker_not_found' };
366
+ const res = await this.messages.send({ fromWorker, toWorker, text });
367
+ this.emit({
368
+ type: 'message',
369
+ actors: [fromWorker, toWorker],
370
+ summary: `${from?.name ?? fromWorker} → ${toWorker}:${text.slice(0, 60)}`,
371
+ });
372
+ return { ok: res.delivered };
373
+ }
374
+
375
+ // ── helpers ────────────────────────────────────────────────────
376
+
377
+ /** 应用声誉增量 + 双向记录协作关系。 */
378
+ private async reward(
379
+ workerId: string,
380
+ partner: string,
381
+ success: boolean,
382
+ needId: string
383
+ ): Promise<void> {
384
+ const w = await this.profiles.get(workerId);
385
+ if (w) {
386
+ const delta = reputationDeltaForOutcome(success);
387
+ await this.profiles.upsert(applyReputationDelta(w, delta));
388
+ }
389
+ const rels = await this.relationships.list();
390
+ const now = this.clock.now();
391
+ const next = recordCollaboration(
392
+ recordCollaboration(rels, workerId, partner, success, now),
393
+ partner,
394
+ workerId,
395
+ success,
396
+ now
397
+ );
398
+ await this.relationships.bulkSet(next);
399
+ if (success) {
400
+ this.emit({
401
+ type: 'relationship_strengthened',
402
+ actors: [workerId, partner],
403
+ needId,
404
+ summary: `${workerId} 与 ${partner} 信任度上升`,
405
+ });
406
+ }
407
+ }
408
+
409
+ private emit(e: Omit<SocialEvent, 'eventId' | 'timestamp'>): void {
410
+ this.events?.append({ ...e, eventId: `evt-${randomId()}`, timestamp: this.clock.now() });
411
+ }
412
+ }
413
+
414
+ function randomId(): string {
415
+ // 应用层(非 workflow 脚本)可使用 crypto.randomUUID;降级到时间+计数。
416
+ const g = globalThis as { crypto?: { randomUUID?: () => string } };
417
+ if (g.crypto?.randomUUID) return g.crypto.randomUUID();
418
+ return `${Date.now().toString(36)}-${Math.floor(Math.random() * 1e9).toString(36)}`;
419
+ }
420
+
421
+ /** 为外部调用方暴露 computeFitScore 的便捷包装(如前端预估)。 */
422
+ export function estimateFit(
423
+ need: PublishedNeed,
424
+ worker: WorkerProfile,
425
+ relationships: Relationship[] = []
426
+ ): number {
427
+ return computeFitScore(need, worker, relationships).score;
428
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Worker Society — 应用层测试用 Fake 实现(仿 teams-mvp/TaskDispatchService.test.ts)
3
+ *
4
+ * 供 application use case / adapter mapping / renderer utility 测试复用。
5
+ * 不含业务规则,只是 Map/数组的薄封装。
6
+ */
7
+
8
+ import type {
9
+ PublishedNeed,
10
+ Relationship,
11
+ SocialEvent,
12
+ WorkerProfile,
13
+ } from '../domain/models/society';
14
+ import type {
15
+ ClockPort,
16
+ MessageGateway,
17
+ NeedStore,
18
+ RelationshipStore,
19
+ SocialEventSink,
20
+ SocialMessageOut,
21
+ WorkerProfileStore,
22
+ } from './ports';
23
+ import { ACTIVE_NEED_STATUSES } from '../domain/policies/societyPolicies';
24
+
25
+ export class FakeClock implements ClockPort {
26
+ constructor(private t: string) {}
27
+ now(): string {
28
+ return this.t;
29
+ }
30
+ set(iso: string): void {
31
+ this.t = iso;
32
+ }
33
+ }
34
+
35
+ export class FakeProfileStore implements WorkerProfileStore {
36
+ private map = new Map<string, WorkerProfile>();
37
+ async get(workerId: string): Promise<WorkerProfile | undefined> {
38
+ return this.map.get(workerId);
39
+ }
40
+ async list(): Promise<WorkerProfile[]> {
41
+ return [...this.map.values()];
42
+ }
43
+ async upsert(profile: WorkerProfile): Promise<WorkerProfile> {
44
+ this.map.set(profile.workerId, profile);
45
+ return profile;
46
+ }
47
+ async delete(workerId: string): Promise<void> {
48
+ this.map.delete(workerId);
49
+ }
50
+ }
51
+
52
+ export class FakeNeedStore implements NeedStore {
53
+ private map = new Map<string, PublishedNeed>();
54
+ async get(needId: string): Promise<PublishedNeed | undefined> {
55
+ return this.map.get(needId);
56
+ }
57
+ async list(): Promise<PublishedNeed[]> {
58
+ return [...this.map.values()];
59
+ }
60
+ async listOpen(): Promise<PublishedNeed[]> {
61
+ return [...this.map.values()].filter((n) => n.status === 'open');
62
+ }
63
+ async listActive(): Promise<PublishedNeed[]> {
64
+ return [...this.map.values()].filter((n) => ACTIVE_NEED_STATUSES.includes(n.status));
65
+ }
66
+ async upsert(need: PublishedNeed): Promise<PublishedNeed> {
67
+ this.map.set(need.needId, need);
68
+ return need;
69
+ }
70
+ }
71
+
72
+ export class FakeRelationshipStore implements RelationshipStore {
73
+ private rels: Relationship[] = [];
74
+ async list(): Promise<Relationship[]> {
75
+ return [...this.rels];
76
+ }
77
+ async bulkSet(relationships: Relationship[]): Promise<void> {
78
+ this.rels = [...relationships];
79
+ }
80
+ }
81
+
82
+ export class FakeMessageGateway implements MessageGateway {
83
+ sent: SocialMessageOut[] = [];
84
+ async send(msg: SocialMessageOut): Promise<{ delivered: boolean }> {
85
+ this.sent.push(msg);
86
+ return { delivered: true };
87
+ }
88
+ }
89
+
90
+ export class MemoryEventSink implements SocialEventSink {
91
+ private events: SocialEvent[] = [];
92
+ append(event: SocialEvent): void {
93
+ this.events.push(event);
94
+ }
95
+ all(): SocialEvent[] {
96
+ return [...this.events];
97
+ }
98
+ recent(limit: number): SocialEvent[] {
99
+ return this.events.slice(-limit);
100
+ }
101
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Worker Society — 应用层 ports(被 main/infrastructure 实现)
3
+ *
4
+ * core/application 只依赖这些抽象端口,不触碰 FS/Redis/Fastify/cc-connect。
5
+ * 这样 worker 自治引擎可被纯单测驱动(Fake 实现)。
6
+ */
7
+
8
+ import type {
9
+ PublishedNeed,
10
+ Relationship,
11
+ SocialEvent,
12
+ WorkerProfile,
13
+ } from '../domain/models/society';
14
+
15
+ /** 时钟端口,保证应用层可注入确定性时间。 */
16
+ export interface ClockPort {
17
+ now(): string;
18
+ }
19
+
20
+ /** Worker 社会档案存储。 */
21
+ export interface WorkerProfileStore {
22
+ get(workerId: string): Promise<WorkerProfile | undefined>;
23
+ list(): Promise<WorkerProfile[]>;
24
+ upsert(profile: WorkerProfile): Promise<WorkerProfile>;
25
+ delete?(workerId: string): Promise<void>;
26
+ }
27
+
28
+ /** 广场(Agora)需求存储。 */
29
+ export interface NeedStore {
30
+ get(needId: string): Promise<PublishedNeed | undefined>;
31
+ list(): Promise<PublishedNeed[]>;
32
+ listOpen(): Promise<PublishedNeed[]>;
33
+ /** 仍在交互生命周期内(open/assigned/in_progress/delivered,未终结)的需求。 */
34
+ listActive(): Promise<PublishedNeed[]>;
35
+ upsert(need: PublishedNeed): Promise<PublishedNeed>;
36
+ }
37
+
38
+ /** worker 间关系图存储。 */
39
+ export interface RelationshipStore {
40
+ list(): Promise<Relationship[]>;
41
+ bulkSet(relationships: Relationship[]): Promise<void>;
42
+ }
43
+
44
+ /** 出站社交消息(worker↔worker 或 worker→user)。由 cc-connect Bridge / inbox 实现。 */
45
+ export interface SocialMessageOut {
46
+ fromWorker: string;
47
+ toWorker: string;
48
+ text: string;
49
+ needId?: string;
50
+ }
51
+
52
+ export interface MessageGateway {
53
+ send(msg: SocialMessageOut): Promise<{ delivered: boolean }>;
54
+ }
55
+
56
+ /** 社会活动流 sink —— 用于前端实时渲染社会视图。 */
57
+ export interface SocialEventSink {
58
+ append(event: SocialEvent): void;
59
+ recent?(limit: number): SocialEvent[];
60
+ }
61
+
62
+ /** 聚合依赖,构造 WorkerSocietyService 时注入。 */
63
+ export interface WorkerSocietyDeps {
64
+ profiles: WorkerProfileStore;
65
+ needs: NeedStore;
66
+ relationships: RelationshipStore;
67
+ messages: MessageGateway;
68
+ clock: ClockPort;
69
+ events?: SocialEventSink;
70
+ }