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,493 @@
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.evaluateStartPreflight = evaluateStartPreflight;
37
+ exports.daemon = daemon;
38
+ exports.formatBytesAsMb = formatBytesAsMb;
39
+ exports.formatUptime = formatUptime;
40
+ /**
41
+ * Daemon CLI command handler — `agent-tempo daemon <start|stop|status|logs|install|uninstall>`.
42
+ *
43
+ * **Critical constraint**: this module must NOT import from `@temporalio/*`,
44
+ * `../workflows/*`, `../adapters/*`, `../spawn`, `../client`, or any module
45
+ * that transitively pulls in the Temporal SDK or rxjs. The daemon CLI must
46
+ * remain operable even when the Temporal SDK itself is broken (e.g. a
47
+ * `@temporalio/core-bridge` native-module build failure on an unsupported
48
+ * Node version — see issue #157: users were stranded with orphan processes
49
+ * they couldn't stop because `daemon stop` crashed before executing).
50
+ *
51
+ * Keeping this module's dep graph minimal also avoids pulling ~250MB of
52
+ * Temporal SDK code + workflow bundle parsing into every CLI invocation.
53
+ *
54
+ * ## Test guarantee
55
+ *
56
+ * `test/daemon-command-isolation.test.ts` spawns a child Node process that
57
+ * requires the compiled `dist/cli/daemon-command.js` and asserts that
58
+ * `require.cache` contains zero entries matching `@temporalio|rxjs|@grpc`.
59
+ * If you add an import here that transitively leaks Temporal deps, that
60
+ * test will fail.
61
+ */
62
+ const fs_1 = require("fs");
63
+ const path_1 = require("path");
64
+ const os_1 = require("os");
65
+ const child_process_1 = require("child_process");
66
+ const http = __importStar(require("http"));
67
+ const config_1 = require("../config");
68
+ const port_file_1 = require("../http/port-file");
69
+ const daemon_1 = require("./daemon");
70
+ const out = __importStar(require("./output"));
71
+ /**
72
+ * Pure decision function for `daemon start`. Given a scanner result and the
73
+ * current daemon status, computes whether to no-op, abort with orphans, or
74
+ * spawn. `force` bypasses the orphan check and signals that a stale pid file
75
+ * (if any) should be cleared before the spawn.
76
+ *
77
+ * `otherProfilePid` is the live PID (if any) of the opposite profile's
78
+ * daemon (dev's prod sibling, or prod's dev sibling). Including it in the
79
+ * known-PID set keeps cross-profile coexistence working (ADR 0014 §5.6) —
80
+ * starting the dev daemon must not flag the prod daemon as an orphan, and
81
+ * vice versa.
82
+ *
83
+ * @internal — exported for unit tests in test/daemon-start-orphan-check.test.ts.
84
+ */
85
+ function evaluateStartPreflight(scanned, status, force, otherProfilePid) {
86
+ if (status.running && typeof status.pid === 'number') {
87
+ return { action: 'already-running', pid: status.pid };
88
+ }
89
+ if (!force) {
90
+ const orphans = (0, daemon_1.selectOrphans)(scanned, [status.pid, otherProfilePid]);
91
+ if (orphans.length > 0)
92
+ return { action: 'abort', orphans };
93
+ }
94
+ return { action: 'spawn', cleanupStalePid: force };
95
+ }
96
+ /** Package root is two levels up from dist/cli/ */
97
+ const PACKAGE_ROOT = (0, path_1.resolve)(__dirname, '..', '..');
98
+ function packagingFile(...segments) {
99
+ return (0, path_1.join)(PACKAGE_ROOT, 'packaging', ...segments);
100
+ }
101
+ async function daemon(opts) {
102
+ const config = (0, config_1.getConfig)(opts);
103
+ switch (opts.subcommand) {
104
+ case 'start': {
105
+ const status = (0, daemon_1.getDaemonStatus)();
106
+ // ADR 0014 §5.6 — if the OPPOSITE profile's daemon is running on this
107
+ // machine, exclude its PID from the orphan set. Dev + prod daemons
108
+ // are designed to coexist (different home dir / port / namespace).
109
+ // When the other profile shows weak evidence of running (port file
110
+ // exists but PID file doesn't / PID is unparseable), skip the orphan
111
+ // scan entirely — see also `stopDaemon`'s mirroring behavior.
112
+ const otherPid = (0, daemon_1.getOtherProfilePid)();
113
+ const skipOrphanScan = (0, daemon_1.isOtherProfileLikelyRunning)() && otherPid === undefined;
114
+ if (skipOrphanScan) {
115
+ out.warn('Skipping orphan-process scan — the other profile (dev/prod) appears to be running ' +
116
+ 'without a PID file. Re-run with `daemon start --force` if you have already verified ' +
117
+ 'no rogue daemon for THIS profile is present.');
118
+ }
119
+ const preflight = evaluateStartPreflight(
120
+ // Skip the actual OS scan when we're already-running, force is set,
121
+ // or we're suppressing for cross-profile safety.
122
+ status.running || opts.force || skipOrphanScan ? [] : (0, daemon_1.scanAgentTempoDaemons)(), status, Boolean(opts.force) || skipOrphanScan, otherPid);
123
+ switch (preflight.action) {
124
+ case 'already-running':
125
+ out.success(`Daemon already running (pid ${preflight.pid})`);
126
+ return;
127
+ case 'abort':
128
+ // Piling a new daemon on top of orphans is the original #157 user-pain
129
+ // scenario. User must clean up first — see troubleshooting docs.
130
+ out.error(`Found ${preflight.orphans.length} orphaned agent-tempo daemon process${preflight.orphans.length === 1 ? '' : 'es'} — daemon start aborted.`);
131
+ for (const p of preflight.orphans)
132
+ out.log(` pid ${p.pid}: ${p.commandLine}`);
133
+ out.log('');
134
+ out.log(` ${out.dim('Emergency cleanup: see docs/troubleshooting.md → "Orphaned daemon processes"')}`);
135
+ out.log(` ${out.dim('Override (use only after confirming): agent-tempo daemon start --force')}`);
136
+ process.exit(1);
137
+ break;
138
+ case 'spawn':
139
+ if (preflight.cleanupStalePid && (0, fs_1.existsSync)(daemon_1.DAEMON_PID_PATH)) {
140
+ // Force path — clean up a stale pid file if present.
141
+ // `getDaemonStatus` already unlinks the file when it detects a
142
+ // dead pid; this handles the rarer "file exists, contents
143
+ // unparseable OR fs error" branch.
144
+ try {
145
+ (0, fs_1.unlinkSync)(daemon_1.DAEMON_PID_PATH);
146
+ }
147
+ catch { /* ignore */ }
148
+ }
149
+ out.log('Starting daemon...');
150
+ try {
151
+ const pid = await (0, daemon_1.startDaemon)(config);
152
+ out.success(`Daemon started (pid ${pid})`);
153
+ out.log(` ${out.dim('Logs: ' + daemon_1.DAEMON_LOG_PATH)}`);
154
+ }
155
+ catch (err) {
156
+ out.error(err.message || String(err));
157
+ process.exit(1);
158
+ }
159
+ break;
160
+ }
161
+ break;
162
+ }
163
+ case 'stop': {
164
+ if ((0, daemon_1.stopDaemon)()) {
165
+ out.success('Daemon stopped');
166
+ }
167
+ else {
168
+ out.warn('Daemon is not running');
169
+ }
170
+ break;
171
+ }
172
+ case 'status': {
173
+ const status = (0, daemon_1.getDaemonStatus)();
174
+ const scanned = (0, daemon_1.scanAgentTempoDaemons)();
175
+ if (status.running) {
176
+ out.success(`Daemon running (pid ${status.pid})`);
177
+ // Heartbeat diagnostic — distinguishes "pid alive AND main loop
178
+ // serving" from "pid alive but something hung" (#157 PR B).
179
+ const staleThresholdMs = daemon_1.HEARTBEAT_INTERVAL_MS * daemon_1.HEARTBEAT_STALE_MULTIPLIER;
180
+ if (status.heartbeatAge !== undefined && status.heartbeatAge !== null) {
181
+ const ageSec = Math.round(status.heartbeatAge / 1000);
182
+ if (status.heartbeatAge > staleThresholdMs) {
183
+ out.warn(` Last heartbeat: ${ageSec}s ago — STALE (threshold ${staleThresholdMs / 1000}s). The daemon's main loop may be hung.`);
184
+ }
185
+ else {
186
+ out.log(` ${out.dim(`Last heartbeat: ${ageSec}s ago`)}`);
187
+ }
188
+ }
189
+ else if (status.heartbeatAge === null) {
190
+ out.log(` ${out.dim('Last heartbeat: (not yet written — daemon just started or pre-heartbeat version)')}`);
191
+ }
192
+ // Warn if the scanner reports extras the pid file doesn't know about —
193
+ // orphans from a prior crashed run that never removed its pid file, or
194
+ // a second daemon started by a stale concurrent CLI invocation (#157).
195
+ // The opposite profile's daemon (if running) also gets excluded so
196
+ // prod doesn't flag dev as an orphan / vice versa (ADR 0014 §5.6).
197
+ const extras = (0, daemon_1.selectOrphans)(scanned, [status.pid, (0, daemon_1.getOtherProfilePid)()]);
198
+ if (extras.length > 0) {
199
+ out.warn(`Found ${extras.length} additional agent-tempo daemon process${extras.length === 1 ? '' : 'es'} not tracked by the pid file:`);
200
+ for (const p of extras)
201
+ out.log(` pid ${p.pid}: ${p.commandLine}`);
202
+ out.log(` ${out.dim('See `agent-tempo daemon --help` or docs/troubleshooting.md for emergency cleanup.')}`);
203
+ }
204
+ }
205
+ else {
206
+ out.log('Daemon is not running');
207
+ if (scanned.length > 0) {
208
+ out.warn(`Found ${scanned.length} orphaned agent-tempo daemon process${scanned.length === 1 ? '' : 'es'} (no pid file):`);
209
+ for (const p of scanned)
210
+ out.log(` pid ${p.pid}: ${p.commandLine}`);
211
+ out.log(` ${out.dim('These are untracked. See docs/troubleshooting.md → "Orphaned daemon processes" for emergency cleanup.')}`);
212
+ }
213
+ }
214
+ break;
215
+ }
216
+ case 'stats': {
217
+ await daemonStats();
218
+ break;
219
+ }
220
+ case 'logs': {
221
+ if (!(0, fs_1.existsSync)(daemon_1.DAEMON_LOG_PATH)) {
222
+ out.warn('No daemon log file found');
223
+ return;
224
+ }
225
+ // Tail the log file
226
+ if (process.platform === 'win32') {
227
+ // On Windows, read the last 32KB of the log (size-capped to avoid OOM on large logs)
228
+ const MAX_TAIL_BYTES = 32 * 1024;
229
+ const stat = (0, fs_1.statSync)(daemon_1.DAEMON_LOG_PATH);
230
+ const fd = (0, fs_1.openSync)(daemon_1.DAEMON_LOG_PATH, 'r');
231
+ const readStart = Math.max(0, stat.size - MAX_TAIL_BYTES);
232
+ const buf = Buffer.alloc(Math.min(stat.size, MAX_TAIL_BYTES));
233
+ (0, fs_1.readSync)(fd, buf, 0, buf.length, readStart);
234
+ (0, fs_1.closeSync)(fd);
235
+ const chunk = buf.toString('utf8');
236
+ // Skip partial first line if we didn't read from the start
237
+ const lines = readStart > 0 ? chunk.split('\n').slice(1) : chunk.split('\n');
238
+ console.log(lines.slice(-50).join('\n'));
239
+ }
240
+ else {
241
+ // On Unix, use tail -f for live following
242
+ const child = (0, child_process_1.spawn)('tail', ['-f', '-n', '50', daemon_1.DAEMON_LOG_PATH], {
243
+ stdio: 'inherit',
244
+ });
245
+ child.on('error', () => {
246
+ // Fallback: just read the file
247
+ const content = (0, fs_1.readFileSync)(daemon_1.DAEMON_LOG_PATH, 'utf8');
248
+ const lines = content.split('\n');
249
+ console.log(lines.slice(-50).join('\n'));
250
+ });
251
+ // Keep running until user presses Ctrl+C
252
+ await new Promise((resolve) => {
253
+ child.on('exit', () => resolve());
254
+ process.on('SIGINT', () => { child.kill(); resolve(); });
255
+ });
256
+ }
257
+ break;
258
+ }
259
+ case 'install':
260
+ await daemonInstall();
261
+ break;
262
+ case 'uninstall':
263
+ await daemonUninstall();
264
+ break;
265
+ default:
266
+ out.error('Usage: agent-tempo daemon <start|stop|status|stats|logs|install|uninstall>');
267
+ out.log(`\n ${out.dim('agent-tempo daemon start [--force]')} Start the worker daemon`);
268
+ out.log(` ${out.dim(' --force: skip orphan-process check + clear stale pid file')}`);
269
+ out.log(` ${out.dim('agent-tempo daemon stop')} Stop the worker daemon`);
270
+ out.log(` ${out.dim('agent-tempo daemon status')} Check daemon status + heartbeat + orphans`);
271
+ out.log(` ${out.dim('agent-tempo daemon stats')} Show memory + uptime + ensemble count`);
272
+ out.log(` ${out.dim('agent-tempo daemon logs')} Tail daemon log output`);
273
+ out.log(` ${out.dim('agent-tempo daemon install')} Install as a system service`);
274
+ out.log(` ${out.dim('agent-tempo daemon uninstall')} Uninstall the system service`);
275
+ process.exit(1);
276
+ }
277
+ // Used only to silence "config declared but never used" when a branch exits early.
278
+ void config;
279
+ }
280
+ async function daemonInstall() {
281
+ const platform = process.platform;
282
+ if (platform === 'linux') {
283
+ const src = packagingFile('systemd', 'agent-tempo.service');
284
+ const dstDir = (0, path_1.join)((0, os_1.homedir)(), '.config', 'systemd', 'user');
285
+ const dst = (0, path_1.join)(dstDir, 'agent-tempo.service');
286
+ (0, fs_1.mkdirSync)(dstDir, { recursive: true });
287
+ (0, fs_1.copyFileSync)(src, dst);
288
+ out.success(`Installed systemd --user unit: ${dst}`);
289
+ // Try to enable + start. User may still need `systemctl --user daemon-reload`.
290
+ try {
291
+ (0, child_process_1.execFileSync)('systemctl', ['--user', 'daemon-reload'], { stdio: 'ignore' });
292
+ (0, child_process_1.execFileSync)('systemctl', ['--user', 'enable', '--now', 'agent-tempo'], { stdio: 'ignore' });
293
+ out.log(' Enabled + started: systemctl --user enable --now agent-tempo');
294
+ }
295
+ catch {
296
+ out.warn(' systemctl invocation failed — run manually:');
297
+ out.log(` ${out.dim('systemctl --user daemon-reload')}`);
298
+ out.log(` ${out.dim('systemctl --user enable --now agent-tempo')}`);
299
+ }
300
+ return;
301
+ }
302
+ if (platform === 'darwin') {
303
+ const src = packagingFile('launchd', 'com.agent.tempo.plist');
304
+ const dstDir = (0, path_1.join)((0, os_1.homedir)(), 'Library', 'LaunchAgents');
305
+ const dst = (0, path_1.join)(dstDir, 'com.agent.tempo.plist');
306
+ (0, fs_1.mkdirSync)(dstDir, { recursive: true });
307
+ (0, fs_1.copyFileSync)(src, dst);
308
+ out.success(`Installed launchd agent: ${dst}`);
309
+ out.warn(' NOTE: macOS launchd integration is best-effort — feedback welcome.');
310
+ try {
311
+ (0, child_process_1.execFileSync)('launchctl', ['load', dst], { stdio: 'ignore' });
312
+ out.log(' Loaded: launchctl load ' + dst);
313
+ }
314
+ catch {
315
+ out.warn(' launchctl invocation failed — run manually:');
316
+ out.log(` ${out.dim(`launchctl load ${dst}`)}`);
317
+ }
318
+ return;
319
+ }
320
+ if (platform === 'win32') {
321
+ const script = packagingFile('windows', 'install-task.ps1');
322
+ try {
323
+ (0, child_process_1.execFileSync)('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', script], { stdio: 'inherit' });
324
+ }
325
+ catch (err) {
326
+ out.error(`Failed to register scheduled task: ${err?.message ?? err}`);
327
+ process.exit(1);
328
+ }
329
+ return;
330
+ }
331
+ out.error(`Unsupported platform: ${platform}`);
332
+ out.log(' Supported: linux (systemd --user), darwin (launchd), win32 (Task Scheduler).');
333
+ process.exit(1);
334
+ }
335
+ async function daemonUninstall() {
336
+ const platform = process.platform;
337
+ if (platform === 'linux') {
338
+ // Backward-compat: clean up either the new (`agent-tempo.service`) or
339
+ // legacy (`agent-tempo.service`) unit so v0.x installs migrate cleanly.
340
+ const dirSystemd = (0, path_1.join)((0, os_1.homedir)(), '.config', 'systemd', 'user');
341
+ const dstNew = (0, path_1.join)(dirSystemd, 'agent-tempo.service');
342
+ const dstLegacy = (0, path_1.join)(dirSystemd, 'agent-tempo.service');
343
+ for (const svc of ['agent-tempo', 'agent-tempo']) {
344
+ try {
345
+ (0, child_process_1.execFileSync)('systemctl', ['--user', 'disable', '--now', svc], { stdio: 'ignore' });
346
+ }
347
+ catch { /* may not be running */ }
348
+ }
349
+ let removed = false;
350
+ try {
351
+ for (const dst of [dstNew, dstLegacy]) {
352
+ if ((0, fs_1.existsSync)(dst)) {
353
+ (0, fs_1.unlinkSync)(dst);
354
+ out.success(`Removed ${dst}`);
355
+ removed = true;
356
+ }
357
+ }
358
+ if (!removed)
359
+ out.log('No systemd unit file found.');
360
+ }
361
+ catch (err) {
362
+ out.error(`Failed to remove systemd unit: ${err?.message ?? err}`);
363
+ process.exit(1);
364
+ }
365
+ return;
366
+ }
367
+ if (platform === 'darwin') {
368
+ // Backward-compat: clean up either the new (`com.agent.tempo.plist`) or
369
+ // legacy (`com.claude.tempo.plist`) plist so v0.x installs migrate cleanly.
370
+ const dstNew = (0, path_1.join)((0, os_1.homedir)(), 'Library', 'LaunchAgents', 'com.agent.tempo.plist');
371
+ const dstLegacy = (0, path_1.join)((0, os_1.homedir)(), 'Library', 'LaunchAgents', 'com.claude.tempo.plist');
372
+ let removed = false;
373
+ for (const dst of [dstNew, dstLegacy]) {
374
+ try {
375
+ (0, child_process_1.execFileSync)('launchctl', ['unload', dst], { stdio: 'ignore' });
376
+ }
377
+ catch { /* may not be loaded */ }
378
+ if ((0, fs_1.existsSync)(dst)) {
379
+ (0, fs_1.unlinkSync)(dst);
380
+ out.success(`Removed ${dst}`);
381
+ removed = true;
382
+ }
383
+ }
384
+ if (!removed)
385
+ out.log('No launchd plist found.');
386
+ return;
387
+ }
388
+ if (platform === 'win32') {
389
+ const script = packagingFile('windows', 'install-task.ps1');
390
+ try {
391
+ (0, child_process_1.execFileSync)('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', script, '-Uninstall'], { stdio: 'inherit' });
392
+ }
393
+ catch (err) {
394
+ out.error(`Failed to unregister scheduled task: ${err?.message ?? err}`);
395
+ process.exit(1);
396
+ }
397
+ return;
398
+ }
399
+ out.error(`Unsupported platform: ${platform}`);
400
+ process.exit(1);
401
+ }
402
+ /** Pretty-print a byte count as MB (rounded). Pure helper, exported for tests. */
403
+ function formatBytesAsMb(n) {
404
+ if (typeof n !== 'number' || !Number.isFinite(n))
405
+ return 'n/a';
406
+ return `${Math.round(n / (1024 * 1024))} MB`;
407
+ }
408
+ /** Pretty-print a millisecond uptime as `Xh Ym Zs`. Pure helper, exported for tests. */
409
+ function formatUptime(ms) {
410
+ if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0)
411
+ return 'n/a';
412
+ const totalSec = Math.floor(ms / 1000);
413
+ const hours = Math.floor(totalSec / 3600);
414
+ const minutes = Math.floor((totalSec % 3600) / 60);
415
+ const seconds = totalSec % 60;
416
+ if (hours > 0)
417
+ return `${hours}h ${minutes}m ${seconds}s`;
418
+ if (minutes > 0)
419
+ return `${minutes}m ${seconds}s`;
420
+ return `${seconds}s`;
421
+ }
422
+ /** GET `http://127.0.0.1:<port>/v1/health` and parse the JSON body. Used by `daemon stats`. */
423
+ function fetchHealth(port) {
424
+ return new Promise((resolve, reject) => {
425
+ const req = http.request({ hostname: '127.0.0.1', port, path: '/v1/health', method: 'GET', timeout: 3000 }, (res) => {
426
+ const chunks = [];
427
+ res.on('data', (c) => chunks.push(c));
428
+ res.on('end', () => {
429
+ if (res.statusCode !== 200) {
430
+ reject(new Error(`HTTP ${res.statusCode}`));
431
+ return;
432
+ }
433
+ try {
434
+ resolve(JSON.parse(Buffer.concat(chunks).toString('utf8')));
435
+ }
436
+ catch (err) {
437
+ reject(err);
438
+ }
439
+ });
440
+ });
441
+ req.on('error', reject);
442
+ req.on('timeout', () => {
443
+ req.destroy(new Error('request timed out after 3000ms'));
444
+ });
445
+ req.end();
446
+ });
447
+ }
448
+ /**
449
+ * Render the `daemon stats` payload to stdout. Filed under #336 — gives
450
+ * operators a one-shot way to spot daemon memory growth without tailing
451
+ * logs or attaching a debugger.
452
+ */
453
+ async function daemonStats() {
454
+ // First check the daemon is even running — surface a friendlier message
455
+ // than a raw ECONNREFUSED if not.
456
+ const status = (0, daemon_1.getDaemonStatus)();
457
+ if (!status.running) {
458
+ out.warn('Daemon is not running — start it with `agent-tempo daemon start`');
459
+ process.exit(1);
460
+ }
461
+ const port = (0, port_file_1.readPortFile)();
462
+ if (port === null) {
463
+ out.error('Daemon port file not found at ~/.agent-tempo/daemon.port');
464
+ out.log(` ${out.dim('The daemon may be from a pre-HTTP build. Restart it with `agent-tempo daemon stop && start`.')}`);
465
+ process.exit(1);
466
+ }
467
+ let body;
468
+ try {
469
+ body = await fetchHealth(port);
470
+ }
471
+ catch (err) {
472
+ out.error(`Failed to query daemon at http://127.0.0.1:${port}/v1/health: ${err instanceof Error ? err.message : err}`);
473
+ process.exit(1);
474
+ }
475
+ out.success(`Daemon stats (pid ${status.pid})`);
476
+ out.log(` ${out.dim('Version: ')}${typeof body.version === 'string' ? body.version : 'n/a'}`);
477
+ out.log(` ${out.dim('Namespace: ')}${typeof body.namespace === 'string' ? body.namespace : 'n/a'}`);
478
+ out.log(` ${out.dim('Uptime: ')}${formatUptime(body.uptimeMs)}`);
479
+ out.log(` ${out.dim('Ensembles: ')}${typeof body.ensembleCount === 'number' ? body.ensembleCount : 'n/a'}`);
480
+ out.log(` ${out.dim('SSE subscribers:')}${typeof body.subscriberCount === 'number' ? ` ${body.subscriberCount}` : ' n/a'}`);
481
+ out.log('');
482
+ if (body.memory) {
483
+ out.log(` ${out.dim('Memory (#336 diagnostic):')}`);
484
+ out.log(` ${out.dim('RSS: ')}${formatBytesAsMb(body.memory.rss)}`);
485
+ out.log(` ${out.dim('Heap used: ')}${formatBytesAsMb(body.memory.heapUsed)}`);
486
+ out.log(` ${out.dim('Heap total: ')}${formatBytesAsMb(body.memory.heapTotal)}`);
487
+ out.log(` ${out.dim('External: ')}${formatBytesAsMb(body.memory.external)}`);
488
+ out.log(` ${out.dim('Array buffers: ')}${formatBytesAsMb(body.memory.arrayBuffers)}`);
489
+ }
490
+ else {
491
+ out.warn('Memory diagnostics not present in /v1/health response — daemon may be from a pre-#336 build.');
492
+ }
493
+ }