agent-tempo 1.0.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 (484) hide show
  1. package/CLAUDE.md +213 -0
  2. package/LICENSE +21 -0
  3. package/README.md +289 -0
  4. package/assets/icon-32.png +0 -0
  5. package/assets/icon-512.png +0 -0
  6. package/assets/icon-64.png +0 -0
  7. package/assets/icon-dark-32.png +0 -0
  8. package/assets/icon-dark-64.png +0 -0
  9. package/assets/icon-dark.svg +9 -0
  10. package/assets/icon.svg +9 -0
  11. package/assets/logo-dark.svg +11 -0
  12. package/assets/logo-light.svg +11 -0
  13. package/dashboard/README.md +91 -0
  14. package/dashboard/dist/assets/index-CB78ToNE.css +2 -0
  15. package/dashboard/dist/assets/index-_5jV0Znu.js +62 -0
  16. package/dashboard/dist/assets/index-_5jV0Znu.js.map +1 -0
  17. package/dashboard/dist/index.html +21 -0
  18. package/dashboard/package.json +47 -0
  19. package/dist/activities/hard-terminate.d.ts +32 -0
  20. package/dist/activities/hard-terminate.js +460 -0
  21. package/dist/activities/maestro.d.ts +72 -0
  22. package/dist/activities/maestro.js +254 -0
  23. package/dist/activities/outbox.d.ts +188 -0
  24. package/dist/activities/outbox.js +849 -0
  25. package/dist/activities/resolve.d.ts +64 -0
  26. package/dist/activities/resolve.js +129 -0
  27. package/dist/activities/schedule-fire.d.ts +36 -0
  28. package/dist/activities/schedule-fire.js +147 -0
  29. package/dist/adapters/base.d.ts +426 -0
  30. package/dist/adapters/base.js +1270 -0
  31. package/dist/adapters/claude-api/adapter.d.ts +168 -0
  32. package/dist/adapters/claude-api/adapter.js +797 -0
  33. package/dist/adapters/claude-api/api-error.d.ts +96 -0
  34. package/dist/adapters/claude-api/api-error.js +191 -0
  35. package/dist/adapters/claude-api/index.d.ts +16 -0
  36. package/dist/adapters/claude-api/index.js +21 -0
  37. package/dist/adapters/claude-api/mcp-bridge.d.ts +50 -0
  38. package/dist/adapters/claude-api/mcp-bridge.js +157 -0
  39. package/dist/adapters/claude-code/adapter.d.ts +133 -0
  40. package/dist/adapters/claude-code/adapter.js +274 -0
  41. package/dist/adapters/claude-code/index.d.ts +15 -0
  42. package/dist/adapters/claude-code/index.js +20 -0
  43. package/dist/adapters/claude-code-headless/adapter.d.ts +131 -0
  44. package/dist/adapters/claude-code-headless/adapter.js +710 -0
  45. package/dist/adapters/claude-code-headless/error-mapper.d.ts +107 -0
  46. package/dist/adapters/claude-code-headless/error-mapper.js +281 -0
  47. package/dist/adapters/claude-code-headless/index.d.ts +17 -0
  48. package/dist/adapters/claude-code-headless/index.js +26 -0
  49. package/dist/adapters/claude-code-headless/pre-flight.d.ts +51 -0
  50. package/dist/adapters/claude-code-headless/pre-flight.js +207 -0
  51. package/dist/adapters/claude-code-headless/prompt.d.ts +93 -0
  52. package/dist/adapters/claude-code-headless/prompt.js +79 -0
  53. package/dist/adapters/claude-code-headless/stream-json.d.ts +242 -0
  54. package/dist/adapters/claude-code-headless/stream-json.js +208 -0
  55. package/dist/adapters/claude-code-headless/types.d.ts +28 -0
  56. package/dist/adapters/claude-code-headless/types.js +36 -0
  57. package/dist/adapters/copilot/adapter.d.ts +100 -0
  58. package/dist/adapters/copilot/adapter.js +730 -0
  59. package/dist/adapters/copilot/index.d.ts +15 -0
  60. package/dist/adapters/copilot/index.js +20 -0
  61. package/dist/adapters/index.d.ts +42 -0
  62. package/dist/adapters/index.js +115 -0
  63. package/dist/adapters/opencode/adapter.d.ts +82 -0
  64. package/dist/adapters/opencode/adapter.js +710 -0
  65. package/dist/adapters/opencode/config.d.ts +90 -0
  66. package/dist/adapters/opencode/config.js +137 -0
  67. package/dist/adapters/opencode/helpers.d.ts +40 -0
  68. package/dist/adapters/opencode/helpers.js +144 -0
  69. package/dist/adapters/opencode/index.d.ts +12 -0
  70. package/dist/adapters/opencode/index.js +17 -0
  71. package/dist/adapters/opencode/server-bridge.d.ts +124 -0
  72. package/dist/adapters/opencode/server-bridge.js +216 -0
  73. package/dist/adapters/sdk/base.d.ts +95 -0
  74. package/dist/adapters/sdk/base.js +134 -0
  75. package/dist/adapters/sdk/system-prompt.d.ts +64 -0
  76. package/dist/adapters/sdk/system-prompt.js +78 -0
  77. package/dist/adapters/terminal-error.d.ts +27 -0
  78. package/dist/adapters/terminal-error.js +39 -0
  79. package/dist/channel.d.ts +3 -0
  80. package/dist/channel.js +48 -0
  81. package/dist/cli/commands.d.ts +245 -0
  82. package/dist/cli/commands.js +2438 -0
  83. package/dist/cli/config-command.d.ts +8 -0
  84. package/dist/cli/config-command.js +254 -0
  85. package/dist/cli/daemon-command.d.ts +57 -0
  86. package/dist/cli/daemon-command.js +493 -0
  87. package/dist/cli/daemon.d.ts +217 -0
  88. package/dist/cli/daemon.js +632 -0
  89. package/dist/cli/dashboard-command.d.ts +20 -0
  90. package/dist/cli/dashboard-command.js +241 -0
  91. package/dist/cli/dev-banner.d.ts +107 -0
  92. package/dist/cli/dev-banner.js +190 -0
  93. package/dist/cli/dev-mode-bootstrap.d.ts +29 -0
  94. package/dist/cli/dev-mode-bootstrap.js +36 -0
  95. package/dist/cli/dev-verbs.d.ts +43 -0
  96. package/dist/cli/dev-verbs.js +254 -0
  97. package/dist/cli/help-text.d.ts +1 -0
  98. package/dist/cli/help-text.js +158 -0
  99. package/dist/cli/legacy-migration.d.ts +35 -0
  100. package/dist/cli/legacy-migration.js +335 -0
  101. package/dist/cli/mcp.d.ts +8 -0
  102. package/dist/cli/mcp.js +63 -0
  103. package/dist/cli/output.d.ts +12 -0
  104. package/dist/cli/output.js +37 -0
  105. package/dist/cli/preflight.d.ts +9 -0
  106. package/dist/cli/preflight.js +96 -0
  107. package/dist/cli/removed-verbs.d.ts +9 -0
  108. package/dist/cli/removed-verbs.js +78 -0
  109. package/dist/cli/sa-preflight.d.ts +99 -0
  110. package/dist/cli/sa-preflight.js +183 -0
  111. package/dist/cli/scenarios-command.d.ts +6 -0
  112. package/dist/cli/scenarios-command.js +167 -0
  113. package/dist/cli/startup.d.ts +112 -0
  114. package/dist/cli/startup.js +641 -0
  115. package/dist/cli/upgrade-command.d.ts +5 -0
  116. package/dist/cli/upgrade-command.js +240 -0
  117. package/dist/cli.d.ts +2 -0
  118. package/dist/cli.js +680 -0
  119. package/dist/client/core.d.ts +33 -0
  120. package/dist/client/core.js +1260 -0
  121. package/dist/client/ensure-conductor-spawned.d.ts +35 -0
  122. package/dist/client/ensure-conductor-spawned.js +48 -0
  123. package/dist/client/index.d.ts +32 -0
  124. package/dist/client/index.js +22 -0
  125. package/dist/client/interface.d.ts +461 -0
  126. package/dist/client/interface.js +2 -0
  127. package/dist/client/subscribe.d.ts +108 -0
  128. package/dist/client/subscribe.js +598 -0
  129. package/dist/client/with-spawn.d.ts +27 -0
  130. package/dist/client/with-spawn.js +87 -0
  131. package/dist/config.d.ts +323 -0
  132. package/dist/config.js +593 -0
  133. package/dist/connection.d.ts +7 -0
  134. package/dist/connection.js +46 -0
  135. package/dist/constants.d.ts +50 -0
  136. package/dist/constants.js +74 -0
  137. package/dist/copilot-bridge.d.ts +22 -0
  138. package/dist/copilot-bridge.js +565 -0
  139. package/dist/daemon-adapter-versions.d.ts +52 -0
  140. package/dist/daemon-adapter-versions.js +170 -0
  141. package/dist/daemon.d.ts +275 -0
  142. package/dist/daemon.js +989 -0
  143. package/dist/ensemble/agent-types.d.ts +23 -0
  144. package/dist/ensemble/agent-types.js +132 -0
  145. package/dist/ensemble/loader.d.ts +14 -0
  146. package/dist/ensemble/loader.js +140 -0
  147. package/dist/ensemble/saver.d.ts +49 -0
  148. package/dist/ensemble/saver.js +201 -0
  149. package/dist/ensemble/schema.d.ts +71 -0
  150. package/dist/ensemble/schema.js +3 -0
  151. package/dist/git-info.d.ts +4 -0
  152. package/dist/git-info.js +29 -0
  153. package/dist/http/aggregate.d.ts +319 -0
  154. package/dist/http/aggregate.js +684 -0
  155. package/dist/http/auth.d.ts +67 -0
  156. package/dist/http/auth.js +177 -0
  157. package/dist/http/body.d.ts +71 -0
  158. package/dist/http/body.js +121 -0
  159. package/dist/http/catalog.d.ts +67 -0
  160. package/dist/http/catalog.js +209 -0
  161. package/dist/http/cors.d.ts +42 -0
  162. package/dist/http/cors.js +111 -0
  163. package/dist/http/dashboard-pair.d.ts +94 -0
  164. package/dist/http/dashboard-pair.js +148 -0
  165. package/dist/http/dashboard.d.ts +20 -0
  166. package/dist/http/dashboard.js +160 -0
  167. package/dist/http/event-bus.d.ts +217 -0
  168. package/dist/http/event-bus.js +365 -0
  169. package/dist/http/event-id.d.ts +77 -0
  170. package/dist/http/event-id.js +117 -0
  171. package/dist/http/event-types.d.ts +348 -0
  172. package/dist/http/event-types.js +36 -0
  173. package/dist/http/fixtures/chat-stress.d.ts +8 -0
  174. package/dist/http/fixtures/chat-stress.js +63 -0
  175. package/dist/http/fixtures/conductor-leaving.d.ts +8 -0
  176. package/dist/http/fixtures/conductor-leaving.js +80 -0
  177. package/dist/http/fixtures/constants.d.ts +10 -0
  178. package/dist/http/fixtures/constants.js +13 -0
  179. package/dist/http/fixtures/eight-player-broadcast.d.ts +10 -0
  180. package/dist/http/fixtures/eight-player-broadcast.js +81 -0
  181. package/dist/http/fixtures/empty-ensemble.d.ts +6 -0
  182. package/dist/http/fixtures/empty-ensemble.js +26 -0
  183. package/dist/http/fixtures/index.d.ts +55 -0
  184. package/dist/http/fixtures/index.js +110 -0
  185. package/dist/http/fixtures/single-conductor.d.ts +7 -0
  186. package/dist/http/fixtures/single-conductor.js +46 -0
  187. package/dist/http/fixtures/sse-reconnect.d.ts +8 -0
  188. package/dist/http/fixtures/sse-reconnect.js +77 -0
  189. package/dist/http/index.d.ts +21 -0
  190. package/dist/http/index.js +61 -0
  191. package/dist/http/port-file.d.ts +22 -0
  192. package/dist/http/port-file.js +132 -0
  193. package/dist/http/responses.d.ts +27 -0
  194. package/dist/http/responses.js +40 -0
  195. package/dist/http/ring-buffer.d.ts +41 -0
  196. package/dist/http/ring-buffer.js +80 -0
  197. package/dist/http/server.d.ts +122 -0
  198. package/dist/http/server.js +459 -0
  199. package/dist/http/snapshot.d.ts +85 -0
  200. package/dist/http/snapshot.js +180 -0
  201. package/dist/http/sse-handler.d.ts +87 -0
  202. package/dist/http/sse-handler.js +294 -0
  203. package/dist/http/writes.d.ts +55 -0
  204. package/dist/http/writes.js +240 -0
  205. package/dist/palette/index.d.ts +138 -0
  206. package/dist/palette/index.js +221 -0
  207. package/dist/reconcile/orphans.d.ts +255 -0
  208. package/dist/reconcile/orphans.js +340 -0
  209. package/dist/scripts/258-spotcheck.js +303 -0
  210. package/dist/scripts/check-components-css-sync.js +199 -0
  211. package/dist/scripts/run-shard.js +121 -0
  212. package/dist/scripts/verify-daemon-isolation-guard.js +128 -0
  213. package/dist/server-tools.d.ts +87 -0
  214. package/dist/server-tools.js +146 -0
  215. package/dist/server.d.ts +2 -0
  216. package/dist/server.js +366 -0
  217. package/dist/spawn.d.ts +296 -0
  218. package/dist/spawn.js +747 -0
  219. package/dist/tools/agent-types.d.ts +2 -0
  220. package/dist/tools/agent-types.js +21 -0
  221. package/dist/tools/attachment-info.d.ts +4 -0
  222. package/dist/tools/attachment-info.js +48 -0
  223. package/dist/tools/broadcast.d.ts +4 -0
  224. package/dist/tools/broadcast.js +76 -0
  225. package/dist/tools/cancel-stage.d.ts +3 -0
  226. package/dist/tools/cancel-stage.js +20 -0
  227. package/dist/tools/clear-state.d.ts +3 -0
  228. package/dist/tools/clear-state.js +37 -0
  229. package/dist/tools/coat-check-evict.d.ts +4 -0
  230. package/dist/tools/coat-check-evict.js +43 -0
  231. package/dist/tools/coat-check-get.d.ts +4 -0
  232. package/dist/tools/coat-check-get.js +56 -0
  233. package/dist/tools/coat-check-list.d.ts +4 -0
  234. package/dist/tools/coat-check-list.js +60 -0
  235. package/dist/tools/coat-check-put.d.ts +4 -0
  236. package/dist/tools/coat-check-put.js +53 -0
  237. package/dist/tools/cue.d.ts +44 -0
  238. package/dist/tools/cue.js +201 -0
  239. package/dist/tools/destroy.d.ts +4 -0
  240. package/dist/tools/destroy.js +188 -0
  241. package/dist/tools/detach.d.ts +4 -0
  242. package/dist/tools/detach.js +45 -0
  243. package/dist/tools/encore.d.ts +4 -0
  244. package/dist/tools/encore.js +31 -0
  245. package/dist/tools/ensemble.d.ts +32 -0
  246. package/dist/tools/ensemble.js +198 -0
  247. package/dist/tools/evaluate-gate.d.ts +3 -0
  248. package/dist/tools/evaluate-gate.js +32 -0
  249. package/dist/tools/fetch-state.d.ts +13 -0
  250. package/dist/tools/fetch-state.js +78 -0
  251. package/dist/tools/gates.d.ts +3 -0
  252. package/dist/tools/gates.js +41 -0
  253. package/dist/tools/helpers.d.ts +21 -0
  254. package/dist/tools/helpers.js +25 -0
  255. package/dist/tools/hosts.d.ts +4 -0
  256. package/dist/tools/hosts.js +40 -0
  257. package/dist/tools/listen.d.ts +3 -0
  258. package/dist/tools/listen.js +22 -0
  259. package/dist/tools/load-lineup.d.ts +5 -0
  260. package/dist/tools/load-lineup.js +381 -0
  261. package/dist/tools/migrate.d.ts +4 -0
  262. package/dist/tools/migrate.js +60 -0
  263. package/dist/tools/pause-ensemble.d.ts +4 -0
  264. package/dist/tools/pause-ensemble.js +58 -0
  265. package/dist/tools/pause.d.ts +4 -0
  266. package/dist/tools/pause.js +36 -0
  267. package/dist/tools/play.d.ts +4 -0
  268. package/dist/tools/play.js +57 -0
  269. package/dist/tools/quality-gate.d.ts +3 -0
  270. package/dist/tools/quality-gate.js +26 -0
  271. package/dist/tools/recall.d.ts +3 -0
  272. package/dist/tools/recall.js +32 -0
  273. package/dist/tools/recruit.d.ts +38 -0
  274. package/dist/tools/recruit.js +447 -0
  275. package/dist/tools/release.d.ts +4 -0
  276. package/dist/tools/release.js +98 -0
  277. package/dist/tools/report.d.ts +3 -0
  278. package/dist/tools/report.js +29 -0
  279. package/dist/tools/resolve.d.ts +1 -0
  280. package/dist/tools/resolve.js +7 -0
  281. package/dist/tools/restart.d.ts +35 -0
  282. package/dist/tools/restart.js +131 -0
  283. package/dist/tools/restore.d.ts +4 -0
  284. package/dist/tools/restore.js +107 -0
  285. package/dist/tools/resume-ensemble.d.ts +4 -0
  286. package/dist/tools/resume-ensemble.js +79 -0
  287. package/dist/tools/save-lineup.d.ts +4 -0
  288. package/dist/tools/save-lineup.js +36 -0
  289. package/dist/tools/save-state.d.ts +3 -0
  290. package/dist/tools/save-state.js +57 -0
  291. package/dist/tools/schedule.d.ts +4 -0
  292. package/dist/tools/schedule.js +152 -0
  293. package/dist/tools/schedules.d.ts +4 -0
  294. package/dist/tools/schedules.js +54 -0
  295. package/dist/tools/set-ensemble-description.d.ts +4 -0
  296. package/dist/tools/set-ensemble-description.js +37 -0
  297. package/dist/tools/set-name.d.ts +4 -0
  298. package/dist/tools/set-name.js +45 -0
  299. package/dist/tools/set-part.d.ts +3 -0
  300. package/dist/tools/set-part.js +20 -0
  301. package/dist/tools/shutdown.d.ts +4 -0
  302. package/dist/tools/shutdown.js +54 -0
  303. package/dist/tools/stage.d.ts +3 -0
  304. package/dist/tools/stage.js +28 -0
  305. package/dist/tools/stages.d.ts +3 -0
  306. package/dist/tools/stages.js +35 -0
  307. package/dist/tools/stop.d.ts +4 -0
  308. package/dist/tools/stop.js +29 -0
  309. package/dist/tools/unschedule.d.ts +4 -0
  310. package/dist/tools/unschedule.js +35 -0
  311. package/dist/tools/who-am-i.d.ts +3 -0
  312. package/dist/tools/who-am-i.js +34 -0
  313. package/dist/tools/worktree.d.ts +4 -0
  314. package/dist/tools/worktree.js +181 -0
  315. package/dist/tui/App.d.ts +85 -0
  316. package/dist/tui/App.js +1791 -0
  317. package/dist/tui/bootstrap-types.d.ts +46 -0
  318. package/dist/tui/bootstrap-types.js +7 -0
  319. package/dist/tui/client.d.ts +6 -0
  320. package/dist/tui/client.js +9 -0
  321. package/dist/tui/commands.d.ts +71 -0
  322. package/dist/tui/commands.js +1375 -0
  323. package/dist/tui/components/ActivityLog.d.ts +16 -0
  324. package/dist/tui/components/ActivityLog.js +36 -0
  325. package/dist/tui/components/ChatView.d.ts +35 -0
  326. package/dist/tui/components/ChatView.js +54 -0
  327. package/dist/tui/components/CommandOverlay.d.ts +15 -0
  328. package/dist/tui/components/CommandOverlay.js +34 -0
  329. package/dist/tui/components/CommandPalette.d.ts +21 -0
  330. package/dist/tui/components/CommandPalette.js +67 -0
  331. package/dist/tui/components/ConductorChat.d.ts +16 -0
  332. package/dist/tui/components/ConductorChat.js +32 -0
  333. package/dist/tui/components/ConversationStream.d.ts +114 -0
  334. package/dist/tui/components/ConversationStream.js +307 -0
  335. package/dist/tui/components/CreateEnsembleWizard.d.ts +19 -0
  336. package/dist/tui/components/CreateEnsembleWizard.js +223 -0
  337. package/dist/tui/components/DestroyConfirmModal.d.ts +17 -0
  338. package/dist/tui/components/DestroyConfirmModal.js +62 -0
  339. package/dist/tui/components/EnsembleListView.d.ts +14 -0
  340. package/dist/tui/components/EnsembleListView.js +32 -0
  341. package/dist/tui/components/EnsemblePanel.d.ts +12 -0
  342. package/dist/tui/components/EnsemblePanel.js +40 -0
  343. package/dist/tui/components/ErrorView.d.ts +31 -0
  344. package/dist/tui/components/ErrorView.js +129 -0
  345. package/dist/tui/components/HomeView.d.ts +54 -0
  346. package/dist/tui/components/HomeView.js +306 -0
  347. package/dist/tui/components/InputBar.d.ts +13 -0
  348. package/dist/tui/components/InputBar.js +58 -0
  349. package/dist/tui/components/LoadLineupModal.d.ts +18 -0
  350. package/dist/tui/components/LoadLineupModal.js +79 -0
  351. package/dist/tui/components/MainView.d.ts +21 -0
  352. package/dist/tui/components/MainView.js +107 -0
  353. package/dist/tui/components/NewEnsembleModal.d.ts +9 -0
  354. package/dist/tui/components/NewEnsembleModal.js +73 -0
  355. package/dist/tui/components/Picker.d.ts +23 -0
  356. package/dist/tui/components/Picker.js +70 -0
  357. package/dist/tui/components/PlayerDetailView.d.ts +26 -0
  358. package/dist/tui/components/PlayerDetailView.js +118 -0
  359. package/dist/tui/components/PromptArea.d.ts +50 -0
  360. package/dist/tui/components/PromptArea.js +303 -0
  361. package/dist/tui/components/RecruitWizard.d.ts +17 -0
  362. package/dist/tui/components/RecruitWizard.js +221 -0
  363. package/dist/tui/components/RestoreConfirmModal.d.ts +18 -0
  364. package/dist/tui/components/RestoreConfirmModal.js +71 -0
  365. package/dist/tui/components/ScheduleOverlay.d.ts +13 -0
  366. package/dist/tui/components/ScheduleOverlay.js +113 -0
  367. package/dist/tui/components/ScheduleWizard.d.ts +19 -0
  368. package/dist/tui/components/ScheduleWizard.js +259 -0
  369. package/dist/tui/components/Splash.d.ts +23 -0
  370. package/dist/tui/components/Splash.js +221 -0
  371. package/dist/tui/components/StatusBar.d.ts +48 -0
  372. package/dist/tui/components/StatusBar.js +128 -0
  373. package/dist/tui/components/StatusOverlay.d.ts +15 -0
  374. package/dist/tui/components/StatusOverlay.js +76 -0
  375. package/dist/tui/components/TitleBar.d.ts +10 -0
  376. package/dist/tui/components/TitleBar.js +21 -0
  377. package/dist/tui/components/TopBar.d.ts +12 -0
  378. package/dist/tui/components/TopBar.js +15 -0
  379. package/dist/tui/core-api.d.ts +26 -0
  380. package/dist/tui/core-api.js +67 -0
  381. package/dist/tui/hooks/useEnsembleDiscovery.d.ts +3 -0
  382. package/dist/tui/hooks/useEnsembleDiscovery.js +30 -0
  383. package/dist/tui/hooks/useMaestroPoller.d.ts +3 -0
  384. package/dist/tui/hooks/useMaestroPoller.js +36 -0
  385. package/dist/tui/hooks/useSendCommand.d.ts +7 -0
  386. package/dist/tui/hooks/useSendCommand.js +29 -0
  387. package/dist/tui/index.d.ts +15 -0
  388. package/dist/tui/index.js +156 -0
  389. package/dist/tui/ink-context.d.ts +18 -0
  390. package/dist/tui/ink-context.js +59 -0
  391. package/dist/tui/ink-loader.d.ts +26 -0
  392. package/dist/tui/ink-loader.js +42 -0
  393. package/dist/tui/removed-commands.d.ts +9 -0
  394. package/dist/tui/removed-commands.js +22 -0
  395. package/dist/tui/sse-handler.d.ts +52 -0
  396. package/dist/tui/sse-handler.js +157 -0
  397. package/dist/tui/store.d.ts +598 -0
  398. package/dist/tui/store.js +753 -0
  399. package/dist/tui/utils/format.d.ts +56 -0
  400. package/dist/tui/utils/format.js +155 -0
  401. package/dist/tui/utils/fullscreen.d.ts +23 -0
  402. package/dist/tui/utils/fullscreen.js +71 -0
  403. package/dist/tui/utils/history.d.ts +10 -0
  404. package/dist/tui/utils/history.js +85 -0
  405. package/dist/tui/utils/platform.d.ts +45 -0
  406. package/dist/tui/utils/platform.js +258 -0
  407. package/dist/tui/utils/theme.d.ts +21 -0
  408. package/dist/tui/utils/theme.js +24 -0
  409. package/dist/types.d.ts +1020 -0
  410. package/dist/types.js +39 -0
  411. package/dist/utils/attachment-format.d.ts +22 -0
  412. package/dist/utils/attachment-format.js +32 -0
  413. package/dist/utils/default-part.d.ts +43 -0
  414. package/dist/utils/default-part.js +104 -0
  415. package/dist/utils/duration.d.ts +30 -0
  416. package/dist/utils/duration.js +69 -0
  417. package/dist/utils/ensemble-ops.d.ts +61 -0
  418. package/dist/utils/ensemble-ops.js +77 -0
  419. package/dist/utils/format-hosts.d.ts +21 -0
  420. package/dist/utils/format-hosts.js +73 -0
  421. package/dist/utils/hosts.d.ts +113 -0
  422. package/dist/utils/hosts.js +265 -0
  423. package/dist/utils/parent-death-watchdog.d.ts +1 -0
  424. package/dist/utils/parent-death-watchdog.js +47 -0
  425. package/dist/utils/query-timeout.d.ts +103 -0
  426. package/dist/utils/query-timeout.js +113 -0
  427. package/dist/utils/recall-format.d.ts +78 -0
  428. package/dist/utils/recall-format.js +105 -0
  429. package/dist/utils/restore-format.d.ts +49 -0
  430. package/dist/utils/restore-format.js +91 -0
  431. package/dist/utils/safe-path.d.ts +10 -0
  432. package/dist/utils/safe-path.js +43 -0
  433. package/dist/utils/sdk-probe.d.ts +9 -0
  434. package/dist/utils/sdk-probe.js +45 -0
  435. package/dist/utils/search-attributes.d.ts +76 -0
  436. package/dist/utils/search-attributes.js +86 -0
  437. package/dist/utils/validation.d.ts +113 -0
  438. package/dist/utils/validation.js +163 -0
  439. package/dist/utils/visibility-deadline.d.ts +186 -0
  440. package/dist/utils/visibility-deadline.js +158 -0
  441. package/dist/utils/worktree.d.ts +103 -0
  442. package/dist/utils/worktree.js +327 -0
  443. package/dist/worker.d.ts +14 -0
  444. package/dist/worker.js +146 -0
  445. package/dist/workflows/attachment-math.d.ts +56 -0
  446. package/dist/workflows/attachment-math.js +47 -0
  447. package/dist/workflows/index.d.ts +3 -0
  448. package/dist/workflows/index.js +11 -0
  449. package/dist/workflows/maestro-signals.d.ts +217 -0
  450. package/dist/workflows/maestro-signals.js +155 -0
  451. package/dist/workflows/maestro.d.ts +3 -0
  452. package/dist/workflows/maestro.js +812 -0
  453. package/dist/workflows/scheduler-signals.d.ts +10 -0
  454. package/dist/workflows/scheduler-signals.js +14 -0
  455. package/dist/workflows/scheduler.d.ts +17 -0
  456. package/dist/workflows/scheduler.js +143 -0
  457. package/dist/workflows/session.d.ts +2 -0
  458. package/dist/workflows/session.js +1638 -0
  459. package/dist/workflows/signals.d.ts +297 -0
  460. package/dist/workflows/signals.js +239 -0
  461. package/examples/agents/tempo-composer.md +56 -0
  462. package/examples/agents/tempo-conductor.md +117 -0
  463. package/examples/agents/tempo-critic.md +73 -0
  464. package/examples/agents/tempo-improv.md +74 -0
  465. package/examples/agents/tempo-liner.md +75 -0
  466. package/examples/agents/tempo-roadie.md +61 -0
  467. package/examples/agents/tempo-soloist.md +71 -0
  468. package/examples/agents/tempo-tuner.md +94 -0
  469. package/examples/ensembles/tempo-big-band.yaml +146 -0
  470. package/examples/ensembles/tempo-dev-team.yaml +58 -0
  471. package/examples/ensembles/tempo-headless-jam.yaml +77 -0
  472. package/examples/ensembles/tempo-jam-session.yaml +41 -0
  473. package/examples/ensembles/tempo-mock-jam.yaml +79 -0
  474. package/examples/ensembles/tempo-review-squad.yaml +32 -0
  475. package/package.json +172 -0
  476. package/packaging/launchd/com.agent.tempo.plist +46 -0
  477. package/packaging/systemd/agent-tempo.service +32 -0
  478. package/packaging/windows/install-task.ps1 +71 -0
  479. package/scenarios/conductor-recruit-mock.yaml +33 -0
  480. package/scenarios/echo-roundtrip.yaml +15 -0
  481. package/scenarios/multi-player-handoff.yaml +38 -0
  482. package/scenarios/recruit-cascade.yaml +38 -0
  483. package/scenarios/two-player-conversation.yaml +33 -0
  484. package/workflow-bundle.js +14146 -0
@@ -0,0 +1,381 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerLoadLineupTool = registerLoadLineupTool;
4
+ const zod_1 = require("zod");
5
+ const croner_1 = require("croner");
6
+ const client_1 = require("@temporalio/client");
7
+ const config_1 = require("../config");
8
+ const agent_types_1 = require("../ensemble/agent-types");
9
+ const loader_1 = require("../ensemble/loader");
10
+ const resolve_1 = require("./resolve");
11
+ const resolve_2 = require("../activities/resolve");
12
+ const signals_1 = require("../workflows/signals");
13
+ const duration_1 = require("../utils/duration");
14
+ const safe_path_1 = require("../utils/safe-path");
15
+ const helpers_1 = require("./helpers");
16
+ const validation_1 = require("../utils/validation");
17
+ const constants_1 = require("../constants");
18
+ const log = (...args) => console.error('[agent-tempo:load-lineup]', ...args);
19
+ function registerLoadLineupTool(server, client, config, getPlayerId, ownAgentType = 'claude', handle, setPlayerId, isConductor) {
20
+ (0, helpers_1.defineTool)(server, 'load_lineup', 'Load an ensemble lineup — recruits players and creates schedules.', {
21
+ name: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).optional().describe('Name of a lineup — resolves saved lineups, then shipped examples (e.g. "tempo-dev-team")'),
22
+ path: zod_1.z.string().max(validation_1.PATH_MAX).optional().describe('Explicit file path to a lineup YAML file'),
23
+ hold: zod_1.z.boolean().optional().describe('When true, spawn players in "warm hold": processes start and attach but their outbox is locked, so they receive a standby message and defer their initial task until `release` is called.'),
24
+ initialStartup: zod_1.z.boolean().optional().describe('Issue #172: when true, the lineup was loaded as part of initial ensemble startup (`up --lineup` / `conduct --lineup`). Conductor instructions are stored as pending context and combined with the user\'s first message instead of firing immediately. Also recruits players with `hold: true`. Defaults to false — conductor-invoked mid-work `load_lineup` keeps the legacy behavior.'),
25
+ }, async (args) => {
26
+ const lineupName = args.name;
27
+ const lineupPath = args.path;
28
+ const initialStartup = args.initialStartup === true;
29
+ // Initial-startup always implies warm-hold — players should wait for
30
+ // the conductor to decompose the user's first message before starting.
31
+ const hold = args.hold === true || initialStartup;
32
+ if (!lineupName && !lineupPath) {
33
+ return (0, helpers_1.fail)('Provide either `name` (saved lineup) or `path` (file path). Exactly one is required.');
34
+ }
35
+ if (lineupName && lineupPath) {
36
+ return (0, helpers_1.fail)('Provide either `name` or `path`, not both.');
37
+ }
38
+ try {
39
+ // Resolve the file path: saved → shipped examples → direct file path
40
+ let filePath;
41
+ if (lineupPath) {
42
+ // User-provided path — validate against allowed roots
43
+ filePath = (0, safe_path_1.safeLineupPath)(lineupPath, process.cwd());
44
+ }
45
+ else {
46
+ const resolution = (0, loader_1.resolveLineupPath)(lineupName);
47
+ filePath = resolution.path;
48
+ // Only validate user-facing paths (saved lineups, file paths).
49
+ // Shipped examples are package-controlled and may live outside
50
+ // allowed roots when globally installed.
51
+ if (resolution.source !== 'shipped') {
52
+ filePath = (0, safe_path_1.safeLineupPath)(filePath, process.cwd());
53
+ }
54
+ }
55
+ const lineup = (0, agent_types_1.loadAndResolveLineup)(filePath);
56
+ const recruited = [];
57
+ const failed = [];
58
+ const conductorActions = [];
59
+ // Issue #172 follow-up: on `initialStartup`, fire the `from: 'system'`
60
+ // directive BEFORE any lineup instructions. Earlier messages weigh
61
+ // more heavily with the LLM — putting the "call resume_ensemble +
62
+ // release FIRST" framing at the top of the conductor's inbox reduces
63
+ // the chance the model skims past it and goes straight to broadcast.
64
+ // Runs independently of whether the lineup has a `conductor:` section
65
+ // (e.g. players-only lineups still need the banner + directive).
66
+ if (initialStartup && isConductor && handle) {
67
+ try {
68
+ const playerCount = lineup.players.length;
69
+ await handle.signal('receiveMessage', {
70
+ from: 'system',
71
+ text: (0, constants_1.ensembleReadyDirective)(lineup.name, playerCount),
72
+ responseRequested: false,
73
+ });
74
+ conductorActions.push('startup banner + directive delivered');
75
+ }
76
+ catch (err) {
77
+ failed.push(`conductor startup banner: ${err}`);
78
+ }
79
+ }
80
+ // Apply conductor section if present and this session is the conductor
81
+ if (lineup.conductor && isConductor && handle) {
82
+ // Apply conductor name
83
+ if (lineup.conductor.name && lineup.conductor.name !== getPlayerId()) {
84
+ try {
85
+ // Check if the name is already taken
86
+ const existing = await (0, resolve_1.resolveSession)(client, config.ensemble, lineup.conductor.name);
87
+ if (existing && existing.workflowId !== handle.workflowId) {
88
+ failed.push(`conductor name "${lineup.conductor.name}": already taken by another session`);
89
+ }
90
+ else {
91
+ await handle.signal('setName', lineup.conductor.name);
92
+ if (setPlayerId)
93
+ setPlayerId(lineup.conductor.name);
94
+ conductorActions.push(`name → ${lineup.conductor.name}`);
95
+ log(`Conductor name set to "${lineup.conductor.name}"`);
96
+ }
97
+ }
98
+ catch (err) {
99
+ failed.push(`conductor name: ${err}`);
100
+ }
101
+ }
102
+ // Apply conductor type (update metadata)
103
+ if (lineup.conductor.type) {
104
+ try {
105
+ const typeInfo = (0, agent_types_1.resolveAgentType)(lineup.conductor.type);
106
+ if (typeInfo) {
107
+ await handle.signal('updateMetadata', {
108
+ playerType: typeInfo.name,
109
+ playerTypeDescription: typeInfo.description || '',
110
+ });
111
+ conductorActions.push(`type → ${typeInfo.name}`);
112
+ log(`Conductor type set to "${typeInfo.name}"`);
113
+ }
114
+ else {
115
+ failed.push(`conductor type "${lineup.conductor.type}": agent type not found`);
116
+ }
117
+ }
118
+ catch (err) {
119
+ failed.push(`conductor type: ${err}`);
120
+ }
121
+ }
122
+ // Send conductor instructions.
123
+ // Issue #172 (v0.26 simplification): on the initial-startup path,
124
+ // signal the lineup instructions as a `receiveMessage` immediately
125
+ // — the ensemble-wide pause (below) stops any downstream dispatch,
126
+ // and the banner+directive signal (also below) tells the LLM to
127
+ // wait silently until the user speaks and then call
128
+ // `resume_ensemble` first. Legacy mid-work path also signals
129
+ // immediately — no branching required.
130
+ if (lineup.conductor.instructions) {
131
+ try {
132
+ await handle.signal('receiveMessage', {
133
+ from: 'lineup',
134
+ text: lineup.conductor.instructions,
135
+ responseRequested: false,
136
+ });
137
+ conductorActions.push(initialStartup ? 'instructions seeded (initial startup)' : 'instructions delivered');
138
+ log('Conductor instructions delivered');
139
+ }
140
+ catch (err) {
141
+ failed.push(`conductor instructions: ${err}`);
142
+ }
143
+ }
144
+ }
145
+ // Legacy hold-mode standby (conductor-invoked mid-work with hold: true).
146
+ // Runs ONLY on the non-initial-startup path — initialStartup handling
147
+ // happens earlier above, ordered before the lineup instructions.
148
+ if (!initialStartup && hold && isConductor && handle) {
149
+ try {
150
+ await handle.signal('receiveMessage', {
151
+ from: 'system',
152
+ text: 'Ensemble is loading in hold mode — players are connecting but on standby. Wait for instructions from the user or maestro before directing the ensemble. When ready, use the `release` tool to deliver task assignments to all held players.',
153
+ responseRequested: false,
154
+ });
155
+ conductorActions.push('hold mode standby');
156
+ }
157
+ catch (err) {
158
+ failed.push(`conductor hold message: ${err}`);
159
+ }
160
+ }
161
+ // Recruit players via outbox — no polling needed
162
+ for (const player of lineup.players) {
163
+ const playerName = player.name;
164
+ const workDir = player.workDir || process.cwd();
165
+ const agentType = player.agent === 'copilot' ? 'copilot' : 'claude';
166
+ const isCustomAgent = player.agent && player.agent !== 'default' && player.agent !== 'copilot';
167
+ const systemPrompt = player._agentDefinition ? undefined : (isCustomAgent ? player.agent : undefined);
168
+ const agentDefinition = player._agentDefinition;
169
+ const agentDefinitionPath = player._agentDefinitionPath;
170
+ // Skip if already active — send instructions via cue instead
171
+ const existing = await (0, resolve_1.resolveSession)(client, config.ensemble, playerName);
172
+ if (existing) {
173
+ log(`Player "${playerName}" already active — skipping recruit`);
174
+ recruited.push(`${playerName} (already active)`);
175
+ if (player.instructions && handle) {
176
+ try {
177
+ const cueEntry = {
178
+ type: 'cue',
179
+ targetPlayerId: playerName,
180
+ message: player.instructions,
181
+ };
182
+ await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [cueEntry] });
183
+ }
184
+ catch (err) {
185
+ log(`Failed to send instructions to already-active player "${playerName}":`, err);
186
+ }
187
+ }
188
+ continue;
189
+ }
190
+ // Submit recruit via outbox — pre-creates workflow with pending status
191
+ if (!handle) {
192
+ failed.push(`${playerName}: load_lineup requires a workflow handle to recruit`);
193
+ continue;
194
+ }
195
+ try {
196
+ // Resolve full agent type info (description, nativeResolvable) if available
197
+ const resolvedType = agentDefinition ? (0, agent_types_1.resolveAgentType)(agentDefinition) : null;
198
+ const entry = {
199
+ type: 'recruit',
200
+ targetName: playerName,
201
+ workDir,
202
+ isConductor: false,
203
+ initialMessage: player.instructions,
204
+ agent: agentType,
205
+ systemPrompt: agentDefinition ? undefined : systemPrompt,
206
+ agentDefinition: resolvedType?.name || agentDefinition,
207
+ agentDefinitionPath: resolvedType?.path || agentDefinitionPath,
208
+ agentDefinitionDescription: resolvedType?.description,
209
+ nativeResolvable: resolvedType?.nativeResolvable,
210
+ allowedTools: player.allowedTools,
211
+ claudeBin: config.claudeBin,
212
+ ...(hold ? { held: true } : {}),
213
+ };
214
+ await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
215
+ recruited.push(playerName);
216
+ log(`Recruit request submitted for "${playerName}" in ${workDir}`);
217
+ }
218
+ catch (err) {
219
+ failed.push(`${playerName}: recruit failed — ${err}`);
220
+ }
221
+ }
222
+ // Create schedules
223
+ const schedulesCreated = [];
224
+ const scheduleWarnings = [];
225
+ if (lineup.schedules && lineup.schedules.length > 0) {
226
+ // Build valid target set from lineup player names + special values
227
+ const validTargets = new Set(lineup.players.map((p) => p.name));
228
+ validTargets.add('conductor');
229
+ validTargets.add('all');
230
+ for (const sched of lineup.schedules) {
231
+ try {
232
+ // Validate schedule target against known player names
233
+ if (!validTargets.has(sched.target)) {
234
+ scheduleWarnings.push(`schedule "${sched.name}": target "${sched.target}" does not match any player in this lineup (known: ${[...validTargets].join(', ')})`);
235
+ }
236
+ const now = Date.now();
237
+ let nextFireAt;
238
+ let interval;
239
+ let cronExpression;
240
+ let timezone;
241
+ if (sched.at) {
242
+ nextFireAt = Date.parse(sched.at);
243
+ // Support at + every: use `at` as the initial fire time, `every` as the interval
244
+ if (sched.every) {
245
+ const ms = (0, duration_1.parseDuration)(sched.every);
246
+ if (!ms)
247
+ throw new Error(`Invalid interval: ${sched.every}`);
248
+ interval = ms;
249
+ }
250
+ }
251
+ else if (sched.delay) {
252
+ const ms = (0, duration_1.parseDuration)(sched.delay);
253
+ if (!ms)
254
+ throw new Error(`Invalid delay: ${sched.delay}`);
255
+ nextFireAt = now + ms;
256
+ }
257
+ else if (sched.every) {
258
+ const ms = (0, duration_1.parseDuration)(sched.every);
259
+ if (!ms)
260
+ throw new Error(`Invalid interval: ${sched.every}`);
261
+ nextFireAt = now + ms;
262
+ interval = ms;
263
+ }
264
+ else if (sched.cron) {
265
+ cronExpression = sched.cron;
266
+ timezone = sched.timezone || 'UTC';
267
+ const job = new croner_1.Cron(cronExpression, { timezone });
268
+ const next = job.nextRun();
269
+ if (!next)
270
+ throw new Error(`Cron expression "${sched.cron}" has no upcoming fire time`);
271
+ nextFireAt = next.getTime();
272
+ }
273
+ else {
274
+ throw new Error('No timing specified');
275
+ }
276
+ const type = sched.cron ? 'cron' : (sched.every || interval) ? 'interval' : 'once';
277
+ const scheduleEntry = {
278
+ name: sched.name,
279
+ message: sched.message,
280
+ target: sched.target,
281
+ type,
282
+ nextFireAt: new Date(nextFireAt).toISOString(),
283
+ interval,
284
+ cronExpression,
285
+ timezone,
286
+ until: sched.until,
287
+ remainingCount: sched.count,
288
+ firedCount: 0,
289
+ createdBy: getPlayerId(),
290
+ };
291
+ const wfId = (0, config_1.schedulerWorkflowId)(config.ensemble);
292
+ try {
293
+ const handle = client.workflow.getHandle(wfId);
294
+ await handle.describe();
295
+ await handle.signal('addSchedule', scheduleEntry);
296
+ }
297
+ catch {
298
+ await client.workflow.start('agentSchedulerWorkflow', {
299
+ workflowId: wfId,
300
+ taskQueue: config.taskQueue,
301
+ args: [{ ensemble: config.ensemble, entries: [scheduleEntry] }],
302
+ workflowIdConflictPolicy: client_1.WorkflowIdConflictPolicy.USE_EXISTING,
303
+ searchAttributes: {
304
+ AgentTempoEnsemble: [config.ensemble],
305
+ },
306
+ });
307
+ }
308
+ schedulesCreated.push(sched.name);
309
+ }
310
+ catch (err) {
311
+ failed.push(`schedule "${sched.name}": ${err}`);
312
+ }
313
+ }
314
+ }
315
+ // Issue #172: on the initial-startup path, pause the whole ensemble
316
+ // so scheduler fires, maestro nudges, and per-session outbox dispatch
317
+ // are all halted while we wait for the user's first message. The
318
+ // conductor's `receiveMessageSignal` handler combines lineup context +
319
+ // user text and the combined prompt instructs Claude Code to call
320
+ // `resume_ensemble` BEFORE any other action. Inlines the three signals
321
+ // that `pause_ensemble` fires so we don't depend on the tool impl.
322
+ if (initialStartup && isConductor && handle) {
323
+ try {
324
+ const maestroId = (0, config_1.maestroWorkflowId)(config.ensemble);
325
+ await client.workflow.getHandle(maestroId).signal('maestroSetPaused', true);
326
+ }
327
+ catch {
328
+ // Maestro may not be running yet — fine, it will start paused once spawned.
329
+ }
330
+ try {
331
+ const schedulerId = (0, config_1.schedulerWorkflowId)(config.ensemble);
332
+ await client.workflow.getHandle(schedulerId).signal('setSchedulerPaused', true);
333
+ }
334
+ catch {
335
+ // Scheduler may not exist yet if no schedules are defined — ignore.
336
+ }
337
+ try {
338
+ const sessions = await (0, resolve_2.scanEnsembleSessions)(client, config.ensemble);
339
+ for (const session of sessions) {
340
+ try {
341
+ await client.workflow.getHandle(session.workflowId).signal('setPaused', true);
342
+ }
343
+ catch {
344
+ // Individual session may have just terminated — skip.
345
+ }
346
+ }
347
+ conductorActions.push('ensemble paused (awaiting first user message)');
348
+ }
349
+ catch (err) {
350
+ failed.push(`pause ensemble: ${(0, helpers_1.formatError)(err)}`);
351
+ }
352
+ }
353
+ // Build summary
354
+ const lines = [`Loaded lineup **${lineup.name}**.`];
355
+ if (conductorActions.length > 0) {
356
+ lines.push(`Conductor: ${conductorActions.join(', ')}`);
357
+ }
358
+ if (recruited.length > 0) {
359
+ if (hold) {
360
+ lines.push(`Held: ${recruited.join(', ')} — ${recruited.length} player(s) held. Use \`release\` to start them.`);
361
+ }
362
+ else {
363
+ lines.push(`Recruited: ${recruited.join(', ')}`);
364
+ }
365
+ }
366
+ if (schedulesCreated.length > 0) {
367
+ lines.push(`Schedules created: ${schedulesCreated.join(', ')}`);
368
+ }
369
+ if (scheduleWarnings.length > 0) {
370
+ lines.push(`⚠ Schedule target warnings:\n${scheduleWarnings.map(w => ` - ${w}`).join('\n')}`);
371
+ }
372
+ if (failed.length > 0) {
373
+ lines.push(`Failures:\n${failed.map(f => ` - ${f}`).join('\n')}`);
374
+ }
375
+ return (0, helpers_1.ok)(lines.join('\n'));
376
+ }
377
+ catch (err) {
378
+ return (0, helpers_1.fail)(`Failed to load lineup: ${(0, helpers_1.formatError)(err)}`);
379
+ }
380
+ });
381
+ }
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Client, WorkflowHandle } from '@temporalio/client';
3
+ import { Config } from '../config';
4
+ export declare function registerMigrateTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string, handle: WorkflowHandle): void;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerMigrateTool = registerMigrateTool;
4
+ /**
5
+ * `migrate` — sugar for `restart --host=<h>` per design §9.6.
6
+ *
7
+ * Identical semantics to `restart` with the `host` argument required. Separate
8
+ * verb for UX clarity: "migrate to host X" vs "restart this session". Both
9
+ * names route through the same `RestartOutboxEntry` outbox path so the §8.2
10
+ * algorithm is implemented once in `deliverRestart` (QA B3).
11
+ *
12
+ * PR-F wires the `confirmStealFromHost` guard (design §16.5 Option B) via the
13
+ * shared `enforceYesStealGuard` helper from `restart.ts`. When the caller passes
14
+ * `force: true` AND the target's current attachment is on a different host,
15
+ * `confirmStealFromHost` must name that hostname exactly.
16
+ */
17
+ const zod_1 = require("zod");
18
+ const signals_1 = require("../workflows/signals");
19
+ const helpers_1 = require("./helpers");
20
+ const restart_1 = require("./restart");
21
+ const validation_1 = require("../utils/validation");
22
+ function registerMigrateTool(server, client, config, getPlayerId, handle) {
23
+ (0, helpers_1.defineTool)(server, 'migrate', 'Migrate a session to a different host — sugar for `restart` with a required `host`. Reaps the current attachment, claims fresh on the target host, spawns a new adapter. Cross-host routing (per-host task queues) is honored automatically. When `force=true` AND the target is currently on a different host, `confirmStealFromHost` must match that hostname (design §16.5).', {
24
+ playerId: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).describe('The player name to migrate'),
25
+ host: zod_1.z.string().min(1).describe('Target hostname — required'),
26
+ fresh: zod_1.z.boolean().optional().describe('Skip context replay (default false)'),
27
+ force: zod_1.z.boolean().optional().describe('Steal a live attachment via forceDetach (default false)'),
28
+ contextMessages: zod_1.z.number().min(0).max(validation_1.RESTART_CONTEXT_MESSAGES_MAX).optional().describe('Number of recent messages to include in context (default 10)'),
29
+ confirmStealFromHost: zod_1.z.string().optional().describe('Required when `force=true` and the target\'s current attachment is on a different host (design §16.5 Option B).'),
30
+ }, async (args) => {
31
+ const input = args;
32
+ const nameError = (0, validation_1.validatePlayerName)(input.playerId);
33
+ if (nameError)
34
+ return (0, helpers_1.fail)(nameError);
35
+ if (!input.host || !input.host.trim()) {
36
+ return (0, helpers_1.fail)('`host` is required for migrate. Use `restart` (without host) to restart on the session\'s current host.');
37
+ }
38
+ // Shared cross-host guard with `restart` — same rules, same copy-paste
39
+ // error messages (§16.5).
40
+ const guardError = await (0, restart_1.enforceYesStealGuard)(client, config.ensemble, input.playerId, input);
41
+ if (guardError)
42
+ return (0, helpers_1.fail)(guardError);
43
+ try {
44
+ const entry = {
45
+ type: 'restart',
46
+ targetPlayerId: input.playerId,
47
+ invokerPlayerId: getPlayerId(),
48
+ host: input.host,
49
+ ...(input.fresh !== undefined ? { fresh: input.fresh } : {}),
50
+ ...(input.force !== undefined ? { force: input.force } : {}),
51
+ ...(input.contextMessages !== undefined ? { contextMessages: input.contextMessages } : {}),
52
+ };
53
+ const entryId = await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
54
+ return (0, helpers_1.ok)(`Migrate queued for **${input.playerId}** → ${input.host}. (outbox: ${entryId})`);
55
+ }
56
+ catch (err) {
57
+ return (0, helpers_1.fail)(`Failed to migrate: ${(0, helpers_1.formatError)(err)}`);
58
+ }
59
+ });
60
+ }
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Client } from '@temporalio/client';
3
+ import { Config } from '../config';
4
+ export declare function registerPauseEnsembleTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPauseEnsembleTool = registerPauseEnsembleTool;
4
+ const config_1 = require("../config");
5
+ const resolve_1 = require("../activities/resolve");
6
+ const helpers_1 = require("./helpers");
7
+ const log = (...args) => console.error('[claude-tempo:pause]', ...args);
8
+ function registerPauseEnsembleTool(server, client, config, getPlayerId) {
9
+ (0, helpers_1.defineTool)(server, 'pause_ensemble', 'Pause all sessions in the ensemble — locks outbox dispatch and pauses the scheduler. Stop commands still go through. Use resume_ensemble to unpause.', {}, async () => {
10
+ try {
11
+ const results = [];
12
+ const errors = [];
13
+ // 1. Signal maestro with paused state (ground truth)
14
+ try {
15
+ const maestroId = (0, config_1.maestroWorkflowId)(config.ensemble);
16
+ const maestroHandle = client.workflow.getHandle(maestroId);
17
+ await maestroHandle.signal('maestroSetPaused', true);
18
+ results.push('maestro paused');
19
+ }
20
+ catch {
21
+ // Maestro may not be running
22
+ }
23
+ // 2. Signal all active sessions
24
+ const sessions = await (0, resolve_1.scanEnsembleSessions)(client, config.ensemble);
25
+ let sessionCount = 0;
26
+ for (const session of sessions) {
27
+ try {
28
+ const sessionHandle = client.workflow.getHandle(session.workflowId);
29
+ await sessionHandle.signal('setPaused', true);
30
+ sessionCount++;
31
+ }
32
+ catch (err) {
33
+ errors.push(`${session.playerId}: ${(0, helpers_1.formatError)(err)}`);
34
+ }
35
+ }
36
+ results.push(`${sessionCount} session(s) paused`);
37
+ // 3. Signal scheduler
38
+ try {
39
+ const schedulerId = (0, config_1.schedulerWorkflowId)(config.ensemble);
40
+ const schedulerHandle = client.workflow.getHandle(schedulerId);
41
+ await schedulerHandle.signal('setSchedulerPaused', true);
42
+ results.push('scheduler paused');
43
+ }
44
+ catch {
45
+ // Scheduler may not be running
46
+ }
47
+ const lines = [`Ensemble **${config.ensemble}** paused.`, results.join(', ')];
48
+ if (errors.length > 0) {
49
+ lines.push(`Errors:\n${errors.map((e) => ` - ${e}`).join('\n')}`);
50
+ }
51
+ log(`Paused ensemble "${config.ensemble}" by ${getPlayerId()}`);
52
+ return (0, helpers_1.ok)(lines.join('\n'));
53
+ }
54
+ catch (err) {
55
+ return (0, helpers_1.fail)(`Failed to pause ensemble: ${(0, helpers_1.formatError)(err)}`);
56
+ }
57
+ });
58
+ }
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Client } from '@temporalio/client';
3
+ import { Config } from '../config';
4
+ export declare function registerPauseTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPauseTool = registerPauseTool;
4
+ const signals_1 = require("../workflows/signals");
5
+ const helpers_1 = require("./helpers");
6
+ const ensemble_ops_1 = require("../utils/ensemble-ops");
7
+ const log = (...args) => console.error('[agent-tempo:pause]', ...args);
8
+ function registerPauseTool(server, client, config, getPlayerId) {
9
+ (0, helpers_1.defineTool)(server, 'pause', 'Pause all sessions in the ensemble — locks outbox dispatch and pauses the scheduler. Stop commands still go through. Use `play` to unpause.', {}, async () => {
10
+ try {
11
+ const [toggle, sessions] = await Promise.all([
12
+ (0, ensemble_ops_1.pauseMaestroAndScheduler)(client, config.ensemble),
13
+ (0, ensemble_ops_1.signalAllSessions)(client, config.ensemble, signals_1.setPausedSignal.name, true),
14
+ ]);
15
+ const bits = [
16
+ `Ensemble **${config.ensemble}** paused.`,
17
+ `${sessions.sent} session(s) paused`,
18
+ ];
19
+ if (toggle.maestro)
20
+ bits.push('maestro paused');
21
+ if (toggle.scheduler)
22
+ bits.push('scheduler paused');
23
+ if (sessions.failed > 0) {
24
+ const errs = sessions.perSession
25
+ .filter((p) => p.outcome === 'failed')
26
+ .map((p) => ` - ${p.playerId}: ${'error' in p ? p.error : ''}`);
27
+ bits.push(`Errors:\n${errs.join('\n')}`);
28
+ }
29
+ log(`Paused ensemble "${config.ensemble}" by ${getPlayerId()}`);
30
+ return (0, helpers_1.ok)(bits.join('\n'));
31
+ }
32
+ catch (err) {
33
+ return (0, helpers_1.fail)(`Failed to pause ensemble: ${(0, helpers_1.formatError)(err)}`);
34
+ }
35
+ });
36
+ }
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Client } from '@temporalio/client';
3
+ import { Config } from '../config';
4
+ export declare function registerPlayTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPlayTool = registerPlayTool;
4
+ const zod_1 = require("zod");
5
+ const signals_1 = require("../workflows/signals");
6
+ const helpers_1 = require("./helpers");
7
+ const ensemble_ops_1 = require("../utils/ensemble-ops");
8
+ const log = (...args) => console.error('[agent-tempo:play]', ...args);
9
+ function registerPlayTool(server, client, config, getPlayerId) {
10
+ (0, helpers_1.defineTool)(server, 'play', 'Resume all paused sessions in the ensemble — unlocks outbox dispatch and resumes the scheduler. Buffered outbox entries will be dispatched. Pass `release: true` to also release any held sessions (deliver deferred task messages and unlock their outboxes) in the same call.', {
11
+ release: zod_1.z.boolean().optional().describe('Also release any held sessions (deliver deferred task messages and unlock outboxes). Safe to call when no sessions are held — it is a no-op on those. Default: false.'),
12
+ }, async (args) => {
13
+ const release = args.release === true;
14
+ try {
15
+ // Unpause everything in parallel: maestro + scheduler + every session.
16
+ const [toggle, sessions] = await Promise.all([
17
+ (0, ensemble_ops_1.unpauseMaestroAndScheduler)(client, config.ensemble),
18
+ (0, ensemble_ops_1.signalAllSessions)(client, config.ensemble, signals_1.setPausedSignal.name, false),
19
+ ]);
20
+ // `releaseHeld` is idempotent — safe to fan out to everyone. Keep it
21
+ // AFTER the unpause so sessions aren't releasing while paused.
22
+ let releasedCount = 0;
23
+ const releaseErrors = [];
24
+ if (release) {
25
+ const released = await (0, ensemble_ops_1.signalAllSessions)(client, config.ensemble,
26
+ // typed constant → `'releaseHeld'` string name, matches the session handler
27
+ signals_1.releaseHeldSignal.name, undefined);
28
+ releasedCount = released.sent;
29
+ for (const p of released.perSession) {
30
+ if (p.outcome === 'failed')
31
+ releaseErrors.push(`${p.playerId} release: ${'error' in p ? p.error : ''}`);
32
+ }
33
+ }
34
+ const bits = [
35
+ `Ensemble **${config.ensemble}** resumed.`,
36
+ `${sessions.sent} session(s) resumed`,
37
+ ];
38
+ if (release)
39
+ bits.push(`${releasedCount} session(s) signalled for release`);
40
+ if (toggle.maestro)
41
+ bits.push('maestro resumed');
42
+ if (toggle.scheduler)
43
+ bits.push('scheduler resumed');
44
+ const failedUnpause = sessions.perSession
45
+ .filter((p) => p.outcome === 'failed')
46
+ .map((p) => ` - ${p.playerId}: ${'error' in p ? p.error : ''}`);
47
+ const allErrors = [...failedUnpause, ...releaseErrors.map((e) => ` - ${e}`)];
48
+ if (allErrors.length > 0)
49
+ bits.push(`Errors:\n${allErrors.join('\n')}`);
50
+ log(`Resumed ensemble "${config.ensemble}" by ${getPlayerId()}${release ? ' (with release)' : ''}`);
51
+ return (0, helpers_1.ok)(bits.join('\n'));
52
+ }
53
+ catch (err) {
54
+ return (0, helpers_1.fail)(`Failed to resume ensemble: ${(0, helpers_1.formatError)(err)}`);
55
+ }
56
+ });
57
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { WorkflowHandle } from '@temporalio/client';
3
+ export declare function registerQualityGateTool(server: McpServer, handle: WorkflowHandle, getPlayerId: () => string): void;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerQualityGateTool = registerQualityGateTool;
4
+ const zod_1 = require("zod");
5
+ const helpers_1 = require("./helpers");
6
+ const validation_1 = require("../utils/validation");
7
+ function registerQualityGateTool(server, handle, getPlayerId) {
8
+ (0, helpers_1.defineTool)(server, 'quality_gate', 'Define or replace a quality gate for a task. Each gate has a list of criteria that must pass before the task is considered complete. Conductor only.', {
9
+ task: zod_1.z.string().max(validation_1.GATE_TASK_MAX).describe('Unique task name for this gate (e.g. "pr-review", "deploy-staging")'),
10
+ criteria: zod_1.z.array(zod_1.z.string().max(validation_1.GATE_CRITERION_TEXT_MAX)).min(1).max(validation_1.GATE_CRITERIA_MAX).describe('List of criteria that must be evaluated (e.g. ["Tests pass", "No lint errors", "Code reviewed"])'),
11
+ }, async (args) => {
12
+ const { task, criteria } = args;
13
+ try {
14
+ await handle.signal('setQualityGate', {
15
+ task,
16
+ criteria,
17
+ createdBy: getPlayerId(),
18
+ });
19
+ const lines = criteria.map((c, i) => ` ${i}. [ ] ${c}`);
20
+ return (0, helpers_1.ok)(`Quality gate **${task}** set with ${criteria.length} criteria:\n${lines.join('\n')}`);
21
+ }
22
+ catch (err) {
23
+ return (0, helpers_1.fail)(`Failed to set quality gate: ${(0, helpers_1.formatError)(err)}`);
24
+ }
25
+ });
26
+ }