@codemieai/code 0.0.16 → 0.0.17

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 (408) hide show
  1. package/README.md +62 -5
  2. package/bin/agent-executor.js +7 -28
  3. package/bin/codemie-claude.js +18 -0
  4. package/bin/codemie-codex.js +18 -0
  5. package/bin/codemie-deepagents.js +18 -0
  6. package/bin/codemie-gemini.js +18 -0
  7. package/dist/agents/codemie-code/agent.d.ts.map +1 -1
  8. package/dist/agents/codemie-code/agent.js +3 -32
  9. package/dist/agents/codemie-code/agent.js.map +1 -1
  10. package/dist/agents/codemie-code/tools/planning.d.ts +2 -2
  11. package/dist/agents/core/AgentCLI.d.ts.map +1 -1
  12. package/dist/agents/core/AgentCLI.js +25 -59
  13. package/dist/agents/core/AgentCLI.js.map +1 -1
  14. package/dist/agents/core/BaseAgentAdapter.d.ts +9 -1
  15. package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
  16. package/dist/agents/core/BaseAgentAdapter.js +103 -10
  17. package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
  18. package/dist/agents/core/BaseMetricsAdapter.d.ts +64 -0
  19. package/dist/agents/core/BaseMetricsAdapter.d.ts.map +1 -0
  20. package/dist/agents/core/BaseMetricsAdapter.js +74 -0
  21. package/dist/agents/core/BaseMetricsAdapter.js.map +1 -0
  22. package/dist/agents/core/types.d.ts +1 -0
  23. package/dist/agents/core/types.d.ts.map +1 -1
  24. package/dist/agents/plugins/claude.metrics.d.ts +112 -0
  25. package/dist/agents/plugins/claude.metrics.d.ts.map +1 -0
  26. package/dist/agents/plugins/claude.metrics.js +700 -0
  27. package/dist/agents/plugins/claude.metrics.js.map +1 -0
  28. package/dist/agents/plugins/claude.plugin.d.ts +9 -0
  29. package/dist/agents/plugins/claude.plugin.d.ts.map +1 -1
  30. package/dist/agents/plugins/claude.plugin.js +52 -10
  31. package/dist/agents/plugins/claude.plugin.js.map +1 -1
  32. package/dist/agents/plugins/codemie-code.plugin.d.ts.map +1 -1
  33. package/dist/agents/plugins/codemie-code.plugin.js +45 -13
  34. package/dist/agents/plugins/codemie-code.plugin.js.map +1 -1
  35. package/dist/agents/plugins/codex.plugin.d.ts.map +1 -1
  36. package/dist/agents/plugins/codex.plugin.js +0 -2
  37. package/dist/agents/plugins/codex.plugin.js.map +1 -1
  38. package/dist/agents/plugins/gemini.plugin.d.ts.map +1 -1
  39. package/dist/agents/plugins/gemini.plugin.js +0 -7
  40. package/dist/agents/plugins/gemini.plugin.js.map +1 -1
  41. package/dist/agents/plugins/history-parser.d.ts +52 -0
  42. package/dist/agents/plugins/history-parser.d.ts.map +1 -0
  43. package/dist/agents/plugins/history-parser.js +155 -0
  44. package/dist/agents/plugins/history-parser.js.map +1 -0
  45. package/dist/cli/commands/analytics/aggregator.d.ts +58 -0
  46. package/dist/cli/commands/analytics/aggregator.d.ts.map +1 -0
  47. package/dist/cli/commands/analytics/aggregator.js +702 -0
  48. package/dist/cli/commands/analytics/aggregator.js.map +1 -0
  49. package/dist/cli/commands/analytics/data-loader.d.ts +84 -0
  50. package/dist/cli/commands/analytics/data-loader.d.ts.map +1 -0
  51. package/dist/cli/commands/analytics/data-loader.js +211 -0
  52. package/dist/cli/commands/analytics/data-loader.js.map +1 -0
  53. package/dist/cli/commands/analytics/exporter.d.ts +20 -0
  54. package/dist/cli/commands/analytics/exporter.d.ts.map +1 -0
  55. package/dist/cli/commands/analytics/exporter.js +103 -0
  56. package/dist/cli/commands/analytics/exporter.js.map +1 -0
  57. package/dist/cli/commands/analytics/formatter.d.ts +49 -0
  58. package/dist/cli/commands/analytics/formatter.d.ts.map +1 -0
  59. package/dist/cli/commands/analytics/formatter.js +309 -0
  60. package/dist/cli/commands/analytics/formatter.js.map +1 -0
  61. package/dist/cli/commands/analytics/index.d.ts +6 -0
  62. package/dist/cli/commands/analytics/index.d.ts.map +1 -0
  63. package/dist/cli/commands/analytics/index.js +157 -0
  64. package/dist/cli/commands/analytics/index.js.map +1 -0
  65. package/dist/cli/commands/analytics/model-normalizer.d.ts +21 -0
  66. package/dist/cli/commands/analytics/model-normalizer.d.ts.map +1 -0
  67. package/dist/cli/commands/analytics/model-normalizer.js +44 -0
  68. package/dist/cli/commands/analytics/model-normalizer.js.map +1 -0
  69. package/dist/cli/commands/analytics/types.d.ts +188 -0
  70. package/dist/cli/commands/analytics/types.d.ts.map +1 -0
  71. package/dist/cli/commands/analytics/types.js +6 -0
  72. package/dist/cli/commands/analytics/types.js.map +1 -0
  73. package/dist/cli/commands/doctor/checks/AwsCliCheck.d.ts +9 -0
  74. package/dist/cli/commands/doctor/checks/AwsCliCheck.d.ts.map +1 -0
  75. package/dist/cli/commands/doctor/checks/AwsCliCheck.js +28 -0
  76. package/dist/cli/commands/doctor/checks/AwsCliCheck.js.map +1 -0
  77. package/dist/cli/commands/doctor/checks/PythonCheck.d.ts.map +1 -1
  78. package/dist/cli/commands/doctor/checks/PythonCheck.js +10 -0
  79. package/dist/cli/commands/doctor/checks/PythonCheck.js.map +1 -1
  80. package/dist/cli/commands/doctor/checks/WorkflowsCheck.d.ts.map +1 -1
  81. package/dist/cli/commands/doctor/checks/WorkflowsCheck.js +2 -1
  82. package/dist/cli/commands/doctor/checks/WorkflowsCheck.js.map +1 -1
  83. package/dist/cli/commands/doctor/checks/index.d.ts +1 -0
  84. package/dist/cli/commands/doctor/checks/index.d.ts.map +1 -1
  85. package/dist/cli/commands/doctor/checks/index.js +1 -0
  86. package/dist/cli/commands/doctor/checks/index.js.map +1 -1
  87. package/dist/cli/commands/doctor/index.d.ts.map +1 -1
  88. package/dist/cli/commands/doctor/index.js +85 -3
  89. package/dist/cli/commands/doctor/index.js.map +1 -1
  90. package/dist/cli/commands/profile.d.ts.map +1 -1
  91. package/dist/cli/commands/profile.js +49 -89
  92. package/dist/cli/commands/profile.js.map +1 -1
  93. package/dist/cli/commands/setup.js +1 -21
  94. package/dist/cli/commands/setup.js.map +1 -1
  95. package/dist/cli/index.js +1 -1
  96. package/dist/cli/index.js.map +1 -1
  97. package/dist/env/types.d.ts +14 -2
  98. package/dist/env/types.d.ts.map +1 -1
  99. package/dist/env/types.js.map +1 -1
  100. package/dist/metrics/MetricsOrchestrator.d.ts +67 -0
  101. package/dist/metrics/MetricsOrchestrator.d.ts.map +1 -0
  102. package/dist/metrics/MetricsOrchestrator.js +287 -0
  103. package/dist/metrics/MetricsOrchestrator.js.map +1 -0
  104. package/dist/metrics/config.d.ts +38 -0
  105. package/dist/metrics/config.d.ts.map +1 -0
  106. package/dist/metrics/config.js +80 -0
  107. package/dist/metrics/config.js.map +1 -0
  108. package/dist/metrics/core/DeltaWriter.d.ts +49 -0
  109. package/dist/metrics/core/DeltaWriter.d.ts.map +1 -0
  110. package/dist/metrics/core/DeltaWriter.js +146 -0
  111. package/dist/metrics/core/DeltaWriter.js.map +1 -0
  112. package/dist/metrics/core/FileSnapshotter.d.ts +22 -0
  113. package/dist/metrics/core/FileSnapshotter.d.ts.map +1 -0
  114. package/dist/metrics/core/FileSnapshotter.js +74 -0
  115. package/dist/metrics/core/FileSnapshotter.js.map +1 -0
  116. package/dist/metrics/core/SessionCorrelator.d.ts +34 -0
  117. package/dist/metrics/core/SessionCorrelator.d.ts.map +1 -0
  118. package/dist/metrics/core/SessionCorrelator.js +115 -0
  119. package/dist/metrics/core/SessionCorrelator.js.map +1 -0
  120. package/dist/metrics/core/SyncStateManager.d.ts +69 -0
  121. package/dist/metrics/core/SyncStateManager.d.ts.map +1 -0
  122. package/dist/metrics/core/SyncStateManager.js +284 -0
  123. package/dist/metrics/core/SyncStateManager.js.map +1 -0
  124. package/dist/metrics/index.d.ts +9 -0
  125. package/dist/metrics/index.d.ts.map +1 -0
  126. package/dist/metrics/index.js +11 -0
  127. package/dist/metrics/index.js.map +1 -0
  128. package/dist/metrics/session/SessionStore.d.ts +43 -0
  129. package/dist/metrics/session/SessionStore.d.ts.map +1 -0
  130. package/dist/metrics/session/SessionStore.js +142 -0
  131. package/dist/metrics/session/SessionStore.js.map +1 -0
  132. package/dist/metrics/sync/MetricsApiClient.d.ts +32 -0
  133. package/dist/metrics/sync/MetricsApiClient.d.ts.map +1 -0
  134. package/dist/metrics/sync/MetricsApiClient.js +155 -0
  135. package/dist/metrics/sync/MetricsApiClient.js.map +1 -0
  136. package/dist/metrics/sync/aggregator.d.ts +13 -0
  137. package/dist/metrics/sync/aggregator.d.ts.map +1 -0
  138. package/dist/metrics/sync/aggregator.js +196 -0
  139. package/dist/metrics/sync/aggregator.js.map +1 -0
  140. package/dist/metrics/sync/index.d.ts +10 -0
  141. package/dist/metrics/sync/index.d.ts.map +1 -0
  142. package/dist/metrics/sync/index.js +10 -0
  143. package/dist/metrics/sync/index.js.map +1 -0
  144. package/dist/metrics/sync/jsonl-writer.d.ts +28 -0
  145. package/dist/metrics/sync/jsonl-writer.d.ts.map +1 -0
  146. package/dist/metrics/sync/jsonl-writer.js +72 -0
  147. package/dist/metrics/sync/jsonl-writer.js.map +1 -0
  148. package/dist/metrics/sync/types.d.ts +72 -0
  149. package/dist/metrics/sync/types.d.ts.map +1 -0
  150. package/dist/metrics/sync/types.js +7 -0
  151. package/dist/metrics/sync/types.js.map +1 -0
  152. package/dist/metrics/types.d.ts +308 -0
  153. package/dist/metrics/types.d.ts.map +1 -0
  154. package/dist/metrics/types.js +8 -0
  155. package/dist/metrics/types.js.map +1 -0
  156. package/dist/providers/index.d.ts +2 -0
  157. package/dist/providers/index.d.ts.map +1 -1
  158. package/dist/providers/index.js +2 -0
  159. package/dist/providers/index.js.map +1 -1
  160. package/dist/providers/integration/setup-ui.d.ts +1 -1
  161. package/dist/providers/integration/setup-ui.d.ts.map +1 -1
  162. package/dist/providers/integration/setup-ui.js +51 -6
  163. package/dist/providers/integration/setup-ui.js.map +1 -1
  164. package/dist/providers/plugins/bedrock/bedrock.health.d.ts +53 -0
  165. package/dist/providers/plugins/bedrock/bedrock.health.d.ts.map +1 -0
  166. package/dist/providers/plugins/bedrock/bedrock.health.js +115 -0
  167. package/dist/providers/plugins/bedrock/bedrock.health.js.map +1 -0
  168. package/dist/providers/plugins/bedrock/bedrock.models.d.ts +26 -0
  169. package/dist/providers/plugins/bedrock/bedrock.models.d.ts.map +1 -0
  170. package/dist/providers/plugins/bedrock/bedrock.models.js +89 -0
  171. package/dist/providers/plugins/bedrock/bedrock.models.js.map +1 -0
  172. package/dist/providers/plugins/bedrock/bedrock.setup-steps.d.ts +12 -0
  173. package/dist/providers/plugins/bedrock/bedrock.setup-steps.d.ts.map +1 -0
  174. package/dist/providers/plugins/bedrock/bedrock.setup-steps.js +308 -0
  175. package/dist/providers/plugins/bedrock/bedrock.setup-steps.js.map +1 -0
  176. package/dist/providers/plugins/bedrock/bedrock.template.d.ts +11 -0
  177. package/dist/providers/plugins/bedrock/bedrock.template.d.ts.map +1 -0
  178. package/dist/providers/plugins/bedrock/bedrock.template.js +85 -0
  179. package/dist/providers/plugins/bedrock/bedrock.template.js.map +1 -0
  180. package/dist/providers/plugins/bedrock/index.d.ts +11 -0
  181. package/dist/providers/plugins/bedrock/index.d.ts.map +1 -0
  182. package/dist/providers/plugins/bedrock/index.js +11 -0
  183. package/dist/providers/plugins/bedrock/index.js.map +1 -0
  184. package/dist/providers/plugins/ollama/ollama.template.d.ts.map +1 -1
  185. package/dist/providers/plugins/ollama/ollama.template.js +2 -0
  186. package/dist/providers/plugins/ollama/ollama.template.js.map +1 -1
  187. package/dist/providers/plugins/sso/sso.http-client.d.ts +2 -0
  188. package/dist/providers/plugins/sso/sso.http-client.d.ts.map +1 -1
  189. package/dist/providers/plugins/sso/sso.http-client.js +9 -3
  190. package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
  191. package/dist/proxy/http-client.d.ts.map +1 -1
  192. package/dist/proxy/http-client.js +49 -14
  193. package/dist/proxy/http-client.js.map +1 -1
  194. package/dist/proxy/plugins/endpoint-blocker.plugin.d.ts +19 -0
  195. package/dist/proxy/plugins/endpoint-blocker.plugin.d.ts.map +1 -0
  196. package/dist/proxy/plugins/endpoint-blocker.plugin.js +61 -0
  197. package/dist/proxy/plugins/endpoint-blocker.plugin.js.map +1 -0
  198. package/dist/proxy/plugins/header-injection.plugin.js +3 -0
  199. package/dist/proxy/plugins/header-injection.plugin.js.map +1 -1
  200. package/dist/proxy/plugins/index.d.ts +3 -1
  201. package/dist/proxy/plugins/index.d.ts.map +1 -1
  202. package/dist/proxy/plugins/index.js +5 -1
  203. package/dist/proxy/plugins/index.js.map +1 -1
  204. package/dist/proxy/plugins/logging.plugin.d.ts +3 -3
  205. package/dist/proxy/plugins/logging.plugin.js +84 -20
  206. package/dist/proxy/plugins/logging.plugin.js.map +1 -1
  207. package/dist/proxy/plugins/metrics-sync.plugin.d.ts +33 -0
  208. package/dist/proxy/plugins/metrics-sync.plugin.d.ts.map +1 -0
  209. package/dist/proxy/plugins/metrics-sync.plugin.js +310 -0
  210. package/dist/proxy/plugins/metrics-sync.plugin.js.map +1 -0
  211. package/dist/proxy/plugins/registry.d.ts.map +1 -1
  212. package/dist/proxy/plugins/registry.js +8 -1
  213. package/dist/proxy/plugins/registry.js.map +1 -1
  214. package/dist/proxy/plugins/types.d.ts +6 -2
  215. package/dist/proxy/plugins/types.d.ts.map +1 -1
  216. package/dist/proxy/types.d.ts +7 -0
  217. package/dist/proxy/types.d.ts.map +1 -1
  218. package/dist/utils/ascii-logo.d.ts +21 -0
  219. package/dist/utils/ascii-logo.d.ts.map +1 -0
  220. package/dist/utils/ascii-logo.js +75 -0
  221. package/dist/utils/ascii-logo.js.map +1 -0
  222. package/dist/utils/codemie-proxy.d.ts +0 -6
  223. package/dist/utils/codemie-proxy.d.ts.map +1 -1
  224. package/dist/utils/codemie-proxy.js +46 -56
  225. package/dist/utils/codemie-proxy.js.map +1 -1
  226. package/dist/utils/config-loader.d.ts.map +1 -1
  227. package/dist/utils/config-loader.js +22 -6
  228. package/dist/utils/config-loader.js.map +1 -1
  229. package/dist/utils/exec.d.ts +11 -0
  230. package/dist/utils/exec.d.ts.map +1 -1
  231. package/dist/utils/exec.js +17 -1
  232. package/dist/utils/exec.js.map +1 -1
  233. package/dist/utils/goodbye-messages.d.ts +13 -0
  234. package/dist/utils/goodbye-messages.d.ts.map +1 -0
  235. package/dist/utils/goodbye-messages.js +245 -0
  236. package/dist/utils/goodbye-messages.js.map +1 -0
  237. package/dist/utils/json-parser.d.ts +52 -0
  238. package/dist/utils/json-parser.d.ts.map +1 -0
  239. package/dist/utils/json-parser.js +126 -0
  240. package/dist/utils/json-parser.js.map +1 -0
  241. package/dist/utils/logger.d.ts +37 -1
  242. package/dist/utils/logger.d.ts.map +1 -1
  243. package/dist/utils/logger.js +92 -20
  244. package/dist/utils/logger.js.map +1 -1
  245. package/dist/utils/sanitize.d.ts.map +1 -1
  246. package/dist/utils/sanitize.js +0 -1
  247. package/dist/utils/sanitize.js.map +1 -1
  248. package/dist/utils/which.d.ts +20 -0
  249. package/dist/utils/which.d.ts.map +1 -0
  250. package/dist/utils/which.js +47 -0
  251. package/dist/utils/which.js.map +1 -0
  252. package/package.json +10 -5
  253. package/dist/analytics/aggregation/adapters/claude.adapter.d.ts +0 -37
  254. package/dist/analytics/aggregation/adapters/claude.adapter.d.ts.map +0 -1
  255. package/dist/analytics/aggregation/adapters/claude.adapter.js +0 -531
  256. package/dist/analytics/aggregation/adapters/claude.adapter.js.map +0 -1
  257. package/dist/analytics/aggregation/adapters/codex.adapter.d.ts +0 -25
  258. package/dist/analytics/aggregation/adapters/codex.adapter.d.ts.map +0 -1
  259. package/dist/analytics/aggregation/adapters/codex.adapter.js +0 -396
  260. package/dist/analytics/aggregation/adapters/codex.adapter.js.map +0 -1
  261. package/dist/analytics/aggregation/adapters/gemini.adapter.d.ts +0 -36
  262. package/dist/analytics/aggregation/adapters/gemini.adapter.d.ts.map +0 -1
  263. package/dist/analytics/aggregation/adapters/gemini.adapter.js +0 -365
  264. package/dist/analytics/aggregation/adapters/gemini.adapter.js.map +0 -1
  265. package/dist/analytics/aggregation/adapters/index.d.ts +0 -7
  266. package/dist/analytics/aggregation/adapters/index.d.ts.map +0 -1
  267. package/dist/analytics/aggregation/adapters/index.js +0 -7
  268. package/dist/analytics/aggregation/adapters/index.js.map +0 -1
  269. package/dist/analytics/aggregation/aggregator.d.ts +0 -49
  270. package/dist/analytics/aggregation/aggregator.d.ts.map +0 -1
  271. package/dist/analytics/aggregation/aggregator.js +0 -239
  272. package/dist/analytics/aggregation/aggregator.js.map +0 -1
  273. package/dist/analytics/aggregation/core/BaseAnalyticsAdapter.d.ts +0 -99
  274. package/dist/analytics/aggregation/core/BaseAnalyticsAdapter.d.ts.map +0 -1
  275. package/dist/analytics/aggregation/core/BaseAnalyticsAdapter.js +0 -110
  276. package/dist/analytics/aggregation/core/BaseAnalyticsAdapter.js.map +0 -1
  277. package/dist/analytics/aggregation/core/adapter.interface.d.ts +0 -76
  278. package/dist/analytics/aggregation/core/adapter.interface.d.ts.map +0 -1
  279. package/dist/analytics/aggregation/core/adapter.interface.js +0 -9
  280. package/dist/analytics/aggregation/core/adapter.interface.js.map +0 -1
  281. package/dist/analytics/aggregation/core/aggregation-utils.d.ts +0 -86
  282. package/dist/analytics/aggregation/core/aggregation-utils.d.ts.map +0 -1
  283. package/dist/analytics/aggregation/core/aggregation-utils.js +0 -126
  284. package/dist/analytics/aggregation/core/aggregation-utils.js.map +0 -1
  285. package/dist/analytics/aggregation/core/discovery.d.ts +0 -40
  286. package/dist/analytics/aggregation/core/discovery.d.ts.map +0 -1
  287. package/dist/analytics/aggregation/core/discovery.js +0 -132
  288. package/dist/analytics/aggregation/core/discovery.js.map +0 -1
  289. package/dist/analytics/aggregation/core/file-utils.d.ts +0 -24
  290. package/dist/analytics/aggregation/core/file-utils.d.ts.map +0 -1
  291. package/dist/analytics/aggregation/core/file-utils.js +0 -143
  292. package/dist/analytics/aggregation/core/file-utils.js.map +0 -1
  293. package/dist/analytics/aggregation/core/index.d.ts +0 -14
  294. package/dist/analytics/aggregation/core/index.d.ts.map +0 -1
  295. package/dist/analytics/aggregation/core/index.js +0 -14
  296. package/dist/analytics/aggregation/core/index.js.map +0 -1
  297. package/dist/analytics/aggregation/core/project-mapping.d.ts +0 -50
  298. package/dist/analytics/aggregation/core/project-mapping.d.ts.map +0 -1
  299. package/dist/analytics/aggregation/core/project-mapping.js +0 -102
  300. package/dist/analytics/aggregation/core/project-mapping.js.map +0 -1
  301. package/dist/analytics/aggregation/core/streaming.d.ts +0 -26
  302. package/dist/analytics/aggregation/core/streaming.d.ts.map +0 -1
  303. package/dist/analytics/aggregation/core/streaming.js +0 -58
  304. package/dist/analytics/aggregation/core/streaming.js.map +0 -1
  305. package/dist/analytics/aggregation/core/user-prompt-source.d.ts +0 -81
  306. package/dist/analytics/aggregation/core/user-prompt-source.d.ts.map +0 -1
  307. package/dist/analytics/aggregation/core/user-prompt-source.js +0 -69
  308. package/dist/analytics/aggregation/core/user-prompt-source.js.map +0 -1
  309. package/dist/analytics/aggregation/core/user-prompt-sources/json.d.ts +0 -49
  310. package/dist/analytics/aggregation/core/user-prompt-sources/json.d.ts.map +0 -1
  311. package/dist/analytics/aggregation/core/user-prompt-sources/json.js +0 -66
  312. package/dist/analytics/aggregation/core/user-prompt-sources/json.js.map +0 -1
  313. package/dist/analytics/aggregation/core/user-prompt-sources/jsonl.d.ts +0 -43
  314. package/dist/analytics/aggregation/core/user-prompt-sources/jsonl.d.ts.map +0 -1
  315. package/dist/analytics/aggregation/core/user-prompt-sources/jsonl.js +0 -56
  316. package/dist/analytics/aggregation/core/user-prompt-sources/jsonl.js.map +0 -1
  317. package/dist/analytics/aggregation/index.d.ts +0 -8
  318. package/dist/analytics/aggregation/index.d.ts.map +0 -1
  319. package/dist/analytics/aggregation/index.js +0 -8
  320. package/dist/analytics/aggregation/index.js.map +0 -1
  321. package/dist/analytics/aggregation/types.d.ts +0 -278
  322. package/dist/analytics/aggregation/types.d.ts.map +0 -1
  323. package/dist/analytics/aggregation/types.js +0 -8
  324. package/dist/analytics/aggregation/types.js.map +0 -1
  325. package/dist/analytics/collector.d.ts +0 -46
  326. package/dist/analytics/collector.d.ts.map +0 -1
  327. package/dist/analytics/collector.js +0 -83
  328. package/dist/analytics/collector.js.map +0 -1
  329. package/dist/analytics/config.d.ts +0 -15
  330. package/dist/analytics/config.d.ts.map +0 -1
  331. package/dist/analytics/config.js +0 -65
  332. package/dist/analytics/config.js.map +0 -1
  333. package/dist/analytics/index.d.ts +0 -99
  334. package/dist/analytics/index.d.ts.map +0 -1
  335. package/dist/analytics/index.js +0 -280
  336. package/dist/analytics/index.js.map +0 -1
  337. package/dist/analytics/plugins/api-metrics.plugin.d.ts +0 -26
  338. package/dist/analytics/plugins/api-metrics.plugin.d.ts.map +0 -1
  339. package/dist/analytics/plugins/api-metrics.plugin.js +0 -97
  340. package/dist/analytics/plugins/api-metrics.plugin.js.map +0 -1
  341. package/dist/analytics/plugins/index.d.ts +0 -15
  342. package/dist/analytics/plugins/index.d.ts.map +0 -1
  343. package/dist/analytics/plugins/index.js +0 -15
  344. package/dist/analytics/plugins/index.js.map +0 -1
  345. package/dist/analytics/plugins/model-metrics.plugin.d.ts +0 -39
  346. package/dist/analytics/plugins/model-metrics.plugin.d.ts.map +0 -1
  347. package/dist/analytics/plugins/model-metrics.plugin.js +0 -105
  348. package/dist/analytics/plugins/model-metrics.plugin.js.map +0 -1
  349. package/dist/analytics/plugins/provider-metrics.plugin.d.ts +0 -41
  350. package/dist/analytics/plugins/provider-metrics.plugin.d.ts.map +0 -1
  351. package/dist/analytics/plugins/provider-metrics.plugin.js +0 -123
  352. package/dist/analytics/plugins/provider-metrics.plugin.js.map +0 -1
  353. package/dist/analytics/plugins/types.d.ts +0 -61
  354. package/dist/analytics/plugins/types.d.ts.map +0 -1
  355. package/dist/analytics/plugins/types.js +0 -54
  356. package/dist/analytics/plugins/types.js.map +0 -1
  357. package/dist/analytics/privacy.d.ts +0 -10
  358. package/dist/analytics/privacy.d.ts.map +0 -1
  359. package/dist/analytics/privacy.js +0 -20
  360. package/dist/analytics/privacy.js.map +0 -1
  361. package/dist/analytics/remote-submission/cursor-manager.d.ts +0 -71
  362. package/dist/analytics/remote-submission/cursor-manager.d.ts.map +0 -1
  363. package/dist/analytics/remote-submission/cursor-manager.js +0 -204
  364. package/dist/analytics/remote-submission/cursor-manager.js.map +0 -1
  365. package/dist/analytics/remote-submission/index.d.ts +0 -12
  366. package/dist/analytics/remote-submission/index.d.ts.map +0 -1
  367. package/dist/analytics/remote-submission/index.js +0 -11
  368. package/dist/analytics/remote-submission/index.js.map +0 -1
  369. package/dist/analytics/remote-submission/lock-manager.d.ts +0 -71
  370. package/dist/analytics/remote-submission/lock-manager.d.ts.map +0 -1
  371. package/dist/analytics/remote-submission/lock-manager.js +0 -238
  372. package/dist/analytics/remote-submission/lock-manager.js.map +0 -1
  373. package/dist/analytics/remote-submission/metric-transformer.d.ts +0 -21
  374. package/dist/analytics/remote-submission/metric-transformer.d.ts.map +0 -1
  375. package/dist/analytics/remote-submission/metric-transformer.js +0 -82
  376. package/dist/analytics/remote-submission/metric-transformer.js.map +0 -1
  377. package/dist/analytics/remote-submission/submitter.d.ts +0 -79
  378. package/dist/analytics/remote-submission/submitter.d.ts.map +0 -1
  379. package/dist/analytics/remote-submission/submitter.js +0 -362
  380. package/dist/analytics/remote-submission/submitter.js.map +0 -1
  381. package/dist/analytics/remote-submission/types.d.ts +0 -123
  382. package/dist/analytics/remote-submission/types.d.ts.map +0 -1
  383. package/dist/analytics/remote-submission/types.js +0 -13
  384. package/dist/analytics/remote-submission/types.js.map +0 -1
  385. package/dist/analytics/session.d.ts +0 -56
  386. package/dist/analytics/session.d.ts.map +0 -1
  387. package/dist/analytics/session.js +0 -95
  388. package/dist/analytics/session.js.map +0 -1
  389. package/dist/analytics/types.d.ts +0 -104
  390. package/dist/analytics/types.d.ts.map +0 -1
  391. package/dist/analytics/types.js +0 -15
  392. package/dist/analytics/types.js.map +0 -1
  393. package/dist/analytics/writer.d.ts +0 -18
  394. package/dist/analytics/writer.d.ts.map +0 -1
  395. package/dist/analytics/writer.js +0 -44
  396. package/dist/analytics/writer.js.map +0 -1
  397. package/dist/cli/commands/analytics.d.ts +0 -3
  398. package/dist/cli/commands/analytics.d.ts.map +0 -1
  399. package/dist/cli/commands/analytics.js +0 -748
  400. package/dist/cli/commands/analytics.js.map +0 -1
  401. package/dist/utils/analytics-reader.d.ts +0 -117
  402. package/dist/utils/analytics-reader.d.ts.map +0 -1
  403. package/dist/utils/analytics-reader.js +0 -421
  404. package/dist/utils/analytics-reader.js.map +0 -1
  405. package/dist/utils/date-formatter.d.ts +0 -88
  406. package/dist/utils/date-formatter.d.ts.map +0 -1
  407. package/dist/utils/date-formatter.js +0 -133
  408. package/dist/utils/date-formatter.js.map +0 -1
@@ -0,0 +1,700 @@
1
+ /**
2
+ * Claude Metrics Adapter
3
+ *
4
+ * Implements metrics support for Claude Code agent.
5
+ * Handles Claude-specific file formats and parsing logic.
6
+ */
7
+ import { readFile, readdir } from 'fs/promises';
8
+ import { extname, join, dirname } from 'path';
9
+ import { homedir } from 'os';
10
+ import { existsSync } from 'fs';
11
+ import { BaseMetricsAdapter } from '../core/BaseMetricsAdapter.js';
12
+ import { logger } from '../../utils/logger.js';
13
+ import { parseMultiLineJSON } from '../../utils/json-parser.js';
14
+ import { HistoryParser } from './history-parser.js';
15
+ export class ClaudeMetricsAdapter extends BaseMetricsAdapter {
16
+ // Note: dataPaths now comes from ClaudePluginMetadata passed via constructor
17
+ /**
18
+ * Check if file matches Claude session pattern
19
+ * Pattern: ~/.claude/projects/{hash}/{session-id}.jsonl
20
+ * Note: Claude uses JSONL (JSON Lines) format, not regular JSON
21
+ * Matches UUID format but EXCLUDES agent-* files (those are sub-agents)
22
+ */
23
+ matchesSessionPattern(path) {
24
+ // Explicitly reject agent-* files (sub-agents/sidechains)
25
+ if (path.includes('/agent-') || path.includes('\\agent-')) {
26
+ return false;
27
+ }
28
+ // Match UUID session files only
29
+ // UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.jsonl
30
+ return /\.claude\/projects\/[^/]+\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl$/.test(path);
31
+ }
32
+ /**
33
+ * Find all agent-*.jsonl files in the same directory as the session file
34
+ * that belong to the same Claude sessionId (filters by sessionId)
35
+ *
36
+ * Agent files contain sub-agent/tool execution data with potentially different models
37
+ *
38
+ * @param sessionFilePath - Path to the main session file
39
+ * @returns Array of agent file paths matching the same sessionId
40
+ */
41
+ async findAgentFiles(sessionFilePath) {
42
+ try {
43
+ const dir = dirname(sessionFilePath);
44
+ if (!existsSync(dir)) {
45
+ return [];
46
+ }
47
+ // Read the sessionId from the file (may not be on first line)
48
+ // First line is often file-history-snapshot without sessionId
49
+ const mainContent = await readFile(sessionFilePath, 'utf-8');
50
+ const lines = mainContent.split('\n').filter(l => l.trim());
51
+ let targetSessionId;
52
+ for (const line of lines.slice(0, 10)) { // Check first 10 lines
53
+ try {
54
+ const event = JSON.parse(line);
55
+ if (event.sessionId) {
56
+ targetSessionId = event.sessionId;
57
+ break;
58
+ }
59
+ }
60
+ catch {
61
+ continue;
62
+ }
63
+ }
64
+ if (!targetSessionId) {
65
+ logger.debug(`[ClaudeMetrics] No sessionId found in ${sessionFilePath}`);
66
+ return [];
67
+ }
68
+ // Find all agent files in the directory
69
+ const files = await readdir(dir);
70
+ const agentFileCandidates = files
71
+ .filter(f => f.startsWith('agent-') && f.endsWith('.jsonl'))
72
+ .map(f => join(dir, f));
73
+ // Filter agent files by matching sessionId
74
+ const matchingAgentFiles = [];
75
+ for (const agentFile of agentFileCandidates) {
76
+ try {
77
+ const content = await readFile(agentFile, 'utf-8');
78
+ const firstLine = content.split('\n')[0];
79
+ if (firstLine) {
80
+ const firstEvent = JSON.parse(firstLine);
81
+ if (firstEvent.sessionId === targetSessionId) {
82
+ matchingAgentFiles.push(agentFile);
83
+ }
84
+ }
85
+ }
86
+ catch {
87
+ // Skip files that can't be parsed
88
+ continue;
89
+ }
90
+ }
91
+ logger.debug(`[ClaudeMetrics] Found ${matchingAgentFiles.length} agent files for session ${targetSessionId}`);
92
+ return matchingAgentFiles;
93
+ }
94
+ catch (error) {
95
+ logger.debug(`[ClaudeMetrics] Failed to find agent files:`, error);
96
+ return [];
97
+ }
98
+ }
99
+ /**
100
+ * Parse all models from agent files
101
+ * Agent files may contain different models used by sub-agents/tools
102
+ *
103
+ * @param agentFilePaths - Array of agent file paths
104
+ * @returns Map of model names to call counts
105
+ */
106
+ async parseModelsFromAgentFiles(agentFilePaths) {
107
+ const modelCalls = new Map();
108
+ for (const filePath of agentFilePaths) {
109
+ try {
110
+ const content = await readFile(filePath, 'utf-8');
111
+ const jsonObjects = parseMultiLineJSON(content);
112
+ for (const obj of jsonObjects) {
113
+ if (obj.message?.model) {
114
+ const model = obj.message.model;
115
+ modelCalls.set(model, (modelCalls.get(model) || 0) + 1);
116
+ }
117
+ }
118
+ }
119
+ catch (error) {
120
+ logger.debug(`[ClaudeMetrics] Failed to parse agent file ${filePath}:`, error);
121
+ }
122
+ }
123
+ return modelCalls;
124
+ }
125
+ /**
126
+ * Extract session ID from Claude file path
127
+ * Examples:
128
+ * ~/.claude/projects/abc123/session-def-456.jsonl → session-def-456
129
+ * ~/.claude/projects/abc123/agent-abc123de.jsonl → agent-abc123de
130
+ */
131
+ extractSessionId(path) {
132
+ const match = path.match(/([a-z0-9-]+)\.jsonl$/);
133
+ return match?.[1] || '';
134
+ }
135
+ /**
136
+ * Parse Claude session file (multi-line JSON objects) and extract metrics
137
+ * Each object contains a conversation turn with message data
138
+ */
139
+ async parseSessionFile(path) {
140
+ try {
141
+ const content = await readFile(path, 'utf-8');
142
+ const jsonObjects = parseMultiLineJSON(content);
143
+ if (jsonObjects.length === 0) {
144
+ throw new Error('Empty session file');
145
+ }
146
+ // Parse first object to get session metadata
147
+ const firstObject = jsonObjects[0];
148
+ const sessionId = firstObject.sessionId || '';
149
+ const workingDirectory = firstObject.cwd || '';
150
+ const gitBranch = firstObject.gitBranch;
151
+ // Aggregate metrics from all objects
152
+ let inputTokens = 0;
153
+ let outputTokens = 0;
154
+ let cacheCreationTokens = 0;
155
+ let cacheReadTokens = 0;
156
+ // Track all models (not just first)
157
+ const modelCalls = new Map();
158
+ // Tool tracking maps
159
+ const toolCalls = [];
160
+ const toolUseMap = new Map();
161
+ for (const turn of jsonObjects) {
162
+ // Track all models with call counts
163
+ if (turn.message?.model) {
164
+ const model = turn.message.model;
165
+ modelCalls.set(model, (modelCalls.get(model) || 0) + 1);
166
+ }
167
+ // Aggregate token usage
168
+ if (turn.message?.usage) {
169
+ const usage = turn.message.usage;
170
+ inputTokens += usage.input_tokens || 0;
171
+ outputTokens += usage.output_tokens || 0;
172
+ cacheCreationTokens += usage.cache_creation_input_tokens || 0;
173
+ cacheReadTokens += usage.cache_read_input_tokens || 0;
174
+ }
175
+ // Extract tool use events (from assistant messages)
176
+ if (turn.message?.role === 'assistant' && Array.isArray(turn.message.content)) {
177
+ for (const block of turn.message.content) {
178
+ if (block.type === 'tool_use') {
179
+ // Store tool_use for later correlation
180
+ toolUseMap.set(block.id, {
181
+ name: block.name,
182
+ timestamp: turn.timestamp || Date.now(),
183
+ input: block.input
184
+ });
185
+ }
186
+ }
187
+ }
188
+ // Extract tool result events (from user messages)
189
+ if (turn.message?.role === 'user' && Array.isArray(turn.message.content)) {
190
+ for (const block of turn.message.content) {
191
+ if (block.type === 'tool_result') {
192
+ const toolUse = toolUseMap.get(block.tool_use_id);
193
+ if (toolUse) {
194
+ const toolCall = {
195
+ id: block.tool_use_id,
196
+ name: toolUse.name, // Use raw tool name
197
+ timestamp: toolUse.timestamp,
198
+ status: block.is_error ? 'error' : 'success',
199
+ input: toolUse.input,
200
+ error: block.is_error ? (typeof block.content === 'string' ? block.content : JSON.stringify(block.content)) : undefined
201
+ };
202
+ // Extract file operation details
203
+ const fileOp = this.extractFileOperation(toolUse.name, toolUse.input);
204
+ if (fileOp) {
205
+ toolCall.fileOperation = fileOp;
206
+ }
207
+ toolCalls.push(toolCall);
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ // Parse agent files to get models from sub-agents/tools
214
+ const agentFiles = await this.findAgentFiles(path);
215
+ const agentModels = await this.parseModelsFromAgentFiles(agentFiles);
216
+ // Merge agent models with session models
217
+ for (const [model, count] of agentModels) {
218
+ modelCalls.set(model, (modelCalls.get(model) || 0) + count);
219
+ }
220
+ // Build aggregated tool usage summary
221
+ const toolUsageSummary = this.buildToolUsageSummary(toolCalls);
222
+ // Get all models (raw, unnormalized)
223
+ const allModels = Array.from(modelCalls.keys());
224
+ const snapshot = {
225
+ sessionId,
226
+ timestamp: Date.now(),
227
+ tokens: {
228
+ input: inputTokens,
229
+ output: outputTokens,
230
+ cacheCreation: cacheCreationTokens > 0 ? cacheCreationTokens : undefined,
231
+ cacheRead: cacheReadTokens > 0 ? cacheReadTokens : undefined
232
+ },
233
+ toolCalls,
234
+ toolUsageSummary,
235
+ turnCount: jsonObjects.length,
236
+ model: allModels.length > 0 ? allModels[0] : undefined, // Primary model for backward compat
237
+ metadata: {
238
+ workingDirectory,
239
+ gitBranch,
240
+ totalInputTokens: inputTokens + cacheCreationTokens + cacheReadTokens,
241
+ models: allModels, // All raw model names (unnormalized)
242
+ modelCalls: Object.fromEntries(modelCalls) // Map of model -> call count
243
+ }
244
+ };
245
+ logger.debug(`[ClaudeMetrics] Parsed session ${sessionId}: ${inputTokens} input, ${outputTokens} output, ` +
246
+ `${cacheReadTokens} cache read, ${toolCalls.length} tool calls, ${allModels.length} models`);
247
+ return snapshot;
248
+ }
249
+ catch (error) {
250
+ logger.error(`[ClaudeMetrics] Failed to parse session file: ${path}`, error);
251
+ throw error;
252
+ }
253
+ }
254
+ /**
255
+ * Extract file operation details from tool input and result
256
+ * Uses raw tool names (provider-specific, e.g., "Write", "Edit", "Read")
257
+ *
258
+ * @param toolName - Tool name (Read, Write, Edit, etc.)
259
+ * @param input - Tool input parameters
260
+ * @param toolUseResult - Tool execution result with structured data (optional)
261
+ */
262
+ extractFileOperation(toolName, input, toolUseResult) {
263
+ // Map raw tool names to operation types
264
+ const typeMap = {
265
+ 'Read': 'read',
266
+ 'Write': 'write',
267
+ 'Edit': 'edit',
268
+ // Note: Bash excluded - too varied to categorize reliably
269
+ 'Grep': 'grep',
270
+ 'Glob': 'glob'
271
+ };
272
+ const type = typeMap[toolName];
273
+ if (!type)
274
+ return undefined;
275
+ const fileOp = { type };
276
+ // Extract file path from toolUseResult (most accurate) or input
277
+ const filePath = toolUseResult?.filePath || toolUseResult?.file?.filePath || input?.file_path || input?.path;
278
+ if (filePath) {
279
+ fileOp.path = filePath;
280
+ fileOp.format = this.extractFormat(filePath);
281
+ fileOp.language = this.detectLanguage(filePath);
282
+ }
283
+ else if (input?.pattern) {
284
+ // For Grep/Glob operations
285
+ fileOp.pattern = input.pattern;
286
+ }
287
+ // Extract line changes from toolUseResult (most accurate source)
288
+ if (toolName === 'Write') {
289
+ // Write tool: calculate from toolUseResult.content or toolUseResult.file or input.content
290
+ const content = toolUseResult?.content || toolUseResult?.file?.content || input?.content;
291
+ if (content) {
292
+ const lines = content.split('\n');
293
+ fileOp.linesAdded = lines.length;
294
+ }
295
+ else if (toolUseResult?.file?.numLines) {
296
+ fileOp.linesAdded = toolUseResult.file.numLines;
297
+ }
298
+ else if (toolUseResult?.file?.totalLines) {
299
+ fileOp.linesAdded = toolUseResult.file.totalLines;
300
+ }
301
+ }
302
+ else if (toolName === 'Edit' && toolUseResult?.structuredPatch) {
303
+ // Edit tool: use structured patch to get accurate line counts
304
+ let added = 0;
305
+ let removed = 0;
306
+ for (const patch of toolUseResult.structuredPatch) {
307
+ // Parse patch.lines array: "+line" = added, "-line" = removed, " line" = unchanged
308
+ for (const line of patch.lines || []) {
309
+ if (line.startsWith('+')) {
310
+ added++;
311
+ }
312
+ else if (line.startsWith('-')) {
313
+ removed++;
314
+ }
315
+ // Lines starting with space are unchanged (context)
316
+ }
317
+ }
318
+ if (added > 0)
319
+ fileOp.linesAdded = added;
320
+ if (removed > 0)
321
+ fileOp.linesRemoved = removed;
322
+ // If no adds/removes but edit happened, count as modified
323
+ if (added === 0 && removed === 0 && toolUseResult.structuredPatch.length > 0) {
324
+ fileOp.linesModified = toolUseResult.structuredPatch[0].oldLines || 0;
325
+ }
326
+ }
327
+ else if (toolName === 'Read' && toolUseResult?.file) {
328
+ // Read tool: no line changes, but we have file info
329
+ // numLines already captured above
330
+ }
331
+ return fileOp;
332
+ }
333
+ /**
334
+ * Extract file format from path
335
+ */
336
+ extractFormat(path) {
337
+ const ext = extname(path);
338
+ return ext ? ext.slice(1) : undefined;
339
+ }
340
+ /**
341
+ * Detect programming language from file extension
342
+ */
343
+ detectLanguage(path) {
344
+ const ext = extname(path).toLowerCase();
345
+ const langMap = {
346
+ '.ts': 'typescript',
347
+ '.tsx': 'typescript',
348
+ '.js': 'javascript',
349
+ '.jsx': 'javascript',
350
+ '.py': 'python',
351
+ '.java': 'java',
352
+ '.go': 'go',
353
+ '.rs': 'rust',
354
+ '.cpp': 'cpp',
355
+ '.c': 'c',
356
+ '.rb': 'ruby',
357
+ '.php': 'php',
358
+ '.swift': 'swift',
359
+ '.kt': 'kotlin',
360
+ '.md': 'markdown',
361
+ '.json': 'json',
362
+ '.yaml': 'yaml',
363
+ '.yml': 'yaml'
364
+ };
365
+ return langMap[ext];
366
+ }
367
+ /**
368
+ * Build aggregated tool usage summary from detailed tool calls
369
+ */
370
+ buildToolUsageSummary(toolCalls) {
371
+ const summaryMap = new Map();
372
+ for (const call of toolCalls) {
373
+ let summary = summaryMap.get(call.name);
374
+ if (!summary) {
375
+ summary = {
376
+ name: call.name,
377
+ count: 0,
378
+ successCount: 0,
379
+ errorCount: 0,
380
+ fileOperations: {}
381
+ };
382
+ summaryMap.set(call.name, summary);
383
+ }
384
+ summary.count++;
385
+ if (call.status === 'success') {
386
+ summary.successCount++;
387
+ }
388
+ else if (call.status === 'error') {
389
+ summary.errorCount++;
390
+ }
391
+ // Aggregate file operations
392
+ if (call.fileOperation) {
393
+ const opType = call.fileOperation.type;
394
+ summary.fileOperations[opType] = (summary.fileOperations[opType] || 0) + 1;
395
+ }
396
+ }
397
+ return Array.from(summaryMap.values());
398
+ }
399
+ /**
400
+ * Claude uses hash-based watermark (full file rewrite)
401
+ */
402
+ getWatermarkStrategy() {
403
+ return 'hash';
404
+ }
405
+ /**
406
+ * Claude initialization delay: 500ms
407
+ */
408
+ getInitDelay() {
409
+ return 500;
410
+ }
411
+ /**
412
+ * Get user prompts for a specific session
413
+ * Claude stores user prompts in history file (path from metadata)
414
+ *
415
+ * @param sessionId - Claude session ID
416
+ * @param fromTimestamp - Start timestamp (Unix ms) - optional
417
+ * @param toTimestamp - End timestamp (Unix ms) - optional
418
+ * @returns Array of user prompts
419
+ */
420
+ async getUserPrompts(sessionId, fromTimestamp, toTimestamp) {
421
+ try {
422
+ // Get history file path from metadata
423
+ if (!this.metadata?.dataPaths?.home || !this.metadata?.dataPaths?.history) {
424
+ logger.debug(`[ClaudeMetrics] No history path configured in metadata`);
425
+ return [];
426
+ }
427
+ const home = this.metadata.dataPaths.home.replace('~', homedir());
428
+ const historyPath = join(home, this.metadata.dataPaths.history);
429
+ const parser = new HistoryParser(historyPath);
430
+ // Get prompts for this session within time range
431
+ const prompts = await parser.getPromptsInRange(sessionId, fromTimestamp, toTimestamp);
432
+ logger.debug(`[ClaudeMetrics] Found ${prompts.length} user prompts for session ${sessionId}`);
433
+ return prompts;
434
+ }
435
+ catch (error) {
436
+ logger.error(`[ClaudeMetrics] Failed to get user prompts for session ${sessionId}:`, error);
437
+ return [];
438
+ }
439
+ }
440
+ /**
441
+ * Parse session file and extract incremental delta records
442
+ * Returns array of delta records for turns with token usage
443
+ *
444
+ * Automatically discovers and parses ALL agent files for the session
445
+ * to capture sub-agents/sidechains that share the same Claude sessionId
446
+ *
447
+ * @param path - Path to agent session file
448
+ * @param processedRecordIds - Set of record IDs already written to metrics
449
+ * @param attachedUserPromptTexts - Set of user prompt texts already attached (persisted from sync state)
450
+ */
451
+ async parseIncrementalMetrics(path, processedRecordIds = new Set(), attachedUserPromptTexts = new Set()) {
452
+ try {
453
+ // Find ALL agent files for this session (including sidechains)
454
+ const agentFiles = await this.findAgentFiles(path);
455
+ // Add the main file to the list if not already included
456
+ if (!agentFiles.includes(path)) {
457
+ agentFiles.unshift(path);
458
+ }
459
+ // Track initial size to determine newly attached prompts
460
+ const initialAttachedCount = attachedUserPromptTexts.size;
461
+ // Parse all agent files and merge deltas
462
+ const allDeltas = [];
463
+ let maxLastLine = 0;
464
+ for (const agentFile of agentFiles) {
465
+ const { deltas, lastLine } = await this.parseAgentFileDeltas(agentFile, processedRecordIds, attachedUserPromptTexts);
466
+ allDeltas.push(...deltas);
467
+ maxLastLine = Math.max(maxLastLine, lastLine);
468
+ }
469
+ // Calculate newly attached prompts (after processing - before processing)
470
+ const newlyAttachedPrompts = Array.from(attachedUserPromptTexts).slice(initialAttachedCount);
471
+ return {
472
+ deltas: allDeltas,
473
+ lastLine: maxLastLine,
474
+ newlyAttachedPrompts
475
+ };
476
+ }
477
+ catch (error) {
478
+ logger.error(`[ClaudeMetrics] Failed to parse incremental metrics: ${path}`, error);
479
+ throw error;
480
+ }
481
+ }
482
+ /**
483
+ * Parse a single agent file for deltas
484
+ * Extracted from parseIncrementalMetrics for reuse across multiple files
485
+ *
486
+ * @param path - Path to agent file
487
+ * @param processedRecordIds - Set of record IDs already processed
488
+ * @param attachedUserPrompts - Set of user prompt display texts that have been attached (shared across files)
489
+ */
490
+ async parseAgentFileDeltas(path, processedRecordIds, attachedUserPrompts = new Set()) {
491
+ try {
492
+ const content = await readFile(path, 'utf-8');
493
+ const jsonObjects = parseMultiLineJSON(content);
494
+ if (jsonObjects.length === 0) {
495
+ return { deltas: [], lastLine: 0 };
496
+ }
497
+ // FIRST PASS: Build tool_result map from ALL jsonObjects
498
+ // This ensures we can match tool_results that come after tool_use in the file
499
+ const toolResultMap = new Map();
500
+ for (const record of jsonObjects) {
501
+ if (record.message?.role === 'user' && Array.isArray(record.message.content)) {
502
+ for (const block of record.message.content) {
503
+ if (block.type === 'tool_result') {
504
+ toolResultMap.set(block.tool_use_id, {
505
+ timestamp: record.timestamp,
506
+ isError: block.is_error || false,
507
+ errorMessage: block.is_error ? (typeof block.content === 'string' ? block.content : JSON.stringify(block.content)) : undefined,
508
+ durationMs: block.durationMs,
509
+ toolUseResult: record.toolUseResult // Contains structured patch and file details
510
+ });
511
+ }
512
+ }
513
+ }
514
+ }
515
+ // Extract session ID from first record that has one
516
+ let extractedSessionId = '';
517
+ for (const record of jsonObjects) {
518
+ if (record.sessionId) {
519
+ extractedSessionId = record.sessionId;
520
+ break;
521
+ }
522
+ }
523
+ // ZERO PASS: Get user prompts from history.jsonl and build UUID map
524
+ // Map user prompt UUIDs to prompts for direct correlation
525
+ const userPromptsByUuid = new Map();
526
+ try {
527
+ const userPrompts = await this.getUserPrompts(extractedSessionId);
528
+ logger.debug(`[ClaudeMetrics] Found ${userPrompts.length} user prompts in history.jsonl for session ${extractedSessionId}`);
529
+ // Build a map of record UUIDs to user prompts
530
+ // We'll correlate by finding user messages that match prompts
531
+ for (const record of jsonObjects) {
532
+ if (record.type === 'user' &&
533
+ record.message?.role === 'user' &&
534
+ typeof record.message.content === 'string') {
535
+ // This is an initial user message (not a tool result)
536
+ const messageContent = record.message.content;
537
+ const recordTime = typeof record.timestamp === 'string'
538
+ ? new Date(record.timestamp).getTime()
539
+ : record.timestamp;
540
+ // Find matching prompt from history.jsonl by content or timestamp
541
+ const matchingPrompt = userPrompts.find(p => {
542
+ // Match by content (most reliable)
543
+ if (p.display === messageContent) {
544
+ return true;
545
+ }
546
+ // Fallback: match by timestamp (±10 seconds window for initial prompts)
547
+ const timeDiff = Math.abs(p.timestamp - recordTime);
548
+ return timeDiff <= 10000; // 10 second window
549
+ });
550
+ if (matchingPrompt && record.uuid) {
551
+ userPromptsByUuid.set(record.uuid, matchingPrompt);
552
+ }
553
+ }
554
+ }
555
+ logger.debug(`[ClaudeMetrics] Matched ${userPromptsByUuid.size} prompts to message UUIDs`);
556
+ }
557
+ catch (error) {
558
+ logger.debug(`[ClaudeMetrics] Could not load user prompts (non-critical):`, error);
559
+ // Continue without user prompts - non-critical feature
560
+ }
561
+ // SECOND PASS: Create deltas for NEW records with usage (assistant messages)
562
+ // Skip records that have already been processed
563
+ const deltas = [];
564
+ const sessionModels = []; // Track all unique models
565
+ let lastUserPrompt;
566
+ for (const record of jsonObjects) {
567
+ // Track user prompts as we iterate (BEFORE processing/skipping)
568
+ // Only update lastUserPrompt for INITIAL user messages (with string content), not tool_result messages
569
+ if (record.type === 'user' &&
570
+ record.uuid &&
571
+ userPromptsByUuid.has(record.uuid) &&
572
+ record.message?.role === 'user' &&
573
+ typeof record.message.content === 'string') {
574
+ lastUserPrompt = userPromptsByUuid.get(record.uuid);
575
+ }
576
+ // Skip records already processed
577
+ if (processedRecordIds.has(record.uuid)) {
578
+ continue;
579
+ }
580
+ // Collect all unique models from all records (not just first)
581
+ if (record.message?.model && !sessionModels.includes(record.message.model)) {
582
+ sessionModels.push(record.message.model);
583
+ }
584
+ // Create delta for records with token usage
585
+ if (record.message?.usage && record.message?.role === 'assistant') {
586
+ // Check if this record has tool_use blocks waiting for tool_results
587
+ let hasUnresolvedTools = false;
588
+ if (Array.isArray(record.message.content)) {
589
+ for (const block of record.message.content) {
590
+ if (block.type === 'tool_use') {
591
+ if (!toolResultMap.has(block.id)) {
592
+ hasUnresolvedTools = true;
593
+ break;
594
+ }
595
+ }
596
+ }
597
+ }
598
+ // Skip records with tool_use blocks that haven't received tool_results yet
599
+ if (hasUnresolvedTools) {
600
+ logger.debug(`[ClaudeMetrics] Skipping record ${record.uuid} - waiting for tool results`);
601
+ continue;
602
+ }
603
+ const usage = record.message.usage;
604
+ const inputTokens = usage.input_tokens || 0;
605
+ const outputTokens = usage.output_tokens || 0;
606
+ const cacheCreationTokens = usage.cache_creation_input_tokens || 0;
607
+ const cacheReadTokens = usage.cache_read_input_tokens || 0;
608
+ // Extract tool_use IDs from this record
609
+ const tools = {};
610
+ const toolStatus = {};
611
+ const fileOperations = [];
612
+ let apiErrorMessage;
613
+ if (Array.isArray(record.message.content)) {
614
+ for (const block of record.message.content) {
615
+ if (block.type === 'tool_use') {
616
+ // block IS the tool_use with name and input
617
+ const toolResult = toolResultMap.get(block.id);
618
+ // Only count if we have tool_result (tool was executed)
619
+ if (toolResult) {
620
+ // Use raw tool name (provider-specific)
621
+ const toolName = block.name;
622
+ tools[toolName] = (tools[toolName] || 0) + 1;
623
+ // Track success/failure
624
+ if (!toolStatus[toolName]) {
625
+ toolStatus[toolName] = { success: 0, failure: 0 };
626
+ }
627
+ if (toolResult.isError) {
628
+ toolStatus[toolName].failure++;
629
+ // Capture first error message
630
+ if (!apiErrorMessage && toolResult.errorMessage) {
631
+ apiErrorMessage = toolResult.errorMessage;
632
+ }
633
+ }
634
+ else {
635
+ toolStatus[toolName].success++;
636
+ // Only extract file operations for successful tool calls
637
+ const fileOp = this.extractFileOperation(toolName, block.input, toolResult.toolUseResult);
638
+ if (fileOp) {
639
+ // Add durationMs if available
640
+ if (toolResult.durationMs) {
641
+ fileOp.durationMs = toolResult.durationMs;
642
+ }
643
+ fileOperations.push(fileOp);
644
+ }
645
+ }
646
+ }
647
+ }
648
+ }
649
+ }
650
+ // Include user prompt ONLY for the first assistant response after a user prompt
651
+ // Use shared Set to prevent duplication across ALL agent files
652
+ const userPrompts = [];
653
+ if (lastUserPrompt && lastUserPrompt.display && !attachedUserPrompts.has(lastUserPrompt.display)) {
654
+ userPrompts.push({
655
+ count: 1,
656
+ text: lastUserPrompt.display
657
+ });
658
+ // Mark as attached to prevent duplicate counting across multiple assistant turns AND agent files
659
+ attachedUserPrompts.add(lastUserPrompt.display);
660
+ // Clear lastUserPrompt so it doesn't attach to subsequent assistant turns
661
+ lastUserPrompt = undefined;
662
+ }
663
+ // Get model and gitBranch for this turn
664
+ const turnModel = record.message?.model;
665
+ const gitBranch = record.gitBranch;
666
+ // Create delta record (use message UUID as recordId for backtracking)
667
+ const delta = {
668
+ recordId: record.uuid, // Use message UUID for backtracking
669
+ sessionId: '', // Will be set by caller
670
+ agentSessionId: record.sessionId || '',
671
+ timestamp: record.timestamp || new Date().toISOString(),
672
+ gitBranch, // Git branch at time of this turn
673
+ tokens: {
674
+ input: inputTokens,
675
+ output: outputTokens,
676
+ cacheCreation: cacheCreationTokens > 0 ? cacheCreationTokens : undefined,
677
+ cacheRead: cacheReadTokens > 0 ? cacheReadTokens : undefined
678
+ },
679
+ tools,
680
+ toolStatus: Object.keys(toolStatus).length > 0 ? toolStatus : undefined,
681
+ fileOperations: fileOperations.length > 0 ? fileOperations : undefined,
682
+ userPrompts: userPrompts.length > 0 ? userPrompts : undefined,
683
+ apiErrorMessage,
684
+ models: turnModel ? [turnModel] : undefined // Store raw model name(s) for this turn
685
+ };
686
+ deltas.push(delta);
687
+ }
688
+ }
689
+ return {
690
+ deltas,
691
+ lastLine: jsonObjects.length
692
+ };
693
+ }
694
+ catch (error) {
695
+ logger.error(`[ClaudeMetrics] Failed to parse incremental metrics: ${path}`, error);
696
+ throw error;
697
+ }
698
+ }
699
+ }
700
+ //# sourceMappingURL=claude.metrics.js.map