@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,767 @@
1
+ /**
2
+ * Claude Code SDK backend implementation
3
+ * @module ClaudeCodeBackend
4
+ */
5
+
6
+ import BaseBackend from './BaseBackend.js';
7
+ import { BackendError, ErrorTypes, ProgressTracker, FileChangeParser, TokenEstimator } from '../core/utils.js';
8
+ import { exec, spawn } from 'child_process';
9
+ import { promisify } from 'util';
10
+ import path from 'path';
11
+ import { TIMEOUTS, getDefaultTimeoutMs } from '../core/timeouts.js';
12
+
13
+ const execPromise = promisify(exec);
14
+
15
+ /**
16
+ * Claude Code SDK implementation backend
17
+ * @class
18
+ * @extends BaseBackend
19
+ */
20
+ class ClaudeCodeBackend extends BaseBackend {
21
+ constructor() {
22
+ super('claude-code', '1.0.0');
23
+ this.config = null;
24
+ }
25
+
26
+ /**
27
+ * @override
28
+ */
29
+ async initialize(config) {
30
+ this.config = {
31
+ apiKey: config.apiKey || process.env.ANTHROPIC_API_KEY,
32
+ model: config.model || 'claude-3-5-sonnet-20241022',
33
+ baseUrl: config.baseUrl,
34
+ timeout: config.timeout || getDefaultTimeoutMs(), // Use centralized default (20 minutes)
35
+ maxTokens: config.maxTokens || 8000,
36
+ temperature: config.temperature || 0.3,
37
+ systemPrompt: config.systemPrompt,
38
+ tools: config.tools || ['edit', 'search', 'bash'],
39
+ maxTurns: config.maxTurns || 100,
40
+ ...config
41
+ };
42
+
43
+ try {
44
+ // Claude Code backend only uses CLI interface
45
+ this.log('debug', 'Using Claude Code CLI interface');
46
+
47
+ // Validate configuration
48
+ await this.validateConfiguration();
49
+
50
+ // Test connection/availability
51
+ const available = await this.isAvailable();
52
+ if (!available) {
53
+ throw new Error('Claude Code is not available');
54
+ }
55
+
56
+ this.initialized = true;
57
+
58
+ } catch (error) {
59
+ throw new BackendError(
60
+ `Failed to initialize Claude Code backend: ${error.message}`,
61
+ ErrorTypes.INITIALIZATION_FAILED,
62
+ 'CLAUDE_CODE_INIT_FAILED',
63
+ { originalError: error }
64
+ );
65
+ }
66
+ }
67
+
68
+ /**
69
+ * @override
70
+ */
71
+ async isAvailable() {
72
+ if (!this.config.apiKey) {
73
+ this.log('warn', 'No API key configured');
74
+ return false;
75
+ }
76
+
77
+ try {
78
+ let claudeCommand = null;
79
+
80
+ // Method 1: Try direct execution with claude --version
81
+ try {
82
+ await execPromise('claude --version', { timeout: TIMEOUTS.VERSION_CHECK });
83
+ claudeCommand = 'claude';
84
+ this.log('debug', 'Claude found in PATH via direct execution');
85
+ } catch (directError) {
86
+ this.log('debug', 'Claude not directly executable from PATH', { error: directError.message });
87
+ }
88
+
89
+ // Method 2: Check npm global installation and find the binary
90
+ if (!claudeCommand) {
91
+ try {
92
+ const { stdout } = await execPromise('npm list -g @anthropic-ai/claude-code --depth=0', { timeout: TIMEOUTS.VERSION_CHECK });
93
+ if (stdout.includes('@anthropic-ai/claude-code')) {
94
+ // Get npm global bin directory
95
+ const { stdout: binPath } = await execPromise('npm bin -g', { timeout: TIMEOUTS.VERSION_CHECK });
96
+ const npmBinDir = binPath.trim();
97
+
98
+ // Build the claude command path
99
+ const isWindows = process.platform === 'win32';
100
+ const claudeBinary = isWindows ? 'claude.cmd' : 'claude';
101
+ const claudePath = path.join(npmBinDir, claudeBinary);
102
+
103
+ // Test if we can execute it
104
+ try {
105
+ await execPromise(`"${claudePath}" --version`, { timeout: TIMEOUTS.VERSION_CHECK });
106
+ claudeCommand = claudePath;
107
+
108
+ // Update PATH for this process to include npm global bin
109
+ const pathSeparator = isWindows ? ';' : ':';
110
+ process.env.PATH = `${npmBinDir}${pathSeparator}${process.env.PATH}`;
111
+
112
+ this.log('debug', `Claude found at ${claudePath}, added ${npmBinDir} to PATH`);
113
+ } catch (execError) {
114
+ this.log('debug', `Failed to execute claude at ${claudePath}`, { error: execError.message });
115
+ }
116
+ }
117
+ } catch (npmError) {
118
+ this.log('debug', 'Failed to check npm global packages', { error: npmError.message });
119
+ }
120
+ }
121
+
122
+ // Method 3: Try WSL on Windows
123
+ if (!claudeCommand && process.platform === 'win32') {
124
+ try {
125
+ // Check if WSL is available and claude is installed there
126
+ const { stdout: wslCheck } = await execPromise('wsl --list', { timeout: TIMEOUTS.WSL_CHECK });
127
+ if (wslCheck) {
128
+ this.log('debug', 'WSL detected, checking for claude in WSL');
129
+ try {
130
+ // Try to run claude through WSL
131
+ await execPromise('wsl claude --version', { timeout: TIMEOUTS.VERSION_CHECK });
132
+ claudeCommand = 'wsl claude';
133
+ this.log('debug', 'Claude found in WSL');
134
+ } catch (wslClaudeError) {
135
+ this.log('debug', 'Claude not found in WSL', { error: wslClaudeError.message });
136
+
137
+ // Try common WSL paths
138
+ const wslPaths = [
139
+ 'wsl /usr/local/bin/claude',
140
+ 'wsl ~/.npm-global/bin/claude',
141
+ 'wsl ~/.local/bin/claude',
142
+ 'wsl ~/node_modules/.bin/claude'
143
+ ];
144
+
145
+ for (const wslPath of wslPaths) {
146
+ try {
147
+ await execPromise(`${wslPath} --version`, { timeout: TIMEOUTS.WSL_CHECK });
148
+ claudeCommand = wslPath;
149
+ this.log('debug', `Claude found in WSL at: ${wslPath}`);
150
+ break;
151
+ } catch (e) {
152
+ // Continue searching
153
+ }
154
+ }
155
+ }
156
+ }
157
+ } catch (wslError) {
158
+ this.log('debug', 'WSL not available or accessible', { error: wslError.message });
159
+ }
160
+ }
161
+
162
+ // Method 4: Try to find claude in common locations
163
+ if (!claudeCommand) {
164
+ const isWindows = process.platform === 'win32';
165
+ const homeDir = process.env[isWindows ? 'USERPROFILE' : 'HOME'];
166
+ const claudeBinary = isWindows ? 'claude.cmd' : 'claude';
167
+
168
+ // Common npm global locations
169
+ const commonPaths = [
170
+ // Windows paths
171
+ isWindows && path.join(process.env.APPDATA || '', 'npm', claudeBinary),
172
+ isWindows && path.join('C:', 'Program Files', 'nodejs', claudeBinary),
173
+ // Unix-like paths
174
+ !isWindows && path.join('/usr/local/bin', claudeBinary),
175
+ !isWindows && path.join(homeDir, '.npm-global', 'bin', claudeBinary),
176
+ !isWindows && path.join(homeDir, '.local', 'bin', claudeBinary),
177
+ // Cross-platform home directory paths
178
+ path.join(homeDir, 'node_modules', '.bin', claudeBinary),
179
+ ].filter(Boolean);
180
+
181
+ for (const claudePath of commonPaths) {
182
+ try {
183
+ await execPromise(`"${claudePath}" --version`, { timeout: TIMEOUTS.WSL_CHECK });
184
+ claudeCommand = claudePath;
185
+ this.log('debug', `Claude found at ${claudePath}`);
186
+ break;
187
+ } catch (e) {
188
+ // Continue searching
189
+ }
190
+ }
191
+ }
192
+
193
+ if (!claudeCommand) {
194
+ this.log('warn', 'Claude Code CLI not found. Please install with: npm install -g @anthropic-ai/claude-code (or in WSL on Windows)');
195
+ return false;
196
+ }
197
+
198
+ // Store the command for later use
199
+ this.claudeCommand = claudeCommand;
200
+
201
+ // Just verify the API key exists (non-empty)
202
+ // Don't validate format as it can vary
203
+ if (!this.config.apiKey || this.config.apiKey.trim() === '') {
204
+ this.log('warn', 'API key is not configured');
205
+ return false;
206
+ }
207
+
208
+ return true;
209
+ } catch (error) {
210
+ this.log('debug', 'Availability check failed', { error: error.message });
211
+ return false;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * @override
217
+ */
218
+ getRequiredDependencies() {
219
+ return [
220
+ {
221
+ name: 'claude-code',
222
+ type: 'cli',
223
+ installCommand: 'npm install -g @anthropic-ai/claude-code',
224
+ description: 'Claude Code CLI tool'
225
+ },
226
+ {
227
+ name: 'ANTHROPIC_API_KEY',
228
+ type: 'environment',
229
+ description: 'Anthropic API key for Claude Code'
230
+ }
231
+ ];
232
+ }
233
+
234
+ /**
235
+ * @override
236
+ */
237
+ getCapabilities() {
238
+ return {
239
+ supportsLanguages: ['javascript', 'typescript', 'python', 'rust', 'go', 'java', 'c++', 'c#', 'ruby', 'php', 'swift'],
240
+ supportsStreaming: true,
241
+ supportsRollback: false,
242
+ supportsDirectFileEdit: true,
243
+ supportsPlanGeneration: true,
244
+ supportsTestGeneration: true,
245
+ maxConcurrentSessions: 5
246
+ };
247
+ }
248
+
249
+ /**
250
+ * @override
251
+ */
252
+ getDescription() {
253
+ return 'Claude Code CLI - Advanced AI coding assistant powered by Claude';
254
+ }
255
+
256
+ /**
257
+ * @override
258
+ */
259
+ async execute(request) {
260
+ this.checkInitialized();
261
+
262
+ const validation = this.validateRequest(request);
263
+ if (!validation.valid) {
264
+ throw new BackendError(
265
+ `Invalid request: ${validation.errors.join(', ')}`,
266
+ ErrorTypes.VALIDATION_ERROR,
267
+ 'INVALID_REQUEST'
268
+ );
269
+ }
270
+
271
+ const sessionInfo = this.createSessionInfo(request.sessionId);
272
+ const progressTracker = new ProgressTracker(request.sessionId, request.callbacks?.onProgress);
273
+
274
+ this.activeSessions.set(request.sessionId, sessionInfo);
275
+
276
+ try {
277
+ progressTracker.startStep('prepare', 'Preparing Claude Code execution');
278
+
279
+ // Build the prompt
280
+ const prompt = this.buildPrompt(request);
281
+ const workingDir = request.context?.workingDirectory || process.cwd();
282
+
283
+ this.updateSessionStatus(request.sessionId, {
284
+ status: 'running',
285
+ progress: 25,
286
+ message: 'Claude Code is processing your request'
287
+ });
288
+
289
+ progressTracker.endStep();
290
+ progressTracker.startStep('execute', 'Executing with Claude Code');
291
+
292
+ // Always use CLI interface
293
+ const result = await this.executeWithCLI(prompt, workingDir, request, sessionInfo, progressTracker);
294
+
295
+ progressTracker.endStep();
296
+
297
+ this.updateSessionStatus(request.sessionId, {
298
+ status: 'completed',
299
+ progress: 100,
300
+ message: 'Implementation completed successfully'
301
+ });
302
+
303
+ return result;
304
+
305
+ } catch (error) {
306
+ this.updateSessionStatus(request.sessionId, {
307
+ status: 'failed',
308
+ message: error.message
309
+ });
310
+
311
+ if (error instanceof BackendError) {
312
+ throw error;
313
+ }
314
+
315
+ throw new BackendError(
316
+ `Claude Code execution failed: ${error.message}`,
317
+ ErrorTypes.EXECUTION_FAILED,
318
+ 'CLAUDE_CODE_EXECUTION_FAILED',
319
+ { originalError: error, sessionId: request.sessionId }
320
+ );
321
+ } finally {
322
+ this.activeSessions.delete(request.sessionId);
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Validate configuration
328
+ * @private
329
+ */
330
+ async validateConfiguration() {
331
+ if (!this.config.apiKey) {
332
+ throw new Error('API key is required. Set ANTHROPIC_API_KEY environment variable or provide apiKey in config');
333
+ }
334
+
335
+ // No format validation - API key formats can vary
336
+ // Model validation removed - model names change frequently
337
+
338
+ // Tools validation not needed since we always use --dangerously-skip-permissions
339
+ }
340
+
341
+ /**
342
+ * Build prompt for Claude Code
343
+ * @param {import('../types/BackendTypes').ImplementRequest} request - Implementation request
344
+ * @returns {string} Formatted prompt
345
+ * @private
346
+ */
347
+ buildPrompt(request) {
348
+ let prompt = '';
349
+
350
+ // Add context if provided
351
+ if (request.context?.additionalContext) {
352
+ prompt += `Context:\n${request.context.additionalContext}\n\n`;
353
+ }
354
+
355
+ // Add main task
356
+ prompt += `Task:\n${request.task}\n`;
357
+
358
+ // Add constraints
359
+ if (request.context?.allowedFiles && request.context.allowedFiles.length > 0) {
360
+ prompt += `\nOnly modify these files: ${request.context.allowedFiles.join(', ')}\n`;
361
+ }
362
+
363
+ if (request.context?.language) {
364
+ prompt += `\nPrimary language: ${request.context.language}\n`;
365
+ }
366
+
367
+ // Add options
368
+ if (request.options?.generateTests) {
369
+ prompt += '\nAlso generate appropriate tests for the implemented functionality.\n';
370
+ }
371
+
372
+ if (request.options?.dryRun) {
373
+ prompt += '\nThis is a dry run - describe what changes would be made without actually implementing them.\n';
374
+ }
375
+
376
+ return prompt.trim();
377
+ }
378
+
379
+ /**
380
+ * Build system prompt for Claude Code
381
+ * @param {import('../types/BackendTypes').ImplementRequest} request - Implementation request
382
+ * @returns {string} System prompt
383
+ * @private
384
+ */
385
+ buildSystemPrompt(request) {
386
+ if (this.config.systemPrompt) {
387
+ return this.config.systemPrompt;
388
+ }
389
+
390
+ return `You are an expert software developer assistant using Claude Code. Your task is to implement code changes based on user requirements.
391
+
392
+ Key guidelines:
393
+ - Follow best practices for the detected programming language
394
+ - Write clean, maintainable, and well-documented code
395
+ - Include error handling where appropriate
396
+ - Consider edge cases and potential issues
397
+ - Generate tests when requested or when it would be beneficial
398
+ - Make minimal, focused changes that achieve the requested functionality
399
+ - Preserve existing code style and conventions
400
+
401
+ Working directory: ${request.context?.workingDirectory || process.cwd()}
402
+ ${request.context?.allowedFiles ? `Allowed files: ${request.context.allowedFiles.join(', ')}` : ''}
403
+ ${request.context?.language ? `Primary language: ${request.context.language}` : ''}`;
404
+ }
405
+
406
+
407
+ /**
408
+ * Execute using CLI interface
409
+ * @private
410
+ */
411
+ async executeWithCLI(prompt, workingDir, request, sessionInfo, progressTracker) {
412
+ const startTime = Date.now();
413
+
414
+ // Build Claude Code CLI arguments securely
415
+ const args = this.buildSecureCommandArgs(request);
416
+
417
+ // Add the prompt using -p flag (multiline strings are handled safely by spawn)
418
+ const validatedPrompt = this.validatePrompt(prompt);
419
+ args.unshift('-p', validatedPrompt);
420
+
421
+ this.log('debug', 'Executing Claude Code CLI', {
422
+ command: 'claude',
423
+ args: args.slice(0, 5), // Log first few args only for security
424
+ workingDir
425
+ });
426
+
427
+ // Always log command info to stderr for debugging (visible in all modes)
428
+ console.error(`[INFO] Claude Code execution details:`);
429
+ console.error(`[INFO] Working directory: ${workingDir}`);
430
+ console.error(`[INFO] Environment: ANTHROPIC_API_KEY=${this.config.apiKey ? '***set***' : '***not set***'}`);
431
+ console.error(`[INFO] Prompt length: ${validatedPrompt.length} characters`);
432
+
433
+ return new Promise(async (resolve, reject) => {
434
+ // Use spawn instead of exec for better security
435
+ // Use the command we found during isAvailable() check
436
+ let claudeCommand = this.claudeCommand || 'claude';
437
+
438
+ // If we don't have a stored command, try to find it again
439
+ if (!this.claudeCommand) {
440
+ try {
441
+ // Try direct execution first
442
+ await execPromise('claude --version', { timeout: TIMEOUTS.PATH_CHECK });
443
+ claudeCommand = 'claude';
444
+ } catch (e) {
445
+ const isWindows = process.platform === 'win32';
446
+
447
+ // Try WSL on Windows
448
+ if (isWindows) {
449
+ try {
450
+ await execPromise('wsl claude --version', { timeout: TIMEOUTS.WSL_CHECK });
451
+ claudeCommand = 'wsl claude';
452
+ this.log('debug', 'Using claude from WSL');
453
+ } catch (wslError) {
454
+ // Continue to npm global check
455
+ }
456
+ }
457
+
458
+ // Try to find it in npm global bin
459
+ if (claudeCommand === 'claude') {
460
+ try {
461
+ const { stdout: binPath } = await execPromise('npm bin -g', { timeout: TIMEOUTS.PATH_CHECK });
462
+ const claudeBinary = isWindows ? 'claude.cmd' : 'claude';
463
+ const potentialClaudePath = path.join(binPath.trim(), claudeBinary);
464
+
465
+ // Test if we can execute it
466
+ await execPromise(`"${potentialClaudePath}" --version`, { timeout: TIMEOUTS.PATH_CHECK });
467
+ claudeCommand = potentialClaudePath;
468
+ this.log('debug', `Using claude from npm global: ${claudeCommand}`);
469
+ } catch (npmError) {
470
+ // Fall back to 'claude' and let it fail with a clear error
471
+ this.log('warn', 'Could not find claude in npm global bin or WSL, attempting direct execution');
472
+ }
473
+ }
474
+ }
475
+ }
476
+
477
+ // Special handling for WSL commands
478
+ let spawnCommand = claudeCommand;
479
+ let spawnArgs = args;
480
+
481
+ if (claudeCommand.startsWith('wsl ')) {
482
+ // Split WSL command properly
483
+ const wslParts = claudeCommand.split(' ');
484
+ spawnCommand = wslParts[0]; // 'wsl'
485
+ spawnArgs = [...wslParts.slice(1), ...args]; // claude path + original args
486
+ }
487
+
488
+ // Log the exact spawn command to stderr (always visible)
489
+ console.error(`[INFO] Executing command: ${spawnCommand} ${spawnArgs.join(' ')}`);
490
+ console.error(`[INFO] Shell mode: ${process.platform === 'win32'}`);
491
+
492
+ const child = spawn(spawnCommand, spawnArgs, {
493
+ cwd: workingDir,
494
+ env: this.buildSecureEnvironment(),
495
+ stdio: ['pipe', 'pipe', 'pipe'],
496
+ shell: process.platform === 'win32' // Use shell on Windows for .cmd files
497
+ });
498
+
499
+ sessionInfo.childProcess = child;
500
+ sessionInfo.cancel = () => {
501
+ if (child && !child.killed) {
502
+ child.kill('SIGTERM');
503
+ }
504
+ };
505
+
506
+ let output = '';
507
+ let errorOutput = '';
508
+
509
+ // No need to send prompt to stdin - it's passed via -p argument
510
+ if (child.stdin) {
511
+ child.stdin.end();
512
+ }
513
+
514
+ // Handle stdout
515
+ if (child.stdout) {
516
+ child.stdout.on('data', (data) => {
517
+ const chunk = data.toString();
518
+ output += chunk;
519
+
520
+ // Stream to stderr for visibility
521
+ process.stderr.write(chunk);
522
+
523
+ // Report progress
524
+ progressTracker.reportMessage(chunk.trim(), 'stdout');
525
+ });
526
+ }
527
+
528
+ // Handle stderr
529
+ if (child.stderr) {
530
+ child.stderr.on('data', (data) => {
531
+ const chunk = data.toString();
532
+ errorOutput += chunk;
533
+
534
+ // Stream to stderr
535
+ process.stderr.write(chunk);
536
+
537
+ // Check for errors
538
+ if (chunk.toLowerCase().includes('error')) {
539
+ progressTracker.reportMessage(chunk.trim(), 'stderr');
540
+ }
541
+ });
542
+ }
543
+
544
+ // Handle completion
545
+ child.on('close', (code) => {
546
+ const executionTime = Date.now() - startTime;
547
+
548
+ // Clear timeout
549
+ clearTimeout(timeoutId);
550
+
551
+ if (code === 0) {
552
+ // Parse changes from output
553
+ const changes = FileChangeParser.parseChanges(output, workingDir);
554
+
555
+ resolve({
556
+ success: true,
557
+ sessionId: request.sessionId,
558
+ output,
559
+ changes,
560
+ metrics: {
561
+ executionTime,
562
+ tokensUsed: TokenEstimator.estimate(prompt + output),
563
+ filesModified: changes.length,
564
+ linesChanged: 0,
565
+ exitCode: code
566
+ },
567
+ metadata: {
568
+ command: 'claude',
569
+ args: args.slice(0, 5), // Limited args for security
570
+ model: this.config.model
571
+ }
572
+ });
573
+ } else {
574
+ // Log full error details to stderr
575
+ console.error(`[ERROR] Claude Code CLI failed with exit code: ${code}`);
576
+ console.error(`[ERROR] Full command: ${claudeCommand} ${args.join(' ')}`);
577
+ console.error(`[ERROR] Working directory: ${workingDir}`);
578
+ console.error(`[ERROR] Full stdout output:`);
579
+ console.error(output || '(no stdout)');
580
+ console.error(`[ERROR] Full stderr output:`);
581
+ console.error(errorOutput || '(no stderr)');
582
+ console.error(`[ERROR] Execution time: ${Date.now() - startTime}ms`);
583
+
584
+ reject(new BackendError(
585
+ `Claude Code CLI exited with code ${code}`,
586
+ ErrorTypes.EXECUTION_FAILED,
587
+ 'CLI_EXECUTION_FAILED',
588
+ {
589
+ exitCode: code,
590
+ stdout: output.substring(0, 1000),
591
+ stderr: errorOutput.substring(0, 1000)
592
+ }
593
+ ));
594
+ }
595
+ });
596
+
597
+ // Handle errors
598
+ child.on('error', (error) => {
599
+ // Clear timeout
600
+ clearTimeout(timeoutId);
601
+
602
+ // Log full error details to stderr
603
+ console.error(`[ERROR] Failed to spawn Claude Code CLI process:`);
604
+ console.error(`[ERROR] Command: ${spawnCommand}`);
605
+ console.error(`[ERROR] Args: ${spawnArgs.join(' ')}`);
606
+ console.error(`[ERROR] Working directory: ${workingDir}`);
607
+ console.error(`[ERROR] Error message: ${error.message}`);
608
+ console.error(`[ERROR] Error code: ${error.code || 'unknown'}`);
609
+ console.error(`[ERROR] Error signal: ${error.signal || 'none'}`);
610
+ console.error(`[ERROR] Full error:`, error);
611
+
612
+ reject(new BackendError(
613
+ `Failed to execute Claude Code CLI: ${error.message}`,
614
+ ErrorTypes.EXECUTION_FAILED,
615
+ 'CLI_SPAWN_FAILED',
616
+ { originalError: error }
617
+ ));
618
+ });
619
+
620
+ // Set timeout
621
+ const timeout = request.options?.timeout || this.config.timeout;
622
+ const timeoutId = setTimeout(() => {
623
+ if (!child.killed) {
624
+ // Log timeout details to stderr
625
+ console.error(`[ERROR] Claude Code CLI timed out after ${timeout}ms`);
626
+ console.error(`[ERROR] Command: ${spawnCommand} ${spawnArgs.join(' ')}`);
627
+ console.error(`[ERROR] Working directory: ${workingDir}`);
628
+ console.error(`[ERROR] Partial stdout output:`);
629
+ console.error(output || '(no stdout)');
630
+ console.error(`[ERROR] Partial stderr output:`);
631
+ console.error(errorOutput || '(no stderr)');
632
+
633
+ child.kill('SIGTERM');
634
+ reject(new BackendError(
635
+ `Claude Code execution timed out after ${timeout}ms`,
636
+ ErrorTypes.TIMEOUT,
637
+ 'CLAUDE_CODE_TIMEOUT',
638
+ { timeout }
639
+ ));
640
+ }
641
+ }, timeout);
642
+ });
643
+ }
644
+
645
+
646
+ /**
647
+ * Build secure command arguments
648
+ * @param {import('../types/BackendTypes').ImplementRequest} request - Implementation request
649
+ * @returns {Array<string>} Secure command arguments
650
+ * @private
651
+ */
652
+ buildSecureCommandArgs(request) {
653
+ const args = [];
654
+
655
+ // Add max turns with validation
656
+ const maxTurns = this.validateMaxTurns(request.options?.maxTurns || this.config.maxTurns);
657
+ if (process.env.DEBUG) {
658
+ this.log('debug', 'Max turns check', {
659
+ requestMaxTurns: request.options?.maxTurns,
660
+ configMaxTurns: this.config.maxTurns,
661
+ validatedMaxTurns: maxTurns
662
+ });
663
+ }
664
+ args.push('--max-turns', maxTurns.toString());
665
+
666
+ // Model and temperature are not supported by Claude CLI
667
+ // Claude CLI uses default model and temperature settings
668
+
669
+ // Always use --dangerously-skip-permissions to avoid tool permission complexity
670
+ args.push('--dangerously-skip-permissions');
671
+
672
+ if (process.env.DEBUG) {
673
+ this.log('debug', 'Final args constructed', { args });
674
+ }
675
+ return args;
676
+ }
677
+
678
+ /**
679
+ * Build secure environment variables
680
+ * @returns {Object} Secure environment variables
681
+ * @private
682
+ */
683
+ buildSecureEnvironment() {
684
+ const env = { ...process.env };
685
+
686
+ if (this.config.apiKey && this.isValidApiKey(this.config.apiKey)) {
687
+ env.ANTHROPIC_API_KEY = this.config.apiKey;
688
+ }
689
+
690
+ return env;
691
+ }
692
+
693
+ /**
694
+ * Validate API key format
695
+ * @param {string} apiKey - API key to validate
696
+ * @returns {boolean} True if valid format
697
+ * @private
698
+ */
699
+ isValidApiKey(apiKey) {
700
+ // Just check if it's a non-empty string
701
+ // API key formats can vary between providers and versions
702
+ return apiKey && typeof apiKey === 'string' && apiKey.trim().length > 0;
703
+ }
704
+
705
+
706
+ /**
707
+ * Validate max turns value
708
+ * @param {number} maxTurns - Max turns to validate
709
+ * @returns {number} Validated max turns value
710
+ * @private
711
+ */
712
+ validateMaxTurns(maxTurns) {
713
+ if (typeof maxTurns !== 'number' || isNaN(maxTurns) || maxTurns < 1) {
714
+ return 100; // Default value
715
+ }
716
+
717
+ return Math.min(Math.max(Math.floor(maxTurns), 1), 1000); // Clamp between 1 and 1000
718
+ }
719
+
720
+
721
+ /**
722
+ * Validate prompt content
723
+ * @param {string} prompt - Prompt to validate
724
+ * @returns {string} Validated prompt
725
+ * @private
726
+ */
727
+ validatePrompt(prompt) {
728
+ if (!prompt || typeof prompt !== 'string') {
729
+ throw new BackendError(
730
+ 'Invalid prompt content',
731
+ ErrorTypes.VALIDATION_ERROR,
732
+ 'INVALID_PROMPT'
733
+ );
734
+ }
735
+
736
+ const maxPromptLength = 100000; // 100KB limit for prompts
737
+
738
+ if (prompt.length > maxPromptLength) {
739
+ throw new BackendError(
740
+ `Prompt too long (${prompt.length} chars, max: ${maxPromptLength})`,
741
+ ErrorTypes.VALIDATION_ERROR,
742
+ 'PROMPT_TOO_LONG'
743
+ );
744
+ }
745
+
746
+ // Check for control characters that could cause issues
747
+ if (this.containsControlCharacters(prompt)) {
748
+ this.log('warn', 'Prompt contains control characters, they will be filtered');
749
+ return prompt.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, ''); // Remove most control chars but keep newlines/tabs
750
+ }
751
+
752
+ return prompt;
753
+ }
754
+
755
+ /**
756
+ * Check if string contains problematic control characters
757
+ * @param {string} str - String to check
758
+ * @returns {boolean} True if contains control characters
759
+ * @private
760
+ */
761
+ containsControlCharacters(str) {
762
+ // Check for control characters excluding newlines and tabs
763
+ return /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(str);
764
+ }
765
+ }
766
+
767
+ export default ClaudeCodeBackend;