@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,20 +1,20 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import type { ConversationMessage } from '../../adapters/AgentAdapter.js';
4
- import { AgentStatus } from '../../adapters/AgentAdapter.js';
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import type { ConversationMessage } from "../../adapters/AgentAdapter.js";
4
+ import { AgentStatus } from "../../adapters/AgentAdapter.js";
5
5
 
6
6
  /**
7
7
  * Content block within a Claude Code JSONL message entry.
8
8
  * Handles text, tool_use, and tool_result block types.
9
9
  */
10
10
  export interface ContentBlock {
11
- type?: string;
12
- text?: string;
13
- content?: string;
14
- name?: string;
15
- input?: Record<string, unknown>;
16
- tool_use_id?: string;
17
- is_error?: boolean;
11
+ type?: string;
12
+ text?: string;
13
+ content?: string;
14
+ name?: string;
15
+ input?: Record<string, unknown>;
16
+ tool_use_id?: string;
17
+ is_error?: boolean;
18
18
  }
19
19
 
20
20
  /**
@@ -26,12 +26,12 @@ export interface ContentBlock {
26
26
  * - "last-prompt" / "file-history-snapshot" — metadata (not conversation state)
27
27
  */
28
28
  export interface SessionEntry {
29
- type?: string;
30
- timestamp?: string;
31
- cwd?: string;
32
- message?: {
33
- content?: string | ContentBlock[];
34
- };
29
+ type?: string;
30
+ timestamp?: string;
31
+ cwd?: string;
32
+ message?: {
33
+ content?: string | ContentBlock[];
34
+ };
35
35
  }
36
36
 
37
37
  /**
@@ -39,16 +39,16 @@ export interface SessionEntry {
39
39
  * Aggregates data from all entries into a single summary.
40
40
  */
41
41
  export interface ClaudeSession {
42
- sessionId: string;
43
- projectPath: string;
44
- lastCwd?: string;
45
- sessionStart: Date;
46
- lastActive: Date;
47
- lastEntryType?: string;
48
- isInterrupted: boolean;
49
- lastUserMessage?: string;
50
- /** First meaningful user prompt in the session (post noise filter) */
51
- firstUserMessage?: string;
42
+ sessionId: string;
43
+ projectPath: string;
44
+ lastCwd?: string;
45
+ sessionStart: Date;
46
+ lastActive: Date;
47
+ lastEntryType?: string;
48
+ isInterrupted: boolean;
49
+ lastUserMessage?: string;
50
+ /** First meaningful user prompt in the session (post noise filter) */
51
+ firstUserMessage?: string;
52
52
  }
53
53
 
54
54
  /**
@@ -61,13 +61,7 @@ export interface ClaudeSession {
61
61
  * last conversation turn — otherwise polling between writes lands on a
62
62
  * UI-state entry and `determineStatus` falls through to UNKNOWN.
63
63
  */
64
- const CONVERSATION_ENTRY_TYPES = new Set([
65
- 'user',
66
- 'assistant',
67
- 'system',
68
- 'progress',
69
- 'thinking',
70
- ]);
64
+ const CONVERSATION_ENTRY_TYPES = new Set(["user", "assistant", "system", "progress", "thinking"]);
71
65
 
72
66
  /**
73
67
  * Parses Claude Code session JSONL files into structured data.
@@ -77,314 +71,307 @@ const CONVERSATION_ENTRY_TYPES = new Set([
77
71
  * event (user turn, assistant response, tool call, etc.).
78
72
  */
79
73
  export class ClaudeSessionParser {
80
- /**
81
- * Parse a session JSONL file into a ClaudeSession summary.
82
- *
83
- * Iterates all lines to extract: session start time (from first entry),
84
- * last activity timestamp, last entry type (for status), whether the
85
- * session was interrupted, and the last meaningful user message.
86
- *
87
- * Returns null if the file is unreadable or empty.
88
- */
89
- readSession(filePath: string, projectPath: string): ClaudeSession | null {
90
- const sessionId = path.basename(filePath, '.jsonl');
91
-
92
- let content: string;
93
- try {
94
- content = fs.readFileSync(filePath, 'utf-8');
95
- } catch {
96
- return null;
97
- }
98
-
99
- const allLines = content.trim().split('\n');
100
- if (allLines.length === 0) {
101
- return null;
102
- }
103
-
104
- const sessionStart = this.parseSessionStart(allLines[0]);
105
-
106
- let lastEntryType: string | undefined;
107
- let lastActive: Date | undefined;
108
- let lastCwd: string | undefined;
109
- let isInterrupted = false;
110
- let lastUserMessage: string | undefined;
111
- let firstUserMessage: string | undefined;
112
-
113
- for (const line of allLines) {
114
- try {
115
- const entry: SessionEntry = JSON.parse(line);
116
-
117
- if (entry.timestamp) {
118
- const ts = new Date(entry.timestamp);
119
- if (!Number.isNaN(ts.getTime())) {
120
- lastActive = ts;
121
- }
122
- }
123
-
124
- if (typeof entry.cwd === 'string' && entry.cwd.trim().length > 0) {
125
- lastCwd = entry.cwd;
126
- }
127
-
128
- if (entry.type && CONVERSATION_ENTRY_TYPES.has(entry.type)) {
129
- lastEntryType = entry.type;
130
-
131
- if (entry.type === 'user') {
132
- const msgContent = entry.message?.content;
133
- isInterrupted =
134
- Array.isArray(msgContent) &&
135
- msgContent.some(
136
- (c) =>
137
- (c.type === 'text' &&
138
- c.text?.includes('[Request interrupted')) ||
139
- (c.type === 'tool_result' &&
140
- c.content?.includes('[Request interrupted')),
141
- );
142
-
143
- const text = this.extractUserMessageText(msgContent);
144
- if (text) {
145
- lastUserMessage = text;
146
- if (!firstUserMessage) {
147
- firstUserMessage = text;
148
- }
149
- }
150
- } else {
151
- isInterrupted = false;
152
- }
153
- }
154
- } catch {
155
- continue;
156
- }
157
- }
74
+ /**
75
+ * Parse a session JSONL file into a ClaudeSession summary.
76
+ *
77
+ * Iterates all lines to extract: session start time (from first entry),
78
+ * last activity timestamp, last entry type (for status), whether the
79
+ * session was interrupted, and the last meaningful user message.
80
+ *
81
+ * Returns null if the file is unreadable or empty.
82
+ */
83
+ readSession(filePath: string, projectPath: string): ClaudeSession | null {
84
+ const sessionId = path.basename(filePath, ".jsonl");
85
+
86
+ let content: string;
87
+ try {
88
+ content = fs.readFileSync(filePath, "utf-8");
89
+ } catch {
90
+ return null;
91
+ }
158
92
 
159
- return {
160
- sessionId,
161
- projectPath: projectPath || lastCwd || '',
162
- lastCwd,
163
- sessionStart: sessionStart || lastActive || new Date(),
164
- lastActive: lastActive || new Date(),
165
- lastEntryType,
166
- isInterrupted,
167
- lastUserMessage,
168
- firstUserMessage,
169
- };
93
+ const allLines = content.trim().split("\n");
94
+ if (allLines.length === 0) {
95
+ return null;
170
96
  }
171
97
 
172
- /**
173
- * Determine agent status from parsed session state.
174
- *
175
- * Status mapping:
176
- * - "user" + interrupted → WAITING (agent finished, awaiting new input)
177
- * - "user" + not interrupted → RUNNING (agent is processing)
178
- * - "progress" / "thinking" → RUNNING
179
- * - "assistant" → WAITING (agent responded, awaiting user)
180
- * - "system" → IDLE
181
- */
182
- determineStatus(session: ClaudeSession): AgentStatus {
183
- if (!session.lastEntryType) {
184
- return AgentStatus.UNKNOWN;
185
- }
98
+ const sessionStart = this.parseSessionStart(allLines[0]);
186
99
 
187
- if (session.lastEntryType === 'user') {
188
- return session.isInterrupted
189
- ? AgentStatus.WAITING
190
- : AgentStatus.RUNNING;
191
- }
100
+ let lastEntryType: string | undefined;
101
+ let lastActive: Date | undefined;
102
+ let lastCwd: string | undefined;
103
+ let isInterrupted = false;
104
+ let lastUserMessage: string | undefined;
105
+ let firstUserMessage: string | undefined;
192
106
 
193
- if (
194
- session.lastEntryType === 'progress' ||
195
- session.lastEntryType === 'thinking'
196
- ) {
197
- return AgentStatus.RUNNING;
198
- }
107
+ for (const line of allLines) {
108
+ try {
109
+ const entry: SessionEntry = JSON.parse(line);
199
110
 
200
- if (session.lastEntryType === 'assistant') {
201
- return AgentStatus.WAITING;
111
+ if (entry.timestamp) {
112
+ const ts = new Date(entry.timestamp);
113
+ if (!Number.isNaN(ts.getTime())) {
114
+ lastActive = ts;
115
+ }
202
116
  }
203
117
 
204
- if (session.lastEntryType === 'system') {
205
- return AgentStatus.IDLE;
118
+ if (typeof entry.cwd === "string" && entry.cwd.trim().length > 0) {
119
+ lastCwd = entry.cwd;
206
120
  }
207
121
 
208
- return AgentStatus.UNKNOWN;
209
- }
210
-
211
- /**
212
- * Read the full conversation from a session JSONL file.
213
- *
214
- * Default mode returns only text content from user/assistant/system messages.
215
- * Verbose mode also includes tool_use and tool_result blocks.
216
- */
217
- getConversation(sessionFilePath: string, options?: { verbose?: boolean }): ConversationMessage[] {
218
- const verbose = options?.verbose ?? false;
219
-
220
- let content: string;
221
- try {
222
- content = fs.readFileSync(sessionFilePath, 'utf-8');
223
- } catch {
224
- return [];
225
- }
226
-
227
- const lines = content.trim().split('\n');
228
- const messages: ConversationMessage[] = [];
229
-
230
- for (const line of lines) {
231
- let entry: SessionEntry;
232
- try {
233
- entry = JSON.parse(line);
234
- } catch {
235
- continue;
236
- }
237
-
238
- let role: ConversationMessage['role'];
239
- if (entry.type === 'user') {
240
- role = 'user';
241
- } else if (entry.type === 'assistant') {
242
- role = 'assistant';
243
- } else if (entry.type === 'system') {
244
- role = 'system';
245
- } else {
246
- continue;
122
+ if (entry.type && CONVERSATION_ENTRY_TYPES.has(entry.type)) {
123
+ lastEntryType = entry.type;
124
+
125
+ if (entry.type === "user") {
126
+ const msgContent = entry.message?.content;
127
+ isInterrupted =
128
+ Array.isArray(msgContent) &&
129
+ msgContent.some(
130
+ (c) =>
131
+ (c.type === "text" && c.text?.includes("[Request interrupted")) ||
132
+ (c.type === "tool_result" && c.content?.includes("[Request interrupted")),
133
+ );
134
+
135
+ const text = this.extractUserMessageText(msgContent);
136
+ if (text) {
137
+ lastUserMessage = text;
138
+ if (!firstUserMessage) {
139
+ firstUserMessage = text;
140
+ }
247
141
  }
142
+ } else {
143
+ isInterrupted = false;
144
+ }
145
+ }
146
+ } catch {
147
+ continue;
148
+ }
149
+ }
248
150
 
249
- const text = this.extractConversationContent(entry.message?.content, role, verbose);
250
- if (!text) continue;
151
+ return {
152
+ sessionId,
153
+ projectPath: projectPath || lastCwd || "",
154
+ lastCwd,
155
+ sessionStart: sessionStart || lastActive || new Date(),
156
+ lastActive: lastActive || new Date(),
157
+ lastEntryType,
158
+ isInterrupted,
159
+ lastUserMessage,
160
+ firstUserMessage,
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Determine agent status from parsed session state.
166
+ *
167
+ * Status mapping:
168
+ * - "user" + interrupted → WAITING (agent finished, awaiting new input)
169
+ * - "user" + not interrupted → RUNNING (agent is processing)
170
+ * - "progress" / "thinking" → RUNNING
171
+ * - "assistant" → WAITING (agent responded, awaiting user)
172
+ * - "system" → IDLE
173
+ */
174
+ determineStatus(session: ClaudeSession): AgentStatus {
175
+ if (!session.lastEntryType) {
176
+ return AgentStatus.UNKNOWN;
177
+ }
251
178
 
252
- messages.push({
253
- role,
254
- content: text,
255
- timestamp: entry.timestamp,
256
- });
257
- }
179
+ if (session.lastEntryType === "user") {
180
+ return session.isInterrupted ? AgentStatus.WAITING : AgentStatus.RUNNING;
181
+ }
258
182
 
259
- return messages;
183
+ if (session.lastEntryType === "progress" || session.lastEntryType === "thinking") {
184
+ return AgentStatus.RUNNING;
260
185
  }
261
186
 
262
- /**
263
- * Parse session start time from the first JSONL line.
264
- *
265
- * Claude Code may emit a "file-history-snapshot" as the first entry,
266
- * which stores its timestamp inside "snapshot.timestamp" rather than
267
- * at the root level.
268
- */
269
- private parseSessionStart(firstLine: string): Date | null {
270
- try {
271
- const firstEntry = JSON.parse(firstLine);
272
- const rawTs: string | undefined =
273
- firstEntry.timestamp || firstEntry.snapshot?.timestamp;
274
- if (rawTs) {
275
- const ts = new Date(rawTs);
276
- if (!Number.isNaN(ts.getTime())) {
277
- return ts;
278
- }
279
- }
280
- } catch {
281
- /* malformed first line */
282
- }
283
- return null;
187
+ if (session.lastEntryType === "assistant") {
188
+ return AgentStatus.WAITING;
284
189
  }
285
190
 
286
- /**
287
- * Extract meaningful text from a user message content field.
288
- *
289
- * Handles multiple formats:
290
- * - Plain string content
291
- * - Array of content blocks (extracts first text block)
292
- * - Skill slash-commands (<command-message> tags)
293
- * - Expanded skill content (extracts ARGUMENTS line)
294
- * - Filters noise messages (interruptions, tool loaded, session continued)
295
- */
296
- private extractUserMessageText(
297
- content: string | Array<{ type?: string; text?: string }> | undefined,
298
- ): string | undefined {
299
- if (!content) {
300
- return undefined;
301
- }
191
+ if (session.lastEntryType === "system") {
192
+ return AgentStatus.IDLE;
193
+ }
302
194
 
303
- let raw: string | undefined;
195
+ return AgentStatus.UNKNOWN;
196
+ }
197
+
198
+ /**
199
+ * Read the full conversation from a session JSONL file.
200
+ *
201
+ * Default mode returns only text content from user/assistant/system messages.
202
+ * Verbose mode also includes tool_use and tool_result blocks.
203
+ */
204
+ getConversation(sessionFilePath: string, options?: { verbose?: boolean }): ConversationMessage[] {
205
+ const verbose = options?.verbose ?? false;
206
+
207
+ let content: string;
208
+ try {
209
+ content = fs.readFileSync(sessionFilePath, "utf-8");
210
+ } catch {
211
+ return [];
212
+ }
304
213
 
305
- if (typeof content === 'string') {
306
- raw = content.trim();
307
- } else if (Array.isArray(content)) {
308
- for (const block of content) {
309
- if (block.type === 'text' && block.text?.trim()) {
310
- raw = block.text.trim();
311
- break;
312
- }
313
- }
314
- }
214
+ const lines = content.trim().split("\n");
215
+ const messages: ConversationMessage[] = [];
216
+
217
+ for (const line of lines) {
218
+ let entry: SessionEntry;
219
+ try {
220
+ entry = JSON.parse(line);
221
+ } catch {
222
+ continue;
223
+ }
224
+
225
+ let role: ConversationMessage["role"];
226
+ if (entry.type === "user") {
227
+ role = "user";
228
+ } else if (entry.type === "assistant") {
229
+ role = "assistant";
230
+ } else if (entry.type === "system") {
231
+ role = "system";
232
+ } else {
233
+ continue;
234
+ }
235
+
236
+ const text = this.extractConversationContent(entry.message?.content, role, verbose);
237
+ if (!text) continue;
238
+
239
+ messages.push({
240
+ role,
241
+ content: text,
242
+ timestamp: entry.timestamp,
243
+ });
244
+ }
315
245
 
316
- if (!raw) {
317
- return undefined;
246
+ return messages;
247
+ }
248
+
249
+ /**
250
+ * Parse session start time from the first JSONL line.
251
+ *
252
+ * Claude Code may emit a "file-history-snapshot" as the first entry,
253
+ * which stores its timestamp inside "snapshot.timestamp" rather than
254
+ * at the root level.
255
+ */
256
+ private parseSessionStart(firstLine: string): Date | null {
257
+ try {
258
+ const firstEntry = JSON.parse(firstLine);
259
+ const rawTs: string | undefined = firstEntry.timestamp || firstEntry.snapshot?.timestamp;
260
+ if (rawTs) {
261
+ const ts = new Date(rawTs);
262
+ if (!Number.isNaN(ts.getTime())) {
263
+ return ts;
318
264
  }
265
+ }
266
+ } catch {
267
+ /* malformed first line */
268
+ }
269
+ return null;
270
+ }
271
+
272
+ /**
273
+ * Extract meaningful text from a user message content field.
274
+ *
275
+ * Handles multiple formats:
276
+ * - Plain string content
277
+ * - Array of content blocks (extracts first text block)
278
+ * - Skill slash-commands (<command-message> tags)
279
+ * - Expanded skill content (extracts ARGUMENTS line)
280
+ * - Filters noise messages (interruptions, tool loaded, session continued)
281
+ */
282
+ private extractUserMessageText(
283
+ content: string | Array<{ type?: string; text?: string }> | undefined,
284
+ ): string | undefined {
285
+ if (!content) {
286
+ return undefined;
287
+ }
319
288
 
320
- if (raw.startsWith('<command-message>')) {
321
- return this.parseCommandMessage(raw);
322
- }
289
+ let raw: string | undefined;
323
290
 
324
- if (raw.startsWith('Base directory for this skill:')) {
325
- const argsMatch = raw.match(/\nARGUMENTS:\s*(.+)/);
326
- return argsMatch?.[1]?.trim() || undefined;
291
+ if (typeof content === "string") {
292
+ raw = content.trim();
293
+ } else if (Array.isArray(content)) {
294
+ for (const block of content) {
295
+ if (block.type === "text" && block.text?.trim()) {
296
+ raw = block.text.trim();
297
+ break;
327
298
  }
299
+ }
300
+ }
328
301
 
329
- if (isNoiseMessage(raw)) {
330
- return undefined;
331
- }
302
+ if (!raw) {
303
+ return undefined;
304
+ }
332
305
 
333
- return raw;
306
+ if (raw.startsWith("<command-message>")) {
307
+ return this.parseCommandMessage(raw);
334
308
  }
335
309
 
336
- /**
337
- * Parse a <command-message> string into "/command args" format.
338
- */
339
- private parseCommandMessage(raw: string): string | undefined {
340
- const nameMatch = raw.match(/<command-name>([^<]+)<\/command-name>/);
341
- const argsMatch = raw.match(/<command-args>([^<]+)<\/command-args>/);
342
- const name = nameMatch?.[1]?.trim();
343
- if (!name) {
344
- return undefined;
345
- }
346
- const args = argsMatch?.[1]?.trim();
347
- return args ? `${name} ${args}` : name;
310
+ if (raw.startsWith("Base directory for this skill:")) {
311
+ const argsMatch = raw.match(/\nARGUMENTS:\s*(.+)/);
312
+ return argsMatch?.[1]?.trim() || undefined;
348
313
  }
349
314
 
350
- /**
351
- * Extract displayable content from a message content field for conversation output.
352
- */
353
- private extractConversationContent(
354
- content: string | ContentBlock[] | undefined,
355
- role: ConversationMessage['role'],
356
- verbose: boolean,
357
- ): string | undefined {
358
- if (!content) return undefined;
359
-
360
- if (typeof content === 'string') {
361
- const cleaned = stripHarnessTags(content);
362
- if (role === 'user' && isNoiseMessage(cleaned)) return undefined;
363
- return cleaned || undefined;
364
- }
315
+ if (isNoiseMessage(raw)) {
316
+ return undefined;
317
+ }
365
318
 
366
- if (!Array.isArray(content)) return undefined;
367
-
368
- const parts: string[] = [];
369
-
370
- for (const block of content) {
371
- if (block.type === 'text' && block.text?.trim()) {
372
- const cleaned = stripHarnessTags(block.text);
373
- if (!cleaned) continue;
374
- if (role === 'user' && isNoiseMessage(cleaned)) continue;
375
- parts.push(cleaned);
376
- } else if (block.type === 'tool_use' && verbose) {
377
- const inputSummary = block.input?.file_path || block.input?.pattern || block.input?.command || '';
378
- parts.push(`[Tool: ${block.name}]${inputSummary ? ' ' + inputSummary : ''}`);
379
- } else if (block.type === 'tool_result' && verbose) {
380
- const truncated = truncateToolResult(block.content || '');
381
- const prefix = block.is_error ? '[Tool Error]' : '[Tool Result]';
382
- parts.push(`${prefix} ${truncated}`);
383
- }
384
- }
319
+ return raw;
320
+ }
321
+
322
+ /**
323
+ * Parse a <command-message> string into "/command args" format.
324
+ */
325
+ private parseCommandMessage(raw: string): string | undefined {
326
+ const nameMatch = raw.match(/<command-name>([^<]+)<\/command-name>/);
327
+ const argsMatch = raw.match(/<command-args>([^<]+)<\/command-args>/);
328
+ const name = nameMatch?.[1]?.trim();
329
+ if (!name) {
330
+ return undefined;
331
+ }
332
+ const args = argsMatch?.[1]?.trim();
333
+ return args ? `${name} ${args}` : name;
334
+ }
335
+
336
+ /**
337
+ * Extract displayable content from a message content field for conversation output.
338
+ */
339
+ private extractConversationContent(
340
+ content: string | ContentBlock[] | undefined,
341
+ role: ConversationMessage["role"],
342
+ verbose: boolean,
343
+ ): string | undefined {
344
+ if (!content) return undefined;
345
+
346
+ if (typeof content === "string") {
347
+ const cleaned = stripHarnessTags(content);
348
+ if (role === "user" && isNoiseMessage(cleaned)) return undefined;
349
+ return cleaned || undefined;
350
+ }
385
351
 
386
- return parts.length > 0 ? parts.join('\n') : undefined;
352
+ if (!Array.isArray(content)) return undefined;
353
+
354
+ const parts: string[] = [];
355
+
356
+ for (const block of content) {
357
+ if (block.type === "text" && block.text?.trim()) {
358
+ const cleaned = stripHarnessTags(block.text);
359
+ if (!cleaned) continue;
360
+ if (role === "user" && isNoiseMessage(cleaned)) continue;
361
+ parts.push(cleaned);
362
+ } else if (block.type === "tool_use" && verbose) {
363
+ const inputSummary =
364
+ block.input?.file_path || block.input?.pattern || block.input?.command || "";
365
+ parts.push(`[Tool: ${block.name}]${inputSummary ? " " + inputSummary : ""}`);
366
+ } else if (block.type === "tool_result" && verbose) {
367
+ const truncated = truncateToolResult(block.content || "");
368
+ const prefix = block.is_error ? "[Tool Error]" : "[Tool Result]";
369
+ parts.push(`${prefix} ${truncated}`);
370
+ }
387
371
  }
372
+
373
+ return parts.length > 0 ? parts.join("\n") : undefined;
374
+ }
388
375
  }
389
376
 
390
377
  /**
@@ -393,25 +380,22 @@ export class ClaudeSessionParser {
393
380
  * stdout), not meaningful conversation content.
394
381
  */
395
382
  const HARNESS_DROP_TAGS = [
396
- 'system-reminder',
397
- 'local-command-stdout',
398
- 'local-command-stderr',
399
- 'user-prompt-submit-hook',
400
- 'command-stdout',
401
- 'command-stderr',
402
- 'bash-input',
403
- 'bash-stdout',
404
- 'bash-stderr',
405
- 'command-message',
383
+ "system-reminder",
384
+ "local-command-stdout",
385
+ "local-command-stderr",
386
+ "user-prompt-submit-hook",
387
+ "command-stdout",
388
+ "command-stderr",
389
+ "bash-input",
390
+ "bash-stdout",
391
+ "bash-stderr",
392
+ "command-message",
406
393
  ] as const;
407
394
 
408
- const HARNESS_DROP_RE = new RegExp(
409
- `<(${HARNESS_DROP_TAGS.join('|')})>[\\s\\S]*?</\\1>`,
410
- 'g',
411
- );
395
+ const HARNESS_DROP_RE = new RegExp(`<(${HARNESS_DROP_TAGS.join("|")})>[\\s\\S]*?</\\1>`, "g");
412
396
 
413
397
  const COMMAND_INVOCATION_RE =
414
- /<command-name>([^<]+)<\/command-name>(?:\s*<command-args>([\s\S]*?)<\/command-args>)?/g;
398
+ /<command-name>([^<]+)<\/command-name>(?:\s*<command-args>([\s\S]*?)<\/command-args>)?/g;
415
399
 
416
400
  /**
417
401
  * Remove harness-injected XML blocks from message text and collapse
@@ -421,28 +405,28 @@ const COMMAND_INVOCATION_RE =
421
405
  * survives stripping.
422
406
  */
423
407
  function stripHarnessTags(text: string): string {
424
- let out = text.replace(HARNESS_DROP_RE, '');
408
+ let out = text.replace(HARNESS_DROP_RE, "");
425
409
 
426
- out = out.replace(COMMAND_INVOCATION_RE, (_match, rawName: string, rawArgs?: string) => {
427
- const name = rawName.trim();
428
- const args = rawArgs?.trim();
429
- return args ? `${name} ${args}` : name;
430
- });
410
+ out = out.replace(COMMAND_INVOCATION_RE, (_match, rawName: string, rawArgs?: string) => {
411
+ const name = rawName.trim();
412
+ const args = rawArgs?.trim();
413
+ return args ? `${name} ${args}` : name;
414
+ });
431
415
 
432
- return out.replace(/\n{3,}/g, '\n\n').trim();
416
+ return out.replace(/\n{3,}/g, "\n\n").trim();
433
417
  }
434
418
 
435
419
  /** Check if a message is noise (not a meaningful user intent). */
436
420
  function isNoiseMessage(text: string): boolean {
437
- return (
438
- text.startsWith('[Request interrupted') ||
439
- text === 'Tool loaded.' ||
440
- text.startsWith('This session is being continued')
441
- );
421
+ return (
422
+ text.startsWith("[Request interrupted") ||
423
+ text === "Tool loaded." ||
424
+ text.startsWith("This session is being continued")
425
+ );
442
426
  }
443
427
 
444
428
  function truncateToolResult(content: string, maxLength = 200): string {
445
- const firstLine = content.split('\n')[0] || '';
446
- if (firstLine.length <= maxLength) return firstLine;
447
- return firstLine.slice(0, maxLength - 3) + '...';
429
+ const firstLine = content.split("\n")[0] || "";
430
+ if (firstLine.length <= maxLength) return firstLine;
431
+ return firstLine.slice(0, maxLength - 3) + "...";
448
432
  }