Pasted screenshots all share the same filename (e.g. "image.png"), so the
placeholder substitution in _renderUserTextContent resolved every
placeholder to the FIRST matching inline image via find() - showing the
first image N times. Data itself was always correct (DB/agent received
all images; a refresh rendered them properly).
Match images consumingly (findIndex + splice on a copy) instead: labels
and inlineImages are built in the same order, so same-named images now
map one-to-one. Also fix the same latent issue in the legacy attachment
path in history.js (_autoLoadImageAttachments), keeping the shift()
fallback.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Let the user inject a message into a running chain instead of only being
able to abort it. While a chain streams, typing + Enter sends the text to
a new /api/chat/steer endpoint; it is drained at the next iteration
boundary, wrapped with a hint so the model actively classifies it
("complements the task -> keep working" vs. "changes course -> adjust"),
and stored as a Type="steer" user message so it survives reload.
Shared infrastructure (provider-agnostic):
- SteeringQueue: out-of-band queue keyed by sessionId, mirrored from
StreamingTracker (Enqueue/Drain/Clear).
- Program.cs registers it as a singleton and passes it to AnthropicService.
- ChatEndpoint: POST /api/chat/steer enqueues only while IsStreaming,
Clear() in the finally.
- ChatService.BuildHistoryFromDb groups Type="steer" so no two
consecutive user turns are produced on re-chat.
- Frontend api.js/chat.js/bubbles.js/history.js + chat.css render the
optimistic steer bubble and the steer_injected SSE event; Enter during
a stream sends a steer instead of being blocked.
Anthropic API path:
- Drain point B (tool boundary, merged into the tool_result user turn)
and C (turn end -> inject + continue instead of finalize).
Claude CLI path (kill-and-restart):
- The agentic loop runs inside the claude child, so true mid-turn inject
is impossible. On a pending steer the child is killed at the next tool
boundary, progress is rebuilt from the DB as a <work_in_progress>
transcript, and the CLI is restarted with the steer appended.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Long-Poll durch Short-Poll ersetzt (MCP-Server pollt jede Sekunde statt einer blockierenden HTTP-Anfrage)
- Expliziter Lambda-Rückgabetyp Task<IResult> für ASP.NET Minimal API Endpoints (behebt 200 empty body Bug)
- Freitext-Option bei Choice-Buttons ("Eigene Antwort…") für freie User-Eingabe
- Stop während ask_user_choice markiert Chain als awaiting_user_choice statt stopped (Kontext bleibt erhalten)
- ask_user_choice System-Prompt-Instruktion breiter formuliert (Quiz, Multiple-Choice etc.)
- Text wird jetzt immer in DB gespeichert, auch bei ask_user_choice
- Key-Check Model auf claude-haiku-4-5 geändert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MCP-Server erweitert um ask_user_choice (Long-Poll), memory_read, memory_write
und memory_list Tools. MCP-Config wird jetzt immer generiert (nicht nur bei
Remote-Verbindung). InternalEndpoint um PendingChoices + choice-respond Endpoint
ergänzt. Frontend differenziert CLI-Modus (choice-respond API) vs. API-Modus.
Gesamter :::ASK_USER_CHOICE::: Text-Marker-Mechanismus aus ClaudeCliService,
AnthropicService, markdown.js und stream-ui.js entfernt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>