fix(orchestrator,agent): rendezvous cross-project réarmé par jeton d'activité live model-agnostique — #287 (le watchdog d'inactivité du rendez-vous expirait à 600s sur un tour structured actif car seul le transcript Claude servait de signe de vie; nouveau drain_with_readiness_announcements_and_activity_outcome exposant un jeton monotone AtomicU64 incrémenté par chaque ReplyEvent non terminal du tap send_with_tap, passé au watchdog via AskWatchdogActivity pour réarmer la fenêtre quelle que soit l'adapter; la sonde transcript devient fallback externe; QA verte: orchestrator_service 81/81, rendezvous 5/5, mcp_server 40/40, backend 87+7 ignored, cargo fmt --check; scripts/ hors périmètre)
This commit is contained in:
@ -23,7 +23,8 @@ pub use session_limit::{AgentResumer, SessionLimitService, RESUME_PROMPT};
|
||||
pub use structured::{
|
||||
drain_reply_stream_with_readiness, drain_with_readiness,
|
||||
drain_with_readiness_and_announcements, drain_with_readiness_and_announcements_outcome,
|
||||
drain_with_readiness_outcome, send_blocking, AnnouncementPublisher, TurnOutcome,
|
||||
drain_with_readiness_announcements_and_activity_outcome, drain_with_readiness_outcome,
|
||||
send_blocking, AnnouncementPublisher, TurnOutcome,
|
||||
};
|
||||
|
||||
pub use catalogue::{
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
//! DRY : un seul chemin de lecture (le flux). `send_blocking` n'est qu'un *consom-
|
||||
//! mateur* du même flux que la cellule chat utilise pour le rendu incrémental.
|
||||
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
@ -203,15 +204,49 @@ pub async fn drain_with_readiness_and_announcements_outcome(
|
||||
agent: RuntimeAgentKey,
|
||||
announcements: Option<AnnouncementPublisher>,
|
||||
) -> Result<TurnOutcome, AgentSessionError> {
|
||||
let Some(publisher) = announcements else {
|
||||
if announcements.is_none() {
|
||||
return drain_with_readiness_outcome(session, prompt, timeout, mediator, agent).await;
|
||||
};
|
||||
}
|
||||
drain_with_readiness_announcements_and_activity_outcome(
|
||||
session,
|
||||
prompt,
|
||||
timeout,
|
||||
mediator,
|
||||
agent,
|
||||
announcements,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Variante du drain d'annonces qui expose aussi un jeton monotone d'activité live.
|
||||
///
|
||||
/// Le jeton avance pour chaque [`ReplyEvent`] non terminal reçu via
|
||||
/// [`AgentSession::send_with_tap`], donc pendant que `send_with_tap` travaille encore
|
||||
/// et avant que son flux batch final soit disponible. Il permet au watchdog du
|
||||
/// rendez-vous de distinguer un tour structured actif d'un vrai silence, quel que
|
||||
/// soit le provider. `Final` reste exclusivement traité par le drain normal.
|
||||
pub async fn drain_with_readiness_announcements_and_activity_outcome(
|
||||
session: &dyn AgentSession,
|
||||
prompt: &str,
|
||||
timeout: Option<Duration>,
|
||||
mediator: &dyn InputMediator,
|
||||
agent: RuntimeAgentKey,
|
||||
announcements: Option<AnnouncementPublisher>,
|
||||
activity: Option<Arc<AtomicU64>>,
|
||||
) -> Result<TurnOutcome, AgentSessionError> {
|
||||
let (tap_tx, tap_rx) = std::sync::mpsc::channel();
|
||||
let live_publisher = publisher.clone();
|
||||
let live_publisher = announcements.clone();
|
||||
let live_pump = std::thread::spawn(move || {
|
||||
for event in tap_rx {
|
||||
live_publisher.publish_event(&event);
|
||||
if !matches!(event, ReplyEvent::Final { .. }) {
|
||||
if let Some(activity) = &activity {
|
||||
activity.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
if let Some(publisher) = &live_publisher {
|
||||
publisher.publish_event(&event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -230,7 +265,9 @@ pub async fn drain_with_readiness_and_announcements_outcome(
|
||||
if !matches!(event, ReplyEvent::Final { .. }) {
|
||||
mediator.mark_alive(agent);
|
||||
}
|
||||
publisher.publish_event(event);
|
||||
if let Some(publisher) = &announcements {
|
||||
publisher.publish_event(event);
|
||||
}
|
||||
},
|
||||
|signal| {
|
||||
if signal == ReadinessSignal::TurnEnded {
|
||||
|
||||
Reference in New Issue
Block a user