agentworkshop 0.7.49 → 0.7.51

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 (887) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +409 -6
  2. package/.output/.AgentWorkShop/aml-python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  3. package/.output/.AgentWorkShop/aml-python/__pycache__/amlkit.cpython-312.pyc +0 -0
  4. package/.output/.AgentWorkShop/aml-python/__pycache__/train-example.cpython-312.pyc +0 -0
  5. package/.output/.AgentWorkShop/aml-python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  6. package/.output/.AgentWorkShop/aml-python/aml_eval.py +39 -6
  7. package/.output/.AgentWorkShop/aml-python/amlkit.py +222 -3
  8. package/.output/.AgentWorkShop/aml-python/train-hybrid-example.py +278 -32
  9. package/.output/.AgentWorkShop/prompts/host-tools.json +409 -6
  10. package/.output/.AgentWorkShop/schema.json +135 -133
  11. package/.output/nitro.json +1 -1
  12. package/.output/public/_nuxt/2_DkYoqD2.js +1 -0
  13. package/.output/public/_nuxt/8FXd9As6.js +1 -0
  14. package/.output/public/_nuxt/{d-w5jR8R.js → B3zB6K6m.js} +1 -1
  15. package/.output/public/_nuxt/{OXtV_ukR.js → B4ujjkUI.js} +1 -1
  16. package/.output/public/_nuxt/B9BmiUil.js +2 -0
  17. package/.output/public/_nuxt/B9QzrmgE.js +1 -0
  18. package/.output/public/_nuxt/BE7BrEw6.js +1 -0
  19. package/.output/public/_nuxt/{Cu8c3oMN2.js → BFZIll912.js} +1 -1
  20. package/.output/public/_nuxt/{ChtjzEpK2.js → BGAaKBeo2.js} +1 -1
  21. package/.output/public/_nuxt/BOmDHp5L.js +14 -0
  22. package/.output/public/_nuxt/BPou3U7b.js +1 -0
  23. package/.output/public/_nuxt/{CiTQY_n32.js → BXx9AxdF2.js} +1 -1
  24. package/.output/public/_nuxt/Bfe2qOYs.js +1 -0
  25. package/.output/public/_nuxt/BgEDwFMf.js +1 -0
  26. package/.output/public/_nuxt/BgnhB8r5.js +1 -0
  27. package/.output/public/_nuxt/Bhe953zV2.js +1 -0
  28. package/.output/public/_nuxt/{BITZvQBK.js → Bpkm4W5P.js} +1 -1
  29. package/.output/public/_nuxt/C4lagVdN2.js +1 -0
  30. package/.output/public/_nuxt/C5cf3T4d.js +1 -0
  31. package/.output/public/_nuxt/CBIoheY42.js +1 -0
  32. package/.output/public/_nuxt/{CN1CDAwe.js → CFQSjB1h.js} +1 -1
  33. package/.output/public/_nuxt/CFQyYMEn2.js +1 -0
  34. package/.output/public/_nuxt/CHrErv1E.js +1 -0
  35. package/.output/public/_nuxt/{fxWyOzyp2.js → CI2yXRr42.js} +1 -1
  36. package/.output/public/_nuxt/CIduggmC.js +1 -0
  37. package/.output/public/_nuxt/CU-mhG0-.js +1 -0
  38. package/.output/public/_nuxt/CXzfXC5M.js +1 -0
  39. package/.output/public/_nuxt/{H6pPjo0l.js → C_sjV3Ee.js} +1 -1
  40. package/.output/public/_nuxt/Ccps4cxo.js +1 -0
  41. package/.output/public/_nuxt/{CPmNRTBk2.js → CdIsmU5a2.js} +10 -10
  42. package/.output/public/_nuxt/{BS9P_Ies2.js → ChGuLxwW2.js} +1 -1
  43. package/.output/public/_nuxt/{Ck5oMvUk.js → Cn6ihm8j.js} +1 -1
  44. package/.output/public/_nuxt/{CWzp2R6G.js → D-Xyb3DA.js} +1 -1
  45. package/.output/public/_nuxt/D0SNhlnt.js +1 -0
  46. package/.output/public/_nuxt/D0ldVwl-.js +1 -0
  47. package/.output/public/_nuxt/DClNt1uS.js +1 -0
  48. package/.output/public/_nuxt/{CTVfcnjU.js → DQMbdg4t.js} +2 -2
  49. package/.output/public/_nuxt/{DHSDk8Bq2.js → DTxfFIvL2.js} +1 -1
  50. package/.output/public/_nuxt/DVKXGuMz2.js +1 -0
  51. package/.output/public/_nuxt/{CLySL7mW.js → Da0h_6VA.js} +1 -1
  52. package/.output/public/_nuxt/{PixDfCSm.js → DefDtlKK.js} +1 -1
  53. package/.output/public/_nuxt/DjefmmJu.js +1 -0
  54. package/.output/public/_nuxt/DnH9SRMW2.js +1 -0
  55. package/.output/public/_nuxt/{BmiMC_BC.js → DppqsiPC.js} +1 -1
  56. package/.output/public/_nuxt/Drq9iy6V.js +1 -0
  57. package/.output/public/_nuxt/DsGf2IV82.js +1 -0
  58. package/.output/public/_nuxt/{DoKpLEqc.js → DzfVS8N72.js} +1 -1
  59. package/.output/public/_nuxt/{DRpFsrno.js → I1cI6sPJ2.js} +1 -1
  60. package/.output/public/_nuxt/IU-UGkCJ2.js +1 -0
  61. package/.output/public/_nuxt/KXjvpIk2.js +1 -0
  62. package/.output/public/_nuxt/NJn94js_.js +1 -0
  63. package/.output/public/_nuxt/ON2x-t6n.js +1 -0
  64. package/.output/public/_nuxt/S799kNo8.js +1 -0
  65. package/.output/public/_nuxt/{uI9Ki_XZ.js → S9rLP7_v.js} +1 -1
  66. package/.output/public/_nuxt/UN3nSFjj2.js +1 -0
  67. package/.output/public/_nuxt/WVTVkqef.js +1 -0
  68. package/.output/public/_nuxt/{C_VAXV7I2.js → Yv9YItEX2.js} +1 -1
  69. package/.output/public/_nuxt/_id_.DamiFT0Q.css +1 -0
  70. package/.output/public/_nuxt/{_id_.BTrFUIHX.css → _id_.DpRe1PRh.css} +1 -1
  71. package/.output/public/_nuxt/_wsId_.DkrQkT6r.css +1 -0
  72. package/.output/public/_nuxt/aml.-czpKIs8.css +1 -0
  73. package/.output/public/_nuxt/asmJ99nX2.js +47 -0
  74. package/.output/public/_nuxt/builds/latest.json +1 -1
  75. package/.output/public/_nuxt/builds/meta/912eb5bb-670e-4cc8-b21d-7fc097723466.json +1 -0
  76. package/.output/public/_nuxt/{default.uao9U50c.css → default.CXb_zoN6.css} +1 -1
  77. package/.output/public/_nuxt/{entry.6DEjPWvR.css → entry.JdEG3KJg.css} +1 -1
  78. package/.output/public/_nuxt/jRTz0hjN2.js +1 -0
  79. package/.output/public/_nuxt/{DLPuRMeG.js → k5K6Jj6g.js} +1 -1
  80. package/.output/public/_nuxt/operations.B8X9uWK6.css +1 -0
  81. package/.output/public/_nuxt/{settings.Bo5EYkLI.css → settings.O26Dw1iT.css} +1 -1
  82. package/.output/public/_nuxt/{BACBBVdw.js → tKxYgsf-.js} +1 -1
  83. package/.output/public/_nuxt/{Cm_PTn9t2.js → vXrNItas2.js} +1 -1
  84. package/.output/public/_nuxt/{Cr518Gh02.js → zsRclU9w2.js} +1 -1
  85. package/.output/server/chunks/_/LeftOutlined.mjs +1 -1
  86. package/.output/server/chunks/_/SearchOutlined.mjs +1 -1
  87. package/.output/server/chunks/_/binding-authz.mjs +1 -1
  88. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  89. package/.output/server/chunks/_/entity.mjs +1 -1
  90. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  91. package/.output/server/chunks/_/nitro.mjs +26245 -21135
  92. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  93. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  94. package/.output/server/chunks/build/Checkbox-4EdGAAl_.mjs +1 -1
  95. package/.output/server/chunks/build/FormItemContext-4ORSzhWv.mjs +1 -1
  96. package/.output/server/chunks/build/{OmpTerminalPanel-EQHrOJbw.mjs → OmpTerminalPanel-mk31gVzA.mjs} +3 -3
  97. package/.output/server/chunks/build/{OmpTerminalPanel-EQHrOJbw.mjs.map → OmpTerminalPanel-mk31gVzA.mjs.map} +1 -1
  98. package/.output/server/chunks/build/{PluginSlot-BP_qedpQ.mjs → PluginSlot-D2WUZgbp.mjs} +2 -2
  99. package/.output/server/chunks/build/{PluginSlot-BP_qedpQ.mjs.map → PluginSlot-D2WUZgbp.mjs.map} +1 -1
  100. package/.output/server/chunks/build/{TownView-BAR8CPIZ.mjs → TownView-fP9BiALv.mjs} +6 -6
  101. package/.output/server/chunks/build/{TownView-BAR8CPIZ.mjs.map → TownView-fP9BiALv.mjs.map} +1 -1
  102. package/.output/server/chunks/build/{_id_-DgMpjM3_.mjs → _id_-BUpQSlzo.mjs} +142 -106
  103. package/.output/server/chunks/build/_id_-BUpQSlzo.mjs.map +1 -0
  104. package/.output/server/chunks/build/{_id_-Dv3BQbYV.mjs → _id_-CDlur81q.mjs} +25 -24
  105. package/.output/server/chunks/build/_id_-CDlur81q.mjs.map +1 -0
  106. package/.output/server/chunks/build/{_wsId_-BKJvFmyf.mjs → _wsId_-DPy2BXRd.mjs} +547 -158
  107. package/.output/server/chunks/build/_wsId_-DPy2BXRd.mjs.map +1 -0
  108. package/.output/server/chunks/build/{agents-B2GLPmn2.mjs → agents-CDLcboCv.mjs} +12 -12
  109. package/.output/server/chunks/build/{agents-B2GLPmn2.mjs.map → agents-CDLcboCv.mjs.map} +1 -1
  110. package/.output/server/chunks/build/{aml-DdWicH3t.mjs → aml-DsgtDLWF.mjs} +28 -27
  111. package/.output/server/chunks/build/aml-DsgtDLWF.mjs.map +1 -0
  112. package/.output/server/chunks/build/api-BY6ji7RC.mjs +6 -6
  113. package/.output/server/chunks/build/card-CUSocE9p.mjs +1 -1
  114. package/.output/server/chunks/build/{channel-templates-RPOtkgRf.mjs → channel-templates-DjEsj0_v.mjs} +8 -8
  115. package/.output/server/chunks/build/{channel-templates-RPOtkgRf.mjs.map → channel-templates-DjEsj0_v.mjs.map} +1 -1
  116. package/.output/server/chunks/build/checkbox-C4AKj81e.mjs +1 -1
  117. package/.output/server/chunks/build/constants-HPHJvjne.mjs +6 -6
  118. package/.output/server/chunks/build/{daq-CPtsh0e7.mjs → daq-N69AOtgw.mjs} +12 -11
  119. package/.output/server/chunks/build/daq-N69AOtgw.mjs.map +1 -0
  120. package/.output/server/chunks/build/{dcw-ry5Gyw6Y.mjs → dcw-CN9d3Rs7.mjs} +10 -10
  121. package/.output/server/chunks/build/{dcw-ry5Gyw6Y.mjs.map → dcw-CN9d3Rs7.mjs.map} +1 -1
  122. package/.output/server/chunks/build/{default-DxOE1eB0.mjs → default-DCf9tn1i.mjs} +38 -30
  123. package/.output/server/chunks/build/{default-DxOE1eB0.mjs.map → default-DCf9tn1i.mjs.map} +1 -1
  124. package/.output/server/chunks/build/descriptions-CFaUq4y4.mjs +1 -1
  125. package/.output/server/chunks/build/drawer-Cfh9_zft.mjs +1 -1
  126. package/.output/server/chunks/build/dropdown-KdKWCS5K.mjs +1 -1
  127. package/.output/server/chunks/build/form-uSlNqIAV.mjs +1 -1
  128. package/.output/server/chunks/build/input-Cr_KFj4T.mjs +1 -1
  129. package/.output/server/chunks/build/input-number-BRVnxeiA.mjs +1 -1
  130. package/.output/server/chunks/build/{logs-CeaiO3y9.mjs → logs-BcAjU1Ps.mjs} +12 -11
  131. package/.output/server/chunks/build/logs-BcAjU1Ps.mjs.map +1 -0
  132. package/.output/server/chunks/build/menu-BgkRSSx7.mjs +1 -1
  133. package/.output/server/chunks/build/{monitor-DnuXEIi5.mjs → monitor-DX_K0WMq.mjs} +13 -13
  134. package/.output/server/chunks/build/{monitor-DnuXEIi5.mjs.map → monitor-DX_K0WMq.mjs.map} +1 -1
  135. package/.output/server/chunks/build/operations-OFHYXwh4.mjs +282 -0
  136. package/.output/server/chunks/build/operations-OFHYXwh4.mjs.map +1 -0
  137. package/.output/server/chunks/build/{pages-Bn90ijKD.mjs → pages-rZKH72eC.mjs} +10 -11
  138. package/.output/server/chunks/build/pages-rZKH72eC.mjs.map +1 -0
  139. package/.output/server/chunks/build/{permissions-DL70W1YD.mjs → permissions-BvmodvsO.mjs} +8 -8
  140. package/.output/server/chunks/build/{permissions-DL70W1YD.mjs.map → permissions-BvmodvsO.mjs.map} +1 -1
  141. package/.output/server/chunks/build/{plugins-DrsZo--K.mjs → plugins-DSka7-vS.mjs} +9 -9
  142. package/.output/server/chunks/build/{plugins-DrsZo--K.mjs.map → plugins-DSka7-vS.mjs.map} +1 -1
  143. package/.output/server/chunks/build/popconfirm-Ox-_2V8A.mjs +1 -1
  144. package/.output/server/chunks/build/{schedules-VLzNcjnW.mjs → schedules-lo4bfgVt.mjs} +8 -8
  145. package/.output/server/chunks/build/{schedules-VLzNcjnW.mjs.map → schedules-lo4bfgVt.mjs.map} +1 -1
  146. package/.output/server/chunks/build/segmented-C61yLHvo.mjs +1 -1
  147. package/.output/server/chunks/build/select-rdBWytVK.mjs +1 -1
  148. package/.output/server/chunks/build/{settings-DVAUVMsX.mjs → settings-CAJWvul5.mjs} +32 -13
  149. package/.output/server/chunks/build/settings-CAJWvul5.mjs.map +1 -0
  150. package/.output/server/chunks/build/space-B2uhHJG8.mjs +1 -1
  151. package/.output/server/chunks/build/spin-C2cuvGth.mjs +1 -1
  152. package/.output/server/chunks/build/switch-DZAUIbIN.mjs +1 -1
  153. package/.output/server/chunks/build/table-DOFAvY-v.mjs +1 -1
  154. package/.output/server/chunks/build/tabs-DTeIuZeP.mjs +1 -1
  155. package/.output/server/chunks/build/tag-CHLGvNM6.mjs +1 -1
  156. package/.output/server/chunks/build/{teams-Mc07PYO8.mjs → teams-DBBvIToa.mjs} +14 -14
  157. package/.output/server/chunks/build/{teams-Mc07PYO8.mjs.map → teams-DBBvIToa.mjs.map} +1 -1
  158. package/.output/server/chunks/build/{tokens-DiwD5qni.mjs → tokens-CloWk4x_.mjs} +12 -12
  159. package/.output/server/chunks/build/{tokens-DiwD5qni.mjs.map → tokens-CloWk4x_.mjs.map} +1 -1
  160. package/.output/server/chunks/build/{town-D8VmTCmN.mjs → town-BMlctE4m.mjs} +12 -12
  161. package/.output/server/chunks/build/{town-D8VmTCmN.mjs.map → town-BMlctE4m.mjs.map} +1 -1
  162. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  163. package/.output/server/chunks/build/{useAgentHarnessOptions-CPn5dzKe.mjs → useAgentHarnessOptions-D6SJ_uUr.mjs} +7 -7
  164. package/.output/server/chunks/build/{useAgentHarnessOptions-CPn5dzKe.mjs.map → useAgentHarnessOptions-D6SJ_uUr.mjs.map} +1 -1
  165. package/.output/server/chunks/build/{useAgentTemplateActions-DQWzVnZ0.mjs → useAgentTemplateActions-CdG4g_PF.mjs} +7 -7
  166. package/.output/server/chunks/build/{useAgentTemplateActions-DQWzVnZ0.mjs.map → useAgentTemplateActions-CdG4g_PF.mjs.map} +1 -1
  167. package/.output/server/chunks/build/useAgentTemplateDialogState-CZzpu5og.mjs +6 -6
  168. package/.output/server/chunks/build/{useAgentTemplateForm-vqyiRPtt.mjs → useAgentTemplateForm-a5y-N5sB.mjs} +7 -7
  169. package/.output/server/chunks/build/{useAgentTemplateForm-vqyiRPtt.mjs.map → useAgentTemplateForm-a5y-N5sB.mjs.map} +1 -1
  170. package/.output/server/chunks/build/{useAgentTemplatesCatalog-DcQbsOik.mjs → useAgentTemplatesCatalog-pBVcUuN3.mjs} +7 -7
  171. package/.output/server/chunks/build/{useAgentTemplatesCatalog-DcQbsOik.mjs.map → useAgentTemplatesCatalog-pBVcUuN3.mjs.map} +1 -1
  172. package/.output/server/chunks/build/useAmlDatasets-BM0lZu40.mjs +6 -6
  173. package/.output/server/chunks/build/{useAmlEntities-BjXWvFd_.mjs → useAmlEntities-BDQ8TmLL.mjs} +7 -7
  174. package/.output/server/chunks/build/{useAmlEntities-BjXWvFd_.mjs.map → useAmlEntities-BDQ8TmLL.mjs.map} +1 -1
  175. package/.output/server/chunks/build/{useAmlEnv-BB7p6x_w.mjs → useAmlEnv-DgTVwpqi.mjs} +7 -7
  176. package/.output/server/chunks/build/{useAmlEnv-BB7p6x_w.mjs.map → useAmlEnv-DgTVwpqi.mjs.map} +1 -1
  177. package/.output/server/chunks/build/useAmlExperiments-BtyW32PO.mjs +6 -6
  178. package/.output/server/chunks/build/{useAmlFormat-WrKuRfw2.mjs → useAmlFormat-C2sl3MGB.mjs} +7 -7
  179. package/.output/server/chunks/build/{useAmlFormat-WrKuRfw2.mjs.map → useAmlFormat-C2sl3MGB.mjs.map} +1 -1
  180. package/.output/server/chunks/build/{useAmlJobs-DBuLvWMF.mjs → useAmlJobs-fk-H5Rp5.mjs} +10 -9
  181. package/.output/server/chunks/build/useAmlJobs-fk-H5Rp5.mjs.map +1 -0
  182. package/.output/server/chunks/build/{useAmlModels-VurmkBYe.mjs → useAmlModels-hgyVHoAq.mjs} +7 -7
  183. package/.output/server/chunks/build/{useAmlModels-VurmkBYe.mjs.map → useAmlModels-hgyVHoAq.mjs.map} +1 -1
  184. package/.output/server/chunks/build/{useAmlNotes-BUdj3X6Y.mjs → useAmlNotes-BjbYNADm.mjs} +7 -7
  185. package/.output/server/chunks/build/{useAmlNotes-BUdj3X6Y.mjs.map → useAmlNotes-BjbYNADm.mjs.map} +1 -1
  186. package/.output/server/chunks/build/{useAmlPredict-DFy-Do10.mjs → useAmlPredict-U24-SZNA.mjs} +7 -7
  187. package/.output/server/chunks/build/{useAmlPredict-DFy-Do10.mjs.map → useAmlPredict-U24-SZNA.mjs.map} +1 -1
  188. package/.output/server/chunks/build/useDaqAddNode-kW7uTSMQ.mjs +7 -7
  189. package/.output/server/chunks/build/useDaqDetailBinding-cpBz4hSL.mjs +6 -6
  190. package/.output/server/chunks/build/useDaqDetailFrames-BZGtKKXW.mjs +6 -6
  191. package/.output/server/chunks/build/{useDaqDetailHistory-C4_hVeqZ.mjs → useDaqDetailHistory-DtSTfyMi.mjs} +7 -7
  192. package/.output/server/chunks/build/{useDaqDetailHistory-C4_hVeqZ.mjs.map → useDaqDetailHistory-DtSTfyMi.mjs.map} +1 -1
  193. package/.output/server/chunks/build/{useDaqDetailNode-Bwid_iA8.mjs → useDaqDetailNode-D_vhG0jF.mjs} +8 -8
  194. package/.output/server/chunks/build/{useDaqDetailNode-Bwid_iA8.mjs.map → useDaqDetailNode-D_vhG0jF.mjs.map} +1 -1
  195. package/.output/server/chunks/build/useDaqDetailParams-JfqHvTxr.mjs +7 -7
  196. package/.output/server/chunks/build/{useDaqFilters-C13836p-.mjs → useDaqFilters-BUQtZ82a.mjs} +8 -8
  197. package/.output/server/chunks/build/{useDaqFilters-C13836p-.mjs.map → useDaqFilters-BUQtZ82a.mjs.map} +1 -1
  198. package/.output/server/chunks/build/useDaqNodeWindow-1DWj2H5G.mjs +6 -6
  199. package/.output/server/chunks/build/useDaqOptimizations-Ct-TSXxy.mjs +6 -6
  200. package/.output/server/chunks/build/useDaqStream-wOxZcMDA.mjs +1 -1
  201. package/.output/server/chunks/build/useDaqTemplates-BqQRdrIm.mjs +7 -7
  202. package/.output/server/chunks/build/{useDashboardCharts-DZysNDUX.mjs → useDashboardCharts-D45083s_.mjs} +7 -7
  203. package/.output/server/chunks/build/{useDashboardCharts-DZysNDUX.mjs.map → useDashboardCharts-D45083s_.mjs.map} +1 -1
  204. package/.output/server/chunks/build/{useDashboardData-Ny_wtbo6.mjs → useDashboardData-Do_Vsepa.mjs} +8 -8
  205. package/.output/server/chunks/build/{useDashboardData-Ny_wtbo6.mjs.map → useDashboardData-Do_Vsepa.mjs.map} +1 -1
  206. package/.output/server/chunks/build/{useDcwAddNode-C8nE7geh.mjs → useDcwAddNode-C1HDP3yG.mjs} +12 -9
  207. package/.output/server/chunks/build/useDcwAddNode-C1HDP3yG.mjs.map +1 -0
  208. package/.output/server/chunks/build/useDcwCards-ETEsHvVy.mjs +6 -6
  209. package/.output/server/chunks/build/{useDcwDetailScope-BNrpDzbO.mjs → useDcwDetailScope-QTr1G6Oe.mjs} +7 -7
  210. package/.output/server/chunks/build/{useDcwDetailScope-BNrpDzbO.mjs.map → useDcwDetailScope-QTr1G6Oe.mjs.map} +1 -1
  211. package/.output/server/chunks/build/{useDcwDetailTemplates-IcKAJ37Y.mjs → useDcwDetailTemplates-Djt-0Vse.mjs} +7 -7
  212. package/.output/server/chunks/build/{useDcwDetailTemplates-IcKAJ37Y.mjs.map → useDcwDetailTemplates-Djt-0Vse.mjs.map} +1 -1
  213. package/.output/server/chunks/build/useDcwFilter-FfVlDdyS.mjs +6 -6
  214. package/.output/server/chunks/build/useDcwLedger-BLoMmcu1.mjs +6 -6
  215. package/.output/server/chunks/build/useDcwLineMutations-BMC5BTWU.mjs +6 -6
  216. package/.output/server/chunks/build/{useDcwLineRun-Bpxk4mse.mjs → useDcwLineRun-74gN_s6T.mjs} +7 -7
  217. package/.output/server/chunks/build/{useDcwLineRun-Bpxk4mse.mjs.map → useDcwLineRun-74gN_s6T.mjs.map} +1 -1
  218. package/.output/server/chunks/build/useDcwProducts-D-zrMaeV.mjs +6 -6
  219. package/.output/server/chunks/build/{useDcwQuery-1lYHOaU6.mjs → useDcwQuery-7tX4QYmv.mjs} +7 -7
  220. package/.output/server/chunks/build/{useDcwQuery-1lYHOaU6.mjs.map → useDcwQuery-7tX4QYmv.mjs.map} +1 -1
  221. package/.output/server/chunks/build/useDcwQuickActions-C-tgcXIr.mjs +6 -6
  222. package/.output/server/chunks/build/{useDcwRecipes-BzGOymqz.mjs → useDcwRecipes-FVk5gDLV.mjs} +23 -15
  223. package/.output/server/chunks/build/useDcwRecipes-FVk5gDLV.mjs.map +1 -0
  224. package/.output/server/chunks/build/useDcwStream-D04kCV3J.mjs +1 -1
  225. package/.output/server/chunks/build/{useDcwTemplates-Dsjw9u6U.mjs → useDcwTemplates-LDZffy4u.mjs} +7 -7
  226. package/.output/server/chunks/build/{useDcwTemplates-Dsjw9u6U.mjs.map → useDcwTemplates-LDZffy4u.mjs.map} +1 -1
  227. package/.output/server/chunks/build/{useDcwWrites-3RxwN36I.mjs → useDcwWrites-B22mwliK.mjs} +25 -8
  228. package/.output/server/chunks/build/useDcwWrites-B22mwliK.mjs.map +1 -0
  229. package/.output/server/chunks/build/useLocalTime-DZ2RAtVs.mjs +49 -0
  230. package/.output/server/chunks/build/useLocalTime-DZ2RAtVs.mjs.map +1 -0
  231. package/.output/server/chunks/build/{useLogsFormat-BlwLpyzy.mjs → useLogsFormat-B-o4MHy7.mjs} +7 -7
  232. package/.output/server/chunks/build/{useLogsFormat-BlwLpyzy.mjs.map → useLogsFormat-B-o4MHy7.mjs.map} +1 -1
  233. package/.output/server/chunks/build/{useLogsManual-Deev2Cjk.mjs → useLogsManual-COfCyUtj.mjs} +7 -7
  234. package/.output/server/chunks/build/{useLogsManual-Deev2Cjk.mjs.map → useLogsManual-COfCyUtj.mjs.map} +1 -1
  235. package/.output/server/chunks/build/useLogsQuery-CRAm2hmS.mjs +6 -6
  236. package/.output/server/chunks/build/useLogsScope-ClNijVj4.mjs +6 -6
  237. package/.output/server/chunks/build/{useMonitorColumns-ylxrUNTK.mjs → useMonitorColumns-DhYvkLDq.mjs} +7 -7
  238. package/.output/server/chunks/build/{useMonitorColumns-ylxrUNTK.mjs.map → useMonitorColumns-DhYvkLDq.mjs.map} +1 -1
  239. package/.output/server/chunks/build/{useMonitorData-CEpKXoD4.mjs → useMonitorData-guVjMDtR.mjs} +9 -8
  240. package/.output/server/chunks/build/useMonitorData-guVjMDtR.mjs.map +1 -0
  241. package/.output/server/chunks/build/{useMonitorFormat-_7zLapf3.mjs → useMonitorFormat-C7lhZe4g.mjs} +13 -12
  242. package/.output/server/chunks/build/useMonitorFormat-C7lhZe4g.mjs.map +1 -0
  243. package/.output/server/chunks/build/useMonitorTerminal-Dj4QwRNW.mjs +6 -6
  244. package/.output/server/chunks/build/useOperationsFeed-CeXeHqUK.mjs +191 -0
  245. package/.output/server/chunks/build/useOperationsFeed-CeXeHqUK.mjs.map +1 -0
  246. package/.output/server/chunks/build/{useTeamActions-D6sxdpkP.mjs → useTeamActions-C4n-taBk.mjs} +7 -7
  247. package/.output/server/chunks/build/{useTeamActions-D6sxdpkP.mjs.map → useTeamActions-C4n-taBk.mjs.map} +1 -1
  248. package/.output/server/chunks/build/{useTeamAddMemberDialog-Q-ntQ6Vo.mjs → useTeamAddMemberDialog-Cp_z3nMa.mjs} +7 -7
  249. package/.output/server/chunks/build/{useTeamAddMemberDialog-Q-ntQ6Vo.mjs.map → useTeamAddMemberDialog-Cp_z3nMa.mjs.map} +1 -1
  250. package/.output/server/chunks/build/{useTeamCreateDialog-D7OMfDTM.mjs → useTeamCreateDialog-C8LKUoe2.mjs} +7 -7
  251. package/.output/server/chunks/build/{useTeamCreateDialog-D7OMfDTM.mjs.map → useTeamCreateDialog-C8LKUoe2.mjs.map} +1 -1
  252. package/.output/server/chunks/build/{useTeamDeployDialog-vBRqjiut.mjs → useTeamDeployDialog-wdBVsNWY.mjs} +7 -7
  253. package/.output/server/chunks/build/{useTeamDeployDialog-vBRqjiut.mjs.map → useTeamDeployDialog-wdBVsNWY.mjs.map} +1 -1
  254. package/.output/server/chunks/build/useTeamDialogState-CFRUQxAf.mjs +6 -6
  255. package/.output/server/chunks/build/{useTeamPluginDialog-B8kxewpZ.mjs → useTeamPluginDialog-CIk8G8nI.mjs} +7 -7
  256. package/.output/server/chunks/build/{useTeamPluginDialog-B8kxewpZ.mjs.map → useTeamPluginDialog-CIk8G8nI.mjs.map} +1 -1
  257. package/.output/server/chunks/build/{useTeamsCatalog-xRhk7ezA.mjs → useTeamsCatalog-D6TULzmS.mjs} +7 -7
  258. package/.output/server/chunks/build/{useTeamsCatalog-xRhk7ezA.mjs.map → useTeamsCatalog-D6TULzmS.mjs.map} +1 -1
  259. package/.output/server/chunks/build/useTokenClipboard-CwQpoFeP.mjs +6 -6
  260. package/.output/server/chunks/build/{useTokenCreate-DpDcF1Vx.mjs → useTokenCreate-DkYvEQUD.mjs} +7 -7
  261. package/.output/server/chunks/build/{useTokenCreate-DpDcF1Vx.mjs.map → useTokenCreate-DkYvEQUD.mjs.map} +1 -1
  262. package/.output/server/chunks/build/{useTokenRename-BRejFrtc.mjs → useTokenRename-DOCP4aeI.mjs} +7 -7
  263. package/.output/server/chunks/build/{useTokenRename-BRejFrtc.mjs.map → useTokenRename-DOCP4aeI.mjs.map} +1 -1
  264. package/.output/server/chunks/build/{useTokenReveal-DER2afAS.mjs → useTokenReveal-CybwwflV.mjs} +7 -7
  265. package/.output/server/chunks/build/{useTokenReveal-DER2afAS.mjs.map → useTokenReveal-CybwwflV.mjs.map} +1 -1
  266. package/.output/server/chunks/build/{useTokensList-DHt65IOY.mjs → useTokensList-BLiMvrc4.mjs} +7 -7
  267. package/.output/server/chunks/build/{useTokensList-DHt65IOY.mjs.map → useTokensList-BLiMvrc4.mjs.map} +1 -1
  268. package/.output/server/chunks/build/{useWorkbenchAuth-B2j-zILO.mjs → useWorkbenchAuth-DqjBX-6w.mjs} +7 -7
  269. package/.output/server/chunks/build/{useWorkbenchAuth-B2j-zILO.mjs.map → useWorkbenchAuth-DqjBX-6w.mjs.map} +1 -1
  270. package/.output/server/chunks/build/{useWorkbenchWorkspaces-B_2mOxN6.mjs → useWorkbenchWorkspaces-DgiSCzsX.mjs} +10 -9
  271. package/.output/server/chunks/build/useWorkbenchWorkspaces-DgiSCzsX.mjs.map +1 -0
  272. package/.output/server/chunks/build/{useWorkshopWs-B-Es2Xg3.mjs → useWorkshopWs-Bm80bLn7.mjs} +8 -7
  273. package/.output/server/chunks/build/useWorkshopWs-Bm80bLn7.mjs.map +1 -0
  274. package/.output/server/chunks/build/{useWorkspaceAuth-tQ1ORWXo.mjs → useWorkspaceAuth-Dlvj9csD.mjs} +8 -8
  275. package/.output/server/chunks/build/{useWorkspaceAuth-tQ1ORWXo.mjs.map → useWorkspaceAuth-Dlvj9csD.mjs.map} +1 -1
  276. package/.output/server/chunks/build/{useWorkspaceChannels-BwB6TAWY.mjs → useWorkspaceChannels-D61Al2dr.mjs} +11 -10
  277. package/.output/server/chunks/build/useWorkspaceChannels-D61Al2dr.mjs.map +1 -0
  278. package/.output/server/chunks/build/{useWorkspacePanels-CuAmDpT5.mjs → useWorkspacePanels-CTwREmq0.mjs} +8 -8
  279. package/.output/server/chunks/build/{useWorkspacePanels-CuAmDpT5.mjs.map → useWorkspacePanels-CTwREmq0.mjs.map} +1 -1
  280. package/.output/server/chunks/build/{useWorkspaceShell-CcQ4JlqO.mjs → useWorkspaceShell-BCypjjjE.mjs} +7 -7
  281. package/.output/server/chunks/build/{useWorkspaceShell-CcQ4JlqO.mjs.map → useWorkspaceShell-BCypjjjE.mjs.map} +1 -1
  282. package/.output/server/chunks/build/{users-De2HygNt.mjs → users-CCf5PgRs.mjs} +8 -8
  283. package/.output/server/chunks/build/{users-De2HygNt.mjs.map → users-CCf5PgRs.mjs.map} +1 -1
  284. package/.output/server/chunks/build/{workshop-CmgpTwyf.mjs → workshop-FQ4YzooB.mjs} +13 -12
  285. package/.output/server/chunks/build/workshop-FQ4YzooB.mjs.map +1 -0
  286. package/.output/server/chunks/build/{workspaces-DVIEk1Bl.mjs → workspaces-CmW0cpOt.mjs} +1 -1
  287. package/.output/server/chunks/build/{workspaces-DVIEk1Bl.mjs.map → workspaces-CmW0cpOt.mjs.map} +1 -1
  288. package/.output/server/chunks/routes/api/health.get.mjs +6 -6
  289. package/.output/server/chunks/routes/api/index.get.mjs +7 -7
  290. package/.output/server/chunks/routes/api/index.post.mjs +7 -7
  291. package/.output/server/chunks/routes/api/mcp/workshop.mjs +6 -6
  292. package/.output/server/chunks/routes/api/metrics.mjs +6 -6
  293. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +6 -6
  294. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +6 -6
  295. package/.output/server/chunks/routes/api/plugins/i18n.get.mjs +6 -6
  296. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +6 -6
  297. package/.output/server/chunks/routes/api/system/config-groups/_id_.delete.mjs +6 -6
  298. package/.output/server/chunks/routes/api/system/config-groups/_id_.patch.mjs +6 -6
  299. package/.output/server/chunks/routes/api/system/config.get.mjs +6 -6
  300. package/.output/server/chunks/routes/api/system/index.get.mjs +6 -6
  301. package/.output/server/chunks/routes/api/system/index.patch.mjs +6 -6
  302. package/.output/server/chunks/routes/api/system/index.post.mjs +6 -6
  303. package/.output/server/chunks/routes/api/system/index2.get.mjs +6 -6
  304. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +6 -6
  305. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +6 -6
  306. package/.output/server/chunks/routes/api/system/monitor.get.mjs +6 -6
  307. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +6 -6
  308. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +6 -6
  309. package/.output/server/chunks/routes/api/system/timezone.get.mjs +36 -0
  310. package/.output/server/chunks/routes/api/system/timezone.get.mjs.map +1 -0
  311. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +7 -7
  312. package/.output/server/chunks/routes/api/users/_id_.get.mjs +7 -7
  313. package/.output/server/chunks/routes/api/users/_id_.put.mjs +7 -7
  314. package/.output/server/chunks/routes/api/users/index.get.mjs +7 -7
  315. package/.output/server/chunks/routes/api/users/index.post.mjs +7 -7
  316. package/.output/server/chunks/routes/api/users/login.post.mjs +7 -7
  317. package/.output/server/chunks/routes/api/users/logout.post.mjs +7 -7
  318. package/.output/server/chunks/routes/api/users/me.get.mjs +7 -7
  319. package/.output/server/chunks/routes/api/users/register.post.mjs +7 -7
  320. package/.output/server/chunks/routes/api/users/setup-status.get.mjs +7 -7
  321. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +7 -7
  322. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +7 -7
  323. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +7 -7
  324. package/.output/server/chunks/routes/api/workshop/_...path_.mjs +6 -6
  325. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +7 -7
  326. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +5 -5
  327. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +6 -6
  328. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +7 -7
  329. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +7 -7
  330. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +10 -7
  331. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs.map +1 -1
  332. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +7 -7
  333. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +7 -7
  334. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +7 -7
  335. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +7 -7
  336. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +7 -7
  337. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +6 -6
  338. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +6 -6
  339. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +6 -6
  340. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +6 -6
  341. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +6 -6
  342. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +7 -7
  343. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +7 -7
  344. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +7 -7
  345. package/.output/server/chunks/routes/api/workshop/aml/entities/prune.post.mjs +7 -7
  346. package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs +7 -8
  347. package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs.map +1 -1
  348. package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs +7 -8
  349. package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs.map +1 -1
  350. package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs +7 -8
  351. package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs.map +1 -1
  352. package/.output/server/chunks/routes/api/workshop/aml/index.get.mjs +7 -7
  353. package/.output/server/chunks/routes/api/workshop/aml/index.post.mjs +7 -7
  354. package/.output/server/chunks/routes/api/workshop/aml/index2.get.mjs +6 -6
  355. package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs +20 -7
  356. package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs.map +1 -1
  357. package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs +7 -8
  358. package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs.map +1 -1
  359. package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs +49 -0
  360. package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs.map +1 -0
  361. package/.output/server/chunks/routes/api/workshop/aml/index4.get.mjs +7 -7
  362. package/.output/server/chunks/routes/api/workshop/aml/index5.get.mjs +7 -7
  363. package/.output/server/chunks/routes/api/workshop/aml/index6.get.mjs +7 -7
  364. package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs +28 -0
  365. package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs.map +1 -0
  366. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/cancel.post.mjs +7 -7
  367. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/logs.get.mjs +7 -7
  368. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/retry.post.mjs +7 -7
  369. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.delete.mjs +7 -7
  370. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.get.mjs +7 -7
  371. package/.output/server/chunks/routes/api/workshop/aml/models/_id/predict.post.mjs +7 -7
  372. package/.output/server/chunks/routes/api/workshop/aml/models/_id/promote.post.mjs +7 -7
  373. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.delete.mjs +7 -7
  374. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +7 -7
  375. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs +35 -0
  376. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs.map +1 -0
  377. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs +35 -0
  378. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs.map +1 -0
  379. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs +44 -0
  380. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs.map +1 -0
  381. package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs +46 -0
  382. package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs.map +1 -0
  383. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +7 -7
  384. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +5 -5
  385. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +5 -5
  386. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +6 -6
  387. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +6 -6
  388. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +5 -5
  389. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +6 -6
  390. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +6 -6
  391. package/.output/server/chunks/routes/api/workshop/caller.mjs +7 -7
  392. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +16 -10
  393. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +1 -1
  394. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +6 -6
  395. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +6 -6
  396. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +6 -6
  397. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +6 -6
  398. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +7 -7
  399. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +6 -6
  400. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +6 -6
  401. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +6 -6
  402. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +6 -6
  403. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +6 -6
  404. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +6 -6
  405. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +6 -6
  406. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +6 -6
  407. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +6 -6
  408. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +6 -6
  409. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.get.mjs +6 -6
  410. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +6 -6
  411. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/messages/_messageId/read.post.mjs +6 -6
  412. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/permissions.get.mjs +6 -6
  413. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +6 -6
  414. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +6 -6
  415. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +6 -6
  416. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +7 -7
  417. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +6 -6
  418. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +6 -6
  419. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +6 -6
  420. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +6 -6
  421. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +6 -6
  422. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +6 -6
  423. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +7 -7
  424. package/.output/server/chunks/routes/api/workshop/channels/_id/index6.get.mjs +6 -6
  425. package/.output/server/chunks/routes/api/workshop/channels/_id/members/_userId/approve.post.mjs +6 -6
  426. package/.output/server/chunks/routes/api/workshop/channels/_id/members/_userId_.delete.mjs +6 -6
  427. package/.output/server/chunks/routes/api/workshop/channels/_id/members/join.post.mjs +6 -6
  428. package/.output/server/chunks/routes/api/workshop/channels/_id/members/leave.post.mjs +6 -6
  429. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +6 -6
  430. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +6 -6
  431. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +7 -7
  432. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +51 -0
  433. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs.map +1 -0
  434. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +71 -0
  435. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs.map +1 -0
  436. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +6 -6
  437. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +7 -7
  438. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +6 -6
  439. package/.output/server/chunks/routes/api/workshop/channels.get.mjs +6 -6
  440. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +9 -9
  441. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +7 -7
  442. package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +7 -7
  443. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +7 -7
  444. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +7 -7
  445. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +7 -7
  446. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +7 -7
  447. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +7 -7
  448. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +7 -7
  449. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +7 -7
  450. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +7 -7
  451. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +7 -7
  452. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +7 -7
  453. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +7 -7
  454. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +7 -7
  455. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +7 -7
  456. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +7 -7
  457. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +7 -7
  458. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +7 -7
  459. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +7 -7
  460. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +7 -7
  461. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +7 -7
  462. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +7 -7
  463. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +7 -7
  464. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +7 -7
  465. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +7 -7
  466. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +7 -7
  467. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +7 -7
  468. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +7 -7
  469. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +7 -7
  470. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +7 -7
  471. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +7 -7
  472. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +7 -7
  473. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +7 -7
  474. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +7 -7
  475. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +7 -7
  476. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +7 -7
  477. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +7 -7
  478. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +7 -7
  479. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +7 -7
  480. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +7 -7
  481. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +7 -7
  482. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +7 -7
  483. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +7 -7
  484. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +7 -7
  485. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +7 -7
  486. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +7 -7
  487. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +7 -7
  488. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +7 -7
  489. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +7 -7
  490. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +7 -7
  491. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +7 -7
  492. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +7 -7
  493. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +7 -7
  494. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +7 -7
  495. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +7 -7
  496. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.post.mjs +7 -7
  497. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +7 -7
  498. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs +7 -7
  499. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +7 -7
  500. package/.output/server/chunks/routes/api/workshop/dcw/recipes/index.patch.mjs +7 -7
  501. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +7 -7
  502. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +7 -7
  503. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +7 -7
  504. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +7 -7
  505. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +7 -7
  506. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +7 -7
  507. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +7 -7
  508. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +7 -7
  509. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +7 -7
  510. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +7 -7
  511. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +5 -5
  512. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +7 -7
  513. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +7 -7
  514. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +7 -7
  515. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +7 -7
  516. package/.output/server/chunks/routes/api/workshop/index.get.mjs +6 -6
  517. package/.output/server/chunks/routes/api/workshop/index.post.mjs +6 -6
  518. package/.output/server/chunks/routes/api/workshop/index.put.mjs +7 -7
  519. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +7 -7
  520. package/.output/server/chunks/routes/api/workshop/index11.get.mjs +6 -6
  521. package/.output/server/chunks/routes/api/workshop/index12.get.mjs +6 -6
  522. package/.output/server/chunks/routes/api/workshop/index13.get.mjs +6 -6
  523. package/.output/server/chunks/routes/api/workshop/index14.get.mjs +6 -6
  524. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +7 -8
  525. package/.output/server/chunks/routes/api/workshop/index2.get.mjs.map +1 -1
  526. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +6 -6
  527. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +6 -6
  528. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +7 -7
  529. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +6 -6
  530. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +7 -7
  531. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +7 -7
  532. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +7 -7
  533. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +7 -7
  534. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +7 -7
  535. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +7 -7
  536. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +6 -6
  537. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +6 -6
  538. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +6 -6
  539. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +6 -6
  540. package/.output/server/chunks/routes/api/workshop/index9.post.mjs +6 -6
  541. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +6 -6
  542. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +6 -6
  543. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +6 -6
  544. package/.output/server/chunks/routes/api/workshop/notifications/read.post.mjs +6 -6
  545. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +7 -7
  546. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +7 -7
  547. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +6 -6
  548. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +6 -6
  549. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +7 -7
  550. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +7 -7
  551. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +6 -6
  552. package/.output/server/chunks/routes/api/workshop/schedules/_id/run.post.mjs +6 -6
  553. package/.output/server/chunks/routes/api/workshop/schedules/_id/runs.get.mjs +6 -6
  554. package/.output/server/chunks/routes/api/workshop/schedules/_id_.delete.mjs +6 -6
  555. package/.output/server/chunks/routes/api/workshop/schedules/_id_.get.mjs +6 -6
  556. package/.output/server/chunks/routes/api/workshop/schedules/_id_.patch.mjs +6 -6
  557. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +6 -6
  558. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +6 -6
  559. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +6 -6
  560. package/.output/server/chunks/routes/api/workshop/tasks/_id/reassign.post.mjs +6 -6
  561. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +6 -6
  562. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +6 -6
  563. package/.output/server/chunks/routes/api/workshop/tasks/_id/update.post.mjs +6 -6
  564. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +6 -6
  565. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +6 -6
  566. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +6 -6
  567. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +6 -6
  568. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +6 -6
  569. package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +7 -7
  570. package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +7 -7
  571. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +6 -6
  572. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +6 -6
  573. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +6 -6
  574. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +6 -6
  575. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +6 -6
  576. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +6 -6
  577. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +7 -7
  578. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +6 -6
  579. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +6 -6
  580. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +6 -6
  581. package/.output/server/chunks/routes/renderer.mjs +2 -2
  582. package/.output/server/chunks/virtual/entry.mjs +645 -525
  583. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  584. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  585. package/.output/server/index.mjs +6 -6
  586. package/.output/server/package.json +1 -1
  587. package/README-zh.md +829 -813
  588. package/README.md +839 -823
  589. package/app/components/AppSidebar.vue +1 -0
  590. package/app/components/aml/AmlModelsTable.vue +180 -173
  591. package/app/components/daq/DaqDetailFramesTile.vue +140 -139
  592. package/app/components/daq/DaqDetailHistoryCard.vue +129 -128
  593. package/app/components/dcw/DcwAddNodeModal.vue +342 -328
  594. package/app/components/dcw/DcwNodesTable.vue +290 -253
  595. package/app/components/dcw/DcwQueryCard.vue +252 -251
  596. package/app/components/dcw/DcwRecipeEditModal.vue +297 -285
  597. package/app/components/dcw/DcwRecipePanel.vue +371 -367
  598. package/app/components/operations/OperationsFilterCard.vue +164 -0
  599. package/app/components/operations/OperationsPageHead.vue +47 -0
  600. package/app/components/operations/OperationsTimeline.vue +215 -0
  601. package/app/components/settings/RuntimeFieldRow.vue +207 -189
  602. package/app/components/workshop/ChatTimeline.vue +596 -569
  603. package/app/components/workshop/EventBlock.vue +224 -214
  604. package/app/components/workshop/blocks/ClusterTool.vue +20 -2
  605. package/app/components/workshop/console/LineOperationsPanel.vue +179 -0
  606. package/app/components/workshop/console/RightPane.vue +6 -0
  607. package/app/composables/workshop/event-blocks/constants.ts +48 -2
  608. package/app/composables/workshop/operation-events.ts +151 -0
  609. package/app/composables/workshop/useAmlStream.ts +137 -136
  610. package/app/composables/workshop/useLocalTime.ts +81 -37
  611. package/app/config/schema.ts +3 -0
  612. package/app/pages/aml/styles.css +422 -420
  613. package/app/pages/aml/types.ts +195 -189
  614. package/app/pages/dcw/[id].vue +300 -297
  615. package/app/pages/dcw/composables/useDcwAddNode.ts +124 -121
  616. package/app/pages/dcw/composables/useDcwRecipes.ts +242 -239
  617. package/app/pages/dcw/composables/useDcwWrites.ts +100 -81
  618. package/app/pages/monitor/composables/useMonitorData.ts +125 -124
  619. package/app/pages/monitor/composables/useMonitorFormat.ts +41 -39
  620. package/app/pages/operations/composables/useOperationsFeed.ts +137 -0
  621. package/app/pages/operations.vue +61 -0
  622. package/app/stores/runtime-config.ts +1 -1
  623. package/app/stores/workshop/chat.ts +434 -434
  624. package/app/stores/workshop/notifications.ts +288 -288
  625. package/app/utils/dcw-recipe-form.ts +26 -0
  626. package/cli/aw.mjs +3 -2
  627. package/cli/commands/mcp.mjs +154 -0
  628. package/cli/core/context.mjs +5 -0
  629. package/config.yml +180 -176
  630. package/docs/aml.md +112 -111
  631. package/docs/cli.en.md +447 -445
  632. package/docs/cli.md +412 -410
  633. package/docs/mcp.en.md +27 -0
  634. package/docs/mcp.md +108 -0
  635. package/docs/plugins.en.md +621 -567
  636. package/docs/plugins.md +610 -560
  637. package/docs/sdk.en.md +964 -922
  638. package/docs/sdk.md +900 -861
  639. package/i18n/dicts/aml.json +207 -205
  640. package/i18n/locales/en.ts +37 -0
  641. package/i18n/locales/zh-CN.ts +37 -0
  642. package/mcp/aw-mcp-server.mjs +796 -0
  643. package/mcp/discovery.mjs +227 -0
  644. package/nuxt.config.ts +2 -0
  645. package/package.json +181 -172
  646. package/scripts/.chk-tok +1 -0
  647. package/scripts/.retrain-body.json +1 -0
  648. package/scripts/.retrain3-body.json +1 -0
  649. package/scripts/.rt-tok +1 -0
  650. package/scripts/.rt3-tok +1 -0
  651. package/scripts/_audit/.tmp/audit-data/dcw-params.json +15 -0
  652. package/scripts/_audit/.tmp/audit-data/dcws.json +30 -0
  653. package/scripts/_audit/aw-mcp-live-e2e.mjs +293 -0
  654. package/scripts/_audit/dcw-controller-e2e.ts +25 -18
  655. package/scripts/_audit/dcw-rollback-ledger.ts +4 -1
  656. package/scripts/_audit/feature-audit-e2e.mjs +339 -0
  657. package/scripts/_audit/full-e2e-adopt.mjs +238 -0
  658. package/scripts/_audit/full-e2e-close-loop.mjs +134 -0
  659. package/scripts/_audit/full-e2e-retrain.mjs +320 -0
  660. package/scripts/_audit/full-e2e-supplement.mjs +192 -0
  661. package/scripts/_audit/full-e2e-ui-final.mjs +111 -0
  662. package/scripts/_audit/full-e2e-ui-mount.mjs +111 -0
  663. package/scripts/_audit/full-feature-e2e-20260927.mjs +627 -0
  664. package/scripts/_audit/kb-diag-complete.mjs +261 -0
  665. package/scripts/_audit/kb-diag-complete2.mjs +271 -0
  666. package/scripts/_audit/kb-diag-loop-e2e.mjs +357 -0
  667. package/scripts/_audit/kb-diag-loop-mock.mjs +416 -0
  668. package/scripts/_audit/kb-diag-loop-v2.mjs +314 -0
  669. package/scripts/_audit/recipe-save-e2e.mjs +365 -0
  670. package/scripts/_audit/run.mjs +21 -0
  671. package/scripts/_audit/runtime-dir-e2e.mjs +393 -0
  672. package/scripts/_audit/skills-guided-e2e.mjs +316 -0
  673. package/scripts/_audit/stability-soak.mjs +252 -0
  674. package/scripts/_aw0748-failclosed-probe.mjs +1 -1
  675. package/scripts/_aw0748-mock-closedloop.mjs +12 -0
  676. package/scripts/_aw0748-mock-dispatch-diag.mjs +66 -0
  677. package/scripts/_dbg-configroot-audit.mjs +86 -84
  678. package/scripts/_dbg-daq-intervals-func.mjs +115 -94
  679. package/scripts/_dbg-optloop-ui-shots.mjs +52 -0
  680. package/scripts/_dbg-param-map-e2e.ts +7 -1
  681. package/scripts/_dbg-perms-e2e.mjs +11 -1
  682. package/scripts/_dbg-protocol-matrix.mjs +3 -1
  683. package/scripts/_dbg-render-regression.mjs +67 -25
  684. package/scripts/_lib-aml-python-run.mjs +17 -0
  685. package/scripts/_lint-reflow.mjs +105 -0
  686. package/scripts/_probe-model-channel-link.cjs +25 -0
  687. package/scripts/acceptance-aml-hybrid-e2e.ts +396 -0
  688. package/scripts/acceptance-aml-hybrid-twin.ts +3 -3
  689. package/scripts/acceptance-aml-model-identity.ts +137 -0
  690. package/scripts/dev-guard.mjs +4 -2
  691. package/scripts/dev-protocol-simulators.mjs +3 -2
  692. package/scripts/e2e-aml-decoupled.mjs +162 -0
  693. package/scripts/e2e-closedloop/scenarios-accounts.mjs +2 -0
  694. package/scripts/e2e-closedloop/scenarios-authz.mjs +12 -6
  695. package/scripts/e2e-closedloop/scenarios-daq-dcw.mjs +4 -1
  696. package/scripts/e2e-timezone-settings.mjs +57 -0
  697. package/scripts/live-aml-mockomp.mjs +304 -0
  698. package/scripts/live-aml-optloop-resume.mjs +322 -0
  699. package/scripts/live-aml-optloop.mjs +545 -0
  700. package/scripts/live-aml-stage9.mjs +169 -0
  701. package/scripts/live-aml-two-goals.mjs +315 -0
  702. package/scripts/live-optloop-two-modes.mjs +857 -0
  703. package/scripts/start.mjs +3 -1
  704. package/scripts/test-aw-skills.mjs +102 -0
  705. package/scripts/test-twin-plugin-sdk.mjs +30 -0
  706. package/sdk/context.mjs +305 -0
  707. package/sdk/index.d.mts +149 -0
  708. package/sdk/index.mjs +5 -2
  709. package/server/api/system/timezone.get.ts +20 -0
  710. package/server/api/workshop/agent-tools/bindings/[id].patch.ts +28 -23
  711. package/server/api/workshop/aml/jobs/index.post.ts +74 -44
  712. package/server/api/workshop/aml/training-plans/[id]/train.post.ts +18 -0
  713. package/server/api/workshop/aml/training-plans/[id].delete.ts +18 -0
  714. package/server/api/workshop/aml/training-plans/[id].patch.ts +30 -0
  715. package/server/api/workshop/aml/training-plans/index.get.ts +9 -0
  716. package/server/api/workshop/aml/training-plans/index.post.ts +43 -0
  717. package/server/api/workshop/aml/twin/providers.get.ts +33 -0
  718. package/server/api/workshop/channel-templates/[id]/instantiate.post.ts +8 -2
  719. package/server/api/workshop/channels/[id]/twin-profile.get.ts +45 -0
  720. package/server/api/workshop/channels/[id]/twin-profile.patch.ts +72 -0
  721. package/server/plugins/00-local-time.ts +13 -10
  722. package/server/plugins/aml-twin-worker.ts +32 -0
  723. package/server/plugins/aw-plugins.ts +16 -0
  724. package/server/plugins/workshop.ts +21 -0
  725. package/server/plugins-builtin/twin-injection-default/index.mjs +23 -0
  726. package/server/services/system-config/helpers.ts +42 -41
  727. package/server/services/system-config/recompute.ts +68 -66
  728. package/server/services/workshop/agents/host-tool-bridge/catalog.ts +50 -18
  729. package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +51 -5
  730. package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +19 -6
  731. package/server/services/workshop/agents/industrial/aml-dataset-tools.ts +276 -276
  732. package/server/services/workshop/agents/industrial/aml-job-tools.ts +549 -363
  733. package/server/services/workshop/agents/industrial/audit-query.ts +30 -0
  734. package/server/services/workshop/agents/industrial/dcw-judge-tools.ts +9 -13
  735. package/server/services/workshop/agents/industrial/dcw-tools.ts +208 -213
  736. package/server/services/workshop/agents/industrial/index.ts +3 -2
  737. package/server/services/workshop/agents/industrial/manual-approval.ts +45 -0
  738. package/server/services/workshop/agents/industrial/ops-tools.ts +370 -382
  739. package/server/services/workshop/agents/industrial/optimization-tools.ts +148 -0
  740. package/server/services/workshop/agents/industrial/param-tools.ts +169 -172
  741. package/server/services/workshop/agents/industrial/twin-tools.ts +618 -61
  742. package/server/services/workshop/agents/industrial-context.ts +4 -2
  743. package/server/services/workshop/agents/node-bindings.repo.ts +35 -2
  744. package/server/services/workshop/agents/tool-classes.ts +28 -0
  745. package/server/services/workshop/aml/aml.repo.ts +412 -386
  746. package/server/services/workshop/aml/job-orchestrator/stages.ts +108 -96
  747. package/server/services/workshop/aml/job-orchestrator/start-job.ts +29 -5
  748. package/server/services/workshop/aml/job-orchestrator/submit.ts +36 -1
  749. package/server/services/workshop/aml/model-registry.ts +265 -175
  750. package/server/services/workshop/aml/predictor.ts +336 -262
  751. package/server/services/workshop/aml/python/__pycache__/aml_eval.cpython-312.pyc +0 -0
  752. package/server/services/workshop/aml/python/__pycache__/amlkit.cpython-312.pyc +0 -0
  753. package/server/services/workshop/aml/python/__pycache__/train-example.cpython-312.pyc +0 -0
  754. package/server/services/workshop/aml/python/__pycache__/train-hybrid-example.cpython-312.pyc +0 -0
  755. package/server/services/workshop/aml/python/aml_eval.py +39 -6
  756. package/server/services/workshop/aml/python/amlkit.py +222 -3
  757. package/server/services/workshop/aml/python/train-hybrid-example.py +278 -32
  758. package/server/services/workshop/aml/runtime.ts +4 -3
  759. package/server/services/workshop/aml/twin/acceptance.ts +26 -0
  760. package/server/services/workshop/aml/twin/binding-snapshot.ts +603 -0
  761. package/server/services/workshop/aml/twin/calibration-worker.ts +150 -0
  762. package/server/services/workshop/aml/twin/channel-profile.ts +80 -7
  763. package/server/services/workshop/aml/twin/contracts.ts +3 -0
  764. package/server/services/workshop/aml/twin/declarative-provider.ts +108 -0
  765. package/server/services/workshop/aml/twin/feature-flags.ts +63 -0
  766. package/server/services/workshop/aml/twin/hybrid-provider.ts +86 -0
  767. package/server/services/workshop/aml/twin/model-backed-provider.ts +332 -0
  768. package/server/services/workshop/aml/twin/physics-spec-draft.ts +185 -0
  769. package/server/services/workshop/aml/twin/physics-spec.ts +338 -0
  770. package/server/services/workshop/aml/twin/prompt-composer.ts +143 -0
  771. package/server/services/workshop/aml/twin/provider-contracts.ts +98 -34
  772. package/server/services/workshop/aml/twin/provider-health.ts +69 -8
  773. package/server/services/workshop/aml/twin/provider-loader.ts +76 -45
  774. package/server/services/workshop/aml/twin/provider-registry.ts +670 -49
  775. package/server/services/workshop/aml/twin/repo.ts +63 -4
  776. package/server/services/workshop/aml/twin/scene-builder.ts +118 -0
  777. package/server/services/workshop/aml/twin/scene-lifecycle.ts +60 -0
  778. package/server/services/workshop/aml/twin/snapshot-service.ts +395 -22
  779. package/server/services/workshop/aml/twin/training-plans.ts +260 -0
  780. package/server/services/workshop/aml/twin/trial-service.ts +97 -13
  781. package/server/services/workshop/aml/twin/write-guard.ts +20 -0
  782. package/server/services/workshop/daq/daq-controller/state.ts +8 -5
  783. package/server/services/workshop/daq/drivers/registry.ts +116 -144
  784. package/server/services/workshop/db/database/migrations.ts +40 -0
  785. package/server/services/workshop/db/database/open.ts +4 -1
  786. package/server/services/workshop/db/database/schema.ts +68 -1
  787. package/server/services/workshop/db/database/seed.ts +22 -0
  788. package/server/services/workshop/db/readonly.ts +30 -0
  789. package/server/services/workshop/dcw/dcw-controller/crud.ts +162 -152
  790. package/server/services/workshop/dcw/dcw-controller/helpers.ts +61 -57
  791. package/server/services/workshop/dcw/dcw-controller/types.ts +61 -57
  792. package/server/services/workshop/dcw/dcw-controller/write-audit.ts +49 -0
  793. package/server/services/workshop/dcw/dcw-controller/write.ts +137 -147
  794. package/server/services/workshop/dcw/dcw-node.ts +18 -2
  795. package/server/services/workshop/dcw/dcw-recipe.repo.ts +5 -0
  796. package/server/services/workshop/dcw/dcw-runtime.ts +9 -3
  797. package/server/services/workshop/dcw/drivers/index.ts +2 -1
  798. package/server/services/workshop/dcw/drivers/modbus-rtu.ts +85 -93
  799. package/server/services/workshop/dcw/drivers/modbus.ts +131 -139
  800. package/server/services/workshop/dcw/drivers/opcua.ts +103 -110
  801. package/server/services/workshop/dcw/drivers/registry.ts +25 -45
  802. package/server/services/workshop/dcw/drivers/shared.ts +24 -6
  803. package/server/services/workshop/dcw/param-limits.ts +193 -142
  804. package/server/services/workshop/dcw/param-map.repo.ts +318 -305
  805. package/server/services/workshop/plugin-driver-registry.ts +108 -0
  806. package/server/services/workshop/runtime/manager/admin-channel.ts +13 -0
  807. package/server/services/workshop/runtime/manager/channel-templates.ts +29 -2
  808. package/server/services/workshop/runtime/manager/runtime-wiring.ts +8 -0
  809. package/server/services/workshop/runtime/permission-scope.ts +79 -81
  810. package/server/services/workshop/runtime/schedule-runtime.ts +33 -6
  811. package/server/utils/errors.ts +8 -0
  812. package/shared/config/engine.mjs +5 -0
  813. package/shared/config/home.mjs +15 -20
  814. package/shared/config/schema.json +135 -133
  815. package/shared/dcw-protocol/line.ts +133 -131
  816. package/shared/dcw-protocol/recipe.ts +311 -301
  817. package/shared/local-time.mjs +116 -36
  818. package/.output/public/_nuxt/-hB4kEmt.js +0 -1
  819. package/.output/public/_nuxt/74x7BOWv2.js +0 -1
  820. package/.output/public/_nuxt/9c5GOgbu.js +0 -1
  821. package/.output/public/_nuxt/BHwG4yNs.js +0 -1
  822. package/.output/public/_nuxt/BIOq3xqe2.js +0 -1
  823. package/.output/public/_nuxt/BL_dbd2v2.js +0 -1
  824. package/.output/public/_nuxt/BNnnYEYh2.js +0 -1
  825. package/.output/public/_nuxt/BxYTM0hb.js +0 -1
  826. package/.output/public/_nuxt/C3twEwTh2.js +0 -1
  827. package/.output/public/_nuxt/CGZVhYJ4.js +0 -1
  828. package/.output/public/_nuxt/CJRDL4EG.js +0 -1
  829. package/.output/public/_nuxt/CKQPwwZa2.js +0 -1
  830. package/.output/public/_nuxt/CeWnOF3O.js +0 -1
  831. package/.output/public/_nuxt/ChoLwR-s.js +0 -1
  832. package/.output/public/_nuxt/DGw8juu_.js +0 -2
  833. package/.output/public/_nuxt/DJdDFnjG2.js +0 -1
  834. package/.output/public/_nuxt/DXIaadqv.js +0 -1
  835. package/.output/public/_nuxt/D_7AzAWe.js +0 -1
  836. package/.output/public/_nuxt/DdvQ7LRI.js +0 -14
  837. package/.output/public/_nuxt/DeYsUzhr.js +0 -1
  838. package/.output/public/_nuxt/DkLCjrCk2.js +0 -47
  839. package/.output/public/_nuxt/DpqA8D8_.js +0 -1
  840. package/.output/public/_nuxt/DqtgGFEc.js +0 -1
  841. package/.output/public/_nuxt/Dy3oXKdn2.js +0 -1
  842. package/.output/public/_nuxt/PLGqdko0.js +0 -1
  843. package/.output/public/_nuxt/U8oQxruK.js +0 -1
  844. package/.output/public/_nuxt/WleoCtUX.js +0 -1
  845. package/.output/public/_nuxt/ZvXovq7N2.js +0 -1
  846. package/.output/public/_nuxt/_id_.Bossmhv1.css +0 -1
  847. package/.output/public/_nuxt/_wsId_.D-u-dbP9.css +0 -1
  848. package/.output/public/_nuxt/aml.Bi5X6_oi.css +0 -1
  849. package/.output/public/_nuxt/builds/meta/0530cee1-fff5-4025-a6f4-5708b6534608.json +0 -1
  850. package/.output/public/_nuxt/cDcDztgb2.js +0 -1
  851. package/.output/public/_nuxt/e7BBCLxr.js +0 -1
  852. package/.output/public/_nuxt/hkMGMTqt.js +0 -1
  853. package/.output/public/_nuxt/ikAUnxx3.js +0 -1
  854. package/.output/public/_nuxt/y9kob70X.js +0 -1
  855. package/.output/server/chunks/_/env-manager.mjs +0 -162
  856. package/.output/server/chunks/_/env-manager.mjs.map +0 -1
  857. package/.output/server/chunks/build/_id_-DgMpjM3_.mjs.map +0 -1
  858. package/.output/server/chunks/build/_id_-Dv3BQbYV.mjs.map +0 -1
  859. package/.output/server/chunks/build/_wsId_-BKJvFmyf.mjs.map +0 -1
  860. package/.output/server/chunks/build/aml-DdWicH3t.mjs.map +0 -1
  861. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs +0 -43
  862. package/.output/server/chunks/build/client-only-qNA2OVV_.mjs.map +0 -1
  863. package/.output/server/chunks/build/daq-CPtsh0e7.mjs.map +0 -1
  864. package/.output/server/chunks/build/logs-CeaiO3y9.mjs.map +0 -1
  865. package/.output/server/chunks/build/pages-Bn90ijKD.mjs.map +0 -1
  866. package/.output/server/chunks/build/settings-DVAUVMsX.mjs.map +0 -1
  867. package/.output/server/chunks/build/useAmlJobs-DBuLvWMF.mjs.map +0 -1
  868. package/.output/server/chunks/build/useDcwAddNode-C8nE7geh.mjs.map +0 -1
  869. package/.output/server/chunks/build/useDcwRecipes-BzGOymqz.mjs.map +0 -1
  870. package/.output/server/chunks/build/useDcwWrites-3RxwN36I.mjs.map +0 -1
  871. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs +0 -35
  872. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs.map +0 -1
  873. package/.output/server/chunks/build/useMonitorData-CEpKXoD4.mjs.map +0 -1
  874. package/.output/server/chunks/build/useMonitorFormat-_7zLapf3.mjs.map +0 -1
  875. package/.output/server/chunks/build/useWorkbenchWorkspaces-B_2mOxN6.mjs.map +0 -1
  876. package/.output/server/chunks/build/useWorkshopWs-B-Es2Xg3.mjs.map +0 -1
  877. package/.output/server/chunks/build/useWorkspaceChannels-BwB6TAWY.mjs.map +0 -1
  878. package/.output/server/chunks/build/workshop-CmgpTwyf.mjs.map +0 -1
  879. /package/.output/public/_nuxt/{B2x8SKRO.js → B2x8SKRO2.js} +0 -0
  880. /package/.output/public/_nuxt/{BzvHUfRR2.js → BzvHUfRR.js} +0 -0
  881. /package/.output/public/_nuxt/{DPUXbTg92.js → DPUXbTg9.js} +0 -0
  882. /package/.output/public/_nuxt/{DdNujZN5.js → DdNujZN52.js} +0 -0
  883. /package/.output/public/_nuxt/{DlUQa0wn2.js → DlUQa0wn.js} +0 -0
  884. /package/.output/public/_nuxt/{Du9v6qGB.js → Du9v6qGB2.js} +0 -0
  885. /package/.output/public/_nuxt/{TOWR4WpO.js → TOWR4WpO2.js} +0 -0
  886. /package/.output/public/_nuxt/{cBI0JqsV2.js → cBI0JqsV.js} +0 -0
  887. /package/.output/public/_nuxt/{zh-S_7rN.js → zh-S_7rN2.js} +0 -0
package/docs/plugins.md CHANGED
@@ -1,560 +1,610 @@
1
- # AgentWorkShop 插件开发指南(完整版)
2
-
3
- > 插件 = 一个自包含目录:入口 `index.mjs`(必需),可选 `client.mjs`(浏览器增强)与
4
- > `i18n.json`(多语言消息包)。一个目录同时增强**服务端**(路由/工具/数采/事件)与
5
- > **浏览器**(面板组件/多语言/设置 UI),放入即装载,启停即热重载。
6
- > 本文是唯一权威参考;`docs/site/plugins/` 的分页文档与本文同源。
7
- >
8
- > 适用版本:插件系统 v2 自 **v0.7.29** 起可用(前端组件注入 / 插件设置 / 插件 i18n /
9
- > 运行时服务面);本文档对应当前版本 **v0.7.49**。`ctx.sdkVersion` 当前为 `0.3.0`。
10
-
11
- ## 一、目录结构与快速开始
12
-
13
- ```bash
14
- aw plugin create my-plugin # 脚手架到 <repo>/.AgentWorkShop/plugins/my-plugin(项目级,默认)
15
- aw plugin create my-plugin --global # 或用户级 ~/.AgentWorkShop/plugins/my-plugin(-g 同义)
16
- aw plugin list # 三作用域清单(含启停态)
17
- aw plugin disable my-plugin # 停用(写状态文件,服务自感知热重载)
18
- aw plugin enable my-plugin # 重新启用
19
- ```
20
-
21
- `aw plugin create` 默认落 **project** 级;`--global` / `-g` 落 **user** 级;`--project` 是显式写法(与默认等价,保留以符合直觉);`--force` / `-f` 覆盖已存在目录。插件名校验 `^[a-z][a-z0-9-]{1,31}$`(小写字母开头,2~32 位)。命令生成三个文件:
22
-
23
- ```
24
- <repo>/.AgentWorkShop/plugins/my-plugin/
25
- ├── index.mjs # 服务端入口(必需):export default { name, setup(ctx), … }
26
- ├── client.mjs # 浏览器增强(可选,且必须在 manifest 里声明 client:'./client.mjs')
27
- └── README.md
28
- ```
29
-
30
- 插件根目录还可以放 `i18n.json`(多语言消息包,见 §5)。**插件 KV 不在这里** —— 它落在 `<配置根>/data/plugins/<插件名>/kv.json`(见 §6)。
31
-
32
- ### 三作用域与优先级
33
-
34
- 宿主按 `builtin` → `project` → `user` 顺序扫描,**同名先到先得**:
35
-
36
- | 作用域 | 入口路径 | 说明 |
37
- |---|---|---|
38
- | `builtin` | `<包根>/server/plugins-builtin/<name>/index.mjs` | 随包发布,永远存在;当前发行内置 `diag-bridge`、`rag-bridge` |
39
- | `project` | `<repo>/.AgentWorkShop/plugins/<name>/index.mjs` | 随检出分发,可 git 版本化 |
40
- | `user` | `$AW_HOME/plugins/<name>/index.mjs`(默认 `~/.AgentWorkShop/plugins`) | 用户级,跨项目生效 |
41
-
42
- 同名优先级 **builtin > project > user**(宿主先扫先占,`seen` 集合去重)。注意方向:CLI 指令注册表(`cli/core/registry.mjs`)是**后扫覆盖**,即 project > user > builtin —— 两者相反,不可互相类推。`aw plugin list` / `aw plugin enable|disable` 用的也是这同一顺序,所以启停一定打到你看到的那个插件上。
43
-
44
- ### 启停状态文件
45
-
46
- 启停状态在 **`<home>/plugins-state.json`**,其中 `home = $AW_HOME || ~/.AgentWorkShop`。源码检出下它与**配置根不是同一个目录**:
47
-
48
- - `configRoot = <repo>/.AgentWorkShop` —— 数据与插件 KV 在这里;
49
- - `home = ~/.AgentWorkShop` —— 启停状态在这里。
50
-
51
- 全局安装(home 模式)时两者重合,旧描述写成"配置根"时看不出差别,但源码检出下会指向错误路径。文件格式:
52
-
53
- ```json
54
- { "version": 1, "updatedAt": "2026-09-03T00:00:00.000Z", "disabled": ["my-plugin"] }
55
- ```
56
-
57
- `aw plugin enable|disable`、Web 插件管理页与宿主三方读写同一份文件。
58
-
59
- ## 二、插件契约(index.mjs)
60
-
61
- `index.mjs` 导出**普通对象**(零导入依赖 —— `ctx` 由宿主注入):
62
-
63
- ```js
64
- export default {
65
- name: 'my-plugin', // 必填,全局唯一(缺失/非字符串立即装载失败)
66
- version: '1.1.0', // 可选,manifest 展示用
67
- description: '…', // 可选
68
- auth: 'user', // 可选:none(默认)| user | admin | agent-or-user
69
- client: './client.mjs', // 可选:浏览器入口(必须是相对路径字符串)
70
- settings: [ /* 可选:插件设置声明,见 §4 */ ],
71
- configGroups: [ /* 可选:插件配置分组声明,见 §4 */ ],
72
- routes: [ // 可选:声明式路由(setup 返回后才注册)
73
- { method: 'GET', path: '/health', handler: () => ({ ok: true }) },
74
- ],
75
- async setup(ctx) { /* 服务端生命周期,见 §3 */ },
76
- }
77
- ```
78
-
79
- 装载期宿主做形态校验(`validatePluginModule`):`name` 必须是非空字符串;`setup` 若存在必须是函数;`client` 若存在必须是字符串;`settings` 若存在必须是数组。任一不满足即装载失败,记入 `failures` 并告警,**错误隔离绝不拖垮主服务**。
80
-
81
- 路由注册顺序很重要:**先 `await setup(ctx)`,再注册 `routes[]`**。这样 `setup` 抛错时不会留下"路由活着、宿主无记录"的幽灵路由。
82
-
83
- ## 三、启用、停用与热重载
84
-
85
- | 阶段 | 服务端 | 浏览器 |
86
- |---|---|---|
87
- | 装载 | nitro 插件 `server/plugins/aw-plugins.ts` → 三作用域扫描 → 动态 import(`?t=` 破缓存)→ 形态校验 → `setup(ctx)` → 注册 `routes[]` | loader(`app/plugins/aw-plugins.client.ts`)拉 `GET /api/plugins/manifest` → 拉 `GET /api/plugins/i18n` → 动态 import `/api/plugins/client/<name>` → `setup(ctx)` |
88
- | 注入 | 路由/工具/驱动/模板/处理器即时生效;设置描述符并入 `SystemConfigService` | 面板经 `ctx.ui.registerPanel` 注入页面插槽;`client:init` 钩子广播 |
89
- | 运行 | `daq:sample` / `daq:frame` / `dcw:write` / `line:start\|stop` / `config:changed` / `event:<type>` / `*` | `event:<type>`(与 WS 同源)/ `page:change` / `i18n:changed` |
90
- | 重载 | 状态文件变化 → 全量 dispose(逐个 `await`)→ 解绑 hooks → 清路由 → 重新装载 → 广播 `plugins:reloaded` | WS `plugins.reloaded` 即时同步,另有 15s 轮询兜底 → 停用插件 `ctx.dispose()` |
91
- | 关机 | 逐插件执行 dispose 队列(含 KV 同步落盘)→ 广播 `server:close` | 页面 `pagehide` 自动 `ctx.dispose()` |
92
-
93
- 热重载的几个事实:
94
-
95
- - **触发源是状态文件**:宿主 `fs.watch` 监听 `plugins-state.json` 所在目录,另有 **10s mtime 轮询**兜底(Windows 上 `rename` 原子写可能丢事件)。`aw plugin enable|disable`、Web 开关、或直接触碰该文件都会触发,**约 1s 内**完成全量重装载。
96
- - **改代码不需要重启进程**:重装载用 `import(entry + '?t=' + Date.now())` 打破 ESM 模块缓存,所以插件代码改动会在下一次重装载时生效。宿主没有独立的插件目录 watcher —— 改完代码后触碰 `plugins-state.json`(或 enable/disable 往返一次)就能让它立刻生效。
97
- - **核心代码仍需重启**:`server/` 与 `shared/` 的改动不在插件热重载范围内。
98
- - **竞态防护**:重装载进行期间状态文件再次变化(如 disable→enable 连击)时,去抖回调会撞上 in-flight 守卫;装载结束后宿主比对禁用集快照,有差异自动补跑一次,启停事件不丢失。
99
- - **浏览器侧**:新启用的插件最迟 15s 注入(WS 可用时即时);停用插件立即卸载并回收其全部面板。
100
-
101
- ## 四、插件设置与配置分组
102
-
103
- ### 声明式字段(manifest `settings[]`)
104
-
105
- ```js
106
- settings: [
107
- { key: 'base_url', type: 'string', default: 'http://127.0.0.1:8770',
108
- labelKey: 'plugin.my-plugin.settings.base_url', // i18n 键(见 §5)
109
- label: '服务地址(回退文案)', description: '保存即热生效' },
110
- { key: 'max_turns', type: 'number', default: 0, min: 0, max: 2000, label: '最大轮数' },
111
- { key: 'auto_enabled', type: 'boolean', default: false, label: '自动模式' },
112
- { key: 'mode', type: 'select', default: 'a', options: ['a', 'b'], label: '模式' },
113
- ],
114
- ```
115
-
116
- 校验器(`validatePluginSettings`)的硬约束 —— 任一条不满足,该条目被**跳过并告警**,其余条目照常装载:
117
-
118
- | 约束 | 规则 |
119
- |---|---|
120
- | `key` | 必填,且匹配 `/^[A-Za-z0-9_-]+$/`(仅字母数字与 `-` `_`) |
121
- | `type` | 必须是 `'string' \| 'number' \| 'boolean' \| 'select'` 之一 |
122
- | `default` | **必填** —— 不给默认值的条目直接跳过 |
123
- | `select` | 必须给 `options` 数组,且 `default` 必须在其中(比较按字符串) |
124
- | `min` / `max` | 仅 `number` 生效(仍会被写进描述符,但对其他类型无意义) |
125
- | `label` | 缺省回落 `key`;`labelKey` 存在时优先解析 i18n |
126
- | `description` | 缺省为空串 |
127
-
128
- 规范化后的描述符 `applies` 恒为 `'live'`(保存即热生效),键被强制编址为 **`plugins.<插件名>.<key>`** —— 与全局 schema 键同一编址空间。
129
-
130
- ### 配置分组(manifest `configGroups[]` + `settings[].group`)
131
-
132
- ```js
133
- configGroups: [
134
- { id: 'default', label: '连接', description: '后端地址与鉴权', order: 400 },
135
- { id: 'advanced', label: '高级', collapsed: true },
136
- ],
137
- settings: [
138
- { key: 'base_url', type: 'string', default: 'http://127.0.0.1:8770', group: 'default', label: '服务地址' },
139
- { key: 'timeout_ms', type: 'number', default: 8000, group: 'advanced', label: '超时(ms)' },
140
- ],
141
- ```
142
-
143
- - 分组 id 会被收敛进本插件命名空间:`default`(或写成插件名)映射为 `plugin-<插件名>`,其余声明 id `x` 映射为 `plugin-<插件名>-x`。两个插件用同一个 `network` 也不会互相覆盖。
144
- - `settings[].group` 引用的是**声明时的原始 id**(`default` / `advanced`),不是已经加过前缀的 id。
145
- - **未声明 `group` 的字段**落入本插件默认分区,id 为 `plugin-<插件名>`;若插件没有为这个默认 id 声明过标题,设置页显示的标题就是这个 id 本身(即 `plugin-<插件名>`)。想显示可读标题,就像上面那样声明一个 `{ id: 'default', label: '…' }` —— 两个内置插件都这么做。
146
- - 分组会在插件卸载/停用时自动摘除,不残留空分区。
147
- - 设置页里**没有**一个字面叫「插件」的配置分组:那是系统设置 → 运行配置里的插件管理清单(启停开关 + 健康检测),与插件自己的配置分区是两块 UI。
148
-
149
- > 字段 `configGroups` 是宿主实际读取的名字(`host.mjs` 读 `def.configGroups`)。类型声明文件 `sdk/index.d.mts` 里写的是 `groups?`,与运行时不一致,以本文与代码为准。
150
-
151
- ### 运行时注册(在 `setup` 里按条件扩展)
152
-
153
- ```js
154
- async setup(ctx) {
155
- // 追加一个分组,并拿到收敛后的真实 id
156
- const group = ctx.config.defineGroup({ id: 'rules', label: '自动规则', collapsed: true })
157
- // 追加字段(等价于 manifest 的 settings[],但可以按条件注册)
158
- ctx.config.defineField({
159
- key: 'auto_rules', type: 'string', default: '', group: 'rules', label: 'JSON 规则',
160
- })
161
- ctx.logger.info(ctx.config.groups().map(g => g.id).join(','))
162
- ctx.logger.info(ctx.config.fields().map(f => f.key).join(','))
163
- // 摘除(removeGroup 收的是 defineGroup 返回的已命名空间化 id;removeField 收短 key)
164
- if (group) ctx.config.removeGroup(group.id)
165
- ctx.config.removeField('auto_rules')
166
- }
167
- ```
168
-
169
- `defineGroup` / `defineField` 的校验规则与声明式完全一致(不合法返回 `null` 并告警);`removeGroup` / `removeField` 返回布尔值表示是否真的移除了。这些分组与字段随插件卸载自动摘除,已保存的值不会因为重注册而丢失。
170
-
171
- ### 读取与持久化
172
-
173
- - 读取:`ctx.config.get('plugins.my-plugin.base_url')`(每次调用都读合并后的有效值,保存即热生效);`ctx.config.all()` 拿全量快照。
174
- - 订阅:`ctx.config.onChange(fn)` 等价于 `ctx.hooks.on('config:changed', fn)`。
175
- - 运行时覆盖持久化在 `<配置根>/runtime-settings.json`;`PATCH /api/system/settings` 按同一份描述符校验,前端设置页按描述符渲染。
176
- - 迁移:0.7.28 前写死在 `shared/config/schema.json` 的 `plugins.kb.*` / `plugins.diag.*` 已由插件声明取代;服务启动时一次性搬移旧覆盖到新键(新键未注册时保留旧键等下一次 pass,绝不丢数据)。
177
-
178
- ## 五、插件 i18n(i18n.json)
179
-
180
- ```json
181
- {
182
- "zh-CN": { "settings": { "base_url": "服务地址" }, "panel": { "title": "我的面板" } },
183
- "en": { "settings": { "base_url": "Service URL" }, "panel": { "title": "My panel" } }
184
- }
185
- ```
186
-
187
- - 装载期宿主解析插件根目录的 `i18n.json`(坏文件忽略,不阻断装载)。
188
- - `GET /api/plugins/i18n` 汇编全部**已启用**插件的消息包(免鉴权;只放 UI 文案,**严禁放敏感信息**),返回 `{ i18n: { "<插件名>": { "<locale>": { … } } }, locales: ["zh-CN", "en"] }`。
189
- - 浏览器 loader 拉取后:合并进 vue-i18n 命名空间 `plugin.<插件名>` —— 宿主组件(设置页 `labelKey`、面板 `titleKey`)直接解析;同时 `ctx.t(key)` 在插件自有的消息树上自解析(`ctx.t('panel.title')` 解析到 `plugin.my-plugin.panel.title`,未命中回落原键)。
190
- - 语言切换时 loader 广播 `i18n:changed` 钩子;插件用 `ctx.hooks.on('i18n:changed', fn)` 接收(注意:它**不在** `ctx.on` 的投递面上)。
191
- - manifest 暴露 `hasI18n` / `settingsCount` / `hasClient` 供前端展示。
192
-
193
- ## 六、服务端 ctx 全参考
194
-
195
- | 面 | 成员 | 说明 |
196
- |---|---|---|
197
- | 身份 | `ctx.name` / `ctx.scope` / `ctx.dir` / `ctx.sdkVersion` | `scope ∈ 'builtin' \| 'project' \| 'user'`;`dir` 为插件目录绝对路径 |
198
- | 钩子 | `ctx.hooks.on / once / off / emit` | 每插件门面;热重载自动解绑,无需手动 `off` |
199
- | 日志 | `ctx.logger.debug / info / warn / error` | 自动前缀 `[aw-plugins] [<插件名>]` |
200
- | 配置 | `ctx.config.get / all / onChange / defineGroup / defineField / removeGroup / removeField / groups / fields` | 有效配置只读 + 变更订阅 + 运行时分区分字段注册(见 §4) |
201
- | 存储 | `ctx.kv.get / set / all / bump` | 插件私有 KV;**没有 `reset()`**;内存态为准 + 200ms 防抖原子落盘 |
202
- | 定时 | `ctx.timer.setInterval / setTimeout` | 自动进回收队列,关机与热重载都会清理 |
203
- | 清理 | `ctx.onDispose(fn)` / `ctx.subscriptions.add(d)` | 与 `ctx.timer` 共用同一个宿主回收队列 |
204
- | 路由 | `ctx.route(method, path, handler)` | 挂 `/api/plugins/<插件名><path>`(exact-match);**返回 boolean** |
205
- | 平台 | `ctx.api` | 平台 REST 客户端(自环 origin;自动解信封;鉴权端点需 `ctx.api.setToken(token)`) |
206
- | 网络 | `ctx.http.get(url, opt)` / `ctx.http.post(url, body, opt)` | 出站 fetch;守卫**只校验协议**(仅 http/https),不限制 host;默认超时 8s;`headers` 透传 |
207
- | 事件 | `ctx.events.on(type, fn)` / `ctx.events.off(type, fn)` | scene 实时事件糖:内部订阅 `event:<type>`(见 §7) |
208
- | 路径 | `ctx.paths.home / configRoot / dataDir`;`ctx.dataDir` | `ctx.dataDir` 即本插件 KV 目录 `<配置根>/data/plugins/<插件名>` |
209
- | 数采 | `ctx.daq.registerDriver / registerProcessor / registerTemplate / onFrame / onSample / query / nodes` | 驱动、下沉处理器、节点模板注册 + 时序查询 + 节点元数据快照 |
210
- | 写控 | `ctx.dcw.registerWriteDriver(driver)` | 写驱动注入(与数采读驱动对称):契约 `{ kind, available(), write(input), test(cfg), read?(input), meta? }`;热重载停用即失效 |
211
- | 工具 | `ctx.omp.registerTool({ name, label?, description, parameters, roles?, handler })` | Agent 工具注入;`roles` 仅 `'lead'` 与 `'worker'`(见 §10) |
212
- | 服务 | `ctx.services.names()` / `.get(name)` / `.provide(name, getter)` | 运行时对象面:`get('daq' \| 'lines' \| 'channels' \| 'plugins')`;`provide` 自动加 `<插件名>.` 前缀 |
213
- | 权限 | `ctx.permissions.lineMode / visibleLineIds / listGrants / setGrants` | 产线授权查询与管理 |
214
-
215
- ### 通信协议插件(自定义接口连接方式)
216
-
217
- `ctx.daq.registerDriver` / `ctx.dcw.registerWriteDriver` 是**协议接入点**:串口、其他 PLC 协议、
218
- 私有总线的连接实现都从这里注入,主链路(采样循环 / 写控网关 / 前端表单)零改动。
219
-
220
- ```js
221
- ctx.daq.registerDriver({
222
- kind: 'serial', // 自定义协议 kind(与内置冲突时插件覆盖并告警)
223
- async available() { return true }, // 协议栈包探测(缺失时 UI 显示「未安装」)
224
- async sample({ driverConfig }) { return 25.3 }, // 读数(标量或 v2 帧信封)
225
- async test(driverConfig) { return { ok: true, message: '连接成功', sampleValue: 25.3 } },
226
- meta: { // 自描述(前端「添加节点」下拉 + 动态参数表单)
227
- label: '串口 Serial(RS-232/485)',
228
- status: 'real',
229
- configFields: [{ key: 'path', label: '串口路径', type: 'string', required: true, placeholder: 'COM3' }],
230
- },
231
- })
232
- ```
233
-
234
- 要点:
235
- - 驱动目录经 `GET /api/workshop/daq`(读)与 `GET /api/workshop/dcw`(写)的 `drivers` 字段下发,
236
- 前端数采/写控页据此渲染插件协议与参数表单(带 ⌁ 徽标);不带 `meta` 的驱动只出现在可用性里;
237
- - 热重载先清空全部插件驱动再重装载:**停用/卸载的协议驱动立即失效**,不会残留到重启;
238
- - 内置示例:`server/plugins-builtin/serial-bridge`(串口 Modbus RTU + ASCII 行协议,含读/写驱动、
239
- `health`/`ports`/`probe` API、前端面板与 `serial_ports` Agent 工具)——新协议插件建议以它为模板。
240
-
241
- ### KV 落在哪里
242
-
243
- `<configRoot>/data/plugins/<插件名>/kv.json` —— **不在插件目录里**。写入以内存为准,200ms 防抖后 `tmp + rename` 原子落盘;关机与热重载时取消挂起的防抖并同步落盘。`ctx.kv` 只有 `get / set / all / bump` 四个方法。
244
-
245
- ```js
246
- ctx.kv.set('threshold', 180) // 写(200ms 后落盘)
247
- ctx.kv.get('threshold') // 读(未写过为 undefined)
248
- ctx.kv.bump('alarms') // +1,返回新值;bump('alarms', -1) 递减
249
- ctx.kv.all() // 全量浅拷贝快照
250
- ```
251
-
252
- ## 七、事件参考(服务端)
253
-
254
- 事件经 HookBus 分发,**监听器按注册序串行 await**,同一个监听器收到的 payload 始终是**同一个未被改写的对象** —— 不是 waterfall(只有最后一个非 `undefined` 的返回值被保留,宿主不使用它),v1 也没有 veto / 拦截能力。单个监听器抛错被隔离并计数:成功清零,**连续失败 8 次自动摘除**(熔断)。
255
-
256
- ### 生命周期与平台事件
257
-
258
- | 事件 | 时机 | payload |
259
- |---|---|---|
260
- | `plugin:host:init` | 全部插件 setup 完成后(一次性) | `{ plugins: string[], failures: number }` |
261
- | `plugins:reloaded` | 热重载收尾 | `{ plugins: <manifest> }` |
262
- | `config:changed` | `runtime-settings.json` / 设置页变化 | `{ type, changed: string[], effective, sources }` —— **没有 `at` 字段** |
263
- | `server:close` | nitro close,逐插件 dispose 之后 | `{ at }` |
264
-
265
- ### 业务事件
266
-
267
- | 事件 | 时机 | payload |
268
- |---|---|---|
269
- | `daq:sample` | 节点采样经管线汇聚后的**下发级**出口(与 WS `daq.reading` 同点同节拍,按 `publishIntervalMs` 门控) | `{ nodeId, templateRef, value, state, at, lineId }` |
270
- | `daq:frame` | 多形态帧(向量/图像)入账后(只含元数据/指标/预览,不含 blob) | `{ nodeId, templateRef, kind, at, lineId, preview?, metrics, thumbUrl?, state }` |
271
- | `dcw:write` | 写控 ACK 落账后(含 10s 同值去重) | `{ nodeId, name, eng, prevValue, ok, source, lineId, at }`;`source ∈ manual \| recipe \| agent \| rollback` |
272
- | `line:start` | 批次窗口开启 | `{ lineId, runId, recipeId, productName }` |
273
- | `line:stop` | 批次窗口关闭 | `{ lineId, runId }` |
274
- | `event:<scene-type>` | 任一 `broadcastSceneEvent(type, payload)`,与浏览器 WS 完全同源 | 事件自身 payload |
275
-
276
- ### 通配符与 scene 事件
277
-
278
- 服务端通配写法是**裸星号 `'*'`**,回调收到的是 `{ type, payload }` 包装:
279
-
280
- ```js
281
- ctx.hooks.on('*', ({ type, payload }) => {
282
- ctx.logger.debug('全事件审计', type)
283
- void payload
284
- })
285
- ```
286
-
287
- `ctx.hooks.on('event:*', fn)` 是**错的** —— 永远不会触发。要按类型订阅 scene 事件,用 `ctx.events`,它会替你补 `event:` 前缀:
288
-
289
- ```js
290
- ctx.events.on('daq.node.changed', (p) => ctx.logger.debug('节点变更', p?.op))
291
- ctx.events.on('daq.alarm.changed', (p) => ctx.logger.info('告警状态', p?.nodeId, p?.recovered))
292
- ```
293
-
294
- 常见 scene 事件:`daq.reading`、`daq.frame`、`daq.alarm`、`daq.alarm.changed`、`daq.node.changed`、`daq.controller`、`daq.template.changed`、`dcw.node.changed`、`device.created|updated|deleted`、`ops.log`、`permissions.changed`、`plugins.reloaded`、`aml.job|dataset|model`。
295
-
296
- ### 权限变更
297
-
298
- 权限变更到达插件总线时是 scene 事件 `permissions.changed`(原始总线上的名字是 `event:permissions.changed`)。`ctx.hooks.on('permissions:changed', …)` **永远不触发**,正确写法:
299
-
300
- ```js
301
- ctx.events.on('permissions.changed', (p) => ctx.logger.info('授权变更', p?.userId))
302
- ```
303
-
304
- ### 配置变更
305
-
306
- ```js
307
- ctx.hooks.on('config:changed', (p) => {
308
- ctx.logger.info('配置已变更', p.changed)
309
- ctx.logger.info('当前主题色', ctx.config.get('theme.primaryColor'))
310
- })
311
- // 等价糖:ctx.config.onChange(fn)
312
- ```
313
-
314
- ## 八、浏览器 client.mjs(ctx 面参考)
315
-
316
- 客户端入口必须**在 manifest 里声明** `client: './client.mjs'` —— 仅存在文件是不够的。loader 从 `/api/plugins/client/<插件名>` 取脚本后动态 import 并调用 `setup(ctx)`。
317
-
318
- ```js
319
- export function setup(ctx) {
320
- let samples = 0
321
- const counter = ctx.el('strong', {}, ['0'])
322
-
323
- // scene 事件:type 传事件名本身;收全部 scene 事件用字面量 'event:*'
324
- ctx.on('daq.reading', () => { samples += 1; counter.textContent = String(samples) })
325
-
326
- // 生命周期钩子只能走 ctx.hooks.on(不在 ctx.on 的投递面上)
327
- ctx.hooks.on('i18n:changed', ({ locale }) => ctx.log.info('语言切换:', locale))
328
-
329
- ctx.ui.registerPanel({
330
- slot: 'plugins.page', // 插槽名(见下)
331
- name: 'my-panel', // 同插件内唯一
332
- titleKey: 'panel.title', // 解析 plugin.my-plugin.panel.title(或用静态 title)
333
- order: 10,
334
- mount(el) { // el = 面板容器(标题由插槽渲染)
335
- const box = ctx.el('div', {}, ['样本数:', counter])
336
- el.append(box)
337
- const timer = setInterval(() => { counter.textContent = String(samples) }, 5000)
338
- return () => { clearInterval(timer); box.remove() } // 清理函数:面板卸载时调用
339
- },
340
- })
341
-
342
- ctx.log.info('客户端已注入')
343
- }
344
- ```
345
-
346
- | 成员 | 说明 |
347
- |---|---|
348
- | `ctx.name` / `ctx.sdkVersion` | 插件名 / 客户端 SDK 版本 |
349
- | `ctx.hooks` | 真实 HookBus:`client:init` / `page:change` / `i18n:changed` / `client:destroy` |
350
- | `ctx.on(type, fn)` | scene 事件订阅(type 传事件名本身,内部装到 `event:<type>`);只有字面量 `'event:*'` 是通配;返回解绑函数 |
351
- | `ctx.fetch(path, opt)` | 同源平台 API 助手(自动带 cookie token、解 `{code,data}` 信封、非 2xx 抛错) |
352
- | `ctx.el(tag, attrs, children)` | DOM 助手;`style` 走 `cssText`,`class` 走 `className`,`onXxx` 自动 `addEventListener` |
353
- | `ctx.mount(target, node)` / `ctx.root()` | 挂到选择器/元素(缺失时挂 `ctx.root()`)/ 插件私有挂载点 `#aw-plugin-<name>` |
354
- | `ctx.ui.registerPanel(entry)` / `ctx.ui.slots` | 向命名插槽注册面板,返回注销函数;`slots` 为已知插槽名 |
355
- | `ctx.t(key, params?)` | 插件命名空间翻译(`plugin.<name>.<key>`) |
356
- | `ctx.locale` | 当前界面语言 |
357
- | `ctx.log.info / warn / error` | 带 `[aw-plugin:<name>]` 前缀的 console |
358
- | `ctx.dispose()` | 卸载:广播 `client:destroy` → 回收订阅 → 移除 `root()`(幂等) |
359
-
360
- ### 通配与不可达的订阅(高频坑)
361
-
362
- | 写法 | 结果 |
363
- |---|---|
364
- | `ctx.on('daq.reading', fn)` | 正确:订阅 scene 事件 `daq.reading` |
365
- | `ctx.on('event:*', fn)` | 正确:唯一通配写法,收全部 scene 事件 |
366
- | `ctx.on('*', fn)` | **死订阅**:不会触发 |
367
- | `ctx.on('event:line.start', fn)` | **死订阅**:只订阅同名 scene 事件 `event:line.start`,而它不存在 |
368
- | `ctx.on('daq:sample', fn)` | **死订阅**:服务端钩子不过桥到浏览器 |
369
- | `ctx.hooks.on('page:change', fn)` | 正确:生命周期钩子走 `ctx.hooks` |
370
- | `ctx.on('client:init', fn)` | **死订阅**:生命周期钩子不在 `ctx.on` 面上 |
371
-
372
- 服务端钩子(`daq:sample`、`daq:frame`、`dcw:write`、`line:start\\|stop`)**永远不会到达浏览器**;浏览器能收到的只有 scene 事件(经 TownBus/WS 桥)。反过来,`page:change` / `i18n:changed` 也只存在于浏览器侧。
373
-
374
- ### 面板与页面插槽
375
-
376
- 宿主页面在任意位置放 `<workshop-plugin-slot slot-name="…" />` 即接收注入;`ctx.ui.slots` 当前为:
377
-
378
- | 插槽 | 落点 |
379
- |---|---|
380
- | `plugins.page` | 插件管理页(默认落点) |
381
- | `settings.plugins` | 系统设置 → 运行配置 → 插件管理区下方 |
382
- | `dashboard.widgets` | 仪表盘页尾 |
383
-
384
- `registerPanel` 返回 `unregisterPanel` 注销函数;面板的 `mount(el)` 可以返回清理函数(面板卸载时调用),也可以抛错 —— 单面板异常由插槽隔离,不影响其他面板与页面。
385
-
386
- ### 卸载语义
387
-
388
- - `ctx.dispose()` 由 **`pagehide`** 触发(导航离开 / 进入 bfcache;切标签页**不**触发)。它会广播 `client:destroy`、回收插件自己的订阅、移除 `root()`。
389
- - `ctx.dispose()` 本身**不注销面板** —— 面板回收由 loader 在停用/热重载时调用 `unregisterPlugin(name)` 完成。
390
- - 热通道双保险:WS `plugins.reloaded` 事件(即时)+ 15s 轮询 diff。
391
-
392
- ## 九、路由与鉴权
393
-
394
- `ctx.route(method, path, handler)` 立即注册并返回 **boolean**;manifest 里的 `routes[]` 在 `setup` 返回之后才注册。两者最终都挂在同一个路由表上:
395
-
396
- ```
397
- GET /api/plugins/<插件名>/health ← ctx.route('GET', '/health', handler)
398
- ← routes: [{ method: 'GET', path: '/health', handler }]
399
- ```
400
-
401
- - 匹配是 **exact-match**,路径统一以 `/` 开头;没有通配段、没有子路由匹配。
402
- - handler 收到 h3 的 `event`;JSON body 已由平台转发层预读并挂在 **`event.awBody`** 上(插件无需导入 h3)。
403
- - handler 的返回值由 nitro 序列化为 JSON;抛错会变成 500 信封(带插件归属的日志),不裸传堆栈。
404
- - **鉴权由声明式 `auth` 字段统一执行**,在进入 handler **之前**校验,对 `routes[]` 与 `ctx.route()` 一视同仁:
405
-
406
- | `auth` | 行为 |
407
- |---|---|
408
- | `'none'`(默认) | 不校验,直接进入 handler |
409
- | `'user'` | 需要有效用户 token,否则 401 |
410
- | `'admin'` | 需要管理员,否则 401 |
411
- | `'agent-or-user'` | 接受 Agent 身份或用户 token |
412
-
413
- **不要把鉴权写进 handler**:`resolveUser(event)` 不可从插件导入,`ctx` 上也没有它。要鉴权就声明 `auth`。
414
-
415
- ```js
416
- ctx.route('GET', '/report', () => ({ plugin: ctx.name, at: new Date().toISOString() }))
417
-
418
- ctx.route('POST', '/threshold', (event) => {
419
- const v = Number(event.awBody?.threshold) // 宿主已预读 JSON body
420
- if (!Number.isFinite(v)) return { ok: false, error: 'threshold 必须是数字' }
421
- ctx.kv.set('threshold', v)
422
- return { ok: true, threshold: v }
423
- })
424
- ```
425
-
426
- ## 十、工具与团队开关
427
-
428
- `ctx.omp.registerTool(def)` 注册的工具出现在全部 harness 的工具面上(omp 经 RPC `set_host_tools` 下发 / 其余引擎经 MCP 桥 `tools/list` / pi 经工具文件 / mock 经 REST invoke 直调),注册表变化会**热重发**给在跑的会话,无需重启或重 spawn 子进程。
429
-
430
- ```js
431
- ctx.omp.registerTool({
432
- name: 'sensor_log',
433
- label: '传感器标定',
434
- description: '查询/登记传感器标定结论',
435
- parameters: { type: 'object', properties: { sensor: { type: 'string' } }, required: ['sensor'] },
436
- roles: ['lead', 'worker'], // 仅这两个字面量;缺省=两者都可用
437
- handler: async (args, agent) => ({ text: `${agent.role}@${agent.channelId}: ${args.sensor}` }),
438
- })
439
- ```
440
-
441
- 参数 schema 里**不要开 `url` / `host` 这类注入口** —— 插件工具的参数直接来自模型,任何"让模型指定目标地址"的字段都会变成 SSRF 面。
442
-
443
- ### 团队 / Channel 级开关
444
-
445
- 全局启停之外,每个团队(Channel)还有独立的插件开关组(由 `channel_plugins` 表承载):
446
-
447
- - **建队时勾选**:`POST /api/workshop/teams` 接受 `plugins: [{ name, enabled }]`,以 team id 为键落库,部署时传导到 Channel;
448
- - **随时切换**:`GET|PUT /api/workshop/channels/:id/plugins`、`GET|PUT /api/workshop/teams/:id/plugins`(body 为 `{ plugins: [{ name, enabled }] }`,全量替换语义,未知/停用插件名忽略);
449
- - **语义**:无显式行 = 未配置 → 全部启用插件对该团队可见(向后兼容);写入显式行后按行过滤 —— **被关闭插件的工具不注入该团队的 Agent,dispatch 同源拒绝**;
450
- - **前端**:workshop teams 页(创建勾选 + 团队弹层)。
451
-
452
- ## 十一、完整示例
453
-
454
- ```js
455
- // index.mjs —— 服务端入口(零导入依赖;ctx 由宿主注入)
456
- export default {
457
- name: 'my-plugin',
458
- version: '1.0.0',
459
- description: '示例:越限计数 + 自有 API + 设置分区 + Agent 工具',
460
- auth: 'user',
461
- client: './client.mjs',
462
- configGroups: [
463
- { id: 'default', label: '我的插件', description: '基础配置', order: 500 },
464
- { id: 'advanced', label: '高级', collapsed: true },
465
- ],
466
- settings: [
467
- { key: 'threshold', type: 'number', default: 180, min: 0, max: 5000, group: 'default',
468
- label: '告警阈值', description: '保存即热生效' },
469
- { key: 'endpoint', type: 'string', default: 'http://127.0.0.1:8080', group: 'advanced',
470
- label: '外部服务地址' },
471
- ],
472
- routes: [
473
- { method: 'GET', path: '/health', handler: () => ({ ok: true }) },
474
- ],
475
-
476
- async setup(ctx) {
477
- ctx.logger.info(`装载完成(scope=${ctx.scope}, sdk=${ctx.sdkVersion})`)
478
-
479
- const threshold = () => Number(ctx.config.get('plugins.my-plugin.threshold')) || 180
480
-
481
- // 1) 数采下发级样本:越限计数落插件私有 KV
482
- ctx.hooks.on('daq:sample', (s) => {
483
- if (typeof s?.value === 'number' && s.value > threshold())
484
- ctx.kv.bump(`alarm:${s.nodeId}`)
485
- })
486
-
487
- // 2) scene 事件订阅(ctx.events 自动补 event: 前缀)
488
- ctx.events.on('daq.alarm', (a) => ctx.logger.warn('告警', a?.nodeId))
489
- ctx.events.on('permissions.changed', (p) => ctx.logger.info('授权变更', p?.userId))
490
-
491
- // 3) 全事件审计:服务端通配是裸 '*',回调收 { type, payload }
492
- ctx.hooks.on('*', ({ type }) => ctx.logger.debug('event', type))
493
-
494
- // 4) setup 之后才会注册 routes[];这里用 ctx.route 立即注册(返回 boolean)
495
- ctx.route('POST', '/threshold', (event) => {
496
- const v = Number(event.awBody?.threshold)
497
- if (!Number.isFinite(v)) return { ok: false, error: 'threshold 必须是数字' }
498
- ctx.kv.set('threshold', v)
499
- return { ok: true, threshold: v }
500
- })
501
-
502
- // 5) 定时器 + 清理:同一个宿主回收队列,关机与热重载都会执行
503
- ctx.timer.setInterval(() => ctx.kv.set('heartbeat', new Date().toISOString()), 5000)
504
- ctx.onDispose(() => ctx.logger.info('插件已清理'))
505
-
506
- // 6) Agent 工具(roles 仅 'lead' | 'worker')
507
- ctx.omp.registerTool({
508
- name: 'my_alarm_report',
509
- description: '读取本插件记录的越限告警计数',
510
- parameters: { type: 'object', properties: { nodeId: { type: 'string' } }, required: ['nodeId'] },
511
- roles: ['lead', 'worker'],
512
- handler: async (args, agent) => ({
513
- text: `${args.nodeId} 告警 ${ctx.kv.get(`alarm:${args.nodeId}`) ?? 0} 次(by ${agent.role})`,
514
- }),
515
- })
516
- },
517
- }
518
- ```
519
-
520
- `client.mjs` 见 §8;`i18n.json` 见 §5。装到哪个作用域、怎么启停见 §1。
521
-
522
- ## 十二、故障排查
523
-
524
- | 现象 | 原因 / 处理 |
525
- |---|---|
526
- | 改了插件代码没生效 | 宿主没有插件目录 watcher:触碰 `<home>/plugins-state.json` 或 `aw plugin enable/disable` 往返一次触发重载(重载会带 `?t=` 破缓存);核心 `server/`、`shared/` 改动仍需重启进程 |
527
- | 重建同名插件后路由 404 | 此前 disable 过的插件名在 `<home>/plugins-state.json` 里留有禁用标记,重建目录不会自动恢复装载 —— 重建后必须显式 `aw plugin enable <name>`(实测踩过) |
528
- | 装载失败看不到 | `aw plugin list` **不显示**装载失败。用 `GET /api/workshop/plugins`(返回 `{ plugins, failures, initedAt }`,**没有 `{code,data}` 信封**),或看启动日志里的 `[aw-plugins] 装载失败 …` |
529
- | 插件路由 404 | exact-match;检查 method 与 path 前导 `/`,以及插件是否处于启用态(停用插件的路由已从路由表移除) |
530
- | 插件路由 401 | 入口声明了 `auth: 'user' \| 'admin' \| 'agent-or-user'`,请求未带有效凭据;开放接口才用 `auth: 'none'` |
531
- | 客户端面板没出现 | 浏览器 console 看 `[aw-plugins]` 告警;确认 manifest `hasClient: true`(即 manifest 里声明了 `client:'./client.mjs'`)且插件 `enabled !== false` |
532
- | 客户端订阅不触发 | 检查是不是踩了 §8 的坑(`ctx.on('*')`、`ctx.on('event:line.start')`、`ctx.on('daq:sample')`,或把生命周期钩子交给 `ctx.on`) |
533
- | 设置项没渲染 | 声明里缺 `default` 会被跳过并告警;`select` 的 `default` 必须在 `options` 里;`key` 只允许字母数字与 `-` `_` |
534
- | 设置值改了没生效 | 确认读的是 `ctx.config.get('plugins.<插件名>.<key>')`(短 key 读不到) |
535
- | `permissions:changed` 钩子不触发 | 该名字不存在;用 `ctx.events.on('permissions.changed', fn)` |
536
- | KV 数据"丢了" | KV 在 `<配置根>/data/plugins/<插件名>/kv.json`,不在插件目录;写入 200ms 防抖落盘,强杀进程会有极小丢失窗口 |
537
- | `ctx.api` 401 | 鉴权端点需 `ctx.api.setToken(token)`;免鉴权端点(manifest / ping)无需 |
538
-
539
- **信任模型**:插件是任意 node 代码,与 aw commands 同级 —— 只安装/启用你信任的插件。
540
-
541
- ### 已知边界(有意为之,不是缺陷)
542
-
543
- - **钩子是观察语义**:v1 没有 veto / 拦截 / 改写能力,写控联锁完整性优先。
544
- - **`ctx.http` 守卫只校验协议**(仅 http/https),**不限制 host**;需要白名单请在插件内自行校验(内置 `diag-bridge` / `rag-bridge` 就是这么做的)。
545
- - **`ctx.t(key, params)` 的 `params` 当前被忽略**(不做插值);需要拼字符串请在插件里自己做。
546
- - **`ctx.kv` 没有 `reset()`**,只有 `get / set / all / bump`。
547
- - **服务端与浏览器的订阅面不互通**:服务端钩子不过桥,浏览器事件也不上服务端。
548
- - **浏览器新启用插件注入延迟 ≤15s**(WS 可用时即时)。
549
- - **`server:close` / `onDispose` 依赖优雅关闭信号**,Windows 强杀进程不触发。
550
- - **`aw plugin list` 只做目录扫描**,不反映装载失败与运行态健康。
551
- - **协议插件的原生栈与宿主同进程**:serial-bridge 的 RTU 帧机为自研实现(单 serialport 原生栈;弃用 modbus-serial —— 其包装层在 dev 模式实测触发 V8 原生崩溃)。已知边界:**`aw dev` 进程内,串口事务「写→超时→关闭」序列可能触发 bindings-cpp 的 V8 原生崩溃**(HandleScope fatal,JS 层不可捕获,与具体串口无关);**生产模式(`aw start`)不受影响 —— 已实测同一序列在生产下诚实返回超时且服务存活**,纯打开(ASCII 探针)在 dev 下同样正常。开发期连接真实硬件请知悉此风险;对稳定性要求极高的部署可把串口网关放进独立进程(参考 plc-node-simulator 的子进程模式)。
552
-
553
- ## 十三、发布前验证清单
554
-
555
- 1. `aw plugin list` 三个作用域都能看到;C 端插件显示 `+client`;启停开关往返后路由/工具/面板同步生灭(连击不丢事件)。
556
- 2. `GET /api/workshop/plugins` 的 `failures` 为空;`GET /api/plugins/manifest` 的 `settingsCount` / `hasClient` / `hasI18n` 与声明一致。
557
- 3. 设置页出现本插件的配置分区(未声明分组的字段落在 `plugin-<插件名>` 分区),改值后 `ctx.config.get('plugins.<插件名>.<key>')` 立即读到新值。
558
- 4. 语言切换:面板标题/文案跟随;`i18n:changed` 清理函数无泄漏。
559
- 5. 工具经 `GET /api/workshop/agent-tools/list` 可见;参数里没有 `url` / `host` 注入口;团队开关关闭后工具消失且 dispatch 拒绝。
560
- 6. 触发一次热重载(enable/disable 往返),确认 `plugins:reloaded` 到达插件、KV 与定时器无泄漏。
1
+ # AgentWorkShop 插件开发指南(完整版)
2
+
3
+ > 插件 = 一个自包含目录:入口 `index.mjs`(必需),可选 `client.mjs`(浏览器增强)与
4
+ > `i18n.json`(多语言消息包)。一个目录同时增强**服务端**(路由/工具/数采/事件)与
5
+ > **浏览器**(面板组件/多语言/设置 UI),放入即装载,启停即热重载。
6
+ > 本文是唯一权威参考;`docs/site/plugins/` 的分页文档与本文同源。
7
+ >
8
+ > 适用版本:插件系统 v2 自 **v0.7.29** 起可用(前端组件注入 / 插件设置 / 插件 i18n /
9
+ > 运行时服务面);本文档对应当前版本 **v0.7.51**。`ctx.sdkVersion` 当前为 `0.3.0`。
10
+
11
+ ## 一、目录结构与快速开始
12
+
13
+ ```bash
14
+ aw plugin create my-plugin # 脚手架到 <repo>/.AgentWorkShop/plugins/my-plugin(项目级,默认)
15
+ aw plugin create my-plugin --global # 或用户级 ~/.AgentWorkShop/plugins/my-plugin(-g 同义)
16
+ aw plugin list # 三作用域清单(含启停态)
17
+ aw plugin disable my-plugin # 停用(写状态文件,服务自感知热重载)
18
+ aw plugin enable my-plugin # 重新启用
19
+ ```
20
+
21
+ `aw plugin create` 默认落 **project** 级;`--global` / `-g` 落 **user** 级;`--project` 是显式写法(与默认等价,保留以符合直觉);`--force` / `-f` 覆盖已存在目录。插件名校验 `^[a-z][a-z0-9-]{1,31}$`(小写字母开头,2~32 位)。命令生成三个文件:
22
+
23
+ ```
24
+ <repo>/.AgentWorkShop/plugins/my-plugin/
25
+ ├── index.mjs # 服务端入口(必需):export default { name, setup(ctx), … }
26
+ ├── client.mjs # 浏览器增强(可选,且必须在 manifest 里声明 client:'./client.mjs')
27
+ └── README.md
28
+ ```
29
+
30
+ 插件根目录还可以放 `i18n.json`(多语言消息包,见 §5)。**插件 KV 不在这里** —— 它落在 `<配置根>/data/plugins/<插件名>/kv.json`(见 §6)。
31
+
32
+ ### 三作用域与优先级
33
+
34
+ 宿主按 `builtin` → `project` → `user` 顺序扫描,**同名先到先得**:
35
+
36
+ | 作用域 | 入口路径 | 说明 |
37
+ |---|---|---|
38
+ | `builtin` | `<包根>/server/plugins-builtin/<name>/index.mjs` | 随包发布,永远存在;当前发行内置 `diag-bridge`、`rag-bridge` |
39
+ | `project` | `<repo>/.AgentWorkShop/plugins/<name>/index.mjs` | 随检出分发,可 git 版本化 |
40
+ | `user` | `$AW_HOME/plugins/<name>/index.mjs`(默认 `~/.AgentWorkShop/plugins`) | 用户级,跨项目生效 |
41
+
42
+ 同名优先级 **builtin > project > user**(宿主先扫先占,`seen` 集合去重)。注意方向:CLI 指令注册表(`cli/core/registry.mjs`)是**后扫覆盖**,即 project > user > builtin —— 两者相反,不可互相类推。`aw plugin list` / `aw plugin enable|disable` 用的也是这同一顺序,所以启停一定打到你看到的那个插件上。
43
+
44
+ ### 启停状态文件
45
+
46
+ 启停状态在 **`<home>/plugins-state.json`**,其中 `home = $AW_HOME || ~/.AgentWorkShop`。源码检出下它与**配置根不是同一个目录**:
47
+
48
+ - `configRoot = <repo>/.AgentWorkShop` —— 数据与插件 KV 在这里;
49
+ - `home = ~/.AgentWorkShop` —— 启停状态在这里。
50
+
51
+ 全局安装(home 模式)时两者重合,旧描述写成"配置根"时看不出差别,但源码检出下会指向错误路径。文件格式:
52
+
53
+ ```json
54
+ { "version": 1, "updatedAt": "2026-09-03T00:00:00.000Z", "disabled": ["my-plugin"] }
55
+ ```
56
+
57
+ `aw plugin enable|disable`、Web 插件管理页与宿主三方读写同一份文件。
58
+
59
+ ## 二、插件契约(index.mjs)
60
+
61
+ `index.mjs` 导出**普通对象**(零导入依赖 —— `ctx` 由宿主注入):
62
+
63
+ ```js
64
+ export default {
65
+ name: 'my-plugin', // 必填,全局唯一(缺失/非字符串立即装载失败)
66
+ version: '1.1.0', // 可选,manifest 展示用
67
+ description: '…', // 可选
68
+ auth: 'user', // 可选:none(默认)| user | admin | agent-or-user
69
+ client: './client.mjs', // 可选:浏览器入口(必须是相对路径字符串)
70
+ settings: [ /* 可选:插件设置声明,见 §4 */ ],
71
+ configGroups: [ /* 可选:插件配置分组声明,见 §4 */ ],
72
+ routes: [ // 可选:声明式路由(setup 返回后才注册)
73
+ { method: 'GET', path: '/health', handler: () => ({ ok: true }) },
74
+ ],
75
+ async setup(ctx) { /* 服务端生命周期,见 §3 */ },
76
+ }
77
+ ```
78
+
79
+ 装载期宿主做形态校验(`validatePluginModule`):`name` 必须是非空字符串;`setup` 若存在必须是函数;`client` 若存在必须是字符串;`settings` 若存在必须是数组。任一不满足即装载失败,记入 `failures` 并告警,**错误隔离绝不拖垮主服务**。
80
+
81
+ 路由注册顺序很重要:**先 `await setup(ctx)`,再注册 `routes[]`**。这样 `setup` 抛错时不会留下"路由活着、宿主无记录"的幽灵路由。
82
+
83
+ ## 三、启用、停用与热重载
84
+
85
+ | 阶段 | 服务端 | 浏览器 |
86
+ |---|---|---|
87
+ | 装载 | nitro 插件 `server/plugins/aw-plugins.ts` → 三作用域扫描 → 动态 import(`?t=` 破缓存)→ 形态校验 → `setup(ctx)` → 注册 `routes[]` | loader(`app/plugins/aw-plugins.client.ts`)拉 `GET /api/plugins/manifest` → 拉 `GET /api/plugins/i18n` → 动态 import `/api/plugins/client/<name>` → `setup(ctx)` |
88
+ | 注入 | 路由/工具/驱动/模板/处理器即时生效;设置描述符并入 `SystemConfigService` | 面板经 `ctx.ui.registerPanel` 注入页面插槽;`client:init` 钩子广播 |
89
+ | 运行 | `daq:sample` / `daq:frame` / `dcw:write` / `line:start\|stop` / `config:changed` / `event:<type>` / `*` | `event:<type>`(与 WS 同源)/ `page:change` / `i18n:changed` |
90
+ | 重载 | 状态文件变化 → 全量 dispose(逐个 `await`)→ 解绑 hooks → 清路由 → 重新装载 → 广播 `plugins:reloaded` | WS `plugins.reloaded` 即时同步,另有 15s 轮询兜底 → 停用插件 `ctx.dispose()` |
91
+ | 关机 | 逐插件执行 dispose 队列(含 KV 同步落盘)→ 广播 `server:close` | 页面 `pagehide` 自动 `ctx.dispose()` |
92
+
93
+ 热重载的几个事实:
94
+
95
+ - **触发源是状态文件**:宿主 `fs.watch` 监听 `plugins-state.json` 所在目录,另有 **10s mtime 轮询**兜底(Windows 上 `rename` 原子写可能丢事件)。`aw plugin enable|disable`、Web 开关、或直接触碰该文件都会触发,**约 1s 内**完成全量重装载。
96
+ - **改代码不需要重启进程**:重装载用 `import(entry + '?t=' + Date.now())` 打破 ESM 模块缓存,所以插件代码改动会在下一次重装载时生效。宿主没有独立的插件目录 watcher —— 改完代码后触碰 `plugins-state.json`(或 enable/disable 往返一次)就能让它立刻生效。
97
+ - **核心代码仍需重启**:`server/` 与 `shared/` 的改动不在插件热重载范围内。
98
+ - **竞态防护**:重装载进行期间状态文件再次变化(如 disable→enable 连击)时,去抖回调会撞上 in-flight 守卫;装载结束后宿主比对禁用集快照,有差异自动补跑一次,启停事件不丢失。
99
+ - **浏览器侧**:新启用的插件最迟 15s 注入(WS 可用时即时);停用插件立即卸载并回收其全部面板。
100
+
101
+ ## 四、插件设置与配置分组
102
+
103
+ ### 声明式字段(manifest `settings[]`)
104
+
105
+ ```js
106
+ settings: [
107
+ { key: 'base_url', type: 'string', default: 'http://127.0.0.1:8770',
108
+ labelKey: 'plugin.my-plugin.settings.base_url', // i18n 键(见 §5)
109
+ label: '服务地址(回退文案)', description: '保存即热生效' },
110
+ { key: 'max_turns', type: 'number', default: 0, min: 0, max: 2000, label: '最大轮数' },
111
+ { key: 'auto_enabled', type: 'boolean', default: false, label: '自动模式' },
112
+ { key: 'mode', type: 'select', default: 'a', options: ['a', 'b'], label: '模式' },
113
+ ],
114
+ ```
115
+
116
+ 校验器(`validatePluginSettings`)的硬约束 —— 任一条不满足,该条目被**跳过并告警**,其余条目照常装载:
117
+
118
+ | 约束 | 规则 |
119
+ |---|---|
120
+ | `key` | 必填,且匹配 `/^[A-Za-z0-9_-]+$/`(仅字母数字与 `-` `_`) |
121
+ | `type` | 必须是 `'string' \| 'number' \| 'boolean' \| 'select'` 之一 |
122
+ | `default` | **必填** —— 不给默认值的条目直接跳过 |
123
+ | `select` | 必须给 `options` 数组,且 `default` 必须在其中(比较按字符串) |
124
+ | `min` / `max` | 仅 `number` 生效(仍会被写进描述符,但对其他类型无意义) |
125
+ | `label` | 缺省回落 `key`;`labelKey` 存在时优先解析 i18n |
126
+ | `description` | 缺省为空串 |
127
+
128
+ 规范化后的描述符 `applies` 恒为 `'live'`(保存即热生效),键被强制编址为 **`plugins.<插件名>.<key>`** —— 与全局 schema 键同一编址空间。
129
+
130
+ ### 配置分组(manifest `configGroups[]` + `settings[].group`)
131
+
132
+ ```js
133
+ configGroups: [
134
+ { id: 'default', label: '连接', description: '后端地址与鉴权', order: 400 },
135
+ { id: 'advanced', label: '高级', collapsed: true },
136
+ ],
137
+ settings: [
138
+ { key: 'base_url', type: 'string', default: 'http://127.0.0.1:8770', group: 'default', label: '服务地址' },
139
+ { key: 'timeout_ms', type: 'number', default: 8000, group: 'advanced', label: '超时(ms)' },
140
+ ],
141
+ ```
142
+
143
+ - 分组 id 会被收敛进本插件命名空间:`default`(或写成插件名)映射为 `plugin-<插件名>`,其余声明 id `x` 映射为 `plugin-<插件名>-x`。两个插件用同一个 `network` 也不会互相覆盖。
144
+ - `settings[].group` 引用的是**声明时的原始 id**(`default` / `advanced`),不是已经加过前缀的 id。
145
+ - **未声明 `group` 的字段**落入本插件默认分区,id 为 `plugin-<插件名>`;若插件没有为这个默认 id 声明过标题,设置页显示的标题就是这个 id 本身(即 `plugin-<插件名>`)。想显示可读标题,就像上面那样声明一个 `{ id: 'default', label: '…' }` —— 两个内置插件都这么做。
146
+ - 分组会在插件卸载/停用时自动摘除,不残留空分区。
147
+ - 设置页里**没有**一个字面叫「插件」的配置分组:那是系统设置 → 运行配置里的插件管理清单(启停开关 + 健康检测),与插件自己的配置分区是两块 UI。
148
+
149
+ > 字段 `configGroups` 是宿主实际读取的名字(`host.mjs` 读 `def.configGroups`)。类型声明文件 `sdk/index.d.mts` 里写的是 `groups?`,与运行时不一致,以本文与代码为准。
150
+
151
+ ### 运行时注册(在 `setup` 里按条件扩展)
152
+
153
+ ```js
154
+ async setup(ctx) {
155
+ // 追加一个分组,并拿到收敛后的真实 id
156
+ const group = ctx.config.defineGroup({ id: 'rules', label: '自动规则', collapsed: true })
157
+ // 追加字段(等价于 manifest 的 settings[],但可以按条件注册)
158
+ ctx.config.defineField({
159
+ key: 'auto_rules', type: 'string', default: '', group: 'rules', label: 'JSON 规则',
160
+ })
161
+ ctx.logger.info(ctx.config.groups().map(g => g.id).join(','))
162
+ ctx.logger.info(ctx.config.fields().map(f => f.key).join(','))
163
+ // 摘除(removeGroup 收的是 defineGroup 返回的已命名空间化 id;removeField 收短 key)
164
+ if (group) ctx.config.removeGroup(group.id)
165
+ ctx.config.removeField('auto_rules')
166
+ }
167
+ ```
168
+
169
+ `defineGroup` / `defineField` 的校验规则与声明式完全一致(不合法返回 `null` 并告警);`removeGroup` / `removeField` 返回布尔值表示是否真的移除了。这些分组与字段随插件卸载自动摘除,已保存的值不会因为重注册而丢失。
170
+
171
+ ### 读取与持久化
172
+
173
+ - 读取:`ctx.config.get('plugins.my-plugin.base_url')`(每次调用都读合并后的有效值,保存即热生效);`ctx.config.all()` 拿全量快照。
174
+ - 订阅:`ctx.config.onChange(fn)` 等价于 `ctx.hooks.on('config:changed', fn)`。
175
+ - 运行时覆盖持久化在 `<配置根>/runtime-settings.json`;`PATCH /api/system/settings` 按同一份描述符校验,前端设置页按描述符渲染。
176
+ - 迁移:0.7.28 前写死在 `shared/config/schema.json` 的 `plugins.kb.*` / `plugins.diag.*` 已由插件声明取代;服务启动时一次性搬移旧覆盖到新键(新键未注册时保留旧键等下一次 pass,绝不丢数据)。
177
+
178
+ ## 五、插件 i18n(i18n.json)
179
+
180
+ ```json
181
+ {
182
+ "zh-CN": { "settings": { "base_url": "服务地址" }, "panel": { "title": "我的面板" } },
183
+ "en": { "settings": { "base_url": "Service URL" }, "panel": { "title": "My panel" } }
184
+ }
185
+ ```
186
+
187
+ - 装载期宿主解析插件根目录的 `i18n.json`(坏文件忽略,不阻断装载)。
188
+ - `GET /api/plugins/i18n` 汇编全部**已启用**插件的消息包(免鉴权;只放 UI 文案,**严禁放敏感信息**),返回 `{ i18n: { "<插件名>": { "<locale>": { … } } }, locales: ["zh-CN", "en"] }`。
189
+ - 浏览器 loader 拉取后:合并进 vue-i18n 命名空间 `plugin.<插件名>` —— 宿主组件(设置页 `labelKey`、面板 `titleKey`)直接解析;同时 `ctx.t(key)` 在插件自有的消息树上自解析(`ctx.t('panel.title')` 解析到 `plugin.my-plugin.panel.title`,未命中回落原键)。
190
+ - 语言切换时 loader 广播 `i18n:changed` 钩子;插件用 `ctx.hooks.on('i18n:changed', fn)` 接收(注意:它**不在** `ctx.on` 的投递面上)。
191
+ - manifest 暴露 `hasI18n` / `settingsCount` / `hasClient` 供前端展示。
192
+
193
+ ## 六、服务端 ctx 全参考
194
+
195
+ | 面 | 成员 | 说明 |
196
+ |---|---|---|
197
+ | 身份 | `ctx.name` / `ctx.scope` / `ctx.dir` / `ctx.sdkVersion` | `scope ∈ 'builtin' \| 'project' \| 'user'`;`dir` 为插件目录绝对路径 |
198
+ | 钩子 | `ctx.hooks.on / once / off / emit` | 每插件门面;热重载自动解绑,无需手动 `off` |
199
+ | 日志 | `ctx.logger.debug / info / warn / error` | 自动前缀 `[aw-plugins] [<插件名>]` |
200
+ | 配置 | `ctx.config.get / all / onChange / defineGroup / defineField / removeGroup / removeField / groups / fields` | 有效配置只读 + 变更订阅 + 运行时分区分字段注册(见 §4) |
201
+ | 存储 | `ctx.kv.get / set / all / bump` | 插件私有 KV;**没有 `reset()`**;内存态为准 + 200ms 防抖原子落盘 |
202
+ | 定时 | `ctx.timer.setInterval / setTimeout` | 自动进回收队列,关机与热重载都会清理 |
203
+ | 清理 | `ctx.onDispose(fn)` / `ctx.subscriptions.add(d)` | 与 `ctx.timer` 共用同一个宿主回收队列 |
204
+ | 路由 | `ctx.route(method, path, handler)` | 挂 `/api/plugins/<插件名><path>`(exact-match);**返回 boolean** |
205
+ | 平台 | `ctx.api` | 平台 REST 客户端(自环 origin;自动解信封;鉴权端点需 `ctx.api.setToken(token)`) |
206
+ | 网络 | `ctx.http.get(url, opt)` / `ctx.http.post(url, body, opt)` | 出站 fetch;守卫**只校验协议**(仅 http/https),不限制 host;默认超时 8s;`headers` 透传 |
207
+ | 事件 | `ctx.events.on(type, fn)` / `ctx.events.off(type, fn)` | scene 实时事件糖:内部订阅 `event:<type>`(见 §7) |
208
+ | 路径 | `ctx.paths.home / configRoot / dataDir`;`ctx.dataDir` | `ctx.dataDir` 即本插件 KV 目录 `<配置根>/data/plugins/<插件名>` |
209
+ | 数采 | `ctx.daq.registerDriver / registerProcessor / registerTemplate / onFrame / onSample / query / nodes` | 驱动、下沉处理器、节点模板注册 + 时序查询 + 节点元数据快照 |
210
+ | 写控 | `ctx.dcw.registerWriteDriver(driver)` | 写驱动注入(与数采读驱动对称):契约 `{ kind, available(), write(input), test(cfg), read?(input), meta? }`;热重载停用即失效 |
211
+ | 工具 | `ctx.omp.registerTool({ name, label?, description, parameters, roles?, handler })` | Agent 工具注入;`roles` 仅 `'lead'` 与 `'worker'`(见 §10) |
212
+ | 服务 | `ctx.services.names()` / `.get(name)` / `.provide(name, getter)` | 运行时对象面:`get('daq' \| 'lines' \| 'channels' \| 'plugins')`;`provide` 自动加 `<插件名>.` 前缀 |
213
+ | 孪生 | `ctx.twin.registerPhysicsProvider / registerScenePack / registerObjectiveProfile / registerTrainingAdapter / registerSolverAdapter`;`listProviders / getProviderHealth / resolveProvider / validateProvider / retireProvider / isRegistryAvailable` | 混合孪生 **Provider Registry** 桥:注册可热替换的工业场景物理主干 / 场景包 / 求解器(见下节) |
214
+ | 权限 | `ctx.permissions.lineMode / visibleLineIds / listGrants / setGrants` | 产线授权查询与管理 |
215
+
216
+ ### 混合孪生 Provider 插件(`ctx.twin`)
217
+
218
+ `ctx.twin` 是**混合孪生 Provider Registry** 的插件面:把工业场景的物理主干、场景包与求解器注册进来。
219
+ `twin_scene_read` / `twin_snapshot_create` / `twin_trial_run` / `mpc_optimize` 按 `SceneContract.physicsProfileId`
220
+ 解析 Provider(解析不到时回退系统自带 `twin-injection-default`),因此**换场景不需要改工具与频道**。
221
+
222
+ | 注册面 | 载荷 | 说明 |
223
+ |---|---|---|
224
+ | `registerPhysicsProvider(provider)` | `PhysicsProviderManifest` + `initialize` / `step` / `simulate` / `evaluateConstraints`,可选 `validateScene` / `calibrate` / `designSafeExperiment` / `estimateUncertainty` / `exportArtifacts` / `health` | 物理主干(灰箱 / 白箱 / ROM 均可);`apiVersion` 必须为 `twin-provider.v1` |
225
+ | `registerScenePack(pack)` | `{ sceneKind, sceneSchemaVersion, compile?, discover?, constraints?, objectives?, datasetSchema?, metadata? }` | 场景包:把现场节点与配方编译成 `SceneContract` |
226
+ | `registerObjectiveProfile(profile)` | 目标与权重 | MPC 目标面 |
227
+ | `registerTrainingAdapter(adapter)` / `registerSolverAdapter(adapter)` | 训练 / 求解适配器 | 外部求解器(ONNX / ROM / 第三方求解器) |
228
+ | `listProviders(filter?)` · `getProviderHealth(id, version?)` · `resolveProvider(id, version?)` · `validateProvider(id, version?)` · `retireProvider(id, version?)` · `isRegistryAvailable()` | — | 查询、健康、解析、校验与退役 |
229
+
230
+ **清单要点**:`providerId` / `version` / `apiVersion` / `sceneKinds[]` / `backend`
231
+ (`typescript` | `pytorch` | `python` | `onnx` | `rom` | `external-solver`)/ 四类变量表
232
+ (`stateVariables` / `controlVariables` / `disturbanceVariables` / `observationVariables?`)/
233
+ `parameterPriors` / `capabilities`(`onlineStep` / `rollout` / `calibration` / `uncertainty` / `externalSolver` / `mpc`)/
234
+ `artifactContract`。
235
+
236
+ **代际热替换**:生命周期 `DISCOVERED → VALIDATED → REGISTERED → READY → DRAINING → RETIRED`(失败为 `FAILED`)。
237
+ 热重载按 **generation** 装载新代并排空旧代:试验与 MPC 通过租约持有旧代,排空期间**在飞工作不被作废**;
238
+ `retireProvider` 等引用归零后才真正下线。
239
+
240
+ **最小示例**(系统自带注塑 Provider 走的就是这套外部契约,见 `server/plugins-builtin/twin-injection-default/index.mjs`):
241
+
242
+ ```js
243
+ export default {
244
+ name: 'my-injection-provider',
245
+ version: '1.0.0',
246
+ auth: 'none',
247
+ async setup(ctx) {
248
+ const core = await ctx.services.get('twinCore')
249
+ const provider = core.createInjectionProvider() // 换成你自己的物理主干
250
+ ctx.twin.registerPhysicsProvider(provider)
251
+ ctx.twin.registerScenePack({
252
+ sceneKind: 'injection',
253
+ sceneSchemaVersion: '1.0.0',
254
+ compile: () => core.defaultInjectionScene('my-injection-provider'),
255
+ })
256
+ ctx.logger.info(`已注册 ${provider.manifest.physicsModelId}@${provider.manifest.version}`)
257
+ },
258
+ }
259
+ ```
260
+
261
+ **装在哪里**:与其它插件同址(见 §1 三作用域)——`~/.AgentWorkShop/plugins/<插件名>/`(user)、
262
+ `<repo>/.AgentWorkShop/plugins/<插件名>/`(project)、`server/plugins-builtin/<插件名>/`(随包分发)。
263
+ 停用或热重载会重新装载 / 排空对应 generation,**无需重启服务**。
264
+
265
+ ### 通信协议插件(自定义接口连接方式)
266
+
267
+ `ctx.daq.registerDriver` / `ctx.dcw.registerWriteDriver` 是**协议接入点**:串口、其他 PLC 协议、
268
+ 私有总线的连接实现都从这里注入,主链路(采样循环 / 写控网关 / 前端表单)零改动。
269
+
270
+ ```js
271
+ ctx.daq.registerDriver({
272
+ kind: 'serial', // 自定义协议 kind(与内置冲突时插件覆盖并告警)
273
+ async available() { return true }, // 协议栈包探测(缺失时 UI 显示「未安装」)
274
+ async sample({ driverConfig }) { return 25.3 }, // 读数(标量或 v2 帧信封)
275
+ async test(driverConfig) { return { ok: true, message: '连接成功', sampleValue: 25.3 } },
276
+ meta: { // 自描述(前端「添加节点」下拉 + 动态参数表单)
277
+ label: '串口 Serial(RS-232/485)',
278
+ status: 'real',
279
+ configFields: [{ key: 'path', label: '串口路径', type: 'string', required: true, placeholder: 'COM3' }],
280
+ },
281
+ })
282
+ ```
283
+
284
+ 要点:
285
+ - 驱动目录经 `GET /api/workshop/daq`(读)与 `GET /api/workshop/dcw`(写)的 `drivers` 字段下发,
286
+ 前端数采/写控页据此渲染插件协议与参数表单(带 ⌁ 徽标);不带 `meta` 的驱动只出现在可用性里;
287
+ - 热重载先清空全部插件驱动再重装载:**停用/卸载的协议驱动立即失效**,不会残留到重启;
288
+ - 内置示例:`server/plugins-builtin/serial-bridge`(串口 Modbus RTU + ASCII 行协议,含读/写驱动、
289
+ `health`/`ports`/`probe` API、前端面板与 `serial_ports` Agent 工具)——新协议插件建议以它为模板。
290
+
291
+ ### KV 落在哪里
292
+
293
+ `<configRoot>/data/plugins/<插件名>/kv.json` —— **不在插件目录里**。写入以内存为准,200ms 防抖后 `tmp + rename` 原子落盘;关机与热重载时取消挂起的防抖并同步落盘。`ctx.kv` 只有 `get / set / all / bump` 四个方法。
294
+
295
+ ```js
296
+ ctx.kv.set('threshold', 180) // 写(200ms 后落盘)
297
+ ctx.kv.get('threshold') // 读(未写过为 undefined)
298
+ ctx.kv.bump('alarms') // +1,返回新值;bump('alarms', -1) 递减
299
+ ctx.kv.all() // 全量浅拷贝快照
300
+ ```
301
+
302
+ ## 七、事件参考(服务端)
303
+
304
+ 事件经 HookBus 分发,**监听器按注册序串行 await**,同一个监听器收到的 payload 始终是**同一个未被改写的对象** —— 不是 waterfall(只有最后一个非 `undefined` 的返回值被保留,宿主不使用它),v1 也没有 veto / 拦截能力。单个监听器抛错被隔离并计数:成功清零,**连续失败 8 次自动摘除**(熔断)。
305
+
306
+ ### 生命周期与平台事件
307
+
308
+ | 事件 | 时机 | payload |
309
+ |---|---|---|
310
+ | `plugin:host:init` | 全部插件 setup 完成后(一次性) | `{ plugins: string[], failures: number }` |
311
+ | `plugins:reloaded` | 热重载收尾 | `{ plugins: <manifest> }` |
312
+ | `config:changed` | `runtime-settings.json` / 设置页变化 | `{ type, changed: string[], effective, sources }` —— **没有 `at` 字段** |
313
+ | `server:close` | nitro close,逐插件 dispose 之后 | `{ at }` |
314
+
315
+ ### 业务事件
316
+
317
+ | 事件 | 时机 | payload |
318
+ |---|---|---|
319
+ | `daq:sample` | 节点采样经管线汇聚后的**下发级**出口(与 WS `daq.reading` 同点同节拍,按 `publishIntervalMs` 门控) | `{ nodeId, templateRef, value, state, at, lineId }` |
320
+ | `daq:frame` | 多形态帧(向量/图像)入账后(只含元数据/指标/预览,不含 blob) | `{ nodeId, templateRef, kind, at, lineId, preview?, metrics, thumbUrl?, state }` |
321
+ | `dcw:write` | 写控 ACK 落账后(含 10s 同值去重) | `{ nodeId, name, eng, prevValue, ok, source, lineId, at }`;`source ∈ manual \| recipe \| agent \| rollback` |
322
+ | `line:start` | 批次窗口开启 | `{ lineId, runId, recipeId, productName }` |
323
+ | `line:stop` | 批次窗口关闭 | `{ lineId, runId }` |
324
+ | `event:<scene-type>` | 任一 `broadcastSceneEvent(type, payload)`,与浏览器 WS 完全同源 | 事件自身 payload |
325
+
326
+ ### 通配符与 scene 事件
327
+
328
+ 服务端通配写法是**裸星号 `'*'`**,回调收到的是 `{ type, payload }` 包装:
329
+
330
+ ```js
331
+ ctx.hooks.on('*', ({ type, payload }) => {
332
+ ctx.logger.debug('全事件审计', type)
333
+ void payload
334
+ })
335
+ ```
336
+
337
+ `ctx.hooks.on('event:*', fn)` 是**错的** —— 永远不会触发。要按类型订阅 scene 事件,用 `ctx.events`,它会替你补 `event:` 前缀:
338
+
339
+ ```js
340
+ ctx.events.on('daq.node.changed', (p) => ctx.logger.debug('节点变更', p?.op))
341
+ ctx.events.on('daq.alarm.changed', (p) => ctx.logger.info('告警状态', p?.nodeId, p?.recovered))
342
+ ```
343
+
344
+ 常见 scene 事件:`daq.reading`、`daq.frame`、`daq.alarm`、`daq.alarm.changed`、`daq.node.changed`、`daq.controller`、`daq.template.changed`、`dcw.node.changed`、`device.created|updated|deleted`、`ops.log`、`permissions.changed`、`plugins.reloaded`、`aml.job|dataset|model`。
345
+
346
+ ### 权限变更
347
+
348
+ 权限变更到达插件总线时是 scene 事件 `permissions.changed`(原始总线上的名字是 `event:permissions.changed`)。`ctx.hooks.on('permissions:changed', …)` **永远不触发**,正确写法:
349
+
350
+ ```js
351
+ ctx.events.on('permissions.changed', (p) => ctx.logger.info('授权变更', p?.userId))
352
+ ```
353
+
354
+ ### 配置变更
355
+
356
+ ```js
357
+ ctx.hooks.on('config:changed', (p) => {
358
+ ctx.logger.info('配置已变更', p.changed)
359
+ ctx.logger.info('当前主题色', ctx.config.get('theme.primaryColor'))
360
+ })
361
+ // 等价糖:ctx.config.onChange(fn)
362
+ ```
363
+
364
+ ## 八、浏览器 client.mjs(ctx 面参考)
365
+
366
+ 客户端入口必须**在 manifest 里声明** `client: './client.mjs'` —— 仅存在文件是不够的。loader 从 `/api/plugins/client/<插件名>` 取脚本后动态 import 并调用 `setup(ctx)`。
367
+
368
+ ```js
369
+ export function setup(ctx) {
370
+ let samples = 0
371
+ const counter = ctx.el('strong', {}, ['0'])
372
+
373
+ // scene 事件:type 传事件名本身;收全部 scene 事件用字面量 'event:*'
374
+ ctx.on('daq.reading', () => { samples += 1; counter.textContent = String(samples) })
375
+
376
+ // 生命周期钩子只能走 ctx.hooks.on(不在 ctx.on 的投递面上)
377
+ ctx.hooks.on('i18n:changed', ({ locale }) => ctx.log.info('语言切换:', locale))
378
+
379
+ ctx.ui.registerPanel({
380
+ slot: 'plugins.page', // 插槽名(见下)
381
+ name: 'my-panel', // 同插件内唯一
382
+ titleKey: 'panel.title', // 解析 plugin.my-plugin.panel.title(或用静态 title)
383
+ order: 10,
384
+ mount(el) { // el = 面板容器(标题由插槽渲染)
385
+ const box = ctx.el('div', {}, ['样本数:', counter])
386
+ el.append(box)
387
+ const timer = setInterval(() => { counter.textContent = String(samples) }, 5000)
388
+ return () => { clearInterval(timer); box.remove() } // 清理函数:面板卸载时调用
389
+ },
390
+ })
391
+
392
+ ctx.log.info('客户端已注入')
393
+ }
394
+ ```
395
+
396
+ | 成员 | 说明 |
397
+ |---|---|
398
+ | `ctx.name` / `ctx.sdkVersion` | 插件名 / 客户端 SDK 版本 |
399
+ | `ctx.hooks` | 真实 HookBus:`client:init` / `page:change` / `i18n:changed` / `client:destroy` |
400
+ | `ctx.on(type, fn)` | scene 事件订阅(type 传事件名本身,内部装到 `event:<type>`);只有字面量 `'event:*'` 是通配;返回解绑函数 |
401
+ | `ctx.fetch(path, opt)` | 同源平台 API 助手(自动带 cookie token、解 `{code,data}` 信封、非 2xx 抛错) |
402
+ | `ctx.el(tag, attrs, children)` | DOM 助手;`style` 走 `cssText`,`class` 走 `className`,`onXxx` 自动 `addEventListener` |
403
+ | `ctx.mount(target, node)` / `ctx.root()` | 挂到选择器/元素(缺失时挂 `ctx.root()`)/ 插件私有挂载点 `#aw-plugin-<name>` |
404
+ | `ctx.ui.registerPanel(entry)` / `ctx.ui.slots` | 向命名插槽注册面板,返回注销函数;`slots` 为已知插槽名 |
405
+ | `ctx.t(key, params?)` | 插件命名空间翻译(`plugin.<name>.<key>`) |
406
+ | `ctx.locale` | 当前界面语言 |
407
+ | `ctx.log.info / warn / error` | 带 `[aw-plugin:<name>]` 前缀的 console |
408
+ | `ctx.dispose()` | 卸载:广播 `client:destroy` → 回收订阅 → 移除 `root()`(幂等) |
409
+
410
+ ### 通配与不可达的订阅(高频坑)
411
+
412
+ | 写法 | 结果 |
413
+ |---|---|
414
+ | `ctx.on('daq.reading', fn)` | 正确:订阅 scene 事件 `daq.reading` |
415
+ | `ctx.on('event:*', fn)` | 正确:唯一通配写法,收全部 scene 事件 |
416
+ | `ctx.on('*', fn)` | **死订阅**:不会触发 |
417
+ | `ctx.on('event:line.start', fn)` | **死订阅**:只订阅同名 scene 事件 `event:line.start`,而它不存在 |
418
+ | `ctx.on('daq:sample', fn)` | **死订阅**:服务端钩子不过桥到浏览器 |
419
+ | `ctx.hooks.on('page:change', fn)` | 正确:生命周期钩子走 `ctx.hooks` |
420
+ | `ctx.on('client:init', fn)` | **死订阅**:生命周期钩子不在 `ctx.on` 面上 |
421
+
422
+ 服务端钩子(`daq:sample`、`daq:frame`、`dcw:write`、`line:start\\|stop`)**永远不会到达浏览器**;浏览器能收到的只有 scene 事件(经 TownBus/WS 桥)。反过来,`page:change` / `i18n:changed` 也只存在于浏览器侧。
423
+
424
+ ### 面板与页面插槽
425
+
426
+ 宿主页面在任意位置放 `<workshop-plugin-slot slot-name="…" />` 即接收注入;`ctx.ui.slots` 当前为:
427
+
428
+ | 插槽 | 落点 |
429
+ |---|---|
430
+ | `plugins.page` | 插件管理页(默认落点) |
431
+ | `settings.plugins` | 系统设置 → 运行配置 → 插件管理区下方 |
432
+ | `dashboard.widgets` | 仪表盘页尾 |
433
+
434
+ `registerPanel` 返回 `unregisterPanel` 注销函数;面板的 `mount(el)` 可以返回清理函数(面板卸载时调用),也可以抛错 —— 单面板异常由插槽隔离,不影响其他面板与页面。
435
+
436
+ ### 卸载语义
437
+
438
+ - `ctx.dispose()` 由 **`pagehide`** 触发(导航离开 / 进入 bfcache;切标签页**不**触发)。它会广播 `client:destroy`、回收插件自己的订阅、移除 `root()`。
439
+ - `ctx.dispose()` 本身**不注销面板** —— 面板回收由 loader 在停用/热重载时调用 `unregisterPlugin(name)` 完成。
440
+ - 热通道双保险:WS `plugins.reloaded` 事件(即时)+ 15s 轮询 diff。
441
+
442
+ ## 九、路由与鉴权
443
+
444
+ `ctx.route(method, path, handler)` 立即注册并返回 **boolean**;manifest 里的 `routes[]` 在 `setup` 返回之后才注册。两者最终都挂在同一个路由表上:
445
+
446
+ ```
447
+ GET /api/plugins/<插件名>/health ← ctx.route('GET', '/health', handler)
448
+ ← routes: [{ method: 'GET', path: '/health', handler }]
449
+ ```
450
+
451
+ - 匹配是 **exact-match**,路径统一以 `/` 开头;没有通配段、没有子路由匹配。
452
+ - handler 收到 h3 的 `event`;JSON body 已由平台转发层预读并挂在 **`event.awBody`** 上(插件无需导入 h3)。
453
+ - handler 的返回值由 nitro 序列化为 JSON;抛错会变成 500 信封(带插件归属的日志),不裸传堆栈。
454
+ - **鉴权由声明式 `auth` 字段统一执行**,在进入 handler **之前**校验,对 `routes[]` 与 `ctx.route()` 一视同仁:
455
+
456
+ | `auth` | 行为 |
457
+ |---|---|
458
+ | `'none'`(默认) | 不校验,直接进入 handler |
459
+ | `'user'` | 需要有效用户 token,否则 401 |
460
+ | `'admin'` | 需要管理员,否则 401 |
461
+ | `'agent-or-user'` | 接受 Agent 身份或用户 token |
462
+
463
+ **不要把鉴权写进 handler**:`resolveUser(event)` 不可从插件导入,`ctx` 上也没有它。要鉴权就声明 `auth`。
464
+
465
+ ```js
466
+ ctx.route('GET', '/report', () => ({ plugin: ctx.name, at: new Date().toISOString() }))
467
+
468
+ ctx.route('POST', '/threshold', (event) => {
469
+ const v = Number(event.awBody?.threshold) // 宿主已预读 JSON body
470
+ if (!Number.isFinite(v)) return { ok: false, error: 'threshold 必须是数字' }
471
+ ctx.kv.set('threshold', v)
472
+ return { ok: true, threshold: v }
473
+ })
474
+ ```
475
+
476
+ ## 十、工具与团队开关
477
+
478
+ `ctx.omp.registerTool(def)` 注册的工具出现在全部 harness 的工具面上(omp 经 RPC `set_host_tools` 下发 / 其余引擎经 MCP 桥 `tools/list` / pi 经工具文件 / mock 经 REST invoke 直调),注册表变化会**热重发**给在跑的会话,无需重启或重 spawn 子进程。
479
+
480
+ ```js
481
+ ctx.omp.registerTool({
482
+ name: 'sensor_log',
483
+ label: '传感器标定',
484
+ description: '查询/登记传感器标定结论',
485
+ parameters: { type: 'object', properties: { sensor: { type: 'string' } }, required: ['sensor'] },
486
+ roles: ['lead', 'worker'], // 仅这两个字面量;缺省=两者都可用
487
+ handler: async (args, agent) => ({ text: `${agent.role}@${agent.channelId}: ${args.sensor}` }),
488
+ })
489
+ ```
490
+
491
+ 参数 schema 里**不要开 `url` / `host` 这类注入口** —— 插件工具的参数直接来自模型,任何"让模型指定目标地址"的字段都会变成 SSRF 面。
492
+
493
+ ### 团队 / Channel 级开关
494
+
495
+ 全局启停之外,每个团队(Channel)还有独立的插件开关组(由 `channel_plugins` 表承载):
496
+
497
+ - **建队时勾选**:`POST /api/workshop/teams` 接受 `plugins: [{ name, enabled }]`,以 team id 为键落库,部署时传导到 Channel;
498
+ - **随时切换**:`GET|PUT /api/workshop/channels/:id/plugins`、`GET|PUT /api/workshop/teams/:id/plugins`(body 为 `{ plugins: [{ name, enabled }] }`,全量替换语义,未知/停用插件名忽略);
499
+ - **语义**:无显式行 = 未配置 → 全部启用插件对该团队可见(向后兼容);写入显式行后按行过滤 —— **被关闭插件的工具不注入该团队的 Agent,dispatch 同源拒绝**;
500
+ - **前端**:workshop teams 页(创建勾选 + 团队弹层)。
501
+
502
+ ## 十一、完整示例
503
+
504
+ ```js
505
+ // index.mjs —— 服务端入口(零导入依赖;ctx 由宿主注入)
506
+ export default {
507
+ name: 'my-plugin',
508
+ version: '1.0.0',
509
+ description: '示例:越限计数 + 自有 API + 设置分区 + Agent 工具',
510
+ auth: 'user',
511
+ client: './client.mjs',
512
+ configGroups: [
513
+ { id: 'default', label: '我的插件', description: '基础配置', order: 500 },
514
+ { id: 'advanced', label: '高级', collapsed: true },
515
+ ],
516
+ settings: [
517
+ { key: 'threshold', type: 'number', default: 180, min: 0, max: 5000, group: 'default',
518
+ label: '告警阈值', description: '保存即热生效' },
519
+ { key: 'endpoint', type: 'string', default: 'http://127.0.0.1:8080', group: 'advanced',
520
+ label: '外部服务地址' },
521
+ ],
522
+ routes: [
523
+ { method: 'GET', path: '/health', handler: () => ({ ok: true }) },
524
+ ],
525
+
526
+ async setup(ctx) {
527
+ ctx.logger.info(`装载完成(scope=${ctx.scope}, sdk=${ctx.sdkVersion})`)
528
+
529
+ const threshold = () => Number(ctx.config.get('plugins.my-plugin.threshold')) || 180
530
+
531
+ // 1) 数采下发级样本:越限计数落插件私有 KV
532
+ ctx.hooks.on('daq:sample', (s) => {
533
+ if (typeof s?.value === 'number' && s.value > threshold())
534
+ ctx.kv.bump(`alarm:${s.nodeId}`)
535
+ })
536
+
537
+ // 2) scene 事件订阅(ctx.events 自动补 event: 前缀)
538
+ ctx.events.on('daq.alarm', (a) => ctx.logger.warn('告警', a?.nodeId))
539
+ ctx.events.on('permissions.changed', (p) => ctx.logger.info('授权变更', p?.userId))
540
+
541
+ // 3) 全事件审计:服务端通配是裸 '*',回调收 { type, payload }
542
+ ctx.hooks.on('*', ({ type }) => ctx.logger.debug('event', type))
543
+
544
+ // 4) setup 之后才会注册 routes[];这里用 ctx.route 立即注册(返回 boolean)
545
+ ctx.route('POST', '/threshold', (event) => {
546
+ const v = Number(event.awBody?.threshold)
547
+ if (!Number.isFinite(v)) return { ok: false, error: 'threshold 必须是数字' }
548
+ ctx.kv.set('threshold', v)
549
+ return { ok: true, threshold: v }
550
+ })
551
+
552
+ // 5) 定时器 + 清理:同一个宿主回收队列,关机与热重载都会执行
553
+ ctx.timer.setInterval(() => ctx.kv.set('heartbeat', new Date().toISOString()), 5000)
554
+ ctx.onDispose(() => ctx.logger.info('插件已清理'))
555
+
556
+ // 6) Agent 工具(roles 仅 'lead' | 'worker')
557
+ ctx.omp.registerTool({
558
+ name: 'my_alarm_report',
559
+ description: '读取本插件记录的越限告警计数',
560
+ parameters: { type: 'object', properties: { nodeId: { type: 'string' } }, required: ['nodeId'] },
561
+ roles: ['lead', 'worker'],
562
+ handler: async (args, agent) => ({
563
+ text: `${args.nodeId} 告警 ${ctx.kv.get(`alarm:${args.nodeId}`) ?? 0} 次(by ${agent.role})`,
564
+ }),
565
+ })
566
+ },
567
+ }
568
+ ```
569
+
570
+ `client.mjs` 见 §8;`i18n.json` 见 §5。装到哪个作用域、怎么启停见 §1。
571
+
572
+ ## 十二、故障排查
573
+
574
+ | 现象 | 原因 / 处理 |
575
+ |---|---|
576
+ | 改了插件代码没生效 | 宿主没有插件目录 watcher:触碰 `<home>/plugins-state.json` 或 `aw plugin enable/disable` 往返一次触发重载(重载会带 `?t=` 破缓存);核心 `server/`、`shared/` 改动仍需重启进程 |
577
+ | 重建同名插件后路由 404 | 此前 disable 过的插件名在 `<home>/plugins-state.json` 里留有禁用标记,重建目录不会自动恢复装载 —— 重建后必须显式 `aw plugin enable <name>`(实测踩过) |
578
+ | 装载失败看不到 | `aw plugin list` **不显示**装载失败。用 `GET /api/workshop/plugins`(返回 `{ plugins, failures, initedAt }`,**没有 `{code,data}` 信封**),或看启动日志里的 `[aw-plugins] 装载失败 …` |
579
+ | 插件路由 404 | exact-match;检查 method 与 path 前导 `/`,以及插件是否处于启用态(停用插件的路由已从路由表移除) |
580
+ | 插件路由 401 | 入口声明了 `auth: 'user' \| 'admin' \| 'agent-or-user'`,请求未带有效凭据;开放接口才用 `auth: 'none'` |
581
+ | 客户端面板没出现 | 浏览器 console 看 `[aw-plugins]` 告警;确认 manifest `hasClient: true`(即 manifest 里声明了 `client:'./client.mjs'`)且插件 `enabled !== false` |
582
+ | 客户端订阅不触发 | 检查是不是踩了 §8 的坑(`ctx.on('*')`、`ctx.on('event:line.start')`、`ctx.on('daq:sample')`,或把生命周期钩子交给 `ctx.on`) |
583
+ | 设置项没渲染 | 声明里缺 `default` 会被跳过并告警;`select` 的 `default` 必须在 `options` 里;`key` 只允许字母数字与 `-` `_` |
584
+ | 设置值改了没生效 | 确认读的是 `ctx.config.get('plugins.<插件名>.<key>')`(短 key 读不到) |
585
+ | `permissions:changed` 钩子不触发 | 该名字不存在;用 `ctx.events.on('permissions.changed', fn)` |
586
+ | KV 数据"丢了" | KV 在 `<配置根>/data/plugins/<插件名>/kv.json`,不在插件目录;写入 200ms 防抖落盘,强杀进程会有极小丢失窗口 |
587
+ | `ctx.api` 401 | 鉴权端点需 `ctx.api.setToken(token)`;免鉴权端点(manifest / ping)无需 |
588
+
589
+ **信任模型**:插件是任意 node 代码,与 aw commands 同级 —— 只安装/启用你信任的插件。
590
+
591
+ ### 已知边界(有意为之,不是缺陷)
592
+
593
+ - **钩子是观察语义**:v1 没有 veto / 拦截 / 改写能力,写控联锁完整性优先。
594
+ - **`ctx.http` 守卫只校验协议**(仅 http/https),**不限制 host**;需要白名单请在插件内自行校验(内置 `diag-bridge` / `rag-bridge` 就是这么做的)。
595
+ - **`ctx.t(key, params)` 的 `params` 当前被忽略**(不做插值);需要拼字符串请在插件里自己做。
596
+ - **`ctx.kv` 没有 `reset()`**,只有 `get / set / all / bump`。
597
+ - **服务端与浏览器的订阅面不互通**:服务端钩子不过桥,浏览器事件也不上服务端。
598
+ - **浏览器新启用插件注入延迟 ≤15s**(WS 可用时即时)。
599
+ - **`server:close` / `onDispose` 依赖优雅关闭信号**,Windows 强杀进程不触发。
600
+ - **`aw plugin list` 只做目录扫描**,不反映装载失败与运行态健康。
601
+ - **协议插件的原生栈与宿主同进程**:serial-bridge 的 RTU 帧机为自研实现(单 serialport 原生栈;弃用 modbus-serial —— 其包装层在 dev 模式实测触发 V8 原生崩溃)。已知边界:**`aw dev` 进程内,串口事务「写→超时→关闭」序列可能触发 bindings-cpp 的 V8 原生崩溃**(HandleScope fatal,JS 层不可捕获,与具体串口无关);**生产模式(`aw start`)不受影响 —— 已实测同一序列在生产下诚实返回超时且服务存活**,纯打开(ASCII 探针)在 dev 下同样正常。开发期连接真实硬件请知悉此风险;对稳定性要求极高的部署可把串口网关放进独立进程(参考 plc-node-simulator 的子进程模式)。
602
+
603
+ ## 十三、发布前验证清单
604
+
605
+ 1. `aw plugin list` 三个作用域都能看到;C 端插件显示 `+client`;启停开关往返后路由/工具/面板同步生灭(连击不丢事件)。
606
+ 2. `GET /api/workshop/plugins` 的 `failures` 为空;`GET /api/plugins/manifest` 的 `settingsCount` / `hasClient` / `hasI18n` 与声明一致。
607
+ 3. 设置页出现本插件的配置分区(未声明分组的字段落在 `plugin-<插件名>` 分区),改值后 `ctx.config.get('plugins.<插件名>.<key>')` 立即读到新值。
608
+ 4. 语言切换:面板标题/文案跟随;`i18n:changed` 清理函数无泄漏。
609
+ 5. 工具经 `GET /api/workshop/agent-tools/list` 可见;参数里没有 `url` / `host` 注入口;团队开关关闭后工具消失且 dispatch 拒绝。
610
+ 6. 触发一次热重载(enable/disable 往返),确认 `plugins:reloaded` 到达插件、KV 与定时器无泄漏。