const express = require('express'); const router = express.Router(); const { PROVIDER_PRESETS, getProviders, getProvider, saveProvider, deleteProvider, maskKey, chatCompletion, syncAiConfigFile } = require('../lib/ai'); const { logAudit } = require('../db'); router.get('/', (req, res) => { const providers = getProviders().map(p => ({ ...p, api_key_masked: maskKey(getProvider(p.id)?.api_key) })); res.render('ai-providers', { providers, presets: PROVIDER_PRESETS, saved: req.query.saved === '1', tested: req.query.tested, error: req.query.error || null }); }); router.post('/save', (req, res) => { const { id, name, provider_type, api_key, base_url, default_model, is_active, is_default } = req.body; const preset = PROVIDER_PRESETS[provider_type] || PROVIDER_PRESETS.custom; let key = api_key; if (id && (!key || key.includes('••••'))) { const existing = getProvider(id); key = existing?.api_key || ''; } saveProvider({ id: id ? parseInt(id, 10) : null, name: name || preset.label, provider_type: provider_type || 'openrouter', api_key: key, base_url: base_url || preset.base_url, default_model: default_model || preset.models[0] || '', is_active: is_active === '1', is_default: is_default === '1' }); logAudit(req.session.userId, req.session.username, 'ai_provider_saved', 'ai_provider', id || null, name); res.redirect('/ai?saved=1'); }); router.post('/delete/:id', (req, res) => { deleteProvider(req.params.id); logAudit(req.session.userId, req.session.username, 'ai_provider_deleted', 'ai_provider', req.params.id, ''); res.redirect('/ai?saved=1'); }); router.post('/sync', (req, res) => { syncAiConfigFile(); res.redirect('/ai?saved=1'); }); router.post('/test/:id', async (req, res) => { try { const result = await chatCompletion( [{ role: 'user', content: 'Antwoord met exact: Mek-Tech AI verbinding OK' }], { providerId: parseInt(req.params.id, 10), max_tokens: 50 } ); const text = result.choices?.[0]?.message?.content || 'OK'; res.redirect('/ai?tested=' + encodeURIComponent(text.slice(0, 80))); } catch (e) { res.redirect('/ai?error=' + encodeURIComponent(e.message)); } }); router.post('/chat', async (req, res) => { try { const { messages, provider_id, model, client_id } = req.body; const result = await chatCompletion(messages, { providerId: provider_id ? parseInt(provider_id, 10) : null, model }); const content = result.choices?.[0]?.message?.content || ''; if (client_id) { const { getDb } = require('../db'); getDb().prepare('INSERT INTO client_notes (client_id, content, created_by) VALUES (?, ?, ?)') .run(client_id, `[AI] ${content.slice(0, 2000)}`, req.session.username || 'ai'); } res.json({ success: true, content, model: result.model }); } catch (e) { res.status(500).json({ success: false, error: e.message }); } }); module.exports = router;