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,135 +0,0 @@
1
- /**
2
- * ScriptBrain 模拟 Agent — 纯逻辑单测(node + tsx 直跑,无浏览器依赖)
3
- *
4
- * 验证状态机迁移与动作输出:
5
- * 1. 初始 tick → 进入 wander + move 动作
6
- * 2. 玩家进入 6 tiles → approach + 朝玩家方向移动
7
- * 3. 玩家贴脸(≤3 tiles)→ talk + dialog 发起 + face
8
- * 4. dialog.closed 事件 → wait,冷却后恢复 wander
9
- * 5. 地图边缘 → 不朝边界外走
10
- * 6. 对话中 → 不产出 move
11
- */
12
- import { ScriptBrain } from '../server/services/game/agent'
13
- import type { AgentContext, Dir } from '../server/types/game'
14
-
15
- let failures = 0
16
- function check(name: string, ok: boolean, detail = '') {
17
- console.log(`${ok ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}`)
18
- if (!ok)
19
- failures += 1
20
- }
21
-
22
- const AGENT_START = { x: 720, y: 656 }
23
- const rngSeq = (() => {
24
- let i = 0
25
- const seq = [0.9, 0.1, 0.5, 0.7, 0.3, 0.6, 0.2, 0.8, 0.4, 0.95]
26
- return () => seq[i++ % seq.length]
27
- })()
28
-
29
- function mkCtx(over: Partial<AgentContext> = {}): AgentContext {
30
- return {
31
- tick: 1,
32
- now: 1000,
33
- agent: { ...AGENT_START, dir: 'down', mode: 'idle' },
34
- player: { x: 0, y: 0, lastSeenAt: null, distance: Infinity },
35
- rng: rngSeq,
36
- ...over,
37
- }
38
- }
39
-
40
- // 1. 初始:进入 wander 并产出 move
41
- {
42
- const brain = new ScriptBrain()
43
- const acts = brain.think(mkCtx())
44
- const state = acts.find(a => a.kind === 'state')
45
- const move = acts.find(a => a.kind === 'move')
46
- check('初始 tick 进入 wander', state?.kind === 'state' && state.mode === 'wander')
47
- check('初始 tick 产出移动动作', move?.kind === 'move' && (move as { durationMs: number }).durationMs > 0,
48
- `dir=${(move as { dir: Dir }).dir} dur=${(move as { durationMs: number }).durationMs}ms`)
49
- }
50
-
51
- // 2. 玩家 5 tiles:approach + 朝玩家方向
52
- {
53
- const brain = new ScriptBrain()
54
- brain.think(mkCtx()) // 进入 wander
55
- const ctx = mkCtx({
56
- now: 2000,
57
- player: { x: AGENT_START.x + 160, y: AGENT_START.y, lastSeenAt: 1999, distance: 160 },
58
- })
59
- const acts = brain.think(ctx)
60
- const state = acts.find(a => a.kind === 'state')
61
- const move = acts.find(a => a.kind === 'move')
62
- check('玩家 5 tiles → approach', state?.kind === 'state' && state.mode === 'approach')
63
- check('approach 朝玩家方向(right)', move?.kind === 'move' && (move as { dir: Dir }).dir === 'right')
64
- }
65
-
66
- // 3. 玩家贴脸:talk + dialog
67
- {
68
- const brain = new ScriptBrain()
69
- brain.think(mkCtx())
70
- const ctx = mkCtx({
71
- now: 3000,
72
- player: { x: AGENT_START.x + 64, y: AGENT_START.y, lastSeenAt: 2999, distance: 64 },
73
- })
74
- const acts = brain.think(ctx)
75
- const dialog = acts.find(a => a.kind === 'dialog')
76
- const move = acts.find(a => a.kind === 'move')
77
- check('贴脸发起对话', dialog?.kind === 'dialog' && (dialog as { lines: string[] }).lines.length >= 1)
78
- check('对话中不产出移动', move === undefined)
79
- // 继续 tick:仍 talk,无新 dialog
80
- const acts2 = brain.think(mkCtx({ now: 3100, player: { x: AGENT_START.x + 64, y: AGENT_START.y, lastSeenAt: 3099, distance: 64 } }))
81
- check('对话期间不重复发起', !acts2.some(a => a.kind === 'dialog'))
82
- }
83
-
84
- // 4. 对话关闭 → wait → 冷却后 wander
85
- {
86
- const brain = new ScriptBrain()
87
- brain.think(mkCtx())
88
- brain.think(mkCtx({ now: 3000, player: { x: AGENT_START.x + 64, y: AGENT_START.y, lastSeenAt: 2999, distance: 64 } }))
89
- brain.onEvent?.({ kind: 'dialog.closed' })
90
- const during = brain.think(mkCtx({ now: 3500, player: { x: AGENT_START.x + 64, y: AGENT_START.y, lastSeenAt: 3499, distance: 64 } }))
91
- check('dialog.closed → 无动作(wait 冷却)', during.length === 0 || !during.some(a => a.kind === 'move'))
92
- const after = brain.think(mkCtx({ now: 9000, player: { x: AGENT_START.x + 64, y: AGENT_START.y, lastSeenAt: 8999, distance: 64 } }))
93
- const state = after.find(a => a.kind === 'state')
94
- check('冷却后恢复 wander', state?.kind === 'state' && state.mode === 'wander')
95
- }
96
-
97
- // 5. 地图边缘:不向界外走
98
- {
99
- const brain = new ScriptBrain()
100
- const ctx = mkCtx({
101
- now: 5000,
102
- agent: { x: 40, y: 656, dir: 'down', mode: 'wander' }, // 左边缘 40px(<2 tiles=64)
103
- })
104
- // 固定 rng 序列首个 0.9 → 可能选 left;边缘保护应避免向界外
105
- for (let i = 0; i < 20; i++) {
106
- const acts = brain.think(ctx)
107
- const move = acts.find(a => a.kind === 'move')
108
- if (move?.kind === 'move' && move.dir === 'left') {
109
- check('地图边缘不向左走', false, `tick ${i} 仍向左`)
110
- break
111
- }
112
- if (i === 19)
113
- check('地图边缘不向左走', true)
114
- }
115
- }
116
-
117
- // 6. 玩家远离(>11 tiles) → 放弃追逐回 wander
118
- {
119
- const brain = new ScriptBrain()
120
- brain.think(mkCtx()) // wander
121
- brain.think(mkCtx({
122
- now: 2000,
123
- player: { x: AGENT_START.x + 160, y: AGENT_START.y, lastSeenAt: 1999, distance: 160 },
124
- })) // approach
125
- const far = mkCtx({
126
- now: 3000,
127
- player: { x: AGENT_START.x + 400, y: AGENT_START.y + 400, lastSeenAt: 2999, distance: 566 },
128
- })
129
- const acts = brain.think(far)
130
- const state = acts.find(a => a.kind === 'state')
131
- check('玩家远离 → 回 wander', state?.kind === 'state' && state.mode === 'wander')
132
- }
133
-
134
- console.log(`\n===== ${6 - failures}/6 passed =====`)
135
- process.exit(failures ? 1 : 0)
@@ -1,156 +0,0 @@
1
- /**
2
- * CMDParser 协议解析测试 + MCP 接缝验证(node + tsx 直跑,无浏览器)
3
- *
4
- * 覆盖:
5
- * 1. 协议同步(assertProtocolSync):JSON 注册表 ↔ wire 类型键集合一致,example 自洽
6
- * 2. CMDParser.parseUplink:合法/空/坏JSON/缺字段/未知指令/无效枚举/越界值
7
- * 3. CMDParser.parseDownlink:合法 + 闭合结构(拒绝额外字段)
8
- * 4. toMcpTools:agentCallable=true 的 downlink 即工具集,description 非空
9
- * 5. GameSession.execDownlink:Agent 可调用指令注入成功,会话生命周期指令被 FORBIDDEN 拦截
10
- */
11
- import {
12
- assertProtocolSync,
13
- CMDParser,
14
- PROTOCOL,
15
- toMcpTools,
16
- } from '../shared/game-protocol'
17
- import { gameSession } from '../server/services/game/session'
18
- import type { ServerToClient } from '../server/types/game'
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
- /** 假 WS peer:捕获下行指令(结构兼容 h3 peer) */
29
- class FakePeer {
30
- sent: ServerToClient[] = []
31
-
32
- send(data: string | Uint8Array): void {
33
- this.sent.push(JSON.parse(typeof data === 'string' ? data : new TextDecoder().decode(data)))
34
- }
35
-
36
- close(): void {}
37
- }
38
-
39
- function testProtocolSync(): void {
40
- console.log('\n--- 1. 协议同步 ---')
41
- const report = assertProtocolSync()
42
- check('downlink 键集合无漂移', report.unsyncedDownlink.length === 0, JSON.stringify(report.downlink))
43
- check('uplink 键集合无漂移', report.unsyncedUplink.length === 0, JSON.stringify(report.uplink))
44
- check('所有 example 自洽', report.badExamples.length === 0)
45
- check('agentCallable 指令存在', report.downlink.some(k => PROTOCOL.downlink[k]?.agentCallable))
46
- }
47
-
48
- function testParseUplink(): void {
49
- console.log('\n--- 2. CMDParser.parseUplink ---')
50
-
51
- // 合法
52
- const ok = CMDParser.parseUplink('{"type":"input.move","payload":{"dx":1,"dy":0}}')
53
- check('合法 input.move 解析成功', ok.ok && ok.value.type === 'input.move')
54
-
55
- // 空字符串
56
- const empty = CMDParser.parseUplink('')
57
- check('空字符串 → BAD_MESSAGE', !empty.ok && empty.error.code === 'BAD_MESSAGE')
58
-
59
- // 坏 JSON
60
- const bad = CMDParser.parseUplink('{not json')
61
- check('坏 JSON → BAD_MESSAGE', !bad.ok && bad.error.code === 'BAD_MESSAGE')
62
-
63
- // 缺 payload
64
- const noPayload = CMDParser.parseUplink('{"type":"input.move","payload_dx":1}')
65
- check('缺 payload → BAD_MESSAGE', !noPayload.ok && noPayload.error.code === 'BAD_MESSAGE')
66
-
67
- // 未知指令
68
- const unknown = CMDParser.parseUplink('{"type":"foo.bar","payload":{}}')
69
- check('未知指令 → UNKNOWN_COMMAND', !unknown.ok && unknown.error.code === 'UNKNOWN_COMMAND')
70
-
71
- // 无效枚举
72
- const badEnum = CMDParser.parseUplink('{"type":"input.move","payload":{"dx":2,"dy":0}}')
73
- check('dx=2 越界枚举 → INVALID_PAYLOAD', !badEnum.ok && badEnum.error.code === 'INVALID_PAYLOAD',
74
- badEnum.ok ? '' : badEnum.error.path)
75
-
76
- // 缺必填
77
- const missing = CMDParser.parseUplink('{"type":"player.pos","payload":{"x":1,"y":2}}')
78
- check('缺 tileX/tileY → INVALID_PAYLOAD', !missing.ok && missing.error.code === 'INVALID_PAYLOAD')
79
- }
80
-
81
- function testParseDownlink(): void {
82
- console.log('\n--- 3. CMDParser.parseDownlink ---')
83
-
84
- const ok = CMDParser.parseDownlink('{"type":"agent.say","payload":{"text":"hi","ttlMs":1000}}')
85
- check('合法 agent.say 解析成功', ok.ok && ok.value.type === 'agent.say')
86
-
87
- // 闭合结构:拒绝额外字段
88
- const extra = CMDParser.parseDownlink('{"type":"agent.face","payload":{"dir":"down","extra":1}}')
89
- check('额外字段被拒绝(闭合 schema)', !extra.ok && extra.error.code === 'INVALID_PAYLOAD')
90
-
91
- // 对象类型指令:缺必填
92
- const missing = CMDParser.parseDownlink('{"type":"session.ready","payload":{"agentName":"x"}}')
93
- check('session.ready 缺 spawn → INVALID_PAYLOAD', !missing.ok && missing.error.code === 'INVALID_PAYLOAD')
94
- }
95
-
96
- function testMcpTools(): void {
97
- console.log('\n--- 4. MCP 工具词表 ---')
98
- const tools = toMcpTools()
99
- const names = tools.map(t => t.name)
100
- check('工具数 > 0', tools.length > 0, names.join(','))
101
-
102
- const allCallable = names.every(n => PROTOCOL.downlink[n]?.agentCallable === true)
103
- check('全部工具对应 agentCallable=true', allCallable)
104
-
105
- const allDescribed = tools.every(t => t.description.length > 0 && t.inputSchema.type === 'object')
106
- check('每个工具有 description + object inputSchema', allDescribed)
107
-
108
- // 关键 Agent 工具应在册
109
- check('agent.move 在工具集', names.includes('agent.move'))
110
- check('agent.say 在工具集', names.includes('agent.say'))
111
- check('dialog.open 在工具集', names.includes('dialog.open'))
112
-
113
- // 非工具:会话生命周期 + 协议内部指令不应可调用
114
- check('session.ready 不在工具集', !names.includes('session.ready'))
115
- check('dialog.advance 不在工具集', !names.includes('dialog.advance'))
116
- check('error 不在工具集', !names.includes('error'))
117
- }
118
-
119
- async function testExecDownlink(): Promise<void> {
120
- console.log('\n--- 5. GameSession.execDownlink(MCP 接缝) ---')
121
- const peer = new FakePeer()
122
- gameSession.connect(peer)
123
- // connect 后首两条为 session.ready / agent.state,execDownlink 的新指令在其后追加
124
- const baseline = peer.sent.length
125
-
126
- // Agent 可调用指令:注入成功 + 下行广播
127
- const res = gameSession.execDownlink('agent.say', { text: '来自 Agent', ttlMs: 1500 })
128
- check('execDownlink agent.say 成功', res.ok)
129
- check('agent.say 下发到 peer', peer.sent.length === baseline + 1
130
- && peer.sent[peer.sent.length - 1]!.type === 'agent.say', `sent=${peer.sent.length}`)
131
-
132
- // 非 agentCallable 指令:FORBIDDEN
133
- const forbidden = gameSession.execDownlink('session.ready', { agentName: 'x', spawn: { x: 0, y: 0 } })
134
- check('session.ready 被 FORBIDDEN 拦截', !forbidden.ok && forbidden.error.code === 'FORBIDDEN')
135
-
136
- // 无效 payload:校验失败
137
- const invalid = gameSession.execDownlink('agent.move', { dir: 'sideways', durationMs: 100 })
138
- check('agent.move 非法 dir → 校验失败', !invalid.ok && invalid.error.code === 'INVALID_PAYLOAD')
139
- gameSession.stop()
140
- }
141
-
142
- async function main(): Promise<void> {
143
- testProtocolSync()
144
- testParseUplink()
145
- testParseDownlink()
146
- testMcpTools()
147
- await testExecDownlink()
148
-
149
- console.log(`\n${failures === 0 ? 'ALL PASS' : `${failures} FAILED`}`)
150
- process.exit(failures === 0 ? 0 : 1)
151
- }
152
-
153
- main().catch((e) => {
154
- console.error(e)
155
- process.exit(1)
156
- })
@@ -1,72 +0,0 @@
1
- import { openWorkshopDb } from '../server/services/workshop/db/database'
2
- import { createTaskRepo } from '../server/services/workshop/db/task.repo'
3
- import { TaskEngine } from '../server/services/workshop/runtime/task-engine'
4
- import { createMessageRepo } from '../server/services/workshop/db/message.repo'
5
-
6
- const db = openWorkshopDb(':memory:')
7
- const now = new Date().toISOString()
8
- db.prepare('INSERT INTO channels (id, name, enabled, created_at, updated_at) VALUES (\'ch1\', \'test\', 1, ?, ?)').run(now, now)
9
- const tasks = createTaskRepo(db)
10
- const messages = createMessageRepo(db)
11
- const engine = new TaskEngine({ tasks, messages })
12
-
13
- let failed = 0
14
- const okIf = (m: string, c: boolean) => {
15
- if (c) console.log(`PASS ${m}`)
16
- else {
17
- console.log(`FAIL ${m}`)
18
- failed++
19
- }
20
- }
21
-
22
- const parent = engine.create({ channelId: 'ch1', creatorId: 'u1', assigneeId: 'lead', title: 'parent', description: '[mode:goal] do it' })
23
- // 调度器同款前置:SUBMITTED → WORKING 后 dispatch(WORKING → WAITING 合法)
24
- engine.transition(parent.id, 'WORKING', 'lead')
25
- engine.dispatch(parent, { assigneeId: 'w1', title: 'child one' })
26
-
27
- // 判重:同父 + 归一化同题(大小写/空白)+ 非终态 → 409,不创建新任务
28
- let caught409 = false
29
- try {
30
- engine.dispatch(parent, { assigneeId: 'w2', title: 'Child ONE' })
31
- }
32
- catch (e) {
33
- const err = e as { code?: string, statusCode?: number, status?: number }
34
- caught409 = err.code === 'DUPLICATE_DISPATCH' || err.statusCode === 409 || err.status === 409
35
- }
36
- okIf('duplicate-dispatch-409', caught409)
37
-
38
- // 409 后无新任务:parent + child one = 2 行;children = 1
39
- const lite = engine.listLite('ch1')
40
- const views = engine.queueViewsOfLite('ch1')
41
- okIf(`listLite rows after 409: ${lite.length} (expect 2: parent+child one)`, lite.length === 2)
42
- okIf('lite fields ok(状态/进度/数组字段齐备,大列置空)', lite.every(t => typeof t.id === 'string' && t.state && typeof t.progress === 'number' && Array.isArray(t.history) && Array.isArray(t.artifacts)))
43
- okIf(`queueViewsLite assignees: ${[...views.keys()].sort().join(',')} (expect lead,w1)`, [...views.keys()].sort().join(',') === 'lead,w1')
44
- okIf(`queued in w1 view: ${views.get('w1')?.queued.length ?? -1} (expect 1)`, views.get('w1')?.queued.length === 1)
45
- okIf(`listChildrenMeta after 409: ${tasks.listChildrenMeta('ch1', parent.id).length} (expect 1)`, tasks.listChildrenMeta('ch1', parent.id).length === 1)
46
-
47
- // 异题派发合法:第二个子任务可建
48
- const c3 = engine.dispatch(parent, { assigneeId: 'w2', title: 'child two' })
49
- okIf('second-distinct-child', !!c3)
50
- okIf(`listLite rows after child two: ${engine.listLite('ch1').length} (expect 3)`, engine.listLite('ch1').length === 3)
51
- okIf(`listChildrenMeta after child two: ${tasks.listChildrenMeta('ch1', parent.id).length} (expect 2)`, tasks.listChildrenMeta('ch1', parent.id).length === 2)
52
-
53
- // 完成闸门:仅一个子完成 → parent 仍 WAITING;双子终态后显式 complete(parent) 放行
54
- const childrenIds = tasks.listChildrenMeta('ch1', parent.id).map(r => r.id)
55
- engine.transition(childrenIds[0]!, 'WORKING', 'w1')
56
- engine.complete(childrenIds[0]!, [{ artifactId: 'a1', name: 'output', parts: [{ text: 'done' }] }])
57
- okIf(`complete-child: ${engine.get(childrenIds[0]!)?.state} (expect COMPLETED)`, engine.get(childrenIds[0]!)?.state === 'COMPLETED')
58
- okIf(`parent state(单子完成): ${engine.get(parent.id)?.state} (expect WAITING)`, engine.get(parent.id)?.state === 'WAITING')
59
- engine.transition(childrenIds[1]!, 'WORKING', 'w2')
60
- engine.complete(childrenIds[1]!, [{ artifactId: 'a2', name: 'output2', parts: [{ text: 'done2' }] }])
61
- // 父任务收口由调度器(goal 宽限窗/规则引擎)负责;TaskEngine 层验证 done-check 闸门:
62
- // 全部子任务终态后 complete(parent) 应放行(WAITING → COMPLETED 合法迁移)
63
- engine.complete(parent.id, [{ artifactId: 'a3', name: 'summary', parts: [{ text: 'all done' }] }])
64
- okIf(`parent state(双子终态后显式 complete): ${engine.get(parent.id)?.state} (expect COMPLETED)`, engine.get(parent.id)?.state === 'COMPLETED')
65
-
66
- // F1:legacy 迁移列与索引
67
- const cols = (db.prepare('PRAGMA table_info(tasks)').all() as Array<{ name: string }>).map(c => c.name)
68
- okIf('route_reason column present', cols.includes('route_reason'))
69
- okIf('idx_tasks_parent present', !!db.prepare('SELECT name FROM sqlite_master WHERE type=\'index\' AND name=\'idx_tasks_parent\'').get())
70
-
71
- console.log(failed ? `SMOKE FAILED(${failed})` : 'SMOKE ALL PASS')
72
- process.exit(failed ? 1 : 0)