@newrelic/preflight 0.0.1-pre.1 → 1.0.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 (578) hide show
  1. package/LICENSE +183 -0
  2. package/README.md +498 -0
  3. package/dist/alerts/alert-log.d.ts +24 -0
  4. package/dist/alerts/alert-log.d.ts.map +1 -0
  5. package/dist/alerts/alert-log.js +159 -0
  6. package/dist/alerts/alert-log.js.map +1 -0
  7. package/dist/alerts/alert-snapshot-collector.d.ts +168 -0
  8. package/dist/alerts/alert-snapshot-collector.d.ts.map +1 -0
  9. package/dist/alerts/alert-snapshot-collector.js +243 -0
  10. package/dist/alerts/alert-snapshot-collector.js.map +1 -0
  11. package/dist/alerts/local-alert-engine.d.ts +86 -0
  12. package/dist/alerts/local-alert-engine.d.ts.map +1 -0
  13. package/dist/alerts/local-alert-engine.js +466 -0
  14. package/dist/alerts/local-alert-engine.js.map +1 -0
  15. package/dist/alerts/local-alert-rule.d.ts +439 -0
  16. package/dist/alerts/local-alert-rule.d.ts.map +1 -0
  17. package/dist/alerts/local-alert-rule.js +139 -0
  18. package/dist/alerts/local-alert-rule.js.map +1 -0
  19. package/dist/alerts/os-notifier.d.ts +39 -0
  20. package/dist/alerts/os-notifier.d.ts.map +1 -0
  21. package/dist/alerts/os-notifier.js +170 -0
  22. package/dist/alerts/os-notifier.js.map +1 -0
  23. package/dist/alerts/types.d.ts +35 -0
  24. package/dist/alerts/types.d.ts.map +1 -0
  25. package/dist/alerts/types.js +8 -0
  26. package/dist/alerts/types.js.map +1 -0
  27. package/dist/config.d.ts +169 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +860 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/dashboard/dashboard-server.d.ts +38 -0
  32. package/dist/dashboard/dashboard-server.d.ts.map +1 -0
  33. package/dist/dashboard/dashboard-server.js +207 -0
  34. package/dist/dashboard/dashboard-server.js.map +1 -0
  35. package/dist/dashboard/index.d.ts +3 -0
  36. package/dist/dashboard/index.d.ts.map +1 -0
  37. package/dist/dashboard/index.js +2 -0
  38. package/dist/dashboard/index.js.map +1 -0
  39. package/dist/dashboard/live-event-bus.d.ts +99 -0
  40. package/dist/dashboard/live-event-bus.d.ts.map +1 -0
  41. package/dist/dashboard/live-event-bus.js +56 -0
  42. package/dist/dashboard/live-event-bus.js.map +1 -0
  43. package/dist/dashboard/routes/api-handler.d.ts +122 -0
  44. package/dist/dashboard/routes/api-handler.d.ts.map +1 -0
  45. package/dist/dashboard/routes/api-handler.js +1414 -0
  46. package/dist/dashboard/routes/api-handler.js.map +1 -0
  47. package/dist/dashboard/routes/replay-analyzer.d.ts +15 -0
  48. package/dist/dashboard/routes/replay-analyzer.d.ts.map +1 -0
  49. package/dist/dashboard/routes/replay-analyzer.js +227 -0
  50. package/dist/dashboard/routes/replay-analyzer.js.map +1 -0
  51. package/dist/dashboard/routes/sse-handler.d.ts +4 -0
  52. package/dist/dashboard/routes/sse-handler.d.ts.map +1 -0
  53. package/dist/dashboard/routes/sse-handler.js +122 -0
  54. package/dist/dashboard/routes/sse-handler.js.map +1 -0
  55. package/dist/dashboard/routes/static-handler.d.ts +3 -0
  56. package/dist/dashboard/routes/static-handler.d.ts.map +1 -0
  57. package/dist/dashboard/routes/static-handler.js +103 -0
  58. package/dist/dashboard/routes/static-handler.js.map +1 -0
  59. package/dist/data/alerts/conditions/01-daily-cost-spike.json +16 -0
  60. package/dist/data/alerts/conditions/02-low-efficiency-score.json +16 -0
  61. package/dist/data/alerts/conditions/03-stuck-loop-rate.json +16 -0
  62. package/dist/data/alerts/conditions/04-anti-pattern-rate.json +16 -0
  63. package/dist/data/alerts/conditions/05-session-cost-budget.json +16 -0
  64. package/dist/data/alerts/conditions-personal/01-personal-daily-cost.json +16 -0
  65. package/dist/data/alerts/conditions-personal/02-personal-session-cost.json +16 -0
  66. package/dist/data/alerts/conditions-personal/03-personal-low-efficiency.json +16 -0
  67. package/dist/data/alerts/conditions-personal/04-personal-anti-pattern-rate.json +16 -0
  68. package/dist/data/alerts/conditions-personal/05-personal-stuck-loop.json +16 -0
  69. package/dist/data/alerts/policy.json +4 -0
  70. package/dist/data/dashboards/ai-coding-assistant-manager-view.json +103 -0
  71. package/dist/data/dashboards/ai-coding-assistant-overview.json +239 -0
  72. package/dist/data/dashboards/ai-coding-assistant-personal.json +442 -0
  73. package/dist/data/dashboards/ai-coding-assistant-platform-comparison.json +320 -0
  74. package/dist/data/dashboards/ai-coding-assistant-security.json +275 -0
  75. package/dist/data/dashboards/ai-coding-assistant-session-detail.json +296 -0
  76. package/dist/data/dashboards/ai-coding-assistant-team-view.json +345 -0
  77. package/dist/deploy/data-paths.d.ts +22 -0
  78. package/dist/deploy/data-paths.d.ts.map +1 -0
  79. package/dist/deploy/data-paths.js +69 -0
  80. package/dist/deploy/data-paths.js.map +1 -0
  81. package/dist/deploy/deploy-alerts.d.ts +58 -0
  82. package/dist/deploy/deploy-alerts.d.ts.map +1 -0
  83. package/dist/deploy/deploy-alerts.js +371 -0
  84. package/dist/deploy/deploy-alerts.js.map +1 -0
  85. package/dist/deploy/deploy-dashboards.d.ts +92 -0
  86. package/dist/deploy/deploy-dashboards.d.ts.map +1 -0
  87. package/dist/deploy/deploy-dashboards.js +282 -0
  88. package/dist/deploy/deploy-dashboards.js.map +1 -0
  89. package/dist/digest/digest-formatter.d.ts +3 -0
  90. package/dist/digest/digest-formatter.d.ts.map +1 -0
  91. package/dist/digest/digest-formatter.js +37 -0
  92. package/dist/digest/digest-formatter.js.map +1 -0
  93. package/dist/digest/digest-sender.d.ts +2 -0
  94. package/dist/digest/digest-sender.d.ts.map +1 -0
  95. package/dist/digest/digest-sender.js +29 -0
  96. package/dist/digest/digest-sender.js.map +1 -0
  97. package/dist/hooks/bash-classifier.d.ts +26 -0
  98. package/dist/hooks/bash-classifier.d.ts.map +1 -0
  99. package/dist/hooks/bash-classifier.js +409 -0
  100. package/dist/hooks/bash-classifier.js.map +1 -0
  101. package/dist/hooks/collector-script.d.ts +47 -0
  102. package/dist/hooks/collector-script.d.ts.map +1 -0
  103. package/dist/hooks/collector-script.js +662 -0
  104. package/dist/hooks/collector-script.js.map +1 -0
  105. package/dist/hooks/event-processor.d.ts +65 -0
  106. package/dist/hooks/event-processor.d.ts.map +1 -0
  107. package/dist/hooks/event-processor.js +342 -0
  108. package/dist/hooks/event-processor.js.map +1 -0
  109. package/dist/hooks/index.d.ts +7 -0
  110. package/dist/hooks/index.d.ts.map +1 -0
  111. package/dist/hooks/index.js +5 -0
  112. package/dist/hooks/index.js.map +1 -0
  113. package/dist/hooks/session-resolver.d.ts +66 -0
  114. package/dist/hooks/session-resolver.d.ts.map +1 -0
  115. package/dist/hooks/session-resolver.js +196 -0
  116. package/dist/hooks/session-resolver.js.map +1 -0
  117. package/dist/hooks/tool-parsers.d.ts +19 -0
  118. package/dist/hooks/tool-parsers.d.ts.map +1 -0
  119. package/dist/hooks/tool-parsers.js +260 -0
  120. package/dist/hooks/tool-parsers.js.map +1 -0
  121. package/dist/index.d.ts +107 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +1505 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/install/cli.d.ts +11 -0
  126. package/dist/install/cli.d.ts.map +1 -0
  127. package/dist/install/cli.js +365 -0
  128. package/dist/install/cli.js.map +1 -0
  129. package/dist/install/index.d.ts +4 -0
  130. package/dist/install/index.d.ts.map +1 -0
  131. package/dist/install/index.js +3 -0
  132. package/dist/install/index.js.map +1 -0
  133. package/dist/install/install-helper.d.ts +35 -0
  134. package/dist/install/install-helper.d.ts.map +1 -0
  135. package/dist/install/install-helper.js +227 -0
  136. package/dist/install/install-helper.js.map +1 -0
  137. package/dist/install/key-validator.d.ts +19 -0
  138. package/dist/install/key-validator.d.ts.map +1 -0
  139. package/dist/install/key-validator.js +122 -0
  140. package/dist/install/key-validator.js.map +1 -0
  141. package/dist/install/migrate.d.ts +12 -0
  142. package/dist/install/migrate.d.ts.map +1 -0
  143. package/dist/install/migrate.js +115 -0
  144. package/dist/install/migrate.js.map +1 -0
  145. package/dist/install/schedule.d.ts +11 -0
  146. package/dist/install/schedule.d.ts.map +1 -0
  147. package/dist/install/schedule.js +114 -0
  148. package/dist/install/schedule.js.map +1 -0
  149. package/dist/install/setup-wizard.d.ts +40 -0
  150. package/dist/install/setup-wizard.d.ts.map +1 -0
  151. package/dist/install/setup-wizard.js +489 -0
  152. package/dist/install/setup-wizard.js.map +1 -0
  153. package/dist/lib/date.d.ts +54 -0
  154. package/dist/lib/date.d.ts.map +1 -0
  155. package/dist/lib/date.js +85 -0
  156. package/dist/lib/date.js.map +1 -0
  157. package/dist/metrics/anti-patterns.d.ts +62 -0
  158. package/dist/metrics/anti-patterns.d.ts.map +1 -0
  159. package/dist/metrics/anti-patterns.js +301 -0
  160. package/dist/metrics/anti-patterns.js.map +1 -0
  161. package/dist/metrics/api-failure-tracker.d.ts +82 -0
  162. package/dist/metrics/api-failure-tracker.d.ts.map +1 -0
  163. package/dist/metrics/api-failure-tracker.js +202 -0
  164. package/dist/metrics/api-failure-tracker.js.map +1 -0
  165. package/dist/metrics/budget-tracker.d.ts +60 -0
  166. package/dist/metrics/budget-tracker.d.ts.map +1 -0
  167. package/dist/metrics/budget-tracker.js +130 -0
  168. package/dist/metrics/budget-tracker.js.map +1 -0
  169. package/dist/metrics/claudemd-tracker.d.ts +108 -0
  170. package/dist/metrics/claudemd-tracker.d.ts.map +1 -0
  171. package/dist/metrics/claudemd-tracker.js +337 -0
  172. package/dist/metrics/claudemd-tracker.js.map +1 -0
  173. package/dist/metrics/collaboration-profile.d.ts +65 -0
  174. package/dist/metrics/collaboration-profile.d.ts.map +1 -0
  175. package/dist/metrics/collaboration-profile.js +231 -0
  176. package/dist/metrics/collaboration-profile.js.map +1 -0
  177. package/dist/metrics/context-composition-tracker.d.ts +74 -0
  178. package/dist/metrics/context-composition-tracker.d.ts.map +1 -0
  179. package/dist/metrics/context-composition-tracker.js +202 -0
  180. package/dist/metrics/context-composition-tracker.js.map +1 -0
  181. package/dist/metrics/context-tracker.d.ts +78 -0
  182. package/dist/metrics/context-tracker.d.ts.map +1 -0
  183. package/dist/metrics/context-tracker.js +222 -0
  184. package/dist/metrics/context-tracker.js.map +1 -0
  185. package/dist/metrics/context-window-tracker.d.ts +18 -0
  186. package/dist/metrics/context-window-tracker.d.ts.map +1 -0
  187. package/dist/metrics/context-window-tracker.js +35 -0
  188. package/dist/metrics/context-window-tracker.js.map +1 -0
  189. package/dist/metrics/cost-forecast.d.ts +36 -0
  190. package/dist/metrics/cost-forecast.d.ts.map +1 -0
  191. package/dist/metrics/cost-forecast.js +91 -0
  192. package/dist/metrics/cost-forecast.js.map +1 -0
  193. package/dist/metrics/cost-per-outcome.d.ts +102 -0
  194. package/dist/metrics/cost-per-outcome.d.ts.map +1 -0
  195. package/dist/metrics/cost-per-outcome.js +266 -0
  196. package/dist/metrics/cost-per-outcome.js.map +1 -0
  197. package/dist/metrics/cost-tracker.d.ts +78 -0
  198. package/dist/metrics/cost-tracker.d.ts.map +1 -0
  199. package/dist/metrics/cost-tracker.js +169 -0
  200. package/dist/metrics/cost-tracker.js.map +1 -0
  201. package/dist/metrics/decision-tracker.d.ts +49 -0
  202. package/dist/metrics/decision-tracker.d.ts.map +1 -0
  203. package/dist/metrics/decision-tracker.js +161 -0
  204. package/dist/metrics/decision-tracker.js.map +1 -0
  205. package/dist/metrics/efficiency-score.d.ts +80 -0
  206. package/dist/metrics/efficiency-score.d.ts.map +1 -0
  207. package/dist/metrics/efficiency-score.js +219 -0
  208. package/dist/metrics/efficiency-score.js.map +1 -0
  209. package/dist/metrics/git-efficiency-tracker.d.ts +165 -0
  210. package/dist/metrics/git-efficiency-tracker.d.ts.map +1 -0
  211. package/dist/metrics/git-efficiency-tracker.js +1056 -0
  212. package/dist/metrics/git-efficiency-tracker.js.map +1 -0
  213. package/dist/metrics/index.d.ts +26 -0
  214. package/dist/metrics/index.d.ts.map +1 -0
  215. package/dist/metrics/index.js +14 -0
  216. package/dist/metrics/index.js.map +1 -0
  217. package/dist/metrics/instruction-drift-tracker.d.ts +69 -0
  218. package/dist/metrics/instruction-drift-tracker.d.ts.map +1 -0
  219. package/dist/metrics/instruction-drift-tracker.js +213 -0
  220. package/dist/metrics/instruction-drift-tracker.js.map +1 -0
  221. package/dist/metrics/latency-decomposition.d.ts +50 -0
  222. package/dist/metrics/latency-decomposition.d.ts.map +1 -0
  223. package/dist/metrics/latency-decomposition.js +112 -0
  224. package/dist/metrics/latency-decomposition.js.map +1 -0
  225. package/dist/metrics/latency-tracker.d.ts +33 -0
  226. package/dist/metrics/latency-tracker.d.ts.map +1 -0
  227. package/dist/metrics/latency-tracker.js +93 -0
  228. package/dist/metrics/latency-tracker.js.map +1 -0
  229. package/dist/metrics/live-session-registry.d.ts +29 -0
  230. package/dist/metrics/live-session-registry.d.ts.map +1 -0
  231. package/dist/metrics/live-session-registry.js +103 -0
  232. package/dist/metrics/live-session-registry.js.map +1 -0
  233. package/dist/metrics/model-usage-tracker.d.ts +21 -0
  234. package/dist/metrics/model-usage-tracker.d.ts.map +1 -0
  235. package/dist/metrics/model-usage-tracker.js +53 -0
  236. package/dist/metrics/model-usage-tracker.js.map +1 -0
  237. package/dist/metrics/percentile.d.ts +5 -0
  238. package/dist/metrics/percentile.d.ts.map +1 -0
  239. package/dist/metrics/percentile.js +10 -0
  240. package/dist/metrics/percentile.js.map +1 -0
  241. package/dist/metrics/personal-coach.d.ts +47 -0
  242. package/dist/metrics/personal-coach.d.ts.map +1 -0
  243. package/dist/metrics/personal-coach.js +241 -0
  244. package/dist/metrics/personal-coach.js.map +1 -0
  245. package/dist/metrics/prompt-feedback.d.ts +75 -0
  246. package/dist/metrics/prompt-feedback.d.ts.map +1 -0
  247. package/dist/metrics/prompt-feedback.js +286 -0
  248. package/dist/metrics/prompt-feedback.js.map +1 -0
  249. package/dist/metrics/proxy-metrics.d.ts +54 -0
  250. package/dist/metrics/proxy-metrics.d.ts.map +1 -0
  251. package/dist/metrics/proxy-metrics.js +228 -0
  252. package/dist/metrics/proxy-metrics.js.map +1 -0
  253. package/dist/metrics/quality-proxy-tracker.d.ts +51 -0
  254. package/dist/metrics/quality-proxy-tracker.d.ts.map +1 -0
  255. package/dist/metrics/quality-proxy-tracker.js +162 -0
  256. package/dist/metrics/quality-proxy-tracker.js.map +1 -0
  257. package/dist/metrics/recommendation-engine.d.ts +72 -0
  258. package/dist/metrics/recommendation-engine.d.ts.map +1 -0
  259. package/dist/metrics/recommendation-engine.js +207 -0
  260. package/dist/metrics/recommendation-engine.js.map +1 -0
  261. package/dist/metrics/retry-detector.d.ts +43 -0
  262. package/dist/metrics/retry-detector.d.ts.map +1 -0
  263. package/dist/metrics/retry-detector.js +179 -0
  264. package/dist/metrics/retry-detector.js.map +1 -0
  265. package/dist/metrics/session-tracker.d.ts +75 -0
  266. package/dist/metrics/session-tracker.d.ts.map +1 -0
  267. package/dist/metrics/session-tracker.js +249 -0
  268. package/dist/metrics/session-tracker.js.map +1 -0
  269. package/dist/metrics/task-completion-tracker.d.ts +15 -0
  270. package/dist/metrics/task-completion-tracker.d.ts.map +1 -0
  271. package/dist/metrics/task-completion-tracker.js +27 -0
  272. package/dist/metrics/task-completion-tracker.js.map +1 -0
  273. package/dist/metrics/task-detector.d.ts +84 -0
  274. package/dist/metrics/task-detector.d.ts.map +1 -0
  275. package/dist/metrics/task-detector.js +302 -0
  276. package/dist/metrics/task-detector.js.map +1 -0
  277. package/dist/metrics/tool-selection-scorer.d.ts +39 -0
  278. package/dist/metrics/tool-selection-scorer.d.ts.map +1 -0
  279. package/dist/metrics/tool-selection-scorer.js +193 -0
  280. package/dist/metrics/tool-selection-scorer.js.map +1 -0
  281. package/dist/metrics/trend-analyzer.d.ts +92 -0
  282. package/dist/metrics/trend-analyzer.d.ts.map +1 -0
  283. package/dist/metrics/trend-analyzer.js +293 -0
  284. package/dist/metrics/trend-analyzer.js.map +1 -0
  285. package/dist/metrics/turn-cost-attributor.d.ts +41 -0
  286. package/dist/metrics/turn-cost-attributor.d.ts.map +1 -0
  287. package/dist/metrics/turn-cost-attributor.js +118 -0
  288. package/dist/metrics/turn-cost-attributor.js.map +1 -0
  289. package/dist/metrics/turn-tracker.d.ts +49 -0
  290. package/dist/metrics/turn-tracker.d.ts.map +1 -0
  291. package/dist/metrics/turn-tracker.js +192 -0
  292. package/dist/metrics/turn-tracker.js.map +1 -0
  293. package/dist/platforms/amazon-q-adapter.d.ts +10 -0
  294. package/dist/platforms/amazon-q-adapter.d.ts.map +1 -0
  295. package/dist/platforms/amazon-q-adapter.js +75 -0
  296. package/dist/platforms/amazon-q-adapter.js.map +1 -0
  297. package/dist/platforms/claude-code-adapter.d.ts +10 -0
  298. package/dist/platforms/claude-code-adapter.d.ts.map +1 -0
  299. package/dist/platforms/claude-code-adapter.js +48 -0
  300. package/dist/platforms/claude-code-adapter.js.map +1 -0
  301. package/dist/platforms/continue-adapter.d.ts +10 -0
  302. package/dist/platforms/continue-adapter.d.ts.map +1 -0
  303. package/dist/platforms/continue-adapter.js +73 -0
  304. package/dist/platforms/continue-adapter.js.map +1 -0
  305. package/dist/platforms/copilot-adapter.d.ts +37 -0
  306. package/dist/platforms/copilot-adapter.d.ts.map +1 -0
  307. package/dist/platforms/copilot-adapter.js +66 -0
  308. package/dist/platforms/copilot-adapter.js.map +1 -0
  309. package/dist/platforms/cursor-adapter.d.ts +10 -0
  310. package/dist/platforms/cursor-adapter.d.ts.map +1 -0
  311. package/dist/platforms/cursor-adapter.js +60 -0
  312. package/dist/platforms/cursor-adapter.js.map +1 -0
  313. package/dist/platforms/generic-mcp-adapter.d.ts +113 -0
  314. package/dist/platforms/generic-mcp-adapter.d.ts.map +1 -0
  315. package/dist/platforms/generic-mcp-adapter.js +139 -0
  316. package/dist/platforms/generic-mcp-adapter.js.map +1 -0
  317. package/dist/platforms/index.d.ts +15 -0
  318. package/dist/platforms/index.d.ts.map +1 -0
  319. package/dist/platforms/index.js +12 -0
  320. package/dist/platforms/index.js.map +1 -0
  321. package/dist/platforms/platform-registry.d.ts +11 -0
  322. package/dist/platforms/platform-registry.d.ts.map +1 -0
  323. package/dist/platforms/platform-registry.js +54 -0
  324. package/dist/platforms/platform-registry.js.map +1 -0
  325. package/dist/platforms/types.d.ts +36 -0
  326. package/dist/platforms/types.d.ts.map +1 -0
  327. package/dist/platforms/types.js +2 -0
  328. package/dist/platforms/types.js.map +1 -0
  329. package/dist/platforms/windsurf-adapter.d.ts +10 -0
  330. package/dist/platforms/windsurf-adapter.d.ts.map +1 -0
  331. package/dist/platforms/windsurf-adapter.js +63 -0
  332. package/dist/platforms/windsurf-adapter.js.map +1 -0
  333. package/dist/platforms/zed-adapter.d.ts +10 -0
  334. package/dist/platforms/zed-adapter.d.ts.map +1 -0
  335. package/dist/platforms/zed-adapter.js +72 -0
  336. package/dist/platforms/zed-adapter.js.map +1 -0
  337. package/dist/proxy/index.d.ts +7 -0
  338. package/dist/proxy/index.d.ts.map +1 -0
  339. package/dist/proxy/index.js +5 -0
  340. package/dist/proxy/index.js.map +1 -0
  341. package/dist/proxy/otlp-receiver.d.ts +28 -0
  342. package/dist/proxy/otlp-receiver.d.ts.map +1 -0
  343. package/dist/proxy/otlp-receiver.js +319 -0
  344. package/dist/proxy/otlp-receiver.js.map +1 -0
  345. package/dist/proxy/proxy-manager.d.ts +47 -0
  346. package/dist/proxy/proxy-manager.d.ts.map +1 -0
  347. package/dist/proxy/proxy-manager.js +338 -0
  348. package/dist/proxy/proxy-manager.js.map +1 -0
  349. package/dist/proxy/types.d.ts +72 -0
  350. package/dist/proxy/types.d.ts.map +1 -0
  351. package/dist/proxy/types.js +33 -0
  352. package/dist/proxy/types.js.map +1 -0
  353. package/dist/proxy/upstream-http.d.ts +26 -0
  354. package/dist/proxy/upstream-http.d.ts.map +1 -0
  355. package/dist/proxy/upstream-http.js +209 -0
  356. package/dist/proxy/upstream-http.js.map +1 -0
  357. package/dist/proxy/upstream-stdio.d.ts +25 -0
  358. package/dist/proxy/upstream-stdio.d.ts.map +1 -0
  359. package/dist/proxy/upstream-stdio.js +256 -0
  360. package/dist/proxy/upstream-stdio.js.map +1 -0
  361. package/dist/security/audit-trail.d.ts +74 -0
  362. package/dist/security/audit-trail.d.ts.map +1 -0
  363. package/dist/security/audit-trail.js +338 -0
  364. package/dist/security/audit-trail.js.map +1 -0
  365. package/dist/security/index.d.ts +5 -0
  366. package/dist/security/index.d.ts.map +1 -0
  367. package/dist/security/index.js +4 -0
  368. package/dist/security/index.js.map +1 -0
  369. package/dist/security/ssrf.d.ts +2 -0
  370. package/dist/security/ssrf.d.ts.map +1 -0
  371. package/dist/security/ssrf.js +126 -0
  372. package/dist/security/ssrf.js.map +1 -0
  373. package/dist/server.d.ts +14 -0
  374. package/dist/server.d.ts.map +1 -0
  375. package/dist/server.js +117 -0
  376. package/dist/server.js.map +1 -0
  377. package/dist/shared/__test-utils__/log-output.d.ts +49 -0
  378. package/dist/shared/__test-utils__/log-output.d.ts.map +1 -0
  379. package/dist/shared/__test-utils__/log-output.js +38 -0
  380. package/dist/shared/__test-utils__/log-output.js.map +1 -0
  381. package/dist/shared/config.d.ts +56 -0
  382. package/dist/shared/config.d.ts.map +1 -0
  383. package/dist/shared/config.js +290 -0
  384. package/dist/shared/config.js.map +1 -0
  385. package/dist/shared/errors.d.ts +139 -0
  386. package/dist/shared/errors.d.ts.map +1 -0
  387. package/dist/shared/errors.js +406 -0
  388. package/dist/shared/errors.js.map +1 -0
  389. package/dist/shared/events/factory.d.ts +143 -0
  390. package/dist/shared/events/factory.d.ts.map +1 -0
  391. package/dist/shared/events/factory.js +351 -0
  392. package/dist/shared/events/factory.js.map +1 -0
  393. package/dist/shared/events/index.d.ts +6 -0
  394. package/dist/shared/events/index.d.ts.map +1 -0
  395. package/dist/shared/events/index.js +3 -0
  396. package/dist/shared/events/index.js.map +1 -0
  397. package/dist/shared/events/serialize.d.ts +87 -0
  398. package/dist/shared/events/serialize.d.ts.map +1 -0
  399. package/dist/shared/events/serialize.js +510 -0
  400. package/dist/shared/events/serialize.js.map +1 -0
  401. package/dist/shared/events/types.d.ts +139 -0
  402. package/dist/shared/events/types.d.ts.map +1 -0
  403. package/dist/shared/events/types.js +2 -0
  404. package/dist/shared/events/types.js.map +1 -0
  405. package/dist/shared/harvest/event-buffer.d.ts +59 -0
  406. package/dist/shared/harvest/event-buffer.d.ts.map +1 -0
  407. package/dist/shared/harvest/event-buffer.js +100 -0
  408. package/dist/shared/harvest/event-buffer.js.map +1 -0
  409. package/dist/shared/harvest/harvest-scheduler.d.ts +200 -0
  410. package/dist/shared/harvest/harvest-scheduler.d.ts.map +1 -0
  411. package/dist/shared/harvest/harvest-scheduler.js +647 -0
  412. package/dist/shared/harvest/harvest-scheduler.js.map +1 -0
  413. package/dist/shared/harvest/index.d.ts +7 -0
  414. package/dist/shared/harvest/index.d.ts.map +1 -0
  415. package/dist/shared/harvest/index.js +4 -0
  416. package/dist/shared/harvest/index.js.map +1 -0
  417. package/dist/shared/harvest/metric-aggregator.d.ts +115 -0
  418. package/dist/shared/harvest/metric-aggregator.d.ts.map +1 -0
  419. package/dist/shared/harvest/metric-aggregator.js +247 -0
  420. package/dist/shared/harvest/metric-aggregator.js.map +1 -0
  421. package/dist/shared/index.d.ts +22 -0
  422. package/dist/shared/index.d.ts.map +1 -0
  423. package/dist/shared/index.js +13 -0
  424. package/dist/shared/index.js.map +1 -0
  425. package/dist/shared/logger.d.ts +57 -0
  426. package/dist/shared/logger.d.ts.map +1 -0
  427. package/dist/shared/logger.js +166 -0
  428. package/dist/shared/logger.js.map +1 -0
  429. package/dist/shared/pricing-data.d.ts +4 -0
  430. package/dist/shared/pricing-data.d.ts.map +1 -0
  431. package/dist/shared/pricing-data.js +473 -0
  432. package/dist/shared/pricing-data.js.map +1 -0
  433. package/dist/shared/pricing.d.ts +148 -0
  434. package/dist/shared/pricing.d.ts.map +1 -0
  435. package/dist/shared/pricing.js +528 -0
  436. package/dist/shared/pricing.js.map +1 -0
  437. package/dist/shared/redact.d.ts +33 -0
  438. package/dist/shared/redact.d.ts.map +1 -0
  439. package/dist/shared/redact.js +110 -0
  440. package/dist/shared/redact.js.map +1 -0
  441. package/dist/shared/timing.d.ts +96 -0
  442. package/dist/shared/timing.d.ts.map +1 -0
  443. package/dist/shared/timing.js +173 -0
  444. package/dist/shared/timing.js.map +1 -0
  445. package/dist/shared/tokens.d.ts +145 -0
  446. package/dist/shared/tokens.d.ts.map +1 -0
  447. package/dist/shared/tokens.js +492 -0
  448. package/dist/shared/tokens.js.map +1 -0
  449. package/dist/shared/transport/events-api.d.ts +14 -0
  450. package/dist/shared/transport/events-api.d.ts.map +1 -0
  451. package/dist/shared/transport/events-api.js +29 -0
  452. package/dist/shared/transport/events-api.js.map +1 -0
  453. package/dist/shared/transport/http-client.d.ts +49 -0
  454. package/dist/shared/transport/http-client.d.ts.map +1 -0
  455. package/dist/shared/transport/http-client.js +381 -0
  456. package/dist/shared/transport/http-client.js.map +1 -0
  457. package/dist/shared/transport/index.d.ts +10 -0
  458. package/dist/shared/transport/index.d.ts.map +1 -0
  459. package/dist/shared/transport/index.js +6 -0
  460. package/dist/shared/transport/index.js.map +1 -0
  461. package/dist/shared/transport/logs-api.d.ts +29 -0
  462. package/dist/shared/transport/logs-api.d.ts.map +1 -0
  463. package/dist/shared/transport/logs-api.js +40 -0
  464. package/dist/shared/transport/logs-api.js.map +1 -0
  465. package/dist/shared/transport/metric-api.d.ts +9 -0
  466. package/dist/shared/transport/metric-api.d.ts.map +1 -0
  467. package/dist/shared/transport/metric-api.js +39 -0
  468. package/dist/shared/transport/metric-api.js.map +1 -0
  469. package/dist/shared/transport/otlp-event-bridge.d.ts +22 -0
  470. package/dist/shared/transport/otlp-event-bridge.d.ts.map +1 -0
  471. package/dist/shared/transport/otlp-event-bridge.js +50 -0
  472. package/dist/shared/transport/otlp-event-bridge.js.map +1 -0
  473. package/dist/shared/transport/otlp-shared.d.ts +14 -0
  474. package/dist/shared/transport/otlp-shared.d.ts.map +1 -0
  475. package/dist/shared/transport/otlp-shared.js +49 -0
  476. package/dist/shared/transport/otlp-shared.js.map +1 -0
  477. package/dist/shared/transport/otlp-transport.d.ts +58 -0
  478. package/dist/shared/transport/otlp-transport.d.ts.map +1 -0
  479. package/dist/shared/transport/otlp-transport.js +236 -0
  480. package/dist/shared/transport/otlp-transport.js.map +1 -0
  481. package/dist/shared/transport/types.d.ts +129 -0
  482. package/dist/shared/transport/types.d.ts.map +1 -0
  483. package/dist/shared/transport/types.js +2 -0
  484. package/dist/shared/transport/types.js.map +1 -0
  485. package/dist/shared/version.d.ts +2 -0
  486. package/dist/shared/version.d.ts.map +1 -0
  487. package/dist/shared/version.js +2 -0
  488. package/dist/shared/version.js.map +1 -0
  489. package/dist/storage/index.d.ts +7 -0
  490. package/dist/storage/index.d.ts.map +1 -0
  491. package/dist/storage/index.js +4 -0
  492. package/dist/storage/index.js.map +1 -0
  493. package/dist/storage/local-store.d.ts +153 -0
  494. package/dist/storage/local-store.d.ts.map +1 -0
  495. package/dist/storage/local-store.js +719 -0
  496. package/dist/storage/local-store.js.map +1 -0
  497. package/dist/storage/retention.d.ts +2 -0
  498. package/dist/storage/retention.d.ts.map +1 -0
  499. package/dist/storage/retention.js +53 -0
  500. package/dist/storage/retention.js.map +1 -0
  501. package/dist/storage/session-store.d.ts +97 -0
  502. package/dist/storage/session-store.d.ts.map +1 -0
  503. package/dist/storage/session-store.js +391 -0
  504. package/dist/storage/session-store.js.map +1 -0
  505. package/dist/storage/types.d.ts +64 -0
  506. package/dist/storage/types.d.ts.map +1 -0
  507. package/dist/storage/types.js +2 -0
  508. package/dist/storage/types.js.map +1 -0
  509. package/dist/storage/weekly-summary.d.ts +61 -0
  510. package/dist/storage/weekly-summary.d.ts.map +1 -0
  511. package/dist/storage/weekly-summary.js +243 -0
  512. package/dist/storage/weekly-summary.js.map +1 -0
  513. package/dist/tools/analytics-tools.d.ts +101 -0
  514. package/dist/tools/analytics-tools.d.ts.map +1 -0
  515. package/dist/tools/analytics-tools.js +71 -0
  516. package/dist/tools/analytics-tools.js.map +1 -0
  517. package/dist/tools/cost-tools.d.ts +121 -0
  518. package/dist/tools/cost-tools.d.ts.map +1 -0
  519. package/dist/tools/cost-tools.js +174 -0
  520. package/dist/tools/cost-tools.js.map +1 -0
  521. package/dist/tools/cross-session-tools.d.ts +376 -0
  522. package/dist/tools/cross-session-tools.d.ts.map +1 -0
  523. package/dist/tools/cross-session-tools.js +820 -0
  524. package/dist/tools/cross-session-tools.js.map +1 -0
  525. package/dist/tools/extended-analytics-tools.d.ts +164 -0
  526. package/dist/tools/extended-analytics-tools.d.ts.map +1 -0
  527. package/dist/tools/extended-analytics-tools.js +121 -0
  528. package/dist/tools/extended-analytics-tools.js.map +1 -0
  529. package/dist/tools/index.d.ts +7 -0
  530. package/dist/tools/index.d.ts.map +1 -0
  531. package/dist/tools/index.js +4 -0
  532. package/dist/tools/index.js.map +1 -0
  533. package/dist/tools/session-stats.d.ts +162 -0
  534. package/dist/tools/session-stats.d.ts.map +1 -0
  535. package/dist/tools/session-stats.js +1054 -0
  536. package/dist/tools/session-stats.js.map +1 -0
  537. package/dist/tools/workflow-tools.d.ts +126 -0
  538. package/dist/tools/workflow-tools.d.ts.map +1 -0
  539. package/dist/tools/workflow-tools.js +274 -0
  540. package/dist/tools/workflow-tools.js.map +1 -0
  541. package/dist/tracing/mcp-tracer.d.ts +4 -0
  542. package/dist/tracing/mcp-tracer.d.ts.map +1 -0
  543. package/dist/tracing/mcp-tracer.js +14 -0
  544. package/dist/tracing/mcp-tracer.js.map +1 -0
  545. package/dist/tracing/session-span.d.ts +14 -0
  546. package/dist/tracing/session-span.d.ts.map +1 -0
  547. package/dist/tracing/session-span.js +53 -0
  548. package/dist/tracing/session-span.js.map +1 -0
  549. package/dist/tracing/task-span-tracker.d.ts +11 -0
  550. package/dist/tracing/task-span-tracker.d.ts.map +1 -0
  551. package/dist/tracing/task-span-tracker.js +59 -0
  552. package/dist/tracing/task-span-tracker.js.map +1 -0
  553. package/dist/tracing/tool-call-span.d.ts +4 -0
  554. package/dist/tracing/tool-call-span.d.ts.map +1 -0
  555. package/dist/tracing/tool-call-span.js +60 -0
  556. package/dist/tracing/tool-call-span.js.map +1 -0
  557. package/dist/transport/index.d.ts +3 -0
  558. package/dist/transport/index.d.ts.map +1 -0
  559. package/dist/transport/index.js +2 -0
  560. package/dist/transport/index.js.map +1 -0
  561. package/dist/transport/log-ingest.d.ts +42 -0
  562. package/dist/transport/log-ingest.d.ts.map +1 -0
  563. package/dist/transport/log-ingest.js +151 -0
  564. package/dist/transport/log-ingest.js.map +1 -0
  565. package/dist/transport/nr-ingest.d.ts +171 -0
  566. package/dist/transport/nr-ingest.d.ts.map +1 -0
  567. package/dist/transport/nr-ingest.js +659 -0
  568. package/dist/transport/nr-ingest.js.map +1 -0
  569. package/dist/types.d.ts +45 -0
  570. package/dist/types.d.ts.map +1 -0
  571. package/dist/types.js +2 -0
  572. package/dist/types.js.map +1 -0
  573. package/dist/web/assets/index-BrL281N-.css +2 -0
  574. package/dist/web/assets/index-CcaYZzXm.js +42 -0
  575. package/dist/web/favicon.svg +15 -0
  576. package/dist/web/index.html +15 -0
  577. package/examples/local-alert-rules.json +106 -0
  578. package/package.json +125 -1
@@ -0,0 +1,659 @@
1
+ /**
2
+ * New Relic Event Ingestion — converts ToolCallRecords into NR events and
3
+ * metrics, then ships them via the shared HarvestScheduler.
4
+ */
5
+ import { HarvestScheduler, MetricAggregator, sendEvents, sendMetrics, OtlpTransport, OtlpEventBridge, createLogger, } from '../shared/index.js';
6
+ const logger = createLogger('nr-ingest');
7
+ import { redactSensitive } from '../config.js';
8
+ import { ProxyMetricsTracker } from '../metrics/proxy-metrics.js';
9
+ import { AuditTrailManager, auditRecordToNrEvent, securityAlertToNrEvent, } from '../security/index.js';
10
+ import { LogIngestManager } from './log-ingest.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Serializer
13
+ // ---------------------------------------------------------------------------
14
+ /** Standard ToolCallRecord keys that are handled explicitly. */
15
+ const STANDARD_KEYS = new Set([
16
+ 'id',
17
+ 'sessionId',
18
+ 'toolName',
19
+ 'toolUseId',
20
+ 'timestamp',
21
+ 'durationMs',
22
+ 'success',
23
+ 'errorType',
24
+ 'error',
25
+ 'inputSizeBytes',
26
+ 'outputSizeBytes',
27
+ 'inputHash',
28
+ 'platform',
29
+ ]);
30
+ /**
31
+ * Tool-specific string fields that may carry secrets (Bash commands, file paths,
32
+ * grep patterns, sub-agent prompts, audit detail strings). Anything in this set
33
+ * is run through redactSensitive() before leaving the process. New fields that
34
+ * could contain user input must be added here — silent passthrough is the
35
+ * default failure mode and it leaks secrets to NR.
36
+ */
37
+ const REDACT_FIELD_KEYS = new Set([
38
+ 'command',
39
+ 'filePath',
40
+ 'file_path',
41
+ 'pattern',
42
+ 'agentDescription',
43
+ 'agent_description',
44
+ 'detail',
45
+ 'cwd',
46
+ ]);
47
+ /**
48
+ * Convert a ToolCallRecord into a flat NR event object.
49
+ *
50
+ * Standard fields are mapped to snake_case NR attributes; any extra
51
+ * tool-specific fields (string | number | boolean) are included as-is.
52
+ */
53
+ export function toolCallToNrEvent(record, attrs) {
54
+ const event = {
55
+ eventType: 'AiToolCall',
56
+ timestamp: record.timestamp,
57
+ tool: record.toolName,
58
+ tool_use_id: record.toolUseId,
59
+ success: record.success,
60
+ developer: attrs.developer,
61
+ app_name: attrs.appName,
62
+ };
63
+ if (attrs.teamId)
64
+ event.team_id = attrs.teamId;
65
+ if (attrs.projectId)
66
+ event.project_id = attrs.projectId;
67
+ if (attrs.orgId)
68
+ event.org_id = attrs.orgId;
69
+ if (attrs.sessionTraceId != null)
70
+ event.session_id = attrs.sessionTraceId;
71
+ if (record.durationMs != null)
72
+ event.duration_ms = record.durationMs;
73
+ if (record.errorType != null)
74
+ event.error_type = record.errorType;
75
+ // Tool error messages occasionally include URLs from failed curl commands
76
+ // and similar — possible to embed an Authorization header or token query
77
+ // string in the message. Same redaction policy as the tool-specific fields.
78
+ if (record.error != null)
79
+ event.error = redactSensitive(record.error);
80
+ if (record.inputSizeBytes != null)
81
+ event.input_size_bytes = record.inputSizeBytes;
82
+ if (record.outputSizeBytes != null)
83
+ event.output_size_bytes = record.outputSizeBytes;
84
+ if (record.inputHash != null)
85
+ event.input_hash = record.inputHash;
86
+ // Platform attribution — defaults to 'claude-code' for backward compatibility
87
+ event.platform = typeof record.platform === 'string' ? record.platform : 'claude-code';
88
+ // Include tool-specific fields from parsers. String fields known to potentially
89
+ // carry secrets (commands, file paths, grep patterns, sub-agent prompts) are
90
+ // redacted before egress — the auditRecordToNrEvent path already does this for
91
+ // its own egress channel; the AiToolCall path must do the same.
92
+ for (const [key, value] of Object.entries(record)) {
93
+ if (STANDARD_KEYS.has(key))
94
+ continue;
95
+ if (typeof value === 'string') {
96
+ event[key] = REDACT_FIELD_KEYS.has(key) ? redactSensitive(value) : value;
97
+ }
98
+ else if (typeof value === 'number' || typeof value === 'boolean') {
99
+ event[key] = value;
100
+ }
101
+ }
102
+ return event;
103
+ }
104
+ /** Type guard for ProxyToolCallRecord (has serverName and upstreamLatencyMs with correct types). */
105
+ export function isProxyToolCall(record) {
106
+ return ('serverName' in record &&
107
+ typeof record.serverName === 'string' &&
108
+ 'upstreamLatencyMs' in record &&
109
+ typeof record.upstreamLatencyMs === 'number');
110
+ }
111
+ /**
112
+ * Convert a ProxyToolCallRecord into an NR event with proxy-specific attributes.
113
+ */
114
+ export function proxyToolCallToNrEvent(record, attrs) {
115
+ const event = {
116
+ eventType: 'AiMcpToolCall',
117
+ timestamp: record.timestamp,
118
+ server: record.serverName,
119
+ tool: record.toolName,
120
+ duration_ms: record.durationMs ?? 0,
121
+ upstream_latency_ms: record.upstreamLatencyMs,
122
+ success: record.success,
123
+ developer: attrs.developer,
124
+ app_name: attrs.appName,
125
+ };
126
+ if (attrs.teamId)
127
+ event.team_id = attrs.teamId;
128
+ if (attrs.projectId)
129
+ event.project_id = attrs.projectId;
130
+ if (attrs.orgId)
131
+ event.org_id = attrs.orgId;
132
+ if (attrs.sessionTraceId != null)
133
+ event.session_id = attrs.sessionTraceId;
134
+ if (record.proxyOverheadMs != null)
135
+ event.proxy_overhead_ms = record.proxyOverheadMs;
136
+ if (record.errorType != null)
137
+ event.error_type = record.errorType;
138
+ if (record.inputSizeBytes != null)
139
+ event.request_size_bytes = record.inputSizeBytes;
140
+ if (record.outputSizeBytes != null)
141
+ event.response_size_bytes = record.outputSizeBytes;
142
+ return event;
143
+ }
144
+ /**
145
+ * Convert a ProxyRequestRecord (discovery methods like tools/list) into an NR event.
146
+ */
147
+ export function proxyRequestToNrEvent(record, attrs) {
148
+ const event = {
149
+ eventType: 'AiProxyRequest',
150
+ timestamp: record.timestamp,
151
+ server: record.serverName,
152
+ method: record.method,
153
+ duration_ms: record.durationMs,
154
+ upstream_latency_ms: record.upstreamLatencyMs,
155
+ success: record.success,
156
+ developer: attrs.developer,
157
+ app_name: attrs.appName,
158
+ };
159
+ if (attrs.teamId)
160
+ event.team_id = attrs.teamId;
161
+ if (attrs.projectId)
162
+ event.project_id = attrs.projectId;
163
+ if (attrs.orgId)
164
+ event.org_id = attrs.orgId;
165
+ if (record.proxyOverheadMs != null)
166
+ event.proxy_overhead_ms = record.proxyOverheadMs;
167
+ if (record.responseSizeBytes != null)
168
+ event.response_size_bytes = record.responseSizeBytes;
169
+ return event;
170
+ }
171
+ /**
172
+ * Convert an AiCodingTask into a flat NR event object.
173
+ *
174
+ * All fields use snake_case to match the convention of AiToolCall/AiAuditEvent.
175
+ * File path arrays are emitted as counts to keep event size small.
176
+ */
177
+ export function codingTaskToNrEvent(task, attrs) {
178
+ const firstRecord = task.toolCalls[0];
179
+ const platform = typeof firstRecord?.platform === 'string' ? firstRecord.platform : 'claude-code';
180
+ const event = {
181
+ eventType: 'AiCodingTask',
182
+ timestamp: task.endTime,
183
+ task_id: task.taskId,
184
+ developer: attrs.developer,
185
+ app_name: attrs.appName,
186
+ platform,
187
+ start_time: task.startTime,
188
+ end_time: task.endTime,
189
+ duration_ms: task.durationMs,
190
+ tool_call_count: task.toolCallCount,
191
+ files_read: task.filesRead.length,
192
+ files_modified: task.filesModified.length,
193
+ lines_added: task.linesAdded,
194
+ lines_removed: task.linesRemoved,
195
+ bash_commands_run: task.bashCommandsRun,
196
+ tests_run: task.testsRun,
197
+ tests_passed: task.testsPassed,
198
+ build_run: task.buildRun,
199
+ build_passed: task.buildPassed,
200
+ estimated_cost_usd: task.estimatedCostUsd ?? 0,
201
+ // Distinguish genuine zero-cost from "cost was never computed" so NRQL
202
+ // sum(estimated_cost_usd) doesn't silently undercount.
203
+ cost_estimated: task.estimatedCostUsd !== null,
204
+ tokens_used: task.tokensUsed,
205
+ asked_user_questions: task.askedUserQuestions,
206
+ sub_agents_spawned: task.subAgentsSpawned,
207
+ };
208
+ if (attrs.teamId)
209
+ event.team_id = attrs.teamId;
210
+ if (attrs.projectId)
211
+ event.project_id = attrs.projectId;
212
+ if (attrs.orgId)
213
+ event.org_id = attrs.orgId;
214
+ // Fix 3: sessionTraceId is the resolved Claude Code session_id; the
215
+ // firstRecord?.sessionId fallback was only meaningful when the MCP fabricated
216
+ // its own UUID and lost cross-reference with the tool-call records.
217
+ if (attrs.sessionTraceId != null)
218
+ event.session_id = attrs.sessionTraceId;
219
+ return event;
220
+ }
221
+ /**
222
+ * Convert an AntiPattern into a flat NR event object.
223
+ *
224
+ * Optional fields are only included when defined on the source pattern.
225
+ */
226
+ export function antiPatternToNrEvent(pattern, attrs) {
227
+ const event = {
228
+ eventType: 'AiAntiPattern',
229
+ timestamp: attrs.detectedAt ?? Date.now(),
230
+ // Field name is intentionally 'type' (not 'patternType') — used by all NRQL queries and dashboards. Do not rename.
231
+ type: pattern.type,
232
+ task_id: attrs.taskId,
233
+ developer: attrs.developer,
234
+ app_name: attrs.appName,
235
+ platform: attrs.platform ?? 'claude-code',
236
+ suggestion: pattern.suggestion,
237
+ };
238
+ if (attrs.teamId)
239
+ event.team_id = attrs.teamId;
240
+ if (attrs.projectId)
241
+ event.project_id = attrs.projectId;
242
+ if (attrs.orgId)
243
+ event.org_id = attrs.orgId;
244
+ if (attrs.sessionId != null)
245
+ event.session_id = attrs.sessionId;
246
+ // pattern.file is sourced from raw call.filePath in detectThrashing, and
247
+ // pattern.command from raw Bash commands in other detectors — both can
248
+ // carry query-string tokens or Authorization headers. Same egress channel
249
+ // as toolCallToNrEvent, so the same redaction policy applies.
250
+ if (pattern.file != null)
251
+ event.file = redactSensitive(pattern.file);
252
+ if (pattern.command != null)
253
+ event.command = redactSensitive(pattern.command);
254
+ if (pattern.iterations != null)
255
+ event.iterations = pattern.iterations;
256
+ if (pattern.readCount != null)
257
+ event.read_count = pattern.readCount;
258
+ if (pattern.repeatCount != null)
259
+ event.repeat_count = pattern.repeatCount;
260
+ if (pattern.editCount != null)
261
+ event.edit_count = pattern.editCount;
262
+ if (pattern.agentCount != null)
263
+ event.agent_count = pattern.agentCount;
264
+ return event;
265
+ }
266
+ // ---------------------------------------------------------------------------
267
+ // Retry classification
268
+ // ---------------------------------------------------------------------------
269
+ // 4xx errors that the transport already dropped as permanent failures — re-queuing them
270
+ // would cause an infinite retry loop since the same request will fail again. Exclude 408
271
+ // (Request Timeout, network-level, worth retrying) and 429 (Too Many Requests, rate-limited,
272
+ // worth retrying on the next harvest cycle).
273
+ function isNonRetryable4xx(statusCode) {
274
+ return statusCode >= 400 && statusCode < 500 && statusCode !== 408 && statusCode !== 429;
275
+ }
276
+ // ---------------------------------------------------------------------------
277
+ // NrIngestManager
278
+ // ---------------------------------------------------------------------------
279
+ export class NrIngestManager {
280
+ scheduler;
281
+ logIngest;
282
+ sessionTracker;
283
+ proxyMetrics;
284
+ costTracker;
285
+ efficiencyScorer;
286
+ auditTrail;
287
+ developer;
288
+ appName;
289
+ sessionTraceId;
290
+ teamId;
291
+ projectId;
292
+ orgId;
293
+ metricHarvestIntervalMs;
294
+ turnCostAttributor;
295
+ otlpTransport;
296
+ otlpEventBridge;
297
+ sessionGaugeIntervalId = null;
298
+ running = false;
299
+ constructor(options) {
300
+ this.developer = options.developer;
301
+ this.appName = options.appName;
302
+ this.sessionTraceId = options.sessionTraceId;
303
+ this.teamId = options.teamId;
304
+ this.projectId = options.projectId;
305
+ this.orgId = options.orgId;
306
+ this.sessionTracker = options.sessionTracker;
307
+ this.proxyMetrics = new ProxyMetricsTracker();
308
+ this.costTracker = options.costTracker;
309
+ this.efficiencyScorer = options.efficiencyScorer;
310
+ this.turnCostAttributor = options.turnCostAttributor;
311
+ this.auditTrail =
312
+ options.auditTrail ??
313
+ new AuditTrailManager({
314
+ developer: options.developer,
315
+ sessionId: options.sessionId ?? null,
316
+ localStore: options.localStore,
317
+ });
318
+ this.metricHarvestIntervalMs = options.metricHarvestIntervalMs ?? 60_000;
319
+ let otlpTransport = null;
320
+ let otlpEventBridge = null;
321
+ if (options.otlpEndpoint) {
322
+ otlpTransport = new OtlpTransport({
323
+ endpoint: options.otlpEndpoint,
324
+ headers: options.otlpHeaders,
325
+ appName: options.appName,
326
+ clientName: 'newrelic-preflight',
327
+ });
328
+ otlpEventBridge = new OtlpEventBridge({
329
+ endpoint: options.otlpEndpoint,
330
+ headers: options.otlpHeaders,
331
+ appName: options.appName,
332
+ clientName: 'newrelic-preflight',
333
+ });
334
+ // OtlpTransport no longer has an explicit start() — providers initialise in the constructor.
335
+ }
336
+ this.otlpTransport = otlpTransport;
337
+ this.otlpEventBridge = otlpEventBridge;
338
+ // Wrap send functions so non-retryable 4xx failures (400, 403, etc.) are not
339
+ // re-queued by HarvestScheduler. Returning success=true suppresses the requeue
340
+ // without masking the original error — we log a warning before returning.
341
+ const rawSendEventsFn = options.sendEventsFn ?? sendEvents;
342
+ const classifyingEventsFn = async (events, licenseKey, opts) => {
343
+ const result = await rawSendEventsFn(events, licenseKey, opts);
344
+ if (!result.success && result.statusCode !== null && isNonRetryable4xx(result.statusCode)) {
345
+ logger.warn('Dropping non-retryable event batch', {
346
+ statusCode: result.statusCode,
347
+ batchSize: events.length,
348
+ });
349
+ return { ...result, success: true };
350
+ }
351
+ return result;
352
+ };
353
+ const rawSendMetricsFn = options.sendMetricsFn ?? sendMetrics;
354
+ const classifyingMetricsFn = async (metrics, licenseKey, opts) => {
355
+ const result = await rawSendMetricsFn(metrics, licenseKey, opts);
356
+ if (!result.success && result.statusCode !== null && isNonRetryable4xx(result.statusCode)) {
357
+ logger.warn('Dropping non-retryable metric batch', {
358
+ statusCode: result.statusCode,
359
+ batchSize: metrics.length,
360
+ });
361
+ return { ...result, success: true };
362
+ }
363
+ return result;
364
+ };
365
+ const transportOptions = {
366
+ ...options.transportOptions,
367
+ clientName: 'newrelic-preflight',
368
+ };
369
+ this.scheduler = new HarvestScheduler({
370
+ licenseKey: options.licenseKey,
371
+ transportOptions,
372
+ eventHarvestIntervalMs: options.eventHarvestIntervalMs,
373
+ metricHarvestIntervalMs: options.metricHarvestIntervalMs,
374
+ sendEventsFn: classifyingEventsFn,
375
+ sendMetricsFn: classifyingMetricsFn,
376
+ otlpEventBridge: otlpEventBridge ?? undefined,
377
+ otlpTransport: otlpTransport ?? undefined,
378
+ transport: options.transport,
379
+ allowProcessExit: true,
380
+ });
381
+ this.logIngest = new LogIngestManager({
382
+ licenseKey: options.licenseKey,
383
+ transportOptions,
384
+ developer: options.developer,
385
+ appName: options.appName,
386
+ logHarvestIntervalMs: options.logHarvestIntervalMs,
387
+ sendLogsFn: options.sendLogsFn,
388
+ });
389
+ }
390
+ ingestProxyRequest(record) {
391
+ const event = proxyRequestToNrEvent(record, {
392
+ developer: this.developer,
393
+ appName: this.appName,
394
+ teamId: this.teamId,
395
+ projectId: this.projectId,
396
+ orgId: this.orgId,
397
+ });
398
+ this.scheduler.addEvent(event);
399
+ const server = record.serverName;
400
+ this.scheduler.recordMetric('ai.mcp.proxy_request_count', 1, { server, method: record.method });
401
+ if (record.durationMs != null) {
402
+ this.scheduler.recordMetric('ai.mcp.proxy_request_duration_ms', record.durationMs, {
403
+ server,
404
+ });
405
+ }
406
+ // Aggregate into proxy metrics tracker
407
+ this.proxyMetrics.recordProxyRequest(record);
408
+ }
409
+ ingestToolCall(record, auditRecord) {
410
+ // Buffer event for NR Events API
411
+ const event = toolCallToNrEvent(record, {
412
+ developer: this.developer,
413
+ appName: this.appName,
414
+ sessionTraceId: this.sessionTraceId,
415
+ teamId: this.teamId,
416
+ projectId: this.projectId,
417
+ orgId: this.orgId,
418
+ });
419
+ // Cost attribution is available via the nr_observe_get_cost_per_tool MCP tool only.
420
+ // Enriching NR events here would always produce null because the token event
421
+ // (which finalizes turn cost) arrives asynchronously after ingestToolCall is called.
422
+ this.scheduler.addEvent(event);
423
+ // Record per-call metrics for NR Metric API
424
+ const tool = record.toolName;
425
+ const sessionId = this.sessionTraceId;
426
+ const teamDims = {};
427
+ if (this.teamId)
428
+ teamDims.team_id = this.teamId;
429
+ if (this.projectId)
430
+ teamDims.project_id = this.projectId;
431
+ if (this.orgId)
432
+ teamDims.org_id = this.orgId;
433
+ this.scheduler.recordMetric('ai.tool.call_count', 1, sessionId != null ? { tool, session_id: sessionId, ...teamDims } : { tool, ...teamDims });
434
+ if (record.durationMs != null) {
435
+ this.scheduler.recordMetric('ai.tool.duration_ms', record.durationMs, sessionId != null ? { tool, session_id: sessionId, ...teamDims } : { tool, ...teamDims });
436
+ }
437
+ this.scheduler.recordMetric('ai.tool.success', record.success ? 1 : 0, sessionId != null ? { tool, session_id: sessionId, ...teamDims } : { tool, ...teamDims });
438
+ // If this is a proxied tool call, also emit AiMcpToolCall event and aggregate
439
+ if (isProxyToolCall(record)) {
440
+ const proxyEvent = proxyToolCallToNrEvent(record, {
441
+ developer: this.developer,
442
+ appName: this.appName,
443
+ sessionTraceId: this.sessionTraceId,
444
+ teamId: this.teamId,
445
+ projectId: this.projectId,
446
+ orgId: this.orgId,
447
+ });
448
+ this.scheduler.addEvent(proxyEvent);
449
+ this.proxyMetrics.recordProxyCall(record);
450
+ }
451
+ // Security audit trail. The caller may pass a pre-computed auditRecord
452
+ // (e.g. from the onRecord pipeline so audit recording works in local mode);
453
+ // fall back to recording here for any callers that don't.
454
+ const finalAuditRecord = auditRecord ??
455
+ (isProxyToolCall(record)
456
+ ? this.auditTrail.recordProxyCall(record)
457
+ : this.auditTrail.recordToolCall(record));
458
+ this.scheduler.addEvent(auditRecordToNrEvent(finalAuditRecord, {
459
+ teamId: this.teamId,
460
+ projectId: this.projectId,
461
+ orgId: this.orgId,
462
+ }));
463
+ if (finalAuditRecord.securityAlert) {
464
+ this.scheduler.addEvent(securityAlertToNrEvent(finalAuditRecord, {
465
+ teamId: this.teamId,
466
+ projectId: this.projectId,
467
+ orgId: this.orgId,
468
+ }));
469
+ }
470
+ // Queue audit log entry for NR Logs API
471
+ this.logIngest.addAuditRecord(finalAuditRecord);
472
+ }
473
+ ingestCodingTask(task) {
474
+ const event = codingTaskToNrEvent(task, {
475
+ developer: this.developer,
476
+ appName: this.appName,
477
+ sessionTraceId: this.sessionTraceId,
478
+ teamId: this.teamId,
479
+ projectId: this.projectId,
480
+ orgId: this.orgId,
481
+ });
482
+ this.scheduler.addEvent(event);
483
+ }
484
+ ingestAntiPattern(pattern, context) {
485
+ const event = antiPatternToNrEvent(pattern, {
486
+ developer: this.developer,
487
+ appName: this.appName,
488
+ sessionId: this.sessionTraceId,
489
+ platform: context.platform,
490
+ taskId: context.taskId,
491
+ teamId: this.teamId,
492
+ projectId: this.projectId,
493
+ orgId: this.orgId,
494
+ detectedAt: context.detectedAt,
495
+ });
496
+ this.scheduler.addEvent(event);
497
+ }
498
+ ingestContextSnapshot(snapshot, topTools) {
499
+ const nrEvent = {
500
+ eventType: 'AiContextSnapshot',
501
+ timestamp: snapshot.timestamp,
502
+ developer: this.developer,
503
+ appName: this.appName,
504
+ turn_number: snapshot.turnNumber,
505
+ total_context_tokens: snapshot.inputTokens,
506
+ output_tokens: snapshot.outputTokens,
507
+ cache_read_tokens: snapshot.cacheReadTokens,
508
+ cache_creation_tokens: snapshot.cacheCreationTokens,
509
+ fill_percent: snapshot.fillPercent,
510
+ system_tokens: snapshot.breakdown.system,
511
+ tool_tokens: snapshot.breakdown.tools,
512
+ user_tokens: snapshot.breakdown.user,
513
+ assistant_tokens: snapshot.breakdown.assistant,
514
+ };
515
+ if (topTools.length > 0) {
516
+ nrEvent.top_tool = topTools[0].tool;
517
+ nrEvent.top_tool_bytes = topTools[0].totalBytes;
518
+ nrEvent.top_tool_tokens = topTools[0].estimatedTokens;
519
+ }
520
+ if (this.teamId)
521
+ nrEvent.team_id = this.teamId;
522
+ if (this.projectId)
523
+ nrEvent.project_id = this.projectId;
524
+ if (this.orgId)
525
+ nrEvent.org_id = this.orgId;
526
+ if (this.sessionTraceId != null)
527
+ nrEvent.session_id = this.sessionTraceId;
528
+ this.scheduler.addEvent(nrEvent);
529
+ }
530
+ ingestBudgetWarning(event) {
531
+ const nrEvent = {
532
+ eventType: 'AiBudgetWarning',
533
+ timestamp: event.timestamp,
534
+ developer: this.developer,
535
+ appName: this.appName,
536
+ budget_period: event.period,
537
+ threshold_pct: event.thresholdPct,
538
+ spent_usd: event.spentUsd,
539
+ budget_usd: event.budgetUsd,
540
+ remaining_usd: Math.max(0, event.budgetUsd - event.spentUsd),
541
+ };
542
+ if (this.teamId)
543
+ nrEvent.team_id = this.teamId;
544
+ if (this.projectId)
545
+ nrEvent.project_id = this.projectId;
546
+ if (this.orgId)
547
+ nrEvent.org_id = this.orgId;
548
+ if (this.sessionTraceId != null)
549
+ nrEvent.session_id = this.sessionTraceId;
550
+ this.scheduler.addEvent(nrEvent);
551
+ }
552
+ start() {
553
+ if (this.running)
554
+ return;
555
+ this.running = true;
556
+ this.scheduler.start();
557
+ this.logIngest.start();
558
+ // Emit session-level gauges on the metric harvest cadence
559
+ this.sessionGaugeIntervalId = setInterval(() => {
560
+ this.emitSessionGauges();
561
+ }, this.metricHarvestIntervalMs);
562
+ this.sessionGaugeIntervalId.unref();
563
+ }
564
+ async stop() {
565
+ if (!this.running)
566
+ return;
567
+ // Emit final session gauges before clearing interval and stopping scheduler
568
+ this.emitSessionGauges();
569
+ // Clear session gauge interval
570
+ if (this.sessionGaugeIntervalId !== null) {
571
+ clearInterval(this.sessionGaugeIntervalId);
572
+ this.sessionGaugeIntervalId = null;
573
+ }
574
+ this.running = false;
575
+ const cleanupPromises = [this.scheduler.stop(), this.logIngest.stop()];
576
+ if (this.otlpTransport) {
577
+ cleanupPromises.push(this.otlpTransport.shutdown());
578
+ }
579
+ if (this.otlpEventBridge) {
580
+ cleanupPromises.push(this.otlpEventBridge.shutdown());
581
+ }
582
+ const results = await Promise.allSettled(cleanupPromises);
583
+ for (const r of results) {
584
+ if (r.status === 'rejected') {
585
+ logger.warn('Error stopping NrIngest service', { error: String(r.reason) });
586
+ }
587
+ }
588
+ }
589
+ emitSessionGauges() {
590
+ if (!this.running)
591
+ return;
592
+ const sessionId = this.sessionTraceId;
593
+ const teamAttrs = {};
594
+ if (this.teamId)
595
+ teamAttrs.team_id = this.teamId;
596
+ if (this.projectId)
597
+ teamAttrs.project_id = this.projectId;
598
+ if (this.orgId)
599
+ teamAttrs.org_id = this.orgId;
600
+ const record = (name, value, attrs = {}) => {
601
+ this.scheduler.recordMetric(name, value, sessionId != null ? { session_id: sessionId, ...attrs } : attrs);
602
+ };
603
+ const metrics = this.sessionTracker.getMetrics();
604
+ record('ai.session.duration_ms', metrics.sessionDurationMs, { ...teamAttrs });
605
+ record('ai.session.unique_files_read', metrics.uniqueFilesRead, { ...teamAttrs });
606
+ record('ai.session.unique_files_written', metrics.uniqueFilesWritten, { ...teamAttrs });
607
+ // Emit cost and efficiency metrics with developer dimension so Team View
608
+ // FACET developer queries return per-developer breakdowns.
609
+ if (this.costTracker || this.efficiencyScorer) {
610
+ const developer = this.developer;
611
+ const scheduler = this.scheduler;
612
+ const devAggregator = new MetricAggregator();
613
+ const _origRecord = devAggregator.record.bind(devAggregator);
614
+ // Override record() to inject developer + team attribution on every metric.
615
+ // The bound original is preserved so TypeScript sees the full MetricAggregator type.
616
+ devAggregator.record = (name, value, attrs = {}) => {
617
+ scheduler.recordMetric(name, value, sessionId != null
618
+ ? { developer, session_id: sessionId, ...teamAttrs, ...attrs }
619
+ : { developer, ...teamAttrs, ...attrs });
620
+ return true;
621
+ };
622
+ this.costTracker?.emitMetrics(devAggregator);
623
+ this.efficiencyScorer?.emitMetrics(devAggregator);
624
+ }
625
+ // Emit aggregated proxy metrics
626
+ const proxyMetrics = this.proxyMetrics.getMetrics();
627
+ for (const [server, stats] of Object.entries(proxyMetrics.perServer)) {
628
+ this.scheduler.recordMetric('ai.mcp.server_call_count', stats.callCount, {
629
+ server,
630
+ ...teamAttrs,
631
+ });
632
+ if (stats.latencyMs.count > 0) {
633
+ const avg = stats.latencyMs.sum / stats.latencyMs.count;
634
+ this.scheduler.recordMetric('ai.mcp.server_latency_ms', avg, { server, ...teamAttrs });
635
+ }
636
+ if (stats.errorRate > 0) {
637
+ this.scheduler.recordMetric('ai.mcp.server_error_rate', stats.errorRate, {
638
+ server,
639
+ ...teamAttrs,
640
+ });
641
+ }
642
+ }
643
+ if (proxyMetrics.avgProxyOverheadMs > 0) {
644
+ this.scheduler.recordMetric('ai.mcp.proxy_overhead_ms', proxyMetrics.avgProxyOverheadMs, {
645
+ ...teamAttrs,
646
+ });
647
+ }
648
+ // Cap at 100 (tool, server) combinations to stay within NR Metric API cardinality limits.
649
+ const MAX_TOOL_POPULARITY_ENTRIES = 100;
650
+ for (const entry of proxyMetrics.toolPopularity.slice(0, MAX_TOOL_POPULARITY_ENTRIES)) {
651
+ this.scheduler.recordMetric('ai.mcp.tool_popularity', entry.count, {
652
+ tool: entry.tool,
653
+ server: entry.server,
654
+ ...teamAttrs,
655
+ });
656
+ }
657
+ }
658
+ }
659
+ //# sourceMappingURL=nr-ingest.js.map