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,375 @@
1
+ """
2
+ Smart Error Handler for API Providers
3
+
4
+ Provides intelligent error handling with:
5
+ - Classification of retryable vs non-retryable errors
6
+ - Exponential backoff retry strategy
7
+ - Agent-friendly error messages with recovery suggestions
8
+ - Detailed error context and history
9
+ """
10
+
11
+ import logging
12
+ import time
13
+ from datetime import datetime
14
+ from typing import Any, Callable, Dict, List
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class SmartErrorHandler:
20
+ """
21
+ Intelligent error handler with retry logic and recovery suggestions.
22
+
23
+ Automatically classifies errors, applies appropriate retry strategies,
24
+ and provides actionable recovery suggestions for AI agents.
25
+ """
26
+
27
+ # Error types that can be retried
28
+ RETRYABLE_ERRORS = [
29
+ "timeout",
30
+ "connection",
31
+ "rate limit",
32
+ "rate_limit",
33
+ "429", # Too Many Requests
34
+ "500", # Internal Server Error
35
+ "502", # Bad Gateway
36
+ "503", # Service Unavailable
37
+ "504", # Gateway Timeout
38
+ "temporary",
39
+ "transient",
40
+ ]
41
+
42
+ # Error types that should not be retried
43
+ NON_RETRYABLE_ERRORS = [
44
+ "authentication",
45
+ "auth",
46
+ "api key",
47
+ "unauthorized",
48
+ "401", # Unauthorized
49
+ "403", # Forbidden
50
+ "invalid",
51
+ "not found",
52
+ "404", # Not Found
53
+ "bad request",
54
+ "400", # Bad Request
55
+ ]
56
+
57
+ def __init__(
58
+ self,
59
+ max_retries: int = 3,
60
+ backoff_factor: float = 2.0,
61
+ initial_delay: float = 1.0,
62
+ max_delay: float = 30.0,
63
+ ):
64
+ """
65
+ Initialize error handler.
66
+
67
+ Args:
68
+ max_retries: Maximum number of retry attempts
69
+ backoff_factor: Multiplier for exponential backoff
70
+ initial_delay: Initial delay in seconds before first retry
71
+ max_delay: Maximum delay between retries in seconds
72
+ """
73
+ self.max_retries = max_retries
74
+ self.backoff_factor = backoff_factor
75
+ self.initial_delay = initial_delay
76
+ self.max_delay = max_delay
77
+
78
+ def execute_with_retry(
79
+ self,
80
+ operation_func: Callable[[], Any],
81
+ operation_name: str = "operation",
82
+ provider_name: str = "provider",
83
+ ) -> Dict[str, Any]:
84
+ """
85
+ Execute an operation with intelligent retry logic.
86
+
87
+ Args:
88
+ operation_func: Function to execute (should take no arguments)
89
+ operation_name: Name of the operation for logging
90
+ provider_name: Name of the provider for logging
91
+
92
+ Returns:
93
+ Dictionary with:
94
+ - success: bool
95
+ - data: result data if successful
96
+ - error: error details if failed
97
+ - retry_info: retry attempt information
98
+ """
99
+ last_error = None
100
+ retry_info = {"attempts": 0, "errors": [], "recovery_suggestions": []}
101
+
102
+ for attempt in range(self.max_retries):
103
+ retry_info["attempts"] = attempt + 1
104
+
105
+ try:
106
+ # Execute the operation
107
+ result = operation_func()
108
+
109
+ # Success!
110
+ if attempt > 0:
111
+ logger.info(
112
+ f"{provider_name}.{operation_name} succeeded after "
113
+ f"{attempt + 1} attempts"
114
+ )
115
+
116
+ return {
117
+ "success": True,
118
+ "data": result,
119
+ "retry_info": retry_info,
120
+ }
121
+
122
+ except Exception as e:
123
+ last_error = e
124
+ error_msg = str(e).lower()
125
+ error_type = self._classify_error(e, error_msg)
126
+
127
+ # Record this error
128
+ retry_info["errors"].append(
129
+ {
130
+ "attempt": attempt + 1,
131
+ "error": str(e),
132
+ "error_type": error_type,
133
+ "timestamp": datetime.utcnow().isoformat(),
134
+ }
135
+ )
136
+
137
+ # Determine if we should retry
138
+ is_retryable = self._is_retryable(error_msg, error_type)
139
+ is_last_attempt = attempt == self.max_retries - 1
140
+
141
+ if not is_retryable:
142
+ logger.warning(
143
+ f"{provider_name}.{operation_name} failed with non-retryable "
144
+ f"error: {error_type}"
145
+ )
146
+ break
147
+
148
+ if is_last_attempt:
149
+ logger.error(
150
+ f"{provider_name}.{operation_name} failed after "
151
+ f"{self.max_retries} attempts"
152
+ )
153
+ break
154
+
155
+ # Calculate wait time with exponential backoff
156
+ wait_time = min(
157
+ self.initial_delay * (self.backoff_factor**attempt),
158
+ self.max_delay,
159
+ )
160
+
161
+ logger.info(
162
+ f"{provider_name}.{operation_name} attempt {attempt + 1} failed "
163
+ f"({error_type}), retrying in {wait_time:.1f}s..."
164
+ )
165
+
166
+ time.sleep(wait_time)
167
+
168
+ # All retries exhausted or non-retryable error
169
+ retry_info["recovery_suggestions"] = self._generate_recovery_suggestions(
170
+ last_error, operation_name, provider_name
171
+ )
172
+
173
+ return {
174
+ "success": False,
175
+ "error": {
176
+ "type": type(last_error).__name__,
177
+ "message": str(last_error),
178
+ "details": self._parse_error_details(last_error),
179
+ "is_retryable": self._is_retryable(
180
+ str(last_error).lower(),
181
+ self._classify_error(last_error, str(last_error).lower()),
182
+ ),
183
+ },
184
+ "retry_info": retry_info,
185
+ }
186
+
187
+ def _classify_error(self, error: Exception, error_msg: str) -> str:
188
+ """
189
+ Classify error type.
190
+
191
+ Args:
192
+ error: The exception object
193
+ error_msg: Error message in lowercase
194
+
195
+ Returns:
196
+ Error classification string
197
+ """
198
+ # Check exception type
199
+ error_class = type(error).__name__.lower()
200
+
201
+ if "timeout" in error_class or "timeout" in error_msg:
202
+ return "timeout"
203
+ elif "connection" in error_class or "connection" in error_msg:
204
+ return "connection"
205
+ elif "rate" in error_msg and "limit" in error_msg:
206
+ return "rate_limit"
207
+ elif "429" in error_msg:
208
+ return "rate_limit"
209
+ elif "auth" in error_msg or "401" in error_msg or "403" in error_msg:
210
+ return "authentication"
211
+ elif "not found" in error_msg or "404" in error_msg:
212
+ return "not_found"
213
+ elif "bad request" in error_msg or "400" in error_msg:
214
+ return "invalid_parameter"
215
+ elif "500" in error_msg or "502" in error_msg or "503" in error_msg or "504" in error_msg:
216
+ return "server_error"
217
+ elif "invalid" in error_msg:
218
+ return "invalid_parameter"
219
+ else:
220
+ return "unknown"
221
+
222
+ def _is_retryable(self, error_msg: str, error_type: str) -> bool:
223
+ """
224
+ Determine if an error is retryable.
225
+
226
+ Args:
227
+ error_msg: Error message in lowercase
228
+ error_type: Classified error type
229
+
230
+ Returns:
231
+ True if error is retryable
232
+ """
233
+ # Check non-retryable first (higher priority)
234
+ for non_retryable in self.NON_RETRYABLE_ERRORS:
235
+ if non_retryable in error_msg or non_retryable in error_type:
236
+ return False
237
+
238
+ # Check retryable
239
+ for retryable in self.RETRYABLE_ERRORS:
240
+ if retryable in error_msg or retryable in error_type:
241
+ return True
242
+
243
+ # Default: retry server errors and unknown errors
244
+ return error_type in [
245
+ "server_error",
246
+ "timeout",
247
+ "connection",
248
+ "rate_limit",
249
+ ]
250
+
251
+ def _parse_error_details(self, error: Exception) -> Dict[str, Any]:
252
+ """
253
+ Extract detailed information from error.
254
+
255
+ Args:
256
+ error: The exception object
257
+
258
+ Returns:
259
+ Dictionary with error details
260
+ """
261
+ details = {"class": type(error).__name__, "message": str(error)}
262
+
263
+ # Extract HTTP status code if available
264
+ if hasattr(error, "response") and hasattr(error.response, "status_code"):
265
+ details["status_code"] = error.response.status_code
266
+ if hasattr(error.response, "text"):
267
+ # Limit size
268
+ details["response_body"] = error.response.text[:500]
269
+
270
+ # Extract additional context
271
+ if hasattr(error, "__cause__") and error.__cause__:
272
+ details["cause"] = str(error.__cause__)
273
+
274
+ return details
275
+
276
+ def _generate_recovery_suggestions(
277
+ self, error: Exception, operation_name: str, provider_name: str
278
+ ) -> List[str]:
279
+ """
280
+ Generate actionable recovery suggestions for the error.
281
+
282
+ Args:
283
+ error: The exception object
284
+ operation_name: Name of the failed operation
285
+ provider_name: Name of the provider
286
+
287
+ Returns:
288
+ List of recovery suggestion strings
289
+ """
290
+ suggestions = []
291
+ error_msg = str(error).lower()
292
+ error_type = self._classify_error(error, error_msg)
293
+
294
+ if error_type == "authentication":
295
+ suggestions.extend(
296
+ [
297
+ f"Check that your {provider_name.upper()} API key is valid and properly configured",
298
+ f"Verify the API key environment variable {provider_name.upper()}_API_KEY is set",
299
+ "Confirm the API key has not expired or been revoked",
300
+ f"Ensure you have the necessary permissions for the {operation_name} operation",
301
+ ]
302
+ )
303
+
304
+ elif error_type == "rate_limit":
305
+ suggestions.extend(
306
+ [
307
+ "Wait before making more requests (rate limit exceeded)",
308
+ "Consider using a different provider if available",
309
+ "Reduce the frequency of requests or implement request batching",
310
+ "Check if you can upgrade your API plan for higher rate limits",
311
+ "Enable caching to reduce API calls",
312
+ ]
313
+ )
314
+
315
+ elif error_type == "not_found":
316
+ suggestions.extend(
317
+ [
318
+ f"Verify the resource ID or parameter values are correct for {provider_name}",
319
+ "Use the search or list operations to find valid resource IDs",
320
+ "Check that the resource exists and is accessible with your credentials",
321
+ f"Review the {provider_name} API documentation for correct resource identifiers",
322
+ ]
323
+ )
324
+
325
+ elif error_type == "invalid_parameter":
326
+ suggestions.extend(
327
+ [
328
+ f"Check the operation schema for {operation_name} to see required parameters",
329
+ "Review parameter types and value formats",
330
+ f"Use get_operation_schema('{operation_name}') to see valid parameters and examples",
331
+ "Verify parameter names are spelled correctly",
332
+ ]
333
+ )
334
+
335
+ elif error_type == "timeout":
336
+ suggestions.extend(
337
+ [
338
+ "Try again with a smaller date range or result limit",
339
+ "Increase the timeout setting in the provider configuration",
340
+ "Check your network connection",
341
+ "The API service may be experiencing high load, try again later",
342
+ ]
343
+ )
344
+
345
+ elif error_type == "connection":
346
+ suggestions.extend(
347
+ [
348
+ "Check your internet connection",
349
+ "Verify the API endpoint is accessible",
350
+ "Check if there are any firewall or proxy issues",
351
+ "The API service may be temporarily unavailable",
352
+ ]
353
+ )
354
+
355
+ elif error_type == "server_error":
356
+ suggestions.extend(
357
+ [
358
+ "The API service is experiencing issues, try again later",
359
+ "Check the API status page for known outages",
360
+ "Try a different provider if available",
361
+ "Reduce the complexity of your request",
362
+ ]
363
+ )
364
+
365
+ else:
366
+ suggestions.extend(
367
+ [
368
+ "Review the error message for specific details",
369
+ f"Check the {provider_name} API documentation for {operation_name}",
370
+ "Verify all required parameters are provided",
371
+ "Try a simpler query to isolate the issue",
372
+ ]
373
+ )
374
+
375
+ return suggestions