feat(backend,application,frontend,domain,web-server,app-tauri): bouton Redémarrer l'agent dans la barre supérieure des cellules — #317 (QA verte)

La cellule expose un bouton Redémarrer l'agent valable pour les trois
modes de présentation (headless, TUI native, CLI custom), sans jamais
prendre la présentation pour vérité runtime.

- Application: use case RestartCellAgentRuntime validant le binding
  exact cellule/runtime via les snapshots live (RestartRuntimeNotFound,
  ConflictAgentVisibleElsewhere, AgentNotBoundToCell) puis déléguant au
  scheduler self-restart existant (schedule_cell); CellAgentPresentation
  purement informationnelle.
- Backend/app-tauri/web-server: commande restart_cell_agent sur contrat
  DTO identique Tauri/HTTP, stop borné par timeout typé
  (RestartStopTimeout), relance préservant routage TUI natif, géométrie
  de cellule (node/rows/cols) et conversation; évenements domaine
  enrichis.
- Frontend: bouton dans la barre de cellule avec confirmation,
  overlay d'état Redémarrage…/échec (libellés par code d'erreur, Fermer/
  Réessayer), gardes d'identité de cellule et de restarts externes,
  gateway/mock/http adapters et ports alignés.
- Tests: dto_agents, workstate_actions, contrats web-server,
  LayoutGrid.cellControlsLayering, adapters agent/mock/http.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 15:00:43 +02:00
parent 46449bdf46
commit 7fb9d8bb86
26 changed files with 1404 additions and 58 deletions

View File

@ -100,6 +100,7 @@ use backend::dto::{
RemoveOpenProjectRestoreEntryRequestDto, RemoveProjectRequestDto, RemoveProjectResponseDto,
RenameLayoutRequestDto, ResolveAgentPermissionsRequestDto, ResolveAgentPermissionsResponseDto,
ResolveAgentSystemPermissionsRequestDto, ResolvedAgentSystemPermissionsDto,
RestartCellAgentRuntimeRequestDto, RestartCellAgentRuntimeResponseDto,
RestoreOpenProjectsOutputDto, ResumableAgentListDto, RetryOpenProjectRestoreRequestDto,
SaveEmbedderProfileRequestDto, SaveOpenCodeProviderProfileRequestDto,
SaveOpenProjectRestoreOrderRequestDto, SaveProfileRequestDto, SetActiveLayoutRequestDto,
@ -3442,6 +3443,9 @@ async fn invoke(
"list_resumable_agents" => invoke_list_resumable_agents(&request.args, &state.app).await,
"attach_live_agent" => invoke_attach_live_agent(&request.args, &state.app).await,
"stop_live_agent" => invoke_stop_live_agent(&request.args, &state.app).await,
"restart_cell_agent_runtime" => {
invoke_restart_cell_agent_runtime(&request.args, &state.app).await
}
"create_agent" => invoke_create_agent(&request.args, &state.app).await,
"change_agent_profile" => invoke_change_agent_profile(&request.args, &state.app).await,
"read_agent_context" => invoke_read_agent_context(&request.args, &state.app).await,
@ -4128,6 +4132,31 @@ async fn invoke_stop_live_agent(args: &Value, state: &BackendCore) -> Result<Val
serde_json::to_value(output).map_err(serialization_error)
}
async fn invoke_restart_cell_agent_runtime(
args: &Value,
state: &BackendCore,
) -> Result<Value, ErrorDto> {
let request =
required_request::<RestartCellAgentRuntimeRequestDto>("restart_cell_agent_runtime", args)?;
let project = resolve_project_readonly(&request.project_id, state).await?;
let output = state
.restart_cell_agent_runtime
.execute(application::RestartCellAgentRuntimeInput {
project,
node_id: parse_node_id(&request.node_id)?,
agent_id: parse_agent_id(&request.agent_id)?,
presentation: request.presentation.into(),
layout_id: request
.layout_id
.as_deref()
.map(parse_layout_id)
.transpose()?,
})
.map(RestartCellAgentRuntimeResponseDto::from)
.map_err(ErrorDto::from)?;
serde_json::to_value(output).map_err(serialization_error)
}
async fn invoke_create_agent(args: &Value, state: &BackendCore) -> Result<Value, ErrorDto> {
let request = required_request::<CreateAgentRequestDto>("create_agent", args)?;
let project = resolve_project_readonly(&request.project_id, state).await?;
@ -10748,6 +10777,7 @@ mod tests {
"list_resumable_agents",
"attach_live_agent",
"stop_live_agent",
"restart_cell_agent_runtime",
"create_agent",
"change_agent_profile",
"read_agent_context",