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,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.probeClaudeBinary = probeClaudeBinary;
4
+ exports.probeClaudeAuth = probeClaudeAuth;
5
+ exports.parseAuthStatusOutput = parseAuthStatusOutput;
6
+ /**
7
+ * Pre-flight probes for the claude-code-headless adapter.
8
+ *
9
+ * Two checks, both invoked from `src/tools/recruit.ts` before submitting the
10
+ * spawn outbox entry; both also re-used by the daemon boot probe (PR-2) so
11
+ * cross-host recruit can fail fast against an unconfigured host.
12
+ *
13
+ * 1. **Binary probe** — `claude --version` exits 0 within 3s. Catches the
14
+ * "Claude Code not installed" case with an actionable error, distinct
15
+ * from "logged out" (#2 below).
16
+ * 2. **Auth probe** — `claude auth status` exits 0 within 5s and emits a
17
+ * JSON envelope with `loggedIn: true`. Confirms the host's Claude Code
18
+ * CLI has a usable OAuth session — which is the whole point of this
19
+ * adapter (subscription extra-usage credits, design §1).
20
+ *
21
+ * Both probes are pure observers — they make NO billed API call and NO
22
+ * subprocess that registers as an ensemble player. The auth probe is an
23
+ * official `claude auth` subcommand; the version probe is a one-line
24
+ * `--version` invocation.
25
+ *
26
+ * Spike findings (issue #520 §11.3, captured 2026-05-02): `claude auth
27
+ * status` outputs JSON in all logged-in states; exit code is 0 even when
28
+ * logged out, so the boolean `loggedIn` field is the source of truth.
29
+ *
30
+ * Design reference: `docs/design/520-claude-code-headless-adapter.md`
31
+ * §3.4 (recruit pre-flight contract)
32
+ * §11.3 (auth-status parser fixtures)
33
+ */
34
+ const child_process_1 = require("child_process");
35
+ const VERSION_PROBE_TIMEOUT_MS = 3_000;
36
+ const AUTH_PROBE_TIMEOUT_MS = 5_000;
37
+ /**
38
+ * Probe whether `claude --version` is callable on the host PATH and returns
39
+ * a parseable version string. Bounded by {@link VERSION_PROBE_TIMEOUT_MS} so
40
+ * a hung binary can't stall the recruit pre-flight.
41
+ *
42
+ * Returns `{ ok: false, error }` for missing binary, hung process, or
43
+ * non-zero exit. The error string is operator-actionable (mentions both
44
+ * "install" and "PATH" so the user knows where to start).
45
+ */
46
+ function probeClaudeBinary(claudeBin = 'claude') {
47
+ let result;
48
+ try {
49
+ result = (0, child_process_1.spawnSync)(claudeBin, ['--version'], {
50
+ stdio: ['ignore', 'pipe', 'pipe'],
51
+ timeout: VERSION_PROBE_TIMEOUT_MS,
52
+ // shell: false on Windows — npm-installed `claude` is a `.cmd` shim;
53
+ // spawnSync's `shell: false` path won't find it. Workaround: call via
54
+ // `cmd.exe /c` on Windows so the shim resolves.
55
+ shell: false,
56
+ });
57
+ }
58
+ catch (err) {
59
+ return {
60
+ ok: false,
61
+ error: `\`${claudeBin} --version\` failed to spawn: ${err?.message ?? err}. Install Claude Code (https://claude.com/download) and ensure \`${claudeBin}\` is on PATH.`,
62
+ };
63
+ }
64
+ if (result.error && result.error.code === 'ENOENT') {
65
+ // Try Windows `.cmd` fallback — npm-installed CLI binaries land as `.cmd`
66
+ // shims that bare spawnSync without shell can't resolve.
67
+ if (process.platform === 'win32' && claudeBin === 'claude') {
68
+ const winResult = (0, child_process_1.spawnSync)('cmd.exe', ['/c', 'claude', '--version'], {
69
+ stdio: ['ignore', 'pipe', 'pipe'],
70
+ timeout: VERSION_PROBE_TIMEOUT_MS,
71
+ });
72
+ if (winResult.status === 0) {
73
+ const version = (winResult.stdout?.toString('utf8') ?? '').trim();
74
+ return { ok: true, version: parseVersion(version) };
75
+ }
76
+ }
77
+ return {
78
+ ok: false,
79
+ error: `\`${claudeBin}\` not found on PATH. Install Claude Code (https://claude.com/download) and verify \`which ${claudeBin}\` resolves.`,
80
+ };
81
+ }
82
+ // spawnSync sets `signal: 'SIGTERM'` on timeout; status is null in that case.
83
+ if (result.signal === 'SIGTERM' || (result.status === null && result.signal !== null)) {
84
+ return {
85
+ ok: false,
86
+ error: `\`${claudeBin} --version\` timed out after ${VERSION_PROBE_TIMEOUT_MS}ms. The binary may be hung or stuck on a first-run prompt; try \`${claudeBin} --version\` interactively first.`,
87
+ };
88
+ }
89
+ if (result.status !== 0) {
90
+ const stderr = (result.stderr?.toString('utf8') ?? '').trim().slice(0, 200);
91
+ return {
92
+ ok: false,
93
+ error: `\`${claudeBin} --version\` exited ${result.status}${stderr ? `: ${stderr}` : ''}.`,
94
+ };
95
+ }
96
+ const version = parseVersion((result.stdout?.toString('utf8') ?? '').trim());
97
+ return { ok: true, version };
98
+ }
99
+ /**
100
+ * Probe whether the host's Claude Code CLI is logged in to an Anthropic
101
+ * account. Calls `claude auth status` — an official supported subcommand
102
+ * that does NOT make a billed API call.
103
+ *
104
+ * Per spike findings (#520 §11.3), exit code is 0 in all cases — the
105
+ * boolean `loggedIn` field in the JSON envelope is the source of truth.
106
+ *
107
+ * Returns `{ loggedIn: false, error }` for: not-logged-in, malformed JSON,
108
+ * timeout, or spawn failure. Caller surfaces `error` actionably.
109
+ */
110
+ function probeClaudeAuth(claudeBin = 'claude') {
111
+ let result;
112
+ try {
113
+ result = (0, child_process_1.spawnSync)(claudeBin, ['auth', 'status'], {
114
+ stdio: ['ignore', 'pipe', 'pipe'],
115
+ timeout: AUTH_PROBE_TIMEOUT_MS,
116
+ shell: false,
117
+ });
118
+ }
119
+ catch (err) {
120
+ return {
121
+ loggedIn: false,
122
+ error: `\`${claudeBin} auth status\` failed to spawn: ${err?.message ?? err}.`,
123
+ };
124
+ }
125
+ // Windows .cmd shim fallback (mirrors probeClaudeBinary). Per QA Nit 2 from
126
+ // PR-1's review: explicitly check whether the cmd.exe fallback also failed,
127
+ // so the error copy stays "not found on PATH" instead of degrading to the
128
+ // generic "produced no output" the parser would otherwise emit on empty stdout.
129
+ if (result.error && result.error.code === 'ENOENT') {
130
+ if (process.platform === 'win32' && claudeBin === 'claude') {
131
+ result = (0, child_process_1.spawnSync)('cmd.exe', ['/c', 'claude', 'auth', 'status'], {
132
+ stdio: ['ignore', 'pipe', 'pipe'],
133
+ timeout: AUTH_PROBE_TIMEOUT_MS,
134
+ });
135
+ if (result.status !== 0 && (!result.stdout || result.stdout.length === 0)) {
136
+ const stderr = (result.stderr?.toString('utf8') ?? '').trim().slice(0, 200);
137
+ return {
138
+ loggedIn: false,
139
+ error: `\`${claudeBin}\` not found on PATH (cmd.exe shim also failed: ${stderr || `exit ${result.status}`}).`,
140
+ };
141
+ }
142
+ }
143
+ else {
144
+ return { loggedIn: false, error: `\`${claudeBin}\` not found on PATH.` };
145
+ }
146
+ }
147
+ if (result.signal === 'SIGTERM' || (result.status === null && result.signal !== null)) {
148
+ return {
149
+ loggedIn: false,
150
+ error: `\`${claudeBin} auth status\` timed out after ${AUTH_PROBE_TIMEOUT_MS}ms.`,
151
+ };
152
+ }
153
+ const stdout = (result.stdout?.toString('utf8') ?? '').trim();
154
+ return parseAuthStatusOutput(stdout, result.status, claudeBin);
155
+ }
156
+ /**
157
+ * Parse a `claude auth status` stdout envelope. Exported for unit tests
158
+ * that load fixtures from `tests/adapters/fixtures/claude-code-headless/`.
159
+ *
160
+ * Per spike findings, the schema is JSON `{loggedIn, authMethod?, apiProvider?, ...}`.
161
+ * Logged-out variant is `{loggedIn: false}`. We tolerate trailing whitespace
162
+ * and missing optional fields.
163
+ */
164
+ function parseAuthStatusOutput(stdout, exitStatus, claudeBin = 'claude') {
165
+ if (!stdout) {
166
+ return {
167
+ loggedIn: false,
168
+ error: `\`${claudeBin} auth status\` produced no output (exit=${exitStatus}).`,
169
+ };
170
+ }
171
+ let parsed;
172
+ try {
173
+ parsed = JSON.parse(stdout);
174
+ }
175
+ catch (err) {
176
+ return {
177
+ loggedIn: false,
178
+ error: `Failed to parse \`${claudeBin} auth status\` JSON output: ${err?.message ?? err}. First 200 bytes: ${stdout.slice(0, 200)}`,
179
+ };
180
+ }
181
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
182
+ return {
183
+ loggedIn: false,
184
+ error: `\`${claudeBin} auth status\` returned non-object JSON: ${stdout.slice(0, 200)}`,
185
+ };
186
+ }
187
+ const obj = parsed;
188
+ const loggedIn = obj.loggedIn === true;
189
+ const authMethod = typeof obj.authMethod === 'string' ? obj.authMethod : undefined;
190
+ const apiProvider = typeof obj.apiProvider === 'string' ? obj.apiProvider : undefined;
191
+ if (!loggedIn) {
192
+ return {
193
+ loggedIn: false,
194
+ error: `\`${claudeBin}\` is installed but not logged in. Run \`${claudeBin} auth login\` (subscription) or \`${claudeBin} auth setup-token\` (CI/long-lived OAuth), or recruit with \`agent: 'claude-api'\` to use a Console API key instead.`,
195
+ };
196
+ }
197
+ return { loggedIn: true, authMethod, apiProvider };
198
+ }
199
+ /**
200
+ * Parse the version string from `claude --version` stdout. The CLI prints
201
+ * `"2.1.126 (Claude Code)"` — we keep just the dotted-number prefix so
202
+ * downstream comparators work cleanly.
203
+ */
204
+ function parseVersion(raw) {
205
+ const m = raw.match(/^(\d+\.\d+\.\d+(?:[-+][0-9a-zA-Z.]+)?)/);
206
+ return m ? m[1] : raw || undefined;
207
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Pure prompt-building helpers for the claude-code-headless adapter.
3
+ *
4
+ * Issue #536 root cause: `invokeSdkWithBatch` in `adapter.ts` was
5
+ * inlining both the per-message attribution prompt AND the per-turn
6
+ * argv composition, with no `--append-system-prompt` and no
7
+ * MAESTRO_ACK augmentation. The model received only
8
+ * `[from X]: <text>` framing, no MCP-tool guidance, and replied with
9
+ * stdout prose that the adapter captured but had nowhere to deliver
10
+ * — so cues from the dashboard saw zero cue-back replies.
11
+ *
12
+ * This module factors the two prompt-build steps out of the adapter
13
+ * for two reasons:
14
+ *
15
+ * 1. **Testability.** Both helpers are pure — no Temporal client,
16
+ * no subprocess, no filesystem. The test in
17
+ * `tests/adapters/claude-code-headless/prompt.test.ts` exercises
18
+ * every `--append-system-prompt` invariant + every MAESTRO_ACK
19
+ * conditional shape directly, instead of having to stub a
20
+ * whole subprocess + spawn pipeline.
21
+ *
22
+ * 2. **Read-locality.** The `invokeSdkWithBatch` body in
23
+ * `adapter.ts` was already 80+ lines of mixed concerns
24
+ * (subprocess spawn, env hygiene, stream-json read loop,
25
+ * cleanup). Extracting the string composition keeps the per-
26
+ * turn driver focused on the I/O side.
27
+ */
28
+ import type { Message } from '../../types';
29
+ import { buildSdkSystemPrompt } from '../sdk/system-prompt';
30
+ import type { ClaudeCodeHeadlessPermissionMode } from './types';
31
+ /**
32
+ * Compose the per-turn prompt text from the workflow's queued
33
+ * messages. Mirrors copilot's poll-loop pattern at
34
+ * `src/adapters/copilot/adapter.ts:639-645` — same conditional
35
+ * MAESTRO_ACK augmentation per `m.isMaestro`, same `\n\n` join.
36
+ *
37
+ * The attribution prefix is `[from X]:` (matches the pre-#536
38
+ * shape in `invokeSdkWithBatch`); copilot's `[Message from X]:` is
39
+ * stylistic drift from a different vintage but is left unchanged
40
+ * here since #536 is scoped to the cue-back framing fix, not a
41
+ * cross-adapter prompt-styling unification.
42
+ *
43
+ * @returns Empty string when `messages` is empty (no `\n\n` floor).
44
+ */
45
+ export declare function buildPromptText(messages: Message[]): string;
46
+ export interface BuildClaudeArgsOpts {
47
+ /** Deterministic session UUID — pinned via `--session-id` on first
48
+ * turn, found via `--resume` on subsequent turns. */
49
+ sessionId: string;
50
+ /** True when the per-cwd JSONL session file already exists.
51
+ * Toggles `--resume <id>` vs `--session-id <id>` (mutually
52
+ * exclusive in `claude -p` v2.1.126+). */
53
+ isResume: boolean;
54
+ /** Already-stringified inline `--mcp-config` JSON. The adapter
55
+ * computes this from `getConfig()` at call time; the helper just
56
+ * threads the bytes. */
57
+ mcpConfig: string;
58
+ /** Resolved permission mode (default `'acceptEdits'`). Ignored
59
+ * when `dangerouslySkipPermissions` is true — they're mutually
60
+ * exclusive per #520 and rejected at recruit-tool layer. */
61
+ permissionMode: ClaudeCodeHeadlessPermissionMode;
62
+ /** When true, emit `--dangerously-skip-permissions` and skip
63
+ * `--permission-mode`. */
64
+ dangerouslySkipPermissions: boolean;
65
+ /** Per-turn system-prompt content. Pass the result of
66
+ * `buildSdkSystemPrompt({ ensemble })` for the canonical #536
67
+ * framing. */
68
+ systemPrompt: string;
69
+ /** Final positional argument — the prompt text the model receives
70
+ * for this turn. Pass the result of `buildPromptText(messages)`. */
71
+ promptText: string;
72
+ }
73
+ /**
74
+ * Compose the `claude -p` argv for a single turn. Pure function so
75
+ * tests can pin every flag invariant without mocking `spawn`.
76
+ *
77
+ * #536 change: emits `--append-system-prompt <systemPrompt>` to
78
+ * inject the canonical "use your MCP tools to reply" framing into
79
+ * the model's per-request system prompt. The flag is in the request
80
+ * itself, so it dodges the MCP-startup race the priming-turn pattern
81
+ * would otherwise mitigate (per the issue body's "MCP startup race —
82
+ * secondary" footnote).
83
+ *
84
+ * Invariant ordering (kept stable so transcripts and CI snapshots
85
+ * compare cleanly across releases):
86
+ * `-p` → `--output-format` → `--verbose` → `--strict-mcp-config`
87
+ * → `--mcp-config` → `--append-system-prompt`
88
+ * → (`--resume` | `--session-id`)
89
+ * → (`--dangerously-skip-permissions` | `--permission-mode`)
90
+ * → `<promptText>`
91
+ */
92
+ export declare function buildClaudeArgs(opts: BuildClaudeArgsOpts): string[];
93
+ export { buildSdkSystemPrompt };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSdkSystemPrompt = void 0;
4
+ exports.buildPromptText = buildPromptText;
5
+ exports.buildClaudeArgs = buildClaudeArgs;
6
+ const system_prompt_1 = require("../sdk/system-prompt");
7
+ Object.defineProperty(exports, "buildSdkSystemPrompt", { enumerable: true, get: function () { return system_prompt_1.buildSdkSystemPrompt; } });
8
+ /**
9
+ * Compose the per-turn prompt text from the workflow's queued
10
+ * messages. Mirrors copilot's poll-loop pattern at
11
+ * `src/adapters/copilot/adapter.ts:639-645` — same conditional
12
+ * MAESTRO_ACK augmentation per `m.isMaestro`, same `\n\n` join.
13
+ *
14
+ * The attribution prefix is `[from X]:` (matches the pre-#536
15
+ * shape in `invokeSdkWithBatch`); copilot's `[Message from X]:` is
16
+ * stylistic drift from a different vintage but is left unchanged
17
+ * here since #536 is scoped to the cue-back framing fix, not a
18
+ * cross-adapter prompt-styling unification.
19
+ *
20
+ * @returns Empty string when `messages` is empty (no `\n\n` floor).
21
+ */
22
+ function buildPromptText(messages) {
23
+ return messages
24
+ .map((m) => {
25
+ const line = `[from ${m.from}]: ${m.text}`;
26
+ return m.isMaestro ? line + system_prompt_1.MAESTRO_ACK : line;
27
+ })
28
+ .join('\n\n');
29
+ }
30
+ /**
31
+ * Compose the `claude -p` argv for a single turn. Pure function so
32
+ * tests can pin every flag invariant without mocking `spawn`.
33
+ *
34
+ * #536 change: emits `--append-system-prompt <systemPrompt>` to
35
+ * inject the canonical "use your MCP tools to reply" framing into
36
+ * the model's per-request system prompt. The flag is in the request
37
+ * itself, so it dodges the MCP-startup race the priming-turn pattern
38
+ * would otherwise mitigate (per the issue body's "MCP startup race —
39
+ * secondary" footnote).
40
+ *
41
+ * Invariant ordering (kept stable so transcripts and CI snapshots
42
+ * compare cleanly across releases):
43
+ * `-p` → `--output-format` → `--verbose` → `--strict-mcp-config`
44
+ * → `--mcp-config` → `--append-system-prompt`
45
+ * → (`--resume` | `--session-id`)
46
+ * → (`--dangerously-skip-permissions` | `--permission-mode`)
47
+ * → `<promptText>`
48
+ */
49
+ function buildClaudeArgs(opts) {
50
+ return [
51
+ '-p',
52
+ '--output-format', 'stream-json',
53
+ '--verbose',
54
+ '--strict-mcp-config',
55
+ '--mcp-config', opts.mcpConfig,
56
+ // #536 — per-turn system-prompt injection. Without this, the
57
+ // model received only `[from X]: <text>` framing and had no
58
+ // reason to call the `cue` MCP tool to reply.
59
+ '--append-system-prompt', opts.systemPrompt,
60
+ // Mutually exclusive — `claude -p` v2.1.126 rejects the combo
61
+ // `--session-id X --resume X` with: *"--session-id can only be
62
+ // used with --continue or --resume if --fork-session is also
63
+ // specified."* Spike-confirmed during PR-4 §8.4 manual smoke;
64
+ // see #520 design doc §16.9. First turn uses `--session-id`
65
+ // to PIN the deterministic UUID; subsequent turns use `--resume`
66
+ // alone (the resume target IS the same UUID — the JSONL
67
+ // filename embeds it, so claude finds the right session).
68
+ ...(opts.isResume
69
+ ? ['--resume', opts.sessionId]
70
+ : ['--session-id', opts.sessionId]),
71
+ ...(opts.dangerouslySkipPermissions
72
+ ? ['--dangerously-skip-permissions']
73
+ : ['--permission-mode', opts.permissionMode]),
74
+ // Trailing positional argument — the prompt text. The CLI accepts
75
+ // up to ARG_MAX bytes here (Windows: 32KB). Per #520 §11.5 spike
76
+ // check, typical multi-cue batches stay well under the limit.
77
+ opts.promptText,
78
+ ];
79
+ }
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Stream-JSON frame parser for `claude -p --output-format stream-json`.
3
+ *
4
+ * Issue #520 PR-3. Parses the newline-delimited JSON envelope the Claude
5
+ * Code CLI emits during a per-turn invocation, accumulating the bits the
6
+ * adapter needs (assembled assistant text, stop reason, usage, cost, plus
7
+ * the fatal-/transient-classifier inputs).
8
+ *
9
+ * **Schema is grounded in the §11.1 spike fixtures** captured against
10
+ * `claude --version` 2.1.126 — see `tests/adapters/fixtures/claude-code-headless/`.
11
+ * Three deltas vs design §5.3 (documented in §16 spike-findings appendix):
12
+ *
13
+ * 1. **`result` frame has a `subtype: 'success' | 'error'`** — design listed
14
+ * `result` as a top-level type. Reality: `subtype` distinguishes success
15
+ * vs error envelopes. Bonus: `is_error: boolean` + `api_error_status:
16
+ * number | null` are clean classifier inputs (see {@link ResultFrame}).
17
+ * 2. **`system/hook_started` + `system/hook_response` + `system/status`** —
18
+ * not in design. Emitted whenever the host has Claude Code hooks
19
+ * configured (most operators do — SessionStart hooks for project
20
+ * context). The `output`/`stdout` fields can carry arbitrary user
21
+ * content, so we IGNORE them outright (the fixture corpus shows a
22
+ * 107KB SessionStart hook body in real captures).
23
+ * 3. **`rate_limit_event` is a top-level type** — design assumed it was
24
+ * a `system/api_retry` subtype. Reality: it's its own frame. AND it
25
+ * carries TWO signal modes (informational vs action-required) on the
26
+ * same wire shape, distinguished by `rate_limit_info.status`. See
27
+ * {@link RateLimitEvent}.
28
+ *
29
+ * Pure code; no I/O; trivially unit-testable with synthesized + captured
30
+ * fixtures. The error classifier (`./error-mapper.ts`) consumes the
31
+ * accumulator state to emit a single `ApiErrorCategory` per turn.
32
+ */
33
+ /**
34
+ * Permissive frame shape — `claude -p` may add fields between minor versions.
35
+ * Every concrete frame type is a discriminated subset.
36
+ */
37
+ export interface BaseFrame {
38
+ type: string;
39
+ subtype?: string;
40
+ uuid?: string;
41
+ session_id?: string;
42
+ }
43
+ /** First frame of every turn. Used for telemetry — not classifier input. */
44
+ export interface SystemInitFrame extends BaseFrame {
45
+ type: 'system';
46
+ subtype: 'init';
47
+ /** `'none'` when running on OAuth (subscription billing — the v0.28 default). */
48
+ apiKeySource?: string;
49
+ cwd?: string;
50
+ model?: string;
51
+ permissionMode?: string;
52
+ claude_code_version?: string;
53
+ tools?: string[];
54
+ mcp_servers?: unknown[];
55
+ /** Non-empty array indicates a config error — log loudly. */
56
+ plugin_errors?: unknown[];
57
+ }
58
+ /** Hook lifecycle frames. Adapter IGNORES these — see Delta #2 above. */
59
+ export interface SystemHookFrame extends BaseFrame {
60
+ type: 'system';
61
+ subtype: 'hook_started' | 'hook_response';
62
+ hook_name?: string;
63
+ hook_event?: string;
64
+ /** May contain arbitrary user content (operator's hook output). Ignored. */
65
+ output?: string;
66
+ stdout?: string;
67
+ stderr?: string;
68
+ exit_code?: number;
69
+ outcome?: string;
70
+ }
71
+ /** Bare status heartbeat. Ignored. */
72
+ export interface SystemStatusFrame extends BaseFrame {
73
+ type: 'system';
74
+ subtype: 'status';
75
+ status?: string;
76
+ }
77
+ /** Documented retry signal. May or may not actually fire on v2.x — see Delta #3. */
78
+ export interface SystemApiRetryFrame extends BaseFrame {
79
+ type: 'system';
80
+ subtype: 'api_retry';
81
+ attempt?: number;
82
+ max_retries?: number;
83
+ retry_delay_ms?: number;
84
+ error_status?: number;
85
+ /** Documented enum: `authentication_failed` | `oauth_org_not_allowed` | `billing_error` | `rate_limit` | `invalid_request` | `server_error` | `unknown` | `max_output_tokens`. */
86
+ error?: string;
87
+ }
88
+ /** Top-level rate-limit informational AND action-required signal — Delta #3. */
89
+ export interface RateLimitEvent extends BaseFrame {
90
+ type: 'rate_limit_event';
91
+ rate_limit_info?: {
92
+ /** `'allowed'` (informational, every turn) | `'blocked'` (action-required). */
93
+ status?: string;
94
+ rateLimitType?: string;
95
+ resetsAt?: number;
96
+ /** `'allowed'` | `'blocked'`. When BOTH this AND `status` are blocked → fatal (subscription + extra-usage exhausted). */
97
+ overageStatus?: string;
98
+ overageResetsAt?: number;
99
+ isUsingOverage?: boolean;
100
+ };
101
+ }
102
+ /** Mid-turn assistant message. Content array may include text / thinking / tool_use blocks. */
103
+ export interface AssistantFrame extends BaseFrame {
104
+ type: 'assistant';
105
+ message?: {
106
+ role?: 'assistant';
107
+ content?: Array<{
108
+ type?: 'text' | 'thinking' | 'tool_use' | string;
109
+ text?: string;
110
+ id?: string;
111
+ name?: string;
112
+ input?: unknown;
113
+ }>;
114
+ stop_reason?: string | null;
115
+ usage?: Record<string, unknown>;
116
+ };
117
+ parent_tool_use_id?: string | null;
118
+ }
119
+ /** Tool result wrapped as user turn — telemetry only. */
120
+ export interface UserFrame extends BaseFrame {
121
+ type: 'user';
122
+ message?: {
123
+ role?: 'user';
124
+ content?: Array<{
125
+ type?: 'tool_result' | string;
126
+ tool_use_id?: string;
127
+ content?: unknown;
128
+ }>;
129
+ };
130
+ tool_use_result?: unknown;
131
+ }
132
+ /** Token-delta frame. Only emitted with `--include-partial-messages`. v1 ignores. */
133
+ export interface StreamEventFrame extends BaseFrame {
134
+ type: 'stream_event';
135
+ event?: unknown;
136
+ ttft_ms?: number;
137
+ }
138
+ /** Closing frame of every turn. Authoritative source for assembled text + usage + cost. */
139
+ export interface ResultFrame extends BaseFrame {
140
+ type: 'result';
141
+ /** `'success'` | `'error'` (and possibly more). Discriminates envelope shape. */
142
+ subtype?: string;
143
+ /** Clean fatal-vs-success boolean — primary classifier input per architect. */
144
+ is_error?: boolean;
145
+ /** HTTP status code on API errors. Reuse claude-api's HTTP-code classifier. */
146
+ api_error_status?: number | null;
147
+ /** Assembled assistant text — the canonical reply the adapter returns. */
148
+ result?: string;
149
+ /** `'end_turn'` | `'max_tokens'` | `'stop_sequence'` | … */
150
+ stop_reason?: string;
151
+ duration_ms?: number;
152
+ duration_api_ms?: number;
153
+ num_turns?: number;
154
+ /** Equivalent API cost (NOT real subscription burn). */
155
+ total_cost_usd?: number;
156
+ usage?: Record<string, unknown>;
157
+ modelUsage?: Record<string, unknown>;
158
+ permission_denials?: unknown[];
159
+ /** `'completed'` | `'aborted'` | … */
160
+ terminal_reason?: string;
161
+ }
162
+ /**
163
+ * Discriminated union of everything we recognize. The parser tolerates
164
+ * unknown `type` strings by passing them through as `BaseFrame`.
165
+ */
166
+ export type StreamJsonFrame = SystemInitFrame | SystemHookFrame | SystemStatusFrame | SystemApiRetryFrame | RateLimitEvent | AssistantFrame | UserFrame | StreamEventFrame | ResultFrame | BaseFrame;
167
+ /**
168
+ * Per-turn accumulator. The parser folds each frame into this state; the
169
+ * adapter reads it after the subprocess exits to assemble the SDK return
170
+ * value AND to feed the error classifier.
171
+ */
172
+ export interface TurnAccumulator {
173
+ /** Canonical assembled assistant text — set from `result.result` (preferred) or assistant-frame text fallback. */
174
+ assembledText: string;
175
+ /** `result.stop_reason`. */
176
+ stopReason: string | null;
177
+ /** `result.usage` — opaque token accounting. */
178
+ usage: Record<string, unknown> | null;
179
+ /** `result.total_cost_usd` — equivalent API cost (NOT real subscription burn). */
180
+ totalCostUsd: number | null;
181
+ /** `result.is_error` — primary classifier input. */
182
+ resultIsError: boolean | null;
183
+ /** `result.api_error_status` — HTTP code when is_error=true. */
184
+ resultApiErrorStatus: number | null;
185
+ /** `result.subtype` — `'success'` | `'error'` | … */
186
+ resultSubtype: string | null;
187
+ /** Did we see a `result` frame at all? `false` means subprocess exited before completing the turn. */
188
+ resultFrameSeen: boolean;
189
+ /** `system/api_retry` events observed on stdout — fed into the classifier. */
190
+ apiRetryEvents: SystemApiRetryFrame[];
191
+ /** `rate_limit_event` frames observed — separated by status for the classifier. */
192
+ rateLimitEvents: RateLimitEvent[];
193
+ /** Plugin-config errors from `system/init` — non-empty means config bug. */
194
+ pluginErrors: unknown[];
195
+ /** Model id from `system/init`, e.g. `'claude-opus-4-7[1m]'`. Telemetry only. */
196
+ initModel: string | null;
197
+ /** `apiKeySource` from `system/init` — `'none'` confirms OAuth subscription billing. */
198
+ initApiKeySource: string | null;
199
+ }
200
+ /** Build a fresh accumulator. */
201
+ export declare function newTurnAccumulator(): TurnAccumulator;
202
+ /**
203
+ * Fold one stream-json frame into the accumulator. Pure mutation — return
204
+ * the same instance for chaining.
205
+ *
206
+ * Unknown frame types are silently passed through (the parser is tolerant
207
+ * by design — Claude Code may add new frame types between minor versions
208
+ * and we don't want to crash on them; the adapter only ever acts on the
209
+ * categories we recognize).
210
+ *
211
+ * The hook + status frames are explicitly enumerated as IGNORED rather
212
+ * than falling through `default`, so future readers don't think the
213
+ * pass-through is accidental.
214
+ */
215
+ export declare function applyFrame(state: TurnAccumulator, frame: StreamJsonFrame): TurnAccumulator;
216
+ /**
217
+ * Stateful line-buffered stream-json reader. Feed it raw stdout chunks;
218
+ * call `flush()` after subprocess exit to emit any trailing partial line.
219
+ *
220
+ * Exposed as a class so the adapter can wire it to the `claude -p`
221
+ * subprocess's `stdout.on('data', ...)` event without needing a
222
+ * Transform stream subclass — keeps the dep surface minimal.
223
+ *
224
+ * Malformed JSON lines are skipped with a logged warning (defensive —
225
+ * shouldn't happen in practice but a single bad line shouldn't crash
226
+ * the turn).
227
+ */
228
+ export declare class StreamJsonReader {
229
+ private buffer;
230
+ private state;
231
+ private readonly onParseError?;
232
+ constructor(opts?: {
233
+ onParseError?: (line: string, err: Error) => void;
234
+ });
235
+ /** Feed a chunk of stdout. Triggers `applyFrame` for every complete line. */
236
+ feed(chunk: Buffer | string): void;
237
+ /** Process any trailing line that didn't end with a newline. Idempotent. */
238
+ flush(): void;
239
+ /** Snapshot of the current accumulator. Caller may freely mutate. */
240
+ snapshot(): TurnAccumulator;
241
+ private parseLine;
242
+ }