fix(layout): auto-réparer l'onglet actif
stale
Le backend renvoie l'id actif autoritaire et le
frontend l'adopte pour éviter de rejouer un layout
disparu après overwrite externe.
Co-Authored-By: Claude Opus 4.8
<noreply@anthropic.com>
This commit is contained in:
@ -19,12 +19,11 @@ use application::{
|
||||
ListResumableAgentsInput, ListSkillsInput, LiveSessions, LoadLayoutInput, McpRuntime,
|
||||
MutateLayoutInput, OpenProjectInput, ReadAgentContextInput, ReadConversationPageInput,
|
||||
ReadMemoryIndexInput, ReadProjectContextInput, RecallMemoryInput, ReconcileLayoutsInput,
|
||||
ReconcileLiveStateInput,
|
||||
RenameLayoutInput, ResolveAgentPermissionsInput, ResolveMemoryLinksInput,
|
||||
RotateConversationLogInput, SetActiveLayoutInput, SnapshotRunningAgentsInput,
|
||||
StopLiveAgentInput, SyncAgentWithTemplateInput, UnassignSkillFromAgentInput,
|
||||
UpdateAgentContextInput, UpdateAgentPermissionsInput, UpdateMemoryInput,
|
||||
UpdateProjectContextInput, UpdateProjectPermissionsInput, UpdateSkillInput,
|
||||
ReconcileLiveStateInput, RenameLayoutInput, ResolveAgentPermissionsInput,
|
||||
ResolveMemoryLinksInput, RotateConversationLogInput, SetActiveLayoutInput,
|
||||
SnapshotRunningAgentsInput, StopLiveAgentInput, SyncAgentWithTemplateInput,
|
||||
UnassignSkillFromAgentInput, UpdateAgentContextInput, UpdateAgentPermissionsInput,
|
||||
UpdateMemoryInput, UpdateProjectContextInput, UpdateProjectPermissionsInput, UpdateSkillInput,
|
||||
};
|
||||
use domain::ports::PtyHandle;
|
||||
|
||||
@ -49,13 +48,13 @@ use crate::dto::{
|
||||
ReadConversationPageRequestDto, ReattachChatDto, ReattachResultDto, RecallMemoryRequestDto,
|
||||
RenameLayoutRequestDto, ReplyChunk, ResizeTerminalRequestDto,
|
||||
ResolveAgentPermissionsRequestDto, ResumableAgentListDto, SaveEmbedderProfileRequestDto,
|
||||
SaveProfileRequestDto, SetActiveLayoutRequestDto, SkillDto, SkillListDto,
|
||||
StopLiveAgentRequestDto, StopLiveAgentResponseDto, SyncAgentWithTemplateRequestDto,
|
||||
SyncResultDto, TemplateDto, TemplateListDto, TerminalClosedDto, TerminalSessionDto,
|
||||
TurnPageDto, UnassignSkillRequestDto, UpdateAgentContextRequestDto,
|
||||
UpdateAgentPermissionsRequestDto, UpdateMemoryRequestDto, UpdateProjectContextRequestDto,
|
||||
UpdateProjectPermissionsRequestDto, UpdateSkillRequestDto, UpdateTemplateRequestDto,
|
||||
WriteTerminalRequestDto,
|
||||
SaveProfileRequestDto, SetActiveLayoutRequestDto, SetActiveLayoutResultDto, SkillDto,
|
||||
SkillListDto, StopLiveAgentRequestDto, StopLiveAgentResponseDto,
|
||||
SyncAgentWithTemplateRequestDto, SyncResultDto, TemplateDto, TemplateListDto,
|
||||
TerminalClosedDto, TerminalSessionDto, TurnPageDto, UnassignSkillRequestDto,
|
||||
UpdateAgentContextRequestDto, UpdateAgentPermissionsRequestDto, UpdateMemoryRequestDto,
|
||||
UpdateProjectContextRequestDto, UpdateProjectPermissionsRequestDto, UpdateSkillRequestDto,
|
||||
UpdateTemplateRequestDto, WriteTerminalRequestDto,
|
||||
};
|
||||
use crate::pty::{PtyBridge, PtyChunk};
|
||||
use crate::state::AppState;
|
||||
@ -678,14 +677,16 @@ pub async fn delete_layout(
|
||||
|
||||
/// `set_active_layout` — switch the active named layout of a project.
|
||||
///
|
||||
/// Self-healing: a stale `layout_id` does not error; the active layout is left
|
||||
/// unchanged and the actually-active id is returned (authoritative).
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns an [`ErrorDto`] (`INVALID` for malformed id, `NOT_FOUND` if the
|
||||
/// project or layout is unknown).
|
||||
/// Returns an [`ErrorDto`] (`INVALID` for malformed id) or a persistence error.
|
||||
#[tauri::command]
|
||||
pub async fn set_active_layout(
|
||||
request: SetActiveLayoutRequestDto,
|
||||
state: State<'_, AppState>,
|
||||
) -> Result<(), ErrorDto> {
|
||||
) -> Result<SetActiveLayoutResultDto, ErrorDto> {
|
||||
let project_id = parse_project_id(&request.project_id)?;
|
||||
let layout_id = parse_layout_id(&request.layout_id)?;
|
||||
state
|
||||
@ -695,6 +696,7 @@ pub async fn set_active_layout(
|
||||
layout_id,
|
||||
})
|
||||
.await
|
||||
.map(SetActiveLayoutResultDto::from)
|
||||
.map_err(ErrorDto::from)
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +390,7 @@ pub fn parse_session_id(raw: &str) -> Result<SessionId, ErrorDto> {
|
||||
|
||||
use application::{
|
||||
CreateLayoutOutput, DeleteLayoutOutput, LayoutInfo, LayoutOperation, ListLayoutsOutput,
|
||||
LoadLayoutOutput, MutateLayoutOutput,
|
||||
LoadLayoutOutput, MutateLayoutOutput, SetActiveLayoutOutput,
|
||||
};
|
||||
use domain::{AgentId, Direction, LayoutId, LayoutTree, NodeId};
|
||||
|
||||
@ -700,6 +700,23 @@ pub struct DeleteLayoutRequestDto {
|
||||
pub layout_id: String,
|
||||
}
|
||||
|
||||
/// Response DTO for `set_active_layout`.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SetActiveLayoutResultDto {
|
||||
/// The layout actually activated — equals the requested id when valid, else
|
||||
/// the unchanged current active id (self-healing fallback). Authoritative.
|
||||
pub active_id: String,
|
||||
}
|
||||
|
||||
impl From<SetActiveLayoutOutput> for SetActiveLayoutResultDto {
|
||||
fn from(out: SetActiveLayoutOutput) -> Self {
|
||||
Self {
|
||||
active_id: out.active_id.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Request DTO for `set_active_layout`.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
Reference in New Issue
Block a user