fix(runtime): stop/restart d'agent visible robuste — kill réel, état stopped, relance froide (#196, QA verte)
Solidifie le cycle stop/restart d'un agent visible en cellule: - terminal/registry: kill effectif de la TUI native et de la CLI custom, arrêt idempotent du live runtime (PTY + structuré), distinction nette « agent stoppé » vs « pas de session ». - workstate + lifecycle: projection d'un état runtime explicite « stopped » (AgentRuntimeState: running/stopping/stopped/failedStart), réconcilié avec le live state; traitement des courses « agent not found ». - relance froide via freshStart: repart de zéro sans réattacher une session morte et recharge la configuration courante de l'agent (y compris changement de modèle). - contrat projeté côté adapters frontend (ports/domain/normalization/mock) pour la consommation UI future (#197/#198), sans surface UI ici. Tests QA verts: workstate_actions, orchestrator_service stop_agent, agent_lifecycle (reopen/fresh_start), workstate stopped runtime state, vitest adapter stop_live_agent.
This commit is contained in:
@ -10,8 +10,8 @@ use async_trait::async_trait;
|
||||
use application::{
|
||||
AppExitWorkGuardDetail, ConversationLogProvider, ConversationPreviewStatus,
|
||||
GetAppExitWorkGuardState, GetAppExitWorkGuardStateInput, GetProjectWorkState,
|
||||
GetProjectWorkStateInput, HandoffProvider, LiveSessionKind, LiveSessions, StructuredSessions,
|
||||
TerminalSessions, TicketWorkSource, TicketWorkStatus,
|
||||
GetProjectWorkStateInput, HandoffProvider, LiveRuntimeState, LiveSessionKind, LiveSessions,
|
||||
StructuredSessions, TerminalSessions, TicketWorkSource, TicketWorkStatus,
|
||||
};
|
||||
use domain::mailbox::{
|
||||
AgentQueueSnapshot, MailboxError, PendingReply, QueuedTicketSnapshot, Ticket, TurnResolution,
|
||||
@ -702,6 +702,37 @@ async fn workstate_attaches_live_structured_session_to_manifest_agent() {
|
||||
assert_eq!(live.kind, LiveSessionKind::Structured);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn workstate_exposes_stopped_runtime_state_without_live_session() {
|
||||
let a = agent(10, "alpha");
|
||||
let f = fixture(std::slice::from_ref(&a));
|
||||
let snapshot = application::LiveSessionSnapshot {
|
||||
project_id: f.project.id,
|
||||
agent_id: a.id,
|
||||
node_id: nid(300),
|
||||
session_id: sid(3),
|
||||
kind: LiveSessionKind::Pty,
|
||||
};
|
||||
let live = LiveSessions::new(Arc::clone(&f.pty), Arc::clone(&f.structured));
|
||||
live.mark_runtime_state(snapshot, LiveRuntimeState::Stopped);
|
||||
let usecase = GetProjectWorkState::new(
|
||||
Arc::new(FakeContexts {
|
||||
manifest: manifest(std::slice::from_ref(&a)),
|
||||
}),
|
||||
Arc::new(live),
|
||||
Arc::clone(&f.input) as Arc<dyn InputMediator>,
|
||||
Arc::clone(&f.queue) as Arc<dyn AgentQueueSnapshot>,
|
||||
);
|
||||
|
||||
let out = usecase
|
||||
.execute(GetProjectWorkStateInput { project: f.project })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(out.agents[0].live, None);
|
||||
assert_eq!(out.agents[0].runtime_state, Some(LiveRuntimeState::Stopped));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn app_exit_guard_is_false_without_busy_agent_or_active_background_task() {
|
||||
let a = agent(10, "alpha");
|
||||
|
||||
Reference in New Issue
Block a user