crackerjack 0.37.9__py3-none-any.whl → 0.45.2__py3-none-any.whl
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.
- crackerjack/README.md +19 -0
- crackerjack/__init__.py +30 -1
- crackerjack/__main__.py +342 -1263
- crackerjack/adapters/README.md +18 -0
- crackerjack/adapters/__init__.py +27 -5
- crackerjack/adapters/_output_paths.py +167 -0
- crackerjack/adapters/_qa_adapter_base.py +309 -0
- crackerjack/adapters/_tool_adapter_base.py +706 -0
- crackerjack/adapters/ai/README.md +65 -0
- crackerjack/adapters/ai/__init__.py +5 -0
- crackerjack/adapters/ai/claude.py +853 -0
- crackerjack/adapters/complexity/README.md +53 -0
- crackerjack/adapters/complexity/__init__.py +10 -0
- crackerjack/adapters/complexity/complexipy.py +641 -0
- crackerjack/adapters/dependency/__init__.py +22 -0
- crackerjack/adapters/dependency/pip_audit.py +418 -0
- crackerjack/adapters/format/README.md +72 -0
- crackerjack/adapters/format/__init__.py +11 -0
- crackerjack/adapters/format/mdformat.py +313 -0
- crackerjack/adapters/format/ruff.py +516 -0
- crackerjack/adapters/lint/README.md +47 -0
- crackerjack/adapters/lint/__init__.py +11 -0
- crackerjack/adapters/lint/codespell.py +273 -0
- crackerjack/adapters/lsp/README.md +49 -0
- crackerjack/adapters/lsp/__init__.py +27 -0
- crackerjack/adapters/{rust_tool_manager.py → lsp/_manager.py} +3 -3
- crackerjack/adapters/{skylos_adapter.py → lsp/skylos.py} +59 -7
- crackerjack/adapters/{zuban_adapter.py → lsp/zuban.py} +3 -6
- crackerjack/adapters/refactor/README.md +59 -0
- crackerjack/adapters/refactor/__init__.py +12 -0
- crackerjack/adapters/refactor/creosote.py +318 -0
- crackerjack/adapters/refactor/refurb.py +406 -0
- crackerjack/adapters/refactor/skylos.py +494 -0
- crackerjack/adapters/sast/README.md +132 -0
- crackerjack/adapters/sast/__init__.py +32 -0
- crackerjack/adapters/sast/_base.py +201 -0
- crackerjack/adapters/sast/bandit.py +423 -0
- crackerjack/adapters/sast/pyscn.py +405 -0
- crackerjack/adapters/sast/semgrep.py +241 -0
- crackerjack/adapters/security/README.md +111 -0
- crackerjack/adapters/security/__init__.py +17 -0
- crackerjack/adapters/security/gitleaks.py +339 -0
- crackerjack/adapters/type/README.md +52 -0
- crackerjack/adapters/type/__init__.py +12 -0
- crackerjack/adapters/type/pyrefly.py +402 -0
- crackerjack/adapters/type/ty.py +402 -0
- crackerjack/adapters/type/zuban.py +522 -0
- crackerjack/adapters/utility/README.md +51 -0
- crackerjack/adapters/utility/__init__.py +10 -0
- crackerjack/adapters/utility/checks.py +884 -0
- crackerjack/agents/README.md +264 -0
- crackerjack/agents/__init__.py +40 -12
- crackerjack/agents/base.py +1 -0
- crackerjack/agents/claude_code_bridge.py +641 -0
- crackerjack/agents/coordinator.py +49 -53
- crackerjack/agents/dry_agent.py +187 -3
- crackerjack/agents/enhanced_coordinator.py +279 -0
- crackerjack/agents/enhanced_proactive_agent.py +185 -0
- crackerjack/agents/error_middleware.py +53 -0
- crackerjack/agents/formatting_agent.py +6 -8
- crackerjack/agents/helpers/__init__.py +9 -0
- crackerjack/agents/helpers/performance/__init__.py +22 -0
- crackerjack/agents/helpers/performance/performance_ast_analyzer.py +357 -0
- crackerjack/agents/helpers/performance/performance_pattern_detector.py +909 -0
- crackerjack/agents/helpers/performance/performance_recommender.py +572 -0
- crackerjack/agents/helpers/refactoring/__init__.py +22 -0
- crackerjack/agents/helpers/refactoring/code_transformer.py +536 -0
- crackerjack/agents/helpers/refactoring/complexity_analyzer.py +344 -0
- crackerjack/agents/helpers/refactoring/dead_code_detector.py +437 -0
- crackerjack/agents/helpers/test_creation/__init__.py +19 -0
- crackerjack/agents/helpers/test_creation/test_ast_analyzer.py +216 -0
- crackerjack/agents/helpers/test_creation/test_coverage_analyzer.py +643 -0
- crackerjack/agents/helpers/test_creation/test_template_generator.py +1031 -0
- crackerjack/agents/performance_agent.py +121 -1152
- crackerjack/agents/refactoring_agent.py +156 -655
- crackerjack/agents/semantic_agent.py +479 -0
- crackerjack/agents/semantic_helpers.py +356 -0
- crackerjack/agents/test_creation_agent.py +19 -1605
- crackerjack/api.py +5 -7
- crackerjack/cli/README.md +394 -0
- crackerjack/cli/__init__.py +1 -1
- crackerjack/cli/cache_handlers.py +23 -18
- crackerjack/cli/cache_handlers_enhanced.py +1 -4
- crackerjack/cli/facade.py +70 -8
- crackerjack/cli/formatting.py +13 -0
- crackerjack/cli/handlers/__init__.py +85 -0
- crackerjack/cli/handlers/advanced.py +103 -0
- crackerjack/cli/handlers/ai_features.py +62 -0
- crackerjack/cli/handlers/analytics.py +479 -0
- crackerjack/cli/handlers/changelog.py +271 -0
- crackerjack/cli/handlers/config_handlers.py +16 -0
- crackerjack/cli/handlers/coverage.py +84 -0
- crackerjack/cli/handlers/documentation.py +280 -0
- crackerjack/cli/handlers/main_handlers.py +497 -0
- crackerjack/cli/handlers/monitoring.py +371 -0
- crackerjack/cli/handlers.py +249 -49
- crackerjack/cli/interactive.py +8 -5
- crackerjack/cli/options.py +203 -110
- crackerjack/cli/semantic_handlers.py +292 -0
- crackerjack/cli/version.py +19 -0
- crackerjack/code_cleaner.py +60 -24
- crackerjack/config/README.md +472 -0
- crackerjack/config/__init__.py +256 -0
- crackerjack/config/global_lock_config.py +191 -54
- crackerjack/config/hooks.py +188 -16
- crackerjack/config/loader.py +239 -0
- crackerjack/config/settings.py +141 -0
- crackerjack/config/tool_commands.py +331 -0
- crackerjack/core/README.md +393 -0
- crackerjack/core/async_workflow_orchestrator.py +79 -53
- crackerjack/core/autofix_coordinator.py +22 -9
- crackerjack/core/container.py +10 -9
- crackerjack/core/enhanced_container.py +9 -9
- crackerjack/core/performance.py +1 -1
- crackerjack/core/performance_monitor.py +5 -3
- crackerjack/core/phase_coordinator.py +1018 -634
- crackerjack/core/proactive_workflow.py +3 -3
- crackerjack/core/retry.py +275 -0
- crackerjack/core/service_watchdog.py +167 -23
- crackerjack/core/session_coordinator.py +187 -382
- crackerjack/core/timeout_manager.py +161 -44
- crackerjack/core/workflow/__init__.py +21 -0
- crackerjack/core/workflow/workflow_ai_coordinator.py +863 -0
- crackerjack/core/workflow/workflow_event_orchestrator.py +1107 -0
- crackerjack/core/workflow/workflow_issue_parser.py +714 -0
- crackerjack/core/workflow/workflow_phase_executor.py +1158 -0
- crackerjack/core/workflow/workflow_security_gates.py +400 -0
- crackerjack/core/workflow_orchestrator.py +1247 -953
- crackerjack/data/README.md +11 -0
- crackerjack/data/__init__.py +8 -0
- crackerjack/data/models.py +79 -0
- crackerjack/data/repository.py +210 -0
- crackerjack/decorators/README.md +180 -0
- crackerjack/decorators/__init__.py +35 -0
- crackerjack/decorators/error_handling.py +649 -0
- crackerjack/decorators/error_handling_decorators.py +334 -0
- crackerjack/decorators/helpers.py +58 -0
- crackerjack/decorators/patterns.py +281 -0
- crackerjack/decorators/utils.py +58 -0
- crackerjack/docs/README.md +11 -0
- crackerjack/docs/generated/api/CLI_REFERENCE.md +1 -1
- crackerjack/documentation/README.md +11 -0
- crackerjack/documentation/ai_templates.py +1 -1
- crackerjack/documentation/dual_output_generator.py +11 -9
- crackerjack/documentation/reference_generator.py +104 -59
- crackerjack/dynamic_config.py +52 -61
- crackerjack/errors.py +1 -1
- crackerjack/events/README.md +11 -0
- crackerjack/events/__init__.py +16 -0
- crackerjack/events/telemetry.py +175 -0
- crackerjack/events/workflow_bus.py +346 -0
- crackerjack/exceptions/README.md +301 -0
- crackerjack/exceptions/__init__.py +5 -0
- crackerjack/exceptions/config.py +4 -0
- crackerjack/exceptions/tool_execution_error.py +245 -0
- crackerjack/executors/README.md +591 -0
- crackerjack/executors/__init__.py +2 -0
- crackerjack/executors/async_hook_executor.py +539 -77
- crackerjack/executors/cached_hook_executor.py +3 -3
- crackerjack/executors/hook_executor.py +967 -102
- crackerjack/executors/hook_lock_manager.py +31 -22
- crackerjack/executors/individual_hook_executor.py +66 -32
- crackerjack/executors/lsp_aware_hook_executor.py +136 -57
- crackerjack/executors/progress_hook_executor.py +282 -0
- crackerjack/executors/tool_proxy.py +23 -7
- crackerjack/hooks/README.md +485 -0
- crackerjack/hooks/lsp_hook.py +8 -9
- crackerjack/intelligence/README.md +557 -0
- crackerjack/interactive.py +37 -10
- crackerjack/managers/README.md +369 -0
- crackerjack/managers/async_hook_manager.py +41 -57
- crackerjack/managers/hook_manager.py +449 -79
- crackerjack/managers/publish_manager.py +81 -36
- crackerjack/managers/test_command_builder.py +290 -12
- crackerjack/managers/test_executor.py +93 -8
- crackerjack/managers/test_manager.py +1082 -75
- crackerjack/managers/test_progress.py +118 -26
- crackerjack/mcp/README.md +374 -0
- crackerjack/mcp/cache.py +25 -2
- crackerjack/mcp/client_runner.py +35 -18
- crackerjack/mcp/context.py +9 -9
- crackerjack/mcp/dashboard.py +24 -8
- crackerjack/mcp/enhanced_progress_monitor.py +34 -23
- crackerjack/mcp/file_monitor.py +27 -6
- crackerjack/mcp/progress_components.py +45 -34
- crackerjack/mcp/progress_monitor.py +6 -9
- crackerjack/mcp/rate_limiter.py +11 -7
- crackerjack/mcp/server.py +2 -0
- crackerjack/mcp/server_core.py +187 -55
- crackerjack/mcp/service_watchdog.py +12 -9
- crackerjack/mcp/task_manager.py +2 -2
- crackerjack/mcp/tools/README.md +27 -0
- crackerjack/mcp/tools/__init__.py +2 -0
- crackerjack/mcp/tools/core_tools.py +75 -52
- crackerjack/mcp/tools/execution_tools.py +87 -31
- crackerjack/mcp/tools/intelligence_tools.py +2 -2
- crackerjack/mcp/tools/proactive_tools.py +1 -1
- crackerjack/mcp/tools/semantic_tools.py +584 -0
- crackerjack/mcp/tools/utility_tools.py +180 -132
- crackerjack/mcp/tools/workflow_executor.py +87 -46
- crackerjack/mcp/websocket/README.md +31 -0
- crackerjack/mcp/websocket/app.py +11 -1
- crackerjack/mcp/websocket/event_bridge.py +188 -0
- crackerjack/mcp/websocket/jobs.py +27 -4
- crackerjack/mcp/websocket/monitoring/__init__.py +25 -0
- crackerjack/mcp/websocket/monitoring/api/__init__.py +19 -0
- crackerjack/mcp/websocket/monitoring/api/dependencies.py +141 -0
- crackerjack/mcp/websocket/monitoring/api/heatmap.py +154 -0
- crackerjack/mcp/websocket/monitoring/api/intelligence.py +199 -0
- crackerjack/mcp/websocket/monitoring/api/metrics.py +203 -0
- crackerjack/mcp/websocket/monitoring/api/telemetry.py +101 -0
- crackerjack/mcp/websocket/monitoring/dashboard.py +18 -0
- crackerjack/mcp/websocket/monitoring/factory.py +109 -0
- crackerjack/mcp/websocket/monitoring/filters.py +10 -0
- crackerjack/mcp/websocket/monitoring/metrics.py +64 -0
- crackerjack/mcp/websocket/monitoring/models.py +90 -0
- crackerjack/mcp/websocket/monitoring/utils.py +171 -0
- crackerjack/mcp/websocket/monitoring/websocket_manager.py +78 -0
- crackerjack/mcp/websocket/monitoring/websockets/__init__.py +17 -0
- crackerjack/mcp/websocket/monitoring/websockets/dependencies.py +126 -0
- crackerjack/mcp/websocket/monitoring/websockets/heatmap.py +176 -0
- crackerjack/mcp/websocket/monitoring/websockets/intelligence.py +291 -0
- crackerjack/mcp/websocket/monitoring/websockets/metrics.py +291 -0
- crackerjack/mcp/websocket/monitoring_endpoints.py +16 -2930
- crackerjack/mcp/websocket/server.py +1 -3
- crackerjack/mcp/websocket/websocket_handler.py +107 -6
- crackerjack/models/README.md +308 -0
- crackerjack/models/__init__.py +10 -1
- crackerjack/models/config.py +639 -22
- crackerjack/models/config_adapter.py +6 -6
- crackerjack/models/protocols.py +1167 -23
- crackerjack/models/pydantic_models.py +320 -0
- crackerjack/models/qa_config.py +145 -0
- crackerjack/models/qa_results.py +134 -0
- crackerjack/models/results.py +35 -0
- crackerjack/models/semantic_models.py +258 -0
- crackerjack/models/task.py +19 -3
- crackerjack/models/test_models.py +60 -0
- crackerjack/monitoring/README.md +11 -0
- crackerjack/monitoring/ai_agent_watchdog.py +5 -4
- crackerjack/monitoring/metrics_collector.py +4 -3
- crackerjack/monitoring/regression_prevention.py +4 -3
- crackerjack/monitoring/websocket_server.py +4 -241
- crackerjack/orchestration/README.md +340 -0
- crackerjack/orchestration/__init__.py +43 -0
- crackerjack/orchestration/advanced_orchestrator.py +20 -67
- crackerjack/orchestration/cache/README.md +312 -0
- crackerjack/orchestration/cache/__init__.py +37 -0
- crackerjack/orchestration/cache/memory_cache.py +338 -0
- crackerjack/orchestration/cache/tool_proxy_cache.py +340 -0
- crackerjack/orchestration/config.py +297 -0
- crackerjack/orchestration/coverage_improvement.py +13 -6
- crackerjack/orchestration/execution_strategies.py +6 -6
- crackerjack/orchestration/hook_orchestrator.py +1398 -0
- crackerjack/orchestration/strategies/README.md +401 -0
- crackerjack/orchestration/strategies/__init__.py +39 -0
- crackerjack/orchestration/strategies/adaptive_strategy.py +630 -0
- crackerjack/orchestration/strategies/parallel_strategy.py +237 -0
- crackerjack/orchestration/strategies/sequential_strategy.py +299 -0
- crackerjack/orchestration/test_progress_streamer.py +1 -1
- crackerjack/plugins/README.md +11 -0
- crackerjack/plugins/hooks.py +3 -2
- crackerjack/plugins/loader.py +3 -3
- crackerjack/plugins/managers.py +1 -1
- crackerjack/py313.py +191 -0
- crackerjack/security/README.md +11 -0
- crackerjack/services/README.md +374 -0
- crackerjack/services/__init__.py +8 -21
- crackerjack/services/ai/README.md +295 -0
- crackerjack/services/ai/__init__.py +7 -0
- crackerjack/services/ai/advanced_optimizer.py +878 -0
- crackerjack/services/{contextual_ai_assistant.py → ai/contextual_ai_assistant.py} +5 -3
- crackerjack/services/ai/embeddings.py +444 -0
- crackerjack/services/ai/intelligent_commit.py +328 -0
- crackerjack/services/ai/predictive_analytics.py +510 -0
- crackerjack/services/api_extractor.py +5 -3
- crackerjack/services/bounded_status_operations.py +45 -5
- crackerjack/services/cache.py +249 -318
- crackerjack/services/changelog_automation.py +7 -3
- crackerjack/services/command_execution_service.py +305 -0
- crackerjack/services/config_integrity.py +83 -39
- crackerjack/services/config_merge.py +9 -6
- crackerjack/services/config_service.py +198 -0
- crackerjack/services/config_template.py +13 -26
- crackerjack/services/coverage_badge_service.py +6 -4
- crackerjack/services/coverage_ratchet.py +53 -27
- crackerjack/services/debug.py +18 -7
- crackerjack/services/dependency_analyzer.py +4 -4
- crackerjack/services/dependency_monitor.py +13 -13
- crackerjack/services/documentation_generator.py +4 -2
- crackerjack/services/documentation_service.py +62 -33
- crackerjack/services/enhanced_filesystem.py +81 -27
- crackerjack/services/enterprise_optimizer.py +1 -1
- crackerjack/services/error_pattern_analyzer.py +10 -10
- crackerjack/services/file_filter.py +221 -0
- crackerjack/services/file_hasher.py +5 -7
- crackerjack/services/file_io_service.py +361 -0
- crackerjack/services/file_modifier.py +615 -0
- crackerjack/services/filesystem.py +80 -109
- crackerjack/services/git.py +99 -5
- crackerjack/services/health_metrics.py +4 -6
- crackerjack/services/heatmap_generator.py +12 -3
- crackerjack/services/incremental_executor.py +380 -0
- crackerjack/services/initialization.py +101 -49
- crackerjack/services/log_manager.py +2 -2
- crackerjack/services/logging.py +120 -68
- crackerjack/services/lsp_client.py +12 -12
- crackerjack/services/memory_optimizer.py +27 -22
- crackerjack/services/monitoring/README.md +30 -0
- crackerjack/services/monitoring/__init__.py +9 -0
- crackerjack/services/monitoring/dependency_monitor.py +678 -0
- crackerjack/services/monitoring/error_pattern_analyzer.py +676 -0
- crackerjack/services/monitoring/health_metrics.py +716 -0
- crackerjack/services/monitoring/metrics.py +587 -0
- crackerjack/services/{performance_benchmarks.py → monitoring/performance_benchmarks.py} +100 -14
- crackerjack/services/{performance_cache.py → monitoring/performance_cache.py} +21 -15
- crackerjack/services/{performance_monitor.py → monitoring/performance_monitor.py} +10 -6
- crackerjack/services/parallel_executor.py +166 -55
- crackerjack/services/patterns/__init__.py +142 -0
- crackerjack/services/patterns/agents.py +107 -0
- crackerjack/services/patterns/code/__init__.py +15 -0
- crackerjack/services/patterns/code/detection.py +118 -0
- crackerjack/services/patterns/code/imports.py +107 -0
- crackerjack/services/patterns/code/paths.py +159 -0
- crackerjack/services/patterns/code/performance.py +119 -0
- crackerjack/services/patterns/code/replacement.py +36 -0
- crackerjack/services/patterns/core.py +212 -0
- crackerjack/services/patterns/documentation/__init__.py +14 -0
- crackerjack/services/patterns/documentation/badges_markdown.py +96 -0
- crackerjack/services/patterns/documentation/comments_blocks.py +83 -0
- crackerjack/services/patterns/documentation/docstrings.py +89 -0
- crackerjack/services/patterns/formatting.py +226 -0
- crackerjack/services/patterns/operations.py +339 -0
- crackerjack/services/patterns/security/__init__.py +23 -0
- crackerjack/services/patterns/security/code_injection.py +122 -0
- crackerjack/services/patterns/security/credentials.py +190 -0
- crackerjack/services/patterns/security/path_traversal.py +221 -0
- crackerjack/services/patterns/security/unsafe_operations.py +216 -0
- crackerjack/services/patterns/templates.py +62 -0
- crackerjack/services/patterns/testing/__init__.py +18 -0
- crackerjack/services/patterns/testing/error_patterns.py +107 -0
- crackerjack/services/patterns/testing/pytest_output.py +126 -0
- crackerjack/services/patterns/tool_output/__init__.py +16 -0
- crackerjack/services/patterns/tool_output/bandit.py +72 -0
- crackerjack/services/patterns/tool_output/other.py +97 -0
- crackerjack/services/patterns/tool_output/pyright.py +67 -0
- crackerjack/services/patterns/tool_output/ruff.py +44 -0
- crackerjack/services/patterns/url_sanitization.py +114 -0
- crackerjack/services/patterns/utilities.py +42 -0
- crackerjack/services/patterns/utils.py +339 -0
- crackerjack/services/patterns/validation.py +46 -0
- crackerjack/services/patterns/versioning.py +62 -0
- crackerjack/services/predictive_analytics.py +21 -8
- crackerjack/services/profiler.py +280 -0
- crackerjack/services/quality/README.md +415 -0
- crackerjack/services/quality/__init__.py +11 -0
- crackerjack/services/quality/anomaly_detector.py +392 -0
- crackerjack/services/quality/pattern_cache.py +333 -0
- crackerjack/services/quality/pattern_detector.py +479 -0
- crackerjack/services/quality/qa_orchestrator.py +491 -0
- crackerjack/services/{quality_baseline.py → quality/quality_baseline.py} +163 -2
- crackerjack/services/{quality_baseline_enhanced.py → quality/quality_baseline_enhanced.py} +4 -1
- crackerjack/services/{quality_intelligence.py → quality/quality_intelligence.py} +180 -16
- crackerjack/services/regex_patterns.py +58 -2987
- crackerjack/services/regex_utils.py +55 -29
- crackerjack/services/secure_status_formatter.py +42 -15
- crackerjack/services/secure_subprocess.py +35 -2
- crackerjack/services/security.py +16 -8
- crackerjack/services/server_manager.py +40 -51
- crackerjack/services/smart_scheduling.py +46 -6
- crackerjack/services/status_authentication.py +3 -3
- crackerjack/services/thread_safe_status_collector.py +1 -0
- crackerjack/services/tool_filter.py +368 -0
- crackerjack/services/tool_version_service.py +9 -5
- crackerjack/services/unified_config.py +43 -351
- crackerjack/services/vector_store.py +689 -0
- crackerjack/services/version_analyzer.py +6 -4
- crackerjack/services/version_checker.py +14 -8
- crackerjack/services/zuban_lsp_service.py +5 -4
- crackerjack/slash_commands/README.md +11 -0
- crackerjack/slash_commands/init.md +2 -12
- crackerjack/slash_commands/run.md +84 -50
- crackerjack/tools/README.md +11 -0
- crackerjack/tools/__init__.py +30 -0
- crackerjack/tools/_git_utils.py +105 -0
- crackerjack/tools/check_added_large_files.py +139 -0
- crackerjack/tools/check_ast.py +105 -0
- crackerjack/tools/check_json.py +103 -0
- crackerjack/tools/check_jsonschema.py +297 -0
- crackerjack/tools/check_toml.py +103 -0
- crackerjack/tools/check_yaml.py +110 -0
- crackerjack/tools/codespell_wrapper.py +72 -0
- crackerjack/tools/end_of_file_fixer.py +202 -0
- crackerjack/tools/format_json.py +128 -0
- crackerjack/tools/mdformat_wrapper.py +114 -0
- crackerjack/tools/trailing_whitespace.py +198 -0
- crackerjack/tools/validate_regex_patterns.py +7 -3
- crackerjack/ui/README.md +11 -0
- crackerjack/ui/dashboard_renderer.py +28 -0
- crackerjack/ui/templates/README.md +11 -0
- crackerjack/utils/console_utils.py +13 -0
- crackerjack/utils/dependency_guard.py +230 -0
- crackerjack/utils/retry_utils.py +275 -0
- crackerjack/workflows/README.md +590 -0
- crackerjack/workflows/__init__.py +46 -0
- crackerjack/workflows/actions.py +811 -0
- crackerjack/workflows/auto_fix.py +444 -0
- crackerjack/workflows/container_builder.py +499 -0
- crackerjack/workflows/definitions.py +443 -0
- crackerjack/workflows/engine.py +177 -0
- crackerjack/workflows/event_bridge.py +242 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/METADATA +678 -98
- crackerjack-0.45.2.dist-info/RECORD +478 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/WHEEL +1 -1
- crackerjack/managers/test_manager_backup.py +0 -1075
- crackerjack/mcp/tools/execution_tools_backup.py +0 -1011
- crackerjack/mixins/__init__.py +0 -3
- crackerjack/mixins/error_handling.py +0 -145
- crackerjack/services/config.py +0 -358
- crackerjack/ui/server_panels.py +0 -125
- crackerjack-0.37.9.dist-info/RECORD +0 -231
- /crackerjack/adapters/{rust_tool_adapter.py → lsp/_base.py} +0 -0
- /crackerjack/adapters/{lsp_client.py → lsp/_client.py} +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.37.9.dist-info → crackerjack-0.45.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,584 @@
|
|
|
1
|
+
"""Semantic search and vector store MCP tools for AI agent integration."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import typing as t
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from crackerjack.models.semantic_models import SearchQuery, SemanticConfig
|
|
8
|
+
from crackerjack.services.ai.embeddings import EmbeddingService
|
|
9
|
+
from crackerjack.services.input_validator import get_input_validator
|
|
10
|
+
from crackerjack.services.vector_store import VectorStore
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_persistent_db_path() -> Path:
|
|
14
|
+
"""Get the path to the persistent semantic search database."""
|
|
15
|
+
db_path = Path.cwd() / ".crackerjack" / "semantic_index.db"
|
|
16
|
+
db_path.parent.mkdir(exist_ok=True)
|
|
17
|
+
return db_path
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_semantic_tools(mcp_app: t.Any) -> None:
|
|
21
|
+
"""Register all semantic search tools with the MCP server."""
|
|
22
|
+
_register_index_file_tool(mcp_app)
|
|
23
|
+
_register_search_semantic_tool(mcp_app)
|
|
24
|
+
_register_get_semantic_stats_tool(mcp_app)
|
|
25
|
+
_register_remove_file_from_index_tool(mcp_app)
|
|
26
|
+
_register_get_embeddings_tool(mcp_app)
|
|
27
|
+
_register_calculate_similarity_tool(mcp_app)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _register_index_file_tool(mcp_app: t.Any) -> None:
|
|
31
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
32
|
+
async def index_file_semantic(
|
|
33
|
+
file_path: str,
|
|
34
|
+
config_json: str = "",
|
|
35
|
+
) -> str:
|
|
36
|
+
"""Index a file for semantic search.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
file_path: Path to the file to index
|
|
40
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
JSON string with indexing results
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
validator = get_input_validator()
|
|
47
|
+
|
|
48
|
+
# Validate file path
|
|
49
|
+
path_result = validator.validate_file_path(file_path)
|
|
50
|
+
if not path_result.valid:
|
|
51
|
+
return json.dumps(
|
|
52
|
+
{
|
|
53
|
+
"success": False,
|
|
54
|
+
"error": f"Invalid file path: {path_result.error_message}",
|
|
55
|
+
"validation_type": path_result.validation_type,
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
file_path_obj = Path(path_result.sanitized_value or file_path)
|
|
60
|
+
|
|
61
|
+
# Parse configuration
|
|
62
|
+
config = _parse_semantic_config(config_json)
|
|
63
|
+
if isinstance(config, str): # Error occurred
|
|
64
|
+
return config
|
|
65
|
+
|
|
66
|
+
# Initialize vector store with persistent database
|
|
67
|
+
vector_store = VectorStore(config, db_path=_get_persistent_db_path())
|
|
68
|
+
|
|
69
|
+
# Index the file
|
|
70
|
+
embeddings = vector_store.index_file(file_path_obj)
|
|
71
|
+
|
|
72
|
+
return json.dumps(
|
|
73
|
+
{
|
|
74
|
+
"success": True,
|
|
75
|
+
"chunks_processed": len(embeddings),
|
|
76
|
+
"file_path": str(file_path_obj),
|
|
77
|
+
"embedding_dimension": config.embedding_dimension,
|
|
78
|
+
"message": f"Successfully indexed {len(embeddings)} chunks from {file_path_obj.name}",
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
return json.dumps(
|
|
84
|
+
{
|
|
85
|
+
"success": False,
|
|
86
|
+
"error": f"Failed to index file: {e}",
|
|
87
|
+
"file_path": file_path,
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _register_search_semantic_tool(mcp_app: t.Any) -> None:
|
|
93
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
94
|
+
async def search_semantic(
|
|
95
|
+
query: str,
|
|
96
|
+
max_results: int = 10,
|
|
97
|
+
min_similarity: float = 0.7,
|
|
98
|
+
file_types: str = "",
|
|
99
|
+
config_json: str = "",
|
|
100
|
+
) -> str:
|
|
101
|
+
"""Perform semantic search across indexed files.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
query: The search query text
|
|
105
|
+
max_results: Maximum number of results to return (1-100)
|
|
106
|
+
min_similarity: Minimum similarity threshold (0.0-1.0)
|
|
107
|
+
file_types: Comma-separated list of file types to filter by
|
|
108
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
JSON string with search results
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
# Validate query
|
|
115
|
+
sanitized_query, query_error = _validate_search_query(query)
|
|
116
|
+
if query_error:
|
|
117
|
+
return _create_error_response(
|
|
118
|
+
query_error,
|
|
119
|
+
validation_type="query_validation",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Validate parameters
|
|
123
|
+
param_error = _validate_search_parameters(max_results, min_similarity)
|
|
124
|
+
if param_error:
|
|
125
|
+
return _create_error_response(param_error)
|
|
126
|
+
|
|
127
|
+
# Parse file types and configuration
|
|
128
|
+
file_types_list = _parse_file_types(file_types)
|
|
129
|
+
config = _parse_semantic_config(config_json)
|
|
130
|
+
if isinstance(config, str): # Error occurred
|
|
131
|
+
return config
|
|
132
|
+
|
|
133
|
+
# Create search query and execute search
|
|
134
|
+
search_query = SearchQuery(
|
|
135
|
+
query=sanitized_query,
|
|
136
|
+
max_results=max_results,
|
|
137
|
+
min_similarity=min_similarity,
|
|
138
|
+
file_types=file_types_list,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
vector_store = VectorStore(config, db_path=_get_persistent_db_path())
|
|
142
|
+
results = vector_store.search(search_query)
|
|
143
|
+
|
|
144
|
+
# Format and return results
|
|
145
|
+
response_data = _format_search_results(
|
|
146
|
+
results, sanitized_query, max_results, min_similarity
|
|
147
|
+
)
|
|
148
|
+
return json.dumps(response_data)
|
|
149
|
+
|
|
150
|
+
except Exception as e:
|
|
151
|
+
return _create_error_response(
|
|
152
|
+
f"Failed to perform semantic search: {e}",
|
|
153
|
+
query=query,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _register_get_semantic_stats_tool(mcp_app: t.Any) -> None:
|
|
158
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
159
|
+
async def get_semantic_stats(config_json: str = "") -> str:
|
|
160
|
+
"""Get statistics about the semantic search index.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
JSON string with index statistics
|
|
167
|
+
"""
|
|
168
|
+
try:
|
|
169
|
+
# Parse configuration
|
|
170
|
+
config = _parse_semantic_config(config_json)
|
|
171
|
+
if isinstance(config, str): # Error occurred
|
|
172
|
+
return config
|
|
173
|
+
|
|
174
|
+
# Initialize vector store and get stats
|
|
175
|
+
vector_store = VectorStore(config, db_path=_get_persistent_db_path())
|
|
176
|
+
stats = vector_store.get_stats()
|
|
177
|
+
|
|
178
|
+
return json.dumps(
|
|
179
|
+
{
|
|
180
|
+
"success": True,
|
|
181
|
+
"total_files": stats.total_files,
|
|
182
|
+
"total_chunks": stats.total_chunks,
|
|
183
|
+
"index_size_mb": stats.index_size_mb,
|
|
184
|
+
"average_chunks_per_file": round(
|
|
185
|
+
stats.total_chunks / stats.total_files, 2
|
|
186
|
+
)
|
|
187
|
+
if stats.total_files > 0
|
|
188
|
+
else 0.0,
|
|
189
|
+
"embedding_model": config.embedding_model,
|
|
190
|
+
"embedding_dimension": config.embedding_dimension,
|
|
191
|
+
"last_updated": stats.last_updated.isoformat()
|
|
192
|
+
if stats.last_updated
|
|
193
|
+
else None,
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
return json.dumps(
|
|
199
|
+
{
|
|
200
|
+
"success": False,
|
|
201
|
+
"error": f"Failed to get semantic stats: {e}",
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _register_remove_file_from_index_tool(mcp_app: t.Any) -> None:
|
|
207
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
208
|
+
async def remove_file_from_semantic_index(
|
|
209
|
+
file_path: str,
|
|
210
|
+
config_json: str = "",
|
|
211
|
+
) -> str:
|
|
212
|
+
"""Remove a file from the semantic search index.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
file_path: Path to the file to remove
|
|
216
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
JSON string with removal results
|
|
220
|
+
"""
|
|
221
|
+
try:
|
|
222
|
+
validator = get_input_validator()
|
|
223
|
+
|
|
224
|
+
# Validate file path
|
|
225
|
+
path_result = validator.validate_file_path(file_path)
|
|
226
|
+
if not path_result.valid:
|
|
227
|
+
return json.dumps(
|
|
228
|
+
{
|
|
229
|
+
"success": False,
|
|
230
|
+
"error": f"Invalid file path: {path_result.error_message}",
|
|
231
|
+
"validation_type": path_result.validation_type,
|
|
232
|
+
}
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
file_path_obj = Path(path_result.sanitized_value or file_path)
|
|
236
|
+
|
|
237
|
+
# Parse configuration
|
|
238
|
+
config = _parse_semantic_config(config_json)
|
|
239
|
+
if isinstance(config, str): # Error occurred
|
|
240
|
+
return config
|
|
241
|
+
|
|
242
|
+
# Initialize vector store and remove file
|
|
243
|
+
vector_store = VectorStore(config, db_path=_get_persistent_db_path())
|
|
244
|
+
success = vector_store.remove_file(file_path_obj)
|
|
245
|
+
|
|
246
|
+
return json.dumps(
|
|
247
|
+
{
|
|
248
|
+
"success": success,
|
|
249
|
+
"file_path": str(file_path_obj),
|
|
250
|
+
"message": f"{'Successfully removed' if success else 'Failed to remove'} {file_path_obj.name} from index",
|
|
251
|
+
}
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
except Exception as e:
|
|
255
|
+
return json.dumps(
|
|
256
|
+
{
|
|
257
|
+
"success": False,
|
|
258
|
+
"error": f"Failed to remove file: {e}",
|
|
259
|
+
"file_path": file_path,
|
|
260
|
+
}
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _register_get_embeddings_tool(mcp_app: t.Any) -> None:
|
|
265
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
266
|
+
async def get_embeddings(
|
|
267
|
+
texts: str,
|
|
268
|
+
config_json: str = "",
|
|
269
|
+
) -> str:
|
|
270
|
+
"""Generate embeddings for given texts.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
texts: JSON array of texts to generate embeddings for
|
|
274
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
JSON string with embeddings
|
|
278
|
+
"""
|
|
279
|
+
try:
|
|
280
|
+
# Parse and validate input texts
|
|
281
|
+
texts_list, parse_error = _parse_texts_input(texts)
|
|
282
|
+
if parse_error:
|
|
283
|
+
return parse_error
|
|
284
|
+
|
|
285
|
+
# Parse configuration
|
|
286
|
+
config = _parse_semantic_config(config_json)
|
|
287
|
+
if isinstance(config, str): # Error occurred
|
|
288
|
+
return config
|
|
289
|
+
|
|
290
|
+
# Generate embeddings
|
|
291
|
+
embeddings = _generate_embeddings_for_texts(texts_list, config)
|
|
292
|
+
|
|
293
|
+
return _format_embeddings_response(texts_list, embeddings)
|
|
294
|
+
|
|
295
|
+
except Exception as e:
|
|
296
|
+
return json.dumps(
|
|
297
|
+
{
|
|
298
|
+
"success": False,
|
|
299
|
+
"error": f"Failed to generate embeddings: {e}",
|
|
300
|
+
}
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def _register_calculate_similarity_tool(mcp_app: t.Any) -> None:
|
|
305
|
+
@mcp_app.tool() # type: ignore[misc]
|
|
306
|
+
async def calculate_similarity_semantic(
|
|
307
|
+
embedding1: str,
|
|
308
|
+
embedding2: str,
|
|
309
|
+
config_json: str = "",
|
|
310
|
+
) -> str:
|
|
311
|
+
"""Calculate cosine similarity between two embeddings.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
embedding1: JSON array representing first embedding vector
|
|
315
|
+
embedding2: JSON array representing second embedding vector
|
|
316
|
+
config_json: Optional JSON configuration for semantic search settings
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
JSON string with similarity score
|
|
320
|
+
"""
|
|
321
|
+
try:
|
|
322
|
+
# Parse embeddings
|
|
323
|
+
try:
|
|
324
|
+
emb1 = json.loads(embedding1)
|
|
325
|
+
emb2 = json.loads(embedding2)
|
|
326
|
+
|
|
327
|
+
if not (isinstance(emb1, list) and isinstance(emb2, list)):
|
|
328
|
+
return json.dumps(
|
|
329
|
+
{
|
|
330
|
+
"success": False,
|
|
331
|
+
"error": "Both embeddings must be JSON arrays",
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
except json.JSONDecodeError as e:
|
|
335
|
+
return json.dumps(
|
|
336
|
+
{
|
|
337
|
+
"success": False,
|
|
338
|
+
"error": f"Invalid JSON for embeddings: {e}",
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Parse configuration
|
|
343
|
+
config = _parse_semantic_config(config_json)
|
|
344
|
+
if isinstance(config, str): # Error occurred
|
|
345
|
+
return config
|
|
346
|
+
|
|
347
|
+
# Calculate similarity
|
|
348
|
+
embedding_service = EmbeddingService(config)
|
|
349
|
+
similarity = embedding_service.calculate_similarity(emb1, emb2)
|
|
350
|
+
|
|
351
|
+
return json.dumps(
|
|
352
|
+
{
|
|
353
|
+
"success": True,
|
|
354
|
+
"similarity_score": round(similarity, 6),
|
|
355
|
+
"embedding1_dimension": len(emb1),
|
|
356
|
+
"embedding2_dimension": len(emb2),
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
except Exception as e:
|
|
361
|
+
return json.dumps(
|
|
362
|
+
{
|
|
363
|
+
"success": False,
|
|
364
|
+
"error": f"Failed to calculate similarity: {e}",
|
|
365
|
+
}
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _create_error_response(error: str, **kwargs) -> str:
|
|
370
|
+
"""Create standardized error response JSON.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
error: Error message
|
|
374
|
+
**kwargs: Additional fields to include in response
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
JSON string with error response
|
|
378
|
+
"""
|
|
379
|
+
response = {
|
|
380
|
+
"success": False,
|
|
381
|
+
"error": error,
|
|
382
|
+
}
|
|
383
|
+
response.update(kwargs)
|
|
384
|
+
return json.dumps(response)
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def _validate_search_query(query: str) -> tuple[str, str | None]:
|
|
388
|
+
"""Validate and sanitize search query.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
query: Raw search query
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
Tuple of (sanitized_query, error_message)
|
|
395
|
+
"""
|
|
396
|
+
validator = get_input_validator()
|
|
397
|
+
query_result = validator.validate_command_args(query)
|
|
398
|
+
|
|
399
|
+
if not query_result.valid:
|
|
400
|
+
error_msg = f"Invalid query: {query_result.error_message}"
|
|
401
|
+
return "", error_msg
|
|
402
|
+
|
|
403
|
+
return query_result.sanitized_value or query, None
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def _validate_search_parameters(max_results: int, min_similarity: float) -> str | None:
|
|
407
|
+
"""Validate search parameters.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
max_results: Maximum results to return
|
|
411
|
+
min_similarity: Minimum similarity threshold
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
Error message if invalid, None if valid
|
|
415
|
+
"""
|
|
416
|
+
if not (1 <= max_results <= 100):
|
|
417
|
+
return "max_results must be between 1 and 100"
|
|
418
|
+
|
|
419
|
+
if not (0.0 <= min_similarity <= 1.0):
|
|
420
|
+
return "min_similarity must be between 0.0 and 1.0"
|
|
421
|
+
|
|
422
|
+
return None
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def _parse_file_types(file_types: str) -> list[str]:
|
|
426
|
+
"""Parse comma-separated file types string.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
file_types: Comma-separated file types
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
List of file type strings
|
|
433
|
+
"""
|
|
434
|
+
if not file_types.strip():
|
|
435
|
+
return []
|
|
436
|
+
return [ft.strip() for ft in file_types.split(",")]
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def _format_search_results(
|
|
440
|
+
results: list,
|
|
441
|
+
sanitized_query: str,
|
|
442
|
+
max_results: int,
|
|
443
|
+
min_similarity: float,
|
|
444
|
+
) -> dict:
|
|
445
|
+
"""Format search results for JSON response.
|
|
446
|
+
|
|
447
|
+
Args:
|
|
448
|
+
results: Search results from vector store
|
|
449
|
+
sanitized_query: Sanitized search query
|
|
450
|
+
max_results: Maximum results requested
|
|
451
|
+
min_similarity: Minimum similarity threshold
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
Dictionary with formatted results
|
|
455
|
+
"""
|
|
456
|
+
formatted_results = [
|
|
457
|
+
{
|
|
458
|
+
"file_path": str(result.file_path),
|
|
459
|
+
"content": result.content,
|
|
460
|
+
"similarity_score": round(result.similarity_score, 4),
|
|
461
|
+
"start_line": result.start_line,
|
|
462
|
+
"end_line": result.end_line,
|
|
463
|
+
"file_type": result.file_type,
|
|
464
|
+
"chunk_id": result.chunk_id,
|
|
465
|
+
}
|
|
466
|
+
for result in results
|
|
467
|
+
]
|
|
468
|
+
|
|
469
|
+
return {
|
|
470
|
+
"success": True,
|
|
471
|
+
"query": sanitized_query,
|
|
472
|
+
"results_count": len(results),
|
|
473
|
+
"max_results": max_results,
|
|
474
|
+
"min_similarity": min_similarity,
|
|
475
|
+
"results": formatted_results,
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def _parse_texts_input(texts: str) -> tuple[list[str], str | None]:
|
|
480
|
+
"""Parse and validate texts input.
|
|
481
|
+
|
|
482
|
+
Args:
|
|
483
|
+
texts: JSON string containing array of texts
|
|
484
|
+
|
|
485
|
+
Returns:
|
|
486
|
+
Tuple of (texts_list, error_message)
|
|
487
|
+
"""
|
|
488
|
+
try:
|
|
489
|
+
texts_list = json.loads(texts)
|
|
490
|
+
if not isinstance(texts_list, list):
|
|
491
|
+
error = json.dumps(
|
|
492
|
+
{
|
|
493
|
+
"success": False,
|
|
494
|
+
"error": "texts must be a JSON array of strings",
|
|
495
|
+
}
|
|
496
|
+
)
|
|
497
|
+
return [], error
|
|
498
|
+
return texts_list, None
|
|
499
|
+
except json.JSONDecodeError as e:
|
|
500
|
+
error = json.dumps(
|
|
501
|
+
{
|
|
502
|
+
"success": False,
|
|
503
|
+
"error": f"Invalid JSON for texts: {e}",
|
|
504
|
+
}
|
|
505
|
+
)
|
|
506
|
+
return [], error
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def _generate_embeddings_for_texts(
|
|
510
|
+
texts_list: list[str], config: SemanticConfig
|
|
511
|
+
) -> list:
|
|
512
|
+
"""Generate embeddings for a list of texts.
|
|
513
|
+
|
|
514
|
+
Args:
|
|
515
|
+
texts_list: List of texts to generate embeddings for
|
|
516
|
+
config: Semantic search configuration
|
|
517
|
+
|
|
518
|
+
Returns:
|
|
519
|
+
List of embedding vectors
|
|
520
|
+
"""
|
|
521
|
+
embedding_service = EmbeddingService(config)
|
|
522
|
+
|
|
523
|
+
if len(texts_list) == 1:
|
|
524
|
+
return [embedding_service.generate_embedding(texts_list[0])]
|
|
525
|
+
return embedding_service.generate_embeddings_batch(texts_list)
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
def _format_embeddings_response(texts_list: list[str], embeddings: list) -> str:
|
|
529
|
+
"""Format embeddings response as JSON.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
texts_list: Original list of texts
|
|
533
|
+
embeddings: Generated embeddings
|
|
534
|
+
|
|
535
|
+
Returns:
|
|
536
|
+
JSON string with formatted response
|
|
537
|
+
"""
|
|
538
|
+
return json.dumps(
|
|
539
|
+
{
|
|
540
|
+
"success": True,
|
|
541
|
+
"texts_count": len(texts_list),
|
|
542
|
+
"embedding_dimension": len(embeddings[0]) if embeddings else 0,
|
|
543
|
+
"embeddings": embeddings,
|
|
544
|
+
}
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def _parse_semantic_config(config_json: str) -> SemanticConfig | str:
|
|
549
|
+
"""Parse semantic configuration from JSON string.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
config_json: JSON configuration string
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
SemanticConfig object or error string
|
|
556
|
+
"""
|
|
557
|
+
if not config_json.strip():
|
|
558
|
+
# Use default configuration
|
|
559
|
+
return SemanticConfig(
|
|
560
|
+
embedding_model="sentence-transformers/all-MiniLM-L6-v2",
|
|
561
|
+
chunk_size=512,
|
|
562
|
+
chunk_overlap=50,
|
|
563
|
+
max_search_results=10,
|
|
564
|
+
similarity_threshold=0.7,
|
|
565
|
+
embedding_dimension=384,
|
|
566
|
+
)
|
|
567
|
+
|
|
568
|
+
try:
|
|
569
|
+
config_dict = json.loads(config_json)
|
|
570
|
+
return SemanticConfig(**config_dict)
|
|
571
|
+
except json.JSONDecodeError as e:
|
|
572
|
+
return json.dumps(
|
|
573
|
+
{
|
|
574
|
+
"success": False,
|
|
575
|
+
"error": f"Invalid JSON configuration: {e}",
|
|
576
|
+
}
|
|
577
|
+
)
|
|
578
|
+
except Exception as e:
|
|
579
|
+
return json.dumps(
|
|
580
|
+
{
|
|
581
|
+
"success": False,
|
|
582
|
+
"error": f"Invalid configuration: {e}",
|
|
583
|
+
}
|
|
584
|
+
)
|