feat(chat): persistance bornee du brouillon custom chat par projet/layout (#182)

This commit is contained in:
2026-08-11 16:24:20 +02:00
parent 25ad44a3d9
commit 94b4ce7e5f
23 changed files with 1552 additions and 70 deletions

View File

@ -14,20 +14,20 @@ use crate::dto::DismissEmbedderSuggestionRequestDto;
use application::plugin_slash_commands_from_runtime_catalog;
use application::{
AppError, AssignSkillToAgentInput, AttachLiveAgentInput, ChangeAgentProfileInput,
CloseProjectInput, CreateAgentInput, CreateLayoutInput, CreateMemoryInput, CreateSkillInput,
DeleteAgentInput, DeleteEmbedderProfileInput, DeleteLayoutInput, DeleteMemoryInput,
DeleteSkillInput, DeleteTemplateInput, DetectAgentDriftInput, ExecuteSlashCommandInput,
GetMemoryInput, GetProjectSystemPermissionsInput, GetProjectWorkStateInput, GitBranchesInput,
GitCheckoutInput, GitCommitInput, GitGraphInput, GitInitInput, GitLogInput, GitStagePathInput,
GitStatusInput, InspectConversationInput, LaunchAgentInput, ListAgentsInput, ListDevicesInput,
ListLayoutsInput, ListMemoriesInput, ListResumableAgentsInput, ListSkillsInput,
ListSlashCommandsInput, LiveSessions, LoadLayoutInput, McpRuntime, MutateLayoutInput,
OpenPluginLayoutWindowInput, OpenProjectInput, ReadAgentContextInput,
ReadConversationPageInput, ReadMcpToolPermissionsInput, ReadMemoryIndexInput,
ReadProjectContextInput, RecallMemoryInput, ReconcileLayoutsInput, ReconcileLiveStateInput,
RenameDeviceInput, RenameLayoutInput, ResolveAgentPermissionsInput,
ChatDraftScopeInput, CloseProjectInput, CreateAgentInput, CreateLayoutInput, CreateMemoryInput,
CreateSkillInput, DeleteAgentInput, DeleteEmbedderProfileInput, DeleteLayoutInput,
DeleteMemoryInput, DeleteSkillInput, DeleteTemplateInput, DetectAgentDriftInput,
ExecuteSlashCommandInput, GetMemoryInput, GetProjectSystemPermissionsInput,
GetProjectWorkStateInput, GitBranchesInput, GitCheckoutInput, GitCommitInput, GitGraphInput,
GitInitInput, GitLogInput, GitStagePathInput, GitStatusInput, InspectConversationInput,
LaunchAgentInput, ListAgentsInput, ListDevicesInput, ListLayoutsInput, ListMemoriesInput,
ListResumableAgentsInput, ListSkillsInput, ListSlashCommandsInput, LiveSessions,
LoadLayoutInput, McpRuntime, MutateLayoutInput, OpenPluginLayoutWindowInput, OpenProjectInput,
ReadAgentContextInput, ReadConversationPageInput, ReadMcpToolPermissionsInput,
ReadMemoryIndexInput, ReadProjectContextInput, RecallMemoryInput, ReconcileLayoutsInput,
ReconcileLiveStateInput, RenameDeviceInput, RenameLayoutInput, ResolveAgentPermissionsInput,
ResolveAgentSystemPermissionsInput, ResolveMemoryLinksInput, RevokeDeviceInput,
RotateConversationLogInput, SetActiveLayoutInput, SlashCommandEffect,
RotateConversationLogInput, SaveChatDraftInput, SetActiveLayoutInput, SlashCommandEffect,
SnapshotRunningAgentsInput, StopLiveAgentInput, SyncAgentWithTemplateInput,
UnassignSkillFromAgentInput, UpdateAgentContextInput, UpdateAgentEffortInput,
UpdateAgentMcpToolPermissionsInput, UpdateAgentPermissionsInput,
@ -48,28 +48,29 @@ use crate::dto::{
AppExitWorkGuardStateDto, AssignSkillRequestDto, AttachBackgroundTaskResultDto,
AttachLiveAgentRequestDto, AttachLiveAgentResponseDto, BackgroundTaskDto, CellKind,
ChangeAgentProfileDto, ChangeAgentProfileRequestDto, ChatAttachmentDto, ChatAttachmentInputDto,
CloneOpenCodeProfileFromSeedRequestDto, CloneProfileFromSeedRequestDto,
ConfigureProfilesRequestDto, ConversationDetailsDto, CreateAgentFromTemplateRequestDto,
CreateAgentRequestDto, CreateLayoutRequestDto, CreateLayoutResultDto, CreateMemoryRequestDto,
CreateProjectRequestDto, CreateSkillRequestDto, CreateTemplateRequestDto,
DeleteLayoutRequestDto, DeleteLayoutResultDto, DeliveredDelegationRequestDto,
DetectProfilesRequestDto, DetectProfilesResponseDto, EmbedderEnginesDto, EmbedderProfileDto,
EmbedderProfileListDto, ErrorDto, ExecuteSlashCommandRequestDto,
ExecuteSlashCommandResponseDto, FirstRunStateDto, FrontAttachedRequestDto, GitBranchesDto,
GitCheckoutRequestDto, GitCommitDto, GitCommitListDto, GitCommitRequestDto, GitStageRequestDto,
GitStatusListDto, GraphCommitListDto, HealthRequestDto, HealthResponseDto,
ImportChatAttachmentsRequestDto, ImportChatAttachmentsResponseDto,
InspectConversationRequestDto, InterruptAgentRequestDto, LaunchAgentRequestDto, LayoutDto,
LayoutOperationDto, ListLayoutsDto, LiveAgentListDto, MemoryDto, MemoryIndexDto,
MemoryLinksDto, MemoryListDto, ModelServerConfigDto, ModelServerConfigListDto,
OpenCodeProviderListDto, OpenTerminalRequestDto, PreviewModelServerCommandDto, ProfileDto,
ProfileListDto, ProfileModelCatalogDto, ProjectDto, ProjectListDto,
ProjectMcpToolPermissionsDto, ProjectPermissionsDto, ProjectSystemPermissionsDto,
ProjectWorkStateDto, ReadAgentContextResponseDto, ReadConversationPageRequestDto,
ReattachChatDto, ReattachResultDto, RecallMemoryRequestDto, RenameLayoutRequestDto, ReplyChunk,
ResizeTerminalRequestDto, ResolveAgentPermissionsRequestDto,
ResolveAgentPermissionsResponseDto, ResolveAgentSystemPermissionsRequestDto,
ResolvedAgentSystemPermissionsDto, ResumableAgentListDto, SaveEmbedderProfileRequestDto,
ChatDraftScopeRequestDto, CloneOpenCodeProfileFromSeedRequestDto,
CloneProfileFromSeedRequestDto, ConfigureProfilesRequestDto, ConversationDetailsDto,
CreateAgentFromTemplateRequestDto, CreateAgentRequestDto, CreateLayoutRequestDto,
CreateLayoutResultDto, CreateMemoryRequestDto, CreateProjectRequestDto, CreateSkillRequestDto,
CreateTemplateRequestDto, DeleteLayoutRequestDto, DeleteLayoutResultDto,
DeliveredDelegationRequestDto, DetectProfilesRequestDto, DetectProfilesResponseDto,
EmbedderEnginesDto, EmbedderProfileDto, EmbedderProfileListDto, ErrorDto,
ExecuteSlashCommandRequestDto, ExecuteSlashCommandResponseDto, FirstRunStateDto,
FrontAttachedRequestDto, GitBranchesDto, GitCheckoutRequestDto, GitCommitDto, GitCommitListDto,
GitCommitRequestDto, GitStageRequestDto, GitStatusListDto, GraphCommitListDto,
HealthRequestDto, HealthResponseDto, ImportChatAttachmentsRequestDto,
ImportChatAttachmentsResponseDto, InspectConversationRequestDto, InterruptAgentRequestDto,
LaunchAgentRequestDto, LayoutDto, LayoutOperationDto, ListLayoutsDto, LiveAgentListDto,
MemoryDto, MemoryIndexDto, MemoryLinksDto, MemoryListDto, ModelServerConfigDto,
ModelServerConfigListDto, OpenCodeProviderListDto, OpenTerminalRequestDto,
PreviewModelServerCommandDto, ProfileDto, ProfileListDto, ProfileModelCatalogDto, ProjectDto,
ProjectListDto, ProjectMcpToolPermissionsDto, ProjectPermissionsDto,
ProjectSystemPermissionsDto, ProjectWorkStateDto, ReadAgentContextResponseDto,
ReadChatDraftResponseDto, ReadConversationPageRequestDto, ReattachChatDto, ReattachResultDto,
RecallMemoryRequestDto, RenameLayoutRequestDto, ReplyChunk, ResizeTerminalRequestDto,
ResolveAgentPermissionsRequestDto, ResolveAgentPermissionsResponseDto,
ResolveAgentSystemPermissionsRequestDto, ResolvedAgentSystemPermissionsDto,
ResumableAgentListDto, SaveChatDraftRequestDto, SaveEmbedderProfileRequestDto,
SaveModelServerRequestDto, SaveOpenCodeProviderProfileRequestDto, SaveProfileRequestDto,
SetActiveLayoutRequestDto, SetActiveLayoutResultDto, SkillDto, SkillListDto,
SlashCommandEffectDto, SlashCommandListDto, StopLiveAgentRequestDto, StopLiveAgentResponseDto,
@ -2237,6 +2238,77 @@ pub async fn change_agent_profile(
.map_err(ErrorDto::from)
}
fn chat_draft_scope_from_dto(
request: ChatDraftScopeRequestDto,
) -> Result<ChatDraftScopeInput, ErrorDto> {
Ok(ChatDraftScopeInput {
project_id: parse_project_id(&request.project_id)?,
layout_id: parse_layout_id(&request.layout_id)?,
node_id: parse_node_id(&request.node_id)?,
})
}
/// `read_chat_draft` — read persisted custom chat draft text for a project/layout/node.
///
/// # Errors
/// Returns an [`ErrorDto`] for malformed ids, unknown project, or store failure.
#[tauri::command]
pub async fn read_chat_draft(
request: ChatDraftScopeRequestDto,
state: State<'_, AppState>,
) -> Result<ReadChatDraftResponseDto, ErrorDto> {
let output = state
.read_chat_draft
.execute(chat_draft_scope_from_dto(request)?)
.await
.map_err(ErrorDto::from)?;
Ok(ReadChatDraftResponseDto {
text: output.text,
updated_at_ms: output.updated_at_ms,
})
}
/// `save_chat_draft` — persist custom chat draft text for a project/layout/node.
///
/// Empty text clears the draft. Attachments are not part of this contract.
///
/// # Errors
/// Returns an [`ErrorDto`] for malformed ids, unknown project, invalid text, or store failure.
#[tauri::command]
pub async fn save_chat_draft(
request: SaveChatDraftRequestDto,
state: State<'_, AppState>,
) -> Result<(), ErrorDto> {
state
.save_chat_draft
.execute(SaveChatDraftInput {
scope: ChatDraftScopeInput {
project_id: parse_project_id(&request.project_id)?,
layout_id: parse_layout_id(&request.layout_id)?,
node_id: parse_node_id(&request.node_id)?,
},
text: request.text,
})
.await
.map_err(ErrorDto::from)
}
/// `clear_chat_draft` — clear persisted custom chat draft text for a project/layout/node.
///
/// # Errors
/// Returns an [`ErrorDto`] for malformed ids, unknown project, or store failure.
#[tauri::command]
pub async fn clear_chat_draft(
request: ChatDraftScopeRequestDto,
state: State<'_, AppState>,
) -> Result<(), ErrorDto> {
state
.clear_chat_draft
.execute(chat_draft_scope_from_dto(request)?)
.await
.map_err(ErrorDto::from)
}
/// `agent_send` — send a prompt to a live **structured** (chat) session and pump
/// the turn's reply events to the frontend over `on_reply` (ARCHITECTURE §17.7).
///