agentworkshop 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (895) hide show
  1. package/.AgentWorkShop/prompts/host-tools.json +631 -0
  2. package/.AgentWorkShop/prompts/lead-supervise.md +42 -0
  3. package/.AgentWorkShop/prompts/mode-goal.md +26 -0
  4. package/.AgentWorkShop/prompts/mode-loop.md +10 -0
  5. package/.AgentWorkShop/prompts/mode-pipeline.md +16 -0
  6. package/.AgentWorkShop/prompts/peer-lead-roster.md +3 -0
  7. package/.AgentWorkShop/prompts/peer-message.md +14 -0
  8. package/.AgentWorkShop/prompts/peer-reply-optional.md +2 -0
  9. package/.AgentWorkShop/prompts/peer-reply-required.md +8 -0
  10. package/.AgentWorkShop/prompts/scenario-default.md +11 -0
  11. package/.AgentWorkShop/prompts/system-manual.md +18 -0
  12. package/.AgentWorkShop/prompts/team-roster.md +9 -0
  13. package/.AgentWorkShop/prompts/worker-workflow.md +19 -0
  14. package/.env.example +34 -0
  15. package/README-zh.md +424 -0
  16. package/README.md +424 -0
  17. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.json +1 -0
  18. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/1459e6269990a5d229b9228c8b2f62ffaa7d350068380ae8b875fee0db45cca6.source +180 -0
  19. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/c2991e909c70c5c12b90a407c7adcf63384c51668a2b334e6e047fa675c268fe.source +305 -0
  20. package/app/.mimosa/hook-state/sess_05189059-e42d-4188-8911-4f7baabe009b.mtg0vz68-49792-75b0709555.baseline/e09129039d1e27e3fac24becc9bdafd2d1a7c8049bff24173df007be865f0165.source +264 -0
  21. package/app/.mimosa/hook-status/sess_05189059-e42d-4188-8911-4f7baabe009b-28ef7c75ea.json +14 -0
  22. package/app/app.vue +139 -0
  23. package/app/assets/css/main.css +1257 -0
  24. package/app/components/AppHeader.vue +675 -0
  25. package/app/components/AppSidebar.vue +286 -0
  26. package/app/components/AwChart.vue +44 -0
  27. package/app/components/AwLogo.vue +75 -0
  28. package/app/components/workshop/A2aRpcDebugger.vue +237 -0
  29. package/app/components/workshop/AgentInspectorDrawer.vue +424 -0
  30. package/app/components/workshop/AgentLanesView.vue +947 -0
  31. package/app/components/workshop/ArtifactCard.vue +120 -0
  32. package/app/components/workshop/AssetLibrary.vue +450 -0
  33. package/app/components/workshop/ChannelSessionList.vue +593 -0
  34. package/app/components/workshop/CommandPalette.vue +270 -0
  35. package/app/components/workshop/Composer.vue +731 -0
  36. package/app/components/workshop/DeviceTwinPanel.vue +607 -0
  37. package/app/components/workshop/EventBlock.vue +602 -0
  38. package/app/components/workshop/FileSelectorModal.vue +188 -0
  39. package/app/components/workshop/InspectorPanel.vue +265 -0
  40. package/app/components/workshop/LiveAgentBar.vue +362 -0
  41. package/app/components/workshop/MemoryPanel.vue +364 -0
  42. package/app/components/workshop/MentionHoverCard.vue +155 -0
  43. package/app/components/workshop/MultiChannelView.vue +189 -0
  44. package/app/components/workshop/PaneSplitter.vue +142 -0
  45. package/app/components/workshop/StatsPanel.vue +168 -0
  46. package/app/components/workshop/TaskBoardView.vue +636 -0
  47. package/app/components/workshop/TaskInspectorDrawer.vue +390 -0
  48. package/app/components/workshop/TranscriptTimeline.vue +545 -0
  49. package/app/components/workshop/blocks/ClusterArtifact.vue +77 -0
  50. package/app/components/workshop/blocks/ClusterError.vue +85 -0
  51. package/app/components/workshop/blocks/ClusterLife.vue +87 -0
  52. package/app/components/workshop/blocks/ClusterMember.vue +93 -0
  53. package/app/components/workshop/blocks/ClusterMemory.vue +84 -0
  54. package/app/components/workshop/blocks/ClusterOther.vue +67 -0
  55. package/app/components/workshop/blocks/ClusterRoute.vue +359 -0
  56. package/app/components/workshop/blocks/ClusterStatus.vue +147 -0
  57. package/app/components/workshop/blocks/ClusterStream.vue +325 -0
  58. package/app/components/workshop/blocks/ClusterTask.vue +151 -0
  59. package/app/components/workshop/blocks/ClusterTool.vue +158 -0
  60. package/app/components/workshop/lanes/LaneBlocks.vue +149 -0
  61. package/app/components/workshop/terminal/OmpTerminalPanel.vue +1010 -0
  62. package/app/components/workshop/town/ModelPreview3D.vue +276 -0
  63. package/app/components/workshop/town/TownScene.ts +1355 -0
  64. package/app/components/workshop/town/TownScene3D.ts +4533 -0
  65. package/app/components/workshop/town/TownView.vue +7071 -0
  66. package/app/composables/useCodeCopy.ts +30 -0
  67. package/app/composables/useHttp.ts +8 -0
  68. package/app/composables/useRouteMeta.ts +50 -0
  69. package/app/composables/useSiteConfig.ts +21 -0
  70. package/app/composables/workshop/apiClient.ts +95 -0
  71. package/app/composables/workshop/useCharacterAssets.ts +292 -0
  72. package/app/composables/workshop/useClusteredBlocks.ts +150 -0
  73. package/app/composables/workshop/useComposerBus.ts +16 -0
  74. package/app/composables/workshop/useDaqStream.ts +379 -0
  75. package/app/composables/workshop/useDcwStream.ts +300 -0
  76. package/app/composables/workshop/useDeviceTwins.ts +147 -0
  77. package/app/composables/workshop/useEventBlocks.ts +662 -0
  78. package/app/composables/workshop/useLocalTime.ts +33 -0
  79. package/app/composables/workshop/useOpsLog.ts +164 -0
  80. package/app/composables/workshop/useSceneLayouts.ts +166 -0
  81. package/app/composables/workshop/useTownBus.ts +47 -0
  82. package/app/composables/workshop/useVisibleInterval.ts +42 -0
  83. package/app/composables/workshop/useWorkshopApi.ts +224 -0
  84. package/app/composables/workshop/useWorkshopWs.ts +113 -0
  85. package/app/config/index.ts +66 -0
  86. package/app/config/schema.ts +68 -0
  87. package/app/error.vue +76 -0
  88. package/app/layouts/default.vue +100 -0
  89. package/app/layouts/town.vue +16 -0
  90. package/app/pages/daq/[id].vue +796 -0
  91. package/app/pages/daq/index.vue +2577 -0
  92. package/app/pages/dcw/[id].vue +2259 -0
  93. package/app/pages/dcw/index.vue +1079 -0
  94. package/app/pages/index.vue +830 -0
  95. package/app/pages/logs/index.vue +621 -0
  96. package/app/pages/monitor.vue +665 -0
  97. package/app/pages/settings.vue +757 -0
  98. package/app/pages/tokens.vue +610 -0
  99. package/app/pages/town.vue +145 -0
  100. package/app/pages/users.vue +257 -0
  101. package/app/pages/workshop/agents.vue +382 -0
  102. package/app/pages/workshop/channel-templates.vue +456 -0
  103. package/app/pages/workshop/index.vue +604 -0
  104. package/app/pages/workshop/teams.vue +448 -0
  105. package/app/pages/workshop/w/[wsId].vue +516 -0
  106. package/app/plugins/http.ts +71 -0
  107. package/app/plugins/locale-restore.client.ts +13 -0
  108. package/app/plugins/runtime-config.client.ts +65 -0
  109. package/app/plugins/session-restore.client.ts +24 -0
  110. package/app/plugins/theme.client.ts +15 -0
  111. package/app/stores/app.ts +32 -0
  112. package/app/stores/route-trail.ts +45 -0
  113. package/app/stores/runtime-config.ts +212 -0
  114. package/app/stores/workshop/connection.ts +184 -0
  115. package/app/stores/workshop/entities.ts +350 -0
  116. package/app/stores/workshop/events.ts +292 -0
  117. package/app/stores/workshop/user.ts +176 -0
  118. package/app/stores/workshop/workspaces.ts +133 -0
  119. package/bin/aw.mjs +13 -0
  120. package/cli/aw.mjs +184 -0
  121. package/cli/commands/build.mjs +33 -0
  122. package/cli/commands/config.mjs +157 -0
  123. package/cli/commands/dev.mjs +74 -0
  124. package/cli/commands/doctor.mjs +120 -0
  125. package/cli/commands/home.mjs +75 -0
  126. package/cli/commands/init.mjs +150 -0
  127. package/cli/commands/register.mjs +123 -0
  128. package/cli/commands/start.mjs +106 -0
  129. package/cli/commands/status.mjs +67 -0
  130. package/cli/commands/update.mjs +116 -0
  131. package/cli/commands/version.mjs +32 -0
  132. package/cli/core/args.mjs +95 -0
  133. package/cli/core/context.mjs +264 -0
  134. package/cli/core/errors.mjs +18 -0
  135. package/cli/core/help.mjs +68 -0
  136. package/cli/core/logger.mjs +40 -0
  137. package/cli/core/registry.mjs +111 -0
  138. package/config.yml +70 -0
  139. package/docker-compose.yml +34 -0
  140. package/docs/cli.md +220 -0
  141. package/i18n/dicts/_en.json +1097 -0
  142. package/i18n/dicts/_en2.json +300 -0
  143. package/i18n/dicts/_en3.json +102 -0
  144. package/i18n/dicts/_en4.json +115 -0
  145. package/i18n/dicts/_en5.json +33 -0
  146. package/i18n/dicts/a2aRpcDebugger.json +10 -0
  147. package/i18n/dicts/agentInspectorDrawer.json +25 -0
  148. package/i18n/dicts/agentLanesView.json +57 -0
  149. package/i18n/dicts/agents.json +27 -0
  150. package/i18n/dicts/appHeader.json +7 -0
  151. package/i18n/dicts/appSidebar.json +1 -0
  152. package/i18n/dicts/artifactCard.json +6 -0
  153. package/i18n/dicts/assetLibrary.json +18 -0
  154. package/i18n/dicts/awChart.json +1 -0
  155. package/i18n/dicts/awLogo.json +1 -0
  156. package/i18n/dicts/channelSessionList.json +45 -0
  157. package/i18n/dicts/clusterArtifact.json +4 -0
  158. package/i18n/dicts/clusterError.json +3 -0
  159. package/i18n/dicts/clusterLife.json +5 -0
  160. package/i18n/dicts/clusterMember.json +3 -0
  161. package/i18n/dicts/clusterMemory.json +3 -0
  162. package/i18n/dicts/clusterOther.json +3 -0
  163. package/i18n/dicts/clusterRoute.json +15 -0
  164. package/i18n/dicts/clusterStatus.json +3 -0
  165. package/i18n/dicts/clusterStream.json +3 -0
  166. package/i18n/dicts/clusterTask.json +10 -0
  167. package/i18n/dicts/clusterTool.json +3 -0
  168. package/i18n/dicts/commandPalette.json +16 -0
  169. package/i18n/dicts/composer.json +38 -0
  170. package/i18n/dicts/ctpl.json +32 -0
  171. package/i18n/dicts/daq.json +157 -0
  172. package/i18n/dicts/daqDetail.json +55 -0
  173. package/i18n/dicts/dcw.json +68 -0
  174. package/i18n/dicts/dcwDetail.json +199 -0
  175. package/i18n/dicts/deviceTwinPanel.json +12 -0
  176. package/i18n/dicts/eventBlock.json +8 -0
  177. package/i18n/dicts/fileSelectorModal.json +6 -0
  178. package/i18n/dicts/inspectorPanel.json +12 -0
  179. package/i18n/dicts/laneBlocks.json +6 -0
  180. package/i18n/dicts/liveAgentBar.json +8 -0
  181. package/i18n/dicts/logs.json +39 -0
  182. package/i18n/dicts/memoryPanel.json +20 -0
  183. package/i18n/dicts/mentionHoverCard.json +4 -0
  184. package/i18n/dicts/modelPreview3D.json +1 -0
  185. package/i18n/dicts/monitor.json +5 -0
  186. package/i18n/dicts/multiChannelView.json +13 -0
  187. package/i18n/dicts/ompTerminalPanel.json +7 -0
  188. package/i18n/dicts/paneSplitter.json +3 -0
  189. package/i18n/dicts/settings.json +1 -0
  190. package/i18n/dicts/statsPanel.json +6 -0
  191. package/i18n/dicts/taskBoardView.json +22 -0
  192. package/i18n/dicts/taskInspectorDrawer.json +19 -0
  193. package/i18n/dicts/teams.json +33 -0
  194. package/i18n/dicts/tokens.json +30 -0
  195. package/i18n/dicts/town.json +7 -0
  196. package/i18n/dicts/townView.json +209 -0
  197. package/i18n/dicts/transcriptTimeline.json +31 -0
  198. package/i18n/dicts/users.json +15 -0
  199. package/i18n/dicts/wsHome.json +33 -0
  200. package/i18n/dicts/wsView.json +15 -0
  201. package/i18n/locales/en.ts +1737 -0
  202. package/i18n/locales/zh-CN.ts +1736 -0
  203. package/nuxt.config.ts +209 -0
  204. package/package.json +123 -0
  205. package/public/assets/game/character/bot.png +0 -0
  206. package/public/assets/game/character/device-3d.glb +0 -0
  207. package/public/assets/game/character/hero-3d.glb +0 -0
  208. package/public/assets/game/character/hero-anime-1.glb +0 -0
  209. package/public/assets/game/character/hero-anime-2.glb +0 -0
  210. package/public/assets/game/character/hero-anime-3.glb +0 -0
  211. package/public/assets/game/character/hero-anime-4.glb +0 -0
  212. package/public/assets/game/character/knight.png +0 -0
  213. package/public/assets/game/character/mage.png +0 -0
  214. package/public/assets/game/coin.png +0 -0
  215. package/public/assets/game/devices/agv.glb +0 -0
  216. package/public/assets/game/devices/caster.glb +0 -0
  217. package/public/assets/game/devices/device-console.glb +0 -0
  218. package/public/assets/game/devices/device-robot-arm.glb +0 -0
  219. package/public/assets/game/devices/device-scanner.glb +0 -0
  220. package/public/assets/game/devices/extruder.glb +0 -0
  221. package/public/assets/game/devices/mdo.glb +0 -0
  222. package/public/assets/game/devices/power-cabinet.glb +0 -0
  223. package/public/assets/game/devices/pump.glb +0 -0
  224. package/public/assets/game/devices/tdo.glb +0 -0
  225. package/public/assets/game/devices/thickness-scanner.glb +0 -0
  226. package/public/assets/game/devices/winder.glb +0 -0
  227. package/public/assets/game/npc/boltnu-sheet.png +0 -0
  228. package/public/assets/game/npc/fluttaflap-sheet.png +0 -0
  229. package/public/assets/game/npc/rockitten-sheet.png +0 -0
  230. package/public/assets/game/npc/tux-sheet.png +0 -0
  231. package/public/assets/game/player/misa-back-walk.000.png +0 -0
  232. package/public/assets/game/player/misa-back-walk.001.png +0 -0
  233. package/public/assets/game/player/misa-back-walk.002.png +0 -0
  234. package/public/assets/game/player/misa-back-walk.003.png +0 -0
  235. package/public/assets/game/player/misa-back.png +0 -0
  236. package/public/assets/game/player/misa-front-walk.000.png +0 -0
  237. package/public/assets/game/player/misa-front-walk.001.png +0 -0
  238. package/public/assets/game/player/misa-front-walk.002.png +0 -0
  239. package/public/assets/game/player/misa-front-walk.003.png +0 -0
  240. package/public/assets/game/player/misa-front.png +0 -0
  241. package/public/assets/game/player/misa-left-walk.000.png +0 -0
  242. package/public/assets/game/player/misa-left-walk.001.png +0 -0
  243. package/public/assets/game/player/misa-left-walk.002.png +0 -0
  244. package/public/assets/game/player/misa-left-walk.003.png +0 -0
  245. package/public/assets/game/player/misa-left.png +0 -0
  246. package/public/assets/game/player/misa-right-walk.000.png +0 -0
  247. package/public/assets/game/player/misa-right-walk.001.png +0 -0
  248. package/public/assets/game/player/misa-right-walk.002.png +0 -0
  249. package/public/assets/game/player/misa-right-walk.003.png +0 -0
  250. package/public/assets/game/player/misa-right.png +0 -0
  251. package/public/assets/game/player-sheet.png +0 -0
  252. package/public/assets/game/tuxemon-town.json +1 -0
  253. package/public/assets/game/tuxmon-sample-32px-extruded.png +0 -0
  254. package/public/assets/game/wuwa/scene-map.png +0 -0
  255. package/public/assets/game/wuwa/world-far.png +0 -0
  256. package/public/assets/game/wuwa/world-middle.png +0 -0
  257. package/public/assets/game/wuwa/world-near.png +0 -0
  258. package/public/assets/game/wuwa/wu-aura.png +0 -0
  259. package/public/assets/game/wuwa/wu-lead.png +0 -0
  260. package/public/assets/game/wuwa/wu-ring.png +0 -0
  261. package/public/assets/game/wuwa/wu-slash.png +0 -0
  262. package/public/assets/game/wuwa/wu-worker-0.png +0 -0
  263. package/public/assets/game/wuwa/wu-worker-1.png +0 -0
  264. package/public/assets/game/wuwa/wu-worker-2.png +0 -0
  265. package/public/favicon.svg +14 -0
  266. package/public/scene/background/cyber-town-background.svg +110 -0
  267. package/scripts/_daq-realtime-probe.mjs +68 -0
  268. package/scripts/_daq-warn-probe.mjs +50 -0
  269. package/scripts/_dbg-agent-tools-audit.mjs +154 -0
  270. package/scripts/_dbg-agent-workflow-audit.mjs +177 -0
  271. package/scripts/_dbg-anim-verify.mjs +81 -0
  272. package/scripts/_dbg-audit-all-pages.mjs +43 -0
  273. package/scripts/_dbg-autoframe.mjs +103 -0
  274. package/scripts/_dbg-beacon-final.mjs +181 -0
  275. package/scripts/_dbg-bind-bidi-e2e.mjs +239 -0
  276. package/scripts/_dbg-callout-near.mjs +108 -0
  277. package/scripts/_dbg-chan-focus.mjs +49 -0
  278. package/scripts/_dbg-cleanup.mjs +31 -0
  279. package/scripts/_dbg-closedloop-ui-shot.mjs +61 -0
  280. package/scripts/_dbg-console-audit.mjs +61 -0
  281. package/scripts/_dbg-console-probe.mjs +23 -0
  282. package/scripts/_dbg-context-inject-audit.mjs +231 -0
  283. package/scripts/_dbg-crash-recovery.mjs +143 -0
  284. package/scripts/_dbg-crop-shot.mjs +16 -0
  285. package/scripts/_dbg-daq-acc-probe.mjs +24 -0
  286. package/scripts/_dbg-daq-attrib.mjs +34 -0
  287. package/scripts/_dbg-daq-bind-audit.mjs +119 -0
  288. package/scripts/_dbg-daq-cadence.mjs +104 -0
  289. package/scripts/_dbg-daq-debug.mjs +22 -0
  290. package/scripts/_dbg-daq-diag.mjs +33 -0
  291. package/scripts/_dbg-daq-e2e.mjs +171 -0
  292. package/scripts/_dbg-daq-film.mjs +136 -0
  293. package/scripts/_dbg-daq-filter-e2e.mjs +109 -0
  294. package/scripts/_dbg-daq-filter-e2e2.mjs +62 -0
  295. package/scripts/_dbg-daq-final-regression.mjs +78 -0
  296. package/scripts/_dbg-daq-full-check.mjs +179 -0
  297. package/scripts/_dbg-daq-line-note-verify.mjs +61 -0
  298. package/scripts/_dbg-daq-linebanner-audit.mjs +107 -0
  299. package/scripts/_dbg-daq-pages-shot.mjs +37 -0
  300. package/scripts/_dbg-daq-perf.mjs +61 -0
  301. package/scripts/_dbg-daq-probe.mjs +27 -0
  302. package/scripts/_dbg-daq-recipe-e2e.mjs +30 -0
  303. package/scripts/_dbg-daq-redesign-shot.mjs +88 -0
  304. package/scripts/_dbg-daq-rows-probe.mjs +26 -0
  305. package/scripts/_dbg-daq-rowstate-e2e.mjs +152 -0
  306. package/scripts/_dbg-daq-rowstate-shot.mjs +45 -0
  307. package/scripts/_dbg-daq-rowstate-shot2.mjs +38 -0
  308. package/scripts/_dbg-daq-tpl.mjs +144 -0
  309. package/scripts/_dbg-dash-console-check.mjs +49 -0
  310. package/scripts/_dbg-dash-deep-probe.mjs +61 -0
  311. package/scripts/_dbg-dash-hitpoint.mjs +44 -0
  312. package/scripts/_dbg-dash-live-shot.mjs +36 -0
  313. package/scripts/_dbg-dash-shot.mjs +21 -0
  314. package/scripts/_dbg-dashboard-shot.mjs +35 -0
  315. package/scripts/_dbg-dcw-audit.mjs +126 -0
  316. package/scripts/_dbg-dcw-card-e2e.mjs +108 -0
  317. package/scripts/_dbg-dcw-channel-ui.mjs +144 -0
  318. package/scripts/_dbg-dcw-examples.mjs +81 -0
  319. package/scripts/_dbg-dcw-light-shot.mjs +19 -0
  320. package/scripts/_dbg-dcw-line-audit.mjs +107 -0
  321. package/scripts/_dbg-dcw-pause-tpl-audit.mjs +161 -0
  322. package/scripts/_dbg-dcw-pause-ui.mjs +175 -0
  323. package/scripts/_dbg-dcw-scene.mjs +72 -0
  324. package/scripts/_dbg-dcw-shot2.mjs +14 -0
  325. package/scripts/_dbg-dcw-twin-e2e.mjs +192 -0
  326. package/scripts/_dbg-dt-interact.mjs +193 -0
  327. package/scripts/_dbg-error-probe.mjs +54 -0
  328. package/scripts/_dbg-filter-light-verify.mjs +54 -0
  329. package/scripts/_dbg-final-acceptance-2.mjs +72 -0
  330. package/scripts/_dbg-final-acceptance.mjs +192 -0
  331. package/scripts/_dbg-final-agent-e2e.mjs +151 -0
  332. package/scripts/_dbg-final-full-e2e.mjs +218 -0
  333. package/scripts/_dbg-final-line-e2e.mjs +173 -0
  334. package/scripts/_dbg-final-t6-hitl.mjs +38 -0
  335. package/scripts/_dbg-focus-range.mjs +115 -0
  336. package/scripts/_dbg-fresh-scene-e2e.mjs +125 -0
  337. package/scripts/_dbg-full-feature-e2e.mjs +219 -0
  338. package/scripts/_dbg-fullchain-e2e.mjs +178 -0
  339. package/scripts/_dbg-gate-debug.mjs +37 -0
  340. package/scripts/_dbg-gif-encode.mjs +111 -0
  341. package/scripts/_dbg-gizmo.mjs +95 -0
  342. package/scripts/_dbg-glass-probe.mjs +57 -0
  343. package/scripts/_dbg-glass-shot.mjs +50 -0
  344. package/scripts/_dbg-glass-sweep.mjs +25 -0
  345. package/scripts/_dbg-glb-probe.mjs +43 -0
  346. package/scripts/_dbg-hardening-probe.mjs +90 -0
  347. package/scripts/_dbg-hero-btn-probe.mjs +21 -0
  348. package/scripts/_dbg-hidden-check.mjs +21 -0
  349. package/scripts/_dbg-hitl-timeout-e2e.mjs +93 -0
  350. package/scripts/_dbg-hmi-audit.mjs +164 -0
  351. package/scripts/_dbg-home-repro.mjs +24 -0
  352. package/scripts/_dbg-home-stack.mjs +13 -0
  353. package/scripts/_dbg-huashu-survey.mjs +31 -0
  354. package/scripts/_dbg-huashu-survey2.mjs +35 -0
  355. package/scripts/_dbg-huashu-verify.mjs +25 -0
  356. package/scripts/_dbg-huashu-verify2.mjs +26 -0
  357. package/scripts/_dbg-hydration-detail.mjs +18 -0
  358. package/scripts/_dbg-i18n-debug.mjs +27 -0
  359. package/scripts/_dbg-i18n-debug2.mjs +26 -0
  360. package/scripts/_dbg-i18n-final.mjs +42 -0
  361. package/scripts/_dbg-i18n-scan.mjs +38 -0
  362. package/scripts/_dbg-infra-lifecycle.mjs +44 -0
  363. package/scripts/_dbg-line-aura-shots.mjs +54 -0
  364. package/scripts/_dbg-line-control-e2e.mjs +120 -0
  365. package/scripts/_dbg-line-gate-audit.mjs +108 -0
  366. package/scripts/_dbg-line-live-e2e.mjs +144 -0
  367. package/scripts/_dbg-line-scenario-e2e.mjs +256 -0
  368. package/scripts/_dbg-minimal-omp.mjs +77 -0
  369. package/scripts/_dbg-mode-nav.mjs +173 -0
  370. package/scripts/_dbg-mqtt-chain-e2e.mjs +90 -0
  371. package/scripts/_dbg-nav-rpg.mjs +84 -0
  372. package/scripts/_dbg-nav-shot.mjs +28 -0
  373. package/scripts/_dbg-nav.mjs +27 -0
  374. package/scripts/_dbg-opslog-e2e.mjs +121 -0
  375. package/scripts/_dbg-opslog-shots.mjs +62 -0
  376. package/scripts/_dbg-opt-team-e2e.mjs +133 -0
  377. package/scripts/_dbg-optimization-e2e.mjs +94 -0
  378. package/scripts/_dbg-orbit.mjs +58 -0
  379. package/scripts/_dbg-panesplitter-fix-check.mjs +62 -0
  380. package/scripts/_dbg-phase-e3-monitor.mjs +25 -0
  381. package/scripts/_dbg-pop-clamp-verify.mjs +77 -0
  382. package/scripts/_dbg-preset-e2e.mjs +116 -0
  383. package/scripts/_dbg-preview-console.mjs +28 -0
  384. package/scripts/_dbg-preview-minrepro.mjs +156 -0
  385. package/scripts/_dbg-preview-pixels.mjs +93 -0
  386. package/scripts/_dbg-quality-pages-e2e.mjs +84 -0
  387. package/scripts/_dbg-query-cancel.ts +12 -0
  388. package/scripts/_dbg-rail-tree-e2e.mjs +183 -0
  389. package/scripts/_dbg-real-driver-e2e.mjs +55 -0
  390. package/scripts/_dbg-redesign-shots.mjs +34 -0
  391. package/scripts/_dbg-restart-persist.mjs +41 -0
  392. package/scripts/_dbg-rollback-mgr-audit.mjs +169 -0
  393. package/scripts/_dbg-rpg.mjs +71 -0
  394. package/scripts/_dbg-sc001-dispatch.mjs +63 -0
  395. package/scripts/_dbg-scenario-final-shot.mjs +24 -0
  396. package/scripts/_dbg-scenario-phase-e2.mjs +75 -0
  397. package/scripts/_dbg-scenario-phase-e3.mjs +96 -0
  398. package/scripts/_dbg-scenario-phase1.mjs +90 -0
  399. package/scripts/_dbg-scenario-phase2.mjs +105 -0
  400. package/scripts/_dbg-scenario-phase3-monitor.mjs +48 -0
  401. package/scripts/_dbg-scenario-phase3.mjs +111 -0
  402. package/scripts/_dbg-scene-polish-shot.mjs +118 -0
  403. package/scripts/_dbg-selring-probe.mjs +47 -0
  404. package/scripts/_dbg-sideinfo.mjs +101 -0
  405. package/scripts/_dbg-splitter.mjs +88 -0
  406. package/scripts/_dbg-team-repro.mjs +76 -0
  407. package/scripts/_dbg-town-alarm-e2e.mjs +40 -0
  408. package/scripts/_dbg-town-beauty-shots.mjs +54 -0
  409. package/scripts/_dbg-town-daq-shot.mjs +26 -0
  410. package/scripts/_dbg-town-full-e2e.mjs +104 -0
  411. package/scripts/_dbg-town-gate.mjs +44 -0
  412. package/scripts/_dbg-town-ins-probe.mjs +37 -0
  413. package/scripts/_dbg-town-perf.mjs +50 -0
  414. package/scripts/_dbg-town-polish-shots.mjs +82 -0
  415. package/scripts/_dbg-town-realtime.mjs +42 -0
  416. package/scripts/_dbg-town-shot3.mjs +17 -0
  417. package/scripts/_dbg-town-truth.mjs +37 -0
  418. package/scripts/_dbg-town-truth2.mjs +27 -0
  419. package/scripts/_dbg-transform-audit.mjs +98 -0
  420. package/scripts/_dbg-trend-expand-test.mjs +38 -0
  421. package/scripts/_dbg-twindaq-focus.mjs +81 -0
  422. package/scripts/_dbg-ui-polish-shot.mjs +43 -0
  423. package/scripts/_dbg-ui-polish-verify1.mjs +92 -0
  424. package/scripts/_dbg-ui-polish-verify2.mjs +50 -0
  425. package/scripts/_dbg-ui-polish-verify3.mjs +51 -0
  426. package/scripts/_dbg-ui-polish-verify4.mjs +50 -0
  427. package/scripts/_dbg-ui-shot.mjs +26 -0
  428. package/scripts/_dbg-unify-shot.mjs +43 -0
  429. package/scripts/_dbg-uplink-probe.mjs +36 -0
  430. package/scripts/_dbg-wizard-preview-shot.mjs +58 -0
  431. package/scripts/_dbg-wizard-ui-e2e.mjs +93 -0
  432. package/scripts/_dbg-ws-probe.mjs +86 -0
  433. package/scripts/_dbg-ws-shot2.mjs +23 -0
  434. package/scripts/_dbg-wsdot-sanity.mjs +25 -0
  435. package/scripts/_dev-stack.mjs +46 -0
  436. package/scripts/_http-driver-probe.mjs +30 -0
  437. package/scripts/_lib-dcw-line.mjs +24 -0
  438. package/scripts/_mqtt-driver-probe.mjs +30 -0
  439. package/scripts/_newdriver-rest-probe.mjs +100 -0
  440. package/scripts/_node-state-probe.mjs +5 -0
  441. package/scripts/_opcua-driver-probe.mjs +31 -0
  442. package/scripts/_rtu-debug.mjs +41 -0
  443. package/scripts/_rtu-direct.mjs +6 -0
  444. package/scripts/_rtu-driver-probe.mjs +53 -0
  445. package/scripts/_rtu-mini-slave.mjs +63 -0
  446. package/scripts/_townview_style.css +1185 -0
  447. package/scripts/_townview_template.html +1215 -0
  448. package/scripts/_wizard-shots.mjs +90 -0
  449. package/scripts/acceptance-suite.py +207 -0
  450. package/scripts/api-live-e2e.mjs +467 -0
  451. package/scripts/build-anime-models.mjs +339 -0
  452. package/scripts/build-character-models.mjs +175 -0
  453. package/scripts/build-film-devices.mjs +227 -0
  454. package/scripts/build-model-3d.mjs +173 -0
  455. package/scripts/build-player-sheet.mjs +58 -0
  456. package/scripts/build-world-map.mjs +188 -0
  457. package/scripts/build-wuwa-assets.mjs +345 -0
  458. package/scripts/collab-live-test.py +177 -0
  459. package/scripts/debug-mcp-http.ts +64 -0
  460. package/scripts/demo-lead-worker.ts +256 -0
  461. package/scripts/demo-modes.ts +415 -0
  462. package/scripts/demo-omp-channel.ts +135 -0
  463. package/scripts/design-preflight.mjs +223 -0
  464. package/scripts/design-verify-templates.mjs +110 -0
  465. package/scripts/design-verify.mjs +170 -0
  466. package/scripts/dev-guard.mjs +74 -0
  467. package/scripts/dev-modbus-simulator.mjs +55 -0
  468. package/scripts/dev-opcua-simulator.mjs +57 -0
  469. package/scripts/dev-protocol-simulators.mjs +145 -0
  470. package/scripts/dev-window.cmd +6 -0
  471. package/scripts/device-line-restore.mjs +34 -0
  472. package/scripts/diag-lead-status.ts +101 -0
  473. package/scripts/e2e-a2a-steer-live.mjs +193 -0
  474. package/scripts/e2e-agent-channel-task.ts +151 -0
  475. package/scripts/e2e-agent-team.mjs +168 -0
  476. package/scripts/e2e-auth-matrix.mjs +119 -0
  477. package/scripts/e2e-channel-isolation.ts +325 -0
  478. package/scripts/e2e-dual-drive-comm.ts +259 -0
  479. package/scripts/e2e-lead-team-mgmt.ts +217 -0
  480. package/scripts/e2e-memory-persistence.ts +320 -0
  481. package/scripts/e2e-memory-system.ts +332 -0
  482. package/scripts/e2e-omp-modes.ts +274 -0
  483. package/scripts/e2e-omp-realtime.ts +258 -0
  484. package/scripts/e2e-omp-workspace.ts +180 -0
  485. package/scripts/e2e-parallel-execution.mjs +151 -0
  486. package/scripts/e2e-rest-memory.mjs +251 -0
  487. package/scripts/e2e-rest-robustness.mjs +177 -0
  488. package/scripts/e2e-resume-crash.mjs +254 -0
  489. package/scripts/e2e-tab-close.mjs +136 -0
  490. package/scripts/e2e-task-queue.ts +277 -0
  491. package/scripts/e2e-template-isolation.mjs +267 -0
  492. package/scripts/e2e-token-ui.mjs +149 -0
  493. package/scripts/final-soup-run.py +192 -0
  494. package/scripts/final-soup-watch.py +83 -0
  495. package/scripts/home-bootstrap.mjs +117 -0
  496. package/scripts/i18n-codemod.mjs +173 -0
  497. package/scripts/i18n-fix-en.py +28 -0
  498. package/scripts/i18n-fix-en2.py +31 -0
  499. package/scripts/i18n-merge.mjs +67 -0
  500. package/scripts/omp-real-test.py +328 -0
  501. package/scripts/smoke-optimization-verify.ts +72 -0
  502. package/scripts/start.mjs +60 -0
  503. package/scripts/test-a2a-relay.mjs +222 -0
  504. package/scripts/test-a2a-types.ts +296 -0
  505. package/scripts/test-agent-brain.ts +135 -0
  506. package/scripts/test-agent-multi-channel.ts +160 -0
  507. package/scripts/test-agent-runtime.ts +348 -0
  508. package/scripts/test-api-client.ts +108 -0
  509. package/scripts/test-api-suite.mjs +271 -0
  510. package/scripts/test-block-consumption.mjs +194 -0
  511. package/scripts/test-channel-routing.ts +301 -0
  512. package/scripts/test-cmd-render.mjs +218 -0
  513. package/scripts/test-collab-e2e.mjs +136 -0
  514. package/scripts/test-collab-omp.mjs +192 -0
  515. package/scripts/test-dedup-logic.ts +132 -0
  516. package/scripts/test-dual-drive.ts +227 -0
  517. package/scripts/test-e2e-collaboration.ts +262 -0
  518. package/scripts/test-e2e-monitor.ts +192 -0
  519. package/scripts/test-event-history.ts +112 -0
  520. package/scripts/test-event-persistence.mjs +169 -0
  521. package/scripts/test-exec-modes.ts +316 -0
  522. package/scripts/test-fifo-realtime.mjs +193 -0
  523. package/scripts/test-final-e2e.mjs +290 -0
  524. package/scripts/test-full-system.ts +439 -0
  525. package/scripts/test-game-session.ts +160 -0
  526. package/scripts/test-goal-summary.ts +202 -0
  527. package/scripts/test-harness-liveness.ts +109 -0
  528. package/scripts/test-harness-terminal.ts +164 -0
  529. package/scripts/test-header-trail.mjs +95 -0
  530. package/scripts/test-hitl.ts +360 -0
  531. package/scripts/test-koda-restyle.mjs +105 -0
  532. package/scripts/test-lane-history-live.mjs +103 -0
  533. package/scripts/test-lane-raw.ts +67 -0
  534. package/scripts/test-lanes-history-render.mjs +138 -0
  535. package/scripts/test-loop-omp.mjs +154 -0
  536. package/scripts/test-mcp-tools.ts +285 -0
  537. package/scripts/test-mdlite.ts +53 -0
  538. package/scripts/test-memory-dynamic.ts +99 -0
  539. package/scripts/test-memory-maintenance.ts +117 -0
  540. package/scripts/test-memory-vector.ts +154 -0
  541. package/scripts/test-memory.ts +431 -0
  542. package/scripts/test-mock-collab.mjs +226 -0
  543. package/scripts/test-modern-render.mjs +174 -0
  544. package/scripts/test-omp-terminal.mjs +187 -0
  545. package/scripts/test-orchestration.ts +425 -0
  546. package/scripts/test-persistence-lazy.ts +323 -0
  547. package/scripts/test-prompt-system.mjs +181 -0
  548. package/scripts/test-prompts-loader.ts +56 -0
  549. package/scripts/test-protocol.ts +156 -0
  550. package/scripts/test-real-scenario.mjs +290 -0
  551. package/scripts/test-route-reason.mjs +111 -0
  552. package/scripts/test-scheduler-loop.ts +469 -0
  553. package/scripts/test-stream-render.ts +37 -0
  554. package/scripts/test-task-drawer.mjs +204 -0
  555. package/scripts/test-task-engine.ts +433 -0
  556. package/scripts/test-task-invariants.mjs +169 -0
  557. package/scripts/test-terminal-e2e.mjs +264 -0
  558. package/scripts/test-town-3d.mjs +121 -0
  559. package/scripts/test-town-drag.mjs +218 -0
  560. package/scripts/test-town-layout.mjs +200 -0
  561. package/scripts/test-town-page.mjs +136 -0
  562. package/scripts/test-town-scene-math.ts +169 -0
  563. package/scripts/test-town-twin.mjs +121 -0
  564. package/scripts/test-town-upload.mjs +89 -0
  565. package/scripts/test-town-user-flow.mjs +619 -0
  566. package/scripts/test-town-world.mjs +76 -0
  567. package/scripts/test-town-wuwa.mjs +198 -0
  568. package/scripts/test-user-isolation.mjs +193 -0
  569. package/scripts/test-workshop-db.ts +280 -0
  570. package/scripts/test-workshop-entries.ts +370 -0
  571. package/scripts/test-workspace-api.ts +329 -0
  572. package/scripts/test-ws-aep.mjs +187 -0
  573. package/scripts/test-ws-protocol.ts +134 -0
  574. package/scripts/test-ws-stress.mjs +208 -0
  575. package/scripts/town-demo-seed.mjs +75 -0
  576. package/scripts/town-scene-clear.mjs +56 -0
  577. package/scripts/ui-screenshot.mjs +128 -0
  578. package/scripts/verify-a2a-live.mjs +124 -0
  579. package/scripts/verify-exec-modes-report.ts +248 -0
  580. package/scripts/verify-game.mjs +477 -0
  581. package/scripts/verify-lead-mail.ts +188 -0
  582. package/scripts/verify-page-smoke.mjs +87 -0
  583. package/scripts/verify-ws-events.mjs +123 -0
  584. package/scripts/ws-test.mjs +176 -0
  585. package/scripts/ws-test.py +4 -0
  586. package/server/api/health.get.ts +32 -0
  587. package/server/api/mcp/workshop.ts +78 -0
  588. package/server/api/metrics.ts +75 -0
  589. package/server/api/system/config.get.ts +12 -0
  590. package/server/api/system/monitor/terminal/ws.ts +177 -0
  591. package/server/api/system/monitor/terminate.post.ts +36 -0
  592. package/server/api/system/monitor.get.ts +13 -0
  593. package/server/api/system/settings/events.get.ts +28 -0
  594. package/server/api/system/settings/index.get.ts +14 -0
  595. package/server/api/system/settings/index.patch.ts +22 -0
  596. package/server/api/system/settings/reset.post.ts +12 -0
  597. package/server/api/users/[id].delete.ts +11 -0
  598. package/server/api/users/[id].get.ts +11 -0
  599. package/server/api/users/[id].put.ts +14 -0
  600. package/server/api/users/index.get.ts +13 -0
  601. package/server/api/users/index.post.ts +13 -0
  602. package/server/api/users/login.post.ts +11 -0
  603. package/server/api/users/logout.post.ts +9 -0
  604. package/server/api/users/me.get.ts +9 -0
  605. package/server/api/users/register.post.ts +11 -0
  606. package/server/api/users/tokens/[id]/token.get.ts +11 -0
  607. package/server/api/users/tokens/[id].delete.ts +11 -0
  608. package/server/api/users/tokens/[id].patch.ts +14 -0
  609. package/server/api/users/tokens/index.get.ts +9 -0
  610. package/server/api/users/tokens/index.post.ts +13 -0
  611. package/server/api/workshop/[...path].ts +13 -0
  612. package/server/api/workshop/a2a/[agentId]/card/index.get.ts +75 -0
  613. package/server/api/workshop/a2a/[agentId]/rpc/index.post.ts +429 -0
  614. package/server/api/workshop/a2a/send.post.ts +28 -0
  615. package/server/api/workshop/agent-tools/approvals/[id]/decide.post.ts +21 -0
  616. package/server/api/workshop/agent-tools/approvals/index.get.ts +18 -0
  617. package/server/api/workshop/agent-tools/bindings/[id].delete.ts +21 -0
  618. package/server/api/workshop/agent-tools/bindings/[id].patch.ts +14 -0
  619. package/server/api/workshop/agent-tools/bindings/index.get.ts +14 -0
  620. package/server/api/workshop/agent-tools/bindings/index.post.ts +20 -0
  621. package/server/api/workshop/agent-tools/invoke.post.ts +34 -0
  622. package/server/api/workshop/agents/[id].delete.ts +20 -0
  623. package/server/api/workshop/agents/[id].get.ts +19 -0
  624. package/server/api/workshop/agents/[id].patch.ts +30 -0
  625. package/server/api/workshop/agents/index.get.ts +13 -0
  626. package/server/api/workshop/agents/index.post.ts +29 -0
  627. package/server/api/workshop/agents/subscribe.post.ts +21 -0
  628. package/server/api/workshop/approvals/[id]/decide.post.ts +30 -0
  629. package/server/api/workshop/approvals/index.get.ts +22 -0
  630. package/server/api/workshop/assets/character/[id].delete.ts +33 -0
  631. package/server/api/workshop/assets/character/index.get.ts +17 -0
  632. package/server/api/workshop/assets/character/index.post.ts +87 -0
  633. package/server/api/workshop/assets/devices/[id].delete.ts +43 -0
  634. package/server/api/workshop/assets/devices/index.get.ts +103 -0
  635. package/server/api/workshop/assets/devices/index.post.ts +53 -0
  636. package/server/api/workshop/audit.get.ts +43 -0
  637. package/server/api/workshop/caller.ts +141 -0
  638. package/server/api/workshop/channel-templates/[id]/instantiate.post.ts +31 -0
  639. package/server/api/workshop/channel-templates/[id].delete.ts +20 -0
  640. package/server/api/workshop/channel-templates/[id].get.ts +19 -0
  641. package/server/api/workshop/channel-templates/[id].patch.ts +48 -0
  642. package/server/api/workshop/channel-templates/from-channel.post.ts +31 -0
  643. package/server/api/workshop/channel-templates/index.get.ts +13 -0
  644. package/server/api/workshop/channel-templates/index.post.ts +61 -0
  645. package/server/api/workshop/channels/[id]/activate.post.ts +19 -0
  646. package/server/api/workshop/channels/[id]/agents/[agentId]/memories/[memoryId].delete.ts +30 -0
  647. package/server/api/workshop/channels/[id]/agents/[agentId]/memories/index.get.ts +29 -0
  648. package/server/api/workshop/channels/[id]/agents/[agentId]/memories/index.post.ts +48 -0
  649. package/server/api/workshop/channels/[id]/agents/[agentId]/memories/search.post.ts +43 -0
  650. package/server/api/workshop/channels/[id]/agents/[agentId]/model.patch.ts +39 -0
  651. package/server/api/workshop/channels/[id]/agents/[agentId]/position.patch.ts +33 -0
  652. package/server/api/workshop/channels/[id]/agents/[agentId]/range.patch.ts +54 -0
  653. package/server/api/workshop/channels/[id]/agents/[agentId]/stop.post.ts +25 -0
  654. package/server/api/workshop/channels/[id]/agents/[agentId].delete.ts +23 -0
  655. package/server/api/workshop/channels/[id]/agents/[agentId].patch.ts +28 -0
  656. package/server/api/workshop/channels/[id]/agents/index.get.ts +27 -0
  657. package/server/api/workshop/channels/[id]/agents/index.post.ts +61 -0
  658. package/server/api/workshop/channels/[id]/events.get.ts +55 -0
  659. package/server/api/workshop/channels/[id]/index.get.ts +18 -0
  660. package/server/api/workshop/channels/[id]/index.patch.ts +30 -0
  661. package/server/api/workshop/channels/[id]/memories/[memoryId].delete.ts +29 -0
  662. package/server/api/workshop/channels/[id]/memories/index.get.ts +28 -0
  663. package/server/api/workshop/channels/[id]/memories/index.post.ts +42 -0
  664. package/server/api/workshop/channels/[id]/messages/index.get.ts +56 -0
  665. package/server/api/workshop/channels/[id]/messages/index.post.ts +75 -0
  666. package/server/api/workshop/channels/[id]/queue.get.ts +25 -0
  667. package/server/api/workshop/channels/[id]/tasks/index.get.ts +24 -0
  668. package/server/api/workshop/channels/[id]/tasks/index.post.ts +79 -0
  669. package/server/api/workshop/channels/[id]/terminals.get.ts +21 -0
  670. package/server/api/workshop/channels/[id].delete.ts +18 -0
  671. package/server/api/workshop/channels.get.ts +11 -0
  672. package/server/api/workshop/channels.post.ts +48 -0
  673. package/server/api/workshop/daq/[id]/bind.post.ts +19 -0
  674. package/server/api/workshop/daq/[id]/samples.get.ts +22 -0
  675. package/server/api/workshop/daq/[id]/test.post.ts +17 -0
  676. package/server/api/workshop/daq/[id].delete.ts +30 -0
  677. package/server/api/workshop/daq/[id].patch.ts +31 -0
  678. package/server/api/workshop/daq/alarms/[id]/ack.post.ts +15 -0
  679. package/server/api/workshop/daq/alarms.get.ts +16 -0
  680. package/server/api/workshop/daq/controller.post.ts +52 -0
  681. package/server/api/workshop/daq/index.get.ts +40 -0
  682. package/server/api/workshop/daq/index.post.ts +33 -0
  683. package/server/api/workshop/daq/infra/reconnect.post.ts +17 -0
  684. package/server/api/workshop/daq/infra.get.ts +11 -0
  685. package/server/api/workshop/daq/templates/[key].delete.ts +17 -0
  686. package/server/api/workshop/daq/templates/[key].patch.ts +18 -0
  687. package/server/api/workshop/daq/templates/index.post.ts +17 -0
  688. package/server/api/workshop/daq/test-driver.post.ts +23 -0
  689. package/server/api/workshop/dcw/[id]/bind.post.ts +17 -0
  690. package/server/api/workshop/dcw/[id]/param-ledger.get.ts +15 -0
  691. package/server/api/workshop/dcw/[id]/test.post.ts +15 -0
  692. package/server/api/workshop/dcw/[id]/write.post.ts +19 -0
  693. package/server/api/workshop/dcw/[id].delete.ts +30 -0
  694. package/server/api/workshop/dcw/[id].patch.ts +18 -0
  695. package/server/api/workshop/dcw/controller.post.ts +43 -0
  696. package/server/api/workshop/dcw/index.get.ts +25 -0
  697. package/server/api/workshop/dcw/index.post.ts +20 -0
  698. package/server/api/workshop/dcw/journal/index.get.ts +21 -0
  699. package/server/api/workshop/dcw/journal/node/[nodeId]/rollback.post.ts +22 -0
  700. package/server/api/workshop/dcw/line/query.get.ts +31 -0
  701. package/server/api/workshop/dcw/lines/[id]/start.post.ts +35 -0
  702. package/server/api/workshop/dcw/lines/[id]/stop.post.ts +34 -0
  703. package/server/api/workshop/dcw/lines/[id].delete.ts +35 -0
  704. package/server/api/workshop/dcw/lines/[id].patch.ts +15 -0
  705. package/server/api/workshop/dcw/lines/index.get.ts +14 -0
  706. package/server/api/workshop/dcw/lines/index.post.ts +31 -0
  707. package/server/api/workshop/dcw/optimizations/[id]/judge.post.ts +24 -0
  708. package/server/api/workshop/dcw/optimizations/[id]/rollback.post.ts +29 -0
  709. package/server/api/workshop/dcw/optimizations/[id]/series.get.ts +18 -0
  710. package/server/api/workshop/dcw/optimizations/[id].get.ts +17 -0
  711. package/server/api/workshop/dcw/optimizations/index.get.ts +23 -0
  712. package/server/api/workshop/dcw/products/[id].delete.ts +16 -0
  713. package/server/api/workshop/dcw/products/[id].patch.ts +17 -0
  714. package/server/api/workshop/dcw/products/index.post.ts +16 -0
  715. package/server/api/workshop/dcw/recipes/[id]/apply.post.ts +40 -0
  716. package/server/api/workshop/dcw/recipes/[id]/mark-good.post.ts +21 -0
  717. package/server/api/workshop/dcw/recipes/[id]/rollback-good.post.ts +19 -0
  718. package/server/api/workshop/dcw/recipes/[id].delete.ts +14 -0
  719. package/server/api/workshop/dcw/recipes/[id].patch.ts +16 -0
  720. package/server/api/workshop/dcw/recipes/index.get.ts +12 -0
  721. package/server/api/workshop/dcw/recipes/index.post.ts +15 -0
  722. package/server/api/workshop/dcw/runs/[id]/close.post.ts +15 -0
  723. package/server/api/workshop/dcw/runs/[id]/data.get.ts +15 -0
  724. package/server/api/workshop/dcw/runs/[id]/rollback.post.ts +20 -0
  725. package/server/api/workshop/dcw/runs/index.get.ts +11 -0
  726. package/server/api/workshop/dcw/templates/[key].delete.ts +14 -0
  727. package/server/api/workshop/dcw/templates/[key].patch.ts +16 -0
  728. package/server/api/workshop/dcw/templates/index.post.ts +15 -0
  729. package/server/api/workshop/dcw/test-driver.post.ts +16 -0
  730. package/server/api/workshop/device-twins/[id]/control.post.ts +21 -0
  731. package/server/api/workshop/device-twins/[id]/telemetry.post.ts +21 -0
  732. package/server/api/workshop/device-twins/[id].delete.ts +25 -0
  733. package/server/api/workshop/device-twins/[id].patch.ts +29 -0
  734. package/server/api/workshop/device-twins/index.get.ts +16 -0
  735. package/server/api/workshop/device-twins/index.post.ts +32 -0
  736. package/server/api/workshop/fs/dirs.get.ts +40 -0
  737. package/server/api/workshop/mailbox/all.get.ts +19 -0
  738. package/server/api/workshop/mailbox.get.ts +14 -0
  739. package/server/api/workshop/memories/maintenance.post.ts +15 -0
  740. package/server/api/workshop/ops-logs/index.get.ts +30 -0
  741. package/server/api/workshop/ops-logs/index.post.ts +39 -0
  742. package/server/api/workshop/runtime.get.ts +11 -0
  743. package/server/api/workshop/scene/layouts/[channelId].delete.ts +23 -0
  744. package/server/api/workshop/scene/layouts/[channelId].put.ts +31 -0
  745. package/server/api/workshop/scene/layouts.get.ts +13 -0
  746. package/server/api/workshop/tasks/[id]/cancel/index.post.ts +34 -0
  747. package/server/api/workshop/tasks/[id]/complete.post.ts +32 -0
  748. package/server/api/workshop/tasks/[id]/dispatch.post.ts +30 -0
  749. package/server/api/workshop/tasks/[id]/report.post.ts +38 -0
  750. package/server/api/workshop/tasks/[id]/retry.post.ts +33 -0
  751. package/server/api/workshop/tasks/[id].get.ts +32 -0
  752. package/server/api/workshop/tasks.get.ts +13 -0
  753. package/server/api/workshop/teams/[id]/deploy.post.ts +40 -0
  754. package/server/api/workshop/teams/[id]/members/[agentId].delete.ts +19 -0
  755. package/server/api/workshop/teams/[id]/members/index.get.ts +19 -0
  756. package/server/api/workshop/teams/[id]/members/index.post.ts +32 -0
  757. package/server/api/workshop/teams/[id].delete.ts +20 -0
  758. package/server/api/workshop/teams/[id].get.ts +19 -0
  759. package/server/api/workshop/teams/[id].patch.ts +32 -0
  760. package/server/api/workshop/teams/index.get.ts +13 -0
  761. package/server/api/workshop/teams/index.post.ts +27 -0
  762. package/server/api/workshop/users/me.get.ts +23 -0
  763. package/server/api/workshop/users/register.post.ts +33 -0
  764. package/server/api/workshop/workspaces/[id]/channel-templates/[tplId].post.ts +31 -0
  765. package/server/api/workshop/workspaces/[id]/channels/[channelId].delete.ts +15 -0
  766. package/server/api/workshop/workspaces/[id]/channels/[channelId].post.ts +15 -0
  767. package/server/api/workshop/workspaces/[id]/index.delete.ts +14 -0
  768. package/server/api/workshop/workspaces/index.get.ts +11 -0
  769. package/server/api/workshop/workspaces/index.post.ts +17 -0
  770. package/server/api/workshop/ws.ts +694 -0
  771. package/server/data/agent-node-bindings.json +554 -0
  772. package/server/data/daq-templates.json +16 -0
  773. package/server/data/daqs.json +2680 -0
  774. package/server/data/dcw-lines.json +919 -0
  775. package/server/data/dcw-products.json +835 -0
  776. package/server/data/dcw-recipes.json +1650 -0
  777. package/server/data/dcw-rollback.json +9339 -0
  778. package/server/data/dcw-runs.json +4633 -0
  779. package/server/data/dcw-templates.json +26 -0
  780. package/server/data/dcw-writes.json +9770 -0
  781. package/server/data/dcws.json +1736 -0
  782. package/server/data/device-twins.json +133 -0
  783. package/server/data/line-runs.json +152 -0
  784. package/server/data/scene-layouts.json +200 -0
  785. package/server/mcp/workshop-server.ts +510 -0
  786. package/server/middleware/request-log.ts +15 -0
  787. package/server/plugins/backup.ts +85 -0
  788. package/server/plugins/daq.ts +65 -0
  789. package/server/plugins/dev-stability-guard.ts +42 -0
  790. package/server/plugins/security.ts +29 -0
  791. package/server/plugins/system-config.ts +38 -0
  792. package/server/plugins/workshop.ts +145 -0
  793. package/server/repositories/user.repository.ts +391 -0
  794. package/server/schemas/user.schema.ts +67 -0
  795. package/server/services/system-config.ts +356 -0
  796. package/server/services/user.service.ts +186 -0
  797. package/server/services/workshop/agents/adapters/omp-rpc-client.ts +539 -0
  798. package/server/services/workshop/agents/adapters/to-a2a.ts +40 -0
  799. package/server/services/workshop/agents/agent-interface.ts +219 -0
  800. package/server/services/workshop/agents/claude-agent.ts +47 -0
  801. package/server/services/workshop/agents/factory.ts +24 -0
  802. package/server/services/workshop/agents/harness-process.ts +158 -0
  803. package/server/services/workshop/agents/harness-terminal.ts +545 -0
  804. package/server/services/workshop/agents/industrial-context.ts +222 -0
  805. package/server/services/workshop/agents/industrial-tools.ts +362 -0
  806. package/server/services/workshop/agents/mock-agent.ts +396 -0
  807. package/server/services/workshop/agents/node-bindings.repo.ts +165 -0
  808. package/server/services/workshop/agents/omp-agent.ts +1598 -0
  809. package/server/services/workshop/agents/tool-approvals.ts +174 -0
  810. package/server/services/workshop/assets/character-asset.repo.ts +120 -0
  811. package/server/services/workshop/assets/device-twin.repo.ts +236 -0
  812. package/server/services/workshop/daq/alarm-notify.ts +100 -0
  813. package/server/services/workshop/daq/bus/index.ts +46 -0
  814. package/server/services/workshop/daq/bus/inproc.adapter.ts +62 -0
  815. package/server/services/workshop/daq/bus/mqtt.adapter.ts +112 -0
  816. package/server/services/workshop/daq/bus/queue-port.ts +36 -0
  817. package/server/services/workshop/daq/daq-controller.ts +778 -0
  818. package/server/services/workshop/daq/daq-node.repo.ts +96 -0
  819. package/server/services/workshop/daq/daq-node.ts +247 -0
  820. package/server/services/workshop/daq/daq-runtime.ts +168 -0
  821. package/server/services/workshop/daq/daq-templates.ts +157 -0
  822. package/server/services/workshop/daq/drivers.ts +771 -0
  823. package/server/services/workshop/daq/host-bindings.ts +71 -0
  824. package/server/services/workshop/daq/host-ports.ts +64 -0
  825. package/server/services/workshop/daq/infra.ts +202 -0
  826. package/server/services/workshop/daq/storage/index.ts +96 -0
  827. package/server/services/workshop/daq/storage/sqlite.adapter.ts +205 -0
  828. package/server/services/workshop/daq/storage/timescale.adapter.ts +185 -0
  829. package/server/services/workshop/daq/storage/tsdb-port.ts +74 -0
  830. package/server/services/workshop/db/agent.repo.ts +105 -0
  831. package/server/services/workshop/db/channel-agent.repo.ts +119 -0
  832. package/server/services/workshop/db/channel-event.repo.ts +154 -0
  833. package/server/services/workshop/db/channel-template.repo.ts +113 -0
  834. package/server/services/workshop/db/channel.repo.ts +101 -0
  835. package/server/services/workshop/db/database.ts +934 -0
  836. package/server/services/workshop/db/memory.repo.ts +249 -0
  837. package/server/services/workshop/db/message.repo.ts +149 -0
  838. package/server/services/workshop/db/ops.repo.ts +323 -0
  839. package/server/services/workshop/db/schema.sql +143 -0
  840. package/server/services/workshop/db/subscription.repo.ts +62 -0
  841. package/server/services/workshop/db/task.repo.ts +175 -0
  842. package/server/services/workshop/db/team-member.repo.ts +70 -0
  843. package/server/services/workshop/db/team.repo.ts +109 -0
  844. package/server/services/workshop/db/user.repo.ts +100 -0
  845. package/server/services/workshop/dcw/dcw-controller.ts +841 -0
  846. package/server/services/workshop/dcw/dcw-line.repo.ts +86 -0
  847. package/server/services/workshop/dcw/dcw-node.repo.ts +89 -0
  848. package/server/services/workshop/dcw/dcw-node.ts +200 -0
  849. package/server/services/workshop/dcw/dcw-product.repo.ts +95 -0
  850. package/server/services/workshop/dcw/dcw-recipe.repo.ts +349 -0
  851. package/server/services/workshop/dcw/dcw-runtime.ts +82 -0
  852. package/server/services/workshop/dcw/dcw-templates.ts +138 -0
  853. package/server/services/workshop/dcw/drivers.ts +523 -0
  854. package/server/services/workshop/dcw/line-run.ts +101 -0
  855. package/server/services/workshop/dcw/recipe-rollback-manager.ts +702 -0
  856. package/server/services/workshop/dcw/recipe-rollback.repo.ts +197 -0
  857. package/server/services/workshop/logger.ts +58 -0
  858. package/server/services/workshop/ops/ops.ts +78 -0
  859. package/server/services/workshop/prompts/loader.ts +112 -0
  860. package/server/services/workshop/runtime/agent-runtime.ts +698 -0
  861. package/server/services/workshop/runtime/channel-runtime.ts +202 -0
  862. package/server/services/workshop/runtime/embedding-provider.ts +79 -0
  863. package/server/services/workshop/runtime/execution-mode.ts +215 -0
  864. package/server/services/workshop/runtime/mailbox.ts +148 -0
  865. package/server/services/workshop/runtime/manager.ts +2543 -0
  866. package/server/services/workshop/runtime/memory.ts +439 -0
  867. package/server/services/workshop/runtime/monitor.ts +194 -0
  868. package/server/services/workshop/runtime/scheduler-loop.ts +773 -0
  869. package/server/services/workshop/runtime/task-engine.ts +574 -0
  870. package/server/services/workshop/scene/scene-layout.repo.ts +112 -0
  871. package/server/services/workshop/scene-events.ts +63 -0
  872. package/server/services/workshop/types/a2a.ts +61 -0
  873. package/server/services/workshop/types/task.ts +85 -0
  874. package/server/types/user.ts +53 -0
  875. package/server/utils/approval-gate.ts +67 -0
  876. package/server/utils/auth.ts +13 -0
  877. package/server/utils/config.ts +40 -0
  878. package/server/utils/errors.ts +24 -0
  879. package/server/utils/response.ts +49 -0
  880. package/server/utils/validate.ts +19 -0
  881. package/shared/config/engine.d.mts +41 -0
  882. package/shared/config/engine.mjs +291 -0
  883. package/shared/config/home.d.mts +48 -0
  884. package/shared/config/home.mjs +146 -0
  885. package/shared/config/schema.json +30 -0
  886. package/shared/daq-protocol.ts +361 -0
  887. package/shared/dcw-protocol.ts +576 -0
  888. package/shared/terminal-protocol.ts +70 -0
  889. package/shared/town-anim.ts +56 -0
  890. package/shared/town-behavior.ts +136 -0
  891. package/shared/town-protocol.ts +110 -0
  892. package/shared/town-scene-math.ts +283 -0
  893. package/shared/workshop-protocol.ts +199 -0
  894. package/tsconfig.json +10 -0
  895. package/uno.config.ts +37 -0
@@ -0,0 +1,773 @@
1
+ /**
2
+ * SchedulerLoop — lead 常驻调度循环(统一调度核心)。
3
+ * 定时 tick + 事件唤醒(wake 去抖合并);每轮在 lead.execLock 串行化下:
4
+ * 收集快照 → lead.supervise 决策(未实现/抛错回退内置规则引擎)→ 逐条执行决策。
5
+ * 支持三种执行模式:goal(满意度判断)/ loop(循环重放)/ pipeline(流水线)。
6
+ * 权威契约见 docs/superpowers/plans/2026-08-13-agent-workshop-multi-agent.md 核心契约块 T5。
7
+ */
8
+ import { createLogger } from '../logger'
9
+ import { randomUUID } from 'node:crypto'
10
+ import { TERMINAL_TASK_STATES } from '../types/task'
11
+ import type { A2AMessage, ChannelMail } from '../types/a2a'
12
+ import type { SupervisionDecision, SupervisionSnapshot, ExecutionMode, AgentWorkspace } from '../agents/agent-interface'
13
+ import { AppError } from '../../../utils/errors'
14
+ import type { ChannelRuntime } from './channel-runtime'
15
+ import type { AgentRuntime } from './agent-runtime'
16
+ import {
17
+ extractTaskMode,
18
+ findModeTask,
19
+ isGoalSummaryArtifact,
20
+ LoopController,
21
+ type ModeConfig,
22
+ } from './execution-mode'
23
+
24
+ const log = createLogger('workshop.scheduler')
25
+
26
+ /** 调度快照注入的最近邮件条数(倒序;控制 supervise prompt 体量) */
27
+ const MAIL_SNAPSHOT_LIMIT = 20
28
+
29
+ /** 成员摘要(快照内;含队列上下文与实时进度,供 lead 最优调配与停滞识别) */
30
+ interface MemberView {
31
+ agentId: string
32
+ name: string
33
+ role: 'lead' | 'worker'
34
+ state: 'idle' | 'busy' | 'stopped'
35
+ /** 待执行队列长度(SUBMITTED/ASSIGNED;FIFO) */
36
+ queued: number
37
+ /** 执行中任务 id(空闲为 null) */
38
+ currentTaskId: string | null
39
+ /** 执行中任务标题(lead 观察 worker 在干什么,不必翻任务表) */
40
+ currentTaskTitle: string | null
41
+ /** 执行中任务进度 0-100(空闲/未上报为 null;lead 据此判断是否在推进) */
42
+ currentTaskProgress: number | null
43
+ /** 已完成任务数 */
44
+ completedCount: number
45
+ /** 忙碌但进度长期停滞(超 stallMs 未变)→ lead 应介入(notify/reassign/cancel) */
46
+ stalled: boolean
47
+ }
48
+
49
+ export interface SchedulerLoopOptions {
50
+ tickMs?: number
51
+ stallMs?: number
52
+ /** 调度快照邮件提供者(manager 注入;返回最新在前);未注入则快照 mail 为空 */
53
+ supervisionMail?: (limit: number) => ChannelMail[]
54
+ }
55
+
56
+ /** 空闲退避上限(指纹不变时 tick 间隔指数退避至此;事件 wake 立即恢复) */
57
+ const IDLE_TICK_CAP_MS = 8000
58
+
59
+ export class SchedulerLoop {
60
+ private readonly tickMs: number
61
+ private readonly stallMs: number
62
+ private readonly supervisionMail: ((limit: number) => ChannelMail[]) | null
63
+ /** supervise 节流:最小间隔与最近一次执行时刻/信号指纹(token 效率) */
64
+ private lastSuperviseAt = 0
65
+ private lastFingerprint = ''
66
+ private timer: NodeJS.Timeout | null = null
67
+ private started = false
68
+ private running = false
69
+ private pendingWake = false
70
+ private tick = 0
71
+ /** 已催办一次的 WORKING 任务(再次停滞 → cancel) */
72
+ private readonly notified = new Set<string>()
73
+ /** WORKING 任务最近一次 progress 与时间(停滞检测) */
74
+ private readonly lastProgress = new Map<string, { progress: number, at: number }>()
75
+ /** busy 成员执行中任务的进度基线(与 lastProgress 分离:busy 不重置——
76
+ * 独立检测"忙碌但进度长期不变"的停滞,喂给快照的 stalled 标记) */
77
+ private readonly progressSeen = new Map<string, { progress: number, at: number }>()
78
+ /** goal 父任务「全部子任务 COMPLETED」首见时刻(宽限后规则引擎兜底收口) */
79
+ private readonly goalAllDoneAt = new Map<string, number>()
80
+ /** goal 收口宽限窗(ms):给 lead 充分判定机会,超时平台兜底完成 */
81
+ private readonly goalGraceMs = 45_000
82
+ /** 成员空闲起始时间(最久空闲 worker 排序) */
83
+ private readonly idleSince = new Map<string, number>()
84
+ /** 当前活跃的执行模式(null = 默认无模式) */
85
+ private activeMode: ExecutionMode | null = null
86
+ private activeModeConfig: ModeConfig = {}
87
+ /** loop 模式控制器 */
88
+ private loopController: LoopController | null = null
89
+ /** 已通知 loop 控制器的完成任务,避免每轮 tick 重复计数 */
90
+ private readonly loopCompletedTaskIds = new Set<string>()
91
+ /** 调度器启动时刻(loop 完成识别基线;防进程重启后重放重启前的 loop 主任务) */
92
+ private readonly bootAt = Date.now()
93
+ /** loop 模式下重新提交任务的回调 */
94
+ private onLoopResubmit: ((title: string, description: string) => void) | null = null
95
+
96
+ constructor(
97
+ private readonly channelRuntime: ChannelRuntime,
98
+ private readonly lead: AgentRuntime,
99
+ options: SchedulerLoopOptions = {},
100
+ ) {
101
+ this.tickMs = options.tickMs ?? 1000
102
+ this.stallMs = options.stallMs ?? 300000
103
+ this.supervisionMail = options.supervisionMail ?? null
104
+ }
105
+
106
+ /** 空闲退避:快照指纹连续不变的轮数(决定下次 tick 间隔) */
107
+ private idleStreak = 0
108
+ /** 上一轮快照指纹(空闲判定) */
109
+ private lastRoundFingerprint = ''
110
+
111
+ /** 启动调度(自重排 setTimeout:tick 间隔可按空闲状态退避) */
112
+ start(): void {
113
+ if (this.started) return
114
+ this.started = true
115
+ this.scheduleNext(this.tickMs)
116
+ }
117
+
118
+ /** 事件唤醒(任务状态变化即调):空闲退避中的循环立即恢复快节奏 */
119
+ wake(): void {
120
+ if (!this.started) return
121
+ if (this.running) {
122
+ this.pendingWake = true
123
+ return
124
+ }
125
+ this.clearTimer()
126
+ void this.runRound()
127
+ }
128
+
129
+ private clearTimer(): void {
130
+ if (this.timer) {
131
+ clearTimeout(this.timer)
132
+ this.timer = null
133
+ }
134
+ }
135
+
136
+ private scheduleNext(delayMs: number): void {
137
+ this.clearTimer()
138
+ this.timer = setTimeout(() => {
139
+ this.timer = null
140
+ this.wake()
141
+ }, delayMs)
142
+ this.timer.unref?.()
143
+ }
144
+
145
+ stop(): void {
146
+ this.started = false
147
+ this.clearTimer()
148
+ if (this.loopController) {
149
+ this.loopController.stop()
150
+ this.loopController = null
151
+ }
152
+ this.loopCompletedTaskIds.clear()
153
+ }
154
+
155
+ /** 设置 loop 模式重新提交回调(manager 注入 submitChannelTask) */
156
+ setLoopResubmitCallback(fn: (title: string, description: string) => void): void {
157
+ this.onLoopResubmit = fn
158
+ }
159
+
160
+ // ===== 内部 =====
161
+
162
+ private async runRound(): Promise<void> {
163
+ this.running = true
164
+ try {
165
+ await this.lead.withExecLock(() => this.tickRound())
166
+ }
167
+ catch (err) {
168
+ log.error(`[SchedulerLoop:${this.lead.agentId}] 一轮调度失败:`, err)
169
+ }
170
+ finally {
171
+ this.running = false
172
+ if (this.started) {
173
+ if (this.pendingWake) {
174
+ // 事件驱动:执行期间有新信号 → 立即下一轮(节奏不退避)
175
+ this.pendingWake = false
176
+ void this.runRound()
177
+ }
178
+ else {
179
+ // 定时驱动:空闲退避(指纹不变 → 间隔翻倍至 8s 上限;有事件 wake() 即刻打断)
180
+ this.scheduleNext(Math.min(this.tickMs * 2 ** this.idleStreak, IDLE_TICK_CAP_MS))
181
+ }
182
+ }
183
+ }
184
+ }
185
+
186
+ private async tickRound(): Promise<void> {
187
+ this.tick += 1
188
+ const snapshot = this.collectSnapshot()
189
+ // 状态 Map 生命周期修剪:终态/已删任务的条目随轮清理(长会话内存有界)。
190
+ // progressSeen 全程只增不减;notified/lastProgress/goalAllDoneAt/loopCompletedTaskIds
191
+ // 仅部分路径清理 —— 统一对当前任务集收敛,任务重入(FAILED→ASSIGNED)时自然重建。
192
+ const liveIds = new Set(snapshot.tasks.map(t => t.id))
193
+ for (const map of [this.progressSeen, this.lastProgress, this.goalAllDoneAt]) {
194
+ for (const key of map.keys()) {
195
+ if (!liveIds.has(key)) map.delete(key)
196
+ }
197
+ }
198
+ for (const key of this.notified) {
199
+ if (!liveIds.has(key)) this.notified.delete(key)
200
+ }
201
+ for (const key of this.loopCompletedTaskIds) {
202
+ if (!liveIds.has(key)) this.loopCompletedTaskIds.delete(key)
203
+ }
204
+ // 空闲判定指纹(与 supervise 节流同源):任务/成员/邮件信号均未变 → 退避
205
+ const fp = this.superviseFingerprint(snapshot)
206
+ if (fp === this.lastRoundFingerprint) this.idleStreak++
207
+ else {
208
+ this.idleStreak = 0
209
+ this.lastRoundFingerprint = fp
210
+ }
211
+
212
+ // 检测当前活跃的执行模式
213
+ const modeTask = findModeTask(snapshot.tasks, this.lead.agentId)
214
+ if (modeTask) {
215
+ this.activeMode = modeTask.mode
216
+ this.activeModeConfig = modeTask.config
217
+ }
218
+
219
+ // loop 模式:检测主任务完成 → 触发循环控制器
220
+ this.checkLoopCompletion(snapshot)
221
+
222
+ const decisions = await this.decide(snapshot)
223
+ for (const decision of decisions) {
224
+ try {
225
+ this.execute(decision)
226
+ }
227
+ catch (err) {
228
+ log.error(`[SchedulerLoop:${this.lead.agentId}] 执行决策失败:`, decision, err)
229
+ }
230
+ }
231
+ }
232
+
233
+ /**
234
+ * supervise 智能节流(token 效率,纯指纹驱动):
235
+ * - 信号指纹 = 任务状态集合 · 成员状态/队列 · 最新邮件 id,不含 progress 渐变
236
+ * (worker 进度上报不值得唤醒 lead;状态翻转/新邮件才是需要行动的信号);
237
+ * - 指纹无变化 → 跳过 LLM supervise,只跑规则引擎(停滞检测/兜底派发照常);
238
+ * - 指纹变化 → 立即 supervise(mock 剧本的秒级状态机与 LLM 决策跟进都不被拖延);
239
+ * - 首轮必跑。
240
+ */
241
+ private superviseFingerprint(snapshot: SupervisionSnapshot): string {
242
+ const tasks = snapshot.tasks
243
+ .map(t => `${t.id}:${t.state}`)
244
+ .sort()
245
+ .join('|')
246
+ const members = snapshot.members
247
+ .map(m => `${m.agentId}:${m.state}:${m.queued ?? 0}`)
248
+ .sort()
249
+ .join('|')
250
+ const mailTop = snapshot.mail?.[0]?.messageId ?? ''
251
+ return `${tasks}#${members}#${mailTop}`
252
+ }
253
+
254
+ private shouldSupervise(snapshot: SupervisionSnapshot): boolean {
255
+ if (this.lead.supervise === null) return false // 无 LLM 决策能力,规则引擎自走
256
+ if (this.lastSuperviseAt === 0) return true // 首轮
257
+ // 收尾挂起例外:父任务 WAITING 且子任务全部终态(有完成交付)——指纹虽稳定,
258
+ // lead 也必须获得监督回合做目标判定收尾(否则作废尝试会永久阻塞 goal 闭环)。
259
+ // 30s 冷却:LLM 反复不收尾时不会每 tick 消耗回合
260
+ if (this.hasCloseableParent(snapshot)) {
261
+ if (Date.now() - this.lastCloseOutAt >= 30_000) {
262
+ this.lastCloseOutAt = Date.now()
263
+ return true
264
+ }
265
+ return false
266
+ }
267
+ return this.superviseFingerprint(snapshot) !== this.lastFingerprint
268
+ }
269
+
270
+ private lastCloseOutAt = 0
271
+
272
+ /** 存在"子任务全部终态且至少一个完成交付"的 WAITING 父任务(待 lead 判定收尾) */
273
+ private hasCloseableParent(snapshot: SupervisionSnapshot): boolean {
274
+ return snapshot.tasks.some((t) => {
275
+ if (t.state !== 'WAITING') return false
276
+ const children = snapshot.tasks.filter(c => c.parentId === t.id)
277
+ if (children.length === 0) return false
278
+ return children.every(c => TERMINAL_TASK_STATES[c.state] === true)
279
+ && children.some(c => c.state === 'COMPLETED')
280
+ })
281
+ }
282
+
283
+ /**
284
+ * 决策:lead.supervise 优先(真实 harness 的 LLM 调度);
285
+ * supervise 未实现/抛错 → 内置规则引擎;
286
+ * supervise 返回空但有可调度任务且无任何进展(如 LLM 拒绝/漏看)→ 规则引擎兜底补齐,
287
+ * 保证系统不因单轮 LLM 决策失败而停滞(harness 无关的安全网)。
288
+ * 节流:指纹无变化 → 跳过 LLM(本轮仅规则引擎)。
289
+ */
290
+ private async decide(snapshot: SupervisionSnapshot): Promise<SupervisionDecision[]> {
291
+ try {
292
+ if (!this.shouldSupervise(snapshot)) return this.ruleEngine(snapshot)
293
+ this.lastSuperviseAt = Date.now()
294
+ this.lastFingerprint = this.superviseFingerprint(snapshot)
295
+ const decisions = await this.lead.supervise(snapshot)
296
+ if (decisions === null) return this.ruleEngine(snapshot)
297
+ if (decisions.length > 0) return decisions
298
+ // 空决策 + 规则引擎发现可行动作 → 兜底(LLM 优先,规则保底推进)
299
+ const fallback = this.ruleEngine(snapshot)
300
+ return fallback.length > 0
301
+ ? fallback
302
+ : decisions
303
+ }
304
+ catch (err) {
305
+ log.error(`[SchedulerLoop:${this.lead.agentId}] lead supervise 抛错,回退规则引擎:`, err)
306
+ return this.ruleEngine(snapshot)
307
+ }
308
+ }
309
+
310
+ /** 收集快照:全 channel 任务 + 成员状态与队列视图(含未装配成员,标 idle)+ pendingChildren */
311
+ private collectSnapshot(): SupervisionSnapshot {
312
+ const now = Date.now()
313
+ // lite 快照:元数据投影,免每 tick 对全部任务做 artifacts/history JSON 大列解析
314
+ // (调度决策/规则引擎仅消费状态/进度/标题/描述;LLM 交付预览降级,状态信息仍完整)
315
+ const tasks = this.lead.taskEngine.listLite(this.channelRuntime.channelId)
316
+ // 已装配成员的实时状态
317
+ const wired = new Map(this.channelRuntime.getAgents().map(a => [a.agentId, a.getState()]))
318
+ // channel 全部 enabled 成员(含未装配懒加载成员 → idle,lead 可据此 dispatch);
319
+ // 队列视图来自 tasks 表(未装配成员的排队任务同样可见)
320
+ // 队列视图批量化:一次 list(channel) 聚合全部成员(原每成员一次查询)
321
+ const views = this.lead.taskEngine.queueViewsOfLite(this.channelRuntime.channelId)
322
+ const emptyView = { queued: [] as typeof tasks, current: undefined, completed: [] as typeof tasks }
323
+ const members: MemberView[] = this.channelRuntime.listChannelAgents().map((m) => {
324
+ const view = views.get(m.agentId) ?? emptyView
325
+ const current = view.current
326
+ const progress = current?.progress ?? null
327
+ // 进度基线更新:progress 变化或首次记录时刷新时间;不变则保留起始时刻
328
+ if (current && progress != null) {
329
+ const seen = this.progressSeen.get(current.id)
330
+ if (!seen || seen.progress !== progress) {
331
+ this.progressSeen.set(current.id, { progress, at: now })
332
+ }
333
+ }
334
+ // 停滞识别:执行中任务长期无进度变化(i.e. progress 与上次观测相同且超 stallMs)。
335
+ // busy 状态不再无限豁免 —— 一个进程活着但 LLM 回合内卡死、progress 从不变化的
336
+ // worker 是最危险场景(worker 自认为在跑,lead 无从知晓),必须给 lead 明确信号。
337
+ const seen = current ? this.progressSeen.get(current.id) : undefined
338
+ const stalled = current != null
339
+ && seen != null
340
+ && seen.progress === progress
341
+ && now - seen.at > this.stallMs
342
+ return {
343
+ agentId: m.agentId,
344
+ name: m.name,
345
+ role: m.role,
346
+ state: wired.get(m.agentId) ?? 'idle',
347
+ queued: view.queued.length,
348
+ currentTaskId: current?.id ?? null,
349
+ currentTaskTitle: current?.title ?? null,
350
+ currentTaskProgress: progress,
351
+ completedCount: view.completed.length,
352
+ stalled,
353
+ }
354
+ })
355
+ const pendingChildren: Record<string, number> = {}
356
+ for (const task of tasks) {
357
+ if (!task.parentId) continue
358
+ if (TERMINAL_TASK_STATES[task.state]) continue
359
+ pendingChildren[task.parentId] = (pendingChildren[task.parentId] ?? 0) + 1
360
+ }
361
+ return {
362
+ tick: this.tick,
363
+ now,
364
+ tasks,
365
+ members,
366
+ pendingChildren,
367
+ // 最近邮件(最新在前):lead 观察 worker 间通信/回执,判断结果是否已产出
368
+ mail: this.supervisionMail ? this.supervisionMail(MAIL_SNAPSHOT_LIMIT) : [],
369
+ }
370
+ }
371
+
372
+ /** 内置规则引擎兜底(harness 无关) */
373
+ private ruleEngine(snapshot: SupervisionSnapshot): SupervisionDecision[] {
374
+ const decisions: SupervisionDecision[] = []
375
+ const { tasks, members, now } = snapshot
376
+ this.refreshIdle(members, now)
377
+ // parent → children 一次构建(原每任务 some/filter 全量扫描,O(N²) → O(N))
378
+ const childrenByParent = new Map<string, typeof tasks>()
379
+ for (const t of tasks) {
380
+ if (!t.parentId) continue
381
+ const arr = childrenByParent.get(t.parentId)
382
+ if (arr) arr.push(t)
383
+ else childrenByParent.set(t.parentId, [t])
384
+ }
385
+ const childrenOf = (id: string): typeof tasks => childrenByParent.get(id) ?? []
386
+ // 本轮可用空闲 worker 池:dispatch/reassign 消费后即从池中移除,
387
+ // 保证一轮内不会把多个任务重复分给同一个"看似空闲"的 worker(其状态尚未翻 busy)。
388
+ const pool = members.filter(m => m.role === 'worker' && m.state === 'idle')
389
+
390
+ // 任务按 createdAt ASC 迭代(list 顺序)= 外部提交 FIFO:先提交先分解先分发。
391
+ for (const task of tasks) {
392
+ // SUBMITTED or WORKING 且 assignee=lead 且无子任务 → dispatch 给最优空闲 worker
393
+ const hasChildren = childrenOf(task.id).length > 0
394
+ if ((task.state === 'SUBMITTED' || task.state === 'WORKING')
395
+ && task.assigneeId === this.lead.agentId
396
+ && !hasChildren) {
397
+ const worker = this.pickWorker(pool, now)
398
+ if (worker) {
399
+ decisions.push({
400
+ kind: 'dispatch',
401
+ parentTaskId: task.id,
402
+ assigneeId: worker.agentId,
403
+ title: task.title,
404
+ description: task.description,
405
+ })
406
+ }
407
+ }
408
+ // FAILED 且 retryCount<3:优先换人重试;仅剩原 assignee 空闲(如单 worker channel)
409
+ // → 由原 assignee 重试(reassign 到自己,走 FAILED→ASSIGNED 恢复);无人可用 → cancel(允许终结)
410
+ if (task.state === 'FAILED') {
411
+ if (task.retryCount < 3) {
412
+ const other = this.pickWorker(pool, now, task.assigneeId)
413
+ if (other) {
414
+ decisions.push({ kind: 'reassign', taskId: task.id, toAgentId: other.agentId })
415
+ }
416
+ else {
417
+ const same = this.pickWorker(pool, now)
418
+ if (same && same.agentId === task.assigneeId) {
419
+ decisions.push({ kind: 'reassign', taskId: task.id, toAgentId: same.agentId })
420
+ }
421
+ else {
422
+ decisions.push({ kind: 'cancel', taskId: task.id })
423
+ }
424
+ }
425
+ }
426
+ else {
427
+ decisions.push({ kind: 'cancel', taskId: task.id })
428
+ }
429
+ }
430
+ }
431
+
432
+ // WORKING 停滞检测:progress 停滞超过 stallMs → notify 催一次;再超时 → cancel。
433
+ // 活跃度感知:assignee 正 busy(执行中,含多轮协作/等待回执的长任务)不算"被遗弃"——
434
+ // 看门狗不回收 busy(取消忙碌中的回合是破坏性的)。
435
+ // 但 busy 且 progress 长期不变(progressSeen 基线)代表"在跑但无产出信号",
436
+ // 用 progressSeen 独立追踪:给 lead 发一次 notify 提醒介入(可见性修复:杜绝
437
+ // worker 自己觉得在跑、lead 却毫无感知)。是否 cancel 由 lead(supervise)判断,
438
+ // 规则引擎对 busy 不强制取消 —— 只留可见信号,不做破坏性动作。
439
+ const assigneeState = new Map(this.channelRuntime.getAgents().map(a => [a.agentId, a.getState()]))
440
+ for (const task of tasks) {
441
+ if (task.state !== 'WORKING') continue
442
+ if (assigneeState.get(task.assigneeId) === 'busy') {
443
+ // busy 且 progress 长期不变:催一次 lead 介入(notify 到 assignee 本人,请其推进/汇报);
444
+ // 尚未到基准时间或 progress 已变 → 刷新基线
445
+ const seen = this.progressSeen.get(task.id)
446
+ if (seen && seen.progress === task.progress && now - seen.at > this.stallMs) {
447
+ if (!this.notified.has(task.id)) {
448
+ this.notified.add(task.id)
449
+ decisions.push({
450
+ kind: 'notify',
451
+ toAgentId: task.assigneeId,
452
+ parts: [{ text: `任务「${task.title}」进度 ${task.progress}% 已 ${Math.round((now - seen.at) / 1000)}s 未变化,请确认是否仍在推进;若卡住请说明阻塞并请求协助` }],
453
+ })
454
+ }
455
+ // 已催过一次仍无变化:不重复催(避免每 tick 打扰),把最终裁决交给 lead
456
+ }
457
+ else {
458
+ this.notified.delete(task.id)
459
+ this.lastProgress.set(task.id, { progress: task.progress, at: now })
460
+ }
461
+ continue
462
+ }
463
+ const prev = this.lastProgress.get(task.id)
464
+ if (!prev || prev.progress !== task.progress) {
465
+ this.lastProgress.set(task.id, { progress: task.progress, at: now })
466
+ continue
467
+ }
468
+ if (now - prev.at <= this.stallMs) continue
469
+ if (!this.notified.has(task.id)) {
470
+ this.notified.add(task.id)
471
+ this.lastProgress.set(task.id, { progress: task.progress, at: now })
472
+ decisions.push({
473
+ kind: 'notify',
474
+ toAgentId: task.assigneeId,
475
+ parts: [{ text: `任务「${task.title}」停滞超过 ${this.stallMs}ms,请推进` }],
476
+ })
477
+ }
478
+ else {
479
+ this.notified.delete(task.id)
480
+ this.lastProgress.delete(task.id)
481
+ decisions.push({ kind: 'cancel', taskId: task.id })
482
+ }
483
+ }
484
+
485
+ // 子任务全完成且父任务(WAITING/WORKING)→ complete 父
486
+ for (const task of tasks) {
487
+ const children = childrenOf(task.id)
488
+ if (children.length === 0) continue
489
+ if (task.state === 'COMPLETED' || task.state === 'FAILED' || task.state === 'CANCELED') continue
490
+ const allDone = children.every(c => c.state === 'COMPLETED')
491
+ // goal/pipeline 父任务的完成判定属于 lead 模式剧本(goal 需满意度判定、
492
+ // pipeline 需全部阶段收敛),规则引擎不越权提前收口;loop 与无模式照旧兜底
493
+ const modeInfo = extractTaskMode(task)
494
+ if (modeInfo && (modeInfo.mode === 'goal' || modeInfo.mode === 'pipeline')) {
495
+ // goal 收口保活:lead 判定回合可能以纯文本收尾(未调用 complete_task),之后
496
+ // 状态不再变化 → 监督回合被指纹节流 → goal 永挂 WORKING 直至看门狗误取消。
497
+ // 全部子任务 COMPLETED 持续超过宽限窗(45s,lead 仍有充分判定机会)后由
498
+ // 规则引擎兜底收口;taskEngine.complete 内建 goal-summary 合成,标志必然落盘。
499
+ if (modeInfo.mode !== 'goal') continue
500
+ if (!allDone || (task.state !== 'WAITING' && task.state !== 'WORKING')) {
501
+ this.goalAllDoneAt.delete(task.id)
502
+ continue
503
+ }
504
+ const since = this.goalAllDoneAt.get(task.id)
505
+ if (since === undefined) {
506
+ this.goalAllDoneAt.set(task.id, now)
507
+ }
508
+ else if (now - since >= this.goalGraceMs) {
509
+ this.goalAllDoneAt.delete(task.id)
510
+ decisions.push({ kind: 'complete', taskId: task.id })
511
+ }
512
+ continue
513
+ }
514
+ if (allDone && (task.state === 'WAITING' || task.state === 'WORKING')) {
515
+ decisions.push({ kind: 'complete', taskId: task.id })
516
+ }
517
+ // 部分成功收口(防父任务永挂):全部子任务已终态,但存在失败/取消且至少一个
518
+ // COMPLETED 交付 —— 父任务不应 CANCEL(有成果),也不应无限 WAITING。
519
+ // 以"已有成果"为完成条件收口父任务(lead 汇总已产出部分,缺的口子明确可见),
520
+ // 否则父任务在子任务混合终态时永久卡死,lead 无从得知去补派。
521
+ else if (
522
+ (task.state === 'WAITING' || task.state === 'WORKING')
523
+ && children.every(c => TERMINAL_TASK_STATES[c.state] === true)
524
+ && children.some(c => c.state === 'COMPLETED')
525
+ && !children.every(c => c.state === 'COMPLETED')
526
+ ) {
527
+ decisions.push({ kind: 'complete', taskId: task.id })
528
+ }
529
+ }
530
+
531
+ // 父任务终结:子任务全部终态且存在不可重试的 FAILED/CANCELED
532
+ // → 父任务无法交付 → cancel 父任务(避免 WAITING 永挂;lead 可重新提交)。
533
+ // 已有 COMPLETED 交付的父任务不自动取消——作废尝试(FAILED/CANCELED)不阻塞,
534
+ // 收尾判定属于 lead(goal 模式按目标达成度而非子任务簿记收尾)
535
+ for (const task of tasks) {
536
+ const children = childrenOf(task.id)
537
+ if (children.length === 0) continue
538
+ if (task.state !== 'WAITING' && task.state !== 'WORKING') continue
539
+ const allTerminal = children.every(c => TERMINAL_TASK_STATES[c.state] === true)
540
+ const anyUnsuccessful = children.some(c => c.state !== 'COMPLETED')
541
+ const hasRetryableFailure = children.some(c => c.state === 'FAILED' && c.retryCount < 3)
542
+ const hasCompletedDeliverable = children.some(c => c.state === 'COMPLETED')
543
+ if (allTerminal && anyUnsuccessful && !hasRetryableFailure && !hasCompletedDeliverable) {
544
+ decisions.push({ kind: 'cancel', taskId: task.id })
545
+ }
546
+ }
547
+
548
+ return decisions
549
+ }
550
+
551
+ /** 执行单条决策(身份=lead,经 TaskEngine 与 ChannelRuntime) */
552
+ private execute(decision: SupervisionDecision): void {
553
+ switch (decision.kind) {
554
+ case 'dispatch': {
555
+ if (!decision.parentTaskId) {
556
+ throw new AppError(400, 'INVALID_DECISION', 'dispatch 决策缺少 parentTaskId')
557
+ }
558
+ // HITL 竞态守卫:快照后成员可能已被用户/lead 移除,目标不存在则跳过本轮
559
+ // (任务保持 SUBMITTED/WORKING,下一轮快照重新决策;避免派发给幽灵成员)
560
+ // listChannelAgents 仅返回 enabled=1 成员,存在即可用
561
+ const target = this.channelRuntime.listChannelAgents().find(a => a.agentId === decision.assigneeId)
562
+ if (!target) {
563
+ log.warn(`[SchedulerLoop:${this.lead.agentId}] dispatch 目标成员已不存在/禁用,跳过: ${decision.assigneeId}`)
564
+ break
565
+ }
566
+ const parent = this.lead.taskEngine.get(decision.parentTaskId)
567
+ if (!parent) throw new AppError(404, 'NOT_FOUND', `父任务不存在: ${decision.parentTaskId}`)
568
+ // lead 自动接取:SUBMITTED → WORKING(§2.2 状态机,dispatch 需父任务处于 WORKING/WAITING)
569
+ if (parent.state === 'SUBMITTED') {
570
+ this.lead.taskEngine.transition(parent.id, 'WORKING', this.lead.agentId)
571
+ }
572
+ this.lead.taskEngine.dispatch(parent, {
573
+ assigneeId: decision.assigneeId,
574
+ title: decision.title,
575
+ description: decision.description,
576
+ parts: decision.parts,
577
+ })
578
+ this.wakeAgent(decision.assigneeId)
579
+ break
580
+ }
581
+ case 'reassign': {
582
+ // HITL 竞态守卫:目标成员被移除/禁用时跳过重派(任务保持 FAILED,留待 lead/用户重试)
583
+ // listChannelAgents 仅返回 enabled=1 成员,存在即可用
584
+ const target = this.channelRuntime.listChannelAgents().find(a => a.agentId === decision.toAgentId)
585
+ if (!target) {
586
+ log.warn(`[SchedulerLoop:${this.lead.agentId}] reassign 目标成员已不存在/禁用,跳过: ${decision.toAgentId}`)
587
+ break
588
+ }
589
+ this.lead.taskEngine.reassign(decision.taskId, decision.toAgentId)
590
+ this.wakeAgent(decision.toAgentId)
591
+ break
592
+ }
593
+ case 'cancel': {
594
+ const task = this.lead.taskEngine.get(decision.taskId)
595
+ this.lead.taskEngine.cancel(decision.taskId, this.lead.agentId)
596
+ // lead 终态同步:经调度器判定取消同样不经 processMessage,重广播队列上下文
597
+ this.lead.refreshStatus()
598
+ if (task) {
599
+ const assignee = this.channelRuntime.getAgents().find(a => a.agentId === task.assigneeId)
600
+ if (assignee && assignee.getState() === 'busy') assignee.abortCurrent()
601
+ }
602
+ break
603
+ }
604
+ case 'complete': {
605
+ // 幂等守卫:LLM lead 可能对已终态任务重复 complete(快照滞后/重复决策)——
606
+ // 静默跳过而非报错,避免调度噪音(正确性不受影响:终态即目标状态)
607
+ const existing = this.lead.taskEngine.get(decision.taskId)
608
+ if (existing && ['COMPLETED', 'CANCELED', 'FAILED'].includes(existing.state)) {
609
+ break
610
+ }
611
+ const completed = this.lead.taskEngine.complete(decision.taskId, decision.artifacts)
612
+ // lead 状态同步:complete 由调度器直接收口(不经 processMessage),终态迁移后
613
+ // 重广播 lead 队列上下文(current→null/completed+1),前端实时反映 lead 判定完成
614
+ this.lead.refreshStatus()
615
+ // 汇总成果走统一事件流(与 harness 事件同构,monitor/WS 可见)
616
+ for (const artifact of decision.artifacts ?? []) {
617
+ this.lead.emitExternal({ kind: 'artifact', artifact }, this.lead.agentId)
618
+ }
619
+ // goal 保底合成产物(lead 未自带总结时 taskEngine 追加)同样广播
620
+ const knownArtifacts = new Set((decision.artifacts ?? []).map(a => a.artifactId))
621
+ for (const artifact of completed.artifacts) {
622
+ if (isGoalSummaryArtifact(artifact) && !knownArtifacts.has(artifact.artifactId)) {
623
+ this.lead.emitExternal({ kind: 'artifact', artifact }, this.lead.agentId)
624
+ }
625
+ }
626
+ // lead 终态记忆沉淀:调度器直接收口不经过 processMessage,此处补齐 harvest(异常不阻塞调度)
627
+ void this.lead.recordTaskMemory(completed).catch(() => {})
628
+ if (completed.parentId) {
629
+ this.lead.taskEngine.onChildCompleted(completed)
630
+ const parent = this.lead.taskEngine.get(completed.parentId)
631
+ if (parent) this.wakeAgent(parent.assigneeId)
632
+ }
633
+ break
634
+ }
635
+ case 'notify': {
636
+ const message: A2AMessage = {
637
+ messageId: randomUUID(),
638
+ contextId: this.channelRuntime.channelId,
639
+ role: 'ROLE_AGENT',
640
+ parts: decision.parts,
641
+ metadata: {
642
+ 'x-aw-target-agent': decision.toAgentId,
643
+ 'x-aw-from-agent': this.lead.agentId,
644
+ },
645
+ }
646
+ this.channelRuntime.route(message)
647
+ break
648
+ }
649
+ // 团队成员管理决策(lead 自主扩容/调参/裁撤;经 AgentWorkspace 与工具桥同源路径)。
650
+ // fire-and-forget:成员落库即刻对下一轮快照可见,dispatch 在后续 tick 自然衔接。
651
+ case 'spawn_agent': {
652
+ const ws: AgentWorkspace = this.lead.workspace
653
+ void ws.createTeamMember({
654
+ name: decision.name,
655
+ harness: decision.harness,
656
+ config: decision.config,
657
+ templateId: decision.templateId,
658
+ reason: decision.reason,
659
+ }).catch((err) => {
660
+ log.error(`[SchedulerLoop:${this.lead.agentId}] spawn_agent 决策执行失败:`, err)
661
+ })
662
+ break
663
+ }
664
+ case 'update_agent': {
665
+ const ws: AgentWorkspace = this.lead.workspace
666
+ void ws.updateTeamMember(decision.agentId, {
667
+ name: decision.name,
668
+ config: decision.config,
669
+ enabled: decision.enabled === undefined ? undefined : (decision.enabled ? 1 : 0),
670
+ reason: decision.reason,
671
+ }).catch((err) => {
672
+ log.error(`[SchedulerLoop:${this.lead.agentId}] update_agent 决策执行失败:`, err)
673
+ })
674
+ break
675
+ }
676
+ case 'remove_agent': {
677
+ const ws: AgentWorkspace = this.lead.workspace
678
+ void ws.removeTeamMember(decision.agentId, decision.reason).catch((err) => {
679
+ log.error(`[SchedulerLoop:${this.lead.agentId}] remove_agent 决策执行失败:`, err)
680
+ })
681
+ break
682
+ }
683
+ }
684
+ }
685
+
686
+ private wakeAgent(agentId: string): void {
687
+ this.channelRuntime.wakeAgent(agentId)
688
+ }
689
+
690
+ private refreshIdle(members: SupervisionSnapshot['members'], now: number): void {
691
+ const liveIds = new Set(members.map(m => m.agentId))
692
+ // 修剪已删除成员的残留条目(成员删除时正 idle → 不在 liveIds,不清会永久残留)
693
+ for (const id of this.idleSince.keys()) {
694
+ if (!liveIds.has(id)) this.idleSince.delete(id)
695
+ }
696
+ for (const m of members) {
697
+ if (m.state === 'idle') {
698
+ if (!this.idleSince.has(m.agentId)) this.idleSince.set(m.agentId, now)
699
+ }
700
+ else {
701
+ this.idleSince.delete(m.agentId)
702
+ }
703
+ }
704
+ }
705
+
706
+ /**
707
+ * 从本轮空闲池选最优 worker 并消费(选中即移出,一轮不重复用):
708
+ * 队列最短优先(负载均衡),空闲最久次之(FIFO 兜底)。
709
+ */
710
+ private pickWorker(pool: SupervisionSnapshot['members'], now: number, exclude?: string) {
711
+ const idx = pool.findIndex(w => w.agentId !== exclude)
712
+ if (idx < 0) return undefined
713
+ let best = idx
714
+ for (let i = idx + 1; i < pool.length; i++) {
715
+ const a = pool[i]!
716
+ const b = pool[best]!
717
+ const byQueue = (a.queued ?? 0) - (b.queued ?? 0)
718
+ const byIdle = (this.idleSince.get(a.agentId) ?? now) - (this.idleSince.get(b.agentId) ?? now)
719
+ if (byQueue < 0 || (byQueue === 0 && byIdle < 0)) best = i
720
+ }
721
+ return pool.splice(best, 1)[0]
722
+ }
723
+
724
+ /** loop 模式:检测主任务完成 → 启动循环控制器重放 */
725
+ private checkLoopCompletion(snapshot: SupervisionSnapshot): void {
726
+ if (this.activeMode !== 'loop') return
727
+
728
+ // 找到当前循环新完成的 COMPLETED 主任务(尚未通知过控制器)。
729
+ // bootAt 过滤:loopCompletedTaskIds 是内存态,进程重启后为空 —— 不过滤会把
730
+ // 重启前已完成的主任务再识别一次并 resubmit(多跑一轮);只认本进程生命
731
+ // 周期内完成的任务,重启前的历史 loop 由用户/上游重新提交
732
+ const current = snapshot.tasks.find((t) => {
733
+ if (t.assigneeId !== this.lead.agentId) return false
734
+ if (t.state !== 'COMPLETED') return false
735
+ if (this.loopCompletedTaskIds.has(t.id)) return false
736
+ if (Date.parse(t.updatedAt) < this.bootAt) return false
737
+ const modeInfo = extractTaskMode(t)
738
+ return !!modeInfo && modeInfo.mode === 'loop'
739
+ })
740
+ if (!current) {
741
+ // 无新的完成事件,但控制器可能已达到最大次数:清空以允许后续新 loop 任务重新开始
742
+ if (this.loopController?.exhausted) {
743
+ this.loopController = null
744
+ }
745
+ return
746
+ }
747
+
748
+ // 同一主任务只通知一次(防每轮 tick 重复计数)
749
+ this.loopCompletedTaskIds.add(current.id)
750
+
751
+ // 已有控制器 → 让控制器推进下一轮
752
+ if (this.loopController) {
753
+ this.loopController.onTaskCompleted()
754
+ return
755
+ }
756
+
757
+ // 创建 loop 控制器 → 每次主任务完成后等待 intervalMs 再重新提交相同任务
758
+ const modeInfo = extractTaskMode(current)!
759
+ const intervalMs = Math.min(86_400_000, Math.max(100, Math.floor(modeInfo.config.intervalMs ?? 60_000)))
760
+ const maxIterations = modeInfo.config.maxIterations ?? Number.POSITIVE_INFINITY
761
+ if (this.onLoopResubmit) {
762
+ this.loopController = new LoopController(
763
+ this.channelRuntime.channelId,
764
+ current.title,
765
+ current.description ?? '',
766
+ intervalMs,
767
+ maxIterations,
768
+ this.onLoopResubmit,
769
+ )
770
+ this.loopController.onTaskCompleted()
771
+ }
772
+ }
773
+ }