feat(chat): livre la CLI custom de chat agent (#147) et corrige Cancel

Implémente la vue chat structurée par cellule agent (toggle TUI/CLI custom,
préférence persistée `preferred_view`, reattach live, composer + pièces
jointes) avec le socle backend AgentSession/ChatBridge (UserPrompt,
cancel_current_turn, routage interrupt_agent, commande cancel_agent_chat).

Corrige le bug bloquant relevé par QA : le bouton Cancel de
CustomAgentChatView interrompait tout le tour via closeAgentChat au lieu
de n'annuler que le tour courant via cancelAgentChat, ce qui tuait la
session contrairement au contrat produit validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 11:59:39 +02:00
parent efbd56a149
commit dcba76b871
33 changed files with 1681 additions and 144 deletions

View File

@ -1120,7 +1120,9 @@ use application::{
CreateLayoutOutput, DeleteLayoutOutput, LayoutInfo, LayoutOperation, ListLayoutsOutput,
LoadLayoutOutput, MutateLayoutOutput, PluginLayoutOrigin, SetActiveLayoutOutput,
};
use domain::{AgentId, Direction, LayoutId, LayoutTree, NodeId, PluginId, PluginLayoutType};
use domain::{
AgentId, Direction, LayoutId, LayoutTree, NodeId, PluginId, PluginLayoutType, PreferredView,
};
/// Response DTO carrying a layout tree.
///
@ -1214,6 +1216,14 @@ pub enum LayoutOperationDto {
#[serde(default)]
conversation_id: Option<String>,
},
/// Persist the preferred live view for an agent leaf.
#[serde(rename_all = "camelCase")]
SetCellPreferredView {
/// Hosting leaf.
target: String,
/// Preferred live view.
preferred_view: PreferredView,
},
/// Persist opaque plugin layout state.
#[serde(rename_all = "camelCase")]
SetPluginLayoutState {
@ -1273,6 +1283,13 @@ impl LayoutOperationDto {
target: parse_node_id(&target)?,
conversation_id,
},
Self::SetCellPreferredView {
target,
preferred_view,
} => LayoutOperation::SetCellPreferredView {
target: parse_node_id(&target)?,
preferred_view,
},
Self::SetPluginLayoutState { target, state } => LayoutOperation::SetPluginLayoutState {
target: parse_node_id(&target)?,
state,
@ -2957,6 +2974,12 @@ impl From<TerminalSession> for TerminalSessionDto {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "camelCase")]
pub enum ReplyChunk {
/// The user's submitted prompt, retained in live scrollback for reattach.
#[serde(rename_all = "camelCase")]
UserPrompt {
/// Submitted prompt text.
text: String,
},
/// An assistant text fragment (incremental chat rendering).
#[serde(rename_all = "camelCase")]
TextDelta {