@ai-devkit/agent-manager 0.35.0 → 0.37.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 (651) hide show
  1. package/dist/AgentManager.d.ts +9 -4
  2. package/dist/AgentManager.d.ts.map +1 -1
  3. package/dist/AgentManager.js +21 -2
  4. package/dist/AgentManager.js.map +1 -1
  5. package/dist/__tests__/AgentManager.test.js +151 -3
  6. package/dist/__tests__/AgentManager.test.js.map +1 -1
  7. package/dist/__tests__/adapters/IncrementalSessionRefresh.test.js +486 -0
  8. package/dist/__tests__/adapters/IncrementalSessionRefresh.test.js.map +1 -0
  9. package/dist/__tests__/adapters/adapterProcessImports.test.js +52 -0
  10. package/dist/__tests__/adapters/adapterProcessImports.test.js.map +1 -0
  11. package/dist/__tests__/adapters/adapterSnapshotCandidates.test.js +247 -0
  12. package/dist/__tests__/adapters/adapterSnapshotCandidates.test.js.map +1 -0
  13. package/dist/__tests__/capacity/claude.test.js +485 -0
  14. package/dist/__tests__/capacity/claude.test.js.map +1 -0
  15. package/dist/__tests__/capacity/openai.test.js +670 -0
  16. package/dist/__tests__/capacity/openai.test.js.map +1 -0
  17. package/dist/__tests__/capacity/wham.test.js +144 -0
  18. package/dist/__tests__/capacity/wham.test.js.map +1 -0
  19. package/dist/__tests__/harnesses/BoundedSummarySkip.test.js +568 -0
  20. package/dist/__tests__/harnesses/BoundedSummarySkip.test.js.map +1 -0
  21. package/dist/__tests__/harnesses/SessionSummaryEquivalence.test.js +1089 -0
  22. package/dist/__tests__/harnesses/SessionSummaryEquivalence.test.js.map +1 -0
  23. package/dist/__tests__/harnesses/antigravity/AntigravityCliAdapter.subprocess.test.js +143 -0
  24. package/dist/__tests__/harnesses/antigravity/AntigravityCliAdapter.subprocess.test.js.map +1 -0
  25. package/dist/__tests__/harnesses/antigravity/AntigravityCliAdapter.test.js +462 -0
  26. package/dist/__tests__/harnesses/antigravity/AntigravityCliAdapter.test.js.map +1 -0
  27. package/dist/__tests__/harnesses/builtinAdapters.test.js +33 -0
  28. package/dist/__tests__/harnesses/builtinAdapters.test.js.map +1 -0
  29. package/dist/__tests__/{providers → harnesses}/claude/ClaudeAgentMapper.test.js +4 -4
  30. package/dist/__tests__/harnesses/claude/ClaudeAgentMapper.test.js.map +1 -0
  31. package/dist/__tests__/{adapters → harnesses/claude}/ClaudeCodeAdapter.test.js +47 -19
  32. package/dist/__tests__/harnesses/claude/ClaudeCodeAdapter.test.js.map +1 -0
  33. package/dist/__tests__/{providers → harnesses}/claude/ClaudeSessionLocator.test.js +1 -12
  34. package/dist/__tests__/{providers → harnesses}/claude/ClaudeSessionLocator.test.js.map +1 -1
  35. package/dist/__tests__/{utils → harnesses/claude}/ClaudeSessionParser.test.js +2 -2
  36. package/dist/__tests__/harnesses/claude/ClaudeSessionParser.test.js.map +1 -0
  37. package/dist/__tests__/{print → harnesses/claude/durable}/ClaudeCliProbe.test.js +1 -1
  38. package/dist/__tests__/harnesses/claude/durable/ClaudeCliProbe.test.js.map +1 -0
  39. package/dist/__tests__/{print → harnesses/claude/durable}/ClaudePrintAgent.integration.test.js +1 -1
  40. package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgent.integration.test.js.map +1 -0
  41. package/dist/__tests__/{print → harnesses/claude/durable}/ClaudePrintAgentService.test.js +4 -4
  42. package/dist/__tests__/harnesses/claude/durable/ClaudePrintAgentService.test.js.map +1 -0
  43. package/dist/__tests__/{print → harnesses/claude/durable}/ClaudePrintRunner.test.js +1 -1
  44. package/dist/__tests__/harnesses/claude/durable/ClaudePrintRunner.test.js.map +1 -0
  45. package/dist/__tests__/{adapters → harnesses/codex}/CodexAdapter.test.js +304 -10
  46. package/dist/__tests__/harnesses/codex/CodexAdapter.test.js.map +1 -0
  47. package/dist/__tests__/harnesses/codex/CodexSessionLocator.test.js +463 -0
  48. package/dist/__tests__/harnesses/codex/CodexSessionLocator.test.js.map +1 -0
  49. package/dist/__tests__/{providers → harnesses}/codex/CodexSessionMapping.test.js +1 -1
  50. package/dist/__tests__/{providers → harnesses}/codex/CodexSessionMapping.test.js.map +1 -1
  51. package/dist/__tests__/{providers → harnesses}/codex/CodexSessionParser.test.js +1 -1
  52. package/dist/__tests__/{providers → harnesses}/codex/CodexSessionParser.test.js.map +1 -1
  53. package/dist/__tests__/{durable → harnesses/codex/durable}/CodexCliProbe.test.js +4 -4
  54. package/dist/__tests__/harnesses/codex/durable/CodexCliProbe.test.js.map +1 -0
  55. package/dist/__tests__/{durable → harnesses/codex/durable}/CodexDurableAgentRepository.test.js +1 -1
  56. package/dist/__tests__/harnesses/codex/durable/CodexDurableAgentRepository.test.js.map +1 -0
  57. package/dist/__tests__/{durable → harnesses/codex/durable}/CodexPrintAgent.integration.test.js +1 -1
  58. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgent.integration.test.js.map +1 -0
  59. package/dist/__tests__/{durable → harnesses/codex/durable}/CodexPrintAgentService.test.js +8 -18
  60. package/dist/__tests__/harnesses/codex/durable/CodexPrintAgentService.test.js.map +1 -0
  61. package/dist/__tests__/{durable → harnesses/codex/durable}/CodexPrintRunner.test.js +2 -7
  62. package/dist/__tests__/harnesses/codex/durable/CodexPrintRunner.test.js.map +1 -0
  63. package/dist/__tests__/{providers → harnesses}/copilot/CopilotAdapter.test.js +1 -1
  64. package/dist/__tests__/{providers → harnesses}/copilot/CopilotAdapter.test.js.map +1 -1
  65. package/dist/__tests__/harnesses/copilot/CopilotRefreshIO.test.js +290 -0
  66. package/dist/__tests__/harnesses/copilot/CopilotRefreshIO.test.js.map +1 -0
  67. package/dist/__tests__/{providers → harnesses}/gemini/GeminiCliAdapter.test.js +34 -25
  68. package/dist/__tests__/harnesses/gemini/GeminiCliAdapter.test.js.map +1 -0
  69. package/dist/__tests__/harnesses/gemini/GeminiSessionJsonl.test.js +491 -0
  70. package/dist/__tests__/harnesses/gemini/GeminiSessionJsonl.test.js.map +1 -0
  71. package/dist/__tests__/harnesses/gemini/GeminiSessionLocator.test.js +399 -0
  72. package/dist/__tests__/harnesses/gemini/GeminiSessionLocator.test.js.map +1 -0
  73. package/dist/__tests__/{providers → harnesses}/grok/GrokAgentMapper.test.js +1 -1
  74. package/dist/__tests__/{providers → harnesses}/grok/GrokAgentMapper.test.js.map +1 -1
  75. package/dist/__tests__/{providers → harnesses}/grok/GrokCliAdapter.test.js +1 -1
  76. package/dist/__tests__/{providers → harnesses}/grok/GrokCliAdapter.test.js.map +1 -1
  77. package/dist/__tests__/harnesses/grok/GrokIncrementalRefresh.test.js +167 -0
  78. package/dist/__tests__/harnesses/grok/GrokIncrementalRefresh.test.js.map +1 -0
  79. package/dist/__tests__/{providers → harnesses}/grok/GrokSessionLocator.test.js +1 -1
  80. package/dist/__tests__/{providers → harnesses}/grok/GrokSessionLocator.test.js.map +1 -1
  81. package/dist/__tests__/harnesses/grok/GrokSessionParser.test.js +301 -0
  82. package/dist/__tests__/harnesses/grok/GrokSessionParser.test.js.map +1 -0
  83. package/dist/__tests__/harnesses/kiro/KiroAdapter.test.js +662 -0
  84. package/dist/__tests__/harnesses/kiro/KiroAdapter.test.js.map +1 -0
  85. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeAdapter.test.js +1 -1
  86. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeAdapter.test.js.map +1 -1
  87. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeAgentMapper.test.js +1 -1
  88. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeAgentMapper.test.js.map +1 -1
  89. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeSessionLocator.test.js +2 -2
  90. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeSessionLocator.test.js.map +1 -1
  91. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeSessionParser.test.js +1 -1
  92. package/dist/__tests__/{providers → harnesses}/opencode/OpenCodeSessionParser.test.js.map +1 -1
  93. package/dist/__tests__/{providers → harnesses}/pi/PiAdapter.test.js +1 -1
  94. package/dist/__tests__/{providers → harnesses}/pi/PiAdapter.test.js.map +1 -1
  95. package/dist/__tests__/harnesses/pi/PiDiscoveryIO.test.js +382 -0
  96. package/dist/__tests__/harnesses/pi/PiDiscoveryIO.test.js.map +1 -0
  97. package/dist/__tests__/{providers → harnesses}/pi/PiSessionParser.test.js +171 -1
  98. package/dist/__tests__/harnesses/pi/PiSessionParser.test.js.map +1 -0
  99. package/dist/__tests__/{providers → harnesses}/pi/PiSessionTracker.test.js +1 -1
  100. package/dist/__tests__/{providers → harnesses}/pi/PiSessionTracker.test.js.map +1 -1
  101. package/dist/__tests__/{providers → harnesses}/pi/durable/PiCliProbe.test.js.map +1 -1
  102. package/dist/__tests__/{providers → harnesses}/pi/durable/PiDurableAgentRepository.test.js.map +1 -1
  103. package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintAgentService.test.js.map +1 -1
  104. package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintProtocol.test.js +1 -1
  105. package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintProtocol.test.js.map +1 -1
  106. package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintRunner.test.js.map +1 -1
  107. package/dist/__tests__/{providers → harnesses}/pi/durable/PiStreamParser.test.js +1 -1
  108. package/dist/__tests__/{providers → harnesses}/pi/durable/PiStreamParser.test.js.map +1 -1
  109. package/dist/__tests__/readiness/AgentReadiness.test.js +20 -0
  110. package/dist/__tests__/readiness/AgentReadiness.test.js.map +1 -1
  111. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js +49 -0
  112. package/dist/__tests__/runtime/ManagedAgentRuntime.test.js.map +1 -1
  113. package/dist/__tests__/utils/IncrementalJsonlSummary.test.js +650 -0
  114. package/dist/__tests__/utils/IncrementalJsonlSummary.test.js.map +1 -0
  115. package/dist/__tests__/utils/agents.test.js +72 -2
  116. package/dist/__tests__/utils/agents.test.js.map +1 -1
  117. package/dist/__tests__/utils/conversationTail.bench.test.js +258 -0
  118. package/dist/__tests__/utils/conversationTail.bench.test.js.map +1 -0
  119. package/dist/__tests__/utils/conversationTailParity.test.js +588 -0
  120. package/dist/__tests__/utils/conversationTailParity.test.js.map +1 -0
  121. package/dist/__tests__/utils/jsonlTail.test.js +360 -0
  122. package/dist/__tests__/utils/jsonlTail.test.js.map +1 -0
  123. package/dist/__tests__/utils/matchingConstants.test.js +35 -0
  124. package/dist/__tests__/utils/matchingConstants.test.js.map +1 -0
  125. package/dist/__tests__/utils/process.test.js +436 -2
  126. package/dist/__tests__/utils/process.test.js.map +1 -1
  127. package/dist/adapters/AgentAdapter.d.ts +25 -6
  128. package/dist/adapters/AgentAdapter.d.ts.map +1 -1
  129. package/dist/adapters/AgentAdapter.js +12 -3
  130. package/dist/adapters/AgentAdapter.js.map +1 -1
  131. package/dist/capacity/claude.d.ts +17 -0
  132. package/dist/capacity/claude.d.ts.map +1 -0
  133. package/dist/capacity/claude.js +271 -0
  134. package/dist/capacity/claude.js.map +1 -0
  135. package/dist/capacity/codex.d.ts +1 -2
  136. package/dist/capacity/codex.d.ts.map +1 -1
  137. package/dist/capacity/codex.js +5 -47
  138. package/dist/capacity/codex.js.map +1 -1
  139. package/dist/capacity/index.d.ts +11 -0
  140. package/dist/capacity/index.d.ts.map +1 -1
  141. package/dist/capacity/index.js +17 -0
  142. package/dist/capacity/index.js.map +1 -1
  143. package/dist/capacity/openai.d.ts +47 -0
  144. package/dist/capacity/openai.d.ts.map +1 -0
  145. package/dist/capacity/openai.js +307 -0
  146. package/dist/capacity/openai.js.map +1 -0
  147. package/dist/capacity/wham.d.ts +16 -0
  148. package/dist/capacity/wham.d.ts.map +1 -0
  149. package/dist/capacity/wham.js +66 -0
  150. package/dist/capacity/wham.js.map +1 -0
  151. package/dist/harnesses/antigravity/AntigravityAgentMapper.d.ts +13 -0
  152. package/dist/harnesses/antigravity/AntigravityAgentMapper.d.ts.map +1 -0
  153. package/dist/harnesses/antigravity/AntigravityAgentMapper.js +30 -0
  154. package/dist/harnesses/antigravity/AntigravityAgentMapper.js.map +1 -0
  155. package/dist/harnesses/antigravity/AntigravityCliAdapter.d.ts +32 -0
  156. package/dist/harnesses/antigravity/AntigravityCliAdapter.d.ts.map +1 -0
  157. package/dist/harnesses/antigravity/AntigravityCliAdapter.js +97 -0
  158. package/dist/harnesses/antigravity/AntigravityCliAdapter.js.map +1 -0
  159. package/dist/harnesses/antigravity/AntigravitySessionLocator.d.ts +30 -0
  160. package/dist/harnesses/antigravity/AntigravitySessionLocator.d.ts.map +1 -0
  161. package/dist/harnesses/antigravity/AntigravitySessionLocator.js +56 -0
  162. package/dist/harnesses/antigravity/AntigravitySessionLocator.js.map +1 -0
  163. package/dist/harnesses/antigravity/AntigravitySessionParser.d.ts +75 -0
  164. package/dist/harnesses/antigravity/AntigravitySessionParser.d.ts.map +1 -0
  165. package/dist/harnesses/antigravity/AntigravitySessionParser.js +174 -0
  166. package/dist/harnesses/antigravity/AntigravitySessionParser.js.map +1 -0
  167. package/dist/{providers → harnesses}/claude/ClaudeAgentMapper.d.ts.map +1 -1
  168. package/dist/{providers → harnesses}/claude/ClaudeAgentMapper.js +4 -10
  169. package/dist/harnesses/claude/ClaudeAgentMapper.js.map +1 -0
  170. package/dist/{providers → harnesses}/claude/ClaudeCodeAdapter.d.ts +5 -6
  171. package/dist/harnesses/claude/ClaudeCodeAdapter.d.ts.map +1 -0
  172. package/dist/{providers → harnesses}/claude/ClaudeCodeAdapter.js +17 -15
  173. package/dist/harnesses/claude/ClaudeCodeAdapter.js.map +1 -0
  174. package/dist/{providers → harnesses}/claude/ClaudeSessionLocator.d.ts.map +1 -1
  175. package/dist/{providers → harnesses}/claude/ClaudeSessionLocator.js +3 -3
  176. package/dist/harnesses/claude/ClaudeSessionLocator.js.map +1 -0
  177. package/dist/{providers → harnesses}/claude/ClaudeSessionParser.d.ts +40 -6
  178. package/dist/harnesses/claude/ClaudeSessionParser.d.ts.map +1 -0
  179. package/dist/{providers → harnesses}/claude/ClaudeSessionParser.js +141 -85
  180. package/dist/harnesses/claude/ClaudeSessionParser.js.map +1 -0
  181. package/dist/{providers → harnesses}/claude/durable/ClaudeCliProbe.d.ts.map +1 -1
  182. package/dist/{providers → harnesses}/claude/durable/ClaudeCliProbe.js.map +1 -1
  183. package/dist/{providers → harnesses}/claude/durable/ClaudePrintAgentService.d.ts.map +1 -1
  184. package/dist/{providers → harnesses}/claude/durable/ClaudePrintAgentService.js.map +1 -1
  185. package/dist/{providers → harnesses}/claude/durable/ClaudePrintRunner.d.ts.map +1 -1
  186. package/dist/{providers → harnesses}/claude/durable/ClaudePrintRunner.js.map +1 -1
  187. package/dist/{providers → harnesses}/claude/durable/ClaudeStreamParser.d.ts.map +1 -1
  188. package/dist/{providers → harnesses}/claude/durable/ClaudeStreamParser.js.map +1 -1
  189. package/dist/{providers → harnesses}/codex/CodexAdapter.d.ts +5 -4
  190. package/dist/harnesses/codex/CodexAdapter.d.ts.map +1 -0
  191. package/dist/{providers → harnesses}/codex/CodexAdapter.js +139 -19
  192. package/dist/harnesses/codex/CodexAdapter.js.map +1 -0
  193. package/dist/{providers → harnesses}/codex/CodexAgentMapper.d.ts.map +1 -1
  194. package/dist/{providers → harnesses}/codex/CodexAgentMapper.js +4 -11
  195. package/dist/harnesses/codex/CodexAgentMapper.js.map +1 -0
  196. package/dist/harnesses/codex/CodexSessionLocator.d.ts +74 -0
  197. package/dist/harnesses/codex/CodexSessionLocator.d.ts.map +1 -0
  198. package/dist/harnesses/codex/CodexSessionLocator.js +359 -0
  199. package/dist/harnesses/codex/CodexSessionLocator.js.map +1 -0
  200. package/dist/{providers → harnesses}/codex/CodexSessionMapping.d.ts.map +1 -1
  201. package/dist/{providers → harnesses}/codex/CodexSessionMapping.js +3 -3
  202. package/dist/harnesses/codex/CodexSessionMapping.js.map +1 -0
  203. package/dist/harnesses/codex/CodexSessionParser.d.ts +89 -0
  204. package/dist/harnesses/codex/CodexSessionParser.d.ts.map +1 -0
  205. package/dist/{providers → harnesses}/codex/CodexSessionParser.js +124 -78
  206. package/dist/harnesses/codex/CodexSessionParser.js.map +1 -0
  207. package/dist/{providers → harnesses}/codex/durable/CodexCliProbe.d.ts.map +1 -1
  208. package/dist/{providers → harnesses}/codex/durable/CodexCliProbe.js.map +1 -1
  209. package/dist/{providers → harnesses}/codex/durable/CodexPrintAgentService.d.ts.map +1 -1
  210. package/dist/{providers → harnesses}/codex/durable/CodexPrintAgentService.js.map +1 -1
  211. package/dist/{providers → harnesses}/codex/durable/CodexPrintRunner.d.ts.map +1 -1
  212. package/dist/{providers → harnesses}/codex/durable/CodexPrintRunner.js.map +1 -1
  213. package/dist/{providers → harnesses}/codex/durable/CodexStreamParser.d.ts.map +1 -1
  214. package/dist/{providers → harnesses}/codex/durable/CodexStreamParser.js.map +1 -1
  215. package/dist/{providers → harnesses}/copilot/CopilotAdapter.d.ts +7 -6
  216. package/dist/harnesses/copilot/CopilotAdapter.d.ts.map +1 -0
  217. package/dist/{providers → harnesses}/copilot/CopilotAdapter.js +19 -14
  218. package/dist/harnesses/copilot/CopilotAdapter.js.map +1 -0
  219. package/dist/{providers → harnesses}/copilot/CopilotAgentMapper.d.ts.map +1 -1
  220. package/dist/{providers → harnesses}/copilot/CopilotAgentMapper.js +4 -11
  221. package/dist/harnesses/copilot/CopilotAgentMapper.js.map +1 -0
  222. package/dist/harnesses/copilot/CopilotSessionLocator.d.ts +42 -0
  223. package/dist/harnesses/copilot/CopilotSessionLocator.d.ts.map +1 -0
  224. package/dist/harnesses/copilot/CopilotSessionLocator.js +126 -0
  225. package/dist/harnesses/copilot/CopilotSessionLocator.js.map +1 -0
  226. package/dist/harnesses/copilot/CopilotSessionParser.d.ts +62 -0
  227. package/dist/harnesses/copilot/CopilotSessionParser.d.ts.map +1 -0
  228. package/dist/harnesses/copilot/CopilotSessionParser.js +236 -0
  229. package/dist/harnesses/copilot/CopilotSessionParser.js.map +1 -0
  230. package/dist/{providers → harnesses}/gemini/GeminiAgentMapper.d.ts.map +1 -1
  231. package/dist/{providers → harnesses}/gemini/GeminiAgentMapper.js +4 -11
  232. package/dist/harnesses/gemini/GeminiAgentMapper.js.map +1 -0
  233. package/dist/{providers → harnesses}/gemini/GeminiCliAdapter.d.ts +4 -5
  234. package/dist/harnesses/gemini/GeminiCliAdapter.d.ts.map +1 -0
  235. package/dist/{providers → harnesses}/gemini/GeminiCliAdapter.js +6 -7
  236. package/dist/harnesses/gemini/GeminiCliAdapter.js.map +1 -0
  237. package/dist/harnesses/gemini/GeminiSessionLocator.d.ts +72 -0
  238. package/dist/harnesses/gemini/GeminiSessionLocator.d.ts.map +1 -0
  239. package/dist/harnesses/gemini/GeminiSessionLocator.js +300 -0
  240. package/dist/harnesses/gemini/GeminiSessionLocator.js.map +1 -0
  241. package/dist/{providers → harnesses}/gemini/GeminiSessionParser.d.ts +34 -7
  242. package/dist/harnesses/gemini/GeminiSessionParser.d.ts.map +1 -0
  243. package/dist/harnesses/gemini/GeminiSessionParser.js +272 -0
  244. package/dist/harnesses/gemini/GeminiSessionParser.js.map +1 -0
  245. package/dist/harnesses/gemini/fileSignature.d.ts +8 -0
  246. package/dist/harnesses/gemini/fileSignature.d.ts.map +1 -0
  247. package/dist/harnesses/gemini/fileSignature.js +9 -0
  248. package/dist/harnesses/gemini/fileSignature.js.map +1 -0
  249. package/dist/{providers → harnesses}/grok/GrokAgentMapper.d.ts.map +1 -1
  250. package/dist/{providers → harnesses}/grok/GrokAgentMapper.js +4 -10
  251. package/dist/harnesses/grok/GrokAgentMapper.js.map +1 -0
  252. package/dist/{providers → harnesses}/grok/GrokCliAdapter.d.ts +5 -5
  253. package/dist/harnesses/grok/GrokCliAdapter.d.ts.map +1 -0
  254. package/dist/{providers → harnesses}/grok/GrokCliAdapter.js +14 -10
  255. package/dist/harnesses/grok/GrokCliAdapter.js.map +1 -0
  256. package/dist/{providers → harnesses}/grok/GrokSessionLocator.d.ts.map +1 -1
  257. package/dist/{providers → harnesses}/grok/GrokSessionLocator.js +2 -2
  258. package/dist/harnesses/grok/GrokSessionLocator.js.map +1 -0
  259. package/dist/harnesses/grok/GrokSessionParser.d.ts +87 -0
  260. package/dist/harnesses/grok/GrokSessionParser.d.ts.map +1 -0
  261. package/dist/harnesses/grok/GrokSessionParser.js +185 -0
  262. package/dist/harnesses/grok/GrokSessionParser.js.map +1 -0
  263. package/dist/harnesses/index.d.ts +7 -0
  264. package/dist/harnesses/index.d.ts.map +1 -0
  265. package/dist/harnesses/index.js +27 -0
  266. package/dist/harnesses/index.js.map +1 -0
  267. package/dist/harnesses/kiro/KiroAdapter.d.ts +31 -0
  268. package/dist/harnesses/kiro/KiroAdapter.d.ts.map +1 -0
  269. package/dist/harnesses/kiro/KiroAdapter.js +125 -0
  270. package/dist/harnesses/kiro/KiroAdapter.js.map +1 -0
  271. package/dist/harnesses/kiro/KiroAgentMapper.d.ts +13 -0
  272. package/dist/harnesses/kiro/KiroAgentMapper.d.ts.map +1 -0
  273. package/dist/harnesses/kiro/KiroAgentMapper.js +29 -0
  274. package/dist/harnesses/kiro/KiroAgentMapper.js.map +1 -0
  275. package/dist/harnesses/kiro/KiroSessionLocator.d.ts +38 -0
  276. package/dist/harnesses/kiro/KiroSessionLocator.d.ts.map +1 -0
  277. package/dist/harnesses/kiro/KiroSessionLocator.js +95 -0
  278. package/dist/harnesses/kiro/KiroSessionLocator.js.map +1 -0
  279. package/dist/harnesses/kiro/KiroSessionParser.d.ts +81 -0
  280. package/dist/harnesses/kiro/KiroSessionParser.d.ts.map +1 -0
  281. package/dist/harnesses/kiro/KiroSessionParser.js +251 -0
  282. package/dist/harnesses/kiro/KiroSessionParser.js.map +1 -0
  283. package/dist/{providers → harnesses}/opencode/OpenCodeAdapter.d.ts +2 -4
  284. package/dist/harnesses/opencode/OpenCodeAdapter.d.ts.map +1 -0
  285. package/dist/{providers → harnesses}/opencode/OpenCodeAdapter.js +4 -7
  286. package/dist/harnesses/opencode/OpenCodeAdapter.js.map +1 -0
  287. package/dist/{providers → harnesses}/opencode/OpenCodeAgentMapper.d.ts.map +1 -1
  288. package/dist/{providers → harnesses}/opencode/OpenCodeAgentMapper.js +5 -13
  289. package/dist/harnesses/opencode/OpenCodeAgentMapper.js.map +1 -0
  290. package/dist/{providers → harnesses}/opencode/OpenCodeSessionLocator.d.ts.map +1 -1
  291. package/dist/{providers → harnesses}/opencode/OpenCodeSessionLocator.js +2 -2
  292. package/dist/harnesses/opencode/OpenCodeSessionLocator.js.map +1 -0
  293. package/dist/{providers → harnesses}/opencode/OpenCodeSessionParser.d.ts +2 -4
  294. package/dist/harnesses/opencode/OpenCodeSessionParser.d.ts.map +1 -0
  295. package/dist/{providers → harnesses}/opencode/OpenCodeSessionParser.js +2 -1
  296. package/dist/harnesses/opencode/OpenCodeSessionParser.js.map +1 -0
  297. package/dist/{providers → harnesses}/pi/PiAdapter.d.ts +5 -4
  298. package/dist/harnesses/pi/PiAdapter.d.ts.map +1 -0
  299. package/dist/{providers → harnesses}/pi/PiAdapter.js +16 -12
  300. package/dist/harnesses/pi/PiAdapter.js.map +1 -0
  301. package/dist/{providers → harnesses}/pi/PiAgentMapper.d.ts.map +1 -1
  302. package/dist/{providers → harnesses}/pi/PiAgentMapper.js +4 -11
  303. package/dist/harnesses/pi/PiAgentMapper.js.map +1 -0
  304. package/dist/harnesses/pi/PiSessionLocator.d.ts +61 -0
  305. package/dist/harnesses/pi/PiSessionLocator.d.ts.map +1 -0
  306. package/dist/harnesses/pi/PiSessionLocator.js +212 -0
  307. package/dist/harnesses/pi/PiSessionLocator.js.map +1 -0
  308. package/dist/harnesses/pi/PiSessionParser.d.ts +88 -0
  309. package/dist/harnesses/pi/PiSessionParser.d.ts.map +1 -0
  310. package/dist/harnesses/pi/PiSessionParser.js +318 -0
  311. package/dist/harnesses/pi/PiSessionParser.js.map +1 -0
  312. package/dist/{providers → harnesses}/pi/PiSessionTracker.d.ts.map +1 -1
  313. package/dist/{providers → harnesses}/pi/PiSessionTracker.js +2 -2
  314. package/dist/harnesses/pi/PiSessionTracker.js.map +1 -0
  315. package/dist/{providers → harnesses}/pi/durable/PiCliProbe.d.ts.map +1 -1
  316. package/dist/{providers → harnesses}/pi/durable/PiCliProbe.js.map +1 -1
  317. package/dist/{providers → harnesses}/pi/durable/PiPrintAgentService.d.ts.map +1 -1
  318. package/dist/{providers → harnesses}/pi/durable/PiPrintAgentService.js.map +1 -1
  319. package/dist/{providers → harnesses}/pi/durable/PiPrintProtocol.d.ts.map +1 -1
  320. package/dist/{providers → harnesses}/pi/durable/PiPrintProtocol.js.map +1 -1
  321. package/dist/{providers → harnesses}/pi/durable/PiPrintRunner.d.ts.map +1 -1
  322. package/dist/{providers → harnesses}/pi/durable/PiPrintRunner.js.map +1 -1
  323. package/dist/{providers → harnesses}/pi/durable/PiStreamParser.d.ts.map +1 -1
  324. package/dist/{providers → harnesses}/pi/durable/PiStreamParser.js.map +1 -1
  325. package/dist/harnesses/shared.d.ts +41 -0
  326. package/dist/harnesses/shared.d.ts.map +1 -0
  327. package/dist/harnesses/shared.js +71 -0
  328. package/dist/harnesses/shared.js.map +1 -0
  329. package/dist/index.d.ts +28 -25
  330. package/dist/index.d.ts.map +1 -1
  331. package/dist/index.js +19 -16
  332. package/dist/index.js.map +1 -1
  333. package/dist/readiness/AgentReadiness.d.ts +1 -1
  334. package/dist/readiness/AgentReadiness.d.ts.map +1 -1
  335. package/dist/readiness/AgentReadiness.js.map +1 -1
  336. package/dist/runtime/ManagedAgentRuntime.js +3 -1
  337. package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
  338. package/dist/runtime/herdr/HerdrAgentDiscovery.js +10 -0
  339. package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
  340. package/dist/utils/IncrementalJsonlSummary.d.ts +100 -0
  341. package/dist/utils/IncrementalJsonlSummary.d.ts.map +1 -0
  342. package/dist/utils/IncrementalJsonlSummary.js +209 -0
  343. package/dist/utils/IncrementalJsonlSummary.js.map +1 -0
  344. package/dist/utils/agents.d.ts +3 -2
  345. package/dist/utils/agents.d.ts.map +1 -1
  346. package/dist/utils/agents.js +61 -15
  347. package/dist/utils/agents.js.map +1 -1
  348. package/dist/utils/index.d.ts +2 -1
  349. package/dist/utils/index.d.ts.map +1 -1
  350. package/dist/utils/index.js +1 -1
  351. package/dist/utils/index.js.map +1 -1
  352. package/dist/utils/jsonlTail.d.ts +73 -0
  353. package/dist/utils/jsonlTail.d.ts.map +1 -0
  354. package/dist/utils/jsonlTail.js +238 -0
  355. package/dist/utils/jsonlTail.js.map +1 -0
  356. package/dist/utils/matching.d.ts +2 -0
  357. package/dist/utils/matching.d.ts.map +1 -1
  358. package/dist/utils/matching.js +3 -2
  359. package/dist/utils/matching.js.map +1 -1
  360. package/dist/utils/matchingConstants.d.ts +15 -0
  361. package/dist/utils/matchingConstants.d.ts.map +1 -0
  362. package/dist/utils/matchingConstants.js +14 -0
  363. package/dist/utils/matchingConstants.js.map +1 -0
  364. package/dist/utils/process.d.ts +38 -2
  365. package/dist/utils/process.d.ts.map +1 -1
  366. package/dist/utils/process.js +131 -43
  367. package/dist/utils/process.js.map +1 -1
  368. package/package.json +2 -1
  369. package/scripts/benchmark-cold-start.mjs +350 -0
  370. package/src/AgentManager.ts +26 -5
  371. package/src/__tests__/AgentManager.test.ts +141 -3
  372. package/src/__tests__/adapters/IncrementalSessionRefresh.test.ts +437 -0
  373. package/src/__tests__/adapters/adapterProcessImports.test.ts +58 -0
  374. package/src/__tests__/adapters/adapterSnapshotCandidates.test.ts +243 -0
  375. package/src/__tests__/capacity/claude.test.ts +467 -0
  376. package/src/__tests__/capacity/fixtures/claude-credentials.json +7 -0
  377. package/src/__tests__/capacity/fixtures/claude-usage-malformed.json +1 -0
  378. package/src/__tests__/capacity/fixtures/claude-usage-partial.json +15 -0
  379. package/src/__tests__/capacity/fixtures/claude-usage.json +63 -0
  380. package/src/__tests__/capacity/fixtures/openai-auth.json +6 -0
  381. package/src/__tests__/capacity/fixtures/openai-codex-auth.json +9 -0
  382. package/src/__tests__/capacity/fixtures/openai-usage-completions.json +67 -0
  383. package/src/__tests__/capacity/fixtures/openai-usage-responses.json +20 -0
  384. package/src/__tests__/capacity/fixtures/wham-usage.json +32 -0
  385. package/src/__tests__/capacity/openai.test.ts +560 -0
  386. package/src/__tests__/capacity/wham.test.ts +104 -0
  387. package/src/__tests__/harnesses/BoundedSummarySkip.test.ts +496 -0
  388. package/src/__tests__/harnesses/SessionSummaryEquivalence.test.ts +726 -0
  389. package/src/__tests__/harnesses/antigravity/AntigravityCliAdapter.subprocess.test.ts +133 -0
  390. package/src/__tests__/harnesses/antigravity/AntigravityCliAdapter.test.ts +396 -0
  391. package/src/__tests__/harnesses/builtinAdapters.test.ts +33 -0
  392. package/src/__tests__/{providers → harnesses}/claude/ClaudeAgentMapper.test.ts +5 -5
  393. package/src/__tests__/{adapters → harnesses/claude}/ClaudeCodeAdapter.test.ts +54 -24
  394. package/src/__tests__/{providers → harnesses}/claude/ClaudeSessionLocator.test.ts +1 -12
  395. package/src/__tests__/{utils → harnesses/claude}/ClaudeSessionParser.test.ts +2 -2
  396. package/src/__tests__/{print → harnesses/claude/durable}/ClaudeCliProbe.test.ts +1 -1
  397. package/src/__tests__/{print → harnesses/claude/durable}/ClaudePrintAgent.integration.test.ts +1 -1
  398. package/src/__tests__/{print → harnesses/claude/durable}/ClaudePrintAgentService.test.ts +4 -4
  399. package/src/__tests__/{print → harnesses/claude/durable}/ClaudePrintRunner.test.ts +2 -2
  400. package/src/__tests__/{adapters → harnesses/codex}/CodexAdapter.test.ts +277 -12
  401. package/src/__tests__/harnesses/codex/CodexSessionLocator.test.ts +419 -0
  402. package/src/__tests__/{providers → harnesses}/codex/CodexSessionMapping.test.ts +1 -1
  403. package/src/__tests__/{providers → harnesses}/codex/CodexSessionParser.test.ts +1 -1
  404. package/src/__tests__/{durable → harnesses/codex/durable}/CodexCliProbe.test.ts +4 -4
  405. package/src/__tests__/{durable → harnesses/codex/durable}/CodexDurableAgentRepository.test.ts +1 -1
  406. package/src/__tests__/{durable → harnesses/codex/durable}/CodexPrintAgent.integration.test.ts +1 -1
  407. package/src/__tests__/{durable → harnesses/codex/durable}/CodexPrintAgentService.test.ts +8 -18
  408. package/src/__tests__/{durable → harnesses/codex/durable}/CodexPrintRunner.test.ts +3 -9
  409. package/src/__tests__/{providers → harnesses}/copilot/CopilotAdapter.test.ts +1 -1
  410. package/src/__tests__/harnesses/copilot/CopilotRefreshIO.test.ts +270 -0
  411. package/src/__tests__/{providers → harnesses}/gemini/GeminiCliAdapter.test.ts +27 -23
  412. package/src/__tests__/harnesses/gemini/GeminiSessionJsonl.test.ts +402 -0
  413. package/src/__tests__/harnesses/gemini/GeminiSessionLocator.test.ts +396 -0
  414. package/src/__tests__/{providers → harnesses}/grok/GrokAgentMapper.test.ts +2 -2
  415. package/src/__tests__/{providers → harnesses}/grok/GrokCliAdapter.test.ts +1 -1
  416. package/src/__tests__/harnesses/grok/GrokIncrementalRefresh.test.ts +170 -0
  417. package/src/__tests__/{providers → harnesses}/grok/GrokSessionLocator.test.ts +1 -1
  418. package/src/__tests__/harnesses/grok/GrokSessionParser.test.ts +230 -0
  419. package/src/__tests__/harnesses/kiro/KiroAdapter.test.ts +552 -0
  420. package/src/__tests__/{providers → harnesses}/opencode/OpenCodeAdapter.test.ts +1 -1
  421. package/src/__tests__/{providers → harnesses}/opencode/OpenCodeAgentMapper.test.ts +1 -1
  422. package/src/__tests__/{providers → harnesses}/opencode/OpenCodeSessionLocator.test.ts +2 -2
  423. package/src/__tests__/{providers → harnesses}/opencode/OpenCodeSessionParser.test.ts +1 -1
  424. package/src/__tests__/{providers → harnesses}/pi/PiAdapter.test.ts +1 -1
  425. package/src/__tests__/harnesses/pi/PiDiscoveryIO.test.ts +337 -0
  426. package/src/__tests__/{providers → harnesses}/pi/PiSessionParser.test.ts +91 -1
  427. package/src/__tests__/{providers → harnesses}/pi/PiSessionTracker.test.ts +1 -1
  428. package/src/__tests__/{providers → harnesses}/pi/durable/PiPrintProtocol.test.ts +1 -1
  429. package/src/__tests__/{providers → harnesses}/pi/durable/PiStreamParser.test.ts +1 -1
  430. package/src/__tests__/readiness/AgentReadiness.test.ts +16 -0
  431. package/src/__tests__/runtime/ManagedAgentRuntime.test.ts +30 -0
  432. package/src/__tests__/utils/IncrementalJsonlSummary.test.ts +414 -0
  433. package/src/__tests__/utils/agents.test.ts +83 -2
  434. package/src/__tests__/utils/conversationTail.bench.test.ts +193 -0
  435. package/src/__tests__/utils/conversationTailParity.test.ts +365 -0
  436. package/src/__tests__/utils/jsonlTail.test.ts +317 -0
  437. package/src/__tests__/utils/matchingConstants.test.ts +40 -0
  438. package/src/__tests__/utils/process.test.ts +254 -0
  439. package/src/adapters/AgentAdapter.ts +37 -12
  440. package/src/capacity/claude.ts +313 -0
  441. package/src/capacity/codex.ts +25 -134
  442. package/src/capacity/index.ts +33 -4
  443. package/src/capacity/openai.ts +355 -0
  444. package/src/capacity/wham.ts +84 -0
  445. package/src/harnesses/antigravity/AntigravityAgentMapper.ts +34 -0
  446. package/src/harnesses/antigravity/AntigravityCliAdapter.ts +126 -0
  447. package/src/harnesses/antigravity/AntigravitySessionLocator.ts +75 -0
  448. package/src/harnesses/antigravity/AntigravitySessionParser.ts +252 -0
  449. package/src/{providers → harnesses}/claude/ClaudeAgentMapper.ts +2 -10
  450. package/src/{providers → harnesses}/claude/ClaudeCodeAdapter.ts +22 -20
  451. package/src/{providers → harnesses}/claude/ClaudeSessionLocator.ts +3 -3
  452. package/src/{providers → harnesses}/claude/ClaudeSessionParser.ts +189 -97
  453. package/src/{providers → harnesses}/codex/CodexAdapter.ts +153 -29
  454. package/src/{providers → harnesses}/codex/CodexAgentMapper.ts +2 -11
  455. package/src/harnesses/codex/CodexSessionLocator.ts +509 -0
  456. package/src/{providers → harnesses}/codex/CodexSessionMapping.ts +3 -3
  457. package/src/{providers → harnesses}/codex/CodexSessionParser.ts +169 -92
  458. package/src/{providers → harnesses}/copilot/CopilotAdapter.ts +22 -22
  459. package/src/{providers → harnesses}/copilot/CopilotAgentMapper.ts +2 -11
  460. package/src/harnesses/copilot/CopilotSessionLocator.ts +161 -0
  461. package/src/harnesses/copilot/CopilotSessionParser.ts +380 -0
  462. package/src/{providers → harnesses}/gemini/GeminiAgentMapper.ts +2 -11
  463. package/src/{providers → harnesses}/gemini/GeminiCliAdapter.ts +7 -9
  464. package/src/harnesses/gemini/GeminiSessionLocator.ts +394 -0
  465. package/src/{providers → harnesses}/gemini/GeminiSessionParser.ts +155 -31
  466. package/src/harnesses/gemini/fileSignature.ts +10 -0
  467. package/src/{providers → harnesses}/grok/GrokAgentMapper.ts +2 -11
  468. package/src/{providers → harnesses}/grok/GrokCliAdapter.ts +16 -15
  469. package/src/{providers → harnesses}/grok/GrokSessionLocator.ts +2 -2
  470. package/src/harnesses/grok/GrokSessionParser.ts +251 -0
  471. package/src/harnesses/index.ts +28 -0
  472. package/src/harnesses/kiro/KiroAdapter.ts +143 -0
  473. package/src/harnesses/kiro/KiroAgentMapper.ts +34 -0
  474. package/src/harnesses/kiro/KiroSessionLocator.ts +143 -0
  475. package/src/harnesses/kiro/KiroSessionParser.ts +376 -0
  476. package/src/{providers → harnesses}/opencode/OpenCodeAdapter.ts +5 -11
  477. package/src/{providers → harnesses}/opencode/OpenCodeAgentMapper.ts +3 -13
  478. package/src/{providers → harnesses}/opencode/OpenCodeSessionLocator.ts +2 -2
  479. package/src/{providers → harnesses}/opencode/OpenCodeSessionParser.ts +4 -3
  480. package/src/{providers → harnesses}/pi/PiAdapter.ts +20 -18
  481. package/src/{providers → harnesses}/pi/PiAgentMapper.ts +2 -11
  482. package/src/harnesses/pi/PiSessionLocator.ts +288 -0
  483. package/src/harnesses/pi/PiSessionParser.ts +488 -0
  484. package/src/{providers → harnesses}/pi/PiSessionTracker.ts +2 -2
  485. package/src/harnesses/shared.ts +119 -0
  486. package/src/index.ts +34 -23
  487. package/src/readiness/AgentReadiness.ts +4 -1
  488. package/src/runtime/ManagedAgentRuntime.ts +2 -0
  489. package/src/runtime/herdr/HerdrAgentDiscovery.ts +5 -1
  490. package/src/utils/IncrementalJsonlSummary.ts +306 -0
  491. package/src/utils/agents.ts +62 -20
  492. package/src/utils/index.ts +2 -0
  493. package/src/utils/jsonlTail.ts +349 -0
  494. package/src/utils/matching.ts +3 -3
  495. package/src/utils/matchingConstants.ts +15 -0
  496. package/src/utils/process.ts +189 -45
  497. package/dist/__tests__/adapters/ClaudeCodeAdapter.test.js.map +0 -1
  498. package/dist/__tests__/adapters/CodexAdapter.test.js.map +0 -1
  499. package/dist/__tests__/durable/CodexCliProbe.test.js.map +0 -1
  500. package/dist/__tests__/durable/CodexDurableAgentRepository.test.js.map +0 -1
  501. package/dist/__tests__/durable/CodexPrintAgent.integration.test.js.map +0 -1
  502. package/dist/__tests__/durable/CodexPrintAgentService.test.js.map +0 -1
  503. package/dist/__tests__/durable/CodexPrintRunner.test.js.map +0 -1
  504. package/dist/__tests__/print/ClaudeCliProbe.test.js.map +0 -1
  505. package/dist/__tests__/print/ClaudePrintAgent.integration.test.js.map +0 -1
  506. package/dist/__tests__/print/ClaudePrintAgentService.test.js.map +0 -1
  507. package/dist/__tests__/print/ClaudePrintRunner.test.js.map +0 -1
  508. package/dist/__tests__/providers/claude/ClaudeAgentMapper.test.js.map +0 -1
  509. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js +0 -194
  510. package/dist/__tests__/providers/codex/CodexSessionLocator.test.js.map +0 -1
  511. package/dist/__tests__/providers/gemini/GeminiCliAdapter.test.js.map +0 -1
  512. package/dist/__tests__/providers/pi/PiSessionParser.test.js.map +0 -1
  513. package/dist/__tests__/utils/ClaudeSessionParser.test.js.map +0 -1
  514. package/dist/adapters/index.d.ts +0 -10
  515. package/dist/adapters/index.d.ts.map +0 -1
  516. package/dist/adapters/index.js +0 -10
  517. package/dist/adapters/index.js.map +0 -1
  518. package/dist/providers/claude/ClaudeAgentMapper.js.map +0 -1
  519. package/dist/providers/claude/ClaudeCodeAdapter.d.ts.map +0 -1
  520. package/dist/providers/claude/ClaudeCodeAdapter.js.map +0 -1
  521. package/dist/providers/claude/ClaudeSessionLocator.js.map +0 -1
  522. package/dist/providers/claude/ClaudeSessionParser.d.ts.map +0 -1
  523. package/dist/providers/claude/ClaudeSessionParser.js.map +0 -1
  524. package/dist/providers/codex/CodexAdapter.d.ts.map +0 -1
  525. package/dist/providers/codex/CodexAdapter.js.map +0 -1
  526. package/dist/providers/codex/CodexAgentMapper.js.map +0 -1
  527. package/dist/providers/codex/CodexSessionLocator.d.ts +0 -44
  528. package/dist/providers/codex/CodexSessionLocator.d.ts.map +0 -1
  529. package/dist/providers/codex/CodexSessionLocator.js +0 -207
  530. package/dist/providers/codex/CodexSessionLocator.js.map +0 -1
  531. package/dist/providers/codex/CodexSessionMapping.js.map +0 -1
  532. package/dist/providers/codex/CodexSessionParser.d.ts +0 -58
  533. package/dist/providers/codex/CodexSessionParser.d.ts.map +0 -1
  534. package/dist/providers/codex/CodexSessionParser.js.map +0 -1
  535. package/dist/providers/copilot/CopilotAdapter.d.ts.map +0 -1
  536. package/dist/providers/copilot/CopilotAdapter.js.map +0 -1
  537. package/dist/providers/copilot/CopilotAgentMapper.js.map +0 -1
  538. package/dist/providers/copilot/CopilotSessionLocator.d.ts +0 -20
  539. package/dist/providers/copilot/CopilotSessionLocator.d.ts.map +0 -1
  540. package/dist/providers/copilot/CopilotSessionLocator.js +0 -49
  541. package/dist/providers/copilot/CopilotSessionLocator.js.map +0 -1
  542. package/dist/providers/copilot/CopilotSessionParser.d.ts +0 -30
  543. package/dist/providers/copilot/CopilotSessionParser.d.ts.map +0 -1
  544. package/dist/providers/copilot/CopilotSessionParser.js +0 -181
  545. package/dist/providers/copilot/CopilotSessionParser.js.map +0 -1
  546. package/dist/providers/gemini/GeminiAgentMapper.js.map +0 -1
  547. package/dist/providers/gemini/GeminiCliAdapter.d.ts.map +0 -1
  548. package/dist/providers/gemini/GeminiCliAdapter.js.map +0 -1
  549. package/dist/providers/gemini/GeminiSessionLocator.d.ts +0 -30
  550. package/dist/providers/gemini/GeminiSessionLocator.d.ts.map +0 -1
  551. package/dist/providers/gemini/GeminiSessionLocator.js +0 -142
  552. package/dist/providers/gemini/GeminiSessionLocator.js.map +0 -1
  553. package/dist/providers/gemini/GeminiSessionParser.d.ts.map +0 -1
  554. package/dist/providers/gemini/GeminiSessionParser.js +0 -166
  555. package/dist/providers/gemini/GeminiSessionParser.js.map +0 -1
  556. package/dist/providers/grok/GrokAgentMapper.js.map +0 -1
  557. package/dist/providers/grok/GrokCliAdapter.d.ts.map +0 -1
  558. package/dist/providers/grok/GrokCliAdapter.js.map +0 -1
  559. package/dist/providers/grok/GrokSessionLocator.js.map +0 -1
  560. package/dist/providers/grok/GrokSessionParser.d.ts +0 -54
  561. package/dist/providers/grok/GrokSessionParser.d.ts.map +0 -1
  562. package/dist/providers/grok/GrokSessionParser.js +0 -122
  563. package/dist/providers/grok/GrokSessionParser.js.map +0 -1
  564. package/dist/providers/opencode/OpenCodeAdapter.d.ts.map +0 -1
  565. package/dist/providers/opencode/OpenCodeAdapter.js.map +0 -1
  566. package/dist/providers/opencode/OpenCodeAgentMapper.js.map +0 -1
  567. package/dist/providers/opencode/OpenCodeSessionLocator.js.map +0 -1
  568. package/dist/providers/opencode/OpenCodeSessionParser.d.ts.map +0 -1
  569. package/dist/providers/opencode/OpenCodeSessionParser.js.map +0 -1
  570. package/dist/providers/pi/PiAdapter.d.ts.map +0 -1
  571. package/dist/providers/pi/PiAdapter.js.map +0 -1
  572. package/dist/providers/pi/PiAgentMapper.js.map +0 -1
  573. package/dist/providers/pi/PiSessionLocator.d.ts +0 -24
  574. package/dist/providers/pi/PiSessionLocator.d.ts.map +0 -1
  575. package/dist/providers/pi/PiSessionLocator.js +0 -86
  576. package/dist/providers/pi/PiSessionLocator.js.map +0 -1
  577. package/dist/providers/pi/PiSessionParser.d.ts +0 -36
  578. package/dist/providers/pi/PiSessionParser.d.ts.map +0 -1
  579. package/dist/providers/pi/PiSessionParser.js +0 -191
  580. package/dist/providers/pi/PiSessionParser.js.map +0 -1
  581. package/dist/providers/pi/PiSessionTracker.js.map +0 -1
  582. package/src/__tests__/fixtures/fake-claude.cjs +0 -31
  583. package/src/__tests__/fixtures/fake-codex.cjs +0 -56
  584. package/src/__tests__/providers/codex/CodexSessionLocator.test.ts +0 -182
  585. package/src/adapters/index.ts +0 -15
  586. package/src/providers/codex/CodexSessionLocator.ts +0 -279
  587. package/src/providers/copilot/CopilotSessionLocator.ts +0 -63
  588. package/src/providers/copilot/CopilotSessionParser.ts +0 -289
  589. package/src/providers/gemini/GeminiSessionLocator.ts +0 -183
  590. package/src/providers/grok/GrokSessionParser.ts +0 -166
  591. package/src/providers/pi/PiSessionLocator.ts +0 -110
  592. package/src/providers/pi/PiSessionParser.ts +0 -284
  593. /package/dist/__tests__/{providers → harnesses}/pi/durable/PiCliProbe.test.js +0 -0
  594. /package/dist/__tests__/{providers → harnesses}/pi/durable/PiDurableAgentRepository.test.js +0 -0
  595. /package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintAgentService.test.js +0 -0
  596. /package/dist/__tests__/{providers → harnesses}/pi/durable/PiPrintRunner.test.js +0 -0
  597. /package/dist/{providers → harnesses}/claude/ClaudeAgentMapper.d.ts +0 -0
  598. /package/dist/{providers → harnesses}/claude/ClaudeSessionLocator.d.ts +0 -0
  599. /package/dist/{providers → harnesses}/claude/durable/ClaudeCliProbe.d.ts +0 -0
  600. /package/dist/{providers → harnesses}/claude/durable/ClaudeCliProbe.js +0 -0
  601. /package/dist/{providers → harnesses}/claude/durable/ClaudePrintAgentService.d.ts +0 -0
  602. /package/dist/{providers → harnesses}/claude/durable/ClaudePrintAgentService.js +0 -0
  603. /package/dist/{providers → harnesses}/claude/durable/ClaudePrintRunner.d.ts +0 -0
  604. /package/dist/{providers → harnesses}/claude/durable/ClaudePrintRunner.js +0 -0
  605. /package/dist/{providers → harnesses}/claude/durable/ClaudeStreamParser.d.ts +0 -0
  606. /package/dist/{providers → harnesses}/claude/durable/ClaudeStreamParser.js +0 -0
  607. /package/dist/{providers → harnesses}/codex/CodexAgentMapper.d.ts +0 -0
  608. /package/dist/{providers → harnesses}/codex/CodexSessionMapping.d.ts +0 -0
  609. /package/dist/{providers → harnesses}/codex/durable/CodexCliProbe.d.ts +0 -0
  610. /package/dist/{providers → harnesses}/codex/durable/CodexCliProbe.js +0 -0
  611. /package/dist/{providers → harnesses}/codex/durable/CodexPrintAgentService.d.ts +0 -0
  612. /package/dist/{providers → harnesses}/codex/durable/CodexPrintAgentService.js +0 -0
  613. /package/dist/{providers → harnesses}/codex/durable/CodexPrintRunner.d.ts +0 -0
  614. /package/dist/{providers → harnesses}/codex/durable/CodexPrintRunner.js +0 -0
  615. /package/dist/{providers → harnesses}/codex/durable/CodexStreamParser.d.ts +0 -0
  616. /package/dist/{providers → harnesses}/codex/durable/CodexStreamParser.js +0 -0
  617. /package/dist/{providers → harnesses}/copilot/CopilotAgentMapper.d.ts +0 -0
  618. /package/dist/{providers → harnesses}/gemini/GeminiAgentMapper.d.ts +0 -0
  619. /package/dist/{providers → harnesses}/grok/GrokAgentMapper.d.ts +0 -0
  620. /package/dist/{providers → harnesses}/grok/GrokSessionLocator.d.ts +0 -0
  621. /package/dist/{providers → harnesses}/opencode/OpenCodeAgentMapper.d.ts +0 -0
  622. /package/dist/{providers → harnesses}/opencode/OpenCodeSessionLocator.d.ts +0 -0
  623. /package/dist/{providers → harnesses}/pi/PiAgentMapper.d.ts +0 -0
  624. /package/dist/{providers → harnesses}/pi/PiSessionTracker.d.ts +0 -0
  625. /package/dist/{providers → harnesses}/pi/durable/PiCliProbe.d.ts +0 -0
  626. /package/dist/{providers → harnesses}/pi/durable/PiCliProbe.js +0 -0
  627. /package/dist/{providers → harnesses}/pi/durable/PiPrintAgentService.d.ts +0 -0
  628. /package/dist/{providers → harnesses}/pi/durable/PiPrintAgentService.js +0 -0
  629. /package/dist/{providers → harnesses}/pi/durable/PiPrintProtocol.d.ts +0 -0
  630. /package/dist/{providers → harnesses}/pi/durable/PiPrintProtocol.js +0 -0
  631. /package/dist/{providers → harnesses}/pi/durable/PiPrintRunner.d.ts +0 -0
  632. /package/dist/{providers → harnesses}/pi/durable/PiPrintRunner.js +0 -0
  633. /package/dist/{providers → harnesses}/pi/durable/PiStreamParser.d.ts +0 -0
  634. /package/dist/{providers → harnesses}/pi/durable/PiStreamParser.js +0 -0
  635. /package/src/__tests__/{providers → harnesses}/pi/durable/PiCliProbe.test.ts +0 -0
  636. /package/src/__tests__/{providers → harnesses}/pi/durable/PiDurableAgentRepository.test.ts +0 -0
  637. /package/src/__tests__/{providers → harnesses}/pi/durable/PiPrintAgentService.test.ts +0 -0
  638. /package/src/__tests__/{providers → harnesses}/pi/durable/PiPrintRunner.test.ts +0 -0
  639. /package/src/{providers → harnesses}/claude/durable/ClaudeCliProbe.ts +0 -0
  640. /package/src/{providers → harnesses}/claude/durable/ClaudePrintAgentService.ts +0 -0
  641. /package/src/{providers → harnesses}/claude/durable/ClaudePrintRunner.ts +0 -0
  642. /package/src/{providers → harnesses}/claude/durable/ClaudeStreamParser.ts +0 -0
  643. /package/src/{providers → harnesses}/codex/durable/CodexCliProbe.ts +0 -0
  644. /package/src/{providers → harnesses}/codex/durable/CodexPrintAgentService.ts +0 -0
  645. /package/src/{providers → harnesses}/codex/durable/CodexPrintRunner.ts +0 -0
  646. /package/src/{providers → harnesses}/codex/durable/CodexStreamParser.ts +0 -0
  647. /package/src/{providers → harnesses}/pi/durable/PiCliProbe.ts +0 -0
  648. /package/src/{providers → harnesses}/pi/durable/PiPrintAgentService.ts +0 -0
  649. /package/src/{providers → harnesses}/pi/durable/PiPrintProtocol.ts +0 -0
  650. /package/src/{providers → harnesses}/pi/durable/PiPrintRunner.ts +0 -0
  651. /package/src/{providers → harnesses}/pi/durable/PiStreamParser.ts +0 -0
@@ -1,4 +1,4 @@
1
- import type { ConversationMessage, SessionSummary } from "../../adapters/AgentAdapter.js";
1
+ import type { ConversationMessage, ConversationOptions, SessionSummary } from "../../adapters/AgentAdapter.js";
2
2
  import { AgentStatus } from "../../adapters/AgentAdapter.js";
3
3
  /**
4
4
  * A single Gemini CLI message content part. Mirrors the `{text?: string}`
@@ -47,27 +47,54 @@ export interface GeminiSession {
47
47
  lastMessageType?: string;
48
48
  }
49
49
  export declare class GeminiSessionParser {
50
+ private readonly sessionCache;
50
51
  /**
51
52
  * Parse session file content into GeminiSession.
52
- * Uses cached content if available, otherwise reads from disk.
53
+ * Uses the given content if available; otherwise reads from disk, reusing
54
+ * the previous result while the file's inode, size and mtime are unchanged.
53
55
  */
54
56
  parseSession(cachedContent: string | undefined, filePath: string): GeminiSession | null;
57
+ private rememberSession;
58
+ private buildSession;
55
59
  determineStatus(session: GeminiSession): AgentStatus;
56
60
  /**
57
61
  * Read the full conversation from a Gemini CLI session JSON file.
58
62
  *
59
63
  * Gemini sessions store messages in an array with `type` field — typically
60
64
  * 'user' or 'gemini' for visible turns, with tool and system entries mixed in.
65
+ *
66
+ * `tail` only slices the result: the session is a single JSON document, so
67
+ * it cannot be read from the end and is always parsed in full. Callers that
68
+ * poll (the console preview) rely on their mtime cache to skip re-parses.
61
69
  */
62
- getConversation(sessionFilePath: string, options?: {
63
- verbose?: boolean;
64
- }): ConversationMessage[];
70
+ getConversation(sessionFilePath: string, options?: ConversationOptions): ConversationMessage[];
65
71
  /**
66
72
  * Read a Gemini session JSON file and produce a {@link SessionSummary}.
67
73
  * Returns null when the file is unreadable, the JSON doesn't parse,
68
74
  * or the body lacks a sessionId.
69
75
  */
70
76
  fileToSessionSummary(filePath: string): SessionSummary | null;
77
+ /**
78
+ * Parse either session format into the legacy single-document shape:
79
+ * `session-*.json` is one JSON document, `session-*.jsonl` (Gemini CLI
80
+ * 0.46+) is an append-only log replayed by {@link replaySessionLog}.
81
+ */
82
+ private parseSessionContent;
83
+ /**
84
+ * Rebuild a session document from a `.jsonl` log, mirroring Gemini CLI's
85
+ * own loader (`loadConversationRecord`):
86
+ * - a record with a string `id` is a message, upserted by id in place;
87
+ * - `{"$set": {...}}` merges metadata; a `$set.messages` array replaces
88
+ * every message;
89
+ * - `{"$rewindTo": id}` drops that message and all later ones (all
90
+ * messages when the id is unknown);
91
+ * - a record with `sessionId` and `projectHash` (line 1) merges metadata.
92
+ * Unknown operators, non-object lines and a torn trailing line (a write
93
+ * in progress) are ignored.
94
+ */
95
+ private replaySessionLog;
96
+ private rewindMessages;
97
+ private parseLogRecord;
71
98
  private parseSessionJson;
72
99
  private readSessionFile;
73
100
  private roleForEntry;
@@ -87,8 +114,8 @@ export declare class GeminiSessionParser {
87
114
  */
88
115
  private resolveContent;
89
116
  private extractFirstUserMessage;
90
- private parseTimestamp;
91
- private truncate;
92
117
  }
118
+ /** Gemini CLI 0.46+ writes sessions as append-only `.jsonl` logs. */
119
+ export declare function isSessionLogPath(filePath: string): boolean;
93
120
  export {};
94
121
  //# sourceMappingURL=GeminiSessionParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiSessionParser.d.ts","sourceRoot":"","sources":["../../../src/harnesses/gemini/GeminiSessionParser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACf,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAM7D;;;;;;GAMG;AACH,UAAU,iBAAiB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,KAAK,oBAAoB,GAAG,MAAM,GAAG,iBAAiB,EAAE,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,IAAI,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAWD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0C;IAEvE;;;;OAIG;IACH,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAmBvF,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,YAAY;IAiCpB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW;IAYpD;;;;;;;;;OASG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE;IA0B9F;;;;OAIG;IACH,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAkC7D;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,cAAc;IAWtB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAMnB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,uBAAuB;CAQhC;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D"}
@@ -0,0 +1,272 @@
1
+ import * as fs from "fs";
2
+ import { AgentStatus } from "../../adapters/AgentAdapter.js";
3
+ import { sliceTail } from "../../utils/jsonlTail.js";
4
+ import { safeReadFile, safeStat } from "../../utils/session.js";
5
+ import { fileSignature } from "./fileSignature.js";
6
+ import { isIdle, parseTimestamp, SUMMARY_MAX_LENGTH, truncate } from "../shared.js";
7
+ const SESSION_LOG_EXTENSION = ".jsonl";
8
+ /** Parsed sessions are small (summary is truncated); cap entries, not bytes. */ const MAX_CACHED_SESSIONS = 256;
9
+ export class GeminiSessionParser {
10
+ sessionCache = new Map();
11
+ /**
12
+ * Parse session file content into GeminiSession.
13
+ * Uses the given content if available; otherwise reads from disk, reusing
14
+ * the previous result while the file's inode, size and mtime are unchanged.
15
+ */ parseSession(cachedContent, filePath) {
16
+ const fileStat = safeStat(filePath);
17
+ if (cachedContent !== undefined) return this.buildSession(cachedContent, filePath, fileStat);
18
+ if (!fileStat) {
19
+ this.sessionCache.delete(filePath);
20
+ return null;
21
+ }
22
+ const signature = fileSignature(fileStat);
23
+ const cached = this.sessionCache.get(filePath);
24
+ if (cached?.signature === signature) return cached.session;
25
+ const content = this.readSessionFile(filePath);
26
+ const session = content === null ? null : this.buildSession(content, filePath, fileStat);
27
+ this.rememberSession(filePath, {
28
+ signature,
29
+ session
30
+ });
31
+ return session;
32
+ }
33
+ rememberSession(filePath, entry) {
34
+ this.sessionCache.delete(filePath);
35
+ this.sessionCache.set(filePath, entry);
36
+ while(this.sessionCache.size > MAX_CACHED_SESSIONS){
37
+ const oldest = this.sessionCache.keys().next().value;
38
+ if (oldest === undefined) break;
39
+ this.sessionCache.delete(oldest);
40
+ }
41
+ }
42
+ buildSession(content, filePath, fileStat) {
43
+ const parsed = this.parseSessionContent(content, filePath);
44
+ if (!parsed?.sessionId) return null;
45
+ const messages = Array.isArray(parsed.messages) ? parsed.messages : [];
46
+ const lastEntry = messages.length > 0 ? messages[messages.length - 1] : undefined;
47
+ const lastActive = parseTimestamp(parsed.lastUpdated) || parseTimestamp(lastEntry?.timestamp) || fileStat?.mtime || new Date();
48
+ const sessionStart = parseTimestamp(parsed.startTime) || lastActive;
49
+ const projectPath = Array.isArray(parsed.directories) && parsed.directories.length > 0 ? parsed.directories[0] : "";
50
+ return {
51
+ sessionId: parsed.sessionId,
52
+ projectPath,
53
+ summary: this.extractSummary(messages),
54
+ sessionStart,
55
+ lastActive,
56
+ lastMessageType: lastEntry?.type
57
+ };
58
+ }
59
+ determineStatus(session) {
60
+ if (isIdle(session.lastActive)) {
61
+ return AgentStatus.IDLE;
62
+ }
63
+ if (session.lastMessageType === "gemini" || session.lastMessageType === "assistant") {
64
+ return AgentStatus.WAITING;
65
+ }
66
+ return AgentStatus.RUNNING;
67
+ }
68
+ /**
69
+ * Read the full conversation from a Gemini CLI session JSON file.
70
+ *
71
+ * Gemini sessions store messages in an array with `type` field — typically
72
+ * 'user' or 'gemini' for visible turns, with tool and system entries mixed in.
73
+ *
74
+ * `tail` only slices the result: the session is a single JSON document, so
75
+ * it cannot be read from the end and is always parsed in full. Callers that
76
+ * poll (the console preview) rely on their mtime cache to skip re-parses.
77
+ */ getConversation(sessionFilePath, options) {
78
+ const verbose = options?.verbose ?? false;
79
+ const content = safeReadFile(sessionFilePath);
80
+ if (content === undefined) return [];
81
+ const parsed = this.parseSessionContent(content, sessionFilePath);
82
+ if (!Array.isArray(parsed?.messages)) return [];
83
+ const messages = [];
84
+ for (const entry of parsed.messages){
85
+ const role = this.roleForEntry(entry?.type, verbose);
86
+ if (!role) continue;
87
+ const text = this.messageText(entry).trim();
88
+ if (!text) continue;
89
+ messages.push({
90
+ role,
91
+ content: text,
92
+ timestamp: entry.timestamp
93
+ });
94
+ }
95
+ return sliceTail(messages, options?.tail);
96
+ }
97
+ /**
98
+ * Read a Gemini session JSON file and produce a {@link SessionSummary}.
99
+ * Returns null when the file is unreadable, the JSON doesn't parse,
100
+ * or the body lacks a sessionId.
101
+ */ fileToSessionSummary(filePath) {
102
+ const content = safeReadFile(filePath);
103
+ if (content === undefined) return null;
104
+ const parsed = this.parseSessionContent(content, filePath);
105
+ if (!parsed?.sessionId) return null;
106
+ const messages = Array.isArray(parsed.messages) ? parsed.messages : [];
107
+ const firstUserMessage = this.extractFirstUserMessage(messages);
108
+ const cwd = Array.isArray(parsed.directories) && parsed.directories.length > 0 ? parsed.directories[0] : "";
109
+ const stat = safeStat(filePath);
110
+ const lastEntryTimestamp = parseTimestamp(messages.length > 0 ? messages[messages.length - 1]?.timestamp : undefined);
111
+ const lastActive = parseTimestamp(parsed.lastUpdated) || lastEntryTimestamp || stat?.mtime || new Date();
112
+ const startedAt = parseTimestamp(parsed.startTime) || stat?.birthtime || stat?.mtime || lastActive;
113
+ return {
114
+ type: "gemini_cli",
115
+ sessionId: parsed.sessionId,
116
+ cwd,
117
+ firstUserMessage,
118
+ lastActive,
119
+ startedAt,
120
+ sessionFilePath: filePath
121
+ };
122
+ }
123
+ /**
124
+ * Parse either session format into the legacy single-document shape:
125
+ * `session-*.json` is one JSON document, `session-*.jsonl` (Gemini CLI
126
+ * 0.46+) is an append-only log replayed by {@link replaySessionLog}.
127
+ */ parseSessionContent(content, filePath) {
128
+ return isSessionLogPath(filePath) ? this.replaySessionLog(content) : this.parseSessionJson(content);
129
+ }
130
+ /**
131
+ * Rebuild a session document from a `.jsonl` log, mirroring Gemini CLI's
132
+ * own loader (`loadConversationRecord`):
133
+ * - a record with a string `id` is a message, upserted by id in place;
134
+ * - `{"$set": {...}}` merges metadata; a `$set.messages` array replaces
135
+ * every message;
136
+ * - `{"$rewindTo": id}` drops that message and all later ones (all
137
+ * messages when the id is unknown);
138
+ * - a record with `sessionId` and `projectHash` (line 1) merges metadata.
139
+ * Unknown operators, non-object lines and a torn trailing line (a write
140
+ * in progress) are ignored.
141
+ */ replaySessionLog(content) {
142
+ let metadata = {};
143
+ const messages = new Map();
144
+ const upsertAll = (entries)=>{
145
+ if (!Array.isArray(entries)) return;
146
+ for (const entry of entries){
147
+ if (isRecord(entry) && typeof entry.id === "string") messages.set(entry.id, entry);
148
+ }
149
+ };
150
+ for (const line of content.split("\n")){
151
+ if (!line.trim()) continue;
152
+ const record = this.parseLogRecord(line);
153
+ if (!record) continue;
154
+ if (typeof record.$rewindTo === "string") {
155
+ this.rewindMessages(messages, record.$rewindTo);
156
+ } else if (typeof record.id === "string") {
157
+ messages.set(record.id, record);
158
+ } else if (isRecord(record.$set)) {
159
+ if (Array.isArray(record.$set.messages)) {
160
+ messages.clear();
161
+ upsertAll(record.$set.messages);
162
+ }
163
+ metadata = {
164
+ ...metadata,
165
+ ...record.$set
166
+ };
167
+ } else if (typeof record.sessionId === "string" && typeof record.projectHash === "string") {
168
+ metadata = {
169
+ ...metadata,
170
+ ...record
171
+ };
172
+ upsertAll(record.messages);
173
+ }
174
+ }
175
+ if (typeof metadata.sessionId !== "string") return null;
176
+ return {
177
+ ...metadata,
178
+ messages: Array.from(messages.values())
179
+ };
180
+ }
181
+ rewindMessages(messages, messageId) {
182
+ if (!messages.has(messageId)) {
183
+ messages.clear();
184
+ return;
185
+ }
186
+ let found = false;
187
+ for (const id of Array.from(messages.keys())){
188
+ if (id === messageId) found = true;
189
+ if (found) messages.delete(id);
190
+ }
191
+ }
192
+ parseLogRecord(line) {
193
+ try {
194
+ const record = JSON.parse(line);
195
+ return isRecord(record) ? record : null;
196
+ } catch {
197
+ return null;
198
+ }
199
+ }
200
+ parseSessionJson(content) {
201
+ try {
202
+ return JSON.parse(content);
203
+ } catch {
204
+ return null;
205
+ }
206
+ }
207
+ readSessionFile(filePath) {
208
+ try {
209
+ return fs.readFileSync(filePath, "utf-8");
210
+ } catch {
211
+ return null;
212
+ }
213
+ }
214
+ roleForEntry(entryType, verbose) {
215
+ if (entryType === "user") return "user";
216
+ if (entryType === "gemini" || entryType === "assistant") return "assistant";
217
+ if (verbose && entryType) return "system";
218
+ return null;
219
+ }
220
+ extractSummary(messages) {
221
+ for(let i = messages.length - 1; i >= 0; i--){
222
+ const entry = messages[i];
223
+ if (entry?.type !== "user") continue;
224
+ const text = this.messageText(entry).trim();
225
+ if (text) return truncate(text, SUMMARY_MAX_LENGTH);
226
+ }
227
+ return "Gemini CLI session active";
228
+ }
229
+ /**
230
+ * Normalize an entry's content/displayContent into a plain string.
231
+ * Prefers displayContent when both are present (matches Gemini CLI's
232
+ * own rendering priority for the /chat UI).
233
+ */ messageText(entry) {
234
+ const displayText = this.resolveContent(entry.displayContent);
235
+ if (displayText) return displayText;
236
+ return this.resolveContent(entry.content);
237
+ }
238
+ /**
239
+ * Collapse a Gemini message content field into plain text.
240
+ * Accepts either a pre-joined string (assistant turns) or a Part[]
241
+ * list (user turns carrying `[{text: "..."}]`). Non-text part
242
+ * variants (data, file) are dropped since this helper is only used
243
+ * for summary/conversation rendering.
244
+ */ resolveContent(content) {
245
+ if (!content) return "";
246
+ if (typeof content === "string") return content;
247
+ if (!Array.isArray(content)) return "";
248
+ const parts = [];
249
+ for (const part of content){
250
+ if (part && typeof part.text === "string" && part.text) {
251
+ parts.push(part.text);
252
+ }
253
+ }
254
+ return parts.join("");
255
+ }
256
+ extractFirstUserMessage(messages) {
257
+ for (const entry of messages){
258
+ if (entry?.type !== "user") continue;
259
+ const text = this.messageText(entry).trim();
260
+ if (text) return text;
261
+ }
262
+ return "";
263
+ }
264
+ }
265
+ /** Gemini CLI 0.46+ writes sessions as append-only `.jsonl` logs. */ export function isSessionLogPath(filePath) {
266
+ return filePath.endsWith(SESSION_LOG_EXTENSION);
267
+ }
268
+ function isRecord(value) {
269
+ return value !== null && typeof value === "object" && !Array.isArray(value);
270
+ }
271
+
272
+ //# sourceMappingURL=GeminiSessionParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/gemini/GeminiSessionParser.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport type {\n ConversationMessage,\n ConversationOptions,\n SessionSummary,\n} from \"../../adapters/AgentAdapter.js\";\nimport { AgentStatus } from \"../../adapters/AgentAdapter.js\";\nimport { sliceTail } from \"../../utils/jsonlTail.js\";\nimport { safeReadFile, safeStat } from \"../../utils/session.js\";\nimport { fileSignature } from \"./fileSignature.js\";\nimport { isIdle, parseTimestamp, SUMMARY_MAX_LENGTH, truncate } from \"../shared.js\";\n\n/**\n * A single Gemini CLI message content part. Mirrors the `{text?: string}`\n * shape that Gemini writes for user message parts (derived from the\n * Gemini API `Content.parts[]` schema). Non-text part variants (data,\n * file, etc.) are preserved via the index signature but ignored by\n * `resolveContent` since the adapter only surfaces human-readable text.\n */\ninterface GeminiContentPart {\n text?: string;\n [key: string]: unknown;\n}\n\ntype GeminiMessageContent = string | GeminiContentPart[];\n\nexport interface GeminiMessageEntry {\n id?: string;\n timestamp?: string;\n type?: string;\n /**\n * Gemini CLI stores two different content shapes depending on the\n * message origin:\n * - `type: \"user\"` messages carry the raw Part[] from userContent.parts\n * (e.g. `[{ text: \"hello\" }]`).\n * - `type: \"gemini\"` (assistant) messages carry a pre-joined string\n * built from `consolidatedParts.filter(p => p.text).join('').trim()`.\n * Both forms must be normalized via resolveContent before any string\n * operation is applied.\n */\n content?: GeminiMessageContent;\n displayContent?: GeminiMessageContent;\n}\n\nexport interface GeminiSessionFile {\n sessionId?: string;\n projectHash?: string;\n startTime?: string;\n lastUpdated?: string;\n messages?: GeminiMessageEntry[];\n directories?: string[];\n kind?: string;\n}\n\nexport interface GeminiSession {\n sessionId: string;\n projectPath: string;\n summary: string;\n sessionStart: Date;\n lastActive: Date;\n lastMessageType?: string;\n}\n\ninterface CachedParsedSession {\n signature: string;\n session: GeminiSession | null;\n}\n\nconst SESSION_LOG_EXTENSION = \".jsonl\";\n/** Parsed sessions are small (summary is truncated); cap entries, not bytes. */\nconst MAX_CACHED_SESSIONS = 256;\n\nexport class GeminiSessionParser {\n private readonly sessionCache = new Map<string, CachedParsedSession>();\n\n /**\n * Parse session file content into GeminiSession.\n * Uses the given content if available; otherwise reads from disk, reusing\n * the previous result while the file's inode, size and mtime are unchanged.\n */\n parseSession(cachedContent: string | undefined, filePath: string): GeminiSession | null {\n const fileStat = safeStat(filePath);\n if (cachedContent !== undefined) return this.buildSession(cachedContent, filePath, fileStat);\n\n if (!fileStat) {\n this.sessionCache.delete(filePath);\n return null;\n }\n\n const signature = fileSignature(fileStat);\n const cached = this.sessionCache.get(filePath);\n if (cached?.signature === signature) return cached.session;\n\n const content = this.readSessionFile(filePath);\n const session = content === null ? null : this.buildSession(content, filePath, fileStat);\n this.rememberSession(filePath, { signature, session });\n return session;\n }\n\n private rememberSession(filePath: string, entry: CachedParsedSession): void {\n this.sessionCache.delete(filePath);\n this.sessionCache.set(filePath, entry);\n while (this.sessionCache.size > MAX_CACHED_SESSIONS) {\n const oldest = this.sessionCache.keys().next().value;\n if (oldest === undefined) break;\n this.sessionCache.delete(oldest);\n }\n }\n\n private buildSession(\n content: string,\n filePath: string,\n fileStat: fs.Stats | undefined,\n ): GeminiSession | null {\n const parsed = this.parseSessionContent(content, filePath);\n if (!parsed?.sessionId) return null;\n\n const messages = Array.isArray(parsed.messages) ? parsed.messages : [];\n const lastEntry = messages.length > 0 ? messages[messages.length - 1] : undefined;\n\n const lastActive =\n parseTimestamp(parsed.lastUpdated) ||\n parseTimestamp(lastEntry?.timestamp) ||\n fileStat?.mtime ||\n new Date();\n\n const sessionStart = parseTimestamp(parsed.startTime) || lastActive;\n const projectPath =\n Array.isArray(parsed.directories) && parsed.directories.length > 0\n ? parsed.directories[0]\n : \"\";\n\n return {\n sessionId: parsed.sessionId,\n projectPath,\n summary: this.extractSummary(messages),\n sessionStart,\n lastActive,\n lastMessageType: lastEntry?.type,\n };\n }\n\n determineStatus(session: GeminiSession): AgentStatus {\n if (isIdle(session.lastActive)) {\n return AgentStatus.IDLE;\n }\n\n if (session.lastMessageType === \"gemini\" || session.lastMessageType === \"assistant\") {\n return AgentStatus.WAITING;\n }\n\n return AgentStatus.RUNNING;\n }\n\n /**\n * Read the full conversation from a Gemini CLI session JSON file.\n *\n * Gemini sessions store messages in an array with `type` field — typically\n * 'user' or 'gemini' for visible turns, with tool and system entries mixed in.\n *\n * `tail` only slices the result: the session is a single JSON document, so\n * it cannot be read from the end and is always parsed in full. Callers that\n * poll (the console preview) rely on their mtime cache to skip re-parses.\n */\n getConversation(sessionFilePath: string, options?: ConversationOptions): ConversationMessage[] {\n const verbose = options?.verbose ?? false;\n const content = safeReadFile(sessionFilePath);\n if (content === undefined) return [];\n\n const parsed = this.parseSessionContent(content, sessionFilePath);\n if (!Array.isArray(parsed?.messages)) return [];\n\n const messages: ConversationMessage[] = [];\n for (const entry of parsed.messages) {\n const role = this.roleForEntry(entry?.type, verbose);\n if (!role) continue;\n\n const text = this.messageText(entry).trim();\n if (!text) continue;\n\n messages.push({\n role,\n content: text,\n timestamp: entry.timestamp,\n });\n }\n\n return sliceTail(messages, options?.tail);\n }\n\n /**\n * Read a Gemini session JSON file and produce a {@link SessionSummary}.\n * Returns null when the file is unreadable, the JSON doesn't parse,\n * or the body lacks a sessionId.\n */\n fileToSessionSummary(filePath: string): SessionSummary | null {\n const content = safeReadFile(filePath);\n if (content === undefined) return null;\n\n const parsed = this.parseSessionContent(content, filePath);\n if (!parsed?.sessionId) return null;\n\n const messages = Array.isArray(parsed.messages) ? parsed.messages : [];\n const firstUserMessage = this.extractFirstUserMessage(messages);\n const cwd =\n Array.isArray(parsed.directories) && parsed.directories.length > 0\n ? parsed.directories[0]\n : \"\";\n\n const stat = safeStat(filePath);\n const lastEntryTimestamp = parseTimestamp(\n messages.length > 0 ? messages[messages.length - 1]?.timestamp : undefined,\n );\n const lastActive =\n parseTimestamp(parsed.lastUpdated) || lastEntryTimestamp || stat?.mtime || new Date();\n const startedAt =\n parseTimestamp(parsed.startTime) || stat?.birthtime || stat?.mtime || lastActive;\n\n return {\n type: \"gemini_cli\",\n sessionId: parsed.sessionId,\n cwd,\n firstUserMessage,\n lastActive,\n startedAt,\n sessionFilePath: filePath,\n };\n }\n\n /**\n * Parse either session format into the legacy single-document shape:\n * `session-*.json` is one JSON document, `session-*.jsonl` (Gemini CLI\n * 0.46+) is an append-only log replayed by {@link replaySessionLog}.\n */\n private parseSessionContent(content: string, filePath: string): GeminiSessionFile | null {\n return isSessionLogPath(filePath)\n ? this.replaySessionLog(content)\n : this.parseSessionJson(content);\n }\n\n /**\n * Rebuild a session document from a `.jsonl` log, mirroring Gemini CLI's\n * own loader (`loadConversationRecord`):\n * - a record with a string `id` is a message, upserted by id in place;\n * - `{\"$set\": {...}}` merges metadata; a `$set.messages` array replaces\n * every message;\n * - `{\"$rewindTo\": id}` drops that message and all later ones (all\n * messages when the id is unknown);\n * - a record with `sessionId` and `projectHash` (line 1) merges metadata.\n * Unknown operators, non-object lines and a torn trailing line (a write\n * in progress) are ignored.\n */\n private replaySessionLog(content: string): GeminiSessionFile | null {\n let metadata: Record<string, unknown> = {};\n const messages = new Map<string, GeminiMessageEntry>();\n const upsertAll = (entries: unknown): void => {\n if (!Array.isArray(entries)) return;\n for (const entry of entries) {\n if (isRecord(entry) && typeof entry.id === \"string\") messages.set(entry.id, entry);\n }\n };\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n const record = this.parseLogRecord(line);\n if (!record) continue;\n\n if (typeof record.$rewindTo === \"string\") {\n this.rewindMessages(messages, record.$rewindTo);\n } else if (typeof record.id === \"string\") {\n messages.set(record.id, record);\n } else if (isRecord(record.$set)) {\n if (Array.isArray(record.$set.messages)) {\n messages.clear();\n upsertAll(record.$set.messages);\n }\n metadata = { ...metadata, ...record.$set };\n } else if (typeof record.sessionId === \"string\" && typeof record.projectHash === \"string\") {\n metadata = { ...metadata, ...record };\n upsertAll(record.messages);\n }\n }\n\n if (typeof metadata.sessionId !== \"string\") return null;\n return { ...(metadata as GeminiSessionFile), messages: Array.from(messages.values()) };\n }\n\n private rewindMessages(messages: Map<string, GeminiMessageEntry>, messageId: string): void {\n if (!messages.has(messageId)) {\n messages.clear();\n return;\n }\n let found = false;\n for (const id of Array.from(messages.keys())) {\n if (id === messageId) found = true;\n if (found) messages.delete(id);\n }\n }\n\n private parseLogRecord(line: string): Record<string, unknown> | null {\n try {\n const record: unknown = JSON.parse(line);\n return isRecord(record) ? record : null;\n } catch {\n return null;\n }\n }\n\n private parseSessionJson(content: string): GeminiSessionFile | null {\n try {\n return JSON.parse(content) as GeminiSessionFile;\n } catch {\n return null;\n }\n }\n\n private readSessionFile(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n }\n\n private roleForEntry(\n entryType: string | undefined,\n verbose: boolean,\n ): ConversationMessage[\"role\"] | null {\n if (entryType === \"user\") return \"user\";\n if (entryType === \"gemini\" || entryType === \"assistant\") return \"assistant\";\n if (verbose && entryType) return \"system\";\n return null;\n }\n\n private extractSummary(messages: GeminiMessageEntry[]): string {\n for (let i = messages.length - 1; i >= 0; i--) {\n const entry = messages[i];\n if (entry?.type !== \"user\") continue;\n const text = this.messageText(entry).trim();\n if (text) return truncate(text, SUMMARY_MAX_LENGTH);\n }\n\n return \"Gemini CLI session active\";\n }\n\n /**\n * Normalize an entry's content/displayContent into a plain string.\n * Prefers displayContent when both are present (matches Gemini CLI's\n * own rendering priority for the /chat UI).\n */\n private messageText(entry: GeminiMessageEntry): string {\n const displayText = this.resolveContent(entry.displayContent);\n if (displayText) return displayText;\n return this.resolveContent(entry.content);\n }\n\n /**\n * Collapse a Gemini message content field into plain text.\n * Accepts either a pre-joined string (assistant turns) or a Part[]\n * list (user turns carrying `[{text: \"...\"}]`). Non-text part\n * variants (data, file) are dropped since this helper is only used\n * for summary/conversation rendering.\n */\n private resolveContent(content: GeminiMessageContent | undefined): string {\n if (!content) return \"\";\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n\n const parts: string[] = [];\n for (const part of content) {\n if (part && typeof part.text === \"string\" && part.text) {\n parts.push(part.text);\n }\n }\n return parts.join(\"\");\n }\n\n private extractFirstUserMessage(messages: GeminiMessageEntry[]): string {\n for (const entry of messages) {\n if (entry?.type !== \"user\") continue;\n const text = this.messageText(entry).trim();\n if (text) return text;\n }\n return \"\";\n }\n}\n\n/** Gemini CLI 0.46+ writes sessions as append-only `.jsonl` logs. */\nexport function isSessionLogPath(filePath: string): boolean {\n return filePath.endsWith(SESSION_LOG_EXTENSION);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n"],"names":["fs","AgentStatus","sliceTail","safeReadFile","safeStat","fileSignature","isIdle","parseTimestamp","SUMMARY_MAX_LENGTH","truncate","SESSION_LOG_EXTENSION","MAX_CACHED_SESSIONS","GeminiSessionParser","sessionCache","Map","parseSession","cachedContent","filePath","fileStat","undefined","buildSession","delete","signature","cached","get","session","content","readSessionFile","rememberSession","entry","set","size","oldest","keys","next","value","parsed","parseSessionContent","sessionId","messages","Array","isArray","lastEntry","length","lastActive","lastUpdated","timestamp","mtime","Date","sessionStart","startTime","projectPath","directories","summary","extractSummary","lastMessageType","type","determineStatus","IDLE","WAITING","RUNNING","getConversation","sessionFilePath","options","verbose","role","roleForEntry","text","messageText","trim","push","tail","fileToSessionSummary","firstUserMessage","extractFirstUserMessage","cwd","stat","lastEntryTimestamp","startedAt","birthtime","isSessionLogPath","replaySessionLog","parseSessionJson","metadata","upsertAll","entries","isRecord","id","line","split","record","parseLogRecord","$rewindTo","rewindMessages","$set","clear","projectHash","from","values","messageId","has","found","JSON","parse","readFileSync","entryType","i","displayText","resolveContent","displayContent","parts","part","join","endsWith"],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type * as fs from "fs";
2
+ /**
3
+ * Identity of a file's current contents derived from `stat` alone:
4
+ * inode, size and mtime. Used to reuse metadata and parse results across
5
+ * refreshes without re-reading unchanged Gemini chat files.
6
+ */
7
+ export declare function fileSignature(stat: fs.Stats): string;
8
+ //# sourceMappingURL=fileSignature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileSignature.d.ts","sourceRoot":"","sources":["../../../src/harnesses/gemini/fileSignature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,EAAE,MAAM,IAAI,CAAC;AAE9B;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Identity of a file's current contents derived from `stat` alone:
3
+ * inode, size and mtime. Used to reuse metadata and parse results across
4
+ * refreshes without re-reading unchanged Gemini chat files.
5
+ */ export function fileSignature(stat) {
6
+ return `${stat.ino}:${stat.size}:${stat.mtimeMs}`;
7
+ }
8
+
9
+ //# sourceMappingURL=fileSignature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/gemini/fileSignature.ts"],"sourcesContent":["import type * as fs from \"fs\";\n\n/**\n * Identity of a file's current contents derived from `stat` alone:\n * inode, size and mtime. Used to reuse metadata and parse results across\n * refreshes without re-reading unchanged Gemini chat files.\n */\nexport function fileSignature(stat: fs.Stats): string {\n return `${stat.ino}:${stat.size}:${stat.mtimeMs}`;\n}\n"],"names":["fileSignature","stat","ino","size","mtimeMs"],"mappings":"AAEA;;;;CAIC,GACD,OAAO,SAASA,cAAcC,IAAc;IAC1C,OAAO,GAAGA,KAAKC,GAAG,CAAC,CAAC,EAAED,KAAKE,IAAI,CAAC,CAAC,EAAEF,KAAKG,OAAO,EAAE;AACnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"GrokAgentMapper.d.ts","sourceRoot":"","sources":["../../../src/providers/grok/GrokAgentMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG7E,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,iBAA2C;IAEhF,iBAAiB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,qBAAqB,GAAG,SAAS;IAc7E,mFAAmF;IACnF,mBAAmB,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS;CAYtE"}
1
+ {"version":3,"file":"GrokAgentMapper.d.ts","sourceRoot":"","sources":["../../../src/harnesses/grok/GrokAgentMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAG7E,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE7E,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,GAAE,iBAA2C;IAEhF,iBAAiB,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,qBAAqB,GAAG,SAAS;IAc7E,mFAAmF;IACnF,mBAAmB,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS;CAGtE"}
@@ -1,5 +1,5 @@
1
- import { AgentStatus } from "../../adapters/AgentAdapter.js";
2
1
  import { generateAgentName } from "../../utils/matching.js";
2
+ import { processOnlyAgent } from "../shared.js";
3
3
  import { GrokSessionParser } from "./GrokSessionParser.js";
4
4
  export class GrokAgentMapper {
5
5
  parser;
@@ -20,16 +20,10 @@ export class GrokAgentMapper {
20
20
  };
21
21
  }
22
22
  /** `cwd` is already resolved by the locator (registry first, then process cwd). */ mapProcessOnlyAgent(processInfo, cwd) {
23
- return {
24
- name: generateAgentName(cwd, processInfo.pid),
25
- type: "grok_cli",
26
- status: AgentStatus.RUNNING,
23
+ return processOnlyAgent("grok_cli", processInfo, {
27
24
  summary: "Grok CLI process running",
28
- pid: processInfo.pid,
29
- projectPath: cwd,
30
- sessionId: `pid-${processInfo.pid}`,
31
- lastActive: new Date()
32
- };
25
+ cwd
26
+ });
33
27
  }
34
28
  }
35
29
 
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/grok/GrokAgentMapper.ts"],"sourcesContent":["import type { AgentInfo, ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { generateAgentName } from \"../../utils/matching.js\";\nimport { processOnlyAgent } from \"../shared.js\";\nimport { GrokSessionParser, type GrokSession } from \"./GrokSessionParser.js\";\n\nexport interface GrokSessionAgentInput {\n session: GrokSession;\n processInfo: ProcessInfo;\n}\n\nexport class GrokAgentMapper {\n constructor(private readonly parser: GrokSessionParser = new GrokSessionParser()) {}\n\n mapSessionToAgent({ session, processInfo }: GrokSessionAgentInput): AgentInfo {\n return {\n name: generateAgentName(session.projectPath, processInfo.pid),\n type: \"grok_cli\",\n status: this.parser.determineStatus(session),\n summary: session.lastUserMessage || \"Grok CLI session active\",\n pid: processInfo.pid,\n projectPath: session.projectPath,\n sessionId: session.sessionId,\n lastActive: session.lastActive,\n sessionFilePath: session.sessionFilePath,\n };\n }\n\n /** `cwd` is already resolved by the locator (registry first, then process cwd). */\n mapProcessOnlyAgent(processInfo: ProcessInfo, cwd: string): AgentInfo {\n return processOnlyAgent(\"grok_cli\", processInfo, { summary: \"Grok CLI process running\", cwd });\n }\n}\n"],"names":["generateAgentName","processOnlyAgent","GrokSessionParser","GrokAgentMapper","parser","mapSessionToAgent","session","processInfo","name","projectPath","pid","type","status","determineStatus","summary","lastUserMessage","sessionId","lastActive","sessionFilePath","mapProcessOnlyAgent","cwd"],"mappings":"AACA,SAASA,iBAAiB,QAAQ,0BAA0B;AAC5D,SAASC,gBAAgB,QAAQ,eAAe;AAChD,SAASC,iBAAiB,QAA0B,yBAAyB;AAO7E,OAAO,MAAMC;;IACX,YAAY,AAAiBC,SAA4B,IAAIF,mBAAmB,CAAE;aAArDE,SAAAA;IAAsD;IAEnFC,kBAAkB,EAAEC,OAAO,EAAEC,WAAW,EAAyB,EAAa;QAC5E,OAAO;YACLC,MAAMR,kBAAkBM,QAAQG,WAAW,EAAEF,YAAYG,GAAG;YAC5DC,MAAM;YACNC,QAAQ,IAAI,CAACR,MAAM,CAACS,eAAe,CAACP;YACpCQ,SAASR,QAAQS,eAAe,IAAI;YACpCL,KAAKH,YAAYG,GAAG;YACpBD,aAAaH,QAAQG,WAAW;YAChCO,WAAWV,QAAQU,SAAS;YAC5BC,YAAYX,QAAQW,UAAU;YAC9BC,iBAAiBZ,QAAQY,eAAe;QAC1C;IACF;IAEA,iFAAiF,GACjFC,oBAAoBZ,WAAwB,EAAEa,GAAW,EAAa;QACpE,OAAOnB,iBAAiB,YAAYM,aAAa;YAAEO,SAAS;YAA4BM;QAAI;IAC9F;AACF"}
@@ -1,4 +1,4 @@
1
- import type { AgentAdapter, AgentInfo, ProcessInfo, ConversationMessage, SessionSummary, ListSessionsOptions, AgentDetectionContext } from "../../adapters/AgentAdapter.js";
1
+ import type { AgentAdapter, AgentInfo, ProcessInfo, ConversationMessage, ConversationOptions, SessionSummary, ListSessionsOptions, AgentDetectionContext } from "../../adapters/AgentAdapter.js";
2
2
  /**
3
3
  * Grok Build CLI Adapter
4
4
  *
@@ -15,6 +15,8 @@ import type { AgentAdapter, AgentInfo, ProcessInfo, ConversationMessage, Session
15
15
  * record of the conversation). The last user turn (the text inside
16
16
  * <user_query>...</user_query>) is the summary; the file's mtime is the last
17
17
  * activity time. summary.json / updates.jsonl are intentionally not used.
18
+ * The summary is cached incrementally across refreshes, so an unchanged
19
+ * transcript is not re-read and an appended one is read only from its tail.
18
20
  */
19
21
  export declare class GrokCliAdapter implements AgentAdapter {
20
22
  readonly type: "grok_cli";
@@ -24,11 +26,9 @@ export declare class GrokCliAdapter implements AgentAdapter {
24
26
  private locator;
25
27
  constructor();
26
28
  canHandle(processInfo: ProcessInfo): boolean;
27
- private isGrokExecutable;
28
29
  detectAgents(context?: AgentDetectionContext): Promise<AgentInfo[]>;
29
- getConversation(sessionFilePath: string, options?: {
30
- verbose?: boolean;
31
- }): ConversationMessage[];
30
+ private detectRunningAgents;
31
+ getConversation(sessionFilePath: string, options?: ConversationOptions): ConversationMessage[];
32
32
  listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]>;
33
33
  findSessionsById(sessionId: string): Promise<SessionSummary[]>;
34
34
  private toSessionSummary;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GrokCliAdapter.d.ts","sourceRoot":"","sources":["../../../src/harnesses/grok/GrokCliAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,gCAAgC,CAAC;AAMxC;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,EAAG,UAAU,CAAU;IACpC,QAAQ,CAAC,YAAY,oBAAqB;IAE1C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,OAAO,CAAqB;;IAQpC,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO;IAItC,YAAY,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YAS3D,mBAAmB;IAoBjC,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,mBAAmB,EAAE;IAIxF,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAgBnE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAapE,OAAO,CAAC,gBAAgB;CAWzB"}
@@ -1,4 +1,4 @@
1
- import { captureProcessSnapshot, executableBasename, filterByProcessNames } from "../../utils/process.js";
1
+ import { findHarnessProcesses, matchesExecutable } from "../shared.js";
2
2
  import { GrokAgentMapper } from "./GrokAgentMapper.js";
3
3
  import { GrokSessionLocator } from "./GrokSessionLocator.js";
4
4
  import { GrokSessionParser } from "./GrokSessionParser.js";
@@ -18,6 +18,8 @@ import { GrokSessionParser } from "./GrokSessionParser.js";
18
18
  * record of the conversation). The last user turn (the text inside
19
19
  * <user_query>...</user_query>) is the summary; the file's mtime is the last
20
20
  * activity time. summary.json / updates.jsonl are intentionally not used.
21
+ * The summary is cached incrementally across refreshes, so an unchanged
22
+ * transcript is not re-read and an appended one is read only from its tail.
21
23
  */ export class GrokCliAdapter {
22
24
  type = "grok_cli";
23
25
  processNames = [
@@ -32,22 +34,24 @@ import { GrokSessionParser } from "./GrokSessionParser.js";
32
34
  this.locator = new GrokSessionLocator();
33
35
  }
34
36
  canHandle(processInfo) {
35
- return this.isGrokExecutable(processInfo.command);
36
- }
37
- isGrokExecutable(command) {
38
- const base = executableBasename(command);
39
- return base === "grok" || base === "grok.exe";
37
+ return matchesExecutable(processInfo.command, "grok");
40
38
  }
41
39
  async detectAgents(context) {
42
- const snapshot = context?.processes ?? await captureProcessSnapshot(this.processNames);
43
- const relevant = filterByProcessNames(snapshot, this.processNames);
44
- const processes = relevant.filter((process)=>this.canHandle(process));
40
+ try {
41
+ return await this.detectRunningAgents(context);
42
+ } finally{
43
+ // Drop cached summaries for sessions that were not part of this refresh
44
+ this.parser.pruneSessionCache();
45
+ }
46
+ }
47
+ async detectRunningAgents(context) {
48
+ const { processes } = await findHarnessProcesses(this, context);
45
49
  if (processes.length === 0) {
46
50
  return [];
47
51
  }
48
52
  const agents = [];
49
53
  for (const { process: proc, cwd, sessionDir } of this.locator.matchRunningProcesses(processes)){
50
- const session = sessionDir ? this.parser.readSession(sessionDir, cwd) : null;
54
+ const session = sessionDir ? this.parser.readSessionIncremental(sessionDir, cwd) : null;
51
55
  if (session) {
52
56
  agents.push(this.mapper.mapSessionToAgent({
53
57
  session,
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/grok/GrokCliAdapter.ts"],"sourcesContent":["import type {\n AgentAdapter,\n AgentInfo,\n ProcessInfo,\n ConversationMessage,\n ConversationOptions,\n SessionSummary,\n ListSessionsOptions,\n AgentDetectionContext,\n} from \"../../adapters/AgentAdapter.js\";\nimport { findHarnessProcesses, matchesExecutable } from \"../shared.js\";\nimport { GrokAgentMapper } from \"./GrokAgentMapper.js\";\nimport { GrokSessionLocator } from \"./GrokSessionLocator.js\";\nimport { GrokSessionParser, type GrokSession } from \"./GrokSessionParser.js\";\n\n/**\n * Grok Build CLI Adapter\n *\n * Detects running Grok Build CLI agents by:\n * 1. Filtering `grok` processes from a shared asynchronous snapshot — Grok is\n * a native binary at ~/.grok/bin/grok, so argv[0] basename is `grok`.\n * 2. Resolving each live process to its working directory via\n * ~/.grok/active_sessions.json, which Grok maintains as a list of\n * { pid, cwd, opened_at } for every running session. The cwd is then encoded\n * into the session group dir ~/.grok/sessions/<encodeURIComponent(cwd)>/, and\n * the most recently active session subdirectory is picked from it. The\n * process cwd from lsof is only a fallback when the PID is not registered.\n * 3. Reading the session transcript from chat_history.jsonl (the authoritative\n * record of the conversation). The last user turn (the text inside\n * <user_query>...</user_query>) is the summary; the file's mtime is the last\n * activity time. summary.json / updates.jsonl are intentionally not used.\n * The summary is cached incrementally across refreshes, so an unchanged\n * transcript is not re-read and an appended one is read only from its tail.\n */\nexport class GrokCliAdapter implements AgentAdapter {\n readonly type = \"grok_cli\" as const;\n readonly processNames = [\"grok\"] as const;\n\n private parser: GrokSessionParser;\n private mapper: GrokAgentMapper;\n private locator: GrokSessionLocator;\n\n constructor() {\n this.parser = new GrokSessionParser();\n this.mapper = new GrokAgentMapper(this.parser);\n this.locator = new GrokSessionLocator();\n }\n\n canHandle(processInfo: ProcessInfo): boolean {\n return matchesExecutable(processInfo.command, \"grok\");\n }\n\n async detectAgents(context?: AgentDetectionContext): Promise<AgentInfo[]> {\n try {\n return await this.detectRunningAgents(context);\n } finally {\n // Drop cached summaries for sessions that were not part of this refresh\n this.parser.pruneSessionCache();\n }\n }\n\n private async detectRunningAgents(context?: AgentDetectionContext): Promise<AgentInfo[]> {\n const { processes } = await findHarnessProcesses(this, context);\n if (processes.length === 0) {\n return [];\n }\n\n const agents: AgentInfo[] = [];\n for (const { process: proc, cwd, sessionDir } of this.locator.matchRunningProcesses(\n processes,\n )) {\n const session = sessionDir ? this.parser.readSessionIncremental(sessionDir, cwd) : null;\n if (session) {\n agents.push(this.mapper.mapSessionToAgent({ session, processInfo: proc }));\n } else {\n agents.push(this.mapper.mapProcessOnlyAgent(proc, cwd));\n }\n }\n return agents;\n }\n\n getConversation(sessionFilePath: string, options?: ConversationOptions): ConversationMessage[] {\n return this.parser.getConversation(sessionFilePath, options);\n }\n\n async listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]> {\n const filterCwd = opts?.cwd;\n const summaries: SessionSummary[] = [];\n\n for (const { sessionDir, defaultCwd } of this.locator.discoverHistoricalSessionDirs()) {\n const session = this.parser.readSession(sessionDir, defaultCwd);\n if (!session) continue;\n\n if (filterCwd !== undefined && session.projectPath !== filterCwd) continue;\n\n summaries.push(this.toSessionSummary(session));\n }\n\n return summaries;\n }\n\n async findSessionsById(sessionId: string): Promise<SessionSummary[]> {\n const summaries: SessionSummary[] = [];\n for (const { sessionDir, defaultCwd } of this.locator.findHistoricalSessionDirsById(\n sessionId,\n )) {\n const session = this.parser.readSession(sessionDir, defaultCwd);\n if (!session) continue;\n\n summaries.push(this.toSessionSummary(session));\n }\n return summaries;\n }\n\n private toSessionSummary(session: GrokSession): SessionSummary {\n return {\n type: this.type,\n sessionId: session.sessionId,\n cwd: session.projectPath,\n firstUserMessage: session.firstUserMessage || \"\",\n lastActive: session.lastActive,\n startedAt: session.sessionStart,\n sessionFilePath: session.sessionFilePath,\n };\n }\n}\n"],"names":["findHarnessProcesses","matchesExecutable","GrokAgentMapper","GrokSessionLocator","GrokSessionParser","GrokCliAdapter","type","processNames","parser","mapper","locator","canHandle","processInfo","command","detectAgents","context","detectRunningAgents","pruneSessionCache","processes","length","agents","process","proc","cwd","sessionDir","matchRunningProcesses","session","readSessionIncremental","push","mapSessionToAgent","mapProcessOnlyAgent","getConversation","sessionFilePath","options","listSessions","opts","filterCwd","summaries","defaultCwd","discoverHistoricalSessionDirs","readSession","undefined","projectPath","toSessionSummary","findSessionsById","sessionId","findHistoricalSessionDirsById","firstUserMessage","lastActive","startedAt","sessionStart"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"GrokSessionLocator.d.ts","sourceRoot":"","sources":["../../../src/providers/grok/GrokSessionLocator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAoBlE,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,OAAO,GAAE,yBAA8B;IASnD;;;;;;OAMG;IACH,qBAAqB,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,gBAAgB,EAAE;IAQnE,4EAA4E;IAC5E,6BAA6B,IAAI,cAAc,EAAE;IAUjD,yEAAyE;IACzE,6BAA6B,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAalE;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,UAAU;IAYlB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;CASvB"}
1
+ {"version":3,"file":"GrokSessionLocator.d.ts","sourceRoot":"","sources":["../../../src/harnesses/grok/GrokSessionLocator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAqBlE,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wEAAwE;AACxE,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,OAAO,GAAE,yBAA8B;IAQnD;;;;;;OAMG;IACH,qBAAqB,CAAC,SAAS,EAAE,WAAW,EAAE,GAAG,gBAAgB,EAAE;IAQnE,4EAA4E;IAC5E,6BAA6B,IAAI,cAAc,EAAE;IAUjD,yEAAyE;IACzE,6BAA6B,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,EAAE;IAalE;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,UAAU;IAYlB;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc;CASvB"}
@@ -1,5 +1,6 @@
1
1
  import * as path from "path";
2
2
  import { isDirectory, isSafePathSegment, safeReadFile, safeReaddir, safeStat } from "../../utils/session.js";
3
+ import { homeDir } from "../shared.js";
3
4
  import { CHAT_HISTORY_FILE } from "./GrokSessionParser.js";
4
5
  const ACTIVE_SESSIONS_FILE = "active_sessions.json";
5
6
  const CWD_FILE = ".cwd";
@@ -10,8 +11,7 @@ export class GrokSessionLocator {
10
11
  // GROK_HOME overrides the ~/.grok base directory; sessions live under
11
12
  // <base>/sessions/ and the active-session registry at
12
13
  // <base>/active_sessions.json.
13
- const homeDir = process.env.HOME || process.env.USERPROFILE || "";
14
- this.baseDir = options.baseDir ?? (process.env.GROK_HOME || path.join(homeDir, ".grok"));
14
+ this.baseDir = options.baseDir ?? (process.env.GROK_HOME || path.join(homeDir(), ".grok"));
15
15
  this.sessionsDir = path.join(this.baseDir, "sessions");
16
16
  }
17
17
  /**
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/harnesses/grok/GrokSessionLocator.ts"],"sourcesContent":["import * as path from \"path\";\nimport type { ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport {\n isDirectory,\n isSafePathSegment,\n safeReadFile,\n safeReaddir,\n safeStat,\n} from \"../../utils/session.js\";\nimport { homeDir } from \"../shared.js\";\nimport { CHAT_HISTORY_FILE } from \"./GrokSessionParser.js\";\n\nconst ACTIVE_SESSIONS_FILE = \"active_sessions.json\";\nconst CWD_FILE = \".cwd\";\n\n/** One entry of ~/.grok/active_sessions.json. */\ninterface ActiveSessionEntry {\n pid?: number;\n cwd?: string;\n opened_at?: number | string;\n}\n\n/** A live Grok process paired with its resolved cwd and (if any) session dir. */\nexport interface GrokProcessMatch {\n process: ProcessInfo;\n cwd: string;\n sessionDir: string | null;\n}\n\n/** A historical session dir plus the cwd decoded from its group dir. */\nexport interface GrokSessionDir {\n sessionDir: string;\n defaultCwd: string;\n}\n\nexport interface GrokSessionLocatorOptions {\n /** Overrides the ~/.grok base directory (defaults to GROK_HOME or ~/.grok). */\n baseDir?: string;\n}\n\nexport class GrokSessionLocator {\n private readonly baseDir: string;\n private readonly sessionsDir: string;\n\n constructor(options: GrokSessionLocatorOptions = {}) {\n // GROK_HOME overrides the ~/.grok base directory; sessions live under\n // <base>/sessions/ and the active-session registry at\n // <base>/active_sessions.json.\n this.baseDir = options.baseDir ?? (process.env.GROK_HOME || path.join(homeDir(), \".grok\"));\n this.sessionsDir = path.join(this.baseDir, \"sessions\");\n }\n\n /**\n * Pair live Grok processes with their session dirs.\n *\n * active_sessions.json is the authoritative pid -> cwd map for live\n * sessions; the lsof-derived process cwd is only a fallback. The most\n * recently active session under that cwd's group dir is picked.\n */\n matchRunningProcesses(processes: ProcessInfo[]): GrokProcessMatch[] {\n const pidToCwd = this.readActiveSessions();\n return processes.map((proc) => {\n const cwd = pidToCwd.get(proc.pid) || proc.cwd || \"\";\n return { process: proc, cwd, sessionDir: cwd ? this.latestSessionDir(cwd) : null };\n });\n }\n\n /** Every session dir under ~/.grok/sessions/, across all project groups. */\n discoverHistoricalSessionDirs(): GrokSessionDir[] {\n const results: GrokSessionDir[] = [];\n for (const { groupDir, defaultCwd } of this.listGroups()) {\n for (const sessionDir of this.listSessionDirs(groupDir)) {\n results.push({ sessionDir, defaultCwd });\n }\n }\n return results;\n }\n\n /** Session dirs named exactly `sessionId`, across all project groups. */\n findHistoricalSessionDirsById(sessionId: string): GrokSessionDir[] {\n if (!isSafePathSegment(sessionId)) return [];\n\n const results: GrokSessionDir[] = [];\n for (const { groupDir, defaultCwd } of this.listGroups()) {\n const sessionDir = path.join(groupDir, sessionId);\n if (isDirectory(sessionDir)) {\n results.push({ sessionDir, defaultCwd });\n }\n }\n return results;\n }\n\n /**\n * Read ~/.grok/active_sessions.json into a pid -> cwd map. Grok writes one\n * { pid, cwd, opened_at } entry per running session and removes it on exit,\n * so this is the reliable way to learn a live process's working directory.\n */\n private readActiveSessions(): Map<number, string> {\n const map = new Map<number, string>();\n const content = safeReadFile(path.join(this.baseDir, ACTIVE_SESSIONS_FILE));\n if (content === undefined) return map;\n\n let entries: unknown;\n try {\n entries = JSON.parse(content);\n } catch {\n return map;\n }\n if (!Array.isArray(entries)) return map;\n\n for (const entry of entries as ActiveSessionEntry[]) {\n if (typeof entry?.pid === \"number\" && typeof entry?.cwd === \"string\" && entry.cwd) {\n map.set(entry.pid, entry.cwd);\n }\n }\n return map;\n }\n\n /**\n * Return the most recently active session subdirectory for a cwd, i.e. the\n * ~/.grok/sessions/<encodeURIComponent(cwd)>/<id>/ whose chat_history.jsonl\n * was written last. Returns null when the group dir or any transcript is\n * missing.\n */\n private latestSessionDir(cwd: string): string | null {\n const groupDir = path.join(this.sessionsDir, encodeURIComponent(cwd));\n if (!isDirectory(groupDir)) return null;\n\n let best: { dir: string; mtimeMs: number } | null = null;\n for (const sessionDir of this.listSessionDirs(groupDir)) {\n const stat = safeStat(path.join(sessionDir, CHAT_HISTORY_FILE));\n if (!stat) continue;\n if (!best || stat.mtimeMs > best.mtimeMs) {\n best = { dir: sessionDir, mtimeMs: stat.mtimeMs };\n }\n }\n return best?.dir ?? null;\n }\n\n private listGroups(): Array<{ groupDir: string; defaultCwd: string }> {\n if (!isDirectory(this.sessionsDir)) return [];\n\n const groups: Array<{ groupDir: string; defaultCwd: string }> = [];\n for (const groupName of safeReaddir(this.sessionsDir)) {\n const groupDir = path.join(this.sessionsDir, groupName);\n if (!isDirectory(groupDir)) continue;\n groups.push({ groupDir, defaultCwd: this.decodeGroupCwd(groupName, groupDir) });\n }\n return groups;\n }\n\n /**\n * Full paths of the session subdirectories directly under a group dir,\n * skipping any non-directory entries (e.g. prompt_history.jsonl).\n */\n private listSessionDirs(groupDir: string): string[] {\n return safeReaddir(groupDir)\n .map((sessionId) => path.join(groupDir, sessionId))\n .filter((sessionDir) => isDirectory(sessionDir));\n }\n\n /**\n * Resolve the working directory a session group dir was created for.\n *\n * The common case is `decodeURIComponent(<group-name>)`. For paths whose\n * encoded form exceeds the filesystem limit Grok uses a slug+hash and records\n * the original path in a `.cwd` file inside the group — prefer that when\n * present.\n */\n private decodeGroupCwd(groupName: string, groupDir: string): string {\n const fromFile = safeReadFile(path.join(groupDir, CWD_FILE));\n if (fromFile !== undefined && fromFile.trim()) return fromFile.trim();\n try {\n return decodeURIComponent(groupName);\n } catch {\n return \"\";\n }\n }\n}\n"],"names":["path","isDirectory","isSafePathSegment","safeReadFile","safeReaddir","safeStat","homeDir","CHAT_HISTORY_FILE","ACTIVE_SESSIONS_FILE","CWD_FILE","GrokSessionLocator","baseDir","sessionsDir","options","process","env","GROK_HOME","join","matchRunningProcesses","processes","pidToCwd","readActiveSessions","map","proc","cwd","get","pid","sessionDir","latestSessionDir","discoverHistoricalSessionDirs","results","groupDir","defaultCwd","listGroups","listSessionDirs","push","findHistoricalSessionDirsById","sessionId","Map","content","undefined","entries","JSON","parse","Array","isArray","entry","set","encodeURIComponent","best","stat","mtimeMs","dir","groups","groupName","decodeGroupCwd","filter","fromFile","trim","decodeURIComponent"],"mappings":"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"}