agentworkshop 0.7.39 → 0.7.41

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 (405) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +55 -0
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +55 -0
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/88GOowgO2.js +1 -0
  5. package/.output/public/_nuxt/{BNT8gYU92.js → BC9wjTJK2.js} +2 -2
  6. package/.output/public/_nuxt/{CY9LbPCI.js → BN16aRdQ.js} +1 -1
  7. package/.output/public/_nuxt/BWVhZntO.js +1 -0
  8. package/.output/public/_nuxt/{HBLJ-wei.js → BXxH0UQE.js} +1 -1
  9. package/.output/public/_nuxt/{zIGh7R49.js → BneN7fbu.js} +1 -1
  10. package/.output/public/_nuxt/BsROmY89.js +1 -0
  11. package/.output/public/_nuxt/{DUrecWPx.js → C0ZrS1KL.js} +2 -2
  12. package/.output/public/_nuxt/{C_OLzD09.js → C4oW1HsE.js} +1 -1
  13. package/.output/public/_nuxt/{CUDwzgLV.js → C4s_niy-.js} +9 -9
  14. package/.output/public/_nuxt/CFxtLwjp.js +1 -0
  15. package/.output/public/_nuxt/{Cec0Ua3F.js → CS50LB_l.js} +1 -1
  16. package/.output/public/_nuxt/CssgYAAL2.js +1 -0
  17. package/.output/public/_nuxt/D6mbFA-a.js +1 -0
  18. package/.output/public/_nuxt/D98NH8kG.js +1 -0
  19. package/.output/public/_nuxt/DGIuvyRN2.js +1 -0
  20. package/.output/public/_nuxt/DGbd-UiG.js +1 -0
  21. package/.output/public/_nuxt/{CojCTLKD.js → DGj-WEBg.js} +1 -1
  22. package/.output/public/_nuxt/{DDShH71m.js → DS8qj8EL.js} +1 -1
  23. package/.output/public/_nuxt/DTFCy6h-.js +1 -0
  24. package/.output/public/_nuxt/{DrYV5i68.js → DUjW5Yq5.js} +1 -1
  25. package/.output/public/_nuxt/{45zuyAso.js → D_OTvQza.js} +1 -1
  26. package/.output/public/_nuxt/Dap5PmTL.js +2 -0
  27. package/.output/public/_nuxt/Dqw1lpr-.js +1 -0
  28. package/.output/public/_nuxt/DvLxILQP.js +1 -0
  29. package/.output/public/_nuxt/IREZ1eC2.js +1 -0
  30. package/.output/public/_nuxt/TownView.f-YOdXRs.css +1 -0
  31. package/.output/public/_nuxt/_id_.D9ymtHB5.css +1 -0
  32. package/.output/public/_nuxt/_id_.jf-_8E_c.css +1 -0
  33. package/.output/public/_nuxt/_wsId_.B4WiqkIS.css +1 -0
  34. package/.output/public/_nuxt/agents.ZD0rVdHE.css +1 -0
  35. package/.output/public/_nuxt/aml.BN8ZEW4h.css +1 -0
  36. package/.output/public/_nuxt/builds/latest.json +1 -1
  37. package/.output/public/_nuxt/builds/meta/78a295bb-2072-48a4-8b46-6d545fdae743.json +1 -0
  38. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  39. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +1 -0
  40. package/.output/public/_nuxt/daq.DjSgY94l.css +1 -0
  41. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +1 -0
  42. package/.output/public/_nuxt/default.J32SgqFY.css +1 -0
  43. package/.output/public/_nuxt/entry.bdm0tv6M.css +1 -0
  44. package/.output/public/_nuxt/eqq3wWQF.js +18 -0
  45. package/.output/public/_nuxt/logs.BpKzmKsh.css +1 -0
  46. package/.output/public/_nuxt/monitor.D9pe7qN6.css +1 -0
  47. package/.output/public/_nuxt/pages.D7aSDlUI.css +1 -0
  48. package/.output/public/_nuxt/permissions.DwTVlFe6.css +1 -0
  49. package/.output/public/_nuxt/plugins.sb4nDGqr.css +1 -0
  50. package/.output/public/_nuxt/{Cbq-mryP.js → qr6R6Ha1.js} +1 -1
  51. package/.output/public/_nuxt/settings.BTgR-NiE.css +1 -0
  52. package/.output/public/_nuxt/teams.CxnxKVVs.css +1 -0
  53. package/.output/public/_nuxt/tokens.BFY7qv4f.css +1 -0
  54. package/.output/public/_nuxt/{town.DKIAhKnx.css → town.BBXZmeoP.css} +1 -1
  55. package/.output/public/_nuxt/users.DLgZ1D0h.css +1 -0
  56. package/.output/public/_nuxt/workshop.CR_QzeAN.css +1 -0
  57. package/.output/public/_nuxt/{BzHEilTt.js → xh3_vYcu.js} +1 -1
  58. package/.output/public/_nuxt/yF0aYMF1.js +4 -0
  59. package/.output/server/chunks/_/entity.mjs.map +1 -1
  60. package/.output/server/chunks/_/nitro.mjs +2355 -1362
  61. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  62. package/.output/server/chunks/build/{TownView-jVazYOjN.mjs → TownView--otsnr_7.mjs} +290 -208
  63. package/.output/server/chunks/build/TownView--otsnr_7.mjs.map +1 -0
  64. package/.output/server/chunks/build/{_id_-CfVosNg3.mjs → _id_-Brv-JSvr.mjs} +142 -141
  65. package/.output/server/chunks/build/_id_-Brv-JSvr.mjs.map +1 -0
  66. package/.output/server/chunks/build/{_id_-Hwr4rZpr.mjs → _id_-D9pl1OZy.mjs} +38 -36
  67. package/.output/server/chunks/build/_id_-D9pl1OZy.mjs.map +1 -0
  68. package/.output/server/chunks/build/{_wsId_-BVg3bB77.mjs → _wsId_-BASfDf0s.mjs} +295 -261
  69. package/.output/server/chunks/build/{_wsId_-BVg3bB77.mjs.map → _wsId_-BASfDf0s.mjs.map} +1 -1
  70. package/.output/server/chunks/build/{agents-Bvin73QY.mjs → agents-CLQqJF2y.mjs} +21 -27
  71. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +1 -0
  72. package/.output/server/chunks/build/{aml-BCSJCdX7.mjs → aml-_7FdFL2p.mjs} +109 -109
  73. package/.output/server/chunks/build/{aml-BCSJCdX7.mjs.map → aml-_7FdFL2p.mjs.map} +1 -1
  74. package/.output/server/chunks/build/api-error-dul30BYQ.mjs.map +1 -1
  75. package/.output/server/chunks/build/{channel-templates-BTq8570n.mjs → channel-templates-p6SZNjlM.mjs} +19 -19
  76. package/.output/server/chunks/build/{channel-templates-BTq8570n.mjs.map → channel-templates-p6SZNjlM.mjs.map} +1 -1
  77. package/.output/server/chunks/build/{daq-C03Uu5UE.mjs → daq-DkMvD8sg.mjs} +193 -126
  78. package/.output/server/chunks/build/daq-DkMvD8sg.mjs.map +1 -0
  79. package/.output/server/chunks/build/{dcw-6vEYVeje.mjs → dcw-C1jgVJkO.mjs} +46 -46
  80. package/.output/server/chunks/build/{dcw-6vEYVeje.mjs.map → dcw-C1jgVJkO.mjs.map} +1 -1
  81. package/.output/server/chunks/build/{default-CZmZFpqH.mjs → default-BE4r0FZN.mjs} +152 -58
  82. package/.output/server/chunks/build/{default-CZmZFpqH.mjs.map → default-BE4r0FZN.mjs.map} +1 -1
  83. package/.output/server/chunks/build/{logs-B-xhuqln.mjs → logs--dByNyhw.mjs} +35 -35
  84. package/.output/server/chunks/build/{logs-B-xhuqln.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  85. package/.output/server/chunks/build/{monitor-CyfDt4nR.mjs → monitor-C0okQaXz.mjs} +33 -33
  86. package/.output/server/chunks/build/{monitor-CyfDt4nR.mjs.map → monitor-C0okQaXz.mjs.map} +1 -1
  87. package/.output/server/chunks/build/{pages-BO7yZsXA.mjs → pages-B0bUWnC6.mjs} +35 -19
  88. package/.output/server/chunks/build/pages-B0bUWnC6.mjs.map +1 -0
  89. package/.output/server/chunks/build/{permissions-B52oOmaO.mjs → permissions-68SsNjex.mjs} +12 -12
  90. package/.output/server/chunks/build/{permissions-B52oOmaO.mjs.map → permissions-68SsNjex.mjs.map} +1 -1
  91. package/.output/server/chunks/build/{plugins-CUWmMdyt.mjs → plugins-lGlUr1lj.mjs} +17 -17
  92. package/.output/server/chunks/build/{plugins-CUWmMdyt.mjs.map → plugins-lGlUr1lj.mjs.map} +1 -1
  93. package/.output/server/chunks/build/{settings-DoQ2Oq3P.mjs → settings-Ddd1qx2Z.mjs} +50 -47
  94. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +1 -0
  95. package/.output/server/chunks/build/{teams-2kz3CusY.mjs → teams-MEDLZdMn.mjs} +38 -34
  96. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +1 -0
  97. package/.output/server/chunks/build/{tokens-BbWLqtVz.mjs → tokens-C7fTM5C2.mjs} +14 -14
  98. package/.output/server/chunks/build/{tokens-BbWLqtVz.mjs.map → tokens-C7fTM5C2.mjs.map} +1 -1
  99. package/.output/server/chunks/build/{town-BOl6hs9B.mjs → town-CoQdblbZ.mjs} +38 -12
  100. package/.output/server/chunks/build/town-CoQdblbZ.mjs.map +1 -0
  101. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  102. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  103. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  104. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  105. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs +49 -0
  106. package/.output/server/chunks/build/useResponsive-BKDMGTHs.mjs.map +1 -0
  107. package/.output/server/chunks/build/{users-fohSmF-J.mjs → users-Cfd5-l2-.mjs} +6 -6
  108. package/.output/server/chunks/build/{users-fohSmF-J.mjs.map → users-Cfd5-l2-.mjs.map} +1 -1
  109. package/.output/server/chunks/build/{workshop-DX5-ldc4.mjs → workshop-BL5bhfs0.mjs} +15 -15
  110. package/.output/server/chunks/build/{workshop-DX5-ldc4.mjs.map → workshop-BL5bhfs0.mjs.map} +1 -1
  111. package/.output/server/chunks/build/{workspaces-BuydxM-3.mjs → workspaces-Bgz5Ekwp.mjs} +18 -3
  112. package/.output/server/chunks/build/workspaces-Bgz5Ekwp.mjs.map +1 -0
  113. package/.output/server/chunks/routes/api/system/config-groups/_id_.patch.mjs.map +1 -1
  114. package/.output/server/chunks/routes/api/system/index.patch.mjs.map +1 -1
  115. package/.output/server/chunks/routes/api/system/index.post.mjs.map +1 -1
  116. package/.output/server/chunks/routes/api/system/settings/events.get.mjs.map +1 -1
  117. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +6 -2
  118. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
  119. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +2 -1
  120. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs.map +1 -1
  121. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  122. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  123. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs.map +1 -1
  124. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs.map +1 -1
  125. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs.map +1 -1
  126. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +3 -2
  127. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs.map +1 -1
  128. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -1
  129. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs.map +1 -1
  130. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +8 -6
  131. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs.map +1 -1
  132. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +5 -5
  133. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs.map +1 -1
  134. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +14 -4
  135. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs.map +1 -1
  136. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +4 -4
  137. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs.map +1 -1
  138. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +4 -3
  139. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs.map +1 -1
  140. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +31 -0
  141. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs.map +1 -0
  142. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +28 -0
  143. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs.map +1 -0
  144. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  145. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  146. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs.map +1 -1
  147. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +32 -0
  148. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs.map +1 -0
  149. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +34 -0
  150. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs.map +1 -0
  151. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +33 -0
  152. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs.map +1 -0
  153. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +34 -0
  154. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs.map +1 -0
  155. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  156. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  157. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  158. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  159. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  163. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  164. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +5 -1
  165. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  166. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +3 -1
  167. package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
  168. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  169. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  170. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  173. package/.output/server/chunks/routes/renderer.mjs +3 -3
  174. package/.output/server/chunks/virtual/entry.mjs +51 -25
  175. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  176. package/.output/server/package.json +1 -1
  177. package/README-zh.md +203 -39
  178. package/README.md +739 -591
  179. package/app/app.vue +9 -3
  180. package/app/assets/css/main.css +517 -7
  181. package/app/components/AppHeader.vue +98 -7
  182. package/app/components/AppSidebar.vue +117 -11
  183. package/app/components/AwChart.vue +2 -1
  184. package/app/components/workshop/AgentInspectorDrawer.vue +6 -6
  185. package/app/components/workshop/AgentLanesView.vue +52 -1
  186. package/app/components/workshop/AssetLibrary.vue +4 -2
  187. package/app/components/workshop/ChannelSessionList.vue +4 -2
  188. package/app/components/workshop/Composer.vue +96 -0
  189. package/app/components/workshop/DaqNodeRow.vue +19 -0
  190. package/app/components/workshop/DaqTemplateIcon.vue +33 -0
  191. package/app/components/workshop/DeviceTwinPanel.vue +37 -35
  192. package/app/components/workshop/EventBlock.vue +3 -3
  193. package/app/components/workshop/InspectorPanel.vue +47 -11
  194. package/app/components/workshop/LiveAgentBar.vue +34 -0
  195. package/app/components/workshop/TaskBoardView.vue +83 -33
  196. package/app/components/workshop/TranscriptTimeline.vue +56 -0
  197. package/app/components/workshop/blocks/ClusterError.vue +1 -1
  198. package/app/components/workshop/blocks/ClusterRoute.vue +3 -1
  199. package/app/components/workshop/blocks/ClusterStatus.vue +2 -2
  200. package/app/components/workshop/blocks/ClusterStream.vue +8 -2
  201. package/app/components/workshop/town/ModelPreview3D.vue +1 -1
  202. package/app/components/workshop/town/TownView.vue +507 -82
  203. package/app/composables/useResponsive.ts +88 -0
  204. package/app/composables/useRouteMeta.ts +3 -0
  205. package/app/composables/workshop/useDaqStream.ts +7 -4
  206. package/app/composables/workshop/useDcwStream.ts +8 -2
  207. package/app/composables/workshop/useVisibleInterval.ts +2 -2
  208. package/app/composables/workshop/useWorkshopApi.ts +1 -1
  209. package/app/layouts/default.vue +46 -2
  210. package/app/pages/aml/index.vue +712 -616
  211. package/app/pages/daq/[id].vue +12 -7
  212. package/app/pages/daq/index.vue +216 -13
  213. package/app/pages/dcw/[id].vue +117 -32
  214. package/app/pages/dcw/index.vue +83 -23
  215. package/app/pages/index.vue +35 -1
  216. package/app/pages/logs/index.vue +147 -13
  217. package/app/pages/monitor.vue +56 -12
  218. package/app/pages/permissions/index.vue +34 -0
  219. package/app/pages/plugins/index.vue +35 -4
  220. package/app/pages/settings.vue +90 -21
  221. package/app/pages/tokens.vue +23 -0
  222. package/app/pages/town.vue +50 -5
  223. package/app/pages/users.vue +23 -0
  224. package/app/pages/workshop/agents.vue +92 -2
  225. package/app/pages/workshop/channel-templates.vue +53 -0
  226. package/app/pages/workshop/index.vue +14 -0
  227. package/app/pages/workshop/teams.vue +66 -6
  228. package/app/pages/workshop/w/[wsId].vue +202 -14
  229. package/app/plugins/aw-plugins.client.ts +13 -8
  230. package/app/stores/app.ts +33 -1
  231. package/app/stores/workshop/user.ts +1 -1
  232. package/app/stores/workshop/workspaces.ts +18 -2
  233. package/app/utils/api-error.ts +1 -1
  234. package/cli/commands/build.mjs +8 -1
  235. package/docker-compose.yml +6 -0
  236. package/docs/cli.en.md +2 -2
  237. package/docs/cli.md +2 -2
  238. package/docs/plugins.en.md +33 -1
  239. package/docs/plugins.md +29 -1
  240. package/docs/sdk.en.md +1 -1
  241. package/docs/sdk.md +1 -1
  242. package/i18n/locales/en.ts +2 -0
  243. package/i18n/locales/zh-CN.ts +2 -0
  244. package/nuxt.config.ts +31 -0
  245. package/package.json +11 -2
  246. package/scripts/_dbg-param-map-e2e.ts +242 -0
  247. package/scripts/_dbg-param-map-rest-smoke.mjs +73 -0
  248. package/scripts/_dbg-param-real-scenario.mjs +153 -0
  249. package/scripts/_loop-biax-campaign.mjs +124 -0
  250. package/scripts/api-live-e2e.mjs +40 -8
  251. package/scripts/capture-walkthrough.mjs +232 -0
  252. package/scripts/render-walkthrough-figure.mjs +46 -0
  253. package/scripts/seed-walkthrough-fixture.mjs +143 -0
  254. package/scripts/test-plugin-hardening.mjs +8 -0
  255. package/scripts/test-serial-bridge.mjs +418 -0
  256. package/scripts/ui/admin-shots.mjs +46 -0
  257. package/scripts/ui/audit-layout.mjs +301 -0
  258. package/scripts/ui/bump-microfont.mjs +39 -0
  259. package/scripts/ui/e2e-interactive.mjs +328 -0
  260. package/scripts/ui/lib.mjs +198 -0
  261. package/scripts/ui/linkcheck2.mjs +37 -0
  262. package/scripts/ui/live-render-check.mjs +72 -0
  263. package/scripts/ui/md-lint.mjs +80 -0
  264. package/scripts/ui/perf-audit.mjs +132 -0
  265. package/scripts/ui/readme-assets.mjs +30 -0
  266. package/scripts/ui/readme-shots.mjs +42 -0
  267. package/scripts/ui/record.mjs +225 -0
  268. package/scripts/ui/seed-admin.mjs +68 -0
  269. package/scripts/ui/seed-demo.mjs +83 -0
  270. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  271. package/scripts/ui/shot-hero.mjs +25 -0
  272. package/scripts/ui/shots.mjs +75 -0
  273. package/scripts/ui/sim-ui-shot.mjs +16 -0
  274. package/scripts/ui/verify-nav.mjs +51 -0
  275. package/scripts/ui/verify-responsive.mjs +285 -0
  276. package/server/api/system/config-groups/[id].patch.ts +1 -1
  277. package/server/api/system/config-groups/index.post.ts +1 -1
  278. package/server/api/system/settings/events.get.ts +1 -1
  279. package/server/api/system/settings/index.patch.ts +1 -1
  280. package/server/api/workshop/agent-tools/invoke.post.ts +16 -2
  281. package/server/api/workshop/aml/datasets/[id].get.ts +8 -1
  282. package/server/api/workshop/daq/index.get.ts +3 -1
  283. package/server/api/workshop/daq/infra/reconnect.post.ts +1 -1
  284. package/server/api/workshop/daq/templates/[key].delete.ts +1 -0
  285. package/server/api/workshop/daq/templates/[key].patch.ts +1 -0
  286. package/server/api/workshop/daq/templates/index.post.ts +1 -0
  287. package/server/api/workshop/dcw/[id]/write.post.ts +10 -2
  288. package/server/api/workshop/dcw/[id].delete.ts +5 -2
  289. package/server/api/workshop/dcw/index.get.ts +5 -0
  290. package/server/api/workshop/dcw/lines/[id].patch.ts +1 -1
  291. package/server/api/workshop/dcw/params/[id]/read.post.ts +17 -0
  292. package/server/api/workshop/dcw/params/[id]/write.post.ts +21 -0
  293. package/server/api/workshop/dcw/params/[id].delete.ts +19 -0
  294. package/server/api/workshop/dcw/params/[id].patch.ts +23 -0
  295. package/server/api/workshop/dcw/params/index.get.ts +27 -0
  296. package/server/api/workshop/dcw/params/index.post.ts +25 -0
  297. package/server/api/workshop/permissions/index.get.ts +3 -1
  298. package/server/plugins/aw-plugins.ts +23 -10
  299. package/server/plugins/dev-stability-guard.ts +3 -1
  300. package/server/plugins/system-config.ts +6 -1
  301. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  302. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  303. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  304. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  305. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  306. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  307. package/server/services/system-config.ts +28 -9
  308. package/server/services/workshop/agents/adapters/one-shot-cli-agent.ts +2 -1
  309. package/server/services/workshop/agents/agent-interface.ts +8 -6
  310. package/server/services/workshop/agents/base-agent.ts +18 -4
  311. package/server/services/workshop/agents/claude-agent.ts +7 -3
  312. package/server/services/workshop/agents/codex-agent.ts +3 -3
  313. package/server/services/workshop/agents/dsh-agent.ts +3 -3
  314. package/server/services/workshop/agents/goose-agent.ts +0 -1
  315. package/server/services/workshop/agents/harness-terminal.ts +14 -1
  316. package/server/services/workshop/agents/hermes-agent.ts +4 -2
  317. package/server/services/workshop/agents/host-tool-bridge.ts +5 -1
  318. package/server/services/workshop/agents/industrial-context.ts +4 -1
  319. package/server/services/workshop/agents/industrial-tools.ts +164 -6
  320. package/server/services/workshop/agents/omp-agent.ts +15 -9
  321. package/server/services/workshop/agents/opencode-agent.ts +47 -21
  322. package/server/services/workshop/agents/qwen-agent.ts +10 -5
  323. package/server/services/workshop/aml/entity.ts +3 -1
  324. package/server/services/workshop/aml/python-runtime.ts +3 -2
  325. package/server/services/workshop/daq/bus/mqtt.adapter.ts +8 -4
  326. package/server/services/workshop/daq/daq-controller.ts +25 -5
  327. package/server/services/workshop/daq/daq-runtime.ts +5 -3
  328. package/server/services/workshop/daq/drivers.ts +141 -11
  329. package/server/services/workshop/daq/host-ports.ts +3 -2
  330. package/server/services/workshop/daq/storage/timescale.adapter.ts +3 -1
  331. package/server/services/workshop/db/channel.repo.ts +4 -0
  332. package/server/services/workshop/db/ops.repo.ts +5 -2
  333. package/server/services/workshop/db/retention.ts +8 -3
  334. package/server/services/workshop/dcw/dcw-controller.ts +147 -16
  335. package/server/services/workshop/dcw/dcw-product.repo.ts +38 -1
  336. package/server/services/workshop/dcw/dcw-runtime.ts +3 -2
  337. package/server/services/workshop/dcw/drivers.ts +90 -4
  338. package/server/services/workshop/dcw/param-conversion.ts +78 -0
  339. package/server/services/workshop/dcw/param-limits.ts +142 -0
  340. package/server/services/workshop/dcw/param-map.repo.ts +305 -0
  341. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  342. package/server/services/workshop/dcw/recipe-rollback-manager.ts +13 -7
  343. package/server/services/workshop/plugins/host.mjs +30 -0
  344. package/server/services/workshop/runtime/agent-runtime.ts +4 -0
  345. package/server/services/workshop/runtime/manager.ts +9 -2
  346. package/server/services/workshop/settings.ts +4 -2
  347. package/server/types/pg.d.ts +49 -0
  348. package/server/utils/stability-severity.ts +13 -2
  349. package/shared/config/groups.mjs +22 -1
  350. package/shared/config/home.d.mts +28 -0
  351. package/shared/daq-protocol.ts +15 -0
  352. package/shared/dcw-protocol.ts +136 -0
  353. package/uno.config.ts +12 -1
  354. package/.output/public/_nuxt/8NMOXZOV.js +0 -1
  355. package/.output/public/_nuxt/BFkgkW8u.js +0 -4
  356. package/.output/public/_nuxt/C5gUkRwn.js +0 -1
  357. package/.output/public/_nuxt/CM12FuB42.js +0 -1
  358. package/.output/public/_nuxt/CZiw7sEV.js +0 -1
  359. package/.output/public/_nuxt/Cc_9VzD42.js +0 -1
  360. package/.output/public/_nuxt/CdPzkOMV.js +0 -1
  361. package/.output/public/_nuxt/CmsOtOAA2.js +0 -1
  362. package/.output/public/_nuxt/D1YDxZpZ.js +0 -1
  363. package/.output/public/_nuxt/D20Yamr4.js +0 -1
  364. package/.output/public/_nuxt/DAe0h2MB.js +0 -1
  365. package/.output/public/_nuxt/DmqknNvV.js +0 -18
  366. package/.output/public/_nuxt/DnUuIR83.js +0 -1
  367. package/.output/public/_nuxt/S_fVQwJK.js +0 -1
  368. package/.output/public/_nuxt/TownView.0oLiQgTC.css +0 -1
  369. package/.output/public/_nuxt/_id_.D-SYuyZb.css +0 -1
  370. package/.output/public/_nuxt/_id_.hma_BU6T.css +0 -1
  371. package/.output/public/_nuxt/_wsId_.B12v3PhY.css +0 -1
  372. package/.output/public/_nuxt/agents.BV70ioCv.css +0 -1
  373. package/.output/public/_nuxt/ahgEJu2R.js +0 -1
  374. package/.output/public/_nuxt/aml.COEKNNqK.css +0 -1
  375. package/.output/public/_nuxt/builds/meta/4457d63f-0866-4cea-b320-04a321f24795.json +0 -1
  376. package/.output/public/_nuxt/channel-templates.C-M5nKcC.css +0 -1
  377. package/.output/public/_nuxt/daq.B3265ZDn.css +0 -1
  378. package/.output/public/_nuxt/dcw.DLYZqEhT.css +0 -1
  379. package/.output/public/_nuxt/default.BXI_fZUi.css +0 -1
  380. package/.output/public/_nuxt/entry.BB-Eeh-J.css +0 -1
  381. package/.output/public/_nuxt/logs.CqFyMrJw.css +0 -1
  382. package/.output/public/_nuxt/monitor.B--1dPzs.css +0 -1
  383. package/.output/public/_nuxt/pages.ooEzrMm9.css +0 -1
  384. package/.output/public/_nuxt/permissions.B1pjGChZ.css +0 -1
  385. package/.output/public/_nuxt/plugins.5e5chZ67.css +0 -1
  386. package/.output/public/_nuxt/pz2JDAM7.js +0 -2
  387. package/.output/public/_nuxt/settings.Dm3M0RLy.css +0 -1
  388. package/.output/public/_nuxt/teams.BC75EGnR.css +0 -1
  389. package/.output/public/_nuxt/tokens.xRb1fSPU.css +0 -1
  390. package/.output/public/_nuxt/users.CXnP2E08.css +0 -1
  391. package/.output/public/_nuxt/workshop.Jk5HxWPE.css +0 -1
  392. package/.output/server/chunks/build/TownView-jVazYOjN.mjs.map +0 -1
  393. package/.output/server/chunks/build/_id_-CfVosNg3.mjs.map +0 -1
  394. package/.output/server/chunks/build/_id_-Hwr4rZpr.mjs.map +0 -1
  395. package/.output/server/chunks/build/agents-Bvin73QY.mjs.map +0 -1
  396. package/.output/server/chunks/build/daq-C03Uu5UE.mjs.map +0 -1
  397. package/.output/server/chunks/build/pages-BO7yZsXA.mjs.map +0 -1
  398. package/.output/server/chunks/build/settings-DoQ2Oq3P.mjs.map +0 -1
  399. package/.output/server/chunks/build/teams-2kz3CusY.mjs.map +0 -1
  400. package/.output/server/chunks/build/town-BOl6hs9B.mjs.map +0 -1
  401. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  402. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  403. package/.output/server/chunks/build/workspaces-BuydxM-3.mjs.map +0 -1
  404. /package/.output/public/_nuxt/{36oeS8_R2.js → 36oeS8_R.js} +0 -0
  405. /package/.output/public/_nuxt/{CYWVXZTS.js → CYWVXZTS2.js} +0 -0
@@ -7,9 +7,9 @@
7
7
  import { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'
8
8
  import { useRoute } from 'vue-router'
9
9
  import { useDcwStream } from '@/app/composables/workshop/useDcwStream'
10
- import { useDaqStream, type DaqFrameLive } from '@/app/composables/workshop/useDaqStream'
10
+ import { useDaqStream, type DaqFrameLive, type DaqTsdbPoint } from '@/app/composables/workshop/useDaqStream'
11
11
  import { useDeviceTwins } from '@/app/composables/workshop/useDeviceTwins'
12
- import { daqKeyFromRef, DAQ_DRIVERS, type DaqDriverKind, type DaqNodeState, type DriverConfigField, type DriverTestResult as DaqDriverTestResult } from '#shared/daq-protocol'
12
+ import { daqKeyFromRef, DAQ_DRIVERS, type DaqDriverCatalogEntry, type DaqDriverKind, type DaqNodeState, type DriverConfigField, type DriverTestResult as DaqDriverTestResult } from '#shared/daq-protocol'
13
13
 
14
14
  const { t } = useI18n()
15
15
 
@@ -129,9 +129,13 @@ watch(node, (n) => {
129
129
  }, { immediate: true })
130
130
 
131
131
  // 驱动连接参数编辑(真实协议:host/register/endpoint...;schema 驱动渲染)
132
+ // 驱动目录:server 权威(内置 + 协议插件自描述;REST 未返回时回落静态目录)
133
+ const driverCatalog = computed<DaqDriverCatalogEntry[]>(() => daq.meta.drivers.length
134
+ ? daq.meta.drivers
135
+ : DAQ_DRIVERS.map(d => ({ ...d })))
132
136
  const driverCfg = ref<Record<string, string | number>>({})
133
137
  const driverFields = computed<DriverConfigField[]>(() =>
134
- DAQ_DRIVERS.find(d => d.kind === form.driver)?.configFields ?? [])
138
+ driverCatalog.value.find(d => d.kind === form.driver)?.configFields ?? [])
135
139
  watch(node, (n) => {
136
140
  if (n) driverCfg.value = { ...(n.driverConfig as Record<string, string | number>) }
137
141
  }, { immediate: true })
@@ -210,7 +214,8 @@ const availableDevices = computed(() =>
210
214
  )
211
215
 
212
216
  // ---------- 历史(时序库) ----------
213
- type ChartRow = { at: number, value?: number, avg?: number, min?: number, max?: number }
217
+ /** 历史点 = 数采时序点(直接用 DaqTsdbPoint:手写副本漏了 state/cnt,模板取值即报错) */
218
+ type ChartRow = DaqTsdbPoint
214
219
  const historyPoints = ref<ChartRow[]>([])
215
220
  const bucketMs = ref<number>(15000)
216
221
  const histLoading = ref(false)
@@ -507,12 +512,12 @@ watch(effectiveRefreshMs, () => armHistTimer())
507
512
  class="input"
508
513
  >
509
514
  <option
510
- v-for="d in DAQ_DRIVERS"
515
+ v-for="d in driverCatalog"
511
516
  :key="d.kind"
512
517
  :value="d.kind"
513
518
  :disabled="d.status === 'planned'"
514
519
  >
515
- {{ d.label }}{{ d.status === 'planned' ? $t('daqDetail.kz8zr9v035') : '' }}
520
+ {{ d.label }}{{ d.plugin ? ' ⌁' : '' }}{{ d.status === 'planned' ? $t('daqDetail.kz8zr9v035') : '' }}
516
521
  </option>
517
522
  </select>
518
523
  </label>
@@ -654,7 +659,7 @@ watch(effectiveRefreshMs, () => armHistTimer())
654
659
  <!-- 驱动连接参数(mock 空;真实协议 schema 动态表单 + 测试连接) -->
655
660
  <template v-if="driverFields.length">
656
661
  <h3 class="sec mt">
657
- {{ $t('daqDetail.k1p9gioa033') }} {{ DAQ_DRIVERS.find(d => d.kind === form.driver)?.label }}
662
+ {{ $t('daqDetail.k1p9gioa033') }} {{ driverCatalog.find(d => d.kind === form.driver)?.label }}
658
663
  </h3>
659
664
  <div class="driver-grid">
660
665
  <label
@@ -9,7 +9,7 @@ import { message } from 'ant-design-vue'
9
9
  import { useDaqStream, type DaqNodeLive } from '@/app/composables/workshop/useDaqStream'
10
10
  import { useDcwStream } from '@/app/composables/workshop/useDcwStream'
11
11
  import { useWorkshopWs } from '@/app/composables/workshop/useWorkshopWs'
12
- import { DAQ_TEMPLATES, DAQ_DRIVERS, DAQ_TEMPLATE_ICONS, daqKeyFromRef, type DaqNodeView, type DaqNodeState, type DriverConfigField, type DriverTestResult as DaqDriverTestResult, type DaqTemplateDef, type DaqTemplateIcon } from '#shared/daq-protocol'
12
+ import { DAQ_TEMPLATES, DAQ_DRIVERS, DAQ_TEMPLATE_ICONS, daqKeyFromRef, type DaqDriverCatalogEntry, type DaqNodeView, type DaqNodeState, type DriverConfigField, type DriverTestResult as DaqDriverTestResult, type DaqTemplateDef, type DaqTemplateIcon } from '#shared/daq-protocol'
13
13
  import { useDeviceTwins } from '@/app/composables/workshop/useDeviceTwins'
14
14
  import { useOpsLog } from '@/app/composables/workshop/useOpsLog'
15
15
  import { useVisibleInterval } from '@/app/composables/workshop/useVisibleInterval'
@@ -263,6 +263,75 @@ const filteredNodes = computed<DaqNodeLive[]>(() => daq.nodes.filter((n) => {
263
263
  return true
264
264
  }))
265
265
 
266
+ /* ── 节点表窗口化渲染(virtual window) ────────────────────────────────────────
267
+ * 为什么必须做:节点表是**全量**渲染的,而每一行都带实时读数 + sparkline,
268
+ * 每次读数合批(500ms)都会点亮所有行。实测 498 个节点时:
269
+ * · DOM 节点 13.5 万
270
+ * · 主线程每秒 ≈3.8 万次 DOM 变更(其中 99.6% 来自这张表)
271
+ * · 帧率掉到 24 FPS、92% 的帧超时、单帧最大间隔 361ms、长任务阻塞 936ms
272
+ * 也就是说"数据刷新太频繁导致卡顿"的根因不是刷新频率,而是**离屏行也在被补丁**。
273
+ *
274
+ * 做法:按页面滚动窗口只挂载可见行 + 上下各 OVERSCAN 行,用两条占位 <tr> 撑起
275
+ * 滚动高度。行的实际高度由 contain-intrinsic-size 固定为 42px(见样式),所以
276
+ * 窗口计算不需要测量 DOM。
277
+ *
278
+ * 为什么用**页面滚动**而不是容器滚动:这张表的滚动条是页面的(.table-card 只负责
279
+ * 横向),所以窗口要跟着 window.scrollY 走。
280
+ */
281
+ const VS_ROW_H = 42
282
+ const VS_OVERSCAN = 8
283
+ const nodesTableRef = ref<HTMLTableElement | null>(null)
284
+ const winStart = ref(0)
285
+ const winEnd = ref(60)
286
+
287
+ const visibleNodes = computed<DaqNodeLive[]>(() => {
288
+ const list = filteredNodes.value
289
+ const s = Math.min(winStart.value, Math.max(0, list.length - 1))
290
+ return list.slice(s, winEnd.value)
291
+ })
292
+ const padTopPx = computed(() => winStart.value * VS_ROW_H)
293
+ const padBottomPx = computed(() => Math.max(0, (filteredNodes.value.length - winEnd.value) * VS_ROW_H))
294
+
295
+ let winRaf = 0
296
+ function updateNodeWindow(): void {
297
+ const el = nodesTableRef.value
298
+ if (!el) return
299
+ const total = filteredNodes.value.length
300
+ const vh = window.innerHeight || 800
301
+ // 表格顶部相对文档的坐标(表头 40px 也算进"还没到第一行")
302
+ const tableTop = el.getBoundingClientRect().top + window.scrollY + 40
303
+ const firstVisible = Math.floor((window.scrollY - tableTop) / VS_ROW_H)
304
+ const count = Math.ceil(vh / VS_ROW_H) + VS_OVERSCAN * 2
305
+ const s = Math.max(0, Math.min(firstVisible - VS_OVERSCAN, Math.max(0, total - 1)))
306
+ const e = Math.max(s, Math.min(total, s + count))
307
+ if (s !== winStart.value) winStart.value = s
308
+ if (e !== winEnd.value) winEnd.value = e
309
+ }
310
+ function scheduleNodeWindow(): void {
311
+ if (winRaf) return
312
+ winRaf = requestAnimationFrame(() => {
313
+ winRaf = 0
314
+ updateNodeWindow()
315
+ })
316
+ }
317
+
318
+ onMounted(() => {
319
+ updateNodeWindow()
320
+ window.addEventListener('scroll', scheduleNodeWindow, { passive: true })
321
+ window.addEventListener('resize', scheduleNodeWindow, { passive: true })
322
+ })
323
+ onBeforeUnmount(() => {
324
+ window.removeEventListener('scroll', scheduleNodeWindow)
325
+ window.removeEventListener('resize', scheduleNodeWindow)
326
+ if (winRaf) cancelAnimationFrame(winRaf)
327
+ })
328
+ // 筛选/搜索改变行数后窗口必须重算(否则会停在旧的切片上,看起来"表空了")
329
+ watch(() => filteredNodes.value.length, () => {
330
+ winStart.value = 0
331
+ winEnd.value = Math.min(filteredNodes.value.length, winEnd.value || 60)
332
+ scheduleNodeWindow()
333
+ })
334
+
266
335
  // 设备名映射(device-twins 注册表;绑定筛选下拉展示用)
267
336
  const deviceTwins = useDeviceTwins()
268
337
  const nodeDevices = new Map<string, string>()
@@ -284,7 +353,10 @@ const addTest = ref<DaqDriverTestResult | null>(null)
284
353
  const addSaving = ref(false)
285
354
  const addError = ref('')
286
355
 
287
- const addDriverMeta = computed(() => DAQ_DRIVERS.find(d => d.kind === addDriver.value))
356
+ // 驱动目录:server 权威(内置 + 协议插件自描述;REST 未返回时回落静态目录)
357
+ const driverCatalog = computed<DaqDriverCatalogEntry[]>(() =>
358
+ daq.meta.drivers.length ? daq.meta.drivers : DAQ_DRIVERS.map(d => ({ ...d })))
359
+ const addDriverMeta = computed(() => driverCatalog.value.find(d => d.kind === addDriver.value))
288
360
  const addFields = computed<DriverConfigField[]>(() => addDriverMeta.value?.configFields ?? [])
289
361
  const driverReady = (kind: string): boolean =>
290
362
  daq.meta.drivers.find(d => d.kind === kind)?.status !== 'planned' && (daq.meta.driverAvailable?.[kind] !== false)
@@ -772,11 +844,11 @@ async function doReconnect(): Promise<void> {
772
844
  class="inp"
773
845
  >
774
846
  <option
775
- v-for="d in DAQ_DRIVERS.filter(x => x.status !== 'planned')"
847
+ v-for="d in driverCatalog.filter(x => x.status !== 'planned')"
776
848
  :key="d.kind"
777
849
  :value="d.kind"
778
850
  >
779
- {{ d.label }}{{ driverReady(d.kind) ? '' : $t('daq.kjbqphp098') }}
851
+ {{ d.label }}{{ d.plugin ? ' ⌁' : '' }}{{ driverReady(d.kind) ? '' : $t('daq.kjbqphp098') }}
780
852
  </option>
781
853
  </select>
782
854
  </label>
@@ -1187,7 +1259,7 @@ async function doReconnect(): Promise<void> {
1187
1259
  class="opt-series"
1188
1260
  >
1189
1261
  <div
1190
- v-for="ch in optSeriesOf[r.id].channels"
1262
+ v-for="ch in (optSeriesOf[r.id]?.channels ?? [])"
1191
1263
  :key="ch.nodeId"
1192
1264
  class="opt-ch"
1193
1265
  >
@@ -1201,7 +1273,7 @@ async function doReconnect(): Promise<void> {
1201
1273
  <span class="mono">{{ ch.ch }} {{ fmtPoint(ch.points.at(-1)?.value ?? ch.points.at(-1)?.avg) }}{{ ch.unit }}</span>
1202
1274
  </div>
1203
1275
  <p
1204
- v-if="optSeriesOf[r.id].channels.length === 0"
1276
+ v-if="(optSeriesOf[r.id]?.channels.length ?? 0) === 0"
1205
1277
  class="opt-empty"
1206
1278
  >
1207
1279
  {{ $t('daq.k1opte002') }}
@@ -1472,7 +1544,10 @@ async function doReconnect(): Promise<void> {
1472
1544
  </div>
1473
1545
  </div>
1474
1546
  </div>
1475
- <table class="nodes-table">
1547
+ <table
1548
+ ref="nodesTableRef"
1549
+ class="nodes-table"
1550
+ >
1476
1551
  <thead>
1477
1552
  <tr>
1478
1553
  <th>{{ $t('daq.k45uio067') }}</th>
@@ -1496,11 +1571,33 @@ async function doReconnect(): Promise<void> {
1496
1571
  </tr>
1497
1572
  </thead>
1498
1573
  <tbody>
1574
+ <!-- 上占位行:撑起"已滚过"的高度,让滚动条与真实全量列表一致 -->
1575
+ <tr
1576
+ v-if="padTopPx > 0"
1577
+ class="vs-pad"
1578
+ aria-hidden="true"
1579
+ >
1580
+ <td
1581
+ :colspan="11"
1582
+ :style="{ height: padTopPx + 'px' }"
1583
+ />
1584
+ </tr>
1499
1585
  <WorkshopDaqNodeRow
1500
- v-for="n in filteredNodes"
1586
+ v-for="n in visibleNodes"
1501
1587
  :key="n.id"
1502
1588
  :n="n"
1503
1589
  />
1590
+ <!-- 下占位行 -->
1591
+ <tr
1592
+ v-if="padBottomPx > 0"
1593
+ class="vs-pad"
1594
+ aria-hidden="true"
1595
+ >
1596
+ <td
1597
+ :colspan="11"
1598
+ :style="{ height: padBottomPx + 'px' }"
1599
+ />
1600
+ </tr>
1504
1601
  <tr v-if="daq.loaded && daq.nodes.length === 0">
1505
1602
  <td colspan="11">
1506
1603
  <div
@@ -1570,9 +1667,15 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
1570
1667
  align-items: center;
1571
1668
  justify-content: space-between;
1572
1669
  }
1573
- .ctrl-left { display: flex; gap: 14px; align-items: center; }
1670
+ /* 窄屏前先写死「不可压缩」:药丸/周期项被 flex 收缩到 min-content → 中文退化成单列竖排。
1671
+ 保持自然宽度,由外层 flex-wrap 决定换行位置。 */
1672
+ .ctrl-left { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; min-width: 0; }
1673
+ .ctrl-left > *, .ctrl-right > * { flex: 0 0 auto; }
1674
+ .aw-pill { flex: 0 0 auto; white-space: nowrap; }
1675
+ /* 行内小按钮(确认/筛选/回滚…)同族:窄屏禁止中文折成两行 */
1676
+ .mini-btn, .mini-act, .pill-btn, .node-toggle { white-space: nowrap; }
1574
1677
  .aw-pill.running { background: var(--accent); }
1575
- .cycle { display: inline-flex; gap: 6px; align-items: center; font-size: 12px; color: var(--ink-faint); }
1678
+ .cycle { display: inline-flex; flex: 0 0 auto; gap: 6px; align-items: center; font-size: 12px; white-space: nowrap; color: var(--ink-faint); }
1576
1679
  .cycle input {
1577
1680
  width: 84px;
1578
1681
  padding: 4px 8px;
@@ -1581,7 +1684,8 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
1581
1684
  border: 1px solid var(--line-strong);
1582
1685
  border-radius: var(--radius-chip);
1583
1686
  }
1584
- .ctrl-metrics { display: flex; gap: 8px; align-items: center; font-size: 11.5px; color: var(--ink-soft); }
1687
+ .ctrl-metrics { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; min-width: 0; font-size: 11.5px; color: var(--ink-soft); }
1688
+ .ctrl-metrics > span { white-space: nowrap; }
1585
1689
  .ctrl-metrics .sep { opacity: 0.4; }
1586
1690
  .ctrl-metrics .warn { color: var(--tone-warning-dot); }
1587
1691
 
@@ -1661,6 +1765,9 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
1661
1765
  }
1662
1766
 
1663
1767
  .table-card { overflow-x: auto; }
1768
+ /* 窗口化占位行:只提供高度,不参与绘制/命中,也不继承单元格内距与下边框
1769
+ (否则占位行会自带一条分割线和一个 9px 内距,滚动高度算不准) */
1770
+ .vs-pad td { padding: 0 !important; border: 0 !important; }
1664
1771
  .nodes-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
1665
1772
  /* 离屏行跳过布局/绘制(102 行长表;contain-intrinsic-size 给出占位高度防滚动条跳动) */
1666
1773
  .nodes-table tbody tr { content-visibility: auto; contain-intrinsic-size: auto 42px; }
@@ -1815,6 +1922,7 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
1815
1922
  /* ---------- 未确认报警条(S5) ---------- */
1816
1923
  .alarm-bar {
1817
1924
  display: flex;
1925
+ flex-wrap: wrap;
1818
1926
  gap: 12px;
1819
1927
  align-items: center;
1820
1928
  padding: 8px 14px;
@@ -1877,8 +1985,8 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
1877
1985
  .alarm-item .ack:hover { opacity: 0.85; border-color: transparent; color: var(--paper-raised); }
1878
1986
 
1879
1987
  /* ---------- 添加节点向导 ---------- */
1880
- .ctrl-right { display: flex; gap: 12px; align-items: center; }
1881
- .add-btn { padding: 8px 16px; font-size: 13px; }
1988
+ .ctrl-right { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; min-width: 0; }
1989
+ .add-btn { padding: 8px 16px; font-size: 13px; white-space: nowrap; }
1882
1990
  .modal-mask {
1883
1991
  position: fixed;
1884
1992
  z-index: 50;
@@ -2110,4 +2218,99 @@ h1 { margin: 2px 0 4px; font-size: 30px; font-weight: 400; letter-spacing: -0.01
2110
2218
  stroke: var(--tone-info-dot);
2111
2219
  stroke-width: 1.5;
2112
2220
  }
2221
+
2222
+ /* ══════════════════════════════════════════════════════════════════════════
2223
+ 页面级自适应加固(375 / 768 / 1440 三档)
2224
+ 根因统一:flex 子项被压缩到 min-content → 中文按钮退化成「单列竖排」,
2225
+ 左右两组控件抢同一行 → 右边缘越界。策略:先禁止压缩(nowrap),
2226
+ 再在窄屏把控制条改成「整行 / 两列」分层排布;筛选区单列堆叠 → 两列网格。
2227
+ ══════════════════════════════════════════════════════════════════════════ */
2228
+ /* —— 标签字号地板(全档位,不只是窄屏)——
2229
+ 本页所有自有小标签原为 9.5–11px,低于「标签 ≥11.5px」验收线;统一抬到 11.5px。
2230
+ 注:节点表行内 10/10.5px 徽标在 app/components/workshop/DaqNodeRow.vue,不在本页职责内。 —— */
2231
+ .badge, .sec-label, .flt, .hint, .strip-label, .strip-label small,
2232
+ .line-pill small, .opt-status, .opt-time, .opt-line2, .mini-act,
2233
+ .src-badge, .kind-chip, .evt-row .t, .opt-count,
2234
+ .infra-banner .txt small { font-size: 11.5px; }
2235
+ .sub { font-size: 13px; }
2236
+ .alarm-item small, .alarm-row small { font-size: 11.5px; }
2237
+
2238
+ @media (max-width: 900px) {
2239
+ /* —— 兜底字号地板:本页任何 small/mono 小字在手持档不得低于 11.5px ——
2240
+ 逐类点名容易漏(实测 infra-banner 的配方名、line-pill 的 mono 小字都漏过),
2241
+ 这里用元素级兜底把整页收口;它放在本媒体块的**最后面**,
2242
+ 同特异度时后写者胜,所以不会破坏上面更细的排版意图。 */
2243
+ .page small,
2244
+ .page small.mono,
2245
+ .page small.mono b {
2246
+ font-size: 11.5px;
2247
+ }
2248
+
2249
+ /* —— 触摸目标:报警「确认」在窄屏只有 44×22,手指点不中 —— */
2250
+ .alarm-item { padding: 6px 10px; }
2251
+ .alarm-item .ack, .mini-btn.ack { min-height: 32px; padding: 4px 12px; white-space: nowrap; }
2252
+ .alarm-row { flex-wrap: wrap; }
2253
+
2254
+ /* —— 窄屏字号地板(正文 ≥12.5px / 标签 ≥11.5px)——
2255
+ 注:侧栏 8.5px/9.5px 属全局层(main.css / AppSidebar.vue),不在本页职责内 —— */
2256
+ .flt, .sec-label, .hint { font-size: 11.5px; }
2257
+ .inp-sel { font-size: 12.5px; }
2258
+ .badge, .strip-label, .line-pill small { font-size: 11.5px; }
2259
+ .ctrl-metrics { font-size: 12px; }
2260
+ .evt-row { font-size: 12.5px; }
2261
+ .evt-row .t, .src-badge, .kind-chip { font-size: 11.5px; }
2262
+ .panel-head { font-size: 13px; }
2263
+ .alarm-item, .alarm-item small, .alarm-row small, .opt-status, .mini-act,
2264
+ .opt-time, .opt-line2, .clear-btn, .opt-count, .strip-label small { font-size: 11.5px; }
2265
+ .tpl-table .range, .opt-empty, .panel-empty { font-size: 12px; }
2266
+ .infra-banner .txt small { font-size: 11.5px; }
2267
+ .m-title { font-size: 16px; }
2268
+ .sub { font-size: 13px; }
2269
+ }
2270
+
2271
+ @media (max-width: 700px) {
2272
+ /* —— 控制器总控条:暂停全部采集 整行;两个周期项两列;两个 CTA 两列 —— */
2273
+ .ctrl-card { padding: 12px 14px 11px; }
2274
+ .ctrl-row { flex-direction: column; align-items: stretch; gap: 12px; }
2275
+ .ctrl-left { gap: 10px; }
2276
+ .ctrl-left > .aw-pill { flex: 1 1 100%; }
2277
+ .ctrl-left > .cycle { flex: 1 1 calc(50% - 5px); justify-content: space-between; }
2278
+ .cycle input { width: 62px; }
2279
+ .ctrl-right { gap: 10px; }
2280
+ .ctrl-metrics { flex: 1 1 100%; }
2281
+ .ctrl-right > .add-btn { flex: 1 1 calc(50% - 5px); }
2282
+
2283
+ /* —— 未确认报警横条:标题独占一行,滚动轨吃满整宽(右侧内容不再被挤掉) —— */
2284
+ .alarm-bar { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; }
2285
+ .bar-label { justify-content: flex-start; }
2286
+ .alarm-scroll { width: 100%; padding-bottom: 3px; }
2287
+ .alarm-item { max-width: 100%; }
2288
+
2289
+ /* —— 节点筛选工具条:单列下拉堆叠 → 两列网格 —— */
2290
+ .tbl-toolbar { flex-direction: column; align-items: stretch; gap: 8px; padding: 11px 12px; }
2291
+ .filters { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; }
2292
+ .filters > .flt { min-width: 0; }
2293
+ .inp-sel { width: 100%; min-width: 0; }
2294
+ .flt-search { width: 100%; }
2295
+ .clear-btn { grid-column: 1 / -1; min-height: 34px; }
2296
+ .count { padding-bottom: 0; }
2297
+
2298
+ /* —— Agent 优化记录:筛选区两列网格;记录行允许换行,长节点名不再被切 —— */
2299
+ .opt-filters { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
2300
+ .opt-filters > .mini-act { grid-column: 1 / -1; min-height: 34px; }
2301
+ .opt-line1 { flex-wrap: wrap; }
2302
+ .opt-node { flex: 1 1 100%; overflow: visible; white-space: normal; }
2303
+ .opt-time { margin-left: 0; }
2304
+ .opt-ch { flex: 1 1 100%; }
2305
+ .opt-spark { flex: 1 1 auto; width: auto; min-width: 96px; }
2306
+
2307
+ /* —— 主表:压缩单元格内边距,缩短横向滚动距离(表格横滚 + 首列 sticky 是全局层设计) —— */
2308
+ .nodes-table th, .nodes-table :deep(td) { padding: 7px 8px; }
2309
+ .table-card { -webkit-overflow-scrolling: touch; }
2310
+ .opt-body.open { max-height: 70vh; }
2311
+
2312
+ /* —— 实时事件行:摘要原来只剩 141px 被省略号切掉 → 换行后独占整宽 —— */
2313
+ .evt-row { flex-wrap: wrap; }
2314
+ .evt-row .txt { flex: 1 1 100%; white-space: normal; overflow: visible; }
2315
+ }
2113
2316
  </style>