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,279 +0,0 @@
1
- /**
2
- * 模拟真实产线全栈 E2E(生产实例 :3001,真实协议:Modbus TCP/RTU、MQTT、OPC UA、HTTP)
3
- *
4
- * S1 夹具:产线+产品+配方+5 数采节点(modbus-tcp/rtu/mqtt/opcua/http)+5 数控节点
5
- * S2 协议连通:逐节点驱动 test(真实连接)
6
- * S3 数采:开跑 → 采样流入(mock 之外的 5 协议节点值变化)+ Timescale 落库
7
- * S4 数控:REST 下发 modbus-tcp/rtu/opcua/http/mqtt 五路(真实协议写+回读/路由捕获)
8
- * S5 Agent 闭环:绑定 → 任务(dcw_control→daq_query→dcw_judge)→ CLOSEDLOOP-OK
9
- * S6 HITL:manual 绑定的 OPC UA 节点 → 待审批 → 批准 → 真实写入
10
- * S7 Recipe:下发(PLC=目标)/recipe_update/recipe_rollback/版本史/参数账本回退
11
- *
12
- * 用法:NO_PROXY='127.0.0.1,localhost' node scripts/_dbg-live-line-e2e.mjs [base] [tag]
13
- */
14
- const BASE = process.argv[2] ?? 'http://127.0.0.1:3001'
15
- const TAG = process.argv[3] ?? `lv${Math.random().toString(36).slice(2, 6)}`
16
- const { createRequire } = await import('node:module')
17
- const reqMqtt = createRequire(import.meta.url)
18
- let pass = 0
19
- let fail = 0
20
- const ok = (cond, name, extra = '') => {
21
- if (cond) {
22
- pass++
23
- console.log(` ✓ ${name}`)
24
- }
25
- else {
26
- fail++
27
- console.log(` ✗ ${name} ${extra}`)
28
- }
29
- }
30
- const sleep = ms => new Promise(r => setTimeout(r, ms))
31
- const api = async (method, path, { body, token } = {}) => {
32
- const res = await fetch(`${BASE}${path}`, {
33
- method,
34
- headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
35
- body: body === undefined ? undefined : JSON.stringify(body),
36
- signal: AbortSignal.timeout(60_000),
37
- })
38
- return { status: res.status, ...(await res.json().catch(() => ({}))) }
39
- }
40
- const invoke = (token, agentId, tool, args) => api('POST', '/api/workshop/agent-tools/invoke', { body: { agentId, tool, args }, token })
41
-
42
- async function main() {
43
- console.log(`━━━ 模拟真实产线全栈 E2E @ ${BASE} (tag=${TAG}) ━━━`)
44
-
45
- // ════ S0 登录 ════
46
- const login = await api('POST', '/api/users/login', { body: { email: 'admin@awshop.local', password: 'admin123' } })
47
- if (login.data?.token === undefined) {
48
- // 隔离库回退:admin 用户名
49
- const alt = await api('POST', '/api/users/login', { body: { email: 'admin', password: 'admin123' } })
50
- login.data = alt.data
51
- }
52
- const token = login.data?.token
53
- ok(Boolean(token), 'admin 登录')
54
- if (!token) process.exit(1)
55
-
56
- // ════ S1 夹具 ════
57
- const line = (await api('POST', '/api/workshop/dcw/lines', { body: { name: `模拟产线-${TAG}` }, token })).data?.line
58
- const product = (await api('POST', '/api/workshop/dcw/products', { body: { name: `模拟产品-${TAG}`, lineId: line.id }, token })).data?.product
59
- ok(Boolean(line?.id && product?.id), `产线/产品创建(${line.id.slice(0, 8)})`)
60
-
61
- // 5 数采节点(5 协议)
62
- const daqDefs = [
63
- { key: 'modbus-tcp', name: `进料压力-MBTCP`, driverConfig: { host: '127.0.0.1', port: 1502, unitId: 1, register: 40001, registerType: 'holding', dataType: 'float32', scale: 1, byteOrder: 'big' }, template: 'pressure-tx' },
64
- { key: 'modbus-rtu', name: `RTU 温度`, driverConfig: { host: '127.0.0.1', port: 15030, unitId: 1, register: 40001, registerType: 'holding', dataType: 'float32', scale: 1, byteOrder: 'big' }, template: 'temp-tc' },
65
- { key: 'opcua', name: `OPC 炉温`, driverConfig: { endpoint: 'opc.tcp://127.0.0.1:4840', nodeId: 'ns=2;s=AW.Temp' }, template: 'temp-tc' },
66
- { key: 'mqtt', name: `MQTT 均温`, driverConfig: { host: '127.0.0.1', port: 1883, topic: 'aw/sim/temp', jsonPath: 'data.temp' }, template: 'temp-tc' },
67
- { key: 'http', name: `HTTP 品质值`, driverConfig: { url: 'http://127.0.0.1:1889/api/value', jsonPath: 'data.value' }, template: 'temp-tc' },
68
- ]
69
- const daqNodes = {}
70
- for (const d of daqDefs) {
71
- const test = await api('POST', '/api/workshop/daq/test-driver', { body: { driver: d.key, driverConfig: d.driverConfig }, token })
72
- const node = (await api('POST', '/api/workshop/daq', {
73
- body: { name: `${d.name}-${TAG}`, templateRef: d.template, driver: d.key, driverConfig: d.driverConfig, unit: d.key === 'modbus-tcp' ? 'MPa' : '℃', min: 0, max: 200, intervalMs: 2000, lineId: line.id },
74
- token,
75
- })).data?.node
76
- daqNodes[d.key] = node
77
- const testOk = test.data?.test?.ok !== false
78
- ok(Boolean(node?.id), `[daq] ${d.key} 创建(test=${testOk ? '连通' : (test.data?.test?.message ?? '失败')})`, test.data?.test?.message)
79
- }
80
-
81
- // 5 数控节点(5 协议)
82
- const dcwDefs = [
83
- { key: 'modbus-tcp', name: `压力设定-MBTCP`, driverConfig: { host: '127.0.0.1', port: 1502, unitId: 1, register: 40021, dataType: 'float32', byteOrder: 'big' }, unit: 'MPa', min: 0, max: 5 },
84
- { key: 'modbus-rtu', name: `RTU 开度`, driverConfig: { host: '127.0.0.1', port: 15030, unitId: 1, register: 40021, dataType: 'int16', byteOrder: 'big' }, unit: '%', min: 0, max: 10000 },
85
- { key: 'opcua', name: `OPC 炉温设定`, driverConfig: { endpoint: 'opc.tcp://127.0.0.1:4840', nodeId: 'ns=2;s=AW.SetTemp' }, unit: '℃', min: 0, max: 200 },
86
- { key: 'mqtt', name: `MQTT 下位机设定`, driverConfig: { host: '127.0.0.1', port: 1883, topic: `aw/sim/setpoint/${TAG}`, jsonKey: 'value' }, unit: '℃', min: 0, max: 200 },
87
- { key: 'http', name: `HTTP 加热设定`, driverConfig: { url: 'http://127.0.0.1:1889/api/setpoint', bodyKey: 'value' }, unit: '℃', min: 0, max: 200 },
88
- ]
89
- const dcwNodes = {}
90
- for (const d of dcwDefs) {
91
- const node = (await api('POST', '/api/workshop/dcw', {
92
- body: { name: `${d.name}-${TAG}`, templateRef: 'temp-sp', driver: d.key, driverConfig: d.driverConfig, unit: d.unit, min: d.min, max: d.max, lineId: line.id },
93
- token,
94
- })).data?.node
95
- dcwNodes[d.key] = node
96
- ok(Boolean(node?.id), `[dcw] ${d.key} 创建`)
97
- }
98
-
99
- // 配方:2 个真实协议参数
100
- const recipe = (await api('POST', '/api/workshop/dcw/recipes', {
101
- body: { name: `工艺A-${TAG}`, productId: product.id, params: [
102
- { nodeId: dcwNodes['modbus-tcp'].id, value: 0.9, min: 0.6, max: 1.1 },
103
- { nodeId: dcwNodes['modbus-rtu'].id, value: 500 },
104
- ] },
105
- token,
106
- })).data?.recipe
107
- ok(Boolean(recipe?.id), `配方创建(${recipe?.id})`)
108
-
109
- // ════ S2 数采协议连通(节点级 test)════
110
- for (const [k, n] of Object.entries(daqNodes)) {
111
- const t = await api('POST', `/api/workshop/daq/${n.id}/test`, { body: {}, token })
112
- ok(t.data?.ok === true || t.data?.ok === undefined || t.status === 200, `[daq] ${k} test 连通`, JSON.stringify(t.data ?? t).slice(0, 90))
113
- }
114
-
115
- // ════ S3 数采流入(开跑 → 采样 + Timescale)════
116
- const producedBefore = (await api('GET', '/api/workshop/daq', { token })).data?.meta?.produced ?? 0
117
- const start = await api('POST', `/api/workshop/dcw/lines/${line.id}/start`, { body: { recipeId: recipe.id }, token })
118
- ok(start.status === 200, '产线开跑(绑定配方批次)', start.message)
119
- await sleep(9000)
120
- const daqSnap = (await api('GET', '/api/workshop/daq', { token })).data
121
- const liveNodes = daqSnap.nodes.filter(n => Object.values(daqNodes).some(x => x?.id === n.id))
122
- const changing = liveNodes.filter(n => n.value != null)
123
- ok(changing.length >= 4, `数采流入:5 协议节点中 ${changing.length} 个有实时值(${changing.map(n => `${n.name}=${n.value}`).join('; ').slice(0, 140)})`)
124
- const prodAfter = daqSnap.meta?.produced ?? 0
125
- ok(prodAfter > producedBefore, `管线 produced 增长(${producedBefore} → ${prodAfter})`)
126
-
127
- // ════ S4 数控五协议下发 ════
128
- const w1 = await api('POST', `/api/workshop/dcw/${dcwNodes['modbus-tcp'].id}/write`, { body: { value: 0.95 }, token })
129
- ok(w1.data?.outcome?.ok === true || w1.data?.ok !== false, `modbus-tcp 写 0.95(回读 ${w1.data?.outcome?.readback ?? w1.data?.readback ?? '?'})`, JSON.stringify(w1.data ?? w1).slice(0, 120))
130
- const w2 = await api('POST', `/api/workshop/dcw/${dcwNodes['modbus-rtu'].id}/write`, { body: { value: 500 }, token })
131
- ok(w2.data?.outcome?.ok === true || w2.data?.ok !== false, `modbus-rtu 写 500(int16,回读 ${w2.data?.outcome?.readback ?? w2.data?.readback ?? '?'})`, JSON.stringify(w2.data ?? w2).slice(0, 120))
132
- const w3 = await api('POST', `/api/workshop/dcw/${dcwNodes['opcua'].id}/write`, { body: { value: 88 }, token })
133
- ok(w3.data?.outcome?.ok === true, `opcua 写 88(回读 ${w3.data?.outcome?.readback ?? '?'})`, JSON.stringify(w3.data ?? w3).slice(0, 120))
134
- const w4 = await api('POST', `/api/workshop/dcw/${dcwNodes['http'].id}/write`, { body: { value: 66.6 }, token })
135
- ok(w4.data?.outcome?.ok === true, `http 写 66.6(POST /api/setpoint,回读 ${w4.data?.outcome?.readback ?? '?'})`, JSON.stringify(w4.data ?? w4).slice(0, 120))
136
-
137
- // mqtt 下发:订阅容器内 mosquitto?此处 1883 是 proto-sim broker —— 用 node 订阅捕获
138
- const captured = await captureMqtt(`aw/sim/setpoint/${TAG}`, async () => {
139
- await api('POST', `/api/workshop/dcw/${dcwNodes['mqtt'].id}/write`, { body: { value: 55.5 }, token })
140
- })
141
- ok(captured.includes('55.5'), `mqtt 下发路由捕获(topic=aw/sim/setpoint/${TAG} payload 含 55.5)`, captured.slice(0, 80))
142
-
143
- // ════ S5 Agent 闭环(真实协议节点)════
144
- const ch = (await api('POST', '/api/workshop/channels', {
145
- body: { name: `live-${TAG}`, leadAgent: { name: `lead-${TAG}`, harness: 'mock', config: { delayMs: 60 } } },
146
- token,
147
- })).data
148
- const tpl = await api('POST', '/api/workshop/agents', {
149
- body: { name: `op-${TAG}`, harness: 'omp', config: { provider: 'zhipu-coding-plan', model: 'glm-5.3-flash', systemPromptPrefix: '你是产线操作员:严格按步骤执行,完成后立即调用 complete_task。' } },
150
- token,
151
- })
152
- const join = await api('POST', `/api/workshop/channels/${ch.channelId}/agents`, { body: { agentId: tpl.data.id, role: 'worker' }, token })
153
- const instId = join.data?.id
154
- await api('POST', '/api/workshop/agent-tools/bindings', { body: { agentId: instId, nodeId: dcwNodes['modbus-tcp'].id, kind: 'dcw', mode: 'auto' }, token })
155
- await api('POST', '/api/workshop/agent-tools/bindings', { body: { agentId: instId, nodeId: daqNodes['modbus-tcp'].id, kind: 'daq', mode: 'auto' }, token })
156
- // HITL:opcua 设定节点 manual 模式
157
- await api('POST', '/api/workshop/agent-tools/bindings', { body: { agentId: instId, nodeId: dcwNodes['opcua'].id, kind: 'dcw', mode: 'manual' }, token })
158
- ok(Boolean(instId), 'Agent 入队 + 三节点绑定(auto×2 + manual×1)')
159
-
160
- // 闭环任务
161
- const t1 = await api('POST', `/api/workshop/channels/${ch.channelId}/tasks`, {
162
- body: {
163
- title: `closedloop-${TAG}`,
164
- parts: [{ text: `闭环调优(严格按步骤):
165
- 1. dcw_control(node_id="${dcwNodes['modbus-tcp'].id}", value=0.95, hypothesis="提压验证") 下发压力设定;
166
- 2. 等待 3 秒后 daq_query(node_id="${daqNodes['modbus-tcp'].id}") 查看进料压力响应;
167
- 3. 基于数采证据 dcw_judge:对刚才下发的优化记录落判定 keep(附一句证据);
168
- 4. 最终交付原样包含一行标记 CLOSEDLOOP-OK,并附压力设定值与采样值各一个。
169
- 完成后调用 complete_task。` }],
170
- assigneeId: instId,
171
- },
172
- token,
173
- })
174
- const task1 = t1.data?.task?.id ?? t1.data?.id
175
- const st1 = await pollTask(token, task1, 12 * 60_000)
176
- ok(st1 === 'COMPLETED', `[闭环] 任务 COMPLETED(state=${st1})`)
177
- const blob1 = await gatherTaskBlob(token, ch.channelId, task1)
178
- ok(blob1.includes('CLOSEDLOOP-OK'), '[闭环] 交付含 CLOSEDLOOP-OK(真实协议下发+数采证据+判定)')
179
-
180
- // ════ S6 HITL(manual 绑定 → invoke 挂起 → 审批 → 真实写入)════
181
- // HITL 语义:invoke 挂起等待裁决(超时 300s),因此后台发起、轮询待办、批准后收结果
182
- const hitlPromise = invoke(token, instId, 'dcw_control', { node_id: dcwNodes['opcua'].id, value: 92, task_id: 'hitl-e2e' }).catch(err => ({ data: { result: { text: `invoke err: ${err.message}`, isError: true } } }))
183
- let pending = null
184
- for (let i = 0; i < 10 && !pending; i++) {
185
- await sleep(1500)
186
- const pend = (await api('GET', '/api/workshop/agent-tools/approvals', { token })).data?.approvals ?? []
187
- pending = pend.find(p => p.agentId === instId) ?? null
188
- }
189
- ok(Boolean(pending?.id), `[HITL] 产生待审批(${pending?.id ?? '无'})`)
190
- if (pending?.id) {
191
- const dec = await api('POST', `/api/workshop/agent-tools/approvals/${pending.id}/decide`, { body: { approved: true, comment: 'E2E 批准' }, token })
192
- ok(dec.status === 200, '[HITL] 管理员批准')
193
- const hitl = await hitlPromise
194
- ok(hitl.data?.result?.isError !== true, '[HITL] Agent 收到批准结果并执行', (hitl.data?.result?.text ?? '').slice(0, 90))
195
- await sleep(1500)
196
- const rd = await api('POST', `/api/workshop/dcw/${dcwNodes['opcua'].id}/read`, { body: {}, token })
197
- ok(String(rd.data?.read?.value ?? '').startsWith('92'), `[HITL] 批准后真实写入生效(OPC UA SetTemp 回读 ${rd.data?.read?.value})`, JSON.stringify(rd.data ?? rd).slice(0, 90))
198
- }
199
- else {
200
- await hitlPromise.catch(() => {})
201
- }
202
-
203
- // ════ S7 Recipe 全生命周期(真实协议下发)════
204
- const upd = await invoke(token, instId, 'recipe_update', { recipe_id: recipe.id, params: [{ node_id: dcwNodes['modbus-tcp'].id, value: 0.98 }], reason: '闭环验证:压力窗口内稳定' })
205
- ok(upd.data?.result?.text?.includes('v2'), '[recipe] Agent recipe_update → v2', upd.data?.result?.text?.slice(0, 90))
206
- const rv = await api('POST', `/api/workshop/dcw/recipes/${recipe.id}/revert`, { body: { version: 1, reason: 'E2E 回退到初版' }, token })
207
- ok(rv.data?.recipe?.version === 3, '[recipe] 界面回退 → v3')
208
- const jl = await invoke(token, instId, 'dcw_journal', { node_id: dcwNodes['modbus-tcp'].id })
209
- ok(jl.data?.result?.text?.includes('优化记录') || jl.data?.result?.text?.includes('锚'), '[journal] dcw_journal 参数账本可查')
210
- // 节点级参数回退:回退压力设定到上一稳定锚
211
- const rb = await invoke(token, instId, 'dcw_rollback', { node_id: dcwNodes['modbus-tcp'].id })
212
- const rbOk = rb.data?.result?.text?.includes('回退') && !rb.data?.result?.isError
213
- const rbSkip = (rb.data?.result?.text ?? '').includes('冷却') || (rb.data?.result?.text ?? '').includes('无可回退')
214
- ok(rbOk || rbSkip, `[journal] dcw_rollback 执行(${rb.data?.result?.text?.slice(0, 70) ?? '∅'})`)
215
-
216
- // ════ 清理 ════
217
- await api('POST', `/api/workshop/dcw/lines/${line.id}/stop`, { body: {}, token }).catch(() => {})
218
- await api('DELETE', `/api/workshop/channels/${ch.channelId}?purge=1`, { token }).catch(() => {})
219
- await api('DELETE', `/api/workshop/agents/${tpl.data.id}`, { token }).catch(() => {})
220
- await api('DELETE', `/api/workshop/dcw/recipes/${recipe.id}`, { token }).catch(() => {})
221
- await api('DELETE', `/api/workshop/dcw/products/${product.id}`, { token }).catch(() => {})
222
- for (const n of Object.values(dcwNodes)) await api('DELETE', `/api/workshop/dcw/${n.id}`, { token }).catch(() => {})
223
- for (const n of Object.values(daqNodes)) await api('DELETE', `/api/workshop/daq/${n.id}`, { token }).catch(() => {})
224
- await api('DELETE', `/api/workshop/dcw/lines/${line.id}`, { token }).catch(() => {})
225
-
226
- console.log(`\n━━━ LiveLine E2E: ${pass} passed / ${fail} failed ━━━`)
227
- process.exit(fail === 0 ? 0 : 1)
228
- }
229
-
230
- async function pollTask(token, id, timeoutMs) {
231
- const deadline = Date.now() + timeoutMs
232
- let state = ''
233
- while (Date.now() < deadline) {
234
- for (let i = 0; i < 3; i++) {
235
- try {
236
- const me = await api('GET', `/api/workshop/tasks/${id}`, { token })
237
- state = me.data?.state ?? ''
238
- break
239
- }
240
- catch { await sleep(3000) }
241
- }
242
- if (['COMPLETED', 'FAILED', 'CANCELED'].includes(state)) return state
243
- await sleep(6000)
244
- }
245
- return state || 'RUNNING'
246
- }
247
-
248
- async function gatherTaskBlob(token, channelId, taskId) {
249
- const taskBlob = JSON.stringify((await api('GET', `/api/workshop/tasks/${taskId}`, { token })).data ?? {})
250
- const msgBlob = JSON.stringify((await api('GET', `/api/workshop/channels/${channelId}/messages?limit=200`, { token })).data ?? {})
251
- const evBlob = JSON.stringify((await api('GET', `/api/workshop/channels/${channelId}/events?limit=400`, { token })).data ?? {})
252
- return taskBlob + msgBlob + evBlob
253
- }
254
-
255
- /** 订阅 MQTT 主题并执行动作,断言捕获 payload(真实 broker = 127.0.0.1:1883) */
256
- async function captureMqtt(topic, action) {
257
- const mqtt = createMqttLib()
258
- return await new Promise((resolve) => {
259
- const client = mqtt.connect('mqtt://127.0.0.1:1883')
260
- let got = ''
261
- const done = () => { try { client.end(true) } catch {} ; resolve(got) }
262
- client.on('connect', async () => {
263
- client.subscribe(topic, () => {
264
- setTimeout(action, 300)
265
- })
266
- setTimeout(() => done(), 9000)
267
- })
268
- client.on('message', (t, payload) => { got = `${t} ${payload.toString()}` })
269
- setTimeout(() => done(), 12_000)
270
- })
271
- }
272
- function createMqttLib() {
273
- return reqMqtt('mqtt')
274
- }
275
-
276
- main().catch((err) => {
277
- console.error('E2E 异常:', err)
278
- process.exit(1)
279
- })
@@ -1,77 +0,0 @@
1
- /**
2
- * 最小复现:omp worker 任务失败根因定位(不清理,便于事后查库)。
3
- */
4
- const ROOT = 'http://127.0.0.1:3000'
5
- let TOKEN = ''
6
- const H = () => ({ authorization: `Bearer ${TOKEN}`, 'content-type': 'application/json' })
7
- const sleep = (ms) => new Promise(r => setTimeout(r, ms))
8
- const jpost = (u, b) => fetch(ROOT + u, { method: 'POST', headers: H(), body: JSON.stringify(b ?? {}) }).then(r => r.json())
9
- const jget = (u) => fetch(ROOT + u, { headers: H() }).then(r => r.json())
10
-
11
- async function main() {
12
- const reg = await jpost('/api/workshop/users/register', { name: 'ompdbg-' + Math.random().toString(36).slice(2, 8) })
13
- TOKEN = reg.data?.token
14
- if (!TOKEN) { console.error('register failed'); process.exit(1) }
15
- console.log('[ok] registered')
16
-
17
- // 产线:1 数采 + 1 数控 + 开跑(Agent 有数据可读)
18
- const lineRes = await jpost('/api/workshop/dcw/lines', { name: 'OMPDBG-线' })
19
- console.log('[line-res]', JSON.stringify(lineRes).slice(0, 150))
20
- const line = lineRes.data.line
21
- const dq = (await jpost('/api/workshop/daq', { templateRef: 'daq-temp-tc', name: 'OMPDBG-温度', lineId: line.id, intervalMs: 500 })).data.node
22
- const dw = (await jpost('/api/workshop/dcw', { templateRef: 'dcw-temp-sp', name: 'OMPDBG-设定', lineId: line.id })).data.node
23
- const prod = (await jpost('/api/workshop/dcw/products', { name: 'OMPDBG-产品', lineId: line.id })).data.product
24
- console.log('[prod]', prod?.id)
25
- const rcRes = await jpost('/api/workshop/dcw/recipes', {
26
- productId: prod.id, name: 'OMPDBG-配方', params: [{ templateRef: 'dcw-temp-sp', nodeId: dw.id, value: 180, min: 176, max: 188 }],
27
- daqWindows: [{ nodeId: dq.id, min: 100, max: 260 }],
28
- })
29
- console.log('[rc-res]', JSON.stringify(rcRes).slice(0, 200))
30
- const rc = rcRes.data.recipe
31
- const st = await jpost(`/api/workshop/dcw/lines/${line.id}/start`, { recipeId: rc.id })
32
- console.log('[line]', st.data?.line?.active ? 'running' : 'FAILED')
33
-
34
- // channel + omp worker(直派,无 lead 调度)
35
- const ch = (await jpost('/api/workshop/channels', { name: 'OMPDBG-channel', leadAgent: { name: 'OMPDBG-lead', harness: 'mock', config: { delayMs: 60 } } })).data
36
- console.log('[channel]', JSON.stringify(ch).slice(0, 120))
37
- const tpl = (await jpost('/api/workshop/agents', {
38
- name: 'OMPDBG-worker', harness: 'omp',
39
- config: { systemPromptPrefix: '你是测试工程师。收到任务后用 daq_query 读数并汇报均值,不要做其他事。' },
40
- })).data
41
- await jpost(`/api/workshop/channels/${ch.channelId}/agents`, { agentId: tpl.id, role: 'worker' })
42
- const agents = (await jget(`/api/workshop/channels/${ch.channelId}/agents`)).data
43
- const worker = agents.find(a => a.role === 'worker')
44
- console.log('[worker]', worker?.id?.slice(0, 8), 'harness=' + worker?.harness)
45
- await jpost('/api/workshop/agent-tools/bindings', { agentId: worker.id, nodeId: dq.id, kind: 'daq', mode: 'auto' })
46
-
47
- // 直派任务到 worker(assigneeId 直投,不经过 lead)
48
- const taskRes = await jpost(`/api/workshop/channels/${ch.channelId}/tasks`, {
49
- title: 'OMPDBG-读数任务',
50
- parts: [{ text: '用 daq_query 获取 OMPDBG-温度 最近 2 分钟数据,汇报均值。完成后用 complete_task 提交结论。' }],
51
- assigneeId: worker.id,
52
- })
53
- console.log('[task-res]', JSON.stringify(taskRes).slice(0, 260))
54
- const task = taskRes.data
55
- const taskId = task?.task?.id ?? task?.id
56
- console.log('[task]', taskId?.slice(0, 8))
57
-
58
- // 观察任务状态 + 工具审批
59
- for (let i = 0; i < 60; i++) {
60
- await sleep(3000)
61
- const t = (await jget(`/api/workshop/channels/${ch.channelId}/tasks`)).data
62
- const arr = Array.isArray(t) ? t : t?.tasks ?? []
63
- const me = arr.find(x => x.id === taskId)
64
- const proc = await jget('/api/workshop/runtime')
65
- if (i % 4 === 0) {
66
- console.log(`[t+${i * 3}s] task=${me?.state} progress=${me?.progress} wired=${proc.data?.wiredAgents?.length}`)
67
- }
68
- if (['COMPLETED', 'FAILED', 'CANCELED'].includes(me?.state)) {
69
- console.log('[final]', me?.state)
70
- const detail = (await jget(`/api/workshop/tasks/${taskId}`)).data
71
- console.log('[history]', JSON.stringify(detail?.history ?? detail?.task?.history ?? []).slice(0, 1500))
72
- break
73
- }
74
- }
75
- console.log('[cleanup-hint] channel=' + ch.channelId + ' line=' + line.id)
76
- }
77
- main().catch(e => { console.error('FATAL', e.message); process.exit(1) })
@@ -1,173 +0,0 @@
1
- /**
2
- * 运行/编辑只读锁 + 小地图同步 + 数采可视距离 审计:
3
- * 1) 运行模式:实体拖拽拒绝 / 投放拒绝+提示 / Inspector 只读(无删除、无绑定添加、名称禁用);
4
- * 2) 编辑模式:拖拽放行 / 投放成功 / Inspector 编辑控件在;
5
- * 3) 小地图与视角同步:zoomBy 后 meta ×N 变化(navScale=dolly),画布重绘;
6
- * 4) 数采可视距离滑杆:300 → 卡隐,3000 → 卡显(注视设备不变);
7
- * 5) 截图(编辑模式注视设备,堆叠卡 + 小地图)。
8
- */
9
- import puppeteer from 'puppeteer-core'
10
-
11
- const BASE = process.env.AW_PAGE_BASE ?? 'http://127.0.0.1:3000'
12
- const TOKEN = process.env.AW_PAGE_TOKEN ?? ''
13
- const H = { 'authorization': `Bearer ${TOKEN}`, 'content-type': 'application/json' }
14
-
15
- const spec = [
16
- { name: 'TD 拉幅机 L1', ref: 'dev-folder-tdo', x: 1700, z: 600, kind: 'device' },
17
- { name: '温度传感器 01', ref: 'daq-temp-tc', x: 1750, z: 690, kind: 'daq' },
18
- { name: '电参采集器 09', ref: 'daq-power-meter', x: 2900, z: 200, kind: 'daq' },
19
- ]
20
- const created = []
21
- for (const s of spec) {
22
- const res = await fetch(`${BASE}/api/workshop/device-twins`, {
23
- method: 'POST', headers: H,
24
- body: JSON.stringify({ name: s.name, modelRef: s.ref, kind: s.kind, posX: s.x, posZ: s.z }),
25
- })
26
- const j = await res.json().catch(() => ({}))
27
- const id = j?.data?.twin?.id ?? j?.data?.id
28
- if (res.ok && id) created.push({ ...s, id })
29
- }
30
- const byName = Object.fromEntries(created.map(c => [c.name, c.id]))
31
- const bindings = { [byName['温度传感器 01']]: byName['TD 拉幅机 L1'] }
32
- console.log(`created ${created.length}/${spec.length}`)
33
-
34
- const browser = await puppeteer.launch({
35
- executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
36
- headless: 'new',
37
- args: ['--no-sandbox', '--disable-gpu', '--no-first-run', '--disable-extensions', '--window-size=1600,1000'],
38
- })
39
- const page = await browser.newPage()
40
- await page.setViewport({ width: 1600, height: 1000 })
41
- await page.setCookie({ name: 'token', value: TOKEN, domain: '127.0.0.1', path: '/' })
42
- await page.evaluateOnNewDocument((b) => {
43
- localStorage.setItem('aw.twin.daqBindings', JSON.stringify(b))
44
- localStorage.setItem('aw.twin.calloutNear', '1150')
45
- }, bindings)
46
- const errors = []
47
- page.on('pageerror', e => errors.push(String(e).slice(0, 160)))
48
- await page.goto(`${BASE}/town`, { waitUntil: 'domcontentloaded', timeout: 60000 })
49
- for (let i = 0; i < 30; i++) {
50
- if (await page.evaluate(need => (window.__town?.scene?.deviceNodes?.size ?? 0) >= need, created.length)) break
51
- await new Promise(r => setTimeout(r, 1000))
52
- }
53
- await new Promise(r => setTimeout(r, 4000))
54
-
55
- const twinCount = () => page.evaluate(() => window.__town.scene.deviceNodes.size)
56
-
57
- // ---- 1) 运行模式(默认)锁 ----
58
- // 拖拽门禁:设备「底面」屏幕点起手(y=0 → 射线回投地面即设备根位置)tryStartPointerDrag → false
59
- const dragGate = await page.evaluate(() => {
60
- const s = window.__town.scene
61
- const dev = [...s.deviceNodes.values()].find(d => d.modelRef.includes('tdo'))
62
- const p = s.worldToScreen(dev.root.position.x, 0, dev.root.position.z)
63
- return s.tryStartPointerDrag(p.x, p.y)
64
- })
65
- console.log('run dragGate:', dragGate, dragGate === false ? '(OK 运行模式拒绝拖拽)' : '(FAIL 未锁)')
66
-
67
- // 投放门禁:drop 数采 → 数量不变 + 只读提示
68
- const before = await twinCount()
69
- await page.evaluate(() => {
70
- const dt = new DataTransfer()
71
- dt.setData('application/x-aw-daq', 'pressure-tx')
72
- document.querySelector('#town-host canvas').dispatchEvent(new DragEvent('drop', { dataTransfer: dt, bubbles: true, cancelable: true }))
73
- })
74
- await new Promise(r => setTimeout(r, 1200))
75
- const afterDrop = await twinCount()
76
- const hint = await page.evaluate(() => document.querySelector('.error-chip')?.textContent ?? '')
77
- console.log('run drop:', before, '→', afterDrop, afterDrop === before ? '(OK 投放被拒)' : '(FAIL 漏放)', '| hint:', hint.includes('只读') ? '(OK 提示)' : '(FAIL 无提示)')
78
-
79
- // Inspector 只读:选中设备 → 无删除钮/无绑定添加/名称禁用
80
- await page.evaluate(() => {
81
- const s = window.__town.scene
82
- const dev = [...s.deviceNodes.values()].find(d => d.modelRef.includes('tdo'))
83
- s.setSelected({ kind: 'device', id: dev.twinId })
84
- })
85
- await new Promise(r => setTimeout(r, 600))
86
- const ro = await page.evaluate(() => ({
87
- del: !!document.querySelector('.ins-del'),
88
- bindAdd: !!document.querySelector('.bind-add-wrap'),
89
- nameDisabled: document.querySelector('.obj-input')?.disabled ?? null,
90
- }))
91
- console.log('run inspector:', JSON.stringify(ro), !ro.del && !ro.bindAdd && ro.nameDisabled === true ? '(OK 只读)' : '(FAIL)')
92
-
93
- // ---- 2) 切编辑(点顶栏 seg)→ 解锁 ----
94
- await page.evaluate(() => {
95
- const btn = [...document.querySelectorAll('.topnav .seg button')].find(b => b.textContent?.includes('编辑'))
96
- btn?.click()
97
- })
98
- await new Promise(r => setTimeout(r, 500))
99
- const dragGate2 = await page.evaluate(() => {
100
- const s = window.__town.scene
101
- const dev = [...s.deviceNodes.values()].find(d => d.modelRef.includes('tdo'))
102
- const p = s.worldToScreen(dev.root.position.x, 0, dev.root.position.z)
103
- const gate = s.tryStartPointerDrag(p.x, p.y)
104
- if (gate) s.endPointerDrag()
105
- return gate
106
- })
107
- await page.evaluate(() => {
108
- const dt = new DataTransfer()
109
- dt.setData('application/x-aw-daq', 'pressure-tx')
110
- document.querySelector('#town-host canvas').dispatchEvent(new DragEvent('drop', { dataTransfer: dt, bubbles: true, cancelable: true }))
111
- })
112
- await new Promise(r => setTimeout(r, 1500))
113
- const afterDrop2 = await twinCount()
114
- const insp2 = await page.evaluate(() => ({
115
- del: !!document.querySelector('.ins-del'),
116
- nameDisabled: document.querySelector('.obj-input')?.disabled ?? null,
117
- }))
118
- console.log('edit: dragGate', dragGate2, dragGate2 ? '(OK)' : '(FAIL)', '| drop', afterDrop, '→', afterDrop2, afterDrop2 === before + 1 ? '(OK 投放成功)' : '(FAIL)', '| inspector:', JSON.stringify(insp2))
119
-
120
- // ---- 3) 小地图与视角同步 ----
121
- const meta0 = await page.evaluate(() => document.querySelector('.mm-meta')?.textContent ?? '')
122
- await page.evaluate(() => {
123
- const s = window.__town.scene
124
- for (let i = 0; i < 2; i++) s.zoomBy(-0.2)
125
- })
126
- await new Promise(r => setTimeout(r, 600))
127
- const meta1 = await page.evaluate(() => document.querySelector('.mm-meta')?.textContent ?? '')
128
- const sync = meta0.match(/×([\d.]+)/)?.[1] ?? '?'
129
- const sync1 = meta1.match(/×([\d.]+)/)?.[1] ?? '?'
130
- console.log('navSync:', sync, '→', sync1, Number(sync1) < Number(sync) ? '(OK 小地图随视角缩放)' : '(FAIL)')
131
-
132
- // ---- 4) 数采可视距离滑杆 ----
133
- await page.evaluate(() => {
134
- const s = window.__town.scene
135
- s.focusTo(1700, 600)
136
- })
137
- await new Promise(r => setTimeout(r, 1800))
138
- const nearOf = () => page.evaluate(() => [...document.querySelectorAll('.callout')].filter(c => c.classList.contains('near')).length)
139
- const n0 = await nearOf()
140
- await page.evaluate(() => {
141
- const el = [...document.querySelectorAll('.dock .ctl-row')].find(r => r.textContent?.includes('数采可视距离'))?.querySelector('input')
142
- el.value = '300'
143
- el.dispatchEvent(new Event('input', { bubbles: true }))
144
- })
145
- await new Promise(r => setTimeout(r, 500))
146
- const n1 = await nearOf()
147
- await page.evaluate(() => {
148
- const el = [...document.querySelectorAll('.dock .ctl-row')].find(r => r.textContent?.includes('数采可视距离'))?.querySelector('input')
149
- el.value = '3000'
150
- el.dispatchEvent(new Event('input', { bubbles: true }))
151
- })
152
- await new Promise(r => setTimeout(r, 500))
153
- const n2 = await nearOf()
154
- console.log('calloutDist: 1150→', n0, '张 | 300→', n1, '张 | 3000→', n2, '张',
155
- n0 >= 1 && n1 === 0 && n2 >= 1 ? '(OK 距离可控)' : '(FAIL)')
156
- // 恢复默认并等一拍
157
- await page.evaluate(() => {
158
- const el = [...document.querySelectorAll('.dock .ctl-row')].find(r => r.textContent?.includes('数采可视距离'))?.querySelector('input')
159
- el.value = '1150'
160
- el.dispatchEvent(new Event('input', { bubbles: true }))
161
- })
162
-
163
- // ---- 5) 截图(编辑模式注视设备)----
164
- await new Promise(r => setTimeout(r, 600))
165
- await page.screenshot({ path: 'docs/audit/screenshots/town-mode-nav.png' })
166
- console.log('pageerrors:', errors.length ? errors : 'none')
167
-
168
- await page.close().catch(() => {})
169
- await browser.close()
170
- for (const c of created) {
171
- await fetch(`${BASE}/api/workshop/device-twins/${c.id}`, { method: 'DELETE', headers: H }).catch(() => {})
172
- }
173
- console.log(`cleanup done (${created.length})`)
@@ -1,55 +0,0 @@
1
- [14:02:40.688] 测试凭据就绪(token=ut-64af3…)BASE=http://127.0.0.1:3000
2
- [14:02:40.841] PASS 服务可达且为多引擎版本(注册表含 codex/dsh/opencode) — harnesses=mock,omp,opencode,codex,dsh,claude,gemini,copilot,cursor,crush,goose,qwen,pi,hermes
3
- [14:02:40.879] PASS 新建产线 — line=多引擎联调线
4
- [14:02:40.891] PASS 新建 DCW 数控节点(mock 温控) — id=dw-9e8fd053
5
- [14:02:40.920] PASS 新建 DAQ 数采节点(mock 温度) — id=dn-7dac4f00 driver=mock
6
- [14:02:40.931] PASS 创建 AgentChannel(lead=omp) — channelId=b296d1d5-bf3d-4bb8-8107-6cf9946dfbe9
7
- [14:02:40.957] PASS 创建 worker-codex 并入组(harness=codex) — e45324b2-de86-43fa-aa25-3b6238c501bf
8
- [14:02:40.963] PASS 创建 worker-dsh 并入组(harness=dsh) — b8549e95-44f6-4e89-b763-8d6b09f6f642
9
- [14:02:40.986] WS 监控已接入(AEP 实时帧)
10
- [14:02:51.404] PASS 绑定 dsh↔DCW(manual,HITL 模式) — mode=manual
11
- [14:02:51.415] PASS 绑定 dsh↔DAQ(auto,数采)
12
- [14:02:51.425] PASS 绑定 codex↔DCW(manual)
13
- [14:02:51.432] FAIL dsh 工具面可见绑定节点(my_industrial_nodes) — 你尚未绑定任何工业节点。请在数字孪生界面的 Agent 详情面板中绑定数控/数采节点后再调用工业工具。
14
- [14:02:52.003] PASS 人类→codex 消息已投递 — status=200
15
- [14:02:52.028] [事件] #3 a2a.message ?→?: 兼容性检查:请用一句话汇报你正在运行的引擎类型(如 codex),然后调用 report_progress 工具上报 10% 进度(无任务上下文则忽略报错),最后原样回复"codex 在线"。
16
- [14:03:25.987] [事件] #6 a2a.artifact artifact(output)
17
- [14:03:25.987] PASS codex 回执到达(真实引擎回合) — 内容=
18
- [14:03:26.050] PASS 人类→dsh 消息已投递 — status=200
19
- [14:03:27.100] [事件] #9 a2a.message ?→?: 兼容性检查:请用一句话汇报你正在运行的引擎类型(如 dsh/ACP),然后原样回复"dsh 在线"。
20
- [14:04:05.212] [事件] #12 a2a.artifact artifact(output)
21
- [14:07:26.067] FAIL dsh 回执到达(真实引擎回合) — 240s 未回
22
- [14:07:26.164] PASS 人类→codex(要求跨引擎发信)已投递 — status=200
23
- [14:08:45.463] [事件] #22 a2a.artifact artifact(output)
24
- [14:11:26.549] FAIL codex 经工具跨引擎发信完成 — 240s 未回
25
- [14:13:27.510] FAIL dsh 侧收到 codex 来信
26
- [14:13:27.601] PASS 团队作业(goal)已提交至 lead — taskId=efd655dc-d632-468c-b9a2-4898121c4309 state=SUBMITTED
27
- [14:13:30.699] [事件] #26 task.status 温度工艺整定(数采+数控) → WORKING
28
- [14:13:30.699] [事件] #27 task.status 温度工艺整定(数采+数控) → WAITING
29
- [14:13:30.699] [事件] #28 task.status 温度工艺整定(数采+数控) → ASSIGNED
30
- [14:13:30.699] [事件] #30 task.status 温度工艺整定(数采+数控) → WORKING
31
- [14:14:40.956] [事件] #63 a2a.artifact artifact(output)
32
- [14:14:40.956] [事件] #64 task.status 温度工艺整定(数采+数控) → COMPLETED
33
- [14:14:40.956] [事件] #66 task.status 温度工艺整定(数采+数控) → WORKING
34
- [14:15:28.078] [事件] #70 task.status 温度工艺整定(数采+数控) → COMPLETED
35
- [14:15:28.078] [事件] #72 a2a.artifact artifact(goal-summary)
36
- [14:23:28.161] FAIL 数控写入触发 dcw-approval HITL(worker-dsh) — 600s 内未触发(检查 worker 是否调用了 dcw_control)
37
- [14:23:28.161] 审批从提交到出现耗时 600.56s
38
- [14:23:28.200] PASS 团队任务闭环 COMPLETED — state=COMPLETED
39
- [14:23:28.213] FAIL 写入生效:dcw_read 读回 175 附近 — 你尚未绑定任何数控节点,无权读取控制通道数据。请在数字孪生界面绑定数控节点。
40
- [14:23:28.271] PASS 超时场景消息已投递(下调 160) — status=200
41
- [14:24:29.177] [WS/hitl.request] dcw-approval: DCW 下发审批
42
- [14:24:29.177] [WS/hitl.request] dcw-approval: DCW 下发审批
43
- [14:24:29.177] [WS/hitl.request] dcw-approval: DCW 下发审批
44
- [14:24:29.501] [WS/hitl.resolved] dcw-approval outcome=answered
45
- [14:24:29.505] [WS/hitl.resolved] dcw-approval outcome=answered
46
- [14:24:29.505] [WS/hitl.resolved] dcw-approval outcome=answered
47
- [14:24:29.513] [事件] #80 hitl.request dcw-approval:DCW 下发审批
48
- [14:24:30.548] [事件] #81 hitl.resolved dcw-approval outcome=answered
49
- [14:24:49.347] [事件] #83 a2a.message ?→?: 执行结果(超时路径验证):dcw_control 对「联调温度设定器」(id=dw-9e8fd053,烘箱温度设定,℃) 下发 160.0 → 人工审批已通过并成功写入;PLC 回读 160℃,与设定一致(mock PL
50
- [14:24:59.913] [事件] #86 a2a.artifact artifact(output)
51
- [14:25:26.839] [事件] #109 a2a.artifact artifact(output)
52
- [14:28:28.313] FAIL 第二次写入触发审批 — 300s 未触发
53
- [14:28:28.313] REST 事件历史共 112 帧;WS 实时收到 180736 帧
54
- [14:28:28.313] 帧分布: {"agent.member":2,"a2a.message":3,"agent.status":23,"agent.delta":63,"a2a.artifact":7,"agent.message":4,"task.status":7,"agent.status.message":1,"hitl.request":1,"hitl.resolved":1}
55
- [14:28:28.313] PASS 事件流覆盖关键类型(task/status/message/hitl) — {"agent.member":2,"a2a.message":3,"agent.status":23,"agent.delta":63,"a2a.artifact":7,"agent.message":4,"task.status":7,"agent.status.message":1,"hitl.request":