@crownpeak/dqm-react-component-dev-mcp 1.2.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 (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. package/src/index.js +395 -0
@@ -0,0 +1,1268 @@
1
+ /**
2
+ * Unit tests for schemaUtils module
3
+ * Tests JSON and Mermaid validation functionality
4
+ */
5
+
6
+ import { describe, test, expect, beforeEach } from '@jest/globals';
7
+ import {
8
+ cleanSchemaResponse,
9
+ validateJsonResponse,
10
+ validateXmlResponse,
11
+ processSchemaResponse,
12
+ isJsonSchema,
13
+ createJsonCorrectionPrompt,
14
+ isMermaidSchema,
15
+ extractMermaidFromMarkdown,
16
+ validateMermaidDiagram,
17
+ validateMermaidResponse,
18
+ createMermaidCorrectionPrompt,
19
+ generateExampleFromSchema
20
+ } from '../../src/agent/schemaUtils.js';
21
+
22
+ describe('Schema Utilities', () => {
23
+ describe('cleanSchemaResponse', () => {
24
+ test('should handle null/undefined input', () => {
25
+ expect(cleanSchemaResponse(null)).toBeNull();
26
+ expect(cleanSchemaResponse(undefined)).toBeUndefined();
27
+ expect(cleanSchemaResponse('')).toBe('');
28
+ });
29
+
30
+ test('should handle non-string input', () => {
31
+ expect(cleanSchemaResponse(123)).toBe(123);
32
+ expect(cleanSchemaResponse({})).toEqual({});
33
+ });
34
+
35
+ test('should extract JSON from markdown code blocks when response starts with {', () => {
36
+ const input = '```json\n{"test": "value"}\n```';
37
+ const expected = '{"test": "value"}';
38
+ expect(cleanSchemaResponse(input)).toBe(expected);
39
+ });
40
+
41
+ test('should extract JSON from markdown code blocks when response starts with [', () => {
42
+ const input = '```json\n[{"test": "value"}]\n```';
43
+ const expected = '[{"test": "value"}]';
44
+ expect(cleanSchemaResponse(input)).toBe(expected);
45
+ });
46
+
47
+ test('should extract JSON boundaries correctly with multiple brackets', () => {
48
+ const input = '```json\n{"nested": {"array": [1, 2, 3]}}\n```';
49
+ const expected = '{"nested": {"array": [1, 2, 3]}}';
50
+ expect(cleanSchemaResponse(input)).toBe(expected);
51
+ });
52
+
53
+ test('should return original input when not starting with JSON brackets', () => {
54
+ const input = '```xml\n<root>test</root>\n```';
55
+ expect(cleanSchemaResponse(input)).toBe(input); // Returns unchanged
56
+ });
57
+
58
+ test('should return original input for non-JSON backtick content', () => {
59
+ const input = '`some text content`';
60
+ expect(cleanSchemaResponse(input)).toBe(input); // Returns unchanged
61
+ });
62
+
63
+ test('should handle JSON with surrounding whitespace and markdown', () => {
64
+ const input = ' ```json\n{"test": "value"}\n``` ';
65
+ const expected = '{"test": "value"}';
66
+ expect(cleanSchemaResponse(input)).toBe(expected);
67
+ });
68
+
69
+ test('should handle direct JSON input without markdown', () => {
70
+ const input = '{"test": "value"}';
71
+ const expected = '{"test": "value"}';
72
+ expect(cleanSchemaResponse(input)).toBe(expected);
73
+ });
74
+
75
+ test('should handle array JSON input without markdown', () => {
76
+ const input = '[1, 2, 3]';
77
+ const expected = '[1, 2, 3]';
78
+ expect(cleanSchemaResponse(input)).toBe(expected);
79
+ });
80
+
81
+ test('should not extract JSON from text with surrounding content', () => {
82
+ const input = 'This is some text with {"json": "inside"}';
83
+ // Should return original since JSON has text before/after it
84
+ // This prevents false positives like extracting {{ pr.title }} from markdown
85
+ expect(cleanSchemaResponse(input)).toBe(input);
86
+ });
87
+
88
+ test('should return original for text with too much content before JSON', () => {
89
+ const input = 'Line 1\nLine 2\nLine 3\nLine 4\nMany lines of text that should prevent extraction {"json": "inside"}';
90
+ // Should return original since there are too many lines before the JSON
91
+ expect(cleanSchemaResponse(input)).toBe(input);
92
+ });
93
+
94
+ test('should handle empty JSON object', () => {
95
+ const input = '{}';
96
+ const expected = '{}';
97
+ expect(cleanSchemaResponse(input)).toBe(expected);
98
+ });
99
+
100
+ test('should handle empty JSON array', () => {
101
+ const input = '[]';
102
+ const expected = '[]';
103
+ expect(cleanSchemaResponse(input)).toBe(expected);
104
+ });
105
+
106
+ // New tests for enhanced JSON detection after code blocks
107
+ test('should extract JSON from code blocks with various patterns', () => {
108
+ const testCases = [
109
+ {
110
+ input: '```json\n{"test": "value"}\n```',
111
+ expected: '{"test": "value"}',
112
+ description: 'standard json code block'
113
+ },
114
+ {
115
+ input: '```\n{"test": "value"}\n```',
116
+ expected: '{"test": "value"}',
117
+ description: 'code block without language specifier'
118
+ },
119
+ {
120
+ input: '`{"test": "value"}`',
121
+ expected: '{"test": "value"}',
122
+ description: 'single backtick JSON'
123
+ }
124
+ ];
125
+
126
+ testCases.forEach(({ input, expected, description }) => {
127
+ expect(cleanSchemaResponse(input)).toBe(expected);
128
+ });
129
+ });
130
+
131
+ test('should handle code blocks with immediate JSON start', () => {
132
+ const input = '```json\n{';
133
+ const remaining = '"test": "value", "nested": {"array": [1, 2, 3]}}';
134
+ const fullInput = input + remaining;
135
+
136
+ expect(cleanSchemaResponse(fullInput)).toBe('{' + remaining);
137
+ });
138
+
139
+ test('should handle code blocks with array JSON', () => {
140
+ const input = '```json\n[{"item": 1}, {"item": 2}]```';
141
+ const expected = '[{"item": 1}, {"item": 2}]';
142
+ expect(cleanSchemaResponse(input)).toBe(expected);
143
+ });
144
+
145
+ test('should extract JSON with proper bracket counting', () => {
146
+ const input = '```json\n{"outer": {"inner": {"deep": [1, 2, {"nested": true}]}}}\n```';
147
+ const expected = '{"outer": {"inner": {"deep": [1, 2, {"nested": true}]}}}';
148
+ expect(cleanSchemaResponse(input)).toBe(expected);
149
+ });
150
+
151
+ test('should handle code blocks with whitespace after marker', () => {
152
+ const input = '```json \n {"test": "value"} \n```';
153
+ const expected = '{"test": "value"}';
154
+ expect(cleanSchemaResponse(input)).toBe(expected);
155
+ });
156
+
157
+ test('should handle incomplete code blocks gracefully', () => {
158
+ const input = '```json\n{"test": "incomplete"';
159
+ // Should fall back to boundary detection
160
+ expect(cleanSchemaResponse(input)).toBe(input);
161
+ });
162
+
163
+ test('should prioritize code block extraction over boundary detection', () => {
164
+ const input = 'Some text {"not": "this"} ```json\n{"extract": "this"}\n```';
165
+ const expected = '{"extract": "this"}';
166
+ expect(cleanSchemaResponse(input)).toBe(expected);
167
+ });
168
+
169
+ test('should handle mixed bracket types in code blocks', () => {
170
+ const input = '```json\n[{"objects": [1, 2]}, {"more": {"nested": true}}]\n```';
171
+ const expected = '[{"objects": [1, 2]}, {"more": {"nested": true}}]';
172
+ expect(cleanSchemaResponse(input)).toBe(expected);
173
+ });
174
+
175
+ test('should not extract JSON when embedded in surrounding text', () => {
176
+ const input = 'Here is some JSON: {"test": "value"} that should be extracted';
177
+ // Should return original since JSON has text before and after it
178
+ // This prevents extracting fragments like {{ pr.title }} from content
179
+ expect(cleanSchemaResponse(input)).toBe(input);
180
+ });
181
+
182
+ test('should not extract JSON when text precedes it', () => {
183
+ const input = 'Result:\n{"test": "value"}';
184
+ // Should return original since there's text before the JSON
185
+ expect(cleanSchemaResponse(input)).toBe(input);
186
+ });
187
+
188
+ test('should extract JSON from code block after correction prompt (mermaid-style fix)', () => {
189
+ // This is the exact pattern we see when LLM responds to correction prompts
190
+ // with ```json blocks instead of raw JSON
191
+ const input = '```json\n{\n "issues": [\n {\n "file": "test.js",\n "line": 1\n }\n ]\n}\n```';
192
+ const result = cleanSchemaResponse(input);
193
+
194
+ // Should extract the JSON content without the code block markers
195
+ expect(result).not.toContain('```');
196
+ expect(result).toContain('"issues"');
197
+
198
+ // Verify it can be parsed
199
+ expect(() => JSON.parse(result)).not.toThrow();
200
+ const parsed = JSON.parse(result);
201
+ expect(parsed.issues).toBeDefined();
202
+ expect(Array.isArray(parsed.issues)).toBe(true);
203
+ });
204
+
205
+ test('should extract multiline JSON from ```json blocks', () => {
206
+ const input = '```json\n{\n "key": "value",\n "nested": {\n "array": [1, 2, 3]\n }\n}\n```';
207
+ const result = cleanSchemaResponse(input);
208
+
209
+ expect(result).not.toContain('```');
210
+ const parsed = JSON.parse(result);
211
+ expect(parsed.key).toBe('value');
212
+ expect(parsed.nested.array).toEqual([1, 2, 3]);
213
+ });
214
+ });
215
+
216
+ describe('validateJsonResponse', () => {
217
+ test('should validate correct JSON', () => {
218
+ const result = validateJsonResponse('{"test": "value"}');
219
+ expect(result.isValid).toBe(true);
220
+ expect(result.parsed).toEqual({ test: "value" });
221
+ });
222
+
223
+ test('should validate JSON arrays', () => {
224
+ const result = validateJsonResponse('[1, 2, 3]');
225
+ expect(result.isValid).toBe(true);
226
+ expect(result.parsed).toEqual([1, 2, 3]);
227
+ });
228
+
229
+ test('should validate primitive JSON values', () => {
230
+ expect(validateJsonResponse('null').isValid).toBe(true);
231
+ expect(validateJsonResponse('42').isValid).toBe(true);
232
+ expect(validateJsonResponse('"string"').isValid).toBe(true);
233
+ expect(validateJsonResponse('true').isValid).toBe(true);
234
+ });
235
+
236
+ test('should reject invalid JSON', () => {
237
+ const result = validateJsonResponse('{"test": value}'); // Missing quotes
238
+ expect(result.isValid).toBe(false);
239
+ expect(result.error).toBeDefined();
240
+ });
241
+
242
+ test('should reject incomplete JSON', () => {
243
+ const result = validateJsonResponse('{"test":');
244
+ expect(result.isValid).toBe(false);
245
+ expect(result.error).toBeDefined();
246
+ });
247
+
248
+ test('should handle empty input', () => {
249
+ const result = validateJsonResponse('');
250
+ expect(result.isValid).toBe(false);
251
+ expect(result.error).toBeDefined();
252
+ });
253
+
254
+ test('should handle complex nested JSON', () => {
255
+ const complex = '{"nested": {"array": [1, {"deep": true}], "null": null}}';
256
+ const result = validateJsonResponse(complex);
257
+ expect(result.isValid).toBe(true);
258
+ expect(result.parsed.nested.array[1].deep).toBe(true);
259
+ });
260
+
261
+ // Schema validation tests
262
+ test('should validate JSON against schema with required fields', () => {
263
+ const schema = {
264
+ type: 'object',
265
+ properties: {
266
+ name: { type: 'string' },
267
+ age: { type: 'number' }
268
+ },
269
+ required: ['name', 'age']
270
+ };
271
+
272
+ const validJson = '{"name": "John", "age": 30}';
273
+ const result = validateJsonResponse(validJson, { schema });
274
+ expect(result.isValid).toBe(true);
275
+ expect(result.parsed).toEqual({ name: 'John', age: 30 });
276
+ });
277
+
278
+ test('should reject JSON missing required fields', () => {
279
+ const schema = {
280
+ type: 'object',
281
+ properties: {
282
+ name: { type: 'string' },
283
+ age: { type: 'number' }
284
+ },
285
+ required: ['name', 'age']
286
+ };
287
+
288
+ const invalidJson = '{"name": "John"}';
289
+ const result = validateJsonResponse(invalidJson, { schema });
290
+ expect(result.isValid).toBe(false);
291
+ expect(result.error).toBe('Schema validation failed');
292
+ expect(result.schemaErrors).toBeDefined();
293
+ expect(result.formattedErrors).toBeDefined();
294
+ expect(result.formattedErrors.some(e => e.includes('age'))).toBe(true);
295
+ });
296
+
297
+ test('should reject JSON with wrong field types', () => {
298
+ const schema = {
299
+ type: 'object',
300
+ properties: {
301
+ name: { type: 'string' },
302
+ age: { type: 'number' }
303
+ }
304
+ };
305
+
306
+ const invalidJson = '{"name": "John", "age": "thirty"}';
307
+ const result = validateJsonResponse(invalidJson, { schema });
308
+ expect(result.isValid).toBe(false);
309
+ expect(result.error).toBe('Schema validation failed');
310
+ expect(result.formattedErrors.some(e => e.includes('number') || e.includes('age'))).toBe(true);
311
+ });
312
+
313
+ test('should reject JSON with additional properties when not allowed', () => {
314
+ const schema = {
315
+ type: 'object',
316
+ properties: {
317
+ name: { type: 'string' }
318
+ },
319
+ additionalProperties: false
320
+ };
321
+
322
+ const invalidJson = '{"name": "John", "extra": "field"}';
323
+ const result = validateJsonResponse(invalidJson, { schema });
324
+ expect(result.isValid).toBe(false);
325
+ expect(result.error).toBe('Schema validation failed');
326
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
327
+ });
328
+
329
+ test('should allow JSON with additional properties when allowed', () => {
330
+ const schema = {
331
+ type: 'object',
332
+ properties: {
333
+ name: { type: 'string' }
334
+ },
335
+ additionalProperties: true
336
+ };
337
+
338
+ const validJson = '{"name": "John", "extra": "field"}';
339
+ const result = validateJsonResponse(validJson, { schema });
340
+ expect(result.isValid).toBe(true);
341
+ expect(result.parsed).toEqual({ name: 'John', extra: 'field' });
342
+ });
343
+
344
+ test('should validate arrays against schema', () => {
345
+ const schema = {
346
+ type: 'array',
347
+ items: {
348
+ type: 'object',
349
+ properties: {
350
+ id: { type: 'number' },
351
+ name: { type: 'string' }
352
+ },
353
+ required: ['id']
354
+ }
355
+ };
356
+
357
+ const validJson = '[{"id": 1, "name": "Item 1"}, {"id": 2}]';
358
+ const result = validateJsonResponse(validJson, { schema });
359
+ expect(result.isValid).toBe(true);
360
+ });
361
+
362
+ test('should reject invalid array items', () => {
363
+ const schema = {
364
+ type: 'array',
365
+ items: {
366
+ type: 'object',
367
+ properties: {
368
+ id: { type: 'number' }
369
+ },
370
+ required: ['id']
371
+ }
372
+ };
373
+
374
+ const invalidJson = '[{"id": 1}, {"name": "missing id"}]';
375
+ const result = validateJsonResponse(invalidJson, { schema });
376
+ expect(result.isValid).toBe(false);
377
+ expect(result.schemaErrors).toBeDefined();
378
+ });
379
+
380
+ test('should accept schema as string', () => {
381
+ const schemaString = '{"type": "object", "properties": {"name": {"type": "string"}}, "required": ["name"]}';
382
+ const validJson = '{"name": "John"}';
383
+ const result = validateJsonResponse(validJson, { schema: schemaString });
384
+ expect(result.isValid).toBe(true);
385
+ });
386
+
387
+ test('should handle invalid schema gracefully', () => {
388
+ const invalidSchema = 'not valid json';
389
+ const validJson = '{"name": "John"}';
390
+ const result = validateJsonResponse(validJson, { schema: invalidSchema });
391
+ expect(result.isValid).toBe(false);
392
+ expect(result.error).toBe('Invalid schema provided');
393
+ expect(result.schemaError).toBeDefined();
394
+ });
395
+
396
+ test('should validate nested object schemas', () => {
397
+ const schema = {
398
+ type: 'object',
399
+ properties: {
400
+ user: {
401
+ type: 'object',
402
+ properties: {
403
+ name: { type: 'string' },
404
+ email: { type: 'string' }
405
+ },
406
+ required: ['name'],
407
+ additionalProperties: false
408
+ }
409
+ },
410
+ required: ['user']
411
+ };
412
+
413
+ const validJson = '{"user": {"name": "John", "email": "john@example.com"}}';
414
+ const result = validateJsonResponse(validJson, { schema });
415
+ expect(result.isValid).toBe(true);
416
+ });
417
+
418
+ test('should provide detailed error messages for nested violations', () => {
419
+ const schema = {
420
+ type: 'object',
421
+ properties: {
422
+ user: {
423
+ type: 'object',
424
+ properties: {
425
+ name: { type: 'string' }
426
+ },
427
+ required: ['name'],
428
+ additionalProperties: false
429
+ }
430
+ }
431
+ };
432
+
433
+ const invalidJson = '{"user": {"age": 30}}';
434
+ const result = validateJsonResponse(invalidJson, { schema });
435
+ expect(result.isValid).toBe(false);
436
+ expect(result.formattedErrors).toBeDefined();
437
+ expect(result.errorSummary).toContain('Schema validation failed');
438
+ });
439
+
440
+ test('should work without schema (backward compatibility)', () => {
441
+ const validJson = '{"name": "John", "extra": "field"}';
442
+ const result = validateJsonResponse(validJson);
443
+ expect(result.isValid).toBe(true);
444
+ expect(result.parsed).toEqual({ name: 'John', extra: 'field' });
445
+ });
446
+
447
+ // Strict schema mode tests (automatic additionalProperties enforcement)
448
+ test('should automatically enforce additionalProperties on nested objects in strict mode', () => {
449
+ const schema = {
450
+ type: 'object',
451
+ properties: {
452
+ user: {
453
+ type: 'object',
454
+ properties: {
455
+ name: { type: 'string' }
456
+ }
457
+ // No additionalProperties specified - should be auto-added
458
+ }
459
+ }
460
+ // No additionalProperties on root either - should be auto-added
461
+ };
462
+
463
+ const invalidJson = '{"user": {"name": "John", "age": 30}}';
464
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
465
+
466
+ expect(result.isValid).toBe(false);
467
+ expect(result.error).toBe('Schema validation failed');
468
+ // Should reject the extra 'age' field in nested object
469
+ expect(result.formattedErrors.some(e => e.includes('age'))).toBe(true);
470
+ });
471
+
472
+ test('should allow disabling strict mode to permit additional properties', () => {
473
+ const schema = {
474
+ type: 'object',
475
+ properties: {
476
+ user: {
477
+ type: 'object',
478
+ properties: {
479
+ name: { type: 'string' }
480
+ }
481
+ }
482
+ }
483
+ };
484
+
485
+ const jsonWithExtra = '{"user": {"name": "John", "age": 30}}';
486
+ const result = validateJsonResponse(jsonWithExtra, { schema, strictSchema: false });
487
+
488
+ // Should allow extra fields when strictSchema is disabled
489
+ expect(result.isValid).toBe(true);
490
+ expect(result.parsed.user.age).toBe(30);
491
+ });
492
+
493
+ test('should respect explicit additionalProperties: true even in strict mode', () => {
494
+ const schema = {
495
+ type: 'object',
496
+ properties: {
497
+ user: {
498
+ type: 'object',
499
+ properties: {
500
+ name: { type: 'string' }
501
+ },
502
+ additionalProperties: true // Explicitly allow
503
+ }
504
+ }
505
+ };
506
+
507
+ const jsonWithExtra = '{"user": {"name": "John", "age": 30}}';
508
+ const result = validateJsonResponse(jsonWithExtra, { schema, strictSchema: true });
509
+
510
+ // Should respect explicit additionalProperties: true
511
+ expect(result.isValid).toBe(true);
512
+ expect(result.parsed.user.age).toBe(30);
513
+ });
514
+
515
+ test('should enforce strict mode on deeply nested objects', () => {
516
+ const schema = {
517
+ type: 'object',
518
+ properties: {
519
+ level1: {
520
+ type: 'object',
521
+ properties: {
522
+ level2: {
523
+ type: 'object',
524
+ properties: {
525
+ level3: {
526
+ type: 'object',
527
+ properties: {
528
+ name: { type: 'string' }
529
+ }
530
+ }
531
+ }
532
+ }
533
+ }
534
+ }
535
+ }
536
+ };
537
+
538
+ const invalidJson = '{"level1": {"level2": {"level3": {"name": "test", "extra": "field"}}}}';
539
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
540
+
541
+ expect(result.isValid).toBe(false);
542
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
543
+ });
544
+
545
+ test('should enforce strict mode on array items', () => {
546
+ const schema = {
547
+ type: 'object',
548
+ properties: {
549
+ items: {
550
+ type: 'array',
551
+ items: {
552
+ type: 'object',
553
+ properties: {
554
+ id: { type: 'number' }
555
+ }
556
+ // No additionalProperties - should be enforced
557
+ }
558
+ }
559
+ }
560
+ };
561
+
562
+ const invalidJson = '{"items": [{"id": 1, "extra": "field"}]}';
563
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
564
+
565
+ expect(result.isValid).toBe(false);
566
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
567
+ });
568
+
569
+ test('strict mode should be enabled by default', () => {
570
+ const schema = {
571
+ type: 'object',
572
+ properties: {
573
+ name: { type: 'string' }
574
+ }
575
+ };
576
+
577
+ const invalidJson = '{"name": "John", "extra": "field"}';
578
+ // Don't specify strictSchema - should default to true
579
+ const result = validateJsonResponse(invalidJson, { schema });
580
+
581
+ expect(result.isValid).toBe(false);
582
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
583
+ });
584
+
585
+ test('should enforce strict mode with oneOf schemas', () => {
586
+ const schema = {
587
+ type: 'object',
588
+ properties: {
589
+ data: {
590
+ oneOf: [
591
+ {
592
+ type: 'object',
593
+ properties: {
594
+ type: { type: 'string', const: 'user' },
595
+ name: { type: 'string' }
596
+ },
597
+ required: ['type', 'name']
598
+ },
599
+ {
600
+ type: 'object',
601
+ properties: {
602
+ type: { type: 'string', const: 'product' },
603
+ price: { type: 'number' }
604
+ },
605
+ required: ['type', 'price']
606
+ }
607
+ ]
608
+ }
609
+ }
610
+ };
611
+
612
+ const invalidJson = '{"data": {"type": "user", "name": "John", "extra": "field"}}';
613
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
614
+
615
+ expect(result.isValid).toBe(false);
616
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
617
+ });
618
+
619
+ test('should enforce strict mode with anyOf schemas', () => {
620
+ const schema = {
621
+ type: 'object',
622
+ properties: {
623
+ value: {
624
+ anyOf: [
625
+ {
626
+ type: 'object',
627
+ properties: {
628
+ num: { type: 'number' }
629
+ }
630
+ },
631
+ {
632
+ type: 'object',
633
+ properties: {
634
+ str: { type: 'string' }
635
+ }
636
+ }
637
+ ]
638
+ }
639
+ }
640
+ };
641
+
642
+ const invalidJson = '{"value": {"num": 42, "extra": "field"}}';
643
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
644
+
645
+ expect(result.isValid).toBe(false);
646
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
647
+ });
648
+
649
+ test('should enforce strict mode with allOf schemas', () => {
650
+ const schema = {
651
+ type: 'object',
652
+ properties: {
653
+ entity: {
654
+ allOf: [
655
+ {
656
+ type: 'object',
657
+ properties: {
658
+ id: { type: 'number' }
659
+ }
660
+ },
661
+ {
662
+ type: 'object',
663
+ properties: {
664
+ name: { type: 'string' }
665
+ }
666
+ }
667
+ ]
668
+ }
669
+ }
670
+ };
671
+
672
+ const invalidJson = '{"entity": {"id": 1, "name": "Test", "extra": "field"}}';
673
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
674
+
675
+ expect(result.isValid).toBe(false);
676
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
677
+ });
678
+
679
+ test('should enforce strict mode with schema definitions', () => {
680
+ const schema = {
681
+ type: 'object',
682
+ definitions: {
683
+ address: {
684
+ type: 'object',
685
+ properties: {
686
+ street: { type: 'string' },
687
+ city: { type: 'string' }
688
+ }
689
+ }
690
+ },
691
+ properties: {
692
+ home: { $ref: '#/definitions/address' }
693
+ }
694
+ };
695
+
696
+ const invalidJson = '{"home": {"street": "123 Main St", "city": "NYC", "extra": "field"}}';
697
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
698
+
699
+ expect(result.isValid).toBe(false);
700
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
701
+ });
702
+
703
+ test('should enforce strict mode with $defs (JSON Schema 2019-09)', () => {
704
+ const schema = {
705
+ type: 'object',
706
+ $defs: {
707
+ person: {
708
+ type: 'object',
709
+ properties: {
710
+ name: { type: 'string' },
711
+ age: { type: 'number' }
712
+ }
713
+ }
714
+ },
715
+ properties: {
716
+ employee: { $ref: '#/$defs/person' }
717
+ }
718
+ };
719
+
720
+ const invalidJson = '{"employee": {"name": "John", "age": 30, "extra": "field"}}';
721
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
722
+
723
+ expect(result.isValid).toBe(false);
724
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
725
+ });
726
+
727
+ test('should enforce strict mode on array items with tuple validation', () => {
728
+ const schema = {
729
+ type: 'object',
730
+ properties: {
731
+ coordinates: {
732
+ type: 'array',
733
+ items: [
734
+ {
735
+ type: 'object',
736
+ properties: {
737
+ x: { type: 'number' }
738
+ }
739
+ },
740
+ {
741
+ type: 'object',
742
+ properties: {
743
+ y: { type: 'number' }
744
+ }
745
+ }
746
+ ]
747
+ }
748
+ }
749
+ };
750
+
751
+ const invalidJson = '{"coordinates": [{"x": 10, "extra": "bad"}, {"y": 20}]}';
752
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
753
+
754
+ expect(result.isValid).toBe(false);
755
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
756
+ });
757
+
758
+ test('should handle schemas without type specified', () => {
759
+ const schema = {
760
+ properties: {
761
+ user: {
762
+ properties: {
763
+ name: { type: 'string' }
764
+ }
765
+ // No type: 'object' specified, but has properties
766
+ }
767
+ }
768
+ };
769
+
770
+ const invalidJson = '{"user": {"name": "John", "extra": "field"}}';
771
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
772
+
773
+ // Without explicit type: 'object', strict mode won't add additionalProperties
774
+ // This is expected behavior - schemas should be well-formed
775
+ expect(result.isValid).toBe(true);
776
+ });
777
+
778
+ test('should not modify schemas with explicit additionalProperties: false', () => {
779
+ const schema = {
780
+ type: 'object',
781
+ properties: {
782
+ data: {
783
+ type: 'object',
784
+ properties: {
785
+ id: { type: 'number' }
786
+ },
787
+ additionalProperties: false // Already set
788
+ }
789
+ },
790
+ additionalProperties: false // Already set
791
+ };
792
+
793
+ const invalidJson = '{"data": {"id": 1, "extra": "field"}}';
794
+ const result = validateJsonResponse(invalidJson, { schema, strictSchema: true });
795
+
796
+ expect(result.isValid).toBe(false);
797
+ expect(result.formattedErrors.some(e => e.includes('extra'))).toBe(true);
798
+ });
799
+
800
+ // Enhanced error message tests
801
+ test('should provide crisp error messages with dot notation paths', () => {
802
+ const schema = {
803
+ type: 'object',
804
+ properties: {
805
+ user: {
806
+ type: 'object',
807
+ properties: {
808
+ profile: {
809
+ type: 'object',
810
+ properties: {
811
+ name: { type: 'string' }
812
+ },
813
+ required: ['name']
814
+ }
815
+ }
816
+ }
817
+ }
818
+ };
819
+
820
+ const invalidJson = '{"user": {"profile": {}}}';
821
+ const result = validateJsonResponse(invalidJson, { schema });
822
+
823
+ expect(result.isValid).toBe(false);
824
+ // Should use dot notation, not slashes
825
+ expect(result.formattedErrors[0]).toContain("at 'user.profile'");
826
+ expect(result.formattedErrors[0]).not.toContain('/user/profile');
827
+ // Should have actionable suggestion
828
+ expect(result.formattedErrors[0]).toContain("Missing required field 'name'");
829
+ expect(result.formattedErrors[0]).toContain("Add 'name' to this object");
830
+ });
831
+
832
+ test('should show actual values in type errors', () => {
833
+ const schema = {
834
+ type: 'object',
835
+ properties: {
836
+ age: { type: 'number' }
837
+ }
838
+ };
839
+
840
+ const invalidJson = '{"age": "thirty"}';
841
+ const result = validateJsonResponse(invalidJson, { schema });
842
+
843
+ expect(result.isValid).toBe(false);
844
+ expect(result.formattedErrors[0]).toContain('Wrong type');
845
+ expect(result.formattedErrors[0]).toContain('expected number');
846
+ expect(result.formattedErrors[0]).toContain('got string');
847
+ expect(result.formattedErrors[0]).toContain('value: "thirty"');
848
+ expect(result.formattedErrors[0]).toContain('Change value to number type');
849
+ });
850
+
851
+ test('should provide actionable suggestions for additional properties', () => {
852
+ const schema = {
853
+ type: 'object',
854
+ properties: {
855
+ name: { type: 'string' }
856
+ },
857
+ additionalProperties: false
858
+ };
859
+
860
+ const invalidJson = '{"name": "John", "extra": "field"}';
861
+ const result = validateJsonResponse(invalidJson, { schema });
862
+
863
+ expect(result.isValid).toBe(false);
864
+ expect(result.formattedErrors[0]).toContain("Extra field 'extra' is not allowed");
865
+ expect(result.formattedErrors[0]).toContain("Remove 'extra' or add it to the schema");
866
+ });
867
+
868
+ test('should show allowed values for enum violations', () => {
869
+ const schema = {
870
+ type: 'object',
871
+ properties: {
872
+ role: { type: 'string', enum: ['admin', 'user', 'guest'] }
873
+ }
874
+ };
875
+
876
+ const invalidJson = '{"role": "superadmin"}';
877
+ const result = validateJsonResponse(invalidJson, { schema });
878
+
879
+ expect(result.isValid).toBe(false);
880
+ expect(result.formattedErrors[0]).toContain('Invalid value "superadmin"');
881
+ expect(result.formattedErrors[0]).toContain('Allowed: "admin", "user", "guest"');
882
+ expect(result.formattedErrors[0]).toContain('Use one of the allowed values');
883
+ });
884
+
885
+ test('should show constraint details for range violations', () => {
886
+ const schema = {
887
+ type: 'object',
888
+ properties: {
889
+ age: { type: 'number', minimum: 0, maximum: 150 }
890
+ }
891
+ };
892
+
893
+ const invalidJson = '{"age": 200}';
894
+ const result = validateJsonResponse(invalidJson, { schema });
895
+
896
+ expect(result.isValid).toBe(false);
897
+ expect(result.formattedErrors[0]).toContain('at \'age\'');
898
+ expect(result.formattedErrors[0]).toContain('Value 200');
899
+ expect(result.formattedErrors[0]).toContain('150');
900
+ expect(result.formattedErrors[0]).toContain('Adjust value to meet constraint');
901
+ });
902
+
903
+ test('should show current length for string length violations', () => {
904
+ const schema = {
905
+ type: 'object',
906
+ properties: {
907
+ username: { type: 'string', minLength: 3, maxLength: 20 }
908
+ }
909
+ };
910
+
911
+ const invalidJson = '{"username": "ab"}';
912
+ const result = validateJsonResponse(invalidJson, { schema });
913
+
914
+ expect(result.isValid).toBe(false);
915
+ expect(result.formattedErrors[0]).toContain('String length');
916
+ expect(result.formattedErrors[0]).toContain('current: 2');
917
+ expect(result.formattedErrors[0]).toContain('minLength: 3');
918
+ expect(result.formattedErrors[0]).toContain('Adjust string length');
919
+ });
920
+
921
+ test('should handle root-level errors clearly', () => {
922
+ const schema = {
923
+ type: 'object',
924
+ properties: {
925
+ name: { type: 'string' }
926
+ },
927
+ additionalProperties: false
928
+ };
929
+
930
+ const invalidJson = '{"extra": "field"}';
931
+ const result = validateJsonResponse(invalidJson, { schema });
932
+
933
+ expect(result.isValid).toBe(false);
934
+ expect(result.formattedErrors[0]).toContain('at \'<root>\'');
935
+ expect(result.formattedErrors[0]).toContain("Extra field 'extra' is not allowed");
936
+ });
937
+ });
938
+
939
+ describe('validateXmlResponse', () => {
940
+ test('should validate basic XML', () => {
941
+ const result = validateXmlResponse('<root>test</root>');
942
+ expect(result.isValid).toBe(true);
943
+ });
944
+
945
+ test('should validate XML with attributes', () => {
946
+ const result = validateXmlResponse('<root attr="value">test</root>');
947
+ expect(result.isValid).toBe(true);
948
+ });
949
+
950
+ test('should validate self-closing tags', () => {
951
+ const result = validateXmlResponse('<root><item/></root>');
952
+ expect(result.isValid).toBe(true);
953
+ });
954
+
955
+ test('should reject non-XML content', () => {
956
+ const result = validateXmlResponse('just plain text');
957
+ expect(result.isValid).toBe(false);
958
+ expect(result.error).toBe('No XML tags found');
959
+ });
960
+
961
+ test('should reject empty input', () => {
962
+ const result = validateXmlResponse('');
963
+ expect(result.isValid).toBe(false);
964
+ expect(result.error).toBe('No XML tags found');
965
+ });
966
+ });
967
+
968
+ describe('isJsonSchema', () => {
969
+ test('should detect JSON object schemas', () => {
970
+ expect(isJsonSchema('{"type": "object"}')).toBe(true);
971
+ expect(isJsonSchema('{ "properties": {} }')).toBe(true);
972
+ expect(isJsonSchema('{"test": "value"}')).toBe(true);
973
+ });
974
+
975
+ test('should detect JSON array schemas', () => {
976
+ expect(isJsonSchema('[{"name": "string"}]')).toBe(true);
977
+ expect(isJsonSchema('[]')).toBe(true);
978
+ });
979
+
980
+ test('should detect JSON content-type indicators', () => {
981
+ expect(isJsonSchema('application/json')).toBe(true);
982
+ expect(isJsonSchema('Response should be JSON format')).toBe(true);
983
+ expect(isJsonSchema('return as json')).toBe(true);
984
+ });
985
+
986
+ test('should handle mixed case', () => {
987
+ expect(isJsonSchema('{"Type": "Object"}')).toBe(true);
988
+ expect(isJsonSchema('APPLICATION/JSON')).toBe(true);
989
+ });
990
+
991
+ test('should reject non-JSON schemas', () => {
992
+ expect(isJsonSchema('<schema></schema>')).toBe(false);
993
+ expect(isJsonSchema('plain text schema')).toBe(false);
994
+ expect(isJsonSchema('')).toBe(false);
995
+ expect(isJsonSchema(null)).toBe(false);
996
+ expect(isJsonSchema(undefined)).toBe(false);
997
+ });
998
+ });
999
+
1000
+ describe('createJsonCorrectionPrompt', () => {
1001
+ test('should create basic correction prompt for first retry (retryCount 0)', () => {
1002
+ const invalidResponse = '{"test": value}';
1003
+ const schema = '{"test": "string"}';
1004
+ const error = 'Unexpected token v in JSON';
1005
+
1006
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error, 0);
1007
+
1008
+ expect(prompt).toContain(invalidResponse);
1009
+ expect(prompt).toContain(schema);
1010
+ expect(prompt).toContain(error);
1011
+ expect(prompt).toContain('CRITICAL JSON ERROR:');
1012
+ expect(prompt).toContain('Return ONLY the corrected JSON');
1013
+ });
1014
+
1015
+ test('should create more urgent prompt for second retry (retryCount 1)', () => {
1016
+ const invalidResponse = '{"test": value}';
1017
+ const schema = '{"test": "string"}';
1018
+ const error = 'Unexpected token v in JSON';
1019
+
1020
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error, 1);
1021
+
1022
+ expect(prompt).toContain('URGENT - JSON PARSING FAILED:');
1023
+ expect(prompt).toContain('second chance');
1024
+ expect(prompt).toContain('ABSOLUTELY NO explanatory text');
1025
+ });
1026
+
1027
+ test('should create final attempt prompt for third retry (retryCount 2)', () => {
1028
+ const invalidResponse = '{"test": value}';
1029
+ const schema = '{"test": "string"}';
1030
+ const error = 'Unexpected token v in JSON';
1031
+
1032
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error, 2);
1033
+
1034
+ expect(prompt).toContain('FINAL ATTEMPT - CRITICAL JSON ERROR:');
1035
+ expect(prompt).toContain('final retry');
1036
+ expect(prompt).toContain('EXAMPLE:');
1037
+ expect(prompt).toContain('NOT:');
1038
+ });
1039
+
1040
+ test('should cap at highest strength level for retryCount > 2', () => {
1041
+ const invalidResponse = '{"test": value}';
1042
+ const schema = '{"test": "string"}';
1043
+ const error = 'Unexpected token v in JSON';
1044
+
1045
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error, 5);
1046
+
1047
+ expect(prompt).toContain('FINAL ATTEMPT - CRITICAL JSON ERROR:');
1048
+ });
1049
+
1050
+ test('should truncate long invalid responses', () => {
1051
+ const longResponse = 'Hello '.repeat(200) + '{"test": value}';
1052
+ const schema = '{"test": "string"}';
1053
+ const error = 'Unexpected token v';
1054
+
1055
+ const prompt = createJsonCorrectionPrompt(longResponse, schema, error, 0);
1056
+
1057
+ expect(prompt).toContain('...');
1058
+ expect(prompt.length).toBeLessThan(longResponse.length + 500);
1059
+ });
1060
+
1061
+ test('should handle default retryCount parameter', () => {
1062
+ const invalidResponse = '{"test": value}';
1063
+ const schema = '{"test": "string"}';
1064
+ const error = 'Unexpected token v in JSON';
1065
+
1066
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error);
1067
+
1068
+ expect(prompt).toContain('CRITICAL JSON ERROR:');
1069
+ });
1070
+
1071
+ test('should handle multiline responses with truncation', () => {
1072
+ const invalidResponse = '{\n "test": value\n}';
1073
+ const schema = '{"test": "string"}';
1074
+ const error = 'Unexpected token v';
1075
+
1076
+ const prompt = createJsonCorrectionPrompt(invalidResponse, schema, error, 1);
1077
+
1078
+ expect(prompt).toContain('URGENT');
1079
+ expect(prompt.split('\n').length).toBeGreaterThan(5);
1080
+ });
1081
+ });
1082
+
1083
+ describe('processSchemaResponse', () => {
1084
+ test('should process and clean response', () => {
1085
+ const input = '```json\n{"test": "value"}\n```';
1086
+ const result = processSchemaResponse(input, '{}');
1087
+
1088
+ expect(result.cleaned).toBe('{"test": "value"}');
1089
+ });
1090
+
1091
+ test('should include debug information when requested', () => {
1092
+ const input = '```json\n{"test": "value"}\n```';
1093
+ const result = processSchemaResponse(input, '{}', { debug: true });
1094
+
1095
+ expect(result.debug).toBeDefined();
1096
+ expect(result.debug.wasModified).toBe(true);
1097
+ expect(result.debug.originalLength).toBeGreaterThan(result.debug.cleanedLength);
1098
+ });
1099
+
1100
+ test('should validate JSON when requested', () => {
1101
+ const input = '{"test": "value"}';
1102
+ const result = processSchemaResponse(input, '{}', { validateJson: true });
1103
+
1104
+ expect(result.jsonValidation).toBeDefined();
1105
+ expect(result.jsonValidation.isValid).toBe(true);
1106
+ });
1107
+
1108
+ test('should validate XML when requested', () => {
1109
+ const input = '<root>test</root>';
1110
+ const result = processSchemaResponse(input, '<schema/>', { validateXml: true });
1111
+
1112
+ expect(result.xmlValidation).toBeDefined();
1113
+ expect(result.xmlValidation.isValid).toBe(true);
1114
+ });
1115
+ });
1116
+
1117
+ describe('generateExampleFromSchema', () => {
1118
+ test('should generate example from object schema with basic types', () => {
1119
+ const schema = {
1120
+ type: 'object',
1121
+ properties: {
1122
+ name: { type: 'string', description: 'User name' },
1123
+ age: { type: 'number' },
1124
+ active: { type: 'boolean' },
1125
+ tags: { type: 'array' }
1126
+ }
1127
+ };
1128
+
1129
+ const result = generateExampleFromSchema(schema);
1130
+
1131
+ expect(result).toEqual({
1132
+ name: 'User name',
1133
+ age: 0,
1134
+ active: false,
1135
+ tags: []
1136
+ });
1137
+ });
1138
+
1139
+ test('should use description for string fields', () => {
1140
+ const schema = {
1141
+ type: 'object',
1142
+ properties: {
1143
+ message: { type: 'string', description: 'Hello world' },
1144
+ noDescription: { type: 'string' }
1145
+ }
1146
+ };
1147
+
1148
+ const result = generateExampleFromSchema(schema);
1149
+
1150
+ expect(result.message).toBe('Hello world');
1151
+ expect(result.noDescription).toBe('your answer here');
1152
+ });
1153
+
1154
+ test('should handle nested objects', () => {
1155
+ const schema = {
1156
+ type: 'object',
1157
+ properties: {
1158
+ user: { type: 'object' },
1159
+ settings: { type: 'object' }
1160
+ }
1161
+ };
1162
+
1163
+ const result = generateExampleFromSchema(schema);
1164
+
1165
+ expect(result).toEqual({
1166
+ user: {},
1167
+ settings: {}
1168
+ });
1169
+ });
1170
+
1171
+ test('should parse schema from JSON string', () => {
1172
+ const schema = JSON.stringify({
1173
+ type: 'object',
1174
+ properties: {
1175
+ refined: { type: 'boolean' },
1176
+ text: { type: 'string' }
1177
+ }
1178
+ });
1179
+
1180
+ const result = generateExampleFromSchema(schema);
1181
+
1182
+ expect(result).toEqual({
1183
+ refined: false,
1184
+ text: 'your answer here'
1185
+ });
1186
+ });
1187
+
1188
+ test('should return null for non-object schema', () => {
1189
+ const schema = {
1190
+ type: 'string'
1191
+ };
1192
+
1193
+ const result = generateExampleFromSchema(schema);
1194
+
1195
+ expect(result).toBeNull();
1196
+ });
1197
+
1198
+ test('should return null for schema without properties', () => {
1199
+ const schema = {
1200
+ type: 'object'
1201
+ };
1202
+
1203
+ const result = generateExampleFromSchema(schema);
1204
+
1205
+ expect(result).toBeNull();
1206
+ });
1207
+
1208
+ test('should return null for invalid schema', () => {
1209
+ const schema = 'not valid json {';
1210
+
1211
+ const result = generateExampleFromSchema(schema);
1212
+
1213
+ expect(result).toBeNull();
1214
+ });
1215
+
1216
+ test('should handle schema with multiple field types', () => {
1217
+ const schema = {
1218
+ type: 'object',
1219
+ properties: {
1220
+ id: { type: 'number' },
1221
+ name: { type: 'string', description: 'Product name' },
1222
+ inStock: { type: 'boolean' },
1223
+ categories: { type: 'array' },
1224
+ metadata: { type: 'object' }
1225
+ }
1226
+ };
1227
+
1228
+ const result = generateExampleFromSchema(schema);
1229
+
1230
+ expect(result).toEqual({
1231
+ id: 0,
1232
+ name: 'Product name',
1233
+ inStock: false,
1234
+ categories: [],
1235
+ metadata: {}
1236
+ });
1237
+ });
1238
+
1239
+ test('should match the exact schema used in Visor refine check', () => {
1240
+ // This is the actual schema from the bug report
1241
+ const schema = {
1242
+ type: 'object',
1243
+ additionalProperties: false,
1244
+ properties: {
1245
+ refined: {
1246
+ type: 'boolean',
1247
+ description: 'true if the task description is clear and actionable, false if clarification is needed'
1248
+ },
1249
+ text: {
1250
+ type: 'string',
1251
+ description: 'If refined=true, confirmation message. If refined=false, specific questions to ask.'
1252
+ }
1253
+ },
1254
+ required: ['refined', 'text']
1255
+ };
1256
+
1257
+ const result = generateExampleFromSchema(schema);
1258
+
1259
+ expect(result).toEqual({
1260
+ refined: false,
1261
+ text: 'If refined=true, confirmation message. If refined=false, specific questions to ask.'
1262
+ });
1263
+
1264
+ // Verify it's valid JSON when stringified
1265
+ expect(() => JSON.parse(JSON.stringify(result))).not.toThrow();
1266
+ });
1267
+ });
1268
+ });