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,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerReportTool = registerReportTool;
4
+ const zod_1 = require("zod");
5
+ const signals_1 = require("../workflows/signals");
6
+ const helpers_1 = require("./helpers");
7
+ const validation_1 = require("../utils/validation");
8
+ function registerReportTool(server, handle) {
9
+ (0, helpers_1.defineTool)(server, 'report', 'Send an update to the conductor. Use this to report task completion, blockers, or questions. No-op if no conductor is running.', {
10
+ text: zod_1.z.string().max(validation_1.MESSAGE_MAX).describe('The report content'),
11
+ type: zod_1.z.enum(['result', 'blocker', 'question', 'update']).optional()
12
+ .describe('Type of report: "result" (default, task done), "blocker" (stuck), "question" (need input), "update" (progress update, still working)'),
13
+ }, async (args) => {
14
+ const text = args.text;
15
+ const type = (args.type ?? 'result');
16
+ try {
17
+ const entry = {
18
+ type: 'report',
19
+ text,
20
+ reportType: type,
21
+ };
22
+ const entryId = await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
23
+ return (0, helpers_1.ok)(`Report sent to conductor: [${type}] ${text} (outbox: ${entryId})`);
24
+ }
25
+ catch (err) {
26
+ return (0, helpers_1.fail)(`Failed to send report: ${(0, helpers_1.formatError)(err)}`);
27
+ }
28
+ });
29
+ }
@@ -0,0 +1 @@
1
+ export { resolveSession } from '../activities/resolve';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSession = void 0;
4
+ // Re-export from the canonical location.
5
+ // Tools and activities share the same resolveSession implementation.
6
+ var resolve_1 = require("../activities/resolve");
7
+ Object.defineProperty(exports, "resolveSession", { enumerable: true, get: function () { return resolve_1.resolveSession; } });
@@ -0,0 +1,35 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { Client, WorkflowHandle } from '@temporalio/client';
3
+ import { Config } from '../config';
4
+ export interface RestartToolArgs {
5
+ playerId: string;
6
+ host?: string;
7
+ fresh?: boolean;
8
+ force?: boolean;
9
+ contextMessages?: number;
10
+ confirmStealFromHost?: string;
11
+ /** #334 PR-2 — see {@link RestartOutboxEntry.loadFromState}. */
12
+ loadFromState?: boolean | string;
13
+ /** #334 PR-2 — see {@link RestartOutboxEntry.transcript}. */
14
+ transcript?: 'suppress' | 'replay';
15
+ }
16
+ /**
17
+ * Shared `--yes-steal` guard (design §16.5 Option B).
18
+ *
19
+ * Returns `null` if the call is allowed, or a user-facing error message
20
+ * (matching the brief's copy-paste-friendly format) if not. Exported for
21
+ * the `migrate` CLI command and unit tests.
22
+ *
23
+ * Only fires when BOTH:
24
+ * - caller passed `force: true`
25
+ * - target session currently has an attachment on a host other than ours
26
+ *
27
+ * Graceful (non-force) restarts always pass. Non-cross-host force restarts
28
+ * always pass. Missing `confirmStealFromHost` + mismatched
29
+ * `confirmStealFromHost` are both rejected with the same copy-paste format.
30
+ */
31
+ export declare function enforceYesStealGuard(client: Client, ensemble: string, playerId: string, args: {
32
+ force?: boolean;
33
+ confirmStealFromHost?: string;
34
+ }, localHostname?: string): Promise<string | null>;
35
+ export declare function registerRestartTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string, handle: WorkflowHandle): void;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enforceYesStealGuard = enforceYesStealGuard;
4
+ exports.registerRestartTool = registerRestartTool;
5
+ /**
6
+ * `restart` — reap the current attachment, claim a fresh one, spawn a new adapter.
7
+ *
8
+ * QA B3: enqueues a `RestartOutboxEntry` on the caller's workflow outbox
9
+ * rather than running the multi-step §8.2 algorithm inline from tool code.
10
+ * The session workflow's dispatch loop runs the `deliverRestart` activity on
11
+ * the target, which owns the full algorithm:
12
+ *
13
+ * graceful `requestDetach` → re-query phase → optional `forceDetach`
14
+ * → `claimAttachment` → optional `receiveMessage` context replay
15
+ * → `enqueueSpawn` on the target's outbox
16
+ *
17
+ * PR-F adds two cross-host pieces:
18
+ *
19
+ * 1. `host` param — routes the eventual `spawnProcess` to the
20
+ * `agent-tempo-{host}` task queue. Threaded through the existing
21
+ * `RestartOutboxEntry.host` → `deliverRestart` activity → `enqueueSpawn`
22
+ * update → `SpawnOutboxEntry.targetHostname` → `case 'spawn':`
23
+ * dispatcher → `getSpawnProxy(host)` → per-host task queue. All the
24
+ * plumbing already exists; this PR just surfaces the input.
25
+ *
26
+ * 2. `--yes-steal` guard (design §16.5 Option B) — when `force: true`
27
+ * AND the target's current attachment is on a different host, the
28
+ * caller must pass `confirmStealFromHost` matching that hostname.
29
+ * Client-side only; the workflow trusts the caller (P1 gotcha).
30
+ *
31
+ * Durability bonus: mid-algorithm failures surface as ApplicationFailures
32
+ * and retry per the activity's policy. Design §8.2.
33
+ */
34
+ const zod_1 = require("zod");
35
+ const os_1 = require("os");
36
+ const signals_1 = require("../workflows/signals");
37
+ const resolve_1 = require("./resolve");
38
+ const helpers_1 = require("./helpers");
39
+ const validation_1 = require("../utils/validation");
40
+ const DEFAULT_CONTEXT_MESSAGES = 10;
41
+ /**
42
+ * Shared `--yes-steal` guard (design §16.5 Option B).
43
+ *
44
+ * Returns `null` if the call is allowed, or a user-facing error message
45
+ * (matching the brief's copy-paste-friendly format) if not. Exported for
46
+ * the `migrate` CLI command and unit tests.
47
+ *
48
+ * Only fires when BOTH:
49
+ * - caller passed `force: true`
50
+ * - target session currently has an attachment on a host other than ours
51
+ *
52
+ * Graceful (non-force) restarts always pass. Non-cross-host force restarts
53
+ * always pass. Missing `confirmStealFromHost` + mismatched
54
+ * `confirmStealFromHost` are both rejected with the same copy-paste format.
55
+ */
56
+ async function enforceYesStealGuard(client, ensemble, playerId, args, localHostname = (0, os_1.hostname)()) {
57
+ if (!args.force)
58
+ return null;
59
+ const resolved = await (0, resolve_1.resolveSession)(client, ensemble, playerId);
60
+ if (!resolved)
61
+ return null; // No target — downstream enqueue will handle the error.
62
+ let info;
63
+ try {
64
+ info = await resolved.query(signals_1.attachmentInfoQuery);
65
+ }
66
+ catch {
67
+ // If we can't read the phase, let the downstream algorithm handle the
68
+ // state. Not our job to synthesize cross-host errors here.
69
+ return null;
70
+ }
71
+ const currentHost = info.currentAttachment?.hostname;
72
+ if (!currentHost || currentHost === localHostname)
73
+ return null;
74
+ // Cross-host force-restart detected — demand --yes-steal match.
75
+ if (!args.confirmStealFromHost) {
76
+ return (`session "${playerId}" is attached to host "${currentHost}". ` +
77
+ `To force-restart from there, pass confirmStealFromHost: "${currentHost}". ` +
78
+ `This safety flag prevents accidental cross-host session takeover.`);
79
+ }
80
+ if (args.confirmStealFromHost !== currentHost) {
81
+ return (`confirmStealFromHost mismatch: session "${playerId}" is on ` +
82
+ `"${currentHost}", not "${args.confirmStealFromHost}". ` +
83
+ `Re-run with confirmStealFromHost: "${currentHost}".`);
84
+ }
85
+ return null;
86
+ }
87
+ function registerRestartTool(server, client, config, getPlayerId, handle) {
88
+ (0, helpers_1.defineTool)(server, 'restart', 'Restart a session — reap the current attachment (gracefully, or with force=true), claim a fresh attachment, spawn a new adapter, and optionally replay recent context. Replaces `encore`, `recruit --force`, and `stop`-then-`recruit`. Pass `host` to restart on a different machine; when `force=true` AND the target is currently on a different host, pass `confirmStealFromHost` matching that hostname (design §16.5). Pass `loadFromState` to seed the restarted session from a saved-state slot (#334) instead of (or alongside) transcript replay.', {
89
+ playerId: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).describe('The player name to restart'),
90
+ host: zod_1.z.string().optional().describe('Target host for the new attachment (defaults to the session\'s preferredHost or last-known hostname). When set, the spawn is routed to the per-host task queue `agent-tempo-{host}`.'),
91
+ fresh: zod_1.z.boolean().optional().describe('Skip context replay — spawn a clean slate (default false)'),
92
+ force: zod_1.z.boolean().optional().describe('Steal a live attachment via forceDetach (default false; graceful detach is tried first regardless)'),
93
+ 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 ${DEFAULT_CONTEXT_MESSAGES}, max ${validation_1.RESTART_CONTEXT_MESSAGES_MAX})`),
94
+ confirmStealFromHost: zod_1.z.string().optional().describe('Required when `force=true` and the target\'s current attachment is on a different host. Must match the hostname currently holding the attachment (design §16.5 Option B).'),
95
+ // #334 PR-2 — saved-state seed integration.
96
+ loadFromState: zod_1.z.union([
97
+ zod_1.z.boolean(),
98
+ zod_1.z.string().regex(validation_1.PLAYER_STATE_KEY_REGEX).max(validation_1.PLAYER_STATE_KEY_MAX),
99
+ ]).optional().describe(`Seed the restarted session with a saved-state slot. \`true\` resolves to the default key "${validation_1.PLAYER_STATE_DEFAULT_KEY}"; a string names a specific slot. By default, transcript replay is suppressed when this is set — pass \`transcript: 'replay'\` to stack both. Falls back to transcript replay if the slot is empty.`),
100
+ transcript: zod_1.z.enum(['suppress', 'replay']).optional().describe('When `loadFromState` is set, controls transcript-replay interaction: `suppress` (default) seeds only the saved state; `replay` seeds the saved state and then replays the recent transcript on top of it. Ignored when `loadFromState` is absent.'),
101
+ }, async (args) => {
102
+ const input = args;
103
+ const nameError = (0, validation_1.validatePlayerName)(input.playerId);
104
+ if (nameError)
105
+ return (0, helpers_1.fail)(nameError);
106
+ // Client-side --yes-steal guard (§16.5). Cross-host force-restart
107
+ // requires an explicit confirmStealFromHost matching the current holder.
108
+ const guardError = await enforceYesStealGuard(client, config.ensemble, input.playerId, input);
109
+ if (guardError)
110
+ return (0, helpers_1.fail)(guardError);
111
+ try {
112
+ const entry = {
113
+ type: 'restart',
114
+ targetPlayerId: input.playerId,
115
+ invokerPlayerId: getPlayerId(),
116
+ ...(input.host !== undefined ? { host: input.host } : {}),
117
+ ...(input.fresh !== undefined ? { fresh: input.fresh } : {}),
118
+ ...(input.force !== undefined ? { force: input.force } : {}),
119
+ ...(input.contextMessages !== undefined ? { contextMessages: input.contextMessages } : {}),
120
+ ...(input.loadFromState !== undefined ? { loadFromState: input.loadFromState } : {}),
121
+ ...(input.transcript !== undefined ? { transcript: input.transcript } : {}),
122
+ };
123
+ const entryId = await handle.executeUpdate(signals_1.submitOutboxUpdate, { args: [entry] });
124
+ return (0, helpers_1.ok)(`Restart queued for **${input.playerId}**${input.host ? ` on ${input.host}` : ''}` +
125
+ `${input.fresh ? ' (fresh)' : ''}${input.force ? ' (force)' : ''}. (outbox: ${entryId})`);
126
+ }
127
+ catch (err) {
128
+ return (0, helpers_1.fail)(`Failed to restart: ${(0, helpers_1.formatError)(err)}`);
129
+ }
130
+ });
131
+ }
@@ -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 registerRestoreTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerRestoreTool = registerRestoreTool;
4
+ /**
5
+ * `restore` — ensemble-wide revive (#287).
6
+ *
7
+ * Counterpart to `shutdown`:
8
+ * 1. Reattach every local orphan (delegates to the shared
9
+ * `restoreOrphansOnce` helper from `src/reconcile/orphans.ts`, which
10
+ * is the same code the daemon runs at boot and the CLI resume flow
11
+ * runs on `up` option 2 / `conduct --resume`).
12
+ * 2. Unpause the maestro + scheduler so new work flows again.
13
+ * 3. Fan out `setPaused=false` to every session so per-session outbox
14
+ * dispatchers (gated on `!paused`) start delivering again. Mirrors
15
+ * `play()` and `TempoClient.restore()` — the maestro/scheduler hub
16
+ * toggle is necessary but not sufficient: a session that was paused
17
+ * via `/pause` keeps its own `paused=true` flag and the outbox loop
18
+ * `canDispatch = !outboxLocked && !paused && hasPendingOutbox()`
19
+ * silently swallows messages until the per-session flag clears.
20
+ *
21
+ * Scope note: conductor-auto-spawn is intentionally NOT handled here
22
+ * (#287 product decision). MCP tools run inside the daemon worker; opening
23
+ * a GUI terminal from that context is platform-fragile and surprising for
24
+ * headless / programmatic callers. The CLI `restore` surface (S4 of #285)
25
+ * owns terminal spawning where a TTY context is available.
26
+ */
27
+ const os_1 = require("os");
28
+ const zod_1 = require("zod");
29
+ const orphans_1 = require("../reconcile/orphans");
30
+ const signals_1 = require("../workflows/signals");
31
+ const helpers_1 = require("./helpers");
32
+ const ensemble_ops_1 = require("../utils/ensemble-ops");
33
+ const log = (...args) => console.error('[agent-tempo:restore]', ...args);
34
+ function registerRestoreTool(server, client, config, getPlayerId) {
35
+ (0, helpers_1.defineTool)(server, 'restore', 'Revive the ensemble after `shutdown`: reattach orphaned sessions and unpause the maestro + scheduler. Defaults to scanning the local host; pass `hostname` to target a remote machine in distributed setups (per-host task queues). Does NOT spawn a conductor terminal — use the CLI for that.', {
36
+ // #306 follow-up: cross-host restore. The default (omitted) preserves
37
+ // the original behavior — scan the local daemon's host. When supplied,
38
+ // we route the orphan-visibility query against the named host's
39
+ // `AgentTempoAttachedHost`/`AgentTempoHostname` search attributes,
40
+ // so an operator on host A can revive sessions parked on host B.
41
+ // Surfaced from my own #306 review (regression risk #2): "MCP
42
+ // restore hard-codes hostname: osHostname() — won't see orphans on
43
+ // other hosts in distributed setups."
44
+ hostname: zod_1.z.string().min(1).max(253).optional().describe('Target host whose orphans should be restored. Defaults to the local OS hostname. Use this when the conductor / TUI is on a different machine than the workers that owned the parked sessions.'),
45
+ }, async (args) => {
46
+ const { hostname: explicitHostname } = args;
47
+ const targetHostname = explicitHostname ?? (0, os_1.hostname)();
48
+ try {
49
+ let summary;
50
+ try {
51
+ summary = await (0, orphans_1.restoreOrphansOnce)(client, {
52
+ hostname: targetHostname,
53
+ invokerPlayerId: getPlayerId(),
54
+ policy: 'auto',
55
+ // #306: narrow to detached-only so a live attached/processing
56
+ // session is never flagged as an orphan by user-invoked
57
+ // `/restore`. Daemon reconcile-on-boot + CLI `up --resume`
58
+ // keep the broad live-phase default (no PID memory after
59
+ // crash → must treat every live phase as presumed orphan).
60
+ phases: ['detached'],
61
+ }, log);
62
+ }
63
+ catch (err) {
64
+ return (0, helpers_1.fail)(`Failed to scan for orphans: ${(0, helpers_1.formatError)(err)}`);
65
+ }
66
+ // Maestro/scheduler hub unpause + per-session `setPaused=false`
67
+ // fan-out run in parallel — independent calls and a slow session
68
+ // shouldn't gate the hub toggle (or vice-versa).
69
+ const [toggle, sessions] = await Promise.all([
70
+ (0, ensemble_ops_1.unpauseMaestroAndScheduler)(client, config.ensemble),
71
+ (0, ensemble_ops_1.signalAllSessions)(client, config.ensemble, signals_1.setPausedSignal.name, false),
72
+ ]);
73
+ const hostSuffix = explicitHostname !== undefined
74
+ ? ` (host: ${explicitHostname})`
75
+ : '';
76
+ const lines = [
77
+ `Ensemble **${config.ensemble}** restored${hostSuffix}.`,
78
+ `${summary.reattached} reattached, ${summary.skipped} skipped, ${summary.failed} failed`,
79
+ ];
80
+ if (summary.details.length > 0) {
81
+ lines.push(...summary.details.map((d) => ` - ${d.playerId} (${d.ensemble}): ${(0, orphans_1.formatRestoreOutcome)(d.outcome)}`));
82
+ }
83
+ if (sessions.sent > 0) {
84
+ lines.push(`${sessions.sent} session(s) resumed`);
85
+ }
86
+ const unpausedBits = [];
87
+ if (toggle.maestro)
88
+ unpausedBits.push('maestro');
89
+ if (toggle.scheduler)
90
+ unpausedBits.push('scheduler');
91
+ if (unpausedBits.length > 0)
92
+ lines.push(`Unpaused: ${unpausedBits.join(', ')}`);
93
+ if (sessions.failed > 0) {
94
+ const errs = sessions.perSession
95
+ .filter((p) => p.outcome === 'failed')
96
+ .map((p) => ` - ${p.playerId}: ${'error' in p ? p.error : ''}`);
97
+ lines.push(`Errors:\n${errs.join('\n')}`);
98
+ }
99
+ log(`Restore by ${getPlayerId()} in "${config.ensemble}" on host "${targetHostname}": ` +
100
+ `${summary.reattached}/${summary.skipped}/${summary.failed}`);
101
+ return (0, helpers_1.ok)(lines.join('\n'));
102
+ }
103
+ catch (err) {
104
+ return (0, helpers_1.fail)(`Failed to restore ensemble: ${(0, helpers_1.formatError)(err)}`);
105
+ }
106
+ });
107
+ }
@@ -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 registerResumeEnsembleTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerResumeEnsembleTool = registerResumeEnsembleTool;
4
+ const zod_1 = require("zod");
5
+ const config_1 = require("../config");
6
+ const resolve_1 = require("../activities/resolve");
7
+ const signals_1 = require("../workflows/signals");
8
+ const helpers_1 = require("./helpers");
9
+ const log = (...args) => console.error('[claude-tempo:resume]', ...args);
10
+ function registerResumeEnsembleTool(server, client, config, getPlayerId) {
11
+ (0, helpers_1.defineTool)(server, 'resume_ensemble', '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.', {
12
+ 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.'),
13
+ }, async (args) => {
14
+ const release = args.release === true;
15
+ try {
16
+ const results = [];
17
+ const errors = [];
18
+ // 1. Signal maestro with unpaused state (ground truth)
19
+ try {
20
+ const maestroId = (0, config_1.maestroWorkflowId)(config.ensemble);
21
+ const maestroHandle = client.workflow.getHandle(maestroId);
22
+ await maestroHandle.signal('maestroSetPaused', false);
23
+ results.push('maestro resumed');
24
+ }
25
+ catch {
26
+ // Maestro may not be running
27
+ }
28
+ // 2. Signal all active sessions — unpause, and release held ones if opted in.
29
+ // `releaseHeld` is idempotent on sessions that aren't holding (no heldMessage,
30
+ // outboxLocked: false already), so it's safe to fan out unconditionally when
31
+ // `release: true`. See `src/workflows/session.ts` releaseHeldSignal handler.
32
+ const sessions = await (0, resolve_1.scanEnsembleSessions)(client, config.ensemble);
33
+ let sessionCount = 0;
34
+ let releasedCount = 0;
35
+ for (const session of sessions) {
36
+ try {
37
+ const sessionHandle = client.workflow.getHandle(session.workflowId);
38
+ await sessionHandle.signal('setPaused', false);
39
+ sessionCount++;
40
+ if (release) {
41
+ try {
42
+ await sessionHandle.signal(signals_1.releaseHeldSignal);
43
+ releasedCount++;
44
+ }
45
+ catch (err) {
46
+ errors.push(`${session.playerId} release: ${(0, helpers_1.formatError)(err)}`);
47
+ }
48
+ }
49
+ }
50
+ catch (err) {
51
+ errors.push(`${session.playerId}: ${(0, helpers_1.formatError)(err)}`);
52
+ }
53
+ }
54
+ results.push(`${sessionCount} session(s) resumed`);
55
+ if (release) {
56
+ results.push(`${releasedCount} session(s) signalled for release`);
57
+ }
58
+ // 3. Signal scheduler
59
+ try {
60
+ const schedulerId = (0, config_1.schedulerWorkflowId)(config.ensemble);
61
+ const schedulerHandle = client.workflow.getHandle(schedulerId);
62
+ await schedulerHandle.signal('setSchedulerPaused', false);
63
+ results.push('scheduler resumed');
64
+ }
65
+ catch {
66
+ // Scheduler may not be running
67
+ }
68
+ const lines = [`Ensemble **${config.ensemble}** resumed.`, results.join(', ')];
69
+ if (errors.length > 0) {
70
+ lines.push(`Errors:\n${errors.map((e) => ` - ${e}`).join('\n')}`);
71
+ }
72
+ log(`Resumed ensemble "${config.ensemble}" by ${getPlayerId()}${release ? ' (with release)' : ''}`);
73
+ return (0, helpers_1.ok)(lines.join('\n'));
74
+ }
75
+ catch (err) {
76
+ return (0, helpers_1.fail)(`Failed to resume ensemble: ${(0, helpers_1.formatError)(err)}`);
77
+ }
78
+ });
79
+ }
@@ -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 registerSaveLineupTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string, isConductor: boolean): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerSaveLineupTool = registerSaveLineupTool;
4
+ const zod_1 = require("zod");
5
+ const saver_1 = require("../ensemble/saver");
6
+ const safe_path_1 = require("../utils/safe-path");
7
+ const helpers_1 = require("./helpers");
8
+ const validation_1 = require("../utils/validation");
9
+ const log = (...args) => console.error('[agent-tempo:save-lineup]', ...args);
10
+ function registerSaveLineupTool(server, client, config, getPlayerId, isConductor) {
11
+ (0, helpers_1.defineTool)(server, 'save_lineup', 'Save the current ensemble state as a YAML lineup. Only available to the conductor.', {
12
+ name: zod_1.z.string().max(validation_1.PLAYER_NAME_MAX).optional().describe('Lineup name (defaults to ensemble name)'),
13
+ path: zod_1.z.string().max(validation_1.PATH_MAX).optional().describe('Explicit file path to save to'),
14
+ }, async (args) => {
15
+ if (!isConductor) {
16
+ return (0, helpers_1.fail)('Only the conductor can save ensemble lineups.');
17
+ }
18
+ const lineupName = args.name;
19
+ const filePath = args.path;
20
+ try {
21
+ // Validate user-supplied path if provided
22
+ let validatedPath = filePath;
23
+ if (validatedPath) {
24
+ validatedPath = (0, safe_path_1.safeLineupPath)(validatedPath, process.cwd());
25
+ }
26
+ // Pass lineupName as optional name override for the output filename.
27
+ // If no name or path is provided, saveLineup defaults to ensemble name.
28
+ const outputPath = await (0, saver_1.saveLineup)(client, config.ensemble, validatedPath, lineupName);
29
+ log(`Saved lineup to ${outputPath}`);
30
+ return (0, helpers_1.ok)(`Ensemble lineup saved to **${outputPath}**.`);
31
+ }
32
+ catch (err) {
33
+ return (0, helpers_1.fail)(`Failed to save ensemble: ${(0, helpers_1.formatError)(err)}`);
34
+ }
35
+ });
36
+ }
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { WorkflowHandle } from '@temporalio/client';
3
+ export declare function registerSaveStateTool(server: McpServer, handle: WorkflowHandle, getPlayerId: () => string): void;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerSaveStateTool = registerSaveStateTool;
4
+ /**
5
+ * `save_state` — write a curated artifact to one of the calling player's
6
+ * saveable-state slots (#334 PR-1, ADR 0011).
7
+ *
8
+ * Owner-only by structure: there is no `playerId` arg — the tool always
9
+ * writes through the calling player's own session-workflow handle, so
10
+ * the workflow doesn't need an authorisation layer. The `savedBy` field
11
+ * captures the calling player's id as the audit identity.
12
+ *
13
+ * The tool docstring nudges the LLM toward a markdown structure
14
+ * (Current task / Findings / Next steps / Open questions) but the schema
15
+ * itself is opaque — no enforced typing.
16
+ */
17
+ const zod_1 = require("zod");
18
+ const signals_1 = require("../workflows/signals");
19
+ const helpers_1 = require("./helpers");
20
+ const validation_1 = require("../utils/validation");
21
+ function registerSaveStateTool(server, handle, getPlayerId) {
22
+ (0, helpers_1.defineTool)(server, 'save_state', `Save curated state for yourself into a named slot — a peer can later read it via \`fetch_state\`, and a future restart can seed itself from this artifact instead of replaying the transcript.
23
+
24
+ Recommended structure (markdown, not enforced):
25
+
26
+ ## Current task
27
+ ...
28
+ ## Findings
29
+ ...
30
+ ## Next steps
31
+ ...
32
+ ## Open questions
33
+ ...
34
+
35
+ Limits: ${validation_1.PLAYER_STATE_CONTENT_MAX} bytes per slot, max ${validation_1.PLAYER_STATE_SLOTS_MAX} slots per player. Slot key defaults to "${validation_1.PLAYER_STATE_DEFAULT_KEY}". When all ${validation_1.PLAYER_STATE_SLOTS_MAX} slots are full, saving a new key fails with \`PlayerStateSlotsFull\` — call \`clear_state\` to free a slot.`, {
36
+ content: zod_1.z.string().min(1).max(validation_1.PLAYER_STATE_CONTENT_MAX).describe(`The state content — markdown encouraged, opaque to the system. Max ${validation_1.PLAYER_STATE_CONTENT_MAX} bytes (UTF-8).`),
37
+ key: zod_1.z.string().regex(validation_1.PLAYER_STATE_KEY_REGEX).max(validation_1.PLAYER_STATE_KEY_MAX).optional().describe(`Slot name (default "${validation_1.PLAYER_STATE_DEFAULT_KEY}"). Alphanumeric + underscore + hyphen, max ${validation_1.PLAYER_STATE_KEY_MAX} chars.`),
38
+ }, async (args) => {
39
+ const { content, key } = args;
40
+ const slotKey = key ?? validation_1.PLAYER_STATE_DEFAULT_KEY;
41
+ const savedBy = getPlayerId();
42
+ try {
43
+ const result = await handle.executeUpdate(signals_1.savePlayerStateUpdate, {
44
+ args: [{ key: slotKey, content, savedBy }],
45
+ });
46
+ return (0, helpers_1.ok)(`Saved to slot **"${slotKey}"** at ${result.savedAt}.`);
47
+ }
48
+ catch (err) {
49
+ // The workflow validator surfaces structured ApplicationFailure errors
50
+ // (`PlayerStateSlotsFull`, `PlayerStateContentTooLarge`,
51
+ // `PlayerStateInvalidKey`). The `formatError` message preserves the
52
+ // workflow-supplied text so the LLM sees the existing-keys list and
53
+ // can pick which slot to clear.
54
+ return (0, helpers_1.fail)(`Failed to save state: ${(0, helpers_1.formatError)(err)}`);
55
+ }
56
+ });
57
+ }
@@ -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 registerScheduleTool(server: McpServer, client: Client, config: Config, getPlayerId: () => string): void;