django-cfg 1.3.9__py3-none-any.whl β 1.3.13__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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/inlines.py +11 -5
- django_cfg/apps/payments/admin/networks_admin.py +12 -1
- django_cfg/apps/payments/admin/payments_admin.py +13 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/payment_service.py +265 -38
- django_cfg/apps/payments/services/providers/base.py +209 -3
- django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
- django_cfg/apps/payments/services/providers/models/base.py +25 -2
- django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
- django_cfg/apps/payments/services/providers/registry.py +5 -5
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/views/api/currencies.py +3 -0
- django_cfg/apps/payments/views/serializers/currencies.py +18 -5
- django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html β overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/registry/core.py +4 -9
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.9.dist-info β django_cfg-1.3.13.dist-info}/METADATA +2 -2
- {django_cfg-1.3.9.dist-info β django_cfg-1.3.13.dist-info}/RECORD +85 -153
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/app_agent_diagnose.py +0 -470
- django_cfg/management/commands/app_agent_generate.py +0 -342
- django_cfg/management/commands/app_agent_info.py +0 -308
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/modules/django_app_agent/__init__.py +0 -87
- django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
- django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
- django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
- django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
- django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
- django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
- django_cfg/modules/django_app_agent/core/__init__.py +0 -33
- django_cfg/modules/django_app_agent/core/config.py +0 -300
- django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
- django_cfg/modules/django_app_agent/models/__init__.py +0 -71
- django_cfg/modules/django_app_agent/models/base.py +0 -283
- django_cfg/modules/django_app_agent/models/context.py +0 -496
- django_cfg/modules/django_app_agent/models/enums.py +0 -481
- django_cfg/modules/django_app_agent/models/requests.py +0 -500
- django_cfg/modules/django_app_agent/models/responses.py +0 -585
- django_cfg/modules/django_app_agent/pytest.ini +0 -6
- django_cfg/modules/django_app_agent/services/__init__.py +0 -42
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
- django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
- django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
- django_cfg/modules/django_app_agent/services/base.py +0 -437
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
- django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
- django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
- django_cfg/modules/django_app_agent/services/report_service.py +0 -332
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
- django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
- django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
- django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
- django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
- django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
- django_cfg/modules/django_app_agent/ui/cli.py +0 -419
- django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
- django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
- django_cfg/modules/django_app_agent/utils/logging.py +0 -360
- django_cfg/modules/django_app_agent/utils/validation.py +0 -417
- {django_cfg-1.3.9.dist-info β django_cfg-1.3.13.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.9.dist-info β django_cfg-1.3.13.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.9.dist-info β django_cfg-1.3.13.dist-info}/licenses/LICENSE +0 -0
@@ -1,430 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Agent execution management for Django App Agent Module.
|
3
|
-
|
4
|
-
This module provides execution management and orchestration for AI agents,
|
5
|
-
including result handling, error management, and performance tracking.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from typing import TypeVar, Generic, Optional, Dict, Any, List, Union, Callable, Awaitable
|
9
|
-
from dataclasses import dataclass, field
|
10
|
-
from datetime import datetime, timezone
|
11
|
-
from enum import Enum
|
12
|
-
import asyncio
|
13
|
-
|
14
|
-
from pydantic import BaseModel, Field, ConfigDict
|
15
|
-
|
16
|
-
from ...core.config import AgentConfig
|
17
|
-
from ...core.exceptions import AgentExecutionError, ValidationError
|
18
|
-
from ...models.base import TimestampedModel
|
19
|
-
from ...utils.logging import StructuredLogger, get_logger
|
20
|
-
from .context import AgentDependencies, AgentContext
|
21
|
-
from .agent import DjangoAgent
|
22
|
-
|
23
|
-
# Type variables
|
24
|
-
OutputT = TypeVar('OutputT')
|
25
|
-
DepsT = TypeVar('DepsT', bound=AgentDependencies)
|
26
|
-
|
27
|
-
|
28
|
-
class ExecutionStatus(str, Enum):
|
29
|
-
"""Status of agent execution."""
|
30
|
-
PENDING = "pending"
|
31
|
-
RUNNING = "running"
|
32
|
-
COMPLETED = "completed"
|
33
|
-
FAILED = "failed"
|
34
|
-
CANCELLED = "cancelled"
|
35
|
-
|
36
|
-
|
37
|
-
class ExecutionResult(BaseModel, Generic[OutputT]):
|
38
|
-
"""Result of agent execution."""
|
39
|
-
|
40
|
-
model_config = ConfigDict(
|
41
|
-
extra='forbid',
|
42
|
-
validate_assignment=True,
|
43
|
-
arbitrary_types_allowed=True
|
44
|
-
)
|
45
|
-
|
46
|
-
# Execution metadata
|
47
|
-
execution_id: str = Field(description="Unique execution identifier")
|
48
|
-
agent_name: str = Field(description="Name of the agent that was executed")
|
49
|
-
status: ExecutionStatus = Field(description="Execution status")
|
50
|
-
|
51
|
-
# Timing information
|
52
|
-
start_time: datetime = Field(description="Execution start time")
|
53
|
-
end_time: Optional[datetime] = Field(default=None, description="Execution end time")
|
54
|
-
|
55
|
-
# Results
|
56
|
-
output: Optional[OutputT] = Field(default=None, description="Agent output")
|
57
|
-
error: Optional[str] = Field(default=None, description="Error message if failed")
|
58
|
-
|
59
|
-
# Performance metrics
|
60
|
-
execution_time_seconds: float = Field(default=0.0, description="Total execution time")
|
61
|
-
token_usage: Dict[str, int] = Field(default_factory=dict, description="Token usage by provider")
|
62
|
-
api_calls_count: int = Field(default=0, description="Number of API calls made")
|
63
|
-
|
64
|
-
# Context information
|
65
|
-
correlation_id: str = Field(description="Correlation ID for tracing")
|
66
|
-
operation_name: str = Field(description="Name of the operation")
|
67
|
-
|
68
|
-
@property
|
69
|
-
def is_successful(self) -> bool:
|
70
|
-
"""Check if execution was successful."""
|
71
|
-
return self.status == ExecutionStatus.COMPLETED and self.output is not None
|
72
|
-
|
73
|
-
@property
|
74
|
-
def is_failed(self) -> bool:
|
75
|
-
"""Check if execution failed."""
|
76
|
-
return self.status == ExecutionStatus.FAILED
|
77
|
-
|
78
|
-
def get_summary(self) -> Dict[str, Any]:
|
79
|
-
"""Get execution summary."""
|
80
|
-
return {
|
81
|
-
"execution_id": self.execution_id,
|
82
|
-
"agent_name": self.agent_name,
|
83
|
-
"status": self.status.value,
|
84
|
-
"is_successful": self.is_successful,
|
85
|
-
"execution_time_seconds": self.execution_time_seconds,
|
86
|
-
"total_tokens": sum(self.token_usage.values()),
|
87
|
-
"api_calls": self.api_calls_count,
|
88
|
-
"has_output": self.output is not None,
|
89
|
-
"has_error": self.error is not None,
|
90
|
-
}
|
91
|
-
|
92
|
-
|
93
|
-
@dataclass
|
94
|
-
class ExecutionPlan:
|
95
|
-
"""Plan for executing multiple agents in sequence or parallel."""
|
96
|
-
|
97
|
-
name: str
|
98
|
-
agents: List[DjangoAgent] = field(default_factory=list)
|
99
|
-
dependencies: Dict[str, List[str]] = field(default_factory=dict)
|
100
|
-
parallel_groups: List[List[str]] = field(default_factory=list)
|
101
|
-
timeout_seconds: float = 300.0
|
102
|
-
|
103
|
-
def add_agent(self, agent: DjangoAgent, depends_on: Optional[List[str]] = None) -> None:
|
104
|
-
"""Add agent to execution plan."""
|
105
|
-
self.agents.append(agent)
|
106
|
-
if depends_on:
|
107
|
-
self.dependencies[agent.agent_name] = depends_on
|
108
|
-
|
109
|
-
def add_parallel_group(self, agent_names: List[str]) -> None:
|
110
|
-
"""Add group of agents that can run in parallel."""
|
111
|
-
self.parallel_groups.append(agent_names)
|
112
|
-
|
113
|
-
def validate(self) -> List[str]:
|
114
|
-
"""Validate execution plan."""
|
115
|
-
errors = []
|
116
|
-
agent_names = {agent.agent_name for agent in self.agents}
|
117
|
-
|
118
|
-
# Check dependencies reference existing agents
|
119
|
-
for agent_name, deps in self.dependencies.items():
|
120
|
-
if agent_name not in agent_names:
|
121
|
-
errors.append(f"Agent '{agent_name}' in dependencies not found in plan")
|
122
|
-
|
123
|
-
for dep in deps:
|
124
|
-
if dep not in agent_names:
|
125
|
-
errors.append(f"Dependency '{dep}' for '{agent_name}' not found in plan")
|
126
|
-
|
127
|
-
# Check parallel groups reference existing agents
|
128
|
-
for group in self.parallel_groups:
|
129
|
-
for agent_name in group:
|
130
|
-
if agent_name not in agent_names:
|
131
|
-
errors.append(f"Agent '{agent_name}' in parallel group not found in plan")
|
132
|
-
|
133
|
-
return errors
|
134
|
-
|
135
|
-
|
136
|
-
class AgentExecutor:
|
137
|
-
"""Executor for managing and running Django App Agent AI agents."""
|
138
|
-
|
139
|
-
def __init__(self, config: AgentConfig):
|
140
|
-
"""Initialize agent executor.
|
141
|
-
|
142
|
-
Args:
|
143
|
-
config: Agent configuration
|
144
|
-
"""
|
145
|
-
self.config = config
|
146
|
-
self.logger = get_logger("agent_executor")
|
147
|
-
self._active_executions: Dict[str, ExecutionResult] = {}
|
148
|
-
|
149
|
-
async def execute_single(
|
150
|
-
self,
|
151
|
-
agent: DjangoAgent[DepsT, OutputT],
|
152
|
-
prompt: str,
|
153
|
-
deps: DepsT,
|
154
|
-
execution_id: Optional[str] = None,
|
155
|
-
timeout_seconds: Optional[float] = None
|
156
|
-
) -> ExecutionResult[OutputT]:
|
157
|
-
"""Execute a single agent.
|
158
|
-
|
159
|
-
Args:
|
160
|
-
agent: Agent to execute
|
161
|
-
prompt: Input prompt
|
162
|
-
deps: Agent dependencies
|
163
|
-
execution_id: Optional execution ID
|
164
|
-
timeout_seconds: Optional timeout override
|
165
|
-
|
166
|
-
Returns:
|
167
|
-
Execution result
|
168
|
-
"""
|
169
|
-
import uuid
|
170
|
-
|
171
|
-
if execution_id is None:
|
172
|
-
execution_id = str(uuid.uuid4())
|
173
|
-
|
174
|
-
start_time = datetime.now(timezone.utc)
|
175
|
-
|
176
|
-
# Create execution result
|
177
|
-
result = ExecutionResult[OutputT](
|
178
|
-
execution_id=execution_id,
|
179
|
-
agent_name=agent.agent_name,
|
180
|
-
status=ExecutionStatus.PENDING,
|
181
|
-
start_time=start_time,
|
182
|
-
correlation_id=deps.correlation_id,
|
183
|
-
operation_name=deps.operation_name
|
184
|
-
)
|
185
|
-
|
186
|
-
# Track active execution
|
187
|
-
self._active_executions[execution_id] = result
|
188
|
-
|
189
|
-
try:
|
190
|
-
# Update status to running
|
191
|
-
result.status = ExecutionStatus.RUNNING
|
192
|
-
|
193
|
-
# Create execution context
|
194
|
-
context = AgentContext()
|
195
|
-
|
196
|
-
# Determine timeout
|
197
|
-
timeout = timeout_seconds or 300.0
|
198
|
-
|
199
|
-
self.logger.info(
|
200
|
-
f"Starting execution of agent {agent.agent_name}",
|
201
|
-
execution_id=execution_id,
|
202
|
-
agent_name=agent.agent_name,
|
203
|
-
timeout_seconds=timeout
|
204
|
-
)
|
205
|
-
|
206
|
-
# Execute agent with timeout
|
207
|
-
output = await asyncio.wait_for(
|
208
|
-
agent.run(prompt, deps, context),
|
209
|
-
timeout=timeout
|
210
|
-
)
|
211
|
-
|
212
|
-
# Update result with success
|
213
|
-
end_time = datetime.now(timezone.utc)
|
214
|
-
result.status = ExecutionStatus.COMPLETED
|
215
|
-
result.output = output
|
216
|
-
result.end_time = end_time
|
217
|
-
result.execution_time_seconds = (end_time - start_time).total_seconds()
|
218
|
-
result.token_usage = context.token_usage.copy()
|
219
|
-
result.api_calls_count = context.api_calls_count
|
220
|
-
|
221
|
-
self.logger.info(
|
222
|
-
f"Completed execution of agent {agent.agent_name}",
|
223
|
-
execution_id=execution_id,
|
224
|
-
execution_time_seconds=result.execution_time_seconds,
|
225
|
-
success=True
|
226
|
-
)
|
227
|
-
|
228
|
-
return result
|
229
|
-
|
230
|
-
except asyncio.TimeoutError:
|
231
|
-
error_msg = f"Agent {agent.agent_name} execution timed out after {timeout} seconds"
|
232
|
-
result.status = ExecutionStatus.FAILED
|
233
|
-
result.error = error_msg
|
234
|
-
result.end_time = datetime.now(timezone.utc)
|
235
|
-
result.execution_time_seconds = (result.end_time - start_time).total_seconds()
|
236
|
-
|
237
|
-
self.logger.error(
|
238
|
-
error_msg,
|
239
|
-
execution_id=execution_id,
|
240
|
-
agent_name=agent.agent_name,
|
241
|
-
timeout_seconds=timeout
|
242
|
-
)
|
243
|
-
|
244
|
-
return result
|
245
|
-
|
246
|
-
except Exception as e:
|
247
|
-
error_msg = f"Agent {agent.agent_name} execution failed: {e}"
|
248
|
-
result.status = ExecutionStatus.FAILED
|
249
|
-
result.error = error_msg
|
250
|
-
result.end_time = datetime.now(timezone.utc)
|
251
|
-
result.execution_time_seconds = (result.end_time - start_time).total_seconds()
|
252
|
-
|
253
|
-
self.logger.error(
|
254
|
-
error_msg,
|
255
|
-
execution_id=execution_id,
|
256
|
-
agent_name=agent.agent_name,
|
257
|
-
error=str(e),
|
258
|
-
error_type=type(e).__name__
|
259
|
-
)
|
260
|
-
|
261
|
-
return result
|
262
|
-
|
263
|
-
finally:
|
264
|
-
# Remove from active executions
|
265
|
-
self._active_executions.pop(execution_id, None)
|
266
|
-
|
267
|
-
async def execute_plan(
|
268
|
-
self,
|
269
|
-
plan: ExecutionPlan,
|
270
|
-
prompt: str,
|
271
|
-
deps: AgentDependencies,
|
272
|
-
execution_id: Optional[str] = None
|
273
|
-
) -> Dict[str, ExecutionResult]:
|
274
|
-
"""Execute multiple agents according to a plan.
|
275
|
-
|
276
|
-
Args:
|
277
|
-
plan: Execution plan
|
278
|
-
prompt: Input prompt for all agents
|
279
|
-
deps: Base dependencies (will be copied for each agent)
|
280
|
-
execution_id: Optional execution ID
|
281
|
-
|
282
|
-
Returns:
|
283
|
-
Dictionary mapping agent names to execution results
|
284
|
-
"""
|
285
|
-
import uuid
|
286
|
-
|
287
|
-
if execution_id is None:
|
288
|
-
execution_id = str(uuid.uuid4())
|
289
|
-
|
290
|
-
# Validate plan
|
291
|
-
validation_errors = plan.validate()
|
292
|
-
if validation_errors:
|
293
|
-
raise ValidationError(
|
294
|
-
f"Invalid execution plan: {'; '.join(validation_errors)}",
|
295
|
-
validation_type="execution_plan"
|
296
|
-
)
|
297
|
-
|
298
|
-
self.logger.info(
|
299
|
-
f"Starting execution plan '{plan.name}'",
|
300
|
-
execution_id=execution_id,
|
301
|
-
agents_count=len(plan.agents),
|
302
|
-
parallel_groups=len(plan.parallel_groups)
|
303
|
-
)
|
304
|
-
|
305
|
-
results: Dict[str, ExecutionResult] = {}
|
306
|
-
agent_map = {agent.agent_name: agent for agent in plan.agents}
|
307
|
-
|
308
|
-
try:
|
309
|
-
# Execute agents in dependency order
|
310
|
-
executed = set()
|
311
|
-
|
312
|
-
while len(executed) < len(plan.agents):
|
313
|
-
# Find agents ready to execute (dependencies satisfied)
|
314
|
-
ready_agents = []
|
315
|
-
|
316
|
-
for agent in plan.agents:
|
317
|
-
if agent.agent_name in executed:
|
318
|
-
continue
|
319
|
-
|
320
|
-
# Check if dependencies are satisfied
|
321
|
-
agent_deps = plan.dependencies.get(agent.agent_name, [])
|
322
|
-
if all(dep in executed for dep in agent_deps):
|
323
|
-
ready_agents.append(agent)
|
324
|
-
|
325
|
-
if not ready_agents:
|
326
|
-
# Check for circular dependencies
|
327
|
-
remaining = [a.agent_name for a in plan.agents if a.agent_name not in executed]
|
328
|
-
raise AgentExecutionError(
|
329
|
-
f"Circular dependency detected or no agents ready to execute. Remaining: {remaining}",
|
330
|
-
agent_name="executor",
|
331
|
-
agent_operation="execute_plan"
|
332
|
-
)
|
333
|
-
|
334
|
-
# Execute ready agents (potentially in parallel)
|
335
|
-
tasks = []
|
336
|
-
for agent in ready_agents:
|
337
|
-
# Create agent-specific dependencies
|
338
|
-
agent_deps = AgentDependencies(
|
339
|
-
config=deps.config,
|
340
|
-
logger=deps.logger,
|
341
|
-
project_context=deps.project_context,
|
342
|
-
infrastructure_context=deps.infrastructure_context,
|
343
|
-
correlation_id=f"{execution_id}_{agent.agent_name}",
|
344
|
-
operation_name=f"{deps.operation_name}_{agent.agent_name}",
|
345
|
-
project_root=deps.project_root,
|
346
|
-
output_directory=deps.output_directory,
|
347
|
-
execution_metadata=deps.execution_metadata.copy()
|
348
|
-
)
|
349
|
-
|
350
|
-
task = self.execute_single(
|
351
|
-
agent,
|
352
|
-
prompt,
|
353
|
-
agent_deps,
|
354
|
-
f"{execution_id}_{agent.agent_name}",
|
355
|
-
plan.timeout_seconds
|
356
|
-
)
|
357
|
-
tasks.append((agent.agent_name, task))
|
358
|
-
|
359
|
-
# Wait for all ready agents to complete
|
360
|
-
for agent_name, task in tasks:
|
361
|
-
result = await task
|
362
|
-
results[agent_name] = result
|
363
|
-
executed.add(agent_name)
|
364
|
-
|
365
|
-
if not result.is_successful:
|
366
|
-
self.logger.warning(
|
367
|
-
f"Agent {agent_name} failed in execution plan",
|
368
|
-
execution_id=execution_id,
|
369
|
-
error=result.error
|
370
|
-
)
|
371
|
-
|
372
|
-
self.logger.info(
|
373
|
-
f"Completed execution plan '{plan.name}'",
|
374
|
-
execution_id=execution_id,
|
375
|
-
successful_agents=sum(1 for r in results.values() if r.is_successful),
|
376
|
-
failed_agents=sum(1 for r in results.values() if r.is_failed)
|
377
|
-
)
|
378
|
-
|
379
|
-
return results
|
380
|
-
|
381
|
-
except Exception as e:
|
382
|
-
self.logger.error(
|
383
|
-
f"Execution plan '{plan.name}' failed",
|
384
|
-
execution_id=execution_id,
|
385
|
-
error=str(e),
|
386
|
-
error_type=type(e).__name__
|
387
|
-
)
|
388
|
-
raise
|
389
|
-
|
390
|
-
def get_active_executions(self) -> Dict[str, ExecutionResult]:
|
391
|
-
"""Get currently active executions."""
|
392
|
-
return self._active_executions.copy()
|
393
|
-
|
394
|
-
def cancel_execution(self, execution_id: str) -> bool:
|
395
|
-
"""Cancel an active execution.
|
396
|
-
|
397
|
-
Args:
|
398
|
-
execution_id: ID of execution to cancel
|
399
|
-
|
400
|
-
Returns:
|
401
|
-
True if execution was cancelled, False if not found
|
402
|
-
"""
|
403
|
-
if execution_id in self._active_executions:
|
404
|
-
result = self._active_executions[execution_id]
|
405
|
-
result.status = ExecutionStatus.CANCELLED
|
406
|
-
result.end_time = datetime.now(timezone.utc)
|
407
|
-
result.execution_time_seconds = (result.end_time - result.start_time).total_seconds()
|
408
|
-
|
409
|
-
self.logger.info(
|
410
|
-
f"Cancelled execution {execution_id}",
|
411
|
-
execution_id=execution_id,
|
412
|
-
agent_name=result.agent_name
|
413
|
-
)
|
414
|
-
|
415
|
-
return True
|
416
|
-
|
417
|
-
return False
|
418
|
-
|
419
|
-
def get_execution_summary(self) -> Dict[str, Any]:
|
420
|
-
"""Get summary of executor state."""
|
421
|
-
active = self.get_active_executions()
|
422
|
-
|
423
|
-
return {
|
424
|
-
"active_executions_count": len(active),
|
425
|
-
"active_agents": [r.agent_name for r in active.values()],
|
426
|
-
"executor_config": {
|
427
|
-
"debug_mode": self.config.debug_mode,
|
428
|
-
"log_level": self.config.log_level.value,
|
429
|
-
}
|
430
|
-
}
|
@@ -1,12 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Code Generation Agents for Django App Agent Module.
|
3
|
-
|
4
|
-
This module contains AI agents responsible for generating Django application code
|
5
|
-
using Pydantic AI framework.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from .app_generator import AppGeneratorAgent
|
9
|
-
|
10
|
-
__all__ = [
|
11
|
-
"AppGeneratorAgent",
|
12
|
-
]
|
@@ -1,15 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Django Application Generator Agent Package.
|
3
|
-
|
4
|
-
This package contains the decomposed components of the AI agent
|
5
|
-
responsible for generating Django applications with intelligent code generation.
|
6
|
-
"""
|
7
|
-
|
8
|
-
from .main import AppGeneratorAgent
|
9
|
-
from .models import FileGenerationRequest, GeneratedFileResponse
|
10
|
-
|
11
|
-
__all__ = [
|
12
|
-
'AppGeneratorAgent',
|
13
|
-
'FileGenerationRequest',
|
14
|
-
'GeneratedFileResponse'
|
15
|
-
]
|
@@ -1,147 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Configuration validation for the App Generator Agent.
|
3
|
-
|
4
|
-
This module handles API key validation and model configuration
|
5
|
-
using django-cfg integration.
|
6
|
-
"""
|
7
|
-
|
8
|
-
import os
|
9
|
-
from typing import Optional
|
10
|
-
|
11
|
-
from pydantic_ai.models.openai import OpenAIModel
|
12
|
-
|
13
|
-
from ....core.config import AgentConfig, AIProvider
|
14
|
-
from ....core.exceptions import ConfigurationError
|
15
|
-
|
16
|
-
|
17
|
-
class ConfigValidator:
|
18
|
-
"""Validates and configures API keys and AI models."""
|
19
|
-
|
20
|
-
def __init__(self):
|
21
|
-
"""Initialize the config validator."""
|
22
|
-
self.model: Optional[OpenAIModel] = None
|
23
|
-
|
24
|
-
def validate_and_configure(self, config) -> OpenAIModel:
|
25
|
-
"""
|
26
|
-
Validate API keys and configure AI model.
|
27
|
-
|
28
|
-
Args:
|
29
|
-
config: Configuration object (AgentConfig or other)
|
30
|
-
|
31
|
-
Returns:
|
32
|
-
Configured OpenAI model
|
33
|
-
|
34
|
-
Raises:
|
35
|
-
ConfigurationError: If no valid API keys found
|
36
|
-
"""
|
37
|
-
try:
|
38
|
-
# Get configuration from django-cfg
|
39
|
-
print(f"π Debug config type: {type(config)}")
|
40
|
-
print(f"π Debug config: {config}")
|
41
|
-
|
42
|
-
if isinstance(config, AgentConfig):
|
43
|
-
# Use provided AgentConfig
|
44
|
-
agent_config = config
|
45
|
-
print("β
Using provided AgentConfig")
|
46
|
-
else:
|
47
|
-
# Load from django-cfg
|
48
|
-
print("π Loading from django-cfg...")
|
49
|
-
agent_config = AgentConfig.from_django_cfg()
|
50
|
-
print(f"β
Loaded AgentConfig: {type(agent_config)}")
|
51
|
-
|
52
|
-
print(f"π AgentConfig attributes: {dir(agent_config)}")
|
53
|
-
|
54
|
-
# Get API keys from configuration
|
55
|
-
openai_key = self._get_api_key(agent_config, AIProvider.OPENAI)
|
56
|
-
openrouter_key = self._get_api_key(agent_config, AIProvider.OPENROUTER)
|
57
|
-
|
58
|
-
print(f"π API keys via get_api_key: OpenAI={bool(openai_key)}, OpenRouter={bool(openrouter_key)}")
|
59
|
-
|
60
|
-
# Fallback to direct access
|
61
|
-
if not openai_key and not openrouter_key:
|
62
|
-
openai_key, openrouter_key = self._get_keys_direct_access(agent_config)
|
63
|
-
|
64
|
-
# Debug: Print what we found
|
65
|
-
print(f"π Final API Keys from django-cfg:")
|
66
|
-
print(f" OpenAI: {'β
Found' if openai_key else 'β Missing'}")
|
67
|
-
print(f" OpenRouter: {'β
Found' if openrouter_key else 'β Missing'}")
|
68
|
-
|
69
|
-
if not openai_key and not openrouter_key:
|
70
|
-
raise ConfigurationError(
|
71
|
-
"β AI Agent Configuration Error: No API keys found in django-cfg!\n\n"
|
72
|
-
"π Required: Either OpenAI or OpenRouter API key must be configured.\n\n"
|
73
|
-
"π How to fix in django-cfg config:\n"
|
74
|
-
" api_keys:\n"
|
75
|
-
" openai: 'your-openai-key'\n"
|
76
|
-
" openrouter: 'your-openrouter-key'\n\n"
|
77
|
-
"π Without API keys, AI agents cannot generate intelligent code!\n"
|
78
|
-
" You'll only get basic template-based generation.",
|
79
|
-
config_key="api_keys"
|
80
|
-
)
|
81
|
-
|
82
|
-
# Configure and return the model
|
83
|
-
return self._configure_model(openai_key, openrouter_key)
|
84
|
-
|
85
|
-
except Exception as e:
|
86
|
-
print(f"β Error loading API keys from django-cfg: {e}")
|
87
|
-
raise ConfigurationError(
|
88
|
-
f"Failed to load API keys from django-cfg configuration: {e}\n\n"
|
89
|
-
"π§ Make sure django-cfg is properly configured with API keys.",
|
90
|
-
config_key="api_keys",
|
91
|
-
cause=e
|
92
|
-
)
|
93
|
-
|
94
|
-
def _get_api_key(self, agent_config: AgentConfig, provider: AIProvider) -> Optional[str]:
|
95
|
-
"""Get API key for specific provider."""
|
96
|
-
if hasattr(agent_config, 'get_api_key'):
|
97
|
-
return agent_config.get_api_key(provider)
|
98
|
-
return None
|
99
|
-
|
100
|
-
def _get_keys_direct_access(self, agent_config: AgentConfig) -> tuple[Optional[str], Optional[str]]:
|
101
|
-
"""Get API keys via direct access as fallback."""
|
102
|
-
openai_key = None
|
103
|
-
openrouter_key = None
|
104
|
-
|
105
|
-
print("π Trying direct access to api_keys...")
|
106
|
-
if hasattr(agent_config, 'api_keys') and agent_config.api_keys:
|
107
|
-
print(f"π api_keys type: {type(agent_config.api_keys)}")
|
108
|
-
print(f"π api_keys content: {agent_config.api_keys}")
|
109
|
-
|
110
|
-
if hasattr(agent_config.api_keys, 'get'):
|
111
|
-
openai_key = agent_config.api_keys.get('openai', '')
|
112
|
-
openrouter_key = agent_config.api_keys.get('openrouter', '')
|
113
|
-
else:
|
114
|
-
openai_key = getattr(agent_config.api_keys, 'openai', '')
|
115
|
-
openrouter_key = getattr(agent_config.api_keys, 'openrouter', '')
|
116
|
-
|
117
|
-
print(f"π Direct access results: OpenAI={bool(openai_key)}, OpenRouter={bool(openrouter_key)}")
|
118
|
-
|
119
|
-
return openai_key, openrouter_key
|
120
|
-
|
121
|
-
def _configure_model(self, openai_key: Optional[str], openrouter_key: Optional[str]) -> OpenAIModel:
|
122
|
-
"""Configure AI model with available API key."""
|
123
|
-
if openrouter_key:
|
124
|
-
print("π Using OpenRouter API via django-cfg")
|
125
|
-
print(f"π OpenRouter key length: {len(openrouter_key)}")
|
126
|
-
print(f"π OpenRouter key prefix: {openrouter_key[:20]}...")
|
127
|
-
|
128
|
-
# Set environment variables for OpenRouter
|
129
|
-
os.environ['OPENAI_API_KEY'] = openrouter_key
|
130
|
-
os.environ['OPENAI_BASE_URL'] = 'https://openrouter.ai/api/v1'
|
131
|
-
# OpenRouter ΡΡΠ΅Π±ΡΠ΅Ρ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ
|
132
|
-
os.environ['OPENAI_DEFAULT_HEADERS'] = '{"HTTP-Referer": "https://djangocfg.com", "X-Title": "Django CFG App Agent"}'
|
133
|
-
|
134
|
-
self.model = OpenAIModel('gpt-4o-mini')
|
135
|
-
|
136
|
-
elif openai_key:
|
137
|
-
print("π Using OpenAI API via django-cfg")
|
138
|
-
|
139
|
-
# Set environment variable for OpenAI
|
140
|
-
os.environ['OPENAI_API_KEY'] = openai_key
|
141
|
-
# Remove base URL for standard OpenAI
|
142
|
-
if 'OPENAI_BASE_URL' in os.environ:
|
143
|
-
del os.environ['OPENAI_BASE_URL']
|
144
|
-
|
145
|
-
self.model = OpenAIModel('gpt-4o-mini')
|
146
|
-
|
147
|
-
return self.model
|