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,296 +0,0 @@
1
- /**
2
- * A2A 类型 + Agent 接口层测试(node + tsx 直跑,无浏览器)。
3
- *
4
- * 覆盖:
5
- * 1. Part 四变体(text/data/url/raw)构造与判别
6
- * 2. A2AMessage 往返 JSON 序列化(messageId/contextId/parts/metadata 保真)
7
- * 3. WorkspaceTask 默认值与 JSON 序列化
8
- * 4. AgentEvent 五变体(kind 判别 + 各字段类型收窄)
9
- * 5. SupervisionDecision 五变体判别
10
- * 6. AgentInterface 结构验证(mock 对象 run 返回 AsyncIterable 可迭代)
11
- */
12
- import type { Part, A2AMessage, A2AArtifact } from '../server/services/workshop/types/a2a'
13
- import type { TaskState, WorkspaceTask } from '../server/services/workshop/types/task'
14
- import type {
15
- AgentEvent,
16
- AgentInfo,
17
- AgentInterface,
18
- AgentRunContext,
19
- AgentRunRequest,
20
- AgentWorkspace,
21
- SupervisionDecision,
22
- SupervisionSnapshot,
23
- } from '../server/services/workshop/agents/agent-interface'
24
-
25
- let failures = 0
26
- function check(name: string, ok: boolean, detail = ''): void {
27
- console.log(`${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
28
- if (!ok) {
29
- failures += 1
30
- }
31
- }
32
-
33
- /** 判别 Part 变体,返回其判别键(用于类型收窄验证) */
34
- function partKind(part: Part): 'text' | 'data' | 'url' | 'raw' {
35
- if ('text' in part) return 'text'
36
- if ('data' in part) return 'data'
37
- if ('url' in part) return 'url'
38
- return 'raw'
39
- }
40
-
41
- function testPart(): void {
42
- console.log('\n--- 1. Part 四变体 ---')
43
-
44
- const text: Part = { text: 'hello', mediaType: 'text/plain', metadata: { k: 'v' } }
45
- const data: Part = { data: { n: 1 }, mediaType: 'application/json' }
46
- const url: Part = { url: 'https://example.com/a.png', mediaType: 'image/png', filename: 'a.png' }
47
- const raw: Part = { raw: 'base64==', mediaType: 'application/octet-stream', filename: 'b.bin' }
48
-
49
- check('text 变体判别', partKind(text) === 'text')
50
- check('text 变体字段收窄(string)', typeof text.text === 'string')
51
- check('text 变体 mediaType', text.mediaType === 'text/plain')
52
- check('text 变体 metadata', text.metadata?.k === 'v')
53
-
54
- check('data 变体判别', partKind(data) === 'data')
55
- check('data 变体字段收窄(unknown 承载任意值)', (data.data as { n: number }).n === 1)
56
- check('data 变体 mediaType', data.mediaType === 'application/json')
57
-
58
- check('url 变体判别', partKind(url) === 'url')
59
- check('url 变体字段收窄(string + filename)', typeof url.url === 'string' && url.filename === 'a.png')
60
-
61
- check('raw 变体判别', partKind(raw) === 'raw')
62
- check('raw 变体字段收窄(string + filename)', typeof raw.raw === 'string' && raw.filename === 'b.bin')
63
- }
64
-
65
- function testA2AMessage(): void {
66
- console.log('\n--- 2. A2AMessage 往返 JSON 序列化 ---')
67
-
68
- const msg: A2AMessage = {
69
- messageId: 'm-1',
70
- contextId: 'ch-1',
71
- taskId: 't-1',
72
- role: 'ROLE_AGENT',
73
- parts: [
74
- { text: 'hi' },
75
- { data: { x: 42 }, mediaType: 'application/json' },
76
- { url: 'https://x/y', filename: 'y' },
77
- { raw: 'AAAA', mediaType: 'application/octet-stream' },
78
- ],
79
- metadata: { 'x-aw-task-kind': 'assign', 'x-aw-task-id': 't-1' },
80
- extensions: ['ext-a'],
81
- referenceTaskIds: ['t-0'],
82
- }
83
-
84
- const roundtrip: A2AMessage = JSON.parse(JSON.stringify(msg))
85
- check('messageId 保真', roundtrip.messageId === 'm-1')
86
- check('contextId 保真', roundtrip.contextId === 'ch-1')
87
- check('taskId 保真', roundtrip.taskId === 't-1')
88
- check('role 保真', roundtrip.role === 'ROLE_AGENT')
89
- check('parts 长度保真', roundtrip.parts.length === 4)
90
- check('parts 内容保真(text)', (roundtrip.parts[0] as { text: string }).text === 'hi')
91
- check('parts 内容保真(data)', (roundtrip.parts[1] as { data: unknown }).data !== undefined)
92
- check('metadata 保真', roundtrip.metadata?.['x-aw-task-kind'] === 'assign')
93
- check('extensions 保真', roundtrip.extensions?.[0] === 'ext-a')
94
- check('referenceTaskIds 保真', roundtrip.referenceTaskIds?.[0] === 't-0')
95
- }
96
-
97
- function testWorkspaceTask(): void {
98
- console.log('\n--- 3. WorkspaceTask 默认值与 JSON 序列化 ---')
99
-
100
- const artifact: A2AArtifact = { artifactId: 'art-1', name: '报告', parts: [{ text: '成果' }] }
101
- const history: A2AMessage = { messageId: 'm-h', contextId: 'ch-1', role: 'ROLE_USER', parts: [{ text: '开始' }] }
102
-
103
- const task: WorkspaceTask = {
104
- id: 'task-1',
105
- channelId: 'ch-1',
106
- assigneeId: 'agent-a',
107
- creatorId: 'lead-1',
108
- title: '写周报',
109
- state: 'WORKING',
110
- progress: 0,
111
- retryCount: 0,
112
- artifacts: [artifact],
113
- history: [history],
114
- createdAt: '2026-08-13T00:00:00.000Z',
115
- updatedAt: '2026-08-13T00:00:00.000Z',
116
- }
117
-
118
- // 可选字段(parentId/description)缺省为 undefined
119
- check('parentId 缺省为 undefined', task.parentId === undefined)
120
- check('description 缺省为 undefined', task.description === undefined)
121
-
122
- const roundtrip: WorkspaceTask = JSON.parse(JSON.stringify(task))
123
- check('id 保真', roundtrip.id === 'task-1')
124
- check('channelId 保真', roundtrip.channelId === 'ch-1')
125
- check('state 保真', roundtrip.state === 'WORKING')
126
- check('progress 保真', roundtrip.progress === 0)
127
- check('retryCount 保真', roundtrip.retryCount === 0)
128
- check('artifacts 保真', roundtrip.artifacts.length === 1 && roundtrip.artifacts[0].artifactId === 'art-1')
129
- check('history 保真', roundtrip.history.length === 1 && roundtrip.history[0].messageId === 'm-h')
130
- check('createdAt 保真', roundtrip.createdAt === '2026-08-13T00:00:00.000Z')
131
-
132
- // 终态枚举:TaskState 各取值均可赋值
133
- const states: TaskState[] = ['SUBMITTED', 'ASSIGNED', 'WORKING', 'WAITING', 'COMPLETED', 'FAILED', 'CANCELED']
134
- check('TaskState 七个枚举值', states.length === 7 && states.includes('COMPLETED') && states.includes('CANCELED'))
135
- }
136
-
137
- function testAgentEvent(): void {
138
- console.log('\n--- 4. AgentEvent 五变体 ---')
139
-
140
- const statusEvt: AgentEvent = { kind: 'status', status: { state: 'working', timestamp: '2026-08-13T00:00:00.000Z' } }
141
- const msgEvt: AgentEvent = { kind: 'message', message: { messageId: 'm-1', contextId: 'ch-1', role: 'ROLE_AGENT', parts: [{ text: 'hi' }] } }
142
- const artEvt: AgentEvent = { kind: 'artifact', artifact: { artifactId: 'art-1', parts: [{ text: 'x' }] }, append: true, lastChunk: false, totalChunks: 3 }
143
- const errEvt: AgentEvent = { kind: 'error', error: { code: 'X', message: 'boom' } }
144
- const doneEvt: AgentEvent = { kind: 'done', final: { taskId: 't-1' } }
145
-
146
- check('status 变体判别', statusEvt.kind === 'status')
147
- check('status 变体字段收窄(state/timestamp)', typeof statusEvt.status.state === 'string' && typeof statusEvt.status.timestamp === 'string')
148
-
149
- check('message 变体判别', msgEvt.kind === 'message')
150
- check('message 变体字段收窄(A2AMessage)', msgEvt.message.messageId === 'm-1')
151
-
152
- check('artifact 变体判别', artEvt.kind === 'artifact')
153
- check('artifact 变体字段收窄(artifact + 分块)', artEvt.artifact.artifactId === 'art-1' && artEvt.append === true && artEvt.lastChunk === false && artEvt.totalChunks === 3)
154
-
155
- check('error 变体判别', errEvt.kind === 'error')
156
- check('error 变体字段收窄(A2AError)', errEvt.error.code === 'X' && errEvt.error.message === 'boom')
157
-
158
- check('done 变体判别', doneEvt.kind === 'done')
159
- check('done 变体字段收窄(final.taskId)', doneEvt.final?.taskId === 't-1')
160
-
161
- // 泛化类型收窄:switch 后可安全访问各字段
162
- const events: AgentEvent[] = [statusEvt, msgEvt, artEvt, errEvt, doneEvt]
163
- let narrowed = true
164
- for (const ev of events) {
165
- switch (ev.kind) {
166
- case 'status':
167
- narrowed = narrowed && ev.status.state !== undefined
168
- break
169
- case 'message':
170
- narrowed = narrowed && ev.message.messageId !== undefined
171
- break
172
- case 'artifact':
173
- narrowed = narrowed && ev.artifact.artifactId !== undefined
174
- break
175
- case 'error':
176
- narrowed = narrowed && ev.error.code !== undefined
177
- break
178
- case 'done':
179
- narrowed = narrowed && ev.final !== undefined
180
- break
181
- default:
182
- narrowed = false
183
- }
184
- }
185
- check('五变体 switch 全收窄无遗漏', narrowed)
186
- }
187
-
188
- function testSupervisionDecision(): void {
189
- console.log('\n--- 5. SupervisionDecision 五变体判别 ---')
190
-
191
- const decisions: SupervisionDecision[] = [
192
- { kind: 'dispatch', parentTaskId: 'p-1', assigneeId: 'w-1', title: '子任务', description: 'd', parts: [{ text: 'x' }] },
193
- { kind: 'reassign', taskId: 't-1', toAgentId: 'w-2' },
194
- { kind: 'cancel', taskId: 't-2' },
195
- { kind: 'complete', taskId: 't-3', artifacts: [{ artifactId: 'a-1', parts: [{ text: 'r' }] }] },
196
- { kind: 'notify', toAgentId: 'w-3', parts: [{ text: '通知' }] },
197
- ]
198
-
199
- check('dispatch 判别', decisions[0].kind === 'dispatch')
200
- check('dispatch 字段(assigneeId/title/parts)', decisions[0].kind === 'dispatch' && decisions[0].assigneeId === 'w-1' && decisions[0].title === '子任务' && decisions[0].parts?.length === 1)
201
-
202
- check('reassign 判别', decisions[1].kind === 'reassign')
203
- check('reassign 字段(taskId/toAgentId)', decisions[1].kind === 'reassign' && decisions[1].taskId === 't-1' && decisions[1].toAgentId === 'w-2')
204
-
205
- check('cancel 判别', decisions[2].kind === 'cancel')
206
- check('cancel 字段(taskId)', decisions[2].kind === 'cancel' && decisions[2].taskId === 't-2')
207
-
208
- check('complete 判别', decisions[3].kind === 'complete')
209
- check('complete 字段(taskId/artifacts)', decisions[3].kind === 'complete' && decisions[3].taskId === 't-3' && decisions[3].artifacts?.length === 1)
210
-
211
- check('notify 判别', decisions[4].kind === 'notify')
212
- check('notify 字段(toAgentId/parts)', decisions[4].kind === 'notify' && decisions[4].toAgentId === 'w-3' && decisions[4].parts.length === 1)
213
- }
214
-
215
- async function testAgentInterface(): Promise<void> {
216
- console.log('\n--- 6. AgentInterface 结构验证 ---')
217
-
218
- const mockImpl: AgentInterface = {
219
- async* run(request: AgentRunRequest, _ctx: AgentRunContext): AsyncIterable<AgentEvent> {
220
- yield { kind: 'status', status: { state: 'running', timestamp: new Date().toISOString() } }
221
- yield { kind: 'message', message: request.message }
222
- yield { kind: 'done', final: { taskId: request.taskId } }
223
- },
224
- async supervise(snapshot: SupervisionSnapshot, _ctx: AgentRunContext): Promise<SupervisionDecision[]> {
225
- return snapshot.tasks.length === 0 ? [] : [{ kind: 'cancel', taskId: snapshot.tasks[0].id }]
226
- },
227
- }
228
-
229
- const agent: AgentInfo = { id: 'agent-a', channelId: 'ch-1', name: 'A', harness: 'mock', role: 'worker', config: {} }
230
- const workspace: AgentWorkspace = {
231
- listAgents: async () => [agent],
232
- dispatchTask: async () => { throw new Error('not implemented') },
233
- listTasks: async () => [],
234
- getTask: async () => { throw new Error('not implemented') },
235
- reportTask: async () => { throw new Error('not implemented') },
236
- completeTask: async () => { throw new Error('not implemented') },
237
- cancelTask: async () => { throw new Error('not implemented') },
238
- myQueue: async () => ({ agentId: 'agent-a', channelId: 'ch-1', queued: [], completed: [] }),
239
- queueOverview: async () => [],
240
- updateTask: async () => { throw new Error('not implemented') },
241
- reassignTask: async () => { throw new Error('not implemented') },
242
- sendMessage: async () => { throw new Error('not implemented') },
243
- pollMailbox: async () => [],
244
- listMail: async () => [],
245
- subscribe: async () => {},
246
- recallMemory: async () => [],
247
- saveMemory: async () => { throw new Error('not implemented') },
248
- }
249
- const ctx: AgentRunContext = { agentId: 'agent-a', channelId: 'ch-1', role: 'worker', workspace, signal: new AbortController().signal }
250
-
251
- const req: AgentRunRequest = {
252
- message: { messageId: 'm-1', contextId: 'ch-1', role: 'ROLE_USER', parts: [{ text: 'hi' }] },
253
- contextId: 'ch-1',
254
- fromAgentId: null,
255
- toAgentId: 'agent-a',
256
- }
257
-
258
- check('run 返回 AsyncIterable 且可迭代', typeof mockImpl.run(req, ctx)[Symbol.asyncIterator] === 'function')
259
-
260
- // 实际迭代收集事件
261
- const collected: AgentEvent[] = []
262
- for await (const ev of mockImpl.run(req, ctx)) {
263
- collected.push(ev)
264
- }
265
- check('迭代产出 3 个事件', collected.length === 3)
266
- check('事件顺序(status→message→done)', collected[0].kind === 'status' && collected[1].kind === 'message' && collected[2].kind === 'done')
267
-
268
- // supervise 可选实现
269
- check('supervise 可调用返回决策', mockImpl.supervise !== undefined)
270
- const decisions = await mockImpl.supervise!(
271
- { tick: 1, now: Date.now(), tasks: [], members: [], pendingChildren: {} },
272
- ctx,
273
- )
274
- check('supervise 空快照返回空数组', Array.isArray(decisions) && decisions.length === 0)
275
-
276
- // init/dispose 为可选方法
277
- check('init 可选(未实现为 undefined)', mockImpl.init === undefined)
278
- check('dispose 可选(未实现为 undefined)', mockImpl.dispose === undefined)
279
- }
280
-
281
- async function main(): Promise<void> {
282
- testPart()
283
- testA2AMessage()
284
- testWorkspaceTask()
285
- testAgentEvent()
286
- testSupervisionDecision()
287
- await testAgentInterface()
288
-
289
- console.log(`\n${failures === 0 ? 'ALL PASS' : `${failures} FAILED`}`)
290
- process.exit(failures === 0 ? 0 : 1)
291
- }
292
-
293
- main().catch((e) => {
294
- console.error(e)
295
- process.exit(1)
296
- })
@@ -1,285 +0,0 @@
1
- /**
2
- * MCP 工具层测试(node + tsx 直跑,无浏览器)。
3
- *
4
- * 覆盖:
5
- * 1. tools/list 返回 §6.1 的 16 个工具(名逐字一致)
6
- * 2. tools/call 参数校验(zod 错误返回)
7
- * 3. 无 token → UNAUTHORIZED
8
- * 4. 无效 token → UNAUTHORIZED
9
- * 5. a2a.send 的 fromAgentId 由 token 决定(manager 收到 callerAgentId,而非请求体自报)
10
- *
11
- * 通过 SDK 的 Client + InMemoryTransport 协议层测试;token 经自定义 transport
12
- * 注入(Authorization 头 / auth 中间件两种路径)。
13
- */
14
- import { Client } from '@modelcontextprotocol/sdk/client/index.js'
15
- import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'
16
- import { createWorkshopMcpServer } from '../server/mcp/workshop-server'
17
- import type { AgentChannelManager } from '../server/services/workshop/runtime/manager'
18
- import type { AgentInfo } from '../server/services/workshop/agents/agent-interface'
19
-
20
- let failures = 0
21
- function check(name: string, ok: boolean, detail = ''): void {
22
- console.log(`${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
23
- if (!ok) {
24
- failures += 1
25
- }
26
- }
27
-
28
- /** 提取工具错误文案(isError 结果的第一个文本块) */
29
- function toolErrorText(result: unknown): string {
30
- const block = (result as { content?: Array<{ text?: string }> })?.content?.[0]
31
- return typeof block?.text === 'string' ? block.text : ''
32
- }
33
-
34
- /** 可注入 caller token 的客户端 transport(InMemoryTransport 只原生转发 authInfo) */
35
- class TokenClientTransport extends InMemoryTransport {
36
- token: string | undefined
37
- /** 'auth' = 经 authInfo.token 注入;'header' = 经 Authorization: Bearer 头(requestInfo)注入 */
38
- mode: 'auth' | 'header' = 'auth'
39
-
40
- override async send(message: unknown, options?: { authInfo?: unknown }): Promise<void> {
41
- if (this.token === undefined) {
42
- return super.send(message as never, options as never)
43
- }
44
- if (this.mode === 'auth') {
45
- return super.send(message as never, {
46
- ...options,
47
- authInfo: { token: this.token, clientId: 'test-client', scopes: [] },
48
- } as never)
49
- }
50
- // header 模式:复刻 InMemoryTransport.send 但注入 requestInfo(Authorization 头)
51
- const self = this as unknown as { _otherTransport?: { onmessage?: (m: unknown, e: unknown) => void, _messageQueue: Array<{ message: unknown, extra: unknown }> } }
52
- const other = self._otherTransport
53
- if (!other) throw new Error('Not connected')
54
- const extra = { requestInfo: { headers: { authorization: `Bearer ${this.token}` } } }
55
- if (other.onmessage) other.onmessage(message, extra)
56
- else other._messageQueue.push({ message, extra })
57
- }
58
- }
59
-
60
- /** 手动链接一对 transport(client 侧为可注入 token 的 TokenClientTransport) */
61
- function createLinkedPair(): [TokenClientTransport, InMemoryTransport] {
62
- const clientTransport = new TokenClientTransport()
63
- const serverTransport = new InMemoryTransport()
64
- const c = clientTransport as unknown as { _otherTransport?: InMemoryTransport }
65
- const s = serverTransport as unknown as { _otherTransport?: InMemoryTransport }
66
- c._otherTransport = serverTransport
67
- s._otherTransport = clientTransport
68
- return [clientTransport, serverTransport]
69
- }
70
-
71
- /** MCP 工具目录(与 server/mcp/workshop-server.ts 逐字一致):16 基础 + 4 扩展 + 5 设备孪生 */
72
- const EXPECTED_TOOLS = [
73
- 'workshop.channel.create',
74
- 'workshop.channel.list',
75
- 'workshop.channel.remove',
76
- 'workshop.agent.create',
77
- 'workshop.agent.add',
78
- 'workshop.agent.definitions',
79
- 'workshop.agent.list',
80
- 'workshop.agent.remove',
81
- 'workshop.task.submit',
82
- 'workshop.task.dispatch',
83
- 'workshop.task.list',
84
- 'workshop.task.get',
85
- 'workshop.task.report',
86
- 'workshop.task.complete',
87
- 'workshop.task.cancel',
88
- 'workshop.a2a.send',
89
- 'workshop.a2a.poll',
90
- 'workshop.a2a.subscribe',
91
- 'workshop.mail.list',
92
- 'workshop.queue.overview',
93
- 'device.list',
94
- 'device.read',
95
- 'device.control',
96
- 'device.push_telemetry',
97
- 'device.bind_agent',
98
- ]
99
-
100
- /** fake manager stub:记录调用 + 返回预设值(与 AgentChannelManager 相同方法签名) */
101
- function makeFakeManager() {
102
- const calls: Array<{ method: string, args: unknown[] }> = []
103
-
104
- const agentsByToken = new Map<string, AgentInfo>()
105
- agentsByToken.set('token-lead-1', {
106
- id: 'agent-lead-1',
107
- channelId: 'ch-1',
108
- name: 'Lead',
109
- harness: 'mock',
110
- role: 'lead',
111
- config: {},
112
- })
113
- agentsByToken.set('token-worker-2', {
114
- id: 'agent-worker-2',
115
- channelId: 'ch-1',
116
- name: 'Worker2',
117
- harness: 'mock',
118
- role: 'worker',
119
- config: {},
120
- })
121
-
122
- const record
123
- = (method: string, result: unknown) =>
124
- (...args: unknown[]) => {
125
- calls.push({ method, args })
126
- return Promise.resolve(result)
127
- }
128
-
129
- const manager = {
130
- createChannel: record('createChannel', { channelId: 'ch-1' }),
131
- listChannels: record('listChannels', []),
132
- removeChannel: record('removeChannel', undefined),
133
- createAgent: record('createAgent', {
134
- id: 'agent-tpl',
135
- name: 'New',
136
- harness: 'mock',
137
- config: {},
138
- enabled: 1,
139
- instances: [],
140
- }),
141
- addAgentToChannel: record('addAgentToChannel', {
142
- id: 'agent-inst',
143
- channelId: 'ch-1',
144
- name: 'New',
145
- harness: 'mock',
146
- role: 'worker',
147
- config: {},
148
- }),
149
- listAgents: record('listAgents', []),
150
- listChannelAgents: record('listChannelAgents', []),
151
- submitChannelTask: record('submitChannelTask', { id: 'task-1' }),
152
- dispatchTask: record('dispatchTask', { id: 'task-2' }),
153
- reportTask: record('reportTask', { id: 'task-1' }),
154
- completeTask: record('completeTask', { id: 'task-1' }),
155
- cancelTask: record('cancelTask', { id: 'task-1' }),
156
- listTasks: record('listTasks', []),
157
- getTask: record('getTask', { id: 'task-1' }),
158
- sendA2A: record('sendA2A', {
159
- messageId: 'm-1',
160
- contextId: 'ch-1',
161
- role: 'ROLE_AGENT',
162
- parts: [{ text: 'hi' }],
163
- }),
164
- pollMailbox: record('pollMailbox', []),
165
- listChannelMail: record('listChannelMail', []),
166
- queueOverview: record('queueOverview', []),
167
- subscribe: record('subscribe', undefined),
168
- findByToken: (token: string) => agentsByToken.get(token),
169
- restore: record('restore', undefined),
170
- }
171
-
172
- return {
173
- manager: manager as unknown as AgentChannelManager,
174
- calls,
175
- agentsByToken,
176
- }
177
- }
178
-
179
- async function main(): Promise<void> {
180
- const [clientTransport, serverTransport] = createLinkedPair()
181
- const fake = makeFakeManager()
182
- const server = createWorkshopMcpServer(fake.manager)
183
-
184
- const client = new Client({ name: 'test-client', version: '1.0.0' })
185
- await server.connect(serverTransport)
186
- await client.connect(clientTransport)
187
-
188
- // ===== 1. tools/list:20 个工具,名逐字一致 =====
189
- const { tools } = await client.listTools()
190
- const actualNames = tools.map(t => t.name).sort()
191
- const expectedNames = [...EXPECTED_TOOLS].sort()
192
- check('tools/list 返回 25 个工具', tools.length === 25, `got ${tools.length}`)
193
- check(
194
- '工具名与 §6.1 逐字一致',
195
- JSON.stringify(actualNames) === JSON.stringify(expectedNames),
196
- JSON.stringify(actualNames),
197
- )
198
-
199
- // ===== 2. 参数校验:zod 错误返回 =====
200
- const missingName = await client.callTool({ name: 'workshop.channel.create', arguments: {} })
201
- check(
202
- '参数校验:channel.create 缺 name → 工具错误',
203
- (missingName as { isError?: boolean }).isError === true,
204
- toolErrorText(missingName),
205
- )
206
- check(
207
- '参数校验:错误文案含 Input validation error',
208
- toolErrorText(missingName).includes('Input validation error'),
209
- toolErrorText(missingName),
210
- )
211
-
212
- const badRole = await client.callTool({
213
- name: 'workshop.agent.add',
214
- arguments: { channelId: 'ch-1', agentId: 'agent-tpl', role: 'admin' },
215
- })
216
- check(
217
- '参数校验:agent.add role 非法枚举 → 工具错误',
218
- (badRole as { isError?: boolean }).isError === true,
219
- toolErrorText(badRole),
220
- )
221
-
222
- // ===== 3. 无 token → UNAUTHORIZED =====
223
- clientTransport.token = undefined
224
- const noToken = await client.callTool({ name: 'workshop.agent.list', arguments: {} })
225
- check(
226
- '无 token → UNAUTHORIZED',
227
- (noToken as { isError?: boolean }).isError === true && toolErrorText(noToken) === 'UNAUTHORIZED',
228
- toolErrorText(noToken),
229
- )
230
-
231
- // ===== 4. 无效 token → UNAUTHORIZED =====
232
- clientTransport.token = 'bad-token'
233
- const badToken = await client.callTool({ name: 'workshop.agent.list', arguments: {} })
234
- check(
235
- '无效 token → UNAUTHORIZED',
236
- (badToken as { isError?: boolean }).isError === true && toolErrorText(badToken) === 'UNAUTHORIZED',
237
- toolErrorText(badToken),
238
- )
239
-
240
- // ===== 5. a2a.send 的 fromAgentId 由 token 决定 =====
241
- clientTransport.token = 'token-lead-1'
242
- // 请求体故意自报 fromAgentId,应被忽略;caller 由 token 解析为 agent-lead-1
243
- const sendResult = await client.callTool({
244
- name: 'workshop.a2a.send',
245
- arguments: { toAgentId: 'agent-worker-2', parts: [{ text: 'hello' }], fromAgentId: 'evil-agent' },
246
- })
247
- check('a2a.send(有效 token)→ 成功', (sendResult as { isError?: boolean }).isError !== true, toolErrorText(sendResult))
248
-
249
- const sendCall = fake.calls.find(c => c.method === 'sendA2A')
250
- const callerAgentId = sendCall?.args[1]
251
- const sendInput = sendCall?.args[2] as { toAgentId?: string, fromAgentId?: string } | undefined
252
- check(
253
- 'a2a.send callerAgentId 由 token 决定(agent-lead-1)',
254
- callerAgentId === 'agent-lead-1',
255
- `got ${String(callerAgentId)}`,
256
- )
257
- check(
258
- 'a2a.send 忽略请求体自报的 fromAgentId',
259
- sendInput?.fromAgentId === undefined && sendInput?.toAgentId === 'agent-worker-2',
260
- JSON.stringify(sendInput),
261
- )
262
-
263
- // ===== 6. Authorization 头路径同样解析 token =====
264
- clientTransport.mode = 'header'
265
- clientTransport.token = 'token-worker-2'
266
- const headerResult = await client.callTool({ name: 'workshop.a2a.send', arguments: { toAgentId: 'agent-lead-1', parts: [{ text: 'hi' }] } })
267
- check('Authorization 头解析 token → 成功', (headerResult as { isError?: boolean }).isError !== true, toolErrorText(headerResult))
268
- const headerCall = fake.calls.filter(c => c.method === 'sendA2A').at(-1)
269
- check(
270
- 'Authorization 头路径 callerAgentId = agent-worker-2',
271
- headerCall?.args[1] === 'agent-worker-2',
272
- `got ${String(headerCall?.args[1])}`,
273
- )
274
-
275
- await client.close()
276
- await server.close()
277
-
278
- console.log(`\n${failures === 0 ? 'ALL PASS' : `${failures} FAILED`}`)
279
- process.exit(failures === 0 ? 0 : 1)
280
- }
281
-
282
- main().catch((e) => {
283
- console.error(e)
284
- process.exit(1)
285
- })