@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.
- package/LICENSE +183 -0
- package/README.md +498 -0
- package/dist/alerts/alert-log.d.ts +24 -0
- package/dist/alerts/alert-log.d.ts.map +1 -0
- package/dist/alerts/alert-log.js +159 -0
- package/dist/alerts/alert-log.js.map +1 -0
- package/dist/alerts/alert-snapshot-collector.d.ts +168 -0
- package/dist/alerts/alert-snapshot-collector.d.ts.map +1 -0
- package/dist/alerts/alert-snapshot-collector.js +243 -0
- package/dist/alerts/alert-snapshot-collector.js.map +1 -0
- package/dist/alerts/local-alert-engine.d.ts +86 -0
- package/dist/alerts/local-alert-engine.d.ts.map +1 -0
- package/dist/alerts/local-alert-engine.js +466 -0
- package/dist/alerts/local-alert-engine.js.map +1 -0
- package/dist/alerts/local-alert-rule.d.ts +439 -0
- package/dist/alerts/local-alert-rule.d.ts.map +1 -0
- package/dist/alerts/local-alert-rule.js +139 -0
- package/dist/alerts/local-alert-rule.js.map +1 -0
- package/dist/alerts/os-notifier.d.ts +39 -0
- package/dist/alerts/os-notifier.d.ts.map +1 -0
- package/dist/alerts/os-notifier.js +170 -0
- package/dist/alerts/os-notifier.js.map +1 -0
- package/dist/alerts/types.d.ts +35 -0
- package/dist/alerts/types.d.ts.map +1 -0
- package/dist/alerts/types.js +8 -0
- package/dist/alerts/types.js.map +1 -0
- package/dist/config.d.ts +169 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +860 -0
- package/dist/config.js.map +1 -0
- package/dist/dashboard/dashboard-server.d.ts +38 -0
- package/dist/dashboard/dashboard-server.d.ts.map +1 -0
- package/dist/dashboard/dashboard-server.js +207 -0
- package/dist/dashboard/dashboard-server.js.map +1 -0
- package/dist/dashboard/index.d.ts +3 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +2 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/live-event-bus.d.ts +99 -0
- package/dist/dashboard/live-event-bus.d.ts.map +1 -0
- package/dist/dashboard/live-event-bus.js +56 -0
- package/dist/dashboard/live-event-bus.js.map +1 -0
- package/dist/dashboard/routes/api-handler.d.ts +122 -0
- package/dist/dashboard/routes/api-handler.d.ts.map +1 -0
- package/dist/dashboard/routes/api-handler.js +1414 -0
- package/dist/dashboard/routes/api-handler.js.map +1 -0
- package/dist/dashboard/routes/replay-analyzer.d.ts +15 -0
- package/dist/dashboard/routes/replay-analyzer.d.ts.map +1 -0
- package/dist/dashboard/routes/replay-analyzer.js +227 -0
- package/dist/dashboard/routes/replay-analyzer.js.map +1 -0
- package/dist/dashboard/routes/sse-handler.d.ts +4 -0
- package/dist/dashboard/routes/sse-handler.d.ts.map +1 -0
- package/dist/dashboard/routes/sse-handler.js +122 -0
- package/dist/dashboard/routes/sse-handler.js.map +1 -0
- package/dist/dashboard/routes/static-handler.d.ts +3 -0
- package/dist/dashboard/routes/static-handler.d.ts.map +1 -0
- package/dist/dashboard/routes/static-handler.js +103 -0
- package/dist/dashboard/routes/static-handler.js.map +1 -0
- package/dist/data/alerts/conditions/01-daily-cost-spike.json +16 -0
- package/dist/data/alerts/conditions/02-low-efficiency-score.json +16 -0
- package/dist/data/alerts/conditions/03-stuck-loop-rate.json +16 -0
- package/dist/data/alerts/conditions/04-anti-pattern-rate.json +16 -0
- package/dist/data/alerts/conditions/05-session-cost-budget.json +16 -0
- package/dist/data/alerts/conditions-personal/01-personal-daily-cost.json +16 -0
- package/dist/data/alerts/conditions-personal/02-personal-session-cost.json +16 -0
- package/dist/data/alerts/conditions-personal/03-personal-low-efficiency.json +16 -0
- package/dist/data/alerts/conditions-personal/04-personal-anti-pattern-rate.json +16 -0
- package/dist/data/alerts/conditions-personal/05-personal-stuck-loop.json +16 -0
- package/dist/data/alerts/policy.json +4 -0
- package/dist/data/dashboards/ai-coding-assistant-manager-view.json +103 -0
- package/dist/data/dashboards/ai-coding-assistant-overview.json +239 -0
- package/dist/data/dashboards/ai-coding-assistant-personal.json +442 -0
- package/dist/data/dashboards/ai-coding-assistant-platform-comparison.json +320 -0
- package/dist/data/dashboards/ai-coding-assistant-security.json +275 -0
- package/dist/data/dashboards/ai-coding-assistant-session-detail.json +296 -0
- package/dist/data/dashboards/ai-coding-assistant-team-view.json +345 -0
- package/dist/deploy/data-paths.d.ts +22 -0
- package/dist/deploy/data-paths.d.ts.map +1 -0
- package/dist/deploy/data-paths.js +69 -0
- package/dist/deploy/data-paths.js.map +1 -0
- package/dist/deploy/deploy-alerts.d.ts +58 -0
- package/dist/deploy/deploy-alerts.d.ts.map +1 -0
- package/dist/deploy/deploy-alerts.js +371 -0
- package/dist/deploy/deploy-alerts.js.map +1 -0
- package/dist/deploy/deploy-dashboards.d.ts +92 -0
- package/dist/deploy/deploy-dashboards.d.ts.map +1 -0
- package/dist/deploy/deploy-dashboards.js +282 -0
- package/dist/deploy/deploy-dashboards.js.map +1 -0
- package/dist/digest/digest-formatter.d.ts +3 -0
- package/dist/digest/digest-formatter.d.ts.map +1 -0
- package/dist/digest/digest-formatter.js +37 -0
- package/dist/digest/digest-formatter.js.map +1 -0
- package/dist/digest/digest-sender.d.ts +2 -0
- package/dist/digest/digest-sender.d.ts.map +1 -0
- package/dist/digest/digest-sender.js +29 -0
- package/dist/digest/digest-sender.js.map +1 -0
- package/dist/hooks/bash-classifier.d.ts +26 -0
- package/dist/hooks/bash-classifier.d.ts.map +1 -0
- package/dist/hooks/bash-classifier.js +409 -0
- package/dist/hooks/bash-classifier.js.map +1 -0
- package/dist/hooks/collector-script.d.ts +47 -0
- package/dist/hooks/collector-script.d.ts.map +1 -0
- package/dist/hooks/collector-script.js +662 -0
- package/dist/hooks/collector-script.js.map +1 -0
- package/dist/hooks/event-processor.d.ts +65 -0
- package/dist/hooks/event-processor.d.ts.map +1 -0
- package/dist/hooks/event-processor.js +342 -0
- package/dist/hooks/event-processor.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/session-resolver.d.ts +66 -0
- package/dist/hooks/session-resolver.d.ts.map +1 -0
- package/dist/hooks/session-resolver.js +196 -0
- package/dist/hooks/session-resolver.js.map +1 -0
- package/dist/hooks/tool-parsers.d.ts +19 -0
- package/dist/hooks/tool-parsers.d.ts.map +1 -0
- package/dist/hooks/tool-parsers.js +260 -0
- package/dist/hooks/tool-parsers.js.map +1 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1505 -0
- package/dist/index.js.map +1 -0
- package/dist/install/cli.d.ts +11 -0
- package/dist/install/cli.d.ts.map +1 -0
- package/dist/install/cli.js +365 -0
- package/dist/install/cli.js.map +1 -0
- package/dist/install/index.d.ts +4 -0
- package/dist/install/index.d.ts.map +1 -0
- package/dist/install/index.js +3 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/install-helper.d.ts +35 -0
- package/dist/install/install-helper.d.ts.map +1 -0
- package/dist/install/install-helper.js +227 -0
- package/dist/install/install-helper.js.map +1 -0
- package/dist/install/key-validator.d.ts +19 -0
- package/dist/install/key-validator.d.ts.map +1 -0
- package/dist/install/key-validator.js +122 -0
- package/dist/install/key-validator.js.map +1 -0
- package/dist/install/migrate.d.ts +12 -0
- package/dist/install/migrate.d.ts.map +1 -0
- package/dist/install/migrate.js +115 -0
- package/dist/install/migrate.js.map +1 -0
- package/dist/install/schedule.d.ts +11 -0
- package/dist/install/schedule.d.ts.map +1 -0
- package/dist/install/schedule.js +114 -0
- package/dist/install/schedule.js.map +1 -0
- package/dist/install/setup-wizard.d.ts +40 -0
- package/dist/install/setup-wizard.d.ts.map +1 -0
- package/dist/install/setup-wizard.js +489 -0
- package/dist/install/setup-wizard.js.map +1 -0
- package/dist/lib/date.d.ts +54 -0
- package/dist/lib/date.d.ts.map +1 -0
- package/dist/lib/date.js +85 -0
- package/dist/lib/date.js.map +1 -0
- package/dist/metrics/anti-patterns.d.ts +62 -0
- package/dist/metrics/anti-patterns.d.ts.map +1 -0
- package/dist/metrics/anti-patterns.js +301 -0
- package/dist/metrics/anti-patterns.js.map +1 -0
- package/dist/metrics/api-failure-tracker.d.ts +82 -0
- package/dist/metrics/api-failure-tracker.d.ts.map +1 -0
- package/dist/metrics/api-failure-tracker.js +202 -0
- package/dist/metrics/api-failure-tracker.js.map +1 -0
- package/dist/metrics/budget-tracker.d.ts +60 -0
- package/dist/metrics/budget-tracker.d.ts.map +1 -0
- package/dist/metrics/budget-tracker.js +130 -0
- package/dist/metrics/budget-tracker.js.map +1 -0
- package/dist/metrics/claudemd-tracker.d.ts +108 -0
- package/dist/metrics/claudemd-tracker.d.ts.map +1 -0
- package/dist/metrics/claudemd-tracker.js +337 -0
- package/dist/metrics/claudemd-tracker.js.map +1 -0
- package/dist/metrics/collaboration-profile.d.ts +65 -0
- package/dist/metrics/collaboration-profile.d.ts.map +1 -0
- package/dist/metrics/collaboration-profile.js +231 -0
- package/dist/metrics/collaboration-profile.js.map +1 -0
- package/dist/metrics/context-composition-tracker.d.ts +74 -0
- package/dist/metrics/context-composition-tracker.d.ts.map +1 -0
- package/dist/metrics/context-composition-tracker.js +202 -0
- package/dist/metrics/context-composition-tracker.js.map +1 -0
- package/dist/metrics/context-tracker.d.ts +78 -0
- package/dist/metrics/context-tracker.d.ts.map +1 -0
- package/dist/metrics/context-tracker.js +222 -0
- package/dist/metrics/context-tracker.js.map +1 -0
- package/dist/metrics/context-window-tracker.d.ts +18 -0
- package/dist/metrics/context-window-tracker.d.ts.map +1 -0
- package/dist/metrics/context-window-tracker.js +35 -0
- package/dist/metrics/context-window-tracker.js.map +1 -0
- package/dist/metrics/cost-forecast.d.ts +36 -0
- package/dist/metrics/cost-forecast.d.ts.map +1 -0
- package/dist/metrics/cost-forecast.js +91 -0
- package/dist/metrics/cost-forecast.js.map +1 -0
- package/dist/metrics/cost-per-outcome.d.ts +102 -0
- package/dist/metrics/cost-per-outcome.d.ts.map +1 -0
- package/dist/metrics/cost-per-outcome.js +266 -0
- package/dist/metrics/cost-per-outcome.js.map +1 -0
- package/dist/metrics/cost-tracker.d.ts +78 -0
- package/dist/metrics/cost-tracker.d.ts.map +1 -0
- package/dist/metrics/cost-tracker.js +169 -0
- package/dist/metrics/cost-tracker.js.map +1 -0
- package/dist/metrics/decision-tracker.d.ts +49 -0
- package/dist/metrics/decision-tracker.d.ts.map +1 -0
- package/dist/metrics/decision-tracker.js +161 -0
- package/dist/metrics/decision-tracker.js.map +1 -0
- package/dist/metrics/efficiency-score.d.ts +80 -0
- package/dist/metrics/efficiency-score.d.ts.map +1 -0
- package/dist/metrics/efficiency-score.js +219 -0
- package/dist/metrics/efficiency-score.js.map +1 -0
- package/dist/metrics/git-efficiency-tracker.d.ts +165 -0
- package/dist/metrics/git-efficiency-tracker.d.ts.map +1 -0
- package/dist/metrics/git-efficiency-tracker.js +1056 -0
- package/dist/metrics/git-efficiency-tracker.js.map +1 -0
- package/dist/metrics/index.d.ts +26 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +14 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/instruction-drift-tracker.d.ts +69 -0
- package/dist/metrics/instruction-drift-tracker.d.ts.map +1 -0
- package/dist/metrics/instruction-drift-tracker.js +213 -0
- package/dist/metrics/instruction-drift-tracker.js.map +1 -0
- package/dist/metrics/latency-decomposition.d.ts +50 -0
- package/dist/metrics/latency-decomposition.d.ts.map +1 -0
- package/dist/metrics/latency-decomposition.js +112 -0
- package/dist/metrics/latency-decomposition.js.map +1 -0
- package/dist/metrics/latency-tracker.d.ts +33 -0
- package/dist/metrics/latency-tracker.d.ts.map +1 -0
- package/dist/metrics/latency-tracker.js +93 -0
- package/dist/metrics/latency-tracker.js.map +1 -0
- package/dist/metrics/live-session-registry.d.ts +29 -0
- package/dist/metrics/live-session-registry.d.ts.map +1 -0
- package/dist/metrics/live-session-registry.js +103 -0
- package/dist/metrics/live-session-registry.js.map +1 -0
- package/dist/metrics/model-usage-tracker.d.ts +21 -0
- package/dist/metrics/model-usage-tracker.d.ts.map +1 -0
- package/dist/metrics/model-usage-tracker.js +53 -0
- package/dist/metrics/model-usage-tracker.js.map +1 -0
- package/dist/metrics/percentile.d.ts +5 -0
- package/dist/metrics/percentile.d.ts.map +1 -0
- package/dist/metrics/percentile.js +10 -0
- package/dist/metrics/percentile.js.map +1 -0
- package/dist/metrics/personal-coach.d.ts +47 -0
- package/dist/metrics/personal-coach.d.ts.map +1 -0
- package/dist/metrics/personal-coach.js +241 -0
- package/dist/metrics/personal-coach.js.map +1 -0
- package/dist/metrics/prompt-feedback.d.ts +75 -0
- package/dist/metrics/prompt-feedback.d.ts.map +1 -0
- package/dist/metrics/prompt-feedback.js +286 -0
- package/dist/metrics/prompt-feedback.js.map +1 -0
- package/dist/metrics/proxy-metrics.d.ts +54 -0
- package/dist/metrics/proxy-metrics.d.ts.map +1 -0
- package/dist/metrics/proxy-metrics.js +228 -0
- package/dist/metrics/proxy-metrics.js.map +1 -0
- package/dist/metrics/quality-proxy-tracker.d.ts +51 -0
- package/dist/metrics/quality-proxy-tracker.d.ts.map +1 -0
- package/dist/metrics/quality-proxy-tracker.js +162 -0
- package/dist/metrics/quality-proxy-tracker.js.map +1 -0
- package/dist/metrics/recommendation-engine.d.ts +72 -0
- package/dist/metrics/recommendation-engine.d.ts.map +1 -0
- package/dist/metrics/recommendation-engine.js +207 -0
- package/dist/metrics/recommendation-engine.js.map +1 -0
- package/dist/metrics/retry-detector.d.ts +43 -0
- package/dist/metrics/retry-detector.d.ts.map +1 -0
- package/dist/metrics/retry-detector.js +179 -0
- package/dist/metrics/retry-detector.js.map +1 -0
- package/dist/metrics/session-tracker.d.ts +75 -0
- package/dist/metrics/session-tracker.d.ts.map +1 -0
- package/dist/metrics/session-tracker.js +249 -0
- package/dist/metrics/session-tracker.js.map +1 -0
- package/dist/metrics/task-completion-tracker.d.ts +15 -0
- package/dist/metrics/task-completion-tracker.d.ts.map +1 -0
- package/dist/metrics/task-completion-tracker.js +27 -0
- package/dist/metrics/task-completion-tracker.js.map +1 -0
- package/dist/metrics/task-detector.d.ts +84 -0
- package/dist/metrics/task-detector.d.ts.map +1 -0
- package/dist/metrics/task-detector.js +302 -0
- package/dist/metrics/task-detector.js.map +1 -0
- package/dist/metrics/tool-selection-scorer.d.ts +39 -0
- package/dist/metrics/tool-selection-scorer.d.ts.map +1 -0
- package/dist/metrics/tool-selection-scorer.js +193 -0
- package/dist/metrics/tool-selection-scorer.js.map +1 -0
- package/dist/metrics/trend-analyzer.d.ts +92 -0
- package/dist/metrics/trend-analyzer.d.ts.map +1 -0
- package/dist/metrics/trend-analyzer.js +293 -0
- package/dist/metrics/trend-analyzer.js.map +1 -0
- package/dist/metrics/turn-cost-attributor.d.ts +41 -0
- package/dist/metrics/turn-cost-attributor.d.ts.map +1 -0
- package/dist/metrics/turn-cost-attributor.js +118 -0
- package/dist/metrics/turn-cost-attributor.js.map +1 -0
- package/dist/metrics/turn-tracker.d.ts +49 -0
- package/dist/metrics/turn-tracker.d.ts.map +1 -0
- package/dist/metrics/turn-tracker.js +192 -0
- package/dist/metrics/turn-tracker.js.map +1 -0
- package/dist/platforms/amazon-q-adapter.d.ts +10 -0
- package/dist/platforms/amazon-q-adapter.d.ts.map +1 -0
- package/dist/platforms/amazon-q-adapter.js +75 -0
- package/dist/platforms/amazon-q-adapter.js.map +1 -0
- package/dist/platforms/claude-code-adapter.d.ts +10 -0
- package/dist/platforms/claude-code-adapter.d.ts.map +1 -0
- package/dist/platforms/claude-code-adapter.js +48 -0
- package/dist/platforms/claude-code-adapter.js.map +1 -0
- package/dist/platforms/continue-adapter.d.ts +10 -0
- package/dist/platforms/continue-adapter.d.ts.map +1 -0
- package/dist/platforms/continue-adapter.js +73 -0
- package/dist/platforms/continue-adapter.js.map +1 -0
- package/dist/platforms/copilot-adapter.d.ts +37 -0
- package/dist/platforms/copilot-adapter.d.ts.map +1 -0
- package/dist/platforms/copilot-adapter.js +66 -0
- package/dist/platforms/copilot-adapter.js.map +1 -0
- package/dist/platforms/cursor-adapter.d.ts +10 -0
- package/dist/platforms/cursor-adapter.d.ts.map +1 -0
- package/dist/platforms/cursor-adapter.js +60 -0
- package/dist/platforms/cursor-adapter.js.map +1 -0
- package/dist/platforms/generic-mcp-adapter.d.ts +113 -0
- package/dist/platforms/generic-mcp-adapter.d.ts.map +1 -0
- package/dist/platforms/generic-mcp-adapter.js +139 -0
- package/dist/platforms/generic-mcp-adapter.js.map +1 -0
- package/dist/platforms/index.d.ts +15 -0
- package/dist/platforms/index.d.ts.map +1 -0
- package/dist/platforms/index.js +12 -0
- package/dist/platforms/index.js.map +1 -0
- package/dist/platforms/platform-registry.d.ts +11 -0
- package/dist/platforms/platform-registry.d.ts.map +1 -0
- package/dist/platforms/platform-registry.js +54 -0
- package/dist/platforms/platform-registry.js.map +1 -0
- package/dist/platforms/types.d.ts +36 -0
- package/dist/platforms/types.d.ts.map +1 -0
- package/dist/platforms/types.js +2 -0
- package/dist/platforms/types.js.map +1 -0
- package/dist/platforms/windsurf-adapter.d.ts +10 -0
- package/dist/platforms/windsurf-adapter.d.ts.map +1 -0
- package/dist/platforms/windsurf-adapter.js +63 -0
- package/dist/platforms/windsurf-adapter.js.map +1 -0
- package/dist/platforms/zed-adapter.d.ts +10 -0
- package/dist/platforms/zed-adapter.d.ts.map +1 -0
- package/dist/platforms/zed-adapter.js +72 -0
- package/dist/platforms/zed-adapter.js.map +1 -0
- package/dist/proxy/index.d.ts +7 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/index.js +5 -0
- package/dist/proxy/index.js.map +1 -0
- package/dist/proxy/otlp-receiver.d.ts +28 -0
- package/dist/proxy/otlp-receiver.d.ts.map +1 -0
- package/dist/proxy/otlp-receiver.js +319 -0
- package/dist/proxy/otlp-receiver.js.map +1 -0
- package/dist/proxy/proxy-manager.d.ts +47 -0
- package/dist/proxy/proxy-manager.d.ts.map +1 -0
- package/dist/proxy/proxy-manager.js +338 -0
- package/dist/proxy/proxy-manager.js.map +1 -0
- package/dist/proxy/types.d.ts +72 -0
- package/dist/proxy/types.d.ts.map +1 -0
- package/dist/proxy/types.js +33 -0
- package/dist/proxy/types.js.map +1 -0
- package/dist/proxy/upstream-http.d.ts +26 -0
- package/dist/proxy/upstream-http.d.ts.map +1 -0
- package/dist/proxy/upstream-http.js +209 -0
- package/dist/proxy/upstream-http.js.map +1 -0
- package/dist/proxy/upstream-stdio.d.ts +25 -0
- package/dist/proxy/upstream-stdio.d.ts.map +1 -0
- package/dist/proxy/upstream-stdio.js +256 -0
- package/dist/proxy/upstream-stdio.js.map +1 -0
- package/dist/security/audit-trail.d.ts +74 -0
- package/dist/security/audit-trail.d.ts.map +1 -0
- package/dist/security/audit-trail.js +338 -0
- package/dist/security/audit-trail.js.map +1 -0
- package/dist/security/index.d.ts +5 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +4 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/ssrf.d.ts +2 -0
- package/dist/security/ssrf.d.ts.map +1 -0
- package/dist/security/ssrf.js +126 -0
- package/dist/security/ssrf.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +117 -0
- package/dist/server.js.map +1 -0
- package/dist/shared/__test-utils__/log-output.d.ts +49 -0
- package/dist/shared/__test-utils__/log-output.d.ts.map +1 -0
- package/dist/shared/__test-utils__/log-output.js +38 -0
- package/dist/shared/__test-utils__/log-output.js.map +1 -0
- package/dist/shared/config.d.ts +56 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +290 -0
- package/dist/shared/config.js.map +1 -0
- package/dist/shared/errors.d.ts +139 -0
- package/dist/shared/errors.d.ts.map +1 -0
- package/dist/shared/errors.js +406 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/events/factory.d.ts +143 -0
- package/dist/shared/events/factory.d.ts.map +1 -0
- package/dist/shared/events/factory.js +351 -0
- package/dist/shared/events/factory.js.map +1 -0
- package/dist/shared/events/index.d.ts +6 -0
- package/dist/shared/events/index.d.ts.map +1 -0
- package/dist/shared/events/index.js +3 -0
- package/dist/shared/events/index.js.map +1 -0
- package/dist/shared/events/serialize.d.ts +87 -0
- package/dist/shared/events/serialize.d.ts.map +1 -0
- package/dist/shared/events/serialize.js +510 -0
- package/dist/shared/events/serialize.js.map +1 -0
- package/dist/shared/events/types.d.ts +139 -0
- package/dist/shared/events/types.d.ts.map +1 -0
- package/dist/shared/events/types.js +2 -0
- package/dist/shared/events/types.js.map +1 -0
- package/dist/shared/harvest/event-buffer.d.ts +59 -0
- package/dist/shared/harvest/event-buffer.d.ts.map +1 -0
- package/dist/shared/harvest/event-buffer.js +100 -0
- package/dist/shared/harvest/event-buffer.js.map +1 -0
- package/dist/shared/harvest/harvest-scheduler.d.ts +200 -0
- package/dist/shared/harvest/harvest-scheduler.d.ts.map +1 -0
- package/dist/shared/harvest/harvest-scheduler.js +647 -0
- package/dist/shared/harvest/harvest-scheduler.js.map +1 -0
- package/dist/shared/harvest/index.d.ts +7 -0
- package/dist/shared/harvest/index.d.ts.map +1 -0
- package/dist/shared/harvest/index.js +4 -0
- package/dist/shared/harvest/index.js.map +1 -0
- package/dist/shared/harvest/metric-aggregator.d.ts +115 -0
- package/dist/shared/harvest/metric-aggregator.d.ts.map +1 -0
- package/dist/shared/harvest/metric-aggregator.js +247 -0
- package/dist/shared/harvest/metric-aggregator.js.map +1 -0
- package/dist/shared/index.d.ts +22 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +13 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/logger.d.ts +57 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +166 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/pricing-data.d.ts +4 -0
- package/dist/shared/pricing-data.d.ts.map +1 -0
- package/dist/shared/pricing-data.js +473 -0
- package/dist/shared/pricing-data.js.map +1 -0
- package/dist/shared/pricing.d.ts +148 -0
- package/dist/shared/pricing.d.ts.map +1 -0
- package/dist/shared/pricing.js +528 -0
- package/dist/shared/pricing.js.map +1 -0
- package/dist/shared/redact.d.ts +33 -0
- package/dist/shared/redact.d.ts.map +1 -0
- package/dist/shared/redact.js +110 -0
- package/dist/shared/redact.js.map +1 -0
- package/dist/shared/timing.d.ts +96 -0
- package/dist/shared/timing.d.ts.map +1 -0
- package/dist/shared/timing.js +173 -0
- package/dist/shared/timing.js.map +1 -0
- package/dist/shared/tokens.d.ts +145 -0
- package/dist/shared/tokens.d.ts.map +1 -0
- package/dist/shared/tokens.js +492 -0
- package/dist/shared/tokens.js.map +1 -0
- package/dist/shared/transport/events-api.d.ts +14 -0
- package/dist/shared/transport/events-api.d.ts.map +1 -0
- package/dist/shared/transport/events-api.js +29 -0
- package/dist/shared/transport/events-api.js.map +1 -0
- package/dist/shared/transport/http-client.d.ts +49 -0
- package/dist/shared/transport/http-client.d.ts.map +1 -0
- package/dist/shared/transport/http-client.js +381 -0
- package/dist/shared/transport/http-client.js.map +1 -0
- package/dist/shared/transport/index.d.ts +10 -0
- package/dist/shared/transport/index.d.ts.map +1 -0
- package/dist/shared/transport/index.js +6 -0
- package/dist/shared/transport/index.js.map +1 -0
- package/dist/shared/transport/logs-api.d.ts +29 -0
- package/dist/shared/transport/logs-api.d.ts.map +1 -0
- package/dist/shared/transport/logs-api.js +40 -0
- package/dist/shared/transport/logs-api.js.map +1 -0
- package/dist/shared/transport/metric-api.d.ts +9 -0
- package/dist/shared/transport/metric-api.d.ts.map +1 -0
- package/dist/shared/transport/metric-api.js +39 -0
- package/dist/shared/transport/metric-api.js.map +1 -0
- package/dist/shared/transport/otlp-event-bridge.d.ts +22 -0
- package/dist/shared/transport/otlp-event-bridge.d.ts.map +1 -0
- package/dist/shared/transport/otlp-event-bridge.js +50 -0
- package/dist/shared/transport/otlp-event-bridge.js.map +1 -0
- package/dist/shared/transport/otlp-shared.d.ts +14 -0
- package/dist/shared/transport/otlp-shared.d.ts.map +1 -0
- package/dist/shared/transport/otlp-shared.js +49 -0
- package/dist/shared/transport/otlp-shared.js.map +1 -0
- package/dist/shared/transport/otlp-transport.d.ts +58 -0
- package/dist/shared/transport/otlp-transport.d.ts.map +1 -0
- package/dist/shared/transport/otlp-transport.js +236 -0
- package/dist/shared/transport/otlp-transport.js.map +1 -0
- package/dist/shared/transport/types.d.ts +129 -0
- package/dist/shared/transport/types.d.ts.map +1 -0
- package/dist/shared/transport/types.js +2 -0
- package/dist/shared/transport/types.js.map +1 -0
- package/dist/shared/version.d.ts +2 -0
- package/dist/shared/version.d.ts.map +1 -0
- package/dist/shared/version.js +2 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +4 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local-store.d.ts +153 -0
- package/dist/storage/local-store.d.ts.map +1 -0
- package/dist/storage/local-store.js +719 -0
- package/dist/storage/local-store.js.map +1 -0
- package/dist/storage/retention.d.ts +2 -0
- package/dist/storage/retention.d.ts.map +1 -0
- package/dist/storage/retention.js +53 -0
- package/dist/storage/retention.js.map +1 -0
- package/dist/storage/session-store.d.ts +97 -0
- package/dist/storage/session-store.d.ts.map +1 -0
- package/dist/storage/session-store.js +391 -0
- package/dist/storage/session-store.js.map +1 -0
- package/dist/storage/types.d.ts +64 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/weekly-summary.d.ts +61 -0
- package/dist/storage/weekly-summary.d.ts.map +1 -0
- package/dist/storage/weekly-summary.js +243 -0
- package/dist/storage/weekly-summary.js.map +1 -0
- package/dist/tools/analytics-tools.d.ts +101 -0
- package/dist/tools/analytics-tools.d.ts.map +1 -0
- package/dist/tools/analytics-tools.js +71 -0
- package/dist/tools/analytics-tools.js.map +1 -0
- package/dist/tools/cost-tools.d.ts +121 -0
- package/dist/tools/cost-tools.d.ts.map +1 -0
- package/dist/tools/cost-tools.js +174 -0
- package/dist/tools/cost-tools.js.map +1 -0
- package/dist/tools/cross-session-tools.d.ts +376 -0
- package/dist/tools/cross-session-tools.d.ts.map +1 -0
- package/dist/tools/cross-session-tools.js +820 -0
- package/dist/tools/cross-session-tools.js.map +1 -0
- package/dist/tools/extended-analytics-tools.d.ts +164 -0
- package/dist/tools/extended-analytics-tools.d.ts.map +1 -0
- package/dist/tools/extended-analytics-tools.js +121 -0
- package/dist/tools/extended-analytics-tools.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/session-stats.d.ts +162 -0
- package/dist/tools/session-stats.d.ts.map +1 -0
- package/dist/tools/session-stats.js +1054 -0
- package/dist/tools/session-stats.js.map +1 -0
- package/dist/tools/workflow-tools.d.ts +126 -0
- package/dist/tools/workflow-tools.d.ts.map +1 -0
- package/dist/tools/workflow-tools.js +274 -0
- package/dist/tools/workflow-tools.js.map +1 -0
- package/dist/tracing/mcp-tracer.d.ts +4 -0
- package/dist/tracing/mcp-tracer.d.ts.map +1 -0
- package/dist/tracing/mcp-tracer.js +14 -0
- package/dist/tracing/mcp-tracer.js.map +1 -0
- package/dist/tracing/session-span.d.ts +14 -0
- package/dist/tracing/session-span.d.ts.map +1 -0
- package/dist/tracing/session-span.js +53 -0
- package/dist/tracing/session-span.js.map +1 -0
- package/dist/tracing/task-span-tracker.d.ts +11 -0
- package/dist/tracing/task-span-tracker.d.ts.map +1 -0
- package/dist/tracing/task-span-tracker.js +59 -0
- package/dist/tracing/task-span-tracker.js.map +1 -0
- package/dist/tracing/tool-call-span.d.ts +4 -0
- package/dist/tracing/tool-call-span.d.ts.map +1 -0
- package/dist/tracing/tool-call-span.js +60 -0
- package/dist/tracing/tool-call-span.js.map +1 -0
- package/dist/transport/index.d.ts +3 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +2 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/log-ingest.d.ts +42 -0
- package/dist/transport/log-ingest.d.ts.map +1 -0
- package/dist/transport/log-ingest.js +151 -0
- package/dist/transport/log-ingest.js.map +1 -0
- package/dist/transport/nr-ingest.d.ts +171 -0
- package/dist/transport/nr-ingest.d.ts.map +1 -0
- package/dist/transport/nr-ingest.js +659 -0
- package/dist/transport/nr-ingest.js.map +1 -0
- package/dist/types.d.ts +45 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/web/assets/index-BrL281N-.css +2 -0
- package/dist/web/assets/index-CcaYZzXm.js +42 -0
- package/dist/web/favicon.svg +15 -0
- package/dist/web/index.html +15 -0
- package/examples/local-alert-rules.json +106 -0
- 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"}
|