aiecs 1.0.1__py3-none-any.whl → 1.7.6__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.
Potentially problematic release.
This version of aiecs might be problematic. Click here for more details.
- aiecs/__init__.py +13 -16
- aiecs/__main__.py +7 -7
- aiecs/aiecs_client.py +269 -75
- aiecs/application/executors/operation_executor.py +79 -54
- aiecs/application/knowledge_graph/__init__.py +7 -0
- aiecs/application/knowledge_graph/builder/__init__.py +37 -0
- aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
- aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
- aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
- aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
- aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
- aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
- aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
- aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
- aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
- aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
- aiecs/application/knowledge_graph/extractors/base.py +98 -0
- aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
- aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
- aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
- aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
- aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
- aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
- aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
- aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
- aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
- aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
- aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
- aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
- aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
- aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
- aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
- aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
- aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
- aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
- aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
- aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
- aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
- aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
- aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
- aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
- aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
- aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
- aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
- aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
- aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
- aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
- aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
- aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
- aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
- aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
- aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
- aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
- aiecs/application/knowledge_graph/search/__init__.py +59 -0
- aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
- aiecs/application/knowledge_graph/search/reranker.py +293 -0
- aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
- aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
- aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
- aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
- aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
- aiecs/application/knowledge_graph/validators/__init__.py +13 -0
- aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
- aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
- aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
- aiecs/common/__init__.py +9 -0
- aiecs/common/knowledge_graph/__init__.py +17 -0
- aiecs/common/knowledge_graph/runnable.py +471 -0
- aiecs/config/__init__.py +20 -5
- aiecs/config/config.py +762 -31
- aiecs/config/graph_config.py +131 -0
- aiecs/config/tool_config.py +399 -0
- aiecs/core/__init__.py +29 -13
- aiecs/core/interface/__init__.py +2 -2
- aiecs/core/interface/execution_interface.py +22 -22
- aiecs/core/interface/storage_interface.py +37 -88
- aiecs/core/registry/__init__.py +31 -0
- aiecs/core/registry/service_registry.py +92 -0
- aiecs/domain/__init__.py +270 -1
- aiecs/domain/agent/__init__.py +191 -0
- aiecs/domain/agent/base_agent.py +3870 -0
- aiecs/domain/agent/exceptions.py +99 -0
- aiecs/domain/agent/graph_aware_mixin.py +569 -0
- aiecs/domain/agent/hybrid_agent.py +1435 -0
- aiecs/domain/agent/integration/__init__.py +29 -0
- aiecs/domain/agent/integration/context_compressor.py +216 -0
- aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
- aiecs/domain/agent/integration/protocols.py +281 -0
- aiecs/domain/agent/integration/retry_policy.py +218 -0
- aiecs/domain/agent/integration/role_config.py +213 -0
- aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
- aiecs/domain/agent/lifecycle.py +291 -0
- aiecs/domain/agent/llm_agent.py +692 -0
- aiecs/domain/agent/memory/__init__.py +12 -0
- aiecs/domain/agent/memory/conversation.py +1124 -0
- aiecs/domain/agent/migration/__init__.py +14 -0
- aiecs/domain/agent/migration/conversion.py +163 -0
- aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
- aiecs/domain/agent/models.py +884 -0
- aiecs/domain/agent/observability.py +479 -0
- aiecs/domain/agent/persistence.py +449 -0
- aiecs/domain/agent/prompts/__init__.py +29 -0
- aiecs/domain/agent/prompts/builder.py +159 -0
- aiecs/domain/agent/prompts/formatters.py +187 -0
- aiecs/domain/agent/prompts/template.py +255 -0
- aiecs/domain/agent/registry.py +253 -0
- aiecs/domain/agent/tool_agent.py +444 -0
- aiecs/domain/agent/tools/__init__.py +15 -0
- aiecs/domain/agent/tools/schema_generator.py +364 -0
- aiecs/domain/community/__init__.py +155 -0
- aiecs/domain/community/agent_adapter.py +469 -0
- aiecs/domain/community/analytics.py +432 -0
- aiecs/domain/community/collaborative_workflow.py +648 -0
- aiecs/domain/community/communication_hub.py +634 -0
- aiecs/domain/community/community_builder.py +320 -0
- aiecs/domain/community/community_integration.py +796 -0
- aiecs/domain/community/community_manager.py +803 -0
- aiecs/domain/community/decision_engine.py +849 -0
- aiecs/domain/community/exceptions.py +231 -0
- aiecs/domain/community/models/__init__.py +33 -0
- aiecs/domain/community/models/community_models.py +234 -0
- aiecs/domain/community/resource_manager.py +461 -0
- aiecs/domain/community/shared_context_manager.py +589 -0
- aiecs/domain/context/__init__.py +40 -10
- aiecs/domain/context/context_engine.py +1910 -0
- aiecs/domain/context/conversation_models.py +87 -53
- aiecs/domain/context/graph_memory.py +582 -0
- aiecs/domain/execution/model.py +12 -4
- aiecs/domain/knowledge_graph/__init__.py +19 -0
- aiecs/domain/knowledge_graph/models/__init__.py +52 -0
- aiecs/domain/knowledge_graph/models/entity.py +148 -0
- aiecs/domain/knowledge_graph/models/evidence.py +178 -0
- aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
- aiecs/domain/knowledge_graph/models/path.py +171 -0
- aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
- aiecs/domain/knowledge_graph/models/query.py +261 -0
- aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
- aiecs/domain/knowledge_graph/models/relation.py +202 -0
- aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
- aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
- aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
- aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
- aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
- aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
- aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
- aiecs/domain/task/dsl_processor.py +172 -56
- aiecs/domain/task/model.py +20 -8
- aiecs/domain/task/task_context.py +27 -24
- aiecs/infrastructure/__init__.py +0 -2
- aiecs/infrastructure/graph_storage/__init__.py +11 -0
- aiecs/infrastructure/graph_storage/base.py +837 -0
- aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
- aiecs/infrastructure/graph_storage/cache.py +424 -0
- aiecs/infrastructure/graph_storage/distributed.py +223 -0
- aiecs/infrastructure/graph_storage/error_handling.py +380 -0
- aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
- aiecs/infrastructure/graph_storage/health_checks.py +378 -0
- aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
- aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
- aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
- aiecs/infrastructure/graph_storage/metrics.py +344 -0
- aiecs/infrastructure/graph_storage/migration.py +400 -0
- aiecs/infrastructure/graph_storage/pagination.py +483 -0
- aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
- aiecs/infrastructure/graph_storage/postgres.py +1563 -0
- aiecs/infrastructure/graph_storage/property_storage.py +353 -0
- aiecs/infrastructure/graph_storage/protocols.py +76 -0
- aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
- aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
- aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
- aiecs/infrastructure/graph_storage/streaming.py +487 -0
- aiecs/infrastructure/graph_storage/tenant.py +412 -0
- aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
- aiecs/infrastructure/messaging/websocket_manager.py +51 -35
- aiecs/infrastructure/monitoring/__init__.py +22 -0
- aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
- aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
- aiecs/infrastructure/monitoring/structured_logger.py +3 -7
- aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
- aiecs/infrastructure/persistence/__init__.py +14 -1
- aiecs/infrastructure/persistence/context_engine_client.py +184 -0
- aiecs/infrastructure/persistence/database_manager.py +67 -43
- aiecs/infrastructure/persistence/file_storage.py +180 -103
- aiecs/infrastructure/persistence/redis_client.py +74 -21
- aiecs/llm/__init__.py +73 -25
- aiecs/llm/callbacks/__init__.py +11 -0
- aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
- aiecs/llm/client_factory.py +224 -36
- aiecs/llm/client_resolver.py +155 -0
- aiecs/llm/clients/__init__.py +38 -0
- aiecs/llm/clients/base_client.py +324 -0
- aiecs/llm/clients/google_function_calling_mixin.py +457 -0
- aiecs/llm/clients/googleai_client.py +241 -0
- aiecs/llm/clients/openai_client.py +158 -0
- aiecs/llm/clients/openai_compatible_mixin.py +367 -0
- aiecs/llm/clients/vertex_client.py +897 -0
- aiecs/llm/clients/xai_client.py +201 -0
- aiecs/llm/config/__init__.py +51 -0
- aiecs/llm/config/config_loader.py +272 -0
- aiecs/llm/config/config_validator.py +206 -0
- aiecs/llm/config/model_config.py +143 -0
- aiecs/llm/protocols.py +149 -0
- aiecs/llm/utils/__init__.py +10 -0
- aiecs/llm/utils/validate_config.py +89 -0
- aiecs/main.py +140 -121
- aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
- aiecs/scripts/aid/__init__.py +19 -0
- aiecs/scripts/aid/module_checker.py +499 -0
- aiecs/scripts/aid/version_manager.py +235 -0
- aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
- aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
- aiecs/scripts/dependance_check/__init__.py +15 -0
- aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
- aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
- aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
- aiecs/scripts/dependance_patch/__init__.py +7 -0
- aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
- aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
- aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
- aiecs/scripts/knowledge_graph/__init__.py +3 -0
- aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
- aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
- aiecs/scripts/tools_develop/README.md +671 -0
- aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
- aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
- aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
- aiecs/scripts/tools_develop/__init__.py +21 -0
- aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
- aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
- aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
- aiecs/scripts/tools_develop/schema_coverage.py +511 -0
- aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
- aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
- aiecs/scripts/tools_develop/verify_tools.py +352 -0
- aiecs/tasks/__init__.py +0 -1
- aiecs/tasks/worker.py +115 -47
- aiecs/tools/__init__.py +194 -72
- aiecs/tools/apisource/__init__.py +99 -0
- aiecs/tools/apisource/intelligence/__init__.py +19 -0
- aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
- aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
- aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
- aiecs/tools/apisource/monitoring/__init__.py +9 -0
- aiecs/tools/apisource/monitoring/metrics.py +330 -0
- aiecs/tools/apisource/providers/__init__.py +112 -0
- aiecs/tools/apisource/providers/base.py +671 -0
- aiecs/tools/apisource/providers/census.py +397 -0
- aiecs/tools/apisource/providers/fred.py +535 -0
- aiecs/tools/apisource/providers/newsapi.py +409 -0
- aiecs/tools/apisource/providers/worldbank.py +352 -0
- aiecs/tools/apisource/reliability/__init__.py +12 -0
- aiecs/tools/apisource/reliability/error_handler.py +363 -0
- aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
- aiecs/tools/apisource/tool.py +832 -0
- aiecs/tools/apisource/utils/__init__.py +9 -0
- aiecs/tools/apisource/utils/validators.py +334 -0
- aiecs/tools/base_tool.py +415 -21
- aiecs/tools/docs/__init__.py +121 -0
- aiecs/tools/docs/ai_document_orchestrator.py +607 -0
- aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
- aiecs/tools/docs/content_insertion_tool.py +1320 -0
- aiecs/tools/docs/document_creator_tool.py +1323 -0
- aiecs/tools/docs/document_layout_tool.py +1160 -0
- aiecs/tools/docs/document_parser_tool.py +1011 -0
- aiecs/tools/docs/document_writer_tool.py +1829 -0
- aiecs/tools/knowledge_graph/__init__.py +17 -0
- aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
- aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
- aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
- aiecs/tools/langchain_adapter.py +300 -138
- aiecs/tools/schema_generator.py +455 -0
- aiecs/tools/search_tool/__init__.py +100 -0
- aiecs/tools/search_tool/analyzers.py +581 -0
- aiecs/tools/search_tool/cache.py +264 -0
- aiecs/tools/search_tool/constants.py +128 -0
- aiecs/tools/search_tool/context.py +224 -0
- aiecs/tools/search_tool/core.py +778 -0
- aiecs/tools/search_tool/deduplicator.py +119 -0
- aiecs/tools/search_tool/error_handler.py +242 -0
- aiecs/tools/search_tool/metrics.py +343 -0
- aiecs/tools/search_tool/rate_limiter.py +172 -0
- aiecs/tools/search_tool/schemas.py +275 -0
- aiecs/tools/statistics/__init__.py +80 -0
- aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
- aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
- aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
- aiecs/tools/statistics/data_loader_tool.py +555 -0
- aiecs/tools/statistics/data_profiler_tool.py +638 -0
- aiecs/tools/statistics/data_transformer_tool.py +580 -0
- aiecs/tools/statistics/data_visualizer_tool.py +498 -0
- aiecs/tools/statistics/model_trainer_tool.py +507 -0
- aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
- aiecs/tools/task_tools/__init__.py +49 -36
- aiecs/tools/task_tools/chart_tool.py +200 -184
- aiecs/tools/task_tools/classfire_tool.py +268 -267
- aiecs/tools/task_tools/image_tool.py +175 -131
- aiecs/tools/task_tools/office_tool.py +226 -146
- aiecs/tools/task_tools/pandas_tool.py +477 -121
- aiecs/tools/task_tools/report_tool.py +390 -142
- aiecs/tools/task_tools/research_tool.py +149 -79
- aiecs/tools/task_tools/scraper_tool.py +339 -145
- aiecs/tools/task_tools/stats_tool.py +448 -209
- aiecs/tools/temp_file_manager.py +26 -24
- aiecs/tools/tool_executor/__init__.py +18 -16
- aiecs/tools/tool_executor/tool_executor.py +364 -52
- aiecs/utils/LLM_output_structor.py +74 -48
- aiecs/utils/__init__.py +14 -3
- aiecs/utils/base_callback.py +0 -3
- aiecs/utils/cache_provider.py +696 -0
- aiecs/utils/execution_utils.py +50 -31
- aiecs/utils/prompt_loader.py +1 -0
- aiecs/utils/token_usage_repository.py +37 -11
- aiecs/ws/socket_server.py +14 -4
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
- aiecs-1.7.6.dist-info/RECORD +337 -0
- aiecs-1.7.6.dist-info/entry_points.txt +13 -0
- aiecs/config/registry.py +0 -19
- aiecs/domain/context/content_engine.py +0 -982
- aiecs/llm/base_client.py +0 -99
- aiecs/llm/openai_client.py +0 -125
- aiecs/llm/vertex_client.py +0 -186
- aiecs/llm/xai_client.py +0 -184
- aiecs/scripts/dependency_checker.py +0 -857
- aiecs/scripts/quick_dependency_check.py +0 -269
- aiecs/tools/task_tools/search_api.py +0 -7
- aiecs-1.0.1.dist-info/RECORD +0 -90
- aiecs-1.0.1.dist-info/entry_points.txt +0 -7
- /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
- /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
- /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
- /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
- {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Error Handler for Logic Query Parser
|
|
3
|
+
|
|
4
|
+
This module provides comprehensive error handling for the Logic Query Parser,
|
|
5
|
+
including error conversion, context extraction, suggestion generation, and formatting.
|
|
6
|
+
|
|
7
|
+
Design Principles:
|
|
8
|
+
1. Two-phase error handling: Syntax (fatal) vs Semantic (accumulated)
|
|
9
|
+
2. Helpful error messages with context and suggestions
|
|
10
|
+
3. Fuzzy matching for keyword suggestions
|
|
11
|
+
4. Optional colorization for terminal output
|
|
12
|
+
|
|
13
|
+
Phase: 2.4 - Logic Query Parser
|
|
14
|
+
Task: 2.3 - Implement Error Handler
|
|
15
|
+
Version: 1.0
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from typing import Optional, List, Any, Type, cast
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
from lark import (
|
|
23
|
+
LarkError,
|
|
24
|
+
UnexpectedInput,
|
|
25
|
+
UnexpectedToken,
|
|
26
|
+
UnexpectedCharacters,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
LARK_AVAILABLE = True
|
|
30
|
+
except ImportError:
|
|
31
|
+
LARK_AVAILABLE = False
|
|
32
|
+
# When Lark is not available, use Exception as fallback
|
|
33
|
+
# Use different names to avoid redefinition errors
|
|
34
|
+
LarkError = Exception # type: ignore[misc,assignment]
|
|
35
|
+
UnexpectedInput = Exception # type: ignore[misc,assignment]
|
|
36
|
+
UnexpectedToken = Exception # type: ignore[misc,assignment]
|
|
37
|
+
UnexpectedCharacters = Exception # type: ignore[misc,assignment]
|
|
38
|
+
|
|
39
|
+
# Optional: colorama for terminal colors
|
|
40
|
+
try:
|
|
41
|
+
from colorama import Fore, Style, init as colorama_init
|
|
42
|
+
|
|
43
|
+
COLORAMA_AVAILABLE = True
|
|
44
|
+
colorama_init(autoreset=True)
|
|
45
|
+
except ImportError:
|
|
46
|
+
COLORAMA_AVAILABLE = False
|
|
47
|
+
# Fallback: no colors
|
|
48
|
+
# Create fallback classes with same interface but different implementation
|
|
49
|
+
class _ForeFallback: # type: ignore[no-redef]
|
|
50
|
+
RED = ""
|
|
51
|
+
YELLOW = ""
|
|
52
|
+
GREEN = ""
|
|
53
|
+
CYAN = ""
|
|
54
|
+
RESET = ""
|
|
55
|
+
|
|
56
|
+
class _StyleFallback: # type: ignore[no-redef]
|
|
57
|
+
BRIGHT = ""
|
|
58
|
+
RESET_ALL = ""
|
|
59
|
+
|
|
60
|
+
Fore = _ForeFallback # type: ignore[assignment,misc]
|
|
61
|
+
Style = _StyleFallback # type: ignore[assignment,misc]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass
|
|
65
|
+
class ParserError:
|
|
66
|
+
"""
|
|
67
|
+
Parser error with location, message, and suggestion
|
|
68
|
+
|
|
69
|
+
This dataclass represents both syntax errors (from Lark) and semantic errors
|
|
70
|
+
(from AST validation). The `phase` field distinguishes between them.
|
|
71
|
+
|
|
72
|
+
Attributes:
|
|
73
|
+
line: Line number (1-based)
|
|
74
|
+
column: Column number (1-based)
|
|
75
|
+
message: Error message
|
|
76
|
+
suggestion: Optional suggestion for fixing the error
|
|
77
|
+
phase: Error phase ("syntax" or "semantic")
|
|
78
|
+
context: Optional error context (surrounding lines)
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
line: int
|
|
82
|
+
column: int
|
|
83
|
+
message: str
|
|
84
|
+
suggestion: Optional[str] = None
|
|
85
|
+
phase: str = "syntax" # "syntax" or "semantic"
|
|
86
|
+
context: Optional[str] = None
|
|
87
|
+
|
|
88
|
+
def __repr__(self) -> str:
|
|
89
|
+
"""String representation for debugging"""
|
|
90
|
+
suggestion_str = f", suggestion={self.suggestion}" if self.suggestion else ""
|
|
91
|
+
return f"ParserError(line={self.line}, col={self.column}, " f"phase={self.phase}, message={self.message}{suggestion_str})"
|
|
92
|
+
|
|
93
|
+
def __str__(self) -> str:
|
|
94
|
+
"""Human-readable string representation"""
|
|
95
|
+
return self.format()
|
|
96
|
+
|
|
97
|
+
def format(self, use_colors: bool = False) -> str:
|
|
98
|
+
"""
|
|
99
|
+
Format error for display
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
use_colors: Whether to use terminal colors (requires colorama)
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Formatted error string
|
|
106
|
+
"""
|
|
107
|
+
if use_colors and not COLORAMA_AVAILABLE:
|
|
108
|
+
use_colors = False
|
|
109
|
+
|
|
110
|
+
# Build error message
|
|
111
|
+
parts = []
|
|
112
|
+
|
|
113
|
+
# Error header
|
|
114
|
+
if use_colors:
|
|
115
|
+
phase_color = Fore.RED if self.phase == "syntax" else Fore.YELLOW
|
|
116
|
+
parts.append(f"{phase_color}{Style.BRIGHT}{self.phase.upper()} ERROR{Style.RESET_ALL}")
|
|
117
|
+
else:
|
|
118
|
+
parts.append(f"{self.phase.upper()} ERROR")
|
|
119
|
+
|
|
120
|
+
# Location
|
|
121
|
+
if use_colors:
|
|
122
|
+
parts.append(f" at {Fore.CYAN}line {self.line}, column {self.column}{Style.RESET_ALL}")
|
|
123
|
+
else:
|
|
124
|
+
parts.append(f" at line {self.line}, column {self.column}")
|
|
125
|
+
|
|
126
|
+
# Message
|
|
127
|
+
parts.append(f"\n {self.message}")
|
|
128
|
+
|
|
129
|
+
# Context (if available)
|
|
130
|
+
if self.context:
|
|
131
|
+
parts.append(f"\n\n{self.context}")
|
|
132
|
+
|
|
133
|
+
# Suggestion (if available)
|
|
134
|
+
if self.suggestion:
|
|
135
|
+
if use_colors:
|
|
136
|
+
parts.append(f"\n\n{Fore.GREEN}💡 Suggestion:{Style.RESET_ALL} {self.suggestion}")
|
|
137
|
+
else:
|
|
138
|
+
parts.append(f"\n\nSuggestion: {self.suggestion}")
|
|
139
|
+
|
|
140
|
+
return "".join(parts)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class ErrorHandler:
|
|
144
|
+
"""
|
|
145
|
+
Error handler for Logic Query Parser
|
|
146
|
+
|
|
147
|
+
This class provides methods for:
|
|
148
|
+
- Converting Lark errors to ParserError
|
|
149
|
+
- Converting ValidationError to ParserError
|
|
150
|
+
- Extracting error context from query string
|
|
151
|
+
- Generating helpful suggestions
|
|
152
|
+
- Formatting errors for display
|
|
153
|
+
|
|
154
|
+
Example:
|
|
155
|
+
```python
|
|
156
|
+
handler = ErrorHandler()
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
parse_tree = parser.parse(query)
|
|
160
|
+
except LarkError as e:
|
|
161
|
+
error = handler.from_lark_error(e, query)
|
|
162
|
+
print(error.format(use_colors=True))
|
|
163
|
+
```
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
def __init__(self):
|
|
167
|
+
"""Initialize error handler"""
|
|
168
|
+
|
|
169
|
+
# ========================================================================
|
|
170
|
+
# Error Conversion Methods
|
|
171
|
+
# ========================================================================
|
|
172
|
+
|
|
173
|
+
def from_lark_error(self, error: Exception, query: str) -> ParserError:
|
|
174
|
+
"""
|
|
175
|
+
Convert Lark error to ParserError
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
error: Lark exception (LarkError, UnexpectedInput, etc.)
|
|
179
|
+
query: Original query string
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
ParserError with phase="syntax"
|
|
183
|
+
"""
|
|
184
|
+
# Extract line and column from error
|
|
185
|
+
line = getattr(error, "line", 1)
|
|
186
|
+
column = getattr(error, "column", 1)
|
|
187
|
+
|
|
188
|
+
# Get error message
|
|
189
|
+
message = str(error)
|
|
190
|
+
|
|
191
|
+
# Extract context
|
|
192
|
+
context = self.extract_context(query, line, column)
|
|
193
|
+
|
|
194
|
+
# Generate suggestion
|
|
195
|
+
suggestion = self.suggest_fix(error, query)
|
|
196
|
+
|
|
197
|
+
return ParserError(
|
|
198
|
+
line=line,
|
|
199
|
+
column=column,
|
|
200
|
+
message=message,
|
|
201
|
+
suggestion=suggestion,
|
|
202
|
+
phase="syntax",
|
|
203
|
+
context=context,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def from_validation_error(self, error: Any, query: Optional[str] = None) -> ParserError:
|
|
207
|
+
"""
|
|
208
|
+
Convert ValidationError to ParserError
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
error: ValidationError from AST validation
|
|
212
|
+
query: Optional query string for context
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
ParserError with phase="semantic"
|
|
216
|
+
"""
|
|
217
|
+
line = getattr(error, "line", 1)
|
|
218
|
+
column = getattr(error, "column", 1)
|
|
219
|
+
message = getattr(error, "message", str(error))
|
|
220
|
+
suggestion = getattr(error, "suggestion", None)
|
|
221
|
+
|
|
222
|
+
# Extract context if query is provided
|
|
223
|
+
context = None
|
|
224
|
+
if query:
|
|
225
|
+
context = self.extract_context(query, line, column)
|
|
226
|
+
|
|
227
|
+
return ParserError(
|
|
228
|
+
line=line,
|
|
229
|
+
column=column,
|
|
230
|
+
message=message,
|
|
231
|
+
suggestion=suggestion,
|
|
232
|
+
phase="semantic",
|
|
233
|
+
context=context,
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# ========================================================================
|
|
237
|
+
# Context Extraction
|
|
238
|
+
# ========================================================================
|
|
239
|
+
|
|
240
|
+
def extract_context(self, query: str, line: int, column: int, context_lines: int = 2) -> str:
|
|
241
|
+
"""
|
|
242
|
+
Extract error context from query string
|
|
243
|
+
|
|
244
|
+
Shows the error line with surrounding context and a pointer to the error location.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
query: Query string
|
|
248
|
+
line: Error line number (1-based)
|
|
249
|
+
column: Error column number (1-based)
|
|
250
|
+
context_lines: Number of lines to show before and after error line
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Formatted context string
|
|
254
|
+
"""
|
|
255
|
+
lines = query.split("\n")
|
|
256
|
+
|
|
257
|
+
# Validate line number
|
|
258
|
+
if line < 1 or line > len(lines):
|
|
259
|
+
return ""
|
|
260
|
+
|
|
261
|
+
# Calculate context range
|
|
262
|
+
start_line = max(1, line - context_lines)
|
|
263
|
+
end_line = min(len(lines), line + context_lines)
|
|
264
|
+
|
|
265
|
+
# Build context
|
|
266
|
+
context_parts = []
|
|
267
|
+
|
|
268
|
+
for i in range(start_line - 1, end_line):
|
|
269
|
+
line_num = i + 1
|
|
270
|
+
line_content = lines[i]
|
|
271
|
+
|
|
272
|
+
# Add line number and content
|
|
273
|
+
if line_num == line:
|
|
274
|
+
# Error line - highlight it
|
|
275
|
+
context_parts.append(f" {line_num:3d} | {line_content}")
|
|
276
|
+
|
|
277
|
+
# Add pointer to error column
|
|
278
|
+
pointer = " " * (column - 1) + "^"
|
|
279
|
+
context_parts.append(f" | {pointer}")
|
|
280
|
+
else:
|
|
281
|
+
# Context line
|
|
282
|
+
context_parts.append(f" {line_num:3d} | {line_content}")
|
|
283
|
+
|
|
284
|
+
return "\n".join(context_parts)
|
|
285
|
+
|
|
286
|
+
# ========================================================================
|
|
287
|
+
# Suggestion Generation
|
|
288
|
+
# ========================================================================
|
|
289
|
+
|
|
290
|
+
def suggest_fix(self, error: Exception, query: str) -> Optional[str]:
|
|
291
|
+
"""
|
|
292
|
+
Generate helpful suggestion for fixing the error
|
|
293
|
+
|
|
294
|
+
Uses pattern matching and fuzzy matching to suggest fixes.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
error: Exception that occurred
|
|
298
|
+
query: Original query string
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Suggestion string or None
|
|
302
|
+
"""
|
|
303
|
+
message = str(error).lower()
|
|
304
|
+
|
|
305
|
+
# Pattern-based suggestions
|
|
306
|
+
suggestion = self._suggest_from_pattern(message, query)
|
|
307
|
+
if suggestion:
|
|
308
|
+
return suggestion
|
|
309
|
+
|
|
310
|
+
# Keyword suggestions (fuzzy matching)
|
|
311
|
+
suggestion = self._suggest_keyword(query)
|
|
312
|
+
if suggestion:
|
|
313
|
+
return suggestion
|
|
314
|
+
|
|
315
|
+
return None
|
|
316
|
+
|
|
317
|
+
def _suggest_from_pattern(self, message: str, query: str) -> Optional[str]:
|
|
318
|
+
"""
|
|
319
|
+
Generate suggestion based on error message patterns
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
message: Error message (lowercase)
|
|
323
|
+
query: Original query string
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
Suggestion string or None
|
|
327
|
+
"""
|
|
328
|
+
# Missing/mismatched delimiters
|
|
329
|
+
if "unexpected token" in message or "unexpected character" in message:
|
|
330
|
+
if "(" in message or ")" in message:
|
|
331
|
+
return "Check for missing or mismatched parentheses"
|
|
332
|
+
elif "[" in message or "]" in message:
|
|
333
|
+
return "Check for missing or mismatched brackets"
|
|
334
|
+
elif "'" in message or '"' in message:
|
|
335
|
+
return "Check for missing or mismatched quotes"
|
|
336
|
+
elif "`" in message:
|
|
337
|
+
return "Check for missing or mismatched backticks in entity names"
|
|
338
|
+
|
|
339
|
+
# Expected tokens
|
|
340
|
+
if "expected one of" in message or "expected" in message:
|
|
341
|
+
if "where" in message.lower():
|
|
342
|
+
return "WHERE clause requires a condition (e.g., WHERE property == value)"
|
|
343
|
+
elif "follows" in message.lower():
|
|
344
|
+
return "FOLLOWS clause requires a relation type (e.g., FOLLOWS RelationType)"
|
|
345
|
+
else:
|
|
346
|
+
return "Check the query syntax - you may be missing a keyword or operator"
|
|
347
|
+
|
|
348
|
+
# Incomplete query
|
|
349
|
+
if "unexpected end" in message or "unexpected eof" in message:
|
|
350
|
+
return "Query appears incomplete - check for missing closing delimiters or keywords"
|
|
351
|
+
|
|
352
|
+
return None
|
|
353
|
+
|
|
354
|
+
def _suggest_keyword(self, query: str) -> Optional[str]:
|
|
355
|
+
"""
|
|
356
|
+
Generate suggestion for incorrect keyword case
|
|
357
|
+
|
|
358
|
+
Uses fuzzy matching to detect common keyword mistakes.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
query: Original query string
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
Suggestion string or None
|
|
365
|
+
"""
|
|
366
|
+
# Define correct keywords
|
|
367
|
+
keywords = {
|
|
368
|
+
"find": "Find",
|
|
369
|
+
"where": "WHERE",
|
|
370
|
+
"follows": "FOLLOWS",
|
|
371
|
+
"and": "AND",
|
|
372
|
+
"or": "OR",
|
|
373
|
+
"not": "NOT",
|
|
374
|
+
"in": "IN",
|
|
375
|
+
"contains": "CONTAINS",
|
|
376
|
+
"incoming": "INCOMING",
|
|
377
|
+
"outgoing": "OUTGOING",
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
# Check for lowercase keywords
|
|
381
|
+
query_lower = query.lower()
|
|
382
|
+
for wrong, correct in keywords.items():
|
|
383
|
+
if wrong in query_lower and correct not in query:
|
|
384
|
+
return f"Keywords are case-sensitive. Use '{correct}' instead of '{wrong}'"
|
|
385
|
+
|
|
386
|
+
return None
|
|
387
|
+
|
|
388
|
+
def _fuzzy_match(self, word: str, candidates: List[str], threshold: float = 0.7) -> Optional[str]:
|
|
389
|
+
"""
|
|
390
|
+
Find closest match using fuzzy string matching
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
word: Word to match
|
|
394
|
+
candidates: List of candidate words
|
|
395
|
+
threshold: Minimum similarity threshold (0.0 to 1.0)
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
Best match or None
|
|
399
|
+
"""
|
|
400
|
+
try:
|
|
401
|
+
# Try to use python-Levenshtein if available
|
|
402
|
+
import Levenshtein # type: ignore[import-not-found]
|
|
403
|
+
|
|
404
|
+
best_match = None
|
|
405
|
+
best_ratio = 0.0
|
|
406
|
+
|
|
407
|
+
for candidate in candidates:
|
|
408
|
+
ratio = Levenshtein.ratio(word.lower(), candidate.lower())
|
|
409
|
+
if ratio > best_ratio and ratio >= threshold:
|
|
410
|
+
best_ratio = ratio
|
|
411
|
+
best_match = candidate
|
|
412
|
+
|
|
413
|
+
return best_match
|
|
414
|
+
except ImportError:
|
|
415
|
+
# Fallback: simple substring matching
|
|
416
|
+
word_lower = word.lower()
|
|
417
|
+
for candidate in candidates:
|
|
418
|
+
if word_lower in candidate.lower() or candidate.lower() in word_lower:
|
|
419
|
+
return candidate
|
|
420
|
+
return None
|
|
421
|
+
|
|
422
|
+
# ========================================================================
|
|
423
|
+
# Formatting Methods
|
|
424
|
+
# ========================================================================
|
|
425
|
+
|
|
426
|
+
def format_errors(self, errors: List[ParserError], use_colors: bool = False) -> str:
|
|
427
|
+
"""
|
|
428
|
+
Format multiple errors for display
|
|
429
|
+
|
|
430
|
+
Args:
|
|
431
|
+
errors: List of ParserError objects
|
|
432
|
+
use_colors: Whether to use terminal colors
|
|
433
|
+
|
|
434
|
+
Returns:
|
|
435
|
+
Formatted error string
|
|
436
|
+
"""
|
|
437
|
+
if not errors:
|
|
438
|
+
return ""
|
|
439
|
+
|
|
440
|
+
parts = []
|
|
441
|
+
|
|
442
|
+
# Header
|
|
443
|
+
error_count = len(errors)
|
|
444
|
+
if use_colors and COLORAMA_AVAILABLE:
|
|
445
|
+
parts.append(f"{Fore.RED}{Style.BRIGHT}Found {error_count} error(s):{Style.RESET_ALL}\n")
|
|
446
|
+
else:
|
|
447
|
+
parts.append(f"Found {error_count} error(s):\n")
|
|
448
|
+
|
|
449
|
+
# Format each error
|
|
450
|
+
for i, error in enumerate(errors, 1):
|
|
451
|
+
parts.append(f"\n{i}. {error.format(use_colors=use_colors)}")
|
|
452
|
+
|
|
453
|
+
return "\n".join(parts)
|
|
454
|
+
|
|
455
|
+
def format_for_api(self, errors: List[ParserError]) -> List[dict]:
|
|
456
|
+
"""
|
|
457
|
+
Format errors for API response (JSON-serializable)
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
errors: List of ParserError objects
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
List of error dictionaries
|
|
464
|
+
"""
|
|
465
|
+
return [
|
|
466
|
+
{
|
|
467
|
+
"line": error.line,
|
|
468
|
+
"column": error.column,
|
|
469
|
+
"message": error.message,
|
|
470
|
+
"suggestion": error.suggestion,
|
|
471
|
+
"phase": error.phase,
|
|
472
|
+
"context": error.context,
|
|
473
|
+
}
|
|
474
|
+
for error in errors
|
|
475
|
+
]
|