@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
@@ -1,38 +1,38 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import type { ProcessInfo } from '../../adapters/AgentAdapter.js';
4
- import { AgentStatus } from '../../adapters/AgentAdapter.js';
5
- import { matchProcessesToSessions, type MatchResult } from '../../utils/matching.js';
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import type { ProcessInfo } from "../../adapters/AgentAdapter.js";
4
+ import { AgentStatus } from "../../adapters/AgentAdapter.js";
5
+ import { matchProcessesToSessions, type MatchResult } from "../../utils/matching.js";
6
6
  import {
7
- batchGetSessionFileBirthtimes,
8
- isDirectory,
9
- listJsonl,
10
- safeReaddir,
11
- safeStat,
12
- type SessionFile,
13
- } from '../../utils/session.js';
7
+ batchGetSessionFileBirthtimes,
8
+ isDirectory,
9
+ listJsonl,
10
+ safeReaddir,
11
+ safeStat,
12
+ type SessionFile,
13
+ } from "../../utils/session.js";
14
14
 
15
15
  /**
16
16
  * Entry in ~/.claude/sessions/<pid>.json written by Claude Code.
17
17
  * Maps a running process to its session file via PID.
18
18
  */
19
19
  interface PidFileEntry {
20
- pid: number;
21
- sessionId: string;
22
- cwd: string;
23
- /** Epoch milliseconds when the Claude Code process started */
24
- startedAt: number;
25
- kind: string;
26
- entrypoint: string;
27
- /**
28
- * Authoritative live status published by the Claude Code process
29
- * (e.g., 'running', 'waiting', 'idle'). Preferred over JSONL-derived
30
- * status because trailing entries like 'permission-mode' / 'ai-title'
31
- * can mask the real conversational state.
32
- */
33
- status?: string;
34
- /** Short description of what the agent is waiting on (e.g., "approve Read"). */
35
- waitingFor?: string;
20
+ pid: number;
21
+ sessionId: string;
22
+ cwd: string;
23
+ /** Epoch milliseconds when the Claude Code process started */
24
+ startedAt: number;
25
+ kind: string;
26
+ entrypoint: string;
27
+ /**
28
+ * Authoritative live status published by the Claude Code process
29
+ * (e.g., 'running', 'waiting', 'idle'). Preferred over JSONL-derived
30
+ * status because trailing entries like 'permission-mode' / 'ai-title'
31
+ * can mask the real conversational state.
32
+ */
33
+ status?: string;
34
+ /** Short description of what the agent is waiting on (e.g., "approve Read"). */
35
+ waitingFor?: string;
36
36
  }
37
37
 
38
38
  /**
@@ -43,298 +43,296 @@ interface PidFileEntry {
43
43
  * the JSONL-derived heuristic.
44
44
  */
45
45
  export interface ClaudeDirectMatch {
46
- process: ProcessInfo;
47
- sessionFile: SessionFile;
48
- pidStatus?: AgentStatus;
49
- waitingFor?: string;
46
+ process: ProcessInfo;
47
+ sessionFile: SessionFile;
48
+ pidStatus?: AgentStatus;
49
+ waitingFor?: string;
50
50
  }
51
51
 
52
52
  export interface ClaudeProcessSessionMatches {
53
- direct: ClaudeDirectMatch[];
54
- legacyMatches: MatchResult[];
53
+ direct: ClaudeDirectMatch[];
54
+ legacyMatches: MatchResult[];
55
55
  }
56
56
 
57
57
  export interface ClaudeSessionLocatorOptions {
58
- projectsDir?: string;
59
- sessionsDir?: string;
58
+ projectsDir?: string;
59
+ sessionsDir?: string;
60
60
  }
61
61
 
62
62
  /** Maximum allowed delta (ms) between process start time and PID file startedAt. */
63
63
  const PID_FILE_STALENESS_MS = 60000;
64
64
 
65
65
  export class ClaudeSessionLocator {
66
- private readonly projectsDir: string;
67
- private readonly sessionsDir: string;
68
-
69
- constructor(options: ClaudeSessionLocatorOptions = {}) {
70
- const homeDir = process.env.HOME || process.env.USERPROFILE || '';
71
- this.projectsDir = options.projectsDir ?? path.join(homeDir, '.claude', 'projects');
72
- this.sessionsDir = options.sessionsDir ?? path.join(homeDir, '.claude', 'sessions');
66
+ private readonly projectsDir: string;
67
+ private readonly sessionsDir: string;
68
+
69
+ constructor(options: ClaudeSessionLocatorOptions = {}) {
70
+ const homeDir = process.env.HOME || process.env.USERPROFILE || "";
71
+ this.projectsDir = options.projectsDir ?? path.join(homeDir, ".claude", "projects");
72
+ this.sessionsDir = options.sessionsDir ?? path.join(homeDir, ".claude", "sessions");
73
+ }
74
+
75
+ /**
76
+ * Pair live Claude processes with their session files.
77
+ *
78
+ * Runs three staged strategies, each handing its unmatched processes
79
+ * to the next:
80
+ * 1. `--resume <id>` on the command line — authoritative for resumed
81
+ * sessions whose JSONL predates the process.
82
+ * 2. PID-file matching via ~/.claude/sessions/<pid>.json.
83
+ * 3. Legacy CWD+birthtime heuristic, for processes with no PID file.
84
+ */
85
+ matchRunningProcesses(processes: ProcessInfo[]): ClaudeProcessSessionMatches {
86
+ const { direct: resumeDirect, fallback: noResume } = this.tryResumeMatching(processes);
87
+ const { direct: pidDirect, fallback } = this.tryPidFileMatching(noResume);
88
+ const legacySessions = this.discoverLiveSessions(fallback);
89
+ const legacyMatches =
90
+ fallback.length > 0 && legacySessions.length > 0
91
+ ? matchProcessesToSessions(fallback, legacySessions)
92
+ : [];
93
+
94
+ return {
95
+ direct: [...resumeDirect, ...pidDirect],
96
+ legacyMatches,
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Discover candidate session files for listing historical sessions.
102
+ *
103
+ * Always walks every subdirectory of `projectsDir`. We can't use the
104
+ * encoded-dir shortcut for the cwd-scoped path because Claude Code
105
+ * indexes session files by where the *process was launched*, not by
106
+ * the recorded `cwd` field inside the session — these diverge in
107
+ * worktrees and similar setups. The cwd filter is applied later
108
+ * against `session.lastCwd` so callers see exactly the sessions whose
109
+ * recorded cwd matches.
110
+ */
111
+ discoverHistoricalSessionFiles(): Array<{ filePath: string; defaultCwd: string }> {
112
+ const out: Array<{ filePath: string; defaultCwd: string }> = [];
113
+
114
+ if (!isDirectory(this.projectsDir)) return out;
115
+
116
+ for (const dirName of safeReaddir(this.projectsDir)) {
117
+ const projectDir = path.join(this.projectsDir, dirName);
118
+ if (!isDirectory(projectDir)) continue;
119
+
120
+ // Best-effort decode for the rare case session content has no
121
+ // recorded cwd: '-Users-foo-bar' → '/Users/foo/bar'. Lossy for
122
+ // paths containing '-'; session content's lastCwd overrides
123
+ // this when available.
124
+ const decoded = dirName.replace(/-/g, "/");
125
+ for (const name of listJsonl(projectDir)) {
126
+ out.push({ filePath: path.join(projectDir, name), defaultCwd: decoded });
127
+ }
73
128
  }
74
129
 
75
- /**
76
- * Pair live Claude processes with their session files.
77
- *
78
- * Runs three staged strategies, each handing its unmatched processes
79
- * to the next:
80
- * 1. `--resume <id>` on the command line — authoritative for resumed
81
- * sessions whose JSONL predates the process.
82
- * 2. PID-file matching via ~/.claude/sessions/<pid>.json.
83
- * 3. Legacy CWD+birthtime heuristic, for processes with no PID file.
84
- */
85
- matchRunningProcesses(processes: ProcessInfo[]): ClaudeProcessSessionMatches {
86
- const { direct: resumeDirect, fallback: noResume } = this.tryResumeMatching(processes);
87
- const { direct: pidDirect, fallback } = this.tryPidFileMatching(noResume);
88
- const legacySessions = this.discoverLiveSessions(fallback);
89
- const legacyMatches =
90
- fallback.length > 0 && legacySessions.length > 0
91
- ? matchProcessesToSessions(fallback, legacySessions)
92
- : [];
93
-
94
- return {
95
- direct: [...resumeDirect, ...pidDirect],
96
- legacyMatches,
97
- };
130
+ return out;
131
+ }
132
+
133
+ /**
134
+ * Derive the Claude Code project directory for a given CWD.
135
+ *
136
+ * Claude Code encodes paths by replacing every non-alphanumeric
137
+ * character with '-', so '/', '_', '.', spaces, etc. all collapse:
138
+ * /Users/foo/bar → -Users-foo-bar
139
+ * /Users/foo/my_project → -Users-foo-my-project
140
+ * /Users/foo/.worktrees/x -Users-foo--worktrees-x
141
+ *
142
+ * The encoding is lossy multiple real paths can collide on the
143
+ * same encoded dir. Callers that need to disambiguate must read the
144
+ * `cwd` field inside each session JSONL.
145
+ */
146
+ private getProjectDir(cwd: string): string {
147
+ const encoded = cwd.replace(/[^a-zA-Z0-9]/g, "-");
148
+ return path.join(this.projectsDir, encoded);
149
+ }
150
+
151
+ /**
152
+ * Discover session files for the given processes.
153
+ *
154
+ * For each unique process CWD, encodes it to derive the expected
155
+ * ~/.claude/projects/<encoded>/ directory, then gets session file birthtimes
156
+ * via a single batched stat call across all directories.
157
+ */
158
+ discoverLiveSessions(processes: ProcessInfo[]): SessionFile[] {
159
+ const dirToCwd = new Map<string, string>();
160
+
161
+ for (const proc of processes) {
162
+ if (!proc.cwd) continue;
163
+
164
+ const projectDir = this.getProjectDir(proc.cwd);
165
+ if (dirToCwd.has(projectDir)) continue;
166
+
167
+ try {
168
+ if (!fs.statSync(projectDir).isDirectory()) continue;
169
+ } catch {
170
+ continue;
171
+ }
172
+
173
+ dirToCwd.set(projectDir, proc.cwd);
98
174
  }
99
175
 
100
- /**
101
- * Discover candidate session files for listing historical sessions.
102
- *
103
- * Always walks every subdirectory of `projectsDir`. We can't use the
104
- * encoded-dir shortcut for the cwd-scoped path because Claude Code
105
- * indexes session files by where the *process was launched*, not by
106
- * the recorded `cwd` field inside the session — these diverge in
107
- * worktrees and similar setups. The cwd filter is applied later
108
- * against `session.lastCwd` so callers see exactly the sessions whose
109
- * recorded cwd matches.
110
- */
111
- discoverHistoricalSessionFiles(): Array<{ filePath: string; defaultCwd: string }> {
112
- const out: Array<{ filePath: string; defaultCwd: string }> = [];
113
-
114
- if (!isDirectory(this.projectsDir)) return out;
115
-
116
- for (const dirName of safeReaddir(this.projectsDir)) {
117
- const projectDir = path.join(this.projectsDir, dirName);
118
- if (!isDirectory(projectDir)) continue;
119
-
120
- // Best-effort decode for the rare case session content has no
121
- // recorded cwd: '-Users-foo-bar' → '/Users/foo/bar'. Lossy for
122
- // paths containing '-'; session content's lastCwd overrides
123
- // this when available.
124
- const decoded = dirName.replace(/-/g, '/');
125
- for (const name of listJsonl(projectDir)) {
126
- out.push({ filePath: path.join(projectDir, name), defaultCwd: decoded });
127
- }
128
- }
176
+ if (dirToCwd.size === 0) return [];
129
177
 
130
- return out;
131
- }
178
+ const files = batchGetSessionFileBirthtimes([...dirToCwd.keys()]);
132
179
 
133
- /**
134
- * Derive the Claude Code project directory for a given CWD.
135
- *
136
- * Claude Code encodes paths by replacing every non-alphanumeric
137
- * character with '-', so '/', '_', '.', spaces, etc. all collapse:
138
- * /Users/foo/bar → -Users-foo-bar
139
- * /Users/foo/my_project → -Users-foo-my-project
140
- * /Users/foo/.worktrees/x → -Users-foo--worktrees-x
141
- *
142
- * The encoding is lossy — multiple real paths can collide on the
143
- * same encoded dir. Callers that need to disambiguate must read the
144
- * `cwd` field inside each session JSONL.
145
- */
146
- private getProjectDir(cwd: string): string {
147
- const encoded = cwd.replace(/[^a-zA-Z0-9]/g, '-');
148
- return path.join(this.projectsDir, encoded);
180
+ for (const file of files) {
181
+ file.resolvedCwd = dirToCwd.get(file.projectDir) || "";
149
182
  }
150
183
 
151
- /**
152
- * Discover session files for the given processes.
153
- *
154
- * For each unique process CWD, encodes it to derive the expected
155
- * ~/.claude/projects/<encoded>/ directory, then gets session file birthtimes
156
- * via a single batched stat call across all directories.
157
- */
158
- discoverLiveSessions(processes: ProcessInfo[]): SessionFile[] {
159
- const dirToCwd = new Map<string, string>();
160
-
161
- for (const proc of processes) {
162
- if (!proc.cwd) continue;
163
-
164
- const projectDir = this.getProjectDir(proc.cwd);
165
- if (dirToCwd.has(projectDir)) continue;
166
-
167
- try {
168
- if (!fs.statSync(projectDir).isDirectory()) continue;
169
- } catch {
170
- continue;
171
- }
172
-
173
- dirToCwd.set(projectDir, proc.cwd);
174
- }
175
-
176
- if (dirToCwd.size === 0) return [];
177
-
178
- const files = batchGetSessionFileBirthtimes([...dirToCwd.keys()]);
184
+ return files;
185
+ }
179
186
 
180
- for (const file of files) {
181
- file.resolvedCwd = dirToCwd.get(file.projectDir) || '';
182
- }
183
-
184
- return files;
187
+ /**
188
+ * Match processes via `claude --resume <uuid>` in their command line.
189
+ * This works for resumed sessions, where the JSONL was created earlier
190
+ * (so its birthtime is far from the process startTime and the legacy
191
+ * matcher can't pair them) and the PID file may also be misaligned.
192
+ */
193
+ private tryResumeMatching(processes: ProcessInfo[]): {
194
+ direct: ClaudeDirectMatch[];
195
+ fallback: ProcessInfo[];
196
+ } {
197
+ const direct: ClaudeDirectMatch[] = [];
198
+ const fallback: ProcessInfo[] = [];
199
+
200
+ for (const proc of processes) {
201
+ const sessionId = this.extractResumeSessionId(proc.command);
202
+ if (!sessionId || !proc.cwd) {
203
+ fallback.push(proc);
204
+ continue;
205
+ }
206
+
207
+ const projectDir = this.getProjectDir(proc.cwd);
208
+ const jsonlPath = path.join(projectDir, `${sessionId}.jsonl`);
209
+
210
+ const stat = safeStat(jsonlPath);
211
+ if (!stat) {
212
+ fallback.push(proc);
213
+ continue;
214
+ }
215
+
216
+ // Best-effort: the PID file (if present for this proc) is the
217
+ // authoritative source of live status. We still match the session
218
+ // via --resume, but we read the PID file alongside to capture
219
+ // status/waitingFor.
220
+ const pidEntry = this.readMatchingPidFile(proc.pid, proc.startTime);
221
+
222
+ direct.push({
223
+ process: proc,
224
+ sessionFile: {
225
+ sessionId,
226
+ filePath: jsonlPath,
227
+ projectDir,
228
+ birthtimeMs: stat.birthtimeMs,
229
+ resolvedCwd: proc.cwd,
230
+ },
231
+ pidStatus: this.mapPidStatus(pidEntry?.status),
232
+ waitingFor: pidEntry?.waitingFor,
233
+ });
185
234
  }
186
235
 
187
- /**
188
- * Match processes via `claude --resume <uuid>` in their command line.
189
- * This works for resumed sessions, where the JSONL was created earlier
190
- * (so its birthtime is far from the process startTime and the legacy
191
- * matcher can't pair them) and the PID file may also be misaligned.
192
- */
193
- private tryResumeMatching(processes: ProcessInfo[]): {
194
- direct: ClaudeDirectMatch[];
195
- fallback: ProcessInfo[];
196
- } {
197
- const direct: ClaudeDirectMatch[] = [];
198
- const fallback: ProcessInfo[] = [];
199
-
200
- for (const proc of processes) {
201
- const sessionId = this.extractResumeSessionId(proc.command);
202
- if (!sessionId || !proc.cwd) {
203
- fallback.push(proc);
204
- continue;
205
- }
206
-
207
- const projectDir = this.getProjectDir(proc.cwd);
208
- const jsonlPath = path.join(projectDir, `${sessionId}.jsonl`);
209
-
210
- const stat = safeStat(jsonlPath);
211
- if (!stat) {
212
- fallback.push(proc);
213
- continue;
214
- }
215
-
216
- // Best-effort: the PID file (if present for this proc) is the
217
- // authoritative source of live status. We still match the session
218
- // via --resume, but we read the PID file alongside to capture
219
- // status/waitingFor.
220
- const pidEntry = this.readMatchingPidFile(proc.pid, proc.startTime);
221
-
222
- direct.push({
223
- process: proc,
224
- sessionFile: {
225
- sessionId,
226
- filePath: jsonlPath,
227
- projectDir,
228
- birthtimeMs: stat.birthtimeMs,
229
- resolvedCwd: proc.cwd,
230
- },
231
- pidStatus: this.mapPidStatus(pidEntry?.status),
232
- waitingFor: pidEntry?.waitingFor,
233
- });
236
+ return { direct, fallback };
237
+ }
238
+
239
+ private extractResumeSessionId(command: string): string | null {
240
+ const match = command.match(/--resume\s+([0-9a-f-]{36})/i);
241
+ return match?.[1] ?? null;
242
+ }
243
+
244
+ /**
245
+ * Read and parse ~/.claude/sessions/<pid>.json, returning null on any
246
+ * I/O / parse failure or when the file is stale relative to the live
247
+ * process.
248
+ *
249
+ * "Stale" means the PID file's startedAt diverges from the process's
250
+ * start time by more than {@link PID_FILE_STALENESS_MS} — typically
251
+ * a previous Claude Code process recycled the same PID without cleanup.
252
+ */
253
+ private readMatchingPidFile(pid: number, procStartTime?: Date): PidFileEntry | null {
254
+ const pidFilePath = path.join(this.sessionsDir, `${pid}.json`);
255
+ try {
256
+ const entry = JSON.parse(fs.readFileSync(pidFilePath, "utf-8")) as PidFileEntry;
257
+
258
+ if (procStartTime) {
259
+ const deltaMs = Math.abs(procStartTime.getTime() - entry.startedAt);
260
+ if (deltaMs > PID_FILE_STALENESS_MS) {
261
+ return null;
234
262
  }
263
+ }
235
264
 
236
- return { direct, fallback };
265
+ return entry;
266
+ } catch {
267
+ return null;
237
268
  }
238
-
239
- private extractResumeSessionId(command: string): string | null {
240
- const match = command.match(/--resume\s+([0-9a-f-]{36})/i);
241
- return match?.[1] ?? null;
269
+ }
270
+
271
+ /**
272
+ * Map the PID file's live status string to {@link AgentStatus}.
273
+ *
274
+ * Returns undefined for missing / unrecognized values so the caller
275
+ * can fall back to JSONL-derived heuristics.
276
+ */
277
+ private mapPidStatus(status: string | undefined): AgentStatus | undefined {
278
+ switch (status) {
279
+ case "running":
280
+ return AgentStatus.RUNNING;
281
+ case "waiting":
282
+ return AgentStatus.WAITING;
283
+ case "idle":
284
+ return AgentStatus.IDLE;
285
+ default:
286
+ return undefined;
242
287
  }
243
-
244
- /**
245
- * Read and parse ~/.claude/sessions/<pid>.json, returning null on any
246
- * I/O / parse failure or when the file is stale relative to the live
247
- * process.
248
- *
249
- * "Stale" means the PID file's startedAt diverges from the process's
250
- * start time by more than {@link PID_FILE_STALENESS_MS} typically
251
- * a previous Claude Code process recycled the same PID without cleanup.
252
- */
253
- private readMatchingPidFile(pid: number, procStartTime?: Date): PidFileEntry | null {
254
- const pidFilePath = path.join(this.sessionsDir, `${pid}.json`);
255
- try {
256
- const entry = JSON.parse(
257
- fs.readFileSync(pidFilePath, 'utf-8'),
258
- ) as PidFileEntry;
259
-
260
- if (procStartTime) {
261
- const deltaMs = Math.abs(procStartTime.getTime() - entry.startedAt);
262
- if (deltaMs > PID_FILE_STALENESS_MS) {
263
- return null;
264
- }
265
- }
266
-
267
- return entry;
268
- } catch {
269
- return null;
270
- }
271
- }
272
-
273
- /**
274
- * Map the PID file's live status string to {@link AgentStatus}.
275
- *
276
- * Returns undefined for missing / unrecognized values so the caller
277
- * can fall back to JSONL-derived heuristics.
278
- */
279
- private mapPidStatus(status: string | undefined): AgentStatus | undefined {
280
- switch (status) {
281
- case 'running':
282
- return AgentStatus.RUNNING;
283
- case 'waiting':
284
- return AgentStatus.WAITING;
285
- case 'idle':
286
- return AgentStatus.IDLE;
287
- default:
288
- return undefined;
289
- }
288
+ }
289
+
290
+ /**
291
+ * Attempt to match each process to its session via ~/.claude/sessions/<pid>.json.
292
+ *
293
+ * Returns:
294
+ * direct — processes matched authoritatively via PID file
295
+ * fallback processes with no valid PID file (sent to legacy matching)
296
+ *
297
+ * Per-process fallback triggers on: file absent, malformed JSON,
298
+ * stale startedAt (>60s from proc.startTime), or missing JSONL.
299
+ */
300
+ private tryPidFileMatching(processes: ProcessInfo[]): {
301
+ direct: ClaudeDirectMatch[];
302
+ fallback: ProcessInfo[];
303
+ } {
304
+ const direct: ClaudeDirectMatch[] = [];
305
+ const fallback: ProcessInfo[] = [];
306
+
307
+ for (const proc of processes) {
308
+ const entry = this.readMatchingPidFile(proc.pid, proc.startTime);
309
+ if (!entry) {
310
+ fallback.push(proc);
311
+ continue;
312
+ }
313
+
314
+ const projectDir = this.getProjectDir(entry.cwd);
315
+ const jsonlPath = path.join(projectDir, `${entry.sessionId}.jsonl`);
316
+
317
+ if (!fs.existsSync(jsonlPath)) {
318
+ fallback.push(proc);
319
+ continue;
320
+ }
321
+
322
+ direct.push({
323
+ process: proc,
324
+ sessionFile: {
325
+ sessionId: entry.sessionId,
326
+ filePath: jsonlPath,
327
+ projectDir,
328
+ birthtimeMs: entry.startedAt,
329
+ resolvedCwd: entry.cwd,
330
+ },
331
+ pidStatus: this.mapPidStatus(entry.status),
332
+ waitingFor: entry.waitingFor,
333
+ });
290
334
  }
291
335
 
292
- /**
293
- * Attempt to match each process to its session via ~/.claude/sessions/<pid>.json.
294
- *
295
- * Returns:
296
- * direct — processes matched authoritatively via PID file
297
- * fallback — processes with no valid PID file (sent to legacy matching)
298
- *
299
- * Per-process fallback triggers on: file absent, malformed JSON,
300
- * stale startedAt (>60s from proc.startTime), or missing JSONL.
301
- */
302
- private tryPidFileMatching(processes: ProcessInfo[]): {
303
- direct: ClaudeDirectMatch[];
304
- fallback: ProcessInfo[];
305
- } {
306
- const direct: ClaudeDirectMatch[] = [];
307
- const fallback: ProcessInfo[] = [];
308
-
309
- for (const proc of processes) {
310
- const entry = this.readMatchingPidFile(proc.pid, proc.startTime);
311
- if (!entry) {
312
- fallback.push(proc);
313
- continue;
314
- }
315
-
316
- const projectDir = this.getProjectDir(entry.cwd);
317
- const jsonlPath = path.join(projectDir, `${entry.sessionId}.jsonl`);
318
-
319
- if (!fs.existsSync(jsonlPath)) {
320
- fallback.push(proc);
321
- continue;
322
- }
323
-
324
- direct.push({
325
- process: proc,
326
- sessionFile: {
327
- sessionId: entry.sessionId,
328
- filePath: jsonlPath,
329
- projectDir,
330
- birthtimeMs: entry.startedAt,
331
- resolvedCwd: entry.cwd,
332
- },
333
- pidStatus: this.mapPidStatus(entry.status),
334
- waitingFor: entry.waitingFor,
335
- });
336
- }
337
-
338
- return { direct, fallback };
339
- }
336
+ return { direct, fallback };
337
+ }
340
338
  }