fix(backend,orchestrator,chat): l'objectif suspendu guide le premier tour post-restart — #290 regression partielle (register_suspended_turn capture la demande utilisateur exacte au point d'entrée chat agent_send/chat.send avec source diagnostique, RestartRendezvousCoordinator conserve tour/objectif/restart_attempt_id, take_continuation consommable exactement une fois et seulement par la tentative courante: suspended_restart_continuation_prompt place l'objectif utilisateur avant toute consigne generique et StructuredHumanTurnTransition::Resume porte le prompt host-provided injecte au runtime de remplacement; nettoyage du tour suspendu sur succes, echec, annulation et abandon/expiration; diagnostics projet/agent/turn_id/restart_attempt_id/source; rendez-vous inter-agents #289 inchanges; QA verte reconfirmee par Git: cargo check --workspace, backend self_restart_contract_tests 3/3, orchestrator_service restart 10/10, workstate_actions 9/9, app-tauri chat_bridge 31/31, web-server websocket_chat_send 3/3, fmt --check, diff --check; restants: rebuild AppImage + validation live reprise objectif apres restart; carnet #290 iteration regression + passage store qa inclus; scripts/ hors périmètre; aucun push)
This commit is contained in:
@ -2620,13 +2620,14 @@ pub async fn agent_send(
|
||||
.collect();
|
||||
let session_meta = state.structured_sessions.meta_for_session(&sid);
|
||||
let turn_guard = session_meta.as_ref().map(|(project_id, agent_id, _, _)| {
|
||||
backend::StructuredHumanTurnGuard::start(
|
||||
backend::StructuredHumanTurnGuard::start_with_source(
|
||||
std::sync::Arc::clone(&state.turn_watch_input),
|
||||
std::sync::Arc::clone(&state.input_mailbox),
|
||||
std::sync::Arc::clone(&state.restart_rendezvous),
|
||||
*project_id,
|
||||
*agent_id,
|
||||
&prompt_for_model,
|
||||
&prompt,
|
||||
"agent_send",
|
||||
)
|
||||
});
|
||||
|
||||
@ -2711,6 +2712,7 @@ pub async fn agent_send(
|
||||
'logical_turn: loop {
|
||||
let mut concrete_terminal = false;
|
||||
let mut resume = false;
|
||||
let mut resume_prompt = None;
|
||||
for event in current_stream {
|
||||
let provider_terminal = matches!(
|
||||
event,
|
||||
@ -2722,8 +2724,9 @@ pub async fn agent_send(
|
||||
if let Some(guard) = turn_guard.as_mut() {
|
||||
match runtime.block_on(guard.transition_after_provider_terminal_async()) {
|
||||
backend::StructuredHumanTurnTransition::Complete => {}
|
||||
backend::StructuredHumanTurnTransition::Resume => {
|
||||
backend::StructuredHumanTurnTransition::Resume { prompt } => {
|
||||
resume = true;
|
||||
resume_prompt = Some(prompt);
|
||||
break;
|
||||
}
|
||||
backend::StructuredHumanTurnTransition::Failed(message) => {
|
||||
@ -2789,7 +2792,10 @@ pub async fn agent_send(
|
||||
if let Some(guard) = turn_guard.as_mut() {
|
||||
match runtime.block_on(guard.transition_after_provider_terminal_async()) {
|
||||
backend::StructuredHumanTurnTransition::Complete => {}
|
||||
backend::StructuredHumanTurnTransition::Resume => resume = true,
|
||||
backend::StructuredHumanTurnTransition::Resume { prompt } => {
|
||||
resume = true;
|
||||
resume_prompt = Some(prompt);
|
||||
}
|
||||
backend::StructuredHumanTurnTransition::Failed(message) => {
|
||||
terminal_visible = true;
|
||||
let _ = bridge.send_output_settled(
|
||||
@ -2824,8 +2830,9 @@ pub async fn agent_send(
|
||||
);
|
||||
break;
|
||||
};
|
||||
match runtime.block_on(replacement.send(application::SELF_RESTART_CONTINUATION_PROMPT))
|
||||
{
|
||||
let resume_prompt = resume_prompt
|
||||
.unwrap_or_else(|| application::SELF_RESTART_CONTINUATION_PROMPT.to_owned());
|
||||
match runtime.block_on(replacement.send(&resume_prompt)) {
|
||||
Ok(stream) => current_stream = stream,
|
||||
Err(error) => {
|
||||
terminal_visible = true;
|
||||
|
||||
Reference in New Issue
Block a user