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
@@ -7,7 +7,7 @@
7
7
  "productId": "pd-6348a595",
8
8
  "productName": "0.8mm 光学膜",
9
9
  "startedAt": "2026-09-03T11:18:01.213Z",
10
- "taggedSamples": 40180
10
+ "taggedSamples": 49286
11
11
  },
12
12
  {
13
13
  "lineId": "ln-9a60a0cd",
@@ -57,7 +57,7 @@
57
57
  "productId": "pd-db432902",
58
58
  "productName": "探针产品",
59
59
  "startedAt": "2026-09-04T05:08:10.103Z",
60
- "taggedSamples": 11354
60
+ "taggedSamples": 17196
61
61
  },
62
62
  {
63
63
  "lineId": "ln-6a34fbc7",
@@ -67,7 +67,7 @@
67
67
  "productId": "pd-10cfc2b3",
68
68
  "productName": "全协议产品-mtnynfph",
69
69
  "startedAt": "2026-09-05T05:47:26.453Z",
70
- "taggedSamples": 25175
70
+ "taggedSamples": 48679
71
71
  },
72
72
  {
73
73
  "lineId": "ln-419463e0",
@@ -77,7 +77,7 @@
77
77
  "productId": "pd-b9b15b64",
78
78
  "productName": "全协议产品-mtnzg090",
79
79
  "startedAt": "2026-09-05T06:09:36.931Z",
80
- "taggedSamples": 25155
80
+ "taggedSamples": 48652
81
81
  },
82
82
  {
83
83
  "lineId": "ln-3548f325",
@@ -87,7 +87,7 @@
87
87
  "productId": "pd-fd822802",
88
88
  "productName": "runp3-prod",
89
89
  "startedAt": "2026-09-05T07:23:51.972Z",
90
- "taggedSamples": 1994
90
+ "taggedSamples": 3925
91
91
  },
92
92
  {
93
93
  "lineId": "ln-c3a7ba01",
@@ -107,6 +107,26 @@
107
107
  "productId": "pd-d547a376",
108
108
  "productName": "pp-prod",
109
109
  "startedAt": "2026-09-05T09:47:55.526Z",
110
- "taggedSamples": 393
110
+ "taggedSamples": 6231
111
+ },
112
+ {
113
+ "lineId": "ln-1acc1a0c",
114
+ "runId": "rr-d3ac8878",
115
+ "recipeId": "rc-2a7b0def",
116
+ "recipeName": "lx8-recipe",
117
+ "productId": "pd-3adf854f",
118
+ "productName": "lx8-prod",
119
+ "startedAt": "2026-09-06T02:22:23.209+08:00",
120
+ "taggedSamples": 4136
121
+ },
122
+ {
123
+ "lineId": "ln-917490c1",
124
+ "runId": "rr-04594711",
125
+ "recipeId": "rc-4c9d5135",
126
+ "recipeName": "lx8-recipe",
127
+ "productId": "pd-75752beb",
128
+ "productName": "lx8-prod",
129
+ "startedAt": "2026-09-06T02:24:50.582+08:00",
130
+ "taggedSamples": 3995
111
131
  }
112
132
  ]
@@ -1,116 +1,119 @@
1
- /**
2
- * 备份定时插件(S6,production-readiness-plan)。
3
- *
4
- * 对 data/ 下三库(workshop/users/daq-timeseries)每日 serialize 镜像快照到
5
- * data/backups/,按 BACKUP_KEEP(默认 7)轮转;调度模式复用 ws.ts 保留期清理的
6
- * setInterval + globalThis key 防 HMR 重复 + unref()。dev 与生产均生效
7
- * (备份无副作用,始终开启;BACKUP_DISABLED=1 可关)。
8
- */
9
- import { copyFileSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync } from 'node:fs'
10
- import { resolve } from 'node:path'
11
- import { ensureDataDir } from '@/shared/config/home.mjs'
12
- import { backupSettings } from '../services/workshop/settings'
13
- import { backupRegistry } from '../services/workshop/db/backup-registry'
14
-
15
- const g = globalThis as typeof globalThis & { __awBackupTimer?: NodeJS.Timeout, __awBackupLastAt?: string }
16
-
17
- const DB_FILES = ['workshop.sqlite', 'users.sqlite', 'daq-timeseries.sqlite'] as const
18
-
19
- /**
20
- * 单库在线快照(hardening ST-2 终版:零侵入文件拷贝)。
21
- *
22
- * 真实事故两连(Windows + node:sqlite):
23
- * 1) 对活库开第二连接 serialize/close → 主连接 prepared statements 全部失效;
24
- * 2) 对主连接 serialize() → 该连接上全部语句被 finalize(20 分钟后 Mailbox 一用即炸)。
25
- * 结论:node:sqlite 上 serialize 路线对常驻服务不可行。终版:PASSIVE checkpoint
26
- * (尽力把 WAL 并回主文件,失败不影响服务)→ 拷贝主文件。得到的是「最后一次
27
- * checkpoint 时刻」的有效 SQLite 镜像;备份语义为日级韧性的兜底,允许略旧。
28
- */
29
- async function backupOne(src: string, target: string): Promise<void> {
30
- const db = backupRegistry.get(src)
31
- if (db) {
32
- try {
33
- db.exec('PRAGMA wal_checkpoint(PASSIVE)')
34
- }
35
- catch { /* 忙时跳过 checkpoint,拷出的镜像退回上次 checkpoint 点,仍有效 */ }
36
- }
37
- // 原子落盘:快照写一半被杀会留下截断 .bak(轮转后还被当作有效备份)
38
- const tmp = `${target}.tmp`
39
- copyFileSync(src, tmp)
40
- try {
41
- renameSync(tmp, target)
42
- }
43
- catch {
44
- // rename 失败(目标被占用等):退回直写,可用性优先
45
- copyFileSync(src, target)
46
- try {
47
- rmSync(tmp)
48
- }
49
- catch { /* ignore */ }
50
- }
51
- }
52
-
53
- async function backupOnce(dataDir: string): Promise<void> {
54
- const backupDir = resolve(dataDir, 'backups')
55
- mkdirSync(backupDir, { recursive: true })
56
- const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)
57
- for (const file of DB_FILES) {
58
- const src = resolve(dataDir, file)
59
- if (!existsSync(src) || !backupRegistry.has(src)) continue
60
- const target = resolve(backupDir, `${file}.${stamp}.bak`)
61
- try {
62
- await backupOne(src, target)
63
- console.log('[backup]', file, '快照完成(serialize)')
64
- }
65
- catch (err) {
66
- console.error(`[backup] ${file} 快照失败:`, err instanceof Error ? err.message : err)
67
- }
68
- }
69
- // 轮转:每库仅保留最近 backup.keep 份(按文件名内时间戳倒序;env BACKUP_KEEP 兼容)
70
- const keep = Math.max(1, backupSettings().keep)
71
- for (const file of DB_FILES) {
72
- const own = readdirSync(backupDir)
73
- .filter(f => f.startsWith(`${file}.`) && f.endsWith('.bak'))
74
- .sort()
75
- .reverse()
76
- for (const stale of own.slice(keep)) {
77
- try {
78
- rmSync(resolve(backupDir, stale))
79
- }
80
- catch { /* 轮转失败不致命 */ }
81
- }
82
- }
83
- console.log('[backup] 快照完成 →', backupDir)
84
- // R4:记录最近一次成功备份时间,供 /api/metrics 观测
85
- g.__awBackupLastAt = new Date().toISOString()
86
- }
87
-
88
- export default function backupPlugin() {
89
- const backupCfg = backupSettings()
90
- if (backupCfg.disabled) return
91
- if (g.__awBackupTimer) return
92
- const dataDir = ensureDataDir()
93
-
94
- // 启动 30s 后首备(避开启动风暴),此后每 backup.interval_hours(默认 24h)
95
- const first = setTimeout(() => {
96
- try {
97
- // backupOnce 是 async:同步 try/catch 接不住内部 rejection(会变成 unhandled
98
- // rejection 触发 dev-stability-guard 退进程),必须显式 .catch
99
- backupOnce(dataDir).catch((err: unknown) => {
100
- console.error('[backup] 首备失败:', err instanceof Error ? err.message : err)
101
- })
102
- }
103
- catch (err) {
104
- console.error('[backup] 首备失败:', err instanceof Error ? err.message : err)
105
- }
106
- }, 30_000)
107
- first.unref?.()
108
- const hours = Math.max(1, backupCfg.interval_hours)
109
- const timer = setInterval(() => {
110
- backupOnce(dataDir).catch((err: unknown) => {
111
- console.error('[backup] 定时备份失败:', err instanceof Error ? err.message : err)
112
- })
113
- }, hours * 3_600_000)
114
- timer.unref?.()
115
- g.__awBackupTimer = timer
116
- }
1
+ /**
2
+ * 备份定时插件(S6,production-readiness-plan)。
3
+ *
4
+ * 对 data/ 下三库(workshop/users/daq-timeseries)每日 serialize 镜像快照到
5
+ * data/backups/,按 BACKUP_KEEP(默认 7)轮转;调度模式复用 ws.ts 保留期清理的
6
+ * setInterval + globalThis key 防 HMR 重复 + unref()。dev 与生产均生效
7
+ * (备份无副作用,始终开启;BACKUP_DISABLED=1 可关)。
8
+ */
9
+ import { existsSync, mkdirSync, readdirSync, renameSync, rmSync } from 'node:fs'
10
+ import { copyFile as copyFileAsync } from 'node:fs/promises'
11
+ import { resolve } from 'node:path'
12
+ import { ensureDataDir } from '@/shared/config/home.mjs'
13
+ import { backupSettings } from '../services/workshop/settings'
14
+ import { backupRegistry } from '../services/workshop/db/backup-registry'
15
+
16
+ const g = globalThis as typeof globalThis & { __awBackupTimer?: NodeJS.Timeout, __awBackupLastAt?: string }
17
+
18
+ const DB_FILES = ['workshop.sqlite', 'users.sqlite', 'daq-timeseries.sqlite'] as const
19
+
20
+ /**
21
+ * 单库在线快照(hardening ST-2 终版:零侵入文件拷贝)。
22
+ *
23
+ * 真实事故两连(Windows + node:sqlite):
24
+ * 1) 对活库开第二连接 serialize/close → 主连接 prepared statements 全部失效;
25
+ * 2) 对主连接 serialize() → 该连接上全部语句被 finalize(20 分钟后 Mailbox 一用即炸)。
26
+ * 结论:node:sqlite 上 serialize 路线对常驻服务不可行。终版:PASSIVE checkpoint
27
+ * (尽力把 WAL 并回主文件,失败不影响服务)→ 拷贝主文件。得到的是「最后一次
28
+ * checkpoint 时刻」的有效 SQLite 镜像;备份语义为日级韧性的兜底,允许略旧。
29
+ */
30
+ async function backupOne(src: string, target: string): Promise<void> {
31
+ const db = backupRegistry.get(src)
32
+ if (db) {
33
+ try {
34
+ db.exec('PRAGMA wal_checkpoint(PASSIVE)')
35
+ }
36
+ catch { /* 忙时跳过 checkpoint,拷出的镜像退回上次 checkpoint 点,仍有效 */ }
37
+ }
38
+ // 原子落盘:快照写一半被杀会留下截断 .bak(轮转后还被当作有效备份)
39
+ // 异步拷贝:daq-timeseries 可达数百 MB,copyFileSync 会同步冻结事件循环数秒
40
+ // (期间 WS 扇出/采样 sweep/API 全部停摆)
41
+ const tmp = `${target}.tmp`
42
+ await copyFileAsync(src, tmp)
43
+ try {
44
+ renameSync(tmp, target)
45
+ }
46
+ catch {
47
+ // rename 失败(目标被占用等):退回直写,可用性优先
48
+ await copyFileAsync(src, target)
49
+ try {
50
+ rmSync(tmp)
51
+ }
52
+ catch { /* ignore */ }
53
+ }
54
+ }
55
+
56
+ async function backupOnce(dataDir: string): Promise<void> {
57
+ const backupDir = resolve(dataDir, 'backups')
58
+ mkdirSync(backupDir, { recursive: true })
59
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19)
60
+ for (const file of DB_FILES) {
61
+ const src = resolve(dataDir, file)
62
+ if (!existsSync(src) || !backupRegistry.has(src)) continue
63
+ const target = resolve(backupDir, `${file}.${stamp}.bak`)
64
+ try {
65
+ await backupOne(src, target)
66
+ console.log('[backup]', file, '快照完成(serialize)')
67
+ }
68
+ catch (err) {
69
+ console.error(`[backup] ${file} 快照失败:`, err instanceof Error ? err.message : err)
70
+ }
71
+ }
72
+ // 轮转:每库仅保留最近 backup.keep 份(按文件名内时间戳倒序;env BACKUP_KEEP 兼容)
73
+ const keep = Math.max(1, backupSettings().keep)
74
+ for (const file of DB_FILES) {
75
+ const own = readdirSync(backupDir)
76
+ .filter(f => f.startsWith(`${file}.`) && f.endsWith('.bak'))
77
+ .sort()
78
+ .reverse()
79
+ for (const stale of own.slice(keep)) {
80
+ try {
81
+ rmSync(resolve(backupDir, stale))
82
+ }
83
+ catch { /* 轮转失败不致命 */ }
84
+ }
85
+ }
86
+ console.log('[backup] 快照完成 →', backupDir)
87
+ // R4:记录最近一次成功备份时间,供 /api/metrics 观测
88
+ g.__awBackupLastAt = new Date().toISOString()
89
+ }
90
+
91
+ export default function backupPlugin() {
92
+ const backupCfg = backupSettings()
93
+ if (backupCfg.disabled) return
94
+ if (g.__awBackupTimer) return
95
+ const dataDir = ensureDataDir()
96
+
97
+ // 启动 30s 后首备(避开启动风暴),此后每 backup.interval_hours(默认 24h)
98
+ const first = setTimeout(() => {
99
+ try {
100
+ // backupOnce 是 async:同步 try/catch 接不住内部 rejection(会变成 unhandled
101
+ // rejection 触发 dev-stability-guard 退进程),必须显式 .catch
102
+ backupOnce(dataDir).catch((err: unknown) => {
103
+ console.error('[backup] 首备失败:', err instanceof Error ? err.message : err)
104
+ })
105
+ }
106
+ catch (err) {
107
+ console.error('[backup] 首备失败:', err instanceof Error ? err.message : err)
108
+ }
109
+ }, 30_000)
110
+ first.unref?.()
111
+ const hours = Math.max(1, backupCfg.interval_hours)
112
+ const timer = setInterval(() => {
113
+ backupOnce(dataDir).catch((err: unknown) => {
114
+ console.error('[backup] 定时备份失败:', err instanceof Error ? err.message : err)
115
+ })
116
+ }, hours * 3_600_000)
117
+ timer.unref?.()
118
+ g.__awBackupTimer = timer
119
+ }
@@ -40,6 +40,14 @@ CREATE TABLE IF NOT EXISTS user_tokens (
40
40
  last_used_at TEXT
41
41
  );
42
42
  CREATE INDEX IF NOT EXISTS idx_user_tokens_user ON user_tokens(user_id);
43
+ CREATE TABLE IF NOT EXISTS user_line_grants (
44
+ user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
45
+ line_id TEXT NOT NULL,
46
+ mode TEXT NOT NULL,
47
+ granted_by TEXT,
48
+ granted_at TEXT NOT NULL,
49
+ PRIMARY KEY (user_id, line_id)
50
+ );
43
51
  `
44
52
 
45
53
  let db: DatabaseSync | null = null
@@ -50,6 +58,9 @@ function getDb(): DatabaseSync {
50
58
  db = new DatabaseSync(DB_PATH)
51
59
  // 主连接登记(备份 serialize 用;见 backup-registry 说明)
52
60
  backupRegistry.register(DB_PATH, db)
61
+ // WAL:认证读路径不再与写互斥(rollback 模式每请求写锁+fsync 串行化全部 API)
62
+ db.exec('PRAGMA journal_mode = WAL')
63
+ db.exec('PRAGMA synchronous = NORMAL')
53
64
  db.exec('PRAGMA busy_timeout = 5000')
54
65
  db.exec(SCHEMA_SQL)
55
66
  migrateSchema(db)
@@ -69,6 +80,8 @@ function migrateSchema(d: DatabaseSync): void {
69
80
  if (!cols.some(c => c.name === 'expires_at')) {
70
81
  d.exec('ALTER TABLE user_tokens ADD COLUMN expires_at TEXT')
71
82
  }
83
+ // 安全迁移:清空存量明文 token——库中只保留哈希,备份/文件拷贝不再等于凭据泄漏
84
+ d.exec('UPDATE user_tokens SET token_plain = NULL WHERE token_plain IS NOT NULL')
72
85
  // 存量 token 宽限 30 天(从部署时刻起算,避免升级即全员掉线)
73
86
  d.prepare('UPDATE user_tokens SET expires_at = ? WHERE expires_at IS NULL').run(isoInDays(TOKEN_TTL_DAYS))
74
87
  }
@@ -168,7 +181,7 @@ function hashToken(token: string): string {
168
181
  return createHash('sha256').update(token).digest('hex')
169
182
  }
170
183
 
171
- /** 签发新 token:明文返回一次并存档(token_plain,支持随时查看),库中另存哈希用于认证比对 */
184
+ /** 签发新 token:明文仅此一次返回,库中只存 SHA-256 哈希(0.7.10 起不再存档明文) */
172
185
  function issueToken(userId: string, label: string): { raw: string, row: UserToken } {
173
186
  const raw = `ut-${randomUUID().replace(/-/g, '')}`
174
187
  const hash = hashToken(raw)
@@ -179,14 +192,18 @@ function issueToken(userId: string, label: string): { raw: string, row: UserToke
179
192
  createdAt: now(),
180
193
  lastUsedAt: null,
181
194
  preview: maskPreview(raw),
182
- hasPlain: true,
195
+ hasPlain: false,
183
196
  }
184
197
  const d = getDb()
185
- d.prepare('INSERT INTO user_tokens (id, user_id, label, token_hash, token_plain, created_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?)')
186
- .run(row.id, userId, label, hash, raw, row.createdAt, isoInDays(TOKEN_TTL_DAYS))
198
+ d.prepare('INSERT INTO user_tokens (id, user_id, label, token_hash, token_plain, created_at, expires_at) VALUES (?, ?, ?, ?, NULL, ?, ?)')
199
+ .run(row.id, userId, label, hash, row.createdAt, isoInDays(TOKEN_TTL_DAYS))
187
200
  return { raw, row }
188
201
  }
189
202
 
203
+ /** last_used_at 写节流:每 tokenId 60s 最多落库一次(高频认证路径不再逐请求写锁) */
204
+ const lastUsedSeen = new Map<string, number>()
205
+ const LAST_USED_THROTTLE_MS = 60_000
206
+
190
207
  /** 按 token 明文查用户(命中且未过期则刷新 last_used_at);无效/已过期返回 null。tokenId 供前端识别当前会话 token。 */
191
208
  export function findByToken(token: string): (User & { tokenId: string }) | null {
192
209
  const d = getDb()
@@ -201,7 +218,11 @@ WHERE t.token_hash = ?`,
201
218
  if (row.expiresAt && Date.parse(row.expiresAt) < Date.now()) return null
202
219
  // 禁用账号即时失效(此前存量 token 在禁用后最长 30 天仍可用)
203
220
  if (row.status && row.status !== 'active') return null
204
- d.prepare('UPDATE user_tokens SET last_used_at = ? WHERE token_hash = ?').run(now(), hash)
221
+ const seenAt = lastUsedSeen.get(row.tokenId) ?? 0
222
+ if (Date.now() - seenAt >= LAST_USED_THROTTLE_MS) {
223
+ lastUsedSeen.set(row.tokenId, Date.now())
224
+ d.prepare('UPDATE user_tokens SET last_used_at = ? WHERE token_hash = ?').run(now(), hash)
225
+ }
205
226
  return row
206
227
  }
207
228
 
@@ -233,6 +254,19 @@ export const userRepository = {
233
254
  return { items: rows.map(toUser), total, page, pageSize }
234
255
  },
235
256
 
257
+ /** 全量用户(不分页;管理面授权矩阵用,避免分页截断) */
258
+ listAll(): User[] {
259
+ const d = getDb()
260
+ const rows = d.prepare('SELECT id, name, email, role, status, created_at AS createdAt FROM users ORDER BY created_at DESC').all() as Array<Record<string, unknown>>
261
+ return rows.map(toUser)
262
+ },
263
+
264
+ /** 全部产线授权(单查询;管理面按 userId 分组,替代逐用户 N+1) */
265
+ allGrants(): Array<{ userId: string, lineId: string, mode: string, grantedBy: string | null, grantedAt: string }> {
266
+ const d = getDb()
267
+ return d.prepare('SELECT user_id AS userId, line_id AS lineId, mode, granted_by AS grantedBy, granted_at AS grantedAt FROM user_line_grants').all() as Array<{ userId: string, lineId: string, mode: string, grantedBy: string | null, grantedAt: string }>
268
+ },
269
+
236
270
  findById(id: string): User | undefined {
237
271
  const d = getDb()
238
272
  const row = d.prepare('SELECT id, name, email, role, status, created_at AS createdAt FROM users WHERE id = ?').get(id) as Record<string, unknown> | undefined
@@ -254,10 +288,37 @@ export const userRepository = {
254
288
  /** 是否存在活跃管理员(初始化判定:false → 系统处于首启注册模式,首个注册账号将成为管理员) */
255
289
  hasActiveAdmin(): boolean {
256
290
  const d = getDb()
257
- const { n } = d.prepare("SELECT COUNT(*) AS n FROM users WHERE role = 'admin' AND status = 'active'").get() as { n: number }
291
+ const { n } = d.prepare('SELECT COUNT(*) AS n FROM users WHERE role = \'admin\' AND status = \'active\'').get() as { n: number }
258
292
  return n > 0
259
293
  },
260
294
 
295
+ // ===== 产线授权(user_line_grants;admin/editor 不查此表,全量全权)=====
296
+
297
+ /** 某用户全部产线授权 */
298
+ listGrants(userId: string): Array<{ lineId: string, mode: string, grantedBy: string | null, grantedAt: string }> {
299
+ const d = getDb()
300
+ return d.prepare('SELECT line_id AS lineId, mode, granted_by AS grantedBy, granted_at AS grantedAt FROM user_line_grants WHERE user_id = ?').all(userId) as Array<{ lineId: string, mode: string, grantedBy: string | null, grantedAt: string }>
301
+ },
302
+
303
+ /** 单条授权(mode 非 readonly/operate → 撤销);返回是否发生变化 */
304
+ setGrant(userId: string, lineId: string, mode: string | null, grantedBy: string | null): boolean {
305
+ const d = getDb()
306
+ if (mode !== 'readonly' && mode !== 'operate') {
307
+ return d.prepare('DELETE FROM user_line_grants WHERE user_id = ? AND line_id = ?').run(userId, lineId).changes > 0
308
+ }
309
+ d.prepare(`INSERT INTO user_line_grants (user_id, line_id, mode, granted_by, granted_at) VALUES (?, ?, ?, ?, ?)
310
+ ON CONFLICT(user_id, line_id) DO UPDATE SET mode = excluded.mode, granted_by = excluded.granted_by, granted_at = excluded.granted_at`)
311
+ .run(userId, lineId, mode, grantedBy, now())
312
+ return true
313
+ },
314
+
315
+ /** 用户 → 产线访问映射(lineId → 'readonly'|'operate');无记录 = 无权 */
316
+ lineAccessMap(userId: string): Map<string, string> {
317
+ const d = getDb()
318
+ const rows = d.prepare('SELECT line_id AS lineId, mode FROM user_line_grants WHERE user_id = ?').all(userId) as Array<{ lineId: string, mode: string }>
319
+ return new Map(rows.map(r => [r.lineId, r.mode]))
320
+ },
321
+
261
322
  /** 内部:取密码哈希(仅认证路径使用,不参与领域对象外泄) */
262
323
  getPasswordHash(email: string): { id: string, hash: string } | null {
263
324
  const d = getDb()
@@ -280,6 +341,25 @@ export const userRepository = {
280
341
  return user
281
342
  },
282
343
 
344
+ /** 原子注册(IMMEDIATE 事务内判定管理员空缺):并发注册不会产生第二个 bootstrap admin */
345
+ createWithRoleBootstrap(input: UserCreate & { password: string }): { user: User, bootstrap: boolean } {
346
+ const d = getDb()
347
+ d.exec('BEGIN IMMEDIATE')
348
+ try {
349
+ const bootstrap = !this.hasActiveAdmin()
350
+ const user = this.create({ ...input, role: bootstrap ? 'admin' : input.role })
351
+ d.exec('COMMIT')
352
+ return { user, bootstrap }
353
+ }
354
+ catch (err) {
355
+ try {
356
+ d.exec('ROLLBACK')
357
+ }
358
+ catch { /* 事务已自滚 */ }
359
+ throw err
360
+ }
361
+ },
362
+
283
363
  update(id: string, input: UserUpdate): User | undefined {
284
364
  const d = getDb()
285
365
  const current = this.findById(id)
@@ -97,6 +97,11 @@ export class SystemConfigService {
97
97
  private disposed = false
98
98
  private applyWarned = false
99
99
 
100
+ /** 是否已完成 init()(descriptors 装载完毕;settings.ts 据此决定消费内存权威还是文件链) */
101
+ get ready(): boolean {
102
+ return this.descriptors.length > 0
103
+ }
104
+
100
105
  constructor(readonly root: string) {
101
106
  this.configPath = join(root, 'config.yml')
102
107
  // 设置文件必须与 CLI(aw config set)/start/dev-guard 同源(resolveRunMode 单一入口):
@@ -84,7 +84,8 @@ export const userService = {
84
84
  // ===== 认证(公开端点)=====
85
85
 
86
86
  /** 注册:创建账号 + 签发首个 token(邮箱/用户名占用 → 409)。
87
- * 首启初始化:系统尚无活跃管理员时,首个注册账号授予 admin(空库自注册建站) */
87
+ * 首启初始化:原子事务内判定「尚无活跃管理员」→ 首个注册账号授予 admin
88
+ * (并发注册不会产生第二个 bootstrap admin) */
88
89
  register(input: UserRegister): AuthResult {
89
90
  if (userRepository.findByEmail(input.email)) {
90
91
  throw new AppError(409, ErrorCodes.CONFLICT, '邮箱已被注册')
@@ -92,11 +93,12 @@ export const userService = {
92
93
  if (userRepository.findByName(input.name)) {
93
94
  throw new AppError(409, 'USER_EXISTS', `用户名已存在: ${input.name}`)
94
95
  }
95
- const needsBootstrap = !userRepository.hasActiveAdmin()
96
+ const { user, bootstrap: needsBootstrap } = userRepository.createWithRoleBootstrap({
97
+ ...input, role: 'user', status: 'active',
98
+ })
96
99
  if (needsBootstrap) {
97
100
  console.log(`[users] 初始化:尚无管理员账号,首个注册账号授予管理员角色(${input.email})`)
98
101
  }
99
- const user = userRepository.create({ ...input, role: needsBootstrap ? 'admin' : 'user', status: 'active' })
100
102
  const { raw } = userRepository.createToken(user.id, needsBootstrap ? 'bootstrap-admin' : 'default')
101
103
  return { user: this.publicProfile(user), token: raw }
102
104
  },
@@ -2,13 +2,13 @@
2
2
  * DaqQueuePort 工厂 —— 配置驱动(DAQ_MQTT_URL 由 infra 提供),缺省进程内 mock 队列。
3
3
  * 单例 globalThis;rebuildDaqQueue() 支持重连时切回真实 MQTT。
4
4
  */
5
- import { createLogger } from '../../logger'
5
+ import { createLogger } from '../../logger'
6
6
  import { InProcQueueAdapter } from './inproc.adapter'
7
7
  import { MqttQueueAdapter } from './mqtt.adapter'
8
8
  import type { DaqQueuePort } from './queue-port'
9
9
 
10
- const log = createLogger('daq.queue')
11
-
10
+ const log = createLogger('daq.queue')
11
+
12
12
  const g = globalThis as typeof globalThis & { __daqQueue?: DaqQueuePort }
13
13
 
14
14
  export async function getDaqQueue(): Promise<DaqQueuePort> {
@@ -22,6 +22,8 @@ export async function getDaqQueue(): Promise<DaqQueuePort> {
22
22
 
23
23
  /** 重连/初始装配:按 infra 判定结果(重新)构建 MQTT 或进程内队列 */
24
24
  export async function rebuildDaqQueue(online: boolean, url?: string | null): Promise<DaqQueuePort> {
25
+ // 换装前释放旧 adapter(mqtt 连接 / inproc 泵),防重建泄漏
26
+ await g.__daqQueue?.close?.()
25
27
  if (!online || !url) {
26
28
  if (g.__daqQueue?.backend !== 'inproc') {
27
29
  g.__daqQueue = new InProcQueueAdapter()
@@ -3,11 +3,11 @@
3
3
  * 与 MQTT 版同契约:生产端 publish 即刻入队不阻塞采集;消费泵按序拉取,
4
4
  * 拥塞时丢最旧并计数(暴露给 meta,诚实可见)。
5
5
  */
6
- import { createLogger } from '../../logger'
6
+ import { createLogger } from '../../logger'
7
7
  import type { DaqConsumer, DaqQueuePort, DaqSampleEnvelope } from './queue-port'
8
8
 
9
- const log = createLogger('daq.queue')
10
-
9
+ const log = createLogger('daq.queue')
10
+
11
11
  const QUEUE_CAP = 10_000
12
12
  /** 消费泵节拍(ms):攒批交给下游(TSDB 批量写) */
13
13
  const PUMP_INTERVAL = 250
@@ -45,6 +45,15 @@ export class InProcQueueAdapter implements DaqQueuePort {
45
45
  }
46
46
  }
47
47
 
48
+ /** 释放消费泵(rebuild 换装前调用,防定时器泄漏) */
49
+ close(): void {
50
+ if (this.pump) {
51
+ clearInterval(this.pump)
52
+ this.pump = null
53
+ }
54
+ this.consumers.clear()
55
+ }
56
+
48
57
  private drain(): void {
49
58
  if (this.queue.length === 0 || this.consumers.size === 0) return
50
59
  const batch = this.queue.splice(0, this.queue.length)
@@ -107,5 +107,18 @@ export class MqttQueueAdapter implements DaqQueuePort {
107
107
  return () => {
108
108
  this.consumers.delete(fn)
109
109
  }
110
+ }
111
+
112
+ /** 断开 MQTT 连接并清理订阅(rebuild 换装前调用,防 socket/keepalive 泄漏) */
113
+ async close(): Promise<void> {
114
+ this.consumers.clear()
115
+ const c = this.client
116
+ this.client = null
117
+ if (c) {
118
+ try {
119
+ await new Promise<void>(r => c.end(false, () => r()))
120
+ }
121
+ catch { /* 已断连等场景:尽力而为 */ }
122
+ }
110
123
  }
111
124
  }
@@ -51,4 +51,6 @@ export interface DaqQueuePort {
51
51
  publish(env: DaqSampleEnvelope): void
52
52
  /** 消费者:注册处理函数;返回退订 */
53
53
  consume(fn: DaqConsumer): () => void
54
+ /** 释放底层资源(mqtt 连接 / inproc 泵);rebuild 换装前必须调用,防 socket/定时器泄漏 */
55
+ close?(): Promise<void> | void
54
56
  }
@@ -289,6 +289,7 @@ class DaqController {
289
289
  value: node.value ?? env.value,
290
290
  state: node.state,
291
291
  at: env.at,
292
+ lineId: node.lineId ?? null,
292
293
  } satisfies AepDaqReading
293
294
  this.broadcast?.('daq.reading', reading)
294
295
  // 插件钩子:下发级采样观察(与 WS daq.reading 同点同节拍;宿主未装载时零开销 no-op)
@@ -373,6 +374,7 @@ class DaqController {
373
374
  templateRef: node.templateRef,
374
375
  kind: f.kind,
375
376
  at: env.at,
377
+ lineId: node.lineId ?? null,
376
378
  preview: f.kind === 'vector' ? DaqController.previewOf(f.points ?? [], FRAME_PREVIEW_POINTS) : undefined,
377
379
  metrics,
378
380
  thumbUrl: f.kind === 'image' && f.objectKey
@@ -619,6 +621,9 @@ class DaqController {
619
621
  }
620
622
  finally {
621
623
  this.tsdbWriting = false
624
+ // 尾批自愈:flush 期间新样本/帧到达时 schedule 被跳过(tsdbWriting 守卫),
625
+ // 若此处不留 timer,停线后的残余批次将无定时器可触发,驻留内存直至进程重启
626
+ if (this.tsdbBuffer.length > 0 || this.frameBuffer.length > 0) this.scheduleTsdbFlush()
622
627
  }
623
628
  }
624
629
 
@@ -626,13 +631,25 @@ class DaqController {
626
631
  * 状态随行:节点 alarm 派生自用户设置的量程/预警带(数据驱动),透传给孪生而非让孪生按硬编码阈值猜 */
627
632
  private pendingBackfill = new Map<string, Record<string, number | string | boolean>>()
628
633
 
634
+ /** 同绑定 siblings 缓存(1s TTL):回写热路径不再逐样本全量 scan,O(N²)→O(N)/周期 */
635
+ private siblingsCache = new Map<string, { at: number, list: DaqNode[] }>()
636
+
637
+ private siblingsOf(bindingId: string): DaqNode[] {
638
+ const hit = this.siblingsCache.get(bindingId)
639
+ if (hit && Date.now() - hit.at < 1000) return hit.list
640
+ const list = this.repo.all().filter(n => n.deviceBindingId === bindingId)
641
+ if (this.siblingsCache.size > 500) this.siblingsCache.clear()
642
+ this.siblingsCache.set(bindingId, { at: Date.now(), list })
643
+ return list
644
+ }
645
+
629
646
  private writeBackTelemetry(node: DaqNode): void {
630
647
  if (!node.deviceBindingId || node.value == null) return
631
648
  const host = getDaqHostPorts()
632
649
  if (!host) return // 端口未装配(边缘独立/装配前):不攒积压,直接跳过回写
633
650
  const key = findDaqTemplate(node.templateKey)?.telemetryKey ?? node.templateKey
634
651
  // 同设备多节点绑定:取最严重节点态(alarm > warn > ok/offline),避免"最近写者定态"抖动
635
- const siblings = this.repo.all().filter(n => n.deviceBindingId === node.deviceBindingId)
652
+ const siblings = this.siblingsOf(node.deviceBindingId)
636
653
  const worst = siblings.some(n => n.state === 'alarm')
637
654
  ? 'alarm'
638
655
  : siblings.some(n => n.state === 'warn') ? 'warn' : 'ok'