fix(orchestrator): la délégation simple vers UX renvoie son Final structuré (#207, QA verte)

Une demande idea_ask_agent vers UX échouait avec « finished without a structured Final response » alors qu'Architect répondait. Deux causes corrigées:

- session/process: un tour CLI terminé en code non nul SANS stdout (ex. erreur 401/auth) renvoyait une sortie vide au lieu du stderr réel; l'orchestrateur concluait alors à un « no Final ». On remonte désormais le stderr effectif (drain sync + async + helper process_exit_message + test dédié).

- orchestrator/service: la branche « ask waiting on background » masquait le premier Final structuré; la réponse synchrone redevient le premier Final (suppression de active_rendezvous_has_background_tasks / mark_rendezvous_task_waiting).

Nettoyage runtime corollaire (#204): arrêt du live runtime stale (PTY + structuré) d'un agent recréé afin que la délégation route vers l'agent courant (LiveSessions, stop_live_agent_runtime_in_project, wiring backend via DeleteAgent::with_runtime_cleanup, lifecycle, workstate cascade).
This commit is contained in:
2026-08-12 14:09:06 +02:00
parent ba176e3cf2
commit 646b9d9284
11 changed files with 673 additions and 203 deletions

View File

@ -1514,6 +1514,10 @@ impl BackendCore {
// `profile.structured_adapter`. Injectés dans LaunchAgent (routage §17.4) et
// ChangeAgentProfile (shutdown polymorphe au hot-swap).
let structured_sessions = Arc::new(StructuredSessions::new());
let live_sessions = Arc::new(LiveSessions::new(
Arc::clone(&terminal_sessions),
Arc::clone(&structured_sessions),
));
let openai_tool_invoker = Arc::new(LateBoundOpenAiToolInvoker::new());
let openai_tool_invoker_port = Arc::clone(&openai_tool_invoker) as Arc<dyn ToolInvoker>;
let session_factory = Arc::new(
@ -2065,10 +2069,10 @@ impl BackendCore {
));
let read_agent_context = Arc::new(ReadAgentContext::new(Arc::clone(&contexts_port)));
let update_agent_context = Arc::new(UpdateAgentContext::new(Arc::clone(&contexts_port)));
let delete_agent = Arc::new(DeleteAgent::new(
Arc::clone(&contexts_port),
Arc::clone(&events_port),
));
let delete_agent = Arc::new(
DeleteAgent::new(Arc::clone(&contexts_port), Arc::clone(&events_port))
.with_runtime_cleanup(Arc::clone(&live_sessions), Arc::clone(&close_terminal)),
);
// LaunchAgent shares the SAME pty_port and terminal_sessions as the terminal
// use cases — indispensable for transport bridges to work correctly.
//
@ -2661,10 +2665,6 @@ impl BackendCore {
}
});
}
let live_sessions = Arc::new(LiveSessions::new(
Arc::clone(&terminal_sessions),
Arc::clone(&structured_sessions),
));
let delete_model_artifact = Arc::new(DeleteModelArtifact::new(
Arc::clone(&model_server_registry_port),
Arc::clone(&model_server_probe_port),