aiecs 1.3.4__tar.gz → 1.3.7__tar.gz

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 (182) hide show
  1. {aiecs-1.3.4/aiecs.egg-info → aiecs-1.3.7}/PKG-INFO +1 -1
  2. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/__init__.py +1 -1
  3. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/vertex_client.py +111 -38
  4. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/main.py +2 -2
  5. {aiecs-1.3.4 → aiecs-1.3.7/aiecs.egg-info}/PKG-INFO +1 -1
  6. {aiecs-1.3.4 → aiecs-1.3.7}/pyproject.toml +1 -1
  7. {aiecs-1.3.4 → aiecs-1.3.7}/LICENSE +0 -0
  8. {aiecs-1.3.4 → aiecs-1.3.7}/MANIFEST.in +0 -0
  9. {aiecs-1.3.4 → aiecs-1.3.7}/README.md +0 -0
  10. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/__main__.py +0 -0
  11. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/aiecs_client.py +0 -0
  12. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/application/__init__.py +0 -0
  13. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/application/executors/__init__.py +0 -0
  14. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/application/executors/operation_executor.py +0 -0
  15. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/config/__init__.py +0 -0
  16. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/config/config.py +0 -0
  17. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/config/registry.py +0 -0
  18. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/core/__init__.py +0 -0
  19. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/core/interface/__init__.py +0 -0
  20. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/core/interface/execution_interface.py +0 -0
  21. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/core/interface/storage_interface.py +0 -0
  22. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/__init__.py +0 -0
  23. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/__init__.py +0 -0
  24. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/agent_adapter.py +0 -0
  25. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/analytics.py +0 -0
  26. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/collaborative_workflow.py +0 -0
  27. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/communication_hub.py +0 -0
  28. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/community_builder.py +0 -0
  29. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/community_integration.py +0 -0
  30. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/community_manager.py +0 -0
  31. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/decision_engine.py +0 -0
  32. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/exceptions.py +0 -0
  33. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/models/__init__.py +0 -0
  34. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/models/community_models.py +0 -0
  35. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/resource_manager.py +0 -0
  36. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/community/shared_context_manager.py +0 -0
  37. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/context/__init__.py +0 -0
  38. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/context/context_engine.py +0 -0
  39. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/context/conversation_models.py +0 -0
  40. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/execution/__init__.py +0 -0
  41. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/execution/model.py +0 -0
  42. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/task/__init__.py +0 -0
  43. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/task/dsl_processor.py +0 -0
  44. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/task/model.py +0 -0
  45. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/domain/task/task_context.py +0 -0
  46. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/__init__.py +0 -0
  47. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/messaging/__init__.py +0 -0
  48. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/messaging/celery_task_manager.py +0 -0
  49. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/messaging/websocket_manager.py +0 -0
  50. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/monitoring/__init__.py +0 -0
  51. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/monitoring/executor_metrics.py +0 -0
  52. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/monitoring/global_metrics_manager.py +0 -0
  53. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/monitoring/structured_logger.py +0 -0
  54. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/monitoring/tracing_manager.py +0 -0
  55. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/persistence/__init__.py +0 -0
  56. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/persistence/context_engine_client.py +0 -0
  57. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/persistence/database_manager.py +0 -0
  58. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/persistence/file_storage.py +0 -0
  59. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/infrastructure/persistence/redis_client.py +0 -0
  60. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/__init__.py +0 -0
  61. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/callbacks/__init__.py +0 -0
  62. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/callbacks/custom_callbacks.py +0 -0
  63. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/client_factory.py +0 -0
  64. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/__init__.py +0 -0
  65. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/base_client.py +0 -0
  66. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/googleai_client.py +0 -0
  67. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/openai_client.py +0 -0
  68. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/clients/xai_client.py +0 -0
  69. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/config/__init__.py +0 -0
  70. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/config/config_loader.py +0 -0
  71. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/config/config_validator.py +0 -0
  72. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/config/model_config.py +0 -0
  73. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/utils/__init__.py +0 -0
  74. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/llm/utils/validate_config.py +0 -0
  75. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/__init__.py +0 -0
  76. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/aid/VERSION_MANAGEMENT.md +0 -0
  77. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/aid/__init__.py +0 -0
  78. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/aid/version_manager.py +0 -0
  79. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/DEPENDENCY_SYSTEM_SUMMARY.md +0 -0
  80. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/README_DEPENDENCY_CHECKER.md +0 -0
  81. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/__init__.py +0 -0
  82. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/dependency_checker.py +0 -0
  83. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/dependency_fixer.py +0 -0
  84. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/download_nlp_data.py +0 -0
  85. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/quick_dependency_check.py +0 -0
  86. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_check/setup_nlp_data.sh +0 -0
  87. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/__init__.py +0 -0
  88. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/README_WEASEL_PATCH.md +0 -0
  89. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/__init__.py +0 -0
  90. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.py +0 -0
  91. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/fix_weasel_validator.sh +0 -0
  92. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/patch_weasel_library.sh +0 -0
  93. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/dependance_patch/fix_weasel/run_weasel_patch.sh +0 -0
  94. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/README.md +0 -0
  95. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/TOOL_AUTO_DISCOVERY.md +0 -0
  96. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/__init__.py +0 -0
  97. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/check_type_annotations.py +0 -0
  98. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/validate_tool_schemas.py +0 -0
  99. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/scripts/tools_develop/verify_tools.py +0 -0
  100. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tasks/__init__.py +0 -0
  101. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tasks/worker.py +0 -0
  102. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/__init__.py +0 -0
  103. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/__init__.py +0 -0
  104. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/intelligence/__init__.py +0 -0
  105. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/intelligence/data_fusion.py +0 -0
  106. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/intelligence/query_analyzer.py +0 -0
  107. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/intelligence/search_enhancer.py +0 -0
  108. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/monitoring/__init__.py +0 -0
  109. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/monitoring/metrics.py +0 -0
  110. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/__init__.py +0 -0
  111. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/base.py +0 -0
  112. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/census.py +0 -0
  113. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/fred.py +0 -0
  114. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/newsapi.py +0 -0
  115. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/providers/worldbank.py +0 -0
  116. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/reliability/__init__.py +0 -0
  117. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/reliability/error_handler.py +0 -0
  118. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/reliability/fallback_strategy.py +0 -0
  119. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/tool.py +0 -0
  120. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/utils/__init__.py +0 -0
  121. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/apisource/utils/validators.py +0 -0
  122. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/base_tool.py +0 -0
  123. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/__init__.py +0 -0
  124. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/ai_document_orchestrator.py +0 -0
  125. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/ai_document_writer_orchestrator.py +0 -0
  126. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/content_insertion_tool.py +0 -0
  127. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/document_creator_tool.py +0 -0
  128. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/document_layout_tool.py +0 -0
  129. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/document_parser_tool.py +0 -0
  130. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/docs/document_writer_tool.py +0 -0
  131. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/langchain_adapter.py +0 -0
  132. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/schema_generator.py +0 -0
  133. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/__init__.py +0 -0
  134. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/analyzers.py +0 -0
  135. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/cache.py +0 -0
  136. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/constants.py +0 -0
  137. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/context.py +0 -0
  138. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/core.py +0 -0
  139. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/deduplicator.py +0 -0
  140. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/error_handler.py +0 -0
  141. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/metrics.py +0 -0
  142. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/rate_limiter.py +0 -0
  143. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/search_tool/schemas.py +0 -0
  144. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/__init__.py +0 -0
  145. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/ai_data_analysis_orchestrator.py +0 -0
  146. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/ai_insight_generator_tool.py +0 -0
  147. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/ai_report_orchestrator_tool.py +0 -0
  148. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/data_loader_tool.py +0 -0
  149. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/data_profiler_tool.py +0 -0
  150. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/data_transformer_tool.py +0 -0
  151. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/data_visualizer_tool.py +0 -0
  152. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/model_trainer_tool.py +0 -0
  153. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/statistics/statistical_analyzer_tool.py +0 -0
  154. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/__init__.py +0 -0
  155. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/chart_tool.py +0 -0
  156. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/classfire_tool.py +0 -0
  157. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/image_tool.py +0 -0
  158. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/office_tool.py +0 -0
  159. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/pandas_tool.py +0 -0
  160. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/report_tool.py +0 -0
  161. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/research_tool.py +0 -0
  162. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/scraper_tool.py +0 -0
  163. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/task_tools/stats_tool.py +0 -0
  164. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/temp_file_manager.py +0 -0
  165. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/tool_executor/__init__.py +0 -0
  166. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/tools/tool_executor/tool_executor.py +0 -0
  167. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/LLM_output_structor.py +0 -0
  168. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/__init__.py +0 -0
  169. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/base_callback.py +0 -0
  170. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/cache_provider.py +0 -0
  171. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/execution_utils.py +0 -0
  172. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/logging.py +0 -0
  173. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/prompt_loader.py +0 -0
  174. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/utils/token_usage_repository.py +0 -0
  175. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/ws/__init__.py +0 -0
  176. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs/ws/socket_server.py +0 -0
  177. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs.egg-info/SOURCES.txt +0 -0
  178. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs.egg-info/dependency_links.txt +0 -0
  179. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs.egg-info/entry_points.txt +0 -0
  180. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs.egg-info/requires.txt +0 -0
  181. {aiecs-1.3.4 → aiecs-1.3.7}/aiecs.egg-info/top_level.txt +0 -0
  182. {aiecs-1.3.4 → aiecs-1.3.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiecs
3
- Version: 1.3.4
3
+ Version: 1.3.7
4
4
  Summary: AI Execute Services - A middleware framework for AI-powered task execution and tool orchestration
5
5
  Author-email: AIECS Team <iretbl@gmail.com>
6
6
  License-Expression: MIT
@@ -5,7 +5,7 @@ A powerful Python middleware framework for building AI-powered applications
5
5
  with tool orchestration, task execution, and multi-provider LLM support.
6
6
  """
7
7
 
8
- __version__ = "1.3.4"
8
+ __version__ = "1.3.7"
9
9
  __author__ = "AIECS Team"
10
10
  __email__ = "iretbl@gmail.com"
11
11
 
@@ -23,6 +23,12 @@ class VertexAIClient(BaseLLMClient):
23
23
  super().__init__("Vertex")
24
24
  self.settings = get_settings()
25
25
  self._initialized = False
26
+ # Track part count statistics for monitoring
27
+ self._part_count_stats = {
28
+ "total_responses": 0,
29
+ "part_counts": {}, # {part_count: frequency}
30
+ "last_part_count": None
31
+ }
26
32
 
27
33
  def _init_vertex_ai(self):
28
34
  """Lazy initialization of Vertex AI with proper authentication"""
@@ -141,52 +147,62 @@ class VertexAIClient(BaseLLMClient):
141
147
  text_parts.append(part.text)
142
148
 
143
149
  if text_parts:
150
+ # Log part count for monitoring
151
+ part_count = len(text_parts)
152
+ self.logger.info(f"📊 Vertex AI response: {part_count} parts detected")
153
+
154
+ # Update statistics
155
+ self._part_count_stats["total_responses"] += 1
156
+ self._part_count_stats["part_counts"][part_count] = self._part_count_stats["part_counts"].get(part_count, 0) + 1
157
+ self._part_count_stats["last_part_count"] = part_count
158
+
159
+ # Log statistics if significant variation detected
160
+ if part_count != self._part_count_stats.get("last_part_count", part_count):
161
+ self.logger.warning(f"⚠️ Part count variation detected: {part_count} parts (previous: {self._part_count_stats.get('last_part_count', 'unknown')})")
162
+
144
163
  # Handle multi-part response format
145
164
  if len(text_parts) > 1:
146
- # Multi-part response (typical for Gemini 2.5 with tool calling)
147
- # Check if parts already contain <thinking> tags
148
- first_part = text_parts[0]
149
- has_thinking_tags = '<thinking>' in first_part
165
+ # Multi-part response
166
+ # Minimal fix: only fix incomplete <thinking> tags, preserve original order
167
+ # Do NOT reorganize content - let downstream code handle semantics
150
168
 
151
- if has_thinking_tags:
152
- # Parts already have <thinking> tags, extract thinking content and actual output
153
- thinking_contents = []
154
- actual_outputs = []
169
+ processed_parts = []
170
+ fixed_count = 0
171
+
172
+ for i, part in enumerate(text_parts):
173
+ # Check for thinking content that needs formatting
174
+ needs_thinking_format = False
155
175
 
156
- for part in text_parts:
157
- if '<thinking>' in part and '</thinking>' in part:
158
- # Extract thinking content from this part
159
- import re
160
- thinking_match = re.search(r'<thinking>(.*?)</thinking>', part, re.DOTALL)
161
- if thinking_match:
162
- thinking_contents.append(thinking_match.group(1).strip())
163
-
164
- # Extract content after </thinking>
165
- after_thinking = part[thinking_match.end():].strip()
166
- if after_thinking:
167
- actual_outputs.append(after_thinking)
176
+ if '<thinking>' in part and '</thinking>' not in part:
177
+ # Incomplete <thinking> tag: add closing tag
178
+ part = part + '\n</thinking>'
179
+ needs_thinking_format = True
180
+ self.logger.debug(f" Part {i+1}: Incomplete <thinking> tag fixed")
181
+ elif part.startswith('thinking') and '</thinking>' not in part:
182
+ # thinking\n format: convert to <thinking>...</thinking>
183
+ if part.startswith('thinking\n'):
184
+ # thinking\n格式:提取内容并包装
185
+ content = part[8:] # 跳过 "thinking\n"
168
186
  else:
169
- # This part doesn't have thinking tags, treat as actual output
170
- actual_outputs.append(part)
187
+ # thinking开头但无换行:提取内容并包装
188
+ content = part[7:] # 跳过 "thinking"
189
+
190
+ part = f"<thinking>\n{content}\n</thinking>"
191
+ needs_thinking_format = True
192
+ self.logger.debug(f" Part {i+1}: thinking\\n format converted to <thinking> tags")
171
193
 
172
- # Combine thinking content and actual outputs
173
- if thinking_contents:
174
- combined_thinking = '\n\n'.join(thinking_contents)
175
- content = f"<thinking>\n{combined_thinking}\n</thinking>"
176
- if actual_outputs:
177
- content += "\n" + "\n".join(actual_outputs)
178
- else:
179
- content = "\n".join(text_parts)
194
+ if needs_thinking_format:
195
+ fixed_count += 1
180
196
 
181
- self.logger.info(f"✅ Multi-part response with existing <thinking> tags processed: {len(text_parts)} parts")
197
+ processed_parts.append(part)
198
+
199
+ # Merge in original order
200
+ content = "\n".join(processed_parts)
201
+
202
+ if fixed_count > 0:
203
+ self.logger.info(f"✅ Multi-part response merged: {len(text_parts)} parts, {fixed_count} incomplete tags fixed, order preserved")
182
204
  else:
183
- # Parts don't have <thinking> tags, wrap first part
184
- thinking_part = text_parts[0]
185
- actual_output_parts = text_parts[1:]
186
-
187
- # Format: <thinking>Part 1</thinking>\nPart 2\nPart 3...
188
- content = f"<thinking>\n{thinking_part}\n</thinking>\n" + "\n".join(actual_output_parts)
189
- self.logger.info(f"✅ Multi-part response wrapped with <thinking> tags: {len(text_parts)} parts")
205
+ self.logger.info(f"✅ Multi-part response merged: {len(text_parts)} parts, order preserved")
190
206
  else:
191
207
  # Single part response - use as is
192
208
  content = text_parts[0]
@@ -271,7 +287,64 @@ class VertexAIClient(BaseLLMClient):
271
287
  yield word + " "
272
288
  await asyncio.sleep(0.05) # Small delay to simulate streaming
273
289
 
290
+ def get_part_count_stats(self) -> Dict[str, Any]:
291
+ """
292
+ Get statistics about part count variations in Vertex AI responses.
293
+
294
+ Returns:
295
+ Dictionary containing part count statistics and analysis
296
+ """
297
+ stats = self._part_count_stats.copy()
298
+
299
+ if stats["total_responses"] > 0:
300
+ # Calculate variation metrics
301
+ part_counts = list(stats["part_counts"].keys())
302
+ stats["variation_analysis"] = {
303
+ "unique_part_counts": len(part_counts),
304
+ "most_common_count": max(stats["part_counts"].items(), key=lambda x: x[1])[0] if stats["part_counts"] else None,
305
+ "part_count_range": f"{min(part_counts)}-{max(part_counts)}" if part_counts else "N/A",
306
+ "stability_score": 1.0 - (len(part_counts) - 1) / max(stats["total_responses"], 1) # 0-1, higher is more stable
307
+ }
308
+
309
+ # Generate recommendations
310
+ if stats["variation_analysis"]["stability_score"] < 0.7:
311
+ stats["recommendations"] = [
312
+ "High part count variation detected",
313
+ "Consider optimizing prompt structure",
314
+ "Monitor input complexity patterns",
315
+ "Review tool calling configuration"
316
+ ]
317
+ else:
318
+ stats["recommendations"] = [
319
+ "Part count variation is within acceptable range",
320
+ "Continue monitoring for patterns"
321
+ ]
322
+
323
+ return stats
324
+
325
+ def log_part_count_summary(self):
326
+ """Log a summary of part count statistics"""
327
+ stats = self.get_part_count_stats()
328
+
329
+ if stats["total_responses"] > 0:
330
+ self.logger.info("📈 Vertex AI Part Count Summary:")
331
+ self.logger.info(f" Total responses: {stats['total_responses']}")
332
+ self.logger.info(f" Part count distribution: {stats['part_counts']}")
333
+
334
+ if "variation_analysis" in stats:
335
+ analysis = stats["variation_analysis"]
336
+ self.logger.info(f" Stability score: {analysis['stability_score']:.2f}")
337
+ self.logger.info(f" Most common count: {analysis['most_common_count']}")
338
+ self.logger.info(f" Count range: {analysis['part_count_range']}")
339
+
340
+ if "recommendations" in stats:
341
+ self.logger.info(" Recommendations:")
342
+ for rec in stats["recommendations"]:
343
+ self.logger.info(f" • {rec}")
344
+
274
345
  async def close(self):
275
346
  """Clean up resources"""
347
+ # Log final statistics before cleanup
348
+ self.log_part_count_summary()
276
349
  # Vertex AI doesn't require explicit cleanup
277
350
  self._initialized = False
@@ -142,7 +142,7 @@ async def lifespan(app: FastAPI):
142
142
  app = FastAPI(
143
143
  title="AIECS - AI Execute Services",
144
144
  description="Middleware service for AI-powered task execution and tool orchestration",
145
- version="1.3.4",
145
+ version="1.3.7",
146
146
  lifespan=lifespan
147
147
  )
148
148
 
@@ -167,7 +167,7 @@ async def health_check():
167
167
  return {
168
168
  "status": "healthy",
169
169
  "service": "aiecs",
170
- "version": "1.3.4"
170
+ "version": "1.3.7"
171
171
  }
172
172
 
173
173
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiecs
3
- Version: 1.3.4
3
+ Version: 1.3.7
4
4
  Summary: AI Execute Services - A middleware framework for AI-powered task execution and tool orchestration
5
5
  Author-email: AIECS Team <iretbl@gmail.com>
6
6
  License-Expression: MIT
@@ -28,7 +28,7 @@ pytest-timeout = "^2.4.0"
28
28
 
29
29
  [project]
30
30
  name = "aiecs"
31
- version = "1.3.4"
31
+ version = "1.3.7"
32
32
  description = "AI Execute Services - A middleware framework for AI-powered task execution and tool orchestration"
33
33
  authors = [
34
34
  {name = "AIECS Team", email = "iretbl@gmail.com"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes