agentworkshop 0.8.5 → 0.8.6

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 (349) hide show
  1. package/.AgentWorkShop/prompts/host-tools.en.json +3 -3
  2. package/.AgentWorkShop/prompts/host-tools.json +14 -4
  3. package/.output/.AgentWorkShop/prompts/host-tools.en.json +3 -3
  4. package/.output/.AgentWorkShop/prompts/host-tools.json +14 -4
  5. package/.output/nitro.json +1 -1
  6. package/.output/public/_nuxt/{U_n8pryv2.js → 7op-BMk82.js} +1 -1
  7. package/.output/public/_nuxt/{zWZ26UWi.js → B1SIgyrl.js} +1 -1
  8. package/.output/public/_nuxt/{C4tXwpSt.js → BA2lmfW4.js} +1 -1
  9. package/.output/public/_nuxt/{EJkmXP432.js → BDXQqSkl2.js} +1 -1
  10. package/.output/public/_nuxt/{CY_7u1ST2.js → BI9jj13f2.js} +1 -1
  11. package/.output/public/_nuxt/{CGf9neEK2.js → BiXqyYNw2.js} +1 -1
  12. package/.output/public/_nuxt/{D9GoOkyP2.js → BlOm8JIs2.js} +1 -1
  13. package/.output/public/_nuxt/{CQ31GiJU2.js → BoXKUOiN2.js} +1 -1
  14. package/.output/public/_nuxt/{DZzbCFY2.js → BuLoPmcf.js} +1 -1
  15. package/.output/public/_nuxt/{D9ppMCbw.js → BwOK42JQ.js} +1 -1
  16. package/.output/public/_nuxt/{CZJ5cw6r2.js → C1RMfPoB2.js} +1 -1
  17. package/.output/public/_nuxt/{CGviZq4E.js → COfo_Bg3.js} +1 -1
  18. package/.output/public/_nuxt/CTGJHZ8X2.js +1 -0
  19. package/.output/public/_nuxt/{SgsmmrsZ.js → CY2NkFvI.js} +1 -1
  20. package/.output/public/_nuxt/{B4GOTVfN.js → C_4mzQ5X.js} +1 -1
  21. package/.output/public/_nuxt/{DGmFHb7m.js → CdvMP3lv.js} +1 -1
  22. package/.output/public/_nuxt/{iqxZGXsY.js → CooauJ7D.js} +1 -1
  23. package/.output/public/_nuxt/{C3vxePED.js → D1eVi1zr.js} +1 -1
  24. package/.output/public/_nuxt/{DnuJ66Jy.js → D6PUmBb0.js} +1 -1
  25. package/.output/public/_nuxt/{BBhroEeN.js → DC8sMA36.js} +1 -1
  26. package/.output/public/_nuxt/{DOUuGOQR2.js → DDHh85c42.js} +1 -1
  27. package/.output/public/_nuxt/{Cy_HDgSl.js → DDXOfmo2.js} +2 -2
  28. package/.output/public/_nuxt/{Cr2xJ_CY.js → DMFwLxfu.js} +1 -1
  29. package/.output/public/_nuxt/{BZg_MIK42.js → DoprKJ5a2.js} +1 -1
  30. package/.output/public/_nuxt/{BzBBEE-o2.js → Dr1FVeQG2.js} +1 -1
  31. package/.output/public/_nuxt/{W0sNnJQh.js → DtnsTW7e.js} +1 -1
  32. package/.output/public/_nuxt/{gUYi1hLJ2.js → DxDqd6T42.js} +1 -1
  33. package/.output/public/_nuxt/{B0UUODeh.js → DzU3zEKX.js} +1 -1
  34. package/.output/public/_nuxt/{BkO5WdX5.js → EgO70wrE.js} +1 -1
  35. package/.output/public/_nuxt/{7OZQiw002.js → HJKu4eEV2.js} +1 -1
  36. package/.output/public/_nuxt/{ChF6qLpY2.js → K5Xen0wZ2.js} +1 -1
  37. package/.output/public/_nuxt/{CNrRZmSx2.js → Rb4o4o-82.js} +1 -1
  38. package/.output/public/_nuxt/{BqBTlfiz.js → Tf6SJSDj.js} +1 -1
  39. package/.output/public/_nuxt/{DJaGVY4v2.js → ZzOyoXex2.js} +1 -1
  40. package/.output/public/_nuxt/{PbzVdCTA2.js → azOGy_tU2.js} +1 -1
  41. package/.output/public/_nuxt/{D1thFC3z.js → be-4wyTo.js} +1 -1
  42. package/.output/public/_nuxt/builds/latest.json +1 -1
  43. package/.output/public/_nuxt/builds/meta/593b65bd-cf1d-4b7f-a993-57e939c38f36.json +1 -0
  44. package/.output/public/_nuxt/{8b9CKi6F.js → dcjPjLPI.js} +1 -1
  45. package/.output/public/_nuxt/{ae2-5ZPt.js → h-Fn7pRD.js} +1 -1
  46. package/.output/public/_nuxt/{-gy9k_TE2.js → hyLdZsOd2.js} +1 -1
  47. package/.output/public/_nuxt/{BHxG41IQ2.js → o8sYG6xx2.js} +1 -1
  48. package/.output/server/chunks/_/access.mjs +1 -1
  49. package/.output/server/chunks/_/agent-dto.mjs +26 -0
  50. package/.output/server/chunks/_/agent-dto.mjs.map +1 -0
  51. package/.output/server/chunks/_/data-export.mjs +6 -6
  52. package/.output/server/chunks/_/data-query.mjs +3 -3
  53. package/.output/server/chunks/_/eda-run.repo.mjs +2 -2
  54. package/.output/server/chunks/_/features.mjs +5 -5
  55. package/.output/server/chunks/_/golden.mjs +3 -3
  56. package/.output/server/chunks/_/harness-spawn-policy.mjs +77 -0
  57. package/.output/server/chunks/_/harness-spawn-policy.mjs.map +1 -0
  58. package/.output/server/chunks/_/index.mjs +1 -1
  59. package/.output/server/chunks/_/line-scope.mjs +32 -0
  60. package/.output/server/chunks/_/line-scope.mjs.map +1 -0
  61. package/.output/server/chunks/_/mes-console.mjs +1 -1
  62. package/.output/server/chunks/_/nitro.mjs +2429 -1726
  63. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  64. package/.output/server/chunks/_/ocap.mjs +1 -1
  65. package/.output/server/chunks/_/rest-auth.mjs +1 -1
  66. package/.output/server/chunks/_/spc.mjs +1 -1
  67. package/.output/server/chunks/build/TownView-BWMDbosY.mjs +1 -1
  68. package/.output/server/chunks/build/daq-CdxcfY_G.mjs +1 -1
  69. package/.output/server/chunks/build/dcw-BlDQtS4q.mjs +1 -1
  70. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  71. package/.output/server/chunks/build/useDaqAddNode-D_Rkju0f.mjs +1 -1
  72. package/.output/server/chunks/build/useDaqDetailNode-DeOsDxK5.mjs +1 -1
  73. package/.output/server/chunks/build/useDaqDetailParams-Cm9a9r5G.mjs +1 -1
  74. package/.output/server/chunks/build/useDaqFilters-CctmO03p.mjs +1 -1
  75. package/.output/server/chunks/build/useDaqStream-B9ZBVQrI.mjs +1 -1
  76. package/.output/server/chunks/build/useDaqTemplates-CK37sMfi.mjs +1 -1
  77. package/.output/server/chunks/build/useDcwAddNode-DACVcEHs.mjs +1 -1
  78. package/.output/server/chunks/build/useDcwStream-Dir5ufAU.mjs +1 -1
  79. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  80. package/.output/server/chunks/routes/api/system/backup/run.post.mjs +2 -2
  81. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +17 -9
  82. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs.map +1 -1
  83. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +3 -0
  84. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs.map +1 -1
  85. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  86. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +6 -0
  87. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs.map +1 -1
  88. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +5 -0
  89. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs.map +1 -1
  90. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +5 -2
  91. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs.map +1 -1
  92. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +7 -1
  93. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs.map +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +3 -1
  95. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs.map +1 -1
  96. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +8 -6
  97. package/.output/server/chunks/routes/api/workshop/channels.post.mjs.map +1 -1
  98. package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs +29 -49
  99. package/.output/server/chunks/routes/api/workshop/daq/_id/ingest.post.mjs.map +1 -1
  100. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +6 -1
  102. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs.map +1 -1
  103. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +4 -2
  104. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs.map +1 -1
  105. package/.output/server/chunks/routes/api/workshop/daq/index2.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +14 -5
  107. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs.map +1 -1
  108. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
  109. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
  110. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
  111. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +7 -4
  112. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs.map +1 -1
  113. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +6 -2
  116. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs.map +1 -1
  117. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +6 -2
  118. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs.map +1 -1
  119. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
  120. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
  121. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
  122. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +6 -1
  123. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs.map +1 -1
  124. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
  125. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +7 -4
  126. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs.map +1 -1
  127. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
  128. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
  129. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
  130. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +6 -2
  131. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs.map +1 -1
  132. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
  133. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +7 -4
  134. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs.map +1 -1
  135. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
  136. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
  137. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  138. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +6 -2
  139. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs.map +1 -1
  140. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
  141. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
  142. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  143. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  144. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  145. package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs +6 -2
  146. package/.output/server/chunks/routes/api/workshop/dcw/mes-artifacts/file.get.mjs.map +1 -1
  147. package/.output/server/chunks/routes/api/workshop/dcw/mes-hook-test.post.mjs +1 -1
  148. package/.output/server/chunks/routes/api/workshop/dcw/mes-test-read.post.mjs +1 -1
  149. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
  150. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
  151. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +6 -2
  152. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs.map +1 -1
  153. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +4 -2
  154. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs.map +1 -1
  155. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +5 -2
  156. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs.map +1 -1
  157. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +1 -1
  158. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  159. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
  163. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
  164. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs +7 -3
  165. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs.map +1 -1
  166. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +8 -1
  167. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs.map +1 -1
  168. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +6 -2
  169. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs.map +1 -1
  170. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  173. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  174. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +7 -4
  175. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs.map +1 -1
  176. package/.output/server/chunks/routes/api/workshop/eda/commonality.get.mjs +1 -1
  177. package/.output/server/chunks/routes/api/workshop/eda/vm/predict.post.mjs +1 -1
  178. package/.output/server/chunks/routes/api/workshop/exp/confirmations/_id/decide.post.mjs +1 -1
  179. package/.output/server/chunks/routes/api/workshop/exp/index.get.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/index.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/index.post.mjs +2 -0
  187. package/.output/server/chunks/routes/api/workshop/index.post.mjs.map +1 -1
  188. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +8 -3
  190. package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
  191. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
  192. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  193. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  194. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/mes/datasets.get.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/autofix.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/compile.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/evidence.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/publish.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval-decision.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/approval.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/rules/_ruleId/transition.mjs +1 -1
  203. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/subgraph.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId/validate.mjs +1 -1
  205. package/.output/server/chunks/routes/api/workshop/ontology/drafts/_draftId_.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/ontology/export/_ontologyId_.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/ontology/index.mjs +1 -1
  208. package/.output/server/chunks/routes/api/workshop/ontology/scene.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/ontology/traces/_ontologyId_.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId/compare.mjs +1 -1
  211. package/.output/server/chunks/routes/api/workshop/ontology/versions/_ontologyId_.mjs +1 -1
  212. package/.output/server/chunks/routes/api/workshop/optimization/capabilities.get.mjs +1 -1
  213. package/.output/server/chunks/routes/api/workshop/optimization/index.get.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/optimization/index.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/optimization/index2.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/optimization/profiles/_id/publish.post.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/crosscheck.post.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/optimization/recommendations/_id/dispatch.post.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/optimization/solve.post.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/process-model/datasets.post.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/process-model/eligibility.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/process-model/index.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/process-model/specs/_id/publish.post.mjs +1 -1
  226. package/.output/server/chunks/routes/api/workshop/process-model/train.post.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  228. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  229. package/.output/server/chunks/routes/api/workshop/tools/sync.post.mjs +1 -1
  230. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  231. package/.output/server/chunks/routes/renderer.mjs +2 -2
  232. package/.output/server/chunks/virtual/entry.mjs +1 -1
  233. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  234. package/.output/server/package.json +1 -1
  235. package/README-zh.md +4 -2
  236. package/README.md +9 -2
  237. package/config.yml +1 -1
  238. package/docker-compose.yml +4 -2
  239. package/docs/cli.en.md +2 -2
  240. package/docs/cli.md +2 -2
  241. package/docs/plugins.en.md +1 -1
  242. package/docs/plugins.md +1 -1
  243. package/docs/sdk.en.md +1 -1
  244. package/docs/sdk.md +1 -1
  245. package/package.json +1 -1
  246. package/scripts/_audit/_live-mqtt-e2e-20261028.mjs +219 -0
  247. package/scripts/_audit/prompt-injection-probe.mts +76 -0
  248. package/scripts/api-live-e2e.mjs +9 -3
  249. package/scripts/e2e-multiexpert-remediation-real.mjs +453 -0
  250. package/scripts/e2e-node-binding-3mode-real.mjs +697 -0
  251. package/scripts/e2e-node-binding-authz.mjs +332 -0
  252. package/scripts/security-acceptance.mjs +218 -0
  253. package/server/api/workshop/agent-tools/bindings/index.post.ts +33 -17
  254. package/server/api/workshop/agents/[id].patch.ts +3 -0
  255. package/server/api/workshop/agents/index.post.ts +3 -0
  256. package/server/api/workshop/channel-templates/[id].patch.ts +5 -0
  257. package/server/api/workshop/channel-templates/index.post.ts +6 -0
  258. package/server/api/workshop/channels/[id]/agents/[agentId].patch.ts +5 -0
  259. package/server/api/workshop/channels/[id]/agents/index.get.ts +8 -2
  260. package/server/api/workshop/channels/[id]/agents/index.post.ts +7 -0
  261. package/server/api/workshop/channels/[id]/index.get.ts +10 -4
  262. package/server/api/workshop/channels.post.ts +3 -0
  263. package/server/api/workshop/daq/[id]/ingest.post.ts +26 -22
  264. package/server/api/workshop/daq/[id].patch.ts +8 -0
  265. package/server/api/workshop/daq/alarms.get.ts +18 -16
  266. package/server/api/workshop/daq/infra/reconnect.post.ts +21 -5
  267. package/server/api/workshop/daq/test-driver.post.ts +10 -3
  268. package/server/api/workshop/dcw/[id]/param-ledger.get.ts +7 -1
  269. package/server/api/workshop/dcw/[id]/read.post.ts +6 -1
  270. package/server/api/workshop/dcw/[id].patch.ts +49 -40
  271. package/server/api/workshop/dcw/journal/index.get.ts +7 -3
  272. package/server/api/workshop/dcw/mes-artifacts/file.get.ts +7 -1
  273. package/server/api/workshop/dcw/mes-artifacts/index.get.ts +7 -1
  274. package/server/api/workshop/dcw/optimizations/[id]/series.get.ts +6 -1
  275. package/server/api/workshop/dcw/optimizations/[id].get.ts +3 -1
  276. package/server/api/workshop/dcw/optimizations/index.get.ts +6 -3
  277. package/server/api/workshop/dcw/params/[id]/read.post.ts +22 -17
  278. package/server/api/workshop/dcw/recipes/[id]/versions.get.ts +20 -14
  279. package/server/api/workshop/dcw/recipes/[id].delete.ts +33 -25
  280. package/server/api/workshop/dcw/recipes/index.get.ts +17 -12
  281. package/server/api/workshop/dcw/runs/[id]/close.post.ts +21 -15
  282. package/server/api/workshop/dcw/test-driver.post.ts +21 -16
  283. package/server/api/workshop/ws/hub.ts +2 -1
  284. package/server/plugins/01-instance-guard.ts +82 -0
  285. package/server/plugins/daq.ts +40 -8
  286. package/server/plugins/workshop.ts +12 -0
  287. package/server/services/workshop/agents/adapters/line-spawn.ts +24 -1
  288. package/server/services/workshop/agents/agent-dto.ts +54 -0
  289. package/server/services/workshop/agents/harness-spawn-policy.ts +114 -0
  290. package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +22 -0
  291. package/server/services/workshop/agents/host-tool-bridge/index.ts +1 -1
  292. package/server/services/workshop/agents/host-tool-bridge/per-agent.ts +17 -3
  293. package/server/services/workshop/agents/host-tool-bridge/tools/tasks.ts +1 -1
  294. package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +5 -1
  295. package/server/services/workshop/agents/industrial/dcw-tools.ts +6 -2
  296. package/server/services/workshop/agents/industrial/ops-tools.ts +54 -12
  297. package/server/services/workshop/agents/industrial/recipe-gate.ts +68 -15
  298. package/server/services/workshop/agents/industrial/tool-verify-legacy-specs.ts +2 -2
  299. package/server/services/workshop/agents/industrial/tool-verify.ts +31 -2
  300. package/server/services/workshop/agents/node-bindings.repo.ts +4 -3
  301. package/server/services/workshop/agents/node-delegation.ts +49 -4
  302. package/server/services/workshop/agents/tool-approvals.ts +23 -0
  303. package/server/services/workshop/agents/tool-reference-spec.ts +3 -0
  304. package/server/services/workshop/daq/bus/mqtt.adapter.ts +12 -0
  305. package/server/services/workshop/daq/daq-controller/crud.ts +5 -3
  306. package/server/services/workshop/daq/daq-controller/ingest.ts +23 -0
  307. package/server/services/workshop/daq/daq-controller/push.ts +24 -3
  308. package/server/services/workshop/daq/daq-controller/runtime-control.ts +6 -0
  309. package/server/services/workshop/daq/daq-controller/sweep-alarms.ts +3 -1
  310. package/server/services/workshop/daq/daq-controller/tsdb-twin.ts +21 -1
  311. package/server/services/workshop/daq/daq-node.repo.ts +10 -7
  312. package/server/services/workshop/daq/daq-node.ts +2 -0
  313. package/server/services/workshop/daq/daq-runtime.ts +10 -2
  314. package/server/services/workshop/daq/drivers/modbus-tcp.ts +8 -5
  315. package/server/services/workshop/daq/drivers/registry.ts +5 -4
  316. package/server/services/workshop/daq/infra.ts +13 -0
  317. package/server/services/workshop/daq/ingest-policy.ts +24 -1
  318. package/server/services/workshop/daq/storage/timescale.adapter.ts +42 -3
  319. package/server/services/workshop/db/database/migrations.ts +83 -68
  320. package/server/services/workshop/dcw/dcw-controller/crud.ts +27 -2
  321. package/server/services/workshop/dcw/dcw-controller/lines.ts +14 -3
  322. package/server/services/workshop/dcw/dcw-controller/recipes.ts +63 -5
  323. package/server/services/workshop/dcw/dcw-recipe.repo.ts +10 -1
  324. package/server/services/workshop/dcw/dcw-runtime.ts +37 -14
  325. package/server/services/workshop/dcw/drivers/shared.ts +62 -6
  326. package/server/services/workshop/dcw/recipe-op-anchor.ts +28 -0
  327. package/server/services/workshop/dcw/recipe-rollback-manager/rollback.ts +204 -190
  328. package/server/services/workshop/dcw/recipe-rollback-manager/sweep.ts +97 -77
  329. package/server/services/workshop/line-scope.ts +80 -0
  330. package/server/services/workshop/optimization/dispatch.service.ts +18 -2
  331. package/server/services/workshop/permissions.ts +2 -0
  332. package/server/services/workshop/runtime/agent-runtime/message.ts +17 -0
  333. package/server/services/workshop/runtime/agent-runtime/state.ts +9 -3
  334. package/server/services/workshop/runtime/agent-runtime/types.ts +2 -1
  335. package/server/services/workshop/runtime/channel-runtime.ts +3 -1
  336. package/server/services/workshop/runtime/mailbox.ts +6 -3
  337. package/server/services/workshop/runtime/manager/a2a.ts +4 -2
  338. package/server/services/workshop/runtime/manager/admin-channel.ts +1 -1
  339. package/server/services/workshop/runtime/manager/chat.ts +3 -1
  340. package/server/services/workshop/runtime/manager/host-tools.ts +1 -1
  341. package/server/services/workshop/runtime/manager/runtime-wiring.ts +31 -19
  342. package/server/services/workshop/runtime/manager/state.ts +43 -1
  343. package/server/services/workshop/runtime/permission-scope.ts +21 -0
  344. package/server/services/workshop/runtime/scheduler-loop/tick.ts +16 -4
  345. package/server/services/workshop/scene-events.ts +19 -0
  346. package/shared/daq-protocol.ts +24 -5
  347. package/shared/dcw-protocol/catalog.ts +4 -4
  348. package/.output/public/_nuxt/CCI-fwcS2.js +0 -1
  349. package/.output/public/_nuxt/builds/meta/5cd11284-05bf-4fcd-9a69-56a01c9f56dd.json +0 -1
@@ -1,190 +1,204 @@
1
- /**
2
- * RecipeRollBackManagerRollback —— 分级回退(全部经 controller.write 单点)
3
- * (拆分层,承 RecipeRollBackManagerJudge;方法体与原文件逐行一致)
4
- */
5
- import { RecipeRollBackManagerJudge } from './judge'
6
- import type { DcwWriteMeta, OptimizationRecord } from '../../../../../shared/dcw-protocol'
7
- import { AppError, ErrorCodes } from '../../../../utils/errors'
8
- import { COOLDOWN_MS } from './helpers'
9
- import { getDcwNodeRepo } from '../dcw-node.repo'
10
- import { getDcwRecipeRepo } from '../dcw-recipe.repo'
11
- import { recordOps } from '../../ops/ops'
12
-
13
- export abstract class RecipeRollBackManagerRollback extends RecipeRollBackManagerJudge {
14
- /** 回退一条优化记录:目标 = 该记录的 from 值(设定前基线) */
15
- async rollbackRecord(recordId: string, actor: string, by: 'agent' | 'user' | 'system', approvalId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
16
- const record = this.repo.byId(recordId)
17
- if (!record)
18
- throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${recordId}`)
19
- const from = record.params[0]?.from
20
- if (from == null)
21
- throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId} 无基线值(首写无 prevValue),无法回退`)
22
- if (by === 'agent')
23
- this.checkRollbackAllowed(record.nodeId)
24
- return this.executeRollbackWrite(record, from, actor, approvalId, undefined, by, opts?.actorName)
25
- }
26
-
27
- /** 节点级单步回退:目标 = 最近稳定锚的 prevValue(撤销栈栈顶) */
28
- async rollbackNode(nodeId: string, actor: string, by: 'agent' | 'user' | 'system', toAnchorId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
29
- const node = getDcwNodeRepo().byId(nodeId)
30
- if (!node)
31
- throw new AppError(404, ErrorCodes.NOT_FOUND, `控制节点不存在: ${nodeId}`)
32
- const anchor = toAnchorId ? this.repo.anchorById(toAnchorId) : this.repo.lastStableAnchor(nodeId)
33
- if (!anchor)
34
- throw new AppError(409, ErrorCodes.CONFLICT, `节点「${node.name}」无可回退锚(账本无 prevValue≠newValue 的历史)`)
35
- if (anchor.prevValue == null)
36
- throw new AppError(409, ErrorCodes.CONFLICT, '目标锚无基线值(首写锚),无法回退')
37
- if (by === 'agent')
38
- this.checkRollbackAllowed(nodeId)
39
- return this.executeRollbackWrite(
40
- {
41
- id: `node:${nodeId}`,
42
- nodeId,
43
- nodeName: node.name,
44
- lineId: node.lineId,
45
- params: [{ nodeId, templateRef: node.templateRef, from: anchor.prevValue, to: anchor.newValue }],
46
- } as unknown as OptimizationRecord,
47
- anchor.prevValue,
48
- actor,
49
- undefined,
50
- toAnchorId,
51
- by,
52
- opts?.actorName,
53
- )
54
- }
55
-
56
- /** 批次级回退:恢复该 run 涉及节点在 run.startedAt 之前的值(撤销这次实验) */
57
- async rollbackRun(runId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
58
- const run = getDcwRecipeRepo().runById(runId)
59
- if (!run)
60
- throw new AppError(404, ErrorCodes.NOT_FOUND, `批次不存在: ${runId}`)
61
- const startedMs = Date.parse(run.startedAt)
62
- const nodeIds = [...new Set(run.results.map(r => r.nodeId).filter((v): v is string => !!v))]
63
- const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
64
- for (const nodeId of nodeIds) {
65
- const anchor = this.repo.lastStableBefore(nodeId, startedMs)
66
- if (!anchor || anchor.prevValue == null) {
67
- outcomes.push({ nodeId, ok: false, message: '无批次前基线锚,跳过' })
68
- continue
69
- }
70
- try {
71
- await this.writeViaController(nodeId, anchor.prevValue, { source: 'rollback', actor, hypothesis: `批次 ${runId} 撤销:恢复 ${anchor.prevValue}` })
72
- outcomes.push({ nodeId, ok: true, message: `已恢复 ${anchor.prevValue}` })
73
- }
74
- catch (err) {
75
- outcomes.push({ nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
76
- }
77
- }
78
- return outcomes
79
- }
80
-
81
- /** 基准恢复:重新下发 lastGood 批次冻结的参数集 */
82
- async rollbackRecipeGood(recipeId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
83
- const recipe = getDcwRecipeRepo().byId(recipeId)
84
- if (!recipe)
85
- throw new AppError(404, ErrorCodes.NOT_FOUND, `Recipe 不存在: ${recipeId}`)
86
- if (!recipe.lastGoodRunId)
87
- throw new AppError(409, ErrorCodes.CONFLICT, `配方「${recipe.name}」未标记已知良好批次(先 mark-good)`)
88
- const run = getDcwRecipeRepo().runById(recipe.lastGoodRunId)
89
- const snapshot = run?.paramsSnapshot
90
- if (!snapshot || snapshot.length === 0)
91
- throw new AppError(409, ErrorCodes.CONFLICT, '良好批次无参数快照(建批早于版本化),无法基准恢复')
92
- const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
93
- for (const p of snapshot) {
94
- try {
95
- await this.writeViaController(p.nodeId, p.value, { source: 'rollback', actor, hypothesis: `基准恢复 ${recipe.name}(良好批次 ${recipe.lastGoodRunId})` })
96
- outcomes.push({ nodeId: p.nodeId, ok: true, message: `已恢复 ${p.value}` })
97
- }
98
- catch (err) {
99
- outcomes.push({ nodeId: p.nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
100
- }
101
- }
102
- return outcomes
103
- }
104
-
105
- /** 判定回退的执行入口:关闭原记录(rolled-back)+ 反向下发产生新回退记录。
106
- * 状态语义:'rolled-back' 只在回读校验通过后落定;下发期间先置 'judged'(防 afterWrite 误 supersede),
107
- * 下发失败则如实停在 'judged' 并把失败原因写进 judge.reason。 */
108
- protected async executeRollbackWrite(
109
- record: Pick<OptimizationRecord, 'id' | 'nodeId' | 'nodeName' | 'lineId' | 'params'>,
110
- target: number,
111
- actor: string,
112
- approvalId?: string,
113
- toAnchorId?: string,
114
- by: 'agent' | 'user' | 'system' = 'system',
115
- actorName?: string,
116
- ): Promise<OptimizationRecord> {
117
- // 先关原记录(防回退写自身的 afterWrite 把它当 open supersede)
118
- const orig = this.repo.byId(record.id)
119
- const wasOpen = orig?.status === 'open'
120
- if (orig && wasOpen) {
121
- orig.judge ??= { by: 'system', actor, verdict: 'rollback', reason: '执行回退', at: new Date().toISOString() }
122
- this.closeRecord(orig, 'judged')
123
- orig.status = 'judged'
124
- this.repo.updateRecord(orig.id, { status: 'judged', judge: orig.judge, closedAt: orig.closedAt, closedBy: orig.closedBy, windowAgg: orig.windowAgg })
125
- }
126
- try {
127
- await this.writeViaController(record.nodeId, target, {
128
- source: 'rollback',
129
- actor,
130
- hypothesis: `回退 ${record.id}:恢复 ${target}`,
131
- rollbackOf: record.id.startsWith('node:') ? undefined : record.id,
132
- }, approvalId, toAnchorId)
133
- }
134
- catch (err) {
135
- if (orig && wasOpen) {
136
- const reason = err instanceof Error ? err.message : String(err)
137
- orig.judge = { ...orig.judge!, reason: `${orig.judge!.reason};回退下发失败:${reason}`, at: orig.judge!.at }
138
- this.repo.updateRecord(orig.id, { judge: orig.judge })
139
- }
140
- throw err
141
- }
142
- if (orig && wasOpen) {
143
- orig.status = 'rolled-back'
144
- this.repo.updateRecord(orig.id, { status: 'rolled-back' })
145
- this.emit('rolled-back', orig)
146
- recordOps({
147
- actor,
148
- actorName: actorName ?? actor,
149
- actorKind: by === 'agent' ? 'agent' : by === 'user' ? 'user' : 'system',
150
- action: 'optimization.rollback',
151
- kind: 'rollback',
152
- targetKind: 'optimization',
153
- targetId: record.id,
154
- summary: `回退完成:「${record.nodeName ?? record.nodeId}」已恢复 ${target}${record.id.startsWith('node:') ? '' : `(记录 ${record.id})`}`,
155
- lineId: record.lineId ?? '',
156
- recipeId: (record as { recipeId?: string }).recipeId ?? '',
157
- detail: { recordId: record.id, target },
158
- })
159
- }
160
- const fresh = this.repo.listRecords({ nodeId: record.nodeId, limit: 1 })[0]
161
- return fresh!
162
- }
163
-
164
- protected async writeViaController(nodeId: string, eng: number, meta: DcwWriteMeta & { rollbackOf?: string }, approvalId?: string, toAnchorId?: string): Promise<void> {
165
- const { getDcwController } = await import('../dcw-controller')
166
- const outcome = await getDcwController().write(nodeId, eng, null, meta)
167
- if (outcome.ok === false)
168
- throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `回退下发未通过回读校验: ${outcome.message}`)
169
- if (toAnchorId || approvalId) {
170
- const anchor = toAnchorId ? this.repo.anchorById(toAnchorId) : undefined
171
- if (anchor && approvalId)
172
- anchor.approvalId = approvalId
173
- this.repo.flushNow()
174
- }
175
- }
176
-
177
- /** Agent 回退护栏:冷却(用户/系统兜底不受链限) */
178
- protected checkRollbackAllowed(nodeId: string): void {
179
- const rb = this.repo.lastRollbackAnchor(nodeId)
180
- if (rb) {
181
- const elapsed = Date.now() - Date.parse(rb.at)
182
- if (elapsed < COOLDOWN_MS())
183
- throw new AppError(409, ErrorCodes.CONFLICT, `回退冷却中:节点 ${Math.ceil((COOLDOWN_MS() - elapsed) / 1000)}s 内禁止再次回退`)
184
- }
185
- }
186
-
187
- // ================================================================
188
- // 系统兜底评估(挂 sweep() 节拍;F1)
189
- // ================================================================
190
- }
1
+ /**
2
+ * RecipeRollBackManagerRollback —— 分级回退(全部经 controller.write 单点)
3
+ * (拆分层,承 RecipeRollBackManagerJudge;方法体与原文件逐行一致)
4
+ */
5
+ import { RecipeRollBackManagerJudge } from './judge'
6
+ import type { DcwWriteMeta, OptimizationRecord } from '../../../../../shared/dcw-protocol'
7
+ import { AppError, ErrorCodes } from '../../../../utils/errors'
8
+ import { COOLDOWN_MS } from './helpers'
9
+ import { getDcwNodeRepo } from '../dcw-node.repo'
10
+ import { getDcwRecipeRepo } from '../dcw-recipe.repo'
11
+ import { recordOps } from '../../ops/ops'
12
+
13
+ export abstract class RecipeRollBackManagerRollback extends RecipeRollBackManagerJudge {
14
+ /** 回退一条优化记录:目标 = 该记录的 from 值(设定前基线) */
15
+ async rollbackRecord(recordId: string, actor: string, by: 'agent' | 'user' | 'system', approvalId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
16
+ const record = this.repo.byId(recordId)
17
+ if (!record)
18
+ throw new AppError(404, ErrorCodes.NOT_FOUND, `优化记录不存在: ${recordId}`)
19
+ // 2026-10-28:回退写自身会生成 open 记录(from=回退前的问题值),再回退它会写回问题值。
20
+ if (record.rollbackOf) {
21
+ throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId} 是一次回退产生的记录,不允许再次作为回退目标(会把回退前的问题值写回)。请对节点/批次重新发起调控。`)
22
+ }
23
+ const from = record.params[0]?.from
24
+ if (from == null)
25
+ throw new AppError(409, ErrorCodes.CONFLICT, `记录 ${recordId} 无基线值(首写无 prevValue),无法回退`)
26
+ if (by === 'agent')
27
+ this.checkRollbackAllowed(record.nodeId)
28
+ return this.executeRollbackWrite(record, from, actor, approvalId, undefined, by, opts?.actorName)
29
+ }
30
+
31
+ /** 节点级单步回退:目标 = 最近稳定锚的 prevValue(撤销栈栈顶) */
32
+ async rollbackNode(nodeId: string, actor: string, by: 'agent' | 'user' | 'system', toAnchorId?: string, opts?: { actorName?: string }): Promise<OptimizationRecord> {
33
+ const node = getDcwNodeRepo().byId(nodeId)
34
+ if (!node)
35
+ throw new AppError(404, ErrorCodes.NOT_FOUND, `控制节点不存在: ${nodeId}`)
36
+ // 2026-10-28:回退目标必须来自"正常写"的稳定锚。若最新锚本身就是回退写
37
+ // (prev=坏值,new=恢复值),直接取 prevValue 会把坏值再写回去。
38
+ const anchor = toAnchorId
39
+ ? this.repo.anchorById(toAnchorId)
40
+ : this.repo.listAnchors({ nodeId, limit: 200 }).find(a => a.source !== 'rollback' && a.prevValue != null && a.prevValue !== a.newValue)
41
+ if (!anchor)
42
+ throw new AppError(409, ErrorCodes.CONFLICT, `节点「${node.name}」无可回退锚(账本无 prevValue≠newValue 的正常写历史)`)
43
+ if (anchor.nodeId !== nodeId) {
44
+ throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `目标锚 ${anchor.id} 属于节点 ${anchor.nodeId},不能用于节点 ${nodeId} 的回退`)
45
+ }
46
+ if (anchor.prevValue == null)
47
+ throw new AppError(409, ErrorCodes.CONFLICT, '目标锚无基线值(首写锚),无法回退')
48
+ if (typeof node.value === 'number' && anchor.prevValue === node.value && by !== 'agent') {
49
+ throw new AppError(409, ErrorCodes.CONFLICT, `节点「${node.name}」当前值已是回退目标 ${anchor.prevValue}${node.unit || ''},无需回退`)
50
+ }
51
+ if (by === 'agent')
52
+ this.checkRollbackAllowed(nodeId)
53
+ return this.executeRollbackWrite(
54
+ {
55
+ id: `node:${nodeId}`,
56
+ nodeId,
57
+ nodeName: node.name,
58
+ lineId: node.lineId,
59
+ params: [{ nodeId, templateRef: node.templateRef, from: anchor.prevValue, to: anchor.newValue }],
60
+ } as unknown as OptimizationRecord,
61
+ anchor.prevValue,
62
+ actor,
63
+ undefined,
64
+ toAnchorId,
65
+ by,
66
+ opts?.actorName,
67
+ )
68
+ }
69
+
70
+ /** 批次级回退:恢复该 run 涉及节点在 run.startedAt 之前的值(撤销这次实验) */
71
+ async rollbackRun(runId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
72
+ const run = getDcwRecipeRepo().runById(runId)
73
+ if (!run)
74
+ throw new AppError(404, ErrorCodes.NOT_FOUND, `批次不存在: ${runId}`)
75
+ const startedMs = Date.parse(run.startedAt)
76
+ const nodeIds = [...new Set(run.results.map(r => r.nodeId).filter((v): v is string => !!v))]
77
+ const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
78
+ for (const nodeId of nodeIds) {
79
+ const anchor = this.repo.lastStableBefore(nodeId, startedMs)
80
+ if (!anchor || anchor.prevValue == null) {
81
+ outcomes.push({ nodeId, ok: false, message: '无批次前基线锚,跳过' })
82
+ continue
83
+ }
84
+ try {
85
+ await this.writeViaController(nodeId, anchor.prevValue, { source: 'rollback', actor, hypothesis: `批次 ${runId} 撤销:恢复 ${anchor.prevValue}` })
86
+ outcomes.push({ nodeId, ok: true, message: `已恢复 ${anchor.prevValue}` })
87
+ }
88
+ catch (err) {
89
+ outcomes.push({ nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
90
+ }
91
+ }
92
+ return outcomes
93
+ }
94
+
95
+ /** 基准恢复:重新下发 lastGood 批次冻结的参数集 */
96
+ async rollbackRecipeGood(recipeId: string, actor: string): Promise<Array<{ nodeId: string, ok: boolean, message: string }>> {
97
+ const recipe = getDcwRecipeRepo().byId(recipeId)
98
+ if (!recipe)
99
+ throw new AppError(404, ErrorCodes.NOT_FOUND, `Recipe 不存在: ${recipeId}`)
100
+ if (!recipe.lastGoodRunId)
101
+ throw new AppError(409, ErrorCodes.CONFLICT, `配方「${recipe.name}」未标记已知良好批次(先 mark-good)`)
102
+ const run = getDcwRecipeRepo().runById(recipe.lastGoodRunId)
103
+ const snapshot = run?.paramsSnapshot
104
+ if (!snapshot || snapshot.length === 0)
105
+ throw new AppError(409, ErrorCodes.CONFLICT, '良好批次无参数快照(建批早于版本化),无法基准恢复')
106
+ const outcomes: Array<{ nodeId: string, ok: boolean, message: string }> = []
107
+ for (const p of snapshot) {
108
+ try {
109
+ await this.writeViaController(p.nodeId, p.value, { source: 'rollback', actor, hypothesis: `基准恢复 ${recipe.name}(良好批次 ${recipe.lastGoodRunId})` })
110
+ outcomes.push({ nodeId: p.nodeId, ok: true, message: `已恢复 ${p.value}` })
111
+ }
112
+ catch (err) {
113
+ outcomes.push({ nodeId: p.nodeId, ok: false, message: err instanceof Error ? err.message : String(err) })
114
+ }
115
+ }
116
+ return outcomes
117
+ }
118
+
119
+ /** 判定回退的执行入口:关闭原记录(rolled-back)+ 反向下发产生新回退记录。
120
+ * 状态语义:'rolled-back' 只在回读校验通过后落定;下发期间先置 'judged'(防 afterWrite 误 supersede),
121
+ * 下发失败则如实停在 'judged' 并把失败原因写进 judge.reason。 */
122
+ protected async executeRollbackWrite(
123
+ record: Pick<OptimizationRecord, 'id' | 'nodeId' | 'nodeName' | 'lineId' | 'params'>,
124
+ target: number,
125
+ actor: string,
126
+ approvalId?: string,
127
+ toAnchorId?: string,
128
+ by: 'agent' | 'user' | 'system' = 'system',
129
+ actorName?: string,
130
+ ): Promise<OptimizationRecord> {
131
+ // 先关原记录(防回退写自身的 afterWrite 把它当 open supersede)
132
+ const orig = this.repo.byId(record.id)
133
+ const wasOpen = orig?.status === 'open'
134
+ if (orig && wasOpen) {
135
+ orig.judge ??= { by: 'system', actor, verdict: 'rollback', reason: '执行回退', at: new Date().toISOString() }
136
+ this.closeRecord(orig, 'judged')
137
+ orig.status = 'judged'
138
+ this.repo.updateRecord(orig.id, { status: 'judged', judge: orig.judge, closedAt: orig.closedAt, closedBy: orig.closedBy, windowAgg: orig.windowAgg })
139
+ }
140
+ try {
141
+ await this.writeViaController(record.nodeId, target, {
142
+ source: 'rollback',
143
+ actor,
144
+ hypothesis: `回退 ${record.id}:恢复 ${target}`,
145
+ rollbackOf: record.id.startsWith('node:') ? undefined : record.id,
146
+ }, approvalId, toAnchorId)
147
+ }
148
+ catch (err) {
149
+ if (orig && wasOpen) {
150
+ const reason = err instanceof Error ? err.message : String(err)
151
+ orig.judge = { ...orig.judge!, reason: `${orig.judge!.reason};回退下发失败:${reason}`, at: orig.judge!.at }
152
+ this.repo.updateRecord(orig.id, { judge: orig.judge })
153
+ }
154
+ throw err
155
+ }
156
+ if (orig && wasOpen) {
157
+ orig.status = 'rolled-back'
158
+ this.repo.updateRecord(orig.id, { status: 'rolled-back' })
159
+ this.emit('rolled-back', orig)
160
+ recordOps({
161
+ actor,
162
+ actorName: actorName ?? actor,
163
+ actorKind: by === 'agent' ? 'agent' : by === 'user' ? 'user' : 'system',
164
+ action: 'optimization.rollback',
165
+ kind: 'rollback',
166
+ targetKind: 'optimization',
167
+ targetId: record.id,
168
+ summary: `回退完成:「${record.nodeName ?? record.nodeId}」已恢复 ${target}${record.id.startsWith('node:') ? '' : `(记录 ${record.id})`}`,
169
+ lineId: record.lineId ?? '',
170
+ recipeId: (record as { recipeId?: string }).recipeId ?? '',
171
+ detail: { recordId: record.id, target },
172
+ })
173
+ }
174
+ const fresh = this.repo.listRecords({ nodeId: record.nodeId, limit: 1 })[0]
175
+ return fresh!
176
+ }
177
+
178
+ protected async writeViaController(nodeId: string, eng: number, meta: DcwWriteMeta & { rollbackOf?: string }, approvalId?: string, toAnchorId?: string): Promise<void> {
179
+ const { getDcwController } = await import('../dcw-controller')
180
+ const outcome = await getDcwController().write(nodeId, eng, null, meta)
181
+ if (outcome.ok === false)
182
+ throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `回退下发未通过回读校验: ${outcome.message}`)
183
+ if (toAnchorId || approvalId) {
184
+ const anchor = toAnchorId ? this.repo.anchorById(toAnchorId) : undefined
185
+ if (anchor && approvalId)
186
+ anchor.approvalId = approvalId
187
+ this.repo.flushNow()
188
+ }
189
+ }
190
+
191
+ /** Agent 回退护栏:冷却(用户/系统兜底不受链限) */
192
+ protected checkRollbackAllowed(nodeId: string): void {
193
+ const rb = this.repo.lastRollbackAnchor(nodeId)
194
+ if (rb) {
195
+ const elapsed = Date.now() - Date.parse(rb.at)
196
+ if (elapsed < COOLDOWN_MS())
197
+ throw new AppError(409, ErrorCodes.CONFLICT, `回退冷却中:节点 ${Math.ceil((COOLDOWN_MS() - elapsed) / 1000)}s 内禁止再次回退`)
198
+ }
199
+ }
200
+
201
+ // ================================================================
202
+ // 系统兜底评估(挂 sweep() 节拍;F1)
203
+ // ================================================================
204
+ }
@@ -1,77 +1,97 @@
1
- /**
2
- * RecipeRollBackManagerSweep —— 系统兜底评估(按 sweep 节拍)
3
- * (拆分层,承 RecipeRollBackManagerRollback;方法体与原文件逐行一致)
4
- */
5
- import { RecipeRollBackManagerRollback } from './rollback'
6
- import type { OptimizationRecord } from '../../../../../shared/dcw-protocol'
7
- import { BREACH_THRESHOLD, MAX_AUTO_ROLLBACKS, MIN_WINDOW_MS, RECHECK_MS } from './helpers'
8
- import { recordOps } from '../../ops/ops'
9
-
10
- export abstract class RecipeRollBackManagerSweep extends RecipeRollBackManagerRollback {
11
- evaluateOpenRecords(now: number): void {
12
- // 走 open 索引(O(open))而非 listRecords 的「全量倒序 + limit 500」:
13
- // 后者在 open 记录 >500 时会**静默漏评估**,且每次 sweep 都对全量 records 做一次拷贝。
14
- for (const record of this.repo.listOpenRecords()) {
15
- if (record.policy === 'observe_only')
16
- continue
17
- const setMs = Date.parse(record.setAt)
18
- if (now - setMs < MIN_WINDOW_MS())
19
- continue
20
- if (record.evaluatedAt && now - Date.parse(record.evaluatedAt) < RECHECK_MS)
21
- continue
22
- record.evaluatedAt = new Date(now).toISOString()
23
- void this.evaluateOnce(record)
24
- }
25
- }
26
-
27
- protected async evaluateOnce(record: OptimizationRecord): Promise<void> {
28
- try {
29
- const from = Date.parse(record.setAt)
30
- const agg = await this.captureMetrics(record.nodeId, record.lineId, record.recipeId, from, Date.now())
31
- const totalBreaches = agg.channels.reduce((sum, c) => sum + Math.max(0, c.breaches), 0)
32
- if (totalBreaches < BREACH_THRESHOLD) {
33
- this.repo.updateRecord(record.id, { evaluatedAt: record.evaluatedAt, windowAgg: record.windowAgg ?? agg })
34
- return
35
- }
36
- const reason = `观察窗内数采越配方监控窗累计 ${totalBreaches} 采样(阈值 ${BREACH_THRESHOLD}),系统兜底判定回退`
37
- if (record.policy === 'auto_rollback' && this.repo.chainRollbackCount(record.nodeId) < MAX_AUTO_ROLLBACKS) {
38
- record.judge = { by: 'system', actor: 'system', verdict: 'rollback', reason, at: new Date().toISOString() }
39
- this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
40
- this.emit('judged', record)
41
- recordOps({
42
- actor: 'system',
43
- actorName: 'system',
44
- actorKind: 'system',
45
- action: 'optimization.judge',
46
- kind: 'rollback',
47
- targetKind: 'optimization',
48
- targetId: record.id,
49
- summary: `系统兜底判定回退:窗口内累计越限 ${totalBreaches} 采样,自动恢复基线`,
50
- lineId: record.lineId ?? '',
51
- recipeId: record.recipeId ?? '',
52
- detail: { breaches: totalBreaches, policy: record.policy },
53
- })
54
- await this.rollbackRecord(record.id, 'system', 'system')
55
- }
56
- else {
57
- // approve_rollback 或自动回退链达上限:提议人工确认(判定入册,执行等 REST/工具)
58
- record.judge = {
59
- by: 'system',
60
- actor: 'system',
61
- verdict: 'rollback',
62
- reason: `${reason};${record.policy === 'approve_rollback' ? '等待人工确认' : '自动回退链达上限,升级人工'}`,
63
- at: new Date().toISOString(),
64
- }
65
- this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
66
- this.emit('judged', record)
67
- }
68
- }
69
- catch (err) {
70
- console.error('[recipe-rollback] 兜底评估失败:', record.id, err)
71
- }
72
- }
73
-
74
- // ================================================================
75
- // 数据面:窗口聚合 / 台账 / 序列(全部复用 lineQuery 参数化查询)
76
- // ================================================================
77
- }
1
+ /**
2
+ * RecipeRollBackManagerSweep —— 系统兜底评估(按 sweep 节拍)
3
+ * (拆分层,承 RecipeRollBackManagerRollback;方法体与原文件逐行一致)
4
+ */
5
+ import { RecipeRollBackManagerRollback } from './rollback'
6
+ import type { OptimizationRecord } from '../../../../../shared/dcw-protocol'
7
+ import { BREACH_THRESHOLD, MAX_AUTO_ROLLBACKS, MIN_WINDOW_MS, RECHECK_MS } from './helpers'
8
+ import { recordOps } from '../../ops/ops'
9
+
10
+ export abstract class RecipeRollBackManagerSweep extends RecipeRollBackManagerRollback {
11
+ evaluateOpenRecords(now: number): void {
12
+ // 走 open 索引(O(open))而非 listRecords 的「全量倒序 + limit 500」:
13
+ // 后者在 open 记录 >500 时会**静默漏评估**,且每次 sweep 都对全量 records 做一次拷贝。
14
+ for (const record of this.repo.listOpenRecords()) {
15
+ if (record.policy === 'observe_only')
16
+ continue
17
+ const setMs = Date.parse(record.setAt)
18
+ if (now - setMs < MIN_WINDOW_MS())
19
+ continue
20
+ if (record.evaluatedAt && now - Date.parse(record.evaluatedAt) < RECHECK_MS)
21
+ continue
22
+ record.evaluatedAt = new Date(now).toISOString()
23
+ void this.evaluateOnce(record)
24
+ }
25
+ }
26
+
27
+ protected async evaluateOnce(record: OptimizationRecord): Promise<void> {
28
+ try {
29
+ // 2026-10-28:回退写产生的记录不再参与自动兜底 —— 否则"回退的回退"会写回问题值。
30
+ if (record.rollbackOf) return
31
+ const from = Date.parse(record.setAt)
32
+ const agg = await this.captureMetrics(record.nodeId, record.lineId, record.recipeId, from, Date.now())
33
+ // B-P1-1(2026-10-28 审查):captureMetrics 是跨 await 的长查询 —— 期间世界已变。
34
+ // 判定/执行前必须重验"这条记录还是不是当前该行动的那条",否则会:
35
+ // ① 覆盖人工已下的 uncertain/判词(推翻人的裁决);
36
+ // ② 记录已被关闭/被执行(重复物理写);
37
+ // ③ 同节点已有更新的写意图接管(按旧值回退,把最新意图冲掉)。
38
+ // 三者任一发生都只补记聚合(windowAgg)并返回,绝不产生任何写入。
39
+ const latest = this.repo.byId(record.id)
40
+ if (!latest || latest.status !== 'open' || latest.judge) {
41
+ if (latest?.status === 'open') {
42
+ this.repo.updateRecord(latest.id, { evaluatedAt: latest.evaluatedAt, windowAgg: latest.windowAgg ?? agg })
43
+ }
44
+ return
45
+ }
46
+ const current = this.repo.openRecordOf(record.nodeId)
47
+ if (!current || current.id !== record.id) {
48
+ this.repo.updateRecord(latest.id, { evaluatedAt: latest.evaluatedAt, windowAgg: latest.windowAgg ?? agg })
49
+ return
50
+ }
51
+ const totalBreaches = agg.channels.reduce((sum, c) => sum + Math.max(0, c.breaches), 0)
52
+ if (totalBreaches < BREACH_THRESHOLD) {
53
+ this.repo.updateRecord(record.id, { evaluatedAt: record.evaluatedAt, windowAgg: record.windowAgg ?? agg })
54
+ return
55
+ }
56
+ const reason = `观察窗内数采越配方监控窗累计 ${totalBreaches} 采样(阈值 ${BREACH_THRESHOLD}),系统兜底判定回退`
57
+ if (record.policy === 'auto_rollback' && this.repo.chainRollbackCount(record.nodeId) < MAX_AUTO_ROLLBACKS) {
58
+ record.judge = { by: 'system', actor: 'system', verdict: 'rollback', reason, at: new Date().toISOString() }
59
+ this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
60
+ this.emit('judged', record)
61
+ recordOps({
62
+ actor: 'system',
63
+ actorName: 'system',
64
+ actorKind: 'system',
65
+ action: 'optimization.judge',
66
+ kind: 'rollback',
67
+ targetKind: 'optimization',
68
+ targetId: record.id,
69
+ summary: `系统兜底判定回退:窗口内累计越限 ${totalBreaches} 采样,自动恢复基线`,
70
+ lineId: record.lineId ?? '',
71
+ recipeId: record.recipeId ?? '',
72
+ detail: { breaches: totalBreaches, policy: record.policy },
73
+ })
74
+ await this.rollbackRecord(record.id, 'system', 'system')
75
+ }
76
+ else {
77
+ // approve_rollback 或自动回退链达上限:提议人工确认(判定入册,执行等 REST/工具)
78
+ record.judge = {
79
+ by: 'system',
80
+ actor: 'system',
81
+ verdict: 'rollback',
82
+ reason: `${reason};${record.policy === 'approve_rollback' ? '等待人工确认' : '自动回退链达上限,升级人工'}`,
83
+ at: new Date().toISOString(),
84
+ }
85
+ this.repo.updateRecord(record.id, { judge: record.judge, evaluatedAt: record.evaluatedAt })
86
+ this.emit('judged', record)
87
+ }
88
+ }
89
+ catch (err) {
90
+ console.error('[recipe-rollback] 兜底评估失败:', record.id, err)
91
+ }
92
+ }
93
+
94
+ // ================================================================
95
+ // 数据面:窗口聚合 / 台账 / 序列(全部复用 lineQuery 参数化查询)
96
+ // ================================================================
97
+ }