webmcp-cli 1.0.0 → 1.2.1

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 (347) hide show
  1. package/dist/agent/features/agent-simulator.d.ts +67 -0
  2. package/dist/agent/features/agent-simulator.js +368 -0
  3. package/dist/agent/features/agent-simulator.js.map +1 -0
  4. package/dist/agent/features/index.d.ts +8 -0
  5. package/dist/agent/features/index.js +9 -0
  6. package/dist/agent/features/index.js.map +1 -0
  7. package/dist/agent/features/simulation-judge.d.ts +78 -0
  8. package/dist/agent/features/simulation-judge.js +276 -0
  9. package/dist/agent/features/simulation-judge.js.map +1 -0
  10. package/dist/agent/features/test-case-generator.d.ts +35 -0
  11. package/dist/agent/features/test-case-generator.js +257 -0
  12. package/dist/agent/features/test-case-generator.js.map +1 -0
  13. package/dist/agent/index.d.ts +7 -0
  14. package/dist/agent/index.js +10 -0
  15. package/dist/agent/index.js.map +1 -0
  16. package/dist/agent/llm-client.d.ts +76 -0
  17. package/dist/agent/llm-client.js +198 -0
  18. package/dist/agent/llm-client.js.map +1 -0
  19. package/dist/audit/run-single-page-audit.d.ts +41 -0
  20. package/dist/audit/run-single-page-audit.js +103 -0
  21. package/dist/audit/run-single-page-audit.js.map +1 -0
  22. package/dist/bin/webmcp.d.ts +5 -0
  23. package/dist/bin/webmcp.js +14 -0
  24. package/dist/bin/webmcp.js.map +1 -0
  25. package/dist/browser/audit-runner.d.ts +30 -0
  26. package/dist/browser/audit-runner.js +77 -0
  27. package/dist/browser/audit-runner.js.map +1 -0
  28. package/dist/browser/index.d.ts +6 -0
  29. package/dist/browser/index.js +7 -0
  30. package/dist/browser/index.js.map +1 -0
  31. package/dist/browser/interceptor.d.ts +68 -0
  32. package/dist/browser/interceptor.js +257 -0
  33. package/dist/browser/interceptor.js.map +1 -0
  34. package/dist/browser/playwright.d.ts +98 -0
  35. package/dist/browser/playwright.js +158 -0
  36. package/dist/browser/playwright.js.map +1 -0
  37. package/dist/cli/commands/audit.d.ts +12 -0
  38. package/dist/cli/commands/audit.js +349 -0
  39. package/dist/cli/commands/audit.js.map +1 -0
  40. package/dist/cli/commands/interactive.d.ts +10 -0
  41. package/dist/cli/commands/interactive.js +34 -0
  42. package/dist/cli/commands/interactive.js.map +1 -0
  43. package/dist/cli/index.d.ts +17 -0
  44. package/dist/cli/index.js +84 -0
  45. package/dist/cli/index.js.map +1 -0
  46. package/dist/cli/options/parse-audit-options.d.ts +12 -0
  47. package/dist/cli/options/parse-audit-options.js +64 -0
  48. package/dist/cli/options/parse-audit-options.js.map +1 -0
  49. package/dist/core/constants.d.ts +102 -0
  50. package/dist/core/constants.js +214 -0
  51. package/dist/core/constants.js.map +1 -0
  52. package/dist/core/types/audit.d.ts +260 -0
  53. package/dist/core/types/audit.js +5 -0
  54. package/dist/core/types/audit.js.map +1 -0
  55. package/dist/core/types/index.d.ts +6 -0
  56. package/dist/core/types/index.js +7 -0
  57. package/dist/core/types/index.js.map +1 -0
  58. package/dist/core/types/rule.d.ts +190 -0
  59. package/dist/core/types/rule.js +26 -0
  60. package/dist/core/types/rule.js.map +1 -0
  61. package/dist/core/types/tool.d.ts +312 -0
  62. package/dist/core/types/tool.js +6 -0
  63. package/dist/core/types/tool.js.map +1 -0
  64. package/dist/detection/declarative.d.ts +27 -0
  65. package/dist/detection/declarative.js +343 -0
  66. package/dist/detection/declarative.js.map +1 -0
  67. package/dist/detection/imperative.d.ts +38 -0
  68. package/dist/detection/imperative.js +99 -0
  69. package/dist/detection/imperative.js.map +1 -0
  70. package/dist/detection/index.d.ts +5 -0
  71. package/dist/detection/index.js +6 -0
  72. package/dist/detection/index.js.map +1 -0
  73. package/dist/index.d.ts +12 -0
  74. package/dist/index.js +19 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/llm/advice-service.d.ts +38 -0
  77. package/dist/llm/advice-service.js +243 -0
  78. package/dist/llm/advice-service.js.map +1 -0
  79. package/dist/llm/evaluator.d.ts +89 -0
  80. package/dist/llm/evaluator.js +274 -0
  81. package/dist/llm/evaluator.js.map +1 -0
  82. package/dist/llm/index.d.ts +11 -0
  83. package/dist/llm/index.js +15 -0
  84. package/dist/llm/index.js.map +1 -0
  85. package/dist/llm/json-response.d.ts +12 -0
  86. package/dist/llm/json-response.js +67 -0
  87. package/dist/llm/json-response.js.map +1 -0
  88. package/dist/llm/providers/mock.d.ts +29 -0
  89. package/dist/llm/providers/mock.js +324 -0
  90. package/dist/llm/providers/mock.js.map +1 -0
  91. package/dist/llm/providers/openrouter.d.ts +53 -0
  92. package/dist/llm/providers/openrouter.js +321 -0
  93. package/dist/llm/providers/openrouter.js.map +1 -0
  94. package/dist/llm/request-cache.d.ts +28 -0
  95. package/dist/llm/request-cache.js +99 -0
  96. package/dist/llm/request-cache.js.map +1 -0
  97. package/dist/llm/types.d.ts +233 -0
  98. package/dist/llm/types.js +7 -0
  99. package/dist/llm/types.js.map +1 -0
  100. package/dist/rules/best-practices/BP-001.d.ts +11 -0
  101. package/dist/rules/best-practices/BP-001.js +56 -0
  102. package/dist/rules/best-practices/BP-001.js.map +1 -0
  103. package/dist/rules/best-practices/BP-002.d.ts +11 -0
  104. package/dist/rules/best-practices/BP-002.js +63 -0
  105. package/dist/rules/best-practices/BP-002.js.map +1 -0
  106. package/dist/rules/best-practices/BP-003.d.ts +11 -0
  107. package/dist/rules/best-practices/BP-003.js +68 -0
  108. package/dist/rules/best-practices/BP-003.js.map +1 -0
  109. package/dist/rules/coverage/COV-001.d.ts +8 -0
  110. package/dist/rules/coverage/COV-001.js +51 -0
  111. package/dist/rules/coverage/COV-001.js.map +1 -0
  112. package/dist/rules/description/DESC-003.d.ts +13 -0
  113. package/dist/rules/description/DESC-003.js +96 -0
  114. package/dist/rules/description/DESC-003.js.map +1 -0
  115. package/dist/rules/description/DESC-004.d.ts +8 -0
  116. package/dist/rules/description/DESC-004.js +61 -0
  117. package/dist/rules/description/DESC-004.js.map +1 -0
  118. package/dist/rules/description/DESC-005.d.ts +12 -0
  119. package/dist/rules/description/DESC-005.js +70 -0
  120. package/dist/rules/description/DESC-005.js.map +1 -0
  121. package/dist/rules/description/index.d.ts +4 -0
  122. package/dist/rules/description/index.js +5 -0
  123. package/dist/rules/description/index.js.map +1 -0
  124. package/dist/rules/implementation/IMP-001.d.ts +10 -0
  125. package/dist/rules/implementation/IMP-001.js +36 -0
  126. package/dist/rules/implementation/IMP-001.js.map +1 -0
  127. package/dist/rules/implementation/IMP-003.d.ts +9 -0
  128. package/dist/rules/implementation/IMP-003.js +45 -0
  129. package/dist/rules/implementation/IMP-003.js.map +1 -0
  130. package/dist/rules/implementation/IMP-004.d.ts +9 -0
  131. package/dist/rules/implementation/IMP-004.js +48 -0
  132. package/dist/rules/implementation/IMP-004.js.map +1 -0
  133. package/dist/rules/implementation/IMP-005.d.ts +9 -0
  134. package/dist/rules/implementation/IMP-005.js +54 -0
  135. package/dist/rules/implementation/IMP-005.js.map +1 -0
  136. package/dist/rules/implementation/IMP-007.d.ts +8 -0
  137. package/dist/rules/implementation/IMP-007.js +79 -0
  138. package/dist/rules/implementation/IMP-007.js.map +1 -0
  139. package/dist/rules/implementation/IMP-013.d.ts +9 -0
  140. package/dist/rules/implementation/IMP-013.js +55 -0
  141. package/dist/rules/implementation/IMP-013.js.map +1 -0
  142. package/dist/rules/implementation/index.d.ts +9 -0
  143. package/dist/rules/implementation/index.js +10 -0
  144. package/dist/rules/implementation/index.js.map +1 -0
  145. package/dist/rules/index.d.ts +51 -0
  146. package/dist/rules/index.js +100 -0
  147. package/dist/rules/index.js.map +1 -0
  148. package/dist/rules/llm/LLM-001.d.ts +14 -0
  149. package/dist/rules/llm/LLM-001.js +78 -0
  150. package/dist/rules/llm/LLM-001.js.map +1 -0
  151. package/dist/rules/llm/LLM-002.d.ts +14 -0
  152. package/dist/rules/llm/LLM-002.js +77 -0
  153. package/dist/rules/llm/LLM-002.js.map +1 -0
  154. package/dist/rules/llm/LLM-003.d.ts +16 -0
  155. package/dist/rules/llm/LLM-003.js +82 -0
  156. package/dist/rules/llm/LLM-003.js.map +1 -0
  157. package/dist/rules/llm/LLM-004.d.ts +14 -0
  158. package/dist/rules/llm/LLM-004.js +87 -0
  159. package/dist/rules/llm/LLM-004.js.map +1 -0
  160. package/dist/rules/llm/LLM-005.d.ts +16 -0
  161. package/dist/rules/llm/LLM-005.js +105 -0
  162. package/dist/rules/llm/LLM-005.js.map +1 -0
  163. package/dist/rules/llm/index.d.ts +10 -0
  164. package/dist/rules/llm/index.js +11 -0
  165. package/dist/rules/llm/index.js.map +1 -0
  166. package/dist/rules/runner.d.ts +54 -0
  167. package/dist/rules/runner.js +138 -0
  168. package/dist/rules/runner.js.map +1 -0
  169. package/dist/rules/schema/SCHEMA-001.d.ts +9 -0
  170. package/dist/rules/schema/SCHEMA-001.js +57 -0
  171. package/dist/rules/schema/SCHEMA-001.js.map +1 -0
  172. package/dist/rules/schema/SCHEMA-002.d.ts +9 -0
  173. package/dist/rules/schema/SCHEMA-002.js +59 -0
  174. package/dist/rules/schema/SCHEMA-002.js.map +1 -0
  175. package/dist/rules/schema/SCHEMA-003.d.ts +10 -0
  176. package/dist/rules/schema/SCHEMA-003.js +66 -0
  177. package/dist/rules/schema/SCHEMA-003.js.map +1 -0
  178. package/dist/rules/schema/SCHEMA-011.d.ts +10 -0
  179. package/dist/rules/schema/SCHEMA-011.js +62 -0
  180. package/dist/rules/schema/SCHEMA-011.js.map +1 -0
  181. package/dist/rules/security/SEC-001.d.ts +12 -0
  182. package/dist/rules/security/SEC-001.js +66 -0
  183. package/dist/rules/security/SEC-001.js.map +1 -0
  184. package/dist/rules/utils/keywords.d.ts +35 -0
  185. package/dist/rules/utils/keywords.js +100 -0
  186. package/dist/rules/utils/keywords.js.map +1 -0
  187. package/dist/scoring/calculator.d.ts +27 -0
  188. package/dist/scoring/calculator.js +194 -0
  189. package/dist/scoring/calculator.js.map +1 -0
  190. package/dist/scoring/grades.d.ts +34 -0
  191. package/dist/scoring/grades.js +167 -0
  192. package/dist/scoring/grades.js.map +1 -0
  193. package/dist/scoring/index.d.ts +5 -0
  194. package/dist/scoring/index.js +6 -0
  195. package/dist/scoring/index.js.map +1 -0
  196. package/dist/ui/banner.d.ts +21 -0
  197. package/dist/ui/banner.js +60 -0
  198. package/dist/ui/banner.js.map +1 -0
  199. package/dist/ui/design-tokens.d.ts +23 -0
  200. package/dist/ui/design-tokens.js +58 -0
  201. package/dist/ui/design-tokens.js.map +1 -0
  202. package/dist/ui/findings.d.ts +23 -0
  203. package/dist/ui/findings.js +190 -0
  204. package/dist/ui/findings.js.map +1 -0
  205. package/dist/ui/index.d.ts +9 -0
  206. package/dist/ui/index.js +10 -0
  207. package/dist/ui/index.js.map +1 -0
  208. package/dist/ui/ink/App.d.ts +14 -0
  209. package/dist/ui/ink/App.js +113 -0
  210. package/dist/ui/ink/App.js.map +1 -0
  211. package/dist/ui/ink/FullScreenLayout.d.ts +16 -0
  212. package/dist/ui/ink/FullScreenLayout.js +29 -0
  213. package/dist/ui/ink/FullScreenLayout.js.map +1 -0
  214. package/dist/ui/ink/InteractiveApp.d.ts +28 -0
  215. package/dist/ui/ink/InteractiveApp.js +229 -0
  216. package/dist/ui/ink/InteractiveApp.js.map +1 -0
  217. package/dist/ui/ink/RealAuditApp.d.ts +19 -0
  218. package/dist/ui/ink/RealAuditApp.js +170 -0
  219. package/dist/ui/ink/RealAuditApp.js.map +1 -0
  220. package/dist/ui/ink/components/AnimatedProgressBar.d.ts +20 -0
  221. package/dist/ui/ink/components/AnimatedProgressBar.js +46 -0
  222. package/dist/ui/ink/components/AnimatedProgressBar.js.map +1 -0
  223. package/dist/ui/ink/components/AsciiLogo.d.ts +12 -0
  224. package/dist/ui/ink/components/AsciiLogo.js +35 -0
  225. package/dist/ui/ink/components/AsciiLogo.js.map +1 -0
  226. package/dist/ui/ink/components/CategoryBars.d.ts +18 -0
  227. package/dist/ui/ink/components/CategoryBars.js +18 -0
  228. package/dist/ui/ink/components/CategoryBars.js.map +1 -0
  229. package/dist/ui/ink/components/FindingsTable.d.ts +18 -0
  230. package/dist/ui/ink/components/FindingsTable.js +19 -0
  231. package/dist/ui/ink/components/FindingsTable.js.map +1 -0
  232. package/dist/ui/ink/components/Footer.d.ts +15 -0
  233. package/dist/ui/ink/components/Footer.js +20 -0
  234. package/dist/ui/ink/components/Footer.js.map +1 -0
  235. package/dist/ui/ink/components/Header.d.ts +11 -0
  236. package/dist/ui/ink/components/Header.js +12 -0
  237. package/dist/ui/ink/components/Header.js.map +1 -0
  238. package/dist/ui/ink/components/LinkList.d.ts +17 -0
  239. package/dist/ui/ink/components/LinkList.js +44 -0
  240. package/dist/ui/ink/components/LinkList.js.map +1 -0
  241. package/dist/ui/ink/components/Navigation.d.ts +26 -0
  242. package/dist/ui/ink/components/Navigation.js +62 -0
  243. package/dist/ui/ink/components/Navigation.js.map +1 -0
  244. package/dist/ui/ink/components/ProgressBar.d.ts +15 -0
  245. package/dist/ui/ink/components/ProgressBar.js +14 -0
  246. package/dist/ui/ink/components/ProgressBar.js.map +1 -0
  247. package/dist/ui/ink/components/ScoreCard.d.ts +30 -0
  248. package/dist/ui/ink/components/ScoreCard.js +26 -0
  249. package/dist/ui/ink/components/ScoreCard.js.map +1 -0
  250. package/dist/ui/ink/components/SimulationResults.d.ts +33 -0
  251. package/dist/ui/ink/components/SimulationResults.js +23 -0
  252. package/dist/ui/ink/components/SimulationResults.js.map +1 -0
  253. package/dist/ui/ink/components/Spinner.d.ts +11 -0
  254. package/dist/ui/ink/components/Spinner.js +12 -0
  255. package/dist/ui/ink/components/Spinner.js.map +1 -0
  256. package/dist/ui/ink/components/ToolCard.d.ts +23 -0
  257. package/dist/ui/ink/components/ToolCard.js +20 -0
  258. package/dist/ui/ink/components/ToolCard.js.map +1 -0
  259. package/dist/ui/ink/components/shared/Badge.d.ts +21 -0
  260. package/dist/ui/ink/components/shared/Badge.js +39 -0
  261. package/dist/ui/ink/components/shared/Badge.js.map +1 -0
  262. package/dist/ui/ink/components/shared/Card.d.ts +18 -0
  263. package/dist/ui/ink/components/shared/Card.js +11 -0
  264. package/dist/ui/ink/components/shared/Card.js.map +1 -0
  265. package/dist/ui/ink/components/shared/HelpOverlay.d.ts +10 -0
  266. package/dist/ui/ink/components/shared/HelpOverlay.js +28 -0
  267. package/dist/ui/ink/components/shared/HelpOverlay.js.map +1 -0
  268. package/dist/ui/ink/components/shared/LoadingWithTimeout.d.ts +11 -0
  269. package/dist/ui/ink/components/shared/LoadingWithTimeout.js +21 -0
  270. package/dist/ui/ink/components/shared/LoadingWithTimeout.js.map +1 -0
  271. package/dist/ui/ink/components/shared/Menu.d.ts +23 -0
  272. package/dist/ui/ink/components/shared/Menu.js +43 -0
  273. package/dist/ui/ink/components/shared/Menu.js.map +1 -0
  274. package/dist/ui/ink/components/shared/Table.d.ts +23 -0
  275. package/dist/ui/ink/components/shared/Table.js +40 -0
  276. package/dist/ui/ink/components/shared/Table.js.map +1 -0
  277. package/dist/ui/ink/components/views/CrawlingView.d.ts +12 -0
  278. package/dist/ui/ink/components/views/CrawlingView.js +34 -0
  279. package/dist/ui/ink/components/views/CrawlingView.js.map +1 -0
  280. package/dist/ui/ink/components/views/DashboardView.d.ts +21 -0
  281. package/dist/ui/ink/components/views/DashboardView.js +51 -0
  282. package/dist/ui/ink/components/views/DashboardView.js.map +1 -0
  283. package/dist/ui/ink/components/views/FindingDetailView.d.ts +16 -0
  284. package/dist/ui/ink/components/views/FindingDetailView.js +34 -0
  285. package/dist/ui/ink/components/views/FindingDetailView.js.map +1 -0
  286. package/dist/ui/ink/components/views/FindingsView.d.ts +16 -0
  287. package/dist/ui/ink/components/views/FindingsView.js +79 -0
  288. package/dist/ui/ink/components/views/FindingsView.js.map +1 -0
  289. package/dist/ui/ink/components/views/OnboardingView.d.ts +12 -0
  290. package/dist/ui/ink/components/views/OnboardingView.js +40 -0
  291. package/dist/ui/ink/components/views/OnboardingView.js.map +1 -0
  292. package/dist/ui/ink/components/views/SimulationView.d.ts +17 -0
  293. package/dist/ui/ink/components/views/SimulationView.js +53 -0
  294. package/dist/ui/ink/components/views/SimulationView.js.map +1 -0
  295. package/dist/ui/ink/components/views/TestCaseDetailView.d.ts +11 -0
  296. package/dist/ui/ink/components/views/TestCaseDetailView.js +53 -0
  297. package/dist/ui/ink/components/views/TestCaseDetailView.js.map +1 -0
  298. package/dist/ui/ink/components/views/ToolDetailView.d.ts +15 -0
  299. package/dist/ui/ink/components/views/ToolDetailView.js +25 -0
  300. package/dist/ui/ink/components/views/ToolDetailView.js.map +1 -0
  301. package/dist/ui/ink/components/views/ToolsView.d.ts +15 -0
  302. package/dist/ui/ink/components/views/ToolsView.js +43 -0
  303. package/dist/ui/ink/components/views/ToolsView.js.map +1 -0
  304. package/dist/ui/ink/demo.d.ts +6 -0
  305. package/dist/ui/ink/demo.js +254 -0
  306. package/dist/ui/ink/demo.js.map +1 -0
  307. package/dist/ui/ink/hooks/useAnimation.d.ts +29 -0
  308. package/dist/ui/ink/hooks/useAnimation.js +89 -0
  309. package/dist/ui/ink/hooks/useAnimation.js.map +1 -0
  310. package/dist/ui/ink/hooks/useAudit.d.ts +69 -0
  311. package/dist/ui/ink/hooks/useAudit.js +99 -0
  312. package/dist/ui/ink/hooks/useAudit.js.map +1 -0
  313. package/dist/ui/ink/hooks/useCrawlAnimation.d.ts +19 -0
  314. package/dist/ui/ink/hooks/useCrawlAnimation.js +204 -0
  315. package/dist/ui/ink/hooks/useCrawlAnimation.js.map +1 -0
  316. package/dist/ui/ink/hooks/useKeyboardNav.d.ts +23 -0
  317. package/dist/ui/ink/hooks/useKeyboardNav.js +81 -0
  318. package/dist/ui/ink/hooks/useKeyboardNav.js.map +1 -0
  319. package/dist/ui/ink/hooks/useNavigation.d.ts +16 -0
  320. package/dist/ui/ink/hooks/useNavigation.js +42 -0
  321. package/dist/ui/ink/hooks/useNavigation.js.map +1 -0
  322. package/dist/ui/ink/hooks/useTerminalSize.d.ts +10 -0
  323. package/dist/ui/ink/hooks/useTerminalSize.js +29 -0
  324. package/dist/ui/ink/hooks/useTerminalSize.js.map +1 -0
  325. package/dist/ui/ink/index.d.ts +43 -0
  326. package/dist/ui/ink/index.js +50 -0
  327. package/dist/ui/ink/index.js.map +1 -0
  328. package/dist/ui/ink/render.d.ts +24 -0
  329. package/dist/ui/ink/render.js +14 -0
  330. package/dist/ui/ink/render.js.map +1 -0
  331. package/dist/ui/ink/theme.d.ts +37 -0
  332. package/dist/ui/ink/theme.js +38 -0
  333. package/dist/ui/ink/theme.js.map +1 -0
  334. package/dist/ui/ink/types.d.ts +77 -0
  335. package/dist/ui/ink/types.js +5 -0
  336. package/dist/ui/ink/types.js.map +1 -0
  337. package/dist/ui/score-display.d.ts +16 -0
  338. package/dist/ui/score-display.js +201 -0
  339. package/dist/ui/score-display.js.map +1 -0
  340. package/dist/ui/spinner.d.ts +45 -0
  341. package/dist/ui/spinner.js +112 -0
  342. package/dist/ui/spinner.js.map +1 -0
  343. package/dist/ui/utils.d.ts +13 -0
  344. package/dist/ui/utils.js +25 -0
  345. package/dist/ui/utils.js.map +1 -0
  346. package/package.json +61 -9
  347. package/index.js +0 -105
@@ -0,0 +1,321 @@
1
+ /**
2
+ * OpenRouter LLM Provider
3
+ *
4
+ * Uses OpenRouter's OpenAI-compatible API to access various models
5
+ * including Claude.
6
+ */
7
+ import { parseJsonObject } from '../json-response.js';
8
+ const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
9
+ /**
10
+ * Default configuration
11
+ */
12
+ const DEFAULT_CONFIG = {
13
+ model: 'anthropic/claude-sonnet-4',
14
+ temperature: 0.1,
15
+ maxTokens: 2048,
16
+ };
17
+ /**
18
+ * System prompt for tool description evaluation
19
+ */
20
+ const EVALUATION_SYSTEM_PROMPT = `You are an expert at evaluating WebMCP tool definitions for AI agent readiness.
21
+ Your task is to analyze tool descriptions and provide specific, actionable feedback.
22
+ Be concise but thorough. Always provide a score from 0-10 and clear reasoning.
23
+ Respond in JSON format only.`;
24
+ /**
25
+ * OpenRouter LLM Provider implementation
26
+ */
27
+ export class OpenRouterProvider {
28
+ name = 'openrouter';
29
+ config;
30
+ constructor(config = {}) {
31
+ const apiKey = config.apiKey || process.env['OPENROUTER_API_KEY'] || '';
32
+ this.config = {
33
+ apiKey,
34
+ model: config.model || DEFAULT_CONFIG.model,
35
+ baseUrl: config.baseUrl || OPENROUTER_API_URL,
36
+ temperature: config.temperature ?? DEFAULT_CONFIG.temperature,
37
+ maxTokens: config.maxTokens ?? DEFAULT_CONFIG.maxTokens,
38
+ };
39
+ }
40
+ /**
41
+ * Check if the provider has valid credentials
42
+ */
43
+ isAvailable() {
44
+ return Boolean(this.config.apiKey && this.config.apiKey.length > 10);
45
+ }
46
+ /**
47
+ * Send a prompt and get a response
48
+ */
49
+ async complete(prompt, systemPrompt) {
50
+ if (!this.isAvailable()) {
51
+ throw new Error('OpenRouter API key not configured');
52
+ }
53
+ const messages = [];
54
+ if (systemPrompt) {
55
+ messages.push({ role: 'system', content: systemPrompt });
56
+ }
57
+ messages.push({ role: 'user', content: prompt });
58
+ const response = await fetch(this.config.baseUrl, {
59
+ method: 'POST',
60
+ headers: {
61
+ 'Authorization': `Bearer ${this.config.apiKey}`,
62
+ 'Content-Type': 'application/json',
63
+ 'HTTP-Referer': 'https://agentready.dev',
64
+ 'X-Title': 'AgentReady CLI',
65
+ },
66
+ body: JSON.stringify({
67
+ model: this.config.model,
68
+ messages,
69
+ temperature: this.config.temperature,
70
+ max_tokens: this.config.maxTokens,
71
+ }),
72
+ });
73
+ if (!response.ok) {
74
+ const error = await response.text();
75
+ throw new Error(`OpenRouter API error: ${response.status} - ${error}`);
76
+ }
77
+ const data = await response.json();
78
+ return data.choices[0]?.message?.content || '';
79
+ }
80
+ /**
81
+ * Evaluate a specific aspect of a tool description
82
+ */
83
+ async evaluateDescription(context) {
84
+ const prompt = this.buildEvaluationPrompt(context);
85
+ try {
86
+ const response = await this.complete(prompt, EVALUATION_SYSTEM_PROMPT);
87
+ return this.parseEvaluationResponse(response, context.aspect);
88
+ }
89
+ catch (error) {
90
+ return {
91
+ passed: false,
92
+ score: 0,
93
+ reasoning: `Evaluation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
94
+ issues: ['LLM evaluation could not be completed'],
95
+ };
96
+ }
97
+ }
98
+ /**
99
+ * Get a comprehensive quality report for a tool
100
+ */
101
+ async getQualityReport(tool) {
102
+ const prompt = this.buildQualityReportPrompt(tool);
103
+ try {
104
+ const response = await this.complete(prompt, EVALUATION_SYSTEM_PROMPT);
105
+ return this.parseQualityReport(response, tool);
106
+ }
107
+ catch (error) {
108
+ // Return a default failed report
109
+ const failedResult = {
110
+ passed: false,
111
+ score: 0,
112
+ reasoning: 'Evaluation failed',
113
+ };
114
+ return {
115
+ overallScore: 0,
116
+ aspects: {
117
+ clarity: failedResult,
118
+ specificity: failedResult,
119
+ positiveFraming: failedResult,
120
+ completeness: failedResult,
121
+ steeringPerformance: failedResult,
122
+ atomicity: failedResult,
123
+ },
124
+ summary: `Quality report generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
125
+ priorityImprovements: ['Unable to generate improvements due to evaluation failure'],
126
+ };
127
+ }
128
+ }
129
+ /**
130
+ * Build the evaluation prompt for a specific aspect
131
+ */
132
+ buildEvaluationPrompt(context) {
133
+ const { name, description, inputSchema, aspect } = context;
134
+ const aspectPrompts = {
135
+ clarity: `
136
+ Evaluate the CLARITY of this tool description.
137
+ - Is the description unambiguous?
138
+ - Would an AI agent understand exactly what this tool does?
139
+ - Are there any confusing terms or phrases?`,
140
+ specificity: `
141
+ Evaluate the SPECIFICITY of the tool name and description.
142
+ - Does the name use a specific action verb (search, create, delete, book) vs ambiguous ones (handle, process, do, manage)?
143
+ - Is the description specific about what the tool does?
144
+ Good: "search_flights", "create_booking", "delete_reservation"
145
+ Bad: "handle_request", "process_data", "do_action"`,
146
+ 'positive-framing': `
147
+ Evaluate the POSITIVE FRAMING of this description.
148
+ - Does it use positive instructions ("Returns flight options") vs negative limitations ("Do not use for...", "Don't call when...")?
149
+ - Descriptions should tell the AI what the tool DOES, not what it shouldn't do.
150
+ Check for: "do not", "don't", "never", "avoid", "cannot", "won't"`,
151
+ completeness: `
152
+ Evaluate the COMPLETENESS of this description.
153
+ - Does it explain WHAT the tool does? (required)
154
+ - Does it explain WHEN to use the tool? (recommended)
155
+ - Does it mention any important constraints or requirements?`,
156
+ steering: `
157
+ Evaluate the STEERING PERFORMANCE of this description.
158
+ - Will this description help an AI agent choose this tool at the right time?
159
+ - Are there clear indicators of when to use vs not use this tool?
160
+ - Could the description cause the AI to misuse the tool or miss opportunities to use it?
161
+ Consider: Would an AI agent reading only this description and parameters make correct decisions?`,
162
+ atomicity: `
163
+ Evaluate the ATOMICITY of this tool.
164
+ - Does this tool do ONE thing well, or multiple unrelated things?
165
+ - Is the description trying to cover too many use cases?
166
+ - Would this be better split into multiple tools?
167
+ Signs of non-atomic tools: "and", "or", "also", "additionally", multiple action verbs`,
168
+ similarity: `
169
+ Analyze if this tool description could be confused with other common tools.
170
+ - Are there standard patterns this description should follow?
171
+ - Could the name/description clash with common tool conventions?`,
172
+ all: `
173
+ Provide a comprehensive evaluation covering:
174
+ 1. Clarity - Is it unambiguous?
175
+ 2. Specificity - Uses specific verbs?
176
+ 3. Positive framing - Avoids negative language?
177
+ 4. Completeness - Explains what and when?
178
+ 5. Steering - Will it guide AI correctly?
179
+ 6. Atomicity - Does one thing well?`,
180
+ };
181
+ return `
182
+ TOOL NAME: ${name}
183
+ TOOL DESCRIPTION: ${description}
184
+ ${inputSchema ? `INPUT SCHEMA: ${inputSchema}` : ''}
185
+
186
+ ${aspectPrompts[aspect] || aspectPrompts['all']}
187
+
188
+ Respond with a JSON object:
189
+ {
190
+ "passed": boolean,
191
+ "score": number (0-10),
192
+ "reasoning": "string explaining your evaluation",
193
+ "issues": ["array of specific issues found"],
194
+ "suggestions": ["array of improvement suggestions"]
195
+ }`;
196
+ }
197
+ /**
198
+ * Build the comprehensive quality report prompt
199
+ */
200
+ buildQualityReportPrompt(tool) {
201
+ const schemaStr = tool.inputSchema
202
+ ? JSON.stringify(tool.inputSchema, null, 2)
203
+ : 'No schema defined';
204
+ return `
205
+ Analyze this WebMCP tool definition and provide a comprehensive quality report.
206
+
207
+ TOOL NAME: ${tool.name}
208
+ TOOL DESCRIPTION: ${tool.description}
209
+ INPUT SCHEMA:
210
+ ${schemaStr}
211
+ ${tool.annotations ? `ANNOTATIONS: ${JSON.stringify(tool.annotations)}` : ''}
212
+
213
+ Evaluate the following aspects (score 0-10 each):
214
+
215
+ 1. CLARITY: Is the description unambiguous? Will an AI understand exactly what this does?
216
+
217
+ 2. SPECIFICITY: Does the name use specific action verbs (search, create, delete) vs ambiguous ones (handle, process)?
218
+
219
+ 3. POSITIVE FRAMING: Does it use positive instructions vs negative limitations ("do not", "don't", "never")?
220
+
221
+ 4. COMPLETENESS: Does it explain what the tool does and when to use it?
222
+
223
+ 5. STEERING PERFORMANCE: Will this description help AI agents choose and use this tool correctly?
224
+ - Consider: routing accuracy (will AI pick this tool at the right time?)
225
+ - Consider: parameter accuracy (will AI fill parameters correctly?)
226
+ - Consider: avoiding hallucination (is the description specific enough?)
227
+
228
+ 6. ATOMICITY: Does this tool do one thing well, or is it trying to do too much?
229
+
230
+ Respond with JSON:
231
+ {
232
+ "overallScore": number (0-100, weighted average),
233
+ "aspects": {
234
+ "clarity": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] },
235
+ "specificity": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] },
236
+ "positiveFraming": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] },
237
+ "completeness": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] },
238
+ "steeringPerformance": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] },
239
+ "atomicity": { "passed": boolean, "score": number, "reasoning": "...", "issues": [], "suggestions": [] }
240
+ },
241
+ "summary": "Overall assessment in 2-3 sentences",
242
+ "priorityImprovements": ["Top 3 most important improvements"],
243
+ "suggestedDescription": "Optional: A rewritten, improved description"
244
+ }`;
245
+ }
246
+ /**
247
+ * Parse the evaluation response from LLM
248
+ */
249
+ parseEvaluationResponse(response, aspect) {
250
+ try {
251
+ const parsed = parseJsonObject(response);
252
+ return {
253
+ passed: parsed.passed ?? (parsed.score !== undefined && parsed.score >= 7),
254
+ score: parsed.score ?? 0,
255
+ reasoning: parsed.reasoning ?? 'No reasoning provided',
256
+ issues: parsed.issues ?? [],
257
+ suggestions: parsed.suggestions ?? [],
258
+ rawResponse: response,
259
+ };
260
+ }
261
+ catch (error) {
262
+ return {
263
+ passed: false,
264
+ score: 0,
265
+ reasoning: `Failed to parse LLM response for ${aspect}: ${error instanceof Error ? error.message : 'Parse error'}`,
266
+ issues: ['Response parsing failed'],
267
+ rawResponse: response,
268
+ };
269
+ }
270
+ }
271
+ /**
272
+ * Parse the quality report response from LLM
273
+ */
274
+ parseQualityReport(response, _tool) {
275
+ const defaultResult = {
276
+ passed: false,
277
+ score: 0,
278
+ reasoning: 'Parse error',
279
+ };
280
+ try {
281
+ const parsed = parseJsonObject(response);
282
+ return {
283
+ overallScore: parsed.overallScore ?? 0,
284
+ aspects: {
285
+ clarity: parsed.aspects?.clarity ?? defaultResult,
286
+ specificity: parsed.aspects?.specificity ?? defaultResult,
287
+ positiveFraming: parsed.aspects?.positiveFraming ?? defaultResult,
288
+ completeness: parsed.aspects?.completeness ?? defaultResult,
289
+ steeringPerformance: parsed.aspects?.steeringPerformance ?? defaultResult,
290
+ atomicity: parsed.aspects?.atomicity ?? defaultResult,
291
+ },
292
+ summary: parsed.summary ?? 'Unable to generate summary',
293
+ priorityImprovements: parsed.priorityImprovements ?? [],
294
+ suggestedDescription: parsed.suggestedDescription,
295
+ };
296
+ }
297
+ catch (error) {
298
+ return {
299
+ overallScore: 0,
300
+ aspects: {
301
+ clarity: defaultResult,
302
+ specificity: defaultResult,
303
+ positiveFraming: defaultResult,
304
+ completeness: defaultResult,
305
+ steeringPerformance: defaultResult,
306
+ atomicity: defaultResult,
307
+ },
308
+ summary: `Failed to parse quality report: ${error instanceof Error ? error.message : 'Parse error'}`,
309
+ priorityImprovements: [],
310
+ };
311
+ }
312
+ }
313
+ }
314
+ /**
315
+ * Create an OpenRouter provider with environment configuration
316
+ */
317
+ export function createOpenRouterProvider(config) {
318
+ return new OpenRouterProvider(config);
319
+ }
320
+ export default OpenRouterProvider;
321
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../src/llm/providers/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Universal LLM Request Cache
3
+ *
4
+ * Caches OpenRouter API responses by full request body hash.
5
+ * Ensures identical requests never hit the API twice.
6
+ */
7
+ export declare class LLMRequestCache {
8
+ private cache;
9
+ constructor();
10
+ getCacheKey(requestBody: object): string;
11
+ get(requestBody: object): string | null;
12
+ set(requestBody: object, response: string, model: string): void;
13
+ has(requestBody: object): boolean;
14
+ private loadCache;
15
+ private saveCache;
16
+ /**
17
+ * Get cache statistics
18
+ */
19
+ getStats(): {
20
+ entries: number;
21
+ sizeBytes: number;
22
+ };
23
+ /**
24
+ * Clear expired entries
25
+ */
26
+ cleanup(): number;
27
+ }
28
+ export declare function getRequestCache(): LLMRequestCache;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Universal LLM Request Cache
3
+ *
4
+ * Caches OpenRouter API responses by full request body hash.
5
+ * Ensures identical requests never hit the API twice.
6
+ */
7
+ import { createHash } from 'crypto';
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
9
+ import { homedir } from 'os';
10
+ import { join } from 'path';
11
+ const CACHE_DIR = join(homedir(), '.webmcp', 'cache');
12
+ const REQUEST_CACHE_FILE = join(CACHE_DIR, 'llm-requests.json');
13
+ const CACHE_TTL = 30 * 24 * 60 * 60 * 1000; // 30 days
14
+ export class LLMRequestCache {
15
+ cache;
16
+ constructor() {
17
+ this.cache = this.loadCache();
18
+ }
19
+ getCacheKey(requestBody) {
20
+ const normalized = JSON.stringify(requestBody);
21
+ return createHash('sha256').update(normalized).digest('hex');
22
+ }
23
+ get(requestBody) {
24
+ const key = this.getCacheKey(requestBody);
25
+ const entry = this.cache.entries[key];
26
+ if (!entry)
27
+ return null;
28
+ if (Date.now() - entry.timestamp > CACHE_TTL) {
29
+ delete this.cache.entries[key];
30
+ this.saveCache();
31
+ return null;
32
+ }
33
+ return entry.response;
34
+ }
35
+ set(requestBody, response, model) {
36
+ const key = this.getCacheKey(requestBody);
37
+ this.cache.entries[key] = {
38
+ response,
39
+ timestamp: Date.now(),
40
+ model,
41
+ };
42
+ this.saveCache();
43
+ }
44
+ has(requestBody) {
45
+ return this.get(requestBody) !== null;
46
+ }
47
+ loadCache() {
48
+ try {
49
+ if (existsSync(REQUEST_CACHE_FILE)) {
50
+ return JSON.parse(readFileSync(REQUEST_CACHE_FILE, 'utf-8'));
51
+ }
52
+ }
53
+ catch { /* ignore */ }
54
+ return { version: 1, entries: {} };
55
+ }
56
+ saveCache() {
57
+ try {
58
+ if (!existsSync(CACHE_DIR)) {
59
+ mkdirSync(CACHE_DIR, { recursive: true });
60
+ }
61
+ writeFileSync(REQUEST_CACHE_FILE, JSON.stringify(this.cache, null, 2));
62
+ }
63
+ catch { /* ignore */ }
64
+ }
65
+ /**
66
+ * Get cache statistics
67
+ */
68
+ getStats() {
69
+ const entries = Object.keys(this.cache.entries).length;
70
+ const sizeBytes = JSON.stringify(this.cache).length;
71
+ return { entries, sizeBytes };
72
+ }
73
+ /**
74
+ * Clear expired entries
75
+ */
76
+ cleanup() {
77
+ const now = Date.now();
78
+ let removed = 0;
79
+ for (const [key, entry] of Object.entries(this.cache.entries)) {
80
+ if (now - entry.timestamp > CACHE_TTL) {
81
+ delete this.cache.entries[key];
82
+ removed++;
83
+ }
84
+ }
85
+ if (removed > 0) {
86
+ this.saveCache();
87
+ }
88
+ return removed;
89
+ }
90
+ }
91
+ // Singleton instance
92
+ let instance = null;
93
+ export function getRequestCache() {
94
+ if (!instance) {
95
+ instance = new LLMRequestCache();
96
+ }
97
+ return instance;
98
+ }
99
+ //# sourceMappingURL=request-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-cache.js","sourceRoot":"","sources":["../../src/llm/request-cache.ts"],"names":[],"mappings":"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"}