feat: Nvidia API direkt-Anbindung mit Thinking-Mode Support

Neues Server-Setting NvidiaApiKey – wenn gesetzt, wird direkt
integrate.api.nvidia.com verwendet statt g4f.space Proxy.
Thinking-Modelle (kimi-k2, qwq, deepseek-r1) erhalten automatisch
chat_template_kwargs und reasoning-Output wird als klappbare
Denkprozess-Bubble im Chat angezeigt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.6 committed 2026-03-25 09:09:02 +01:00
1 parent 1101bb83a0
commit 4960b57ec7
6 files changed
+176 -3

No files matched your search

+51
View File
@@ -52,6 +52,57 @@ function endStreamBubble() {
_streamText = '';
}
// ── Thinking Bubble (Nvidia Reasoning) ──
let _thinkingDiv = null;
let _thinkingText = '';
function startThinkingBubble() {
_thinkingDiv = document.createElement('div');
_thinkingDiv.className = 'tool-box thinking-box streamed';
var header = document.createElement('div');
header.className = 'tool-box-header clickable';
header.innerHTML = '<span class="tool-name">Denkprozess</span>';
var content = document.createElement('div');
content.className = 'thinking-content markdown';
content.hidden = true;
content.innerHTML = '<p><span class="cursor"></span></p>';
header.addEventListener('click', function() { content.hidden = !content.hidden; });
_thinkingDiv.appendChild(header);
_thinkingDiv.appendChild(content);
_thinkingText = '';
chatEl().appendChild(_thinkingDiv);
scrollDown();
}
function appendToThinking(text) {
if (!_thinkingDiv) startThinkingBubble();
_thinkingText += text;
var contentEl = _thinkingDiv.querySelector('.thinking-content');
contentEl.innerHTML = renderMarkdown(_thinkingText);
var cursor = document.createElement('span');
cursor.className = 'cursor';
var lastBlock = contentEl.lastElementChild;
if (lastBlock) lastBlock.appendChild(cursor);
else contentEl.appendChild(cursor);
scrollDown();
}
function endThinkingBubble() {
if (_thinkingDiv) {
var cursor = _thinkingDiv.querySelector('.cursor');
if (cursor) cursor.remove();
var contentEl = _thinkingDiv.querySelector('.thinking-content');
if (!_thinkingText.trim()) _thinkingDiv.remove();
else {
contentEl.innerHTML = renderMarkdown(_thinkingText);
contentEl.hidden = true;
}
}
_thinkingDiv = null;
_thinkingText = '';
}
// ── Review Bubbles (Streaming) ──
let _reviewBubble = null;