@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,723 @@
1
+ /**
2
+ * Unit tests for Mermaid validation functionality
3
+ */
4
+
5
+ import { describe, test, expect } from '@jest/globals';
6
+ import {
7
+ isMermaidSchema,
8
+ extractMermaidFromMarkdown,
9
+ extractMermaidFromJson,
10
+ validateMermaidDiagram,
11
+ validateMermaidResponse,
12
+ createMermaidCorrectionPrompt,
13
+ decodeHtmlEntities,
14
+ replaceMermaidDiagramsInJson
15
+ } from '../../src/agent/schemaUtils.js';
16
+
17
+ describe('Mermaid Validation', () => {
18
+ describe('isMermaidSchema', () => {
19
+ test('should detect mermaid keywords', () => {
20
+ const mermaidSchemas = [
21
+ 'Generate a mermaid flowchart',
22
+ 'Create a sequence diagram',
23
+ 'Show me a gantt chart',
24
+ 'Draw a state diagram',
25
+ 'Create a class diagram',
26
+ 'Entity relationship diagram',
27
+ 'User journey diagram',
28
+ 'Git graph visualization',
29
+ 'Requirement diagram',
30
+ 'C4 context diagram',
31
+ 'Return in mermaid format',
32
+ 'DIAGRAM should be mermaid',
33
+ 'Create a pie chart visualization'
34
+ ];
35
+
36
+ const nonMermaidSchemas = [
37
+ 'Return JSON format',
38
+ 'Generate plain text',
39
+ 'Create a table',
40
+ 'Show code example',
41
+ 'Data visualization in Python',
42
+ '',
43
+ null,
44
+ undefined
45
+ ];
46
+
47
+ mermaidSchemas.forEach(schema => {
48
+ expect(isMermaidSchema(schema)).toBe(true);
49
+ });
50
+
51
+ nonMermaidSchemas.forEach(schema => {
52
+ expect(isMermaidSchema(schema)).toBe(false);
53
+ });
54
+ });
55
+
56
+ test('should handle case insensitivity', () => {
57
+ expect(isMermaidSchema('MERMAID FLOWCHART')).toBe(true);
58
+ expect(isMermaidSchema('sequence DIAGRAM')).toBe(true);
59
+ expect(isMermaidSchema('Gantt Chart')).toBe(true);
60
+ });
61
+ });
62
+
63
+ describe('extractMermaidFromMarkdown', () => {
64
+ test('should extract single diagram', () => {
65
+ const response = `Here's a flowchart:
66
+
67
+ \`\`\`mermaid
68
+ graph TD
69
+ A[Start] --> B[Process]
70
+ B --> C[End]
71
+ \`\`\`
72
+
73
+ That's the diagram.`;
74
+
75
+ const result = extractMermaidFromMarkdown(response);
76
+ expect(result.diagrams).toHaveLength(1);
77
+ expect(result.diagrams[0].content).toContain('graph TD');
78
+ expect(result.diagrams[0].content).toContain('A[Start] --> B[Process]');
79
+ });
80
+
81
+ test('should extract multiple diagrams', () => {
82
+ const response = `Here are two diagrams:
83
+
84
+ \`\`\`mermaid
85
+ graph TD
86
+ A --> B
87
+ \`\`\`
88
+
89
+ And another one:
90
+
91
+ \`\`\`mermaid
92
+ sequenceDiagram
93
+ Alice->>Bob: Hello
94
+ Bob-->>Alice: Hi
95
+ \`\`\``;
96
+
97
+ const result = extractMermaidFromMarkdown(response);
98
+ expect(result.diagrams).toHaveLength(2);
99
+ expect(result.diagrams[0].content).toContain('graph TD');
100
+ expect(result.diagrams[1].content).toContain('sequenceDiagram');
101
+ });
102
+
103
+ test('should handle diagrams with extra whitespace', () => {
104
+ const response = `\`\`\`mermaid
105
+
106
+
107
+ graph TD
108
+ A --> B
109
+
110
+
111
+ \`\`\``;
112
+
113
+ const result = extractMermaidFromMarkdown(response);
114
+ expect(result.diagrams).toHaveLength(1);
115
+ // Maid 0.0.5 preserves trailing newlines (needed for sequence diagrams)
116
+ // Content includes leading/trailing whitespace
117
+ expect(result.diagrams[0].content).toContain('graph TD');
118
+ expect(result.diagrams[0].content).toContain('A --> B');
119
+ });
120
+
121
+ test('should return empty array for no diagrams', () => {
122
+ const response = 'No mermaid diagrams here, just text.';
123
+ const result = extractMermaidFromMarkdown(response);
124
+ expect(result.diagrams).toHaveLength(0);
125
+ });
126
+
127
+ test('should handle malformed markdown blocks', () => {
128
+ const response = `\`\`\`mermaid
129
+ graph TD
130
+ A --> B
131
+ \`\`\`
132
+
133
+ \`\`\`mermaid
134
+ sequenceDiagram
135
+ Alice->>Bob: Test
136
+ \`\`\``;
137
+
138
+ const result = extractMermaidFromMarkdown(response);
139
+ expect(result.diagrams).toHaveLength(2);
140
+ expect(result.diagrams[0].content).toContain('graph TD');
141
+ expect(result.diagrams[1].content).toContain('sequenceDiagram');
142
+ });
143
+
144
+ test('should handle null/undefined input', () => {
145
+ expect(extractMermaidFromMarkdown(null).diagrams).toHaveLength(0);
146
+ expect(extractMermaidFromMarkdown(undefined).diagrams).toHaveLength(0);
147
+ expect(extractMermaidFromMarkdown('').diagrams).toHaveLength(0);
148
+ });
149
+ });
150
+
151
+ describe('validateMermaidDiagram', () => {
152
+ test('should validate flowchart diagrams', async () => {
153
+ const validFlowcharts = [
154
+ 'graph TD\n A[Start] --> B[Process]\n B --> C[End]',
155
+ 'graph LR\n A --> B\n B --> C',
156
+ 'flowchart TD\n A --> B'
157
+ ];
158
+
159
+ for (const diagram of validFlowcharts) {
160
+ const result = await validateMermaidDiagram(diagram);
161
+ expect(result.isValid).toBe(true);
162
+ expect(result.diagramType).toBe('flowchart');
163
+ }
164
+ });
165
+
166
+ test('should validate sequence diagrams', async () => {
167
+ // Maid 0.0.5 requires trailing newline for sequence diagrams (bug #2 from issue #18)
168
+ const validSequence = 'sequenceDiagram\n Alice->>Bob: Hello\n Bob-->>Alice: Hi\n';
169
+ const result = await validateMermaidDiagram(validSequence);
170
+ expect(result.isValid).toBe(true);
171
+ expect(result.diagramType).toBe('sequence');
172
+ });
173
+ });
174
+
175
+ describe('validateMermaidResponse', () => {
176
+ test('should validate response with single valid diagram', async () => {
177
+ const response = `Here's your diagram:
178
+
179
+ \`\`\`mermaid
180
+ graph TD
181
+ A[Start] --> B[Process]
182
+ B --> C[End]
183
+ \`\`\``;
184
+
185
+ const result = await validateMermaidResponse(response);
186
+ expect(result.isValid).toBe(true);
187
+ expect(result.diagrams).toHaveLength(1);
188
+ expect(result.diagrams[0].isValid).toBe(true);
189
+ expect(result.diagrams[0].diagramType).toBe('flowchart');
190
+ });
191
+
192
+ test('should reject response with invalid diagram', async () => {
193
+ const response = `Here's your diagram:
194
+
195
+ \`\`\`mermaid
196
+ invalid syntax here
197
+ \`\`\``;
198
+
199
+ const result = await validateMermaidResponse(response);
200
+ expect(result.isValid).toBe(false);
201
+ expect(result.errors).toBeDefined();
202
+ expect(result.errors.length).toBeGreaterThan(0);
203
+ });
204
+
205
+ test('should handle mixed valid and invalid diagrams', async () => {
206
+ const response = `Here are your diagrams:
207
+
208
+ \`\`\`mermaid
209
+ graph TD
210
+ A --> B
211
+ \`\`\`
212
+
213
+ \`\`\`mermaid
214
+ invalid syntax
215
+ \`\`\`
216
+
217
+ \`\`\`mermaid
218
+ pie title Test
219
+ "A" : 50
220
+ "B" : 50
221
+ \`\`\``;
222
+
223
+ const result = await validateMermaidResponse(response);
224
+ expect(result.isValid).toBe(false);
225
+ expect(result.diagrams).toHaveLength(3);
226
+ expect(result.errors).toBeDefined();
227
+ expect(result.errors.length).toBeGreaterThan(0);
228
+
229
+ // Check individual diagram results
230
+ expect(result.diagrams[0].isValid).toBe(true); // First diagram valid
231
+ expect(result.diagrams[1].isValid).toBe(false); // Second diagram invalid
232
+ expect(result.diagrams[2].isValid).toBe(true); // Third diagram valid
233
+ });
234
+
235
+ test('should reject response with no diagrams', async () => {
236
+ const response = 'This response contains no mermaid diagrams.';
237
+ const result = await validateMermaidResponse(response);
238
+ expect(result.isValid).toBe(false);
239
+ expect(result.errors).toContain('No mermaid diagrams found in response');
240
+ });
241
+
242
+ test('should handle multiple valid diagrams', async () => {
243
+ const response = `\`\`\`mermaid
244
+ graph TD
245
+ A --> B
246
+ \`\`\`
247
+
248
+ \`\`\`mermaid
249
+ sequenceDiagram
250
+ Alice->>Bob: Hello
251
+ \`\`\``;
252
+
253
+ const result = await validateMermaidResponse(response);
254
+ expect(result.isValid).toBe(true);
255
+ expect(result.diagrams).toHaveLength(2);
256
+ expect(result.diagrams.every(d => d.isValid)).toBe(true);
257
+ });
258
+ });
259
+
260
+ describe('createMermaidCorrectionPrompt', () => {
261
+ test('should create comprehensive correction prompt', () => {
262
+ const invalidResponse = `\`\`\`mermaid
263
+ invalid syntax
264
+ \`\`\``;
265
+
266
+ const schema = 'Create a mermaid flowchart';
267
+ const errors = ['Diagram 1: Parse error at line 1'];
268
+ const diagrams = [{
269
+ diagram: 'invalid syntax',
270
+ isValid: false,
271
+ error: 'Parse error at line 1',
272
+ detailedError: 'Unexpected token at position 0'
273
+ }];
274
+
275
+ const prompt = createMermaidCorrectionPrompt(invalidResponse, schema, errors, diagrams);
276
+
277
+ expect(prompt).toContain(invalidResponse);
278
+ expect(prompt).toContain(schema);
279
+ expect(prompt).toContain('Parse error at line 1');
280
+ expect(prompt).toContain('invalid syntax');
281
+ expect(prompt).toContain('mermaid code blocks');
282
+ expect(prompt).toContain('Unexpected token at position 0');
283
+ expect(prompt).toContain('Validation Errors:');
284
+ expect(prompt).toContain('Diagram Details:');
285
+ });
286
+
287
+ test('should handle multiple errors', () => {
288
+ const errors = [
289
+ 'Diagram 1: Syntax error',
290
+ 'Diagram 2: Missing closing bracket'
291
+ ];
292
+ const diagrams = [
293
+ { diagram: 'bad syntax 1', isValid: false, error: 'Syntax error' },
294
+ { diagram: 'bad syntax 2', isValid: false, error: 'Missing closing bracket' }
295
+ ];
296
+
297
+ const prompt = createMermaidCorrectionPrompt('response', 'schema', errors, diagrams);
298
+
299
+ expect(prompt).toContain('1. Diagram 1: Syntax error');
300
+ expect(prompt).toContain('2. Diagram 2: Missing closing bracket');
301
+ });
302
+
303
+ test('should truncate long diagram content', () => {
304
+ const longDiagram = 'graph TD\n' + 'A --> B\n'.repeat(50);
305
+ const diagrams = [{
306
+ diagram: longDiagram,
307
+ isValid: false,
308
+ error: 'Test error'
309
+ }];
310
+
311
+ const prompt = createMermaidCorrectionPrompt('response', 'schema', ['Error'], diagrams);
312
+
313
+ // Should truncate and add ellipsis
314
+ expect(prompt).toContain('...');
315
+ expect(prompt.indexOf(longDiagram)).toBe(-1); // Full diagram should not be present
316
+ });
317
+
318
+ test('should handle diagrams without detailed errors', () => {
319
+ const diagrams = [{
320
+ diagram: 'invalid',
321
+ isValid: false,
322
+ error: 'Basic error'
323
+ // No detailedError
324
+ }];
325
+
326
+ const prompt = createMermaidCorrectionPrompt('response', 'schema', ['Error'], diagrams);
327
+
328
+ expect(prompt).toContain('Basic error');
329
+ // The word "Details:" appears in "Diagram Details:" section header, so we check for the specific pattern
330
+ expect(prompt).not.toContain('Details: Basic error');
331
+ });
332
+ });
333
+
334
+ describe('decodeHtmlEntities', () => {
335
+ test('should decode common HTML entities', () => {
336
+ const testCases = [
337
+ { input: '&lt;br&gt;', expected: '<br>' },
338
+ { input: '&amp;', expected: '&' },
339
+ { input: '&quot;test&quot;', expected: '"test"' },
340
+ { input: '&#39;test&#39;', expected: "'test'" },
341
+ { input: '&nbsp;', expected: ' ' },
342
+ { input: 'normal text', expected: 'normal text' },
343
+ { input: '', expected: '' }
344
+ ];
345
+
346
+ testCases.forEach(({ input, expected }) => {
347
+ expect(decodeHtmlEntities(input)).toBe(expected);
348
+ });
349
+ });
350
+
351
+ test('should decode multiple entities in same string', () => {
352
+ const input = 'A[Start] --&gt; B{&quot;Decision&lt;br&gt;Point&quot;}';
353
+ const expected = 'A[Start] --> B{"Decision<br>Point"}';
354
+ expect(decodeHtmlEntities(input)).toBe(expected);
355
+ });
356
+
357
+ test('should handle repeated entities', () => {
358
+ const input = '&lt;&lt;interface&gt;&gt;';
359
+ const expected = '<<interface>>';
360
+ expect(decodeHtmlEntities(input)).toBe(expected);
361
+ });
362
+
363
+ test('should handle null and undefined inputs', () => {
364
+ expect(decodeHtmlEntities(null)).toBe(null);
365
+ expect(decodeHtmlEntities(undefined)).toBe(undefined);
366
+ expect(decodeHtmlEntities('')).toBe('');
367
+ });
368
+
369
+ test('should handle non-string inputs', () => {
370
+ expect(decodeHtmlEntities(123)).toBe(123);
371
+ expect(decodeHtmlEntities({})).toEqual({});
372
+ expect(decodeHtmlEntities([])).toEqual([]);
373
+ });
374
+
375
+ test('should decode entities in mermaid diagram contexts', () => {
376
+ const mermaidWithEntities = `graph TD
377
+ A[Start] --&gt; B{&quot;Is it working?&quot;}
378
+ B --&gt; C[Yes &amp; Good]
379
+ B --&gt; D[No&lt;br&gt;Fix it]`;
380
+
381
+ const expectedMermaid = `graph TD
382
+ A[Start] --> B{"Is it working?"}
383
+ B --> C[Yes & Good]
384
+ B --> D[No<br>Fix it]`;
385
+
386
+ expect(decodeHtmlEntities(mermaidWithEntities)).toBe(expectedMermaid);
387
+ });
388
+
389
+ test('should not affect valid HTML tags that are not encoded', () => {
390
+ const input = 'A[Start] --> B{Decision<br>Point}';
391
+ const expected = 'A[Start] --> B{Decision<br>Point}';
392
+ expect(decodeHtmlEntities(input)).toBe(expected);
393
+ });
394
+ });
395
+
396
+ describe('Validation order with schema cleaning', () => {
397
+ test('should extract mermaid diagrams from mixed JSON+Mermaid responses', () => {
398
+ // Regression test: Verify diagrams are found even when mixed with JSON
399
+ // This ensures validation runs BEFORE cleanSchemaResponse strips content
400
+ const mixedResponse = `Here is the data:
401
+
402
+ \`\`\`json
403
+ {"name": "Test", "value": 42}
404
+ \`\`\`
405
+
406
+ And here is a diagram:
407
+
408
+ \`\`\`mermaid
409
+ graph TD
410
+ A[Start] --> B{Decision}
411
+ B -->|Yes| C[Result]
412
+ B -->|No| D[End]
413
+ \`\`\``;
414
+
415
+ const result = extractMermaidFromMarkdown(mixedResponse);
416
+
417
+ // Must find the diagram even though JSON is present
418
+ expect(result.diagrams).toHaveLength(1);
419
+ expect(result.diagrams[0].content).toContain('graph TD');
420
+ expect(result.diagrams[0].content).toContain('A[Start] --> B{Decision}');
421
+ });
422
+
423
+ test('should extract multiple diagrams from schema responses with explanatory text', () => {
424
+ // Regression test: Verify all diagrams are found in complex responses
425
+ const complexResponse = `Based on your schema:
426
+
427
+ \`\`\`json
428
+ {"count": 2}
429
+ \`\`\`
430
+
431
+ First diagram:
432
+ \`\`\`mermaid
433
+ graph TD
434
+ A --> B
435
+ \`\`\`
436
+
437
+ Explanation text that would be stripped by cleanSchemaResponse.
438
+
439
+ Second diagram:
440
+ \`\`\`mermaid
441
+ sequenceDiagram
442
+ Alice->>Bob: Hello
443
+ \`\`\`
444
+
445
+ More text here.`;
446
+
447
+ const result = extractMermaidFromMarkdown(complexResponse);
448
+
449
+ // Must find both diagrams
450
+ expect(result.diagrams).toHaveLength(2);
451
+ expect(result.diagrams[0].content).toContain('graph TD');
452
+ expect(result.diagrams[1].content).toContain('sequenceDiagram');
453
+ });
454
+
455
+ test('should not skip diagrams that appear after JSON blocks', () => {
456
+ // Regression test for the bug: diagrams after JSON should not be ignored
457
+ const responseWithTrailingDiagram = `\`\`\`json
458
+ {"result": "success"}
459
+ \`\`\`
460
+
461
+ \`\`\`mermaid
462
+ graph LR
463
+ A --> B
464
+ \`\`\``;
465
+
466
+ const result = extractMermaidFromMarkdown(responseWithTrailingDiagram);
467
+
468
+ // The diagram after JSON must be found
469
+ expect(result.diagrams).toHaveLength(1);
470
+ expect(result.diagrams[0].content).toContain('graph LR');
471
+ });
472
+ });
473
+
474
+ describe('extractMermaidFromJson', () => {
475
+ test('should extract mermaid diagram from JSON string value', () => {
476
+ const jsonResponse = `{
477
+ "text": "\`\`\`mermaid\\ngraph TD\\n A[Start] --> B[End]\\n\`\`\`",
478
+ "tags": {
479
+ "label": "diagram"
480
+ }
481
+ }`;
482
+
483
+ const result = extractMermaidFromJson(jsonResponse);
484
+
485
+ expect(result.diagrams).toHaveLength(1);
486
+ expect(result.diagrams[0].content).toContain('graph TD');
487
+ expect(result.diagrams[0].content).toContain('A[Start] --> B[End]');
488
+ expect(result.diagrams[0].isInJson).toBe(true);
489
+ expect(result.diagrams[0].jsonPath).toBe('text');
490
+ });
491
+
492
+ test('should extract mermaid diagram from JSON in code block', () => {
493
+ const jsonResponse = `\`\`\`json
494
+ {
495
+ "diagram": "\`\`\`mermaid\\nsequenceDiagram\\n Alice->>Bob: Hello\\n\`\`\`"
496
+ }
497
+ \`\`\``;
498
+
499
+ const result = extractMermaidFromJson(jsonResponse);
500
+
501
+ expect(result.diagrams).toHaveLength(1);
502
+ expect(result.diagrams[0].content).toContain('sequenceDiagram');
503
+ expect(result.diagrams[0].content).toContain('Alice->>Bob: Hello');
504
+ expect(result.diagrams[0].isInJson).toBe(true);
505
+ });
506
+
507
+ test('should extract multiple mermaid diagrams from JSON', () => {
508
+ const jsonResponse = `{
509
+ "overview": "\`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`",
510
+ "details": "\`\`\`mermaid\\nsequenceDiagram\\n User->>System: Request\\n\`\`\`"
511
+ }`;
512
+
513
+ const result = extractMermaidFromJson(jsonResponse);
514
+
515
+ expect(result.diagrams).toHaveLength(2);
516
+ expect(result.diagrams[0].content).toContain('graph TD');
517
+ expect(result.diagrams[1].content).toContain('sequenceDiagram');
518
+ expect(result.diagrams[0].jsonPath).toBe('overview');
519
+ expect(result.diagrams[1].jsonPath).toBe('details');
520
+ });
521
+
522
+ test('should extract mermaid from nested JSON objects', () => {
523
+ const jsonResponse = `{
524
+ "data": {
525
+ "visualization": "\`\`\`mermaid\\ngraph LR\\n X --> Y\\n\`\`\`"
526
+ }
527
+ }`;
528
+
529
+ const result = extractMermaidFromJson(jsonResponse);
530
+
531
+ expect(result.diagrams).toHaveLength(1);
532
+ expect(result.diagrams[0].content).toContain('graph LR');
533
+ expect(result.diagrams[0].jsonPath).toBe('data.visualization');
534
+ });
535
+
536
+ test('should extract mermaid from JSON arrays', () => {
537
+ const jsonResponse = `{
538
+ "diagrams": [
539
+ "\`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`",
540
+ "\`\`\`mermaid\\npie title Distribution\\n \\"A\\": 30\\n \\"B\\": 70\\n\`\`\`"
541
+ ]
542
+ }`;
543
+
544
+ const result = extractMermaidFromJson(jsonResponse);
545
+
546
+ expect(result.diagrams).toHaveLength(2);
547
+ expect(result.diagrams[0].jsonPath).toBe('diagrams.[0]');
548
+ expect(result.diagrams[1].jsonPath).toBe('diagrams.[1]');
549
+ });
550
+
551
+ test('should handle both escaped and literal newlines mixed in pattern', () => {
552
+ // This tests the regex pattern can handle \\n (escaped) which is the JSON format
553
+ const jsonResponse = `{
554
+ "text": "\`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`"
555
+ }`;
556
+
557
+ const result = extractMermaidFromJson(jsonResponse);
558
+
559
+ expect(result.diagrams).toHaveLength(1);
560
+ expect(result.diagrams[0].content).toContain('graph TD');
561
+ expect(result.diagrams[0].content).toContain('A --> B');
562
+ });
563
+
564
+ test('should return empty array for non-JSON input', () => {
565
+ const nonJsonResponse = 'This is not JSON';
566
+ const result = extractMermaidFromJson(nonJsonResponse);
567
+
568
+ expect(result.diagrams).toHaveLength(0);
569
+ expect(result.parsedJson).toBeNull();
570
+ });
571
+
572
+ test('should return empty array for JSON without mermaid', () => {
573
+ const jsonResponse = '{"text": "No diagrams here", "value": 42}';
574
+ const result = extractMermaidFromJson(jsonResponse);
575
+
576
+ expect(result.diagrams).toHaveLength(0);
577
+ expect(result.parsedJson).not.toBeNull();
578
+ });
579
+
580
+ test('should unescape newlines in diagram content', () => {
581
+ const jsonResponse = `{
582
+ "diagram": "\`\`\`mermaid\\ngraph TD\\n A[Start]\\n B[Middle]\\n A --> B\\n\`\`\`"
583
+ }`;
584
+
585
+ const result = extractMermaidFromJson(jsonResponse);
586
+
587
+ expect(result.diagrams).toHaveLength(1);
588
+ // Content should have actual newlines, not \\n
589
+ expect(result.diagrams[0].content).toContain('\n');
590
+ expect(result.diagrams[0].content).not.toContain('\\n');
591
+ expect(result.diagrams[0].content.split('\n').length).toBeGreaterThan(1);
592
+ });
593
+ });
594
+
595
+ describe('replaceMermaidDiagramsInJson', () => {
596
+ test('should replace mermaid diagram in JSON string value', () => {
597
+ const originalResponse = `{
598
+ "text": "\`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`"
599
+ }`;
600
+
601
+ // fullMatch should have actual newlines since it comes from the parsed JSON value
602
+ const correctedDiagrams = [{
603
+ content: 'graph TD\n A --> B\n B --> C',
604
+ fullMatch: '```mermaid\ngraph TD\n A --> B\n```',
605
+ isInJson: true,
606
+ jsonPath: 'text',
607
+ attributes: ''
608
+ }];
609
+
610
+ const result = replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
611
+
612
+ expect(result).toContain('graph TD');
613
+ expect(result).toContain('B --> C');
614
+ // Should be valid JSON
615
+ expect(() => JSON.parse(result)).not.toThrow();
616
+ const parsed = JSON.parse(result);
617
+ expect(parsed.text).toContain('B --> C');
618
+ });
619
+
620
+ test('should preserve JSON structure and formatting', () => {
621
+ const originalResponse = `{
622
+ "text": "Some diagram: \`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`",
623
+ "tags": {
624
+ "label": "bug"
625
+ }
626
+ }`;
627
+
628
+ const correctedDiagrams = [{
629
+ content: 'graph TD\n A --> B --> C',
630
+ fullMatch: '```mermaid\ngraph TD\n A --> B\n```',
631
+ isInJson: true,
632
+ jsonPath: 'text',
633
+ attributes: ''
634
+ }];
635
+
636
+ const result = replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
637
+
638
+ const parsed = JSON.parse(result);
639
+ expect(parsed.tags.label).toBe('bug');
640
+ expect(parsed.text).toContain('A --> B --> C');
641
+ });
642
+
643
+ test('should handle code block wrapped JSON', () => {
644
+ const originalResponse = `\`\`\`json
645
+ {
646
+ "diagram": "\`\`\`mermaid\\ngraph LR\\n X --> Y\\n\`\`\`"
647
+ }
648
+ \`\`\``;
649
+
650
+ const correctedDiagrams = [{
651
+ content: 'graph LR\n X --> Y --> Z',
652
+ fullMatch: '```mermaid\ngraph LR\n X --> Y\n```',
653
+ isInJson: true,
654
+ jsonPath: 'diagram',
655
+ attributes: ''
656
+ }];
657
+
658
+ const result = replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
659
+
660
+ expect(result).toContain('```json');
661
+ expect(result).toContain('X --> Y --> Z');
662
+ // Extract JSON from code block and verify it's valid
663
+ const jsonMatch = result.match(/```json\s*\n([\s\S]*?)\n```/);
664
+ expect(jsonMatch).not.toBeNull();
665
+ expect(() => JSON.parse(jsonMatch[1])).not.toThrow();
666
+ });
667
+
668
+ test('should return original response if no JSON found', () => {
669
+ const originalResponse = 'Not JSON';
670
+ const correctedDiagrams = [{
671
+ content: 'graph TD\n A --> B',
672
+ isInJson: true
673
+ }];
674
+
675
+ const result = replaceMermaidDiagramsInJson(originalResponse, correctedDiagrams);
676
+
677
+ expect(result).toBe(originalResponse);
678
+ });
679
+ });
680
+
681
+ describe('extractMermaidFromMarkdown with JSON support', () => {
682
+ test('should detect and extract mermaid from JSON responses', () => {
683
+ const jsonResponse = `{
684
+ "text": "Here's a diagram: \`\`\`mermaid\\ngraph TD\\n A --> B\\n\`\`\`"
685
+ }`;
686
+
687
+ const result = extractMermaidFromMarkdown(jsonResponse);
688
+
689
+ expect(result.diagrams).toHaveLength(1);
690
+ expect(result.diagrams[0].content).toContain('graph TD');
691
+ expect(result.diagrams[0].isInJson).toBe(true);
692
+ });
693
+
694
+ test('should fallback to markdown extraction for non-JSON', () => {
695
+ const markdownResponse = `Here's a diagram:
696
+
697
+ \`\`\`mermaid
698
+ graph TD
699
+ A --> B
700
+ \`\`\``;
701
+
702
+ const result = extractMermaidFromMarkdown(markdownResponse);
703
+
704
+ expect(result.diagrams).toHaveLength(1);
705
+ expect(result.diagrams[0].content).toContain('graph TD');
706
+ expect(result.diagrams[0].isInJson).toBe(false);
707
+ });
708
+
709
+ test('should extract from JSON code blocks', () => {
710
+ const jsonCodeBlock = `\`\`\`json
711
+ {
712
+ "diagram": "\`\`\`mermaid\\nsequenceDiagram\\n Alice->>Bob: Test\\n\`\`\`"
713
+ }
714
+ \`\`\``;
715
+
716
+ const result = extractMermaidFromMarkdown(jsonCodeBlock);
717
+
718
+ expect(result.diagrams).toHaveLength(1);
719
+ expect(result.diagrams[0].content).toContain('sequenceDiagram');
720
+ expect(result.diagrams[0].isInJson).toBe(true);
721
+ });
722
+ });
723
+ });