fix(luci-app-localai): Fix JSON parse error in chat

- Use L.url() for proper ubus endpoint URL
- Pass messages as array instead of JSON string
- Add credentials and better error handling
- Fix AbortController error handling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-01-22 05:14:15 +01:00
parent 6b07a613f1
commit 2dc9f6831b

View File

@ -19,29 +19,36 @@ function callChatWithTimeout(model, messages, timeoutMs) {
reject(new Error('Request timed out - model may need more time')); reject(new Error('Request timed out - model may need more time'));
}, timeout); }, timeout);
// Use ubus directly via L.Request or fetch // Use ubus RPC endpoint
var ubusUrl = L.url('admin/ubus');
var payload = JSON.stringify({ var payload = JSON.stringify({
jsonrpc: '2.0', jsonrpc: '2.0',
id: 1, id: Date.now(),
method: 'call', method: 'call',
params: [ params: [
L.env.sessionid || '00000000000000000000000000000000', rpc.getSessionID() || '00000000000000000000000000000000',
'luci.localai', 'luci.localai',
'chat', 'chat',
{ model: model, messages: JSON.parse(messages) } { model: model, messages: messages }
] ]
}); });
fetch(L.env.requestpath + 'admin/ubus', { fetch(ubusUrl, {
method: 'POST', method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: payload, body: payload,
signal: controller.signal signal: controller.signal
}) })
.then(function(response) { return response.json(); }) .then(function(response) {
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.json();
})
.then(function(data) { .then(function(data) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (data.result && data.result[1]) { if (data.result && Array.isArray(data.result) && data.result[1]) {
resolve(data.result[1]); resolve(data.result[1]);
} else if (data.error) { } else if (data.error) {
reject(new Error(data.error.message || 'RPC error')); reject(new Error(data.error.message || 'RPC error'));
@ -51,7 +58,11 @@ function callChatWithTimeout(model, messages, timeoutMs) {
}) })
.catch(function(err) { .catch(function(err) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (err.name === 'AbortError') {
reject(new Error('Request timed out - model may need more time'));
} else {
reject(err); reject(err);
}
}); });
}); });
} }
@ -178,7 +189,8 @@ return view.extend({
this.messages.push({ role: 'user', content: message }); this.messages.push({ role: 'user', content: message });
// Send to API (120s timeout for slow models) // Send to API (120s timeout for slow models)
callChatWithTimeout(this.selectedModel, JSON.stringify(this.messages), 120000) // Pass messages as array - RPCD will handle JSON serialization
callChatWithTimeout(this.selectedModel, this.messages, 120000)
.then(function(result) { .then(function(result) {
var loading = document.getElementById('loading-msg'); var loading = document.getElementById('loading-msg');
if (loading) loading.remove(); if (loading) loading.remove();