aiecs 1.0.0__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 (90) hide show
  1. aiecs/__init__.py +75 -0
  2. aiecs/__main__.py +41 -0
  3. aiecs/aiecs_client.py +295 -0
  4. aiecs/application/__init__.py +10 -0
  5. aiecs/application/executors/__init__.py +10 -0
  6. aiecs/application/executors/operation_executor.py +341 -0
  7. aiecs/config/__init__.py +15 -0
  8. aiecs/config/config.py +117 -0
  9. aiecs/config/registry.py +19 -0
  10. aiecs/core/__init__.py +46 -0
  11. aiecs/core/interface/__init__.py +34 -0
  12. aiecs/core/interface/execution_interface.py +150 -0
  13. aiecs/core/interface/storage_interface.py +214 -0
  14. aiecs/domain/__init__.py +20 -0
  15. aiecs/domain/context/__init__.py +28 -0
  16. aiecs/domain/context/content_engine.py +982 -0
  17. aiecs/domain/context/conversation_models.py +306 -0
  18. aiecs/domain/execution/__init__.py +12 -0
  19. aiecs/domain/execution/model.py +49 -0
  20. aiecs/domain/task/__init__.py +13 -0
  21. aiecs/domain/task/dsl_processor.py +460 -0
  22. aiecs/domain/task/model.py +50 -0
  23. aiecs/domain/task/task_context.py +257 -0
  24. aiecs/infrastructure/__init__.py +26 -0
  25. aiecs/infrastructure/messaging/__init__.py +13 -0
  26. aiecs/infrastructure/messaging/celery_task_manager.py +341 -0
  27. aiecs/infrastructure/messaging/websocket_manager.py +289 -0
  28. aiecs/infrastructure/monitoring/__init__.py +12 -0
  29. aiecs/infrastructure/monitoring/executor_metrics.py +138 -0
  30. aiecs/infrastructure/monitoring/structured_logger.py +50 -0
  31. aiecs/infrastructure/monitoring/tracing_manager.py +376 -0
  32. aiecs/infrastructure/persistence/__init__.py +12 -0
  33. aiecs/infrastructure/persistence/database_manager.py +286 -0
  34. aiecs/infrastructure/persistence/file_storage.py +671 -0
  35. aiecs/infrastructure/persistence/redis_client.py +162 -0
  36. aiecs/llm/__init__.py +54 -0
  37. aiecs/llm/base_client.py +99 -0
  38. aiecs/llm/client_factory.py +339 -0
  39. aiecs/llm/custom_callbacks.py +228 -0
  40. aiecs/llm/openai_client.py +125 -0
  41. aiecs/llm/vertex_client.py +186 -0
  42. aiecs/llm/xai_client.py +184 -0
  43. aiecs/main.py +351 -0
  44. aiecs/scripts/DEPENDENCY_SYSTEM_SUMMARY.md +241 -0
  45. aiecs/scripts/README_DEPENDENCY_CHECKER.md +309 -0
  46. aiecs/scripts/README_WEASEL_PATCH.md +126 -0
  47. aiecs/scripts/__init__.py +3 -0
  48. aiecs/scripts/dependency_checker.py +825 -0
  49. aiecs/scripts/dependency_fixer.py +348 -0
  50. aiecs/scripts/download_nlp_data.py +348 -0
  51. aiecs/scripts/fix_weasel_validator.py +121 -0
  52. aiecs/scripts/fix_weasel_validator.sh +82 -0
  53. aiecs/scripts/patch_weasel_library.sh +188 -0
  54. aiecs/scripts/quick_dependency_check.py +269 -0
  55. aiecs/scripts/run_weasel_patch.sh +41 -0
  56. aiecs/scripts/setup_nlp_data.sh +217 -0
  57. aiecs/tasks/__init__.py +2 -0
  58. aiecs/tasks/worker.py +111 -0
  59. aiecs/tools/__init__.py +196 -0
  60. aiecs/tools/base_tool.py +202 -0
  61. aiecs/tools/langchain_adapter.py +361 -0
  62. aiecs/tools/task_tools/__init__.py +82 -0
  63. aiecs/tools/task_tools/chart_tool.py +704 -0
  64. aiecs/tools/task_tools/classfire_tool.py +901 -0
  65. aiecs/tools/task_tools/image_tool.py +397 -0
  66. aiecs/tools/task_tools/office_tool.py +600 -0
  67. aiecs/tools/task_tools/pandas_tool.py +565 -0
  68. aiecs/tools/task_tools/report_tool.py +499 -0
  69. aiecs/tools/task_tools/research_tool.py +363 -0
  70. aiecs/tools/task_tools/scraper_tool.py +548 -0
  71. aiecs/tools/task_tools/search_api.py +7 -0
  72. aiecs/tools/task_tools/stats_tool.py +513 -0
  73. aiecs/tools/temp_file_manager.py +126 -0
  74. aiecs/tools/tool_executor/__init__.py +35 -0
  75. aiecs/tools/tool_executor/tool_executor.py +518 -0
  76. aiecs/utils/LLM_output_structor.py +409 -0
  77. aiecs/utils/__init__.py +23 -0
  78. aiecs/utils/base_callback.py +50 -0
  79. aiecs/utils/execution_utils.py +158 -0
  80. aiecs/utils/logging.py +1 -0
  81. aiecs/utils/prompt_loader.py +13 -0
  82. aiecs/utils/token_usage_repository.py +279 -0
  83. aiecs/ws/__init__.py +0 -0
  84. aiecs/ws/socket_server.py +41 -0
  85. aiecs-1.0.0.dist-info/METADATA +610 -0
  86. aiecs-1.0.0.dist-info/RECORD +90 -0
  87. aiecs-1.0.0.dist-info/WHEEL +5 -0
  88. aiecs-1.0.0.dist-info/entry_points.txt +7 -0
  89. aiecs-1.0.0.dist-info/licenses/LICENSE +225 -0
  90. aiecs-1.0.0.dist-info/top_level.txt +1 -0
aiecs/__init__.py ADDED
@@ -0,0 +1,75 @@
1
+ """
2
+ AIECS - AI Execute Services
3
+
4
+ A powerful Python middleware framework for building AI-powered applications
5
+ with tool orchestration, task execution, and multi-provider LLM support.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+ __author__ = "AIECS Team"
10
+ __email__ = "iretbl@gmail.com"
11
+
12
+ # Core imports - these should work without configuration
13
+ from .aiecs_client import AIECS, create_aiecs_client, create_simple_client, create_full_client
14
+ from .domain.task.task_context import TaskContext
15
+
16
+ # Configuration
17
+ from .config.config import get_settings, validate_required_settings
18
+
19
+ # Tool system - safe to import
20
+ from .tools import (
21
+ discover_tools,
22
+ list_tools,
23
+ get_tool,
24
+ register_tool
25
+ )
26
+
27
+ # Infrastructure components - can be imported safely (for advanced usage)
28
+ # These classes only require configuration when actually used
29
+ from .infrastructure.persistence.database_manager import DatabaseManager
30
+ from .infrastructure.messaging.celery_task_manager import CeleryTaskManager
31
+
32
+ # LLM providers
33
+ from .llm.client_factory import LLMClientFactory, AIProvider
34
+
35
+
36
+ def get_fastapi_app():
37
+ """
38
+ Get the FastAPI application instance (lazy loading)
39
+ Only loads when explicitly requested to avoid import-time configuration validation
40
+ """
41
+ from .main import app
42
+ return app
43
+
44
+ __all__ = [
45
+ # Core API
46
+ "AIECS",
47
+ "create_aiecs_client",
48
+ "create_simple_client",
49
+ "create_full_client",
50
+ "TaskContext",
51
+
52
+ # FastAPI application (lazy loading)
53
+ "get_fastapi_app",
54
+
55
+ # Tool system
56
+ "discover_tools",
57
+ "list_tools",
58
+ "get_tool",
59
+ "register_tool",
60
+
61
+ # Configuration
62
+ "get_settings",
63
+ "validate_required_settings",
64
+
65
+ # Infrastructure (advanced)
66
+ "DatabaseManager",
67
+ "CeleryTaskManager",
68
+ "LLMClientFactory",
69
+ "AIProvider",
70
+
71
+ # Metadata
72
+ "__version__",
73
+ "__author__",
74
+ "__email__",
75
+ ]
aiecs/__main__.py ADDED
@@ -0,0 +1,41 @@
1
+ """
2
+ AIECS main entry point for command line execution
3
+ """
4
+
5
+ import sys
6
+ import os
7
+
8
+
9
+ def main():
10
+ """Main entry point for AIECS CLI"""
11
+ # Add the parent directory to the Python path to ensure imports work
12
+ parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
13
+ if parent_dir not in sys.path:
14
+ sys.path.insert(0, parent_dir)
15
+
16
+ # Import and run uvicorn
17
+ import uvicorn
18
+ from aiecs.main import app
19
+ from aiecs.ws.socket_server import sio
20
+ import socketio
21
+
22
+ # Create the combined Socket.IO + FastAPI app
23
+ socket_app = socketio.ASGIApp(sio, other_asgi_app=app)
24
+
25
+ # Get port from environment or use default
26
+ port = int(os.environ.get("PORT", 8000))
27
+
28
+ print(f"Starting AIECS server on port {port}...")
29
+
30
+ # Run the application with Socket.IO support
31
+ uvicorn.run(
32
+ socket_app,
33
+ host="0.0.0.0",
34
+ port=port,
35
+ log_level="info",
36
+ reload=bool(os.environ.get("RELOAD", False))
37
+ )
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
aiecs/aiecs_client.py ADDED
@@ -0,0 +1,295 @@
1
+ """
2
+ AIECS Client - Main API for programmatic usage of AI Execute Services
3
+ """
4
+
5
+ import asyncio
6
+ import logging
7
+ from typing import Dict, Any, Optional, List
8
+ from contextlib import asynccontextmanager
9
+
10
+ # Import core components
11
+ from aiecs.config.config import get_settings, validate_required_settings
12
+ from aiecs.domain.task.task_context import TaskContext
13
+ from aiecs.tools import discover_tools, list_tools, get_tool
14
+ from aiecs.llm.client_factory import LLMClientFactory
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class AIECS:
20
+ """
21
+ Main AIECS client for programmatic usage
22
+
23
+ This class provides a high-level API for:
24
+ - Executing tasks with AI providers
25
+ - Managing tool orchestration
26
+ - Configuration management
27
+
28
+ Two operation modes:
29
+ - Simple mode: Tools and basic AI functionality (no database/Celery)
30
+ - Full mode: Complete infrastructure (requires database/Redis)
31
+ """
32
+
33
+ def __init__(self, config: Optional[Dict[str, Any]] = None, mode: str = "simple"):
34
+ """
35
+ Initialize AIECS client
36
+
37
+ Args:
38
+ config: Optional configuration override
39
+ mode: Operation mode - "simple" or "full"
40
+ """
41
+ self.settings = get_settings()
42
+ self.config = config or {}
43
+ self.mode = mode
44
+
45
+ # Core components (loaded based on mode)
46
+ self.db_manager = None
47
+ self.task_manager = None
48
+ self.operation_executor = None
49
+
50
+ # State
51
+ self._initialized = False
52
+ self._tools_discovered = False
53
+
54
+ async def initialize(self):
55
+ """Initialize AIECS services based on mode"""
56
+ if self._initialized:
57
+ return
58
+
59
+ logger.info(f"Initializing AIECS client in {self.mode} mode...")
60
+
61
+ try:
62
+ # Always discover tools
63
+ if not self._tools_discovered:
64
+ discover_tools("aiecs.tools")
65
+ self._tools_discovered = True
66
+ logger.info("Tools discovered and registered")
67
+
68
+ if self.mode == "simple":
69
+ # Simple mode: only tools, no database/Celery
70
+ logger.info("Simple mode: tools only")
71
+
72
+ elif self.mode == "full":
73
+ # Full mode: with database and task queue
74
+ try:
75
+ # Check configuration first
76
+ validate_required_settings("database")
77
+
78
+ # Initialize database connection
79
+ from aiecs.infrastructure.persistence.database_manager import DatabaseManager
80
+ self.db_manager = DatabaseManager()
81
+ await self.db_manager.init_connection_pool()
82
+ logger.info("Database connection pool established")
83
+
84
+ # Initialize task manager
85
+ from aiecs.infrastructure.messaging.celery_task_manager import CeleryTaskManager
86
+ celery_config = {
87
+ "broker_url": self.settings.celery_broker_url,
88
+ "backend_url": self.settings.celery_broker_url,
89
+ }
90
+ self.task_manager = CeleryTaskManager(celery_config)
91
+ logger.info("Task manager initialized")
92
+
93
+ # Initialize operation executor
94
+ from aiecs.application.executors.operation_executor import OperationExecutor
95
+ from aiecs.tools.tool_executor import ToolExecutor
96
+ from aiecs.utils.execution_utils import ExecutionUtils
97
+
98
+ tool_executor = ToolExecutor()
99
+ execution_utils = ExecutionUtils()
100
+ self.operation_executor = OperationExecutor(
101
+ tool_executor=tool_executor,
102
+ execution_utils=execution_utils,
103
+ config=self.config
104
+ )
105
+
106
+ except Exception as e:
107
+ logger.warning(f"Full mode initialization failed: {e}")
108
+ logger.info("Falling back to simple mode")
109
+ self.mode = "simple"
110
+
111
+ self._initialized = True
112
+ logger.info(f"AIECS client initialized successfully in {self.mode} mode")
113
+
114
+ except Exception as e:
115
+ logger.error(f"Failed to initialize AIECS: {e}")
116
+ raise
117
+
118
+ async def execute(self, context: TaskContext) -> Dict[str, Any]:
119
+ """
120
+ Execute a task with the given context
121
+
122
+ Args:
123
+ context: TaskContext with task parameters
124
+
125
+ Returns:
126
+ Task execution result
127
+ """
128
+ if not self._initialized:
129
+ await self.initialize()
130
+
131
+ if self.mode == "simple":
132
+ # Simple mode: direct execution without queue
133
+ logger.info("Executing task in simple mode (direct execution)")
134
+
135
+ # Basic validation
136
+ try:
137
+ validate_required_settings("llm")
138
+ except ValueError as e:
139
+ return {
140
+ "status": "failed",
141
+ "error": f"LLM configuration required: {e}",
142
+ "mode": "simple"
143
+ }
144
+
145
+ # TODO: Implement direct task execution without Celery
146
+ # For now, return a placeholder
147
+ return {
148
+ "status": "completed",
149
+ "result": "Simple mode execution (placeholder)",
150
+ "mode": "simple",
151
+ "context_id": context.user_id
152
+ }
153
+
154
+ elif self.mode == "full":
155
+ if not self.task_manager:
156
+ raise RuntimeError("Task manager not initialized in full mode")
157
+
158
+ # Submit task to queue and get result
159
+ task_id = await self.task_manager.submit_task(
160
+ context=context,
161
+ task_type="task"
162
+ )
163
+
164
+ # Wait for task completion
165
+ result = await self._wait_for_task_completion(task_id)
166
+ return result
167
+
168
+ else:
169
+ raise ValueError(f"Unknown mode: {self.mode}")
170
+
171
+ async def execute_tool(self, tool_name: str, operation: str, params: Dict[str, Any]) -> Any:
172
+ """
173
+ Execute a specific tool operation directly
174
+
175
+ Args:
176
+ tool_name: Name of the tool
177
+ operation: Operation to execute
178
+ params: Parameters for the operation
179
+
180
+ Returns:
181
+ Operation result
182
+ """
183
+ if not self._initialized:
184
+ await self.initialize()
185
+
186
+ # Get tool and execute directly (works in both modes)
187
+ tool = get_tool(tool_name)
188
+ if not tool:
189
+ raise ValueError(f"Tool '{tool_name}' not found")
190
+
191
+ # Prepare parameters with operation
192
+ tool_params = {**params, "op": operation}
193
+
194
+ # Execute tool
195
+ return await tool.execute(tool_params)
196
+
197
+ async def get_available_tools(self) -> List[Dict[str, Any]]:
198
+ """Get list of all available tools"""
199
+ if not self._tools_discovered:
200
+ discover_tools("aiecs.tools")
201
+ self._tools_discovered = True
202
+
203
+ return list_tools()
204
+
205
+ async def get_tool(self, tool_name: str):
206
+ """Get a specific tool instance"""
207
+ if not self._tools_discovered:
208
+ discover_tools("aiecs.tools")
209
+ self._tools_discovered = True
210
+
211
+ return get_tool(tool_name)
212
+
213
+ async def _wait_for_task_completion(self, task_id: str, timeout: int = 300) -> Dict[str, Any]:
214
+ """
215
+ Wait for task completion with timeout
216
+
217
+ Args:
218
+ task_id: Task ID to wait for
219
+ timeout: Maximum wait time in seconds
220
+
221
+ Returns:
222
+ Task result
223
+ """
224
+ if not self.task_manager:
225
+ raise RuntimeError("Task manager not initialized")
226
+
227
+ start_time = asyncio.get_event_loop().time()
228
+
229
+ while True:
230
+ status = await self.task_manager.get_task_status(task_id)
231
+
232
+ if status.get("status") in ["completed", "failed", "cancelled"]:
233
+ return status
234
+
235
+ # Check timeout
236
+ if asyncio.get_event_loop().time() - start_time > timeout:
237
+ raise TimeoutError(f"Task {task_id} did not complete within {timeout} seconds")
238
+
239
+ # Wait before checking again
240
+ await asyncio.sleep(1)
241
+
242
+ async def close(self):
243
+ """Close AIECS client and cleanup resources"""
244
+ logger.info("Shutting down AIECS client...")
245
+
246
+ if self.mode == "full" and self.db_manager:
247
+ try:
248
+ await self.db_manager.close_connection_pool()
249
+ logger.info("Database connection pool closed")
250
+ except Exception as e:
251
+ logger.error(f"Error closing database: {e}")
252
+
253
+ # Close all LLM clients
254
+ try:
255
+ await LLMClientFactory.close_all()
256
+ logger.info("LLM clients closed")
257
+ except Exception as e:
258
+ logger.error(f"Error closing LLM clients: {e}")
259
+
260
+ self._initialized = False
261
+ logger.info("AIECS client shutdown complete")
262
+
263
+ @asynccontextmanager
264
+ async def session(self):
265
+ """Context manager for AIECS session"""
266
+ await self.initialize()
267
+ try:
268
+ yield self
269
+ finally:
270
+ await self.close()
271
+
272
+
273
+ # Convenience functions for quick usage
274
+ async def create_aiecs_client(config: Optional[Dict[str, Any]] = None, mode: str = "simple") -> AIECS:
275
+ """
276
+ Create and initialize an AIECS client
277
+
278
+ Args:
279
+ config: Optional configuration override
280
+ mode: Operation mode - "simple" or "full"
281
+
282
+ Returns:
283
+ Initialized AIECS client
284
+ """
285
+ client = AIECS(config, mode)
286
+ await client.initialize()
287
+ return client
288
+
289
+ async def create_simple_client(config: Optional[Dict[str, Any]] = None) -> AIECS:
290
+ """Create a simple AIECS client (tools only, no database/Celery)"""
291
+ return await create_aiecs_client(config, "simple")
292
+
293
+ async def create_full_client(config: Optional[Dict[str, Any]] = None) -> AIECS:
294
+ """Create a full AIECS client (with database and Celery)"""
295
+ return await create_aiecs_client(config, "full")
@@ -0,0 +1,10 @@
1
+ """Application layer module
2
+
3
+ Contains application services and use case orchestration.
4
+ """
5
+
6
+ from .executors.operation_executor import OperationExecutor
7
+
8
+ __all__ = [
9
+ "OperationExecutor",
10
+ ]
@@ -0,0 +1,10 @@
1
+ """Application executors module
2
+
3
+ Contains service executors and application-level coordination.
4
+ """
5
+
6
+ from .operation_executor import OperationExecutor
7
+
8
+ __all__ = [
9
+ "OperationExecutor",
10
+ ]