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,78 @@
1
+ /**
2
+ * Shared recall formatter (#128).
3
+ *
4
+ * Single source of truth for how the MCP `recall` tool, TUI `/recall` slash
5
+ * command, and CLI `agent-tempo recall` present a timeline. Pure — no
6
+ * Temporal, no stdout, no I/O — so each surface can unit-test its rendering
7
+ * with canned data.
8
+ *
9
+ * Execution order (established by the #128 design):
10
+ * query → filter (`since`, `from`) → sort desc by timestamp → compute
11
+ * total → slice [offset, offset+limit) → conditionally truncate bodies
12
+ * by `previewLength` → emit pagination header.
13
+ *
14
+ * `previewLength` is unset by default (no sane ceiling). Callers opt in to
15
+ * truncation; the prior hardcoded 200-char cap at the MCP tool is retired
16
+ * from the recall path (the shared constant stays elsewhere).
17
+ */
18
+ import type { Message, SentMessage } from '../types';
19
+ export interface TimelineEntry {
20
+ direction: 'received' | 'sent';
21
+ /** Sender player name for received entries; undefined for sent. */
22
+ from?: string;
23
+ /** Recipient player name for sent entries; undefined for received. */
24
+ to?: string;
25
+ text: string;
26
+ /** ISO timestamp. */
27
+ timestamp: string;
28
+ /** Only set on received entries. */
29
+ delivered?: boolean;
30
+ }
31
+ export interface RecallFormatOpts {
32
+ /** Max entries per page. Defaults to 20; schema enforces 1-100 upstream. */
33
+ limit?: number;
34
+ /** Skip N entries for paging. Defaults to 0. */
35
+ offset?: number;
36
+ /**
37
+ * Truncate each entry body to this many characters + `…`. Omitted =
38
+ * unlimited (full body). Schema upstream enforces `min(1)`.
39
+ */
40
+ previewLength?: number;
41
+ /** ISO timestamp — only entries at or after this are included. */
42
+ since?: string;
43
+ /** Sender filter — only applied to received entries. */
44
+ from?: string;
45
+ }
46
+ /**
47
+ * Build the flat, unfiltered, unsorted timeline from a session's raw query
48
+ * results. Mirrors the shape the MCP tool used inline before #128.
49
+ *
50
+ * `includeSent === false` drops the sent-messages lane entirely rather than
51
+ * tagging them `direction: 'sent'`, matching the existing MCP semantics.
52
+ */
53
+ export declare function buildTimeline(received: Message[], sent: SentMessage[], includeSent: boolean): TimelineEntry[];
54
+ export interface RecallRenderResult {
55
+ /** Final rendered lines (header + entries, joined with blank lines between entries). */
56
+ text: string;
57
+ /** Post-filter total (before offset/limit). Useful for callers needing raw counts. */
58
+ total: number;
59
+ /** Number of entries actually rendered (≤ limit). */
60
+ shown: number;
61
+ /** `true` iff pagination would continue past `offset + limit`. */
62
+ hasMore: boolean;
63
+ }
64
+ /**
65
+ * Filter → sort → slice → render pipeline per the #128 design. Returns a
66
+ * single formatted string (plus counts for callers that want to branch on
67
+ * pagination state without re-scanning the rendered text).
68
+ *
69
+ * Header convention (matches `gh pr list` / `gh issue list`):
70
+ * `Showing X-Y of Z messages.`
71
+ * Append `Use offset: N for next page.` only when total > offset + limit.
72
+ *
73
+ * Edge cases:
74
+ * - empty (post-filter) → `No messages found matching the filter.`
75
+ * - offset ≥ total (non-empty) → `No messages at offset N. Total: Z. Use offset: 0 to start over.`
76
+ * - `previewLength > text.length` → full body, no ellipsis
77
+ */
78
+ export declare function formatRecall(timeline: TimelineEntry[], opts?: RecallFormatOpts): RecallRenderResult;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildTimeline = buildTimeline;
4
+ exports.formatRecall = formatRecall;
5
+ /**
6
+ * Build the flat, unfiltered, unsorted timeline from a session's raw query
7
+ * results. Mirrors the shape the MCP tool used inline before #128.
8
+ *
9
+ * `includeSent === false` drops the sent-messages lane entirely rather than
10
+ * tagging them `direction: 'sent'`, matching the existing MCP semantics.
11
+ */
12
+ function buildTimeline(received, sent, includeSent) {
13
+ const timeline = received.map((m) => ({
14
+ direction: 'received',
15
+ from: m.from,
16
+ text: m.text,
17
+ timestamp: m.timestamp,
18
+ delivered: m.delivered,
19
+ }));
20
+ if (includeSent) {
21
+ for (const s of sent) {
22
+ timeline.push({
23
+ direction: 'sent',
24
+ to: s.to,
25
+ text: s.text,
26
+ timestamp: s.timestamp,
27
+ });
28
+ }
29
+ }
30
+ return timeline;
31
+ }
32
+ /**
33
+ * Filter → sort → slice → render pipeline per the #128 design. Returns a
34
+ * single formatted string (plus counts for callers that want to branch on
35
+ * pagination state without re-scanning the rendered text).
36
+ *
37
+ * Header convention (matches `gh pr list` / `gh issue list`):
38
+ * `Showing X-Y of Z messages.`
39
+ * Append `Use offset: N for next page.` only when total > offset + limit.
40
+ *
41
+ * Edge cases:
42
+ * - empty (post-filter) → `No messages found matching the filter.`
43
+ * - offset ≥ total (non-empty) → `No messages at offset N. Total: Z. Use offset: 0 to start over.`
44
+ * - `previewLength > text.length` → full body, no ellipsis
45
+ */
46
+ function formatRecall(timeline, opts = {}) {
47
+ const limit = opts.limit ?? 20;
48
+ const offset = opts.offset ?? 0;
49
+ // ── 1. Filter ──
50
+ let filtered = timeline;
51
+ if (opts.since !== undefined) {
52
+ const sinceTs = Date.parse(opts.since);
53
+ if (!Number.isNaN(sinceTs)) {
54
+ filtered = filtered.filter((e) => Date.parse(e.timestamp) >= sinceTs);
55
+ }
56
+ }
57
+ if (opts.from) {
58
+ filtered = filtered.filter((e) => (e.direction === 'received' ? e.from === opts.from : true));
59
+ }
60
+ // ── 2. Sort desc by timestamp ──
61
+ filtered = [...filtered].sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp));
62
+ // ── 3. Compute total (post-filter) ──
63
+ const total = filtered.length;
64
+ // ── Early-return paths ──
65
+ if (total === 0) {
66
+ return {
67
+ text: 'No messages found matching the filter.',
68
+ total: 0,
69
+ shown: 0,
70
+ hasMore: false,
71
+ };
72
+ }
73
+ if (offset >= total) {
74
+ return {
75
+ text: `No messages at offset ${offset}. Total: ${total}. Use offset: 0 to start over.`,
76
+ total,
77
+ shown: 0,
78
+ hasMore: false,
79
+ };
80
+ }
81
+ // ── 4. Slice [offset, offset+limit) ──
82
+ const page = filtered.slice(offset, offset + limit);
83
+ // ── 5. Render ──
84
+ const renderedEntries = page.map((e) => renderEntry(e, opts.previewLength));
85
+ const startIdx = offset + 1;
86
+ const endIdx = offset + page.length;
87
+ const hasMore = total > offset + limit;
88
+ const headerLines = [`Showing ${startIdx}-${endIdx} of ${total} messages.`];
89
+ if (hasMore)
90
+ headerLines.push(`Use offset: ${offset + limit} for next page.`);
91
+ return {
92
+ text: [headerLines.join(' '), '', ...renderedEntries].join('\n'),
93
+ total,
94
+ shown: page.length,
95
+ hasMore,
96
+ };
97
+ }
98
+ function renderEntry(e, previewLength) {
99
+ const dir = e.direction === 'sent' ? `→ ${e.to}` : `← ${e.from}`;
100
+ const status = e.direction === 'received' && e.delivered === false ? ' (undelivered)' : '';
101
+ const body = previewLength !== undefined && e.text.length > previewLength
102
+ ? `${e.text.slice(0, previewLength)}…`
103
+ : e.text;
104
+ return `[${e.timestamp}] ${dir}${status}\n ${body}`;
105
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Shared formatter for the #151 `restore --all-hosts` cluster-view listing.
3
+ *
4
+ * Pure: no Temporal, no I/O, no ANSI colors. Mirrors the
5
+ * `format-hosts.ts` convention so unit tests can pin the rendering
6
+ * without spinning up a Temporal client. Consumed by:
7
+ * - `src/cli/commands.ts` (`restore` verb's `--all-hosts` branch)
8
+ *
9
+ * Liveness annotation semantics (joined against `listHosts()`):
10
+ *
11
+ * [live] — host's daemon is polling now
12
+ * (`HOST_FRESHNESS_THRESHOLD_MS`, 60s default). Recovery is
13
+ * imminent on its next reconcile tick — no manual action
14
+ * needed in most cases.
15
+ * [stale] — host has been registered but no poller seen in the last
16
+ * minute. Probably down; manual `/migrate` from the TUI if
17
+ * recovery can't wait.
18
+ * [missing] — host has no registered profile at all (never came back
19
+ * since boot, or maestro restarted and the profile expired).
20
+ * Almost certainly safe to deliberately steal.
21
+ *
22
+ * Action edge — for cross-host orphans (NOT for `(local)` ones), the
23
+ * formatter prints the TUI `/migrate` command the operator would run to
24
+ * deliberately steal the session to the local host. The architect's
25
+ * §16.5-Option-B `--yes-steal=<host>` deliberate-action gate isn't on
26
+ * the TUI slash-command yet (separate follow-up); we print the available
27
+ * surface that actually parses today.
28
+ */
29
+ import type { HostInfo } from '../types';
30
+ import type { RestoreOrphanDetail } from '../reconcile/orphans';
31
+ export interface FormatCrossHostOrphansOpts {
32
+ /** Operator's local hostname — sorted first, gets the `(local)` tag. */
33
+ localHost: string;
34
+ /**
35
+ * When set, the operator passed `--ensemble <name>` (narrowing the
36
+ * cluster-view listing). Otherwise the formatter says "every ensemble".
37
+ */
38
+ ensemble?: string;
39
+ }
40
+ /**
41
+ * Render the `--all-hosts` listing.
42
+ *
43
+ * Pre-condition: `details` are produced by
44
+ * `restoreOrphansOnce(..., { mode: 'all-hosts-readonly' })`. Entries not
45
+ * shaped as `{ kind: 'skipped', reason: 'crossHost' }` are silently
46
+ * filtered out — defensive: the formatter is a final renderer, not a
47
+ * data-shape gatekeeper.
48
+ */
49
+ export declare function formatCrossHostOrphans(details: RestoreOrphanDetail[], hosts: HostInfo[], opts: FormatCrossHostOrphansOpts): string;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatCrossHostOrphans = formatCrossHostOrphans;
4
+ /**
5
+ * Render the `--all-hosts` listing.
6
+ *
7
+ * Pre-condition: `details` are produced by
8
+ * `restoreOrphansOnce(..., { mode: 'all-hosts-readonly' })`. Entries not
9
+ * shaped as `{ kind: 'skipped', reason: 'crossHost' }` are silently
10
+ * filtered out — defensive: the formatter is a final renderer, not a
11
+ * data-shape gatekeeper.
12
+ */
13
+ function formatCrossHostOrphans(details, hosts, opts) {
14
+ const { localHost, ensemble } = opts;
15
+ const scope = ensemble
16
+ ? `ensemble "${ensemble}" across all hosts`
17
+ : 'every ensemble across all hosts';
18
+ // Group orphans by preferredHost (the `detail` field on each crossHost
19
+ // skip — set by `restoreOrphansOnce` to `preferredHost ??
20
+ // lastAdapter.hostname ?? '(unknown)'`).
21
+ const groups = new Map();
22
+ for (const d of details) {
23
+ if (d.outcome.kind !== 'skipped' || d.outcome.reason !== 'crossHost')
24
+ continue;
25
+ const key = d.outcome.detail ?? '(unknown)';
26
+ const bucket = groups.get(key) ?? [];
27
+ bucket.push(d);
28
+ groups.set(key, bucket);
29
+ }
30
+ const totalOrphans = Array.from(groups.values()).reduce((n, g) => n + g.length, 0);
31
+ if (totalOrphans === 0) {
32
+ return `No orphans found (${scope}).`;
33
+ }
34
+ // Stable order: local-host first (its own dormant orphans are the most
35
+ // actionable for the operator), then alphabetical, `(unknown)` last.
36
+ const groupOrder = Array.from(groups.keys()).sort((a, b) => {
37
+ if (a === localHost)
38
+ return -1;
39
+ if (b === localHost)
40
+ return 1;
41
+ if (a === '(unknown)')
42
+ return 1;
43
+ if (b === '(unknown)')
44
+ return -1;
45
+ return a.localeCompare(b);
46
+ });
47
+ // Build the host lookup once for the liveness join.
48
+ const hostByName = new Map();
49
+ for (const h of hosts)
50
+ hostByName.set(h.hostname, h);
51
+ const liveness = (preferredHost) => {
52
+ if (preferredHost === '(unknown)')
53
+ return 'missing';
54
+ const h = hostByName.get(preferredHost);
55
+ if (!h)
56
+ return 'missing';
57
+ return h.freshness === 'live' ? 'live' : 'stale';
58
+ };
59
+ const lines = [];
60
+ lines.push(`${totalOrphans} cross-host orphan${totalOrphans === 1 ? '' : 's'} found (${scope}).`);
61
+ lines.push('');
62
+ lines.push('These sessions are reattached automatically when their preferred host returns.');
63
+ lines.push("Below are the manual-takeover commands if a host won't come back.");
64
+ lines.push('');
65
+ for (const host of groupOrder) {
66
+ const orphans = groups.get(host);
67
+ const label = liveness(host);
68
+ const isLocal = host === localHost;
69
+ const hostHeading = isLocal
70
+ ? `**${host}** [${label}] (local)`
71
+ : `**${host}** [${label}]`;
72
+ lines.push(hostHeading);
73
+ for (const d of orphans) {
74
+ lines.push(` - ${d.playerId} (ensemble: ${d.ensemble})`);
75
+ if (!isLocal && host !== '(unknown)') {
76
+ // Action edge — TUI slash-command form. Architect confirmed (#151
77
+ // dispatch thread) that `--yes-steal=<host>` deliberate-action is
78
+ // a separate follow-up since the CLI `migrate` verb was removed
79
+ // in #288 and the TUI `/migrate` doesn't accept the flag yet.
80
+ lines.push(` In TUI: /migrate ${d.playerId} ${localHost} --force`);
81
+ }
82
+ else if (isLocal) {
83
+ lines.push(` Use \`agent-tempo restore ${d.ensemble}\` (single-ensemble) to reattach.`);
84
+ }
85
+ }
86
+ lines.push('');
87
+ }
88
+ if (lines[lines.length - 1] === '')
89
+ lines.pop();
90
+ return lines.join('\n');
91
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Assert that a resolved file path falls within one of the allowed root directories.
3
+ * Throws if the path escapes all allowed roots (path traversal attempt).
4
+ */
5
+ export declare function assertSafePath(filePath: string, allowedRoots: string[]): void;
6
+ /**
7
+ * Validate and resolve a lineup file path, ensuring it stays within allowed directories.
8
+ * Allowed roots: ~/.agent-tempo/ensembles/, cwd, and optionally a project dir.
9
+ */
10
+ export declare function safeLineupPath(filePath: string, cwd: string, projectDir?: string): string;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertSafePath = assertSafePath;
4
+ exports.safeLineupPath = safeLineupPath;
5
+ const path_1 = require("path");
6
+ /**
7
+ * Assert that a resolved file path falls within one of the allowed root directories.
8
+ * Throws if the path escapes all allowed roots (path traversal attempt).
9
+ */
10
+ function assertSafePath(filePath, allowedRoots) {
11
+ const resolved = (0, path_1.normalize)((0, path_1.resolve)(filePath));
12
+ const isAllowed = allowedRoots.some((root) => {
13
+ const normalizedRoot = (0, path_1.normalize)((0, path_1.resolve)(root));
14
+ // Ensure the path starts with root + separator (or is exactly the root)
15
+ return resolved === normalizedRoot || resolved.startsWith(normalizedRoot + getSep(normalizedRoot));
16
+ });
17
+ if (!isAllowed) {
18
+ throw new Error(`Path traversal blocked: "${filePath}" resolves to "${resolved}" which is outside allowed roots: ${allowedRoots.join(', ')}`);
19
+ }
20
+ }
21
+ /**
22
+ * Validate and resolve a lineup file path, ensuring it stays within allowed directories.
23
+ * Allowed roots: ~/.agent-tempo/ensembles/, cwd, and optionally a project dir.
24
+ */
25
+ function safeLineupPath(filePath, cwd, projectDir) {
26
+ const { join } = require('path');
27
+ const { homedir } = require('os');
28
+ const allowedRoots = [
29
+ join(homedir(), '.agent-tempo', 'ensembles'),
30
+ cwd,
31
+ ];
32
+ if (projectDir && projectDir !== cwd) {
33
+ allowedRoots.push(projectDir);
34
+ }
35
+ const resolved = (0, path_1.normalize)((0, path_1.resolve)(filePath));
36
+ assertSafePath(resolved, allowedRoots);
37
+ return resolved;
38
+ }
39
+ /** Get the path separator used in a given path string. */
40
+ function getSep(p) {
41
+ // Use backslash if path contains backslashes (Windows), forward slash otherwise
42
+ return p.includes('\\') ? '\\' : '/';
43
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @param pkgName Bare specifier (e.g. `'@opencode-ai/sdk'`).
3
+ * @param fromDir Where to start the walk. Defaults to the caller's
4
+ * `__dirname`-equivalent — pass an explicit value if you need to anchor
5
+ * the search elsewhere.
6
+ * @returns `true` if `<dir>/node_modules/<pkgName>/package.json` exists
7
+ * anywhere on the walk up the filesystem.
8
+ */
9
+ export declare function probeSdkInstall(pkgName: string, fromDir?: string): boolean;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.probeSdkInstall = probeSdkInstall;
4
+ /**
5
+ * Filesystem-walk probe for an installed npm package.
6
+ *
7
+ * Walks `node_modules` directories upward from `__dirname` looking for a
8
+ * package's `package.json`. Returns whether the package is installed.
9
+ *
10
+ * **Why not `require.resolve(pkgName)` or `require.resolve(pkgName + '/package.json')`?**
11
+ * Some packages publish with strict ESM `exports` maps that have no
12
+ * `"require"` key and no `"./package.json"` sub-path entry — e.g.
13
+ * `@opencode-ai/sdk`. CJS-side resolution then trips
14
+ * `ERR_PACKAGE_PATH_NOT_EXPORTED` even when the package is correctly
15
+ * installed. The filesystem walk bypasses Node's exports-map gate
16
+ * cleanly. The Copilot SDK works with `require('<pkg>/package.json')`
17
+ * (`src/daemon-adapter-versions.ts:175`) because it doesn't have that
18
+ * restriction; this helper is for packages that do.
19
+ *
20
+ * Used by:
21
+ * - `src/adapters/opencode/adapter.ts` — module-load optional-dep gate
22
+ * - `src/tools/recruit.ts` — recruit pre-flight check
23
+ */
24
+ const fs_1 = require("fs");
25
+ const path_1 = require("path");
26
+ /**
27
+ * @param pkgName Bare specifier (e.g. `'@opencode-ai/sdk'`).
28
+ * @param fromDir Where to start the walk. Defaults to the caller's
29
+ * `__dirname`-equivalent — pass an explicit value if you need to anchor
30
+ * the search elsewhere.
31
+ * @returns `true` if `<dir>/node_modules/<pkgName>/package.json` exists
32
+ * anywhere on the walk up the filesystem.
33
+ */
34
+ function probeSdkInstall(pkgName, fromDir = __dirname) {
35
+ let dir = fromDir;
36
+ while (true) {
37
+ const candidate = (0, path_1.join)(dir, 'node_modules', pkgName, 'package.json');
38
+ if ((0, fs_1.existsSync)(candidate))
39
+ return true;
40
+ const parent = (0, path_1.dirname)(dir);
41
+ if (parent === dir)
42
+ return false;
43
+ dir = parent;
44
+ }
45
+ }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Reusable helpers for extracting Temporal search attributes from
3
+ * `WorkflowExecutionInfo` (from `client.workflow.list()` iteration) and
4
+ * `WorkflowExecutionDescription` (from `handle.describe()`).
5
+ *
6
+ * Extracted per issue #203 to eliminate the inline
7
+ * `arr = wf.searchAttributes?.<Attr>; first = Array.isArray(arr) ? arr[0] : undefined`
8
+ * pattern previously duplicated across 9 call sites.
9
+ *
10
+ * Kept free of `@temporalio/client` imports — the `SearchAttributeCarrier`
11
+ * type is structural. That keeps this util reusable from tests and future
12
+ * call sites without dragging the Temporal client dependency in.
13
+ */
14
+ import { AttachmentPhase } from '../types';
15
+ /**
16
+ * Structural shape of objects carrying Temporal search attributes.
17
+ *
18
+ * Matches both `WorkflowExecutionInfo` and `WorkflowExecutionDescription`
19
+ * without depending on Temporal SDK types. The underlying JSON shape is a
20
+ * `Record<string, ReadonlyArray<unknown> | undefined>` — the SDK preserves
21
+ * the list shape even for single-value attributes like ensemble name or
22
+ * phase, and exposes it with `readonly` arrays (so this type uses
23
+ * `ReadonlyArray` to stay assignable from the Temporal SDK's
24
+ * `SearchAttributes` type).
25
+ */
26
+ export interface SearchAttributeCarrier {
27
+ searchAttributes?: Record<string, ReadonlyArray<unknown> | undefined>;
28
+ }
29
+ /**
30
+ * Read the first element of a search-attribute array as a string.
31
+ *
32
+ * Returns `undefined` when any of these holds:
33
+ * - The carrier has no `searchAttributes` object.
34
+ * - The named attribute is absent.
35
+ * - The attribute value is not an array.
36
+ * - The array is empty.
37
+ *
38
+ * Non-string values are coerced via `String(v)` — matches the legacy
39
+ * inline pattern (`String(vals[0])`) at the migrated call sites.
40
+ */
41
+ export declare function getSearchAttrString(carrier: SearchAttributeCarrier, name: string): string | undefined;
42
+ /**
43
+ * Read the first element of a search-attribute array as a boolean.
44
+ *
45
+ * Returns `undefined` when the attribute is missing or non-boolean-shaped.
46
+ * Tolerates string representations (`"true"` / `"false"`) that some
47
+ * Temporal client versions have been known to surface instead of native
48
+ * booleans — same forgiveness policy as the legacy inline pattern.
49
+ */
50
+ export declare function getSearchAttrBool(carrier: SearchAttributeCarrier, name: string): boolean | undefined;
51
+ /**
52
+ * Read the attachment phase from `AgentTempoAttachmentState`.
53
+ *
54
+ * Post-#175 this is the canonical lifecycle state (replaced the v0.25
55
+ * `AgentTempoStatus` heuristic). Returns `undefined` when the attribute is
56
+ * missing — typically during the brief post-start window before the
57
+ * workflow has written its first phase transition, or for workflows that
58
+ * predate the attachment-lifecycle rework.
59
+ */
60
+ export declare function getAttachmentPhase(carrier: SearchAttributeCarrier): AttachmentPhase | undefined;
61
+ /**
62
+ * Read the ensemble name from `AgentTempoEnsemble`.
63
+ *
64
+ * Returns `undefined` when the attribute is absent — callers typically
65
+ * treat that as "skip this session" since every session workflow should
66
+ * set the attribute on start.
67
+ */
68
+ export declare function getEnsembleName(carrier: SearchAttributeCarrier): string | undefined;
69
+ /**
70
+ * Read the conductor flag from `AgentTempoIsConductor`.
71
+ *
72
+ * Returns `undefined` when absent (e.g. transiently un-indexed after a
73
+ * conductor spawn). Callers wanting the pre-#178 workflow-id-suffix
74
+ * fallback (`endsWith('-conductor')`) should apply it on `undefined`.
75
+ */
76
+ export declare function getIsConductor(carrier: SearchAttributeCarrier): boolean | undefined;
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSearchAttrString = getSearchAttrString;
4
+ exports.getSearchAttrBool = getSearchAttrBool;
5
+ exports.getAttachmentPhase = getAttachmentPhase;
6
+ exports.getEnsembleName = getEnsembleName;
7
+ exports.getIsConductor = getIsConductor;
8
+ /**
9
+ * Read the first element of a search-attribute array as a string.
10
+ *
11
+ * Returns `undefined` when any of these holds:
12
+ * - The carrier has no `searchAttributes` object.
13
+ * - The named attribute is absent.
14
+ * - The attribute value is not an array.
15
+ * - The array is empty.
16
+ *
17
+ * Non-string values are coerced via `String(v)` — matches the legacy
18
+ * inline pattern (`String(vals[0])`) at the migrated call sites.
19
+ */
20
+ function getSearchAttrString(carrier, name) {
21
+ const arr = carrier.searchAttributes?.[name];
22
+ if (!Array.isArray(arr) || arr.length === 0)
23
+ return undefined;
24
+ const v = arr[0];
25
+ return typeof v === 'string' ? v : String(v);
26
+ }
27
+ /**
28
+ * Read the first element of a search-attribute array as a boolean.
29
+ *
30
+ * Returns `undefined` when the attribute is missing or non-boolean-shaped.
31
+ * Tolerates string representations (`"true"` / `"false"`) that some
32
+ * Temporal client versions have been known to surface instead of native
33
+ * booleans — same forgiveness policy as the legacy inline pattern.
34
+ */
35
+ function getSearchAttrBool(carrier, name) {
36
+ const arr = carrier.searchAttributes?.[name];
37
+ if (!Array.isArray(arr) || arr.length === 0)
38
+ return undefined;
39
+ const v = arr[0];
40
+ if (typeof v === 'boolean')
41
+ return v;
42
+ if (typeof v === 'string') {
43
+ if (v === 'true')
44
+ return true;
45
+ if (v === 'false')
46
+ return false;
47
+ }
48
+ return undefined;
49
+ }
50
+ // ── Typed wrappers for agent-tempo's custom search attributes ──
51
+ //
52
+ // Keeping one wrapper per attribute gives callers a readable, typed API
53
+ // without re-stating the attribute name at every site. Adding a fourth
54
+ // attribute (e.g. `AgentTempoHost`) later follows the same pattern.
55
+ /**
56
+ * Read the attachment phase from `AgentTempoAttachmentState`.
57
+ *
58
+ * Post-#175 this is the canonical lifecycle state (replaced the v0.25
59
+ * `AgentTempoStatus` heuristic). Returns `undefined` when the attribute is
60
+ * missing — typically during the brief post-start window before the
61
+ * workflow has written its first phase transition, or for workflows that
62
+ * predate the attachment-lifecycle rework.
63
+ */
64
+ function getAttachmentPhase(carrier) {
65
+ return getSearchAttrString(carrier, 'AgentTempoAttachmentState');
66
+ }
67
+ /**
68
+ * Read the ensemble name from `AgentTempoEnsemble`.
69
+ *
70
+ * Returns `undefined` when the attribute is absent — callers typically
71
+ * treat that as "skip this session" since every session workflow should
72
+ * set the attribute on start.
73
+ */
74
+ function getEnsembleName(carrier) {
75
+ return getSearchAttrString(carrier, 'AgentTempoEnsemble');
76
+ }
77
+ /**
78
+ * Read the conductor flag from `AgentTempoIsConductor`.
79
+ *
80
+ * Returns `undefined` when absent (e.g. transiently un-indexed after a
81
+ * conductor spawn). Callers wanting the pre-#178 workflow-id-suffix
82
+ * fallback (`endsWith('-conductor')`) should apply it on `undefined`.
83
+ */
84
+ function getIsConductor(carrier) {
85
+ return getSearchAttrBool(carrier, 'AgentTempoIsConductor');
86
+ }