agentworkshop 0.5.9 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (572) hide show
  1. package/.AgentWorkShop/prompts/compaction-hints.md +9 -9
  2. package/.AgentWorkShop/prompts/host-tools.json +42 -0
  3. package/.output/.AgentWorkShop/prompts/compaction-hints.md +9 -9
  4. package/.output/.AgentWorkShop/prompts/host-tools.json +42 -0
  5. package/.output/nitro.json +1 -1
  6. package/.output/public/_nuxt/{Dm5mD6XT.js → BD9D9pl4.js} +1 -1
  7. package/.output/public/_nuxt/{BdKzfJiM.js → BxD8Fg_Z.js} +1 -1
  8. package/.output/public/_nuxt/{dRAyjbJ6.js → C-Y5ydB6.js} +3 -3
  9. package/.output/public/_nuxt/{Bok1DRqh.js → C0FogB-p.js} +1 -1
  10. package/.output/public/_nuxt/{BUNGEK2z.js → C2QSTAWf.js} +1 -1
  11. package/.output/public/_nuxt/{CWDzKGtj.js → CclO6GyL.js} +1 -1
  12. package/.output/public/_nuxt/{B3__nfxM.js → Ck6tznoQ.js} +1 -1
  13. package/.output/public/_nuxt/CwS_UHeH.js +1 -0
  14. package/.output/public/_nuxt/{CE2ynNi9.js → CwcOEM8m.js} +1 -1
  15. package/.output/public/_nuxt/MhK4buEJ.js +1 -0
  16. package/.output/public/_nuxt/_id_.DN3U6EF9.css +1 -0
  17. package/.output/public/_nuxt/builds/latest.json +1 -1
  18. package/.output/public/_nuxt/builds/meta/221de779-a113-4232-b9a1-31a614f5e3c7.json +1 -0
  19. package/.output/public/_nuxt/{entry.DjhxLu-f.css → entry.DvlXlPwx.css} +1 -1
  20. package/.output/public/_nuxt/settings.BG0K9_MG.css +1 -0
  21. package/.output/server/chunks/_/error-500.mjs.map +1 -1
  22. package/.output/server/chunks/_/nitro.mjs +2675 -1425
  23. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  24. package/.output/server/chunks/build/{OmpTerminalPanel-CZnxR3M_.mjs → OmpTerminalPanel-B_SYhmgb.mjs} +2 -2
  25. package/.output/server/chunks/build/{OmpTerminalPanel-CZnxR3M_.mjs.map → OmpTerminalPanel-B_SYhmgb.mjs.map} +1 -1
  26. package/.output/server/chunks/build/{TownView-DYlUNRZe.mjs → TownView-D9yCQe1T.mjs} +6 -6
  27. package/.output/server/chunks/build/{TownView-DYlUNRZe.mjs.map → TownView-D9yCQe1T.mjs.map} +1 -1
  28. package/.output/server/chunks/build/{_id_-BOhG2yz8.mjs → _id_-CmKAEFHV.mjs} +4 -2
  29. package/.output/server/chunks/build/_id_-CmKAEFHV.mjs.map +1 -0
  30. package/.output/server/chunks/build/{_id_-CuyMYmhY.mjs → _id_-xR3AChMO.mjs} +74 -26
  31. package/.output/server/chunks/build/_id_-xR3AChMO.mjs.map +1 -0
  32. package/.output/server/chunks/build/{_wsId_-B5f5BdW2.mjs → _wsId_-C45nVrl-.mjs} +12 -10
  33. package/.output/server/chunks/build/{_wsId_-B5f5BdW2.mjs.map → _wsId_-C45nVrl-.mjs.map} +1 -1
  34. package/.output/server/chunks/build/{agents-BVaxN75W.mjs → agents-D4l1icvn.mjs} +5 -3
  35. package/.output/server/chunks/build/agents-D4l1icvn.mjs.map +1 -0
  36. package/.output/server/chunks/build/{channel-templates-D1K2IKrE.mjs → channel-templates-DqjtC-R0.mjs} +5 -3
  37. package/.output/server/chunks/build/channel-templates-DqjtC-R0.mjs.map +1 -0
  38. package/.output/server/chunks/build/{client-only-CFTHwakk.mjs → client-only-D5BzSQc6.mjs} +2 -2
  39. package/.output/server/chunks/build/client-only-D5BzSQc6.mjs.map +1 -0
  40. package/.output/server/chunks/build/{daq-ObtN1TQ4.mjs → daq-Boz_dlAQ.mjs} +6 -4
  41. package/.output/server/chunks/build/daq-Boz_dlAQ.mjs.map +1 -0
  42. package/.output/server/chunks/build/{dcw-fINr-He1.mjs → dcw-wTRwBAUi.mjs} +3 -1
  43. package/.output/server/chunks/build/dcw-wTRwBAUi.mjs.map +1 -0
  44. package/.output/server/chunks/build/{default-CVVO40Jj.mjs → default-Dt6xLdpd.mjs} +7 -5
  45. package/.output/server/chunks/build/{default-CVVO40Jj.mjs.map → default-Dt6xLdpd.mjs.map} +1 -1
  46. package/.output/server/chunks/build/interval-WlxgjTzO.mjs +9 -0
  47. package/.output/server/chunks/build/interval-WlxgjTzO.mjs.map +1 -0
  48. package/.output/server/chunks/build/{logs-DqNgCJAn.mjs → logs-Cdi-eXlN.mjs} +5 -3
  49. package/.output/server/chunks/build/logs-Cdi-eXlN.mjs.map +1 -0
  50. package/.output/server/chunks/build/{monitor-CTZLwbdw.mjs → monitor-yNoV98rf.mjs} +6 -4
  51. package/.output/server/chunks/build/{monitor-CTZLwbdw.mjs.map → monitor-yNoV98rf.mjs.map} +1 -1
  52. package/.output/server/chunks/build/{pages-DC52d7z7.mjs → pages-bWKy0ZsA.mjs} +6 -4
  53. package/.output/server/chunks/build/pages-bWKy0ZsA.mjs.map +1 -0
  54. package/.output/server/chunks/build/{plugins-DVQty7qG.mjs → plugins-B-ZNey0Z.mjs} +4 -2
  55. package/.output/server/chunks/build/plugins-B-ZNey0Z.mjs.map +1 -0
  56. package/.output/server/chunks/build/{settings-BeergncK.mjs → settings-C3T5hR2A.mjs} +21 -19
  57. package/.output/server/chunks/build/settings-C3T5hR2A.mjs.map +1 -0
  58. package/.output/server/chunks/build/{teams-CFeDlHDh.mjs → teams-QR3BBF7A.mjs} +5 -3
  59. package/.output/server/chunks/build/teams-QR3BBF7A.mjs.map +1 -0
  60. package/.output/server/chunks/build/{tokens-CBAUbOce.mjs → tokens-DFvr_TLj.mjs} +4 -2
  61. package/.output/server/chunks/build/tokens-DFvr_TLj.mjs.map +1 -0
  62. package/.output/server/chunks/build/town-BUqRobze.mjs +2 -0
  63. package/.output/server/chunks/build/town-BUqRobze.mjs.map +1 -1
  64. package/.output/server/chunks/build/{town-BxH-XXth.mjs → town-CKg6Qxba.mjs} +9 -7
  65. package/.output/server/chunks/build/town-CKg6Qxba.mjs.map +1 -0
  66. package/.output/server/chunks/build/{useDaqStream-CwORhsD7.mjs → useDaqStream-zHEptJQ_.mjs} +44 -1
  67. package/.output/server/chunks/build/useDaqStream-zHEptJQ_.mjs.map +1 -0
  68. package/.output/server/chunks/build/{useSiteConfig-Cc-ABesl.mjs → useSiteConfig-DJe_KMVr.mjs} +1 -1
  69. package/.output/server/chunks/build/{useSiteConfig-Cc-ABesl.mjs.map → useSiteConfig-DJe_KMVr.mjs.map} +1 -1
  70. package/.output/server/chunks/build/{useWorkshopApi-5er8_EHZ.mjs → useWorkshopApi-Bh5VUHWu.mjs} +1 -1
  71. package/.output/server/chunks/build/{useWorkshopApi-5er8_EHZ.mjs.map → useWorkshopApi-Bh5VUHWu.mjs.map} +1 -1
  72. package/.output/server/chunks/build/{useWorkshopWs-Dwr_1Q8f.mjs → useWorkshopWs-xcdeiSmJ.mjs} +2 -2
  73. package/.output/server/chunks/build/{useWorkshopWs-Dwr_1Q8f.mjs.map → useWorkshopWs-xcdeiSmJ.mjs.map} +1 -1
  74. package/.output/server/chunks/build/{user-CpVY4OAA.mjs → user-Dk-ytEUV.mjs} +1 -1
  75. package/.output/server/chunks/build/{user-CpVY4OAA.mjs.map → user-Dk-ytEUV.mjs.map} +1 -1
  76. package/.output/server/chunks/build/{users-BMs4s_6K.mjs → users-4FZ0yFUO.mjs} +4 -2
  77. package/.output/server/chunks/build/users-4FZ0yFUO.mjs.map +1 -0
  78. package/.output/server/chunks/build/{workshop-CJAyZ5zS.mjs → workshop-CLhwe5eo.mjs} +6 -4
  79. package/.output/server/chunks/build/workshop-CLhwe5eo.mjs.map +1 -0
  80. package/.output/server/chunks/build/{workspaces-Dq-1zvu9.mjs → workspaces-IfORCDJE.mjs} +2 -2
  81. package/.output/server/chunks/build/{workspaces-Dq-1zvu9.mjs.map → workspaces-IfORCDJE.mjs.map} +1 -1
  82. package/.output/server/chunks/routes/api/health.get.mjs +2 -0
  83. package/.output/server/chunks/routes/api/health.get.mjs.map +1 -1
  84. package/.output/server/chunks/routes/api/index.get.mjs +2 -0
  85. package/.output/server/chunks/routes/api/index.get.mjs.map +1 -1
  86. package/.output/server/chunks/routes/api/index.post.mjs +2 -0
  87. package/.output/server/chunks/routes/api/index.post.mjs.map +1 -1
  88. package/.output/server/chunks/routes/api/mcp/workshop.mjs +2 -0
  89. package/.output/server/chunks/routes/api/mcp/workshop.mjs.map +1 -1
  90. package/.output/server/chunks/routes/api/metrics.mjs +2 -0
  91. package/.output/server/chunks/routes/api/metrics.mjs.map +1 -1
  92. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +2 -0
  93. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs.map +1 -1
  94. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +2 -0
  95. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs.map +1 -1
  96. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +2 -0
  97. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs.map +1 -1
  98. package/.output/server/chunks/routes/api/system/config.get.mjs +2 -0
  99. package/.output/server/chunks/routes/api/system/config.get.mjs.map +1 -1
  100. package/.output/server/chunks/routes/api/system/index.get.mjs +2 -0
  101. package/.output/server/chunks/routes/api/system/index.get.mjs.map +1 -1
  102. package/.output/server/chunks/routes/api/system/index.patch.mjs +2 -0
  103. package/.output/server/chunks/routes/api/system/index.patch.mjs.map +1 -1
  104. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +2 -0
  105. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs.map +1 -1
  106. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +2 -0
  107. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs.map +1 -1
  108. package/.output/server/chunks/routes/api/system/monitor.get.mjs +2 -0
  109. package/.output/server/chunks/routes/api/system/monitor.get.mjs.map +1 -1
  110. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +3 -2
  111. package/.output/server/chunks/routes/api/system/settings/events.get.mjs.map +1 -1
  112. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +2 -0
  113. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs.map +1 -1
  114. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +2 -0
  115. package/.output/server/chunks/routes/api/users/_id_.delete.mjs.map +1 -1
  116. package/.output/server/chunks/routes/api/users/_id_.get.mjs +2 -0
  117. package/.output/server/chunks/routes/api/users/_id_.get.mjs.map +1 -1
  118. package/.output/server/chunks/routes/api/users/_id_.put.mjs +2 -0
  119. package/.output/server/chunks/routes/api/users/_id_.put.mjs.map +1 -1
  120. package/.output/server/chunks/routes/api/users/index.get.mjs +2 -0
  121. package/.output/server/chunks/routes/api/users/index.get.mjs.map +1 -1
  122. package/.output/server/chunks/routes/api/users/index.post.mjs +2 -0
  123. package/.output/server/chunks/routes/api/users/index.post.mjs.map +1 -1
  124. package/.output/server/chunks/routes/api/users/login.post.mjs +2 -0
  125. package/.output/server/chunks/routes/api/users/login.post.mjs.map +1 -1
  126. package/.output/server/chunks/routes/api/users/logout.post.mjs +2 -0
  127. package/.output/server/chunks/routes/api/users/logout.post.mjs.map +1 -1
  128. package/.output/server/chunks/routes/api/users/me.get.mjs +2 -0
  129. package/.output/server/chunks/routes/api/users/me.get.mjs.map +1 -1
  130. package/.output/server/chunks/routes/api/users/register.post.mjs +2 -0
  131. package/.output/server/chunks/routes/api/users/register.post.mjs.map +1 -1
  132. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +2 -0
  133. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs.map +1 -1
  134. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +2 -0
  135. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs.map +1 -1
  136. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +2 -0
  137. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs.map +1 -1
  138. package/.output/server/chunks/routes/api/workshop/_...path_.mjs +2 -0
  139. package/.output/server/chunks/routes/api/workshop/_...path_.mjs.map +1 -1
  140. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +2 -0
  141. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs.map +1 -1
  142. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +2 -0
  143. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs.map +1 -1
  144. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +2 -0
  145. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs.map +1 -1
  146. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +2 -0
  147. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs.map +1 -1
  148. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +2 -0
  149. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs.map +1 -1
  150. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +2 -0
  151. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs.map +1 -1
  152. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +2 -0
  153. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs.map +1 -1
  154. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +2 -0
  155. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs.map +1 -1
  156. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +2 -0
  157. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs.map +1 -1
  158. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +2 -0
  159. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
  160. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +2 -0
  161. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs.map +1 -1
  162. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +2 -0
  163. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs.map +1 -1
  164. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +2 -0
  165. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs.map +1 -1
  166. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +2 -0
  167. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs.map +1 -1
  168. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +2 -0
  169. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs.map +1 -1
  170. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +2 -0
  171. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs.map +1 -1
  172. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +2 -0
  173. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs.map +1 -1
  174. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +2 -0
  175. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs.map +1 -1
  176. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +2 -0
  177. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs.map +1 -1
  178. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +2 -0
  179. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs.map +1 -1
  180. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +2 -0
  181. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs.map +1 -1
  182. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +2 -0
  183. package/.output/server/chunks/routes/api/workshop/audit.get.mjs.map +1 -1
  184. package/.output/server/chunks/routes/api/workshop/caller.mjs +2 -0
  185. package/.output/server/chunks/routes/api/workshop/caller.mjs.map +1 -1
  186. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +2 -0
  187. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs.map +1 -1
  188. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +2 -0
  189. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs.map +1 -1
  190. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +2 -0
  191. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs.map +1 -1
  192. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +2 -0
  193. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs.map +1 -1
  194. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +2 -0
  195. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs.map +1 -1
  196. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +2 -0
  197. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs.map +1 -1
  198. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +2 -0
  199. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs.map +1 -1
  200. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +2 -0
  201. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs.map +1 -1
  202. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +2 -0
  203. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs.map +1 -1
  204. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +2 -0
  205. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs.map +1 -1
  206. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +2 -0
  207. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs.map +1 -1
  208. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +2 -0
  209. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs.map +1 -1
  210. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +2 -0
  211. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs.map +1 -1
  212. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +2 -0
  213. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs.map +1 -1
  214. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +2 -0
  215. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs.map +1 -1
  216. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +2 -0
  217. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs.map +1 -1
  218. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +2 -0
  219. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs.map +1 -1
  220. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +2 -0
  221. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs.map +1 -1
  222. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +2 -0
  223. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs.map +1 -1
  224. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +2 -0
  225. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs.map +1 -1
  226. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +2 -0
  227. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs.map +1 -1
  228. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +2 -0
  229. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs.map +1 -1
  230. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +2 -0
  231. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs.map +1 -1
  232. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +2 -0
  233. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs.map +1 -1
  234. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +2 -0
  235. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs.map +1 -1
  236. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +2 -0
  237. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs.map +1 -1
  238. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +2 -0
  239. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs.map +1 -1
  240. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +2 -0
  241. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs.map +1 -1
  242. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +2 -0
  243. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs.map +1 -1
  244. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +2 -0
  245. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs.map +1 -1
  246. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +2 -0
  247. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs.map +1 -1
  248. package/.output/server/chunks/routes/api/workshop/channels.get.mjs +2 -0
  249. package/.output/server/chunks/routes/api/workshop/channels.get.mjs.map +1 -1
  250. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +2 -0
  251. package/.output/server/chunks/routes/api/workshop/channels.post.mjs.map +1 -1
  252. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +2 -0
  253. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs.map +1 -1
  254. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +36 -0
  255. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs.map +1 -0
  256. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +53 -0
  257. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs.map +1 -0
  258. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +2 -0
  259. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs.map +1 -1
  260. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +2 -0
  261. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs.map +1 -1
  262. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +2 -0
  263. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs.map +1 -1
  264. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +2 -0
  265. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs.map +1 -1
  266. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +2 -0
  267. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs.map +1 -1
  268. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +2 -0
  269. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs.map +1 -1
  270. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +2 -0
  271. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs.map +1 -1
  272. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +2 -0
  273. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs.map +1 -1
  274. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +2 -0
  275. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs.map +1 -1
  276. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +2 -0
  277. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs.map +1 -1
  278. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +2 -0
  279. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs.map +1 -1
  280. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +2 -0
  281. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs.map +1 -1
  282. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +2 -0
  283. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs.map +1 -1
  284. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +2 -0
  285. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs.map +1 -1
  286. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +2 -0
  287. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs.map +1 -1
  288. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +2 -0
  289. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs.map +1 -1
  290. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +2 -0
  291. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs.map +1 -1
  292. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -0
  293. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs.map +1 -1
  294. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +2 -0
  295. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs.map +1 -1
  296. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +2 -0
  297. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs.map +1 -1
  298. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +2 -0
  299. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs.map +1 -1
  300. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +2 -0
  301. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs.map +1 -1
  302. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +2 -0
  303. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs.map +1 -1
  304. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +2 -0
  305. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs.map +1 -1
  306. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +2 -0
  307. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs.map +1 -1
  308. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +2 -0
  309. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs.map +1 -1
  310. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +2 -0
  311. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs.map +1 -1
  312. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +2 -0
  313. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs.map +1 -1
  314. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +2 -0
  315. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs.map +1 -1
  316. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +2 -0
  317. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs.map +1 -1
  318. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +2 -0
  319. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs.map +1 -1
  320. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +2 -0
  321. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs.map +1 -1
  322. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +2 -0
  323. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs.map +1 -1
  324. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +2 -0
  325. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs.map +1 -1
  326. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +2 -0
  327. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs.map +1 -1
  328. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +2 -0
  329. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs.map +1 -1
  330. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +2 -0
  331. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs.map +1 -1
  332. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +2 -0
  333. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs.map +1 -1
  334. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +2 -0
  335. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs.map +1 -1
  336. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +2 -0
  337. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs.map +1 -1
  338. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +2 -0
  339. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs.map +1 -1
  340. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +2 -0
  341. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs.map +1 -1
  342. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +2 -0
  343. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs.map +1 -1
  344. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +2 -0
  345. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs.map +1 -1
  346. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +2 -0
  347. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs.map +1 -1
  348. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs +2 -0
  349. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs.map +1 -1
  350. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +2 -0
  351. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs.map +1 -1
  352. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +2 -0
  353. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs.map +1 -1
  354. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +2 -0
  355. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs.map +1 -1
  356. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +2 -0
  357. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs.map +1 -1
  358. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +2 -0
  359. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs.map +1 -1
  360. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +2 -0
  361. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs.map +1 -1
  362. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +2 -0
  363. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs.map +1 -1
  364. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +2 -0
  365. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs.map +1 -1
  366. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +2 -0
  367. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs.map +1 -1
  368. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +2 -0
  369. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs.map +1 -1
  370. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +2 -0
  371. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs.map +1 -1
  372. package/.output/server/chunks/routes/api/workshop/index.get.mjs +2 -0
  373. package/.output/server/chunks/routes/api/workshop/index.get.mjs.map +1 -1
  374. package/.output/server/chunks/routes/api/workshop/index.post.mjs +2 -0
  375. package/.output/server/chunks/routes/api/workshop/index.post.mjs.map +1 -1
  376. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +2 -0
  377. package/.output/server/chunks/routes/api/workshop/index10.get.mjs.map +1 -1
  378. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +2 -0
  379. package/.output/server/chunks/routes/api/workshop/index2.get.mjs.map +1 -1
  380. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +2 -0
  381. package/.output/server/chunks/routes/api/workshop/index2.post.mjs.map +1 -1
  382. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +2 -0
  383. package/.output/server/chunks/routes/api/workshop/index3.get.mjs.map +1 -1
  384. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +2 -0
  385. package/.output/server/chunks/routes/api/workshop/index3.post.mjs.map +1 -1
  386. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +2 -0
  387. package/.output/server/chunks/routes/api/workshop/index4.get.mjs.map +1 -1
  388. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +2 -0
  389. package/.output/server/chunks/routes/api/workshop/index4.post.mjs.map +1 -1
  390. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +2 -0
  391. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  392. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +2 -0
  393. package/.output/server/chunks/routes/api/workshop/index5.post.mjs.map +1 -1
  394. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +2 -0
  395. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  396. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +2 -0
  397. package/.output/server/chunks/routes/api/workshop/index6.post.mjs.map +1 -1
  398. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +2 -0
  399. package/.output/server/chunks/routes/api/workshop/index7.get.mjs.map +1 -1
  400. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +2 -0
  401. package/.output/server/chunks/routes/api/workshop/index7.post.mjs.map +1 -1
  402. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +2 -0
  403. package/.output/server/chunks/routes/api/workshop/index8.get.mjs.map +1 -1
  404. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +2 -0
  405. package/.output/server/chunks/routes/api/workshop/index8.post.mjs.map +1 -1
  406. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +2 -0
  407. package/.output/server/chunks/routes/api/workshop/index9.get.mjs.map +1 -1
  408. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +2 -0
  409. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs.map +1 -1
  410. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +2 -0
  411. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs.map +1 -1
  412. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +2 -0
  413. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs.map +1 -1
  414. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +2 -0
  415. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs.map +1 -1
  416. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +2 -0
  417. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs.map +1 -1
  418. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +2 -0
  419. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs.map +1 -1
  420. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +2 -0
  421. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs.map +1 -1
  422. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +2 -0
  423. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs.map +1 -1
  424. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +2 -0
  425. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs.map +1 -1
  426. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +2 -0
  427. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs.map +1 -1
  428. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +2 -0
  429. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs.map +1 -1
  430. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +2 -0
  431. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs.map +1 -1
  432. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +2 -0
  433. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs.map +1 -1
  434. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +2 -0
  435. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs.map +1 -1
  436. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +2 -0
  437. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs.map +1 -1
  438. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +2 -0
  439. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs.map +1 -1
  440. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +2 -0
  441. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs.map +1 -1
  442. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +2 -0
  443. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs.map +1 -1
  444. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +2 -0
  445. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs.map +1 -1
  446. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +2 -0
  447. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs.map +1 -1
  448. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +2 -0
  449. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs.map +1 -1
  450. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +2 -0
  451. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs.map +1 -1
  452. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +2 -0
  453. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs.map +1 -1
  454. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +2 -0
  455. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs.map +1 -1
  456. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +2 -0
  457. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs.map +1 -1
  458. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +2 -0
  459. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs.map +1 -1
  460. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -0
  461. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs.map +1 -1
  462. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +2 -0
  463. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs.map +1 -1
  464. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +2 -0
  465. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs.map +1 -1
  466. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +2 -0
  467. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs.map +1 -1
  468. package/.output/server/chunks/routes/renderer.mjs +1 -1
  469. package/.output/server/chunks/routes/renderer.mjs.map +1 -1
  470. package/.output/server/chunks/virtual/entry.mjs +166 -114
  471. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  472. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  473. package/.output/server/index.mjs +2 -0
  474. package/.output/server/index.mjs.map +1 -1
  475. package/.output/server/package.json +1 -1
  476. package/app/composables/workshop/useDaqStream.ts +59 -1
  477. package/app/config/schema.ts +8 -0
  478. package/app/pages/daq/[id].vue +141 -1
  479. package/app/pages/settings.vue +10 -5
  480. package/app/plugins/runtime-config.client.ts +65 -65
  481. package/app/stores/runtime-config.ts +212 -212
  482. package/config.yml +77 -70
  483. package/docker-compose.yml +19 -2
  484. package/docs/plugins.md +271 -197
  485. package/i18n/dicts/_en.json +7 -2
  486. package/i18n/dicts/daqDetail.json +8 -2
  487. package/i18n/locales/en.ts +55 -29
  488. package/i18n/locales/zh-CN.ts +55 -29
  489. package/nuxt.config.ts +1 -1
  490. package/package.json +144 -143
  491. package/scripts/_dbg-collab-scenario-e2e.mjs +185 -0
  492. package/scripts/_dbg-daq-frame-alarm.mjs +49 -0
  493. package/scripts/_dbg-daq-frame-ui.mjs +62 -0
  494. package/scripts/_dbg-daq-frame-ws.mjs +72 -0
  495. package/scripts/_dbg-daq-frames-e2e.mjs +118 -0
  496. package/scripts/_dbg-host.mjs +16 -0
  497. package/scripts/_dbg-plugin-agent-read.ts +56 -0
  498. package/scripts/_dbg-plugin-sink-rest.mjs +70 -0
  499. package/scripts/_dbg-plugin-sink-ui.mjs +81 -0
  500. package/scripts/_dbg-plugin-tools-inject.ts +80 -0
  501. package/scripts/_dbg-plugin-verify-e2e.mjs +123 -0
  502. package/scripts/_dbg-prompts-hotreload-test.ts +76 -0
  503. package/scripts/_dbg-release-smoke.mjs +104 -0
  504. package/scripts/i18n-merge.mjs +69 -67
  505. package/scripts/test-context-governor.ts +176 -176
  506. package/scripts/test-daq-frames.ts +180 -0
  507. package/scripts/test-daq-minio.ts +77 -0
  508. package/scripts/test-memory-rrf-mmr.ts +114 -114
  509. package/scripts/test-plugin-ext.ts +173 -0
  510. package/server/api/system/settings/events.get.ts +27 -28
  511. package/server/api/system/settings/index.get.ts +14 -14
  512. package/server/api/system/settings/index.patch.ts +22 -22
  513. package/server/api/system/settings/reset.post.ts +12 -12
  514. package/server/api/workshop/daq/[id]/frames/content.get.ts +24 -0
  515. package/server/api/workshop/daq/[id]/frames.get.ts +44 -0
  516. package/server/data/daqs.json +113 -89
  517. package/server/data/dcw-rollback.json +1 -1
  518. package/server/data/dcw-runs.json +3207 -2517
  519. package/server/data/dcw-writes.json +720 -0
  520. package/server/data/dcws.json +4 -4
  521. package/server/data/line-runs.json +1 -232
  522. package/server/plugins/daq.ts +11 -0
  523. package/server/plugins/system-config.ts +38 -38
  524. package/server/services/system-config.ts +365 -356
  525. package/server/services/workshop/agents/industrial-tools.ts +91 -25
  526. package/server/services/workshop/agents/omp-agent.ts +1955 -1895
  527. package/server/services/workshop/agents/plugin-tools.ts +145 -0
  528. package/server/services/workshop/daq/bus/queue-port.ts +18 -0
  529. package/server/services/workshop/daq/daq-controller.ts +216 -14
  530. package/server/services/workshop/daq/daq-node.ts +257 -247
  531. package/server/services/workshop/daq/daq-runtime.ts +36 -4
  532. package/server/services/workshop/daq/daq-templates.ts +213 -157
  533. package/server/services/workshop/daq/drivers.ts +134 -30
  534. package/server/services/workshop/daq/frames.ts +227 -0
  535. package/server/services/workshop/daq/infra.ts +31 -17
  536. package/server/services/workshop/daq/objectstore/disk.adapter.ts +38 -0
  537. package/server/services/workshop/daq/objectstore/index.ts +88 -0
  538. package/server/services/workshop/daq/objectstore/minio.adapter.ts +60 -0
  539. package/server/services/workshop/daq/objectstore/objectstore-port.ts +27 -0
  540. package/server/services/workshop/daq/plugin-bridge.ts +73 -0
  541. package/server/services/workshop/daq/png-enc.ts +71 -0
  542. package/server/services/workshop/daq/storage/sqlite.adapter.ts +104 -1
  543. package/server/services/workshop/daq/storage/timescale.adapter.ts +95 -4
  544. package/server/services/workshop/daq/storage/tsdb-port.ts +46 -0
  545. package/server/services/workshop/plugins/host.mjs +479 -417
  546. package/server/services/workshop/runtime/agent-runtime.ts +744 -744
  547. package/shared/config/schema.json +6 -1
  548. package/shared/daq-protocol.ts +88 -0
  549. package/.output/public/_nuxt/B-PgoIPN.js +0 -1
  550. package/.output/public/_nuxt/DVNYfGsj.js +0 -1
  551. package/.output/public/_nuxt/_id_.CbiF5PrV.css +0 -1
  552. package/.output/public/_nuxt/builds/meta/6f7e40bf-a960-4f51-8a2e-bb1fffeaa5e8.json +0 -1
  553. package/.output/public/_nuxt/settings.BANibAnV.css +0 -1
  554. package/.output/server/chunks/build/_id_-BOhG2yz8.mjs.map +0 -1
  555. package/.output/server/chunks/build/_id_-CuyMYmhY.mjs.map +0 -1
  556. package/.output/server/chunks/build/agents-BVaxN75W.mjs.map +0 -1
  557. package/.output/server/chunks/build/channel-templates-D1K2IKrE.mjs.map +0 -1
  558. package/.output/server/chunks/build/client-only-CFTHwakk.mjs.map +0 -1
  559. package/.output/server/chunks/build/daq-ObtN1TQ4.mjs.map +0 -1
  560. package/.output/server/chunks/build/dcw-fINr-He1.mjs.map +0 -1
  561. package/.output/server/chunks/build/interval-Bt11uRPw.mjs +0 -9
  562. package/.output/server/chunks/build/interval-Bt11uRPw.mjs.map +0 -1
  563. package/.output/server/chunks/build/logs-DqNgCJAn.mjs.map +0 -1
  564. package/.output/server/chunks/build/pages-DC52d7z7.mjs.map +0 -1
  565. package/.output/server/chunks/build/plugins-DVQty7qG.mjs.map +0 -1
  566. package/.output/server/chunks/build/settings-BeergncK.mjs.map +0 -1
  567. package/.output/server/chunks/build/teams-CFeDlHDh.mjs.map +0 -1
  568. package/.output/server/chunks/build/tokens-CBAUbOce.mjs.map +0 -1
  569. package/.output/server/chunks/build/town-BxH-XXth.mjs.map +0 -1
  570. package/.output/server/chunks/build/useDaqStream-CwORhsD7.mjs.map +0 -1
  571. package/.output/server/chunks/build/users-BMs4s_6K.mjs.map +0 -1
  572. package/.output/server/chunks/build/workshop-CJAyZ5zS.mjs.map +0 -1
@@ -1,744 +1,744 @@
1
- /**
2
- * AgentRuntime — Agent 独立运行时对象。
3
- * 状态机 idle/busy/stopped + 消费循环(自动接取/自动作业)+ run/supervise 互斥 + abort。
4
- * 任务管理系统:每个运行时对自己的任务队列(待执行 FIFO / 执行中 / 已完成)有完整视图;
5
- * 队列是 tasks 表的派生投影(DB 唯一事实源),状态迁移实时广播(idle/busy + 队列上下文)。
6
- */
7
- import { createLogger } from '../logger'
8
- import { randomUUID } from 'node:crypto'
9
- import type {
10
- AgentEvent,
11
- AgentInfo,
12
- AgentInterface,
13
- AgentRunContext,
14
- AgentRunRequest,
15
- AgentWorkspace,
16
- SupervisionDecision,
17
- SupervisionSnapshot,
18
- } from '../agents/agent-interface'
19
- import type { A2AMessage, A2AArtifact, Part } from '../types/a2a'
20
- import type { AgentContextStats, AgentStatusView, AgentTaskQueueView, TaskState, WorkspaceTask } from '../types/task'
21
- import { TERMINAL_TASK_STATES } from '../types/task'
22
- import type { AgentMemory } from './memory'
23
- import type { Mailbox } from './mailbox'
24
-
25
- const log = createLogger('workshop.agent-runtime')
26
-
27
- /** ChannelBus:运行时事件总线(逐事件广播 + 任务/成员事件通知 + 调度唤醒) */
28
- /** 任务变更事件携带的源头任务视图(WS 推送免 per-event 回查;WorkspaceTask 结构兼容) */
29
- export interface TaskEventTask {
30
- id: string
31
- title?: string
32
- parentId?: string
33
- assigneeId?: string
34
- progress?: number | null
35
- routeReason?: string
36
- createdAt: string
37
- artifacts?: unknown[]
38
- }
39
-
40
- export interface ChannelBus {
41
- /** AgentEvent 流式广播:所有 harness 的统一事件出口(自定义协议流) */
42
- emit(event: AgentEvent, source: A2AMessage): void
43
- /** 订阅 AgentEvent 流(monitor/WS 消费);返回退订函数 */
44
- onEvent(fn: (event: AgentEvent, source: A2AMessage) => void): () => void
45
- /** 任务事件通知(状态迁移/进度变化;由 TaskEngine hooks 统一触发;task = 源头视图) */
46
- notifyTask(e: { taskId: string, state?: TaskState, progress?: number, agentId?: string, task?: TaskEventTask }): void
47
- onTaskEvent(fn: (e: { taskId: string, state?: TaskState, progress?: number, agentId?: string, task?: TaskEventTask }) => void): () => void
48
- /**
49
- * 成员状态通知(idle/busy/stopped + 队列上下文;AgentRuntime 转换处触发,事件驱动无轮询)。
50
- * currentTaskId/currentTaskTitle/currentTaskProgress/queuedCount/completedCount
51
- * 为增量字段:实时状态追踪的完整视图(lead 观察 worker 进度,防"在跑但无信号")。
52
- */
53
- notifyAgent(e: {
54
- agentId: string
55
- state: 'idle' | 'busy' | 'stopped'
56
- currentTaskId?: string | null
57
- currentTaskTitle?: string | null
58
- currentTaskProgress?: number | null
59
- queuedCount?: number
60
- completedCount?: number
61
- /** harness 上下文用量(omp 有;进程内 harness 缺省) */
62
- context?: AgentContextStats | null
63
- }): void
64
- onAgentStatus(fn: (e: {
65
- agentId: string
66
- state: 'idle' | 'busy' | 'stopped'
67
- currentTaskId?: string | null
68
- currentTaskTitle?: string | null
69
- currentTaskProgress?: number | null
70
- queuedCount?: number
71
- completedCount?: number
72
- context?: AgentContextStats | null
73
- }) => void): () => void
74
- /** channel 内消息投递通知(route 汇流点触发;AEP a2a.message 事件源) */
75
- notifyMessage(message: A2AMessage): void
76
- onMessage(fn: (message: A2AMessage) => void): () => void
77
- /** 团队成员增/改/删通知(lead 自主管理或用户 REST;AEP agent.member 事件源) */
78
- notifyMember(e: MemberChangeEvent): void
79
- onMemberEvent(fn: (e: MemberChangeEvent) => void): () => void
80
- /** 记忆写入通知(策展/主动沉淀;AEP memory.saved 事件源) */
81
- notifyMemory(e: { agentId: string, scope: 'private' | 'shared', title: string, dedupKey: string }): void
82
- onMemoryEvent(fn: (e: { agentId: string, scope: 'private' | 'shared', title: string, dedupKey: string }) => void): () => void
83
- wakeScheduler(): void
84
- }
85
-
86
- /** 团队成员变更事件(lead 执行中自主管理成员或用户 REST 操作;AEP agent.member 载荷) */
87
- export interface MemberChangeEvent {
88
- op: 'added' | 'updated' | 'removed'
89
- agentId: string
90
- name: string
91
- role: 'lead' | 'worker'
92
- harness: string
93
- enabled?: number
94
- /** 实例 config(含 systemPromptPrefix 场景提示词;added/updated 时携带,removed 可空) */
95
- config?: Record<string, unknown>
96
- /** 操作发起方:'lead:<agentId>' 或 'user' */
97
- by: string
98
- reason?: string
99
- }
100
-
101
- /** Parts → 纯文本(text 片段拼接;记忆召回查询与回复收集共用) */
102
- function partsToText(parts: Part[]): string {
103
- return parts.map(p => ('text' in p ? p.text : '')).filter(Boolean).join('\n')
104
- }
105
-
106
- /**
107
- * TaskEngine 结构契约(实现方 T4 task-engine.ts,同步签名)。
108
- * 以接口而非具体类声明依赖,便于测试注入 fake 与集成装配真实引擎。
109
- */
110
- export interface TaskEngine {
111
- create(input: {
112
- channelId: string
113
- creatorId: string
114
- assigneeId: string
115
- title: string
116
- description?: string
117
- parentId?: string
118
- parts?: Part[]
119
- }): WorkspaceTask
120
- dispatch(
121
- parent: WorkspaceTask,
122
- input: { assigneeId: string, title: string, description?: string, parts?: Part[], routeReason?: string },
123
- ): WorkspaceTask
124
- transition(taskId: string, state: TaskState, by: string): WorkspaceTask
125
- applyEvent(taskId: string, event: AgentEvent): void
126
- list(channelId: string): WorkspaceTask[]
127
- get(taskId: string): WorkspaceTask | undefined
128
- complete(taskId: string, artifacts?: A2AArtifact[]): WorkspaceTask
129
- reassign(taskId: string, toAgentId: string): WorkspaceTask
130
- /** 修改待执行任务(title/description)+ 刷新 assignee 队列投递 */
131
- updateTask(taskId: string, patch: { title?: string, description?: string }, by: string): WorkspaceTask
132
- cancel(taskId: string, by: string): WorkspaceTask
133
- onChildCompleted(child: WorkspaceTask): void
134
- /** 断线重连重投:非终态任务无 pending assign 时向 assignee 重发(restore 用) */
135
- redeliverAssign(taskId: string): WorkspaceTask
136
- /** 单 agent 任务队列视图(待执行 FIFO / 执行中 / 已完成) */
137
- queueViewOf(channelId: string, agentId: string): AgentTaskQueueView
138
- /** 批量队列视图(一次查询聚合全 channel;调度快照热路径) */
139
- queueViewsOf(channelId: string): Map<string, AgentTaskQueueView>
140
- }
141
-
142
- /**
143
- * AgentRuntime 的结构契约(ChannelRuntime/SchedulerLoop 消费的最小接口)。
144
- */
145
- export interface AgentRuntimeLike {
146
- readonly agentId: string
147
- readonly role: 'lead' | 'worker'
148
- readonly channelId: string
149
- readonly name: string
150
- enqueue(message: A2AMessage): void
151
- getState(): 'idle' | 'busy' | 'stopped'
152
- /** 实时状态视图(idle/busy/stopped + 当前任务 + 队列长度) */
153
- getStatus(): AgentStatusView
154
- /** 本 agent 的任务队列视图(待执行 FIFO / 执行中 / 已完成) */
155
- getQueueView(): AgentTaskQueueView
156
- abortCurrent(): void
157
- wakeMailbox(): void
158
- stop(): Promise<void>
159
- /** 平台侧合成事件出口(如 SchedulerLoop 汇总成果);转发 ChannelBus.emit 走统一事件流 */
160
- emitExternal(event: AgentEvent, fromAgentId?: string): void
161
- /** 实时消息注入:busy 时通过 impl.steer 注入 omp 会话;idle 时入 mailbox 队列 */
162
- injectSteer(message: A2AMessage): void
163
- /** Agent 能力面(调度器执行成员管理决策用;AgentRuntime 始终提供) */
164
- readonly workspace?: AgentWorkspace
165
- }
166
-
167
- export class AgentRuntime {
168
- readonly agentId: string
169
- readonly role: 'lead' | 'worker'
170
- readonly channelId: string
171
- readonly name: string
172
- private state: 'idle' | 'busy' | 'stopped' = 'idle'
173
- /** 回合失败重投计数(每消息;进程内存,重启由 resetConsuming 重新给机会) */
174
- private runErrorRetries = new Map<string, number>()
175
- /** 正在执行的任务 id(run 期间;空闲时 null) */
176
- private currentTaskId: string | null = null
177
- /** poll_messages 阻塞等待数(waitPending 活动计数;>0 = 有轮询在等,实时消息留信箱由其取走) */
178
- private pollWaiters = 0
179
- /** run 与 supervise 互斥锁(promise 链) */
180
- private execLock: Promise<void> = Promise.resolve()
181
- private abortController: AbortController | null = null
182
- private loopPromise: Promise<void> | null = null
183
- private started = false
184
-
185
- constructor(
186
- agent: AgentInfo,
187
- private impl: AgentInterface,
188
- private deps: {
189
- mailbox: Mailbox
190
- taskEngine: TaskEngine
191
- bus: ChannelBus
192
- workspace: AgentWorkspace
193
- memory?: AgentMemory
194
- },
195
- ) {
196
- this.agentId = agent.id
197
- this.role = agent.role
198
- this.channelId = agent.channelId
199
- this.name = agent.name
200
- }
201
-
202
- /** 投递消息;idle 时立即唤醒消费 */
203
- enqueue(message: A2AMessage): void {
204
- this.deps.mailbox.enqueue(message)
205
- }
206
-
207
- getState(): 'idle' | 'busy' | 'stopped' {
208
- return this.state
209
- }
210
-
211
- /** 实时状态视图:idle/busy/stopped + 当前任务 + 队列 + harness 上下文用量 */
212
- getStatus(): AgentStatusView {
213
- const queue = this.getQueueView()
214
- const current = queue.current ?? (this.currentTaskId ? this.deps.taskEngine.get(this.currentTaskId) : undefined)
215
- const context = this.impl.getContextStats?.() ?? undefined
216
- return {
217
- agentId: this.agentId,
218
- channelId: this.channelId,
219
- role: this.role,
220
- name: this.name,
221
- state: this.state,
222
- currentTaskId: current?.id ?? null,
223
- // 进度/标题透出:lead 观察 worker 是否在推进(progress 空闲/未上报时为 null)
224
- currentTaskTitle: current?.title ?? null,
225
- currentTaskProgress: current?.progress != null ? current.progress : null,
226
- queuedCount: queue.queued.length,
227
- completedCount: queue.completed.length,
228
- ...(context ? { context } : {}),
229
- }
230
- }
231
-
232
- /** 本 agent 的任务队列视图(自己的任务管理系统:待执行 FIFO / 执行中 / 已完成) */
233
- getQueueView(): AgentTaskQueueView {
234
- return this.deps.taskEngine.queueViewOf(this.channelId, this.agentId)
235
- }
236
-
237
- /** 中止当前 run(任务取消/Agent 移除时);空闲时无操作 */
238
- abortCurrent(): void {
239
- log.warn(`[AgentRuntime:${this.agentId}] abortCurrent 调用(state=${this.state})`)
240
- this.abortController?.abort()
241
- // supervise 回合同样可打断(调度器 cancel 路径 → LLM 回合真中止)
242
- this.superviseController?.abort()
243
- }
244
-
245
- emitExternal(event: AgentEvent, fromAgentId?: string): void {
246
- // 合成 source(monitor 依 metadata 归属 agent);平台侧产出与 harness 事件同流
247
- const source: A2AMessage = {
248
- messageId: randomUUID(),
249
- contextId: this.channelId,
250
- role: 'ROLE_AGENT',
251
- parts: [],
252
- metadata: { 'x-aw-from-agent': fromAgentId ?? this.agentId },
253
- }
254
- this.deps.bus.emit(event, source)
255
- }
256
-
257
- /**
258
- * 实时注入策略(信箱优先,与主动轮询完全兼容):
259
- * - poll_messages 等待中:任何实时消息留在 pending —— 等待中的轮询经 Mailbox
260
- * 到信回调毫秒级取走(读即取=已读),零打断、不与轮询竞争唯一所有权
261
- * - agent 间协作消息(from-agent):同样走信箱 —— turn 结束后消费循环按 peer
262
- * 回合处理(require_reply 触发语义/回执关联完整)。steer 注入 omp 会话会让
263
- * 其把排队消息后的工具调用标记 "Skipped due to queued user message",
264
- * 中断 poll_messages 长等待并污染执行流(实测故障源)
265
- * - 仅人类紧急直发(immediate + from-label,无 from-agent)保留 steer 同轮注入:
266
- * 紧急人工打断是唯一值得中断会话的场景
267
- */
268
- injectSteer(message: A2AMessage): void {
269
- if (this.state !== 'busy' || !this.impl.steer) return
270
- // ① 轮询等待中:留 pending 给 poll_messages(毫秒级取走并标记已读)
271
- if (this.pollWaiters > 0) return
272
- // ② agent 间协作消息:信箱优先(turn 结束 peer 回合处理)
273
- const from = message.metadata?.['x-aw-from-agent']
274
- if (typeof from === 'string' && from.length > 0) return
275
- // ③ 其余(人类紧急直发):原有 steer 注入路径
276
- if (!this.deps.mailbox.claim(message.messageId)) return
277
- const text = message.parts
278
- .map((p) => {
279
- if ('text' in p) return p.text
280
- if ('data' in p) return JSON.stringify(p.data)
281
- return ''
282
- })
283
- .join('\n')
284
- const fromId = (message.metadata?.['x-aw-from-agent'] as string | undefined) ?? 'system'
285
- const lines = [`[实时消息 from ${fromId}]: ${text}`]
286
- if (message.metadata?.['x-aw-require-reply'] === 'true') {
287
- lines.push(
288
- `[系统触发器] 本消息要求回复(reply_to=${message.messageId})。`,
289
- `请处理消息中的需求,随后用 send_message_to_agent 回复发送者 ${fromId}:`,
290
- `参数 message=执行结果+对方所需内容, in_reply_to=${message.messageId},`,
291
- `require_reply=仅当你还需要对方进一步响应时才设 true。`,
292
- )
293
- }
294
- this.impl.steer(lines.join('\n'))
295
- .then((mode) => {
296
- if (mode === 'steer') {
297
- // 确认注入流式会话 → 消费落定(at-least-once:进程崩溃由 resetConsuming 兜底)
298
- this.deps.mailbox.markConsumed(message.messageId)
299
- }
300
- else {
301
- // deferred:释放认领回 pending,poll_messages(250ms 兜底重查)或
302
- // 本回合结束后的消费循环(FIFO)接管,消息必达不丢失
303
- this.releaseSteerClaim(message.messageId)
304
- }
305
- })
306
- .catch((err) => {
307
- log.error(`[AgentRuntime:${this.agentId}] steer 失败(释放认领回 pending 待循环处理):`, err)
308
- this.releaseSteerClaim(message.messageId)
309
- })
310
- }
311
-
312
- /** 释放 steer 认领:consuming → pending + 唤醒 dequeue 门闩与到信等待方 */
313
- private releaseSteerClaim(messageId: string): void {
314
- if (this.deps.mailbox.requeue(messageId)) {
315
- this.deps.mailbox.wake()
316
- }
317
- }
318
-
319
- /**
320
- * 长轮询未消费消息(poll_messages host 工具用):
321
- * 250ms 兜底重查 + Mailbox 到信回调即时唤醒——消息到达后毫秒级返回,
322
- * 不再每秒盲查。不改消息状态(peek 只读);消费语义由调用方(poll 读即取)决定。
323
- * pollWaiters 计数暴露"轮询等待中"状态:injectSteer 据此把实时消息留在信箱
324
- * 由本方法取走(不打断会话、与主动轮询兼容)。
325
- */
326
- async waitPending(limit: number, waitMs: number): Promise<A2AMessage[]> {
327
- this.pollWaiters += 1
328
- try {
329
- const deadline = Date.now() + Math.max(0, waitMs)
330
- for (;;) {
331
- const msgs = await this.deps.mailbox.peek(limit)
332
- if (msgs.length > 0 || Date.now() >= deadline) return msgs
333
- const { promise, resolve } = Promise.withResolvers<unknown>()
334
- const off = this.deps.mailbox.onArrival(() => resolve(undefined))
335
- const timer = setTimeout(() => resolve(undefined), 250)
336
- await promise
337
- clearTimeout(timer)
338
- off()
339
- }
340
- }
341
- finally {
342
- this.pollWaiters -= 1
343
- }
344
- }
345
-
346
- /** 启动消费循环 */
347
- start(): void {
348
- if (this.started) return
349
- this.started = true
350
- this.state = 'idle'
351
- this.loopPromise = this.consumeLoop()
352
- }
353
-
354
- /** 停止:中断当前 run + 等当前事件流结束 + dispose impl(杀子进程等) */
355
- async stop(): Promise<void> {
356
- log.warn(`[AgentRuntime:${this.agentId}] runtime.stop() 调用(卸载/停用)`)
357
- this.state = 'stopped'
358
- this.abortController?.abort()
359
- this.deps.mailbox.close()
360
- // 状态广播:前端经 WS agent.status 实时反映 stopped
361
- this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'stopped', ...this.queueContext() })
362
- await this.loopPromise
363
- // 清理 impl 持有的资源(omp 子进程等);容错:impl.dispose 可能不存在
364
- try {
365
- await this.impl.dispose?.()
366
- }
367
- catch (err) {
368
- log.error(`[AgentRuntime:${this.agentId}] dispose 失败:`, err)
369
- }
370
- }
371
-
372
- /** 唤醒 mailbox(供 manager 在 taskEngine 直接落库投递后唤醒消费) */
373
- wakeMailbox(): void {
374
- this.deps.mailbox.wake()
375
- }
376
-
377
- /**
378
- * 状态重广播:调度器收口(complete/cancel 等不经 processMessage 的终态迁移)
379
- * 直接改动了本 agent 的队列上下文(current/completed),重新广播 agent.status,
380
- * 前端实时反映 lead 判定完成后的最新状态(不刷新即可见)。
381
- */
382
- refreshStatus(): void {
383
- this.deps.bus.notifyAgent({ agentId: this.agentId, state: this.state, ...this.queueContext() })
384
- }
385
-
386
- /** harness 进程资源信息(运行时资源监控;进程内 harness 无外部进程 → null) */
387
- getProcessInfo(): { pid: number, alive: boolean, command: string } | null {
388
- return this.impl.getProcessInfo?.() ?? null
389
- }
390
-
391
- /**
392
- * 强制终止 harness 进程(不等优雅退出)。
393
- * 调用方(manager terminateRuntimeProcess)终止后随即 stop 本运行时。
394
- */
395
- killProcess(): void {
396
- this.impl.killProcess?.()
397
- }
398
-
399
- /** harness 进程存活校准(manager sweeper 周期性调用;休眠/强杀后校准 alive 失真;异常不抛出) */
400
- reconcileProcess(): void {
401
- try {
402
- this.impl.reconcileProcess?.()
403
- }
404
- catch (err) {
405
- log.error(`[AgentRuntime:${this.agentId}] 进程存活校准失败:`, err)
406
- }
407
- }
408
-
409
- /** 暴露 TaskEngine(供 SchedulerLoop 收集快照与执行调度决策) */
410
- get taskEngine(): TaskEngine {
411
- return this.deps.taskEngine
412
- }
413
-
414
- /** 暴露 AgentWorkspace(供 SchedulerLoop 执行 lead 成员管理决策) */
415
- get workspace(): AgentWorkspace {
416
- return this.deps.workspace
417
- }
418
-
419
- /**
420
- * lead 调度决策(供 SchedulerLoop 调用):转发 impl.supervise。
421
- * 未实现 supervise 时返回 null(调用方回退内置规则引擎);
422
- * 与 run 的互斥由调用方通过 withExecLock 保证。
423
- */
424
- /** 当前 supervise 回合的控制器(abortCurrent 经此打断 LLM 调度回合) */
425
- private superviseController: AbortController | null = null
426
-
427
- async supervise(snapshot: SupervisionSnapshot): Promise<SupervisionDecision[] | null> {
428
- if (!this.impl.supervise) return null
429
- // lead 调度记忆:非终态/失败任务标题 + 成员名构造查询;touch:false 防 tick 通胀
430
- let memoryBlock: string | undefined
431
- try {
432
- const query = [
433
- ...snapshot.tasks.filter(t => t.state === 'SUBMITTED' || t.state === 'FAILED' || t.state === 'WAITING').map(t => t.title),
434
- ...snapshot.members.map(m => m.name),
435
- ].join(' ')
436
- memoryBlock = (await this.deps.memory?.recall(query, { touch: false })) ?? undefined
437
- }
438
- catch (err) {
439
- log.error(`[AgentRuntime:${this.agentId}] supervise 记忆召回失败:`, err)
440
- }
441
- const controller = new AbortController()
442
- this.superviseController = controller
443
- const ctx: AgentRunContext = {
444
- agentId: this.agentId,
445
- channelId: this.channelId,
446
- role: this.role,
447
- workspace: this.deps.workspace,
448
- signal: controller.signal,
449
- memory: memoryBlock,
450
- }
451
- try {
452
- return await this.impl.supervise(snapshot, ctx, { signal: controller.signal })
453
- }
454
- finally {
455
- if (this.superviseController === controller) this.superviseController = null
456
- // 调度回合落定:lead 的 supervise 是上下文膨胀大户,同样走 post-settle 压缩检查
457
- this.maybePostSettle()
458
- }
459
- }
460
-
461
- /**
462
- * 平台侧任务记忆沉淀(调度器直接执行决策的收口路径):
463
- * lead 经 supervise 决策 complete/cancel 任务时不经过 processMessage,
464
- * 由 SchedulerLoop 调用此方法补齐终态 harvest(与 worker 路径同源)。
465
- */
466
- async recordTaskMemory(task: WorkspaceTask): Promise<void> {
467
- await this.deps.memory?.recordTaskOutcome(task)
468
- }
469
-
470
- /** run/supervise 互斥执行(promise 链;供消费循环与 SchedulerLoop 串行化) */
471
- withExecLock<T>(fn: () => Promise<T>): Promise<T> {
472
- const prev = this.execLock
473
- let release!: () => void
474
- this.execLock = new Promise<void>((r) => {
475
- release = r
476
- })
477
- return (async () => {
478
- await prev
479
- try {
480
- return await fn()
481
- }
482
- finally {
483
- release()
484
- }
485
- })()
486
- }
487
-
488
- /** 消费循环:空闲自动接取,执行中不打断 */
489
- private async consumeLoop(): Promise<void> {
490
- while (this.state !== 'stopped') {
491
- const msg = await this.deps.mailbox.dequeue()
492
- if (this.getState() === 'stopped' || msg === null) break
493
- // 单条 run 抛错不阻塞下一条
494
- try {
495
- await this.withExecLock(() => this.processMessage(msg))
496
- }
497
- catch (err) {
498
- log.error(`[AgentRuntime:${this.agentId}] run 失败:`, err)
499
- }
500
- }
501
- }
502
-
503
- private async processMessage(msg: A2AMessage): Promise<void> {
504
- const taskId = this.taskIdOf(msg)
505
- // 过期任务投递检查:任务已终态(cancel/reassign 后残留的旧 assign)→ 跳过执行,
506
- // 否则 worker 会对着已取消任务的旧投递真的跑一轮 harness。
507
- if (msg.metadata?.['x-aw-task-kind'] === 'assign' && taskId) {
508
- const task = this.deps.taskEngine.get(taskId)
509
- if (!task || TERMINAL_TASK_STATES[task.state]) {
510
- this.deps.mailbox.markConsumed(msg.messageId)
511
- return
512
- }
513
- }
514
- this.state = 'busy'
515
- this.currentTaskId = taskId ?? null
516
- this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'busy', ...this.queueContext() })
517
- // 回合失败标记(须在 try 外声明,finally 依据它决定重投还是消费)
518
- let sawRunError = false
519
- try {
520
- // 任务消息联动:assign → WORKING(自动接取;状态事件由 TaskEngine transition hooks 广播)
521
- // 仅 SUBMITTED/ASSIGNED 自动接取:WAITING(已有子任务)的任务由 SchedulerLoop/子任务汇总推进,
522
- // 此处不得把父任务从 WAITING 翻回 WORKING(否则父任务在子任务执行期间虚挂 WORKING,
523
- // 会被 stall 检测误判为停滞而 cancel)。
524
- if (msg.metadata?.['x-aw-task-kind'] === 'assign' && taskId) {
525
- const task = this.deps.taskEngine.get(taskId)
526
- if (task && (task.state === 'SUBMITTED' || task.state === 'ASSIGNED')) {
527
- await this.deps.taskEngine.transition(taskId, 'WORKING', this.agentId)
528
- }
529
- }
530
- // 每次 run 新建 AbortController;abort 后事件流终止
531
- this.abortController = new AbortController()
532
- // 记忆召回(异常不阻塞):查询=消息原文(title 首词天然显著)+ 任务关联加权
533
- let memoryBlock: string | undefined
534
- try {
535
- memoryBlock = (await this.deps.memory?.recall(partsToText(msg.parts), {
536
- relatedTaskIds: this.relatedTaskIdsOf(taskId),
537
- })) ?? undefined
538
- }
539
- catch (err) {
540
- log.error(`[AgentRuntime:${this.agentId}] 记忆召回失败:`, err)
541
- }
542
- const request: AgentRunRequest = this.toRequest(msg, memoryBlock)
543
- const ctx: AgentRunContext = {
544
- agentId: this.agentId,
545
- channelId: msg.contextId,
546
- role: this.role,
547
- workspace: this.deps.workspace,
548
- signal: this.abortController.signal,
549
- }
550
- // 补入产出者 agentId(monitor 据此归属事件;不改原 msg,用浅拷贝)
551
- const enrichedSource = { ...msg, metadata: { ...msg.metadata, 'x-aw-producing-agent': this.agentId } }
552
- // 回复文本收集(V9:omp 不产 message 事件,聚合三类源——message 事件 / status.message / 终态 artifact 'output')
553
- let replyText = ''
554
- const cap = (text: string): void => {
555
- if (replyText.length < 400) replyText += text.slice(0, 400 - replyText.length)
556
- }
557
- try {
558
- for await (const event of this.impl.run(request, ctx)) {
559
- this.deps.bus.emit(event, enrichedSource)
560
- // LLM 流式增量:只走事件流(AEP agent.delta),不进任务引擎/交付兜底管道
561
- if (event.kind === 'delta') continue
562
- if (event.kind === 'error') sawRunError = true
563
- if (taskId) await this.deps.taskEngine.applyEvent(taskId, event)
564
- if (event.kind === 'message') cap(partsToText(event.message.parts))
565
- else if (event.kind === 'status' && event.status.message) cap(partsToText(event.status.message.parts))
566
- else if (event.kind === 'artifact' && event.artifact.name === 'output') cap(partsToText(event.artifact.parts))
567
- }
568
- }
569
- catch (err) {
570
- // run 生成器抛错(如 omp 子进程 spawn 失败):按回合失败走重投,不外抛断循环
571
- sawRunError = true
572
- log.error(`[AgentRuntime:${this.agentId}] 回合异常:`, err)
573
- }
574
- // 交付兜底(harness 回合结束 ≠ 任务完成):
575
- // - 回合产出过实质 artifact(LLM 完成了工作但跳过 complete_task 工具)→ 隐式完成,
576
- // 交付物即回合规避的输出,平台代为收口(进度 100)。
577
- // - 无任何产出(LLM 空转)→ FAILED 交给调度器 retry/reassign。
578
- // 仅 worker 的 assign 执行消息生效:lead 由 supervise 协调;WAITING 父任务不属此列。
579
- if (taskId && this.role === 'worker' && msg.metadata?.['x-aw-task-kind'] === 'assign') {
580
- const after = this.deps.taskEngine.get(taskId)
581
- if (after && after.assigneeId === this.agentId && after.state === 'WORKING') {
582
- const deliverable = after.artifacts.find(a => a.name !== 'input' && a.parts.some(p => ('text' in p ? p.text.trim().length : 1) > 0))
583
- if (deliverable) {
584
- const completed = await this.deps.taskEngine.complete(taskId)
585
- this.emitExternal({
586
- kind: 'status',
587
- status: {
588
- state: 'COMPLETED',
589
- message: {
590
- messageId: randomUUID(),
591
- contextId: this.channelId,
592
- role: 'ROLE_AGENT',
593
- parts: [{ text: `任务 ${taskId} 回合已产出交付物但未调用完成工具,平台隐式收口为 COMPLETED` }],
594
- },
595
- timestamp: new Date().toISOString(),
596
- },
597
- })
598
- // 子任务隐式完成 → 通知父任务(lead 汇总/WAITING→WORKING 接续):
599
- // 与 manager.completeTask 的显式收口同构,否则父任务 WAITING 永挂
600
- // (无 child-completed 事件、父任务不翻转,lead 无感知)。
601
- if (completed.parentId) {
602
- this.deps.taskEngine.onChildCompleted(completed)
603
- const parent = this.deps.taskEngine.get(completed.parentId)
604
- if (parent) this.deps.bus.wakeScheduler()
605
- }
606
- }
607
- else {
608
- await this.deps.taskEngine.transition(taskId, 'FAILED', this.agentId)
609
- this.emitExternal({
610
- kind: 'status',
611
- status: {
612
- state: 'FAILED',
613
- message: {
614
- messageId: randomUUID(),
615
- contextId: this.channelId,
616
- role: 'ROLE_AGENT',
617
- parts: [{ text: `任务 ${taskId} 执行结束但无交付(harness 回合结束未产出),标记 FAILED 待重试` }],
618
- },
619
- timestamp: new Date().toISOString(),
620
- },
621
- })
622
- }
623
- }
624
- }
625
-
626
- // 记忆沉淀:终态任务 harvest;无 taskId 的点对点消息记协作(异常不阻塞)
627
- if (this.deps.memory) {
628
- try {
629
- const task = taskId ? this.deps.taskEngine.get(taskId) : undefined
630
- if (task && TERMINAL_TASK_STATES[task.state]) {
631
- await this.deps.memory.recordTaskOutcome(task)
632
- }
633
- else if (!taskId) {
634
- const fromAgentId = (msg.metadata?.['x-aw-from-agent'] as string | undefined) ?? null
635
- if (fromAgentId) await this.deps.memory.recordPeerExchange(msg, replyText)
636
- }
637
- }
638
- catch (err) {
639
- log.error(`[AgentRuntime:${this.agentId}] 记忆写入失败:`, err)
640
- }
641
- }
642
- }
643
- finally {
644
- this.abortController = null
645
- this.currentTaskId = null
646
- if (this.state === 'busy') {
647
- this.state = 'idle'
648
- this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'idle', ...this.queueContext() })
649
- }
650
- // 回合失败(harness 错误/停滞看门狗中止/子进程异常):重投消息而非静默消费,
651
- // 内容不丢,重试回合(通常已是全新子进程)再处理;每消息最多重投 2 次防毒消息死循环。
652
- // 任务已终态(取消/收口后 abort 让回合报错)则不再重投 —— 消息依任务终态
653
- // 由调度器 reassign/新 assign 驱动,重投只会空转(启动即被终态检查消费)。
654
- const taskNow = taskId ? this.deps.taskEngine.get(taskId) : undefined
655
- const taskDone = !!taskNow && TERMINAL_TASK_STATES[taskNow.state]
656
- if (sawRunError && !taskDone && (this.runErrorRetries.get(msg.messageId) ?? 0) < 2
657
- && this.deps.mailbox.requeue(msg.messageId)) {
658
- const attempt = (this.runErrorRetries.get(msg.messageId) ?? 0) + 1
659
- this.runErrorRetries.set(msg.messageId, attempt)
660
- this.emitExternal({
661
- kind: 'status',
662
- status: {
663
- state: 'WORKING',
664
- message: {
665
- messageId: randomUUID(),
666
- contextId: this.channelId,
667
- role: 'ROLE_AGENT',
668
- parts: [{ text: `消息 ${msg.messageId.slice(0, 8)} 回合失败,已重投信箱待重试(第 ${attempt} 次)` }],
669
- },
670
- timestamp: new Date().toISOString(),
671
- },
672
- })
673
- }
674
- else {
675
- this.runErrorRetries.delete(msg.messageId)
676
- this.deps.mailbox.markConsumed(msg.messageId)
677
- }
678
- // 回合落定:信箱空 → 后台压缩检查(post-settle 路径;impl 自守卫不阻塞)
679
- this.maybePostSettle()
680
- }
681
- }
682
-
683
- /** 状态通知的队列上下文(实时:当前任务/待执行数/已完成数/harness 上下文用量) */
684
- private queueContext(): Pick<AgentStatusView, 'currentTaskId' | 'currentTaskTitle' | 'currentTaskProgress' | 'queuedCount' | 'completedCount'> & { context?: AgentContextStats | null } {
685
- const status = this.getStatus()
686
- return {
687
- currentTaskId: status.currentTaskId,
688
- currentTaskTitle: status.currentTaskTitle,
689
- currentTaskProgress: status.currentTaskProgress,
690
- queuedCount: status.queuedCount,
691
- completedCount: status.completedCount,
692
- context: status.context ?? null,
693
- }
694
- }
695
-
696
- /**
697
- * 任务关联集(自身+父+兄弟,≤20):related-task boost 数据源。
698
- * 同父兄弟任务的记忆(前几个子任务做了什么)在引子中必然置顶——
699
- * 纯内存 id 判断,零检索开销。
700
- */
701
- private relatedTaskIdsOf(taskId: string | undefined): string[] | undefined {
702
- if (!taskId) return undefined
703
- const task = this.deps.taskEngine.get(taskId)
704
- if (!task) return undefined
705
- const ids = new Set<string>([taskId])
706
- if (task.parentId) {
707
- ids.add(task.parentId)
708
- for (const t of this.deps.taskEngine.list(this.channelId)) {
709
- if (t.parentId === task.parentId) ids.add(t.id)
710
- if (ids.size >= 20) break
711
- }
712
- }
713
- return [...ids]
714
- }
715
-
716
- /**
717
- * post-settle 压缩检查:仅信箱无排队消息时触发(排队消息的 pre-prompt gate 兜底)。
718
- * impl 自守卫(回合间隙才压缩、异常不抛出);本方法自身也不阻塞消费循环。
719
- */
720
- private maybePostSettle(): void {
721
- if (!this.impl.onTurnSettled) return
722
- void this.deps.mailbox.peek(1)
723
- .then((pending) => {
724
- if (pending.length > 0) return undefined
725
- return this.impl.onTurnSettled?.()
726
- })
727
- .catch(() => {})
728
- }
729
-
730
- private toRequest(msg: A2AMessage, memory?: string): AgentRunRequest {
731
- return {
732
- message: msg,
733
- taskId: msg.taskId,
734
- contextId: msg.contextId,
735
- fromAgentId: (msg.metadata?.['x-aw-from-agent'] as string | undefined) ?? null,
736
- toAgentId: this.agentId,
737
- memory,
738
- }
739
- }
740
-
741
- private taskIdOf(msg: A2AMessage): string | undefined {
742
- return msg.taskId ?? (msg.metadata?.['x-aw-task-id'] as string | undefined)
743
- }
744
- }
1
+ /**
2
+ * AgentRuntime — Agent 独立运行时对象。
3
+ * 状态机 idle/busy/stopped + 消费循环(自动接取/自动作业)+ run/supervise 互斥 + abort。
4
+ * 任务管理系统:每个运行时对自己的任务队列(待执行 FIFO / 执行中 / 已完成)有完整视图;
5
+ * 队列是 tasks 表的派生投影(DB 唯一事实源),状态迁移实时广播(idle/busy + 队列上下文)。
6
+ */
7
+ import { createLogger } from '../logger'
8
+ import { randomUUID } from 'node:crypto'
9
+ import type {
10
+ AgentEvent,
11
+ AgentInfo,
12
+ AgentInterface,
13
+ AgentRunContext,
14
+ AgentRunRequest,
15
+ AgentWorkspace,
16
+ SupervisionDecision,
17
+ SupervisionSnapshot,
18
+ } from '../agents/agent-interface'
19
+ import type { A2AMessage, A2AArtifact, Part } from '../types/a2a'
20
+ import type { AgentContextStats, AgentStatusView, AgentTaskQueueView, TaskState, WorkspaceTask } from '../types/task'
21
+ import { TERMINAL_TASK_STATES } from '../types/task'
22
+ import type { AgentMemory } from './memory'
23
+ import type { Mailbox } from './mailbox'
24
+
25
+ const log = createLogger('workshop.agent-runtime')
26
+
27
+ /** ChannelBus:运行时事件总线(逐事件广播 + 任务/成员事件通知 + 调度唤醒) */
28
+ /** 任务变更事件携带的源头任务视图(WS 推送免 per-event 回查;WorkspaceTask 结构兼容) */
29
+ export interface TaskEventTask {
30
+ id: string
31
+ title?: string
32
+ parentId?: string
33
+ assigneeId?: string
34
+ progress?: number | null
35
+ routeReason?: string
36
+ createdAt: string
37
+ artifacts?: unknown[]
38
+ }
39
+
40
+ export interface ChannelBus {
41
+ /** AgentEvent 流式广播:所有 harness 的统一事件出口(自定义协议流) */
42
+ emit(event: AgentEvent, source: A2AMessage): void
43
+ /** 订阅 AgentEvent 流(monitor/WS 消费);返回退订函数 */
44
+ onEvent(fn: (event: AgentEvent, source: A2AMessage) => void): () => void
45
+ /** 任务事件通知(状态迁移/进度变化;由 TaskEngine hooks 统一触发;task = 源头视图) */
46
+ notifyTask(e: { taskId: string, state?: TaskState, progress?: number, agentId?: string, task?: TaskEventTask }): void
47
+ onTaskEvent(fn: (e: { taskId: string, state?: TaskState, progress?: number, agentId?: string, task?: TaskEventTask }) => void): () => void
48
+ /**
49
+ * 成员状态通知(idle/busy/stopped + 队列上下文;AgentRuntime 转换处触发,事件驱动无轮询)。
50
+ * currentTaskId/currentTaskTitle/currentTaskProgress/queuedCount/completedCount
51
+ * 为增量字段:实时状态追踪的完整视图(lead 观察 worker 进度,防"在跑但无信号")。
52
+ */
53
+ notifyAgent(e: {
54
+ agentId: string
55
+ state: 'idle' | 'busy' | 'stopped'
56
+ currentTaskId?: string | null
57
+ currentTaskTitle?: string | null
58
+ currentTaskProgress?: number | null
59
+ queuedCount?: number
60
+ completedCount?: number
61
+ /** harness 上下文用量(omp 有;进程内 harness 缺省) */
62
+ context?: AgentContextStats | null
63
+ }): void
64
+ onAgentStatus(fn: (e: {
65
+ agentId: string
66
+ state: 'idle' | 'busy' | 'stopped'
67
+ currentTaskId?: string | null
68
+ currentTaskTitle?: string | null
69
+ currentTaskProgress?: number | null
70
+ queuedCount?: number
71
+ completedCount?: number
72
+ context?: AgentContextStats | null
73
+ }) => void): () => void
74
+ /** channel 内消息投递通知(route 汇流点触发;AEP a2a.message 事件源) */
75
+ notifyMessage(message: A2AMessage): void
76
+ onMessage(fn: (message: A2AMessage) => void): () => void
77
+ /** 团队成员增/改/删通知(lead 自主管理或用户 REST;AEP agent.member 事件源) */
78
+ notifyMember(e: MemberChangeEvent): void
79
+ onMemberEvent(fn: (e: MemberChangeEvent) => void): () => void
80
+ /** 记忆写入通知(策展/主动沉淀;AEP memory.saved 事件源) */
81
+ notifyMemory(e: { agentId: string, scope: 'private' | 'shared', title: string, dedupKey: string }): void
82
+ onMemoryEvent(fn: (e: { agentId: string, scope: 'private' | 'shared', title: string, dedupKey: string }) => void): () => void
83
+ wakeScheduler(): void
84
+ }
85
+
86
+ /** 团队成员变更事件(lead 执行中自主管理成员或用户 REST 操作;AEP agent.member 载荷) */
87
+ export interface MemberChangeEvent {
88
+ op: 'added' | 'updated' | 'removed'
89
+ agentId: string
90
+ name: string
91
+ role: 'lead' | 'worker'
92
+ harness: string
93
+ enabled?: number
94
+ /** 实例 config(含 systemPromptPrefix 场景提示词;added/updated 时携带,removed 可空) */
95
+ config?: Record<string, unknown>
96
+ /** 操作发起方:'lead:<agentId>' 或 'user' */
97
+ by: string
98
+ reason?: string
99
+ }
100
+
101
+ /** Parts → 纯文本(text 片段拼接;记忆召回查询与回复收集共用) */
102
+ function partsToText(parts: Part[]): string {
103
+ return parts.map(p => ('text' in p ? p.text : '')).filter(Boolean).join('\n')
104
+ }
105
+
106
+ /**
107
+ * TaskEngine 结构契约(实现方 T4 task-engine.ts,同步签名)。
108
+ * 以接口而非具体类声明依赖,便于测试注入 fake 与集成装配真实引擎。
109
+ */
110
+ export interface TaskEngine {
111
+ create(input: {
112
+ channelId: string
113
+ creatorId: string
114
+ assigneeId: string
115
+ title: string
116
+ description?: string
117
+ parentId?: string
118
+ parts?: Part[]
119
+ }): WorkspaceTask
120
+ dispatch(
121
+ parent: WorkspaceTask,
122
+ input: { assigneeId: string, title: string, description?: string, parts?: Part[], routeReason?: string },
123
+ ): WorkspaceTask
124
+ transition(taskId: string, state: TaskState, by: string): WorkspaceTask
125
+ applyEvent(taskId: string, event: AgentEvent): void
126
+ list(channelId: string): WorkspaceTask[]
127
+ get(taskId: string): WorkspaceTask | undefined
128
+ complete(taskId: string, artifacts?: A2AArtifact[]): WorkspaceTask
129
+ reassign(taskId: string, toAgentId: string): WorkspaceTask
130
+ /** 修改待执行任务(title/description)+ 刷新 assignee 队列投递 */
131
+ updateTask(taskId: string, patch: { title?: string, description?: string }, by: string): WorkspaceTask
132
+ cancel(taskId: string, by: string): WorkspaceTask
133
+ onChildCompleted(child: WorkspaceTask): void
134
+ /** 断线重连重投:非终态任务无 pending assign 时向 assignee 重发(restore 用) */
135
+ redeliverAssign(taskId: string): WorkspaceTask
136
+ /** 单 agent 任务队列视图(待执行 FIFO / 执行中 / 已完成) */
137
+ queueViewOf(channelId: string, agentId: string): AgentTaskQueueView
138
+ /** 批量队列视图(一次查询聚合全 channel;调度快照热路径) */
139
+ queueViewsOf(channelId: string): Map<string, AgentTaskQueueView>
140
+ }
141
+
142
+ /**
143
+ * AgentRuntime 的结构契约(ChannelRuntime/SchedulerLoop 消费的最小接口)。
144
+ */
145
+ export interface AgentRuntimeLike {
146
+ readonly agentId: string
147
+ readonly role: 'lead' | 'worker'
148
+ readonly channelId: string
149
+ readonly name: string
150
+ enqueue(message: A2AMessage): void
151
+ getState(): 'idle' | 'busy' | 'stopped'
152
+ /** 实时状态视图(idle/busy/stopped + 当前任务 + 队列长度) */
153
+ getStatus(): AgentStatusView
154
+ /** 本 agent 的任务队列视图(待执行 FIFO / 执行中 / 已完成) */
155
+ getQueueView(): AgentTaskQueueView
156
+ abortCurrent(): void
157
+ wakeMailbox(): void
158
+ stop(): Promise<void>
159
+ /** 平台侧合成事件出口(如 SchedulerLoop 汇总成果);转发 ChannelBus.emit 走统一事件流 */
160
+ emitExternal(event: AgentEvent, fromAgentId?: string): void
161
+ /** 实时消息注入:busy 时通过 impl.steer 注入 omp 会话;idle 时入 mailbox 队列 */
162
+ injectSteer(message: A2AMessage): void
163
+ /** Agent 能力面(调度器执行成员管理决策用;AgentRuntime 始终提供) */
164
+ readonly workspace?: AgentWorkspace
165
+ }
166
+
167
+ export class AgentRuntime {
168
+ readonly agentId: string
169
+ readonly role: 'lead' | 'worker'
170
+ readonly channelId: string
171
+ readonly name: string
172
+ private state: 'idle' | 'busy' | 'stopped' = 'idle'
173
+ /** 回合失败重投计数(每消息;进程内存,重启由 resetConsuming 重新给机会) */
174
+ private runErrorRetries = new Map<string, number>()
175
+ /** 正在执行的任务 id(run 期间;空闲时 null) */
176
+ private currentTaskId: string | null = null
177
+ /** poll_messages 阻塞等待数(waitPending 活动计数;>0 = 有轮询在等,实时消息留信箱由其取走) */
178
+ private pollWaiters = 0
179
+ /** run 与 supervise 互斥锁(promise 链) */
180
+ private execLock: Promise<void> = Promise.resolve()
181
+ private abortController: AbortController | null = null
182
+ private loopPromise: Promise<void> | null = null
183
+ private started = false
184
+
185
+ constructor(
186
+ agent: AgentInfo,
187
+ private impl: AgentInterface,
188
+ private deps: {
189
+ mailbox: Mailbox
190
+ taskEngine: TaskEngine
191
+ bus: ChannelBus
192
+ workspace: AgentWorkspace
193
+ memory?: AgentMemory
194
+ },
195
+ ) {
196
+ this.agentId = agent.id
197
+ this.role = agent.role
198
+ this.channelId = agent.channelId
199
+ this.name = agent.name
200
+ }
201
+
202
+ /** 投递消息;idle 时立即唤醒消费 */
203
+ enqueue(message: A2AMessage): void {
204
+ this.deps.mailbox.enqueue(message)
205
+ }
206
+
207
+ getState(): 'idle' | 'busy' | 'stopped' {
208
+ return this.state
209
+ }
210
+
211
+ /** 实时状态视图:idle/busy/stopped + 当前任务 + 队列 + harness 上下文用量 */
212
+ getStatus(): AgentStatusView {
213
+ const queue = this.getQueueView()
214
+ const current = queue.current ?? (this.currentTaskId ? this.deps.taskEngine.get(this.currentTaskId) : undefined)
215
+ const context = this.impl.getContextStats?.() ?? undefined
216
+ return {
217
+ agentId: this.agentId,
218
+ channelId: this.channelId,
219
+ role: this.role,
220
+ name: this.name,
221
+ state: this.state,
222
+ currentTaskId: current?.id ?? null,
223
+ // 进度/标题透出:lead 观察 worker 是否在推进(progress 空闲/未上报时为 null)
224
+ currentTaskTitle: current?.title ?? null,
225
+ currentTaskProgress: current?.progress != null ? current.progress : null,
226
+ queuedCount: queue.queued.length,
227
+ completedCount: queue.completed.length,
228
+ ...(context ? { context } : {}),
229
+ }
230
+ }
231
+
232
+ /** 本 agent 的任务队列视图(自己的任务管理系统:待执行 FIFO / 执行中 / 已完成) */
233
+ getQueueView(): AgentTaskQueueView {
234
+ return this.deps.taskEngine.queueViewOf(this.channelId, this.agentId)
235
+ }
236
+
237
+ /** 中止当前 run(任务取消/Agent 移除时);空闲时无操作 */
238
+ abortCurrent(): void {
239
+ log.warn(`[AgentRuntime:${this.agentId}] abortCurrent 调用(state=${this.state})`)
240
+ this.abortController?.abort()
241
+ // supervise 回合同样可打断(调度器 cancel 路径 → LLM 回合真中止)
242
+ this.superviseController?.abort()
243
+ }
244
+
245
+ emitExternal(event: AgentEvent, fromAgentId?: string): void {
246
+ // 合成 source(monitor 依 metadata 归属 agent);平台侧产出与 harness 事件同流
247
+ const source: A2AMessage = {
248
+ messageId: randomUUID(),
249
+ contextId: this.channelId,
250
+ role: 'ROLE_AGENT',
251
+ parts: [],
252
+ metadata: { 'x-aw-from-agent': fromAgentId ?? this.agentId },
253
+ }
254
+ this.deps.bus.emit(event, source)
255
+ }
256
+
257
+ /**
258
+ * 实时注入策略(信箱优先,与主动轮询完全兼容):
259
+ * - poll_messages 等待中:任何实时消息留在 pending —— 等待中的轮询经 Mailbox
260
+ * 到信回调毫秒级取走(读即取=已读),零打断、不与轮询竞争唯一所有权
261
+ * - agent 间协作消息(from-agent):同样走信箱 —— turn 结束后消费循环按 peer
262
+ * 回合处理(require_reply 触发语义/回执关联完整)。steer 注入 omp 会话会让
263
+ * 其把排队消息后的工具调用标记 "Skipped due to queued user message",
264
+ * 中断 poll_messages 长等待并污染执行流(实测故障源)
265
+ * - 仅人类紧急直发(immediate + from-label,无 from-agent)保留 steer 同轮注入:
266
+ * 紧急人工打断是唯一值得中断会话的场景
267
+ */
268
+ injectSteer(message: A2AMessage): void {
269
+ if (this.state !== 'busy' || !this.impl.steer) return
270
+ // ① 轮询等待中:留 pending 给 poll_messages(毫秒级取走并标记已读)
271
+ if (this.pollWaiters > 0) return
272
+ // ② agent 间协作消息:信箱优先(turn 结束 peer 回合处理)
273
+ const from = message.metadata?.['x-aw-from-agent']
274
+ if (typeof from === 'string' && from.length > 0) return
275
+ // ③ 其余(人类紧急直发):原有 steer 注入路径
276
+ if (!this.deps.mailbox.claim(message.messageId)) return
277
+ const text = message.parts
278
+ .map((p) => {
279
+ if ('text' in p) return p.text
280
+ if ('data' in p) return JSON.stringify(p.data)
281
+ return ''
282
+ })
283
+ .join('\n')
284
+ const fromId = (message.metadata?.['x-aw-from-agent'] as string | undefined) ?? 'system'
285
+ const lines = [`[实时消息 from ${fromId}]: ${text}`]
286
+ if (message.metadata?.['x-aw-require-reply'] === 'true') {
287
+ lines.push(
288
+ `[系统触发器] 本消息要求回复(reply_to=${message.messageId})。`,
289
+ `请处理消息中的需求,随后用 send_message_to_agent 回复发送者 ${fromId}:`,
290
+ `参数 message=执行结果+对方所需内容, in_reply_to=${message.messageId},`,
291
+ `require_reply=仅当你还需要对方进一步响应时才设 true。`,
292
+ )
293
+ }
294
+ this.impl.steer(lines.join('\n'))
295
+ .then((mode) => {
296
+ if (mode === 'steer') {
297
+ // 确认注入流式会话 → 消费落定(at-least-once:进程崩溃由 resetConsuming 兜底)
298
+ this.deps.mailbox.markConsumed(message.messageId)
299
+ }
300
+ else {
301
+ // deferred:释放认领回 pending,poll_messages(250ms 兜底重查)或
302
+ // 本回合结束后的消费循环(FIFO)接管,消息必达不丢失
303
+ this.releaseSteerClaim(message.messageId)
304
+ }
305
+ })
306
+ .catch((err) => {
307
+ log.error(`[AgentRuntime:${this.agentId}] steer 失败(释放认领回 pending 待循环处理):`, err)
308
+ this.releaseSteerClaim(message.messageId)
309
+ })
310
+ }
311
+
312
+ /** 释放 steer 认领:consuming → pending + 唤醒 dequeue 门闩与到信等待方 */
313
+ private releaseSteerClaim(messageId: string): void {
314
+ if (this.deps.mailbox.requeue(messageId)) {
315
+ this.deps.mailbox.wake()
316
+ }
317
+ }
318
+
319
+ /**
320
+ * 长轮询未消费消息(poll_messages host 工具用):
321
+ * 250ms 兜底重查 + Mailbox 到信回调即时唤醒——消息到达后毫秒级返回,
322
+ * 不再每秒盲查。不改消息状态(peek 只读);消费语义由调用方(poll 读即取)决定。
323
+ * pollWaiters 计数暴露"轮询等待中"状态:injectSteer 据此把实时消息留在信箱
324
+ * 由本方法取走(不打断会话、与主动轮询兼容)。
325
+ */
326
+ async waitPending(limit: number, waitMs: number): Promise<A2AMessage[]> {
327
+ this.pollWaiters += 1
328
+ try {
329
+ const deadline = Date.now() + Math.max(0, waitMs)
330
+ for (;;) {
331
+ const msgs = await this.deps.mailbox.peek(limit)
332
+ if (msgs.length > 0 || Date.now() >= deadline) return msgs
333
+ const { promise, resolve } = Promise.withResolvers<unknown>()
334
+ const off = this.deps.mailbox.onArrival(() => resolve(undefined))
335
+ const timer = setTimeout(() => resolve(undefined), 250)
336
+ await promise
337
+ clearTimeout(timer)
338
+ off()
339
+ }
340
+ }
341
+ finally {
342
+ this.pollWaiters -= 1
343
+ }
344
+ }
345
+
346
+ /** 启动消费循环 */
347
+ start(): void {
348
+ if (this.started) return
349
+ this.started = true
350
+ this.state = 'idle'
351
+ this.loopPromise = this.consumeLoop()
352
+ }
353
+
354
+ /** 停止:中断当前 run + 等当前事件流结束 + dispose impl(杀子进程等) */
355
+ async stop(): Promise<void> {
356
+ log.warn(`[AgentRuntime:${this.agentId}] runtime.stop() 调用(卸载/停用)`)
357
+ this.state = 'stopped'
358
+ this.abortController?.abort()
359
+ this.deps.mailbox.close()
360
+ // 状态广播:前端经 WS agent.status 实时反映 stopped
361
+ this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'stopped', ...this.queueContext() })
362
+ await this.loopPromise
363
+ // 清理 impl 持有的资源(omp 子进程等);容错:impl.dispose 可能不存在
364
+ try {
365
+ await this.impl.dispose?.()
366
+ }
367
+ catch (err) {
368
+ log.error(`[AgentRuntime:${this.agentId}] dispose 失败:`, err)
369
+ }
370
+ }
371
+
372
+ /** 唤醒 mailbox(供 manager 在 taskEngine 直接落库投递后唤醒消费) */
373
+ wakeMailbox(): void {
374
+ this.deps.mailbox.wake()
375
+ }
376
+
377
+ /**
378
+ * 状态重广播:调度器收口(complete/cancel 等不经 processMessage 的终态迁移)
379
+ * 直接改动了本 agent 的队列上下文(current/completed),重新广播 agent.status,
380
+ * 前端实时反映 lead 判定完成后的最新状态(不刷新即可见)。
381
+ */
382
+ refreshStatus(): void {
383
+ this.deps.bus.notifyAgent({ agentId: this.agentId, state: this.state, ...this.queueContext() })
384
+ }
385
+
386
+ /** harness 进程资源信息(运行时资源监控;进程内 harness 无外部进程 → null) */
387
+ getProcessInfo(): { pid: number, alive: boolean, command: string } | null {
388
+ return this.impl.getProcessInfo?.() ?? null
389
+ }
390
+
391
+ /**
392
+ * 强制终止 harness 进程(不等优雅退出)。
393
+ * 调用方(manager terminateRuntimeProcess)终止后随即 stop 本运行时。
394
+ */
395
+ killProcess(): void {
396
+ this.impl.killProcess?.()
397
+ }
398
+
399
+ /** harness 进程存活校准(manager sweeper 周期性调用;休眠/强杀后校准 alive 失真;异常不抛出) */
400
+ reconcileProcess(): void {
401
+ try {
402
+ this.impl.reconcileProcess?.()
403
+ }
404
+ catch (err) {
405
+ log.error(`[AgentRuntime:${this.agentId}] 进程存活校准失败:`, err)
406
+ }
407
+ }
408
+
409
+ /** 暴露 TaskEngine(供 SchedulerLoop 收集快照与执行调度决策) */
410
+ get taskEngine(): TaskEngine {
411
+ return this.deps.taskEngine
412
+ }
413
+
414
+ /** 暴露 AgentWorkspace(供 SchedulerLoop 执行 lead 成员管理决策) */
415
+ get workspace(): AgentWorkspace {
416
+ return this.deps.workspace
417
+ }
418
+
419
+ /**
420
+ * lead 调度决策(供 SchedulerLoop 调用):转发 impl.supervise。
421
+ * 未实现 supervise 时返回 null(调用方回退内置规则引擎);
422
+ * 与 run 的互斥由调用方通过 withExecLock 保证。
423
+ */
424
+ /** 当前 supervise 回合的控制器(abortCurrent 经此打断 LLM 调度回合) */
425
+ private superviseController: AbortController | null = null
426
+
427
+ async supervise(snapshot: SupervisionSnapshot): Promise<SupervisionDecision[] | null> {
428
+ if (!this.impl.supervise) return null
429
+ // lead 调度记忆:非终态/失败任务标题 + 成员名构造查询;touch:false 防 tick 通胀
430
+ let memoryBlock: string | undefined
431
+ try {
432
+ const query = [
433
+ ...snapshot.tasks.filter(t => t.state === 'SUBMITTED' || t.state === 'FAILED' || t.state === 'WAITING').map(t => t.title),
434
+ ...snapshot.members.map(m => m.name),
435
+ ].join(' ')
436
+ memoryBlock = (await this.deps.memory?.recall(query, { touch: false })) ?? undefined
437
+ }
438
+ catch (err) {
439
+ log.error(`[AgentRuntime:${this.agentId}] supervise 记忆召回失败:`, err)
440
+ }
441
+ const controller = new AbortController()
442
+ this.superviseController = controller
443
+ const ctx: AgentRunContext = {
444
+ agentId: this.agentId,
445
+ channelId: this.channelId,
446
+ role: this.role,
447
+ workspace: this.deps.workspace,
448
+ signal: controller.signal,
449
+ memory: memoryBlock,
450
+ }
451
+ try {
452
+ return await this.impl.supervise(snapshot, ctx, { signal: controller.signal })
453
+ }
454
+ finally {
455
+ if (this.superviseController === controller) this.superviseController = null
456
+ // 调度回合落定:lead 的 supervise 是上下文膨胀大户,同样走 post-settle 压缩检查
457
+ this.maybePostSettle()
458
+ }
459
+ }
460
+
461
+ /**
462
+ * 平台侧任务记忆沉淀(调度器直接执行决策的收口路径):
463
+ * lead 经 supervise 决策 complete/cancel 任务时不经过 processMessage,
464
+ * 由 SchedulerLoop 调用此方法补齐终态 harvest(与 worker 路径同源)。
465
+ */
466
+ async recordTaskMemory(task: WorkspaceTask): Promise<void> {
467
+ await this.deps.memory?.recordTaskOutcome(task)
468
+ }
469
+
470
+ /** run/supervise 互斥执行(promise 链;供消费循环与 SchedulerLoop 串行化) */
471
+ withExecLock<T>(fn: () => Promise<T>): Promise<T> {
472
+ const prev = this.execLock
473
+ let release!: () => void
474
+ this.execLock = new Promise<void>((r) => {
475
+ release = r
476
+ })
477
+ return (async () => {
478
+ await prev
479
+ try {
480
+ return await fn()
481
+ }
482
+ finally {
483
+ release()
484
+ }
485
+ })()
486
+ }
487
+
488
+ /** 消费循环:空闲自动接取,执行中不打断 */
489
+ private async consumeLoop(): Promise<void> {
490
+ while (this.state !== 'stopped') {
491
+ const msg = await this.deps.mailbox.dequeue()
492
+ if (this.getState() === 'stopped' || msg === null) break
493
+ // 单条 run 抛错不阻塞下一条
494
+ try {
495
+ await this.withExecLock(() => this.processMessage(msg))
496
+ }
497
+ catch (err) {
498
+ log.error(`[AgentRuntime:${this.agentId}] run 失败:`, err)
499
+ }
500
+ }
501
+ }
502
+
503
+ private async processMessage(msg: A2AMessage): Promise<void> {
504
+ const taskId = this.taskIdOf(msg)
505
+ // 过期任务投递检查:任务已终态(cancel/reassign 后残留的旧 assign)→ 跳过执行,
506
+ // 否则 worker 会对着已取消任务的旧投递真的跑一轮 harness。
507
+ if (msg.metadata?.['x-aw-task-kind'] === 'assign' && taskId) {
508
+ const task = this.deps.taskEngine.get(taskId)
509
+ if (!task || TERMINAL_TASK_STATES[task.state]) {
510
+ this.deps.mailbox.markConsumed(msg.messageId)
511
+ return
512
+ }
513
+ }
514
+ this.state = 'busy'
515
+ this.currentTaskId = taskId ?? null
516
+ this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'busy', ...this.queueContext() })
517
+ // 回合失败标记(须在 try 外声明,finally 依据它决定重投还是消费)
518
+ let sawRunError = false
519
+ try {
520
+ // 任务消息联动:assign → WORKING(自动接取;状态事件由 TaskEngine transition hooks 广播)
521
+ // 仅 SUBMITTED/ASSIGNED 自动接取:WAITING(已有子任务)的任务由 SchedulerLoop/子任务汇总推进,
522
+ // 此处不得把父任务从 WAITING 翻回 WORKING(否则父任务在子任务执行期间虚挂 WORKING,
523
+ // 会被 stall 检测误判为停滞而 cancel)。
524
+ if (msg.metadata?.['x-aw-task-kind'] === 'assign' && taskId) {
525
+ const task = this.deps.taskEngine.get(taskId)
526
+ if (task && (task.state === 'SUBMITTED' || task.state === 'ASSIGNED')) {
527
+ await this.deps.taskEngine.transition(taskId, 'WORKING', this.agentId)
528
+ }
529
+ }
530
+ // 每次 run 新建 AbortController;abort 后事件流终止
531
+ this.abortController = new AbortController()
532
+ // 记忆召回(异常不阻塞):查询=消息原文(title 首词天然显著)+ 任务关联加权
533
+ let memoryBlock: string | undefined
534
+ try {
535
+ memoryBlock = (await this.deps.memory?.recall(partsToText(msg.parts), {
536
+ relatedTaskIds: this.relatedTaskIdsOf(taskId),
537
+ })) ?? undefined
538
+ }
539
+ catch (err) {
540
+ log.error(`[AgentRuntime:${this.agentId}] 记忆召回失败:`, err)
541
+ }
542
+ const request: AgentRunRequest = this.toRequest(msg, memoryBlock)
543
+ const ctx: AgentRunContext = {
544
+ agentId: this.agentId,
545
+ channelId: msg.contextId,
546
+ role: this.role,
547
+ workspace: this.deps.workspace,
548
+ signal: this.abortController.signal,
549
+ }
550
+ // 补入产出者 agentId(monitor 据此归属事件;不改原 msg,用浅拷贝)
551
+ const enrichedSource = { ...msg, metadata: { ...msg.metadata, 'x-aw-producing-agent': this.agentId } }
552
+ // 回复文本收集(V9:omp 不产 message 事件,聚合三类源——message 事件 / status.message / 终态 artifact 'output')
553
+ let replyText = ''
554
+ const cap = (text: string): void => {
555
+ if (replyText.length < 400) replyText += text.slice(0, 400 - replyText.length)
556
+ }
557
+ try {
558
+ for await (const event of this.impl.run(request, ctx)) {
559
+ this.deps.bus.emit(event, enrichedSource)
560
+ // LLM 流式增量:只走事件流(AEP agent.delta),不进任务引擎/交付兜底管道
561
+ if (event.kind === 'delta') continue
562
+ if (event.kind === 'error') sawRunError = true
563
+ if (taskId) await this.deps.taskEngine.applyEvent(taskId, event)
564
+ if (event.kind === 'message') cap(partsToText(event.message.parts))
565
+ else if (event.kind === 'status' && event.status.message) cap(partsToText(event.status.message.parts))
566
+ else if (event.kind === 'artifact' && event.artifact.name === 'output') cap(partsToText(event.artifact.parts))
567
+ }
568
+ }
569
+ catch (err) {
570
+ // run 生成器抛错(如 omp 子进程 spawn 失败):按回合失败走重投,不外抛断循环
571
+ sawRunError = true
572
+ log.error(`[AgentRuntime:${this.agentId}] 回合异常:`, err)
573
+ }
574
+ // 交付兜底(harness 回合结束 ≠ 任务完成):
575
+ // - 回合产出过实质 artifact(LLM 完成了工作但跳过 complete_task 工具)→ 隐式完成,
576
+ // 交付物即回合规避的输出,平台代为收口(进度 100)。
577
+ // - 无任何产出(LLM 空转)→ FAILED 交给调度器 retry/reassign。
578
+ // 仅 worker 的 assign 执行消息生效:lead 由 supervise 协调;WAITING 父任务不属此列。
579
+ if (taskId && this.role === 'worker' && msg.metadata?.['x-aw-task-kind'] === 'assign') {
580
+ const after = this.deps.taskEngine.get(taskId)
581
+ if (after && after.assigneeId === this.agentId && after.state === 'WORKING') {
582
+ const deliverable = after.artifacts.find(a => a.name !== 'input' && a.parts.some(p => ('text' in p ? p.text.trim().length : 1) > 0))
583
+ if (deliverable) {
584
+ const completed = await this.deps.taskEngine.complete(taskId)
585
+ this.emitExternal({
586
+ kind: 'status',
587
+ status: {
588
+ state: 'COMPLETED',
589
+ message: {
590
+ messageId: randomUUID(),
591
+ contextId: this.channelId,
592
+ role: 'ROLE_AGENT',
593
+ parts: [{ text: `任务 ${taskId} 回合已产出交付物但未调用完成工具,平台隐式收口为 COMPLETED` }],
594
+ },
595
+ timestamp: new Date().toISOString(),
596
+ },
597
+ })
598
+ // 子任务隐式完成 → 通知父任务(lead 汇总/WAITING→WORKING 接续):
599
+ // 与 manager.completeTask 的显式收口同构,否则父任务 WAITING 永挂
600
+ // (无 child-completed 事件、父任务不翻转,lead 无感知)。
601
+ if (completed.parentId) {
602
+ this.deps.taskEngine.onChildCompleted(completed)
603
+ const parent = this.deps.taskEngine.get(completed.parentId)
604
+ if (parent) this.deps.bus.wakeScheduler()
605
+ }
606
+ }
607
+ else {
608
+ await this.deps.taskEngine.transition(taskId, 'FAILED', this.agentId)
609
+ this.emitExternal({
610
+ kind: 'status',
611
+ status: {
612
+ state: 'FAILED',
613
+ message: {
614
+ messageId: randomUUID(),
615
+ contextId: this.channelId,
616
+ role: 'ROLE_AGENT',
617
+ parts: [{ text: `任务 ${taskId} 执行结束但无交付(harness 回合结束未产出),标记 FAILED 待重试` }],
618
+ },
619
+ timestamp: new Date().toISOString(),
620
+ },
621
+ })
622
+ }
623
+ }
624
+ }
625
+
626
+ // 记忆沉淀:终态任务 harvest;无 taskId 的点对点消息记协作(异常不阻塞)
627
+ if (this.deps.memory) {
628
+ try {
629
+ const task = taskId ? this.deps.taskEngine.get(taskId) : undefined
630
+ if (task && TERMINAL_TASK_STATES[task.state]) {
631
+ await this.deps.memory.recordTaskOutcome(task)
632
+ }
633
+ else if (!taskId) {
634
+ const fromAgentId = (msg.metadata?.['x-aw-from-agent'] as string | undefined) ?? null
635
+ if (fromAgentId) await this.deps.memory.recordPeerExchange(msg, replyText)
636
+ }
637
+ }
638
+ catch (err) {
639
+ log.error(`[AgentRuntime:${this.agentId}] 记忆写入失败:`, err)
640
+ }
641
+ }
642
+ }
643
+ finally {
644
+ this.abortController = null
645
+ this.currentTaskId = null
646
+ if (this.state === 'busy') {
647
+ this.state = 'idle'
648
+ this.deps.bus.notifyAgent({ agentId: this.agentId, state: 'idle', ...this.queueContext() })
649
+ }
650
+ // 回合失败(harness 错误/停滞看门狗中止/子进程异常):重投消息而非静默消费,
651
+ // 内容不丢,重试回合(通常已是全新子进程)再处理;每消息最多重投 2 次防毒消息死循环。
652
+ // 任务已终态(取消/收口后 abort 让回合报错)则不再重投 —— 消息依任务终态
653
+ // 由调度器 reassign/新 assign 驱动,重投只会空转(启动即被终态检查消费)。
654
+ const taskNow = taskId ? this.deps.taskEngine.get(taskId) : undefined
655
+ const taskDone = !!taskNow && TERMINAL_TASK_STATES[taskNow.state]
656
+ if (sawRunError && !taskDone && (this.runErrorRetries.get(msg.messageId) ?? 0) < 2
657
+ && this.deps.mailbox.requeue(msg.messageId)) {
658
+ const attempt = (this.runErrorRetries.get(msg.messageId) ?? 0) + 1
659
+ this.runErrorRetries.set(msg.messageId, attempt)
660
+ this.emitExternal({
661
+ kind: 'status',
662
+ status: {
663
+ state: 'WORKING',
664
+ message: {
665
+ messageId: randomUUID(),
666
+ contextId: this.channelId,
667
+ role: 'ROLE_AGENT',
668
+ parts: [{ text: `消息 ${msg.messageId.slice(0, 8)} 回合失败,已重投信箱待重试(第 ${attempt} 次)` }],
669
+ },
670
+ timestamp: new Date().toISOString(),
671
+ },
672
+ })
673
+ }
674
+ else {
675
+ this.runErrorRetries.delete(msg.messageId)
676
+ this.deps.mailbox.markConsumed(msg.messageId)
677
+ }
678
+ // 回合落定:信箱空 → 后台压缩检查(post-settle 路径;impl 自守卫不阻塞)
679
+ this.maybePostSettle()
680
+ }
681
+ }
682
+
683
+ /** 状态通知的队列上下文(实时:当前任务/待执行数/已完成数/harness 上下文用量) */
684
+ private queueContext(): Pick<AgentStatusView, 'currentTaskId' | 'currentTaskTitle' | 'currentTaskProgress' | 'queuedCount' | 'completedCount'> & { context?: AgentContextStats | null } {
685
+ const status = this.getStatus()
686
+ return {
687
+ currentTaskId: status.currentTaskId,
688
+ currentTaskTitle: status.currentTaskTitle,
689
+ currentTaskProgress: status.currentTaskProgress,
690
+ queuedCount: status.queuedCount,
691
+ completedCount: status.completedCount,
692
+ context: status.context ?? null,
693
+ }
694
+ }
695
+
696
+ /**
697
+ * 任务关联集(自身+父+兄弟,≤20):related-task boost 数据源。
698
+ * 同父兄弟任务的记忆(前几个子任务做了什么)在引子中必然置顶——
699
+ * 纯内存 id 判断,零检索开销。
700
+ */
701
+ private relatedTaskIdsOf(taskId: string | undefined): string[] | undefined {
702
+ if (!taskId) return undefined
703
+ const task = this.deps.taskEngine.get(taskId)
704
+ if (!task) return undefined
705
+ const ids = new Set<string>([taskId])
706
+ if (task.parentId) {
707
+ ids.add(task.parentId)
708
+ for (const t of this.deps.taskEngine.list(this.channelId)) {
709
+ if (t.parentId === task.parentId) ids.add(t.id)
710
+ if (ids.size >= 20) break
711
+ }
712
+ }
713
+ return [...ids]
714
+ }
715
+
716
+ /**
717
+ * post-settle 压缩检查:仅信箱无排队消息时触发(排队消息的 pre-prompt gate 兜底)。
718
+ * impl 自守卫(回合间隙才压缩、异常不抛出);本方法自身也不阻塞消费循环。
719
+ */
720
+ private maybePostSettle(): void {
721
+ if (!this.impl.onTurnSettled) return
722
+ void this.deps.mailbox.peek(1)
723
+ .then((pending) => {
724
+ if (pending.length > 0) return undefined
725
+ return this.impl.onTurnSettled?.()
726
+ })
727
+ .catch(() => {})
728
+ }
729
+
730
+ private toRequest(msg: A2AMessage, memory?: string): AgentRunRequest {
731
+ return {
732
+ message: msg,
733
+ taskId: msg.taskId,
734
+ contextId: msg.contextId,
735
+ fromAgentId: (msg.metadata?.['x-aw-from-agent'] as string | undefined) ?? null,
736
+ toAgentId: this.agentId,
737
+ memory,
738
+ }
739
+ }
740
+
741
+ private taskIdOf(msg: A2AMessage): string | undefined {
742
+ return msg.taskId ?? (msg.metadata?.['x-aw-task-id'] as string | undefined)
743
+ }
744
+ }