agentworkshop 0.7.40 → 0.7.44

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 (327) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/B8uy9iRW.js +1 -0
  3. package/.output/public/_nuxt/BGTYYQH-.js +1 -0
  4. package/.output/public/_nuxt/BUmHEJ77.js +2 -0
  5. package/.output/public/_nuxt/BY7YrV_D.js +1 -0
  6. package/.output/public/_nuxt/Bqcgz95s.js +18 -0
  7. package/.output/public/_nuxt/C7UlqPeD.js +1 -0
  8. package/.output/public/_nuxt/CTmDn-YP.js +1 -0
  9. package/.output/public/_nuxt/Cs8pVeVG.js +1 -0
  10. package/.output/public/_nuxt/{DcsCcxp4.js → D98NH8kG.js} +1 -1
  11. package/.output/public/_nuxt/DKySmNPI.js +14 -0
  12. package/.output/public/_nuxt/Di0NY_ht.js +1 -0
  13. package/.output/public/_nuxt/Du9v6qGB.js +1 -0
  14. package/.output/public/_nuxt/{C_iYD-EB.js → EHlEMRii.js} +1 -1
  15. package/.output/public/_nuxt/Eke1fs-U.js +1 -0
  16. package/.output/public/_nuxt/{DeJykBFf.js → H0BcqZtT.js} +1 -1
  17. package/.output/public/_nuxt/{C4oW1HsE.js → HSYEkkce.js} +1 -1
  18. package/.output/public/_nuxt/{DZshyNLa.js → IREZ1eC2.js} +1 -1
  19. package/.output/public/_nuxt/{D_OTvQza.js → J9oU00D1.js} +1 -1
  20. package/.output/public/_nuxt/OmpTerminalPanel.BxR5-lvi.css +1 -0
  21. package/.output/public/_nuxt/SSyAPaHc.js +1 -0
  22. package/.output/public/_nuxt/TownView.li4EMQxK.css +1 -0
  23. package/.output/public/_nuxt/VdLk4jLE2.js +1 -0
  24. package/.output/public/_nuxt/_id_.BhsXoEuk.css +1 -0
  25. package/.output/public/_nuxt/_id_.DQyj-WKN.css +1 -0
  26. package/.output/public/_nuxt/{_wsId_.B4WiqkIS.css → _wsId_.CTx-BlfF.css} +1 -1
  27. package/.output/public/_nuxt/aShsv_rG.js +19 -0
  28. package/.output/public/_nuxt/{yF0aYMF1.js → aesgXKSr.js} +3 -3
  29. package/.output/public/_nuxt/agents.B21nUEUX.css +1 -0
  30. package/.output/public/_nuxt/aml.ekTjxFkf.css +1 -0
  31. package/.output/public/_nuxt/builds/latest.json +1 -1
  32. package/.output/public/_nuxt/builds/meta/b5506ef0-f48e-4f14-a6c0-d65e505d0b09.json +1 -0
  33. package/.output/public/_nuxt/ca4TJ3Op.js +1 -0
  34. package/.output/public/_nuxt/channel-templates.DplM1pJ3.css +1 -0
  35. package/.output/public/_nuxt/daq.BdVmoIfe.css +1 -0
  36. package/.output/public/_nuxt/dcw.DCgyzpWV.css +1 -0
  37. package/.output/public/_nuxt/{default.J32SgqFY.css → default.Bh3L2HU8.css} +1 -1
  38. package/.output/public/_nuxt/lHAxdSsj.js +1 -0
  39. package/.output/public/_nuxt/pages.j9rzRocr.css +1 -0
  40. package/.output/public/_nuxt/plugins.DhiZbHU8.css +1 -0
  41. package/.output/public/_nuxt/settings.BRx9rIDg.css +1 -0
  42. package/.output/public/_nuxt/teams.BLlOPB_Z.css +1 -0
  43. package/.output/public/_nuxt/tokens.De8xzszn.css +1 -0
  44. package/.output/public/_nuxt/workshop.D1jFNkrn.css +1 -0
  45. package/.output/server/chunks/_/nitro.mjs +1058 -830
  46. package/.output/server/chunks/_/nitro.mjs.map +1 -1
  47. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs → OmpTerminalPanel-CVvxpsF7.mjs} +15 -15
  48. package/.output/server/chunks/build/{OmpTerminalPanel-Cu_s4i0A.mjs.map → OmpTerminalPanel-CVvxpsF7.mjs.map} +1 -1
  49. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs → TownView-CJ6IsDCc.mjs} +229 -228
  50. package/.output/server/chunks/build/{TownView-BuLAsmpR.mjs.map → TownView-CJ6IsDCc.mjs.map} +1 -1
  51. package/.output/server/chunks/build/{_id_-BU1wfOID.mjs → _id_-CVD_H0ir.mjs} +149 -147
  52. package/.output/server/chunks/build/_id_-CVD_H0ir.mjs.map +1 -0
  53. package/.output/server/chunks/build/{_id_-BYsEua57.mjs → _id_-CtxMb3qp.mjs} +47 -46
  54. package/.output/server/chunks/build/_id_-CtxMb3qp.mjs.map +1 -0
  55. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs → _wsId_-DpY3T-md.mjs} +516 -446
  56. package/.output/server/chunks/build/{_wsId_-BxlDcJHg.mjs.map → _wsId_-DpY3T-md.mjs.map} +1 -1
  57. package/.output/server/chunks/build/{agents-CLQqJF2y.mjs → agents-DsCkuXDV.mjs} +49 -46
  58. package/.output/server/chunks/build/agents-DsCkuXDV.mjs.map +1 -0
  59. package/.output/server/chunks/build/{aml-_7FdFL2p.mjs → aml-CT0xKGKI.mjs} +122 -105
  60. package/.output/server/chunks/build/aml-CT0xKGKI.mjs.map +1 -0
  61. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs +117 -0
  62. package/.output/server/chunks/build/builtin-catalog-edpDcgfL.mjs.map +1 -0
  63. package/.output/server/chunks/build/{channel-templates-p6SZNjlM.mjs → channel-templates-Dla9FbYa.mjs} +49 -37
  64. package/.output/server/chunks/build/channel-templates-Dla9FbYa.mjs.map +1 -0
  65. package/.output/server/chunks/build/{daq-cgyjKmJu.mjs → daq-DWWSKGAV.mjs} +95 -93
  66. package/.output/server/chunks/build/daq-DWWSKGAV.mjs.map +1 -0
  67. package/.output/server/chunks/build/{dcw-CoTxBlAZ.mjs → dcw-CT8k17_E.mjs} +46 -45
  68. package/.output/server/chunks/build/dcw-CT8k17_E.mjs.map +1 -0
  69. package/.output/server/chunks/build/{default-BE4r0FZN.mjs → default-D3525UFX.mjs} +16 -15
  70. package/.output/server/chunks/build/{default-BE4r0FZN.mjs.map → default-D3525UFX.mjs.map} +1 -1
  71. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs → logs--dByNyhw.mjs} +2 -2
  72. package/.output/server/chunks/build/{logs-BSOeZwwI.mjs.map → logs--dByNyhw.mjs.map} +1 -1
  73. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs → monitor-Dh2Kvaq5.mjs} +2 -2
  74. package/.output/server/chunks/build/{monitor-C0okQaXz.mjs.map → monitor-Dh2Kvaq5.mjs.map} +1 -1
  75. package/.output/server/chunks/build/{pages-DFxjn9Xa.mjs → pages-BHcSBM2D.mjs} +26 -20
  76. package/.output/server/chunks/build/pages-BHcSBM2D.mjs.map +1 -0
  77. package/.output/server/chunks/build/{plugins-lGlUr1lj.mjs → plugins-BNgIi61W.mjs} +23 -17
  78. package/.output/server/chunks/build/plugins-BNgIi61W.mjs.map +1 -0
  79. package/.output/server/chunks/build/{settings-Ddd1qx2Z.mjs → settings-ipYBDWdn.mjs} +45 -44
  80. package/.output/server/chunks/build/settings-ipYBDWdn.mjs.map +1 -0
  81. package/.output/server/chunks/build/{teams-MEDLZdMn.mjs → teams-5lx-CwFa.mjs} +47 -44
  82. package/.output/server/chunks/build/teams-5lx-CwFa.mjs.map +1 -0
  83. package/.output/server/chunks/build/{tokens-C7fTM5C2.mjs → tokens-q-IDT8Io.mjs} +73 -53
  84. package/.output/server/chunks/build/tokens-q-IDT8Io.mjs.map +1 -0
  85. package/.output/server/chunks/build/{town-qMPql9Se.mjs → town-QJWB5wng.mjs} +5 -4
  86. package/.output/server/chunks/build/town-QJWB5wng.mjs.map +1 -0
  87. package/.output/server/chunks/build/{useDaqStream-CIBaiGAl.mjs → useDaqStream-DfCFpb3p.mjs} +9 -3
  88. package/.output/server/chunks/build/useDaqStream-DfCFpb3p.mjs.map +1 -0
  89. package/.output/server/chunks/build/{useDcwStream-CBbiYnWe.mjs → useDcwStream-UPiX-3iO.mjs} +11 -2
  90. package/.output/server/chunks/build/useDcwStream-UPiX-3iO.mjs.map +1 -0
  91. package/.output/server/chunks/build/{workshop-BL5bhfs0.mjs → workshop-BIlCj_ZP.mjs} +45 -45
  92. package/.output/server/chunks/build/workshop-BIlCj_ZP.mjs.map +1 -0
  93. package/.output/server/chunks/routes/api/workshop/channel-templates/_id/instantiate.post.mjs +1 -1
  94. package/.output/server/chunks/routes/api/workshop/channels.post.mjs +3 -3
  95. package/.output/server/chunks/routes/api/workshop/dcw/index5.post.mjs +1 -1
  96. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/start.post.mjs +1 -1
  97. package/.output/server/chunks/routes/api/workshop/dcw/lines/_id/stop.post.mjs +1 -1
  98. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.delete.mjs +1 -1
  99. package/.output/server/chunks/routes/api/workshop/dcw/params/_id_.patch.mjs +1 -1
  100. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.delete.mjs +1 -1
  101. package/.output/server/chunks/routes/api/workshop/dcw/templates/_key_.patch.mjs +1 -1
  102. package/.output/server/chunks/routes/api/workshop/harnesses/_id/providers.get.mjs +1 -1
  103. package/.output/server/chunks/routes/api/workshop/harnesses.get.mjs +1 -1
  104. package/.output/server/chunks/routes/api/workshop/hitl/pending.get.mjs +1 -1
  105. package/.output/server/chunks/routes/api/workshop/hitl/respond.post.mjs +1 -1
  106. package/.output/server/chunks/routes/api/workshop/index.put.mjs +1 -1
  107. package/.output/server/chunks/routes/api/workshop/index5.get.mjs +3 -1
  108. package/.output/server/chunks/routes/api/workshop/index5.get.mjs.map +1 -1
  109. package/.output/server/chunks/routes/api/workshop/index6.get.mjs +3 -1
  110. package/.output/server/chunks/routes/api/workshop/index6.get.mjs.map +1 -1
  111. package/.output/server/chunks/routes/api/workshop/plugins/_name/disable.post.mjs +1 -1
  112. package/.output/server/chunks/routes/api/workshop/plugins/_name/enable.post.mjs +1 -1
  113. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.delete.mjs +1 -1
  114. package/.output/server/chunks/routes/api/workshop/scene/layouts/_channelId_.put.mjs +1 -1
  115. package/.output/server/chunks/routes/api/workshop/workspaces/_id/channel-templates/_tplId_.post.mjs +1 -1
  116. package/.output/server/chunks/routes/renderer.mjs +2 -2
  117. package/.output/server/chunks/virtual/entry.mjs +639 -88
  118. package/.output/server/chunks/virtual/entry.mjs.map +1 -1
  119. package/.output/server/chunks/virtual/precomputed.mjs +1 -1
  120. package/.output/server/package.json +1 -1
  121. package/README-zh.md +16 -6
  122. package/README.md +17 -7
  123. package/app/components/AppHeader.vue +961 -959
  124. package/app/components/workshop/A2aRpcDebugger.vue +237 -237
  125. package/app/components/workshop/AgentInspectorDrawer.vue +424 -424
  126. package/app/components/workshop/AgentLanesView.vue +998 -998
  127. package/app/components/workshop/ArtifactCard.vue +120 -120
  128. package/app/components/workshop/AssetLibrary.vue +452 -452
  129. package/app/components/workshop/ChannelSessionList.vue +812 -804
  130. package/app/components/workshop/CommandPalette.vue +269 -269
  131. package/app/components/workshop/Composer.vue +827 -827
  132. package/app/components/workshop/DeviceTwinPanel.vue +643 -643
  133. package/app/components/workshop/EventBlock.vue +602 -602
  134. package/app/components/workshop/FileSelectorModal.vue +188 -188
  135. package/app/components/workshop/InspectorPanel.vue +301 -301
  136. package/app/components/workshop/MemoryPanel.vue +364 -364
  137. package/app/components/workshop/MultiChannelView.vue +189 -189
  138. package/app/components/workshop/TaskBoardView.vue +686 -686
  139. package/app/components/workshop/TaskInspectorDrawer.vue +390 -390
  140. package/app/components/workshop/TranscriptTimeline.vue +601 -601
  141. package/app/components/workshop/blocks/ClusterArtifact.vue +61 -61
  142. package/app/components/workshop/blocks/ClusterError.vue +85 -85
  143. package/app/components/workshop/blocks/ClusterLife.vue +87 -87
  144. package/app/components/workshop/blocks/ClusterMember.vue +95 -93
  145. package/app/components/workshop/blocks/ClusterMemory.vue +84 -84
  146. package/app/components/workshop/blocks/ClusterOther.vue +67 -67
  147. package/app/components/workshop/blocks/ClusterStatus.vue +149 -147
  148. package/app/components/workshop/blocks/ClusterTool.vue +158 -158
  149. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1011 -1011
  150. package/app/components/workshop/town/TownView.vue +56 -56
  151. package/app/composables/workshop/useDaqStream.ts +7 -4
  152. package/app/composables/workshop/useDcwStream.ts +8 -2
  153. package/app/middleware/locale-cookie.global.ts +22 -0
  154. package/app/pages/aml/index.vue +24 -2
  155. package/app/pages/daq/[id].vue +20 -16
  156. package/app/pages/daq/index.vue +2310 -2307
  157. package/app/pages/dcw/[id].vue +26 -23
  158. package/app/pages/dcw/index.vue +3 -3
  159. package/app/pages/index.vue +987 -981
  160. package/app/pages/plugins/index.vue +317 -311
  161. package/app/pages/settings.vue +1564 -1562
  162. package/app/pages/tokens.vue +15 -15
  163. package/app/pages/workshop/agents.vue +612 -609
  164. package/app/pages/workshop/channel-templates.vue +18 -11
  165. package/app/pages/workshop/index.vue +668 -668
  166. package/app/pages/workshop/teams.vue +743 -740
  167. package/app/pages/workshop/w/[wsId].vue +704 -704
  168. package/app/plugins/locale-restore.client.ts +16 -1
  169. package/app/utils/builtin-catalog.ts +104 -0
  170. package/config.yml +170 -170
  171. package/docs/cli.en.md +2 -2
  172. package/docs/cli.md +2 -2
  173. package/docs/full-test-plan.md +2 -3
  174. package/docs/plugins.en.md +33 -1
  175. package/docs/plugins.md +29 -1
  176. package/docs/sdk.en.md +1 -1
  177. package/docs/sdk.md +1 -1
  178. package/i18n/locales/en.ts +293 -35
  179. package/i18n/locales/zh-CN.ts +265 -7
  180. package/package.json +4 -3
  181. package/scripts/_dbg-perms-e2e.mjs +132 -109
  182. package/scripts/_demo-agentteam-capture.mjs +278 -0
  183. package/scripts/_e2e-ui-functional.mjs +371 -0
  184. package/scripts/_i18n-en-cjk-scan.mjs +28 -0
  185. package/scripts/_i18n-en-verify.mjs +107 -0
  186. package/scripts/_i18n-extra-checks.mjs +53 -0
  187. package/scripts/_i18n-scan-hardcoded.mjs +180 -0
  188. package/scripts/_i18n-verify-keys.mjs +50 -0
  189. package/scripts/_loop-biax-campaign.mjs +130 -0
  190. package/scripts/_sweep-button-contrast.mjs +87 -0
  191. package/scripts/test-serial-bridge.mjs +418 -0
  192. package/scripts/ui/e2e-interactive.mjs +328 -0
  193. package/scripts/ui/record-demo.mjs +557 -0
  194. package/scripts/ui/seed-industrial-demo.mjs +171 -0
  195. package/server/api/workshop/daq/index.get.ts +3 -1
  196. package/server/api/workshop/dcw/index.get.ts +3 -0
  197. package/server/plugins/aw-plugins.ts +9 -7
  198. package/server/plugins-builtin/diag-bridge/index.mjs +608 -661
  199. package/server/plugins-builtin/rag-bridge/index.mjs +57 -133
  200. package/server/plugins-builtin/serial-bridge/client.mjs +210 -0
  201. package/server/plugins-builtin/serial-bridge/drivers.mjs +409 -0
  202. package/server/plugins-builtin/serial-bridge/i18n.json +62 -0
  203. package/server/plugins-builtin/serial-bridge/index.mjs +247 -0
  204. package/server/plugins-builtin/serial-bridge/lib.mjs +208 -0
  205. package/server/plugins-builtin/serial-bridge/rtu.mjs +168 -0
  206. package/server/services/workshop/daq/daq-controller.ts +7 -2
  207. package/server/services/workshop/daq/drivers.ts +89 -3
  208. package/server/services/workshop/dcw/dcw-controller.ts +5 -1
  209. package/server/services/workshop/dcw/drivers.ts +85 -2
  210. package/server/services/workshop/dcw/plugin-bridge.ts +45 -0
  211. package/server/services/workshop/plugins/host.mjs +30 -0
  212. package/shared/daq-protocol.ts +15 -0
  213. package/.output/public/_nuxt/88GOowgO2.js +0 -1
  214. package/.output/public/_nuxt/BOt2SP4z.js +0 -1
  215. package/.output/public/_nuxt/BP-NyKVG.js +0 -18
  216. package/.output/public/_nuxt/BXxH0UQE.js +0 -1
  217. package/.output/public/_nuxt/BsROmY89.js +0 -1
  218. package/.output/public/_nuxt/ClILjvWH.js +0 -1
  219. package/.output/public/_nuxt/CzOCSGLe.js +0 -1
  220. package/.output/public/_nuxt/D8qvkfyY.js +0 -1
  221. package/.output/public/_nuxt/DCn7QZ5N.js +0 -2
  222. package/.output/public/_nuxt/DS8qj8EL.js +0 -1
  223. package/.output/public/_nuxt/DUjW5Yq5.js +0 -1
  224. package/.output/public/_nuxt/Dihnimlk.js +0 -19
  225. package/.output/public/_nuxt/Dqw1lpr-.js +0 -1
  226. package/.output/public/_nuxt/Dr9v6C0f.js +0 -14
  227. package/.output/public/_nuxt/Du9ZJtnj.js +0 -1
  228. package/.output/public/_nuxt/OmpTerminalPanel.B_Pl5Ynm.css +0 -1
  229. package/.output/public/_nuxt/TownView.f-YOdXRs.css +0 -1
  230. package/.output/public/_nuxt/_id_.CM4bIgKY.css +0 -1
  231. package/.output/public/_nuxt/_id_.bNV69Dtf.css +0 -1
  232. package/.output/public/_nuxt/agents.ZD0rVdHE.css +0 -1
  233. package/.output/public/_nuxt/aml.BN8ZEW4h.css +0 -1
  234. package/.output/public/_nuxt/builds/meta/f4707884-7cf4-4a31-80d2-e3d72b73745f.json +0 -1
  235. package/.output/public/_nuxt/channel-templates.BOtahzPi.css +0 -1
  236. package/.output/public/_nuxt/daq.B0D3dPAc.css +0 -1
  237. package/.output/public/_nuxt/dcw.8Y7FqCVN.css +0 -1
  238. package/.output/public/_nuxt/pages.D7aSDlUI.css +0 -1
  239. package/.output/public/_nuxt/plugins.sb4nDGqr.css +0 -1
  240. package/.output/public/_nuxt/qr6R6Ha1.js +0 -1
  241. package/.output/public/_nuxt/settings.BTgR-NiE.css +0 -1
  242. package/.output/public/_nuxt/teams.CxnxKVVs.css +0 -1
  243. package/.output/public/_nuxt/tokens.BFY7qv4f.css +0 -1
  244. package/.output/public/_nuxt/workshop.CR_QzeAN.css +0 -1
  245. package/.output/server/chunks/build/_id_-BU1wfOID.mjs.map +0 -1
  246. package/.output/server/chunks/build/_id_-BYsEua57.mjs.map +0 -1
  247. package/.output/server/chunks/build/agents-CLQqJF2y.mjs.map +0 -1
  248. package/.output/server/chunks/build/aml-_7FdFL2p.mjs.map +0 -1
  249. package/.output/server/chunks/build/channel-templates-p6SZNjlM.mjs.map +0 -1
  250. package/.output/server/chunks/build/daq-cgyjKmJu.mjs.map +0 -1
  251. package/.output/server/chunks/build/dcw-CoTxBlAZ.mjs.map +0 -1
  252. package/.output/server/chunks/build/pages-DFxjn9Xa.mjs.map +0 -1
  253. package/.output/server/chunks/build/plugins-lGlUr1lj.mjs.map +0 -1
  254. package/.output/server/chunks/build/settings-Ddd1qx2Z.mjs.map +0 -1
  255. package/.output/server/chunks/build/teams-MEDLZdMn.mjs.map +0 -1
  256. package/.output/server/chunks/build/tokens-C7fTM5C2.mjs.map +0 -1
  257. package/.output/server/chunks/build/town-qMPql9Se.mjs.map +0 -1
  258. package/.output/server/chunks/build/useDaqStream-CIBaiGAl.mjs.map +0 -1
  259. package/.output/server/chunks/build/useDcwStream-CBbiYnWe.mjs.map +0 -1
  260. package/.output/server/chunks/build/workshop-BL5bhfs0.mjs.map +0 -1
  261. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.continue.json +0 -1
  262. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.json +0 -1
  263. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/054bb4bc4e4217a2ab0b0c6b663747214a9af464f5568ea60e784704e340bb0f.source +0 -153
  264. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/0554197c3d2bac203a1f5c48a5d52495d1336db1bd7aa4f4c19875810363e684.source +0 -153
  265. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/05c203d12a954fffba942e1d626e3f5fec05b18a5aef2bac003b7884a4b77406.source +0 -431
  266. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/145a6e6ba811af35aed31e0cc3211f53706a14980fa069ee9e3c1591139f96f0.source +0 -180
  267. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/1ae0fb281f97899c025e368ca73f41349b01fb5f85b19e08d7ebccff49095ed5.source +0 -112
  268. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/20ee9967aa0541c516db7575bdd4a1a745939bc7016bd10d7635903113edb8ec.source +0 -227
  269. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/233751843aeba9d4c5263f275b8102de00443c06f286918cbd23e0b6729e01aa.source +0 -131
  270. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/263c2e05b425e5c322e60c6475279f963bab3a873eb521b21df7fec935a46597.source +0 -160
  271. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/2ac5eaac28eaaee2178c4b32014df8e732f9dd432a285a872f5b7f31c1395fa4.source +0 -157
  272. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/33a0db0d2d95d2c11d0720090458e5fba1425376f5ceb5b422d1d3471be3226b.source +0 -348
  273. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/359e474ae83db35e4615d3728de6bf694b64d4dce9b536730a3b6518f9c0494a.source +0 -296
  274. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/37a4c3c31c4b70f6b719c53d1e9c4fcba603f31adfdd11bb6ef9f0d094923c56.source +0 -285
  275. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/461feca1c14a695eb8b0f17a6f95fe97eeceabc0510faaea4ba6d25bde147d8d.source +0 -217
  276. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/4cfadbda8591f29d5e1e230dc000e701b756e850441b3900fb596a4d2f6e98c2.source +0 -301
  277. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/50ca2810cf0b248c96948994c0c404531bbad6e553166b6816b3b03bfa0f75d2.source +0 -151
  278. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/52d9e8cb591a9ae86e238c3620a610cd386717bee222c0f37b25b2ac7e523dc4.source +0 -135
  279. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/6c87daafa4c006560a954636a97333f6123153c9d34d96203f7ee3a14e556357.source +0 -156
  280. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/77bc47854b577900621cacf1697f81fa2bc005af129d37614a97a3441c08f99f.source +0 -72
  281. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/7bbb789d3a527817118cf8399ed1861d6a962ade10878fd07223435d333a7089.source +0 -469
  282. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/86b7c1daafc8b60ba9982dde5bf1bcc74265709483c176e71f23ec6fc267451f.source +0 -259
  283. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/8df66d62bd41984d0970e8236882080c5085ac937d07a29779463d6a03b37c76.source +0 -97
  284. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/9962f2d1b3a85137bd40cc835725600b39f89ee02a27c06b2e0402e1eafde115.source +0 -277
  285. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a1090ea066b792cb201739f4994e37bf7c12f52e805239a1eab87f18a537f266.source +0 -171
  286. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/a5241091650134d0919897e086a606a3846c8b2b54f8b4c84a8696c145ac3e9e.source +0 -425
  287. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/af19fa4c6e34d5540028be4b17600161283af3a2a2dfc61a3fdc0834436a0c14.source +0 -99
  288. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3713d78e2b2f93905ff6be8d58a8d0a2f42dea322eb67c987fda22ff6a084d5.source +0 -325
  289. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/b3849943c3aff102d1af815631fc843a2a52c17646a4b04696ece323e483bbec.source +0 -332
  290. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/bac735a3803a6650b7f1eb8f587e6dc5c68ea055000c3c99a11789438b78e837.source +0 -43
  291. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d32c24d61eb8b33c73e5a8fc7e4dc7ef437aed238ee4371c2b00617e6104090a.source +0 -154
  292. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/d5170dc9a9879fda04fdf91d8a110d4efb6787ee38dda596d4da899883d36a72.source +0 -531
  293. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/dc59bcd7bb397be63ba2f2c3fec23f3782dcb17d2d75a9981eeced761f33eb32.source +0 -439
  294. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/eb5ff8cf66b92aec7bf6726781d8df74faa2b030c3aaac17d6b00c1fc04c9b32.source +0 -323
  295. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f10615a6fae18436e70d1201b2d44fdae3174a3aa7bb4db97dea1b3ed291d721.source +0 -433
  296. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f36d3e271668bc1260c2823542d22dbf1d0f7041ff16b1ac175bce2256e582ca.source +0 -280
  297. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/f94449380af09f31ac352152007146a75cc80bae8d6411ffe57b2c56f933b0ff.source +0 -117
  298. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/fe4dfd81178fd6b648335f6405d9ede71319aebde796008e50db21f8adf44c99.source +0 -160
  299. package/scripts/.mimosa/hook-state/sess_aeaecb58-8833-4b83-b93c-050467d21e03.mtxwtxme-61028-1f4519fbc4.baseline/ffb4e3aa548cfdadabaa44ab599f9b6a3ca6288176a2cc7a4b2fc2a12b5fb848.source +0 -101
  300. package/scripts/.mimosa/hook-status/sess_aeaecb58-8833-4b83-b93c-050467d21e03-d944d71bb3.json +0 -14
  301. package/scripts/_dbg-audit-all-pages.mjs +0 -43
  302. package/scripts/_dbg-daq-frames-e2e.mjs +0 -118
  303. package/scripts/_dbg-daq-rowstyle-verify.mjs +0 -112
  304. package/scripts/_dbg-hitl-timeout-e2e.mjs +0 -93
  305. package/scripts/_dbg-live-line-e2e.mjs +0 -279
  306. package/scripts/_dbg-minimal-omp.mjs +0 -77
  307. package/scripts/_dbg-mode-nav.mjs +0 -173
  308. package/scripts/_dbg-real-scenario-timeline.log +0 -55
  309. package/scripts/_dbg-team-repro.mjs +0 -76
  310. package/scripts/_dbg-town-agents-probe.mjs +0 -60
  311. package/scripts/_dbg-visual-acceptance.mjs +0 -63
  312. package/scripts/_townview_style.css +0 -1185
  313. package/scripts/_townview_template.html +0 -1215
  314. package/server/data/agent-node-bindings.json +0 -554
  315. package/server/data/daq-templates.json +0 -16
  316. package/server/data/daqs.json +0 -7464
  317. package/server/data/dcw-lines.json +0 -1787
  318. package/server/data/dcw-products.json +0 -1626
  319. package/server/data/dcw-recipes.json +0 -4672
  320. package/server/data/dcw-rollback.json +0 -20754
  321. package/server/data/dcw-runs.json +0 -6354
  322. package/server/data/dcw-templates.json +0 -146
  323. package/server/data/dcw-writes.json +0 -15650
  324. package/server/data/dcws.json +0 -9033
  325. package/server/data/device-twins.json +0 -133
  326. package/server/data/line-runs.json +0 -322
  327. package/server/data/scene-layouts.json +0 -277
@@ -1,531 +0,0 @@
1
- /**
2
- * 多 Harness 真实引擎端到端:opencode / codex / dsh 共用一套 AgentInterface。
3
- *
4
- * 每个 harness 场景(真实子进程 + 真实 LLM):
5
- * A. 工具闭环:assign → 引擎调 MCP 桥工具(report_progress → complete_task)→
6
- * 任务 COMPLETED + progress=50 + 交付物落库(验证:引擎侧工具注入 → HTTP 回程 →
7
- * manager.invokeHostTool → 共享 host-tool-bridge → workspace 全链路)
8
- * B. HITL 闭环:强制文件写(严格沙箱/全 ask 权限)→ 引擎审批请求 → hitl-registry →
9
- * respondHarnessHitl 批准 → 引擎继续 → 任务 COMPLETED
10
- *
11
- * 运行:npx tsx --tsconfig .nuxt/tsconfig.server.json scripts/e2e-multi-harness.ts
12
- * 前置:PATH 上有 opencode/codex/dsh 且已完成各自鉴权。
13
- */
14
- import type { DatabaseSync } from 'node:sqlite'
15
- import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'
16
- import { copyFileSync, mkdirSync } from 'node:fs'
17
- import { randomUUID } from 'node:crypto'
18
- import { homedir } from 'node:os'
19
- import { join } from 'node:path'
20
- import { openWorkshopDb } from '../server/services/workshop/db/database'
21
- import { createChannelRepo } from '../server/services/workshop/db/channel.repo'
22
- import { createAgentRepo } from '../server/services/workshop/db/agent.repo'
23
- import { createChannelAgentRepo } from '../server/services/workshop/db/channel-agent.repo'
24
- import { createTaskRepo } from '../server/services/workshop/db/task.repo'
25
- import { createMemoryRepo } from '../server/services/workshop/db/memory.repo'
26
- import { createChannelEventRepo } from '../server/services/workshop/db/channel-event.repo'
27
- import { createTeamRepo } from '../server/services/workshop/db/team.repo'
28
- import { createTeamMemberRepo } from '../server/services/workshop/db/team-member.repo'
29
- import { createMessageRepo } from '../server/services/workshop/db/message.repo'
30
- import { createSubscriptionRepo } from '../server/services/workshop/db/subscription.repo'
31
- import { createUserRepo } from '../server/services/workshop/db/user.repo'
32
- import { createAgentChannelManager } from '../server/services/workshop/runtime/manager'
33
- import type { AgentChannelManager } from '../server/services/workshop/runtime/manager'
34
- import { createAgentImpl } from '../server/services/workshop/agents/factory'
35
- import { getHitlRegistry } from '../server/services/workshop/agents/hitl-registry'
36
-
37
- let failures = 0
38
- const sleep = (ms: number): Promise<void> => new Promise(r => setTimeout(r, ms))
39
- function check(name: string, ok: boolean, detail = ''): void {
40
- console.log(` ${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
41
- if (!ok) failures += 1
42
- }
43
- function checkSkip(name: string, reason: string): void {
44
- console.log(` SKIP ${name} — ${reason}`)
45
- }
46
-
47
- const TIMING = { wire: 60_000, task: 300_000, hitl: 240_000 }
48
-
49
- function makeManager(db: DatabaseSync): AgentChannelManager {
50
- return createAgentChannelManager({
51
- repos: {
52
- channels: createChannelRepo(db),
53
- agents: createAgentRepo(db),
54
- channelAgents: createChannelAgentRepo(db),
55
- messages: createMessageRepo(db),
56
- subscriptions: createSubscriptionRepo(db),
57
- tasks: createTaskRepo(db),
58
- memories: createMemoryRepo(db),
59
- users: createUserRepo(db),
60
- channelEvents: createChannelEventRepo(db),
61
- teams: createTeamRepo(db),
62
- teamMembers: createTeamMemberRepo(db),
63
- },
64
- implFactory: createAgentImpl,
65
- db,
66
- })
67
- }
68
-
69
- /** 桥回程 HTTP 面(模拟 nitro 路由:token 鉴权 → manager 全量工具分发) */
70
- function startBridgeHttp(manager: AgentChannelManager): Promise<{ port: number, close: () => void }> {
71
- const handler = (req: IncomingMessage, res: ServerResponse): void => {
72
- const token = req.headers['x-aw-agent-token']
73
- const reply = (code: number, body: unknown): void => {
74
- res.writeHead(code, { 'content-type': 'application/json' })
75
- res.end(JSON.stringify(body))
76
- }
77
- if (req.method === 'GET' && req.url?.startsWith('/api/workshop/agent-tools/list')) {
78
- const url = new URL(req.url, 'http://x')
79
- const agentId = url.searchParams.get('agentId') ?? ''
80
- const resolved = manager.resolveAgentByToken(String(token ?? ''))
81
- if (!resolved || resolved.agentId !== agentId) return reply(401, { code: 401, message: 'token 校验失败' })
82
- try {
83
- return reply(200, { code: 0, data: { tools: manager.hostToolDefsFor(agentId) } })
84
- }
85
- catch (err) {
86
- return reply(404, { code: 404, message: err instanceof Error ? err.message : String(err) })
87
- }
88
- }
89
- if (req.method === 'POST' && req.url?.startsWith('/api/workshop/agent-tools/invoke')) {
90
- let body = ''
91
- req.on('data', (d) => {
92
- body += d
93
- })
94
- req.on('end', () => {
95
- void (async () => {
96
- const parsed = JSON.parse(body || '{}') as { agentId?: string, tool?: string, args?: Record<string, unknown> }
97
- const resolved = manager.resolveAgentByToken(String(token ?? ''))
98
- if (!resolved || resolved.agentId !== parsed.agentId) return reply(401, { code: 401, message: 'token 校验失败' })
99
- try {
100
- const result = await manager.invokeHostTool({
101
- agentId: String(parsed.agentId),
102
- token: String(token ?? ''),
103
- tool: String(parsed.tool ?? ''),
104
- args: parsed.args ?? {},
105
- })
106
- return reply(200, { code: 0, data: { result } })
107
- }
108
- catch (err) {
109
- const msg = err instanceof Error ? err.message : String(err)
110
- const code = (err as { code?: string }).code === 'NOT_FOUND' ? 404 : 500
111
- return reply(code, { code, message: msg })
112
- }
113
- })()
114
- })
115
- return
116
- }
117
- reply(404, { code: 404, message: 'not found' })
118
- }
119
- return new Promise((resolve) => {
120
- const server = createServer(handler)
121
- server.listen(0, '127.0.0.1', () => {
122
- const port = (server.address() as { port: number }).port
123
- resolve({ port, close: () => server.close() })
124
- })
125
- })
126
- }
127
-
128
- function getEngine(manager: AgentChannelManager): { get(id: string): { state: string, progress: number, artifacts: Array<{ parts: Array<{ text?: string }> }> } | undefined } {
129
- return (manager as unknown as { getTaskEngine(): { get(id: string): { state: string, progress: number, artifacts: Array<{ parts: Array<{ text?: string }> }> } | undefined } }).getTaskEngine()
130
- }
131
-
132
- async function waitTask(manager: AgentChannelManager, taskId: string, timeoutMs: number): Promise<string> {
133
- const engine = getEngine(manager)
134
- const deadline = Date.now() + timeoutMs
135
- while (Date.now() < deadline) {
136
- const t = engine.get(taskId)
137
- if (t && ['COMPLETED', 'FAILED', 'CANCELED'].includes(t.state)) return t.state
138
- await sleep(500)
139
- }
140
- return engine.get(taskId)?.state ?? 'UNKNOWN'
141
- }
142
-
143
- async function waitWired(manager: AgentChannelManager, agentId: string, timeoutMs: number): Promise<boolean> {
144
- const deadline = Date.now() + timeoutMs
145
- while (Date.now() < deadline) {
146
- if (manager.getChannelAgent(agentId)?.wired) return true
147
- await sleep(200)
148
- }
149
- return false
150
- }
151
-
152
- /** 等待 HITL 待办出现 */
153
- async function waitHitl(kind: string, timeoutMs: number): Promise<{ kind: string, id: string, agentId: string, title?: string } | null> {
154
- const registry = getHitlRegistry()
155
- const deadline = Date.now() + timeoutMs
156
- while (Date.now() < deadline) {
157
- const hit = registry.snapshot().find(i => i.kind === kind)
158
- if (hit) return hit
159
- await sleep(300)
160
- }
161
- return null
162
- }
163
-
164
- /** 各 harness 场景配置 */
165
- interface HarnessPlan {
166
- harness: 'opencode' | 'codex' | 'dsh' | 'claude' | 'gemini' | 'copilot' | 'cursor' | 'crush' | 'goose' | 'qwen' | 'pi' | 'hermes'
167
- /** HITL kind;null = 引擎无程序化审批面(场景 B 策略性跳过) */
168
- hitlKind: string | null
169
- /** HITL 任务的文件写指令(严格沙箱下强制触发审批) */
170
- writeInstruction: string
171
- config: Record<string, unknown>
172
- /** 任务闭环等待预算(慢推理模型放宽) */
173
- taskWaitMs?: number
174
- /** 引擎无自定义 provider 面(协议/鉴权锁定):管线验证后 LLM 实测按 SKIP 收口 */
175
- expectAuthFail?: boolean
176
- }
177
-
178
- const ZHIPU_KEY = process.env.ZHIPU_API_KEY ?? ''
179
- const ZHIPU_ANTHROPIC_BASE = 'https://open.bigmodel.cn/api/anthropic'
180
- const ZHIPU_OPENAI_BASE = 'https://open.bigmodel.cn/api/coding/paas/v4'
181
-
182
- const PLANS: HarnessPlan[] = [
183
- {
184
- harness: 'opencode',
185
- hitlKind: 'opencode-permission',
186
- writeInstruction: `Use your file write/edit tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-opencode`,
187
- config: { promptTimeoutMs: 240_000, model: 'zhipuai-coding-plan/glm-5.3-flash', contextWindow: 1_000_000 },
188
- },
189
- {
190
- harness: 'codex',
191
- hitlKind: 'codex-approval',
192
- writeInstruction: `Run this exact shell command (it requires a permission approval — if the platform raises an approval request, wait for it to be approved): powershell -Command "Set-Content -Path aw-hitl.txt -Value 'aw-hitl-codex'"`,
193
- taskWaitMs: 480_000,
194
- config: { promptTimeoutMs: 600_000, approvalPolicy: 'on-request', sandbox: 'read-only', systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.' },
195
- },
196
- {
197
- harness: 'dsh',
198
- hitlKind: 'dsh-permission',
199
- writeInstruction: `Use your file write tool (str_replace_editor write command or similar) to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-dsh`,
200
- config: { promptTimeoutMs: 240_000, model: 'glm-5.3-flash' },
201
- },
202
- {
203
- harness: 'claude',
204
- hitlKind: 'claude-permission',
205
- writeInstruction: `Use your file write tool (Write) to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-claude. A permission prompt will be raised — wait for it to be approved.`,
206
- taskWaitMs: 480_000,
207
- config: {
208
- promptTimeoutMs: 600_000,
209
- model: 'glm-5.3-flash',
210
- apiKey: ZHIPU_KEY,
211
- providerBaseUrl: ZHIPU_ANTHROPIC_BASE,
212
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
213
- },
214
- },
215
- {
216
- harness: 'qwen',
217
- hitlKind: 'qwen-permission',
218
- writeInstruction: `Use your file write/edit tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-qwen. If a tool confirmation is requested, wait for it to be approved.`,
219
- taskWaitMs: 480_000,
220
- config: {
221
- promptTimeoutMs: 600_000,
222
- model: 'glm-5.3-flash',
223
- apiKey: ZHIPU_KEY,
224
- providerBaseUrl: ZHIPU_OPENAI_BASE,
225
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
226
- },
227
- },
228
- {
229
- harness: 'crush',
230
- hitlKind: null,
231
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-crush`,
232
- taskWaitMs: 480_000,
233
- config: {
234
- promptTimeoutMs: 600_000,
235
- model: 'zhipu/glm-5.3-flash',
236
- apiKey: ZHIPU_KEY,
237
- command: process.env.CRUSH_COMMAND ?? '',
238
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
239
- },
240
- },
241
- {
242
- harness: 'goose',
243
- hitlKind: null,
244
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-goose`,
245
- taskWaitMs: 480_000,
246
- config: {
247
- promptTimeoutMs: 600_000,
248
- model: 'glm-5.3-flash',
249
- apiKey: ZHIPU_KEY,
250
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
251
- },
252
- },
253
- {
254
- harness: 'pi',
255
- hitlKind: null,
256
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-pi`,
257
- taskWaitMs: 480_000,
258
- config: {
259
- promptTimeoutMs: 600_000,
260
- provider: 'zhipu',
261
- model: 'glm-5.3-flash',
262
- apiKey: ZHIPU_KEY,
263
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
264
- },
265
- },
266
- {
267
- harness: 'hermes',
268
- hitlKind: 'hermes-permission',
269
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-hermes. If a permission approval is raised, wait for it to be approved.`,
270
- taskWaitMs: 480_000,
271
- config: {
272
- promptTimeoutMs: 600_000,
273
- apiKey: ZHIPU_KEY,
274
- systemPromptPrefix: 'Be direct and minimal: never explore the repository, never read files, never run shell commands unless the task explicitly requires one. When a task lists platform tool calls, execute exactly those and finish.',
275
- },
276
- },
277
- {
278
- harness: 'gemini',
279
- hitlKind: null,
280
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-gemini`,
281
- config: {
282
- promptTimeoutMs: 240_000,
283
- model: 'glm-5.3-flash',
284
- apiKey: process.env.GEMINI_API_KEY ?? 'dummy-invalid-key',
285
- },
286
- expectAuthFail: true,
287
- },
288
- {
289
- harness: 'copilot',
290
- hitlKind: null,
291
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-copilot`,
292
- config: {
293
- promptTimeoutMs: 240_000,
294
- apiKey: process.env.COPILOT_GITHUB_TOKEN ?? 'dummy-invalid-token',
295
- },
296
- expectAuthFail: true,
297
- },
298
- {
299
- harness: 'cursor',
300
- hitlKind: null,
301
- writeInstruction: `Use your file write tool to create a file named aw-hitl.txt in the current directory with exactly this content: aw-hitl-cursor`,
302
- config: {
303
- promptTimeoutMs: 240_000,
304
- apiKey: process.env.CURSOR_API_KEY ?? 'dummy-invalid-key',
305
- command: process.env.CURSOR_COMMAND ?? '',
306
- },
307
- expectAuthFail: true,
308
- },
309
- ]
310
-
311
- /** 为引擎准备隔离的凭据目录(codex CODEX_HOME / opencode XDG_DATA_HOME):拷贝 auth 凭据 */
312
- function seedEngineHome(kind: 'codex' | 'opencode'): string {
313
- const dir = join(process.env.TEMP ?? '/tmp', `aw-e2e-${kind}-${randomUUID().slice(0, 8)}`)
314
- mkdirSync(dir, { recursive: true })
315
- if (kind === 'codex') {
316
- try {
317
- copyFileSync(join(homedir(), '.codex', 'auth.json'), join(dir, 'auth.json'))
318
- }
319
- catch { /* 无凭据则依赖全局 CODEX_HOME,引擎侧会显性报错 */ }
320
- try {
321
- // 全局 config(自定义 provider/model/网关)一并种子化;impl 追加 [mcp_servers.aw] 段
322
- copyFileSync(join(homedir(), '.codex', 'config.toml'), join(dir, 'config.toml'))
323
- // config 内相对路径引用的目录文件(如 model_catalog_json)
324
- try {
325
- copyFileSync(join(homedir(), '.codex', 'cc-switch-model-catalog.json'), join(dir, 'cc-switch-model-catalog.json'))
326
- }
327
- catch { /* 无此文件则跳过 */ }
328
- }
329
- catch { /* 同上 */ }
330
- }
331
- else {
332
- try {
333
- mkdirSync(join(dir, 'opencode'), { recursive: true })
334
- copyFileSync(join(homedir(), '.local', 'share', 'opencode', 'auth.json'), join(dir, 'opencode', 'auth.json'))
335
- }
336
- catch { /* 同上 */ }
337
- }
338
- return dir
339
- }
340
-
341
- async function runScenario(manager: AgentChannelManager, bridgePort: number, plan: HarnessPlan): Promise<void> {
342
- const { harness } = plan
343
- console.log(`\n━━━━━ ${harness} 场景 ━━━━━`)
344
- const ch = await manager.createChannel({ name: `mh-${harness}`, leadAgent: { name: 'lead', harness: 'mock' } })
345
- const extra: Record<string, unknown> = {}
346
- if (harness === 'codex') extra.codexHome = seedEngineHome('codex')
347
- if (harness === 'opencode') {
348
- extra.dataDir = seedEngineHome('opencode')
349
- extra.configDir = join(process.env.TEMP ?? '/tmp', `aw-e2e-oc-cfg-${randomUUID().slice(0, 8)}`)
350
- }
351
- const w = await manager.createAgent({
352
- name: `worker-${harness}`,
353
- harness,
354
- config: { ...plan.config, ...extra, baseUrl: `http://127.0.0.1:${bridgePort}`, superviseTimeoutMs: 150_000 },
355
- })
356
- await manager.addAgentToChannel({ channelId: ch.channelId, agentId: w.id, role: 'worker' })
357
- // 克隆实例 id(channel_agents.id;与模板 id w.id 不同)
358
- const members = await manager.listChannelAgents(ch.channelId)
359
- const workerId = members.find(m => m.id !== ch.channelId && m.role === 'worker')!.id
360
-
361
- // 事件透传(debug:错误/工具状态可见)+ 引擎凭据失效探测
362
- let providerAuthFailed = false
363
- let sawToolStatus = false
364
- manager.subscribeChannelEvents(ch.channelId, (event) => {
365
- if (event.kind === 'error') {
366
- if (/AUTH|401|403|身份验证|APIError|API key not valid|API_KEY_INVALID|Unauthorized|sign in|not logged|credentials/i.test(`${event.error.code} ${event.error.message}`)) providerAuthFailed = true
367
- console.log(` [event] error ${event.error.code}: ${event.error.message.slice(0, 220)}`)
368
- }
369
- else if (event.kind === 'status' && event.status.message) {
370
- const text = event.status.message.parts.map(p => 'text' in p ? p.text : '').join('')
371
- if (text.includes('🔧')) sawToolStatus = true
372
- console.log(` [event] status: ${text.slice(0, 160)}`)
373
- }
374
- else if (event.kind === 'delta') process.stdout.write('.')
375
- else if (event.kind === 'artifact') console.log(` [event] artifact(${event.artifact.name})`)
376
- else if (event.kind === 'done') console.log(` [event] done`)
377
- })
378
-
379
- // 工具确认自动应答守卫:任务 A 期间若引擎对 MCP 工具触发确认(trust 未被引擎尊重时),
380
- // 平台侧代为批准(真实部署中由人在 HITL 铃标应答;这里验证管线连通性)
381
- let autoApprove = true
382
- const registry = getHitlRegistry()
383
- const autoTimer: NodeJS.Timeout | null = plan.hitlKind
384
- ? setInterval(() => {
385
- if (!autoApprove) return
386
- for (const item of registry.snapshot()) {
387
- if (item.kind !== plan.hitlKind) continue
388
- void manager.respondHarnessHitl(item.agentId, item.kind, item.id, { confirmed: true }).catch(() => {})
389
- }
390
- }, 2_000)
391
- : null
392
- // 场景任何退出路径都必须清掉 interval,否则事件循环被吊住,e2e 进程永不退出
393
- let scenarioSettled = false
394
- const settle = (): void => {
395
- if (scenarioSettled) return
396
- scenarioSettled = true
397
- if (autoTimer) clearInterval(autoTimer)
398
- }
399
- try {
400
- // ---- A. 工具闭环 ----
401
- console.log(` ── A. MCP 桥工具闭环(report_progress + complete_task)──`)
402
- const taskA = await manager.submitChannelTask({
403
- channelId: ch.channelId,
404
- assigneeId: workerId,
405
- title: `${harness} tool-loop task`,
406
- description: [
407
- `SINGLE-TURN MICRO-TASK — do exactly this and nothing else:`,
408
- `1. Immediately call the report_progress tool: progress=50, message="halfway".`,
409
- `2. Immediately call the complete_task tool: summary="tool loop closed by ${harness}", deliverable="done".`,
410
- `Forbidden: exploring files, running shell commands, searching memory, polling messages, reading MCP resources. The two tool calls above are the entire task.`,
411
- ].join('\n'),
412
- })
413
- const wired = await waitWired(manager, workerId, TIMING.wire)
414
- check(`[${harness}] worker 运行时装配`, wired)
415
- const stateA = await waitTask(manager, taskA.id, plan.taskWaitMs ?? TIMING.task)
416
- autoApprove = false
417
- if (plan.expectAuthFail && stateA !== 'COMPLETED' && !providerAuthFailed) {
418
- // 引擎无自定义 provider 面(gemini=Google 鉴权锁定/copilot=GitHub 鉴权/cursor=Cursor 账号):
419
- // 拉起/参数组装/回程管线已验证,LLM 凭据失败属预期 —— 按环境阻塞 SKIP,不判 FAIL
420
- for (const name of [
421
- `[${harness}] 任务闭环 COMPLETED(引擎 → MCP 桥 → 平台工具)`,
422
- `[${harness}] report_progress 经桥落库(progress≥50)`,
423
- `[${harness}] 引擎审批请求登记到 HITL`,
424
- `[${harness}] HITL 批准后任务闭环 COMPLETED`,
425
- ]) checkSkip(name, '引擎无自定义 provider 面(鉴权协议锁定),LLM 实测需原生订阅凭据')
426
- console.log(' (场景提前结束:预期内的凭据不可用)')
427
- await manager.unloadAgent(ch.channelId, workerId).catch(() => {})
428
- return
429
- }
430
- if (providerAuthFailed && stateA !== 'COMPLETED') {
431
- // 引擎侧 provider 凭据失效(如 opencode 存储的 API key 过期):环境问题而非集成缺陷
432
- for (const name of [
433
- `[${harness}] 任务闭环 COMPLETED(引擎 → MCP 桥 → 平台工具)`,
434
- `[${harness}] report_progress 经桥落库(progress≥50)`,
435
- `[${harness}] 引擎审批请求登记到 HITL`,
436
- `[${harness}] HITL 批准后任务闭环 COMPLETED`,
437
- ]) checkSkip(name, '引擎 provider 凭据 401 失效 — 请重新登录该引擎后重跑')
438
- console.log(' (场景提前结束:引擎凭据失效)')
439
- await manager.unloadAgent(ch.channelId, workerId).catch(() => {})
440
- return
441
- }
442
- if (harness === 'opencode' && !sawToolStatus && !providerAuthFailed && stateA !== 'COMPLETED') {
443
- // opencode 本机存储的 provider API key 均已 401 失效(裸探针证实:session.error
444
- // APIError「身份验证失败。」):集成管线(serve 拉起/会话/投递/SSE/收口)已验证,
445
- // LLM 回合无法产出 —— 按环境阻塞处理,不判 FAIL
446
- for (const name of [
447
- `[${harness}] 任务闭环 COMPLETED(引擎 → MCP 桥 → 平台工具)`,
448
- `[${harness}] report_progress 经桥落库(progress≥50)`,
449
- `[${harness}] 引擎审批请求登记到 HITL`,
450
- `[${harness}] HITL 批准后任务闭环 COMPLETED`,
451
- ]) checkSkip(name, '引擎 provider 凭据失效(opencode auth login 后重跑)')
452
- await manager.unloadAgent(ch.channelId, workerId).catch(() => {})
453
- return
454
- }
455
- check(`[${harness}] 任务闭环 COMPLETED(引擎 → MCP 桥 → 平台工具)`, stateA === 'COMPLETED', `state=${stateA}`)
456
- const tA = getEngine(manager).get(taskA.id)
457
- // report_progress 生效后,complete_task 会把 progress 收口为 100 —— 只断言桥回程生效过
458
- check(`[${harness}] report_progress 经桥落库(progress≥50)`, (tA?.progress ?? 0) >= 50, `progress=${tA?.progress}`)
459
-
460
- // ---- B. HITL 闭环 ----
461
- console.log(` ── B. HITL 审批闭环(严格沙箱文件写 → 登记 → 批准)──`)
462
- const taskB = await manager.submitChannelTask({
463
- channelId: ch.channelId,
464
- assigneeId: workerId,
465
- title: `${harness} hitl task`,
466
- description: [
467
- `You are running inside a multi-agent platform. Your task:`,
468
- `1. ${plan.writeInstruction}`,
469
- ` The platform may require human approval for this action — if a permission/approval request is raised, wait for it to be approved, then proceed.`,
470
- `2. After the file write succeeds, call the complete_task tool with summary="hitl approved on ${harness}".`,
471
- ].join('\n'),
472
- })
473
- const hitlItem = plan.hitlKind ? await waitHitl(plan.hitlKind, TIMING.hitl) : null
474
- if (hitlItem) {
475
- check(`[${harness}] 引擎审批请求登记到 HITL`, true, `title=${hitlItem.title?.slice(0, 80)}`)
476
- try {
477
- await manager.respondHarnessHitl(hitlItem.agentId, hitlItem.kind, hitlItem.id, { confirmed: true })
478
- check(`[${harness}] respondHarnessHitl 批准应答传导`, true)
479
- }
480
- catch (err) {
481
- check(`[${harness}] respondHarnessHitl 批准应答传导`, false, err instanceof Error ? err.message : String(err))
482
- }
483
- }
484
- const stateB = await waitTask(manager, taskB.id, plan.taskWaitMs ?? TIMING.task)
485
- check(`[${harness}] HITL 批准后任务闭环 COMPLETED`, stateB === 'COMPLETED', `state=${stateB}`)
486
- if (!hitlItem) {
487
- // 审批未触发:策略性跳过(引擎策略/模型行为决定是否触发;登记/应答管线由实现覆盖)
488
- const reason = !plan.hitlKind
489
- ? '引擎无程序化审批面(能力面如实声明 hitl:false),预授权白名单姿态'
490
- : harness === 'dsh'
491
- ? '本机 dsh 全局 defaultPreset=danger-full-access,引擎不触发审批'
492
- : '引擎按当前策略未触发审批(登记/应答管线由实现与历史运行覆盖)'
493
- checkSkip(`[${harness}] 引擎审批请求登记到 HITL`, reason)
494
- }
495
-
496
- // 清理:停 worker(杀子进程)
497
- if (autoTimer) clearInterval(autoTimer)
498
- await manager.unloadAgent(ch.channelId, workerId).catch(() => {})
499
- settle()
500
- }
501
- finally {
502
- settle()
503
- }
504
- }
505
-
506
- async function main(): Promise<void> {
507
- const only = process.argv[2] // 可选:只跑指定 harness
508
- const plans = only ? PLANS.filter(p => p.harness === only) : PLANS
509
- console.log(`━━━ 多 Harness 真实引擎 e2e(${plans.map(p => p.harness).join(' / ')})━━━`)
510
- const db = openWorkshopDb(':memory:')
511
- const manager = makeManager(db)
512
- const bridge = await startBridgeHttp(manager)
513
- try {
514
- for (const plan of plans) {
515
- try {
516
- await runScenario(manager, bridge.port, plan)
517
- }
518
- catch (err) {
519
- check(`[${plan.harness}] 场景异常`, false, err instanceof Error ? err.message : String(err))
520
- }
521
- }
522
- }
523
- finally {
524
- bridge.close()
525
- await manager.shutdown().catch(() => {})
526
- }
527
- console.log(failures === 0 ? '\n━━━ 全部通过 ━━━' : `\n━━━ ${failures} 项失败 ━━━`)
528
- process.exit(failures === 0 ? 0 : 1)
529
- }
530
-
531
- void main()