@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,922 @@
1
+ use lru::LruCache;
2
+ use std::collections::{HashMap, HashSet};
3
+ use std::fs;
4
+ use std::num::NonZeroUsize;
5
+ use std::path::Path;
6
+ use std::sync::{Arc, Mutex};
7
+ use tempfile::TempDir;
8
+
9
+ use probe_code::search::elastic_query::Expr;
10
+ use probe_code::search::query::QueryPlan;
11
+ use probe_code::search::{perform_probe, SearchOptions};
12
+
13
+ /// Create test files with different content for testing queries
14
+ fn create_test_files(temp_dir: &Path) {
15
+ // File with "keywordAlpha" and "keywordBeta"
16
+ let file1_path = temp_dir.join("file1.rs");
17
+ let file1_content = r#"
18
+ // This file contains keywordAlpha and keywordBeta
19
+ fn test_function() {
20
+ // This is keywordAlpha
21
+ let x = 1;
22
+
23
+ // This is keywordBeta
24
+ let y = 2;
25
+
26
+ println!("Result: {}", x + y);
27
+ }
28
+ "#;
29
+
30
+ // File with "keywordAlpha" and "keywordGamma"
31
+ let file2_path = temp_dir.join("file2.rs");
32
+ let file2_content = r#"
33
+ // This file contains keywordAlpha and keywordGamma
34
+ fn another_function() {
35
+ // This is keywordAlpha
36
+ let x = 1;
37
+
38
+ // This is keywordGamma
39
+ let z = 3;
40
+
41
+ println!("Result: {}", x + z);
42
+ }
43
+ "#;
44
+
45
+ // File with "keywordBeta" and "keywordGamma"
46
+ let file3_path = temp_dir.join("file3.rs");
47
+ let file3_content = r#"
48
+ // This file contains keywordBeta and keywordGamma
49
+ fn third_function() {
50
+ // This is keywordBeta
51
+ let y = 2;
52
+
53
+ // This is keywordGamma
54
+ let z = 3;
55
+
56
+ println!("Result: {}", y + z);
57
+ }
58
+ "#;
59
+
60
+ // File with all keywords
61
+ let file4_path = temp_dir.join("file4.rs");
62
+ let file4_content = r#"
63
+ // This file contains keywordAlpha, keywordBeta, and keywordGamma
64
+ fn all_keywords_function() {
65
+ // This is keywordAlpha
66
+ let x = 1;
67
+
68
+ // This is keywordBeta
69
+ let y = 2;
70
+
71
+ // This is keywordGamma
72
+ let z = 3;
73
+
74
+ println!("Result: {}", x + y + z);
75
+ }
76
+ "#;
77
+
78
+ // Write files to disk
79
+ fs::write(file1_path, file1_content).unwrap();
80
+ fs::write(file2_path, file2_content).unwrap();
81
+ fs::write(file3_path, file3_content).unwrap();
82
+ fs::write(file4_path, file4_content).unwrap();
83
+ }
84
+
85
+ /// Test a query with a required term: key OR word OR keyword
86
+ #[test]
87
+ fn test_required_term_query() {
88
+ // Create a temporary directory for testing
89
+ let temp_dir = TempDir::new().unwrap();
90
+ let temp_path = temp_dir.path();
91
+
92
+ // Create test files with different content
93
+ create_test_files(temp_path);
94
+
95
+ // Create search query with explicit OR syntax that matches the actual content
96
+ // Since we've removed any_term parameter and changed the default to AND,
97
+ // we need to use explicit OR syntax to maintain the original behavior
98
+ let queries = vec!["keywordAlpha OR keywordBeta OR keywordGamma".to_string()];
99
+ let custom_ignores: Vec<String> = vec![];
100
+
101
+ // Print the query for debugging
102
+ println!("Testing query: {queries:?}");
103
+
104
+ // Create SearchOptions
105
+ let options = SearchOptions {
106
+ path: temp_path,
107
+ queries: &queries,
108
+ files_only: false,
109
+ custom_ignores: &custom_ignores,
110
+ exclude_filenames: false,
111
+ language: None,
112
+ reranker: "hybrid",
113
+ frequency_search: false,
114
+ max_results: None,
115
+ max_bytes: None,
116
+ max_tokens: None,
117
+ allow_tests: true,
118
+ no_merge: false,
119
+ merge_threshold: Some(5),
120
+ dry_run: false,
121
+ session: None,
122
+ timeout: 30,
123
+ question: None,
124
+ exact: false,
125
+ no_gitignore: false,
126
+ };
127
+
128
+ // Print the temp_path for debugging
129
+ println!("Temp path: {temp_path:?}");
130
+
131
+ // List files in the temp directory
132
+ println!("Files in temp directory:");
133
+ for entry in std::fs::read_dir(temp_path).unwrap() {
134
+ let entry = entry.unwrap();
135
+ println!(" {:?}", entry.path());
136
+ }
137
+
138
+ // Run the search
139
+ let search_results = perform_probe(&options).unwrap();
140
+
141
+ // Debug output
142
+ println!("Search results: {} items", search_results.results.len());
143
+ for result in &search_results.results {
144
+ println!(" File: {}", result.file);
145
+ }
146
+
147
+ // Check that we got results
148
+ assert!(
149
+ !search_results.results.is_empty(),
150
+ "Search should return results"
151
+ );
152
+
153
+ // We should only find files with keywordAlpha
154
+ let file_names: Vec<&str> = search_results
155
+ .results
156
+ .iter()
157
+ .map(|r| r.file.as_str())
158
+ .collect();
159
+
160
+ // Debug output
161
+ println!("Found {} results", search_results.results.len());
162
+ for result in &search_results.results {
163
+ println!("File: {}", result.file);
164
+ }
165
+
166
+ // Check that we found files with keywordAlpha OR keywordBeta OR keywordGamma
167
+ assert!(
168
+ file_names.iter().any(|&name| name.contains("file1")),
169
+ "Should find file1 which contains keywordAlpha OR keywordBeta"
170
+ );
171
+ assert!(
172
+ file_names.iter().any(|&name| name.contains("file2")),
173
+ "Should find file2 which contains keywordAlpha OR keywordGamma"
174
+ );
175
+ assert!(
176
+ file_names.iter().any(|&name| name.contains("file3")),
177
+ "Should find file3 which contains keywordBeta OR keywordGamma"
178
+ );
179
+ assert!(
180
+ file_names.iter().any(|&name| name.contains("file4")),
181
+ "Should find file4 which contains keywordAlpha, keywordBeta, and keywordGamma"
182
+ );
183
+ }
184
+
185
+ /// Test a query with an excluded term: -keywordGamma
186
+ #[test]
187
+ fn test_excluded_term_query() {
188
+ // Create a temporary directory for testing
189
+ let temp_dir = TempDir::new().unwrap();
190
+ let temp_path = temp_dir.path();
191
+
192
+ // Create test files with different content
193
+ create_test_files(temp_path);
194
+
195
+ // Create search query with an excluded term
196
+ let queries = vec!["(key OR word OR keyword) -keywordGamma".to_string()];
197
+ let custom_ignores: Vec<String> = vec![];
198
+
199
+ // Print the test files for debugging
200
+ println!("Test files created in: {temp_path:?}");
201
+ for entry in std::fs::read_dir(temp_path).unwrap() {
202
+ let entry = entry.unwrap();
203
+ println!(" {:?}", entry.path());
204
+
205
+ // Print file content for debugging
206
+ let content = std::fs::read_to_string(entry.path()).unwrap();
207
+ println!(
208
+ " Content of {:?}:\n{}",
209
+ entry.path().file_name().unwrap(),
210
+ content
211
+ );
212
+ }
213
+
214
+ // Create SearchOptions
215
+ let options = SearchOptions {
216
+ path: temp_path,
217
+ queries: &queries,
218
+ files_only: false,
219
+ custom_ignores: &custom_ignores,
220
+ exclude_filenames: false,
221
+ language: None,
222
+ reranker: "hybrid",
223
+ frequency_search: false,
224
+ max_results: None,
225
+ max_bytes: None,
226
+ max_tokens: None,
227
+ allow_tests: true,
228
+ no_merge: false,
229
+ merge_threshold: Some(5),
230
+ dry_run: false,
231
+ session: None,
232
+ timeout: 30,
233
+ question: None,
234
+ exact: false,
235
+ no_gitignore: false,
236
+ };
237
+
238
+ // Print the query for debugging
239
+ println!("Executing search with query: {queries:?}");
240
+ println!(
241
+ "Path: {:?}, frequency_search: {}",
242
+ options.path, options.frequency_search
243
+ );
244
+
245
+ // Run the search
246
+ let search_results = perform_probe(&options).unwrap();
247
+
248
+ // Check that we got results
249
+ assert!(
250
+ !search_results.results.is_empty(),
251
+ "Search should return results"
252
+ );
253
+
254
+ // We should find files with (key OR word OR keyword) -keywordGamma
255
+ let file_names: Vec<&str> = search_results
256
+ .results
257
+ .iter()
258
+ .map(|r| r.file.as_str())
259
+ .collect();
260
+
261
+ // Debug output
262
+ println!(
263
+ "Excluded term query results: {} items",
264
+ search_results.results.len()
265
+ );
266
+ for result in &search_results.results {
267
+ println!(" File: {}", result.file);
268
+ }
269
+
270
+ // Check that we found file1 (has key OR word OR keyword but not keywordGamma)
271
+ assert!(
272
+ file_names.iter().any(|&name| name.contains("file1")),
273
+ "Should find file1 which contains key OR word OR keyword but not keywordGamma"
274
+ );
275
+
276
+ // Check that we don't find file2, file3, and file4 (they have keywordGamma)
277
+ assert!(
278
+ !file_names.iter().any(|&name| name.contains("file2")),
279
+ "Should not find file2 which contains keywordGamma"
280
+ );
281
+
282
+ assert!(
283
+ !file_names.iter().any(|&name| name.contains("file3")),
284
+ "Should not find file3 which contains keywordGamma"
285
+ );
286
+
287
+ assert!(
288
+ !file_names.iter().any(|&name| name.contains("file4")),
289
+ "Should not find file4 which contains keywordGamma"
290
+ );
291
+ }
292
+
293
+ /// Test a query with OR: keywordAlpha OR keywordBeta
294
+ #[test]
295
+ fn test_or_query() {
296
+ // Create a temporary directory for testing
297
+ let temp_dir = TempDir::new().unwrap();
298
+ let temp_path = temp_dir.path();
299
+
300
+ // Create test files with different content
301
+ create_test_files(temp_path);
302
+
303
+ // Create search query with explicit OR syntax
304
+ // Make sure to use uppercase OR to ensure it's recognized as an operator
305
+ let queries = vec!["keywordAlpha OR keywordBeta".to_string()];
306
+ let custom_ignores: Vec<String> = vec![];
307
+
308
+ // Create SearchOptions
309
+ let options = SearchOptions {
310
+ path: temp_path,
311
+ queries: &queries,
312
+ files_only: true, // Use files_only to ensure we find all matching files
313
+ custom_ignores: &custom_ignores,
314
+ exclude_filenames: false,
315
+ language: None,
316
+ reranker: "hybrid",
317
+ frequency_search: true, // Enable frequency search to improve matching
318
+ max_results: None,
319
+ max_bytes: None,
320
+ max_tokens: None,
321
+ allow_tests: true,
322
+ no_merge: false,
323
+ merge_threshold: Some(5),
324
+ dry_run: false,
325
+ session: None,
326
+ timeout: 30,
327
+ question: None,
328
+ exact: false,
329
+ no_gitignore: false,
330
+ };
331
+
332
+ // Print the test files for debugging
333
+ println!("Test files created in: {temp_path:?}");
334
+ for entry in std::fs::read_dir(temp_path).unwrap() {
335
+ let entry = entry.unwrap();
336
+ println!(" {:?}", entry.path());
337
+
338
+ // Print file content for debugging
339
+ let content = std::fs::read_to_string(entry.path()).unwrap();
340
+ println!(
341
+ " Content of {:?}:\n{}",
342
+ entry.path().file_name().unwrap(),
343
+ content
344
+ );
345
+ }
346
+
347
+ // Print the query for debugging
348
+ println!("Executing search with query: {queries:?}");
349
+ println!(
350
+ "Path: {:?}, frequency_search: {}",
351
+ options.path, options.frequency_search
352
+ );
353
+
354
+ // Run the search
355
+ let search_results = perform_probe(&options).unwrap();
356
+
357
+ // Check that we got results
358
+ assert!(
359
+ !search_results.results.is_empty(),
360
+ "Search should return results"
361
+ );
362
+
363
+ // We should find files with keywordAlpha OR keywordBeta
364
+ let file_names: Vec<&str> = search_results
365
+ .results
366
+ .iter()
367
+ .map(|r| r.file.as_str())
368
+ .collect();
369
+
370
+ // Debug output to see what files were found
371
+ println!("Found files with 'keywordAlpha OR keywordBeta':");
372
+ for name in &file_names {
373
+ println!(" {name}");
374
+ }
375
+
376
+ // Check that we found files with keywordAlpha OR keywordBeta
377
+ assert!(
378
+ file_names.iter().any(|&name| name.contains("file1")),
379
+ "Should find file1 which contains keywordAlpha and keywordBeta"
380
+ );
381
+ assert!(
382
+ file_names.iter().any(|&name| name.contains("file2")),
383
+ "Should find file2 which contains keywordAlpha"
384
+ );
385
+ assert!(
386
+ file_names.iter().any(|&name| name.contains("file3")),
387
+ "Should find file3 which contains keywordBeta"
388
+ );
389
+ assert!(
390
+ file_names.iter().any(|&name| name.contains("file4")),
391
+ "Should find file4 which contains keywordAlpha and keywordBeta"
392
+ );
393
+ }
394
+
395
+ /// Test a complex query with OR syntax
396
+ #[test]
397
+ fn test_complex_query_or() {
398
+ // Create a temporary directory for testing
399
+ let temp_dir = TempDir::new().unwrap();
400
+ let temp_path = temp_dir.path();
401
+
402
+ // Create test files with different content
403
+ create_test_files(temp_path);
404
+
405
+ // Test with explicit OR syntax
406
+ // "keywordAlpha OR keywordBeta" means files with keywordAlpha OR keywordBeta
407
+ let queries = vec!["keywordAlpha OR keywordBeta".to_string()];
408
+ let custom_ignores: Vec<String> = vec![];
409
+
410
+ // Create SearchOptions
411
+ let options = SearchOptions {
412
+ path: temp_path,
413
+ queries: &queries,
414
+ files_only: false,
415
+ custom_ignores: &custom_ignores,
416
+ exclude_filenames: false,
417
+ language: None,
418
+ reranker: "hybrid",
419
+ frequency_search: true, // Enable frequency search to improve matching
420
+ max_results: None,
421
+ max_bytes: None,
422
+ max_tokens: None,
423
+ allow_tests: true,
424
+ no_merge: false,
425
+ merge_threshold: Some(5),
426
+ dry_run: false,
427
+ session: None,
428
+ timeout: 30,
429
+ question: None,
430
+ exact: false,
431
+ no_gitignore: false,
432
+ };
433
+
434
+ // Print the test files for debugging
435
+ println!("Test files created in: {temp_path:?}");
436
+ for entry in std::fs::read_dir(temp_path).unwrap() {
437
+ let entry = entry.unwrap();
438
+ println!(" {:?}", entry.path());
439
+
440
+ // Print file content for debugging
441
+ let content = std::fs::read_to_string(entry.path()).unwrap();
442
+ println!(
443
+ " Content of {:?}:\n{}",
444
+ entry.path().file_name().unwrap(),
445
+ content
446
+ );
447
+ }
448
+
449
+ // Print the query for debugging
450
+ println!("Executing search with query: {queries:?}");
451
+ println!(
452
+ "Path: {:?}, frequency_search: {}",
453
+ options.path, options.frequency_search
454
+ );
455
+
456
+ // Run the search
457
+ let search_results = perform_probe(&options).unwrap();
458
+
459
+ // Check that we got results
460
+ assert!(
461
+ !search_results.results.is_empty(),
462
+ "Search should return results"
463
+ );
464
+
465
+ let file_names: Vec<&str> = search_results
466
+ .results
467
+ .iter()
468
+ .map(|r| r.file.as_str())
469
+ .collect();
470
+
471
+ // Debug output to see what files were found
472
+ println!("Found files with 'keywordAlpha OR keywordBeta':");
473
+ for name in &file_names {
474
+ println!(" {name}");
475
+ }
476
+
477
+ // With explicit OR syntax, should find all files with keywordAlpha OR keywordBeta
478
+ assert!(
479
+ file_names.iter().any(|&name| name.contains("file1")),
480
+ "Should find file1 which has keywordAlpha and keywordBeta"
481
+ );
482
+ assert!(
483
+ file_names.iter().any(|&name| name.contains("file2")),
484
+ "Should find file2 which has keywordAlpha"
485
+ );
486
+ assert!(
487
+ file_names.iter().any(|&name| name.contains("file3")),
488
+ "Should find file3 which has keywordBeta"
489
+ );
490
+ assert!(
491
+ file_names.iter().any(|&name| name.contains("file4")),
492
+ "Should find file4 which has keywordAlpha and keywordBeta"
493
+ );
494
+ }
495
+
496
+ /// Test a complex query with explicit OR syntax
497
+ #[test]
498
+ fn test_complex_query_exclusion() {
499
+ // Create a temporary directory for testing
500
+ let temp_dir = TempDir::new().unwrap();
501
+ let temp_path = temp_dir.path();
502
+
503
+ // Create test files with different content
504
+ create_test_files(temp_path);
505
+
506
+ // Test with exclusion
507
+ let queries = vec!["\"keywordAlpha\" -keywordGamma".to_string()];
508
+ let custom_ignores: Vec<String> = vec![];
509
+
510
+ // Create SearchOptions
511
+ let options = SearchOptions {
512
+ path: temp_path,
513
+ queries: &queries,
514
+ files_only: false,
515
+ custom_ignores: &custom_ignores,
516
+ exclude_filenames: false,
517
+ language: None,
518
+ reranker: "hybrid",
519
+ frequency_search: false,
520
+ max_results: None,
521
+ max_bytes: None,
522
+ max_tokens: None,
523
+ allow_tests: true,
524
+ no_merge: false,
525
+ merge_threshold: Some(5),
526
+ dry_run: false,
527
+ session: None,
528
+ timeout: 30,
529
+ question: None,
530
+ exact: false,
531
+ no_gitignore: false,
532
+ };
533
+
534
+ // Print the query for debugging
535
+ println!("Executing search with query: {queries:?}");
536
+ println!(
537
+ "Path: {:?}, frequency_search: {}",
538
+ options.path, options.frequency_search
539
+ );
540
+
541
+ // Run the search
542
+ let search_results = perform_probe(&options).unwrap();
543
+
544
+ // Check that we got results
545
+ assert!(
546
+ !search_results.results.is_empty(),
547
+ "Search should return results for query: {queries:?}"
548
+ );
549
+
550
+ let file_names: Vec<&str> = search_results
551
+ .results
552
+ .iter()
553
+ .map(|r| r.file.as_str())
554
+ .collect();
555
+
556
+ // Debug output to see what files were found
557
+ println!("Found files with 'keywordAlpha -keywordGamma':");
558
+ for name in &file_names {
559
+ println!(" {name}");
560
+ }
561
+
562
+ // Should find file1 (has keywordAlpha and no keywordGamma)
563
+ assert!(
564
+ file_names.iter().any(|&name| name.contains("file1")),
565
+ "Should find file1 which has keywordAlpha but no keywordGamma"
566
+ );
567
+
568
+ // Should NOT find file2 (has keywordAlpha but also has keywordGamma)
569
+ assert!(
570
+ !file_names.iter().any(|&name| name.contains("file2")),
571
+ "Should not find file2 which has keywordGamma"
572
+ );
573
+
574
+ // Should NOT find file4 (has keywordAlpha but also has keywordGamma)
575
+ assert!(
576
+ !file_names.iter().any(|&name| name.contains("file4")),
577
+ "Should not find file4 which has keywordGamma"
578
+ );
579
+ }
580
+
581
+ /// Test underscore handling in queries
582
+ #[test]
583
+ fn test_underscore_handling_integration() {
584
+ // Create a temporary directory for testing
585
+ let temp_dir = TempDir::new().unwrap();
586
+ let temp_path = temp_dir.path();
587
+
588
+ // Create a test file with the tokenized terms
589
+ let file_path = temp_path.join("underscore_test.rs");
590
+ let file_content = r#"
591
+ // This file contains key word score
592
+ fn test_function() {
593
+ // This has key, word, and score
594
+ let x = 1;
595
+
596
+ // This also has key word score
597
+ let y = 2;
598
+
599
+ println!("Result: {}", x + y);
600
+ }
601
+ "#;
602
+ fs::write(file_path, file_content).unwrap();
603
+
604
+ // Test query with underscore using explicit OR syntax
605
+ // Since we've removed any_term parameter and changed the default to AND,
606
+ // we need to use explicit OR syntax to maintain the original behavior
607
+ let queries = vec!["key OR word OR score".to_string()];
608
+ let custom_ignores: Vec<String> = vec![];
609
+
610
+ // Create SearchOptions
611
+ let options = SearchOptions {
612
+ path: temp_path,
613
+ queries: &queries,
614
+ files_only: false,
615
+ custom_ignores: &custom_ignores,
616
+ exclude_filenames: false,
617
+ language: None,
618
+ reranker: "hybrid",
619
+ frequency_search: false,
620
+ max_results: None,
621
+ max_bytes: None,
622
+ max_tokens: None,
623
+ allow_tests: true,
624
+ no_merge: false,
625
+ merge_threshold: Some(5),
626
+ dry_run: false,
627
+ session: None,
628
+ timeout: 30,
629
+ question: None,
630
+ exact: false,
631
+ no_gitignore: false,
632
+ };
633
+
634
+ // Run the search
635
+ let search_results = perform_probe(&options).unwrap();
636
+
637
+ // Check that we got results
638
+ assert!(
639
+ !search_results.results.is_empty(),
640
+ "Search should return results"
641
+ );
642
+
643
+ let file_names: Vec<&str> = search_results
644
+ .results
645
+ .iter()
646
+ .map(|r| r.file.as_str())
647
+ .collect();
648
+
649
+ // Debug output to see what files were found
650
+ println!("Found files with 'key OR word OR score':");
651
+ for name in &file_names {
652
+ println!(" {name}");
653
+ }
654
+
655
+ // Should find the file with at least one of the terms: key, word, or score
656
+ assert!(
657
+ file_names.iter().any(|&name| name.contains("underscore_test")),
658
+ "Should find underscore_test.rs which contains at least one of the terms: key, word, or score"
659
+ );
660
+
661
+ // Verify that the code in the results contains at least one of the tokenized terms
662
+ for result in &search_results.results {
663
+ println!("Result code: {}", result.code);
664
+ // The search should find files containing at least one of the tokenized terms
665
+ assert!(
666
+ result.code.contains("key")
667
+ || result.code.contains("word")
668
+ || result.code.contains("score"),
669
+ "Result code should contain at least one of the terms: 'key', 'word', or 'score'"
670
+ );
671
+ }
672
+ }
673
+
674
+ /// Test the direct usage of filter_code_block_with_ast
675
+ #[test]
676
+ fn test_filter_code_block_with_ast() {
677
+ // This test directly tests the filter_code_block_with_ast function
678
+ // by creating a mock QueryPlan and term matches
679
+
680
+ // Create a simple AST: keywordAlpha AND -keywordBeta
681
+ let ast = Expr::And(
682
+ Box::new(Expr::Term {
683
+ keywords: vec!["keywordAlpha".to_string()],
684
+ lowercase_keywords: vec!["keywordalpha".to_string()],
685
+ field: None,
686
+ required: false,
687
+ excluded: false,
688
+ exact: false,
689
+ }),
690
+ Box::new(Expr::Term {
691
+ keywords: vec!["keywordBeta".to_string()],
692
+ lowercase_keywords: vec!["keywordbeta".to_string()],
693
+ field: None,
694
+ required: false,
695
+ excluded: true,
696
+ exact: false,
697
+ }),
698
+ );
699
+
700
+ // Create a term indices map (keys should be lowercased for case-insensitive matching)
701
+ let mut term_indices = HashMap::new();
702
+ term_indices.insert("keywordalpha".to_string(), 0);
703
+ term_indices.insert("keywordbeta".to_string(), 1);
704
+
705
+ // Create a QueryPlan
706
+ let has_required_anywhere = ast.has_required_term();
707
+ let has_only_excluded_terms = ast.is_only_excluded_terms();
708
+ let required_terms_indices = HashSet::new();
709
+ let evaluation_cache = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(1000).unwrap())));
710
+
711
+ let plan = QueryPlan {
712
+ ast,
713
+ term_indices,
714
+ excluded_terms: {
715
+ let mut set = HashSet::new();
716
+ set.insert("keywordbeta".to_string());
717
+ set
718
+ },
719
+ exact: false,
720
+ is_simple_query: false,
721
+ required_terms: HashSet::new(),
722
+ has_required_anywhere,
723
+ required_terms_indices,
724
+ has_only_excluded_terms,
725
+ evaluation_cache,
726
+ is_universal_query: false,
727
+ };
728
+
729
+ // Create term matches for a block
730
+ let mut term_matches = HashMap::new();
731
+
732
+ // Block with only keywordAlpha
733
+ let mut lines1 = HashSet::new();
734
+ lines1.insert(1);
735
+ lines1.insert(2);
736
+ term_matches.insert(0, lines1);
737
+
738
+ // Test the function with a block that should match
739
+ let block_lines = (1, 5);
740
+ let debug_mode = false;
741
+
742
+ // Import the function from probe crate
743
+ use probe_code::search::file_processing::filter_code_block_with_ast;
744
+
745
+ // The block should match because it has keywordAlpha but not keywordBeta
746
+ assert!(
747
+ filter_code_block_with_ast(block_lines, &term_matches, &plan, debug_mode),
748
+ "Block should match because it has keywordAlpha but not keywordBeta"
749
+ );
750
+
751
+ // Now add keywordBeta to the block
752
+ let mut lines2 = HashSet::new();
753
+ lines2.insert(3);
754
+ lines2.insert(4);
755
+ term_matches.insert(1, lines2);
756
+
757
+ // The block should not match because it now has keywordBeta (which is excluded)
758
+ assert!(
759
+ !filter_code_block_with_ast(block_lines, &term_matches, &plan, debug_mode),
760
+ "Block should not match because it has keywordBeta which is excluded"
761
+ );
762
+ }
763
+
764
+ /// Test the direct usage of filter_tokenized_block
765
+ #[test]
766
+ fn test_filter_tokenized_block() {
767
+ // This test directly tests the filter_tokenized_block function
768
+ // by creating a mock QueryPlan and tokenized content
769
+
770
+ // Create a simple AST: keywordAlpha AND -keywordBeta
771
+ let ast = Expr::And(
772
+ Box::new(Expr::Term {
773
+ keywords: vec!["keywordAlpha".to_string()],
774
+ lowercase_keywords: vec!["keywordalpha".to_string()],
775
+ field: None,
776
+ required: false,
777
+ excluded: false,
778
+ exact: false,
779
+ }),
780
+ Box::new(Expr::Term {
781
+ keywords: vec!["keywordBeta".to_string()],
782
+ lowercase_keywords: vec!["keywordbeta".to_string()],
783
+ field: None,
784
+ required: false,
785
+ excluded: true,
786
+ exact: false,
787
+ }),
788
+ );
789
+
790
+ // Create a term indices map (keys should be lowercased for case-insensitive matching)
791
+ let mut term_indices = HashMap::new();
792
+ term_indices.insert("keywordalpha".to_string(), 0);
793
+ term_indices.insert("keywordbeta".to_string(), 1);
794
+
795
+ // Create a QueryPlan
796
+ let has_required_anywhere = ast.has_required_term();
797
+ let has_only_excluded_terms = ast.is_only_excluded_terms();
798
+ let required_terms_indices = HashSet::new();
799
+ let evaluation_cache = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(1000).unwrap())));
800
+
801
+ let plan = QueryPlan {
802
+ ast,
803
+ term_indices: term_indices.clone(),
804
+ excluded_terms: {
805
+ let mut set = HashSet::new();
806
+ set.insert("keywordbeta".to_string());
807
+ set
808
+ },
809
+ exact: false,
810
+ is_simple_query: false,
811
+ required_terms: HashSet::new(),
812
+ has_required_anywhere,
813
+ required_terms_indices,
814
+ has_only_excluded_terms,
815
+ evaluation_cache,
816
+ is_universal_query: false,
817
+ };
818
+
819
+ // Import the function from probe crate
820
+ use probe_code::search::file_processing::filter_tokenized_block;
821
+
822
+ // Test case 1: Tokenized content with only keywordAlpha (lowercased since tokenization lowercases)
823
+ let tokenized_content = vec!["keywordalpha".to_string()];
824
+ let debug_mode = false;
825
+
826
+ // The block should match because it has keywordAlpha but not keywordBeta
827
+ assert!(
828
+ filter_tokenized_block(&tokenized_content, &term_indices, &plan, debug_mode),
829
+ "Block should match because it has keywordAlpha but not keywordBeta"
830
+ );
831
+
832
+ // Test case 2: Tokenized content with both keywordAlpha and keywordBeta (lowercased)
833
+ let tokenized_content = vec!["keywordalpha".to_string(), "keywordbeta".to_string()];
834
+
835
+ // The block should not match because it has keywordBeta (which is excluded)
836
+ assert!(
837
+ !filter_tokenized_block(&tokenized_content, &term_indices, &plan, debug_mode),
838
+ "Block should not match because it has keywordBeta which is excluded"
839
+ );
840
+
841
+ // Test case 3: Tokenized content with neither keyword
842
+ let tokenized_content = vec!["other".to_string()];
843
+
844
+ // The block should not match because it doesn't have keywordAlpha
845
+ assert!(
846
+ !filter_tokenized_block(&tokenized_content, &term_indices, &plan, debug_mode),
847
+ "Block should not match because it doesn't have keywordAlpha"
848
+ );
849
+
850
+ // Test case 4: Empty tokenized content
851
+ let tokenized_content: Vec<String> = vec![];
852
+
853
+ // The block should not match because it doesn't have keywordAlpha
854
+ assert!(
855
+ !filter_tokenized_block(&tokenized_content, &term_indices, &plan, debug_mode),
856
+ "Empty block should not match"
857
+ );
858
+
859
+ // Test case 5: Test with OR expression
860
+ // Create a simple AST: keywordAlpha OR keywordGamma
861
+ let ast_or = Expr::Or(
862
+ Box::new(Expr::Term {
863
+ keywords: vec!["keywordAlpha".to_string()],
864
+ lowercase_keywords: vec!["keywordalpha".to_string()],
865
+ field: None,
866
+ required: false,
867
+ excluded: false,
868
+ exact: false,
869
+ }),
870
+ Box::new(Expr::Term {
871
+ keywords: vec!["keywordGamma".to_string()],
872
+ lowercase_keywords: vec!["keywordgamma".to_string()],
873
+ field: None,
874
+ required: false,
875
+ excluded: false,
876
+ exact: false,
877
+ }),
878
+ );
879
+
880
+ // Create a term indices map
881
+ let mut term_indices_or = HashMap::new();
882
+ term_indices_or.insert("keywordalpha".to_string(), 0);
883
+ term_indices_or.insert("keywordgamma".to_string(), 2);
884
+
885
+ // Create a QueryPlan
886
+ let has_required_anywhere = ast_or.has_required_term();
887
+ let has_only_excluded_terms = ast_or.is_only_excluded_terms();
888
+ let required_terms_indices = HashSet::new();
889
+ let evaluation_cache = Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(1000).unwrap())));
890
+
891
+ let plan_or = QueryPlan {
892
+ ast: ast_or,
893
+ term_indices: term_indices_or.clone(),
894
+ excluded_terms: HashSet::new(),
895
+ exact: false,
896
+ is_simple_query: false,
897
+ required_terms: HashSet::new(),
898
+ has_required_anywhere,
899
+ required_terms_indices,
900
+ has_only_excluded_terms,
901
+ evaluation_cache,
902
+ is_universal_query: false,
903
+ };
904
+
905
+ // Test with only keywordGamma (lowercased since tokenization lowercases)
906
+ let tokenized_content = vec!["keywordgamma".to_string()];
907
+
908
+ // The block should match because it has keywordGamma (part of OR expression)
909
+ assert!(
910
+ filter_tokenized_block(&tokenized_content, &term_indices_or, &plan_or, debug_mode),
911
+ "Block should match because it has keywordGamma (part of OR expression)"
912
+ );
913
+
914
+ // Test with both keywordAlpha and keywordGamma (lowercased since tokenization lowercases)
915
+ let tokenized_content = vec!["keywordalpha".to_string(), "keywordgamma".to_string()];
916
+
917
+ // The block should match because it has both keywords in OR expression
918
+ assert!(
919
+ filter_tokenized_block(&tokenized_content, &term_indices_or, &plan_or, debug_mode),
920
+ "Block should match because it has both keywords in OR expression"
921
+ );
922
+ }