aiecs 1.0.1__py3-none-any.whl → 1.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of aiecs might be problematic. Click here for more details.

Files changed (340) hide show
  1. aiecs/__init__.py +13 -16
  2. aiecs/__main__.py +7 -7
  3. aiecs/aiecs_client.py +269 -75
  4. aiecs/application/executors/operation_executor.py +79 -54
  5. aiecs/application/knowledge_graph/__init__.py +7 -0
  6. aiecs/application/knowledge_graph/builder/__init__.py +37 -0
  7. aiecs/application/knowledge_graph/builder/data_quality.py +302 -0
  8. aiecs/application/knowledge_graph/builder/data_reshaping.py +293 -0
  9. aiecs/application/knowledge_graph/builder/document_builder.py +369 -0
  10. aiecs/application/knowledge_graph/builder/graph_builder.py +490 -0
  11. aiecs/application/knowledge_graph/builder/import_optimizer.py +396 -0
  12. aiecs/application/knowledge_graph/builder/schema_inference.py +462 -0
  13. aiecs/application/knowledge_graph/builder/schema_mapping.py +563 -0
  14. aiecs/application/knowledge_graph/builder/structured_pipeline.py +1384 -0
  15. aiecs/application/knowledge_graph/builder/text_chunker.py +317 -0
  16. aiecs/application/knowledge_graph/extractors/__init__.py +27 -0
  17. aiecs/application/knowledge_graph/extractors/base.py +98 -0
  18. aiecs/application/knowledge_graph/extractors/llm_entity_extractor.py +422 -0
  19. aiecs/application/knowledge_graph/extractors/llm_relation_extractor.py +347 -0
  20. aiecs/application/knowledge_graph/extractors/ner_entity_extractor.py +241 -0
  21. aiecs/application/knowledge_graph/fusion/__init__.py +78 -0
  22. aiecs/application/knowledge_graph/fusion/ab_testing.py +395 -0
  23. aiecs/application/knowledge_graph/fusion/abbreviation_expander.py +327 -0
  24. aiecs/application/knowledge_graph/fusion/alias_index.py +597 -0
  25. aiecs/application/knowledge_graph/fusion/alias_matcher.py +384 -0
  26. aiecs/application/knowledge_graph/fusion/cache_coordinator.py +343 -0
  27. aiecs/application/knowledge_graph/fusion/entity_deduplicator.py +433 -0
  28. aiecs/application/knowledge_graph/fusion/entity_linker.py +511 -0
  29. aiecs/application/knowledge_graph/fusion/evaluation_dataset.py +240 -0
  30. aiecs/application/knowledge_graph/fusion/knowledge_fusion.py +632 -0
  31. aiecs/application/knowledge_graph/fusion/matching_config.py +489 -0
  32. aiecs/application/knowledge_graph/fusion/name_normalizer.py +352 -0
  33. aiecs/application/knowledge_graph/fusion/relation_deduplicator.py +183 -0
  34. aiecs/application/knowledge_graph/fusion/semantic_name_matcher.py +464 -0
  35. aiecs/application/knowledge_graph/fusion/similarity_pipeline.py +534 -0
  36. aiecs/application/knowledge_graph/pattern_matching/__init__.py +21 -0
  37. aiecs/application/knowledge_graph/pattern_matching/pattern_matcher.py +342 -0
  38. aiecs/application/knowledge_graph/pattern_matching/query_executor.py +366 -0
  39. aiecs/application/knowledge_graph/profiling/__init__.py +12 -0
  40. aiecs/application/knowledge_graph/profiling/query_plan_visualizer.py +195 -0
  41. aiecs/application/knowledge_graph/profiling/query_profiler.py +223 -0
  42. aiecs/application/knowledge_graph/reasoning/__init__.py +27 -0
  43. aiecs/application/knowledge_graph/reasoning/evidence_synthesis.py +341 -0
  44. aiecs/application/knowledge_graph/reasoning/inference_engine.py +500 -0
  45. aiecs/application/knowledge_graph/reasoning/logic_form_parser.py +163 -0
  46. aiecs/application/knowledge_graph/reasoning/logic_parser/__init__.py +79 -0
  47. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_builder.py +513 -0
  48. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_nodes.py +913 -0
  49. aiecs/application/knowledge_graph/reasoning/logic_parser/ast_validator.py +866 -0
  50. aiecs/application/knowledge_graph/reasoning/logic_parser/error_handler.py +475 -0
  51. aiecs/application/knowledge_graph/reasoning/logic_parser/parser.py +396 -0
  52. aiecs/application/knowledge_graph/reasoning/logic_parser/query_context.py +208 -0
  53. aiecs/application/knowledge_graph/reasoning/logic_query_integration.py +170 -0
  54. aiecs/application/knowledge_graph/reasoning/query_planner.py +855 -0
  55. aiecs/application/knowledge_graph/reasoning/reasoning_engine.py +518 -0
  56. aiecs/application/knowledge_graph/retrieval/__init__.py +27 -0
  57. aiecs/application/knowledge_graph/retrieval/query_intent_classifier.py +211 -0
  58. aiecs/application/knowledge_graph/retrieval/retrieval_strategies.py +592 -0
  59. aiecs/application/knowledge_graph/retrieval/strategy_types.py +23 -0
  60. aiecs/application/knowledge_graph/search/__init__.py +59 -0
  61. aiecs/application/knowledge_graph/search/hybrid_search.py +457 -0
  62. aiecs/application/knowledge_graph/search/reranker.py +293 -0
  63. aiecs/application/knowledge_graph/search/reranker_strategies.py +535 -0
  64. aiecs/application/knowledge_graph/search/text_similarity.py +392 -0
  65. aiecs/application/knowledge_graph/traversal/__init__.py +15 -0
  66. aiecs/application/knowledge_graph/traversal/enhanced_traversal.py +305 -0
  67. aiecs/application/knowledge_graph/traversal/path_scorer.py +271 -0
  68. aiecs/application/knowledge_graph/validators/__init__.py +13 -0
  69. aiecs/application/knowledge_graph/validators/relation_validator.py +239 -0
  70. aiecs/application/knowledge_graph/visualization/__init__.py +11 -0
  71. aiecs/application/knowledge_graph/visualization/graph_visualizer.py +313 -0
  72. aiecs/common/__init__.py +9 -0
  73. aiecs/common/knowledge_graph/__init__.py +17 -0
  74. aiecs/common/knowledge_graph/runnable.py +471 -0
  75. aiecs/config/__init__.py +20 -5
  76. aiecs/config/config.py +762 -31
  77. aiecs/config/graph_config.py +131 -0
  78. aiecs/config/tool_config.py +399 -0
  79. aiecs/core/__init__.py +29 -13
  80. aiecs/core/interface/__init__.py +2 -2
  81. aiecs/core/interface/execution_interface.py +22 -22
  82. aiecs/core/interface/storage_interface.py +37 -88
  83. aiecs/core/registry/__init__.py +31 -0
  84. aiecs/core/registry/service_registry.py +92 -0
  85. aiecs/domain/__init__.py +270 -1
  86. aiecs/domain/agent/__init__.py +191 -0
  87. aiecs/domain/agent/base_agent.py +3870 -0
  88. aiecs/domain/agent/exceptions.py +99 -0
  89. aiecs/domain/agent/graph_aware_mixin.py +569 -0
  90. aiecs/domain/agent/hybrid_agent.py +1435 -0
  91. aiecs/domain/agent/integration/__init__.py +29 -0
  92. aiecs/domain/agent/integration/context_compressor.py +216 -0
  93. aiecs/domain/agent/integration/context_engine_adapter.py +587 -0
  94. aiecs/domain/agent/integration/protocols.py +281 -0
  95. aiecs/domain/agent/integration/retry_policy.py +218 -0
  96. aiecs/domain/agent/integration/role_config.py +213 -0
  97. aiecs/domain/agent/knowledge_aware_agent.py +1892 -0
  98. aiecs/domain/agent/lifecycle.py +291 -0
  99. aiecs/domain/agent/llm_agent.py +692 -0
  100. aiecs/domain/agent/memory/__init__.py +12 -0
  101. aiecs/domain/agent/memory/conversation.py +1124 -0
  102. aiecs/domain/agent/migration/__init__.py +14 -0
  103. aiecs/domain/agent/migration/conversion.py +163 -0
  104. aiecs/domain/agent/migration/legacy_wrapper.py +86 -0
  105. aiecs/domain/agent/models.py +884 -0
  106. aiecs/domain/agent/observability.py +479 -0
  107. aiecs/domain/agent/persistence.py +449 -0
  108. aiecs/domain/agent/prompts/__init__.py +29 -0
  109. aiecs/domain/agent/prompts/builder.py +159 -0
  110. aiecs/domain/agent/prompts/formatters.py +187 -0
  111. aiecs/domain/agent/prompts/template.py +255 -0
  112. aiecs/domain/agent/registry.py +253 -0
  113. aiecs/domain/agent/tool_agent.py +444 -0
  114. aiecs/domain/agent/tools/__init__.py +15 -0
  115. aiecs/domain/agent/tools/schema_generator.py +364 -0
  116. aiecs/domain/community/__init__.py +155 -0
  117. aiecs/domain/community/agent_adapter.py +469 -0
  118. aiecs/domain/community/analytics.py +432 -0
  119. aiecs/domain/community/collaborative_workflow.py +648 -0
  120. aiecs/domain/community/communication_hub.py +634 -0
  121. aiecs/domain/community/community_builder.py +320 -0
  122. aiecs/domain/community/community_integration.py +796 -0
  123. aiecs/domain/community/community_manager.py +803 -0
  124. aiecs/domain/community/decision_engine.py +849 -0
  125. aiecs/domain/community/exceptions.py +231 -0
  126. aiecs/domain/community/models/__init__.py +33 -0
  127. aiecs/domain/community/models/community_models.py +234 -0
  128. aiecs/domain/community/resource_manager.py +461 -0
  129. aiecs/domain/community/shared_context_manager.py +589 -0
  130. aiecs/domain/context/__init__.py +40 -10
  131. aiecs/domain/context/context_engine.py +1910 -0
  132. aiecs/domain/context/conversation_models.py +87 -53
  133. aiecs/domain/context/graph_memory.py +582 -0
  134. aiecs/domain/execution/model.py +12 -4
  135. aiecs/domain/knowledge_graph/__init__.py +19 -0
  136. aiecs/domain/knowledge_graph/models/__init__.py +52 -0
  137. aiecs/domain/knowledge_graph/models/entity.py +148 -0
  138. aiecs/domain/knowledge_graph/models/evidence.py +178 -0
  139. aiecs/domain/knowledge_graph/models/inference_rule.py +184 -0
  140. aiecs/domain/knowledge_graph/models/path.py +171 -0
  141. aiecs/domain/knowledge_graph/models/path_pattern.py +171 -0
  142. aiecs/domain/knowledge_graph/models/query.py +261 -0
  143. aiecs/domain/knowledge_graph/models/query_plan.py +181 -0
  144. aiecs/domain/knowledge_graph/models/relation.py +202 -0
  145. aiecs/domain/knowledge_graph/schema/__init__.py +23 -0
  146. aiecs/domain/knowledge_graph/schema/entity_type.py +131 -0
  147. aiecs/domain/knowledge_graph/schema/graph_schema.py +253 -0
  148. aiecs/domain/knowledge_graph/schema/property_schema.py +143 -0
  149. aiecs/domain/knowledge_graph/schema/relation_type.py +163 -0
  150. aiecs/domain/knowledge_graph/schema/schema_manager.py +691 -0
  151. aiecs/domain/knowledge_graph/schema/type_enums.py +209 -0
  152. aiecs/domain/task/dsl_processor.py +172 -56
  153. aiecs/domain/task/model.py +20 -8
  154. aiecs/domain/task/task_context.py +27 -24
  155. aiecs/infrastructure/__init__.py +0 -2
  156. aiecs/infrastructure/graph_storage/__init__.py +11 -0
  157. aiecs/infrastructure/graph_storage/base.py +837 -0
  158. aiecs/infrastructure/graph_storage/batch_operations.py +458 -0
  159. aiecs/infrastructure/graph_storage/cache.py +424 -0
  160. aiecs/infrastructure/graph_storage/distributed.py +223 -0
  161. aiecs/infrastructure/graph_storage/error_handling.py +380 -0
  162. aiecs/infrastructure/graph_storage/graceful_degradation.py +294 -0
  163. aiecs/infrastructure/graph_storage/health_checks.py +378 -0
  164. aiecs/infrastructure/graph_storage/in_memory.py +1197 -0
  165. aiecs/infrastructure/graph_storage/index_optimization.py +446 -0
  166. aiecs/infrastructure/graph_storage/lazy_loading.py +431 -0
  167. aiecs/infrastructure/graph_storage/metrics.py +344 -0
  168. aiecs/infrastructure/graph_storage/migration.py +400 -0
  169. aiecs/infrastructure/graph_storage/pagination.py +483 -0
  170. aiecs/infrastructure/graph_storage/performance_monitoring.py +456 -0
  171. aiecs/infrastructure/graph_storage/postgres.py +1563 -0
  172. aiecs/infrastructure/graph_storage/property_storage.py +353 -0
  173. aiecs/infrastructure/graph_storage/protocols.py +76 -0
  174. aiecs/infrastructure/graph_storage/query_optimizer.py +642 -0
  175. aiecs/infrastructure/graph_storage/schema_cache.py +290 -0
  176. aiecs/infrastructure/graph_storage/sqlite.py +1373 -0
  177. aiecs/infrastructure/graph_storage/streaming.py +487 -0
  178. aiecs/infrastructure/graph_storage/tenant.py +412 -0
  179. aiecs/infrastructure/messaging/celery_task_manager.py +92 -54
  180. aiecs/infrastructure/messaging/websocket_manager.py +51 -35
  181. aiecs/infrastructure/monitoring/__init__.py +22 -0
  182. aiecs/infrastructure/monitoring/executor_metrics.py +45 -11
  183. aiecs/infrastructure/monitoring/global_metrics_manager.py +212 -0
  184. aiecs/infrastructure/monitoring/structured_logger.py +3 -7
  185. aiecs/infrastructure/monitoring/tracing_manager.py +63 -35
  186. aiecs/infrastructure/persistence/__init__.py +14 -1
  187. aiecs/infrastructure/persistence/context_engine_client.py +184 -0
  188. aiecs/infrastructure/persistence/database_manager.py +67 -43
  189. aiecs/infrastructure/persistence/file_storage.py +180 -103
  190. aiecs/infrastructure/persistence/redis_client.py +74 -21
  191. aiecs/llm/__init__.py +73 -25
  192. aiecs/llm/callbacks/__init__.py +11 -0
  193. aiecs/llm/{custom_callbacks.py → callbacks/custom_callbacks.py} +26 -19
  194. aiecs/llm/client_factory.py +224 -36
  195. aiecs/llm/client_resolver.py +155 -0
  196. aiecs/llm/clients/__init__.py +38 -0
  197. aiecs/llm/clients/base_client.py +324 -0
  198. aiecs/llm/clients/google_function_calling_mixin.py +457 -0
  199. aiecs/llm/clients/googleai_client.py +241 -0
  200. aiecs/llm/clients/openai_client.py +158 -0
  201. aiecs/llm/clients/openai_compatible_mixin.py +367 -0
  202. aiecs/llm/clients/vertex_client.py +897 -0
  203. aiecs/llm/clients/xai_client.py +201 -0
  204. aiecs/llm/config/__init__.py +51 -0
  205. aiecs/llm/config/config_loader.py +272 -0
  206. aiecs/llm/config/config_validator.py +206 -0
  207. aiecs/llm/config/model_config.py +143 -0
  208. aiecs/llm/protocols.py +149 -0
  209. aiecs/llm/utils/__init__.py +10 -0
  210. aiecs/llm/utils/validate_config.py +89 -0
  211. aiecs/main.py +140 -121
  212. aiecs/scripts/aid/VERSION_MANAGEMENT.md +138 -0
  213. aiecs/scripts/aid/__init__.py +19 -0
  214. aiecs/scripts/aid/module_checker.py +499 -0
  215. aiecs/scripts/aid/version_manager.py +235 -0
  216. aiecs/scripts/{DEPENDENCY_SYSTEM_SUMMARY.md → dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md} +1 -0
  217. aiecs/scripts/{README_DEPENDENCY_CHECKER.md → dependance_check/README_DEPENDENCY_CHECKER.md} +1 -0
  218. aiecs/scripts/dependance_check/__init__.py +15 -0
  219. aiecs/scripts/dependance_check/dependency_checker.py +1835 -0
  220. aiecs/scripts/{dependency_fixer.py → dependance_check/dependency_fixer.py} +192 -90
  221. aiecs/scripts/{download_nlp_data.py → dependance_check/download_nlp_data.py} +203 -71
  222. aiecs/scripts/dependance_patch/__init__.py +7 -0
  223. aiecs/scripts/dependance_patch/fix_weasel/__init__.py +11 -0
  224. aiecs/scripts/{fix_weasel_validator.py → dependance_patch/fix_weasel/fix_weasel_validator.py} +21 -14
  225. aiecs/scripts/{patch_weasel_library.sh → dependance_patch/fix_weasel/patch_weasel_library.sh} +1 -1
  226. aiecs/scripts/knowledge_graph/__init__.py +3 -0
  227. aiecs/scripts/knowledge_graph/run_threshold_experiments.py +212 -0
  228. aiecs/scripts/migrations/multi_tenancy/README.md +142 -0
  229. aiecs/scripts/tools_develop/README.md +671 -0
  230. aiecs/scripts/tools_develop/README_CONFIG_CHECKER.md +273 -0
  231. aiecs/scripts/tools_develop/TOOLS_CONFIG_GUIDE.md +1287 -0
  232. aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +234 -0
  233. aiecs/scripts/tools_develop/__init__.py +21 -0
  234. aiecs/scripts/tools_develop/check_all_tools_config.py +548 -0
  235. aiecs/scripts/tools_develop/check_type_annotations.py +257 -0
  236. aiecs/scripts/tools_develop/pre-commit-schema-coverage.sh +66 -0
  237. aiecs/scripts/tools_develop/schema_coverage.py +511 -0
  238. aiecs/scripts/tools_develop/validate_tool_schemas.py +475 -0
  239. aiecs/scripts/tools_develop/verify_executor_config_fix.py +98 -0
  240. aiecs/scripts/tools_develop/verify_tools.py +352 -0
  241. aiecs/tasks/__init__.py +0 -1
  242. aiecs/tasks/worker.py +115 -47
  243. aiecs/tools/__init__.py +194 -72
  244. aiecs/tools/apisource/__init__.py +99 -0
  245. aiecs/tools/apisource/intelligence/__init__.py +19 -0
  246. aiecs/tools/apisource/intelligence/data_fusion.py +632 -0
  247. aiecs/tools/apisource/intelligence/query_analyzer.py +417 -0
  248. aiecs/tools/apisource/intelligence/search_enhancer.py +385 -0
  249. aiecs/tools/apisource/monitoring/__init__.py +9 -0
  250. aiecs/tools/apisource/monitoring/metrics.py +330 -0
  251. aiecs/tools/apisource/providers/__init__.py +112 -0
  252. aiecs/tools/apisource/providers/base.py +671 -0
  253. aiecs/tools/apisource/providers/census.py +397 -0
  254. aiecs/tools/apisource/providers/fred.py +535 -0
  255. aiecs/tools/apisource/providers/newsapi.py +409 -0
  256. aiecs/tools/apisource/providers/worldbank.py +352 -0
  257. aiecs/tools/apisource/reliability/__init__.py +12 -0
  258. aiecs/tools/apisource/reliability/error_handler.py +363 -0
  259. aiecs/tools/apisource/reliability/fallback_strategy.py +376 -0
  260. aiecs/tools/apisource/tool.py +832 -0
  261. aiecs/tools/apisource/utils/__init__.py +9 -0
  262. aiecs/tools/apisource/utils/validators.py +334 -0
  263. aiecs/tools/base_tool.py +415 -21
  264. aiecs/tools/docs/__init__.py +121 -0
  265. aiecs/tools/docs/ai_document_orchestrator.py +607 -0
  266. aiecs/tools/docs/ai_document_writer_orchestrator.py +2350 -0
  267. aiecs/tools/docs/content_insertion_tool.py +1320 -0
  268. aiecs/tools/docs/document_creator_tool.py +1323 -0
  269. aiecs/tools/docs/document_layout_tool.py +1160 -0
  270. aiecs/tools/docs/document_parser_tool.py +1011 -0
  271. aiecs/tools/docs/document_writer_tool.py +1829 -0
  272. aiecs/tools/knowledge_graph/__init__.py +17 -0
  273. aiecs/tools/knowledge_graph/graph_reasoning_tool.py +807 -0
  274. aiecs/tools/knowledge_graph/graph_search_tool.py +944 -0
  275. aiecs/tools/knowledge_graph/kg_builder_tool.py +524 -0
  276. aiecs/tools/langchain_adapter.py +300 -138
  277. aiecs/tools/schema_generator.py +455 -0
  278. aiecs/tools/search_tool/__init__.py +100 -0
  279. aiecs/tools/search_tool/analyzers.py +581 -0
  280. aiecs/tools/search_tool/cache.py +264 -0
  281. aiecs/tools/search_tool/constants.py +128 -0
  282. aiecs/tools/search_tool/context.py +224 -0
  283. aiecs/tools/search_tool/core.py +778 -0
  284. aiecs/tools/search_tool/deduplicator.py +119 -0
  285. aiecs/tools/search_tool/error_handler.py +242 -0
  286. aiecs/tools/search_tool/metrics.py +343 -0
  287. aiecs/tools/search_tool/rate_limiter.py +172 -0
  288. aiecs/tools/search_tool/schemas.py +275 -0
  289. aiecs/tools/statistics/__init__.py +80 -0
  290. aiecs/tools/statistics/ai_data_analysis_orchestrator.py +646 -0
  291. aiecs/tools/statistics/ai_insight_generator_tool.py +508 -0
  292. aiecs/tools/statistics/ai_report_orchestrator_tool.py +684 -0
  293. aiecs/tools/statistics/data_loader_tool.py +555 -0
  294. aiecs/tools/statistics/data_profiler_tool.py +638 -0
  295. aiecs/tools/statistics/data_transformer_tool.py +580 -0
  296. aiecs/tools/statistics/data_visualizer_tool.py +498 -0
  297. aiecs/tools/statistics/model_trainer_tool.py +507 -0
  298. aiecs/tools/statistics/statistical_analyzer_tool.py +472 -0
  299. aiecs/tools/task_tools/__init__.py +49 -36
  300. aiecs/tools/task_tools/chart_tool.py +200 -184
  301. aiecs/tools/task_tools/classfire_tool.py +268 -267
  302. aiecs/tools/task_tools/image_tool.py +175 -131
  303. aiecs/tools/task_tools/office_tool.py +226 -146
  304. aiecs/tools/task_tools/pandas_tool.py +477 -121
  305. aiecs/tools/task_tools/report_tool.py +390 -142
  306. aiecs/tools/task_tools/research_tool.py +149 -79
  307. aiecs/tools/task_tools/scraper_tool.py +339 -145
  308. aiecs/tools/task_tools/stats_tool.py +448 -209
  309. aiecs/tools/temp_file_manager.py +26 -24
  310. aiecs/tools/tool_executor/__init__.py +18 -16
  311. aiecs/tools/tool_executor/tool_executor.py +364 -52
  312. aiecs/utils/LLM_output_structor.py +74 -48
  313. aiecs/utils/__init__.py +14 -3
  314. aiecs/utils/base_callback.py +0 -3
  315. aiecs/utils/cache_provider.py +696 -0
  316. aiecs/utils/execution_utils.py +50 -31
  317. aiecs/utils/prompt_loader.py +1 -0
  318. aiecs/utils/token_usage_repository.py +37 -11
  319. aiecs/ws/socket_server.py +14 -4
  320. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/METADATA +52 -15
  321. aiecs-1.7.6.dist-info/RECORD +337 -0
  322. aiecs-1.7.6.dist-info/entry_points.txt +13 -0
  323. aiecs/config/registry.py +0 -19
  324. aiecs/domain/context/content_engine.py +0 -982
  325. aiecs/llm/base_client.py +0 -99
  326. aiecs/llm/openai_client.py +0 -125
  327. aiecs/llm/vertex_client.py +0 -186
  328. aiecs/llm/xai_client.py +0 -184
  329. aiecs/scripts/dependency_checker.py +0 -857
  330. aiecs/scripts/quick_dependency_check.py +0 -269
  331. aiecs/tools/task_tools/search_api.py +0 -7
  332. aiecs-1.0.1.dist-info/RECORD +0 -90
  333. aiecs-1.0.1.dist-info/entry_points.txt +0 -7
  334. /aiecs/scripts/{setup_nlp_data.sh → dependance_check/setup_nlp_data.sh} +0 -0
  335. /aiecs/scripts/{README_WEASEL_PATCH.md → dependance_patch/fix_weasel/README_WEASEL_PATCH.md} +0 -0
  336. /aiecs/scripts/{fix_weasel_validator.sh → dependance_patch/fix_weasel/fix_weasel_validator.sh} +0 -0
  337. /aiecs/scripts/{run_weasel_patch.sh → dependance_patch/fix_weasel/run_weasel_patch.sh} +0 -0
  338. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/WHEEL +0 -0
  339. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/licenses/LICENSE +0 -0
  340. {aiecs-1.0.1.dist-info → aiecs-1.7.6.dist-info}/top_level.txt +0 -0
@@ -7,20 +7,21 @@ in different formats. It supports template-based rendering, data visualization,
7
7
  Author: Your Organization
8
8
  Version: 1.0.0
9
9
  """
10
+
10
11
  import os
11
12
  import bleach
12
13
  from typing import Dict, Any, List, Optional, Union, Tuple, Set
13
14
  from jinja2 import FileSystemLoader, sandbox
15
+
14
16
  # from weasyprint import HTML # TODO: Re-enable when deployment issues are resolved
15
- import pandas as pd
17
+ import pandas as pd # type: ignore[import-untyped]
16
18
  from pptx import Presentation
17
19
  from pptx.util import Pt
18
20
  from docx import Document
19
- from docx.shared import Pt as DocxPt, RGBColor
20
- import markdown
21
+ from docx.shared import Pt as DocxPt
21
22
  import matplotlib.pyplot as plt
22
- from pydantic import ValidationError, ConfigDict
23
- from pydantic_settings import BaseSettings
23
+ from pydantic import Field, BaseModel, ConfigDict
24
+ from pydantic_settings import BaseSettings, SettingsConfigDict
24
25
  import tempfile
25
26
  import logging
26
27
 
@@ -28,57 +29,24 @@ from aiecs.tools.base_tool import BaseTool
28
29
  from aiecs.tools import register_tool
29
30
  from aiecs.tools.temp_file_manager import TempFileManager
30
31
 
31
- # Configuration for ReportTool
32
- class ReportSettings(BaseSettings):
33
- """
34
- Configuration for ReportTool.
35
-
36
- Attributes:
37
- templates_dir (str): Directory for Jinja2 templates.
38
- default_output_dir (str): Default directory for output files.
39
- allowed_extensions (List[str]): Allowed file extensions for outputs.
40
- pdf_page_size (str): Default PDF page size.
41
- default_font (str): Default font for documents.
42
- default_font_size (int): Default font size in points.
43
- allowed_html_tags (Set[str]): Allowed HTML tags for sanitization.
44
- allowed_html_attributes (Dict[str, List[str]]): Allowed HTML attributes for sanitization.
45
- temp_files_max_age (int): Maximum age of temporary files in seconds.
46
- env_prefix (str): Environment variable prefix for settings.
47
- """
48
- templates_dir: str = os.getcwd()
49
- default_output_dir: str = os.path.join(tempfile.gettempdir(), 'reports')
50
- allowed_extensions: List[str] = ['.html', '.pdf', '.xlsx', '.pptx', '.docx', '.md', '.png']
51
- pdf_page_size: str = 'A4'
52
- default_font: str = 'Arial'
53
- default_font_size: int = 12
54
- allowed_html_tags: Set[str] = {
55
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'br', 'a', 'ul', 'ol', 'li',
56
- 'strong', 'em', 'b', 'i', 'table', 'tr', 'td', 'th', 'thead', 'tbody',
57
- 'span', 'div', 'img', 'hr', 'code', 'pre'
58
- }
59
- allowed_html_attributes: Dict[str, List[str]] = {
60
- 'a': ['href', 'title', 'target'],
61
- 'img': ['src', 'alt', 'title', 'width', 'height'],
62
- 'td': ['colspan', 'rowspan', 'align'],
63
- 'th': ['colspan', 'rowspan', 'align'],
64
- '*': ['class', 'id', 'style']
65
- }
66
- temp_files_max_age: int = 3600 # 1 hour in seconds
67
- env_prefix: str = 'REPORT_TOOL_'
68
-
69
- model_config = ConfigDict(env_prefix='REPORT_TOOL_')
70
32
 
71
33
  # Exceptions
72
34
  class ReportToolError(Exception):
73
35
  """Base exception for ReportTool errors."""
74
- pass
36
+
75
37
 
76
38
  class FileOperationError(ReportToolError):
77
39
  """Raised when file operations fail."""
78
- pass
40
+
79
41
 
80
42
  # Helper function for HTML sanitization
81
- def sanitize_html(html_content: str, allowed_tags: Set[str], allowed_attributes: Dict[str, List[str]]) -> str:
43
+
44
+
45
+ def sanitize_html(
46
+ html_content: str,
47
+ allowed_tags: Set[str],
48
+ allowed_attributes: Dict[str, List[str]],
49
+ ) -> str:
82
50
  """
83
51
  Sanitize HTML content to prevent XSS attacks.
84
52
 
@@ -94,13 +62,17 @@ def sanitize_html(html_content: str, allowed_tags: Set[str], allowed_attributes:
94
62
  html_content,
95
63
  tags=allowed_tags,
96
64
  attributes=allowed_attributes,
97
- strip=True
65
+ strip=True,
98
66
  )
99
67
 
68
+
100
69
  # Type alias for dataset entries
101
- DatasetType = Dict[str, Union[pd.DataFrame, List[Dict[str, Any]]]]
70
+ # Note: Using Any instead of pd.DataFrame to avoid Pydantic schema generation errors
71
+ # The actual runtime type can be pd.DataFrame or List[Dict[str, Any]]
72
+ DatasetType = Dict[str, Union[Any, List[Dict[str, Any]]]]
73
+
102
74
 
103
- @register_tool('report')
75
+ @register_tool("report")
104
76
  class ReportTool(BaseTool):
105
77
  """
106
78
  Multi-format report generation tool supporting HTML, Excel, PowerPoint, Markdown, Word, and image-based reports.
@@ -119,36 +91,212 @@ class ReportTool(BaseTool):
119
91
 
120
92
  Inherits from BaseTool.
121
93
  """
122
- def __init__(self, config: Optional[Dict[str, Any]] = None):
94
+
95
+ # Configuration schema
96
+ class Config(BaseSettings):
97
+ """Configuration for the report tool
98
+
99
+ Automatically reads from environment variables with REPORT_TOOL_ prefix.
100
+ Example: REPORT_TOOL_TEMPLATES_DIR -> templates_dir
101
+ """
102
+
103
+ model_config = SettingsConfigDict(env_prefix="REPORT_TOOL_")
104
+
105
+ templates_dir: str = Field(default=os.getcwd(), description="Directory for Jinja2 templates")
106
+ default_output_dir: str = Field(
107
+ default=os.path.join(tempfile.gettempdir(), "reports"),
108
+ description="Default directory for output files",
109
+ )
110
+ allowed_extensions: List[str] = Field(
111
+ default=[
112
+ ".html",
113
+ ".pdf",
114
+ ".xlsx",
115
+ ".pptx",
116
+ ".docx",
117
+ ".md",
118
+ ".png",
119
+ ],
120
+ description="Allowed file extensions for outputs",
121
+ )
122
+ pdf_page_size: str = Field(default="A4", description="Default PDF page size")
123
+ default_font: str = Field(default="Arial", description="Default font for documents")
124
+ default_font_size: int = Field(default=12, description="Default font size in points")
125
+ allowed_html_tags: Set[str] = Field(
126
+ default={
127
+ "h1",
128
+ "h2",
129
+ "h3",
130
+ "h4",
131
+ "h5",
132
+ "h6",
133
+ "p",
134
+ "br",
135
+ "a",
136
+ "ul",
137
+ "ol",
138
+ "li",
139
+ "strong",
140
+ "em",
141
+ "b",
142
+ "i",
143
+ "table",
144
+ "tr",
145
+ "td",
146
+ "th",
147
+ "thead",
148
+ "tbody",
149
+ "span",
150
+ "div",
151
+ "img",
152
+ "hr",
153
+ "code",
154
+ "pre",
155
+ },
156
+ description="Allowed HTML tags for sanitization",
157
+ )
158
+ allowed_html_attributes: Dict[str, List[str]] = Field(
159
+ default={
160
+ "a": ["href", "title", "target"],
161
+ "img": ["src", "alt", "title", "width", "height"],
162
+ "td": ["colspan", "rowspan", "align"],
163
+ "th": ["colspan", "rowspan", "align"],
164
+ "*": ["class", "id", "style"],
165
+ },
166
+ description="Allowed HTML attributes for sanitization",
167
+ )
168
+ temp_files_max_age: int = Field(
169
+ default=3600,
170
+ description="Maximum age of temporary files in seconds",
171
+ )
172
+
173
+ # Schema definitions
174
+ class Generate_htmlSchema(BaseModel):
175
+ """Schema for generate_html operation"""
176
+
177
+ template_path: Optional[str] = Field(default=None, description="Optional path to the Jinja2 template file. Either template_path or template_str must be provided")
178
+ template_str: Optional[str] = Field(default=None, description="Optional template string content. Either template_path or template_str must be provided")
179
+ context: Dict[str, Any] = Field(description="Dictionary of template context data to render the template with")
180
+ output_path: str = Field(description="Path where the generated HTML file will be saved")
181
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
182
+
183
+ class Generate_pdfSchema(BaseModel):
184
+ """Schema for generate_pdf operation (currently disabled)"""
185
+
186
+ html: Optional[str] = Field(default=None, description="Optional HTML content string. Either html or html_schema must be provided")
187
+ html_schema: Optional[Dict[str, Any]] = Field(default=None, description="Optional dictionary for HTML generation. Either html or html_schema must be provided")
188
+ output_path: str = Field(description="Path where the generated PDF file will be saved")
189
+ page_size: Optional[str] = Field(default=None, description="Optional PDF page size (e.g., 'A4', 'Letter'). Uses default if not specified")
190
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
191
+
192
+ class Generate_excelSchema(BaseModel):
193
+ """Schema for generate_excel operation"""
194
+
195
+ model_config = ConfigDict(arbitrary_types_allowed=True)
196
+
197
+ sheets: Dict[str, Union[Any, List[Dict[str, Any]]]] = Field(description="Dictionary mapping sheet names to sheet data. Data can be a pandas DataFrame or list of dictionaries")
198
+ output_path: str = Field(description="Path where the generated Excel file will be saved")
199
+ styles: Optional[Dict[str, Dict[str, Any]]] = Field(default=None, description="Optional dictionary mapping sheet names to cell styling dictionaries. Each style dict maps cell addresses (e.g., 'A1') to style properties")
200
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
201
+
202
+ class Generate_pptxSchema(BaseModel):
203
+ """Schema for generate_pptx operation"""
204
+
205
+ slides: List[Dict[str, Any]] = Field(description="List of slide dictionaries. Each slide should have 'title' (str) and 'bullets' (list of strings). Optional: 'font', 'font_size', 'font_color'")
206
+ output_path: str = Field(description="Path where the generated PowerPoint file will be saved")
207
+ default_font: Optional[str] = Field(default=None, description="Optional default font name for all slides. Uses tool default if not specified")
208
+ default_font_size: Optional[int] = Field(default=None, description="Optional default font size in points for all slides. Uses tool default if not specified")
209
+ default_font_color: Optional[Tuple[int, int, int]] = Field(default=None, description="Optional default font color as RGB tuple (r, g, b) for all slides")
210
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
211
+
212
+ class Generate_markdownSchema(BaseModel):
213
+ """Schema for generate_markdown operation"""
214
+
215
+ template_path: Optional[str] = Field(default=None, description="Optional path to the Jinja2 template file. Either template_path or template_str must be provided")
216
+ template_str: Optional[str] = Field(default=None, description="Optional template string content. Either template_path or template_str must be provided")
217
+ context: Dict[str, Any] = Field(description="Dictionary of template context data to render the template with")
218
+ output_path: str = Field(description="Path where the generated Markdown file will be saved")
219
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
220
+
221
+ class Generate_wordSchema(BaseModel):
222
+ """Schema for generate_word operation"""
223
+
224
+ template_path: Optional[str] = Field(default=None, description="Optional path to the Jinja2 template file. Either template_path or template_str must be provided")
225
+ template_str: Optional[str] = Field(default=None, description="Optional template string content. Either template_path or template_str must be provided")
226
+ context: Dict[str, Any] = Field(description="Dictionary of template context data to render the template with")
227
+ output_path: str = Field(description="Path where the generated Word document will be saved")
228
+ font: Optional[str] = Field(default=None, description="Optional font name for the document. Uses tool default if not specified")
229
+ font_size: Optional[int] = Field(default=None, description="Optional font size in points. Uses tool default if not specified")
230
+ font_color: Optional[Tuple[int, int, int]] = Field(default=None, description="Optional font color as RGB tuple (r, g, b)")
231
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
232
+
233
+ class Generate_imageSchema(BaseModel):
234
+ """Schema for generate_image operation"""
235
+
236
+ model_config = ConfigDict(arbitrary_types_allowed=True)
237
+
238
+ chart_type: str = Field(description="Type of chart to generate: 'bar', 'line', or 'pie'")
239
+ data: Union[Any, List[Dict[str, Any]]] = Field(description="Chart data as pandas DataFrame or list of dictionaries")
240
+ output_path: str = Field(description="Path where the generated image file will be saved")
241
+ x_col: Optional[str] = Field(default=None, description="Optional X-axis column name for bar and line charts. For pie charts, used as labels if labels not provided")
242
+ y_col: Optional[str] = Field(default=None, description="Optional Y-axis column name for bar, line, and pie charts")
243
+ labels: Optional[List[str]] = Field(default=None, description="Optional list of labels for pie chart. If not provided and x_col is specified, uses x_col values")
244
+ title: Optional[str] = Field(default=None, description="Optional chart title")
245
+ width: int = Field(default=8, description="Chart width in inches")
246
+ height: int = Field(default=6, description="Chart height in inches")
247
+ template_variables: Optional[Dict[str, str]] = Field(default=None, description="Optional dictionary of variables for dynamic output path generation")
248
+
249
+ class Batch_generateSchema(BaseModel):
250
+ """Schema for batch_generate operation"""
251
+
252
+ model_config = ConfigDict(arbitrary_types_allowed=True)
253
+
254
+ operation: str = Field(description="Operation to perform: 'generate_html', 'generate_excel', 'generate_pptx', 'generate_markdown', 'generate_word', 'generate_image', or 'generate_pdf'")
255
+ contexts: List[Dict[str, Any]] = Field(default=[], description="List of context dictionaries for HTML, Markdown, Word, or PDF operations. Each dict should match the corresponding operation's parameters")
256
+ output_paths: List[str] = Field(description="List of output file paths, one for each report to generate")
257
+ datasets: Optional[List[DatasetType]] = Field(default=None, description="Optional list of dataset dictionaries for Excel or Image operations. Each dict should match the corresponding operation's parameters")
258
+ slides: Optional[List[List[Dict[str, Any]]]] = Field(default=None, description="Optional list of slide lists for PPTX operations. Each inner list contains slide dictionaries")
259
+
260
+ def __init__(self, config: Optional[Dict[str, Any]] = None, **kwargs):
123
261
  """
124
262
  Initialize ReportTool with settings and resources.
125
263
 
126
264
  Args:
127
- config (Dict, optional): Configuration overrides for ReportSettings.
265
+ config (Dict, optional): Configuration overrides for ReportTool.
266
+ **kwargs: Additional arguments passed to BaseTool (e.g., tool_name)
128
267
 
129
268
  Raises:
130
269
  ValueError: If config contains invalid settings.
270
+
271
+ Configuration is automatically loaded by BaseTool from:
272
+ 1. Explicit config dict (highest priority)
273
+ 2. YAML config files (config/tools/report.yaml)
274
+ 3. Environment variables (via dotenv from .env files)
275
+ 4. Tool defaults (lowest priority)
131
276
  """
132
- super().__init__(config)
133
- self.settings = ReportSettings()
134
- if config:
135
- try:
136
- self.settings = self.settings.model_validate({**self.settings.model_dump(), **config})
137
- except ValidationError as e:
138
- raise ValueError(f"Invalid configuration: {e}")
277
+ super().__init__(config, **kwargs)
278
+
279
+ # Configuration is automatically loaded by BaseTool into self._config_obj
280
+ # Access config via self._config_obj (BaseSettings instance)
281
+ self.config = self._config_obj if self._config_obj else self.Config()
282
+
139
283
  self.logger = logging.getLogger(__name__)
140
284
  if not self.logger.handlers:
141
285
  handler = logging.StreamHandler()
142
- handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s'))
286
+ handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))
143
287
  self.logger.addHandler(handler)
144
288
  self.logger.setLevel(logging.INFO)
145
- self._jinja_env = sandbox.SandboxedEnvironment(
146
- loader=FileSystemLoader(self.settings.templates_dir),
147
- autoescape=True
148
- )
149
- self._temp_manager = TempFileManager(self.settings.default_output_dir, self.settings.temp_files_max_age)
150
-
151
- def generate_html(self, template_path: Optional[str], template_str: Optional[str], context: Dict[str, Any], output_path: str, template_variables: Optional[Dict[str, str]] = None) -> str:
289
+ self._jinja_env = sandbox.SandboxedEnvironment(loader=FileSystemLoader(self.config.templates_dir), autoescape=True)
290
+ self._temp_manager = TempFileManager(self.config.default_output_dir, self.config.temp_files_max_age)
291
+
292
+ def generate_html(
293
+ self,
294
+ template_path: Optional[str],
295
+ template_str: Optional[str],
296
+ context: Dict[str, Any],
297
+ output_path: str,
298
+ template_variables: Optional[Dict[str, str]] = None,
299
+ ) -> str:
152
300
  """
153
301
  Render an HTML report using a Jinja2 template.
154
302
 
@@ -167,26 +315,39 @@ class ReportTool(BaseTool):
167
315
  """
168
316
  try:
169
317
  if template_path:
170
- path = os.path.join(self.settings.templates_dir, template_path)
318
+ os.path.join(self.config.templates_dir, template_path)
171
319
  tmpl = self._jinja_env.get_template(template_path)
172
320
  else:
321
+ if template_str is None:
322
+ raise FileOperationError("Either template_path or template_str must be provided")
173
323
  tmpl = self._jinja_env.from_string(template_str)
174
324
  html = tmpl.render(**context)
175
- csrf_meta = '<meta http-equiv="Content-Security-Policy" content="default-src \'self\'; script-src \'self\'; object-src \'none\'">\n'
325
+ csrf_meta = "<meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'self'; script-src 'self'; object-src 'none'\">\n"
176
326
  csrf_meta += '<meta name="referrer" content="no-referrer">\n'
177
- if '<head>' in html:
178
- html = html.replace('<head>', '<head>\n' + csrf_meta)
327
+ if "<head>" in html:
328
+ html = html.replace("<head>", "<head>\n" + csrf_meta)
179
329
  else:
180
330
  html = csrf_meta + html
181
- html = sanitize_html(html, self.settings.allowed_html_tags, self.settings.allowed_html_attributes)
182
- with open(output_path, 'w', encoding='utf-8') as f:
331
+ html = sanitize_html(
332
+ html,
333
+ self.config.allowed_html_tags,
334
+ self.config.allowed_html_attributes,
335
+ )
336
+ with open(output_path, "w", encoding="utf-8") as f:
183
337
  f.write(html)
184
338
  self._temp_manager.register_file(output_path)
185
339
  return output_path
186
340
  except Exception as e:
187
341
  raise FileOperationError(f"Failed to generate HTML: {str(e)}")
188
342
 
189
- def generate_pdf(self, html: Optional[str], html_schema: Optional[Dict], output_path: str, page_size: Optional[str] = None, template_variables: Optional[Dict[str, str]] = None) -> str:
343
+ def generate_pdf(
344
+ self,
345
+ html: Optional[str],
346
+ html_schema: Optional[Dict],
347
+ output_path: str,
348
+ page_size: Optional[str] = None,
349
+ template_variables: Optional[Dict[str, str]] = None,
350
+ ) -> str:
190
351
  """
191
352
  Generate a PDF report from HTML content or a Jinja2 template.
192
353
 
@@ -227,7 +388,13 @@ class ReportTool(BaseTool):
227
388
  # except Exception as e:
228
389
  # raise FileOperationError(f"Failed to generate PDF: {str(e)}")
229
390
 
230
- def generate_excel(self, sheets: Dict[str, Union[pd.DataFrame, List[Dict[str, Any]]]], output_path: str, styles: Optional[Dict[str, Dict[str, Any]]] = None, template_variables: Optional[Dict[str, str]] = None) -> str:
391
+ def generate_excel(
392
+ self,
393
+ sheets: Dict[str, Union[pd.DataFrame, List[Dict[str, Any]]]],
394
+ output_path: str,
395
+ styles: Optional[Dict[str, Dict[str, Any]]] = None,
396
+ template_variables: Optional[Dict[str, str]] = None,
397
+ ) -> str:
231
398
  """
232
399
  Generate an Excel workbook with multiple sheets and optional styling.
233
400
 
@@ -244,7 +411,7 @@ class ReportTool(BaseTool):
244
411
  FileOperationError: If Excel generation fails.
245
412
  """
246
413
  try:
247
- writer = pd.ExcelWriter(output_path, engine='xlsxwriter')
414
+ writer = pd.ExcelWriter(output_path, engine="xlsxwriter")
248
415
  workbook = writer.book
249
416
  for name, data in sheets.items():
250
417
  df = data if isinstance(data, pd.DataFrame) else pd.DataFrame(data)
@@ -253,20 +420,32 @@ class ReportTool(BaseTool):
253
420
  worksheet = writer.sheets[name[:31]]
254
421
  for cell, style in styles[name].items():
255
422
  format_dict = {}
256
- if style.get('bold'):
257
- format_dict['bold'] = True
258
- if style.get('font_size'):
259
- format_dict['font_size'] = style['font_size']
260
- if style.get('bg_color'):
261
- format_dict['bg_color'] = style['bg_color']
262
- worksheet.write(cell, df.loc[int(cell[1:]) - 1, cell[0]], workbook.add_format(format_dict))
423
+ if style.get("bold"):
424
+ format_dict["bold"] = True
425
+ if style.get("font_size"):
426
+ format_dict["font_size"] = style["font_size"]
427
+ if style.get("bg_color"):
428
+ format_dict["bg_color"] = style["bg_color"]
429
+ worksheet.write(
430
+ cell,
431
+ df.loc[int(cell[1:]) - 1, cell[0]],
432
+ workbook.add_format(format_dict),
433
+ )
263
434
  writer.close()
264
435
  self._temp_manager.register_file(output_path)
265
436
  return output_path
266
437
  except Exception as e:
267
438
  raise FileOperationError(f"Failed to generate Excel: {str(e)}")
268
439
 
269
- def generate_pptx(self, slides: List[Dict], output_path: str, default_font: Optional[str] = None, default_font_size: Optional[int] = None, default_font_color: Optional[Tuple[int, int, int]] = None, template_variables: Optional[Dict[str, str]] = None) -> str:
440
+ def generate_pptx(
441
+ self,
442
+ slides: List[Dict],
443
+ output_path: str,
444
+ default_font: Optional[str] = None,
445
+ default_font_size: Optional[int] = None,
446
+ default_font_color: Optional[Tuple[int, int, int]] = None,
447
+ template_variables: Optional[Dict[str, str]] = None,
448
+ ) -> str:
270
449
  """
271
450
  Generate a PowerPoint presentation with customizable slides.
272
451
 
@@ -289,31 +468,38 @@ class ReportTool(BaseTool):
289
468
  for slide in slides:
290
469
  s = prs.slides.add_slide(prs.slide_layouts[1])
291
470
  title_shape = s.shapes.title
292
- title_shape.text = slide['title']
293
- font = slide.get('font') or default_font or self.settings.default_font
294
- font_size = slide.get('font_size') or default_font_size or self.settings.default_font_size
295
- font_color = slide.get('font_color') or default_font_color or (0, 0, 0)
471
+ title_shape.text = slide["title"]
472
+ font = slide.get("font") or default_font or self.config.default_font
473
+ font_size = slide.get("font_size") or default_font_size or self.config.default_font_size
474
+ slide.get("font_color") or default_font_color or (0, 0, 0)
296
475
  title_shape.text_frame.paragraphs[0].font.name = font
297
476
  title_shape.text_frame.paragraphs[0].font.size = Pt(font_size)
298
477
  # Set font color safely - skip color setting for now to avoid library issues
299
- # Font color setting in python-pptx can be problematic, focusing on core functionality
300
- pass
478
+ # Font color setting in python-pptx can be problematic,
479
+ # focusing on core functionality
301
480
  body = s.shapes.placeholders[1].text_frame
302
- for bullet in slide['bullets']:
481
+ for bullet in slide["bullets"]:
303
482
  p = body.add_paragraph()
304
483
  p.text = bullet
305
484
  p.level = 0
306
485
  p.font.name = font
307
486
  p.font.size = Pt(font_size)
308
- # Skip font color setting for bullet points to avoid library issues
309
- pass
487
+ # Skip font color setting for bullet points to avoid
488
+ # library issues
310
489
  prs.save(output_path)
311
490
  self._temp_manager.register_file(output_path)
312
491
  return output_path
313
492
  except Exception as e:
314
493
  raise FileOperationError(f"Failed to generate PPTX: {str(e)}")
315
494
 
316
- def generate_markdown(self, template_path: Optional[str], template_str: Optional[str], context: Dict[str, Any], output_path: str, template_variables: Optional[Dict[str, str]] = None) -> str:
495
+ def generate_markdown(
496
+ self,
497
+ template_path: Optional[str],
498
+ template_str: Optional[str],
499
+ context: Dict[str, Any],
500
+ output_path: str,
501
+ template_variables: Optional[Dict[str, str]] = None,
502
+ ) -> str:
317
503
  """
318
504
  Render a Markdown report using a Jinja2 template.
319
505
 
@@ -334,16 +520,28 @@ class ReportTool(BaseTool):
334
520
  if template_path:
335
521
  tmpl = self._jinja_env.get_template(template_path)
336
522
  else:
523
+ if template_str is None:
524
+ raise FileOperationError("Either template_path or template_str must be provided")
337
525
  tmpl = self._jinja_env.from_string(template_str)
338
526
  markdown_content = tmpl.render(**context)
339
- with open(output_path, 'w', encoding='utf-8') as f:
527
+ with open(output_path, "w", encoding="utf-8") as f:
340
528
  f.write(markdown_content)
341
529
  self._temp_manager.register_file(output_path)
342
530
  return output_path
343
531
  except Exception as e:
344
532
  raise FileOperationError(f"Failed to generate Markdown: {str(e)}")
345
533
 
346
- def generate_word(self, template_path: Optional[str], template_str: Optional[str], context: Dict[str, Any], output_path: str, font: Optional[str] = None, font_size: Optional[int] = None, font_color: Optional[Tuple[int, int, int]] = None, template_variables: Optional[Dict[str, str]] = None) -> str:
534
+ def generate_word(
535
+ self,
536
+ template_path: Optional[str],
537
+ template_str: Optional[str],
538
+ context: Dict[str, Any],
539
+ output_path: str,
540
+ font: Optional[str] = None,
541
+ font_size: Optional[int] = None,
542
+ font_color: Optional[Tuple[int, int, int]] = None,
543
+ template_variables: Optional[Dict[str, str]] = None,
544
+ ) -> str:
347
545
  """
348
546
  Generate a Word document from a Jinja2 template with customizable styles.
349
547
 
@@ -367,26 +565,40 @@ class ReportTool(BaseTool):
367
565
  if template_path:
368
566
  tmpl = self._jinja_env.get_template(template_path)
369
567
  else:
568
+ if template_str is None:
569
+ raise FileOperationError("Either template_path or template_str must be provided")
370
570
  tmpl = self._jinja_env.from_string(template_str)
371
571
  content = tmpl.render(**context)
372
572
  doc = Document()
373
- font = font or self.settings.default_font
374
- font_size = font_size or self.settings.default_font_size
573
+ font = font or self.config.default_font
574
+ font_size = font_size or self.config.default_font_size
375
575
  font_color = font_color or (0, 0, 0)
376
576
  for line in content.splitlines():
377
577
  p = doc.add_paragraph()
378
578
  run = p.add_run(line)
379
579
  run.font.name = font
380
580
  run.font.size = DocxPt(font_size)
381
- # Skip font color setting for Word documents to avoid library issues
382
- pass
581
+ # Skip font color setting for Word documents to avoid library
582
+ # issues
383
583
  doc.save(output_path)
384
584
  self._temp_manager.register_file(output_path)
385
585
  return output_path
386
586
  except Exception as e:
387
587
  raise FileOperationError(f"Failed to generate Word: {str(e)}")
388
588
 
389
- def generate_image(self, chart_type: str, data: Union[pd.DataFrame, List[Dict[str, Any]]], output_path: str, x_col: Optional[str] = None, y_col: Optional[str] = None, labels: Optional[List[str]] = None, title: Optional[str] = None, width: int = 8, height: int = 6, template_variables: Optional[Dict[str, str]] = None) -> str:
589
+ def generate_image(
590
+ self,
591
+ chart_type: str,
592
+ data: Union[pd.DataFrame, List[Dict[str, Any]]],
593
+ output_path: str,
594
+ x_col: Optional[str] = None,
595
+ y_col: Optional[str] = None,
596
+ labels: Optional[List[str]] = None,
597
+ title: Optional[str] = None,
598
+ width: int = 8,
599
+ height: int = 6,
600
+ template_variables: Optional[Dict[str, str]] = None,
601
+ ) -> str:
390
602
  """
391
603
  Generate a chart (bar, line, pie) using Matplotlib.
392
604
 
@@ -411,13 +623,18 @@ class ReportTool(BaseTool):
411
623
  try:
412
624
  df = data if isinstance(data, pd.DataFrame) else pd.DataFrame(data)
413
625
  plt.figure(figsize=(width, height))
414
- if chart_type == 'bar':
626
+ if chart_type == "bar":
415
627
  df.plot.bar(x=x_col, y=y_col, title=title)
416
- elif chart_type == 'line':
628
+ elif chart_type == "line":
417
629
  df.plot.line(x=x_col, y=y_col, title=title)
418
- elif chart_type == 'pie':
419
- plt.pie(df[y_col], labels=df[x_col] if x_col else labels, autopct='%1.1f%%')
420
- plt.title(title)
630
+ elif chart_type == "pie":
631
+ plt.pie(
632
+ df[y_col],
633
+ labels=df[x_col] if x_col else labels,
634
+ autopct="%1.1f%%",
635
+ )
636
+ if title:
637
+ plt.title(title)
421
638
  plt.savefig(output_path)
422
639
  plt.close()
423
640
  self._temp_manager.register_file(output_path)
@@ -425,7 +642,14 @@ class ReportTool(BaseTool):
425
642
  except Exception as e:
426
643
  raise FileOperationError(f"Failed to generate image: {str(e)}")
427
644
 
428
- def batch_generate(self, operation: str, contexts: List[Dict[str, Any]], output_paths: List[str], datasets: Optional[List[DatasetType]] = None, slides: Optional[List[List[Dict]]] = None) -> List[str]:
645
+ def batch_generate(
646
+ self,
647
+ operation: str,
648
+ contexts: List[Dict[str, Any]],
649
+ output_paths: List[str],
650
+ datasets: Optional[List[DatasetType]] = None,
651
+ slides: Optional[List[List[Dict]]] = None,
652
+ ) -> List[str]:
429
653
  """
430
654
  Generate multiple reports in parallel for different contexts or datasets.
431
655
 
@@ -445,54 +669,78 @@ class ReportTool(BaseTool):
445
669
  try:
446
670
  tasks = []
447
671
  input_data = contexts or datasets or slides
672
+ if input_data is None:
673
+ raise ValueError("At least one of contexts, datasets, or slides must be provided")
674
+ if not isinstance(input_data, list):
675
+ raise ValueError("input_data must be a list")
448
676
  for i, output_path in enumerate(output_paths):
449
- op_params = {'output_path': output_path}
450
- if operation in ('generate_html', 'generate_markdown', 'generate_word'):
451
- op_params.update(input_data[i])
452
- op_params['template_path'] = input_data[i].get('template_path')
453
- op_params['template_str'] = input_data[i].get('template_str')
454
- if operation == 'generate_word':
455
- op_params['font'] = input_data[i].get('font')
456
- op_params['font_size'] = input_data[i].get('font_size')
457
- op_params['font_color'] = input_data[i].get('font_color')
458
- elif operation == 'generate_excel':
459
- op_params['sheets'] = input_data[i]
460
- op_params['styles'] = input_data[i].get('styles')
461
- elif operation == 'generate_pptx':
462
- op_params['slides'] = input_data[i]
463
- op_params['default_font'] = input_data[i][0].get('font') if input_data[i] else None
464
- op_params['default_font_size'] = input_data[i][0].get('font_size') if input_data[i] else None
465
- op_params['default_font_color'] = input_data[i][0].get('font_color') if input_data[i] else None
466
- elif operation == 'generate_image':
467
- op_params.update(input_data[i])
468
- elif operation == 'generate_pdf':
469
- op_params['html'] = input_data[i].get('html')
470
- op_params['html_schema'] = input_data[i] if input_data[i].get('context') else None
471
- op_params['page_size'] = input_data[i].get('page_size')
472
- tasks.append({'op': operation, 'kwargs': op_params})
677
+ op_params: Dict[str, Any] = {"output_path": output_path}
678
+
679
+ # Type narrowing: ensure input_data[i] is a dict for operations that need it
680
+ if operation in (
681
+ "generate_html",
682
+ "generate_markdown",
683
+ "generate_word",
684
+ ):
685
+ item = input_data[i]
686
+ if isinstance(item, dict):
687
+ op_params.update(item)
688
+ op_params["template_path"] = item.get("template_path")
689
+ op_params["template_str"] = item.get("template_str")
690
+ if operation == "generate_word":
691
+ op_params["font"] = item.get("font")
692
+ op_params["font_size"] = item.get("font_size")
693
+ op_params["font_color"] = item.get("font_color")
694
+ elif operation == "generate_excel":
695
+ item = input_data[i]
696
+ op_params["sheets"] = item
697
+ if isinstance(item, dict):
698
+ op_params["styles"] = item.get("styles")
699
+ elif operation == "generate_pptx":
700
+ item = input_data[i]
701
+ op_params["slides"] = item
702
+ if isinstance(item, list) and len(item) > 0 and isinstance(item[0], dict):
703
+ op_params["default_font"] = item[0].get("font")
704
+ op_params["default_font_size"] = item[0].get("font_size")
705
+ op_params["default_font_color"] = item[0].get("font_color")
706
+ else:
707
+ op_params["default_font"] = None
708
+ op_params["default_font_size"] = None
709
+ op_params["default_font_color"] = None
710
+ elif operation == "generate_image":
711
+ item = input_data[i]
712
+ if isinstance(item, dict):
713
+ op_params.update(item)
714
+ elif operation == "generate_pdf":
715
+ item = input_data[i]
716
+ if isinstance(item, dict):
717
+ op_params["html"] = item.get("html")
718
+ op_params["html_schema"] = item if item.get("context") else None
719
+ op_params["page_size"] = item.get("page_size")
720
+ tasks.append({"op": operation, "kwargs": op_params})
473
721
  # Execute tasks synchronously for batch generation
474
722
  results = []
475
723
  for task in tasks:
476
- op_name = task['op']
477
- kwargs = task['kwargs']
478
-
479
- if op_name == 'generate_html':
724
+ op_name = task["op"]
725
+ kwargs: Dict[str, Any] = task["kwargs"] # type: ignore[assignment]
726
+
727
+ if op_name == "generate_html":
480
728
  result = self.generate_html(**kwargs)
481
- elif op_name == 'generate_excel':
729
+ elif op_name == "generate_excel":
482
730
  result = self.generate_excel(**kwargs)
483
- elif op_name == 'generate_pptx':
731
+ elif op_name == "generate_pptx":
484
732
  result = self.generate_pptx(**kwargs)
485
- elif op_name == 'generate_markdown':
733
+ elif op_name == "generate_markdown":
486
734
  result = self.generate_markdown(**kwargs)
487
- elif op_name == 'generate_word':
735
+ elif op_name == "generate_word":
488
736
  result = self.generate_word(**kwargs)
489
- elif op_name == 'generate_image':
737
+ elif op_name == "generate_image":
490
738
  result = self.generate_image(**kwargs)
491
- elif op_name == 'generate_pdf':
739
+ elif op_name == "generate_pdf":
492
740
  result = self.generate_pdf(**kwargs)
493
741
  else:
494
742
  raise FileOperationError(f"Unsupported operation: {op_name}")
495
-
743
+
496
744
  results.append(result)
497
745
  return results
498
746
  except Exception as e: