agentworkshop 0.7.6 → 0.7.7

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 (517) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +1 -1
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +1 -1
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/{rzGB_ojX.js → 3612gD2V.js} +2 -2
  5. package/.output/public/_nuxt/8eIQAVlb.js +1 -0
  6. package/.output/public/_nuxt/Ah9qOv1m.js +1 -0
  7. package/.output/public/_nuxt/{DdPeifHR.js → B4Fia4FB.js} +1 -1
  8. package/.output/public/_nuxt/B7aqqzkY.js +1 -0
  9. package/.output/public/_nuxt/BJ-fxrSw.js +1 -0
  10. package/.output/public/_nuxt/{DPDqAD1e.js → BSXx2vqR.js} +1 -1
  11. package/.output/public/_nuxt/{CdSgfcYR.js → BVZjSVs2.js} +1 -1
  12. package/.output/public/_nuxt/{DP6bdyIp.js → BVzDoF8t.js} +1 -1
  13. package/.output/public/_nuxt/BYL0Rjqj.js +7 -0
  14. package/.output/public/_nuxt/{CXmkVXS5.js → BjVLsC3M.js} +1 -1
  15. package/.output/public/_nuxt/{7ZABjMRh2.js → BkfchkK62.js} +1 -1
  16. package/.output/public/_nuxt/BnVoQ74r.js +1 -0
  17. package/.output/public/_nuxt/Bnp4vIAf.js +1 -0
  18. package/.output/public/_nuxt/BsMpJf7S.js +70 -0
  19. package/.output/public/_nuxt/{Z8k0uMSI.js → Bt_HDizI.js} +1 -1
  20. package/.output/public/_nuxt/Bu-P92Pe.js +18 -0
  21. package/.output/public/_nuxt/ButLXkjo.js +2 -0
  22. package/.output/public/_nuxt/C-GarxYC.js +1 -0
  23. package/.output/public/_nuxt/{D8DDDzV62.js → C2iWjzEC2.js} +1 -1
  24. package/.output/public/_nuxt/{HWXLx5Hz.js → C8dxXc6K.js} +5 -5
  25. package/.output/public/_nuxt/CGdPdJPP.js +1 -0
  26. package/.output/public/_nuxt/{CyygA0q4.js → CQiKcuoG.js} +4 -4
  27. package/.output/public/_nuxt/{CN7Zh8GQ.js → CRGlf1Gb.js} +1 -1
  28. package/.output/public/_nuxt/{DSBfvCi5.js → CblLEiCZ.js} +7 -7
  29. package/.output/public/_nuxt/Cd15nPnG2.js +1 -0
  30. package/.output/public/_nuxt/{OwJ1LJkF.js → CsCpu2Zh.js} +1 -1
  31. package/.output/public/_nuxt/CvbHIGQY2.js +1 -0
  32. package/.output/public/_nuxt/Cyk3du4K2.js +1 -0
  33. package/.output/public/_nuxt/{DVQAz9WI.js → D4qXvjuV.js} +2 -2
  34. package/.output/public/_nuxt/{CfIXY-ET.js → DCEyMaN-.js} +1 -1
  35. package/.output/public/_nuxt/{BFYNhG9S.js → DCXIGxzT.js} +1 -1
  36. package/.output/public/_nuxt/{B9aPoQvt.js → DM8DS9MA.js} +1 -1
  37. package/.output/public/_nuxt/{ChnfyQHz.js → DNzaswei.js} +1 -1
  38. package/.output/public/_nuxt/{CrFGZYVB2.js → DYZBdSSg2.js} +1 -1
  39. package/.output/public/_nuxt/{dObsRdSQ.js → DZk24ego.js} +1 -1
  40. package/.output/public/_nuxt/DeYsUzhr.js +1 -0
  41. package/.output/public/_nuxt/Dk6pq9JB2.js +1 -0
  42. package/.output/public/_nuxt/{ByGNWgAr.js → Do88WZG2.js} +3 -3
  43. package/.output/public/_nuxt/{R_WxTozV2.js → Du-eSpo2.js} +1 -1
  44. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +1 -0
  45. package/.output/public/_nuxt/{Bsc69G4x.js → VnIWJ0ts.js} +3 -3
  46. package/.output/public/_nuxt/_id_.BzKMZnLe.css +1 -0
  47. package/.output/public/_nuxt/_id_.CbpDAWRh.css +1 -0
  48. package/.output/public/_nuxt/{_wsId_.DET_GinP.css → _wsId_.COUzMXpP.css} +1 -1
  49. package/.output/public/_nuxt/agents.BlejnOOC.css +1 -0
  50. package/.output/public/_nuxt/builds/latest.json +1 -1
  51. package/.output/public/_nuxt/builds/meta/14df171d-89cb-43ec-ad6f-9df72d6da7f5.json +1 -0
  52. package/.output/public/_nuxt/daq.zZ8GR433.css +1 -0
  53. package/.output/public/_nuxt/{default.D17kXlD6.css → default.V3_hUJq1.css} +1 -1
  54. package/.output/public/_nuxt/{B4GHHF6d2.js → fQUs58kX2.js} +1 -1
  55. package/.output/public/_nuxt/p7wSGMtc.js +1 -0
  56. package/.output/public/_nuxt/tRBT-plo.js +1 -0
  57. package/.output/server/chunks/_/SearchOutlined.mjs +4 -4
  58. package/.output/server/chunks/_/SearchOutlined.mjs.map +1 -1
  59. package/.output/server/chunks/_/character-asset.repo.mjs +3 -6
  60. package/.output/server/chunks/_/character-asset.repo.mjs.map +1 -1
  61. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  62. package/.output/server/chunks/_/nitro.mjs +4967 -2035
  63. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  64. package/.output/server/chunks/_/scene-layout.repo.mjs +4 -10
  65. package/.output/server/chunks/_/scene-layout.repo.mjs.map +1 -1
  66. package/.output/server/chunks/build/{Col-D7fjGDF6.mjs → Col-biaNnEPf.mjs} +2 -2
  67. package/.output/server/chunks/build/{Col-D7fjGDF6.mjs.map → Col-biaNnEPf.mjs.map} +1 -1
  68. package/.output/server/chunks/build/{OmpTerminalPanel-B_SYhmgb.mjs → OmpTerminalPanel-COphA1br.mjs} +20 -19
  69. package/.output/server/chunks/build/OmpTerminalPanel-COphA1br.mjs.map +1 -0
  70. package/.output/server/chunks/build/{TownView-Bl8Gkcxi.mjs → TownView-B5KifIaT.mjs} +4 -4
  71. package/.output/server/chunks/build/{TownView-Bl8Gkcxi.mjs.map → TownView-B5KifIaT.mjs.map} +1 -1
  72. package/.output/server/chunks/build/{_id_-GnRJPykX.mjs → _id_-C-ewLgfl.mjs} +119 -119
  73. package/.output/server/chunks/build/{_id_-GnRJPykX.mjs.map → _id_-C-ewLgfl.mjs.map} +1 -1
  74. package/.output/server/chunks/build/{_id_-CWLFGZjV.mjs → _id_-Ct4Jhvl1.mjs} +42 -38
  75. package/.output/server/chunks/build/_id_-Ct4Jhvl1.mjs.map +1 -0
  76. package/.output/server/chunks/build/{_wsId_-BhQMjyHG.mjs → _wsId_-CanI_6Su.mjs} +591 -53
  77. package/.output/server/chunks/build/{_wsId_-BhQMjyHG.mjs.map → _wsId_-CanI_6Su.mjs.map} +1 -1
  78. package/.output/server/chunks/build/{agents-D4l1icvn.mjs → agents-DSOptxXA.mjs} +146 -91
  79. package/.output/server/chunks/build/agents-DSOptxXA.mjs.map +1 -0
  80. package/.output/server/chunks/build/{alert-gH-s7yIh.mjs → alert-qJnjyRcP.mjs} +3 -3
  81. package/.output/server/chunks/build/{alert-gH-s7yIh.mjs.map → alert-qJnjyRcP.mjs.map} +1 -1
  82. package/.output/server/chunks/build/{button-BhbX5ACI.mjs → button-DEcZFcqN.mjs} +3 -3
  83. package/.output/server/chunks/build/{button-BhbX5ACI.mjs.map → button-DEcZFcqN.mjs.map} +1 -1
  84. package/.output/server/chunks/build/{card-l4BbX67w.mjs → card-Dipvaykh.mjs} +5 -5
  85. package/.output/server/chunks/build/{card-l4BbX67w.mjs.map → card-Dipvaykh.mjs.map} +1 -1
  86. package/.output/server/chunks/build/{channel-templates-DqjtC-R0.mjs → channel-templates-BK0KuPOd.mjs} +13 -12
  87. package/.output/server/chunks/build/channel-templates-BK0KuPOd.mjs.map +1 -0
  88. package/.output/server/chunks/build/{checkbox-BF11p3dH.mjs → checkbox-dzcpU_Cd.mjs} +4 -4
  89. package/.output/server/chunks/build/{checkbox-BF11p3dH.mjs.map → checkbox-dzcpU_Cd.mjs.map} +1 -1
  90. package/.output/server/chunks/build/{daq-BOgpn9sl.mjs → daq-D9RA_uze.mjs} +102 -102
  91. package/.output/server/chunks/build/{daq-BOgpn9sl.mjs.map → daq-D9RA_uze.mjs.map} +1 -1
  92. package/.output/server/chunks/build/dcw-BTM5YU-B.mjs +1 -1
  93. package/.output/server/chunks/build/{default-CKJWhkot.mjs → default-BfWGTlbj.mjs} +81 -23
  94. package/.output/server/chunks/build/{default-CKJWhkot.mjs.map → default-BfWGTlbj.mjs.map} +1 -1
  95. package/.output/server/chunks/build/{drawer-CVValqoh.mjs → drawer-Cmh90erI.mjs} +3 -3
  96. package/.output/server/chunks/build/{drawer-CVValqoh.mjs.map → drawer-Cmh90erI.mjs.map} +1 -1
  97. package/.output/server/chunks/build/{dropdown-ByCsEWlQ.mjs → dropdown-CGQ0KAzA.mjs} +2 -2
  98. package/.output/server/chunks/build/{dropdown-ByCsEWlQ.mjs.map → dropdown-CGQ0KAzA.mjs.map} +1 -1
  99. package/.output/server/chunks/build/{dropdown-Dex8PXu6.mjs → dropdown-vhn1NPFs.mjs} +4 -4
  100. package/.output/server/chunks/build/{dropdown-Dex8PXu6.mjs.map → dropdown-vhn1NPFs.mjs.map} +1 -1
  101. package/.output/server/chunks/build/{input-number-BBlRoAJ7.mjs → input-number-Bd55elNN.mjs} +5 -5
  102. package/.output/server/chunks/build/{input-number-BBlRoAJ7.mjs.map → input-number-Bd55elNN.mjs.map} +1 -1
  103. package/.output/server/chunks/build/{input--KMeLYqZ.mjs → input-sf_BT6o6.mjs} +3 -3
  104. package/.output/server/chunks/build/{input--KMeLYqZ.mjs.map → input-sf_BT6o6.mjs.map} +1 -1
  105. package/.output/server/chunks/build/logs-Dyk0I2I9.mjs +1 -1
  106. package/.output/server/chunks/build/{menu-xN-SXb9Q.mjs → menu-WCrlpYVh.mjs} +3 -3
  107. package/.output/server/chunks/build/{menu-xN-SXb9Q.mjs.map → menu-WCrlpYVh.mjs.map} +1 -1
  108. package/.output/server/chunks/build/{modal-DrCOcjrl.mjs → modal-yvUquPj5.mjs} +4 -4
  109. package/.output/server/chunks/build/{modal-DrCOcjrl.mjs.map → modal-yvUquPj5.mjs.map} +1 -1
  110. package/.output/server/chunks/build/{monitor-KW8WLOJd.mjs → monitor-MIOvsyLa.mjs} +21 -21
  111. package/.output/server/chunks/build/{monitor-KW8WLOJd.mjs.map → monitor-MIOvsyLa.mjs.map} +1 -1
  112. package/.output/server/chunks/build/pages-DR2bzczM.mjs +1 -1
  113. package/.output/server/chunks/build/{plugins-B-ZNey0Z.mjs → plugins-DnOBIWGg.mjs} +7 -7
  114. package/.output/server/chunks/build/{plugins-B-ZNey0Z.mjs.map → plugins-DnOBIWGg.mjs.map} +1 -1
  115. package/.output/server/chunks/build/{popconfirm-C5H1Qoh3.mjs → popconfirm-CRaHcz5O.mjs} +4 -4
  116. package/.output/server/chunks/build/{popconfirm-C5H1Qoh3.mjs.map → popconfirm-CRaHcz5O.mjs.map} +1 -1
  117. package/.output/server/chunks/build/{useWorkshopApi-Bh5VUHWu.mjs → segmented-DPe9ZzLO.mjs} +7 -78
  118. package/.output/server/chunks/build/segmented-DPe9ZzLO.mjs.map +1 -0
  119. package/.output/server/chunks/build/{select-D7H2ysgT.mjs → select-D-CeE5vY.mjs} +3 -3
  120. package/.output/server/chunks/build/{select-D7H2ysgT.mjs.map → select-D-CeE5vY.mjs.map} +1 -1
  121. package/.output/server/chunks/build/{settings-Cr06lbRy.mjs → settings-DA8IkGLo.mjs} +11 -11
  122. package/.output/server/chunks/build/{settings-Cr06lbRy.mjs.map → settings-DA8IkGLo.mjs.map} +1 -1
  123. package/.output/server/chunks/build/{space-DCwIlnkI.mjs → space-CCBYAkXt.mjs} +2 -2
  124. package/.output/server/chunks/build/{space-DCwIlnkI.mjs.map → space-CCBYAkXt.mjs.map} +1 -1
  125. package/.output/server/chunks/build/{switch-VC0m9ede.mjs → switch-CelRXpcy.mjs} +3 -3
  126. package/.output/server/chunks/build/{switch-VC0m9ede.mjs.map → switch-CelRXpcy.mjs.map} +1 -1
  127. package/.output/server/chunks/build/{table-BksLg3Q_.mjs → table-Cswq-l2r.mjs} +10 -10
  128. package/.output/server/chunks/build/{table-BksLg3Q_.mjs.map → table-Cswq-l2r.mjs.map} +1 -1
  129. package/.output/server/chunks/build/{tabs-CzUfD3iX.mjs → tabs-BM3tAh_J.mjs} +5 -5
  130. package/.output/server/chunks/build/{tabs-CzUfD3iX.mjs.map → tabs-BM3tAh_J.mjs.map} +1 -1
  131. package/.output/server/chunks/build/{tag-oQI3VtqM.mjs → tag-NO9jEqKy.mjs} +4 -4
  132. package/.output/server/chunks/build/{tag-oQI3VtqM.mjs.map → tag-NO9jEqKy.mjs.map} +1 -1
  133. package/.output/server/chunks/build/{teams-QR3BBF7A.mjs → teams-BhSKBBBM.mjs} +15 -14
  134. package/.output/server/chunks/build/teams-BhSKBBBM.mjs.map +1 -0
  135. package/.output/server/chunks/build/{tokens-DFvr_TLj.mjs → tokens-D_eyxmcv.mjs} +16 -16
  136. package/.output/server/chunks/build/{tokens-DFvr_TLj.mjs.map → tokens-D_eyxmcv.mjs.map} +1 -1
  137. package/.output/server/chunks/build/town-BUqRobze.mjs +1 -1
  138. package/.output/server/chunks/build/{town-_4tEEEVW.mjs → town-DPtOPRRO.mjs} +4 -4
  139. package/.output/server/chunks/build/{town-_4tEEEVW.mjs.map → town-DPtOPRRO.mjs.map} +1 -1
  140. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs +42 -0
  141. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs.map +1 -0
  142. package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs +81 -0
  143. package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs.map +1 -0
  144. package/.output/server/chunks/build/useWorkshopWs-B3j5wIAK.mjs +1 -1
  145. package/.output/server/chunks/build/user-Dk-ytEUV.mjs +1 -1
  146. package/.output/server/chunks/build/{users-4FZ0yFUO.mjs → users-CmVvb1oq.mjs} +16 -16
  147. package/.output/server/chunks/build/{users-4FZ0yFUO.mjs.map → users-CmVvb1oq.mjs.map} +1 -1
  148. package/.output/server/chunks/build/{workshop-k0XZTFKg.mjs → workshop-iCzNRifn.mjs} +9 -9
  149. package/.output/server/chunks/build/{workshop-k0XZTFKg.mjs.map → workshop-iCzNRifn.mjs.map} +1 -1
  150. package/.output/server/chunks/build/workspaces-IfORCDJE.mjs +1 -1
  151. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  152. package/.output/server/chunks/routes/api/index.get.mjs +1 -1
  153. package/.output/server/chunks/routes/api/index.post.mjs +1 -1
  154. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  155. package/.output/server/chunks/routes/api/metrics.mjs +1 -1
  156. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
  157. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +1 -1
  158. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +1 -1
  159. package/.output/server/chunks/routes/api/system/config.get.mjs +1 -1
  160. package/.output/server/chunks/routes/api/system/index.get.mjs +3 -3
  161. package/.output/server/chunks/routes/api/system/index.get.mjs.map +1 -1
  162. package/.output/server/chunks/routes/api/system/index.patch.mjs +1 -1
  163. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
  164. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
  165. package/.output/server/chunks/routes/api/system/monitor.get.mjs +1 -1
  166. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
  167. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +1 -1
  168. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +1 -1
  169. package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
  170. package/.output/server/chunks/routes/api/users/_id_.put.mjs +1 -1
  171. package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
  172. package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
  173. package/.output/server/chunks/routes/api/users/login.post.mjs +1 -1
  174. package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
  175. package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
  176. package/.output/server/chunks/routes/api/users/register.post.mjs +1 -1
  177. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
  178. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
  179. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/_...path_.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +6 -14
  191. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
  192. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +39 -0
  193. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs.map +1 -0
  194. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +2 -2
  203. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +2 -2
  205. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/caller.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +2 -2
  208. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
  211. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
  212. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +2 -2
  213. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +2 -2
  226. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +1 -1
  228. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +1 -1
  229. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  230. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +1 -1
  231. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  232. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +1 -1
  233. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +1 -1
  234. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +2 -2
  235. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +1 -1
  236. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +2 -2
  237. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +9 -2
  238. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs.map +1 -1
  239. package/.output/server/chunks/routes/api/workshop/channels.get.mjs +1 -1
  240. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +2 -2
  241. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +2 -2
  242. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +2 -2
  243. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +2 -2
  244. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +6 -4
  245. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs.map +1 -1
  246. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +2 -2
  247. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +2 -2
  248. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +2 -2
  249. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +2 -2
  250. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +2 -2
  251. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +2 -2
  252. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +2 -2
  253. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +2 -2
  254. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +2 -2
  255. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +2 -2
  256. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +2 -2
  257. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +2 -2
  258. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +2 -2
  259. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +2 -2
  260. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +2 -2
  261. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +2 -2
  262. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +2 -2
  263. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -2
  264. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +2 -2
  265. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +2 -2
  266. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +2 -2
  267. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +2 -2
  268. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +2 -2
  269. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +2 -2
  270. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +2 -2
  271. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +2 -2
  272. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +2 -2
  273. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +2 -2
  274. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +2 -2
  275. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +2 -2
  276. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +2 -2
  277. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +2 -2
  278. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +2 -2
  279. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +2 -2
  280. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +2 -2
  281. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +2 -2
  282. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +2 -2
  283. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +2 -2
  284. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +2 -2
  285. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +2 -2
  286. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +2 -2
  287. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +2 -2
  288. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +2 -2
  289. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +2 -2
  290. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +2 -2
  291. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs +2 -2
  292. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +2 -2
  293. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +2 -2
  294. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +2 -2
  295. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +2 -2
  296. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +2 -2
  297. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +2 -2
  298. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  299. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  300. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +2 -2
  301. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +2 -2
  302. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
  303. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +247 -0
  304. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs.map +1 -0
  305. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +27 -0
  306. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs.map +1 -0
  307. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  308. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +19 -7
  309. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs.map +1 -1
  310. package/.output/server/chunks/routes/api/workshop/index.get.mjs +1 -1
  311. package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
  312. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +1 -1
  313. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  314. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +1 -1
  315. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
  316. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +2 -2
  317. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +2 -2
  318. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +2 -2
  319. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +2 -2
  320. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +2 -2
  321. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  322. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +2 -2
  323. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  324. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
  325. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
  326. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
  327. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +1 -1
  328. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +1 -1
  329. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +1 -1
  330. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +1 -1
  331. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  332. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  333. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +1 -1
  334. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +1 -1
  335. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  336. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  337. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +1 -1
  338. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
  339. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
  340. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +1 -1
  341. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
  342. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +1 -1
  343. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
  344. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +1 -1
  345. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +2 -2
  346. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +1 -1
  347. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +1 -1
  348. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +1 -1
  349. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +1 -1
  350. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +1 -1
  351. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +1 -1
  352. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +1 -1
  353. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +1 -1
  354. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -2
  355. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +1 -1
  356. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +1 -1
  357. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +1 -1
  358. package/.output/server/chunks/routes/renderer.mjs +1 -1
  359. package/.output/server/chunks/virtual/entry.mjs +123 -113
  360. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  361. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  362. package/.output/server/index.mjs +1 -1
  363. package/.output/server/package.json +1 -1
  364. package/app/components/AppHeader.vue +56 -2
  365. package/app/components/workshop/ChannelSessionList.vue +703 -593
  366. package/app/components/workshop/terminal/OmpTerminalPanel.vue +2 -1
  367. package/app/composables/workshop/useLocalTime.ts +16 -0
  368. package/app/composables/workshop/useSceneLayouts.ts +2 -1
  369. package/app/composables/workshop/useWorkshopApi.ts +249 -224
  370. package/app/pages/daq/[id].vue +7 -6
  371. package/app/pages/daq/index.vue +2 -2
  372. package/app/pages/dcw/[id].vue +3 -3
  373. package/app/pages/workshop/agents.vue +432 -382
  374. package/bin/aw.mjs +0 -0
  375. package/cli/aw.mjs +8 -1
  376. package/cli/commands/stop.mjs +7 -4
  377. package/cli/commands/tui.mjs +10 -1
  378. package/cli/core/registry.mjs +5 -3
  379. package/config.yml +134 -134
  380. package/docs/tui.md +1 -1
  381. package/i18n/locales/en.ts +5 -0
  382. package/i18n/locales/zh-CN.ts +5 -0
  383. package/package.json +148 -140
  384. package/scripts/_dbg-catalog-smoke.ts +20 -0
  385. package/scripts/_dbg-codex-probe.mjs +58 -0
  386. package/scripts/_dbg-dsh-probe.mjs +31 -0
  387. package/scripts/_dbg-interval-scenario.mjs +126 -0
  388. package/scripts/_dbg-line-spawn.ts +31 -0
  389. package/scripts/_dbg-live-engine-probe.mjs +80 -0
  390. package/scripts/_dbg-mcp-bridge-probe.mjs +147 -0
  391. package/scripts/_dbg-opencode-sse.mjs +101 -0
  392. package/scripts/_dbg-opencode-start.ts +57 -0
  393. package/scripts/_dbg-plugin-matrix.mjs +212 -0
  394. package/scripts/_dbg-protocol-matrix.mjs +425 -0
  395. package/scripts/_dbg-real-scenario-timeline.log +123 -0
  396. package/scripts/_dbg-registry-smoke.ts +14 -0
  397. package/scripts/_dbg-sim-keeper.mjs +100 -0
  398. package/scripts/_dbg-team-drill.mjs +173 -0
  399. package/scripts/dev-guard.mjs +11 -3
  400. package/scripts/dev-protocol-simulators.mjs +28 -1
  401. package/scripts/e2e-multi-harness.ts +374 -0
  402. package/scripts/e2e-multiharness-team.mjs +319 -0
  403. package/scripts/e2e-plc-scenario.mjs +292 -0
  404. package/scripts/e2e-real-scenario.mjs +452 -0
  405. package/scripts/migrate-local-time.mjs +123 -0
  406. package/scripts/start.mjs +30 -2
  407. package/server/api/system/settings/index.get.ts +3 -3
  408. package/server/api/workshop/agent-tools/invoke.post.ts +27 -41
  409. package/server/api/workshop/agent-tools/list.get.ts +25 -0
  410. package/server/api/workshop/channels/[id]/index.patch.ts +38 -30
  411. package/server/api/workshop/daq/[id]/samples.get.ts +6 -3
  412. package/server/api/workshop/harnesses/[id]/providers.get.ts +16 -0
  413. package/server/api/workshop/harnesses.get.ts +12 -0
  414. package/server/api/workshop/hitl/respond.post.ts +87 -67
  415. package/server/api/workshop/ws.ts +13 -0
  416. package/server/data/daqs.json +1366 -16
  417. package/server/data/dcw-lines.json +266 -0
  418. package/server/data/dcw-products.json +203 -0
  419. package/server/data/dcw-recipes.json +784 -0
  420. package/server/data/dcw-rollback.json +1144 -1
  421. package/server/data/dcw-runs.json +983 -791
  422. package/server/data/dcw-writes.json +1080 -0
  423. package/server/data/dcws.json +3278 -203
  424. package/server/data/line-runs.json +52 -2
  425. package/server/harness/aw-mcp-bridge.mjs +153 -0
  426. package/server/plugins/00-local-time.ts +10 -0
  427. package/server/plugins/aw-plugins.ts +3 -0
  428. package/server/plugins/backup.ts +116 -97
  429. package/server/plugins/dev-stability-guard.ts +24 -15
  430. package/server/plugins/retention.ts +1 -0
  431. package/server/plugins/security.ts +24 -3
  432. package/server/plugins/workshop.ts +156 -153
  433. package/server/repositories/user.repository.ts +414 -391
  434. package/server/services/system-config.ts +30 -6
  435. package/server/services/workshop/.mimosa/hook-state/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f.json +1 -0
  436. package/server/services/workshop/.mimosa/hook-status/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f-e6b75bbfe6.json +14 -0
  437. package/server/services/workshop/agents/adapters/line-spawn.ts +108 -0
  438. package/server/services/workshop/agents/adapters/stdio-jsonrpc.ts +316 -0
  439. package/server/services/workshop/agents/agent-interface.ts +17 -0
  440. package/server/services/workshop/agents/codex-agent.ts +822 -0
  441. package/server/services/workshop/agents/dsh-agent.ts +670 -0
  442. package/server/services/workshop/agents/factory.ts +4 -16
  443. package/server/services/workshop/agents/harness-env.ts +54 -0
  444. package/server/services/workshop/agents/harness-models.ts +270 -0
  445. package/server/services/workshop/agents/host-tool-bridge.ts +592 -0
  446. package/server/services/workshop/agents/industrial-tools.ts +5 -1
  447. package/server/services/workshop/agents/node-bindings.repo.ts +4 -5
  448. package/server/services/workshop/agents/omp-agent.ts +1178 -1957
  449. package/server/services/workshop/agents/opencode-agent.ts +987 -0
  450. package/server/services/workshop/agents/prompt-builder.ts +393 -0
  451. package/server/services/workshop/agents/registry.ts +125 -0
  452. package/server/services/workshop/assets/character-asset.repo.ts +3 -5
  453. package/server/services/workshop/assets/device-twin.repo.ts +3 -5
  454. package/server/services/workshop/daq/daq-controller.ts +8 -4
  455. package/server/services/workshop/daq/daq-node.repo.ts +3 -5
  456. package/server/services/workshop/daq/daq-node.ts +2 -2
  457. package/server/services/workshop/daq/daq-templates.ts +3 -5
  458. package/server/services/workshop/daq/drivers.ts +41 -12
  459. package/server/services/workshop/daq/storage/sqlite.adapter.ts +313 -309
  460. package/server/services/workshop/db/backup-registry.ts +33 -0
  461. package/server/services/workshop/db/channel.repo.ts +104 -101
  462. package/server/services/workshop/db/database.ts +956 -949
  463. package/server/services/workshop/dcw/dcw-controller.ts +3 -1
  464. package/server/services/workshop/dcw/dcw-line.repo.ts +4 -11
  465. package/server/services/workshop/dcw/dcw-node.repo.ts +3 -5
  466. package/server/services/workshop/dcw/dcw-node.ts +13 -1
  467. package/server/services/workshop/dcw/dcw-product.repo.ts +3 -4
  468. package/server/services/workshop/dcw/dcw-recipe.repo.ts +3 -19
  469. package/server/services/workshop/dcw/dcw-templates.ts +3 -5
  470. package/server/services/workshop/dcw/drivers.ts +37 -13
  471. package/server/services/workshop/dcw/line-run.ts +3 -5
  472. package/server/services/workshop/dcw/recipe-rollback.repo.ts +4 -10
  473. package/server/services/workshop/json-store.mjs +72 -0
  474. package/server/services/workshop/plugins/host.mjs +2 -1
  475. package/server/services/workshop/runtime/agent-runtime.ts +44 -0
  476. package/server/services/workshop/runtime/manager.ts +2953 -2868
  477. package/server/services/workshop/scene/scene-layout.repo.ts +4 -11
  478. package/server/services/workshop/settings.ts +7 -0
  479. package/shared/config/schema.json +5 -0
  480. package/shared/config/single-instance.mjs +5 -1
  481. package/shared/local-time.mjs +36 -0
  482. package/shared/workshop-protocol.ts +11 -5
  483. package/tui/aw-tui.mjs +28 -10
  484. package/tui/components/hitl-card.mjs +47 -36
  485. package/tui/lib/ws.mjs +2 -1
  486. package/.output/public/_nuxt/9X0fVBD7.js +0 -57
  487. package/.output/public/_nuxt/B6M2WJWm2.js +0 -1
  488. package/.output/public/_nuxt/B9Yie5HN.js +0 -2
  489. package/.output/public/_nuxt/BF9XPEuw.js +0 -1
  490. package/.output/public/_nuxt/BbQornXa.js +0 -1
  491. package/.output/public/_nuxt/Bxgaym6j.js +0 -1
  492. package/.output/public/_nuxt/Bxh5nf8j.js +0 -1
  493. package/.output/public/_nuxt/CXLI50Sq.js +0 -1
  494. package/.output/public/_nuxt/CdfAP_IH2.js +0 -1
  495. package/.output/public/_nuxt/Ce1zyNYu.js +0 -1
  496. package/.output/public/_nuxt/D-Ne4C9a.js +0 -1
  497. package/.output/public/_nuxt/DEHNjlTq2.js +0 -1
  498. package/.output/public/_nuxt/DFnGFEav.js +0 -18
  499. package/.output/public/_nuxt/DYWgGHNo.js +0 -7
  500. package/.output/public/_nuxt/OmpTerminalPanel.Bc9GjNU5.css +0 -1
  501. package/.output/public/_nuxt/W1E3-5ML.js +0 -14
  502. package/.output/public/_nuxt/XVB9_zwP.js +0 -1
  503. package/.output/public/_nuxt/Xaf_HIR3.js +0 -1
  504. package/.output/public/_nuxt/_id_.BeqSLvl_.css +0 -1
  505. package/.output/public/_nuxt/_id_.DN3U6EF9.css +0 -1
  506. package/.output/public/_nuxt/agents.BJwgTLFZ.css +0 -1
  507. package/.output/public/_nuxt/builds/meta/55c10854-ee0e-4be4-924b-a1b0e100fe11.json +0 -1
  508. package/.output/public/_nuxt/daq.BXsnevQv.css +0 -1
  509. package/.output/public/_nuxt/yIKY_V1P.js +0 -1
  510. package/.output/server/chunks/build/OmpTerminalPanel-B_SYhmgb.mjs.map +0 -1
  511. package/.output/server/chunks/build/_id_-CWLFGZjV.mjs.map +0 -1
  512. package/.output/server/chunks/build/agents-D4l1icvn.mjs.map +0 -1
  513. package/.output/server/chunks/build/channel-templates-DqjtC-R0.mjs.map +0 -1
  514. package/.output/server/chunks/build/interval-WlxgjTzO.mjs +0 -9
  515. package/.output/server/chunks/build/interval-WlxgjTzO.mjs.map +0 -1
  516. package/.output/server/chunks/build/teams-QR3BBF7A.mjs.map +0 -1
  517. package/.output/server/chunks/build/useWorkshopApi-Bh5VUHWu.mjs.map +0 -1
@@ -1,309 +1,313 @@
1
- /**
2
- * SqliteTimeSeriesAdapter —— TsdbPort 的开发仿真实现。
3
- *
4
- * 无 Timescale 实例时的缺省后端:同一契约落在本地 SQLite(data/daq-timeseries.sqlite),
5
- * 结构与时序语义对齐(ts_ms 主键 + 节点索引、bucketMs 降采样用整除分桶聚合)。
6
- * 生产环境配置 DAQ_TSDB_URL 即切换 Timescale,业务代码零改动。
7
- */
8
- import { createLogger } from '../../logger'
9
- import { join } from 'node:path'
10
- import { DatabaseSync } from 'node:sqlite'
11
- import { ensureDataDir } from '@/shared/config/home.mjs'
12
- import type { DaqQueryOpts, DaqSampleRow, TsdbPoint, TsdbPort } from './tsdb-port'
13
- import { daqRuntimeSettings } from '../../settings'
14
-
15
- const log = createLogger('daq.tsdb.sqlite')
16
-
17
- const DB_PATH = join(ensureDataDir(), 'daq-timeseries.sqlite')
18
-
19
- export class SqliteTimeSeriesAdapter implements TsdbPort {
20
- readonly backend = 'sqlite-emulated'
21
- private db: DatabaseSync | null = null
22
- /** 启动清理水位(daq.tsRetentionH;env DAQ_TS_RETENTION_H 兼容) */
23
- private readonly retentionH = daqRuntimeSettings().tsRetentionH
24
- private retentionTimer: NodeJS.Timeout | null = null
25
-
26
- async init(): Promise<void> {
27
- this.db = new DatabaseSync(DB_PATH)
28
- this.db.exec('PRAGMA journal_mode = WAL')
29
- // WAL + NORMAL:批写单事务一次 fsync,兼顾持久性与事件循环停顿
30
- this.db.exec('PRAGMA synchronous = NORMAL')
31
- this.db.exec(`
32
- CREATE TABLE IF NOT EXISTS daq_samples (
33
- node_id TEXT NOT NULL,
34
- ts_ms INTEGER NOT NULL,
35
- value REAL NOT NULL,
36
- state TEXT NOT NULL DEFAULT 'ok',
37
- line_id TEXT,
38
- product_id TEXT,
39
- recipe_id TEXT,
40
- run_id TEXT,
41
- PRIMARY KEY (node_id, ts_ms)
42
- );
43
- CREATE INDEX IF NOT EXISTS idx_daq_node_ts ON daq_samples (node_id, ts_ms DESC);
44
- `)
45
- // 存量库迁移:先补打标列(幂等),再建依赖列的索引
46
- const cols = new Set((this.db.prepare('PRAGMA table_info(daq_samples)').all() as Array<{ name: string }>).map(c => c.name))
47
- for (const [col, ddl] of [['line_id', 'ALTER TABLE daq_samples ADD COLUMN line_id TEXT'], ['product_id', 'ALTER TABLE daq_samples ADD COLUMN product_id TEXT'], ['recipe_id', 'ALTER TABLE daq_samples ADD COLUMN recipe_id TEXT'], ['run_id', 'ALTER TABLE daq_samples ADD COLUMN run_id TEXT']] as const) {
48
- if (!cols.has(col)) this.db.exec(ddl)
49
- }
50
- this.db.exec(`
51
- CREATE INDEX IF NOT EXISTS idx_daq_tag ON daq_samples (product_id, recipe_id, ts_ms DESC);
52
- CREATE INDEX IF NOT EXISTS idx_daq_run ON daq_samples (run_id, ts_ms DESC);
53
- `)
54
- // 帧表(v2:向量/图像;meta/metrics JSON 序列化 TEXT,与 Timescale 契约对齐)
55
- this.db.exec(`
56
- CREATE TABLE IF NOT EXISTS daq_frames (
57
- node_id TEXT NOT NULL,
58
- ts_ms INTEGER NOT NULL,
59
- kind TEXT NOT NULL,
60
- template_key TEXT,
61
- device_binding_id TEXT,
62
- line_id TEXT, product_id TEXT, recipe_id TEXT, run_id TEXT,
63
- points INTEGER NOT NULL DEFAULT 0,
64
- meta TEXT NOT NULL DEFAULT '{}',
65
- metrics TEXT NOT NULL DEFAULT '{}',
66
- PRIMARY KEY (node_id, ts_ms)
67
- )
68
- `)
69
- this.db.exec('CREATE INDEX IF NOT EXISTS idx_daq_frames_node_ts ON daq_frames (node_id, ts_ms DESC)')
70
- // 保留窗口:启动清一次 + 后台周期任务(30min,防长会话磁盘无限涨)
71
- this.sweepRetention()
72
- this.sweepFrameRetention()
73
- if (!this.retentionTimer) {
74
- this.retentionTimer = setInterval(() => {
75
- this.sweepRetention()
76
- this.sweepFrameRetention()
77
- }, 30 * 60_000)
78
- this.retentionTimer.unref?.()
79
- }
80
- }
81
-
82
- /** 保留期清理:分批 DELETE(单批 5000 行,避免长事务锁库) */
83
- private sweepRetention(): void {
84
- if (!this.db) return
85
- const cutoff = Date.now() - this.retentionH * 3600_000
86
- try {
87
- let removed = 0
88
- for (;;) {
89
- const r = this.db.prepare(
90
- 'DELETE FROM daq_samples WHERE rowid IN (SELECT rowid FROM daq_samples WHERE ts_ms < ? LIMIT 5000)',
91
- ).run(cutoff)
92
- removed += Number(r.changes)
93
- if (Number(r.changes) < 5000) break
94
- }
95
- if (removed > 0) log.info(`[daq-tsdb] 保留期清理 ${removed} 行(>${this.retentionH}h)`)
96
- }
97
- catch (err) {
98
- log.error('[daq-tsdb] 保留期清理失败:', err instanceof Error ? err.message : err)
99
- }
100
- }
101
-
102
- async writeSamples(rows: DaqSampleRow[]): Promise<void> {
103
- if (!this.db || rows.length === 0) return
104
- // 批内单事务:一次 fsync 落整批(逐行 run 会每行一次 WAL fsync,写放大)
105
- const ins = this.db.prepare(
106
- 'INSERT OR IGNORE INTO daq_samples (node_id, ts_ms, value, state, line_id, product_id, recipe_id, run_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
107
- )
108
- this.db.exec('BEGIN')
109
- try {
110
- for (const r of rows) ins.run(r.nodeId, r.tsMs, r.value, r.state, r.lineId ?? null, r.productId ?? null, r.recipeId ?? null, r.runId ?? null)
111
- this.db.exec('COMMIT')
112
- }
113
- catch (err) {
114
- try {
115
- this.db.exec('ROLLBACK')
116
- }
117
- catch { /* 事务已终结 */ }
118
- throw err
119
- }
120
- }
121
-
122
- async query(nodeId: string, opts: DaqQueryOpts): Promise<TsdbPoint[]> {
123
- if (!this.db) return []
124
- const limit = Math.min(opts.limit ?? 500, 5000)
125
- const from = opts.fromMs ?? 0
126
- const to = opts.toMs ?? Date.now()
127
- if (opts.bucketMs && opts.bucketMs >= 100) {
128
- const bucket = opts.bucketMs
129
- const rows = this.db.prepare(`
130
- SELECT (ts_ms / :b) * :b AS b_at,
131
- AVG(value) AS avg, MIN(value) AS min, MAX(value) AS max, COUNT(*) AS cnt
132
- FROM daq_samples
133
- WHERE node_id = :id AND ts_ms >= :from AND ts_ms <= :to
134
- GROUP BY b_at ORDER BY b_at DESC LIMIT :lim
135
- `).all({ ':id': nodeId, ':from': from, ':to': to, ':b': bucket, ':lim': limit }) as Array<{ b_at: number, avg: number, min: number, max: number, cnt: number }>
136
- return rows.map(r => ({ at: Number(r.b_at), avg: r.avg, min: r.min, max: r.max, cnt: Number(r.cnt) }))
137
- }
138
- const rows = this.db.prepare(`
139
- SELECT ts_ms, value, state FROM daq_samples
140
- WHERE node_id = :id AND ts_ms >= :from AND ts_ms <= :to
141
- ORDER BY ts_ms DESC LIMIT :lim
142
- `).all({ ':id': nodeId, ':from': from, ':to': to, ':lim': limit }) as Array<{ ts_ms: number, value: number, state: string }>
143
- return rows.map(r => ({ at: Number(r.ts_ms), value: Number(r.value), state: String(r.state) }))
144
- }
145
-
146
- async queryTagged(q: import('./tsdb-port').TsdbTagQuery): Promise<Map<string, import('./tsdb-port').TsdbPoint[]>> {
147
- const out = new Map<string, import('./tsdb-port').TsdbPoint[]>()
148
- if (!this.db) return out
149
- const where: string[] = []
150
- const params: Array<string | number> = []
151
- if (q.lineId) {
152
- where.push('line_id = ?')
153
- params.push(q.lineId)
154
- }
155
- if (q.productId) {
156
- where.push('product_id = ?')
157
- params.push(q.productId)
158
- }
159
- if (q.recipeId) {
160
- where.push('recipe_id = ?')
161
- params.push(q.recipeId)
162
- }
163
- if (q.runId) {
164
- where.push('run_id = ?')
165
- params.push(q.runId)
166
- }
167
- if (q.nodeIds?.length) {
168
- where.push(`node_id IN (${q.nodeIds.map(() => '?').join(',')})`)
169
- params.push(...q.nodeIds)
170
- }
171
- where.push('ts_ms >= ?')
172
- params.push(q.fromMs ?? 0)
173
- where.push('ts_ms <= ?')
174
- params.push(q.toMs ?? Date.now())
175
- const limit = Math.min(q.limit ?? 2000, 10_000)
176
- if (q.bucketMs && q.bucketMs >= 100) {
177
- const rows2 = (this.db.prepare(`
178
- SELECT node_id, (ts_ms / ?) * ? AS b_at, AVG(value) AS avg, MIN(value) AS min, MAX(value) AS max, COUNT(*) AS cnt
179
- FROM daq_samples WHERE ${where.join(' AND ')}
180
- GROUP BY node_id, b_at ORDER BY b_at ASC LIMIT ?
181
- `).all(q.bucketMs, q.bucketMs, ...params, limit)) as Array<{ node_id: string, b_at: number, avg: number, min: number, max: number, cnt: number }>
182
- for (const r of rows2) {
183
- const list = out.get(r.node_id) ?? []
184
- list.push({ at: Number(r.b_at), avg: r.avg, min: r.min, max: r.max, cnt: Number(r.cnt) })
185
- out.set(r.node_id, list)
186
- }
187
- return out
188
- }
189
- const rows = (this.db.prepare(`
190
- SELECT node_id, ts_ms, value FROM daq_samples WHERE ${where.join(' AND ')}
191
- ORDER BY ts_ms ASC LIMIT ?
192
- `).all(...params, limit)) as Array<{ node_id: string, ts_ms: number, value: number }>
193
- for (const r of rows) {
194
- const list = out.get(r.node_id) ?? []
195
- list.push({ at: Number(r.ts_ms), value: r.value })
196
- out.set(r.node_id, list)
197
- }
198
- return out
199
- }
200
-
201
- async latest(): Promise<Map<string, DaqSampleRow>> {
202
- const out = new Map<string, DaqSampleRow>()
203
- if (!this.db) return out
204
- // SQLite 裸列保证:GROUP BY + MAX() 时裸列取自 max 所在行(命中 idx_daq_node_ts,免相关子查询)
205
- const rows = this.db.prepare(`
206
- SELECT node_id, MAX(ts_ms) AS ts_ms, value, state FROM daq_samples GROUP BY node_id
207
- `).all() as Array<{ node_id: string, ts_ms: number, value: number, state: string }>
208
- for (const r of rows) {
209
- out.set(r.node_id, { nodeId: r.node_id, tsMs: Number(r.ts_ms), value: Number(r.value), state: String(r.state) })
210
- }
211
- return out
212
- }
213
-
214
- // ===== 帧(daq_frames;与 Timescale 同契约)=====
215
-
216
- async writeFrames(rows: import('./tsdb-port').DaqFrameRow[]): Promise<void> {
217
- if (!this.db || rows.length === 0) return
218
- const ins = this.db.prepare(
219
- 'INSERT OR IGNORE INTO daq_frames (node_id, ts_ms, kind, template_key, device_binding_id, line_id, product_id, recipe_id, run_id, points, meta, metrics) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
220
- )
221
- this.db.exec('BEGIN')
222
- try {
223
- for (const r of rows) {
224
- ins.run(r.nodeId, r.tsMs, r.kind, r.templateKey ?? null, r.deviceBindingId ?? null, r.lineId ?? null, r.productId ?? null, r.recipeId ?? null, r.runId ?? null, r.points, JSON.stringify(r.meta ?? {}), JSON.stringify(r.metrics ?? {}))
225
- }
226
- this.db.exec('COMMIT')
227
- }
228
- catch (err) {
229
- try {
230
- this.db.exec('ROLLBACK')
231
- }
232
- catch { /* 事务已终结 */ }
233
- throw err
234
- }
235
- }
236
-
237
- async queryFrames(nodeId: string, opts: import('./tsdb-port').DaqFrameQueryOpts): Promise<import('./tsdb-port').DaqFrameRecord[]> {
238
- if (!this.db) return []
239
- const limit = Math.min(opts.limit ?? 100, 1000)
240
- const rows = this.db.prepare(`
241
- SELECT ts_ms, kind, meta, metrics, device_binding_id, line_id, product_id, recipe_id, run_id
242
- FROM daq_frames
243
- WHERE node_id = :id AND (:kind IS NULL OR kind = :kind) AND ts_ms >= :from AND ts_ms <= :to
244
- ORDER BY ts_ms DESC LIMIT :lim
245
- `).all({
246
- ':id': nodeId,
247
- ':kind': opts.kind ?? null,
248
- ':from': opts.fromMs ?? 0,
249
- ':to': opts.toMs ?? Date.now(),
250
- ':lim': limit,
251
- }) as Array<{ ts_ms: number, kind: string, meta: string, metrics: string, device_binding_id: string | null, line_id: string | null, product_id: string | null, recipe_id: string | null, run_id: string | null }>
252
- return rows.map(r => ({
253
- at: Number(r.ts_ms),
254
- kind: String(r.kind) as 'vector' | 'image',
255
- points: r.kind === 'vector' ? pointsFromMeta(asObject(r.meta)) : undefined,
256
- metrics: asObject(r.metrics) as Record<string, number>,
257
- meta: asObject(r.meta),
258
- deviceBindingId: r.device_binding_id,
259
- lineId: r.line_id,
260
- productId: r.product_id,
261
- recipeId: r.recipe_id,
262
- runId: r.run_id,
263
- }))
264
- }
265
-
266
- /** 帧保留期清理(与样本同拍;daq.frameRetentionH,env DAQ_FRAME_RETENTION_H 兼容) */
267
- private sweepFrameRetention(): void {
268
- if (!this.db) return
269
- const cutoff = Date.now() - daqRuntimeSettings().frameRetentionH * 3600_000
270
- try {
271
- this.db.prepare('DELETE FROM daq_frames WHERE ts_ms < ?').run(cutoff)
272
- }
273
- catch (err) {
274
- log.error('[daq-tsdb] 帧保留期清理失败:', err instanceof Error ? err.message : err)
275
- }
276
- }
277
-
278
- close(): Promise<void> | void {
279
- this.sweepRetentionTimerStop()
280
- this.db?.close()
281
- this.db = null
282
- }
283
-
284
- private sweepRetentionTimerStop(): void {
285
- if (this.retentionTimer) {
286
- clearInterval(this.retentionTimer)
287
- this.retentionTimer = null
288
- }
289
- }
290
- }
291
-
292
- /** 向量点列从 meta JSON 还原(非数组/越界防御) */
293
- function pointsFromMeta(meta: Record<string, unknown>): number[] | undefined {
294
- const p = meta.points
295
- if (!Array.isArray(p) || p.length === 0 || p.length > 4096) return undefined
296
- return p.every(x => Number.isFinite(Number(x))) ? p.map(Number) : undefined
297
- }
298
-
299
- function asObject(v: unknown): Record<string, unknown> {
300
- if (typeof v === 'string') {
301
- try {
302
- return JSON.parse(v) as Record<string, unknown>
303
- }
304
- catch {
305
- return {}
306
- }
307
- }
308
- return (v && typeof v === 'object' ? v : {}) as Record<string, unknown>
309
- }
1
+ /**
2
+ * SqliteTimeSeriesAdapter —— TsdbPort 的开发仿真实现。
3
+ *
4
+ * 无 Timescale 实例时的缺省后端:同一契约落在本地 SQLite(data/daq-timeseries.sqlite),
5
+ * 结构与时序语义对齐(ts_ms 主键 + 节点索引、bucketMs 降采样用整除分桶聚合)。
6
+ * 生产环境配置 DAQ_TSDB_URL 即切换 Timescale,业务代码零改动。
7
+ */
8
+ import { createLogger } from '../../logger'
9
+ import { backupRegistry } from '../../db/backup-registry'
10
+ import { join } from 'node:path'
11
+ import { DatabaseSync } from 'node:sqlite'
12
+ import { ensureDataDir } from '@/shared/config/home.mjs'
13
+ import type { DaqQueryOpts, DaqSampleRow, TsdbPoint, TsdbPort } from './tsdb-port'
14
+ import { daqRuntimeSettings } from '../../settings'
15
+
16
+ const log = createLogger('daq.tsdb.sqlite')
17
+
18
+ const DB_PATH = join(ensureDataDir(), 'daq-timeseries.sqlite')
19
+
20
+ export class SqliteTimeSeriesAdapter implements TsdbPort {
21
+ readonly backend = 'sqlite-emulated'
22
+ private db: DatabaseSync | null = null
23
+ /** 启动清理水位(daq.tsRetentionH;env DAQ_TS_RETENTION_H 兼容) */
24
+ private readonly retentionH = daqRuntimeSettings().tsRetentionH
25
+ private retentionTimer: NodeJS.Timeout | null = null
26
+
27
+ async init(): Promise<void> {
28
+ this.db = new DatabaseSync(DB_PATH)
29
+ // 主连接登记(备份 serialize 用)
30
+ backupRegistry.register(DB_PATH, this.db)
31
+ this.db.exec('PRAGMA journal_mode = WAL')
32
+ this.db.exec('PRAGMA busy_timeout = 5000')
33
+ // WAL + NORMAL:批写单事务一次 fsync,兼顾持久性与事件循环停顿
34
+ this.db.exec('PRAGMA synchronous = NORMAL')
35
+ this.db.exec(`
36
+ CREATE TABLE IF NOT EXISTS daq_samples (
37
+ node_id TEXT NOT NULL,
38
+ ts_ms INTEGER NOT NULL,
39
+ value REAL NOT NULL,
40
+ state TEXT NOT NULL DEFAULT 'ok',
41
+ line_id TEXT,
42
+ product_id TEXT,
43
+ recipe_id TEXT,
44
+ run_id TEXT,
45
+ PRIMARY KEY (node_id, ts_ms)
46
+ );
47
+ CREATE INDEX IF NOT EXISTS idx_daq_node_ts ON daq_samples (node_id, ts_ms DESC);
48
+ `)
49
+ // 存量库迁移:先补打标列(幂等),再建依赖列的索引
50
+ const cols = new Set((this.db.prepare('PRAGMA table_info(daq_samples)').all() as Array<{ name: string }>).map(c => c.name))
51
+ for (const [col, ddl] of [['line_id', 'ALTER TABLE daq_samples ADD COLUMN line_id TEXT'], ['product_id', 'ALTER TABLE daq_samples ADD COLUMN product_id TEXT'], ['recipe_id', 'ALTER TABLE daq_samples ADD COLUMN recipe_id TEXT'], ['run_id', 'ALTER TABLE daq_samples ADD COLUMN run_id TEXT']] as const) {
52
+ if (!cols.has(col)) this.db.exec(ddl)
53
+ }
54
+ this.db.exec(`
55
+ CREATE INDEX IF NOT EXISTS idx_daq_tag ON daq_samples (product_id, recipe_id, ts_ms DESC);
56
+ CREATE INDEX IF NOT EXISTS idx_daq_run ON daq_samples (run_id, ts_ms DESC);
57
+ `)
58
+ // 帧表(v2:向量/图像;meta/metrics JSON 序列化 TEXT,与 Timescale 契约对齐)
59
+ this.db.exec(`
60
+ CREATE TABLE IF NOT EXISTS daq_frames (
61
+ node_id TEXT NOT NULL,
62
+ ts_ms INTEGER NOT NULL,
63
+ kind TEXT NOT NULL,
64
+ template_key TEXT,
65
+ device_binding_id TEXT,
66
+ line_id TEXT, product_id TEXT, recipe_id TEXT, run_id TEXT,
67
+ points INTEGER NOT NULL DEFAULT 0,
68
+ meta TEXT NOT NULL DEFAULT '{}',
69
+ metrics TEXT NOT NULL DEFAULT '{}',
70
+ PRIMARY KEY (node_id, ts_ms)
71
+ )
72
+ `)
73
+ this.db.exec('CREATE INDEX IF NOT EXISTS idx_daq_frames_node_ts ON daq_frames (node_id, ts_ms DESC)')
74
+ // 保留窗口:启动清一次 + 后台周期任务(30min,防长会话磁盘无限涨)
75
+ this.sweepRetention()
76
+ this.sweepFrameRetention()
77
+ if (!this.retentionTimer) {
78
+ this.retentionTimer = setInterval(() => {
79
+ this.sweepRetention()
80
+ this.sweepFrameRetention()
81
+ }, 30 * 60_000)
82
+ this.retentionTimer.unref?.()
83
+ }
84
+ }
85
+
86
+ /** 保留期清理:分批 DELETE(单批 5000 行,避免长事务锁库) */
87
+ private sweepRetention(): void {
88
+ if (!this.db) return
89
+ const cutoff = Date.now() - this.retentionH * 3600_000
90
+ try {
91
+ let removed = 0
92
+ for (;;) {
93
+ const r = this.db.prepare(
94
+ 'DELETE FROM daq_samples WHERE rowid IN (SELECT rowid FROM daq_samples WHERE ts_ms < ? LIMIT 5000)',
95
+ ).run(cutoff)
96
+ removed += Number(r.changes)
97
+ if (Number(r.changes) < 5000) break
98
+ }
99
+ if (removed > 0) log.info(`[daq-tsdb] 保留期清理 ${removed} 行(>${this.retentionH}h)`)
100
+ }
101
+ catch (err) {
102
+ log.error('[daq-tsdb] 保留期清理失败:', err instanceof Error ? err.message : err)
103
+ }
104
+ }
105
+
106
+ async writeSamples(rows: DaqSampleRow[]): Promise<void> {
107
+ if (!this.db || rows.length === 0) return
108
+ // 批内单事务:一次 fsync 落整批(逐行 run 会每行一次 WAL fsync,写放大)
109
+ const ins = this.db.prepare(
110
+ 'INSERT OR IGNORE INTO daq_samples (node_id, ts_ms, value, state, line_id, product_id, recipe_id, run_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
111
+ )
112
+ this.db.exec('BEGIN')
113
+ try {
114
+ for (const r of rows) ins.run(r.nodeId, r.tsMs, r.value, r.state, r.lineId ?? null, r.productId ?? null, r.recipeId ?? null, r.runId ?? null)
115
+ this.db.exec('COMMIT')
116
+ }
117
+ catch (err) {
118
+ try {
119
+ this.db.exec('ROLLBACK')
120
+ }
121
+ catch { /* 事务已终结 */ }
122
+ throw err
123
+ }
124
+ }
125
+
126
+ async query(nodeId: string, opts: DaqQueryOpts): Promise<TsdbPoint[]> {
127
+ if (!this.db) return []
128
+ const limit = Math.min(opts.limit ?? 500, 5000)
129
+ const from = opts.fromMs ?? 0
130
+ const to = opts.toMs ?? Date.now()
131
+ if (opts.bucketMs && opts.bucketMs >= 100) {
132
+ const bucket = opts.bucketMs
133
+ const rows = this.db.prepare(`
134
+ SELECT (ts_ms / :b) * :b AS b_at,
135
+ AVG(value) AS avg, MIN(value) AS min, MAX(value) AS max, COUNT(*) AS cnt
136
+ FROM daq_samples
137
+ WHERE node_id = :id AND ts_ms >= :from AND ts_ms <= :to
138
+ GROUP BY b_at ORDER BY b_at DESC LIMIT :lim
139
+ `).all({ ':id': nodeId, ':from': from, ':to': to, ':b': bucket, ':lim': limit }) as Array<{ b_at: number, avg: number, min: number, max: number, cnt: number }>
140
+ return rows.map(r => ({ at: Number(r.b_at), avg: r.avg, min: r.min, max: r.max, cnt: Number(r.cnt) }))
141
+ }
142
+ const rows = this.db.prepare(`
143
+ SELECT ts_ms, value, state FROM daq_samples
144
+ WHERE node_id = :id AND ts_ms >= :from AND ts_ms <= :to
145
+ ORDER BY ts_ms DESC LIMIT :lim
146
+ `).all({ ':id': nodeId, ':from': from, ':to': to, ':lim': limit }) as Array<{ ts_ms: number, value: number, state: string }>
147
+ return rows.map(r => ({ at: Number(r.ts_ms), value: Number(r.value), state: String(r.state) }))
148
+ }
149
+
150
+ async queryTagged(q: import('./tsdb-port').TsdbTagQuery): Promise<Map<string, import('./tsdb-port').TsdbPoint[]>> {
151
+ const out = new Map<string, import('./tsdb-port').TsdbPoint[]>()
152
+ if (!this.db) return out
153
+ const where: string[] = []
154
+ const params: Array<string | number> = []
155
+ if (q.lineId) {
156
+ where.push('line_id = ?')
157
+ params.push(q.lineId)
158
+ }
159
+ if (q.productId) {
160
+ where.push('product_id = ?')
161
+ params.push(q.productId)
162
+ }
163
+ if (q.recipeId) {
164
+ where.push('recipe_id = ?')
165
+ params.push(q.recipeId)
166
+ }
167
+ if (q.runId) {
168
+ where.push('run_id = ?')
169
+ params.push(q.runId)
170
+ }
171
+ if (q.nodeIds?.length) {
172
+ where.push(`node_id IN (${q.nodeIds.map(() => '?').join(',')})`)
173
+ params.push(...q.nodeIds)
174
+ }
175
+ where.push('ts_ms >= ?')
176
+ params.push(q.fromMs ?? 0)
177
+ where.push('ts_ms <= ?')
178
+ params.push(q.toMs ?? Date.now())
179
+ const limit = Math.min(q.limit ?? 2000, 10_000)
180
+ if (q.bucketMs && q.bucketMs >= 100) {
181
+ const rows2 = (this.db.prepare(`
182
+ SELECT node_id, (ts_ms / ?) * ? AS b_at, AVG(value) AS avg, MIN(value) AS min, MAX(value) AS max, COUNT(*) AS cnt
183
+ FROM daq_samples WHERE ${where.join(' AND ')}
184
+ GROUP BY node_id, b_at ORDER BY b_at ASC LIMIT ?
185
+ `).all(q.bucketMs, q.bucketMs, ...params, limit)) as Array<{ node_id: string, b_at: number, avg: number, min: number, max: number, cnt: number }>
186
+ for (const r of rows2) {
187
+ const list = out.get(r.node_id) ?? []
188
+ list.push({ at: Number(r.b_at), avg: r.avg, min: r.min, max: r.max, cnt: Number(r.cnt) })
189
+ out.set(r.node_id, list)
190
+ }
191
+ return out
192
+ }
193
+ const rows = (this.db.prepare(`
194
+ SELECT node_id, ts_ms, value FROM daq_samples WHERE ${where.join(' AND ')}
195
+ ORDER BY ts_ms ASC LIMIT ?
196
+ `).all(...params, limit)) as Array<{ node_id: string, ts_ms: number, value: number }>
197
+ for (const r of rows) {
198
+ const list = out.get(r.node_id) ?? []
199
+ list.push({ at: Number(r.ts_ms), value: r.value })
200
+ out.set(r.node_id, list)
201
+ }
202
+ return out
203
+ }
204
+
205
+ async latest(): Promise<Map<string, DaqSampleRow>> {
206
+ const out = new Map<string, DaqSampleRow>()
207
+ if (!this.db) return out
208
+ // SQLite 裸列保证:GROUP BY + MAX() 时裸列取自 max 所在行(命中 idx_daq_node_ts,免相关子查询)
209
+ const rows = this.db.prepare(`
210
+ SELECT node_id, MAX(ts_ms) AS ts_ms, value, state FROM daq_samples GROUP BY node_id
211
+ `).all() as Array<{ node_id: string, ts_ms: number, value: number, state: string }>
212
+ for (const r of rows) {
213
+ out.set(r.node_id, { nodeId: r.node_id, tsMs: Number(r.ts_ms), value: Number(r.value), state: String(r.state) })
214
+ }
215
+ return out
216
+ }
217
+
218
+ // ===== 帧(daq_frames;与 Timescale 同契约)=====
219
+
220
+ async writeFrames(rows: import('./tsdb-port').DaqFrameRow[]): Promise<void> {
221
+ if (!this.db || rows.length === 0) return
222
+ const ins = this.db.prepare(
223
+ 'INSERT OR IGNORE INTO daq_frames (node_id, ts_ms, kind, template_key, device_binding_id, line_id, product_id, recipe_id, run_id, points, meta, metrics) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
224
+ )
225
+ this.db.exec('BEGIN')
226
+ try {
227
+ for (const r of rows) {
228
+ ins.run(r.nodeId, r.tsMs, r.kind, r.templateKey ?? null, r.deviceBindingId ?? null, r.lineId ?? null, r.productId ?? null, r.recipeId ?? null, r.runId ?? null, r.points, JSON.stringify(r.meta ?? {}), JSON.stringify(r.metrics ?? {}))
229
+ }
230
+ this.db.exec('COMMIT')
231
+ }
232
+ catch (err) {
233
+ try {
234
+ this.db.exec('ROLLBACK')
235
+ }
236
+ catch { /* 事务已终结 */ }
237
+ throw err
238
+ }
239
+ }
240
+
241
+ async queryFrames(nodeId: string, opts: import('./tsdb-port').DaqFrameQueryOpts): Promise<import('./tsdb-port').DaqFrameRecord[]> {
242
+ if (!this.db) return []
243
+ const limit = Math.min(opts.limit ?? 100, 1000)
244
+ const rows = this.db.prepare(`
245
+ SELECT ts_ms, kind, meta, metrics, device_binding_id, line_id, product_id, recipe_id, run_id
246
+ FROM daq_frames
247
+ WHERE node_id = :id AND (:kind IS NULL OR kind = :kind) AND ts_ms >= :from AND ts_ms <= :to
248
+ ORDER BY ts_ms DESC LIMIT :lim
249
+ `).all({
250
+ ':id': nodeId,
251
+ ':kind': opts.kind ?? null,
252
+ ':from': opts.fromMs ?? 0,
253
+ ':to': opts.toMs ?? Date.now(),
254
+ ':lim': limit,
255
+ }) as Array<{ ts_ms: number, kind: string, meta: string, metrics: string, device_binding_id: string | null, line_id: string | null, product_id: string | null, recipe_id: string | null, run_id: string | null }>
256
+ return rows.map(r => ({
257
+ at: Number(r.ts_ms),
258
+ kind: String(r.kind) as 'vector' | 'image',
259
+ points: r.kind === 'vector' ? pointsFromMeta(asObject(r.meta)) : undefined,
260
+ metrics: asObject(r.metrics) as Record<string, number>,
261
+ meta: asObject(r.meta),
262
+ deviceBindingId: r.device_binding_id,
263
+ lineId: r.line_id,
264
+ productId: r.product_id,
265
+ recipeId: r.recipe_id,
266
+ runId: r.run_id,
267
+ }))
268
+ }
269
+
270
+ /** 帧保留期清理(与样本同拍;daq.frameRetentionH,env DAQ_FRAME_RETENTION_H 兼容) */
271
+ private sweepFrameRetention(): void {
272
+ if (!this.db) return
273
+ const cutoff = Date.now() - daqRuntimeSettings().frameRetentionH * 3600_000
274
+ try {
275
+ this.db.prepare('DELETE FROM daq_frames WHERE ts_ms < ?').run(cutoff)
276
+ }
277
+ catch (err) {
278
+ log.error('[daq-tsdb] 帧保留期清理失败:', err instanceof Error ? err.message : err)
279
+ }
280
+ }
281
+
282
+ close(): Promise<void> | void {
283
+ this.sweepRetentionTimerStop()
284
+ this.db?.close()
285
+ this.db = null
286
+ }
287
+
288
+ private sweepRetentionTimerStop(): void {
289
+ if (this.retentionTimer) {
290
+ clearInterval(this.retentionTimer)
291
+ this.retentionTimer = null
292
+ }
293
+ }
294
+ }
295
+
296
+ /** 向量点列从 meta JSON 还原(非数组/越界防御) */
297
+ function pointsFromMeta(meta: Record<string, unknown>): number[] | undefined {
298
+ const p = meta.points
299
+ if (!Array.isArray(p) || p.length === 0 || p.length > 4096) return undefined
300
+ return p.every(x => Number.isFinite(Number(x))) ? p.map(Number) : undefined
301
+ }
302
+
303
+ function asObject(v: unknown): Record<string, unknown> {
304
+ if (typeof v === 'string') {
305
+ try {
306
+ return JSON.parse(v) as Record<string, unknown>
307
+ }
308
+ catch {
309
+ return {}
310
+ }
311
+ }
312
+ return (v && typeof v === 'object' ? v : {}) as Record<string, unknown>
313
+ }