From 5e97ca8ea1c1689c64dae535d4e51fa89cb9d67d Mon Sep 17 00:00:00 2001 From: Ashad Qureshi Date: Tue, 17 Jun 2025 21:52:16 +0500 Subject: [PATCH 1/5] Logging and clean up --- auto-analyst-backend/DEFAULT_AGENTS_SETUP.md | 237 ------------------ .../scripts/populate_agent_templates.py | 52 ++-- .../custom-templates/TemplatesModal.tsx | 20 +- .../custom-templates/useTemplates.ts | 18 -- auto-analyst-frontend/lib/utils/logger.ts | 2 +- 5 files changed, 28 insertions(+), 301 deletions(-) delete mode 100644 auto-analyst-backend/DEFAULT_AGENTS_SETUP.md diff --git a/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md b/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md deleted file mode 100644 index 1242c834..00000000 --- a/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md +++ /dev/null @@ -1,237 +0,0 @@ -# Default Agents Setup Guide - -This guide explains how to set up and use the default agents system in the Auto-Analyst backend. - -## Overview - -The system now includes 4 default agents that are stored in the database as templates: - -1. **Data Preprocessing Agent** (`preprocessing_agent`) - Data cleaning and preparation -2. **Statistical Analytics Agent** (`statistical_analytics_agent`) - Statistical analysis using statsmodels -3. **Machine Learning Agent** (`sk_learn_agent`) - ML modeling using scikit-learn -4. **Data Visualization Agent** (`data_viz_agent`) - Interactive visualizations using Plotly - -## Setup Instructions - -### 1. Load Default Agents into Database - -Run the setup script to populate the database with default agents: - -```bash -cd Auto-Analyst-CS/auto-analyst-backend -python load_default_agents.py -``` - -**Or** use the API endpoint: - -```bash -curl -X POST "http://localhost:8000/templates/load-default-agents" \ - -H "Content-Type: application/json" \ - -d '{"force_update": false}' -``` - -### 2. Agent Properties - -All default agents are created with: -- `is_active = True` (available for use) -- `is_premium_only = False` (free to use) -- Proper categories (Data Manipulation, Statistical Analysis, Modelling, Visualization) - -## User Preferences System - -### Default Behavior -- **Default agents (preprocessing, statistical_analytics, sk_learn, data_viz) are ENABLED by default** for all users -- **Other templates are DISABLED by default** and must be explicitly enabled -- Templates can be used directly via `@template_name` regardless of preferences - -### Managing User Preferences - -#### Enable/Disable Templates -```bash -# Enable a template for a user -curl -X POST "http://localhost:8000/templates/user/1/template/1/toggle" \ - -H "Content-Type: application/json" \ - -d '{"is_enabled": true}' - -# Disable a template for a user -curl -X POST "http://localhost:8000/templates/user/1/template/1/toggle" \ - -H "Content-Type: application/json" \ - -d '{"is_enabled": false}' -``` - -#### Bulk Enable/Disable -```bash -# Enable multiple templates at once -curl -X POST "http://localhost:8000/templates/user/1/bulk-toggle" \ - -H "Content-Type: application/json" \ - -d '{ - "template_preferences": { - "1": true, - "2": true, - "3": false - } - }' -``` - -#### Get User's Template Preferences -```bash -# Get all templates with user's enabled/disabled status -curl "http://localhost:8000/templates/user/1" - -# Get only enabled templates for user -curl "http://localhost:8000/templates/user/1/enabled" - -# Get enabled templates for planner (max 10, ordered by usage) -curl "http://localhost:8000/templates/user/1/enabled/planner" -``` - -## Planner Integration - -### How It Works -1. **Template Loading**: Only user-enabled templates are loaded into the planner -2. **No Agents Available**: If no templates are enabled, planner returns a helpful message -3. **Usage Tracking**: Template usage is tracked for prioritization - -### Planner Response When No Agents Enabled -```json -{ - "complexity": "no_agents_available", - "plan": "no_agents_available", - "plan_instructions": { - "message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis." - } -} -``` - -## API Endpoints - -### Template Management -- `GET /templates/` - Get all available templates -- `GET /templates/template/{template_id}` - Get specific template -- `POST /templates/load-default-agents` - Load default agents into database - -### User Preferences -- `GET /templates/user/{user_id}` - Get user's template preferences -- `GET /templates/user/{user_id}/enabled` - Get user's enabled templates -- `GET /templates/user/{user_id}/enabled/planner` - Get templates for planner (max 10) -- `POST /templates/user/{user_id}/template/{template_id}/toggle` - Toggle template preference -- `POST /templates/user/{user_id}/bulk-toggle` - Bulk toggle preferences - -### Categories -- `GET /templates/categories/list` - Get all categories -- `GET /templates/categories` - Get templates grouped by category -- `GET /templates/category/{category}` - Get templates in specific category - -## Usage Examples - -### Frontend Integration -```typescript -// Enable preprocessing and visualization agents for user -const enableAgents = async (userId: number) => { - await fetch(`/templates/user/${userId}/bulk-toggle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - template_preferences: { - "1": true, // preprocessing_agent - "4": true // data_viz_agent - } - }) - }); -}; - -// Get user's enabled templates -const getUserTemplates = async (userId: number) => { - const response = await fetch(`/templates/user/${userId}/enabled`); - return await response.json(); -}; -``` - -### Direct Agent Usage -Users can still use any agent directly regardless of preferences: -``` -@preprocessing_agent clean this data -@data_viz_agent create a scatter plot of sales vs price -``` - -### Planner Usage -Only enabled agents will be available to the planner: -``` -User: "Clean the data and create a visualization" -System: Uses only enabled agents to create the plan -``` - -## Database Schema - -### AgentTemplate Table -```sql -CREATE TABLE agent_templates ( - template_id SERIAL PRIMARY KEY, - template_name VARCHAR UNIQUE NOT NULL, - display_name VARCHAR, - description TEXT, - prompt_template TEXT, - category VARCHAR, - is_premium_only BOOLEAN DEFAULT FALSE, - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP, - updated_at TIMESTAMP -); -``` - -### UserTemplatePreference Table -```sql -CREATE TABLE user_template_preferences ( - user_id INTEGER, - template_id INTEGER, - is_enabled BOOLEAN DEFAULT FALSE, - usage_count INTEGER DEFAULT 0, - last_used_at TIMESTAMP, - created_at TIMESTAMP, - updated_at TIMESTAMP, - PRIMARY KEY (user_id, template_id), - FOREIGN KEY (user_id) REFERENCES users(user_id), - FOREIGN KEY (template_id) REFERENCES agent_templates(template_id) -); -``` - -## Troubleshooting - -### Common Issues - -1. **No agents available in planner** - - Check if user has enabled any templates: `GET /templates/user/{user_id}/enabled` - - Enable templates using the toggle endpoint - -2. **Default agents not found** - - Run the load script: `python load_default_agents.py` - - Check if agents exist: `GET /templates/` - -3. **Import errors in load script** - - Ensure you're in the backend directory - - Check that all dependencies are installed - - Verify database connection - -### Logs -Check the application logs for detailed error messages: -```bash -tail -f logs/templates_routes.log -tail -f logs/agents.log -``` - -## Migration from Old System - -If migrating from the previous custom agents system: - -1. **Data Migration**: Existing custom agents should be migrated to the new template system -2. **User Preferences**: Users will need to re-enable their preferred agents -3. **API Updates**: Update frontend code to use new template endpoints -4. **Testing**: Verify planner works with enabled templates only - -## Support - -For issues or questions: -1. Check the logs for error messages -2. Verify database connections -3. Ensure proper API endpoint usage -4. Test with the load script first \ No newline at end of file diff --git a/auto-analyst-backend/scripts/populate_agent_templates.py b/auto-analyst-backend/scripts/populate_agent_templates.py index d1d7b87d..986a377e 100644 --- a/auto-analyst-backend/scripts/populate_agent_templates.py +++ b/auto-analyst-backend/scripts/populate_agent_templates.py @@ -377,35 +377,35 @@ def populate_agents_and_templates(include_defaults=True, include_premiums=True): print(f"\nšŸ”’ --- Processing Premium Templates (Paid) ---") for category, templates in PREMIUM_TEMPLATES.items(): print(f"\nšŸ“ {category}:") + + for template_data in templates: + template_name = template_data["template_name"] + + # Check if template already exists + existing = session.query(AgentTemplate).filter( + AgentTemplate.template_name == template_name + ).first() + + if existing: + print(f"ā­ļø Skipping {template_name} (already exists)") + skipped_count += 1 + continue - for template_data in templates: - template_name = template_data["template_name"] - - # Check if template already exists - existing = session.query(AgentTemplate).filter( - AgentTemplate.template_name == template_name - ).first() - - if existing: - print(f"ā­ļø Skipping {template_name} (already exists)") - skipped_count += 1 - continue - # Create new premium template - template = AgentTemplate( - template_name=template_name, - display_name=template_data["display_name"], - description=template_data["description"], - icon_url=template_data["icon_url"], - prompt_template=template_data["prompt_template"], - category=category, + template = AgentTemplate( + template_name=template_name, + display_name=template_data["display_name"], + description=template_data["description"], + icon_url=template_data["icon_url"], + prompt_template=template_data["prompt_template"], + category=category, is_premium_only=True, # Premium templates require subscription - is_active=True, - created_at=datetime.now(UTC), - updated_at=datetime.now(UTC) - ) - - session.add(template) + is_active=True, + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC) + ) + + session.add(template) print(f"āœ… Created premium template: {template_name}") premium_created += 1 diff --git a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx index 89fab668..4e06a15f 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx @@ -90,7 +90,7 @@ export default function TemplatesModal({ }) setTemplates(templatesData) - setPreferences([]) // No preferences for free users + setPreferences([]) // No preferences for free users setChanges({}) } catch (error) { console.error('Error loading templates:', error) @@ -108,42 +108,30 @@ export default function TemplatesModal({ const loadData = async () => { setLoading(true) try { - console.log('Loading templates data for modal...', { API_URL, userId }) - // Fetch global template data with global usage counts const [templatesResponse, preferencesResponse] = await Promise.all([ fetch(`${API_URL}/templates/`).catch(err => { - console.error('Templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }), // Global templates with global usage counts fetch(`${API_URL}/templates/user/${userId}`).catch(err => { - console.error('Preferences fetch error:', err) throw new Error(`Preferences endpoint failed: ${err.message}`) }) // User preferences with per-user usage ]) - console.log('Modal responses received:', { - templatesStatus: templatesResponse.status, - preferencesStatus: preferencesResponse.status - }) - // Check templates response if (!templatesResponse.ok) { const errorText = await templatesResponse.text() - console.error('Templates response error:', { status: templatesResponse.status, errorText }) throw new Error(`Failed to load templates: ${templatesResponse.status} ${templatesResponse.statusText} - ${errorText}`) } // Check preferences response if (!preferencesResponse.ok) { const errorText = await preferencesResponse.text() - console.error('Preferences response error:', { status: preferencesResponse.status, errorText }) throw new Error(`Failed to load preferences: ${preferencesResponse.status} ${preferencesResponse.statusText} - ${errorText}`) } // Parse templates response const globalTemplatesData = await templatesResponse.json().catch(err => { - console.error('Templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) @@ -165,7 +153,6 @@ export default function TemplatesModal({ // Parse preferences response const userPreferencesData = await preferencesResponse.json().catch(err => { - console.error('Preferences JSON parse error:', err) throw new Error(`Failed to parse preferences response: ${err.message}`) }) @@ -183,11 +170,6 @@ export default function TemplatesModal({ })) setPreferences(preferencesData) - console.log('Modal data parsed successfully:', { - templatesCount: templatesData.length, - preferencesCount: preferencesData.length - }) - // Reset changes when loading data setChanges({}) } catch (error) { diff --git a/auto-analyst-frontend/components/custom-templates/useTemplates.ts b/auto-analyst-frontend/components/custom-templates/useTemplates.ts index f958d116..6caab3c2 100644 --- a/auto-analyst-frontend/components/custom-templates/useTemplates.ts +++ b/auto-analyst-frontend/components/custom-templates/useTemplates.ts @@ -34,54 +34,36 @@ export function useTemplates({ userId, enabled = true }: UseTemplatesProps): Use setError(null) try { - console.log('Loading templates data...', { API_URL, userId }) - const [templatesResponse, preferencesResponse] = await Promise.all([ fetch(`${API_URL}/templates/`).catch(err => { - console.error('Templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }), fetch(`${API_URL}/templates/user/${userId}`).catch(err => { - console.error('Preferences fetch error:', err) throw new Error(`Preferences endpoint failed: ${err.message}`) }) ]) - console.log('Responses received:', { - templatesStatus: templatesResponse.status, - preferencesStatus: preferencesResponse.status - }) - // Check templates response if (!templatesResponse.ok) { const errorText = await templatesResponse.text() - console.error('Templates response error:', { status: templatesResponse.status, errorText }) throw new Error(`Failed to load templates: ${templatesResponse.status} ${templatesResponse.statusText} - ${errorText}`) } // Check preferences response if (!preferencesResponse.ok) { const errorText = await preferencesResponse.text() - console.error('Preferences response error:', { status: preferencesResponse.status, errorText }) throw new Error(`Failed to load preferences: ${preferencesResponse.status} ${preferencesResponse.statusText} - ${errorText}`) } // Parse responses const templatesData = await templatesResponse.json().catch(err => { - console.error('Templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) const preferencesData = await preferencesResponse.json().catch(err => { - console.error('Preferences JSON parse error:', err) throw new Error(`Failed to parse preferences response: ${err.message}`) }) - console.log('Data parsed successfully:', { - templatesCount: templatesData.length, - preferencesCount: preferencesData.length - }) - setTemplates(templatesData) setPreferences(preferencesData) diff --git a/auto-analyst-frontend/lib/utils/logger.ts b/auto-analyst-frontend/lib/utils/logger.ts index 282b9f0b..405abb3a 100644 --- a/auto-analyst-frontend/lib/utils/logger.ts +++ b/auto-analyst-frontend/lib/utils/logger.ts @@ -6,7 +6,7 @@ */ // Set this to true to disable all non-error logs -const DISABLE_LOGS = false; +const DISABLE_LOGS = true; const logger = { log: (...args: any[]) => { From 669420c6ff7e75c4e9ae0056c4106eb17466ff14 Mon Sep 17 00:00:00 2001 From: Ashad Qureshi Date: Wed, 18 Jun 2025 11:52:58 +0500 Subject: [PATCH 2/5] Template/Default Agents now limit in 1-10 Agents for Planner --- auto-analyst-backend/app.py | 1 + auto-analyst-backend/chat_database.db | 4 +- .../scripts/populate_agent_templates.py | 54 ++++++------ auto-analyst-backend/src/agents/agents.py | 6 +- .../src/routes/templates_routes.py | 84 +++++++++++++++++-- .../custom-templates/TemplateCard.tsx | 52 ++++++++---- .../custom-templates/TemplatesModal.tsx | 47 +++++++---- 7 files changed, 181 insertions(+), 67 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index bfe73b8b..749b2342 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -1069,6 +1069,7 @@ def _get_model_name_for_provider(provider: str) -> str: async def _execute_plan_with_timeout(ai_system, enhanced_query, plan_response): """Execute the plan with timeout handling for each step""" try: + logger.log_message(f"Plan response: {plan_response}", level=logging.INFO) # Use the async generator from execute_plan directly async for agent_name, inputs, response in ai_system.execute_plan(enhanced_query, plan_response): # Yield results as they come diff --git a/auto-analyst-backend/chat_database.db b/auto-analyst-backend/chat_database.db index e99a3734..5e822b7a 100644 --- a/auto-analyst-backend/chat_database.db +++ b/auto-analyst-backend/chat_database.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:061a038faca46d439d7178af5bc140ee7a523d4ef00cf57ca75d2d9e708fcdb2 -size 69632 +oid sha256:411541bb611238c8dc72a19c30c359deee92c3a0692e9a13ef64d426d1b746cf +size 139264 diff --git a/auto-analyst-backend/scripts/populate_agent_templates.py b/auto-analyst-backend/scripts/populate_agent_templates.py index 986a377e..8244562e 100644 --- a/auto-analyst-backend/scripts/populate_agent_templates.py +++ b/auto-analyst-backend/scripts/populate_agent_templates.py @@ -25,7 +25,6 @@ def get_database_type(): else: return "unknown" -# Default agents (free for all users) DEFAULT_AGENTS = { "Data Manipulation": [ { @@ -203,7 +202,6 @@ def statistical_model(X, y, goal, period=None): ] } -# Premium template agent definitions PREMIUM_TEMPLATES = { "Data Visualization": [ { @@ -377,35 +375,35 @@ def populate_agents_and_templates(include_defaults=True, include_premiums=True): print(f"\nšŸ”’ --- Processing Premium Templates (Paid) ---") for category, templates in PREMIUM_TEMPLATES.items(): print(f"\nšŸ“ {category}:") - - for template_data in templates: - template_name = template_data["template_name"] - - # Check if template already exists - existing = session.query(AgentTemplate).filter( - AgentTemplate.template_name == template_name - ).first() - - if existing: - print(f"ā­ļø Skipping {template_name} (already exists)") - skipped_count += 1 - continue + for template_data in templates: + template_name = template_data["template_name"] + + # Check if template already exists + existing = session.query(AgentTemplate).filter( + AgentTemplate.template_name == template_name + ).first() + + if existing: + print(f"ā­ļø Skipping {template_name} (already exists)") + skipped_count += 1 + continue + # Create new premium template - template = AgentTemplate( - template_name=template_name, - display_name=template_data["display_name"], - description=template_data["description"], - icon_url=template_data["icon_url"], - prompt_template=template_data["prompt_template"], - category=category, + template = AgentTemplate( + template_name=template_name, + display_name=template_data["display_name"], + description=template_data["description"], + icon_url=template_data["icon_url"], + prompt_template=template_data["prompt_template"], + category=category, is_premium_only=True, # Premium templates require subscription - is_active=True, - created_at=datetime.now(UTC), - updated_at=datetime.now(UTC) - ) - - session.add(template) + is_active=True, + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC) + ) + + session.add(template) print(f"āœ… Created premium template: {template_name}") premium_created += 1 diff --git a/auto-analyst-backend/src/agents/agents.py b/auto-analyst-backend/src/agents/agents.py index 8de9d96f..215863a3 100644 --- a/auto-analyst-backend/src/agents/agents.py +++ b/auto-analyst-backend/src/agents/agents.py @@ -1582,7 +1582,7 @@ def __init__(self, agents, retrievers, user_id=None, db_session=None): try: # For planner use, load planner-enabled templates (max 10, prioritized by usage) template_signatures = load_user_enabled_templates_for_planner_from_db(user_id, db_session) - logger.log_message(f"Loaded {len(template_signatures)} templates for planner use", level=logging.INFO) + logger.log_message(f"Loaded {template_signatures} templates for planner use", level=logging.INFO) for template_name, signature in template_signatures.items(): # Skip if this is a core agent - we'll load it separately @@ -1861,6 +1861,7 @@ async def get_plan(self, query): else: complexity = 'basic' plan_dict['complexity'] = complexity + logger.log_message(f"Plan dict: {plan_dict}", level=logging.INFO) return plan_dict @@ -1880,7 +1881,8 @@ async def execute_plan(self, query, plan): import json # Clean and split the plan string into agent names - plan_text = plan.get("plan", "").replace("Plan", "").replace(":", "").strip() + plan_text = plan.get("plan", "").lower().replace("plan", "").replace(":", "").strip() + logger.log_message(f"Plan text: {plan_text}", level=logging.INFO) if "basic_qa_agent" in plan_text: inputs = dict(goal=query) diff --git a/auto-analyst-backend/src/routes/templates_routes.py b/auto-analyst-backend/src/routes/templates_routes.py index 06394a17..ca81096d 100644 --- a/auto-analyst-backend/src/routes/templates_routes.py +++ b/auto-analyst-backend/src/routes/templates_routes.py @@ -355,6 +355,46 @@ async def toggle_template_preference(user_id: int, template_id: int, request: To if not user: raise HTTPException(status_code=404, detail="User not found") + # If trying to disable, check if this would leave user with no enabled templates + if not request.is_enabled: + # Get list of default agent names that should be enabled by default + default_agent_names = [ + "preprocessing_agent", + "statistical_analytics_agent", + "sk_learn_agent", + "data_viz_agent" + ] + + # Get all active templates + all_templates = session.query(AgentTemplate).filter( + AgentTemplate.is_active == True + ).all() + + enabled_count = 0 + for template in all_templates: + # Check if user has a preference record for this template + preference = session.query(UserTemplatePreference).filter( + UserTemplatePreference.user_id == user_id, + UserTemplatePreference.template_id == template.template_id + ).first() + + # Determine if template should be enabled by default + is_default_agent = template.template_name in default_agent_names + default_enabled = is_default_agent + + # Template is enabled by default for default agents, disabled for others + is_enabled = preference.is_enabled if preference else default_enabled + + if is_enabled: + enabled_count += 1 + + # If disabling this template would leave the user with 0 enabled templates, reject + if enabled_count <= 1: + raise HTTPException( + status_code=400, + detail="Cannot disable the last active agent. At least one agent must remain active." + ) + success, message = toggle_user_template_preference( user_id, template_id, request.is_enabled, session ) @@ -391,19 +431,51 @@ async def bulk_toggle_template_preferences(user_id: int, request: dict): if not template_preferences: raise HTTPException(status_code=400, detail="No preferences provided") - # Check current enabled count for limit enforcement - current_enabled_count = session.query(UserTemplatePreference).filter( - UserTemplatePreference.user_id == user_id, - UserTemplatePreference.is_enabled == True - ).count() + # Get list of default agent names that should be enabled by default + default_agent_names = [ + "preprocessing_agent", + "statistical_analytics_agent", + "sk_learn_agent", + "data_viz_agent" + ] + + # Calculate current enabled count properly (including defaults) + all_templates = session.query(AgentTemplate).filter( + AgentTemplate.is_active == True + ).all() + + current_enabled_count = 0 + for template in all_templates: + # Check if user has a preference record for this template + preference = session.query(UserTemplatePreference).filter( + UserTemplatePreference.user_id == user_id, + UserTemplatePreference.template_id == template.template_id + ).first() + + # Determine if template should be enabled by default + is_default_agent = template.template_name in default_agent_names + default_enabled = is_default_agent + + # Template is enabled by default for default agents, disabled for others + is_enabled = preference.is_enabled if preference else default_enabled + + if is_enabled: + current_enabled_count += 1 - # Count how many templates we're trying to enable + # Count how many templates we're trying to enable/disable enabling_count = sum(1 for pref in template_preferences if pref.get("is_enabled", False)) disabling_count = sum(1 for pref in template_preferences if not pref.get("is_enabled", False)) # Calculate what the new count would be projected_enabled_count = current_enabled_count + enabling_count - disabling_count + # Check if the bulk operation would leave user with 0 enabled templates + if projected_enabled_count < 1: + raise HTTPException( + status_code=400, + detail="Cannot disable all agents. At least one agent must remain active." + ) + results = [] for pref in template_preferences: template_id = pref.get("template_id") diff --git a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx index 0b3e6b34..33855719 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx @@ -9,6 +9,7 @@ interface TemplateCardProps { preference?: TemplatePreference isEnabled: boolean hasAccess: boolean + isLastTemplate?: boolean onToggleChange: (templateId: number, enabled: boolean) => void } @@ -17,11 +18,13 @@ export default function TemplateCard({ preference, isEnabled, hasAccess, + isLastTemplate = false, onToggleChange }: TemplateCardProps) { // User can only toggle if they have access (covers both free and premium users) // Premium-only templates are only toggleable by premium users (hasAccess = true for premium) - const canToggle = hasAccess + // Also cannot disable if this is the last template + const canToggle = hasAccess && !(isEnabled && isLastTemplate) const handleClick = () => { if (canToggle) { @@ -29,6 +32,22 @@ export default function TemplateCard({ } } + // Determine the status text and color + const getStatusInfo = () => { + if (!hasAccess) { + return { text: 'Premium', color: 'text-gray-400' } + } + if (isEnabled && isLastTemplate) { + return { text: 'Required', color: 'text-orange-600' } + } + if (isEnabled) { + return { text: 'Active', color: 'text-green-600' } + } + return { text: 'Inactive', color: 'text-gray-400' } + } + + const statusInfo = getStatusInfo() + return ( {/* Lock overlay for free users */} {!canToggle && ( @@ -88,6 +108,11 @@ export default function TemplateCard({ Premium )} + {/* {isEnabled && isLastTemplate && ( + + Required + + )} */} @@ -113,26 +138,23 @@ export default function TemplateCard({ disabled={!canToggle} className={`w-6 h-6 rounded-md border-2 flex items-center justify-center transition-all duration-200 ${ isEnabled - ? 'bg-[#FF7F7F] border-[#FF7F7F] text-white' + ? isLastTemplate + ? 'bg-orange-500 border-orange-500 text-white' + : 'bg-[#FF7F7F] border-[#FF7F7F] text-white' : 'border-gray-300 hover:border-[#FF7F7F] bg-white' } ${!canToggle ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:scale-105'}`} + title={isEnabled && isLastTemplate ? 'At least one agent must remain active' : undefined} > {isEnabled && } - - {!canToggle - ? 'Premium' - : isEnabled - ? 'Active' - : 'Inactive' - } + + {statusInfo.text} + {isEnabled && isLastTemplate && ( + + Min required + + )} diff --git a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx index 4e06a15f..67549cdb 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx @@ -64,33 +64,22 @@ export default function TemplatesModal({ const loadTemplatesForFreeUsers = async () => { setLoading(true) try { - console.log('Loading templates for free users...', { API_URL }) - // Fetch all templates (no user-specific data needed) const response = await fetch(`${API_URL}/templates/`).catch(err => { - console.error('Free user templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }) - console.log('Free user templates response:', { status: response.status }) - if (!response.ok) { const errorText = await response.text() - console.error('Free user templates response error:', { status: response.status, errorText }) throw new Error(`Failed to load templates: ${response.status} ${response.statusText} - ${errorText}`) } const templatesData = await response.json().catch(err => { - console.error('Free user templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) - console.log('Free user templates data parsed successfully:', { - templatesCount: templatesData.length - }) - setTemplates(templatesData) - setPreferences([]) // No preferences for free users + setPreferences([]) // No preferences for free users setChanges({}) } catch (error) { console.error('Error loading templates:', error) @@ -321,7 +310,7 @@ export default function TemplatesModal({ if (response.ok) { toast({ title: "Settings Saved!", - description: `Updated ${preferencesToUpdate.length} template preferences`, + description: `Updated template preferences`, duration: 3000, }) setChanges({}) @@ -350,8 +339,29 @@ export default function TemplatesModal({ return { preference, isEnabled } } + // Calculate enabled count including pending changes + const getEnabledCountWithChanges = () => { + let count = 0 + templates.forEach(template => { + const isCurrentlyEnabled = getTemplateEnabledState(template) + if (isCurrentlyEnabled) { + count++ + } + }) + return count + } + + // Check if disabling this template would leave user with 0 templates + const wouldLeaveZeroTemplates = (templateId: number) => { + const currentEnabledCount = getEnabledCountWithChanges() + const templateCurrentlyEnabled = getTemplateEnabledState(templates.find(t => t.template_id === templateId)!) + + // If this template is currently enabled and it's the only one, disabling it would leave 0 + return templateCurrentlyEnabled && currentEnabledCount === 1 + } + const enabledCount = hasAccess - ? templates.filter(template => getTemplateEnabledState(template)).length + ? getEnabledCountWithChanges() : 0 return ( @@ -517,6 +527,8 @@ export default function TemplatesModal({
{filteredTemplates.map(template => { const { preference, isEnabled } = getTemplateData(template) + const isLastTemplate = wouldLeaveZeroTemplates(template.template_id) + return ( ) @@ -545,6 +558,12 @@ export default function TemplatesModal({ <> Use the toggle switches to enable/disable agents to be used by planner. You can use any agent directly with @agent_name. +
+ {enabledCount === 1 && ( + + {' '}Note: At least one agent must remain active. + + )}
{Object.keys(changes).length > 0 && ( From 5c36d04581868bf71d41f3e3db6f2459574d222c Mon Sep 17 00:00:00 2001 From: Ashad Qureshi Date: Wed, 18 Jun 2025 12:30:44 +0500 Subject: [PATCH 3/5] Landing Page - Templates v1 --- auto-analyst-backend/chat_database.db | 4 +- .../components/chat/AgentSuggestions.tsx | 37 ++++------ .../components/landing/AgentsSection.tsx | 73 ++++++++++--------- .../components/landing/FnT.tsx | 51 ++++++++++++- 4 files changed, 107 insertions(+), 58 deletions(-) diff --git a/auto-analyst-backend/chat_database.db b/auto-analyst-backend/chat_database.db index 5e822b7a..d78194e9 100644 --- a/auto-analyst-backend/chat_database.db +++ b/auto-analyst-backend/chat_database.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:411541bb611238c8dc72a19c30c359deee92c3a0692e9a13ef64d426d1b746cf -size 139264 +oid sha256:4e0854398016042fe9083a6fad651f974078fd1c502b035192601e7de9d913ab +size 147456 diff --git a/auto-analyst-frontend/components/chat/AgentSuggestions.tsx b/auto-analyst-frontend/components/chat/AgentSuggestions.tsx index f1af1018..7e812afc 100644 --- a/auto-analyst-frontend/components/chat/AgentSuggestions.tsx +++ b/auto-analyst-frontend/components/chat/AgentSuggestions.tsx @@ -65,7 +65,7 @@ export default function AgentSuggestions({ return null } - // Fetch agents from the main agents endpoint (includes both standard and custom) + // Fetch agents from the main agents endpoint (now all are templates in DB) const fetchAllAgents = async (): Promise => { const currentUserId = getUserId() @@ -82,34 +82,23 @@ export default function AgentSuggestions({ const data = await response.json() const allAgents: AgentSuggestion[] = [] - // // Add standard agents - // if (data.standard_agents) { - // data.standard_agents.forEach((agentName: string) => { - // const standardAgent = standardAgents.find(agent => agent.name === agentName) - // if (standardAgent) { - // allAgents.push(standardAgent) - // } - // }) - // } - - // Add template agents (only for users with custom agents access) - if (data.template_agents && data.template_agents.length > 0 && customAgentsAccess.hasAccess) { + // All agents are now template agents from the database + // Load all template agents, filtering will be done based on premium access + if (data.template_agents && data.template_agents.length > 0) { const templateAgents = await fetchTemplateAgents() allAgents.push(...templateAgents) } - // Custom agents are deprecated - using templates only - return allAgents } else { console.error('Failed to fetch agents:', response.status, await response.text()) - // Fallback to standard agents only - return standardAgents + // Fallback to empty array since all agents should be in DB now + return [] } } catch (error) { console.error('Error fetching agents:', error) - // Fallback to standard agents only - return standardAgents + // Fallback to empty array since all agents should be in DB now + return [] } } @@ -129,10 +118,14 @@ export default function AgentSuggestions({ const mappedTemplates = category.templates.map((template: any) => ({ name: template.agent_name, description: template.description, - // isTemplate: true, + isTemplate: true, isPremium: template.is_premium_only })) - allTemplates.push(...mappedTemplates) + // Filter out premium agents if user doesn't have access + const filteredTemplates = customAgentsAccess.hasAccess + ? mappedTemplates + : mappedTemplates.filter((template: any) => !template.isPremium) + allTemplates.push(...filteredTemplates) } }) @@ -304,7 +297,7 @@ export default function AgentSuggestions({
{agent.name}
{agent.isPremium && ( - + Template )} diff --git a/auto-analyst-frontend/components/landing/AgentsSection.tsx b/auto-analyst-frontend/components/landing/AgentsSection.tsx index 1b36547d..78c74b2d 100644 --- a/auto-analyst-frontend/components/landing/AgentsSection.tsx +++ b/auto-analyst-frontend/components/landing/AgentsSection.tsx @@ -1,8 +1,8 @@ "use client" import { motion } from "framer-motion" -import { agents } from "./FnT" +import { templateCategories } from "./FnT" import { Badge } from "@/components/ui/badge" -import { CheckCircle } from "lucide-react" +import { CheckCircle, Plus } from "lucide-react" export default function AgentsSection() { return ( @@ -16,66 +16,70 @@ export default function AgentsSection() { className="text-center mb-10 sm:mb-16" >

- Four Specialized AI Agents + Three Categories of AI Agents

- Unlike ChatGPT's general-purpose approach, Auto-Analyst uses four specialized agents that work together to handle complex data science workflows with precision and reliability. + Auto-Analyst organizes specialized AI agents into three powerful categories, each designed to handle specific aspects of your data science workflow with precision and expertise.

-
- {agents.map((agent, index) => ( +
+ {templateCategories.map((category, index) => ( {/* Gradient Background */} -
+
- {/* Agent Header */} -
-
- + {/* Category Header */} +
+
+
-

{agent.name}

-

{agent.description}

+

{category.name}

+

{category.description}

{/* Capabilities */} -
-

Key Capabilities:

- {agent.capabilities.map((capability, capIndex) => ( +
+

Key Capabilities:

+ {category.capabilities.map((capability, capIndex) => ( - + {capability} ))}
- {/* Agent Usage Indicator */} -
- - @{agent.name.toLowerCase().replace(/\s+/g, '_')} - -

- Direct your queries to this agent using @mentions + {/* Examples */} +

+
+ + Example Agents: +
+

+ {category.examples}

+ + {/* Hover Effect Border */} +
))}
@@ -88,21 +92,24 @@ export default function AgentsSection() { viewport={{ once: true }} className="text-center mt-10 sm:mt-16" > -
+

Intelligent Agent Orchestration

- Our planner automatically selects and coordinates the right agents for your specific query, - or you can direct questions to specific agents using @mentions for precise control. + Our intelligent planner automatically selects and coordinates the right agents from these categories for your specific query. + You can also direct questions to specific agents using @mentions for precise control over your analysis workflow.

-
- {agents.map((agent, index) => ( - - @{agent.name.toLowerCase().replace(/\s+/g, '_')} +
+ {templateCategories.map((category, index) => ( + + {category.name} ))}
+

+ We are continuously adding new templates for you. +

diff --git a/auto-analyst-frontend/components/landing/FnT.tsx b/auto-analyst-frontend/components/landing/FnT.tsx index a528f8e9..2fc83157 100644 --- a/auto-analyst-frontend/components/landing/FnT.tsx +++ b/auto-analyst-frontend/components/landing/FnT.tsx @@ -1,5 +1,5 @@ "use client" -import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe } from "lucide-react" +import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe, Wrench, Target, Eye } from "lucide-react" export const features = [ { @@ -34,6 +34,55 @@ export const features = [ }, ] +export const templateCategories = [ + { + icon: Wrench, + name: "Data Manipulation", + description: "Transform, clean, and prepare your data for analysis", + capabilities: [ + "Clean and preprocess datasets with advanced techniques", + "Handle missing values and data quality issues", + "Transform and reshape data structures", + "Merge, join, and aggregate multiple data sources", + "High-performance data processing capabilities" + ], + color: "from-red-300 to-red-400", + bgGradient: "from-red-50 to-red-100", + examples: "Pandas preprocessing, Polars optimization, data cleaning specialists" + }, + { + icon: Target, + name: "Data Modelling", + description: "Build statistical models and machine learning algorithms", + capabilities: [ + "Statistical analysis and hypothesis testing", + "Machine learning model development", + "Predictive analytics and forecasting", + "Feature engineering and selection", + "Model validation and performance evaluation" + ], + color: "from-red-400 to-red-500", + bgGradient: "from-red-100 to-red-200", + examples: "Statistical analysis, ML algorithms, predictive modeling" + }, + { + icon: Eye, + name: "Data Visualization", + description: "Create compelling charts and interactive visualizations", + capabilities: [ + "Interactive and static chart creation", + "Multi-dimensional data visualization", + "Statistical plot recommendations", + "Custom styling and formatting options", + "Publication-ready visual outputs" + ], + color: "from-red-500 to-red-600", + bgGradient: "from-red-200 to-red-300", + examples: "Plotly interactives, Matplotlib static plots, Seaborn statistical charts" + } +] + +// Legacy agents array for backward compatibility export const agents = [ { icon: Database, From fd69ed54896d97279aedb747537400c4e1218cad Mon Sep 17 00:00:00 2001 From: Ashad Qureshi Date: Wed, 18 Jun 2025 13:42:05 +0500 Subject: [PATCH 4/5] Landing Page - Templates v2 --- .../scripts/populate_agent_templates.py | 52 ++++---- .../components/landing/AgentsSection.tsx | 116 ++++++++++++++---- .../components/landing/FnT.tsx | 31 ++--- .../components/landing/LandingPage.tsx | 2 +- .../public/icons/templates/numpy.svg | 1 + .../public/icons/templates/statsmodel.svg | 74 +++++++++++ .../public/icons/templates/xgboost.png | Bin 0 -> 18577 bytes 7 files changed, 213 insertions(+), 63 deletions(-) create mode 100644 auto-analyst-frontend/public/icons/templates/numpy.svg create mode 100644 auto-analyst-frontend/public/icons/templates/statsmodel.svg create mode 100644 auto-analyst-frontend/public/icons/templates/xgboost.png diff --git a/auto-analyst-backend/scripts/populate_agent_templates.py b/auto-analyst-backend/scripts/populate_agent_templates.py index 8244562e..aaedd215 100644 --- a/auto-analyst-backend/scripts/populate_agent_templates.py +++ b/auto-analyst-backend/scripts/populate_agent_templates.py @@ -375,35 +375,35 @@ def populate_agents_and_templates(include_defaults=True, include_premiums=True): print(f"\nšŸ”’ --- Processing Premium Templates (Paid) ---") for category, templates in PREMIUM_TEMPLATES.items(): print(f"\nšŸ“ {category}:") + + for template_data in templates: + template_name = template_data["template_name"] + + # Check if template already exists + existing = session.query(AgentTemplate).filter( + AgentTemplate.template_name == template_name + ).first() + + if existing: + print(f"ā­ļø Skipping {template_name} (already exists)") + skipped_count += 1 + continue - for template_data in templates: - template_name = template_data["template_name"] - - # Check if template already exists - existing = session.query(AgentTemplate).filter( - AgentTemplate.template_name == template_name - ).first() - - if existing: - print(f"ā­ļø Skipping {template_name} (already exists)") - skipped_count += 1 - continue - # Create new premium template - template = AgentTemplate( - template_name=template_name, - display_name=template_data["display_name"], - description=template_data["description"], - icon_url=template_data["icon_url"], - prompt_template=template_data["prompt_template"], - category=category, + template = AgentTemplate( + template_name=template_name, + display_name=template_data["display_name"], + description=template_data["description"], + icon_url=template_data["icon_url"], + prompt_template=template_data["prompt_template"], + category=category, is_premium_only=True, # Premium templates require subscription - is_active=True, - created_at=datetime.now(UTC), - updated_at=datetime.now(UTC) - ) - - session.add(template) + is_active=True, + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC) + ) + + session.add(template) print(f"āœ… Created premium template: {template_name}") premium_created += 1 diff --git a/auto-analyst-frontend/components/landing/AgentsSection.tsx b/auto-analyst-frontend/components/landing/AgentsSection.tsx index 78c74b2d..69fcb0e8 100644 --- a/auto-analyst-frontend/components/landing/AgentsSection.tsx +++ b/auto-analyst-frontend/components/landing/AgentsSection.tsx @@ -3,8 +3,28 @@ import { motion } from "framer-motion" import { templateCategories } from "./FnT" import { Badge } from "@/components/ui/badge" import { CheckCircle, Plus } from "lucide-react" +import Image from "next/image" export default function AgentsSection() { + // Library showcase for each category + const libraryShowcase = { + "Data Manipulation": [ + { name: "Pandas", icon: "/icons/templates/preprocessing_agent.svg" }, + { name: "NumPy", icon: "/icons/templates/numpy.svg" }, + { name: "Polars", icon: "/icons/templates/polars.svg" } + ], + "Data Modelling": [ + { name: "Scikit-Learn", icon: "/icons/templates/sk_learn_agent.svg" }, + { name: "XGBoost", icon: "/icons/templates/xgboost.png" }, + { name: "Statistical Models", icon: "/icons/templates/statsmodel.svg" } + ], + "Data Visualization": [ + { name: "Plotly", icon: "/icons/templates/data_viz_agent.svg" }, + { name: "Matplotlib", icon: "/icons/templates/matplotlib.svg" }, + { name: "Seaborn", icon: "/icons/templates/seaborn.svg" } + ] + } + return (
@@ -16,13 +36,46 @@ export default function AgentsSection() { className="text-center mb-10 sm:mb-16" >

- Three Categories of AI Agents + Powered by Industry-Leading Libraries

- Auto-Analyst organizes specialized AI agents into three powerful categories, each designed to handle specific aspects of your data science workflow with precision and expertise. + Auto-Analyst harnesses the power of the most trusted data science libraries, organized into three specialized categories for maximum efficiency.

+ {/* Library Icons Showcase */} + +

Major Libraries Integrated

+
+ {Object.values(libraryShowcase).flat().map((library, index) => ( + +
+ {library.name} +
+ {library.name} +
+ ))} +
+
+
{templateCategories.map((category, index) => ( {/* Category Header */} -
+
@@ -48,10 +101,37 @@ export default function AgentsSection() {
+ {/* Featured Libraries for this Category */} +
+

Featured Libraries:

+
+ {libraryShowcase[category.name as keyof typeof libraryShowcase]?.map((library, libIndex) => ( + +
+ {library.name} +
+ {library.name} +
+ ))} +
+
+ {/* Capabilities */} -
-

Key Capabilities:

- {category.capabilities.map((capability, capIndex) => ( +
+

What You Can Do:

+ {category.capabilities.slice(0, 3).map((capability, capIndex) => ( - - {capability} + + {capability} ))} -
- - {/* Examples */} -
-
- - Example Agents: -
-

- {category.examples} + {category.capabilities.length > 3 && ( +

+ + {category.capabilities.length - 3} more capabilities

+ )}
@@ -94,11 +168,11 @@ export default function AgentsSection() { >

- Intelligent Agent Orchestration + Smart Agent Selection

- Our intelligent planner automatically selects and coordinates the right agents from these categories for your specific query. - You can also direct questions to specific agents using @mentions for precise control over your analysis workflow. + Our AI planner automatically chooses the best libraries and agents for your task. + Use @mentions to call specific agents directly.

{templateCategories.map((category, index) => ( diff --git a/auto-analyst-frontend/components/landing/FnT.tsx b/auto-analyst-frontend/components/landing/FnT.tsx index 2fc83157..4e43f015 100644 --- a/auto-analyst-frontend/components/landing/FnT.tsx +++ b/auto-analyst-frontend/components/landing/FnT.tsx @@ -1,5 +1,5 @@ "use client" -import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe, Wrench, Target, Eye } from "lucide-react" +import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe, Wrench, Target, ScatterChart, Table2 } from "lucide-react" export const features = [ { @@ -36,15 +36,13 @@ export const features = [ export const templateCategories = [ { - icon: Wrench, + icon: Table2, name: "Data Manipulation", description: "Transform, clean, and prepare your data for analysis", capabilities: [ "Clean and preprocess datasets with advanced techniques", "Handle missing values and data quality issues", "Transform and reshape data structures", - "Merge, join, and aggregate multiple data sources", - "High-performance data processing capabilities" ], color: "from-red-300 to-red-400", bgGradient: "from-red-50 to-red-100", @@ -56,24 +54,20 @@ export const templateCategories = [ description: "Build statistical models and machine learning algorithms", capabilities: [ "Statistical analysis and hypothesis testing", - "Machine learning model development", "Predictive analytics and forecasting", - "Feature engineering and selection", - "Model validation and performance evaluation" + "Sophisticated ML techniques for advanced modelling", ], color: "from-red-400 to-red-500", bgGradient: "from-red-100 to-red-200", examples: "Statistical analysis, ML algorithms, predictive modeling" }, { - icon: Eye, + icon: ScatterChart, name: "Data Visualization", description: "Create compelling charts and interactive visualizations", capabilities: [ "Interactive and static chart creation", "Multi-dimensional data visualization", - "Statistical plot recommendations", - "Custom styling and formatting options", "Publication-ready visual outputs" ], color: "from-red-500 to-red-600", @@ -105,8 +99,6 @@ export const agents = [ "Correlation and regression analysis", "Hypothesis testing and A/B tests", "Time series analysis", - "Statistical modeling", - "Confidence intervals and p-values" ], color: "from-green-500 to-green-600" }, @@ -115,11 +107,9 @@ export const agents = [ name: "Scikit-Learn Agent", description: "Machine learning specialist for predictive modeling", capabilities: [ - "Random Forest and ensemble methods", "K-means clustering analysis", "Classification and regression", "Feature selection and engineering", - "Model evaluation and validation" ], color: "from-purple-500 to-purple-600" }, @@ -129,7 +119,6 @@ export const agents = [ description: "Interactive visualizations using Plotly", capabilities: [ "Interactive charts and graphs", - "Statistical plot recommendations", "Multi-dimensional visualizations", "Custom styling and formatting", "Export-ready visualizations" @@ -138,6 +127,18 @@ export const agents = [ } ] +export const majorLibraries = [ + { name: "Pandas", category: "Data Manipulation", icon: "/icons/templates/preprocessing_agent.svg", description: "Data cleaning & preprocessing" }, + { name: "NumPy", category: "Data Manipulation", icon: "/icons/templates/numpy.svg", description: "Numerical computing foundation" }, + { name: "Polars", category: "Data Manipulation", icon: "/icons/templates/polars.svg", description: "High-performance data processing" }, + { name: "Scikit-Learn", category: "Data Modelling", icon: "/icons/templates/sk_learn_agent.svg", description: "Machine learning algorithms" }, + { name: "XGBoost", category: "Data Modelling", icon: "/icons/templates/xgboost.svg", description: "Gradient boosting framework" }, + { name: "Statistical Models", category: "Data Modelling", icon: "/icons/templates/statsmodels.svg", description: "Statistical analysis tools" }, + { name: "Plotly", category: "Data Visualization", icon: "/icons/templates/data_viz_agent.svg", description: "Interactive visualizations" }, + { name: "Matplotlib", category: "Data Visualization", icon: "/icons/templates/matplotlib.svg", description: "Static publication plots" }, + { name: "Seaborn", category: "Data Visualization", icon: "/icons/templates/seaborn.svg", description: "Statistical visualizations" } +] + export const supportedConnectors = [ { category: "File Formats", diff --git a/auto-analyst-frontend/components/landing/LandingPage.tsx b/auto-analyst-frontend/components/landing/LandingPage.tsx index 22ad4cb7..03c55cc4 100644 --- a/auto-analyst-frontend/components/landing/LandingPage.tsx +++ b/auto-analyst-frontend/components/landing/LandingPage.tsx @@ -101,8 +101,8 @@ export default function LandingPage() {
- + diff --git a/auto-analyst-frontend/public/icons/templates/numpy.svg b/auto-analyst-frontend/public/icons/templates/numpy.svg new file mode 100644 index 00000000..262f0301 --- /dev/null +++ b/auto-analyst-frontend/public/icons/templates/numpy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auto-analyst-frontend/public/icons/templates/statsmodel.svg b/auto-analyst-frontend/public/icons/templates/statsmodel.svg new file mode 100644 index 00000000..ac9aabbc --- /dev/null +++ b/auto-analyst-frontend/public/icons/templates/statsmodel.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/auto-analyst-frontend/public/icons/templates/xgboost.png b/auto-analyst-frontend/public/icons/templates/xgboost.png new file mode 100644 index 0000000000000000000000000000000000000000..fab1fbf996be352dfb1697132642947bbf3e0dc2 GIT binary patch literal 18577 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 DI0wPs literal 0 HcmV?d00001 From 11c1c8152673fae48d519650f7a24fc7ffe48acd Mon Sep 17 00:00:00 2001 From: Ashad Qureshi Date: Wed, 18 Jun 2025 13:49:09 +0500 Subject: [PATCH 5/5] Indentation Fix --- .../scripts/populate_agent_templates.py | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/auto-analyst-backend/scripts/populate_agent_templates.py b/auto-analyst-backend/scripts/populate_agent_templates.py index aaedd215..8244562e 100644 --- a/auto-analyst-backend/scripts/populate_agent_templates.py +++ b/auto-analyst-backend/scripts/populate_agent_templates.py @@ -375,35 +375,35 @@ def populate_agents_and_templates(include_defaults=True, include_premiums=True): print(f"\nšŸ”’ --- Processing Premium Templates (Paid) ---") for category, templates in PREMIUM_TEMPLATES.items(): print(f"\nšŸ“ {category}:") - - for template_data in templates: - template_name = template_data["template_name"] - - # Check if template already exists - existing = session.query(AgentTemplate).filter( - AgentTemplate.template_name == template_name - ).first() - - if existing: - print(f"ā­ļø Skipping {template_name} (already exists)") - skipped_count += 1 - continue + for template_data in templates: + template_name = template_data["template_name"] + + # Check if template already exists + existing = session.query(AgentTemplate).filter( + AgentTemplate.template_name == template_name + ).first() + + if existing: + print(f"ā­ļø Skipping {template_name} (already exists)") + skipped_count += 1 + continue + # Create new premium template - template = AgentTemplate( - template_name=template_name, - display_name=template_data["display_name"], - description=template_data["description"], - icon_url=template_data["icon_url"], - prompt_template=template_data["prompt_template"], - category=category, + template = AgentTemplate( + template_name=template_name, + display_name=template_data["display_name"], + description=template_data["description"], + icon_url=template_data["icon_url"], + prompt_template=template_data["prompt_template"], + category=category, is_premium_only=True, # Premium templates require subscription - is_active=True, - created_at=datetime.now(UTC), - updated_at=datetime.now(UTC) - ) - - session.add(template) + is_active=True, + created_at=datetime.now(UTC), + updated_at=datetime.now(UTC) + ) + + session.add(template) print(f"āœ… Created premium template: {template_name}") premium_created += 1