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:
@ -12,13 +12,14 @@ use serde_json::Value;
|
||||
|
||||
use application::{
|
||||
AgentBackgroundTaskState, AgentTicketState, AppError, AppExitWorkGuardDetail,
|
||||
AppExitWorkGuardState, AttachLiveAgentOutput, BackgroundTaskKindLabel,
|
||||
AppExitWorkGuardState, AttachLiveAgentOutput, BackgroundTaskKindLabel, CellAgentPresentation,
|
||||
ConversationPreviewStatus, ConversationTurnWorkPreview, ConversationWorkSummary,
|
||||
CreateProjectInput, CreateProjectOutput, ExecuteSlashCommandOutput, GitGraphOutput,
|
||||
HealthInput, HealthReport, LayoutKind, ListProjectsOutput, ListSlashCommandsOutput,
|
||||
LiveRuntimeState, LiveSessionKind, LiveSessionSnapshot, OpenProjectOutput, ProjectWorkState,
|
||||
RestoreOpenProjectFailure, RestoreOpenProjectsOutput, SlashCommandEffect, StopLiveAgentOutput,
|
||||
TicketWorkSource, TicketWorkStatus, TurnPage, TurnSource, TurnView,
|
||||
RestartCellAgentRuntimeOutput, RestoreOpenProjectFailure, RestoreOpenProjectsOutput,
|
||||
SlashCommandEffect, StopLiveAgentOutput, TicketWorkSource, TicketWorkStatus, TurnPage,
|
||||
TurnSource, TurnView,
|
||||
};
|
||||
use domain::ports::{ReplyProgress, ReplyProgressKind, ReplyProgressSource, ReplyProgressStage};
|
||||
use domain::{
|
||||
@ -4611,6 +4612,98 @@ pub struct StopLiveAgentRequestDto {
|
||||
pub reason: Option<String>,
|
||||
}
|
||||
|
||||
/// Informational presentation supplied by the cell that requests a restart.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum CellAgentPresentationDto {
|
||||
/// Background/headless orchestration surface.
|
||||
Headless,
|
||||
/// Native interactive provider terminal.
|
||||
Tui,
|
||||
/// IdeA structured/custom CLI chat.
|
||||
CustomCli,
|
||||
/// Presentation cannot be determined by the caller.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<CellAgentPresentationDto> for CellAgentPresentation {
|
||||
fn from(value: CellAgentPresentationDto) -> Self {
|
||||
match value {
|
||||
CellAgentPresentationDto::Headless => Self::Headless,
|
||||
CellAgentPresentationDto::Tui => Self::Tui,
|
||||
CellAgentPresentationDto::CustomCli => Self::CustomCli,
|
||||
CellAgentPresentationDto::Unknown => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CellAgentPresentation> for CellAgentPresentationDto {
|
||||
fn from(value: CellAgentPresentation) -> Self {
|
||||
match value {
|
||||
CellAgentPresentation::Headless => Self::Headless,
|
||||
CellAgentPresentation::Tui => Self::Tui,
|
||||
CellAgentPresentation::CustomCli => Self::CustomCli,
|
||||
CellAgentPresentation::Unknown => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Request for an atomic restart of the runtime bound to one agent cell.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RestartCellAgentRuntimeRequestDto {
|
||||
/// Owning project registry id.
|
||||
pub project_id: String,
|
||||
/// Exact hosting layout leaf.
|
||||
pub node_id: String,
|
||||
/// Agent expected to be bound to the leaf.
|
||||
pub agent_id: String,
|
||||
/// Informational presentation; the backend resolves the real runtime.
|
||||
#[serde(default = "unknown_cell_agent_presentation")]
|
||||
pub presentation: CellAgentPresentationDto,
|
||||
/// Optional named layout id when already known by the caller.
|
||||
#[serde(default)]
|
||||
pub layout_id: Option<String>,
|
||||
}
|
||||
|
||||
fn unknown_cell_agent_presentation() -> CellAgentPresentationDto {
|
||||
CellAgentPresentationDto::Unknown
|
||||
}
|
||||
|
||||
/// Immediate acknowledgement for an accepted cell restart.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RestartCellAgentRuntimeResponseDto {
|
||||
/// Correlation id used by `agentRestart*` events.
|
||||
pub restart_id: String,
|
||||
/// Stable acknowledgement state.
|
||||
pub status: &'static str,
|
||||
/// Validated agent id.
|
||||
pub agent_id: String,
|
||||
/// Validated node id.
|
||||
pub node_id: String,
|
||||
/// Actual live runtime family (`pty` or `structured`).
|
||||
pub kind: LiveWorkSessionKindDto,
|
||||
/// Informational presentation echoed to the caller.
|
||||
pub presentation: CellAgentPresentationDto,
|
||||
/// Optional layout id echoed to the caller.
|
||||
pub layout_id: Option<String>,
|
||||
}
|
||||
|
||||
impl From<RestartCellAgentRuntimeOutput> for RestartCellAgentRuntimeResponseDto {
|
||||
fn from(out: RestartCellAgentRuntimeOutput) -> Self {
|
||||
Self {
|
||||
restart_id: out.restart_id,
|
||||
status: "scheduled",
|
||||
agent_id: out.agent_id.to_string(),
|
||||
node_id: out.node_id.to_string(),
|
||||
kind: out.kind.into(),
|
||||
presentation: out.presentation.into(),
|
||||
layout_id: out.layout_id.map(|id| id.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Response DTO for `stop_live_agent`: the torn-down session's coordinates.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
Reference in New Issue
Block a user