@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 @@
1
+ {"version":3,"file":"context-window-tracker.d.ts","sourceRoot":"","sources":["../../src/metrics/context-window-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/E;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,cAAc,CAA6B;IAEnD,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAQ5C,UAAU,IAAI,oBAAoB;IAuBlC,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAGhC"}
@@ -0,0 +1,35 @@
1
+ export class ContextWindowTracker {
2
+ fileReadCounts = new Map();
3
+ recordToolCall(record) {
4
+ if (record.toolName !== 'Read')
5
+ return;
6
+ const filePath = record.filePath;
7
+ if (!filePath)
8
+ return;
9
+ const count = this.fileReadCounts.get(filePath) ?? 0;
10
+ this.fileReadCounts.set(filePath, count + 1);
11
+ }
12
+ getMetrics() {
13
+ const entries = [...this.fileReadCounts.entries()];
14
+ const totalReadOperations = entries.reduce((sum, [, c]) => sum + c, 0);
15
+ const uniqueFilesRead = entries.length;
16
+ const repeatedReadCount = entries.reduce((sum, [, c]) => sum + Math.max(0, c - 1), 0);
17
+ const repeatedReadRatio = totalReadOperations > 0 ? repeatedReadCount / totalReadOperations : null;
18
+ const topRepeatedFiles = entries
19
+ .filter(([, c]) => c > 1)
20
+ .sort((a, b) => b[1] - a[1])
21
+ .slice(0, 5)
22
+ .map(([file, readCount]) => ({ file, readCount }));
23
+ return {
24
+ uniqueFilesRead,
25
+ totalReadOperations,
26
+ repeatedReadCount,
27
+ repeatedReadRatio,
28
+ topRepeatedFiles,
29
+ };
30
+ }
31
+ reset(_sessionId) {
32
+ this.fileReadCounts.clear();
33
+ }
34
+ }
35
+ //# sourceMappingURL=context-window-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-window-tracker.js","sourceRoot":"","sources":["../../src/metrics/context-window-tracker.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,oBAAoB;IACvB,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEnD,cAAc,CAAC,MAAsB;QACnC,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM;YAAE,OAAO;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAA8B,CAAC;QACvD,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IAED,UAAU;QACR,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;QACnD,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;QACvC,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtF,MAAM,iBAAiB,GACrB,mBAAmB,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,GAAG,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;QAE3E,MAAM,gBAAgB,GAAG,OAAO;aAC7B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;aACxB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3B,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;QAErD,OAAO;YACL,eAAe;YACf,mBAAmB;YACnB,iBAAiB;YACjB,iBAAiB;YACjB,gBAAgB;SACjB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,UAAkB;QACtB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;CACF"}
@@ -0,0 +1,36 @@
1
+ export interface CostForecast {
2
+ readonly elapsedMs: number;
3
+ readonly spentUsd: number;
4
+ readonly rateUsdPerMs: number;
5
+ readonly forecastEndOfDayUsd: number | null;
6
+ readonly forecastEndOfWeekUsd: number | null;
7
+ readonly forecastSessionEndUsd: number | null;
8
+ readonly confidenceNote: string;
9
+ }
10
+ export interface CostForecastInputs {
11
+ /** Total spend during the live session, used for the session-end forecast. */
12
+ readonly sessionSpentUsd: number;
13
+ /** Wall-clock start of the current session. */
14
+ readonly sessionStartMs: number;
15
+ /**
16
+ * Optional daily anchor — when provided, the EoD forecast uses today's
17
+ * burn rate (`dailySpentUsd / (now - dailyFirstActivityMs)`) instead of
18
+ * the session-wide rate. This avoids two cross-midnight bugs:
19
+ * 1) Inflated EoD baseline (yesterday's portion of a still-running
20
+ * session counted as "today's spend so far").
21
+ * 2) Diluted burn rate (multi-day session averages busy hours with
22
+ * overnight idle hours, dragging the rate down).
23
+ * When omitted, falls back to the session rate over `msUntilEndOfDay`,
24
+ * which only matches reality when the session started today.
25
+ */
26
+ readonly dailySpentUsd?: number;
27
+ readonly dailyFirstActivityMs?: number | null;
28
+ }
29
+ /**
30
+ * Backward-compatible legacy entrypoint. Prefer `buildCostForecastFromInputs`
31
+ * so the EoD forecast can be anchored to today's spend rather than the full
32
+ * session.
33
+ */
34
+ export declare function buildCostForecast(spentUsd: number, sessionStartMs: number, nowMs?: number): CostForecast;
35
+ export declare function buildCostForecastFromInputs(inputs: CostForecastInputs, nowMs?: number): CostForecast;
36
+ //# sourceMappingURL=cost-forecast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-forecast.d.ts","sourceRoot":"","sources":["../../src/metrics/cost-forecast.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,MAAmB,GACzB,YAAY,CAEd;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,kBAAkB,EAC1B,KAAK,GAAE,MAAmB,GACzB,YAAY,CA0Fd"}
@@ -0,0 +1,91 @@
1
+ import { localStartOfDay } from '../lib/date.js';
2
+ /**
3
+ * Backward-compatible legacy entrypoint. Prefer `buildCostForecastFromInputs`
4
+ * so the EoD forecast can be anchored to today's spend rather than the full
5
+ * session.
6
+ */
7
+ export function buildCostForecast(spentUsd, sessionStartMs, nowMs = Date.now()) {
8
+ return buildCostForecastFromInputs({ sessionSpentUsd: spentUsd, sessionStartMs }, nowMs);
9
+ }
10
+ export function buildCostForecastFromInputs(inputs, nowMs = Date.now()) {
11
+ const { sessionSpentUsd, sessionStartMs, dailySpentUsd, dailyFirstActivityMs } = inputs;
12
+ const elapsedMs = nowMs - sessionStartMs;
13
+ if (elapsedMs < 1) {
14
+ return {
15
+ elapsedMs: 0,
16
+ spentUsd: 0,
17
+ rateUsdPerMs: 0,
18
+ forecastEndOfDayUsd: null,
19
+ forecastEndOfWeekUsd: null,
20
+ forecastSessionEndUsd: null,
21
+ confidenceNote: 'Insufficient data for forecast.',
22
+ };
23
+ }
24
+ // Session running but nothing spent yet — return zero forecasts so callers
25
+ // display $0.00 instead of "—".
26
+ if (sessionSpentUsd === 0) {
27
+ return {
28
+ elapsedMs,
29
+ spentUsd: 0,
30
+ rateUsdPerMs: 0,
31
+ forecastEndOfDayUsd: 0,
32
+ forecastEndOfWeekUsd: 0,
33
+ forecastSessionEndUsd: 0,
34
+ confidenceNote: 'Session running — no spend recorded yet.',
35
+ };
36
+ }
37
+ const sessionRateUsdPerMs = sessionSpentUsd / elapsedMs;
38
+ // End-of-day boundary in **local** time, matching the rest of the dashboard
39
+ // (lib/date.ts localStartOfDay). Previously this used UTC, which drifted
40
+ // a forecast across the day boundary for non-UTC users.
41
+ const dayStartMs = localStartOfDay(nowMs);
42
+ const dayEndMs = dayStartMs + 86_400_000;
43
+ const msUntilEndOfDay = Math.max(0, dayEndMs - nowMs);
44
+ // Daily-anchored EoD/EoW forecast when caller supplies today's spend +
45
+ // first-activity-of-day. Both the day and week projections use the same
46
+ // effective rate and base so they are internally consistent: the week
47
+ // forecast is simply the day forecast extended to the full remaining week.
48
+ // Falls back to session rate/base when the daily anchor is absent.
49
+ let effectiveRateUsdPerMs;
50
+ let effectiveBaseUsd;
51
+ if (typeof dailySpentUsd === 'number' &&
52
+ dailySpentUsd >= 0 &&
53
+ typeof dailyFirstActivityMs === 'number' &&
54
+ dailyFirstActivityMs > 0) {
55
+ const dailyElapsedMs = Math.max(1, nowMs - dailyFirstActivityMs);
56
+ effectiveRateUsdPerMs = dailySpentUsd / dailyElapsedMs;
57
+ effectiveBaseUsd = dailySpentUsd;
58
+ }
59
+ else {
60
+ effectiveRateUsdPerMs = sessionRateUsdPerMs;
61
+ effectiveBaseUsd = sessionSpentUsd;
62
+ }
63
+ const forecastEndOfDayUsd = effectiveBaseUsd + effectiveRateUsdPerMs * msUntilEndOfDay;
64
+ // ISO week ends on Sunday. Convert local getDay() (0=Sun…6=Sat) to ISO day (1=Mon…7=Sun)
65
+ // then compute remaining days: Sunday → 0 remaining, Monday → 6, …, Saturday → 1.
66
+ // Use getDay() (local) not getUTCDay() — the week boundary must match the local EoD boundary.
67
+ const now = new Date(nowMs);
68
+ const dayOfWeek = now.getDay();
69
+ const isoDay = dayOfWeek === 0 ? 7 : dayOfWeek;
70
+ const msUntilEndOfWeek = ((7 - isoDay) % 7) * 86_400_000 + msUntilEndOfDay;
71
+ const forecastEndOfWeekUsd = effectiveBaseUsd + effectiveRateUsdPerMs * msUntilEndOfWeek;
72
+ const SESSION_TARGET_MS = 8 * 60 * 60 * 1000;
73
+ const msUntilSessionEnd = Math.max(0, SESSION_TARGET_MS - elapsedMs);
74
+ const forecastSessionEndUsd = sessionSpentUsd + sessionRateUsdPerMs * msUntilSessionEnd;
75
+ const elapsedMinutes = elapsedMs / 60_000;
76
+ const confidenceNote = elapsedMinutes < 10
77
+ ? 'Low confidence — less than 10 minutes of data.'
78
+ : elapsedMinutes < 30
79
+ ? 'Moderate confidence — based on less than 30 minutes of data.'
80
+ : 'Reasonable confidence — based on 30+ minutes of data.';
81
+ return {
82
+ elapsedMs,
83
+ spentUsd: sessionSpentUsd,
84
+ rateUsdPerMs: sessionRateUsdPerMs,
85
+ forecastEndOfDayUsd,
86
+ forecastEndOfWeekUsd,
87
+ forecastSessionEndUsd,
88
+ confidenceNote,
89
+ };
90
+ }
91
+ //# sourceMappingURL=cost-forecast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-forecast.js","sourceRoot":"","sources":["../../src/metrics/cost-forecast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Cost-Per-Outcome Analysis — classifies AI coding tasks by outcome type,
3
+ * computes cost attribution per outcome category, and estimates ROI.
4
+ *
5
+ * Outcome types:
6
+ * - bug_fix: test failed → edit → test passed
7
+ * - feature: new files created via Write
8
+ * - refactor: existing files modified, no test regressions
9
+ * - investigation: mostly Read/Grep/Glob calls
10
+ * - configuration: only config file edits (.json, .yaml, etc.)
11
+ * - documentation: only .md file edits
12
+ * - failed_attempt: tests failed and never recovered
13
+ */
14
+ import type { MetricAggregator } from '../shared/index.js';
15
+ import type { AiCodingTask } from './task-detector.js';
16
+ export type OutcomeType = 'bug_fix' | 'feature' | 'refactor' | 'investigation' | 'configuration' | 'documentation' | 'failed_attempt';
17
+ export interface OutcomeDistribution {
18
+ [outcome: string]: {
19
+ count: number;
20
+ totalCost: number;
21
+ avgCost: number;
22
+ };
23
+ }
24
+ export interface CostAttribution {
25
+ readonly outcomeDistribution: OutcomeDistribution;
26
+ readonly costPerBugFix: number;
27
+ readonly costPerFeature: number;
28
+ readonly costPerRefactor: number;
29
+ readonly costPerInvestigation: number;
30
+ readonly costPerConfiguration: number;
31
+ readonly costPerDocumentation: number;
32
+ readonly costPerFailedAttempt: number;
33
+ readonly wasteRatio: number;
34
+ readonly totalCost: number;
35
+ readonly totalTasks: number;
36
+ }
37
+ export interface RoiEstimate {
38
+ readonly totalAiCost: number;
39
+ readonly estimatedHoursSaved: number;
40
+ readonly estimatedValueUsd: number;
41
+ readonly roi: number;
42
+ readonly byOutcome: Record<string, {
43
+ count: number;
44
+ hoursSaved: number;
45
+ valueUsd: number;
46
+ }>;
47
+ }
48
+ export interface TaskOutcomeEvent {
49
+ readonly outcome: OutcomeType;
50
+ readonly costUsd: number;
51
+ readonly toolCalls: number;
52
+ readonly durationMs: number;
53
+ readonly developer: string;
54
+ readonly sessionId: string;
55
+ }
56
+ export declare class CostPerOutcomeAnalyzer {
57
+ private readonly hoursSaved;
58
+ constructor(options?: {
59
+ hoursSaved?: Partial<Record<OutcomeType, number>>;
60
+ });
61
+ /**
62
+ * Classify a task by its outcome type using a priority-based rule set
63
+ * that inspects the tool call sequence.
64
+ */
65
+ classifyOutcome(task: AiCodingTask): OutcomeType;
66
+ /**
67
+ * Attribute costs across tasks by outcome category.
68
+ */
69
+ attributeCosts(tasks: AiCodingTask[]): CostAttribution;
70
+ /**
71
+ * Estimate ROI by multiplying task counts by hours-saved estimates
72
+ * and the developer's hourly cost.
73
+ */
74
+ estimateROI(attribution: CostAttribution, developerHourlyCost: number): RoiEstimate;
75
+ /**
76
+ * Emit outcome metrics to New Relic.
77
+ */
78
+ emitMetrics(aggregator: MetricAggregator, tasks: AiCodingTask[], developer: string): void;
79
+ }
80
+ /**
81
+ * Subset of FullSessionSummary fields needed to bucket a stored session into
82
+ * an outcome category. Used by the History view so we can render a
83
+ * cost-per-outcome breakdown across persisted sessions without retaining the
84
+ * raw per-task tool-call sequence on disk.
85
+ *
86
+ * The heuristic mirrors classifyOutcome's priority order but uses session
87
+ * aggregates: it cannot detect intra-session "test fail → edit → test pass"
88
+ * flow precisely, so a passing test with edits is treated as bug_fix.
89
+ */
90
+ export interface SessionOutcomeInputs {
91
+ readonly testRunCount: number;
92
+ readonly testPassCount: number;
93
+ readonly filesModified: readonly string[];
94
+ readonly toolBreakdown: Record<string, number>;
95
+ readonly toolCallCount: number;
96
+ }
97
+ export declare function classifySessionOutcome(s: SessionOutcomeInputs): OutcomeType;
98
+ export interface SessionLikeForCostOutcome extends SessionOutcomeInputs {
99
+ readonly estimatedCostUsd: number | null;
100
+ }
101
+ export declare function attributeSessionCosts(sessions: readonly SessionLikeForCostOutcome[]): CostAttribution;
102
+ //# sourceMappingURL=cost-per-outcome.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-per-outcome.d.ts","sourceRoot":"","sources":["../../src/metrics/cost-per-outcome.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Cost-Per-Outcome Analysis — classifies AI coding tasks by outcome type,
3
+ * computes cost attribution per outcome category, and estimates ROI.
4
+ *
5
+ * Outcome types:
6
+ * - bug_fix: test failed → edit → test passed
7
+ * - feature: new files created via Write
8
+ * - refactor: existing files modified, no test regressions
9
+ * - investigation: mostly Read/Grep/Glob calls
10
+ * - configuration: only config file edits (.json, .yaml, etc.)
11
+ * - documentation: only .md file edits
12
+ * - failed_attempt: tests failed and never recovered
13
+ */
14
+ import { createLogger } from '../shared/index.js';
15
+ const logger = createLogger('cost-per-outcome');
16
+ // ---------------------------------------------------------------------------
17
+ // Constants
18
+ // ---------------------------------------------------------------------------
19
+ const DEFAULT_HOURS_SAVED = {
20
+ bug_fix: 2,
21
+ feature: 4,
22
+ refactor: 1.5,
23
+ investigation: 0.5,
24
+ configuration: 0.5,
25
+ documentation: 1,
26
+ failed_attempt: 0,
27
+ };
28
+ const CONFIG_EXTENSIONS = /\.(json|yaml|yml|toml|env|ini)$/i;
29
+ const DOC_EXTENSIONS = /\.md$/i;
30
+ const READ_TOOLS = new Set(['Read', 'Grep', 'Glob']);
31
+ // ---------------------------------------------------------------------------
32
+ // CostPerOutcomeAnalyzer
33
+ // ---------------------------------------------------------------------------
34
+ export class CostPerOutcomeAnalyzer {
35
+ hoursSaved;
36
+ constructor(options) {
37
+ this.hoursSaved = { ...DEFAULT_HOURS_SAVED, ...options?.hoursSaved };
38
+ }
39
+ /**
40
+ * Classify a task by its outcome type using a priority-based rule set
41
+ * that inspects the tool call sequence.
42
+ */
43
+ classifyOutcome(task) {
44
+ const toolCalls = task.toolCalls;
45
+ let hasTestFailure = false;
46
+ let hasTestPassAfterEdit = false;
47
+ let hasWriteNewFile = false;
48
+ let sawEditAfterFailure = false;
49
+ for (const tc of toolCalls) {
50
+ const rec = tc;
51
+ if (rec.isTestCommand === true) {
52
+ if (tc.success === false) {
53
+ hasTestFailure = true;
54
+ }
55
+ else if (tc.success === true && hasTestFailure && sawEditAfterFailure) {
56
+ hasTestPassAfterEdit = true;
57
+ }
58
+ }
59
+ if ((tc.toolName === 'Edit' || tc.toolName === 'Write') && hasTestFailure) {
60
+ sawEditAfterFailure = true;
61
+ }
62
+ if (tc.toolName === 'Write') {
63
+ hasWriteNewFile = true;
64
+ }
65
+ }
66
+ // Priority 1: failed_attempt — tests failed and never recovered.
67
+ // Exclude tasks that also created new files; those are better classified
68
+ // as feature/refactor attempts that happen to have failing tests.
69
+ if (hasTestFailure && !hasTestPassAfterEdit && !hasWriteNewFile) {
70
+ return 'failed_attempt';
71
+ }
72
+ // Priority 2: bug_fix — test fail → edit → test pass
73
+ if (hasTestFailure && hasTestPassAfterEdit) {
74
+ return 'bug_fix';
75
+ }
76
+ // Priority 3: feature — new files created
77
+ if (hasWriteNewFile) {
78
+ return 'feature';
79
+ }
80
+ // Priority 4: configuration — only config files modified
81
+ const modifiedFiles = task.filesModified;
82
+ if (modifiedFiles.length > 0 && modifiedFiles.every((f) => CONFIG_EXTENSIONS.test(f))) {
83
+ return 'configuration';
84
+ }
85
+ // Priority 5: documentation — only .md files modified
86
+ if (modifiedFiles.length > 0 && modifiedFiles.every((f) => DOC_EXTENSIONS.test(f))) {
87
+ return 'documentation';
88
+ }
89
+ // Priority 6: refactor — files modified, no test regressions
90
+ if (modifiedFiles.length > 0) {
91
+ return 'refactor';
92
+ }
93
+ // Priority 7: investigation — mostly read/search tools
94
+ if (task.toolCallCount > 0) {
95
+ const readCount = toolCalls.filter((tc) => READ_TOOLS.has(tc.toolName)).length;
96
+ if (readCount / task.toolCallCount >= 0.8) {
97
+ return 'investigation';
98
+ }
99
+ }
100
+ // Default
101
+ return 'feature';
102
+ }
103
+ /**
104
+ * Attribute costs across tasks by outcome category.
105
+ */
106
+ attributeCosts(tasks) {
107
+ const distribution = {};
108
+ let totalCost = 0;
109
+ for (const task of tasks) {
110
+ const outcome = this.classifyOutcome(task);
111
+ const cost = task.estimatedCostUsd ?? 0;
112
+ totalCost += cost;
113
+ if (!distribution[outcome]) {
114
+ distribution[outcome] = { count: 0, totalCost: 0, avgCost: 0 };
115
+ }
116
+ distribution[outcome].count++;
117
+ distribution[outcome].totalCost += cost;
118
+ }
119
+ // Compute averages
120
+ for (const entry of Object.values(distribution)) {
121
+ entry.avgCost = entry.count > 0 ? round(entry.totalCost / entry.count, 4) : 0;
122
+ entry.totalCost = round(entry.totalCost, 4);
123
+ }
124
+ const avgCostFor = (outcome) => distribution[outcome]?.avgCost ?? 0;
125
+ const failedCost = distribution['failed_attempt']?.totalCost ?? 0;
126
+ const wasteRatio = totalCost > 0 ? round(failedCost / totalCost, 4) : 0;
127
+ return {
128
+ outcomeDistribution: distribution,
129
+ costPerBugFix: avgCostFor('bug_fix'),
130
+ costPerFeature: avgCostFor('feature'),
131
+ costPerRefactor: avgCostFor('refactor'),
132
+ costPerInvestigation: avgCostFor('investigation'),
133
+ costPerConfiguration: avgCostFor('configuration'),
134
+ costPerDocumentation: avgCostFor('documentation'),
135
+ costPerFailedAttempt: avgCostFor('failed_attempt'),
136
+ wasteRatio,
137
+ totalCost: round(totalCost, 4),
138
+ totalTasks: tasks.length,
139
+ };
140
+ }
141
+ /**
142
+ * Estimate ROI by multiplying task counts by hours-saved estimates
143
+ * and the developer's hourly cost.
144
+ */
145
+ estimateROI(attribution, developerHourlyCost) {
146
+ let totalHoursSaved = 0;
147
+ let totalValue = 0;
148
+ const byOutcome = {};
149
+ for (const [outcome, entry] of Object.entries(attribution.outcomeDistribution)) {
150
+ const hours = (this.hoursSaved[outcome] ?? 0) * entry.count;
151
+ const value = hours * developerHourlyCost;
152
+ totalHoursSaved += hours;
153
+ totalValue += value;
154
+ byOutcome[outcome] = {
155
+ count: entry.count,
156
+ hoursSaved: round(hours, 2),
157
+ valueUsd: round(value, 2),
158
+ };
159
+ }
160
+ const roi = round(totalValue - attribution.totalCost, 2);
161
+ return {
162
+ totalAiCost: attribution.totalCost,
163
+ estimatedHoursSaved: round(totalHoursSaved, 2),
164
+ estimatedValueUsd: round(totalValue, 2),
165
+ roi,
166
+ byOutcome,
167
+ };
168
+ }
169
+ /**
170
+ * Emit outcome metrics to New Relic.
171
+ */
172
+ emitMetrics(aggregator, tasks, developer) {
173
+ const attribution = this.attributeCosts(tasks);
174
+ // Per-task outcome events
175
+ for (const task of tasks) {
176
+ const outcome = this.classifyOutcome(task);
177
+ aggregator.record('ai.task.outcome', 1, {
178
+ developer,
179
+ outcome,
180
+ costUsd: task.estimatedCostUsd ?? 0,
181
+ toolCalls: task.toolCallCount,
182
+ });
183
+ }
184
+ // Per-category cost summaries
185
+ for (const [outcome, entry] of Object.entries(attribution.outcomeDistribution)) {
186
+ aggregator.record('ai.cost_per_outcome', entry.avgCost, {
187
+ developer,
188
+ outcome,
189
+ count: entry.count,
190
+ totalCost: entry.totalCost,
191
+ });
192
+ }
193
+ logger.debug('Cost-per-outcome metrics emitted', {
194
+ developer,
195
+ taskCount: tasks.length,
196
+ categories: Object.keys(attribution.outcomeDistribution).length,
197
+ });
198
+ }
199
+ }
200
+ export function classifySessionOutcome(s) {
201
+ if (s.testRunCount > 0 && s.testPassCount === 0)
202
+ return 'failed_attempt';
203
+ if (s.testRunCount > 0 && s.testPassCount > 0 && s.filesModified.length > 0)
204
+ return 'bug_fix';
205
+ const writeCount = s.toolBreakdown['Write'] ?? 0;
206
+ if (writeCount >= 1 && s.filesModified.length > 0)
207
+ return 'feature';
208
+ if (s.filesModified.length > 0 && s.filesModified.every((f) => CONFIG_EXTENSIONS.test(f))) {
209
+ return 'configuration';
210
+ }
211
+ if (s.filesModified.length > 0 && s.filesModified.every((f) => DOC_EXTENSIONS.test(f))) {
212
+ return 'documentation';
213
+ }
214
+ if (s.filesModified.length > 0)
215
+ return 'refactor';
216
+ if (s.toolCallCount > 0) {
217
+ const readCount = (s.toolBreakdown['Read'] ?? 0) +
218
+ (s.toolBreakdown['Grep'] ?? 0) +
219
+ (s.toolBreakdown['Glob'] ?? 0);
220
+ if (readCount / s.toolCallCount >= 0.8)
221
+ return 'investigation';
222
+ }
223
+ return 'feature';
224
+ }
225
+ export function attributeSessionCosts(sessions) {
226
+ const distribution = {};
227
+ let totalCost = 0;
228
+ for (const s of sessions) {
229
+ const outcome = classifySessionOutcome(s);
230
+ const cost = s.estimatedCostUsd ?? 0;
231
+ totalCost += cost;
232
+ if (!distribution[outcome]) {
233
+ distribution[outcome] = { count: 0, totalCost: 0, avgCost: 0 };
234
+ }
235
+ distribution[outcome].count++;
236
+ distribution[outcome].totalCost += cost;
237
+ }
238
+ for (const entry of Object.values(distribution)) {
239
+ entry.avgCost = entry.count > 0 ? round(entry.totalCost / entry.count, 4) : 0;
240
+ entry.totalCost = round(entry.totalCost, 4);
241
+ }
242
+ const avgCostFor = (outcome) => distribution[outcome]?.avgCost ?? 0;
243
+ const failedCost = distribution['failed_attempt']?.totalCost ?? 0;
244
+ const wasteRatio = totalCost > 0 ? round(failedCost / totalCost, 4) : 0;
245
+ return {
246
+ outcomeDistribution: distribution,
247
+ costPerBugFix: avgCostFor('bug_fix'),
248
+ costPerFeature: avgCostFor('feature'),
249
+ costPerRefactor: avgCostFor('refactor'),
250
+ costPerInvestigation: avgCostFor('investigation'),
251
+ costPerConfiguration: avgCostFor('configuration'),
252
+ costPerDocumentation: avgCostFor('documentation'),
253
+ costPerFailedAttempt: avgCostFor('failed_attempt'),
254
+ wasteRatio,
255
+ totalCost: round(totalCost, 4),
256
+ totalTasks: sessions.length,
257
+ };
258
+ }
259
+ // ---------------------------------------------------------------------------
260
+ // Helpers
261
+ // ---------------------------------------------------------------------------
262
+ function round(value, decimals) {
263
+ const factor = Math.pow(10, decimals);
264
+ return Math.round(value * factor) / factor;
265
+ }
266
+ //# sourceMappingURL=cost-per-outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-per-outcome.js","sourceRoot":"","sources":["../../src/metrics/cost-per-outcome.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Cost Tracking — maintains running token counts and cost calculations.
3
+ *
4
+ * Two paths feed into the tracker:
5
+ * 1. Self-reporting via the `nr_observe_report_tokens` MCP tool (primary)
6
+ * 2. Estimation from hook input/output byte sizes (fallback)
7
+ *
8
+ * Cost calculation delegates to `calculateCost()` from the shared package.
9
+ */
10
+ import type { TokenUsage, CostBreakdown, MetricAggregator } from '../shared/index.js';
11
+ import type { SessionTracker } from './session-tracker.js';
12
+ export interface CostMetrics {
13
+ sessionTotalCostUsd: number | null;
14
+ costByTask: null;
15
+ costByModel: Record<string, number>;
16
+ costPerLineOfCode: number | null;
17
+ costPerFileModified: number | null;
18
+ model: string | null;
19
+ totalInputTokens: number;
20
+ totalOutputTokens: number;
21
+ totalThinkingTokens: number;
22
+ totalCacheReadTokens: number;
23
+ totalCacheCreationTokens: number;
24
+ reportCount: number;
25
+ estimationCount: number;
26
+ latestCostBreakdown: CostBreakdown | null;
27
+ }
28
+ export declare class CostTracker {
29
+ private sessionTracker;
30
+ private totalCostUsd;
31
+ private totalInputTokens;
32
+ private totalOutputTokens;
33
+ private totalThinkingTokens;
34
+ private totalCacheReadTokens;
35
+ private totalCacheCreationTokens;
36
+ private currentModel;
37
+ private reportCount;
38
+ private estimationCount;
39
+ private latestCostBreakdown;
40
+ private costByModel;
41
+ private costByDayUsd;
42
+ private firstActivityMsByDay;
43
+ private totalLinesChanged;
44
+ constructor(sessionTracker?: SessionTracker);
45
+ /**
46
+ * Primary path: record exact token usage from self-reporting.
47
+ */
48
+ recordTokenUsage(usage: TokenUsage, model: string): CostBreakdown;
49
+ /**
50
+ * Fallback path: estimate tokens from character counts.
51
+ * Uses the heuristic: tokens ≈ characters / 4.
52
+ */
53
+ recordEstimatedTokens(inputChars: number, outputChars: number, model: string): CostBreakdown;
54
+ private accumulateTokens;
55
+ /**
56
+ * Cost spent during a specific local-time day, attributed at the moment
57
+ * each token event was recorded. Used to fix the cross-midnight inflation
58
+ * of "Today Spend" — when a session that started yesterday continues into
59
+ * today, this returns only today's portion.
60
+ */
61
+ getCostForDay(dayKey: string): number;
62
+ /**
63
+ * Epoch ms of the first token event recorded today (local time), or null
64
+ * if no spend has been booked today. The forecast burn-rate denominator
65
+ * should be (now - firstActivityToday), not (now - sessionStart) — the
66
+ * latter dilutes the rate with idle hours from previous days when a
67
+ * session spans midnight.
68
+ */
69
+ getFirstActivityMsForDay(dayKey: string): number | null;
70
+ /**
71
+ * Record lines of code changed (from Edit/Write tool data).
72
+ */
73
+ recordLinesChanged(lines: number): void;
74
+ getMetrics(): CostMetrics;
75
+ emitMetrics(aggregator: MetricAggregator): void;
76
+ reset(): void;
77
+ }
78
+ //# sourceMappingURL=cost-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tracker.d.ts","sourceRoot":"","sources":["../../src/metrics/cost-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D,MAAM,WAAW,WAAW;IAC1B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,IAAI,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wBAAwB,EAAE,MAAM,CAAC;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,aAAa,GAAG,IAAI,CAAC;CAC3C;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,cAAc,CAAwB;IAE9C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,mBAAmB,CAA8B;IACzD,OAAO,CAAC,WAAW,CAA6B;IAMhD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,oBAAoB,CAA6B;IACzD,OAAO,CAAC,iBAAiB,CAAK;gBAElB,cAAc,CAAC,EAAE,cAAc;IAI3C;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa;IAKjE;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa;IAgB5F,OAAO,CAAC,gBAAgB;IAuBxB;;;;;OAKG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIrC;;;;;;OAMG;IACH,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvD;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,UAAU,IAAI,WAAW;IA2BzB,WAAW,CAAC,UAAU,EAAE,gBAAgB,GAAG,IAAI;IAmC/C,KAAK,IAAI,IAAI;CAgBd"}