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

@ -171,6 +171,38 @@ describe("TauriAgentGateway invoke payloads", () => {
expect(invoke).not.toHaveBeenCalledWith("close_agent_session", expect.anything());
});
it("sendAgentChat forwards structured clipboard attachments to agent_send", async () => {
await new TauriAgentGateway().sendAgentChat(
"chat-session-1",
"",
vi.fn(),
{
attachments: [
{
filename: "clipboard.png",
contentBase64: "AQID",
mime: "image/png",
sourceKind: "clipboard",
},
],
},
);
expect(invoke).toHaveBeenCalledWith("agent_send", {
sessionId: "chat-session-1",
prompt: "",
attachments: [
{
filename: "clipboard.png",
contentBase64: "AQID",
mime: "image/png",
sourceKind: "clipboard",
},
],
onReply: expect.anything(),
});
});
it("launchAgentChat returns a handle only when launch_agent confirms cellKind chat", async () => {
invoke.mockResolvedValueOnce({
sessionId: "chat-session-1",

View File

@ -32,6 +32,7 @@ import type {
OpenTerminalOptions,
ReattachAgentChatResult,
ReattachResult,
SendAgentChatOptions,
StoppedLiveAgent,
TerminalHandle,
} from "@/ports";
@ -261,12 +262,14 @@ export class TauriAgentGateway implements AgentGateway {
sessionId: string,
prompt: string,
onChunk: (chunk: ReplyChunk) => void,
options: SendAgentChatOptions = {},
): Promise<void> {
const channel = new Channel<ReplyChunk>();
channel.onmessage = onChunk;
await invoke("agent_send", {
sessionId,
prompt,
...(options.attachments ? { attachments: options.attachments } : {}),
onReply: channel,
});
}

View File

@ -150,6 +150,7 @@ import type {
RemoteGateway,
ReviewPluginPackageInput,
SaveOpenCodeProviderProfileInput,
SendAgentChatOptions,
SkillGateway,
StoppedLiveAgent,
SystemGateway,
@ -826,6 +827,7 @@ export class MockAgentGateway implements AgentGateway {
sessionId: string,
prompt: string,
onChunk: (chunk: ReplyChunk) => void,
_options: SendAgentChatOptions = {},
): Promise<void> {
const chunks = this.chatScrollback.get(sessionId);
if (!chunks) {