diff --git a/.gitignore b/.gitignore
index 2f2142b..cc7d04f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -230,4 +230,5 @@ secrets.json
# NextJS frontend directory
nextjs/
netcop-ai-hub/
-temp/
\ No newline at end of file
+temp/
+five-whys-agent-new.html
diff --git a/agent_base/management/commands/populate_agents.py b/agent_base/management/commands/populate_agents.py
index 8bda506..342c510 100644
--- a/agent_base/management/commands/populate_agents.py
+++ b/agent_base/management/commands/populate_agents.py
@@ -78,6 +78,15 @@ class Command(BaseCommand):
'icon': '📱',
'agent_type': 'webhook',
},
+ {
+ 'name': '5 Whys Analysis Agent',
+ 'slug': 'five-whys-analyzer',
+ 'description': 'Systematic root cause analysis using the proven 5 Whys methodology to identify and solve business problems effectively.',
+ 'category': 'analytics',
+ 'price': 8.0,
+ 'icon': '🔍',
+ 'agent_type': 'webhook',
+ },
]
created_count = 0
diff --git a/five_whys_analyzer/__init__.py b/five_whys_analyzer/__init__.py
new file mode 100644
index 0000000..1f5df5b
--- /dev/null
+++ b/five_whys_analyzer/__init__.py
@@ -0,0 +1 @@
+# 5 Whys Analysis Agent Agent App
\ No newline at end of file
diff --git a/five_whys_analyzer/admin.py b/five_whys_analyzer/admin.py
new file mode 100644
index 0000000..fd2d7a1
--- /dev/null
+++ b/five_whys_analyzer/admin.py
@@ -0,0 +1,43 @@
+from django.contrib import admin
+from .models import FiveWhysAnalyzerRequest, FiveWhysAnalyzerResponse
+
+
+@admin.register(FiveWhysAnalyzerRequest)
+class FiveWhysAnalyzerRequestAdmin(admin.ModelAdmin):
+ list_display = ['id', 'user', 'session_id', 'status', 'report_generated', 'chat_active', 'created_at', 'cost']
+ list_filter = ['status', 'report_generated', 'chat_active', 'analysis_depth', 'created_at']
+ search_fields = ['user__email', 'user__username', 'session_id', 'problem_statement']
+ readonly_fields = ['id', 'created_at', 'processed_at', 'session_id']
+ ordering = ['-created_at']
+
+ fieldsets = (
+ ('Basic Info', {
+ 'fields': ('id', 'user', 'session_id', 'status', 'created_at', 'processed_at')
+ }),
+ ('Chat Session', {
+ 'fields': ('chat_active', 'chat_messages')
+ }),
+ ('Report Generation', {
+ 'fields': ('report_generated', 'problem_statement', 'context_info', 'analysis_depth', 'cost')
+ }),
+ )
+
+
+@admin.register(FiveWhysAnalyzerResponse)
+class FiveWhysAnalyzerResponseAdmin(admin.ModelAdmin):
+ list_display = ['id', 'request', 'success', 'created_at']
+ list_filter = ['success', 'created_at']
+ readonly_fields = ['id', 'created_at']
+ ordering = ['-created_at']
+
+ fieldsets = (
+ ('Basic Info', {
+ 'fields': ('id', 'request', 'success', 'created_at', 'processing_time', 'error_message')
+ }),
+ ('Chat Response', {
+ 'fields': ('chat_response', 'chat_history')
+ }),
+ ('Final Report', {
+ 'fields': ('final_report', 'report_metadata')
+ }),
+ )
\ No newline at end of file
diff --git a/five_whys_analyzer/apps.py b/five_whys_analyzer/apps.py
new file mode 100644
index 0000000..8127422
--- /dev/null
+++ b/five_whys_analyzer/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class FiveWhysAnalyzerConfig(AppConfig):
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'five_whys_analyzer'
\ No newline at end of file
diff --git a/five_whys_analyzer/migrations/0001_initial.py b/five_whys_analyzer/migrations/0001_initial.py
new file mode 100644
index 0000000..7224c15
--- /dev/null
+++ b/five_whys_analyzer/migrations/0001_initial.py
@@ -0,0 +1,74 @@
+# Generated by Django 5.2.4 on 2025-07-12 16:08
+
+import django.db.models.deletion
+import uuid
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('agent_base', '0001_initial'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='FiveWhysAnalyzerRequest',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('status', models.CharField(choices=[('pending', 'Pending'), ('processing', 'Processing'), ('completed', 'Completed'), ('failed', 'Failed')], default='pending', max_length=20)),
+ ('cost', models.DecimalField(decimal_places=2, max_digits=10)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('processed_at', models.DateTimeField(blank=True, null=True)),
+ ('session_id', models.CharField(db_index=True, default=uuid.uuid4, max_length=100)),
+ ('chat_messages', models.JSONField(default=list, help_text='Store chat history as list of messages')),
+ ('problem_statement', models.TextField(blank=True, help_text='Main problem to analyze')),
+ ('context_info', models.TextField(blank=True, help_text='Additional context information')),
+ ('analysis_depth', models.CharField(blank=True, choices=[('standard', 'Standard 5 Whys'), ('detailed', 'Extended Analysis'), ('comprehensive', 'Comprehensive Report')], default='standard', max_length=20)),
+ ('report_generated', models.BooleanField(default=False, help_text='Has final report been generated and paid for')),
+ ('chat_active', models.BooleanField(default=True, help_text='Is chat session still active')),
+ ('input_text', models.TextField(blank=True)),
+ ('agent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='agent_base.baseagent')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ options={
+ 'verbose_name': '5 Whys Analysis Agent Request',
+ 'verbose_name_plural': '5 Whys Analysis Agent Requests',
+ 'db_table': 'five_whys_analyzer_requests',
+ },
+ ),
+ migrations.CreateModel(
+ name='FiveWhysAnalyzerResponse',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('success', models.BooleanField(default=False)),
+ ('error_message', models.TextField(blank=True)),
+ ('processing_time', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('chat_response', models.TextField(blank=True, help_text='Latest chat response')),
+ ('chat_history', models.JSONField(default=list, help_text='Full chat response history')),
+ ('final_report', models.TextField(blank=True, help_text='Generated 5 Whys analysis report')),
+ ('report_metadata', models.JSONField(default=dict, help_text='Report generation metadata')),
+ ('output_text', models.TextField(blank=True)),
+ ('raw_response', models.JSONField(blank=True, default=dict)),
+ ('request', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='response', to='five_whys_analyzer.fivewhysanalyzerrequest')),
+ ],
+ options={
+ 'verbose_name': '5 Whys Analysis Agent Response',
+ 'verbose_name_plural': '5 Whys Analysis Agent Responses',
+ 'db_table': 'five_whys_analyzer_responses',
+ },
+ ),
+ migrations.AddIndex(
+ model_name='fivewhysanalyzerrequest',
+ index=models.Index(fields=['session_id'], name='five_whys_a_session_0dd791_idx'),
+ ),
+ migrations.AddIndex(
+ model_name='fivewhysanalyzerrequest',
+ index=models.Index(fields=['user', 'chat_active'], name='five_whys_a_user_id_810315_idx'),
+ ),
+ ]
diff --git a/five_whys_analyzer/migrations/__init__.py b/five_whys_analyzer/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/five_whys_analyzer/models.py b/five_whys_analyzer/models.py
new file mode 100644
index 0000000..9d2214e
--- /dev/null
+++ b/five_whys_analyzer/models.py
@@ -0,0 +1,71 @@
+from django.db import models
+from decimal import Decimal
+from agent_base.models import BaseAgentRequest, BaseAgentResponse
+import uuid
+
+
+class FiveWhysAnalyzerRequest(BaseAgentRequest):
+ """5 Whys Analysis Agent request tracking with chat support"""
+
+ # Chat session management
+ session_id = models.CharField(max_length=100, default=uuid.uuid4, db_index=True)
+
+ # Chat interaction tracking
+ chat_messages = models.JSONField(default=list, help_text="Store chat history as list of messages")
+
+ # Final report fields (only filled when report is generated)
+ problem_statement = models.TextField(blank=True, help_text="Main problem to analyze")
+ context_info = models.TextField(blank=True, help_text="Additional context information")
+ analysis_depth = models.CharField(
+ max_length=20,
+ blank=True,
+ choices=[
+ ('standard', 'Standard 5 Whys'),
+ ('detailed', 'Extended Analysis'),
+ ('comprehensive', 'Comprehensive Report')
+ ],
+ default='standard'
+ )
+
+ # Chat vs Report tracking
+ report_generated = models.BooleanField(default=False, help_text="Has final report been generated and paid for")
+ chat_active = models.BooleanField(default=True, help_text="Is chat session still active")
+
+ # Legacy field for compatibility
+ input_text = models.TextField(blank=True)
+
+ class Meta:
+ db_table = 'five_whys_analyzer_requests'
+ verbose_name = '5 Whys Analysis Agent Request'
+ verbose_name_plural = '5 Whys Analysis Agent Requests'
+ indexes = [
+ models.Index(fields=['session_id']),
+ models.Index(fields=['user', 'chat_active']),
+ ]
+
+
+class FiveWhysAnalyzerResponse(BaseAgentResponse):
+ """5 Whys Analysis Agent response storage"""
+
+ request = models.OneToOneField(
+ FiveWhysAnalyzerRequest,
+ on_delete=models.CASCADE,
+ related_name='response'
+ )
+
+ # Chat responses (free interactions)
+ chat_response = models.TextField(blank=True, help_text="Latest chat response")
+ chat_history = models.JSONField(default=list, help_text="Full chat response history")
+
+ # Final report (paid interaction)
+ final_report = models.TextField(blank=True, help_text="Generated 5 Whys analysis report")
+ report_metadata = models.JSONField(default=dict, help_text="Report generation metadata")
+
+ # Legacy fields for compatibility
+ output_text = models.TextField(blank=True)
+ raw_response = models.JSONField(default=dict, blank=True)
+
+ class Meta:
+ db_table = 'five_whys_analyzer_responses'
+ verbose_name = '5 Whys Analysis Agent Response'
+ verbose_name_plural = '5 Whys Analysis Agent Responses'
\ No newline at end of file
diff --git a/five_whys_analyzer/processor.py b/five_whys_analyzer/processor.py
new file mode 100644
index 0000000..4e7c0df
--- /dev/null
+++ b/five_whys_analyzer/processor.py
@@ -0,0 +1,247 @@
+from agent_base.processors import StandardWebhookProcessor
+from django.utils import timezone
+from django.conf import settings
+from .models import FiveWhysAnalyzerRequest, FiveWhysAnalyzerResponse
+import json
+import uuid
+
+
+class FiveWhysAnalyzerProcessor(StandardWebhookProcessor):
+ """Dual-mode webhook processor for 5 Whys Analysis Agent - supports chat and report generation"""
+
+ agent_slug = 'five-whys-analyzer'
+ webhook_url = 'https://m8taq6tk.rpcld.cc/webhook/5-whys-web'
+ agent_id = 'five-whys-001'
+
+ def process_response(self, response_data, request_obj):
+ """Required implementation of abstract method - delegates to specific handlers"""
+ # This method is required by the base class but we handle responses
+ # differently in our dual-mode approach
+ return self.process_report_response(response_data, request_obj)
+
+ def process_request(self, **kwargs):
+ """Handle both chat messages (free) and report generation (paid)"""
+ message_type = kwargs.get('message_type', 'chat')
+
+ if message_type == 'chat':
+ return self.handle_chat_message(**kwargs)
+ elif message_type == 'generate_report':
+ return self.handle_report_generation(**kwargs)
+ else:
+ raise ValueError(f"Unknown message type: {message_type}")
+
+ def handle_chat_message(self, **kwargs):
+ """Handle free chat interactions - no wallet deduction"""
+ user = kwargs.get('user')
+ session_id = kwargs.get('session_id', str(uuid.uuid4()))
+ user_message = kwargs.get('message', '')
+
+ # Get the agent object
+ from agent_base.models import BaseAgent
+ try:
+ agent = BaseAgent.objects.get(slug=self.agent_slug)
+ except BaseAgent.DoesNotExist:
+ raise Exception(f"Agent with slug '{self.agent_slug}' not found")
+
+ # Get or create request object for this session
+ request_obj, created = FiveWhysAnalyzerRequest.objects.get_or_create(
+ user=user,
+ session_id=session_id,
+ chat_active=True,
+ defaults={
+ 'agent': agent,
+ 'cost': 0, # No cost for chat
+ 'status': 'pending'
+ }
+ )
+
+ # Add user message to chat history
+ chat_messages = request_obj.chat_messages
+ chat_messages.append({
+ 'role': 'user',
+ 'message': user_message,
+ 'timestamp': timezone.now().isoformat()
+ })
+ request_obj.chat_messages = chat_messages
+ request_obj.save()
+
+ # Prepare chat payload for webhook
+ chat_payload = {
+ 'message': {
+ 'text': f"Chat message: {user_message}. Provide helpful guidance about 5 Whys analysis. Do not generate the final report - just chat and help the user understand their problem."
+ },
+ 'sessionId': session_id,
+ 'userId': str(user.id),
+ 'agentId': self.agent_id,
+ 'messageType': 'chat'
+ }
+
+ # Send to webhook
+ response_data = self.make_request(chat_payload)
+
+ # Process chat response (no wallet deduction)
+ return self.process_chat_response(response_data, request_obj, user_message)
+
+ def handle_report_generation(self, **kwargs):
+ """Handle paid report generation - deduct wallet after success"""
+ user = kwargs.get('user')
+ session_id = kwargs.get('session_id')
+ problem_statement = kwargs.get('problem_statement', '')
+ context_info = kwargs.get('context_info', '')
+ analysis_depth = kwargs.get('analysis_depth', 'standard')
+
+ # Get the agent object
+ from agent_base.models import BaseAgent
+ try:
+ agent = BaseAgent.objects.get(slug=self.agent_slug)
+ except BaseAgent.DoesNotExist:
+ raise Exception(f"Agent with slug '{self.agent_slug}' not found")
+
+ # Get existing session or create new one
+ try:
+ request_obj = FiveWhysAnalyzerRequest.objects.get(
+ user=user,
+ session_id=session_id,
+ chat_active=True
+ )
+ except FiveWhysAnalyzerRequest.DoesNotExist:
+ # Create new request for report generation
+ request_obj = FiveWhysAnalyzerRequest.objects.create(
+ user=user,
+ session_id=session_id,
+ agent=agent,
+ cost=8.0, # Cost for report generation
+ status='pending'
+ )
+
+ # Update request with report details
+ request_obj.problem_statement = problem_statement
+ request_obj.context_info = context_info
+ request_obj.analysis_depth = analysis_depth
+ request_obj.cost = 8.0 # Ensure cost is set for report
+ request_obj.save()
+
+ # Prepare report generation payload
+ report_payload = {
+ 'message': {
+ 'text': f"Generate comprehensive 5 Whys analysis report.\nProblem: {problem_statement}\nContext: {context_info}\nDepth: {analysis_depth}\nChat History: {json.dumps(request_obj.chat_messages[-10:])}"
+ },
+ 'sessionId': session_id,
+ 'userId': str(user.id),
+ 'agentId': self.agent_id,
+ 'messageType': 'report',
+ 'analysisDepth': analysis_depth
+ }
+
+ # Send to webhook
+ response_data = self.make_request(report_payload)
+
+ # Process report response (with wallet deduction)
+ return self.process_report_response(response_data, request_obj)
+
+ def process_chat_response(self, response_data, request_obj, user_message):
+ """Process chat response - no wallet deduction"""
+ try:
+ # Extract chat response
+ chat_response = response_data.get('output', response_data.get('message', 'I\'m here to help with 5 Whys analysis. What would you like to know?'))
+
+ # Add assistant response to chat history
+ chat_messages = request_obj.chat_messages
+ chat_messages.append({
+ 'role': 'assistant',
+ 'message': chat_response,
+ 'timestamp': timezone.now().isoformat()
+ })
+ request_obj.chat_messages = chat_messages
+ request_obj.status = 'completed' # Chat message completed
+ request_obj.save()
+
+ # Get or create response object
+ response_obj, created = FiveWhysAnalyzerResponse.objects.get_or_create(
+ request=request_obj,
+ defaults={
+ 'success': True,
+ 'processing_time': response_data.get('processing_time', 0)
+ }
+ )
+
+ # Update response with chat data
+ response_obj.chat_response = chat_response
+ chat_history = response_obj.chat_history
+ chat_history.append({
+ 'user_message': user_message,
+ 'assistant_response': chat_response,
+ 'timestamp': timezone.now().isoformat()
+ })
+ response_obj.chat_history = chat_history
+ response_obj.save()
+
+ print(f"{self.agent_slug}: Chat message processed - no wallet deduction")
+ return response_obj
+
+ except Exception as e:
+ request_obj.status = 'failed'
+ request_obj.save()
+ raise Exception(f"Failed to process chat response: {e}")
+
+ def process_report_response(self, response_data, request_obj):
+ """Process report generation response - deduct wallet after success"""
+ try:
+ request_obj.status = 'processing'
+ request_obj.save()
+
+ # Extract report data
+ final_report = response_data.get('output', response_data.get('report', ''))
+ success = bool(final_report) and response_data.get('success', True)
+
+ # Get or create response object
+ response_obj, created = FiveWhysAnalyzerResponse.objects.get_or_create(
+ request=request_obj,
+ defaults={
+ 'success': success,
+ 'processing_time': response_data.get('processing_time', 0)
+ }
+ )
+
+ if success:
+ # Update with final report
+ response_obj.final_report = final_report
+ response_obj.report_metadata = {
+ 'analysis_depth': request_obj.analysis_depth,
+ 'generated_at': timezone.now().isoformat(),
+ 'problem_statement': request_obj.problem_statement,
+ 'context_info': request_obj.context_info
+ }
+ response_obj.save()
+
+ # Mark request as report generated
+ request_obj.report_generated = True
+ request_obj.chat_active = False # End chat session
+
+ # ONLY deduct wallet balance after successful report generation
+ request_obj.user.deduct_balance(
+ request_obj.cost,
+ f"5 Whys Analysis Agent - Final Report ({request_obj.analysis_depth})",
+ 'five-whys-analyzer'
+ )
+ print(f"{self.agent_slug}: Wallet deducted {request_obj.cost} AED for successful report generation")
+
+ request_obj.status = 'completed'
+ else:
+ request_obj.status = 'failed'
+ response_obj.error_message = "Failed to generate report"
+ response_obj.save()
+
+ request_obj.processed_at = timezone.now()
+ request_obj.save()
+
+ return response_obj
+
+ except Exception as e:
+ request_obj.status = 'failed'
+ request_obj.save()
+ raise Exception(f"Failed to process report response: {e}")
+
+ def prepare_message_text(self, **kwargs):
+ """Legacy method for compatibility"""
+ return kwargs.get('message', 'Process 5 Whys analysis')
\ No newline at end of file
diff --git a/five_whys_analyzer/templates/five_whys_analyzer/detail.html b/five_whys_analyzer/templates/five_whys_analyzer/detail.html
new file mode 100644
index 0000000..8e3e739
--- /dev/null
+++ b/five_whys_analyzer/templates/five_whys_analyzer/detail.html
@@ -0,0 +1,671 @@
+{% extends "base.html" %}
+{% csrf_token %}
+
+{% block title %}5 Whys Analysis Agent - NetCop AI Hub{% endblock %}
+
+{% block content %}
+
+
+
+
+
+
+
+
+ 🔍 {{ agent.name }}
+
+
+ {{ agent.description }}
+
+
+
+
+
+
💬 Chat with 5 Whys Analyst
+
+
+
+
5 Whys Analyst
+
+ Hello! I'm here to help you with root cause analysis using the 5 Whys methodology.
+
+ You can ask me questions, describe your problem, and I'll guide you through the analysis process. When you're ready, I can generate a comprehensive report for 8.00 AED.
+
+ How can I help you today?
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
✅
+
5 Whys Analysis Report
+
+ ✅ Complete
+
+
+
+
+
+
+
+
+
+ 📋 Copy Report
+
+
+ 💾 Download Report
+
+
+
+
+
+
+
+
+
💳 Your Wallet
+
+
+ {{ user.wallet_balance|floatformat:2 }} AED
+
+
+ Available Balance
+
+
+
+ 💳 Top Up Wallet
+
+
+
+
+
💡 How it works
+
+
+ •
+ Chat freely to explore your problem
+
+
+ •
+ Get guidance and ask questions
+
+
+ •
+ Generate final report when ready
+
+
+ •
+ Pay only for the final report
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/five_whys_analyzer/urls.py b/five_whys_analyzer/urls.py
new file mode 100644
index 0000000..d333e82
--- /dev/null
+++ b/five_whys_analyzer/urls.py
@@ -0,0 +1,13 @@
+from django.urls import path
+from . import views
+
+app_name = 'five_whys_analyzer'
+
+urlpatterns = [
+ path('', views.five_whys_analyzer_detail, name='detail'),
+ path('chat/', views.FiveWhysAnalyzerChatView.as_view(), name='chat'),
+ path('report/', views.FiveWhysAnalyzerReportView.as_view(), name='report'),
+ path('session//', views.five_whys_analyzer_session, name='session'),
+ # Legacy compatibility
+ path('process/', views.FiveWhysAnalyzerProcessView.as_view(), name='process'),
+]
\ No newline at end of file
diff --git a/five_whys_analyzer/views.py b/five_whys_analyzer/views.py
new file mode 100644
index 0000000..5258281
--- /dev/null
+++ b/five_whys_analyzer/views.py
@@ -0,0 +1,186 @@
+from django.shortcuts import render, redirect
+from django.contrib.auth.decorators import login_required
+from django.contrib import messages
+from django.http import JsonResponse
+from django.views.decorators.csrf import csrf_exempt
+from django.utils.decorators import method_decorator
+from django.views import View
+from agent_base.models import BaseAgent
+from .models import FiveWhysAnalyzerRequest, FiveWhysAnalyzerResponse
+from .processor import FiveWhysAnalyzerProcessor
+import json
+import uuid
+
+
+@login_required
+def five_whys_analyzer_detail(request):
+ """Detail page for 5 Whys Analysis Agent with chat interface"""
+ try:
+ agent = BaseAgent.objects.get(slug='five-whys-analyzer')
+ except BaseAgent.DoesNotExist:
+ messages.error(request, '5 Whys Analysis Agent agent not found.')
+ return redirect('core:homepage')
+
+ # Get user's active chat sessions
+ active_sessions = FiveWhysAnalyzerRequest.objects.filter(
+ user=request.user,
+ chat_active=True
+ ).order_by('-created_at')[:5]
+
+ # Get user's completed reports
+ completed_reports = FiveWhysAnalyzerRequest.objects.filter(
+ user=request.user,
+ report_generated=True
+ ).order_by('-created_at')[:10]
+
+ context = {
+ 'agent': agent,
+ 'active_sessions': active_sessions,
+ 'completed_reports': completed_reports
+ }
+ return render(request, 'five_whys_analyzer/detail.html', context)
+
+
+@method_decorator(csrf_exempt, name='dispatch')
+class FiveWhysAnalyzerChatView(View):
+ """Handle chat messages - free interactions"""
+
+ def post(self, request):
+ if not request.user.is_authenticated:
+ return JsonResponse({'error': 'Authentication required'}, status=401)
+
+ try:
+ # Parse request data
+ data = json.loads(request.body)
+
+ # Get session ID or create new one
+ session_id = data.get('session_id', str(uuid.uuid4()))
+ user_message = data.get('message', '').strip()
+
+ if not user_message:
+ return JsonResponse({'error': 'Message cannot be empty'}, status=400)
+
+ # Process chat message (no wallet deduction)
+ processor = FiveWhysAnalyzerProcessor()
+ result = processor.handle_chat_message(
+ user=request.user,
+ session_id=session_id,
+ message=user_message
+ )
+
+ return JsonResponse({
+ 'success': True,
+ 'session_id': session_id,
+ 'response': result.chat_response,
+ 'message_type': 'chat',
+ 'wallet_balance': float(request.user.wallet_balance) # No change expected
+ })
+
+ except Exception as e:
+ return JsonResponse({'error': str(e)}, status=500)
+
+
+@method_decorator(csrf_exempt, name='dispatch')
+class FiveWhysAnalyzerReportView(View):
+ """Generate final report - paid interaction"""
+
+ def post(self, request):
+ if not request.user.is_authenticated:
+ return JsonResponse({'error': 'Authentication required'}, status=401)
+
+ try:
+ # Parse request data
+ data = json.loads(request.body)
+
+ # Get report parameters
+ session_id = data.get('session_id')
+ problem_statement = data.get('problem_statement', '').strip()
+ context_info = data.get('context_info', '').strip()
+ analysis_depth = data.get('analysis_depth', 'standard')
+
+ if not session_id:
+ return JsonResponse({'error': 'Session ID required'}, status=400)
+
+ if not problem_statement:
+ return JsonResponse({'error': 'Problem statement required'}, status=400)
+
+ # Get agent for price checking
+ agent = BaseAgent.objects.get(slug='five-whys-analyzer')
+
+ # Check wallet balance
+ if not request.user.has_sufficient_balance(agent.price):
+ return JsonResponse({'error': 'Insufficient wallet balance'}, status=400)
+
+ # Process report generation (wallet deduction after success)
+ processor = FiveWhysAnalyzerProcessor()
+ result = processor.handle_report_generation(
+ user=request.user,
+ session_id=session_id,
+ problem_statement=problem_statement,
+ context_info=context_info,
+ analysis_depth=analysis_depth
+ )
+
+ # Refresh user to get updated wallet balance
+ request.user.refresh_from_db()
+
+ return JsonResponse({
+ 'success': True,
+ 'session_id': session_id,
+ 'report': result.final_report,
+ 'message_type': 'report',
+ 'analysis_depth': analysis_depth,
+ 'wallet_balance': float(request.user.wallet_balance)
+ })
+
+ except BaseAgent.DoesNotExist:
+ return JsonResponse({'error': '5 Whys Analysis Agent not found'}, status=404)
+ except Exception as e:
+ return JsonResponse({'error': str(e)}, status=500)
+
+
+@login_required
+def five_whys_analyzer_session(request, session_id):
+ """Get chat session data"""
+ try:
+ session_request = FiveWhysAnalyzerRequest.objects.get(
+ session_id=session_id,
+ user=request.user
+ )
+
+ session_data = {
+ 'session_id': session_id,
+ 'chat_messages': session_request.chat_messages,
+ 'chat_active': session_request.chat_active,
+ 'report_generated': session_request.report_generated,
+ 'problem_statement': session_request.problem_statement,
+ 'context_info': session_request.context_info,
+ 'analysis_depth': session_request.analysis_depth
+ }
+
+ # Add final report if generated
+ if session_request.report_generated and hasattr(session_request, 'response'):
+ session_data['final_report'] = session_request.response.final_report
+ session_data['report_metadata'] = session_request.response.report_metadata
+
+ return JsonResponse({
+ 'success': True,
+ 'session': session_data
+ })
+
+ except FiveWhysAnalyzerRequest.DoesNotExist:
+ return JsonResponse({'error': 'Session not found'}, status=404)
+ except Exception as e:
+ return JsonResponse({'error': str(e)}, status=500)
+
+
+# Legacy view for compatibility
+@method_decorator(csrf_exempt, name='dispatch')
+class FiveWhysAnalyzerProcessView(View):
+ """Legacy process view - redirects to chat interface"""
+
+ def post(self, request):
+ return JsonResponse({
+ 'error': 'This endpoint is deprecated. Use the chat interface instead.',
+ 'redirect': '/agents/five-whys-analyzer/'
+ }, status=410)
\ No newline at end of file
diff --git a/netcop_hub/settings.py b/netcop_hub/settings.py
index cb59873..7e25461 100644
--- a/netcop_hub/settings.py
+++ b/netcop_hub/settings.py
@@ -51,6 +51,7 @@ INSTALLED_APPS = [
'data_analyzer',
'job_posting_generator',
'social_ads_generator',
+ 'five_whys_analyzer',
]
MIDDLEWARE = [
diff --git a/netcop_hub/urls.py b/netcop_hub/urls.py
index 1d7a776..48b0309 100644
--- a/netcop_hub/urls.py
+++ b/netcop_hub/urls.py
@@ -26,6 +26,7 @@ urlpatterns = [
path('agents/data-analyzer/', include('data_analyzer.urls')),
path('agents/job-posting-generator/', include('job_posting_generator.urls')),
path('agents/social-ads-generator/', include('social_ads_generator.urls')),
+ path('agents/five-whys-analyzer/', include('five_whys_analyzer.urls')),
path('', include('core.urls')),
]