@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,114 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { writeFileSync, readFileSync, existsSync, statSync, accessSync, constants, unlinkSync, mkdirSync, } from 'node:fs';
3
+ import { resolve, join } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ function escapeXml(s) {
6
+ return s
7
+ .replace(/&/g, '&')
8
+ .replace(/</g, '&lt;')
9
+ .replace(/>/g, '&gt;')
10
+ .replace(/"/g, '&quot;');
11
+ }
12
+ const PLIST_LABEL = 'com.preflight.update';
13
+ function plistPath() {
14
+ return resolve(homedir(), 'Library', 'LaunchAgents', `${PLIST_LABEL}.plist`);
15
+ }
16
+ function updateLogPath() {
17
+ return resolve(homedir(), '.newrelic-preflight', 'update.log');
18
+ }
19
+ function buildPlist(binaryPath, hour, minute) {
20
+ return `<?xml version="1.0" encoding="UTF-8"?>
21
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
22
+ <plist version="1.0">
23
+ <dict>
24
+ <key>Label</key>
25
+ <string>${PLIST_LABEL}</string>
26
+ <key>ProgramArguments</key>
27
+ <array>
28
+ <string>${escapeXml(binaryPath)}</string>
29
+ <string>update</string>
30
+ </array>
31
+ <key>StartCalendarInterval</key>
32
+ <dict>
33
+ <key>Hour</key>
34
+ <integer>${hour}</integer>
35
+ <key>Minute</key>
36
+ <integer>${minute}</integer>
37
+ </dict>
38
+ <key>StandardOutPath</key>
39
+ <string>${escapeXml(updateLogPath())}</string>
40
+ <key>StandardErrorPath</key>
41
+ <string>${escapeXml(updateLogPath())}</string>
42
+ <key>RunAtLoad</key>
43
+ <false/>
44
+ </dict>
45
+ </plist>`;
46
+ }
47
+ export function installSchedule(binaryPath, hour, minute) {
48
+ const path = plistPath();
49
+ mkdirSync(resolve(homedir(), 'Library', 'LaunchAgents'), { recursive: true, mode: 0o755 });
50
+ writeFileSync(path, buildPlist(binaryPath, hour, minute), { mode: 0o600 });
51
+ try {
52
+ execFileSync('launchctl', ['unload', path], { stdio: 'pipe' });
53
+ }
54
+ catch {
55
+ // Not yet loaded — that's fine.
56
+ }
57
+ try {
58
+ execFileSync('launchctl', ['load', path], { stdio: 'pipe' });
59
+ }
60
+ catch (err) {
61
+ throw new Error(`launchctl load failed: ${err instanceof Error ? err.message : String(err)}`);
62
+ }
63
+ }
64
+ export function removeSchedule() {
65
+ const path = plistPath();
66
+ if (!existsSync(path))
67
+ return;
68
+ try {
69
+ execFileSync('launchctl', ['unload', path], { stdio: 'pipe' });
70
+ }
71
+ catch {
72
+ // Already unloaded.
73
+ }
74
+ unlinkSync(path);
75
+ }
76
+ export function getScheduleStatus() {
77
+ const path = plistPath();
78
+ if (!existsSync(path))
79
+ return { installed: false };
80
+ try {
81
+ const content = readFileSync(path, 'utf-8');
82
+ const hourMatch = content.match(/<key>Hour<\/key>\s*<integer>(\d+)<\/integer>/);
83
+ const minuteMatch = content.match(/<key>Minute<\/key>\s*<integer>(\d+)<\/integer>/);
84
+ const binaryMatch = content.match(/<key>ProgramArguments<\/key>\s*<array>\s*<string>([^<]+)<\/string>/);
85
+ return {
86
+ installed: true,
87
+ hour: hourMatch ? parseInt(hourMatch[1], 10) : undefined,
88
+ minute: minuteMatch ? parseInt(minuteMatch[1], 10) : undefined,
89
+ binaryPath: binaryMatch ? binaryMatch[1] : undefined,
90
+ };
91
+ }
92
+ catch {
93
+ return { installed: false };
94
+ }
95
+ }
96
+ export function resolveBinaryPath() {
97
+ // Walk PATH directly — avoids hardcoding the `which` location and is safe
98
+ // for Nix/Homebrew installs where binaries live outside /usr/bin.
99
+ const pathDirs = (process.env.PATH ?? '').split(':').filter(Boolean);
100
+ for (const dir of pathDirs) {
101
+ const candidate = join(dir, 'preflight');
102
+ try {
103
+ if (statSync(candidate).isFile()) {
104
+ accessSync(candidate, constants.X_OK);
105
+ return candidate;
106
+ }
107
+ }
108
+ catch {
109
+ continue;
110
+ }
111
+ }
112
+ return null;
113
+ }
114
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../src/install/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,aAAa,EACb,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C,SAAS,SAAS;IAChB,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,WAAW,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,YAAY,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,UAAU,CAAC,UAAkB,EAAE,IAAY,EAAE,MAAc;IAClE,OAAO;;;;;YAKG,WAAW;;;cAGT,SAAS,CAAC,UAAU,CAAC;;;;;;eAMpB,IAAI;;eAEJ,MAAM;;;YAGT,SAAS,CAAC,aAAa,EAAE,CAAC;;YAE1B,SAAS,CAAC,aAAa,EAAE,CAAC;;;;SAI7B,CAAC;AACV,CAAC;AASD,MAAM,UAAU,eAAe,CAAC,UAAkB,EAAE,IAAY,EAAE,MAAc;IAC9E,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3F,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IACD,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,YAAY,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAChF,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpF,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAC/B,oEAAoE,CACrE,CAAC;QACF,OAAO;YACL,SAAS,EAAE,IAAI;YACf,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YACxD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YAC9D,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;SACrD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrE,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACzC,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACjC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;gBACtC,OAAO,SAAS,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,40 @@
1
+ interface WizardLogger {
2
+ warn(msg: string, meta?: object): void;
3
+ info(msg: string, meta?: object): void;
4
+ }
5
+ export interface CopyStarterAlertRulesOptions {
6
+ /** Path to the source examples/local-alert-rules.json. */
7
+ readonly sourcePath: string;
8
+ /** Destination path (default: ~/.newrelic-preflight/alerts/rules.json). */
9
+ readonly destPath: string;
10
+ /** Optional logger; otherwise no-op. */
11
+ readonly logger?: WizardLogger;
12
+ }
13
+ export interface CopyStarterAlertRulesResult {
14
+ readonly copied: boolean;
15
+ readonly reason?: string;
16
+ }
17
+ /**
18
+ * Copy the bundled starter alert rules into the destination path. Idempotent:
19
+ * if the destination already exists, the function leaves it alone (so a
20
+ * user-edited rules file is never clobbered by a re-run of `setup`). The
21
+ * destination directory is created with `0o700` if missing; the file is
22
+ * written with `0o600`.
23
+ */
24
+ export declare function copyStarterAlertRules(opts: CopyStarterAlertRulesOptions): CopyStarterAlertRulesResult;
25
+ export type WizardMode = 'cloud' | 'local' | 'both';
26
+ export declare function buildConfig(existing: Record<string, unknown>, inputs: {
27
+ accountId: string;
28
+ licenseKey: string;
29
+ developer: string;
30
+ teamId: string | null;
31
+ projectId: string | null;
32
+ sessionBudgetUsd: number | null;
33
+ mode?: WizardMode;
34
+ dashboardPort?: number | null;
35
+ nrApiKey?: string | null;
36
+ collectorHost?: string | null;
37
+ }): Record<string, unknown>;
38
+ export declare function runSetupWizard(): Promise<void>;
39
+ export {};
40
+ //# sourceMappingURL=setup-wizard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-wizard.d.ts","sourceRoot":"","sources":["../../src/install/setup-wizard.ts"],"names":[],"mappings":"AAuBA,UAAU,YAAY;IACpB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAwBD,MAAM,WAAW,4BAA4B;IAC3C,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,4BAA4B,GACjC,2BAA2B,CA6B7B;AA2CD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,EAAE;IACN,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,GACA,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAWD,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CA6ZpD"}
@@ -0,0 +1,489 @@
1
+ import { createInterface } from 'node:readline/promises';
2
+ import { writeFileSync, renameSync, mkdirSync, readFileSync, existsSync, copyFileSync, chmodSync, realpathSync, } from 'node:fs';
3
+ import { resolve, dirname } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ import { normalizeDeveloperName, ConfigFileSchema } from '../config.js';
6
+ import { migrateStoragePath } from './migrate.js';
7
+ import { runInstallCli, verifyBinaryOnPath } from './cli.js';
8
+ import { installSchedule, resolveBinaryPath } from './schedule.js';
9
+ import { validateLicenseKey, validateApiKey } from './key-validator.js';
10
+ const DEFAULT_STORAGE_PATH = resolve(homedir(), '.newrelic-preflight');
11
+ const CONFIG_PATH = resolve(DEFAULT_STORAGE_PATH, 'config.json');
12
+ const ALERT_RULES_DEST = resolve(DEFAULT_STORAGE_PATH, 'alerts', 'rules.json');
13
+ /**
14
+ * Resolve the path to the bundled `examples/local-alert-rules.json`. The
15
+ * wizard ships from either `dist/install/` (when installed via npm) or
16
+ * `src/install/` (when executed via `npx tsx`); both resolve to the repo
17
+ * root by walking up two directories from the running script.
18
+ *
19
+ * Uses `process.argv[1]` rather than `__dirname` (which doesn't exist in
20
+ * ESM) or `import.meta.url` (which trips Jest's TS module check). Same
21
+ * pattern as `src/index.ts` for resolving the static dashboard dir.
22
+ */
23
+ function defaultStarterRulesSource() {
24
+ const rawPath = process.argv[1] ?? process.cwd();
25
+ const scriptPath = (() => {
26
+ try {
27
+ return realpathSync(rawPath);
28
+ }
29
+ catch {
30
+ return rawPath;
31
+ }
32
+ })();
33
+ return resolve(dirname(scriptPath), '..', '..', 'examples', 'local-alert-rules.json');
34
+ }
35
+ /**
36
+ * Copy the bundled starter alert rules into the destination path. Idempotent:
37
+ * if the destination already exists, the function leaves it alone (so a
38
+ * user-edited rules file is never clobbered by a re-run of `setup`). The
39
+ * destination directory is created with `0o700` if missing; the file is
40
+ * written with `0o600`.
41
+ */
42
+ export function copyStarterAlertRules(opts) {
43
+ const { sourcePath, destPath, logger } = opts;
44
+ if (existsSync(destPath)) {
45
+ logger?.info('alerts: rules file already exists; skipping copy', {
46
+ destPath,
47
+ });
48
+ return { copied: false, reason: 'exists' };
49
+ }
50
+ if (!existsSync(sourcePath)) {
51
+ logger?.warn('alerts: starter rules source not found', { sourcePath });
52
+ return { copied: false, reason: 'source-missing' };
53
+ }
54
+ try {
55
+ mkdirSync(dirname(destPath), { recursive: true, mode: 0o700 });
56
+ copyFileSync(sourcePath, destPath);
57
+ // copyFileSync preserves permissions from source; force 0o600 so the
58
+ // destination is locked-down regardless of what the source file had.
59
+ try {
60
+ chmodSync(destPath, 0o600);
61
+ }
62
+ catch {
63
+ // Non-fatal — Windows may not honour chmod, etc.
64
+ }
65
+ logger?.info('alerts: copied starter rules', { sourcePath, destPath });
66
+ return { copied: true };
67
+ }
68
+ catch (err) {
69
+ const error = err instanceof Error ? err.message : String(err);
70
+ logger?.warn('alerts: copy failed', { sourcePath, destPath, error });
71
+ return { copied: false, reason: error };
72
+ }
73
+ }
74
+ function print(msg = '') {
75
+ process.stdout.write(msg + '\n');
76
+ }
77
+ function loadExisting() {
78
+ let parsed;
79
+ try {
80
+ parsed = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
81
+ }
82
+ catch {
83
+ return {};
84
+ }
85
+ // Validate via the same schema loadMcpConfig uses, then keep ONLY recognized
86
+ // top-level keys. The schema is `.passthrough()` so safeParse won't strip
87
+ // unknown keys for us; the explicit filter below makes sure the wizard's
88
+ // later spread (`...existing` in buildConfig) doesn't perpetuate stale keys
89
+ // back into the rewritten config file.
90
+ const validation = ConfigFileSchema.safeParse(parsed);
91
+ const knownKeys = new Set(Object.keys(ConfigFileSchema.shape));
92
+ if (!validation.success) {
93
+ // Recognized-key value is malformed (e.g. accountId is a number, not a
94
+ // string). Log a warning and fall back to defaults — the wizard will
95
+ // re-prompt for those fields rather than pre-fill bad data.
96
+ const issues = validation.error.issues
97
+ .map((issue) => `${issue.path.join('.') || 'root'}: ${issue.message}`)
98
+ .join('; ');
99
+ process.stderr.write(`[setup-wizard] Existing config has invalid values; ignoring: ${issues}\n`);
100
+ return {};
101
+ }
102
+ // Strip unknown keys from the validated object so they don't get spread
103
+ // back into the rewritten config.
104
+ const filtered = {};
105
+ for (const [key, value] of Object.entries(validation.data)) {
106
+ if (knownKeys.has(key)) {
107
+ filtered[key] = value;
108
+ }
109
+ }
110
+ return filtered;
111
+ }
112
+ export function buildConfig(existing, inputs) {
113
+ const mode = inputs.mode ?? 'cloud';
114
+ const includeNrCreds = mode !== 'local';
115
+ return {
116
+ ...existing,
117
+ ...(inputs.mode ? { mode } : {}),
118
+ ...(includeNrCreds ? { accountId: inputs.accountId, licenseKey: inputs.licenseKey } : {}),
119
+ developer: inputs.developer,
120
+ ...(inputs.teamId ? { teamId: inputs.teamId } : {}),
121
+ ...(inputs.projectId ? { projectId: inputs.projectId } : {}),
122
+ ...(inputs.sessionBudgetUsd !== null ? { sessionBudgetUsd: inputs.sessionBudgetUsd } : {}),
123
+ ...(inputs.dashboardPort != null
124
+ ? { dashboard: { port: inputs.dashboardPort, host: '127.0.0.1', openOnStart: false } }
125
+ : {}),
126
+ ...(inputs.nrApiKey ? { nrApiKey: inputs.nrApiKey } : {}),
127
+ ...(inputs.collectorHost ? { collectorHost: inputs.collectorHost } : {}),
128
+ };
129
+ }
130
+ function parseModeAnswer(raw, fallback) {
131
+ const trimmed = raw.trim().toLowerCase();
132
+ if (trimmed === '' || trimmed === fallback)
133
+ return fallback;
134
+ if (trimmed === 'cloud' || trimmed === '1')
135
+ return 'cloud';
136
+ if (trimmed === 'local' || trimmed === '2')
137
+ return 'local';
138
+ if (trimmed === 'both' || trimmed === '3')
139
+ return 'both';
140
+ return fallback;
141
+ }
142
+ export async function runSetupWizard() {
143
+ migrateStoragePath(true);
144
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
145
+ try {
146
+ print('\n=== Preflight Setup ===\n');
147
+ print('This wizard will configure observability for your AI coding assistant.');
148
+ print('Press Ctrl+C at any time to cancel.\n');
149
+ const existing = loadExisting();
150
+ // Step 0: Mode
151
+ const existingMode = typeof existing.mode === 'string' &&
152
+ (existing.mode === 'cloud' || existing.mode === 'local' || existing.mode === 'both')
153
+ ? existing.mode
154
+ : 'local';
155
+ print('Modes:');
156
+ print(' 1) cloud — ship telemetry to New Relic');
157
+ print(' 2) local — keep all data on this machine, run a local dashboard (default)');
158
+ print(' 3) both — ship to NR AND run the local dashboard');
159
+ const modeRaw = await rl.question(`Which mode? [${existingMode}]: `);
160
+ const mode = parseModeAnswer(modeRaw, existingMode);
161
+ // Step 1+2: NR credentials (skip in local mode)
162
+ let accountId = '';
163
+ let licenseKey = '';
164
+ let collectorHost = null;
165
+ let nrApiKey = null;
166
+ let validatedEmail = null;
167
+ if (mode !== 'local') {
168
+ const envAccountId = process.env.NEW_RELIC_ACCOUNT_ID?.trim() ?? '';
169
+ const existingAccountId = typeof existing.accountId === 'string' ? existing.accountId : '';
170
+ const defaultAccountId = existingAccountId || envAccountId;
171
+ const accountIdHint = existingAccountId
172
+ ? existingAccountId
173
+ : envAccountId
174
+ ? '$NEW_RELIC_ACCOUNT_ID'
175
+ : '';
176
+ const accountIdPrompt = accountIdHint
177
+ ? `Account ID — your NR account number, found in the NR One URL [${accountIdHint}]: `
178
+ : 'Account ID — your NR account number, found in the NR One URL (required): ';
179
+ accountId = (await rl.question(accountIdPrompt)).trim();
180
+ if (!accountId)
181
+ accountId = defaultAccountId;
182
+ if (!/^\d{1,12}$/.test(accountId)) {
183
+ const src = accountId === envAccountId && !existingAccountId
184
+ ? ' (value from $NEW_RELIC_ACCOUNT_ID)'
185
+ : '';
186
+ console.error(`Invalid account ID: "${accountId}". Must be 1–12 digits.${src}`);
187
+ rl.close();
188
+ process.exit(1);
189
+ }
190
+ const envLicenseKey = process.env.NEW_RELIC_LICENSE_KEY?.trim() ?? '';
191
+ const existingKey = typeof existing.licenseKey === 'string' ? existing.licenseKey : '';
192
+ const defaultKey = existingKey || envLicenseKey;
193
+ const keyHint = existingKey
194
+ ? '(already set)'
195
+ : envLicenseKey
196
+ ? '$NEW_RELIC_LICENSE_KEY'
197
+ : 'required';
198
+ const keyPrompt = `License Key — authenticates telemetry ingest to your NR account [${keyHint}]: `;
199
+ licenseKey = (await rl.question(keyPrompt)).trim();
200
+ if (!licenseKey)
201
+ licenseKey = defaultKey;
202
+ if (!licenseKey) {
203
+ console.error('License key is required. Set NEW_RELIC_LICENSE_KEY or enter a value above.');
204
+ rl.close();
205
+ process.exit(1);
206
+ }
207
+ // Step 2b: Environment / region
208
+ const existingCollectorHost = typeof existing.collectorHost === 'string' ? existing.collectorHost : null;
209
+ const keyLower = licenseKey.toLowerCase();
210
+ const autoEnv = keyLower.startsWith('eu01')
211
+ ? 'eu'
212
+ : keyLower.startsWith('gov01')
213
+ ? 'gov'
214
+ : 'us';
215
+ const defaultEnv = existingCollectorHost ?? autoEnv;
216
+ print('Environment:');
217
+ print(' 1) US — api.newrelic.com');
218
+ print(' 2) EU — api.eu.newrelic.com');
219
+ print(' 3) FedRAMP — api.newrelic.com (FedRAMP/GovCloud)');
220
+ const envRaw = (await rl.question(`Which environment? [${defaultEnv}]: `))
221
+ .trim()
222
+ .toLowerCase();
223
+ const resolvedEnv = envRaw === '' || envRaw === defaultEnv
224
+ ? defaultEnv
225
+ : envRaw === '1' || envRaw === 'us'
226
+ ? 'us'
227
+ : envRaw === '2' || envRaw === 'eu'
228
+ ? 'eu'
229
+ : envRaw === '3' || envRaw === 'fedramp' || envRaw === 'gov'
230
+ ? 'gov'
231
+ : defaultEnv;
232
+ collectorHost = resolvedEnv === 'us' ? null : resolvedEnv;
233
+ // Warn if license key prefix contradicts selected environment.
234
+ const keyRegion = keyLower.startsWith('eu01')
235
+ ? 'eu'
236
+ : keyLower.startsWith('gov01')
237
+ ? 'gov'
238
+ : keyLower.startsWith('us01')
239
+ ? 'us'
240
+ : null;
241
+ if (keyRegion && keyRegion !== resolvedEnv) {
242
+ print(` ⚠ Your license key looks like a ${keyRegion.toUpperCase()} key but you selected ${resolvedEnv.toUpperCase()}. Verify this is intentional.`);
243
+ }
244
+ // Step 2c: NR API key (optional)
245
+ const envApiKey = process.env.NEW_RELIC_API_KEY?.trim() ?? '';
246
+ const existingApiKey = typeof existing.nrApiKey === 'string' ? existing.nrApiKey : null;
247
+ const defaultApiKey = existingApiKey ?? (envApiKey || null);
248
+ const apiKeyHint = existingApiKey
249
+ ? '(already set)'
250
+ : envApiKey
251
+ ? '$NEW_RELIC_API_KEY'
252
+ : 'optional';
253
+ const apiKeyRaw = (await rl.question(`API Key (NRAK-...) — for team queries and deploying dashboards/alerts [${apiKeyHint}]: `)).trim();
254
+ if (apiKeyRaw) {
255
+ nrApiKey = apiKeyRaw;
256
+ }
257
+ else if (defaultApiKey) {
258
+ nrApiKey = defaultApiKey;
259
+ }
260
+ // Step 2d: Validate credentials
261
+ print('\nValidating credentials...');
262
+ const licenseResult = await validateLicenseKey({ licenseKey, accountId, collectorHost });
263
+ if (licenseResult.valid) {
264
+ print(' ✓ License key: OK');
265
+ }
266
+ else if (licenseResult.reason === 'unauthorized') {
267
+ print(' ✗ License key: unauthorized — double-check your key and environment selection');
268
+ }
269
+ else if (licenseResult.reason === 'timeout' || licenseResult.reason === 'network') {
270
+ print(` ⚠ License key: could not reach NR ingest API (${licenseResult.detail ?? licenseResult.reason}) — check your network`);
271
+ }
272
+ else {
273
+ print(` ⚠ License key: unexpected response (${licenseResult.detail ?? 'unknown'}) — proceeding anyway`);
274
+ }
275
+ if (nrApiKey) {
276
+ const apiResult = await validateApiKey({ nrApiKey, collectorHost });
277
+ if (apiResult.valid) {
278
+ validatedEmail = apiResult.detail ?? null;
279
+ const who = validatedEmail ? ` (${validatedEmail})` : '';
280
+ print(` ✓ API key: OK${who}`);
281
+ }
282
+ else if (apiResult.reason === 'unauthorized') {
283
+ print(' ✗ API key: unauthorized — double-check your NRAK key');
284
+ }
285
+ else if (apiResult.reason === 'timeout' || apiResult.reason === 'network') {
286
+ print(` ⚠ API key: could not reach NerdGraph (${apiResult.detail ?? apiResult.reason}) — check your network`);
287
+ }
288
+ else {
289
+ print(` ⚠ API key: unexpected response (${apiResult.detail ?? 'unknown'}) — proceeding anyway`);
290
+ }
291
+ }
292
+ }
293
+ print('\n ℹ Telemetry note: this server sends events and metrics to your NR account — ingest costs');
294
+ print(' apply on paid plans. Monitor usage via NR One → Data Management → Data Ingestion.');
295
+ // Step 3: Developer name — prefer existing config, then email local-part, then $USER
296
+ const emailLocalPart = validatedEmail ? (validatedEmail.split('@')[0] ?? '') : '';
297
+ const defaultDeveloper = typeof existing.developer === 'string'
298
+ ? existing.developer
299
+ : normalizeDeveloperName(emailLocalPart || process.env.USER || process.env.USERNAME || '');
300
+ const rawInput = (await rl.question(`Developer name — stamped on every event so you can filter your own data [${defaultDeveloper}]: `)).trim() || defaultDeveloper;
301
+ const developer = normalizeDeveloperName(rawInput);
302
+ if (developer !== rawInput) {
303
+ print(` → Normalized to: ${developer}`);
304
+ }
305
+ // Step 4: Optional fields
306
+ print('\n-- Optional fields (press Enter to skip any) --');
307
+ const existingTeamId = typeof existing.teamId === 'string' ? existing.teamId : null;
308
+ const teamIdAnswer = (await rl.question(`Team label — a slug you define, e.g. "platform-eng" (not your NR account ID) used for recording metrics [${existingTeamId ?? 'optional'}]: `)).trim();
309
+ const teamId = teamIdAnswer || existingTeamId;
310
+ const existingProjectId = typeof existing.projectId === 'string' ? existing.projectId : null;
311
+ const projectIdAnswer = (await rl.question(`Project ID — labels all events by project for per-project filtering [${existingProjectId ?? 'optional, auto-detected from git'}]: `)).trim();
312
+ const projectId = projectIdAnswer || existingProjectId;
313
+ // Step 5: Budget caps
314
+ const existingBudget = typeof existing.sessionBudgetUsd === 'number' ? String(existing.sessionBudgetUsd) : null;
315
+ const sessionBudgetStr = (await rl.question(`Session budget USD — triggers a warning event when AI spend exceeds this per session [${existingBudget ?? 'no limit'}]: `)).trim() ||
316
+ (existingBudget ?? '');
317
+ let sessionBudgetUsd = null;
318
+ if (sessionBudgetStr) {
319
+ const parsed = parseFloat(sessionBudgetStr);
320
+ if (!Number.isFinite(parsed) || parsed <= 0) {
321
+ console.error(`Invalid session budget "${sessionBudgetStr}": must be a positive number.`);
322
+ rl.close();
323
+ process.exit(1);
324
+ }
325
+ sessionBudgetUsd = parsed;
326
+ }
327
+ // Step 5b: Dashboard port (local/both only)
328
+ let dashboardPort = null;
329
+ if (mode === 'local' || mode === 'both') {
330
+ const existingDashboard = existing.dashboard && typeof existing.dashboard === 'object'
331
+ ? existing.dashboard
332
+ : null;
333
+ const defaultPort = existingDashboard?.port ?? 7777;
334
+ const portStr = (await rl.question(`Dashboard port — open http://127.0.0.1:${defaultPort} in your browser to view metrics [${defaultPort}]: `)).trim();
335
+ if (portStr) {
336
+ const parsed = parseInt(portStr, 10);
337
+ if (!Number.isFinite(parsed) || parsed <= 0 || parsed >= 65536) {
338
+ console.error(`Invalid port "${portStr}": must be 1–65535.`);
339
+ rl.close();
340
+ process.exit(1);
341
+ }
342
+ dashboardPort = parsed;
343
+ }
344
+ else {
345
+ dashboardPort = defaultPort;
346
+ }
347
+ }
348
+ // Write config
349
+ const config = buildConfig(existing, {
350
+ accountId,
351
+ licenseKey,
352
+ developer,
353
+ teamId,
354
+ projectId,
355
+ sessionBudgetUsd,
356
+ mode,
357
+ dashboardPort,
358
+ nrApiKey,
359
+ collectorHost,
360
+ });
361
+ mkdirSync(DEFAULT_STORAGE_PATH, { recursive: true, mode: 0o700 });
362
+ const configTmp = CONFIG_PATH + '.tmp';
363
+ writeFileSync(configTmp, JSON.stringify(config, null, 2), { mode: 0o600 });
364
+ renameSync(configTmp, CONFIG_PATH);
365
+ print(`\nConfig written to ${CONFIG_PATH}`);
366
+ // Step 5c: Starter alert rules (local + both modes only).
367
+ // Default-yes prompt; copy is idempotent — re-running the wizard never
368
+ // overwrites a user-edited rules file.
369
+ if (mode === 'local' || mode === 'both') {
370
+ const copyAnswer = (await rl.question('Copy starter alert rules to ~/.newrelic-preflight/alerts/rules.json? [Y/n]: '))
371
+ .trim()
372
+ .toLowerCase();
373
+ if (copyAnswer !== 'n' && copyAnswer !== 'no') {
374
+ const result = copyStarterAlertRules({
375
+ sourcePath: defaultStarterRulesSource(),
376
+ destPath: ALERT_RULES_DEST,
377
+ logger: {
378
+ warn: (msg) => print(` ! ${msg}`),
379
+ info: (msg) => print(` → ${msg}`),
380
+ },
381
+ });
382
+ if (result.copied) {
383
+ print(`Starter alert rules copied to ${ALERT_RULES_DEST}`);
384
+ }
385
+ else if (result.reason === 'exists') {
386
+ print(`Existing rules.json left in place (skipped — file exists).`);
387
+ }
388
+ else {
389
+ print(`Could not copy starter rules: ${result.reason ?? 'unknown error'}`);
390
+ }
391
+ }
392
+ }
393
+ // Step 6: Hook install
394
+ // Config is already written above; pass no credentials to install so it only
395
+ // wires hooks and MCP without overwriting the config we just wrote.
396
+ const installHooks = (await rl.question('\nInstall Claude Code hooks now? [Y/n]: '))
397
+ .trim()
398
+ .toLowerCase();
399
+ if (installHooks !== 'n') {
400
+ print('\nRunning hook installer...');
401
+ await runInstallCli(['install']);
402
+ print('Hooks installed.');
403
+ if (verifyBinaryOnPath()) {
404
+ print('✓ preflight is on your PATH');
405
+ }
406
+ else {
407
+ print('\n⚠ preflight is not on your PATH.');
408
+ print(' Claude Code hooks will fail with "command not found" until this is resolved.');
409
+ print(' Fix: run `npm link` in the project directory, or install globally:');
410
+ print(' npm install -g @newrelic/preflight');
411
+ }
412
+ }
413
+ // Step 7: Auto-update schedule (macOS only)
414
+ if (process.platform === 'darwin') {
415
+ const enableUpdate = (await rl.question('\nEnable daily auto-updates? [Y/n]: '))
416
+ .trim()
417
+ .toLowerCase();
418
+ if (enableUpdate !== 'n' && enableUpdate !== 'no') {
419
+ const timeRaw = (await rl.question('Update time (24h HH:MM) [08:00]: ')).trim();
420
+ const timeStr = timeRaw || '08:00';
421
+ const match = timeStr.match(/^(\d{1,2}):(\d{2})$/);
422
+ const parsedHour = match ? parseInt(match[1], 10) : -1;
423
+ const parsedMinute = match ? parseInt(match[2], 10) : -1;
424
+ const validTime = parsedHour >= 0 && parsedHour <= 23 && parsedMinute >= 0 && parsedMinute <= 59;
425
+ const hour = validTime ? parsedHour : 8;
426
+ const minute = validTime ? parsedMinute : 0;
427
+ if (!validTime && timeStr !== '08:00') {
428
+ print(`⚠ Invalid time "${timeStr}", using default 08:00.`);
429
+ }
430
+ const hh = String(hour).padStart(2, '0');
431
+ const mm = String(minute).padStart(2, '0');
432
+ const binaryPath = resolveBinaryPath();
433
+ if (binaryPath) {
434
+ try {
435
+ installSchedule(binaryPath, hour, minute);
436
+ print(`✓ Daily auto-update scheduled for ${hh}:${mm}`);
437
+ }
438
+ catch {
439
+ print(`⚠ Could not register schedule — run: preflight schedule --time ${hh}:${mm}`);
440
+ }
441
+ }
442
+ else {
443
+ print('\n⚠ Cannot schedule — preflight not found on PATH.');
444
+ print(` Run preflight schedule --time ${hh}:${mm} after fixing PATH.`);
445
+ }
446
+ }
447
+ }
448
+ // Step 8: Dashboard deploy — show manual command
449
+ if (mode !== 'local') {
450
+ const regionFlag = collectorHost === 'eu' ? ' --eu' : '';
451
+ // Mask the API key in printed commands — users copy these snippets to
452
+ // terminals, docs, and chat messages, and the raw key could be captured.
453
+ const apiKeyVar = nrApiKey
454
+ ? `NEW_RELIC_API_KEY=${nrApiKey.slice(0, 8)}...`
455
+ : 'NEW_RELIC_API_KEY=<NRAK-...>';
456
+ print('\nTo deploy dashboards, run:');
457
+ print(` ${apiKeyVar} NEW_RELIC_ACCOUNT_ID=${accountId} preflight deploy-dashboards --all${regionFlag}`);
458
+ print(`\nFor a personal dashboard pre-filtered to you:`);
459
+ print(` ${apiKeyVar} NEW_RELIC_ACCOUNT_ID=${accountId} preflight deploy-dashboards ai-coding-assistant-personal.json --developer ${developer}${regionFlag}`);
460
+ print(`\nFor personal alerts scoped to you:`);
461
+ print(` ${apiKeyVar} NEW_RELIC_ACCOUNT_ID=${accountId} preflight deploy-alerts --developer ${developer}${regionFlag}`);
462
+ }
463
+ else if (mode === 'local') {
464
+ print(`\nLocal mode selected — dashboard and metrics will be available locally.`);
465
+ }
466
+ // The MCP server is launched automatically by Claude Code based on the
467
+ // .mcp.json entry written above — there is no manual start step. Telling
468
+ // users to run `preflight --stdio` themselves leads them to
469
+ // start a second process that competes with the auto-launched one for
470
+ // the buffer file lock and produces interleaved metrics.
471
+ print('\n✓ Setup complete.');
472
+ print(' Start a new Claude Code session — the MCP server and hooks are loaded at session');
473
+ print(' start. If you ran this setup inside an existing session, exit and start a fresh one');
474
+ print(' for the hooks to take effect.');
475
+ if (mode !== 'cloud') {
476
+ print(` Dashboard is available at http://127.0.0.1:${dashboardPort ?? 7777} once Claude Code starts.`);
477
+ print(' On first launch you will see only nr_observe_health and nr_observe_get_config until');
478
+ print(' the first tool call fires the hook — all tools appear automatically after that.');
479
+ }
480
+ else {
481
+ print(' Metrics will appear in your New Relic dashboard within a few minutes.');
482
+ }
483
+ print('');
484
+ }
485
+ finally {
486
+ rl.close();
487
+ }
488
+ }
489
+ //# sourceMappingURL=setup-wizard.js.map