@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,669 @@
1
+ use lru::LruCache;
2
+ use probe_code::search::elastic_query::{self, parse_query_test as parse_query};
3
+ use probe_code::search::file_processing::filter_code_block_with_ast;
4
+ use probe_code::search::query::create_query_plan;
5
+ use std::collections::{HashMap, HashSet};
6
+ use std::num::NonZeroUsize;
7
+ use std::sync::{Arc, Mutex};
8
+
9
+ /// Test direct usage of filter_code_block_with_ast with various complex queries
10
+ #[test]
11
+ fn test_filter_code_block_with_complex_ast() {
12
+ // Enable debug mode
13
+ std::env::set_var("DEBUG", "1");
14
+
15
+ // Test case 1: Simple AND query
16
+ test_simple_and_query();
17
+
18
+ // Test case 2: Simple OR query
19
+ test_simple_or_query();
20
+
21
+ // Test case 3: Complex query with AND, OR, and negation
22
+ test_complex_query_with_negation();
23
+
24
+ // Test case 4: Query with all required terms
25
+ test_required_terms_query();
26
+
27
+ // Test case 5: Query with nested expressions
28
+ test_nested_expressions_query();
29
+
30
+ // Reset debug mode
31
+ std::env::remove_var("DEBUG");
32
+ }
33
+
34
+ /// Test a simple AND query: "ip AND whitelist"
35
+ fn test_simple_and_query() {
36
+ println!("\n=== Testing simple AND query: ip AND whitelist ===");
37
+
38
+ // Create the query
39
+ let query = "ip AND whitelist";
40
+
41
+ // Parse the query into an AST
42
+ // Using standard Elasticsearch behavior (AND for implicit combinations)
43
+ let ast = parse_query(query).unwrap();
44
+ println!("Parsed AST: {ast:?}");
45
+
46
+ // Create a QueryPlan
47
+ let plan = create_query_plan(query, false).unwrap();
48
+
49
+ // Use the term indices from the QueryPlan
50
+ let term_indices = &plan.term_indices;
51
+
52
+ // Test case 1: Block with both terms (should match)
53
+ {
54
+ let mut term_matches = HashMap::new();
55
+
56
+ // Add "ip" matches
57
+ let mut ip_lines = HashSet::new();
58
+ ip_lines.insert(3);
59
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
60
+
61
+ // Add "whitelist" matches directly (tokenization behavior has changed)
62
+ let mut whitelist_lines = HashSet::new();
63
+ whitelist_lines.insert(4);
64
+
65
+ // Check if "whitelist" is in the term_indices, or if it's split into "white" and "list"
66
+ if let Some(&idx) = term_indices.get("whitelist") {
67
+ term_matches.insert(idx, whitelist_lines);
68
+ } else {
69
+ // If "whitelist" is not in the term_indices, try "white" and "list"
70
+ if let Some(&idx) = term_indices.get("white") {
71
+ let mut white_lines = HashSet::new();
72
+ white_lines.insert(4);
73
+ term_matches.insert(idx, white_lines);
74
+ }
75
+
76
+ if let Some(&idx) = term_indices.get("list") {
77
+ let mut list_lines = HashSet::new();
78
+ list_lines.insert(4);
79
+ term_matches.insert(idx, list_lines);
80
+ }
81
+ }
82
+
83
+ // Block lines
84
+ let block_lines = (1, 10);
85
+
86
+ // Test filtering
87
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
88
+ assert!(
89
+ result,
90
+ "Block with both 'ip' and 'whitelist' should match the AND query"
91
+ );
92
+ println!("✓ Block with both terms matches");
93
+ }
94
+
95
+ // Test case 2: Block with only one term (should not match)
96
+ {
97
+ let mut term_matches = HashMap::new();
98
+
99
+ // Add only "ip" matches
100
+ let mut ip_lines = HashSet::new();
101
+ ip_lines.insert(3);
102
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
103
+
104
+ // Block lines
105
+ let block_lines = (1, 10);
106
+
107
+ // Test filtering
108
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
109
+ assert!(
110
+ !result,
111
+ "Block with only 'ip' should not match the AND query"
112
+ );
113
+ println!("✓ Block with only one term doesn't match");
114
+ }
115
+ }
116
+
117
+ /// Test a simple OR query: "ip OR port"
118
+ fn test_simple_or_query() {
119
+ println!("\n=== Testing simple OR query: ip OR port ===");
120
+
121
+ // Create the query
122
+ let query = "ip OR port";
123
+
124
+ // Parse the query into an AST
125
+ // Using standard Elasticsearch behavior (AND for implicit combinations)
126
+ let ast = parse_query(query).unwrap();
127
+ println!("Parsed AST: {ast:?}");
128
+
129
+ // Create a QueryPlan
130
+ let plan = create_query_plan(query, false).unwrap();
131
+
132
+ // Use the term indices from the QueryPlan
133
+ let term_indices = &plan.term_indices;
134
+
135
+ // Test case 1: Block with both terms (should match)
136
+ {
137
+ let mut term_matches = HashMap::new();
138
+
139
+ // Add "ip" matches
140
+ let mut ip_lines = HashSet::new();
141
+ ip_lines.insert(3);
142
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
143
+
144
+ // Add "port" matches
145
+ let mut port_lines = HashSet::new();
146
+ port_lines.insert(4);
147
+ term_matches.insert(*term_indices.get("port").unwrap(), port_lines);
148
+
149
+ // Block lines
150
+ let block_lines = (1, 10);
151
+
152
+ // Test filtering
153
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
154
+ assert!(
155
+ result,
156
+ "Block with both 'ip' and 'port' should match the OR query"
157
+ );
158
+ println!("✓ Block with both terms matches");
159
+ }
160
+
161
+ // Test case 2: Block with only "ip" (should match)
162
+ {
163
+ let mut term_matches = HashMap::new();
164
+
165
+ // Add only "ip" matches
166
+ let mut ip_lines = HashSet::new();
167
+ ip_lines.insert(3);
168
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
169
+
170
+ // Block lines
171
+ let block_lines = (1, 10);
172
+
173
+ // Test filtering
174
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
175
+ assert!(result, "Block with only 'ip' should match the OR query");
176
+ println!("✓ Block with only 'ip' matches");
177
+ }
178
+
179
+ // Test case 3: Block with only "port" (should match)
180
+ {
181
+ let mut term_matches = HashMap::new();
182
+
183
+ // Add only "port" matches
184
+ let mut port_lines = HashSet::new();
185
+ port_lines.insert(4);
186
+ term_matches.insert(*term_indices.get("port").unwrap(), port_lines);
187
+
188
+ // Block lines
189
+ let block_lines = (1, 10);
190
+
191
+ // Test filtering
192
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
193
+ assert!(result, "Block with only 'port' should match the OR query");
194
+ println!("✓ Block with only 'port' matches");
195
+ }
196
+
197
+ // Test case 4: Block with neither term (should not match)
198
+ {
199
+ let term_matches = HashMap::new();
200
+
201
+ // Block lines
202
+ let block_lines = (1, 10);
203
+
204
+ // Test filtering
205
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
206
+ assert!(
207
+ !result,
208
+ "Block with neither 'ip' nor 'port' should not match the OR query"
209
+ );
210
+ println!("✓ Block with neither term doesn't match");
211
+ }
212
+ }
213
+
214
+ /// Test a complex query with AND, OR, and negation: "(ip OR port) AND whitelist AND -denylist"
215
+ fn test_complex_query_with_negation() {
216
+ println!("\n=== Testing complex query: (ip OR port) AND whitelist AND -denylist ===");
217
+
218
+ // Create the query
219
+ let query = "(ip OR port) AND whitelist AND -denylist";
220
+
221
+ // Parse the query into an AST
222
+ // Using standard Elasticsearch behavior (AND for implicit combinations)
223
+ let ast = parse_query(query).unwrap();
224
+ println!("Parsed AST: {ast:?}");
225
+
226
+ // Create a QueryPlan
227
+ let plan = create_query_plan(query, false).unwrap();
228
+ // Use the term indices from the QueryPlan
229
+ let term_indices = &plan.term_indices;
230
+
231
+ // Test case 1: Block with "ip", "whitelist", no "denylist" (should match)
232
+ {
233
+ let mut term_matches = HashMap::new();
234
+
235
+ // Add "ip" matches
236
+ let mut ip_lines = HashSet::new();
237
+ ip_lines.insert(3);
238
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
239
+
240
+ // Add "whitelist" matches directly (tokenization behavior has changed)
241
+ let mut whitelist_lines = HashSet::new();
242
+ whitelist_lines.insert(4);
243
+
244
+ // Check if "whitelist" is in the term_indices, or if it's split into "white" and "list"
245
+ if let Some(&idx) = term_indices.get("whitelist") {
246
+ term_matches.insert(idx, whitelist_lines);
247
+ } else {
248
+ // If "whitelist" is not in the term_indices, try "white" and "list"
249
+ if let Some(&idx) = term_indices.get("white") {
250
+ let mut white_lines = HashSet::new();
251
+ white_lines.insert(4);
252
+ term_matches.insert(idx, white_lines);
253
+ }
254
+
255
+ if let Some(&idx) = term_indices.get("list") {
256
+ let mut list_lines = HashSet::new();
257
+ list_lines.insert(4);
258
+ term_matches.insert(idx, list_lines);
259
+ }
260
+ }
261
+
262
+ // Block lines
263
+ let block_lines = (1, 10);
264
+
265
+ // Test filtering
266
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
267
+ assert!(
268
+ result,
269
+ "Block with 'ip', 'whitelist', no 'denylist' should match"
270
+ );
271
+ println!("✓ Block with 'ip', 'whitelist', no 'denylist' matches");
272
+ }
273
+
274
+ // Test case 2: Block with "port", "whitelist", no "denylist" (should match)
275
+ {
276
+ let mut term_matches = HashMap::new();
277
+
278
+ // Add "port" matches
279
+ let mut port_lines = HashSet::new();
280
+ port_lines.insert(3);
281
+ term_matches.insert(*term_indices.get("port").unwrap(), port_lines);
282
+
283
+ // Add "whitelist" matches directly (tokenization behavior has changed)
284
+ let mut whitelist_lines = HashSet::new();
285
+ whitelist_lines.insert(4);
286
+
287
+ // Check if "whitelist" is in the term_indices, or if it's split into "white" and "list"
288
+ if let Some(&idx) = term_indices.get("whitelist") {
289
+ term_matches.insert(idx, whitelist_lines);
290
+ } else {
291
+ // If "whitelist" is not in the term_indices, try "white" and "list"
292
+ if let Some(&idx) = term_indices.get("white") {
293
+ let mut white_lines = HashSet::new();
294
+ white_lines.insert(4);
295
+ term_matches.insert(idx, white_lines);
296
+ }
297
+
298
+ if let Some(&idx) = term_indices.get("list") {
299
+ let mut list_lines = HashSet::new();
300
+ list_lines.insert(4);
301
+ term_matches.insert(idx, list_lines);
302
+ }
303
+ }
304
+
305
+ // Block lines
306
+ let block_lines = (1, 10);
307
+
308
+ // Test filtering
309
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
310
+ assert!(
311
+ result,
312
+ "Block with 'port', 'whitelist', no 'denylist' should match"
313
+ );
314
+ println!("✓ Block with 'port', 'whitelist', no 'denylist' matches");
315
+ }
316
+
317
+ // Test case 3: Block with "ip", "whitelist", and "denylist" (should NOT match)
318
+ {
319
+ let mut term_matches = HashMap::new();
320
+
321
+ // Add "ip" matches
322
+ let mut ip_lines = HashSet::new();
323
+ ip_lines.insert(3);
324
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
325
+
326
+ // Add "whitelist" matches directly (tokenization behavior has changed)
327
+ let mut whitelist_lines = HashSet::new();
328
+ whitelist_lines.insert(4);
329
+
330
+ // Check if "whitelist" is in the term_indices, or if it's split into "white" and "list"
331
+ if let Some(&idx) = term_indices.get("whitelist") {
332
+ term_matches.insert(idx, whitelist_lines);
333
+ } else {
334
+ // If "whitelist" is not in the term_indices, try "white" and "list"
335
+ if let Some(&idx) = term_indices.get("white") {
336
+ let mut white_lines = HashSet::new();
337
+ white_lines.insert(4);
338
+ term_matches.insert(idx, white_lines);
339
+ }
340
+
341
+ if let Some(&idx) = term_indices.get("list") {
342
+ let mut list_lines = HashSet::new();
343
+ list_lines.insert(4);
344
+ term_matches.insert(idx, list_lines);
345
+ }
346
+ }
347
+
348
+ // Add "denylist" matches
349
+ let mut denylist_lines = HashSet::new();
350
+ denylist_lines.insert(5);
351
+ term_matches.insert(*term_indices.get("denylist").unwrap(), denylist_lines);
352
+
353
+ // Block lines
354
+ let block_lines = (1, 10);
355
+
356
+ // Test filtering
357
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
358
+ assert!(
359
+ !result,
360
+ "Block with 'ip', 'whitelist', and 'denylist' should NOT match"
361
+ );
362
+ println!("✓ Block with 'ip', 'whitelist', and 'denylist' doesn't match");
363
+ }
364
+
365
+ // Test case 4: Block with only "ip" and "port" (should NOT match due to missing "whitelist")
366
+ {
367
+ let mut term_matches = HashMap::new();
368
+
369
+ // Add "ip" matches
370
+ let mut ip_lines = HashSet::new();
371
+ ip_lines.insert(3);
372
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
373
+
374
+ // Add "port" matches
375
+ let mut port_lines = HashSet::new();
376
+ port_lines.insert(4);
377
+ term_matches.insert(*term_indices.get("port").unwrap(), port_lines);
378
+
379
+ // Block lines
380
+ let block_lines = (1, 10);
381
+
382
+ // Test filtering
383
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
384
+ assert!(
385
+ !result,
386
+ "Block with only 'ip' and 'port' should NOT match due to missing 'whitelist'"
387
+ );
388
+ println!("✓ Block with only 'ip' and 'port' doesn't match");
389
+ }
390
+ }
391
+
392
+ /// Test a query with all required terms: "+ip +whitelist +security" (note: these are connected with OR, not AND)
393
+ fn test_required_terms_query() {
394
+ println!("\n=== Testing required terms query: +ip +whitelist +security ===");
395
+
396
+ // Create the query
397
+ let _query = "+ip +whitelist +security";
398
+
399
+ // Create a custom AST with OR semantics for required terms
400
+ let keywords1 = vec!["ip".to_string()];
401
+ let keywords2 = vec!["white".to_string(), "list".to_string()];
402
+ let keywords3 = vec!["secur".to_string()];
403
+ let ast = elastic_query::Expr::Or(
404
+ Box::new(elastic_query::Expr::Or(
405
+ Box::new(elastic_query::Expr::Term {
406
+ lowercase_keywords: keywords1.iter().map(|k| k.to_lowercase()).collect(),
407
+ keywords: keywords1,
408
+ field: None,
409
+ required: true,
410
+ excluded: false,
411
+ exact: false,
412
+ }),
413
+ Box::new(elastic_query::Expr::Term {
414
+ lowercase_keywords: keywords2.iter().map(|k| k.to_lowercase()).collect(),
415
+ keywords: keywords2,
416
+ field: None,
417
+ required: true,
418
+ excluded: false,
419
+ exact: false,
420
+ }),
421
+ )),
422
+ Box::new(elastic_query::Expr::Term {
423
+ lowercase_keywords: keywords3.iter().map(|k| k.to_lowercase()).collect(),
424
+ keywords: keywords3,
425
+ field: None,
426
+ required: true,
427
+ excluded: false,
428
+ exact: false,
429
+ }),
430
+ );
431
+ println!("Parsed AST: {ast:?}");
432
+
433
+ // Create a custom QueryPlan with our AST
434
+ let mut indices = HashMap::new();
435
+ indices.insert("ip".to_string(), 0);
436
+ indices.insert("list".to_string(), 1);
437
+ indices.insert("secur".to_string(), 2);
438
+ indices.insert("white".to_string(), 3);
439
+
440
+ let has_required_anywhere = ast.has_required_term();
441
+ let has_only_excluded_terms = ast.is_only_excluded_terms();
442
+ let required_terms_indices = HashSet::new();
443
+ let evaluation_cache = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(1000).unwrap())));
444
+
445
+ let plan = probe_code::search::query::QueryPlan {
446
+ ast: ast.clone(),
447
+ term_indices: indices.clone(),
448
+ excluded_terms: HashSet::new(),
449
+ exact: false,
450
+ is_simple_query: false,
451
+ required_terms: HashSet::new(),
452
+ has_required_anywhere,
453
+ required_terms_indices,
454
+ has_only_excluded_terms,
455
+ evaluation_cache,
456
+ is_universal_query: false,
457
+ };
458
+
459
+ // Use the term indices directly
460
+ let term_indices = &indices;
461
+
462
+ // Test case 1: Block with all required terms (should match)
463
+ {
464
+ let mut term_matches = HashMap::new();
465
+
466
+ // Add all term matches
467
+ let mut ip_lines = HashSet::new();
468
+ ip_lines.insert(3);
469
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
470
+
471
+ // Add "white" and "list" matches (from tokenization of "whitelist")
472
+ let mut white_lines = HashSet::new();
473
+ white_lines.insert(4);
474
+ term_matches.insert(*term_indices.get("white").unwrap(), white_lines);
475
+
476
+ let mut list_lines = HashSet::new();
477
+ list_lines.insert(4);
478
+ term_matches.insert(*term_indices.get("list").unwrap(), list_lines);
479
+
480
+ let mut secur_lines = HashSet::new();
481
+ secur_lines.insert(5);
482
+ term_matches.insert(*term_indices.get("secur").unwrap(), secur_lines);
483
+
484
+ // Block lines
485
+ let block_lines = (1, 10);
486
+
487
+ // Test filtering
488
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
489
+ assert!(result, "Block with all required terms should match");
490
+ println!("✓ Block with all required terms matches");
491
+ }
492
+
493
+ // Test case 2: Block missing one required term (should NOT match)
494
+ {
495
+ let mut term_matches = HashMap::new();
496
+
497
+ // Add only two term matches
498
+ let mut ip_lines = HashSet::new();
499
+ ip_lines.insert(3);
500
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
501
+
502
+ // Add "white" and "list" matches (from tokenization of "whitelist")
503
+ let mut white_lines = HashSet::new();
504
+ white_lines.insert(4);
505
+ term_matches.insert(*term_indices.get("white").unwrap(), white_lines);
506
+
507
+ let mut list_lines = HashSet::new();
508
+ list_lines.insert(4);
509
+ term_matches.insert(*term_indices.get("list").unwrap(), list_lines);
510
+
511
+ // Block lines
512
+ let block_lines = (1, 10);
513
+
514
+ // Test filtering
515
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
516
+ // Note: In correct Lucene semantics, ALL required terms must be present
517
+ // This block is missing 'security', so it should NOT match
518
+ assert!(
519
+ !result,
520
+ "Block missing required term 'security' should NOT match"
521
+ );
522
+ println!("✓ Block missing required terms correctly rejected");
523
+ }
524
+ }
525
+
526
+ /// Test a query with nested expressions: "ip AND (whitelist OR (security AND firewall))"
527
+ fn test_nested_expressions_query() {
528
+ println!(
529
+ "\n=== Testing nested expressions query: ip AND (whitelist OR (security AND firewall)) ==="
530
+ );
531
+
532
+ // Create the query
533
+ let query = "ip AND (whitelist OR (security AND firewall))";
534
+
535
+ // Parse the query into an AST
536
+ // Using standard Elasticsearch behavior (AND for implicit combinations)
537
+ let ast = parse_query(query).unwrap();
538
+ println!("Parsed AST: {ast:?}");
539
+
540
+ // Create a QueryPlan
541
+ let plan = create_query_plan(query, false).unwrap();
542
+
543
+ // Use the term indices from the QueryPlan
544
+ let term_indices = &plan.term_indices;
545
+
546
+ // Test case 1: Block with "ip" and "whitelist" (should match)
547
+ {
548
+ let mut term_matches = HashMap::new();
549
+
550
+ // Add "ip" matches
551
+ let mut ip_lines = HashSet::new();
552
+ ip_lines.insert(3);
553
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
554
+
555
+ // Add "whitelist" matches directly (tokenization behavior has changed)
556
+ let mut whitelist_lines = HashSet::new();
557
+ whitelist_lines.insert(4);
558
+
559
+ // Check if "whitelist" is in the term_indices, or if it's split into "white" and "list"
560
+ if let Some(&idx) = term_indices.get("whitelist") {
561
+ term_matches.insert(idx, whitelist_lines);
562
+ } else {
563
+ // If "whitelist" is not in the term_indices, try "white" and "list"
564
+ if let Some(&idx) = term_indices.get("white") {
565
+ let mut white_lines = HashSet::new();
566
+ white_lines.insert(4);
567
+ term_matches.insert(idx, white_lines);
568
+ }
569
+
570
+ if let Some(&idx) = term_indices.get("list") {
571
+ let mut list_lines = HashSet::new();
572
+ list_lines.insert(4);
573
+ term_matches.insert(idx, list_lines);
574
+ }
575
+ }
576
+
577
+ // Block lines
578
+ let block_lines = (1, 10);
579
+
580
+ // Test filtering
581
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
582
+ assert!(result, "Block with 'ip' and 'whitelist' should match");
583
+ println!("✓ Block with 'ip' and 'whitelist' matches");
584
+ }
585
+
586
+ // Test case 2: Block with "ip", "security", and "firewall" (should match)
587
+ {
588
+ let mut term_matches = HashMap::new();
589
+
590
+ // Add "ip" matches
591
+ let mut ip_lines = HashSet::new();
592
+ ip_lines.insert(3);
593
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
594
+
595
+ // Add "secur" matches (stemmed from "security")
596
+ let mut secur_lines = HashSet::new();
597
+ secur_lines.insert(4);
598
+ term_matches.insert(*term_indices.get("secur").unwrap(), secur_lines);
599
+
600
+ // Add "firewal" and "firewall" matches (stemmed from "firewall")
601
+ let mut firewal_lines = HashSet::new();
602
+ firewal_lines.insert(5);
603
+
604
+ // Check if "firewal" is in the term_indices
605
+ if let Some(&idx) = term_indices.get("firewal") {
606
+ term_matches.insert(idx, firewal_lines.clone());
607
+ }
608
+
609
+ // Check if "firewall" is in the term_indices
610
+ if let Some(&idx) = term_indices.get("firewall") {
611
+ term_matches.insert(idx, firewal_lines);
612
+ }
613
+
614
+ // Block lines
615
+ let block_lines = (1, 10);
616
+
617
+ // Test filtering
618
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
619
+ assert!(
620
+ result,
621
+ "Block with 'ip', 'security', and 'firewall' should match"
622
+ );
623
+ println!("✓ Block with 'ip', 'security', and 'firewall' matches");
624
+ }
625
+
626
+ // Test case 3: Block with "ip" and "security" but no "firewall" (should NOT match)
627
+ {
628
+ let mut term_matches = HashMap::new();
629
+
630
+ // Add "ip" matches
631
+ let mut ip_lines = HashSet::new();
632
+ ip_lines.insert(3);
633
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
634
+
635
+ // Add "secur" matches (stemmed from "security")
636
+ let mut secur_lines = HashSet::new();
637
+ secur_lines.insert(4);
638
+ term_matches.insert(*term_indices.get("secur").unwrap(), secur_lines);
639
+
640
+ // Block lines
641
+ let block_lines = (1, 10);
642
+
643
+ // Test filtering
644
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
645
+ assert!(
646
+ !result,
647
+ "Block with 'ip' and 'security' but no 'firewall' should NOT match"
648
+ );
649
+ println!("✓ Block with 'ip' and 'security' but no 'firewall' doesn't match");
650
+ }
651
+
652
+ // Test case 4: Block with only "ip" (should NOT match)
653
+ {
654
+ let mut term_matches = HashMap::new();
655
+
656
+ // Add only "ip" matches
657
+ let mut ip_lines = HashSet::new();
658
+ ip_lines.insert(3);
659
+ term_matches.insert(*term_indices.get("ip").unwrap(), ip_lines);
660
+
661
+ // Block lines
662
+ let block_lines = (1, 10);
663
+
664
+ // Test filtering
665
+ let result = filter_code_block_with_ast(block_lines, &term_matches, &plan, true);
666
+ assert!(!result, "Block with only 'ip' should NOT match");
667
+ println!("✓ Block with only 'ip' doesn't match");
668
+ }
669
+ }