@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,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for delegation limits and security features with SDK-based delegation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { jest } from '@jest/globals';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, resolve } from 'path';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = dirname(__filename);
|
|
11
|
+
|
|
12
|
+
// Mock ProbeAgent
|
|
13
|
+
const mockAnswer = jest.fn();
|
|
14
|
+
const MockProbeAgent = jest.fn().mockImplementation(() => ({
|
|
15
|
+
answer: mockAnswer
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// Use absolute path for mocking
|
|
19
|
+
const probeAgentPath = resolve(__dirname, '../../src/agent/ProbeAgent.js');
|
|
20
|
+
const delegatePath = resolve(__dirname, '../../src/delegate.js');
|
|
21
|
+
|
|
22
|
+
jest.unstable_mockModule(probeAgentPath, () => ({
|
|
23
|
+
ProbeAgent: MockProbeAgent
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
// Import after mocking
|
|
27
|
+
const { delegate, cleanupDelegationManager, getDelegationStats } = await import(delegatePath);
|
|
28
|
+
|
|
29
|
+
describe('Delegate Tool Security and Limits (SDK-based)', () => {
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
// Clear previous mocks
|
|
32
|
+
jest.clearAllMocks();
|
|
33
|
+
|
|
34
|
+
// Clean up delegation manager state (now synchronous)
|
|
35
|
+
cleanupDelegationManager();
|
|
36
|
+
|
|
37
|
+
// Mock successful response by default
|
|
38
|
+
mockAnswer.mockResolvedValue('Test response from subagent');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
// Ensure cleanup after each test (now synchronous)
|
|
44
|
+
cleanupDelegationManager();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('Recursion prevention', () => {
|
|
48
|
+
it('should create ProbeAgent with enableDelegate=false to prevent recursion', async () => {
|
|
49
|
+
const task = 'Test task';
|
|
50
|
+
|
|
51
|
+
await delegate({ task });
|
|
52
|
+
|
|
53
|
+
// Check that ProbeAgent was created with enableDelegate: false
|
|
54
|
+
expect(MockProbeAgent).toHaveBeenCalledWith(
|
|
55
|
+
expect.objectContaining({
|
|
56
|
+
enableDelegate: false
|
|
57
|
+
})
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should use code-researcher prompt for subagent', async () => {
|
|
62
|
+
const task = 'Test task';
|
|
63
|
+
|
|
64
|
+
await delegate({ task });
|
|
65
|
+
|
|
66
|
+
// Check that ProbeAgent was created with code-researcher prompt
|
|
67
|
+
expect(MockProbeAgent).toHaveBeenCalledWith(
|
|
68
|
+
expect.objectContaining({
|
|
69
|
+
promptType: 'code-researcher'
|
|
70
|
+
})
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should disable validations for faster processing', async () => {
|
|
75
|
+
const task = 'Test task';
|
|
76
|
+
|
|
77
|
+
await delegate({ task });
|
|
78
|
+
|
|
79
|
+
// Check that validations are disabled
|
|
80
|
+
expect(MockProbeAgent).toHaveBeenCalledWith(
|
|
81
|
+
expect.objectContaining({
|
|
82
|
+
disableMermaidValidation: true,
|
|
83
|
+
disableJsonValidation: true
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should pass remaining iterations to subagent', async () => {
|
|
89
|
+
const task = 'Test task';
|
|
90
|
+
|
|
91
|
+
await delegate({
|
|
92
|
+
task,
|
|
93
|
+
currentIteration: 5,
|
|
94
|
+
maxIterations: 30
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Check that maxIterations is calculated correctly (30 - 5 = 25)
|
|
98
|
+
expect(MockProbeAgent).toHaveBeenCalledWith(
|
|
99
|
+
expect.objectContaining({
|
|
100
|
+
maxIterations: 25
|
|
101
|
+
})
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should inherit path, provider, and model from parent', async () => {
|
|
106
|
+
const task = 'Test task';
|
|
107
|
+
|
|
108
|
+
await delegate({
|
|
109
|
+
task,
|
|
110
|
+
path: '/test/path',
|
|
111
|
+
provider: 'anthropic',
|
|
112
|
+
model: 'claude-3-opus'
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Check that config is inherited
|
|
116
|
+
expect(MockProbeAgent).toHaveBeenCalledWith(
|
|
117
|
+
expect.objectContaining({
|
|
118
|
+
path: '/test/path',
|
|
119
|
+
provider: 'anthropic',
|
|
120
|
+
model: 'claude-3-opus'
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('Concurrent delegation limits', () => {
|
|
127
|
+
it('should enforce global concurrent delegation limit', async () => {
|
|
128
|
+
// Make responses slow to ensure they overlap
|
|
129
|
+
mockAnswer.mockImplementation(() =>
|
|
130
|
+
new Promise(resolve => setTimeout(() => resolve('Slow response'), 50))
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// Start 3 delegations (max)
|
|
134
|
+
const task1 = delegate({ task: 'Task 1' });
|
|
135
|
+
const task2 = delegate({ task: 'Task 2' });
|
|
136
|
+
const task3 = delegate({ task: 'Task 3' });
|
|
137
|
+
|
|
138
|
+
// Wait a bit to ensure they're all active
|
|
139
|
+
await new Promise(resolve => setTimeout(resolve, 10));
|
|
140
|
+
|
|
141
|
+
// Fourth delegation should fail immediately
|
|
142
|
+
await expect(delegate({ task: 'Task 4' })).rejects.toThrow(
|
|
143
|
+
/Maximum concurrent delegations.*reached/
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Clean up - wait for all to complete
|
|
147
|
+
await Promise.allSettled([task1, task2, task3]);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should enforce per-session delegation limit', async () => {
|
|
151
|
+
// Reset to fast responses but with slight delay
|
|
152
|
+
mockAnswer.mockImplementation(() =>
|
|
153
|
+
new Promise(resolve => setTimeout(() => resolve('Response'), 10))
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const parentSessionId = 'test-session-123';
|
|
157
|
+
|
|
158
|
+
// Start delegations sequentially and wait for each to complete
|
|
159
|
+
// This tests the per-session limit without hitting global limit
|
|
160
|
+
for (let i = 0; i < 10; i++) {
|
|
161
|
+
await delegate({
|
|
162
|
+
task: `Task ${i}`,
|
|
163
|
+
parentSessionId
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 11th delegation for same session should fail due to session counter
|
|
168
|
+
// Wait a moment to ensure all previous have decremented
|
|
169
|
+
await new Promise(resolve => setTimeout(resolve, 20));
|
|
170
|
+
|
|
171
|
+
// Now try 10 more in parallel - should work (counters reset)
|
|
172
|
+
const tasks = [];
|
|
173
|
+
for (let i = 0; i < 3; i++) { // Use 3 to not hit global limit
|
|
174
|
+
tasks.push(delegate({
|
|
175
|
+
task: `Parallel Task ${i}`,
|
|
176
|
+
parentSessionId
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
await Promise.allSettled(tasks);
|
|
181
|
+
|
|
182
|
+
// Now start 3 more to fill global slots
|
|
183
|
+
const moreTasks = [];
|
|
184
|
+
for (let i = 0; i < 3; i++) {
|
|
185
|
+
moreTasks.push(delegate({
|
|
186
|
+
task: `More Task ${i}`,
|
|
187
|
+
parentSessionId
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Wait to ensure they're active
|
|
192
|
+
await new Promise(resolve => setTimeout(resolve, 5));
|
|
193
|
+
|
|
194
|
+
// This should fail due to global limit (3 concurrent max)
|
|
195
|
+
await expect(delegate({
|
|
196
|
+
task: 'Should fail',
|
|
197
|
+
parentSessionId
|
|
198
|
+
})).rejects.toThrow(
|
|
199
|
+
/Maximum concurrent delegations.*reached/
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
// Clean up
|
|
203
|
+
await Promise.allSettled(moreTasks);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should decrement counter when delegation completes successfully', async () => {
|
|
207
|
+
// Complete first delegation
|
|
208
|
+
await delegate({ task: 'Task 1' });
|
|
209
|
+
|
|
210
|
+
// Should be able to start another (counter was decremented)
|
|
211
|
+
await expect(delegate({ task: 'Task 2' })).resolves.toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should decrement counter when delegation fails', async () => {
|
|
215
|
+
// Make subagent fail
|
|
216
|
+
mockAnswer.mockRejectedValueOnce(new Error('Subagent error'));
|
|
217
|
+
|
|
218
|
+
// First delegation fails
|
|
219
|
+
await expect(delegate({ task: 'Task 1' })).rejects.toThrow();
|
|
220
|
+
|
|
221
|
+
// Counter should be decremented, so next delegation works
|
|
222
|
+
mockAnswer.mockResolvedValueOnce('Success');
|
|
223
|
+
await expect(delegate({ task: 'Task 2' })).resolves.toBeDefined();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should decrement counter on timeout', async () => {
|
|
227
|
+
// Ensure clean state
|
|
228
|
+
cleanupDelegationManager();
|
|
229
|
+
|
|
230
|
+
// Make subagent never resolve
|
|
231
|
+
mockAnswer.mockImplementation(() => new Promise(() => {}));
|
|
232
|
+
|
|
233
|
+
// First delegation times out (50ms)
|
|
234
|
+
await expect(
|
|
235
|
+
delegate({ task: 'Task 1', timeout: 0.05 })
|
|
236
|
+
).rejects.toThrow(/timed out/);
|
|
237
|
+
|
|
238
|
+
// Counter should be decremented, so next delegation works
|
|
239
|
+
mockAnswer.mockResolvedValueOnce('Success');
|
|
240
|
+
await expect(delegate({ task: 'Task 2' })).resolves.toBeDefined();
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe('Parent session tracking', () => {
|
|
245
|
+
it('should track delegations per parent session independently', async () => {
|
|
246
|
+
const session1 = 'session-1';
|
|
247
|
+
const session2 = 'session-2';
|
|
248
|
+
|
|
249
|
+
// Start delegations for both sessions
|
|
250
|
+
await delegate({ task: 'Task 1', parentSessionId: session1 });
|
|
251
|
+
await delegate({ task: 'Task 2', parentSessionId: session2 });
|
|
252
|
+
|
|
253
|
+
// Both should succeed (different sessions)
|
|
254
|
+
expect(mockAnswer).toHaveBeenCalledTimes(2);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should clean up session tracking after delegations complete', async () => {
|
|
258
|
+
const parentSessionId = 'cleanup-test';
|
|
259
|
+
|
|
260
|
+
// Complete a delegation
|
|
261
|
+
await delegate({ task: 'Task 1', parentSessionId });
|
|
262
|
+
|
|
263
|
+
// Session should be cleaned up, so can start fresh
|
|
264
|
+
await delegate({ task: 'Task 2', parentSessionId });
|
|
265
|
+
|
|
266
|
+
expect(mockAnswer).toHaveBeenCalledTimes(2);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('Timeout handling', () => {
|
|
271
|
+
it('should timeout after specified duration', async () => {
|
|
272
|
+
// Make subagent take too long
|
|
273
|
+
mockAnswer.mockImplementation(() =>
|
|
274
|
+
new Promise(resolve => setTimeout(() => resolve('Late'), 200))
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
// Should timeout at 50ms
|
|
278
|
+
await expect(
|
|
279
|
+
delegate({ task: 'Test task', timeout: 0.05 })
|
|
280
|
+
).rejects.toThrow(/timed out after 0.05 seconds/);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should complete if response comes before timeout', async () => {
|
|
284
|
+
// Make subagent respond quickly
|
|
285
|
+
mockAnswer.mockImplementation(() =>
|
|
286
|
+
new Promise(resolve => setTimeout(() => resolve('Quick response'), 10))
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// Should complete successfully with 1 second timeout
|
|
290
|
+
await expect(
|
|
291
|
+
delegate({ task: 'Test task', timeout: 1 })
|
|
292
|
+
).resolves.toBe('Quick response');
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should clear timeout when task completes successfully', async () => {
|
|
296
|
+
const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout');
|
|
297
|
+
|
|
298
|
+
mockAnswer.mockResolvedValue('Quick success');
|
|
299
|
+
|
|
300
|
+
await delegate({ task: 'Test task', timeout: 5 });
|
|
301
|
+
|
|
302
|
+
// clearTimeout should have been called
|
|
303
|
+
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
304
|
+
|
|
305
|
+
clearTimeoutSpy.mockRestore();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('should clear timeout when task fails', async () => {
|
|
309
|
+
const clearTimeoutSpy = jest.spyOn(global, 'clearTimeout');
|
|
310
|
+
|
|
311
|
+
mockAnswer.mockRejectedValue(new Error('Task error'));
|
|
312
|
+
|
|
313
|
+
await expect(delegate({ task: 'Test task', timeout: 5 })).rejects.toThrow();
|
|
314
|
+
|
|
315
|
+
// clearTimeout should have been called
|
|
316
|
+
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
317
|
+
|
|
318
|
+
clearTimeoutSpy.mockRestore();
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
describe('Error handling', () => {
|
|
323
|
+
it('should reject with clear error message when task is empty', async () => {
|
|
324
|
+
await expect(delegate({ task: '' })).rejects.toThrow(
|
|
325
|
+
/Task parameter is required/
|
|
326
|
+
);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('should reject when parentSessionId is not a string', async () => {
|
|
330
|
+
await expect(delegate({
|
|
331
|
+
task: 'Test task',
|
|
332
|
+
parentSessionId: 123 // Invalid: should be string
|
|
333
|
+
})).rejects.toThrow(
|
|
334
|
+
/parentSessionId must be a string/
|
|
335
|
+
);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should accept null or undefined parentSessionId', async () => {
|
|
339
|
+
// null should work
|
|
340
|
+
await expect(delegate({
|
|
341
|
+
task: 'Test task',
|
|
342
|
+
parentSessionId: null
|
|
343
|
+
})).resolves.toBeDefined();
|
|
344
|
+
|
|
345
|
+
// undefined should work (implicit)
|
|
346
|
+
await expect(delegate({
|
|
347
|
+
task: 'Test task'
|
|
348
|
+
})).resolves.toBeDefined();
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('should reject when subagent returns empty response', async () => {
|
|
352
|
+
mockAnswer.mockResolvedValue('');
|
|
353
|
+
|
|
354
|
+
await expect(delegate({ task: 'Test task' })).rejects.toThrow(
|
|
355
|
+
/returned empty or whitespace-only response/
|
|
356
|
+
);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('should reject when subagent returns only whitespace', async () => {
|
|
360
|
+
mockAnswer.mockResolvedValue(' \n\t ');
|
|
361
|
+
|
|
362
|
+
await expect(delegate({ task: 'Test task' })).rejects.toThrow(
|
|
363
|
+
/returned empty or whitespace-only response/
|
|
364
|
+
);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should reject when subagent returns response with null bytes', async () => {
|
|
368
|
+
mockAnswer.mockResolvedValue('Valid content\0with null bytes');
|
|
369
|
+
|
|
370
|
+
await expect(delegate({ task: 'Test task' })).rejects.toThrow(
|
|
371
|
+
/returned response containing null bytes/
|
|
372
|
+
);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('should reject when subagent returns non-string response', async () => {
|
|
376
|
+
mockAnswer.mockResolvedValue(null);
|
|
377
|
+
|
|
378
|
+
await expect(delegate({ task: 'Test task' })).rejects.toThrow(
|
|
379
|
+
/returned invalid response \(not a string\)/
|
|
380
|
+
);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
it('should propagate subagent errors with context', async () => {
|
|
384
|
+
mockAnswer.mockRejectedValue(new Error('AI provider error'));
|
|
385
|
+
|
|
386
|
+
await expect(delegate({ task: 'Test task' })).rejects.toThrow(
|
|
387
|
+
/Delegation failed: AI provider error/
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe('SDK integration', () => {
|
|
393
|
+
it('should call subagent.answer() with the task', async () => {
|
|
394
|
+
const task = 'Analyze the codebase structure';
|
|
395
|
+
|
|
396
|
+
await delegate({ task });
|
|
397
|
+
|
|
398
|
+
expect(mockAnswer).toHaveBeenCalledWith(task);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it('should return the subagent response', async () => {
|
|
402
|
+
const expectedResponse = 'Detailed analysis results';
|
|
403
|
+
mockAnswer.mockResolvedValue(expectedResponse);
|
|
404
|
+
|
|
405
|
+
const result = await delegate({ task: 'Test task' });
|
|
406
|
+
|
|
407
|
+
expect(result).toBe(expectedResponse);
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
it('should create unique session ID for each delegation', async () => {
|
|
411
|
+
await delegate({ task: 'Task 1' });
|
|
412
|
+
await delegate({ task: 'Task 2' });
|
|
413
|
+
|
|
414
|
+
// Check that two different session IDs were generated
|
|
415
|
+
const call1SessionId = MockProbeAgent.mock.calls[0][0].sessionId;
|
|
416
|
+
const call2SessionId = MockProbeAgent.mock.calls[1][0].sessionId;
|
|
417
|
+
|
|
418
|
+
expect(call1SessionId).not.toBe(call2SessionId);
|
|
419
|
+
expect(call1SessionId).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
});
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for direct content attempt_completion tool (no <result> wrapper)
|
|
3
|
+
* Tests the simplified parsing that uses entire inner content as result
|
|
4
|
+
*/
|
|
5
|
+
import { jest, describe, test, expect, beforeEach } from '@jest/globals';
|
|
6
|
+
import { parseXmlToolCallWithThinking } from '../../src/agent/tools.js';
|
|
7
|
+
|
|
8
|
+
describe('Direct Content attempt_completion Parsing', () => {
|
|
9
|
+
test('should parse simple attempt_completion with direct content', () => {
|
|
10
|
+
const xml = `<attempt_completion>
|
|
11
|
+
The authentication system has been analyzed successfully. It uses secure JWT tokens.
|
|
12
|
+
</attempt_completion>`;
|
|
13
|
+
|
|
14
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
15
|
+
|
|
16
|
+
expect(parsed).toBeDefined();
|
|
17
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
18
|
+
expect(parsed.params.result).toBe('The authentication system has been analyzed successfully. It uses secure JWT tokens.');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('should handle multiline content with formatting', () => {
|
|
22
|
+
const xml = `<attempt_completion>
|
|
23
|
+
Analysis Complete:
|
|
24
|
+
|
|
25
|
+
**Security Findings:**
|
|
26
|
+
- JWT tokens are properly signed
|
|
27
|
+
- Password hashing uses bcrypt
|
|
28
|
+
- Rate limiting is implemented
|
|
29
|
+
|
|
30
|
+
**Recommendations:**
|
|
31
|
+
1. Add 2FA support
|
|
32
|
+
2. Implement session timeouts
|
|
33
|
+
3. Add audit logging
|
|
34
|
+
</attempt_completion>`;
|
|
35
|
+
|
|
36
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
37
|
+
|
|
38
|
+
expect(parsed).toBeDefined();
|
|
39
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
40
|
+
expect(parsed.params.result).toContain('Analysis Complete:');
|
|
41
|
+
expect(parsed.params.result).toContain('**Security Findings:**');
|
|
42
|
+
expect(parsed.params.result).toContain('**Recommendations:**');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('should handle JSON content directly', () => {
|
|
46
|
+
const xml = `<attempt_completion>
|
|
47
|
+
{
|
|
48
|
+
"analysis": "The authentication system is secure",
|
|
49
|
+
"findings": [
|
|
50
|
+
"JWT tokens properly implemented",
|
|
51
|
+
"Password hashing uses bcrypt",
|
|
52
|
+
"Rate limiting active"
|
|
53
|
+
],
|
|
54
|
+
"confidence": 0.95,
|
|
55
|
+
"recommendations": [
|
|
56
|
+
{"action": "Add 2FA", "priority": "high"},
|
|
57
|
+
{"action": "Implement session timeouts", "priority": "medium"}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
</attempt_completion>`;
|
|
61
|
+
|
|
62
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
63
|
+
|
|
64
|
+
expect(parsed).toBeDefined();
|
|
65
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
66
|
+
expect(parsed.params.result).toContain('"analysis": "The authentication system is secure"');
|
|
67
|
+
expect(parsed.params.result).toContain('"confidence": 0.95');
|
|
68
|
+
expect(parsed.params.result).toContain('"recommendations"');
|
|
69
|
+
|
|
70
|
+
// Should be valid JSON
|
|
71
|
+
expect(() => JSON.parse(parsed.params.result.trim())).not.toThrow();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('should handle code blocks in content', () => {
|
|
75
|
+
const xml = `<attempt_completion>
|
|
76
|
+
I found the authentication function:
|
|
77
|
+
|
|
78
|
+
\`\`\`javascript
|
|
79
|
+
function authenticate(token) {
|
|
80
|
+
return jwt.verify(token, secret);
|
|
81
|
+
}
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
This function validates JWT tokens using the secret key.
|
|
85
|
+
</attempt_completion>`;
|
|
86
|
+
|
|
87
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
88
|
+
|
|
89
|
+
expect(parsed).toBeDefined();
|
|
90
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
91
|
+
expect(parsed.params.result).toContain('```javascript');
|
|
92
|
+
expect(parsed.params.result).toContain('function authenticate');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('should handle XML-like content without confusion', () => {
|
|
96
|
+
const xml = `<attempt_completion>
|
|
97
|
+
The config file contains: <database><host>localhost</host></database>
|
|
98
|
+
</attempt_completion>`;
|
|
99
|
+
|
|
100
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
101
|
+
|
|
102
|
+
expect(parsed).toBeDefined();
|
|
103
|
+
expect(parsed.params.result).toContain('<database><host>localhost</host></database>');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test('should handle empty content', () => {
|
|
107
|
+
const xml = `<attempt_completion></attempt_completion>`;
|
|
108
|
+
|
|
109
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
110
|
+
|
|
111
|
+
expect(parsed).toBeDefined();
|
|
112
|
+
expect(parsed.params.result).toBe('');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('should handle content with special characters', () => {
|
|
116
|
+
const xml = `<attempt_completion>
|
|
117
|
+
Found 5 files with "special" characters: @#$%^&*()[]{}|\\:";'<>?,./
|
|
118
|
+
</attempt_completion>`;
|
|
119
|
+
|
|
120
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
121
|
+
|
|
122
|
+
expect(parsed).toBeDefined();
|
|
123
|
+
expect(parsed.params.result).toContain('special');
|
|
124
|
+
expect(parsed.params.result).toContain('@#$%^&*()[]{}|\\:');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('should remove command parameter if parsed by generic logic', () => {
|
|
128
|
+
// Test the legacy compatibility where command might be parsed but should be removed
|
|
129
|
+
const xml = `<attempt_completion>
|
|
130
|
+
Task completed successfully.
|
|
131
|
+
<command>npm test</command>
|
|
132
|
+
</attempt_completion>`;
|
|
133
|
+
|
|
134
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
135
|
+
|
|
136
|
+
expect(parsed).toBeDefined();
|
|
137
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
138
|
+
|
|
139
|
+
// The entire inner content should be the result (including the command tag if present)
|
|
140
|
+
expect(parsed.params.result).toContain('Task completed successfully.');
|
|
141
|
+
expect(parsed.params.result).toContain('<command>npm test</command>');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('should preserve whitespace and formatting', () => {
|
|
145
|
+
const xml = `<attempt_completion>
|
|
146
|
+
Indented analysis:
|
|
147
|
+
- Finding 1
|
|
148
|
+
- Finding 2
|
|
149
|
+
|
|
150
|
+
Conclusion: System is secure.
|
|
151
|
+
</attempt_completion>`;
|
|
152
|
+
|
|
153
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
154
|
+
|
|
155
|
+
expect(parsed).toBeDefined();
|
|
156
|
+
expect(parsed.params.result).toContain('Indented analysis:');
|
|
157
|
+
expect(parsed.params.result).toContain(' - Finding 1');
|
|
158
|
+
expect(parsed.params.result).toContain('Conclusion: System is secure.');
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('Direct Content vs Legacy <result> Tag', () => {
|
|
163
|
+
test('should NOT parse <result> tags anymore', () => {
|
|
164
|
+
// This test ensures we no longer support the <result> wrapper
|
|
165
|
+
const xml = `<attempt_completion>
|
|
166
|
+
<result>This should be treated as part of the content, not as a parameter</result>
|
|
167
|
+
</attempt_completion>`;
|
|
168
|
+
|
|
169
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
170
|
+
|
|
171
|
+
expect(parsed).toBeDefined();
|
|
172
|
+
expect(parsed.toolName).toBe('attempt_completion');
|
|
173
|
+
|
|
174
|
+
// The <result> tags should be part of the content, not parsed as parameters
|
|
175
|
+
expect(parsed.params.result).toContain('<result>This should be treated as part of the content, not as a parameter</result>');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('should treat everything inside attempt_completion as direct content', () => {
|
|
179
|
+
const xml = `<attempt_completion>
|
|
180
|
+
<title>Security Analysis Report</title>
|
|
181
|
+
<summary>System is secure</summary>
|
|
182
|
+
<details>
|
|
183
|
+
<finding>JWT implementation correct</finding>
|
|
184
|
+
<finding>Password hashing proper</finding>
|
|
185
|
+
</details>
|
|
186
|
+
</attempt_completion>`;
|
|
187
|
+
|
|
188
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
189
|
+
|
|
190
|
+
expect(parsed).toBeDefined();
|
|
191
|
+
expect(parsed.params.result).toContain('<title>Security Analysis Report</title>');
|
|
192
|
+
expect(parsed.params.result).toContain('<summary>System is secure</summary>');
|
|
193
|
+
expect(parsed.params.result).toContain('<finding>JWT implementation correct</finding>');
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('Integration with Schema Response Flow', () => {
|
|
198
|
+
test('should handle JSON schema responses cleanly', () => {
|
|
199
|
+
const jsonResponse = `{
|
|
200
|
+
"status": "complete",
|
|
201
|
+
"analysis": "Authentication system analysis finished",
|
|
202
|
+
"findings": ["Secure JWT implementation", "Proper password hashing"],
|
|
203
|
+
"score": 95
|
|
204
|
+
}`;
|
|
205
|
+
|
|
206
|
+
const xml = `<attempt_completion>${jsonResponse}</attempt_completion>`;
|
|
207
|
+
|
|
208
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
209
|
+
|
|
210
|
+
expect(parsed).toBeDefined();
|
|
211
|
+
expect(parsed.params.result.trim()).toBe(jsonResponse);
|
|
212
|
+
|
|
213
|
+
// Should be valid JSON that can be parsed
|
|
214
|
+
const jsonData = JSON.parse(parsed.params.result.trim());
|
|
215
|
+
expect(jsonData.status).toBe('complete');
|
|
216
|
+
expect(jsonData.score).toBe(95);
|
|
217
|
+
expect(Array.isArray(jsonData.findings)).toBe(true);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test('should handle non-JSON responses for non-JSON schemas', () => {
|
|
221
|
+
const mermaidResponse = `graph TD
|
|
222
|
+
A[Authentication] --> B[JWT Validation]
|
|
223
|
+
B --> C[User Access]
|
|
224
|
+
C --> D[Protected Resource]`;
|
|
225
|
+
|
|
226
|
+
const xml = `<attempt_completion>${mermaidResponse}</attempt_completion>`;
|
|
227
|
+
|
|
228
|
+
const parsed = parseXmlToolCallWithThinking(xml);
|
|
229
|
+
|
|
230
|
+
expect(parsed).toBeDefined();
|
|
231
|
+
expect(parsed.params.result.trim()).toBe(mermaidResponse);
|
|
232
|
+
expect(parsed.params.result).toContain('graph TD');
|
|
233
|
+
expect(parsed.params.result).toContain('Authentication');
|
|
234
|
+
});
|
|
235
|
+
});
|