@ai-devkit/agent-manager 0.32.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 +134 -134
  76. package/dist/__tests__/readiness/AgentReadiness.test.js.map +1 -1
  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 -43
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +27 -26
  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 +6 -6
  279. package/dist/readiness/AgentReadiness.d.ts.map +1 -1
  280. package/dist/readiness/AgentReadiness.js +130 -130
  281. package/dist/readiness/AgentReadiness.js.map +1 -1
  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 +217 -169
  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 +144 -103
  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 +585 -513
  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,80 @@
1
+ import { TmuxManager } from "../../terminal/TmuxManager.js";
2
+ import { TtyWriter } from "../../terminal/TtyWriter.js";
3
+ import { AgentPidPollTimeoutError, AgentTerminalNotFoundError } from "../errors.js";
4
+ import { pollForPid } from "./PidPolling.js";
5
+ import { parseTmuxRuntimeRef } from "./TmuxRuntimeRef.js";
6
+ export class TmuxAgentRuntime {
7
+ provider = "tmux";
8
+ tmux;
9
+ constructor(tmux = new TmuxManager()){
10
+ this.tmux = tmux;
11
+ }
12
+ async isAvailable() {
13
+ if (await this.tmux.isAvailable()) {
14
+ return {
15
+ ok: true,
16
+ insideRuntime: Boolean(process.env.TMUX)
17
+ };
18
+ }
19
+ return {
20
+ ok: false,
21
+ reason: "binary-missing",
22
+ detail: "tmux is not installed or not in PATH."
23
+ };
24
+ }
25
+ async startAgent(input) {
26
+ if (!input.command || !input.matches || input.pollIntervalMs === undefined) {
27
+ throw new Error("Tmux start requires command, process matcher, and poll interval.");
28
+ }
29
+ if (await this.tmux.sessionExists(input.name)) {
30
+ await this.tmux.killSession(input.name);
31
+ }
32
+ await this.tmux.createSession(input.name, input.cwd);
33
+ await this.tmux.sendKeys(input.name, input.command);
34
+ const pid = await pollForPid(this.tmux, input.name, input.matches, input.pollIntervalMs, input.timeoutMs);
35
+ if (pid === null) {
36
+ await this.tmux.killSession(input.name);
37
+ throw new AgentPidPollTimeoutError(input.name, input.command, input.timeoutMs);
38
+ }
39
+ return {
40
+ pid,
41
+ runtimeRef: {
42
+ session: input.name
43
+ }
44
+ };
45
+ }
46
+ async send(input, deps) {
47
+ if (!deps) {
48
+ throw new Error("Tmux send requires terminal lookup dependencies.");
49
+ }
50
+ const location = await deps.focusManager.findTerminal(input.agent.pid);
51
+ if (!location) {
52
+ throw new AgentTerminalNotFoundError(input.agent.name, input.agent.pid);
53
+ }
54
+ await (deps.writer ?? TtyWriter.send)(location, input.prompt);
55
+ }
56
+ async focus(input) {
57
+ const location = await input.focusManager.findTerminal(input.agent.pid);
58
+ if (!location) return false;
59
+ return await input.focusManager.focusTerminal(location);
60
+ }
61
+ async stop(input) {
62
+ const killProcess = input.killProcess ?? ((pid, signal)=>process.kill(pid, signal));
63
+ try {
64
+ killProcess(input.agent.pid, "SIGTERM");
65
+ } catch (error) {
66
+ if (!isProcessAlreadyGone(error)) {
67
+ throw error;
68
+ }
69
+ }
70
+ const tmuxRef = parseTmuxRuntimeRef(input.runtimeRef);
71
+ if (tmuxRef) {
72
+ await this.tmux.killSession(tmuxRef.session);
73
+ }
74
+ }
75
+ }
76
+ function isProcessAlreadyGone(error) {
77
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ESRCH";
78
+ }
79
+
80
+ //# sourceMappingURL=TmuxAgentRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/runtime/tmux/TmuxAgentRuntime.ts"],"sourcesContent":["import { TmuxManager } from \"../../terminal/TmuxManager.js\";\nimport { TtyWriter } from \"../../terminal/TtyWriter.js\";\nimport { AgentPidPollTimeoutError, AgentTerminalNotFoundError } from \"../errors.js\";\nimport { pollForPid } from \"./PidPolling.js\";\nimport { parseTmuxRuntimeRef } from \"./TmuxRuntimeRef.js\";\nimport type {\n AgentRuntimeAvailability,\n InteractiveAgentRuntime,\n RuntimeFocusInput,\n RuntimeSendDeps,\n RuntimeSendInput,\n RuntimeStartInput,\n RuntimeStartResult,\n RuntimeStopInput,\n} from \"../types.js\";\n\nexport class TmuxAgentRuntime implements InteractiveAgentRuntime {\n readonly provider = \"tmux\" as const;\n private readonly tmux: TmuxManager;\n\n constructor(tmux: TmuxManager = new TmuxManager()) {\n this.tmux = tmux;\n }\n\n async isAvailable(): Promise<AgentRuntimeAvailability> {\n if (await this.tmux.isAvailable()) {\n return { ok: true, insideRuntime: Boolean(process.env.TMUX) };\n }\n return {\n ok: false,\n reason: \"binary-missing\",\n detail: \"tmux is not installed or not in PATH.\",\n };\n }\n\n async startAgent(\n input: RuntimeStartInput & {\n command?: string;\n matches?: (psCommand: string) => boolean;\n pollIntervalMs?: number;\n },\n ): Promise<RuntimeStartResult> {\n if (!input.command || !input.matches || input.pollIntervalMs === undefined) {\n throw new Error(\"Tmux start requires command, process matcher, and poll interval.\");\n }\n\n if (await this.tmux.sessionExists(input.name)) {\n await this.tmux.killSession(input.name);\n }\n\n await this.tmux.createSession(input.name, input.cwd);\n await this.tmux.sendKeys(input.name, input.command);\n\n const pid = await pollForPid(\n this.tmux,\n input.name,\n input.matches,\n input.pollIntervalMs,\n input.timeoutMs,\n );\n if (pid === null) {\n await this.tmux.killSession(input.name);\n throw new AgentPidPollTimeoutError(input.name, input.command, input.timeoutMs);\n }\n\n return {\n pid,\n runtimeRef: { session: input.name },\n };\n }\n\n async send(input: RuntimeSendInput, deps?: RuntimeSendDeps): Promise<void> {\n if (!deps) {\n throw new Error(\"Tmux send requires terminal lookup dependencies.\");\n }\n const location = await deps.focusManager.findTerminal(input.agent.pid);\n if (!location) {\n throw new AgentTerminalNotFoundError(input.agent.name, input.agent.pid);\n }\n await (deps.writer ?? TtyWriter.send)(location, input.prompt);\n }\n\n async focus(input: RuntimeFocusInput): Promise<boolean> {\n const location = await input.focusManager.findTerminal(input.agent.pid);\n if (!location) return false;\n return await input.focusManager.focusTerminal(location);\n }\n\n async stop(input: RuntimeStopInput): Promise<void> {\n const killProcess = input.killProcess ?? ((pid, signal) => process.kill(pid, signal));\n try {\n killProcess(input.agent.pid, \"SIGTERM\");\n } catch (error) {\n if (!isProcessAlreadyGone(error)) {\n throw error;\n }\n }\n\n const tmuxRef = parseTmuxRuntimeRef(input.runtimeRef);\n if (tmuxRef) {\n await this.tmux.killSession(tmuxRef.session);\n }\n }\n}\n\nfunction isProcessAlreadyGone(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as NodeJS.ErrnoException).code === \"ESRCH\"\n );\n}\n"],"names":["TmuxManager","TtyWriter","AgentPidPollTimeoutError","AgentTerminalNotFoundError","pollForPid","parseTmuxRuntimeRef","TmuxAgentRuntime","provider","tmux","isAvailable","ok","insideRuntime","Boolean","process","env","TMUX","reason","detail","startAgent","input","command","matches","pollIntervalMs","undefined","Error","sessionExists","name","killSession","createSession","cwd","sendKeys","pid","timeoutMs","runtimeRef","session","send","deps","location","focusManager","findTerminal","agent","writer","prompt","focus","focusTerminal","stop","killProcess","signal","kill","error","isProcessAlreadyGone","tmuxRef","code"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface TmuxRuntimeRef {
2
+ session: string;
3
+ }
4
+ export declare function parseTmuxRuntimeRef(value: unknown): TmuxRuntimeRef | null;
5
+ //# sourceMappingURL=TmuxRuntimeRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TmuxRuntimeRef.d.ts","sourceRoot":"","sources":["../../../src/runtime/tmux/TmuxRuntimeRef.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAIzE"}
@@ -0,0 +1,9 @@
1
+ export function parseTmuxRuntimeRef(value) {
2
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
3
+ const session = value.session;
4
+ return typeof session === "string" && session.trim() ? {
5
+ session
6
+ } : null;
7
+ }
8
+
9
+ //# sourceMappingURL=TmuxRuntimeRef.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/runtime/tmux/TmuxRuntimeRef.ts"],"sourcesContent":["export interface TmuxRuntimeRef {\n session: string;\n}\n\nexport function parseTmuxRuntimeRef(value: unknown): TmuxRuntimeRef | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const session = (value as { session?: unknown }).session;\n return typeof session === \"string\" && session.trim() ? { session } : null;\n}\n"],"names":["parseTmuxRuntimeRef","value","Array","isArray","session","trim"],"mappings":"AAIA,OAAO,SAASA,oBAAoBC,KAAc;IAChD,IAAI,CAACA,SAAS,OAAOA,UAAU,YAAYC,MAAMC,OAAO,CAACF,QAAQ,OAAO;IACxE,MAAMG,UAAU,AAACH,MAAgCG,OAAO;IACxD,OAAO,OAAOA,YAAY,YAAYA,QAAQC,IAAI,KAAK;QAAED;IAAQ,IAAI;AACvE"}
@@ -0,0 +1,54 @@
1
+ import type { AgentInfo } from "../adapters/AgentAdapter.js";
2
+ import type { TerminalLocation } from "../terminal/TerminalFocusManager.js";
3
+ import type { AgentRuntimeProvider } from "../utils/AgentRegistry.js";
4
+ export type AgentRuntimeAvailability = {
5
+ ok: true;
6
+ insideRuntime: boolean;
7
+ currentPaneId?: string;
8
+ } | {
9
+ ok: false;
10
+ reason: "binary-missing" | "backend-unreachable";
11
+ detail: string;
12
+ };
13
+ export interface RuntimeStartInput {
14
+ name: string;
15
+ cwd: string;
16
+ kind: string;
17
+ args: string[];
18
+ timeoutMs: number;
19
+ }
20
+ export interface RuntimeStartResult {
21
+ pid: number;
22
+ runtimeRef: unknown;
23
+ }
24
+ export interface RuntimeTargetInput {
25
+ agent: Pick<AgentInfo, "name" | "pid">;
26
+ runtimeRef: unknown | null;
27
+ }
28
+ export interface RuntimeSendInput extends RuntimeTargetInput {
29
+ prompt: string;
30
+ }
31
+ export interface RuntimeFocusInput extends RuntimeTargetInput {
32
+ focusManager: {
33
+ findTerminal(pid: number): Promise<TerminalLocation | null>;
34
+ focusTerminal(location: TerminalLocation): Promise<boolean>;
35
+ };
36
+ }
37
+ export interface RuntimeStopInput extends RuntimeTargetInput {
38
+ killProcess?: (pid: number, signal: NodeJS.Signals) => void;
39
+ }
40
+ export interface RuntimeSendDeps {
41
+ focusManager: {
42
+ findTerminal(pid: number): Promise<TerminalLocation | null>;
43
+ };
44
+ writer?: (location: TerminalLocation, text: string) => Promise<void>;
45
+ }
46
+ export interface InteractiveAgentRuntime {
47
+ provider: AgentRuntimeProvider;
48
+ isAvailable(): Promise<AgentRuntimeAvailability>;
49
+ startAgent(input: RuntimeStartInput): Promise<RuntimeStartResult>;
50
+ send(input: RuntimeSendInput, deps?: RuntimeSendDeps): Promise<void>;
51
+ focus(input: RuntimeFocusInput): Promise<boolean>;
52
+ stop(input: RuntimeStopInput): Promise<void>;
53
+ }
54
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/runtime/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,GAAG,qBAAqB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;IACvC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,YAAY,EAAE;QACZ,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;QAC5D,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAC7D,CAAC;CACH;AAED,MAAM,WAAW,gBAAiB,SAAQ,kBAAkB;IAC1D,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE;QACZ,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;KAC7D,CAAC;IACF,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACjD,UAAU,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClE,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C"}
@@ -0,0 +1,3 @@
1
+ export { };
2
+
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/runtime/types.ts"],"sourcesContent":["import type { AgentInfo } from \"../adapters/AgentAdapter.js\";\nimport type { TerminalLocation } from \"../terminal/TerminalFocusManager.js\";\nimport type { AgentRuntimeProvider } from \"../utils/AgentRegistry.js\";\n\nexport type AgentRuntimeAvailability =\n | { ok: true; insideRuntime: boolean; currentPaneId?: string }\n | { ok: false; reason: \"binary-missing\" | \"backend-unreachable\"; detail: string };\n\nexport interface RuntimeStartInput {\n name: string;\n cwd: string;\n kind: string;\n args: string[];\n timeoutMs: number;\n}\n\nexport interface RuntimeStartResult {\n pid: number;\n runtimeRef: unknown;\n}\n\nexport interface RuntimeTargetInput {\n agent: Pick<AgentInfo, \"name\" | \"pid\">;\n runtimeRef: unknown | null;\n}\n\nexport interface RuntimeSendInput extends RuntimeTargetInput {\n prompt: string;\n}\n\nexport interface RuntimeFocusInput extends RuntimeTargetInput {\n focusManager: {\n findTerminal(pid: number): Promise<TerminalLocation | null>;\n focusTerminal(location: TerminalLocation): Promise<boolean>;\n };\n}\n\nexport interface RuntimeStopInput extends RuntimeTargetInput {\n killProcess?: (pid: number, signal: NodeJS.Signals) => void;\n}\n\nexport interface RuntimeSendDeps {\n focusManager: {\n findTerminal(pid: number): Promise<TerminalLocation | null>;\n };\n writer?: (location: TerminalLocation, text: string) => Promise<void>;\n}\n\nexport interface InteractiveAgentRuntime {\n provider: AgentRuntimeProvider;\n isAvailable(): Promise<AgentRuntimeAvailability>;\n startAgent(input: RuntimeStartInput): Promise<RuntimeStartResult>;\n send(input: RuntimeSendInput, deps?: RuntimeSendDeps): Promise<void>;\n focus(input: RuntimeFocusInput): Promise<boolean>;\n stop(input: RuntimeStopInput): Promise<void>;\n}\n"],"names":[],"mappings":"AAgDA,WAOC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TerminalFocusManager.d.ts","sourceRoot":"","sources":["../../src/terminal/TerminalFocusManager.ts"],"names":[],"mappings":"AAOA,oBAAY,YAAY;IACpB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACf;AAaD;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5D,qBAAa,oBAAoB;IACjB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAN,KAAK,CAAC,EAAE,mBAAmB,YAAA;IAExD;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAqDjE;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;YA2BnD,eAAe;YA6Bf,gBAAgB;YAShB,YAAY;YAwBZ,iBAAiB;YAsCjB,qBAAqB;YAoCrB,gBAAgB;YAQhB,aAAa;YASb,kBAAkB;YAqBlB,sBAAsB;CAmBvC"}
1
+ {"version":3,"file":"TerminalFocusManager.d.ts","sourceRoot":"","sources":["../../src/terminal/TerminalFocusManager.ts"],"names":[],"mappings":"AAOA,oBAAY,YAAY;IACtB,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAaD;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5D,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAN,KAAK,CAAC,EAAE,mBAAmB,YAAA;IAExD;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAqDjE;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;YA6BnD,eAAe;YA2Bf,gBAAgB;YAShB,YAAY;YA2BZ,iBAAiB;YAsCjB,qBAAqB;YAoCrB,gBAAgB;YAQhB,aAAa;YASb,kBAAkB;YAqBlB,sBAAsB;CAmBrC"}
@@ -1,7 +1,7 @@
1
- import { execFile } from 'child_process';
2
- import { promisify } from 'util';
3
- import { getProcessTty } from '../utils/process.js';
4
- import { escapeAppleScript } from '../utils/applescript.js';
1
+ import { execFile } from "child_process";
2
+ import { promisify } from "util";
3
+ import { getProcessTty } from "../utils/process.js";
4
+ import { escapeAppleScript } from "../utils/applescript.js";
5
5
  const execFileAsync = promisify(execFile);
6
6
  export var TerminalType = /*#__PURE__*/ function(TerminalType) {
7
7
  TerminalType["TMUX"] = "tmux";
@@ -17,11 +17,11 @@ export class TerminalFocusManager {
17
17
  this.debug = debug;
18
18
  }
19
19
  /**
20
- * Find the terminal location (emulator info) for a given process ID
21
- */ async findTerminal(pid) {
20
+ * Find the terminal location (emulator info) for a given process ID
21
+ */ async findTerminal(pid) {
22
22
  const ttyShort = getProcessTty(pid);
23
23
  // If no TTY or invalid, we can't find the terminal
24
- if (!ttyShort || ttyShort === '?') {
24
+ if (!ttyShort || ttyShort === "?") {
25
25
  this.debug?.(`findTerminal(pid=${pid}): no usable TTY, cannot resolve terminal`);
26
26
  return null;
27
27
  }
@@ -33,39 +33,39 @@ export class TerminalFocusManager {
33
33
  this.debug?.(`findTerminal: matched tmux (identifier=${tmuxLocation.identifier})`);
34
34
  return tmuxLocation;
35
35
  }
36
- this.debug?.('findTerminal: tmux no match');
36
+ this.debug?.("findTerminal: tmux no match");
37
37
  // 2. Check WezTerm (cross-platform, via its CLI — no AppleScript)
38
38
  const weztermLocation = await this.findWeztermPane(fullTty);
39
39
  if (weztermLocation) {
40
40
  this.debug?.(`findTerminal: matched wezterm (pane_id=${weztermLocation.identifier})`);
41
41
  return weztermLocation;
42
42
  }
43
- this.debug?.('findTerminal: wezterm no match');
43
+ this.debug?.("findTerminal: wezterm no match");
44
44
  // 3. Check iTerm2
45
45
  const itermLocation = await this.findITerm2Session(fullTty);
46
46
  if (itermLocation) {
47
47
  this.debug?.(`findTerminal: matched iTerm2 (tty=${itermLocation.tty})`);
48
48
  return itermLocation;
49
49
  }
50
- this.debug?.('findTerminal: iTerm2 no match');
50
+ this.debug?.("findTerminal: iTerm2 no match");
51
51
  // 4. Check Terminal.app
52
52
  const terminalAppLocation = await this.findTerminalAppWindow(fullTty);
53
53
  if (terminalAppLocation) {
54
54
  this.debug?.(`findTerminal: matched Terminal.app (tty=${terminalAppLocation.tty})`);
55
55
  return terminalAppLocation;
56
56
  }
57
- this.debug?.('findTerminal: Terminal.app no match');
57
+ this.debug?.("findTerminal: Terminal.app no match");
58
58
  // 5. Fallback: we know the TTY but not the emulator wrapper
59
- this.debug?.('findTerminal: no emulator matched; returning UNKNOWN');
59
+ this.debug?.("findTerminal: no emulator matched; returning UNKNOWN");
60
60
  return {
61
61
  type: "unknown",
62
- identifier: '',
62
+ identifier: "",
63
63
  tty: fullTty
64
64
  };
65
65
  }
66
66
  /**
67
- * Focus the terminal identified by the location
68
- */ async focusTerminal(location) {
67
+ * Focus the terminal identified by the location
68
+ */ async focusTerminal(location) {
69
69
  this.debug?.(`focusTerminal: focusing ${location.type} (identifier=${location.identifier}, tty=${location.tty})`);
70
70
  let success = false;
71
71
  try {
@@ -88,21 +88,21 @@ export class TerminalFocusManager {
88
88
  } catch {
89
89
  success = false;
90
90
  }
91
- this.debug?.(`focusTerminal: ${success ? 'succeeded' : 'failed'} for ${location.type}`);
91
+ this.debug?.(`focusTerminal: ${success ? "succeeded" : "failed"} for ${location.type}`);
92
92
  return success;
93
93
  }
94
94
  async findWeztermPane(tty) {
95
95
  try {
96
- const { stdout } = await execFileAsync('wezterm', [
97
- 'cli',
98
- 'list',
99
- '--format',
100
- 'json'
96
+ const { stdout } = await execFileAsync("wezterm", [
97
+ "cli",
98
+ "list",
99
+ "--format",
100
+ "json"
101
101
  ]);
102
102
  const panes = JSON.parse(stdout);
103
103
  if (!Array.isArray(panes)) return null;
104
104
  for (const pane of panes){
105
- if (pane && typeof pane.tty_name === 'string' && pane.tty_name === tty && pane.pane_id != null) {
105
+ if (pane && typeof pane.tty_name === "string" && pane.tty_name === tty && pane.pane_id != null) {
106
106
  return {
107
107
  type: "wezterm",
108
108
  identifier: String(pane.pane_id),
@@ -117,10 +117,10 @@ export class TerminalFocusManager {
117
117
  }
118
118
  async focusWeztermPane(paneId) {
119
119
  try {
120
- await execFileAsync('wezterm', [
121
- 'cli',
122
- 'activate-pane',
123
- '--pane-id',
120
+ await execFileAsync("wezterm", [
121
+ "cli",
122
+ "activate-pane",
123
+ "--pane-id",
124
124
  paneId
125
125
  ]);
126
126
  return true;
@@ -130,16 +130,16 @@ export class TerminalFocusManager {
130
130
  }
131
131
  async findTmuxPane(tty) {
132
132
  try {
133
- const { stdout } = await execFileAsync('tmux', [
134
- 'list-panes',
135
- '-a',
136
- '-F',
137
- '#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}'
133
+ const { stdout } = await execFileAsync("tmux", [
134
+ "list-panes",
135
+ "-a",
136
+ "-F",
137
+ "#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}"
138
138
  ]);
139
- const lines = stdout.trim().split('\n');
139
+ const lines = stdout.trim().split("\n");
140
140
  for (const line of lines){
141
141
  if (!line.trim()) continue;
142
- const [paneTty, identifier] = line.split('|');
142
+ const [paneTty, identifier] = line.split("|");
143
143
  if (paneTty === tty && identifier) {
144
144
  return {
145
145
  type: "tmux",
@@ -156,7 +156,7 @@ export class TerminalFocusManager {
156
156
  async findITerm2Session(tty) {
157
157
  try {
158
158
  // Check if iTerm2 is running first to avoid launching it.
159
- if (!await this.isProcessRunning('iTerm2')) return null;
159
+ if (!await this.isProcessRunning("iTerm2")) return null;
160
160
  } catch {
161
161
  return null;
162
162
  }
@@ -175,8 +175,8 @@ export class TerminalFocusManager {
175
175
  end repeat
176
176
  end tell
177
177
  `;
178
- const { stdout } = await execFileAsync('osascript', [
179
- '-e',
178
+ const { stdout } = await execFileAsync("osascript", [
179
+ "-e",
180
180
  script
181
181
  ]);
182
182
  if (stdout.trim() === "found") {
@@ -194,7 +194,7 @@ export class TerminalFocusManager {
194
194
  async findTerminalAppWindow(tty) {
195
195
  try {
196
196
  // Check if Terminal.app is running
197
- if (!await this.isProcessRunning('Terminal')) return null;
197
+ if (!await this.isProcessRunning("Terminal")) return null;
198
198
  } catch {
199
199
  return null;
200
200
  }
@@ -211,8 +211,8 @@ export class TerminalFocusManager {
211
211
  end repeat
212
212
  end tell
213
213
  `;
214
- const { stdout } = await execFileAsync('osascript', [
215
- '-e',
214
+ const { stdout } = await execFileAsync("osascript", [
215
+ "-e",
216
216
  script
217
217
  ]);
218
218
  if (stdout.trim() === "found") {
@@ -228,17 +228,17 @@ export class TerminalFocusManager {
228
228
  return null;
229
229
  }
230
230
  async isProcessRunning(name) {
231
- const { stdout } = await execFileAsync('ps', [
232
- '-Axo',
233
- 'comm'
231
+ const { stdout } = await execFileAsync("ps", [
232
+ "-Axo",
233
+ "comm"
234
234
  ]);
235
- return stdout.split('\n').map((line)=>line.trim()).some((command)=>command === name || command.endsWith(`/${name}`));
235
+ return stdout.split("\n").map((line)=>line.trim()).some((command)=>command === name || command.endsWith(`/${name}`));
236
236
  }
237
237
  async focusTmuxPane(identifier) {
238
238
  try {
239
- await execFileAsync('tmux', [
240
- 'switch-client',
241
- '-t',
239
+ await execFileAsync("tmux", [
240
+ "switch-client",
241
+ "-t",
242
242
  identifier
243
243
  ]);
244
244
  return true;
@@ -263,8 +263,8 @@ export class TerminalFocusManager {
263
263
  end repeat
264
264
  end tell
265
265
  `;
266
- const { stdout } = await execFileAsync('osascript', [
267
- '-e',
266
+ const { stdout } = await execFileAsync("osascript", [
267
+ "-e",
268
268
  script
269
269
  ]);
270
270
  return stdout.trim() === "true";
@@ -285,8 +285,8 @@ export class TerminalFocusManager {
285
285
  end repeat
286
286
  end tell
287
287
  `;
288
- const { stdout } = await execFileAsync('osascript', [
289
- '-e',
288
+ const { stdout } = await execFileAsync("osascript", [
289
+ "-e",
290
290
  script
291
291
  ]);
292
292
  return stdout.trim() === "true";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/terminal/TerminalFocusManager.ts"],"sourcesContent":["import { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { getProcessTty } from '../utils/process.js';\nimport { escapeAppleScript } from '../utils/applescript.js';\n\nconst execFileAsync = promisify(execFile);\n\nexport enum TerminalType {\n TMUX = 'tmux',\n WEZTERM = 'wezterm',\n ITERM2 = 'iterm2',\n TERMINAL_APP = 'terminal-app',\n UNKNOWN = 'unknown',\n}\n\nexport interface TerminalLocation {\n type: TerminalType;\n identifier: string; // e.g., \"session:window.pane\" for tmux, WezTerm pane id, or TTY for others\n tty: string; // e.g., \"/dev/ttys030\"\n}\n\n/**\n * Subset of a `wezterm cli list --format json` entry. Only `pane_id` and\n * `tty_name` are read; extra fields are ignored so schema additions across\n * WezTerm versions don't break parsing. (The TTY is exposed as `tty_name` in\n * the JSON, not `tty`.)\n */\ninterface WeztermPaneEntry {\n pane_id?: number;\n tty_name?: string | null;\n}\n\n/**\n * Optional trace sink. When provided to {@link TerminalFocusManager}, each\n * discovery/focus step reports a human-readable line so callers (e.g. the\n * `agent open --debug` command) can inspect the matching/focus decision path.\n */\nexport type TerminalDebugLogger = (message: string) => void;\n\nexport class TerminalFocusManager {\n constructor(private readonly debug?: TerminalDebugLogger) {}\n\n /**\n * Find the terminal location (emulator info) for a given process ID\n */\n async findTerminal(pid: number): Promise<TerminalLocation | null> {\n const ttyShort = getProcessTty(pid);\n\n // If no TTY or invalid, we can't find the terminal\n if (!ttyShort || ttyShort === '?') {\n this.debug?.(`findTerminal(pid=${pid}): no usable TTY, cannot resolve terminal`);\n return null;\n }\n\n const fullTty = `/dev/${ttyShort}`;\n this.debug?.(`findTerminal(pid=${pid}): resolving terminal for ${fullTty}`);\n\n // 1. Check tmux (most specific if running inside it)\n const tmuxLocation = await this.findTmuxPane(fullTty);\n if (tmuxLocation) {\n this.debug?.(`findTerminal: matched tmux (identifier=${tmuxLocation.identifier})`);\n return tmuxLocation;\n }\n this.debug?.('findTerminal: tmux no match');\n\n // 2. Check WezTerm (cross-platform, via its CLI — no AppleScript)\n const weztermLocation = await this.findWeztermPane(fullTty);\n if (weztermLocation) {\n this.debug?.(`findTerminal: matched wezterm (pane_id=${weztermLocation.identifier})`);\n return weztermLocation;\n }\n this.debug?.('findTerminal: wezterm no match');\n\n // 3. Check iTerm2\n const itermLocation = await this.findITerm2Session(fullTty);\n if (itermLocation) {\n this.debug?.(`findTerminal: matched iTerm2 (tty=${itermLocation.tty})`);\n return itermLocation;\n }\n this.debug?.('findTerminal: iTerm2 no match');\n\n // 4. Check Terminal.app\n const terminalAppLocation = await this.findTerminalAppWindow(fullTty);\n if (terminalAppLocation) {\n this.debug?.(`findTerminal: matched Terminal.app (tty=${terminalAppLocation.tty})`);\n return terminalAppLocation;\n }\n this.debug?.('findTerminal: Terminal.app no match');\n\n // 5. Fallback: we know the TTY but not the emulator wrapper\n this.debug?.('findTerminal: no emulator matched; returning UNKNOWN');\n return {\n type: TerminalType.UNKNOWN,\n identifier: '',\n tty: fullTty\n };\n }\n\n /**\n * Focus the terminal identified by the location\n */\n async focusTerminal(location: TerminalLocation): Promise<boolean> {\n this.debug?.(`focusTerminal: focusing ${location.type} (identifier=${location.identifier}, tty=${location.tty})`);\n let success = false;\n try {\n switch (location.type) {\n case TerminalType.TMUX:\n success = await this.focusTmuxPane(location.identifier);\n break;\n case TerminalType.WEZTERM:\n success = await this.focusWeztermPane(location.identifier);\n break;\n case TerminalType.ITERM2:\n success = await this.focusITerm2Session(location.tty);\n break;\n case TerminalType.TERMINAL_APP:\n success = await this.focusTerminalAppWindow(location.tty);\n break;\n default:\n success = false;\n }\n } catch {\n success = false;\n }\n this.debug?.(`focusTerminal: ${success ? 'succeeded' : 'failed'} for ${location.type}`);\n return success;\n }\n\n private async findWeztermPane(tty: string): Promise<TerminalLocation | null> {\n try {\n const { stdout } = await execFileAsync('wezterm', [\n 'cli', 'list', '--format', 'json',\n ]);\n\n const panes = JSON.parse(stdout) as WeztermPaneEntry[];\n if (!Array.isArray(panes)) return null;\n\n for (const pane of panes) {\n if (\n pane &&\n typeof pane.tty_name === 'string' &&\n pane.tty_name === tty &&\n pane.pane_id != null\n ) {\n return {\n type: TerminalType.WEZTERM,\n identifier: String(pane.pane_id),\n tty,\n };\n }\n }\n } catch {\n // wezterm not installed, not running, or returned invalid JSON\n }\n return null;\n }\n\n private async focusWeztermPane(paneId: string): Promise<boolean> {\n try {\n await execFileAsync('wezterm', ['cli', 'activate-pane', '--pane-id', paneId]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async findTmuxPane(tty: string): Promise<TerminalLocation | null> {\n try {\n const { stdout } = await execFileAsync('tmux', [\n 'list-panes', '-a', '-F', '#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}'\n ]);\n\n const lines = stdout.trim().split('\\n');\n for (const line of lines) {\n if (!line.trim()) continue;\n const [paneTty, identifier] = line.split('|');\n if (paneTty === tty && identifier) {\n return {\n type: TerminalType.TMUX,\n identifier,\n tty\n };\n }\n }\n } catch {\n // tmux might not be installed or running\n }\n return null;\n }\n\n private async findITerm2Session(tty: string): Promise<TerminalLocation | null> {\n try {\n // Check if iTerm2 is running first to avoid launching it.\n if (!await this.isProcessRunning('iTerm2')) return null;\n } catch {\n return null;\n }\n\n try {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"iTerm\"\n repeat with w in windows\n repeat with t in tabs of w\n repeat with s in sessions of t\n if tty of s is \"${escapedTty}\" then\n return \"found\"\n end if\n end repeat\n end repeat\n end repeat\n end tell\n `;\n\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n if (stdout.trim() === \"found\") {\n return {\n type: TerminalType.ITERM2,\n identifier: tty,\n tty\n };\n }\n } catch {\n // iTerm2 script failed\n }\n return null;\n }\n\n private async findTerminalAppWindow(tty: string): Promise<TerminalLocation | null> {\n try {\n // Check if Terminal.app is running\n if (!await this.isProcessRunning('Terminal')) return null;\n } catch {\n return null;\n }\n\n try {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"Terminal\"\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapedTty}\" then\n return \"found\"\n end if\n end repeat\n end repeat\n end tell\n `;\n\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n if (stdout.trim() === \"found\") {\n return {\n type: TerminalType.TERMINAL_APP,\n identifier: tty,\n tty\n };\n }\n } catch {\n // Terminal.app script failed\n }\n return null;\n }\n\n private async isProcessRunning(name: string): Promise<boolean> {\n const { stdout } = await execFileAsync('ps', ['-Axo', 'comm']);\n return stdout\n .split('\\n')\n .map((line) => line.trim())\n .some((command) => command === name || command.endsWith(`/${name}`));\n }\n\n private async focusTmuxPane(identifier: string): Promise<boolean> {\n try {\n await execFileAsync('tmux', ['switch-client', '-t', identifier]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async focusITerm2Session(tty: string): Promise<boolean> {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"iTerm\"\n activate\n repeat with w in windows\n repeat with t in tabs of w\n repeat with s in sessions of t\n if tty of s is \"${escapedTty}\" then\n select s\n return \"true\"\n end if\n end repeat\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n return stdout.trim() === \"true\";\n }\n\n private async focusTerminalAppWindow(tty: string): Promise<boolean> {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"Terminal\"\n activate\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapedTty}\" then\n set index of w to 1\n set selected tab of w to t\n return \"true\"\n end if\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync('osascript', ['-e', script]);\n return stdout.trim() === \"true\";\n }\n}\n"],"names":["execFile","promisify","getProcessTty","escapeAppleScript","execFileAsync","TerminalType","TerminalFocusManager","debug","findTerminal","pid","ttyShort","fullTty","tmuxLocation","findTmuxPane","identifier","weztermLocation","findWeztermPane","itermLocation","findITerm2Session","tty","terminalAppLocation","findTerminalAppWindow","type","focusTerminal","location","success","focusTmuxPane","focusWeztermPane","focusITerm2Session","focusTerminalAppWindow","stdout","panes","JSON","parse","Array","isArray","pane","tty_name","pane_id","String","paneId","lines","trim","split","line","paneTty","isProcessRunning","escapedTty","script","name","map","some","command","endsWith"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/terminal/TerminalFocusManager.ts"],"sourcesContent":["import { execFile } from \"child_process\";\nimport { promisify } from \"util\";\nimport { getProcessTty } from \"../utils/process.js\";\nimport { escapeAppleScript } from \"../utils/applescript.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport enum TerminalType {\n TMUX = \"tmux\",\n WEZTERM = \"wezterm\",\n ITERM2 = \"iterm2\",\n TERMINAL_APP = \"terminal-app\",\n UNKNOWN = \"unknown\",\n}\n\nexport interface TerminalLocation {\n type: TerminalType;\n identifier: string; // e.g., \"session:window.pane\" for tmux, WezTerm pane id, or TTY for others\n tty: string; // e.g., \"/dev/ttys030\"\n}\n\n/**\n * Subset of a `wezterm cli list --format json` entry. Only `pane_id` and\n * `tty_name` are read; extra fields are ignored so schema additions across\n * WezTerm versions don't break parsing. (The TTY is exposed as `tty_name` in\n * the JSON, not `tty`.)\n */\ninterface WeztermPaneEntry {\n pane_id?: number;\n tty_name?: string | null;\n}\n\n/**\n * Optional trace sink. When provided to {@link TerminalFocusManager}, each\n * discovery/focus step reports a human-readable line so callers (e.g. the\n * `agent open --debug` command) can inspect the matching/focus decision path.\n */\nexport type TerminalDebugLogger = (message: string) => void;\n\nexport class TerminalFocusManager {\n constructor(private readonly debug?: TerminalDebugLogger) {}\n\n /**\n * Find the terminal location (emulator info) for a given process ID\n */\n async findTerminal(pid: number): Promise<TerminalLocation | null> {\n const ttyShort = getProcessTty(pid);\n\n // If no TTY or invalid, we can't find the terminal\n if (!ttyShort || ttyShort === \"?\") {\n this.debug?.(`findTerminal(pid=${pid}): no usable TTY, cannot resolve terminal`);\n return null;\n }\n\n const fullTty = `/dev/${ttyShort}`;\n this.debug?.(`findTerminal(pid=${pid}): resolving terminal for ${fullTty}`);\n\n // 1. Check tmux (most specific if running inside it)\n const tmuxLocation = await this.findTmuxPane(fullTty);\n if (tmuxLocation) {\n this.debug?.(`findTerminal: matched tmux (identifier=${tmuxLocation.identifier})`);\n return tmuxLocation;\n }\n this.debug?.(\"findTerminal: tmux no match\");\n\n // 2. Check WezTerm (cross-platform, via its CLI — no AppleScript)\n const weztermLocation = await this.findWeztermPane(fullTty);\n if (weztermLocation) {\n this.debug?.(`findTerminal: matched wezterm (pane_id=${weztermLocation.identifier})`);\n return weztermLocation;\n }\n this.debug?.(\"findTerminal: wezterm no match\");\n\n // 3. Check iTerm2\n const itermLocation = await this.findITerm2Session(fullTty);\n if (itermLocation) {\n this.debug?.(`findTerminal: matched iTerm2 (tty=${itermLocation.tty})`);\n return itermLocation;\n }\n this.debug?.(\"findTerminal: iTerm2 no match\");\n\n // 4. Check Terminal.app\n const terminalAppLocation = await this.findTerminalAppWindow(fullTty);\n if (terminalAppLocation) {\n this.debug?.(`findTerminal: matched Terminal.app (tty=${terminalAppLocation.tty})`);\n return terminalAppLocation;\n }\n this.debug?.(\"findTerminal: Terminal.app no match\");\n\n // 5. Fallback: we know the TTY but not the emulator wrapper\n this.debug?.(\"findTerminal: no emulator matched; returning UNKNOWN\");\n return {\n type: TerminalType.UNKNOWN,\n identifier: \"\",\n tty: fullTty,\n };\n }\n\n /**\n * Focus the terminal identified by the location\n */\n async focusTerminal(location: TerminalLocation): Promise<boolean> {\n this.debug?.(\n `focusTerminal: focusing ${location.type} (identifier=${location.identifier}, tty=${location.tty})`,\n );\n let success = false;\n try {\n switch (location.type) {\n case TerminalType.TMUX:\n success = await this.focusTmuxPane(location.identifier);\n break;\n case TerminalType.WEZTERM:\n success = await this.focusWeztermPane(location.identifier);\n break;\n case TerminalType.ITERM2:\n success = await this.focusITerm2Session(location.tty);\n break;\n case TerminalType.TERMINAL_APP:\n success = await this.focusTerminalAppWindow(location.tty);\n break;\n default:\n success = false;\n }\n } catch {\n success = false;\n }\n this.debug?.(`focusTerminal: ${success ? \"succeeded\" : \"failed\"} for ${location.type}`);\n return success;\n }\n\n private async findWeztermPane(tty: string): Promise<TerminalLocation | null> {\n try {\n const { stdout } = await execFileAsync(\"wezterm\", [\"cli\", \"list\", \"--format\", \"json\"]);\n\n const panes = JSON.parse(stdout) as WeztermPaneEntry[];\n if (!Array.isArray(panes)) return null;\n\n for (const pane of panes) {\n if (\n pane &&\n typeof pane.tty_name === \"string\" &&\n pane.tty_name === tty &&\n pane.pane_id != null\n ) {\n return {\n type: TerminalType.WEZTERM,\n identifier: String(pane.pane_id),\n tty,\n };\n }\n }\n } catch {\n // wezterm not installed, not running, or returned invalid JSON\n }\n return null;\n }\n\n private async focusWeztermPane(paneId: string): Promise<boolean> {\n try {\n await execFileAsync(\"wezterm\", [\"cli\", \"activate-pane\", \"--pane-id\", paneId]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async findTmuxPane(tty: string): Promise<TerminalLocation | null> {\n try {\n const { stdout } = await execFileAsync(\"tmux\", [\n \"list-panes\",\n \"-a\",\n \"-F\",\n \"#{pane_tty}|#{session_name}:#{window_index}.#{pane_index}\",\n ]);\n\n const lines = stdout.trim().split(\"\\n\");\n for (const line of lines) {\n if (!line.trim()) continue;\n const [paneTty, identifier] = line.split(\"|\");\n if (paneTty === tty && identifier) {\n return {\n type: TerminalType.TMUX,\n identifier,\n tty,\n };\n }\n }\n } catch {\n // tmux might not be installed or running\n }\n return null;\n }\n\n private async findITerm2Session(tty: string): Promise<TerminalLocation | null> {\n try {\n // Check if iTerm2 is running first to avoid launching it.\n if (!(await this.isProcessRunning(\"iTerm2\"))) return null;\n } catch {\n return null;\n }\n\n try {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"iTerm\"\n repeat with w in windows\n repeat with t in tabs of w\n repeat with s in sessions of t\n if tty of s is \"${escapedTty}\" then\n return \"found\"\n end if\n end repeat\n end repeat\n end repeat\n end tell\n `;\n\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n if (stdout.trim() === \"found\") {\n return {\n type: TerminalType.ITERM2,\n identifier: tty,\n tty,\n };\n }\n } catch {\n // iTerm2 script failed\n }\n return null;\n }\n\n private async findTerminalAppWindow(tty: string): Promise<TerminalLocation | null> {\n try {\n // Check if Terminal.app is running\n if (!(await this.isProcessRunning(\"Terminal\"))) return null;\n } catch {\n return null;\n }\n\n try {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"Terminal\"\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapedTty}\" then\n return \"found\"\n end if\n end repeat\n end repeat\n end tell\n `;\n\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n if (stdout.trim() === \"found\") {\n return {\n type: TerminalType.TERMINAL_APP,\n identifier: tty,\n tty,\n };\n }\n } catch {\n // Terminal.app script failed\n }\n return null;\n }\n\n private async isProcessRunning(name: string): Promise<boolean> {\n const { stdout } = await execFileAsync(\"ps\", [\"-Axo\", \"comm\"]);\n return stdout\n .split(\"\\n\")\n .map((line) => line.trim())\n .some((command) => command === name || command.endsWith(`/${name}`));\n }\n\n private async focusTmuxPane(identifier: string): Promise<boolean> {\n try {\n await execFileAsync(\"tmux\", [\"switch-client\", \"-t\", identifier]);\n return true;\n } catch {\n return false;\n }\n }\n\n private async focusITerm2Session(tty: string): Promise<boolean> {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"iTerm\"\n activate\n repeat with w in windows\n repeat with t in tabs of w\n repeat with s in sessions of t\n if tty of s is \"${escapedTty}\" then\n select s\n return \"true\"\n end if\n end repeat\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n return stdout.trim() === \"true\";\n }\n\n private async focusTerminalAppWindow(tty: string): Promise<boolean> {\n const escapedTty = escapeAppleScript(tty);\n const script = `\n tell application \"Terminal\"\n activate\n repeat with w in windows\n repeat with t in tabs of w\n if tty of t is \"${escapedTty}\" then\n set index of w to 1\n set selected tab of w to t\n return \"true\"\n end if\n end repeat\n end repeat\n end tell\n `;\n const { stdout } = await execFileAsync(\"osascript\", [\"-e\", script]);\n return stdout.trim() === \"true\";\n }\n}\n"],"names":["execFile","promisify","getProcessTty","escapeAppleScript","execFileAsync","TerminalType","TerminalFocusManager","debug","findTerminal","pid","ttyShort","fullTty","tmuxLocation","findTmuxPane","identifier","weztermLocation","findWeztermPane","itermLocation","findITerm2Session","tty","terminalAppLocation","findTerminalAppWindow","type","focusTerminal","location","success","focusTmuxPane","focusWeztermPane","focusITerm2Session","focusTerminalAppWindow","stdout","panes","JSON","parse","Array","isArray","pane","tty_name","pane_id","String","paneId","lines","trim","split","line","paneTty","isProcessRunning","escapedTty","script","name","map","some","command","endsWith"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TmuxManager.d.ts","sourceRoot":"","sources":["../../src/terminal/TmuxManager.ts"],"names":[],"mappings":"AAKA,qBAAa,WAAW;IACd,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS7C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C;;;;;;;;;;;;;;;OAeG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAyBtF,UAAU;YAYV,aAAa;YAab,iBAAiB;CASlC"}
1
+ {"version":3,"file":"TmuxManager.d.ts","sourceRoot":"","sources":["../../src/terminal/TmuxManager.ts"],"names":[],"mappings":"AAKA,qBAAa,WAAW;IAChB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS7C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C;;;;;;;;;;;;;;;OAeG;IACG,YAAY,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAyBX,UAAU;YAgBV,aAAa;YAab,iBAAiB;CAShC"}