@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,33 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Preset configuration structure.
4
+ */
5
+ interface Preset {
6
+ name: string;
7
+ llm: {
8
+ provider: 'openai' | 'anthropic' | 'ollama';
9
+ model?: string;
10
+ };
11
+ interview: {
12
+ maxQuestionsPerTool?: number;
13
+ personas?: string[];
14
+ timeout?: number;
15
+ skipErrorTests?: boolean;
16
+ };
17
+ output: {
18
+ format?: 'markdown' | 'json' | 'both';
19
+ outputDir?: string;
20
+ };
21
+ }
22
+ export declare const presetCommand: Command;
23
+ /**
24
+ * Get the preset config to merge with main config.
25
+ * Returns null if no current preset is set.
26
+ */
27
+ export declare function getActivePresetConfig(): Partial<{
28
+ llm: Preset['llm'];
29
+ interview: Preset['interview'];
30
+ output: Preset['output'];
31
+ }> | null;
32
+ export {};
33
+ //# sourceMappingURL=preset.d.ts.map
@@ -0,0 +1,297 @@
1
+ import { Command } from 'commander';
2
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, unlinkSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { stringify } from 'yaml';
6
+ import { z } from 'zod';
7
+ import { parseYamlSecure } from '../../utils/yaml-parser.js';
8
+ import * as output from '../output.js';
9
+ /**
10
+ * Zod schema for preset validation to prevent untrusted YAML injection.
11
+ */
12
+ const presetSchema = z.object({
13
+ name: z.string().min(1).max(64),
14
+ llm: z.object({
15
+ provider: z.enum(['openai', 'anthropic', 'ollama']),
16
+ model: z.string().optional(),
17
+ }),
18
+ interview: z.object({
19
+ maxQuestionsPerTool: z.number().positive().optional(),
20
+ personas: z.array(z.string()).optional(),
21
+ timeout: z.number().positive().optional(),
22
+ skipErrorTests: z.boolean().optional(),
23
+ }).optional().default({}),
24
+ output: z.object({
25
+ format: z.enum(['markdown', 'json', 'both']).optional(),
26
+ outputDir: z.string().optional(),
27
+ }).optional().default({}),
28
+ });
29
+ const PROFILES_DIR = join(homedir(), '.bellwether', 'presets');
30
+ const CURRENT_PROFILE_FILE = join(homedir(), '.bellwether', 'current-preset');
31
+ /**
32
+ * Validate preset name to prevent path traversal attacks.
33
+ * Only alphanumeric characters, hyphens, and underscores are allowed.
34
+ */
35
+ function isValidPresetName(name) {
36
+ return /^[a-zA-Z0-9_-]+$/.test(name) && name.length > 0 && name.length <= 64;
37
+ }
38
+ function ensurePresetsDir() {
39
+ if (!existsSync(PROFILES_DIR)) {
40
+ mkdirSync(PROFILES_DIR, { recursive: true });
41
+ }
42
+ }
43
+ function getPresetPath(name) {
44
+ if (!isValidPresetName(name)) {
45
+ throw new Error(`Invalid preset name: "${name}". Only alphanumeric characters, hyphens, and underscores are allowed.`);
46
+ }
47
+ return join(PROFILES_DIR, `${name}.yaml`);
48
+ }
49
+ function loadPreset(name) {
50
+ const path = getPresetPath(name);
51
+ if (!existsSync(path)) {
52
+ return null;
53
+ }
54
+ const content = readFileSync(path, 'utf-8');
55
+ return parseYamlSecure(content);
56
+ }
57
+ function savePreset(preset) {
58
+ ensurePresetsDir();
59
+ const path = getPresetPath(preset.name);
60
+ writeFileSync(path, stringify(preset));
61
+ }
62
+ function deletePreset(name) {
63
+ const path = getPresetPath(name);
64
+ if (!existsSync(path)) {
65
+ return false;
66
+ }
67
+ unlinkSync(path);
68
+ return true;
69
+ }
70
+ function listPresets() {
71
+ ensurePresetsDir();
72
+ return readdirSync(PROFILES_DIR)
73
+ .filter(f => f.endsWith('.yaml'))
74
+ .map(f => f.replace('.yaml', ''));
75
+ }
76
+ function getCurrentPreset() {
77
+ if (!existsSync(CURRENT_PROFILE_FILE)) {
78
+ return null;
79
+ }
80
+ return readFileSync(CURRENT_PROFILE_FILE, 'utf-8').trim();
81
+ }
82
+ function setCurrentPreset(name) {
83
+ ensurePresetsDir();
84
+ if (name) {
85
+ writeFileSync(CURRENT_PROFILE_FILE, name);
86
+ }
87
+ else if (existsSync(CURRENT_PROFILE_FILE)) {
88
+ unlinkSync(CURRENT_PROFILE_FILE);
89
+ }
90
+ }
91
+ export const presetCommand = new Command('preset')
92
+ .description('Manage test configuration presets (deprecated: use bellwether init --preset)')
93
+ .addHelpText('after', `
94
+ Note: Runtime presets are deprecated.
95
+ Use 'bellwether init --preset <name>' to create a config file with preset settings.
96
+
97
+ Available init presets: ci, security, thorough, local
98
+ `)
99
+ .addCommand(new Command('create')
100
+ .description('Create a new preset (deprecated)')
101
+ .argument('<name>', 'Preset name')
102
+ .option('-p, --provider <provider>', 'LLM provider (openai, anthropic, ollama)', 'openai')
103
+ .option('-m, --model <model>', 'LLM model')
104
+ .option('-q, --max-questions <n>', 'Max questions per tool')
105
+ .option('--personas <list>', 'Comma-separated list of personas')
106
+ .option('-f, --format <format>', 'Output format (markdown, json, both)')
107
+ .option('--use', 'Set as current preset after creation')
108
+ .action((name, options) => {
109
+ output.warn('Warning: Runtime presets are deprecated.');
110
+ output.warn('Use `bellwether init --preset <name>` to create a config file instead.\n');
111
+ if (loadPreset(name)) {
112
+ output.error(`Preset '${name}' already exists. Use 'preset update' to modify it.`);
113
+ process.exit(1);
114
+ }
115
+ const preset = {
116
+ name,
117
+ llm: {
118
+ provider: options.provider,
119
+ model: options.model,
120
+ },
121
+ interview: {
122
+ maxQuestionsPerTool: options.maxQuestions ? parseInt(options.maxQuestions, 10) : undefined,
123
+ personas: options.personas ? options.personas.split(',').map((s) => s.trim()) : undefined,
124
+ },
125
+ output: {
126
+ format: options.format,
127
+ },
128
+ };
129
+ savePreset(preset);
130
+ output.info(`Preset '${name}' created.`);
131
+ if (options.use) {
132
+ setCurrentPreset(name);
133
+ output.info(`Set '${name}' as current preset.`);
134
+ }
135
+ }))
136
+ .addCommand(new Command('list')
137
+ .description('List all presets')
138
+ .action(() => {
139
+ const presets = listPresets();
140
+ const current = getCurrentPreset();
141
+ if (presets.length === 0) {
142
+ output.info('No presets found.');
143
+ output.info('Create one with: bellwether preset create <name>');
144
+ return;
145
+ }
146
+ output.info('Available presets:\n');
147
+ for (const name of presets) {
148
+ const marker = name === current ? ' (current)' : '';
149
+ const preset = loadPreset(name);
150
+ if (preset) {
151
+ output.info(` ${name}${marker}`);
152
+ output.info(` Provider: ${preset.llm.provider}`);
153
+ if (preset.llm.model) {
154
+ output.info(` Model: ${preset.llm.model}`);
155
+ }
156
+ }
157
+ }
158
+ }))
159
+ .addCommand(new Command('use')
160
+ .description('Set the current preset (deprecated)')
161
+ .argument('<name>', 'Preset name')
162
+ .action((name) => {
163
+ output.warn('Warning: Runtime presets are deprecated.');
164
+ output.warn('The test command now reads settings from bellwether.yaml.');
165
+ output.warn('Use `bellwether init --preset <name>` to create a config file.\n');
166
+ if (!loadPreset(name)) {
167
+ output.error(`Preset '${name}' not found.`);
168
+ output.info('Available presets: ' + (listPresets().join(', ') || 'none'));
169
+ process.exit(1);
170
+ }
171
+ setCurrentPreset(name);
172
+ output.info(`Set '${name}' as current preset.`);
173
+ }))
174
+ .addCommand(new Command('show')
175
+ .description('Show preset details')
176
+ .argument('[name]', 'Preset name (defaults to current)')
177
+ .action((name) => {
178
+ const presetName = name ?? getCurrentPreset();
179
+ if (!presetName) {
180
+ output.error('No preset specified and no current preset set.');
181
+ process.exit(1);
182
+ }
183
+ const preset = loadPreset(presetName);
184
+ if (!preset) {
185
+ output.error(`Preset '${presetName}' not found.`);
186
+ process.exit(1);
187
+ }
188
+ output.info(`Preset: ${presetName}`);
189
+ output.info(stringify(preset));
190
+ }))
191
+ .addCommand(new Command('delete')
192
+ .description('Delete a preset')
193
+ .argument('<name>', 'Preset name')
194
+ .action((name) => {
195
+ if (!deletePreset(name)) {
196
+ output.error(`Preset '${name}' not found.`);
197
+ process.exit(1);
198
+ }
199
+ // Clear current if deleted
200
+ if (getCurrentPreset() === name) {
201
+ setCurrentPreset(null);
202
+ }
203
+ output.info(`Preset '${name}' deleted.`);
204
+ }))
205
+ .addCommand(new Command('update')
206
+ .description('Update an existing preset')
207
+ .argument('<name>', 'Preset name')
208
+ .option('-p, --provider <provider>', 'LLM provider')
209
+ .option('-m, --model <model>', 'LLM model')
210
+ .option('-q, --max-questions <n>', 'Max questions per tool')
211
+ .option('--personas <list>', 'Comma-separated list of personas')
212
+ .option('-f, --format <format>', 'Output format')
213
+ .action((name, options) => {
214
+ const preset = loadPreset(name);
215
+ if (!preset) {
216
+ output.error(`Preset '${name}' not found.`);
217
+ process.exit(1);
218
+ }
219
+ if (options.provider) {
220
+ preset.llm.provider = options.provider;
221
+ }
222
+ if (options.model) {
223
+ preset.llm.model = options.model;
224
+ }
225
+ if (options.maxQuestions) {
226
+ preset.interview.maxQuestionsPerTool = parseInt(options.maxQuestions, 10);
227
+ }
228
+ if (options.personas) {
229
+ preset.interview.personas = options.personas.split(',').map((s) => s.trim());
230
+ }
231
+ if (options.format) {
232
+ preset.output.format = options.format;
233
+ }
234
+ savePreset(preset);
235
+ output.info(`Preset '${name}' updated.`);
236
+ }))
237
+ .addCommand(new Command('export')
238
+ .description('Export preset as YAML')
239
+ .argument('[name]', 'Preset name (defaults to current)')
240
+ .action((name) => {
241
+ const presetName = name ?? getCurrentPreset();
242
+ if (!presetName) {
243
+ output.error('No preset specified and no current preset set.');
244
+ process.exit(1);
245
+ }
246
+ const preset = loadPreset(presetName);
247
+ if (!preset) {
248
+ output.error(`Preset '${presetName}' not found.`);
249
+ process.exit(1);
250
+ }
251
+ output.info(stringify(preset));
252
+ }))
253
+ .addCommand(new Command('import')
254
+ .description('Import preset from YAML file')
255
+ .argument('<file>', 'YAML file path')
256
+ .option('-n, --name <name>', 'Override preset name')
257
+ .action((file, options) => {
258
+ if (!existsSync(file)) {
259
+ output.error(`File not found: ${file}`);
260
+ process.exit(1);
261
+ }
262
+ const content = readFileSync(file, 'utf-8');
263
+ const rawPreset = parseYamlSecure(content);
264
+ // Validate preset against schema to prevent malicious YAML
265
+ const parseResult = presetSchema.safeParse({
266
+ ...rawPreset,
267
+ name: options.name || rawPreset?.name,
268
+ });
269
+ if (!parseResult.success) {
270
+ output.error('Invalid preset format:');
271
+ for (const issue of parseResult.error.issues) {
272
+ output.error(` - ${issue.path.join('.')}: ${issue.message}`);
273
+ }
274
+ process.exit(1);
275
+ }
276
+ const preset = parseResult.data;
277
+ savePreset(preset);
278
+ output.info(`Preset '${preset.name}' imported.`);
279
+ }));
280
+ /**
281
+ * Get the preset config to merge with main config.
282
+ * Returns null if no current preset is set.
283
+ */
284
+ export function getActivePresetConfig() {
285
+ const current = getCurrentPreset();
286
+ if (!current)
287
+ return null;
288
+ const preset = loadPreset(current);
289
+ if (!preset)
290
+ return null;
291
+ return {
292
+ llm: preset.llm,
293
+ interview: preset.interview,
294
+ output: preset.output,
295
+ };
296
+ }
297
+ //# sourceMappingURL=preset.js.map
@@ -0,0 +1,33 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Profile configuration structure.
4
+ */
5
+ interface Profile {
6
+ name: string;
7
+ llm: {
8
+ provider: 'openai' | 'anthropic' | 'ollama';
9
+ model?: string;
10
+ };
11
+ interview: {
12
+ maxQuestionsPerTool?: number;
13
+ personas?: string[];
14
+ timeout?: number;
15
+ skipErrorTests?: boolean;
16
+ };
17
+ output: {
18
+ format?: 'markdown' | 'json' | 'both';
19
+ outputDir?: string;
20
+ };
21
+ }
22
+ export declare const profileCommand: Command;
23
+ /**
24
+ * Get the profile config to merge with main config.
25
+ * Returns null if no current profile is set.
26
+ */
27
+ export declare function getActiveProfileConfig(): Partial<{
28
+ llm: Profile['llm'];
29
+ interview: Profile['interview'];
30
+ output: Profile['output'];
31
+ }> | null;
32
+ export {};
33
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1,286 @@
1
+ import { Command } from 'commander';
2
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, unlinkSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { homedir } from 'os';
5
+ import { stringify } from 'yaml';
6
+ import { z } from 'zod';
7
+ import { parseYamlSecure } from '../../utils/yaml-parser.js';
8
+ import * as output from '../output.js';
9
+ /**
10
+ * Zod schema for profile validation to prevent untrusted YAML injection.
11
+ */
12
+ const profileSchema = z.object({
13
+ name: z.string().min(1).max(64),
14
+ llm: z.object({
15
+ provider: z.enum(['openai', 'anthropic', 'ollama']),
16
+ model: z.string().optional(),
17
+ }),
18
+ interview: z.object({
19
+ maxQuestionsPerTool: z.number().positive().optional(),
20
+ personas: z.array(z.string()).optional(),
21
+ timeout: z.number().positive().optional(),
22
+ skipErrorTests: z.boolean().optional(),
23
+ }).optional().default({}),
24
+ output: z.object({
25
+ format: z.enum(['markdown', 'json', 'both']).optional(),
26
+ outputDir: z.string().optional(),
27
+ }).optional().default({}),
28
+ });
29
+ const PROFILES_DIR = join(homedir(), '.bellwether', 'profiles');
30
+ const CURRENT_PROFILE_FILE = join(homedir(), '.bellwether', 'current-profile');
31
+ /**
32
+ * Validate profile name to prevent path traversal attacks.
33
+ * Only alphanumeric characters, hyphens, and underscores are allowed.
34
+ */
35
+ function isValidProfileName(name) {
36
+ return /^[a-zA-Z0-9_-]+$/.test(name) && name.length > 0 && name.length <= 64;
37
+ }
38
+ function ensureProfilesDir() {
39
+ if (!existsSync(PROFILES_DIR)) {
40
+ mkdirSync(PROFILES_DIR, { recursive: true });
41
+ }
42
+ }
43
+ function getProfilePath(name) {
44
+ if (!isValidProfileName(name)) {
45
+ throw new Error(`Invalid profile name: "${name}". Only alphanumeric characters, hyphens, and underscores are allowed.`);
46
+ }
47
+ return join(PROFILES_DIR, `${name}.yaml`);
48
+ }
49
+ function loadProfile(name) {
50
+ const path = getProfilePath(name);
51
+ if (!existsSync(path)) {
52
+ return null;
53
+ }
54
+ const content = readFileSync(path, 'utf-8');
55
+ return parseYamlSecure(content);
56
+ }
57
+ function saveProfile(profile) {
58
+ ensureProfilesDir();
59
+ const path = getProfilePath(profile.name);
60
+ writeFileSync(path, stringify(profile));
61
+ }
62
+ function deleteProfile(name) {
63
+ const path = getProfilePath(name);
64
+ if (!existsSync(path)) {
65
+ return false;
66
+ }
67
+ unlinkSync(path);
68
+ return true;
69
+ }
70
+ function listProfiles() {
71
+ ensureProfilesDir();
72
+ return readdirSync(PROFILES_DIR)
73
+ .filter(f => f.endsWith('.yaml'))
74
+ .map(f => f.replace('.yaml', ''));
75
+ }
76
+ function getCurrentProfile() {
77
+ if (!existsSync(CURRENT_PROFILE_FILE)) {
78
+ return null;
79
+ }
80
+ return readFileSync(CURRENT_PROFILE_FILE, 'utf-8').trim();
81
+ }
82
+ function setCurrentProfile(name) {
83
+ ensureProfilesDir();
84
+ if (name) {
85
+ writeFileSync(CURRENT_PROFILE_FILE, name);
86
+ }
87
+ else if (existsSync(CURRENT_PROFILE_FILE)) {
88
+ unlinkSync(CURRENT_PROFILE_FILE);
89
+ }
90
+ }
91
+ export const profileCommand = new Command('profile')
92
+ .description('Manage interview profiles')
93
+ .addCommand(new Command('create')
94
+ .description('Create a new profile')
95
+ .argument('<name>', 'Profile name')
96
+ .option('-p, --provider <provider>', 'LLM provider (openai, anthropic, ollama)', 'openai')
97
+ .option('-m, --model <model>', 'LLM model')
98
+ .option('-q, --max-questions <n>', 'Max questions per tool')
99
+ .option('--personas <list>', 'Comma-separated list of personas')
100
+ .option('-f, --format <format>', 'Output format (markdown, json, both)')
101
+ .option('--use', 'Set as current profile after creation')
102
+ .action((name, options) => {
103
+ if (loadProfile(name)) {
104
+ output.error(`Profile '${name}' already exists. Use 'profile update' to modify it.`);
105
+ process.exit(1);
106
+ }
107
+ const profile = {
108
+ name,
109
+ llm: {
110
+ provider: options.provider,
111
+ model: options.model,
112
+ },
113
+ interview: {
114
+ maxQuestionsPerTool: options.maxQuestions ? parseInt(options.maxQuestions, 10) : undefined,
115
+ personas: options.personas ? options.personas.split(',').map((s) => s.trim()) : undefined,
116
+ },
117
+ output: {
118
+ format: options.format,
119
+ },
120
+ };
121
+ saveProfile(profile);
122
+ output.info(`Profile '${name}' created.`);
123
+ if (options.use) {
124
+ setCurrentProfile(name);
125
+ output.info(`Set '${name}' as current profile.`);
126
+ }
127
+ }))
128
+ .addCommand(new Command('list')
129
+ .description('List all profiles')
130
+ .action(() => {
131
+ const profiles = listProfiles();
132
+ const current = getCurrentProfile();
133
+ if (profiles.length === 0) {
134
+ output.info('No profiles found.');
135
+ output.info('Create one with: bellwether profile create <name>');
136
+ return;
137
+ }
138
+ output.info('Available profiles:\n');
139
+ for (const name of profiles) {
140
+ const marker = name === current ? ' (current)' : '';
141
+ const profile = loadProfile(name);
142
+ if (profile) {
143
+ output.info(` ${name}${marker}`);
144
+ output.info(` Provider: ${profile.llm.provider}`);
145
+ if (profile.llm.model) {
146
+ output.info(` Model: ${profile.llm.model}`);
147
+ }
148
+ }
149
+ }
150
+ }))
151
+ .addCommand(new Command('use')
152
+ .description('Set the current profile')
153
+ .argument('<name>', 'Profile name')
154
+ .action((name) => {
155
+ if (!loadProfile(name)) {
156
+ output.error(`Profile '${name}' not found.`);
157
+ output.info('Available profiles: ' + (listProfiles().join(', ') || 'none'));
158
+ process.exit(1);
159
+ }
160
+ setCurrentProfile(name);
161
+ output.info(`Set '${name}' as current profile.`);
162
+ }))
163
+ .addCommand(new Command('show')
164
+ .description('Show profile details')
165
+ .argument('[name]', 'Profile name (defaults to current)')
166
+ .action((name) => {
167
+ const profileName = name ?? getCurrentProfile();
168
+ if (!profileName) {
169
+ output.error('No profile specified and no current profile set.');
170
+ process.exit(1);
171
+ }
172
+ const profile = loadProfile(profileName);
173
+ if (!profile) {
174
+ output.error(`Profile '${profileName}' not found.`);
175
+ process.exit(1);
176
+ }
177
+ output.info(`Profile: ${profileName}`);
178
+ output.info(stringify(profile));
179
+ }))
180
+ .addCommand(new Command('delete')
181
+ .description('Delete a profile')
182
+ .argument('<name>', 'Profile name')
183
+ .action((name) => {
184
+ if (!deleteProfile(name)) {
185
+ output.error(`Profile '${name}' not found.`);
186
+ process.exit(1);
187
+ }
188
+ // Clear current if deleted
189
+ if (getCurrentProfile() === name) {
190
+ setCurrentProfile(null);
191
+ }
192
+ output.info(`Profile '${name}' deleted.`);
193
+ }))
194
+ .addCommand(new Command('update')
195
+ .description('Update an existing profile')
196
+ .argument('<name>', 'Profile name')
197
+ .option('-p, --provider <provider>', 'LLM provider')
198
+ .option('-m, --model <model>', 'LLM model')
199
+ .option('-q, --max-questions <n>', 'Max questions per tool')
200
+ .option('--personas <list>', 'Comma-separated list of personas')
201
+ .option('-f, --format <format>', 'Output format')
202
+ .action((name, options) => {
203
+ const profile = loadProfile(name);
204
+ if (!profile) {
205
+ output.error(`Profile '${name}' not found.`);
206
+ process.exit(1);
207
+ }
208
+ if (options.provider) {
209
+ profile.llm.provider = options.provider;
210
+ }
211
+ if (options.model) {
212
+ profile.llm.model = options.model;
213
+ }
214
+ if (options.maxQuestions) {
215
+ profile.interview.maxQuestionsPerTool = parseInt(options.maxQuestions, 10);
216
+ }
217
+ if (options.personas) {
218
+ profile.interview.personas = options.personas.split(',').map((s) => s.trim());
219
+ }
220
+ if (options.format) {
221
+ profile.output.format = options.format;
222
+ }
223
+ saveProfile(profile);
224
+ output.info(`Profile '${name}' updated.`);
225
+ }))
226
+ .addCommand(new Command('export')
227
+ .description('Export profile as YAML')
228
+ .argument('[name]', 'Profile name (defaults to current)')
229
+ .action((name) => {
230
+ const profileName = name ?? getCurrentProfile();
231
+ if (!profileName) {
232
+ output.error('No profile specified and no current profile set.');
233
+ process.exit(1);
234
+ }
235
+ const profile = loadProfile(profileName);
236
+ if (!profile) {
237
+ output.error(`Profile '${profileName}' not found.`);
238
+ process.exit(1);
239
+ }
240
+ output.info(stringify(profile));
241
+ }))
242
+ .addCommand(new Command('import')
243
+ .description('Import profile from YAML file')
244
+ .argument('<file>', 'YAML file path')
245
+ .option('-n, --name <name>', 'Override profile name')
246
+ .action((file, options) => {
247
+ if (!existsSync(file)) {
248
+ output.error(`File not found: ${file}`);
249
+ process.exit(1);
250
+ }
251
+ const content = readFileSync(file, 'utf-8');
252
+ const rawProfile = parseYamlSecure(content);
253
+ // Validate profile against schema to prevent malicious YAML
254
+ const parseResult = profileSchema.safeParse({
255
+ ...rawProfile,
256
+ name: options.name || rawProfile?.name,
257
+ });
258
+ if (!parseResult.success) {
259
+ output.error('Invalid profile format:');
260
+ for (const issue of parseResult.error.issues) {
261
+ output.error(` - ${issue.path.join('.')}: ${issue.message}`);
262
+ }
263
+ process.exit(1);
264
+ }
265
+ const profile = parseResult.data;
266
+ saveProfile(profile);
267
+ output.info(`Profile '${profile.name}' imported.`);
268
+ }));
269
+ /**
270
+ * Get the profile config to merge with main config.
271
+ * Returns null if no current profile is set.
272
+ */
273
+ export function getActiveProfileConfig() {
274
+ const current = getCurrentProfile();
275
+ if (!current)
276
+ return null;
277
+ const profile = loadProfile(current);
278
+ if (!profile)
279
+ return null;
280
+ return {
281
+ llm: profile.llm,
282
+ interview: profile.interview,
283
+ output: profile.output,
284
+ };
285
+ }
286
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Registry command - search and lookup MCP servers from the registry.
3
+ */
4
+ import { Command } from 'commander';
5
+ /**
6
+ * Create a new registry command instance.
7
+ * Useful for testing where fresh command instances are needed.
8
+ */
9
+ export declare function createRegistryCommand(): Command;
10
+ export declare const registryCommand: Command;
11
+ //# sourceMappingURL=registry.d.ts.map