ideas-generator/server/scripts/import-remaining-agents.py
DJP 77da1f44f0 Add comprehensive admin dashboard with analytics, full agent management, and complete system improvements
## Major Features Added:
- Complete admin dashboard with user, agent, conversation, and usage management
- Real-time usage analytics with interactive Chart.js visualizations
- Advanced trend analysis with line charts and bar graphs
- CSV export functionality for usage reports with date/user/agent filtering
- Full CRUD operations for agent management including system prompts and starter messages

## UI/UX Improvements:
- Professional top navigation bar with admin access and logout functionality
- Moved admin link from homepage to navigation for better UX
- Reduced all font sizes by 20% for better formatting consistency
- Changed color scheme from blue to orange (#e6a335) throughout application
- Fixed conversation double-click bug in chat interface
- Added separate starter message field distinct from system instructions

## Backend Enhancements:
- Added analytics API endpoints (/api/analytics/usage, /api/analytics/stats, /api/analytics/trends)
- Enhanced assistant API with admin-level data access and full CRUD operations
- Implemented starterMessage database field with automatic migration and data extraction
- Added comprehensive usage tracking and trend analysis capabilities
- Imported 34 additional agents from CSV (total: 53 agents)

## Technical Architecture:
- Integrated Chart.js with Vue.js for professional data visualization
- Implemented proper chart cleanup to prevent memory leaks
- Added comprehensive error handling and fallback states
- Enhanced API service layer with dedicated analytics methods
- Implemented role-based authentication and admin route protection

## Database Improvements:
- Added starterMessage field to Assistant model with automatic data migration
- Enhanced seed script with proper agent categorization and data cleanup
- Improved assistant API responses to include all necessary admin fields
- Implemented proper foreign key relationships for analytics queries

🚀 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 14:41:32 -04:00

273 lines
No EOL
9.9 KiB
Python
Executable file

#!/usr/bin/env python3
import csv
import json
import re
import sys
import urllib.request
import urllib.parse
import urllib.error
from pathlib import Path
# Get current directory and CSV file path
script_dir = Path(__file__).parent
csv_file = script_dir.parent.parent / "I-gen-assistant-instructions.csv"
api_base = "http://localhost:3000/api"
def slugify(text):
"""Convert text to slug format"""
# Remove special characters and convert to lowercase
text = re.sub(r'[^\w\s-]', '', text).strip().lower()
# Replace spaces and multiple dashes with single dash
return re.sub(r'[-\s]+', '-', text)
def extract_starter_message(system_instructions):
"""Extract starter message from system instructions"""
# Look for common patterns of starter messages
patterns = [
r'STARTER MESSAGE:\s*"([^"]+)"',
r'INITIAL MESSAGE:\s*"([^"]+)"',
r'GREETING:\s*"([^"]+)"',
r'Hello[^.]*\.',
r'Hi[^.]*\.',
r'Welcome[^.]*\.'
]
for pattern in patterns:
match = re.search(pattern, system_instructions, re.IGNORECASE | re.MULTILINE)
if match:
if '"' in pattern:
return match.group(1).strip()
else:
return match.group(0).strip()
# If no pattern found, return None
return None
def categorize_agent(name, instructions):
"""Determine category based on name and instructions"""
name_lower = name.lower()
instructions_lower = instructions.lower()
# Business category keywords
if any(word in name_lower or word in instructions_lower for word in [
'business', 'marketing', 'sales', 'strategy', 'consultant', 'finance',
'management', 'entrepreneur', 'profit', 'revenue', 'market'
]):
return 'business'
# Creative category keywords
if any(word in name_lower or word in instructions_lower for word in [
'creative', 'design', 'art', 'writer', 'writing', 'content', 'story',
'brand', 'advertisement', 'creative', 'innovation', 'idea'
]):
return 'creative'
# Technical category keywords
if any(word in name_lower or word in instructions_lower for word in [
'technical', 'code', 'programming', 'software', 'development', 'api',
'database', 'algorithm', 'technology', 'digital'
]):
return 'technical'
# Educational category keywords
if any(word in name_lower or word in instructions_lower for word in [
'teach', 'learn', 'education', 'training', 'tutorial', 'explain',
'knowledge', 'study', 'academic'
]):
return 'educational'
# Health category keywords
if any(word in name_lower or word in instructions_lower for word in [
'health', 'fitness', 'wellness', 'medical', 'therapy', 'mental',
'physical', 'nutrition', 'exercise'
]):
return 'health'
# Personal category keywords
if any(word in name_lower or word in instructions_lower for word in [
'personal', 'life', 'relationship', 'goal', 'motivation', 'self',
'habit', 'productivity', 'organization'
]):
return 'personal'
# Default to creative
return 'creative'
def get_existing_agents():
"""Get list of existing agent original IDs"""
try:
url = f"{api_base}/assistants?admin=true"
with urllib.request.urlopen(url) as response:
if response.status == 200:
data = json.loads(response.read().decode('utf-8'))
return {agent.get('metadata', {}).get('originalId') for agent in data.get('agents', [])}
else:
print(f"Failed to get existing agents: {response.status}")
return set()
except Exception as e:
print(f"Error getting existing agents: {e}")
return set()
def create_agent(agent_data):
"""Create new agent via API"""
try:
url = f"{api_base}/assistants"
data = json.dumps(agent_data).encode('utf-8')
req = urllib.request.Request(
url,
data=data,
headers={'Content-Type': 'application/json'}
)
with urllib.request.urlopen(req) as response:
if response.status == 201:
result = json.loads(response.read().decode('utf-8'))
return True, result
else:
return False, f"HTTP {response.status}"
except urllib.error.HTTPError as e:
error_body = e.read().decode('utf-8') if hasattr(e, 'read') else str(e)
return False, f"HTTP {e.code}: {error_body}"
except Exception as e:
return False, str(e)
def main():
print("🚀 Starting agent import from CSV...")
if not csv_file.exists():
print(f"❌ CSV file not found: {csv_file}")
sys.exit(1)
# Get existing agents
print("📋 Getting existing agents...")
existing_ids = get_existing_agents()
print(f"Found {len(existing_ids)} existing agents")
# Parse CSV and import new agents
imported_count = 0
skipped_count = 0
error_count = 0
print("📖 Reading CSV file...")
with open(csv_file, 'r', encoding='utf-8') as file:
# Handle potential CSV parsing issues with multi-line fields
content = file.read()
# Split into lines but handle quoted multi-line fields
lines = []
current_line = ""
in_quotes = False
for char in content:
if char == '"' and (len(current_line) == 0 or current_line[-1] != '\\'):
in_quotes = not in_quotes
elif char == '\n' and not in_quotes:
lines.append(current_line)
current_line = ""
continue
current_line += char
if current_line:
lines.append(current_line)
# Parse header
header = lines[0].split(',')
print(f"CSV columns: {header}")
# Process each agent
for i, line in enumerate(lines[1:], 1):
try:
# Handle CSV parsing for quoted fields
fields = []
current_field = ""
in_quotes = False
j = 0
while j < len(line):
char = line[j]
if char == '"':
in_quotes = not in_quotes
elif char == ',' and not in_quotes:
fields.append(current_field.strip('"'))
current_field = ""
j += 1
continue
current_field += char
j += 1
if current_field:
fields.append(current_field.strip('"'))
if len(fields) < 3: # Need at least ID, name, and instructions
print(f"⚠️ Skipping line {i}: insufficient fields")
continue
assistant_id = fields[0].strip()
assistant_name = fields[1].strip()
system_instructions = fields[2].strip() if len(fields) > 2 else ""
# Skip if already imported
if assistant_id in existing_ids:
skipped_count += 1
continue
# Extract starter message
starter_message = extract_starter_message(system_instructions)
# Clean system instructions (remove starter message if found)
if starter_message:
clean_instructions = re.sub(
r'STARTER MESSAGE:\s*"[^"]+"',
'',
system_instructions,
flags=re.IGNORECASE | re.MULTILINE
).strip()
else:
clean_instructions = system_instructions
# Generate default starter message
starter_message = f"Hello! I'm {assistant_name}. How can I help you today?"
# Create agent data
agent_key = slugify(assistant_name)
category = categorize_agent(assistant_name, system_instructions)
agent_data = {
"key": agent_key,
"name": assistant_name,
"description": f"AI assistant specialized in {assistant_name.lower()}",
"category": category,
"systemPrompt": clean_instructions,
"starterMessage": starter_message,
"model": "gpt-4o",
"temperature": 0.7,
"maxTokens": 4000,
"metadata": {
"originalId": assistant_id
}
}
# Create the agent
success, result = create_agent(agent_data)
if success:
print(f"✅ Created agent: {assistant_name}")
imported_count += 1
else:
print(f"❌ Failed to create {assistant_name}: {result}")
error_count += 1
except Exception as e:
print(f"❌ Error processing line {i}: {e}")
error_count += 1
print(f"\n🎉 Import complete!")
print(f"✅ Imported: {imported_count}")
print(f"⏭️ Skipped (already exists): {skipped_count}")
print(f"❌ Errors: {error_count}")
if __name__ == "__main__":
main()