feat: MCP-Server für remote_execute + Inline-Choice-UI
- Python MCP-Server (stdio, JSON-RPC 2.0) für remote_execute via Claude CLI - Interner API-Endpoint /api/internal/remote-execute mit Token-Auth - MCP-Config wird automatisch generiert wenn Remote-Verbindung vorhanden - Auth-Middleware: /api/internal/ von Auth ausgenommen - Frontend: :::ASK_USER_CHOICE::: Blöcke als interaktive Buttons rendern - Streaming: Unvollständige Choice-Blöcke werden während des Streams versteckt - tool-ui.js: MCP-Tool-Namen generisch normalisieren (mcp__server__tool → tool) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
ee0b817f25
commit
3b068a7866
14 files changed
+576
-6
No files matched your search
@@ -402,6 +402,14 @@ async function sendMessage() {
|
||||
await _runStream((signal) => apiChat(content, getCurrentSessionId(), signal, _planModeActive));
|
||||
}
|
||||
|
||||
// ── Direct Message (für Inline-Choice-Buttons) ──
|
||||
async function sendMessageDirect(text) {
|
||||
if (isStreaming || !text) return;
|
||||
addUserBubble(text, true);
|
||||
scrollDownForce();
|
||||
await _runStream((signal) => apiChat(text, getCurrentSessionId(), signal, _planModeActive));
|
||||
}
|
||||
|
||||
// ── Choice Click Handler ──
|
||||
|
||||
async function handleChoiceClick(toolCallId, choice, bubbleDiv) {
|
||||
@@ -419,3 +427,23 @@ async function handleChoiceClick(toolCallId, choice, bubbleDiv) {
|
||||
|
||||
await _runStream((signal) => apiChatChoice(getCurrentSessionId(), toolCallId, choice, signal, _planModeActive));
|
||||
}
|
||||
|
||||
// ── Inline Choice Blocks (Fallback aus Markdown-Rendering) ──
|
||||
// Event-Delegation für .inline-choice-btn Buttons die von renderMarkdown() erzeugt wurden
|
||||
document.addEventListener('click', function(e) {
|
||||
var btn = e.target.closest('.inline-choice-btn');
|
||||
if (!btn) return;
|
||||
var block = btn.closest('.inline-choice-block');
|
||||
if (!block || block.classList.contains('choice-answered')) return;
|
||||
|
||||
var choice = btn.dataset.choice;
|
||||
// Buttons deaktivieren + markieren
|
||||
block.querySelectorAll('.inline-choice-btn').forEach(function(b) {
|
||||
b.disabled = true;
|
||||
b.classList.add(b === btn ? 'choice-selected' : 'choice-unselected');
|
||||
});
|
||||
block.classList.add('choice-answered');
|
||||
|
||||
// Inline-Choice als normale User-Nachricht senden (kein tool_use in DB vorhanden)
|
||||
sendMessageDirect(choice);
|
||||
});
|
||||
Reference in new issue
Block a user