@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,513 @@
1
+ /**
2
+ * Workflow auto-generator - generates workflow YAML from discovered tools.
3
+ *
4
+ * This module analyzes tool descriptions and schemas to automatically
5
+ * generate test workflows that represent common usage patterns.
6
+ * Unlike the LLM-powered WorkflowDiscoverer, this uses heuristics
7
+ * for deterministic workflow generation in check mode.
8
+ */
9
+ import { WORKFLOW } from '../constants.js';
10
+ /**
11
+ * Default options for workflow generation.
12
+ */
13
+ const DEFAULT_OPTIONS = {
14
+ maxWorkflows: WORKFLOW.MAX_DISCOVERED_WORKFLOWS,
15
+ minSteps: WORKFLOW.MIN_WORKFLOW_STEPS,
16
+ maxSteps: WORKFLOW.MAX_WORKFLOW_STEPS,
17
+ };
18
+ /**
19
+ * Common CRUD operation prefixes for pattern matching.
20
+ */
21
+ const CRUD_PREFIXES = {
22
+ create: ['create', 'add', 'new', 'insert', 'post', 'make'],
23
+ read: ['get', 'read', 'fetch', 'retrieve', 'find', 'list', 'search', 'query'],
24
+ update: ['update', 'edit', 'modify', 'patch', 'set', 'change'],
25
+ delete: ['delete', 'remove', 'destroy', 'clear', 'reset'],
26
+ };
27
+ /**
28
+ * Workflow relationship patterns found in tool descriptions.
29
+ */
30
+ const RELATIONSHIP_PATTERNS = [
31
+ { pattern: /after\s+(?:calling\s+)?['"`]?(\w+)['"`]?/i, type: 'after' },
32
+ { pattern: /requires?\s+(?:output\s+from\s+)?['"`]?(\w+)['"`]?/i, type: 'requires' },
33
+ { pattern: /use\s+(?:the\s+)?(?:result|output)\s+(?:of|from)\s+['"`]?(\w+)['"`]?/i, type: 'uses' },
34
+ { pattern: /(?:first|before)\s+(?:call\s+)?['"`]?(\w+)['"`]?/i, type: 'after' },
35
+ { pattern: /chain\s+(?:with\s+)?['"`]?(\w+)['"`]?/i, type: 'chains' },
36
+ ];
37
+ /**
38
+ * Common parameter patterns that suggest data flow.
39
+ */
40
+ const PARAMETER_FLOW_PATTERNS = [
41
+ { paramPattern: /^(item|access|session|auth)_?token$/i, sourceField: 'token' },
42
+ { paramPattern: /^(item|access|session)_?id$/i, sourceField: 'id' },
43
+ { paramPattern: /^(public|link)_?token$/i, sourceField: 'link_token' },
44
+ { paramPattern: /^(cursor|next_?cursor|page_?token)$/i, sourceField: 'next_cursor' },
45
+ { paramPattern: /^(file|resource|entity)_?path$/i, sourceField: 'path' },
46
+ ];
47
+ /**
48
+ * Generate workflows from available tools using pattern matching.
49
+ *
50
+ * This function analyzes tool names, descriptions, and schemas to
51
+ * identify common workflow patterns like CRUD operations, auth flows,
52
+ * and chained data processing.
53
+ *
54
+ * @param tools - Available MCP tools
55
+ * @param options - Generation options
56
+ * @returns Array of generated workflows
57
+ */
58
+ export function generateWorkflowsFromTools(tools, options = {}) {
59
+ const opts = { ...DEFAULT_OPTIONS, ...options };
60
+ if (tools.length < 2) {
61
+ return [];
62
+ }
63
+ const workflows = [];
64
+ // Strategy 1: Find CRUD patterns
65
+ const crudWorkflows = findCrudWorkflows(tools, opts);
66
+ workflows.push(...crudWorkflows);
67
+ // Strategy 2: Find relationship-based workflows from descriptions
68
+ const relationshipWorkflows = findRelationshipWorkflows(tools, opts);
69
+ workflows.push(...relationshipWorkflows);
70
+ // Strategy 3: Find parameter-based workflows (data flow patterns)
71
+ const parameterWorkflows = findParameterFlowWorkflows(tools, opts);
72
+ workflows.push(...parameterWorkflows);
73
+ // Deduplicate workflows by ID
74
+ const seen = new Set();
75
+ const uniqueWorkflows = workflows.filter(w => {
76
+ if (seen.has(w.id))
77
+ return false;
78
+ seen.add(w.id);
79
+ return true;
80
+ });
81
+ // Limit to max workflows
82
+ return uniqueWorkflows.slice(0, opts.maxWorkflows);
83
+ }
84
+ /**
85
+ * Find CRUD-based workflows by grouping tools by resource type.
86
+ */
87
+ function findCrudWorkflows(tools, opts) {
88
+ const workflows = [];
89
+ const toolsByResource = groupToolsByResource(tools);
90
+ for (const [resource, resourceTools] of toolsByResource.entries()) {
91
+ // Need at least 2 tools for a workflow
92
+ if (resourceTools.length < opts.minSteps)
93
+ continue;
94
+ // Try to build create-read workflow
95
+ const createTool = resourceTools.find(t => matchesCrudOperation(t.name, 'create'));
96
+ const readTool = resourceTools.find(t => matchesCrudOperation(t.name, 'read'));
97
+ if (createTool && readTool) {
98
+ workflows.push({
99
+ id: `crud_create_read_${resource}`,
100
+ name: `Create and Read ${capitalize(resource)}`,
101
+ description: `Create a new ${resource} and verify it can be retrieved`,
102
+ expectedOutcome: `Successfully create and read ${resource}`,
103
+ steps: [
104
+ {
105
+ tool: createTool.name,
106
+ description: `Create a new ${resource}`,
107
+ args: generateMinimalArgs(createTool),
108
+ },
109
+ {
110
+ tool: readTool.name,
111
+ description: `Retrieve the created ${resource}`,
112
+ argMapping: inferArgMapping(createTool, readTool, 0),
113
+ },
114
+ ],
115
+ discovered: true,
116
+ });
117
+ }
118
+ // Try to build list workflow
119
+ const listTool = resourceTools.find(t => /^(list|get_all|search)_/i.test(t.name));
120
+ if (listTool && readTool && listTool !== readTool) {
121
+ workflows.push({
122
+ id: `crud_list_read_${resource}`,
123
+ name: `List and Read ${capitalize(resource)}`,
124
+ description: `List ${resource}s and get details of the first one`,
125
+ expectedOutcome: `Successfully list and retrieve ${resource} details`,
126
+ steps: [
127
+ {
128
+ tool: listTool.name,
129
+ description: `List available ${resource}s`,
130
+ args: generateMinimalArgs(listTool),
131
+ },
132
+ {
133
+ tool: readTool.name,
134
+ description: `Get details of first ${resource}`,
135
+ argMapping: inferListToDetailMapping(listTool, readTool),
136
+ },
137
+ ],
138
+ discovered: true,
139
+ });
140
+ }
141
+ }
142
+ return workflows;
143
+ }
144
+ /**
145
+ * Find workflows based on relationship patterns in descriptions.
146
+ */
147
+ function findRelationshipWorkflows(tools, opts) {
148
+ const workflows = [];
149
+ const toolsByName = new Map(tools.map(t => [t.name.toLowerCase(), t]));
150
+ for (const tool of tools) {
151
+ const description = tool.description || '';
152
+ for (const { pattern, type } of RELATIONSHIP_PATTERNS) {
153
+ const match = description.match(pattern);
154
+ if (!match)
155
+ continue;
156
+ const referencedToolName = match[1].toLowerCase();
157
+ const referencedTool = toolsByName.get(referencedToolName);
158
+ if (!referencedTool || referencedTool.name === tool.name)
159
+ continue;
160
+ // Build workflow based on relationship type
161
+ const steps = [];
162
+ if (type === 'after' || type === 'requires' || type === 'uses') {
163
+ // Referenced tool comes first
164
+ steps.push({
165
+ tool: referencedTool.name,
166
+ description: referencedTool.description || `Call ${referencedTool.name}`,
167
+ args: generateMinimalArgs(referencedTool),
168
+ });
169
+ steps.push({
170
+ tool: tool.name,
171
+ description: tool.description || `Call ${tool.name}`,
172
+ argMapping: inferArgMapping(referencedTool, tool, 0),
173
+ });
174
+ }
175
+ else {
176
+ // Current tool comes first (chains pattern)
177
+ steps.push({
178
+ tool: tool.name,
179
+ description: tool.description || `Call ${tool.name}`,
180
+ args: generateMinimalArgs(tool),
181
+ });
182
+ steps.push({
183
+ tool: referencedTool.name,
184
+ description: referencedTool.description || `Call ${referencedTool.name}`,
185
+ argMapping: inferArgMapping(tool, referencedTool, 0),
186
+ });
187
+ }
188
+ if (steps.length >= opts.minSteps) {
189
+ const workflowId = `rel_${tool.name}_${referencedTool.name}`.toLowerCase().replace(/[^a-z0-9]+/g, '_');
190
+ workflows.push({
191
+ id: workflowId,
192
+ name: `${capitalize(steps[0].tool)} to ${capitalize(steps[1].tool)}`,
193
+ description: `Workflow discovered from tool description relationship`,
194
+ expectedOutcome: `Successfully chain ${steps[0].tool} and ${steps[1].tool}`,
195
+ steps,
196
+ discovered: true,
197
+ });
198
+ }
199
+ }
200
+ }
201
+ return workflows;
202
+ }
203
+ /**
204
+ * Find workflows based on parameter name patterns that suggest data flow.
205
+ */
206
+ function findParameterFlowWorkflows(tools, _opts) {
207
+ const workflows = [];
208
+ // Map tools by what they might produce based on description/name
209
+ const producerTools = new Map();
210
+ for (const tool of tools) {
211
+ const description = (tool.description || '').toLowerCase();
212
+ const name = tool.name.toLowerCase();
213
+ // Tools that create/generate tokens
214
+ if (/(?:create|generate|get).*(?:token|link)/i.test(name) ||
215
+ /returns?\s+(?:a\s+)?(?:link_?)?token/i.test(description)) {
216
+ producerTools.set('token', tool);
217
+ }
218
+ // Tools that list/return items with IDs
219
+ if (/^list_|^get_all_|^search_/i.test(name)) {
220
+ const resource = extractResourceName(name);
221
+ if (resource) {
222
+ producerTools.set(`${resource}_list`, tool);
223
+ }
224
+ }
225
+ }
226
+ // Find consumer tools and create workflows
227
+ for (const tool of tools) {
228
+ const schema = tool.inputSchema;
229
+ if (!schema?.properties)
230
+ continue;
231
+ for (const paramName of Object.keys(schema.properties)) {
232
+ for (const { paramPattern, sourceField } of PARAMETER_FLOW_PATTERNS) {
233
+ if (!paramPattern.test(paramName))
234
+ continue;
235
+ // Find a producer for this parameter
236
+ const producerKey = sourceField === 'token' ? 'token' : extractResourceName(paramName) + '_list';
237
+ const producer = producerTools.get(producerKey) || producerTools.get('token');
238
+ if (!producer || producer.name === tool.name)
239
+ continue;
240
+ const workflowId = `flow_${producer.name}_${tool.name}`.toLowerCase().replace(/[^a-z0-9]+/g, '_');
241
+ // Check if we already have this workflow
242
+ if (workflows.some(w => w.id === workflowId))
243
+ continue;
244
+ workflows.push({
245
+ id: workflowId,
246
+ name: `${capitalize(producer.name)} to ${capitalize(tool.name)}`,
247
+ description: `Data flow workflow: ${producer.name} produces input for ${tool.name}`,
248
+ expectedOutcome: `Successfully pass ${sourceField} from ${producer.name} to ${tool.name}`,
249
+ steps: [
250
+ {
251
+ tool: producer.name,
252
+ description: producer.description || `Call ${producer.name}`,
253
+ args: generateMinimalArgs(producer),
254
+ },
255
+ {
256
+ tool: tool.name,
257
+ description: tool.description || `Call ${tool.name}`,
258
+ argMapping: {
259
+ [paramName]: `$steps[0].result.${sourceField}`,
260
+ },
261
+ },
262
+ ],
263
+ discovered: true,
264
+ });
265
+ // Only one workflow per tool pair
266
+ break;
267
+ }
268
+ }
269
+ }
270
+ return workflows;
271
+ }
272
+ /**
273
+ * Group tools by their inferred resource type.
274
+ */
275
+ function groupToolsByResource(tools) {
276
+ const groups = new Map();
277
+ for (const tool of tools) {
278
+ const resource = extractResourceName(tool.name);
279
+ if (!resource)
280
+ continue;
281
+ if (!groups.has(resource)) {
282
+ groups.set(resource, []);
283
+ }
284
+ groups.get(resource).push(tool);
285
+ }
286
+ return groups;
287
+ }
288
+ /**
289
+ * Extract resource name from a tool name (e.g., "get_user" -> "user").
290
+ */
291
+ function extractResourceName(toolName) {
292
+ // Remove common prefixes
293
+ let name = toolName.toLowerCase();
294
+ for (const prefixes of Object.values(CRUD_PREFIXES)) {
295
+ for (const prefix of prefixes) {
296
+ if (name.startsWith(prefix + '_')) {
297
+ name = name.slice(prefix.length + 1);
298
+ break;
299
+ }
300
+ if (name.startsWith(prefix)) {
301
+ name = name.slice(prefix.length);
302
+ break;
303
+ }
304
+ }
305
+ }
306
+ // Clean up remaining underscores and pluralization
307
+ name = name.replace(/^_+|_+$/g, '');
308
+ name = name.replace(/s$/, ''); // Simple depluralization
309
+ return name || null;
310
+ }
311
+ /**
312
+ * Check if a tool name matches a CRUD operation type.
313
+ */
314
+ function matchesCrudOperation(toolName, operation) {
315
+ const name = toolName.toLowerCase();
316
+ return CRUD_PREFIXES[operation].some(prefix => name.startsWith(prefix + '_') || name.startsWith(prefix));
317
+ }
318
+ /**
319
+ * Generate minimal arguments for a tool based on its schema.
320
+ * Only includes required parameters with placeholder values.
321
+ */
322
+ function generateMinimalArgs(tool) {
323
+ const schema = tool.inputSchema;
324
+ if (!schema?.properties || !schema.required) {
325
+ return {};
326
+ }
327
+ const args = {};
328
+ for (const reqParam of schema.required) {
329
+ const propSchema = schema.properties[reqParam];
330
+ if (!propSchema)
331
+ continue;
332
+ // Use default if available
333
+ if (propSchema.default !== undefined) {
334
+ args[reqParam] = propSchema.default;
335
+ continue;
336
+ }
337
+ // Use first enum value if available
338
+ if (propSchema.enum && propSchema.enum.length > 0) {
339
+ args[reqParam] = propSchema.enum[0];
340
+ continue;
341
+ }
342
+ // Generate placeholder based on type
343
+ switch (propSchema.type) {
344
+ case 'string':
345
+ args[reqParam] = `test_${reqParam}`;
346
+ break;
347
+ case 'number':
348
+ case 'integer':
349
+ args[reqParam] = 1;
350
+ break;
351
+ case 'boolean':
352
+ args[reqParam] = true;
353
+ break;
354
+ case 'array':
355
+ args[reqParam] = [];
356
+ break;
357
+ case 'object':
358
+ args[reqParam] = {};
359
+ break;
360
+ default:
361
+ args[reqParam] = `test_${reqParam}`;
362
+ }
363
+ }
364
+ return args;
365
+ }
366
+ /**
367
+ * Infer argument mapping from a source tool to a target tool.
368
+ */
369
+ function inferArgMapping(_sourceTool, targetTool, sourceStepIndex) {
370
+ const targetSchema = targetTool.inputSchema;
371
+ if (!targetSchema?.properties)
372
+ return undefined;
373
+ const mapping = {};
374
+ const targetParams = Object.keys(targetSchema.properties);
375
+ // Common result field names to try
376
+ const commonResultFields = ['id', 'result', 'data', 'token', 'value', 'output'];
377
+ for (const param of targetParams) {
378
+ const paramLower = param.toLowerCase();
379
+ // Look for ID fields
380
+ if (paramLower.includes('id')) {
381
+ mapping[param] = `$steps[${sourceStepIndex}].result.id`;
382
+ }
383
+ // Look for token fields
384
+ else if (paramLower.includes('token')) {
385
+ const tokenType = paramLower.replace('_token', '').replace('token', '');
386
+ if (tokenType) {
387
+ mapping[param] = `$steps[${sourceStepIndex}].result.${tokenType}_token`;
388
+ }
389
+ else {
390
+ mapping[param] = `$steps[${sourceStepIndex}].result.token`;
391
+ }
392
+ }
393
+ // Look for matching field names
394
+ else if (commonResultFields.includes(paramLower)) {
395
+ mapping[param] = `$steps[${sourceStepIndex}].result.${paramLower}`;
396
+ }
397
+ }
398
+ return Object.keys(mapping).length > 0 ? mapping : undefined;
399
+ }
400
+ /**
401
+ * Infer mapping from a list operation to a detail operation.
402
+ */
403
+ function inferListToDetailMapping(listTool, detailTool) {
404
+ const detailSchema = detailTool.inputSchema;
405
+ if (!detailSchema?.properties)
406
+ return undefined;
407
+ const mapping = {};
408
+ const detailParams = Object.keys(detailSchema.properties);
409
+ for (const param of detailParams) {
410
+ const paramLower = param.toLowerCase();
411
+ // Map ID parameters to first item in list
412
+ if (paramLower.includes('id')) {
413
+ // Infer the array name from the list tool name
414
+ const resource = extractResourceName(listTool.name);
415
+ const arrayName = resource ? `${resource}s` : 'items';
416
+ mapping[param] = `$steps[0].result.${arrayName}[0].id`;
417
+ }
418
+ }
419
+ return Object.keys(mapping).length > 0 ? mapping : undefined;
420
+ }
421
+ /**
422
+ * Capitalize the first letter of a string.
423
+ */
424
+ function capitalize(str) {
425
+ return str.charAt(0).toUpperCase() + str.slice(1).replace(/_/g, ' ');
426
+ }
427
+ /**
428
+ * Generate YAML content for workflows.
429
+ */
430
+ export function generateWorkflowYamlContent(workflows) {
431
+ const lines = [
432
+ '# Auto-generated workflow definitions',
433
+ '# Generated by: bellwether check --generate-workflows',
434
+ '# ',
435
+ '# Usage: bellwether check --workflows ./bellwether-workflows.yaml',
436
+ '# ',
437
+ '# You can modify these workflows to add assertions, customize arguments,',
438
+ '# or add additional steps. See the Bellwether documentation for more details.',
439
+ '',
440
+ ];
441
+ for (let i = 0; i < workflows.length; i++) {
442
+ const workflow = workflows[i];
443
+ if (i > 0) {
444
+ lines.push('---');
445
+ }
446
+ lines.push(`id: ${workflow.id}`);
447
+ lines.push(`name: "${escapeYamlString(workflow.name)}"`);
448
+ lines.push(`description: "${escapeYamlString(workflow.description)}"`);
449
+ lines.push(`expectedOutcome: "${escapeYamlString(workflow.expectedOutcome)}"`);
450
+ lines.push('');
451
+ lines.push('steps:');
452
+ for (const step of workflow.steps) {
453
+ lines.push(` - tool: ${step.tool}`);
454
+ lines.push(` description: "${escapeYamlString(step.description)}"`);
455
+ if (step.args && Object.keys(step.args).length > 0) {
456
+ lines.push(' args:');
457
+ for (const [key, value] of Object.entries(step.args)) {
458
+ const formattedValue = formatYamlValue(value);
459
+ lines.push(` ${key}: ${formattedValue}`);
460
+ }
461
+ }
462
+ if (step.argMapping && Object.keys(step.argMapping).length > 0) {
463
+ lines.push(' argMapping:');
464
+ for (const [key, value] of Object.entries(step.argMapping)) {
465
+ lines.push(` ${key}: "${value}"`);
466
+ }
467
+ }
468
+ if (step.optional) {
469
+ lines.push(' optional: true');
470
+ }
471
+ // Add empty assertions section as a template
472
+ lines.push(' # assertions:');
473
+ lines.push(' # - path: "$.result"');
474
+ lines.push(' # condition: exists');
475
+ }
476
+ lines.push('');
477
+ }
478
+ return lines.join('\n');
479
+ }
480
+ /**
481
+ * Escape a string for YAML double-quoted strings.
482
+ */
483
+ function escapeYamlString(str) {
484
+ return str
485
+ .replace(/\\/g, '\\\\')
486
+ .replace(/"/g, '\\"')
487
+ .replace(/\n/g, '\\n');
488
+ }
489
+ /**
490
+ * Format a value for YAML output.
491
+ */
492
+ function formatYamlValue(value) {
493
+ if (value === null)
494
+ return 'null';
495
+ if (value === undefined)
496
+ return '~';
497
+ if (typeof value === 'string')
498
+ return `"${escapeYamlString(value)}"`;
499
+ if (typeof value === 'number' || typeof value === 'boolean')
500
+ return String(value);
501
+ if (Array.isArray(value)) {
502
+ if (value.length === 0)
503
+ return '[]';
504
+ return JSON.stringify(value);
505
+ }
506
+ if (typeof value === 'object') {
507
+ if (Object.keys(value).length === 0)
508
+ return '{}';
509
+ return JSON.stringify(value);
510
+ }
511
+ return String(value);
512
+ }
513
+ //# sourceMappingURL=auto-generator.js.map
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Workflow discovery - uses LLM to identify likely tool workflows.
3
+ */
4
+ import type { MCPTool } from '../transport/types.js';
5
+ import type { LLMClient } from '../llm/client.js';
6
+ import type { Workflow, WorkflowDiscoveryOptions } from './types.js';
7
+ /**
8
+ * Discovers likely workflows from a set of tools.
9
+ */
10
+ export declare class WorkflowDiscoverer {
11
+ private llm;
12
+ private options;
13
+ constructor(llm: LLMClient, options?: WorkflowDiscoveryOptions);
14
+ /**
15
+ * Discover workflows from available tools.
16
+ */
17
+ discover(tools: MCPTool[]): Promise<Workflow[]>;
18
+ /**
19
+ * Extract parameter information from a tool schema.
20
+ */
21
+ private extractParams;
22
+ /**
23
+ * Normalize and validate discovered workflows.
24
+ */
25
+ private normalizeWorkflows;
26
+ /**
27
+ * Normalize a workflow step.
28
+ */
29
+ private normalizeStep;
30
+ /**
31
+ * Generate a URL-safe ID from a name.
32
+ */
33
+ private generateId;
34
+ /**
35
+ * Fallback discovery when LLM fails.
36
+ * Tries to identify tools that might work together based on naming patterns.
37
+ */
38
+ private fallbackDiscovery;
39
+ }
40
+ //# sourceMappingURL=discovery.d.ts.map