feat(chat): #155 paste image depuis presse-papier dans le composer custom (QA verte)

- frontend: onPaste sur CustomAgentChatView, détection MIME image, chip/preview d'attachment, envoi via le contrat #154 (adapters/agent, ports)

- backend: import d'image par bytes dans le store attachments (commands, chat_attachments app+infra, dto, ports) + tests
This commit is contained in:
2026-08-06 11:01:50 +02:00
parent 88dfbfe471
commit 790c4755be
15 changed files with 791 additions and 84 deletions

View File

@ -119,7 +119,26 @@ fn chat_attachment_input_dto_deserialises_camel_case() {
}))
.unwrap();
assert_eq!(dto.path, "/tmp/picked.png");
assert_eq!(dto.path.as_deref(), Some("/tmp/picked.png"));
assert_eq!(dto.filename, None);
assert_eq!(dto.content_base64, None);
assert_eq!(dto.mime.as_deref(), Some("image/png"));
assert_eq!(dto.source_kind, Some(ChatAttachmentSourceKind::Clipboard));
}
#[test]
fn chat_attachment_input_dto_deserialises_clipboard_bytes_camel_case() {
let dto: ChatAttachmentInputDto = serde_json::from_value(json!({
"filename": "clipboard.png",
"contentBase64": "cG5nIGJ5dGVz",
"mime": "image/png",
"sourceKind": "clipboard"
}))
.unwrap();
assert_eq!(dto.path, None);
assert_eq!(dto.filename.as_deref(), Some("clipboard.png"));
assert_eq!(dto.content_base64.as_deref(), Some("cG5nIGJ5dGVz"));
assert_eq!(dto.mime.as_deref(), Some("image/png"));
assert_eq!(dto.source_kind, Some(ChatAttachmentSourceKind::Clipboard));
}
@ -154,6 +173,11 @@ fn import_chat_attachments_request_response_use_camel_case() {
"path": "/tmp/picked.png",
"mime": "image/png",
"sourceKind": "dragDrop"
}, {
"filename": "clipboard.png",
"contentBase64": "cG5nIGJ5dGVz",
"mime": "image/png",
"sourceKind": "clipboard"
}]
}))
.unwrap();
@ -164,6 +188,10 @@ fn import_chat_attachments_request_response_use_camel_case() {
request.attachments[0].source_kind,
Some(ChatAttachmentSourceKind::DragDrop)
);
assert_eq!(
request.attachments[1].content_base64.as_deref(),
Some("cG5nIGJ5dGVz")
);
let response = ImportChatAttachmentsResponseDto {
attachments: vec![ChatAttachmentDto {