mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-16 19:29:26 +02:00
* docs(plans): chat attachment & image support implementation plan Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * feat(db): add chat_session_id/chat_message_id to attachment Co-authored-by: multica-agent <github@multica.ai> * feat(db): sqlc — chat_session_id on CreateAttachment + LinkAttachmentsToChatMessage Co-authored-by: multica-agent <github@multica.ai> * feat(file): upload-file accepts chat_session_id form field Co-authored-by: multica-agent <github@multica.ai> * feat(chat): SendChatMessage links uploaded attachments to the new message Co-authored-by: multica-agent <github@multica.ai> * feat(api): uploadFile accepts chatSessionId; sendChatMessage accepts attachmentIds Co-authored-by: multica-agent <github@multica.ai> * feat(core): useFileUpload supports chatSessionId context Co-authored-by: multica-agent <github@multica.ai> * feat(chat): support paste/drag/upload attachments in chat input Co-authored-by: multica-agent <github@multica.ai> * test(e2e): chat input attachment upload + send round-trip Co-authored-by: multica-agent <github@multica.ai> * chore(chat): keep lazy-created session title empty so untitled fallback localizes Co-authored-by: multica-agent <github@multica.ai> * fix(chat): address review — dedupe ensureSession + parse upload response - chat-window: cache in-flight createSession promise in a ref so a file drop followed by a quick send no longer spawns two sessions (and orphans the attachment on the losing one). - Attachment type + EMPTY_ATTACHMENT + AttachmentResponseSchema: include the new chat_session_id / chat_message_id fields the server now returns. - uploadFile: route the response through parseWithFallback so a malformed body returns EMPTY_ATTACHMENT instead of an undefined-keyed Attachment, matching the API boundary rule. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * fix(chat): address PR #2445 review — test ctx, send gating, attachment surface 1. Backend test was 400ing because the handler reads workspace from middleware-injected ctx, and `newRequest` only sets the header. Helper `withChatTestWorkspaceCtx` mirrors the agent-access-test pattern and loads the member row + SetMemberContext before invoking the handler. 2. Attachment metadata now flows end-to-end: - new sqlc `ListAttachmentsByChatMessageIDs` (batch lookup, mirrors the comment-side query) - `chatMessageToResponse` takes `attachments` and `ChatMessageResponse` surfaces them — same shape as CommentResponse - `ListChatMessages` loads them via a new `groupChatMessageAttachments` helper so the chat bubble can render file cards - daemon claim path pulls `ListAttachmentsByChatMessage` for the latest user message and ships `ChatMessageAttachments` to the daemon - `buildChatPrompt` lists id+filename+content_type and instructs the agent to `multica attachment download <id>` — fixes the private-CDN expiring-URL problem where the markdown URL would have expired by the time the agent acts - TS `ChatMessage` gains an optional `attachments` field 3. Chat composer now blocks send while uploads are in flight: - `pendingUploads` counter increments in handleUpload, SubmitButton uses it to disable - handleSend also gates on `editorRef.current.hasActiveUploads()` to catch the Mod+Enter path that bypasses the button - new vitest covers the "drop large file → immediate send" scenario where attachment id would otherwise be silently dropped Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> * chore: drop implementation plan doc Process artefact, not something the repo needs to keep. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>