agentworkshop 0.7.51 → 0.7.52

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 (259) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +2028 -1955
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +2028 -1955
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/{CdIsmU5a2.js → 4wrEQ3np2.js} +1 -1
  5. package/.output/public/_nuxt/{asmJ99nX2.js → B8zP7kaj2.js} +1 -1
  6. package/.output/public/_nuxt/{D89BUtx6.js → B9cGf8mg.js} +1 -1
  7. package/.output/public/_nuxt/{CP0I2l-6.js → BVzw5a_0.js} +1 -1
  8. package/.output/public/_nuxt/{CFQSjB1h.js → B_opxrHJ.js} +1 -1
  9. package/.output/public/_nuxt/{BGAaKBeo2.js → BiUhxH3t2.js} +1 -1
  10. package/.output/public/_nuxt/{B7jlMWsz.js → C00Rd6Cg.js} +1 -1
  11. package/.output/public/_nuxt/{BOmDHp5L.js → CGQvF-Gg.js} +3 -3
  12. package/.output/public/_nuxt/CTvh8v4T.js +1 -0
  13. package/.output/public/_nuxt/{B9QzrmgE.js → Cbeifv55.js} +1 -1
  14. package/.output/public/_nuxt/{BWU1pvLL.js → CcGuXiOa.js} +1 -1
  15. package/.output/public/_nuxt/{zh-S_7rN2.js → CkPxL4UX2.js} +1 -1
  16. package/.output/public/_nuxt/{DzfVS8N72.js → D_Ce9Fon2.js} +1 -1
  17. package/.output/public/_nuxt/{DClNt1uS.js → Da90gveK.js} +1 -1
  18. package/.output/public/_nuxt/builds/latest.json +1 -1
  19. package/.output/public/_nuxt/builds/meta/c64014ca-3595-4b7a-a5ca-055687c83ba2.json +1 -0
  20. package/.output/public/_nuxt/channel-templates.DkNZg-lF.css +1 -0
  21. package/.output/public/_nuxt/{JAM4aNC_.js → evt5VGDh.js} +1 -1
  22. package/.output/public/_nuxt/{DhFv8S2Z.js → mNnuUoSy.js} +1 -1
  23. package/.output/public/_nuxt/{CU-mhG0-.js → mgWHSRc8.js} +1 -1
  24. package/.output/public/_nuxt/{jRTz0hjN2.js → qPsch_ny2.js} +1 -1
  25. package/.output/public/_nuxt/{lWYQbIR3.js → ty5W5QwO.js} +1 -1
  26. package/.output/public/_nuxt/{DMYYS5sK.js → xQX5r6tW.js} +1 -1
  27. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  28. package/.output/server/chunks/_/entity.mjs +1 -1
  29. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  30. package/.output/server/chunks/_/nitro.mjs +1209 -967
  31. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  32. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  33. package/.output/server/chunks/build/TownView-fP9BiALv.mjs +1 -1
  34. package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs → _wsId_-C4L9fVHC.mjs} +2 -2
  35. package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs.map → _wsId_-C4L9fVHC.mjs.map} +1 -1
  36. package/.output/server/chunks/build/{agents-CDLcboCv.mjs → agents-ydYu-Ol9.mjs} +6 -6
  37. package/.output/server/chunks/build/{agents-CDLcboCv.mjs.map → agents-ydYu-Ol9.mjs.map} +1 -1
  38. package/.output/server/chunks/build/{channel-templates-DjEsj0_v.mjs → channel-templates-DP1ndA5K.mjs} +114 -25
  39. package/.output/server/chunks/build/channel-templates-DP1ndA5K.mjs.map +1 -0
  40. package/.output/server/chunks/build/daq-N69AOtgw.mjs +1 -1
  41. package/.output/server/chunks/build/dcw-CN9d3Rs7.mjs +1 -1
  42. package/.output/server/chunks/build/{pages-rZKH72eC.mjs → pages-BzmrmLL_.mjs} +3 -3
  43. package/.output/server/chunks/build/{pages-rZKH72eC.mjs.map → pages-BzmrmLL_.mjs.map} +1 -1
  44. package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs → schedules-BYR-lA1k.mjs} +2 -2
  45. package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs.map → schedules-BYR-lA1k.mjs.map} +1 -1
  46. package/.output/server/chunks/build/{settings-CAJWvul5.mjs → settings-UyZ78w2e.mjs} +2 -2
  47. package/.output/server/chunks/build/{settings-CAJWvul5.mjs.map → settings-UyZ78w2e.mjs.map} +1 -1
  48. package/.output/server/chunks/build/{teams-DBBvIToa.mjs → teams-D-Y5mzU7.mjs} +8 -8
  49. package/.output/server/chunks/build/{teams-DBBvIToa.mjs.map → teams-D-Y5mzU7.mjs.map} +1 -1
  50. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  51. package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs → useAgentHarnessOptions-CRyQYYY0.mjs} +2 -2
  52. package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs.map → useAgentHarnessOptions-CRyQYYY0.mjs.map} +1 -1
  53. package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs → useAgentTemplateActions-CaRsOBmB.mjs} +2 -2
  54. package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs.map → useAgentTemplateActions-CaRsOBmB.mjs.map} +1 -1
  55. package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs → useAgentTemplateForm-ChiIuPYr.mjs} +2 -2
  56. package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs.map → useAgentTemplateForm-ChiIuPYr.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs → useAgentTemplatesCatalog-Bf5hk6Jf.mjs} +2 -2
  58. package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs.map → useAgentTemplatesCatalog-Bf5hk6Jf.mjs.map} +1 -1
  59. package/.output/server/chunks/build/useDaqAddNode-kW7uTSMQ.mjs +1 -1
  60. package/.output/server/chunks/build/useDaqDetailNode-D_vhG0jF.mjs +1 -1
  61. package/.output/server/chunks/build/useDaqDetailParams-JfqHvTxr.mjs +1 -1
  62. package/.output/server/chunks/build/useDaqFilters-BUQtZ82a.mjs +1 -1
  63. package/.output/server/chunks/build/useDaqStream-wOxZcMDA.mjs +1 -1
  64. package/.output/server/chunks/build/useDaqTemplates-BqQRdrIm.mjs +1 -1
  65. package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs → useDashboardData-CNOY4Bi3.mjs} +2 -2
  66. package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs.map → useDashboardData-CNOY4Bi3.mjs.map} +1 -1
  67. package/.output/server/chunks/build/useDcwAddNode-C1HDP3yG.mjs +1 -1
  68. package/.output/server/chunks/build/useDcwStream-D04kCV3J.mjs +1 -1
  69. package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs → useTeamActions-C51ciLb0.mjs} +2 -2
  70. package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs.map → useTeamActions-C51ciLb0.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs → useTeamAddMemberDialog-DthpCMP8.mjs} +2 -2
  72. package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs.map → useTeamAddMemberDialog-DthpCMP8.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs → useTeamCreateDialog-Dc2KTwyg.mjs} +2 -2
  74. package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs.map → useTeamCreateDialog-Dc2KTwyg.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs → useTeamDeployDialog-CXpvPnJD.mjs} +2 -2
  76. package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs.map → useTeamDeployDialog-CXpvPnJD.mjs.map} +1 -1
  77. package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs → useTeamPluginDialog-DTs-7SSm.mjs} +2 -2
  78. package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs.map → useTeamPluginDialog-DTs-7SSm.mjs.map} +1 -1
  79. package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs → useTeamsCatalog-CcpetYyW.mjs} +2 -2
  80. package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs.map → useTeamsCatalog-CcpetYyW.mjs.map} +1 -1
  81. package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs → useWorkshopApi-CO3ophqt.mjs} +5 -2
  82. package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs.map → useWorkshopApi-CO3ophqt.mjs.map} +1 -1
  83. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  84. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs +54 -0
  85. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs.map +1 -0
  86. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs +51 -0
  87. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs.map +1 -0
  88. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  89. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +1 -1
  90. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +1 -1
  91. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +1 -1
  92. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +1 -1
  93. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +1 -1
  95. package/.output/server/chunks/routes/api/workshop/aml/entities/prune.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/aml/index.get.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/aml/index.post.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/aml/index4.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/aml/index5.get.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/aml/index6.get.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs +1 -1
  108. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/cancel.post.mjs +1 -1
  109. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/logs.get.mjs +1 -1
  110. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/retry.post.mjs +1 -1
  111. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.delete.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.get.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/aml/models/_id/predict.post.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/aml/models/_id/promote.post.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.delete.mjs +1 -1
  116. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +1 -1
  117. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs +1 -1
  118. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs +1 -1
  119. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs +1 -1
  120. package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs +1 -1
  121. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
  122. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
  123. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +5 -4
  124. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +1 -1
  125. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
  126. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
  127. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
  128. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
  129. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  130. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  131. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
  132. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
  133. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +1 -1
  134. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +1 -1
  135. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
  136. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +4 -4
  137. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
  138. package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
  139. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
  140. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
  141. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
  142. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
  143. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
  144. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
  145. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
  146. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
  147. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +1 -1
  148. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +1 -1
  149. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
  150. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
  151. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
  152. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +1 -1
  153. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
  154. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
  155. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +1 -1
  156. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +1 -1
  157. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
  158. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
  159. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +1 -1
  163. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
  164. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
  165. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
  166. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +1 -1
  167. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
  168. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +1 -1
  169. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
  170. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +1 -1
  173. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
  174. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +1 -1
  175. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  176. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  177. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  178. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
  179. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
  191. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
  192. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +1 -1
  193. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
  194. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  203. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  205. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  208. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +1 -1
  211. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
  212. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  213. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -2
  223. package/.output/server/chunks/routes/renderer.mjs +2 -2
  224. package/.output/server/chunks/virtual/entry.mjs +29 -19
  225. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  226. package/.output/server/package.json +1 -1
  227. package/README-zh.md +2 -2
  228. package/README.md +2 -2
  229. package/app/composables/workshop/useWorkshopApi.ts +4 -2
  230. package/app/pages/workshop/channel-templates.vue +43 -4
  231. package/config.yml +1 -1
  232. package/docs/cli.en.md +2 -2
  233. package/docs/cli.md +2 -2
  234. package/docs/plugins.en.md +1 -1
  235. package/docs/plugins.md +1 -1
  236. package/docs/sdk.en.md +1 -1
  237. package/docs/sdk.md +1 -1
  238. package/i18n/dicts/ctpl.json +37 -32
  239. package/i18n/locales/en.ts +5 -0
  240. package/i18n/locales/zh-CN.ts +5 -0
  241. package/package.json +1 -1
  242. package/scripts/_audit/kb-team-mock-e2e.mjs +146 -0
  243. package/scripts/_audit/kb-team-omp-e2e.mjs +229 -0
  244. package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -0
  245. package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -0
  246. package/server/api/workshop/channel-templates/[id]/instantiate.post.ts +2 -1
  247. package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +6 -1
  248. package/server/services/workshop/agents/host-tool-bridge/tools/tasks.ts +15 -2
  249. package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -0
  250. package/server/services/workshop/agents/node-bindings.repo.ts +10 -1
  251. package/server/services/workshop/agents/node-delegation.ts +150 -0
  252. package/server/services/workshop/agents/tool-classes.ts +2 -0
  253. package/server/services/workshop/db/database/seed.ts +20 -0
  254. package/server/services/workshop/runtime/manager/channel-templates.ts +26 -2
  255. package/server/services/workshop/runtime/manager/types.ts +2 -0
  256. package/.output/public/_nuxt/8FXd9As6.js +0 -1
  257. package/.output/public/_nuxt/builds/meta/912eb5bb-670e-4cc8-b21d-7fc097723466.json +0 -1
  258. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +0 -1
  259. package/.output/server/chunks/build/channel-templates-DjEsj0_v.mjs.map +0 -1
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * scripts/_audit/kb-team-omp-e2e.mjs —— 知识库集成通用闭环优化频道 × 真实 omp × 多 PLC 模拟场景。
4
+ *
5
+ * 每个 scenario:
6
+ * ① 模拟器建场(ensureScenarioLine) + 平台建线开跑(provisionScenarioLine,真实协议链路);
7
+ * ② 实例化「通用闭环优化频道(标准)」模板,enableKnowledgeBase=true(频道加载 rag-bridge);
8
+ * ③ lead 绑定 PV 数采节点 + 调节数控节点(auto);
9
+ * ④ 提交优化 goal(要求:先查知识库 → lead 委派节点权限 → 治理小步下发复测 → 判定 → 经验沉淀);
10
+ * ⑤ 期间轮询任务/消息/事件,全程转录落盘(transcript.md + 原始 JSON);
11
+ * ⑥ 验收:根任务收口 + worker 确实被授予节点(grantedBy 溯源) + 发生过治理写入
12
+ * + PV 回带 + 知识库经验新增(kb_agent 异步落库)。
13
+ *
14
+ * 用法:
15
+ * node scripts/_audit/kb-team-omp-e2e.mjs --base http://127.0.0.1:3456 --scenarios injection,wwtp
16
+ * 前置:目标实例为本仓库构建(内置通用模板 + rag-bridge);rag-bridge token 已配置(启 KB 鉴权时);
17
+ * omp CLI 在 PATH 且可用;模拟器可自举(bench/lib/sim.mjs ensureSimulator)。
18
+ */
19
+ import { join, dirname, resolve } from 'node:path'
20
+ import { writeFileSync, appendFileSync } from 'node:fs'
21
+ import { fileURLToPath } from 'node:url'
22
+ import { makeApi, ensureDir, sleep } from '../../bench/lib/util.mjs'
23
+ import { ensureSimulator, simUp } from '../../bench/lib/sim.mjs'
24
+ import { SCENARIOS, ensureScenarioLine, provisionScenarioLine, readPvMean } from '../../bench/lib/scenarios.mjs'
25
+
26
+ const HERE = dirname(fileURLToPath(import.meta.url))
27
+ const REPO = resolve(HERE, '../..')
28
+ const args = process.argv.slice(2)
29
+ const arg = (k, d) => { const i = args.indexOf(`--${k}`); return i >= 0 ? (args[i + 1] ?? '') : d }
30
+
31
+ const BASE = arg('base', process.env.AW_BASE ?? 'http://127.0.0.1:3456')
32
+ const list = (arg('scenarios', 'injection') || 'injection').split(',').map(s => s.trim()).filter(id => SCENARIOS[id])
33
+ const TASK_TIMEOUT_MS = Number(arg('timeout-min', '32')) * 60_000
34
+ const KB_WAIT_MS = Number(arg('kb-wait-min', '6')) * 60_000
35
+ const POLL_MS = 20_000
36
+ const sfx = arg('sfx', `kb${new Date().toISOString().slice(5, 16).replace(/[-T:]/g, '')}`)
37
+
38
+ const rid = `kb-team-omp-${new Date().toISOString().slice(0, 19).replace(/[-T:]/g, '')}`
39
+ const outDir = ensureDir(join(REPO, 'bench', 'results', rid))
40
+ console.log(`=== kb-team × omp 闭环优化 × 多场景 ===\nbase=${BASE} scenarios=${list.join(',')} out=${outDir}\n`)
41
+
42
+ // ── 自举 ──
43
+ if (!(await simUp())) {
44
+ const r = await ensureSimulator({ log: console.log })
45
+ if (!r.started && !(await simUp())) { console.error(`✘ 模拟器自举失败: ${r.reason}`); process.exit(1) }
46
+ }
47
+ const api = makeApi(BASE)
48
+ const login = await api.login(process.env.AW_ADMIN_EMAIL ?? 'admin@awshop.local', process.env.AW_ADMIN_PASSWORD ?? 'Awshop@123!')
49
+ if (!login.ok) { console.error('✘ 平台登录失败'); process.exit(1) }
50
+ console.log(`平台就绪(${login.how},role=${login.role});模拟器就绪\n`)
51
+
52
+ const globalResult = { rid, base: BASE, scenarios: [] }
53
+
54
+ for (const id of list) {
55
+ const scen = SCENARIOS[id]
56
+ const dir = ensureDir(join(outDir, id))
57
+ const res = { scenario: id, zh: scen.zh, checks: {}, errors: [] }
58
+ globalResult.scenarios.push(res)
59
+ const log = (line) => { console.log(`[${id}] ${line}`); appendFileSync(join(dir, 'transcript.md'), `${line}\n`) }
60
+ writeFileSync(join(dir, 'transcript.md'), `# ${scen.zh}(kb-team × omp)作业转录\n\n- 开始: ${new Date().toISOString()}\n- 频道模板: chtl-generic-optimize-default(enableKnowledgeBase=true)\n\n`)
61
+
62
+ try {
63
+ // ── ① 建场 + 建线 ──
64
+ log(`① 模拟器建场 ${scen.key} …`)
65
+ const ensure = await ensureScenarioLine(scen)
66
+ log(` 设备=${ensure.verified.devices}/${ensure.verified.expectDevices} SP=${ensure.verified.sp} PV=${ensure.verified.pv} 协议=${ensure.verified.protocols.join('/')}`)
67
+ const line = await provisionScenarioLine(api, scen, { sfx: `${sfx}-${id}` })
68
+ if (line.errors?.length || !line.ids?.lineId) throw new Error(`建线失败: ${line.errors?.join(';')}`)
69
+ res.line = { lineId: line.ids.lineId, recipeId: line.ids.recipeId, started: line.ids.started, reused: line.reused }
70
+ log(`① 平台建线 ${line.lineName} started=${line.ids.started} dcw=${Object.keys(line.dcw).length} daq=${Object.keys(line.daq).length}`)
71
+
72
+ // ── ② 实例化 KB 通用频道 ──
73
+ const inst = (await api.call('POST', '/api/workshop/channel-templates/chtpl-generic-optimize-default/instantiate', {
74
+ name: `KB闭环优化-${scen.zh}-${sfx}-${id}`,
75
+ enableKnowledgeBase: true,
76
+ }))
77
+ const channelId = inst.data?.channelId
78
+ if (!channelId) throw new Error(`频道实例化失败: ${inst.message}`)
79
+ const agents = (await api.call('GET', `/api/workshop/channels/${channelId}/agents`)).data ?? []
80
+ const lead = agents.find(a => a.role === 'lead')
81
+ res.channel = { channelId, leadId: lead?.id, leadHarness: lead?.harness }
82
+ log(`② 频道 ${channelId} 已实例化(lead=${lead?.name}/${lead?.harness},成员=${agents.length})`)
83
+
84
+ // ── ③ lead 绑定 PV 数采 + 调节数控(auto) ──
85
+ const pvNode = line.daq[scen.pv.sig]
86
+ const knobSigs = (scen.knobs ?? []).map(k => k.sig).slice(0, 2)
87
+ const knobNodes = knobSigs.map(s => line.dcw[s]).filter(Boolean)
88
+ if (!pvNode || !knobNodes.length) throw new Error(`关键节点缺失: pv=${pvNode} knobs=${knobNodes}`)
89
+ for (const [nodeId, kind] of [[pvNode, 'daq'], ...knobNodes.map(n => [n, 'dcw'])]) {
90
+ const r = await api.call('POST', '/api/workshop/agent-tools/bindings', { agentId: lead.id, nodeId, kind, mode: 'auto' })
91
+ if (r.status !== 200) throw new Error(`lead 绑定失败 ${kind} ${nodeId}: ${r.message}`)
92
+ }
93
+ res.leadBindings = { pvNode, knobNodes }
94
+ log(`③ lead 绑定:daq(${scen.pv.sig})=${pvNode} dcw=${knobNodes.join(',')}`)
95
+
96
+ // ── ④ 提交 goal ──
97
+ const knobText = (scen.knobs ?? []).slice(0, 2).map(k => `${k.sig}`).join('、')
98
+ const guardText = (scen.guards ?? []).map(g => `${g.label}≤${g.max}`).join('、') || '无'
99
+ const goal = [
100
+ `【产线闭环优化】${scen.zh}:${scen.story}`,
101
+ `目标:把「${scen.pv.label}(${scen.pv.sig})」稳定控制回 ${scen.pv.target}±${scen.pv.tol}${scen.pv.unit} 目标带;守卫约束:${guardText}。`,
102
+ `可调手段(数控节点,治理下发):${knobText}。`,
103
+ `作业要求:`,
104
+ `1. 开工先查知识库:lead 用 kb_agent(mode=sync) 检索「${scen.zh} 数据分析」「${scen.pv.label} 物理机理与设定影响」,把检索结论作为寻优方向与步长依据;`,
105
+ `2. lead 把自己已绑定的节点授权授予 worker(dispatch_task 带 grant_node_ids 随任务授予,或 team_grant_nodes),确保工艺工程师与数据分析师各自拿到所需节点权限,不要无权限空转;`,
106
+ `3. 工艺工程师单变量小步调整(每步 ≤ 量程 2%,尊重单步限幅与写入间隔),每次调整后等 ${Math.round(scen.settleMs / 1000)}s 再 daq_query 复测「${scen.pv.label}」;`,
107
+ `4. 进入目标带且复测稳定后 dcw_judge 落判定(keep),lead 用 kb_agent(mode=async) 把本次经验沉淀入知识库(含调整前后参数值与响应数据),随后完成收口汇报。`,
108
+ ].join('\n')
109
+ const task = (await api.call('POST', `/api/workshop/channels/${channelId}/tasks`, { title: `${scen.zh}(KB 闭环)`, description: goal })).data
110
+ if (!task?.id) throw new Error(`根任务提交失败`)
111
+ res.rootTaskId = task.id
112
+ log(`④ 根任务 ${task.id} 已提交,开始作业(超时 ${Math.round(TASK_TIMEOUT_MS / 60000)}min)…\n`)
113
+
114
+ // ── ⑤ 轮询转录 ──
115
+ let seenMsg = new Set()
116
+ let seenTaskState = new Map()
117
+ let lastEventSeq = 0
118
+ let toolEvidence = { kbAgent: 0, grant: 0 }
119
+ const t0 = Date.now()
120
+ let terminal = null
121
+ const dump = async () => {
122
+ const msgs = (await api.call('GET', `/api/workshop/channels/${channelId}/messages?limit=200`)).data ?? []
123
+ for (const m of [...msgs].reverse()) {
124
+ const key = m.id ?? `${m.createdAt}:${m.fromAgentName}`
125
+ if (seenMsg.has(key)) continue
126
+ seenMsg.add(key)
127
+ const who = m.fromAgentName ?? m.from ?? '?'
128
+ const text = String(m.text ?? m.preview ?? '').slice(0, 600)
129
+ if (text.trim()) appendFileSync(join(dir, 'transcript.md'), `\n> **${who}** @ ${m.createdAt ?? ''}\n>\n${text.split('\n').map(l => `> ${l}`).join('\n')}\n`)
130
+ }
131
+ const tasks = (await api.call('GET', `/api/workshop/channels/${channelId}/tasks`)).data ?? []
132
+ const arr = Array.isArray(tasks) ? tasks : (tasks.tasks ?? [])
133
+ for (const t of arr) {
134
+ const st = `${t.id}:${t.state}:${t.progress ?? 0}`
135
+ if (seenTaskState.get(t.id) !== st) {
136
+ seenTaskState.set(t.id, st)
137
+ appendFileSync(join(dir, 'transcript.md'), `\n- [任务] ${t.id} 「${t.title}」 state=${t.state} progress=${t.progress ?? 0}% assignee=${t.assigneeId ?? '-'}`)
138
+ }
139
+ }
140
+ // 事件流:记录工具调用证据(kb_agent / team_grant_nodes / grant_node_ids)与 lead 进度报告
141
+ const ev = (await api.call('GET', `/api/workshop/channels/${channelId}/events?limit=200&afterSeq=${lastEventSeq}`)).data ?? {}
142
+ for (const item of (ev.items ?? [])) {
143
+ lastEventSeq = Math.max(lastEventSeq, Number(item.seq ?? 0))
144
+ const text = String(item.payload?.text ?? item.payload?.summary ?? '')
145
+ if (!text) continue
146
+ const kbHits = (text.match(/kb_agent/g) ?? []).length
147
+ const grantHits = (text.match(/team_grant_nodes|grant_node_ids/g) ?? []).length
148
+ toolEvidence.kbAgent += kbHits
149
+ toolEvidence.grant += grantHits
150
+ if (kbHits || grantHits) {
151
+ appendFileSync(join(dir, 'transcript.md'), `\n- [工具证据] @ ${(item.at ?? item.createdAt ?? '').slice(11, 19)} ${text.replace(/\n+/g, ' ').slice(0, 220)}`)
152
+ }
153
+ }
154
+ return { tasks: arr, msgs }
155
+ }
156
+ while (Date.now() - t0 < TASK_TIMEOUT_MS) {
157
+ await sleep(POLL_MS)
158
+ try {
159
+ const { tasks } = await dump()
160
+ const root = tasks.find(t => t.id === task.id)
161
+ if (root && ['COMPLETED', 'FAILED', 'CANCELED'].includes(root.state)) { terminal = root; break }
162
+ log(`… 作业中(${Math.round((Date.now() - t0) / 60000)}min)root=${root?.state ?? '?'}`)
163
+ }
164
+ catch (err) {
165
+ log(`… 轮询抖动(忽略): ${err?.message ?? err}`)
166
+ }
167
+ }
168
+ await dump()
169
+ if (!terminal) { res.errors.push(`根任务超时(${Math.round(TASK_TIMEOUT_MS / 60000)}min)未收口`) }
170
+ else if (terminal.state !== 'COMPLETED') { res.errors.push(`根任务终态=${terminal.state}`) }
171
+ res.checks.rootTaskClosed = terminal?.state === 'COMPLETED'
172
+ log(`\n⑤ 根任务终态=${terminal?.state ?? 'TIMEOUT'}`)
173
+
174
+ // ── ⑥ 验收 ──
175
+ const workers = agents.filter(a => a.role === 'worker')
176
+ let delegated = 0
177
+ for (const w of workers) {
178
+ const bs = (await api.call('GET', `/api/workshop/agent-tools/bindings?agentId=${w.id}`)).data
179
+ const flat = Array.isArray(bs) ? bs : (bs?.bindings ?? [])
180
+ if (flat.some(b => b.grantedByAgentId === lead.id)) delegated++
181
+ }
182
+ res.checks.workerDelegated = delegated > 0
183
+ log(`⑥ 委派核验:${delegated}/${workers.length} 个 worker 持有 lead 授予的节点授权`)
184
+
185
+ const dcwNow = (await api.call('GET', '/api/workshop/dcw')).data?.nodes ?? []
186
+ const myDcw = dcwNow.filter(n => Object.values(line.dcw).includes(n.id))
187
+ const wrote = myDcw.some(n => n.lastWriteAt)
188
+ res.checks.governedWriteHappened = wrote
189
+ res.dcAfter = myDcw.map(n => ({ id: n.id, name: n.name, value: n.value, lastWriteAt: n.lastWriteAt ?? null }))
190
+ log(`⑥ 治理写入核验:${wrote ? '发生过 dcw 治理写入' : '无 dcw 写入痕迹'}`)
191
+
192
+ const pvMean = await readPvMean(api, pvNode, 5).catch(() => null)
193
+ const inBand = pvMean != null && Math.abs(Number(pvMean) - scen.pv.target) <= scen.pv.tol
194
+ res.checks.pvInBand = inBand
195
+ res.pvMean = pvMean
196
+ log(`⑥ PV 复测:均值=${pvMean} 目标带=${scen.pv.target}±${scen.pv.tol} → ${inBand ? '达标' : '未达标'}`)
197
+
198
+ res.toolEvidence = toolEvidence
199
+ res.checks.kbToolUsed = toolEvidence.kbAgent > 0
200
+ res.checks.grantToolUsed = toolEvidence.grant > 0 || delegated > 0
201
+ log(`⑥ 工具证据(事件流):kb_agent×${toolEvidence.kbAgent} 委派×${toolEvidence.grant}`)
202
+
203
+ log(`⑥ 等待知识库经验沉淀可检索(≤${Math.round(KB_WAIT_MS / 60000)}min)…`)
204
+ const kbQuery = encodeURIComponent(`${scen.zh.slice(0, 6)} ${scen.pv.label} 经验`)
205
+ const kbDeadline = Date.now() + KB_WAIT_MS
206
+ let kbHit = false
207
+ while (Date.now() < kbDeadline) {
208
+ await sleep(45_000)
209
+ const sr = (await api.call('GET', `/api/plugins/rag-bridge/search?q=${kbQuery}&top_k=5`).catch(() => null))?.data
210
+ if ((sr?.total_results ?? 0) > 0 || (sr?.results ?? []).length > 0) { kbHit = true; break }
211
+ log(` … 检索暂未命中(累计等待 ${Math.round((kbDeadline - Date.now()) / 60000)}min)`)
212
+ }
213
+ res.checks.kbExperience = kbHit
214
+ log(`⑥ 知识库经验检索:${kbHit ? '已检出本场景经验内容' : '超时未检出(检索面后端索引漂移时以转录工具证据为准)'}`)
215
+ }
216
+ catch (err) {
217
+ res.errors.push(String(err?.message ?? err))
218
+ log(`✘ 异常: ${err?.message ?? err}`)
219
+ }
220
+
221
+ res.ok = res.errors.length === 0 && Object.values(res.checks).every(Boolean)
222
+ log(`\n════ [${id}] 结果: ${res.ok ? 'PASS' : 'FAIL'} checks=${JSON.stringify(res.checks)}${res.errors.length ? ` errors=${res.errors.join(';')}` : ''}`)
223
+ writeFileSync(join(dir, 'final.json'), JSON.stringify(res, null, 2))
224
+ }
225
+
226
+ writeFileSync(join(outDir, 'kb-team-omp-result.json'), JSON.stringify(globalResult, null, 2))
227
+ const allOk = globalResult.scenarios.every(s => s.ok)
228
+ console.log(`\n════ 总结果: ${allOk ? '✅ 全场景 PASS' : '❌ 存在 FAIL'}(明细: ${outDir})`)
229
+ process.exit(allOk ? 0 : 1)
@@ -0,0 +1,45 @@
1
+ /**
2
+ * POST /api/workshop/agent-tools/bindings/grant —— lead 把自己绑定的节点授权给同频道 worker。
3
+ * body: { channelId, agentId(worker 成员实例), nodeIds: string[], mode?: 'auto'|'manual' }
4
+ * 硬约束:nodeIds 每一个都必须在频道 lead 的绑定面内(权限不可超越授予者);全成全败。
5
+ * 产线权限随绑定继承(lead 绑定建立时已校验);绑定带 grantedByAgentId/grantedAt 溯源。
6
+ * 鉴权:channel 归属者(遗留公共 channel 需 admin)。
7
+ */
8
+ import { readBody } from 'h3'
9
+ import { resolveUser } from '@/server/api/workshop/caller'
10
+ import { defineApiHandler } from '@/server/utils/response'
11
+ import { getWorkshopManager } from '@/server/plugins/workshop'
12
+ import { AppError, ErrorCodes } from '@/server/utils/errors'
13
+ import { applyDelegation, planDelegation } from '@/server/services/workshop/agents/node-delegation'
14
+ import type { DelegationMember } from '@/server/services/workshop/agents/node-delegation'
15
+
16
+ export default defineApiHandler(async (event) => {
17
+ const user = resolveUser(event)
18
+ const body = await readBody<{ channelId?: string, agentId?: string, nodeIds?: string[], mode?: 'auto' | 'manual' }>(event) ?? {}
19
+ const channelId = String(body.channelId ?? '')
20
+ const agentId = String(body.agentId ?? '')
21
+ const nodeIds = Array.isArray(body.nodeIds) ? body.nodeIds.map(x => String(x ?? '').trim()).filter(Boolean) : []
22
+ if (!channelId || !agentId || !nodeIds.length) {
23
+ throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'channelId / agentId / nodeIds 必填')
24
+ }
25
+ const manager = getWorkshopManager()
26
+ const channel = manager.getChannelForUser(channelId, user.id)
27
+ if (channel?.ownerUserId === null) {
28
+ const { requireAdmin } = await import('@/server/api/workshop/caller')
29
+ requireAdmin(event)
30
+ }
31
+ const row = (await manager.listChannels()).find(c => c.id === channelId)
32
+ if (!row?.leadAgentId) throw new AppError(404, ErrorCodes.NOT_FOUND, `频道不存在或没有 lead: ${channelId}`)
33
+
34
+ const members = await manager.listChannelAgents(channelId) as unknown as DelegationMember[]
35
+ const plan = planDelegation({
36
+ leaderAgentId: row.leadAgentId,
37
+ channelId,
38
+ targetAgentId: agentId,
39
+ nodeIds,
40
+ members,
41
+ mode: body.mode,
42
+ })
43
+ const bindings = applyDelegation(plan, row.leadAgentId)
44
+ return { granted: bindings }
45
+ })
@@ -0,0 +1,42 @@
1
+ /**
2
+ * POST /api/workshop/agent-tools/bindings/revoke —— lead 收回授予给 worker 的节点授权。
3
+ * body: { channelId, agentId(worker 成员实例), nodeIds: string[] }
4
+ * 可收回:lead 自己授予的(grantedByAgentId=lead)或 lead 也持有的节点绑定;
5
+ * 其余绑定原样保留并在结果中标注 revoked=false。
6
+ * 鉴权:channel 归属者(遗留公共 channel 需 admin)。
7
+ */
8
+ import { readBody } from 'h3'
9
+ import { resolveUser } from '@/server/api/workshop/caller'
10
+ import { defineApiHandler } from '@/server/utils/response'
11
+ import { getWorkshopManager } from '@/server/plugins/workshop'
12
+ import { AppError, ErrorCodes } from '@/server/utils/errors'
13
+ import { revokeDelegation } from '@/server/services/workshop/agents/node-delegation'
14
+ import type { DelegationMember } from '@/server/services/workshop/agents/node-delegation'
15
+
16
+ export default defineApiHandler(async (event) => {
17
+ const user = resolveUser(event)
18
+ const body = await readBody<{ channelId?: string, agentId?: string, nodeIds?: string[] }>(event) ?? {}
19
+ const channelId = String(body.channelId ?? '')
20
+ const agentId = String(body.agentId ?? '')
21
+ const nodeIds = Array.isArray(body.nodeIds) ? body.nodeIds.map(x => String(x ?? '').trim()).filter(Boolean) : []
22
+ if (!channelId || !agentId || !nodeIds.length) {
23
+ throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'channelId / agentId / nodeIds 必填')
24
+ }
25
+ const manager = getWorkshopManager()
26
+ const channel = manager.getChannelForUser(channelId, user.id)
27
+ if (channel?.ownerUserId === null) {
28
+ const { requireAdmin } = await import('@/server/api/workshop/caller')
29
+ requireAdmin(event)
30
+ }
31
+ const row = (await manager.listChannels()).find(c => c.id === channelId)
32
+ if (!row?.leadAgentId) throw new AppError(404, ErrorCodes.NOT_FOUND, `频道不存在或没有 lead: ${channelId}`)
33
+
34
+ const members = await manager.listChannelAgents(channelId) as unknown as DelegationMember[]
35
+ const results = revokeDelegation({
36
+ leaderAgentId: row.leadAgentId,
37
+ targetAgentId: agentId,
38
+ nodeIds,
39
+ members,
40
+ })
41
+ return { results }
42
+ })
@@ -23,6 +23,7 @@ const instantiateSchema = z.object({
23
23
  scenePackId: z.string().min(1).optional(),
24
24
  optimizationMode: z.enum(['exploration', 'aml']).optional(),
25
25
  boundModelId: z.string().min(1).optional(),
26
+ enableKnowledgeBase: z.boolean().optional(),
26
27
  })
27
28
 
28
29
  export default defineApiHandler(async (event) => {
@@ -30,7 +31,7 @@ export default defineApiHandler(async (event) => {
30
31
  const user = resolveUser(event)
31
32
  const body = await readValidatedBody(event, zValidator(instantiateSchema))
32
33
  const manager = getWorkshopManager()
33
- const result = await manager.instantiateChannelTemplate(templateId, user, body.name, { scene: body.scene, promptVariables: body.promptVariables, objective: body.objective, toolProfile: body.toolProfile, controlPolicy: body.controlPolicy, providerId: body.providerId, providerVersion: body.providerVersion, providerHash: body.providerHash, scenePackId: body.scenePackId, optimizationMode: body.optimizationMode, boundModelId: body.boundModelId })
34
+ const result = await manager.instantiateChannelTemplate(templateId, user, body.name, { scene: body.scene, promptVariables: body.promptVariables, objective: body.objective, toolProfile: body.toolProfile, controlPolicy: body.controlPolicy, providerId: body.providerId, providerVersion: body.providerVersion, providerHash: body.providerHash, scenePackId: body.scenePackId, optimizationMode: body.optimizationMode, boundModelId: body.boundModelId, enableKnowledgeBase: body.enableKnowledgeBase })
34
35
  // 模板含 lead 时直接启动调度循环(可提交任务)
35
36
  if (result.leadAgentId) {
36
37
  ensureLeadSchedulerLoop(manager, result.channelId)
@@ -19,6 +19,7 @@ import type { HostToolBridgeContext, HostToolCall, HostToolResult } from './type
19
19
  import { INDUSTRIAL_TOOL_NAMES, dispatchIndustrialTool } from './tools/industrial'
20
20
  import { handleCompleteTask, handleReportProgress } from './tools/progress'
21
21
  import { handleCancelTask, handleDispatchTask, handleGetMyTaskQueue, handleGetTaskDetails, handleListChannelTasks, handleReassignTask, handleRefuseTask, handleSubmitTask, handleUpdateTask } from './tools/tasks'
22
+ import { handleGrantNodes, handleRevokeNodes } from './tools/team-delegation'
22
23
  import { handleBroadcastMessage, handleListOtherTeams, handlePollMessages, handleReadChannelMail, handleSearchOtherTeamsMemory, handleSendCrossChannelMessage, handleSendMessageToAgent } from './tools/messaging'
23
24
  import { handleSaveMemory, handleSearchMemory } from './tools/memory'
24
25
  import { handleCreateTeamAgent, handleGetQueueOverview, handleListTeamAgents, handleRemoveTeamAgent, handleUpdateTeamAgent } from './tools/team'
@@ -121,7 +122,11 @@ export async function dispatchHostTool(ctx: HostToolBridgeContext, req: HostTool
121
122
  case 'submit_task':
122
123
  return await handleSubmitTask(args, state, ws)
123
124
  case 'dispatch_task':
124
- return await handleDispatchTask(args, ws)
125
+ return await handleDispatchTask(args, ws, identity)
126
+ case 'team_grant_nodes':
127
+ return await handleGrantNodes(identity, args, ws)
128
+ case 'team_revoke_nodes':
129
+ return await handleRevokeNodes(identity, args, ws)
125
130
  case 'send_message_to_agent':
126
131
  return await handleSendMessageToAgent(args, state, ws)
127
132
  case 'send_cross_channel_message':
@@ -23,12 +23,25 @@ export async function handleSubmitTask(args: Record<string, unknown>, state: Hos
23
23
  }
24
24
  }
25
25
 
26
- export async function handleDispatchTask(args: Record<string, unknown>, ws: AgentWorkspace): Promise<HostToolResult> {
26
+ export async function handleDispatchTask(args: Record<string, unknown>, ws: AgentWorkspace, identity?: HostToolBridgeContext['identity']): Promise<HostToolResult> {
27
27
  const assigneeId = args.assignee_id as string
28
28
  const title = args.title as string
29
29
  const description = args.description as string | undefined
30
30
  const parentTaskId = args.parent_task_id as string | undefined
31
31
  const routeReason = args.route_reason as string | undefined
32
+ // 派发时随任务授予节点权限(lead 专属;grant_node_ids ⊆ lead 自身绑定面,fail-closed):
33
+ // 任一节点不满足则整单拒绝,任务不创建 —— 避免 worker 拿到任务却没有节点权限的半途态。
34
+ let grantNote = ''
35
+ const rawGrant = args.grant_node_ids ?? args.grantNodeIds
36
+ if (rawGrant != null && identity) {
37
+ const { grantNodesForDispatch } = await import('./team-delegation')
38
+ const grantNodeIds = (Array.isArray(rawGrant) ? rawGrant : String(rawGrant).split(',')).map(x => String(x ?? '').trim()).filter(Boolean)
39
+ if (!grantNodeIds.length) return { text: 'grant_node_ids 为空:要么不传,要么给出至少一个节点 id。', isError: true }
40
+ const grantMode = args.grant_mode === 'manual' || args.grant_mode === 'auto' ? (args.grant_mode as 'auto' | 'manual') : undefined
41
+ const grant = await grantNodesForDispatch(identity, assigneeId, grantNodeIds, grantMode, ws)
42
+ if (!grant.ok) return { text: `未派发:${grant.text}\n请先用 team_grant_nodes 确认你持有这些节点,或修正 node id 后重试。`, isError: true }
43
+ grantNote = `\n${grant.text}`
44
+ }
32
45
  // 重复派发守卫(真实场景实测:lead 模型可能对同一目标重复派发,引发协调风暴):
33
46
  // 同父任务下已存在同标题非终态子任务 → 不再创建,直接指路既有任务
34
47
  const dup = await ws.listTasks()
@@ -42,7 +55,7 @@ export async function handleDispatchTask(args: Record<string, unknown>, ws: Agen
42
55
  }
43
56
  }
44
57
  const task = await ws.dispatchTask({ assigneeId, title, description, parentTaskId, routeReason })
45
- return { text: `子任务 ${task.id} 已创建并指派 → ${assigneeId}(父任务 ${parentTaskId ?? '无'},标题: ${title}${routeReason ? `,路由理由: ${routeReason}` : ''})` }
58
+ return { text: `子任务 ${task.id} 已创建并指派 → ${assigneeId}(父任务 ${parentTaskId ?? '无'},标题: ${title}${routeReason ? `,路由理由: ${routeReason}` : ''})${grantNote}` }
46
59
  }
47
60
 
48
61
  export async function handleRefuseTask(args: Record<string, unknown>, ws: AgentWorkspace): Promise<HostToolResult> {
@@ -0,0 +1,104 @@
1
+ /**
2
+ * 团队节点权限委派工具(lead 专属):team_grant_nodes / team_revoke_nodes。
3
+ *
4
+ * lead 把**自己已绑定**的 DAQ/DCW 节点授权给同频道 worker(派发前、执行中均可),
5
+ * 授权面不可超越 lead 本人的绑定面(planDelegation fail-closed 校验)。
6
+ * 校验核心在 agents/node-delegation.ts;本文件只做工具面参数解析与结果文本。
7
+ */
8
+ import { AppError } from '../../../../../utils/errors'
9
+ import { applyDelegation, planDelegation, revokeDelegation, type DelegationMember } from '../../node-delegation'
10
+ import type { HostToolBridgeContext, HostToolResult } from '../types'
11
+
12
+ /** workspace 成员视图(listAgents 与本工具面的最小接口;便于单测桩替换) */
13
+ interface MembersView {
14
+ listAgents(): Promise<Array<{ id: string, role: 'lead' | 'worker', enabled?: number }>>
15
+ }
16
+
17
+ function membersOf(ws: MembersView): Promise<DelegationMember[]> {
18
+ return ws.listAgents() as Promise<DelegationMember[]>
19
+ }
20
+
21
+ function summaryText(bindings: Array<{ nodeId: string, kind: string, mode: string }>): string {
22
+ const lines = bindings.map(b => ` - ${b.kind === 'daq' ? '数采' : '写控'} ${b.nodeId}(mode=${b.mode})`)
23
+ return `\n${lines.join('\n')}`
24
+ }
25
+
26
+ function parseNodeIds(args: Record<string, unknown>): string[] {
27
+ const raw = args.node_ids ?? args.nodeIds
28
+ const list = Array.isArray(raw) ? raw : String(raw ?? '').split(',')
29
+ return list.map(x => String(x ?? '').trim()).filter(Boolean)
30
+ }
31
+
32
+ /** lead → worker 授予节点(自己绑定面内的节点;fail-closed 全成全败) */
33
+ export async function handleGrantNodes(identity: HostToolBridgeContext['identity'], args: Record<string, unknown>, ws: MembersView): Promise<HostToolResult> {
34
+ const targetAgentId = String(args.agent_id ?? args.assignee_id ?? '').trim()
35
+ const nodeIds = parseNodeIds(args)
36
+ const mode = args.mode === 'manual' || args.mode === 'auto' ? (args.mode as 'auto' | 'manual') : undefined
37
+ try {
38
+ const plan = planDelegation({
39
+ leaderAgentId: identity.agentId,
40
+ channelId: identity.channelId,
41
+ targetAgentId,
42
+ nodeIds,
43
+ members: await membersOf(ws),
44
+ mode,
45
+ })
46
+ const bindings = applyDelegation(plan, identity.agentId)
47
+ return {
48
+ text: `已把 ${bindings.length} 条节点授权授予 ${targetAgentId}:${summaryText(bindings)}\n来源:lead 绑定面内的节点;worker 现在可用 my_industrial_nodes 查看自己的授权。`,
49
+ }
50
+ }
51
+ catch (err) {
52
+ return { text: err instanceof AppError ? err.message : `节点授权失败: ${err instanceof Error ? err.message : String(err)}`, isError: true }
53
+ }
54
+ }
55
+
56
+ /** lead 收回授予给 worker 的节点授权 */
57
+ export async function handleRevokeNodes(identity: HostToolBridgeContext['identity'], args: Record<string, unknown>, ws: MembersView): Promise<HostToolResult> {
58
+ const targetAgentId = String(args.agent_id ?? args.assignee_id ?? '').trim()
59
+ const nodeIds = parseNodeIds(args)
60
+ try {
61
+ const results = revokeDelegation({
62
+ leaderAgentId: identity.agentId,
63
+ targetAgentId,
64
+ nodeIds,
65
+ members: await membersOf(ws),
66
+ })
67
+ const okList = results.filter(r => r.revoked)
68
+ const missList = results.filter(r => !r.revoked)
69
+ const parts = [`已收回 ${okList.length} 条授权`, ...okList.map(r => ` - ${r.kind} ${r.nodeId}`)]
70
+ if (missList.length) parts.push(`未收回(不在其绑定面或非你授予):${missList.map(r => `${r.kind}:${r.nodeId}`).join('、')}`)
71
+ return { text: parts.join('\n') }
72
+ }
73
+ catch (err) {
74
+ return { text: err instanceof AppError ? err.message : `收回授权失败: ${err instanceof Error ? err.message : String(err)}`, isError: true }
75
+ }
76
+ }
77
+
78
+ export interface DispatchGrantResult {
79
+ ok: boolean
80
+ text: string
81
+ }
82
+
83
+ /**
84
+ * 派发时随任务授予节点(dispatch_task 的 grant_node_ids;lead 专属)。
85
+ * fail-closed:任一节点不在 lead 绑定面 → 整单失败,任务不创建。
86
+ */
87
+ export async function grantNodesForDispatch(identity: HostToolBridgeContext['identity'], assigneeId: string, nodeIds: string[], mode: 'auto' | 'manual' | undefined, ws: MembersView): Promise<DispatchGrantResult> {
88
+ try {
89
+ const plan = planDelegation({
90
+ leaderAgentId: identity.agentId,
91
+ channelId: identity.channelId,
92
+ targetAgentId: assigneeId,
93
+ nodeIds,
94
+ members: await membersOf(ws),
95
+ mode,
96
+ })
97
+ const bindings = applyDelegation(plan, identity.agentId)
98
+ return { ok: true, text: `随任务授予 ${bindings.length} 条节点授权 → ${assigneeId}${summaryText(bindings)}` }
99
+ }
100
+ catch (err) {
101
+ const msg = err instanceof AppError ? err.message : `随任务授予节点失败: ${err instanceof Error ? err.message : String(err)}`
102
+ return { ok: false, text: msg }
103
+ }
104
+ }
@@ -38,6 +38,10 @@ export interface AgentNodeBinding {
38
38
  kind: AgentNodeBindingKind
39
39
  mode: AgentNodeBindingMode
40
40
  tuning?: AgentNodeBindingTuning
41
+ /** 委派来源:lead 经 team_grant_nodes / dispatch_task(grant_node_ids) 授予时 = lead 成员实例 id */
42
+ grantedByAgentId?: string
43
+ /** 委派时间(ISO;仅委派产生的绑定携带) */
44
+ grantedAt?: string
41
45
  createdAt: string
42
46
  }
43
47
 
@@ -83,7 +87,7 @@ export class AgentNodeBindingRepo {
83
87
  return this.list.find(b => b.agentId === agentId && b.nodeId === nodeId && b.kind === kind)
84
88
  }
85
89
 
86
- bind(agentId: string, nodeId: string, kind: AgentNodeBindingKind, mode: AgentNodeBindingMode, tuning?: AgentNodeBindingTuning): AgentNodeBinding {
90
+ bind(agentId: string, nodeId: string, kind: AgentNodeBindingKind, mode: AgentNodeBindingMode, tuning?: AgentNodeBindingTuning, provenance?: { grantedByAgentId?: string }): AgentNodeBinding {
87
91
  if (!agentId) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'agentId 必填')
88
92
  if (!nodeId) throw new AppError(400, ErrorCodes.VALIDATION_ERROR, 'nodeId 必填')
89
93
  if (kind !== 'dcw' && kind !== 'daq') throw new AppError(400, ErrorCodes.VALIDATION_ERROR, `未知节点类型: ${kind}`)
@@ -92,6 +96,10 @@ export class AgentNodeBindingRepo {
92
96
  if (prev) {
93
97
  prev.mode = mode
94
98
  if (tuning !== undefined) prev.tuning = normalizeTuning(tuning)
99
+ if (provenance?.grantedByAgentId) {
100
+ prev.grantedByAgentId = provenance.grantedByAgentId
101
+ prev.grantedAt = new Date().toISOString()
102
+ }
95
103
  this.flush()
96
104
  return prev
97
105
  }
@@ -102,6 +110,7 @@ export class AgentNodeBindingRepo {
102
110
  kind,
103
111
  mode,
104
112
  ...(tuning ? { tuning: normalizeTuning(tuning) } : {}),
113
+ ...(provenance?.grantedByAgentId ? { grantedByAgentId: provenance.grantedByAgentId, grantedAt: new Date().toISOString() } : {}),
105
114
  createdAt: new Date().toISOString(),
106
115
  }
107
116
  this.list.push(binding)