fix(domain,application,infrastructure,backend,app-tauri,frontend): Stop demande agent préserve la conversation ouverte — arrêt sans fermeture/clôture du chat, états cohérents après cancel sur les 3 adapters de session, cellule et workstate synchronisés — #343 (QA verte)
This commit is contained in:
@ -12,16 +12,19 @@ use serde_json::Value;
|
||||
|
||||
use application::{
|
||||
AgentBackgroundTaskState, AgentTicketState, AppError, AppExitWorkGuardDetail,
|
||||
AppExitWorkGuardState, AttachLiveAgentOutput, BackgroundTaskKindLabel, CellAgentPresentation,
|
||||
ConversationPreviewStatus, ConversationTurnWorkPreview, ConversationWorkSummary,
|
||||
CreateProjectInput, CreateProjectOutput, ExecuteSlashCommandOutput, GitGraphOutput,
|
||||
HealthInput, HealthReport, LayoutKind, ListProjectsOutput, ListSlashCommandsOutput,
|
||||
LiveRuntimeState, LiveSessionKind, LiveSessionSnapshot, OpenProjectOutput, ProjectWorkState,
|
||||
RestartCellAgentRuntimeOutput, RestoreOpenProjectFailure, RestoreOpenProjectsOutput,
|
||||
SlashCommandEffect, StopLiveAgentOutput, TicketWorkSource, TicketWorkStatus, TurnPage,
|
||||
TurnSource, TurnView,
|
||||
AppExitWorkGuardState, AttachLiveAgentOutput, BackgroundTaskKindLabel, CancelAgentChatOutput,
|
||||
CellAgentPresentation, ConversationPreviewStatus, ConversationTurnWorkPreview,
|
||||
ConversationWorkSummary, CreateProjectInput, CreateProjectOutput, ExecuteSlashCommandOutput,
|
||||
GitGraphOutput, HealthInput, HealthReport, LayoutKind, ListProjectsOutput,
|
||||
ListSlashCommandsOutput, LiveRuntimeState, LiveSessionKind, LiveSessionSnapshot,
|
||||
OpenProjectOutput, ProjectWorkState, RestartCellAgentRuntimeOutput, RestoreOpenProjectFailure,
|
||||
RestoreOpenProjectsOutput, SlashCommandEffect, StopLiveAgentOutput, TicketWorkSource,
|
||||
TicketWorkStatus, TurnPage, TurnSource, TurnView,
|
||||
};
|
||||
use domain::ports::{
|
||||
CancelCurrentTurnOutcome, ReplyProgress, ReplyProgressKind, ReplyProgressSource,
|
||||
ReplyProgressStage,
|
||||
};
|
||||
use domain::ports::{ReplyProgress, ReplyProgressKind, ReplyProgressSource, ReplyProgressStage};
|
||||
use domain::{
|
||||
AgentBusyState, PageCursor, PageDirection, Project, ProjectId, ProjectSystemPermissions,
|
||||
ResolvedAgentSystemPermissions, SlashCommand, SystemPermissionSet, TurnRole,
|
||||
@ -4763,6 +4766,45 @@ pub struct StopLiveAgentResponseDto {
|
||||
pub already_stopped: bool,
|
||||
}
|
||||
|
||||
/// Response DTO for a non-destructive `cancel_agent_chat` request.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CancelAgentChatResponseDto {
|
||||
/// Stable structured session, still live after the operation.
|
||||
pub session_id: String,
|
||||
/// Idempotent turn-level result.
|
||||
pub outcome: CancelAgentChatOutcomeDto,
|
||||
}
|
||||
|
||||
/// Public cancellation outcomes, distinct from a missing-session error.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum CancelAgentChatOutcomeDto {
|
||||
/// A running request was cancelled.
|
||||
Cancelled,
|
||||
/// That request had already been cancelled.
|
||||
AlreadyCancelled,
|
||||
/// The live session currently had no running request.
|
||||
AlreadyCompleted,
|
||||
}
|
||||
|
||||
impl From<CancelAgentChatOutput> for CancelAgentChatResponseDto {
|
||||
fn from(output: CancelAgentChatOutput) -> Self {
|
||||
Self {
|
||||
session_id: output.session_id.to_string(),
|
||||
outcome: match output.outcome {
|
||||
CancelCurrentTurnOutcome::Cancelled => CancelAgentChatOutcomeDto::Cancelled,
|
||||
CancelCurrentTurnOutcome::AlreadyCancelled => {
|
||||
CancelAgentChatOutcomeDto::AlreadyCancelled
|
||||
}
|
||||
CancelCurrentTurnOutcome::AlreadyCompleted => {
|
||||
CancelAgentChatOutcomeDto::AlreadyCompleted
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One stopped runtime in an agent-level stop response.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -6298,6 +6340,22 @@ mod tests {
|
||||
use serde_json::json;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[test]
|
||||
fn cancel_agent_chat_outcomes_are_stable_camel_case_values() {
|
||||
let response = CancelAgentChatResponseDto::from(CancelAgentChatOutput {
|
||||
session_id: domain::SessionId::from_uuid(Uuid::from_u128(343)),
|
||||
outcome: CancelCurrentTurnOutcome::AlreadyCancelled,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
serde_json::to_value(response).unwrap(),
|
||||
json!({
|
||||
"sessionId": Uuid::from_u128(343).to_string(),
|
||||
"outcome": "alreadyCancelled"
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn settings_dtos_are_additive_and_validate_language_and_icon_contracts() {
|
||||
let legacy_user: UserSettingsDto = serde_json::from_value(json!({})).unwrap();
|
||||
|
||||
Reference in New Issue
Block a user