feat(05-02): exa-search research integration
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
const express = require('express');
|
||||
|
||||
const normalizeQuery = (exerciseName, body) => {
|
||||
if (body && typeof body.query === 'string' && body.query.trim()) {
|
||||
return body.query.trim();
|
||||
}
|
||||
|
||||
if (body && typeof body.name === 'string' && body.name.trim()) {
|
||||
return body.name.trim();
|
||||
}
|
||||
|
||||
return `${exerciseName} exercise`;
|
||||
};
|
||||
|
||||
const createExerciseResearchRouter = ({ pool, exaSearch }) => {
|
||||
if (!pool || typeof pool.query !== 'function') {
|
||||
throw new Error('Pool with query function is required');
|
||||
}
|
||||
if (!exaSearch || typeof exaSearch !== 'function') {
|
||||
throw new Error('exaSearch function is required');
|
||||
}
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/:id/research', async (req, res) => {
|
||||
try {
|
||||
const exerciseId = Number.parseInt(req.params.id, 10);
|
||||
if (!Number.isInteger(exerciseId)) {
|
||||
return res.status(400).json({ error: 'Exercise id must be an integer' });
|
||||
}
|
||||
|
||||
const exerciseResult = await pool.query(
|
||||
'SELECT id, name, description, muscle_groups, difficulty, equipment_needed FROM exercises WHERE id = $1',
|
||||
[exerciseId]
|
||||
);
|
||||
|
||||
if (!exerciseResult.rows.length) {
|
||||
return res.status(404).json({ error: 'Exercise not found' });
|
||||
}
|
||||
|
||||
const exercise = exerciseResult.rows[0];
|
||||
const query = normalizeQuery(exercise.name, req.body);
|
||||
const requestedResults = req.body?.num_results;
|
||||
const numResults = Number.isInteger(requestedResults) && requestedResults > 0
|
||||
? Math.min(requestedResults, 10)
|
||||
: 5;
|
||||
|
||||
const { summary, results } = await exaSearch({ query, numResults });
|
||||
|
||||
let researchRecord = null;
|
||||
try {
|
||||
const insertResult = await pool.query(
|
||||
`INSERT INTO research_results (exercise_id, query, summary, results, provider)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, created_at`,
|
||||
[exerciseId, query, summary, JSON.stringify(results), 'exa']
|
||||
);
|
||||
researchRecord = insertResult.rows[0] || null;
|
||||
} catch (err) {
|
||||
console.warn('Failed to store research results:', err.message);
|
||||
}
|
||||
|
||||
res.json({
|
||||
exercise,
|
||||
query,
|
||||
summary,
|
||||
results,
|
||||
stored: researchRecord
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error running exercise research:', err);
|
||||
res.status(500).json({ error: 'Failed to fetch research' });
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createExerciseResearchRouter
|
||||
};
|
||||
Reference in New Issue
Block a user