nc1709 1.15.4__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.
Files changed (86) hide show
  1. nc1709/__init__.py +13 -0
  2. nc1709/agent/__init__.py +36 -0
  3. nc1709/agent/core.py +505 -0
  4. nc1709/agent/mcp_bridge.py +245 -0
  5. nc1709/agent/permissions.py +298 -0
  6. nc1709/agent/tools/__init__.py +21 -0
  7. nc1709/agent/tools/base.py +440 -0
  8. nc1709/agent/tools/bash_tool.py +367 -0
  9. nc1709/agent/tools/file_tools.py +454 -0
  10. nc1709/agent/tools/notebook_tools.py +516 -0
  11. nc1709/agent/tools/search_tools.py +322 -0
  12. nc1709/agent/tools/task_tool.py +284 -0
  13. nc1709/agent/tools/web_tools.py +555 -0
  14. nc1709/agents/__init__.py +17 -0
  15. nc1709/agents/auto_fix.py +506 -0
  16. nc1709/agents/test_generator.py +507 -0
  17. nc1709/checkpoints.py +372 -0
  18. nc1709/cli.py +3380 -0
  19. nc1709/cli_ui.py +1080 -0
  20. nc1709/cognitive/__init__.py +149 -0
  21. nc1709/cognitive/anticipation.py +594 -0
  22. nc1709/cognitive/context_engine.py +1046 -0
  23. nc1709/cognitive/council.py +824 -0
  24. nc1709/cognitive/learning.py +761 -0
  25. nc1709/cognitive/router.py +583 -0
  26. nc1709/cognitive/system.py +519 -0
  27. nc1709/config.py +155 -0
  28. nc1709/custom_commands.py +300 -0
  29. nc1709/executor.py +333 -0
  30. nc1709/file_controller.py +354 -0
  31. nc1709/git_integration.py +308 -0
  32. nc1709/github_integration.py +477 -0
  33. nc1709/image_input.py +446 -0
  34. nc1709/linting.py +519 -0
  35. nc1709/llm_adapter.py +667 -0
  36. nc1709/logger.py +192 -0
  37. nc1709/mcp/__init__.py +18 -0
  38. nc1709/mcp/client.py +370 -0
  39. nc1709/mcp/manager.py +407 -0
  40. nc1709/mcp/protocol.py +210 -0
  41. nc1709/mcp/server.py +473 -0
  42. nc1709/memory/__init__.py +20 -0
  43. nc1709/memory/embeddings.py +325 -0
  44. nc1709/memory/indexer.py +474 -0
  45. nc1709/memory/sessions.py +432 -0
  46. nc1709/memory/vector_store.py +451 -0
  47. nc1709/models/__init__.py +86 -0
  48. nc1709/models/detector.py +377 -0
  49. nc1709/models/formats.py +315 -0
  50. nc1709/models/manager.py +438 -0
  51. nc1709/models/registry.py +497 -0
  52. nc1709/performance/__init__.py +343 -0
  53. nc1709/performance/cache.py +705 -0
  54. nc1709/performance/pipeline.py +611 -0
  55. nc1709/performance/tiering.py +543 -0
  56. nc1709/plan_mode.py +362 -0
  57. nc1709/plugins/__init__.py +17 -0
  58. nc1709/plugins/agents/__init__.py +18 -0
  59. nc1709/plugins/agents/django_agent.py +912 -0
  60. nc1709/plugins/agents/docker_agent.py +623 -0
  61. nc1709/plugins/agents/fastapi_agent.py +887 -0
  62. nc1709/plugins/agents/git_agent.py +731 -0
  63. nc1709/plugins/agents/nextjs_agent.py +867 -0
  64. nc1709/plugins/base.py +359 -0
  65. nc1709/plugins/manager.py +411 -0
  66. nc1709/plugins/registry.py +337 -0
  67. nc1709/progress.py +443 -0
  68. nc1709/prompts/__init__.py +22 -0
  69. nc1709/prompts/agent_system.py +180 -0
  70. nc1709/prompts/task_prompts.py +340 -0
  71. nc1709/prompts/unified_prompt.py +133 -0
  72. nc1709/reasoning_engine.py +541 -0
  73. nc1709/remote_client.py +266 -0
  74. nc1709/shell_completions.py +349 -0
  75. nc1709/slash_commands.py +649 -0
  76. nc1709/task_classifier.py +408 -0
  77. nc1709/version_check.py +177 -0
  78. nc1709/web/__init__.py +8 -0
  79. nc1709/web/server.py +950 -0
  80. nc1709/web/templates/index.html +1127 -0
  81. nc1709-1.15.4.dist-info/METADATA +858 -0
  82. nc1709-1.15.4.dist-info/RECORD +86 -0
  83. nc1709-1.15.4.dist-info/WHEEL +5 -0
  84. nc1709-1.15.4.dist-info/entry_points.txt +2 -0
  85. nc1709-1.15.4.dist-info/licenses/LICENSE +9 -0
  86. nc1709-1.15.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,912 @@
1
+ """
2
+ Django Agent for NC1709
3
+ Scaffolds Django projects, apps, models, views, and more
4
+ """
5
+ import os
6
+ import re
7
+ from pathlib import Path
8
+ from typing import Dict, Any, Optional, List
9
+
10
+ from ..base import (
11
+ Plugin, PluginMetadata, PluginCapability,
12
+ ActionResult
13
+ )
14
+
15
+
16
+ class DjangoAgent(Plugin):
17
+ """
18
+ Django scaffolding and development agent.
19
+
20
+ Provides:
21
+ - Project scaffolding
22
+ - App generation
23
+ - Model generation
24
+ - View generation (function and class-based)
25
+ - URL configuration
26
+ - Admin registration
27
+ - Serializer generation (DRF)
28
+ """
29
+
30
+ METADATA = PluginMetadata(
31
+ name="django",
32
+ version="1.0.0",
33
+ description="Django project scaffolding and development",
34
+ author="NC1709 Team",
35
+ capabilities=[
36
+ PluginCapability.CODE_GENERATION,
37
+ PluginCapability.PROJECT_SCAFFOLDING
38
+ ],
39
+ keywords=[
40
+ "django", "python", "model", "view", "template",
41
+ "admin", "orm", "rest", "drf", "serializer",
42
+ "migration", "backend", "web"
43
+ ],
44
+ config_schema={
45
+ "project_path": {"type": "string", "default": "."},
46
+ "use_drf": {"type": "boolean", "default": True},
47
+ "database": {"type": "string", "enum": ["sqlite", "postgresql", "mysql"], "default": "sqlite"}
48
+ }
49
+ )
50
+
51
+ @property
52
+ def metadata(self) -> PluginMetadata:
53
+ return self.METADATA
54
+
55
+ def __init__(self, config: Optional[Dict[str, Any]] = None):
56
+ super().__init__(config)
57
+ self._project_path: Optional[Path] = None
58
+
59
+ def initialize(self) -> bool:
60
+ """Initialize the Django agent"""
61
+ self._project_path = Path(self._config.get("project_path", ".")).resolve()
62
+ return True
63
+
64
+ def cleanup(self) -> None:
65
+ """Cleanup resources"""
66
+ pass
67
+
68
+ def _register_actions(self) -> None:
69
+ """Register Django actions"""
70
+ self.register_action(
71
+ "scaffold",
72
+ self.scaffold_project,
73
+ "Create a new Django project structure",
74
+ parameters={
75
+ "name": {"type": "string", "required": True},
76
+ "with_drf": {"type": "boolean", "default": True}
77
+ }
78
+ )
79
+
80
+ self.register_action(
81
+ "app",
82
+ self.create_app,
83
+ "Generate a new Django app",
84
+ parameters={
85
+ "name": {"type": "string", "required": True}
86
+ }
87
+ )
88
+
89
+ self.register_action(
90
+ "model",
91
+ self.create_model,
92
+ "Generate a Django model",
93
+ parameters={
94
+ "app": {"type": "string", "required": True},
95
+ "name": {"type": "string", "required": True},
96
+ "fields": {"type": "object", "required": True}
97
+ }
98
+ )
99
+
100
+ self.register_action(
101
+ "view",
102
+ self.create_view,
103
+ "Generate a Django view",
104
+ parameters={
105
+ "app": {"type": "string", "required": True},
106
+ "name": {"type": "string", "required": True},
107
+ "view_type": {"type": "string", "enum": ["function", "class", "viewset"], "default": "class"}
108
+ }
109
+ )
110
+
111
+ self.register_action(
112
+ "serializer",
113
+ self.create_serializer,
114
+ "Generate a DRF serializer",
115
+ parameters={
116
+ "app": {"type": "string", "required": True},
117
+ "model": {"type": "string", "required": True}
118
+ }
119
+ )
120
+
121
+ self.register_action(
122
+ "analyze",
123
+ self.analyze_project,
124
+ "Analyze existing Django project structure"
125
+ )
126
+
127
+ def scaffold_project(
128
+ self,
129
+ name: str,
130
+ with_drf: bool = True
131
+ ) -> ActionResult:
132
+ """Create a new Django project structure
133
+
134
+ Args:
135
+ name: Project name
136
+ with_drf: Include Django REST Framework
137
+
138
+ Returns:
139
+ ActionResult
140
+ """
141
+ project_dir = self._project_path / name
142
+
143
+ if project_dir.exists():
144
+ return ActionResult.fail(f"Directory '{name}' already exists")
145
+
146
+ try:
147
+ # Create directory structure
148
+ config_dir = project_dir / name # Django puts config in project_name/project_name
149
+ dirs = [
150
+ project_dir,
151
+ config_dir,
152
+ project_dir / "apps",
153
+ project_dir / "templates",
154
+ project_dir / "static",
155
+ project_dir / "media",
156
+ ]
157
+
158
+ for d in dirs:
159
+ d.mkdir(parents=True, exist_ok=True)
160
+
161
+ # Create __init__.py files
162
+ (config_dir / "__init__.py").write_text("")
163
+ (project_dir / "apps" / "__init__.py").write_text("")
164
+
165
+ # Create manage.py
166
+ manage_content = self._generate_manage_py(name)
167
+ (project_dir / "manage.py").write_text(manage_content)
168
+
169
+ # Create settings.py
170
+ settings_content = self._generate_settings(name, with_drf)
171
+ (config_dir / "settings.py").write_text(settings_content)
172
+
173
+ # Create urls.py
174
+ urls_content = self._generate_urls(name, with_drf)
175
+ (config_dir / "urls.py").write_text(urls_content)
176
+
177
+ # Create wsgi.py
178
+ wsgi_content = self._generate_wsgi(name)
179
+ (config_dir / "wsgi.py").write_text(wsgi_content)
180
+
181
+ # Create asgi.py
182
+ asgi_content = self._generate_asgi(name)
183
+ (config_dir / "asgi.py").write_text(asgi_content)
184
+
185
+ # Create requirements.txt
186
+ requirements = self._generate_requirements(with_drf)
187
+ (project_dir / "requirements.txt").write_text(requirements)
188
+
189
+ # Create .env.example
190
+ env_content = self._generate_env_example(name)
191
+ (project_dir / ".env.example").write_text(env_content)
192
+
193
+ # Create .gitignore
194
+ gitignore = self._generate_gitignore()
195
+ (project_dir / ".gitignore").write_text(gitignore)
196
+
197
+ files_created = len(list(project_dir.rglob("*")))
198
+
199
+ return ActionResult.ok(
200
+ message=f"Created Django project '{name}' with {files_created} files",
201
+ data={
202
+ "project_path": str(project_dir),
203
+ "with_drf": with_drf,
204
+ "next_steps": [
205
+ f"cd {name}",
206
+ "python -m venv venv",
207
+ "source venv/bin/activate",
208
+ "pip install -r requirements.txt",
209
+ "python manage.py migrate",
210
+ "python manage.py runserver"
211
+ ]
212
+ }
213
+ )
214
+
215
+ except Exception as e:
216
+ return ActionResult.fail(str(e))
217
+
218
+ def create_app(self, name: str) -> ActionResult:
219
+ """Generate a new Django app
220
+
221
+ Args:
222
+ name: App name
223
+
224
+ Returns:
225
+ ActionResult with generated structure
226
+ """
227
+ app_dir = self._project_path / "apps" / name
228
+
229
+ if app_dir.exists():
230
+ return ActionResult.fail(f"App '{name}' already exists")
231
+
232
+ try:
233
+ # Create app directory
234
+ app_dir.mkdir(parents=True, exist_ok=True)
235
+ (app_dir / "migrations").mkdir()
236
+
237
+ # Create __init__.py files
238
+ (app_dir / "__init__.py").write_text("")
239
+ (app_dir / "migrations" / "__init__.py").write_text("")
240
+
241
+ # Create models.py
242
+ models_content = self._generate_models_py()
243
+ (app_dir / "models.py").write_text(models_content)
244
+
245
+ # Create views.py
246
+ views_content = self._generate_views_py()
247
+ (app_dir / "views.py").write_text(views_content)
248
+
249
+ # Create urls.py
250
+ urls_content = self._generate_app_urls(name)
251
+ (app_dir / "urls.py").write_text(urls_content)
252
+
253
+ # Create admin.py
254
+ admin_content = self._generate_admin_py()
255
+ (app_dir / "admin.py").write_text(admin_content)
256
+
257
+ # Create apps.py
258
+ apps_content = self._generate_apps_py(name)
259
+ (app_dir / "apps.py").write_text(apps_content)
260
+
261
+ # Create serializers.py (for DRF)
262
+ serializers_content = self._generate_serializers_py()
263
+ (app_dir / "serializers.py").write_text(serializers_content)
264
+
265
+ # Create tests.py
266
+ tests_content = self._generate_tests_py(name)
267
+ (app_dir / "tests.py").write_text(tests_content)
268
+
269
+ return ActionResult.ok(
270
+ message=f"Created Django app '{name}'",
271
+ data={
272
+ "app_path": str(app_dir),
273
+ "files": [
274
+ "models.py",
275
+ "views.py",
276
+ "urls.py",
277
+ "admin.py",
278
+ "serializers.py",
279
+ "tests.py"
280
+ ],
281
+ "note": f"Add 'apps.{name}' to INSTALLED_APPS in settings.py"
282
+ }
283
+ )
284
+
285
+ except Exception as e:
286
+ return ActionResult.fail(str(e))
287
+
288
+ def create_model(
289
+ self,
290
+ app: str,
291
+ name: str,
292
+ fields: Dict[str, str]
293
+ ) -> ActionResult:
294
+ """Generate a Django model
295
+
296
+ Args:
297
+ app: App name
298
+ name: Model name
299
+ fields: Dict of field_name -> field_type
300
+
301
+ Returns:
302
+ ActionResult with generated code
303
+ """
304
+ code = self._generate_model_code(name, fields)
305
+
306
+ return ActionResult.ok(
307
+ message=f"Generated model '{name}' for app '{app}'",
308
+ data={
309
+ "code": code,
310
+ "path": f"apps/{app}/models.py",
311
+ "migrations_note": "Run: python manage.py makemigrations && python manage.py migrate"
312
+ }
313
+ )
314
+
315
+ def create_view(
316
+ self,
317
+ app: str,
318
+ name: str,
319
+ view_type: str = "class"
320
+ ) -> ActionResult:
321
+ """Generate a Django view
322
+
323
+ Args:
324
+ app: App name
325
+ name: View name
326
+ view_type: Type of view (function, class, viewset)
327
+
328
+ Returns:
329
+ ActionResult with generated code
330
+ """
331
+ if view_type == "function":
332
+ code = self._generate_function_view(name)
333
+ elif view_type == "viewset":
334
+ code = self._generate_viewset(name)
335
+ else:
336
+ code = self._generate_class_view(name)
337
+
338
+ return ActionResult.ok(
339
+ message=f"Generated {view_type} view '{name}'",
340
+ data={
341
+ "code": code,
342
+ "path": f"apps/{app}/views.py",
343
+ "type": view_type
344
+ }
345
+ )
346
+
347
+ def create_serializer(
348
+ self,
349
+ app: str,
350
+ model: str
351
+ ) -> ActionResult:
352
+ """Generate a DRF serializer
353
+
354
+ Args:
355
+ app: App name
356
+ model: Model name
357
+
358
+ Returns:
359
+ ActionResult with generated code
360
+ """
361
+ code = self._generate_serializer_code(model)
362
+
363
+ return ActionResult.ok(
364
+ message=f"Generated serializer for '{model}'",
365
+ data={
366
+ "code": code,
367
+ "path": f"apps/{app}/serializers.py"
368
+ }
369
+ )
370
+
371
+ def analyze_project(self) -> ActionResult:
372
+ """Analyze existing Django project structure
373
+
374
+ Returns:
375
+ ActionResult with project analysis
376
+ """
377
+ manage_py = self._project_path / "manage.py"
378
+
379
+ if not manage_py.exists():
380
+ return ActionResult.fail("No Django project found (manage.py not found)")
381
+
382
+ analysis = {
383
+ "project_path": str(self._project_path),
384
+ "apps": [],
385
+ "models": [],
386
+ "views": [],
387
+ "urls": []
388
+ }
389
+
390
+ # Find apps
391
+ for apps_dir in [self._project_path / "apps", self._project_path]:
392
+ if apps_dir.exists():
393
+ for item in apps_dir.iterdir():
394
+ if item.is_dir() and (item / "models.py").exists():
395
+ app_name = item.name
396
+ analysis["apps"].append(app_name)
397
+
398
+ # Find models in this app
399
+ models_file = item / "models.py"
400
+ if models_file.exists():
401
+ content = models_file.read_text()
402
+ for match in re.finditer(r'class\s+(\w+)\s*\([^)]*Model[^)]*\)', content):
403
+ analysis["models"].append({
404
+ "app": app_name,
405
+ "name": match.group(1)
406
+ })
407
+
408
+ # Find views
409
+ views_file = item / "views.py"
410
+ if views_file.exists():
411
+ content = views_file.read_text()
412
+ for match in re.finditer(r'(?:def|class)\s+(\w+)', content):
413
+ analysis["views"].append({
414
+ "app": app_name,
415
+ "name": match.group(1)
416
+ })
417
+
418
+ return ActionResult.ok(
419
+ message=f"Analyzed Django project with {len(analysis['apps'])} apps",
420
+ data=analysis
421
+ )
422
+
423
+ # Code generation helpers
424
+
425
+ def _generate_manage_py(self, name: str) -> str:
426
+ """Generate manage.py"""
427
+ return f'''#!/usr/bin/env python
428
+ """Django's command-line utility for administrative tasks."""
429
+ import os
430
+ import sys
431
+
432
+
433
+ def main():
434
+ """Run administrative tasks."""
435
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{name}.settings')
436
+ try:
437
+ from django.core.management import execute_from_command_line
438
+ except ImportError as exc:
439
+ raise ImportError(
440
+ "Couldn't import Django. Are you sure it's installed and "
441
+ "available on your PYTHONPATH environment variable? Did you "
442
+ "forget to activate a virtual environment?"
443
+ ) from exc
444
+ execute_from_command_line(sys.argv)
445
+
446
+
447
+ if __name__ == '__main__':
448
+ main()
449
+ '''
450
+
451
+ def _generate_settings(self, name: str, with_drf: bool) -> str:
452
+ """Generate settings.py"""
453
+ drf_apps = "'rest_framework'," if with_drf else ""
454
+ drf_settings = '''
455
+ REST_FRAMEWORK = {
456
+ 'DEFAULT_PERMISSION_CLASSES': [
457
+ 'rest_framework.permissions.IsAuthenticated',
458
+ ],
459
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
460
+ 'rest_framework.authentication.SessionAuthentication',
461
+ ],
462
+ 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
463
+ 'PAGE_SIZE': 10,
464
+ }
465
+ ''' if with_drf else ""
466
+
467
+ return f'''"""
468
+ Django settings for {name} project.
469
+ """
470
+ import os
471
+ from pathlib import Path
472
+
473
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
474
+ BASE_DIR = Path(__file__).resolve().parent.parent
475
+
476
+ # SECURITY WARNING: keep the secret key used in production secret!
477
+ SECRET_KEY = os.environ.get('SECRET_KEY', 'django-insecure-change-me-in-production')
478
+
479
+ # SECURITY WARNING: don't run with debug turned on in production!
480
+ DEBUG = os.environ.get('DEBUG', 'True').lower() == 'true'
481
+
482
+ ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')
483
+
484
+ # Application definition
485
+ INSTALLED_APPS = [
486
+ 'django.contrib.admin',
487
+ 'django.contrib.auth',
488
+ 'django.contrib.contenttypes',
489
+ 'django.contrib.sessions',
490
+ 'django.contrib.messages',
491
+ 'django.contrib.staticfiles',
492
+ {drf_apps}
493
+ # Add your apps here
494
+ ]
495
+
496
+ MIDDLEWARE = [
497
+ 'django.middleware.security.SecurityMiddleware',
498
+ 'django.contrib.sessions.middleware.SessionMiddleware',
499
+ 'django.middleware.common.CommonMiddleware',
500
+ 'django.middleware.csrf.CsrfViewMiddleware',
501
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
502
+ 'django.contrib.messages.middleware.MessageMiddleware',
503
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
504
+ ]
505
+
506
+ ROOT_URLCONF = '{name}.urls'
507
+
508
+ TEMPLATES = [
509
+ {{
510
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
511
+ 'DIRS': [BASE_DIR / 'templates'],
512
+ 'APP_DIRS': True,
513
+ 'OPTIONS': {{
514
+ 'context_processors': [
515
+ 'django.template.context_processors.debug',
516
+ 'django.template.context_processors.request',
517
+ 'django.contrib.auth.context_processors.auth',
518
+ 'django.contrib.messages.context_processors.messages',
519
+ ],
520
+ }},
521
+ }},
522
+ ]
523
+
524
+ WSGI_APPLICATION = '{name}.wsgi.application'
525
+
526
+ # Database
527
+ DATABASES = {{
528
+ 'default': {{
529
+ 'ENGINE': 'django.db.backends.sqlite3',
530
+ 'NAME': BASE_DIR / 'db.sqlite3',
531
+ }}
532
+ }}
533
+
534
+ # Password validation
535
+ AUTH_PASSWORD_VALIDATORS = [
536
+ {{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'}},
537
+ {{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'}},
538
+ {{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'}},
539
+ {{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}},
540
+ ]
541
+
542
+ # Internationalization
543
+ LANGUAGE_CODE = 'en-us'
544
+ TIME_ZONE = 'UTC'
545
+ USE_I18N = True
546
+ USE_TZ = True
547
+
548
+ # Static files (CSS, JavaScript, Images)
549
+ STATIC_URL = 'static/'
550
+ STATICFILES_DIRS = [BASE_DIR / 'static']
551
+ STATIC_ROOT = BASE_DIR / 'staticfiles'
552
+
553
+ # Media files
554
+ MEDIA_URL = 'media/'
555
+ MEDIA_ROOT = BASE_DIR / 'media'
556
+
557
+ # Default primary key field type
558
+ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
559
+ {drf_settings}
560
+ '''
561
+
562
+ def _generate_urls(self, name: str, with_drf: bool) -> str:
563
+ """Generate urls.py"""
564
+ drf_imports = "from rest_framework import routers" if with_drf else ""
565
+ drf_urls = '''
566
+ router = routers.DefaultRouter()
567
+ # Register your viewsets here
568
+ # router.register(r'items', ItemViewSet)
569
+ ''' if with_drf else ""
570
+ drf_include = "path('api/', include(router.urls))," if with_drf else ""
571
+
572
+ return f'''"""
573
+ URL configuration for {name} project.
574
+ """
575
+ from django.contrib import admin
576
+ from django.urls import path, include
577
+ {drf_imports}
578
+ {drf_urls}
579
+ urlpatterns = [
580
+ path('admin/', admin.site.urls),
581
+ {drf_include}
582
+ ]
583
+ '''
584
+
585
+ def _generate_wsgi(self, name: str) -> str:
586
+ """Generate wsgi.py"""
587
+ return f'''"""
588
+ WSGI config for {name} project.
589
+ """
590
+ import os
591
+ from django.core.wsgi import get_wsgi_application
592
+
593
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{name}.settings')
594
+ application = get_wsgi_application()
595
+ '''
596
+
597
+ def _generate_asgi(self, name: str) -> str:
598
+ """Generate asgi.py"""
599
+ return f'''"""
600
+ ASGI config for {name} project.
601
+ """
602
+ import os
603
+ from django.core.asgi import get_asgi_application
604
+
605
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', '{name}.settings')
606
+ application = get_asgi_application()
607
+ '''
608
+
609
+ def _generate_requirements(self, with_drf: bool) -> str:
610
+ """Generate requirements.txt"""
611
+ reqs = [
612
+ "Django>=4.2",
613
+ "python-dotenv>=1.0.0",
614
+ "gunicorn>=21.0.0",
615
+ ]
616
+ if with_drf:
617
+ reqs.append("djangorestframework>=3.14.0")
618
+
619
+ reqs.extend([
620
+ "pytest>=7.0.0",
621
+ "pytest-django>=4.5.0",
622
+ ])
623
+
624
+ return '\n'.join(reqs) + '\n'
625
+
626
+ def _generate_env_example(self, name: str) -> str:
627
+ """Generate .env.example"""
628
+ return f'''# {name} Environment Variables
629
+ DEBUG=True
630
+ SECRET_KEY=your-secret-key-change-in-production
631
+ ALLOWED_HOSTS=localhost,127.0.0.1
632
+ DATABASE_URL=sqlite:///db.sqlite3
633
+ '''
634
+
635
+ def _generate_gitignore(self) -> str:
636
+ """Generate .gitignore"""
637
+ return '''# Python
638
+ __pycache__/
639
+ *.py[cod]
640
+ *$py.class
641
+ *.so
642
+ .Python
643
+ venv/
644
+ .venv/
645
+ ENV/
646
+
647
+ # Django
648
+ *.log
649
+ local_settings.py
650
+ db.sqlite3
651
+ *.pot
652
+ *.pyc
653
+ staticfiles/
654
+ media/
655
+
656
+ # IDE
657
+ .idea/
658
+ .vscode/
659
+ *.swp
660
+ *.swo
661
+
662
+ # Environment
663
+ .env
664
+ .env.local
665
+
666
+ # Testing
667
+ .coverage
668
+ htmlcov/
669
+ .pytest_cache/
670
+ '''
671
+
672
+ def _generate_models_py(self) -> str:
673
+ """Generate models.py"""
674
+ return '''"""
675
+ Models for this app.
676
+ """
677
+ from django.db import models
678
+
679
+
680
+ # Create your models here.
681
+ class BaseModel(models.Model):
682
+ """Abstract base model with common fields."""
683
+ created_at = models.DateTimeField(auto_now_add=True)
684
+ updated_at = models.DateTimeField(auto_now=True)
685
+
686
+ class Meta:
687
+ abstract = True
688
+ '''
689
+
690
+ def _generate_views_py(self) -> str:
691
+ """Generate views.py"""
692
+ return '''"""
693
+ Views for this app.
694
+ """
695
+ from django.shortcuts import render
696
+ from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
697
+
698
+
699
+ # Create your views here.
700
+ '''
701
+
702
+ def _generate_app_urls(self, name: str) -> str:
703
+ """Generate app urls.py"""
704
+ return f'''"""
705
+ URL patterns for {name} app.
706
+ """
707
+ from django.urls import path
708
+ from . import views
709
+
710
+ app_name = '{name}'
711
+
712
+ urlpatterns = [
713
+ # Add your URL patterns here
714
+ ]
715
+ '''
716
+
717
+ def _generate_admin_py(self) -> str:
718
+ """Generate admin.py"""
719
+ return '''"""
720
+ Admin configuration for this app.
721
+ """
722
+ from django.contrib import admin
723
+
724
+ # Register your models here.
725
+ '''
726
+
727
+ def _generate_apps_py(self, name: str) -> str:
728
+ """Generate apps.py"""
729
+ return f'''"""
730
+ App configuration.
731
+ """
732
+ from django.apps import AppConfig
733
+
734
+
735
+ class {name.title().replace("_", "")}Config(AppConfig):
736
+ default_auto_field = 'django.db.models.BigAutoField'
737
+ name = 'apps.{name}'
738
+ '''
739
+
740
+ def _generate_serializers_py(self) -> str:
741
+ """Generate serializers.py"""
742
+ return '''"""
743
+ DRF Serializers for this app.
744
+ """
745
+ from rest_framework import serializers
746
+
747
+ # Create your serializers here.
748
+ '''
749
+
750
+ def _generate_tests_py(self, name: str) -> str:
751
+ """Generate tests.py"""
752
+ return f'''"""
753
+ Tests for {name} app.
754
+ """
755
+ from django.test import TestCase
756
+
757
+
758
+ class {name.title().replace("_", "")}Tests(TestCase):
759
+ """Tests for {name} app."""
760
+
761
+ def test_placeholder(self):
762
+ """Placeholder test."""
763
+ self.assertTrue(True)
764
+ '''
765
+
766
+ def _generate_model_code(self, name: str, fields: Dict[str, str]) -> str:
767
+ """Generate model code"""
768
+ field_mappings = {
769
+ "str": "CharField(max_length=255)",
770
+ "string": "CharField(max_length=255)",
771
+ "text": "TextField()",
772
+ "int": "IntegerField()",
773
+ "integer": "IntegerField()",
774
+ "float": "FloatField()",
775
+ "decimal": "DecimalField(max_digits=10, decimal_places=2)",
776
+ "bool": "BooleanField(default=False)",
777
+ "boolean": "BooleanField(default=False)",
778
+ "date": "DateField()",
779
+ "datetime": "DateTimeField()",
780
+ "email": "EmailField()",
781
+ "url": "URLField()",
782
+ "file": "FileField(upload_to='files/')",
783
+ "image": "ImageField(upload_to='images/')",
784
+ }
785
+
786
+ code = f'''class {name}(BaseModel):
787
+ """{name} model."""
788
+ '''
789
+ for field_name, field_type in fields.items():
790
+ django_field = field_mappings.get(field_type.lower(), f"CharField(max_length=255) # {field_type}")
791
+ code += f' {field_name} = models.{django_field}\n'
792
+
793
+ code += f'''
794
+ class Meta:
795
+ ordering = ['-created_at']
796
+ verbose_name = '{name}'
797
+ verbose_name_plural = '{name}s'
798
+
799
+ def __str__(self):
800
+ return f"{name} {{self.id}}"
801
+ '''
802
+ return code
803
+
804
+ def _generate_function_view(self, name: str) -> str:
805
+ """Generate function-based view"""
806
+ return f'''def {name.lower()}_view(request):
807
+ """{name} view."""
808
+ context = {{}}
809
+ return render(request, '{name.lower()}.html', context)
810
+ '''
811
+
812
+ def _generate_class_view(self, name: str) -> str:
813
+ """Generate class-based view"""
814
+ return f'''class {name}View(ListView):
815
+ """{name} list view."""
816
+ # model = {name}
817
+ template_name = '{name.lower()}_list.html'
818
+ context_object_name = 'items'
819
+ paginate_by = 10
820
+
821
+
822
+ class {name}DetailView(DetailView):
823
+ """{name} detail view."""
824
+ # model = {name}
825
+ template_name = '{name.lower()}_detail.html'
826
+ context_object_name = 'item'
827
+
828
+
829
+ class {name}CreateView(CreateView):
830
+ """{name} create view."""
831
+ # model = {name}
832
+ # fields = ['field1', 'field2']
833
+ template_name = '{name.lower()}_form.html'
834
+ success_url = '/'
835
+ '''
836
+
837
+ def _generate_viewset(self, name: str) -> str:
838
+ """Generate DRF ViewSet"""
839
+ return f'''from rest_framework import viewsets
840
+ from rest_framework.permissions import IsAuthenticated
841
+ # from .models import {name}
842
+ # from .serializers import {name}Serializer
843
+
844
+
845
+ class {name}ViewSet(viewsets.ModelViewSet):
846
+ """{name} API ViewSet."""
847
+ # queryset = {name}.objects.all()
848
+ # serializer_class = {name}Serializer
849
+ permission_classes = [IsAuthenticated]
850
+
851
+ def get_queryset(self):
852
+ """Filter queryset based on user."""
853
+ return super().get_queryset()
854
+ '''
855
+
856
+ def _generate_serializer_code(self, model: str) -> str:
857
+ """Generate serializer code"""
858
+ return f'''from rest_framework import serializers
859
+ # from .models import {model}
860
+
861
+
862
+ class {model}Serializer(serializers.ModelSerializer):
863
+ """{model} serializer."""
864
+
865
+ class Meta:
866
+ # model = {model}
867
+ fields = '__all__'
868
+ read_only_fields = ['id', 'created_at', 'updated_at']
869
+
870
+
871
+ class {model}CreateSerializer(serializers.ModelSerializer):
872
+ """Serializer for creating {model}."""
873
+
874
+ class Meta:
875
+ # model = {model}
876
+ exclude = ['id', 'created_at', 'updated_at']
877
+ '''
878
+
879
+ def can_handle(self, request: str) -> float:
880
+ """Check if request is Django-related"""
881
+ request_lower = request.lower()
882
+
883
+ high_conf = ["django", "drf", "django rest", "manage.py"]
884
+ for kw in high_conf:
885
+ if kw in request_lower:
886
+ return 0.9
887
+
888
+ med_conf = ["model", "view", "serializer", "migration", "admin"]
889
+ for kw in med_conf:
890
+ if kw in request_lower:
891
+ return 0.5
892
+
893
+ return super().can_handle(request)
894
+
895
+ def handle_request(self, request: str, **kwargs) -> Optional[ActionResult]:
896
+ """Handle a natural language request"""
897
+ request_lower = request.lower()
898
+
899
+ if "scaffold" in request_lower or "new project" in request_lower:
900
+ words = request.split()
901
+ name = "myproject"
902
+ for i, word in enumerate(words):
903
+ if word.lower() in ["project", "called", "named"]:
904
+ if i + 1 < len(words):
905
+ name = words[i + 1].strip("'\"")
906
+ break
907
+ return self.scaffold_project(name=name)
908
+
909
+ if "analyze" in request_lower:
910
+ return self.analyze_project()
911
+
912
+ return None