django-cfg 1.3.7__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/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.7.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/RECORD +223 -117
- 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.7.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,300 @@
|
|
1
|
+
"""
|
2
|
+
Configuration management for Django App Agent Module.
|
3
|
+
|
4
|
+
This module provides type-safe configuration management with:
|
5
|
+
- Integration with django-cfg BaseCfgModule
|
6
|
+
- Pydantic 2 models for all configuration
|
7
|
+
- Environment variable support
|
8
|
+
- Validation and default values
|
9
|
+
- AI model configuration
|
10
|
+
"""
|
11
|
+
|
12
|
+
from typing import Optional, Dict, Any, List, Literal
|
13
|
+
from pathlib import Path
|
14
|
+
from pydantic import BaseModel, Field, ConfigDict, field_validator
|
15
|
+
from enum import Enum
|
16
|
+
|
17
|
+
from django_cfg.modules.base import BaseCfgModule
|
18
|
+
from .exceptions import ConfigurationError
|
19
|
+
|
20
|
+
|
21
|
+
class LogLevel(str, Enum):
|
22
|
+
"""Logging levels."""
|
23
|
+
DEBUG = "DEBUG"
|
24
|
+
INFO = "INFO"
|
25
|
+
WARNING = "WARNING"
|
26
|
+
ERROR = "ERROR"
|
27
|
+
CRITICAL = "CRITICAL"
|
28
|
+
|
29
|
+
|
30
|
+
class AIProvider(str, Enum):
|
31
|
+
"""AI service providers."""
|
32
|
+
OPENAI = "openai"
|
33
|
+
ANTHROPIC = "anthropic"
|
34
|
+
OPENROUTER = "openrouter"
|
35
|
+
|
36
|
+
|
37
|
+
class ModelTier(str, Enum):
|
38
|
+
"""AI model performance tiers."""
|
39
|
+
FAST = "fast" # Fast, cheaper models for simple tasks
|
40
|
+
BALANCED = "balanced" # Balanced performance and cost
|
41
|
+
PREMIUM = "premium" # Best quality, higher cost
|
42
|
+
|
43
|
+
|
44
|
+
class ModelConfig(BaseModel):
|
45
|
+
"""Configuration for AI models."""
|
46
|
+
|
47
|
+
model_config = ConfigDict(
|
48
|
+
extra='forbid',
|
49
|
+
validate_assignment=True,
|
50
|
+
str_strip_whitespace=True
|
51
|
+
)
|
52
|
+
|
53
|
+
provider: AIProvider = Field(description="AI service provider")
|
54
|
+
model_id: str = Field(description="Model identifier")
|
55
|
+
tier: ModelTier = Field(description="Model performance tier")
|
56
|
+
max_tokens: int = Field(gt=0, le=200000, description="Maximum tokens per request")
|
57
|
+
temperature: float = Field(ge=0.0, le=2.0, default=0.1, description="Model temperature")
|
58
|
+
timeout_seconds: float = Field(gt=0, default=300.0, description="Request timeout")
|
59
|
+
|
60
|
+
@field_validator('model_id')
|
61
|
+
@classmethod
|
62
|
+
def validate_model_id(cls, v: str) -> str:
|
63
|
+
"""Validate model ID format."""
|
64
|
+
if not v or len(v.strip()) == 0:
|
65
|
+
raise ValueError("Model ID cannot be empty")
|
66
|
+
return v.strip()
|
67
|
+
|
68
|
+
|
69
|
+
class APIKeyConfig(BaseModel):
|
70
|
+
"""API key configuration."""
|
71
|
+
|
72
|
+
model_config = ConfigDict(
|
73
|
+
extra='forbid',
|
74
|
+
validate_assignment=True,
|
75
|
+
str_strip_whitespace=True
|
76
|
+
)
|
77
|
+
|
78
|
+
openai: Optional[str] = Field(default=None, description="OpenAI API key")
|
79
|
+
anthropic: Optional[str] = Field(default=None, description="Anthropic API key")
|
80
|
+
openrouter: Optional[str] = Field(default=None, description="OpenRouter API key")
|
81
|
+
|
82
|
+
def get_key(self, provider: AIProvider) -> Optional[str]:
|
83
|
+
"""Get API key for provider."""
|
84
|
+
return getattr(self, provider.value, None)
|
85
|
+
|
86
|
+
def has_key(self, provider: AIProvider) -> bool:
|
87
|
+
"""Check if API key exists for provider."""
|
88
|
+
key = self.get_key(provider)
|
89
|
+
return key is not None and len(key.strip()) > 0
|
90
|
+
|
91
|
+
|
92
|
+
class UIConfig(BaseModel):
|
93
|
+
"""User interface configuration."""
|
94
|
+
|
95
|
+
model_config = ConfigDict(
|
96
|
+
extra='forbid',
|
97
|
+
validate_assignment=True
|
98
|
+
)
|
99
|
+
|
100
|
+
enable_rich_interface: bool = Field(default=True, description="Enable Rich CLI interface")
|
101
|
+
show_progress_bars: bool = Field(default=True, description="Show progress bars")
|
102
|
+
enable_colors: bool = Field(default=True, description="Enable colored output")
|
103
|
+
verbose_output: bool = Field(default=False, description="Enable verbose output")
|
104
|
+
max_console_width: int = Field(gt=40, le=200, default=120, description="Maximum console width")
|
105
|
+
|
106
|
+
|
107
|
+
class GenerationConfig(BaseModel):
|
108
|
+
"""Code generation configuration."""
|
109
|
+
|
110
|
+
model_config = ConfigDict(
|
111
|
+
extra='forbid',
|
112
|
+
validate_assignment=True
|
113
|
+
)
|
114
|
+
|
115
|
+
max_questions: int = Field(gt=0, le=50, default=20, description="Maximum questions to ask")
|
116
|
+
questioning_timeout_minutes: int = Field(gt=0, le=60, default=15, description="Questioning timeout")
|
117
|
+
quality_threshold: float = Field(ge=0.0, le=10.0, default=8.0, description="Minimum quality score")
|
118
|
+
enable_caching: bool = Field(default=True, description="Enable response caching")
|
119
|
+
cache_ttl_seconds: int = Field(gt=0, default=3600, description="Cache TTL in seconds")
|
120
|
+
max_concurrent_generations: int = Field(gt=0, le=10, default=3, description="Max concurrent generations")
|
121
|
+
|
122
|
+
@field_validator('quality_threshold')
|
123
|
+
@classmethod
|
124
|
+
def validate_quality_threshold(cls, v: float) -> float:
|
125
|
+
"""Validate quality threshold is reasonable."""
|
126
|
+
if v < 5.0:
|
127
|
+
raise ValueError("Quality threshold should be at least 5.0 for production use")
|
128
|
+
return v
|
129
|
+
|
130
|
+
|
131
|
+
class AgentConfig(BaseModel):
|
132
|
+
"""Django App Agent Module configuration."""
|
133
|
+
|
134
|
+
model_config = ConfigDict(
|
135
|
+
extra='forbid',
|
136
|
+
validate_assignment=True,
|
137
|
+
str_strip_whitespace=True
|
138
|
+
)
|
139
|
+
|
140
|
+
# Core settings
|
141
|
+
module_name: str = Field(default="django_app_agent", description="Module name")
|
142
|
+
version: str = Field(default="0.1.0", description="Module version")
|
143
|
+
debug_mode: bool = Field(default=False, description="Enable debug mode")
|
144
|
+
log_level: LogLevel = Field(default=LogLevel.INFO, description="Logging level")
|
145
|
+
|
146
|
+
# API configuration
|
147
|
+
api_keys: APIKeyConfig = Field(default_factory=APIKeyConfig, description="API keys")
|
148
|
+
preferred_models: Dict[str, ModelConfig] = Field(
|
149
|
+
default_factory=dict,
|
150
|
+
description="Preferred models for different tasks"
|
151
|
+
)
|
152
|
+
|
153
|
+
# UI configuration
|
154
|
+
ui: UIConfig = Field(default_factory=UIConfig, description="UI settings")
|
155
|
+
|
156
|
+
# Generation configuration
|
157
|
+
generation: GenerationConfig = Field(default_factory=GenerationConfig, description="Generation settings")
|
158
|
+
|
159
|
+
# File paths
|
160
|
+
output_directory: Optional[Path] = Field(default=None, description="Default output directory")
|
161
|
+
template_directory: Optional[Path] = Field(default=None, description="Template directory")
|
162
|
+
cache_directory: Optional[Path] = Field(default=None, description="Cache directory")
|
163
|
+
|
164
|
+
@classmethod
|
165
|
+
def from_django_cfg(cls) -> "AgentConfig":
|
166
|
+
"""Load configuration from django-cfg."""
|
167
|
+
try:
|
168
|
+
cfg_module = BaseCfgModule()
|
169
|
+
django_cfg_config = cfg_module.get_config()
|
170
|
+
|
171
|
+
# Extract relevant configuration
|
172
|
+
config_data: Dict[str, Any] = {}
|
173
|
+
|
174
|
+
# API keys - extract string values from SecretStr
|
175
|
+
if hasattr(django_cfg_config, 'api_keys'):
|
176
|
+
api_keys_data = {}
|
177
|
+
if hasattr(django_cfg_config.api_keys, 'openai') and django_cfg_config.api_keys.openai:
|
178
|
+
# Extract string value from SecretStr if needed
|
179
|
+
openai_key = django_cfg_config.api_keys.openai
|
180
|
+
api_keys_data['openai'] = str(openai_key) if hasattr(openai_key, 'get_secret_value') else openai_key
|
181
|
+
if hasattr(django_cfg_config.api_keys, 'anthropic') and django_cfg_config.api_keys.anthropic:
|
182
|
+
# Extract string value from SecretStr if needed
|
183
|
+
anthropic_key = django_cfg_config.api_keys.anthropic
|
184
|
+
api_keys_data['anthropic'] = str(anthropic_key) if hasattr(anthropic_key, 'get_secret_value') else anthropic_key
|
185
|
+
if hasattr(django_cfg_config.api_keys, 'openrouter') and django_cfg_config.api_keys.openrouter:
|
186
|
+
# Extract string value from SecretStr if needed
|
187
|
+
openrouter_key = django_cfg_config.api_keys.openrouter
|
188
|
+
api_keys_data['openrouter'] = str(openrouter_key) if hasattr(openrouter_key, 'get_secret_value') else openrouter_key
|
189
|
+
|
190
|
+
config_data['api_keys'] = api_keys_data
|
191
|
+
|
192
|
+
# Agent-specific settings
|
193
|
+
if hasattr(django_cfg_config, 'agents') and django_cfg_config.agents:
|
194
|
+
agent_config = django_cfg_config.agents
|
195
|
+
|
196
|
+
if hasattr(agent_config, 'debug_mode'):
|
197
|
+
config_data['debug_mode'] = agent_config.debug_mode
|
198
|
+
|
199
|
+
if hasattr(agent_config, 'max_questions'):
|
200
|
+
config_data['generation'] = config_data.get('generation', {})
|
201
|
+
config_data['generation']['max_questions'] = agent_config.max_questions
|
202
|
+
|
203
|
+
if hasattr(agent_config, 'quality_threshold'):
|
204
|
+
config_data['generation'] = config_data.get('generation', {})
|
205
|
+
config_data['generation']['quality_threshold'] = agent_config.quality_threshold
|
206
|
+
|
207
|
+
return cls(**config_data)
|
208
|
+
|
209
|
+
except Exception as e:
|
210
|
+
raise ConfigurationError(
|
211
|
+
f"Failed to load configuration from django-cfg: {e}",
|
212
|
+
cause=e
|
213
|
+
)
|
214
|
+
|
215
|
+
def get_api_key(self, provider: AIProvider) -> Optional[str]:
|
216
|
+
"""Get API key for provider."""
|
217
|
+
return self.api_keys.get_key(provider)
|
218
|
+
|
219
|
+
def has_api_key(self, provider: AIProvider) -> bool:
|
220
|
+
"""Check if API key exists for provider."""
|
221
|
+
return self.api_keys.has_key(provider)
|
222
|
+
|
223
|
+
def get_model_config(self, task_type: str) -> Optional[ModelConfig]:
|
224
|
+
"""Get model configuration for task type."""
|
225
|
+
return self.preferred_models.get(task_type)
|
226
|
+
|
227
|
+
def validate_configuration(self) -> List[str]:
|
228
|
+
"""Validate configuration and return list of issues."""
|
229
|
+
issues: List[str] = []
|
230
|
+
|
231
|
+
# Check API keys
|
232
|
+
if not any(self.api_keys.has_key(provider) for provider in AIProvider):
|
233
|
+
issues.append("No API keys configured for any AI provider")
|
234
|
+
|
235
|
+
# Check directories
|
236
|
+
if self.output_directory and not self.output_directory.exists():
|
237
|
+
issues.append(f"Output directory does not exist: {self.output_directory}")
|
238
|
+
|
239
|
+
if self.template_directory and not self.template_directory.exists():
|
240
|
+
issues.append(f"Template directory does not exist: {self.template_directory}")
|
241
|
+
|
242
|
+
# Check model configurations
|
243
|
+
for task_type, model_config in self.preferred_models.items():
|
244
|
+
if not self.has_api_key(model_config.provider):
|
245
|
+
issues.append(f"No API key for {model_config.provider} (required for {task_type})")
|
246
|
+
|
247
|
+
return issues
|
248
|
+
|
249
|
+
|
250
|
+
# Default model configurations
|
251
|
+
DEFAULT_MODELS: Dict[str, ModelConfig] = {
|
252
|
+
"generation": ModelConfig(
|
253
|
+
provider=AIProvider.OPENROUTER,
|
254
|
+
model_id="anthropic/claude-3-haiku",
|
255
|
+
tier=ModelTier.BALANCED,
|
256
|
+
max_tokens=100000,
|
257
|
+
temperature=0.1,
|
258
|
+
timeout_seconds=300.0
|
259
|
+
),
|
260
|
+
"analysis": ModelConfig(
|
261
|
+
provider=AIProvider.OPENROUTER,
|
262
|
+
model_id="openai/gpt-4o-mini",
|
263
|
+
tier=ModelTier.FAST,
|
264
|
+
max_tokens=50000,
|
265
|
+
temperature=0.0,
|
266
|
+
timeout_seconds=180.0
|
267
|
+
),
|
268
|
+
"validation": ModelConfig(
|
269
|
+
provider=AIProvider.OPENROUTER,
|
270
|
+
model_id="anthropic/claude-3-haiku",
|
271
|
+
tier=ModelTier.FAST,
|
272
|
+
max_tokens=30000,
|
273
|
+
temperature=0.0,
|
274
|
+
timeout_seconds=120.0
|
275
|
+
),
|
276
|
+
"dialogue": ModelConfig(
|
277
|
+
provider=AIProvider.OPENROUTER,
|
278
|
+
model_id="openai/gpt-4o-mini",
|
279
|
+
tier=ModelTier.FAST,
|
280
|
+
max_tokens=20000,
|
281
|
+
temperature=0.2,
|
282
|
+
timeout_seconds=60.0
|
283
|
+
)
|
284
|
+
}
|
285
|
+
|
286
|
+
|
287
|
+
def get_default_config() -> AgentConfig:
|
288
|
+
"""Get default configuration with sensible defaults."""
|
289
|
+
return AgentConfig(
|
290
|
+
preferred_models=DEFAULT_MODELS.copy()
|
291
|
+
)
|
292
|
+
|
293
|
+
|
294
|
+
def load_config() -> AgentConfig:
|
295
|
+
"""Load configuration from django-cfg or use defaults."""
|
296
|
+
try:
|
297
|
+
return AgentConfig.from_django_cfg()
|
298
|
+
except ConfigurationError:
|
299
|
+
# Fall back to default configuration
|
300
|
+
return get_default_config()
|
@@ -0,0 +1,359 @@
|
|
1
|
+
"""
|
2
|
+
Exception hierarchy for Django App Agent Module.
|
3
|
+
|
4
|
+
This module defines a comprehensive exception hierarchy following best practices:
|
5
|
+
- Clear inheritance structure
|
6
|
+
- Contextual error information
|
7
|
+
- Structured error data with Pydantic models
|
8
|
+
- Support for error recovery and retry logic
|
9
|
+
"""
|
10
|
+
|
11
|
+
from typing import Optional, Dict, Any, List
|
12
|
+
from pathlib import Path
|
13
|
+
from pydantic import BaseModel, Field, ConfigDict
|
14
|
+
|
15
|
+
|
16
|
+
class ErrorContext(BaseModel):
|
17
|
+
"""Context information for errors."""
|
18
|
+
|
19
|
+
model_config = ConfigDict(
|
20
|
+
extra='forbid',
|
21
|
+
validate_assignment=True,
|
22
|
+
str_strip_whitespace=True
|
23
|
+
)
|
24
|
+
|
25
|
+
operation: str = Field(description="Operation that caused the error")
|
26
|
+
component: str = Field(description="Component where error occurred")
|
27
|
+
timestamp: str = Field(description="Error timestamp")
|
28
|
+
correlation_id: Optional[str] = Field(default=None, description="Correlation ID for tracing")
|
29
|
+
additional_data: Dict[str, Any] = Field(default_factory=dict, description="Additional error context")
|
30
|
+
|
31
|
+
|
32
|
+
class DjangoAppAgentError(Exception):
|
33
|
+
"""Base exception for all Django App Agent Module errors."""
|
34
|
+
|
35
|
+
def __init__(
|
36
|
+
self,
|
37
|
+
message: str,
|
38
|
+
*,
|
39
|
+
error_code: Optional[str] = None,
|
40
|
+
context: Optional[ErrorContext] = None,
|
41
|
+
cause: Optional[Exception] = None,
|
42
|
+
recoverable: bool = False
|
43
|
+
) -> None:
|
44
|
+
"""Initialize Django App Agent error.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
message: Human-readable error message
|
48
|
+
error_code: Machine-readable error code
|
49
|
+
context: Error context information
|
50
|
+
cause: Original exception that caused this error
|
51
|
+
recoverable: Whether this error can be recovered from
|
52
|
+
"""
|
53
|
+
super().__init__(message)
|
54
|
+
self.message = message
|
55
|
+
self.error_code = error_code or self.__class__.__name__
|
56
|
+
self.context = context
|
57
|
+
self.cause = cause
|
58
|
+
self.recoverable = recoverable
|
59
|
+
|
60
|
+
def __str__(self) -> str:
|
61
|
+
"""String representation of the error."""
|
62
|
+
parts = [self.message]
|
63
|
+
|
64
|
+
if self.error_code:
|
65
|
+
parts.append(f"[{self.error_code}]")
|
66
|
+
|
67
|
+
if self.context:
|
68
|
+
parts.append(f"Operation: {self.context.operation}")
|
69
|
+
parts.append(f"Component: {self.context.component}")
|
70
|
+
|
71
|
+
return " | ".join(parts)
|
72
|
+
|
73
|
+
def to_dict(self) -> Dict[str, Any]:
|
74
|
+
"""Convert error to dictionary representation."""
|
75
|
+
return {
|
76
|
+
"error_type": self.__class__.__name__,
|
77
|
+
"message": self.message,
|
78
|
+
"error_code": self.error_code,
|
79
|
+
"context": self.context.model_dump() if self.context else None,
|
80
|
+
"recoverable": self.recoverable,
|
81
|
+
"cause": str(self.cause) if self.cause else None,
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
class ConfigurationError(DjangoAppAgentError):
|
86
|
+
"""Error in module configuration or setup."""
|
87
|
+
|
88
|
+
def __init__(
|
89
|
+
self,
|
90
|
+
message: str,
|
91
|
+
*,
|
92
|
+
config_key: Optional[str] = None,
|
93
|
+
config_file: Optional[Path] = None,
|
94
|
+
**kwargs
|
95
|
+
) -> None:
|
96
|
+
"""Initialize configuration error.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
message: Error message
|
100
|
+
config_key: Configuration key that caused the error
|
101
|
+
config_file: Configuration file path
|
102
|
+
**kwargs: Additional arguments for base class
|
103
|
+
"""
|
104
|
+
super().__init__(message, **kwargs)
|
105
|
+
self.config_key = config_key
|
106
|
+
self.config_file = config_file
|
107
|
+
|
108
|
+
|
109
|
+
class GenerationError(DjangoAppAgentError):
|
110
|
+
"""Error during application generation process."""
|
111
|
+
|
112
|
+
def __init__(
|
113
|
+
self,
|
114
|
+
message: str,
|
115
|
+
*,
|
116
|
+
app_name: Optional[str] = None,
|
117
|
+
generation_stage: Optional[str] = None,
|
118
|
+
partial_results: Optional[List[str]] = None,
|
119
|
+
**kwargs
|
120
|
+
) -> None:
|
121
|
+
"""Initialize generation error.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
message: Error message
|
125
|
+
app_name: Name of app being generated
|
126
|
+
generation_stage: Stage where error occurred
|
127
|
+
partial_results: Partial results before error
|
128
|
+
**kwargs: Additional arguments for base class
|
129
|
+
"""
|
130
|
+
super().__init__(message, recoverable=True, **kwargs)
|
131
|
+
self.app_name = app_name
|
132
|
+
self.generation_stage = generation_stage
|
133
|
+
self.partial_results = partial_results or []
|
134
|
+
|
135
|
+
|
136
|
+
class ValidationError(DjangoAppAgentError):
|
137
|
+
"""Error during validation of generated code or user input."""
|
138
|
+
|
139
|
+
def __init__(
|
140
|
+
self,
|
141
|
+
message: str,
|
142
|
+
*,
|
143
|
+
validation_type: Optional[str] = None,
|
144
|
+
field_name: Optional[str] = None,
|
145
|
+
field_value: Optional[Any] = None,
|
146
|
+
**kwargs
|
147
|
+
) -> None:
|
148
|
+
"""Initialize validation error.
|
149
|
+
|
150
|
+
Args:
|
151
|
+
message: Error message
|
152
|
+
validation_type: Type of validation that failed
|
153
|
+
field_name: Field that failed validation
|
154
|
+
field_value: Value that failed validation
|
155
|
+
**kwargs: Additional arguments for base class
|
156
|
+
"""
|
157
|
+
super().__init__(message, **kwargs)
|
158
|
+
self.validation_type = validation_type
|
159
|
+
self.field_name = field_name
|
160
|
+
self.field_value = field_value
|
161
|
+
|
162
|
+
|
163
|
+
class QualityValidationError(ValidationError):
|
164
|
+
"""Error when generated code doesn't meet quality standards."""
|
165
|
+
|
166
|
+
def __init__(
|
167
|
+
self,
|
168
|
+
message: str,
|
169
|
+
*,
|
170
|
+
quality_score: Optional[float] = None,
|
171
|
+
minimum_score: Optional[float] = None,
|
172
|
+
quality_issues: Optional[List[str]] = None,
|
173
|
+
**kwargs
|
174
|
+
) -> None:
|
175
|
+
"""Initialize quality validation error.
|
176
|
+
|
177
|
+
Args:
|
178
|
+
message: Error message
|
179
|
+
quality_score: Actual quality score achieved
|
180
|
+
minimum_score: Minimum required quality score
|
181
|
+
quality_issues: List of specific quality issues
|
182
|
+
**kwargs: Additional arguments for base class
|
183
|
+
"""
|
184
|
+
super().__init__(message, validation_type="quality", **kwargs)
|
185
|
+
self.quality_score = quality_score
|
186
|
+
self.minimum_score = minimum_score
|
187
|
+
self.quality_issues = quality_issues or []
|
188
|
+
|
189
|
+
|
190
|
+
class AgentExecutionError(DjangoAppAgentError):
|
191
|
+
"""Error during AI agent execution."""
|
192
|
+
|
193
|
+
def __init__(
|
194
|
+
self,
|
195
|
+
message: str,
|
196
|
+
*,
|
197
|
+
agent_name: Optional[str] = None,
|
198
|
+
agent_operation: Optional[str] = None,
|
199
|
+
retry_count: int = 0,
|
200
|
+
max_retries: int = 3,
|
201
|
+
**kwargs
|
202
|
+
) -> None:
|
203
|
+
"""Initialize agent execution error.
|
204
|
+
|
205
|
+
Args:
|
206
|
+
message: Error message
|
207
|
+
agent_name: Name of the agent that failed
|
208
|
+
agent_operation: Operation the agent was performing
|
209
|
+
retry_count: Number of retries attempted
|
210
|
+
max_retries: Maximum number of retries allowed
|
211
|
+
**kwargs: Additional arguments for base class
|
212
|
+
"""
|
213
|
+
recoverable = retry_count < max_retries
|
214
|
+
super().__init__(message, recoverable=recoverable, **kwargs)
|
215
|
+
self.agent_name = agent_name
|
216
|
+
self.agent_operation = agent_operation
|
217
|
+
self.retry_count = retry_count
|
218
|
+
self.max_retries = max_retries
|
219
|
+
|
220
|
+
|
221
|
+
class AuthenticationError(DjangoAppAgentError):
|
222
|
+
"""Error with AI service authentication."""
|
223
|
+
|
224
|
+
def __init__(
|
225
|
+
self,
|
226
|
+
message: str,
|
227
|
+
*,
|
228
|
+
provider: Optional[str] = None,
|
229
|
+
api_key_hint: Optional[str] = None,
|
230
|
+
**kwargs
|
231
|
+
) -> None:
|
232
|
+
"""Initialize authentication error.
|
233
|
+
|
234
|
+
Args:
|
235
|
+
message: Error message
|
236
|
+
provider: AI service provider (openai, anthropic, etc.)
|
237
|
+
api_key_hint: Hint about API key (first/last chars)
|
238
|
+
**kwargs: Additional arguments for base class
|
239
|
+
"""
|
240
|
+
super().__init__(message, **kwargs)
|
241
|
+
self.provider = provider
|
242
|
+
self.api_key_hint = api_key_hint
|
243
|
+
|
244
|
+
|
245
|
+
class RateLimitError(DjangoAppAgentError):
|
246
|
+
"""Error when AI service rate limits are exceeded."""
|
247
|
+
|
248
|
+
def __init__(
|
249
|
+
self,
|
250
|
+
message: str,
|
251
|
+
*,
|
252
|
+
provider: Optional[str] = None,
|
253
|
+
retry_after: Optional[int] = None,
|
254
|
+
requests_remaining: Optional[int] = None,
|
255
|
+
**kwargs
|
256
|
+
) -> None:
|
257
|
+
"""Initialize rate limit error.
|
258
|
+
|
259
|
+
Args:
|
260
|
+
message: Error message
|
261
|
+
provider: AI service provider
|
262
|
+
retry_after: Seconds to wait before retry
|
263
|
+
requests_remaining: Number of requests remaining
|
264
|
+
**kwargs: Additional arguments for base class
|
265
|
+
"""
|
266
|
+
super().__init__(message, recoverable=True, **kwargs)
|
267
|
+
self.provider = provider
|
268
|
+
self.retry_after = retry_after
|
269
|
+
self.requests_remaining = requests_remaining
|
270
|
+
|
271
|
+
|
272
|
+
class TimeoutError(DjangoAppAgentError):
|
273
|
+
"""Error when operations exceed time limits."""
|
274
|
+
|
275
|
+
def __init__(
|
276
|
+
self,
|
277
|
+
message: str,
|
278
|
+
*,
|
279
|
+
operation: Optional[str] = None,
|
280
|
+
timeout_seconds: Optional[float] = None,
|
281
|
+
elapsed_seconds: Optional[float] = None,
|
282
|
+
**kwargs
|
283
|
+
) -> None:
|
284
|
+
"""Initialize timeout error.
|
285
|
+
|
286
|
+
Args:
|
287
|
+
message: Error message
|
288
|
+
operation: Operation that timed out
|
289
|
+
timeout_seconds: Configured timeout
|
290
|
+
elapsed_seconds: Actual elapsed time
|
291
|
+
**kwargs: Additional arguments for base class
|
292
|
+
"""
|
293
|
+
super().__init__(message, recoverable=True, **kwargs)
|
294
|
+
self.operation = operation
|
295
|
+
self.timeout_seconds = timeout_seconds
|
296
|
+
self.elapsed_seconds = elapsed_seconds
|
297
|
+
|
298
|
+
|
299
|
+
class FileSystemError(DjangoAppAgentError):
|
300
|
+
"""Error when file system operations fail."""
|
301
|
+
|
302
|
+
def __init__(
|
303
|
+
self,
|
304
|
+
message: str,
|
305
|
+
*,
|
306
|
+
file_path: Optional[str] = None,
|
307
|
+
operation: Optional[str] = None,
|
308
|
+
**kwargs
|
309
|
+
) -> None:
|
310
|
+
"""Initialize file system error.
|
311
|
+
|
312
|
+
Args:
|
313
|
+
message: Error message
|
314
|
+
file_path: Path to the file that caused the error
|
315
|
+
operation: File system operation that failed
|
316
|
+
**kwargs: Additional arguments for base class
|
317
|
+
"""
|
318
|
+
super().__init__(message, recoverable=True, **kwargs)
|
319
|
+
self.file_path = file_path
|
320
|
+
self.operation = operation
|
321
|
+
|
322
|
+
|
323
|
+
# Exception mapping for easy lookup
|
324
|
+
EXCEPTION_MAP: Dict[str, type[DjangoAppAgentError]] = {
|
325
|
+
"configuration": ConfigurationError,
|
326
|
+
"generation": GenerationError,
|
327
|
+
"validation": ValidationError,
|
328
|
+
"quality": QualityValidationError,
|
329
|
+
"agent": AgentExecutionError,
|
330
|
+
"auth": AuthenticationError,
|
331
|
+
"rate_limit": RateLimitError,
|
332
|
+
"timeout": TimeoutError,
|
333
|
+
"filesystem": FileSystemError,
|
334
|
+
}
|
335
|
+
|
336
|
+
|
337
|
+
def create_error(
|
338
|
+
error_type: str,
|
339
|
+
message: str,
|
340
|
+
**kwargs
|
341
|
+
) -> DjangoAppAgentError:
|
342
|
+
"""Create an error of the specified type.
|
343
|
+
|
344
|
+
Args:
|
345
|
+
error_type: Type of error to create
|
346
|
+
message: Error message
|
347
|
+
**kwargs: Additional arguments for the error
|
348
|
+
|
349
|
+
Returns:
|
350
|
+
Appropriate error instance
|
351
|
+
|
352
|
+
Raises:
|
353
|
+
ValueError: If error_type is not recognized
|
354
|
+
"""
|
355
|
+
if error_type not in EXCEPTION_MAP:
|
356
|
+
raise ValueError(f"Unknown error type: {error_type}")
|
357
|
+
|
358
|
+
error_class = EXCEPTION_MAP[error_type]
|
359
|
+
return error_class(message, **kwargs)
|