@dotsetlabs/bellwether 0.10.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 (403) hide show
  1. package/CHANGELOG.md +291 -0
  2. package/LICENSE +21 -0
  3. package/README.md +739 -0
  4. package/dist/auth/credentials.d.ts +64 -0
  5. package/dist/auth/credentials.js +218 -0
  6. package/dist/auth/index.d.ts +6 -0
  7. package/dist/auth/index.js +6 -0
  8. package/dist/auth/keychain.d.ts +64 -0
  9. package/dist/auth/keychain.js +268 -0
  10. package/dist/baseline/ab-testing.d.ts +80 -0
  11. package/dist/baseline/ab-testing.js +236 -0
  12. package/dist/baseline/ai-compatibility-scorer.d.ts +95 -0
  13. package/dist/baseline/ai-compatibility-scorer.js +606 -0
  14. package/dist/baseline/calibration.d.ts +77 -0
  15. package/dist/baseline/calibration.js +136 -0
  16. package/dist/baseline/category-matching.d.ts +85 -0
  17. package/dist/baseline/category-matching.js +289 -0
  18. package/dist/baseline/change-impact-analyzer.d.ts +98 -0
  19. package/dist/baseline/change-impact-analyzer.js +592 -0
  20. package/dist/baseline/comparator.d.ts +64 -0
  21. package/dist/baseline/comparator.js +916 -0
  22. package/dist/baseline/confidence.d.ts +55 -0
  23. package/dist/baseline/confidence.js +122 -0
  24. package/dist/baseline/converter.d.ts +61 -0
  25. package/dist/baseline/converter.js +585 -0
  26. package/dist/baseline/dependency-analyzer.d.ts +89 -0
  27. package/dist/baseline/dependency-analyzer.js +567 -0
  28. package/dist/baseline/deprecation-tracker.d.ts +133 -0
  29. package/dist/baseline/deprecation-tracker.js +322 -0
  30. package/dist/baseline/diff.d.ts +55 -0
  31. package/dist/baseline/diff.js +1584 -0
  32. package/dist/baseline/documentation-scorer.d.ts +205 -0
  33. package/dist/baseline/documentation-scorer.js +466 -0
  34. package/dist/baseline/embeddings.d.ts +118 -0
  35. package/dist/baseline/embeddings.js +251 -0
  36. package/dist/baseline/error-analyzer.d.ts +198 -0
  37. package/dist/baseline/error-analyzer.js +721 -0
  38. package/dist/baseline/evaluation/evaluator.d.ts +42 -0
  39. package/dist/baseline/evaluation/evaluator.js +323 -0
  40. package/dist/baseline/evaluation/expanded-dataset.d.ts +45 -0
  41. package/dist/baseline/evaluation/expanded-dataset.js +1164 -0
  42. package/dist/baseline/evaluation/golden-dataset.d.ts +58 -0
  43. package/dist/baseline/evaluation/golden-dataset.js +717 -0
  44. package/dist/baseline/evaluation/index.d.ts +15 -0
  45. package/dist/baseline/evaluation/index.js +15 -0
  46. package/dist/baseline/evaluation/types.d.ts +186 -0
  47. package/dist/baseline/evaluation/types.js +8 -0
  48. package/dist/baseline/external-dependency-detector.d.ts +181 -0
  49. package/dist/baseline/external-dependency-detector.js +524 -0
  50. package/dist/baseline/golden-output.d.ts +162 -0
  51. package/dist/baseline/golden-output.js +636 -0
  52. package/dist/baseline/health-scorer.d.ts +174 -0
  53. package/dist/baseline/health-scorer.js +451 -0
  54. package/dist/baseline/incremental-checker.d.ts +97 -0
  55. package/dist/baseline/incremental-checker.js +174 -0
  56. package/dist/baseline/index.d.ts +31 -0
  57. package/dist/baseline/index.js +42 -0
  58. package/dist/baseline/migration-generator.d.ts +137 -0
  59. package/dist/baseline/migration-generator.js +554 -0
  60. package/dist/baseline/migrations.d.ts +60 -0
  61. package/dist/baseline/migrations.js +197 -0
  62. package/dist/baseline/performance-tracker.d.ts +214 -0
  63. package/dist/baseline/performance-tracker.js +577 -0
  64. package/dist/baseline/pr-comment-generator.d.ts +117 -0
  65. package/dist/baseline/pr-comment-generator.js +546 -0
  66. package/dist/baseline/response-fingerprint.d.ts +127 -0
  67. package/dist/baseline/response-fingerprint.js +728 -0
  68. package/dist/baseline/response-schema-tracker.d.ts +129 -0
  69. package/dist/baseline/response-schema-tracker.js +420 -0
  70. package/dist/baseline/risk-scorer.d.ts +54 -0
  71. package/dist/baseline/risk-scorer.js +434 -0
  72. package/dist/baseline/saver.d.ts +89 -0
  73. package/dist/baseline/saver.js +554 -0
  74. package/dist/baseline/scenario-generator.d.ts +151 -0
  75. package/dist/baseline/scenario-generator.js +905 -0
  76. package/dist/baseline/schema-compare.d.ts +86 -0
  77. package/dist/baseline/schema-compare.js +557 -0
  78. package/dist/baseline/schema-evolution.d.ts +189 -0
  79. package/dist/baseline/schema-evolution.js +467 -0
  80. package/dist/baseline/semantic.d.ts +203 -0
  81. package/dist/baseline/semantic.js +908 -0
  82. package/dist/baseline/synonyms.d.ts +60 -0
  83. package/dist/baseline/synonyms.js +386 -0
  84. package/dist/baseline/telemetry.d.ts +165 -0
  85. package/dist/baseline/telemetry.js +294 -0
  86. package/dist/baseline/test-pruner.d.ts +120 -0
  87. package/dist/baseline/test-pruner.js +387 -0
  88. package/dist/baseline/types.d.ts +449 -0
  89. package/dist/baseline/types.js +5 -0
  90. package/dist/baseline/version.d.ts +138 -0
  91. package/dist/baseline/version.js +206 -0
  92. package/dist/cache/index.d.ts +5 -0
  93. package/dist/cache/index.js +5 -0
  94. package/dist/cache/response-cache.d.ts +151 -0
  95. package/dist/cache/response-cache.js +287 -0
  96. package/dist/ci/index.d.ts +60 -0
  97. package/dist/ci/index.js +342 -0
  98. package/dist/cli/commands/auth.d.ts +12 -0
  99. package/dist/cli/commands/auth.js +352 -0
  100. package/dist/cli/commands/badge.d.ts +3 -0
  101. package/dist/cli/commands/badge.js +74 -0
  102. package/dist/cli/commands/baseline-accept.d.ts +15 -0
  103. package/dist/cli/commands/baseline-accept.js +178 -0
  104. package/dist/cli/commands/baseline-migrate.d.ts +12 -0
  105. package/dist/cli/commands/baseline-migrate.js +164 -0
  106. package/dist/cli/commands/baseline.d.ts +14 -0
  107. package/dist/cli/commands/baseline.js +449 -0
  108. package/dist/cli/commands/beta.d.ts +10 -0
  109. package/dist/cli/commands/beta.js +231 -0
  110. package/dist/cli/commands/check.d.ts +11 -0
  111. package/dist/cli/commands/check.js +820 -0
  112. package/dist/cli/commands/cloud/badge.d.ts +3 -0
  113. package/dist/cli/commands/cloud/badge.js +74 -0
  114. package/dist/cli/commands/cloud/diff.d.ts +6 -0
  115. package/dist/cli/commands/cloud/diff.js +79 -0
  116. package/dist/cli/commands/cloud/history.d.ts +6 -0
  117. package/dist/cli/commands/cloud/history.js +102 -0
  118. package/dist/cli/commands/cloud/link.d.ts +9 -0
  119. package/dist/cli/commands/cloud/link.js +119 -0
  120. package/dist/cli/commands/cloud/login.d.ts +7 -0
  121. package/dist/cli/commands/cloud/login.js +499 -0
  122. package/dist/cli/commands/cloud/projects.d.ts +6 -0
  123. package/dist/cli/commands/cloud/projects.js +44 -0
  124. package/dist/cli/commands/cloud/shared.d.ts +7 -0
  125. package/dist/cli/commands/cloud/shared.js +42 -0
  126. package/dist/cli/commands/cloud/teams.d.ts +8 -0
  127. package/dist/cli/commands/cloud/teams.js +169 -0
  128. package/dist/cli/commands/cloud/upload.d.ts +8 -0
  129. package/dist/cli/commands/cloud/upload.js +181 -0
  130. package/dist/cli/commands/contract.d.ts +11 -0
  131. package/dist/cli/commands/contract.js +280 -0
  132. package/dist/cli/commands/discover.d.ts +3 -0
  133. package/dist/cli/commands/discover.js +82 -0
  134. package/dist/cli/commands/eval.d.ts +9 -0
  135. package/dist/cli/commands/eval.js +187 -0
  136. package/dist/cli/commands/explore.d.ts +11 -0
  137. package/dist/cli/commands/explore.js +437 -0
  138. package/dist/cli/commands/feedback.d.ts +9 -0
  139. package/dist/cli/commands/feedback.js +174 -0
  140. package/dist/cli/commands/golden.d.ts +12 -0
  141. package/dist/cli/commands/golden.js +407 -0
  142. package/dist/cli/commands/history.d.ts +10 -0
  143. package/dist/cli/commands/history.js +202 -0
  144. package/dist/cli/commands/init.d.ts +9 -0
  145. package/dist/cli/commands/init.js +219 -0
  146. package/dist/cli/commands/interview.d.ts +3 -0
  147. package/dist/cli/commands/interview.js +903 -0
  148. package/dist/cli/commands/link.d.ts +10 -0
  149. package/dist/cli/commands/link.js +169 -0
  150. package/dist/cli/commands/login.d.ts +7 -0
  151. package/dist/cli/commands/login.js +499 -0
  152. package/dist/cli/commands/preset.d.ts +33 -0
  153. package/dist/cli/commands/preset.js +297 -0
  154. package/dist/cli/commands/profile.d.ts +33 -0
  155. package/dist/cli/commands/profile.js +286 -0
  156. package/dist/cli/commands/registry.d.ts +11 -0
  157. package/dist/cli/commands/registry.js +146 -0
  158. package/dist/cli/commands/shared.d.ts +79 -0
  159. package/dist/cli/commands/shared.js +196 -0
  160. package/dist/cli/commands/teams.d.ts +8 -0
  161. package/dist/cli/commands/teams.js +169 -0
  162. package/dist/cli/commands/test.d.ts +9 -0
  163. package/dist/cli/commands/test.js +500 -0
  164. package/dist/cli/commands/upload.d.ts +8 -0
  165. package/dist/cli/commands/upload.js +223 -0
  166. package/dist/cli/commands/validate-config.d.ts +6 -0
  167. package/dist/cli/commands/validate-config.js +35 -0
  168. package/dist/cli/commands/verify.d.ts +11 -0
  169. package/dist/cli/commands/verify.js +283 -0
  170. package/dist/cli/commands/watch.d.ts +12 -0
  171. package/dist/cli/commands/watch.js +253 -0
  172. package/dist/cli/index.d.ts +3 -0
  173. package/dist/cli/index.js +178 -0
  174. package/dist/cli/interactive.d.ts +47 -0
  175. package/dist/cli/interactive.js +216 -0
  176. package/dist/cli/output/terminal-reporter.d.ts +19 -0
  177. package/dist/cli/output/terminal-reporter.js +104 -0
  178. package/dist/cli/output.d.ts +226 -0
  179. package/dist/cli/output.js +438 -0
  180. package/dist/cli/utils/env.d.ts +5 -0
  181. package/dist/cli/utils/env.js +14 -0
  182. package/dist/cli/utils/progress.d.ts +59 -0
  183. package/dist/cli/utils/progress.js +206 -0
  184. package/dist/cli/utils/server-context.d.ts +10 -0
  185. package/dist/cli/utils/server-context.js +36 -0
  186. package/dist/cloud/auth.d.ts +144 -0
  187. package/dist/cloud/auth.js +374 -0
  188. package/dist/cloud/client.d.ts +24 -0
  189. package/dist/cloud/client.js +65 -0
  190. package/dist/cloud/http-client.d.ts +38 -0
  191. package/dist/cloud/http-client.js +215 -0
  192. package/dist/cloud/index.d.ts +23 -0
  193. package/dist/cloud/index.js +25 -0
  194. package/dist/cloud/mock-client.d.ts +107 -0
  195. package/dist/cloud/mock-client.js +545 -0
  196. package/dist/cloud/types.d.ts +515 -0
  197. package/dist/cloud/types.js +15 -0
  198. package/dist/config/defaults.d.ts +160 -0
  199. package/dist/config/defaults.js +169 -0
  200. package/dist/config/loader.d.ts +24 -0
  201. package/dist/config/loader.js +122 -0
  202. package/dist/config/template.d.ts +42 -0
  203. package/dist/config/template.js +647 -0
  204. package/dist/config/validator.d.ts +2112 -0
  205. package/dist/config/validator.js +658 -0
  206. package/dist/constants/cloud.d.ts +107 -0
  207. package/dist/constants/cloud.js +110 -0
  208. package/dist/constants/core.d.ts +521 -0
  209. package/dist/constants/core.js +556 -0
  210. package/dist/constants/testing.d.ts +1283 -0
  211. package/dist/constants/testing.js +1568 -0
  212. package/dist/constants.d.ts +10 -0
  213. package/dist/constants.js +10 -0
  214. package/dist/contract/index.d.ts +6 -0
  215. package/dist/contract/index.js +5 -0
  216. package/dist/contract/validator.d.ts +177 -0
  217. package/dist/contract/validator.js +574 -0
  218. package/dist/cost/index.d.ts +6 -0
  219. package/dist/cost/index.js +5 -0
  220. package/dist/cost/tracker.d.ts +134 -0
  221. package/dist/cost/tracker.js +313 -0
  222. package/dist/discovery/discovery.d.ts +16 -0
  223. package/dist/discovery/discovery.js +173 -0
  224. package/dist/discovery/types.d.ts +51 -0
  225. package/dist/discovery/types.js +2 -0
  226. package/dist/docs/agents.d.ts +3 -0
  227. package/dist/docs/agents.js +995 -0
  228. package/dist/docs/contract.d.ts +51 -0
  229. package/dist/docs/contract.js +1681 -0
  230. package/dist/docs/generator.d.ts +4 -0
  231. package/dist/docs/generator.js +4 -0
  232. package/dist/docs/html-reporter.d.ts +9 -0
  233. package/dist/docs/html-reporter.js +757 -0
  234. package/dist/docs/index.d.ts +10 -0
  235. package/dist/docs/index.js +11 -0
  236. package/dist/docs/junit-reporter.d.ts +18 -0
  237. package/dist/docs/junit-reporter.js +210 -0
  238. package/dist/docs/report.d.ts +14 -0
  239. package/dist/docs/report.js +44 -0
  240. package/dist/docs/sarif-reporter.d.ts +19 -0
  241. package/dist/docs/sarif-reporter.js +335 -0
  242. package/dist/docs/shared.d.ts +35 -0
  243. package/dist/docs/shared.js +162 -0
  244. package/dist/docs/templates.d.ts +12 -0
  245. package/dist/docs/templates.js +76 -0
  246. package/dist/errors/index.d.ts +6 -0
  247. package/dist/errors/index.js +6 -0
  248. package/dist/errors/retry.d.ts +92 -0
  249. package/dist/errors/retry.js +323 -0
  250. package/dist/errors/types.d.ts +321 -0
  251. package/dist/errors/types.js +584 -0
  252. package/dist/index.d.ts +32 -0
  253. package/dist/index.js +32 -0
  254. package/dist/interview/dependency-resolver.d.ts +11 -0
  255. package/dist/interview/dependency-resolver.js +32 -0
  256. package/dist/interview/interviewer.d.ts +232 -0
  257. package/dist/interview/interviewer.js +1939 -0
  258. package/dist/interview/mock-response-generator.d.ts +7 -0
  259. package/dist/interview/mock-response-generator.js +102 -0
  260. package/dist/interview/orchestrator.d.ts +237 -0
  261. package/dist/interview/orchestrator.js +1296 -0
  262. package/dist/interview/rate-limiter.d.ts +15 -0
  263. package/dist/interview/rate-limiter.js +55 -0
  264. package/dist/interview/response-validator.d.ts +10 -0
  265. package/dist/interview/response-validator.js +132 -0
  266. package/dist/interview/schema-inferrer.d.ts +8 -0
  267. package/dist/interview/schema-inferrer.js +71 -0
  268. package/dist/interview/schema-test-generator.d.ts +71 -0
  269. package/dist/interview/schema-test-generator.js +834 -0
  270. package/dist/interview/smart-value-generator.d.ts +155 -0
  271. package/dist/interview/smart-value-generator.js +554 -0
  272. package/dist/interview/stateful-test-runner.d.ts +19 -0
  273. package/dist/interview/stateful-test-runner.js +106 -0
  274. package/dist/interview/types.d.ts +561 -0
  275. package/dist/interview/types.js +2 -0
  276. package/dist/llm/anthropic.d.ts +41 -0
  277. package/dist/llm/anthropic.js +355 -0
  278. package/dist/llm/client.d.ts +123 -0
  279. package/dist/llm/client.js +42 -0
  280. package/dist/llm/factory.d.ts +38 -0
  281. package/dist/llm/factory.js +145 -0
  282. package/dist/llm/fallback.d.ts +140 -0
  283. package/dist/llm/fallback.js +379 -0
  284. package/dist/llm/index.d.ts +18 -0
  285. package/dist/llm/index.js +15 -0
  286. package/dist/llm/ollama.d.ts +37 -0
  287. package/dist/llm/ollama.js +330 -0
  288. package/dist/llm/openai.d.ts +25 -0
  289. package/dist/llm/openai.js +320 -0
  290. package/dist/llm/token-budget.d.ts +161 -0
  291. package/dist/llm/token-budget.js +395 -0
  292. package/dist/logging/logger.d.ts +70 -0
  293. package/dist/logging/logger.js +130 -0
  294. package/dist/metrics/collector.d.ts +106 -0
  295. package/dist/metrics/collector.js +547 -0
  296. package/dist/metrics/index.d.ts +7 -0
  297. package/dist/metrics/index.js +7 -0
  298. package/dist/metrics/prometheus.d.ts +20 -0
  299. package/dist/metrics/prometheus.js +241 -0
  300. package/dist/metrics/types.d.ts +209 -0
  301. package/dist/metrics/types.js +5 -0
  302. package/dist/persona/builtins.d.ts +54 -0
  303. package/dist/persona/builtins.js +219 -0
  304. package/dist/persona/index.d.ts +8 -0
  305. package/dist/persona/index.js +8 -0
  306. package/dist/persona/loader.d.ts +30 -0
  307. package/dist/persona/loader.js +190 -0
  308. package/dist/persona/types.d.ts +144 -0
  309. package/dist/persona/types.js +5 -0
  310. package/dist/persona/validation.d.ts +94 -0
  311. package/dist/persona/validation.js +332 -0
  312. package/dist/prompts/index.d.ts +5 -0
  313. package/dist/prompts/index.js +5 -0
  314. package/dist/prompts/templates.d.ts +180 -0
  315. package/dist/prompts/templates.js +431 -0
  316. package/dist/registry/client.d.ts +49 -0
  317. package/dist/registry/client.js +191 -0
  318. package/dist/registry/index.d.ts +7 -0
  319. package/dist/registry/index.js +6 -0
  320. package/dist/registry/types.d.ts +140 -0
  321. package/dist/registry/types.js +6 -0
  322. package/dist/scenarios/evaluator.d.ts +43 -0
  323. package/dist/scenarios/evaluator.js +206 -0
  324. package/dist/scenarios/index.d.ts +10 -0
  325. package/dist/scenarios/index.js +9 -0
  326. package/dist/scenarios/loader.d.ts +20 -0
  327. package/dist/scenarios/loader.js +285 -0
  328. package/dist/scenarios/types.d.ts +153 -0
  329. package/dist/scenarios/types.js +8 -0
  330. package/dist/security/index.d.ts +17 -0
  331. package/dist/security/index.js +18 -0
  332. package/dist/security/payloads.d.ts +61 -0
  333. package/dist/security/payloads.js +268 -0
  334. package/dist/security/security-tester.d.ts +42 -0
  335. package/dist/security/security-tester.js +582 -0
  336. package/dist/security/types.d.ts +166 -0
  337. package/dist/security/types.js +8 -0
  338. package/dist/transport/base-transport.d.ts +59 -0
  339. package/dist/transport/base-transport.js +38 -0
  340. package/dist/transport/http-transport.d.ts +67 -0
  341. package/dist/transport/http-transport.js +238 -0
  342. package/dist/transport/mcp-client.d.ts +141 -0
  343. package/dist/transport/mcp-client.js +496 -0
  344. package/dist/transport/sse-transport.d.ts +88 -0
  345. package/dist/transport/sse-transport.js +316 -0
  346. package/dist/transport/stdio-transport.d.ts +43 -0
  347. package/dist/transport/stdio-transport.js +238 -0
  348. package/dist/transport/types.d.ts +125 -0
  349. package/dist/transport/types.js +16 -0
  350. package/dist/utils/concurrency.d.ts +123 -0
  351. package/dist/utils/concurrency.js +213 -0
  352. package/dist/utils/formatters.d.ts +16 -0
  353. package/dist/utils/formatters.js +37 -0
  354. package/dist/utils/index.d.ts +8 -0
  355. package/dist/utils/index.js +8 -0
  356. package/dist/utils/jsonpath.d.ts +87 -0
  357. package/dist/utils/jsonpath.js +326 -0
  358. package/dist/utils/markdown.d.ts +113 -0
  359. package/dist/utils/markdown.js +265 -0
  360. package/dist/utils/network.d.ts +14 -0
  361. package/dist/utils/network.js +17 -0
  362. package/dist/utils/sanitize.d.ts +92 -0
  363. package/dist/utils/sanitize.js +191 -0
  364. package/dist/utils/semantic.d.ts +194 -0
  365. package/dist/utils/semantic.js +1051 -0
  366. package/dist/utils/smart-truncate.d.ts +94 -0
  367. package/dist/utils/smart-truncate.js +361 -0
  368. package/dist/utils/timeout.d.ts +153 -0
  369. package/dist/utils/timeout.js +205 -0
  370. package/dist/utils/yaml-parser.d.ts +58 -0
  371. package/dist/utils/yaml-parser.js +86 -0
  372. package/dist/validation/index.d.ts +32 -0
  373. package/dist/validation/index.js +32 -0
  374. package/dist/validation/semantic-test-generator.d.ts +50 -0
  375. package/dist/validation/semantic-test-generator.js +176 -0
  376. package/dist/validation/semantic-types.d.ts +66 -0
  377. package/dist/validation/semantic-types.js +94 -0
  378. package/dist/validation/semantic-validator.d.ts +38 -0
  379. package/dist/validation/semantic-validator.js +340 -0
  380. package/dist/verification/index.d.ts +6 -0
  381. package/dist/verification/index.js +5 -0
  382. package/dist/verification/types.d.ts +133 -0
  383. package/dist/verification/types.js +5 -0
  384. package/dist/verification/verifier.d.ts +30 -0
  385. package/dist/verification/verifier.js +309 -0
  386. package/dist/version.d.ts +19 -0
  387. package/dist/version.js +48 -0
  388. package/dist/workflow/auto-generator.d.ts +27 -0
  389. package/dist/workflow/auto-generator.js +513 -0
  390. package/dist/workflow/discovery.d.ts +40 -0
  391. package/dist/workflow/discovery.js +195 -0
  392. package/dist/workflow/executor.d.ts +82 -0
  393. package/dist/workflow/executor.js +611 -0
  394. package/dist/workflow/index.d.ts +10 -0
  395. package/dist/workflow/index.js +10 -0
  396. package/dist/workflow/loader.d.ts +24 -0
  397. package/dist/workflow/loader.js +194 -0
  398. package/dist/workflow/state-tracker.d.ts +98 -0
  399. package/dist/workflow/state-tracker.js +424 -0
  400. package/dist/workflow/types.d.ts +337 -0
  401. package/dist/workflow/types.js +5 -0
  402. package/package.json +94 -0
  403. package/schemas/bellwether-check.schema.json +651 -0
@@ -0,0 +1,547 @@
1
+ /**
2
+ * Metrics collector for comprehensive observability.
3
+ *
4
+ * Tracks timing, token usage, errors, and costs across all operations.
5
+ */
6
+ import { getModelPricing } from '../cost/tracker.js';
7
+ import { PERCENTILES } from '../constants.js';
8
+ const DEFAULT_OPTIONS = {
9
+ maxRecords: 10000,
10
+ trackRecords: true,
11
+ };
12
+ /**
13
+ * Centralized metrics collector for observability.
14
+ */
15
+ export class MetricsCollector {
16
+ options;
17
+ // Individual records (when trackRecords is true)
18
+ tokenRecords = [];
19
+ timingRecords = [];
20
+ errorRecords = [];
21
+ costRecords = [];
22
+ // Aggregated counters (always maintained)
23
+ tokensByProviderModel = new Map();
24
+ timingByOperation = new Map();
25
+ errorsByCategory = new Map();
26
+ costByProvider = new Map();
27
+ // Interview-specific metrics
28
+ interviewMetrics = null;
29
+ constructor(options = {}) {
30
+ this.options = { ...DEFAULT_OPTIONS, ...options };
31
+ }
32
+ /**
33
+ * Start tracking an interview.
34
+ */
35
+ startInterview() {
36
+ this.interviewMetrics = {
37
+ startedAt: new Date(),
38
+ toolsDiscovered: 0,
39
+ questionsGenerated: 0,
40
+ toolCallsMade: 0,
41
+ toolCallsSucceeded: 0,
42
+ toolCallsFailed: 0,
43
+ personasUsed: 0,
44
+ llmCallsMade: 0,
45
+ totalInputTokens: 0,
46
+ totalOutputTokens: 0,
47
+ totalCostUSD: 0,
48
+ errorsByCategory: {},
49
+ };
50
+ }
51
+ /**
52
+ * End interview tracking.
53
+ */
54
+ endInterview() {
55
+ if (this.interviewMetrics) {
56
+ this.interviewMetrics.endedAt = new Date();
57
+ this.interviewMetrics.totalDurationMs =
58
+ this.interviewMetrics.endedAt.getTime() - this.interviewMetrics.startedAt.getTime();
59
+ }
60
+ return this.interviewMetrics;
61
+ }
62
+ /**
63
+ * Record token usage from an LLM call.
64
+ */
65
+ recordTokenUsage(provider, model, inputTokens, outputTokens, operation) {
66
+ const record = {
67
+ provider,
68
+ model,
69
+ inputTokens,
70
+ outputTokens,
71
+ timestamp: new Date(),
72
+ operation,
73
+ };
74
+ if (this.options.trackRecords) {
75
+ this.tokenRecords.push(record);
76
+ this.trimRecords('token');
77
+ }
78
+ // Update aggregates
79
+ const key = `${provider}:${model}`;
80
+ const existing = this.tokensByProviderModel.get(key) ?? { input: 0, output: 0, calls: 0 };
81
+ existing.input += inputTokens;
82
+ existing.output += outputTokens;
83
+ existing.calls++;
84
+ this.tokensByProviderModel.set(key, existing);
85
+ // Update cost
86
+ const pricing = getModelPricing(model);
87
+ if (pricing) {
88
+ const inputCost = (inputTokens / 1_000_000) * pricing.input;
89
+ const outputCost = (outputTokens / 1_000_000) * pricing.output;
90
+ const totalCost = inputCost + outputCost;
91
+ const costRecord = {
92
+ provider,
93
+ model,
94
+ inputCost,
95
+ outputCost,
96
+ totalCost,
97
+ timestamp: new Date(),
98
+ };
99
+ if (this.options.trackRecords) {
100
+ this.costRecords.push(costRecord);
101
+ this.trimRecords('cost');
102
+ }
103
+ const providerCost = this.costByProvider.get(provider) ?? 0;
104
+ this.costByProvider.set(provider, providerCost + totalCost);
105
+ // Update interview metrics
106
+ if (this.interviewMetrics) {
107
+ this.interviewMetrics.totalCostUSD += totalCost;
108
+ }
109
+ }
110
+ // Update interview metrics
111
+ if (this.interviewMetrics) {
112
+ this.interviewMetrics.totalInputTokens += inputTokens;
113
+ this.interviewMetrics.totalOutputTokens += outputTokens;
114
+ this.interviewMetrics.llmCallsMade++;
115
+ }
116
+ }
117
+ /**
118
+ * Record operation timing.
119
+ */
120
+ recordTiming(operation, durationMs, success, metadata) {
121
+ const record = {
122
+ operation,
123
+ durationMs,
124
+ success,
125
+ timestamp: new Date(),
126
+ metadata,
127
+ };
128
+ if (this.options.trackRecords) {
129
+ this.timingRecords.push(record);
130
+ this.trimRecords('timing');
131
+ }
132
+ // Update aggregates
133
+ const existing = this.timingByOperation.get(operation) ?? { durations: [], successes: 0, failures: 0 };
134
+ existing.durations.push(durationMs);
135
+ if (success) {
136
+ existing.successes++;
137
+ }
138
+ else {
139
+ existing.failures++;
140
+ }
141
+ this.timingByOperation.set(operation, existing);
142
+ // Update interview metrics for tool calls
143
+ if (this.interviewMetrics && operation === 'tool_call') {
144
+ this.interviewMetrics.toolCallsMade++;
145
+ if (success) {
146
+ this.interviewMetrics.toolCallsSucceeded++;
147
+ }
148
+ else {
149
+ this.interviewMetrics.toolCallsFailed++;
150
+ }
151
+ }
152
+ }
153
+ /**
154
+ * Record an error.
155
+ */
156
+ recordError(category, code, message, retryable, operation) {
157
+ const record = {
158
+ category,
159
+ code,
160
+ message,
161
+ timestamp: new Date(),
162
+ retryable,
163
+ operation,
164
+ };
165
+ if (this.options.trackRecords) {
166
+ this.errorRecords.push(record);
167
+ this.trimRecords('error');
168
+ }
169
+ // Update aggregates
170
+ const existing = this.errorsByCategory.get(category) ?? { total: 0, retryable: 0, terminal: 0 };
171
+ existing.total++;
172
+ if (retryable) {
173
+ existing.retryable++;
174
+ }
175
+ else {
176
+ existing.terminal++;
177
+ }
178
+ this.errorsByCategory.set(category, existing);
179
+ // Update interview metrics
180
+ if (this.interviewMetrics) {
181
+ this.interviewMetrics.errorsByCategory[category] =
182
+ (this.interviewMetrics.errorsByCategory[category] ?? 0) + 1;
183
+ }
184
+ }
185
+ /**
186
+ * Update interview-specific counters.
187
+ */
188
+ updateInterviewCounters(updates) {
189
+ if (this.interviewMetrics) {
190
+ if (updates.toolsDiscovered !== undefined) {
191
+ this.interviewMetrics.toolsDiscovered = updates.toolsDiscovered;
192
+ }
193
+ if (updates.questionsGenerated !== undefined) {
194
+ this.interviewMetrics.questionsGenerated += updates.questionsGenerated;
195
+ }
196
+ if (updates.personasUsed !== undefined) {
197
+ this.interviewMetrics.personasUsed = updates.personasUsed;
198
+ }
199
+ }
200
+ }
201
+ /**
202
+ * Create a timed operation wrapper.
203
+ */
204
+ async time(operation, fn, metadata) {
205
+ const startTime = Date.now();
206
+ try {
207
+ const result = await fn();
208
+ this.recordTiming(operation, Date.now() - startTime, true, metadata);
209
+ return result;
210
+ }
211
+ catch (error) {
212
+ this.recordTiming(operation, Date.now() - startTime, false, metadata);
213
+ throw error;
214
+ }
215
+ }
216
+ /**
217
+ * Get current interview metrics.
218
+ */
219
+ getInterviewMetrics() {
220
+ return this.interviewMetrics;
221
+ }
222
+ /**
223
+ * Get aggregated metrics for a time period.
224
+ */
225
+ getAggregatedMetrics(periodStart, periodEnd) {
226
+ const start = periodStart ?? new Date(0);
227
+ const end = periodEnd ?? new Date();
228
+ // Filter records by time period if tracking individual records
229
+ const filteredTokenRecords = this.options.trackRecords
230
+ ? this.tokenRecords.filter(r => r.timestamp >= start && r.timestamp <= end)
231
+ : [];
232
+ const filteredTimingRecords = this.options.trackRecords
233
+ ? this.timingRecords.filter(r => r.timestamp >= start && r.timestamp <= end)
234
+ : [];
235
+ const filteredErrorRecords = this.options.trackRecords
236
+ ? this.errorRecords.filter(r => r.timestamp >= start && r.timestamp <= end)
237
+ : [];
238
+ // Calculate token usage stats
239
+ const tokenUsage = this.options.trackRecords
240
+ ? this.calculateTokenUsageFromRecords(filteredTokenRecords)
241
+ : this.calculateTokenUsageFromAggregates();
242
+ // Calculate operation stats
243
+ const operationStats = this.options.trackRecords
244
+ ? this.calculateOperationStatsFromRecords(filteredTimingRecords)
245
+ : this.calculateOperationStatsFromAggregates();
246
+ // Calculate error stats
247
+ const errorStats = this.options.trackRecords
248
+ ? this.calculateErrorStatsFromRecords(filteredErrorRecords)
249
+ : this.calculateErrorStatsFromAggregates();
250
+ // Calculate total cost
251
+ let totalCostUSD = 0;
252
+ const costByProviderArr = [];
253
+ for (const [provider, cost] of this.costByProvider) {
254
+ totalCostUSD += cost;
255
+ costByProviderArr.push({ provider, costUSD: cost });
256
+ }
257
+ return {
258
+ periodStart: start,
259
+ periodEnd: end,
260
+ tokenUsage,
261
+ operationStats,
262
+ errorStats,
263
+ totalCostUSD,
264
+ costByProvider: costByProviderArr,
265
+ };
266
+ }
267
+ /**
268
+ * Get dashboard-compatible metrics.
269
+ */
270
+ getDashboardMetrics() {
271
+ const interview = this.interviewMetrics;
272
+ const aggregated = this.getAggregatedMetrics();
273
+ // Calculate progress
274
+ let progress = 0;
275
+ let status = 'running';
276
+ if (interview) {
277
+ if (interview.endedAt) {
278
+ const hasErrors = Object.values(interview.errorsByCategory).some(c => c > 0);
279
+ status = hasErrors ? 'failed' : 'completed';
280
+ progress = 100;
281
+ }
282
+ else if (interview.toolsDiscovered > 0) {
283
+ // Estimate progress based on tool calls vs expected
284
+ const expectedCalls = interview.toolsDiscovered * 5; // Rough estimate
285
+ progress = Math.min(99, Math.round((interview.toolCallsMade / expectedCalls) * 100));
286
+ }
287
+ }
288
+ // Calculate average latencies
289
+ const llmStats = aggregated.operationStats.find(s => s.operation === 'llm_call');
290
+ const toolStats = aggregated.operationStats.find(s => s.operation === 'tool_call');
291
+ // Calculate success rate
292
+ let totalOps = 0;
293
+ let successOps = 0;
294
+ for (const stat of aggregated.operationStats) {
295
+ totalOps += stat.count;
296
+ successOps += stat.successCount;
297
+ }
298
+ const successRate = totalOps > 0 ? (successOps / totalOps) * 100 : 100;
299
+ // Calculate total errors
300
+ let errorsTotal = 0;
301
+ for (const stat of aggregated.errorStats) {
302
+ errorsTotal += stat.count;
303
+ }
304
+ // Build provider breakdown
305
+ const providers = [];
306
+ for (const usage of aggregated.tokenUsage) {
307
+ const existing = providers.find(p => p.name === usage.provider);
308
+ if (existing) {
309
+ existing.calls += usage.callCount;
310
+ existing.tokens += usage.totalInputTokens + usage.totalOutputTokens;
311
+ }
312
+ else {
313
+ providers.push({
314
+ name: usage.provider,
315
+ calls: usage.callCount,
316
+ tokens: usage.totalInputTokens + usage.totalOutputTokens,
317
+ errors: 0, // Would need to track errors by provider
318
+ avgLatencyMs: llmStats?.avgDurationMs ?? 0,
319
+ });
320
+ }
321
+ }
322
+ return {
323
+ timestamp: new Date().toISOString(),
324
+ interview: {
325
+ status,
326
+ progress,
327
+ toolsTotal: interview?.toolsDiscovered ?? 0,
328
+ toolsCompleted: interview?.toolCallsSucceeded ?? 0,
329
+ questionsTotal: interview?.questionsGenerated ?? 0,
330
+ questionsCompleted: interview?.toolCallsMade ?? 0,
331
+ },
332
+ tokens: {
333
+ input: interview?.totalInputTokens ?? 0,
334
+ output: interview?.totalOutputTokens ?? 0,
335
+ total: (interview?.totalInputTokens ?? 0) + (interview?.totalOutputTokens ?? 0),
336
+ },
337
+ cost: {
338
+ current: aggregated.totalCostUSD,
339
+ projected: this.calculateProjectedCost(),
340
+ currency: 'USD',
341
+ },
342
+ performance: {
343
+ avgLLMLatencyMs: llmStats?.avgDurationMs ?? 0,
344
+ avgToolLatencyMs: toolStats?.avgDurationMs ?? 0,
345
+ errorsTotal,
346
+ successRate,
347
+ },
348
+ providers,
349
+ };
350
+ }
351
+ /**
352
+ * Reset all metrics.
353
+ */
354
+ reset() {
355
+ this.tokenRecords = [];
356
+ this.timingRecords = [];
357
+ this.errorRecords = [];
358
+ this.costRecords = [];
359
+ this.tokensByProviderModel.clear();
360
+ this.timingByOperation.clear();
361
+ this.errorsByCategory.clear();
362
+ this.costByProvider.clear();
363
+ this.interviewMetrics = null;
364
+ }
365
+ /**
366
+ * Get raw records for external processing.
367
+ */
368
+ getRawRecords() {
369
+ return {
370
+ tokens: [...this.tokenRecords],
371
+ timing: [...this.timingRecords],
372
+ errors: [...this.errorRecords],
373
+ costs: [...this.costRecords],
374
+ };
375
+ }
376
+ // Private helper methods
377
+ trimRecords(type) {
378
+ const maxRecords = this.options.maxRecords;
379
+ switch (type) {
380
+ case 'token':
381
+ if (this.tokenRecords.length > maxRecords) {
382
+ this.tokenRecords = this.tokenRecords.slice(-maxRecords);
383
+ }
384
+ break;
385
+ case 'timing':
386
+ if (this.timingRecords.length > maxRecords) {
387
+ this.timingRecords = this.timingRecords.slice(-maxRecords);
388
+ }
389
+ break;
390
+ case 'error':
391
+ if (this.errorRecords.length > maxRecords) {
392
+ this.errorRecords = this.errorRecords.slice(-maxRecords);
393
+ }
394
+ break;
395
+ case 'cost':
396
+ if (this.costRecords.length > maxRecords) {
397
+ this.costRecords = this.costRecords.slice(-maxRecords);
398
+ }
399
+ break;
400
+ }
401
+ }
402
+ calculateTokenUsageFromRecords(records) {
403
+ const byKey = new Map();
404
+ for (const record of records) {
405
+ const key = `${record.provider}:${record.model}`;
406
+ const existing = byKey.get(key) ?? {
407
+ provider: record.provider,
408
+ model: record.model,
409
+ input: 0,
410
+ output: 0,
411
+ calls: 0,
412
+ };
413
+ existing.input += record.inputTokens;
414
+ existing.output += record.outputTokens;
415
+ existing.calls++;
416
+ byKey.set(key, existing);
417
+ }
418
+ return Array.from(byKey.values()).map(v => ({
419
+ provider: v.provider,
420
+ model: v.model,
421
+ totalInputTokens: v.input,
422
+ totalOutputTokens: v.output,
423
+ callCount: v.calls,
424
+ }));
425
+ }
426
+ calculateTokenUsageFromAggregates() {
427
+ return Array.from(this.tokensByProviderModel.entries()).map(([key, v]) => {
428
+ const [provider, model] = key.split(':');
429
+ return {
430
+ provider,
431
+ model,
432
+ totalInputTokens: v.input,
433
+ totalOutputTokens: v.output,
434
+ callCount: v.calls,
435
+ };
436
+ });
437
+ }
438
+ calculateOperationStatsFromRecords(records) {
439
+ const byOp = new Map();
440
+ for (const record of records) {
441
+ const existing = byOp.get(record.operation) ?? { durations: [], successes: 0, failures: 0 };
442
+ existing.durations.push(record.durationMs);
443
+ if (record.success) {
444
+ existing.successes++;
445
+ }
446
+ else {
447
+ existing.failures++;
448
+ }
449
+ byOp.set(record.operation, existing);
450
+ }
451
+ return this.convertOperationStats(byOp);
452
+ }
453
+ calculateOperationStatsFromAggregates() {
454
+ return this.convertOperationStats(this.timingByOperation);
455
+ }
456
+ convertOperationStats(byOp) {
457
+ const results = [];
458
+ for (const [operation, data] of byOp) {
459
+ const sorted = [...data.durations].sort((a, b) => a - b);
460
+ const count = sorted.length;
461
+ if (count === 0)
462
+ continue;
463
+ const sum = sorted.reduce((a, b) => a + b, 0);
464
+ const avg = sum / count;
465
+ const min = sorted[0];
466
+ const max = sorted[count - 1];
467
+ const p50 = sorted[Math.floor(count * PERCENTILES.P50)];
468
+ const p95 = sorted[Math.floor(count * PERCENTILES.P95)];
469
+ const p99 = sorted[Math.floor(count * PERCENTILES.P99)];
470
+ results.push({
471
+ operation: operation,
472
+ count,
473
+ successCount: data.successes,
474
+ failureCount: data.failures,
475
+ avgDurationMs: Math.round(avg),
476
+ minDurationMs: min,
477
+ maxDurationMs: max,
478
+ p50DurationMs: p50,
479
+ p95DurationMs: p95,
480
+ p99DurationMs: p99,
481
+ });
482
+ }
483
+ return results;
484
+ }
485
+ calculateErrorStatsFromRecords(records) {
486
+ const byCategory = new Map();
487
+ for (const record of records) {
488
+ const existing = byCategory.get(record.category) ?? { total: 0, retryable: 0, terminal: 0 };
489
+ existing.total++;
490
+ if (record.retryable) {
491
+ existing.retryable++;
492
+ }
493
+ else {
494
+ existing.terminal++;
495
+ }
496
+ byCategory.set(record.category, existing);
497
+ }
498
+ return Array.from(byCategory.entries()).map(([category, data]) => ({
499
+ category,
500
+ count: data.total,
501
+ retryableCount: data.retryable,
502
+ terminalCount: data.terminal,
503
+ }));
504
+ }
505
+ calculateErrorStatsFromAggregates() {
506
+ return Array.from(this.errorsByCategory.entries()).map(([category, data]) => ({
507
+ category,
508
+ count: data.total,
509
+ retryableCount: data.retryable,
510
+ terminalCount: data.terminal,
511
+ }));
512
+ }
513
+ calculateProjectedCost() {
514
+ if (!this.interviewMetrics)
515
+ return 0;
516
+ const current = this.interviewMetrics.totalCostUSD;
517
+ const toolsDone = this.interviewMetrics.toolCallsMade;
518
+ const toolsTotal = this.interviewMetrics.toolsDiscovered * 5; // Rough estimate per persona
519
+ if (toolsDone === 0 || toolsTotal === 0)
520
+ return current;
521
+ const progressRatio = toolsDone / toolsTotal;
522
+ if (progressRatio >= 1)
523
+ return current;
524
+ return current / progressRatio;
525
+ }
526
+ }
527
+ /**
528
+ * Global metrics collector instance.
529
+ */
530
+ let globalCollector = null;
531
+ /**
532
+ * Get or create the global metrics collector.
533
+ */
534
+ export function getMetricsCollector(options) {
535
+ if (!globalCollector) {
536
+ globalCollector = new MetricsCollector(options);
537
+ }
538
+ return globalCollector;
539
+ }
540
+ /**
541
+ * Reset the global metrics collector.
542
+ */
543
+ export function resetMetricsCollector() {
544
+ globalCollector?.reset();
545
+ globalCollector = null;
546
+ }
547
+ //# sourceMappingURL=collector.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Metrics collection and export module.
3
+ */
4
+ export * from './types.js';
5
+ export * from './collector.js';
6
+ export * from './prometheus.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Metrics collection and export module.
3
+ */
4
+ export * from './types.js';
5
+ export * from './collector.js';
6
+ export * from './prometheus.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Prometheus metrics exporter.
3
+ *
4
+ * Exports metrics in Prometheus text format for scraping.
5
+ */
6
+ import type { MetricsCollector } from './collector.js';
7
+ import type { PrometheusMetric } from './types.js';
8
+ /**
9
+ * Export metrics in Prometheus text format.
10
+ */
11
+ export declare function exportPrometheusMetrics(collector: MetricsCollector): string;
12
+ /**
13
+ * Export metrics as JSON for dashboard consumption.
14
+ */
15
+ export declare function exportMetricsJSON(collector: MetricsCollector): string;
16
+ /**
17
+ * Get metric definitions for documentation.
18
+ */
19
+ export declare function getMetricDefinitions(): PrometheusMetric[];
20
+ //# sourceMappingURL=prometheus.d.ts.map