@ai-devkit/agent-manager 0.31.0 → 0.33.0

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 (519) hide show
  1. package/dist/AgentManager.d.ts +3 -3
  2. package/dist/AgentManager.d.ts.map +1 -1
  3. package/dist/AgentManager.js +80 -79
  4. package/dist/AgentManager.js.map +1 -1
  5. package/dist/__tests__/AgentManager.test.js +413 -388
  6. package/dist/__tests__/AgentManager.test.js.map +1 -1
  7. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +642 -642
  8. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
  9. package/dist/__tests__/adapters/CodexAdapter.test.js +322 -2321
  10. package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
  11. package/dist/__tests__/adapters/CopilotAdapter.test.js +254 -248
  12. package/dist/__tests__/adapters/CopilotAdapter.test.js.map +1 -1
  13. package/dist/__tests__/adapters/GeminiCliAdapter.test.js +564 -558
  14. package/dist/__tests__/adapters/GeminiCliAdapter.test.js.map +1 -1
  15. package/dist/__tests__/adapters/GrokCliAdapter.test.js +114 -114
  16. package/dist/__tests__/adapters/GrokCliAdapter.test.js.map +1 -1
  17. package/dist/__tests__/adapters/OpenCodeAdapter.test.js +169 -169
  18. package/dist/__tests__/adapters/OpenCodeAdapter.test.js.map +1 -1
  19. package/dist/__tests__/capacity/codex.test.js +93 -93
  20. package/dist/__tests__/capacity/codex.test.js.map +1 -1
  21. package/dist/__tests__/capacity/index.test.js +17 -17
  22. package/dist/__tests__/capacity/index.test.js.map +1 -1
  23. package/dist/__tests__/durable/CodexCliProbe.test.js +60 -60
  24. package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -1
  25. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +28 -28
  26. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -1
  27. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +30 -30
  28. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -1
  29. package/dist/__tests__/durable/CodexPrintAgentService.test.js +71 -71
  30. package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -1
  31. package/dist/__tests__/durable/CodexPrintRunner.test.js +125 -125
  32. package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -1
  33. package/dist/__tests__/print/ClaudeCliProbe.test.js +20 -20
  34. package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
  35. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +20 -20
  36. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
  37. package/dist/__tests__/print/ClaudePrintAgentService.test.js +58 -58
  38. package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
  39. package/dist/__tests__/print/ClaudePrintRunner.test.js +55 -55
  40. package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
  41. package/dist/__tests__/print/DurableAgent.test.js +9 -9
  42. package/dist/__tests__/print/DurableAgent.test.js.map +1 -1
  43. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js +40 -40
  44. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js.map +1 -1
  45. package/dist/__tests__/print/DurableAgentRepository.test.js +66 -66
  46. package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -1
  47. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +34 -34
  48. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -1
  49. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +132 -132
  50. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -1
  51. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js +194 -0
  52. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js.map +1 -0
  53. package/dist/__tests__/providers/codex/CodexSessionMapping.test.js +86 -0
  54. package/dist/__tests__/providers/codex/CodexSessionMapping.test.js.map +1 -0
  55. package/dist/__tests__/providers/codex/CodexSessionParser.test.js +254 -0
  56. package/dist/__tests__/providers/codex/CodexSessionParser.test.js.map +1 -0
  57. package/dist/__tests__/providers/pi/PiAdapter.test.js +337 -0
  58. package/dist/__tests__/providers/pi/PiAdapter.test.js.map +1 -0
  59. package/dist/__tests__/providers/pi/PiSessionParser.test.js +246 -0
  60. package/dist/__tests__/providers/pi/PiSessionParser.test.js.map +1 -0
  61. package/dist/__tests__/providers/pi/PiSessionTracker.test.js +108 -0
  62. package/dist/__tests__/providers/pi/PiSessionTracker.test.js.map +1 -0
  63. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +33 -33
  64. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -1
  65. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +16 -16
  66. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -1
  67. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +52 -52
  68. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -1
  69. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +44 -44
  70. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -1
  71. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +126 -126
  72. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -1
  73. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +14 -14
  74. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -1
  75. package/dist/__tests__/readiness/AgentReadiness.test.js +301 -0
  76. package/dist/__tests__/readiness/AgentReadiness.test.js.map +1 -0
  77. package/dist/__tests__/runtime/AgentRuntime.test.js +13 -0
  78. package/dist/__tests__/runtime/AgentRuntime.test.js.map +1 -0
  79. package/dist/__tests__/runtime/HerdrAgentRuntime.test.js +452 -0
  80. package/dist/__tests__/runtime/HerdrAgentRuntime.test.js.map +1 -0
  81. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js +588 -0
  82. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -0
  83. package/dist/__tests__/terminal/TerminalFocusManager.test.js +100 -100
  84. package/dist/__tests__/terminal/TerminalFocusManager.test.js.map +1 -1
  85. package/dist/__tests__/terminal/TmuxManager.test.js +101 -101
  86. package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
  87. package/dist/__tests__/terminal/TtyWriter.test.js +185 -185
  88. package/dist/__tests__/terminal/TtyWriter.test.js.map +1 -1
  89. package/dist/__tests__/utils/AgentRegistry.test.js +335 -217
  90. package/dist/__tests__/utils/AgentRegistry.test.js.map +1 -1
  91. package/dist/__tests__/utils/ClaudeSessionParser.test.js +103 -101
  92. package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +1 -1
  93. package/dist/__tests__/utils/agent-requests.test.js +43 -43
  94. package/dist/__tests__/utils/agent-requests.test.js.map +1 -1
  95. package/dist/__tests__/utils/agents.test.js +17 -17
  96. package/dist/__tests__/utils/agents.test.js.map +1 -1
  97. package/dist/__tests__/utils/matching.test.js +92 -92
  98. package/dist/__tests__/utils/matching.test.js.map +1 -1
  99. package/dist/__tests__/utils/process.test.js +108 -108
  100. package/dist/__tests__/utils/process.test.js.map +1 -1
  101. package/dist/__tests__/utils/session.test.js +53 -53
  102. package/dist/__tests__/utils/session.test.js.map +1 -1
  103. package/dist/adapters/AgentAdapter.d.ts +2 -2
  104. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  105. package/dist/adapters/AgentAdapter.js +1 -1
  106. package/dist/adapters/AgentAdapter.js.map +1 -1
  107. package/dist/adapters/CopilotAdapter.d.ts +2 -2
  108. package/dist/adapters/CopilotAdapter.d.ts.map +1 -1
  109. package/dist/adapters/CopilotAdapter.js +51 -51
  110. package/dist/adapters/CopilotAdapter.js.map +1 -1
  111. package/dist/adapters/GeminiCliAdapter.d.ts +2 -2
  112. package/dist/adapters/GeminiCliAdapter.d.ts.map +1 -1
  113. package/dist/adapters/GeminiCliAdapter.js +86 -86
  114. package/dist/adapters/GeminiCliAdapter.js.map +1 -1
  115. package/dist/adapters/GrokCliAdapter.d.ts +1 -1
  116. package/dist/adapters/GrokCliAdapter.d.ts.map +1 -1
  117. package/dist/adapters/GrokCliAdapter.js +80 -80
  118. package/dist/adapters/GrokCliAdapter.js.map +1 -1
  119. package/dist/adapters/OpenCodeAdapter.d.ts +1 -1
  120. package/dist/adapters/OpenCodeAdapter.d.ts.map +1 -1
  121. package/dist/adapters/OpenCodeAdapter.js +37 -36
  122. package/dist/adapters/OpenCodeAdapter.js.map +1 -1
  123. package/dist/adapters/index.d.ts +9 -9
  124. package/dist/adapters/index.d.ts.map +1 -1
  125. package/dist/adapters/index.js +8 -8
  126. package/dist/adapters/index.js.map +1 -1
  127. package/dist/capacity/codex.d.ts +3 -3
  128. package/dist/capacity/codex.d.ts.map +1 -1
  129. package/dist/capacity/codex.js +57 -57
  130. package/dist/capacity/codex.js.map +1 -1
  131. package/dist/capacity/index.d.ts +3 -3
  132. package/dist/capacity/index.d.ts.map +1 -1
  133. package/dist/capacity/index.js +8 -8
  134. package/dist/capacity/index.js.map +1 -1
  135. package/dist/capacity/types.d.ts +1 -1
  136. package/dist/capacity/types.js.map +1 -1
  137. package/dist/database/connection.d.ts +1 -1
  138. package/dist/database/connection.d.ts.map +1 -1
  139. package/dist/database/connection.js +15 -15
  140. package/dist/database/connection.js.map +1 -1
  141. package/dist/database/index.d.ts +3 -3
  142. package/dist/database/index.d.ts.map +1 -1
  143. package/dist/database/index.js +2 -2
  144. package/dist/database/index.js.map +1 -1
  145. package/dist/database/migrations/005_agent_runtime.sql +2 -0
  146. package/dist/database/schema.d.ts +1 -1
  147. package/dist/database/schema.d.ts.map +1 -1
  148. package/dist/database/schema.js +7 -7
  149. package/dist/database/schema.js.map +1 -1
  150. package/dist/durable/DurableAgent.d.ts +9 -9
  151. package/dist/durable/DurableAgent.d.ts.map +1 -1
  152. package/dist/durable/DurableAgent.js +16 -16
  153. package/dist/durable/DurableAgent.js.map +1 -1
  154. package/dist/durable/DurableAgentRepository.d.ts +4 -4
  155. package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
  156. package/dist/durable/DurableAgentRepository.js +49 -48
  157. package/dist/durable/DurableAgentRepository.js.map +1 -1
  158. package/dist/durable/process.d.ts +1 -1
  159. package/dist/durable/process.d.ts.map +1 -1
  160. package/dist/durable/process.js +14 -14
  161. package/dist/durable/process.js.map +1 -1
  162. package/dist/durable/run.d.ts +2 -2
  163. package/dist/durable/run.d.ts.map +1 -1
  164. package/dist/durable/run.js +6 -6
  165. package/dist/durable/run.js.map +1 -1
  166. package/dist/durable/utils.d.ts +1 -1
  167. package/dist/durable/utils.d.ts.map +1 -1
  168. package/dist/durable/utils.js +4 -4
  169. package/dist/durable/utils.js.map +1 -1
  170. package/dist/index.d.ts +46 -41
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +27 -25
  173. package/dist/index.js.map +1 -1
  174. package/dist/providers/claude/ClaudeAgentMapper.d.ts +4 -4
  175. package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -1
  176. package/dist/providers/claude/ClaudeAgentMapper.js +10 -10
  177. package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -1
  178. package/dist/providers/claude/ClaudeCodeAdapter.d.ts +1 -1
  179. package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -1
  180. package/dist/providers/claude/ClaudeCodeAdapter.js +14 -14
  181. package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -1
  182. package/dist/providers/claude/ClaudeSessionLocator.d.ts +4 -4
  183. package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -1
  184. package/dist/providers/claude/ClaudeSessionLocator.js +79 -79
  185. package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -1
  186. package/dist/providers/claude/ClaudeSessionParser.d.ts +2 -2
  187. package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -1
  188. package/dist/providers/claude/ClaudeSessionParser.js +99 -99
  189. package/dist/providers/claude/ClaudeSessionParser.js.map +1 -1
  190. package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -1
  191. package/dist/providers/claude/durable/ClaudeCliProbe.js +16 -16
  192. package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -1
  193. package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts +5 -5
  194. package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -1
  195. package/dist/providers/claude/durable/ClaudePrintAgentService.js +10 -10
  196. package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -1
  197. package/dist/providers/claude/durable/ClaudePrintRunner.d.ts +4 -4
  198. package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -1
  199. package/dist/providers/claude/durable/ClaudePrintRunner.js +18 -18
  200. package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -1
  201. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +2 -2
  202. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -1
  203. package/dist/providers/claude/durable/ClaudeStreamParser.js +17 -17
  204. package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -1
  205. package/dist/providers/codex/CodexAdapter.d.ts +27 -0
  206. package/dist/providers/codex/CodexAdapter.d.ts.map +1 -0
  207. package/dist/providers/codex/CodexAdapter.js +162 -0
  208. package/dist/providers/codex/CodexAdapter.js.map +1 -0
  209. package/dist/providers/codex/CodexAgentMapper.d.ts +9 -0
  210. package/dist/providers/codex/CodexAgentMapper.d.ts.map +1 -0
  211. package/dist/providers/codex/CodexAgentMapper.js +35 -0
  212. package/dist/providers/codex/CodexAgentMapper.js.map +1 -0
  213. package/dist/providers/codex/CodexSessionLocator.d.ts +44 -0
  214. package/dist/providers/codex/CodexSessionLocator.d.ts.map +1 -0
  215. package/dist/providers/codex/CodexSessionLocator.js +207 -0
  216. package/dist/providers/codex/CodexSessionLocator.js.map +1 -0
  217. package/dist/providers/codex/CodexSessionMapping.d.ts +23 -0
  218. package/dist/providers/codex/CodexSessionMapping.d.ts.map +1 -0
  219. package/dist/providers/codex/CodexSessionMapping.js +68 -0
  220. package/dist/providers/codex/CodexSessionMapping.js.map +1 -0
  221. package/dist/providers/codex/CodexSessionParser.d.ts +58 -0
  222. package/dist/providers/codex/CodexSessionParser.d.ts.map +1 -0
  223. package/dist/providers/codex/CodexSessionParser.js +262 -0
  224. package/dist/providers/codex/CodexSessionParser.js.map +1 -0
  225. package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -1
  226. package/dist/providers/codex/durable/CodexCliProbe.js +22 -22
  227. package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -1
  228. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +6 -6
  229. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -1
  230. package/dist/providers/codex/durable/CodexPrintAgentService.js +10 -10
  231. package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -1
  232. package/dist/providers/codex/durable/CodexPrintRunner.d.ts +4 -4
  233. package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -1
  234. package/dist/providers/codex/durable/CodexPrintRunner.js +20 -20
  235. package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -1
  236. package/dist/providers/codex/durable/CodexStreamParser.d.ts +2 -2
  237. package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -1
  238. package/dist/providers/codex/durable/CodexStreamParser.js +21 -21
  239. package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -1
  240. package/dist/providers/pi/PiAdapter.d.ts +28 -0
  241. package/dist/providers/pi/PiAdapter.d.ts.map +1 -0
  242. package/dist/providers/pi/PiAdapter.js +153 -0
  243. package/dist/providers/pi/PiAdapter.js.map +1 -0
  244. package/dist/providers/pi/PiAgentMapper.d.ts +9 -0
  245. package/dist/providers/pi/PiAgentMapper.d.ts.map +1 -0
  246. package/dist/providers/pi/PiAgentMapper.js +37 -0
  247. package/dist/providers/pi/PiAgentMapper.js.map +1 -0
  248. package/dist/providers/pi/PiSessionLocator.d.ts +23 -0
  249. package/dist/providers/pi/PiSessionLocator.d.ts.map +1 -0
  250. package/dist/providers/pi/PiSessionLocator.js +79 -0
  251. package/dist/providers/pi/PiSessionLocator.js.map +1 -0
  252. package/dist/providers/pi/PiSessionParser.d.ts +36 -0
  253. package/dist/providers/pi/PiSessionParser.d.ts.map +1 -0
  254. package/dist/providers/pi/PiSessionParser.js +191 -0
  255. package/dist/providers/pi/PiSessionParser.js.map +1 -0
  256. package/dist/providers/pi/PiSessionTracker.d.ts +23 -0
  257. package/dist/providers/pi/PiSessionTracker.d.ts.map +1 -0
  258. package/dist/providers/pi/PiSessionTracker.js +69 -0
  259. package/dist/providers/pi/PiSessionTracker.js.map +1 -0
  260. package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -1
  261. package/dist/providers/pi/durable/PiCliProbe.js +15 -15
  262. package/dist/providers/pi/durable/PiCliProbe.js.map +1 -1
  263. package/dist/providers/pi/durable/PiPrintAgentService.d.ts +6 -6
  264. package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -1
  265. package/dist/providers/pi/durable/PiPrintAgentService.js +10 -10
  266. package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -1
  267. package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -1
  268. package/dist/providers/pi/durable/PiPrintProtocol.js +18 -18
  269. package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -1
  270. package/dist/providers/pi/durable/PiPrintRunner.d.ts +4 -4
  271. package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -1
  272. package/dist/providers/pi/durable/PiPrintRunner.js +15 -15
  273. package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -1
  274. package/dist/providers/pi/durable/PiStreamParser.d.ts +1 -1
  275. package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -1
  276. package/dist/providers/pi/durable/PiStreamParser.js +16 -16
  277. package/dist/providers/pi/durable/PiStreamParser.js.map +1 -1
  278. package/dist/readiness/AgentReadiness.d.ts +67 -0
  279. package/dist/readiness/AgentReadiness.d.ts.map +1 -0
  280. package/dist/readiness/AgentReadiness.js +614 -0
  281. package/dist/readiness/AgentReadiness.js.map +1 -0
  282. package/dist/runtime/ManagedAgentRuntime.d.ts +69 -0
  283. package/dist/runtime/ManagedAgentRuntime.d.ts.map +1 -0
  284. package/dist/runtime/ManagedAgentRuntime.js +156 -0
  285. package/dist/runtime/ManagedAgentRuntime.js.map +1 -0
  286. package/dist/runtime/RuntimeFactory.d.ts +4 -0
  287. package/dist/runtime/RuntimeFactory.d.ts.map +1 -0
  288. package/dist/runtime/RuntimeFactory.js +11 -0
  289. package/dist/runtime/RuntimeFactory.js.map +1 -0
  290. package/dist/runtime/errors.d.ts +27 -0
  291. package/dist/runtime/errors.d.ts.map +1 -0
  292. package/dist/runtime/errors.js +42 -0
  293. package/dist/runtime/errors.js.map +1 -0
  294. package/dist/runtime/herdr/HerdrAgentRuntime.d.ts +31 -0
  295. package/dist/runtime/herdr/HerdrAgentRuntime.d.ts.map +1 -0
  296. package/dist/runtime/herdr/HerdrAgentRuntime.js +184 -0
  297. package/dist/runtime/herdr/HerdrAgentRuntime.js.map +1 -0
  298. package/dist/runtime/herdr/HerdrCliClient.d.ts +13 -0
  299. package/dist/runtime/herdr/HerdrCliClient.d.ts.map +1 -0
  300. package/dist/runtime/herdr/HerdrCliClient.js +60 -0
  301. package/dist/runtime/herdr/HerdrCliClient.js.map +1 -0
  302. package/dist/runtime/herdr/HerdrErrors.d.ts +7 -0
  303. package/dist/runtime/herdr/HerdrErrors.d.ts.map +1 -0
  304. package/dist/runtime/herdr/HerdrErrors.js +10 -0
  305. package/dist/runtime/herdr/HerdrErrors.js.map +1 -0
  306. package/dist/runtime/herdr/HerdrResponseParsers.d.ts +14 -0
  307. package/dist/runtime/herdr/HerdrResponseParsers.d.ts.map +1 -0
  308. package/dist/runtime/herdr/HerdrResponseParsers.js +96 -0
  309. package/dist/runtime/herdr/HerdrResponseParsers.js.map +1 -0
  310. package/dist/runtime/herdr/HerdrRuntimeRef.d.ts +9 -0
  311. package/dist/runtime/herdr/HerdrRuntimeRef.d.ts.map +1 -0
  312. package/dist/runtime/herdr/HerdrRuntimeRef.js +33 -0
  313. package/dist/runtime/herdr/HerdrRuntimeRef.js.map +1 -0
  314. package/dist/runtime/tmux/PidPolling.d.ts +5 -0
  315. package/dist/runtime/tmux/PidPolling.d.ts.map +1 -0
  316. package/dist/runtime/tmux/PidPolling.js +24 -0
  317. package/dist/runtime/tmux/PidPolling.js.map +1 -0
  318. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts +17 -0
  319. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts.map +1 -0
  320. package/dist/runtime/tmux/TmuxAgentRuntime.js +80 -0
  321. package/dist/runtime/tmux/TmuxAgentRuntime.js.map +1 -0
  322. package/dist/runtime/tmux/TmuxRuntimeRef.d.ts +5 -0
  323. package/dist/runtime/tmux/TmuxRuntimeRef.d.ts.map +1 -0
  324. package/dist/runtime/tmux/TmuxRuntimeRef.js +9 -0
  325. package/dist/runtime/tmux/TmuxRuntimeRef.js.map +1 -0
  326. package/dist/runtime/types.d.ts +54 -0
  327. package/dist/runtime/types.d.ts.map +1 -0
  328. package/dist/runtime/types.js +3 -0
  329. package/dist/runtime/types.js.map +1 -0
  330. package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
  331. package/dist/terminal/TerminalFocusManager.js +50 -50
  332. package/dist/terminal/TerminalFocusManager.js.map +1 -1
  333. package/dist/terminal/TmuxManager.d.ts.map +1 -1
  334. package/dist/terminal/TmuxManager.js +47 -47
  335. package/dist/terminal/TmuxManager.js.map +1 -1
  336. package/dist/terminal/TtyWriter.d.ts +1 -1
  337. package/dist/terminal/TtyWriter.d.ts.map +1 -1
  338. package/dist/terminal/TtyWriter.js +89 -89
  339. package/dist/terminal/TtyWriter.js.map +1 -1
  340. package/dist/terminal/index.d.ts +4 -4
  341. package/dist/terminal/index.js +3 -3
  342. package/dist/terminal/index.js.map +1 -1
  343. package/dist/utils/AgentRegistry.d.ts +10 -2
  344. package/dist/utils/AgentRegistry.d.ts.map +1 -1
  345. package/dist/utils/AgentRegistry.js +57 -24
  346. package/dist/utils/AgentRegistry.js.map +1 -1
  347. package/dist/utils/agent-requests.d.ts.map +1 -1
  348. package/dist/utils/agent-requests.js +5 -5
  349. package/dist/utils/agent-requests.js.map +1 -1
  350. package/dist/utils/agents.d.ts +2 -2
  351. package/dist/utils/agents.d.ts.map +1 -1
  352. package/dist/utils/agents.js +15 -15
  353. package/dist/utils/agents.js.map +1 -1
  354. package/dist/utils/applescript.js +1 -1
  355. package/dist/utils/applescript.js.map +1 -1
  356. package/dist/utils/index.d.ts +6 -6
  357. package/dist/utils/index.d.ts.map +1 -1
  358. package/dist/utils/index.js +4 -4
  359. package/dist/utils/index.js.map +1 -1
  360. package/dist/utils/matching.d.ts +2 -2
  361. package/dist/utils/matching.d.ts.map +1 -1
  362. package/dist/utils/matching.js +4 -4
  363. package/dist/utils/matching.js.map +1 -1
  364. package/dist/utils/process.d.ts +1 -1
  365. package/dist/utils/process.d.ts.map +1 -1
  366. package/dist/utils/process.js +74 -74
  367. package/dist/utils/process.js.map +1 -1
  368. package/dist/utils/session.d.ts +1 -1
  369. package/dist/utils/session.d.ts.map +1 -1
  370. package/dist/utils/session.js +7 -7
  371. package/dist/utils/session.js.map +1 -1
  372. package/dist/utils/sortAgents.d.ts +2 -2
  373. package/dist/utils/sortAgents.d.ts.map +1 -1
  374. package/dist/utils/sortAgents.js +5 -5
  375. package/dist/utils/sortAgents.js.map +1 -1
  376. package/package.json +18 -19
  377. package/src/AgentManager.ts +283 -281
  378. package/src/__tests__/AgentManager.test.ts +917 -907
  379. package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1657 -1368
  380. package/src/__tests__/adapters/CodexAdapter.test.ts +365 -1698
  381. package/src/__tests__/adapters/CopilotAdapter.test.ts +576 -481
  382. package/src/__tests__/adapters/GeminiCliAdapter.test.ts +1189 -1157
  383. package/src/__tests__/adapters/GrokCliAdapter.test.ts +325 -272
  384. package/src/__tests__/adapters/OpenCodeAdapter.test.ts +510 -455
  385. package/src/__tests__/capacity/codex.test.ts +178 -91
  386. package/src/__tests__/capacity/index.test.ts +27 -18
  387. package/src/__tests__/durable/CodexCliProbe.test.ts +75 -53
  388. package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +51 -40
  389. package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +89 -64
  390. package/src/__tests__/durable/CodexPrintAgentService.test.ts +196 -118
  391. package/src/__tests__/durable/CodexPrintRunner.test.ts +282 -162
  392. package/src/__tests__/fixtures/fake-claude.cjs +20 -13
  393. package/src/__tests__/fixtures/fake-codex.cjs +41 -30
  394. package/src/__tests__/print/ClaudeCliProbe.test.ts +27 -21
  395. package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +48 -40
  396. package/src/__tests__/print/ClaudePrintAgentService.test.ts +118 -67
  397. package/src/__tests__/print/ClaudePrintRunner.test.ts +136 -83
  398. package/src/__tests__/print/DurableAgent.test.ts +19 -16
  399. package/src/__tests__/print/DurableAgentRepository.sqlite.test.ts +109 -86
  400. package/src/__tests__/print/DurableAgentRepository.test.ts +170 -137
  401. package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +65 -65
  402. package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +400 -377
  403. package/src/__tests__/providers/codex/CodexSessionLocator.test.ts +182 -0
  404. package/src/__tests__/providers/codex/CodexSessionMapping.test.ts +63 -0
  405. package/src/__tests__/providers/codex/CodexSessionParser.test.ts +192 -0
  406. package/src/__tests__/providers/pi/PiAdapter.test.ts +310 -0
  407. package/src/__tests__/providers/pi/PiSessionParser.test.ts +190 -0
  408. package/src/__tests__/providers/pi/PiSessionTracker.test.ts +79 -0
  409. package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +48 -32
  410. package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +24 -23
  411. package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +131 -59
  412. package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +66 -28
  413. package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +236 -90
  414. package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +20 -18
  415. package/src/__tests__/readiness/AgentReadiness.test.ts +242 -0
  416. package/src/__tests__/runtime/AgentRuntime.test.ts +8 -0
  417. package/src/__tests__/runtime/HerdrAgentRuntime.test.ts +358 -0
  418. package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +555 -0
  419. package/src/__tests__/terminal/TerminalFocusManager.test.ts +254 -253
  420. package/src/__tests__/terminal/TmuxManager.test.ts +157 -157
  421. package/src/__tests__/terminal/TtyWriter.test.ts +423 -419
  422. package/src/__tests__/utils/AgentRegistry.test.ts +506 -402
  423. package/src/__tests__/utils/ClaudeSessionParser.test.ts +276 -242
  424. package/src/__tests__/utils/agent-requests.test.ts +76 -56
  425. package/src/__tests__/utils/agents.test.ts +20 -20
  426. package/src/__tests__/utils/matching.test.ts +206 -171
  427. package/src/__tests__/utils/process.test.ts +276 -262
  428. package/src/__tests__/utils/session.test.ts +133 -139
  429. package/src/adapters/AgentAdapter.ts +134 -126
  430. package/src/adapters/CopilotAdapter.ts +405 -395
  431. package/src/adapters/GeminiCliAdapter.ts +598 -600
  432. package/src/adapters/GrokCliAdapter.ts +353 -342
  433. package/src/adapters/OpenCodeAdapter.ts +285 -259
  434. package/src/adapters/index.ts +15 -9
  435. package/src/capacity/codex.ts +137 -84
  436. package/src/capacity/index.ts +18 -13
  437. package/src/capacity/types.ts +1 -1
  438. package/src/database/connection.ts +73 -68
  439. package/src/database/index.ts +6 -6
  440. package/src/database/migrations/005_agent_runtime.sql +2 -0
  441. package/src/database/schema.ts +40 -38
  442. package/src/durable/DurableAgent.ts +85 -85
  443. package/src/durable/DurableAgentRepository.ts +409 -260
  444. package/src/durable/process.ts +22 -21
  445. package/src/durable/run.ts +61 -51
  446. package/src/durable/utils.ts +46 -41
  447. package/src/index.ts +145 -86
  448. package/src/providers/claude/ClaudeAgentMapper.ts +51 -50
  449. package/src/providers/claude/ClaudeCodeAdapter.ts +144 -136
  450. package/src/providers/claude/ClaudeSessionLocator.ts +291 -293
  451. package/src/providers/claude/ClaudeSessionParser.ts +322 -338
  452. package/src/providers/claude/durable/ClaudeCliProbe.ts +42 -37
  453. package/src/providers/claude/durable/ClaudePrintAgentService.ts +63 -50
  454. package/src/providers/claude/durable/ClaudePrintRunner.ts +79 -69
  455. package/src/providers/claude/durable/ClaudeStreamParser.ts +91 -62
  456. package/src/providers/codex/CodexAdapter.ts +205 -0
  457. package/src/providers/codex/CodexAgentMapper.ts +35 -0
  458. package/src/providers/codex/CodexSessionLocator.ts +279 -0
  459. package/src/providers/codex/CodexSessionMapping.ts +89 -0
  460. package/src/providers/codex/CodexSessionParser.ts +385 -0
  461. package/src/providers/codex/durable/CodexCliProbe.ts +50 -42
  462. package/src/providers/codex/durable/CodexPrintAgentService.ts +63 -49
  463. package/src/providers/codex/durable/CodexPrintRunner.ts +79 -69
  464. package/src/providers/codex/durable/CodexStreamParser.ts +97 -84
  465. package/src/providers/pi/PiAdapter.ts +183 -0
  466. package/src/providers/pi/PiAgentMapper.ts +36 -0
  467. package/src/providers/pi/PiSessionLocator.ts +95 -0
  468. package/src/providers/pi/PiSessionParser.ts +284 -0
  469. package/src/providers/pi/PiSessionTracker.ts +87 -0
  470. package/src/providers/pi/durable/PiCliProbe.ts +42 -34
  471. package/src/providers/pi/durable/PiPrintAgentService.ts +61 -53
  472. package/src/providers/pi/durable/PiPrintProtocol.ts +31 -29
  473. package/src/providers/pi/durable/PiPrintRunner.ts +75 -68
  474. package/src/providers/pi/durable/PiStreamParser.ts +82 -72
  475. package/src/readiness/AgentReadiness.ts +727 -0
  476. package/src/runtime/ManagedAgentRuntime.ts +266 -0
  477. package/src/runtime/RuntimeFactory.ts +13 -0
  478. package/src/runtime/errors.ts +50 -0
  479. package/src/runtime/herdr/HerdrAgentRuntime.ts +190 -0
  480. package/src/runtime/herdr/HerdrCliClient.ts +78 -0
  481. package/src/runtime/herdr/HerdrErrors.ts +9 -0
  482. package/src/runtime/herdr/HerdrResponseParsers.ts +76 -0
  483. package/src/runtime/herdr/HerdrRuntimeRef.ts +41 -0
  484. package/src/runtime/tmux/PidPolling.ts +34 -0
  485. package/src/runtime/tmux/TmuxAgentRuntime.ts +113 -0
  486. package/src/runtime/tmux/TmuxRuntimeRef.ts +9 -0
  487. package/src/runtime/types.ts +56 -0
  488. package/src/terminal/TerminalFocusManager.ts +215 -212
  489. package/src/terminal/TmuxManager.ts +99 -92
  490. package/src/terminal/TtyWriter.ts +203 -194
  491. package/src/terminal/index.ts +4 -4
  492. package/src/utils/AgentRegistry.ts +299 -238
  493. package/src/utils/agent-requests.ts +16 -16
  494. package/src/utils/agents.ts +41 -38
  495. package/src/utils/applescript.ts +4 -4
  496. package/src/utils/index.ts +12 -6
  497. package/src/utils/matching.ts +43 -43
  498. package/src/utils/process.ts +261 -258
  499. package/src/utils/session.ts +66 -66
  500. package/src/utils/sortAgents.ts +35 -33
  501. package/tsconfig.json +2 -8
  502. package/vitest.config.ts +16 -16
  503. package/.eslintrc.json +0 -31
  504. package/dist/__tests__/adapters/PiAdapter.test.js +0 -618
  505. package/dist/__tests__/adapters/PiAdapter.test.js.map +0 -1
  506. package/dist/__tests__/database/DurableAgentsDatabase.test.js +0 -128
  507. package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +0 -1
  508. package/dist/adapters/CodexAdapter.d.ts +0 -109
  509. package/dist/adapters/CodexAdapter.d.ts.map +0 -1
  510. package/dist/adapters/CodexAdapter.js +0 -710
  511. package/dist/adapters/CodexAdapter.js.map +0 -1
  512. package/dist/adapters/PiAdapter.d.ts +0 -63
  513. package/dist/adapters/PiAdapter.d.ts.map +0 -1
  514. package/dist/adapters/PiAdapter.js +0 -453
  515. package/dist/adapters/PiAdapter.js.map +0 -1
  516. package/src/__tests__/adapters/PiAdapter.test.ts +0 -458
  517. package/src/__tests__/database/DurableAgentsDatabase.test.ts +0 -102
  518. package/src/adapters/CodexAdapter.ts +0 -923
  519. package/src/adapters/PiAdapter.ts +0 -598
@@ -0,0 +1,266 @@
1
+ import type { AgentInfo } from "../adapters/AgentAdapter.js";
2
+ import type { TerminalLocation } from "../terminal/TerminalFocusManager.js";
3
+ import { TmuxManager } from "../terminal/TmuxManager.js";
4
+ import {
5
+ AgentRegistry,
6
+ type AgentRuntimeProvider,
7
+ type RegistryEntry,
8
+ } from "../utils/AgentRegistry.js";
9
+ import { AGENTS, type StartableAgentType } from "../utils/agents.js";
10
+ import { createInteractiveRuntime } from "./RuntimeFactory.js";
11
+ import { DEFAULT_PID_POLL_INTERVAL_MS, DEFAULT_PID_POLL_TIMEOUT_MS } from "./tmux/PidPolling.js";
12
+ import { TmuxAgentRuntime } from "./tmux/TmuxAgentRuntime.js";
13
+ import type { InteractiveAgentRuntime } from "./types.js";
14
+ import {
15
+ AgentNameInUseError,
16
+ AgentPidPollTimeoutError,
17
+ AgentRuntimeUnavailableError,
18
+ AgentTerminalNotFoundError,
19
+ TmuxUnavailableError,
20
+ } from "./errors.js";
21
+
22
+ export {
23
+ AgentNameInUseError,
24
+ AgentPidPollTimeoutError,
25
+ AgentRuntimeUnavailableError,
26
+ AgentTerminalNotFoundError,
27
+ TmuxUnavailableError,
28
+ };
29
+ export { DEFAULT_PID_POLL_INTERVAL_MS, DEFAULT_PID_POLL_TIMEOUT_MS };
30
+
31
+ export interface StartAgentOptions {
32
+ type: StartableAgentType;
33
+ name: string;
34
+ cwd: string;
35
+ runtimeProvider?: AgentRuntimeProvider;
36
+ pollIntervalMs?: number;
37
+ pollTimeoutMs?: number;
38
+ }
39
+
40
+ export interface StartAgentDeps {
41
+ tmux?: TmuxManager;
42
+ runtime?: InteractiveAgentRuntime;
43
+ registry?: AgentRegistry;
44
+ /** Called for non-fatal events (e.g., replacing an orphan tmux session). */
45
+ onWarning?: (message: string) => void;
46
+ }
47
+
48
+ export interface StopAgentDeps {
49
+ tmux?: Pick<TmuxManager, "killSession">;
50
+ runtime?: InteractiveAgentRuntime;
51
+ registry?: Pick<AgentRegistry, "lookup">;
52
+ killProcess?: (pid: number, signal: NodeJS.Signals) => void;
53
+ }
54
+
55
+ export interface StopAgentResult {
56
+ agentName: string;
57
+ pid: number;
58
+ runtime: AgentRuntimeProvider;
59
+ runtimeRef: unknown | null;
60
+ }
61
+
62
+ export interface FocusAgentDeps {
63
+ runtime?: InteractiveAgentRuntime;
64
+ registry?: Pick<AgentRegistry, "lookup">;
65
+ focusManager: {
66
+ findTerminal(pid: number): Promise<TerminalLocation | null>;
67
+ focusTerminal(location: TerminalLocation): Promise<boolean>;
68
+ };
69
+ }
70
+
71
+ export type FocusAgentResult =
72
+ | { focused: true }
73
+ | { focused: false; reason: "terminal-not-found" | "focus-failed" };
74
+
75
+ export interface SendAgentPromptDeps {
76
+ runtime?: InteractiveAgentRuntime;
77
+ registry?: Pick<AgentRegistry, "lookup">;
78
+ focusManager: {
79
+ findTerminal(pid: number): Promise<TerminalLocation | null>;
80
+ };
81
+ writer?: (location: TerminalLocation, text: string) => Promise<void>;
82
+ }
83
+
84
+ /**
85
+ * Orchestrate `agent start`: ensure the configured runtime is available,
86
+ * create the runtime session, detect the agent PID, and register the entry.
87
+ * Callers are responsible for user input validation before invoking this.
88
+ */
89
+ export async function startAgent(
90
+ opts: StartAgentOptions,
91
+ deps: StartAgentDeps = {},
92
+ ): Promise<RegistryEntry> {
93
+ const registry = deps.registry ?? AgentRegistry.default();
94
+ const agent = AGENTS[opts.type];
95
+ const intervalMs = opts.pollIntervalMs ?? DEFAULT_PID_POLL_INTERVAL_MS;
96
+ const timeoutMs = opts.pollTimeoutMs ?? DEFAULT_PID_POLL_TIMEOUT_MS;
97
+ const provider = opts.runtimeProvider ?? deps.runtime?.provider ?? "tmux";
98
+ const tmux = provider === "tmux" ? (deps.tmux ?? new TmuxManager()) : undefined;
99
+ const runtime = resolveStartRuntime(provider, { ...deps, tmux });
100
+
101
+ const availability = await runtime.isAvailable();
102
+ if (!availability.ok) {
103
+ if (provider === "tmux") throw new TmuxUnavailableError();
104
+ throw new AgentRuntimeUnavailableError(provider, availability.reason, availability.detail);
105
+ }
106
+
107
+ registry.prune();
108
+ const existing = registry.lookup(opts.name);
109
+ if (existing) {
110
+ throw new AgentNameInUseError(opts.name, existing.pid);
111
+ }
112
+
113
+ if (provider === "tmux" && tmux && (await tmux.sessionExists(opts.name))) {
114
+ deps.onWarning?.(
115
+ `tmux session "${opts.name}" already exists but has no live registry entry — it will be replaced.`,
116
+ );
117
+ }
118
+
119
+ const result = await runtime.startAgent({
120
+ name: opts.name,
121
+ cwd: opts.cwd,
122
+ kind: agentRuntimeKind(opts.type, provider),
123
+ args: [],
124
+ timeoutMs,
125
+ ...(provider === "tmux"
126
+ ? {
127
+ command: agent.command,
128
+ matches: agent.matches,
129
+ pollIntervalMs: intervalMs,
130
+ }
131
+ : {}),
132
+ });
133
+
134
+ const entry: RegistryEntry = {
135
+ name: opts.name,
136
+ type: opts.type,
137
+ pid: result.pid,
138
+ runtime: runtime.provider,
139
+ runtimeRef: result.runtimeRef,
140
+ cwd: opts.cwd,
141
+ startedAt: new Date().toISOString(),
142
+ sessionId: "",
143
+ sessionFilePath: "",
144
+ pinned: false,
145
+ };
146
+ registry.register(entry);
147
+ return entry;
148
+ }
149
+
150
+ export async function stopAgent(
151
+ agent: Pick<AgentInfo, "name" | "pid">,
152
+ deps: StopAgentDeps = {},
153
+ ): Promise<StopAgentResult> {
154
+ const registry = deps.registry ?? AgentRegistry.default();
155
+ const registryEntry = registry.lookup(agent.name);
156
+ const runtime = resolveRuntimeForEntry(registryEntry, deps);
157
+ const runtimeRef = registryEntry?.runtimeRef ?? null;
158
+
159
+ await runtime.stop({
160
+ agent,
161
+ runtimeRef,
162
+ killProcess: deps.killProcess,
163
+ });
164
+
165
+ return {
166
+ agentName: agent.name,
167
+ pid: agent.pid,
168
+ runtime: runtime.provider,
169
+ runtimeRef,
170
+ };
171
+ }
172
+
173
+ export async function focusAgent(
174
+ agent: Pick<AgentInfo, "name" | "pid">,
175
+ deps: FocusAgentDeps,
176
+ ): Promise<FocusAgentResult> {
177
+ const registry = deps.registry ?? AgentRegistry.default();
178
+ const registryEntry = registry.lookup(agent.name);
179
+ const runtime = resolveRuntimeForEntry(registryEntry, deps);
180
+ if (runtime.provider === "tmux") {
181
+ const location = await deps.focusManager.findTerminal(agent.pid);
182
+ if (!location) return { focused: false, reason: "terminal-not-found" };
183
+
184
+ const focused = await deps.focusManager.focusTerminal(location);
185
+ return focused ? { focused: true } : { focused: false, reason: "focus-failed" };
186
+ }
187
+
188
+ const focused = await runtime.focus({
189
+ agent,
190
+ runtimeRef: registryEntry?.runtimeRef ?? null,
191
+ focusManager: deps.focusManager,
192
+ });
193
+
194
+ if (focused) return { focused: true };
195
+ return { focused: false, reason: "focus-failed" };
196
+ }
197
+
198
+ export async function sendAgentPrompt(
199
+ agent: Pick<AgentInfo, "name" | "pid">,
200
+ prompt: string,
201
+ deps: SendAgentPromptDeps,
202
+ ): Promise<void> {
203
+ const registry = deps.registry ?? AgentRegistry.default();
204
+ const registryEntry = registry.lookup(agent.name);
205
+ const runtime = resolveRuntimeForEntry(registryEntry, deps);
206
+
207
+ await runtime.send(
208
+ {
209
+ agent,
210
+ runtimeRef: registryEntry?.runtimeRef ?? null,
211
+ prompt,
212
+ },
213
+ {
214
+ focusManager: deps.focusManager,
215
+ writer: deps.writer,
216
+ },
217
+ );
218
+ }
219
+
220
+ function resolveStartRuntime(
221
+ provider: AgentRuntimeProvider,
222
+ deps: StartAgentDeps,
223
+ ): InteractiveAgentRuntime {
224
+ if (deps.runtime && deps.runtime.provider === provider) {
225
+ return deps.runtime;
226
+ }
227
+ if (provider === "tmux") return new TmuxAgentRuntime(deps.tmux);
228
+ return createInteractiveRuntime(provider);
229
+ }
230
+
231
+ function resolveRuntimeForEntry(
232
+ registryEntry: RegistryEntry | null,
233
+ deps: { runtime?: InteractiveAgentRuntime; tmux?: Pick<TmuxManager, "killSession"> },
234
+ ): InteractiveAgentRuntime {
235
+ if (isHerdrRegistryEntry(registryEntry)) {
236
+ return deps.runtime?.provider === "herdr" ? deps.runtime : createInteractiveRuntime("herdr");
237
+ }
238
+ if (deps.runtime?.provider === "tmux") return deps.runtime;
239
+ return deps.tmux
240
+ ? new TmuxAgentRuntime(deps.tmux as TmuxManager)
241
+ : createInteractiveRuntime("tmux");
242
+ }
243
+
244
+ function isHerdrRegistryEntry(
245
+ entry: unknown,
246
+ ): entry is RegistryEntry & { runtime: "herdr"; runtimeRef: unknown } {
247
+ return (
248
+ typeof entry === "object" &&
249
+ entry !== null &&
250
+ (entry as { runtime?: unknown }).runtime === "herdr" &&
251
+ "runtimeRef" in entry
252
+ );
253
+ }
254
+
255
+ function agentRuntimeKind(type: StartableAgentType, provider: AgentRuntimeProvider): string {
256
+ if (provider === "tmux") return type;
257
+ return {
258
+ claude: "claude",
259
+ codex: "codex",
260
+ copilot: "copilot",
261
+ gemini_cli: "gemini",
262
+ grok_cli: "grok",
263
+ opencode: "opencode",
264
+ pi: "pi",
265
+ }[type];
266
+ }
@@ -0,0 +1,13 @@
1
+ import type { AgentRuntimeProvider } from "../utils/AgentRegistry.js";
2
+ import { HerdrAgentRuntime } from "./herdr/HerdrAgentRuntime.js";
3
+ import { TmuxAgentRuntime } from "./tmux/TmuxAgentRuntime.js";
4
+ import type { InteractiveAgentRuntime } from "./types.js";
5
+
6
+ function createHerdrRuntime(): InteractiveAgentRuntime {
7
+ return new HerdrAgentRuntime();
8
+ }
9
+
10
+ export function createInteractiveRuntime(provider: AgentRuntimeProvider): InteractiveAgentRuntime {
11
+ if (provider === "herdr") return createHerdrRuntime();
12
+ return new TmuxAgentRuntime();
13
+ }
@@ -0,0 +1,50 @@
1
+ import type { AgentRuntimeProvider } from "../utils/AgentRegistry.js";
2
+
3
+ export class TmuxUnavailableError extends Error {
4
+ constructor() {
5
+ super("tmux is not installed or not in PATH.");
6
+ this.name = "TmuxUnavailableError";
7
+ }
8
+ }
9
+
10
+ export class AgentNameInUseError extends Error {
11
+ constructor(
12
+ public agentName: string,
13
+ public pid: number,
14
+ ) {
15
+ super(`Agent "${agentName}" is already running (PID ${pid}).`);
16
+ this.name = "AgentNameInUseError";
17
+ }
18
+ }
19
+
20
+ export class AgentPidPollTimeoutError extends Error {
21
+ constructor(
22
+ public agentName: string,
23
+ public command: string,
24
+ public timeoutMs: number,
25
+ ) {
26
+ super(`Agent process not found after ${timeoutMs / 1000}s.`);
27
+ this.name = "AgentPidPollTimeoutError";
28
+ }
29
+ }
30
+
31
+ export class AgentRuntimeUnavailableError extends Error {
32
+ constructor(
33
+ public provider: AgentRuntimeProvider,
34
+ public reason: string,
35
+ public detail: string,
36
+ ) {
37
+ super(`${provider} runtime is unavailable (${reason}): ${detail}`);
38
+ this.name = "AgentRuntimeUnavailableError";
39
+ }
40
+ }
41
+
42
+ export class AgentTerminalNotFoundError extends Error {
43
+ constructor(
44
+ public agentName: string,
45
+ public pid: number,
46
+ ) {
47
+ super(`Cannot find terminal for agent "${agentName}" (PID: ${pid}).`);
48
+ this.name = "AgentTerminalNotFoundError";
49
+ }
50
+ }
@@ -0,0 +1,190 @@
1
+ import { HerdrCliClient, isCommandMissing, type HerdrCommandRunner } from "./HerdrCliClient.js";
2
+ import { HerdrRuntimeError } from "./HerdrErrors.js";
3
+ import { parseHerdrRuntimeRef } from "./HerdrRuntimeRef.js";
4
+ import {
5
+ extractAgentRuntimeRef,
6
+ extractProcessInfoPid,
7
+ extractWorkspaceStart,
8
+ } from "./HerdrResponseParsers.js";
9
+ import type {
10
+ AgentRuntimeAvailability,
11
+ InteractiveAgentRuntime,
12
+ RuntimeFocusInput,
13
+ RuntimeSendInput,
14
+ RuntimeStartInput,
15
+ RuntimeStartResult,
16
+ RuntimeStopInput,
17
+ } from "../types.js";
18
+
19
+ const AGENT_START_BUSY_RETRY_MS = 5000;
20
+ const AGENT_START_BUSY_RETRY_INTERVAL_MS = 100;
21
+
22
+ export interface HerdrRuntimeOptions {
23
+ runner?: HerdrCommandRunner;
24
+ env?: NodeJS.ProcessEnv;
25
+ agentStartBusyRetryMs?: number;
26
+ agentStartBusyRetryIntervalMs?: number;
27
+ }
28
+
29
+ export class HerdrAgentRuntime implements InteractiveAgentRuntime {
30
+ readonly provider = "herdr" as const;
31
+
32
+ private readonly client: HerdrCliClient;
33
+ private readonly env: NodeJS.ProcessEnv;
34
+ private readonly agentStartBusyRetryMs: number;
35
+ private readonly agentStartBusyRetryIntervalMs: number;
36
+
37
+ constructor(options: HerdrRuntimeOptions = {}) {
38
+ this.client = new HerdrCliClient(options.runner);
39
+ this.env = options.env ?? process.env;
40
+ this.agentStartBusyRetryMs = options.agentStartBusyRetryMs ?? AGENT_START_BUSY_RETRY_MS;
41
+ this.agentStartBusyRetryIntervalMs =
42
+ options.agentStartBusyRetryIntervalMs ?? AGENT_START_BUSY_RETRY_INTERVAL_MS;
43
+ }
44
+
45
+ async isAvailable(): Promise<AgentRuntimeAvailability> {
46
+ try {
47
+ await this.client.run(["--version"]);
48
+ } catch (error) {
49
+ if (isCommandMissing(error)) {
50
+ return {
51
+ ok: false,
52
+ reason: "binary-missing",
53
+ detail: "herdr command was not found in PATH.",
54
+ };
55
+ }
56
+ return {
57
+ ok: false,
58
+ reason: "backend-unreachable",
59
+ detail: (error as Error).message,
60
+ };
61
+ }
62
+
63
+ try {
64
+ await this.client.run(["api", "snapshot"]);
65
+ } catch (error) {
66
+ return {
67
+ ok: false,
68
+ reason: "backend-unreachable",
69
+ detail: (error as Error).message,
70
+ };
71
+ }
72
+
73
+ const currentPaneId = nonEmptyString(this.env.HERDR_PANE_ID);
74
+ return {
75
+ ok: true,
76
+ insideRuntime: this.env.HERDR_ENV === "1",
77
+ ...(currentPaneId ? { currentPaneId } : {}),
78
+ };
79
+ }
80
+
81
+ async startAgent(input: RuntimeStartInput): Promise<RuntimeStartResult> {
82
+ const workspace = extractWorkspaceStart(
83
+ await this.client.runJson(["workspace", "create", "--cwd", input.cwd, "--label", input.name]),
84
+ );
85
+
86
+ const agentResponse = await this.runAgentStartJson([
87
+ "agent",
88
+ "start",
89
+ input.name,
90
+ "--kind",
91
+ input.kind,
92
+ "--pane",
93
+ workspace.paneId,
94
+ ...(input.timeoutMs ? ["--timeout", String(input.timeoutMs)] : []),
95
+ ...(input.args?.length ? ["--", ...input.args] : []),
96
+ ]);
97
+ const runtimeRef = extractAgentRuntimeRef(agentResponse, {
98
+ name: input.name,
99
+ paneId: workspace.paneId,
100
+ workspaceId: workspace.workspaceId,
101
+ });
102
+ const processInfoResponse = await this.client.runJson([
103
+ "pane",
104
+ "process-info",
105
+ "--pane",
106
+ runtimeRef.paneId,
107
+ ]);
108
+ const pid = extractProcessInfoPid(processInfoResponse);
109
+ if (pid === null) {
110
+ throw new HerdrRuntimeError("Herdr pane process-info response did not include process pid.");
111
+ }
112
+
113
+ return { pid, runtimeRef };
114
+ }
115
+
116
+ async send(input: RuntimeSendInput): Promise<void> {
117
+ const ref = parseHerdrRuntimeRef(input.runtimeRef);
118
+ await this.client.run(["agent", "prompt", ref.paneId, input.prompt]);
119
+ }
120
+
121
+ async wait(input: { runtimeRef: unknown; timeoutMs: number }): Promise<void> {
122
+ const ref = parseHerdrRuntimeRef(input.runtimeRef);
123
+ await this.client.run([
124
+ "agent",
125
+ "wait",
126
+ ref.paneId,
127
+ "--until",
128
+ "done",
129
+ "--until",
130
+ "blocked",
131
+ "--timeout",
132
+ String(input.timeoutMs),
133
+ ]);
134
+ }
135
+
136
+ async readOutput(input: { runtimeRef: unknown; lines?: number }): Promise<string> {
137
+ const ref = parseHerdrRuntimeRef(input.runtimeRef);
138
+ const { stdout } = await this.client.run([
139
+ "agent",
140
+ "read",
141
+ ref.paneId,
142
+ "--source",
143
+ "recent-unwrapped",
144
+ "--lines",
145
+ String(input.lines ?? 120),
146
+ ]);
147
+ return stdout;
148
+ }
149
+
150
+ async focus(input: RuntimeFocusInput): Promise<boolean> {
151
+ const ref = parseHerdrRuntimeRef(input.runtimeRef);
152
+ await this.client.run(["agent", "focus", ref.paneId]);
153
+ return true;
154
+ }
155
+
156
+ async stop(input: RuntimeStopInput): Promise<void> {
157
+ const ref = parseHerdrRuntimeRef(input.runtimeRef);
158
+ await this.client.run(["pane", "close", ref.paneId]);
159
+ }
160
+
161
+ private async runAgentStartJson(args: string[]): Promise<unknown> {
162
+ const deadline = Date.now() + this.agentStartBusyRetryMs;
163
+ let lastBusyError: HerdrRuntimeError | null = null;
164
+ do {
165
+ try {
166
+ return await this.client.runJson(args);
167
+ } catch (error) {
168
+ if (!(error instanceof HerdrRuntimeError) || error.code !== "agent_pane_busy") throw error;
169
+ lastBusyError = error;
170
+ if (Date.now() >= deadline) break;
171
+ await sleep(this.agentStartBusyRetryIntervalMs);
172
+ }
173
+ } while (Date.now() < deadline);
174
+ throw (
175
+ lastBusyError ??
176
+ new HerdrRuntimeError("Herdr agent start failed because the target pane stayed busy.", {
177
+ code: "agent_pane_busy",
178
+ })
179
+ );
180
+ }
181
+ }
182
+
183
+ function sleep(ms: number): Promise<void> {
184
+ if (ms <= 0) return Promise.resolve();
185
+ return new Promise((resolve) => setTimeout(resolve, ms));
186
+ }
187
+
188
+ function nonEmptyString(value: unknown): string | undefined {
189
+ return typeof value === "string" && value.trim() ? value : undefined;
190
+ }
@@ -0,0 +1,78 @@
1
+ import { execFile } from "child_process";
2
+ import { promisify } from "util";
3
+ import { HerdrRuntimeError } from "./HerdrErrors.js";
4
+ import { herdrErrorFromResponse } from "./HerdrResponseParsers.js";
5
+
6
+ const execFileAsync = promisify(execFile);
7
+
8
+ export interface HerdrCommandResult {
9
+ stdout: string;
10
+ stderr: string;
11
+ }
12
+
13
+ export type HerdrCommandRunner = (command: string, args: string[]) => Promise<HerdrCommandResult>;
14
+
15
+ export class HerdrCliClient {
16
+ constructor(private readonly runner: HerdrCommandRunner = defaultRunner) {}
17
+
18
+ run(args: string[]): Promise<HerdrCommandResult> {
19
+ return this.runner("herdr", args);
20
+ }
21
+
22
+ async runJson(args: string[]): Promise<unknown> {
23
+ let stdout: string;
24
+ try {
25
+ ({ stdout } = await this.run(args));
26
+ } catch (error) {
27
+ throw parseHerdrCommandError(error);
28
+ }
29
+ try {
30
+ const parsed = JSON.parse(stdout) as unknown;
31
+ const herdrError = herdrErrorFromResponse(parsed);
32
+ if (herdrError) throw herdrError;
33
+ return parsed;
34
+ } catch (error) {
35
+ if (error instanceof HerdrRuntimeError) throw error;
36
+ throw new HerdrRuntimeError(`Herdr returned invalid JSON: ${(error as Error).message}`);
37
+ }
38
+ }
39
+ }
40
+
41
+ export function isCommandMissing(error: unknown): boolean {
42
+ return Boolean(
43
+ error &&
44
+ typeof error === "object" &&
45
+ "code" in error &&
46
+ (error as NodeJS.ErrnoException).code === "ENOENT",
47
+ );
48
+ }
49
+
50
+ function defaultRunner(command: string, args: string[]): Promise<HerdrCommandResult> {
51
+ return execFileAsync(command, args).then(({ stdout, stderr }) => ({ stdout, stderr }));
52
+ }
53
+
54
+ function parseHerdrCommandError(error: unknown): HerdrRuntimeError {
55
+ const stdout =
56
+ typeof error === "object" && error && "stdout" in error
57
+ ? String((error as { stdout?: unknown }).stdout ?? "")
58
+ : "";
59
+ const stderr =
60
+ typeof error === "object" && error && "stderr" in error
61
+ ? String((error as { stderr?: unknown }).stderr ?? "")
62
+ : "";
63
+ const parsed = parseJson(stdout) ?? parseJson(stderr);
64
+ if (parsed) {
65
+ const herdrError = herdrErrorFromResponse(parsed);
66
+ if (herdrError) return herdrError;
67
+ }
68
+ return new HerdrRuntimeError((error as Error).message);
69
+ }
70
+
71
+ function parseJson(value: string): unknown | null {
72
+ if (!value.trim()) return null;
73
+ try {
74
+ return JSON.parse(value) as unknown;
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
@@ -0,0 +1,9 @@
1
+ export class HerdrRuntimeError extends Error {
2
+ readonly code?: string;
3
+
4
+ constructor(message: string, options: { code?: string } = {}) {
5
+ super(message);
6
+ this.name = "HerdrRuntimeError";
7
+ this.code = options.code;
8
+ }
9
+ }
@@ -0,0 +1,76 @@
1
+ import { HerdrRuntimeError } from "./HerdrErrors.js";
2
+ import type { HerdrRuntimeRef } from "./HerdrRuntimeRef.js";
3
+
4
+ export function extractWorkspaceStart(value: unknown): { workspaceId?: string; paneId: string } {
5
+ const workspaceId = getString(value, ["result", "workspace", "workspace_id"]);
6
+ const paneId = getString(value, ["result", "root_pane", "pane_id"]);
7
+ if (!paneId) {
8
+ throw new HerdrRuntimeError("Herdr workspace create response did not include root pane id.");
9
+ }
10
+ return {
11
+ ...(workspaceId ? { workspaceId } : {}),
12
+ paneId,
13
+ };
14
+ }
15
+
16
+ export function extractAgentRuntimeRef(
17
+ value: unknown,
18
+ fallback: { paneId: string; name: string; workspaceId?: string },
19
+ ): HerdrRuntimeRef {
20
+ const agentPaneId = getString(value, ["result", "agent", "pane_id"]) ?? fallback.paneId;
21
+ const agentName = getString(value, ["result", "agent", "name"]) ?? fallback.name;
22
+ const tabId = getString(value, ["result", "agent", "tab_id"]);
23
+ return {
24
+ session: "default",
25
+ ...(fallback.workspaceId ? { workspaceId: fallback.workspaceId } : {}),
26
+ ...(tabId ? { tabId } : {}),
27
+ paneId: agentPaneId,
28
+ agentName,
29
+ };
30
+ }
31
+
32
+ export function extractProcessInfoPid(value: unknown): number | null {
33
+ const processInfo = getObject(value, ["result", "process_info"]);
34
+ if (!processInfo) return null;
35
+ const processes = processInfo.foreground_processes;
36
+ if (!Array.isArray(processes)) return numberOrNull(processInfo.shell_pid);
37
+ for (const processInfo of processes) {
38
+ if (!processInfo || typeof processInfo !== "object") continue;
39
+ const pid = numberOrNull((processInfo as { pid?: unknown }).pid);
40
+ if (pid !== null) return pid;
41
+ }
42
+ return numberOrNull(processInfo.shell_pid);
43
+ }
44
+
45
+ export function herdrErrorFromResponse(value: unknown): HerdrRuntimeError | null {
46
+ const error = getObject(value, ["error"]);
47
+ if (!error) return null;
48
+ const message = nonEmptyString(error.message) ?? "Herdr command failed.";
49
+ const code = nonEmptyString(error.code);
50
+ return new HerdrRuntimeError(message, code ? { code } : {});
51
+ }
52
+
53
+ function getObject(value: unknown, path: string[]): Record<string, unknown> | null {
54
+ let current = value;
55
+ for (const part of path) {
56
+ if (!current || typeof current !== "object" || Array.isArray(current) || !(part in current))
57
+ return null;
58
+ current = (current as Record<string, unknown>)[part];
59
+ }
60
+ return current && typeof current === "object" && !Array.isArray(current)
61
+ ? (current as Record<string, unknown>)
62
+ : null;
63
+ }
64
+
65
+ function getString(value: unknown, path: string[]): string | undefined {
66
+ const parent = getObject(value, path.slice(0, -1));
67
+ return parent ? nonEmptyString(parent[path[path.length - 1]!]) : undefined;
68
+ }
69
+
70
+ function nonEmptyString(value: unknown): string | undefined {
71
+ return typeof value === "string" && value.trim() ? value : undefined;
72
+ }
73
+
74
+ function numberOrNull(value: unknown): number | null {
75
+ return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
76
+ }