@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.
- package/README.md +138 -0
- package/data/.env.example +22 -0
- package/data/.gitattributes +47 -0
- package/data/.glfrc.json +7 -0
- package/data/.husky/pre-commit +5 -0
- package/data/.nvmrc +1 -0
- package/data/CHANGELOG.md +75 -0
- package/data/CODE_OF_CONDUCT.md +129 -0
- package/data/CONTRIBUTING.md +203 -0
- package/data/DOCS-STRUCTURE.md +307 -0
- package/data/I18N.md +292 -0
- package/data/LICENSE +22 -0
- package/data/README.md +315 -0
- package/data/SECURITY.md +125 -0
- package/data/WIKI-DEPLOYMENT.md +348 -0
- package/data/docs/AI-FEATURES.md +610 -0
- package/data/docs/API-REFERENCE.md +1022 -0
- package/data/docs/AUTHENTICATION.md +301 -0
- package/data/docs/BACKEND-API.md +468 -0
- package/data/docs/DEVELOPMENT.md +375 -0
- package/data/docs/EXAMPLES.md +622 -0
- package/data/docs/MCP-SERVER.md +307 -0
- package/data/docs/MIGRATION-GUIDE.md +367 -0
- package/data/docs/NPM-PUBLISH.md +193 -0
- package/data/docs/QUICKSTART.md +206 -0
- package/data/docs/REDIS-SETUP.md +162 -0
- package/data/docs/SERVER.md +228 -0
- package/data/docs/TROUBLESHOOTING.md +657 -0
- package/data/docs/WIDGET-GUIDE.md +638 -0
- package/data/docs/WIKI-HOME.md +58 -0
- package/data/docs/WIKI-SIDEBAR.md +39 -0
- package/data/package.json +171 -0
- package/data/playwright.config.ts +64 -0
- package/data/probe/.cargo/config.toml +10 -0
- package/data/probe/.claude/commands/performance-review.md +15 -0
- package/data/probe/.clinerules +288 -0
- package/data/probe/.dockerignore +57 -0
- package/data/probe/.githooks/post-commit +11 -0
- package/data/probe/.githooks/pre-commit +99 -0
- package/data/probe/.githooks/pre-commit-vow +9 -0
- package/data/probe/.prompts/engineer.md +41 -0
- package/data/probe/.roomodes +28 -0
- package/data/probe/.windsurfrules +0 -0
- package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
- package/data/probe/BENCHMARKING.md +256 -0
- package/data/probe/CLAUDE.md +226 -0
- package/data/probe/CODE_OF_CONDUCT.md +128 -0
- package/data/probe/CONTRIBUTING.md +193 -0
- package/data/probe/Cargo.toml +120 -0
- package/data/probe/Cross.toml +10 -0
- package/data/probe/DOCKER-README.md +224 -0
- package/data/probe/Dockerfile +32 -0
- package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
- package/data/probe/LICENSE +201 -0
- package/data/probe/Makefile +210 -0
- package/data/probe/README.md +824 -0
- package/data/probe/SECURITY.md +67 -0
- package/data/probe/WINDOWS-GUIDE.md +294 -0
- package/data/probe/benches/parsing_benchmarks.rs +370 -0
- package/data/probe/benches/search_benchmarks.rs +599 -0
- package/data/probe/benches/simd_benchmarks.rs +372 -0
- package/data/probe/benches/timing_benchmarks.rs +287 -0
- package/data/probe/build-windows.bat +229 -0
- package/data/probe/codex-config/config.toml +6 -0
- package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
- package/data/probe/examples/cache_demo.rs +46 -0
- package/data/probe/examples/chat/.dockerignore +37 -0
- package/data/probe/examples/chat/ChatSessionManager.js +295 -0
- package/data/probe/examples/chat/Dockerfile +98 -0
- package/data/probe/examples/chat/LICENSE +201 -0
- package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
- package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
- package/data/probe/examples/chat/README.md +338 -0
- package/data/probe/examples/chat/TRACING.md +226 -0
- package/data/probe/examples/chat/appTracer.js +968 -0
- package/data/probe/examples/chat/auth.js +76 -0
- package/data/probe/examples/chat/bin/probe-chat.js +13 -0
- package/data/probe/examples/chat/build.js +104 -0
- package/data/probe/examples/chat/cancelRequest.js +84 -0
- package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
- package/data/probe/examples/chat/demo-local-images.js +128 -0
- package/data/probe/examples/chat/fileSpanExporter.js +181 -0
- package/data/probe/examples/chat/implement/README.md +228 -0
- package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
- package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
- package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
- package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
- package/data/probe/examples/chat/implement/backends/registry.js +85 -0
- package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
- package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
- package/data/probe/examples/chat/implement/core/config.js +428 -0
- package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
- package/data/probe/examples/chat/implement/core/utils.js +496 -0
- package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
- package/data/probe/examples/chat/index.js +669 -0
- package/data/probe/examples/chat/mcpServer.js +341 -0
- package/data/probe/examples/chat/npm/LICENSE +15 -0
- package/data/probe/examples/chat/npm/README.md +168 -0
- package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
- package/data/probe/examples/chat/npm/index.js +259 -0
- package/data/probe/examples/chat/npm/package.json +54 -0
- package/data/probe/examples/chat/package.json +102 -0
- package/data/probe/examples/chat/probeChat.js +456 -0
- package/data/probe/examples/chat/probeTool.js +491 -0
- package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
- package/data/probe/examples/chat/telemetry.js +281 -0
- package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
- package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
- package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
- package/data/probe/examples/chat/test/test-backends.js +90 -0
- package/data/probe/examples/chat/test/testUtils.js +530 -0
- package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
- package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
- package/data/probe/examples/chat/test/verify-tests.js +118 -0
- package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
- package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
- package/data/probe/examples/chat/test-chat-tracing.js +38 -0
- package/data/probe/examples/chat/test-direct-function.js +49 -0
- package/data/probe/examples/chat/test-file-size-validation.js +103 -0
- package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
- package/data/probe/examples/chat/test-github-context.txt +12 -0
- package/data/probe/examples/chat/test-hierarchy.js +203 -0
- package/data/probe/examples/chat/test-image-spans.js +37 -0
- package/data/probe/examples/chat/test-local-image-reading.js +176 -0
- package/data/probe/examples/chat/test-mcp-integration.js +136 -0
- package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
- package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
- package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
- package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
- package/data/probe/examples/chat/test-security-validation.js +145 -0
- package/data/probe/examples/chat/test-simple-tracing.js +32 -0
- package/data/probe/examples/chat/test-trace-verification.js +235 -0
- package/data/probe/examples/chat/test-tracing.js +114 -0
- package/data/probe/examples/chat/tokenCounter.js +419 -0
- package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
- package/data/probe/examples/chat/webServer.js +1103 -0
- package/data/probe/examples/reranker/Cargo.toml +33 -0
- package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
- package/data/probe/examples/reranker/MODELS.md +66 -0
- package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
- package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
- package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
- package/data/probe/examples/reranker/README.md +347 -0
- package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
- package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
- package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
- package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
- package/data/probe/examples/reranker/debug_scoring.py +189 -0
- package/data/probe/examples/reranker/debug_tokenization.py +154 -0
- package/data/probe/examples/reranker/download_models.sh +73 -0
- package/data/probe/examples/reranker/requirements.txt +13 -0
- package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
- package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
- package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
- package/data/probe/examples/reranker/simple_test.py +50 -0
- package/data/probe/examples/reranker/test_all_models.sh +63 -0
- package/data/probe/examples/reranker/test_bert_results.sh +44 -0
- package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
- package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
- package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
- package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
- package/data/probe/examples/reranker/test_scores.py +132 -0
- package/data/probe/install.ps1 +508 -0
- package/data/probe/install.sh +460 -0
- package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
- package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
- package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
- package/data/probe/npm/MAID_INTEGRATION.md +313 -0
- package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
- package/data/probe/npm/README.md +824 -0
- package/data/probe/npm/bin/.gitignore +7 -0
- package/data/probe/npm/bin/.gitkeep +0 -0
- package/data/probe/npm/bin/README.md +12 -0
- package/data/probe/npm/bin/probe +167 -0
- package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
- package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
- package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
- package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
- package/data/probe/npm/example-usage.js +335 -0
- package/data/probe/npm/examples/multi-engine-demo.js +117 -0
- package/data/probe/npm/examples/probe-agent-cli.js +113 -0
- package/data/probe/npm/examples/test-agent-edit.js +114 -0
- package/data/probe/npm/examples/test-edit-create.js +120 -0
- package/data/probe/npm/examples/test-edit-direct.js +114 -0
- package/data/probe/npm/index.d.ts +744 -0
- package/data/probe/npm/jest.config.js +52 -0
- package/data/probe/npm/package.json +117 -0
- package/data/probe/npm/scripts/build-agent.cjs +75 -0
- package/data/probe/npm/scripts/build-cjs.js +124 -0
- package/data/probe/npm/scripts/build-mcp.cjs +36 -0
- package/data/probe/npm/scripts/postinstall.js +216 -0
- package/data/probe/npm/test-codex-e2e.js +78 -0
- package/data/probe/npm/test-download-lock.js +109 -0
- package/data/probe/npm/test-grep-security.js +94 -0
- package/data/probe/npm/test-grep-simplified.js +63 -0
- package/data/probe/npm/test-grep.js +51 -0
- package/data/probe/npm/tests/README.md +96 -0
- package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
- package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
- package/data/probe/npm/tests/contextCompactor.test.js +498 -0
- package/data/probe/npm/tests/delegate-config.test.js +353 -0
- package/data/probe/npm/tests/delegate-integration.test.js +348 -0
- package/data/probe/npm/tests/extractor-integration.test.js +162 -0
- package/data/probe/npm/tests/extractor.test.js +317 -0
- package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
- package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
- package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
- package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
- package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
- package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
- package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
- package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
- package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
- package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
- package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
- package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
- package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
- package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
- package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
- package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
- package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
- package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
- package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
- package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
- package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
- package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
- package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
- package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
- package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
- package/data/probe/npm/tests/setup.js +46 -0
- package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
- package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
- package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
- package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
- package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
- package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
- package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
- package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
- package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
- package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
- package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
- package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
- package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
- package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
- package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
- package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
- package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
- package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
- package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
- package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
- package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
- package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
- package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
- package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
- package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
- package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
- package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
- package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
- package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
- package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
- package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
- package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
- package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
- package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
- package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
- package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
- package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
- package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
- package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
- package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
- package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
- package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
- package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
- package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
- package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
- package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
- package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
- package/data/probe/npm/tsconfig.json +21 -0
- package/data/probe/result1.txt +19 -0
- package/data/probe/result2.txt +26 -0
- package/data/probe/scripts/benchmark.sh +270 -0
- package/data/probe/scripts/cache_memory_analysis.rs +844 -0
- package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
- package/data/probe/site/.env.example +10 -0
- package/data/probe/site/DEPLOYMENT.md +86 -0
- package/data/probe/site/README.md +183 -0
- package/data/probe/site/adding-languages.md +135 -0
- package/data/probe/site/ai-chat.md +427 -0
- package/data/probe/site/ai-integration.md +1488 -0
- package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
- package/data/probe/site/blog/index.md +118 -0
- package/data/probe/site/blog/v0.6.0-release.md +426 -0
- package/data/probe/site/blog.md +8 -0
- package/data/probe/site/changelog.md +200 -0
- package/data/probe/site/cli-mode.md +437 -0
- package/data/probe/site/code-extraction.md +436 -0
- package/data/probe/site/contributing/README.md +9 -0
- package/data/probe/site/contributing/documentation-cross-references.md +215 -0
- package/data/probe/site/contributing/documentation-maintenance.md +275 -0
- package/data/probe/site/contributing/documentation-structure.md +75 -0
- package/data/probe/site/documentation-cross-references.md +215 -0
- package/data/probe/site/documentation-guide.md +132 -0
- package/data/probe/site/documentation-maintenance.md +275 -0
- package/data/probe/site/features.md +147 -0
- package/data/probe/site/how-it-works.md +118 -0
- package/data/probe/site/index.md +175 -0
- package/data/probe/site/index.md.bak +133 -0
- package/data/probe/site/installation.md +235 -0
- package/data/probe/site/integrations/docker.md +248 -0
- package/data/probe/site/integrations/github-actions.md +413 -0
- package/data/probe/site/language-support-overview.md +168 -0
- package/data/probe/site/mcp-integration.md +587 -0
- package/data/probe/site/mcp-server.md +304 -0
- package/data/probe/site/navigation-structure.md +76 -0
- package/data/probe/site/nodejs-sdk.md +798 -0
- package/data/probe/site/output-formats.md +625 -0
- package/data/probe/site/package.json +21 -0
- package/data/probe/site/public/_headers +28 -0
- package/data/probe/site/public/_redirects +11 -0
- package/data/probe/site/quick-start.md +289 -0
- package/data/probe/site/search-functionality.md +291 -0
- package/data/probe/site/search-reference.md +291 -0
- package/data/probe/site/supported-languages.md +215 -0
- package/data/probe/site/use-cases/README.md +8 -0
- package/data/probe/site/use-cases/advanced-cli.md +253 -0
- package/data/probe/site/use-cases/ai-code-editors.md +239 -0
- package/data/probe/site/use-cases/building-ai-tools.md +529 -0
- package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
- package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
- package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
- package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
- package/data/probe/site/use-cases/team-chat.md +350 -0
- package/data/probe/site/web-interface.md +434 -0
- package/data/probe/site/wrangler.toml +9 -0
- package/data/probe/test-api-key.sh +1 -0
- package/data/probe/test-probe-implementation/hello.js +7 -0
- package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
- package/data/probe/test_cases/early_termination_issues.rs +533 -0
- package/data/probe/test_data/test_nested_struct.go +26 -0
- package/data/probe/tests/README.md +286 -0
- package/data/probe/tests/README_search_determinism_tests.md +116 -0
- package/data/probe/tests/adjacent_comment_test.rs +152 -0
- package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
- package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
- package/data/probe/tests/block_merging_tests.rs +396 -0
- package/data/probe/tests/c_outline_format_tests.rs +2179 -0
- package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
- package/data/probe/tests/cache_order_tests.rs +147 -0
- package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
- package/data/probe/tests/cli_tests.rs +680 -0
- package/data/probe/tests/comment_context_integration_test.rs +240 -0
- package/data/probe/tests/common.rs +33 -0
- package/data/probe/tests/complex_block_merging_tests.rs +599 -0
- package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
- package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
- package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
- package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
- package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
- package/data/probe/tests/extract_command_tests.rs +1848 -0
- package/data/probe/tests/extract_deduplication_tests.rs +146 -0
- package/data/probe/tests/extract_input_file_tests.rs +84 -0
- package/data/probe/tests/extract_prompt_tests.rs +102 -0
- package/data/probe/tests/filename_search_tests.rs +96 -0
- package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
- package/data/probe/tests/github_extract_tests.rs +234 -0
- package/data/probe/tests/go_comment_test.rs +253 -0
- package/data/probe/tests/go_outline_format_tests.rs +2587 -0
- package/data/probe/tests/go_path_resolver_tests.rs +96 -0
- package/data/probe/tests/html_outline_format_tests.rs +637 -0
- package/data/probe/tests/integration_tests.rs +837 -0
- package/data/probe/tests/ip_whitelist_test.rs +148 -0
- package/data/probe/tests/java_outline_format_tests.rs +1611 -0
- package/data/probe/tests/javascript_extract_tests.rs +315 -0
- package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
- package/data/probe/tests/json_format_tests.rs +436 -0
- package/data/probe/tests/json_schema_validation_tests.rs +450 -0
- package/data/probe/tests/lib_usage.rs +60 -0
- package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
- package/data/probe/tests/line_map_cache_tests.rs +114 -0
- package/data/probe/tests/markdown_integration_tests.rs +190 -0
- package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
- package/data/probe/tests/mocks/test_object.js +27 -0
- package/data/probe/tests/mocks/test_struct.go +50 -0
- package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
- package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
- package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
- package/data/probe/tests/negative_compound_word_tests.rs +246 -0
- package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
- package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
- package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
- package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
- package/data/probe/tests/parallel_extraction_tests.rs +178 -0
- package/data/probe/tests/parallel_search_tests.rs +355 -0
- package/data/probe/tests/path_resolver_tests.rs +698 -0
- package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
- package/data/probe/tests/php_outline_format_tests.rs +768 -0
- package/data/probe/tests/property_tests.proptest-regressions +9 -0
- package/data/probe/tests/property_tests.rs +118 -0
- package/data/probe/tests/python_outline_format_tests.rs +1538 -0
- package/data/probe/tests/query_command_json_tests.rs +438 -0
- package/data/probe/tests/query_command_tests.rs +232 -0
- package/data/probe/tests/query_command_xml_tests.rs +569 -0
- package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
- package/data/probe/tests/required_terms_filename_tests.rs +116 -0
- package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
- package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
- package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
- package/data/probe/tests/rust_outline_format_tests.rs +843 -0
- package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
- package/data/probe/tests/search_determinism_tests.rs +451 -0
- package/data/probe/tests/search_hints_tests.rs +253 -0
- package/data/probe/tests/special_character_escaping_tests.rs +417 -0
- package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
- package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
- package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
- package/data/probe/tests/symbols_tests.rs +166 -0
- package/data/probe/tests/test_file.rs +45 -0
- package/data/probe/tests/test_tokenize.rs +28 -0
- package/data/probe/tests/timeout_tests.rs +82 -0
- package/data/probe/tests/tokenization_tests.rs +195 -0
- package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
- package/data/probe/tests/typescript_extract_tests.rs +214 -0
- package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
- package/data/probe/tests/xml_format_tests.rs +568 -0
- package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
- package/data/scripts/postinstall.mjs +9 -0
- package/data/scripts/set-version.js +0 -0
- package/data/scripts/wiki-build.sh +111 -0
- package/data/scripts/wiki-deploy.sh +73 -0
- package/data/serve.json +12 -0
- package/data/test/demo-dynamic.html +134 -0
- package/data/test/demo-esm.html +105 -0
- package/data/test/demo-iife.html +78 -0
- package/data/tsconfig.json +7 -0
- package/data/vite.server.ts +483 -0
- package/data/vitest.config.ts +40 -0
- package/data/wiki/Home.md +58 -0
- package/data/wiki/_Sidebar.md +39 -0
- package/docs-mcp.config.json +20 -0
- package/package.json +56 -0
- package/src/config.js +111 -0
- 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
|
+
}
|