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,101 +0,0 @@
1
- /**
2
- * 动态记忆感知测试:按需抓取(recallRows scope 过滤/原文还原/touch)、
3
- * 主动沉淀(save 私有/共享分流 + 共享域 dedupKey 命名空间)、
4
- * 记忆引子(小预算 primer + 工具提示行)。
5
- * 运行: npx tsx scripts/test-memory-dynamic.ts
6
- */
7
- import type { DatabaseSync } from 'node:sqlite'
8
- import { openWorkshopDb } from '../server/services/workshop/db/database'
9
- import { createMemoryRepo, TEAM_AGENT_ID } from '../server/services/workshop/db/memory.repo'
10
- import { AgentMemory } from '../server/services/workshop/runtime/memory'
11
-
12
- let failures = 0
13
- function check(name: string, ok: boolean, detail = ''): void {
14
- console.log(` ${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
15
- if (!ok) failures += 1
16
- }
17
-
18
- const db: DatabaseSync = openWorkshopDb(':memory:')
19
- const repo = createMemoryRepo(db)
20
- const seg = (s: string): string => s.replace(/([\u4e00-\u9fff])/g, ' $1 ')
21
-
22
- // 播种:a1 私有 × 2、a2 私有 × 1、team 公共 × 1、他 channel 的 team 行 × 1(隔离守卫)
23
- repo.upsert({ channelId: 'ch1', agentId: 'a1', kind: 'episodic-task', title: '网关限流方案', titleFts: seg('网关限流方案'), content: seg('最终采用令牌桶算法限流,阈值100qps'), importance: 0.8, taskId: 't1', dedupKey: 'task:t1' })
24
- repo.upsert({ channelId: 'ch1', agentId: 'a1', kind: 'episodic-task', title: '部署脚本草稿', titleFts: seg('部署脚本草稿'), content: seg('deploy.sh 需要先source env'), importance: 0.4, taskId: 't2', dedupKey: 'task:t2' })
25
- repo.upsert({ channelId: 'ch1', agentId: 'a2', kind: 'episodic-task', title: '他人限流笔记', titleFts: seg('他人限流笔记'), content: seg('a2自己的限流杂记'), importance: 0.8, taskId: 't3', dedupKey: 'task:t3' })
26
- repo.upsert({ channelId: 'ch1', agentId: TEAM_AGENT_ID, kind: 'semantic', title: 'channel 限流约定', titleFts: seg('channel 限流约定'), content: seg('全channel统一用令牌桶,禁用计数器'), importance: 0.9, taskId: null, dedupKey: 'conv:ratelimit' })
27
- repo.upsert({ channelId: 'ch2', agentId: TEAM_AGENT_ID, kind: 'semantic', title: '他channel限流约定', titleFts: seg('他channel限流约定'), content: seg('ch2专属公共记忆不应被ch1看到'), importance: 0.9, taskId: null, dedupKey: 'conv:other' })
28
-
29
- const memA1 = new AgentMemory(repo, { channelId: 'ch1', agentId: 'a1' })
30
-
31
- console.log('--- 按需抓取 recallRows ---')
32
- {
33
- const auto = await memA1.recallRows('限流 令牌桶')
34
- check('auto 域命中本人 + 公共记忆', auto.some(s => s.title === '网关限流方案') && auto.some(s => s.title === 'channel 限流约定'), JSON.stringify(auto.map(s => s.title)))
35
- check('auto 域不含他人私有记忆', auto.every(s => s.title !== '他人限流笔记'))
36
- check('auto 域不含他 channel 公共记忆', auto.every(s => s.title !== '他channel限流约定'))
37
- check('source 标注 private/shared', auto.some(s => s.source === 'private') && auto.some(s => s.source === 'shared'))
38
- const own = auto.find(s => s.title === '网关限流方案')
39
- check('content 还原为未切分原文', own !== undefined && !/\s/.test(own.content.slice(0, 4)) && own.content.includes('令牌桶'), own?.content.slice(0, 20))
40
- check('返回综合分 score', auto.every(s => typeof s.score === 'number' && s.score > 0))
41
-
42
- const sharedOnly = await memA1.recallRows('限流', { scope: 'shared' })
43
- check('shared 域仅公共记忆', sharedOnly.length > 0 && sharedOnly.every(s => s.source === 'shared'), JSON.stringify(sharedOnly.map(s => s.title)))
44
- check('shared 域严格本 channel', sharedOnly.every(s => s.title !== '他channel限流约定'))
45
-
46
- const privOnly = await memA1.recallRows('限流', { scope: 'private' })
47
- check('private 域仅本人记忆', privOnly.length > 0 && privOnly.every(s => s.source === 'private'), JSON.stringify(privOnly.map(s => s.title)))
48
-
49
- const before = repo.listByAgent('a1', 10).find(r => r.title === '网关限流方案')!.accessCount
50
- await memA1.recallRows('网关 限流')
51
- const after = repo.listByAgent('a1', 10).find(r => r.title === '网关限流方案')!.accessCount
52
- check('recallRows 触发 touch(强化后续排序)', after === before + 1, `before=${before} after=${after}`)
53
-
54
- // scope 域内完全无记忆才真正返回空(全新 channel;有记忆时弱命中/时近兜底会返回行,by design)
55
- const none = await new AgentMemory(repo, { channelId: 'ch-empty', agentId: 'nobody' }).recallRows('完全不存在的关键词xyzq')
56
- check('无命中返回空数组(无记忆 agent)', Array.isArray(none) && none.length === 0)
57
- const fallback = await memA1.recallRows('完全不存在的关键词xyzq')
58
- check('FTS 无命中走时近兜底(有记忆 agent 返回最近行)', fallback.length > 0, JSON.stringify(fallback.map(s => s.title)))
59
- }
60
-
61
- console.log('\n--- 主动沉淀 save(私有/共享分流)---')
62
- {
63
- const priv = await memA1.save({ title: 'SQLite 并发写坑', content: '并发写会 SQLITE_BUSY,须串行化写入', scope: 'private', dedupKey: 'note:sqlite' })
64
- check('私有沉淀落入本人域', repo.findByAgentDedup('ch1', 'a1', 'note:sqlite') !== null && priv.scope === 'private')
65
-
66
- const shared = await memA1.save({ title: '限流阈值结论', content: '全队统一令牌桶阈值100qps', scope: 'shared', dedupKey: 'conv:threshold' })
67
- const teamRow = repo.findByAgentDedup('ch1', TEAM_AGENT_ID, `agent:a1:conv:threshold`)
68
- check('共享沉淀落入 team 公共域(来源命名空间 dedupKey)', teamRow !== null && shared.dedupKey === 'agent:a1:conv:threshold')
69
-
70
- // 同 raw key 不同 agent:命名空间隔离互不覆盖
71
- const memA2 = new AgentMemory(repo, { channelId: 'ch1', agentId: 'a2' })
72
- await memA2.save({ title: 'a2 的阈值结论', content: 'a2认为阈值应按服务分级', scope: 'shared', dedupKey: 'conv:threshold' })
73
- const teamRows = repo.listByAgentChannel('ch1', TEAM_AGENT_ID, 100).filter(r => r.content.includes('阈值') || r.title.includes('阈值'))
74
- check('多 agent 同 raw key 共享沉淀互不覆盖', repo.findByAgentDedup('ch1', TEAM_AGENT_ID, 'agent:a1:conv:threshold') !== null && repo.findByAgentDedup('ch1', TEAM_AGENT_ID, 'agent:a2:conv:threshold') !== null, `rows=${teamRows.length}`)
75
-
76
- // 共享沉淀即时对全员可检索
77
- const a2sees = await memA2.recallRows('阈值 令牌桶', { scope: 'shared' })
78
- check('共享沉淀对其他 agent 即时可检索', a2sees.some(s => s.title === '限流阈值结论'), JSON.stringify(a2sees.map(s => s.title)))
79
-
80
- // 稳定 dedupKey 幂等刷新不重复
81
- await memA1.save({ title: '限流阈值结论', content: '修订:阈值升到200qps', scope: 'shared', dedupKey: 'conv:threshold' })
82
- const count = repo.listByAgentChannel('ch1', TEAM_AGENT_ID, 100).filter(r => r.dedupKey === undefined && r.title === '限流阈值结论').length
83
- const refreshed = repo.listByAgentChannel('ch1', TEAM_AGENT_ID, 100).some(r => r.title === '限流阈值结论')
84
- check('稳定 dedupKey 幂等刷新', refreshed && count <= 1)
85
- }
86
-
87
- console.log('\n--- 记忆引子 primer(小预算注入)---')
88
- {
89
- const block = await memA1.recall('限流 令牌桶 部署', { touch: false })
90
- check('primer 返回记忆块', block !== null)
91
- check('primer 含按需抓取工具提示', block !== null && block.includes('search_memory'), block?.slice(-80))
92
- // v2 三层注入:L0 简报(save(shared) 后自动存在)+ L1 引子 + 提示,同在 300 tok 引子预算 + 500 tok 总预算内
93
- check('primer 含 L0 会话简报', block !== null && block.includes('会话简报'))
94
- check('primer 小预算(行数受限)', block !== null && block.split('\n').length < 16, `lines=${block?.split('\n').length}`)
95
-
96
- const memTiny = new AgentMemory(repo, { channelId: 'ch1', agentId: 'a1', budgetTokens: 5 })
97
- check('极小预算 primer 无行则 null', (await memTiny.recall('限流')) === null)
98
- }
99
-
100
- console.log(failures === 0 ? '\nALL PASS' : `\n${failures} FAILED`)
101
- process.exit(failures === 0 ? 0 : 1)
@@ -1,14 +0,0 @@
1
- {
2
- "schemaVersion": "mimosa-hook-status/v1",
3
- "recordedAt": "2026-09-12T02:04:56.653Z",
4
- "sessionId": "sess_aeaecb58-8833-4b83-b93c-050467d21e03",
5
- "event": "PostToolUse",
6
- "toolName": "Write",
7
- "file": "D:\\codes\\ABO\\AgentWorkShop\\docs\\full-test-plan.md",
8
- "outcome": "clear",
9
- "coverage": "complete",
10
- "findingCount": 0,
11
- "durationMs": 4,
12
- "hostState": "hook_complete",
13
- "reportHint": ".mimosa/reports/"
14
- }
@@ -1,43 +0,0 @@
1
- /** 全站巡检截图:8 个主页面一次采齐。 */
2
- import puppeteer from 'puppeteer-core'
3
-
4
- const ROOT = 'http://127.0.0.1:3000'
5
- const sleep = ms => new Promise(r => setTimeout(r, ms))
6
-
7
- const login = await fetch(`${ROOT}/api/users/login`, {
8
- method: 'POST',
9
- headers: { 'content-type': 'application/json' },
10
- body: JSON.stringify({ email: process.env.E2E_USER ?? 'zhangwei@awshop.io', password: process.env.E2E_PASS ?? 'Awshop@123' }),
11
- }).then(r => r.json())
12
- if (!login.data?.token) { console.error('login failed'); process.exit(1) }
13
-
14
- const browser = await puppeteer.launch({
15
- executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
16
- headless: 'new',
17
- args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'],
18
- })
19
- const page = await browser.newPage()
20
- await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1.25 })
21
- await page.setCookie({ name: 'token', value: login.data.token, domain: '127.0.0.1', path: '/' })
22
-
23
- const shots = [
24
- ['/', 'audit-home'],
25
- ['/daq', 'audit-daq'],
26
- ['/dcw', 'audit-dcw'],
27
- ['/workshop', 'audit-workshop'],
28
- ['/monitor', 'audit-monitor'],
29
- ['/users', 'audit-users'],
30
- ['/settings', 'audit-settings'],
31
- ]
32
- for (const [path, name] of shots) {
33
- try {
34
- await page.goto(`${ROOT}${path}`, { waitUntil: 'domcontentloaded', timeout: 45000 })
35
- await sleep(name === 'audit-workshop' ? 9000 : 5000)
36
- await page.screenshot({ path: `docs/audit/screenshots/redesign0831/${name}.png`, fullPage: name !== 'audit-workshop' })
37
- console.log('ok', name)
38
- } catch (e) {
39
- console.error('FAIL', name, e.message.slice(0, 80))
40
- }
41
- }
42
- await browser.close()
43
- console.log('DONE')
@@ -1,118 +0,0 @@
1
- /**
2
- * 一次性 E2E:多形态数采帧管线 mock 场景活体验证(向量/图像)。
3
- * 前置:dev server(AW_HOME 隔离)跑在本脚本 ROOT;MinIO/Timescale/Mosquitto 可达。
4
- * ①登录拿 token → ②开跑产线 → ③建 thickness-scan(vector)/ccd-image(image)节点
5
- * → ④轮询 daq_frames REST:向量含点列+派生指标,图像含对象引用
6
- * → ⑤图像 content 端点回 PNG 字节 → ⑥scalar 节点零污染(daq_samples 查询无该节点)
7
- * → ⑦停线(帧冻结)+ 清理节点。
8
- * 运行: node scripts/_dbg-daq-frames-e2e.mjs
9
- */
10
- const ROOT = process.env.E2E_ROOT ?? 'http://127.0.0.1:3100'
11
- const sleep = ms => new Promise(r => setTimeout(r, ms))
12
- const fail = (msg) => { console.error('FAIL:', msg); process.exitCode = 1 }
13
-
14
- // ===== 登录(Bearer token 面已足够;daq REST resolveUser 接受 Bearer)=====
15
- const login = await fetch(`${ROOT}/api/users/login`, {
16
- method: 'POST',
17
- headers: { 'content-type': 'application/json' },
18
- body: JSON.stringify({ email: process.env.E2E_USER ?? 'zhangwei@awshop.io', password: process.env.E2E_PASS ?? 'Awshop@123' }),
19
- }).then(r => r.json())
20
- const token = login?.data?.token
21
- if (!token) { console.error('FAIL: login:', JSON.stringify(login).slice(0, 200)); process.exit(1) }
22
- const H = { authorization: `Bearer ${token}`, 'content-type': 'application/json' }
23
- const j = (u, m = 'GET', b) => fetch(ROOT + u, { method: m, headers: H, body: b ? JSON.stringify(b) : undefined }).then(r => r.json())
24
-
25
- // ===== 0. infra/meta:对象存储后端可见 =====
26
- const meta0 = (await j('/api/workshop/daq')).data
27
- console.log('meta.infra:', JSON.stringify(meta0.meta.infra ?? {}).slice(0, 160))
28
- console.log('meta.backends:', JSON.stringify(meta0.meta.backends ?? meta0.meta))
29
- const created = []
30
- try {
31
- // ===== 1. 选产线 + 开跑(任一有配方的产线)=====
32
- const d = (await j('/api/workshop/dcw')).data
33
- const cand = d.lines.map(l => ({ line: l, recipe: d.recipes.find(r => r.lineId === l.id) })).find(x => x.recipe)
34
- if (!cand) { console.error('FAIL: 无可开跑产线(无配方)'); process.exit(1) }
35
- const stop = await j(`/api/workshop/dcw/lines/${cand.line.id}/stop`, 'POST').catch(() => {})
36
- await sleep(1200)
37
- const st = await j(`/api/workshop/dcw/lines/${cand.line.id}/start`, 'POST', { recipeId: cand.recipe.id })
38
- if (!st.data?.line?.active) { console.error('FAIL: line start:', JSON.stringify(st).slice(0, 200)); process.exit(1) }
39
- console.log('line started:', cand.line.name, '| recipe:', cand.recipe.name)
40
-
41
- // ===== 2. 建向量/图像节点(挂产线)=====
42
- const mk = async (templateRef, name) => {
43
- const r = await j('/api/workshop/daq', 'POST', { templateRef, lineId: cand.line.id, name })
44
- if (!r.data?.node?.id) { console.error('FAIL: create node:', JSON.stringify(r).slice(0, 200)); process.exit(1) }
45
- created.push(r.data.node.id)
46
- console.log(`node ${name}: ${r.data.node.id}`)
47
- return r.data.node.id
48
- }
49
- const vecId = await mk('thickness-scan', 'E2E 测厚扫描')
50
- const imgId = await mk('ccd-image', 'E2E CCD 相机')
51
-
52
- // ===== 3. 等帧入库(1s 节拍 × 若干 + 500ms 刷盘窗)=====
53
- let vecFrames = []
54
- let imgFrames = []
55
- for (let i = 0; i < 20; i++) {
56
- await sleep(2000)
57
- vecFrames = (await j(`/api/workshop/daq/${vecId}/frames?limit=10`)).data.frames
58
- imgFrames = (await j(`/api/workshop/daq/${imgId}/frames?limit=10`)).data.frames
59
- if (vecFrames.length >= 3 && imgFrames.length >= 3) break
60
- }
61
- // 向量断言
62
- if (vecFrames.length >= 3) {
63
- const f = vecFrames[0]
64
- if (f.kind === 'vector' && (f.points?.length ?? 0) === 64) console.log(`PASS 向量帧: ${vecFrames.length} 帧,64 点/帧`)
65
- else fail(`vector frame shape: kind=${f.kind} points=${f.points?.length}`)
66
- if (Number.isFinite(f.metrics.avg) && Number.isFinite(f.metrics.max)) console.log(`PASS 向量派生指标: avg=${f.metrics.avg} max=${f.metrics.max}`)
67
- else fail(`vector metrics: ${JSON.stringify(f.metrics)}`)
68
- if (f.lineId === cand.line.id) console.log('PASS 帧产线打标: lineId 继承')
69
- else fail(`frame lineId=${f.lineId} expect ${cand.line.id}`)
70
- } else fail(`vector frames insufficient: ${vecFrames.length}`)
71
- // 图像断言
72
- if (imgFrames.length >= 3) {
73
- const f = imgFrames[0]
74
- if (f.kind === 'image' && f.meta?.objectKey && f.meta?.thumbKey) console.log(`PASS 图像帧: ${imgFrames.length} 帧,对象键 ${String(f.meta.objectKey).slice(0, 40)}…`)
75
- else fail(`image frame meta: ${JSON.stringify(f.meta)}`)
76
- if (Number.isFinite(f.metrics.brightness)) console.log(`PASS 图像派生指标: brightness=${f.metrics.brightness} contrast=${f.metrics.contrast}`)
77
- else fail(`image metrics: ${JSON.stringify(f.metrics)}`)
78
- if (f.thumbUrl) console.log('PASS 缩略图 URL:', f.thumbUrl)
79
- else fail('image thumbUrl missing')
80
- } else fail(`image frames insufficient: ${imgFrames.length}`)
81
-
82
- // ===== 4. 图像 content 端点回 PNG 字节 =====
83
- if (imgFrames[0]) {
84
- const res = await fetch(`${ROOT}${imgFrames[0].thumbUrl}`, { headers: { authorization: H.authorization } })
85
- const buf = Buffer.from(await res.arrayBuffer())
86
- const pngMagic = buf.subarray(0, 4).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47]))
87
- if (res.ok && pngMagic && buf.length > 50) console.log(`PASS 图像 content: HTTP ${res.status},${buf.length} 字节,PNG 魔数 ✓ (${res.headers.get('content-type')})`)
88
- else fail(`content: HTTP ${res.status} len=${buf.length} png=${pngMagic}`)
89
- const full = await fetch(`${ROOT}${imgFrames[0].contentUrl}`, { headers: { authorization: H.authorization } })
90
- const fbuf = Buffer.from(await full.arrayBuffer())
91
- if (full.ok && fbuf.length > imgFrames[0] ? true : fbuf.length > 0) console.log(`PASS 主图 content: ${fbuf.length} 字节(≥缩略图 ${fbuf.length >= buf.length ? '✓' : '✗'})`)
92
- else fail(`full content: HTTP ${full.status}`)
93
- }
94
-
95
- // ===== 5. 标量表零污染:向量/图像节点在 daq_samples 无行 =====
96
- for (const [label, id] of [['vector', vecId], ['image', imgId]]) {
97
- const pts = (await j(`/api/workshop/daq/${id}/samples?limit=10`)).data.points
98
- if (pts.length === 0) console.log(`PASS 标量表零污染(${label}): daq_samples 无该节点行`)
99
- else fail(`scalar pollution (${label}): ${pts.length} rows`)
100
- }
101
-
102
- // ===== 6. WS daq.frame(可选:浏览器外裸 WS 需应用源;此处跳过,REST 已覆盖管线)=====
103
-
104
- // ===== 7. 停线:帧冻结 =====
105
- await j(`/api/workshop/dcw/lines/${cand.line.id}/stop`, 'POST')
106
- await sleep(2500)
107
- const after = (await j(`/api/workshop/daq/${vecId}/frames?limit=5`)).data.frames
108
- await sleep(3000)
109
- const after2 = (await j(`/api/workshop/daq/${vecId}/frames?limit=5`)).data.frames
110
- if (after[0]?.at === after2[0]?.at) console.log('PASS 停线帧冻结: 最新帧时间不再推进')
111
- else fail(`frames still flowing after stop: ${after[0]?.at} → ${after2[0]?.at}`)
112
- } finally {
113
- // ===== 清理:删节点 + 停线兜底 =====
114
- for (const id of created) await j(`/api/workshop/daq/${id}`, 'DELETE').catch(() => {})
115
- console.log(`cleanup: removed ${created.length} nodes`)
116
- }
117
-
118
- console.log(process.exitCode ? '\nE2E FAILED' : '\nE2E ALL PASS')
@@ -1,112 +0,0 @@
1
- /** 一次性验证:①数采节点表行样式与表头/其它列表一致(行组件 scoped 隔离修复);
2
- * ②系统设置里三个独立节拍(采集/WS 下发/趋势刷新)的默认值与下限可独立设定。 */
3
- import puppeteer from 'puppeteer-core'
4
-
5
- const BASE = process.env.AW_BASE ?? 'http://127.0.0.1:3001'
6
- const OUT = process.env.AW_OUT ?? '.e2e-shots/rowstyle'
7
- const EMAIL = process.env.E2E_USER ?? 'zhangwei@awshop.io'
8
- const PASS = process.env.E2E_PASS ?? 'Awshop@123'
9
-
10
- const login = await fetch(`${BASE}/api/users/login`, {
11
- method: 'POST',
12
- headers: { 'content-type': 'application/json' },
13
- body: JSON.stringify({ email: EMAIL, password: PASS }),
14
- }).then(r => r.json())
15
- const token = login?.data?.token
16
- if (!token) { console.error('登录失败', login); process.exit(1) }
17
- console.log(`· 登录 ${login.data.user.name}(${login.data.user.role})`)
18
-
19
- const browser = await puppeteer.launch({
20
- executablePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
21
- headless: 'new',
22
- args: ['--no-sandbox', '--disable-gpu', '--window-size=1760,1100'],
23
- })
24
- const page = await browser.newPage()
25
- await page.setViewport({ width: 1760, height: 1100 })
26
- await page.setCookie({ name: 'token', value: token, domain: '127.0.0.1', path: '/' })
27
-
28
- let fail = 0
29
- const check = (name, ok, extra = '') => {
30
- console.log(`${ok ? '✔' : '✖'} ${name}${extra ? ` — ${extra}` : ''}`)
31
- if (!ok) fail++
32
- }
33
-
34
- // ---------- ① 数采列表行样式 ----------
35
- await page.goto(`${BASE}/daq`, { waitUntil: 'domcontentloaded', timeout: 90_000 })
36
- await page.waitForFunction(() => document.querySelectorAll('.nodes-table tbody tr td b').length > 3, { timeout: 60_000 })
37
- await new Promise(r => setTimeout(r, 2500))
38
-
39
- const probe = await page.evaluate(() => {
40
- const th = document.querySelector('.nodes-table thead th')
41
- const row = document.querySelector('.nodes-table tbody tr')
42
- const tds = [...(row?.querySelectorAll('td') ?? [])]
43
- const cs = el => el ? getComputedStyle(el) : null
44
- const thCs = cs(th), td0 = cs(tds[0])
45
- const pill = row?.querySelector('.st-pill')
46
- const trend = row?.querySelector('.trend')
47
- const drv = row?.querySelector('.drv-tag')
48
- const toggle = row?.querySelector('.node-toggle')
49
- const sel = row?.querySelector('.line-sel')
50
- const runPill = row?.querySelector('.run-pill')
51
- return {
52
- rows: document.querySelectorAll('.nodes-table tbody tr').length,
53
- cols: tds.length,
54
- thPadding: thCs ? `${thCs.paddingTop}/${thCs.paddingLeft}` : null,
55
- tdPadding: td0 ? `${td0.paddingTop}/${td0.paddingLeft}` : null,
56
- tdBorder: td0?.borderBottomWidth ?? null,
57
- pill: pill ? { display: getComputedStyle(pill).display, bg: getComputedStyle(pill).backgroundColor, radius: getComputedStyle(pill).borderRadius } : null,
58
- trend: trend ? { w: getComputedStyle(trend).width, h: getComputedStyle(trend).height } : null,
59
- drv: drv ? { border: getComputedStyle(drv).borderTopWidth, radius: getComputedStyle(drv).borderRadius } : null,
60
- toggle: toggle ? { display: getComputedStyle(toggle).display, cursor: getComputedStyle(toggle).cursor } : null,
61
- sel: sel ? { maxWidth: getComputedStyle(sel).maxWidth } : null,
62
- runPill: runPill ? { display: getComputedStyle(runPill).display, radius: getComputedStyle(runPill).borderRadius } : null,
63
- }
64
- })
65
- console.log(JSON.stringify(probe, null, 1))
66
- check('行数 > 3(真实节点)', probe.rows > 3, `rows=${probe.rows}`)
67
- check('行单元格列数 = 12', probe.cols === 12, `cols=${probe.cols}`)
68
- check('行单元格 padding 与表头一致', probe.tdPadding === probe.thPadding && probe.tdPadding === '9px/12px', `th=${probe.thPadding} td=${probe.tdPadding}`)
69
- check('行单元格有分隔线', probe.tdBorder !== '0px', probe.tdBorder)
70
- check('状态 pill 有底色+胶囊圆角', !!probe.pill && probe.pill.bg !== 'rgba(0, 0, 0, 0)' && probe.pill.radius !== '0px', JSON.stringify(probe.pill))
71
- check('趋势图 120x26', probe.trend?.w === '120px' && probe.trend?.h === '26px', JSON.stringify(probe.trend))
72
- check('驱动标签为 chip', probe.drv?.border === '1px' && probe.drv?.radius !== '0px', JSON.stringify(probe.drv))
73
- check('启停按钮 inline-flex+pointer', probe.toggle?.display === 'inline-flex' && probe.toggle?.cursor === 'pointer', JSON.stringify(probe.toggle))
74
- check('产线下拉 max-width 120px', probe.sel?.maxWidth === '120px', JSON.stringify(probe.sel))
75
- check('产线运行 pill 胶囊化', probe.runPill?.display === 'inline-flex' && probe.runPill?.radius !== '0px', JSON.stringify(probe.runPill))
76
- await page.screenshot({ path: `${OUT}-list.png` })
77
-
78
- // ---------- ② 系统设置:三个独立节拍 ----------
79
- await page.goto(`${BASE}/settings`, { waitUntil: 'domcontentloaded', timeout: 90_000 })
80
- await new Promise(r => setTimeout(r, 1500))
81
- await page.evaluate(() => {
82
- const tab = [...document.querySelectorAll('button,a,div')].find(el => el.textContent?.trim() === '运行时配置')
83
- tab?.click()
84
- })
85
- await page.waitForFunction(() => document.body.textContent?.includes('WS 下发默认间隔'), { timeout: 30_000 }).catch(() => {})
86
- const rt = await page.evaluate(() => {
87
- const txt = document.body.textContent ?? ''
88
- const labels = ['节点采样默认间隔(ms)', '节点采样下限(ms)', 'WS 下发默认间隔(ms)', 'WS 下发下限(ms)', '趋势图刷新间隔(ms)', '趋势图刷新下限(ms)']
89
- const rows = [...document.querySelectorAll('.rt-row')]
90
- const find = label => {
91
- const r = rows.find(el => el.querySelector('.rt-title')?.textContent?.includes(label))
92
- const inp = r?.querySelector('input')
93
- return inp ? { min: inp.getAttribute('aria-valuemin'), max: inp.getAttribute('aria-valuemax'), value: inp.value } : null
94
- }
95
- return {
96
- has: Object.fromEntries(labels.map(l => [l, txt.includes(l)])),
97
- intervals: Object.fromEntries(labels.map(l => [l, find(l)])),
98
- }
99
- })
100
- console.log(JSON.stringify(rt, null, 1))
101
- for (const [k, v] of Object.entries(rt.has)) check(`设置项存在「${k}」`, v)
102
- const iv = rt.intervals
103
- check('采集:默认 5000 / 下限 1000', iv['节点采样默认间隔(ms)']?.value === '5000' && iv['节点采样下限(ms)']?.value === '1000', JSON.stringify(iv['节点采样默认间隔(ms)']))
104
- check('WS 下发:默认 1000 / 下限 0(独立)', iv['WS 下发默认间隔(ms)']?.value === '1000' && iv['WS 下发下限(ms)']?.value === '0', JSON.stringify(iv['WS 下发默认间隔(ms)']))
105
- check('趋势刷新:默认 5000 / 下限 500(独立)', iv['趋势图刷新间隔(ms)']?.value === '5000' && iv['趋势图刷新下限(ms)']?.value === '500', JSON.stringify(iv['趋势图刷新间隔(ms)']))
106
- const minAttrs = ['节点采样下限(ms)', 'WS 下发下限(ms)', '趋势图刷新下限(ms)'].map(k => iv[k]?.min)
107
- check('三组下限各自独立挂在输入框 min 上', new Set(minAttrs).size === 3, `aria-valuemin=${minAttrs.join(' / ')}`)
108
- await page.screenshot({ path: `${OUT}-settings.png` })
109
-
110
- await browser.close()
111
- console.log(fail === 0 ? '全部通过' : `失败 ${fail} 项`)
112
- process.exit(fail === 0 ? 0 : 1)
@@ -1,93 +0,0 @@
1
- /** HITL 超时默认拒绝 E2E(需 HITL_TIMEOUT_MS=5000 的 server):挂起→到期→自动拒绝→Agent 收到保持原值语义。 */
2
- const ROOT = 'http://127.0.0.1:3100'
3
- const H = { authorization: 'Bearer ut-ffc1dfbbc0c1444c87c1ec69a9e8208c', 'content-type': 'application/json' }
4
- const sleep = ms => new Promise(r => setTimeout(r, ms))
5
- const fail = m => { console.error('FAIL:', m); process.exitCode = 1 }
6
- const jget = u => fetch(ROOT + u, { headers: H }).then(r => r.json())
7
- const jpost = (u, b) => fetch(ROOT + u, { method: 'POST', headers: H, body: JSON.stringify(b ?? {}) }).then(r => r.json())
8
- const jdel = u => fetch(ROOT + u, { method: 'DELETE', headers: H }).then(r => r.json())
9
-
10
- const cleanup = []
11
- async function main() {
12
- // 1. 产线 + 数采/数控 + 配方 + 开跑(dcw_control 需要产线运行窗口)
13
- const line = (await jpost('/api/workshop/dcw/lines', { name: 'HITL超时验证线' })).data.line
14
- cleanup.push(['line', line.id])
15
- const dq = (await jpost('/api/workshop/daq', { templateRef: 'daq-temp-tc', name: 'HITL温度采集', lineId: line.id, intervalMs: 500 })).data.node
16
- const dw = (await jpost('/api/workshop/dcw', { templateRef: 'dcw-temp-sp', name: 'HITL温度设定', lineId: line.id })).data.node
17
- cleanup.push(['daq', dq.id], ['dcw', dw.id])
18
- const prod = (await jpost('/api/workshop/dcw/products', { name: 'HITL验证产品', lineId: line.id })).data.product
19
- cleanup.push(['product', prod.id])
20
- const rc = (await jpost('/api/workshop/dcw/recipes', {
21
- productId: prod.id, name: 'HITL验证配方',
22
- params: [{ templateRef: 'dcw-temp-sp', nodeId: dw.id, value: 180, min: 170, max: 190 }],
23
- daqWindows: [],
24
- })).data.recipe
25
- cleanup.push(['recipe', rc.id])
26
- const st = await jpost(`/api/workshop/dcw/lines/${line.id}/start`, { recipeId: rc?.id })
27
- if (!st.data?.line?.active) { fail('产线开跑失败: ' + JSON.stringify(st).slice(0, 120)); return }
28
- console.log('[产线] 已开跑,设定节点目标 180')
29
-
30
- // 2. 团队 + 部署 + manual 绑定
31
- const ch = (await jpost('/api/workshop/channels', { name: 'HITL超时验证' })).data
32
- cleanup.push(['channel', ch.channelId])
33
- const team = (await jpost('/api/workshop/teams', { name: 'HITL超时验证组' })).data
34
- cleanup.push(['team', team.id])
35
- await jpost(`/api/workshop/teams/${team.id}/members`, { agentId: 'tpl-default-lead', role: 'lead' })
36
- const w = (await jpost('/api/workshop/agents', {
37
- name: 'HITL验证worker', harness: 'omp',
38
- config: { intro: '验证用', systemPromptPrefix: '验证 HITL 超时默认拒绝。' },
39
- })).data
40
- cleanup.push(['agent', w.id])
41
- await jpost(`/api/workshop/teams/${team.id}/members`, { agentId: w.id, role: 'worker' })
42
- await jpost(`/api/workshop/teams/${team.id}/deploy`, { channelId: ch.channelId })
43
- const inst = (await jget(`/api/workshop/channels/${ch.channelId}/agents`)).data.find(a => a.role === 'worker')
44
- cleanup.push(['cagent', `${ch.channelId}:${inst.id}`])
45
- await jpost('/api/workshop/agent-tools/bindings', { agentId: inst.id, nodeId: dw.id, kind: 'dcw', mode: 'manual' })
46
- console.log('[部署] worker 实例就绪,manual 绑定智控节点')
47
-
48
- // 3. 发起 dcw_control(不 await 完成态)→ 审批应挂起且带 expiresAt
49
- const invokeP = jpost('/api/workshop/agent-tools/invoke', { agentId: inst.id, tool: 'dcw_control', args: { node_id: dw.id, value: 185 } })
50
- await sleep(1500)
51
- const pend = (await jget(`/api/workshop/agent-tools/approvals?agentId=${inst.id}`)).data.approvals
52
- const ap = pend.find(a => a.nodeId === dw.id)
53
- if (!ap) { fail('审批未挂起'); return }
54
- const ttl = Math.round((Date.parse(ap.expiresAt) - Date.now()) / 1000)
55
- console.log(`[审批] 挂起成功 expiresAt 剩余 ${ttl}s`, ttl > 0 && ttl <= 6 ? 'PASS(短超时窗生效)' : `FAIL(期望 ≤6s)`)
56
- if (!(ttl > 0 && ttl <= 6)) fail('expiresAt/超时窗不符')
57
-
58
- // 4. 等超时(5s 窗 + 余量)→ invoke 应以「默认拒绝」收敛
59
- const res = await Promise.race([invokeP, sleep(15000).then(() => null)])
60
- const text = res?.data?.result?.text ?? JSON.stringify(res).slice(0, 200)
61
- const rejected = !res ? 'TIMEOUT' : ((text.includes('超时') || text.includes('拒绝')) && text.includes('指令未执行'))
62
- console.log('[超时] 工具结果:', text.slice(0, 140))
63
- console.log('[超时] 默认拒绝语义:', rejected === true ? 'PASS(超时→拒绝→指令未执行)' : 'FAIL')
64
- if (rejected !== true) fail('超时未按默认拒绝收敛')
65
-
66
- // 5. 历史留痕:expired 状态可查(scope=history)
67
- const hist = (await jget('/api/workshop/agent-tools/approvals?scope=history&limit=10')).data?.approvals ?? []
68
- const exp = Array.isArray(hist) ? hist.find(x => x.id === ap.id && x.status === 'expired') : null
69
- console.log('[留痕] expired 历史记录:', exp ? 'PASS' : `WARN(未查到: ${JSON.stringify(hist).slice(0, 100)})`)
70
-
71
- // 6. 节点值未被改动(默认拒绝 = 指令不执行)
72
- const dwNow = (await jget('/api/workshop/dcw')).data.nodes.find(n => n.id === dw.id)
73
- console.log(`[语义] 设定值保持 ${dwNow.value}(应 ≈180 配方目标)`, Math.abs(dwNow.value - 180) < 0.01 ? 'PASS' : 'FAIL')
74
- if (Math.abs(dwNow.value - 180) >= 0.01) fail('超时拒绝后设定值被意外改动')
75
- }
76
-
77
- main().then(async () => {
78
- for (const [kind, id] of [...cleanup].reverse()) {
79
- try {
80
- if (kind === 'line') await jpost(`/api/workshop/dcw/lines/${id}/stop`, {})
81
- else if (kind === 'daq') await jdel(`/api/workshop/daq/${id}`)
82
- else if (kind === 'dcw') await jdel(`/api/workshop/dcw/${id}`)
83
- else if (kind === 'recipe') await jdel(`/api/workshop/dcw/recipes/${id}`)
84
- else if (kind === 'product') await jdel(`/api/workshop/dcw/products/${id}`)
85
- else if (kind === 'cagent') { const [c, a] = String(id).split(':'); await jdel(`/api/workshop/channels/${c}/agents/${a}`) }
86
- else if (kind === 'channel') await jdel(`/api/workshop/channels/${id}`)
87
- else if (kind === 'team') await jdel(`/api/workshop/teams/${id}`)
88
- else if (kind === 'agent') await jdel(`/api/workshop/agents/${id}`)
89
- } catch { /* 尽力清理 */ }
90
- }
91
- console.log(process.exitCode ? 'HITL E2E FAILED' : 'HITL E2E ALL PASS')
92
- process.exit(process.exitCode ?? 0)
93
- })