agentworkshop 0.7.6 → 0.7.7

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 (517) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +1 -1
  2. package/.output/.AgentWorkShop/prompts/host-tools.json +1 -1
  3. package/.output/nitro.json +1 -1
  4. package/.output/public/_nuxt/{rzGB_ojX.js → 3612gD2V.js} +2 -2
  5. package/.output/public/_nuxt/8eIQAVlb.js +1 -0
  6. package/.output/public/_nuxt/Ah9qOv1m.js +1 -0
  7. package/.output/public/_nuxt/{DdPeifHR.js → B4Fia4FB.js} +1 -1
  8. package/.output/public/_nuxt/B7aqqzkY.js +1 -0
  9. package/.output/public/_nuxt/BJ-fxrSw.js +1 -0
  10. package/.output/public/_nuxt/{DPDqAD1e.js → BSXx2vqR.js} +1 -1
  11. package/.output/public/_nuxt/{CdSgfcYR.js → BVZjSVs2.js} +1 -1
  12. package/.output/public/_nuxt/{DP6bdyIp.js → BVzDoF8t.js} +1 -1
  13. package/.output/public/_nuxt/BYL0Rjqj.js +7 -0
  14. package/.output/public/_nuxt/{CXmkVXS5.js → BjVLsC3M.js} +1 -1
  15. package/.output/public/_nuxt/{7ZABjMRh2.js → BkfchkK62.js} +1 -1
  16. package/.output/public/_nuxt/BnVoQ74r.js +1 -0
  17. package/.output/public/_nuxt/Bnp4vIAf.js +1 -0
  18. package/.output/public/_nuxt/BsMpJf7S.js +70 -0
  19. package/.output/public/_nuxt/{Z8k0uMSI.js → Bt_HDizI.js} +1 -1
  20. package/.output/public/_nuxt/Bu-P92Pe.js +18 -0
  21. package/.output/public/_nuxt/ButLXkjo.js +2 -0
  22. package/.output/public/_nuxt/C-GarxYC.js +1 -0
  23. package/.output/public/_nuxt/{D8DDDzV62.js → C2iWjzEC2.js} +1 -1
  24. package/.output/public/_nuxt/{HWXLx5Hz.js → C8dxXc6K.js} +5 -5
  25. package/.output/public/_nuxt/CGdPdJPP.js +1 -0
  26. package/.output/public/_nuxt/{CyygA0q4.js → CQiKcuoG.js} +4 -4
  27. package/.output/public/_nuxt/{CN7Zh8GQ.js → CRGlf1Gb.js} +1 -1
  28. package/.output/public/_nuxt/{DSBfvCi5.js → CblLEiCZ.js} +7 -7
  29. package/.output/public/_nuxt/Cd15nPnG2.js +1 -0
  30. package/.output/public/_nuxt/{OwJ1LJkF.js → CsCpu2Zh.js} +1 -1
  31. package/.output/public/_nuxt/CvbHIGQY2.js +1 -0
  32. package/.output/public/_nuxt/Cyk3du4K2.js +1 -0
  33. package/.output/public/_nuxt/{DVQAz9WI.js → D4qXvjuV.js} +2 -2
  34. package/.output/public/_nuxt/{CfIXY-ET.js → DCEyMaN-.js} +1 -1
  35. package/.output/public/_nuxt/{BFYNhG9S.js → DCXIGxzT.js} +1 -1
  36. package/.output/public/_nuxt/{B9aPoQvt.js → DM8DS9MA.js} +1 -1
  37. package/.output/public/_nuxt/{ChnfyQHz.js → DNzaswei.js} +1 -1
  38. package/.output/public/_nuxt/{CrFGZYVB2.js → DYZBdSSg2.js} +1 -1
  39. package/.output/public/_nuxt/{dObsRdSQ.js → DZk24ego.js} +1 -1
  40. package/.output/public/_nuxt/DeYsUzhr.js +1 -0
  41. package/.output/public/_nuxt/Dk6pq9JB2.js +1 -0
  42. package/.output/public/_nuxt/{ByGNWgAr.js → Do88WZG2.js} +3 -3
  43. package/.output/public/_nuxt/{R_WxTozV2.js → Du-eSpo2.js} +1 -1
  44. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +1 -0
  45. package/.output/public/_nuxt/{Bsc69G4x.js → VnIWJ0ts.js} +3 -3
  46. package/.output/public/_nuxt/_id_.BzKMZnLe.css +1 -0
  47. package/.output/public/_nuxt/_id_.CbpDAWRh.css +1 -0
  48. package/.output/public/_nuxt/{_wsId_.DET_GinP.css → _wsId_.COUzMXpP.css} +1 -1
  49. package/.output/public/_nuxt/agents.BlejnOOC.css +1 -0
  50. package/.output/public/_nuxt/builds/latest.json +1 -1
  51. package/.output/public/_nuxt/builds/meta/14df171d-89cb-43ec-ad6f-9df72d6da7f5.json +1 -0
  52. package/.output/public/_nuxt/daq.zZ8GR433.css +1 -0
  53. package/.output/public/_nuxt/{default.D17kXlD6.css → default.V3_hUJq1.css} +1 -1
  54. package/.output/public/_nuxt/{B4GHHF6d2.js → fQUs58kX2.js} +1 -1
  55. package/.output/public/_nuxt/p7wSGMtc.js +1 -0
  56. package/.output/public/_nuxt/tRBT-plo.js +1 -0
  57. package/.output/server/chunks/_/SearchOutlined.mjs +4 -4
  58. package/.output/server/chunks/_/SearchOutlined.mjs.map +1 -1
  59. package/.output/server/chunks/_/character-asset.repo.mjs +3 -6
  60. package/.output/server/chunks/_/character-asset.repo.mjs.map +1 -1
  61. package/.output/server/chunks/_/host-bindings.mjs +1 -1
  62. package/.output/server/chunks/_/nitro.mjs +4967 -2035
  63. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  64. package/.output/server/chunks/_/scene-layout.repo.mjs +4 -10
  65. package/.output/server/chunks/_/scene-layout.repo.mjs.map +1 -1
  66. package/.output/server/chunks/build/{Col-D7fjGDF6.mjs → Col-biaNnEPf.mjs} +2 -2
  67. package/.output/server/chunks/build/{Col-D7fjGDF6.mjs.map → Col-biaNnEPf.mjs.map} +1 -1
  68. package/.output/server/chunks/build/{OmpTerminalPanel-B_SYhmgb.mjs → OmpTerminalPanel-COphA1br.mjs} +20 -19
  69. package/.output/server/chunks/build/OmpTerminalPanel-COphA1br.mjs.map +1 -0
  70. package/.output/server/chunks/build/{TownView-Bl8Gkcxi.mjs → TownView-B5KifIaT.mjs} +4 -4
  71. package/.output/server/chunks/build/{TownView-Bl8Gkcxi.mjs.map → TownView-B5KifIaT.mjs.map} +1 -1
  72. package/.output/server/chunks/build/{_id_-GnRJPykX.mjs → _id_-C-ewLgfl.mjs} +119 -119
  73. package/.output/server/chunks/build/{_id_-GnRJPykX.mjs.map → _id_-C-ewLgfl.mjs.map} +1 -1
  74. package/.output/server/chunks/build/{_id_-CWLFGZjV.mjs → _id_-Ct4Jhvl1.mjs} +42 -38
  75. package/.output/server/chunks/build/_id_-Ct4Jhvl1.mjs.map +1 -0
  76. package/.output/server/chunks/build/{_wsId_-BhQMjyHG.mjs → _wsId_-CanI_6Su.mjs} +591 -53
  77. package/.output/server/chunks/build/{_wsId_-BhQMjyHG.mjs.map → _wsId_-CanI_6Su.mjs.map} +1 -1
  78. package/.output/server/chunks/build/{agents-D4l1icvn.mjs → agents-DSOptxXA.mjs} +146 -91
  79. package/.output/server/chunks/build/agents-DSOptxXA.mjs.map +1 -0
  80. package/.output/server/chunks/build/{alert-gH-s7yIh.mjs → alert-qJnjyRcP.mjs} +3 -3
  81. package/.output/server/chunks/build/{alert-gH-s7yIh.mjs.map → alert-qJnjyRcP.mjs.map} +1 -1
  82. package/.output/server/chunks/build/{button-BhbX5ACI.mjs → button-DEcZFcqN.mjs} +3 -3
  83. package/.output/server/chunks/build/{button-BhbX5ACI.mjs.map → button-DEcZFcqN.mjs.map} +1 -1
  84. package/.output/server/chunks/build/{card-l4BbX67w.mjs → card-Dipvaykh.mjs} +5 -5
  85. package/.output/server/chunks/build/{card-l4BbX67w.mjs.map → card-Dipvaykh.mjs.map} +1 -1
  86. package/.output/server/chunks/build/{channel-templates-DqjtC-R0.mjs → channel-templates-BK0KuPOd.mjs} +13 -12
  87. package/.output/server/chunks/build/channel-templates-BK0KuPOd.mjs.map +1 -0
  88. package/.output/server/chunks/build/{checkbox-BF11p3dH.mjs → checkbox-dzcpU_Cd.mjs} +4 -4
  89. package/.output/server/chunks/build/{checkbox-BF11p3dH.mjs.map → checkbox-dzcpU_Cd.mjs.map} +1 -1
  90. package/.output/server/chunks/build/{daq-BOgpn9sl.mjs → daq-D9RA_uze.mjs} +102 -102
  91. package/.output/server/chunks/build/{daq-BOgpn9sl.mjs.map → daq-D9RA_uze.mjs.map} +1 -1
  92. package/.output/server/chunks/build/dcw-BTM5YU-B.mjs +1 -1
  93. package/.output/server/chunks/build/{default-CKJWhkot.mjs → default-BfWGTlbj.mjs} +81 -23
  94. package/.output/server/chunks/build/{default-CKJWhkot.mjs.map → default-BfWGTlbj.mjs.map} +1 -1
  95. package/.output/server/chunks/build/{drawer-CVValqoh.mjs → drawer-Cmh90erI.mjs} +3 -3
  96. package/.output/server/chunks/build/{drawer-CVValqoh.mjs.map → drawer-Cmh90erI.mjs.map} +1 -1
  97. package/.output/server/chunks/build/{dropdown-ByCsEWlQ.mjs → dropdown-CGQ0KAzA.mjs} +2 -2
  98. package/.output/server/chunks/build/{dropdown-ByCsEWlQ.mjs.map → dropdown-CGQ0KAzA.mjs.map} +1 -1
  99. package/.output/server/chunks/build/{dropdown-Dex8PXu6.mjs → dropdown-vhn1NPFs.mjs} +4 -4
  100. package/.output/server/chunks/build/{dropdown-Dex8PXu6.mjs.map → dropdown-vhn1NPFs.mjs.map} +1 -1
  101. package/.output/server/chunks/build/{input-number-BBlRoAJ7.mjs → input-number-Bd55elNN.mjs} +5 -5
  102. package/.output/server/chunks/build/{input-number-BBlRoAJ7.mjs.map → input-number-Bd55elNN.mjs.map} +1 -1
  103. package/.output/server/chunks/build/{input--KMeLYqZ.mjs → input-sf_BT6o6.mjs} +3 -3
  104. package/.output/server/chunks/build/{input--KMeLYqZ.mjs.map → input-sf_BT6o6.mjs.map} +1 -1
  105. package/.output/server/chunks/build/logs-Dyk0I2I9.mjs +1 -1
  106. package/.output/server/chunks/build/{menu-xN-SXb9Q.mjs → menu-WCrlpYVh.mjs} +3 -3
  107. package/.output/server/chunks/build/{menu-xN-SXb9Q.mjs.map → menu-WCrlpYVh.mjs.map} +1 -1
  108. package/.output/server/chunks/build/{modal-DrCOcjrl.mjs → modal-yvUquPj5.mjs} +4 -4
  109. package/.output/server/chunks/build/{modal-DrCOcjrl.mjs.map → modal-yvUquPj5.mjs.map} +1 -1
  110. package/.output/server/chunks/build/{monitor-KW8WLOJd.mjs → monitor-MIOvsyLa.mjs} +21 -21
  111. package/.output/server/chunks/build/{monitor-KW8WLOJd.mjs.map → monitor-MIOvsyLa.mjs.map} +1 -1
  112. package/.output/server/chunks/build/pages-DR2bzczM.mjs +1 -1
  113. package/.output/server/chunks/build/{plugins-B-ZNey0Z.mjs → plugins-DnOBIWGg.mjs} +7 -7
  114. package/.output/server/chunks/build/{plugins-B-ZNey0Z.mjs.map → plugins-DnOBIWGg.mjs.map} +1 -1
  115. package/.output/server/chunks/build/{popconfirm-C5H1Qoh3.mjs → popconfirm-CRaHcz5O.mjs} +4 -4
  116. package/.output/server/chunks/build/{popconfirm-C5H1Qoh3.mjs.map → popconfirm-CRaHcz5O.mjs.map} +1 -1
  117. package/.output/server/chunks/build/{useWorkshopApi-Bh5VUHWu.mjs → segmented-DPe9ZzLO.mjs} +7 -78
  118. package/.output/server/chunks/build/segmented-DPe9ZzLO.mjs.map +1 -0
  119. package/.output/server/chunks/build/{select-D7H2ysgT.mjs → select-D-CeE5vY.mjs} +3 -3
  120. package/.output/server/chunks/build/{select-D7H2ysgT.mjs.map → select-D-CeE5vY.mjs.map} +1 -1
  121. package/.output/server/chunks/build/{settings-Cr06lbRy.mjs → settings-DA8IkGLo.mjs} +11 -11
  122. package/.output/server/chunks/build/{settings-Cr06lbRy.mjs.map → settings-DA8IkGLo.mjs.map} +1 -1
  123. package/.output/server/chunks/build/{space-DCwIlnkI.mjs → space-CCBYAkXt.mjs} +2 -2
  124. package/.output/server/chunks/build/{space-DCwIlnkI.mjs.map → space-CCBYAkXt.mjs.map} +1 -1
  125. package/.output/server/chunks/build/{switch-VC0m9ede.mjs → switch-CelRXpcy.mjs} +3 -3
  126. package/.output/server/chunks/build/{switch-VC0m9ede.mjs.map → switch-CelRXpcy.mjs.map} +1 -1
  127. package/.output/server/chunks/build/{table-BksLg3Q_.mjs → table-Cswq-l2r.mjs} +10 -10
  128. package/.output/server/chunks/build/{table-BksLg3Q_.mjs.map → table-Cswq-l2r.mjs.map} +1 -1
  129. package/.output/server/chunks/build/{tabs-CzUfD3iX.mjs → tabs-BM3tAh_J.mjs} +5 -5
  130. package/.output/server/chunks/build/{tabs-CzUfD3iX.mjs.map → tabs-BM3tAh_J.mjs.map} +1 -1
  131. package/.output/server/chunks/build/{tag-oQI3VtqM.mjs → tag-NO9jEqKy.mjs} +4 -4
  132. package/.output/server/chunks/build/{tag-oQI3VtqM.mjs.map → tag-NO9jEqKy.mjs.map} +1 -1
  133. package/.output/server/chunks/build/{teams-QR3BBF7A.mjs → teams-BhSKBBBM.mjs} +15 -14
  134. package/.output/server/chunks/build/teams-BhSKBBBM.mjs.map +1 -0
  135. package/.output/server/chunks/build/{tokens-DFvr_TLj.mjs → tokens-D_eyxmcv.mjs} +16 -16
  136. package/.output/server/chunks/build/{tokens-DFvr_TLj.mjs.map → tokens-D_eyxmcv.mjs.map} +1 -1
  137. package/.output/server/chunks/build/town-BUqRobze.mjs +1 -1
  138. package/.output/server/chunks/build/{town-_4tEEEVW.mjs → town-DPtOPRRO.mjs} +4 -4
  139. package/.output/server/chunks/build/{town-_4tEEEVW.mjs.map → town-DPtOPRRO.mjs.map} +1 -1
  140. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs +42 -0
  141. package/.output/server/chunks/build/useLocalTime-9a4B-aHv.mjs.map +1 -0
  142. package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs +81 -0
  143. package/.output/server/chunks/build/useWorkshopApi-D2gq06N2.mjs.map +1 -0
  144. package/.output/server/chunks/build/useWorkshopWs-B3j5wIAK.mjs +1 -1
  145. package/.output/server/chunks/build/user-Dk-ytEUV.mjs +1 -1
  146. package/.output/server/chunks/build/{users-4FZ0yFUO.mjs → users-CmVvb1oq.mjs} +16 -16
  147. package/.output/server/chunks/build/{users-4FZ0yFUO.mjs.map → users-CmVvb1oq.mjs.map} +1 -1
  148. package/.output/server/chunks/build/{workshop-k0XZTFKg.mjs → workshop-iCzNRifn.mjs} +9 -9
  149. package/.output/server/chunks/build/{workshop-k0XZTFKg.mjs.map → workshop-iCzNRifn.mjs.map} +1 -1
  150. package/.output/server/chunks/build/workspaces-IfORCDJE.mjs +1 -1
  151. package/.output/server/chunks/routes/api/health.get.mjs +1 -1
  152. package/.output/server/chunks/routes/api/index.get.mjs +1 -1
  153. package/.output/server/chunks/routes/api/index.post.mjs +1 -1
  154. package/.output/server/chunks/routes/api/mcp/workshop.mjs +1 -1
  155. package/.output/server/chunks/routes/api/metrics.mjs +1 -1
  156. package/.output/server/chunks/routes/api/plugins/_name/_...path_.mjs +1 -1
  157. package/.output/server/chunks/routes/api/plugins/client/_name_.get.mjs +1 -1
  158. package/.output/server/chunks/routes/api/plugins/manifest.get.mjs +1 -1
  159. package/.output/server/chunks/routes/api/system/config.get.mjs +1 -1
  160. package/.output/server/chunks/routes/api/system/index.get.mjs +3 -3
  161. package/.output/server/chunks/routes/api/system/index.get.mjs.map +1 -1
  162. package/.output/server/chunks/routes/api/system/index.patch.mjs +1 -1
  163. package/.output/server/chunks/routes/api/system/monitor/terminal/ws.mjs +1 -1
  164. package/.output/server/chunks/routes/api/system/monitor/terminate.post.mjs +1 -1
  165. package/.output/server/chunks/routes/api/system/monitor.get.mjs +1 -1
  166. package/.output/server/chunks/routes/api/system/settings/events.get.mjs +1 -1
  167. package/.output/server/chunks/routes/api/system/settings/reset.post.mjs +1 -1
  168. package/.output/server/chunks/routes/api/users/_id_.delete.mjs +1 -1
  169. package/.output/server/chunks/routes/api/users/_id_.get.mjs +1 -1
  170. package/.output/server/chunks/routes/api/users/_id_.put.mjs +1 -1
  171. package/.output/server/chunks/routes/api/users/index.get.mjs +1 -1
  172. package/.output/server/chunks/routes/api/users/index.post.mjs +1 -1
  173. package/.output/server/chunks/routes/api/users/login.post.mjs +1 -1
  174. package/.output/server/chunks/routes/api/users/logout.post.mjs +1 -1
  175. package/.output/server/chunks/routes/api/users/me.get.mjs +1 -1
  176. package/.output/server/chunks/routes/api/users/register.post.mjs +1 -1
  177. package/.output/server/chunks/routes/api/users/tokens/_id/token.get.mjs +1 -1
  178. package/.output/server/chunks/routes/api/users/tokens/_id_.delete.mjs +1 -1
  179. package/.output/server/chunks/routes/api/users/tokens/_id_.patch.mjs +1 -1
  180. package/.output/server/chunks/routes/api/workshop/_...path_.mjs +1 -1
  181. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.get.mjs +1 -1
  182. package/.output/server/chunks/routes/api/workshop/a2a/_agentId/index.post.mjs +1 -1
  183. package/.output/server/chunks/routes/api/workshop/a2a/send.post.mjs +1 -1
  184. package/.output/server/chunks/routes/api/workshop/agent-tools/approvals/_id/decide.post.mjs +1 -1
  185. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.delete.mjs +1 -1
  186. package/.output/server/chunks/routes/api/workshop/agent-tools/bindings/_id_.patch.mjs +1 -1
  187. package/.output/server/chunks/routes/api/workshop/agent-tools/index.get.mjs +1 -1
  188. package/.output/server/chunks/routes/api/workshop/agent-tools/index.post.mjs +1 -1
  189. package/.output/server/chunks/routes/api/workshop/agent-tools/index2.get.mjs +1 -1
  190. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs +6 -14
  191. package/.output/server/chunks/routes/api/workshop/agent-tools/invoke.post.mjs.map +1 -1
  192. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs +39 -0
  193. package/.output/server/chunks/routes/api/workshop/agent-tools/list.get.mjs.map +1 -0
  194. package/.output/server/chunks/routes/api/workshop/agents/_id_.delete.mjs +1 -1
  195. package/.output/server/chunks/routes/api/workshop/agents/_id_.get.mjs +1 -1
  196. package/.output/server/chunks/routes/api/workshop/agents/_id_.patch.mjs +1 -1
  197. package/.output/server/chunks/routes/api/workshop/agents/subscribe.post.mjs +1 -1
  198. package/.output/server/chunks/routes/api/workshop/approvals/_id/decide.post.mjs +1 -1
  199. package/.output/server/chunks/routes/api/workshop/assets/character/_id_.delete.mjs +1 -1
  200. package/.output/server/chunks/routes/api/workshop/assets/devices/_id_.delete.mjs +1 -1
  201. package/.output/server/chunks/routes/api/workshop/assets/index.get.mjs +1 -1
  202. package/.output/server/chunks/routes/api/workshop/assets/index.post.mjs +2 -2
  203. package/.output/server/chunks/routes/api/workshop/assets/index2.get.mjs +1 -1
  204. package/.output/server/chunks/routes/api/workshop/assets/index2.post.mjs +2 -2
  205. package/.output/server/chunks/routes/api/workshop/audit.get.mjs +1 -1
  206. package/.output/server/chunks/routes/api/workshop/caller.mjs +1 -1
  207. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +2 -2
  208. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.delete.mjs +1 -1
  209. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.get.mjs +1 -1
  210. package/.output/server/chunks/routes/api/workshop/channel-templates/_id_.patch.mjs +1 -1
  211. package/.output/server/chunks/routes/api/workshop/channel-templates/from-channel.post.mjs +1 -1
  212. package/.output/server/chunks/routes/api/workshop/channels/_id/activate.post.mjs +2 -2
  213. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.get.mjs +1 -1
  214. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/index.post.mjs +1 -1
  215. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/_memoryId_.delete.mjs +1 -1
  216. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/memories/search.post.mjs +1 -1
  217. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/model.patch.mjs +1 -1
  218. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/position.patch.mjs +1 -1
  219. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/range.patch.mjs +1 -1
  220. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId/stop.post.mjs +1 -1
  221. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.delete.mjs +1 -1
  222. package/.output/server/chunks/routes/api/workshop/channels/_id/agents/_agentId_.patch.mjs +1 -1
  223. package/.output/server/chunks/routes/api/workshop/channels/_id/events.get.mjs +1 -1
  224. package/.output/server/chunks/routes/api/workshop/channels/_id/index.get.mjs +1 -1
  225. package/.output/server/chunks/routes/api/workshop/channels/_id/index.post.mjs +2 -2
  226. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.get.mjs +1 -1
  227. package/.output/server/chunks/routes/api/workshop/channels/_id/index2.post.mjs +1 -1
  228. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.get.mjs +1 -1
  229. package/.output/server/chunks/routes/api/workshop/channels/_id/index3.post.mjs +1 -1
  230. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.get.mjs +1 -1
  231. package/.output/server/chunks/routes/api/workshop/channels/_id/index4.post.mjs +1 -1
  232. package/.output/server/chunks/routes/api/workshop/channels/_id/memories/_memoryId_.delete.mjs +1 -1
  233. package/.output/server/chunks/routes/api/workshop/channels/_id/queue.get.mjs +1 -1
  234. package/.output/server/chunks/routes/api/workshop/channels/_id/terminals.get.mjs +2 -2
  235. package/.output/server/chunks/routes/api/workshop/channels/_id_.delete.mjs +1 -1
  236. package/.output/server/chunks/routes/api/workshop/channels/index.get.mjs +2 -2
  237. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs +9 -2
  238. package/.output/server/chunks/routes/api/workshop/channels/index.patch.mjs.map +1 -1
  239. package/.output/server/chunks/routes/api/workshop/channels.get.mjs +1 -1
  240. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +2 -2
  241. package/.output/server/chunks/routes/api/workshop/daq/_id/bind.post.mjs +2 -2
  242. package/.output/server/chunks/routes/api/workshop/daq/_id/frames/content.get.mjs +2 -2
  243. package/.output/server/chunks/routes/api/workshop/daq/_id/frames.get.mjs +2 -2
  244. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs +6 -4
  245. package/.output/server/chunks/routes/api/workshop/daq/_id/samples.get.mjs.map +1 -1
  246. package/.output/server/chunks/routes/api/workshop/daq/_id/test.post.mjs +2 -2
  247. package/.output/server/chunks/routes/api/workshop/daq/_id_.delete.mjs +2 -2
  248. package/.output/server/chunks/routes/api/workshop/daq/_id_.patch.mjs +2 -2
  249. package/.output/server/chunks/routes/api/workshop/daq/alarms/_id/ack.post.mjs +2 -2
  250. package/.output/server/chunks/routes/api/workshop/daq/alarms.get.mjs +2 -2
  251. package/.output/server/chunks/routes/api/workshop/daq/controller.post.mjs +2 -2
  252. package/.output/server/chunks/routes/api/workshop/daq/index.post.mjs +2 -2
  253. package/.output/server/chunks/routes/api/workshop/daq/infra/reconnect.post.mjs +2 -2
  254. package/.output/server/chunks/routes/api/workshop/daq/infra.get.mjs +2 -2
  255. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.delete.mjs +2 -2
  256. package/.output/server/chunks/routes/api/workshop/daq/templates/_key_.patch.mjs +2 -2
  257. package/.output/server/chunks/routes/api/workshop/daq/test-driver.post.mjs +2 -2
  258. package/.output/server/chunks/routes/api/workshop/dcw/_id/bind.post.mjs +2 -2
  259. package/.output/server/chunks/routes/api/workshop/dcw/_id/param-ledger.get.mjs +2 -2
  260. package/.output/server/chunks/routes/api/workshop/dcw/_id/read.post.mjs +2 -2
  261. package/.output/server/chunks/routes/api/workshop/dcw/_id/test.post.mjs +2 -2
  262. package/.output/server/chunks/routes/api/workshop/dcw/_id/write.post.mjs +2 -2
  263. package/.output/server/chunks/routes/api/workshop/dcw/_id_.delete.mjs +2 -2
  264. package/.output/server/chunks/routes/api/workshop/dcw/_id_.patch.mjs +2 -2
  265. package/.output/server/chunks/routes/api/workshop/dcw/controller.post.mjs +2 -2
  266. package/.output/server/chunks/routes/api/workshop/dcw/index.get.mjs +2 -2
  267. package/.output/server/chunks/routes/api/workshop/dcw/index.post.mjs +2 -2
  268. package/.output/server/chunks/routes/api/workshop/dcw/index2.get.mjs +2 -2
  269. package/.output/server/chunks/routes/api/workshop/dcw/index2.post.mjs +2 -2
  270. package/.output/server/chunks/routes/api/workshop/dcw/index3.get.mjs +2 -2
  271. package/.output/server/chunks/routes/api/workshop/dcw/index3.post.mjs +2 -2
  272. package/.output/server/chunks/routes/api/workshop/dcw/index4.get.mjs +2 -2
  273. package/.output/server/chunks/routes/api/workshop/dcw/index4.post.mjs +2 -2
  274. package/.output/server/chunks/routes/api/workshop/dcw/index5.get.mjs +2 -2
  275. package/.output/server/chunks/routes/api/workshop/dcw/journal/node/_nodeId/rollback.post.mjs +2 -2
  276. package/.output/server/chunks/routes/api/workshop/dcw/line/query.get.mjs +2 -2
  277. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +2 -2
  278. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +2 -2
  279. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.delete.mjs +2 -2
  280. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id_.patch.mjs +2 -2
  281. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/judge.post.mjs +2 -2
  282. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/rollback.post.mjs +2 -2
  283. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id/series.get.mjs +2 -2
  284. package/.output/server/chunks/routes/api/workshop/dcw/optimizations/_id_.get.mjs +2 -2
  285. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.delete.mjs +2 -2
  286. package/.output/server/chunks/routes/api/workshop/dcw/products/_id_.patch.mjs +2 -2
  287. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/apply.post.mjs +2 -2
  288. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/mark-good.post.mjs +2 -2
  289. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id/rollback-good.post.mjs +2 -2
  290. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.delete.mjs +2 -2
  291. package/.output/server/chunks/routes/api/workshop/dcw/recipes/_id_.patch.mjs +2 -2
  292. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/close.post.mjs +2 -2
  293. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/data.get.mjs +2 -2
  294. package/.output/server/chunks/routes/api/workshop/dcw/runs/_id/rollback.post.mjs +2 -2
  295. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +2 -2
  296. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +2 -2
  297. package/.output/server/chunks/routes/api/workshop/dcw/test-driver.post.mjs +2 -2
  298. package/.output/server/chunks/routes/api/workshop/device-twins/_id/control.post.mjs +1 -1
  299. package/.output/server/chunks/routes/api/workshop/device-twins/_id/telemetry.post.mjs +1 -1
  300. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.delete.mjs +2 -2
  301. package/.output/server/chunks/routes/api/workshop/device-twins/_id_.patch.mjs +2 -2
  302. package/.output/server/chunks/routes/api/workshop/fs/dirs.get.mjs +1 -1
  303. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +247 -0
  304. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs.map +1 -0
  305. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +27 -0
  306. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs.map +1 -0
  307. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  308. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +19 -7
  309. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs.map +1 -1
  310. package/.output/server/chunks/routes/api/workshop/index.get.mjs +1 -1
  311. package/.output/server/chunks/routes/api/workshop/index.post.mjs +1 -1
  312. package/.output/server/chunks/routes/api/workshop/index10.get.mjs +1 -1
  313. package/.output/server/chunks/routes/api/workshop/index2.get.mjs +1 -1
  314. package/.output/server/chunks/routes/api/workshop/index2.post.mjs +1 -1
  315. package/.output/server/chunks/routes/api/workshop/index3.get.mjs +1 -1
  316. package/.output/server/chunks/routes/api/workshop/index3.post.mjs +2 -2
  317. package/.output/server/chunks/routes/api/workshop/index4.get.mjs +2 -2
  318. package/.output/server/chunks/routes/api/workshop/index4.post.mjs +2 -2
  319. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +2 -2
  320. package/.output/server/chunks/routes/api/workshop/index5.post.mjs +2 -2
  321. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +1 -1
  322. package/.output/server/chunks/routes/api/workshop/index6.post.mjs +2 -2
  323. package/.output/server/chunks/routes/api/workshop/index7.get.mjs +1 -1
  324. package/.output/server/chunks/routes/api/workshop/index7.post.mjs +1 -1
  325. package/.output/server/chunks/routes/api/workshop/index8.get.mjs +1 -1
  326. package/.output/server/chunks/routes/api/workshop/index8.post.mjs +1 -1
  327. package/.output/server/chunks/routes/api/workshop/index9.get.mjs +1 -1
  328. package/.output/server/chunks/routes/api/workshop/mailbox/all.get.mjs +1 -1
  329. package/.output/server/chunks/routes/api/workshop/mailbox.get.mjs +1 -1
  330. package/.output/server/chunks/routes/api/workshop/memories/maintenance.post.mjs +1 -1
  331. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  332. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  333. package/.output/server/chunks/routes/api/workshop/plugins/index.get.mjs +1 -1
  334. package/.output/server/chunks/routes/api/workshop/runtime.get.mjs +1 -1
  335. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  336. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  337. package/.output/server/chunks/routes/api/workshop/scene/layouts.get.mjs +1 -1
  338. package/.output/server/chunks/routes/api/workshop/tasks/_id/complete.post.mjs +1 -1
  339. package/.output/server/chunks/routes/api/workshop/tasks/_id/dispatch.post.mjs +1 -1
  340. package/.output/server/chunks/routes/api/workshop/tasks/_id/index.post.mjs +1 -1
  341. package/.output/server/chunks/routes/api/workshop/tasks/_id/report.post.mjs +1 -1
  342. package/.output/server/chunks/routes/api/workshop/tasks/_id/retry.post.mjs +1 -1
  343. package/.output/server/chunks/routes/api/workshop/tasks/_id_.get.mjs +1 -1
  344. package/.output/server/chunks/routes/api/workshop/tasks.get.mjs +1 -1
  345. package/.output/server/chunks/routes/api/workshop/teams/_id/deploy.post.mjs +2 -2
  346. package/.output/server/chunks/routes/api/workshop/teams/_id/index.get.mjs +1 -1
  347. package/.output/server/chunks/routes/api/workshop/teams/_id/index.post.mjs +1 -1
  348. package/.output/server/chunks/routes/api/workshop/teams/_id/members/_agentId_.delete.mjs +1 -1
  349. package/.output/server/chunks/routes/api/workshop/teams/_id_.delete.mjs +1 -1
  350. package/.output/server/chunks/routes/api/workshop/teams/_id_.get.mjs +1 -1
  351. package/.output/server/chunks/routes/api/workshop/teams/_id_.patch.mjs +1 -1
  352. package/.output/server/chunks/routes/api/workshop/users/me.get.mjs +1 -1
  353. package/.output/server/chunks/routes/api/workshop/users/register.post.mjs +1 -1
  354. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +2 -2
  355. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.delete.mjs +1 -1
  356. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channels/_channelId_.post.mjs +1 -1
  357. package/.output/server/chunks/routes/api/workshop/workspaces/index.delete.mjs +1 -1
  358. package/.output/server/chunks/routes/renderer.mjs +1 -1
  359. package/.output/server/chunks/virtual/entry.mjs +123 -113
  360. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  361. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  362. package/.output/server/index.mjs +1 -1
  363. package/.output/server/package.json +1 -1
  364. package/app/components/AppHeader.vue +56 -2
  365. package/app/components/workshop/ChannelSessionList.vue +703 -593
  366. package/app/components/workshop/terminal/OmpTerminalPanel.vue +2 -1
  367. package/app/composables/workshop/useLocalTime.ts +16 -0
  368. package/app/composables/workshop/useSceneLayouts.ts +2 -1
  369. package/app/composables/workshop/useWorkshopApi.ts +249 -224
  370. package/app/pages/daq/[id].vue +7 -6
  371. package/app/pages/daq/index.vue +2 -2
  372. package/app/pages/dcw/[id].vue +3 -3
  373. package/app/pages/workshop/agents.vue +432 -382
  374. package/bin/aw.mjs +0 -0
  375. package/cli/aw.mjs +8 -1
  376. package/cli/commands/stop.mjs +7 -4
  377. package/cli/commands/tui.mjs +10 -1
  378. package/cli/core/registry.mjs +5 -3
  379. package/config.yml +134 -134
  380. package/docs/tui.md +1 -1
  381. package/i18n/locales/en.ts +5 -0
  382. package/i18n/locales/zh-CN.ts +5 -0
  383. package/package.json +148 -140
  384. package/scripts/_dbg-catalog-smoke.ts +20 -0
  385. package/scripts/_dbg-codex-probe.mjs +58 -0
  386. package/scripts/_dbg-dsh-probe.mjs +31 -0
  387. package/scripts/_dbg-interval-scenario.mjs +126 -0
  388. package/scripts/_dbg-line-spawn.ts +31 -0
  389. package/scripts/_dbg-live-engine-probe.mjs +80 -0
  390. package/scripts/_dbg-mcp-bridge-probe.mjs +147 -0
  391. package/scripts/_dbg-opencode-sse.mjs +101 -0
  392. package/scripts/_dbg-opencode-start.ts +57 -0
  393. package/scripts/_dbg-plugin-matrix.mjs +212 -0
  394. package/scripts/_dbg-protocol-matrix.mjs +425 -0
  395. package/scripts/_dbg-real-scenario-timeline.log +123 -0
  396. package/scripts/_dbg-registry-smoke.ts +14 -0
  397. package/scripts/_dbg-sim-keeper.mjs +100 -0
  398. package/scripts/_dbg-team-drill.mjs +173 -0
  399. package/scripts/dev-guard.mjs +11 -3
  400. package/scripts/dev-protocol-simulators.mjs +28 -1
  401. package/scripts/e2e-multi-harness.ts +374 -0
  402. package/scripts/e2e-multiharness-team.mjs +319 -0
  403. package/scripts/e2e-plc-scenario.mjs +292 -0
  404. package/scripts/e2e-real-scenario.mjs +452 -0
  405. package/scripts/migrate-local-time.mjs +123 -0
  406. package/scripts/start.mjs +30 -2
  407. package/server/api/system/settings/index.get.ts +3 -3
  408. package/server/api/workshop/agent-tools/invoke.post.ts +27 -41
  409. package/server/api/workshop/agent-tools/list.get.ts +25 -0
  410. package/server/api/workshop/channels/[id]/index.patch.ts +38 -30
  411. package/server/api/workshop/daq/[id]/samples.get.ts +6 -3
  412. package/server/api/workshop/harnesses/[id]/providers.get.ts +16 -0
  413. package/server/api/workshop/harnesses.get.ts +12 -0
  414. package/server/api/workshop/hitl/respond.post.ts +87 -67
  415. package/server/api/workshop/ws.ts +13 -0
  416. package/server/data/daqs.json +1366 -16
  417. package/server/data/dcw-lines.json +266 -0
  418. package/server/data/dcw-products.json +203 -0
  419. package/server/data/dcw-recipes.json +784 -0
  420. package/server/data/dcw-rollback.json +1144 -1
  421. package/server/data/dcw-runs.json +983 -791
  422. package/server/data/dcw-writes.json +1080 -0
  423. package/server/data/dcws.json +3278 -203
  424. package/server/data/line-runs.json +52 -2
  425. package/server/harness/aw-mcp-bridge.mjs +153 -0
  426. package/server/plugins/00-local-time.ts +10 -0
  427. package/server/plugins/aw-plugins.ts +3 -0
  428. package/server/plugins/backup.ts +116 -97
  429. package/server/plugins/dev-stability-guard.ts +24 -15
  430. package/server/plugins/retention.ts +1 -0
  431. package/server/plugins/security.ts +24 -3
  432. package/server/plugins/workshop.ts +156 -153
  433. package/server/repositories/user.repository.ts +414 -391
  434. package/server/services/system-config.ts +30 -6
  435. package/server/services/workshop/.mimosa/hook-state/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f.json +1 -0
  436. package/server/services/workshop/.mimosa/hook-status/sess_fed429fb-c8b7-4a50-bbd6-45afc580893f-e6b75bbfe6.json +14 -0
  437. package/server/services/workshop/agents/adapters/line-spawn.ts +108 -0
  438. package/server/services/workshop/agents/adapters/stdio-jsonrpc.ts +316 -0
  439. package/server/services/workshop/agents/agent-interface.ts +17 -0
  440. package/server/services/workshop/agents/codex-agent.ts +822 -0
  441. package/server/services/workshop/agents/dsh-agent.ts +670 -0
  442. package/server/services/workshop/agents/factory.ts +4 -16
  443. package/server/services/workshop/agents/harness-env.ts +54 -0
  444. package/server/services/workshop/agents/harness-models.ts +270 -0
  445. package/server/services/workshop/agents/host-tool-bridge.ts +592 -0
  446. package/server/services/workshop/agents/industrial-tools.ts +5 -1
  447. package/server/services/workshop/agents/node-bindings.repo.ts +4 -5
  448. package/server/services/workshop/agents/omp-agent.ts +1178 -1957
  449. package/server/services/workshop/agents/opencode-agent.ts +987 -0
  450. package/server/services/workshop/agents/prompt-builder.ts +393 -0
  451. package/server/services/workshop/agents/registry.ts +125 -0
  452. package/server/services/workshop/assets/character-asset.repo.ts +3 -5
  453. package/server/services/workshop/assets/device-twin.repo.ts +3 -5
  454. package/server/services/workshop/daq/daq-controller.ts +8 -4
  455. package/server/services/workshop/daq/daq-node.repo.ts +3 -5
  456. package/server/services/workshop/daq/daq-node.ts +2 -2
  457. package/server/services/workshop/daq/daq-templates.ts +3 -5
  458. package/server/services/workshop/daq/drivers.ts +41 -12
  459. package/server/services/workshop/daq/storage/sqlite.adapter.ts +313 -309
  460. package/server/services/workshop/db/backup-registry.ts +33 -0
  461. package/server/services/workshop/db/channel.repo.ts +104 -101
  462. package/server/services/workshop/db/database.ts +956 -949
  463. package/server/services/workshop/dcw/dcw-controller.ts +3 -1
  464. package/server/services/workshop/dcw/dcw-line.repo.ts +4 -11
  465. package/server/services/workshop/dcw/dcw-node.repo.ts +3 -5
  466. package/server/services/workshop/dcw/dcw-node.ts +13 -1
  467. package/server/services/workshop/dcw/dcw-product.repo.ts +3 -4
  468. package/server/services/workshop/dcw/dcw-recipe.repo.ts +3 -19
  469. package/server/services/workshop/dcw/dcw-templates.ts +3 -5
  470. package/server/services/workshop/dcw/drivers.ts +37 -13
  471. package/server/services/workshop/dcw/line-run.ts +3 -5
  472. package/server/services/workshop/dcw/recipe-rollback.repo.ts +4 -10
  473. package/server/services/workshop/json-store.mjs +72 -0
  474. package/server/services/workshop/plugins/host.mjs +2 -1
  475. package/server/services/workshop/runtime/agent-runtime.ts +44 -0
  476. package/server/services/workshop/runtime/manager.ts +2953 -2868
  477. package/server/services/workshop/scene/scene-layout.repo.ts +4 -11
  478. package/server/services/workshop/settings.ts +7 -0
  479. package/shared/config/schema.json +5 -0
  480. package/shared/config/single-instance.mjs +5 -1
  481. package/shared/local-time.mjs +36 -0
  482. package/shared/workshop-protocol.ts +11 -5
  483. package/tui/aw-tui.mjs +28 -10
  484. package/tui/components/hitl-card.mjs +47 -36
  485. package/tui/lib/ws.mjs +2 -1
  486. package/.output/public/_nuxt/9X0fVBD7.js +0 -57
  487. package/.output/public/_nuxt/B6M2WJWm2.js +0 -1
  488. package/.output/public/_nuxt/B9Yie5HN.js +0 -2
  489. package/.output/public/_nuxt/BF9XPEuw.js +0 -1
  490. package/.output/public/_nuxt/BbQornXa.js +0 -1
  491. package/.output/public/_nuxt/Bxgaym6j.js +0 -1
  492. package/.output/public/_nuxt/Bxh5nf8j.js +0 -1
  493. package/.output/public/_nuxt/CXLI50Sq.js +0 -1
  494. package/.output/public/_nuxt/CdfAP_IH2.js +0 -1
  495. package/.output/public/_nuxt/Ce1zyNYu.js +0 -1
  496. package/.output/public/_nuxt/D-Ne4C9a.js +0 -1
  497. package/.output/public/_nuxt/DEHNjlTq2.js +0 -1
  498. package/.output/public/_nuxt/DFnGFEav.js +0 -18
  499. package/.output/public/_nuxt/DYWgGHNo.js +0 -7
  500. package/.output/public/_nuxt/OmpTerminalPanel.Bc9GjNU5.css +0 -1
  501. package/.output/public/_nuxt/W1E3-5ML.js +0 -14
  502. package/.output/public/_nuxt/XVB9_zwP.js +0 -1
  503. package/.output/public/_nuxt/Xaf_HIR3.js +0 -1
  504. package/.output/public/_nuxt/_id_.BeqSLvl_.css +0 -1
  505. package/.output/public/_nuxt/_id_.DN3U6EF9.css +0 -1
  506. package/.output/public/_nuxt/agents.BJwgTLFZ.css +0 -1
  507. package/.output/public/_nuxt/builds/meta/55c10854-ee0e-4be4-924b-a1b0e100fe11.json +0 -1
  508. package/.output/public/_nuxt/daq.BXsnevQv.css +0 -1
  509. package/.output/public/_nuxt/yIKY_V1P.js +0 -1
  510. package/.output/server/chunks/build/OmpTerminalPanel-B_SYhmgb.mjs.map +0 -1
  511. package/.output/server/chunks/build/_id_-CWLFGZjV.mjs.map +0 -1
  512. package/.output/server/chunks/build/agents-D4l1icvn.mjs.map +0 -1
  513. package/.output/server/chunks/build/channel-templates-DqjtC-R0.mjs.map +0 -1
  514. package/.output/server/chunks/build/interval-WlxgjTzO.mjs +0 -9
  515. package/.output/server/chunks/build/interval-WlxgjTzO.mjs.map +0 -1
  516. package/.output/server/chunks/build/teams-QR3BBF7A.mjs.map +0 -1
  517. package/.output/server/chunks/build/useWorkshopApi-Bh5VUHWu.mjs.map +0 -1
@@ -0,0 +1,987 @@
1
+ /**
2
+ * OpenCodeAgentImpl — opencode harness 的 AgentInterface 实现。
3
+ *
4
+ * 进程模型:每 Agent 一个 `opencode serve --port <free>` 子进程(lazy spawn,跨消息复用),
5
+ * 经 HTTP API(prompt_async / abort / permissions / summarize)与全局 SSE 事件流(/event)
6
+ * 交互 —— 官方机器面,协议参考 opencode OpenAPI(1.18.x)。
7
+ *
8
+ * - prompt 组装与工具面与 omp 全引擎同源(prompt-builder / host-tool-bridge);
9
+ * 工具经 stdio MCP 桥(server/harness/aw-mcp-bridge.mjs)以 POST /mcp 运行时注册注入
10
+ * - opencode 事件 → AgentEvent 五变体映射(适配器职责,本文件统一收口)
11
+ * - 权限/提问(permission.asked / question.asked)→ hitl-registry(程序化应答)
12
+ * - steer:回合运行中再投 prompt(引擎 steer/queue admission),内容不丢 → 'steer'
13
+ * - 上下文治理:message.tokens 被动跟踪;越阈值 → POST /session/{id}/summarize
14
+ *
15
+ * 协议权威:https://opencode.ai/docs/server(v1.18.28 实测)。
16
+ */
17
+ import { createLogger } from '../logger'
18
+ import { randomUUID } from 'node:crypto'
19
+ import { createServer } from 'node:net'
20
+ import type {
21
+ AgentEvent,
22
+ AgentInterface,
23
+ AgentInfo,
24
+ AgentRunContext,
25
+ AgentRunRequest,
26
+ SupervisionDecision,
27
+ SupervisionSnapshot,
28
+ } from './agent-interface'
29
+ import type { AgentContextStats } from '../types/task'
30
+ import { registerHarnessProcess, bindHarnessProcess, markHarnessProcessExit, killHarnessProcess, isProcessAlive } from './harness-process'
31
+ import { createSessionState, dispatchHostTool } from './host-tool-bridge'
32
+ import {
33
+ contextPrefix as buildContextPrefix,
34
+ createRosterCache,
35
+ extractJsonArray,
36
+ peerPrompt,
37
+ supervisePrompt,
38
+ systemManual,
39
+ toolArgsPreview,
40
+ workerPrompt,
41
+ } from './prompt-builder'
42
+ import { getHitlRegistry } from './hitl-registry'
43
+ import { harnessSettings } from '../settings'
44
+ import { spawnLineProcess } from './adapters/line-spawn'
45
+ import { resolveBridgePath, resolvePlatformBaseUrl } from './harness-env'
46
+
47
+ const log = createLogger('workshop.opencode')
48
+
49
+ export interface OpenCodeAgentConfig {
50
+ /** opencode 可执行文件(默认取 harness.opencode_command 设置) */
51
+ command?: string
52
+ cwd?: string
53
+ /** 模型(provider/model,如 anthropic/claude-sonnet-4-5) */
54
+ model?: string
55
+ /** opencode agent 名(默认 build) */
56
+ agent?: string
57
+ /** provider 推理档位(variant;effort 为统一注入入口的别名) */
58
+ variant?: string
59
+ /** 思考 effort(统一注入面;等价 variant) */
60
+ effort?: string
61
+ /** 权限策略(session 级;缺省 edit/bash/webfetch 全 ask → HITL) */
62
+ permission?: unknown
63
+ /** 数据目录覆盖(XDG_DATA_HOME;实例隔离/绕开损坏的全局库) */
64
+ dataDir?: string
65
+ /** 配置目录覆盖(XDG_CONFIG_HOME;空目录 = 不加载用户全局 opencode 插件/配置) */
66
+ configDir?: string
67
+ /** 上下文窗口(usage 百分比计算;未知则 percent=null) */
68
+ contextWindow?: number
69
+ /** 压缩阈值(0-1,默认 0.7) */
70
+ compactThreshold?: number
71
+ /** 回合停滞超时(ms,默认 600000) */
72
+ promptTimeoutMs?: number
73
+ /** supervise 超时(ms,默认 150000) */
74
+ superviseTimeoutMs?: number
75
+ systemPromptPrefix?: string
76
+ scenarioPrompt?: string
77
+ agentId?: string
78
+ name?: string
79
+ role?: 'lead' | 'worker'
80
+ channelId?: string
81
+ /** 平台自证 token(MCP 桥回程鉴权;factory 注入) */
82
+ token?: string
83
+ /** 平台 HTTP 基址(桥回程;默认 AW_BASE_URL 或 127.0.0.1:PORT) */
84
+ baseUrl?: string
85
+ /** MCP 桥脚本路径(默认 <packageRoot>/server/harness/aw-mcp-bridge.mjs) */
86
+ mcpBridgePath?: string
87
+ }
88
+
89
+ const sleep = (ms: number): Promise<void> => new Promise(r => setTimeout(r, ms))
90
+
91
+ const DEFAULT_PERMISSION = [
92
+ { permission: 'edit', pattern: '*', action: 'ask' },
93
+ { permission: 'bash', pattern: '*', action: 'ask' },
94
+ { permission: 'webfetch', pattern: '*', action: 'ask' },
95
+ ]
96
+
97
+ /** 取一个空闲 TCP 端口(绑定即弃,竞态窗口小;opencode serve 自身再绑定) */
98
+ async function freePort(): Promise<number> {
99
+ return new Promise((resolve, reject) => {
100
+ const srv = createServer()
101
+ srv.unref()
102
+ srv.on('error', reject)
103
+ srv.listen(0, '127.0.0.1', () => {
104
+ const addr = srv.address()
105
+ const port = typeof addr === 'object' && addr ? addr.port : 0
106
+ srv.close(() => (port ? resolve(port) : reject(new Error('无可用端口'))))
107
+ })
108
+ })
109
+ }
110
+
111
+ interface PendingHitl {
112
+ kind: 'opencode-permission'
113
+ id: string
114
+ type: 'permission' | 'question'
115
+ sessionId: string
116
+ timer: ReturnType<typeof setTimeout> | null
117
+ }
118
+
119
+ export class OpenCodeAgentImpl implements AgentInterface {
120
+ private readonly config: OpenCodeAgentConfig
121
+ private workspace: AgentRunContext['workspace'] | null = null
122
+ private agentInfo: AgentInfo | null = null
123
+ private readonly toolState = createSessionState()
124
+ private readonly bridgeCtx = {
125
+ identity: { agentId: '', channelId: '', role: 'worker' as 'lead' | 'worker', name: 'agent' },
126
+ state: this.toolState,
127
+ getWorkspace: () => this.workspace,
128
+ }
129
+
130
+ private roster = createRosterCache({ selfAgentId: '', listAgents: async () => [] })
131
+
132
+ private selfAgentId = ''
133
+ private agentName = 'agent'
134
+ private agentRole: 'lead' | 'worker' = 'worker'
135
+ private channelId = ''
136
+
137
+ // 服务进程与 API 面
138
+ private child: ReturnType<typeof spawnLineProcess> | null = null
139
+ private baseUrl = ''
140
+ private basicAuth = ''
141
+ private sessionId: string | null = null
142
+ private serverStarting: Promise<void> | null = null
143
+ private exited = false
144
+ private stderrTail = ''
145
+ private sseAbort: AbortController | null = null
146
+
147
+ // 回合状态
148
+ private turnActive = false
149
+ private aborted = false
150
+ /** 助手正文(partId → 全文;message.part.updated 携带全量文本) */
151
+ private partTexts = new Map<string, string>()
152
+ private partOrder: string[] = []
153
+ private lastUsage: { input: number, at: number } | null = null
154
+ private compacting = false
155
+ private lastCompactAt = 0
156
+ /** 待应答 HITL(id → 定位信息) */
157
+ private pendingHitl = new Map<string, PendingHitl>()
158
+
159
+ constructor(config: Record<string, unknown> = {}) {
160
+ this.config = config as OpenCodeAgentConfig
161
+ this.selfAgentId = this.config.agentId ?? ''
162
+ this.agentName = this.config.name ?? 'agent'
163
+ this.agentRole = this.config.role ?? 'worker'
164
+ this.channelId = this.config.channelId ?? ''
165
+ this.refreshIdentity()
166
+ }
167
+
168
+ private refreshIdentity(): void {
169
+ this.bridgeCtx.identity = { agentId: this.selfAgentId, channelId: this.channelId, role: this.agentRole, name: this.agentName }
170
+ this.roster = createRosterCache({
171
+ selfAgentId: this.selfAgentId,
172
+ listAgents: async () => this.workspace?.listAgents() ?? [],
173
+ })
174
+ }
175
+
176
+ async init(input: { agent: AgentInfo, channelId: string }): Promise<void> {
177
+ this.agentInfo = input.agent
178
+ this.channelId = input.channelId
179
+ this.agentName = input.agent.name
180
+ this.agentRole = input.agent.role
181
+ this.selfAgentId = input.agent.id
182
+ this.refreshIdentity()
183
+ }
184
+
185
+ // ===== 生命周期 / 进程面 =====
186
+
187
+ getProcessInfo(): { pid: number, alive: boolean, command: string } | null {
188
+ const pid = this.child?.pid
189
+ if (!pid || !this.child) return null
190
+ return { pid, alive: !this.exited, command: 'opencode serve' }
191
+ }
192
+
193
+ killProcess(): void {
194
+ const pid = this.child?.pid
195
+ if (pid) killHarnessProcess(pid)
196
+ this.child = null
197
+ }
198
+
199
+ reconcileProcess(): void {
200
+ const pid = this.child?.pid
201
+ if (!pid || this.exited) return
202
+ if (!isProcessAlive(pid)) this.handleServerExit(null)
203
+ }
204
+
205
+ async dispose(): Promise<void> {
206
+ this.sseAbort?.abort()
207
+ const pid = this.child?.pid
208
+ if (pid) {
209
+ killHarnessProcess(pid)
210
+ markHarnessProcessExit(pid, null)
211
+ }
212
+ this.child = null
213
+ this.exited = true
214
+ this.serverStarting = null
215
+ for (const [id, p] of this.pendingHitl) {
216
+ if (p.timer) clearTimeout(p.timer)
217
+ this.pendingHitl.delete(id)
218
+ }
219
+ }
220
+
221
+ // ===== 引擎无关面 =====
222
+
223
+ dispatchHostTool(toolName: string, args: Record<string, unknown>): Promise<{ text: string, isError?: boolean }> {
224
+ return dispatchHostTool(this.bridgeCtx, { toolName, arguments: args })
225
+ }
226
+
227
+ getContextStats(): AgentContextStats | null {
228
+ if (!this.lastUsage) return null
229
+ const window = this.config.contextWindow ?? null
230
+ return {
231
+ usedTokens: this.lastUsage.input,
232
+ contextWindow: window,
233
+ percent: window && window > 0 ? Math.min(1, this.lastUsage.input / window) : null,
234
+ compacting: this.compacting,
235
+ }
236
+ }
237
+
238
+ /**
239
+ * 实时注入:回合运行中再投一条 prompt(opencode 引擎 admit 为 steer/queue,
240
+ * 内容必然到达模型)→ 'steer';空闲 → 'deferred'(消费循环起回合处理)。
241
+ */
242
+ async steer(text: string): Promise<'steer' | 'deferred'> {
243
+ if (!this.sessionId || !this.turnActive) return 'deferred'
244
+ try {
245
+ await this.promptAsync(text)
246
+ return 'steer'
247
+ }
248
+ catch (err) {
249
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] steer 投递失败(消息保持 pending):`, err instanceof Error ? err.message : err)
250
+ return 'deferred'
251
+ }
252
+ }
253
+
254
+ /** HITL 应答(codex/opencode/dsh 统一入口;本 impl 处理 opencode-permission) */
255
+ async respondHitl(kind: string, id: string, outcome: {
256
+ confirmed?: boolean
257
+ cancelled?: boolean
258
+ value?: string
259
+ response?: string
260
+ comment?: string
261
+ }): Promise<void> {
262
+ if (kind !== 'opencode-permission') return
263
+ const pending = this.pendingHitl.get(id)
264
+ if (!pending) throw new Error(`待办不存在或已处理: ${id}`)
265
+ // 应答映射:显式 response > confirmed/cancelled 布尔(缺省拒绝,fail-closed)
266
+ const cancelled = outcome.cancelled === true || (outcome.confirmed !== true && !outcome.response)
267
+ if (pending.type === 'permission') {
268
+ const response = cancelled ? 'reject' : (outcome.response === 'always' || outcome.response === 'once' ? outcome.response : 'once')
269
+ await this.api('POST', `/session/${pending.sessionId}/permissions/${encodeURIComponent(id)}`, { response })
270
+ }
271
+ else {
272
+ // question:取消走 reject 端点;回答携带 value
273
+ if (cancelled) {
274
+ await this.api('POST', `/question/${encodeURIComponent(id)}/reject`, {})
275
+ }
276
+ else {
277
+ await this.api('POST', `/question/${encodeURIComponent(id)}/reply`, { answer: outcome.value ?? outcome.comment ?? '' })
278
+ }
279
+ }
280
+ if (pending.timer) clearTimeout(p.timer)
281
+ this.pendingHitl.delete(id)
282
+ getHitlRegistry().resolve(kind, id, cancelled ? 'cancelled' : 'answered')
283
+ }
284
+
285
+ /** 上下文治理(post-settle 钩子):越阈值 → summarize;异常不抛出 */
286
+ async onTurnSettled(): Promise<void> {
287
+ if (this.compacting || !this.sessionId) return
288
+ const stats = this.getContextStats()
289
+ const threshold = this.config.compactThreshold ?? 0.7
290
+ if (!stats?.percent || stats.percent < threshold) return
291
+ if (Date.now() - this.lastCompactAt < 5 * 60_000) return
292
+ this.compacting = true
293
+ this.lastCompactAt = Date.now()
294
+ try {
295
+ await this.api('POST', `/session/${this.sessionId}/summarize`, {})
296
+ log.info(`[OpenCodeAgent:${this.selfAgentId}] 上下文压缩已触发(percent=${(stats.percent * 100).toFixed(0)}%)`)
297
+ }
298
+ catch (err) {
299
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] summarize 失败(放行):`, err instanceof Error ? err.message : err)
300
+ }
301
+ finally {
302
+ this.compacting = false
303
+ }
304
+ }
305
+
306
+ // ===== run / supervise =====
307
+
308
+ async* run(request: AgentRunRequest, ctx: AgentRunContext): AsyncIterable<AgentEvent> {
309
+ const kind = request.message.metadata?.['x-aw-task-kind']
310
+ if (kind === 'assign' && ctx.role === 'worker') {
311
+ yield* this.workerRun(request, ctx)
312
+ return
313
+ }
314
+ if (!kind && (request.fromAgentId || request.message.metadata?.['x-aw-from-label'])) {
315
+ yield* this.peerMessageRun(request, ctx)
316
+ return
317
+ }
318
+ }
319
+
320
+ private supervising = false
321
+
322
+ async supervise(snapshot: SupervisionSnapshot, ctx: AgentRunContext, opts?: { signal?: AbortSignal }): Promise<SupervisionDecision[]> {
323
+ // 引擎/会话不可用 → 本轮监督降级为空(调度器回退规则引擎);绝不让引擎故障
324
+ // 以 unhandledRejection 形态逃逸(dev-stability-guard 会据此杀掉整个服务端)
325
+ try {
326
+ await this.ensureServer(ctx)
327
+ }
328
+ catch (err) {
329
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] supervise 引擎不可用,跳过本轮:`, err instanceof Error ? err.message : err)
330
+ return []
331
+ }
332
+ if (!this.sessionId) return []
333
+ if (this.supervising) return []
334
+ const prompt = supervisePrompt({
335
+ snapshot,
336
+ agentName: this.agentName,
337
+ channelId: this.channelId,
338
+ ctxPrefix: await this.contextPrefix(),
339
+ manual: systemManual(),
340
+ memory: ctx.memory,
341
+ })
342
+ const timeoutMs = this.config.superviseTimeoutMs ?? 150_000
343
+ return await this.runTurn(prompt, undefined, {
344
+ timeoutMs,
345
+ signal: opts?.signal,
346
+ onDone: async () => {
347
+ this.supervising = false
348
+ },
349
+ beforeStart: () => {
350
+ this.supervising = true
351
+ },
352
+ }).then((events) => {
353
+ // 从事件流提取最终文本 → JSON 决策兜底(工具直执行路径返回空)
354
+ let text = ''
355
+ for (const e of events) {
356
+ if (e.kind === 'artifact') {
357
+ text += e.artifact.parts.map(p => 'text' in p ? p.text : '').join('')
358
+ }
359
+ }
360
+ const parsed = extractJsonArray(text)
361
+ return parsed && parsed.length > 0 ? parsed as SupervisionDecision[] : []
362
+ }).catch(() => {
363
+ this.supervising = false
364
+ return []
365
+ })
366
+ }
367
+
368
+ private async* workerRun(request: AgentRunRequest, ctx: AgentRunContext): AsyncGenerator<AgentEvent, void, unknown> {
369
+ const taskId = request.taskId ?? (request.message.metadata?.['x-aw-task-id'] as string | undefined)
370
+ if (!taskId) return
371
+ this.toolState.currentTaskId = taskId
372
+ try {
373
+ await this.ensureServer(ctx)
374
+ const taskText = request.message.parts.map((p) => {
375
+ if ('text' in p) return p.text
376
+ if ('data' in p) return JSON.stringify(p.data)
377
+ if ('url' in p) return p.url
378
+ if ('raw' in p) return p.raw
379
+ return ''
380
+ }).join('\n')
381
+ const prompt = workerPrompt({
382
+ agentName: this.agentName,
383
+ channelId: this.channelId,
384
+ taskId,
385
+ taskText,
386
+ memory: request.memory,
387
+ ctxPrefix: await this.contextPrefix(),
388
+ manual: systemManual(),
389
+ })
390
+ yield* this.runTurn(prompt, taskId, {
391
+ timeoutMs: this.config.promptTimeoutMs ?? 600_000,
392
+ signal: ctx.signal,
393
+ })
394
+ }
395
+ finally {
396
+ this.toolState.currentTaskId = null
397
+ }
398
+ }
399
+
400
+ private async* peerMessageRun(request: AgentRunRequest, ctx: AgentRunContext): AsyncGenerator<AgentEvent, void, unknown> {
401
+ await this.ensureServer(ctx)
402
+ const msg = request.message
403
+ const fromId = request.fromAgentId
404
+ ?? (typeof msg.metadata?.['x-aw-from-label'] === 'string' ? msg.metadata['x-aw-from-label'] : undefined)
405
+ ?? 'unknown'
406
+ const requireReply = msg.metadata?.['x-aw-require-reply'] === 'true'
407
+ const crossChannel = msg.metadata?.['x-aw-cross-channel'] === 'true'
408
+ this.toolState.replyContext = requireReply && request.fromAgentId && !crossChannel
409
+ ? { fromId: request.fromAgentId, messageId: msg.messageId }
410
+ : null
411
+ const msgText = msg.parts.map((p) => {
412
+ if ('text' in p) return p.text
413
+ if ('data' in p) return JSON.stringify(p.data)
414
+ if ('url' in p) return p.url
415
+ if ('raw' in p) return p.raw
416
+ return ''
417
+ }).join('\n')
418
+ const prompt = peerPrompt({
419
+ agentName: this.agentName,
420
+ role: this.agentRole,
421
+ channelId: this.channelId,
422
+ ctxPrefix: await this.contextPrefix(),
423
+ manual: systemManual(),
424
+ memory: request.memory,
425
+ fromId,
426
+ messageId: msg.messageId,
427
+ requireReply,
428
+ isReply: typeof msg.metadata?.['x-aw-in-reply-to'] === 'string',
429
+ crossChannel,
430
+ fromChannel: typeof msg.metadata?.['x-aw-from-channel'] === 'string' ? String(msg.metadata['x-aw-from-channel']) : '',
431
+ msgText,
432
+ })
433
+ yield* this.runTurn(prompt, undefined, { timeoutMs: this.config.promptTimeoutMs ?? 600_000, signal: ctx.signal })
434
+ }
435
+
436
+ private async contextPrefix(): Promise<string> {
437
+ return buildContextPrefix({
438
+ scenarioPrompt: this.config.scenarioPrompt,
439
+ systemPromptPrefix: this.config.systemPromptPrefix,
440
+ agentId: this.selfAgentId,
441
+ roster: await this.roster.roster(),
442
+ })
443
+ }
444
+
445
+ // ===== 回合执行(prompt → SSE 事件 → AgentEvent)=====
446
+
447
+ private runTurn(
448
+ prompt: string,
449
+ taskId: string | undefined,
450
+ opts: { timeoutMs: number, signal?: AbortSignal, beforeStart?: () => void, onDone?: () => void },
451
+ ): AsyncGenerator<AgentEvent, void, unknown> {
452
+ return this._runTurn(prompt, taskId, opts)
453
+ }
454
+
455
+ private async* _runTurn(
456
+ prompt: string,
457
+ taskId: string | undefined,
458
+ opts: { timeoutMs: number, signal?: AbortSignal, beforeStart?: () => void, onDone?: () => void },
459
+ ): AsyncGenerator<AgentEvent, void, unknown> {
460
+ if (!this.sessionId) {
461
+ yield { kind: 'error', error: { code: 'OPENCODE_NOT_READY', message: 'opencode 会话未就绪' } }
462
+ return
463
+ }
464
+ opts.beforeStart?.()
465
+ const queue: AgentEvent[] = []
466
+ let isDone = false
467
+ let resolveWait: (() => void) | null = null
468
+ let lastActivity = Date.now()
469
+ this.turnActive = true
470
+ this.aborted = false
471
+ this.partTexts = new Map()
472
+ this.partOrder = []
473
+
474
+ const enqueue = (e: AgentEvent): void => {
475
+ // done 事件前先收口 artifact(助手正文聚合),保证事件序 artifact → done
476
+ if (e.kind === 'done' && !isDone) {
477
+ const text = this.partOrder.map(id => this.partTexts.get(id) ?? '').join('').trim()
478
+ if (text) {
479
+ queue.push({
480
+ kind: 'artifact',
481
+ artifact: { artifactId: randomUUID(), name: 'output', parts: [{ text }] },
482
+ lastChunk: true,
483
+ totalChunks: 1,
484
+ })
485
+ }
486
+ this.turnActive = false
487
+ opts.onDone?.()
488
+ }
489
+ if (e.kind === 'done' || e.kind === 'error') {
490
+ isDone = true
491
+ this.turnActive = false
492
+ }
493
+ queue.push(e)
494
+ lastActivity = Date.now()
495
+ resolveWait?.()
496
+ resolveWait = null
497
+ }
498
+
499
+ // 事件订阅(SSE → 队列)
500
+ const unsub = this.onEngineEvent((ev) => {
501
+ for (const mapped of this.mapEngineEvent(ev, taskId)) enqueue(mapped)
502
+ })
503
+
504
+ // 停滞看门狗
505
+ let stallTimer: ReturnType<typeof setTimeout> | null = null
506
+
507
+ const finishTurn = (): void => {
508
+ if (isDone) return
509
+ const text = this.partOrder.map(id => this.partTexts.get(id) ?? '').join('').trim()
510
+ if (text) {
511
+ enqueue({
512
+ kind: 'artifact',
513
+ artifact: { artifactId: randomUUID(), name: 'output', parts: [{ text }] },
514
+ lastChunk: true,
515
+ totalChunks: 1,
516
+ })
517
+ }
518
+ enqueue({ kind: 'done', final: taskId ? { taskId } : undefined })
519
+ this.turnActive = false
520
+ opts.onDone?.()
521
+ }
522
+
523
+ const onAbort = (): void => {
524
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] run 被 abort → POST abort,taskId=${taskId ?? '-'}`)
525
+ this.aborted = true
526
+ void this.api('POST', `/session/${this.sessionId}/abort`, {}).catch(() => {})
527
+ // 引擎将回 session.idle → finishTurn;兜底 5s 后强制收口
528
+ setTimeout(() => finishTurn(), 5000)
529
+ }
530
+ if (opts.signal?.aborted) onAbort()
531
+ else opts.signal?.addEventListener('abort', onAbort, { once: true })
532
+
533
+ // 投递 prompt
534
+ try {
535
+ await this.promptAsync(prompt)
536
+ enqueue({ kind: 'status', status: { state: 'WORKING', timestamp: new Date().toISOString() } })
537
+ }
538
+ catch (err) {
539
+ unsub()
540
+ opts.signal?.removeEventListener('abort', onAbort)
541
+ this.turnActive = false
542
+ yield {
543
+ kind: 'error',
544
+ error: {
545
+ code: 'OPENCODE_PROMPT_FAILED',
546
+ message: `opencode prompt 失败: ${err instanceof Error ? err.message : String(err)}`,
547
+ },
548
+ }
549
+ return
550
+ }
551
+
552
+ try {
553
+ while (!isDone || queue.length > 0) {
554
+ if (queue.length === 0 && !isDone) {
555
+ const remaining = opts.timeoutMs - (Date.now() - lastActivity)
556
+ if (remaining <= 0) {
557
+ this.aborted = true
558
+ void this.api('POST', `/session/${this.sessionId}/abort`, {}).catch(() => {})
559
+ enqueue({
560
+ kind: 'error',
561
+ error: {
562
+ code: 'OPENCODE_TURN_STALLED',
563
+ message: `回合停滞 ${Math.round(opts.timeoutMs / 1000)}s 无事件,已中止(消息按已处理落账)`,
564
+ },
565
+ })
566
+ this.turnActive = false
567
+ continue
568
+ }
569
+ await new Promise<void>((r) => {
570
+ resolveWait = r
571
+ stallTimer = setTimeout(() => {
572
+ resolveWait = null
573
+ r()
574
+ }, remaining + 100)
575
+ })
576
+ if (stallTimer) {
577
+ clearTimeout(stallTimer)
578
+ stallTimer = null
579
+ }
580
+ }
581
+ while (queue.length > 0) {
582
+ yield queue.shift()!
583
+ }
584
+ }
585
+ }
586
+ finally {
587
+ if (stallTimer) clearTimeout(stallTimer)
588
+ unsub()
589
+ opts.signal?.removeEventListener('abort', onAbort)
590
+ this.turnActive = false
591
+ }
592
+ }
593
+
594
+ /** 引擎事件 → AgentEvent(适配器核心) */
595
+ private mapEngineEvent(ev: Record<string, unknown>, taskId: string | undefined): AgentEvent[] {
596
+ const type = String(ev.type ?? '')
597
+ const props = (ev.properties ?? {}) as Record<string, unknown>
598
+ const sid = props.sessionID ?? props.sessionId
599
+ if (sid && sid !== this.sessionId) return [] // 多会话实例隔离(本 impl 一会话,防御)
600
+
601
+ const now = new Date().toISOString()
602
+ const statusEvent = (text: string): AgentEvent => ({
603
+ kind: 'status',
604
+ status: {
605
+ state: 'WORKING',
606
+ message: { messageId: randomUUID(), contextId: this.channelId, role: 'ROLE_AGENT', parts: [{ text }] },
607
+ timestamp: now,
608
+ },
609
+ })
610
+
611
+ switch (type) {
612
+ case 'message.part.delta': {
613
+ if (props.field === 'text' && typeof props.delta === 'string' && props.delta) {
614
+ return [{ kind: 'delta', delta: { text: props.delta } }]
615
+ }
616
+ return []
617
+ }
618
+ case 'message.part.updated': {
619
+ const part = props.part as Record<string, unknown> | undefined
620
+ if (!part) return []
621
+ const partId = String(part.id ?? '')
622
+ const partType = String(part.type ?? '')
623
+ if (partType === 'text' && typeof part.text === 'string' && partId) {
624
+ if (!this.partOrder.includes(partId)) this.partOrder.push(partId)
625
+ this.partTexts.set(partId, part.text)
626
+ }
627
+ else if (partType === 'tool') {
628
+ const state = (part.state ?? {}) as Record<string, unknown>
629
+ const tool = String(part.tool ?? 'tool')
630
+ const statusStr = String(state.status ?? '')
631
+ if (statusStr === 'pending' || statusStr === 'running') {
632
+ const input = state.input ?? part.input
633
+ return [statusEvent(`🔧 ${tool}${toolArgsPreview(input)}`)]
634
+ }
635
+ if (statusStr === 'error') {
636
+ return [statusEvent(`🔧 ${tool} 失败: ${String(state.error ?? '未知错误').slice(0, 200)}`)]
637
+ }
638
+ }
639
+ else if (partType === 'compaction') {
640
+ this.lastCompactAt = Date.now()
641
+ }
642
+ return []
643
+ }
644
+ case 'message.updated': {
645
+ const info = props.info as Record<string, unknown> | undefined
646
+ if (info?.role === 'assistant') {
647
+ const tokens = info.tokens as Record<string, unknown> | undefined
648
+ const input = Number(tokens?.input)
649
+ if (Number.isFinite(input) && input > 0) this.lastUsage = { input, at: Date.now() }
650
+ const err = info.error as Record<string, unknown> | undefined
651
+ if (err && this.turnActive) {
652
+ const code = String(err.name ?? 'UnknownError')
653
+ return [{
654
+ kind: 'error',
655
+ error: { code: `OPENCODE_LLM_${code}`, message: String(err.message ?? 'opencode 回合错误') },
656
+ }]
657
+ }
658
+ }
659
+ return []
660
+ }
661
+ case 'session.error': {
662
+ const err = props.error as Record<string, unknown> | undefined
663
+ if (!this.turnActive) return []
664
+ const data = (err?.data ?? {}) as Record<string, unknown>
665
+ const detail = String(data.message ?? err?.message ?? 'opencode 会话错误')
666
+ return [{
667
+ kind: 'error',
668
+ error: {
669
+ code: `OPENCODE_ERROR_${String(err?.name ?? 'UNKNOWN')}`,
670
+ message: `${detail}${data.statusCode != null ? ` (HTTP ${data.statusCode})` : ''}`,
671
+ },
672
+ }]
673
+ }
674
+ case 'session.status': {
675
+ const status = props.status as Record<string, unknown> | undefined
676
+ if (String(status?.type ?? '') === 'idle' && this.turnActive) {
677
+ return [{ kind: 'done', final: taskId ? { taskId } : undefined }]
678
+ }
679
+ return []
680
+ }
681
+ case 'session.idle': {
682
+ if (this.turnActive) {
683
+ return [{ kind: 'done', final: taskId ? { taskId } : undefined }]
684
+ }
685
+ return []
686
+ }
687
+ // ===== HITL =====
688
+ case 'permission.asked':
689
+ case 'permission.v2.asked': {
690
+ this.registerPermissionHitl(type === 'permission.v2.asked', props)
691
+ return []
692
+ }
693
+ case 'question.asked': {
694
+ this.registerQuestionHitl(props)
695
+ return []
696
+ }
697
+ case 'permission.replied':
698
+ case 'permission.v2.replied':
699
+ case 'question.replied':
700
+ case 'question.rejected': {
701
+ const id = String(props.id ?? '')
702
+ if (id && this.pendingHitl.has(id)) {
703
+ const p = this.pendingHitl.get(id)!
704
+ if (p.timer) clearTimeout(p.timer)
705
+ this.pendingHitl.delete(id)
706
+ }
707
+ return []
708
+ }
709
+ default:
710
+ return []
711
+ }
712
+ }
713
+
714
+ private registerPermissionHitl(v2: boolean, props: Record<string, unknown>): void {
715
+ const id = String(props.id ?? '')
716
+ if (!id) return
717
+ if (this.pendingHitl.has(id)) return
718
+ const sessionId = String(props.sessionID ?? this.sessionId ?? '')
719
+ const permission = String(props.permission ?? props.action ?? 'action')
720
+ const patterns = Array.isArray(props.patterns) ? props.patterns.map(String).join(', ') : ''
721
+ const v2res = Array.isArray(props.resources) ? props.resources.map(String).join(', ') : ''
722
+ const detail = patterns || v2res
723
+ const title = `opencode 权限请求:${permission}${detail ? `(${detail})` : ''}`
724
+ this.registerHitl(id, 'permission', sessionId, title, `引擎将执行 ${permission}${detail ? ` → ${detail}` : ''};批准放行一次,拒绝则引擎收到 reject。`)
725
+ }
726
+
727
+ private registerQuestionHitl(props: Record<string, unknown>): void {
728
+ const id = String(props.id ?? '')
729
+ if (!id || this.pendingHitl.has(id)) return
730
+ const sessionId = String(props.sessionID ?? this.sessionId ?? '')
731
+ const questions = Array.isArray(props.questions) ? props.questions : []
732
+ const first = (questions[0] ?? {}) as Record<string, unknown>
733
+ const title = String(first.question ?? first.header ?? 'opencode 提问')
734
+ this.registerHitl(id, 'question', sessionId, title, String(first.question ?? ''), 'input')
735
+ }
736
+
737
+ private registerHitl(id: string, type: 'permission' | 'question', sessionId: string, title: string, detail: string, method: 'confirm' | 'input' = 'confirm'): void {
738
+ const registry = getHitlRegistry()
739
+ registry.register({
740
+ kind: 'opencode-permission',
741
+ id,
742
+ agentId: this.selfAgentId,
743
+ agentName: this.agentName,
744
+ channelId: this.channelId,
745
+ pid: this.child?.pid,
746
+ method,
747
+ title,
748
+ detail,
749
+ createdAt: new Date().toISOString(),
750
+ expiresAt: null,
751
+ })
752
+ // 无人应答超时(fail-closed:到时自动拒绝),0 = 无限等待
753
+ const timeoutMs = harnessSettings().hitl_timeout_ms
754
+ const timer = timeoutMs > 0
755
+ ? setTimeout(() => {
756
+ void this.respondHitl('opencode-permission', id, { cancelled: true }).catch(() => {})
757
+ registry.resolve('opencode-permission', id, 'expired')
758
+ }, timeoutMs)
759
+ : null
760
+ this.pendingHitl.set(id, { kind: 'opencode-permission', id, type, sessionId, timer })
761
+ }
762
+
763
+ // ===== opencode 服务进程与 HTTP 客户端 =====
764
+
765
+ private async ensureServer(ctx: AgentRunContext): Promise<void> {
766
+ if (!this.workspace) this.workspace = ctx.workspace
767
+ if (!this.agentInfo) {
768
+ this.channelId = ctx.channelId
769
+ this.agentRole = ctx.role
770
+ this.refreshIdentity()
771
+ }
772
+ if (this.sessionId && this.child && !this.exited) return
773
+ this.serverStarting ??= this.startServer().finally(() => {
774
+ this.serverStarting = null
775
+ })
776
+ await this.serverStarting
777
+ }
778
+
779
+ private async startServer(): Promise<void> {
780
+ const command = this.config.command ?? harnessSettings().opencode_command
781
+ const port = await freePort()
782
+ const password = randomUUID()
783
+ const cwd = this.config.cwd ?? process.cwd()
784
+ this.exited = false
785
+ const child = spawnLineProcess(command, ['serve', '--port', String(port), '--hostname', '127.0.0.1'], {
786
+ cwd,
787
+ env: {
788
+ OPENCODE_SERVER_PASSWORD: password,
789
+ ...(this.config.dataDir ? { XDG_DATA_HOME: this.config.dataDir } : {}),
790
+ ...(this.config.configDir ? { XDG_CONFIG_HOME: this.config.configDir } : {}),
791
+ },
792
+ })
793
+ this.child = child
794
+ this.baseUrl = `http://127.0.0.1:${port}`
795
+ this.basicAuth = `Basic ${Buffer.from(`opencode:${password}`).toString('base64')}`
796
+ child.stderr?.setEncoding('utf-8')
797
+ child.stderr?.on('data', (d: string) => {
798
+ this.stderrTail = (this.stderrTail + d).slice(-8000)
799
+ })
800
+ const pid = child.pid
801
+ if (pid) {
802
+ registerHarnessProcess(pid, { harness: 'opencode', command, args: ['serve', '--port', String(port)] })
803
+ bindHarnessProcess(pid, { agentId: this.selfAgentId, channelId: this.channelId, name: this.agentName, role: this.agentRole })
804
+ }
805
+ child.on('exit', code => this.handleServerExit(code))
806
+
807
+ // 健康探测(serve 冷启动含 provider registry,预算 60s;/global/health 需 Basic 认证)
808
+ const deadline = Date.now() + 60_000
809
+ let healthy = false
810
+ while (Date.now() < deadline) {
811
+ if (this.exited) {
812
+ throw new Error(`opencode serve 启动失败(进程退出)${this.stderrTail ? `\nstderr: ${this.stderrTail.slice(-400)}` : ''}`)
813
+ }
814
+ try {
815
+ const res = await fetch(`${this.baseUrl}/global/health`, {
816
+ headers: { authorization: this.basicAuth },
817
+ signal: AbortSignal.timeout(2000),
818
+ })
819
+ if (res.ok) {
820
+ healthy = true
821
+ break
822
+ }
823
+ }
824
+ catch { /* 未就绪,重试 */ }
825
+ await new Promise(r => setTimeout(r, 500))
826
+ }
827
+ if (!healthy) throw new Error(`opencode serve 健康探测超时(60s)${this.stderrTail ? `\nstderr: ${this.stderrTail.slice(-400)}` : ''}`)
828
+
829
+ // 注册 MCP 桥(全量 host tools 注入;幂等;command 为 [可执行, 参数...] 数组形态)
830
+ try {
831
+ await this.api('POST', '/mcp', {
832
+ name: 'aw-host-tools',
833
+ config: {
834
+ type: 'local',
835
+ command: [process.execPath, resolveBridgePath(this.config.mcpBridgePath)],
836
+ environment: {
837
+ AW_BASE_URL: resolvePlatformBaseUrl(this.config.baseUrl),
838
+ AW_AGENT_ID: this.selfAgentId,
839
+ AW_AGENT_TOKEN: this.config.token ?? '',
840
+ AW_MCP_TOOL_TIMEOUT_MS: String(200_000),
841
+ },
842
+ },
843
+ })
844
+ }
845
+ catch (err) {
846
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] MCP 桥注册失败(host tools 不可用):`, err instanceof Error ? err.message : err)
847
+ }
848
+
849
+ // 建会话(权限策略缺省全 ask;部分版本不认 permission/model 字段时降级重试;
850
+ // model 按回合在 prompt_async 里传 —— session 创建面不接受它)
851
+ const body: Record<string, unknown> = {
852
+ title: `${this.agentName}@${this.channelId || 'channel'}`,
853
+ }
854
+ const createWith = async (extra: Record<string, unknown> | undefined): Promise<Record<string, unknown>> =>
855
+ this.api('POST', '/session', { ...body, ...(extra ?? {}) })
856
+ const created = await (this.config.permission ?? DEFAULT_PERMISSION)
857
+ ? createWith({ permission: this.config.permission ?? DEFAULT_PERMISSION }).catch(() => createWith(undefined))
858
+ : createWith(undefined)
859
+ this.sessionId = String(created?.id ?? '')
860
+ if (!this.sessionId) {
861
+ // 瞬态失败(实例刚起/内部分配竞态/权限规则不兼容)→ 无附加字段重试,最多 3 次
862
+ for (let i = 0; i < 3 && !this.sessionId; i++) {
863
+ await sleep(2500)
864
+ const retry = await createWith(undefined).catch(() => null)
865
+ this.sessionId = String(retry?.id ?? '')
866
+ }
867
+ }
868
+ if (!this.sessionId) {
869
+ // 会话建不出来(版本/参数不兼容):回收 serve 子进程与句柄后抛错,防泄漏
870
+ const detail = this.stderrTail ? ` stderr: ${this.stderrTail.slice(-300)}` : ''
871
+ killHarnessProcess(this.child?.pid ?? -1)
872
+ this.child = null
873
+ this.exited = true
874
+ throw new Error(`opencode 会话创建失败(无 session id)${detail}`)
875
+ }
876
+
877
+ // 订阅全局事件流
878
+ this.openEventStream()
879
+ }
880
+
881
+ private modelRef(): Record<string, string> | undefined {
882
+ const model = this.config.model
883
+ if (!model) return undefined
884
+ if (model.includes('/')) {
885
+ const [providerID, modelID] = model.split('/', 2)
886
+ return { providerID: providerID ?? '', modelID: modelID ?? '' }
887
+ }
888
+ return { providerID: 'opencode', modelID: model }
889
+ }
890
+
891
+ private handleServerExit(code: number | null): void {
892
+ if (this.exited) return
893
+ this.exited = true
894
+ this.sseAbort?.abort()
895
+ const pid = this.child?.pid
896
+ if (pid) markHarnessProcessExit(pid, code)
897
+ // 在途回合经引擎错误归位:下一回合 ensureServer 重生
898
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] opencode serve 退出(code=${code});下回合自动重生`)
899
+ }
900
+
901
+ /** 全局 SSE 订阅(断线重连;帧解析 data: 行) */
902
+ private openEventStream(): void {
903
+ this.sseAbort?.abort()
904
+ const ctrl = new AbortController()
905
+ this.sseAbort = ctrl
906
+ const connect = async (): Promise<void> => {
907
+ while (!ctrl.signal.aborted && !this.exited) {
908
+ try {
909
+ const res = await fetch(`${this.baseUrl}/event`, {
910
+ headers: { authorization: this.basicAuth, accept: 'text/event-stream' },
911
+ signal: ctrl.signal,
912
+ })
913
+ if (!res.ok || !res.body) throw new Error(`SSE HTTP ${res.status}`)
914
+ const reader = res.body.getReader()
915
+ const decoder = new TextDecoder()
916
+ let buf = ''
917
+ for (;;) {
918
+ const { done, value } = await reader.read()
919
+ if (done) break
920
+ buf += decoder.decode(value, { stream: true })
921
+ const chunks = buf.split('\n\n')
922
+ buf = chunks.pop() ?? ''
923
+ for (const chunk of chunks) {
924
+ for (const line of chunk.split('\n')) {
925
+ if (!line.startsWith('data:')) continue
926
+ const payload = line.slice(5).trim()
927
+ if (!payload) continue
928
+ try {
929
+ this.dispatchEngineEvent(JSON.parse(payload))
930
+ }
931
+ catch { /* 非 JSON data 行忽略 */ }
932
+ }
933
+ }
934
+ }
935
+ }
936
+ catch (err) {
937
+ if (ctrl.signal.aborted || this.exited) return
938
+ log.warn(`[OpenCodeAgent:${this.selfAgentId}] SSE 断开(1s 后重连):`, err instanceof Error ? err.message : err)
939
+ await new Promise(r => setTimeout(r, 1000))
940
+ }
941
+ }
942
+ }
943
+ void connect()
944
+ }
945
+
946
+ /** SSE 事件缓冲(回合未激活时事件即到即弃,激活后由 mapEngineEvent 消费) */
947
+ private engineListeners = new Set<(ev: Record<string, unknown>) => void>()
948
+
949
+ private dispatchEngineEvent(ev: Record<string, unknown>): void {
950
+ for (const fn of this.engineListeners) fn(ev)
951
+ }
952
+
953
+ private onEngineEvent(fn: (ev: Record<string, unknown>) => void): () => void {
954
+ this.engineListeners.add(fn)
955
+ return () => this.engineListeners.delete(fn)
956
+ }
957
+
958
+ private async api(method: string, path: string, body?: unknown): Promise<Record<string, unknown>> {
959
+ const res = await fetch(`${this.baseUrl}${path}`, {
960
+ method,
961
+ headers: { authorization: this.basicAuth, ...(body !== undefined ? { 'content-type': 'application/json' } : {}) },
962
+ ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
963
+ signal: AbortSignal.timeout(60_000),
964
+ })
965
+ if (res.status === 204) return {}
966
+ const text = await res.text()
967
+ let json: Record<string, unknown> = {}
968
+ try {
969
+ json = text ? JSON.parse(text) as Record<string, unknown> : {}
970
+ }
971
+ catch { /* 非 JSON 响应体 */ }
972
+ if (!res.ok) {
973
+ throw new Error(`opencode API ${method} ${path} → HTTP ${res.status}: ${String((json as { message?: string }).message ?? text.slice(0, 200))}`)
974
+ }
975
+ return json
976
+ }
977
+
978
+ private async promptAsync(text: string): Promise<void> {
979
+ if (!this.sessionId) throw new Error('会话未就绪')
980
+ await this.api('POST', `/session/${this.sessionId}/prompt_async`, {
981
+ parts: [{ type: 'text', text }],
982
+ ...(this.config.agent ? { agent: this.config.agent } : {}),
983
+ ...(this.config.model ? { model: this.modelRef() } : {}),
984
+ ...(this.config.variant ? { variant: this.config.variant } : (this.config.effort ? { variant: this.config.effort } : {})),
985
+ })
986
+ }
987
+ }