@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,41 @@
1
+ /**
2
+ * Anthropic Claude LLM client implementation.
3
+ */
4
+ import type { LLMClient, Message, CompletionOptions, ProviderInfo, StreamingOptions, StreamingResult } from './client.js';
5
+ export interface AnthropicClientOptions {
6
+ /** API key (defaults to ANTHROPIC_API_KEY env var) */
7
+ apiKey?: string;
8
+ /** Default model to use */
9
+ model?: string;
10
+ /** Base URL for API (for proxies/alternatives) */
11
+ baseURL?: string;
12
+ /** Callback to receive token usage from each API call */
13
+ onUsage?: (inputTokens: number, outputTokens: number) => void;
14
+ }
15
+ /**
16
+ * Anthropic Claude LLM client implementation.
17
+ */
18
+ export declare class AnthropicClient implements LLMClient {
19
+ private client;
20
+ private defaultModel;
21
+ private logger;
22
+ private onUsage?;
23
+ constructor(options?: AnthropicClientOptions);
24
+ getProviderInfo(): ProviderInfo;
25
+ chat(messages: Message[], options?: CompletionOptions): Promise<string>;
26
+ /**
27
+ * Check for content filtering refusal in Anthropic response.
28
+ * Anthropic uses stop_reason to indicate why generation stopped.
29
+ */
30
+ private checkForRefusal;
31
+ /**
32
+ * Normalize message order for Claude's requirements.
33
+ * Claude requires alternating user/assistant messages starting with user.
34
+ */
35
+ private normalizeMessageOrder;
36
+ complete(prompt: string, options?: CompletionOptions): Promise<string>;
37
+ parseJSON<T>(response: string): T;
38
+ stream(prompt: string, options?: StreamingOptions): Promise<StreamingResult>;
39
+ streamChat(messages: Message[], options?: StreamingOptions): Promise<StreamingResult>;
40
+ }
41
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1,355 @@
1
+ /**
2
+ * Anthropic Claude LLM client implementation.
3
+ */
4
+ import Anthropic from '@anthropic-ai/sdk';
5
+ import { DEFAULT_MODELS, parseJSONResponse } from './client.js';
6
+ import { LLM_DEFAULTS } from '../constants.js';
7
+ import { withRetry, LLM_RETRY_OPTIONS } from '../errors/retry.js';
8
+ import { LLMAuthError, LLMRateLimitError, LLMQuotaError, LLMConnectionError, LLMRefusalError, } from '../errors/index.js';
9
+ import { getLogger } from '../logging/logger.js';
10
+ /**
11
+ * Placeholder messages for Claude message normalization.
12
+ * Claude requires alternating user/assistant messages starting with user.
13
+ */
14
+ const PLACEHOLDER_CONTINUE = 'Continue.';
15
+ const PLACEHOLDER_GREETING = 'Hello.';
16
+ /**
17
+ * Anthropic Claude LLM client implementation.
18
+ */
19
+ export class AnthropicClient {
20
+ client;
21
+ defaultModel;
22
+ logger = getLogger('anthropic');
23
+ onUsage;
24
+ constructor(options) {
25
+ const apiKey = options?.apiKey ?? process.env.ANTHROPIC_API_KEY;
26
+ if (!apiKey) {
27
+ throw new LLMAuthError('anthropic');
28
+ }
29
+ this.client = new Anthropic({
30
+ apiKey,
31
+ baseURL: options?.baseURL,
32
+ });
33
+ this.defaultModel = options?.model ?? DEFAULT_MODELS.anthropic;
34
+ this.onUsage = options?.onUsage;
35
+ }
36
+ getProviderInfo() {
37
+ return {
38
+ id: 'anthropic',
39
+ name: 'Anthropic Claude',
40
+ supportsJSON: false, // Claude doesn't have a JSON mode like OpenAI
41
+ supportsStreaming: true,
42
+ defaultModel: this.defaultModel,
43
+ };
44
+ }
45
+ async chat(messages, options) {
46
+ const model = options?.model ?? this.defaultModel;
47
+ return withRetry(async () => {
48
+ // Separate system message from conversation messages
49
+ const systemPrompt = options?.systemPrompt;
50
+ // Convert messages to Anthropic format
51
+ const anthropicMessages = messages.map(m => ({
52
+ role: m.role === 'assistant' ? 'assistant' : 'user',
53
+ content: m.content,
54
+ }));
55
+ // If first message has system role, extract it
56
+ let system = systemPrompt;
57
+ if (messages.length > 0 && messages[0].role === 'system') {
58
+ system = system ? `${system}\n\n${messages[0].content}` : messages[0].content;
59
+ anthropicMessages.shift();
60
+ }
61
+ // Claude requires messages to start with user role
62
+ // If we have no messages after removing system, add a placeholder
63
+ if (anthropicMessages.length === 0) {
64
+ throw new Error('At least one user message is required');
65
+ }
66
+ // Ensure messages alternate between user and assistant
67
+ // Claude is strict about this
68
+ const normalizedMessages = this.normalizeMessageOrder(anthropicMessages);
69
+ try {
70
+ const response = await this.client.messages.create({
71
+ model,
72
+ max_tokens: options?.maxTokens ?? LLM_DEFAULTS.MAX_TOKENS,
73
+ system: system,
74
+ messages: normalizedMessages,
75
+ });
76
+ // Track actual token usage from API response
77
+ if (this.onUsage && response.usage) {
78
+ this.onUsage(response.usage.input_tokens, response.usage.output_tokens);
79
+ }
80
+ // Check for content filtering refusal
81
+ this.checkForRefusal(response, model);
82
+ // Extract text content from response
83
+ const textBlocks = response.content.filter(block => block.type === 'text');
84
+ if (textBlocks.length === 0) {
85
+ throw new Error('No text content in Claude response');
86
+ }
87
+ return textBlocks.map(block => block.text).join('');
88
+ }
89
+ catch (error) {
90
+ // Don't re-process errors that are already typed LLM errors
91
+ if (error instanceof LLMRefusalError || error instanceof LLMAuthError ||
92
+ error instanceof LLMRateLimitError || error instanceof LLMQuotaError ||
93
+ error instanceof LLMConnectionError) {
94
+ throw error;
95
+ }
96
+ // Convert to typed errors for retry logic
97
+ if (error instanceof Error) {
98
+ const message = error.message.toLowerCase();
99
+ if (message.includes('401') || message.includes('authentication')) {
100
+ throw new LLMAuthError('anthropic', model);
101
+ }
102
+ if (message.includes('429') || message.includes('rate limit')) {
103
+ // Extract retry-after-ms header if available from Anthropic API error
104
+ let retryAfterMs;
105
+ const apiError = error;
106
+ if (apiError.headers?.get) {
107
+ // Anthropic uses retry-after-ms header (milliseconds)
108
+ const retryAfterMsHeader = apiError.headers.get('retry-after-ms');
109
+ if (retryAfterMsHeader) {
110
+ const ms = parseInt(retryAfterMsHeader, 10);
111
+ if (!isNaN(ms)) {
112
+ retryAfterMs = ms;
113
+ this.logger.debug({ retryAfterMs }, 'Extracted retry-after-ms header');
114
+ }
115
+ }
116
+ // Fall back to standard retry-after header (seconds)
117
+ if (!retryAfterMs) {
118
+ const retryAfter = apiError.headers.get('retry-after');
119
+ if (retryAfter) {
120
+ const seconds = parseInt(retryAfter, 10);
121
+ if (!isNaN(seconds)) {
122
+ retryAfterMs = seconds * 1000;
123
+ this.logger.debug({ retryAfterMs }, 'Extracted retry-after header');
124
+ }
125
+ }
126
+ }
127
+ }
128
+ throw new LLMRateLimitError('anthropic', retryAfterMs, model);
129
+ }
130
+ if (message.includes('insufficient') || message.includes('credit')) {
131
+ throw new LLMQuotaError('anthropic', model);
132
+ }
133
+ if (message.includes('econnrefused') || message.includes('fetch failed')) {
134
+ throw new LLMConnectionError('anthropic', model);
135
+ }
136
+ }
137
+ throw error;
138
+ }
139
+ }, {
140
+ ...LLM_RETRY_OPTIONS,
141
+ operation: 'Anthropic chat completion',
142
+ context: { component: 'anthropic', metadata: { model } },
143
+ onRetry: (error, attempt, delayMs) => {
144
+ this.logger.debug({
145
+ attempt,
146
+ delayMs: Math.round(delayMs),
147
+ error: error instanceof Error ? error.message : String(error),
148
+ msg: `Retrying Anthropic API call`,
149
+ });
150
+ },
151
+ });
152
+ }
153
+ /**
154
+ * Check for content filtering refusal in Anthropic response.
155
+ * Anthropic uses stop_reason to indicate why generation stopped.
156
+ */
157
+ checkForRefusal(response, model) {
158
+ // Check stop_reason for content filtering
159
+ if (response.stop_reason === 'content_filter') {
160
+ throw new LLMRefusalError('anthropic', 'Content was filtered', model);
161
+ }
162
+ // Check for safety-related stop reasons
163
+ if (response.stop_reason === 'safety') {
164
+ throw new LLMRefusalError('anthropic', 'Response blocked due to safety concerns', model);
165
+ }
166
+ // Check content for refusal indicators
167
+ const textBlocks = response.content.filter(block => block.type === 'text');
168
+ if (textBlocks.length > 0) {
169
+ const fullText = textBlocks.map(block => block.text ?? '').join('').toLowerCase();
170
+ // Check for common refusal patterns in Claude's responses
171
+ const refusalPatterns = [
172
+ 'i cannot help with',
173
+ 'i am not able to',
174
+ "i can't assist with",
175
+ 'i cannot assist with',
176
+ 'i am unable to',
177
+ "i won't be able to",
178
+ 'i must decline',
179
+ 'i need to refuse',
180
+ 'against my guidelines',
181
+ 'violates my ethical guidelines',
182
+ 'goes against my values',
183
+ 'i cannot provide',
184
+ 'i cannot generate',
185
+ 'harmful content',
186
+ 'dangerous content',
187
+ 'illegal content',
188
+ ];
189
+ for (const pattern of refusalPatterns) {
190
+ if (fullText.includes(pattern)) {
191
+ // Extract more context around the refusal
192
+ const startIdx = Math.max(0, fullText.indexOf(pattern) - 20);
193
+ const endIdx = Math.min(fullText.length, fullText.indexOf(pattern) + pattern.length + 100);
194
+ const context = fullText.slice(startIdx, endIdx).trim();
195
+ throw new LLMRefusalError('anthropic', `Model declined: "${context}..."`, model);
196
+ }
197
+ }
198
+ }
199
+ }
200
+ /**
201
+ * Normalize message order for Claude's requirements.
202
+ * Claude requires alternating user/assistant messages starting with user.
203
+ */
204
+ normalizeMessageOrder(messages) {
205
+ const result = [];
206
+ for (const msg of messages) {
207
+ if (result.length === 0) {
208
+ // First message must be from user
209
+ if (msg.role === 'assistant') {
210
+ // Insert placeholder user message
211
+ result.push({ role: 'user', content: PLACEHOLDER_CONTINUE });
212
+ }
213
+ result.push(msg);
214
+ }
215
+ else {
216
+ const lastRole = result[result.length - 1].role;
217
+ if (msg.role === lastRole) {
218
+ // Same role as previous - merge content
219
+ result[result.length - 1].content += '\n\n' + msg.content;
220
+ }
221
+ else {
222
+ result.push(msg);
223
+ }
224
+ }
225
+ }
226
+ // Ensure we end with the messages array not empty
227
+ if (result.length === 0) {
228
+ result.push({ role: 'user', content: PLACEHOLDER_GREETING });
229
+ }
230
+ return result;
231
+ }
232
+ async complete(prompt, options) {
233
+ return this.chat([{ role: 'user', content: prompt }], options);
234
+ }
235
+ parseJSON(response) {
236
+ return parseJSONResponse(response);
237
+ }
238
+ async stream(prompt, options) {
239
+ return this.streamChat([{ role: 'user', content: prompt }], options);
240
+ }
241
+ async streamChat(messages, options) {
242
+ const model = options?.model ?? this.defaultModel;
243
+ return withRetry(async () => {
244
+ // Separate system message from conversation messages
245
+ const systemPrompt = options?.systemPrompt;
246
+ // Convert messages to Anthropic format
247
+ const anthropicMessages = messages.map(m => ({
248
+ role: m.role === 'assistant' ? 'assistant' : 'user',
249
+ content: m.content,
250
+ }));
251
+ // If first message has system role, extract it
252
+ let system = systemPrompt;
253
+ if (messages.length > 0 && messages[0].role === 'system') {
254
+ system = system ? `${system}\n\n${messages[0].content}` : messages[0].content;
255
+ anthropicMessages.shift();
256
+ }
257
+ // Claude requires messages to start with user role
258
+ if (anthropicMessages.length === 0) {
259
+ throw new Error('At least one user message is required');
260
+ }
261
+ // Ensure messages alternate between user and assistant
262
+ const normalizedMessages = this.normalizeMessageOrder(anthropicMessages);
263
+ try {
264
+ const stream = await this.client.messages.stream({
265
+ model,
266
+ max_tokens: options?.maxTokens ?? LLM_DEFAULTS.MAX_TOKENS,
267
+ system: system,
268
+ messages: normalizedMessages,
269
+ });
270
+ let fullText = '';
271
+ for await (const event of stream) {
272
+ if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
273
+ const text = event.delta.text;
274
+ if (text) {
275
+ fullText += text;
276
+ options?.onChunk?.(text);
277
+ }
278
+ }
279
+ }
280
+ // Get final message for token usage
281
+ const finalMessage = await stream.finalMessage();
282
+ // Track actual token usage from API response
283
+ if (this.onUsage && finalMessage.usage) {
284
+ this.onUsage(finalMessage.usage.input_tokens, finalMessage.usage.output_tokens);
285
+ }
286
+ // Check for content filtering refusal
287
+ this.checkForRefusal(finalMessage, model);
288
+ if (!fullText) {
289
+ throw new Error('No text content in streaming response');
290
+ }
291
+ options?.onComplete?.(fullText);
292
+ return { text: fullText, completed: true };
293
+ }
294
+ catch (error) {
295
+ options?.onError?.(error instanceof Error ? error : new Error(String(error)));
296
+ // Don't re-process errors that are already typed LLM errors
297
+ if (error instanceof LLMRefusalError || error instanceof LLMAuthError ||
298
+ error instanceof LLMRateLimitError || error instanceof LLMQuotaError ||
299
+ error instanceof LLMConnectionError) {
300
+ throw error;
301
+ }
302
+ // Convert to typed errors for retry logic (same as chat method)
303
+ if (error instanceof Error) {
304
+ const message = error.message.toLowerCase();
305
+ if (message.includes('401') || message.includes('authentication')) {
306
+ throw new LLMAuthError('anthropic', model);
307
+ }
308
+ if (message.includes('429') || message.includes('rate limit')) {
309
+ let retryAfterMs;
310
+ const apiError = error;
311
+ if (apiError.headers?.get) {
312
+ const retryAfterMsHeader = apiError.headers.get('retry-after-ms');
313
+ if (retryAfterMsHeader) {
314
+ const ms = parseInt(retryAfterMsHeader, 10);
315
+ if (!isNaN(ms)) {
316
+ retryAfterMs = ms;
317
+ }
318
+ }
319
+ if (!retryAfterMs) {
320
+ const retryAfter = apiError.headers.get('retry-after');
321
+ if (retryAfter) {
322
+ const seconds = parseInt(retryAfter, 10);
323
+ if (!isNaN(seconds)) {
324
+ retryAfterMs = seconds * 1000;
325
+ }
326
+ }
327
+ }
328
+ }
329
+ throw new LLMRateLimitError('anthropic', retryAfterMs, model);
330
+ }
331
+ if (message.includes('insufficient') || message.includes('credit')) {
332
+ throw new LLMQuotaError('anthropic', model);
333
+ }
334
+ if (message.includes('econnrefused') || message.includes('fetch failed')) {
335
+ throw new LLMConnectionError('anthropic', model);
336
+ }
337
+ }
338
+ throw error;
339
+ }
340
+ }, {
341
+ ...LLM_RETRY_OPTIONS,
342
+ operation: 'Anthropic streaming chat completion',
343
+ context: { component: 'anthropic', metadata: { model } },
344
+ onRetry: (error, attempt, delayMs) => {
345
+ this.logger.debug({
346
+ attempt,
347
+ delayMs: Math.round(delayMs),
348
+ error: error instanceof Error ? error.message : String(error),
349
+ msg: `Retrying Anthropic streaming API call`,
350
+ });
351
+ },
352
+ });
353
+ }
354
+ }
355
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1,123 @@
1
+ /**
2
+ * LLM client interface for abstracting different providers.
3
+ */
4
+ export interface Message {
5
+ role: 'system' | 'user' | 'assistant';
6
+ content: string;
7
+ }
8
+ export interface CompletionOptions {
9
+ /** Model to use */
10
+ model?: string;
11
+ /** Maximum tokens in response */
12
+ maxTokens?: number;
13
+ /** Temperature for sampling (0-2) */
14
+ temperature?: number;
15
+ /** Response format */
16
+ responseFormat?: 'text' | 'json';
17
+ /** System prompt to set context */
18
+ systemPrompt?: string;
19
+ }
20
+ /**
21
+ * Options for streaming completions.
22
+ */
23
+ export interface StreamingOptions extends CompletionOptions {
24
+ /** Callback invoked with each chunk of text as it arrives */
25
+ onChunk?: (chunk: string) => void;
26
+ /** Callback invoked when streaming completes with full text */
27
+ onComplete?: (fullText: string) => void;
28
+ /** Callback invoked if an error occurs during streaming */
29
+ onError?: (error: Error) => void;
30
+ }
31
+ /**
32
+ * Result of a streaming completion.
33
+ */
34
+ export interface StreamingResult {
35
+ /** The complete text (after streaming finishes) */
36
+ text: string;
37
+ /** Whether streaming completed successfully */
38
+ completed: boolean;
39
+ }
40
+ /**
41
+ * Provider capabilities and metadata.
42
+ */
43
+ export interface ProviderInfo {
44
+ /** Unique provider identifier */
45
+ id: string;
46
+ /** Human-readable provider name */
47
+ name: string;
48
+ /** Whether the provider supports JSON mode */
49
+ supportsJSON: boolean;
50
+ /** Whether the provider supports streaming */
51
+ supportsStreaming: boolean;
52
+ /** Default model for this provider */
53
+ defaultModel: string;
54
+ }
55
+ export interface LLMClient {
56
+ /**
57
+ * Get provider information.
58
+ */
59
+ getProviderInfo(): ProviderInfo;
60
+ /**
61
+ * Generate a completion from a list of messages.
62
+ */
63
+ chat(messages: Message[], options?: CompletionOptions): Promise<string>;
64
+ /**
65
+ * Generate a completion from a single prompt.
66
+ */
67
+ complete(prompt: string, options?: CompletionOptions): Promise<string>;
68
+ /**
69
+ * Stream a completion from a single prompt.
70
+ * Yields text chunks as they arrive from the LLM.
71
+ * Returns the complete response text when done.
72
+ */
73
+ stream(prompt: string, options?: StreamingOptions): Promise<StreamingResult>;
74
+ /**
75
+ * Stream a chat completion from a list of messages.
76
+ * Yields text chunks as they arrive from the LLM.
77
+ * Returns the complete response text when done.
78
+ */
79
+ streamChat(messages: Message[], options?: StreamingOptions): Promise<StreamingResult>;
80
+ /**
81
+ * Parse JSON from LLM response, handling common formatting issues.
82
+ */
83
+ parseJSON<T>(response: string): T;
84
+ }
85
+ /**
86
+ * Default model configurations per provider.
87
+ * Uses budget-friendly models by default for cost efficiency.
88
+ * @see constants.ts for the source values
89
+ */
90
+ export declare const DEFAULT_MODELS: Record<LLMProviderId, string>;
91
+ /**
92
+ * Premium model configurations for --quality flag.
93
+ * Higher quality output but more expensive.
94
+ * @see constants.ts for the source values
95
+ */
96
+ export declare const PREMIUM_MODELS: Record<LLMProviderId, string>;
97
+ /**
98
+ * Provider IDs.
99
+ */
100
+ export type LLMProviderId = 'openai' | 'anthropic' | 'ollama';
101
+ /**
102
+ * Configuration for LLM providers.
103
+ */
104
+ export interface LLMConfig {
105
+ /** Provider to use */
106
+ provider: LLMProviderId;
107
+ /** Model to use (provider-specific) */
108
+ model?: string;
109
+ /** API key (or env var name containing it) */
110
+ apiKey?: string;
111
+ /** Environment variable containing API key */
112
+ apiKeyEnvVar?: string;
113
+ /** Base URL for API (for proxies/self-hosted) */
114
+ baseUrl?: string;
115
+ /** Callback to receive actual token usage from each API call */
116
+ onUsage?: (inputTokens: number, outputTokens: number) => void;
117
+ }
118
+ /**
119
+ * Parse JSON from LLM response, handling common formatting issues.
120
+ * Shared utility function for all providers.
121
+ */
122
+ export declare function parseJSONResponse<T>(response: string): T;
123
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * LLM client interface for abstracting different providers.
3
+ */
4
+ import { DEFAULT_MODELS as DEFAULT_MODELS_CONST, PREMIUM_MODELS as PREMIUM_MODELS_CONST, } from '../constants.js';
5
+ /**
6
+ * Default model configurations per provider.
7
+ * Uses budget-friendly models by default for cost efficiency.
8
+ * @see constants.ts for the source values
9
+ */
10
+ export const DEFAULT_MODELS = DEFAULT_MODELS_CONST;
11
+ /**
12
+ * Premium model configurations for --quality flag.
13
+ * Higher quality output but more expensive.
14
+ * @see constants.ts for the source values
15
+ */
16
+ export const PREMIUM_MODELS = PREMIUM_MODELS_CONST;
17
+ /**
18
+ * Parse JSON from LLM response, handling common formatting issues.
19
+ * Shared utility function for all providers.
20
+ */
21
+ export function parseJSONResponse(response) {
22
+ // Handle markdown code blocks
23
+ let cleaned = response.trim();
24
+ // Remove ```json or ``` wrappers
25
+ if (cleaned.startsWith('```')) {
26
+ const lines = cleaned.split('\n');
27
+ // Remove first line (```json or ```)
28
+ lines.shift();
29
+ // Remove last line (```)
30
+ if (lines[lines.length - 1]?.trim() === '```') {
31
+ lines.pop();
32
+ }
33
+ cleaned = lines.join('\n');
34
+ }
35
+ try {
36
+ return JSON.parse(cleaned);
37
+ }
38
+ catch (error) {
39
+ throw new Error(`Failed to parse JSON from LLM response: ${error}`);
40
+ }
41
+ }
42
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,38 @@
1
+ /**
2
+ * LLM provider factory - creates and auto-detects providers.
3
+ */
4
+ import type { LLMClient, LLMConfig, LLMProviderId } from './client.js';
5
+ /**
6
+ * Create an LLM client from configuration.
7
+ */
8
+ export declare function createLLMClient(config: LLMConfig): LLMClient;
9
+ /**
10
+ * Auto-detect the best available provider based on environment.
11
+ */
12
+ export declare function detectProvider(): LLMProviderId;
13
+ /**
14
+ * Create an LLM client with auto-detection.
15
+ * Uses environment variables to determine the best provider.
16
+ */
17
+ export declare function createAutoClient(modelOverride?: string): LLMClient;
18
+ /**
19
+ * Get information about available providers.
20
+ */
21
+ export interface ProviderAvailability {
22
+ provider: LLMProviderId;
23
+ available: boolean;
24
+ reason?: string;
25
+ }
26
+ /**
27
+ * Check which providers are available.
28
+ */
29
+ export declare function checkProviderAvailability(): Promise<ProviderAvailability[]>;
30
+ /**
31
+ * Get the default model for a provider.
32
+ */
33
+ export declare function getDefaultModel(provider: LLMProviderId): string;
34
+ /**
35
+ * List all supported providers.
36
+ */
37
+ export declare function getSupportedProviders(): LLMProviderId[];
38
+ //# sourceMappingURL=factory.d.ts.map