agentworkshop 0.7.23 → 0.7.27

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 (344) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/0jKrzLuM.js +19 -0
  3. package/.output/public/_nuxt/2jaJHWIJ.js +1 -0
  4. package/.output/public/_nuxt/{Cor9siSf.js → 6PZPfFcO.js} +1 -1
  5. package/.output/public/_nuxt/B7gZokg82.js +209 -0
  6. package/.output/public/_nuxt/B8kt898d.js +1 -0
  7. package/.output/public/_nuxt/{B-xskWta.js → BCJFMBQ6.js} +1 -1
  8. package/.output/public/_nuxt/BFGpEo8S.js +1 -0
  9. package/.output/public/_nuxt/BG4zduPf.js +14 -0
  10. package/.output/public/_nuxt/{DNxVTfhe.js → BGhOrgle.js} +1 -1
  11. package/.output/public/_nuxt/{n3vMFfrv.js → BHcpzI2n.js} +3 -3
  12. package/.output/public/_nuxt/{CEHmSufQ.js → BTLEvDxM.js} +1 -1
  13. package/.output/public/_nuxt/{CYBq3kS7.js → BWyR3awA.js} +1 -1
  14. package/.output/public/_nuxt/Bc89zKq2.js +1 -0
  15. package/.output/public/_nuxt/BetmGSO4.js +1 -0
  16. package/.output/public/_nuxt/{DAR70Lf5.js → BgCrZKv_2.js} +1 -1
  17. package/.output/public/_nuxt/BowTbasd.js +1 -0
  18. package/.output/public/_nuxt/BvtknqSC2.js +1 -0
  19. package/.output/public/_nuxt/CJviSvm-.js +1 -0
  20. package/.output/public/_nuxt/CTfqWGdy.js +1 -0
  21. package/.output/public/_nuxt/Cb3SnTM8.js +1 -0
  22. package/.output/public/_nuxt/Chc5pfAA.js +1 -0
  23. package/.output/public/_nuxt/CmHzfVc5.js +3 -0
  24. package/.output/public/_nuxt/Cn3J3NXR.js +23 -0
  25. package/.output/public/_nuxt/CobSUzQv.js +2 -0
  26. package/.output/public/_nuxt/{kZV5TQvh2.js → CucID8qg2.js} +1 -1
  27. package/.output/public/_nuxt/{CfVAr2nf.js → Cz9gD2Yo.js} +1 -1
  28. package/.output/public/_nuxt/{E88a-JCG.js → DGAOugLt.js} +1 -1
  29. package/.output/public/_nuxt/DHbTyoAV.js +1 -0
  30. package/.output/public/_nuxt/{BxtpDtzC.js → DNQF_TXX.js} +1 -1
  31. package/.output/public/_nuxt/DfLUN8kY.js +1 -0
  32. package/.output/public/_nuxt/DjU9Dx5Y.js +1 -0
  33. package/.output/public/_nuxt/DnziMlcX.js +1 -0
  34. package/.output/public/_nuxt/{BBwMH_hG.js → DoAlYsiF.js} +1 -1
  35. package/.output/public/_nuxt/{DA4lxCWC2.js → DosOJEmZ2.js} +2 -2
  36. package/.output/public/_nuxt/{DWcEk1ur2.js → DvgKXPgu2.js} +1 -1
  37. package/.output/public/_nuxt/{ed5qX-x5.js → Q_SJDSgx.js} +1 -1
  38. package/.output/public/_nuxt/{TownView.zu2rU5nS.css → TownView.CtskuMXS.css} +1 -1
  39. package/.output/public/_nuxt/XY2z78rj.js +1 -0
  40. package/.output/public/_nuxt/_id_.DdbYeLqn.css +1 -0
  41. package/.output/public/_nuxt/bFnZa2yd.js +1 -0
  42. package/.output/public/_nuxt/builds/latest.json +1 -1
  43. package/.output/public/_nuxt/builds/meta/f7a8e33d-5422-45ac-895d-27168f97e3ad.json +1 -0
  44. package/.output/public/_nuxt/daq.DGV9QS8d.css +1 -0
  45. package/.output/public/_nuxt/entry.BN02X8iR.css +1 -0
  46. package/.output/public/_nuxt/monitor.B--1dPzs.css +1 -0
  47. package/.output/public/_nuxt/permissions.B1pjGChZ.css +1 -0
  48. package/.output/public/_nuxt/plugins.DpCuwaJt.css +1 -0
  49. package/.output/public/_nuxt/rkVgzg62.js +1 -0
  50. package/.output/public/_nuxt/settings.W6qrYAui.css +1 -0
  51. package/.output/public/_nuxt/teams.BBXVkyKq.css +1 -0
  52. package/.output/public/_nuxt/tokens.xRb1fSPU.css +1 -0
  53. package/.output/public/_nuxt/users.DuAt_Zwf.css +1 -0
  54. package/.output/public/_nuxt/workshop.BJg84pOK.css +1 -0
  55. package/.output/public/assets/game/character/yangyang-walk.glb +0 -0
  56. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  57. package/.output/server/chunks/_/nitro.mjs +1073 -925
  58. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  59. package/.output/server/chunks/build/{OmpTerminalPanel-Ban3yJZ4.mjs → OmpTerminalPanel-Cw_Vw9oO.mjs} +3 -3
  60. package/.output/server/chunks/build/{OmpTerminalPanel-Ban3yJZ4.mjs.map → OmpTerminalPanel-Cw_Vw9oO.mjs.map} +1 -1
  61. package/.output/server/chunks/build/{TownView-DxeQe1Bl.mjs → TownView-ftIylqiD.mjs} +178 -151
  62. package/.output/server/chunks/build/{TownView-DxeQe1Bl.mjs.map → TownView-ftIylqiD.mjs.map} +1 -1
  63. package/.output/server/chunks/build/{_id_-DQDqj-cZ.mjs → _id_-3Axz2-gV.mjs} +35 -35
  64. package/.output/server/chunks/build/{_id_-DQDqj-cZ.mjs.map → _id_-3Axz2-gV.mjs.map} +1 -1
  65. package/.output/server/chunks/build/{_id_-DY6v6sqB.mjs → _id_-CahfkmEt.mjs} +5 -5
  66. package/.output/server/chunks/build/{_id_-DY6v6sqB.mjs.map → _id_-CahfkmEt.mjs.map} +1 -1
  67. package/.output/server/chunks/build/{_wsId_-C2O5zZsI.mjs → _wsId_-BymlQhzS.mjs} +13 -15
  68. package/.output/server/chunks/build/{_wsId_-C2O5zZsI.mjs.map → _wsId_-BymlQhzS.mjs.map} +1 -1
  69. package/.output/server/chunks/build/{agents--6bzGtES.mjs → agents-DuMiSWKp.mjs} +7 -9
  70. package/.output/server/chunks/build/agents-DuMiSWKp.mjs.map +1 -0
  71. package/.output/server/chunks/build/button-DEcZFcqN.mjs +1 -1
  72. package/.output/server/chunks/build/{card-CCPQoKlh.mjs → card-Dipvaykh.mjs} +4 -4
  73. package/.output/server/chunks/build/{card-CCPQoKlh.mjs.map → card-Dipvaykh.mjs.map} +1 -1
  74. package/.output/server/chunks/build/{channel-templates-C1Bb-U75.mjs → channel-templates-BStqJ-of.mjs} +5 -7
  75. package/.output/server/chunks/build/channel-templates-BStqJ-of.mjs.map +1 -0
  76. package/.output/server/chunks/build/{checkbox-Dv1kjaUZ.mjs → checkbox-C1gABOca.mjs} +5 -5
  77. package/.output/server/chunks/build/{checkbox-Dv1kjaUZ.mjs.map → checkbox-C1gABOca.mjs.map} +1 -1
  78. package/.output/server/chunks/build/{daq-B-3xCp_2.mjs → daq-ChYCABz1.mjs} +312 -426
  79. package/.output/server/chunks/build/daq-ChYCABz1.mjs.map +1 -0
  80. package/.output/server/chunks/build/{dcw-BL2dhuz7.mjs → dcw-CcQNGggh.mjs} +3 -3
  81. package/.output/server/chunks/build/{dcw-BL2dhuz7.mjs.map → dcw-CcQNGggh.mjs.map} +1 -1
  82. package/.output/server/chunks/build/{default-DdV642BY.mjs → default-95-zOTPt.mjs} +3 -4
  83. package/.output/server/chunks/build/{default-DdV642BY.mjs.map → default-95-zOTPt.mjs.map} +1 -1
  84. package/.output/server/chunks/build/dropdown-vhn1NPFs.mjs +1 -1
  85. package/.output/server/chunks/build/{input-number-CZ3ZrCsy.mjs → input-number-Bd55elNN.mjs} +3 -3
  86. package/.output/server/chunks/build/{input-number-CZ3ZrCsy.mjs.map → input-number-Bd55elNN.mjs.map} +1 -1
  87. package/.output/server/chunks/build/{input-DxDqeyQW.mjs → input-sf_BT6o6.mjs} +553 -5
  88. package/.output/server/chunks/build/input-sf_BT6o6.mjs.map +1 -0
  89. package/.output/server/chunks/build/{logs-Dto_umFY.mjs → logs-D-2UyGtE.mjs} +3 -3
  90. package/.output/server/chunks/build/{logs-Dto_umFY.mjs.map → logs-D-2UyGtE.mjs.map} +1 -1
  91. package/.output/server/chunks/build/menu-WCrlpYVh.mjs +2 -2
  92. package/.output/server/chunks/build/modal-yvUquPj5.mjs +2 -2
  93. package/.output/server/chunks/build/{monitor-miqq9xHB.mjs → monitor-mfG5jBtz.mjs} +70 -192
  94. package/.output/server/chunks/build/monitor-mfG5jBtz.mjs.map +1 -0
  95. package/.output/server/chunks/build/{pages-D9tOoJsf.mjs → pages-Dfosfchr.mjs} +5 -6
  96. package/.output/server/chunks/build/pages-Dfosfchr.mjs.map +1 -0
  97. package/.output/server/chunks/build/{permissions-CxEgXic0.mjs → permissions-B-hhZuzm.mjs} +288 -194
  98. package/.output/server/chunks/build/permissions-B-hhZuzm.mjs.map +1 -0
  99. package/.output/server/chunks/build/{plugins-wLIKHcIE.mjs → plugins-DZR0T4Mh.mjs} +17 -17
  100. package/.output/server/chunks/build/{plugins-wLIKHcIE.mjs.map → plugins-DZR0T4Mh.mjs.map} +1 -1
  101. package/.output/server/chunks/build/popconfirm-CRaHcz5O.mjs +1 -1
  102. package/.output/server/chunks/build/{segmented-ChmQZwz6.mjs → segmented-LPPREMtZ.mjs} +336 -5
  103. package/.output/server/chunks/build/{segmented-ChmQZwz6.mjs.map → segmented-LPPREMtZ.mjs.map} +1 -1
  104. package/.output/server/chunks/build/{settings-BPBll_7K.mjs → settings-BajN9TQW.mjs} +254 -27
  105. package/.output/server/chunks/build/settings-BajN9TQW.mjs.map +1 -0
  106. package/.output/server/chunks/build/space-CCBYAkXt.mjs +1 -1
  107. package/.output/server/chunks/build/switch-CelRXpcy.mjs +1 -1
  108. package/.output/server/chunks/build/{table-BtksyDlQ.mjs → table-Bf1r2JjE.mjs} +5 -5
  109. package/.output/server/chunks/build/{table-BtksyDlQ.mjs.map → table-Bf1r2JjE.mjs.map} +1 -1
  110. package/.output/server/chunks/build/{tabs-DQv-_-R6.mjs → tabs-BM3tAh_J.mjs} +2 -2
  111. package/.output/server/chunks/build/{tabs-DQv-_-R6.mjs.map → tabs-BM3tAh_J.mjs.map} +1 -1
  112. package/.output/server/chunks/build/{tag-A0tZ2Ouq.mjs → tag-NO9jEqKy.mjs} +3 -3
  113. package/.output/server/chunks/build/{tag-A0tZ2Ouq.mjs.map → tag-NO9jEqKy.mjs.map} +1 -1
  114. package/.output/server/chunks/build/{teams-DD8ZXTKL.mjs → teams-t2SkRlJP.mjs} +349 -51
  115. package/.output/server/chunks/build/teams-t2SkRlJP.mjs.map +1 -0
  116. package/.output/server/chunks/build/{tokens-Dxnuw96_.mjs → tokens-DiCojbN8.mjs} +296 -200
  117. package/.output/server/chunks/build/tokens-DiCojbN8.mjs.map +1 -0
  118. package/.output/server/chunks/build/{town-Dsh0jlwZ.mjs → town-C7QM8DYK.mjs} +5 -5
  119. package/.output/server/chunks/build/{town-Dsh0jlwZ.mjs.map → town-C7QM8DYK.mjs.map} +1 -1
  120. package/.output/server/chunks/build/{useDaqStream-DkRL3tEW.mjs → useDaqStream-BeA2X8KR.mjs} +26 -11
  121. package/.output/server/chunks/build/useDaqStream-BeA2X8KR.mjs.map +1 -0
  122. package/.output/server/chunks/build/{useDcwStream-DyB2ufQI.mjs → useDcwStream-BJW_MitY.mjs} +14 -6
  123. package/.output/server/chunks/build/useDcwStream-BJW_MitY.mjs.map +1 -0
  124. package/.output/server/chunks/build/{useDeviceTwins-ZbT86L9O.mjs → useDeviceTwins-Dwz_EY_i.mjs} +2 -2
  125. package/.output/server/chunks/build/{useDeviceTwins-ZbT86L9O.mjs.map → useDeviceTwins-Dwz_EY_i.mjs.map} +1 -1
  126. package/.output/server/chunks/build/{useOpsLog-8HCYFb6n.mjs → useOpsLog-Dm8QEb1I.mjs} +2 -2
  127. package/.output/server/chunks/build/{useOpsLog-8HCYFb6n.mjs.map → useOpsLog-Dm8QEb1I.mjs.map} +1 -1
  128. package/.output/server/chunks/build/{useWorkshopApi-D2gq06N2.mjs → useWorkshopApi-B-L3MmIX.mjs} +9 -2
  129. package/.output/server/chunks/build/{useWorkshopApi-D2gq06N2.mjs.map → useWorkshopApi-B-L3MmIX.mjs.map} +1 -1
  130. package/.output/server/chunks/build/{users-D6RNylrW.mjs → users-B9SAdEtH.mjs} +12 -13
  131. package/.output/server/chunks/build/users-B9SAdEtH.mjs.map +1 -0
  132. package/.output/server/chunks/build/{workshop-CTcYDq2i.mjs → workshop-81xhz368.mjs} +21 -22
  133. package/.output/server/chunks/build/workshop-81xhz368.mjs.map +1 -0
  134. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +14 -2
  135. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
  136. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  137. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +40 -0
  138. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs.map +1 -0
  139. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +21 -9
  140. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs.map +1 -1
  141. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +33 -0
  142. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs.map +1 -0
  143. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
  144. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +15 -1
  145. package/.output/server/chunks/routes/api/workshop/channels.post.mjs.map +1 -1
  146. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
  147. package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
  148. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
  149. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
  150. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
  151. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
  152. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
  153. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
  154. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
  155. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
  156. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +1 -1
  157. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +1 -1
  158. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
  159. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
  163. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
  164. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +1 -1
  165. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +1 -1
  166. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
  167. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
  168. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
  169. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +1 -1
  170. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
  173. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
  174. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
  175. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +1 -1
  176. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
  177. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +1 -1
  178. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
  179. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
  191. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
  192. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
  193. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
  194. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
  203. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  205. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  208. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
  211. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +1 -1
  212. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
  213. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  219. package/.output/server/chunks/routes/renderer.mjs +3 -3
  220. package/.output/server/chunks/virtual/entry.mjs +381 -438
  221. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  222. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  223. package/.output/server/package.json +1 -1
  224. package/app/app.vue +7 -0
  225. package/app/assets/css/main.css +12 -1
  226. package/app/components/workshop/DaqNodeRow.vue +398 -0
  227. package/app/components/workshop/town/ModelPreview3D.vue +26 -4
  228. package/app/components/workshop/town/TownScene3D.ts +60 -12
  229. package/app/components/workshop/town/TownView.vue +4 -3
  230. package/app/composables/workshop/useCharacterAssets.ts +1 -0
  231. package/app/composables/workshop/useDaqStream.ts +24 -5
  232. package/app/composables/workshop/useDcwStream.ts +13 -4
  233. package/app/composables/workshop/useWorkshopApi.ts +294 -259
  234. package/app/pages/daq/[id].vue +27 -3
  235. package/app/pages/daq/index.vue +8 -355
  236. package/app/pages/monitor.vue +56 -68
  237. package/app/pages/permissions/index.vue +86 -82
  238. package/app/pages/plugins/index.vue +12 -7
  239. package/app/pages/settings.vue +253 -2
  240. package/app/pages/tokens.vue +94 -96
  241. package/app/pages/users.vue +10 -18
  242. package/app/pages/workshop/index.vue +34 -5
  243. package/app/pages/workshop/teams.vue +212 -2
  244. package/i18n/dicts/_en.json +361 -1
  245. package/i18n/dicts/plugins.json +10 -0
  246. package/i18n/dicts/settings.json +1 -0
  247. package/i18n/dicts/teamPlugins.json +10 -0
  248. package/i18n/locales/en.ts +1861 -1901
  249. package/i18n/locales/zh-CN.ts +1789 -1830
  250. package/package.json +149 -148
  251. package/public/assets/game/character/yangyang-walk.glb +0 -0
  252. package/scripts/_dbg-cpu-profile.mjs +53 -0
  253. package/scripts/_dbg-logs-ui-e2e.py +3 -2
  254. package/scripts/_dbg-render-perf.mjs +142 -0
  255. package/scripts/_dbg-render-regression.mjs +130 -0
  256. package/scripts/_dbg-ui-survey.py +52 -0
  257. package/scripts/i18n-merge.mjs +152 -30
  258. package/scripts/production-closed-loop-e2e.mjs +254 -0
  259. package/scripts/team-plugins-api-smoke.mjs +149 -0
  260. package/scripts/three-system-e2e.mjs +448 -0
  261. package/server/api/plugins/[name]/[...path].ts +46 -31
  262. package/server/api/workshop/channels/[id]/plugins/index.get.ts +35 -0
  263. package/server/api/workshop/channels/[id]/plugins/index.put.ts +39 -0
  264. package/server/api/workshop/channels.post.ts +17 -0
  265. package/server/data/dcw-lines.json +14 -0
  266. package/server/data/dcw-products.json +14 -0
  267. package/server/data/dcw-recipes.json +23 -1
  268. package/server/data/dcw-rollback.json +585 -10
  269. package/server/data/dcw-runs.json +27 -27
  270. package/server/data/dcw-writes.json +96 -0
  271. package/server/data/dcws.json +394 -366
  272. package/server/data/scene-layouts.json +66 -0
  273. package/server/plugins/aw-plugins.ts +35 -27
  274. package/server/plugins-builtin/diag-bridge/index.mjs +556 -0
  275. package/server/plugins-builtin/rag-bridge/index.mjs +364 -0
  276. package/server/services/workshop/agents/host-tool-bridge.ts +659 -642
  277. package/server/services/workshop/agents/omp-agent.ts +1178 -1178
  278. package/server/services/workshop/agents/plugin-tools.ts +10 -1
  279. package/server/services/workshop/db/channel-plugins.repo.ts +65 -0
  280. package/server/services/workshop/plugins/host.mjs +52 -4
  281. package/server/services/workshop/runtime/manager.ts +2976 -2968
  282. package/shared/config/schema.json +4 -0
  283. package/.output/public/_nuxt/BJbhwS5o.js +0 -1
  284. package/.output/public/_nuxt/BUcmySDa2.js +0 -209
  285. package/.output/public/_nuxt/BWC4HQHQ.js +0 -1
  286. package/.output/public/_nuxt/BbZAzXjZ2.js +0 -1
  287. package/.output/public/_nuxt/BgOhoDTI.js +0 -1
  288. package/.output/public/_nuxt/Bo8t5fkJ.js +0 -1
  289. package/.output/public/_nuxt/BuiGDfMB.js +0 -1
  290. package/.output/public/_nuxt/BxPPAkGA.js +0 -3
  291. package/.output/public/_nuxt/C53drffV.js +0 -1
  292. package/.output/public/_nuxt/CcwJ2mrD2.js +0 -1
  293. package/.output/public/_nuxt/Cr9DkD1d.js +0 -1
  294. package/.output/public/_nuxt/DTYBfjRY.js +0 -1
  295. package/.output/public/_nuxt/DVoWWlUW.js +0 -1
  296. package/.output/public/_nuxt/Dc32T41C.js +0 -1
  297. package/.output/public/_nuxt/Dhqra7NB.js +0 -1
  298. package/.output/public/_nuxt/DlRO_q5L.js +0 -1
  299. package/.output/public/_nuxt/DsUUYP292.js +0 -1
  300. package/.output/public/_nuxt/Dsdy4Ua-.js +0 -1
  301. package/.output/public/_nuxt/DtzZqC0z.js +0 -1
  302. package/.output/public/_nuxt/Ko9mMsJj.js +0 -14
  303. package/.output/public/_nuxt/RzXYI9FM.js +0 -23
  304. package/.output/public/_nuxt/UtviM1bg.js +0 -1
  305. package/.output/public/_nuxt/_id_.C-YXjn8Q.css +0 -1
  306. package/.output/public/_nuxt/bAFueD6a.js +0 -1
  307. package/.output/public/_nuxt/builds/meta/1adc96e0-8bbd-4a79-ac7e-b6952556fef8.json +0 -1
  308. package/.output/public/_nuxt/daq.3OKj58HH.css +0 -1
  309. package/.output/public/_nuxt/dbi5bHkY.js +0 -2
  310. package/.output/public/_nuxt/eHYnGew0.js +0 -19
  311. package/.output/public/_nuxt/entry.OR_psZHp.css +0 -1
  312. package/.output/public/_nuxt/jyQyulh-.js +0 -1
  313. package/.output/public/_nuxt/monitor.CmwpEUCI.css +0 -1
  314. package/.output/public/_nuxt/permissions.DTRtZeTw.css +0 -1
  315. package/.output/public/_nuxt/plugins.BcSEwwGb.css +0 -1
  316. package/.output/public/_nuxt/settings.BqMF2nfj.css +0 -1
  317. package/.output/public/_nuxt/teams.DN0pAGGu.css +0 -1
  318. package/.output/public/_nuxt/tokens.BVXU1jOK.css +0 -1
  319. package/.output/public/_nuxt/users.D8lcLE62.css +0 -1
  320. package/.output/public/_nuxt/workshop.CbymC2LY.css +0 -1
  321. package/.output/public/_nuxt/zVkqCZ78.js +0 -1
  322. package/.output/server/chunks/build/Col-biaNnEPf.mjs +0 -338
  323. package/.output/server/chunks/build/Col-biaNnEPf.mjs.map +0 -1
  324. package/.output/server/chunks/build/agents--6bzGtES.mjs.map +0 -1
  325. package/.output/server/chunks/build/channel-templates-C1Bb-U75.mjs.map +0 -1
  326. package/.output/server/chunks/build/daq-B-3xCp_2.mjs.map +0 -1
  327. package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs +0 -554
  328. package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs.map +0 -1
  329. package/.output/server/chunks/build/input-DxDqeyQW.mjs.map +0 -1
  330. package/.output/server/chunks/build/monitor-miqq9xHB.mjs.map +0 -1
  331. package/.output/server/chunks/build/pages-D9tOoJsf.mjs.map +0 -1
  332. package/.output/server/chunks/build/permissions-CxEgXic0.mjs.map +0 -1
  333. package/.output/server/chunks/build/settings-BPBll_7K.mjs.map +0 -1
  334. package/.output/server/chunks/build/teams-DD8ZXTKL.mjs.map +0 -1
  335. package/.output/server/chunks/build/tokens-Dxnuw96_.mjs.map +0 -1
  336. package/.output/server/chunks/build/useDaqStream-DkRL3tEW.mjs.map +0 -1
  337. package/.output/server/chunks/build/useDcwStream-DyB2ufQI.mjs.map +0 -1
  338. package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs +0 -27
  339. package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs.map +0 -1
  340. package/.output/server/chunks/build/users-D6RNylrW.mjs.map +0 -1
  341. package/.output/server/chunks/build/workshop-CTcYDq2i.mjs.map +0 -1
  342. /package/.output/public/_nuxt/{CNs_Ozdc.js → CNs_Ozdc2.js} +0 -0
  343. /package/.output/public/_nuxt/{Cno6kYiO.js → Cno6kYiO2.js} +0 -0
  344. /package/.output/public/_nuxt/{ORt9oDIy2.js → ORt9oDIy.js} +0 -0
package/package.json CHANGED
@@ -1,148 +1,149 @@
1
- {
2
- "name": "agentworkshop",
3
- "version": "0.7.23",
4
- "type": "module",
5
- "description": "AgentWorkShop 软件开发系统 - 基于 Nuxt 4 的配置驱动运行范式",
6
- "license": "PolyForm-Noncommercial-1.0.0",
7
- "exports": {
8
- ".": {
9
- "types": "./sdk/index.d.mts",
10
- "default": "./sdk/index.mjs"
11
- },
12
- "./sdk": {
13
- "types": "./sdk/index.d.mts",
14
- "default": "./sdk/index.mjs"
15
- },
16
- "./sdk/client": {
17
- "types": "./sdk/client.d.mts",
18
- "default": "./sdk/client.mjs"
19
- },
20
- "./package.json": "./package.json"
21
- },
22
- "bin": {
23
- "aw": "bin/aw.mjs",
24
- "agentworkshop": "bin/aw.mjs"
25
- },
26
- "files": [
27
- ".output",
28
- "bin",
29
- "cli",
30
- "sdk",
31
- "app",
32
- "server",
33
- "shared",
34
- "i18n",
35
- "public",
36
- "scripts",
37
- ".AgentWorkShop/prompts",
38
- "config.yml",
39
- "nuxt.config.ts",
40
- "tsconfig.json",
41
- "uno.config.ts",
42
- "docker-compose.yml",
43
- ".env.example",
44
- "README-zh.md",
45
- "docs/cli.md",
46
- "docs/plugins.md",
47
- "docs/sdk.md",
48
- "docs/tui.md",
49
- "tui"
50
- ],
51
- "packageManager": "pnpm@11.9.0",
52
- "engines": {
53
- "node": ">=23.4.0"
54
- },
55
- "scripts": {
56
- "dev": "node bin/aw.mjs dev",
57
- "build": "node bin/aw.mjs build",
58
- "start": "node bin/aw.mjs start",
59
- "generate": "nuxt generate",
60
- "preview": "node bin/aw.mjs start",
61
- "cli": "node bin/aw.mjs",
62
- "tui": "node tui/aw-tui.mjs",
63
- "postinstall": "node scripts/home-bootstrap.mjs",
64
- "prepublishOnly": "node bin/aw.mjs build",
65
- "lint": "eslint .",
66
- "lint:fix": "eslint . --fix",
67
- "typecheck": "nuxt typecheck",
68
- "prepare": "husky",
69
- "game:test": "tsx scripts/test-agent-brain.ts && tsx scripts/test-game-session.ts",
70
- "test:api-live": "node scripts/api-live-e2e.mjs",
71
- "game:verify": "node scripts/verify-game.mjs",
72
- "game:build-assets": "node scripts/build-player-sheet.mjs",
73
- "game:build-wuwa": "node scripts/build-wuwa-assets.mjs",
74
- "game:build-models": "node scripts/build-character-models.mjs",
75
- "game:build-world": "node scripts/build-world-map.mjs",
76
- "game:build-model3d": "node scripts/build-model-3d.mjs"
77
- },
78
- "lint-staged": {
79
- "*.{js,mjs,cjs,ts,vue}": "eslint --fix"
80
- },
81
- "dependencies": {
82
- "@ant-design-vue/nuxt": "^1.4.6",
83
- "@ant-design/icons-vue": "^7.0.1",
84
- "@earendil-works/pi-tui": "^0.84.4",
85
- "@fontsource-variable/fraunces": "^5.3.0",
86
- "@fontsource-variable/geist": "^5.3.0",
87
- "@fontsource-variable/geist-mono": "^5.3.0",
88
- "@fontsource-variable/inter": "^5.3.0",
89
- "@fontsource/eb-garamond": "^5.3.0",
90
- "@fontsource/ibm-plex-mono": "^5.3.0",
91
- "@iconify-json/tabler": "^1.2.0",
92
- "@modelcontextprotocol/sdk": "^1.30.0",
93
- "@nuxtjs/i18n": "^9.0.0",
94
- "@pinia/nuxt": "^0.11.0",
95
- "@unocss/nuxt": "^66.0.0",
96
- "@unocss/preset-attributify": "^66.0.0",
97
- "@unocss/preset-icons": "^66.7.5",
98
- "@unocss/preset-typography": "^66.0.0",
99
- "@vueuse/core": "^13.0.0",
100
- "@vueuse/nuxt": "^13.0.0",
101
- "@xterm/addon-fit": "^0.11.0",
102
- "@xterm/xterm": "^6.0.0",
103
- "ant-design-vue": "^4.2.6",
104
- "axios": "^1.7.9",
105
- "echarts": "^5.6.0",
106
- "h3": "2.0.1-rc.26",
107
- "js-yaml": "^4.1.0",
108
- "minio": "^8.0.7",
109
- "modbus-serial": "^8.0.25",
110
- "mqtt": "^5.15.2",
111
- "node-opcua": "^2.178.0",
112
- "nuxt": "^4.0.0",
113
- "nuxt-auth-utils": "^0.5.0",
114
- "pg": "^8.23.0",
115
- "phaser": "^4.0.0",
116
- "pinia": "^3.0.0",
117
- "pinia-plugin-persistedstate": "^4.2.0",
118
- "sqlite-vec": "^0.1.9",
119
- "three": "^0.185.1",
120
- "unocss": "^66.0.0",
121
- "unplugin-icons": "^22.0.0",
122
- "vue": "^3.5.13",
123
- "vue-echarts": "^7.0.3",
124
- "vue-router": "^4.5.0",
125
- "zod": "^3.24.1"
126
- },
127
- "devDependencies": {
128
- "@commitlint/cli": "^19.6.1",
129
- "@commitlint/config-conventional": "^19.6.0",
130
- "@nuxt/eslint": "^1.0.0",
131
- "@types/js-yaml": "^4.0.9",
132
- "@types/node": "^26.2.0",
133
- "@types/three": "^0.185.4",
134
- "eslint": "^9.17.0",
135
- "husky": "^9.1.7",
136
- "lint-staged": "^15.3.0",
137
- "pngjs": "^7.0.0",
138
- "puppeteer-core": "^25.5.0",
139
- "tsx": "^4.23.12",
140
- "typescript": "^5.7.3",
141
- "vue-tsc": "^3.3.10"
142
- },
143
- "pnpm": {
144
- "ignoredBuiltDependencies": [
145
- "@serialport/bindings-cpp"
146
- ]
147
- }
148
- }
1
+ {
2
+ "name": "agentworkshop",
3
+ "version": "0.7.27",
4
+ "type": "module",
5
+ "description": "AgentWorkShop 软件开发系统 - 基于 Nuxt 4 的配置驱动运行范式",
6
+ "license": "PolyForm-Noncommercial-1.0.0",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./sdk/index.d.mts",
10
+ "default": "./sdk/index.mjs"
11
+ },
12
+ "./sdk": {
13
+ "types": "./sdk/index.d.mts",
14
+ "default": "./sdk/index.mjs"
15
+ },
16
+ "./sdk/client": {
17
+ "types": "./sdk/client.d.mts",
18
+ "default": "./sdk/client.mjs"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
22
+ "bin": {
23
+ "aw": "bin/aw.mjs",
24
+ "agentworkshop": "bin/aw.mjs"
25
+ },
26
+ "files": [
27
+ ".output",
28
+ "bin",
29
+ "cli",
30
+ "sdk",
31
+ "app",
32
+ "server",
33
+ "shared",
34
+ "i18n",
35
+ "public",
36
+ "scripts",
37
+ ".AgentWorkShop/prompts",
38
+ "server/plugins-builtin",
39
+ "config.yml",
40
+ "nuxt.config.ts",
41
+ "tsconfig.json",
42
+ "uno.config.ts",
43
+ "docker-compose.yml",
44
+ ".env.example",
45
+ "README-zh.md",
46
+ "docs/cli.md",
47
+ "docs/plugins.md",
48
+ "docs/sdk.md",
49
+ "docs/tui.md",
50
+ "tui"
51
+ ],
52
+ "packageManager": "pnpm@11.9.0",
53
+ "engines": {
54
+ "node": ">=23.4.0"
55
+ },
56
+ "scripts": {
57
+ "dev": "node bin/aw.mjs dev",
58
+ "build": "node bin/aw.mjs build",
59
+ "start": "node bin/aw.mjs start",
60
+ "generate": "nuxt generate",
61
+ "preview": "node bin/aw.mjs start",
62
+ "cli": "node bin/aw.mjs",
63
+ "tui": "node tui/aw-tui.mjs",
64
+ "postinstall": "node scripts/home-bootstrap.mjs",
65
+ "prepublishOnly": "node bin/aw.mjs build",
66
+ "lint": "eslint .",
67
+ "lint:fix": "eslint . --fix",
68
+ "typecheck": "nuxt typecheck",
69
+ "prepare": "husky",
70
+ "game:test": "tsx scripts/test-agent-brain.ts && tsx scripts/test-game-session.ts",
71
+ "test:api-live": "node scripts/api-live-e2e.mjs",
72
+ "game:verify": "node scripts/verify-game.mjs",
73
+ "game:build-assets": "node scripts/build-player-sheet.mjs",
74
+ "game:build-wuwa": "node scripts/build-wuwa-assets.mjs",
75
+ "game:build-models": "node scripts/build-character-models.mjs",
76
+ "game:build-world": "node scripts/build-world-map.mjs",
77
+ "game:build-model3d": "node scripts/build-model-3d.mjs"
78
+ },
79
+ "lint-staged": {
80
+ "*.{js,mjs,cjs,ts,vue}": "eslint --fix"
81
+ },
82
+ "dependencies": {
83
+ "@ant-design-vue/nuxt": "^1.4.6",
84
+ "@ant-design/icons-vue": "^7.0.1",
85
+ "@earendil-works/pi-tui": "^0.84.4",
86
+ "@fontsource-variable/fraunces": "^5.3.0",
87
+ "@fontsource-variable/geist": "^5.3.0",
88
+ "@fontsource-variable/geist-mono": "^5.3.0",
89
+ "@fontsource-variable/inter": "^5.3.0",
90
+ "@fontsource/eb-garamond": "^5.3.0",
91
+ "@fontsource/ibm-plex-mono": "^5.3.0",
92
+ "@iconify-json/tabler": "^1.2.0",
93
+ "@modelcontextprotocol/sdk": "^1.30.0",
94
+ "@nuxtjs/i18n": "^9.0.0",
95
+ "@pinia/nuxt": "^0.11.0",
96
+ "@unocss/nuxt": "^66.0.0",
97
+ "@unocss/preset-attributify": "^66.0.0",
98
+ "@unocss/preset-icons": "^66.7.5",
99
+ "@unocss/preset-typography": "^66.0.0",
100
+ "@vueuse/core": "^13.0.0",
101
+ "@vueuse/nuxt": "^13.0.0",
102
+ "@xterm/addon-fit": "^0.11.0",
103
+ "@xterm/xterm": "^6.0.0",
104
+ "ant-design-vue": "^4.2.6",
105
+ "axios": "^1.7.9",
106
+ "echarts": "^5.6.0",
107
+ "h3": "2.0.1-rc.26",
108
+ "js-yaml": "^4.1.0",
109
+ "minio": "^8.0.7",
110
+ "modbus-serial": "^8.0.25",
111
+ "mqtt": "^5.15.2",
112
+ "node-opcua": "^2.178.0",
113
+ "nuxt": "^4.0.0",
114
+ "nuxt-auth-utils": "^0.5.0",
115
+ "pg": "^8.23.0",
116
+ "phaser": "^4.0.0",
117
+ "pinia": "^3.0.0",
118
+ "pinia-plugin-persistedstate": "^4.2.0",
119
+ "sqlite-vec": "^0.1.9",
120
+ "three": "^0.185.1",
121
+ "unocss": "^66.0.0",
122
+ "unplugin-icons": "^22.0.0",
123
+ "vue": "^3.5.13",
124
+ "vue-echarts": "^7.0.3",
125
+ "vue-router": "^4.5.0",
126
+ "zod": "^3.24.1"
127
+ },
128
+ "devDependencies": {
129
+ "@commitlint/cli": "^19.6.1",
130
+ "@commitlint/config-conventional": "^19.6.0",
131
+ "@nuxt/eslint": "^1.0.0",
132
+ "@types/js-yaml": "^4.0.9",
133
+ "@types/node": "^26.2.0",
134
+ "@types/three": "^0.185.4",
135
+ "eslint": "^9.17.0",
136
+ "husky": "^9.1.7",
137
+ "lint-staged": "^15.3.0",
138
+ "pngjs": "^7.0.0",
139
+ "puppeteer-core": "^25.5.0",
140
+ "tsx": "^4.23.12",
141
+ "typescript": "^5.7.3",
142
+ "vue-tsc": "^3.3.10"
143
+ },
144
+ "pnpm": {
145
+ "ignoredBuiltDependencies": [
146
+ "@serialport/bindings-cpp"
147
+ ]
148
+ }
149
+ }
@@ -0,0 +1,53 @@
1
+ /** CPU 热点剖析:/daq 与 /town 各采 12s CPU profile,输出 self-time Top20。 */
2
+ import puppeteer from 'puppeteer-core'
3
+ import { writeFileSync } from 'node:fs'
4
+
5
+ const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
6
+ const OUT = process.argv[3] ?? '.e2e-shots/cpu-profile.json'
7
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
8
+
9
+ const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: 'perf-runner@awshop.io', password: 'Perf@Run2026' }) }).then(r => r.json())
10
+ const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
11
+ const page = await browser.newPage()
12
+ await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
13
+ await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
14
+
15
+ const cdp = await page.createCDPSession()
16
+ await cdp.send('Profiler.enable')
17
+ await cdp.send('Profiler.setSamplingInterval', { interval: 500 })
18
+
19
+ async function profile(path, warmMs, sampleMs) {
20
+ await page.goto(`${ROOT}${path}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
21
+ await sleep(warmMs)
22
+ await cdp.send('Profiler.start')
23
+ await sleep(sampleMs)
24
+ const { profile: prof } = await cdp.send('Profiler.stop')
25
+ // self time 聚合
26
+ const nodesById = new Map(prof.nodes.map(n => [n.id, n]))
27
+ const self = new Map()
28
+ const total = prof.timeDeltas.reduce((a, b) => a + b, 0)
29
+ for (let i = 0; i < prof.samples.length; i++) {
30
+ const id = prof.samples[i]
31
+ const dt = prof.timeDeltas[i] ?? 0
32
+ self.set(id, (self.get(id) ?? 0) + dt)
33
+ }
34
+ const rows = [...self.entries()]
35
+ .map(([id, us]) => {
36
+ const n = nodesById.get(id)
37
+ const cf = n?.callFrame ?? {}
38
+ const url = (cf.url ?? '').replace(/^.*\/(_nuxt|node_modules)\//, '$1/')
39
+ return { fn: `${cf.functionName || '(anon)'} @ ${url}:${(cf.lineNumber ?? 0) + 1}`, selfMs: +(us / 1000).toFixed(1) }
40
+ })
41
+ .sort((a, b) => b.selfMs - a.selfMs)
42
+ .slice(0, 20)
43
+ .filter(r => r.selfMs >= 5)
44
+ return { path, totalMs: +(total / 1000).toFixed(0), top: rows }
45
+ }
46
+
47
+ const daq = await profile('/daq', 12000, 12000)
48
+ console.log('==== /daq self-time Top:', JSON.stringify(daq, null, 1))
49
+ const town = await profile('/town', 18000, 12000)
50
+ console.log('==== /town self-time Top:', JSON.stringify(town, null, 1))
51
+ writeFileSync(OUT, JSON.stringify({ daq, town }, null, 2))
52
+ await browser.close()
53
+ console.log('DONE ->', OUT)
@@ -4,11 +4,12 @@
4
4
  # 3) 页头 aw-page-head 规范(标题30px + 描述间距)
5
5
  # 附带:daq/dcw 页按钮抽查截图。产物 → .e2e-shots/
6
6
  import json
7
+ import os
7
8
  import sys
8
9
  from playwright.sync_api import sync_playwright
9
10
 
10
- BASE = 'http://127.0.0.1:3000'
11
- SHOT = '.e2e-shots'
11
+ BASE = os.environ.get('BASE', 'http://127.0.0.1:3000')
12
+ SHOT = os.environ.get('SHOT_PREFIX', '') or '.e2e-shots'
12
13
  passed = 0
13
14
  failed = 0
14
15
 
@@ -0,0 +1,142 @@
1
+ /** 渲染性能基线/对比测量:/daq 与 /town 双页统一探针(前后对比同参同窗)。
2
+ * 用法:node scripts/_dbg-render-perf.mjs <base> <email> <pass> <outJson>
3
+ * 输出 JSON:{ daq:{...}, town:{...} } —— 供 plan 文档引用(证据化,非估算)。 */
4
+ import puppeteer from 'puppeteer-core'
5
+ import { writeFileSync } from 'node:fs'
6
+
7
+ const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
8
+ const EMAIL = process.argv[3] ?? 'perf-runner@awshop.io'
9
+ const PASS = process.argv[4] ?? 'Perf@Run2026'
10
+ const OUT = process.argv[5] ?? '.e2e-shots/render-perf.json'
11
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
12
+
13
+ const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
14
+ if (!login?.data?.token) { console.error('LOGIN FAIL', JSON.stringify(login)); process.exit(1) }
15
+
16
+ const browser = await puppeteer.launch({
17
+ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe',
18
+ headless: 'new',
19
+ args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'],
20
+ })
21
+ const page = await browser.newPage()
22
+ await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
23
+ await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
24
+
25
+ // 页面加载前注入:WS 帧计数(按 type)+ longtask + 事件循环延迟采样器
26
+ await page.evaluateOnNewDocument(() => {
27
+ window.__perf = { ws: {}, longTasks: 0, longTotal: 0, loopDelays: [], heapSamples: [] }
28
+ try {
29
+ new PerformanceObserver((l) => {
30
+ for (const t of l.getEntries()) { window.__perf.longTasks++; window.__perf.longTotal += t.duration }
31
+ }).observe({ entryTypes: ['longtask'] })
32
+ } catch {}
33
+ const OrigWS = window.WebSocket
34
+ window.WebSocket = function (...args) {
35
+ const ws = new OrigWS(...args)
36
+ ws.addEventListener('message', (ev) => {
37
+ try {
38
+ const d = JSON.parse(String(ev.data))
39
+ const type = d?.type ?? d?.event ?? 'raw'
40
+ window.__perf.ws[type] = (window.__perf.ws[type] ?? 0) + 1
41
+ }
42
+ catch { window.__perf.ws.raw = (window.__perf.ws.raw ?? 0) + 1 }
43
+ })
44
+ return ws
45
+ }
46
+ window.WebSocket.prototype = OrigWS.prototype
47
+ ;['OPEN', 'CLOSED', 'CLOSING', 'CONNECTING'].forEach(k => { try { window.WebSocket[k] = OrigWS[k] } catch {} })
48
+ // 事件循环延迟:50ms 心跳,记录超出量
49
+ let last = performance.now()
50
+ setInterval(() => {
51
+ const now = performance.now()
52
+ window.__perf.loopDelays.push(now - last - 50)
53
+ last = now
54
+ try { window.__perf.heapSamples.push(Math.round(performance.memory.usedJSHeapSize / 1048576)) } catch {}
55
+ }, 50)
56
+ })
57
+
58
+ const summarize = (tag, warmMs, winMs) => page.evaluate(async ({ tag, warmMs, winMs }) => {
59
+ const pct = (arr, p) => arr.length ? +arr.slice().sort((a, b) => a - b)[Math.min(arr.length - 1, Math.floor(arr.length * p))].toFixed(1) : null
60
+ await new Promise(r => setTimeout(r, warmMs))
61
+ const p = window.__perf
62
+ const ws0 = JSON.stringify(p.ws)
63
+ const lt0 = p.longTasks
64
+ const ltT0 = p.longTotal
65
+ const d0 = p.loopDelays.length
66
+ const heap0 = p.heapSamples.length ? p.heapSamples[p.heapSamples.length - 1] : null
67
+ await new Promise(r => setTimeout(r, winMs))
68
+ const ws1 = JSON.parse(JSON.stringify(p.ws))
69
+ const ws0o = JSON.parse(ws0)
70
+ const delta = {}
71
+ for (const k of new Set([...Object.keys(ws1), ...Object.keys(ws0o)])) delta[k] = (ws1[k] ?? 0) - (ws0o[k] ?? 0)
72
+ const delays = p.loopDelays.slice(d0)
73
+ const heaps = p.heapSamples.slice(d0 ? Math.max(0, d0) : 0)
74
+ return {
75
+ tag,
76
+ windowMs: winMs,
77
+ wsDelta: delta,
78
+ longTasks: p.longTasks - lt0,
79
+ longTotalMs: Math.round(p.longTotal - ltT0),
80
+ loopAvg: +(delays.reduce((a, b) => a + b, 0) / Math.max(1, delays.length)).toFixed(1),
81
+ loopP95: pct(delays, 0.95),
82
+ loopMax: delays.length ? +Math.max(...delays).toFixed(0) : 0,
83
+ heapMB: heaps.length ? heaps[heaps.length - 1] : heap0,
84
+ heapPeakMB: heaps.length ? Math.max(...heaps) : null,
85
+ }
86
+ }, { tag, warmMs, winMs })
87
+
88
+ // ---------------- /daq ----------------
89
+ await page.goto(`${ROOT}/daq`, { waitUntil: 'domcontentloaded', timeout: 60000 })
90
+ const daq = await summarize('daq', 12000, 10000)
91
+ // SPA 挂载后采集(预热窗结束后 DOM 才是真实形态)
92
+ const daqDom = await page.evaluate(() => ({
93
+ rows: document.querySelectorAll('.nodes-table tbody tr').length,
94
+ elements: document.getElementsByTagName('*').length,
95
+ svgPolylines: document.querySelectorAll('.nodes-table svg polyline').length,
96
+ }))
97
+ daq.rows = daqDom.rows
98
+ daq.domElements = daqDom.elements
99
+ daq.svgPolylines = daqDom.svgPolylines
100
+ // DOM 变更批次(10s):表格重渲染频率的代理
101
+ daq.domMutationBatches = await page.evaluate((winMs) => new Promise((resolve) => {
102
+ let batches = 0
103
+ let armed = false
104
+ const obs = new MutationObserver(() => { if (armed) batches++ })
105
+ obs.observe(document.querySelector('.nodes-table') ?? document.body, { childList: true, subtree: true, characterData: true, attributes: true })
106
+ setTimeout(() => { armed = true }, 500)
107
+ setTimeout(() => { obs.disconnect(); resolve(batches) }, winMs)
108
+ }), 10000)
109
+
110
+ // ---------------- /town ----------------
111
+ await page.goto(`${ROOT}/town`, { waitUntil: 'domcontentloaded', timeout: 60000 })
112
+ await sleep(18000)
113
+ const fpsSamples = []
114
+ for (let i = 0; i < 6; i++) {
115
+ const fps = await page.evaluate(() => {
116
+ // 优先读场景仪表化(墙钟真实 fps);无 hook 时退回徽标正则(易混入相邻文本)
117
+ const st = window.__townStats
118
+ if (st) return st.fps
119
+ const m = document.body.textContent.match(/(\d+)\s*FPS/i)
120
+ return m ? Number(m[1]) : null
121
+ })
122
+ fpsSamples.push(fps)
123
+ await sleep(2000)
124
+ }
125
+ const dpr = await page.evaluate(() => {
126
+ const cv = document.querySelector('#town-host canvas')
127
+ if (!cv) return null
128
+ return { bufW: cv.width, cssW: cv.clientWidth, ratio: +(cv.width / cv.clientWidth).toFixed(2) }
129
+ })
130
+ const townDom = await page.evaluate(() => document.getElementsByTagName('*').length)
131
+ const town = await summarize('town', 1000, 10000)
132
+ town.fpsSamples = fpsSamples
133
+ town.avgFps = +(fpsSamples.filter(v => v != null).reduce((a, b) => a + b, 0) / Math.max(1, fpsSamples.filter(v => v != null).length)).toFixed(1)
134
+ town.dpr = dpr
135
+ town.domElements = townDom
136
+ town.statsHook = await page.evaluate(() => window.__townStats ? JSON.parse(JSON.stringify(window.__townStats)) : null)
137
+
138
+ const result = { at: new Date().toISOString(), base: ROOT, daq, town }
139
+ writeFileSync(OUT, JSON.stringify(result, null, 2))
140
+ console.log(JSON.stringify(result, null, 2))
141
+ await browser.close()
142
+ console.log('DONE ->', OUT)
@@ -0,0 +1,130 @@
1
+ /** 渲染优化功能回归:/daq 行渲染与交互、/daq/[id] 详情、/town 场景与模型预览、全局 smoke。
2
+ * 用法:node scripts/_dbg-render-regression.mjs [base] [email] [pass] */
3
+ import puppeteer from 'puppeteer-core'
4
+ import { writeFileSync } from 'node:fs'
5
+
6
+ const ROOT = process.argv[2] ?? 'http://127.0.0.1:3001'
7
+ const EMAIL = process.argv[3] ?? 'perf-runner@awshop.io'
8
+ const PASS = process.argv[4] ?? 'Perf@Run2026'
9
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
10
+ const results = []
11
+ const ok = (name, pass, detail = '') => {
12
+ results.push({ name, pass, detail })
13
+ console.log(`${pass ? '✔' : '✖'} ${name}${detail ? ' —— ' + detail : ''}`)
14
+ }
15
+
16
+ const login = await fetch(`${ROOT}/api/users/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ email: EMAIL, password: PASS }) }).then(r => r.json())
17
+ if (!login?.data?.token) { console.error('LOGIN FAIL'); process.exit(1) }
18
+ const browser = await puppeteer.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe', headless: 'new', args: ['--no-sandbox', '--disable-gpu', '--window-size=1600,1000'] })
19
+ const page = await browser.newPage()
20
+ await page.setViewport({ width: 1600, height: 1000, deviceScaleFactor: 1 })
21
+ await page.setCookie({ name: 'token', value: login.data.token, domain: new URL(ROOT).hostname, path: '/' })
22
+ const pageErrors = []
23
+ page.on('pageerror', e => pageErrors.push(String(e).slice(0, 200)))
24
+
25
+ // ---------- 1. /daq 行渲染完整性 ----------
26
+ await page.goto(`${ROOT}/daq`, { waitUntil: 'domcontentloaded', timeout: 60000 })
27
+ await sleep(12000)
28
+ const daqStruct = await page.evaluate(() => {
29
+ const rows = document.querySelectorAll('.nodes-table tbody tr')
30
+ const polylines = document.querySelectorAll('.nodes-table svg polyline')
31
+ const limLines = document.querySelectorAll('.nodes-table svg line.lim')
32
+ const pills = document.querySelectorAll('.nodes-table .st-pill')
33
+ const valCells = [...document.querySelectorAll('.nodes-table .val')].slice(0, 5).map(c => c.textContent.trim())
34
+ const toggles = document.querySelectorAll('.nodes-table .node-toggle')
35
+ const links = document.querySelectorAll('.nodes-table .console-link')
36
+ const lineSelects = document.querySelectorAll('.nodes-table .line-sel:not(.dev-add)')
37
+ return { rows: rows.length, polylines: polylines.length, limLines: limLines.length, pills: pills.length, valCells, toggles: toggles.length, links: links.length, lineSelects: lineSelects.length }
38
+ })
39
+ ok('/daq 行数 227', daqStruct.rows === 227, `rows=${daqStruct.rows}`)
40
+ ok('/daq 每行趋势折线', daqStruct.polylines === 227, `polylines=${daqStruct.polylines}`)
41
+ ok('/daq 状态 pill 齐全', daqStruct.pills >= 227, `pills=${daqStruct.pills}`)
42
+ ok('/daq 启停按钮齐全', daqStruct.toggles === 227, `toggles=${daqStruct.toggles}`)
43
+ ok('/daq 控制台链接齐全', daqStruct.links === 227, `links=${daqStruct.links}`)
44
+ ok('/daq 产线下拉齐全', daqStruct.lineSelects === 227, `selects=${daqStruct.lineSelects}`)
45
+ ok('/daq 值列有数据', daqStruct.valCells.some(v => /\d/.test(v)), daqStruct.valCells[0])
46
+
47
+ // ---------- 2. WS 实时收敛:值列随读数帧变化(优化后合批仍须驱动行更新) ----------
48
+ const valChanges = await page.evaluate(() => new Promise((resolve) => {
49
+ const cells = [...document.querySelectorAll('.nodes-table .val')]
50
+ const texts = cells.map(c => c.textContent.trim())
51
+ setTimeout(() => {
52
+ const now = cells.map(c => c.textContent.trim())
53
+ let changed = 0
54
+ for (let i = 0; i < texts.length; i++) if (now[i] !== texts[i]) changed++
55
+ resolve(changed)
56
+ }, 8000)
57
+ }))
58
+ ok('/daq WS 读数驱动行更新(8s 内 ≥5 行变化)', valChanges >= 5, `changedRows=${valChanges}`)
59
+
60
+ // ---------- 3. 筛选交互(行组件随筛选增减) ----------
61
+ await page.type('.nodes-search input, input[placeholder]', '压力', { delay: 30 }).catch(() => {})
62
+ await sleep(1500)
63
+ const searchFiltered = await page.evaluate(() => document.querySelectorAll('.nodes-table tbody tr').length)
64
+ ok('/daq 搜索筛选生效', searchFiltered > 0 && searchFiltered < 227, `rows=${searchFiltered}`)
65
+ await page.evaluate(() => { location.hash = '' })
66
+ // 清空搜索(全选删除)
67
+ await page.keyboard.down('Control'); await page.keyboard.press('a'); await page.keyboard.up('Control'); await page.keyboard.press('Backspace')
68
+ await sleep(1200)
69
+ const afterClear = await page.evaluate(() => document.querySelectorAll('.nodes-table tbody tr').length)
70
+ ok('/daq 清空搜索恢复全量', afterClear === 227, `rows=${afterClear}`)
71
+
72
+ // ---------- 4. /daq/[id] 详情页(由行内控制台链接进入) ----------
73
+ const detailHref = await page.evaluate(() => document.querySelector('.nodes-table .console-link')?.getAttribute('href'))
74
+ await page.goto(`${ROOT}${detailHref}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
75
+ await sleep(6000)
76
+ const detail = await page.evaluate(() => ({
77
+ bigVal: document.querySelector('.big-val')?.textContent?.trim() ?? '',
78
+ liveCanvas: !!document.querySelector('.live-canvas'),
79
+ histCanvas: !!document.querySelector('.hist-canvas'),
80
+ facts: document.querySelectorAll('.facts div').length,
81
+ }))
82
+ ok('/daq/[id] 大值卡渲染', /\d/.test(detail.bigVal), detail.bigVal.slice(0, 30))
83
+ ok('/daq/[id] live 趋势画布存在', detail.liveCanvas)
84
+ ok('/daq/[id] 历史画布存在', detail.histCanvas)
85
+ ok('/daq/[id] 参数事实表渲染', detail.facts >= 5, `facts=${detail.facts}`)
86
+
87
+ // ---------- 5. /town 场景 + 仪表化 + 模型预览 ----------
88
+ await page.goto(`${ROOT}/town`, { waitUntil: 'domcontentloaded', timeout: 60000 })
89
+ await sleep(18000)
90
+ const town1 = await page.evaluate(() => ({
91
+ canvas: !!document.querySelector('#town-host canvas'),
92
+ stats: window.__townStats ? { ...window.__townStats } : null,
93
+ }))
94
+ ok('/town 3D 画布挂载', town1.canvas)
95
+ ok('/town 仪表化 __townStats 存在', !!town1.stats)
96
+ ok('/town 场景实体(Agent/设备)', !!town1.stats && town1.stats.agents >= 12 && town1.stats.devices >= 30, `agents=${town1.stats?.agents} devices=${town1.stats?.devices}`)
97
+ ok('/town 帧率 > 0(墙钟)', !!town1.stats && town1.stats.fps > 0, `fps=${town1.stats?.fps} rafHz=${town1.stats?.rafHz}`)
98
+ ok('/town 60fps 预算生效', !!town1.stats && town1.stats.frameBudgetMs === 16.67, `frameBudgetMs=${town1.stats?.frameBudgetMs}`)
99
+ const town2 = await page.evaluate(() => new Promise((resolve) => {
100
+ const s0 = JSON.stringify(window.__townStats)
101
+ setTimeout(() => resolve({ s0, s1: JSON.stringify(window.__townStats) }), 3000)
102
+ }))
103
+ ok('/town 仪表化持续更新', town2.s0 !== town2.s1)
104
+
105
+ // 打开模型库抽屉(若存在入口按钮)→ 预览卡渲染不崩
106
+ const libOpened = await page.evaluate(() => {
107
+ const btn = [...document.querySelectorAll('button, .hud-btn, [class*="lib"]')].find(b => /模型/.test(b.textContent ?? ''))
108
+ if (btn) { btn.click(); return true }
109
+ return false
110
+ })
111
+ if (libOpened) {
112
+ await sleep(4000)
113
+ const previews = await page.evaluate(() => document.querySelectorAll('.model-preview-3d canvas').length)
114
+ ok('/town 模型库打开且预览卡有画布', previews > 0, `previews=${previews}`)
115
+ }
116
+ await page.screenshot({ path: '.e2e-shots/regression-town.png' })
117
+
118
+ // ---------- 6. 全局页面 smoke(200 + 无 pageerror) ----------
119
+ for (const path of ['/workshop', '/dcw', '/logs', '/monitor', '/settings', '/users', '/permissions']) {
120
+ const resp = await page.goto(`${ROOT}${path}`, { waitUntil: 'domcontentloaded', timeout: 60000 }).then(r => r.status()).catch(() => 0)
121
+ await sleep(1500)
122
+ ok(`smoke ${path}`, resp === 200, `status=${resp}`)
123
+ }
124
+
125
+ ok('全程无 pageerror', pageErrors.length === 0, pageErrors.slice(0, 3).join(' | '))
126
+ const failed = results.filter(r => !r.pass)
127
+ writeFileSync('.e2e-shots/render-regression.json', JSON.stringify({ at: new Date().toISOString(), base: ROOT, passed: results.length - failed.length, failed: failed.length, results }, null, 2))
128
+ console.log(`\n==== ${results.length - failed.length}/${results.length} PASS ====${failed.length ? ' FAILED: ' + failed.map(f => f.name).join(', ') : ''}`)
129
+ await browser.close()
130
+ process.exit(failed.length ? 1 : 0)