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
@@ -10,19 +10,29 @@ Main Features:
10
10
 
11
11
  import inspect
12
12
  import logging
13
- from typing import Any, Dict, List, Optional, Type, Union, get_type_hints
14
- from pydantic import BaseModel, Field
13
+ from typing import Any, Dict, List, Optional, Type
14
+ from pydantic import BaseModel
15
+
16
+ # Import schema generator
17
+ from aiecs.tools.schema_generator import generate_schema_from_method
15
18
 
16
19
  try:
17
20
  from langchain.tools import BaseTool as LangchainBaseTool
18
- from langchain.callbacks.manager import CallbackManagerForToolRun, AsyncCallbackManagerForToolRun
21
+ from langchain.callbacks.manager import (
22
+ CallbackManagerForToolRun,
23
+ AsyncCallbackManagerForToolRun,
24
+ )
25
+
19
26
  LANGCHAIN_AVAILABLE = True
20
27
  except ImportError:
21
28
  # If langchain is not installed, create simple base class for type checking
22
- class LangchainBaseTool:
29
+ # Use different name to avoid redefinition error
30
+ class _LangchainBaseToolFallback: # type: ignore[no-redef]
23
31
  pass
24
- CallbackManagerForToolRun = None
25
- AsyncCallbackManagerForToolRun = None
32
+
33
+ LangchainBaseTool = _LangchainBaseToolFallback # type: ignore[assignment,misc]
34
+ CallbackManagerForToolRun = None # type: ignore[assignment,misc]
35
+ AsyncCallbackManagerForToolRun = None # type: ignore[assignment,misc]
26
36
  LANGCHAIN_AVAILABLE = False
27
37
 
28
38
  from aiecs.tools.base_tool import BaseTool
@@ -30,332 +40,484 @@ from aiecs.tools import get_tool, list_tools, TOOL_CLASSES
30
40
 
31
41
  logger = logging.getLogger(__name__)
32
42
 
43
+
33
44
  class LangchainToolAdapter(LangchainBaseTool):
34
45
  """
35
46
  Langchain tool adapter for single operation
36
-
37
- Wraps one operation method of BaseTool as an independent Langchain tool
47
+
48
+ Wraps one operation method of BaseTool as an independent Langchain tool.
49
+ Supports both tool-level operations and provider-level operations.
38
50
  """
39
-
51
+
40
52
  # Define class attributes
41
53
  name: str = ""
42
54
  description: str = ""
43
-
55
+ base_tool_name: str = ""
56
+ operation_name: str = ""
57
+ operation_schema: Optional[Type[BaseModel]] = None
58
+ is_provider_operation: bool = False
59
+ provider_name: Optional[str] = None
60
+ method_name: Optional[str] = None
61
+
44
62
  def __init__(
45
- self,
63
+ self,
46
64
  base_tool_name: str,
47
- operation_name: str,
65
+ operation_name: str,
48
66
  operation_schema: Optional[Type[BaseModel]] = None,
49
- description: Optional[str] = None
67
+ description: Optional[str] = None,
68
+ is_provider_operation: bool = False,
69
+ provider_name: Optional[str] = None,
70
+ method_name: Optional[str] = None,
50
71
  ):
51
72
  """
52
73
  Initialize adapter
53
-
74
+
54
75
  Args:
55
76
  base_tool_name: Original tool name
56
77
  operation_name: Operation name
57
78
  operation_schema: Pydantic Schema for the operation
58
79
  description: Tool description
80
+ is_provider_operation: Whether this is a provider-level operation
81
+ provider_name: Provider name (for provider operations)
82
+ method_name: Original method name (for provider operations)
59
83
  """
60
84
  # Construct tool name and description
61
- self.name = f"{base_tool_name}_{operation_name}"
62
- self.description = description or f"Execute {operation_name} operation from {base_tool_name} tool"
63
-
64
- # Store tool information (use self.__dict__ to set directly to avoid pydantic validation)
65
- self.__dict__['base_tool_name'] = base_tool_name
66
- self.__dict__['operation_name'] = operation_name
67
- self.__dict__['operation_schema'] = operation_schema
68
-
69
- # Set parameter Schema
70
- if operation_schema:
71
- self.args_schema = operation_schema
72
-
73
- super().__init__()
74
-
85
+ tool_name = f"{base_tool_name}_{operation_name}"
86
+ tool_description = description or f"Execute {operation_name} operation from {base_tool_name} tool"
87
+
88
+ # Initialize parent class with all required fields
89
+ super().__init__(
90
+ name=tool_name,
91
+ description=tool_description,
92
+ base_tool_name=base_tool_name,
93
+ operation_name=operation_name,
94
+ operation_schema=operation_schema,
95
+ args_schema=operation_schema,
96
+ is_provider_operation=is_provider_operation,
97
+ provider_name=provider_name,
98
+ method_name=method_name,
99
+ )
100
+
75
101
  def _run(
76
- self,
77
- run_manager: Optional[CallbackManagerForToolRun] = None,
78
- **kwargs: Any
102
+ self,
103
+ run_manager: Optional[CallbackManagerForToolRun] = None,
104
+ **kwargs: Any,
79
105
  ) -> Any:
80
106
  """Execute operation synchronously"""
81
107
  try:
82
108
  # Get original tool instance
83
- base_tool = get_tool(self.__dict__['base_tool_name'])
84
-
85
- # Execute operation
86
- result = base_tool.run(self.__dict__['operation_name'], **kwargs)
87
-
109
+ base_tool = get_tool(self.base_tool_name)
110
+
111
+ # Handle provider operations differently
112
+ if self.is_provider_operation:
113
+ # For provider operations, call the query method with provider
114
+ # and operation
115
+ result = base_tool.run(
116
+ "query",
117
+ provider=self.provider_name,
118
+ operation=self.method_name,
119
+ params=kwargs,
120
+ )
121
+ else:
122
+ # For tool-level operations, call directly
123
+ result = base_tool.run(self.operation_name, **kwargs)
124
+
88
125
  logger.info(f"Successfully executed {self.name} with result type: {type(result)}")
89
126
  return result
90
-
127
+
91
128
  except Exception as e:
92
129
  logger.error(f"Error executing {self.name}: {str(e)}")
93
130
  raise
94
-
131
+
95
132
  async def _arun(
96
- self,
133
+ self,
97
134
  run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
98
- **kwargs: Any
135
+ **kwargs: Any,
99
136
  ) -> Any:
100
137
  """Execute operation asynchronously"""
101
138
  try:
102
139
  # Get original tool instance
103
- base_tool = get_tool(self.__dict__['base_tool_name'])
104
-
140
+ base_tool = get_tool(self.base_tool_name)
141
+
105
142
  # Execute asynchronous operation
106
- result = await base_tool.run_async(self.__dict__['operation_name'], **kwargs)
107
-
143
+ result = await base_tool.run_async(self.operation_name, **kwargs)
144
+
108
145
  logger.info(f"Successfully executed {self.name} async with result type: {type(result)}")
109
146
  return result
110
-
147
+
111
148
  except Exception as e:
112
149
  logger.error(f"Error executing {self.name} async: {str(e)}")
113
150
  raise
114
151
 
152
+
115
153
  class ToolRegistry:
116
154
  """Tool Registry: Manages conversion from BaseTool to Langchain tools"""
117
-
118
- def __init__(self):
155
+
156
+ def __init__(self) -> None:
119
157
  self._langchain_tools: Dict[str, LangchainToolAdapter] = {}
120
-
158
+
121
159
  def discover_operations(self, base_tool_class: Type[BaseTool]) -> List[Dict[str, Any]]:
122
160
  """
123
- Discover all operation methods and Schemas of BaseTool class
124
-
161
+ Discover all operation methods and Schemas of BaseTool class.
162
+
163
+ Enhanced to support provider-level operations for tools like APISourceTool
164
+ that expose fine-grained operations from underlying providers.
165
+
125
166
  Args:
126
167
  base_tool_class: BaseTool subclass
127
-
168
+
128
169
  Returns:
129
170
  List of operation information, including method names, Schemas, descriptions, etc.
130
171
  """
131
172
  operations = []
132
-
173
+
174
+ # 1. Discover tool-level operations (existing logic)
175
+ tool_operations = self._discover_tool_operations(base_tool_class)
176
+ operations.extend(tool_operations)
177
+
178
+ # 2. Discover provider-level operations (new logic)
179
+ if hasattr(base_tool_class, "_discover_provider_operations"):
180
+ try:
181
+ provider_operations = base_tool_class._discover_provider_operations()
182
+
183
+ # Convert provider operations to the expected format
184
+ for provider_op in provider_operations:
185
+ operation_info = {
186
+ "name": provider_op["name"],
187
+ "method": None, # Will be handled specially in create_langchain_tools
188
+ "schema": provider_op["schema"],
189
+ "description": provider_op["description"],
190
+ "is_async": False,
191
+ "is_provider_operation": True, # Mark as provider operation
192
+ "provider_name": provider_op.get("provider_name"),
193
+ "method_name": provider_op.get("method_name"),
194
+ }
195
+ operations.append(operation_info)
196
+ logger.debug(f"Added provider operation: {provider_op['name']}")
197
+
198
+ logger.info(f"Discovered {len(provider_operations)} provider operations for {base_tool_class.__name__}")
199
+
200
+ except Exception as e:
201
+ logger.warning(f"Error discovering provider operations for {base_tool_class.__name__}: {e}")
202
+
203
+ return operations
204
+
205
+ def _discover_tool_operations(self, base_tool_class: Type[BaseTool]) -> List[Dict[str, Any]]:
206
+ """
207
+ Discover tool-level operations (original logic extracted to separate method).
208
+
209
+ Args:
210
+ base_tool_class: BaseTool subclass
211
+
212
+ Returns:
213
+ List of tool-level operation information
214
+ """
215
+ operations = []
216
+
133
217
  # Get all Schema classes
218
+ # Build a mapping from normalized names to Schema classes
219
+ # Check both class-level and module-level schemas
134
220
  schemas = {}
221
+
222
+ # 1. Check class-level schemas (e.g., ChartTool)
135
223
  for attr_name in dir(base_tool_class):
136
224
  attr = getattr(base_tool_class, attr_name)
137
- if isinstance(attr, type) and issubclass(attr, BaseModel) and attr.__name__.endswith('Schema'):
138
- op_name = attr.__name__.replace('Schema', '').lower()
139
- schemas[op_name] = attr
140
-
225
+ if isinstance(attr, type) and issubclass(attr, BaseModel) and attr.__name__.endswith("Schema"):
226
+ # Normalize: remove 'Schema' suffix, convert to lowercase,
227
+ # remove underscores
228
+ schema_base_name = attr.__name__.replace("Schema", "")
229
+ normalized_name = schema_base_name.replace("_", "").lower()
230
+ schemas[normalized_name] = attr
231
+ logger.debug(f"Found class-level schema {attr.__name__} -> normalized: {normalized_name}")
232
+
233
+ # 2. Check module-level schemas (e.g., ImageTool)
234
+ tool_module = inspect.getmodule(base_tool_class)
235
+ if tool_module:
236
+ for attr_name in dir(tool_module):
237
+ if attr_name.startswith("_"):
238
+ continue
239
+ attr = getattr(tool_module, attr_name)
240
+ if isinstance(attr, type) and issubclass(attr, BaseModel) and attr.__name__.endswith("Schema"):
241
+ # Skip if already found at class level
242
+ schema_base_name = attr.__name__.replace("Schema", "")
243
+ normalized_name = schema_base_name.replace("_", "").lower()
244
+ if normalized_name not in schemas:
245
+ schemas[normalized_name] = attr
246
+ logger.debug(f"Found module-level schema {attr.__name__} -> normalized: {normalized_name}")
247
+
141
248
  # Get all public methods
142
249
  for method_name in dir(base_tool_class):
143
- if method_name.startswith('_'):
250
+ if method_name.startswith("_"):
144
251
  continue
145
-
252
+
146
253
  method = getattr(base_tool_class, method_name)
147
254
  if not callable(method):
148
255
  continue
149
-
150
- # Skip base class methods
151
- if method_name in ['run', 'run_async', 'run_batch']:
256
+
257
+ # Skip base class methods and Schema classes themselves
258
+ if method_name in ["run", "run_async", "run_batch"]:
259
+ continue
260
+
261
+ # Skip if it's a class (like Config or Schema classes)
262
+ if isinstance(method, type):
152
263
  continue
153
-
264
+
265
+ # Normalize method name: remove underscores and convert to
266
+ # lowercase
267
+ normalized_method_name = method_name.replace("_", "").lower()
268
+
269
+ # Try to find matching schema
270
+ matching_schema = schemas.get(normalized_method_name)
271
+
272
+ if matching_schema:
273
+ logger.debug(f"Matched method {method_name} with manual schema {matching_schema.__name__}")
274
+ else:
275
+ # Auto-generate schema if not found
276
+ auto_schema = generate_schema_from_method(method, method_name)
277
+ if auto_schema:
278
+ matching_schema = auto_schema
279
+ logger.debug(f"Auto-generated schema for method {method_name}: {auto_schema.__name__}")
280
+ else:
281
+ logger.debug(f"No schema found or generated for method {method_name}")
282
+
154
283
  # Get method information
155
284
  operation_info = {
156
- 'name': method_name,
157
- 'method': method,
158
- 'schema': schemas.get(method_name),
159
- 'description': inspect.getdoc(method) or f"Execute {method_name} operation",
160
- 'is_async': inspect.iscoroutinefunction(method)
285
+ "name": method_name,
286
+ "method": method,
287
+ "schema": matching_schema,
288
+ "description": inspect.getdoc(method) or f"Execute {method_name} operation",
289
+ "is_async": inspect.iscoroutinefunction(method),
290
+ "is_provider_operation": False, # Mark as tool-level operation
161
291
  }
162
-
292
+
163
293
  operations.append(operation_info)
164
-
294
+
165
295
  return operations
166
-
167
- def _extract_description(self, method, base_tool_name: str, operation_name: str, schema: Optional[Type[BaseModel]] = None) -> str:
296
+
297
+ def _extract_description(
298
+ self,
299
+ method,
300
+ base_tool_name: str,
301
+ operation_name: str,
302
+ schema: Optional[Type[BaseModel]] = None,
303
+ ) -> str:
168
304
  """Extract detailed description from method docstring and schema"""
169
305
  doc = inspect.getdoc(method)
170
-
306
+
171
307
  # Base description
172
308
  if doc:
173
- base_desc = doc.split('\n')[0].strip()
309
+ base_desc = doc.split("\n")[0].strip()
174
310
  else:
175
311
  base_desc = f"Execute {operation_name} operation"
176
-
312
+
177
313
  # Enhanced description - add specific tool functionality description
178
314
  enhanced_desc = f"{base_desc}"
179
-
315
+
180
316
  # Add specific descriptions based on tool name and operation
181
317
  if base_tool_name == "chart":
182
318
  if operation_name == "read_data":
183
319
  enhanced_desc = "Read and analyze data files in multiple formats (CSV, Excel, JSON, Parquet, etc.). Returns data structure summary, preview, and optional export functionality."
184
320
  elif operation_name == "visualize":
185
- enhanced_desc = "Create data visualizations including histograms, scatter plots, bar charts, line charts, heatmaps, and pair plots. Supports customizable styling, colors, and high-resolution output."
321
+ enhanced_desc = (
322
+ "Create data visualizations including histograms, scatter plots, bar charts, line charts, "
323
+ "heatmaps, and pair plots. Supports customizable styling, colors, and high-resolution output."
324
+ )
186
325
  elif operation_name == "export_data":
187
326
  enhanced_desc = "Export data to various formats (JSON, CSV, HTML, Excel, Markdown) with optional variable selection and path customization."
188
327
  elif base_tool_name == "pandas":
189
328
  enhanced_desc = f"Pandas data manipulation: {base_desc}. Supports DataFrame operations with built-in validation and error handling."
190
329
  elif base_tool_name == "stats":
191
330
  enhanced_desc = f"Statistical analysis: {base_desc}. Provides statistical tests, regression analysis, and data preprocessing capabilities."
192
-
331
+
193
332
  # Add parameter information
194
333
  if schema:
195
334
  try:
196
- fields = schema.__fields__ if hasattr(schema, '__fields__') else {}
197
- if fields:
335
+ fields_raw: Any = schema.__fields__ if hasattr(schema, "__fields__") else {}
336
+ # Type narrowing: ensure fields is a dict
337
+ fields: Dict[str, Any] = fields_raw if isinstance(fields_raw, dict) else {}
338
+ if isinstance(fields, dict) and fields:
198
339
  required_params = [name for name, field in fields.items() if field.is_required()]
199
340
  optional_params = [name for name, field in fields.items() if not field.is_required()]
200
-
341
+
201
342
  param_desc = ""
202
343
  if required_params:
203
344
  param_desc += f" Required: {', '.join(required_params)}."
204
345
  if optional_params:
205
346
  param_desc += f" Optional: {', '.join(optional_params)}."
206
-
347
+
207
348
  enhanced_desc += param_desc
208
349
  except Exception:
209
350
  pass
210
-
351
+
211
352
  return enhanced_desc
212
-
353
+
213
354
  def create_langchain_tools(self, tool_name: str) -> List[LangchainToolAdapter]:
214
355
  """
215
356
  Create all Langchain adapters for specified tool
216
-
357
+
217
358
  Args:
218
359
  tool_name: Tool name
219
-
360
+
220
361
  Returns:
221
362
  List of Langchain tool adapters
222
363
  """
223
364
  if not LANGCHAIN_AVAILABLE:
224
365
  raise ImportError("langchain is not installed. Please install it to use this adapter.")
225
-
366
+
226
367
  if tool_name not in TOOL_CLASSES:
227
368
  raise ValueError(f"Tool '{tool_name}' not found in registry")
228
-
369
+
229
370
  base_tool_class = TOOL_CLASSES[tool_name]
230
371
  operations = self.discover_operations(base_tool_class)
231
-
372
+
232
373
  langchain_tools = []
233
374
  for op_info in operations:
234
375
  # Generate enhanced description
235
- enhanced_description = self._extract_description(
236
- op_info['method'],
237
- tool_name,
238
- op_info['name'],
239
- op_info['schema']
240
- )
241
-
376
+ # For provider operations, use the description directly
377
+ if op_info.get("is_provider_operation", False):
378
+ enhanced_description = op_info["description"]
379
+ else:
380
+ enhanced_description = self._extract_description(
381
+ op_info["method"],
382
+ tool_name,
383
+ op_info["name"],
384
+ op_info["schema"],
385
+ )
386
+
387
+ # Create adapter with provider operation support
242
388
  adapter = LangchainToolAdapter(
243
389
  base_tool_name=tool_name,
244
- operation_name=op_info['name'],
245
- operation_schema=op_info['schema'],
246
- description=enhanced_description
390
+ operation_name=op_info["name"],
391
+ operation_schema=op_info["schema"],
392
+ description=enhanced_description,
393
+ is_provider_operation=op_info.get("is_provider_operation", False),
394
+ provider_name=op_info.get("provider_name"),
395
+ method_name=op_info.get("method_name"),
247
396
  )
248
-
397
+
249
398
  langchain_tools.append(adapter)
250
399
  self._langchain_tools[adapter.name] = adapter
251
-
400
+
252
401
  logger.info(f"Created {len(langchain_tools)} Langchain tools for {tool_name}")
253
402
  return langchain_tools
254
-
403
+
255
404
  def create_all_langchain_tools(self) -> List[LangchainToolAdapter]:
256
405
  """
257
406
  Create Langchain adapters for all registered BaseTools
258
-
407
+
259
408
  Returns:
260
409
  List of all Langchain tool adapters
261
410
  """
262
411
  all_tools = []
263
-
264
- for tool_name in list_tools():
412
+
413
+ # list_tools() returns a list of dicts, extract tool names
414
+ tool_infos = list_tools()
415
+ for tool_info in tool_infos:
416
+ tool_name = tool_info["name"]
265
417
  try:
266
418
  tools = self.create_langchain_tools(tool_name)
267
419
  all_tools.extend(tools)
268
420
  except Exception as e:
269
421
  logger.error(f"Failed to create Langchain tools for {tool_name}: {e}")
270
-
271
- logger.info(f"Created total {len(all_tools)} Langchain tools from {len(list_tools())} base tools")
422
+
423
+ logger.info(f"Created total {len(all_tools)} Langchain tools from {len(tool_infos)} base tools")
272
424
  return all_tools
273
-
425
+
274
426
  def get_tool(self, name: str) -> Optional[LangchainToolAdapter]:
275
427
  """Get Langchain tool with specified name"""
276
428
  return self._langchain_tools.get(name)
277
-
429
+
278
430
  def list_langchain_tools(self) -> List[str]:
279
431
  """List all Langchain tool names"""
280
432
  return list(self._langchain_tools.keys())
281
433
 
434
+
282
435
  # Global registry instance
283
436
  tool_registry = ToolRegistry()
284
437
 
285
- def get_langchain_tools(tool_names: Optional[List[str]] = None) -> List[LangchainToolAdapter]:
438
+
439
+ def get_langchain_tools(
440
+ tool_names: Optional[List[str]] = None,
441
+ ) -> List[LangchainToolAdapter]:
286
442
  """
287
443
  Get Langchain tool collection
288
-
444
+
289
445
  Args:
290
446
  tool_names: List of tool names to convert, None means convert all tools
291
-
447
+
292
448
  Returns:
293
449
  List of Langchain tool adapters
294
450
  """
295
451
  if tool_names is None:
296
452
  return tool_registry.create_all_langchain_tools()
297
-
453
+
298
454
  all_tools = []
299
455
  for tool_name in tool_names:
300
456
  tools = tool_registry.create_langchain_tools(tool_name)
301
457
  all_tools.extend(tools)
302
-
458
+
303
459
  return all_tools
304
460
 
461
+
305
462
  def create_react_agent_tools() -> List[LangchainToolAdapter]:
306
463
  """
307
464
  Create complete tool collection for ReAct Agent
308
-
465
+
309
466
  Returns:
310
467
  List of adapted Langchain tools
311
468
  """
312
469
  return get_langchain_tools()
313
470
 
471
+
314
472
  def create_tool_calling_agent_tools() -> List[LangchainToolAdapter]:
315
473
  """
316
474
  Create complete tool collection for Tool Calling Agent
317
-
475
+
318
476
  Returns:
319
477
  List of adapted Langchain tools optimized for tool calling
320
478
  """
321
479
  return get_langchain_tools()
322
480
 
481
+
323
482
  # Compatibility check functionality
483
+
484
+
324
485
  def check_langchain_compatibility() -> Dict[str, Any]:
325
486
  """
326
487
  Check compatibility between current environment and Langchain
327
-
488
+
328
489
  Returns:
329
490
  Compatibility check results
330
491
  """
331
- result = {
332
- 'langchain_available': LANGCHAIN_AVAILABLE,
333
- 'total_base_tools': len(list_tools()),
334
- 'compatible_tools': [],
335
- 'incompatible_tools': [],
336
- 'total_operations': 0
492
+ result: Dict[str, Any] = {
493
+ "langchain_available": LANGCHAIN_AVAILABLE,
494
+ "total_base_tools": len(list_tools()),
495
+ "compatible_tools": [],
496
+ "incompatible_tools": [],
497
+ "total_operations": 0,
337
498
  }
338
-
499
+
339
500
  if not LANGCHAIN_AVAILABLE:
340
- result['error'] = 'Langchain not installed'
501
+ result["error"] = "Langchain not installed"
341
502
  return result
342
-
503
+
343
504
  for tool_name in list_tools():
344
505
  try:
345
506
  tool_class = TOOL_CLASSES[tool_name]
346
507
  operations = tool_registry.discover_operations(tool_class)
347
-
348
- result['compatible_tools'].append({
349
- 'name': tool_name,
350
- 'operations_count': len(operations),
351
- 'operations': [op['name'] for op in operations]
352
- })
353
- result['total_operations'] += len(operations)
354
-
508
+
509
+ result["compatible_tools"].append(
510
+ {
511
+ "name": tool_name,
512
+ "operations_count": len(operations),
513
+ "operations": [op["name"] for op in operations],
514
+ }
515
+ )
516
+ total_ops = result.get("total_operations", 0)
517
+ if isinstance(total_ops, (int, float)):
518
+ result["total_operations"] = total_ops + len(operations)
519
+
355
520
  except Exception as e:
356
- result['incompatible_tools'].append({
357
- 'name': tool_name,
358
- 'error': str(e)
359
- })
360
-
521
+ result["incompatible_tools"].append({"name": tool_name, "error": str(e)})
522
+
361
523
  return result