aiecs 1.5.1__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.
Files changed (302) hide show
  1. aiecs/__init__.py +72 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +469 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +363 -0
  7. aiecs/application/knowledge_graph/__init__.py +7 -0
  8. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +375 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +356 -0
  11. aiecs/application/knowledge_graph/builder/schema_mapping.py +531 -0
  12. aiecs/application/knowledge_graph/builder/structured_pipeline.py +443 -0
  13. aiecs/application/knowledge_graph/builder/text_chunker.py +319 -0
  14. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  15. aiecs/application/knowledge_graph/extractors/base.py +100 -0
  16. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +327 -0
  17. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +349 -0
  18. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +244 -0
  19. aiecs/application/knowledge_graph/fusion/__init__.py +23 -0
  20. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +387 -0
  21. aiecs/application/knowledge_graph/fusion/entity_linker.py +343 -0
  22. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +580 -0
  23. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +189 -0
  24. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  25. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +344 -0
  26. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +378 -0
  27. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  28. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +199 -0
  29. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  30. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  31. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +347 -0
  32. aiecs/application/knowledge_graph/reasoning/inference_engine.py +504 -0
  33. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +167 -0
  34. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  35. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  36. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +630 -0
  37. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +654 -0
  38. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +477 -0
  39. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +390 -0
  40. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +217 -0
  41. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +169 -0
  42. aiecs/application/knowledge_graph/reasoning/query_planner.py +872 -0
  43. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +554 -0
  44. aiecs/application/knowledge_graph/retrieval/__init__.py +19 -0
  45. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +596 -0
  46. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  47. aiecs/application/knowledge_graph/search/hybrid_search.py +423 -0
  48. aiecs/application/knowledge_graph/search/reranker.py +295 -0
  49. aiecs/application/knowledge_graph/search/reranker_strategies.py +553 -0
  50. aiecs/application/knowledge_graph/search/text_similarity.py +398 -0
  51. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  52. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +329 -0
  53. aiecs/application/knowledge_graph/traversal/path_scorer.py +269 -0
  54. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  55. aiecs/application/knowledge_graph/validators/relation_validator.py +189 -0
  56. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  57. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +321 -0
  58. aiecs/common/__init__.py +9 -0
  59. aiecs/common/knowledge_graph/__init__.py +17 -0
  60. aiecs/common/knowledge_graph/runnable.py +484 -0
  61. aiecs/config/__init__.py +16 -0
  62. aiecs/config/config.py +498 -0
  63. aiecs/config/graph_config.py +137 -0
  64. aiecs/config/registry.py +23 -0
  65. aiecs/core/__init__.py +46 -0
  66. aiecs/core/interface/__init__.py +34 -0
  67. aiecs/core/interface/execution_interface.py +152 -0
  68. aiecs/core/interface/storage_interface.py +171 -0
  69. aiecs/domain/__init__.py +289 -0
  70. aiecs/domain/agent/__init__.py +189 -0
  71. aiecs/domain/agent/base_agent.py +697 -0
  72. aiecs/domain/agent/exceptions.py +103 -0
  73. aiecs/domain/agent/graph_aware_mixin.py +559 -0
  74. aiecs/domain/agent/hybrid_agent.py +490 -0
  75. aiecs/domain/agent/integration/__init__.py +26 -0
  76. aiecs/domain/agent/integration/context_compressor.py +222 -0
  77. aiecs/domain/agent/integration/context_engine_adapter.py +252 -0
  78. aiecs/domain/agent/integration/retry_policy.py +219 -0
  79. aiecs/domain/agent/integration/role_config.py +213 -0
  80. aiecs/domain/agent/knowledge_aware_agent.py +646 -0
  81. aiecs/domain/agent/lifecycle.py +296 -0
  82. aiecs/domain/agent/llm_agent.py +300 -0
  83. aiecs/domain/agent/memory/__init__.py +12 -0
  84. aiecs/domain/agent/memory/conversation.py +197 -0
  85. aiecs/domain/agent/migration/__init__.py +14 -0
  86. aiecs/domain/agent/migration/conversion.py +160 -0
  87. aiecs/domain/agent/migration/legacy_wrapper.py +90 -0
  88. aiecs/domain/agent/models.py +317 -0
  89. aiecs/domain/agent/observability.py +407 -0
  90. aiecs/domain/agent/persistence.py +289 -0
  91. aiecs/domain/agent/prompts/__init__.py +29 -0
  92. aiecs/domain/agent/prompts/builder.py +161 -0
  93. aiecs/domain/agent/prompts/formatters.py +189 -0
  94. aiecs/domain/agent/prompts/template.py +255 -0
  95. aiecs/domain/agent/registry.py +260 -0
  96. aiecs/domain/agent/tool_agent.py +257 -0
  97. aiecs/domain/agent/tools/__init__.py +12 -0
  98. aiecs/domain/agent/tools/schema_generator.py +221 -0
  99. aiecs/domain/community/__init__.py +155 -0
  100. aiecs/domain/community/agent_adapter.py +477 -0
  101. aiecs/domain/community/analytics.py +481 -0
  102. aiecs/domain/community/collaborative_workflow.py +642 -0
  103. aiecs/domain/community/communication_hub.py +645 -0
  104. aiecs/domain/community/community_builder.py +320 -0
  105. aiecs/domain/community/community_integration.py +800 -0
  106. aiecs/domain/community/community_manager.py +813 -0
  107. aiecs/domain/community/decision_engine.py +879 -0
  108. aiecs/domain/community/exceptions.py +225 -0
  109. aiecs/domain/community/models/__init__.py +33 -0
  110. aiecs/domain/community/models/community_models.py +268 -0
  111. aiecs/domain/community/resource_manager.py +457 -0
  112. aiecs/domain/community/shared_context_manager.py +603 -0
  113. aiecs/domain/context/__init__.py +58 -0
  114. aiecs/domain/context/context_engine.py +989 -0
  115. aiecs/domain/context/conversation_models.py +354 -0
  116. aiecs/domain/context/graph_memory.py +467 -0
  117. aiecs/domain/execution/__init__.py +12 -0
  118. aiecs/domain/execution/model.py +57 -0
  119. aiecs/domain/knowledge_graph/__init__.py +19 -0
  120. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  121. aiecs/domain/knowledge_graph/models/entity.py +130 -0
  122. aiecs/domain/knowledge_graph/models/evidence.py +194 -0
  123. aiecs/domain/knowledge_graph/models/inference_rule.py +186 -0
  124. aiecs/domain/knowledge_graph/models/path.py +179 -0
  125. aiecs/domain/knowledge_graph/models/path_pattern.py +173 -0
  126. aiecs/domain/knowledge_graph/models/query.py +272 -0
  127. aiecs/domain/knowledge_graph/models/query_plan.py +187 -0
  128. aiecs/domain/knowledge_graph/models/relation.py +136 -0
  129. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  130. aiecs/domain/knowledge_graph/schema/entity_type.py +135 -0
  131. aiecs/domain/knowledge_graph/schema/graph_schema.py +271 -0
  132. aiecs/domain/knowledge_graph/schema/property_schema.py +155 -0
  133. aiecs/domain/knowledge_graph/schema/relation_type.py +171 -0
  134. aiecs/domain/knowledge_graph/schema/schema_manager.py +496 -0
  135. aiecs/domain/knowledge_graph/schema/type_enums.py +205 -0
  136. aiecs/domain/task/__init__.py +13 -0
  137. aiecs/domain/task/dsl_processor.py +613 -0
  138. aiecs/domain/task/model.py +62 -0
  139. aiecs/domain/task/task_context.py +268 -0
  140. aiecs/infrastructure/__init__.py +24 -0
  141. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  142. aiecs/infrastructure/graph_storage/base.py +601 -0
  143. aiecs/infrastructure/graph_storage/batch_operations.py +449 -0
  144. aiecs/infrastructure/graph_storage/cache.py +429 -0
  145. aiecs/infrastructure/graph_storage/distributed.py +226 -0
  146. aiecs/infrastructure/graph_storage/error_handling.py +390 -0
  147. aiecs/infrastructure/graph_storage/graceful_degradation.py +306 -0
  148. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  149. aiecs/infrastructure/graph_storage/in_memory.py +514 -0
  150. aiecs/infrastructure/graph_storage/index_optimization.py +483 -0
  151. aiecs/infrastructure/graph_storage/lazy_loading.py +410 -0
  152. aiecs/infrastructure/graph_storage/metrics.py +357 -0
  153. aiecs/infrastructure/graph_storage/migration.py +413 -0
  154. aiecs/infrastructure/graph_storage/pagination.py +471 -0
  155. aiecs/infrastructure/graph_storage/performance_monitoring.py +466 -0
  156. aiecs/infrastructure/graph_storage/postgres.py +871 -0
  157. aiecs/infrastructure/graph_storage/query_optimizer.py +635 -0
  158. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  159. aiecs/infrastructure/graph_storage/sqlite.py +623 -0
  160. aiecs/infrastructure/graph_storage/streaming.py +495 -0
  161. aiecs/infrastructure/messaging/__init__.py +13 -0
  162. aiecs/infrastructure/messaging/celery_task_manager.py +383 -0
  163. aiecs/infrastructure/messaging/websocket_manager.py +298 -0
  164. aiecs/infrastructure/monitoring/__init__.py +34 -0
  165. aiecs/infrastructure/monitoring/executor_metrics.py +174 -0
  166. aiecs/infrastructure/monitoring/global_metrics_manager.py +213 -0
  167. aiecs/infrastructure/monitoring/structured_logger.py +48 -0
  168. aiecs/infrastructure/monitoring/tracing_manager.py +410 -0
  169. aiecs/infrastructure/persistence/__init__.py +24 -0
  170. aiecs/infrastructure/persistence/context_engine_client.py +187 -0
  171. aiecs/infrastructure/persistence/database_manager.py +333 -0
  172. aiecs/infrastructure/persistence/file_storage.py +754 -0
  173. aiecs/infrastructure/persistence/redis_client.py +220 -0
  174. aiecs/llm/__init__.py +86 -0
  175. aiecs/llm/callbacks/__init__.py +11 -0
  176. aiecs/llm/callbacks/custom_callbacks.py +264 -0
  177. aiecs/llm/client_factory.py +420 -0
  178. aiecs/llm/clients/__init__.py +33 -0
  179. aiecs/llm/clients/base_client.py +193 -0
  180. aiecs/llm/clients/googleai_client.py +181 -0
  181. aiecs/llm/clients/openai_client.py +131 -0
  182. aiecs/llm/clients/vertex_client.py +437 -0
  183. aiecs/llm/clients/xai_client.py +184 -0
  184. aiecs/llm/config/__init__.py +51 -0
  185. aiecs/llm/config/config_loader.py +275 -0
  186. aiecs/llm/config/config_validator.py +236 -0
  187. aiecs/llm/config/model_config.py +151 -0
  188. aiecs/llm/utils/__init__.py +10 -0
  189. aiecs/llm/utils/validate_config.py +91 -0
  190. aiecs/main.py +363 -0
  191. aiecs/scripts/__init__.py +3 -0
  192. aiecs/scripts/aid/VERSION_MANAGEMENT.md +97 -0
  193. aiecs/scripts/aid/__init__.py +19 -0
  194. aiecs/scripts/aid/version_manager.py +215 -0
  195. aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +242 -0
  196. aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +310 -0
  197. aiecs/scripts/dependance_check/__init__.py +17 -0
  198. aiecs/scripts/dependance_check/dependency_checker.py +938 -0
  199. aiecs/scripts/dependance_check/dependency_fixer.py +391 -0
  200. aiecs/scripts/dependance_check/download_nlp_data.py +396 -0
  201. aiecs/scripts/dependance_check/quick_dependency_check.py +270 -0
  202. aiecs/scripts/dependance_check/setup_nlp_data.sh +217 -0
  203. aiecs/scripts/dependance_patch/__init__.py +7 -0
  204. aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +126 -0
  205. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  206. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +128 -0
  207. aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +82 -0
  208. aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +188 -0
  209. aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +41 -0
  210. aiecs/scripts/tools_develop/README.md +449 -0
  211. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  212. aiecs/scripts/tools_develop/__init__.py +21 -0
  213. aiecs/scripts/tools_develop/check_type_annotations.py +259 -0
  214. aiecs/scripts/tools_develop/validate_tool_schemas.py +422 -0
  215. aiecs/scripts/tools_develop/verify_tools.py +356 -0
  216. aiecs/tasks/__init__.py +1 -0
  217. aiecs/tasks/worker.py +172 -0
  218. aiecs/tools/__init__.py +299 -0
  219. aiecs/tools/apisource/__init__.py +99 -0
  220. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  221. aiecs/tools/apisource/intelligence/data_fusion.py +381 -0
  222. aiecs/tools/apisource/intelligence/query_analyzer.py +413 -0
  223. aiecs/tools/apisource/intelligence/search_enhancer.py +388 -0
  224. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  225. aiecs/tools/apisource/monitoring/metrics.py +303 -0
  226. aiecs/tools/apisource/providers/__init__.py +115 -0
  227. aiecs/tools/apisource/providers/base.py +664 -0
  228. aiecs/tools/apisource/providers/census.py +401 -0
  229. aiecs/tools/apisource/providers/fred.py +564 -0
  230. aiecs/tools/apisource/providers/newsapi.py +412 -0
  231. aiecs/tools/apisource/providers/worldbank.py +357 -0
  232. aiecs/tools/apisource/reliability/__init__.py +12 -0
  233. aiecs/tools/apisource/reliability/error_handler.py +375 -0
  234. aiecs/tools/apisource/reliability/fallback_strategy.py +391 -0
  235. aiecs/tools/apisource/tool.py +850 -0
  236. aiecs/tools/apisource/utils/__init__.py +9 -0
  237. aiecs/tools/apisource/utils/validators.py +338 -0
  238. aiecs/tools/base_tool.py +201 -0
  239. aiecs/tools/docs/__init__.py +121 -0
  240. aiecs/tools/docs/ai_document_orchestrator.py +599 -0
  241. aiecs/tools/docs/ai_document_writer_orchestrator.py +2403 -0
  242. aiecs/tools/docs/content_insertion_tool.py +1333 -0
  243. aiecs/tools/docs/document_creator_tool.py +1317 -0
  244. aiecs/tools/docs/document_layout_tool.py +1166 -0
  245. aiecs/tools/docs/document_parser_tool.py +994 -0
  246. aiecs/tools/docs/document_writer_tool.py +1818 -0
  247. aiecs/tools/knowledge_graph/__init__.py +17 -0
  248. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +734 -0
  249. aiecs/tools/knowledge_graph/graph_search_tool.py +923 -0
  250. aiecs/tools/knowledge_graph/kg_builder_tool.py +476 -0
  251. aiecs/tools/langchain_adapter.py +542 -0
  252. aiecs/tools/schema_generator.py +275 -0
  253. aiecs/tools/search_tool/__init__.py +100 -0
  254. aiecs/tools/search_tool/analyzers.py +589 -0
  255. aiecs/tools/search_tool/cache.py +260 -0
  256. aiecs/tools/search_tool/constants.py +128 -0
  257. aiecs/tools/search_tool/context.py +216 -0
  258. aiecs/tools/search_tool/core.py +749 -0
  259. aiecs/tools/search_tool/deduplicator.py +123 -0
  260. aiecs/tools/search_tool/error_handler.py +271 -0
  261. aiecs/tools/search_tool/metrics.py +371 -0
  262. aiecs/tools/search_tool/rate_limiter.py +178 -0
  263. aiecs/tools/search_tool/schemas.py +277 -0
  264. aiecs/tools/statistics/__init__.py +80 -0
  265. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +643 -0
  266. aiecs/tools/statistics/ai_insight_generator_tool.py +505 -0
  267. aiecs/tools/statistics/ai_report_orchestrator_tool.py +694 -0
  268. aiecs/tools/statistics/data_loader_tool.py +564 -0
  269. aiecs/tools/statistics/data_profiler_tool.py +658 -0
  270. aiecs/tools/statistics/data_transformer_tool.py +573 -0
  271. aiecs/tools/statistics/data_visualizer_tool.py +495 -0
  272. aiecs/tools/statistics/model_trainer_tool.py +487 -0
  273. aiecs/tools/statistics/statistical_analyzer_tool.py +459 -0
  274. aiecs/tools/task_tools/__init__.py +86 -0
  275. aiecs/tools/task_tools/chart_tool.py +732 -0
  276. aiecs/tools/task_tools/classfire_tool.py +922 -0
  277. aiecs/tools/task_tools/image_tool.py +447 -0
  278. aiecs/tools/task_tools/office_tool.py +684 -0
  279. aiecs/tools/task_tools/pandas_tool.py +635 -0
  280. aiecs/tools/task_tools/report_tool.py +635 -0
  281. aiecs/tools/task_tools/research_tool.py +392 -0
  282. aiecs/tools/task_tools/scraper_tool.py +715 -0
  283. aiecs/tools/task_tools/stats_tool.py +688 -0
  284. aiecs/tools/temp_file_manager.py +130 -0
  285. aiecs/tools/tool_executor/__init__.py +37 -0
  286. aiecs/tools/tool_executor/tool_executor.py +881 -0
  287. aiecs/utils/LLM_output_structor.py +445 -0
  288. aiecs/utils/__init__.py +34 -0
  289. aiecs/utils/base_callback.py +47 -0
  290. aiecs/utils/cache_provider.py +695 -0
  291. aiecs/utils/execution_utils.py +184 -0
  292. aiecs/utils/logging.py +1 -0
  293. aiecs/utils/prompt_loader.py +14 -0
  294. aiecs/utils/token_usage_repository.py +323 -0
  295. aiecs/ws/__init__.py +0 -0
  296. aiecs/ws/socket_server.py +52 -0
  297. aiecs-1.5.1.dist-info/METADATA +608 -0
  298. aiecs-1.5.1.dist-info/RECORD +302 -0
  299. aiecs-1.5.1.dist-info/WHEEL +5 -0
  300. aiecs-1.5.1.dist-info/entry_points.txt +10 -0
  301. aiecs-1.5.1.dist-info/licenses/LICENSE +225 -0
  302. aiecs-1.5.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,477 @@
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
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
+ LarkError = Exception
33
+ UnexpectedInput = Exception
34
+ UnexpectedToken = Exception
35
+ UnexpectedCharacters = Exception
36
+
37
+ # Optional: colorama for terminal colors
38
+ try:
39
+ from colorama import Fore, Style, init as colorama_init
40
+
41
+ COLORAMA_AVAILABLE = True
42
+ colorama_init(autoreset=True)
43
+ except ImportError:
44
+ COLORAMA_AVAILABLE = False
45
+ # Fallback: no colors
46
+
47
+ class Fore:
48
+ RED = ""
49
+ YELLOW = ""
50
+ GREEN = ""
51
+ CYAN = ""
52
+ RESET = ""
53
+
54
+ class Style:
55
+ BRIGHT = ""
56
+ RESET_ALL = ""
57
+
58
+
59
+ @dataclass
60
+ class ParserError:
61
+ """
62
+ Parser error with location, message, and suggestion
63
+
64
+ This dataclass represents both syntax errors (from Lark) and semantic errors
65
+ (from AST validation). The `phase` field distinguishes between them.
66
+
67
+ Attributes:
68
+ line: Line number (1-based)
69
+ column: Column number (1-based)
70
+ message: Error message
71
+ suggestion: Optional suggestion for fixing the error
72
+ phase: Error phase ("syntax" or "semantic")
73
+ context: Optional error context (surrounding lines)
74
+ """
75
+
76
+ line: int
77
+ column: int
78
+ message: str
79
+ suggestion: Optional[str] = None
80
+ phase: str = "syntax" # "syntax" or "semantic"
81
+ context: Optional[str] = None
82
+
83
+ def __repr__(self) -> str:
84
+ """String representation for debugging"""
85
+ suggestion_str = f", suggestion={self.suggestion}" if self.suggestion else ""
86
+ return (
87
+ f"ParserError(line={self.line}, col={self.column}, "
88
+ f"phase={self.phase}, message={self.message}{suggestion_str})"
89
+ )
90
+
91
+ def __str__(self) -> str:
92
+ """Human-readable string representation"""
93
+ return self.format()
94
+
95
+ def format(self, use_colors: bool = False) -> str:
96
+ """
97
+ Format error for display
98
+
99
+ Args:
100
+ use_colors: Whether to use terminal colors (requires colorama)
101
+
102
+ Returns:
103
+ Formatted error string
104
+ """
105
+ if use_colors and not COLORAMA_AVAILABLE:
106
+ use_colors = False
107
+
108
+ # Build error message
109
+ parts = []
110
+
111
+ # Error header
112
+ if use_colors:
113
+ phase_color = Fore.RED if self.phase == "syntax" else Fore.YELLOW
114
+ parts.append(f"{phase_color}{Style.BRIGHT}{self.phase.upper()} ERROR{Style.RESET_ALL}")
115
+ else:
116
+ parts.append(f"{self.phase.upper()} ERROR")
117
+
118
+ # Location
119
+ if use_colors:
120
+ parts.append(f" at {Fore.CYAN}line {self.line}, column {self.column}{Style.RESET_ALL}")
121
+ else:
122
+ parts.append(f" at line {self.line}, column {self.column}")
123
+
124
+ # Message
125
+ parts.append(f"\n {self.message}")
126
+
127
+ # Context (if available)
128
+ if self.context:
129
+ parts.append(f"\n\n{self.context}")
130
+
131
+ # Suggestion (if available)
132
+ if self.suggestion:
133
+ if use_colors:
134
+ parts.append(f"\n\n{Fore.GREEN}💡 Suggestion:{Style.RESET_ALL} {self.suggestion}")
135
+ else:
136
+ parts.append(f"\n\nSuggestion: {self.suggestion}")
137
+
138
+ return "".join(parts)
139
+
140
+
141
+ class ErrorHandler:
142
+ """
143
+ Error handler for Logic Query Parser
144
+
145
+ This class provides methods for:
146
+ - Converting Lark errors to ParserError
147
+ - Converting ValidationError to ParserError
148
+ - Extracting error context from query string
149
+ - Generating helpful suggestions
150
+ - Formatting errors for display
151
+
152
+ Example:
153
+ ```python
154
+ handler = ErrorHandler()
155
+
156
+ try:
157
+ parse_tree = parser.parse(query)
158
+ except LarkError as e:
159
+ error = handler.from_lark_error(e, query)
160
+ print(error.format(use_colors=True))
161
+ ```
162
+ """
163
+
164
+ def __init__(self):
165
+ """Initialize error handler"""
166
+
167
+ # ========================================================================
168
+ # Error Conversion Methods
169
+ # ========================================================================
170
+
171
+ def from_lark_error(self, error: Exception, query: str) -> ParserError:
172
+ """
173
+ Convert Lark error to ParserError
174
+
175
+ Args:
176
+ error: Lark exception (LarkError, UnexpectedInput, etc.)
177
+ query: Original query string
178
+
179
+ Returns:
180
+ ParserError with phase="syntax"
181
+ """
182
+ # Extract line and column from error
183
+ line = getattr(error, "line", 1)
184
+ column = getattr(error, "column", 1)
185
+
186
+ # Get error message
187
+ message = str(error)
188
+
189
+ # Extract context
190
+ context = self.extract_context(query, line, column)
191
+
192
+ # Generate suggestion
193
+ suggestion = self.suggest_fix(error, query)
194
+
195
+ return ParserError(
196
+ line=line,
197
+ column=column,
198
+ message=message,
199
+ suggestion=suggestion,
200
+ phase="syntax",
201
+ context=context,
202
+ )
203
+
204
+ def from_validation_error(self, error: Any, query: Optional[str] = None) -> ParserError:
205
+ """
206
+ Convert ValidationError to ParserError
207
+
208
+ Args:
209
+ error: ValidationError from AST validation
210
+ query: Optional query string for context
211
+
212
+ Returns:
213
+ ParserError with phase="semantic"
214
+ """
215
+ line = getattr(error, "line", 1)
216
+ column = getattr(error, "column", 1)
217
+ message = getattr(error, "message", str(error))
218
+ suggestion = getattr(error, "suggestion", None)
219
+
220
+ # Extract context if query is provided
221
+ context = None
222
+ if query:
223
+ context = self.extract_context(query, line, column)
224
+
225
+ return ParserError(
226
+ line=line,
227
+ column=column,
228
+ message=message,
229
+ suggestion=suggestion,
230
+ phase="semantic",
231
+ context=context,
232
+ )
233
+
234
+ # ========================================================================
235
+ # Context Extraction
236
+ # ========================================================================
237
+
238
+ def extract_context(self, query: str, line: int, column: int, context_lines: int = 2) -> str:
239
+ """
240
+ Extract error context from query string
241
+
242
+ Shows the error line with surrounding context and a pointer to the error location.
243
+
244
+ Args:
245
+ query: Query string
246
+ line: Error line number (1-based)
247
+ column: Error column number (1-based)
248
+ context_lines: Number of lines to show before and after error line
249
+
250
+ Returns:
251
+ Formatted context string
252
+ """
253
+ lines = query.split("\n")
254
+
255
+ # Validate line number
256
+ if line < 1 or line > len(lines):
257
+ return ""
258
+
259
+ # Calculate context range
260
+ start_line = max(1, line - context_lines)
261
+ end_line = min(len(lines), line + context_lines)
262
+
263
+ # Build context
264
+ context_parts = []
265
+
266
+ for i in range(start_line - 1, end_line):
267
+ line_num = i + 1
268
+ line_content = lines[i]
269
+
270
+ # Add line number and content
271
+ if line_num == line:
272
+ # Error line - highlight it
273
+ context_parts.append(f" {line_num:3d} | {line_content}")
274
+
275
+ # Add pointer to error column
276
+ pointer = " " * (column - 1) + "^"
277
+ context_parts.append(f" | {pointer}")
278
+ else:
279
+ # Context line
280
+ context_parts.append(f" {line_num:3d} | {line_content}")
281
+
282
+ return "\n".join(context_parts)
283
+
284
+ # ========================================================================
285
+ # Suggestion Generation
286
+ # ========================================================================
287
+
288
+ def suggest_fix(self, error: Exception, query: str) -> Optional[str]:
289
+ """
290
+ Generate helpful suggestion for fixing the error
291
+
292
+ Uses pattern matching and fuzzy matching to suggest fixes.
293
+
294
+ Args:
295
+ error: Exception that occurred
296
+ query: Original query string
297
+
298
+ Returns:
299
+ Suggestion string or None
300
+ """
301
+ message = str(error).lower()
302
+
303
+ # Pattern-based suggestions
304
+ suggestion = self._suggest_from_pattern(message, query)
305
+ if suggestion:
306
+ return suggestion
307
+
308
+ # Keyword suggestions (fuzzy matching)
309
+ suggestion = self._suggest_keyword(query)
310
+ if suggestion:
311
+ return suggestion
312
+
313
+ return None
314
+
315
+ def _suggest_from_pattern(self, message: str, query: str) -> Optional[str]:
316
+ """
317
+ Generate suggestion based on error message patterns
318
+
319
+ Args:
320
+ message: Error message (lowercase)
321
+ query: Original query string
322
+
323
+ Returns:
324
+ Suggestion string or None
325
+ """
326
+ # Missing/mismatched delimiters
327
+ if "unexpected token" in message or "unexpected character" in message:
328
+ if "(" in message or ")" in message:
329
+ return "Check for missing or mismatched parentheses"
330
+ elif "[" in message or "]" in message:
331
+ return "Check for missing or mismatched brackets"
332
+ elif "'" in message or '"' in message:
333
+ return "Check for missing or mismatched quotes"
334
+ elif "`" in message:
335
+ return "Check for missing or mismatched backticks in entity names"
336
+
337
+ # Expected tokens
338
+ if "expected one of" in message or "expected" in message:
339
+ if "where" in message.lower():
340
+ return "WHERE clause requires a condition (e.g., WHERE property == value)"
341
+ elif "follows" in message.lower():
342
+ return "FOLLOWS clause requires a relation type (e.g., FOLLOWS RelationType)"
343
+ else:
344
+ return "Check the query syntax - you may be missing a keyword or operator"
345
+
346
+ # Incomplete query
347
+ if "unexpected end" in message or "unexpected eof" in message:
348
+ return "Query appears incomplete - check for missing closing delimiters or keywords"
349
+
350
+ return None
351
+
352
+ def _suggest_keyword(self, query: str) -> Optional[str]:
353
+ """
354
+ Generate suggestion for incorrect keyword case
355
+
356
+ Uses fuzzy matching to detect common keyword mistakes.
357
+
358
+ Args:
359
+ query: Original query string
360
+
361
+ Returns:
362
+ Suggestion string or None
363
+ """
364
+ # Define correct keywords
365
+ keywords = {
366
+ "find": "Find",
367
+ "where": "WHERE",
368
+ "follows": "FOLLOWS",
369
+ "and": "AND",
370
+ "or": "OR",
371
+ "not": "NOT",
372
+ "in": "IN",
373
+ "contains": "CONTAINS",
374
+ "incoming": "INCOMING",
375
+ "outgoing": "OUTGOING",
376
+ }
377
+
378
+ # Check for lowercase keywords
379
+ query_lower = query.lower()
380
+ for wrong, correct in keywords.items():
381
+ if wrong in query_lower and correct not in query:
382
+ return f"Keywords are case-sensitive. Use '{correct}' instead of '{wrong}'"
383
+
384
+ return None
385
+
386
+ def _fuzzy_match(
387
+ self, word: str, candidates: List[str], threshold: float = 0.7
388
+ ) -> 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
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(
446
+ f"{Fore.RED}{Style.BRIGHT}Found {error_count} error(s):{Style.RESET_ALL}\n"
447
+ )
448
+ else:
449
+ parts.append(f"Found {error_count} error(s):\n")
450
+
451
+ # Format each error
452
+ for i, error in enumerate(errors, 1):
453
+ parts.append(f"\n{i}. {error.format(use_colors=use_colors)}")
454
+
455
+ return "\n".join(parts)
456
+
457
+ def format_for_api(self, errors: List[ParserError]) -> List[dict]:
458
+ """
459
+ Format errors for API response (JSON-serializable)
460
+
461
+ Args:
462
+ errors: List of ParserError objects
463
+
464
+ Returns:
465
+ List of error dictionaries
466
+ """
467
+ return [
468
+ {
469
+ "line": error.line,
470
+ "column": error.column,
471
+ "message": error.message,
472
+ "suggestion": error.suggestion,
473
+ "phase": error.phase,
474
+ "context": error.context,
475
+ }
476
+ for error in errors
477
+ ]