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,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EnsembleListView = EnsembleListView;
7
+ /**
8
+ * Ensemble list view — landing screen showing all ensembles.
9
+ * Arrow keys to navigate, Enter to drill in, q to quit.
10
+ */
11
+ const react_1 = __importDefault(require("react"));
12
+ const ink_context_1 = require("../ink-context");
13
+ const platform_1 = require("../utils/platform");
14
+ function EnsembleListView({ ensembles, selectedIndex }) {
15
+ const { Box, Text } = (0, ink_context_1.useInk)();
16
+ const icons = (0, platform_1.statusIcons)();
17
+ return react_1.default.createElement(Box, { flexDirection: 'column', padding: 1 }, react_1.default.createElement(Text, { bold: true, color: 'cyan' }, 'claude-tempo ensembles'), react_1.default.createElement(Text, { dimColor: true }, 'Arrow keys to navigate, Enter to open, q to quit\n'), ensembles.length === 0
18
+ ? react_1.default.createElement(Box, { marginTop: 1 }, react_1.default.createElement(Text, { dimColor: true }, 'No running ensembles found. Start one with `claude-tempo up`.'))
19
+ : react_1.default.createElement(Box, { flexDirection: 'column' },
20
+ // Header
21
+ react_1.default.createElement(Box, null, react_1.default.createElement(Text, { bold: true, dimColor: true }, ' Ensemble Players Conductor Maestro')),
22
+ // Rows
23
+ ...ensembles.map((e, i) => {
24
+ const selected = i === selectedIndex;
25
+ const cursor = selected ? icons.arrow : ' ';
26
+ const conductorIcon = e.conductorOnline ? icons.active : icons.stale;
27
+ const maestroIcon = e.maestroRunning ? icons.active : icons.stale;
28
+ const conductorColor = e.conductorOnline ? 'green' : 'gray';
29
+ const maestroColor = e.maestroRunning ? 'green' : 'gray';
30
+ return react_1.default.createElement(Box, { key: e.name }, react_1.default.createElement(Text, { color: selected ? 'cyan' : 'white', bold: selected }, `${cursor} ${e.name.padEnd(25)} ${String(e.playerCount).padEnd(9)}`), react_1.default.createElement(Text, { color: conductorColor }, `${conductorIcon}`.padEnd(11)), react_1.default.createElement(Text, { color: maestroColor }, maestroIcon));
31
+ })));
32
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Ensemble panel — shows all players with status icons and parts.
3
+ */
4
+ import React from 'react';
5
+ import type { MaestroPlayerInfo } from '../../types';
6
+ export interface EnsemblePanelProps {
7
+ players: MaestroPlayerInfo[];
8
+ maxWidth?: number;
9
+ }
10
+ export declare function EnsemblePanel({ players, maxWidth }: EnsemblePanelProps): React.FunctionComponentElement<{
11
+ flexDirection: string;
12
+ }>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EnsemblePanel = EnsemblePanel;
7
+ /**
8
+ * Ensemble panel — shows all players with status icons and parts.
9
+ */
10
+ const react_1 = __importDefault(require("react"));
11
+ const ink_context_1 = require("../ink-context");
12
+ const platform_1 = require("../utils/platform");
13
+ const format_1 = require("../utils/format");
14
+ function EnsemblePanel({ players, maxWidth = 40 }) {
15
+ const { Box, Text } = (0, ink_context_1.useInk)();
16
+ const icons = (0, platform_1.statusIcons)();
17
+ const partMaxLen = Math.max(maxWidth - 25, 10);
18
+ if (players.length === 0) {
19
+ return react_1.default.createElement(Box, { flexDirection: 'column' }, react_1.default.createElement(Text, { dimColor: true }, 'No players connected'));
20
+ }
21
+ return react_1.default.createElement(Box, { flexDirection: 'column' }, ...players.map((p) => {
22
+ const icon = p.isConductor ? icons.conductor
23
+ : p.status === 'active' ? icons.active
24
+ : p.status === 'stale' ? icons.stale
25
+ : p.status === 'pending' ? icons.pending
26
+ : p.status === 'blocked' ? icons.blocked
27
+ : p.status === 'terminated' ? icons.terminated
28
+ : icons.player;
29
+ const color = p.isConductor ? 'yellow'
30
+ : p.status === 'active' ? 'green'
31
+ : p.status === 'stale' ? 'gray'
32
+ : p.status === 'blocked' ? 'red'
33
+ : p.status === 'pending' ? 'cyan'
34
+ : 'white';
35
+ const typeSuffix = p.playerType ? ` (${p.playerType})` : '';
36
+ const name = `${p.playerId}${typeSuffix}`;
37
+ const part = (0, format_1.truncate)(p.part, partMaxLen);
38
+ return react_1.default.createElement(Box, { key: p.playerId, flexDirection: 'column' }, react_1.default.createElement(Box, null, react_1.default.createElement(Text, { color }, `${icon} `), react_1.default.createElement(Text, { bold: true, color }, name)), react_1.default.createElement(Text, { dimColor: true }, ` ${part}`));
39
+ }));
40
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * ErrorView — connection failure screen with troubleshooting.
3
+ *
4
+ * Performance: Single <Text> root with nested virtual-text children.
5
+ * Zero Yoga <Box> nodes — follows the pattern from StatusOverlay/ConversationStream.
6
+ */
7
+ import React from 'react';
8
+ export interface ErrorCheck {
9
+ label: string;
10
+ passed: boolean;
11
+ detail?: string;
12
+ }
13
+ export interface ErrorViewProps {
14
+ version: string;
15
+ checks: ErrorCheck[];
16
+ /** Error detail text (e.g., "Connection refused (ECONNREFUSED)"). */
17
+ errorDetail?: string;
18
+ /** Whether auto-retry is active. */
19
+ retrying?: boolean;
20
+ /** Seconds until next retry. */
21
+ retryIn?: number;
22
+ /** Current retry attempt number. */
23
+ retryAttempt?: number;
24
+ /** Max retry attempts. */
25
+ retryMax?: number;
26
+ /** Called when user presses 'r' to retry. */
27
+ onRetry?: () => void;
28
+ /** Called when user presses 'q' to quit. */
29
+ onQuit?: () => void;
30
+ }
31
+ export declare function ErrorView({ version, checks, retrying, retryIn, retryAttempt, retryMax, onRetry, onQuit, }: ErrorViewProps): React.CElement<{}, React.Component<{}, any, any>>;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ErrorView = ErrorView;
37
+ /**
38
+ * ErrorView — connection failure screen with troubleshooting.
39
+ *
40
+ * Performance: Single <Text> root with nested virtual-text children.
41
+ * Zero Yoga <Box> nodes — follows the pattern from StatusOverlay/ConversationStream.
42
+ */
43
+ const react_1 = __importStar(require("react"));
44
+ const ink_context_1 = require("../ink-context");
45
+ const platform_1 = require("../utils/platform");
46
+ const theme_1 = require("../utils/theme");
47
+ function ErrorView({ version, checks, retrying, retryIn, retryAttempt, retryMax, onRetry, onQuit, }) {
48
+ const { Text, useInput } = (0, ink_context_1.useInk)();
49
+ // Wire up keybindings
50
+ useInput((0, react_1.useCallback)((input) => {
51
+ if (input === 'r' && onRetry)
52
+ onRetry();
53
+ if (input === 'q' && onQuit)
54
+ onQuit();
55
+ }, [onRetry, onQuit]));
56
+ const children = [];
57
+ // Static metronome — always center frame (index 1), rendered dim
58
+ const brailleFrames = (0, platform_1.metronomeBrailleFrames)();
59
+ const staticFrame = brailleFrames[1];
60
+ for (let i = 0; i < staticFrame.length; i++) {
61
+ if (i > 0)
62
+ children.push('\n');
63
+ children.push(react_1.default.createElement(react_1.default.Fragment, { key: `m-${i}` }, ...staticFrame[i].map((seg, j) => react_1.default.createElement(Text, { key: j, color: theme_1.THEME.dim }, seg.char))));
64
+ }
65
+ // Title
66
+ children.push('\n\n');
67
+ children.push(react_1.default.createElement(Text, { key: 'title', bold: true, color: theme_1.THEME.accent }, ' agent-tempo'));
68
+ children.push('\n');
69
+ children.push(react_1.default.createElement(Text, { key: 'sub', color: theme_1.THEME.dim }, ' Multi-session orchestration via Temporal'));
70
+ children.push('\n');
71
+ children.push(react_1.default.createElement(Text, { key: 'ver', color: theme_1.THEME.muted }, ` v${version}`));
72
+ // Error header
73
+ children.push('\n\n');
74
+ children.push(react_1.default.createElement(Text, { key: 'err', bold: true, color: theme_1.THEME.error }, ' \u26A0 Connection Failed'));
75
+ // Checklist
76
+ children.push('\n');
77
+ for (let i = 0; i < checks.length; i++) {
78
+ const check = checks[i];
79
+ children.push('\n');
80
+ children.push(react_1.default.createElement(Text, { key: `c-${i}`, color: check.passed ? theme_1.THEME.success : theme_1.THEME.error }, ` ${check.passed ? '\u2713' : '\u2717'} ${check.label}`));
81
+ if (check.detail && !check.passed) {
82
+ children.push('\n');
83
+ children.push(react_1.default.createElement(Text, { key: `cd-${i}`, color: theme_1.THEME.dim }, ` ${check.detail}`));
84
+ }
85
+ }
86
+ // Troubleshooting box (text-based border)
87
+ const boxWidth = 56;
88
+ const hLine = '\u2500'.repeat(boxWidth);
89
+ children.push('\n\n');
90
+ children.push(react_1.default.createElement(Text, { key: 'bt', color: theme_1.THEME.dim }, ` \u250C${hLine}\u2510`));
91
+ children.push('\n');
92
+ children.push(react_1.default.createElement(Text, { key: 'bh', bold: true, color: theme_1.THEME.warning }, ' \u2502 Troubleshooting'));
93
+ children.push(react_1.default.createElement(Text, { key: 'bh2', color: theme_1.THEME.dim }, ' '.repeat(boxWidth - 17) + '\u2502'));
94
+ children.push('\n');
95
+ children.push(react_1.default.createElement(Text, { key: 'bs', color: theme_1.THEME.dim }, ` \u2502${' '.repeat(boxWidth)}\u2502`));
96
+ const steps = [
97
+ { label: '1. Start the Temporal dev server:', cmd: ' $ temporal server start-dev' },
98
+ { label: '2. Or specify a custom address:', cmd: ' $ TEMPORAL_ADDRESS=host:7233 agent-tempo' },
99
+ { label: '3. Check if Temporal is running:', cmd: ' $ temporal operator cluster health' },
100
+ ];
101
+ for (let i = 0; i < steps.length; i++) {
102
+ const s = steps[i];
103
+ const pad1 = ' '.repeat(Math.max(0, boxWidth - s.label.length - 2));
104
+ const pad2 = ' '.repeat(Math.max(0, boxWidth - s.cmd.length - 2));
105
+ children.push('\n');
106
+ children.push(react_1.default.createElement(Text, { key: `s${i}a`, color: theme_1.THEME.text }, ` \u2502 ${s.label}`));
107
+ children.push(react_1.default.createElement(Text, { key: `s${i}ap`, color: theme_1.THEME.dim }, `${pad1}\u2502`));
108
+ children.push('\n');
109
+ children.push(react_1.default.createElement(Text, { key: `s${i}b`, color: theme_1.THEME.accent }, ` \u2502 ${s.cmd}`));
110
+ children.push(react_1.default.createElement(Text, { key: `s${i}bp`, color: theme_1.THEME.dim }, `${pad2}\u2502`));
111
+ }
112
+ children.push('\n');
113
+ children.push(react_1.default.createElement(Text, { key: 'be', color: theme_1.THEME.dim }, ` \u2502${' '.repeat(boxWidth)}\u2502`));
114
+ const docsUrl = 'Docs: https://github.com/vinceblank/agent-tempo#setup';
115
+ const docsPad = ' '.repeat(Math.max(0, boxWidth - docsUrl.length - 2));
116
+ children.push('\n');
117
+ children.push(react_1.default.createElement(Text, { key: 'bd', color: theme_1.THEME.dim }, ` \u2502 ${docsUrl}${docsPad}\u2502`));
118
+ children.push('\n');
119
+ children.push(react_1.default.createElement(Text, { key: 'bb', color: theme_1.THEME.dim }, ` \u2514${hLine}\u2518`));
120
+ // Retry progress
121
+ if (retrying) {
122
+ children.push('\n\n');
123
+ children.push(react_1.default.createElement(Text, { key: 'retry', color: theme_1.THEME.dim }, ` Retrying in ${retryIn ?? '?'}s... (attempt ${retryAttempt ?? '?'}/${retryMax ?? 5})`));
124
+ }
125
+ // Keybindings
126
+ children.push('\n\n');
127
+ children.push(react_1.default.createElement(Text, { key: 'keys', color: theme_1.THEME.dim }, ' [r] retry now [q] quit [?] help'));
128
+ return react_1.default.createElement(Text, null, ...children);
129
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * HomeView — three-list landing surface (Online / Paused / Offline). Polls
3
+ * `listEnsembles` every 10s; `r` forces an immediate refresh.
4
+ *
5
+ * Offline rows whose ensemble name matches the cwd's git-root basename are
6
+ * pinned to the top of the offline list with a `⬡` badge — the visual
7
+ * affordance for "press Enter to restore the ensemble you created here".
8
+ * Online and Paused rows are not cwd-pinned — entering them is a no-op
9
+ * navigation, not a restore that needs a per-cwd hint.
10
+ */
11
+ import React from 'react';
12
+ import type { BootstrapBadges } from '../bootstrap-types';
13
+ import type { EnsembleSummary, TempoClient } from '../../client';
14
+ /**
15
+ * Initial snapshot — structurally a subset of `BootstrapResult` so callers
16
+ * can pass the full bootstrap result directly.
17
+ */
18
+ export interface HomeViewInitial {
19
+ ensembles: EnsembleSummary[];
20
+ cwdGitRoot: string | null;
21
+ badges: BootstrapBadges;
22
+ }
23
+ export interface HomeViewProps {
24
+ initial: HomeViewInitial;
25
+ client: TempoClient;
26
+ onEnterEnsemble: (name: string) => void;
27
+ onCreateEnsemble: () => void;
28
+ onLoadLineup: () => void;
29
+ onRestoreEnsemble: (name: string) => void;
30
+ onQuit: () => void;
31
+ }
32
+ interface SortedLists {
33
+ online: EnsembleSummary[];
34
+ paused: EnsembleSummary[];
35
+ offline: EnsembleSummary[];
36
+ /**
37
+ * Flat sequence used for keyboard navigation. Order matches render
38
+ * order: Online → Paused → Offline (cwd-match offline rows first).
39
+ */
40
+ flat: Array<{
41
+ ensemble: EnsembleSummary;
42
+ isCwdMatch: boolean;
43
+ }>;
44
+ /** Count of cwd-matched offline ensembles pinned at the top of the offline list. */
45
+ cwdMatchCount: number;
46
+ }
47
+ /**
48
+ * Split + sort ensembles into Online / Paused / Offline lists with
49
+ * cwd-match rows pinned to the top of the Offline list. Pure function for
50
+ * testability.
51
+ */
52
+ export declare function partitionEnsembles(ensembles: readonly EnsembleSummary[], cwdGitRoot: string | null, cwdMatcher?: (ensemble: EnsembleSummary, gitRoot: string) => boolean): SortedLists;
53
+ export declare function HomeView(props: HomeViewProps): React.ReactElement;
54
+ export {};
@@ -0,0 +1,306 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.partitionEnsembles = partitionEnsembles;
37
+ exports.HomeView = HomeView;
38
+ /**
39
+ * HomeView — three-list landing surface (Online / Paused / Offline). Polls
40
+ * `listEnsembles` every 10s; `r` forces an immediate refresh.
41
+ *
42
+ * Offline rows whose ensemble name matches the cwd's git-root basename are
43
+ * pinned to the top of the offline list with a `⬡` badge — the visual
44
+ * affordance for "press Enter to restore the ensemble you created here".
45
+ * Online and Paused rows are not cwd-pinned — entering them is a no-op
46
+ * navigation, not a restore that needs a per-cwd hint.
47
+ */
48
+ const react_1 = __importStar(require("react"));
49
+ const ink_context_1 = require("../ink-context");
50
+ const theme_1 = require("../utils/theme");
51
+ const platform_1 = require("../utils/platform");
52
+ const REFRESH_INTERVAL_MS = 10_000;
53
+ /**
54
+ * Split + sort ensembles into Online / Paused / Offline lists with
55
+ * cwd-match rows pinned to the top of the Offline list. Pure function for
56
+ * testability.
57
+ */
58
+ function partitionEnsembles(ensembles, cwdGitRoot, cwdMatcher = defaultCwdMatcher) {
59
+ const online = [];
60
+ const paused = [];
61
+ const offlineMatch = [];
62
+ const offlineOther = [];
63
+ for (const e of ensembles) {
64
+ if (e.state === 'online') {
65
+ online.push(e);
66
+ }
67
+ else if (e.state === 'paused') {
68
+ paused.push(e);
69
+ }
70
+ else if (e.state === 'offline') {
71
+ if (cwdGitRoot && cwdMatcher(e, cwdGitRoot))
72
+ offlineMatch.push(e);
73
+ else
74
+ offlineOther.push(e);
75
+ }
76
+ }
77
+ // Alphabetical — recency-desc will replace this once `lastActivityAt` is
78
+ // threaded through `EnsembleSummary`.
79
+ online.sort((a, b) => a.name.localeCompare(b.name));
80
+ paused.sort((a, b) => a.name.localeCompare(b.name));
81
+ offlineMatch.sort((a, b) => a.name.localeCompare(b.name));
82
+ offlineOther.sort((a, b) => a.name.localeCompare(b.name));
83
+ const offline = [...offlineMatch, ...offlineOther];
84
+ const flat = [
85
+ ...online.map((ensemble) => ({ ensemble, isCwdMatch: false })),
86
+ ...paused.map((ensemble) => ({ ensemble, isCwdMatch: false })),
87
+ ...offlineMatch.map((ensemble) => ({ ensemble, isCwdMatch: true })),
88
+ ...offlineOther.map((ensemble) => ({ ensemble, isCwdMatch: false })),
89
+ ];
90
+ return { online, paused, offline, flat, cwdMatchCount: offlineMatch.length };
91
+ }
92
+ /**
93
+ * Shallow equality over the fields HomeView renders. Keeps the 10s poll
94
+ * from thrashing referential identity when the backend snapshot is
95
+ * unchanged.
96
+ */
97
+ function ensemblesEqual(a, b) {
98
+ if (a === b)
99
+ return true;
100
+ if (a.length !== b.length)
101
+ return false;
102
+ for (let i = 0; i < a.length; i++) {
103
+ const x = a[i];
104
+ const y = b[i];
105
+ if (x.name !== y.name || x.state !== y.state
106
+ || x.playerCount !== y.playerCount
107
+ || x.hasConductor !== y.hasConductor
108
+ || x.conductorStatus !== y.conductorStatus)
109
+ return false;
110
+ }
111
+ return true;
112
+ }
113
+ /** Matches the `agent-tempo up` default: ensemble named after the repo root. */
114
+ function defaultCwdMatcher(ensemble, gitRoot) {
115
+ const basename = gitRoot.split(/[\\/]/).filter(Boolean).pop() ?? '';
116
+ return basename.length > 0 && ensemble.name === basename;
117
+ }
118
+ function HomeView(props) {
119
+ const { initial, client, onEnterEnsemble, onCreateEnsemble, onLoadLineup, onRestoreEnsemble, onQuit, } = props;
120
+ const { Box, Text, useInput } = (0, ink_context_1.useInk)();
121
+ const [ensembles, setEnsembles] = (0, react_1.useState)(initial.ensembles);
122
+ const [selectedIdx, setSelectedIdx] = (0, react_1.useState)(0);
123
+ const [refreshing, setRefreshing] = (0, react_1.useState)(false);
124
+ const [error, setError] = (0, react_1.useState)(null);
125
+ // #306: Track whether the first refresh has completed so the empty state
126
+ // doesn't flash "No ensembles yet" before the discovery query returns.
127
+ // Bootstrap may pass a stale or empty `initial.ensembles`; only after the
128
+ // mount-time refresh do we trust an empty list as "really empty."
129
+ const [firstRefreshDone, setFirstRefreshDone] = (0, react_1.useState)(initial.ensembles.length > 0);
130
+ const lists = (0, react_1.useMemo)(() => partitionEnsembles(ensembles, initial.cwdGitRoot), [ensembles, initial.cwdGitRoot]);
131
+ // Clamp selection whenever the list shrinks underneath the cursor.
132
+ (0, react_1.useEffect)(() => {
133
+ if (selectedIdx >= lists.flat.length) {
134
+ setSelectedIdx(Math.max(0, lists.flat.length - 1));
135
+ }
136
+ }, [lists.flat.length, selectedIdx]);
137
+ // Debounced refresh: setInterval fires every 10s; `r` key calls refresh()
138
+ // immediately. In-flight refreshes short-circuit via `refreshing` flag so
139
+ // a slow query doesn't stack behind a fast one.
140
+ const refreshingRef = (0, react_1.useRef)(false);
141
+ const refresh = (0, react_1.useCallback)(async () => {
142
+ if (refreshingRef.current)
143
+ return;
144
+ refreshingRef.current = true;
145
+ setRefreshing(true);
146
+ try {
147
+ const next = await client.listEnsembles();
148
+ // Identity-stable: skip the setState when the 10s poll returns an
149
+ // equivalent snapshot (common case on an idle host), so HomeView's
150
+ // memoized `partitionEnsembles` result doesn't re-compute.
151
+ setEnsembles((prev) => ensemblesEqual(prev, next) ? prev : next);
152
+ setError(null);
153
+ }
154
+ catch (err) {
155
+ setError(err instanceof Error ? err.message : String(err));
156
+ }
157
+ finally {
158
+ refreshingRef.current = false;
159
+ setRefreshing(false);
160
+ setFirstRefreshDone(true);
161
+ }
162
+ }, [client]);
163
+ (0, react_1.useEffect)(() => {
164
+ // #306: Kick an immediate refresh on mount so the user doesn't see
165
+ // "No ensembles yet" while waiting for the 10s polling timer's first
166
+ // tick. The timer continues polling at the regular cadence after.
167
+ refresh();
168
+ const timer = setInterval(refresh, REFRESH_INTERVAL_MS);
169
+ return () => clearInterval(timer);
170
+ }, [refresh]);
171
+ useInput((0, react_1.useCallback)((input, key) => {
172
+ const total = lists.flat.length;
173
+ if (key.upArrow && total > 0) {
174
+ setSelectedIdx((i) => Math.max(0, i - 1));
175
+ return;
176
+ }
177
+ if (key.downArrow && total > 0) {
178
+ setSelectedIdx((i) => Math.min(total - 1, i + 1));
179
+ return;
180
+ }
181
+ if (key.return && total > 0) {
182
+ const row = lists.flat[selectedIdx];
183
+ if (!row)
184
+ return;
185
+ // Online + Paused both navigate into the ensemble — paused ensembles
186
+ // are signal-paused but their workflows are alive and the user can
187
+ // run `/play` from inside. Offline requires the full restore path.
188
+ if (row.ensemble.state === 'online' || row.ensemble.state === 'paused') {
189
+ onEnterEnsemble(row.ensemble.name);
190
+ }
191
+ else if (row.ensemble.state === 'offline') {
192
+ onRestoreEnsemble(row.ensemble.name);
193
+ }
194
+ return;
195
+ }
196
+ if (input === 'n' || input === 'N') {
197
+ onCreateEnsemble();
198
+ return;
199
+ }
200
+ if (input === 'l' || input === 'L') {
201
+ onLoadLineup();
202
+ return;
203
+ }
204
+ if (input === 'r' || input === 'R') {
205
+ void refresh();
206
+ return;
207
+ }
208
+ if (input === 'q' || input === 'Q') {
209
+ onQuit();
210
+ return;
211
+ }
212
+ }, [lists.flat, selectedIdx, onEnterEnsemble, onRestoreEnsemble, onCreateEnsemble, onLoadLineup, onQuit, refresh]));
213
+ return renderBody({
214
+ Box, Text,
215
+ lists, selectedIdx,
216
+ refreshing, error,
217
+ badges: initial.badges,
218
+ firstRefreshDone,
219
+ });
220
+ }
221
+ function renderBody(props) {
222
+ const { Box, Text, lists, selectedIdx, refreshing, error, badges, firstRefreshDone } = props;
223
+ const icons = (0, platform_1.statusIcons)((0, platform_1.supportsUnicode)());
224
+ const isEmpty = lists.flat.length === 0;
225
+ const header = react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.accent, key: 'home-header' }, ' agent-tempo');
226
+ const statusLine = react_1.default.createElement(Text, { key: 'home-status', color: theme_1.THEME.dim }, ` N new · L lineup · ↵ enter/restore · r refresh${refreshing ? ' …' : ''} · Q quit`);
227
+ const children = [header, statusLine, ...renderBadges(Text, badges)];
228
+ if (error) {
229
+ children.push(react_1.default.createElement(Text, { key: 'home-err', color: theme_1.THEME.error }, ` refresh failed: ${error}`));
230
+ }
231
+ if (isEmpty) {
232
+ // #306: Until the first refresh completes, show a loading state instead
233
+ // of "No ensembles yet" — bootstrap may pass an empty initial list while
234
+ // discovery is in flight, and flashing the "no ensembles" copy is jarring.
235
+ children.push(react_1.default.createElement(Box, { key: 'home-empty', marginTop: 1 }, firstRefreshDone
236
+ ? react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' No ensembles yet. Press ', react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, 'N'), ' to create one, or ', react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, 'L'), ' to load a lineup.')
237
+ : react_1.default.createElement(Text, { color: theme_1.THEME.dim }, ' Loading ensembles …')));
238
+ }
239
+ else {
240
+ // Three sections in priority order: Online → Paused → Offline.
241
+ // Each section's header is skipped when the section is empty so the
242
+ // landing page stays compact on a fresh ensemble (no "Paused (none)"
243
+ // / "Offline (none)" noise). Cursor offsets must mirror the flat
244
+ // sequence built by `partitionEnsembles`.
245
+ let cursorOffset = 0;
246
+ if (lists.online.length > 0) {
247
+ const start = cursorOffset;
248
+ children.push(react_1.default.createElement(Box, { key: 'home-online', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Online'), ...lists.online.map((e, i) => renderRow({
249
+ Text, key: `online-${e.name}`, icons,
250
+ ensemble: e,
251
+ selected: (start + i) === selectedIdx,
252
+ isCwdMatch: false,
253
+ }))));
254
+ cursorOffset += lists.online.length;
255
+ }
256
+ if (lists.paused.length > 0) {
257
+ const start = cursorOffset;
258
+ children.push(react_1.default.createElement(Box, { key: 'home-paused', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Paused'), ...lists.paused.map((e, i) => renderRow({
259
+ Text, key: `paused-${e.name}`, icons,
260
+ ensemble: e,
261
+ selected: (start + i) === selectedIdx,
262
+ isCwdMatch: false,
263
+ }))));
264
+ cursorOffset += lists.paused.length;
265
+ }
266
+ if (lists.offline.length > 0) {
267
+ const start = cursorOffset;
268
+ children.push(react_1.default.createElement(Box, { key: 'home-offline', marginTop: 1, flexDirection: 'column' }, react_1.default.createElement(Text, { bold: true, color: theme_1.THEME.text }, ' Offline'), ...lists.offline.map((e, i) => renderRow({
269
+ Text, key: `offline-${e.name}`, icons,
270
+ ensemble: e,
271
+ selected: (start + i) === selectedIdx,
272
+ isCwdMatch: i < lists.cwdMatchCount,
273
+ }))));
274
+ }
275
+ }
276
+ return react_1.default.createElement(Box, { flexDirection: 'column' }, ...children);
277
+ }
278
+ function renderRow({ Text, key, icons, ensemble, selected, isCwdMatch }) {
279
+ const cursor = selected ? '\u276F' : ' ';
280
+ // Online uses the active glyph; paused + offline both use the stale
281
+ // glyph (no live attachment activity). Color disambiguates: warning
282
+ // for paused (transient, fast resume via /play) vs dim for offline
283
+ // (needs /restore to come back).
284
+ const glyph = ensemble.state === 'online' ? icons.active : icons.stale;
285
+ const glyphColor = ensemble.state === 'online' ? theme_1.THEME.success
286
+ : ensemble.state === 'paused' ? theme_1.THEME.warning
287
+ : theme_1.THEME.dim;
288
+ const cwdBadge = isCwdMatch ? '\u2B21 ' : '';
289
+ const playerSuffix = ` (${ensemble.playerCount} player${ensemble.playerCount === 1 ? '' : 's'})`;
290
+ return react_1.default.createElement(Text, { key, color: selected ? theme_1.THEME.text : theme_1.THEME.textMuted }, ` ${cursor} `, react_1.default.createElement(Text, { color: glyphColor }, `${glyph} `), isCwdMatch
291
+ ? react_1.default.createElement(Text, { color: theme_1.THEME.accent, bold: true }, cwdBadge)
292
+ : null, react_1.default.createElement(Text, { bold: selected, color: selected ? theme_1.THEME.text : theme_1.THEME.textMuted }, ensemble.name), react_1.default.createElement(Text, { color: theme_1.THEME.dim }, playerSuffix));
293
+ }
294
+ function renderBadges(Text, badges) {
295
+ const parts = [];
296
+ if (badges.orphanCount > 0) {
297
+ parts.push(react_1.default.createElement(Text, { key: 'b-orph', color: theme_1.THEME.warning }, ` ${badges.orphanCount} orphan${badges.orphanCount === 1 ? '' : 's'} on this host`));
298
+ }
299
+ if (badges.daemonLogErrors && badges.daemonLogErrors.count > 0) {
300
+ parts.push(react_1.default.createElement(Text, { key: 'b-log', color: theme_1.THEME.error }, ` daemon log: ${badges.daemonLogErrors.count} recent error${badges.daemonLogErrors.count === 1 ? '' : 's'}`));
301
+ }
302
+ if (badges.outdatedVersion) {
303
+ parts.push(react_1.default.createElement(Text, { key: 'b-ver', color: theme_1.THEME.warning }, ` upgrade available: v${badges.outdatedVersion.latest} (${badges.outdatedVersion.severity})`));
304
+ }
305
+ return parts;
306
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Input bar — text input for sending commands to the conductor.
3
+ */
4
+ import React from 'react';
5
+ export interface InputBarProps {
6
+ onSubmit: (text: string) => void;
7
+ sending: boolean;
8
+ error: string | null;
9
+ placeholder?: string;
10
+ }
11
+ export declare function InputBar({ onSubmit, sending, error, placeholder }: InputBarProps): React.FunctionComponentElement<{
12
+ flexDirection: string;
13
+ }>;