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,67 @@
1
+ import { type PersistedConfig } from '../config';
2
+ /**
3
+ * Is the bind address effectively loopback? `0.0.0.0` is NOT loopback
4
+ * (it binds every interface, including external ones).
5
+ */
6
+ export declare function isLoopbackBindAddr(bindAddr: string): boolean;
7
+ /**
8
+ * Parse an `Origin` header to a hostname. Returns `null` when the header
9
+ * is absent, empty, or unparseable as a URL — caller decides the policy.
10
+ */
11
+ export declare function originHost(originHeader: string | undefined): string | null;
12
+ /**
13
+ * Decide whether bearer mode applies to this request, given the daemon's
14
+ * bind addr and the request's `Origin` header.
15
+ *
16
+ * - bind addr non-loopback → always bearer (`true`)
17
+ * - no Origin header on loopback bind → loopback mode (`false`)
18
+ * - Origin host is loopback on loopback bind → loopback mode (`false`)
19
+ * - Origin host is non-loopback OR unparseable on loopback bind → bearer (`true`)
20
+ */
21
+ export declare function bearerRequired(bindAddr: string, originHeader: string | undefined): boolean;
22
+ /**
23
+ * Extract the Bearer token from an `Authorization` header. Returns `null`
24
+ * when the header is missing or doesn't start with the `Bearer ` prefix
25
+ * (case-sensitive per RFC 6750 §2.1). Whitespace inside the token is
26
+ * preserved — comparison is constant-time exact match.
27
+ */
28
+ export declare function extractBearerToken(authHeader: string | undefined): string | null;
29
+ /**
30
+ * Constant-time token comparison.
31
+ *
32
+ * **Length-leak tradeoff** (PR-1 review followup): the leading
33
+ * length-mismatch short-circuit reveals the expected token length to a
34
+ * timing observer who can measure the difference between "rejected
35
+ * before constant-time compare" and "ran the full constant-time
36
+ * compare". Mitigations considered:
37
+ *
38
+ * 1. Pad the received token to a fixed length before comparison.
39
+ * Adds branching in the pad path that itself can leak via timing.
40
+ * 2. Use HMAC-then-compare to render length irrelevant at the cost of
41
+ * an extra hash per request.
42
+ *
43
+ * Neither is worth it for a token whose length is fixed by our own
44
+ * generator (`crypto.randomBytes(32).toString('base64url')` is always
45
+ * 43 chars). An attacker observing length learns nothing they can't
46
+ * trivially guess from inspecting the daemon's source. Without the
47
+ * length gate `crypto.timingSafeEqual` throws on mismatched lengths,
48
+ * which would force a try/catch in the hot path with worse timing
49
+ * properties. Document the assumption here so a future contributor
50
+ * reading "constant-time" doesn't assume length is also blinded.
51
+ */
52
+ export declare function tokensMatch(received: string, expected: string): boolean;
53
+ /**
54
+ * Load (or auto-generate) the daemon's HTTP bearer token.
55
+ *
56
+ * - When `bearerRequired` is true and the persisted config has no
57
+ * `httpToken`, generate one (`crypto.randomBytes(32).toString('base64url')`)
58
+ * and persist it via `saveConfigFile` (which sets 0600 on POSIX).
59
+ * - When `bearerRequired` is false, return whatever is in the config
60
+ * without generating — operators may still want a token saved for
61
+ * future use, and we shouldn't write secrets the user didn't request.
62
+ */
63
+ export declare function loadOrGenerateHttpToken(opts: {
64
+ bearerRequired: boolean;
65
+ load?: () => PersistedConfig;
66
+ save?: (cfg: PersistedConfig) => void;
67
+ }): string | null;
@@ -0,0 +1,177 @@
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.isLoopbackBindAddr = isLoopbackBindAddr;
37
+ exports.originHost = originHost;
38
+ exports.bearerRequired = bearerRequired;
39
+ exports.extractBearerToken = extractBearerToken;
40
+ exports.tokensMatch = tokensMatch;
41
+ exports.loadOrGenerateHttpToken = loadOrGenerateHttpToken;
42
+ /**
43
+ * Authentication for the daemon HTTP surface (SSE-PROTOCOL.md §3).
44
+ *
45
+ * **Two modes**:
46
+ *
47
+ * - **Loopback** (default, no auth) — bind addr is loopback AND the request
48
+ * has no `Origin` header (curl, supervisord) OR `Origin` resolves to a
49
+ * loopback host. Single-user dev workflows hit this path.
50
+ *
51
+ * - **Bearer** — required when bind addr is non-loopback (`0.0.0.0`) OR
52
+ * when the request's `Origin` is non-loopback. Defends against DNS
53
+ * rebinding even on a loopback-bound daemon: a malicious page on the
54
+ * user's machine resolving `evil.com` to `127.0.0.1` cannot read the
55
+ * daemon without the bearer token.
56
+ *
57
+ * `/v1/health` is **never authenticated** — it's the liveness probe used
58
+ * by reverse proxies, supervisord, and the TUI bootstrap state machine.
59
+ *
60
+ * **Token storage** (§3.1) — `~/.agent-tempo/config.json` field
61
+ * `httpToken`. Auto-generated on first daemon boot when bearer mode is
62
+ * required and no token is set: `crypto.randomBytes(32).toString('base64url')`,
63
+ * 0600 on POSIX. Rotation = delete the field; next daemon boot regenerates.
64
+ */
65
+ const crypto = __importStar(require("crypto"));
66
+ const config_1 = require("../config");
67
+ /** Hostnames that count as loopback for §3 mode determination. */
68
+ const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', '[::1]', 'localhost']);
69
+ /**
70
+ * Is the bind address effectively loopback? `0.0.0.0` is NOT loopback
71
+ * (it binds every interface, including external ones).
72
+ */
73
+ function isLoopbackBindAddr(bindAddr) {
74
+ return LOOPBACK_HOSTS.has(bindAddr);
75
+ }
76
+ /**
77
+ * Parse an `Origin` header to a hostname. Returns `null` when the header
78
+ * is absent, empty, or unparseable as a URL — caller decides the policy.
79
+ */
80
+ function originHost(originHeader) {
81
+ if (!originHeader)
82
+ return null;
83
+ try {
84
+ const url = new URL(originHeader);
85
+ return url.hostname;
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ }
91
+ /**
92
+ * Decide whether bearer mode applies to this request, given the daemon's
93
+ * bind addr and the request's `Origin` header.
94
+ *
95
+ * - bind addr non-loopback → always bearer (`true`)
96
+ * - no Origin header on loopback bind → loopback mode (`false`)
97
+ * - Origin host is loopback on loopback bind → loopback mode (`false`)
98
+ * - Origin host is non-loopback OR unparseable on loopback bind → bearer (`true`)
99
+ */
100
+ function bearerRequired(bindAddr, originHeader) {
101
+ if (!isLoopbackBindAddr(bindAddr))
102
+ return true;
103
+ if (!originHeader)
104
+ return false;
105
+ const host = originHost(originHeader);
106
+ if (host == null)
107
+ return true; // unparseable Origin → fail safe
108
+ return !LOOPBACK_HOSTS.has(host);
109
+ }
110
+ /**
111
+ * Extract the Bearer token from an `Authorization` header. Returns `null`
112
+ * when the header is missing or doesn't start with the `Bearer ` prefix
113
+ * (case-sensitive per RFC 6750 §2.1). Whitespace inside the token is
114
+ * preserved — comparison is constant-time exact match.
115
+ */
116
+ function extractBearerToken(authHeader) {
117
+ if (!authHeader)
118
+ return null;
119
+ const prefix = 'Bearer ';
120
+ if (!authHeader.startsWith(prefix))
121
+ return null;
122
+ return authHeader.slice(prefix.length);
123
+ }
124
+ /**
125
+ * Constant-time token comparison.
126
+ *
127
+ * **Length-leak tradeoff** (PR-1 review followup): the leading
128
+ * length-mismatch short-circuit reveals the expected token length to a
129
+ * timing observer who can measure the difference between "rejected
130
+ * before constant-time compare" and "ran the full constant-time
131
+ * compare". Mitigations considered:
132
+ *
133
+ * 1. Pad the received token to a fixed length before comparison.
134
+ * Adds branching in the pad path that itself can leak via timing.
135
+ * 2. Use HMAC-then-compare to render length irrelevant at the cost of
136
+ * an extra hash per request.
137
+ *
138
+ * Neither is worth it for a token whose length is fixed by our own
139
+ * generator (`crypto.randomBytes(32).toString('base64url')` is always
140
+ * 43 chars). An attacker observing length learns nothing they can't
141
+ * trivially guess from inspecting the daemon's source. Without the
142
+ * length gate `crypto.timingSafeEqual` throws on mismatched lengths,
143
+ * which would force a try/catch in the hot path with worse timing
144
+ * properties. Document the assumption here so a future contributor
145
+ * reading "constant-time" doesn't assume length is also blinded.
146
+ */
147
+ function tokensMatch(received, expected) {
148
+ if (received.length !== expected.length)
149
+ return false;
150
+ const a = Buffer.from(received, 'utf8');
151
+ const b = Buffer.from(expected, 'utf8');
152
+ return crypto.timingSafeEqual(a, b);
153
+ }
154
+ /**
155
+ * Load (or auto-generate) the daemon's HTTP bearer token.
156
+ *
157
+ * - When `bearerRequired` is true and the persisted config has no
158
+ * `httpToken`, generate one (`crypto.randomBytes(32).toString('base64url')`)
159
+ * and persist it via `saveConfigFile` (which sets 0600 on POSIX).
160
+ * - When `bearerRequired` is false, return whatever is in the config
161
+ * without generating — operators may still want a token saved for
162
+ * future use, and we shouldn't write secrets the user didn't request.
163
+ */
164
+ function loadOrGenerateHttpToken(opts) {
165
+ const load = opts.load ?? config_1.loadConfigFile;
166
+ const save = opts.save ?? config_1.saveConfigFile;
167
+ const cfg = load();
168
+ if (cfg.httpToken && typeof cfg.httpToken === 'string' && cfg.httpToken.length > 0) {
169
+ return cfg.httpToken;
170
+ }
171
+ if (!opts.bearerRequired)
172
+ return null;
173
+ // Auto-generate. base64url chars are safe inside Authorization values.
174
+ const token = crypto.randomBytes(32).toString('base64url');
175
+ save({ ...cfg, httpToken: token });
176
+ return token;
177
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Shared HTTP body-reading helpers.
3
+ *
4
+ * Extracted from `writes.ts` so catalog/write/dashboard handlers all
5
+ * use the same JSON parser + size cap. The cap is enforced before
6
+ * parsing so a 1 GiB upload can't OOM the daemon.
7
+ *
8
+ * Sentinels (rather than thrown errors) keep the parse path branch-free
9
+ * — handlers compare against `BODY_TOO_LARGE` / `BODY_INVALID_JSON` and
10
+ * map to the appropriate 4xx response.
11
+ */
12
+ import type { IncomingMessage, ServerResponse } from 'http';
13
+ import { type AgentType } from '../types';
14
+ /** Hard cap on incoming JSON body size (1 MiB). */
15
+ export declare const WRITE_BODY_MAX: number;
16
+ export declare const BODY_TOO_LARGE: unique symbol;
17
+ export declare const BODY_INVALID_JSON: unique symbol;
18
+ export type ReadJsonBodyResult = Record<string, unknown> | typeof BODY_TOO_LARGE | typeof BODY_INVALID_JSON;
19
+ /**
20
+ * Read the request body up to {@link WRITE_BODY_MAX} bytes and parse
21
+ * as JSON. Returns the parsed object, an empty object for empty
22
+ * bodies, or one of the sentinel symbols for cap / parse failures.
23
+ *
24
+ * Note on the cap path: returning early from this function ends body
25
+ * consumption; Node's HTTP server tears down the upload when the
26
+ * handler ends. Explicit `req.destroy()` would race the response
27
+ * write — left alone.
28
+ */
29
+ export declare function readJsonBody(req: IncomingMessage): Promise<ReadJsonBodyResult>;
30
+ /**
31
+ * Pluck a string field from a parsed JSON body. Returns `undefined`
32
+ * for absent or non-string values; with `requireNonEmpty: true`, also
33
+ * filters empty strings (used by routes that accept optional fields
34
+ * — empty strings shouldn't propagate to downstream Temporal calls
35
+ * as if the user typed something).
36
+ */
37
+ export declare function stringField(body: Record<string, unknown>, key: string, opts?: {
38
+ requireNonEmpty?: boolean;
39
+ }): string | undefined;
40
+ /**
41
+ * Agent allowlists, derived from {@link AGENT_TYPES} (the SSOT in
42
+ * `src/types.ts`).
43
+ *
44
+ * `'mock'` is dev-mode-only — see ADR 0014 §7. Read at request time so
45
+ * toggling `AGENT_TEMPO_DEV_MODE` between requests is picked up without
46
+ * restart (parity with `src/tools/recruit.ts`).
47
+ *
48
+ * Deriving from `AGENT_TYPES` rather than hardcoding the list closes the
49
+ * #541 drift bug: every new adapter (`claude-api`, `opencode`,
50
+ * `claude-code-headless`, …) added to the SSOT is automatically accepted
51
+ * by the HTTP recruit endpoint, instead of being silently rejected by an
52
+ * allowlist that someone forgot to update.
53
+ */
54
+ export declare const ALLOWED_AGENTS_DEV: readonly AgentType[];
55
+ export declare const ALLOWED_AGENTS_PROD: readonly AgentType[];
56
+ export declare function allowedAgentsForCurrentMode(): readonly AgentType[];
57
+ export declare function isAllowedAgent(s: string, allowed: readonly AgentType[]): s is AgentType;
58
+ /**
59
+ * Pluck a required `playerId` from a parsed body, validating shape.
60
+ *
61
+ * Returns the `playerId` string on success. On any failure (missing or
62
+ * malformed) writes the appropriate 400 response via `errorResponse` and
63
+ * returns `undefined`. **Callers MUST check the return value and bail
64
+ * out** — a missing `if (!playerId) return;` would silently skip the
65
+ * downstream client call and double-send to the response stream.
66
+ *
67
+ * Shared by every per-player route under `/v1/ensembles/:ensemble/<action>`
68
+ * (restart / destroy / detach / recall — `release` keeps an inline check
69
+ * because its `playerId` field is optional, not required).
70
+ */
71
+ export declare function requirePlayerId(res: ServerResponse, body: Record<string, unknown>): string | undefined;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALLOWED_AGENTS_PROD = exports.ALLOWED_AGENTS_DEV = exports.BODY_INVALID_JSON = exports.BODY_TOO_LARGE = exports.WRITE_BODY_MAX = void 0;
4
+ exports.readJsonBody = readJsonBody;
5
+ exports.stringField = stringField;
6
+ exports.allowedAgentsForCurrentMode = allowedAgentsForCurrentMode;
7
+ exports.isAllowedAgent = isAllowedAgent;
8
+ exports.requirePlayerId = requirePlayerId;
9
+ const types_1 = require("../types");
10
+ const config_1 = require("../config");
11
+ const responses_1 = require("./responses");
12
+ const validation_1 = require("../utils/validation");
13
+ /** Hard cap on incoming JSON body size (1 MiB). */
14
+ exports.WRITE_BODY_MAX = 1024 * 1024;
15
+ exports.BODY_TOO_LARGE = Symbol('body-too-large');
16
+ exports.BODY_INVALID_JSON = Symbol('body-invalid-json');
17
+ /**
18
+ * Read the request body up to {@link WRITE_BODY_MAX} bytes and parse
19
+ * as JSON. Returns the parsed object, an empty object for empty
20
+ * bodies, or one of the sentinel symbols for cap / parse failures.
21
+ *
22
+ * Note on the cap path: returning early from this function ends body
23
+ * consumption; Node's HTTP server tears down the upload when the
24
+ * handler ends. Explicit `req.destroy()` would race the response
25
+ * write — left alone.
26
+ */
27
+ async function readJsonBody(req) {
28
+ const chunks = [];
29
+ let total = 0;
30
+ for await (const chunk of req) {
31
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
32
+ total += buf.length;
33
+ if (total > exports.WRITE_BODY_MAX)
34
+ return exports.BODY_TOO_LARGE;
35
+ chunks.push(buf);
36
+ }
37
+ if (total === 0)
38
+ return {};
39
+ try {
40
+ const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
41
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
42
+ return exports.BODY_INVALID_JSON;
43
+ }
44
+ return parsed;
45
+ }
46
+ catch {
47
+ return exports.BODY_INVALID_JSON;
48
+ }
49
+ }
50
+ /**
51
+ * Pluck a string field from a parsed JSON body. Returns `undefined`
52
+ * for absent or non-string values; with `requireNonEmpty: true`, also
53
+ * filters empty strings (used by routes that accept optional fields
54
+ * — empty strings shouldn't propagate to downstream Temporal calls
55
+ * as if the user typed something).
56
+ */
57
+ function stringField(body, key, opts = {}) {
58
+ const v = body[key];
59
+ if (typeof v !== 'string')
60
+ return undefined;
61
+ if (opts.requireNonEmpty && v.length === 0)
62
+ return undefined;
63
+ return v;
64
+ }
65
+ /**
66
+ * Dev-mode-only agent identifiers — must never appear in {@link ALLOWED_AGENTS_PROD}.
67
+ *
68
+ * Currently just `'mock'` (ADR 0014 §7). Listed explicitly so the prod
69
+ * allowlist below is "everything in {@link AGENT_TYPES} minus this set",
70
+ * which keeps the dev-only gate auditable and the derived prod list
71
+ * automatically picks up new adapters as they land in `AGENT_TYPES`
72
+ * (#541 — the drift bug this constant prevents).
73
+ */
74
+ const DEV_ONLY_AGENTS = new Set(['mock']);
75
+ /**
76
+ * Agent allowlists, derived from {@link AGENT_TYPES} (the SSOT in
77
+ * `src/types.ts`).
78
+ *
79
+ * `'mock'` is dev-mode-only — see ADR 0014 §7. Read at request time so
80
+ * toggling `AGENT_TEMPO_DEV_MODE` between requests is picked up without
81
+ * restart (parity with `src/tools/recruit.ts`).
82
+ *
83
+ * Deriving from `AGENT_TYPES` rather than hardcoding the list closes the
84
+ * #541 drift bug: every new adapter (`claude-api`, `opencode`,
85
+ * `claude-code-headless`, …) added to the SSOT is automatically accepted
86
+ * by the HTTP recruit endpoint, instead of being silently rejected by an
87
+ * allowlist that someone forgot to update.
88
+ */
89
+ exports.ALLOWED_AGENTS_DEV = types_1.AGENT_TYPES;
90
+ exports.ALLOWED_AGENTS_PROD = types_1.AGENT_TYPES.filter((a) => !DEV_ONLY_AGENTS.has(a));
91
+ function allowedAgentsForCurrentMode() {
92
+ return (0, config_1.isDevMode)() ? exports.ALLOWED_AGENTS_DEV : exports.ALLOWED_AGENTS_PROD;
93
+ }
94
+ function isAllowedAgent(s, allowed) {
95
+ return allowed.includes(s);
96
+ }
97
+ /**
98
+ * Pluck a required `playerId` from a parsed body, validating shape.
99
+ *
100
+ * Returns the `playerId` string on success. On any failure (missing or
101
+ * malformed) writes the appropriate 400 response via `errorResponse` and
102
+ * returns `undefined`. **Callers MUST check the return value and bail
103
+ * out** — a missing `if (!playerId) return;` would silently skip the
104
+ * downstream client call and double-send to the response stream.
105
+ *
106
+ * Shared by every per-player route under `/v1/ensembles/:ensemble/<action>`
107
+ * (restart / destroy / detach / recall — `release` keeps an inline check
108
+ * because its `playerId` field is optional, not required).
109
+ */
110
+ function requirePlayerId(res, body) {
111
+ const playerId = stringField(body, 'playerId');
112
+ if (!playerId) {
113
+ (0, responses_1.errorResponse)(res, 400, { error: 'missing-field', field: 'playerId' });
114
+ return undefined;
115
+ }
116
+ if ((0, validation_1.validatePlayerName)(playerId) !== null) {
117
+ (0, responses_1.errorResponse)(res, 400, { error: 'invalid-player-name', field: 'playerId' });
118
+ return undefined;
119
+ }
120
+ return playerId;
121
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Daemon HTTP catalog routes — issue #400.
3
+ *
4
+ * Three endpoints exposing on-disk catalog data so the dashboard's
5
+ * Recruit + CreateEnsemble + Loadouts + PlayerTypes wizards can drop
6
+ * the hardcoded fallbacks shipped during PR-E + PR-F:
7
+ *
8
+ * - GET /v1/agent-types → `listAgentTypes()` from ensemble/agent-types.ts
9
+ * - GET /v1/lineups → `listLineups()` from ensemble/loader.ts
10
+ * - POST /v1/ensembles → recruit a conductor (+ lineup players)
11
+ *
12
+ * Auth + CORS gating happens in `server.ts` before the dispatcher
13
+ * reaches these handlers; no per-handler bearer check needed.
14
+ *
15
+ * Response shapes match the issue #400 wire spec; see also
16
+ * `docs/WIRE-PROTOCOL.md` for the full HTTP catalog.
17
+ */
18
+ import type { IncomingMessage, ServerResponse } from 'http';
19
+ import type { TempoClient } from '../client/interface';
20
+ export interface AgentTypeRow {
21
+ name: string;
22
+ description?: string;
23
+ source: 'project' | 'user' | 'shipped';
24
+ }
25
+ /**
26
+ * `listAgentTypes()` returns rows with `path` + `nativeResolvable` +
27
+ * optional `allowedTools` — the dashboard only needs name/description/
28
+ * source. Strip the rest so we don't leak filesystem paths over the
29
+ * wire (loopback bind is the common case but the API is also reachable
30
+ * over LAN behind bearer auth — same privacy contract as `HostProfile`
31
+ * stripping in `src/types.ts`).
32
+ */
33
+ export declare function handleListAgentTypes(res: ServerResponse): void;
34
+ export interface LineupRow {
35
+ name: string;
36
+ description?: string;
37
+ players: number;
38
+ source: 'saved' | 'shipped';
39
+ }
40
+ export declare function handleListLineups(res: ServerResponse): void;
41
+ /**
42
+ * POST `/v1/ensembles` — create a fresh ensemble.
43
+ *
44
+ * The bootstrap path is the daemon-side equivalent of the CLI's
45
+ * `agent-tempo up` codepath, but trimmed to the actions the daemon
46
+ * can run for a browser caller:
47
+ *
48
+ * 1. Validate the body (name regex, lineup exists if specified,
49
+ * startMode in {hold, release}).
50
+ * 2. Reject 409 if an ensemble with that name is already live.
51
+ * 3. Recruit the conductor (`isConductor: true`) — this bootstraps
52
+ * the maestro + scheduler + conductor-session workflows.
53
+ * 4. Recruit each lineup player. Inherits `host` + `held` from the
54
+ * top-level body when the lineup row doesn't specify its own.
55
+ * 5. Return 201 + the ensemble summary so the dashboard can
56
+ * navigate to `/ensemble/:name` without a follow-up snapshot
57
+ * fetch.
58
+ *
59
+ * Skipped vs CLI `up` (intentional):
60
+ * - No Temporal-server start: the daemon serving this request
61
+ * already proves Temporal is up.
62
+ * - No daemon start / agent-type install / MCP register: a browser
63
+ * caller doesn't go through that pre-flight.
64
+ * - No interactive "ensemble already exists" choice tree: HTTP is
65
+ * stateless; we 409 and let the dashboard surface a useful error.
66
+ */
67
+ export declare function handleCreateEnsemble(req: IncomingMessage, res: ServerResponse, client: TempoClient): Promise<void>;