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,203 @@
|
|
1
|
+
"""
|
2
|
+
Syntax Validator for Django App Agent.
|
3
|
+
|
4
|
+
This module provides Python syntax validation and AST analysis
|
5
|
+
for generated code files.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import List, Dict, Any, Optional
|
9
|
+
import ast
|
10
|
+
import re
|
11
|
+
|
12
|
+
from pydantic import BaseModel, Field
|
13
|
+
|
14
|
+
from ...models.responses import GeneratedFile
|
15
|
+
from ..base import ServiceDependencies
|
16
|
+
from .models import ValidationIssue
|
17
|
+
|
18
|
+
|
19
|
+
class SyntaxValidator(BaseModel):
|
20
|
+
"""Validates Python syntax and performs AST analysis."""
|
21
|
+
|
22
|
+
syntax_rules: Dict[str, Dict[str, Any]] = Field(
|
23
|
+
default_factory=lambda: {
|
24
|
+
"valid_python": {
|
25
|
+
"description": "Code must be valid Python syntax",
|
26
|
+
"severity": "error"
|
27
|
+
},
|
28
|
+
"no_syntax_errors": {
|
29
|
+
"description": "No syntax errors allowed",
|
30
|
+
"severity": "error"
|
31
|
+
},
|
32
|
+
"proper_indentation": {
|
33
|
+
"description": "Code must use consistent indentation",
|
34
|
+
"severity": "warning"
|
35
|
+
},
|
36
|
+
"no_unused_imports": {
|
37
|
+
"description": "No unused imports allowed",
|
38
|
+
"severity": "warning"
|
39
|
+
}
|
40
|
+
},
|
41
|
+
description="Syntax validation rules"
|
42
|
+
)
|
43
|
+
|
44
|
+
async def validate_syntax(
|
45
|
+
self,
|
46
|
+
file: GeneratedFile,
|
47
|
+
dependencies: ServiceDependencies
|
48
|
+
) -> List[ValidationIssue]:
|
49
|
+
"""Validate Python syntax for a single file."""
|
50
|
+
issues = []
|
51
|
+
|
52
|
+
if file.file_type != "python":
|
53
|
+
return issues
|
54
|
+
|
55
|
+
try:
|
56
|
+
# Parse the AST
|
57
|
+
tree = ast.parse(file.content)
|
58
|
+
|
59
|
+
# Check for syntax issues
|
60
|
+
issues.extend(self._check_ast_structure(file, tree, dependencies))
|
61
|
+
issues.extend(self._check_imports(file, tree, dependencies))
|
62
|
+
issues.extend(self._check_indentation(file, dependencies))
|
63
|
+
|
64
|
+
except SyntaxError as e:
|
65
|
+
issues.append(ValidationIssue(
|
66
|
+
severity="error",
|
67
|
+
category="syntax",
|
68
|
+
message=f"Syntax error: {e.msg}",
|
69
|
+
file_path=file.path,
|
70
|
+
line_number=e.lineno or 1,
|
71
|
+
column=e.offset,
|
72
|
+
rule_id="syntax_error",
|
73
|
+
suggestion="Fix the syntax error according to Python grammar rules"
|
74
|
+
))
|
75
|
+
except Exception as e:
|
76
|
+
issues.append(ValidationIssue(
|
77
|
+
severity="error",
|
78
|
+
category="syntax",
|
79
|
+
message=f"Failed to parse file: {e}",
|
80
|
+
file_path=file.path,
|
81
|
+
line_number=1,
|
82
|
+
rule_id="parse_error"
|
83
|
+
))
|
84
|
+
|
85
|
+
return issues
|
86
|
+
|
87
|
+
def _check_ast_structure(
|
88
|
+
self,
|
89
|
+
file: GeneratedFile,
|
90
|
+
tree: ast.AST,
|
91
|
+
dependencies: ServiceDependencies
|
92
|
+
) -> List[ValidationIssue]:
|
93
|
+
"""Check AST structure for common issues."""
|
94
|
+
issues = []
|
95
|
+
|
96
|
+
# Check for empty classes/functions
|
97
|
+
for node in ast.walk(tree):
|
98
|
+
if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
|
99
|
+
if len(node.body) == 1 and isinstance(node.body[0], ast.Pass):
|
100
|
+
issues.append(ValidationIssue(
|
101
|
+
severity="warning",
|
102
|
+
category="syntax",
|
103
|
+
message=f"Empty {type(node).__name__.lower()} '{node.name}' with only 'pass'",
|
104
|
+
file_path=file.path,
|
105
|
+
line_number=node.lineno,
|
106
|
+
rule_id="empty_definition",
|
107
|
+
suggestion=f"Add implementation or docstring to {node.name}"
|
108
|
+
))
|
109
|
+
|
110
|
+
return issues
|
111
|
+
|
112
|
+
def _check_imports(
|
113
|
+
self,
|
114
|
+
file: GeneratedFile,
|
115
|
+
tree: ast.AST,
|
116
|
+
dependencies: ServiceDependencies
|
117
|
+
) -> List[ValidationIssue]:
|
118
|
+
"""Check import statements for issues."""
|
119
|
+
issues = []
|
120
|
+
|
121
|
+
# Collect all imports and their usage
|
122
|
+
imports = set()
|
123
|
+
used_names = set()
|
124
|
+
|
125
|
+
for node in ast.walk(tree):
|
126
|
+
if isinstance(node, ast.Import):
|
127
|
+
for alias in node.names:
|
128
|
+
import_name = alias.asname or alias.name
|
129
|
+
imports.add(import_name)
|
130
|
+
elif isinstance(node, ast.ImportFrom):
|
131
|
+
for alias in node.names:
|
132
|
+
import_name = alias.asname or alias.name
|
133
|
+
imports.add(import_name)
|
134
|
+
elif isinstance(node, ast.Name):
|
135
|
+
used_names.add(node.id)
|
136
|
+
elif isinstance(node, ast.Attribute):
|
137
|
+
# Handle attribute access like 'models.Model'
|
138
|
+
if isinstance(node.value, ast.Name):
|
139
|
+
used_names.add(node.value.id)
|
140
|
+
|
141
|
+
# Check for unused imports
|
142
|
+
unused_imports = imports - used_names
|
143
|
+
for unused in unused_imports:
|
144
|
+
# Skip common Django imports that might be used in templates
|
145
|
+
if unused not in ['models', 'admin', 'forms', 'serializers']:
|
146
|
+
issues.append(ValidationIssue(
|
147
|
+
severity="warning",
|
148
|
+
category="syntax",
|
149
|
+
message=f"Unused import: {unused}",
|
150
|
+
file_path=file.path,
|
151
|
+
line_number=1, # Would need more sophisticated tracking for exact line
|
152
|
+
rule_id="unused_import",
|
153
|
+
suggestion=f"Remove unused import '{unused}' or use it in the code"
|
154
|
+
))
|
155
|
+
|
156
|
+
return issues
|
157
|
+
|
158
|
+
def _check_indentation(
|
159
|
+
self,
|
160
|
+
file: GeneratedFile,
|
161
|
+
dependencies: ServiceDependencies
|
162
|
+
) -> List[ValidationIssue]:
|
163
|
+
"""Check for consistent indentation."""
|
164
|
+
issues = []
|
165
|
+
lines = file.content.split('\n')
|
166
|
+
|
167
|
+
# Check for mixed tabs and spaces
|
168
|
+
has_tabs = any('\t' in line for line in lines)
|
169
|
+
has_spaces = any(line.startswith(' ') for line in lines)
|
170
|
+
|
171
|
+
if has_tabs and has_spaces:
|
172
|
+
issues.append(ValidationIssue(
|
173
|
+
severity="warning",
|
174
|
+
category="syntax",
|
175
|
+
message="Mixed tabs and spaces for indentation",
|
176
|
+
file_path=file.path,
|
177
|
+
line_number=1,
|
178
|
+
rule_id="mixed_indentation",
|
179
|
+
suggestion="Use consistent indentation (preferably 4 spaces)"
|
180
|
+
))
|
181
|
+
|
182
|
+
# Check for inconsistent indentation levels
|
183
|
+
indent_levels = set()
|
184
|
+
for i, line in enumerate(lines, 1):
|
185
|
+
if line.strip(): # Skip empty lines
|
186
|
+
leading_spaces = len(line) - len(line.lstrip(' '))
|
187
|
+
if leading_spaces > 0:
|
188
|
+
indent_levels.add(leading_spaces)
|
189
|
+
|
190
|
+
# Check if indentation follows 4-space rule
|
191
|
+
non_standard_indents = [level for level in indent_levels if level % 4 != 0]
|
192
|
+
if non_standard_indents:
|
193
|
+
issues.append(ValidationIssue(
|
194
|
+
severity="info",
|
195
|
+
category="syntax",
|
196
|
+
message=f"Non-standard indentation levels found: {non_standard_indents}",
|
197
|
+
file_path=file.path,
|
198
|
+
line_number=1,
|
199
|
+
rule_id="non_standard_indent",
|
200
|
+
suggestion="Use 4-space indentation consistently"
|
201
|
+
))
|
202
|
+
|
203
|
+
return issues
|
@@ -0,0 +1,25 @@
|
|
1
|
+
"""
|
2
|
+
User Interface Components for Django App Agent Module.
|
3
|
+
|
4
|
+
This module provides rich terminal UI components using Rich library
|
5
|
+
for beautiful and interactive command-line interfaces.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .cli import DjangoAppAgentCLI
|
9
|
+
from .rich_components import (
|
10
|
+
RichProgressTracker,
|
11
|
+
RichQuestionInterface,
|
12
|
+
RichErrorDisplay,
|
13
|
+
RichStatusDisplay
|
14
|
+
)
|
15
|
+
|
16
|
+
__all__ = [
|
17
|
+
# Main CLI interface
|
18
|
+
"DjangoAppAgentCLI",
|
19
|
+
|
20
|
+
# Rich UI components
|
21
|
+
"RichProgressTracker",
|
22
|
+
"RichQuestionInterface",
|
23
|
+
"RichErrorDisplay",
|
24
|
+
"RichStatusDisplay",
|
25
|
+
]
|
@@ -0,0 +1,419 @@
|
|
1
|
+
"""
|
2
|
+
Main CLI Interface for Django App Agent Module.
|
3
|
+
|
4
|
+
This module provides the primary command-line interface using Click
|
5
|
+
with Rich integration for beautiful terminal output.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import Optional, List, Dict, Any
|
9
|
+
from pathlib import Path
|
10
|
+
import asyncio
|
11
|
+
import sys
|
12
|
+
|
13
|
+
import click
|
14
|
+
from rich.console import Console
|
15
|
+
from rich.panel import Panel
|
16
|
+
from rich.text import Text
|
17
|
+
from rich.prompt import Prompt, Confirm
|
18
|
+
from rich.table import Table
|
19
|
+
|
20
|
+
from ..core.config import AgentConfig
|
21
|
+
from ..models.requests import AppGenerationRequest
|
22
|
+
from ..models.enums import AppType, AppComplexity, AppFeature
|
23
|
+
from ..services.app_generator import AppGeneratorService
|
24
|
+
from ..services.project_scanner import ProjectScannerService
|
25
|
+
from ..services.base import create_service_dependencies
|
26
|
+
from ..utils.logging import get_logger
|
27
|
+
from .rich_components import RichProgressTracker, RichQuestionInterface, RichErrorDisplay
|
28
|
+
|
29
|
+
|
30
|
+
class DjangoAppAgentCLI:
|
31
|
+
"""
|
32
|
+
Main CLI interface for Django App Agent.
|
33
|
+
|
34
|
+
Provides commands for:
|
35
|
+
- Interactive application generation
|
36
|
+
- Project scanning and analysis
|
37
|
+
- Batch processing
|
38
|
+
- Configuration management
|
39
|
+
"""
|
40
|
+
|
41
|
+
def __init__(self):
|
42
|
+
"""Initialize CLI interface."""
|
43
|
+
self.console = Console()
|
44
|
+
self.logger = get_logger("cli")
|
45
|
+
self.config = None
|
46
|
+
self.progress_tracker = RichProgressTracker(self.console)
|
47
|
+
self.question_interface = RichQuestionInterface(self.console)
|
48
|
+
self.error_display = RichErrorDisplay(self.console)
|
49
|
+
|
50
|
+
def _load_config(self) -> AgentConfig:
|
51
|
+
"""Load agent configuration."""
|
52
|
+
if self.config is None:
|
53
|
+
try:
|
54
|
+
# In real implementation, this would load from django-cfg
|
55
|
+
self.config = AgentConfig()
|
56
|
+
except Exception as e:
|
57
|
+
self.error_display.show_error(
|
58
|
+
"Configuration Error",
|
59
|
+
f"Failed to load configuration: {e}",
|
60
|
+
suggestions=["Check django-cfg setup", "Verify API keys"]
|
61
|
+
)
|
62
|
+
sys.exit(1)
|
63
|
+
return self.config
|
64
|
+
|
65
|
+
def _show_welcome(self):
|
66
|
+
"""Show welcome message."""
|
67
|
+
welcome_text = Text()
|
68
|
+
welcome_text.append("🚀 Django App Agent", style="bold blue")
|
69
|
+
welcome_text.append("\nAI-Powered Django Application Generator", style="italic")
|
70
|
+
|
71
|
+
panel = Panel(
|
72
|
+
welcome_text,
|
73
|
+
title="Welcome",
|
74
|
+
border_style="blue",
|
75
|
+
padding=(1, 2)
|
76
|
+
)
|
77
|
+
self.console.print(panel)
|
78
|
+
self.console.print()
|
79
|
+
|
80
|
+
def _show_app_types(self) -> AppType:
|
81
|
+
"""Show application type selection."""
|
82
|
+
self.console.print("[bold]Select Application Type:[/bold]")
|
83
|
+
|
84
|
+
table = Table(show_header=True, header_style="bold magenta")
|
85
|
+
table.add_column("Option", style="cyan", width=10)
|
86
|
+
table.add_column("Type", style="green")
|
87
|
+
table.add_column("Description")
|
88
|
+
|
89
|
+
table.add_row("1", "Django", "Standard Django application")
|
90
|
+
table.add_row("2", "Django-CFG", "Django-CFG enhanced application with configuration management")
|
91
|
+
|
92
|
+
self.console.print(table)
|
93
|
+
self.console.print()
|
94
|
+
|
95
|
+
while True:
|
96
|
+
choice = Prompt.ask("Choose application type", choices=["1", "2"], default="2")
|
97
|
+
if choice == "1":
|
98
|
+
return AppType.DJANGO
|
99
|
+
elif choice == "2":
|
100
|
+
return AppType.DJANGO_CFG
|
101
|
+
|
102
|
+
def _show_complexity_levels(self) -> AppComplexity:
|
103
|
+
"""Show complexity level selection."""
|
104
|
+
self.console.print("[bold]Select Complexity Level:[/bold]")
|
105
|
+
|
106
|
+
table = Table(show_header=True, header_style="bold magenta")
|
107
|
+
table.add_column("Option", style="cyan", width=10)
|
108
|
+
table.add_column("Level", style="green")
|
109
|
+
table.add_column("Description")
|
110
|
+
table.add_column("Est. Time", style="yellow")
|
111
|
+
|
112
|
+
table.add_row("1", "Basic", "Simple app with core features", "~5 min")
|
113
|
+
table.add_row("2", "Moderate", "Standard app with common features", "~15 min")
|
114
|
+
table.add_row("3", "Advanced", "Complex app with advanced features", "~30 min")
|
115
|
+
table.add_row("4", "Enterprise", "Full-featured enterprise application", "~60 min")
|
116
|
+
|
117
|
+
self.console.print(table)
|
118
|
+
self.console.print()
|
119
|
+
|
120
|
+
choice = Prompt.ask("Choose complexity level", choices=["1", "2", "3", "4"], default="2")
|
121
|
+
|
122
|
+
complexity_map = {
|
123
|
+
"1": AppComplexity.SIMPLE,
|
124
|
+
"2": AppComplexity.MODERATE,
|
125
|
+
"3": AppComplexity.ADVANCED,
|
126
|
+
"4": AppComplexity.ENTERPRISE
|
127
|
+
}
|
128
|
+
|
129
|
+
return complexity_map[choice]
|
130
|
+
|
131
|
+
def _select_features(self, complexity: AppComplexity) -> List[AppFeature]:
|
132
|
+
"""Interactive feature selection."""
|
133
|
+
recommended = complexity.get_recommended_features()
|
134
|
+
|
135
|
+
self.console.print(f"[bold]Select Features for {complexity.value.title()} Application:[/bold]")
|
136
|
+
self.console.print(f"[dim]Recommended features are pre-selected[/dim]")
|
137
|
+
self.console.print()
|
138
|
+
|
139
|
+
# Show available features
|
140
|
+
all_features = list(AppFeature)
|
141
|
+
selected_features = set(recommended)
|
142
|
+
|
143
|
+
table = Table(show_header=True, header_style="bold magenta")
|
144
|
+
table.add_column("Feature", style="green")
|
145
|
+
table.add_column("Selected", style="cyan", width=10)
|
146
|
+
table.add_column("Description")
|
147
|
+
|
148
|
+
for feature in all_features:
|
149
|
+
selected = "✓" if feature in selected_features else " "
|
150
|
+
description = self._get_feature_description(feature)
|
151
|
+
style = "green" if feature in selected_features else "dim"
|
152
|
+
table.add_row(feature.value, selected, description, style=style)
|
153
|
+
|
154
|
+
self.console.print(table)
|
155
|
+
self.console.print()
|
156
|
+
|
157
|
+
# Allow customization
|
158
|
+
if Confirm.ask("Customize feature selection?", default=False):
|
159
|
+
selected_features = self._customize_features(all_features, selected_features)
|
160
|
+
|
161
|
+
return list(selected_features)
|
162
|
+
|
163
|
+
def _customize_features(self, all_features: List[AppFeature], current: set) -> set:
|
164
|
+
"""Allow user to customize feature selection."""
|
165
|
+
selected = current.copy()
|
166
|
+
|
167
|
+
self.console.print("[bold]Feature Customization:[/bold]")
|
168
|
+
self.console.print("[dim]Type feature name to toggle, 'done' to finish[/dim]")
|
169
|
+
self.console.print()
|
170
|
+
|
171
|
+
while True:
|
172
|
+
# Show current selection
|
173
|
+
self.console.print("[bold]Current selection:[/bold]")
|
174
|
+
for feature in all_features:
|
175
|
+
status = "✓" if feature in selected else " "
|
176
|
+
style = "green" if feature in selected else "dim"
|
177
|
+
self.console.print(f" [{status}] {feature.value}", style=style)
|
178
|
+
|
179
|
+
self.console.print()
|
180
|
+
|
181
|
+
choice = Prompt.ask(
|
182
|
+
"Feature to toggle (or 'done')",
|
183
|
+
default="done"
|
184
|
+
).lower()
|
185
|
+
|
186
|
+
if choice == "done":
|
187
|
+
break
|
188
|
+
|
189
|
+
# Find matching feature
|
190
|
+
matching_feature = None
|
191
|
+
for feature in all_features:
|
192
|
+
if feature.value.lower() == choice or feature.value.lower().startswith(choice):
|
193
|
+
matching_feature = feature
|
194
|
+
break
|
195
|
+
|
196
|
+
if matching_feature:
|
197
|
+
if matching_feature in selected:
|
198
|
+
selected.remove(matching_feature)
|
199
|
+
self.console.print(f"[red]Removed {matching_feature.value}[/red]")
|
200
|
+
else:
|
201
|
+
selected.add(matching_feature)
|
202
|
+
self.console.print(f"[green]Added {matching_feature.value}[/green]")
|
203
|
+
else:
|
204
|
+
self.console.print(f"[red]Feature '{choice}' not found[/red]")
|
205
|
+
|
206
|
+
self.console.print()
|
207
|
+
|
208
|
+
return selected
|
209
|
+
|
210
|
+
def _get_feature_description(self, feature: AppFeature) -> str:
|
211
|
+
"""Get description for a feature."""
|
212
|
+
descriptions = {
|
213
|
+
AppFeature.MODELS: "Database models and ORM",
|
214
|
+
AppFeature.VIEWS: "View functions and classes",
|
215
|
+
AppFeature.URLS: "URL routing configuration",
|
216
|
+
AppFeature.ADMIN: "Django admin interface",
|
217
|
+
AppFeature.FORMS: "Form classes and validation",
|
218
|
+
AppFeature.TEMPLATES: "HTML templates",
|
219
|
+
AppFeature.API: "REST API with DRF",
|
220
|
+
AppFeature.TESTS: "Unit and integration tests",
|
221
|
+
AppFeature.TASKS: "Background tasks (Celery/Dramatiq)",
|
222
|
+
AppFeature.DOCS: "Auto-generated documentation",
|
223
|
+
AppFeature.CONFIG: "Configuration management",
|
224
|
+
AppFeature.SECURITY: "Security and permissions",
|
225
|
+
AppFeature.SIGNALS: "Django signals",
|
226
|
+
AppFeature.MANAGEMENT_COMMANDS: "Custom management commands",
|
227
|
+
AppFeature.MIDDLEWARE: "Custom middleware",
|
228
|
+
AppFeature.CONTEXT_PROCESSORS: "Template context processors",
|
229
|
+
}
|
230
|
+
return descriptions.get(feature, "Additional feature")
|
231
|
+
|
232
|
+
async def _run_generation(self, request: AppGenerationRequest) -> None:
|
233
|
+
"""Run application generation process."""
|
234
|
+
config = self._load_config()
|
235
|
+
|
236
|
+
# Initialize services
|
237
|
+
generator_service = AppGeneratorService(config)
|
238
|
+
|
239
|
+
# Create dependencies
|
240
|
+
deps = create_service_dependencies(
|
241
|
+
config=config,
|
242
|
+
service_name="cli_generation",
|
243
|
+
project_root=Path.cwd()
|
244
|
+
)
|
245
|
+
|
246
|
+
# Start progress tracking
|
247
|
+
with self.progress_tracker.track_generation(request.app_name) as progress:
|
248
|
+
try:
|
249
|
+
# Run generation
|
250
|
+
result = await generator_service.process(request, deps)
|
251
|
+
|
252
|
+
# Show results
|
253
|
+
if result.status == "success":
|
254
|
+
self._show_success_result(result)
|
255
|
+
else:
|
256
|
+
self._show_error_result(result)
|
257
|
+
|
258
|
+
except Exception as e:
|
259
|
+
self.error_display.show_error(
|
260
|
+
"Generation Failed",
|
261
|
+
str(e),
|
262
|
+
suggestions=["Check configuration", "Verify permissions", "Try again"]
|
263
|
+
)
|
264
|
+
|
265
|
+
def _show_success_result(self, result) -> None:
|
266
|
+
"""Show successful generation result."""
|
267
|
+
self.console.print()
|
268
|
+
|
269
|
+
success_panel = Panel(
|
270
|
+
f"✅ Successfully generated application '[bold green]{result.app_name}[/bold green]'\n"
|
271
|
+
f"📁 Files created: {len(result.generated_files)}\n"
|
272
|
+
f"⏱️ Duration: {result.duration_seconds:.1f} seconds",
|
273
|
+
title="Generation Complete",
|
274
|
+
border_style="green",
|
275
|
+
padding=(1, 2)
|
276
|
+
)
|
277
|
+
self.console.print(success_panel)
|
278
|
+
|
279
|
+
# Show quality metrics if available
|
280
|
+
if result.quality_metrics:
|
281
|
+
metrics = result.quality_metrics
|
282
|
+
|
283
|
+
metrics_table = Table(title="Quality Metrics", show_header=True)
|
284
|
+
metrics_table.add_column("Metric", style="cyan")
|
285
|
+
metrics_table.add_column("Score", style="green")
|
286
|
+
|
287
|
+
metrics_table.add_row("Code Readability", f"{metrics.code_readability_score:.2f}/1.0")
|
288
|
+
metrics_table.add_row("Maintainability", f"{metrics.maintainability_score:.2f}/1.0")
|
289
|
+
metrics_table.add_row("Type Hints", f"{metrics.type_hint_completeness:.2f}/1.0")
|
290
|
+
metrics_table.add_row("Pydantic Compliance", f"{metrics.pydantic_compliance_score:.2f}/1.0")
|
291
|
+
metrics_table.add_row("Test Coverage", f"{metrics.test_coverage_percentage:.1f}%")
|
292
|
+
|
293
|
+
self.console.print(metrics_table)
|
294
|
+
|
295
|
+
# Show next steps
|
296
|
+
self.console.print()
|
297
|
+
self.console.print("[bold]Next Steps:[/bold]")
|
298
|
+
self.console.print("1. Add the app to your INSTALLED_APPS")
|
299
|
+
self.console.print("2. Run migrations: [cyan]python manage.py makemigrations && python manage.py migrate[/cyan]")
|
300
|
+
self.console.print("3. Include URLs in your main urls.py")
|
301
|
+
self.console.print("4. Start development!")
|
302
|
+
|
303
|
+
def _show_error_result(self, result) -> None:
|
304
|
+
"""Show error generation result."""
|
305
|
+
self.error_display.show_error(
|
306
|
+
"Generation Failed",
|
307
|
+
result.message,
|
308
|
+
errors=result.errors,
|
309
|
+
warnings=result.warnings
|
310
|
+
)
|
311
|
+
|
312
|
+
|
313
|
+
# Click CLI commands
|
314
|
+
@click.group()
|
315
|
+
@click.version_option(version="0.1.0", prog_name="Django App Agent")
|
316
|
+
def cli():
|
317
|
+
"""🚀 Django App Agent - AI-Powered Django Application Generator"""
|
318
|
+
pass
|
319
|
+
|
320
|
+
|
321
|
+
@cli.command()
|
322
|
+
@click.option('--app-name', prompt='Application name', help='Name of the Django application')
|
323
|
+
@click.option('--description', prompt='Description', help='Brief description of the application')
|
324
|
+
@click.option('--app-type', type=click.Choice(['django', 'django_cfg']), default='django_cfg', help='Application type')
|
325
|
+
@click.option('--complexity', type=click.Choice(['basic', 'moderate', 'advanced', 'enterprise']), default='moderate', help='Complexity level')
|
326
|
+
@click.option('--output-dir', type=click.Path(), help='Output directory')
|
327
|
+
@click.option('--interactive/--no-interactive', default=True, help='Interactive mode')
|
328
|
+
def generate(app_name: str, description: str, app_type: str, complexity: str, output_dir: Optional[str], interactive: bool):
|
329
|
+
"""Generate a new Django application with AI assistance."""
|
330
|
+
|
331
|
+
cli_interface = DjangoAppAgentCLI()
|
332
|
+
|
333
|
+
if interactive:
|
334
|
+
cli_interface._show_welcome()
|
335
|
+
|
336
|
+
# Interactive mode
|
337
|
+
app_type_enum = cli_interface._show_app_types()
|
338
|
+
complexity_enum = cli_interface._show_complexity_levels()
|
339
|
+
features = cli_interface._select_features(complexity_enum)
|
340
|
+
|
341
|
+
else:
|
342
|
+
# Non-interactive mode
|
343
|
+
app_type_enum = AppType.DJANGO_CFG if app_type == 'django_cfg' else AppType.DJANGO
|
344
|
+
complexity_enum = AppComplexity(complexity)
|
345
|
+
features = list(complexity_enum.get_recommended_features())
|
346
|
+
|
347
|
+
# Create generation request
|
348
|
+
request = AppGenerationRequest(
|
349
|
+
app_name=app_name,
|
350
|
+
description=description,
|
351
|
+
app_type=app_type_enum,
|
352
|
+
complexity=complexity_enum,
|
353
|
+
features=features,
|
354
|
+
output_directory=output_dir
|
355
|
+
)
|
356
|
+
|
357
|
+
# Run generation
|
358
|
+
asyncio.run(cli_interface._run_generation(request))
|
359
|
+
|
360
|
+
|
361
|
+
@cli.command()
|
362
|
+
@click.option('--project-root', type=click.Path(exists=True), default='.', help='Project root directory')
|
363
|
+
@click.option('--output-format', type=click.Choice(['table', 'json']), default='table', help='Output format')
|
364
|
+
def scan(project_root: str, output_format: str):
|
365
|
+
"""Scan and analyze Django project structure."""
|
366
|
+
|
367
|
+
cli_interface = DjangoAppAgentCLI()
|
368
|
+
config = cli_interface._load_config()
|
369
|
+
|
370
|
+
async def run_scan():
|
371
|
+
scanner_service = ProjectScannerService(config)
|
372
|
+
|
373
|
+
request = ProjectScanRequest(
|
374
|
+
project_root=Path(project_root),
|
375
|
+
scan_depth=3,
|
376
|
+
analyze_dependencies=True,
|
377
|
+
detect_patterns=True
|
378
|
+
)
|
379
|
+
|
380
|
+
deps = create_service_dependencies(
|
381
|
+
config=config,
|
382
|
+
service_name="cli_scan",
|
383
|
+
project_root=Path(project_root)
|
384
|
+
)
|
385
|
+
|
386
|
+
with cli_interface.progress_tracker.track_scanning() as progress:
|
387
|
+
result = await scanner_service.process(request, deps)
|
388
|
+
|
389
|
+
# Display results
|
390
|
+
if output_format == 'table':
|
391
|
+
cli_interface._show_scan_table(result)
|
392
|
+
else:
|
393
|
+
cli_interface._show_scan_json(result)
|
394
|
+
|
395
|
+
asyncio.run(run_scan())
|
396
|
+
|
397
|
+
|
398
|
+
@cli.command()
|
399
|
+
def config():
|
400
|
+
"""Show current configuration."""
|
401
|
+
|
402
|
+
cli_interface = DjangoAppAgentCLI()
|
403
|
+
config = cli_interface._load_config()
|
404
|
+
|
405
|
+
# Show configuration in a nice table
|
406
|
+
config_table = Table(title="Django App Agent Configuration", show_header=True)
|
407
|
+
config_table.add_column("Setting", style="cyan")
|
408
|
+
config_table.add_column("Value", style="green")
|
409
|
+
|
410
|
+
# Add configuration rows (this would be populated from actual config)
|
411
|
+
config_table.add_row("Version", "0.1.0")
|
412
|
+
config_table.add_row("Default App Type", "django_cfg")
|
413
|
+
config_table.add_row("AI Provider", "OpenRouter")
|
414
|
+
|
415
|
+
cli_interface.console.print(config_table)
|
416
|
+
|
417
|
+
|
418
|
+
if __name__ == '__main__':
|
419
|
+
cli()
|