@ai-devkit/agent-manager 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (519) hide show
  1. package/dist/AgentManager.d.ts +3 -3
  2. package/dist/AgentManager.d.ts.map +1 -1
  3. package/dist/AgentManager.js +80 -79
  4. package/dist/AgentManager.js.map +1 -1
  5. package/dist/__tests__/AgentManager.test.js +413 -388
  6. package/dist/__tests__/AgentManager.test.js.map +1 -1
  7. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js +642 -642
  8. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +1 -1
  9. package/dist/__tests__/adapters/CodexAdapter.test.js +322 -2321
  10. package/dist/__tests__/adapters/CodexAdapter.test.js.map +1 -1
  11. package/dist/__tests__/adapters/CopilotAdapter.test.js +254 -248
  12. package/dist/__tests__/adapters/CopilotAdapter.test.js.map +1 -1
  13. package/dist/__tests__/adapters/GeminiCliAdapter.test.js +564 -558
  14. package/dist/__tests__/adapters/GeminiCliAdapter.test.js.map +1 -1
  15. package/dist/__tests__/adapters/GrokCliAdapter.test.js +114 -114
  16. package/dist/__tests__/adapters/GrokCliAdapter.test.js.map +1 -1
  17. package/dist/__tests__/adapters/OpenCodeAdapter.test.js +169 -169
  18. package/dist/__tests__/adapters/OpenCodeAdapter.test.js.map +1 -1
  19. package/dist/__tests__/capacity/codex.test.js +93 -93
  20. package/dist/__tests__/capacity/codex.test.js.map +1 -1
  21. package/dist/__tests__/capacity/index.test.js +17 -17
  22. package/dist/__tests__/capacity/index.test.js.map +1 -1
  23. package/dist/__tests__/durable/CodexCliProbe.test.js +60 -60
  24. package/dist/__tests__/durable/CodexCliProbe.test.js.map +1 -1
  25. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js +28 -28
  26. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +1 -1
  27. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js +30 -30
  28. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +1 -1
  29. package/dist/__tests__/durable/CodexPrintAgentService.test.js +71 -71
  30. package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +1 -1
  31. package/dist/__tests__/durable/CodexPrintRunner.test.js +125 -125
  32. package/dist/__tests__/durable/CodexPrintRunner.test.js.map +1 -1
  33. package/dist/__tests__/print/ClaudeCliProbe.test.js +20 -20
  34. package/dist/__tests__/print/ClaudeCliProbe.test.js.map +1 -1
  35. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js +20 -20
  36. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +1 -1
  37. package/dist/__tests__/print/ClaudePrintAgentService.test.js +58 -58
  38. package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +1 -1
  39. package/dist/__tests__/print/ClaudePrintRunner.test.js +55 -55
  40. package/dist/__tests__/print/ClaudePrintRunner.test.js.map +1 -1
  41. package/dist/__tests__/print/DurableAgent.test.js +9 -9
  42. package/dist/__tests__/print/DurableAgent.test.js.map +1 -1
  43. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js +40 -40
  44. package/dist/__tests__/print/DurableAgentRepository.sqlite.test.js.map +1 -1
  45. package/dist/__tests__/print/DurableAgentRepository.test.js +66 -66
  46. package/dist/__tests__/print/DurableAgentRepository.test.js.map +1 -1
  47. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js +34 -34
  48. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +1 -1
  49. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js +132 -132
  50. package/dist/__tests__/providers/claude/ClaudeSessionLocator.test.js.map +1 -1
  51. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js +194 -0
  52. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js.map +1 -0
  53. package/dist/__tests__/providers/codex/CodexSessionMapping.test.js +86 -0
  54. package/dist/__tests__/providers/codex/CodexSessionMapping.test.js.map +1 -0
  55. package/dist/__tests__/providers/codex/CodexSessionParser.test.js +254 -0
  56. package/dist/__tests__/providers/codex/CodexSessionParser.test.js.map +1 -0
  57. package/dist/__tests__/providers/pi/PiAdapter.test.js +337 -0
  58. package/dist/__tests__/providers/pi/PiAdapter.test.js.map +1 -0
  59. package/dist/__tests__/providers/pi/PiSessionParser.test.js +246 -0
  60. package/dist/__tests__/providers/pi/PiSessionParser.test.js.map +1 -0
  61. package/dist/__tests__/providers/pi/PiSessionTracker.test.js +108 -0
  62. package/dist/__tests__/providers/pi/PiSessionTracker.test.js.map +1 -0
  63. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js +33 -33
  64. package/dist/__tests__/providers/pi/durable/PiCliProbe.test.js.map +1 -1
  65. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js +16 -16
  66. package/dist/__tests__/providers/pi/durable/PiDurableAgentRepository.test.js.map +1 -1
  67. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js +52 -52
  68. package/dist/__tests__/providers/pi/durable/PiPrintAgentService.test.js.map +1 -1
  69. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js +44 -44
  70. package/dist/__tests__/providers/pi/durable/PiPrintProtocol.test.js.map +1 -1
  71. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js +126 -126
  72. package/dist/__tests__/providers/pi/durable/PiPrintRunner.test.js.map +1 -1
  73. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js +14 -14
  74. package/dist/__tests__/providers/pi/durable/PiStreamParser.test.js.map +1 -1
  75. package/dist/__tests__/readiness/AgentReadiness.test.js +301 -0
  76. package/dist/__tests__/readiness/AgentReadiness.test.js.map +1 -0
  77. package/dist/__tests__/runtime/AgentRuntime.test.js +13 -0
  78. package/dist/__tests__/runtime/AgentRuntime.test.js.map +1 -0
  79. package/dist/__tests__/runtime/HerdrAgentRuntime.test.js +452 -0
  80. package/dist/__tests__/runtime/HerdrAgentRuntime.test.js.map +1 -0
  81. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js +588 -0
  82. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -0
  83. package/dist/__tests__/terminal/TerminalFocusManager.test.js +100 -100
  84. package/dist/__tests__/terminal/TerminalFocusManager.test.js.map +1 -1
  85. package/dist/__tests__/terminal/TmuxManager.test.js +101 -101
  86. package/dist/__tests__/terminal/TmuxManager.test.js.map +1 -1
  87. package/dist/__tests__/terminal/TtyWriter.test.js +185 -185
  88. package/dist/__tests__/terminal/TtyWriter.test.js.map +1 -1
  89. package/dist/__tests__/utils/AgentRegistry.test.js +335 -217
  90. package/dist/__tests__/utils/AgentRegistry.test.js.map +1 -1
  91. package/dist/__tests__/utils/ClaudeSessionParser.test.js +103 -101
  92. package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +1 -1
  93. package/dist/__tests__/utils/agent-requests.test.js +43 -43
  94. package/dist/__tests__/utils/agent-requests.test.js.map +1 -1
  95. package/dist/__tests__/utils/agents.test.js +17 -17
  96. package/dist/__tests__/utils/agents.test.js.map +1 -1
  97. package/dist/__tests__/utils/matching.test.js +92 -92
  98. package/dist/__tests__/utils/matching.test.js.map +1 -1
  99. package/dist/__tests__/utils/process.test.js +108 -108
  100. package/dist/__tests__/utils/process.test.js.map +1 -1
  101. package/dist/__tests__/utils/session.test.js +53 -53
  102. package/dist/__tests__/utils/session.test.js.map +1 -1
  103. package/dist/adapters/AgentAdapter.d.ts +2 -2
  104. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  105. package/dist/adapters/AgentAdapter.js +1 -1
  106. package/dist/adapters/AgentAdapter.js.map +1 -1
  107. package/dist/adapters/CopilotAdapter.d.ts +2 -2
  108. package/dist/adapters/CopilotAdapter.d.ts.map +1 -1
  109. package/dist/adapters/CopilotAdapter.js +51 -51
  110. package/dist/adapters/CopilotAdapter.js.map +1 -1
  111. package/dist/adapters/GeminiCliAdapter.d.ts +2 -2
  112. package/dist/adapters/GeminiCliAdapter.d.ts.map +1 -1
  113. package/dist/adapters/GeminiCliAdapter.js +86 -86
  114. package/dist/adapters/GeminiCliAdapter.js.map +1 -1
  115. package/dist/adapters/GrokCliAdapter.d.ts +1 -1
  116. package/dist/adapters/GrokCliAdapter.d.ts.map +1 -1
  117. package/dist/adapters/GrokCliAdapter.js +80 -80
  118. package/dist/adapters/GrokCliAdapter.js.map +1 -1
  119. package/dist/adapters/OpenCodeAdapter.d.ts +1 -1
  120. package/dist/adapters/OpenCodeAdapter.d.ts.map +1 -1
  121. package/dist/adapters/OpenCodeAdapter.js +37 -36
  122. package/dist/adapters/OpenCodeAdapter.js.map +1 -1
  123. package/dist/adapters/index.d.ts +9 -9
  124. package/dist/adapters/index.d.ts.map +1 -1
  125. package/dist/adapters/index.js +8 -8
  126. package/dist/adapters/index.js.map +1 -1
  127. package/dist/capacity/codex.d.ts +3 -3
  128. package/dist/capacity/codex.d.ts.map +1 -1
  129. package/dist/capacity/codex.js +57 -57
  130. package/dist/capacity/codex.js.map +1 -1
  131. package/dist/capacity/index.d.ts +3 -3
  132. package/dist/capacity/index.d.ts.map +1 -1
  133. package/dist/capacity/index.js +8 -8
  134. package/dist/capacity/index.js.map +1 -1
  135. package/dist/capacity/types.d.ts +1 -1
  136. package/dist/capacity/types.js.map +1 -1
  137. package/dist/database/connection.d.ts +1 -1
  138. package/dist/database/connection.d.ts.map +1 -1
  139. package/dist/database/connection.js +15 -15
  140. package/dist/database/connection.js.map +1 -1
  141. package/dist/database/index.d.ts +3 -3
  142. package/dist/database/index.d.ts.map +1 -1
  143. package/dist/database/index.js +2 -2
  144. package/dist/database/index.js.map +1 -1
  145. package/dist/database/migrations/005_agent_runtime.sql +2 -0
  146. package/dist/database/schema.d.ts +1 -1
  147. package/dist/database/schema.d.ts.map +1 -1
  148. package/dist/database/schema.js +7 -7
  149. package/dist/database/schema.js.map +1 -1
  150. package/dist/durable/DurableAgent.d.ts +9 -9
  151. package/dist/durable/DurableAgent.d.ts.map +1 -1
  152. package/dist/durable/DurableAgent.js +16 -16
  153. package/dist/durable/DurableAgent.js.map +1 -1
  154. package/dist/durable/DurableAgentRepository.d.ts +4 -4
  155. package/dist/durable/DurableAgentRepository.d.ts.map +1 -1
  156. package/dist/durable/DurableAgentRepository.js +49 -48
  157. package/dist/durable/DurableAgentRepository.js.map +1 -1
  158. package/dist/durable/process.d.ts +1 -1
  159. package/dist/durable/process.d.ts.map +1 -1
  160. package/dist/durable/process.js +14 -14
  161. package/dist/durable/process.js.map +1 -1
  162. package/dist/durable/run.d.ts +2 -2
  163. package/dist/durable/run.d.ts.map +1 -1
  164. package/dist/durable/run.js +6 -6
  165. package/dist/durable/run.js.map +1 -1
  166. package/dist/durable/utils.d.ts +1 -1
  167. package/dist/durable/utils.d.ts.map +1 -1
  168. package/dist/durable/utils.js +4 -4
  169. package/dist/durable/utils.js.map +1 -1
  170. package/dist/index.d.ts +46 -41
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +27 -25
  173. package/dist/index.js.map +1 -1
  174. package/dist/providers/claude/ClaudeAgentMapper.d.ts +4 -4
  175. package/dist/providers/claude/ClaudeAgentMapper.d.ts.map +1 -1
  176. package/dist/providers/claude/ClaudeAgentMapper.js +10 -10
  177. package/dist/providers/claude/ClaudeAgentMapper.js.map +1 -1
  178. package/dist/providers/claude/ClaudeCodeAdapter.d.ts +1 -1
  179. package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +1 -1
  180. package/dist/providers/claude/ClaudeCodeAdapter.js +14 -14
  181. package/dist/providers/claude/ClaudeCodeAdapter.js.map +1 -1
  182. package/dist/providers/claude/ClaudeSessionLocator.d.ts +4 -4
  183. package/dist/providers/claude/ClaudeSessionLocator.d.ts.map +1 -1
  184. package/dist/providers/claude/ClaudeSessionLocator.js +79 -79
  185. package/dist/providers/claude/ClaudeSessionLocator.js.map +1 -1
  186. package/dist/providers/claude/ClaudeSessionParser.d.ts +2 -2
  187. package/dist/providers/claude/ClaudeSessionParser.d.ts.map +1 -1
  188. package/dist/providers/claude/ClaudeSessionParser.js +99 -99
  189. package/dist/providers/claude/ClaudeSessionParser.js.map +1 -1
  190. package/dist/providers/claude/durable/ClaudeCliProbe.d.ts.map +1 -1
  191. package/dist/providers/claude/durable/ClaudeCliProbe.js +16 -16
  192. package/dist/providers/claude/durable/ClaudeCliProbe.js.map +1 -1
  193. package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts +5 -5
  194. package/dist/providers/claude/durable/ClaudePrintAgentService.d.ts.map +1 -1
  195. package/dist/providers/claude/durable/ClaudePrintAgentService.js +10 -10
  196. package/dist/providers/claude/durable/ClaudePrintAgentService.js.map +1 -1
  197. package/dist/providers/claude/durable/ClaudePrintRunner.d.ts +4 -4
  198. package/dist/providers/claude/durable/ClaudePrintRunner.d.ts.map +1 -1
  199. package/dist/providers/claude/durable/ClaudePrintRunner.js +18 -18
  200. package/dist/providers/claude/durable/ClaudePrintRunner.js.map +1 -1
  201. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts +2 -2
  202. package/dist/providers/claude/durable/ClaudeStreamParser.d.ts.map +1 -1
  203. package/dist/providers/claude/durable/ClaudeStreamParser.js +17 -17
  204. package/dist/providers/claude/durable/ClaudeStreamParser.js.map +1 -1
  205. package/dist/providers/codex/CodexAdapter.d.ts +27 -0
  206. package/dist/providers/codex/CodexAdapter.d.ts.map +1 -0
  207. package/dist/providers/codex/CodexAdapter.js +162 -0
  208. package/dist/providers/codex/CodexAdapter.js.map +1 -0
  209. package/dist/providers/codex/CodexAgentMapper.d.ts +9 -0
  210. package/dist/providers/codex/CodexAgentMapper.d.ts.map +1 -0
  211. package/dist/providers/codex/CodexAgentMapper.js +35 -0
  212. package/dist/providers/codex/CodexAgentMapper.js.map +1 -0
  213. package/dist/providers/codex/CodexSessionLocator.d.ts +44 -0
  214. package/dist/providers/codex/CodexSessionLocator.d.ts.map +1 -0
  215. package/dist/providers/codex/CodexSessionLocator.js +207 -0
  216. package/dist/providers/codex/CodexSessionLocator.js.map +1 -0
  217. package/dist/providers/codex/CodexSessionMapping.d.ts +23 -0
  218. package/dist/providers/codex/CodexSessionMapping.d.ts.map +1 -0
  219. package/dist/providers/codex/CodexSessionMapping.js +68 -0
  220. package/dist/providers/codex/CodexSessionMapping.js.map +1 -0
  221. package/dist/providers/codex/CodexSessionParser.d.ts +58 -0
  222. package/dist/providers/codex/CodexSessionParser.d.ts.map +1 -0
  223. package/dist/providers/codex/CodexSessionParser.js +262 -0
  224. package/dist/providers/codex/CodexSessionParser.js.map +1 -0
  225. package/dist/providers/codex/durable/CodexCliProbe.d.ts.map +1 -1
  226. package/dist/providers/codex/durable/CodexCliProbe.js +22 -22
  227. package/dist/providers/codex/durable/CodexCliProbe.js.map +1 -1
  228. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts +6 -6
  229. package/dist/providers/codex/durable/CodexPrintAgentService.d.ts.map +1 -1
  230. package/dist/providers/codex/durable/CodexPrintAgentService.js +10 -10
  231. package/dist/providers/codex/durable/CodexPrintAgentService.js.map +1 -1
  232. package/dist/providers/codex/durable/CodexPrintRunner.d.ts +4 -4
  233. package/dist/providers/codex/durable/CodexPrintRunner.d.ts.map +1 -1
  234. package/dist/providers/codex/durable/CodexPrintRunner.js +20 -20
  235. package/dist/providers/codex/durable/CodexPrintRunner.js.map +1 -1
  236. package/dist/providers/codex/durable/CodexStreamParser.d.ts +2 -2
  237. package/dist/providers/codex/durable/CodexStreamParser.d.ts.map +1 -1
  238. package/dist/providers/codex/durable/CodexStreamParser.js +21 -21
  239. package/dist/providers/codex/durable/CodexStreamParser.js.map +1 -1
  240. package/dist/providers/pi/PiAdapter.d.ts +28 -0
  241. package/dist/providers/pi/PiAdapter.d.ts.map +1 -0
  242. package/dist/providers/pi/PiAdapter.js +153 -0
  243. package/dist/providers/pi/PiAdapter.js.map +1 -0
  244. package/dist/providers/pi/PiAgentMapper.d.ts +9 -0
  245. package/dist/providers/pi/PiAgentMapper.d.ts.map +1 -0
  246. package/dist/providers/pi/PiAgentMapper.js +37 -0
  247. package/dist/providers/pi/PiAgentMapper.js.map +1 -0
  248. package/dist/providers/pi/PiSessionLocator.d.ts +23 -0
  249. package/dist/providers/pi/PiSessionLocator.d.ts.map +1 -0
  250. package/dist/providers/pi/PiSessionLocator.js +79 -0
  251. package/dist/providers/pi/PiSessionLocator.js.map +1 -0
  252. package/dist/providers/pi/PiSessionParser.d.ts +36 -0
  253. package/dist/providers/pi/PiSessionParser.d.ts.map +1 -0
  254. package/dist/providers/pi/PiSessionParser.js +191 -0
  255. package/dist/providers/pi/PiSessionParser.js.map +1 -0
  256. package/dist/providers/pi/PiSessionTracker.d.ts +23 -0
  257. package/dist/providers/pi/PiSessionTracker.d.ts.map +1 -0
  258. package/dist/providers/pi/PiSessionTracker.js +69 -0
  259. package/dist/providers/pi/PiSessionTracker.js.map +1 -0
  260. package/dist/providers/pi/durable/PiCliProbe.d.ts.map +1 -1
  261. package/dist/providers/pi/durable/PiCliProbe.js +15 -15
  262. package/dist/providers/pi/durable/PiCliProbe.js.map +1 -1
  263. package/dist/providers/pi/durable/PiPrintAgentService.d.ts +6 -6
  264. package/dist/providers/pi/durable/PiPrintAgentService.d.ts.map +1 -1
  265. package/dist/providers/pi/durable/PiPrintAgentService.js +10 -10
  266. package/dist/providers/pi/durable/PiPrintAgentService.js.map +1 -1
  267. package/dist/providers/pi/durable/PiPrintProtocol.d.ts.map +1 -1
  268. package/dist/providers/pi/durable/PiPrintProtocol.js +18 -18
  269. package/dist/providers/pi/durable/PiPrintProtocol.js.map +1 -1
  270. package/dist/providers/pi/durable/PiPrintRunner.d.ts +4 -4
  271. package/dist/providers/pi/durable/PiPrintRunner.d.ts.map +1 -1
  272. package/dist/providers/pi/durable/PiPrintRunner.js +15 -15
  273. package/dist/providers/pi/durable/PiPrintRunner.js.map +1 -1
  274. package/dist/providers/pi/durable/PiStreamParser.d.ts +1 -1
  275. package/dist/providers/pi/durable/PiStreamParser.d.ts.map +1 -1
  276. package/dist/providers/pi/durable/PiStreamParser.js +16 -16
  277. package/dist/providers/pi/durable/PiStreamParser.js.map +1 -1
  278. package/dist/readiness/AgentReadiness.d.ts +67 -0
  279. package/dist/readiness/AgentReadiness.d.ts.map +1 -0
  280. package/dist/readiness/AgentReadiness.js +614 -0
  281. package/dist/readiness/AgentReadiness.js.map +1 -0
  282. package/dist/runtime/ManagedAgentRuntime.d.ts +69 -0
  283. package/dist/runtime/ManagedAgentRuntime.d.ts.map +1 -0
  284. package/dist/runtime/ManagedAgentRuntime.js +156 -0
  285. package/dist/runtime/ManagedAgentRuntime.js.map +1 -0
  286. package/dist/runtime/RuntimeFactory.d.ts +4 -0
  287. package/dist/runtime/RuntimeFactory.d.ts.map +1 -0
  288. package/dist/runtime/RuntimeFactory.js +11 -0
  289. package/dist/runtime/RuntimeFactory.js.map +1 -0
  290. package/dist/runtime/errors.d.ts +27 -0
  291. package/dist/runtime/errors.d.ts.map +1 -0
  292. package/dist/runtime/errors.js +42 -0
  293. package/dist/runtime/errors.js.map +1 -0
  294. package/dist/runtime/herdr/HerdrAgentRuntime.d.ts +31 -0
  295. package/dist/runtime/herdr/HerdrAgentRuntime.d.ts.map +1 -0
  296. package/dist/runtime/herdr/HerdrAgentRuntime.js +184 -0
  297. package/dist/runtime/herdr/HerdrAgentRuntime.js.map +1 -0
  298. package/dist/runtime/herdr/HerdrCliClient.d.ts +13 -0
  299. package/dist/runtime/herdr/HerdrCliClient.d.ts.map +1 -0
  300. package/dist/runtime/herdr/HerdrCliClient.js +60 -0
  301. package/dist/runtime/herdr/HerdrCliClient.js.map +1 -0
  302. package/dist/runtime/herdr/HerdrErrors.d.ts +7 -0
  303. package/dist/runtime/herdr/HerdrErrors.d.ts.map +1 -0
  304. package/dist/runtime/herdr/HerdrErrors.js +10 -0
  305. package/dist/runtime/herdr/HerdrErrors.js.map +1 -0
  306. package/dist/runtime/herdr/HerdrResponseParsers.d.ts +14 -0
  307. package/dist/runtime/herdr/HerdrResponseParsers.d.ts.map +1 -0
  308. package/dist/runtime/herdr/HerdrResponseParsers.js +96 -0
  309. package/dist/runtime/herdr/HerdrResponseParsers.js.map +1 -0
  310. package/dist/runtime/herdr/HerdrRuntimeRef.d.ts +9 -0
  311. package/dist/runtime/herdr/HerdrRuntimeRef.d.ts.map +1 -0
  312. package/dist/runtime/herdr/HerdrRuntimeRef.js +33 -0
  313. package/dist/runtime/herdr/HerdrRuntimeRef.js.map +1 -0
  314. package/dist/runtime/tmux/PidPolling.d.ts +5 -0
  315. package/dist/runtime/tmux/PidPolling.d.ts.map +1 -0
  316. package/dist/runtime/tmux/PidPolling.js +24 -0
  317. package/dist/runtime/tmux/PidPolling.js.map +1 -0
  318. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts +17 -0
  319. package/dist/runtime/tmux/TmuxAgentRuntime.d.ts.map +1 -0
  320. package/dist/runtime/tmux/TmuxAgentRuntime.js +80 -0
  321. package/dist/runtime/tmux/TmuxAgentRuntime.js.map +1 -0
  322. package/dist/runtime/tmux/TmuxRuntimeRef.d.ts +5 -0
  323. package/dist/runtime/tmux/TmuxRuntimeRef.d.ts.map +1 -0
  324. package/dist/runtime/tmux/TmuxRuntimeRef.js +9 -0
  325. package/dist/runtime/tmux/TmuxRuntimeRef.js.map +1 -0
  326. package/dist/runtime/types.d.ts +54 -0
  327. package/dist/runtime/types.d.ts.map +1 -0
  328. package/dist/runtime/types.js +3 -0
  329. package/dist/runtime/types.js.map +1 -0
  330. package/dist/terminal/TerminalFocusManager.d.ts.map +1 -1
  331. package/dist/terminal/TerminalFocusManager.js +50 -50
  332. package/dist/terminal/TerminalFocusManager.js.map +1 -1
  333. package/dist/terminal/TmuxManager.d.ts.map +1 -1
  334. package/dist/terminal/TmuxManager.js +47 -47
  335. package/dist/terminal/TmuxManager.js.map +1 -1
  336. package/dist/terminal/TtyWriter.d.ts +1 -1
  337. package/dist/terminal/TtyWriter.d.ts.map +1 -1
  338. package/dist/terminal/TtyWriter.js +89 -89
  339. package/dist/terminal/TtyWriter.js.map +1 -1
  340. package/dist/terminal/index.d.ts +4 -4
  341. package/dist/terminal/index.js +3 -3
  342. package/dist/terminal/index.js.map +1 -1
  343. package/dist/utils/AgentRegistry.d.ts +10 -2
  344. package/dist/utils/AgentRegistry.d.ts.map +1 -1
  345. package/dist/utils/AgentRegistry.js +57 -24
  346. package/dist/utils/AgentRegistry.js.map +1 -1
  347. package/dist/utils/agent-requests.d.ts.map +1 -1
  348. package/dist/utils/agent-requests.js +5 -5
  349. package/dist/utils/agent-requests.js.map +1 -1
  350. package/dist/utils/agents.d.ts +2 -2
  351. package/dist/utils/agents.d.ts.map +1 -1
  352. package/dist/utils/agents.js +15 -15
  353. package/dist/utils/agents.js.map +1 -1
  354. package/dist/utils/applescript.js +1 -1
  355. package/dist/utils/applescript.js.map +1 -1
  356. package/dist/utils/index.d.ts +6 -6
  357. package/dist/utils/index.d.ts.map +1 -1
  358. package/dist/utils/index.js +4 -4
  359. package/dist/utils/index.js.map +1 -1
  360. package/dist/utils/matching.d.ts +2 -2
  361. package/dist/utils/matching.d.ts.map +1 -1
  362. package/dist/utils/matching.js +4 -4
  363. package/dist/utils/matching.js.map +1 -1
  364. package/dist/utils/process.d.ts +1 -1
  365. package/dist/utils/process.d.ts.map +1 -1
  366. package/dist/utils/process.js +74 -74
  367. package/dist/utils/process.js.map +1 -1
  368. package/dist/utils/session.d.ts +1 -1
  369. package/dist/utils/session.d.ts.map +1 -1
  370. package/dist/utils/session.js +7 -7
  371. package/dist/utils/session.js.map +1 -1
  372. package/dist/utils/sortAgents.d.ts +2 -2
  373. package/dist/utils/sortAgents.d.ts.map +1 -1
  374. package/dist/utils/sortAgents.js +5 -5
  375. package/dist/utils/sortAgents.js.map +1 -1
  376. package/package.json +18 -19
  377. package/src/AgentManager.ts +283 -281
  378. package/src/__tests__/AgentManager.test.ts +917 -907
  379. package/src/__tests__/adapters/ClaudeCodeAdapter.test.ts +1657 -1368
  380. package/src/__tests__/adapters/CodexAdapter.test.ts +365 -1698
  381. package/src/__tests__/adapters/CopilotAdapter.test.ts +576 -481
  382. package/src/__tests__/adapters/GeminiCliAdapter.test.ts +1189 -1157
  383. package/src/__tests__/adapters/GrokCliAdapter.test.ts +325 -272
  384. package/src/__tests__/adapters/OpenCodeAdapter.test.ts +510 -455
  385. package/src/__tests__/capacity/codex.test.ts +178 -91
  386. package/src/__tests__/capacity/index.test.ts +27 -18
  387. package/src/__tests__/durable/CodexCliProbe.test.ts +75 -53
  388. package/src/__tests__/durable/CodexDurableAgentRepository.test.ts +51 -40
  389. package/src/__tests__/durable/CodexPrintAgent.integration.test.ts +89 -64
  390. package/src/__tests__/durable/CodexPrintAgentService.test.ts +196 -118
  391. package/src/__tests__/durable/CodexPrintRunner.test.ts +282 -162
  392. package/src/__tests__/fixtures/fake-claude.cjs +20 -13
  393. package/src/__tests__/fixtures/fake-codex.cjs +41 -30
  394. package/src/__tests__/print/ClaudeCliProbe.test.ts +27 -21
  395. package/src/__tests__/print/ClaudePrintAgent.integration.test.ts +48 -40
  396. package/src/__tests__/print/ClaudePrintAgentService.test.ts +118 -67
  397. package/src/__tests__/print/ClaudePrintRunner.test.ts +136 -83
  398. package/src/__tests__/print/DurableAgent.test.ts +19 -16
  399. package/src/__tests__/print/DurableAgentRepository.sqlite.test.ts +109 -86
  400. package/src/__tests__/print/DurableAgentRepository.test.ts +170 -137
  401. package/src/__tests__/providers/claude/ClaudeAgentMapper.test.ts +65 -65
  402. package/src/__tests__/providers/claude/ClaudeSessionLocator.test.ts +400 -377
  403. package/src/__tests__/providers/codex/CodexSessionLocator.test.ts +182 -0
  404. package/src/__tests__/providers/codex/CodexSessionMapping.test.ts +63 -0
  405. package/src/__tests__/providers/codex/CodexSessionParser.test.ts +192 -0
  406. package/src/__tests__/providers/pi/PiAdapter.test.ts +310 -0
  407. package/src/__tests__/providers/pi/PiSessionParser.test.ts +190 -0
  408. package/src/__tests__/providers/pi/PiSessionTracker.test.ts +79 -0
  409. package/src/__tests__/providers/pi/durable/PiCliProbe.test.ts +48 -32
  410. package/src/__tests__/providers/pi/durable/PiDurableAgentRepository.test.ts +24 -23
  411. package/src/__tests__/providers/pi/durable/PiPrintAgentService.test.ts +131 -59
  412. package/src/__tests__/providers/pi/durable/PiPrintProtocol.test.ts +66 -28
  413. package/src/__tests__/providers/pi/durable/PiPrintRunner.test.ts +236 -90
  414. package/src/__tests__/providers/pi/durable/PiStreamParser.test.ts +20 -18
  415. package/src/__tests__/readiness/AgentReadiness.test.ts +242 -0
  416. package/src/__tests__/runtime/AgentRuntime.test.ts +8 -0
  417. package/src/__tests__/runtime/HerdrAgentRuntime.test.ts +358 -0
  418. package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +555 -0
  419. package/src/__tests__/terminal/TerminalFocusManager.test.ts +254 -253
  420. package/src/__tests__/terminal/TmuxManager.test.ts +157 -157
  421. package/src/__tests__/terminal/TtyWriter.test.ts +423 -419
  422. package/src/__tests__/utils/AgentRegistry.test.ts +506 -402
  423. package/src/__tests__/utils/ClaudeSessionParser.test.ts +276 -242
  424. package/src/__tests__/utils/agent-requests.test.ts +76 -56
  425. package/src/__tests__/utils/agents.test.ts +20 -20
  426. package/src/__tests__/utils/matching.test.ts +206 -171
  427. package/src/__tests__/utils/process.test.ts +276 -262
  428. package/src/__tests__/utils/session.test.ts +133 -139
  429. package/src/adapters/AgentAdapter.ts +134 -126
  430. package/src/adapters/CopilotAdapter.ts +405 -395
  431. package/src/adapters/GeminiCliAdapter.ts +598 -600
  432. package/src/adapters/GrokCliAdapter.ts +353 -342
  433. package/src/adapters/OpenCodeAdapter.ts +285 -259
  434. package/src/adapters/index.ts +15 -9
  435. package/src/capacity/codex.ts +137 -84
  436. package/src/capacity/index.ts +18 -13
  437. package/src/capacity/types.ts +1 -1
  438. package/src/database/connection.ts +73 -68
  439. package/src/database/index.ts +6 -6
  440. package/src/database/migrations/005_agent_runtime.sql +2 -0
  441. package/src/database/schema.ts +40 -38
  442. package/src/durable/DurableAgent.ts +85 -85
  443. package/src/durable/DurableAgentRepository.ts +409 -260
  444. package/src/durable/process.ts +22 -21
  445. package/src/durable/run.ts +61 -51
  446. package/src/durable/utils.ts +46 -41
  447. package/src/index.ts +145 -86
  448. package/src/providers/claude/ClaudeAgentMapper.ts +51 -50
  449. package/src/providers/claude/ClaudeCodeAdapter.ts +144 -136
  450. package/src/providers/claude/ClaudeSessionLocator.ts +291 -293
  451. package/src/providers/claude/ClaudeSessionParser.ts +322 -338
  452. package/src/providers/claude/durable/ClaudeCliProbe.ts +42 -37
  453. package/src/providers/claude/durable/ClaudePrintAgentService.ts +63 -50
  454. package/src/providers/claude/durable/ClaudePrintRunner.ts +79 -69
  455. package/src/providers/claude/durable/ClaudeStreamParser.ts +91 -62
  456. package/src/providers/codex/CodexAdapter.ts +205 -0
  457. package/src/providers/codex/CodexAgentMapper.ts +35 -0
  458. package/src/providers/codex/CodexSessionLocator.ts +279 -0
  459. package/src/providers/codex/CodexSessionMapping.ts +89 -0
  460. package/src/providers/codex/CodexSessionParser.ts +385 -0
  461. package/src/providers/codex/durable/CodexCliProbe.ts +50 -42
  462. package/src/providers/codex/durable/CodexPrintAgentService.ts +63 -49
  463. package/src/providers/codex/durable/CodexPrintRunner.ts +79 -69
  464. package/src/providers/codex/durable/CodexStreamParser.ts +97 -84
  465. package/src/providers/pi/PiAdapter.ts +183 -0
  466. package/src/providers/pi/PiAgentMapper.ts +36 -0
  467. package/src/providers/pi/PiSessionLocator.ts +95 -0
  468. package/src/providers/pi/PiSessionParser.ts +284 -0
  469. package/src/providers/pi/PiSessionTracker.ts +87 -0
  470. package/src/providers/pi/durable/PiCliProbe.ts +42 -34
  471. package/src/providers/pi/durable/PiPrintAgentService.ts +61 -53
  472. package/src/providers/pi/durable/PiPrintProtocol.ts +31 -29
  473. package/src/providers/pi/durable/PiPrintRunner.ts +75 -68
  474. package/src/providers/pi/durable/PiStreamParser.ts +82 -72
  475. package/src/readiness/AgentReadiness.ts +727 -0
  476. package/src/runtime/ManagedAgentRuntime.ts +266 -0
  477. package/src/runtime/RuntimeFactory.ts +13 -0
  478. package/src/runtime/errors.ts +50 -0
  479. package/src/runtime/herdr/HerdrAgentRuntime.ts +190 -0
  480. package/src/runtime/herdr/HerdrCliClient.ts +78 -0
  481. package/src/runtime/herdr/HerdrErrors.ts +9 -0
  482. package/src/runtime/herdr/HerdrResponseParsers.ts +76 -0
  483. package/src/runtime/herdr/HerdrRuntimeRef.ts +41 -0
  484. package/src/runtime/tmux/PidPolling.ts +34 -0
  485. package/src/runtime/tmux/TmuxAgentRuntime.ts +113 -0
  486. package/src/runtime/tmux/TmuxRuntimeRef.ts +9 -0
  487. package/src/runtime/types.ts +56 -0
  488. package/src/terminal/TerminalFocusManager.ts +215 -212
  489. package/src/terminal/TmuxManager.ts +99 -92
  490. package/src/terminal/TtyWriter.ts +203 -194
  491. package/src/terminal/index.ts +4 -4
  492. package/src/utils/AgentRegistry.ts +299 -238
  493. package/src/utils/agent-requests.ts +16 -16
  494. package/src/utils/agents.ts +41 -38
  495. package/src/utils/applescript.ts +4 -4
  496. package/src/utils/index.ts +12 -6
  497. package/src/utils/matching.ts +43 -43
  498. package/src/utils/process.ts +261 -258
  499. package/src/utils/session.ts +66 -66
  500. package/src/utils/sortAgents.ts +35 -33
  501. package/tsconfig.json +2 -8
  502. package/vitest.config.ts +16 -16
  503. package/.eslintrc.json +0 -31
  504. package/dist/__tests__/adapters/PiAdapter.test.js +0 -618
  505. package/dist/__tests__/adapters/PiAdapter.test.js.map +0 -1
  506. package/dist/__tests__/database/DurableAgentsDatabase.test.js +0 -128
  507. package/dist/__tests__/database/DurableAgentsDatabase.test.js.map +0 -1
  508. package/dist/adapters/CodexAdapter.d.ts +0 -109
  509. package/dist/adapters/CodexAdapter.d.ts.map +0 -1
  510. package/dist/adapters/CodexAdapter.js +0 -710
  511. package/dist/adapters/CodexAdapter.js.map +0 -1
  512. package/dist/adapters/PiAdapter.d.ts +0 -63
  513. package/dist/adapters/PiAdapter.d.ts.map +0 -1
  514. package/dist/adapters/PiAdapter.js +0 -453
  515. package/dist/adapters/PiAdapter.js.map +0 -1
  516. package/src/__tests__/adapters/PiAdapter.test.ts +0 -458
  517. package/src/__tests__/database/DurableAgentsDatabase.test.ts +0 -102
  518. package/src/adapters/CodexAdapter.ts +0 -923
  519. package/src/adapters/PiAdapter.ts +0 -598
@@ -1 +1 @@
1
- {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/utils/matching.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,0BAA0B;IAC1B,OAAO,EAAE,WAAW,CAAC;IAErB,+BAA+B;IAC/B,OAAO,EAAE,WAAW,CAAC;IAErB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACpC,SAAS,EAAE,WAAW,EAAE,EACxB,QAAQ,EAAE,WAAW,EAAE,GACxB,WAAW,EAAE,CAsCf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlE"}
1
+ {"version":3,"file":"matching.d.ts","sourceRoot":"","sources":["../../src/utils/matching.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,0BAA0B;IAC1B,OAAO,EAAE,WAAW,CAAC;IAErB,+BAA+B;IAC/B,OAAO,EAAE,WAAW,CAAC;IAErB,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,WAAW,EAAE,EACxB,QAAQ,EAAE,WAAW,EAAE,GACtB,WAAW,EAAE,CAsCf;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlE"}
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Shared 1:1 greedy matching algorithm that pairs running processes with session files
5
5
  * based on CWD and birth-time proximity to process start time.
6
- */ import * as path from 'path';
6
+ */ import * as path from "path";
7
7
  /** Maximum allowed delta between process start time and session file birth time. */ const TOLERANCE_MS = 3 * 60 * 1000; // 3 minutes
8
8
  /**
9
9
  * Match processes to session files using 1:1 greedy assignment.
@@ -54,9 +54,9 @@
54
54
  *
55
55
  * Format: "folder-name-pid" (lowercase kebab-case)
56
56
  */ export function generateAgentName(cwd, pid) {
57
- const folderName = path.basename(cwd) || 'unknown';
58
- const kebab = folderName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
59
- return `${kebab || 'unknown'}-${pid}`;
57
+ const folderName = path.basename(cwd) || "unknown";
58
+ const kebab = folderName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
59
+ return `${kebab || "unknown"}-${pid}`;
60
60
  }
61
61
 
62
62
  //# sourceMappingURL=matching.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/matching.ts"],"sourcesContent":["/**\n * Session Matching Utilities\n *\n * Shared 1:1 greedy matching algorithm that pairs running processes with session files\n * based on CWD and birth-time proximity to process start time.\n */\n\nimport * as path from 'path';\nimport type { ProcessInfo } from '../adapters/AgentAdapter.js';\nimport type { SessionFile } from './session.js';\n\n/** Maximum allowed delta between process start time and session file birth time. */\nconst TOLERANCE_MS = 3 * 60 * 1000; // 3 minutes\n\n/**\n * Result of matching a process to a session file.\n */\nexport interface MatchResult {\n /** The matched process */\n process: ProcessInfo;\n\n /** The matched session file */\n session: SessionFile;\n\n /** Absolute time delta in ms between process start and session birth time */\n deltaMs: number;\n}\n\n/**\n * Match processes to session files using 1:1 greedy assignment.\n *\n * Algorithm:\n * 1. Exclude processes without startTime (they become process-only fallback).\n * 2. Build candidate pairs where process.cwd === session.resolvedCwd\n * and |process.startTime - session.birthtimeMs| <= 3 minutes.\n * 3. Sort candidates by deltaMs ascending (best matches first).\n * 4. Greedily assign: once a process or session is matched, skip it.\n *\n * Adapters must set session.resolvedCwd before calling this function.\n */\nexport function matchProcessesToSessions(\n processes: ProcessInfo[],\n sessions: SessionFile[],\n): MatchResult[] {\n // Build all candidate pairs\n const candidates: Array<{ process: ProcessInfo; session: SessionFile; deltaMs: number }> = [];\n\n for (const proc of processes) {\n if (!proc.startTime || !proc.cwd) continue;\n\n const processStartMs = proc.startTime.getTime();\n\n for (const session of sessions) {\n if (!session.resolvedCwd) continue;\n if (proc.cwd !== session.resolvedCwd) continue;\n\n const deltaMs = Math.abs(processStartMs - session.birthtimeMs);\n if (deltaMs > TOLERANCE_MS) continue;\n\n candidates.push({ process: proc, session, deltaMs });\n }\n }\n\n // Sort by smallest delta first\n candidates.sort((a, b) => a.deltaMs - b.deltaMs);\n\n // Greedy 1:1 assignment\n const matchedPids = new Set<number>();\n const matchedSessionIds = new Set<string>();\n const results: MatchResult[] = [];\n\n for (const candidate of candidates) {\n if (matchedPids.has(candidate.process.pid)) continue;\n if (matchedSessionIds.has(candidate.session.sessionId)) continue;\n\n matchedPids.add(candidate.process.pid);\n matchedSessionIds.add(candidate.session.sessionId);\n results.push(candidate);\n }\n\n return results;\n}\n\n/**\n * Generate a deterministic agent name from CWD and PID.\n *\n * Format: \"folder-name-pid\" (lowercase kebab-case)\n */\nexport function generateAgentName(cwd: string, pid: number): string {\n const folderName = path.basename(cwd) || 'unknown';\n const kebab = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n return `${kebab || 'unknown'}-${pid}`;\n}\n"],"names":["path","TOLERANCE_MS","matchProcessesToSessions","processes","sessions","candidates","proc","startTime","cwd","processStartMs","getTime","session","resolvedCwd","deltaMs","Math","abs","birthtimeMs","push","process","sort","a","b","matchedPids","Set","matchedSessionIds","results","candidate","has","pid","sessionId","add","generateAgentName","folderName","basename","kebab","toLowerCase","replace"],"mappings":"AAAA;;;;;CAKC,GAED,YAAYA,UAAU,OAAO;AAI7B,kFAAkF,GAClF,MAAMC,eAAe,IAAI,KAAK,MAAM,YAAY;AAgBhD;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,yBACZC,SAAwB,EACxBC,QAAuB;IAEvB,4BAA4B;IAC5B,MAAMC,aAAqF,EAAE;IAE7F,KAAK,MAAMC,QAAQH,UAAW;QAC1B,IAAI,CAACG,KAAKC,SAAS,IAAI,CAACD,KAAKE,GAAG,EAAE;QAElC,MAAMC,iBAAiBH,KAAKC,SAAS,CAACG,OAAO;QAE7C,KAAK,MAAMC,WAAWP,SAAU;YAC5B,IAAI,CAACO,QAAQC,WAAW,EAAE;YAC1B,IAAIN,KAAKE,GAAG,KAAKG,QAAQC,WAAW,EAAE;YAEtC,MAAMC,UAAUC,KAAKC,GAAG,CAACN,iBAAiBE,QAAQK,WAAW;YAC7D,IAAIH,UAAUZ,cAAc;YAE5BI,WAAWY,IAAI,CAAC;gBAAEC,SAASZ;gBAAMK;gBAASE;YAAQ;QACtD;IACJ;IAEA,+BAA+B;IAC/BR,WAAWc,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEP,OAAO,GAAGQ,EAAER,OAAO;IAE/C,wBAAwB;IACxB,MAAMS,cAAc,IAAIC;IACxB,MAAMC,oBAAoB,IAAID;IAC9B,MAAME,UAAyB,EAAE;IAEjC,KAAK,MAAMC,aAAarB,WAAY;QAChC,IAAIiB,YAAYK,GAAG,CAACD,UAAUR,OAAO,CAACU,GAAG,GAAG;QAC5C,IAAIJ,kBAAkBG,GAAG,CAACD,UAAUf,OAAO,CAACkB,SAAS,GAAG;QAExDP,YAAYQ,GAAG,CAACJ,UAAUR,OAAO,CAACU,GAAG;QACrCJ,kBAAkBM,GAAG,CAACJ,UAAUf,OAAO,CAACkB,SAAS;QACjDJ,QAAQR,IAAI,CAACS;IACjB;IAEA,OAAOD;AACX;AAEA;;;;CAIC,GACD,OAAO,SAASM,kBAAkBvB,GAAW,EAAEoB,GAAW;IACtD,MAAMI,aAAahC,KAAKiC,QAAQ,CAACzB,QAAQ;IACzC,MAAM0B,QAAQF,WACTG,WAAW,GACXC,OAAO,CAAC,eAAe,KACvBA,OAAO,CAAC,YAAY;IACzB,OAAO,GAAGF,SAAS,UAAU,CAAC,EAAEN,KAAK;AACzC"}
1
+ {"version":3,"sources":["../../src/utils/matching.ts"],"sourcesContent":["/**\n * Session Matching Utilities\n *\n * Shared 1:1 greedy matching algorithm that pairs running processes with session files\n * based on CWD and birth-time proximity to process start time.\n */\n\nimport * as path from \"path\";\nimport type { ProcessInfo } from \"../adapters/AgentAdapter.js\";\nimport type { SessionFile } from \"./session.js\";\n\n/** Maximum allowed delta between process start time and session file birth time. */\nconst TOLERANCE_MS = 3 * 60 * 1000; // 3 minutes\n\n/**\n * Result of matching a process to a session file.\n */\nexport interface MatchResult {\n /** The matched process */\n process: ProcessInfo;\n\n /** The matched session file */\n session: SessionFile;\n\n /** Absolute time delta in ms between process start and session birth time */\n deltaMs: number;\n}\n\n/**\n * Match processes to session files using 1:1 greedy assignment.\n *\n * Algorithm:\n * 1. Exclude processes without startTime (they become process-only fallback).\n * 2. Build candidate pairs where process.cwd === session.resolvedCwd\n * and |process.startTime - session.birthtimeMs| <= 3 minutes.\n * 3. Sort candidates by deltaMs ascending (best matches first).\n * 4. Greedily assign: once a process or session is matched, skip it.\n *\n * Adapters must set session.resolvedCwd before calling this function.\n */\nexport function matchProcessesToSessions(\n processes: ProcessInfo[],\n sessions: SessionFile[],\n): MatchResult[] {\n // Build all candidate pairs\n const candidates: Array<{ process: ProcessInfo; session: SessionFile; deltaMs: number }> = [];\n\n for (const proc of processes) {\n if (!proc.startTime || !proc.cwd) continue;\n\n const processStartMs = proc.startTime.getTime();\n\n for (const session of sessions) {\n if (!session.resolvedCwd) continue;\n if (proc.cwd !== session.resolvedCwd) continue;\n\n const deltaMs = Math.abs(processStartMs - session.birthtimeMs);\n if (deltaMs > TOLERANCE_MS) continue;\n\n candidates.push({ process: proc, session, deltaMs });\n }\n }\n\n // Sort by smallest delta first\n candidates.sort((a, b) => a.deltaMs - b.deltaMs);\n\n // Greedy 1:1 assignment\n const matchedPids = new Set<number>();\n const matchedSessionIds = new Set<string>();\n const results: MatchResult[] = [];\n\n for (const candidate of candidates) {\n if (matchedPids.has(candidate.process.pid)) continue;\n if (matchedSessionIds.has(candidate.session.sessionId)) continue;\n\n matchedPids.add(candidate.process.pid);\n matchedSessionIds.add(candidate.session.sessionId);\n results.push(candidate);\n }\n\n return results;\n}\n\n/**\n * Generate a deterministic agent name from CWD and PID.\n *\n * Format: \"folder-name-pid\" (lowercase kebab-case)\n */\nexport function generateAgentName(cwd: string, pid: number): string {\n const folderName = path.basename(cwd) || \"unknown\";\n const kebab = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return `${kebab || \"unknown\"}-${pid}`;\n}\n"],"names":["path","TOLERANCE_MS","matchProcessesToSessions","processes","sessions","candidates","proc","startTime","cwd","processStartMs","getTime","session","resolvedCwd","deltaMs","Math","abs","birthtimeMs","push","process","sort","a","b","matchedPids","Set","matchedSessionIds","results","candidate","has","pid","sessionId","add","generateAgentName","folderName","basename","kebab","toLowerCase","replace"],"mappings":"AAAA;;;;;CAKC,GAED,YAAYA,UAAU,OAAO;AAI7B,kFAAkF,GAClF,MAAMC,eAAe,IAAI,KAAK,MAAM,YAAY;AAgBhD;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,yBACdC,SAAwB,EACxBC,QAAuB;IAEvB,4BAA4B;IAC5B,MAAMC,aAAqF,EAAE;IAE7F,KAAK,MAAMC,QAAQH,UAAW;QAC5B,IAAI,CAACG,KAAKC,SAAS,IAAI,CAACD,KAAKE,GAAG,EAAE;QAElC,MAAMC,iBAAiBH,KAAKC,SAAS,CAACG,OAAO;QAE7C,KAAK,MAAMC,WAAWP,SAAU;YAC9B,IAAI,CAACO,QAAQC,WAAW,EAAE;YAC1B,IAAIN,KAAKE,GAAG,KAAKG,QAAQC,WAAW,EAAE;YAEtC,MAAMC,UAAUC,KAAKC,GAAG,CAACN,iBAAiBE,QAAQK,WAAW;YAC7D,IAAIH,UAAUZ,cAAc;YAE5BI,WAAWY,IAAI,CAAC;gBAAEC,SAASZ;gBAAMK;gBAASE;YAAQ;QACpD;IACF;IAEA,+BAA+B;IAC/BR,WAAWc,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEP,OAAO,GAAGQ,EAAER,OAAO;IAE/C,wBAAwB;IACxB,MAAMS,cAAc,IAAIC;IACxB,MAAMC,oBAAoB,IAAID;IAC9B,MAAME,UAAyB,EAAE;IAEjC,KAAK,MAAMC,aAAarB,WAAY;QAClC,IAAIiB,YAAYK,GAAG,CAACD,UAAUR,OAAO,CAACU,GAAG,GAAG;QAC5C,IAAIJ,kBAAkBG,GAAG,CAACD,UAAUf,OAAO,CAACkB,SAAS,GAAG;QAExDP,YAAYQ,GAAG,CAACJ,UAAUR,OAAO,CAACU,GAAG;QACrCJ,kBAAkBM,GAAG,CAACJ,UAAUf,OAAO,CAACkB,SAAS;QACjDJ,QAAQR,IAAI,CAACS;IACf;IAEA,OAAOD;AACT;AAEA;;;;CAIC,GACD,OAAO,SAASM,kBAAkBvB,GAAW,EAAEoB,GAAW;IACxD,MAAMI,aAAahC,KAAKiC,QAAQ,CAACzB,QAAQ;IACzC,MAAM0B,QAAQF,WACXG,WAAW,GACXC,OAAO,CAAC,eAAe,KACvBA,OAAO,CAAC,YAAY;IACvB,OAAO,GAAGF,SAAS,UAAU,CAAC,EAAEN,KAAK;AACvC"}
@@ -5,7 +5,7 @@
5
5
  * Built-in refresh discovery uses captureProcessSnapshot(); synchronous helpers
6
6
  * remain exported for compatibility with existing consumers.
7
7
  */
8
- import type { ProcessInfo } from '../adapters/AgentAdapter.js';
8
+ import type { ProcessInfo } from "../adapters/AgentAdapter.js";
9
9
  export declare function executableBasename(command: string): string;
10
10
  export declare function filterByProcessNames(processes: readonly ProcessInfo[], namePatterns: readonly string[]): ProcessInfo[];
11
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/utils/process.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAK/D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAWD,wBAAgB,oBAAoB,CAChC,SAAS,EAAE,SAAS,WAAW,EAAE,EACjC,YAAY,EAAE,SAAS,MAAM,EAAE,GAChC,WAAW,EAAE,CAMf;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE,CA0CrE;AAoGD;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAsBpG;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAuCvE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAkC3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAavE;AAaD,wBAAgB,kBAAkB,CAC9B,SAAS,EAAE,WAAW,EAAE,EACxB,KAAK,EAAE,WAAW,GACnB,WAAW,GAAG,SAAS,CAMzB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAClC,SAAS,EAAE,WAAW,EAAE,EACxB,gBAAgB,GAAE,WAAW,EAAO,GACrC,GAAG,CAAC,MAAM,CAAC,CAmBb;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYjD"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/utils/process.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAK/D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1D;AAWD,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,WAAW,EAAE,EACjC,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,WAAW,EAAE,CAMf;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE,CA0CrE;AAwGD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,SAAS,MAAM,EAAE,GAC9B,OAAO,CAAC,WAAW,EAAE,CAAC,CAsBxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAuCvE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAiC3E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAavE;AAaD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,WAAW,EAAE,EACxB,KAAK,EAAE,WAAW,GACjB,WAAW,GAAG,SAAS,CAKzB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,WAAW,EAAE,EACxB,gBAAgB,GAAE,WAAW,EAAO,GACnC,GAAG,CAAC,MAAM,CAAC,CAqBb;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASjD"}
@@ -4,17 +4,17 @@
4
4
  * Shared shell command wrappers for detecting and inspecting running processes.
5
5
  * Built-in refresh discovery uses captureProcessSnapshot(); synchronous helpers
6
6
  * remain exported for compatibility with existing consumers.
7
- */ import * as path from 'path';
8
- import { execFile, execFileSync } from 'child_process';
7
+ */ import * as path from "path";
8
+ import { execFile, execFileSync } from "child_process";
9
9
  const PROCESS_EXEC_MAX_BUFFER = 10 * 1024 * 1024;
10
10
  const VALID_EXECUTABLE_NAME = /^[a-zA-Z0-9_-]+$/;
11
11
  export function executableBasename(command) {
12
- const executable = command.trim().split(/\s+/)[0] || '';
13
- return path.basename(executable.replace(/\\/g, '/')).toLowerCase();
12
+ const executable = command.trim().split(/\s+/)[0] || "";
13
+ return path.basename(executable.replace(/\\/g, "/")).toLowerCase();
14
14
  }
15
15
  function normalizeExecutableName(name) {
16
16
  const lower = name.toLowerCase();
17
- return lower.endsWith('.exe') ? lower.slice(0, -4) : lower;
17
+ return lower.endsWith(".exe") ? lower.slice(0, -4) : lower;
18
18
  }
19
19
  function normalizedProcessNames(namePatterns) {
20
20
  return new Set(namePatterns.filter(Boolean).map(normalizeExecutableName));
@@ -38,17 +38,17 @@ export function filterByProcessNames(processes, namePatterns) {
38
38
  return [];
39
39
  }
40
40
  try {
41
- const output = execFileSync('ps', [
42
- '-axo',
43
- 'pid=,ppid=,tty=,command='
41
+ const output = execFileSync("ps", [
42
+ "-axo",
43
+ "pid=,ppid=,tty=,command="
44
44
  ], {
45
- encoding: 'utf-8'
45
+ encoding: "utf-8"
46
46
  });
47
47
  const names = normalizedProcessNames([
48
48
  namePattern
49
49
  ]);
50
50
  const processes = [];
51
- for (const line of output.trim().split('\n')){
51
+ for (const line of output.trim().split("\n")){
52
52
  if (!line.trim()) continue;
53
53
  const match = line.match(/^\s*(\d+)\s+(\d+)\s+(\S+)\s+(.+)$/);
54
54
  if (!match) continue;
@@ -58,12 +58,12 @@ export function filterByProcessNames(processes, namePatterns) {
58
58
  const tty = match[3];
59
59
  const command = match[4];
60
60
  if (!names.has(normalizeExecutableName(executableBasename(command)))) continue;
61
- const ttyShort = tty.startsWith('/dev/') ? tty.slice(5) : tty;
61
+ const ttyShort = tty.startsWith("/dev/") ? tty.slice(5) : tty;
62
62
  processes.push({
63
63
  pid,
64
64
  ppid,
65
65
  command,
66
- cwd: '',
66
+ cwd: "",
67
67
  tty: ttyShort
68
68
  });
69
69
  }
@@ -75,7 +75,7 @@ export function filterByProcessNames(processes, namePatterns) {
75
75
  function execFileText(file, args) {
76
76
  return new Promise((resolve, reject)=>{
77
77
  execFile(file, args, {
78
- encoding: 'utf-8',
78
+ encoding: "utf-8",
79
79
  maxBuffer: PROCESS_EXEC_MAX_BUFFER
80
80
  }, (error, stdout)=>{
81
81
  if (error) {
@@ -88,7 +88,7 @@ function execFileText(file, args) {
88
88
  }
89
89
  function parseProcessList(output, namePatterns) {
90
90
  const processes = [];
91
- for (const line of output.trim().split('\n')){
91
+ for (const line of output.trim().split("\n")){
92
92
  if (!line.trim()) continue;
93
93
  const match = line.match(/^\s*(\d+)\s+(\d+)\s+(\S+)\s+(.+)$/);
94
94
  if (!match) continue;
@@ -104,8 +104,8 @@ function parseProcessList(output, namePatterns) {
104
104
  pid,
105
105
  ppid,
106
106
  command,
107
- cwd: '',
108
- tty: tty.startsWith('/dev/') ? tty.slice(5) : tty
107
+ cwd: "",
108
+ tty: tty.startsWith("/dev/") ? tty.slice(5) : tty
109
109
  });
110
110
  }
111
111
  return processes;
@@ -114,19 +114,19 @@ async function batchGetProcessCwdsAsync(pids) {
114
114
  const result = new Map();
115
115
  if (pids.length === 0) return result;
116
116
  try {
117
- const output = await execFileText('lsof', [
118
- '-a',
119
- '-d',
120
- 'cwd',
121
- '-Fn',
122
- '-p',
123
- pids.join(',')
117
+ const output = await execFileText("lsof", [
118
+ "-a",
119
+ "-d",
120
+ "cwd",
121
+ "-Fn",
122
+ "-p",
123
+ pids.join(",")
124
124
  ]);
125
125
  let currentPid = null;
126
- for (const line of output.trim().split('\n')){
127
- if (line.startsWith('p')) {
126
+ for (const line of output.trim().split("\n")){
127
+ if (line.startsWith("p")) {
128
128
  currentPid = parseInt(line.slice(1), 10);
129
- } else if (line.startsWith('n') && currentPid !== null) {
129
+ } else if (line.startsWith("n") && currentPid !== null) {
130
130
  result.set(currentPid, line.slice(1));
131
131
  currentPid = null;
132
132
  }
@@ -135,7 +135,7 @@ async function batchGetProcessCwdsAsync(pids) {
135
135
  } catch {
136
136
  const entries = await Promise.all(pids.map(async (pid)=>{
137
137
  try {
138
- const output = await execFileText('pwdx', [
138
+ const output = await execFileText("pwdx", [
139
139
  String(pid)
140
140
  ]);
141
141
  const match = output.match(/^\d+:\s*(.+)$/);
@@ -157,13 +157,13 @@ async function batchGetProcessStartTimesAsync(pids) {
157
157
  const result = new Map();
158
158
  if (pids.length === 0) return result;
159
159
  try {
160
- const output = await execFileText('ps', [
161
- '-o',
162
- 'pid=,lstart=',
163
- '-p',
164
- pids.join(',')
160
+ const output = await execFileText("ps", [
161
+ "-o",
162
+ "pid=,lstart=",
163
+ "-p",
164
+ pids.join(",")
165
165
  ]);
166
- for (const rawLine of output.split('\n')){
166
+ for (const rawLine of output.split("\n")){
167
167
  const match = rawLine.trim().match(/^(\d+)\s+(.+)$/);
168
168
  if (!match) continue;
169
169
  const pid = parseInt(match[1], 10);
@@ -182,9 +182,9 @@ async function batchGetProcessStartTimesAsync(pids) {
182
182
  const names = normalizedProcessNames(namePatterns.filter((name)=>Boolean(name) && VALID_EXECUTABLE_NAME.test(name)));
183
183
  if (names.size === 0) return [];
184
184
  try {
185
- const output = await execFileText('ps', [
186
- '-axo',
187
- 'pid=,ppid=,tty=,command='
185
+ const output = await execFileText("ps", [
186
+ "-axo",
187
+ "pid=,ppid=,tty=,command="
188
188
  ]);
189
189
  const processes = parseProcessList(output, names);
190
190
  const pids = processes.map((process)=>process.pid);
@@ -194,7 +194,7 @@ async function batchGetProcessStartTimesAsync(pids) {
194
194
  ]);
195
195
  return processes.map((process)=>({
196
196
  ...process,
197
- cwd: cwdMap.get(process.pid) || '',
197
+ cwd: cwdMap.get(process.pid) || "",
198
198
  startTime: startTimeMap.get(process.pid)
199
199
  }));
200
200
  } catch {
@@ -210,27 +210,27 @@ async function batchGetProcessStartTimesAsync(pids) {
210
210
  const result = new Map();
211
211
  if (pids.length === 0) return result;
212
212
  try {
213
- const output = execFileSync('lsof', [
214
- '-a',
215
- '-d',
216
- 'cwd',
217
- '-Fn',
218
- '-p',
219
- pids.join(',')
213
+ const output = execFileSync("lsof", [
214
+ "-a",
215
+ "-d",
216
+ "cwd",
217
+ "-Fn",
218
+ "-p",
219
+ pids.join(",")
220
220
  ], {
221
- encoding: 'utf-8',
221
+ encoding: "utf-8",
222
222
  stdio: [
223
- 'pipe',
224
- 'pipe',
225
- 'ignore'
223
+ "pipe",
224
+ "pipe",
225
+ "ignore"
226
226
  ]
227
227
  });
228
228
  // lsof output format: p{PID}\nn{path}\np{PID}\nn{path}...
229
229
  let currentPid = null;
230
- for (const line of output.trim().split('\n')){
231
- if (line.startsWith('p')) {
230
+ for (const line of output.trim().split("\n")){
231
+ if (line.startsWith("p")) {
232
232
  currentPid = parseInt(line.slice(1), 10);
233
- } else if (line.startsWith('n') && currentPid !== null) {
233
+ } else if (line.startsWith("n") && currentPid !== null) {
234
234
  result.set(currentPid, line.slice(1));
235
235
  currentPid = null;
236
236
  }
@@ -239,14 +239,14 @@ async function batchGetProcessStartTimesAsync(pids) {
239
239
  // Try per-PID fallback with pwdx (Linux)
240
240
  for (const pid of pids){
241
241
  try {
242
- const output = execFileSync('pwdx', [
242
+ const output = execFileSync("pwdx", [
243
243
  String(pid)
244
244
  ], {
245
- encoding: 'utf-8',
245
+ encoding: "utf-8",
246
246
  stdio: [
247
- 'pipe',
248
- 'pipe',
249
- 'ignore'
247
+ "pipe",
248
+ "pipe",
249
+ "ignore"
250
250
  ]
251
251
  });
252
252
  const match = output.match(/^\d+:\s*(.+)$/);
@@ -270,15 +270,15 @@ async function batchGetProcessStartTimesAsync(pids) {
270
270
  const result = new Map();
271
271
  if (pids.length === 0) return result;
272
272
  try {
273
- const output = execFileSync('ps', [
274
- '-o',
275
- 'pid=,lstart=',
276
- '-p',
277
- pids.join(',')
273
+ const output = execFileSync("ps", [
274
+ "-o",
275
+ "pid=,lstart=",
276
+ "-p",
277
+ pids.join(",")
278
278
  ], {
279
- encoding: 'utf-8'
279
+ encoding: "utf-8"
280
280
  });
281
- for (const rawLine of output.split('\n')){
281
+ for (const rawLine of output.split("\n")){
282
282
  const line = rawLine.trim();
283
283
  if (!line) continue;
284
284
  // Format: " PID DAY MON DD HH:MM:SS YYYY"
@@ -310,15 +310,15 @@ async function batchGetProcessStartTimesAsync(pids) {
310
310
  const cwdMap = batchGetProcessCwds(pids);
311
311
  const startTimeMap = batchGetProcessStartTimes(pids);
312
312
  for (const proc of processes){
313
- proc.cwd = cwdMap.get(proc.pid) || '';
313
+ proc.cwd = cwdMap.get(proc.pid) || "";
314
314
  proc.startTime = startTimeMap.get(proc.pid);
315
315
  }
316
316
  return processes;
317
317
  }
318
318
  function isSameTerminalProcess(proc, matched) {
319
- const sameTty = proc.tty !== '' && proc.tty !== '?' && proc.tty === matched.tty;
320
- const sameCwd = proc.cwd !== '' && proc.cwd === matched.cwd;
321
- return sameTty && (sameCwd || proc.cwd === '' || matched.cwd === '');
319
+ const sameTty = proc.tty !== "" && proc.tty !== "?" && proc.tty === matched.tty;
320
+ const sameCwd = proc.cwd !== "" && proc.cwd === matched.cwd;
321
+ return sameTty && (sameCwd || proc.cwd === "" || matched.cwd === "");
322
322
  }
323
323
  function matchesProcessIdentity(proc, matched) {
324
324
  return proc.pid === matched.pid || isSameTerminalProcess(proc, matched);
@@ -351,18 +351,18 @@ export function findWrapperProcess(processes, child) {
351
351
  * Get the TTY device for a specific process
352
352
  */ export function getProcessTty(pid) {
353
353
  try {
354
- const output = execFileSync('ps', [
355
- '-p',
354
+ const output = execFileSync("ps", [
355
+ "-p",
356
356
  String(pid),
357
- '-o',
358
- 'tty='
357
+ "-o",
358
+ "tty="
359
359
  ], {
360
- encoding: 'utf-8'
360
+ encoding: "utf-8"
361
361
  });
362
362
  const tty = output.trim();
363
- return tty.startsWith('/dev/') ? tty.slice(5) : tty;
363
+ return tty.startsWith("/dev/") ? tty.slice(5) : tty;
364
364
  } catch {
365
- return '?';
365
+ return "?";
366
366
  }
367
367
  }
368
368
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/process.ts"],"sourcesContent":["/**\n * Process Detection Utilities\n *\n * Shared shell command wrappers for detecting and inspecting running processes.\n * Built-in refresh discovery uses captureProcessSnapshot(); synchronous helpers\n * remain exported for compatibility with existing consumers.\n */\n\nimport * as path from 'path';\nimport { execFile, execFileSync } from 'child_process';\nimport type { ProcessInfo } from '../adapters/AgentAdapter.js';\n\nconst PROCESS_EXEC_MAX_BUFFER = 10 * 1024 * 1024;\nconst VALID_EXECUTABLE_NAME = /^[a-zA-Z0-9_-]+$/;\n\nexport function executableBasename(command: string): string {\n const executable = command.trim().split(/\\s+/)[0] || '';\n return path.basename(executable.replace(/\\\\/g, '/')).toLowerCase();\n}\n\nfunction normalizeExecutableName(name: string): string {\n const lower = name.toLowerCase();\n return lower.endsWith('.exe') ? lower.slice(0, -4) : lower;\n}\n\nfunction normalizedProcessNames(namePatterns: readonly string[]): Set<string> {\n return new Set(namePatterns.filter(Boolean).map(normalizeExecutableName));\n}\n\nexport function filterByProcessNames(\n processes: readonly ProcessInfo[],\n namePatterns: readonly string[],\n): ProcessInfo[] {\n const names = normalizedProcessNames(namePatterns);\n if (names.size === 0) return [];\n return processes.filter((process) => (\n names.has(normalizeExecutableName(executableBasename(process.command)))\n ));\n}\n\n/**\n * List running processes matching an agent executable name.\n *\n * Uses `ps -axo` then filters in JS for exact executable basename match.\n * This avoids shell pipelines and string interpolation.\n *\n * Returned ProcessInfo has pid, ppid, command, tty populated.\n * cwd and startTime are NOT populated — call enrichProcesses() to fill them.\n */\nexport function listAgentProcesses(namePattern: string): ProcessInfo[] {\n // Validate pattern contains only safe characters (alphanumeric, dash, underscore)\n if (!namePattern || !VALID_EXECUTABLE_NAME.test(namePattern)) {\n return [];\n }\n\n try {\n const output = execFileSync('ps', ['-axo', 'pid=,ppid=,tty=,command='], { encoding: 'utf-8' });\n\n const names = normalizedProcessNames([namePattern]);\n const processes: ProcessInfo[] = [];\n\n for (const line of output.trim().split('\\n')) {\n if (!line.trim()) continue;\n\n const match = line.match(/^\\s*(\\d+)\\s+(\\d+)\\s+(\\S+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const ppid = parseInt(match[2], 10);\n if (Number.isNaN(pid) || Number.isNaN(ppid)) continue;\n\n const tty = match[3];\n const command = match[4];\n\n if (!names.has(normalizeExecutableName(executableBasename(command)))) continue;\n\n const ttyShort = tty.startsWith('/dev/') ? tty.slice(5) : tty;\n\n processes.push({\n pid,\n ppid,\n command,\n cwd: '',\n tty: ttyShort,\n });\n }\n\n return processes;\n } catch {\n return [];\n }\n}\n\nfunction execFileText(\n file: string,\n args: readonly string[],\n): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(file, args, { encoding: 'utf-8', maxBuffer: PROCESS_EXEC_MAX_BUFFER }, (error, stdout) => {\n if (error) {\n reject(error);\n return;\n }\n resolve(stdout);\n });\n });\n}\n\nfunction parseProcessList(output: string, namePatterns: ReadonlySet<string>): ProcessInfo[] {\n const processes: ProcessInfo[] = [];\n\n for (const line of output.trim().split('\\n')) {\n if (!line.trim()) continue;\n\n const match = line.match(/^\\s*(\\d+)\\s+(\\d+)\\s+(\\S+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const ppid = parseInt(match[2], 10);\n if (Number.isNaN(pid) || Number.isNaN(ppid)) continue;\n\n const tty = match[3];\n const command = match[4];\n const base = executableBasename(command);\n const normalizedBase = normalizeExecutableName(base);\n if (!namePatterns.has(normalizedBase)) continue;\n\n processes.push({\n pid,\n ppid,\n command,\n cwd: '',\n tty: tty.startsWith('/dev/') ? tty.slice(5) : tty,\n });\n }\n\n return processes;\n}\n\nasync function batchGetProcessCwdsAsync(pids: number[]): Promise<Map<number, string>> {\n const result = new Map<number, string>();\n if (pids.length === 0) return result;\n\n try {\n const output = await execFileText('lsof', ['-a', '-d', 'cwd', '-Fn', '-p', pids.join(',')]);\n let currentPid: number | null = null;\n for (const line of output.trim().split('\\n')) {\n if (line.startsWith('p')) {\n currentPid = parseInt(line.slice(1), 10);\n } else if (line.startsWith('n') && currentPid !== null) {\n result.set(currentPid, line.slice(1));\n currentPid = null;\n }\n }\n return result;\n } catch {\n const entries = await Promise.all(pids.map(async (pid) => {\n try {\n const output = await execFileText('pwdx', [String(pid)]);\n const match = output.match(/^\\d+:\\s*(.+)$/);\n return match ? [pid, match[1].trim()] as const : null;\n } catch {\n return null;\n }\n }));\n for (const entry of entries) {\n if (entry) result.set(entry[0], entry[1]);\n }\n return result;\n }\n}\n\nasync function batchGetProcessStartTimesAsync(pids: number[]): Promise<Map<number, Date>> {\n const result = new Map<number, Date>();\n if (pids.length === 0) return result;\n\n try {\n const output = await execFileText('ps', ['-o', 'pid=,lstart=', '-p', pids.join(',')]);\n for (const rawLine of output.split('\\n')) {\n const match = rawLine.trim().match(/^(\\d+)\\s+(.+)$/);\n if (!match) continue;\n const pid = parseInt(match[1], 10);\n const date = new Date(match[2].trim());\n if (Number.isFinite(pid) && !Number.isNaN(date.getTime())) result.set(pid, date);\n }\n } catch {\n // Return partial/empty data, matching the synchronous helper.\n }\n return result;\n}\n\n/**\n * Capture and enrich relevant processes without blocking the event loop.\n * One base process listing is shared by every requested executable name.\n */\nexport async function captureProcessSnapshot(namePatterns: readonly string[]): Promise<ProcessInfo[]> {\n const names = normalizedProcessNames(\n namePatterns.filter((name) => Boolean(name) && VALID_EXECUTABLE_NAME.test(name)),\n );\n if (names.size === 0) return [];\n\n try {\n const output = await execFileText('ps', ['-axo', 'pid=,ppid=,tty=,command=']);\n const processes = parseProcessList(output, names);\n const pids = processes.map((process) => process.pid);\n const [cwdMap, startTimeMap] = await Promise.all([\n batchGetProcessCwdsAsync(pids),\n batchGetProcessStartTimesAsync(pids),\n ]);\n return processes.map((process) => ({\n ...process,\n cwd: cwdMap.get(process.pid) || '',\n startTime: startTimeMap.get(process.pid),\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Batch-get current working directories for multiple PIDs.\n *\n * Single `lsof -a -d cwd -Fn -p PID1,PID2,...` call.\n * Returns partial results — if lsof fails for one PID, others still return.\n */\nexport function batchGetProcessCwds(pids: number[]): Map<number, string> {\n const result = new Map<number, string>();\n if (pids.length === 0) return result;\n\n try {\n const output = execFileSync(\n 'lsof', ['-a', '-d', 'cwd', '-Fn', '-p', pids.join(',')],\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] },\n );\n\n // lsof output format: p{PID}\\nn{path}\\np{PID}\\nn{path}...\n let currentPid: number | null = null;\n for (const line of output.trim().split('\\n')) {\n if (line.startsWith('p')) {\n currentPid = parseInt(line.slice(1), 10);\n } else if (line.startsWith('n') && currentPid !== null) {\n result.set(currentPid, line.slice(1));\n currentPid = null;\n }\n }\n } catch {\n // Try per-PID fallback with pwdx (Linux)\n for (const pid of pids) {\n try {\n const output = execFileSync(\n 'pwdx', [String(pid)],\n { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] },\n );\n const match = output.match(/^\\d+:\\s*(.+)$/);\n if (match) {\n result.set(pid, match[1].trim());\n }\n } catch {\n // Skip this PID\n }\n }\n }\n\n return result;\n}\n\n/**\n * Batch-get process start times for multiple PIDs.\n *\n * Single `ps -o pid=,lstart= -p PID1,PID2,...` call.\n * Uses lstart format which gives full timestamp (e.g., \"Thu Feb 5 16:00:57 2026\").\n * Returns partial results.\n */\nexport function batchGetProcessStartTimes(pids: number[]): Map<number, Date> {\n const result = new Map<number, Date>();\n if (pids.length === 0) return result;\n\n try {\n const output = execFileSync(\n 'ps', ['-o', 'pid=,lstart=', '-p', pids.join(',')],\n { encoding: 'utf-8' },\n );\n\n for (const rawLine of output.split('\\n')) {\n const line = rawLine.trim();\n if (!line) continue;\n\n // Format: \" PID DAY MON DD HH:MM:SS YYYY\"\n // e.g., \" 78070 Wed Mar 18 23:18:01 2026\"\n const match = line.match(/^\\s*(\\d+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const dateStr = match[2].trim();\n\n if (!Number.isFinite(pid)) continue;\n\n const date = new Date(dateStr);\n if (!Number.isNaN(date.getTime())) {\n result.set(pid, date);\n }\n }\n } catch {\n // Return whatever we have\n }\n\n return result;\n}\n\n/**\n * Enrich ProcessInfo array with cwd and startTime.\n *\n * Calls batchGetProcessCwds and batchGetProcessStartTimes in batched shell calls,\n * then populates each ProcessInfo in-place. Returns partial results —\n * if a PID fails, that process keeps empty cwd / undefined startTime.\n */\nexport function enrichProcesses(processes: ProcessInfo[]): ProcessInfo[] {\n if (processes.length === 0) return processes;\n\n const pids = processes.map(p => p.pid);\n const cwdMap = batchGetProcessCwds(pids);\n const startTimeMap = batchGetProcessStartTimes(pids);\n\n for (const proc of processes) {\n proc.cwd = cwdMap.get(proc.pid) || '';\n proc.startTime = startTimeMap.get(proc.pid);\n }\n\n return processes;\n}\n\nfunction isSameTerminalProcess(proc: ProcessInfo, matched: ProcessInfo): boolean {\n const sameTty = proc.tty !== '' && proc.tty !== '?' && proc.tty === matched.tty;\n const sameCwd = proc.cwd !== '' && proc.cwd === matched.cwd;\n\n return sameTty && (sameCwd || proc.cwd === '' || matched.cwd === '');\n}\n\nfunction matchesProcessIdentity(proc: ProcessInfo, matched: ProcessInfo): boolean {\n return proc.pid === matched.pid || isSameTerminalProcess(proc, matched);\n}\n\nexport function findWrapperProcess(\n processes: ProcessInfo[],\n child: ProcessInfo,\n): ProcessInfo | undefined {\n return processes.find((proc) => (\n proc.pid !== child.pid &&\n child.ppid === proc.pid &&\n matchesProcessIdentity(proc, child)\n ));\n}\n\n/**\n * Find parent wrapper processes that should not be reported as separate agents.\n *\n * A process is considered a wrapper when it is the parent of another candidate\n * agent process in the same terminal/worktree, or when it points at the same\n * terminal/worktree as an already session-matched process.\n */\nexport function findWrapperProcessPids(\n processes: ProcessInfo[],\n matchedProcesses: ProcessInfo[] = [],\n): Set<number> {\n const wrappers = new Set<number>();\n\n for (const child of processes) {\n const wrapper = findWrapperProcess(processes, child);\n if (wrapper) {\n wrappers.add(wrapper.pid);\n }\n }\n\n for (const proc of processes) {\n if (matchedProcesses.some((matched) => (\n proc.pid !== matched.pid && isSameTerminalProcess(proc, matched)\n ))) {\n wrappers.add(proc.pid);\n }\n }\n\n return wrappers;\n}\n\n/**\n * Get the TTY device for a specific process\n */\nexport function getProcessTty(pid: number): string {\n try {\n const output = execFileSync(\n 'ps', ['-p', String(pid), '-o', 'tty='],\n { encoding: 'utf-8' },\n );\n\n const tty = output.trim();\n return tty.startsWith('/dev/') ? tty.slice(5) : tty;\n } catch {\n return '?';\n }\n}\n"],"names":["path","execFile","execFileSync","PROCESS_EXEC_MAX_BUFFER","VALID_EXECUTABLE_NAME","executableBasename","command","executable","trim","split","basename","replace","toLowerCase","normalizeExecutableName","name","lower","endsWith","slice","normalizedProcessNames","namePatterns","Set","filter","Boolean","map","filterByProcessNames","processes","names","size","process","has","listAgentProcesses","namePattern","test","output","encoding","line","match","pid","parseInt","ppid","Number","isNaN","tty","ttyShort","startsWith","push","cwd","execFileText","file","args","Promise","resolve","reject","maxBuffer","error","stdout","parseProcessList","base","normalizedBase","batchGetProcessCwdsAsync","pids","result","Map","length","join","currentPid","set","entries","all","String","entry","batchGetProcessStartTimesAsync","rawLine","date","Date","isFinite","getTime","captureProcessSnapshot","cwdMap","startTimeMap","get","startTime","batchGetProcessCwds","stdio","batchGetProcessStartTimes","dateStr","enrichProcesses","p","proc","isSameTerminalProcess","matched","sameTty","sameCwd","matchesProcessIdentity","findWrapperProcess","child","find","findWrapperProcessPids","matchedProcesses","wrappers","wrapper","add","some","getProcessTty"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/process.ts"],"sourcesContent":["/**\n * Process Detection Utilities\n *\n * Shared shell command wrappers for detecting and inspecting running processes.\n * Built-in refresh discovery uses captureProcessSnapshot(); synchronous helpers\n * remain exported for compatibility with existing consumers.\n */\n\nimport * as path from \"path\";\nimport { execFile, execFileSync } from \"child_process\";\nimport type { ProcessInfo } from \"../adapters/AgentAdapter.js\";\n\nconst PROCESS_EXEC_MAX_BUFFER = 10 * 1024 * 1024;\nconst VALID_EXECUTABLE_NAME = /^[a-zA-Z0-9_-]+$/;\n\nexport function executableBasename(command: string): string {\n const executable = command.trim().split(/\\s+/)[0] || \"\";\n return path.basename(executable.replace(/\\\\/g, \"/\")).toLowerCase();\n}\n\nfunction normalizeExecutableName(name: string): string {\n const lower = name.toLowerCase();\n return lower.endsWith(\".exe\") ? lower.slice(0, -4) : lower;\n}\n\nfunction normalizedProcessNames(namePatterns: readonly string[]): Set<string> {\n return new Set(namePatterns.filter(Boolean).map(normalizeExecutableName));\n}\n\nexport function filterByProcessNames(\n processes: readonly ProcessInfo[],\n namePatterns: readonly string[],\n): ProcessInfo[] {\n const names = normalizedProcessNames(namePatterns);\n if (names.size === 0) return [];\n return processes.filter((process) =>\n names.has(normalizeExecutableName(executableBasename(process.command))),\n );\n}\n\n/**\n * List running processes matching an agent executable name.\n *\n * Uses `ps -axo` then filters in JS for exact executable basename match.\n * This avoids shell pipelines and string interpolation.\n *\n * Returned ProcessInfo has pid, ppid, command, tty populated.\n * cwd and startTime are NOT populated — call enrichProcesses() to fill them.\n */\nexport function listAgentProcesses(namePattern: string): ProcessInfo[] {\n // Validate pattern contains only safe characters (alphanumeric, dash, underscore)\n if (!namePattern || !VALID_EXECUTABLE_NAME.test(namePattern)) {\n return [];\n }\n\n try {\n const output = execFileSync(\"ps\", [\"-axo\", \"pid=,ppid=,tty=,command=\"], { encoding: \"utf-8\" });\n\n const names = normalizedProcessNames([namePattern]);\n const processes: ProcessInfo[] = [];\n\n for (const line of output.trim().split(\"\\n\")) {\n if (!line.trim()) continue;\n\n const match = line.match(/^\\s*(\\d+)\\s+(\\d+)\\s+(\\S+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const ppid = parseInt(match[2], 10);\n if (Number.isNaN(pid) || Number.isNaN(ppid)) continue;\n\n const tty = match[3];\n const command = match[4];\n\n if (!names.has(normalizeExecutableName(executableBasename(command)))) continue;\n\n const ttyShort = tty.startsWith(\"/dev/\") ? tty.slice(5) : tty;\n\n processes.push({\n pid,\n ppid,\n command,\n cwd: \"\",\n tty: ttyShort,\n });\n }\n\n return processes;\n } catch {\n return [];\n }\n}\n\nfunction execFileText(file: string, args: readonly string[]): Promise<string> {\n return new Promise((resolve, reject) => {\n execFile(\n file,\n args,\n { encoding: \"utf-8\", maxBuffer: PROCESS_EXEC_MAX_BUFFER },\n (error, stdout) => {\n if (error) {\n reject(error);\n return;\n }\n resolve(stdout);\n },\n );\n });\n}\n\nfunction parseProcessList(output: string, namePatterns: ReadonlySet<string>): ProcessInfo[] {\n const processes: ProcessInfo[] = [];\n\n for (const line of output.trim().split(\"\\n\")) {\n if (!line.trim()) continue;\n\n const match = line.match(/^\\s*(\\d+)\\s+(\\d+)\\s+(\\S+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const ppid = parseInt(match[2], 10);\n if (Number.isNaN(pid) || Number.isNaN(ppid)) continue;\n\n const tty = match[3];\n const command = match[4];\n const base = executableBasename(command);\n const normalizedBase = normalizeExecutableName(base);\n if (!namePatterns.has(normalizedBase)) continue;\n\n processes.push({\n pid,\n ppid,\n command,\n cwd: \"\",\n tty: tty.startsWith(\"/dev/\") ? tty.slice(5) : tty,\n });\n }\n\n return processes;\n}\n\nasync function batchGetProcessCwdsAsync(pids: number[]): Promise<Map<number, string>> {\n const result = new Map<number, string>();\n if (pids.length === 0) return result;\n\n try {\n const output = await execFileText(\"lsof\", [\"-a\", \"-d\", \"cwd\", \"-Fn\", \"-p\", pids.join(\",\")]);\n let currentPid: number | null = null;\n for (const line of output.trim().split(\"\\n\")) {\n if (line.startsWith(\"p\")) {\n currentPid = parseInt(line.slice(1), 10);\n } else if (line.startsWith(\"n\") && currentPid !== null) {\n result.set(currentPid, line.slice(1));\n currentPid = null;\n }\n }\n return result;\n } catch {\n const entries = await Promise.all(\n pids.map(async (pid) => {\n try {\n const output = await execFileText(\"pwdx\", [String(pid)]);\n const match = output.match(/^\\d+:\\s*(.+)$/);\n return match ? ([pid, match[1].trim()] as const) : null;\n } catch {\n return null;\n }\n }),\n );\n for (const entry of entries) {\n if (entry) result.set(entry[0], entry[1]);\n }\n return result;\n }\n}\n\nasync function batchGetProcessStartTimesAsync(pids: number[]): Promise<Map<number, Date>> {\n const result = new Map<number, Date>();\n if (pids.length === 0) return result;\n\n try {\n const output = await execFileText(\"ps\", [\"-o\", \"pid=,lstart=\", \"-p\", pids.join(\",\")]);\n for (const rawLine of output.split(\"\\n\")) {\n const match = rawLine.trim().match(/^(\\d+)\\s+(.+)$/);\n if (!match) continue;\n const pid = parseInt(match[1], 10);\n const date = new Date(match[2].trim());\n if (Number.isFinite(pid) && !Number.isNaN(date.getTime())) result.set(pid, date);\n }\n } catch {\n // Return partial/empty data, matching the synchronous helper.\n }\n return result;\n}\n\n/**\n * Capture and enrich relevant processes without blocking the event loop.\n * One base process listing is shared by every requested executable name.\n */\nexport async function captureProcessSnapshot(\n namePatterns: readonly string[],\n): Promise<ProcessInfo[]> {\n const names = normalizedProcessNames(\n namePatterns.filter((name) => Boolean(name) && VALID_EXECUTABLE_NAME.test(name)),\n );\n if (names.size === 0) return [];\n\n try {\n const output = await execFileText(\"ps\", [\"-axo\", \"pid=,ppid=,tty=,command=\"]);\n const processes = parseProcessList(output, names);\n const pids = processes.map((process) => process.pid);\n const [cwdMap, startTimeMap] = await Promise.all([\n batchGetProcessCwdsAsync(pids),\n batchGetProcessStartTimesAsync(pids),\n ]);\n return processes.map((process) => ({\n ...process,\n cwd: cwdMap.get(process.pid) || \"\",\n startTime: startTimeMap.get(process.pid),\n }));\n } catch {\n return [];\n }\n}\n\n/**\n * Batch-get current working directories for multiple PIDs.\n *\n * Single `lsof -a -d cwd -Fn -p PID1,PID2,...` call.\n * Returns partial results — if lsof fails for one PID, others still return.\n */\nexport function batchGetProcessCwds(pids: number[]): Map<number, string> {\n const result = new Map<number, string>();\n if (pids.length === 0) return result;\n\n try {\n const output = execFileSync(\"lsof\", [\"-a\", \"-d\", \"cwd\", \"-Fn\", \"-p\", pids.join(\",\")], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n\n // lsof output format: p{PID}\\nn{path}\\np{PID}\\nn{path}...\n let currentPid: number | null = null;\n for (const line of output.trim().split(\"\\n\")) {\n if (line.startsWith(\"p\")) {\n currentPid = parseInt(line.slice(1), 10);\n } else if (line.startsWith(\"n\") && currentPid !== null) {\n result.set(currentPid, line.slice(1));\n currentPid = null;\n }\n }\n } catch {\n // Try per-PID fallback with pwdx (Linux)\n for (const pid of pids) {\n try {\n const output = execFileSync(\"pwdx\", [String(pid)], {\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\n });\n const match = output.match(/^\\d+:\\s*(.+)$/);\n if (match) {\n result.set(pid, match[1].trim());\n }\n } catch {\n // Skip this PID\n }\n }\n }\n\n return result;\n}\n\n/**\n * Batch-get process start times for multiple PIDs.\n *\n * Single `ps -o pid=,lstart= -p PID1,PID2,...` call.\n * Uses lstart format which gives full timestamp (e.g., \"Thu Feb 5 16:00:57 2026\").\n * Returns partial results.\n */\nexport function batchGetProcessStartTimes(pids: number[]): Map<number, Date> {\n const result = new Map<number, Date>();\n if (pids.length === 0) return result;\n\n try {\n const output = execFileSync(\"ps\", [\"-o\", \"pid=,lstart=\", \"-p\", pids.join(\",\")], {\n encoding: \"utf-8\",\n });\n\n for (const rawLine of output.split(\"\\n\")) {\n const line = rawLine.trim();\n if (!line) continue;\n\n // Format: \" PID DAY MON DD HH:MM:SS YYYY\"\n // e.g., \" 78070 Wed Mar 18 23:18:01 2026\"\n const match = line.match(/^\\s*(\\d+)\\s+(.+)$/);\n if (!match) continue;\n\n const pid = parseInt(match[1], 10);\n const dateStr = match[2].trim();\n\n if (!Number.isFinite(pid)) continue;\n\n const date = new Date(dateStr);\n if (!Number.isNaN(date.getTime())) {\n result.set(pid, date);\n }\n }\n } catch {\n // Return whatever we have\n }\n\n return result;\n}\n\n/**\n * Enrich ProcessInfo array with cwd and startTime.\n *\n * Calls batchGetProcessCwds and batchGetProcessStartTimes in batched shell calls,\n * then populates each ProcessInfo in-place. Returns partial results —\n * if a PID fails, that process keeps empty cwd / undefined startTime.\n */\nexport function enrichProcesses(processes: ProcessInfo[]): ProcessInfo[] {\n if (processes.length === 0) return processes;\n\n const pids = processes.map((p) => p.pid);\n const cwdMap = batchGetProcessCwds(pids);\n const startTimeMap = batchGetProcessStartTimes(pids);\n\n for (const proc of processes) {\n proc.cwd = cwdMap.get(proc.pid) || \"\";\n proc.startTime = startTimeMap.get(proc.pid);\n }\n\n return processes;\n}\n\nfunction isSameTerminalProcess(proc: ProcessInfo, matched: ProcessInfo): boolean {\n const sameTty = proc.tty !== \"\" && proc.tty !== \"?\" && proc.tty === matched.tty;\n const sameCwd = proc.cwd !== \"\" && proc.cwd === matched.cwd;\n\n return sameTty && (sameCwd || proc.cwd === \"\" || matched.cwd === \"\");\n}\n\nfunction matchesProcessIdentity(proc: ProcessInfo, matched: ProcessInfo): boolean {\n return proc.pid === matched.pid || isSameTerminalProcess(proc, matched);\n}\n\nexport function findWrapperProcess(\n processes: ProcessInfo[],\n child: ProcessInfo,\n): ProcessInfo | undefined {\n return processes.find(\n (proc) =>\n proc.pid !== child.pid && child.ppid === proc.pid && matchesProcessIdentity(proc, child),\n );\n}\n\n/**\n * Find parent wrapper processes that should not be reported as separate agents.\n *\n * A process is considered a wrapper when it is the parent of another candidate\n * agent process in the same terminal/worktree, or when it points at the same\n * terminal/worktree as an already session-matched process.\n */\nexport function findWrapperProcessPids(\n processes: ProcessInfo[],\n matchedProcesses: ProcessInfo[] = [],\n): Set<number> {\n const wrappers = new Set<number>();\n\n for (const child of processes) {\n const wrapper = findWrapperProcess(processes, child);\n if (wrapper) {\n wrappers.add(wrapper.pid);\n }\n }\n\n for (const proc of processes) {\n if (\n matchedProcesses.some(\n (matched) => proc.pid !== matched.pid && isSameTerminalProcess(proc, matched),\n )\n ) {\n wrappers.add(proc.pid);\n }\n }\n\n return wrappers;\n}\n\n/**\n * Get the TTY device for a specific process\n */\nexport function getProcessTty(pid: number): string {\n try {\n const output = execFileSync(\"ps\", [\"-p\", String(pid), \"-o\", \"tty=\"], { encoding: \"utf-8\" });\n\n const tty = output.trim();\n return tty.startsWith(\"/dev/\") ? tty.slice(5) : tty;\n } catch {\n return \"?\";\n }\n}\n"],"names":["path","execFile","execFileSync","PROCESS_EXEC_MAX_BUFFER","VALID_EXECUTABLE_NAME","executableBasename","command","executable","trim","split","basename","replace","toLowerCase","normalizeExecutableName","name","lower","endsWith","slice","normalizedProcessNames","namePatterns","Set","filter","Boolean","map","filterByProcessNames","processes","names","size","process","has","listAgentProcesses","namePattern","test","output","encoding","line","match","pid","parseInt","ppid","Number","isNaN","tty","ttyShort","startsWith","push","cwd","execFileText","file","args","Promise","resolve","reject","maxBuffer","error","stdout","parseProcessList","base","normalizedBase","batchGetProcessCwdsAsync","pids","result","Map","length","join","currentPid","set","entries","all","String","entry","batchGetProcessStartTimesAsync","rawLine","date","Date","isFinite","getTime","captureProcessSnapshot","cwdMap","startTimeMap","get","startTime","batchGetProcessCwds","stdio","batchGetProcessStartTimes","dateStr","enrichProcesses","p","proc","isSameTerminalProcess","matched","sameTty","sameCwd","matchesProcessIdentity","findWrapperProcess","child","find","findWrapperProcessPids","matchedProcesses","wrappers","wrapper","add","some","getProcessTty"],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  * Utilities for discovering session files and their birth times.
5
5
  * Uses Node.js fs APIs to get birth timestamps without reading file contents.
6
6
  */
7
- import * as fs from 'fs';
7
+ import * as fs from "fs";
8
8
  /**
9
9
  * Represents a session file with its birth time metadata.
10
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IAEjB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IAEnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IAEpB,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,SAAS,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAwC3E"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/utils/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAGzB;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAElB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IAEjB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IAEnB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IAEpB,kGAAkG;IAClG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG,SAAS,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMjD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAwC3E"}
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Utilities for discovering session files and their birth times.
5
5
  * Uses Node.js fs APIs to get birth timestamps without reading file contents.
6
- */ import * as fs from 'fs';
7
- import * as path from 'path';
6
+ */ import * as fs from "fs";
7
+ import * as path from "path";
8
8
  /**
9
9
  * Check whether a path exists and is a directory.
10
10
  * Returns false on any error (missing path, permission denied, broken symlink, etc.).
@@ -27,7 +27,7 @@ import * as path from 'path';
27
27
  * raised.
28
28
  */ export function safeReadFile(filePath) {
29
29
  try {
30
- return fs.readFileSync(filePath, 'utf-8');
30
+ return fs.readFileSync(filePath, "utf-8");
31
31
  } catch {
32
32
  return undefined;
33
33
  }
@@ -47,7 +47,7 @@ import * as path from 'path';
47
47
  * List entries in a directory that end with `.jsonl`. Returns `[]` on
48
48
  * read errors. The result preserves directory order (no sorting).
49
49
  */ export function listJsonl(dir) {
50
- return safeReaddir(dir).filter((name)=>name.endsWith('.jsonl'));
50
+ return safeReaddir(dir).filter((name)=>name.endsWith(".jsonl"));
51
51
  }
52
52
  /**
53
53
  * Get birth times for .jsonl session files across multiple directories.
@@ -67,7 +67,7 @@ import * as path from 'path';
67
67
  continue;
68
68
  }
69
69
  for (const entry of entries){
70
- if (!entry.endsWith('.jsonl')) continue;
70
+ if (!entry.endsWith(".jsonl")) continue;
71
71
  const filePath = path.join(dir, entry);
72
72
  let birthtimeMs;
73
73
  try {
@@ -76,13 +76,13 @@ import * as path from 'path';
76
76
  continue;
77
77
  }
78
78
  if (!Number.isFinite(birthtimeMs) || birthtimeMs <= 0) continue;
79
- const sessionId = entry.replace(/\.jsonl$/, '');
79
+ const sessionId = entry.replace(/\.jsonl$/, "");
80
80
  results.push({
81
81
  sessionId,
82
82
  filePath,
83
83
  projectDir: dir,
84
84
  birthtimeMs,
85
- resolvedCwd: ''
85
+ resolvedCwd: ""
86
86
  });
87
87
  }
88
88
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/session.ts"],"sourcesContent":["/**\n * Session File Utilities\n *\n * Utilities for discovering session files and their birth times.\n * Uses Node.js fs APIs to get birth timestamps without reading file contents.\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Represents a session file with its birth time metadata.\n */\nexport interface SessionFile {\n /** Session identifier (filename without .jsonl extension) */\n sessionId: string;\n\n /** Full path to the session file */\n filePath: string;\n\n /** Parent directory of the session file */\n projectDir: string;\n\n /** File creation time in milliseconds since epoch */\n birthtimeMs: number;\n\n /** CWD this session maps to — set by the adapter after calling batchGetSessionFileBirthtimes() */\n resolvedCwd: string;\n}\n\n/**\n * Check whether a path exists and is a directory.\n * Returns false on any error (missing path, permission denied, broken symlink, etc.).\n */\nexport function isDirectory(p: string): boolean {\n return safeStat(p)?.isDirectory() ?? false;\n}\n\n/**\n * `fs.statSync` that swallows errors and returns `undefined` on failure.\n * Callers can pull whichever fields they need (mtime, birthtime, ...).\n */\nexport function safeStat(filePath: string): fs.Stats | undefined {\n try {\n return fs.statSync(filePath);\n } catch {\n return undefined;\n }\n}\n\n/**\n * `fs.readFileSync` (utf-8) that swallows errors and returns `undefined`\n * on failure. Use when an unreadable file should be skipped rather than\n * raised.\n */\nexport function safeReadFile(filePath: string): string | undefined {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return undefined;\n }\n}\n\n/**\n * `fs.readdirSync` that swallows errors and returns `[]` on failure.\n * Useful when walking optional/transient directories where missing or\n * unreadable entries should be skipped silently.\n */\nexport function safeReaddir(dir: string): string[] {\n try {\n return fs.readdirSync(dir);\n } catch {\n return [];\n }\n}\n\n/**\n * List entries in a directory that end with `.jsonl`. Returns `[]` on\n * read errors. The result preserves directory order (no sorting).\n */\nexport function listJsonl(dir: string): string[] {\n return safeReaddir(dir).filter((name) => name.endsWith('.jsonl'));\n}\n\n/**\n * Get birth times for .jsonl session files across multiple directories.\n *\n * Enumerates each directory with readdirSync and stats each .jsonl file\n * to get its birth time. No shell commands are used.\n * Returns empty array if no directories have .jsonl files or reads fail.\n * resolvedCwd is left empty — the adapter must set it.\n */\nexport function batchGetSessionFileBirthtimes(dirs: string[]): SessionFile[] {\n if (dirs.length === 0) return [];\n\n const results: SessionFile[] = [];\n\n for (const dir of dirs) {\n let entries: string[];\n try {\n entries = fs.readdirSync(dir);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.endsWith('.jsonl')) continue;\n\n const filePath = path.join(dir, entry);\n\n let birthtimeMs: number;\n try {\n birthtimeMs = fs.statSync(filePath).birthtimeMs;\n } catch {\n continue;\n }\n\n if (!Number.isFinite(birthtimeMs) || birthtimeMs <= 0) continue;\n\n const sessionId = entry.replace(/\\.jsonl$/, '');\n\n results.push({\n sessionId,\n filePath,\n projectDir: dir,\n birthtimeMs,\n resolvedCwd: '',\n });\n }\n }\n\n return results;\n}\n"],"names":["fs","path","isDirectory","p","safeStat","filePath","statSync","undefined","safeReadFile","readFileSync","safeReaddir","dir","readdirSync","listJsonl","filter","name","endsWith","batchGetSessionFileBirthtimes","dirs","length","results","entries","entry","join","birthtimeMs","Number","isFinite","sessionId","replace","push","projectDir","resolvedCwd"],"mappings":"AAAA;;;;;CAKC,GAED,YAAYA,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAsB7B;;;CAGC,GACD,OAAO,SAASC,YAAYC,CAAS;IACjC,OAAOC,SAASD,IAAID,iBAAiB;AACzC;AAEA;;;CAGC,GACD,OAAO,SAASE,SAASC,QAAgB;IACrC,IAAI;QACA,OAAOL,GAAGM,QAAQ,CAACD;IACvB,EAAE,OAAM;QACJ,OAAOE;IACX;AACJ;AAEA;;;;CAIC,GACD,OAAO,SAASC,aAAaH,QAAgB;IACzC,IAAI;QACA,OAAOL,GAAGS,YAAY,CAACJ,UAAU;IACrC,EAAE,OAAM;QACJ,OAAOE;IACX;AACJ;AAEA;;;;CAIC,GACD,OAAO,SAASG,YAAYC,GAAW;IACnC,IAAI;QACA,OAAOX,GAAGY,WAAW,CAACD;IAC1B,EAAE,OAAM;QACJ,OAAO,EAAE;IACb;AACJ;AAEA;;;CAGC,GACD,OAAO,SAASE,UAAUF,GAAW;IACjC,OAAOD,YAAYC,KAAKG,MAAM,CAAC,CAACC,OAASA,KAAKC,QAAQ,CAAC;AAC3D;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,8BAA8BC,IAAc;IACxD,IAAIA,KAAKC,MAAM,KAAK,GAAG,OAAO,EAAE;IAEhC,MAAMC,UAAyB,EAAE;IAEjC,KAAK,MAAMT,OAAOO,KAAM;QACpB,IAAIG;QACJ,IAAI;YACAA,UAAUrB,GAAGY,WAAW,CAACD;QAC7B,EAAE,OAAM;YACJ;QACJ;QAEA,KAAK,MAAMW,SAASD,QAAS;YACzB,IAAI,CAACC,MAAMN,QAAQ,CAAC,WAAW;YAE/B,MAAMX,WAAWJ,KAAKsB,IAAI,CAACZ,KAAKW;YAEhC,IAAIE;YACJ,IAAI;gBACAA,cAAcxB,GAAGM,QAAQ,CAACD,UAAUmB,WAAW;YACnD,EAAE,OAAM;gBACJ;YACJ;YAEA,IAAI,CAACC,OAAOC,QAAQ,CAACF,gBAAgBA,eAAe,GAAG;YAEvD,MAAMG,YAAYL,MAAMM,OAAO,CAAC,YAAY;YAE5CR,QAAQS,IAAI,CAAC;gBACTF;gBACAtB;gBACAyB,YAAYnB;gBACZa;gBACAO,aAAa;YACjB;QACJ;IACJ;IAEA,OAAOX;AACX"}
1
+ {"version":3,"sources":["../../src/utils/session.ts"],"sourcesContent":["/**\n * Session File Utilities\n *\n * Utilities for discovering session files and their birth times.\n * Uses Node.js fs APIs to get birth timestamps without reading file contents.\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\n\n/**\n * Represents a session file with its birth time metadata.\n */\nexport interface SessionFile {\n /** Session identifier (filename without .jsonl extension) */\n sessionId: string;\n\n /** Full path to the session file */\n filePath: string;\n\n /** Parent directory of the session file */\n projectDir: string;\n\n /** File creation time in milliseconds since epoch */\n birthtimeMs: number;\n\n /** CWD this session maps to — set by the adapter after calling batchGetSessionFileBirthtimes() */\n resolvedCwd: string;\n}\n\n/**\n * Check whether a path exists and is a directory.\n * Returns false on any error (missing path, permission denied, broken symlink, etc.).\n */\nexport function isDirectory(p: string): boolean {\n return safeStat(p)?.isDirectory() ?? false;\n}\n\n/**\n * `fs.statSync` that swallows errors and returns `undefined` on failure.\n * Callers can pull whichever fields they need (mtime, birthtime, ...).\n */\nexport function safeStat(filePath: string): fs.Stats | undefined {\n try {\n return fs.statSync(filePath);\n } catch {\n return undefined;\n }\n}\n\n/**\n * `fs.readFileSync` (utf-8) that swallows errors and returns `undefined`\n * on failure. Use when an unreadable file should be skipped rather than\n * raised.\n */\nexport function safeReadFile(filePath: string): string | undefined {\n try {\n return fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\n/**\n * `fs.readdirSync` that swallows errors and returns `[]` on failure.\n * Useful when walking optional/transient directories where missing or\n * unreadable entries should be skipped silently.\n */\nexport function safeReaddir(dir: string): string[] {\n try {\n return fs.readdirSync(dir);\n } catch {\n return [];\n }\n}\n\n/**\n * List entries in a directory that end with `.jsonl`. Returns `[]` on\n * read errors. The result preserves directory order (no sorting).\n */\nexport function listJsonl(dir: string): string[] {\n return safeReaddir(dir).filter((name) => name.endsWith(\".jsonl\"));\n}\n\n/**\n * Get birth times for .jsonl session files across multiple directories.\n *\n * Enumerates each directory with readdirSync and stats each .jsonl file\n * to get its birth time. No shell commands are used.\n * Returns empty array if no directories have .jsonl files or reads fail.\n * resolvedCwd is left empty — the adapter must set it.\n */\nexport function batchGetSessionFileBirthtimes(dirs: string[]): SessionFile[] {\n if (dirs.length === 0) return [];\n\n const results: SessionFile[] = [];\n\n for (const dir of dirs) {\n let entries: string[];\n try {\n entries = fs.readdirSync(dir);\n } catch {\n continue;\n }\n\n for (const entry of entries) {\n if (!entry.endsWith(\".jsonl\")) continue;\n\n const filePath = path.join(dir, entry);\n\n let birthtimeMs: number;\n try {\n birthtimeMs = fs.statSync(filePath).birthtimeMs;\n } catch {\n continue;\n }\n\n if (!Number.isFinite(birthtimeMs) || birthtimeMs <= 0) continue;\n\n const sessionId = entry.replace(/\\.jsonl$/, \"\");\n\n results.push({\n sessionId,\n filePath,\n projectDir: dir,\n birthtimeMs,\n resolvedCwd: \"\",\n });\n }\n }\n\n return results;\n}\n"],"names":["fs","path","isDirectory","p","safeStat","filePath","statSync","undefined","safeReadFile","readFileSync","safeReaddir","dir","readdirSync","listJsonl","filter","name","endsWith","batchGetSessionFileBirthtimes","dirs","length","results","entries","entry","join","birthtimeMs","Number","isFinite","sessionId","replace","push","projectDir","resolvedCwd"],"mappings":"AAAA;;;;;CAKC,GAED,YAAYA,QAAQ,KAAK;AACzB,YAAYC,UAAU,OAAO;AAsB7B;;;CAGC,GACD,OAAO,SAASC,YAAYC,CAAS;IACnC,OAAOC,SAASD,IAAID,iBAAiB;AACvC;AAEA;;;CAGC,GACD,OAAO,SAASE,SAASC,QAAgB;IACvC,IAAI;QACF,OAAOL,GAAGM,QAAQ,CAACD;IACrB,EAAE,OAAM;QACN,OAAOE;IACT;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASC,aAAaH,QAAgB;IAC3C,IAAI;QACF,OAAOL,GAAGS,YAAY,CAACJ,UAAU;IACnC,EAAE,OAAM;QACN,OAAOE;IACT;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASG,YAAYC,GAAW;IACrC,IAAI;QACF,OAAOX,GAAGY,WAAW,CAACD;IACxB,EAAE,OAAM;QACN,OAAO,EAAE;IACX;AACF;AAEA;;;CAGC,GACD,OAAO,SAASE,UAAUF,GAAW;IACnC,OAAOD,YAAYC,KAAKG,MAAM,CAAC,CAACC,OAASA,KAAKC,QAAQ,CAAC;AACzD;AAEA;;;;;;;CAOC,GACD,OAAO,SAASC,8BAA8BC,IAAc;IAC1D,IAAIA,KAAKC,MAAM,KAAK,GAAG,OAAO,EAAE;IAEhC,MAAMC,UAAyB,EAAE;IAEjC,KAAK,MAAMT,OAAOO,KAAM;QACtB,IAAIG;QACJ,IAAI;YACFA,UAAUrB,GAAGY,WAAW,CAACD;QAC3B,EAAE,OAAM;YACN;QACF;QAEA,KAAK,MAAMW,SAASD,QAAS;YAC3B,IAAI,CAACC,MAAMN,QAAQ,CAAC,WAAW;YAE/B,MAAMX,WAAWJ,KAAKsB,IAAI,CAACZ,KAAKW;YAEhC,IAAIE;YACJ,IAAI;gBACFA,cAAcxB,GAAGM,QAAQ,CAACD,UAAUmB,WAAW;YACjD,EAAE,OAAM;gBACN;YACF;YAEA,IAAI,CAACC,OAAOC,QAAQ,CAACF,gBAAgBA,eAAe,GAAG;YAEvD,MAAMG,YAAYL,MAAMM,OAAO,CAAC,YAAY;YAE5CR,QAAQS,IAAI,CAAC;gBACXF;gBACAtB;gBACAyB,YAAYnB;gBACZa;gBACAO,aAAa;YACf;QACF;IACF;IAEA,OAAOX;AACT"}
@@ -1,4 +1,4 @@
1
- import { type AgentInfo } from '../adapters/AgentAdapter.js';
2
- export type AgentSortKey = 'name' | 'status' | 'pid' | 'lastActive';
1
+ import { type AgentInfo } from "../adapters/AgentAdapter.js";
2
+ export type AgentSortKey = "name" | "status" | "pid" | "lastActive";
3
3
  export declare function sortAgents(agents: AgentInfo[], by: AgentSortKey): AgentInfo[];
4
4
  //# sourceMappingURL=sortAgents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sortAgents.d.ts","sourceRoot":"","sources":["../../src/utils/sortAgents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE1E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC;AAgCpE,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,YAAY,GAAG,SAAS,EAAE,CAiB7E"}
1
+ {"version":3,"file":"sortAgents.d.ts","sourceRoot":"","sources":["../../src/utils/sortAgents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE1E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,YAAY,CAAC;AAkCpE,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,YAAY,GAAG,SAAS,EAAE,CAiB7E"}