@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,530 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { ProbeChat } from '../probeChat.js';
5
+ import { MockLLMProvider, createMockStreamText } from './mocks/mockLLMProvider.js';
6
+ import MockBackend from '../implement/backends/MockBackend.js';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+
11
+ // Test environment setup
12
+ export function setupTestEnvironment() {
13
+ // Store original environment
14
+ const originalEnv = { ...process.env };
15
+
16
+ // Clear API keys to ensure mock providers are used
17
+ delete process.env.ANTHROPIC_API_KEY;
18
+ delete process.env.OPENAI_API_KEY;
19
+ delete process.env.GOOGLE_API_KEY;
20
+
21
+ // Set test mode
22
+ process.env.NODE_ENV = 'test';
23
+ process.env.PROBE_TEST_MODE = 'true';
24
+
25
+ return {
26
+ restore: () => {
27
+ Object.keys(process.env).forEach(key => {
28
+ if (!(key in originalEnv)) {
29
+ delete process.env[key];
30
+ }
31
+ });
32
+ Object.assign(process.env, originalEnv);
33
+ }
34
+ };
35
+ }
36
+
37
+ // Create a test instance of ProbeChat with mocks
38
+ export async function createTestProbeChat(options = {}) {
39
+ const mockProvider = options.mockProvider instanceof MockLLMProvider ?
40
+ options.mockProvider :
41
+ new MockLLMProvider({
42
+ responses: options.responses || [],
43
+ ...(typeof options.mockProvider === 'object' ? options.mockProvider : {})
44
+ });
45
+
46
+ const mockStreamText = createMockStreamText(mockProvider);
47
+
48
+ // Create instance with mocks injected
49
+ const probeChat = new ProbeChat({
50
+ modelName: 'mock-model',
51
+ provider: 'mock',
52
+ ...options.chatOptions
53
+ });
54
+
55
+ // Set temperature and maxTokens if provided
56
+ if (options.chatOptions?.temperature !== undefined) {
57
+ probeChat.temperature = options.chatOptions.temperature;
58
+ }
59
+ if (options.chatOptions?.maxTokens !== undefined) {
60
+ probeChat.maxTokens = options.chatOptions.maxTokens;
61
+ }
62
+ if (options.chatOptions?.systemPrompt !== undefined) {
63
+ probeChat.customPrompt = options.chatOptions.systemPrompt;
64
+ }
65
+
66
+ // Override the streamText function
67
+ probeChat.streamText = mockStreamText;
68
+
69
+ // Override model initialization to use our mock
70
+ probeChat.initializeModel = function() {
71
+ this.model = mockProvider.createMockModel();
72
+ this.modelId = 'mock-model';
73
+ this.modelInfo = {
74
+ provider: 'mock',
75
+ contextWindow: 100000,
76
+ maxOutput: 4096,
77
+ supportsImages: true,
78
+ supportsPromptCaching: false
79
+ };
80
+ this.isInitialized = true;
81
+ this.noApiKeysMode = false; // Disable API key mode for tests
82
+ this.apiType = 'mock';
83
+ };
84
+
85
+ // Initialize the mock model
86
+ probeChat.initializeModel();
87
+
88
+ // Create mock tool instances
89
+ const mockTools = {
90
+ probe_search: {
91
+ execute: async (args) => {
92
+ console.log('Mock probe_search called with:', args);
93
+ return createMockProbeResults();
94
+ },
95
+ validate: (args) => {
96
+ if (!args.query) {
97
+ throw new Error('Missing required field: query');
98
+ }
99
+ }
100
+ },
101
+ probe_query: {
102
+ execute: async (args) => {
103
+ console.log('Mock probe_query called with:', args);
104
+ return {
105
+ matches: [{
106
+ file: 'test.js',
107
+ matches: [{ text: 'mock match' }]
108
+ }]
109
+ };
110
+ }
111
+ },
112
+ probe_extract: {
113
+ execute: async (args) => {
114
+ console.log('Mock probe_extract called with:', args);
115
+ return {
116
+ content: 'mock extracted content',
117
+ language: 'javascript',
118
+ start_line: 1,
119
+ end_line: 10
120
+ };
121
+ }
122
+ },
123
+ implement: {
124
+ execute: async (args, options) => {
125
+ console.log('Mock implement called with:', args);
126
+ return {
127
+ sessionId: 'mock-session',
128
+ status: 'success',
129
+ filesModified: ['mock.js'],
130
+ summary: 'Mock implementation complete'
131
+ };
132
+ },
133
+ handleError: (error) => {
134
+ console.error('Mock implement error:', error);
135
+ }
136
+ }
137
+ };
138
+
139
+ // Make tools accessible for test overrides
140
+ probeChat.tools = mockTools;
141
+
142
+ // Store mock provider reference for test access
143
+ probeChat.mockProvider = mockProvider;
144
+
145
+ // Add missing ProbeChat methods for tests
146
+ probeChat.messages = [];
147
+ probeChat.history = probeChat.messages; // Alias for compatibility with real implementation
148
+ probeChat.sendMessage = async function(message) {
149
+ return await this.chat(message);
150
+ };
151
+
152
+ probeChat.chat = async function(message, options = {}) {
153
+ let userMessage;
154
+ if (typeof message === 'string') {
155
+ userMessage = { role: 'user', content: message };
156
+ } else if (message.role && message.content) {
157
+ userMessage = message;
158
+ } else {
159
+ userMessage = { role: 'user', content: message.content || message };
160
+ }
161
+ this.messages.push(userMessage);
162
+
163
+ // Call the mock provider with streaming support
164
+ const response = await mockStreamText({
165
+ model: this.model,
166
+ messages: this.messages,
167
+ system: this.customPrompt || 'You are a helpful assistant.',
168
+ temperature: this.temperature,
169
+ maxTokens: this.maxTokens
170
+ });
171
+
172
+ let fullResponse = '';
173
+
174
+ // Stream chunks if callback provided
175
+ if (options.onStream) {
176
+ for await (const chunk of response.textStream) {
177
+ options.onStream(chunk);
178
+ fullResponse += chunk;
179
+ }
180
+ } else {
181
+ // Otherwise just collect the full response
182
+ for await (const chunk of response.textStream) {
183
+ fullResponse += chunk;
184
+ }
185
+ }
186
+
187
+ // Check if the mock provider returned tool calls and convert them to XML format
188
+ const currentResponseIndex = this.mockProvider.currentResponseIndex - 1;
189
+ const mockResponse = this.mockProvider.responses[currentResponseIndex];
190
+ if (mockResponse?.toolCalls) {
191
+ // Convert AI SDK tool calls to XML format that ProbeChat expects
192
+ for (const toolCall of mockResponse.toolCalls) {
193
+ const xmlToolCall = this.convertToolCallToXml(toolCall);
194
+ fullResponse += '\n\n' + xmlToolCall;
195
+ }
196
+ }
197
+
198
+ const assistantMessage = { role: 'assistant', content: fullResponse };
199
+ this.messages.push(assistantMessage);
200
+
201
+ return fullResponse;
202
+ };
203
+
204
+ // Helper to convert AI SDK tool calls to XML format
205
+ probeChat.convertToolCallToXml = function(toolCall) {
206
+ const { toolName, args } = toolCall;
207
+ let xmlContent = `<${toolName}>`;
208
+
209
+ if (args) {
210
+ for (const [key, value] of Object.entries(args)) {
211
+ xmlContent += `\n<${key}>${value}</${key}>`;
212
+ }
213
+ }
214
+
215
+ xmlContent += `\n</${toolName}>`;
216
+ return xmlContent;
217
+ };
218
+
219
+ probeChat.resetConversation = function() {
220
+ this.messages = [];
221
+ };
222
+
223
+ probeChat.clearHistory = function() {
224
+ this.messages = [];
225
+ this.history = this.messages; // Alias for compatibility
226
+ return 'mock-session-id'; // Return a mock session ID like the real implementation
227
+ };
228
+
229
+ probeChat.handleToolError = function(error, toolName) {
230
+ console.error(`Tool error in ${toolName}:`, error);
231
+ return `Error executing ${toolName}: ${error.message}`;
232
+ };
233
+
234
+ probeChat.processImageUrl = async function(url) {
235
+ return 'mock-base64-image-data';
236
+ };
237
+
238
+ // Register mock backend if implement tool is being tested
239
+ if (options.useMockBackend) {
240
+ const mockBackend = new MockBackend();
241
+
242
+ if (options.mockBackendResponses) {
243
+ mockBackend.setResponses(options.mockBackendResponses);
244
+ }
245
+
246
+ // Override the implement tool's execute method to use our mock backend
247
+ const originalImplementExecute = probeChat.tools.implement.execute;
248
+ probeChat.tools.implement.execute = async function(args, options) {
249
+ // Force the mock backend
250
+ args.backend = 'mock';
251
+
252
+ // If we need to register the backend, do it here
253
+ if (this.backendManager) {
254
+ await this.backendManager.registerBackend(mockBackend);
255
+ } else {
256
+ // Direct execution with mock backend
257
+ return await mockBackend.implement(args, options);
258
+ }
259
+
260
+ return originalImplementExecute ? originalImplementExecute.call(this, args, options) :
261
+ await mockBackend.implement(args, options);
262
+ };
263
+
264
+ // Return both for test access
265
+ return { probeChat, mockProvider, mockBackend };
266
+ }
267
+
268
+ return { probeChat, mockProvider };
269
+ }
270
+
271
+ // Helper to capture console output
272
+ export function captureConsoleOutput() {
273
+ const originalLog = console.log;
274
+ const originalError = console.error;
275
+ const output = [];
276
+ const errors = [];
277
+
278
+ console.log = (...args) => {
279
+ output.push(args.join(' '));
280
+ };
281
+
282
+ console.error = (...args) => {
283
+ errors.push(args.join(' '));
284
+ };
285
+
286
+ return {
287
+ output,
288
+ errors,
289
+ restore: () => {
290
+ console.log = originalLog;
291
+ console.error = originalError;
292
+ },
293
+ getOutput: () => output.join('\n'),
294
+ getErrors: () => errors.join('\n')
295
+ };
296
+ }
297
+
298
+ // Helper to create temporary test files
299
+ export function createTempTestFiles(files) {
300
+ const tempDir = path.join(__dirname, 'temp-test-' + Date.now());
301
+ fs.mkdirSync(tempDir, { recursive: true });
302
+
303
+ const createdFiles = [];
304
+
305
+ for (const [filePath, content] of Object.entries(files)) {
306
+ const fullPath = path.join(tempDir, filePath);
307
+ const dir = path.dirname(fullPath);
308
+ fs.mkdirSync(dir, { recursive: true });
309
+ fs.writeFileSync(fullPath, content);
310
+ createdFiles.push(fullPath);
311
+ }
312
+
313
+ return {
314
+ tempDir,
315
+ files: createdFiles,
316
+ cleanup: () => {
317
+ fs.rmSync(tempDir, { recursive: true, force: true });
318
+ }
319
+ };
320
+ }
321
+
322
+ // Helper to run a chat interaction and capture results
323
+ export async function runChatInteraction(probeChat, messages, options = {}) {
324
+ const results = {
325
+ responses: [],
326
+ toolCalls: [],
327
+ errors: [],
328
+ streamedText: ''
329
+ };
330
+
331
+ // Override chat to handle tool calls from mock responses
332
+ const originalChat = probeChat.chat.bind(probeChat);
333
+ probeChat.chat = async function(message, opts = {}) {
334
+ const response = await originalChat(message, {
335
+ ...opts,
336
+ onStream: (text) => {
337
+ results.streamedText += text;
338
+ if (opts.onStream) opts.onStream(text);
339
+ }
340
+ });
341
+
342
+ // Check if the mock provider returned tool calls and execute them
343
+ const lastCall = probeChat.mockProvider?.capturedCalls[probeChat.mockProvider.capturedCalls.length - 1];
344
+ if (lastCall) {
345
+ const mockResponse = probeChat.mockProvider.responses[probeChat.mockProvider.currentResponseIndex - 1];
346
+ if (mockResponse?.toolCalls) {
347
+ for (const toolCall of mockResponse.toolCalls) {
348
+ results.toolCalls.push(toolCall);
349
+
350
+ // Actually execute the tool to trigger the test's tracking
351
+ const toolName = toolCall.toolName;
352
+ if (probeChat.tools && probeChat.tools[toolName]) {
353
+ try {
354
+ // Validate tool arguments if validate method exists
355
+ if (typeof probeChat.tools[toolName].validate === 'function') {
356
+ probeChat.tools[toolName].validate(toolCall.args);
357
+ }
358
+
359
+ await probeChat.tools[toolName].execute(toolCall.args);
360
+ } catch (error) {
361
+ // Tool execution errors are expected in some tests
362
+ console.warn(`Tool execution error for ${toolName}:`, error.message);
363
+
364
+ // Call the global error handler if it exists (for testing)
365
+ if (typeof probeChat.handleToolError === 'function') {
366
+ probeChat.handleToolError(error, toolName);
367
+ }
368
+
369
+ // Call the tool-specific error handler if it exists (for testing)
370
+ if (typeof probeChat.tools[toolName].handleError === 'function') {
371
+ probeChat.tools[toolName].handleError(error);
372
+ }
373
+ }
374
+ }
375
+
376
+ if (opts.onToolCall) opts.onToolCall(toolCall);
377
+ }
378
+ }
379
+ }
380
+
381
+ return response;
382
+ };
383
+
384
+ // Store reference to mock provider in probeChat for access
385
+ if (probeChat.model?.mockProvider) {
386
+ probeChat.mockProvider = probeChat.model.mockProvider;
387
+ }
388
+
389
+ for (const message of messages) {
390
+ try {
391
+ let currentResponse = await probeChat.chat(message, options);
392
+ results.responses.push(currentResponse);
393
+
394
+ // Continue the conversation if there are more responses with tool calls
395
+ // This simulates multi-turn tool calling conversations
396
+ let maxTurns = 10; // Prevent infinite loops
397
+ while (maxTurns > 0 && probeChat.mockProvider &&
398
+ probeChat.mockProvider.currentResponseIndex < probeChat.mockProvider.responses.length) {
399
+
400
+ const nextResponseIndex = probeChat.mockProvider.currentResponseIndex;
401
+ const nextResponse = probeChat.mockProvider.responses[nextResponseIndex];
402
+
403
+ // If the next response has tool calls, continue the conversation
404
+ if (nextResponse?.toolCalls) {
405
+ // Add a synthetic assistant message to continue the flow
406
+ const continuationResponse = await probeChat.chat({
407
+ role: 'assistant',
408
+ content: nextResponse.text || 'Continuing with next tool...'
409
+ }, options);
410
+ results.responses.push(continuationResponse);
411
+ } else {
412
+ // No more tool calls, conversation ends
413
+ break;
414
+ }
415
+
416
+ maxTurns--;
417
+ }
418
+ } catch (error) {
419
+ results.errors.push(error);
420
+ }
421
+ }
422
+
423
+ // Restore original chat
424
+ probeChat.chat = originalChat;
425
+
426
+ return results;
427
+ }
428
+
429
+ // Helper to create test probe search results
430
+ export function createMockProbeResults(options = {}) {
431
+ const defaultResult = {
432
+ path: options.path || 'test/file.js',
433
+ matches: options.matches || [{
434
+ line: 1,
435
+ column: 0,
436
+ match: options.match || 'test match',
437
+ context: options.context || 'function test() { return "test match"; }'
438
+ }],
439
+ score: options.score || 0.95,
440
+ excerpt: options.excerpt || 'function test() { return "test match"; }',
441
+ symbols: options.symbols || [{
442
+ name: 'test',
443
+ kind: 'function',
444
+ line: 1
445
+ }]
446
+ };
447
+
448
+ return {
449
+ results: options.results || [defaultResult],
450
+ total_matches: options.total_matches || 1,
451
+ search_time_ms: options.search_time_ms || 50,
452
+ bytes_processed: options.bytes_processed || 1000,
453
+ files_searched: options.files_searched || 10
454
+ };
455
+ }
456
+
457
+ // Helper to wait for async operations
458
+ export function waitFor(condition, timeout = 5000) {
459
+ return new Promise((resolve, reject) => {
460
+ const startTime = Date.now();
461
+ const interval = setInterval(() => {
462
+ if (condition()) {
463
+ clearInterval(interval);
464
+ resolve();
465
+ } else if (Date.now() - startTime > timeout) {
466
+ clearInterval(interval);
467
+ reject(new Error('Timeout waiting for condition'));
468
+ }
469
+ }, 100);
470
+ });
471
+ }
472
+
473
+ // Test assertion helpers
474
+ export const assert = {
475
+ includesText: (actual, expected, message) => {
476
+ if (!actual.includes(expected)) {
477
+ throw new Error(message || `Expected "${actual}" to include "${expected}"`);
478
+ }
479
+ },
480
+
481
+ toolCallMade: (toolCalls, toolName, message) => {
482
+ const found = toolCalls.some(call => call.toolName === toolName);
483
+ if (!found) {
484
+ throw new Error(message || `Expected tool call "${toolName}" to be made`);
485
+ }
486
+ },
487
+
488
+ noErrors: (errors, message) => {
489
+ if (errors.length > 0) {
490
+ throw new Error(message || `Expected no errors but got: ${errors.map(e => e.message).join(', ')}`);
491
+ }
492
+ },
493
+
494
+ responseCount: (responses, expected, message) => {
495
+ if (responses.length !== expected) {
496
+ throw new Error(message || `Expected ${expected} responses but got ${responses.length}`);
497
+ }
498
+ }
499
+ };
500
+
501
+ // Export test data
502
+ export const testData = {
503
+ sampleCode: {
504
+ javascript: `function fibonacci(n) {
505
+ if (n <= 1) return n;
506
+ return fibonacci(n - 1) + fibonacci(n - 2);
507
+ }`,
508
+ python: `def fibonacci(n):
509
+ if n <= 1:
510
+ return n
511
+ return fibonacci(n - 1) + fibonacci(n - 2)`,
512
+ rust: `fn fibonacci(n: u32) -> u32 {
513
+ match n {
514
+ 0 | 1 => n,
515
+ _ => fibonacci(n - 1) + fibonacci(n - 2)
516
+ }
517
+ }`
518
+ },
519
+
520
+ sampleQueries: {
521
+ simple: 'function fibonacci',
522
+ complex: 'function AND (recursive OR recursion)',
523
+ withPath: { query: 'fibonacci', path: './src' },
524
+ withOptions: {
525
+ query: 'fibonacci',
526
+ maxResults: 5,
527
+ maxTokens: 1000
528
+ }
529
+ }
530
+ };
@@ -0,0 +1,161 @@
1
+ import { test, describe, before, after } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { spawn } from 'child_process';
4
+ import { setTimeout as delay } from 'timers/promises';
5
+
6
+ describe('Backend Timeout Cleanup Tests', () => {
7
+ // Helper to count active timers
8
+ function getActiveTimerCount() {
9
+ // This is a simplified check - in real tests you might use
10
+ // process._getActiveHandles() or similar debugging tools
11
+ return process._getActiveHandles().filter(h =>
12
+ h && h.constructor && h.constructor.name === 'Timeout'
13
+ ).length;
14
+ }
15
+
16
+ test('should properly clear timeout when process completes successfully', async () => {
17
+ const initialTimerCount = getActiveTimerCount();
18
+
19
+ // Simulate a simple command that completes quickly
20
+ const child = spawn('echo', ['test'], { shell: true });
21
+ let timeoutFired = false;
22
+
23
+ // Set a timeout (similar to backend implementation)
24
+ const timeoutId = setTimeout(() => {
25
+ timeoutFired = true;
26
+ if (!child.killed) {
27
+ child.kill('SIGTERM');
28
+ }
29
+ }, 5000); // 5 second timeout
30
+
31
+ await new Promise((resolve, reject) => {
32
+ child.on('close', (code) => {
33
+ clearTimeout(timeoutId); // This is what we added to fix the issue
34
+ resolve(code);
35
+ });
36
+
37
+ child.on('error', (error) => {
38
+ clearTimeout(timeoutId); // This is what we added to fix the issue
39
+ reject(error);
40
+ });
41
+ });
42
+
43
+ // Give event loop time to clean up
44
+ await delay(100);
45
+
46
+ // Verify timeout was cleared and didn't fire
47
+ assert.strictEqual(timeoutFired, false, 'Timeout should not have fired');
48
+
49
+ // Check that we don't have extra timers hanging around
50
+ const finalTimerCount = getActiveTimerCount();
51
+ assert.ok(
52
+ finalTimerCount <= initialTimerCount + 1, // Allow for test framework timers
53
+ `Timer leak detected: started with ${initialTimerCount} timers, ended with ${finalTimerCount}`
54
+ );
55
+ });
56
+
57
+ test('should properly clear timeout when process fails', async () => {
58
+ const initialTimerCount = getActiveTimerCount();
59
+
60
+ // Simulate a command that fails
61
+ const child = spawn('exit', ['1'], { shell: true });
62
+ let timeoutFired = false;
63
+
64
+ const timeoutId = setTimeout(() => {
65
+ timeoutFired = true;
66
+ if (!child.killed) {
67
+ child.kill('SIGTERM');
68
+ }
69
+ }, 5000);
70
+
71
+ const exitCode = await new Promise((resolve, reject) => {
72
+ child.on('close', (code) => {
73
+ clearTimeout(timeoutId);
74
+ resolve(code);
75
+ });
76
+
77
+ child.on('error', (error) => {
78
+ clearTimeout(timeoutId);
79
+ reject(error);
80
+ });
81
+ });
82
+
83
+ await delay(100);
84
+
85
+ assert.strictEqual(exitCode, 1, 'Process should have failed with exit code 1');
86
+ assert.strictEqual(timeoutFired, false, 'Timeout should not have fired');
87
+
88
+ const finalTimerCount = getActiveTimerCount();
89
+ assert.ok(
90
+ finalTimerCount <= initialTimerCount + 1,
91
+ `Timer leak detected: started with ${initialTimerCount} timers, ended with ${finalTimerCount}`
92
+ );
93
+ });
94
+
95
+ test('timeout should fire and kill process if it runs too long', async () => {
96
+ let timeoutFired = false;
97
+ let processKilled = false;
98
+
99
+ // Simulate a long-running command
100
+ const child = spawn('sleep', ['10'], { shell: true });
101
+
102
+ const timeoutId = setTimeout(() => {
103
+ timeoutFired = true;
104
+ if (!child.killed) {
105
+ processKilled = true;
106
+ child.kill('SIGTERM');
107
+ }
108
+ }, 100); // Very short timeout to ensure it fires
109
+
110
+ const exitCode = await new Promise((resolve) => {
111
+ child.on('close', (code) => {
112
+ clearTimeout(timeoutId);
113
+ resolve(code);
114
+ });
115
+
116
+ child.on('error', () => {
117
+ clearTimeout(timeoutId);
118
+ resolve(-1);
119
+ });
120
+ });
121
+
122
+ assert.strictEqual(timeoutFired, true, 'Timeout should have fired');
123
+ assert.strictEqual(processKilled, true, 'Process should have been killed');
124
+ assert.notStrictEqual(exitCode, 0, 'Process should not have completed successfully');
125
+ });
126
+
127
+ test('multiple executions should not accumulate timers', async () => {
128
+ const initialTimerCount = getActiveTimerCount();
129
+
130
+ // Run multiple quick commands
131
+ for (let i = 0; i < 5; i++) {
132
+ const child = spawn('echo', [`test${i}`], { shell: true });
133
+
134
+ const timeoutId = setTimeout(() => {
135
+ if (!child.killed) {
136
+ child.kill('SIGTERM');
137
+ }
138
+ }, 5000);
139
+
140
+ await new Promise((resolve, reject) => {
141
+ child.on('close', () => {
142
+ clearTimeout(timeoutId);
143
+ resolve();
144
+ });
145
+
146
+ child.on('error', (error) => {
147
+ clearTimeout(timeoutId);
148
+ reject(error);
149
+ });
150
+ });
151
+ }
152
+
153
+ await delay(100);
154
+
155
+ const finalTimerCount = getActiveTimerCount();
156
+ assert.ok(
157
+ finalTimerCount <= initialTimerCount + 2, // Allow some variance for test framework
158
+ `Timer accumulation detected: started with ${initialTimerCount} timers, ended with ${finalTimerCount} after 5 executions`
159
+ );
160
+ });
161
+ });