feat(backend): modèle unifié streaming/progress/events provider-agnostic + pont app-tauri — foundation #156 (QA verte)

This commit is contained in:
2026-08-06 13:13:17 +02:00
parent 40fa551f32
commit 918116664c
14 changed files with 630 additions and 59 deletions

View File

@ -66,16 +66,25 @@ pub struct AnnouncementPublisher {
impl AnnouncementPublisher {
fn publish_event(&self, event: &ReplyEvent) {
if let ReplyEvent::Announcement { text } = event {
self.bus.publish(DomainEvent::AgentAnnouncement {
project_id: self.project_id,
requester: self.requester,
target: self.target,
ticket: self.ticket,
text: text.clone(),
at_ms: now_epoch_ms(),
});
}
let text = match event {
ReplyEvent::Announcement { text } => Some(text.clone()),
ReplyEvent::Progress { progress } => progress
.text
.clone()
.or_else(|| (!progress.label.trim().is_empty()).then(|| progress.label.clone())),
_ => None,
};
let Some(text) = text else {
return;
};
self.bus.publish(DomainEvent::AgentAnnouncement {
project_id: self.project_id,
requester: self.requester,
target: self.target,
ticket: self.ticket,
text,
at_ms: now_epoch_ms(),
});
}
}
@ -383,9 +392,11 @@ fn drain_stream_to_final(
match event {
ReplyEvent::Final { content } => return Ok(TurnOutcome::Completed(content)),
ReplyEvent::RateLimited { resets_at_ms } => last_rate_limit = Some(resets_at_ms),
// TextDelta / Announcement / ToolActivity / Error / Heartbeat : non terminaux
// Progress / TextDelta / Announcement / ToolActivity / Error / Heartbeat :
// non terminaux
// pour ce drain synchrone ; seul Final est une réponse réussie.
ReplyEvent::TextDelta { .. }
ReplyEvent::Progress { .. }
| ReplyEvent::TextDelta { .. }
| ReplyEvent::Announcement { .. }
| ReplyEvent::Error { .. }
| ReplyEvent::ToolActivity { .. }