agentworkshop 0.7.40 → 0.7.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/B8uy9iRW.js +1 -0
  3. package/.output/public/_nuxt/BGTYYQH-.js +1 -0
  4. package/.output/public/_nuxt/BUmHEJ77.js +2 -0
  5. package/.output/public/_nuxt/BY7YrV_D.js +1 -0
  6. package/.output/public/_nuxt/Bqcgz95s.js +18 -0
  7. package/.output/public/_nuxt/C7UlqPeD.js +1 -0
  8. package/.output/public/_nuxt/CTmDn-YP.js +1 -0
  9. package/.output/public/_nuxt/Cs8pVeVG.js +1 -0
  10. package/.output/public/_nuxt/{DcsCcxp4.js → D98NH8kG.js} +1 -1
  11. package/.output/public/_nuxt/DKySmNPI.js +14 -0
  12. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  13. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  14. package/.output/public/_nuxt/{C_iYD-EB.js → EHlEMRii.js} +1 -1
  15. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  16. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  17. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  18. package/.output/public/_nuxt/{DZshyNLa.js → IREZ1eC2.js} +1 -1
  19. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  20. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  21. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  22. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  23. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  24. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  25. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  26. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  27. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  28. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  29. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  30. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  31. package/.output/public/_nuxt/builds/latest.json +1 -1
  32. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  33. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  34. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  35. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  36. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  37. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  38. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  39. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  40. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  41. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  42. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  43. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  44. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  45. package/.output/server/chunks/_/nitro.mjs +1058 -830
  46. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  47. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  48. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  49. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs → TownView-CJ6IsDCc.mjs} +229 -228
  50. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  51. package/.output/server/chunks/build/{_id_-BU1wfOID.mjs → _id_-CVD_H0ir.mjs} +149 -147
  52. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  53. package/.output/server/chunks/build/{_id_-BYsEua57.mjs → _id_-CtxMb3qp.mjs} +47 -46
  54. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  55. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs → _wsId_-DpY3T-md.mjs} +516 -446
  56. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  58. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  60. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  61. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  62. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  63. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  64. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  65. package/.output/server/chunks/build/{daq-cgyjKmJu.mjs → daq-DWWSKGAV.mjs} +95 -93
  66. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  67. package/.output/server/chunks/build/{dcw-CoTxBlAZ.mjs → dcw-CT8k17_E.mjs} +46 -45
  68. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  69. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  70. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs → logs--dByNyhw.mjs} +2 -2
  72. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  74. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{pages-DFxjn9Xa.mjs → pages-BHcSBM2D.mjs} +26 -20
  76. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  77. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  78. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  79. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  80. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  81. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  82. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  83. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  84. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  85. package/.output/server/chunks/build/{town-qMPql9Se.mjs → town-QJWB5wng.mjs} +5 -4
  86. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  87. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  88. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  89. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  90. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  91. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  92. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  93. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  108. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  109. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +3 -1
  110. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  111. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  116. package/.output/server/chunks/routes/renderer.mjs +2 -2
  117. package/.output/server/chunks/virtual/entry.mjs +639 -88
  118. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  119. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  120. package/.output/server/package.json +1 -1
  121. package/README-zh.md +16 -6
  122. package/README.md +17 -7
  123. package/app/components/AppHeader.vue +961 -959
  124. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  125. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  126. package/app/components/workshop/AgentLanesView.vue +998 -998
  127. package/app/components/workshop/ArtifactCard.vue +120 -120
  128. package/app/components/workshop/AssetLibrary.vue +452 -452
  129. package/app/components/workshop/ChannelSessionList.vue +812 -804
  130. package/app/components/workshop/CommandPalette.vue +269 -269
  131. package/app/components/workshop/Composer.vue +827 -827
  132. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  133. package/app/components/workshop/EventBlock.vue +602 -602
  134. package/app/components/workshop/FileSelectorModal.vue +188 -188
  135. package/app/components/workshop/InspectorPanel.vue +301 -301
  136. package/app/components/workshop/MemoryPanel.vue +364 -364
  137. package/app/components/workshop/MultiChannelView.vue +189 -189
  138. package/app/components/workshop/TaskBoardView.vue +686 -686
  139. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  140. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  141. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  142. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  143. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  144. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  145. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  146. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  147. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  148. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  149. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  150. package/app/components/workshop/town/TownView.vue +56 -56
  151. package/app/composables/workshop/useDaqStream.ts +7 -4
  152. package/app/composables/workshop/useDcwStream.ts +8 -2
  153. package/app/middleware/locale-cookie.global.ts +22 -0
  154. package/app/pages/aml/index.vue +24 -2
  155. package/app/pages/daq/[id].vue +20 -16
  156. package/app/pages/daq/index.vue +2310 -2307
  157. package/app/pages/dcw/[id].vue +26 -23
  158. package/app/pages/dcw/index.vue +3 -3
  159. package/app/pages/index.vue +987 -981
  160. package/app/pages/plugins/index.vue +317 -311
  161. package/app/pages/settings.vue +1564 -1562
  162. package/app/pages/tokens.vue +15 -15
  163. package/app/pages/workshop/agents.vue +612 -609
  164. package/app/pages/workshop/channel-templates.vue +18 -11
  165. package/app/pages/workshop/index.vue +668 -668
  166. package/app/pages/workshop/teams.vue +743 -740
  167. package/app/pages/workshop/w/[wsId].vue +704 -704
  168. package/app/plugins/locale-restore.client.ts +16 -1
  169. package/app/utils/builtin-catalog.ts +104 -0
  170. package/config.yml +170 -170
  171. package/docs/cli.en.md +2 -2
  172. package/docs/cli.md +2 -2
  173. package/docs/full-test-plan.md +2 -3
  174. package/docs/plugins.en.md +33 -1
  175. package/docs/plugins.md +29 -1
  176. package/docs/sdk.en.md +1 -1
  177. package/docs/sdk.md +1 -1
  178. package/i18n/locales/en.ts +293 -35
  179. package/i18n/locales/zh-CN.ts +265 -7
  180. package/package.json +4 -3
  181. package/scripts/_dbg-perms-e2e.mjs +132 -109
  182. package/scripts/_demo-agentteam-capture.mjs +278 -0
  183. package/scripts/_e2e-ui-functional.mjs +371 -0
  184. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  185. package/scripts/_i18n-en-verify.mjs +107 -0
  186. package/scripts/_i18n-extra-checks.mjs +53 -0
  187. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  188. package/scripts/_i18n-verify-keys.mjs +50 -0
  189. package/scripts/_loop-biax-campaign.mjs +130 -0
  190. package/scripts/_sweep-button-contrast.mjs +87 -0
  191. package/scripts/test-serial-bridge.mjs +418 -0
  192. package/scripts/ui/e2e-interactive.mjs +328 -0
  193. package/scripts/ui/record-demo.mjs +557 -0
  194. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  195. package/server/api/workshop/daq/index.get.ts +3 -1
  196. package/server/api/workshop/dcw/index.get.ts +3 -0
  197. package/server/plugins/aw-plugins.ts +9 -7
  198. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  199. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  200. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  201. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  202. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  203. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  204. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  205. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  206. package/server/services/workshop/daq/daq-controller.ts +7 -2
  207. package/server/services/workshop/daq/drivers.ts +89 -3
  208. package/server/services/workshop/dcw/dcw-controller.ts +5 -1
  209. package/server/services/workshop/dcw/drivers.ts +85 -2
  210. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  211. package/server/services/workshop/plugins/host.mjs +30 -0
  212. package/shared/daq-protocol.ts +15 -0
  213. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  214. package/.output/public/_nuxt/BOt2SP4z.js +0 -1
  215. package/.output/public/_nuxt/BP-NyKVG.js +0 -18
  216. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  217. package/.output/public/_nuxt/BsROmY89.js +0 -1
  218. package/.output/public/_nuxt/ClILjvWH.js +0 -1
  219. package/.output/public/_nuxt/CzOCSGLe.js +0 -1
  220. package/.output/public/_nuxt/D8qvkfyY.js +0 -1
  221. package/.output/public/_nuxt/DCn7QZ5N.js +0 -2
  222. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  223. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  224. package/.output/public/_nuxt/Dihnimlk.js +0 -19
  225. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  226. package/.output/public/_nuxt/Dr9v6C0f.js +0 -14
  227. package/.output/public/_nuxt/Du9ZJtnj.js +0 -1
  228. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  229. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  230. package/.output/public/_nuxt/_id_.CM4bIgKY.css +0 -1
  231. package/.output/public/_nuxt/_id_.bNV69Dtf.css +0 -1
  232. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  233. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  234. package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +0 -1
  235. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  236. package/.output/public/_nuxt/daq.B0D3dPAc.css +0 -1
  237. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  238. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  239. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  240. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  241. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  242. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  243. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  244. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  245. package/.output/server/chunks/build/_id_-BU1wfOID.mjs.map +0 -1
  246. package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +0 -1
  247. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  248. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  249. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  250. package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +0 -1
  251. package/.output/server/chunks/build/dcw-CoTxBlAZ.mjs.map +0 -1
  252. package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +0 -1
  253. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  254. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  255. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  256. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  257. package/.output/server/chunks/build/town-qMPql9Se.mjs.map +0 -1
  258. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  259. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  260. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  261. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  262. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  263. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  264. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  265. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  266. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  267. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  268. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  269. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  270. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  271. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  272. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  273. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  274. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  275. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  276. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  277. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  278. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  279. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  280. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  281. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  282. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  283. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  284. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  285. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  286. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  287. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  288. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  289. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  290. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  291. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  292. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  293. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  294. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  295. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  296. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  297. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  298. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  299. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  300. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  301. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  302. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  303. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  304. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  305. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  306. package/scripts/_dbg-minimal-omp.mjs +0 -77
  307. package/scripts/_dbg-mode-nav.mjs +0 -173
  308. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  309. package/scripts/_dbg-team-repro.mjs +0 -76
  310. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  311. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  312. package/scripts/_townview_style.css +0 -1185
  313. package/scripts/_townview_template.html +0 -1215
  314. package/server/data/agent-node-bindings.json +0 -554
  315. package/server/data/daq-templates.json +0 -16
  316. package/server/data/daqs.json +0 -7464
  317. package/server/data/dcw-lines.json +0 -1787
  318. package/server/data/dcw-products.json +0 -1626
  319. package/server/data/dcw-recipes.json +0 -4672
  320. package/server/data/dcw-rollback.json +0 -20754
  321. package/server/data/dcw-runs.json +0 -6354
  322. package/server/data/dcw-templates.json +0 -146
  323. package/server/data/dcw-writes.json +0 -15650
  324. package/server/data/dcws.json +0 -9033
  325. package/server/data/device-twins.json +0 -133
  326. package/server/data/line-runs.json +0 -322
  327. package/server/data/scene-layouts.json +0 -277
@@ -1407,29 +1407,29 @@ const daq = useDaqStream()
1407
1407
  /** 智控流单例(写控制;与数采对称:模板目录/节点/场景/绑定) */
1408
1408
  const dcw = useDcwStream()
1409
1409
  /** 智控模板目录(server 权威;与 daqTemplates 同构投影) */
1410
- const dcwTemplates = reactive(dcw.templates.map(t => ({
1411
- id: t.key,
1412
- name: t.name,
1413
- code: t.code,
1414
- ch: t.ch,
1415
- unit: t.unit,
1416
- min: t.min,
1417
- max: t.max,
1418
- decimals: t.decimals,
1419
- icon: t.icon,
1410
+ const dcwTemplates = reactive(dcw.templates.map(tpl => ({
1411
+ id: tpl.key,
1412
+ name: catalogTplName(t, tpl),
1413
+ code: tpl.code,
1414
+ ch: tpl.ch,
1415
+ unit: tpl.unit,
1416
+ min: tpl.min,
1417
+ max: tpl.max,
1418
+ decimals: tpl.decimals,
1419
+ icon: tpl.icon,
1420
1420
  })))
1421
1421
  watch(() => dcw.templates, (list) => {
1422
1422
  if (!list?.length) return
1423
- dcwTemplates.splice(0, dcwTemplates.length, ...list.map(t => ({
1424
- id: t.key,
1425
- name: t.name,
1426
- code: t.code,
1427
- ch: t.ch,
1428
- unit: t.unit,
1429
- min: t.min,
1430
- max: t.max,
1431
- decimals: t.decimals,
1432
- icon: t.icon,
1423
+ dcwTemplates.splice(0, dcwTemplates.length, ...list.map(tpl => ({
1424
+ id: tpl.key,
1425
+ name: catalogTplName(t, tpl),
1426
+ code: tpl.code,
1427
+ ch: tpl.ch,
1428
+ unit: tpl.unit,
1429
+ min: tpl.min,
1430
+ max: tpl.max,
1431
+ decimals: tpl.decimals,
1432
+ icon: tpl.icon,
1433
1433
  })))
1434
1434
  }, { immediate: true, deep: true })
1435
1435
  /** 左轨树形目录:模板 = 可展开分组(不可拖拽),节点 = 可拖入场景的叶子。
@@ -1523,33 +1523,33 @@ interface DaqTemplate {
1523
1523
  /** 图标(设计稿 ICONS 键) */
1524
1524
  icon: string
1525
1525
  }
1526
- const daqTemplates = reactive<DaqTemplate[]>(DAQ_TEMPLATES.map(t => ({
1527
- id: t.key,
1528
- name: t.name,
1529
- code: t.code,
1530
- ch: t.ch,
1531
- unit: t.unit,
1532
- base: t.base,
1533
- amp: t.amp,
1534
- min: t.min,
1535
- max: t.max,
1536
- decimals: t.decimals,
1537
- icon: t.icon,
1526
+ const daqTemplates = reactive<DaqTemplate[]>(DAQ_TEMPLATES.map(tpl => ({
1527
+ id: tpl.key,
1528
+ name: catalogTplName(t, tpl),
1529
+ code: tpl.code,
1530
+ ch: tpl.ch,
1531
+ unit: tpl.unit,
1532
+ base: tpl.base,
1533
+ amp: tpl.amp,
1534
+ min: tpl.min,
1535
+ max: tpl.max,
1536
+ decimals: tpl.decimals,
1537
+ icon: tpl.icon,
1538
1538
  })))
1539
1539
  watch(() => daq.templates, (list) => {
1540
1540
  if (!list?.length) return
1541
- daqTemplates.splice(0, daqTemplates.length, ...list.map(t => ({
1542
- id: t.key,
1543
- name: t.name,
1544
- code: t.code,
1545
- ch: t.ch,
1546
- unit: t.unit,
1547
- base: t.base,
1548
- amp: t.amp,
1549
- min: t.min,
1550
- max: t.max,
1551
- decimals: t.decimals,
1552
- icon: t.icon,
1541
+ daqTemplates.splice(0, daqTemplates.length, ...list.map(tpl => ({
1542
+ id: tpl.key,
1543
+ name: catalogTplName(t, tpl),
1544
+ code: tpl.code,
1545
+ ch: tpl.ch,
1546
+ unit: tpl.unit,
1547
+ base: tpl.base,
1548
+ amp: tpl.amp,
1549
+ min: tpl.min,
1550
+ max: tpl.max,
1551
+ decimals: tpl.decimals,
1552
+ icon: tpl.icon,
1553
1553
  })))
1554
1554
  }, { immediate: true, deep: true })
1555
1555
  const daqTplById = (ref: string): DaqTemplate | undefined => {
@@ -2969,7 +2969,7 @@ onBeforeUnmount(() => {
2969
2969
  <button
2970
2970
  class="nav-action"
2971
2971
  :disabled="mode !== 'edit'"
2972
- :title="mode === 'edit' ? '把全部设备的位置/朝向/缩放写入数据库' : '运行模式只读'"
2972
+ :title="mode === 'edit' ? $t('townView.saveLayoutTip') : $t('townView.readonlyTip')"
2973
2973
  @click="saveLayout"
2974
2974
  >
2975
2975
  {{ $t('townView.k1b3bk8t029') }}
@@ -3051,7 +3051,7 @@ onBeforeUnmount(() => {
3051
3051
  <button
3052
3052
  type="button"
3053
3053
  class="sheet-x"
3054
- aria-label="关闭"
3054
+ :aria-label="$t('common.close')"
3055
3055
  @click="closeSheet"
3056
3056
  >
3057
3057
  ✕
@@ -3075,7 +3075,7 @@ onBeforeUnmount(() => {
3075
3075
  <button
3076
3076
  class="daq-ctl-btn"
3077
3077
  :class="{ on: daq.controller.running }"
3078
- :title="daq.controller.running ? '暂停全部采集:停止所有启用节点的采样(节点级启停独立)' : '恢复全部采集:仅启用节点恢复采集(手动停用的保持停用)'"
3078
+ :title="daq.controller.running ? $t('townView.daqPauseTip') : $t('townView.daqResumeTip')"
3079
3079
  @click="daq.controllerAction(daq.controller.running ? 'pause' : 'resume')"
3080
3080
  >
3081
3081
  {{ daq.controller.running ? $t('townView.k3w3j8f140') : $t('townView.k3n93ed175') }}
@@ -3271,7 +3271,7 @@ onBeforeUnmount(() => {
3271
3271
  :class="{ active: ch.placed }"
3272
3272
  :draggable="!ch.placed && mode === 'edit'"
3273
3273
  :data-channel-id="ch.channelId"
3274
- :title="ch.placed ? '已在场景中,点击定位' : '拖拽到场景放置'"
3274
+ :title="ch.placed ? $t('townView.chPlaced') : $t('townView.chDragHint')"
3275
3275
  @dragstart="ch.placed ? undefined : onChannelDragStart($event, ch.channelId)"
3276
3276
  @click="onDockCardClick(ch)"
3277
3277
  >
@@ -3388,13 +3388,13 @@ onBeforeUnmount(() => {
3388
3388
  {{ $t('townView.kv72860036') }}
3389
3389
  </option>
3390
3390
  <option value="top">
3391
- 俯视 · TOP
3391
+ {{ $t('townView.viewTop') }}
3392
3392
  </option>
3393
3393
  <option value="front">
3394
- 前视 · FRONT
3394
+ {{ $t('townView.viewFront') }}
3395
3395
  </option>
3396
3396
  <option value="side">
3397
- 侧视 · SIDE
3397
+ {{ $t('townView.viewSide') }}
3398
3398
  </option>
3399
3399
  </select>
3400
3400
  </div>
@@ -3948,7 +3948,7 @@ onBeforeUnmount(() => {
3948
3948
  <button
3949
3949
  type="button"
3950
3950
  class="sheet-x"
3951
- aria-label="关闭"
3951
+ :aria-label="$t('common.close')"
3952
3952
  @click="closeSheet"
3953
3953
  >
3954
3954
  ✕
@@ -4188,7 +4188,7 @@ onBeforeUnmount(() => {
4188
4188
  class="obj-input"
4189
4189
  :placeholder="$t('townView.k1k6vbaf015')"
4190
4190
  :disabled="mode !== 'edit'"
4191
- :title="mode === 'edit' ? '设备名称' : '运行模式只读'"
4191
+ :title="mode === 'edit' ? $t('townView.deviceName') : $t('townView.readonlyTip')"
4192
4192
  @change="onObjNameCommit"
4193
4193
  @keydown.enter="onObjNameCommit"
4194
4194
  >
@@ -4206,7 +4206,7 @@ onBeforeUnmount(() => {
4206
4206
  :key="m.id"
4207
4207
  :value="m.id"
4208
4208
  >
4209
- {{ m.name }}
4209
+ {{ townModelName(t, m) }}
4210
4210
  </option>
4211
4211
  </select>
4212
4212
  </div>
@@ -4432,7 +4432,7 @@ onBeforeUnmount(() => {
4432
4432
  <!-- 变换模式(Blender G/R/S;仅编辑模式) -->
4433
4433
  <template v-if="mode === 'edit'">
4434
4434
  <div class="sect-hd">
4435
- 变换 · BLENDER
4435
+ {{ $t('townView.transformBlender') }}
4436
4436
  </div>
4437
4437
  <div class="xz-seg">
4438
4438
  <button
@@ -4595,7 +4595,7 @@ onBeforeUnmount(() => {
4595
4595
  v-if="!agentBindings.length"
4596
4596
  class="ins-empty"
4597
4597
  >
4598
- 未绑定工业节点 —— 绑定后 Agent 可用 dcw_control / daq_query 工具
4598
+ {{ $t('townView.unboundTip') }}
4599
4599
  </div>
4600
4600
  <div
4601
4601
  v-if="mode === 'edit'"
@@ -10,7 +10,7 @@ import { reactive } from 'vue'
10
10
  import { useTownBus } from './useTownBus'
11
11
  import { apiFetch } from './apiClient'
12
12
  import type { AepEnvelope } from '#shared/workshop-protocol'
13
- import { DAQ_TEMPLATES, type AepDaqControllerState, type AepDaqFrame, type AepDaqReading, type AepDaqNodeChange, type AepDaqTemplateChange, type DaqNodeView, type DaqTemplateDef, type DaqTemplateInput } from '#shared/daq-protocol'
13
+ import { DAQ_TEMPLATES, DAQ_DRIVERS, type AepDaqControllerState, type AepDaqFrame, type AepDaqReading, type AepDaqNodeChange, type AepDaqTemplateChange, type DaqDriverCatalogEntry, type DaqNodeView, type DaqTemplateDef, type DaqTemplateInput } from '#shared/daq-protocol'
14
14
 
15
15
  /** 历史缓冲长度(1s 默认周期 ≈ 最近 5 分钟趋势) */
16
16
  const HIST_CAP = 60
@@ -57,7 +57,8 @@ interface DaqControllerState {
57
57
  interface DaqBackendMeta {
58
58
  tsdb: string
59
59
  queue: string
60
- drivers: Array<{ kind: string, label: string, status: 'builtin' | 'planned' | 'real' }>
60
+ /** 驱动目录(REST `drivers` 权威收敛:内置 + 协议插件自描述;首帧先用内置目录) */
61
+ drivers: DaqDriverCatalogEntry[]
61
62
  produced: number
62
63
  consumed: number
63
64
  dropped: number
@@ -110,7 +111,7 @@ const createStore = () => {
110
111
  const alarms = reactive<DaqAlarmRow[]>([]) // S5:未确认报警(轮询 + ack 后刷新)
111
112
  const controller = reactive<DaqControllerState>({ running: true, defaultIntervalMs: 1000, defaultPublishIntervalMs: 0, queryDisplayIntervalMs: 5000, nodesTotal: 0, nodesOnline: 0 })
112
113
  const meta = reactive<DaqBackendMeta>({
113
- tsdb: '…', queue: '…', drivers: [], driverAvailable: {},
114
+ tsdb: '…', queue: '…', drivers: DAQ_DRIVERS.map(d => ({ kind: d.kind, label: d.label, status: d.status, configFields: d.configFields })), driverAvailable: {},
114
115
  infra: undefined,
115
116
  produced: 0, consumed: 0, dropped: 0, samplesStored: 0,
116
117
  })
@@ -266,7 +267,7 @@ const createStore = () => {
266
267
 
267
268
  async function load(): Promise<void> {
268
269
  try {
269
- const data = await api<{ controller: DaqControllerState, nodes: DaqNodeView[], meta: DaqBackendMeta, driverAvailable?: Record<string, boolean>, infra?: DaqInfraState, templates?: DaqTemplateDef[] }>('')
270
+ const data = await api<{ controller: DaqControllerState, nodes: DaqNodeView[], meta: DaqBackendMeta, driverAvailable?: Record<string, boolean>, drivers?: DaqDriverCatalogEntry[], infra?: DaqInfraState, templates?: DaqTemplateDef[] }>('')
270
271
  // 快照合并:hist 是客户端读数流资产,轮询重载不得清零;
271
272
  // 已有节点就地 assign(保留对象身份 → Vue 只补丁变化字段,不触发整表数组级失效),hist 自然保留
272
273
  const prev = new Map(nodes.map(n => [n.id, n]))
@@ -291,6 +292,8 @@ const createStore = () => {
291
292
  Object.assign(controller, data.controller)
292
293
  Object.assign(meta, data.meta ?? {})
293
294
  meta.driverAvailable = data.driverAvailable ?? {}
295
+ // 驱动目录 server 权威(含协议插件);server 未下发(旧版)时保留内置目录
296
+ if (data.drivers?.length) meta.drivers = data.drivers
294
297
  meta.infra = data.infra
295
298
  if (data.templates?.length) applyTemplates(data.templates)
296
299
  store.loaded = true
@@ -8,7 +8,8 @@ import { reactive } from 'vue'
8
8
  import { useTownBus } from './useTownBus'
9
9
  import { apiFetch } from './apiClient'
10
10
  import type { AepEnvelope } from '#shared/workshop-protocol'
11
- import { DCW_TEMPLATES, type AepDcwControllerState, type AepDcwNodeChange, type AepDcwRead, type AepDcwWritten, type DcwNodeView, type DcwParamLedger, type DcwTemplateDef, type DcwTemplateInput, type LineInput, type LineQueryOpts, type LineQueryResult, type LineRunState, type LineView, type OptimizationRecord, type OptimizationVerdict, type ProductInput, type ProductView, type RecipeInput, type RecipeParam, type RecipeRunView, type RecipeView, type RecipeRunData } from '#shared/dcw-protocol'
11
+ import { DCW_TEMPLATES, DCW_DRIVERS, type AepDcwControllerState, type AepDcwNodeChange, type AepDcwRead, type AepDcwWritten, type DcwNodeView, type DcwParamLedger, type DcwTemplateDef, type DcwTemplateInput, type LineInput, type LineQueryOpts, type LineQueryResult, type LineRunState, type LineView, type OptimizationRecord, type OptimizationVerdict, type ProductInput, type ProductView, type RecipeInput, type RecipeParam, type RecipeRunView, type RecipeView, type RecipeRunData } from '#shared/dcw-protocol'
12
+ import type { DaqDriverCatalogEntry } from '#shared/daq-protocol'
12
13
 
13
14
  export type { DcwNodeView }
14
15
 
@@ -35,6 +36,8 @@ function createStore() {
35
36
  const lineStates = reactive<Record<string, LineRunState>>({})
36
37
  /** Agent 优化记录(调控闭环;dcw.optimization.changed 实时收敛) */
37
38
  const optimizations = reactive<OptimizationRecord[]>([])
39
+ /** 写驱动目录(REST `drivers` 权威:内置 + 协议插件自描述;首帧先用内置目录) */
40
+ const driverCatalog = reactive<DaqDriverCatalogEntry[]>(DCW_DRIVERS.map(d => ({ kind: d.kind, label: d.label, status: d.status, configFields: d.configFields })))
38
41
 
39
42
  function upsert(node: DcwNodeView): void {
40
43
  const i = nodes.findIndex(x => x.id === node.id)
@@ -112,12 +115,14 @@ function createStore() {
112
115
 
113
116
  async function load(): Promise<void> {
114
117
  try {
115
- const data = await api<{ controller: AepDcwControllerState, nodes: DcwNodeView[], templates?: DcwTemplateDef[], recipes?: RecipeView[], runs?: RecipeRunView[], history?: DcwWriteHistoryEntry[], products?: ProductView[], lines?: LineView[], lineStates?: LineRunState[] }>('')
118
+ const data = await api<{ controller: AepDcwControllerState, nodes: DcwNodeView[], templates?: DcwTemplateDef[], drivers?: DaqDriverCatalogEntry[], recipes?: RecipeView[], runs?: RecipeRunView[], history?: DcwWriteHistoryEntry[], products?: ProductView[], lines?: LineView[], lineStates?: LineRunState[] }>('')
116
119
  nodes.splice(0, nodes.length, ...data.nodes)
117
120
  nodeIndex.clear()
118
121
  for (const n of nodes) nodeIndex.set(n.id, n)
119
122
  Object.assign(controller, data.controller)
120
123
  if (data.templates?.length) templates.splice(0, templates.length, ...data.templates.map(t => ({ ...t })))
124
+ // 写驱动目录 server 权威(含协议插件);server 未下发(旧版)时保留内置目录
125
+ if (data.drivers?.length) driverCatalog.splice(0, driverCatalog.length, ...data.drivers)
121
126
  recipes.splice(0, recipes.length, ...(data.recipes ?? []))
122
127
  runs.splice(0, runs.length, ...(data.runs ?? []))
123
128
  history.splice(0, history.length, ...(data.history ?? []))
@@ -144,6 +149,7 @@ function createStore() {
144
149
  lines,
145
150
  lineStates,
146
151
  optimizations,
152
+ driverCatalog,
147
153
  loaded: false,
148
154
  error: '',
149
155
  ensureWsFeed,
@@ -0,0 +1,22 @@
1
+ /**
2
+ * locale cookie 参与 SSR 首帧(与 aw-theme cookie 同一范式)。
3
+ *
4
+ * 为什么必须有:strategy=no_prefix + detectBrowserLanguage=false 下 SSR 恒以 zh 渲染,
5
+ * 客户端 locale 恢复(locale-restore 插件)是异步的 —— 若 setLocale 在水合前落地,
6
+ * prod 水合不修正属性失配(文本会被修正,placeholder 这类 attr 不会),
7
+ * 登录卡输入框曾在 EN 模式下残留中文占位符。cookie 服务端可读,两侧渲染一致,竞态消失。
8
+ *
9
+ * 键名与 localStorage 的 'aw.locale' 同名:header/settings 切换时双写,
10
+ * 本中间件(SSR + 客户端首航都跑)据此在渲染前把 locale 定住。
11
+ */
12
+ export default defineNuxtRouteMiddleware(async () => {
13
+ const cookie = useCookie<string | undefined>('aw.locale')
14
+ const saved = cookie.value
15
+ if (saved !== 'en' && saved !== 'zh-CN') return
16
+ const $i18n = (useNuxtApp() as unknown as {
17
+ $i18n?: { locale: { value: string }, setLocale: (l: string) => Promise<unknown> }
18
+ }).$i18n
19
+ if (!$i18n) return
20
+ // 必须 await:setLocale 未落地就开始渲染的话,SSR 仍是 zh,水合失配回归
21
+ if (saved !== $i18n.locale.value) await $i18n.setLocale(saved)
22
+ })
@@ -304,6 +304,28 @@ const pythonText = computed(() => {
304
304
  const venvText = computed(() =>
305
305
  overview.value ? (overview.value.runtime.venvReady ? tt('aml.k1amlx007') : tt('aml.k1amlx008')) : '--')
306
306
 
307
+ /** 服务端 blocker 是中文数据:已知固定文案映射 i18n,未知(动态 reason)原样透传 */
308
+ const AML_BLOCKER_KEYS: Record<string, string> = {
309
+ '训练环境(./aml/.venv)尚未创建:请在「运行环境」面板点击「创建训练环境」': 'aml.blockerVenv',
310
+ 'Python 解释器不可用': 'aml.blockerPython',
311
+ }
312
+ const blockerText = computed(() =>
313
+ (env.value?.preflight?.blockers ?? [])
314
+ .map(b => (AML_BLOCKER_KEYS[b] ? tt(AML_BLOCKER_KEYS[b]) : b))
315
+ .join(' / '))
316
+
317
+ /** 数据根来源按 amlRootMode 翻译(amlRootSource 是服务端中文标签) */
318
+ const AML_ROOT_SOURCE_KEYS: Record<string, string> = {
319
+ env: 'aml.rootSourceEnv',
320
+ repo: 'aml.rootSourceRepo',
321
+ home: 'aml.rootSourceHome',
322
+ }
323
+ const rootSourceLabel = computed(() => {
324
+ const mode = env.value?.amlRootMode ?? ''
325
+ const key = AML_ROOT_SOURCE_KEYS[mode]
326
+ return key ? tt(key) : (env.value?.amlRootSource ?? '')
327
+ })
328
+
307
329
  // ---------- 1b. 运行环境(uv 检测 / 一键安装 / .venv 供给) ----------
308
330
 
309
331
  /** 完整环境状态(GET /env);比 overview.env 多出任务日志与目录明细 */
@@ -964,7 +986,7 @@ async function doPredict(): Promise<void> {
964
986
  >
965
987
  <span class="i-tabler-alert-triangle" />
966
988
  <span class="txt">
967
- {{ $t('aml.k1amlx178') }}:<b class="mono">{{ env.preflight.blockers.join(' / ') }}</b>
989
+ {{ $t('aml.k1amlx178') }}:<b class="mono">{{ blockerText }}</b>
968
990
  </span>
969
991
  </div>
970
992
 
@@ -1059,7 +1081,7 @@ async function doPredict(): Promise<void> {
1059
1081
  <p class="ec-detail">
1060
1082
  {{ $t('aml.k1amlx174') }}:
1061
1083
  <b class="mono">{{ env.disk.usedMb }} / {{ env.disk.quotaMb }} MB</b>
1062
- <span class="dim"> · {{ env.amlRootSource }}</span>
1084
+ <span class="dim"> · {{ rootSourceLabel }}</span>
1063
1085
  </p>
1064
1086
  </div>
1065
1087
 
@@ -9,7 +9,7 @@ import { useRoute } from 'vue-router'
9
9
  import { useDcwStream } from '@/app/composables/workshop/useDcwStream'
10
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
 
@@ -29,7 +29,7 @@ const tpl = computed(() => {
29
29
  const key = node.value ? daqKeyFromRef(node.value.templateRef) : ''
30
30
  return daq.templates.find(t => t.key === key) ?? null
31
31
  })
32
- const stateLabel: Record<DaqNodeState, string> = { ok: t('daqDetail.k41k5c026'), warn: t('daqDetail.k49z8v027'), alarm: t('daqDetail.k3xmid028'), offline: t('daqDetail.k44c2n029') }
32
+ const stateLabel = computed<Record<DaqNodeState, string>>(() => ({ ok: t('daqDetail.k41k5c026'), warn: t('daqDetail.k49z8v027'), alarm: t('daqDetail.k3xmid028'), offline: t('daqDetail.k44c2n029') }))
33
33
  const effectiveState = (): DaqNodeState => {
34
34
  const n = node.value
35
35
  if (!n) return 'offline'
@@ -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 })
@@ -215,13 +219,13 @@ type ChartRow = DaqTsdbPoint
215
219
  const historyPoints = ref<ChartRow[]>([])
216
220
  const bucketMs = ref<number>(15000)
217
221
  const histLoading = ref(false)
218
- const BUCKETS = [
219
- { label: '1s 桶', ms: 1000 },
220
- { label: '5s 桶', ms: 5000 },
221
- { label: '15s 桶(默认)', ms: 15000 },
222
- { label: '30s 桶', ms: 30000 },
223
- { label: '1min 桶', ms: 60000 },
224
- ]
222
+ const BUCKETS = computed(() => [
223
+ { label: t('daqDetail.bucket1s'), ms: 1000 },
224
+ { label: t('daqDetail.bucket5s'), ms: 5000 },
225
+ { label: t('daqDetail.bucket15s'), ms: 15000 },
226
+ { label: t('daqDetail.bucket30s'), ms: 30000 },
227
+ { label: t('daqDetail.bucket60s'), ms: 60000 },
228
+ ])
225
229
  async function loadHistory(): Promise<void> {
226
230
  if (!nodeId.value) return
227
231
  histLoading.value = true
@@ -508,12 +512,12 @@ watch(effectiveRefreshMs, () => armHistTimer())
508
512
  class="input"
509
513
  >
510
514
  <option
511
- v-for="d in DAQ_DRIVERS"
515
+ v-for="d in driverCatalog"
512
516
  :key="d.kind"
513
517
  :value="d.kind"
514
518
  :disabled="d.status === 'planned'"
515
519
  >
516
- {{ d.label }}{{ d.status === 'planned' ? $t('daqDetail.kz8zr9v035') : '' }}
520
+ {{ d.label }}{{ d.plugin ? ' ⌁' : '' }}{{ d.status === 'planned' ? $t('daqDetail.kz8zr9v035') : '' }}
517
521
  </option>
518
522
  </select>
519
523
  </label>
@@ -541,7 +545,7 @@ watch(effectiveRefreshMs, () => armHistTimer())
541
545
  type="button"
542
546
  class="toggle slim"
543
547
  :class="{ on: form.calKind === 'linear' }"
544
- title="采集标定 decoder:物理值 = scale × PLC采集值 + offset"
548
+ :title="$t('daqDetail.calDecoderTip')"
545
549
  @click="form.calKind = form.calKind === 'linear' ? 'none' : 'linear'"
546
550
  >
547
551
  {{ form.calKind === 'linear' ? $t('daqDetail.k1eru4r1039') : $t('daqDetail.k3oktae047') }}
@@ -552,7 +556,7 @@ watch(effectiveRefreshMs, () => armHistTimer())
552
556
  step="0.1"
553
557
  class="input"
554
558
  :disabled="form.calKind !== 'linear'"
555
- title="decode 斜率(≠0)"
559
+ :title="$t('daqDetail.calScaleTip')"
556
560
  >
557
561
  <input
558
562
  v-model.number="form.calOffset"
@@ -560,7 +564,7 @@ watch(effectiveRefreshMs, () => armHistTimer())
560
564
  step="0.1"
561
565
  class="input"
562
566
  :disabled="form.calKind !== 'linear'"
563
- title="decode 截距"
567
+ :title="$t('daqDetail.calOffsetTip')"
564
568
  ><small>decoder</small>
565
569
  </label>
566
570
  <label class="field row">
@@ -655,7 +659,7 @@ watch(effectiveRefreshMs, () => armHistTimer())
655
659
  <!-- 驱动连接参数(mock 空;真实协议 schema 动态表单 + 测试连接) -->
656
660
  <template v-if="driverFields.length">
657
661
  <h3 class="sec mt">
658
- {{ $t('daqDetail.k1p9gioa033') }} {{ DAQ_DRIVERS.find(d => d.kind === form.driver)?.label }}
662
+ {{ $t('daqDetail.k1p9gioa033') }} {{ driverCatalog.find(d => d.kind === form.driver)?.label }}
659
663
  </h3>
660
664
  <div class="driver-grid">
661
665
  <label