secubox-openwrt/package/secubox/luci-app-localai/htdocs/luci-static/resources/localai/api.js
CyberMind-FR 6b28c4260b feat(localai): Add LocalAI LuCI app with chat, models management and portal integration
- Add secubox-app-localai package with LXC container support for LocalAI service
- Add luci-app-localai with dashboard, chat, models and settings views
- Implement RPCD backend for LocalAI API integration via /v1/models and /v1/chat/completions
- Use direct RPC declarations in LuCI views for reliable frontend communication
- Add LocalAI and Glances to secubox-portal services page
- Move Glances from services to monitoring section

Packages:
- secubox-app-localai: 0.1.0-r1
- luci-app-localai: 0.1.0-r8
- luci-app-secubox-portal: 0.6.0-r5

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 16:54:13 +01:00

141 lines
2.8 KiB
JavaScript

'use strict';
'require baseclass';
'require rpc';
/**
* LocalAI Dashboard API
* Package: luci-app-localai
* RPCD object: luci.localai
*/
// Version: 0.1.0
var callStatus = rpc.declare({
object: 'luci.localai',
method: 'status',
expect: { }
});
var callModels = rpc.declare({
object: 'luci.localai',
method: 'models',
expect: { models: [] }
});
var callConfig = rpc.declare({
object: 'luci.localai',
method: 'config',
expect: { }
});
var callHealth = rpc.declare({
object: 'luci.localai',
method: 'health',
expect: { healthy: false }
});
var callMetrics = rpc.declare({
object: 'luci.localai',
method: 'metrics',
expect: { }
});
var callStart = rpc.declare({
object: 'luci.localai',
method: 'start',
expect: { success: false }
});
var callStop = rpc.declare({
object: 'luci.localai',
method: 'stop',
expect: { success: false }
});
var callRestart = rpc.declare({
object: 'luci.localai',
method: 'restart',
expect: { success: false }
});
var callModelInstall = rpc.declare({
object: 'luci.localai',
method: 'model_install',
params: ['name'],
expect: { success: false }
});
var callModelRemove = rpc.declare({
object: 'luci.localai',
method: 'model_remove',
params: ['name'],
expect: { success: false }
});
var callChat = rpc.declare({
object: 'luci.localai',
method: 'chat',
params: ['model', 'messages'],
expect: { response: '' }
});
var callComplete = rpc.declare({
object: 'luci.localai',
method: 'complete',
params: ['model', 'prompt'],
expect: { text: '' }
});
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
var k = 1024;
var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatUptime(seconds) {
if (!seconds) return 'N/A';
var days = Math.floor(seconds / 86400);
var hours = Math.floor((seconds % 86400) / 3600);
var mins = Math.floor((seconds % 3600) / 60);
if (days > 0) return days + 'd ' + hours + 'h';
if (hours > 0) return hours + 'h ' + mins + 'm';
return mins + 'm';
}
return baseclass.extend({
getStatus: callStatus,
getModels: callModels,
getConfig: callConfig,
getHealth: callHealth,
getMetrics: callMetrics,
start: callStart,
stop: callStop,
restart: callRestart,
modelInstall: callModelInstall,
modelRemove: callModelRemove,
chat: callChat,
complete: callComplete,
formatBytes: formatBytes,
formatUptime: formatUptime,
// Aggregate function for dashboard
getDashboardData: function() {
return Promise.all([
callStatus(),
callModels(),
callHealth(),
callMetrics()
]).then(function(results) {
return {
status: results[0] || {},
models: results[1] || { models: [] },
health: results[2] || { healthy: false },
metrics: results[3] || {}
};
});
}
});