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,564 @@
1
+ """
2
+ Federal Reserve Economic Data (FRED) API Provider
3
+
4
+ Provides access to Federal Reserve Economic Data through the FRED API.
5
+ Supports time series data retrieval, search, and metadata operations.
6
+
7
+ API Documentation: https://fred.stlouisfed.org/docs/api/fred/
8
+ """
9
+
10
+ import logging
11
+ from typing import Any, Dict, List, Optional, Tuple
12
+
13
+ from aiecs.tools.apisource.providers.base import (
14
+ BaseAPIProvider,
15
+ expose_operation,
16
+ )
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Optional HTTP client - graceful degradation
21
+ try:
22
+ import requests
23
+
24
+ REQUESTS_AVAILABLE = True
25
+ except ImportError:
26
+ REQUESTS_AVAILABLE = False
27
+
28
+
29
+ class FREDProvider(BaseAPIProvider):
30
+ """
31
+ Federal Reserve Economic Data (FRED) API provider.
32
+
33
+ Provides access to economic indicators including:
34
+ - GDP, unemployment, inflation data
35
+ - Interest rates and monetary indicators
36
+ - Regional economic data
37
+ - International statistics
38
+ """
39
+
40
+ BASE_URL = "https://api.stlouisfed.org/fred"
41
+
42
+ @property
43
+ def name(self) -> str:
44
+ return "fred"
45
+
46
+ @property
47
+ def description(self) -> str:
48
+ return "Federal Reserve Economic Data API for US economic indicators and time series"
49
+
50
+ @property
51
+ def supported_operations(self) -> List[str]:
52
+ return [
53
+ "get_series",
54
+ "search_series",
55
+ "get_series_observations",
56
+ "get_series_info",
57
+ "get_categories",
58
+ "get_releases",
59
+ ]
60
+
61
+ def validate_params(self, operation: str, params: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
62
+ """Validate parameters for FRED operations with detailed guidance"""
63
+
64
+ if operation == "get_series" or operation == "get_series_info":
65
+ if "series_id" not in params:
66
+ return False, (
67
+ "Missing required parameter: series_id\n"
68
+ "Example: {'series_id': 'GDP'}\n"
69
+ "Use search_series operation to find valid series IDs"
70
+ )
71
+
72
+ elif operation == "get_series_observations":
73
+ if "series_id" not in params:
74
+ return False, (
75
+ "Missing required parameter: series_id\n"
76
+ "Example: {'series_id': 'GDP', 'observation_start': '2020-01-01'}\n"
77
+ "Use search_series to find valid series IDs"
78
+ )
79
+
80
+ elif operation == "search_series":
81
+ if "search_text" not in params:
82
+ return False, (
83
+ "Missing required parameter: search_text\n"
84
+ "Example: {'search_text': 'gdp', 'limit': 10}"
85
+ )
86
+
87
+ return True, None
88
+
89
+ # Exposed operations for AI agent visibility
90
+
91
+ @expose_operation(
92
+ operation_name="get_series_observations",
93
+ description="Get FRED economic time series observation data with optional date range filtering",
94
+ )
95
+ def get_series_observations(
96
+ self,
97
+ series_id: str,
98
+ observation_start: Optional[str] = None,
99
+ observation_end: Optional[str] = None,
100
+ limit: Optional[int] = None,
101
+ offset: Optional[int] = None,
102
+ sort_order: Optional[str] = None,
103
+ ) -> Dict[str, Any]:
104
+ """
105
+ Get time series observation data from FRED.
106
+
107
+ Args:
108
+ series_id: FRED series ID (e.g., 'GDP', 'UNRATE', 'CPIAUCSL')
109
+ observation_start: Start date in YYYY-MM-DD format
110
+ observation_end: End date in YYYY-MM-DD format
111
+ limit: Maximum number of observations to return
112
+ offset: Offset for pagination
113
+ sort_order: Sort order ('asc' or 'desc')
114
+
115
+ Returns:
116
+ Dictionary containing observations and metadata
117
+ """
118
+ params = {"series_id": series_id}
119
+ if observation_start:
120
+ params["observation_start"] = observation_start
121
+ if observation_end:
122
+ params["observation_end"] = observation_end
123
+ if limit:
124
+ params["limit"] = limit
125
+ if offset:
126
+ params["offset"] = offset
127
+ if sort_order:
128
+ params["sort_order"] = sort_order
129
+
130
+ return self.execute("get_series_observations", params)
131
+
132
+ @expose_operation(
133
+ operation_name="search_series",
134
+ description="Search for FRED economic data series by keywords",
135
+ )
136
+ def search_series(
137
+ self,
138
+ search_text: str,
139
+ limit: Optional[int] = None,
140
+ offset: Optional[int] = None,
141
+ ) -> Dict[str, Any]:
142
+ """
143
+ Search for FRED series by keywords.
144
+
145
+ Args:
146
+ search_text: Search keywords (e.g., 'unemployment', 'GDP growth')
147
+ limit: Maximum number of results to return
148
+ offset: Offset for pagination
149
+
150
+ Returns:
151
+ Dictionary containing search results and metadata
152
+ """
153
+ params = {"search_text": search_text}
154
+ if limit:
155
+ params["limit"] = limit
156
+ if offset:
157
+ params["offset"] = offset
158
+
159
+ return self.execute("search_series", params)
160
+
161
+ @expose_operation(
162
+ operation_name="get_series_info",
163
+ description="Get detailed metadata and information about a specific FRED series",
164
+ )
165
+ def get_series_info(self, series_id: str) -> Dict[str, Any]:
166
+ """
167
+ Get metadata about a FRED series.
168
+
169
+ Args:
170
+ series_id: FRED series ID (e.g., 'GDP', 'UNRATE')
171
+
172
+ Returns:
173
+ Dictionary containing series metadata
174
+ """
175
+ return self.execute("get_series_info", {"series_id": series_id})
176
+
177
+ @expose_operation(
178
+ operation_name="get_categories",
179
+ description="Get FRED data categories for browsing available datasets",
180
+ )
181
+ def get_categories(self, category_id: Optional[int] = None) -> Dict[str, Any]:
182
+ """
183
+ Get FRED categories.
184
+
185
+ Args:
186
+ category_id: Optional category ID to get subcategories
187
+
188
+ Returns:
189
+ Dictionary containing category information
190
+ """
191
+ params = {}
192
+ if category_id:
193
+ params["category_id"] = category_id
194
+
195
+ return self.execute("get_categories", params)
196
+
197
+ @expose_operation(
198
+ operation_name="get_releases",
199
+ description="Get FRED data release information and schedules",
200
+ )
201
+ def get_releases(self, limit: Optional[int] = None) -> Dict[str, Any]:
202
+ """
203
+ Get FRED releases.
204
+
205
+ Args:
206
+ limit: Maximum number of releases to return
207
+
208
+ Returns:
209
+ Dictionary containing release information
210
+ """
211
+ params = {}
212
+ if limit:
213
+ params["limit"] = limit
214
+
215
+ return self.execute("get_releases", params)
216
+
217
+ def fetch(self, operation: str, params: Dict[str, Any]) -> Dict[str, Any]:
218
+ """Fetch data from FRED API"""
219
+
220
+ if not REQUESTS_AVAILABLE:
221
+ raise ImportError(
222
+ "requests library is required for FRED provider. Install with: pip install requests"
223
+ )
224
+
225
+ # Get API key
226
+ api_key = self._get_api_key("FRED_API_KEY")
227
+ if not api_key:
228
+ raise ValueError(
229
+ "FRED API key not found. Set FRED_API_KEY environment variable or "
230
+ "provide 'api_key' in config"
231
+ )
232
+
233
+ # Build endpoint based on operation
234
+ if operation == "get_series" or operation == "get_series_observations":
235
+ endpoint = f"{self.BASE_URL}/series/observations"
236
+ query_params = {
237
+ "series_id": params["series_id"],
238
+ "api_key": api_key,
239
+ "file_type": "json",
240
+ }
241
+
242
+ # Optional parameters
243
+ if "limit" in params:
244
+ query_params["limit"] = params["limit"]
245
+ if "offset" in params:
246
+ query_params["offset"] = params["offset"]
247
+ if "sort_order" in params:
248
+ query_params["sort_order"] = params["sort_order"]
249
+ if "observation_start" in params:
250
+ query_params["observation_start"] = params["observation_start"]
251
+ if "observation_end" in params:
252
+ query_params["observation_end"] = params["observation_end"]
253
+
254
+ elif operation == "get_series_info":
255
+ endpoint = f"{self.BASE_URL}/series"
256
+ query_params = {
257
+ "series_id": params["series_id"],
258
+ "api_key": api_key,
259
+ "file_type": "json",
260
+ }
261
+
262
+ elif operation == "search_series":
263
+ endpoint = f"{self.BASE_URL}/series/search"
264
+ query_params = {
265
+ "search_text": params["search_text"],
266
+ "api_key": api_key,
267
+ "file_type": "json",
268
+ }
269
+
270
+ if "limit" in params:
271
+ query_params["limit"] = params["limit"]
272
+ if "offset" in params:
273
+ query_params["offset"] = params["offset"]
274
+
275
+ elif operation == "get_categories":
276
+ endpoint = f"{self.BASE_URL}/category"
277
+ query_params = {"api_key": api_key, "file_type": "json"}
278
+
279
+ if "category_id" in params:
280
+ query_params["category_id"] = params["category_id"]
281
+
282
+ elif operation == "get_releases":
283
+ endpoint = f"{self.BASE_URL}/releases"
284
+ query_params = {"api_key": api_key, "file_type": "json"}
285
+
286
+ if "limit" in params:
287
+ query_params["limit"] = params["limit"]
288
+
289
+ else:
290
+ raise ValueError(f"Unknown operation: {operation}")
291
+
292
+ # Make API request
293
+ timeout = self.config.get("timeout", 30)
294
+ try:
295
+ response = requests.get(endpoint, params=query_params, timeout=timeout)
296
+ response.raise_for_status()
297
+
298
+ data = response.json()
299
+
300
+ # Extract relevant data based on operation
301
+ if operation in ["get_series", "get_series_observations"]:
302
+ result_data = data.get("observations", [])
303
+ elif operation == "search_series":
304
+ result_data = data.get("seriess", [])
305
+ elif operation == "get_series_info":
306
+ result_data = data.get("seriess", [])
307
+ elif operation == "get_categories":
308
+ result_data = data.get("categories", [])
309
+ elif operation == "get_releases":
310
+ result_data = data.get("releases", [])
311
+ else:
312
+ result_data = data
313
+
314
+ return self._format_response(
315
+ operation=operation,
316
+ data=result_data,
317
+ source=f"FRED API - {endpoint}",
318
+ )
319
+
320
+ except requests.exceptions.RequestException as e:
321
+ self.logger.error(f"FRED API request failed: {e}")
322
+ raise Exception(f"FRED API request failed: {str(e)}")
323
+
324
+ def get_operation_schema(self, operation: str) -> Optional[Dict[str, Any]]:
325
+ """Get detailed schema for FRED operations"""
326
+
327
+ schemas = {
328
+ "get_series_observations": {
329
+ "description": "Get time series observation data from FRED",
330
+ "parameters": {
331
+ "series_id": {
332
+ "type": "string",
333
+ "required": True,
334
+ "description": "FRED series ID (e.g., GDP, UNRATE, CPIAUCSL)",
335
+ "examples": ["GDP", "UNRATE", "CPIAUCSL", "DGS10"],
336
+ "validation": {
337
+ "pattern": r"^[A-Z0-9]+$",
338
+ "max_length": 50,
339
+ },
340
+ },
341
+ "observation_start": {
342
+ "type": "string",
343
+ "required": False,
344
+ "description": "Start date for observations (YYYY-MM-DD)",
345
+ "examples": ["2020-01-01", "2015-06-15"],
346
+ "default": "earliest available",
347
+ },
348
+ "observation_end": {
349
+ "type": "string",
350
+ "required": False,
351
+ "description": "End date for observations (YYYY-MM-DD)",
352
+ "examples": ["2025-10-15", "2023-12-31"],
353
+ "default": "latest available",
354
+ },
355
+ "limit": {
356
+ "type": "integer",
357
+ "required": False,
358
+ "description": "Maximum number of observations",
359
+ "examples": [100, 1000],
360
+ "default": 100000,
361
+ },
362
+ "sort_order": {
363
+ "type": "string",
364
+ "required": False,
365
+ "description": "Sort order (asc/desc)",
366
+ "examples": ["desc", "asc"],
367
+ "default": "asc",
368
+ },
369
+ },
370
+ "examples": [
371
+ {
372
+ "description": "Get GDP data for last 5 years",
373
+ "params": {
374
+ "series_id": "GDP",
375
+ "observation_start": "2020-01-01",
376
+ "limit": 100,
377
+ },
378
+ }
379
+ ],
380
+ },
381
+ "search_series": {
382
+ "description": "Search for FRED series by text query",
383
+ "parameters": {
384
+ "search_text": {
385
+ "type": "string",
386
+ "required": True,
387
+ "description": "Text to search for in series",
388
+ "examples": ["gdp", "unemployment", "inflation"],
389
+ },
390
+ "limit": {
391
+ "type": "integer",
392
+ "required": False,
393
+ "description": "Maximum results to return",
394
+ "examples": [10, 50],
395
+ "default": 1000,
396
+ },
397
+ },
398
+ "examples": [
399
+ {
400
+ "description": "Search for GDP series",
401
+ "params": {"search_text": "gdp", "limit": 10},
402
+ }
403
+ ],
404
+ },
405
+ "get_series_info": {
406
+ "description": "Get metadata about a FRED series",
407
+ "parameters": {
408
+ "series_id": {
409
+ "type": "string",
410
+ "required": True,
411
+ "description": "FRED series ID to get information about",
412
+ "examples": ["GDP", "UNRATE", "CPIAUCSL"],
413
+ }
414
+ },
415
+ "examples": [
416
+ {
417
+ "description": "Get info about GDP series",
418
+ "params": {"series_id": "GDP"},
419
+ }
420
+ ],
421
+ },
422
+ "get_categories": {
423
+ "description": "Get FRED data categories",
424
+ "parameters": {
425
+ "category_id": {
426
+ "type": "integer",
427
+ "required": False,
428
+ "description": "Category ID to get subcategories (omit for root categories)",
429
+ "examples": [125, 32991],
430
+ }
431
+ },
432
+ "examples": [
433
+ {"description": "Get root categories", "params": {}},
434
+ {
435
+ "description": "Get subcategories of category 125",
436
+ "params": {"category_id": 125},
437
+ },
438
+ ],
439
+ },
440
+ "get_releases": {
441
+ "description": "Get FRED data releases",
442
+ "parameters": {
443
+ "limit": {
444
+ "type": "integer",
445
+ "required": False,
446
+ "description": "Maximum number of releases to return",
447
+ "examples": [10, 50],
448
+ "default": 1000,
449
+ }
450
+ },
451
+ "examples": [
452
+ {
453
+ "description": "Get recent releases",
454
+ "params": {"limit": 20},
455
+ }
456
+ ],
457
+ },
458
+ }
459
+
460
+ return schemas.get(operation)
461
+
462
+ def validate_and_clean_data(self, operation: str, raw_data: Any) -> Dict[str, Any]:
463
+ """Validate and clean FRED data"""
464
+
465
+ result = {
466
+ "data": raw_data,
467
+ "validation_warnings": [],
468
+ "statistics": {},
469
+ }
470
+
471
+ if operation in ["get_series", "get_series_observations"]:
472
+ if isinstance(raw_data, list) and len(raw_data) > 0:
473
+ # Check for missing values (FRED uses '.')
474
+ completeness_info = self.validator.check_data_completeness(
475
+ raw_data, "value", [".", "NA"]
476
+ )
477
+
478
+ result["statistics"]["completeness"] = completeness_info
479
+
480
+ if completeness_info["missing_count"] > 0:
481
+ result["validation_warnings"].append(
482
+ f"{completeness_info['missing_count']} missing values detected "
483
+ f"({completeness_info['completeness']:.1%} complete)"
484
+ )
485
+
486
+ # Extract numeric values for outlier detection
487
+ numeric_values = []
488
+ for item in raw_data:
489
+ value = item.get("value")
490
+ if value not in [".", "NA", None]:
491
+ try:
492
+ numeric_values.append(float(value))
493
+ except (ValueError, TypeError):
494
+ pass
495
+
496
+ if len(numeric_values) >= 4:
497
+ # Detect outliers
498
+ outlier_indices = self.validator.detect_outliers(
499
+ numeric_values, method="iqr", threshold=3.0
500
+ )
501
+
502
+ if outlier_indices:
503
+ result["validation_warnings"].append(
504
+ f"{len(outlier_indices)} potential outliers detected"
505
+ )
506
+ result["statistics"]["outliers_count"] = len(outlier_indices)
507
+
508
+ # Calculate value range
509
+ value_range = self.validator.calculate_value_range(raw_data, "value")
510
+ if value_range:
511
+ result["statistics"]["value_range"] = value_range
512
+
513
+ # Detect time gaps
514
+ time_gaps = self.validator.detect_time_gaps(raw_data, "date")
515
+ if time_gaps:
516
+ result["validation_warnings"].append(
517
+ f"{len(time_gaps)} time gaps detected in series"
518
+ )
519
+ result["statistics"]["time_gaps"] = len(time_gaps)
520
+
521
+ return result
522
+
523
+ def calculate_data_quality(
524
+ self, operation: str, data: Any, response_time_ms: float
525
+ ) -> Dict[str, Any]:
526
+ """Calculate quality metadata specific to FRED data"""
527
+
528
+ # Get base quality from parent
529
+ quality = super().calculate_data_quality(operation, data, response_time_ms)
530
+
531
+ # FRED-specific quality enhancements
532
+ # FRED is official government data
533
+ quality["authority_level"] = "official"
534
+ quality["confidence"] = 0.95 # High confidence in FRED data
535
+
536
+ # For time series, assess freshness
537
+ if operation in ["get_series", "get_series_observations"]:
538
+ if isinstance(data, list) and len(data) > 0:
539
+ # Check the date of most recent observation
540
+ latest_date = None
541
+ for item in data:
542
+ if "date" in item:
543
+ try:
544
+ from datetime import datetime
545
+
546
+ date_obj = datetime.strptime(item["date"], "%Y-%m-%d")
547
+ if latest_date is None or date_obj > latest_date:
548
+ latest_date = date_obj
549
+ except Exception:
550
+ pass
551
+
552
+ if latest_date:
553
+ from datetime import datetime
554
+
555
+ age_days = (datetime.now() - latest_date).days
556
+ quality["freshness_hours"] = age_days * 24
557
+
558
+ # Adjust quality score based on data freshness
559
+ if age_days < 30:
560
+ quality["score"] = min(quality["score"] + 0.1, 1.0)
561
+ elif age_days > 365:
562
+ quality["score"] = max(quality["score"] - 0.1, 0.0)
563
+
564
+ return quality