feat(backend): modèle unifié streaming/progress/events provider-agnostic + pont app-tauri — foundation #156 (QA verte)
This commit is contained in:
@ -2195,14 +2195,32 @@ pub async fn agent_send(
|
||||
},
|
||||
);
|
||||
|
||||
// Open the turn stream with a live progress tap. The returned `ReplyStream`
|
||||
// remains the authoritative drain to `Final`; the tap is best-effort
|
||||
// observability for provider-native/local progress produced while `send` is
|
||||
// still running.
|
||||
let (tap_tx, tap_rx) = std::sync::mpsc::channel();
|
||||
let tap_bridge = std::sync::Arc::clone(&state.chat_bridge);
|
||||
let tap_sid = sid;
|
||||
let tap_pump = std::thread::spawn(move || {
|
||||
for event in tap_rx {
|
||||
let Some(chunk) = crate::chat::chunk_from_event(event) else {
|
||||
continue;
|
||||
};
|
||||
if matches!(chunk, ReplyChunk::Final { .. } | ReplyChunk::Error { .. }) {
|
||||
continue;
|
||||
}
|
||||
let _ = tap_bridge.send_output(&tap_sid, chunk);
|
||||
}
|
||||
});
|
||||
|
||||
// Open the turn stream. A start failure leaves the just-registered channel in
|
||||
// place (the cell stays attached, ready for a retry) — mirrors the PTY pump,
|
||||
// which only unregisters on a hard subscribe failure; here the session is
|
||||
// still live, so we keep the attach and surface the error.
|
||||
let stream = session
|
||||
.send(&prompt_for_model)
|
||||
.await
|
||||
.map_err(|e| ErrorDto::from(AppError::from(e)))?;
|
||||
let stream_result = session.send_with_tap(&prompt_for_model, tap_tx).await;
|
||||
let _ = tap_pump.join();
|
||||
let stream = stream_result.map_err(|e| ErrorDto::from(AppError::from(e)))?;
|
||||
|
||||
// Drain the blocking reply iterator on a dedicated OS thread (the stream is a
|
||||
// synchronous `Iterator`, exactly like the PTY byte stream). It runs to the
|
||||
|
||||
Reference in New Issue
Block a user