feat(zwischenruf): Korrektur mitten in den laufenden Turn schieben

Neben Senden ein 'Zwischenruf' (App: oranger Button, nur wenn ARIA im
aktiven Kontext arbeitet; Diagnostic: Buttons neben beiden Senden). Geht
NICHT in die Queue und bricht NICHT ab — die Nachricht wird in den
laufenden claude-Subprozess geschoben; er greift sie an der naechsten
Tool-Grenze auf.

Technik:
- proxy-patches/manager.js: claude laeuft jetzt im --input-format
  stream-json-Modus, initialer Prompt als stream-json User-Message,
  stdin bleibt OFFEN; sendMessage() schiebt weitere User-Messages nach;
  bei 'result' wird stdin geschlossen (Turn endet sauber). Ersetzt die
  bisherigen sed-Patches (jetzt volle Datei via cp, docker-compose.yml).
- proxy-patches/routes.js: Side-Channel POST /interject {projectId,text}
  → subprocess.sendMessage der Kontext-Subprozesse.
- rvs: 'interject' erlaubt. bridge: RVS interject → Proxy /interject.
- App/Diagnostic: Zwischenruf-Buttons + lokale '📣 Zwischenruf'-Bubble.

Empirisch verifiziert: mid-turn injizierte Message wird an der naechsten
Tool-Grenze aufgegriffen (nicht mitten in einem blockierenden Befehl).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-06 05:05:13 +02:00
co-authored by Claude Opus 4.8
parent 2ad8c2f245
commit 648e3b04fd
8 changed files with 395 additions and 9 deletions
+14
View File
@@ -328,6 +328,7 @@
<input type="file" id="diag-file-input" multiple accept="image/*,application/pdf,.doc,.docx,.txt" style="display:none;" onchange="handleDiagFileSelect(this.files)">
</label>
<textarea id="chat-input" placeholder="Nachricht an ARIA... (Enter sendet, Shift+Enter neue Zeile)" rows="2" onpaste="handleDiagPaste(event)" oninput="autoResizeTextarea(this)"></textarea>
<button class="btn secondary" onclick="interjectDiag('chat-input')" title="Zwischenruf — Korrektur in den laufenden Turn (kein Abbruch, keine Queue)" style="border-color:#FF9500;color:#FF9500;">📣</button>
<button class="btn" id="btn-rvs" onclick="testRVS()">Senden</button>
</div>
</div>
@@ -345,6 +346,7 @@
</div>
<div class="input-row" style="margin-top:8px;">
<textarea id="chat-input-fs" placeholder="Nachricht an ARIA... (Enter sendet, Shift+Enter neue Zeile)" rows="2" oninput="autoResizeTextarea(this)"></textarea>
<button class="btn secondary" onclick="interjectDiag('chat-input-fs')" title="Zwischenruf — Korrektur in den laufenden Turn (kein Abbruch, keine Queue)" style="border-color:#FF9500;color:#FF9500;">📣</button>
<button class="btn" onclick="testRVSFS()">Senden</button>
</div>
</div>
@@ -2244,6 +2246,18 @@
diagCtxStates[pid] = 'running';
renderDiagQueue();
}
// Zwischenruf: waehrend ARIA arbeitet eine Korrektur in den laufenden Turn
// schieben — NICHT anstellen, NICHT abbrechen.
function interjectDiag(inputId) {
const input = document.getElementById(inputId || 'chat-input');
const text = (input.value || '').trim();
if (!text) return;
send({ action: 'interject', text, projectId: focusedContextId });
addChat('sent', '📣 Zwischenruf: ' + text, 'interject', { projectId: focusedContextId });
diagDrafts[focusedContextId] = '';
localStorage.setItem('diag_ctx_drafts', JSON.stringify(diagDrafts));
input.value = '';
}
function advanceDiagQueue(pid) {
const q = diagCtxQueues[pid] || [];
if (q.length === 0) { diagCtxStates[pid] = 'idle'; renderDiagQueue(); return; }
+8
View File
@@ -2455,6 +2455,14 @@ wss.on("connection", (ws) => {
} else if (msg.action === "test_rvs") {
traceStart("RVS", msg.text || "aria lebst du noch?");
sendToRVS(msg.text || "aria lebst du noch?", true, msg.projectId || "");
} else if (msg.action === "interject") {
// Zwischenruf: in den laufenden Turn schieben (kein Abbruch, keine
// Queue) → RVS interject → Bridge → Proxy /interject.
const t = String(msg.text || "");
if (t.trim()) {
sendToRVS_raw({ type: "interject", payload: { projectId: msg.projectId || "", text: t }, timestamp: Date.now() });
log("info", "server", "Zwischenruf an RVS (project=" + (msg.projectId || "(main)") + "): " + t.slice(0, 60));
}
} else if (msg.action === "reconnect_gateway") {
connectGateway();
} else if (msg.action === "reconnect_rvs") {