fix(codex): dernier agent_message = Final (bootstrap canal)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -219,22 +219,40 @@ impl AgentSession for CodexExecSession {
|
|||||||
|
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
let mut captured_id = None;
|
let mut captured_id = None;
|
||||||
'lines: for line in &raw_lines {
|
// Fix canal (B2, bootstrap) : un tour `codex exec` peut émettre PLUSIEURS
|
||||||
|
// `agent_message` — un préambule (« je vais… ») puis la conclusion. On ne coupe
|
||||||
|
// donc plus au premier : on retient le **dernier** `agent_message` comme unique
|
||||||
|
// `Final` terminal (la conclusion du tour), et on dégrade les précédents en
|
||||||
|
// activité non terminale (readiness préservée). Ainsi le demandeur reçoit la
|
||||||
|
// conclusion, pas le préambule. Absence d'`agent_message` ⇒ aucun `Final`
|
||||||
|
// (no-reply inchangé).
|
||||||
|
let mut last_final: Option<String> = None;
|
||||||
|
for line in &raw_lines {
|
||||||
let parsed = parse_event(line)?;
|
let parsed = parse_event(line)?;
|
||||||
if let Some(id) = parsed.conversation_id {
|
if let Some(id) = parsed.conversation_id {
|
||||||
captured_id = Some(id);
|
captured_id = Some(id);
|
||||||
}
|
}
|
||||||
// Le `Final` est **terminal** (contrat de port) : on arrête d'émettre dès
|
|
||||||
// qu'on l'a vu, pour qu'aucun heartbeat de fin (`turn.completed` postérieur)
|
|
||||||
// ne le suive dans le flux.
|
|
||||||
for event in parsed.events {
|
for event in parsed.events {
|
||||||
let is_final = matches!(event, ReplyEvent::Final { .. });
|
match event {
|
||||||
events.push(event);
|
ReplyEvent::Final { content } => {
|
||||||
if is_final {
|
// Un `agent_message` précédemment retenu est supersédé : il devient
|
||||||
break 'lines;
|
// une activité non terminale, on garde le plus récent en conclusion.
|
||||||
|
if last_final.is_some() {
|
||||||
|
events.push(ReplyEvent::ToolActivity {
|
||||||
|
label: "agent_message".to_owned(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
last_final = Some(content);
|
||||||
|
}
|
||||||
|
other => events.push(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Le dernier `agent_message` retenu est le seul `Final` terminal, émis en fin de
|
||||||
|
// flux (après les heartbeats/activités du tour).
|
||||||
|
if let Some(content) = last_final {
|
||||||
|
events.push(ReplyEvent::Final { content });
|
||||||
|
}
|
||||||
if let Some(id) = captured_id {
|
if let Some(id) = captured_id {
|
||||||
*self.conversation_id.lock().expect("mutex sain") = Some(id);
|
*self.conversation_id.lock().expect("mutex sain") = Some(id);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user