agentworkshop 0.7.8 → 0.7.11

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 (627) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/-6OnbLFb.js +1 -0
  3. package/.output/public/_nuxt/{BUxYN2mw.js → -nb2uqVg.js} +1 -1
  4. package/.output/public/_nuxt/6vYobj4F.js +1 -0
  5. package/.output/public/_nuxt/{BSXx2vqR.js → B-xskWta.js} +1 -1
  6. package/.output/public/_nuxt/B3Psw_sL.js +1 -0
  7. package/.output/public/_nuxt/B53Mp7lD.js +1 -0
  8. package/.output/public/_nuxt/B5CYgFAD.js +14 -0
  9. package/.output/public/_nuxt/{uBbDCfTz.js → B5S_UyaC.js} +1 -1
  10. package/.output/public/_nuxt/{DZk24ego.js → B7wL3pDk.js} +1 -1
  11. package/.output/public/_nuxt/B8WV7GzS.js +1 -0
  12. package/.output/public/_nuxt/{BYL0Rjqj.js → BBwMH_hG.js} +3 -3
  13. package/.output/public/_nuxt/BLzCac9K2.js +1 -0
  14. package/.output/public/_nuxt/BNXfwXpE.js +1 -0
  15. package/.output/public/_nuxt/{VnIWJ0ts.js → BN_PdN3J.js} +1 -1
  16. package/.output/public/_nuxt/BZGNTgTQ2.js +1 -0
  17. package/.output/public/_nuxt/BbZAzXjZ2.js +1 -0
  18. package/.output/public/_nuxt/Bc3PiGGr.js +1 -0
  19. package/.output/public/_nuxt/Bckshc9V.js +1 -0
  20. package/.output/public/_nuxt/BcrN7QEl2.js +1 -0
  21. package/.output/public/_nuxt/BgOhoDTI.js +1 -0
  22. package/.output/public/_nuxt/Bmpvki7M.js +1 -0
  23. package/.output/public/_nuxt/{BkfchkK62.js → Bp5luxkg2.js} +1 -1
  24. package/.output/public/_nuxt/BxPPAkGA.js +3 -0
  25. package/.output/public/_nuxt/{C8dxXc6K.js → BxtpDtzC.js} +1 -1
  26. package/.output/public/_nuxt/{pRQri7vQ2.js → BytVi9VX2.js} +1 -1
  27. package/.output/public/_nuxt/{D5KJ7_0V.js → C3tCneTM.js} +1 -1
  28. package/.output/public/_nuxt/{C_gFA2H_2.js → C4OAdbVK2.js} +1 -1
  29. package/.output/public/_nuxt/C6m-kenn.js +1 -0
  30. package/.output/public/_nuxt/{zwdqvGN_.js → CGx-mtWf.js} +1 -1
  31. package/.output/public/_nuxt/{DCXIGxzT.js → CKfhtOt7.js} +2 -2
  32. package/.output/public/_nuxt/{ChEKFMxj.js → CUXCQXjG.js} +1 -1
  33. package/.output/public/_nuxt/CfVAr2nf.js +1 -0
  34. package/.output/public/_nuxt/Cj6139IM.js +1 -0
  35. package/.output/public/_nuxt/{DM8DS9MA.js → Cor9siSf.js} +1 -1
  36. package/.output/public/_nuxt/{BsMpJf7S.js → D-Ca4BGY.js} +6 -6
  37. package/.output/public/_nuxt/{CsCpu2Zh.js → D1z7i2UP.js} +1 -1
  38. package/.output/public/_nuxt/D7jiode2.js +1 -0
  39. package/.output/public/_nuxt/D8CqF0yy.js +1 -0
  40. package/.output/public/_nuxt/{DYZBdSSg2.js → DA4lxCWC2.js} +1 -1
  41. package/.output/public/_nuxt/DEaY_uvR.js +1 -0
  42. package/.output/public/_nuxt/{DCEyMaN-.js → DNxVTfhe.js} +3 -3
  43. package/.output/public/_nuxt/DT-Wg8r1.js +1 -0
  44. package/.output/public/_nuxt/DTYBfjRY.js +1 -0
  45. package/.output/public/_nuxt/{fQUs58kX2.js → DWcEk1ur2.js} +1 -1
  46. package/.output/public/_nuxt/DXRZPxGs.js +1 -0
  47. package/.output/public/_nuxt/Dhqra7NB.js +1 -0
  48. package/.output/public/_nuxt/DlRO_q5L.js +1 -0
  49. package/.output/public/_nuxt/{C2iWjzEC2.js → DoLasgPj2.js} +1 -1
  50. package/.output/public/_nuxt/{DRq09ZmT.js → DpojD719.js} +1 -1
  51. package/.output/public/_nuxt/Ds8JbqGB.js +1 -0
  52. package/.output/public/_nuxt/{BCipft_k2.js → DsUUYP292.js} +1 -1
  53. package/.output/public/_nuxt/DtBu71ev.js +32 -0
  54. package/.output/public/_nuxt/Dy-mxvXY2.js +1 -0
  55. package/.output/public/_nuxt/DyisHHzD.js +18 -0
  56. package/.output/public/_nuxt/G0qIw7Gq2.js +1 -0
  57. package/.output/public/_nuxt/ORt9oDIy2.js +1 -0
  58. package/.output/public/_nuxt/QoCzfpo2.js +1 -0
  59. package/.output/public/_nuxt/RzXYI9FM.js +23 -0
  60. package/.output/public/_nuxt/TownView.BHLKAjEu.css +1 -0
  61. package/.output/public/_nuxt/VLI2Zy4t.js +5 -0
  62. package/.output/public/_nuxt/_id_.DIxEKj88.css +1 -0
  63. package/.output/public/_nuxt/_id_.DTvjd6VN.css +1 -0
  64. package/.output/public/_nuxt/{_wsId_.COUzMXpP.css → _wsId_.BFyCuUwS.css} +1 -1
  65. package/.output/public/_nuxt/agents.CEbox5-D.css +1 -0
  66. package/.output/public/_nuxt/{ZugRk0CM2.js → arUY5dyq2.js} +2 -2
  67. package/.output/public/_nuxt/builds/latest.json +1 -1
  68. package/.output/public/_nuxt/builds/meta/88479a5b-ce6a-400f-9737-1cc9f54b1fe5.json +1 -0
  69. package/.output/public/_nuxt/channel-templates.De5ZvrGz.css +1 -0
  70. package/.output/public/_nuxt/d_Sz9KGm.js +1 -0
  71. package/.output/public/_nuxt/daq.6IrhVVfy.css +1 -0
  72. package/.output/public/_nuxt/dcw.DcDjwvqv.css +1 -0
  73. package/.output/public/_nuxt/default.BbgdTDCk.css +1 -0
  74. package/.output/public/_nuxt/{CblLEiCZ.js → eHYnGew0.js} +3 -3
  75. package/.output/public/_nuxt/eUGyJdiT.js +1 -0
  76. package/.output/public/_nuxt/{entry.5qf6EqfN.css → entry.B03HBJGC.css} +1 -1
  77. package/.output/public/_nuxt/{Cyk3du4K2.js → kZV5TQvh2.js} +1 -1
  78. package/.output/public/_nuxt/kkEthL84.js +2 -0
  79. package/.output/public/_nuxt/logs.BO-BSyjm.css +1 -0
  80. package/.output/public/_nuxt/{D4qXvjuV.js → niDwBOZW.js} +2 -2
  81. package/.output/public/_nuxt/permissions.CwZo6t1V.css +1 -0
  82. package/.output/public/_nuxt/plugins.Clsky_kl.css +1 -0
  83. package/.output/public/_nuxt/rqZ-1SoP.js +2 -0
  84. package/.output/public/_nuxt/settings.BqMF2nfj.css +1 -0
  85. package/.output/public/_nuxt/tJuVvBSl.js +1 -0
  86. package/.output/public/_nuxt/teams.CUMnbQGf.css +1 -0
  87. package/.output/public/_nuxt/tokens.BPLe9ioQ.css +1 -0
  88. package/.output/public/_nuxt/{Bi6AiCuP.js → vJ4FPb-_.js} +1 -1
  89. package/.output/public/_nuxt/workshop.BIdoGfoC.css +1 -0
  90. package/.output/public/_nuxt/{B7aqqzkY.js → zVkqCZ78.js} +1 -1
  91. package/.output/server/chunks/_/LeftOutlined.mjs +1 -1
  92. package/.output/server/chunks/_/SearchOutlined.mjs +1 -1
  93. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  94. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  95. package/.output/server/chunks/_/nitro.mjs +1614 -1279
  96. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  97. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  98. package/.output/server/chunks/build/Col-biaNnEPf.mjs +1 -1
  99. package/.output/server/chunks/build/{OmpTerminalPanel-COphA1br.mjs → OmpTerminalPanel-Ban3yJZ4.mjs} +4 -5
  100. package/.output/server/chunks/build/OmpTerminalPanel-Ban3yJZ4.mjs.map +1 -0
  101. package/.output/server/chunks/build/{TownView-B5KifIaT.mjs → TownView-CunmEMzS.mjs} +184 -184
  102. package/.output/server/chunks/build/{TownView-B5KifIaT.mjs.map → TownView-CunmEMzS.mjs.map} +1 -1
  103. package/.output/server/chunks/build/{_id_-Ct4Jhvl1.mjs → _id_-CVnMdSeG.mjs} +38 -37
  104. package/.output/server/chunks/build/_id_-CVnMdSeG.mjs.map +1 -0
  105. package/.output/server/chunks/build/{_id_-C-ewLgfl.mjs → _id_-D265Wh_k.mjs} +127 -126
  106. package/.output/server/chunks/build/_id_-D265Wh_k.mjs.map +1 -0
  107. package/.output/server/chunks/build/{_wsId_-CanI_6Su.mjs → _wsId_-eNJmBp05.mjs} +137 -136
  108. package/.output/server/chunks/build/{_wsId_-CanI_6Su.mjs.map → _wsId_-eNJmBp05.mjs.map} +1 -1
  109. package/.output/server/chunks/build/{agents-DSOptxXA.mjs → agents-B10wmFri.mjs} +24 -23
  110. package/.output/server/chunks/build/agents-B10wmFri.mjs.map +1 -0
  111. package/.output/server/chunks/build/alert-qJnjyRcP.mjs +1 -1
  112. package/.output/server/chunks/build/api-error-dul30BYQ.mjs +47 -0
  113. package/.output/server/chunks/build/api-error-dul30BYQ.mjs.map +1 -0
  114. package/.output/server/chunks/build/button-DEcZFcqN.mjs +2 -2
  115. package/.output/server/chunks/build/{card-Dipvaykh.mjs → card-CCPQoKlh.mjs} +4 -4
  116. package/.output/server/chunks/build/{card-Dipvaykh.mjs.map → card-CCPQoKlh.mjs.map} +1 -1
  117. package/.output/server/chunks/build/{channel-templates-BK0KuPOd.mjs → channel-templates-CpWxVk5A.mjs} +29 -28
  118. package/.output/server/chunks/build/channel-templates-CpWxVk5A.mjs.map +1 -0
  119. package/.output/server/chunks/build/{checkbox-dzcpU_Cd.mjs → checkbox-Dv1kjaUZ.mjs} +3 -3
  120. package/.output/server/chunks/build/{checkbox-dzcpU_Cd.mjs.map → checkbox-Dv1kjaUZ.mjs.map} +1 -1
  121. package/.output/server/chunks/build/client-only-D5BzSQc6.mjs +1 -1
  122. package/.output/server/chunks/build/{daq-D9RA_uze.mjs → daq-DxaXk_8N.mjs} +114 -114
  123. package/.output/server/chunks/build/daq-DxaXk_8N.mjs.map +1 -0
  124. package/.output/server/chunks/build/{dcw-BTM5YU-B.mjs → dcw-DqjHrl5Z.mjs} +48 -47
  125. package/.output/server/chunks/build/dcw-DqjHrl5Z.mjs.map +1 -0
  126. package/.output/server/chunks/build/{default-BfWGTlbj.mjs → default-YcUHc1Ev.mjs} +34 -26
  127. package/.output/server/chunks/build/{default-BfWGTlbj.mjs.map → default-YcUHc1Ev.mjs.map} +1 -1
  128. package/.output/server/chunks/build/drawer-Cmh90erI.mjs +1 -1
  129. package/.output/server/chunks/build/dropdown-vhn1NPFs.mjs +2 -2
  130. package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs +554 -0
  131. package/.output/server/chunks/build/hasIn-vQ9LWt-J.mjs.map +1 -0
  132. package/.output/server/chunks/build/initDefaultProps-DIbWwP4R.mjs +1 -1
  133. package/.output/server/chunks/build/{input-sf_BT6o6.mjs → input-DxDqeyQW.mjs} +5 -553
  134. package/.output/server/chunks/build/input-DxDqeyQW.mjs.map +1 -0
  135. package/.output/server/chunks/build/{input-number-Bd55elNN.mjs → input-number-CZ3ZrCsy.mjs} +3 -3
  136. package/.output/server/chunks/build/{input-number-Bd55elNN.mjs.map → input-number-CZ3ZrCsy.mjs.map} +1 -1
  137. package/.output/server/chunks/build/{logs-Dyk0I2I9.mjs → logs-Co854R4y.mjs} +40 -40
  138. package/.output/server/chunks/build/{logs-Dyk0I2I9.mjs.map → logs-Co854R4y.mjs.map} +1 -1
  139. package/.output/server/chunks/build/menu-WCrlpYVh.mjs +2 -2
  140. package/.output/server/chunks/build/modal-yvUquPj5.mjs +2 -2
  141. package/.output/server/chunks/build/{monitor-MIOvsyLa.mjs → monitor-miqq9xHB.mjs} +11 -11
  142. package/.output/server/chunks/build/{monitor-MIOvsyLa.mjs.map → monitor-miqq9xHB.mjs.map} +1 -1
  143. package/.output/server/chunks/build/{pages-DR2bzczM.mjs → pages-DPC1Vp6w.mjs} +6 -5
  144. package/.output/server/chunks/build/pages-DPC1Vp6w.mjs.map +1 -0
  145. package/.output/server/chunks/build/permissions-Eu9e6hfZ.mjs +534 -0
  146. package/.output/server/chunks/build/permissions-Eu9e6hfZ.mjs.map +1 -0
  147. package/.output/server/chunks/build/{plugins-DnOBIWGg.mjs → plugins-D84mvK9G.mjs} +27 -25
  148. package/.output/server/chunks/build/plugins-D84mvK9G.mjs.map +1 -0
  149. package/.output/server/chunks/build/popconfirm-CRaHcz5O.mjs +2 -2
  150. package/.output/server/chunks/build/responsiveObserve-CS0UB6wQ.mjs +1 -1
  151. package/.output/server/chunks/build/{segmented-DPe9ZzLO.mjs → segmented-ChmQZwz6.mjs} +5 -4
  152. package/.output/server/chunks/build/{segmented-DPe9ZzLO.mjs.map → segmented-ChmQZwz6.mjs.map} +1 -1
  153. package/.output/server/chunks/build/select-D-CeE5vY.mjs +1 -1
  154. package/.output/server/chunks/build/{settings-DA8IkGLo.mjs → settings-BPBll_7K.mjs} +28 -26
  155. package/.output/server/chunks/build/settings-BPBll_7K.mjs.map +1 -0
  156. package/.output/server/chunks/build/space-CCBYAkXt.mjs +2 -2
  157. package/.output/server/chunks/build/spin-HVY81X_L.mjs +1 -1
  158. package/.output/server/chunks/build/switch-CelRXpcy.mjs +2 -2
  159. package/.output/server/chunks/build/{table-Cswq-l2r.mjs → table-BtksyDlQ.mjs} +5 -5
  160. package/.output/server/chunks/build/{table-Cswq-l2r.mjs.map → table-BtksyDlQ.mjs.map} +1 -1
  161. package/.output/server/chunks/build/{tabs-BM3tAh_J.mjs → tabs-DQv-_-R6.mjs} +3 -3
  162. package/.output/server/chunks/build/{tabs-BM3tAh_J.mjs.map → tabs-DQv-_-R6.mjs.map} +1 -1
  163. package/.output/server/chunks/build/{tag-NO9jEqKy.mjs → tag-A0tZ2Ouq.mjs} +4 -4
  164. package/.output/server/chunks/build/{tag-NO9jEqKy.mjs.map → tag-A0tZ2Ouq.mjs.map} +1 -1
  165. package/.output/server/chunks/build/{teams-BhSKBBBM.mjs → teams-CNflUtPh.mjs} +25 -24
  166. package/.output/server/chunks/build/teams-CNflUtPh.mjs.map +1 -0
  167. package/.output/server/chunks/build/{tokens-D_eyxmcv.mjs → tokens-CZpnEDVf.mjs} +27 -26
  168. package/.output/server/chunks/build/tokens-CZpnEDVf.mjs.map +1 -0
  169. package/.output/server/chunks/build/town-BUqRobze.mjs +1 -1
  170. package/.output/server/chunks/build/{town-DPtOPRRO.mjs → town-BbaR-8io.mjs} +10 -10
  171. package/.output/server/chunks/build/{town-DPtOPRRO.mjs.map → town-BbaR-8io.mjs.map} +1 -1
  172. package/.output/server/chunks/build/{useDaqStream-hwkhJHFU.mjs → useDaqStream-BkmyQT06.mjs} +36 -24
  173. package/.output/server/chunks/build/useDaqStream-BkmyQT06.mjs.map +1 -0
  174. package/.output/server/chunks/build/{useDcwStream-Bdew_yrr.mjs → useDcwStream-DWVoU96J.mjs} +63 -48
  175. package/.output/server/chunks/build/useDcwStream-DWVoU96J.mjs.map +1 -0
  176. package/.output/server/chunks/build/{useDeviceTwins-C6EBg9oN.mjs → useDeviceTwins-34WGk9aN.mjs} +4 -3
  177. package/.output/server/chunks/build/useDeviceTwins-34WGk9aN.mjs.map +1 -0
  178. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs +1 -1
  179. package/.output/server/chunks/build/{useOpsLog-DdCqKVVG.mjs → useOpsLog-C9zTzYof.mjs} +30 -17
  180. package/.output/server/chunks/build/useOpsLog-C9zTzYof.mjs.map +1 -0
  181. package/.output/server/chunks/build/useSiteConfig-DJe_KMVr.mjs +1 -1
  182. package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs +1 -1
  183. package/.output/server/chunks/build/{useWorkshopWs-B3j5wIAK.mjs → useWorkshopWs-CprkZEdq.mjs} +2 -3
  184. package/.output/server/chunks/build/useWorkshopWs-CprkZEdq.mjs.map +1 -0
  185. package/.output/server/chunks/build/{users-CmVvb1oq.mjs → users-D6RNylrW.mjs} +10 -10
  186. package/.output/server/chunks/build/{users-CmVvb1oq.mjs.map → users-D6RNylrW.mjs.map} +1 -1
  187. package/.output/server/chunks/build/{workshop-D5CQj2A8.mjs → workshop-Crsai2Y9.mjs} +27 -26
  188. package/.output/server/chunks/build/workshop-Crsai2Y9.mjs.map +1 -0
  189. package/.output/server/chunks/build/{workspaces-IfORCDJE.mjs → workspaces-BuydxM-3.mjs} +2 -3
  190. package/.output/server/chunks/build/workspaces-BuydxM-3.mjs.map +1 -0
  191. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  192. package/.output/server/chunks/routes/api/index.get.mjs +1 -1
  193. package/.output/server/chunks/routes/api/index.post.mjs +1 -1
  194. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  195. package/.output/server/chunks/routes/api/metrics.mjs +1 -1
  196. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
  197. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +1 -1
  198. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +1 -1
  199. package/.output/server/chunks/routes/api/system/config.get.mjs +1 -1
  200. package/.output/server/chunks/routes/api/system/index.get.mjs +1 -1
  201. package/.output/server/chunks/routes/api/system/index.patch.mjs +1 -1
  202. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
  203. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
  204. package/.output/server/chunks/routes/api/system/monitor.get.mjs +1 -1
  205. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +1 -1
  207. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +1 -1
  208. package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
  209. package/.output/server/chunks/routes/api/users/_id_.put.mjs +1 -1
  210. package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
  211. package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
  212. package/.output/server/chunks/routes/api/users/login.post.mjs +1 -1
  213. package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
  214. package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
  215. package/.output/server/chunks/routes/api/users/register.post.mjs +1 -1
  216. package/.output/server/chunks/routes/api/users/setup-status.get.mjs +1 -1
  217. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
  218. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
  219. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/_...path_.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
  226. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
  228. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +19 -8
  229. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs.map +1 -1
  230. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  231. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +2 -2
  232. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +2 -2
  233. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +1 -1
  234. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +1 -1
  235. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
  236. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +1 -1
  237. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
  238. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +1 -1
  239. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +1 -1
  240. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +1 -1
  241. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +2 -2
  242. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +1 -1
  243. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +2 -2
  244. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
  245. package/.output/server/chunks/routes/api/workshop/caller.mjs +1 -1
  246. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +3 -3
  247. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +1 -1
  248. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +1 -1
  249. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
  250. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
  251. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +2 -2
  252. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +1 -1
  253. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
  254. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +1 -1
  255. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
  256. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +1 -1
  257. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +1 -1
  258. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +1 -1
  259. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +1 -1
  260. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +1 -1
  261. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +1 -1
  262. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
  263. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +1 -1
  264. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +2 -2
  265. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +1 -1
  266. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +1 -1
  267. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +1 -1
  268. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  269. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +1 -1
  270. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  271. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +1 -1
  272. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +1 -1
  273. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +2 -2
  274. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +1 -1
  275. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +2 -2
  276. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +1 -1
  277. package/.output/server/chunks/routes/api/workshop/channels.get.mjs +1 -1
  278. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  279. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +7 -6
  280. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs.map +1 -1
  281. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +5 -4
  282. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs.map +1 -1
  283. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +5 -4
  284. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs.map +1 -1
  285. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +5 -4
  286. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs.map +1 -1
  287. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +2 -2
  288. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +2 -2
  289. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +5 -4
  290. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs.map +1 -1
  291. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +5 -2
  292. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs.map +1 -1
  293. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +2 -2
  294. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +3 -2
  295. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs.map +1 -1
  296. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +2 -2
  297. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +2 -2
  298. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +2 -2
  299. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +2 -2
  300. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +2 -2
  301. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +2 -2
  302. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +7 -6
  303. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs.map +1 -1
  304. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +2 -2
  305. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +2 -2
  306. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +5 -4
  307. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs.map +1 -1
  308. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +4 -3
  309. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs.map +1 -1
  310. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -2
  311. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +2 -2
  312. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +2 -2
  313. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +2 -2
  314. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +4 -4
  315. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs.map +1 -1
  316. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +8 -4
  317. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs.map +1 -1
  318. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +4 -4
  319. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs.map +1 -1
  320. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +2 -2
  321. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +2 -2
  322. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +2 -2
  323. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +2 -2
  324. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +4 -4
  325. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs.map +1 -1
  326. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +2 -2
  327. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +7 -3
  328. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs.map +1 -1
  329. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +3 -2
  330. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs.map +1 -1
  331. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +3 -2
  332. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs.map +1 -1
  333. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +2 -2
  334. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +2 -2
  335. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +2 -2
  336. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +2 -2
  337. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +2 -2
  338. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +2 -2
  339. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +2 -2
  340. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +2 -2
  341. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +2 -2
  342. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +2 -2
  343. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +2 -2
  344. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +2 -2
  345. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs +2 -2
  346. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +2 -2
  347. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +5 -3
  348. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs.map +1 -1
  349. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +2 -2
  350. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +2 -2
  351. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +2 -2
  352. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +2 -2
  353. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  354. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  355. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +2 -2
  356. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +2 -2
  357. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
  358. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +2 -2
  359. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +2 -2
  360. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +2 -2
  361. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +2 -2
  362. package/.output/server/chunks/routes/api/workshop/index.get.mjs +1 -1
  363. package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
  364. package/.output/server/chunks/routes/api/workshop/index.put.mjs +41 -0
  365. package/.output/server/chunks/routes/api/workshop/index.put.mjs.map +1 -0
  366. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +4 -3
  367. package/.output/server/chunks/routes/api/workshop/index10.get.mjs.map +1 -1
  368. package/.output/server/chunks/routes/api/workshop/index11.get.mjs +27 -0
  369. package/.output/server/chunks/routes/api/workshop/index11.get.mjs.map +1 -0
  370. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  371. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +1 -1
  372. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
  373. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +4 -4
  374. package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
  375. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +5 -4
  376. package/.output/server/chunks/routes/api/workshop/index4.get.mjs.map +1 -1
  377. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +2 -2
  378. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +18 -11
  379. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  380. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +2 -2
  381. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  382. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +2 -2
  383. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  384. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
  385. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +24 -12
  386. package/.output/server/chunks/routes/api/workshop/index8.get.mjs.map +1 -1
  387. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
  388. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +12 -7
  389. package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
  390. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +1 -1
  391. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +1 -1
  392. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +1 -1
  393. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +4 -4
  394. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs.map +1 -1
  395. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +4 -4
  396. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs.map +1 -1
  397. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +1 -1
  398. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +1 -1
  399. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +2 -2
  400. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +2 -2
  401. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +1 -1
  402. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
  403. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
  404. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +1 -1
  405. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
  406. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +1 -1
  407. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
  408. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +1 -1
  409. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +2 -2
  410. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +1 -1
  411. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +1 -1
  412. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +1 -1
  413. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +1 -1
  414. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +1 -1
  415. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +1 -1
  416. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +1 -1
  417. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +1 -1
  418. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +3 -3
  419. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +1 -1
  420. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +1 -1
  421. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +1 -1
  422. package/.output/server/chunks/routes/renderer.mjs +3 -3
  423. package/.output/server/chunks/virtual/entry.mjs +303 -37
  424. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  425. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  426. package/.output/server/index.mjs +1 -1
  427. package/.output/server/package.json +1 -1
  428. package/README-zh.md +15 -0
  429. package/README.md +20 -0
  430. package/app/components/AppHeader.vue +1 -1
  431. package/app/components/AppSidebar.vue +7 -1
  432. package/app/components/workshop/A2aRpcDebugger.vue +1 -1
  433. package/app/components/workshop/AgentInspectorDrawer.vue +3 -3
  434. package/app/components/workshop/AgentLanesView.vue +6 -6
  435. package/app/components/workshop/AssetLibrary.vue +2 -2
  436. package/app/components/workshop/ChannelSessionList.vue +5 -5
  437. package/app/components/workshop/Composer.vue +1 -1
  438. package/app/components/workshop/DeviceTwinPanel.vue +2 -2
  439. package/app/components/workshop/TaskBoardView.vue +1 -1
  440. package/app/components/workshop/TaskInspectorDrawer.vue +2 -2
  441. package/app/components/workshop/town/TownView.vue +23 -23
  442. package/app/composables/workshop/apiClient.ts +103 -95
  443. package/app/composables/workshop/useCharacterAssets.ts +1 -1
  444. package/app/composables/workshop/useDaqStream.ts +36 -22
  445. package/app/composables/workshop/useDcwStream.ts +23 -6
  446. package/app/composables/workshop/useDeviceTwins.ts +1 -1
  447. package/app/composables/workshop/useOpsLog.ts +28 -15
  448. package/app/composables/workshop/useSceneLayouts.ts +1 -1
  449. package/app/composables/workshop/useWorkshopWs.ts +11 -2
  450. package/app/pages/daq/[id].vue +1 -1
  451. package/app/pages/daq/index.vue +8 -8
  452. package/app/pages/dcw/[id].vue +13 -13
  453. package/app/pages/dcw/index.vue +7 -7
  454. package/app/pages/logs/index.vue +1 -1
  455. package/app/pages/permissions/index.vue +327 -0
  456. package/app/pages/plugins/index.vue +14 -6
  457. package/app/pages/settings.vue +4 -2
  458. package/app/pages/tokens.vue +3 -3
  459. package/app/pages/workshop/agents.vue +2 -2
  460. package/app/pages/workshop/channel-templates.vue +3 -3
  461. package/app/pages/workshop/index.vue +4 -4
  462. package/app/pages/workshop/teams.vue +3 -3
  463. package/app/plugins/http.ts +18 -2
  464. package/app/plugins/session-restore.client.ts +7 -2
  465. package/app/stores/workshop/user.ts +14 -1
  466. package/app/utils/api-error.ts +75 -0
  467. package/cli/commands/plugin.mjs +2 -2
  468. package/config.yml +1 -1
  469. package/i18n/locales/en.ts +53 -3
  470. package/i18n/locales/zh-CN.ts +53 -3
  471. package/package.json +1 -1
  472. package/scripts/_dbg-acc-1-setup.mjs +57 -0
  473. package/scripts/_dbg-acc-2-diag.mjs +14 -0
  474. package/scripts/_dbg-acc-2-intervals.mjs +81 -0
  475. package/scripts/_dbg-acc-3-daq.mjs +48 -0
  476. package/scripts/_dbg-acc-4-team.mjs +92 -0
  477. package/scripts/_dbg-acc-5-visual.mjs +63 -0
  478. package/scripts/_dbg-acc-5b-ws-town.mjs +18 -0
  479. package/scripts/_dbg-acc-5c-town.mjs +12 -0
  480. package/scripts/_dbg-acc-6-i18n.mjs +19 -0
  481. package/scripts/_dbg-audit-neg-e2e.mjs +64 -0
  482. package/scripts/_dbg-final-features.mjs +155 -0
  483. package/scripts/_dbg-final-fixups.mjs +62 -0
  484. package/scripts/_dbg-final-visual.mjs +29 -0
  485. package/scripts/_dbg-interval-config.mjs +17 -6
  486. package/scripts/_dbg-perms-e2e.mjs +102 -0
  487. package/scripts/_dbg-perms-visual.mjs +36 -0
  488. package/scripts/_dbg-plugins-e2e.mjs +101 -0
  489. package/scripts/_dbg-protocol-matrix.mjs +16 -0
  490. package/scripts/_dbg-repo-setup-verify.mjs +31 -0
  491. package/scripts/_dbg-setup-e2e.mjs +1 -1
  492. package/sdk/api.mjs +117 -101
  493. package/sdk/context.mjs +240 -219
  494. package/sdk/hooks.mjs +105 -103
  495. package/sdk/index.d.mts +142 -135
  496. package/sdk/lifecycle.mjs +26 -25
  497. package/server/api/workshop/agent-tools/bindings/index.post.ts +40 -20
  498. package/server/api/workshop/daq/[id]/bind.post.ts +5 -2
  499. package/server/api/workshop/daq/[id]/frames/content.get.ts +4 -1
  500. package/server/api/workshop/daq/[id]/frames.get.ts +4 -1
  501. package/server/api/workshop/daq/[id]/samples.get.ts +4 -1
  502. package/server/api/workshop/daq/[id].patch.ts +3 -0
  503. package/server/api/workshop/daq/alarms/[id]/ack.post.ts +20 -15
  504. package/server/api/workshop/daq/controller.post.ts +2 -0
  505. package/server/api/workshop/daq/index.get.ts +5 -3
  506. package/server/api/workshop/daq/index.post.ts +2 -2
  507. package/server/api/workshop/dcw/[id]/bind.post.ts +20 -17
  508. package/server/api/workshop/dcw/[id]/test.post.ts +18 -15
  509. package/server/api/workshop/dcw/[id]/write.post.ts +3 -0
  510. package/server/api/workshop/dcw/index.get.ts +22 -9
  511. package/server/api/workshop/dcw/line/query.get.ts +38 -31
  512. package/server/api/workshop/dcw/lines/[id]/start.post.ts +3 -0
  513. package/server/api/workshop/dcw/lines/[id]/stop.post.ts +3 -0
  514. package/server/api/workshop/dcw/lines/index.get.ts +8 -2
  515. package/server/api/workshop/dcw/lines/index.post.ts +2 -2
  516. package/server/api/workshop/dcw/products/index.post.ts +16 -16
  517. package/server/api/workshop/dcw/runs/[id]/data.get.ts +20 -15
  518. package/server/api/workshop/dcw/runs/index.get.ts +13 -11
  519. package/server/api/workshop/permissions/index.get.ts +30 -0
  520. package/server/api/workshop/permissions/index.put.ts +29 -0
  521. package/server/api/workshop/plugins/[name]/disable.post.ts +5 -3
  522. package/server/api/workshop/plugins/[name]/enable.post.ts +5 -3
  523. package/server/api/workshop/ws.ts +18 -6
  524. package/server/data/daqs.json +90 -46
  525. package/server/data/dcw-lines.json +21 -0
  526. package/server/data/dcw-products.json +140 -0
  527. package/server/data/dcw-recipes.json +506 -0
  528. package/server/data/dcw-rollback.json +281 -6
  529. package/server/data/dcw-runs.json +1374 -1257
  530. package/server/data/dcw-writes.json +312 -0
  531. package/server/data/dcws.json +1165 -477
  532. package/server/data/line-runs.json +26 -6
  533. package/server/plugins/backup.ts +119 -116
  534. package/server/repositories/user.repository.ts +86 -6
  535. package/server/services/system-config.ts +5 -0
  536. package/server/services/user.service.ts +5 -3
  537. package/server/services/workshop/daq/bus/index.ts +5 -3
  538. package/server/services/workshop/daq/bus/inproc.adapter.ts +12 -3
  539. package/server/services/workshop/daq/bus/mqtt.adapter.ts +13 -0
  540. package/server/services/workshop/daq/bus/queue-port.ts +2 -0
  541. package/server/services/workshop/daq/daq-controller.ts +18 -1
  542. package/server/services/workshop/daq/storage/sqlite.adapter.ts +10 -5
  543. package/server/services/workshop/db/ops.repo.ts +6 -0
  544. package/server/services/workshop/dcw/dcw-controller.ts +10 -2
  545. package/server/services/workshop/permissions.ts +79 -0
  546. package/server/services/workshop/plugins/host.mjs +40 -2
  547. package/server/services/workshop/scene-events.ts +25 -1
  548. package/server/services/workshop/settings.ts +10 -0
  549. package/shared/config/single-instance.mjs +24 -0
  550. package/shared/daq-protocol.ts +2 -0
  551. package/.output/public/_nuxt/2LwEn9gX.js +0 -2
  552. package/.output/public/_nuxt/3612gD2V.js +0 -32
  553. package/.output/public/_nuxt/8eIQAVlb.js +0 -1
  554. package/.output/public/_nuxt/Ah9qOv1m.js +0 -1
  555. package/.output/public/_nuxt/B4Fia4FB.js +0 -3
  556. package/.output/public/_nuxt/BH0Z05CS.js +0 -1
  557. package/.output/public/_nuxt/BJ-fxrSw.js +0 -1
  558. package/.output/public/_nuxt/BJvGPTpC.js +0 -1
  559. package/.output/public/_nuxt/BVZjSVs2.js +0 -1
  560. package/.output/public/_nuxt/BVzDoF8t.js +0 -1
  561. package/.output/public/_nuxt/BjVLsC3M.js +0 -1
  562. package/.output/public/_nuxt/BnVoQ74r.js +0 -1
  563. package/.output/public/_nuxt/Bnp4vIAf.js +0 -1
  564. package/.output/public/_nuxt/Bt_HDizI.js +0 -5
  565. package/.output/public/_nuxt/Bu-P92Pe.js +0 -18
  566. package/.output/public/_nuxt/ButLXkjo.js +0 -2
  567. package/.output/public/_nuxt/By-LNp3k.js +0 -1
  568. package/.output/public/_nuxt/CGdPdJPP.js +0 -1
  569. package/.output/public/_nuxt/CRGlf1Gb.js +0 -1
  570. package/.output/public/_nuxt/CS8R0_J3.js +0 -1
  571. package/.output/public/_nuxt/CUxV8Bw_.js +0 -1
  572. package/.output/public/_nuxt/Cd15nPnG2.js +0 -1
  573. package/.output/public/_nuxt/CvbHIGQY2.js +0 -1
  574. package/.output/public/_nuxt/DNJSkm3Q.js +0 -1
  575. package/.output/public/_nuxt/DNzaswei.js +0 -1
  576. package/.output/public/_nuxt/DXK1U43I.js +0 -1
  577. package/.output/public/_nuxt/Dc46i75T.js +0 -14
  578. package/.output/public/_nuxt/Dk6pq9JB2.js +0 -1
  579. package/.output/public/_nuxt/Do88WZG2.js +0 -23
  580. package/.output/public/_nuxt/Du-eSpo2.js +0 -1
  581. package/.output/public/_nuxt/GP2wXyuY.js +0 -1
  582. package/.output/public/_nuxt/NIM0Wglj2.js +0 -1
  583. package/.output/public/_nuxt/PQLnLxYe.js +0 -1
  584. package/.output/public/_nuxt/R_Wv_Nd9.js +0 -1
  585. package/.output/public/_nuxt/TownView.Bt33bo1M.css +0 -1
  586. package/.output/public/_nuxt/_id_.BzKMZnLe.css +0 -1
  587. package/.output/public/_nuxt/_id_.CbpDAWRh.css +0 -1
  588. package/.output/public/_nuxt/agents.BlejnOOC.css +0 -1
  589. package/.output/public/_nuxt/builds/meta/e5bb1803-86d9-43b3-85be-dc787dc9a978.json +0 -1
  590. package/.output/public/_nuxt/channel-templates.lkqEYlWY.css +0 -1
  591. package/.output/public/_nuxt/daq.zZ8GR433.css +0 -1
  592. package/.output/public/_nuxt/dcw.C46dGiF_.css +0 -1
  593. package/.output/public/_nuxt/default.V3_hUJq1.css +0 -1
  594. package/.output/public/_nuxt/eHGLpQSg2.js +0 -1
  595. package/.output/public/_nuxt/logs.DaIsHWZE.css +0 -1
  596. package/.output/public/_nuxt/p7wSGMtc.js +0 -1
  597. package/.output/public/_nuxt/plugins.FTm0PcEe.css +0 -1
  598. package/.output/public/_nuxt/settings.DeRNNUcP.css +0 -1
  599. package/.output/public/_nuxt/tRBT-plo.js +0 -1
  600. package/.output/public/_nuxt/teams.B8JNbUZg.css +0 -1
  601. package/.output/public/_nuxt/tokens.CWOTXM-Z.css +0 -1
  602. package/.output/public/_nuxt/ubPfs9mQ.js +0 -1
  603. package/.output/public/_nuxt/workshop.3kAcLB_M.css +0 -1
  604. package/.output/server/chunks/build/OmpTerminalPanel-COphA1br.mjs.map +0 -1
  605. package/.output/server/chunks/build/_id_-C-ewLgfl.mjs.map +0 -1
  606. package/.output/server/chunks/build/_id_-Ct4Jhvl1.mjs.map +0 -1
  607. package/.output/server/chunks/build/agents-DSOptxXA.mjs.map +0 -1
  608. package/.output/server/chunks/build/channel-templates-BK0KuPOd.mjs.map +0 -1
  609. package/.output/server/chunks/build/daq-D9RA_uze.mjs.map +0 -1
  610. package/.output/server/chunks/build/dcw-BTM5YU-B.mjs.map +0 -1
  611. package/.output/server/chunks/build/input-sf_BT6o6.mjs.map +0 -1
  612. package/.output/server/chunks/build/pages-DR2bzczM.mjs.map +0 -1
  613. package/.output/server/chunks/build/plugins-DnOBIWGg.mjs.map +0 -1
  614. package/.output/server/chunks/build/settings-DA8IkGLo.mjs.map +0 -1
  615. package/.output/server/chunks/build/teams-BhSKBBBM.mjs.map +0 -1
  616. package/.output/server/chunks/build/tokens-D_eyxmcv.mjs.map +0 -1
  617. package/.output/server/chunks/build/useDaqStream-hwkhJHFU.mjs.map +0 -1
  618. package/.output/server/chunks/build/useDcwStream-Bdew_yrr.mjs.map +0 -1
  619. package/.output/server/chunks/build/useDeviceTwins-C6EBg9oN.mjs.map +0 -1
  620. package/.output/server/chunks/build/useOpsLog-DdCqKVVG.mjs.map +0 -1
  621. package/.output/server/chunks/build/useWorkshopWs-B3j5wIAK.mjs.map +0 -1
  622. package/.output/server/chunks/build/user-Dk-ytEUV.mjs +0 -140
  623. package/.output/server/chunks/build/user-Dk-ytEUV.mjs.map +0 -1
  624. package/.output/server/chunks/build/workshop-D5CQj2A8.mjs.map +0 -1
  625. package/.output/server/chunks/build/workspaces-IfORCDJE.mjs.map +0 -1
  626. /package/.output/public/_nuxt/{CNs_Ozdc2.js → CNs_Ozdc.js} +0 -0
  627. /package/.output/public/_nuxt/{Cno6kYiO2.js → Cno6kYiO.js} +0 -0
@@ -1,95 +1,103 @@
1
- /**
2
- * 统一 API 客户端 —— 全部手写 fetch 的单一收口。
3
- * - 信封解析:{code, message, data};code !== 0 或非 2xx 一律抛 ApiError
4
- * - ApiError 保留业务码与 HTTP 状态(调用方可分支),message 为后端可读文案
5
- * - 网络层失败(TypeError/断网)→ ApiError('NETWORK'),不再裸奔 "Failed to fetch"
6
- * - 幂等 GET 可选自动重试(5xx/网络错误;400ms 起退避);写操作永不重试
7
- */
8
-
9
- export class ApiError extends Error {
10
- readonly code: string | number
11
- readonly status: number
12
-
13
- constructor(code: string | number, status: number, message: string) {
14
- super(message)
15
- this.name = 'ApiError'
16
- this.code = code
17
- this.status = status
18
- }
19
- }
20
-
21
- /** 鉴权头(cookie token → Bearer;与既有会话契约同源) */
22
- function authHeaders(json = true): Record<string, string> {
23
- const cookieToken = typeof document !== 'undefined'
24
- ? (document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] ?? '')
25
- : ''
26
- const h: Record<string, string> = {}
27
- if (cookieToken) h.authorization = `Bearer ${decodeURIComponent(cookieToken)}`
28
- if (json) h['content-type'] = 'application/json'
29
- return h
30
- }
31
-
32
- const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
33
-
34
- function isIdempotent(init?: RequestInit): boolean {
35
- const method = (init?.method ?? 'GET').toUpperCase()
36
- return method === 'GET' || method === 'HEAD'
37
- }
38
-
39
- /** 单次请求:信封解析 + 错误归一化(所有失败路径都抛 ApiError) */
40
- async function attemptOnce<T>(base: string, path: string, init?: RequestInit): Promise<T> {
41
- let res: Response
42
- try {
43
- res = await fetch(base + path, { ...init, headers: { ...authHeaders(!!init?.body), ...init?.headers } })
44
- }
45
- catch {
46
- throw new ApiError('NETWORK', 0, '无法连接服务器,请检查网络或服务状态')
47
- }
48
- let json: { code?: string | number, message?: string, data?: T } | null = null
49
- try {
50
- json = await res.json()
51
- }
52
- catch {
53
- // 非 JSON 响应(代理/网关 HTML 错误页等)——按状态码归一化
54
- }
55
- if (!res.ok) {
56
- throw new ApiError(
57
- json?.code ?? `HTTP_${res.status}`,
58
- res.status,
59
- json?.message || `请求失败(HTTP ${res.status})`,
60
- )
61
- }
62
- if (json?.code !== 0) {
63
- throw new ApiError(json?.code ?? 'REQUEST_ERROR', res.status, json?.message || '请求失败')
64
- }
65
- return json.data as T
66
- }
67
-
68
- /**
69
- * 统一请求入口。
70
- * @param opts.base API 前缀(如 '/api/workshop/daq')
71
- * @param opts.path 路径后缀(如 '/:id/bind')
72
- * @param opts.init fetch RequestInit(body 由调用方 JSON.stringify)
73
- * @param opts.retries 幂等请求额外重试次数(仅 5xx/网络错误;默认 0)
74
- */
75
- export async function apiFetch<T>(opts: { base: string, path?: string, init?: RequestInit, retries?: number }): Promise<T> {
76
- const { base, path = '', init, retries = 0 } = opts
77
- const idempotent = isIdempotent(init)
78
- const attempts = idempotent ? retries + 1 : 1
79
- let lastError: ApiError | undefined
80
- for (let attempt = 0; attempt < attempts; attempt++) {
81
- try {
82
- return await attemptOnce<T>(base, path, init)
83
- }
84
- catch (err) {
85
- const apiErr = err instanceof ApiError
86
- ? err
87
- : new ApiError('INTERNAL_ERROR', 0, err instanceof Error ? err.message : String(err))
88
- const retryable = idempotent && (apiErr.code === 'NETWORK' || apiErr.status >= 500)
89
- lastError = apiErr
90
- if (!retryable || attempt === attempts - 1) throw apiErr
91
- await sleep(400 * (attempt + 1))
92
- }
93
- }
94
- throw lastError ?? new ApiError('INTERNAL_ERROR', 0, '请求失败')
95
- }
1
+ /**
2
+ * 统一 API 客户端 —— 全部手写 fetch 的单一收口。
3
+ * - 信封解析:{code, message, data};code !== 0 或非 2xx 一律抛 ApiError
4
+ * - ApiError 保留业务码与 HTTP 状态(调用方可分支),message 为后端可读文案
5
+ * - 网络层失败(TypeError/断网)→ ApiError('NETWORK'),不再裸奔 "Failed to fetch"
6
+ * - 幂等 GET 可选自动重试(5xx/网络错误;400ms 起退避);写操作永不重试
7
+ */
8
+
9
+ export class ApiError extends Error {
10
+ readonly code: string | number
11
+ readonly status: number
12
+
13
+ constructor(code: string | number, status: number, message: string) {
14
+ super(message)
15
+ this.name = 'ApiError'
16
+ this.code = code
17
+ this.status = status
18
+ }
19
+ }
20
+
21
+ /** 鉴权头(cookie token → Bearer;与既有会话契约同源) */
22
+ function authHeaders(json = true): Record<string, string> {
23
+ const cookieToken = typeof document !== 'undefined'
24
+ ? (document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] ?? '')
25
+ : ''
26
+ const h: Record<string, string> = {}
27
+ if (cookieToken) h.authorization = `Bearer ${decodeURIComponent(cookieToken)}`
28
+ if (json) h['content-type'] = 'application/json'
29
+ return h
30
+ }
31
+
32
+ const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
33
+
34
+ function isIdempotent(init?: RequestInit): boolean {
35
+ const method = (init?.method ?? 'GET').toUpperCase()
36
+ return method === 'GET' || method === 'HEAD'
37
+ }
38
+
39
+ /** 单次请求:信封解析 + 错误归一化(所有失败路径都抛 ApiError) */
40
+ async function attemptOnce<T>(base: string, path: string, init?: RequestInit): Promise<T> {
41
+ let res: Response
42
+ try {
43
+ // 超时防挂起:无 AbortSignal 的 fetch 在连接黑洞时 promise 永不 settle,loading 永卡
44
+ res = await fetch(base + path, {
45
+ ...init,
46
+ headers: { ...authHeaders(!!init?.body), ...init?.headers },
47
+ signal: init?.signal ?? AbortSignal.timeout(init?.method && init.method.toUpperCase() !== 'GET' ? 30_000 : 15_000),
48
+ })
49
+ }
50
+ catch (err) {
51
+ if (err instanceof Error && (err.name === 'TimeoutError' || err.name === 'AbortError')) {
52
+ throw new ApiError('TIMEOUT', 0, '请求超时,请检查网络或服务状态')
53
+ }
54
+ throw new ApiError('NETWORK', 0, '无法连接服务器,请检查网络或服务状态')
55
+ }
56
+ let json: { code?: string | number, message?: string, data?: T } | null = null
57
+ try {
58
+ json = await res.json()
59
+ }
60
+ catch {
61
+ // 非 JSON 响应(代理/网关 HTML 错误页等)——按状态码归一化
62
+ }
63
+ if (!res.ok) {
64
+ throw new ApiError(
65
+ json?.code ?? `HTTP_${res.status}`,
66
+ res.status,
67
+ json?.message || `请求失败(HTTP ${res.status})`,
68
+ )
69
+ }
70
+ if (json?.code !== 0) {
71
+ throw new ApiError(json?.code ?? 'REQUEST_ERROR', res.status, json?.message || '请求失败')
72
+ }
73
+ return json.data as T
74
+ }
75
+
76
+ /**
77
+ * 统一请求入口。
78
+ * @param opts.base API 前缀(如 '/api/workshop/daq')
79
+ * @param opts.path 路径后缀(如 '/:id/bind')
80
+ * @param opts.init fetch RequestInit(body 由调用方 JSON.stringify)
81
+ * @param opts.retries 幂等请求额外重试次数(仅 5xx/网络错误;默认 0)
82
+ */
83
+ export async function apiFetch<T>(opts: { base: string, path?: string, init?: RequestInit, retries?: number }): Promise<T> {
84
+ const { base, path = '', init, retries = 0 } = opts
85
+ const idempotent = isIdempotent(init)
86
+ const attempts = idempotent ? retries + 1 : 1
87
+ let lastError: ApiError | undefined
88
+ for (let attempt = 0; attempt < attempts; attempt++) {
89
+ try {
90
+ return await attemptOnce<T>(base, path, init)
91
+ }
92
+ catch (err) {
93
+ const apiErr = err instanceof ApiError
94
+ ? err
95
+ : new ApiError('INTERNAL_ERROR', 0, apiErrorMessage(err))
96
+ const retryable = idempotent && (apiErr.code === 'NETWORK' || apiErr.status >= 500)
97
+ lastError = apiErr
98
+ if (!retryable || attempt === attempts - 1) throw apiErr
99
+ await sleep(400 * (attempt + 1))
100
+ }
101
+ }
102
+ throw lastError ?? new ApiError('INTERNAL_ERROR', 0, '请求失败')
103
+ }
@@ -202,7 +202,7 @@ function createStore(): CharacterAssetStore {
202
202
  }
203
203
  catch (err) {
204
204
  store.loaded = false
205
- store.error = err instanceof Error ? err.message : String(err)
205
+ store.error = apiErrorMessage(err)
206
206
  }
207
207
  finally {
208
208
  store.loading = false
@@ -204,30 +204,44 @@ const createStore = () => {
204
204
  }
205
205
  }
206
206
 
207
- /** 挂 WS 帧(townBus);幂等(globalThis 防重复订阅)。返回退订函数。 */
207
+ /** 挂 WS 帧(townBus)。引用计数:首个调用建立真实订阅,计数归零才退订
208
+ * (修复一次性守卫导致首个页面卸载后实时流永久死亡的缺陷)。返回退订函数。 */
209
+ let feedConsumers = 0
210
+ let feedUnsub: (() => void) | null = null
208
211
  function ensureWsFeed(): () => void {
209
- const g = globalThis as typeof globalThis & { __daqBusFed?: boolean }
210
- if (g.__daqBusFed) return () => {}
211
- g.__daqBusFed = true
212
- return useTownBus().subscribe((e: AepEnvelope) => {
213
- if (e.type === 'daq.reading') applyReading(e.payload as AepDaqReading)
214
- else if (e.type === 'daq.frame') applyFrame(e.payload as unknown as AepDaqFrame)
215
- else if (e.type === 'daq.node.changed') applyChange(e.payload as AepDaqNodeChange)
216
- else if (e.type === 'daq.controller') Object.assign(controller, e.payload as AepDaqControllerState)
217
- else if (e.type === 'daq.template.changed') applyTemplateChange(e.payload as AepDaqTemplateChange)
218
- // S5 实时告警:server 权威事件直推(报警进入轨插入;ack 确认后移出未确认列表)
219
- else if (e.type === 'daq.alarm') {
220
- const p = e.payload as unknown as DaqAlarmRow
221
- if (!alarms.some(a => a.id === p.id)) alarms.unshift(p)
212
+ feedConsumers++
213
+ if (feedConsumers === 1) {
214
+ feedUnsub = useTownBus().subscribe(handler)
215
+ }
216
+ let done = false
217
+ return () => {
218
+ if (done) return
219
+ done = true
220
+ if (--feedConsumers === 0) {
221
+ feedUnsub?.()
222
+ feedUnsub = null
222
223
  }
223
- else if (e.type === 'daq.alarm.changed') {
224
- const p = e.payload as unknown as { id: string, ackedAt?: string, recovered?: boolean }
225
- if (p.ackedAt) {
226
- const i = alarms.findIndex(a => a.id === p.id)
227
- if (i >= 0) alarms.splice(i, 1)
228
- }
224
+ }
225
+ }
226
+
227
+ function handler(e: AepEnvelope) {
228
+ if (e.type === 'daq.reading') applyReading(e.payload as AepDaqReading)
229
+ else if (e.type === 'daq.frame') applyFrame(e.payload as unknown as AepDaqFrame)
230
+ else if (e.type === 'daq.node.changed') applyChange(e.payload as AepDaqNodeChange)
231
+ else if (e.type === 'daq.controller') Object.assign(controller, e.payload as AepDaqControllerState)
232
+ else if (e.type === 'daq.template.changed') applyTemplateChange(e.payload as AepDaqTemplateChange)
233
+ // S5 实时告警:server 权威事件直推(报警进入轨插入;ack 确认后移出未确认列表)
234
+ else if (e.type === 'daq.alarm') {
235
+ const p = e.payload as unknown as DaqAlarmRow
236
+ if (!alarms.some(a => a.id === p.id)) alarms.unshift(p)
237
+ }
238
+ else if (e.type === 'daq.alarm.changed') {
239
+ const p = e.payload as unknown as { id: string, ackedAt?: string, recovered?: boolean }
240
+ if (p.ackedAt) {
241
+ const i = alarms.findIndex(a => a.id === p.id)
242
+ if (i >= 0) alarms.splice(i, 1)
229
243
  }
230
- })
244
+ }
231
245
  }
232
246
 
233
247
  async function load(): Promise<void> {
@@ -259,7 +273,7 @@ const createStore = () => {
259
273
  store.error = ''
260
274
  }
261
275
  catch (err) {
262
- store.error = err instanceof Error ? err.message : String(err)
276
+ store.error = apiErrorMessage(err)
263
277
  }
264
278
  }
265
279
 
@@ -50,11 +50,27 @@ function createStore() {
50
50
  upsert(p.node)
51
51
  }
52
52
 
53
+ /** 引用计数订阅(同 useDaqStream):首个调用建订阅,归零才退订 */
54
+ let feedConsumers = 0
55
+ let feedUnsub: (() => void) | null = null
53
56
  function ensureWsFeed(): () => void {
54
- const g = globalThis as typeof globalThis & { __dcwBusFed?: boolean }
55
- if (g.__dcwBusFed) return () => {}
56
- g.__dcwBusFed = true
57
- return useTownBus().subscribe((e: AepEnvelope) => {
57
+ feedConsumers++
58
+ if (feedConsumers === 1) {
59
+ feedUnsub = useTownBus().subscribe(handler)
60
+ }
61
+ let done = false
62
+ return () => {
63
+ if (done) return
64
+ done = true
65
+ if (--feedConsumers === 0) {
66
+ feedUnsub?.()
67
+ feedUnsub = null
68
+ }
69
+ }
70
+ }
71
+
72
+ function handler(e: AepEnvelope) {
73
+ {
58
74
  if (e.type === 'dcw.written') {
59
75
  const p = e.payload as AepDcwWritten
60
76
  const n = nodes.find(x => x.id === p.nodeId)
@@ -83,8 +99,9 @@ function createStore() {
83
99
  const i = optimizations.findIndex(x => x.id === p.id)
84
100
  if (i >= 0) optimizations[i] = p
85
101
  else optimizations.unshift(p)
102
+ if (optimizations.length > 200) optimizations.length = 200
86
103
  }
87
- })
104
+ }
88
105
  }
89
106
 
90
107
  async function load(): Promise<void> {
@@ -104,7 +121,7 @@ function createStore() {
104
121
  store.error = ''
105
122
  }
106
123
  catch (err) {
107
- store.error = err instanceof Error ? err.message : String(err)
124
+ store.error = apiErrorMessage(err)
108
125
  }
109
126
  }
110
127
 
@@ -83,7 +83,7 @@ function createStore(): DeviceTwinStore {
83
83
  catch (err) {
84
84
  // 失败不再静默清空:保留旧数据 + 置错误态(apiFetch 归一化网络/HTTP/业务错误)
85
85
  store.loaded = false
86
- store.error = err instanceof Error ? err.message : String(err)
86
+ store.error = apiErrorMessage(err)
87
87
  }
88
88
  finally {
89
89
  store.__loading = null
@@ -74,21 +74,34 @@ const createStore = () => {
74
74
  const loading = reactive({ list: false, posting: false })
75
75
  const error = reactive({ list: '', post: '' })
76
76
 
77
- /** 挂 WS 帧(townBus);幂等。返回退订函数。 */
77
+ /** 挂 WS 帧(townBus)。引用计数(同 useDaqStream):归零才退订。 */
78
+ let feedConsumers = 0
79
+ let feedUnsub: (() => void) | null = null
78
80
  function ensureLive(): () => void {
79
- const g = globalThis as typeof globalThis & { __opsLogFed?: boolean }
80
- if (g.__opsLogFed) return () => {}
81
- g.__opsLogFed = true
82
- void seedRecent()
83
- return useTownBus().subscribe((e: AepEnvelope) => {
84
- if (e.type === 'ops.log') {
85
- const row = ingestFrame(e.payload as AepOpsLog)
86
- if (!recent.some(r => r.at === row.at && r.actor === row.actor && r.action === row.action)) {
87
- recent.unshift(row)
88
- if (recent.length > RECENT_CAP) recent.splice(RECENT_CAP)
89
- }
81
+ feedConsumers++
82
+ if (feedConsumers === 1) {
83
+ void seedRecent()
84
+ feedUnsub = useTownBus().subscribe(handler)
85
+ }
86
+ let done = false
87
+ return () => {
88
+ if (done) return
89
+ done = true
90
+ if (--feedConsumers === 0) {
91
+ feedUnsub?.()
92
+ feedUnsub = null
90
93
  }
91
- })
94
+ }
95
+ }
96
+
97
+ function handler(e: AepEnvelope) {
98
+ if (e.type === 'ops.log') {
99
+ const row = ingestFrame(e.payload as AepOpsLog)
100
+ if (!recent.some(r => r.at === row.at && r.actor === row.actor && r.action === row.action)) {
101
+ recent.unshift(row)
102
+ if (recent.length > RECENT_CAP) recent.splice(RECENT_CAP)
103
+ }
104
+ }
92
105
  }
93
106
 
94
107
  /** 首屏预填:最近 15 条历史摘要(实时轨不必从零等事件) */
@@ -117,7 +130,7 @@ const createStore = () => {
117
130
  results.splice(0, results.length, ...(data.logs ?? []))
118
131
  }
119
132
  catch (err) {
120
- error.list = err instanceof Error ? err.message : String(err)
133
+ error.list = apiErrorMessage(err)
121
134
  }
122
135
  finally {
123
136
  loading.list = false
@@ -132,7 +145,7 @@ const createStore = () => {
132
145
  await api('', { method: 'POST', body: JSON.stringify(input) })
133
146
  }
134
147
  catch (err) {
135
- error.post = err instanceof Error ? err.message : String(err)
148
+ error.post = apiErrorMessage(err)
136
149
  throw err
137
150
  }
138
151
  finally {
@@ -143,7 +143,7 @@ function createStore(): SceneLayoutStore {
143
143
  return
144
144
  }
145
145
  catch (err) {
146
- lastErr = err instanceof Error ? err.message : String(err)
146
+ lastErr = apiErrorMessage(err)
147
147
  if (attempt < 2) await sleep(400 * (attempt + 1))
148
148
  }
149
149
  }
@@ -12,6 +12,11 @@ import { useHitlStore } from '../../stores/workshop/hitl'
12
12
  import { useTownBus } from './useTownBus'
13
13
  import type { AepEnvelope, AepSnapshot } from '#shared/workshop-protocol'
14
14
 
15
+ // 心跳单例(模块作用域):所有 useWorkshopWs() 调用方共享一个 15s 定时器,
16
+ // 避免每组件实例一份冗余 ping 打向同一会话
17
+ let heartbeat: ReturnType<typeof setInterval> | null = null
18
+ let heartbeatUsers = 0
19
+
15
20
  export function useWorkshopWs() {
16
21
  const conn = useWsConnectionStore()
17
22
  const userStore = useUserStore()
@@ -100,8 +105,9 @@ export function useWorkshopWs() {
100
105
  session?.ensureConnected()
101
106
  }
102
107
 
103
- let heartbeat: ReturnType<typeof setInterval> | null = null
104
108
  onMounted(() => {
109
+ heartbeatUsers++
110
+ if (heartbeat) return
105
111
  // 15s 心跳:pong 停止后 checkStale 的断线感知最坏 ~20-35s(服务强杀的半开连接
106
112
  // 无 RST,靠 pong 超时发现);ping 发送失败立即关闭走重连,不等 stale 检测
107
113
  heartbeat = setInterval(() => {
@@ -110,7 +116,10 @@ export function useWorkshopWs() {
110
116
  }, 15_000)
111
117
  })
112
118
  onBeforeUnmount(() => {
113
- if (heartbeat) clearInterval(heartbeat)
119
+ if (--heartbeatUsers <= 0 && heartbeat) {
120
+ clearInterval(heartbeat)
121
+ heartbeat = null
122
+ }
114
123
  })
115
124
 
116
125
  return { subscribe, unsubscribe, ensureConnected, conn }
@@ -154,7 +154,7 @@ async function doTest(): Promise<void> {
154
154
  testResult.value = await daq.testNode(nodeId.value)
155
155
  }
156
156
  catch (err) {
157
- testResult.value = { ok: false, message: err instanceof Error ? err.message : String(err) }
157
+ testResult.value = { ok: false, message: apiErrorMessage(err) }
158
158
  }
159
159
  finally {
160
160
  testing.value = false
@@ -36,7 +36,7 @@ async function setNodeLine(id: string, e: Event): Promise<void> {
36
36
  if (n) n.lineId = lineId
37
37
  }
38
38
  catch (err) {
39
- message.error(err instanceof Error ? err.message : String(err))
39
+ message.error(apiErrorMessage(err))
40
40
  }
41
41
  }
42
42
 
@@ -47,7 +47,7 @@ async function setNodeDevice(id: string, e: Event): Promise<void> {
47
47
  await daq.bindNode(id, deviceId || null)
48
48
  }
49
49
  catch (err) {
50
- message.error(err instanceof Error ? err.message : String(err))
50
+ message.error(apiErrorMessage(err))
51
51
  }
52
52
  }
53
53
 
@@ -61,7 +61,7 @@ async function toggleNodeEnabled(n: { id: string, enabled: boolean, state: strin
61
61
  message.success(next ? tt('daq.k1nodestart147') : tt('daq.k1nodestop146'))
62
62
  }
63
63
  catch (err) {
64
- message.error(err instanceof Error ? err.message : String(err))
64
+ message.error(apiErrorMessage(err))
65
65
  }
66
66
  }
67
67
 
@@ -135,7 +135,7 @@ async function ackOne(id: string): Promise<void> {
135
135
  message.success(tt('daq.k1acked144'))
136
136
  }
137
137
  catch (err) {
138
- message.error(err instanceof Error ? err.message : String(err))
138
+ message.error(apiErrorMessage(err))
139
139
  }
140
140
  }
141
141
 
@@ -459,7 +459,7 @@ async function doTestConnection(): Promise<void> {
459
459
  addTest.value = await daq.testDriver(addDriver.value, addCfg.value)
460
460
  }
461
461
  catch (err) {
462
- addTest.value = { ok: false, message: err instanceof Error ? err.message : String(err) }
462
+ addTest.value = { ok: false, message: apiErrorMessage(err) }
463
463
  }
464
464
  finally {
465
465
  addTesting.value = false
@@ -504,7 +504,7 @@ async function doAddNode(): Promise<void> {
504
504
  addTest.value = null
505
505
  }
506
506
  catch (err) {
507
- addError.value = err instanceof Error ? err.message : String(err)
507
+ addError.value = apiErrorMessage(err)
508
508
  }
509
509
  finally {
510
510
  addSaving.value = false
@@ -592,7 +592,7 @@ async function saveTpl(): Promise<void> {
592
592
  resetTplForm()
593
593
  }
594
594
  catch (err) {
595
- tplError.value = err instanceof Error ? err.message : String(err)
595
+ tplError.value = apiErrorMessage(err)
596
596
  }
597
597
  finally {
598
598
  tplSaving.value = false
@@ -609,7 +609,7 @@ async function askDelTpl(t: DaqTemplateDef): Promise<void> {
609
609
  await daq.removeTemplate(t.key)
610
610
  }
611
611
  catch (err) {
612
- tplError.value = err instanceof Error ? err.message : String(err)
612
+ tplError.value = apiErrorMessage(err)
613
613
  }
614
614
  finally {
615
615
  confirmingDel.value = ''
@@ -124,7 +124,7 @@ async function doWrite(nodeId: string, value: number): Promise<void> {
124
124
  }
125
125
  }
126
126
  catch (err) {
127
- writeError.value = err instanceof Error ? err.message : String(err)
127
+ writeError.value = apiErrorMessage(err)
128
128
  }
129
129
  finally {
130
130
  writingId.value = ''
@@ -141,7 +141,7 @@ async function doRead(nodeId: string): Promise<void> {
141
141
  await dcw.readNode(nodeId)
142
142
  }
143
143
  catch (err) {
144
- writeError.value = err instanceof Error ? err.message : String(err)
144
+ writeError.value = apiErrorMessage(err)
145
145
  }
146
146
  finally {
147
147
  readingId.value = ''
@@ -164,7 +164,7 @@ async function toggleControl(nodeId: string, enabled: boolean): Promise<void> {
164
164
  }
165
165
  }
166
166
  catch (err) {
167
- writeError.value = err instanceof Error ? err.message : String(err)
167
+ writeError.value = apiErrorMessage(err)
168
168
  }
169
169
  finally {
170
170
  togglingId.value = ''
@@ -207,7 +207,7 @@ async function doTestConnection(): Promise<void> {
207
207
  addTest.value = await dcw.testDriver(addDriver.value, addCfg.value)
208
208
  }
209
209
  catch (err) {
210
- addTest.value = { ok: false, message: err instanceof Error ? err.message : String(err) }
210
+ addTest.value = { ok: false, message: apiErrorMessage(err) }
211
211
  }
212
212
  finally {
213
213
  addTesting.value = false
@@ -241,7 +241,7 @@ async function doAddNode(): Promise<void> {
241
241
  addSemantics.value = ''
242
242
  }
243
243
  catch (err) {
244
- addError.value = err instanceof Error ? err.message : String(err)
244
+ addError.value = apiErrorMessage(err)
245
245
  }
246
246
  finally {
247
247
  addSaving.value = false
@@ -304,7 +304,7 @@ async function doCreateTemplate(): Promise<void> {
304
304
  tplForm.semantics = ''
305
305
  }
306
306
  catch (err) {
307
- tplError.value = err instanceof Error ? err.message : String(err)
307
+ tplError.value = apiErrorMessage(err)
308
308
  }
309
309
  finally {
310
310
  tplSaving.value = false
@@ -332,7 +332,7 @@ async function doLineStart(): Promise<void> {
332
332
  lineMsg.value = t('dcwDetail.k17jteb9186', { p0: ls.value.productName, p1: ls.value.recipeName, p2: ls.value.runId })
333
333
  }
334
334
  catch (err) {
335
- lineErr.value = err instanceof Error ? err.message : String(err)
335
+ lineErr.value = apiErrorMessage(err)
336
336
  }
337
337
  finally {
338
338
  lineBusy.value = false
@@ -349,7 +349,7 @@ async function doLineStop(): Promise<void> {
349
349
  lineMsg.value = t('dcwDetail.kzl49pd187', { p0: was })
350
350
  }
351
351
  catch (err) {
352
- lineErr.value = err instanceof Error ? err.message : String(err)
352
+ lineErr.value = apiErrorMessage(err)
353
353
  }
354
354
  finally {
355
355
  lineBusy.value = false
@@ -375,7 +375,7 @@ async function doCreateProduct(): Promise<void> {
375
375
  productForm.description = ''
376
376
  }
377
377
  catch (err) {
378
- productError.value = err instanceof Error ? err.message : String(err)
378
+ productError.value = apiErrorMessage(err)
379
379
  }
380
380
  finally {
381
381
  productSaving.value = false
@@ -421,7 +421,7 @@ async function doQuery(): Promise<void> {
421
421
  if (queryResult.value.channels.length === 0) queryError.value = t('dcwDetail.kszv5sq136')
422
422
  }
423
423
  catch (err) {
424
- queryError.value = err instanceof Error ? err.message : String(err)
424
+ queryError.value = apiErrorMessage(err)
425
425
  }
426
426
  finally {
427
427
  queryBusy.value = false
@@ -509,7 +509,7 @@ async function saveRecipe(): Promise<void> {
509
509
  recipeOpen.value = false
510
510
  }
511
511
  catch (err) {
512
- recipeError.value = err instanceof Error ? err.message : String(err)
512
+ recipeError.value = apiErrorMessage(err)
513
513
  }
514
514
  finally {
515
515
  recipeSaving.value = false
@@ -526,7 +526,7 @@ async function doApplyRecipe(id: string): Promise<void> {
526
526
  if (ok < run.results.length) writeError.value = t('dcwDetail.ks7szkt188', { p0: run.results.filter(r => !r.ok).map(r => r.message).join(';') })
527
527
  }
528
528
  catch (err) {
529
- writeError.value = err instanceof Error ? err.message : String(err)
529
+ writeError.value = apiErrorMessage(err)
530
530
  }
531
531
  }
532
532
 
@@ -537,7 +537,7 @@ async function doViewRun(id: string): Promise<void> {
537
537
  runDataView.value = { runId: id, data }
538
538
  }
539
539
  catch (err) {
540
- writeError.value = err instanceof Error ? err.message : String(err)
540
+ writeError.value = apiErrorMessage(err)
541
541
  }
542
542
  finally {
543
543
  runDataLoading.value = false