@crownpeak/dqm-react-component-dev-mcp 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. package/src/index.js +395 -0
@@ -0,0 +1,669 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Check for non-interactive mode flag early, before any imports
4
+ // This ensures the environment variable is set before any module code runs
5
+ if (process.argv.includes('-m') || process.argv.includes('--message')) {
6
+ process.env.PROBE_NON_INTERACTIVE = '1';
7
+ }
8
+
9
+ // Check if stdin is connected to a pipe (not a TTY)
10
+ // This allows for usage like: echo "query" | probe-chat
11
+ if (!process.stdin.isTTY) {
12
+ process.env.PROBE_NON_INTERACTIVE = '1';
13
+ process.env.PROBE_STDIN_PIPED = '1';
14
+ }
15
+
16
+ import 'dotenv/config';
17
+ import inquirer from 'inquirer';
18
+ import chalk from 'chalk';
19
+ import ora from 'ora';
20
+ import { Command } from 'commander';
21
+ import { existsSync, realpathSync, readFileSync } from 'fs';
22
+ import { resolve, dirname, join } from 'path';
23
+ import { fileURLToPath } from 'url';
24
+ import { randomUUID } from 'crypto';
25
+ import { ProbeChat } from './probeChat.js';
26
+ import { TokenUsageDisplay } from './tokenUsageDisplay.js';
27
+ import { DEFAULT_SYSTEM_MESSAGE } from '@probelabs/probe';
28
+
29
+ /**
30
+ * Main function that runs the Probe Chat CLI or web interface
31
+ */
32
+ export function main() {
33
+ // Get the directory name of the current module
34
+ const __dirname = dirname(fileURLToPath(import.meta.url));
35
+ const packageJsonPath = join(__dirname, 'package.json');
36
+
37
+ // Read package.json to get the version
38
+ let version = '1.0.0'; // Default fallback version
39
+ try {
40
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
41
+ version = packageJson.version || version;
42
+ } catch (error) {
43
+ // Non-critical, suppress in non-interactive unless debug
44
+ // console.warn(`Warning: Could not read version from package.json: ${error.message}`);
45
+ }
46
+
47
+ // Create a new instance of the program
48
+ const program = new Command();
49
+
50
+ program
51
+ .name('probe-chat')
52
+ .description('CLI chat interface for Probe code search')
53
+ .version(version)
54
+ .option('-d, --debug', 'Enable debug mode')
55
+ .option('--model-name <model>', 'Specify the model to use') // Renamed from --model
56
+ .option('-f, --force-provider <provider>', 'Force a specific provider (options: anthropic, openai, google)')
57
+ .option('-w, --web', 'Run in web interface mode')
58
+ .option('-p, --port <port>', 'Port to run web server on (default: 8080)')
59
+ .option('-m, --message <message>', 'Send a single message and exit (non-interactive mode)')
60
+ .option('-s, --session-id <sessionId>', 'Specify a session ID for the chat (optional)')
61
+ .option('--images <urls>', 'Comma-separated list of image URLs to include in the message')
62
+ .option('--json', 'Output the response as JSON in non-interactive mode')
63
+ .option('--max-iterations <number>', 'Maximum number of tool iterations allowed (default: 30)')
64
+ .option('--prompt <value>', 'Use a custom prompt (values: architect, code-review, code-review-template, support, path to a file, or arbitrary string)')
65
+ .option('--allow-edit', 'Enable the implement tool for editing files')
66
+ .option('--implement-tool-backend <backend>', 'Choose implementation tool backend (aider, claude-code)')
67
+ .option('--implement-tool-timeout <ms>', 'Implementation tool timeout in milliseconds')
68
+ .option('--implement-tool-config <path>', 'Path to implementation tool configuration file')
69
+ .option('--implement-tool-list-backends', 'List available implementation tool backends')
70
+ .option('--implement-tool-backend-info <backend>', 'Show information about a specific implementation tool backend')
71
+ .option('--enable-bash', 'Enable bash command execution for system exploration')
72
+ .option('--bash-allow <patterns>', 'Additional bash command patterns to allow (comma-separated)')
73
+ .option('--bash-deny <patterns>', 'Additional bash command patterns to deny (comma-separated)')
74
+ .option('--no-default-bash-allow', 'Disable default bash allow list (use only custom patterns)')
75
+ .option('--no-default-bash-deny', 'Disable default bash deny list (use only custom patterns)')
76
+ .option('--bash-timeout <ms>', 'Bash command timeout in milliseconds (default: 120000)')
77
+ .option('--bash-working-dir <path>', 'Default working directory for bash commands')
78
+ .option('--trace-file [path]', 'Enable tracing to file (default: ./traces.jsonl)')
79
+ .option('--trace-remote [endpoint]', 'Enable tracing to remote endpoint (default: http://localhost:4318/v1/traces)')
80
+ .option('--trace-console', 'Enable tracing to console (for debugging)')
81
+ .option('--completion-prompt <prompt>', 'Custom prompt to run after attempt_completion for validation/review (can be a string or path to a file)')
82
+ .argument('[path]', 'Path to the codebase to search (overrides ALLOWED_FOLDERS)')
83
+ .parse(process.argv);
84
+
85
+ const options = program.opts();
86
+ const pathArg = program.args[0];
87
+
88
+ // Parse image URLs if provided
89
+ let imageUrls = [];
90
+ if (options.images) {
91
+ imageUrls = options.images.split(',').map(url => url.trim()).filter(url => url.length > 0);
92
+ console.log(`Using ${imageUrls.length} image(s):`, imageUrls);
93
+ }
94
+
95
+ // --- Logging Configuration ---
96
+ const isPipedInput = process.env.PROBE_STDIN_PIPED === '1';
97
+ const isNonInteractive = !!options.message || isPipedInput;
98
+
99
+ // Environment variable is already set at the top of the file
100
+ // This is just for code clarity
101
+ if (isNonInteractive && process.env.PROBE_NON_INTERACTIVE !== '1') {
102
+ process.env.PROBE_NON_INTERACTIVE = '1';
103
+ }
104
+
105
+ // Raw logging for non-interactive output
106
+ const rawLog = (...args) => console.log(...args);
107
+ const rawError = (...args) => console.error(...args);
108
+
109
+ // Disable color/formatting in raw non-interactive mode
110
+ if (isNonInteractive && !options.json && !options.debug) {
111
+ chalk.level = 0;
112
+ }
113
+
114
+ // Conditional logging helpers
115
+ const logInfo = (...args) => {
116
+ if (!isNonInteractive || options.debug) {
117
+ console.log(...args);
118
+ }
119
+ };
120
+ const logWarn = (...args) => {
121
+ if (!isNonInteractive || options.debug) {
122
+ console.warn(...args);
123
+ } else if (isNonInteractive) {
124
+ // Optionally log warnings to stderr in non-interactive mode even without debug
125
+ // rawError('Warning:', ...args);
126
+ }
127
+ };
128
+ const logError = (...args) => {
129
+ // Always log errors, but use rawError in non-interactive mode
130
+ if (isNonInteractive) {
131
+ rawError('Error:', ...args); // Prefix with Error: for clarity on stderr
132
+ } else {
133
+ console.error(...args);
134
+ }
135
+ };
136
+ // --- End Logging Configuration ---
137
+
138
+ if (options.debug) {
139
+ process.env.DEBUG_CHAT = '1';
140
+ logInfo(chalk.yellow('Debug mode enabled'));
141
+ }
142
+ if (options.modelName) { // Use renamed option
143
+ process.env.MODEL_NAME = options.modelName;
144
+ logInfo(chalk.blue(`Using model: ${options.modelName}`));
145
+ }
146
+ if (options.forceProvider) {
147
+ const provider = options.forceProvider.toLowerCase();
148
+ if (!['anthropic', 'openai', 'google'].includes(provider)) {
149
+ logError(chalk.red(`Invalid provider "${provider}". Must be one of: anthropic, openai, google`));
150
+ process.exit(1);
151
+ }
152
+ process.env.FORCE_PROVIDER = provider;
153
+ logInfo(chalk.blue(`Forcing provider: ${provider}`));
154
+ }
155
+
156
+ // Set MAX_TOOL_ITERATIONS from command line if provided
157
+ if (options.maxIterations) {
158
+ const maxIterations = parseInt(options.maxIterations, 10);
159
+ if (isNaN(maxIterations) || maxIterations <= 0) {
160
+ logError(chalk.red(`Invalid max iterations value: ${options.maxIterations}. Must be a positive number.`));
161
+ process.exit(1);
162
+ }
163
+ process.env.MAX_TOOL_ITERATIONS = maxIterations.toString();
164
+ logInfo(chalk.blue(`Setting maximum tool iterations to: ${maxIterations}`));
165
+ }
166
+
167
+ // Handle --implement-tool-list-backends option
168
+ if (options.implementToolListBackends) {
169
+ (async () => {
170
+ const { listBackendNames, getBackendMetadata } = await import('./implement/backends/registry.js');
171
+ const backends = listBackendNames();
172
+
173
+ console.log('\nAvailable implementation tool backends:');
174
+ for (const backend of backends) {
175
+ const metadata = getBackendMetadata(backend);
176
+ console.log(`\n ${chalk.bold(backend)} - ${metadata.description}`);
177
+ console.log(` Version: ${metadata.version}`);
178
+ console.log(` Languages: ${metadata.capabilities.supportsLanguages.join(', ')}`);
179
+ }
180
+ process.exit(0);
181
+ })();
182
+ }
183
+
184
+ // Handle --implement-tool-backend-info option
185
+ if (options.implementToolBackendInfo) {
186
+ (async () => {
187
+ const { getBackendMetadata } = await import('./implement/backends/registry.js');
188
+ const metadata = getBackendMetadata(options.implementToolBackendInfo);
189
+
190
+ if (!metadata) {
191
+ console.error(`Backend '${options.implementToolBackendInfo}' not found`);
192
+ process.exit(1);
193
+ }
194
+
195
+ console.log(`\n${chalk.bold('Backend Information: ' + options.implementToolBackendInfo)}`);
196
+ console.log(`\nDescription: ${metadata.description}`);
197
+ console.log(`Version: ${metadata.version}`);
198
+ console.log(`\nCapabilities:`);
199
+ console.log(` Languages: ${metadata.capabilities.supportsLanguages.join(', ')}`);
200
+ console.log(` Streaming: ${metadata.capabilities.supportsStreaming ? '✓' : '✗'}`);
201
+ console.log(` Direct File Edit: ${metadata.capabilities.supportsDirectFileEdit ? '✓' : '✗'}`);
202
+ console.log(` Test Generation: ${metadata.capabilities.supportsTestGeneration ? '✓' : '✗'}`);
203
+ console.log(` Plan Generation: ${metadata.capabilities.supportsPlanGeneration ? '✓' : '✗'}`);
204
+ console.log(` Max Sessions: ${metadata.capabilities.maxConcurrentSessions}`);
205
+ console.log(`\nRequired Dependencies:`);
206
+ for (const dep of metadata.dependencies) {
207
+ console.log(` - ${dep.name} (${dep.type}): ${dep.description}`);
208
+ if (dep.installCommand) {
209
+ console.log(` Install: ${dep.installCommand}`);
210
+ }
211
+ }
212
+ process.exit(0);
213
+ })();
214
+ }
215
+
216
+ // Set ALLOW_EDIT from command line if provided
217
+ if (options.allowEdit) {
218
+ process.env.ALLOW_EDIT = '1';
219
+ logInfo(chalk.blue(`Enabling implement tool with --allow-edit flag`));
220
+ }
221
+
222
+ // Set implementation tool backend options
223
+ if (options.implementToolBackend) {
224
+ process.env.IMPLEMENT_TOOL_BACKEND = options.implementToolBackend;
225
+ logInfo(chalk.blue(`Using implementation tool backend: ${options.implementToolBackend}`));
226
+ }
227
+
228
+ if (options.implementToolTimeout) {
229
+ process.env.IMPLEMENT_TOOL_TIMEOUT = options.implementToolTimeout;
230
+ logInfo(chalk.blue(`Implementation tool timeout: ${options.implementToolTimeout}ms`));
231
+ }
232
+
233
+ if (options.implementToolConfig) {
234
+ process.env.IMPLEMENT_TOOL_CONFIG_PATH = options.implementToolConfig;
235
+ logInfo(chalk.blue(`Using implementation tool config: ${options.implementToolConfig}`));
236
+ }
237
+
238
+ // Set telemetry options from command line if provided
239
+ if (options.traceFile !== undefined) {
240
+ process.env.OTEL_ENABLE_FILE = 'true';
241
+ process.env.OTEL_FILE_PATH = options.traceFile || './traces.jsonl';
242
+ logInfo(chalk.blue(`Enabling file tracing to: ${process.env.OTEL_FILE_PATH}`));
243
+ }
244
+
245
+ if (options.traceRemote !== undefined) {
246
+ process.env.OTEL_ENABLE_REMOTE = 'true';
247
+ process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = options.traceRemote || 'http://localhost:4318/v1/traces';
248
+ logInfo(chalk.blue(`Enabling remote tracing to: ${process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}`));
249
+ }
250
+
251
+ if (options.traceConsole) {
252
+ process.env.OTEL_ENABLE_CONSOLE = 'true';
253
+ logInfo(chalk.blue(`Enabling console tracing`));
254
+ }
255
+
256
+
257
+ // Handle completion prompt if provided
258
+ let completionPrompt = null;
259
+ if (options.completionPrompt) {
260
+ // Check if it's a file path
261
+ try {
262
+ const completionPromptPath = resolve(options.completionPrompt);
263
+ if (existsSync(completionPromptPath)) {
264
+ completionPrompt = readFileSync(completionPromptPath, 'utf8');
265
+ logInfo(chalk.blue(`Loaded completion prompt from file: ${completionPromptPath}`));
266
+ } else {
267
+ // Not an existing file, treat as a direct string prompt
268
+ completionPrompt = options.completionPrompt;
269
+ logInfo(chalk.blue(`Using completion prompt string`));
270
+ }
271
+ } catch (error) {
272
+ // If there's an error resolving the path, treat as a direct string prompt
273
+ completionPrompt = options.completionPrompt;
274
+ logInfo(chalk.blue(`Using completion prompt string`));
275
+ }
276
+ }
277
+
278
+ // Handle custom prompt if provided
279
+ let customPrompt = null;
280
+ if (options.prompt) {
281
+ // Check if it's one of the predefined prompts
282
+ const predefinedPrompts = ['architect', 'code-review', 'code-review-template', 'support', 'engineer'];
283
+ if (predefinedPrompts.includes(options.prompt)) {
284
+ process.env.PROMPT_TYPE = options.prompt;
285
+ logInfo(chalk.blue(`Using predefined prompt: ${options.prompt}`));
286
+ } else {
287
+ // Check if it's a file path
288
+ try {
289
+ const promptPath = resolve(options.prompt);
290
+ if (existsSync(promptPath)) {
291
+ customPrompt = readFileSync(promptPath, 'utf8');
292
+ process.env.CUSTOM_PROMPT = customPrompt;
293
+ logInfo(chalk.blue(`Loaded custom prompt from file: ${promptPath}`));
294
+ } else {
295
+ // Not a predefined prompt or existing file, treat as a direct string prompt
296
+ customPrompt = options.prompt;
297
+ process.env.CUSTOM_PROMPT = customPrompt;
298
+ logInfo(chalk.blue(`Using custom prompt string`));
299
+ }
300
+ } catch (error) {
301
+ // If there's an error resolving the path, treat as a direct string prompt
302
+ customPrompt = options.prompt;
303
+ process.env.CUSTOM_PROMPT = customPrompt;
304
+ logInfo(chalk.blue(`Using custom prompt string`));
305
+ }
306
+ }
307
+ }
308
+
309
+ // Parse and validate allowed folders from environment variable
310
+ const allowedFolders = process.env.ALLOWED_FOLDERS
311
+ ? process.env.ALLOWED_FOLDERS.split(',').map(folder => folder.trim()).filter(Boolean)
312
+ : [];
313
+
314
+ // Resolve path argument to override ALLOWED_FOLDERS
315
+ if (pathArg) {
316
+ const resolvedPath = resolve(pathArg);
317
+ if (existsSync(resolvedPath)) {
318
+ const realPath = realpathSync(resolvedPath);
319
+ process.env.ALLOWED_FOLDERS = realPath;
320
+ logInfo(chalk.blue(`Using codebase path: ${realPath}`));
321
+ // Clear allowedFolders if pathArg overrides it
322
+ allowedFolders.length = 0;
323
+ allowedFolders.push(realPath);
324
+ } else {
325
+ logError(chalk.red(`Path does not exist: ${resolvedPath}`));
326
+ process.exit(1);
327
+ }
328
+ } else {
329
+ // Log allowed folders only if interactive or debug
330
+ logInfo('Configured search folders:');
331
+ for (const folder of allowedFolders) {
332
+ const exists = existsSync(folder);
333
+ logInfo(`- ${folder} ${exists ? '✓' : '✗ (not found)'}`);
334
+ if (!exists) {
335
+ logWarn(chalk.yellow(`Warning: Folder "${folder}" does not exist or is not accessible`));
336
+ }
337
+ }
338
+ if (allowedFolders.length === 0 && !isNonInteractive) { // Only warn if interactive
339
+ logWarn(chalk.yellow('No folders configured. Set ALLOWED_FOLDERS in .env file or provide a path argument.'));
340
+ }
341
+ }
342
+
343
+
344
+ // Set port for web server if specified
345
+ if (options.port) {
346
+ process.env.PORT = options.port;
347
+ }
348
+
349
+ // Check for API keys
350
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
351
+ const openaiApiKey = process.env.OPENAI_API_KEY;
352
+ const googleApiKey = process.env.GOOGLE_API_KEY;
353
+ const hasApiKeys = !!(anthropicApiKey || openaiApiKey || googleApiKey);
354
+
355
+ // --- Bash Configuration Processing ---
356
+ let bashConfig = null;
357
+ if (options.enableBash) {
358
+ bashConfig = {};
359
+
360
+ // Parse allow patterns
361
+ if (options.bashAllow) {
362
+ bashConfig.allow = options.bashAllow.split(',').map(p => p.trim()).filter(p => p.length > 0);
363
+ logInfo(chalk.blue(`Bash allow patterns: ${bashConfig.allow.join(', ')}`));
364
+ }
365
+
366
+ // Parse deny patterns
367
+ if (options.bashDeny) {
368
+ bashConfig.deny = options.bashDeny.split(',').map(p => p.trim()).filter(p => p.length > 0);
369
+ logInfo(chalk.blue(`Bash deny patterns: ${bashConfig.deny.join(', ')}`));
370
+ }
371
+
372
+ // Handle default list flags
373
+ if (options.defaultBashAllow === false) {
374
+ bashConfig.disableDefaultAllow = true;
375
+ logInfo(chalk.blue('Default bash allow list disabled'));
376
+ }
377
+
378
+ if (options.defaultBashDeny === false) {
379
+ bashConfig.disableDefaultDeny = true;
380
+ logInfo(chalk.blue('Default bash deny list disabled'));
381
+ }
382
+
383
+ // Parse timeout
384
+ if (options.bashTimeout) {
385
+ const timeout = parseInt(options.bashTimeout, 10);
386
+ if (isNaN(timeout) || timeout < 1000) {
387
+ logError(chalk.red('Bash timeout must be a number >= 1000 milliseconds'));
388
+ process.exit(1);
389
+ }
390
+ bashConfig.timeout = timeout;
391
+ logInfo(chalk.blue(`Bash timeout: ${timeout}ms`));
392
+ }
393
+
394
+ // Set working directory
395
+ if (options.bashWorkingDir) {
396
+ if (!existsSync(options.bashWorkingDir)) {
397
+ logError(chalk.red(`Bash working directory does not exist: ${options.bashWorkingDir}`));
398
+ process.exit(1);
399
+ }
400
+ bashConfig.workingDirectory = realpathSync(options.bashWorkingDir);
401
+ logInfo(chalk.blue(`Bash working directory: ${bashConfig.workingDirectory}`));
402
+ }
403
+
404
+ logInfo(chalk.green('Bash command execution enabled'));
405
+ }
406
+
407
+ // --- Web Mode (check before non-interactive to override) ---
408
+ if (options.web) {
409
+ if (!hasApiKeys) {
410
+ // Use logWarn for web mode warning
411
+ logWarn(chalk.yellow('Warning: No API key provided. The web interface will show instructions on how to set up API keys.'));
412
+ }
413
+ // Import and start web server
414
+ import('./webServer.js')
415
+ .then(async module => {
416
+ const { startWebServer } = module;
417
+ logInfo(`Starting web server on port ${process.env.PORT || 8080}...`);
418
+ await startWebServer(version, hasApiKeys, { allowEdit: options.allowEdit });
419
+ })
420
+ .catch(error => {
421
+ logError(chalk.red(`Error starting web server: ${error.message}`));
422
+ process.exit(1);
423
+ });
424
+ return; // Exit main function
425
+ }
426
+ // --- End Web Mode ---
427
+
428
+ // --- Non-Interactive Mode ---
429
+ if (isNonInteractive) {
430
+ if (!hasApiKeys) {
431
+ logError(chalk.red('No API key provided. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY environment variable.'));
432
+ process.exit(1);
433
+ }
434
+
435
+ let chat;
436
+ try {
437
+ // Pass session ID if provided, ProbeChat generates one otherwise
438
+ chat = new ProbeChat({
439
+ sessionId: options.sessionId,
440
+ isNonInteractive: true,
441
+ customPrompt: customPrompt,
442
+ promptType: options.prompt && ['architect', 'code-review', 'code-review-template', 'support', 'engineer'].includes(options.prompt) ? options.prompt : null,
443
+ allowEdit: options.allowEdit,
444
+ enableBash: options.enableBash,
445
+ bashConfig: bashConfig,
446
+ completionPrompt: completionPrompt
447
+ });
448
+ // Model/Provider info is logged via logInfo above if debug enabled
449
+ logInfo(chalk.blue(`Using Session ID: ${chat.getSessionId()}`)); // Log the actual session ID being used
450
+ } catch (error) {
451
+ logError(chalk.red(`Initializing chat failed: ${error.message}`));
452
+ process.exit(1);
453
+ }
454
+
455
+ // Function to read from stdin
456
+ const readFromStdin = () => {
457
+ return new Promise((resolve) => {
458
+ let data = '';
459
+ process.stdin.on('data', (chunk) => {
460
+ data += chunk;
461
+ });
462
+ process.stdin.on('end', () => {
463
+ resolve(data.trim());
464
+ });
465
+ });
466
+ };
467
+
468
+ // Async function to handle the single chat request
469
+ const runNonInteractiveChat = async () => {
470
+ try {
471
+ // Get message from command line argument or stdin
472
+ let message = options.message;
473
+
474
+ // If no message argument but stdin is piped, read from stdin
475
+ if (!message && isPipedInput) {
476
+ logInfo('Reading message from stdin...'); // Log only if debug
477
+ message = await readFromStdin();
478
+ }
479
+
480
+ if (!message) {
481
+ logError('No message provided. Use --message option or pipe input to stdin.');
482
+ process.exit(1);
483
+ }
484
+
485
+ logInfo('Sending message...'); // Log only if debug
486
+ const result = await chat.chat(message, chat.getSessionId(), null, imageUrls); // Use the chat's current session ID and pass images
487
+
488
+ if (result && typeof result === 'object' && result.response !== undefined) {
489
+ if (options.json) {
490
+ const outputData = {
491
+ response: result.response,
492
+ sessionId: chat.getSessionId(),
493
+ tokenUsage: result.tokenUsage || null // Include usage if available
494
+ };
495
+ // Output JSON to stdout
496
+ rawLog(JSON.stringify(outputData, null, 2));
497
+ } else {
498
+ // Output raw response text to stdout
499
+ rawLog(result.response);
500
+ }
501
+ process.exit(0); // Success
502
+ } else if (typeof result === 'string') { // Handle simple string responses (e.g., cancellation message)
503
+ if (options.json) {
504
+ rawLog(JSON.stringify({ response: result, sessionId: chat.getSessionId(), tokenUsage: null }, null, 2));
505
+ } else {
506
+ rawLog(result);
507
+ }
508
+ process.exit(0); // Exit cleanly
509
+ }
510
+ else {
511
+ logError('Received an unexpected or empty response structure from chat.');
512
+ if (options.json) {
513
+ rawError(JSON.stringify({ error: 'Unexpected response structure', response: result, sessionId: chat.getSessionId() }, null, 2));
514
+ }
515
+ process.exit(1); // Error exit code
516
+ }
517
+ } catch (error) {
518
+ logError(`Chat request failed: ${error.message}`);
519
+ if (options.json) {
520
+ // Output JSON error to stderr
521
+ rawError(JSON.stringify({ error: error.message, sessionId: chat.getSessionId() }, null, 2));
522
+ }
523
+ process.exit(1); // Error exit code
524
+ }
525
+ };
526
+
527
+ runNonInteractiveChat();
528
+ return; // Exit main function, prevent interactive/web mode
529
+ }
530
+ // --- End Non-Interactive Mode ---
531
+
532
+
533
+ // --- Interactive CLI Mode ---
534
+ // (This block only runs if not non-interactive and not web mode)
535
+
536
+ if (!hasApiKeys) {
537
+ // Use logError and standard console.log for setup instructions
538
+ logError(chalk.red('No API key provided. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_API_KEY environment variable.'));
539
+ console.log(chalk.cyan('You can find these instructions in the .env.example file:'));
540
+ console.log(chalk.cyan('1. Create a .env file by copying .env.example'));
541
+ console.log(chalk.cyan('2. Add your API key to the .env file'));
542
+ console.log(chalk.cyan('3. Restart the application'));
543
+ process.exit(1);
544
+ }
545
+
546
+ // Initialize ProbeChat for CLI mode
547
+ let chat;
548
+ try {
549
+ // Pass session ID if provided (though less common for interactive start)
550
+ chat = new ProbeChat({
551
+ sessionId: options.sessionId,
552
+ isNonInteractive: false,
553
+ customPrompt: customPrompt,
554
+ promptType: options.prompt && ['architect', 'code-review', 'code-review-template', 'support', 'engineer'].includes(options.prompt) ? options.prompt : null,
555
+ allowEdit: options.allowEdit,
556
+ enableBash: options.enableBash,
557
+ bashConfig: bashConfig,
558
+ completionPrompt: completionPrompt
559
+ });
560
+
561
+ // Log model/provider info using logInfo
562
+ if (chat.apiType === 'anthropic') {
563
+ logInfo(chalk.green(`Using Anthropic API with model: ${chat.model}`));
564
+ } else if (chat.apiType === 'openai') {
565
+ logInfo(chalk.green(`Using OpenAI API with model: ${chat.model}`));
566
+ } else if (chat.apiType === 'google') {
567
+ logInfo(chalk.green(`Using Google API with model: ${chat.model}`));
568
+ }
569
+
570
+ logInfo(chalk.blue(`Session ID: ${chat.getSessionId()}`));
571
+ logInfo(chalk.cyan('Type "exit" or "quit" to end the chat'));
572
+ logInfo(chalk.cyan('Type "usage" to see token usage statistics'));
573
+ logInfo(chalk.cyan('Type "clear" to clear the chat history'));
574
+ logInfo(chalk.cyan('-------------------------------------------'));
575
+ } catch (error) {
576
+ logError(chalk.red(`Error initializing chat: ${error.message}`));
577
+ process.exit(1);
578
+ }
579
+
580
+ // Format AI response for interactive mode
581
+ function formatResponseInteractive(response) {
582
+ // Check if response is a structured object with response and tokenUsage properties
583
+ let textResponse = '';
584
+ if (response && typeof response === 'object' && 'response' in response) {
585
+ textResponse = response.response;
586
+ } else if (typeof response === 'string') {
587
+ // Fallback for legacy format or simple string response
588
+ textResponse = response;
589
+ } else {
590
+ return chalk.red('[Error: Invalid response format]');
591
+ }
592
+
593
+ // Apply formatting (e.g., highlighting tool calls)
594
+ return textResponse.replace(
595
+ /<tool_call>(.*?)<\/tool_call>/gs,
596
+ (match, toolCall) => chalk.magenta(`[Tool Call] ${toolCall}`)
597
+ );
598
+ }
599
+
600
+ // Main interactive chat loop
601
+ async function startChat() {
602
+ while (true) {
603
+ const { message } = await inquirer.prompt([
604
+ {
605
+ type: 'input',
606
+ name: 'message',
607
+ message: chalk.blue('You:'),
608
+ prefix: '',
609
+ },
610
+ ]);
611
+
612
+ if (message.toLowerCase() === 'exit' || message.toLowerCase() === 'quit') {
613
+ logInfo(chalk.yellow('Goodbye!'));
614
+ break;
615
+ } else if (message.toLowerCase() === 'usage') {
616
+ const usage = chat.getTokenUsage();
617
+ const display = new TokenUsageDisplay();
618
+ const formatted = display.format(usage);
619
+
620
+ // Use logInfo for usage details
621
+ logInfo(chalk.blue('Current:', formatted.current.total));
622
+ logInfo(chalk.blue('Context:', formatted.contextWindow));
623
+ logInfo(chalk.blue('Cache:',
624
+ `Read: ${formatted.current.cache.read},`,
625
+ `Write: ${formatted.current.cache.write},`,
626
+ `Total: ${formatted.current.cache.total}`));
627
+ logInfo(chalk.blue('Total:', formatted.total.total));
628
+
629
+ // Show context window in terminal title (only relevant for interactive)
630
+ process.stdout.write('\x1B]0;Context: ' + formatted.contextWindow + '\x07');
631
+ continue;
632
+ } else if (message.toLowerCase() === 'clear') {
633
+ const newSessionId = chat.clearHistory();
634
+ logInfo(chalk.yellow('Chat history cleared'));
635
+ logInfo(chalk.blue(`New session ID: ${newSessionId}`));
636
+ continue;
637
+ }
638
+
639
+ const spinner = ora('Thinking...').start(); // Spinner is ok for interactive mode
640
+ try {
641
+ const result = await chat.chat(message, null, null, imageUrls); // Uses internal session ID and pass images
642
+ spinner.stop();
643
+
644
+ logInfo(chalk.green('Assistant:'));
645
+ console.log(formatResponseInteractive(result)); // Use standard console.log for the actual response content
646
+ console.log(); // Add a newline for readability
647
+
648
+ // Update terminal title with context window size if available
649
+ if (result && typeof result === 'object' && result.tokenUsage && result.tokenUsage.contextWindow) {
650
+ process.stdout.write('\x1B]0;Context: ' + result.tokenUsage.contextWindow + '\x07');
651
+ }
652
+ } catch (error) {
653
+ spinner.stop();
654
+ logError(chalk.red(`Error: ${error.message}`)); // Use logError
655
+ }
656
+ }
657
+ }
658
+
659
+ startChat().catch((error) => {
660
+ logError(chalk.red(`Fatal error in interactive chat: ${error.message}`));
661
+ process.exit(1);
662
+ });
663
+ // --- End Interactive CLI Mode ---
664
+ }
665
+
666
+ // If this file is run directly, call main()
667
+ if (import.meta.url.startsWith('file:') && process.argv[1] === fileURLToPath(import.meta.url)) {
668
+ main();
669
+ }