diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2569e6c --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Gemini AI API Key +GEMINI_API_KEY=your_api_key_here + +# Database URL (SQLite for development) +DATABASE_URL=file:./dev.db + +# App URL +NEXT_PUBLIC_APP_URL=http://localhost:3000 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..78d3411 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +# prisma +/prisma/dev.db +/prisma/dev.db-journal + +# old files +style.css.old diff --git a/README.md b/README.md index f5a8ce3..b9d3848 100644 --- a/README.md +++ b/README.md @@ -1 +1,173 @@ -# rag7 \ No newline at end of file +# AI Workflow Automation Discovery Platform + +A comprehensive AI-powered platform that helps founders and business owners discover hidden automation opportunities in their operations through systematic interviews and analysis. + +## Features + +### 🎯 Core Capabilities +- **Systematic Workflow Interviews**: Guided interview process to map daily operations, tasks, and bottlenecks +- **AI-Powered Analysis**: Gemini AI analyzes responses to identify top bottlenecks and automation opportunities +- **Prioritization Matrix**: Visual impact vs. effort matrix for decision-making +- **Implementation Roadmap**: Phased automation implementation plans with timelines +- **Context Engineering Studio**: Design optimized AI agent prompts with behavioral constraints +- **Security Scanning**: AI-powered vulnerability detection supporting multiple languages + +### 🛠️ Technical Stack +- **Framework**: Next.js 14+ with App Router +- **Language**: TypeScript with strict type checking +- **Styling**: Tailwind CSS + shadcn/ui components +- **Database**: Prisma ORM with SQLite (dev) / PostgreSQL (production) +- **AI Integration**: Google Gemini AI API +- **Export**: PDF (jsPDF) and CSV formats + +## Getting Started + +### Prerequisites +- Node.js 18+ +- npm or yarn +- Google Gemini API key + +### Installation + +1. Clone the repository: +```bash +git clone https://github.com/Stacey77/rag7.git +cd rag7 +``` + +2. Install dependencies: +```bash +npm install +``` + +3. Set up environment variables: +```bash +cp .env.example .env +``` + +Edit `.env` and add your Gemini API key: +``` +GEMINI_API_KEY=your_api_key_here +DATABASE_URL=file:./dev.db +NEXT_PUBLIC_APP_URL=http://localhost:3000 +``` + +4. Initialize the database: +```bash +npx prisma db push +npx prisma generate +``` + +5. Run the development server: +```bash +npm run dev +``` + +6. Open [http://localhost:3000](http://localhost:3000) in your browser. + +### Building for Production + +```bash +npm run build +npm start +``` + +## Project Structure + +``` +rag7/ +├── app/ # Next.js App Router pages +│ ├── api/ # API routes +│ │ ├── analysis/ # Analysis generation +│ │ ├── contexts/ # Context templates +│ │ ├── interviews/ # Interview CRUD +│ │ └── security/ # Security scanning +│ ├── analysis/ # Analysis page +│ ├── context-studio/ # Context engineering +│ ├── interview/ # Interview flow +│ ├── security/ # Security scan +│ ├── layout.tsx # Root layout +│ └── page.tsx # Dashboard +├── components/ # React components +│ ├── ui/ # shadcn/ui components +│ ├── Analysis.tsx # Analysis visualization +│ ├── ContextStudio.tsx # Context engineering +│ ├── Dashboard.tsx # Main dashboard +│ ├── Interview.tsx # Interview flow +│ ├── SecurityScan.tsx # Security scanner +│ └── Sidebar.tsx # Navigation +├── lib/ # Utilities and services +│ ├── db/ # Database client +│ ├── export/ # PDF/CSV export +│ ├── gemini/ # Gemini AI service +│ └── utils.ts # Helper functions +├── prisma/ # Database schema +├── types/ # TypeScript types +└── public/ # Static assets +``` + +## API Routes + +### Interviews +- `GET /api/interviews` - List all interviews +- `POST /api/interviews` - Create new interview + +### Analysis +- `POST /api/analysis` - Generate analysis from interview + +### Security +- `POST /api/security` - Scan code for vulnerabilities + +### Context Templates +- `GET /api/contexts` - List templates +- `POST /api/contexts` - Create template + +## Database Schema + +- **Interview**: Stores workflow interview data +- **Analysis**: AI-generated bottleneck and opportunity analysis +- **SecurityScan**: Vulnerability scan results +- **ContextTemplate**: Saved AI agent prompt templates + +## Features in Detail + +### Interview System +Systematic question flow covering: +- Daily workflow mapping +- Task frequency and duration +- Manual bottleneck identification +- Data entry patterns +- Approval processes +- Error correction workflows + +### Analysis Engine +- **Bottleneck Visualization**: Top 3-5 workflow pain points with severity +- **Opportunity Matrix**: Impact vs. effort prioritization +- **Implementation Roadmap**: Phased automation plan + +### Context Studio +- AI agent role and expertise configuration +- Output tone/style selection (Professional, Casual, Technical, Consultative, Executive) +- Behavioral constraints with quick-add examples +- Prompt generation and template saving + +### Security Scanner +Multi-language vulnerability detection: +- SQL Injection, XSS, CSRF +- Hardcoded secrets +- Path traversal, Command injection +- Insecure deserialization +- OWASP Top 10 mapping +- Remediation suggestions with code examples + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## License + +This project is licensed under the MIT License. + +## Security + +See [SECURITY.md](SECURITY.md) for reporting security vulnerabilities. \ No newline at end of file diff --git a/app/analysis/page.tsx b/app/analysis/page.tsx new file mode 100644 index 0000000..cb046b6 --- /dev/null +++ b/app/analysis/page.tsx @@ -0,0 +1,5 @@ +import { Analysis } from '@/components/Analysis'; + +export default function AnalysisPage() { + return ; +} diff --git a/app/api/analysis/route.ts b/app/api/analysis/route.ts new file mode 100644 index 0000000..09151f0 --- /dev/null +++ b/app/api/analysis/route.ts @@ -0,0 +1,70 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/lib/db/prisma'; +import { GeminiService } from '@/lib/gemini/service'; + +// POST /api/analysis - Generate analysis from interview +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { interviewId } = body; + + if (!interviewId) { + return NextResponse.json( + { error: 'Interview ID is required' }, + { status: 400 } + ); + } + + // Fetch interview + const interview = await prisma.interview.findUnique({ + where: { id: interviewId }, + }); + + if (!interview) { + return NextResponse.json( + { error: 'Interview not found' }, + { status: 404 } + ); + } + + const responses = JSON.parse(interview.responses); + + // Generate analysis using Gemini + const apiKey = process.env.GEMINI_API_KEY; + if (!apiKey) { + return NextResponse.json( + { error: 'Gemini API key not configured' }, + { status: 500 } + ); + } + + const gemini = new GeminiService(apiKey); + const analysisResult = await gemini.analyzeWorkflow(responses); + + // Generate roadmap + const roadmap = await gemini.generateRoadmap(analysisResult.opportunities); + + // Save analysis + const analysis = await prisma.analysis.create({ + data: { + interviewId, + bottlenecks: JSON.stringify(analysisResult.bottlenecks), + opportunities: JSON.stringify(analysisResult.opportunities), + roadmap: JSON.stringify(roadmap), + }, + }); + + return NextResponse.json({ + ...analysis, + bottlenecks: JSON.parse(analysis.bottlenecks), + opportunities: JSON.parse(analysis.opportunities), + roadmap: JSON.parse(analysis.roadmap), + }); + } catch (error) { + console.error('Error generating analysis:', error); + return NextResponse.json( + { error: 'Failed to generate analysis' }, + { status: 500 } + ); + } +} diff --git a/app/api/contexts/route.ts b/app/api/contexts/route.ts new file mode 100644 index 0000000..b735667 --- /dev/null +++ b/app/api/contexts/route.ts @@ -0,0 +1,55 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/lib/db/prisma'; + +// GET /api/contexts - List all context templates +export async function GET(request: NextRequest) { + try { + const templates = await prisma.contextTemplate.findMany({ + orderBy: { createdAt: 'desc' }, + }); + + return NextResponse.json(templates); + } catch (error) { + console.error('Error fetching context templates:', error); + return NextResponse.json( + { error: 'Failed to fetch templates' }, + { status: 500 } + ); + } +} + +// POST /api/contexts - Create new context template +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { name, description, role, domain, context, tone, constraints, userId } = body; + + if (!name || !role || !domain || !context || !tone) { + return NextResponse.json( + { error: 'Required fields are missing' }, + { status: 400 } + ); + } + + const template = await prisma.contextTemplate.create({ + data: { + name, + description: description || '', + role, + domain, + context, + tone, + constraints: typeof constraints === 'string' ? constraints : JSON.stringify(constraints), + userId, + }, + }); + + return NextResponse.json(template); + } catch (error) { + console.error('Error creating context template:', error); + return NextResponse.json( + { error: 'Failed to create template' }, + { status: 500 } + ); + } +} diff --git a/app/api/interviews/route.ts b/app/api/interviews/route.ts new file mode 100644 index 0000000..3cff2b2 --- /dev/null +++ b/app/api/interviews/route.ts @@ -0,0 +1,62 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/lib/db/prisma'; + +// GET /api/interviews - List all interviews +export async function GET(request: NextRequest) { + try { + const interviews = await prisma.interview.findMany({ + orderBy: { createdAt: 'desc' }, + include: { + analyses: true, + }, + }); + + const formattedInterviews = interviews.map((interview) => ({ + ...interview, + responses: JSON.parse(interview.responses), + })); + + return NextResponse.json(formattedInterviews); + } catch (error) { + console.error('Error fetching interviews:', error); + return NextResponse.json( + { error: 'Failed to fetch interviews' }, + { status: 500 } + ); + } +} + +// POST /api/interviews - Create new interview +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { title, responses, status = 'draft', userId } = body; + + if (!title || !responses) { + return NextResponse.json( + { error: 'Title and responses are required' }, + { status: 400 } + ); + } + + const interview = await prisma.interview.create({ + data: { + title, + responses: JSON.stringify(responses), + status, + userId, + }, + }); + + return NextResponse.json({ + ...interview, + responses: JSON.parse(interview.responses), + }); + } catch (error) { + console.error('Error creating interview:', error); + return NextResponse.json( + { error: 'Failed to create interview' }, + { status: 500 } + ); + } +} diff --git a/app/api/security/route.ts b/app/api/security/route.ts new file mode 100644 index 0000000..8193be4 --- /dev/null +++ b/app/api/security/route.ts @@ -0,0 +1,53 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { prisma } from '@/lib/db/prisma'; +import { GeminiService } from '@/lib/gemini/service'; + +// POST /api/security/scan - Run security scan +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { codeSnippet, language } = body; + + if (!codeSnippet || !language) { + return NextResponse.json( + { error: 'Code snippet and language are required' }, + { status: 400 } + ); + } + + // Scan code using Gemini + const apiKey = process.env.GEMINI_API_KEY; + if (!apiKey) { + return NextResponse.json( + { error: 'Gemini API key not configured' }, + { status: 500 } + ); + } + + const gemini = new GeminiService(apiKey); + const scanResult = await gemini.scanForVulnerabilities(codeSnippet, language); + + // Save scan results + const scan = await prisma.securityScan.create({ + data: { + codeSnippet, + language, + vulnerabilities: JSON.stringify(scanResult.vulnerabilities), + severity: scanResult.severity, + owaspMappings: JSON.stringify(scanResult.owaspMappings), + }, + }); + + return NextResponse.json({ + ...scan, + vulnerabilities: JSON.parse(scan.vulnerabilities), + owaspMappings: JSON.parse(scan.owaspMappings), + }); + } catch (error) { + console.error('Error scanning code:', error); + return NextResponse.json( + { error: 'Failed to scan code' }, + { status: 500 } + ); + } +} diff --git a/app/context-studio/page.tsx b/app/context-studio/page.tsx new file mode 100644 index 0000000..bd4db78 --- /dev/null +++ b/app/context-studio/page.tsx @@ -0,0 +1,5 @@ +import { ContextStudio } from '@/components/ContextStudio'; + +export default function ContextStudioPage() { + return ; +} diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..10c2d37 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,59 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/app/interview/page.tsx b/app/interview/page.tsx new file mode 100644 index 0000000..7b567b4 --- /dev/null +++ b/app/interview/page.tsx @@ -0,0 +1,5 @@ +import { Interview } from '@/components/Interview'; + +export default function InterviewPage() { + return ; +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..5828116 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,27 @@ +import type { Metadata } from "next"; +import "./globals.css"; +import { Sidebar } from "@/components/Sidebar"; + +export const metadata: Metadata = { + title: "AI Workflow Automation Discovery Platform", + description: "Discover hidden automation opportunities in your operations through systematic interviews and AI-powered analysis", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + +
+ +
+ {children} +
+
+ + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..bb93abc --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,5 @@ +import { Dashboard } from '@/components/Dashboard'; + +export default function DashboardPage() { + return ; +} diff --git a/app/security/page.tsx b/app/security/page.tsx new file mode 100644 index 0000000..fea5203 --- /dev/null +++ b/app/security/page.tsx @@ -0,0 +1,5 @@ +import { SecurityScan } from '@/components/SecurityScan'; + +export default function SecurityPage() { + return ; +} diff --git a/components/Analysis.tsx b/components/Analysis.tsx new file mode 100644 index 0000000..d420dcb --- /dev/null +++ b/components/Analysis.tsx @@ -0,0 +1,395 @@ +'use client'; + +import { useState } from 'react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Badge } from '@/components/ui/badge'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { AlertTriangle, TrendingUp, Download, Loader2 } from 'lucide-react'; +import type { Bottleneck, Opportunity, RoadmapPhase } from '@/types'; + +export function Analysis() { + const [loading, setLoading] = useState(false); + const [bottlenecks, setBottlenecks] = useState([]); + const [opportunities, setOpportunities] = useState([]); + const [roadmap, setRoadmap] = useState([]); + + // Mock data for demonstration + const mockBottlenecks: Bottleneck[] = [ + { + name: 'Manual Data Entry', + description: 'Team spends 10+ hours weekly manually copying data between CRM and accounting software', + severity: 'high', + impact: 'High productivity loss and error-prone', + frequency: 'Daily', + }, + { + name: 'Approval Delays', + description: 'Purchase approvals take 3-5 days due to email-based workflow', + severity: 'medium', + impact: 'Delayed procurement and vendor relationships', + frequency: 'Weekly', + }, + { + name: 'Report Generation', + description: 'Monthly reports require 2 days of manual data compilation', + severity: 'medium', + impact: 'Time-consuming and delays decision-making', + frequency: 'Monthly', + }, + ]; + + const mockOpportunities: Opportunity[] = [ + { + id: '1', + name: 'CRM-Accounting Integration', + description: 'Automated data sync between systems', + impact: 'high', + effort: 'moderate', + priority: 1, + }, + { + id: '2', + name: 'Automated Approval Workflow', + description: 'Digital approval system with notifications', + impact: 'high', + effort: 'easy', + priority: 2, + }, + { + id: '3', + name: 'Automated Reporting Dashboard', + description: 'Real-time dashboard with automated report generation', + impact: 'medium', + effort: 'moderate', + priority: 3, + }, + ]; + + const mockRoadmap: RoadmapPhase[] = [ + { + phase: 1, + name: 'Quick Wins', + duration: '2-4 weeks', + items: [ + 'Implement automated approval workflow', + 'Set up basic email notifications', + 'Create approval tracking dashboard', + ], + considerations: [ + 'Start with non-critical approvals for testing', + 'Train team on new approval process', + 'Monitor adoption and gather feedback', + ], + }, + { + phase: 2, + name: 'Core Integration', + duration: '6-8 weeks', + items: [ + 'Design CRM-Accounting data mapping', + 'Implement bi-directional sync', + 'Set up error handling and logging', + ], + considerations: [ + 'Ensure data integrity during migration', + 'Plan for downtime windows', + 'Create rollback procedures', + ], + }, + { + phase: 3, + name: 'Analytics & Optimization', + duration: '4-6 weeks', + items: [ + 'Build automated reporting dashboard', + 'Implement KPI tracking', + 'Set up automated alerts', + ], + considerations: [ + 'Define key metrics with stakeholders', + 'Ensure data accuracy and validation', + 'Plan for ongoing maintenance', + ], + }, + ]; + + const handleLoadAnalysis = () => { + setLoading(true); + // Simulate loading + setTimeout(() => { + setBottlenecks(mockBottlenecks); + setOpportunities(mockOpportunities); + setRoadmap(mockRoadmap); + setLoading(false); + }, 1500); + }; + + const getSeverityColor = (severity: string) => { + switch (severity) { + case 'critical': + return 'destructive'; + case 'high': + return 'destructive'; + case 'medium': + return 'secondary'; + case 'low': + return 'outline'; + default: + return 'outline'; + } + }; + + const getImpactColor = (impact: string) => { + switch (impact.toLowerCase()) { + case 'high': + return 'default'; + case 'medium': + return 'secondary'; + case 'low': + return 'outline'; + default: + return 'outline'; + } + }; + + if (bottlenecks.length === 0) { + return ( +
+
+ +
+

No Analysis Available

+

+ Complete an interview first to generate workflow analysis +

+
+
+ + +
+
+
+ ); + } + + return ( +
+ {/* Header */} +
+
+

Workflow Analysis

+

+ AI-powered insights into your workflow bottlenecks and opportunities +

+
+ +
+ + {/* Tabs */} + + + Bottlenecks + Opportunities + Implementation Roadmap + + + {/* Bottlenecks Tab */} + + + + Identified Workflow Bottlenecks + + Key pain points discovered in your current processes + + + + {bottlenecks.map((bottleneck, index) => ( + + +
+
+ {bottleneck.name} + {bottleneck.description} +
+ + {bottleneck.severity.toUpperCase()} + +
+
+ +
+
+ Impact: + {bottleneck.impact} +
+
+ Frequency: + {bottleneck.frequency} +
+
+
+
+ ))} +
+
+
+ + {/* Opportunities Tab */} + + + + Automation Opportunities + + Potential AI agent implementations prioritized by impact and effort + + + +
+ {opportunities.map((opportunity) => ( + + +
+
+ {opportunity.name} + {opportunity.description} +
+ + #{opportunity.priority} + +
+
+ +
+ + {opportunity.impact.toUpperCase()} Impact + + + {opportunity.effort.toUpperCase()} Effort + +
+
+
+ ))} +
+
+
+ + {/* Priority Matrix */} + + + Impact vs Effort Matrix + + Visual prioritization of automation opportunities + + + +
+ {/* High Impact */} +
+
+

High Impact / Easy

+
+ {opportunities + .filter((o) => o.impact === 'high' && o.effort === 'easy') + .map((o) => ( +
+ {o.name} +
+ ))} +
+
+
+

High Impact / Moderate

+
+ {opportunities + .filter((o) => o.impact === 'high' && o.effort === 'moderate') + .map((o) => ( +
+ {o.name} +
+ ))} +
+
+
+

High Impact / Difficult

+
+ {opportunities + .filter((o) => o.impact === 'high' && o.effort === 'difficult') + .map((o) => ( +
+ {o.name} +
+ ))} +
+
+
+
+
+
+
+ + {/* Roadmap Tab */} + + + + Implementation Roadmap + + Phased approach to implementing automation opportunities + + + + {roadmap.map((phase) => ( + + +
+
+ + Phase {phase.phase}: {phase.name} + + Duration: {phase.duration} +
+ {phase.duration} +
+
+ +
+

Implementation Items:

+
    + {phase.items.map((item, i) => ( +
  • + + {item} +
  • + ))} +
+
+
+

Key Considerations:

+
    + {phase.considerations.map((consideration, i) => ( +
  • + + {consideration} +
  • + ))} +
+
+
+
+ ))} +
+
+
+
+
+ ); +} diff --git a/components/ContextStudio.tsx b/components/ContextStudio.tsx new file mode 100644 index 0000000..3b28796 --- /dev/null +++ b/components/ContextStudio.tsx @@ -0,0 +1,327 @@ +'use client'; + +import { useState } from 'react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { Badge } from '@/components/ui/badge'; +import { Brain, Copy, Save, Sparkles } from 'lucide-react'; +import type { ToneStyle } from '@/types'; + +const toneStyles: { value: ToneStyle; label: string; description: string }[] = [ + { + value: 'professional', + label: 'Professional', + description: 'Formal, courteous, and business-oriented', + }, + { + value: 'casual', + label: 'Casual', + description: 'Friendly, approachable, and conversational', + }, + { + value: 'technical', + label: 'Technical', + description: 'Precise, detailed, and technical', + }, + { + value: 'consultative', + label: 'Consultative', + description: 'Advisory, strategic, and insightful', + }, + { + value: 'executive', + label: 'Executive Summary', + description: 'Concise, high-level, and strategic', + }, +]; + +const constraintExamples = [ + 'Flag any task requiring >3 manual handoffs', + 'Identify manual data entry between systems', + 'Highlight workflows with >2 hour wait times', + 'Flag manual copy-paste operations', + 'Detect error-prone manual corrections', + 'Identify approval delays >24 hours', + 'Highlight repetitive tasks done >5 times daily', + 'Flag processes without error tracking', + 'Identify tasks taking >30 minutes daily', + 'Detect missing automation opportunities', +]; + +export function ContextStudio() { + const [name, setName] = useState(''); + const [role, setRole] = useState(''); + const [domain, setDomain] = useState(''); + const [context, setContext] = useState(''); + const [tone, setTone] = useState('professional'); + const [constraints, setConstraints] = useState([]); + const [customConstraint, setCustomConstraint] = useState(''); + const [generatedPrompt, setGeneratedPrompt] = useState(''); + const [generating, setGenerating] = useState(false); + + const handleAddConstraint = (constraint: string) => { + if (constraint && !constraints.includes(constraint)) { + setConstraints([...constraints, constraint]); + } + setCustomConstraint(''); + }; + + const handleRemoveConstraint = (index: number) => { + setConstraints(constraints.filter((_, i) => i !== index)); + }; + + const handleGenerate = async () => { + setGenerating(true); + try { + // TODO: Call API to generate prompt with Gemini + await new Promise((resolve) => setTimeout(resolve, 2000)); + + const prompt = `You are ${role}, an expert in ${domain}. + +${context} + +Communication Style: ${tone} + +Behavioral Guidelines: +${constraints.map((c, i) => `${i + 1}. ${c}`).join('\n')} + +Your responses should be ${toneStyles.find((t) => t.value === tone)?.description}. + +Always maintain focus on identifying automation opportunities and providing actionable insights.`; + + setGeneratedPrompt(prompt); + } catch (error) { + alert('Failed to generate prompt'); + } finally { + setGenerating(false); + } + }; + + const handleCopyPrompt = () => { + navigator.clipboard.writeText(generatedPrompt); + alert('Prompt copied to clipboard!'); + }; + + const handleSaveTemplate = async () => { + // TODO: Implement API call to save template + alert('Template saved successfully!'); + }; + + return ( +
+ {/* Header */} +
+

Context Engineering Studio

+

+ Design and optimize AI agent prompts for workflow analysis +

+
+ +
+ {/* Configuration Panel */} +
+ + + Agent Configuration + Define the AI agent's role and expertise + + +
+ + setName(e.target.value)} + /> +
+ +
+ + setRole(e.target.value)} + /> +
+ +
+ + setDomain(e.target.value)} + /> +
+ +
+ +