agentworkshop 0.7.40 → 0.7.44

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 (327) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/B8uy9iRW.js +1 -0
  3. package/.output/public/_nuxt/BGTYYQH-.js +1 -0
  4. package/.output/public/_nuxt/BUmHEJ77.js +2 -0
  5. package/.output/public/_nuxt/BY7YrV_D.js +1 -0
  6. package/.output/public/_nuxt/Bqcgz95s.js +18 -0
  7. package/.output/public/_nuxt/C7UlqPeD.js +1 -0
  8. package/.output/public/_nuxt/CTmDn-YP.js +1 -0
  9. package/.output/public/_nuxt/Cs8pVeVG.js +1 -0
  10. package/.output/public/_nuxt/{DcsCcxp4.js → D98NH8kG.js} +1 -1
  11. package/.output/public/_nuxt/DKySmNPI.js +14 -0
  12. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  13. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  14. package/.output/public/_nuxt/{C_iYD-EB.js → EHlEMRii.js} +1 -1
  15. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  16. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  17. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  18. package/.output/public/_nuxt/{DZshyNLa.js → IREZ1eC2.js} +1 -1
  19. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  20. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  21. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  22. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  23. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  24. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  25. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  26. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  27. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  28. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  29. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  30. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  31. package/.output/public/_nuxt/builds/latest.json +1 -1
  32. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  33. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  34. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  35. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  36. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  37. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  38. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  39. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  40. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  41. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  42. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  43. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  44. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  45. package/.output/server/chunks/_/nitro.mjs +1058 -830
  46. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  47. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  48. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  49. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs → TownView-CJ6IsDCc.mjs} +229 -228
  50. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  51. package/.output/server/chunks/build/{_id_-BU1wfOID.mjs → _id_-CVD_H0ir.mjs} +149 -147
  52. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  53. package/.output/server/chunks/build/{_id_-BYsEua57.mjs → _id_-CtxMb3qp.mjs} +47 -46
  54. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  55. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs → _wsId_-DpY3T-md.mjs} +516 -446
  56. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  58. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  60. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  61. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  62. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  63. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  64. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  65. package/.output/server/chunks/build/{daq-cgyjKmJu.mjs → daq-DWWSKGAV.mjs} +95 -93
  66. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  67. package/.output/server/chunks/build/{dcw-CoTxBlAZ.mjs → dcw-CT8k17_E.mjs} +46 -45
  68. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  69. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  70. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs → logs--dByNyhw.mjs} +2 -2
  72. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  74. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{pages-DFxjn9Xa.mjs → pages-BHcSBM2D.mjs} +26 -20
  76. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  77. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  78. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  79. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  80. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  81. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  82. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  83. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  84. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  85. package/.output/server/chunks/build/{town-qMPql9Se.mjs → town-QJWB5wng.mjs} +5 -4
  86. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  87. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  88. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  89. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  90. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  91. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  92. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  93. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  108. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  109. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +3 -1
  110. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  111. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  116. package/.output/server/chunks/routes/renderer.mjs +2 -2
  117. package/.output/server/chunks/virtual/entry.mjs +639 -88
  118. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  119. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  120. package/.output/server/package.json +1 -1
  121. package/README-zh.md +16 -6
  122. package/README.md +17 -7
  123. package/app/components/AppHeader.vue +961 -959
  124. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  125. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  126. package/app/components/workshop/AgentLanesView.vue +998 -998
  127. package/app/components/workshop/ArtifactCard.vue +120 -120
  128. package/app/components/workshop/AssetLibrary.vue +452 -452
  129. package/app/components/workshop/ChannelSessionList.vue +812 -804
  130. package/app/components/workshop/CommandPalette.vue +269 -269
  131. package/app/components/workshop/Composer.vue +827 -827
  132. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  133. package/app/components/workshop/EventBlock.vue +602 -602
  134. package/app/components/workshop/FileSelectorModal.vue +188 -188
  135. package/app/components/workshop/InspectorPanel.vue +301 -301
  136. package/app/components/workshop/MemoryPanel.vue +364 -364
  137. package/app/components/workshop/MultiChannelView.vue +189 -189
  138. package/app/components/workshop/TaskBoardView.vue +686 -686
  139. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  140. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  141. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  142. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  143. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  144. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  145. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  146. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  147. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  148. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  149. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  150. package/app/components/workshop/town/TownView.vue +56 -56
  151. package/app/composables/workshop/useDaqStream.ts +7 -4
  152. package/app/composables/workshop/useDcwStream.ts +8 -2
  153. package/app/middleware/locale-cookie.global.ts +22 -0
  154. package/app/pages/aml/index.vue +24 -2
  155. package/app/pages/daq/[id].vue +20 -16
  156. package/app/pages/daq/index.vue +2310 -2307
  157. package/app/pages/dcw/[id].vue +26 -23
  158. package/app/pages/dcw/index.vue +3 -3
  159. package/app/pages/index.vue +987 -981
  160. package/app/pages/plugins/index.vue +317 -311
  161. package/app/pages/settings.vue +1564 -1562
  162. package/app/pages/tokens.vue +15 -15
  163. package/app/pages/workshop/agents.vue +612 -609
  164. package/app/pages/workshop/channel-templates.vue +18 -11
  165. package/app/pages/workshop/index.vue +668 -668
  166. package/app/pages/workshop/teams.vue +743 -740
  167. package/app/pages/workshop/w/[wsId].vue +704 -704
  168. package/app/plugins/locale-restore.client.ts +16 -1
  169. package/app/utils/builtin-catalog.ts +104 -0
  170. package/config.yml +170 -170
  171. package/docs/cli.en.md +2 -2
  172. package/docs/cli.md +2 -2
  173. package/docs/full-test-plan.md +2 -3
  174. package/docs/plugins.en.md +33 -1
  175. package/docs/plugins.md +29 -1
  176. package/docs/sdk.en.md +1 -1
  177. package/docs/sdk.md +1 -1
  178. package/i18n/locales/en.ts +293 -35
  179. package/i18n/locales/zh-CN.ts +265 -7
  180. package/package.json +4 -3
  181. package/scripts/_dbg-perms-e2e.mjs +132 -109
  182. package/scripts/_demo-agentteam-capture.mjs +278 -0
  183. package/scripts/_e2e-ui-functional.mjs +371 -0
  184. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  185. package/scripts/_i18n-en-verify.mjs +107 -0
  186. package/scripts/_i18n-extra-checks.mjs +53 -0
  187. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  188. package/scripts/_i18n-verify-keys.mjs +50 -0
  189. package/scripts/_loop-biax-campaign.mjs +130 -0
  190. package/scripts/_sweep-button-contrast.mjs +87 -0
  191. package/scripts/test-serial-bridge.mjs +418 -0
  192. package/scripts/ui/e2e-interactive.mjs +328 -0
  193. package/scripts/ui/record-demo.mjs +557 -0
  194. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  195. package/server/api/workshop/daq/index.get.ts +3 -1
  196. package/server/api/workshop/dcw/index.get.ts +3 -0
  197. package/server/plugins/aw-plugins.ts +9 -7
  198. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  199. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  200. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  201. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  202. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  203. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  204. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  205. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  206. package/server/services/workshop/daq/daq-controller.ts +7 -2
  207. package/server/services/workshop/daq/drivers.ts +89 -3
  208. package/server/services/workshop/dcw/dcw-controller.ts +5 -1
  209. package/server/services/workshop/dcw/drivers.ts +85 -2
  210. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  211. package/server/services/workshop/plugins/host.mjs +30 -0
  212. package/shared/daq-protocol.ts +15 -0
  213. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  214. package/.output/public/_nuxt/BOt2SP4z.js +0 -1
  215. package/.output/public/_nuxt/BP-NyKVG.js +0 -18
  216. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  217. package/.output/public/_nuxt/BsROmY89.js +0 -1
  218. package/.output/public/_nuxt/ClILjvWH.js +0 -1
  219. package/.output/public/_nuxt/CzOCSGLe.js +0 -1
  220. package/.output/public/_nuxt/D8qvkfyY.js +0 -1
  221. package/.output/public/_nuxt/DCn7QZ5N.js +0 -2
  222. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  223. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  224. package/.output/public/_nuxt/Dihnimlk.js +0 -19
  225. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  226. package/.output/public/_nuxt/Dr9v6C0f.js +0 -14
  227. package/.output/public/_nuxt/Du9ZJtnj.js +0 -1
  228. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  229. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  230. package/.output/public/_nuxt/_id_.CM4bIgKY.css +0 -1
  231. package/.output/public/_nuxt/_id_.bNV69Dtf.css +0 -1
  232. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  233. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  234. package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +0 -1
  235. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  236. package/.output/public/_nuxt/daq.B0D3dPAc.css +0 -1
  237. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  238. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  239. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  240. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  241. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  242. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  243. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  244. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  245. package/.output/server/chunks/build/_id_-BU1wfOID.mjs.map +0 -1
  246. package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +0 -1
  247. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  248. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  249. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  250. package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +0 -1
  251. package/.output/server/chunks/build/dcw-CoTxBlAZ.mjs.map +0 -1
  252. package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +0 -1
  253. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  254. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  255. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  256. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  257. package/.output/server/chunks/build/town-qMPql9Se.mjs.map +0 -1
  258. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  259. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  260. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  261. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  262. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  263. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  264. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  265. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  266. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  267. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  268. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  269. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  270. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  271. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  272. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  273. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  274. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  275. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  276. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  277. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  278. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  279. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  280. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  281. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  282. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  283. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  284. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  285. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  286. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  287. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  288. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  289. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  290. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  291. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  292. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  293. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  294. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  295. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  296. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  297. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  298. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  299. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  300. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  301. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  302. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  303. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  304. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  305. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  306. package/scripts/_dbg-minimal-omp.mjs +0 -77
  307. package/scripts/_dbg-mode-nav.mjs +0 -173
  308. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  309. package/scripts/_dbg-team-repro.mjs +0 -76
  310. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  311. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  312. package/scripts/_townview_style.css +0 -1185
  313. package/scripts/_townview_template.html +0 -1215
  314. package/server/data/agent-node-bindings.json +0 -554
  315. package/server/data/daq-templates.json +0 -16
  316. package/server/data/daqs.json +0 -7464
  317. package/server/data/dcw-lines.json +0 -1787
  318. package/server/data/dcw-products.json +0 -1626
  319. package/server/data/dcw-recipes.json +0 -4672
  320. package/server/data/dcw-rollback.json +0 -20754
  321. package/server/data/dcw-runs.json +0 -6354
  322. package/server/data/dcw-templates.json +0 -146
  323. package/server/data/dcw-writes.json +0 -15650
  324. package/server/data/dcws.json +0 -9033
  325. package/server/data/device-twins.json +0 -133
  326. package/server/data/line-runs.json +0 -322
  327. package/server/data/scene-layouts.json +0 -277
@@ -1,99 +0,0 @@
1
- /**
2
- * 审计实验 5 —— 端到端:真实 DcwController + mock 驱动,验证
3
- * ① 正常写:硬件写入 + 账本锚 + 写历史(正对照)
4
- * ② PATCH decimals=101(无校验)→ 后续写「已落硬件但记账抛错」→ 无账本锚/无写历史/500
5
- * ③ 不存在节点 id 的语义(服务层 404)
6
- *
7
- * cwd 已切到 scripts/_audit/.tmp:所有仓库文件写到临时目录,绝不碰 server/data/*。
8
- * 运行:node --experimental-transform-types scripts/_audit/run.mjs scripts/_audit/dcw-controller-e2e.ts
9
- */
10
- import { mkdirSync, rmSync } from 'node:fs'
11
-
12
- // 清空本次实验的隔离数据目录(run.mjs 已把 AW_DATA_DIR 指向 scripts/_audit/.tmp/audit-data;
13
- // 同目录其它实验残留的 20000 锚账本会污染断言,故先清空)
14
- const ISOLATED = new URL('./.tmp/audit-data/', import.meta.url)
15
- rmSync(ISOLATED, { recursive: true, force: true })
16
- mkdirSync(ISOLATED, { recursive: true })
17
- // 清空上次实验留下的临时库(benchmark 会写出 10MB+ 的 dcw-rollback.json)
18
- rmSync(new URL('./.tmp/server/', import.meta.url), { recursive: true, force: true })
19
- mkdirSync(new URL('./.tmp/server/data/', import.meta.url), { recursive: true })
20
- process.chdir(new URL('./.tmp/', import.meta.url).pathname.replace(/^\//, ''))
21
-
22
- const { getDcwController } = await import('../../server/services/workshop/dcw/dcw-controller')
23
- const { getRecipeRollBackRepo } = await import('../../server/services/workshop/dcw/recipe-rollback.repo')
24
- const { getDcwRecipeRepo } = await import('../../server/services/workshop/dcw/dcw-recipe.repo')
25
-
26
- let failures = 0
27
- function check(name: string, cond: boolean, extra = ''): void {
28
- if (cond) {
29
- console.log(` PASS ${name}${extra ? ` (${extra})` : ''}`)
30
- }
31
- else {
32
- failures++
33
- console.log(` FAIL ${name}${extra ? ` (${extra})` : ''}`)
34
- }
35
- }
36
-
37
- const mockPlc = (globalThis as { __dcwMockPlc?: Map<string, number> }).__dcwMockPlc!
38
- const plcValue = (): number | undefined => mockPlc.get('default')
39
-
40
- const ctrl = getDcwController()
41
- const ledger = getRecipeRollBackRepo()
42
- const writes = getDcwRecipeRepo()
43
-
44
- const node = ctrl.create({ templateRef: 'temp-sp', driver: 'mock', min: 150, max: 200, decimals: 1, enabled: true })
45
- console.log(` 节点 ${node.id} 创建(mock 驱动,min150 max200 decimals1)`)
46
-
47
- console.log('\n=== ① 正对照:正常写 ===')
48
- {
49
- const anchorsBefore = ledger.stats().anchors
50
- const out = await ctrl.write(node.id, 160, null, { source: 'manual', actor: 'audit' })
51
- check('写入返回 ok', out.ok === true, out.message)
52
- check('mock PLC 记录写入值 160(硬件已写)', plcValue() === 160, `plc=${plcValue()}`)
53
- check('账本新增 1 条锚', ledger.stats().anchors === anchorsBefore + 1, `anchors=${ledger.stats().anchors}`)
54
- check('写历史新增 1 条', writes.historyList(5).length === 1, `n=${writes.historyList(5).length}`)
55
- check('节点 value=160', node.value === 160, `value=${node.value}`)
56
- }
57
-
58
- console.log('\n=== ② PATCH decimals=101(接口无任何范围校验)→ 再写 ===')
59
- {
60
- const patched = ctrl.patch(node.id, { decimals: 101 })
61
- check('PATCH decimals=101 被接受(无校验)', patched.decimals === 101, `decimals=${patched.decimals}`)
62
-
63
- const anchorsBefore = ledger.stats().anchors
64
- const historyBefore = writes.historyList(50).length
65
- let err: unknown
66
- try {
67
- await ctrl.write(node.id, 170, null, { source: 'manual', actor: 'audit' })
68
- }
69
- catch (e) {
70
- err = e
71
- }
72
- console.log(` 写 170 抛错: ${(err as Error)?.name}: ${(err as Error)?.message}`)
73
- check('写入抛出异常(调用方得到 500 而非 ACK)', err != null, String((err as Error)?.name))
74
- check('异常来自 toFixed 的 RangeError 语义', /toFixed|digits|RangeError/i.test(`${(err as Error)?.name} ${(err as Error)?.message}`), `${(err as Error)?.name}`)
75
- check('mock PLC 已记录 170(硬件写入已发生)', plcValue() === 170, `plc=${plcValue()}`)
76
- check('账本未新增锚(这次硬件变更无法回退)', ledger.stats().anchors === anchorsBefore, `anchors=${ledger.stats().anchors}`)
77
- check('写历史未新增条目(审计缺失)', writes.historyList(50).length === historyBefore, `n=${writes.historyList(50).length}`)
78
- check('节点 state=error 且 value 仍是旧值 160', node.state === 'error' && node.value === 160, `state=${node.state} value=${node.value}`)
79
-
80
- const stable = ledger.lastStableAnchor(node.id)
81
- console.log(` 账本最新稳定锚={prev:${stable?.prevValue}, new:${stable?.newValue}};硬件实际=${plcValue()};节点显示=${node.value}`)
82
- check('硬件(170)≠ 账本(160):账本与硬件已漂移', plcValue() !== stable?.newValue)
83
- }
84
-
85
- console.log('\n=== ③ 不存在节点 id 的服务层语义 ===')
86
- {
87
- let e404: unknown
88
- try {
89
- await ctrl.write('dw-nonexistent', 160, null, { source: 'manual', actor: 'audit' })
90
- }
91
- catch (e) {
92
- e404 = e
93
- }
94
- const status = (e404 as { status?: number })?.status
95
- check('不存在节点 → AppError 404(控制器层)', status === 404, `status=${status}`)
96
- }
97
-
98
- console.log(`\nresult: ${failures === 0 ? 'ALL PASS' : `${failures} FAILED`}`)
99
- process.exit(failures === 0 ? 0 : 1)
@@ -1,325 +0,0 @@
1
- /**
2
- * 双 Channel 隔离端到端(真实 omp harness):
3
- * 两个 channel 各自独立 workspace,并行验证:
4
- * S1 任务下发 + workspace 隔离:两 channel 同时下发"读 shared.txt 汇报内容"任务,
5
- * A 的 worker 只能看到 marker-A,B 只能看到 marker-B(cwd 隔离经真实 omp 子进程验证)
6
- * S2 点对点实时通信:A 内 lead↔worker / worker↔worker 触发对话;B 内 worker→lead 触发对话
7
- * (真实 LLM 回执,in_reply_to 关联)
8
- * S3 channel 隔离:任务不串channel、消息不串channel、monitor 事件流互不污染
9
- * S4 监控 + 实时状态:两 channel 各自 monitor 独立事件流;全员最终 idle + 队列空;
10
- * queueOverview 每 channel 只返回自己的成员
11
- *
12
- * 运行: npx tsx scripts/e2e-channel-isolation.ts(依赖 PATH 上的 omp 与已配置模型)
13
- */
14
- import type { DatabaseSync } from 'node:sqlite'
15
- import { mkdirSync, writeFileSync, rmSync } from 'node:fs'
16
- import { resolve } from 'node:path'
17
- import { openWorkshopDb } from '../server/services/workshop/db/database'
18
- import { createChannelRepo } from '../server/services/workshop/db/channel.repo'
19
- import { createAgentRepo } from '../server/services/workshop/db/agent.repo'
20
- import { createChannelAgentRepo } from '../server/services/workshop/db/channel-agent.repo'
21
- import { createTaskRepo } from '../server/services/workshop/db/task.repo'
22
- import { createMemoryRepo } from '../server/services/workshop/db/memory.repo'
23
- import { createChannelEventRepo } from '../server/services/workshop/db/channel-event.repo'
24
- import { createTeamRepo } from '../server/services/workshop/db/team.repo'
25
- import { createTeamMemberRepo } from '../server/services/workshop/db/team-member.repo'
26
- import { createMessageRepo } from '../server/services/workshop/db/message.repo'
27
- import { createSubscriptionRepo } from '../server/services/workshop/db/subscription.repo'
28
- import { createAgentChannelManager } from '../server/services/workshop/runtime/manager'
29
- import type { AgentChannelManager } from '../server/services/workshop/runtime/manager'
30
- import { createAgentImpl } from '../server/services/workshop/agents/factory'
31
- import { monitorChannel } from '../server/services/workshop/runtime/monitor'
32
- import type { WorkshopMonitor, MonitorEvent } from '../server/services/workshop/runtime/monitor'
33
-
34
- let failures = 0
35
- const sleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms))
36
-
37
- function check(name: string, ok: boolean, detail = ''): void {
38
- console.log(` ${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
39
- if (!ok) failures += 1
40
- }
41
-
42
- function makeManager(db: DatabaseSync): AgentChannelManager {
43
- return createAgentChannelManager({
44
- repos: {
45
- channels: createChannelRepo(db),
46
- agents: createAgentRepo(db),
47
- channelAgents: createChannelAgentRepo(db),
48
- messages: createMessageRepo(db),
49
- subscriptions: createSubscriptionRepo(db),
50
- tasks: createTaskRepo(db),
51
- memories: createMemoryRepo(db),
52
-
53
- channelEvents: createChannelEventRepo(db),
54
- teams: createTeamRepo(db),
55
- teamMembers: createTeamMemberRepo(db),
56
- },
57
- implFactory: createAgentImpl,
58
- db,
59
- })
60
- }
61
-
62
- interface Internals {
63
- deps: { repos: { messages: {
64
- listRecentByChannel(channelId: string, limit: number): Array<{ id: string, fromAgentId: string | null, toAgentId: string | null, partsJson: string, metadataJson: string }>
65
- } } }
66
- agentIndex: Map<string, unknown>
67
- getTaskEngine(): {
68
- get(id: string): { id: string, channelId: string, title: string, state: string, assigneeId: string, parentId?: string, artifacts: Array<{ parts: Array<{ text?: string }> }> } | undefined
69
- list(channelId: string): Array<{ id: string, channelId: string, title: string, state: string, assigneeId: string, parentId?: string, artifacts: Array<{ parts: Array<{ text?: string }> }> }>
70
- }
71
- }
72
-
73
- function internalsOf(manager: AgentChannelManager): Internals {
74
- return manager as unknown as Internals
75
- }
76
-
77
- interface Msg { id: string, from: string | null, to: string | null, text: string, metadata: Record<string, unknown> }
78
-
79
- function listMessages(manager: AgentChannelManager, channelId: string, limit = 200): Msg[] {
80
- return internalsOf(manager).deps.repos.messages.listRecentByChannel(channelId, limit).reverse().map(r => ({
81
- id: r.id,
82
- from: r.fromAgentId,
83
- to: r.toAgentId,
84
- text: (JSON.parse(r.partsJson) as Array<{ text?: string }>).map(p => p.text ?? '').join(' '),
85
- metadata: JSON.parse(r.metadataJson) as Record<string, unknown>,
86
- }))
87
- }
88
-
89
- async function waitFor(cond: () => boolean, timeoutMs: number): Promise<boolean> {
90
- const deadline = Date.now() + timeoutMs
91
- while (Date.now() < deadline) {
92
- if (cond()) return true
93
- await sleep(100)
94
- }
95
- return cond()
96
- }
97
-
98
- function ompPidOf(manager: AgentChannelManager, channelId: string, agentId: string): number | null {
99
- const runtime = internalsOf(manager).agentIndex.get(`${channelId}\u0000${agentId}`) as unknown as {
100
- impl?: { client?: { child?: { pid?: number } } }
101
- } | undefined
102
- return runtime?.impl?.client?.child?.pid ?? null
103
- }
104
-
105
- /** 全部任务 artifacts 文本 */
106
- function artifactTexts(manager: AgentChannelManager, channelId: string): string[] {
107
- const engine = internalsOf(manager).getTaskEngine()
108
- return engine.list(channelId).flatMap(t => t.artifacts.flatMap(a => a.parts.map(p => p.text ?? '')))
109
- }
110
-
111
- const TIMING = { task: 240_000, dialog: 180_000, idle: 60_000 }
112
-
113
- interface Team {
114
- channelId: string
115
- workspace: string
116
- marker: string
117
- leadId: string
118
- workers: Array<{ id: string, name: string }>
119
- memberIds: string[]
120
- mon: WorkshopMonitor
121
- }
122
-
123
- async function buildTeam(
124
- manager: AgentChannelManager,
125
- name: string,
126
- workspace: string,
127
- marker: string,
128
- ): Promise<Team> {
129
- writeFileSync(resolve(workspace, 'shared.txt'), `marker:${marker}`, 'utf8')
130
- const ch = await manager.createChannel({
131
- name,
132
- workspace,
133
- leadAgent: { name: `${name}-lead`, harness: 'omp', config: { provider: 'zhipu-coding-plan', model: 'glm-5.2' } },
134
- })
135
- const wTpl1 = await manager.createAgent({ name: `${name}-w1`, harness: 'omp', config: { provider: 'zhipu-coding-plan', model: 'glm-5.2' } })
136
- const wTpl2 = await manager.createAgent({ name: `${name}-w2`, harness: 'omp', config: { provider: 'zhipu-coding-plan', model: 'glm-5.2' } })
137
- const i1 = await manager.addAgentToChannel({ channelId: ch.channelId, agentId: wTpl1.id, role: 'worker' })
138
- const i2 = await manager.addAgentToChannel({ channelId: ch.channelId, agentId: wTpl2.id, role: 'worker' })
139
- // 先激活(装配 bus),monitor 订阅才有效
140
- manager.ensureChannelActive(ch.channelId)
141
- const mon = monitorChannel(manager, ch.channelId)
142
- const members = await manager.listChannelAgents(ch.channelId)
143
- return {
144
- channelId: ch.channelId,
145
- workspace,
146
- marker,
147
- leadId: members.find(m => m.role === 'lead')?.id ?? '',
148
- workers: [i1, i2].map(w => ({ id: w.id, name: w.name })),
149
- memberIds: members.map(m => m.id),
150
- mon,
151
- }
152
- }
153
-
154
- /** monitor 事件流泄漏检查:本 monitor 是否出现对方 channel 的成员/任务 id */
155
- function monitorSawIdsOf(mon: WorkshopMonitor, otherMemberIds: string[], otherTaskIds: string[]): { leakedAgentIds: string[], leakedTaskIds: string[] } {
156
- const leakedAgentIds: string[] = []
157
- const leakedTaskIds: string[] = []
158
- for (const e of mon.events) {
159
- const ev = e as MonitorEvent & { agentId?: string, taskId?: string }
160
- if (ev.agentId && otherMemberIds.includes(ev.agentId)) leakedAgentIds.push(ev.agentId)
161
- if (ev.taskId && otherTaskIds.includes(ev.taskId)) leakedTaskIds.push(ev.taskId)
162
- }
163
- return { leakedAgentIds, leakedTaskIds }
164
- }
165
-
166
- async function main(): Promise<void> {
167
- console.log('━━━ 双 Channel 隔离端到端(真实 omp):任务下发 + 点对点实时通信 + 隔离 + 监控 ━━━')
168
- const root = resolve(process.cwd(), '.tmp-e2e-iso')
169
- const db = openWorkshopDb(':memory:')
170
- const manager = makeManager(db)
171
- try {
172
- // ---- 组队:两个 channel,各自独立 workspace ----
173
- mkdirSync(resolve(root, 'A'), { recursive: true })
174
- mkdirSync(resolve(root, 'B'), { recursive: true })
175
- const teamA = await buildTeam(manager, '频道A', resolve(root, 'A'), 'CHANNEL-ALPHA-7734')
176
- const teamB = await buildTeam(manager, '频道B', resolve(root, 'B'), 'CHANNEL-BETA-9918')
177
- const engine = internalsOf(manager).getTaskEngine()
178
- console.log(` A: ${teamA.channelId.slice(0, 8)} ws=${teamA.workspace}`)
179
- console.log(` B: ${teamB.channelId.slice(0, 8)} ws=${teamB.workspace}`)
180
-
181
- // ---- S1 任务下发 + workspace 隔离(两 channel 并行)----
182
- console.log('\n━━━ S1. 任务下发 + workspace 隔离 ━━━')
183
- const taskDesc = (marker: string) =>
184
- `Read the file shared.txt in your working directory and report its EXACT full content (it starts with "marker:"). Then call complete_task with the file content as the deliverable. Expected prefix: "marker:${marker}" — but report what you actually read.`
185
- const taskA = await manager.submitChannelTask({ channelId: teamA.channelId, title: '读取共享文件', description: taskDesc(teamA.marker) })
186
- const taskB = await manager.submitChannelTask({ channelId: teamB.channelId, title: '读取共享文件', description: taskDesc(teamB.marker) })
187
-
188
- const bothDone = await waitFor(() =>
189
- engine.get(taskA.id)?.state === 'COMPLETED' && engine.get(taskB.id)?.state === 'COMPLETED',
190
- TIMING.task)
191
- check('S1: 两 channel 任务并行下发并全部完成', bothDone,
192
- `A=${engine.get(taskA.id)?.state} B=${engine.get(taskB.id)?.state}`)
193
-
194
- // 子任务下发到本 channel worker(任务下发链路)
195
- const childA = engine.list(teamA.channelId).find(t => t.parentId === taskA.id)
196
- check('S1: A 的 lead 把任务下发给本 channel worker', !!childA && teamA.workers.some(w => w.id === childA.assigneeId),
197
- childA ? `assignee=${childA.assigneeId.slice(0, 8)} state=${childA.state}` : 'no child')
198
- const childB = engine.list(teamB.channelId).find(t => t.parentId === taskB.id)
199
- check('S1: B 的 lead 把任务下发给本 channel worker', !!childB && teamB.workers.some(w => w.id === childB.assigneeId),
200
- childB ? `assignee=${childB.assigneeId.slice(0, 8)} state=${childB.state}` : 'no child')
201
-
202
- // workspace 隔离:成果内容验证
203
- const textsA = artifactTexts(manager, teamA.channelId).join('\n')
204
- const textsB = artifactTexts(manager, teamB.channelId).join('\n')
205
- check('S1: A 成果含本 workspace 标记', textsA.includes(teamA.marker), textsA.slice(0, 60))
206
- check('S1: A 成果不含 B 的标记', !textsA.includes(teamB.marker))
207
- check('S1: B 成果含本 workspace 标记', textsB.includes(teamB.marker), textsB.slice(0, 60))
208
- check('S1: B 成果不含 A 的标记', !textsB.includes(teamA.marker))
209
-
210
- // ---- S2 点对点实时通信(两 channel 并行;真实 LLM 回执)----
211
- console.log('\n━━━ S2. 点对点实时通信(触发器回执)━━━')
212
- const m1 = await manager.sendImmediateMessage({
213
- channelId: teamA.channelId, fromAgentId: teamA.leadId, toAgentId: teamA.workers[0].id,
214
- parts: [{ text: 'What is 2+3? Answer with just the number.' }], requireReply: true,
215
- })
216
- const m2 = await manager.sendA2A(teamA.channelId, teamA.workers[0].id, {
217
- toAgentId: teamA.workers[1].id,
218
- parts: [{ text: 'What is 10-4? Answer with just the number.' }],
219
- metadata: { 'x-aw-msg-priority': 'task', 'x-aw-require-reply': 'true' },
220
- })
221
- const m3 = await manager.sendImmediateMessage({
222
- channelId: teamB.channelId, fromAgentId: teamB.workers[0].id, toAgentId: teamB.leadId,
223
- parts: [{ text: 'What is 6*7? Answer with just the number.' }], requireReply: true,
224
- })
225
-
226
- const [r1, r2, r3] = await Promise.all([
227
- (async () => {
228
- const deadline = Date.now() + TIMING.dialog
229
- while (Date.now() < deadline) {
230
- const hit = listMessages(manager, teamA.channelId).find(x => x.metadata['x-aw-in-reply-to'] === m1.messageId)
231
- if (hit) return hit
232
- await sleep(150)
233
- }
234
- return null
235
- })(),
236
- (async () => {
237
- const deadline = Date.now() + TIMING.dialog
238
- while (Date.now() < deadline) {
239
- const hit = listMessages(manager, teamA.channelId).find(x => x.metadata['x-aw-in-reply-to'] === m2.messageId)
240
- if (hit) return hit
241
- await sleep(150)
242
- }
243
- return null
244
- })(),
245
- (async () => {
246
- const deadline = Date.now() + TIMING.dialog
247
- while (Date.now() < deadline) {
248
- const hit = listMessages(manager, teamB.channelId).find(x => x.metadata['x-aw-in-reply-to'] === m3.messageId)
249
- if (hit) return hit
250
- await sleep(150)
251
- }
252
- return null
253
- })(),
254
- ])
255
-
256
- check('S2: A lead→worker 回执(2+3)', r1 !== null && r1.text.includes('5'), r1?.text.slice(0, 60) ?? 'timeout')
257
- check('S2: A lead→worker in_reply_to 关联', r1?.metadata['x-aw-in-reply-to'] === m1.messageId)
258
- check('S2: A worker↔worker 回执(10-4)', r2 !== null && r2.text.includes('6'), r2?.text.slice(0, 60) ?? 'timeout')
259
- check('S2: A worker↔worker in_reply_to 关联', r2?.metadata['x-aw-in-reply-to'] === m2.messageId)
260
- check('S2: B worker→lead 回执(6*7)', r3 !== null && r3.text.includes('42'), r3?.text.slice(0, 60) ?? 'timeout')
261
- check('S2: B worker→lead in_reply_to 关联', r3?.metadata['x-aw-in-reply-to'] === m3.messageId)
262
-
263
- // ---- S3 channel 隔离 ----
264
- console.log('\n━━━ S3. Channel 隔离 ━━━')
265
- const tasksA = engine.list(teamA.channelId)
266
- const tasksB = engine.list(teamB.channelId)
267
- check('S3: 任务不串 channel', !tasksA.some(t => t.channelId !== teamA.channelId) && !tasksB.some(t => t.channelId !== teamB.channelId),
268
- `A=${tasksA.length} B=${tasksB.length}`)
269
- const msgA = listMessages(manager, teamA.channelId)
270
- const msgB = listMessages(manager, teamB.channelId)
271
- check('S3: 消息不串 channel', !msgA.some(m => teamB.memberIds.includes(m.to ?? '')) && !msgB.some(m => teamA.memberIds.includes(m.to ?? '')))
272
- // monitor 事件流隔离:A 的 monitor 不含 B 的成员/任务事件
273
- const taskIdsB = engine.list(teamB.channelId).map(t => t.id)
274
- const taskIdsA = engine.list(teamA.channelId).map(t => t.id)
275
- const leakA = monitorSawIdsOf(teamA.mon, teamB.memberIds, taskIdsB)
276
- const leakB = monitorSawIdsOf(teamB.mon, teamA.memberIds, taskIdsA)
277
- check('S3: A monitor 无 B 成员事件泄漏', leakA.leakedAgentIds.length === 0, leakA.leakedAgentIds.join(',').slice(0, 40))
278
- check('S3: A monitor 无 B 任务事件泄漏', leakA.leakedTaskIds.length === 0, `n=${leakA.leakedTaskIds.length}`)
279
- check('S3: B monitor 无 A 成员事件泄漏', leakB.leakedAgentIds.length === 0, leakB.leakedAgentIds.join(',').slice(0, 40))
280
- check('S3: B monitor 无 A 任务事件泄漏', leakB.leakedTaskIds.length === 0, `n=${leakB.leakedTaskIds.length}`)
281
-
282
- // ---- S4 监控 + 实时状态 ----
283
- console.log('\n━━━ S4. 监控与实时状态 ━━━')
284
- const evA = teamA.mon.events
285
- const evB = teamB.mon.events
286
- check('S4: A monitor 捕获本 channel 任务完成', evA.some(e => e.kind === 'task.status' && e.taskId === taskA.id && e.state === 'COMPLETED'),
287
- `events=${evA.length}`)
288
- check('S4: B monitor 捕获本 channel 任务完成', evB.some(e => e.kind === 'task.status' && e.taskId === taskB.id && e.state === 'COMPLETED'),
289
- `events=${evB.length}`)
290
- check('S4: busy 事件携带 currentTaskId', evA.some(e => e.kind === 'agent.status' && e.state === 'busy' && e.currentTaskId != null))
291
-
292
- // 全员最终 idle(未装配成员 runtimeState=null 视同空闲;装配过的须 idle)
293
- const allIdle = await waitFor(() => {
294
- return [teamA, teamB].every(t =>
295
- t.memberIds.every((id) => {
296
- const s = manager.getChannelAgent(id)?.runtimeState
297
- return s === null || s === 'idle'
298
- }))
299
- }, TIMING.idle)
300
- check('S4: 两 channel 全员最终 idle', allIdle)
301
-
302
- const overviewA = await manager.queueOverview(teamA.channelId, teamA.leadId)
303
- const overviewB = await manager.queueOverview(teamB.channelId, teamB.leadId)
304
- check('S4: A queueOverview 仅含本 channel 3 成员', overviewA.length === 3 && overviewA.every(s => teamA.memberIds.includes(s.agentId)))
305
- check('S4: B queueOverview 仅含本 channel 3 成员', overviewB.length === 3 && overviewB.every(s => teamB.memberIds.includes(s.agentId)))
306
- check('S4: 全员队列已清空', overviewA.every(s => s.queuedCount === 0) && overviewB.every(s => s.queuedCount === 0))
307
-
308
- // 独立进程:两 channel 全部已装配成员 PID 互不相同
309
- const pids = [...teamA.memberIds.map(id => ompPidOf(manager, teamA.channelId, id)),
310
- ...teamB.memberIds.map(id => ompPidOf(manager, teamB.channelId, id))].filter(p => p !== null)
311
- check('S4: 双 channel 子进程 PID 全部互异', new Set(pids).size === pids.length, `spawned=${pids.length} pids=${pids.join(',')}`)
312
- }
313
- finally {
314
- await manager.shutdown()
315
- rmSync(root, { recursive: true, force: true })
316
- }
317
-
318
- console.log(`\n${failures === 0 ? 'ALL PASS' : `${failures} FAILED`}`)
319
- process.exit(failures === 0 ? 0 : 1)
320
- }
321
-
322
- main().catch((e) => {
323
- console.error('测试异常:', e)
324
- process.exit(1)
325
- })