@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,169 @@
1
+ /**
2
+ * Teams command for managing team selection in Bellwether Cloud.
3
+ *
4
+ * Allows users to list their teams and switch the active team for API requests.
5
+ */
6
+ import { Command } from 'commander';
7
+ import { getStoredSession, getSessionTeams, setActiveTeam, getTeamId, TEAM_ID_ENV_VAR, } from '../../../cloud/auth.js';
8
+ import { EXIT_CODES } from '../../../constants.js';
9
+ import * as output from '../../output.js';
10
+ export const teamsCommand = new Command('teams')
11
+ .description('Manage team selection for cloud operations')
12
+ .option('--json', 'Output as JSON')
13
+ .action(async (options) => {
14
+ // List teams by default
15
+ const session = getStoredSession();
16
+ if (!session) {
17
+ output.error('Not logged in.');
18
+ output.error('Run `bellwether login` first.');
19
+ process.exit(EXIT_CODES.ERROR);
20
+ }
21
+ const teams = getSessionTeams();
22
+ if (teams.length === 0) {
23
+ output.warn('No teams found in session.');
24
+ output.info('Try logging out and back in: `bellwether login --logout && bellwether login`');
25
+ return;
26
+ }
27
+ // Check for env var override
28
+ const envTeamId = process.env[TEAM_ID_ENV_VAR];
29
+ const effectiveTeamId = getTeamId();
30
+ if (options.json) {
31
+ output.info(JSON.stringify({
32
+ teams,
33
+ activeTeamId: session.activeTeamId,
34
+ effectiveTeamId,
35
+ envOverride: envTeamId || null,
36
+ }, null, 2));
37
+ return;
38
+ }
39
+ output.info('Your Teams');
40
+ output.info('-----------');
41
+ for (const team of teams) {
42
+ const isActive = team.id === session.activeTeamId;
43
+ const isEffective = team.id === effectiveTeamId;
44
+ const markers = [];
45
+ if (isActive)
46
+ markers.push('active');
47
+ if (envTeamId && isEffective)
48
+ markers.push('env override');
49
+ const suffix = markers.length > 0 ? ` (${markers.join(', ')})` : '';
50
+ const roleStr = `[${team.role}]`;
51
+ output.info(` ${isEffective ? '>' : ' '} ${team.name} ${roleStr} - ${team.plan}${suffix}`);
52
+ output.info(` ID: ${team.id}`);
53
+ }
54
+ if (envTeamId) {
55
+ output.info(`\nNote: ${TEAM_ID_ENV_VAR} is set, overriding session team.`);
56
+ }
57
+ if (teams.length > 1) {
58
+ output.info('\nUse `bellwether teams switch <team-id>` to change active team.');
59
+ }
60
+ });
61
+ // Subcommand: switch
62
+ teamsCommand
63
+ .command('switch [team-id]')
64
+ .description('Switch to a different team')
65
+ .action(async (teamIdArg) => {
66
+ const session = getStoredSession();
67
+ if (!session) {
68
+ output.error('Not logged in.');
69
+ output.error('Run `bellwether login` first.');
70
+ process.exit(EXIT_CODES.ERROR);
71
+ }
72
+ const teams = getSessionTeams();
73
+ if (teams.length === 0) {
74
+ output.warn('No teams found in session.');
75
+ output.info('Try logging out and back in: `bellwether login --logout && bellwether login`');
76
+ return;
77
+ }
78
+ if (teams.length === 1) {
79
+ output.info(`You only have access to one team: ${teams[0].name}`);
80
+ return;
81
+ }
82
+ const targetTeamId = teamIdArg;
83
+ // If no team ID provided, show interactive selection
84
+ if (!targetTeamId) {
85
+ output.info('Select a team:\n');
86
+ for (let i = 0; i < teams.length; i++) {
87
+ const team = teams[i];
88
+ const isActive = team.id === session.activeTeamId;
89
+ const marker = isActive ? ' (current)' : '';
90
+ output.info(` ${i + 1}. ${team.name} [${team.role}]${marker}`);
91
+ output.info(` ID: ${team.id}`);
92
+ }
93
+ output.info('\nRun `bellwether teams switch <team-id>` with a team ID from above.');
94
+ return;
95
+ }
96
+ // Find the target team
97
+ const targetTeam = teams.find(t => t.id === targetTeamId || t.name.toLowerCase() === targetTeamId.toLowerCase());
98
+ if (!targetTeam) {
99
+ output.error(`Team not found: ${targetTeamId}`);
100
+ output.error('\nAvailable teams:');
101
+ for (const team of teams) {
102
+ output.error(` - ${team.name} (${team.id})`);
103
+ }
104
+ process.exit(EXIT_CODES.ERROR);
105
+ }
106
+ // Check if already active
107
+ if (targetTeam.id === session.activeTeamId) {
108
+ output.info(`Already using team: ${targetTeam.name}`);
109
+ return;
110
+ }
111
+ // Switch team
112
+ const success = setActiveTeam(targetTeam.id);
113
+ if (success) {
114
+ output.info(`Switched to team: ${targetTeam.name}`);
115
+ output.info(`\nAll cloud commands will now use this team context.`);
116
+ // Warn about env var override
117
+ const envTeamId = process.env[TEAM_ID_ENV_VAR];
118
+ if (envTeamId && envTeamId !== targetTeam.id) {
119
+ output.warn(`\nNote: ${TEAM_ID_ENV_VAR} is set and will override this selection.`);
120
+ output.warn(`Unset it with: unset ${TEAM_ID_ENV_VAR}`);
121
+ }
122
+ }
123
+ else {
124
+ output.error('Failed to switch team. Please try logging in again.');
125
+ process.exit(EXIT_CODES.ERROR);
126
+ }
127
+ });
128
+ // Subcommand: current
129
+ teamsCommand
130
+ .command('current')
131
+ .description('Show the current active team')
132
+ .option('--json', 'Output as JSON')
133
+ .action(async (options) => {
134
+ const session = getStoredSession();
135
+ if (!session) {
136
+ output.error('Not logged in.');
137
+ process.exit(EXIT_CODES.ERROR);
138
+ }
139
+ const effectiveTeamId = getTeamId();
140
+ const envTeamId = process.env[TEAM_ID_ENV_VAR];
141
+ const teams = getSessionTeams();
142
+ const activeTeam = teams.find(t => t.id === effectiveTeamId);
143
+ if (options.json) {
144
+ output.info(JSON.stringify({
145
+ team: activeTeam || null,
146
+ source: envTeamId ? 'environment' : 'session',
147
+ envVar: envTeamId || null,
148
+ }, null, 2));
149
+ return;
150
+ }
151
+ if (!activeTeam) {
152
+ output.warn('No active team.');
153
+ if (teams.length > 0) {
154
+ output.info('Run `bellwether teams switch` to select a team.');
155
+ }
156
+ else {
157
+ output.info('Try logging out and back in: `bellwether login --logout && bellwether login`');
158
+ }
159
+ return;
160
+ }
161
+ output.info(`Current team: ${activeTeam.name}`);
162
+ output.info(` ID: ${activeTeam.id}`);
163
+ output.info(` Role: ${activeTeam.role}`);
164
+ output.info(` Plan: ${activeTeam.plan}`);
165
+ if (envTeamId) {
166
+ output.info(`\nSource: ${TEAM_ID_ENV_VAR} environment variable`);
167
+ }
168
+ });
169
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Upload command for uploading baselines to Bellwether Cloud.
3
+ *
4
+ * Can read baseline path from bellwether.yaml config.
5
+ */
6
+ import { Command } from 'commander';
7
+ export declare const uploadCommand: Command;
8
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Upload command for uploading baselines to Bellwether Cloud.
3
+ *
4
+ * Can read baseline path from bellwether.yaml config.
5
+ */
6
+ import { Command } from 'commander';
7
+ import { existsSync, readFileSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { getLinkedProject } from '../../../cloud/auth.js';
10
+ import { loadBaseline } from '../../../baseline/saver.js';
11
+ import { convertToCloudBaseline } from '../../../baseline/converter.js';
12
+ import { EXIT_CODES } from '../../../constants.js';
13
+ import * as output from '../../output.js';
14
+ import { getSeverityIcon } from '../../output.js';
15
+ import { loadConfigOrExit, getSessionTokenOrExit, createAuthenticatedClient } from './shared.js';
16
+ function resolveBaselinePath(pathValue, outputDir) {
17
+ return pathValue.startsWith('/') ? pathValue : join(outputDir, pathValue);
18
+ }
19
+ export const uploadCommand = new Command('upload')
20
+ .description('Upload a baseline to Bellwether Cloud')
21
+ .argument('[baseline]', 'Path to baseline JSON file (defaults to baseline.path in config)')
22
+ .option('-b, --baseline <path>', 'Path to baseline JSON file')
23
+ .option('-c, --config <path>', 'Path to config file')
24
+ .option('-p, --project <id>', 'Project ID to upload to (uses linked project if not specified)')
25
+ .option('--ci', 'CI mode - output URL only, exit 1 on breaking drift')
26
+ .option('--session <session>', 'Session token (overrides stored/env session)')
27
+ .option('--fail-on-drift', 'Exit with error if any behavioral drift detected')
28
+ .action(async (baselineArg, options) => {
29
+ // Get config settings
30
+ const config = loadConfigOrExit(options.config);
31
+ const outputDir = config.output.dir;
32
+ // Determine baseline path with priority:
33
+ // 1. Positional argument
34
+ // 2. --baseline flag
35
+ // 3. baseline.path from config
36
+ let baselinePath = baselineArg ?? options.baseline;
37
+ if (!baselinePath) {
38
+ baselinePath = resolveBaselinePath(config.baseline.path, outputDir);
39
+ }
40
+ const isCiMode = options.ci;
41
+ // Get session
42
+ const sessionToken = getSessionTokenOrExit(options.session, isCiMode ? 'BELLWETHER_SESSION not set' : 'Not authenticated. Run `bellwether login` first or set BELLWETHER_SESSION.');
43
+ // Check baseline file exists
44
+ if (!existsSync(baselinePath)) {
45
+ if (isCiMode) {
46
+ output.error(`Baseline not found: ${baselinePath}`);
47
+ process.exit(EXIT_CODES.ERROR);
48
+ }
49
+ output.error(`Baseline file not found: ${baselinePath}`);
50
+ output.error('\nCreate a baseline first:');
51
+ output.error(' 1. Run `bellwether check` (with output.format: json in config)');
52
+ output.error(' 2. Run `bellwether baseline save`');
53
+ process.exit(EXIT_CODES.ERROR);
54
+ }
55
+ // Determine project ID
56
+ let projectId = options.project;
57
+ if (!projectId) {
58
+ const link = getLinkedProject();
59
+ if (link) {
60
+ projectId = link.projectId;
61
+ if (!isCiMode) {
62
+ output.info(`Using linked project: ${link.projectName}`);
63
+ }
64
+ }
65
+ }
66
+ if (!projectId) {
67
+ if (isCiMode) {
68
+ output.error('No project specified');
69
+ process.exit(EXIT_CODES.ERROR);
70
+ }
71
+ output.error('No project specified.');
72
+ output.error('\nEither:');
73
+ output.error(' - Use --project <id> to specify a project');
74
+ output.error(' - Run `bellwether link` to link this directory to a project');
75
+ process.exit(EXIT_CODES.ERROR);
76
+ }
77
+ // Load and convert baseline
78
+ let cloudBaseline;
79
+ try {
80
+ // Try loading as cloud baseline first
81
+ const content = readFileSync(baselinePath, 'utf-8');
82
+ const parsed = JSON.parse(content);
83
+ if (parsed.version === '1.0' && parsed.metadata?.formatVersion === '1.0') {
84
+ // Already in cloud format
85
+ cloudBaseline = parsed;
86
+ }
87
+ else {
88
+ // Convert from local format
89
+ const localBaseline = loadBaseline(baselinePath);
90
+ cloudBaseline = convertToCloudBaseline(localBaseline);
91
+ }
92
+ }
93
+ catch (error) {
94
+ if (isCiMode) {
95
+ output.error(`Failed to load baseline: ${error instanceof Error ? error.message : error}`);
96
+ process.exit(EXIT_CODES.ERROR);
97
+ }
98
+ output.error('Failed to load baseline: ' + (error instanceof Error ? error.message : String(error)));
99
+ process.exit(EXIT_CODES.ERROR);
100
+ }
101
+ // Create client and upload
102
+ const client = createAuthenticatedClient(sessionToken, isCiMode ? 'Authentication failed' : 'Authentication failed. Run `bellwether login` to re-authenticate.');
103
+ if (!isCiMode) {
104
+ output.info(`Uploading baseline to project ${projectId}...`);
105
+ }
106
+ try {
107
+ const result = await client.uploadBaseline(projectId, cloudBaseline);
108
+ if (isCiMode) {
109
+ // CI mode - minimal output
110
+ output.info(result.viewUrl);
111
+ // Check for drift
112
+ if (result.version > 1) {
113
+ const diff = await client.getLatestDiff(projectId);
114
+ if (diff) {
115
+ if (diff.severity === 'breaking') {
116
+ output.error('Breaking changes detected');
117
+ process.exit(EXIT_CODES.ERROR);
118
+ }
119
+ if (options.failOnDrift && diff.severity !== 'none') {
120
+ output.error(`Behavioral drift detected: ${diff.severity}`);
121
+ process.exit(EXIT_CODES.ERROR);
122
+ }
123
+ }
124
+ }
125
+ }
126
+ else {
127
+ // Interactive mode - detailed output
128
+ output.info(`\nUpload successful!`);
129
+ output.info(`Version: ${result.version}`);
130
+ output.info(`View: ${result.viewUrl}`);
131
+ if (result.diffUrl) {
132
+ output.info(`Diff: ${result.diffUrl}`);
133
+ // Show diff summary
134
+ const diff = await client.getLatestDiff(projectId);
135
+ if (diff) {
136
+ output.info('\nChanges from previous version:');
137
+ printDiffSummary(diff);
138
+ if (diff.severity === 'breaking') {
139
+ output.info('\n⚠️ Breaking changes detected!');
140
+ }
141
+ }
142
+ }
143
+ else {
144
+ output.info('\nThis is the first baseline for this project.');
145
+ }
146
+ }
147
+ }
148
+ catch (error) {
149
+ if (isCiMode) {
150
+ output.error(`Upload failed: ${error instanceof Error ? error.message : error}`);
151
+ process.exit(EXIT_CODES.ERROR);
152
+ }
153
+ output.error('Upload failed: ' + (error instanceof Error ? error.message : String(error)));
154
+ process.exit(EXIT_CODES.ERROR);
155
+ }
156
+ });
157
+ /**
158
+ * Print a diff summary in human-readable format (verbose format).
159
+ */
160
+ function printDiffSummary(diff) {
161
+ output.info(` Severity: ${getSeverityIcon(diff.severity)} ${diff.severity}`);
162
+ if (diff.toolsAdded > 0) {
163
+ output.info(` Tools added: +${diff.toolsAdded}`);
164
+ }
165
+ if (diff.toolsRemoved > 0) {
166
+ output.info(` Tools removed: -${diff.toolsRemoved}`);
167
+ }
168
+ if (diff.toolsModified > 0) {
169
+ output.info(` Tools modified: ~${diff.toolsModified}`);
170
+ }
171
+ if (diff.behaviorChanges > 0) {
172
+ output.info(` Behavior changes: ${diff.behaviorChanges}`);
173
+ }
174
+ if (diff.toolsAdded === 0 &&
175
+ diff.toolsRemoved === 0 &&
176
+ diff.toolsModified === 0 &&
177
+ diff.behaviorChanges === 0) {
178
+ output.info(' No changes detected');
179
+ }
180
+ }
181
+ //# sourceMappingURL=upload.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Contract commands - validate MCP servers against contracts.
3
+ *
4
+ * Subcommands:
5
+ * - validate [path] Validate server against a contract file
6
+ * - generate [path] Generate a contract from current server state
7
+ * - show [path] Display contract contents
8
+ */
9
+ import { Command } from 'commander';
10
+ export declare const contractCommand: Command;
11
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Contract commands - validate MCP servers against contracts.
3
+ *
4
+ * Subcommands:
5
+ * - validate [path] Validate server against a contract file
6
+ * - generate [path] Generate a contract from current server state
7
+ * - show [path] Display contract contents
8
+ */
9
+ import { Command } from 'commander';
10
+ import { existsSync, writeFileSync, readFileSync } from 'fs';
11
+ import { join } from 'path';
12
+ import { loadContract, findContractFile, validateContract, generateContract, generateContractYaml, generateContractValidationMarkdown, } from '../../contract/index.js';
13
+ import { MCPClient } from '../../transport/mcp-client.js';
14
+ import { discover } from '../../discovery/discovery.js';
15
+ import { EXIT_CODES, CONTRACT_TESTING } from '../../constants.js';
16
+ import { loadConfig, ConfigNotFoundError } from '../../config/loader.js';
17
+ import * as output from '../output.js';
18
+ /**
19
+ * Default paths for contract files.
20
+ */
21
+ const DEFAULT_CONTRACT_FILENAMES = CONTRACT_TESTING.CONTRACT_FILENAMES;
22
+ function loadConfigOrExit(configPath) {
23
+ try {
24
+ return loadConfig(configPath);
25
+ }
26
+ catch (error) {
27
+ if (error instanceof ConfigNotFoundError) {
28
+ output.error(error.message);
29
+ process.exit(EXIT_CODES.ERROR);
30
+ }
31
+ throw error;
32
+ }
33
+ }
34
+ /**
35
+ * Find or use provided contract path.
36
+ */
37
+ function resolveContractPath(providedPath, baseDir) {
38
+ if (providedPath) {
39
+ const fullPath = providedPath.startsWith('/')
40
+ ? providedPath
41
+ : join(baseDir || '.', providedPath);
42
+ if (existsSync(fullPath)) {
43
+ return fullPath;
44
+ }
45
+ return null;
46
+ }
47
+ // Try default filenames
48
+ return findContractFile(baseDir || '.');
49
+ }
50
+ export const contractCommand = new Command('contract')
51
+ .description('Validate MCP servers against contract definitions')
52
+ .addHelpText('after', `
53
+ Examples:
54
+ $ bellwether contract validate npx @mcp/server # Validate against contract
55
+ $ bellwether contract generate npx @mcp/server # Generate contract from server
56
+ $ bellwether contract show # Show current contract
57
+ $ bellwether contract validate npx @mcp/server --contract ./my-contract.yaml
58
+ `);
59
+ // contract validate
60
+ contractCommand
61
+ .command('validate')
62
+ .description('Validate an MCP server against a contract file')
63
+ .argument('<server-command...>', 'MCP server command and arguments')
64
+ .option('-c, --config <path>', 'Path to config file')
65
+ .option('--contract <path>', 'Path to contract file (default: bellwether-contract.yaml)')
66
+ .option('--mode <mode>', 'Validation mode: strict, lenient, report')
67
+ .option('--fail-on-violation', 'Exit with error if violations detected (default in CI)')
68
+ .option('--format <format>', 'Output format: text, json, markdown')
69
+ .option('--timeout <ms>', 'Server startup timeout in milliseconds')
70
+ .action(async (serverCmd, options) => {
71
+ const config = loadConfigOrExit(options.config);
72
+ const outputDir = config.output.dir;
73
+ const defaultContractPath = config.contract.path;
74
+ const mode = (options.mode ?? config.contract.mode);
75
+ const format = options.format ?? config.contract.format;
76
+ const timeout = parseInt(options.timeout ?? String(config.contract.timeout), 10);
77
+ // Find contract file
78
+ const contractPath = resolveContractPath(options.contract ?? defaultContractPath, outputDir);
79
+ if (!contractPath) {
80
+ output.error('Contract file not found.');
81
+ output.error('');
82
+ output.error('Create a contract file by running:');
83
+ output.error(' bellwether contract generate <server-command>');
84
+ output.error('');
85
+ output.error(`Expected filenames: ${DEFAULT_CONTRACT_FILENAMES.join(', ')}`);
86
+ process.exit(EXIT_CODES.ERROR);
87
+ }
88
+ // Load contract
89
+ let contract;
90
+ try {
91
+ contract = loadContract(contractPath);
92
+ }
93
+ catch (error) {
94
+ output.error(`Failed to load contract: ${error instanceof Error ? error.message : error}`);
95
+ process.exit(EXIT_CODES.ERROR);
96
+ }
97
+ output.info(`Loading contract: ${contractPath}`);
98
+ output.info(`Validating against: ${serverCmd.join(' ')}`);
99
+ output.newline();
100
+ // Start MCP server
101
+ const mcpClient = new MCPClient({
102
+ timeout,
103
+ debug: false,
104
+ transport: 'stdio',
105
+ });
106
+ try {
107
+ // Parse server command
108
+ const command = serverCmd[0];
109
+ const args = serverCmd.slice(1);
110
+ await mcpClient.connect(command, args);
111
+ // Discover capabilities
112
+ const discovery = await discover(mcpClient, command, args);
113
+ // Validate against contract
114
+ const result = await validateContract(contract, discovery.tools, {
115
+ mode,
116
+ });
117
+ // Output results
118
+ switch (format) {
119
+ case 'json':
120
+ console.log(JSON.stringify(result, null, 2));
121
+ break;
122
+ case 'markdown':
123
+ console.log(generateContractValidationMarkdown(result));
124
+ break;
125
+ default:
126
+ // Text format
127
+ if (result.passed) {
128
+ output.success('Contract validation PASSED');
129
+ }
130
+ else {
131
+ output.error('Contract validation FAILED');
132
+ }
133
+ output.newline();
134
+ output.info(`Mode: ${result.mode}`);
135
+ output.info(`Tools checked: ${result.summary.toolsChecked}`);
136
+ output.info(`Tools passed: ${result.summary.toolsPassed}`);
137
+ output.info(`Violations: ${result.summary.totalViolations}`);
138
+ if (result.violations.length > 0) {
139
+ output.newline();
140
+ output.info('Violations:');
141
+ // Group by severity
142
+ const breaking = result.violations.filter(v => v.severity === 'breaking');
143
+ const warnings = result.violations.filter(v => v.severity === 'warning');
144
+ const infos = result.violations.filter(v => v.severity === 'info');
145
+ for (const v of breaking) {
146
+ output.error(` [BREAKING] ${v.tool || v.type}: ${v.message}`);
147
+ }
148
+ for (const v of warnings) {
149
+ output.warn(` [WARNING] ${v.tool || v.type}: ${v.message}`);
150
+ }
151
+ for (const v of infos.slice(0, 5)) {
152
+ output.info(` [INFO] ${v.tool || v.type}: ${v.message}`);
153
+ }
154
+ if (infos.length > 5) {
155
+ output.info(` ... and ${infos.length - 5} more info violations`);
156
+ }
157
+ }
158
+ }
159
+ // Exit with appropriate code
160
+ const failOnViolation = options.failOnViolation ? true : (config.contract.failOnViolation ?? !!process.env.CI);
161
+ if (!result.passed && failOnViolation) {
162
+ process.exit(EXIT_CODES.BREAKING);
163
+ }
164
+ }
165
+ catch (error) {
166
+ output.error(`Validation failed: ${error instanceof Error ? error.message : error}`);
167
+ process.exit(EXIT_CODES.ERROR);
168
+ }
169
+ finally {
170
+ await mcpClient.disconnect();
171
+ }
172
+ });
173
+ // contract generate
174
+ contractCommand
175
+ .command('generate')
176
+ .description('Generate a contract file from current server state')
177
+ .argument('<server-command...>', 'MCP server command and arguments')
178
+ .option('-c, --config <path>', 'Path to config file')
179
+ .option('-o, --output <path>', 'Output path for contract file')
180
+ .option('--timeout <ms>', 'Server startup timeout in milliseconds')
181
+ .option('-f, --force', 'Overwrite existing contract file')
182
+ .action(async (serverCmd, options) => {
183
+ const config = loadConfigOrExit(options.config);
184
+ const outputDir = config.output.dir;
185
+ const defaultOutput = config.contract.path ?? DEFAULT_CONTRACT_FILENAMES[0];
186
+ const outputOption = options.output ?? defaultOutput;
187
+ const outputPath = outputOption.startsWith('/')
188
+ ? outputOption
189
+ : join(outputDir, outputOption);
190
+ const timeout = parseInt(options.timeout ?? String(config.contract.timeout), 10);
191
+ // Check for existing file
192
+ if (existsSync(outputPath) && !options.force) {
193
+ output.error(`Contract file already exists: ${outputPath}`);
194
+ output.error('Use --force to overwrite.');
195
+ process.exit(EXIT_CODES.ERROR);
196
+ }
197
+ output.info(`Generating contract from: ${serverCmd.join(' ')}`);
198
+ // Start MCP server
199
+ const mcpClient = new MCPClient({
200
+ timeout,
201
+ debug: false,
202
+ transport: 'stdio',
203
+ });
204
+ try {
205
+ // Parse server command
206
+ const command = serverCmd[0];
207
+ const args = serverCmd.slice(1);
208
+ await mcpClient.connect(command, args);
209
+ // Discover capabilities
210
+ const discovery = await discover(mcpClient, command, args);
211
+ // Generate contract
212
+ const serverName = discovery.serverInfo?.name || 'MCP Server';
213
+ const contract = generateContract(discovery.tools, serverName);
214
+ const yaml = generateContractYaml(contract);
215
+ // Write to file
216
+ writeFileSync(outputPath, yaml);
217
+ output.success(`Contract generated: ${outputPath}`);
218
+ output.newline();
219
+ output.info(` Server: ${serverName}`);
220
+ output.info(` Tools: ${discovery.tools.length}`);
221
+ output.info(` Parameters: ${countParameters(contract)}`);
222
+ }
223
+ catch (error) {
224
+ output.error(`Generation failed: ${error instanceof Error ? error.message : error}`);
225
+ process.exit(EXIT_CODES.ERROR);
226
+ }
227
+ finally {
228
+ await mcpClient.disconnect();
229
+ }
230
+ });
231
+ // contract show
232
+ contractCommand
233
+ .command('show')
234
+ .description('Display contract file contents')
235
+ .argument('[path]', 'Path to contract file')
236
+ .option('-c, --config <path>', 'Path to config file')
237
+ .option('--json', 'Output as JSON instead of YAML')
238
+ .action(async (contractPath, options) => {
239
+ const config = loadConfigOrExit(options.config);
240
+ const outputDir = config.output.dir;
241
+ const path = resolveContractPath(contractPath ?? config.contract.path, outputDir);
242
+ if (!path) {
243
+ output.error('Contract file not found.');
244
+ output.error(`Expected filenames: ${DEFAULT_CONTRACT_FILENAMES.join(', ')}`);
245
+ process.exit(EXIT_CODES.ERROR);
246
+ }
247
+ try {
248
+ const contract = loadContract(path);
249
+ output.info(`Contract: ${path}`);
250
+ output.info(`Version: ${contract.version}`);
251
+ if (contract.server?.name) {
252
+ output.info(`Server: ${contract.server.name}`);
253
+ }
254
+ output.newline();
255
+ if (options.json) {
256
+ console.log(JSON.stringify(contract, null, 2));
257
+ }
258
+ else {
259
+ const content = readFileSync(path, 'utf-8');
260
+ console.log(content);
261
+ }
262
+ }
263
+ catch (error) {
264
+ output.error(`Failed to load contract: ${error instanceof Error ? error.message : error}`);
265
+ process.exit(EXIT_CODES.ERROR);
266
+ }
267
+ });
268
+ /**
269
+ * Count total parameters in a contract.
270
+ */
271
+ function countParameters(contract) {
272
+ let count = 0;
273
+ for (const toolContract of Object.values(contract.tools)) {
274
+ if (toolContract.input) {
275
+ count += Object.keys(toolContract.input).length;
276
+ }
277
+ }
278
+ return count;
279
+ }
280
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const discoverCommand: Command;
3
+ //# sourceMappingURL=discover.d.ts.map