@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,395 @@
1
+ /**
2
+ * Token budget enforcement for LLM API calls.
3
+ *
4
+ * Provides pre-estimation, budget tracking, context window management,
5
+ * and graceful truncation.
6
+ */
7
+ import { createLogger } from '../logging/logger.js';
8
+ import { MATH_FACTORS } from '../constants.js';
9
+ const logger = createLogger({ name: 'token-budget' });
10
+ /**
11
+ * Context window sizes for different models (in tokens).
12
+ */
13
+ const CONTEXT_WINDOWS = {
14
+ // OpenAI GPT-5 series
15
+ 'gpt-5.2': 256_000,
16
+ 'gpt-5.1': 256_000,
17
+ 'gpt-5': 200_000,
18
+ 'gpt-5-mini': 128_000,
19
+ 'gpt-5-nano': 64_000,
20
+ // OpenAI GPT-4 series
21
+ 'gpt-4.1': 128_000,
22
+ 'gpt-4.1-mini': 128_000,
23
+ 'gpt-4.1-nano': 64_000,
24
+ 'gpt-4o': 128_000,
25
+ 'gpt-4o-mini': 128_000,
26
+ 'gpt-4-turbo': 128_000,
27
+ 'gpt-4': 8_000,
28
+ 'gpt-3.5-turbo': 16_000,
29
+ // Anthropic Claude 4.5
30
+ 'claude-opus-4-5': 200_000,
31
+ 'claude-opus-4-5-20251101': 200_000,
32
+ 'claude-sonnet-4-5': 200_000,
33
+ 'claude-sonnet-4-5-20250929': 200_000,
34
+ 'claude-haiku-4-5': 200_000,
35
+ 'claude-haiku-4-5-20251001': 200_000,
36
+ // Anthropic Claude 4
37
+ 'claude-opus-4-20250514': 200_000,
38
+ 'claude-sonnet-4-20250514': 200_000,
39
+ // Anthropic Claude 3.x
40
+ 'claude-3-5-sonnet-20241022': 200_000,
41
+ 'claude-3-5-haiku-20241022': 200_000,
42
+ 'claude-3-opus-20240229': 200_000,
43
+ 'claude-3-sonnet-20240229': 200_000,
44
+ 'claude-3-haiku-20240307': 200_000,
45
+ // Ollama (varies by model, using conservative defaults)
46
+ 'llama3.2': 128_000,
47
+ 'llama3.1': 128_000,
48
+ 'mixtral': 32_000,
49
+ 'codellama': 16_000,
50
+ };
51
+ /**
52
+ * Default context window for unknown models.
53
+ */
54
+ const DEFAULT_CONTEXT_WINDOW = 16_000;
55
+ const DEFAULT_OPTIONS = {
56
+ maxTotalTokens: 1_000_000, // 1M tokens default budget
57
+ maxInputTokensPerRequest: 100_000,
58
+ maxOutputTokensPerRequest: 8_000,
59
+ warningThreshold: MATH_FACTORS.WORD_BOUNDARY_THRESHOLD,
60
+ outputReserve: 4_000,
61
+ };
62
+ /**
63
+ * Estimate tokens from text using a character-based heuristic.
64
+ * This is a rough approximation (~4 characters per token for English text).
65
+ */
66
+ export function estimateTokens(text) {
67
+ if (!text)
68
+ return 0;
69
+ // More accurate estimation considering:
70
+ // - Whitespace tokens
71
+ // - Special characters
72
+ // - Code tends to have more tokens per character
73
+ const chars = text.length;
74
+ const words = text.split(/\s+/).filter(w => w.length > 0).length;
75
+ const specialChars = (text.match(/[{}[\]()<>:;,."'`]/g) || []).length;
76
+ // Weighted estimate
77
+ const baseTokens = chars / 4;
78
+ const wordAdjustment = words * 0.3;
79
+ const specialAdjustment = specialChars * MATH_FACTORS.SPECIAL_CHAR_MULTIPLIER;
80
+ return Math.ceil(baseTokens + wordAdjustment + specialAdjustment);
81
+ }
82
+ /**
83
+ * Estimate tokens for a message array.
84
+ */
85
+ export function estimateMessagesTokens(messages) {
86
+ let total = 0;
87
+ for (const msg of messages) {
88
+ // Role overhead (~4 tokens per message for role/formatting)
89
+ total += 4;
90
+ total += estimateTokens(msg.content);
91
+ }
92
+ // Add overhead for message structure
93
+ total += 3;
94
+ return total;
95
+ }
96
+ /**
97
+ * Get context window size for a model.
98
+ */
99
+ export function getContextWindow(model) {
100
+ // Try exact match first
101
+ if (model in CONTEXT_WINDOWS) {
102
+ return CONTEXT_WINDOWS[model];
103
+ }
104
+ // Try prefix matching for versioned models
105
+ for (const [key, value] of Object.entries(CONTEXT_WINDOWS)) {
106
+ if (model.startsWith(key)) {
107
+ return value;
108
+ }
109
+ }
110
+ return DEFAULT_CONTEXT_WINDOW;
111
+ }
112
+ /**
113
+ * Estimate tokens and check against context window.
114
+ */
115
+ export function estimateWithContext(text, model, outputReserve = DEFAULT_OPTIONS.outputReserve) {
116
+ const tokens = typeof text === 'string'
117
+ ? estimateTokens(text)
118
+ : estimateMessagesTokens(text);
119
+ const contextWindow = getContextWindow(model);
120
+ const availableForInput = contextWindow - outputReserve;
121
+ const availableForOutput = Math.max(0, contextWindow - tokens);
122
+ return {
123
+ tokens,
124
+ exceedsContext: tokens > availableForInput,
125
+ contextWindow,
126
+ availableForOutput,
127
+ };
128
+ }
129
+ /**
130
+ * Truncate messages to fit within token budget using sliding window.
131
+ * Keeps system message and most recent messages.
132
+ */
133
+ export function truncateMessages(messages, maxTokens, options = {}) {
134
+ const { keepSystemMessage = true, minMessages = 2 } = options;
135
+ if (messages.length === 0)
136
+ return [];
137
+ // Separate system message from conversation
138
+ let systemMessage = null;
139
+ let conversation = [];
140
+ if (keepSystemMessage && messages[0]?.role === 'system') {
141
+ systemMessage = messages[0];
142
+ conversation = messages.slice(1);
143
+ }
144
+ else {
145
+ conversation = [...messages];
146
+ }
147
+ // Calculate system message tokens
148
+ const systemTokens = systemMessage ? estimateTokens(systemMessage.content) + 4 : 0;
149
+ const availableTokens = maxTokens - systemTokens;
150
+ if (availableTokens <= 0) {
151
+ // System message alone exceeds budget - truncate it
152
+ if (systemMessage) {
153
+ const truncatedSystem = truncateText(systemMessage.content, maxTokens - 10);
154
+ return [{ role: 'system', content: truncatedSystem }];
155
+ }
156
+ return [];
157
+ }
158
+ // Use sliding window - keep most recent messages that fit
159
+ const result = [];
160
+ let currentTokens = 0;
161
+ // Work backwards from most recent
162
+ for (let i = conversation.length - 1; i >= 0; i--) {
163
+ const msg = conversation[i];
164
+ const msgTokens = estimateTokens(msg.content) + 4;
165
+ if (currentTokens + msgTokens <= availableTokens || result.length < minMessages) {
166
+ result.unshift(msg);
167
+ currentTokens += msgTokens;
168
+ }
169
+ else {
170
+ break;
171
+ }
172
+ }
173
+ // Add system message back at the start
174
+ if (systemMessage) {
175
+ result.unshift(systemMessage);
176
+ }
177
+ return result;
178
+ }
179
+ /**
180
+ * Truncate text to approximately fit within token budget.
181
+ */
182
+ export function truncateText(text, maxTokens) {
183
+ const estimated = estimateTokens(text);
184
+ if (estimated <= maxTokens)
185
+ return text;
186
+ // Calculate approximate character limit
187
+ const ratio = maxTokens / estimated;
188
+ const charLimit = Math.floor(text.length * ratio * MATH_FACTORS.TOKEN_SAFETY_MARGIN); // 5% safety margin
189
+ // Try to truncate at word boundary
190
+ let truncated = text.slice(0, charLimit);
191
+ const lastSpace = truncated.lastIndexOf(' ');
192
+ if (lastSpace > charLimit * MATH_FACTORS.WORD_BOUNDARY_THRESHOLD) {
193
+ truncated = truncated.slice(0, lastSpace);
194
+ }
195
+ return truncated + '...';
196
+ }
197
+ /**
198
+ * Token budget tracker for a session.
199
+ */
200
+ export class TokenBudgetTracker {
201
+ options;
202
+ onBudgetWarning;
203
+ onBudgetExceeded;
204
+ totalInputTokens = 0;
205
+ totalOutputTokens = 0;
206
+ warningEmitted = false;
207
+ constructor(options = {}) {
208
+ this.options = { ...DEFAULT_OPTIONS, ...options };
209
+ this.onBudgetWarning = options.onBudgetWarning;
210
+ this.onBudgetExceeded = options.onBudgetExceeded;
211
+ }
212
+ /**
213
+ * Record token usage.
214
+ */
215
+ recordUsage(inputTokens, outputTokens) {
216
+ this.totalInputTokens += inputTokens;
217
+ this.totalOutputTokens += outputTokens;
218
+ const status = this.getStatus();
219
+ // Check for budget exceeded
220
+ if (status.budgetExceeded && this.onBudgetExceeded) {
221
+ this.onBudgetExceeded(status.totalUsed, status.totalBudget);
222
+ }
223
+ // Check for warning threshold
224
+ else if (status.warningTriggered && !this.warningEmitted && this.onBudgetWarning) {
225
+ this.onBudgetWarning(status.totalUsed, status.totalBudget, status.percentageUsed);
226
+ this.warningEmitted = true;
227
+ }
228
+ }
229
+ /**
230
+ * Get current budget status.
231
+ */
232
+ getStatus() {
233
+ const totalUsed = this.totalInputTokens + this.totalOutputTokens;
234
+ const percentageUsed = (totalUsed / this.options.maxTotalTokens) * 100;
235
+ return {
236
+ totalUsed,
237
+ totalBudget: this.options.maxTotalTokens,
238
+ percentageUsed,
239
+ warningTriggered: percentageUsed >= this.options.warningThreshold * 100,
240
+ budgetExceeded: totalUsed >= this.options.maxTotalTokens,
241
+ remaining: Math.max(0, this.options.maxTotalTokens - totalUsed),
242
+ };
243
+ }
244
+ /**
245
+ * Check if a request would exceed the budget.
246
+ */
247
+ wouldExceedBudget(estimatedInputTokens, expectedOutputTokens = 1000) {
248
+ const status = this.getStatus();
249
+ return (status.totalUsed + estimatedInputTokens + expectedOutputTokens) > this.options.maxTotalTokens;
250
+ }
251
+ /**
252
+ * Get maximum safe input tokens for next request.
253
+ */
254
+ getMaxSafeInputTokens() {
255
+ const status = this.getStatus();
256
+ const remaining = status.remaining - this.options.outputReserve;
257
+ return Math.min(remaining, this.options.maxInputTokensPerRequest);
258
+ }
259
+ /**
260
+ * Reset the tracker.
261
+ */
262
+ reset() {
263
+ this.totalInputTokens = 0;
264
+ this.totalOutputTokens = 0;
265
+ this.warningEmitted = false;
266
+ }
267
+ }
268
+ /**
269
+ * Budget-aware error.
270
+ */
271
+ export class TokenBudgetExceededError extends Error {
272
+ used;
273
+ budget;
274
+ requested;
275
+ constructor(used, budget, requested) {
276
+ super(`Token budget exceeded: used ${used} + requested ${requested} > budget ${budget}`);
277
+ this.name = 'TokenBudgetExceededError';
278
+ this.used = used;
279
+ this.budget = budget;
280
+ this.requested = requested;
281
+ }
282
+ }
283
+ /**
284
+ * Wrapper that enforces token budget on an LLM client.
285
+ */
286
+ export class BudgetEnforcedLLMClient {
287
+ client;
288
+ tracker;
289
+ model;
290
+ strict;
291
+ constructor(client, options = {}) {
292
+ this.client = client;
293
+ this.tracker = new TokenBudgetTracker(options);
294
+ this.model = options.model ?? client.getProviderInfo().defaultModel;
295
+ this.strict = options.strict ?? false;
296
+ }
297
+ getProviderInfo() {
298
+ return this.client.getProviderInfo();
299
+ }
300
+ async chat(messages, options) {
301
+ const model = options?.model ?? this.model;
302
+ const estimate = estimateWithContext(messages, model);
303
+ // Check if we need to truncate
304
+ if (estimate.exceedsContext || this.tracker.wouldExceedBudget(estimate.tokens)) {
305
+ if (this.strict) {
306
+ const status = this.tracker.getStatus();
307
+ throw new TokenBudgetExceededError(status.totalUsed, status.totalBudget, estimate.tokens);
308
+ }
309
+ // Truncate messages to fit
310
+ const maxTokens = Math.min(estimate.contextWindow - (options?.maxTokens ?? DEFAULT_OPTIONS.outputReserve), this.tracker.getMaxSafeInputTokens());
311
+ logger.warn({ originalTokens: estimate.tokens, maxTokens }, 'Truncating messages to fit budget');
312
+ messages = truncateMessages(messages, maxTokens);
313
+ }
314
+ const result = await this.client.chat(messages, options);
315
+ // Estimate output tokens and record
316
+ const outputTokens = estimateTokens(result);
317
+ const inputTokens = estimateMessagesTokens(messages);
318
+ this.tracker.recordUsage(inputTokens, outputTokens);
319
+ return result;
320
+ }
321
+ async complete(prompt, options) {
322
+ const model = options?.model ?? this.model;
323
+ const estimate = estimateWithContext(prompt, model);
324
+ if (estimate.exceedsContext || this.tracker.wouldExceedBudget(estimate.tokens)) {
325
+ if (this.strict) {
326
+ const status = this.tracker.getStatus();
327
+ throw new TokenBudgetExceededError(status.totalUsed, status.totalBudget, estimate.tokens);
328
+ }
329
+ const maxTokens = Math.min(estimate.contextWindow - (options?.maxTokens ?? DEFAULT_OPTIONS.outputReserve), this.tracker.getMaxSafeInputTokens());
330
+ logger.warn({ originalTokens: estimate.tokens, maxTokens }, 'Truncating prompt to fit budget');
331
+ prompt = truncateText(prompt, maxTokens);
332
+ }
333
+ const result = await this.client.complete(prompt, options);
334
+ const outputTokens = estimateTokens(result);
335
+ const inputTokens = estimateTokens(prompt);
336
+ this.tracker.recordUsage(inputTokens, outputTokens);
337
+ return result;
338
+ }
339
+ async stream(prompt, options) {
340
+ const model = options?.model ?? this.model;
341
+ const estimate = estimateWithContext(prompt, model);
342
+ if (estimate.exceedsContext || this.tracker.wouldExceedBudget(estimate.tokens)) {
343
+ if (this.strict) {
344
+ const status = this.tracker.getStatus();
345
+ throw new TokenBudgetExceededError(status.totalUsed, status.totalBudget, estimate.tokens);
346
+ }
347
+ const maxTokens = Math.min(estimate.contextWindow - (options?.maxTokens ?? DEFAULT_OPTIONS.outputReserve), this.tracker.getMaxSafeInputTokens());
348
+ prompt = truncateText(prompt, maxTokens);
349
+ }
350
+ const result = await this.client.stream(prompt, options);
351
+ const outputTokens = estimateTokens(result.text);
352
+ const inputTokens = estimateTokens(prompt);
353
+ this.tracker.recordUsage(inputTokens, outputTokens);
354
+ return result;
355
+ }
356
+ async streamChat(messages, options) {
357
+ const model = options?.model ?? this.model;
358
+ const estimate = estimateWithContext(messages, model);
359
+ if (estimate.exceedsContext || this.tracker.wouldExceedBudget(estimate.tokens)) {
360
+ if (this.strict) {
361
+ const status = this.tracker.getStatus();
362
+ throw new TokenBudgetExceededError(status.totalUsed, status.totalBudget, estimate.tokens);
363
+ }
364
+ const maxTokens = Math.min(estimate.contextWindow - (options?.maxTokens ?? DEFAULT_OPTIONS.outputReserve), this.tracker.getMaxSafeInputTokens());
365
+ messages = truncateMessages(messages, maxTokens);
366
+ }
367
+ const result = await this.client.streamChat(messages, options);
368
+ const outputTokens = estimateTokens(result.text);
369
+ const inputTokens = estimateMessagesTokens(messages);
370
+ this.tracker.recordUsage(inputTokens, outputTokens);
371
+ return result;
372
+ }
373
+ parseJSON(response) {
374
+ return this.client.parseJSON(response);
375
+ }
376
+ /**
377
+ * Get current budget status.
378
+ */
379
+ getBudgetStatus() {
380
+ return this.tracker.getStatus();
381
+ }
382
+ /**
383
+ * Reset the budget tracker.
384
+ */
385
+ resetBudget() {
386
+ this.tracker.reset();
387
+ }
388
+ }
389
+ /**
390
+ * Create a budget-enforced wrapper around an LLM client.
391
+ */
392
+ export function withTokenBudget(client, options) {
393
+ return new BudgetEnforcedLLMClient(client, options);
394
+ }
395
+ //# sourceMappingURL=token-budget.js.map
@@ -0,0 +1,70 @@
1
+ import { Logger as PinoLogger } from 'pino';
2
+ /**
3
+ * Log levels supported by Bellwether.
4
+ */
5
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
6
+ /**
7
+ * Logger configuration options.
8
+ */
9
+ export interface LoggerConfig {
10
+ /** Log level (default: 'info') */
11
+ level?: LogLevel;
12
+ /** Output file path (default: stderr) */
13
+ file?: string;
14
+ /** Enable pretty printing for development */
15
+ pretty?: boolean;
16
+ /** Include timestamps in output */
17
+ timestamp?: boolean;
18
+ /** Component name for context */
19
+ name?: string;
20
+ }
21
+ /**
22
+ * Create a new logger instance.
23
+ */
24
+ export declare function createLogger(config?: LoggerConfig): PinoLogger;
25
+ /**
26
+ * Get or create the global logger instance.
27
+ */
28
+ export declare function getLogger(name?: string): PinoLogger;
29
+ /**
30
+ * Configure the global logger.
31
+ */
32
+ export declare function configureLogger(config: LoggerConfig): void;
33
+ /**
34
+ * Reset the global logger (for testing).
35
+ */
36
+ export declare function resetLogger(): void;
37
+ /**
38
+ * Temporarily suppress all logging (set level to 'silent').
39
+ * Call restoreLogLevel() to restore the previous level.
40
+ */
41
+ export declare function suppressLogs(): void;
42
+ /**
43
+ * Restore the log level after suppression.
44
+ */
45
+ export declare function restoreLogLevel(): void;
46
+ /**
47
+ * Create a child logger with additional context.
48
+ */
49
+ export declare function childLogger(parent: PinoLogger, context: Record<string, unknown>): PinoLogger;
50
+ /**
51
+ * Timing helper for performance measurement.
52
+ */
53
+ export interface TimingResult {
54
+ durationMs: number;
55
+ log: () => void;
56
+ }
57
+ /**
58
+ * Start a timing measurement.
59
+ */
60
+ export declare function startTiming(logger: PinoLogger, operation: string): () => TimingResult;
61
+ /**
62
+ * Log levels as numeric values for comparison.
63
+ */
64
+ export declare const LOG_LEVEL_VALUES: Record<LogLevel, number>;
65
+ /**
66
+ * Check if a log level is enabled.
67
+ */
68
+ export declare function isLevelEnabled(currentLevel: LogLevel, checkLevel: LogLevel): boolean;
69
+ export type { PinoLogger as Logger };
70
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1,130 @@
1
+ import pino from 'pino';
2
+ /**
3
+ * Default configuration.
4
+ */
5
+ const DEFAULT_CONFIG = {
6
+ level: 'info',
7
+ pretty: false,
8
+ timestamp: true,
9
+ };
10
+ /**
11
+ * Global logger instance.
12
+ */
13
+ let globalLogger = null;
14
+ /**
15
+ * Create a new logger instance.
16
+ */
17
+ export function createLogger(config = {}) {
18
+ const level = config.level ?? DEFAULT_CONFIG.level;
19
+ const pretty = config.pretty ?? DEFAULT_CONFIG.pretty;
20
+ const timestamp = config.timestamp ?? DEFAULT_CONFIG.timestamp;
21
+ const options = {
22
+ level,
23
+ name: config.name,
24
+ timestamp: timestamp ? pino.stdTimeFunctions.isoTime : false,
25
+ formatters: {
26
+ level: (label) => ({ level: label }),
27
+ },
28
+ };
29
+ // Use pino-pretty transport for development
30
+ if (pretty) {
31
+ options.transport = {
32
+ target: 'pino-pretty',
33
+ options: {
34
+ colorize: true,
35
+ translateTime: 'SYS:standard',
36
+ ignore: 'pid,hostname',
37
+ },
38
+ };
39
+ }
40
+ // Create logger with file destination or stdout
41
+ if (config.file) {
42
+ return pino(options, pino.destination(config.file));
43
+ }
44
+ return pino(options);
45
+ }
46
+ /**
47
+ * Get or create the global logger instance.
48
+ */
49
+ export function getLogger(name) {
50
+ if (!globalLogger) {
51
+ globalLogger = createLogger({ level: 'info' });
52
+ }
53
+ if (name) {
54
+ return globalLogger.child({ component: name });
55
+ }
56
+ return globalLogger;
57
+ }
58
+ /**
59
+ * Configure the global logger.
60
+ */
61
+ export function configureLogger(config) {
62
+ globalLogger = createLogger(config);
63
+ }
64
+ /**
65
+ * Reset the global logger (for testing).
66
+ */
67
+ export function resetLogger() {
68
+ globalLogger = null;
69
+ }
70
+ /**
71
+ * Saved log level for restoration after temporary suppression.
72
+ */
73
+ let savedLogLevel = null;
74
+ /**
75
+ * Temporarily suppress all logging (set level to 'silent').
76
+ * Call restoreLogLevel() to restore the previous level.
77
+ */
78
+ export function suppressLogs() {
79
+ if (globalLogger && savedLogLevel === null) {
80
+ savedLogLevel = globalLogger.level;
81
+ globalLogger.level = 'silent';
82
+ }
83
+ }
84
+ /**
85
+ * Restore the log level after suppression.
86
+ */
87
+ export function restoreLogLevel() {
88
+ if (globalLogger && savedLogLevel !== null) {
89
+ globalLogger.level = savedLogLevel;
90
+ savedLogLevel = null;
91
+ }
92
+ }
93
+ /**
94
+ * Create a child logger with additional context.
95
+ */
96
+ export function childLogger(parent, context) {
97
+ return parent.child(context);
98
+ }
99
+ /**
100
+ * Start a timing measurement.
101
+ */
102
+ export function startTiming(logger, operation) {
103
+ const startTime = Date.now();
104
+ return () => {
105
+ const durationMs = Date.now() - startTime;
106
+ return {
107
+ durationMs,
108
+ log: () => {
109
+ logger.debug({ operation, durationMs }, `${operation} completed`);
110
+ },
111
+ };
112
+ };
113
+ }
114
+ /**
115
+ * Log levels as numeric values for comparison.
116
+ */
117
+ export const LOG_LEVEL_VALUES = {
118
+ debug: 20,
119
+ info: 30,
120
+ warn: 40,
121
+ error: 50,
122
+ silent: Infinity,
123
+ };
124
+ /**
125
+ * Check if a log level is enabled.
126
+ */
127
+ export function isLevelEnabled(currentLevel, checkLevel) {
128
+ return LOG_LEVEL_VALUES[checkLevel] >= LOG_LEVEL_VALUES[currentLevel];
129
+ }
130
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Metrics collector for comprehensive observability.
3
+ *
4
+ * Tracks timing, token usage, errors, and costs across all operations.
5
+ */
6
+ import type { TokenUsageRecord, TimingRecord, ErrorRecord, CostRecord, OperationType, ErrorCategory, InterviewMetrics, AggregatedMetrics, DashboardMetrics } from './types.js';
7
+ /**
8
+ * Options for the metrics collector.
9
+ */
10
+ export interface MetricsCollectorOptions {
11
+ /** Maximum number of records to keep in memory */
12
+ maxRecords?: number;
13
+ /** Whether to track individual records (vs just aggregates) */
14
+ trackRecords?: boolean;
15
+ }
16
+ /**
17
+ * Centralized metrics collector for observability.
18
+ */
19
+ export declare class MetricsCollector {
20
+ private readonly options;
21
+ private tokenRecords;
22
+ private timingRecords;
23
+ private errorRecords;
24
+ private costRecords;
25
+ private tokensByProviderModel;
26
+ private timingByOperation;
27
+ private errorsByCategory;
28
+ private costByProvider;
29
+ private interviewMetrics;
30
+ constructor(options?: MetricsCollectorOptions);
31
+ /**
32
+ * Start tracking an interview.
33
+ */
34
+ startInterview(): void;
35
+ /**
36
+ * End interview tracking.
37
+ */
38
+ endInterview(): InterviewMetrics | null;
39
+ /**
40
+ * Record token usage from an LLM call.
41
+ */
42
+ recordTokenUsage(provider: string, model: string, inputTokens: number, outputTokens: number, operation?: string): void;
43
+ /**
44
+ * Record operation timing.
45
+ */
46
+ recordTiming(operation: OperationType, durationMs: number, success: boolean, metadata?: Record<string, unknown>): void;
47
+ /**
48
+ * Record an error.
49
+ */
50
+ recordError(category: ErrorCategory, code: string, message: string, retryable: boolean, operation?: string): void;
51
+ /**
52
+ * Update interview-specific counters.
53
+ */
54
+ updateInterviewCounters(updates: Partial<{
55
+ toolsDiscovered: number;
56
+ questionsGenerated: number;
57
+ personasUsed: number;
58
+ }>): void;
59
+ /**
60
+ * Create a timed operation wrapper.
61
+ */
62
+ time<T>(operation: OperationType, fn: () => Promise<T>, metadata?: Record<string, unknown>): Promise<T>;
63
+ /**
64
+ * Get current interview metrics.
65
+ */
66
+ getInterviewMetrics(): InterviewMetrics | null;
67
+ /**
68
+ * Get aggregated metrics for a time period.
69
+ */
70
+ getAggregatedMetrics(periodStart?: Date, periodEnd?: Date): AggregatedMetrics;
71
+ /**
72
+ * Get dashboard-compatible metrics.
73
+ */
74
+ getDashboardMetrics(): DashboardMetrics;
75
+ /**
76
+ * Reset all metrics.
77
+ */
78
+ reset(): void;
79
+ /**
80
+ * Get raw records for external processing.
81
+ */
82
+ getRawRecords(): {
83
+ tokens: TokenUsageRecord[];
84
+ timing: TimingRecord[];
85
+ errors: ErrorRecord[];
86
+ costs: CostRecord[];
87
+ };
88
+ private trimRecords;
89
+ private calculateTokenUsageFromRecords;
90
+ private calculateTokenUsageFromAggregates;
91
+ private calculateOperationStatsFromRecords;
92
+ private calculateOperationStatsFromAggregates;
93
+ private convertOperationStats;
94
+ private calculateErrorStatsFromRecords;
95
+ private calculateErrorStatsFromAggregates;
96
+ private calculateProjectedCost;
97
+ }
98
+ /**
99
+ * Get or create the global metrics collector.
100
+ */
101
+ export declare function getMetricsCollector(options?: MetricsCollectorOptions): MetricsCollector;
102
+ /**
103
+ * Reset the global metrics collector.
104
+ */
105
+ export declare function resetMetricsCollector(): void;
106
+ //# sourceMappingURL=collector.d.ts.map