Spaces:
Running
Running
| const aiService = require('../services/aiService'); | |
| const localAtsService = require('../services/localAtsService'); | |
| const logger = require('../config/logger'); | |
| /** | |
| * Scan Resume - Hybrid Approach | |
| * Uses local rules for the core score (FREE) and AI for deeper insights if needed. | |
| */ | |
| exports.scanResume = async (req, res) => { | |
| try { | |
| const { resumeData, useAi = false, jobDescription = '', targetJob = '' } = req.body; | |
| if (!resumeData) { | |
| return res.status(400).json({ success: false, message: 'resumeData is required' }); | |
| } | |
| // 1. Always do local analysis (FAST & FREE) | |
| const localResult = localAtsService.analyze(resumeData); | |
| // 2. If user wants AI "Deep Scan", merge results | |
| if (useAi) { | |
| try { | |
| const aiResult = await aiService.analyzeAts(resumeData, jobDescription, targetJob); | |
| // Add AI results to the response | |
| localResult.aiScore = aiResult.score; | |
| localResult.aiGrade = aiResult.grade; | |
| localResult.aiFeedback = aiResult.feedback; | |
| localResult.topImprovements = aiResult.topImprovements || localResult.topImprovements; | |
| } catch (aiErr) { | |
| logger.error(`AI Deep Scan failed: ${aiErr.message}`); | |
| } | |
| } | |
| res.json({ success: true, data: localResult }); | |
| } catch (error) { | |
| logger.error(`ATS Scan Error: ${error.message}`); | |
| res.status(500).json({ success: false, message: error.message }); | |
| } | |
| }; | |
| exports.translateResume = async (req, res) => { | |
| try { | |
| const { resumeData, language } = req.body; | |
| if (!resumeData || !language) { | |
| return res.status(400).json({ success: false, message: 'resumeData and language are required' }); | |
| } | |
| const result = await aiService.translateResume(resumeData, language); | |
| res.json({ success: true, data: result }); | |
| } catch (error) { | |
| logger.error(`Translation Error: ${error.message}`); | |
| res.status(500).json({ success: false, message: error.message }); | |
| } | |
| }; | |
| exports.generateSuggestion = async (req, res) => { | |
| try { | |
| const { type, context, stream = false } = req.body; | |
| if (!type || !context) { | |
| return res.status(400).json({ success: false, message: 'type and context are required' }); | |
| } | |
| if (stream) { | |
| res.setHeader('Content-Type', 'text/event-stream'); | |
| res.setHeader('Cache-Control', 'no-cache'); | |
| res.setHeader('Connection', 'keep-alive'); | |
| await aiService.generateSuggestionStream(type, context, (chunk) => { | |
| res.write(`data: ${JSON.stringify({ chunk })}\n\n`); | |
| }); | |
| res.write('data: [DONE]\n\n'); | |
| return res.end(); | |
| } | |
| const result = await aiService.generateSuggestion(type, context); | |
| res.json({ success: true, data: result }); | |
| } catch (error) { | |
| logger.error(`AI Suggestion Error: ${error.message}`, { stack: error.stack }); | |
| if (!res.headersSent) { | |
| res.status(500).json({ success: false, message: error.message }); | |
| } else { | |
| res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`); | |
| res.end(); | |
| } | |
| } | |
| }; | |