111 lines
5.0 KiB
JavaScript
111 lines
5.0 KiB
JavaScript
/**
|
|
* WEVIA Sovereign Stream Client v1.0
|
|
* SSE streaming + real exec via WEVIA Master
|
|
* Usage: weviaStream('message', document.getElementById('output'))
|
|
*/
|
|
window.weviaStream = function(message, container, opts) {
|
|
opts = opts || {};
|
|
var system = opts.system || 'Tu es WEVIA, IA souveraine de WEVAL Consulting Casablanca. Reponds en francais, professionnel et naturel comme un collegue expert. Si on te demande une action serveur, genere la commande entre ```bash et ```.';
|
|
var maxTokens = opts.maxTokens || 2000;
|
|
var onDone = opts.onDone || function(){};
|
|
var onToken = opts.onToken || null;
|
|
|
|
var responseDiv = document.createElement('div');
|
|
responseDiv.className = 'wevia-stream-msg';
|
|
responseDiv.innerHTML = '<span class="wevia-thinking-dot"></span> Analyse...';
|
|
container.appendChild(responseDiv);
|
|
|
|
var textBuffer = '';
|
|
var provider = '';
|
|
var startTime = performance.now();
|
|
|
|
fetch('/api/sovereign/v1/chat/completions', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
model: 'auto',
|
|
messages: [
|
|
{role: 'system', content: system},
|
|
{role: 'user', content: message}
|
|
],
|
|
max_tokens: maxTokens,
|
|
stream: true
|
|
})
|
|
}).then(function(response) {
|
|
var reader = response.body.getReader();
|
|
var decoder = new TextDecoder();
|
|
var buf = '';
|
|
|
|
function read() {
|
|
return reader.read().then(function(result) {
|
|
if (result.done) { finish(); return; }
|
|
buf += decoder.decode(result.value, {stream: true});
|
|
var lines = buf.split('\n');
|
|
buf = lines.pop();
|
|
lines.forEach(function(line) {
|
|
if (!line.startsWith('data: ') || line === 'data: [DONE]') {
|
|
if (line === 'data: [DONE]') { finish(); return; }
|
|
return;
|
|
}
|
|
try {
|
|
var d = JSON.parse(line.substring(6));
|
|
if (d.type === 'token' && d.content) {
|
|
textBuffer += d.content;
|
|
if (!provider && d.provider) provider = d.provider;
|
|
responseDiv.innerHTML = renderMarkdown(textBuffer) + '<span class="wevia-cursor">|</span>';
|
|
if (container.scrollHeight) container.scrollTop = container.scrollHeight;
|
|
if (onToken) onToken(d.content, textBuffer);
|
|
}
|
|
} catch(e) {}
|
|
});
|
|
return read();
|
|
});
|
|
}
|
|
return read();
|
|
}).catch(function(err) {
|
|
responseDiv.innerHTML = '<div class="wevia-error">Erreur: ' + err.message + '</div>';
|
|
});
|
|
|
|
function finish() {
|
|
var elapsed = ((performance.now() - startTime) / 1000).toFixed(1);
|
|
var html = renderMarkdown(textBuffer);
|
|
// Detect and execute bash blocks
|
|
var bashBlocks = textBuffer.match(/```bash\n([\s\S]*?)```/g);
|
|
if (bashBlocks && bashBlocks.length > 0) {
|
|
bashBlocks.forEach(function(block) {
|
|
var cmd = block.replace(/```bash\n/, '').replace(/```$/, '').trim();
|
|
html += '<div class="wevia-exec"><div class="exec-header">Execution: ' + escHtml(cmd.substring(0,80)) + '</div><div class="exec-output" id="exec-' + Date.now() + '">En cours...</div></div>';
|
|
// Execute via WEVIA Master
|
|
fetch('/api/wevia-autonomous.php', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({message: cmd})
|
|
}).then(function(r){return r.text()}).then(function(t){
|
|
var lines = t.split('\n');
|
|
var result = '';
|
|
lines.forEach(function(l){
|
|
if (l.startsWith('data: ') && l !== 'data: [DONE]') {
|
|
try { var d = JSON.parse(l.substring(6)); if(d.text) result = d.text; } catch(e){}
|
|
}
|
|
});
|
|
var execDiv = responseDiv.querySelector('.exec-output:last-of-type');
|
|
if (execDiv) execDiv.textContent = result || 'Commande executee';
|
|
});
|
|
});
|
|
}
|
|
html += '<div class="wevia-meta">' + escHtml(provider) + ' · ' + elapsed + 's</div>';
|
|
responseDiv.innerHTML = html;
|
|
onDone({text: textBuffer, provider: provider, elapsed: elapsed});
|
|
}
|
|
|
|
function renderMarkdown(md) {
|
|
return md
|
|
.replace(/```(\w*)\n([\s\S]*?)```/g, '<pre class="code-block"><code>$2</code></pre>')
|
|
.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>')
|
|
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
|
.replace(/\n/g, '<br>');
|
|
}
|
|
function escHtml(t) { var d=document.createElement('div');d.textContent=t;return d.innerHTML; }
|
|
return responseDiv;
|
|
};
|