agentworkshop 0.8.0 → 0.8.1

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 (396) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +123 -0
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +123 -0
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/{DJJDigim2.js → -FhgRqJl2.js} +1 -1
  5. package/.output/public/_nuxt/{CGk_VUhO2.js → 0qvcO_KM2.js} +1 -1
  6. package/.output/public/_nuxt/26OL4Ao82.js +1 -0
  7. package/.output/public/_nuxt/{sBDZymdy2.js → 2Kwo_j9G2.js} +1 -1
  8. package/.output/public/_nuxt/{BqYVLAcm.js → 2v5GdspM.js} +1 -1
  9. package/.output/public/_nuxt/{DkQBMVTs2.js → 8M7wFbEN2.js} +1 -1
  10. package/.output/public/_nuxt/{DtiY69xi2.js → 8SZLbrI42.js} +1 -1
  11. package/.output/public/_nuxt/{DF32f5EL2.js → B2NbzUau2.js} +1 -1
  12. package/.output/public/_nuxt/{CwZW1ZCe2.js → B4JlRHBB2.js} +1 -1
  13. package/.output/public/_nuxt/{BQOn0q6Y.js → B6C4WofF.js} +1 -1
  14. package/.output/public/_nuxt/{BC7W6lNm.js → B6UwtJ1a.js} +1 -1
  15. package/.output/public/_nuxt/{BfQ-ptH0.js → B8HFUsMH.js} +1 -1
  16. package/.output/public/_nuxt/{DzBbYWrw2.js → BBB_j2LU2.js} +1 -1
  17. package/.output/public/_nuxt/BCLUwdP52.js +1 -0
  18. package/.output/public/_nuxt/{CLxmY3Rh.js → BK4wbfGS.js} +1 -1
  19. package/.output/public/_nuxt/{BRMVDfPl2.js → BKidykmV2.js} +1 -1
  20. package/.output/public/_nuxt/BPUQZ9Lq2.js +8 -0
  21. package/.output/public/_nuxt/BRYBzVMJ.js +1 -0
  22. package/.output/public/_nuxt/{Bj5sjA5O.js → BRci9D_l.js} +1 -1
  23. package/.output/public/_nuxt/{Dmgqz2np2.js → BVGzwAxr2.js} +1 -1
  24. package/.output/public/_nuxt/BVg2R2VB2.js +1 -0
  25. package/.output/public/_nuxt/{C3aUN4Vp2.js → BW2uTUx52.js} +1 -1
  26. package/.output/public/_nuxt/{B5FKaMM02.js → BY3Lbz3h2.js} +1 -1
  27. package/.output/public/_nuxt/{DIwmMa_7.js → BYzim_Bn.js} +1 -1
  28. package/.output/public/_nuxt/{D8xUsQGt.js → B_Obcbiu.js} +1 -1
  29. package/.output/public/_nuxt/BaYDgyaR.js +3 -0
  30. package/.output/public/_nuxt/{DZJ11BTI.js → BbACaREb.js} +1 -1
  31. package/.output/public/_nuxt/{BJrj5JVe2.js → BcosvNXb2.js} +1 -1
  32. package/.output/public/_nuxt/{B_-vAvzb.js → BfeXib9G.js} +1 -1
  33. package/.output/public/_nuxt/{CeLqojCJ.js → BfgTar9L.js} +1 -1
  34. package/.output/public/_nuxt/BfvuWqSa.js +1 -0
  35. package/.output/public/_nuxt/{D8r8PNQa2.js → BiZWwdcD2.js} +1 -1
  36. package/.output/public/_nuxt/{DIFkTkdS.js → BkEokGX5.js} +1 -1
  37. package/.output/public/_nuxt/{CJSohaqk2.js → BklGqEto2.js} +2 -2
  38. package/.output/public/_nuxt/{DkpmSnHX.js → Bko5adbu.js} +1 -1
  39. package/.output/public/_nuxt/{DTQTGA6v2.js → BmBlIIJo2.js} +1 -1
  40. package/.output/public/_nuxt/{D_NjL-Hz.js → Bmvt9ydE.js} +1 -1
  41. package/.output/public/_nuxt/{Cp4r6Eiz.js → BoyuIoSm.js} +1 -1
  42. package/.output/public/_nuxt/{62J4vljm.js → Bq-tmkst.js} +1 -1
  43. package/.output/public/_nuxt/{BMMoqi94.js → BqFaZ4kS.js} +1 -1
  44. package/.output/public/_nuxt/BsJYieAL2.js +1 -0
  45. package/.output/public/_nuxt/{DD4J2Otc.js → BtZKe9ZV.js} +1 -1
  46. package/.output/public/_nuxt/{BnpY_zNx.js → BtumQhZK.js} +1 -1
  47. package/.output/public/_nuxt/{BjLzqWJH2.js → BwWs9EdO2.js} +1 -1
  48. package/.output/public/_nuxt/{Bx2a9cuY2.js → BxxpJxZf2.js} +1 -1
  49. package/.output/public/_nuxt/{qRXa-PM22.js → ByTnUqFw2.js} +1 -1
  50. package/.output/public/_nuxt/{DvOETuoT2.js → Byiiiwc72.js} +1 -1
  51. package/.output/public/_nuxt/{Car2lkbb.js → C1-SuwUN.js} +1 -1
  52. package/.output/public/_nuxt/{Dg81dOEO.js → C14pM5G4.js} +1 -1
  53. package/.output/public/_nuxt/{MDhaRQq_.js → C2Yp-B8m.js} +1 -1
  54. package/.output/public/_nuxt/{BJ2nJNlK2.js → C4e6_nom2.js} +1 -1
  55. package/.output/public/_nuxt/{CiCEprsp2.js → C5OStZJ62.js} +1 -1
  56. package/.output/public/_nuxt/{ByMj6e7s.js → C6lssmvl.js} +2 -2
  57. package/.output/public/_nuxt/{C6uBP0Xa.js → CC-GEjfN.js} +1 -1
  58. package/.output/public/_nuxt/CC2Pv8VL2.js +1 -0
  59. package/.output/public/_nuxt/{DKiqdYnj.js → CCcMgxV9.js} +1 -1
  60. package/.output/public/_nuxt/{5S26I34j2.js → CDL30A2z2.js} +1 -1
  61. package/.output/public/_nuxt/{B8C-QJB5.js → CDYLasP8.js} +1 -1
  62. package/.output/public/_nuxt/CElzwyXQ.js +1 -0
  63. package/.output/public/_nuxt/{2KE8xGVm.js → CEvJu-xI.js} +1 -1
  64. package/.output/public/_nuxt/{CR612R752.js → CFQRFctQ2.js} +1 -1
  65. package/.output/public/_nuxt/{DnzjxC0u.js → CHk9XxNi.js} +2 -2
  66. package/.output/public/_nuxt/{Bx4MR0jd.js → CLFmtXU7.js} +1 -1
  67. package/.output/public/_nuxt/{DW8k_0dQ.js → CMJi6yYS.js} +1 -1
  68. package/.output/public/_nuxt/{DD-r0S1p.js → CPvFGbr8.js} +1 -1
  69. package/.output/public/_nuxt/{CCgbgkid.js → CQSxS_Ek.js} +2 -2
  70. package/.output/public/_nuxt/{jGxHnjW6.js → CQuo31jF.js} +1 -1
  71. package/.output/public/_nuxt/{SoO2K-di.js → CRCrWy-6.js} +1 -1
  72. package/.output/public/_nuxt/CUCFFL9m.js +84 -0
  73. package/.output/public/_nuxt/CZYNy60j2.js +1 -0
  74. package/.output/public/_nuxt/{WPwdj9pg.js → CZsFf7ck.js} +1 -1
  75. package/.output/public/_nuxt/CfFUK6932.js +2 -0
  76. package/.output/public/_nuxt/{DAsjfdZD.js → CfIbFnJz.js} +1 -1
  77. package/.output/public/_nuxt/{Tk6TQZjU.js → CjF4QY9h.js} +1 -1
  78. package/.output/public/_nuxt/{DlUQa0wn.js → Cjo1t2IF.js} +1 -1
  79. package/.output/public/_nuxt/{CDn0eDn8.js → CmuGMxDP.js} +1 -1
  80. package/.output/public/_nuxt/Cn6EojFe.js +1 -0
  81. package/.output/public/_nuxt/{DLqSQbGv.js → CnYazk8d.js} +1 -1
  82. package/.output/public/_nuxt/{DQfy6R_2.js → CnrGVJIr.js} +1 -1
  83. package/.output/public/_nuxt/{C0YL0HKK.js → CtcBhkci.js} +1 -1
  84. package/.output/public/_nuxt/{h5gsh8E92.js → Cv-Mv7_h2.js} +1 -1
  85. package/.output/public/_nuxt/{vPcnBJsa2.js → CzlZrfq82.js} +1 -1
  86. package/.output/public/_nuxt/{C2YYOgMe.js → CznnUTZx.js} +2 -2
  87. package/.output/public/_nuxt/{csitHKnE2.js → D-80EfyA2.js} +1 -1
  88. package/.output/public/_nuxt/{BRdoISnJ2.js → D1C6qtS12.js} +1 -1
  89. package/.output/public/_nuxt/{Cnrmlixo.js → D1MkndMZ.js} +2 -2
  90. package/.output/public/_nuxt/{BLwDhlaa.js → D37gODe0.js} +1 -1
  91. package/.output/public/_nuxt/{NXY37IO62.js → D6FhDrYe2.js} +1 -1
  92. package/.output/public/_nuxt/{Btx8wL4-.js → D7TZLu4F.js} +1 -1
  93. package/.output/public/_nuxt/{qoUdVDnC.js → D7tEwf-o.js} +3 -3
  94. package/.output/public/_nuxt/D8HQPtm62.js +1 -0
  95. package/.output/public/_nuxt/D9O4L4jK.js +1 -0
  96. package/.output/public/_nuxt/{aQ1B7BZa2.js → D9lL3fJM2.js} +2 -2
  97. package/.output/public/_nuxt/{CT-vTjcG2.js → DC-2eKo62.js} +1 -1
  98. package/.output/public/_nuxt/DF9ETYJ32.js +1 -0
  99. package/.output/public/_nuxt/DGGBrc0q2.js +1 -0
  100. package/.output/public/_nuxt/DGu_fna7.js +1 -0
  101. package/.output/public/_nuxt/{BupBjt6B.js → DKOvbitt.js} +1 -1
  102. package/.output/public/_nuxt/{B1PzYsqN.js → DNxudyND.js} +1 -1
  103. package/.output/public/_nuxt/{BfX6_AjY.js → DOT-XQyi.js} +1 -1
  104. package/.output/public/_nuxt/{BsTZnkVK.js → DPPC9Teq.js} +1 -1
  105. package/.output/public/_nuxt/{HxohXQ_r.js → DRskyE7l.js} +1 -1
  106. package/.output/public/_nuxt/{B-U7E_Mc2.js → DW4ZgInh2.js} +1 -1
  107. package/.output/public/_nuxt/{BErG4kzc2.js → DWe6BMlp2.js} +1 -1
  108. package/.output/public/_nuxt/{BH8RvpVy.js → DWy0AjON.js} +1 -1
  109. package/.output/public/_nuxt/{Bc_k6AVA.js → DXgw1dVL.js} +4 -4
  110. package/.output/public/_nuxt/{C3sWJ8SD2.js → DZsKIzKD2.js} +1 -1
  111. package/.output/public/_nuxt/D_59BNP1.js +14 -0
  112. package/.output/public/_nuxt/{BQIO4MkA2.js → D_FZ3KZI2.js} +1 -1
  113. package/.output/public/_nuxt/{n_Njdwii2.js → D__vJGHF2.js} +1 -1
  114. package/.output/public/_nuxt/{C9gErLQc2.js → DaizNGUm2.js} +1 -1
  115. package/.output/public/_nuxt/{C-MY-JQE.js → DdyE0ylS.js} +1 -1
  116. package/.output/public/_nuxt/DhLlTxQh2.js +1 -0
  117. package/.output/public/_nuxt/{CxVhG0Xx.js → DhW7cFOa.js} +1 -1
  118. package/.output/public/_nuxt/{Rt2i6k7C2.js → DhjgWrB62.js} +1 -1
  119. package/.output/public/_nuxt/{KwT4sN_d.js → DiWcX4gj.js} +1 -1
  120. package/.output/public/_nuxt/DiloA8vK.js +1 -0
  121. package/.output/public/_nuxt/{DX-c5laM2.js → DlS-SkQ42.js} +1 -1
  122. package/.output/public/_nuxt/{D_Zspo1y.js → DmHp9yQ3.js} +1 -1
  123. package/.output/public/_nuxt/{dq1HKoGD.js → DoL9u6wu.js} +1 -1
  124. package/.output/public/_nuxt/{CIvMT5Ic.js → DqxBCeDe.js} +1 -1
  125. package/.output/public/_nuxt/{BnNmkGJS2.js → DrlnrdvY2.js} +3 -3
  126. package/.output/public/_nuxt/{BAcjVcku2.js → Dt8TL8_X2.js} +1 -1
  127. package/.output/public/_nuxt/{BtfwbNC0.js → Du7gS8RU.js} +1 -1
  128. package/.output/public/_nuxt/DuUc4bbY2.js +1 -0
  129. package/.output/public/_nuxt/{DPUXbTg9.js → DudoisLM.js} +1 -1
  130. package/.output/public/_nuxt/{Ce5R-ZGf2.js → DwgVlehj2.js} +1 -1
  131. package/.output/public/_nuxt/Dyxf2xZw.js +1 -0
  132. package/.output/public/_nuxt/Dz9C2pTa.js +1 -0
  133. package/.output/public/_nuxt/{BYxG9Hb2.js → EMbqTHfT.js} +1 -1
  134. package/.output/public/_nuxt/{B1SzppY12.js → FsRVXpyF2.js} +1 -1
  135. package/.output/public/_nuxt/{0MLy6ogg2.js → GQrEW8nk2.js} +1 -1
  136. package/.output/public/_nuxt/{Tuz5LcLM.js → IXR1BWP5.js} +1 -1
  137. package/.output/public/_nuxt/{-jpUnM1I2.js → Iub61dX92.js} +1 -1
  138. package/.output/public/_nuxt/{CQgOzpvI.js → JegDslce.js} +2 -2
  139. package/.output/public/_nuxt/{DrF3TWoj.js → KzK37yIr.js} +1 -1
  140. package/.output/public/_nuxt/{Br3MggOL.js → N-CCmCsX.js} +1 -1
  141. package/.output/public/_nuxt/{DHhmq7s_.js → NfvZ5Lzv.js} +1 -1
  142. package/.output/public/_nuxt/{CzX_kaPL.js → POTcePF_.js} +1 -1
  143. package/.output/public/_nuxt/{D7s96J3r2.js → Q-JpBT032.js} +1 -1
  144. package/.output/public/_nuxt/{DzwIZ81f2.js → R1g64DNi2.js} +1 -1
  145. package/.output/public/_nuxt/{JgheoP3e.js → R5Pz7BqB.js} +1 -1
  146. package/.output/public/_nuxt/{yLyz0-Yz.js → SvjzWbn8.js} +1 -1
  147. package/.output/public/_nuxt/{Dd7MZc_Q.js → XqXoaoDs.js} +1 -1
  148. package/.output/public/_nuxt/{B6jtLy6z.js → YAA98rWJ.js} +11 -11
  149. package/.output/public/_nuxt/{HX4_xnak2.js → YLYSczSq2.js} +1 -1
  150. package/.output/public/_nuxt/{BBw9ylUY2.js → YNhAoK-R2.js} +1 -1
  151. package/.output/public/_nuxt/Zkbt8Uk5.js +1 -0
  152. package/.output/public/_nuxt/aml.PalMp-5n.css +1 -0
  153. package/.output/public/_nuxt/{C41CcsiD.js → b7UcqLKi.js} +1 -1
  154. package/.output/public/_nuxt/builds/latest.json +1 -1
  155. package/.output/public/_nuxt/builds/meta/fa0af8b5-3929-428d-a6de-3b5cc6b8248f.json +1 -0
  156. package/.output/public/_nuxt/{DVkFSOZi.js → cKj4vSo5.js} +1 -1
  157. package/.output/public/_nuxt/{r1CpGsFp.js → dHwWyr6b.js} +1 -1
  158. package/.output/public/_nuxt/{DlcA9Gxl.js → eePbiWEh.js} +1 -1
  159. package/.output/public/_nuxt/{cjRzSvAg2.js → eymRov9Y2.js} +1 -1
  160. package/.output/public/_nuxt/{B8cViLJT.js → geMze5qw.js} +1 -1
  161. package/.output/public/_nuxt/{uu1wfdfR2.js → gh-WMxV_2.js} +1 -1
  162. package/.output/public/_nuxt/{Ce6e1mPk2.js → hCN555XP2.js} +1 -1
  163. package/.output/public/_nuxt/{rdUE8Khf.js → hZG5MLjK.js} +3 -3
  164. package/.output/public/_nuxt/{CcX_jP-d.js → hlfahYxK.js} +1 -1
  165. package/.output/public/_nuxt/{cGSl2GZp2.js → ilJHF1nA2.js} +1 -1
  166. package/.output/public/_nuxt/{D6ZcgHPz.js → jDuiDtGb.js} +1 -1
  167. package/.output/public/_nuxt/{DbeNMehP.js → k9b520K-.js} +1 -1
  168. package/.output/public/_nuxt/ontology.B_3Wn907.css +1 -0
  169. package/.output/public/_nuxt/optimizer.CLA8I1sy.css +1 -0
  170. package/.output/public/_nuxt/{DSORcpTJ.js → rDvMijKA.js} +2 -2
  171. package/.output/public/_nuxt/{CAiHhX8P2.js → rF7mggl72.js} +2 -2
  172. package/.output/public/_nuxt/ri9UF8rk.js +2 -0
  173. package/.output/public/_nuxt/{KgnxOsMr.js → toG_qAMH.js} +1 -1
  174. package/.output/public/_nuxt/{KQZmHR_K.js → u3h4pGpm.js} +2 -2
  175. package/.output/public/_nuxt/{dJ7gK7C2.js → uomnHjhM.js} +1 -1
  176. package/.output/public/_nuxt/{BUTg4W_x2.js → v77qozuJ2.js} +1 -1
  177. package/.output/public/_nuxt/{BcEr7tIB.js → v7cV7hJa.js} +1 -1
  178. package/.output/public/_nuxt/{D25dVZ822.js → vkQoYNQR2.js} +2 -2
  179. package/.output/public/_nuxt/{wR_w07322.js → vp3LtnTz2.js} +1 -1
  180. package/.output/public/_nuxt/{Bnc8HELj2.js → we7-sMSo2.js} +1 -1
  181. package/.output/public/_nuxt/{kN3ZzR1-.js → wxISMS1i.js} +1 -1
  182. package/.output/public/_nuxt/{DGrrucbG.js → zy7efYKR.js} +1 -1
  183. package/.output/server/chunks/_/data-export.mjs +5 -5
  184. package/.output/server/chunks/_/data-query.mjs +2 -2
  185. package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
  186. package/.output/server/chunks/_/features.mjs +4 -4
  187. package/.output/server/chunks/_/golden.mjs +2 -2
  188. package/.output/server/chunks/_/index.mjs +1 -1
  189. package/.output/server/chunks/_/mes-console.mjs +1 -1
  190. package/.output/server/chunks/_/nitro.mjs +2149 -1520
  191. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  192. package/.output/server/chunks/_/spc.mjs +1 -1
  193. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
  194. package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs → _wsId_-BPy-Aj9L.mjs} +3 -3
  195. package/.output/server/chunks/build/{_wsId_-BNKrrV1H.mjs.map → _wsId_-BPy-Aj9L.mjs.map} +1 -1
  196. package/.output/server/chunks/build/{agents-8tV9xL97.mjs → agents-CpNLdI8E.mjs} +6 -6
  197. package/.output/server/chunks/build/{agents-8tV9xL97.mjs.map → agents-CpNLdI8E.mjs.map} +1 -1
  198. package/.output/server/chunks/build/{aml-BNTEDOsl.mjs → aml-DRAFRcGU.mjs} +15 -12
  199. package/.output/server/chunks/build/{aml-BNTEDOsl.mjs.map → aml-DRAFRcGU.mjs.map} +1 -1
  200. package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs → channel-templates-ByHOQQkO.mjs} +2 -2
  201. package/.output/server/chunks/build/{channel-templates-Iot9Y3vV.mjs.map → channel-templates-ByHOQQkO.mjs.map} +1 -1
  202. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
  203. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
  204. package/.output/server/chunks/build/{default-CJkOcmrm.mjs → default-CNWS6NUw.mjs} +4 -4
  205. package/.output/server/chunks/build/{default-CJkOcmrm.mjs.map → default-CNWS6NUw.mjs.map} +1 -1
  206. package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs → dropdown-BNwTVGde.mjs} +2 -2
  207. package/.output/server/chunks/build/{dropdown-CjwsxU39.mjs.map → dropdown-BNwTVGde.mjs.map} +1 -1
  208. package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs → dropdown-Cd-xPhR6.mjs} +2 -2
  209. package/.output/server/chunks/build/{dropdown-C6YH_kSO.mjs.map → dropdown-Cd-xPhR6.mjs.map} +1 -1
  210. package/.output/server/chunks/build/input-number-BNlNDK7H.mjs +1 -1
  211. package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs → logs-pRb-TMWa.mjs} +3 -3
  212. package/.output/server/chunks/build/{logs-BTfJQ6vQ.mjs.map → logs-pRb-TMWa.mjs.map} +1 -1
  213. package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs → monitor-Cq6hRFeQ.mjs} +6 -6
  214. package/.output/server/chunks/build/{monitor-DvaR3yo8.mjs.map → monitor-Cq6hRFeQ.mjs.map} +1 -1
  215. package/.output/server/chunks/build/{ontology-C3HS5pMo.mjs → ontology-DK0Mf0zT.mjs} +510 -81
  216. package/.output/server/chunks/build/ontology-DK0Mf0zT.mjs.map +1 -0
  217. package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs → operations-SMQrRAcr.mjs} +3 -3
  218. package/.output/server/chunks/build/{operations-Cl8nVm9D.mjs.map → operations-SMQrRAcr.mjs.map} +1 -1
  219. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs +202 -0
  220. package/.output/server/chunks/build/optimizer-BlWTsM-W.mjs.map +1 -0
  221. package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs → pagination-DTAconUo.mjs} +2 -2
  222. package/.output/server/chunks/build/{pagination-KaIvHBzi.mjs.map → pagination-DTAconUo.mjs.map} +1 -1
  223. package/.output/server/chunks/build/{permissions-CVTfixZj.mjs → permissions-DgXQZSyx.mjs} +6 -6
  224. package/.output/server/chunks/build/{permissions-CVTfixZj.mjs.map → permissions-DgXQZSyx.mjs.map} +1 -1
  225. package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs → schedules-dSnr8url.mjs} +6 -6
  226. package/.output/server/chunks/build/{schedules-BLhn2CLn.mjs.map → schedules-dSnr8url.mjs.map} +1 -1
  227. package/.output/server/chunks/build/{select--XFl7CtY.mjs → select-B3Dsb9yq.mjs} +3 -3
  228. package/.output/server/chunks/build/{select--XFl7CtY.mjs.map → select-B3Dsb9yq.mjs.map} +1 -1
  229. package/.output/server/chunks/build/{settings-DIf_iYdu.mjs → settings-BrIhnS2Z.mjs} +2 -2
  230. package/.output/server/chunks/build/{settings-DIf_iYdu.mjs.map → settings-BrIhnS2Z.mjs.map} +1 -1
  231. package/.output/server/chunks/build/{table-DIu_YCJN.mjs → table-CmVD-cA9.mjs} +4 -4
  232. package/.output/server/chunks/build/{table-DIu_YCJN.mjs.map → table-CmVD-cA9.mjs.map} +1 -1
  233. package/.output/server/chunks/build/{teams-B2J6ouRY.mjs → teams-B1d32eHK.mjs} +4 -4
  234. package/.output/server/chunks/build/{teams-B2J6ouRY.mjs.map → teams-B1d32eHK.mjs.map} +1 -1
  235. package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs → tokens-GYaGJ35Z.mjs} +6 -6
  236. package/.output/server/chunks/build/{tokens-DFQGaN2n.mjs.map → tokens-GYaGJ35Z.mjs.map} +1 -1
  237. package/.output/server/chunks/build/{tools-DWJFnU_t.mjs → tools-s_9U1Djj.mjs} +6 -6
  238. package/.output/server/chunks/build/{tools-DWJFnU_t.mjs.map → tools-s_9U1Djj.mjs.map} +1 -1
  239. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  240. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
  241. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +1 -1
  242. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
  243. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +1 -1
  244. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +1 -1
  245. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
  246. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +1 -1
  247. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +1 -1
  248. package/.output/server/chunks/build/{users-BWw0VCr9.mjs → users-DjiVC_tS.mjs} +6 -6
  249. package/.output/server/chunks/build/{users-BWw0VCr9.mjs.map → users-DjiVC_tS.mjs.map} +1 -1
  250. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  251. package/.output/server/chunks/routes/api/system/backup/run.post.mjs +2 -2
  252. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +7 -1
  253. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs.map +1 -1
  254. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  255. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +6 -6
  256. package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +2 -2
  257. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  258. package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
  259. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  260. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs +52 -0
  261. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs.map +1 -0
  262. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +1 -1
  263. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +1 -1
  264. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +1 -1
  265. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +1 -1
  266. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +1 -1
  267. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +1 -1
  268. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs +38 -0
  269. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs.map +1 -0
  270. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +1 -1
  271. package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +1 -1
  272. package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +1 -1
  273. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +8 -1
  274. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs.map +1 -1
  275. package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +1 -1
  276. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +1 -1
  277. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +1 -1
  278. package/.output/server/chunks/routes/api/workshop/optimization/capabilities.get.mjs +1 -1
  279. package/.output/server/chunks/routes/api/workshop/optimization/index.mjs +1 -1
  280. package/.output/server/chunks/routes/api/workshop/optimization/index2.mjs +1 -1
  281. package/.output/server/chunks/routes/api/workshop/optimization/profiles/_id/publish.post.mjs +1 -1
  282. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/crosscheck.post.mjs +1 -1
  283. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/dispatch.post.mjs +1 -1
  284. package/.output/server/chunks/routes/api/workshop/optimization/solve.post.mjs +1 -1
  285. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  286. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  287. package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
  288. package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
  289. package/.output/server/chunks/routes/api/workshop/process-model/index.mjs +1 -1
  290. package/.output/server/chunks/routes/api/workshop/process-model/specs/_id/publish.post.mjs +1 -1
  291. package/.output/server/chunks/routes/api/workshop/process-model/train.post.mjs +1 -1
  292. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  293. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  294. package/.output/server/chunks/routes/api/workshop/tools/sync.post.mjs +1 -1
  295. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  296. package/.output/server/chunks/routes/renderer.mjs +2 -2
  297. package/.output/server/chunks/virtual/entry.mjs +92 -18
  298. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  299. package/.output/server/package.json +1 -1
  300. package/README-zh.md +5 -4
  301. package/README.md +6 -5
  302. package/app/components/aml/AmlModelsTable.vue +5 -0
  303. package/app/components/ontology/OntologyGraph.vue +356 -0
  304. package/app/pages/aml/styles.css +1 -0
  305. package/app/pages/ontology/index.vue +318 -35
  306. package/app/pages/ontology/types.ts +42 -0
  307. package/app/pages/optimizer/index.vue +21 -4
  308. package/config.yml +1 -1
  309. package/docs/cli.en.md +2 -2
  310. package/docs/cli.md +2 -2
  311. package/docs/plugins.en.md +1 -1
  312. package/docs/plugins.md +1 -1
  313. package/docs/sdk.en.md +1 -1
  314. package/docs/sdk.md +1 -1
  315. package/i18n/locales/en.ts +26 -0
  316. package/i18n/locales/zh-CN.ts +26 -0
  317. package/mcp/aw-mcp-server.mjs +20 -2
  318. package/package.json +1 -1
  319. package/scripts/e2e-direct-rest-simulator-paper.mjs +624 -0
  320. package/scripts/e2e-idd-results.mjs +177 -0
  321. package/scripts/e2e-model-loop-live.mjs +58 -4
  322. package/scripts/e2e-ontology-live.mjs +138 -3
  323. package/scripts/e2e-ontology.mjs +393 -328
  324. package/scripts/e2e-pi-simulator-paper.mjs +2316 -0
  325. package/scripts/e2e-registered-harness-simulator-paper.mjs +1926 -0
  326. package/scripts/e2e-simulator-optimizer-paper.mjs +264 -0
  327. package/scripts/fixtures/omp-paper-harness.mjs +163 -0
  328. package/sdk/context.mjs +6 -0
  329. package/sdk/index.d.mts +2 -0
  330. package/server/api/workshop/aml/models/[id].patch.ts +36 -30
  331. package/server/api/workshop/ontology/drafts/[draftId]/autofix.ts +31 -0
  332. package/server/api/workshop/ontology/drafts/[draftId]/subgraph.ts +24 -0
  333. package/server/api/workshop/ontology/scene.ts +14 -1
  334. package/server/plugins-builtin/diag-bridge/client.mjs +390 -239
  335. package/server/plugins-builtin/diag-bridge/host/helpers.mjs +80 -0
  336. package/server/plugins-builtin/diag-bridge/host/plugin.mjs +264 -2
  337. package/server/plugins-builtin/diag-bridge/i18n.json +84 -4
  338. package/server/services/workshop/agents/adapters/omp-rpc-client/frames.ts +129 -111
  339. package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +6 -3
  340. package/server/services/workshop/agents/industrial/aml-job-tools.ts +602 -569
  341. package/server/services/workshop/agents/industrial/grant-guard.ts +15 -1
  342. package/server/services/workshop/agents/industrial/index.ts +2 -2
  343. package/server/services/workshop/agents/industrial/ontology-tools.ts +66 -6
  344. package/server/services/workshop/agents/industrial/ops-tools.ts +54 -16
  345. package/server/services/workshop/agents/industrial/optimizer-tools.ts +2 -0
  346. package/server/services/workshop/agents/industrial/recipe-gate.ts +19 -6
  347. package/server/services/workshop/agents/industrial/recipe-propose-tools.ts +1 -1
  348. package/server/services/workshop/agents/omp-agent/supervision-history.ts +38 -0
  349. package/server/services/workshop/agents/omp-agent/tools-steer.ts +18 -1
  350. package/server/services/workshop/aml/aml.repo.ts +16 -0
  351. package/server/services/workshop/daq/bus/index.ts +12 -5
  352. package/server/services/workshop/db/database/open.ts +97 -97
  353. package/server/services/workshop/db/database/schema.ts +1 -0
  354. package/server/services/workshop/ontology/autofix.ts +198 -0
  355. package/server/services/workshop/ontology/contracts.ts +3 -1
  356. package/server/services/workshop/ontology/index.ts +2 -0
  357. package/server/services/workshop/ontology/ontology.service.ts +46 -0
  358. package/server/services/workshop/ontology/subgraph.core.ts +300 -0
  359. package/server/services/workshop/ontology/subgraph.service.ts +113 -0
  360. package/server/services/workshop/optimization/contracts.ts +2 -0
  361. package/server/services/workshop/optimization/profile-adopt.service.ts +5 -0
  362. package/server/services/workshop/optimization/profile.repo.ts +6 -4
  363. package/.output/public/_nuxt/B3Y5bCrM.js +0 -1
  364. package/.output/public/_nuxt/B8N8nsad2.js +0 -2
  365. package/.output/public/_nuxt/BO0BJx3w2.js +0 -8
  366. package/.output/public/_nuxt/BWn-lfCp2.js +0 -1
  367. package/.output/public/_nuxt/Bcs9zzO62.js +0 -1
  368. package/.output/public/_nuxt/BwO2Y5FH2.js +0 -1
  369. package/.output/public/_nuxt/Byf4IxU2.js +0 -14
  370. package/.output/public/_nuxt/C-LU6xv_.js +0 -1
  371. package/.output/public/_nuxt/CJ0bjZ6v2.js +0 -1
  372. package/.output/public/_nuxt/CJ3Vul2u.js +0 -1
  373. package/.output/public/_nuxt/CNwx04ln.js +0 -84
  374. package/.output/public/_nuxt/CVCscYzb2.js +0 -1
  375. package/.output/public/_nuxt/C_A0MCol2.js +0 -1
  376. package/.output/public/_nuxt/CnP6snIz.js +0 -3
  377. package/.output/public/_nuxt/D0mzKkZr.js +0 -1
  378. package/.output/public/_nuxt/D3buuIkE.js +0 -1
  379. package/.output/public/_nuxt/D4_INWgq.js +0 -1
  380. package/.output/public/_nuxt/D5kCimyw2.js +0 -1
  381. package/.output/public/_nuxt/DBtXLkyA.js +0 -1
  382. package/.output/public/_nuxt/DHURbGkn2.js +0 -1
  383. package/.output/public/_nuxt/DaBzS-iu.js +0 -1
  384. package/.output/public/_nuxt/DnlhV7Xe.js +0 -1
  385. package/.output/public/_nuxt/GtI6PUI32.js +0 -1
  386. package/.output/public/_nuxt/Nw_6OpQZ.js +0 -1
  387. package/.output/public/_nuxt/Y4sMSPrS2.js +0 -1
  388. package/.output/public/_nuxt/aml.CeLxRzvI.css +0 -1
  389. package/.output/public/_nuxt/builds/meta/7a79a7e4-d691-4cf5-ae3a-3b01814479fb.json +0 -1
  390. package/.output/public/_nuxt/goF_oZHF.js +0 -2
  391. package/.output/public/_nuxt/ontology.QMGeh66l.css +0 -1
  392. package/.output/public/_nuxt/optimizer.B8gCbU1b.css +0 -1
  393. package/.output/public/_nuxt/rJ7To74v2.js +0 -1
  394. package/.output/server/chunks/build/ontology-C3HS5pMo.mjs.map +0 -1
  395. package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs +0 -200
  396. package/.output/server/chunks/build/optimizer-BOtGWEtc.mjs.map +0 -1
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable @stylistic/max-statements-per-line */
3
+ /**
4
+ * Current-version cross-scene integration run against an isolated AW home and simulator.
5
+ * The simulator runs from a fresh source copy; existing :4010 and business records are untouched.
6
+ * No truth/optimum endpoint is consumed. Not a benefit benchmark or an autonomous experiment runner.
7
+ *
8
+ * AW_PHYSICAL_CONTEXT=<JSON with base/token/home> node scripts/e2e-simulator-optimizer-paper.mjs
9
+ * Defaults to six 120 s, 1 Hz collection windows when DAQ infrastructure is healthy.
10
+ * Exit: 0 all attempted checks passed, 1 failure, 2 blocked downstream coverage.
11
+ */
12
+ import { spawn } from 'node:child_process'
13
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, openSync, readFileSync, symlinkSync, writeFileSync } from 'node:fs'
14
+ import { createServer } from 'node:net'
15
+ import { dirname, join, resolve } from 'node:path'
16
+ import { fileURLToPath } from 'node:url'
17
+
18
+ const REPO = resolve(dirname(fileURLToPath(import.meta.url)), '..')
19
+ const contextFile = process.env.AW_PHYSICAL_CONTEXT || join(REPO, '.omc', 'optimizer-full-live-20261023', 'live-context.json')
20
+ const context = JSON.parse(readFileSync(contextFile, 'utf8'))
21
+ const BASE = String(context.base || '')
22
+ const token = String(context.token || '')
23
+ const allowed = new Set(['127.0.0.1', 'localhost', '[::1]'])
24
+ if (!allowed.has(new URL(BASE).hostname) || !token) throw new Error('Only an authenticated loopback test instance is allowed')
25
+ if (!/aw-optimizer-live-e2e|optimizer-physical/i.test(String(context.home || ''))) throw new Error('Expected an explicitly isolated optimizer test home')
26
+ const SIM_PORT = Number(process.env.AW_PHYSICAL_SIM_PORT || 4020)
27
+ const MQTT_PORT = Number(process.env.AW_PHYSICAL_MQTT_PORT || 18840)
28
+ const SIM = `http://127.0.0.1:${SIM_PORT}`
29
+ const TAG = `phy${Date.now().toString(36)}`
30
+ const ROOT = mkdtempSync(join(REPO, '.omc', 'optimizer-physical-'))
31
+ const EVID = join(REPO, 'docs', 'audit', 'evidence', '2026-10-25-current-cross-scene', TAG)
32
+ mkdirSync(EVID, { recursive: true })
33
+ const checks = []
34
+ const scenes = []
35
+ let simulator
36
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
37
+ const record = (id, name, status, detail = '') => {
38
+ checks.push({ id, name, status, detail })
39
+ console.log(`${status.toUpperCase()} [${id}] ${name} ${typeof detail === 'string' ? detail : JSON.stringify(detail)}`)
40
+ }
41
+ const check = (id, name, pass, detail = '') => record(id, name, pass ? 'pass' : 'fail', detail)
42
+ async function api(base, method, path, body, auth = false) {
43
+ if (!allowed.has(new URL(base).hostname) || !path.startsWith('/api/')) throw new Error('Loopback API boundary')
44
+ if (/\/plant\/(truth|optimum)/.test(path)) throw new Error('Truth is unavailable to this harness')
45
+ const response = await fetch(base + path, {
46
+ method, headers: { 'content-type': 'application/json', ...(auth ? { authorization: `Bearer ${token}` } : {}) },
47
+ ...(body === undefined ? {} : { body: JSON.stringify(body) }), signal: AbortSignal.timeout(120_000),
48
+ })
49
+ return { status: response.status, ...await response.json().catch(() => ({})) }
50
+ }
51
+ const aw = (method, path, body) => api(BASE, method, path, body, true)
52
+ const sim = (method, path, body) => api(SIM, method, path, body)
53
+ const error = result => ({ status: result.status, code: result?.data?.error?.code || result.code, message: result.message || result.statusMessage })
54
+ const need = (response, key, label) => {
55
+ const value = response?.data?.[key]
56
+ if (response.status !== 200 || !value) throw new Error(`${label}: ${JSON.stringify(error(response))}`)
57
+ return value
58
+ }
59
+ async function assertFree(port) {
60
+ const server = createServer()
61
+ await new Promise((resolvePromise, reject) => { server.once('error', reject); server.listen(port, '127.0.0.1', resolvePromise) })
62
+ await new Promise(resolvePromise => server.close(resolvePromise))
63
+ }
64
+ async function bootSimulator() {
65
+ if (process.env.AW_PHYSICAL_SIM_ROOT) {
66
+ if (!resolve(process.env.AW_PHYSICAL_SIM_ROOT).startsWith(join(REPO, '.omc', 'optimizer-physical-'))) throw new Error('Unexpected simulator runtime root')
67
+ if ((await sim('GET', '/api/nodes')).status !== 200) throw new Error('Prestarted isolated simulator is unavailable')
68
+ return
69
+ }
70
+ await assertFree(SIM_PORT)
71
+ await assertFree(MQTT_PORT)
72
+ const dest = join(ROOT, 'simulator')
73
+ mkdirSync(dest)
74
+ cpSync(join(REPO, 'plc-node-simulator', 'src'), join(dest, 'src'), { recursive: true })
75
+ cpSync(join(REPO, 'plc-node-simulator', 'package.json'), join(dest, 'package.json'))
76
+ const modules = join(REPO, 'plc-node-simulator', 'node_modules')
77
+ if (!existsSync(modules)) throw new Error('Simulator dependencies missing; no automatic installation')
78
+ symlinkSync(modules, join(dest, 'node_modules'), process.platform === 'win32' ? 'junction' : 'dir')
79
+ const log = openSync(join(ROOT, 'simulator.log'), 'a')
80
+ simulator = spawn(process.execPath, [join(REPO, 'node_modules', 'tsx', 'dist', 'cli.mjs'), join(dest, 'src', 'server', 'index.ts')], {
81
+ cwd: dest, env: { ...process.env, SIM_PORT: String(SIM_PORT), MQTT_BROKER_PORT: String(MQTT_PORT), NO_PROXY: '127.0.0.1,localhost' },
82
+ stdio: ['ignore', log, log], windowsHide: true,
83
+ })
84
+ for (let i = 0; i < 80; i++) {
85
+ if (simulator.exitCode !== null) throw new Error(`Simulator exited ${simulator.exitCode}; ${join(ROOT, 'simulator.log')}`)
86
+ try { if ((await sim('GET', '/api/nodes')).status === 200) return }
87
+ catch { /* starting */ }
88
+ await sleep(500)
89
+ }
90
+ throw new Error('Simulator boot timeout')
91
+ }
92
+ async function loadScene(key, label, mvName, cvName, sourceDevice) {
93
+ const blueprint = (await sim('GET', `/api/presets/${key}`)).data
94
+ if (!blueprint?.plantModel) throw new Error(`Missing simulator blueprint ${key}`)
95
+ for (const node of blueprint.nodes) {
96
+ node.config ||= {}
97
+ if (node.config.host) node.config.host = '127.0.0.1'
98
+ if (typeof node.config.port === 'number') { node.config.port += 1000; await assertFree(node.config.port) }
99
+ if (node.protocol === 'mqtt') node.config.brokerUrl = `mqtt://127.0.0.1:${MQTT_PORT}`
100
+ const created = await sim('POST', '/api/nodes', node)
101
+ if (created.status !== 200) throw new Error(`Simulator node ${node.id}: ${JSON.stringify(error(created))}`)
102
+ }
103
+ const plant = { ...blueprint.plantModel, id: label, seed: 42, timeScale: 1, truthExport: false }
104
+ const loaded = await sim('PUT', '/api/plant/config', { plantModel: plant, warm: true, upsert: true })
105
+ check(`${label}.plant`, 'Simulator model loaded at real time scale', loaded.status === 200, { kind: plant.kind || 'castfilm', timeScale: 1 })
106
+ const exported = []
107
+ for (const node of blueprint.nodes) {
108
+ const result = await sim('GET', `/api/nodes/${node.id}/export`)
109
+ for (const item of result?.data?.items || []) exported.push({ ...item, deviceId: node.id })
110
+ }
111
+ const mv = exported.find(item => item.deviceId === sourceDevice && item.signal === mvName)
112
+ const cv = exported.find(item => item.signal === cvName)
113
+ if (!mv || !cv) throw new Error(`${label}: missing MV/CV exports`)
114
+ const line = need(await aw('POST', '/api/workshop/dcw/lines', { name: `${TAG}-${label}`, simulated: true, simSceneId: key }), 'line', 'line')
115
+ const product = need(await aw('POST', '/api/workshop/dcw/products', { name: `${TAG}-${label}`, lineId: line.id }), 'product', 'product')
116
+ const template = need(await aw('POST', '/api/workshop/dcw/templates', { name: `${TAG}-${label}`, unit: mv.unit, min: mv.min, max: mv.max, decimals: mv.decimals || 0 }), 'template', 'template')
117
+ // Process-relevant manipulated/controlled-variable pairs use alternating
118
+ // bounded setpoints. Each step-to-step delta stays within maxStep=30.
119
+ const initial = label === 'film' ? 120 : 730
120
+ const control = need(await aw('POST', '/api/workshop/dcw', { templateRef: template.key, name: `${TAG}-${label}-MV`, driver: mv.driver, driverConfig: mv.driverConfig, lineId: line.id, min: mv.min, max: mv.max, unit: mv.unit, stepLimit: 60, writeLockSeconds: 0, holdIntervalMs: 0, readIntervalMs: 500 }), 'node', 'control')
121
+ const state = { label, key, line, product, control, initial, mv, cv, daq: [], runs: [] }
122
+ scenes.push(state)
123
+ // One exposed scalar for each available protocol; include both training channels.
124
+ const selected = [mv, cv]
125
+ for (const driver of ['modbus-tcp', 'modbus-rtu', 'opcua', 'mqtt', 'http']) {
126
+ if (selected.some(item => item.driver === driver)) continue
127
+ const item = exported.find(item => item.driver === driver && !item.format && !(item.driverConfig?.jsonKey))
128
+ if (item) selected.push(item)
129
+ }
130
+ for (const [i, item] of selected.entries()) {
131
+ const probe = await aw('POST', '/api/workshop/daq/test-driver', { driver: item.driver, driverConfig: item.driverConfig })
132
+ check(`${label}.probe.${i}`, `Platform ${item.driver} driver reads simulator signal ${item.signal}`, probe.status === 200 && probe.data?.test?.ok === true, probe.data?.test || error(probe))
133
+ const node = need(await aw('POST', '/api/workshop/daq', { templateRef: 'daq-temp-tc', name: `${TAG}-${label}-${i}`, driver: item.driver, driverConfig: item.driverConfig, lineId: line.id, min: item.min, max: item.max, unit: item.unit, intervalMs: 500, publishIntervalMs: 0 }), 'node', 'DAQ create')
134
+ state.daq.push({ ...node, export: item })
135
+ }
136
+ const written = await aw('POST', `/api/workshop/dcw/${control.id}/write`, { value: initial + 5 })
137
+ check(`${label}.write`, 'Application DCW writes through simulator protocol endpoint', written.status === 200 && written.data?.outcome?.ok === true, written.data?.outcome || error(written))
138
+ const readback = await aw('POST', '/api/workshop/daq/test-driver', { driver: mv.driver, driverConfig: mv.driverConfig })
139
+ const probeValue = Number(readback.data?.test?.value ?? readback.data?.test?.preview?.value)
140
+ // Dedicated simulator node is the independent exposed readback when test-driver response omits value.
141
+ const simNode = (await sim('GET', '/api/nodes')).data?.find(node => node.id === mv.deviceId)
142
+ const signal = simNode?.signals?.find(item => item.name === mvName)
143
+ const observed = Number(signal?.value ?? signal?.runtime?.value ?? probeValue)
144
+ check(`${label}.readback`, 'Exposed PLC setpoint equals application write', Math.abs(observed - initial - 5) <= 0.01, { expected: initial + 5, observed })
145
+ state.recipe = need(await aw('POST', '/api/workshop/dcw/recipes', { name: `${TAG}-${label}`, productId: product.id, params: [{ nodeId: control.id, templateRef: template.key, value: initial, min: mv.min, max: mv.max, stepLimit: 60 }], daqWindows: state.daq.map(node => ({ nodeId: node.id, min: node.export.min, max: node.export.max })) }), 'recipe', 'recipe')
146
+ return state
147
+ }
148
+ function specOf(scene) {
149
+ return {
150
+ schemaVersion: 2, id: `${TAG}-${scene.label}`, version: 1, lineId: scene.line.id, productId: scene.product.id, recipeId: scene.recipe.id, recipeVersion: scene.recipe.version || 1,
151
+ conditions: [{ id: 'simulator', match: [{ field: 'recipeId', op: 'eq', value: scene.recipe.id }] }],
152
+ variables: [
153
+ { id: 'mv', nodeId: scene.daq[0].id, controlNodeId: scene.control.id, role: 'mv', field: 'value', unit: scene.mv.unit, scale: 1, offset: 0, delayMs: 0, min: scene.mv.min, max: scene.mv.max, maxStep: 30 },
154
+ { id: 'cv', nodeId: scene.daq[1].id, role: 'cv', field: 'value', unit: scene.cv.unit, scale: 1, offset: 0, min: scene.cv.min, max: scene.cv.max },
155
+ ],
156
+ timing: { beatMs: 1000, historySteps: 8, horizonSteps: 4, fixedDt: true },
157
+ trainer: { ref: 'linear_arx@1', config: { arOrder: 1, inputOrder: 1, ridgeLambda: 1e-4, standardize: true } },
158
+ datasetPolicy: { split: { valRatio: 0.4, testRatio: 0.4, seed: 42 }, cleaning: { hampelK: 0, maxInterpMs: 1000 } },
159
+ gatePolicyRef: 'process-model.gates@1', modelInterface: { id: 'linear_state_space', version: 1, inputSemantics: 'setpoint', mode: 'state_space' },
160
+ effectiveDomain: { mv: { mv: { min: scene.mv.min, max: scene.mv.max, maxStep: 30 } }, cv: { cv: { min: scene.cv.min, max: scene.cv.max } } }, purpose: 'mpc_surrogate',
161
+ }
162
+ }
163
+ async function startRun(scene) {
164
+ const started = await aw('POST', `/api/workshop/dcw/lines/${scene.line.id}/start`, { recipeId: scene.recipe.id })
165
+ check(`${scene.label}.run.${scene.runs.length}`, 'Real application line start opens a tagged collection window', started.status === 200 && Boolean(started.data?.run?.id), error(started))
166
+ if (started.data?.run?.id) scene.runs.push(started.data.run.id)
167
+ }
168
+ async function trainAndSolve(scene) {
169
+ const spec = specOf(scene)
170
+ const registered = await aw('POST', '/api/workshop/process-model/specs', spec)
171
+ check(`${scene.label}.spec`, 'Scene-specific ProcessModelSpec accepted', registered.status === 200, error(registered))
172
+ await aw('POST', `/api/workshop/process-model/specs/${spec.id}/publish?version=1`)
173
+ const built = await aw('POST', '/api/workshop/process-model/datasets', spec)
174
+ if (built.status !== 200) { record(`${scene.label}.dataset`, 'Simulator-collected dataset/train/solve', 'blocked', error(built)); return }
175
+ check(`${scene.label}.dataset`, 'Dataset built from platform-collected simulator data', built.data?.rowCount >= 1 && built.data?.lineageVerified === 1, built.data)
176
+ const eligible = await aw('POST', '/api/workshop/process-model/eligibility', { specId: spec.id, specVersion: 1, datasetId: built.data.datasetId, scope: 'simulation' })
177
+ const report = eligible.data?.report
178
+ check(`${scene.label}.eligibility`, 'Simulator data eligibility evaluated', eligible.status === 200 && Boolean(report), report || error(eligible))
179
+ const submit = await aw('POST', '/api/workshop/process-model/train', { spec, datasetId: built.data.datasetId, modelName: `${TAG}-${scene.label}` })
180
+ let job = submit.data?.job
181
+ for (let i = 0; job?.id && !['done', 'failed', 'cancelled', 'timeout', 'interrupted'].includes(job.status) && i < 240; i++) {
182
+ await sleep(500)
183
+ job = (await aw('GET', `/api/workshop/aml/jobs/${job.id}`)).data?.job
184
+ }
185
+ if (!job?.modelId || report?.optimizationEligible !== true) { record(`${scene.label}.train`, 'Training, model gates and optimization eligibility', 'blocked', { job, report }); return }
186
+ check(`${scene.label}.train`, 'Simulator-collected data training registers a model', job.status === 'done', { jobId: job.id, modelId: job.modelId })
187
+ const profileId = `${TAG}-${scene.label}-profile`
188
+ const profile = await aw('POST', '/api/workshop/optimization/profiles', { schemaVersion: 1, id: profileId, version: 1, modelRef: { modelId: job.modelId, artifactKind: 'linear_state_space@1', artifactHash: '', modelInterface: 'linear_state_space', stage: 'candidate' }, processSpecRef: `${spec.id}@1`, conditionIds: [], status: 'draft', problemTemplateRef: 'linear_mpc_quadratic@1', solverRef: 'osqp_mpc@1', solverVersion: '1', problemConfig: { linear_mpc_quadratic: { cvWeights: { cv: 1 }, duWeights: { mv: 0.1 }, terminalWeight: 2, targets: { cv: scene.label === 'film' ? 50 : 710 } } } })
189
+ if (profile.status !== 200) { record(`${scene.label}.profile`, 'Simulator-trained Profile creation', 'blocked', error(profile)); return }
190
+ const published = await aw('POST', `/api/workshop/optimization/profiles/${profileId}/publish?version=1`)
191
+ check(`${scene.label}.publish`, 'Simulator-trained Profile publishes', published.status === 200, error(published))
192
+ const channel = (await aw('POST', '/api/workshop/channel-templates/chtpl-aml-optimization-default/instantiate', { name: `${TAG}-${scene.label}` })).data
193
+ const agentId = channel?.leadAgentId || channel?.agents?.find(agent => agent.role === 'lead')?.id
194
+ const workspace = (await aw('POST', '/api/workshop/workspaces', { name: `${TAG}-${scene.label}` })).data
195
+ await aw('POST', `/api/workshop/workspaces/${workspace.id}/channels/${channel.channelId}`)
196
+ const binding = await aw('POST', '/api/workshop/optimization/bindings', { workspaceId: workspace.id, channelId: channel.channelId, agentInstanceId: agentId, profileId, profileVersion: 1, mode: 'recommendation' })
197
+ check(`${scene.label}.binding`, 'Scene-specific Profile binds to its Agent instance', binding.status === 200, error(binding))
198
+ await startRun(scene)
199
+ await sleep(12_000)
200
+ const result = await aw('POST', '/api/workshop/agent-tools/invoke', { agentId, tool: 'optimizer_solve', args: {} })
201
+ let candidate
202
+ try { candidate = JSON.parse(result.data?.result?.text || '{}') }
203
+ catch { /* recorded below */ }
204
+ check(`${scene.label}.solve`, 'Bound agent tool produces a candidate from simulator history', !result.data?.result?.isError && candidate?.status === 'optimal', candidate || result.data || error(result))
205
+ if (candidate?.status === 'optimal') {
206
+ const raw = candidate.firstMove?.mv
207
+ const engineered = candidate.firstMoveEngineering?.mv
208
+ check(`${scene.label}.raw-bounds`, 'Unmodified solver first move satisfies declared simulator domain', Number.isFinite(raw) && raw >= scene.mv.min - 1e-6 && raw <= scene.mv.max + 1e-6, { raw, min: scene.mv.min, max: scene.mv.max })
209
+ check(`${scene.label}.units`, 'Tool exposes engineering and model values consistently for scale=1', Number.isFinite(engineered) && Math.abs(engineered - raw) <= 1e-9, { model: raw, engineering: engineered })
210
+ }
211
+ record(`${scene.label}.dispatch`, 'Production dispatch and benefit benchmark', 'not-run', 'Recommendation only; no automatic dispatch and no claim of 15% benefit/20 paired runs')
212
+ }
213
+ if (process.argv.includes('--simulator-only')) {
214
+ await bootSimulator()
215
+ writeFileSync(join(REPO, '.omc', 'optimizer-full-live-20261023', 'simulator-context.json'), JSON.stringify({ root: ROOT, base: SIM, port: SIM_PORT, mqttPort: MQTT_PORT, pid: simulator.pid }, null, 2))
216
+ console.log(`Isolated simulator ready ${SIM}, root=${ROOT}`)
217
+ await new Promise(() => setInterval(() => {}, 60_000))
218
+ }
219
+ try {
220
+ await bootSimulator()
221
+ await loadScene('cast-film-physics', 'film', 'ScrewSpeedSP', 'thick', 'dev-extruder-opcua')
222
+ await loadScene('anneal-line', 'anneal', '均热区3炉温SP', 'StripTemp', 'anneal-heating-mbtcp')
223
+ const daq = await aw('GET', '/api/workshop/daq')
224
+ check('infra.observed', 'DAQ infrastructure state is explicitly observed', daq.status === 200, { infra: daq.data?.infra, meta: daq.data?.meta })
225
+ const healthy = daq.data?.infra?.degraded === false
226
+ const seconds = Number(process.env.AW_PHYSICAL_COLLECT_SECONDS || (healthy ? 120 : 20))
227
+ const runs = healthy && seconds >= 60 ? Number(process.env.AW_PHYSICAL_RUNS || 6) : 1
228
+ for (let run = 0; run < runs; run++) {
229
+ for (const scene of scenes) await startRun(scene)
230
+ for (let elapsed = 0; elapsed < seconds; elapsed++) {
231
+ if (healthy && elapsed >= 60 && elapsed % 60 === 0) {
232
+ for (const scene of scenes) {
233
+ const value = scene.initial + (run % 2 === 0 ? 15 : -15)
234
+ const changed = await aw('POST', `/api/workshop/dcw/${scene.control.id}/write`, { value })
235
+ check(`${scene.label}.stimulus.${run}.${elapsed}`, 'Governed online parameter step through DCW', changed.status === 200 && changed.data?.outcome?.ok === true, changed.data?.outcome || error(changed))
236
+ }
237
+ }
238
+ if (elapsed % 30 === 0) console.log(`COLLECT run=${run + 1}/${runs} elapsed=${elapsed}/${seconds}s healthy=${healthy}`)
239
+ await sleep(1000)
240
+ }
241
+ for (const scene of scenes) await aw('POST', `/api/workshop/dcw/lines/${scene.line.id}/stop`)
242
+ }
243
+ for (const scene of scenes) {
244
+ const samples = await aw('GET', `/api/workshop/daq/${scene.daq[1].id}/samples?bucketMs=1000&limit=1000`)
245
+ const points = samples.data?.points || []
246
+ const name = `${scene.label}.collection`
247
+ if (!points.length && !healthy) record(name, 'Simulator samples persisted by platform DAQ', 'blocked', { reason: 'DAQ infrastructure degraded: application disables online acquisition', infra: daq.data?.infra, points: points.length })
248
+ else check(name, 'Simulator samples persisted by platform DAQ', points.length > 5, { points: points.length, tail: points.slice(-2) })
249
+ await trainAndSolve(scene)
250
+ }
251
+ }
252
+ catch (err) { record('harness', 'Simulator harness execution', 'fail', err instanceof Error ? err.stack : String(err)) }
253
+ finally {
254
+ for (const scene of scenes) {
255
+ await aw('POST', `/api/workshop/dcw/lines/${scene.line.id}/stop`).catch(() => {})
256
+ for (const node of scene.daq) await aw('PATCH', `/api/workshop/daq/${node.id}`, { enabled: false }).catch(() => {})
257
+ await aw('PATCH', `/api/workshop/dcw/${scene.control.id}`, { enabled: false }).catch(() => {})
258
+ }
259
+ simulator?.kill()
260
+ const counts = Object.fromEntries(['pass', 'fail', 'blocked', 'not-run'].map(status => [status, checks.filter(item => item.status === status).length]))
261
+ writeFileSync(join(EVID, 'report.json'), JSON.stringify({ at: new Date().toISOString(), base: BASE, simulator: SIM, simulatorRoot: process.env.AW_PHYSICAL_SIM_ROOT || ROOT, applicationHome: context.home, counts, scope: { businessInstanceTouched: false, originalSimulatorTouched: false, realHardwareTouched: false, truthConsumed: false, benefitBenchmark: false, realAgentLlm: false }, scenes: scenes.map(scene => ({ scene: scene.label, lineId: scene.line.id, recipeId: scene.recipe?.id, runs: scene.runs })), checks }, null, 2))
262
+ console.log(JSON.stringify({ counts, report: join(EVID, 'report.json') }))
263
+ process.exitCode = counts.fail ? 1 : counts.blocked ? 2 : 0
264
+ }
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Deterministic OMP-RPC transport fixture for the registered `omp` adapter.
4
+ *
5
+ * This is deliberately not an LLM, planner, or harness decision. It emits the
6
+ * single recipe_trial call supplied by the isolated E2E driver, then records
7
+ * the shared-dispatch result returned by AgentWorkShop over OMP-RPC stdio.
8
+ */
9
+ import { mkdirSync, writeFileSync } from 'node:fs'
10
+ import { dirname, isAbsolute, relative, resolve, sep } from 'node:path'
11
+
12
+ const args = process.argv.slice(2)
13
+ const valueFor = (name) => {
14
+ const index = args.indexOf(name)
15
+ return index >= 0 ? args[index + 1] : undefined
16
+ }
17
+ const scene = valueFor('--scene')
18
+ const recipeId = valueFor('--recipe-id')
19
+ const nodeId = valueFor('--node-id')
20
+ const value = Number(valueFor('--value'))
21
+ const traceRootArg = valueFor('--trace-root')
22
+ const tracePathArg = valueFor('--trace-path')
23
+ const traceRoot = traceRootArg ? resolve(traceRootArg) : ''
24
+ const tracePath = tracePathArg ? resolve(tracePathArg) : ''
25
+ const relativeTracePath = traceRoot && tracePath ? relative(traceRoot, tracePath) : ''
26
+ const expectedTracePath = traceRoot && ['cast-film', 'annealing'].includes(scene)
27
+ ? resolve(traceRoot, `fixture-${scene}.json`)
28
+ : ''
29
+
30
+ if (!['cast-film', 'annealing'].includes(scene)
31
+ || !recipeId
32
+ || !nodeId
33
+ || !Number.isFinite(value)
34
+ || !traceRoot
35
+ || !tracePath
36
+ || isAbsolute(relativeTracePath)
37
+ || relativeTracePath === '..'
38
+ || relativeTracePath.startsWith(`..${sep}`)
39
+ || tracePath !== expectedTracePath) {
40
+ process.stderr.write('fixture arguments incomplete\n')
41
+ process.exit(64)
42
+ }
43
+
44
+ const trace = {
45
+ fixture: 'deterministic-local-omp-rpc-transport',
46
+ decisionSource: 'predeclared-test-vector; not an LLM or harness decision',
47
+ scene,
48
+ hostToolCalls: [],
49
+ hostToolResults: [],
50
+ }
51
+ mkdirSync(dirname(resolve(tracePath)), { recursive: true })
52
+ writeFileSync(tracePath, `${JSON.stringify(trace, null, 2)}\n`, 'utf8')
53
+
54
+ let input = ''
55
+ let promptCount = 0
56
+ let callCount = 0
57
+ let awaitingToolResult = null
58
+
59
+ function send(frame) {
60
+ process.stdout.write(`${JSON.stringify(frame)}\n`)
61
+ }
62
+
63
+ function persist() {
64
+ writeFileSync(tracePath, `${JSON.stringify(trace, null, 2)}\n`, 'utf8')
65
+ }
66
+
67
+ function response(frame, data = {}) {
68
+ send({ type: 'response', id: frame.id, command: frame.type, success: true, data })
69
+ }
70
+
71
+ function onFrame(frame) {
72
+ if (!frame || typeof frame !== 'object' || typeof frame.type !== 'string') return
73
+
74
+ if (frame.type === 'host_tool_result') {
75
+ if (awaitingToolResult && frame.id === awaitingToolResult.id) {
76
+ trace.hostToolResults.push({
77
+ id: frame.id,
78
+ result: frame.result ?? null,
79
+ receivedAt: new Date().toISOString(),
80
+ })
81
+ awaitingToolResult = null
82
+ persist()
83
+ send({ type: 'agent_end', isTerminal: true, messages: [] })
84
+ }
85
+ return
86
+ }
87
+
88
+ if (frame.type === 'prompt') {
89
+ promptCount += 1
90
+ if (promptCount !== 1 || callCount !== 0) {
91
+ trace.protocolError = 'expected exactly one prompt and one host_tool_call per scene'
92
+ persist()
93
+ send({ type: 'agent_end', isTerminal: true, messages: [] })
94
+ return
95
+ }
96
+
97
+ callCount += 1
98
+ const id = `paper-${scene}-${Date.now().toString(36)}`
99
+ const toolCallId = `${id}-tc`
100
+ const toolCall = {
101
+ type: 'host_tool_call',
102
+ id,
103
+ toolCallId,
104
+ toolName: 'recipe_trial',
105
+ arguments: {
106
+ recipe_id: recipeId,
107
+ params: [{ node_id: nodeId, value }],
108
+ hypothesis: `Deterministic simulator integration check for ${scene}; apply one bounded candidate and verify the device ACK/readback.`,
109
+ },
110
+ }
111
+ trace.hostToolCalls.push({
112
+ id,
113
+ toolCallId,
114
+ toolName: toolCall.toolName,
115
+ arguments: toolCall.arguments,
116
+ emittedAt: new Date().toISOString(),
117
+ })
118
+ awaitingToolResult = { id }
119
+ persist()
120
+ send(toolCall)
121
+ return
122
+ }
123
+
124
+ if (frame.type === 'set_host_tools' || frame.type === 'set_auto_compaction' || frame.type === 'get_state') {
125
+ response(frame, frame.type === 'get_state'
126
+ ? { sessionId: `paper-fixture-${scene}`, model: { contextWindow: 8192 } }
127
+ : {})
128
+ return
129
+ }
130
+
131
+ if (typeof frame.id === 'string' && frame.type !== 'host_tool_cancel') {
132
+ response(frame, {})
133
+ }
134
+ }
135
+
136
+ process.stdin.setEncoding('utf8')
137
+ process.stdin.on('data', (chunk) => {
138
+ input += chunk
139
+ const lines = input.split('\n')
140
+ input = lines.pop() ?? ''
141
+ for (const line of lines) {
142
+ const text = line.trim()
143
+ if (!text) continue
144
+ try {
145
+ onFrame(JSON.parse(text))
146
+ }
147
+ catch (error) {
148
+ trace.protocolError = error instanceof Error ? error.message : String(error)
149
+ persist()
150
+ }
151
+ }
152
+ })
153
+ process.stdin.on('end', () => {
154
+ trace.stdinClosedAt = new Date().toISOString()
155
+ persist()
156
+ })
157
+ process.on('uncaughtException', (error) => {
158
+ trace.protocolError = error instanceof Error ? error.message : String(error)
159
+ persist()
160
+ process.exitCode = 70
161
+ })
162
+
163
+ send({ type: 'ready' })
package/sdk/context.mjs CHANGED
@@ -529,6 +529,12 @@ export function createPluginContext(opts) {
529
529
  body: JSON.stringify(body ?? {}),
530
530
  ...safeUrl(url, opts2.timeoutMs),
531
531
  }),
532
+ patch: (url, body, opts2 = {}) => fetch(url, {
533
+ method: 'PATCH',
534
+ headers: { 'content-type': 'application/json', ...(opts2.headers ?? {}) },
535
+ body: JSON.stringify(body ?? {}),
536
+ ...safeUrl(url, opts2.timeoutMs),
537
+ }),
532
538
  },
533
539
  events: {
534
540
  on: (type, fn) => hooks.on(type === '*' ? '*' : `event:${type}`, fn),
package/sdk/index.d.mts CHANGED
@@ -41,6 +41,8 @@ export interface PluginKv {
41
41
  export interface PluginHttp {
42
42
  get(url: string, opts?: { timeoutMs?: number, headers?: Record<string, string> }): Promise<Response>
43
43
  post(url: string, body?: unknown, opts?: { timeoutMs?: number, headers?: Record<string, string> }): Promise<Response>
44
+ /** JSON PATCH(与 post 同构:同协议白名单/超时/头部合并) */
45
+ patch(url: string, body?: unknown, opts?: { timeoutMs?: number, headers?: Record<string, string> }): Promise<Response>
44
46
  }
45
47
 
46
48
  /** 资源面公共形状 —— 对应 sdk/api.mjs 的 `resource(root)`,每个资源都有完整五项。
@@ -1,30 +1,36 @@
1
- /**
2
- * PATCH /api/workshop/aml/models/:id —— 更新模型元数据(备注)。
3
- * body: { note: string }
4
- * 阶段变更不走这里(必须走 /promote,那里有 ONNX 深检与同组唯一性保护)。
5
- */
6
- import { getRouterParam, readBody } from 'h3'
7
- import { defineApiHandler } from '@/server/utils/response'
8
- import { requireRole } from '@/server/api/workshop/caller'
9
- import { requireLineMode } from '@/server/services/workshop/permissions'
10
- import { AppError } from '@/server/utils/errors'
11
- import { getAmlRuntime } from '@/server/services/workshop/aml/runtime'
12
- import { recordOps } from '@/server/services/workshop/ops/ops'
13
-
14
- export default defineApiHandler(async (event) => {
15
- const user = requireRole(event, ['admin', 'editor'])
16
- const id = getRouterParam(event, 'id') ?? ''
17
- const body = await readBody<{ note?: string }>(event) ?? {}
18
- const rt = getAmlRuntime()
19
- const model = rt.repo.model.get(id)
20
- if (!model) throw new AppError(404, 'AML_MODEL_MISSING', `模型 ${id} 不存在`)
21
- requireLineMode(user, rt.repo.dataset.get(model.datasetId)?.lineId, 'operate')
22
- if (typeof body.note === 'string') rt.repo.model.updateNote(id, body.note.slice(0, 2000))
23
- recordOps({
24
- actor: user.id, actorName: user.name, actorKind: 'user',
25
- action: 'aml.model.update', kind: 'system',
26
- summary: `更新模型 ${id} 元数据(备注)`,
27
- targetKind: 'aml_model', targetId: id,
28
- })
29
- return { model: rt.repo.model.get(id) }
30
- })
1
+ /**
2
+ * PATCH /api/workshop/aml/models/:id —— 更新模型元数据(备注)。
3
+ * body: { note?: string, label?: string, description?: string }
4
+ * 阶段变更不走这里(必须走 /promote,那里有 ONNX 深检与同组唯一性保护)。
5
+ */
6
+ import { getRouterParam, readBody } from 'h3'
7
+ import { defineApiHandler } from '@/server/utils/response'
8
+ import { requireRole } from '@/server/api/workshop/caller'
9
+ import { requireLineMode } from '@/server/services/workshop/permissions'
10
+ import { AppError } from '@/server/utils/errors'
11
+ import { getAmlRuntime } from '@/server/services/workshop/aml/runtime'
12
+ import { recordOps } from '@/server/services/workshop/ops/ops'
13
+
14
+ export default defineApiHandler(async (event) => {
15
+ const user = requireRole(event, ['admin', 'editor'])
16
+ const id = getRouterParam(event, 'id') ?? ''
17
+ const body = await readBody<{ note?: string, label?: string, description?: string }>(event) ?? {}
18
+ const rt = getAmlRuntime()
19
+ const model = rt.repo.model.get(id)
20
+ if (!model) throw new AppError(404, 'AML_MODEL_MISSING', `模型 ${id} 不存在`)
21
+ requireLineMode(user, rt.repo.dataset.get(model.datasetId)?.lineId, 'operate')
22
+ if (typeof body.note === 'string') rt.repo.model.updateNote(id, body.note.slice(0, 2000))
23
+ if (typeof body.label === 'string' || typeof body.description === 'string') {
24
+ rt.repo.model.updateIdentity(id, {
25
+ ...(typeof body.label === 'string' ? { label: body.label } : {}),
26
+ ...(typeof body.description === 'string' ? { description: body.description } : {}),
27
+ })
28
+ }
29
+ recordOps({
30
+ actor: user.id, actorName: user.name, actorKind: 'user',
31
+ action: 'aml.model.update', kind: 'system',
32
+ summary: `更新模型 ${id} 元数据(备注/名称/描述)`,
33
+ targetKind: 'aml_model', targetId: id,
34
+ })
35
+ return { model: rt.repo.model.get(id) }
36
+ })
@@ -0,0 +1,31 @@
1
+ /**
2
+ * POST /api/workshop/ontology/drafts/:draftId/autofix — 自动修复草稿
3
+ *
4
+ * 只做安全、确定、幂等的规范化(补描述/量纲跟随单位/作用域回填/悬空引用与重复 id
5
+ * 的确定性修复/证据不足的控制级状态回退);证据本身不会被伪造,平台侧绑定漂移仍在
6
+ * bindings.failures 中如实返回。写路径与 updateDraft 同源(乐观锁 rev + 审计)。
7
+ */
8
+ import { getRouterParam } from 'h3'
9
+ import { defineApiHandler } from '@/server/utils/response'
10
+ import { requireRole, resolveUser } from '@/server/api/workshop/caller'
11
+ import { AppError } from '@/server/utils/errors'
12
+ import { actorFromUser, autoFixDraft } from '@/server/services/workshop/ontology/ontology.service'
13
+ import { recordConfigAction } from '@/server/services/workshop/optimization/access'
14
+
15
+ export default defineApiHandler(async (event) => {
16
+ const draftId = getRouterParam(event, 'draftId') ?? ''
17
+ if (!draftId) throw new AppError(422, 'DRAFT_ID_REQUIRED', 'draftId 缺失')
18
+ const user = requireRole(event, ['admin', 'editor'])
19
+ const detail = autoFixDraft(draftId, actorFromUser(user))
20
+ recordConfigAction(user, 'ontology.draft.autofix', { kind: 'ontology_draft', id: draftId },
21
+ `自动修复本体草稿 ${draftId}(${detail.fixes.length} 项)`, { rev: detail.draft.rev, fixes: detail.fixes.length })
22
+ return {
23
+ draft: { id: detail.draft.id, ontologyId: detail.draft.ontologyId, rev: detail.draft.rev, baseVersion: detail.draft.baseVersion },
24
+ doc: detail.doc,
25
+ validation: detail.validation,
26
+ bindings: detail.bindings,
27
+ fixes: detail.fixes,
28
+ fixedCount: detail.fixes.length,
29
+ actor: resolveUser(event).id,
30
+ }
31
+ })
@@ -0,0 +1,24 @@
1
+ /**
2
+ * GET /api/workshop/ontology/drafts/:draftId/subgraph?entity=&hops=&direction=&kinds=&limit=
3
+ *
4
+ * 草稿子图(供 /ontology 页面:图、表格与抽屉同源,不会出现「图画草稿、抽屉查已发布」的错位)。
5
+ * 只读;沿用草稿的属主/管理员访问规则(getDraftDetail 内部裁决)。
6
+ */
7
+ import { getQuery, getRouterParam } from 'h3'
8
+ import { defineApiHandler } from '@/server/utils/response'
9
+ import { resolveUser } from '@/server/api/workshop/caller'
10
+ import { AppError } from '@/server/utils/errors'
11
+ import { actorFromUser, getDraftDetail } from '@/server/services/workshop/ontology/ontology.service'
12
+ import { parseSubgraphOptions } from '@/server/services/workshop/ontology/subgraph.core'
13
+ import { requireEntityKey, subgraphAroundDoc } from '@/server/services/workshop/ontology/subgraph.service'
14
+
15
+ export default defineApiHandler(async (event) => {
16
+ const draftId = getRouterParam(event, 'draftId') ?? ''
17
+ if (!draftId) throw new AppError(422, 'DRAFT_ID_REQUIRED', 'draftId 缺失')
18
+ const user = resolveUser(event)
19
+ const query = getQuery(event)
20
+ const entityKey = requireEntityKey(query.entity)
21
+ const opts = parseSubgraphOptions(query)
22
+ const detail = getDraftDetail(draftId, actorFromUser(user))
23
+ return { draftId, subgraph: subgraphAroundDoc(detail.doc, entityKey, opts) }
24
+ })
@@ -1,20 +1,33 @@
1
1
  /**
2
2
  * GET /api/workshop/ontology/scene?lineId= — 运行时语义子图(绑定面实体 + 关系 + 规则决策 + 守卫)
3
- * GET /api/workshop/ontology/scene?lineId=&guards=1&values=... — 附运行时守卫求值
3
+ * GET /api/workshop/ontology/scene?lineId=&entity=&hops=&direction=&kinds=&limit= — 以实体为中心的邻接/多跳子图
4
4
  *
5
5
  * 这是 Agent 上下文与 MCP 只读工具的共同数据面;只读、只回已发布版本。
6
+ * 两个模式互不干扰:未给 entity 时行为与历史完全一致(全图);给了 entity 才走子图并校验新参数。
6
7
  */
7
8
  import { getQuery } from 'h3'
8
9
  import { defineApiHandler } from '@/server/utils/response'
9
10
  import { resolveUser } from '@/server/api/workshop/caller'
10
11
  import { AppError } from '@/server/utils/errors'
11
12
  import { sceneSubgraph } from '@/server/services/workshop/ontology/ontology.service'
13
+ import { parseSubgraphOptions } from '@/server/services/workshop/ontology/subgraph.core'
14
+ import { requireEntityKey, subgraphAroundForLine } from '@/server/services/workshop/ontology/subgraph.service'
12
15
 
13
16
  export default defineApiHandler(async (event) => {
14
17
  resolveUser(event)
15
18
  const query = getQuery(event)
16
19
  const lineId = typeof query.lineId === 'string' ? query.lineId : ''
17
20
  if (!lineId) throw new AppError(422, 'LINE_REQUIRED', 'lineId 必填')
21
+
22
+ // 子图模式:仅显式给出 entity 时启用,旧调用零漂移
23
+ if (query.entity !== undefined) {
24
+ const entityKey = requireEntityKey(query.entity)
25
+ const opts = parseSubgraphOptions(query)
26
+ const subgraph = subgraphAroundForLine(lineId, entityKey, opts)
27
+ if (!subgraph) return { lineId, active: false, subgraph: null }
28
+ return { lineId, active: true, subgraph }
29
+ }
30
+
18
31
  const graph = sceneSubgraph(lineId, { limit: query.limit !== undefined ? Math.min(500, Math.max(1, Number(query.limit))) : 200 })
19
32
  if (!graph) return { lineId, active: false, graph: null }
20
33
  return { lineId, active: true, graph }