const express = require('express'); const db = require('../db'); const { streamCompletion } = require('../lib/llm'); const router = express.Router(); // GET /api/models — list all router.get('/', (req, res) => { try { const rows = db.prepare('SELECT * FROM models ORDER BY id').all(); res.json(rows); } catch (err) { console.error('[models] list error:', err.message); res.status(500).json({ error: err.message }); } }); // POST /api/models — create router.post('/', (req, res) => { const { name, api_base, api_key, provider, is_default_main, is_default_fork, is_default_exam } = req.body; if (!name || !api_base || !provider) { return res.status(400).json({ error: 'name, api_base, and provider are required' }); } try { const info = db.prepare(` INSERT INTO models (name, api_base, api_key, provider, is_default_main, is_default_fork, is_default_exam) VALUES (?, ?, ?, ?, ?, ?, ?) `).run( name, api_base, api_key || '', provider, is_default_main ? 1 : 0, is_default_fork ? 1 : 0, is_default_exam ? 1 : 0 ); // If setting a default flag, unset others for that role const newId = info.lastInsertRowid; if (is_default_main) unsetOtherDefaults(newId, 'is_default_main'); if (is_default_fork) unsetOtherDefaults(newId, 'is_default_fork'); if (is_default_exam) unsetOtherDefaults(newId, 'is_default_exam'); const row = db.prepare('SELECT * FROM models WHERE id = ?').get(newId); res.status(201).json(row); } catch (err) { console.error('[models] create error:', err.message); res.status(500).json({ error: err.message }); } }); // PUT /api/models/:id — update router.put('/:id', (req, res) => { const id = parseInt(req.params.id, 10); if (Number.isNaN(id)) { return res.status(400).json({ error: 'Invalid model id' }); } const { name, api_base, api_key, provider, is_default_main, is_default_fork, is_default_exam } = req.body; try { const existing = db.prepare('SELECT * FROM models WHERE id = ?').get(id); if (!existing) { return res.status(404).json({ error: 'Model not found' }); } db.prepare(` UPDATE models SET name = COALESCE(?, name), api_base = COALESCE(?, api_base), api_key = ?, provider = COALESCE(?, provider), is_default_main = COALESCE(?, is_default_main), is_default_fork = COALESCE(?, is_default_fork), is_default_exam = COALESCE(?, is_default_exam) WHERE id = ? `).run( name ?? null, api_base ?? null, api_key !== undefined ? (api_key === null ? '' : api_key) : null, provider ?? null, is_default_main !== undefined ? (is_default_main ? 1 : 0) : null, is_default_fork !== undefined ? (is_default_fork ? 1 : 0) : null, is_default_exam !== undefined ? (is_default_exam ? 1 : 0) : null, id ); if (is_default_main) unsetOtherDefaults(id, 'is_default_main'); if (is_default_fork) unsetOtherDefaults(id, 'is_default_fork'); if (is_default_exam) unsetOtherDefaults(id, 'is_default_exam'); const row = db.prepare('SELECT * FROM models WHERE id = ?').get(id); res.json(row); } catch (err) { console.error('[models] update error:', err.message); res.status(500).json({ error: err.message }); } }); // DELETE /api/models/:id router.delete('/:id', (req, res) => { const id = parseInt(req.params.id, 10); if (Number.isNaN(id)) { return res.status(400).json({ error: 'Invalid model id' }); } try { // Reject if conversations reference this model const convCount = db.prepare('SELECT COUNT(*) as count FROM conversations WHERE model_id = ?').get(id); if (convCount.count > 0) { return res.status(409).json({ error: 'Cannot delete model referenced by conversations' }); } const info = db.prepare('DELETE FROM models WHERE id = ?').run(id); if (info.changes === 0) { return res.status(404).json({ error: 'Model not found' }); } res.json({ deleted: true }); } catch (err) { console.error('[models] delete error:', err.message); res.status(500).json({ error: err.message }); } }); // POST /api/models/:id/test — send "di hola" and return latency router.post('/:id/test', async (req, res) => { const id = parseInt(req.params.id, 10); if (Number.isNaN(id)) { return res.status(400).json({ error: 'Invalid model id' }); } try { const model = db.prepare('SELECT * FROM models WHERE id = ?').get(id); if (!model) { return res.status(404).json({ error: 'Model not found' }); } const start = Date.now(); let fullText = ''; for await (const chunk of streamCompletion(model, [{ role: 'user', content: 'di hola' }], '')) { if (chunk.error) { return res.status(502).json({ error: chunk.error }); } if (chunk.done) { fullText = chunk.fullText; } } const latency = Date.now() - start; res.json({ latency_ms: latency, response: fullText.trim() }); } catch (err) { console.error('[models] test error:', err.message); res.status(500).json({ error: err.message }); } }); function unsetOtherDefaults(exceptId, column) { db.prepare(`UPDATE models SET ${column} = 0 WHERE id != ?`).run(exceptId); } module.exports = router;