agentworkshop 0.7.51 → 0.7.53

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 (482) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +2097 -1955
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +2097 -1955
  3. package/.output/.AgentWorkShop/schema.json +2 -0
  4. package/.output/nitro.json +1 -1
  5. package/.output/public/_nuxt/{D0ldVwl-.js → 77DRSnQv.js} +1 -1
  6. package/.output/public/_nuxt/8oRmGaAV.js +1 -0
  7. package/.output/public/_nuxt/{BPou3U7b.js → BLnLjzka.js} +1 -1
  8. package/.output/public/_nuxt/{CFQyYMEn2.js → BSdJTnk12.js} +1 -1
  9. package/.output/public/_nuxt/{C4lagVdN2.js → BUD1CNvB2.js} +1 -1
  10. package/.output/public/_nuxt/BXR3tgEk.js +1 -0
  11. package/.output/public/_nuxt/{B9QzrmgE.js → BhlRInVa.js} +1 -1
  12. package/.output/public/_nuxt/{DhFv8S2Z.js → BkfA3BbD.js} +1 -1
  13. package/.output/public/_nuxt/{ChGuLxwW2.js → BpcQDwKM2.js} +1 -1
  14. package/.output/public/_nuxt/{DQMbdg4t.js → BwlGxRxA.js} +1 -1
  15. package/.output/public/_nuxt/{Bt2ZL5332.js → C4sQKuhk2.js} +1 -1
  16. package/.output/public/_nuxt/{zh-S_7rN2.js → CBUIODly2.js} +1 -1
  17. package/.output/public/_nuxt/CR-ILcRu2.js +1 -0
  18. package/.output/public/_nuxt/CZLnEnbE.js +14 -0
  19. package/.output/public/_nuxt/{jRTz0hjN2.js → Chxx-DIE2.js} +1 -1
  20. package/.output/public/_nuxt/{BGAaKBeo2.js → CjwxhpwR2.js} +1 -1
  21. package/.output/public/_nuxt/{D89BUtx6.js → CvGYm7w8.js} +1 -1
  22. package/.output/public/_nuxt/{B9BmiUil.js → DAGuPgXa.js} +1 -1
  23. package/.output/public/_nuxt/{DefDtlKK.js → DE6H1HdJ.js} +1 -1
  24. package/.output/public/_nuxt/{DzfVS8N72.js → DFhyhDGa2.js} +1 -1
  25. package/.output/public/_nuxt/{BXx9AxdF2.js → DSqMyLCV2.js} +1 -1
  26. package/.output/public/_nuxt/{asmJ99nX2.js → DV5joWTn2.js} +1 -1
  27. package/.output/public/_nuxt/{DClNt1uS.js → DVOR2pWg.js} +1 -1
  28. package/.output/public/_nuxt/DWsgRq2c.js +1 -0
  29. package/.output/public/_nuxt/{CU-mhG0-.js → DZDi8inD.js} +1 -1
  30. package/.output/public/_nuxt/{DMYYS5sK.js → Dep0Hc9w.js} +1 -1
  31. package/.output/public/_nuxt/{JAM4aNC_.js → DffgG8vT.js} +1 -1
  32. package/.output/public/_nuxt/{CFQSjB1h.js → DlCktWDT.js} +1 -1
  33. package/.output/public/_nuxt/{CP0I2l-6.js → DmzmgYHb.js} +1 -1
  34. package/.output/public/_nuxt/PluginSlot.CGH0vb95.css +1 -0
  35. package/.output/public/_nuxt/{lWYQbIR3.js → WmMwIS4y.js} +1 -1
  36. package/.output/public/_nuxt/{_id_.DamiFT0Q.css → _id_.rdGx-UDx.css} +1 -1
  37. package/.output/public/_nuxt/{BgEDwFMf.js → _kUzq9VF.js} +1 -1
  38. package/.output/public/_nuxt/_wsId_.XjmieZaJ.css +1 -0
  39. package/.output/public/_nuxt/{B7jlMWsz.js → aV6YPjg0.js} +1 -1
  40. package/.output/public/_nuxt/builds/latest.json +1 -1
  41. package/.output/public/_nuxt/builds/meta/5ccc21c2-aba0-4b63-9a13-410e0569e345.json +1 -0
  42. package/.output/public/_nuxt/channel-templates.DkNZg-lF.css +1 -0
  43. package/.output/public/_nuxt/{default.CXb_zoN6.css → default.CyLpQD1C.css} +1 -1
  44. package/.output/public/_nuxt/o9rJf00k.js +1 -0
  45. package/.output/public/_nuxt/sl1EEoCr2.js +21 -0
  46. package/.output/public/robots.txt +3 -0
  47. package/.output/server/chunks/_/binding-authz.mjs +1 -1
  48. package/.output/server/chunks/_/character-asset.repo.mjs +1 -1
  49. package/.output/server/chunks/_/entity.mjs +1 -1
  50. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  51. package/.output/server/chunks/_/nitro.mjs +2268 -1501
  52. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  53. package/.output/server/chunks/_/scene-layout.repo.mjs +1 -1
  54. package/.output/server/chunks/build/{PluginSlot-D2WUZgbp.mjs → PluginSlot-CT4YaNrB.mjs} +5 -5
  55. package/.output/server/chunks/build/{PluginSlot-D2WUZgbp.mjs.map → PluginSlot-CT4YaNrB.mjs.map} +1 -1
  56. package/.output/server/chunks/build/TownView-fP9BiALv.mjs +1 -1
  57. package/.output/server/chunks/build/{_id_-BUpQSlzo.mjs → _id_-CK-QFrDV.mjs} +55 -51
  58. package/.output/server/chunks/build/_id_-CK-QFrDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs → _wsId_-DdqXzycE.mjs} +320 -202
  60. package/.output/server/chunks/build/{_wsId_-DPy2BXRd.mjs.map → _wsId_-DdqXzycE.mjs.map} +1 -1
  61. package/.output/server/chunks/build/{agents-CDLcboCv.mjs → agents-DqICy4AL.mjs} +6 -6
  62. package/.output/server/chunks/build/{agents-CDLcboCv.mjs.map → agents-DqICy4AL.mjs.map} +1 -1
  63. package/.output/server/chunks/build/{channel-templates-DjEsj0_v.mjs → channel-templates-gdCLajKy.mjs} +114 -25
  64. package/.output/server/chunks/build/channel-templates-gdCLajKy.mjs.map +1 -0
  65. package/.output/server/chunks/build/daq-N69AOtgw.mjs +1 -1
  66. package/.output/server/chunks/build/dcw-CN9d3Rs7.mjs +1 -1
  67. package/.output/server/chunks/build/{default-DCf9tn1i.mjs → default-CXUe4HL7.mjs} +65 -62
  68. package/.output/server/chunks/build/{default-DCf9tn1i.mjs.map → default-CXUe4HL7.mjs.map} +1 -1
  69. package/.output/server/chunks/build/{pages-rZKH72eC.mjs → pages-CRMeXrxG.mjs} +3 -3
  70. package/.output/server/chunks/build/{pages-rZKH72eC.mjs.map → pages-CRMeXrxG.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{plugins-DSka7-vS.mjs → plugins-NAS9MQ5r.mjs} +2 -2
  72. package/.output/server/chunks/build/{plugins-DSka7-vS.mjs.map → plugins-NAS9MQ5r.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs → schedules-D8vYHgQ5.mjs} +2 -2
  74. package/.output/server/chunks/build/{schedules-lo4bfgVt.mjs.map → schedules-D8vYHgQ5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{settings-CAJWvul5.mjs → settings-B7HA-sdb.mjs} +3 -3
  76. package/.output/server/chunks/build/{settings-CAJWvul5.mjs.map → settings-B7HA-sdb.mjs.map} +1 -1
  77. package/.output/server/chunks/build/{teams-DBBvIToa.mjs → teams-wM-MdLv9.mjs} +8 -8
  78. package/.output/server/chunks/build/{teams-DBBvIToa.mjs.map → teams-wM-MdLv9.mjs.map} +1 -1
  79. package/.output/server/chunks/build/types-D6J7slEa.mjs +1 -1
  80. package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs → useAgentHarnessOptions-BnFCh23W.mjs} +2 -2
  81. package/.output/server/chunks/build/{useAgentHarnessOptions-D6SJ_uUr.mjs.map → useAgentHarnessOptions-BnFCh23W.mjs.map} +1 -1
  82. package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs → useAgentTemplateActions-DsBRUQni.mjs} +2 -2
  83. package/.output/server/chunks/build/{useAgentTemplateActions-CdG4g_PF.mjs.map → useAgentTemplateActions-DsBRUQni.mjs.map} +1 -1
  84. package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs → useAgentTemplateForm-DzQ_t2Ue.mjs} +2 -2
  85. package/.output/server/chunks/build/{useAgentTemplateForm-a5y-N5sB.mjs.map → useAgentTemplateForm-DzQ_t2Ue.mjs.map} +1 -1
  86. package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs → useAgentTemplatesCatalog-Q7LgG1Af.mjs} +2 -2
  87. package/.output/server/chunks/build/{useAgentTemplatesCatalog-pBVcUuN3.mjs.map → useAgentTemplatesCatalog-Q7LgG1Af.mjs.map} +1 -1
  88. package/.output/server/chunks/build/useDaqAddNode-kW7uTSMQ.mjs +1 -1
  89. package/.output/server/chunks/build/useDaqDetailNode-D_vhG0jF.mjs +1 -1
  90. package/.output/server/chunks/build/useDaqDetailParams-JfqHvTxr.mjs +1 -1
  91. package/.output/server/chunks/build/useDaqFilters-BUQtZ82a.mjs +1 -1
  92. package/.output/server/chunks/build/useDaqStream-wOxZcMDA.mjs +1 -1
  93. package/.output/server/chunks/build/useDaqTemplates-BqQRdrIm.mjs +1 -1
  94. package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs → useDashboardData-DWJ6vHjm.mjs} +2 -2
  95. package/.output/server/chunks/build/{useDashboardData-Do_Vsepa.mjs.map → useDashboardData-DWJ6vHjm.mjs.map} +1 -1
  96. package/.output/server/chunks/build/useDcwAddNode-C1HDP3yG.mjs +1 -1
  97. package/.output/server/chunks/build/useDcwStream-D04kCV3J.mjs +1 -1
  98. package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs → useTeamActions-BOLQkYxg.mjs} +2 -2
  99. package/.output/server/chunks/build/{useTeamActions-C4n-taBk.mjs.map → useTeamActions-BOLQkYxg.mjs.map} +1 -1
  100. package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs → useTeamAddMemberDialog-BCgrLPxI.mjs} +2 -2
  101. package/.output/server/chunks/build/{useTeamAddMemberDialog-Cp_z3nMa.mjs.map → useTeamAddMemberDialog-BCgrLPxI.mjs.map} +1 -1
  102. package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs → useTeamCreateDialog-CJk40LqS.mjs} +2 -2
  103. package/.output/server/chunks/build/{useTeamCreateDialog-C8LKUoe2.mjs.map → useTeamCreateDialog-CJk40LqS.mjs.map} +1 -1
  104. package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs → useTeamDeployDialog-49hdUXQP.mjs} +2 -2
  105. package/.output/server/chunks/build/{useTeamDeployDialog-wdBVsNWY.mjs.map → useTeamDeployDialog-49hdUXQP.mjs.map} +1 -1
  106. package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs → useTeamPluginDialog-Dh-QOoiU.mjs} +2 -2
  107. package/.output/server/chunks/build/{useTeamPluginDialog-CIk8G8nI.mjs.map → useTeamPluginDialog-Dh-QOoiU.mjs.map} +1 -1
  108. package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs → useTeamsCatalog-HBSyKt5P.mjs} +2 -2
  109. package/.output/server/chunks/build/{useTeamsCatalog-D6TULzmS.mjs.map → useTeamsCatalog-HBSyKt5P.mjs.map} +1 -1
  110. package/.output/server/chunks/build/{useWorkshopApi-B1B9vd4m.mjs → useWorkshopApi-C9sTYu1F.mjs} +13 -2
  111. package/.output/server/chunks/build/useWorkshopApi-C9sTYu1F.mjs.map +1 -0
  112. package/.output/server/chunks/build/useWorkshopWs-Bm80bLn7.mjs.map +1 -1
  113. package/.output/server/chunks/routes/api/index.get.mjs +1 -1
  114. package/.output/server/chunks/routes/api/index.post.mjs +14 -3
  115. package/.output/server/chunks/routes/api/index.post.mjs.map +1 -1
  116. package/.output/server/chunks/routes/api/mcp/workshop.mjs +43 -14
  117. package/.output/server/chunks/routes/api/mcp/workshop.mjs.map +1 -1
  118. package/.output/server/chunks/routes/api/metrics.mjs +2 -0
  119. package/.output/server/chunks/routes/api/metrics.mjs.map +1 -1
  120. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
  121. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
  122. package/.output/server/chunks/routes/api/system/backup/list.get.mjs +47 -0
  123. package/.output/server/chunks/routes/api/system/backup/list.get.mjs.map +1 -0
  124. package/.output/server/chunks/routes/api/system/backup/run.post.mjs +35 -0
  125. package/.output/server/chunks/routes/api/system/backup/run.post.mjs.map +1 -0
  126. package/.output/server/chunks/routes/api/system/config-groups/_id_.delete.mjs +1 -1
  127. package/.output/server/chunks/routes/api/system/config-groups/_id_.patch.mjs +1 -1
  128. package/.output/server/chunks/routes/api/system/index.get.mjs +1 -1
  129. package/.output/server/chunks/routes/api/system/index.patch.mjs +15 -4
  130. package/.output/server/chunks/routes/api/system/index.patch.mjs.map +1 -1
  131. package/.output/server/chunks/routes/api/system/index.post.mjs +1 -1
  132. package/.output/server/chunks/routes/api/system/index2.get.mjs +1 -1
  133. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
  134. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
  135. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
  136. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +15 -3
  137. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs.map +1 -1
  138. package/.output/server/chunks/routes/api/system/timezone.get.mjs +1 -1
  139. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +14 -3
  140. package/.output/server/chunks/routes/api/users/_id_.delete.mjs.map +1 -1
  141. package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
  142. package/.output/server/chunks/routes/api/users/_id_.put.mjs +14 -3
  143. package/.output/server/chunks/routes/api/users/_id_.put.mjs.map +1 -1
  144. package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
  145. package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
  146. package/.output/server/chunks/routes/api/users/login.post.mjs +3 -2
  147. package/.output/server/chunks/routes/api/users/login.post.mjs.map +1 -1
  148. package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
  149. package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
  150. package/.output/server/chunks/routes/api/users/register.post.mjs +4 -1
  151. package/.output/server/chunks/routes/api/users/register.post.mjs.map +1 -1
  152. package/.output/server/chunks/routes/api/users/setup-status.get.mjs +1 -1
  153. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
  154. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
  155. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
  156. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
  157. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +19 -15
  158. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs.map +1 -1
  159. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
  160. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +1 -1
  161. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
  162. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
  163. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs +54 -0
  164. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/grant.post.mjs.map +1 -0
  165. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs +51 -0
  166. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/revoke.post.mjs.map +1 -0
  167. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
  168. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +1 -1
  169. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  170. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +1 -1
  171. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +1 -1
  172. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
  173. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +1 -1
  174. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id/preview.get.mjs +1 -1
  175. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.delete.mjs +1 -1
  176. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.get.mjs +1 -1
  177. package/.output/server/chunks/routes/api/workshop/aml/datasets/_id_.patch.mjs +1 -1
  178. package/.output/server/chunks/routes/api/workshop/aml/entities/prune.post.mjs +1 -1
  179. package/.output/server/chunks/routes/api/workshop/aml/env/recheck.post.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/aml/env/uv.post.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/aml/env/venv.post.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/aml/index.get.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/aml/index.post.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/aml/index2.post.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/aml/index3.get.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/aml/index3.post.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/aml/index4.get.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/aml/index5.get.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/aml/index6.get.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/aml/index7.get.mjs +1 -1
  191. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/cancel.post.mjs +1 -1
  192. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/logs.get.mjs +1 -1
  193. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id/retry.post.mjs +1 -1
  194. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.delete.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/aml/jobs/_id_.get.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/aml/models/_id/predict.post.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/aml/models/_id/promote.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.delete.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/aml/models/_id_.patch.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id/train.post.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.delete.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/aml/training-plans/_id_.patch.mjs +1 -1
  203. package/.output/server/chunks/routes/api/workshop/aml/twin/providers.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
  205. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +1 -1
  208. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/caller.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +10 -4
  211. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +1 -1
  212. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
  213. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.get.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/channels/_id/chat/index.post.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/channels/_id/index.put.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  226. package/.output/server/chunks/routes/api/workshop/channels/_id/index5.get.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs +37 -0
  228. package/.output/server/chunks/routes/api/workshop/channels/_id/line.put.mjs.map +1 -0
  229. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +1 -1
  230. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.get.mjs +1 -1
  231. package/.output/server/chunks/routes/api/workshop/channels/_id/twin-profile.patch.mjs +1 -1
  232. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +1 -1
  233. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +1 -1
  234. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +4 -4
  235. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +1 -1
  236. package/.output/server/chunks/routes/api/workshop/daq/_id/bindings.put.mjs +1 -1
  237. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +1 -1
  238. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +1 -1
  239. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +1 -1
  240. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +1 -1
  241. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +1 -1
  242. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +1 -1
  243. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +1 -1
  244. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +1 -1
  245. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +1 -1
  246. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +1 -1
  247. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +1 -1
  248. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +1 -1
  249. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +1 -1
  250. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +1 -1
  251. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +1 -1
  252. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +1 -1
  253. package/.output/server/chunks/routes/api/workshop/dcw/_id/bindings.put.mjs +1 -1
  254. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +1 -1
  255. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +1 -1
  256. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +1 -1
  257. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +1 -1
  258. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +1 -1
  259. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +1 -1
  260. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +1 -1
  261. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +1 -1
  262. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +1 -1
  263. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +1 -1
  264. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +1 -1
  265. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +1 -1
  266. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +1 -1
  267. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +1 -1
  268. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +1 -1
  269. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +1 -1
  270. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  271. package/.output/server/chunks/routes/api/workshop/dcw/index6.get.mjs +1 -1
  272. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +1 -1
  273. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +6 -1
  274. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs.map +1 -1
  275. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  276. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  277. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +1 -1
  278. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +1 -1
  279. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +1 -1
  280. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +1 -1
  281. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +1 -1
  282. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +1 -1
  283. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/read.post.mjs +1 -1
  284. package/.output/server/chunks/routes/api/workshop/dcw/params/_id/write.post.mjs +1 -1
  285. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  286. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  287. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +1 -1
  288. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +1 -1
  289. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +1 -1
  290. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +1 -1
  291. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.post.mjs +3 -3
  292. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/revert.post.mjs.map +1 -1
  293. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +1 -1
  294. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/versions.get.mjs +1 -1
  295. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +1 -1
  296. package/.output/server/chunks/routes/api/workshop/dcw/recipes/index.patch.mjs +1 -1
  297. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +1 -1
  298. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +1 -1
  299. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +1 -1
  300. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  301. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  302. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +1 -1
  303. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  304. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  305. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +1 -1
  306. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +1 -1
  307. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +14 -2
  308. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs.map +1 -1
  309. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  310. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  311. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  312. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  313. package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
  314. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  315. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +1 -1
  316. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  317. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +1 -1
  318. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
  319. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +1 -1
  320. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +1 -1
  321. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +1 -1
  322. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +1 -1
  323. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  324. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +1 -1
  325. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  326. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
  327. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
  328. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
  329. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +3 -3
  330. package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
  331. package/.output/server/chunks/routes/api/workshop/index9.post.mjs +1 -1
  332. package/.output/server/chunks/routes/api/workshop/notifications/read.post.mjs +1 -1
  333. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  334. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  335. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  336. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  337. package/.output/server/chunks/routes/api/workshop/schedules/_id/runs.get.mjs +1 -1
  338. package/.output/server/chunks/routes/api/workshop/schedules/_id_.patch.mjs +1 -1
  339. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
  340. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
  341. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
  342. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
  343. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +1 -1
  344. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +1 -1
  345. package/.output/server/chunks/routes/api/workshop/teams/_id/index.put.mjs +1 -1
  346. package/.output/server/chunks/routes/api/workshop/teams/_id/index2.get.mjs +1 -1
  347. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +1 -1
  348. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +4 -1
  349. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs.map +1 -1
  350. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -2
  351. package/.output/server/chunks/routes/renderer.mjs +2 -2
  352. package/.output/server/chunks/virtual/entry.mjs +350 -52
  353. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  354. package/.output/server/package.json +1 -1
  355. package/README-zh.md +7 -3
  356. package/README.md +11 -5
  357. package/app/components/app-header/HitlBell.vue +9 -9
  358. package/app/components/dcw/DcwAddNodeModal.vue +3 -3
  359. package/app/components/dcw/DcwNodesTable.vue +4 -4
  360. package/app/components/dcw/DcwRecipeEditModal.vue +2 -2
  361. package/app/components/workshop/ChatMemberPanel.vue +39 -38
  362. package/app/components/workshop/ChatTimeline.vue +33 -24
  363. package/app/components/workshop/Composer.vue +7 -7
  364. package/app/components/workshop/NotificationCenter.vue +22 -13
  365. package/app/components/workshop/PluginSlot.vue +1 -1
  366. package/app/components/workshop/TaskInspectorDrawer.vue +5 -5
  367. package/app/components/workshop/blocks/ClusterTool.vue +1 -1
  368. package/app/components/workshop/composer/ComposerToolbar.vue +2 -2
  369. package/app/components/workshop/composer/MentionMenu.vue +1 -1
  370. package/app/components/workshop/composer/ReplyChip.vue +2 -2
  371. package/app/components/workshop/composer/StatusChip.vue +7 -7
  372. package/app/components/workshop/console/LineOperationsPanel.vue +15 -14
  373. package/app/components/workshop/lanes/LaneHeader.vue +5 -3
  374. package/app/components/workshop/session-list/ChannelSettingsModal.vue +43 -1
  375. package/app/composables/useCodeCopy.ts +16 -2
  376. package/app/composables/workshop/useWorkshopApi.ts +11 -2
  377. package/app/pages/workshop/channel-templates.vue +43 -4
  378. package/app/stores/workshop/notifications.ts +43 -17
  379. package/config.yml +1 -1
  380. package/docs/cli.en.md +3 -3
  381. package/docs/cli.md +2 -2
  382. package/docs/plugins.en.md +1 -1
  383. package/docs/plugins.md +1 -1
  384. package/docs/sdk.en.md +1 -1
  385. package/docs/sdk.md +1 -1
  386. package/i18n/dicts/_en.json +1551 -1557
  387. package/i18n/dicts/_en2.json +300 -300
  388. package/i18n/dicts/_en4.json +114 -115
  389. package/i18n/dicts/agentLanesView.json +61 -57
  390. package/i18n/dicts/appHeader.json +17 -7
  391. package/i18n/dicts/channelSessionList.json +51 -48
  392. package/i18n/dicts/chat.json +79 -0
  393. package/i18n/dicts/clusterTool.json +4 -3
  394. package/i18n/dicts/composer.json +38 -38
  395. package/i18n/dicts/ctpl.json +37 -32
  396. package/i18n/dicts/dcwDetail.json +219 -209
  397. package/i18n/dicts/lineOps.json +14 -0
  398. package/i18n/dicts/multiChannelView.json +13 -13
  399. package/i18n/dicts/notifications.json +13 -0
  400. package/i18n/dicts/taskInspectorDrawer.json +25 -19
  401. package/i18n/locales/en.ts +157 -8
  402. package/i18n/locales/zh-CN.ts +157 -8
  403. package/package.json +1 -1
  404. package/public/robots.txt +3 -0
  405. package/scripts/_audit/kb-team-mock-e2e.mjs +146 -0
  406. package/scripts/_audit/kb-team-omp-e2e.mjs +229 -0
  407. package/server/api/mcp/workshop.ts +8 -1
  408. package/server/api/metrics.ts +4 -1
  409. package/server/api/plugins/[name]/[...path].ts +4 -3
  410. package/server/api/system/backup/list.get.ts +32 -0
  411. package/server/api/system/backup/run.post.ts +21 -0
  412. package/server/api/system/settings/index.patch.ts +12 -2
  413. package/server/api/system/settings/reset.post.ts +11 -2
  414. package/server/api/users/[id].delete.ts +9 -2
  415. package/server/api/users/[id].put.ts +9 -2
  416. package/server/api/users/index.post.ts +9 -2
  417. package/server/api/users/login.post.ts +3 -3
  418. package/server/api/users/register.post.ts +11 -1
  419. package/server/api/workshop/a2a/[agentId]/rpc/index.post.ts +23 -13
  420. package/server/api/workshop/agent-tools/bindings/grant.post.ts +45 -0
  421. package/server/api/workshop/agent-tools/bindings/revoke.post.ts +42 -0
  422. package/server/api/workshop/channel-templates/[id]/instantiate.post.ts +8 -1
  423. package/server/api/workshop/channels/[id]/line.put.ts +30 -0
  424. package/server/api/workshop/dcw/line/query.get.ts +6 -0
  425. package/server/api/workshop/dcw/recipes/[id]/revert.post.ts +3 -2
  426. package/server/api/workshop/fs/dirs.get.ts +19 -1
  427. package/server/api/workshop/ops-logs/index.get.ts +3 -2
  428. package/server/api/workshop/users/register.post.ts +7 -0
  429. package/server/mcp/workshop-server.ts +36 -13
  430. package/server/middleware/00-security-headers.ts +38 -0
  431. package/server/middleware/01-rate-guard.ts +101 -0
  432. package/server/plugins/backup.ts +56 -1
  433. package/server/plugins-builtin/diag-bridge/host/plugin.mjs +18 -11
  434. package/server/repositories/user.repository.ts +10 -5
  435. package/server/services/user.service.ts +24 -1
  436. package/server/services/workshop/agents/host-tool-bridge/dispatch.ts +7 -2
  437. package/server/services/workshop/agents/host-tool-bridge/tools/industrial.ts +4 -2
  438. package/server/services/workshop/agents/host-tool-bridge/tools/tasks.ts +15 -2
  439. package/server/services/workshop/agents/host-tool-bridge/tools/team-delegation.ts +104 -0
  440. package/server/services/workshop/agents/industrial/index.ts +1 -1
  441. package/server/services/workshop/agents/industrial/ops-tools.ts +168 -26
  442. package/server/services/workshop/agents/node-bindings.repo.ts +10 -1
  443. package/server/services/workshop/agents/node-delegation.ts +150 -0
  444. package/server/services/workshop/agents/tool-classes.ts +4 -0
  445. package/server/services/workshop/aml/dataset-builder.ts +4 -2
  446. package/server/services/workshop/aml/job-orchestrator/process.ts +1 -0
  447. package/server/services/workshop/aml/job-orchestrator/shared.ts +2 -0
  448. package/server/services/workshop/aml/job-orchestrator/start-job.ts +5 -2
  449. package/server/services/workshop/db/channel.repo.ts +11 -1
  450. package/server/services/workshop/db/database/migrations.ts +2 -0
  451. package/server/services/workshop/db/database/rows.ts +2 -0
  452. package/server/services/workshop/db/database/seed.ts +30 -0
  453. package/server/services/workshop/dcw/dcw-controller/recipes.ts +60 -4
  454. package/server/services/workshop/dcw/dcw-controller/write.ts +35 -6
  455. package/server/services/workshop/dcw/dcw-recipe.repo.ts +4 -3
  456. package/server/services/workshop/dcw/param-map.repo.ts +3 -0
  457. package/server/services/workshop/plugins/host/init.mjs +9 -1
  458. package/server/services/workshop/plugins/host/load.mjs +2 -2
  459. package/server/services/workshop/runtime/manager/admin-channel.ts +27 -1
  460. package/server/services/workshop/runtime/manager/channel-templates.ts +27 -2
  461. package/server/services/workshop/runtime/manager/runtime-wiring.ts +17 -1
  462. package/server/services/workshop/runtime/manager/types.ts +2 -0
  463. package/shared/config/schema.json +2 -0
  464. package/.output/public/_nuxt/8FXd9As6.js +0 -1
  465. package/.output/public/_nuxt/BOmDHp5L.js +0 -14
  466. package/.output/public/_nuxt/BWU1pvLL.js +0 -1
  467. package/.output/public/_nuxt/CdIsmU5a2.js +0 -21
  468. package/.output/public/_nuxt/D0SNhlnt.js +0 -1
  469. package/.output/public/_nuxt/DnH9SRMW2.js +0 -1
  470. package/.output/public/_nuxt/ON2x-t6n.js +0 -1
  471. package/.output/public/_nuxt/PluginSlot.DmjNbrcX.css +0 -1
  472. package/.output/public/_nuxt/_wsId_.DkrQkT6r.css +0 -1
  473. package/.output/public/_nuxt/builds/meta/912eb5bb-670e-4cc8-b21d-7fc097723466.json +0 -1
  474. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +0 -1
  475. package/.output/server/chunks/build/_id_-BUpQSlzo.mjs.map +0 -1
  476. package/.output/server/chunks/build/channel-templates-DjEsj0_v.mjs.map +0 -1
  477. package/.output/server/chunks/build/useWorkshopApi-B1B9vd4m.mjs.map +0 -1
  478. package/scripts/.chk-tok +0 -1
  479. package/scripts/.retrain-body.json +0 -1
  480. package/scripts/.retrain3-body.json +0 -1
  481. package/scripts/.rt-tok +0 -1
  482. package/scripts/.rt3-tok +0 -1
@@ -1,11 +1,21 @@
1
1
  import { readValidatedBody } from 'h3'
2
2
  import { userRegisterSchema, type UserRegister } from '../../schemas/user.schema'
3
3
  import { userService } from '../../services/user.service'
4
+ import { userRepository } from '../../repositories/user.repository'
5
+ import { settingOf } from '../../services/workshop/settings'
6
+ import { AppError } from '../../utils/errors'
4
7
  import { defineApiHandler } from '../../utils/response'
5
8
  import { zValidator } from '../../utils/validate'
6
9
 
7
- /** POST /api/users/register —— 公开注册(name + email + password),签发首个 token */
10
+ /**
11
+ * POST /api/users/register —— 公开注册(name + email + password),签发首个 token。
12
+ * 公网部署闸门:security.allowRegistration=false 且首管理员已就位时关闭自助注册
13
+ * (首 admin 引导不受此门限制;默认 true 保持"用户可自助注册"的产品语义)。
14
+ */
8
15
  export default defineApiHandler(async (event) => {
16
+ if (settingOf('security.allowRegistration') === false && userRepository.hasActiveAdmin()) {
17
+ throw new AppError(403, 'REGISTRATION_CLOSED', '自助注册已关闭(security.allowRegistration=false),请联系管理员开通账号')
18
+ }
9
19
  const body = await readValidatedBody(event, zValidator(userRegisterSchema)) as UserRegister
10
20
  return userService.register(body)
11
21
  })
@@ -246,7 +246,7 @@ function bearerTokenOf(event: H3Event): string | undefined {
246
246
  return match?.[1]?.trim()
247
247
  }
248
248
 
249
- /** 取消任务:优先 token 关联 agent;无 caller 时以任务所在 channel 的 lead 作为系统身份 */
249
+ /** 取消任务:一律以 Bearer token 关联的 agent 身份(无 token 一律 401,不再以 lead 系统身份回退) */
250
250
  async function cancelTaskWithCaller(
251
251
  manager: AgentChannelManager,
252
252
  event: H3Event,
@@ -254,13 +254,23 @@ async function cancelTaskWithCaller(
254
254
  ): Promise<WorkspaceTask> {
255
255
  const token = bearerTokenOf(event)
256
256
  const caller = token ? manager.findByToken(token) : undefined
257
- if (caller) return manager.cancelTask(caller.channelId, caller.id, { taskId })
258
- const task = internalsOf(manager).getTaskEngine().get(taskId)
259
- if (!task) throw new AppError(404, 'NOT_FOUND', `任务不存在: ${taskId}`)
260
- const agents = await manager.listChannelAgents(task.channelId)
261
- const lead = agents.find(a => a.role === 'lead')
262
- if (!lead) throw new AppError(400, 'NO_LEAD_AGENT', `channel ${task.channelId} 无 lead,无法以系统身份取消`)
263
- return manager.cancelTask(lead.channelId, lead.id, { taskId })
257
+ if (!caller) throw new AppError(401, 'UNAUTHORIZED', 'tasks/cancel 需要有效 Agent token(Authorization: Bearer)')
258
+ return manager.cancelTask(caller.channelId, caller.id, { taskId })
259
+ }
260
+
261
+ /**
262
+ * A2A 统一身份门:Bearer token 必须有效,且 URL agent 与 caller 同 channel
263
+ * (编排器以自己 token 调同 channel 其他 agent 的端点是合法流;跨 channel/匿名一律拒绝)。
264
+ * 返回 URL 指向的目标 agent(作用域身份)。
265
+ */
266
+ function requireA2ACaller(manager: AgentChannelManager, event: H3Event, agentId: string): AgentInfo {
267
+ const token = bearerTokenOf(event)
268
+ const caller = token ? manager.findByToken(token) : undefined
269
+ if (!caller) throw new AppError(401, 'UNAUTHORIZED', 'A2A 调用需要有效 Agent token(Authorization: Bearer)')
270
+ const target = findAgent(manager, agentId)
271
+ if (!target) throw new AppError(404, 'NOT_FOUND', `Agent not found: ${agentId}`)
272
+ if (target.channelId !== caller.channelId) throw new AppError(403, 'FORBIDDEN', 'A2A 目标 agent 与 token 身份不在同一 channel')
273
+ return target
264
274
  }
265
275
 
266
276
  // ===== SSE(tasks/sendSubscribe) =====
@@ -342,35 +352,35 @@ async function dispatch(
342
352
  ): Promise<unknown> {
343
353
  switch (method) {
344
354
  case 'tasks/send': {
355
+ const agent = requireA2ACaller(manager, event, agentId)
345
356
  const p = parseParams(sendParamsSchema, params)
346
- const agent = findAgent(manager, agentId) ?? fail(-32001, `Agent not found: ${agentId}`)
347
357
  const task = await submitTask(manager, agent, p)
348
358
  const final = await waitTerminal(manager, task.id)
349
359
  return ok(id, toA2ATask(final))
350
360
  }
351
361
  case 'tasks/sendSubscribe': {
362
+ const agent = requireA2ACaller(manager, event, agentId)
352
363
  const p = parseParams(sendParamsSchema, params)
353
- const agent = findAgent(manager, agentId) ?? fail(-32001, `Agent not found: ${agentId}`)
354
364
  const stream = createEventStream(event)
355
365
  void runSubscribe(stream, manager, agent, p)
356
366
  // h3 EventStream 必须经 send() 激活(否则被当普通对象 JSON 序列化,SSE 从未生效)
357
367
  return stream.send()
358
368
  }
359
369
  case 'tasks/get': {
370
+ const agent = requireA2ACaller(manager, event, agentId)
360
371
  const p = parseParams(taskIdParamsSchema, params)
361
- const agent = findAgent(manager, agentId) ?? fail(-32001, `Agent not found: ${agentId}`)
362
372
  const task = await manager.getTask(agent.channelId, agent.id, p.taskId)
363
373
  return ok(id, toA2ATask(task))
364
374
  }
365
375
  case 'tasks/list': {
376
+ const agent = requireA2ACaller(manager, event, agentId)
366
377
  parseParams(noopParamsSchema, params)
367
- const agent = findAgent(manager, agentId) ?? fail(-32001, `Agent not found: ${agentId}`)
368
378
  const tasks = await manager.listTasks(agent.channelId, agent.id)
369
379
  return ok(id, tasks.map(toA2ATask))
370
380
  }
371
381
  case 'tasks/cancel': {
372
382
  const p = parseParams(taskIdParamsSchema, params)
373
- if (!findAgent(manager, agentId)) fail(-32001, `Agent not found: ${agentId}`)
383
+ requireA2ACaller(manager, event, agentId)
374
384
  const canceled = await cancelTaskWithCaller(manager, event, p.taskId)
375
385
  return ok(id, toA2ATask(canceled))
376
386
  }
@@ -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,9 @@ 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(),
27
+ /** v18:实例化即绑定产线(只读扩权:成员可读该线日志/配方/历史/状态;写仍走节点授权) */
28
+ bindLineId: z.string().min(1).optional(),
26
29
  })
27
30
 
28
31
  export default defineApiHandler(async (event) => {
@@ -30,11 +33,15 @@ export default defineApiHandler(async (event) => {
30
33
  const user = resolveUser(event)
31
34
  const body = await readValidatedBody(event, zValidator(instantiateSchema))
32
35
  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 })
36
+ 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
37
  // 模板含 lead 时直接启动调度循环(可提交任务)
35
38
  if (result.leadAgentId) {
36
39
  ensureLeadSchedulerLoop(manager, result.channelId)
37
40
  }
41
+ // v18:实例化即绑定产线(新频道 owner = 实例化者;产线存在性在 bindChannelLine 内校验)
42
+ if (body.bindLineId) {
43
+ await manager.bindChannelLine(result.channelId, body.bindLineId)
44
+ }
38
45
  // 常驻事件录制器(与 channels.post 同口径):确保无人 WS 订阅前事件也已持久化
39
46
  const { ensureStream } = await import('../../ws')
40
47
  ensureStream(manager, result.channelId)
@@ -0,0 +1,30 @@
1
+ /**
2
+ * PUT /api/workshop/channels/:id/line —— 绑定/解绑产线(v18)。
3
+ * body: { "lineId": "<产线id>" | null } (null/缺省 = 解绑)
4
+ *
5
+ * 只读扩权语义:绑定后频道成员无需节点绑定即可读取该产线的运维日志(ops_log)、
6
+ * 配方变更史(recipe_log/recipe_versions)与实时全景(line_context:运行状态/活动
7
+ * 批次/当前配方);参数下发等写操作仍必须走节点授权,不受绑定影响。
8
+ * 权限:channel owner / admin(与 PATCH channel 同一守卫)。
9
+ * 绑定变更回收成员运行时,下次装配注入产线简报(与场景 prompt 变更同链路)。
10
+ */
11
+ import { z } from 'zod'
12
+ import { getRouterParam, readValidatedBody } from 'h3'
13
+ import { resolveUser } from '../../caller'
14
+ import { zValidator } from '../../../../utils/validate'
15
+ import { defineApiHandler } from '../../../../utils/response'
16
+ import { getWorkshopManager } from '../../../../plugins/workshop'
17
+
18
+ const bindLineSchema = z.object({
19
+ lineId: z.string().trim().nullable().optional(),
20
+ })
21
+
22
+ export default defineApiHandler(async (event) => {
23
+ const channelId = getRouterParam(event, 'id')!
24
+ const user = resolveUser(event)
25
+ const body = await readValidatedBody(event, zValidator(bindLineSchema))
26
+ const manager = getWorkshopManager()
27
+ manager.requireChannelOwner(channelId, user, 'channel')
28
+ const channel = await manager.bindChannelLine(channelId, body.lineId ?? '')
29
+ return { ok: true, lineId: channel.lineId, channel }
30
+ })
@@ -23,6 +23,12 @@ export default defineApiHandler(async (event) => {
23
23
  const n = Number(v)
24
24
  return v != null && v !== '' && Number.isFinite(n) ? n : undefined
25
25
  }
26
+ // 边界健壮性:超大有限数/负数会打穿下游(SQLite OFFSET/负 LIMIT 等)→ 500;在门口校验成 400
27
+ for (const [k, v] of [['from', num(q.from)], ['to', num(q.to)], ['bucketMs', num(q.bucketMs)], ['limit', num(q.limit)]] as const) {
28
+ if (v !== undefined && (!Number.isSafeInteger(v) || v < 0)) {
29
+ throw new AppError(400, 'VALIDATION_ERROR', `查询参数 ${k} 必须为非负安全整数`)
30
+ }
31
+ }
26
32
  const result = await getDcwController().lineQuery({
27
33
  lineId: q.lineId ? String(q.lineId) : undefined,
28
34
  productId: q.productId ? String(q.productId) : undefined,
@@ -3,13 +3,14 @@
3
3
  * 生成新版本(非破坏;历史完整保留)。body: { version?: number, toLastGood?: boolean, reason: string }。
4
4
  */
5
5
  import { getRouterParam, readBody } from 'h3'
6
- import { resolveUser } from '@/server/api/workshop/caller'
6
+ import { requireRole } from '@/server/api/workshop/caller'
7
7
  import { defineApiHandler } from '@/server/utils/response'
8
8
  import { getDcwController } from '@/server/services/workshop/dcw/dcw-controller'
9
9
  import { AppError, ErrorCodes } from '@/server/utils/errors'
10
10
 
11
11
  export default defineApiHandler(async (event) => {
12
- const user = resolveUser(event)
12
+ // 与 apply/rollback-good 同一角色门:配方回退是产线写操作,admin/editor 专属
13
+ const user = requireRole(event)
13
14
  const id = getRouterParam(event, 'id') ?? ''
14
15
  const body = await readBody<{ version?: number, toLastGood?: boolean, reason?: string }> (event) ?? {}
15
16
  if (!body.toLastGood && body.version == null) {
@@ -10,12 +10,25 @@ import { getQuery } from 'h3'
10
10
  import { resolveUser } from '../caller'
11
11
  import { AppError } from '../../../utils/errors'
12
12
  import { defineApiHandler } from '../../../utils/response'
13
+ import { resolveRunMode } from '@/shared/config/home.mjs'
14
+ import { isPathInside } from '@/sdk/index.mjs'
15
+
16
+ /** 允许浏览的根:项目检出根 + 生效配置根 + 数据目录(文件选择器只服务这些工作区) */
17
+ function allowedRoots(): string[] {
18
+ const rm = resolveRunMode({ cwd: process.cwd(), env: process.env })
19
+ return [...new Set([process.cwd(), rm.configRoot, rm.dataDir].map(r => resolve(r)))]
20
+ }
13
21
 
14
22
  export default defineApiHandler(async (event) => {
15
23
  resolveUser(event)
16
24
  const q = getQuery(event)
17
25
  const raw = typeof q.path === 'string' ? q.path.trim() : ''
18
26
  const cwd = raw ? resolve(raw) : process.cwd()
27
+ const roots = allowedRoots()
28
+ // 越权防护:任意绝对路径列举整盘目录是公网部署下的信息泄露面,锁定到工作区白名单根内
29
+ if (!roots.some(r => cwd === r || isPathInside(r, cwd))) {
30
+ throw new AppError(403, 'FS_OUT_OF_ROOT', 'path 必须位于项目根或配置根内')
31
+ }
19
32
  let entries: import('node:fs').Dirent[]
20
33
  try {
21
34
  entries = readdirSync(cwd, { withFileTypes: true })
@@ -35,6 +48,11 @@ export default defineApiHandler(async (event) => {
35
48
  return { name: e.name, path: full, hasChildren }
36
49
  })
37
50
  .sort((a, b) => a.name.localeCompare(b.name))
38
- const parent = dirname(cwd) !== cwd ? dirname(cwd) : null
51
+ // parent 链同样不许逃出白名单根(到根即断,防止逐级上探)
52
+ const parent = (() => {
53
+ const up = dirname(cwd)
54
+ if (up === cwd) return null
55
+ return roots.some(r => up === r || isPathInside(r, up)) ? up : null
56
+ })()
39
57
  return { cwd, parent, isAbsoluteRoot: !isAbsolute(cwd), dirs }
40
58
  })
@@ -4,13 +4,14 @@
4
4
  * 返回 { logs: [...], count }。行结构 = audit_log 投影(id/actor/actorKind/kind/summary/detailJson…)。
5
5
  */
6
6
  import { getQuery } from 'h3'
7
- import { resolveUser } from '@/server/api/workshop/caller'
7
+ import { requireRole } from '@/server/api/workshop/caller'
8
8
  import { defineApiHandler } from '@/server/utils/response'
9
9
  import { getOps } from '../../../services/workshop/ops/ops'
10
10
  import { AppError } from '../../../utils/errors'
11
11
 
12
12
  export default defineApiHandler(async (event) => {
13
- resolveUser(event)
13
+ // 全局审计台账含跨产线运维信息,收权到 admin/editor(普通用户走产线维度自己的记录)
14
+ requireRole(event)
14
15
  const repo = getOps()?.audit
15
16
  if (!repo)
16
17
  throw new AppError(503, 'UNAVAILABLE', '运维日志仓储未就绪')
@@ -10,12 +10,19 @@ import { readValidatedBody } from 'h3'
10
10
  import { zValidator } from '../../../utils/validate'
11
11
  import { defineApiHandler } from '../../../utils/response'
12
12
  import { userService } from '../../../services/user.service'
13
+ import { userRepository } from '../../../repositories/user.repository'
14
+ import { settingOf } from '../../../services/workshop/settings'
15
+ import { AppError } from '../../../utils/errors'
13
16
 
14
17
  const schema = z.object({
15
18
  name: z.string().trim().min(1, 'name 必填').max(64, 'name 过长'),
16
19
  })
17
20
 
18
21
  export default defineApiHandler(async (event) => {
22
+ // 公网部署闸门:与 /api/users/register 同一开关(首 admin 未就位时不受限)
23
+ if (settingOf('security.allowRegistration') === false && userRepository.hasActiveAdmin()) {
24
+ throw new AppError(403, 'REGISTRATION_CLOSED', '自助注册已关闭(security.allowRegistration=false),请联系管理员开通账号')
25
+ }
19
26
  const body = await readValidatedBody(event, zValidator(schema))
20
27
  const name = body.name.trim()
21
28
  const email = `${name.toLowerCase().replace(/[^a-z0-9]+/g, '-')}-${Date.now()}@workshop.local`
@@ -112,7 +112,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
112
112
  .optional(),
113
113
  },
114
114
  },
115
- async (args) => {
115
+ async (args, extra) => {
116
+ requireCaller(manager, extra)
116
117
  const result = await manager.createChannel({
117
118
  name: args.name,
118
119
  description: args.description,
@@ -128,8 +129,11 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
128
129
  description: '全部 channel',
129
130
  inputSchema: {},
130
131
  },
131
- async () => {
132
- return jsonResult(await manager.listChannels())
132
+ async (_args, extra) => {
133
+ const caller = requireCaller(manager, extra)
134
+ // 隔离:Agent 只能看到自己所在 channel(与 workshop.agent.list 同哲学)
135
+ const all = await manager.listChannels()
136
+ return jsonResult(all.filter(c => c.id === caller.channelId))
133
137
  },
134
138
  )
135
139
 
@@ -139,7 +143,9 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
139
143
  description: '删除(级联)',
140
144
  inputSchema: { channelId: z.string() },
141
145
  },
142
- async (args) => {
146
+ async (args, extra) => {
147
+ const caller = requireCaller(manager, extra)
148
+ if (args.channelId !== caller.channelId) throw new Error('FORBIDDEN: 只能删除自己所在 channel')
143
149
  await manager.removeChannel(args.channelId)
144
150
  return jsonResult({ ok: true })
145
151
  },
@@ -157,7 +163,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
157
163
  config: z.record(z.string(), z.unknown()).optional(),
158
164
  },
159
165
  },
160
- async (args) => {
166
+ async (args, extra) => {
167
+ requireCaller(manager, extra)
161
168
  const result = await manager.createAgent({
162
169
  name: args.name,
163
170
  harness: args.harness,
@@ -177,7 +184,9 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
177
184
  role: z.enum(['lead', 'worker']),
178
185
  },
179
186
  },
180
- async (args) => {
187
+ async (args, extra) => {
188
+ const caller = requireCaller(manager, extra)
189
+ if (args.channelId !== caller.channelId) throw new Error('FORBIDDEN: 只能向自己所在 channel 添加 Agent')
181
190
  const result = await manager.addAgentToChannel({
182
191
  channelId: args.channelId,
183
192
  agentId: args.agentId,
@@ -193,7 +202,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
193
202
  description: '列出全部 Agent 模板(全局可复用)',
194
203
  inputSchema: {},
195
204
  },
196
- async () => {
205
+ async (_args, extra) => {
206
+ requireCaller(manager, extra)
197
207
  return jsonResult(await manager.listAgents())
198
208
  },
199
209
  )
@@ -216,7 +226,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
216
226
  description: '删除 Agent 模板(已克隆实例保留)',
217
227
  inputSchema: { agentId: z.string() },
218
228
  },
219
- async (args) => {
229
+ async (args, extra) => {
230
+ requireCaller(manager, extra)
220
231
  await manager.removeAgent(args.agentId)
221
232
  return jsonResult({ ok: true })
222
233
  },
@@ -235,7 +246,9 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
235
246
  parts: z.array(partSchema).optional(),
236
247
  },
237
248
  },
238
- async (args) => {
249
+ async (args, extra) => {
250
+ const caller = requireCaller(manager, extra)
251
+ if (args.channelId !== caller.channelId) throw new Error('FORBIDDEN: 只能向自己所在 channel 提交任务')
239
252
  const result = await manager.submitChannelTask({
240
253
  channelId: args.channelId,
241
254
  title: args.title,
@@ -441,7 +454,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
441
454
  description: '列出数字孪生设备(含 telemetry/state/desired)。Agent 据此判断哪些设备可控、当前状态如何。',
442
455
  inputSchema: { workspaceId: z.string().optional() },
443
456
  },
444
- async (args) => {
457
+ async (args, extra) => {
458
+ requireCaller(manager, extra)
445
459
  return jsonResult(getDeviceTwinRepo().listAll(args.workspaceId))
446
460
  },
447
461
  )
@@ -452,7 +466,8 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
452
466
  description: '读取单个设备实时遥测 + 运行状态 + 可用指令集。数字人作业前先 read 感知设备当前情况。',
453
467
  inputSchema: { deviceId: z.string() },
454
468
  },
455
- async (args) => {
469
+ async (args, extra) => {
470
+ requireCaller(manager, extra)
456
471
  const twin = getDeviceTwinRepo().findById(args.deviceId)
457
472
  if (!twin) throw new Error(`NOT_FOUND: 设备不存在 ${args.deviceId}`)
458
473
  return jsonResult(twin)
@@ -469,7 +484,11 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
469
484
  args: z.record(z.string(), z.unknown()).optional(),
470
485
  },
471
486
  },
472
- async (args) => {
487
+ async (args, extra) => {
488
+ const caller = requireCaller(manager, extra)
489
+ const bound = getDeviceTwinRepo().findById(args.deviceId)
490
+ if (!bound) throw new Error(`NOT_FOUND: 设备不存在 ${args.deviceId}`)
491
+ if (bound.boundAgentId && bound.boundAgentId !== caller.id) throw new Error('FORBIDDEN: 设备已被其他 Agent 绑定')
473
492
  const twin = getDeviceTwinRepo().applyControl(args.deviceId, args.command, args.args ?? {})
474
493
  if (!twin) throw new Error(`NOT_FOUND: 设备不存在 ${args.deviceId}`)
475
494
  return jsonResult(twin)
@@ -485,7 +504,11 @@ export function createWorkshopMcpServer(manager: AgentChannelManager): McpServer
485
504
  telemetry: z.record(z.string(), z.union([z.number(), z.string(), z.boolean()])),
486
505
  },
487
506
  },
488
- async (args) => {
507
+ async (args, extra) => {
508
+ const caller = requireCaller(manager, extra)
509
+ const bound = getDeviceTwinRepo().findById(args.deviceId)
510
+ if (!bound) throw new Error(`NOT_FOUND: 设备不存在 ${args.deviceId}`)
511
+ if (bound.boundAgentId && bound.boundAgentId !== caller.id) throw new Error('FORBIDDEN: 设备已被其他 Agent 绑定')
489
512
  const twin = getDeviceTwinRepo().applyTelemetry(args.deviceId, args.telemetry)
490
513
  if (!twin) throw new Error(`NOT_FOUND: 设备不存在 ${args.deviceId}`)
491
514
  return jsonResult({ state: twin.state, telemetry: twin.telemetry })
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 安全响应头(公网部署基线)—— 全站统一附加:
3
+ * - X-Content-Type-Options / X-Frame-Options / Referrer-Policy / Permissions-Policy
4
+ * - CSP:自托管 SPA 语义('self' + inline 样式/脚本;Nuxt 水合与 antd cssinjs 需要 inline)
5
+ * - HSTS:security.hstsEnabled 设置开启才下发(前提=已上 TLS,反代/隧道终结亦可)
6
+ * 纯 setHeader,不读 body、不阻塞;设置读取走 3s TTL 缓存(settingOf)。
7
+ */
8
+ import { defineEventHandler, getRequestURL, setResponseHeader } from 'h3'
9
+ import { settingOf } from '../services/workshop/settings'
10
+
11
+ const CSP = [
12
+ 'default-src \'self\'',
13
+ 'script-src \'self\' \'unsafe-inline\' \'unsafe-eval\'',
14
+ 'style-src \'self\' \'unsafe-inline\'',
15
+ 'img-src \'self\' data: blob: https:',
16
+ 'font-src \'self\' data:',
17
+ 'connect-src \'self\' ws: wss:',
18
+ 'media-src \'self\' blob:',
19
+ 'object-src \'none\'',
20
+ 'base-uri \'self\'',
21
+ 'frame-ancestors \'none\'',
22
+ 'form-action \'self\'',
23
+ ].join('; ')
24
+
25
+ export default defineEventHandler((event) => {
26
+ if (!event.node?.res) return
27
+ setResponseHeader(event, 'X-Content-Type-Options', 'nosniff')
28
+ setResponseHeader(event, 'X-Frame-Options', 'DENY')
29
+ setResponseHeader(event, 'Referrer-Policy', 'strict-origin-when-cross-origin')
30
+ setResponseHeader(event, 'Permissions-Policy', 'camera=(), microphone=(), geolocation=(), payment=()')
31
+ setResponseHeader(event, 'Content-Security-Policy', CSP)
32
+ const url = getRequestURL(event)
33
+ if (url.pathname.startsWith('/api/')) setResponseHeader(event, 'Cache-Control', 'no-store')
34
+ // HSTS 只在设置开启时下发(未上 TLS 时下发会锁死 http 访问)
35
+ if (settingOf('security.hstsEnabled') === true) {
36
+ setResponseHeader(event, 'Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
37
+ }
38
+ })
@@ -0,0 +1,101 @@
1
+ /**
2
+ * HTTP 防护门(公网部署基线)——单中间件四件事,内存滑窗,无外部依赖:
3
+ * 1. User-Agent 黑名单:默认拦常见扫描器(sqlmap/nikto/nuclei…),AW_UA_BLOCKLIST 可追加(正则段,| 分隔)
4
+ * 2. 请求体上限:Content-Length 超限 413(AW_BODY_LIMIT_MB,默认 64MB)
5
+ * 3. 频率限流:/api 认证面(login/register/mcp/a2a)严限,A其余 API 宽限(AW_RATE_LIMIT_API_PER_MIN,默认 600)
6
+ * 4. 404 扫描封锁:1 分钟内 /api/* 404 超过阈值(AW_SCAN_404_LIMIT,默认 60)→ 封 IP 10 分钟(反爬/反目录爆破)
7
+ * 旁路:AW_RATE_LIMIT_OFF=1 或 AW_BENCH_MODE=1(基准隔离实例)整体停用;
8
+ * 全部状态内存态(重启即清),多实例部署时反代层应另配限流。
9
+ */
10
+ import { defineEventHandler, createError, getRequestIP, getRequestHeaders, getRequestURL } from 'h3'
11
+
12
+ const g = globalThis as typeof globalThis & {
13
+ __awRateBuckets?: Map<string, { count: number, reset: number }>
14
+ __awScanHits?: Map<string, { count: number, reset: number }>
15
+ __awScanBlocked?: Map<string, number>
16
+ }
17
+
18
+ const envNum = (v: string | undefined, dflt: number) => {
19
+ const n = Number(v)
20
+ return Number.isFinite(n) && n > 0 ? n : dflt
21
+ }
22
+
23
+ const OFF = process.env.AW_RATE_LIMIT_OFF === '1' || process.env.AW_BENCH_MODE === '1'
24
+ const AUTH_LIMIT = envNum(process.env.AW_RATE_LIMIT_AUTH_PER_MIN, 20)
25
+ const API_LIMIT = envNum(process.env.AW_RATE_LIMIT_API_PER_MIN, 600)
26
+ const SCAN_LIMIT = envNum(process.env.AW_SCAN_404_LIMIT, 60)
27
+ const BODY_LIMIT_MB = envNum(process.env.AW_BODY_LIMIT_MB, 64)
28
+ const BLOCK_MS = 10 * 60_000
29
+ const WINDOW_MS = 60_000
30
+ // 默认 UA 黑名单:公认攻击工具,不含任何浏览器/爬虫正常名(正常搜索引擎爬虫由 robots.txt 约束)
31
+ const UA_RE = new RegExp(process.env.AW_UA_BLOCKLIST
32
+ || 'sqlmap|nikto|nuclei|masscan|zgrab|dirbuster|gobuster|wfuzz|ffuf|hydra|acunetix|nessus|arachni', 'i')
33
+
34
+ /** 认证/敏感面(严限):登录、注册、MCP、A2A */
35
+ function isAuthFace(pathname: string): boolean {
36
+ return pathname.startsWith('/api/users/login')
37
+ || pathname.startsWith('/api/users/register')
38
+ || pathname.startsWith('/api/workshop/users/register')
39
+ || pathname.startsWith('/api/mcp/')
40
+ || pathname.includes('/a2a/')
41
+ }
42
+
43
+ function bucketOf(map: Map<string, { count: number, reset: number }>, key: string, limit: number, now: number): number {
44
+ const b = map.get(key)
45
+ if (!b || b.reset <= now) {
46
+ map.set(key, { count: 1, reset: now + WINDOW_MS })
47
+ return limit - 1
48
+ }
49
+ b.count += 1
50
+ // 可为负:第 N+1 发起 remaining < 0,由调用方判 429(勿钳 0,否则永不触发)
51
+ return limit - b.count
52
+ }
53
+
54
+ export default defineEventHandler((event) => {
55
+ if (OFF) return
56
+ const url = getRequestURL(event)
57
+ const path = url.pathname
58
+ const ip = getRequestIP(event, { xForwardedFor: true }) ?? 'local'
59
+ const now = Date.now()
60
+
61
+ // 已封锁 IP(404 扫描触发):直接 403,不看别的
62
+ const blockedUntil = g.__awScanBlocked?.get(ip)
63
+ if (blockedUntil && blockedUntil > now) {
64
+ throw createError({ statusCode: 403, statusMessage: `IP temporarily blocked (scanning): retry after ${Math.ceil((blockedUntil - now) / 1000)}s` })
65
+ }
66
+ if (blockedUntil && g.__awScanBlocked) g.__awScanBlocked.delete(ip)
67
+
68
+ // UA 黑名单(全路径,扫描器对静态面也探)
69
+ const ua = getRequestHeaders(event)['user-agent'] ?? ''
70
+ if (ua && UA_RE.test(ua)) {
71
+ throw createError({ statusCode: 403, statusMessage: 'User agent not allowed' })
72
+ }
73
+
74
+ // 请求体上限(带 Content-Length 才拦;chunked 走 nitro 默认)
75
+ const len = Number(getRequestHeaders(event)['content-length'] ?? 0)
76
+ if (len > BODY_LIMIT_MB * 1024 * 1024) {
77
+ throw createError({ statusCode: 413, statusMessage: `Request body too large (limit ${BODY_LIMIT_MB}MB)` })
78
+ }
79
+
80
+ // 只对 /api/* 限流(静态/页面不做)
81
+ if (path.startsWith('/api/')) {
82
+ if (!g.__awRateBuckets) g.__awRateBuckets = new Map()
83
+ const limit = isAuthFace(path) ? AUTH_LIMIT : API_LIMIT
84
+ const remaining = bucketOf(g.__awRateBuckets, `${ip}|${limit}`, limit, now)
85
+ if (remaining < 0) {
86
+ throw createError({ statusCode: 429, statusMessage: 'Too many requests: slow down' })
87
+ }
88
+ // 404 扫描计数(res finish 时回填;blocked 判定在下轮请求入口生效)
89
+ if (!g.__awScanHits) g.__awScanHits = new Map()
90
+ const res = event.node?.res
91
+ if (!res) return
92
+ res.once('finish', () => {
93
+ if (res.statusCode !== 404) return
94
+ const hits = bucketOf(g.__awScanHits!, `${ip}`, SCAN_LIMIT, Date.now())
95
+ if (hits <= 0) {
96
+ if (!g.__awScanBlocked) g.__awScanBlocked = new Map()
97
+ g.__awScanBlocked.set(ip, Date.now() + BLOCK_MS)
98
+ }
99
+ })
100
+ }
101
+ })