70 lines
2.2 KiB
JavaScript
70 lines
2.2 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const appSettings = require('../config/settings');
|
|
|
|
const { getEnv, LLAMACPP, logger } = require('@nexusai/shared');
|
|
const LLAMA_URL = getEnv('LLAMA_SERVER_URL', LLAMACPP.DEFAULT_URL);
|
|
|
|
router.get('/', (req, res) => {
|
|
const { modelsFolderPath } = appSettings.load();
|
|
|
|
try {
|
|
// Try scanning folder for .gguf files
|
|
const files = fs.readdirSync(modelsFolderPath)
|
|
.filter(f => f.endsWith('.gguf'));
|
|
|
|
// Try loading models.json for richer metadata (label, description)
|
|
let manifest = {};
|
|
try {
|
|
const manifestPath = path.join(modelsFolderPath, 'models.json');
|
|
const raw = fs.readFileSync(manifestPath, 'utf8');
|
|
// Index manifest by filename for quick lookup
|
|
const list = JSON.parse(raw);
|
|
for (const m of list) {
|
|
manifest[m.value] = m;
|
|
}
|
|
} catch {
|
|
// No manifest — scan only, that's fine
|
|
}
|
|
|
|
const models = files.map(filename => ({
|
|
value: filename,
|
|
label: manifest[filename]?.label ?? filename.replace('.gguf', ''),
|
|
description: manifest[filename]?.description ?? null,
|
|
size: getFileSizeMB(path.join(modelsFolderPath, filename)),
|
|
}));
|
|
|
|
res.json(models);
|
|
} catch (err) {
|
|
logger.error('[models] Failed to scan folder:', err.message);
|
|
res.status(500).json({ error: `Could not read models folder: ${modelsFolderPath}` });
|
|
}
|
|
});
|
|
|
|
router.get('/props', async (req, res) => {
|
|
try {
|
|
const response = await fetch(`${LLAMA_URL}/props`);
|
|
if (!response.ok) throw new Error(`llama-server error: ${response.status}`);
|
|
const data = await response.json();
|
|
res.json({
|
|
contextWindow: data.default_generation_settings?.n_ctx ?? null,
|
|
modelAlias: data.model_alias,
|
|
});
|
|
} catch (err) {
|
|
logger.error('[models/props]', err.message);
|
|
res.status(503).json({ error: 'Could not reach llama-server' });
|
|
}
|
|
});
|
|
|
|
function getFileSizeMB(filepath) {
|
|
try {
|
|
const bytes = fs.statSync(filepath).size;
|
|
return (bytes / (1024 ** 3)).toFixed(1) + ' GB'; // models are big — show GB
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
module.exports = router; |