diff --git a/backend/routes/aiRoutes.js b/backend/routes/aiRoutes.js index 7ddc6a6..feb95cc 100644 --- a/backend/routes/aiRoutes.js +++ b/backend/routes/aiRoutes.js @@ -25,7 +25,7 @@ const offTopicCache = new NodeCache({ stdTTL: 3600 }); * 200 {"text": "...", "model": "models/gemini-2.5-flash"} */ async function generateHandler(req, res) { - const { prompt, history = [] } = req.body || {}; + const { prompt, history = [], systemInstruction } = req.body || {}; if (!prompt || !prompt.trim()) { return res.status(400).json({ error: "Missing prompt" }); } @@ -73,7 +73,7 @@ async function generateHandler(req, res) { try { const model = genAI.getGenerativeModel({ model: m, - systemInstruction: `You are PrepPilot AI Mentor. + systemInstruction: systemInstruction || `You are PrepPilot AI Mentor. 1. Allow friendly greetings and casual onboarding conversation. 2. Focus primarily on PrepPilot-related domains: interview preparation, coding interviews, aptitude, resumes, career guidance, mock interviews, and platform usage. 3. Politely redirect unrelated conversations. @@ -106,6 +106,10 @@ async function generateHandler(req, res) { if (!result) throw lastErr || new Error("All Gemini models failed"); const rawText = await result.response.text(); + console.log("Incoming Prompt:", prompt); + console.log("Model Used:", usedModel); + console.log("Raw Gemini Response:", rawText); + let cleanedText = rawText .replace(/^[\s`]*json\s*/i, "") .replace(/^\s*```/i, "") diff --git a/backend/validation/aiPromptSchema.js b/backend/validation/aiPromptSchema.js index 50039c1..2972c44 100644 --- a/backend/validation/aiPromptSchema.js +++ b/backend/validation/aiPromptSchema.js @@ -35,9 +35,16 @@ const safePrompt = (value, helpers) => { const aiPromptSchema = Joi.object({ prompt: Joi.string() .min(1) - .max(500) + .max(5000) .required() .custom(safePrompt, "Prompt Injection Protection"), + systemInstruction: Joi.string().optional(), + history: Joi.array().items( + Joi.object({ + role: Joi.string().valid("user", "model").required(), + text: Joi.string().allow("").required() + }) + ).optional() role: Joi.string().min(2).max(50).optional().custom(safePrompt, "Role Injection Protection"), diff --git a/frontend/src/pages/ProjectIdeas/ProjectIdeas.jsx b/frontend/src/pages/ProjectIdeas/ProjectIdeas.jsx index 6cd2d33..a645c39 100644 --- a/frontend/src/pages/ProjectIdeas/ProjectIdeas.jsx +++ b/frontend/src/pages/ProjectIdeas/ProjectIdeas.jsx @@ -16,6 +16,7 @@ import { BookOpen, Star, Zap, + X, } from "lucide-react"; // ───────────────────────────────────────────────────────── @@ -99,13 +100,39 @@ const LEVELS = [ // ───────────────────────────────────────────────────────── // Helpers // ───────────────────────────────────────────────────────── -function buildRequestBody(domainLabel, level) { - // Backend schema: prompt(max 500), role(max 50), topic(max 100) — all required - return { - role: `${level} ${domainLabel} developer`, - topic: `${domainLabel} project ideas for ${level} level`, - prompt: `List 3 ${level} ${domainLabel} project ideas as JSON array. Each: {title, tagline, techStack:[], features:[], githubSearch, difficulty, domain}. Return only valid JSON array.`, - }; +function buildPrompt(domainLabel, level) { + return `Generate 3 to 5 unique project ideas for a ${level} level ${domainLabel} developer. +Avoid generic ideas like Todo App, Calculator, or Weather App. + +For Frontend, prefer things like: Real-time collaborative whiteboard, Design system builder, Accessibility auditing dashboard. +For Backend, prefer things like: Distributed job scheduler, Event-driven notification platform. +For Full Stack, prefer things like: AI-powered hiring platform, Skill exchange marketplace. +For AI / ML, prefer things like: Resume scoring engine, Interview performance analyzer. +For DevOps / Cloud, prefer things like: Kubernetes deployment assistant, Infrastructure monitoring platform. +For Java, prefer things like: Banking transaction simulator, Distributed inventory system. + +For each project, provide: +- "title": Project Title +- "description": Short Description +- "techStack": Array of technologies +- "features": Array of key features +- "learningOutcomes": Array of learning outcomes +- "difficulty": "${level}" +- "resumeValue": String explaining resume value + +Return ONLY a valid JSON array of objects with the exact keys: +[ + { + "title": "...", + "description": "...", + "techStack": ["..."], + "features": ["..."], + "learningOutcomes": ["..."], + "difficulty": "...", + "resumeValue": "..." + } +] +`; } function tryParseJSON(text) { @@ -165,7 +192,7 @@ const IdeaCard = ({ idea, domain, index }) => { {idea.title}
- {idea.tagline} + {idea.description || idea.tagline}
@@ -205,7 +232,7 @@ const IdeaCard = ({ idea, domain, index }) => { {/* Features */} -+ "{idea.resumeValue || "Great addition to your portfolio."}" +
+