Compare commits

..

No commits in common. "main" and "v1.0-working" have entirely different histories.

62 changed files with 663 additions and 14988 deletions

View File

@ -4,10 +4,6 @@ DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
# Email Verification
# Set to False to bypass email verification for testing (until final domain is ready)
REQUIRE_EMAIL_VERIFICATION=True
# Database Configuration
# Default: SQLite (simple, reliable, no setup required)
# Railway: Automatically uses PostgreSQL via DATABASE_URL

156
CLAUDE.md
View File

@ -4,15 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can access AI agent services through a web interface, with execution handled via two distinct systems: N8N webhook integrations and direct form access integrations.
Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can purchase AI agent services through a web interface, with agent execution handled via N8N webhooks and payments processed through Stripe.
**Key Architecture:**
- **Django Framework**: Main web application using Django 5.2.4
- **Agent System**: Database-driven agents app with dual integration systems:
- **Webhook Agents**: N8N integrations for complex processing
- **Direct Access Agents**: Form-based integrations (JotForm, etc.)
- **Agent System**: Database-driven agents app with marketplace and N8N webhook execution
- **Authentication**: Custom user model with email verification
- **Payments**: Stripe integration with wallet system (supports free agents)
- **Payments**: Stripe integration with wallet system
- **Database**: SQLite for development, PostgreSQL for production (Railway)
- **Static Files**: WhiteNoise for production static file serving
@ -103,27 +101,17 @@ gunicorn netcop_hub.wsgi:application
### Agent System (agents app)
**Key Files:**
- `agents/models.py`: Agent, AgentCategory, AgentExecution, ChatSession models
- `agents/views.py`: Dual integration systems and web interface views
- `agents/templates/agents/`: Dynamic agent templates and marketplace
- `agents/models.py`: Agent, AgentCategory, AgentExecution models
- `agents/views.py`: REST API and web interface views
- `agents/templates/agents/`: Dynamic agent templates with form generation
- `agents/management/commands/`: Agent creation and management commands
- `templates/career_navigator.html`: Direct access form template
**Dual Integration Systems:**
**System 1: Webhook Agents (N8N Integration)**
**Agent Flow:**
1. User browses marketplace (`/agents/`)
2. Clicks "Try Now" → Agent detail page (`/agents/{slug}/`)
3. Fills dynamic form → Form submission calls `/agents/api/execute/`
4. N8N webhook processes request and returns response
5. Results displayed with file upload support
**System 2: Direct Access Agents (Form Integration)**
1. User browses marketplace (`/agents/`)
2. Clicks special "Try Now" button → Direct access (`/agents/{slug}/access/`)
3. Payment processed → Redirect to form page (`/agents/{slug}/`)
4. Form displays embedded interface (JotForm, etc.)
5. User interacts directly with external form system
2. Selects agent and fills dynamic form (`/agents/{slug}/`)
3. Form submission creates AgentExecution and calls N8N webhook
4. N8N processes request and returns response via webhook
5. Results displayed with file upload support and real-time wallet updates
### Database Models
**User Management:**
@ -148,21 +136,30 @@ gunicorn netcop_hub.wsgi:application
- `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`: Stripe API keys
- `DATABASE_URL`: PostgreSQL connection string (Railway)
**Current System:**
The platform supports **8 total agents** across **6 categories**:
- **4 Webhook Agents** (N8N integration): Social Ads Generator, Job Posting Generator, PDF Summarizer, 5 Whys Analyzer
- **4 Direct Access Agents** (External forms): CyberSec Career Navigator, AI Brand Strategist, Lean Six Sigma Expert, SWOT Analysis Expert
**N8N Webhook URLs:**
Agent-specific webhook URLs are stored in the database with each agent. Current working agents (all tested and confirmed working):
For detailed agent information and creation instructions, see `docs/AGENT_CREATION.md`.
1. **Social Ads Generator** (social-ads-generator) - 6.00 AED
- Creates compelling social media advertisements
- Form fields: description, social_platform, include_emoji, language
- Webhook: N8N endpoint for social media ad generation
2. **Job Posting Generator** (job-posting-generator) - 10.00 AED
- Creates professional job postings
- Form fields: job_title, company_name, job_description, seniority_level, contract_type, location, language
- Webhook: N8N endpoint for job posting generation
3. **PDF Summarizer** (pdf-summarizer) - 8.00 AED
- Analyzes and summarizes PDF documents with file upload
- Form fields: pdf_file (file upload with drag-and-drop), summary_type
- Webhook: N8N endpoint for PDF processing with multipart file support
### URL Structure
```
/ # Homepage (core app)
/digital-branding/ # Digital branding services page
/auth/ # Authentication (login, register, etc.)
/agents/ # Agent marketplace (agents app)
/agents/{slug}/ # Individual agent pages (webhook agents)
/agents/{slug}/access/ # Direct access agent payment processing
/agents/{slug}/ # Individual agent pages
/wallet/ # Wallet management
/admin/ # Django admin
```
@ -180,16 +177,53 @@ For detailed agent information and creation instructions, see `docs/AGENT_CREATI
## Adding New Agents
For comprehensive agent creation instructions, see **`docs/AGENT_CREATION.md`**.
1. **Create management command** (recommended approach):
```python
# agents/management/commands/create_new_agent.py
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
**Quick Summary:**
1. Create JSON config in `agents/configs/agents/your-agent-name.json`
2. Run `python manage.py populate_agents`
3. Agent appears in marketplace automatically
class Command(BaseCommand):
def handle(self, *args, **options):
category, _ = AgentCategory.objects.get_or_create(
slug='category-slug',
defaults={'name': 'Category Name', 'icon': '🤖'}
)
Agent.objects.get_or_create(
slug='agent-slug',
defaults={
'name': 'Agent Name',
'short_description': 'Brief description',
'description': 'Full description',
'category': category,
'price': 10.0,
'form_schema': {
'fields': [
{
'name': 'input_field',
'type': 'text',
'label': 'Input Field',
'required': True
}
]
},
'webhook_url': 'http://your-n8n-webhook-url'
}
)
```
The platform supports 2 agent types:
- **Webhook Agents** - N8N integration with dynamic forms
- **Direct Access Agents** - External forms (JotForm, etc.) with embedded interfaces
2. **Run the command**: `python manage.py create_new_agent`
3. **Update N8N workflow** to handle the new agent
4. **Agent will automatically appear** in marketplace with dynamic form generation
**Supported Form Field Types:**
- `text`: Text input
- `textarea`: Multi-line text
- `select`: Dropdown with options
- `file`: File upload with drag-and-drop
- `url`: URL input with validation
- `checkbox`: Boolean checkbox
## Production Deployment
@ -236,39 +270,23 @@ The platform supports 2 agent types:
## System Status
**Current Status: ✅ STABLE COMPREHENSIVE SYSTEM**
- **8 agents** confirmed working and tested (4 webhook + 4 direct access)
- **6 categories** with clean, logical organization
- **Dual integration architecture** with clear separation and documentation
- **Streamlined agent creation** via JSON configs + `populate_agents` command
- **Scalable architecture** ready for 100+ agents
**Current Agents:**
- **Webhook Agents (4)**: Social Ads Generator, Job Posting Generator, PDF Summarizer, 5 Whys Analyzer
- **Direct Access Agents (4)**: CyberSec Career Navigator, AI Brand Strategist, Lean Six Sigma Expert, SWOT Analysis Expert
**Current Status: ✅ STABLE WORKING SYSTEM**
- All 3 agents confirmed working and tested
- Clean agents-only architecture (workflows app completely removed)
- Emergency recovery completed from optimization failures
- System restored to stable commit 657712f
**Latest Changes:**
- **Added SWOT Analysis Expert** with proper category assignment (analysis)
- **Streamlined agent creation process** to use only JSON + `populate_agents`
- **Separated documentation** into focused files (`docs/AGENT_CREATION.md`)
- **Removed 10+ redundant management commands** for cleaner codebase
- **Fixed marketplace consistency** and updated documentation
**Architecture Status:**
- **Error-free agent creation** via JSON configuration approach
- **Railway-ready deployment** with automatic agent population
- **Consistent UI standards** across all marketplace components
- **Comprehensive documentation** prevents common development mistakes
- Removed workflows app completely for simplified architecture
- Enhanced agent marketplace with modern responsive design
- Fixed all authentication-aware UI components
- Implemented file upload support for PDF Summarizer
- Real-time wallet balance updates after agent execution
**Future Development:**
- **New agents** should follow patterns in `docs/AGENT_CREATION.md`
- **Use existing categories first** to avoid unnecessary proliferation
- **JSON + populate_agents** is the only supported creation method
- Optimization work available in feature/optimization-backup branch
- Safe to add new agents via database-driven approach
- Performance optimizations should be applied incrementally with testing
---
Last updated: 2025-01-08
## Documentation
- **Quick Agent Requests**: See `docs/AGENT_REQUEST_TEMPLATE.md` for simple agent request template
- **Agent Creation**: See `docs/AGENT_CREATION.md` for comprehensive agent creation guide
- **Project Overview**: This file (CLAUDE.md) for Django development and architecture
Last updated: Last updated: 2025-08-01 01:37:09

View File

@ -1,5 +1,5 @@
from django.contrib import admin
from .models import AgentCategory, Agent, AgentExecution, ChatSession, ChatMessage
from .models import AgentCategory, Agent, AgentExecution
@admin.register(AgentCategory)
class AgentCategoryAdmin(admin.ModelAdmin):
@ -10,8 +10,8 @@ class AgentCategoryAdmin(admin.ModelAdmin):
@admin.register(Agent)
class AgentAdmin(admin.ModelAdmin):
list_display = ['name', 'category', 'agent_type', 'price', 'is_active', 'created_at']
list_filter = ['category', 'agent_type', 'is_active', 'created_at']
list_display = ['name', 'category', 'price', 'is_active', 'created_at']
list_filter = ['category', 'is_active', 'created_at']
search_fields = ['name', 'description', 'short_description']
prepopulated_fields = {'slug': ('name',)}
readonly_fields = ['created_at', 'updated_at']
@ -22,21 +22,3 @@ class AgentExecutionAdmin(admin.ModelAdmin):
list_filter = ['status', 'created_at', 'agent__category']
search_fields = ['agent__name', 'user__email']
readonly_fields = ['created_at', 'completed_at']
@admin.register(ChatSession)
class ChatSessionAdmin(admin.ModelAdmin):
list_display = ['session_id', 'agent', 'user', 'status', 'fee_charged', 'created_at']
list_filter = ['status', 'agent__category', 'created_at']
search_fields = ['session_id', 'agent__name', 'user__email']
readonly_fields = ['session_id', 'created_at', 'updated_at', 'completed_at']
@admin.register(ChatMessage)
class ChatMessageAdmin(admin.ModelAdmin):
list_display = ['session', 'message_type', 'content_preview', 'timestamp']
list_filter = ['message_type', 'timestamp']
search_fields = ['session__session_id', 'content']
readonly_fields = ['timestamp']
def content_preview(self, obj):
return obj.content[:50] + "..." if len(obj.content) > 50 else obj.content
content_preview.short_description = 'Content Preview'

View File

@ -1,113 +0,0 @@
# Agent Configuration System
This directory contains JSON configuration files for dynamically creating agents and categories in the Quantum Tasks AI platform.
## Directory Structure
```
agents/configs/
├── categories/
│ └── categories.json # All agent categories
├── agents/
│ ├── ai-brand-strategist.json # Direct access agent
│ ├── cybersec-career-navigator.json # Direct access agent
│ ├── five-whys-analysis.json # Chat webhook agent
│ ├── job-posting-generator.json # Form webhook agent
│ ├── pdf-summarizer.json # File upload webhook agent
│ └── social-ads-generator.json # Form webhook agent
└── README.md # This file
```
## How It Works
1. **Categories** are defined in `categories/categories.json`
2. **Agents** are defined in individual JSON files in `agents/`
3. Run `python manage.py populate_agents` to create all agents from configs
4. **Adding new agents** is as simple as creating a new JSON file
## Adding New Agents
### Step 1: Create JSON Configuration File
Create a new file in `agents/` directory, e.g., `email-writer.json`:
```json
{
"slug": "email-writer",
"name": "Email Writer",
"short_description": "AI-powered professional email writing assistant",
"description": "Generate professional emails for any purpose with AI assistance.",
"category": "marketing",
"price": 3.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "email_type",
"type": "select",
"label": "Email Type",
"required": true,
"options": [
{"value": "business", "label": "Business Email"},
{"value": "marketing", "label": "Marketing Email"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/email-writer",
"access_url_name": "",
"display_url_name": ""
}
```
### Step 2: Run Population Command
```bash
python manage.py populate_agents
```
### Step 3: Agent Appears Automatically
The agent will now appear in the marketplace with the configured settings.
## Agent Types
### Webhook Agents (N8N Integration)
- Set `system_type`: `"webhook"`
- Include detailed `form_schema` with fields
- Set `webhook_url` to N8N endpoint
- Leave `access_url_name` and `display_url_name` empty
### Direct Access Agents (External Forms)
- Set `system_type`: `"direct_access"`
- Set `form_schema`: `{"fields": []}`
- Set `webhook_url` to external form URL (JotForm, etc.)
- Set `access_url_name`: `"agents:direct_access_handler"`
- Set `display_url_name`: `"agents:direct_access_display"`
## Field Types for Webhook Agents
- `text`: Single-line text input
- `textarea`: Multi-line text input
- `select`: Dropdown with options array
- `file`: File upload with drag-and-drop
- `url`: URL input with validation
- `checkbox`: Boolean checkbox
## Benefits
**Scalable**: Add 100+ agents without code changes
**Version Controlled**: All agent definitions in git
**Consistent**: Ensures local and Railway databases match
**Simple**: Just create JSON file and run command
**Validated**: Built-in validation and error handling
## Railway Deployment
On Railway, just run:
```bash
python manage.py populate_agents
```
All agents defined in JSON files will be created automatically, ensuring Railway marketplace shows all agents consistently.

View File

@ -1,16 +0,0 @@
{
"slug": "ai-brand-strategist",
"name": "AI Brand Strategist",
"short_description": "Get AI-powered brand strategy insights and recommendations for your business",
"description": "Transform your brand with AI-driven strategic insights. Get expert guidance on brand positioning, messaging, visual identity, and competitive differentiation.",
"category": "marketing",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/01986502acd276b48e3d5f39337046c8d9b6",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -1,16 +0,0 @@
{
"slug": "cybersec-career-navigator",
"name": "CyberSec Career Navigator",
"short_description": "Get personalized cybersecurity career guidance from AI expert Jessica",
"description": "Navigate your cybersecurity career path with expert AI guidance. Get personalized advice on certifications, job roles, skills development, and career progression.",
"category": "career-education",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/019865a942ab7fa5b5b743a5fd2abe09e345",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -1,14 +0,0 @@
{
"slug": "five-whys-analysis",
"name": "5 Whys Analysis",
"short_description": "Interactive problem-solving using the proven 5 Whys methodology",
"description": "Systematically find root causes through guided 5 Whys methodology. Perfect for troubleshooting operational problems, understanding failures, and identifying systemic issues.",
"category": "analysis",
"price": 15.0,
"agent_type": "chat",
"system_type": "webhook",
"form_schema": null,
"webhook_url": "http://localhost:5678/webhook/5-whys-web",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -1,55 +0,0 @@
{
"slug": "job-posting-generator",
"name": "Job Posting Generator",
"short_description": "Create professional job postings that attract top talent",
"description": "Generate comprehensive and attractive job postings with AI-powered content creation. Perfect for HR teams and recruiters.",
"category": "human-resources",
"price": 10.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "job_title",
"type": "text",
"label": "Job Title",
"required": true
},
{
"name": "company_name",
"type": "text",
"label": "Company Name",
"required": true
},
{
"name": "job_description",
"type": "textarea",
"label": "Job Description",
"required": true,
"rows": 5
},
{
"name": "seniority_level",
"type": "select",
"label": "Seniority Level",
"required": true,
"options": [
{"value": "", "label": "Select level..."},
{"value": "entry", "label": "Entry Level"},
{"value": "junior", "label": "Junior"},
{"value": "mid", "label": "Mid Level"},
{"value": "senior", "label": "Senior"}
]
},
{
"name": "location",
"type": "text",
"label": "Location",
"required": true
}
]
},
"webhook_url": "http://localhost:5678/webhook/43f84411-eaaa-488c-9b1f-856e90d0aaf6",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -1,16 +0,0 @@
{
"slug": "lean-six-sigma-expert",
"name": "Lean Six Sigma Expert",
"short_description": "Get expert guidance on Lean Six Sigma methodologies and process improvement strategies",
"description": "Optimize your business processes with expert Lean Six Sigma consultation. Our AI-powered expert provides comprehensive guidance on process improvement, waste reduction, quality enhancement, and operational excellence. Get personalized recommendations for implementing Lean Six Sigma methodologies in your organization.",
"category": "consulting",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/01987b8843ae71129342f62a93d2c605efad",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -1,38 +0,0 @@
{
"slug": "pdf-summarizer",
"name": "PDF Summarizer",
"short_description": "Extract and summarize content from PDF documents with AI analysis",
"description": "Upload PDF documents and get comprehensive AI-powered summaries, key insights, and analysis. Perfect for processing reports and research papers.",
"category": "document-processing",
"price": 8.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "pdf_file",
"type": "file",
"label": "Upload PDF Document",
"required": true,
"accept": ".pdf",
"max_size": "10MB"
},
{
"name": "analysis_type",
"type": "select",
"label": "Analysis Type",
"required": true,
"default": "summary",
"options": [
{"value": "", "label": "Select analysis type..."},
{"value": "summary", "label": "Document Summary"},
{"value": "key_points", "label": "Key Points Extraction"},
{"value": "detailed_analysis", "label": "Detailed Analysis"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/simple-pdf-processor",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -1,49 +0,0 @@
{
"slug": "social-ads-generator",
"name": "Social Ads Generator",
"short_description": "Create compelling social media advertisements optimized for different platforms",
"description": "Generate engaging social media advertisements with AI-powered content generation. Optimized for Facebook, Instagram, LinkedIn, Twitter, TikTok, and YouTube.",
"category": "marketing",
"price": 6.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "description",
"type": "textarea",
"label": "Describe what you'd like to generate",
"placeholder": "Describe the product, service, or campaign",
"required": true,
"rows": 4
},
{
"name": "social_platform",
"type": "select",
"label": "For Social Media Platform",
"required": true,
"options": [
{"value": "", "label": "Select a platform..."},
{"value": "facebook", "label": "Facebook"},
{"value": "instagram", "label": "Instagram"},
{"value": "linkedin", "label": "LinkedIn"},
{"value": "twitter", "label": "X (Twitter)"}
]
},
{
"name": "include_emoji",
"type": "select",
"label": "Include Emoji",
"required": true,
"options": [
{"value": "", "label": "Select an option..."},
{"value": "yes", "label": "Yes"},
{"value": "no", "label": "No"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/2dc234d8-7217-454a-83e9-81afe5b4fe2d",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -1,16 +0,0 @@
{
"slug": "swot-analysis-expert",
"name": "SWOT Analysis Expert",
"short_description": "Strategic business analysis consultation",
"description": "Get expert SWOT analysis to evaluate your business strengths, weaknesses, opportunities, and threats with professional strategic insights.",
"category": "analysis",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/019880edcf997a41a2b4c50daa850a50a0b9",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -1,38 +0,0 @@
[
{
"slug": "analysis",
"name": "Analysis & Problem Solving",
"description": "AI-powered analysis tools for problem-solving and decision making",
"icon": "🧠"
},
{
"slug": "career-education",
"name": "Career & Education",
"description": "Professional career guidance and educational resources",
"icon": "🎓"
},
{
"slug": "document-processing",
"name": "Document Processing",
"description": "AI-powered document analysis and processing tools",
"icon": "📄"
},
{
"slug": "human-resources",
"name": "Human Resources",
"description": "HR automation and talent management solutions",
"icon": "💼"
},
{
"slug": "marketing",
"name": "Marketing & Advertising",
"description": "AI-powered marketing tools and advertising solutions",
"icon": "📢"
},
{
"slug": "consulting",
"name": "Business Consulting",
"description": "Professional business consultation and strategy services",
"icon": "💼"
}
]

View File

@ -1,30 +0,0 @@
from django.core.management.base import BaseCommand
from django.utils import timezone
from agents.models import ChatSession
class Command(BaseCommand):
help = 'Mark expired chat sessions as expired'
def handle(self, *args, **options):
now = timezone.now()
# Find active sessions that have expired
expired_sessions = ChatSession.objects.filter(
status='active',
expires_at__lt=now
)
count = expired_sessions.count()
if count > 0:
# Mark them as expired
expired_sessions.update(
status='expired',
completed_at=now
)
self.stdout.write(
self.style.SUCCESS(f'✅ Marked {count} expired sessions as expired')
)
else:
self.stdout.write('✅ No expired sessions found')

View File

@ -0,0 +1,130 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create job posting generator agent'
def handle(self, *args, **options):
# Get or use existing HR category
hr_category, created = AgentCategory.objects.get_or_create(
slug='human-resources',
defaults={
'name': 'Human Resources',
'description': 'AI-powered HR and recruitment tools',
'icon': '💼'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {hr_category.name}'))
else:
self.stdout.write(f'Category already exists: {hr_category.name}')
# Create Job Posting Generator agent
job_posting_agent, created = Agent.objects.get_or_create(
slug='job-posting-generator',
defaults={
'name': 'Job Posting Generator',
'short_description': 'Create professional job postings that attract top talent',
'description': 'Generate comprehensive and attractive job postings with AI-powered content creation. Perfect for HR teams and recruiters looking to create compelling job descriptions that attract qualified candidates. Supports multiple languages, locations, and contract types.',
'category': hr_category,
'price': 10.0,
'form_schema': {
'fields': [
{
'name': 'job_title',
'type': 'text',
'label': 'Job Title',
'placeholder': 'e.g., Senior Full Stack Developer',
'required': True,
'help_text': 'The position title for the job posting'
},
{
'name': 'company_name',
'type': 'text',
'label': 'Company Name',
'placeholder': 'e.g., Quantum Technologies Inc.',
'required': True,
'help_text': 'Name of the hiring company'
},
{
'name': 'job_description',
'type': 'textarea',
'label': 'Job Description',
'placeholder': 'Describe the role, responsibilities, and what makes this opportunity exciting...',
'required': True,
'rows': 5,
'help_text': 'Detailed description of the role, responsibilities, and company culture'
},
{
'name': 'seniority_level',
'type': 'select',
'label': 'Seniority Level',
'required': True,
'options': [
{'value': '', 'label': 'Select seniority level...'},
{'value': 'entry', 'label': 'Entry Level'},
{'value': 'junior', 'label': 'Junior'},
{'value': 'mid', 'label': 'Mid Level'},
{'value': 'senior', 'label': 'Senior'},
{'value': 'lead', 'label': 'Lead'},
{'value': 'principal', 'label': 'Principal'},
{'value': 'executive', 'label': 'Executive'}
],
'help_text': 'Experience level required for this position'
},
{
'name': 'contract_type',
'type': 'select',
'label': 'Contract Type',
'required': True,
'options': [
{'value': '', 'label': 'Select contract type...'},
{'value': 'full-time', 'label': 'Full-time'},
{'value': 'part-time', 'label': 'Part-time'},
{'value': 'contract', 'label': 'Contract'},
{'value': 'freelance', 'label': 'Freelance'},
{'value': 'internship', 'label': 'Internship'},
{'value': 'temporary', 'label': 'Temporary'}
],
'help_text': 'Type of employment contract'
},
{
'name': 'location',
'type': 'text',
'label': 'Location',
'placeholder': 'e.g., Dubai, UAE (Remote)',
'required': True,
'help_text': 'Job location, include if remote work is available'
},
{
'name': 'language',
'type': 'select',
'label': 'Language',
'required': False,
'default': 'English',
'options': [
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Primary language for the job posting'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/43f84411-eaaa-488c-9b1f-856e90d0aaf6'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {job_posting_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {job_posting_agent.name}')
self.stdout.write(self.style.SUCCESS('Job Posting Generator setup completed successfully'))
self.stdout.write(f'Agent ID: {job_posting_agent.id}')
self.stdout.write(f'Agent Slug: {job_posting_agent.slug}')
self.stdout.write(f'Price: {job_posting_agent.price} AED')

View File

@ -0,0 +1,104 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create PDF summarizer agent'
def handle(self, *args, **options):
# Get or create Document Processing category
doc_category, created = AgentCategory.objects.get_or_create(
slug='document-processing',
defaults={
'name': 'Document Processing',
'description': 'AI-powered document analysis and processing tools',
'icon': '📄'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {doc_category.name}'))
else:
self.stdout.write(f'Category already exists: {doc_category.name}')
# Create PDF Summarizer agent
pdf_summarizer_agent, created = Agent.objects.get_or_create(
slug='pdf-summarizer',
defaults={
'name': 'PDF Summarizer',
'short_description': 'Extract and summarize content from PDF documents with AI analysis',
'description': 'Upload PDF documents and get comprehensive AI-powered summaries, key insights, and analysis. Perfect for processing reports, research papers, contracts, and other documents. Supports multiple analysis types including summary, key points extraction, and sentiment analysis.',
'category': doc_category,
'price': 8.0,
'form_schema': {
'fields': [
{
'name': 'pdf_file',
'type': 'file',
'label': 'Upload PDF Document',
'required': True,
'accept': '.pdf',
'max_size': '10MB',
'help_text': 'Select a PDF file to analyze (max 10MB)'
},
{
'name': 'analysis_type',
'type': 'select',
'label': 'Analysis Type',
'required': True,
'default': 'summary',
'options': [
{'value': '', 'label': 'Select analysis type...'},
{'value': 'summary', 'label': 'Document Summary'},
{'value': 'key_points', 'label': 'Key Points Extraction'},
{'value': 'detailed_analysis', 'label': 'Detailed Analysis'},
{'value': 'sentiment', 'label': 'Sentiment Analysis'},
{'value': 'questions', 'label': 'Generate Questions'},
{'value': 'action_items', 'label': 'Extract Action Items'}
],
'help_text': 'Choose the type of analysis to perform on the document'
},
{
'name': 'language',
'type': 'select',
'label': 'Document Language',
'required': False,
'default': 'auto',
'options': [
{'value': 'auto', 'label': 'Auto-detect'},
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Specify document language for better analysis accuracy'
},
{
'name': 'output_length',
'type': 'select',
'label': 'Summary Length',
'required': False,
'default': 'medium',
'options': [
{'value': 'short', 'label': 'Short (1-2 paragraphs)'},
{'value': 'medium', 'label': 'Medium (3-5 paragraphs)'},
{'value': 'long', 'label': 'Long (detailed summary)'}
],
'help_text': 'Choose the desired length of the analysis output'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/simple-pdf-processor'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {pdf_summarizer_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {pdf_summarizer_agent.name}')
self.stdout.write(self.style.SUCCESS('PDF Summarizer setup completed successfully'))
self.stdout.write(f'Agent ID: {pdf_summarizer_agent.id}')
self.stdout.write(f'Agent Slug: {pdf_summarizer_agent.slug}')
self.stdout.write(f'Price: {pdf_summarizer_agent.price} AED')

View File

@ -0,0 +1,151 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create sample agents for testing'
def handle(self, *args, **options):
# Create categories
ai_category, _ = AgentCategory.objects.get_or_create(
slug='ai-tools',
defaults={
'name': 'AI Tools',
'description': 'AI-powered automation tools',
'icon': '🤖'
}
)
data_category, _ = AgentCategory.objects.get_or_create(
slug='data-analysis',
defaults={
'name': 'Data Analysis',
'description': 'Data processing and analysis tools',
'icon': '📊'
}
)
web_category, _ = AgentCategory.objects.get_or_create(
slug='web-scraping',
defaults={
'name': 'Web Scraping',
'description': 'Web data extraction tools',
'icon': '🕷️'
}
)
# Create sample agents
Agent.objects.get_or_create(
slug='pdf-analyzer',
defaults={
'name': 'PDF Content Analyzer',
'short_description': 'Extract and analyze content from PDF documents',
'description': 'This agent processes PDF files and extracts meaningful insights including summaries, keywords, and sentiment analysis. Perfect for document processing workflows.',
'category': ai_category,
'price': 5.00,
'form_schema': {
'fields': [
{
'name': 'pdf_url',
'type': 'url',
'label': 'PDF URL',
'placeholder': 'https://example.com/document.pdf',
'required': True
},
{
'name': 'analysis_type',
'type': 'select',
'label': 'Analysis Type',
'options': [
{'value': 'summary', 'label': 'Summary'},
{'value': 'keywords', 'label': 'Keywords'},
{'value': 'sentiment', 'label': 'Sentiment Analysis'}
],
'required': True
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/pdf-analyzer'
}
)
Agent.objects.get_or_create(
slug='website-scraper',
defaults={
'name': 'Website Data Scraper',
'short_description': 'Extract structured data from any website',
'description': 'Advanced web scraping agent that can extract specific data from websites using CSS selectors or XPath. Handles JavaScript-rendered content and returns clean, structured data.',
'category': web_category,
'price': 3.00,
'form_schema': {
'fields': [
{
'name': 'website_url',
'type': 'url',
'label': 'Website URL',
'placeholder': 'https://example.com',
'required': True
},
{
'name': 'selectors',
'type': 'textarea',
'label': 'CSS Selectors (one per line)',
'placeholder': 'h1.title\n.price\n.description',
'required': True
},
{
'name': 'wait_for_js',
'type': 'checkbox',
'label': 'Wait for JavaScript to load',
'required': False
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/website-scraper'
}
)
Agent.objects.get_or_create(
slug='data-analyzer',
defaults={
'name': 'CSV Data Analyzer',
'short_description': 'Analyze and visualize CSV data with insights',
'description': 'Upload CSV files and get comprehensive data analysis including statistics, trends, and visualizations. Perfect for business intelligence and data exploration.',
'category': data_category,
'price': 4.50,
'form_schema': {
'fields': [
{
'name': 'csv_url',
'type': 'url',
'label': 'CSV File URL',
'placeholder': 'https://example.com/data.csv',
'required': True
},
{
'name': 'analysis_columns',
'type': 'text',
'label': 'Columns to Analyze (comma-separated)',
'placeholder': 'sales,revenue,date',
'required': False
},
{
'name': 'chart_type',
'type': 'select',
'label': 'Chart Type',
'options': [
{'value': 'line', 'label': 'Line Chart'},
{'value': 'bar', 'label': 'Bar Chart'},
{'value': 'pie', 'label': 'Pie Chart'},
{'value': 'scatter', 'label': 'Scatter Plot'}
],
'required': False
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/data-analyzer'
}
)
self.stdout.write(self.style.SUCCESS('Sample agents created successfully'))
self.stdout.write(f'Created categories: {AgentCategory.objects.count()}')
self.stdout.write(f'Created agents: {Agent.objects.count()}')

View File

@ -0,0 +1,101 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create social ads agent for testing'
def handle(self, *args, **options):
# Create Marketing category
marketing_category, created = AgentCategory.objects.get_or_create(
slug='marketing',
defaults={
'name': 'Marketing & Advertising',
'description': 'AI-powered marketing and advertising tools',
'icon': '📢'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {marketing_category.name}'))
else:
self.stdout.write(f'Category already exists: {marketing_category.name}')
# Create Social Ads Generator agent
social_ads_agent, created = Agent.objects.get_or_create(
slug='social-ads-generator',
defaults={
'name': 'Social Ads Generator',
'short_description': 'Create compelling social media advertisements optimized for different platforms',
'description': 'Generate engaging social media advertisements with AI-powered content generation. Optimized for Facebook, Instagram, LinkedIn, Twitter, TikTok, and YouTube. Includes platform-specific formatting, emoji support, and multi-language capabilities.',
'category': marketing_category,
'price': 6.0,
'form_schema': {
'fields': [
{
'name': 'description',
'type': 'textarea',
'label': 'Describe what you\'d like to generate',
'placeholder': 'Describe the product, service, or campaign you want to create an ad for. Include key features, target audience, and any specific messaging you want to emphasize.',
'required': True,
'rows': 4,
'help_text': 'Provide clear, specific information about your product or service for better ad copy'
},
{
'name': 'social_platform',
'type': 'select',
'label': 'For Social Media Platform',
'required': True,
'options': [
{'value': '', 'label': 'Select a platform...'},
{'value': 'facebook', 'label': 'Facebook'},
{'value': 'instagram', 'label': 'Instagram'},
{'value': 'linkedin', 'label': 'LinkedIn'},
{'value': 'twitter', 'label': 'X (Twitter)'},
{'value': 'tiktok', 'label': 'TikTok'},
{'value': 'youtube', 'label': 'YouTube'}
],
'help_text': 'Choose the social media platform for optimization'
},
{
'name': 'include_emoji',
'type': 'select',
'label': 'Include Emoji',
'required': True,
'options': [
{'value': '', 'label': 'Select an option...'},
{'value': 'yes', 'label': 'Yes'},
{'value': 'no', 'label': 'No'}
],
'help_text': 'Whether to include emojis in the ad copy'
},
{
'name': 'language',
'type': 'select',
'label': 'Language',
'required': False,
'default': 'English',
'options': [
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Select the primary language for the ad copy'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/2dc234d8-7217-454a-83e9-81afe5b4fe2d'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {social_ads_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {social_ads_agent.name}')
self.stdout.write(self.style.SUCCESS('Social Ads Agent setup completed successfully'))
self.stdout.write(f'Agent ID: {social_ads_agent.id}')
self.stdout.write(f'Agent Slug: {social_ads_agent.slug}')
self.stdout.write(f'Price: {social_ads_agent.price} AED')

View File

@ -1,142 +0,0 @@
import json
import os
from pathlib import Path
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Dynamically populate all agents and categories from JSON configuration files'
def handle(self, *args, **options):
self.stdout.write(self.style.SUCCESS('🚀 Dynamically populating agents from configuration files...'))
self.stdout.write('')
# Track creation statistics
categories_created = 0
agents_created = 0
config_base_path = Path(__file__).parent.parent.parent / 'configs'
# Load and create categories
categories_file = config_base_path / 'categories' / 'categories.json'
if not categories_file.exists():
self.stdout.write(self.style.ERROR(f'❌ Categories file not found: {categories_file}'))
return
with open(categories_file, 'r', encoding='utf-8') as f:
categories_data = json.load(f)
categories = {}
for category_data in categories_data:
category, created = AgentCategory.objects.get_or_create(
slug=category_data['slug'],
defaults={
'name': category_data['name'],
'description': category_data['description'],
'icon': category_data['icon']
}
)
categories[category_data['slug']] = category
if created:
categories_created += 1
self.stdout.write(f'✅ Created category: {category.name}')
else:
self.stdout.write(f' Category exists: {category.name}')
self.stdout.write('')
# Load and create agents from JSON files
agents_dir = config_base_path / 'agents'
if not agents_dir.exists():
self.stdout.write(self.style.ERROR(f'❌ Agents directory not found: {agents_dir}'))
return
# Get all JSON files in agents directory
agent_files = list(agents_dir.glob('*.json'))
if not agent_files:
self.stdout.write(self.style.WARNING('⚠️ No agent configuration files found'))
return
self.stdout.write(f'📁 Found {len(agent_files)} agent configuration files')
self.stdout.write('')
# Process each agent configuration file
for agent_file in sorted(agent_files):
try:
with open(agent_file, 'r', encoding='utf-8') as f:
agent_data = json.load(f)
# Validate required fields
required_fields = ['slug', 'name', 'category', 'price', 'agent_type']
missing_fields = [field for field in required_fields if field not in agent_data]
if missing_fields:
self.stdout.write(self.style.ERROR(f'❌ Missing fields in {agent_file.name}: {missing_fields}'))
continue
# Get category
category_slug = agent_data['category']
if category_slug not in categories:
self.stdout.write(self.style.ERROR(f'❌ Unknown category "{category_slug}" in {agent_file.name}'))
continue
category = categories[category_slug]
# Create agent
agent, created = Agent.objects.get_or_create(
slug=agent_data['slug'],
defaults={
'name': agent_data['name'],
'short_description': agent_data.get('short_description', ''),
'description': agent_data.get('description', ''),
'category': category,
'price': agent_data['price'],
'agent_type': agent_data['agent_type'],
'form_schema': agent_data.get('form_schema'),
'webhook_url': agent_data.get('webhook_url', ''),
'access_url_name': agent_data.get('access_url_name', ''),
'display_url_name': agent_data.get('display_url_name', '')
}
)
if created:
agents_created += 1
system_type = agent_data.get('system_type', 'webhook')
self.stdout.write(f'✅ Created agent: {agent.name} ({system_type.title()})')
self.stdout.write(f' 💰 Price: {agent.price} AED')
self.stdout.write(f' 📁 Config: {agent_file.name}')
else:
self.stdout.write(f' Agent exists: {agent.name} (from {agent_file.name})')
except json.JSONDecodeError as e:
self.stdout.write(self.style.ERROR(f'❌ Invalid JSON in {agent_file.name}: {e}'))
continue
except Exception as e:
self.stdout.write(self.style.ERROR(f'❌ Error processing {agent_file.name}: {e}'))
continue
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('🎉 Dynamic population completed successfully!'))
self.stdout.write('')
self.stdout.write(f'📊 Summary:')
self.stdout.write(f' Categories created: {categories_created}')
self.stdout.write(f' Agents created: {agents_created}')
self.stdout.write(f' Configuration files processed: {len(agent_files)}')
self.stdout.write('')
# Final verification
total_categories = AgentCategory.objects.filter(is_active=True).count()
total_agents = Agent.objects.filter(is_active=True).count()
webhook_agents = Agent.objects.filter(is_active=True, access_url_name='').count()
direct_agents = Agent.objects.filter(is_active=True).exclude(access_url_name='').count()
self.stdout.write(f'🔍 Final verification:')
self.stdout.write(f' Total categories: {total_categories}')
self.stdout.write(f' Total agents: {total_agents}')
self.stdout.write(f' Webhook agents: {webhook_agents}')
self.stdout.write(f' Direct access agents: {direct_agents}')
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('✅ Database is now consistent and ready!'))
self.stdout.write('')
self.stdout.write('🚀 To add new agents:')
self.stdout.write(' 1. Create new JSON file in agents/configs/agents/')
self.stdout.write(' 2. Run this command again')
self.stdout.write(' 3. Agent will automatically appear in marketplace!')

View File

@ -1,160 +0,0 @@
# Generated by Django 5.2.4 on 2025-08-01 04:01
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name="agent",
name="agent_type",
field=models.CharField(
choices=[("form", "Form-based"), ("chat", "Chat-based")],
default="form",
help_text="Agent interaction type",
max_length=10,
),
),
migrations.AlterField(
model_name="agent",
name="form_schema",
field=models.JSONField(
blank=True, help_text="JSON schema for agent input form", null=True
),
),
migrations.CreateModel(
name="ChatSession",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"session_id",
models.CharField(
help_text="Unique session identifier",
max_length=100,
unique=True,
),
),
(
"status",
models.CharField(
choices=[
("active", "Active"),
("completed", "Completed"),
("abandoned", "Abandoned"),
("failed", "Failed"),
],
default="active",
max_length=20,
),
),
(
"context_data",
models.JSONField(
default=dict, help_text="Session context and progress tracking"
),
),
("fee_charged", models.DecimalField(decimal_places=2, max_digits=10)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("completed_at", models.DateTimeField(blank=True, null=True)),
(
"agent",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="chat_sessions",
to="agents.agent",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"ordering": ["-created_at"],
},
),
migrations.CreateModel(
name="ChatMessage",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"message_type",
models.CharField(
choices=[
("user", "User Message"),
("agent", "Agent Response"),
("system", "System Message"),
],
max_length=10,
),
),
("content", models.TextField()),
(
"metadata",
models.JSONField(
default=dict,
help_text="Additional message data like webhook responses",
),
),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"session",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="messages",
to="agents.chatsession",
),
),
],
options={
"ordering": ["timestamp"],
},
),
migrations.AddIndex(
model_name="chatsession",
index=models.Index(
fields=["session_id"], name="agents_chat_session_0d9cb4_idx"
),
),
migrations.AddIndex(
model_name="chatsession",
index=models.Index(
fields=["user", "-created_at"], name="agents_chat_user_id_f8983d_idx"
),
),
migrations.AddIndex(
model_name="chatmessage",
index=models.Index(
fields=["session", "timestamp"], name="agents_chat_session_e8eaed_idx"
),
),
]

View File

@ -1,40 +0,0 @@
# Generated by Django 5.2.4 on 2025-08-01 10:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"agents",
"0002_agent_agent_type_alter_agent_form_schema_chatsession_and_more",
),
]
operations = [
migrations.AddField(
model_name="chatsession",
name="expires_at",
field=models.DateTimeField(
blank=True,
help_text="Session expiration time (2 hours from last activity)",
null=True,
),
),
migrations.AlterField(
model_name="chatsession",
name="status",
field=models.CharField(
choices=[
("active", "Active"),
("completed", "Completed"),
("expired", "Expired"),
("abandoned", "Abandoned"),
("failed", "Failed"),
],
default="active",
max_length=20,
),
),
]

View File

@ -1,21 +0,0 @@
# Generated by Django 5.2.4 on 2025-08-03 04:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0003_chatsession_expires_at_alter_chatsession_status"),
]
operations = [
migrations.AddField(
model_name="agent",
name="message_limit",
field=models.IntegerField(
default=50,
help_text="Maximum messages per chat session (for chat agents)",
),
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 5.2.4 on 2025-08-04 11:05
from django.db import migrations
def fake_migration(apps, schema_editor):
"""
Fake migration - Railway database already has access_url_name and display_url_name columns
but Django model didn't have them defined. Now model has fields, so we just need to
mark this migration as applied without doing anything.
"""
pass
class Migration(migrations.Migration):
dependencies = [
("agents", "0004_add_message_limit"),
]
operations = [
migrations.RunPython(fake_migration, fake_migration),
]

View File

@ -1,42 +0,0 @@
# Generated by Django 5.2.4 on 2025-08-04 17:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0005_auto_20250804_1105"),
]
operations = [
migrations.AddField(
model_name="agent",
name="access_url_name",
field=models.CharField(
blank=True,
default="",
help_text="URL name for direct access agents",
max_length=100,
),
),
migrations.AddField(
model_name="agent",
name="display_url_name",
field=models.CharField(
blank=True,
default="",
help_text="URL name for agent display page",
max_length=100,
),
),
migrations.AlterField(
model_name="chatsession",
name="expires_at",
field=models.DateTimeField(
blank=True,
help_text="Session expiration time (30 minutes from last activity)",
null=True,
),
),
]

View File

@ -17,11 +17,6 @@ class AgentCategory(models.Model):
return self.name
class Agent(models.Model):
AGENT_TYPE_CHOICES = [
('form', 'Form-based'),
('chat', 'Chat-based'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
@ -29,12 +24,8 @@ class Agent(models.Model):
description = models.TextField()
category = models.ForeignKey(AgentCategory, on_delete=models.CASCADE, related_name='agents')
price = models.DecimalField(max_digits=10, decimal_places=2)
agent_type = models.CharField(max_length=10, choices=AGENT_TYPE_CHOICES, default='form', help_text="Agent interaction type")
form_schema = models.JSONField(help_text="JSON schema for agent input form", null=True, blank=True)
form_schema = models.JSONField(help_text="JSON schema for agent input form")
webhook_url = models.URLField(help_text="n8n webhook URL for execution")
message_limit = models.IntegerField(default=50, help_text="Maximum messages per chat session (for chat agents)")
access_url_name = models.CharField(max_length=100, blank=True, default='', help_text="URL name for direct access agents")
display_url_name = models.CharField(max_length=100, blank=True, default='', help_text="URL name for agent display page")
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@ -71,79 +62,3 @@ class AgentExecution(models.Model):
def __str__(self):
return f"{self.agent.name} - {self.user.email} - {self.status}"
class ChatSession(models.Model):
STATUS_CHOICES = [
('active', 'Active'),
('completed', 'Completed'),
('expired', 'Expired'),
('abandoned', 'Abandoned'),
('failed', 'Failed'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session_id = models.CharField(max_length=100, unique=True, help_text="Unique session identifier")
agent = models.ForeignKey(Agent, on_delete=models.CASCADE, related_name='chat_sessions')
user = models.ForeignKey('authentication.User', on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
context_data = models.JSONField(default=dict, help_text="Session context and progress tracking")
fee_charged = models.DecimalField(max_digits=10, decimal_places=2)
expires_at = models.DateTimeField(null=True, blank=True, help_text="Session expiration time (30 minutes from last activity)")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
completed_at = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
# Set expires_at to 30 minutes from now if not set
if not self.expires_at:
from django.utils import timezone
from datetime import timedelta
self.expires_at = timezone.now() + timedelta(minutes=30)
super().save(*args, **kwargs)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['session_id']),
models.Index(fields=['user', '-created_at']),
]
def __str__(self):
return f"{self.agent.name} - {self.user.email} - {self.session_id}"
def is_expired(self):
from django.utils import timezone
if not self.expires_at:
return False # Sessions without expiration date are considered active
return timezone.now() > self.expires_at
def extend_session(self):
"""Extend session by 30 minutes from now"""
from django.utils import timezone
from datetime import timedelta
self.expires_at = timezone.now() + timedelta(minutes=30)
self.updated_at = timezone.now()
self.save()
class ChatMessage(models.Model):
MESSAGE_TYPE_CHOICES = [
('user', 'User Message'),
('agent', 'Agent Response'),
('system', 'System Message'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session = models.ForeignKey(ChatSession, on_delete=models.CASCADE, related_name='messages')
message_type = models.CharField(max_length=10, choices=MESSAGE_TYPE_CHOICES)
content = models.TextField()
metadata = models.JSONField(default=dict, help_text="Additional message data like webhook responses")
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['timestamp']
indexes = [
models.Index(fields=['session', 'timestamp']),
]
def __str__(self):
return f"{self.session.session_id} - {self.message_type} - {self.timestamp}"

File diff suppressed because it is too large Load Diff

View File

@ -39,42 +39,7 @@ document.body.setAttribute('data-user-balance', '{{ user.wallet_balance }}');
</h3>
</div>
<div class="widget-content">
{% if agent.access_url_name and agent.display_url_name %}
<!-- Direct Access Agent - External Form -->
<div class="direct-access-info">
<div class="section-container">
<h4 class="section-subtitle">{{ agent.category.icon }} {{ agent.name }} - External Consultation</h4>
<p style="color: #6b7280; margin-bottom: var(--spacing-lg);">
This consultation will redirect you to our specialized external form for personalized guidance.
</p>
{% if user.is_authenticated %}
{% if agent.price == 0 %}
<a href="{% url 'agents:direct_access_handler' agent.slug %}" class="btn btn-primary btn-full">
{{ agent.category.icon }} Start {{ agent.name }} Consultation (FREE)
</a>
{% elif user.wallet_balance >= agent.price %}
<a href="{% url 'agents:direct_access_handler' agent.slug %}" class="btn btn-primary btn-full">
{{ agent.category.icon }} Start {{ agent.name }} Consultation ({{ agent.price }} AED)
</a>
{% else %}
<div style="background: #fef2f2; color: #dc2626; padding: var(--spacing-md); border-radius: var(--radius-md); margin-bottom: var(--spacing-md); font-size: 14px; font-weight: 500; text-align: center;">
Insufficient balance! You need {{ agent.price }} AED.
</div>
<a href="{% url 'wallet:wallet' %}" class="btn btn-primary btn-full" style="text-decoration: none;">
💰 Top Up Wallet
</a>
{% endif %}
{% else %}
<a href="{% url 'authentication:login' %}" class="btn btn-primary btn-full">
🔐 Login to Continue
</a>
{% endif %}
</div>
</div>
{% else %}
<!-- Webhook Agent - Dynamic Form -->
<form id="agentForm" method="POST" enctype="multipart/form-data" data-agent-id="{{ agent.id }}">
<form id="agentForm" method="POST" enctype="multipart/form-data" data-agent-id="{{ agent.id }}">
{% csrf_token %}
<!-- Dynamic Form Fields -->
@ -202,7 +167,6 @@ document.body.setAttribute('data-user-balance', '{{ user.wallet_balance }}');
{% endif %}
</div>
</form>
{% endif %}
</div>
</div>

View File

@ -6,9 +6,6 @@
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/agent-base.css' %}">
<link rel="stylesheet" href="{% static 'css/marketplace.css' %}">
<style>
/* All Try Now buttons now use consistent styling from marketplace.css */
</style>
{% endblock %}
{% block content %}
@ -52,11 +49,12 @@
<!-- Stats -->
<div class="marketplace-stats">
{% if search_query %}
Search results for "{{ search_query }}"
{% if selected_category %} • {{ selected_category|capfirst }} category{% endif %}
{% elif selected_category %}
{{ selected_category|capfirst }} category
Search results for "{{ search_query }}" •
{% endif %}
{% if selected_category %}
{{ selected_category|capfirst }} category •
{% endif %}
{{ agents.count }} agent{{ agents.count|pluralize }} available
</div>
<!-- Agents Grid -->
@ -74,47 +72,12 @@
<p class="agent-description">{{ agent.short_description }}</p>
<div class="agent-footer">
{% if user.is_authenticated %}
{% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'agents:career_navigator_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'ai-brand-strategist' %}
<a href="{% url 'agents:ai_brand_strategist_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'lean-six-sigma-expert' %}
<a href="{% url 'agents:lean_six_sigma_expert_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'swot-analysis-expert' %}
<a href="{% url 'agents:swot_analysis_expert_access' %}" class="try-btn">
Try Now →
</a>
{% else %}
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
{% endif %}
<span class="agent-category">{{ agent.category.name }}</span>
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
{% else %}
{% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:career_navigator_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% elif agent.slug == 'ai-brand-strategist' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:ai_brand_strategist_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% elif agent.slug == 'lean-six-sigma-expert' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:lean_six_sigma_expert_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% elif agent.slug == 'swot-analysis-expert' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:swot_analysis_expert_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% else %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% endif %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% endif %}
</div>
</div>

View File

@ -7,36 +7,13 @@ urlpatterns = [
# Web interface
path('', views.agents_marketplace, name='marketplace'),
# Direct access routes
path('career-navigator/', views.career_navigator_view, name='career_navigator'),
path('career-navigator/access/', views.career_navigator_access, name='career_navigator_access'),
path('ai-brand-strategist/', views.ai_brand_strategist_view, name='ai_brand_strategist'),
path('ai-brand-strategist/access/', views.ai_brand_strategist_access, name='ai_brand_strategist_access'),
path('lean-six-sigma-expert/', views.lean_six_sigma_expert_view, name='lean_six_sigma_expert'),
path('lean-six-sigma-expert/access/', views.lean_six_sigma_expert_access, name='lean_six_sigma_expert_access'),
path('swot-analysis-expert/', views.swot_analysis_expert_view, name='swot_analysis_expert'),
path('swot-analysis-expert/access/', views.swot_analysis_expert_access, name='swot_analysis_expert_access'),
# API endpoints - specific URLs first to avoid slug conflicts
path('api/execute/', views.execute_agent, name='execute_agent'),
path('api/executions/', views.execution_list, name='execution_list'),
path('api/executions/<uuid:execution_id>/', views.execution_detail, name='execution_detail'),
# Chat API endpoints
path('api/chat/start/', views.start_chat_session, name='start_chat_session'),
path('api/chat/send/', views.send_chat_message, name='send_chat_message'),
path('api/chat/history/<str:session_id>/', views.get_chat_history, name='get_chat_history'),
path('api/chat/session/<str:session_id>/status/', views.get_session_status, name='get_session_status'),
path('api/chat/end/', views.end_chat_session, name='end_chat_session'),
path('api/chat/export/<str:session_id>/', views.export_chat, name='export_chat'),
path('api/', views.agent_list, name='agent_list'),
path('api/<slug:slug>/', views.agent_detail, name='agent_detail_api'),
# Generic direct access routes (must be before agent detail)
path('<slug:slug>/access/', views.direct_access_handler, name='direct_access_handler'),
path('<slug:slug>/display/', views.direct_access_display, name='direct_access_display'),
# Agent detail page (must be last to avoid conflicts)
path('<slug:slug>/', views.agent_detail_view, name='detail'),
]

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ def validate_password_strength(password):
is_common = password.lower() in common_passwords
if not (has_length and has_lower and has_upper and has_digit and has_special) or is_common:
return ["Password must have 8+ characters, uppercase, lowercase, number, and special character"]
return ["Password must be at least 8 characters with uppercase, lowercase, number, and special character"]
return []
@ -89,17 +89,10 @@ def handle_ratelimited(request, exception):
@ratelimit(key='ip', rate='5/m', method=UNSAFE, block=False)
def login_view(request):
"""User login view with rate limiting (5 attempts per minute per IP)"""
# Handle post-login session messages
if 'post_login_message' in request.session:
messages.info(request, request.session.pop('post_login_message'))
# Check if rate limited
if getattr(request, 'limited', False):
# Use session to avoid repeated rate limit messages
if not request.session.get('rate_limit_shown'):
logger.warning(f"Login rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.error(request, 'Too many login attempts. Please wait before trying again.')
request.session['rate_limit_shown'] = True
logger.warning(f"Login rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.error(request, 'Too many login attempts. Please try again in a few minutes.')
return render(request, 'authentication/login.html')
if request.method == 'POST':
@ -108,16 +101,12 @@ def login_view(request):
user = authenticate(request, username=email, password=password)
if user is not None:
# Check if email is verified (only if email verification is required)
if settings.REQUIRE_EMAIL_VERIFICATION and not user.email_verified:
# Check if email is verified
if not user.email_verified:
messages.warning(request, 'Please verify your email address before logging in. Check your inbox for the verification link.')
# Store resend URL in context for template
context = {'show_resend_verification': True}
return render(request, 'authentication/login.html', context)
return render(request, 'authentication/login.html')
login(request, user)
# Clear rate limit flag on successful login
request.session.pop('rate_limit_shown', None)
# Redirect to 'next' parameter if provided, otherwise homepage
next_url = request.GET.get('next') or request.POST.get('next')
if next_url:
@ -125,8 +114,6 @@ def login_view(request):
return redirect('core:homepage')
else:
messages.error(request, 'Invalid email or password')
# Clear rate limit flag on any POST attempt (failed login)
request.session.pop('rate_limit_shown', None)
return render(request, 'authentication/login.html')
@ -167,25 +154,15 @@ def register_view(request):
email=email,
password=password1
)
# Don't automatically login - require email verification first
# Handle email verification based on settings
if settings.REQUIRE_EMAIL_VERIFICATION:
# Don't automatically login - require email verification first
# Send verification email
if send_verification_email(user):
messages.success(request, 'Account created. Check your email to verify.')
else:
messages.warning(request, 'Account created. Email verification failed - try again later.')
return redirect('authentication:login')
# Send verification email
if send_verification_email(user):
messages.success(request, 'Account created successfully! Please check your email to verify your account.')
else:
# Skip email verification - auto-verify and login
user.email_verified = True
user.save()
login(request, user)
messages.success(request, f'Welcome {user.username}!')
return redirect('core:homepage')
messages.warning(request, 'Account created but verification email could not be sent. You can request a new one after logging in.')
return redirect('authentication:login')
except Exception as e:
logger.error(f"Error creating account for {email}: {str(e)}")
messages.error(request, 'Error creating account')
@ -196,6 +173,7 @@ def register_view(request):
def logout_view(request):
"""User logout view"""
logout(request)
messages.success(request, 'You have been logged out successfully')
return redirect('core:homepage')
@ -347,7 +325,7 @@ def reset_password_view(request, token):
# Mark token as used
reset_token.mark_as_used()
messages.success(request, 'Password reset. You can now log in.')
messages.success(request, 'Your password has been reset successfully. You can now log in.')
return redirect('authentication:login')
return render(request, 'authentication/reset_password.html', {'token': token})
@ -369,7 +347,7 @@ def verify_email_view(request, token):
# Mark token as used
verification_token.mark_as_used()
messages.success(request, 'Email verified. You can now log in.')
messages.success(request, 'Email verified successfully! You can now log in.')
return redirect('authentication:login')
@ -394,7 +372,7 @@ def resend_verification_view(request):
# Send new verification email
if send_verification_email(user):
messages.success(request, 'Verification email sent.')
messages.success(request, 'Verification email sent. Please check your inbox.')
else:
messages.error(request, 'Unable to send verification email at this time.')

View File

@ -5,9 +5,7 @@ app_name = 'core'
urlpatterns = [
path('', views.homepage_view, name='homepage'),
path('digital-branding/', views.digital_branding_view, name='digital_branding'),
path('pricing/', views.pricing_view, name='pricing'),
path('contact/', views.contact_form_view, name='contact_form'),
path('event/', views.event_view, name='event'),
path('health/', views.health_check_view, name='health_check'),
]

View File

@ -39,30 +39,30 @@ def homepage_view(request):
return render(request, 'core/homepage.html', {'featured_agents': [], 'user_balance': 0})
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def pricing_view(request):
"""Pricing page - redirect to marketplace"""
# Redirect all pricing page access to the AI marketplace
return redirect('agents:marketplace')
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def digital_branding_view(request):
"""Digital branding services page with rate limiting"""
"""Pricing page for non-logged-in users with rate limiting"""
# Check if rate limited
if getattr(request, 'limited', False):
logger.warning(f"Digital branding page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
logger.warning(f"Pricing page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.warning(request, 'Too many requests. Please wait a moment before refreshing.')
# If user is already logged in, redirect to wallet top-up
if request.user.is_authenticated:
return redirect('wallet:wallet_topup')
try:
# Get sample agents to show pricing context from database
sample_agents = Agent.objects.filter(is_active=True).select_related('category')[:4]
context = {
'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0,
'sample_agents': sample_agents,
}
return render(request, 'core/digital_branding.html', context)
return render(request, 'core/pricing.html', context)
except Exception as e:
logger.error(f"Digital branding view error: {e}")
messages.error(request, 'Unable to load digital branding page. Please try again.')
return render(request, 'core/digital_branding.html', {})
logger.error(f"Pricing view error: {e}")
messages.error(request, 'Unable to load pricing page. Please try again.')
return render(request, 'core/pricing.html', {'sample_agents': []})
def validate_contact_input(name, email, message, company=""):
@ -214,22 +214,6 @@ def contact_form_view(request):
}, status=500)
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def event_view(request):
"""Event page view"""
# Check if rate limited
if getattr(request, 'limited', False):
logger.warning(f"Event page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.warning(request, 'Too many requests. Please wait a moment before refreshing.')
context = {
'form_url': 'https://form.jotform.com/252214924850455',
'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0,
}
return render(request, 'core/event.html', context)
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def health_check_view(request):
"""Simplified health check endpoint - no database dependency for startup"""

View File

@ -1,302 +0,0 @@
# Agent Creation Guide
This guide provides comprehensive instructions for adding new agents to the Quantum Tasks AI platform.
## Overview
Quantum Tasks AI supports **TWO DISTINCT AGENT SYSTEMS**:
- **Webhook Agents** - N8N integrations for complex processing with dynamic forms
- **Direct Access Agents** - External form services (JotForm, Google Forms) with embedded interfaces
**⚡ RECOMMENDED APPROACH:** Use JSON configuration + `populate_agents` command for error-free, Railway-ready agent creation.
---
## Current Agent Status
**Total Agents: 8** (4 webhook + 4 direct access)
**Total Categories: 6**
### Webhook Agents (N8N Integration)
1. **Social Ads Generator** - 6.00 AED - Creates social media advertisements
2. **Job Posting Generator** - 10.00 AED - Creates professional job postings
3. **PDF Summarizer** - 8.00 AED - Analyzes and summarizes PDF documents
4. **5 Whys Analyzer** - 15.00 AED - Interactive chat-based root cause analysis
### Direct Access Agents (External Forms)
1. **CyberSec Career Navigator** - FREE - Career guidance consultation
2. **AI Brand Strategist** - FREE - Brand strategy consultation
3. **Lean Six Sigma Expert** - FREE - Process improvement consultation
4. **SWOT Analysis Expert** - FREE - Strategic business analysis
---
## 🏷️ Choose Existing Category First
**IMPORTANT:** Always use existing categories before creating new ones to avoid category proliferation.
### Available Categories:
- 🧠 **`analysis`** - Problem-solving, SWOT analysis, strategic analysis tools
- 🎓 **`career-education`** - Career guidance, educational resources, professional development
- 📄 **`document-processing`** - PDF analysis, file processing, document tools
- 💼 **`human-resources`** - Job postings, HR automation, talent management
- 📢 **`marketing`** - Social ads, branding, content marketing, advertising
- 💼 **`consulting`** - Business consultation, strategy services, expert advice
**Only create new categories when absolutely necessary and logically distinct.**
---
## 🚀 Agent Creation Workflow
### System 1: Webhook Agents (N8N Integration)
- **Use for:** Dynamic forms, server-side processing, file uploads, complex workflows
- **Examples:** Social Ads Generator, PDF Summarizer, Job Posting Generator
- **Flow:** Marketplace → Agent detail page → Dynamic form → N8N webhook → Results
### System 2: Direct Access Agents (External Forms)
- **Use for:** External form services (JotForm, Google Forms), consultation interfaces
- **Examples:** SWOT Analysis Expert, CyberSec Career Navigator, AI Brand Strategist
- **Flow:** Marketplace → Payment processing → Quantum Tasks header + embedded external form
---
## 📝 Implementation Steps
### Step 1: Create JSON Configuration
Create a new file in `agents/configs/agents/your-agent-name.json`:
#### Webhook Agent Example:
```json
{
"slug": "content-optimizer",
"name": "Content Optimizer",
"short_description": "AI-powered content optimization and enhancement",
"description": "Enhance your content for better engagement with AI-powered optimization suggestions, tone analysis, and improvement recommendations.",
"category": "marketing",
"price": 5.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "content",
"type": "textarea",
"label": "Content to Optimize",
"required": true
},
{
"name": "content_type",
"type": "select",
"label": "Content Type",
"required": true,
"options": [
{"value": "blog", "label": "Blog Post"},
{"value": "social", "label": "Social Media"},
{"value": "email", "label": "Email Marketing"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/content-optimizer",
"access_url_name": "",
"display_url_name": ""
}
```
#### Direct Access Agent Example:
```json
{
"slug": "business-strategist",
"name": "Business Strategist",
"short_description": "Expert business strategy consultation",
"description": "Get professional business strategy insights and recommendations from experienced consultants to grow your business effectively.",
"category": "consulting",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/your-form-id",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}
```
### Step 2: Run populate_agents Command
```bash
# Development
source venv/bin/activate
python manage.py populate_agents
# Production (Railway)
python manage.py populate_agents # Runs automatically on deployment
```
### Step 3: Additional Setup (Direct Access Agents Only)
For direct access agents that need custom templates or marketplace integration:
#### 3a. Create Custom Template (optional):
```html
<!-- templates/your_agent_name.html -->
{% extends 'base.html' %}
{% load static %}
{% block title %}Your Agent Name - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
.main-container { max-width: none; padding: 0; height: calc(100vh - 80px); }
.iframe-container { width: 100%; height: 100%; }
.iframe-container iframe { width: 100%; height: 100%; border: none; display: block; }
.footer { display: none !important; }
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe src="{{ form_url }}" frameborder="0" scrolling="auto" title="Your Agent Name"></iframe>
</div>
{% endblock %}
```
#### 3b. Add Custom Views (if needed):
Add view functions to `agents/views.py` following the pattern of existing direct access agents.
#### 3c. Add URL Routes (if needed):
Add routes to `agents/urls.py` following the pattern of existing direct access agents.
#### 3d. Update Marketplace Template (if needed):
Add button logic to `agents/templates/agents/marketplace.html` for custom marketplace behavior.
**⚠️ Important**: Keep all "Try Now" buttons consistent with the format `Try Now →` (no icons or emojis).
### Step 4: Setup External Services
#### For Webhook Agents:
- Create N8N workflow at the webhook URL
- Configure webhook to accept JSON payload with `sessionId`, `message`, etc.
#### For Direct Access Agents:
- Create external form (JotForm, Google Forms, etc.)
- Ensure form URL is accessible and properly configured
---
## ✅ Benefits of This Approach
- ✅ **Single source of truth** - JSON configs define everything
- ✅ **Railway-ready immediately** - No manual database setup needed
- ✅ **Error-free** - No category creation mistakes or typos
- ✅ **Consistent** - All agents use same reliable creation process
- ✅ **Scalable** - Easy to add 100+ agents
- ✅ **Version controlled** - Configs are tracked in git
---
## 🔧 Supported Form Field Types (Webhook Agents)
- `text` - Single-line text input
- `textarea` - Multi-line text input
- `select` - Dropdown with options array
- `file` - File upload with drag-and-drop
- `url` - URL input with validation
- `checkbox` - Boolean checkbox
---
## ⚠️ Common Mistakes to Avoid
1. **Creating unnecessary categories** - Use existing ones first
2. **Missing system_type** - Include "webhook" or "direct_access"
3. **Wrong access_url_name** - Empty for webhook agents, populated for direct access
4. **Forgetting populate_agents** - Run after creating JSON config
5. **Complex custom commands** - Use JSON + populate_agents instead
6. **Adding icons to Try Now buttons** - Keep all marketplace buttons consistent with "Try Now →" format
---
## 🔄 Agent Management Commands
### Essential Commands:
```bash
# Populate all agents from JSON configs (main command)
python manage.py populate_agents
# Clean up expired chat sessions
python manage.py cleanup_expired_sessions
```
### Development Workflow:
1. Create JSON config file
2. Run `populate_agents`
3. Test agent functionality
4. Commit changes to git
5. Deploy to Railway (auto-runs populate_agents)
---
## 📊 Agent Configuration Reference
### Required JSON Fields:
- `slug` - URL-friendly identifier (kebab-case)
- `name` - Display name
- `short_description` - Brief description for marketplace
- `description` - Full description with details
- `category` - Must match existing category slug
- `price` - Price in AED (0.0 for free agents)
- `agent_type` - Always "form"
- `system_type` - "webhook" or "direct_access"
### System-Specific Fields:
#### Webhook Agents:
- `form_schema` - JSON schema defining form fields
- `webhook_url` - N8N webhook endpoint
- `access_url_name` - Empty string ""
- `display_url_name` - Empty string ""
#### Direct Access Agents:
- `form_schema` - Usually `{"fields": []}`
- `webhook_url` - External form URL (JotForm, etc.)
- `access_url_name` - "agents:direct_access_handler"
- `display_url_name` - "agents:direct_access_display"
---
## 🚀 Railway Deployment
When you commit changes to the repository:
1. ✅ **Railway auto-deploys** new code
2. ✅ **populate_agents runs automatically** on deployment
3. ✅ **New agents appear** in production marketplace
4. ✅ **Categories are created** if needed (but use existing ones first!)
5. ✅ **No manual database work** required
---
## 📞 Support & Documentation
- **Main Documentation**: See `CLAUDE.md` for project overview
- **Agent Issues**: Check Railway logs and database for agent status
- **Form Problems**: Verify external form URLs are accessible
- **Category Issues**: Use existing categories from the list above
---
## 🚀 Quick Agent Request
**For fast agent creation**, use the **Agent Request Template**:
👉 **See `docs/AGENT_REQUEST_TEMPLATE.md`** for a simple template to request new agents
Simply fill out the template and provide it to Claude Code for instant agent creation!
---
*Last updated: 2025-01-08*

View File

@ -1,135 +0,0 @@
# Agent Request Template
Use this template when requesting new agents to ensure all necessary information is provided for quick, error-free agent creation.
## How to Use This Template
1. **Copy the template below**
2. **Fill in all required fields**
3. **Provide to Claude Code** with the request "Create agent using this template"
4. **Claude will handle** JSON config creation, populate_agents execution, and deployment
---
## Agent Request Template
```markdown
## New Agent Request
**Agent Name**: [Enter the display name for the agent]
**Type**: [Webhook OR Direct Access]
**Category**: [Choose from: analysis, career-education, document-processing, human-resources, marketing, consulting]
**Price**: [X.XX AED or 0.0 for FREE]
**Short Description**: [Brief 1-line description for marketplace]
**Full Description**: [Detailed description of what the agent does and its benefits]
### For Webhook Agents Only:
**Form Fields**:
- Field 1: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
- Field 2: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
- [Add more fields as needed]
**N8N Webhook URL**: [Your N8N webhook endpoint URL]
### For Direct Access Agents Only:
**External Form URL**: [JotForm, Google Forms, or other external form URL]
**Custom Template Needed**: [Yes/No - specify if you need custom styling/layout]
**Custom Views Needed**: [Yes/No - specify if you need special marketplace behavior]
### Optional Information:
**Special Requirements**: [Any unique features or customizations needed]
**Integration Notes**: [Any special setup or configuration details]
```
---
## Available Categories
**Choose from these existing categories** (avoid creating new ones):
- 🧠 **`analysis`** - Problem-solving, SWOT analysis, strategic analysis tools
- 🎓 **`career-education`** - Career guidance, educational resources, professional development
- 📄 **`document-processing`** - PDF analysis, file processing, document tools
- 💼 **`human-resources`** - Job postings, HR automation, talent management
- 📢 **`marketing`** - Social ads, branding, content marketing, advertising
- 💼 **`consulting`** - Business consultation, strategy services, expert advice
---
## Form Field Types (Webhook Agents)
- **`text`** - Single-line text input
- **`textarea`** - Multi-line text input
- **`select`** - Dropdown (requires options array)
- **`file`** - File upload with drag-and-drop
- **`url`** - URL input with validation
- **`checkbox`** - Boolean true/false
---
## Example Requests
### Example 1: Webhook Agent
```markdown
## New Agent Request
**Agent Name**: Email Campaign Optimizer
**Type**: Webhook
**Category**: marketing
**Price**: 4.0 AED
**Short Description**: AI-powered email campaign optimization and A/B testing
**Full Description**: Optimize your email campaigns with AI analysis of subject lines, content, and send times. Get recommendations for better open rates and conversions.
### Form Fields:
- Field 1: [name: email_subject, type: text, label: "Email Subject Line", required: true]
- Field 2: [name: email_content, type: textarea, label: "Email Content", required: true]
- Field 3: [name: target_audience, type: select, label: "Target Audience", required: true, options: [{"value": "b2b", "label": "Business"}, {"value": "b2c", "label": "Consumer"}]]
**N8N Webhook URL**: http://localhost:5678/webhook/email-optimizer
```
### Example 2: Direct Access Agent
```markdown
## New Agent Request
**Agent Name**: Financial Planning Consultant
**Type**: Direct Access
**Category**: consulting
**Price**: 0.0 AED
**Short Description**: Professional financial planning and investment consultation
**Full Description**: Get expert financial advice tailored to your goals. Our certified financial planners provide personalized investment strategies and retirement planning.
### For Direct Access Agents:
**External Form URL**: https://agent.jotform.com/financial-planning-form-id
**Custom Template Needed**: No
**Custom Views Needed**: No
```
---
## What Happens Next
After you provide the completed template:
1. ✅ **Claude creates JSON config** in `agents/configs/agents/`
2. ✅ **Runs populate_agents command** to add agent to database
3. ✅ **Agent appears in marketplace** automatically
4. ✅ **Creates any needed templates/views** (for Direct Access agents)
5. ✅ **Updates marketplace integration** if needed
6. ✅ **Commits changes** and makes them Railway-ready
**No additional work needed on your part!** 🚀
---
## Tips for Better Requests
- ✅ **Use existing categories** - Avoid creating new ones unless absolutely necessary
- ✅ **Be specific** - Clear descriptions help users understand the agent's value
- ✅ **Test external forms** - Ensure JotForm/external URLs are working before requesting
- ✅ **Consider pricing** - Free agents get more usage, paid agents need clear value proposition
- ✅ **Think about fields** - For webhook agents, plan your form fields carefully
---
*For comprehensive agent creation details, see `docs/AGENT_CREATION.md`*

View File

@ -1,10 +1,10 @@
=== Documentation Auto-Update Summary ===
Update Date: 2025-08-01 09:23:11
Update Date: 2025-08-01 01:37:22
Recent Commits:
- 11d28a1 📚 Update documentation after GitHub push
- f6970b6 🎨 Complete Phase 1 UI optimization with button hover fixes
- 277e7ec 📄 Auto-update documentation timestamp after security fixes
- c8ad34f 🔒 Implement critical security fixes for production readiness
- 657712f 🗑️ Remove workflows app completely and streamline to agents-only
Documentation Changes:
- CLAUDE.md

File diff suppressed because it is too large Load Diff

View File

@ -61,10 +61,6 @@ if config('RAILWAY_ENVIRONMENT', default=''):
else:
SITE_URL = config('SITE_URL', default='http://localhost:8000')
# Email verification requirement
# Set to False for testing environments until final domain is ready
REQUIRE_EMAIL_VERIFICATION = config('REQUIRE_EMAIL_VERIFICATION', default=True, cast=bool)
# Application definition

View File

@ -4,7 +4,7 @@
"builder": "NIXPACKS"
},
"deploy": {
"startCommand": "python manage.py migrate; python manage.py populate_agents; python manage.py reset_admin; python manage.py verify_email admin@quantumtaskai.com --force || true; python manage.py collectstatic --noinput && gunicorn netcop_hub.wsgi:application --bind 0.0.0.0:$PORT --workers 1 --timeout 60",
"startCommand": "python manage.py migrate --run-syncdb; python manage.py populate_agents; python manage.py reset_admin; python manage.py verify_email admin@quantumtaskai.com --force || true; python manage.py collectstatic --noinput && gunicorn netcop_hub.wsgi:application --bind 0.0.0.0:$PORT --workers 1 --timeout 60",
"restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 3
},

View File

@ -8,7 +8,6 @@ gunicorn==21.2.0
psycopg2-binary==2.9.9
dj-database-url==2.1.0
whitenoise==6.8.2
reportlab==4.2.5
# Optional performance dependencies
redis==5.2.0

View File

@ -89,7 +89,7 @@ html {
/* Layout - Data Analyzer Exact Copy */
.agent-container {
margin: 0 auto;
padding: var(--spacing-sm);
padding: var(--spacing-lg);
max-width: 1600px;
}
@ -99,7 +99,7 @@ html {
border-radius: var(--radius);
padding: var(--space-lg);
border: var(--agent-card-border);
margin-bottom: var(--space-md);
margin-bottom: var(--space-lg);
backdrop-filter: var(--agent-backdrop-filter);
box-shadow: var(--agent-card-shadow);
}
@ -1207,7 +1207,7 @@ html {
/* Agent Grid and Layout System */
.agent-grid {
display: flex;
gap: var(--spacing-sm);
gap: var(--spacing-lg);
align-items: flex-start;
flex-wrap: wrap;
}
@ -1216,7 +1216,7 @@ html {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
margin-bottom: var(--spacing-xl);
}
/* Typography - Data Analyzer Exact Copy */

View File

@ -1,652 +0,0 @@
/* Digital Branding Services Page Styles */
/* Following homepage.css patterns and using unified color system from base.css */
/* Hero Section - matches homepage hero */
.digital-branding-hero {
position: relative;
background: var(--gradient-hero);
overflow: hidden;
min-height: 85vh;
display: flex;
align-items: center;
padding: clamp(40px, 10vw, 80px) clamp(16px, 4vw, 24px) clamp(60px, 15vw, 100px);
}
.hero-container {
max-width: 1280px;
margin: 0 auto;
text-align: center;
position: relative;
z-index: 10;
width: 100%;
}
.trust-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(59, 130, 246, 0.08);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 2.5rem;
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
border: 1px solid rgba(59, 130, 246, 0.15);
backdrop-filter: blur(10px);
}
.trust-badge-emoji {
font-size: 0.75rem;
}
.hero-title {
font-weight: 800;
margin-bottom: 2.5rem;
line-height: 1.1;
letter-spacing: -0.02em;
font-size: clamp(36px, 8vw, 110px);
margin-bottom: clamp(24px, 6vw, 40px);
}
.hero-title-gradient {
background: var(--gradient-primary);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-title-normal {
color: var(--text-primary);
}
.hero-description {
color: var(--text-secondary);
margin-bottom: 3.5rem;
max-width: 720px;
margin-left: auto;
margin-right: auto;
line-height: 1.7;
font-weight: 400;
font-size: clamp(1.1rem, 3vw, 1.4rem);
margin-bottom: clamp(32px, 8vw, 56px);
padding: 0 clamp(8px, 2vw, 16px);
}
.hero-buttons {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 5rem;
gap: clamp(12px, 3vw, 20px);
margin-bottom: clamp(40px, 10vw, 80px);
padding: 0 clamp(8px, 2vw, 16px);
}
.btn-primary {
background: var(--gradient-primary);
color: white;
border-radius: 1rem;
font-weight: bold;
border: none;
cursor: pointer;
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.25), 0 4px 12px rgba(0, 0, 0, 0.05);
letter-spacing: 0.01em;
text-align: center;
text-decoration: none;
display: inline-block;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.4);
filter: brightness(1.1);
}
.btn-primary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.btn-secondary {
background: var(--background-card);
color: var(--primary-blue);
border-radius: 1rem;
font-weight: 600;
border: 2px solid var(--border-light);
text-decoration: none;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(59, 130, 246, 0.08);
letter-spacing: 0.01em;
display: inline-block;
text-align: center;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-secondary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.15);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
}
.btn-secondary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.12);
}
.trust-indicators {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
gap: clamp(16px, 4vw, 48px);
max-width: 600px;
margin: 0 auto;
padding: 0 clamp(8px, 2vw, 16px);
}
.trust-card {
text-align: center;
background: rgba(255, 255, 255, 0.5);
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.03);
border-radius: 1rem;
padding: clamp(16px, 4vw, 24px) clamp(12px, 3vw, 16px);
}
.trust-number {
background: var(--text-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 800;
margin-bottom: 0.5rem;
font-size: clamp(1rem, 3vw, 1.2rem);
}
.trust-text {
color: var(--text-secondary);
font-weight: 500;
letter-spacing: 0.01em;
font-size: clamp(12px, 3vw, 15px);
}
/* Why Choose Us Section - matches company profile */
.why-choose-us {
position: relative;
background: var(--company-gradient);
overflow: hidden;
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.section-container {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 10;
}
.section-header {
text-align: center;
margin-bottom: clamp(40px, 10vw, 80px);
}
.section-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(30, 64, 175, 0.1);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 1.5rem;
border: 1px solid rgba(30, 64, 175, 0.2);
}
.section-badge-icon {
font-size: 1rem;
}
.section-badge-text {
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
}
.section-title {
font-weight: 800;
color: var(--primary-blue);
margin-bottom: 1rem;
text-align: center;
font-size: clamp(2rem, 5vw, 3.5rem);
}
.section-subtitle {
font-size: 1.25rem;
color: var(--text-light);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.why-choose-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(24px, 6vw, 40px);
}
.choice-card {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 40px);
transition: all 0.2s ease;
}
.choice-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3.5rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.choice-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.choice-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 18px);
}
/* Our Process Section - matches services */
.our-process {
background: var(--services-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.process-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
margin-bottom: clamp(40px, 10vw, 60px);
}
.process-step-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 32px);
display: flex;
align-items: flex-start;
gap: clamp(16px, 4vw, 20px);
transition: all 0.2s ease;
}
.step-number {
background: var(--gradient-primary);
color: white;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: clamp(16px, 4vw, 20px);
flex-shrink: 0;
}
.step-content {
flex: 1;
}
.step-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 0.75rem;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.step-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* RACE Framework */
.race-framework {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 12px 40px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.race-title {
text-align: center;
font-weight: bold;
color: var(--primary-blue);
margin-bottom: clamp(20px, 5vw, 32px);
font-size: clamp(1.3rem, 4vw, 1.8rem);
}
.race-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
gap: clamp(16px, 4vw, 24px);
}
.race-card {
text-align: center;
background: var(--background-light);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
transition: all 0.2s ease;
}
.race-phase {
margin-bottom: 0.75rem;
}
.race-icon {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-bottom: 0.5rem;
display: block;
}
.race-phase h4 {
font-weight: bold;
color: var(--primary-blue);
margin: 0;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.race-focus {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.race-actions {
color: var(--text-light);
font-size: clamp(12px, 3vw, 14px);
line-height: 1.5;
}
/* Branding Services Section - matches services */
.branding-services {
background: var(--clients-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.services-title {
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
}
.services-subtitle {
text-align: center;
color: var(--text-light);
margin-bottom: 3rem;
font-size: clamp(16px, 4vw, 20px);
margin-bottom: clamp(24px, 6vw, 48px);
}
.branding-services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
}
.service-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 32px);
transition: all 0.2s ease;
}
.service-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.service-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.4rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.service-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* CTA Section - matches contact */
.branding-cta {
background: var(--contact-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.cta-container {
max-width: 1200px;
margin: 0 auto;
}
.cta-title {
font-weight: bold;
text-align: center;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
margin-bottom: clamp(24px, 6vw, 48px);
}
.cta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(350px, 100%), 1fr));
gap: clamp(30px, 8vw, 60px);
align-items: start;
}
.cta-content {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-content-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.3rem, 4vw, 1.6rem);
}
.cta-description {
color: var(--text-light);
line-height: 1.6;
margin-bottom: 1.5rem;
font-size: clamp(14px, 3.5vw, 18px);
}
.cta-features {
margin-bottom: 2rem;
}
.cta-feature {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.feature-icon {
color: var(--success-green);
font-weight: bold;
}
.cta-buttons {
display: flex;
flex-direction: column;
gap: clamp(12px, 3vw, 16px);
}
.cta-btn {
padding: clamp(14px, 4vw, 16px) clamp(20px, 5vw, 24px);
border-radius: clamp(8px, 2vw, 12px);
font-weight: 600;
text-decoration: none;
text-align: center;
font-size: clamp(14px, 3.5vw, 16px);
transition: all 0.2s ease;
min-height: 48px;
display: flex;
align-items: center;
justify-content: center;
}
.cta-btn.primary {
background: var(--gradient-primary);
color: white;
box-shadow: 0 4px 16px rgba(59, 130, 246, 0.25);
}
.cta-btn.primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);
}
.cta-btn.secondary {
background: var(--background-card);
color: var(--primary-blue);
border: 2px solid var(--border-light);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
}
.cta-btn.secondary:hover {
transform: translateY(-2px);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.15);
}
.cta-info {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-info-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1.5rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(16px, 4vw, 24px);
}
.contact-item {
display: flex;
align-items: flex-start;
gap: clamp(12px, 3vw, 16px);
margin-bottom: clamp(20px, 5vw, 32px);
}
.contact-icon {
background: var(--primary-gradient);
border-radius: clamp(8px, 2vw, 12px);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
font-size: clamp(16px, 4vw, 20px);
}
.contact-details h4 {
font-weight: 600;
color: var(--primary-blue);
margin-bottom: 0.5rem;
font-size: clamp(16px, 4vw, 19px);
}
.contact-details p {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
.contact-email {
color: var(--primary-blue);
text-decoration: none;
}
.contact-email:hover {
text-decoration: underline;
}
.commitment-statement {
background: var(--services-gradient);
border-left: 4px solid var(--primary-blue);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
margin-top: clamp(20px, 5vw, 32px);
}
.commitment-text {
color: var(--primary-blue);
font-weight: 600;
text-align: center;
font-size: clamp(14px, 3.5vw, 18px);
line-height: 1.6;
}
/* Loading state for buttons */
.cta-btn.loading {
opacity: 0.7;
pointer-events: none;
}
/* Mobile responsive adjustments */
@media (max-width: 767px) {
.cta-buttons {
flex-direction: column;
}
.process-step-card {
flex-direction: column;
text-align: center;
}
.step-number {
margin: 0 auto 1rem auto;
}
.race-grid {
grid-template-columns: 1fr;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

View File

@ -478,109 +478,6 @@ class AgentsCore extends WorkflowsCore {
return isValid;
}
/**
* Handle JotForm agent execution (CyberSec Career Navigator)
*/
async handleJotFormAgent() {
// Check authentication and balance
if (!this.constructor.checkAuthentication()) return;
if (!this.constructor.checkBalance(this.price)) return;
const submitBtn = document.getElementById('generateBtn');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.textContent = '⏳ Processing Payment...';
}
try {
// Create execution record and charge wallet via form API
const response = await fetch('/agents/api/form/access/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
agent_slug: this.agentSlug
})
});
if (response.ok) {
const result = await response.json();
// Update wallet balance
this.constructor.updateWalletBalance(result.new_balance);
// Show white-label interface
this.showWhiteLabelInterface(result.interface_url);
this.constructor.showToast('✅ Payment processed! Access granted to Quantum AI Career Navigator', 'success');
} else {
const error = await response.json();
throw new Error(error.error || 'Failed to process payment');
}
} catch (error) {
console.error('Form agent error:', error);
this.constructor.showToast(`${error.message}`, 'error');
this.resetSubmitButton();
}
}
/**
* Show white-label interface in results container
*/
showWhiteLabelInterface(interfaceUrl) {
const resultsContainer = document.getElementById('resultsContainer');
const resultsContent = document.getElementById('resultsContent');
if (resultsContainer && resultsContent) {
// Update header
const widgetTitle = resultsContainer.querySelector('.widget-title');
if (widgetTitle) {
widgetTitle.innerHTML = '<span class="widget-icon">🎓</span>Quantum AI Career Navigator';
}
// Create white-label interface
resultsContent.innerHTML = `
<div class="career-nav-container" style="text-align: center; margin-bottom: 20px;">
<h3 style="color: #0369a1; margin-bottom: 10px;">🎓 Quantum AI Career Navigator</h3>
<p style="color: #6b7280; margin-bottom: 20px;">Meet Jessica, your personal AI cybersecurity career advisor. Share your goals and get expert guidance tailored to your journey.</p>
</div>
<div class="career-interface-container" style="width: 100%; min-height: 600px; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.1);">
<iframe
src="${interfaceUrl}"
style="width: 100%; min-height: 600px; border: none; background: white;"
frameborder="0"
scrolling="auto"
title="Quantum AI Career Navigator - Your Personal Career Advisor">
</iframe>
</div>
<div class="career-footer" style="margin-top: 20px; padding: 15px; background: #f8fafc; border-radius: 8px; text-align: center;">
<p style="color: #6b7280; font-size: 14px; margin: 0;">
💡 <strong>Pro Tip:</strong> Be specific about your experience level and career goals for the most personalized advice from your AI advisor!
</p>
</div>
`;
// Hide action buttons since this is an interactive interface
const actionButtons = resultsContainer.querySelector('.results-actions');
if (actionButtons) {
actionButtons.style.display = 'none';
}
// Show results container
resultsContainer.style.display = 'block';
// Scroll to results
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
// Reset submit button
this.resetSubmitButton();
}
}
/**
* Reset submit button to original state
*/

View File

@ -1,43 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}AI Brand Strategist - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="AI Brand Strategist">
</iframe>
</div>
{% endblock %}

View File

@ -104,37 +104,6 @@
text-decoration: underline;
}
.verification-actions {
text-align: center;
margin-bottom: var(--spacing-lg);
padding: var(--spacing-md);
background: var(--surface-variant);
border-radius: var(--radius-sm);
border: 1px solid var(--outline);
}
.verification-text {
margin: 0 0 var(--spacing-sm) 0;
color: var(--on-surface-variant);
font-size: 14px;
}
.btn-outline {
background: transparent;
border: 1px solid var(--primary);
color: var(--primary);
}
.btn-outline:hover {
background: var(--primary);
color: var(--on-primary);
}
.btn-sm {
padding: var(--spacing-xs) var(--spacing-md);
font-size: 14px;
}
/* Responsive */
@media (max-width: 480px) {
.login-page {
@ -168,13 +137,6 @@
</div>
{% endif %}
{% if show_resend_verification %}
<div class="verification-actions">
<p class="verification-text">Need to resend verification email?</p>
<a href="{% url 'authentication:resend_verification' %}" class="btn btn-outline btn-sm">Resend Verification</a>
</div>
{% endif %}
<form method="post" class="login-form">
{% csrf_token %}
{% if request.GET.next %}
@ -214,6 +176,7 @@
<div class="login-auth-links">
<p><a href="{% url 'authentication:forgot_password' %}">Forgot your password?</a></p>
<p><a href="{% url 'authentication:resend_verification' %}">Resend email verification</a></p>
<p>Don't have an account? <a href="{% url 'authentication:register' %}">Create account</a></p>
</div>
</div>

View File

@ -6,35 +6,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Quantum Tasks AI - AI Platform{% endblock %}</title>
<!-- SEO Meta Tags -->
<meta name="description" content="{% block description %}Quantum Tasks AI - Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta name="keywords" content="AI, artificial intelligence, automation, AI agents, machine learning, productivity, business tools">
<meta name="author" content="Quantum Tasks AI">
<!-- Open Graph Meta Tags for Rich Link Previews -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="Quantum Tasks AI">
<meta property="og:title" content="{% block og_title %}Quantum Tasks AI - AI Platform{% endblock %}">
<meta property="og:description" content="{% block og_description %}Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta property="og:url" content="{% block og_url %}https://quantumtaskai.com{{ request.get_full_path }}{% endblock %}">
<meta property="og:image" content="{% block og_image %}https://quantumtaskai.com{% static 'img/og-image.png' %}{% endblock %}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Quantum Tasks AI - AI Agent Marketplace">
<!-- Twitter Card Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@quantumtaskai">
<meta name="twitter:title" content="{% block twitter_title %}Quantum Tasks AI - AI Platform{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta name="twitter:image" content="{% block twitter_image %}https://quantumtaskai.com{% static 'img/og-image.png' %}{% endblock %}">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}">
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'img/apple-touch-icon.png' %}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'img/favicon-32x32.png' %}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'img/favicon-16x16.png' %}">
<!-- Unified Font Loading - Single Source of Truth -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@ -59,8 +30,8 @@
</a>
<nav class="header-nav" id="header-nav">
<a href="{% url 'core:homepage' %}" class="nav-link {% if request.resolver_match.url_name == 'homepage' %}active{% endif %}">Home</a>
<a href="{% url 'core:digital_branding' %}" class="nav-link {% if request.resolver_match.url_name == 'digital_branding' %}active{% endif %}">AI Digital Branding</a>
<a href="{% url 'agents:marketplace' %}" class="nav-link {% if request.resolver_match.url_name == 'marketplace' %}active{% endif %}">AI Marketplace</a>
<a href="{% url 'core:pricing' %}" class="nav-link {% if request.resolver_match.url_name == 'pricing' %}active{% endif %}">Pricing</a>
</nav>
<button class="mobile-nav-toggle" onclick="toggleMobileNav()" aria-label="Toggle navigation">

View File

@ -1,43 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Career Navigator - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Career Navigator">
</iframe>
</div>
{% endblock %}

View File

@ -1,119 +0,0 @@
{% if chat_session %}
<div class="agent-widget widget-small" style="min-width: min(280px, 100%); max-width: min(280px, 100%); margin-left: auto;">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">💬</span>
Current Session
</h3>
</div>
<div class="widget-content">
<div class="current-session-info">
<div class="session-status-row">
<span class="status-label">Status:</span>
<span class="session-status status-{{ chat_session.status }}">
{% if chat_session.status == 'active' %}
✅ {{ chat_session.get_status_display }}
{% elif chat_session.status == 'expired' %}
⏰ {{ chat_session.get_status_display }}
{% elif chat_session.status == 'completed' %}
🏁 {{ chat_session.get_status_display }}
{% else %}
{{ chat_session.get_status_display }}
{% endif %}
</span>
</div>
<div class="session-id-row">
<span class="id-label">Session ID:</span>
<span class="session-id">{{ chat_session.session_id }}</span>
</div>
<div class="session-time-row">
<span class="time-label">Started:</span>
<span class="session-time">{{ chat_session.created_at|date:"M d, H:i" }}</span>
</div>
</div>
</div>
</div>
<style>
.current-session-info {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.session-status-row,
.session-id-row,
.session-time-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-xs) 0;
border-bottom: 1px solid var(--outline-variant);
}
.session-status-row:last-child,
.session-id-row:last-child,
.session-time-row:last-child {
border-bottom: none;
}
.status-label,
.id-label,
.time-label {
font-size: 13px;
font-weight: 500;
color: var(--on-surface-variant);
}
.session-status {
font-size: 13px;
font-weight: 600;
display: flex;
align-items: center;
gap: 4px;
}
.session-status.status-active {
color: #10b981;
}
.session-status.status-expired {
color: #f59e0b;
}
.session-status.status-completed {
color: #6366f1;
}
.session-id {
font-family: var(--font-mono);
font-size: 11px;
color: var(--on-surface-variant);
background: var(--surface-variant);
padding: 2px 6px;
border-radius: 3px;
word-break: break-all;
}
.session-time {
font-size: 12px;
color: var(--on-surface);
}
@media (max-width: 768px) {
.session-id-row {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.session-id {
font-size: 10px;
align-self: stretch;
text-align: center;
}
}
</style>
{% endif %}

View File

@ -1,206 +0,0 @@
{% if previous_sessions %}
<div class="agent-widget widget-small" style="min-width: min(280px, 100%); max-width: min(280px, 100%); margin-left: auto;">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">📋</span>
Previous Sessions
</h3>
</div>
<div class="widget-content">
{% for session in previous_sessions %}
<div class="session-item">
<div class="session-header">
<div class="session-info">
<span class="session-status status-{{ session.status }}">
{% if session.status == 'completed' %}✅{% elif session.status == 'expired' %}⏰{% elif session.status == 'abandoned' %}❌{% endif %}
{{ session.get_status_display }}
</span>
<span class="session-date">{{ session.created_at|date:"M d" }}</span>
</div>
<div class="session-stats">
<span class="message-count">{{ session.user_message_count }}/{{ session.agent.message_limit }} msgs</span>
</div>
</div>
{% if session.user_message_count > 0 and session.status != 'active' %}
<div class="session-actions">
<div class="download-actions">
<a href="{% url 'agents:export_chat' session.session_id %}?format=pdf"
class="download-link pdf-link"
title="Download PDF">
📄 PDF
</a>
<a href="{% url 'agents:export_chat' session.session_id %}?format=txt"
class="download-link txt-link"
title="Download TXT">
📝 TXT
</a>
</div>
</div>
{% endif %}
</div>
{% endfor %}
{% if previous_sessions|length >= 5 %}
<div class="view-all-sessions">
<a href="#" class="view-all-link" onclick="alert('Full session history coming soon!')">
View All Sessions →
</a>
</div>
{% endif %}
</div>
</div>
<style>
.session-item {
padding: var(--spacing-sm);
border: 1px solid var(--outline-variant);
border-radius: var(--radius-sm);
margin-bottom: var(--spacing-sm);
background: var(--surface);
transition: all 0.2s ease;
}
.session-item:hover {
background: var(--surface-variant);
border-color: var(--primary);
}
.session-item:last-child {
margin-bottom: 0;
}
.session-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--spacing-xs);
}
.session-info {
display: flex;
flex-direction: column;
gap: 2px;
}
.session-status {
font-size: 12px;
font-weight: 600;
display: flex;
align-items: center;
gap: 4px;
}
.session-status.status-completed {
color: var(--success);
}
.session-status.status-expired {
color: var(--warning);
}
.session-status.status-abandoned {
color: var(--error);
}
.session-date {
font-size: 11px;
color: var(--on-surface-variant);
}
.session-stats {
text-align: right;
}
.message-count {
font-size: 11px;
color: var(--on-surface-variant);
background: var(--surface-variant);
padding: 2px 6px;
border-radius: 3px;
}
.session-actions {
border-top: 1px solid var(--outline-variant);
padding-top: var(--spacing-xs);
}
.download-actions {
display: flex;
gap: var(--spacing-sm);
justify-content: center;
}
.download-link {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: var(--primary);
color: white;
text-decoration: none;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
transition: all 0.2s ease;
flex: 1;
justify-content: center;
}
.download-link:hover {
background: var(--primary-dark);
transform: translateY(-1px);
color: white;
text-decoration: none;
}
.download-link.pdf-link {
background: #dc2626;
}
.download-link.pdf-link:hover {
background: #b91c1c;
}
.download-link.txt-link {
background: var(--primary);
}
.download-link.txt-link:hover {
background: var(--primary-dark);
}
.view-all-sessions {
margin-top: var(--spacing-sm);
text-align: center;
border-top: 1px solid var(--outline-variant);
padding-top: var(--spacing-sm);
}
.view-all-link {
font-size: 12px;
color: var(--primary);
text-decoration: none;
font-weight: 500;
}
.view-all-link:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.session-header {
flex-direction: column;
gap: var(--spacing-xs);
}
.session-stats {
text-align: left;
}
.download-actions {
flex-direction: column;
}
}
</style>
{% endif %}

View File

@ -7,23 +7,29 @@
</div>
<div class="quick-agents-grid">
{% for agent in all_agents %}
{% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'agents:career_navigator_access' %}" class="quick-agent-card">
{% else %}
<a href="{% url 'agents:detail' agent.slug %}" class="quick-agent-card">
{% endif %}
<div class="agent-icon">{{ agent.category.icon }}</div>
<div class="agent-info">
<h4>{{ agent.name }}</h4>
<div class="agent-price">{{ agent.price }} AED</div>
</div>
</a>
{% empty %}
<p style="text-align: center; color: var(--on-surface-variant); padding: 20px;">
No other agents available
</p>
{% endfor %}
<a href="/agents/social-ads-generator/" class="quick-agent-card">
<div class="agent-icon">📢</div>
<div class="agent-info">
<h4>Social Ads Generator</h4>
<p>Create social media ads</p>
</div>
</a>
<a href="/agents/job-posting-generator/" class="quick-agent-card">
<div class="agent-icon">💼</div>
<div class="agent-info">
<h4>Job Posting Generator</h4>
<p>Create professional job posts</p>
</div>
</a>
<a href="/agents/pdf-summarizer/" class="quick-agent-card">
<div class="agent-icon">📄</div>
<div class="agent-info">
<h4>PDF Summarizer</h4>
<p>Analyze and summarize PDFs</p>
</div>
</a>
</div>
<div class="quick-agents-footer">

View File

@ -1,200 +0,0 @@
{% if chat_session and messages %}
<div class="session-indicators">
<h4 class="session-indicators-title">Session Status</h4>
<!-- Time Remaining Indicator -->
<div class="indicator-item">
<div class="indicator-header">
<span class="indicator-icon"></span>
<span class="indicator-label">Time Remaining</span>
<span class="indicator-value" id="timeRemaining">
{% if time_remaining %}
{{ time_remaining }}
{% else %}
Calculating...
{% endif %}
</span>
</div>
<div class="progress-bar">
<div class="progress-fill time-progress" id="timeProgress" style="width: {{ time_percentage|default:100 }}%"></div>
</div>
</div>
<!-- Messages Remaining Indicator -->
<div class="indicator-item">
<div class="indicator-header">
<span class="indicator-icon">💬</span>
<span class="indicator-label">Messages</span>
<span class="indicator-value" id="messageCount">
{{ message_count|default:0 }}/{{ message_limit }} used
</span>
</div>
<div class="progress-bar">
<div class="progress-fill message-progress" id="messageProgress" style="width: {{ message_percentage|default:0 }}%"></div>
</div>
</div>
<!-- Warning Messages -->
<div class="session-warnings" id="sessionWarnings">
{% if time_percentage <= 20 %}
<div class="warning-item time-warning">
⚠️ Session expires soon!
</div>
{% endif %}
{% if message_percentage >= 80 %}
<div class="warning-item message-warning">
⚠️ Approaching message limit!
</div>
{% endif %}
</div>
</div>
<style>
.session-indicators {
background: var(--surface);
border: 1px solid var(--outline-variant);
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
margin-bottom: var(--spacing-md);
box-shadow: var(--shadow-sm);
min-width: min(280px, 100%);
max-width: min(280px, 100%);
margin-left: auto;
}
.session-indicators-title {
font-size: 16px;
font-weight: 600;
color: var(--on-surface);
margin: 0 0 var(--spacing-md) 0;
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.indicator-item {
margin-bottom: var(--spacing-md);
}
.indicator-item:last-of-type {
margin-bottom: 0;
}
.indicator-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--spacing-xs);
}
.indicator-icon {
font-size: 16px;
}
.indicator-label {
font-size: 14px;
font-weight: 500;
color: var(--on-surface);
flex: 1;
margin-left: var(--spacing-sm);
}
.indicator-value {
font-size: 13px;
font-weight: 600;
color: var(--on-surface-variant);
}
.progress-bar {
width: 100%;
height: 6px;
background: var(--surface-variant);
border-radius: 3px;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 3px;
transition: width 0.3s ease, background-color 0.3s ease;
}
.time-progress {
background: linear-gradient(90deg, #10b981, #059669);
}
.time-progress[style*="width: 0"],
.time-progress[style*="width: 1"],
.time-progress[style*="width: 2"] {
background: linear-gradient(90deg, #ef4444, #dc2626);
}
.time-progress[style*="width: 3"],
.time-progress[style*="width: 4"],
.time-progress[style*="width: 5"],
.time-progress[style*="width: 10"],
.time-progress[style*="width: 15"],
.time-progress[style*="width: 20"] {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.message-progress {
background: linear-gradient(90deg, #3b82f6, #2563eb);
}
.message-progress[style*="width: 8"],
.message-progress[style*="width: 9"] {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.message-progress[style*="width: 95"],
.message-progress[style*="width: 96"],
.message-progress[style*="width: 97"],
.message-progress[style*="width: 98"],
.message-progress[style*="width: 99"],
.message-progress[style*="width: 100"] {
background: linear-gradient(90deg, #ef4444, #dc2626);
}
.session-warnings {
margin-top: var(--spacing-md);
}
.warning-item {
background: #fef3c7;
color: #92400e;
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-sm);
font-size: 13px;
font-weight: 500;
margin-bottom: var(--spacing-xs);
border-left: 3px solid #f59e0b;
}
.warning-item:last-child {
margin-bottom: 0;
}
.time-warning {
background: #fee2e2;
color: #991b1b;
border-left-color: #ef4444;
}
@media (max-width: 768px) {
.session-indicators {
padding: var(--spacing-md);
}
.indicator-header {
flex-wrap: wrap;
gap: var(--spacing-xs);
}
.indicator-value {
flex-basis: 100%;
text-align: right;
}
}
</style>
{% endif %}

View File

@ -1,523 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}AI Digital Branding Services - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/digital-branding.css' %}">
{% endblock %}
{% block content %}
<style>
/* Override main-container for full-width sections */
.main-container {
max-width: none;
padding: 0;
}
</style>
<!-- Hero Section -->
<section id="digital-branding-hero" class="digital-branding-hero">
<div class="hero-container">
<!-- Trust Badge -->
<div class="trust-badge">
<span class="trust-badge-emoji"></span>
<span>Trusted Digital Brand Partner</span>
</div>
<h1 class="hero-title">
<span class="hero-title-gradient">
AI-Powered Digital Branding
</span>
<br />
<span class="hero-title-normal">
Intelligence
</span>
</h1>
<p class="hero-description">
Elevate Your Brand with Intelligent Digital Strategies. Combine proven marketing expertise with AI automation to accelerate growth, optimize performance, and deliver measurable results that matter.
</p>
<!-- CTA Buttons -->
<div class="hero-buttons">
{% if user.is_authenticated %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Start Discovery
</a>
<a href="#our-process" class="btn-secondary">
View Process
</a>
{% else %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Get Started
</a>
<a href="#our-process" class="btn-secondary">
Learn More
</a>
{% endif %}
</div>
<!-- Trust Indicators -->
<div class="trust-indicators">
<div class="trust-card">
<div class="trust-number">
250%
</div>
<div class="trust-text">
Average ROI Increase
</div>
</div>
<div class="trust-card">
<div class="trust-number">
3x
</div>
<div class="trust-text">
Faster Content Creation
</div>
</div>
<div class="trust-card">
<div class="trust-number">
24/7
</div>
<div class="trust-text">
Performance Monitoring
</div>
</div>
</div>
</div>
</section>
<!-- Why Choose Us Section -->
<section id="why-choose-us" class="why-choose-us">
<div class="section-container">
<!-- Section Header -->
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">🎯</span>
<span class="section-badge-text">Why Choose Us</span>
</div>
<h2 class="section-title">
Intelligent Digital Excellence
</h2>
<p class="section-subtitle">
Combine proven digital strategies with smart automation and data insights to accelerate your brand's growth and market impact
</p>
</div>
<div class="why-choose-grid">
<div class="choice-card">
<div class="choice-icon">🤖</div>
<h3 class="choice-title">Data-Driven Brand Intelligence</h3>
<p class="choice-description">
Advanced analytics and automation for real-time audience insights, trend forecasting, and competitive intelligence. Our smart systems continuously optimize your strategy based on performance data.
</p>
</div>
<div class="choice-card">
<div class="choice-icon">🌐</div>
<h3 class="choice-title">Comprehensive Digital Automation</h3>
<p class="choice-description">
End-to-end digital presence management with smart automation, content optimization, intelligent scheduling, SEO enhancement, and reputation management for maximum efficiency and impact.
</p>
</div>
<div class="choice-card">
<div class="choice-icon"></div>
<h3 class="choice-title">Smart Personalization & Optimization</h3>
<p class="choice-description">
Intelligent systems that learn your brand identity, automatically adapt strategies for your market, and continuously optimize campaigns based on performance data and market insights.
</p>
</div>
</div>
</div>
</section>
<!-- Our Process Section -->
<section id="our-process" class="our-process">
<div class="section-container">
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">📋</span>
<span class="section-badge-text">Our Process</span>
</div>
<h2 class="section-title">
AI-Enhanced SOSTAC+RACE Framework
</h2>
<p class="section-subtitle">
Our proven methodology supercharged with artificial intelligence, machine learning insights, and automated optimization at every stage
</p>
</div>
<div class="process-grid">
<div class="process-step-card">
<div class="step-number">1</div>
<div class="step-content">
<h3 class="step-title">AI-Powered Situation Analysis</h3>
<p class="step-description">
Deploy machine learning algorithms to analyze your brand's digital DNA, competitive intelligence automation, and predictive market positioning with real-time data insights.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">2</div>
<div class="step-content">
<h3 class="step-title">AI-Optimized Objectives</h3>
<p class="step-description">
Generate data-driven SMART goals using predictive analytics, automated KPI tracking, and AI-powered performance forecasting with continuous goal optimization.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">3</div>
<div class="step-content">
<h3 class="step-title">Intelligent Strategy Design</h3>
<p class="step-description">
AI-driven customer journey mapping, automated audience segmentation, dynamic value proposition testing, and intelligent channel selection with performance optimization.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">4</div>
<div class="step-content">
<h3 class="step-title">AI-Automated Tactics (RACE Framework)</h3>
<p class="step-description">
Deploy intelligent automation for Reach (AI-powered visibility), Act (automated engagement), Convert (smart sales funnels), and Engage (AI-driven loyalty programs).
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">5</div>
<div class="step-content">
<h3 class="step-title">Automated Action Execution</h3>
<p class="step-description">
AI-powered task automation, intelligent timeline management, and automated brand asset generation with smart content creation and deployment systems.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">6</div>
<div class="step-content">
<h3 class="step-title">Intelligent Control & Optimization</h3>
<p class="step-description">
Real-time AI monitoring, predictive KPI analysis, automated strategy refinement, and continuous machine learning optimization with performance forecasting.
</p>
</div>
</div>
</div>
<!-- RACE Framework Details -->
<div class="race-framework">
<h3 class="race-title">RACE Framework Breakdown</h3>
<div class="race-grid">
<div class="race-card">
<div class="race-phase">
<span class="race-icon">📢</span>
<h4>Reach</h4>
</div>
<div class="race-focus">AI-Powered Visibility</div>
<div class="race-actions">Automated LLM optimization, AI-driven SEO, smart ad targeting, AI influencer matching, automated PR distribution</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">💬</span>
<h4>Act</h4>
</div>
<div class="race-focus">Intelligent Engagement</div>
<div class="race-actions">AI content generation, dynamic landing pages, chatbot interactions, automated social responses</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">🎯</span>
<h4>Convert</h4>
</div>
<div class="race-focus">Smart Conversions</div>
<div class="race-actions">AI-optimized CTAs, predictive retargeting, automated lead scoring, intelligent funnel optimization</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">❤️</span>
<h4>Engage</h4>
</div>
<div class="race-focus">AI-Driven Loyalty</div>
<div class="race-actions">Automated email personalization, AI community management, predictive advocacy, smart retention campaigns</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="branding-services">
<div class="section-container">
<h2 class="services-title">
AI-Powered Service Portfolio
</h2>
<p class="services-subtitle">
Advanced artificial intelligence solutions that automate, optimize, and accelerate your digital brand transformation
</p>
<div class="branding-services-grid">
<div class="service-card">
<div class="service-icon">🎨</div>
<h3 class="service-title">Brand Discovery & Smart Identity Design</h3>
<p class="service-description">
Complete brand audit enhanced with AI insights, strategic identity creation, and adaptive design systems that evolve with market trends and audience data.
</p>
</div>
<div class="service-card">
<div class="service-icon">📱</div>
<h3 class="service-title">Strategic Platform Management & Automation</h3>
<p class="service-description">
Smart platform selection and optimization, automated content distribution, intelligent scheduling, and performance optimization across social media, websites, and digital touchpoints.
</p>
</div>
<div class="service-card">
<div class="service-icon">🔍</div>
<h3 class="service-title">Advanced Content & Marketing Automation</h3>
<p class="service-description">
AI-enhanced content creation, automated SEO optimization, intelligent ad targeting and social media management with real-time performance adjustments for maximum impact.
</p>
</div>
<div class="service-card">
<div class="service-icon">📢</div>
<h3 class="service-title">Influencer Partnerships & Digital PR</h3>
<p class="service-description">
Strategic influencer discovery and matching, automated PR campaign management, smart media outreach, and comprehensive relationship management for maximum brand amplification.
</p>
</div>
<div class="service-card">
<div class="service-icon">🎯</div>
<h3 class="service-title">Brand Consistency & Messaging Systems</h3>
<p class="service-description">
Unified brand guidelines with automated enforcement, intelligent messaging frameworks, smart visual asset management, and consistent brand voice across all platforms.
</p>
</div>
<div class="service-card">
<div class="service-icon">📊</div>
<h3 class="service-title">Predictive AI Analytics & Automated Insights</h3>
<p class="service-description">
Real-time predictive analytics, automated performance optimization, AI-generated insights and recommendations, with intelligent forecasting and proactive strategy adjustments.
</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section id="discovery-form" class="branding-cta">
<div class="cta-container">
<h2 class="cta-title">
Accelerate Your Digital Brand Growth
</h2>
<div class="cta-grid">
<!-- CTA Content -->
<div class="cta-content">
<h3 class="cta-content-title">Ready to transform your digital brand presence?</h3>
<p class="cta-description">
Complete our Digital Brand Strategy Assessment and receive a customized growth roadmap with smart automation recommendations within 24 hours.
</p>
<!-- Features List -->
<div class="cta-features">
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Free comprehensive brand analysis</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Personalized growth automation roadmap</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Custom strategy proposal in 24 hours</span>
</div>
</div>
<!-- CTA Buttons -->
<div class="cta-buttons">
<!-- <a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn primary">
🚀 Get Discovery Questionnaire
</a> -->
<a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn secondary">
💬 Contact Us Directly
</a>
</div>
</div>
<!-- Contact Information -->
<div class="cta-info">
<h3 class="cta-info-title">Get in Touch</h3>
<!-- Contact Item -->
<div class="contact-item">
<div class="contact-icon">
✉️
</div>
<div class="contact-details">
<h4>Email Address</h4>
<p>
<a href="mailto:abhay@quantumtaskai.com" class="contact-email">
abhay@quantumtaskai.com
</a>
</p>
</div>
</div>
<!-- Commitment Statement -->
<div class="commitment-statement">
<p class="commitment-text">
Leading the AI Revolution in Digital Branding - Where Artificial Intelligence Meets Brand Excellence for Unprecedented Growth and Automation.
</p>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extra_js %}
<script>
class DigitalBrandingManager {
constructor() {
this.processCards = document.querySelectorAll('.process-step-card');
this.raceCards = document.querySelectorAll('.race-card');
this.serviceCards = document.querySelectorAll('.service-card');
this.ctaButtons = document.querySelectorAll('.cta-btn');
this.init();
}
init() {
this.setupCardInteractions();
this.setupButtonHovers();
this.addScrollAnimations();
this.setupSmoothScrolling();
}
setupCardInteractions() {
// Process step cards
this.processCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// RACE framework cards
this.raceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// Service cards
this.serviceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
}
highlightCard(card) {
card.style.transform = 'translateY(-4px)';
card.style.boxShadow = '0 20px 40px rgba(30, 64, 175, 0.15)';
}
removeHighlight(card) {
card.style.transform = 'translateY(0)';
card.style.boxShadow = '';
}
setupButtonHovers() {
this.ctaButtons.forEach(button => {
button.addEventListener('mouseenter', () => {
button.style.transform = 'translateY(-2px)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = '';
});
button.addEventListener('click', () => {
if (!button.classList.contains('loading')) {
button.classList.add('loading');
const originalText = button.textContent;
button.textContent = '⏳ Loading...';
setTimeout(() => {
if (button.classList.contains('loading')) {
button.classList.remove('loading');
button.textContent = originalText;
}
}, 2000);
}
});
});
}
addScrollAnimations() {
if ('IntersectionObserver' in window) {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe cards for scroll animations
[...this.processCards, ...this.raceCards, ...this.serviceCards].forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
observer.observe(card);
});
// Observe sections
document.querySelectorAll('.section-header, .cta-content').forEach(section => {
section.style.opacity = '0';
section.style.transform = 'translateY(20px)';
section.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(section);
});
}
}
setupSmoothScrolling() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
new DigitalBrandingManager();
});
</script>
{% endblock %}

View File

@ -1,43 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Event - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Event">
</iframe>
</div>
{% endblock %}

View File

@ -3,11 +3,6 @@
{% block title %}Quantum Tasks AI - AI & Task Automation Solutions{% endblock %}
{% block description %}Discover powerful AI agents for automation, analysis, and productivity. Access premium AI tools for social media, business analysis, document processing, and more.{% endblock %}
{% block og_title %}Quantum Tasks AI - AI & Task Automation Solutions{% endblock %}
{% block og_description %}Discover powerful AI agents for automation, analysis, and productivity. Access premium AI tools for social media, business analysis, document processing, and more.{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/homepage.css' %}">
{% endblock %}

View File

@ -1,43 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Lean Six Sigma Expert - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Lean Six Sigma Expert">
</iframe>
</div>
{% endblock %}

View File

@ -1,38 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}SWOT Analysis Expert - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px);
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="SWOT Analysis Expert">
</iframe>
</div>
{% endblock %}

View File

@ -79,22 +79,16 @@ def wallet_topup_view(request):
return redirect('wallet:wallet_topup')
except Exception as e:
logger.error(f"Checkout session creation failed for user {request.user.id}: {e}")
messages.error(request, 'Payment failed. Try again.')
messages.error(request, 'Unable to process payment at this time. Please try again.')
return redirect('wallet:wallet_topup')
return render(request, 'wallet/wallet_topup.html')
@login_required
@ratelimit(key='user', rate='10/m', method='GET', block=False)
def wallet_topup_success_view(request):
"""Payment success page with automatic payment verification"""
# Check authentication first and clear any messages if redirecting to login
if not request.user.is_authenticated:
# Clear any existing messages to prevent them from showing on login page
storage = messages.get_messages(request)
storage.used = True
return redirect('authentication:login')
# Check if rate limited
if getattr(request, 'limited', False):
logger.warning(f"Payment success page rate limit exceeded for user {request.user.id}")
@ -105,7 +99,7 @@ def wallet_topup_success_view(request):
if not session_id:
logger.warning(f"No session ID provided for user {request.user.id}")
messages.error(request, 'Payment session not found.')
messages.error(request, 'No payment session found. Please contact support if you completed a payment.')
return redirect('wallet:wallet')
# Verify payment directly with Stripe API
@ -117,10 +111,10 @@ def wallet_topup_success_view(request):
if result['success']:
if result['processed']:
messages.success(request, f'{result["amount"]} AED added to wallet.')
messages.success(request, f'Payment successful! {result["amount"]} AED has been added to your wallet.')
logger.info(f"Payment verified and wallet updated for user {request.user.id}")
else:
messages.info(request, 'Payment already processed.')
messages.info(request, 'Payment already processed. Your wallet balance is up to date.')
logger.info(f"Payment already processed for session {session_id}")
else:
messages.warning(request, 'Payment verification failed. Please contact support.')
@ -128,21 +122,15 @@ def wallet_topup_success_view(request):
except Exception as e:
logger.error(f"Error verifying payment for user {request.user.id}: {e}")
messages.error(request, 'Payment verification failed.')
messages.error(request, 'Unable to verify payment. Please contact support if you completed a payment.')
return redirect('wallet:wallet')
@login_required
def wallet_topup_cancel_view(request):
"""Payment cancel page"""
# Check authentication first and clear any messages if redirecting to login
if not request.user.is_authenticated:
# Clear any existing messages to prevent them from showing on login page
storage = messages.get_messages(request)
storage.used = True
return redirect('authentication:login')
messages.info(request, 'Payment cancelled.')
messages.info(request, 'Payment was cancelled. No charges were made.')
return redirect('wallet:wallet_topup')