Skip to content

fix(frontend): send attached files from the expert side-panel chat and show the message at once (SECRT-2956 1/3) [1/3] - #15582

Merged
Abhi1992002 merged 10 commits into
devfrom
abhimanyuyadav/secrt-2956-expert-side-panel-chat-drops-attached-files-message-should-p1
Oct 17, 2026
Merged

Abhi1992002 merged 10 commits into
devfrom
abhimanyuyadav/secrt-2956-expert-side-panel-chat-drops-attached-files-message-should-p1

Conversation

@Abhi1992002

@Abhi1992002 Abhi1992002 commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Part of SECRT-2956
https://linear.app/autogpt/issue/SECRT-2956

This is PR 1 of 3. It fixes the bug. PR 2 adds per-file upload status with Retry, and PR 3 adds the new attachment cards.

Why / What / How

Why. In the Team page's expert side panel, a file attached to a message never reached the expert. The composer showed the file and cleared it on Send, but the drawer's onSend(message: string) ignored the files and workspaceFiles arguments that ChatInput passes. Nothing was uploaded and no file_ids went to /stream. In a new thread the panel also stayed on the "What can I do for you?" empty state until session creation returned (about 3 s), then showed the message as text only.

What. The side panel now uploads local files and workspace files and sends them with the message, in a new thread, in an existing thread, while the expert is still replying, and behind the expert's kickoff turn. The user's message and its files show on the first frame after Send, before any network call returns.

How. The upload-then-send code from /copilot's useSendMessage moves into a plain module, sendWithAttachments, and both surfaces call it. On /copilot the code moves without changes, and its tests pass unedited. The drawer keeps its own session and kickoff logic and holds the message locally until a session exists, so it never uses /copilot's global first-send slot. A follow-up with files sent mid-reply does not go through /messages/pending, because that buffer stores files without names and the transcript would drop them. The drawer holds it instead: the bubble shows and the upload starts right away, then the message goes out as the next turn once the reply has ended. Text-only follow-ups still use the buffer.

Changes 🏗️

  • copilot/helpers/sendWithAttachments.ts (new): OutgoingMessage, validateAttachments, describePendingUpload and sendWithAttachments({ sessionId, message, sendMessage, waitUntilReady? }), moved out of useSendMessage.ts. waitUntilReady runs after the uploads and before the send; returning false drops the placeholder.
  • copilot/useSendMessage.ts: calls the helper. No behaviour change on /copilot.
  • copilot/useSettleGate.ts (new): the "wait until the reply has ended" gate, taken out of useCopilotPage.ts, which now uses it. After unmount it resolves false rather than hanging.
  • team/components/ExpertChatDrawer/useExpertChatSend.ts (new): holds the user's message on screen until it can be sent, and sends every message with attachments through one gated send(). Before sending, it checks that the message's thread is still the one on screen and that the reply has fully ended, including any reconnect or finish probe.
  • team/components/ExpertChatDrawer/useNextCommit.ts (new): waits one React commit, so the gate does not open on an error status the render before the stream marks itself as reconnecting.
  • useExpertChatDrawer.ts: onSend(text, files?, workspaceFiles?) builds an OutgoingMessage. Every send path (first send after create, kickoff dequeue, the not-active fallback, a plain send) goes through send(). Thread resets clear the held message.
  • ExpertChatDrawer.tsx: renders the transcript when there is a session or a pending message, keeps onboarding hidden while a message is pending, and passes isUploadingFiles, expertId and expertName to ChatInput. Without expertId, the backend rejects workspace files outside the expert's scope.
  • ChatInput: new opt-in canAttachWhileStreaming prop, set only by the drawer, so files can be attached and queued while the expert replies. /copilot, the builder chat and memory chat keep today's behaviour.
  • copilot/store.ts and useChatInput.ts: a recoveredDraft slot. If a held message can't go out (for example after the user starts a new task during its upload), its text is added to the composer next to any new draft instead of replacing it, with a "Message not sent" toast.
  • copilot/helpers.ts: getSendSuppressionReason now calls a send a duplicate only when both the text and the attachments match the last user message. Before, a new file sent with the same caption as the last message was dropped, in the drawer and on /copilot too.
  • Stop while a follow-up with files is held: useExpertChatSend counts Stops, and a held send that sees a Stop after it was queued does not go out. Its text goes back to the composer with a "Message not sent" toast. This matches the backend, which throws away buffered follow-ups when a reply is cancelled.
  • Tests: ExpertChatDrawer/__tests__/attachments.test.tsx (new, MSW). It covers a new thread, an existing thread with a workspace file, mid-reply hold, kickoff hold, a dropped connection, a send during a reconnect, closing the panel during an upload, and a new task during an upload. Plus a ChatInput test for queuing files during a reply.

Known limits, as the plan expected:

  • While a held follow-up waits for the reply to end, its bubble still says "Uploading 1 file…" after the upload has finished. PR 2 replaces that flag with a status per file.
  • A held follow-up is dropped if the panel is closed before it goes out. The thread is not left locked.
  • After Stop, the held follow-up's text comes back but its files have to be attached again. The toast says so.
  • Byte-level upload progress and failed-upload Retry are not in this PR (PR 2).

Evidence 📸

Verdict: PASS at 2080f3787 (round 5). This replaces the earlier evidence taken at b9cf15078. Since then the branch merged dev, which changed the shared composer, and added the duplicate-send fix and the Stop fix, so every row was proven again on the running app (Docker deps, native backend, next dev). Synthetic users and data only, reduced motion on, 1440×1000 and 390×844. No model key was available, so a scripted provider answered the turns. There are no "before" shots because there was no dev URL to capture from.

Criterion Result 1440 390
Proof 1: the bubble with the file shows on the first frame after Send in a new thread (50 ms / 52 ms after the click), while session create and upload are each held back 1.5 s PASS New thread, right after Send New thread, right after Send, 390
Proof 1: the image uploads, then /stream carries file_ids (create → upload ?session_id= → /stream) PASS New thread, sent New thread, sent, 390
Proof 2: a workspace PDF picked in an existing thread goes out with file_ids PASS Workspace file, existing thread Workspace file, existing thread, 390
Proof 3: a file can be attached while the expert replies (Queue message next to Stop) PASS Attach during a reply Attach during a reply, 390
Proof 3: the follow-up is held under the reply, with no /messages/pending call PASS Held follow-up Held follow-up, 390
Proof 3: it goes out as the next turn with file_ids PASS Follow-up sent Follow-up sent, 390
Proof 4: a file sent during a new expert's kickoff reply is held PASS Held behind kickoff Held behind kickoff, 390
Proof 4: it goes out after the kickoff with file_ids PASS Sent after kickoff Sent after kickoff, 390
Proof 8: /copilot new chat still shows the "Uploading 1 file…" bubble PASS /copilot new chat uploading /copilot new chat uploading, 390
Proof 8: /copilot existing chat still sends a file with file_ids PASS /copilot existing chat sent /copilot existing chat sent, 390
Extra (new in 2080f3787): Stop while a follow-up with a file is held. The bubble goes, the text is back in the composer with a "Message not sent" toast, and no /stream with files goes out PASS Stop returns the held message —
Extra: a file sent during a real dropped connection ("Reconnecting…") is held, then sent after the resumed reply ends PASS Held during reconnect —
Extra: closing the panel during an upload leaves the chat usable on reopen PASS Reopened after close —
Extra: a new task during an upload keeps the new draft and gives the old text back PASS Draft recovered —
The expert's reply describes the image / mentions the PDF UNPROVEN No model key here. The file reference reaches the persisted user message (name (type, size), file_id=…). —

Requests the browser recorded:

New thread (Proof 1):     POST /chat/sessions → POST /workspace/files/upload?session_id=<id> → POST /chat/sessions/<id>/stream  file_ids=[1 id]
Workspace file (Proof 2): POST /chat/sessions/<id>/stream  file_ids=[1 id]
Mid-reply (Proof 3):      pending POSTs=0; /stream file_ids=null (reply) → /stream file_ids=[1 id] (follow-up, ~18 s later)
Kickoff (Proof 4):        pending POSTs=0; /stream expert_kickoff=true → /stream file_ids=[1 id] (~20 s later)
Stop while held:          upload=1; no /stream with files after Stop; pending POSTs=0
/copilot new (Proof 8):   POST /chat/sessions → upload → /stream file_ids=[1 id]
/copilot existing:        upload → /stream file_ids=[1 id]

Also: 277/277 targeted tests across 15 files (drawer __tests__, ChatInput __tests__, useSendMessage, CopilotPage, helpers.test).

Notes: while a held follow-up waits for the reply to end, its bubble still says "Uploading 1 file…" after the upload has finished. PR 2 replaces that flag with a status for each file. The "Connection lost / Reconnecting…" toast in some shots comes from the stream's existing resume logic, which this PR does not change. The held files went out in every run.

Agents and large language models used

  • Claude Code with Claude Opus 5.5 (1M context) (plan, fix, review, evidence and this PR).

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • Unit and integration tests at 2080f3787: 277/277 across 15 targeted files in the evidence step (drawer __tests__, ChatInput __tests__, useSendMessage, CopilotPage, helpers.test). Earlier, in review at b9cf15078, 308/308 across 25 files. attachments.test.tsx failed before the fix and passes after it, and the two drawer tests added for the duplicate-caption and Stop fixes fail on the code before them. pnpm format, pnpm lint and pnpm types are clean.
    • Running app (Docker deps, native backend, next dev), 1440 and 390 wide: new thread with a local image. The bubble shows 50 ms after the click (52 ms at 390) while session create is held back, then the upload runs, then /stream with file_ids.
    • Running app: a workspace PDF picked in an existing thread goes out with file_ids.
    • Running app: a file attached and sent while the expert replies is held under the reply, makes no /messages/pending call, and goes out as the next turn with file_ids.
    • Running app: a file sent during a new expert's kickoff reply goes out after the kickoff with file_ids.
    • Running app: /copilot still sends files in new and existing chats, with the "Uploading 1 file…" bubble.
    • Running app (1440 only): Stop while a follow-up with a file is held (nothing with files goes out, the text comes back), a send during a real dropped connection, closing the panel during an upload, and a new task during an upload (the new draft is kept).
    • Reviewer: with a real model key, send an image in the side panel and check that the expert's reply describes it. The evidence workspace had no model key, so a scripted provider completed the turns. That provider does not read files, so the reply content is unproven. The file reference does reach the persisted user message (name (type, size), file_id=…).
    • Full pnpm test:unit and Playwright suites (CI).

For configuration changes:

No configuration changes.

  • .env.default is updated or already compatible with my changes
  • docker-compose.yml is updated or already compatible with my changes
  • I have included a list of my configuration changes in the PR description (under Changes)

🤖 Generated with Claude Code


Open workspace in Conductor

Abhi1992002 and others added 7 commits October 16, 2026 05:08
The drawer's onSend ignores the files and workspace files ChatInput hands
it, and draws nothing until the session exists. These tests send a local
file in a new thread, a workspace file in an existing one, a file while
the expert is still replying, and a file queued behind the kickoff, and
expect the message on screen at once and file_ids on /stream. They fail
until the fix lands.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…SendMessage

The upload, placeholder and send steps lived inside the /copilot hook, so
the expert side panel could not reuse them and sent text only. They now
live in helpers/sendWithAttachments.ts as one OutgoingMessage type and
a sendWithAttachments() both surfaces can call, with an optional
waitUntilReady step between the uploads and the send. The settle waiters
in useCopilotPage move to useSettleGate so the panel can wait on its own
reply the same way. No behaviour change on /copilot.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…d show the message at once

The side panel's onSend took only the text, so files and workspace files
attached in it never reached the expert, and nothing was drawn until the
session existed, which left the empty state up for seconds after Send.

Every send path in the panel now goes through sendWithAttachments, so
local files upload into the session and go out as file_ids with the
message, in new and existing threads and behind the kickoff. The message
shows from the first render after Send: held in the panel until a
session exists, then as the session's upload placeholder. A follow-up
with files sent while the expert is replying uploads at once and goes
out as the next turn when the reply ends, because the pending buffer
would store its files without their names. If the user starts a new task
before it goes out, its text comes back to the composer. The composer
now gets the expert's id and name, as on /copilot, so the workspace
picker offers that expert's files.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…replies

The composer closed the attach menu, paste and workspace mentions for the
whole reply, and its Queue button only carried text, so a file could not
be sent mid-reply even though the drawer now holds such a message and
sends it as the next turn.

ChatInput takes `canAttachWhileStreaming`. With it, attaching stays open
during a reply, and Queue message (like Enter) sends a message that has
attachments through `onSend`. Only the side panel sets it: /copilot still
refuses to queue files.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…nd through a reconnect

Two ways a message with files could go wrong after Send:

- It was sent with whatever `sendMessage` the panel held when the uploads
  finished. After New task, that belongs to the new thread, so the old
  task's text and files were posted to it. A send now checks that its
  thread is still on screen; if not, the text goes back to the composer.
- A follow-up held until the reply ended was released on `status`
  `ready`/`error` alone. The SDK sets `status` on React's sync lane, but
  the stream's reconnect and post-finish probe flags render one pass later,
  so the send went out while the stream was reconnecting. The stream
  dropped it and the bubble disappeared. The panel now waits for
  `isReconnecting` and `isFinishProbing` too, and confirms the turn is still
  over once those later updates have rendered (`useNextCommit`).

Tests now attach through the visible menu and send with the Queue
button and Enter. They also cover a workspace file picked mid-reply, an
upload that outlives its thread, and a connection dropped while a file is
held.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…anel closes, and over a new draft

Three ways the expert side panel still loses or locks a message with files:
- a file sent while the connection is being restored is cleared from the
  screen and never sent;
- closing the panel while a file uploads leaves the thread's composer
  locked when it is opened again, with or without a reply in flight;
- a message sent back to the composer after New task replaces what the
  user has typed in the new task.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…nel and a new draft

Every message with files now goes out through one send that waits until
the reply in flight has ended. Before, that wait only applied when the SDK
said a reply was streaming. A message sent while the connection was being
restored, or right after a kickoff reply, skipped it, and the stream then
refused the send without telling its caller.

The settle gate and the commit barrier return false once their host has
unmounted. An upload that finished after the panel closed used to wait on
them forever, so the thread's placeholder stayed and its composer stayed
locked.

A message the panel hands back goes into a new recovered-draft slot. The
composer adds it to what the user has typed instead of replacing it. Guided
prompts keep the replace behaviour of `initialPrompt`.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Oct 16, 2026
@Abhi1992002
Abhi1992002 requested a review from a team as a code owner October 16, 2026 08:03
@Abhi1992002
Abhi1992002 requested review from Bentlybro and Pwuts and removed request for a team October 16, 2026 08:03
@github-actions github-actions Bot added platform/frontend AutoGPT Platform - Front end cla: pending CLA not yet signed by all contributors labels Oct 16, 2026
@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d080d75d-f663-453d-a560-35ffe14014bd
📥 Commits

Reviewing files that changed from the base of the PR and between c9362b5 and 2080f37.

📒 Files selected for processing: 6
  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout: 15
  • GitHub Check: check API types
  • GitHub Check: end-to-end tests (smoke)
  • GitHub Check: end-to-end tests (journeys)
  • GitHub Check: conflicts
  • GitHub Check: Seer Code Review
  • GitHub Check: integration_test (shard 1/4)
  • GitHub Check: integration_test (shard 3/4)
  • GitHub Check: integration_test (shard 4/4)
  • GitHub Check: knip
  • GitHub Check: integration_test (shard 2/4)
  • GitHub Check: Analyze (typescript)
  • GitHub Check: Check PR Status
  • GitHub Check: check-overlaps
  • GitHub Check: lint
  • GitHub Check: Analyze (python)
🧰 Additional context used
📚 Code guidelines: 2
autogpt_platform/frontend/AGENTS.md — unknown
AGENTS.md — unknown
📓 Path-based instructions: 4
Source excerpt: After making **any** code changes in the frontend, you MUST run the following commands **in order** before reporting work as done, creating commits, or opening PRs: Source excerpt: After making **any** code changes in the fr...

📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts
Source excerpt: See `/frontend/CONTRIBUTING.md` for complete patterns.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts
Source excerpt: Format frontend code using `pnpm format`.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts
Source excerpt: Format Python code with `poetry run format`.

📄 CodeRabbit inference engine (AGENTS.md)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts

Walkthrough

Copilot and Expert Chat now share attachment-aware message handling. Expert Chat can hold attachment-bearing messages until the current reply ends, including during reconnection, and display pending sends. The changes also add upload validation, failed-draft recovery, and attachment-flow tests.

Changes

Attachment-aware chat

Layer / File(s) Summary
Shared attachment send path
autogpt_platform/frontend/src/app/(platform)/copilot/helpers/sendWithAttachments.ts, autogpt_platform/frontend/src/app/(platform)/copilot/useSendMessage.ts, autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts, autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotStream.ts
Outgoing messages carry text, local files, stored parts, and optional metadata. Shared helpers validate, upload, and dispatch attachments. Duplicate-send checks compare both text and attachment keys.
Streaming input and draft recovery
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatInput/*, autogpt_platform/frontend/src/app/(platform)/copilot/store.ts, autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts, autogpt_platform/frontend/src/app/(platform)/copilot/useSettleGate.ts
ChatInput can accept attachments during streaming when enabled. Copilot uses a settle gate, and the UI store saves recovered drafts that useChatInput restores to the composer.
Expert Chat attachment flow
autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/*
Expert Chat passes complete outgoing messages through session and kickoff flows. Attachment sends wait for stream settlement and are recovered if the thread changes or Stop occurs. The drawer displays pending sends, and tests cover uploads, workspace files, reconnection, thread changes, and drawer closure.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ChatInput
  participant useExpertChatDrawer
  participant useExpertChatSend
  participant sendWithAttachments
  participant useCopilotStream
  ChatInput->>useExpertChatDrawer: Submit outgoing message
  useExpertChatDrawer->>useExpertChatSend: Send message with attachments
  useExpertChatSend->>useExpertChatSend: Wait for reply settlement
  useExpertChatSend->>sendWithAttachments: Upload and prepare attachments
  sendWithAttachments->>useCopilotStream: Send message parts
Loading
Merge Risk: ⚪ Minimal · up to 2080f

The reviewed attachment flow has no established merge-blocking issue; it is ready for normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 65 functions across 17 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly describes the primary change: sending attached files from the expert side-panel chat and displaying the message immediately. The issue and PR sequence suffix add noise but do not mak…
Description check Passed The description is directly related to the changeset. It explains the attachment flow, immediate message display, follow-up handling, recovery behavior, tests, evidence, and known limitations.
Full details: Title check

Explanation

The title clearly describes the primary change: sending attached files from the expert side-panel chat and displaying the message immediately. The issue and PR sequence suffix add noise but do not make the title misleading.

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Abhi1992002

Copy link
Copy Markdown
Member Author

Evidence

Verdict: PASS at b9cf15078. All captures come from the running app (Docker deps, native backend, next dev) with synthetic users and data, reduced motion on, at 1440×1000 and 390×844. No model key was available, so a scripted provider answered the turns; its replies say nothing about the files. No "before" shots: there was no dev URL to capture from.

Criterion Result 1440 390
Proof 1: the bubble with the file shows on the first frame after Send in a new thread (41 ms / 57 ms), with session create and upload held back 1.5 s each PASS New thread, right after Send New thread, right after Send, 390
Proof 1: the image is uploaded and /stream carries file_ids (create → upload ?session_id= → /stream) PASS New thread, sent New thread, sent, 390
Proof 2: a workspace PDF picked in an existing thread goes out with file_ids PASS Workspace file, existing thread Workspace file, existing thread, 390
Proof 3: a file can be attached while the expert replies (Queue message next to Stop) PASS Attach during a reply Attach during a reply, 390
Proof 3: the follow-up is held under the reply, with no /messages/pending call PASS Held follow-up Held follow-up, 390
Proof 3: it goes out as the next turn with file_ids PASS Follow-up sent Follow-up sent, 390
Proof 4: a file sent during a new expert's kickoff reply is held PASS Held behind kickoff Held behind kickoff, 390
Proof 4: it goes out after the kickoff with file_ids PASS Sent after kickoff Sent after kickoff, 390
Proof 8: /copilot new chat still shows the "Uploading 1 file…" bubble PASS /copilot new chat uploading /copilot new chat uploading, 390
Proof 8: /copilot existing chat still sends a file with file_ids PASS /copilot existing chat sent /copilot existing chat sent, 390
Extra: a file sent during "Reconnecting…" is held, then sent after the resumed reply ends PASS Held during reconnect —
Extra: closing the panel during an upload leaves the chat usable on reopen PASS Reopened after close —
Extra: a new task during an upload keeps the new draft and gives the old text back PASS Draft recovered —
The expert's reply describes the image / mentions the PDF UNPROVEN No model key in the evidence workspace. The file reference reaches the persisted user message (name (type, size), file_id=…). —

Requests recorded by the browser:

New thread (Proof 1):     POST /chat/sessions → POST /workspace/files/upload?session_id=<id> → POST /chat/sessions/<id>/stream  file_ids=1
Workspace file (Proof 2): POST /chat/sessions/<id>/stream  file_ids=1
Mid-reply (Proof 3):      pending POSTs=0; /stream file_ids=null (reply) → /stream file_ids=[1 id] (follow-up)
Kickoff (Proof 4):        pending POSTs=0; /stream expert_kickoff=true → /stream file_ids=[1 id]
/copilot new (Proof 8):   POST /chat/sessions → upload → /stream file_ids=1
/copilot existing:        upload → /stream file_ids=1

Notes: while a held follow-up waits for the reply to end, its bubble still says "Uploading 1 file…" after the upload has finished. PR 2 replaces that flag with a status per file. The "Connection lost / Reconnecting…" toast in some shots comes from the stream's existing resume logic, which this PR does not change; the held files still went out in every run.

@github-actions github-actions Bot added cla: signed CLA signed by all contributors and removed cla: pending CLA not yet signed by all contributors labels Oct 16, 2026
@Abhi1992002

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

autogpt-pr-reviewer Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🤖 Review of b9cf150 posted: #15582 (review)

@capy-ai capy-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capy found 2 potential issues (2 medium).

Open in Capy

…956-expert-side-panel-chat-drops-attached-files-message-should-p1

Resolve the ChatInput.tsx conflict by keeping both props: this PR's
canAttachWhileStreaming and dev's atReset.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

This check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early.

🔴 Merge Conflicts Detected

The following PRs have been tested and will have merge conflicts if merged after this PR. Consider coordinating with the authors.

🟢 Low Risk — File Overlap Only

These PRs touch the same files but different sections (click to expand)

Summary: 3 conflict(s), 0 medium risk, 5 low risk (out of 8 PRs with file overlap)


Auto-generated on push. Ignores: openapi.json, lock files.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.89212% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.87%. Comparing base (9849b32) to head (2080f37).

Additional details and impacted files
@@           Coverage Diff            @@
##              dev   #15582    +/-   ##
========================================
  Coverage   86.87%   86.87%            
========================================
  Files        4947     4951     +4     
  Lines      378328   378471   +143     
  Branches    33657    33689    +32     
========================================
+ Hits       328656   328814   +158     
+ Misses      44196    44179    -17     
- Partials     5476     5478     +2     
Flag Coverage Δ
platform-frontend 71.73% <85.83%> (+0.12%) ⬆️
platform-frontend-e2e 29.51% <32.46%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Platform Backend 90.25% <ø> (ø)
Platform Frontend 73.02% <85.89%> (+0.09%) ⬆️
AutoGPT Libs ∅ <ø> (∅)
Classic AutoGPT 28.43% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Abhi1992002 and others added 2 commits October 16, 2026 08:19
…st one

The duplicate-send guard compared only text, so a held side-panel follow-up
with a file and the same caption as the previous message was dropped as a
resend. The guard now also compares the attachments.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>
…pped

Stop ended the reply and the held message with files went out right after,
while the backend discards buffered text follow-ups on cancel. Now Stop
cancels it, puts its text back in the composer and says why.

Co-authored-by: Claude Opus 5.5 (Claude Code) <noreply@anthropic.com>

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Verdict: Approved — No findings require changes before approval; this review counts as an approval.

Well-structured frontend refactor extracting the upload-then-send path into a shared helper and wiring attached files through the expert side-panel chat; no reachable defect found and the concurrency-heavy paths are covered by passing integration tests. Required CI is still pending and the branch currently conflicts with its base, which must be resolved before merge.

Risk level: low | Human review: not required | Duration: 369s | Reviewed: b9cf1507

Findings: 🔴 0 blockers | 🟠 2 should fix | 🟡 1 nice to have | 🔵 1 nit

Optional advice — does not block approval

Follow-ups

  • 🟠 autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatDrawer.ts:303 Stabilize send/release so drawer effects fire on sessionId, not every render — This effect and the kickoff-dequeue effect at line 249 depend on send, which useExpertChatSend recreates every render, so both re-run every render. They avoid duplicate sends only because pendingPromptRef/kickoffAttemptRef are nulled synchronously inside each effect; a future edit to that guard would turn the benign re-run into a duplicate send.
    Suggestion: Stabilize send/release behind a ref (as useSendMessage.ts does with dispatchRef) so the effects trigger on sessionId change only.
  • 🟠 autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/useExpertChatSend.ts:128 Scope recoveredDraft so a dropped drawer message can't reappear in /copilot — recoverUnsentMessage/returnToComposer write to the global useCopilotUIStore. If the drawer unmounts before useChatInput consumes recoveredDraft, the text persists and is appended into the next-mounted consumer (e.g. /copilot). No data loss since it appends, and the window is narrow.
    Suggestion: Scope the recovery slot per surface or clear recoveredDraft on drawer unmount.
Optional advice — does not block approval

🟡 Nice to Have

  • 🔵 autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/ExpertChatDrawer.tsx:190 Keep composer usable while a mid-reply attachment is merely held — isUploadingFiles is bound to !!pendingSend, which stays true for the whole reply while a follow-up attachment is held, disabling the textarea the entire time rather than only during the upload. Explicitly deferred to PR 2.
    Suggestion: Distinguish 'actively uploading' from 'held waiting for reply to end'; acceptable to defer with the PR 2 per-file-status work.
Optional advice — does not block approval

🔵 Nits

  • 🔵 autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/__tests__/attachments.test.tsx:254 Reset useCopilotUIStore in attachments test beforeEach — beforeEach resets the stream store and localStorage but not useCopilotUIStore, which now holds mutable cross-test state (recoveredDraft, initialPrompt). No leak today, but a future test could become order-dependent.
    Suggestion: Add useCopilotUIStore.setState({ recoveredDraft: null, initialPrompt: null }) to beforeEach.

GitHub CI on reviewed head: failure

Validation and specialist details

Specialist Reports

Specialist Status Summary
security ✅ PASS Frontend-only chat composer refactor with no new security surface; workspace-file scoping is correctly tightened via expertId and file-size/count validation is preserved.
architect ✅ PASS Well-structured extraction that routes drawer attachment sends through the shared upload-then-send path with carefully-correct settle/commit timing and thread-identity guards; no blocking defects, one low maintainability note.
performance ✅ PASS Client-side upload/send coordination with no reachable performance, memory, or scalability defects; uploads are parallelized and all async-gate waiters are cleaned up on settle and unmount.
testing ✅ PASS Comprehensive, assertion-strong integration tests directly verify the attachment-send fix and every hold/recovery path; no blocking test defects found.
quality ✅ PASS Clean extraction of the upload-then-send path into shared helpers plus a well-tested fix that sends side-panel attachments and renders the user's message on the first frame; no concrete defects found.
product ✅ PASS Attachment sending from the expert side-panel is implemented correctly across all send states with the message shown on the first frame; copy rules respected and edge cases covered by tests, with one advisory composer-disabled UX limitation.
discussion ✅ PASS No open human-reviewer threads; required checks pending, but the branch has a merge conflict with its base that must be resolved.
ui-reviewer (local) ✅ PASS Frontend fix wiring attached files through the expert side-panel chat is sound and well-covered; targeted drawer/ChatInput/useSendMessage test suites pass (99 tests) and prop/store contracts verify, with only a low-severity cross-surface recoveredDraft advisory.
ui-reviewer (hosted) ✅ PASS The drawer now forwards attached files/workspace files to sendWithAttachments so the expert side panel uploads and sends file_ids; logic is sound and the new plus existing copilot integration suites pass (184 tests) with no regressions.

@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 👍🏼 Mergeable in AutoGPT development kanban Oct 16, 2026
@Abhi1992002

Copy link
Copy Markdown
Member Author

Evidence

Verdict: PASS at 2080f3787 (round 5). This replaces the earlier evidence taken at b9cf15078. Since then the branch merged dev, which changed the shared composer, and added the duplicate-send fix and the Stop fix, so every row was proven again on the running app (Docker deps, native backend, next dev). Synthetic users and data only, reduced motion on, 1440×1000 and 390×844. No model key was available, so a scripted provider answered the turns. There are no "before" shots because there was no dev URL to capture from.

Criterion Result 1440 390
Proof 1: the bubble with the file shows on the first frame after Send in a new thread (50 ms / 52 ms after the click), while session create and upload are each held back 1.5 s PASS New thread, right after Send New thread, right after Send, 390
Proof 1: the image uploads, then /stream carries file_ids (create → upload ?session_id= → /stream) PASS New thread, sent New thread, sent, 390
Proof 2: a workspace PDF picked in an existing thread goes out with file_ids PASS Workspace file, existing thread Workspace file, existing thread, 390
Proof 3: a file can be attached while the expert replies (Queue message next to Stop) PASS Attach during a reply Attach during a reply, 390
Proof 3: the follow-up is held under the reply, with no /messages/pending call PASS Held follow-up Held follow-up, 390
Proof 3: it goes out as the next turn with file_ids PASS Follow-up sent Follow-up sent, 390
Proof 4: a file sent during a new expert's kickoff reply is held PASS Held behind kickoff Held behind kickoff, 390
Proof 4: it goes out after the kickoff with file_ids PASS Sent after kickoff Sent after kickoff, 390
Proof 8: /copilot new chat still shows the "Uploading 1 file…" bubble PASS /copilot new chat uploading /copilot new chat uploading, 390
Proof 8: /copilot existing chat still sends a file with file_ids PASS /copilot existing chat sent /copilot existing chat sent, 390
Extra (new in 2080f3787): Stop while a follow-up with a file is held. The bubble goes, the text is back in the composer with a "Message not sent" toast, and no /stream with files goes out PASS Stop returns the held message —
Extra: a file sent during a real dropped connection ("Reconnecting…") is held, then sent after the resumed reply ends PASS Held during reconnect —
Extra: closing the panel during an upload leaves the chat usable on reopen PASS Reopened after close —
Extra: a new task during an upload keeps the new draft and gives the old text back PASS Draft recovered —
The expert's reply describes the image / mentions the PDF UNPROVEN No model key here. The file reference reaches the persisted user message (name (type, size), file_id=…). —

Requests the browser recorded:

New thread (Proof 1):     POST /chat/sessions → POST /workspace/files/upload?session_id=<id> → POST /chat/sessions/<id>/stream  file_ids=[1 id]
Workspace file (Proof 2): POST /chat/sessions/<id>/stream  file_ids=[1 id]
Mid-reply (Proof 3):      pending POSTs=0; /stream file_ids=null (reply) → /stream file_ids=[1 id] (follow-up, ~18 s later)
Kickoff (Proof 4):        pending POSTs=0; /stream expert_kickoff=true → /stream file_ids=[1 id] (~20 s later)
Stop while held:          upload=1; no /stream with files after Stop; pending POSTs=0
/copilot new (Proof 8):   POST /chat/sessions → upload → /stream file_ids=[1 id]
/copilot existing:        upload → /stream file_ids=[1 id]

Also: 277/277 targeted tests across 15 files (drawer __tests__, ChatInput __tests__, useSendMessage, CopilotPage, helpers.test).

Notes: while a held follow-up waits for the reply to end, its bubble still says "Uploading 1 file…" after the upload has finished. PR 2 replaces that flag with a status for each file. The "Connection lost / Reconnecting…" toast in some shots comes from the stream's existing resume logic, which this PR does not change. The held files went out in every run.

@Abhi1992002

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

autogpt-pr-reviewer Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🤖 Review of 2080f37 posted: #15582 (review)

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Verdict: Approved — No findings require changes before approval; this review counts as an approval.

A disciplined frontend refactor that extracts shared upload-then-send/settle-gate logic and wires attachments through the expert side-panel chat with a flash-free held-message handoff. Every send path and the duplicate-suppression change were traced and are covered by strong, deterministic integration tests; no reachable defect found and CI is green on the reviewed head.

Risk level: low | Human review: not required | Duration: 480s | Reviewed: 2080f378

Findings: 🔴 0 blockers | 🟠 1 should fix | 🟡 2 nice to have | 🔵 0 nits

Optional advice — does not block approval

Follow-ups

  • 🟠 autogpt_platform/frontend/src/app/(platform)/team/components/ExpertChatDrawer/ExpertChatDrawer.tsx:190 Relax composer lock while a held follow-up waits on the reply — isUploadingFiles={!!pendingSend} disables the textarea and attach menu for the entire time a follow-up is held, including the full in-flight reply it waits on, not just the byte upload. Stop stays enabled so the user is not trapped.
    Suggestion: In the planned PR 2, gate the textarea lock on actual upload-in-progress rather than on any pendingSend.
Optional advice — does not block approval

🟡 Nice to Have

  • 🔵 autogpt_platform/frontend/src/app/(platform)/copilot/helpers/sendWithAttachments.ts:171 Collapse the stacked upload-failure toasts — A single failed local upload can surface up to three stacked destructive toasts (per-file, aggregate, and send-failure). Inherited from the existing /copilot path, not introduced here.
    Suggestion: Collapse the cascade into one message in a follow-up.
  • 🔵 autogpt_platform/frontend/src/app/(platform)/copilot/helpers.ts:318 Confirm duplicate-suppression asymmetry is intended — Resending the same caption with fewer/no attachments than the previous message is no longer suppressed. Defensible as a materially different message but a behavior change beyond the stated fix.
    Suggestion: Confirm the asymmetry is intended; no code change required.

GitHub CI on reviewed head: success

Validation and specialist details

Specialist Reports

Specialist Status Summary
security ✅ PASS Frontend chat attachment refactor with server-enforced file scope/limits and an explicit same-session guard against cross-thread send; no concrete security defects found.
architect ✅ PASS Well-structured refactor that extracts shared upload-then-send/settle-gate logic and wires it into the expert drawer with correct hold/release, kickoff, reconnect and Stop handling; no reachable defect found and coupling stays unidirectional.
performance ✅ PASS Frontend attachment-send extraction and drawer hold/settle logic are carefully guarded against the cross-thread and lifecycle races they introduce; no concrete performance or correctness defects found.
testing ✅ PASS The new MSW integration suite and targeted helper/ChatInput tests cover every fixed behavior with strong, deterministic, regression-catching assertions; no concrete test defect found.
quality ✅ PASS Well-structured refactor that correctly fixes attachment sending in the expert side panel with no concrete defects found; the shared /copilot path is behavior-preserving and copy rules are respected.
product ✅ PASS Attachment send paths in the expert side panel are correctly unified, the held-message handoff is flash-free, and error/Stop/reconnect edge cases are handled; no concrete blocker found.
discussion ✅ PASS CI is green on the current head and there are no open human-reviewer requests.
ui-reviewer (local) ✅ PASS Source review of the expert side-panel attachment send/hold logic found no reachable defect; every send path (new thread, existing thread, mid-reply, kickoff, stop, new-task, reconnect) and the duplicate-suppression change are coherent and match the added tests.
ui-reviewer (hosted) ✅ PASS Frontend-only fix that correctly uploads and sends side-panel chat attachments; targeted and full copilot test suites pass (3918+164) with no regression and no reachable defect found.

@Abhi1992002
Abhi1992002 added this pull request to the merge queue Oct 17, 2026
Merged via the queue into dev with commit 4d112c1 Oct 17, 2026
40 checks passed
@Abhi1992002
Abhi1992002 deleted the abhimanyuyadav/secrt-2956-expert-side-panel-chat-drops-attached-files-message-should-p1 branch October 17, 2026 03:57
@github-project-automation github-project-automation Bot moved this to Done in Frontend Oct 17, 2026
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: signed CLA signed by all contributors platform/frontend AutoGPT Platform - Front end size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant