django-cfg 1.3.5__py3-none-any.whl → 1.3.9__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/__init__.py +24 -8
- django_cfg/apps/accounts/admin/activity_admin.py +146 -0
- django_cfg/apps/accounts/admin/filters.py +98 -22
- django_cfg/apps/accounts/admin/group_admin.py +86 -0
- django_cfg/apps/accounts/admin/inlines.py +42 -13
- django_cfg/apps/accounts/admin/otp_admin.py +115 -0
- django_cfg/apps/accounts/admin/registration_admin.py +173 -0
- django_cfg/apps/accounts/admin/resources.py +123 -19
- django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
- django_cfg/apps/accounts/admin/user_admin.py +362 -0
- django_cfg/apps/agents/admin/__init__.py +17 -4
- django_cfg/apps/agents/admin/execution_admin.py +204 -183
- django_cfg/apps/agents/admin/registry_admin.py +230 -255
- django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
- django_cfg/apps/agents/core/__init__.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +221 -0
- django_cfg/apps/agents/core/exceptions.py +14 -0
- django_cfg/apps/agents/core/orchestrator.py +18 -3
- django_cfg/apps/knowbase/admin/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
- django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
- django_cfg/apps/knowbase/admin/document_admin.py +269 -262
- django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
- django_cfg/apps/knowbase/config/settings.py +21 -4
- django_cfg/apps/knowbase/views/chat_views.py +3 -0
- django_cfg/apps/leads/admin/__init__.py +3 -1
- django_cfg/apps/leads/admin/leads_admin.py +235 -35
- django_cfg/apps/maintenance/admin/__init__.py +2 -2
- django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
- django_cfg/apps/maintenance/admin/log_admin.py +143 -61
- django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
- django_cfg/apps/maintenance/admin/site_admin.py +213 -352
- django_cfg/apps/newsletter/admin/__init__.py +29 -2
- django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
- django_cfg/apps/payments/admin/__init__.py +18 -27
- django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
- django_cfg/apps/payments/admin/balance_admin.py +166 -632
- django_cfg/apps/payments/admin/currencies_admin.py +235 -607
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
- django_cfg/apps/payments/admin/filters.py +83 -3
- django_cfg/apps/payments/admin/networks_admin.py +258 -0
- django_cfg/apps/payments/admin/payments_admin.py +171 -461
- django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
- django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
- django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
- django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
- django_cfg/apps/payments/middleware/api_access.py +32 -6
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
- django_cfg/apps/payments/models/balance.py +12 -0
- django_cfg/apps/payments/models/currencies.py +106 -32
- django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +1 -1
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +95 -39
- django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
- django_cfg/apps/payments/services/providers/models/base.py +122 -0
- django_cfg/apps/payments/services/providers/models/providers.py +87 -0
- django_cfg/apps/payments/services/providers/models/universal.py +48 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
- django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
- django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +4 -32
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
- django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
- django_cfg/apps/payments/tasks/__init__.py +39 -0
- django_cfg/apps/payments/tasks/types.py +73 -0
- django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
- django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
- django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
- django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
- django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
- django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +5 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +4 -3
- django_cfg/apps/support/admin/__init__.py +10 -1
- django_cfg/apps/support/admin/support_admin.py +338 -141
- django_cfg/apps/tasks/admin/__init__.py +11 -0
- django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
- django_cfg/apps/urls.py +1 -2
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/management/commands/__init__.py +13 -1
- django_cfg/management/commands/app_agent_diagnose.py +470 -0
- django_cfg/management/commands/app_agent_generate.py +342 -0
- django_cfg/management/commands/app_agent_info.py +308 -0
- django_cfg/management/commands/migrate_all.py +9 -3
- django_cfg/management/commands/migrator.py +11 -6
- django_cfg/management/commands/rundramatiq.py +3 -2
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/modules/django_admin/__init__.py +64 -0
- django_cfg/modules/django_admin/decorators/__init__.py +13 -0
- django_cfg/modules/django_admin/decorators/actions.py +106 -0
- django_cfg/modules/django_admin/decorators/display.py +106 -0
- django_cfg/modules/django_admin/mixins/__init__.py +14 -0
- django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
- django_cfg/modules/django_admin/models/__init__.py +20 -0
- django_cfg/modules/django_admin/models/action_models.py +33 -0
- django_cfg/modules/django_admin/models/badge_models.py +20 -0
- django_cfg/modules/django_admin/models/base.py +26 -0
- django_cfg/modules/django_admin/models/display_models.py +31 -0
- django_cfg/modules/django_admin/utils/badges.py +159 -0
- django_cfg/modules/django_admin/utils/displays.py +247 -0
- django_cfg/modules/django_app_agent/__init__.py +87 -0
- django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
- django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
- django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
- django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
- django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
- django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
- django_cfg/modules/django_app_agent/core/__init__.py +33 -0
- django_cfg/modules/django_app_agent/core/config.py +300 -0
- django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
- django_cfg/modules/django_app_agent/models/__init__.py +71 -0
- django_cfg/modules/django_app_agent/models/base.py +283 -0
- django_cfg/modules/django_app_agent/models/context.py +496 -0
- django_cfg/modules/django_app_agent/models/enums.py +481 -0
- django_cfg/modules/django_app_agent/models/requests.py +500 -0
- django_cfg/modules/django_app_agent/models/responses.py +585 -0
- django_cfg/modules/django_app_agent/pytest.ini +6 -0
- django_cfg/modules/django_app_agent/services/__init__.py +42 -0
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
- django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
- django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
- django_cfg/modules/django_app_agent/services/base.py +437 -0
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
- django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
- django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
- django_cfg/modules/django_app_agent/services/report_service.py +332 -0
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
- django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
- django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
- django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
- django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
- django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
- django_cfg/modules/django_app_agent/ui/cli.py +419 -0
- django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
- django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
- django_cfg/modules/django_app_agent/utils/logging.py +360 -0
- django_cfg/modules/django_app_agent/utils/validation.py +417 -0
- django_cfg/modules/django_currency/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
- django_cfg/modules/django_currency/core/converter.py +12 -12
- django_cfg/modules/django_currency/database/__init__.py +2 -2
- django_cfg/modules/django_currency/database/database_loader.py +93 -42
- django_cfg/modules/django_llm/llm/client.py +10 -2
- django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
- django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
- django_cfg/modules/django_unfold/dashboard.py +14 -13
- django_cfg/modules/django_unfold/models/config.py +1 -1
- django_cfg/registry/core.py +3 -0
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/RECORD +224 -118
- django_cfg/apps/accounts/admin/activity.py +0 -96
- django_cfg/apps/accounts/admin/group.py +0 -17
- django_cfg/apps/accounts/admin/otp.py +0 -59
- django_cfg/apps/accounts/admin/registration_source.py +0 -97
- django_cfg/apps/accounts/admin/twilio_response.py +0 -227
- django_cfg/apps/accounts/admin/user.py +0 -300
- django_cfg/apps/agents/core/agent.py +0 -281
- django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
- django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
- django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
- django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
- django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
- django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
- django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
- django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
- django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/middleware/static_nocache.py +0 -55
- django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
- /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,221 @@
|
|
1
|
+
"""
|
2
|
+
Django Agent - Proper Pydantic AI integration for Django.
|
3
|
+
|
4
|
+
This module provides a Django-friendly wrapper around Pydantic AI agents
|
5
|
+
with optimal model selection for Python development tasks.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import time
|
9
|
+
from typing import TypeVar, Generic, Type, Any, Optional, Dict, Callable, Sequence
|
10
|
+
|
11
|
+
from pydantic_ai import Agent
|
12
|
+
from pydantic_ai.models import KnownModelName
|
13
|
+
from pydantic_ai.models.openai import OpenAIChatModel
|
14
|
+
from pydantic_ai.providers.openrouter import OpenRouterProvider
|
15
|
+
from pydantic_ai.providers.openai import OpenAIProvider
|
16
|
+
|
17
|
+
from django_cfg.modules.django_logger import get_logger
|
18
|
+
from django_cfg.modules.base import BaseCfgModule
|
19
|
+
from .exceptions import ExecutionError, ConfigurationError
|
20
|
+
|
21
|
+
# Type variables for generic typing
|
22
|
+
DepsT = TypeVar('DepsT')
|
23
|
+
OutputT = TypeVar('OutputT')
|
24
|
+
|
25
|
+
logger = get_logger("agents.core")
|
26
|
+
|
27
|
+
|
28
|
+
class DjangoAgent(Generic[DepsT, OutputT]):
|
29
|
+
"""
|
30
|
+
Django-integrated agent using Pydantic AI.
|
31
|
+
|
32
|
+
Features:
|
33
|
+
- Optimal model selection (Kimi Dev 72B for Python coding via OpenRouter)
|
34
|
+
- Automatic fallback to OpenAI models
|
35
|
+
- Metrics collection
|
36
|
+
- Error handling
|
37
|
+
- Tool management
|
38
|
+
"""
|
39
|
+
|
40
|
+
def __init__(
|
41
|
+
self,
|
42
|
+
name: str,
|
43
|
+
deps_type: Type[DepsT],
|
44
|
+
output_type: Type[OutputT],
|
45
|
+
instructions: str,
|
46
|
+
model: Optional[KnownModelName | str] = None,
|
47
|
+
tools: Optional[Sequence] = None,
|
48
|
+
system_prompt: Optional[str] = None,
|
49
|
+
**kwargs
|
50
|
+
):
|
51
|
+
"""Initialize Django Agent with Pydantic AI."""
|
52
|
+
self.name = name
|
53
|
+
self.deps_type = deps_type
|
54
|
+
self.output_type = output_type
|
55
|
+
self.instructions = instructions
|
56
|
+
|
57
|
+
# Select optimal model for Python development
|
58
|
+
if model:
|
59
|
+
selected_model = model
|
60
|
+
model_kwargs = {}
|
61
|
+
else:
|
62
|
+
selected_model, model_kwargs = self._get_optimal_model()
|
63
|
+
|
64
|
+
# Merge model_kwargs with user kwargs (user kwargs take priority)
|
65
|
+
final_kwargs = {**model_kwargs, **kwargs}
|
66
|
+
|
67
|
+
# Initialize Pydantic AI Agent directly
|
68
|
+
self.agent = Agent(
|
69
|
+
model=selected_model,
|
70
|
+
deps_type=deps_type,
|
71
|
+
output_type=output_type,
|
72
|
+
instructions=instructions,
|
73
|
+
system_prompt=system_prompt or "",
|
74
|
+
tools=tools or [],
|
75
|
+
**final_kwargs
|
76
|
+
)
|
77
|
+
|
78
|
+
# Metrics
|
79
|
+
self._execution_count = 0
|
80
|
+
self._total_execution_time = 0.0
|
81
|
+
self._error_count = 0
|
82
|
+
|
83
|
+
logger.info(f"Initialized DjangoAgent '{name}' with model '{selected_model}'")
|
84
|
+
|
85
|
+
def _get_optimal_model(self) -> tuple[str, dict]:
|
86
|
+
"""
|
87
|
+
Get optimal model for Python development tasks.
|
88
|
+
|
89
|
+
Returns:
|
90
|
+
tuple: (model_instance, model_kwargs) where model_instance is an initialized Pydantic AI model
|
91
|
+
|
92
|
+
Priority:
|
93
|
+
1. OpenRouter + GPT-4o-mini (supports tools, better rate limits) - DEFAULT
|
94
|
+
2. OpenAI GPT-4o-mini (fallback if OpenRouter unavailable)
|
95
|
+
3. Test model (for testing)
|
96
|
+
|
97
|
+
Note: We use GPT-4o-mini through OpenRouter instead of specialized models like Kimi Dev 72B
|
98
|
+
because our agents require tool support, which many specialized models don't provide.
|
99
|
+
"""
|
100
|
+
try:
|
101
|
+
# Initialize django-cfg configuration
|
102
|
+
cfg = BaseCfgModule()
|
103
|
+
django_config = cfg.get_config()
|
104
|
+
|
105
|
+
if django_config and hasattr(django_config, 'api_keys') and django_config.api_keys:
|
106
|
+
api_keys = django_config.api_keys
|
107
|
+
|
108
|
+
# Priority 1: OpenRouter + GPT-4o-mini (supports tools) - DEFAULT
|
109
|
+
if api_keys.has_openrouter():
|
110
|
+
openrouter_key = api_keys.get_openrouter_key()
|
111
|
+
logger.info("🚀 Using OpenAI GPT-4o-mini via OpenRouter - reliable tool support (DEFAULT)")
|
112
|
+
logger.debug(f"🔑 OpenRouter API key: {openrouter_key[:10]}...{openrouter_key[-4:] if openrouter_key else 'None'}")
|
113
|
+
|
114
|
+
provider = OpenRouterProvider(api_key=openrouter_key)
|
115
|
+
# Use GPT-4o-mini through OpenRouter (supports tools)
|
116
|
+
model = OpenAIChatModel('openai/gpt-4o-mini', provider=provider)
|
117
|
+
return model, {}
|
118
|
+
|
119
|
+
# Priority 2: OpenAI GPT-4o-mini (fallback if OpenRouter unavailable)
|
120
|
+
if api_keys.has_openai():
|
121
|
+
openai_key = api_keys.get_openai_key()
|
122
|
+
logger.info("⚠️ Using OpenAI GPT-4o-mini - reliable tool support (FALLBACK - OpenRouter unavailable)")
|
123
|
+
logger.debug(f"🔑 OpenAI API key: {openai_key[:10]}...{openai_key[-4:] if openai_key else 'None'}")
|
124
|
+
|
125
|
+
provider = OpenAIProvider(api_key=openai_key)
|
126
|
+
model = OpenAIChatModel('gpt-4o-mini', provider=provider)
|
127
|
+
return model, {}
|
128
|
+
|
129
|
+
# Test model for development
|
130
|
+
logger.warning("⚠️ No API keys found in django-cfg config, using test model")
|
131
|
+
return 'test', {}
|
132
|
+
|
133
|
+
except Exception as e:
|
134
|
+
logger.error(f"❌ Failed to load django-cfg config: {e}")
|
135
|
+
logger.warning("⚠️ Using test model due to config error")
|
136
|
+
return 'test', {}
|
137
|
+
|
138
|
+
async def run(self, prompt: str, deps: DepsT, **kwargs) -> OutputT:
|
139
|
+
"""Run the agent with given prompt and dependencies."""
|
140
|
+
start_time = time.time()
|
141
|
+
|
142
|
+
try:
|
143
|
+
self._execution_count += 1
|
144
|
+
|
145
|
+
# Run Pydantic AI agent
|
146
|
+
result = await self.agent.run(prompt, deps=deps, **kwargs)
|
147
|
+
|
148
|
+
execution_time = time.time() - start_time
|
149
|
+
self._total_execution_time += execution_time
|
150
|
+
|
151
|
+
logger.debug(f"✅ Agent '{self.name}' executed in {execution_time:.2f}s")
|
152
|
+
|
153
|
+
# Return the result data (Pydantic AI returns RunResult with .data attribute)
|
154
|
+
return result.data if hasattr(result, 'data') else result
|
155
|
+
|
156
|
+
except Exception as e:
|
157
|
+
self._error_count += 1
|
158
|
+
execution_time = time.time() - start_time
|
159
|
+
self._total_execution_time += execution_time
|
160
|
+
|
161
|
+
logger.error(f"❌ Agent '{self.name}' failed after {execution_time:.2f}s: {e}")
|
162
|
+
raise ExecutionError(f"Agent execution failed: {e}") from e
|
163
|
+
|
164
|
+
def run_sync(self, prompt: str, deps: DepsT, **kwargs) -> OutputT:
|
165
|
+
"""Run the agent synchronously."""
|
166
|
+
start_time = time.time()
|
167
|
+
|
168
|
+
try:
|
169
|
+
self._execution_count += 1
|
170
|
+
|
171
|
+
# Run Pydantic AI agent synchronously
|
172
|
+
result = self.agent.run_sync(prompt, deps=deps, **kwargs)
|
173
|
+
|
174
|
+
execution_time = time.time() - start_time
|
175
|
+
self._total_execution_time += execution_time
|
176
|
+
|
177
|
+
logger.debug(f"✅ Agent '{self.name}' executed sync in {execution_time:.2f}s")
|
178
|
+
|
179
|
+
# Return the result data (Pydantic AI returns RunResult with .data attribute)
|
180
|
+
return result.data if hasattr(result, 'data') else result
|
181
|
+
|
182
|
+
except Exception as e:
|
183
|
+
self._error_count += 1
|
184
|
+
execution_time = time.time() - start_time
|
185
|
+
self._total_execution_time += execution_time
|
186
|
+
|
187
|
+
logger.error(f"❌ Agent '{self.name}' failed sync after {execution_time:.2f}s: {e}")
|
188
|
+
raise ExecutionError(f"Agent execution failed: {e}") from e
|
189
|
+
|
190
|
+
def tool(self, func: Callable = None, *, name: str = None):
|
191
|
+
"""Decorator to add tools to the agent."""
|
192
|
+
return self.agent.tool(func, name=name)
|
193
|
+
|
194
|
+
def get_metrics(self) -> Dict[str, Any]:
|
195
|
+
"""Get agent execution metrics."""
|
196
|
+
avg_time = self._total_execution_time / max(self._execution_count, 1)
|
197
|
+
success_rate = (self._execution_count - self._error_count) / max(self._execution_count, 1)
|
198
|
+
|
199
|
+
return {
|
200
|
+
"name": self.name,
|
201
|
+
"model": str(self.agent.model),
|
202
|
+
"execution_count": self._execution_count,
|
203
|
+
"total_execution_time": self._total_execution_time,
|
204
|
+
"average_execution_time": avg_time,
|
205
|
+
"error_count": self._error_count,
|
206
|
+
"success_rate": success_rate
|
207
|
+
}
|
208
|
+
|
209
|
+
def reset_metrics(self):
|
210
|
+
"""Reset agent metrics."""
|
211
|
+
self._execution_count = 0
|
212
|
+
self._total_execution_time = 0.0
|
213
|
+
self._error_count = 0
|
214
|
+
|
215
|
+
def __repr__(self) -> str:
|
216
|
+
"""String representation of the agent."""
|
217
|
+
return f"DjangoAgent(name='{self.name}', model='{self.agent.model}', deps_type={self.deps_type.__name__}, output_type={self.output_type.__name__})"
|
218
|
+
|
219
|
+
|
220
|
+
# Export the main class
|
221
|
+
__all__ = ['DjangoAgent']
|
@@ -64,3 +64,17 @@ class TimeoutError(AgentError):
|
|
64
64
|
def __init__(self, message: str, timeout_seconds: Optional[float] = None):
|
65
65
|
super().__init__(message)
|
66
66
|
self.timeout_seconds = timeout_seconds
|
67
|
+
|
68
|
+
|
69
|
+
class OrchestratorError(AgentError):
|
70
|
+
"""Raised when orchestrator execution fails."""
|
71
|
+
|
72
|
+
def __init__(
|
73
|
+
self,
|
74
|
+
message: str,
|
75
|
+
orchestrator_name: Optional[str] = None,
|
76
|
+
original_error: Optional[Exception] = None
|
77
|
+
):
|
78
|
+
super().__init__(message)
|
79
|
+
self.orchestrator_name = orchestrator_name
|
80
|
+
self.original_error = original_error
|
@@ -8,7 +8,7 @@ import logging
|
|
8
8
|
from typing import Dict, List, Any, Optional, Callable
|
9
9
|
from dataclasses import dataclass
|
10
10
|
|
11
|
-
from .
|
11
|
+
from .django_agent import DjangoAgent
|
12
12
|
from .models import ExecutionResult, WorkflowConfig
|
13
13
|
from .exceptions import AgentNotFoundError, ExecutionError, ConfigurationError
|
14
14
|
|
@@ -100,14 +100,29 @@ class ParallelPattern(ExecutionPattern):
|
|
100
100
|
|
101
101
|
async def run_agent_with_semaphore(agent: DjangoAgent) -> ExecutionResult:
|
102
102
|
async with semaphore:
|
103
|
+
start_time = time.time()
|
103
104
|
try:
|
104
|
-
|
105
|
+
# Get agent-specific dependencies if deps is a dict
|
106
|
+
agent_deps = deps
|
107
|
+
if isinstance(deps, dict):
|
108
|
+
agent_deps = deps.get(agent.name, deps)
|
109
|
+
|
110
|
+
result = await agent.run(prompt, agent_deps)
|
111
|
+
execution_time = time.time() - start_time
|
112
|
+
|
113
|
+
return ExecutionResult(
|
114
|
+
agent_name=agent.name,
|
115
|
+
output=result,
|
116
|
+
execution_time=execution_time,
|
117
|
+
error=None
|
118
|
+
)
|
105
119
|
except Exception as e:
|
120
|
+
execution_time = time.time() - start_time
|
106
121
|
logger.error(f"Parallel execution failed for agent '{agent.name}': {e}")
|
107
122
|
return ExecutionResult(
|
108
123
|
agent_name=agent.name,
|
109
124
|
output=None,
|
110
|
-
execution_time=
|
125
|
+
execution_time=execution_time,
|
111
126
|
error=str(e)
|
112
127
|
)
|
113
128
|
|