Skip to content

feat(backend/copilot): attach uploaded images and PDFs as multimodal vision blocks - #12273

Merged
majdyz merged 17 commits into
devfrom
otto/open-3022-featbackendcopilot-attach-uploaded-images-and-pdfs-as
Mar 5, 2026
Merged

feat(backend/copilot): attach uploaded images and PDFs as multimodal vision blocks#12273
majdyz merged 17 commits into
devfrom
otto/open-3022-featbackendcopilot-attach-uploaded-images-and-pdfs-as

Conversation

@Otto-AGPT

@Otto-AGPT Otto-AGPT commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Requested by @majdyz

When users upload images or PDFs to CoPilot, the AI couldn't see the content because the CLI's Zod validator rejects large base64 in MCP tool results and even small images were misidentified (the CLI silently drops or corrupts image content blocks in tool results).

Approach

Embed uploaded images directly as vision content blocks in the user message via client._transport.write(). The SDK's client.query() only accepts string content, so we bypass it for multimodal messages — writing a properly structured user message with [...image_blocks, {"type": "text", "text": query}] directly to the transport. This ensures the CLI binary receives images as native vision blocks, matching how the Anthropic API handles multimodal input.

For binary files accessed via workspace tools at runtime, we save them to the SDK's ephemeral working directory (sdk_cwd) and return a file path for the CLI's built-in Read tool to handle natively.

Changes

Vision content blocks for attached files — service.py

  • _prepare_file_attachments downloads workspace files before the query, converts images to base64 vision blocks ({"type": "image", "source": {"type": "base64", ...}})
  • When vision blocks are present, writes multimodal user message directly to client._transport instead of using client.query()
  • Non-image files (PDFs, text) are saved to sdk_cwd with a hint to use the Read tool

File-path based access for workspace tools — workspace_files.py

  • read_workspace_file saves binary files to sdk_cwd instead of returning base64, returning a path for the Read tool

SDK context for ephemeral directory — tool_adapter.py

  • Added sdk_cwd context variable so workspace tools can access the ephemeral directory
  • Removed inline base64 multimodal block machinery (_extract_content_block, _strip_base64_from_text, _BLOCK_BUILDERS, etc.)

Frontend — rendering improvements

  • MessageAttachments.tsx — uses OutputRenderers system (globalRegistry + OutputItem) for image/video preview rendering instead of custom components
  • GenericTool.tsx — uses OutputRenderers system for inline image rendering of base64 content
  • routes.py — returns 409 for duplicate workspace filenames

Tests

  • tool_adapter_test.py — removed multimodal extraction/stripping tests, added get_sdk_cwd tests
  • service_test.py — rewritten for _prepare_file_attachments with file-on-disk assertions

Closes OPEN-3022

…content blocks

- Bump MAX_INLINE_SIZE_BYTES from 32KB to 20MB (Claude vision limit)
  so read_workspace_file returns base64 for images and documents
- Replace _extract_image_block with generic _extract_content_block
  supporting images (png/jpeg/gif/webp/svg) and documents (pdf)
- Add _MULTIMODAL_TYPES mapping for easy extension of supported types
- Add _INLINEABLE_MIME_TYPES superset in workspace_files.py
- Thread file_ids from processor to SDK service layer
- Add file attachment hint so Claude reads uploaded files via tool
- Accept file_ids in non-SDK service for backward compatibility

Closes OPEN-3022
@Otto-AGPT
Otto-AGPT requested a review from a team as a code owner March 3, 2026 22:50
@Otto-AGPT
Otto-AGPT requested review from 0ubbe and Bentlybro and removed request for a team March 3, 2026 22:50
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Mar 3, 2026
@github-actions github-actions Bot added platform/backend AutoGPT Platform - Back end size/l labels Mar 3, 2026
@coderabbitai

coderabbitai Bot commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Propagates file_ids through CoPilot execution and streaming, updates streaming signatures to accept file_ids, adds SDK-side Claude file-attachment hinting, and expands multimodal inline extraction (images + PDFs) with adjusted size limits and truncation-preservation for non-text blocks.

Changes

Cohort / File(s) Summary
Execution & Streaming
autogpt_platform/backend/backend/copilot/executor/processor.py, autogpt_platform/backend/backend/copilot/service.py, autogpt_platform/backend/backend/copilot/sdk/service.py
Processor now passes file_ids into _execute_async and into the stream_fn; stream_chat_completion and stream_chat_completion_sdk signatures accept file_ids (SDK-only warning added in service).
SDK Claude helper
autogpt_platform/backend/backend/copilot/sdk/service.py
Added _build_file_attachment_hint(file_ids) and updated streaming path to append the hint to queries and stop-hook; logs now include attached file counts.
Multimodal extraction & truncation
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py, autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
Replaced image-only extractor with _extract_content_block supporting image/document blocks, added _strip_base64_from_text, changed truncation to preserve non-text blocks, and added multimodal-focused tests.
Workspace file handling
autogpt_platform/backend/backend/copilot/tools/workspace_files.py
Expanded _INLINEABLE_MIME_TYPES to include PDFs, split inline size constants into MAX_INLINE_TEXT_SIZE_BYTES and MAX_INLINE_MULTIMODAL_SIZE_BYTES, and adjusted inline decision logic and mime normalization.
Tests
autogpt_platform/backend/backend/copilot/sdk/service_test.py, autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
Added unit tests for _build_file_attachment_hint and extensive multimodal extraction/truncation tests covering images and PDFs.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Processor
    participant Executor
    participant StreamFn as StreamFn (stream_chat_completion_sdk)
    participant Claude
    participant WorkspaceTool as Workspace File Tool

    Client->>Processor: request (may include file_ids)
    Processor->>Executor: _execute_async(..., file_ids=entry.file_ids)
    Executor->>StreamFn: stream_fn(..., file_ids=entry.file_ids)
    StreamFn->>StreamFn: _build_file_attachment_hint(file_ids)
    StreamFn->>Claude: send query + file hint
    Claude->>WorkspaceTool: read_workspace_file(file_id)
    WorkspaceTool->>WorkspaceTool: _extract_content_block(multimodal)
    WorkspaceTool-->>Claude: return file content (image/document or text)
    Claude-->>Client: streamed response (with file context)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested reviewers

  • kcze
  • ntindle
  • Pwuts

Poem

🐰 I nibble bytes and tuck in files tight,
PDFs and images snug for Claude to sight,
I pass my hints along the streaming lane,
So processors, executors, and Claude can gain —
Hop—attachments delivered just right! 📎

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.02% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: enabling multimodal file viewing (images and PDFs) through the SDK using file paths instead of inline base64.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation, approach, and specific changes made across multiple files to support multimodal file attachments.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch otto/open-3022-featbackendcopilot-attach-uploaded-images-and-pdfs-as

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 and usage tips.

@github-actions

github-actions Bot commented Mar 3, 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: 1 conflict(s), 0 medium risk, 5 low risk (out of 6 PRs with file overlap)


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

Comment thread autogpt_platform/backend/backend/copilot/tools/workspace_files.py Outdated
- Remove noqa comment from non-SDK service file_ids param
- Replace if/elif branching with _BLOCK_BUILDERS dispatch table
- Add bmp, tiff, svg to supported image types
- Add Callable import for builder type hints
- Text files already supported via existing is_text path
- Videos not supported (Claude API has no native video content blocks)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
autogpt_platform/backend/backend/copilot/sdk/service.py (1)

574-578: Docstring overstates what this function does with attachments.

Current text says files are fetched/base64-attached here, but this code path only appends a hint and relies on tool calls (read_workspace_file) for retrieval. Tightening this wording will reduce future confusion.

✏️ Suggested docstring wording
-        file_ids: Optional workspace file IDs attached to the user's message.
-            When provided, files are fetched, base64-encoded, and attached as
-            multimodal content blocks (images, PDFs, etc.) to the query.
+        file_ids: Optional workspace file IDs attached to the user's message.
+            When provided, a hint is appended so Claude can fetch each file
+            via `read_workspace_file` and process supported multimodal content.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/service.py` around lines 574 -
578, The docstring incorrectly claims that provided file_ids are fetched and
base64-attached; instead update the docstring for the function that accepts the
file_ids parameter to state that when file_ids are provided the function only
appends hints/metadata about attachments to the query and relies on tool calls
(e.g., read_workspace_file) or downstream handlers to actually fetch and decode
file contents. Mention file_ids and read_workspace_file by name so readers know
where responsibility for retrieval lives.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 268-273: The code currently duplicates multimodal base64 payloads
by leaving them in the plain text block and also emitting them as a separate
content_block (see _extract_content_block, content_block, content_blocks, and
the variable text), which causes large attachments to be truncated/corrupted;
update the logic so that when _extract_content_block(text) returns a
content_block you remove/strip the embedded content_base64 (or other multimodal
marker) from the text before appending it to content_blocks (and do the same fix
for the other occurrence around the 295-299 logic), ensuring only the separate
image/document content_block carries the base64 payload while the text block
contains the descriptive metadata only.

In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py`:
- Line 441: Replace the single MAX_INLINE_SIZE_BYTES constant with two
caps—e.g., MAX_INLINE_SIZE_BYTES_MULTIMODAL = 20 * 1024 * 1024 and a much
smaller MAX_INLINE_SIZE_BYTES_TEXT (e.g., 100 * 1024) —and update all
inline-decision logic that currently references MAX_INLINE_SIZE_BYTES to choose
the right cap based on file type (multimodal like images/PDFs vs text/plain).
Locate uses of MAX_INLINE_SIZE_BYTES in the inline check code paths (the
function(s) that decide whether to base64-inline a file) and switch them to use
the multimodal constant when mime/type indicates images/PDFs and the text
constant for general text files so large text files are not inlined.
- Around line 216-220: The _INLINEABLE_MIME_TYPES set is missing
"image/svg+xml", so SVG files aren't returned inline as base64; update the
definition of _INLINEABLE_MIME_TYPES (which currently unions _IMAGE_MIME_TYPES
with {"application/pdf"}) to include "image/svg+xml" (or add it into
_IMAGE_MIME_TYPES if more appropriate) so SVG uploads are treated as inlineable
multimodal content; ensure the symbol name _INLINEABLE_MIME_TYPES is modified
and that any tests or callers expecting inline SVGs now receive base64 data.

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/service.py`:
- Around line 574-578: The docstring incorrectly claims that provided file_ids
are fetched and base64-attached; instead update the docstring for the function
that accepts the file_ids parameter to state that when file_ids are provided the
function only appends hints/metadata about attachments to the query and relies
on tool calls (e.g., read_workspace_file) or downstream handlers to actually
fetch and decode file contents. Mention file_ids and read_workspace_file by name
so readers know where responsibility for retrieval lives.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b504cf9 and f7874ee.

📒 Files selected for processing (5)
  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: types
  • GitHub Check: Seer Code Review
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.13)
  • GitHub Check: Analyze (python)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
🧠 Learnings (1)
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/executor/processor.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
🧬 Code graph analysis (1)
autogpt_platform/backend/backend/copilot/sdk/service.py (2)
autogpt_platform/backend/backend/copilot/response_model.py (1)
  • StreamBaseResponse (48-56)
autogpt_platform/backend/backend/util/logging.py (1)
  • info (41-43)
🔇 Additional comments (3)
autogpt_platform/backend/backend/copilot/service.py (1)

326-326: Compatibility signature update is solid.

Accepting file_ids here prevents stream function signature drift when the processor routes to the non-SDK path.

autogpt_platform/backend/backend/copilot/executor/processor.py (1)

232-232: file_ids propagation is wired correctly here.

This is the right place to thread attachment context into both streaming backends.

autogpt_platform/backend/backend/copilot/sdk/service.py (1)

852-857: Attachment hint injection + telemetry update look good.

Appending the per-turn file hint and logging attached_files gives clear traceability for attachment-aware prompts.

Also applies to: 859-865

Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/workspace_files.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/tools/workspace_files.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

263-273: ⚠️ Potential issue | 🟠 Major

Avoid duplicating content_base64 in both text and multimodal blocks.

At Line 267–273, the raw JSON text block still carries content_base64 while a multimodal block is also appended. This duplicates large payloads and can trigger truncation/corruption under response-size limits.

🔧 Suggested fix
-    content_blocks: list[dict[str, str]] = [{"type": "text", "text": text}]
+    text_block_text = text
+    content_blocks: list[dict[str, Any]] = []
@@
     content_block = _extract_content_block(text)
     if content_block:
+        try:
+            payload = json.loads(text)
+            if isinstance(payload, dict) and "content_base64" in payload:
+                payload["content_base64"] = "[omitted: delivered via multimodal block]"
+                text_block_text = json.dumps(payload)
+        except (json.JSONDecodeError, TypeError):
+            pass
         content_blocks.append(content_block)
+    content_blocks.insert(0, {"type": "text", "text": text_block_text})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py` around lines
263 - 273, The text block currently includes the full raw JSON (variable text)
even when _extract_content_block returns a multimodal content_block, causing
duplicated content_base64; change the logic in the area that builds
content_blocks (using the text variable and _extract_content_block) to strip or
remove any content_base64 fields from the JSON/text used for the "text" content
block when a multimodal content_block is present (e.g., parse result.output into
a dict, delete content_base64 entries or replace them with a placeholder, then
json.dumps that cleaned payload into text) so only the multimodal content_block
carries the large base64 payload.
autogpt_platform/backend/backend/copilot/tools/workspace_files.py (1)

444-445: ⚠️ Potential issue | 🟠 Major

Split text vs multimodal inline size caps.

Line 444 and Line 549 currently allow text files up to 20MB to be inlined, which can bloat MCP payloads and context unnecessarily. Keep the large cap for multimodal only, and retain a small text cap.

🔧 Suggested fix
 class ReadWorkspaceFileTool(BaseTool):
     """Tool for reading file content from workspace."""
 
-    MAX_INLINE_SIZE_BYTES = 20 * 1024 * 1024  # 20MB (Claude vision/document limit)
+    MAX_INLINE_TEXT_SIZE_BYTES = 32 * 1024
+    MAX_INLINE_MULTIMODAL_SIZE_BYTES = 20 * 1024 * 1024  # 20MB
     PREVIEW_SIZE = 500
@@
-            is_small = file_info.size_bytes <= self.MAX_INLINE_SIZE_BYTES
             is_text = _is_text_mime(file_info.mime_type)
             is_inlineable = file_info.mime_type in _INLINEABLE_MIME_TYPES
+            is_small_text = is_text and (
+                file_info.size_bytes <= self.MAX_INLINE_TEXT_SIZE_BYTES
+            )
+            is_small_multimodal = is_inlineable and (
+                file_info.size_bytes <= self.MAX_INLINE_MULTIMODAL_SIZE_BYTES
+            )
@@
-            if is_small and (is_text or is_inlineable) and not force_download_url:
+            if (is_small_text or is_small_multimodal) and not force_download_url:

Also applies to: 544-549

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py` around
lines 444 - 445, Replace the single MAX_INLINE_SIZE_BYTES with two caps: a small
TEXT_MAX_INLINE_SIZE_BYTES (e.g., 500KB) and a large
MULTIMODAL_MAX_INLINE_SIZE_BYTES (20MB) and leave PREVIEW_SIZE as-is; then
update all places that compare a file's size against MAX_INLINE_SIZE_BYTES (look
for functions/methods like can_inline_file, _should_inline, should_inline, or
any size checks in workspace_files.py that use MAX_INLINE_SIZE_BYTES) to choose
the appropriate cap based on the file type (use existing file metadata/mimetype
or file.is_multimodal/is_text helpers) so text files use
TEXT_MAX_INLINE_SIZE_BYTES and images/docs/multimodal files use
MULTIMODAL_MAX_INLINE_SIZE_BYTES.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 263-273: The text block currently includes the full raw JSON
(variable text) even when _extract_content_block returns a multimodal
content_block, causing duplicated content_base64; change the logic in the area
that builds content_blocks (using the text variable and _extract_content_block)
to strip or remove any content_base64 fields from the JSON/text used for the
"text" content block when a multimodal content_block is present (e.g., parse
result.output into a dict, delete content_base64 entries or replace them with a
placeholder, then json.dumps that cleaned payload into text) so only the
multimodal content_block carries the large base64 payload.

In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py`:
- Around line 444-445: Replace the single MAX_INLINE_SIZE_BYTES with two caps: a
small TEXT_MAX_INLINE_SIZE_BYTES (e.g., 500KB) and a large
MULTIMODAL_MAX_INLINE_SIZE_BYTES (20MB) and leave PREVIEW_SIZE as-is; then
update all places that compare a file's size against MAX_INLINE_SIZE_BYTES (look
for functions/methods like can_inline_file, _should_inline, should_inline, or
any size checks in workspace_files.py that use MAX_INLINE_SIZE_BYTES) to choose
the appropriate cap based on the file type (use existing file metadata/mimetype
or file.is_multimodal/is_text helpers) so text files use
TEXT_MAX_INLINE_SIZE_BYTES and images/docs/multimodal files use
MULTIMODAL_MAX_INLINE_SIZE_BYTES.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f7874ee and 5cdb297.

📒 Files selected for processing (3)
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • autogpt_platform/backend/backend/copilot/service.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: types
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: Seer Code Review
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🧠 Learnings (2)
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🔇 Additional comments (2)
autogpt_platform/backend/backend/copilot/tools/workspace_files.py (1)

216-223: Good MIME coverage for inline multimodal types.

Line 216–223 aligns the inlineable set with the new multimodal scope (SVG/BMP/TIFF/PDF), which keeps read behavior consistent with downstream block extraction.

autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

281-305: Nice extensible multimodal dispatch design.

The MIME mapping + builder table keeps Line 281–357 easy to extend and avoids branching growth.

Also applies to: 307-357

@majdyz
majdyz self-requested a review March 4, 2026 05:36
- Remove unsupported image types (svg, bmp, tiff) from multimodal types
  (Claude only supports png, jpeg, gif, webp)
- Split inline size thresholds: 32KB for text, 20MB for images/PDFs
  (prevents bloating context with large text files)
- Flatten nested if for file_ids hint (walrus operator)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
autogpt_platform/backend/backend/copilot/tools/workspace_files.py (1)

542-567: ⚠️ Potential issue | 🟠 Major

Normalize MIME type before inline checks and response emission.

file_info.mime_type is used raw here, but sdk/tool_adapter.py does exact MIME matching in _MULTIMODAL_TYPES. If MIME includes parameters, multimodal extraction can silently fail even when content is inlined.

🔧 Proposed fix
-            is_text = _is_text_mime(file_info.mime_type)
-            is_inlineable = file_info.mime_type in _INLINEABLE_MIME_TYPES
+            normalized_mime = (file_info.mime_type or "").split(";", 1)[0].strip().lower()
+            is_text = _is_text_mime(normalized_mime)
+            is_inlineable = normalized_mime in _INLINEABLE_MIME_TYPES
@@
                 return WorkspaceFileContentResponse(
                     file_id=file_info.id,
                     name=file_info.name,
                     path=file_info.path,
-                    mime_type=file_info.mime_type,
+                    mime_type=normalized_mime,
                     content_base64=base64.b64encode(content).decode("utf-8"),
                     message=msg,
                     session_id=session_id,
                 )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py` around
lines 542 - 567, Normalize file_info.mime_type by stripping any parameters
before doing inline checks and returning it in the response: compute a local
mime_type = file_info.mime_type.split(';', 1)[0].strip() (or equivalent) and use
mime_type when calling _is_text_mime, checking membership in
_INLINEABLE_MIME_TYPES, computing is_inlineable/is_text, and when populating
WorkspaceFileContentResponse.mime_type; leave manager.read_file_by_id, size
checks (MAX_INLINE_MULTIMODAL_SIZE_BYTES / MAX_INLINE_TEXT_SIZE_BYTES) and
content encoding unchanged. This ensures exact MIME matching (matching
_MULTIMODAL_TYPES behavior) and that the emitted response contains the
normalized MIME string.
♻️ Duplicate comments (1)
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

269-273: ⚠️ Potential issue | 🟠 Major

Remove duplicated multimodal base64 from the text block.

At Line 269-273, multimodal payload is still sent twice: once inside the JSON text block and again as the multimodal block. This reintroduces truncation/corruption risk for large attachments in the SDK path.

Proposed fix
-    text = (
-        result.output if isinstance(result.output, str) else json.dumps(result.output)
-    )
-
-    content_blocks: list[dict[str, str]] = [{"type": "text", "text": text}]
+    text = (
+        result.output if isinstance(result.output, str) else json.dumps(result.output)
+    )
+    text_block_text = text
+    content_blocks: list[dict[str, Any]] = []

     # If the tool result contains inline multimodal data, add a content block
     # so Claude can "see" images or read documents (e.g. read_workspace_file).
     content_block = _extract_content_block(text)
     if content_block:
+        try:
+            payload = json.loads(text)
+            if isinstance(payload, dict) and "content_base64" in payload:
+                payload["content_base64"] = "[omitted: delivered via multimodal block]"
+                text_block_text = json.dumps(payload)
+        except (json.JSONDecodeError, TypeError):
+            pass
         content_blocks.append(content_block)
+    content_blocks.insert(0, {"type": "text", "text": text_block_text})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py` around lines
269 - 273, The text block currently contains inline multimodal base64 and is
also extracted into a separate multimodal content block (via
_extract_content_block), causing duplicated payloads; modify the flow so that
after calling _extract_content_block(text) you remove or replace the embedded
multimodal data from the original text before appending it (or change
_extract_content_block to return both the extracted content block and a
cleaned_text); ensure only the cleaned text is added to the message payload
while the multimodal data lives solely in content_blocks (refer to the
_extract_content_block function name, the text variable, and the content_blocks
list for where to make the change).
🧹 Nitpick comments (2)
autogpt_platform/backend/backend/copilot/sdk/service.py (1)

568-577: Minor docstring clarification suggested.

The docstring states files are "fetched, base64-encoded, and attached as multimodal content blocks" in this function, but the actual implementation appends a text hint instructing Claude to use read_workspace_file. The fetching and encoding occur when Claude invokes that tool. Consider clarifying:

📝 Suggested docstring update
     Args:
         file_ids: Optional workspace file IDs attached to the user's message.
-            When provided, files are fetched, base64-encoded, and attached as
-            multimodal content blocks (images, PDFs, etc.) to the query.
+            When provided, a hint is appended to the query instructing Claude
+            to use read_workspace_file to access the content (which returns
+            base64-encoded multimodal content blocks for images, PDFs, etc.).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/service.py` around lines 568 -
577, The docstring for the async generator function (returning
AsyncGenerator[StreamBaseResponse, None]) incorrectly says workspace files are
"fetched, base64-encoded, and attached"; update the docstring to state that when
file_ids are provided the function appends text hints instructing the Claude
agent to call the read_workspace_file tool, and that actual fetching/encoding is
performed by the agent/tool at runtime rather than by this function (reference
the function signature and the file_ids parameter to locate the docstring to
edit).
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

336-347: Harden parsed payload type checks before size validation.

data.get(...) may return non-string values. Adding strict str checks avoids malformed block construction and makes this parser safer.

Proposed hardening
-    mime_type: str = data.get("mime_type", "")
-    base64_content: str = data.get("content_base64", "")
-    if not mime_type or not base64_content:
+    mime_type = data.get("mime_type", "")
+    base64_content = data.get("content_base64", "")
+    if (
+        not isinstance(mime_type, str)
+        or not isinstance(base64_content, str)
+        or not mime_type
+        or not base64_content
+    ):
         return None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py` around lines
336 - 347, The parser currently assumes data.get("mime_type") and
data.get("content_base64") are strings before using them and before checking
size; add explicit type checks/casts so non-string values don't slip through. In
the block that reads mime_type and base64_content, ensure you validate types
(e.g., isinstance(..., str)) or coerce safely to str only after confirming
non-None, return None if either is not a string, then continue to lookup
_MULTIMODAL_TYPES and compare len(base64_content) against max_b64 (from entry)
knowing base64_content is a real string; reference mime_type, base64_content,
_MULTIMODAL_TYPES, and the block returning None on size check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@autogpt_platform/backend/backend/copilot/tools/workspace_files.py`:
- Around line 542-567: Normalize file_info.mime_type by stripping any parameters
before doing inline checks and returning it in the response: compute a local
mime_type = file_info.mime_type.split(';', 1)[0].strip() (or equivalent) and use
mime_type when calling _is_text_mime, checking membership in
_INLINEABLE_MIME_TYPES, computing is_inlineable/is_text, and when populating
WorkspaceFileContentResponse.mime_type; leave manager.read_file_by_id, size
checks (MAX_INLINE_MULTIMODAL_SIZE_BYTES / MAX_INLINE_TEXT_SIZE_BYTES) and
content encoding unchanged. This ensures exact MIME matching (matching
_MULTIMODAL_TYPES behavior) and that the emitted response contains the
normalized MIME string.

---

Duplicate comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 269-273: The text block currently contains inline multimodal
base64 and is also extracted into a separate multimodal content block (via
_extract_content_block), causing duplicated payloads; modify the flow so that
after calling _extract_content_block(text) you remove or replace the embedded
multimodal data from the original text before appending it (or change
_extract_content_block to return both the extracted content block and a
cleaned_text); ensure only the cleaned text is added to the message payload
while the multimodal data lives solely in content_blocks (refer to the
_extract_content_block function name, the text variable, and the content_blocks
list for where to make the change).

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/service.py`:
- Around line 568-577: The docstring for the async generator function (returning
AsyncGenerator[StreamBaseResponse, None]) incorrectly says workspace files are
"fetched, base64-encoded, and attached"; update the docstring to state that when
file_ids are provided the function appends text hints instructing the Claude
agent to call the read_workspace_file tool, and that actual fetching/encoding is
performed by the agent/tool at runtime rather than by this function (reference
the function signature and the file_ids parameter to locate the docstring to
edit).

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 336-347: The parser currently assumes data.get("mime_type") and
data.get("content_base64") are strings before using them and before checking
size; add explicit type checks/casts so non-string values don't slip through. In
the block that reads mime_type and base64_content, ensure you validate types
(e.g., isinstance(..., str)) or coerce safely to str only after confirming
non-None, return None if either is not a string, then continue to lookup
_MULTIMODAL_TYPES and compare len(base64_content) against max_b64 (from entry)
knowing base64_content is a real string; reference mime_type, base64_content,
_MULTIMODAL_TYPES, and the block returning None on size check.

ℹ️ Review info
Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a5a4517-b192-468f-81ad-d901e499f321

📥 Commits

Reviewing files that changed from the base of the PR and between 5cdb297 and da8802f.

📒 Files selected for processing (3)
  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: types
  • GitHub Check: Seer Code Review
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: Analyze (python)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (4)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🧠 Learnings (2)
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🔇 Additional comments (7)
autogpt_platform/backend/backend/copilot/sdk/service.py (3)

539-556: LGTM!

The helper function is well-designed with clear docstring explaining the purpose. The early return for empty file_ids is appropriately defensive, and the message format gives Claude clear instructions on how to access the attached files.


851-854: LGTM!

Clean use of the walrus operator to conditionally build and append the file hint. The double newline separator provides clear visual separation between the user's query and the file attachment instructions.


856-863: LGTM!

Good observability enhancement. The attached_files count in the log message will help with debugging file attachment flows. The null-safe ternary correctly handles both None and empty list cases.

autogpt_platform/backend/backend/copilot/tools/workspace_files.py (2)

216-220: Good multimodal inline type expansion.

Adding application/pdf to _INLINEABLE_MIME_TYPES keeps this tool aligned with multimodal handling goals and the current supported set in the adapter.


441-442: Nice threshold split for text vs multimodal content.

Keeping text at 32KB while allowing 20MB for multimodal files addresses context bloat without blocking image/PDF attachment flows.

autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (2)

14-14: Nice import modernization.

Using Callable from collections.abc is the correct modern typing import for Python 3.11.


291-315: MIME-to-block dispatch structure looks good.

The _MULTIMODAL_TYPES + _BLOCK_BUILDERS split is clean and extensible, and the supported MIME set aligns with the inline workspace types.

…ents

- Protect multimodal content blocks from truncation corruption
- Strip duplicated base64 from text blocks when multimodal block exists
- Normalize MIME type before inline checks (strip parameters like charset)
- Harden type checks in _extract_content_block for non-string values
- Fix docstring accuracy (hint-based, not direct attachment)
- Warn when file_ids passed to non-SDK path
- Add comprehensive tests for multimodal extraction, truncation, and helpers
@majdyz majdyz changed the title feat(backend/copilot): Attach uploaded images and PDFs as multimodal content blocks feat(backend/copilot): attach uploaded images and PDFs as multimodal content blocks Mar 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
autogpt_platform/backend/backend/copilot/sdk/service.py (1)

539-556: Consider bounding attachment hint size to avoid prompt bloat.

If many files are attached, this helper can add a large token payload. A small cap (count + ID length) keeps prompts predictable.

🔧 Proposed hardening
 def _build_file_attachment_hint(file_ids: list[str]) -> str:
@@
-    ids_list = ", ".join(f"`{fid}`" for fid in file_ids)
-    noun = "file" if len(file_ids) == 1 else "files"
+    MAX_IDS_IN_HINT = 20
+    clipped = [str(fid)[:64] for fid in file_ids[:MAX_IDS_IN_HINT]]
+    ids_list = ", ".join(f"`{fid}`" for fid in clipped)
+    noun = "file" if len(file_ids) == 1 else "files"
+    suffix = (
+        f" (+{len(file_ids) - MAX_IDS_IN_HINT} more not listed)"
+        if len(file_ids) > MAX_IDS_IN_HINT
+        else ""
+    )
     return (
         f"[The user attached {len(file_ids)} {noun} to this message. "
-        f"File IDs: {ids_list}. "
+        f"File IDs: {ids_list}{suffix}. "
         f"Use the read_workspace_file tool with the file_id to view "
         f"the content of each attached file.]"
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/service.py` around lines 539 -
556, The helper _build_file_attachment_hint can produce very large hints when
file_ids is long; modify it to enforce a hard cap by limiting the number of IDs
included and total ID characters: compute a max_files_to_show (e.g. 10) and/or
max_total_id_chars (e.g. 256), build ids_list from the first N file_ids
truncating individual IDs with ellipses if they exceed per-id limit, and if any
IDs were omitted include a short suffix like "`... and X more files`" or "`(Y
more IDs omitted)`"; update references to file_ids, ids_list, noun and the
returned string accordingly so the hint stays bounded and you still report the
total count via len(file_ids).
autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py (1)

157-239: Add a regression test for MIME values with parameters.

Given the extraction path depends on MIME matching, add a case like application/pdf; charset=binary to lock behavior and prevent future regressions.

✅ Suggested test addition
 class TestExtractContentBlock:
@@
     def test_pdf_returns_document_block(self):
@@
         assert block["source"]["data"] == "JVBERi0="
+
+    def test_pdf_mime_with_parameters_is_supported(self):
+        payload = json.dumps(
+            {
+                "content_base64": "JVBERi0=",
+                "mime_type": "application/pdf; charset=binary",
+            }
+        )
+        block = _extract_content_block(payload)
+        assert block is not None
+        assert block["type"] == "document"
+        assert block["source"]["media_type"] == "application/pdf"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py` around
lines 157 - 239, Add a regression test inside TestExtractContentBlock that
verifies MIME values with parameters are accepted: create a JSON payload with
"content_base64": "JVBERi0=" and "mime_type": "application/pdf; charset=binary",
call _extract_content_block(payload), assert the result is not None, assert
block["type"] == "document" and that block["source"]["media_type"] starts with
"application/pdf" (or equals "application/pdf" if implementation strips
parameters). Place this new test near test_pdf_returns_document_block so future
changes to _extract_content_block will be covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py`:
- Around line 340-349: The MIME type string from data should be normalized
before lookup so parameterized values like "application/pdf; charset=binary"
match keys in _MULTIMODAL_TYPES: trim whitespace, lowercase, and split on ';'
taking the media type only (update the local mime_type variable used in the
function in tool_adapter.py), then use that normalized value for the lookup at
entry = _MULTIMODAL_TYPES.get(mime_type) and the second lookup around line 359;
ensure you apply the same normalization wherever mime_type is read from data
(e.g., content_base64 handling) to prevent missed multimodal extraction.
- Around line 295-296: The base64 ceiling constants are too low: update
_IMAGE_MAX_B64 and _DOCUMENT_MAX_B64 to account for base64 expansion (4/3) of
binary sizes so a 20 MiB image and 32 MiB document do not get dropped; set
_IMAGE_MAX_B64 to at least 27,962,028 (ceil(20*1024*1024*4/3)) and
_DOCUMENT_MAX_B64 to at least 44,739,243 (ceil(32*1024*1024*4/3)), and adjust
any checks that compare base64 length (the code paths that drop multimodal block
assets) to use these revised constants (_IMAGE_MAX_B64, _DOCUMENT_MAX_B64).

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/service.py`:
- Around line 539-556: The helper _build_file_attachment_hint can produce very
large hints when file_ids is long; modify it to enforce a hard cap by limiting
the number of IDs included and total ID characters: compute a max_files_to_show
(e.g. 10) and/or max_total_id_chars (e.g. 256), build ids_list from the first N
file_ids truncating individual IDs with ellipses if they exceed per-id limit,
and if any IDs were omitted include a short suffix like "`... and X more files`"
or "`(Y more IDs omitted)`"; update references to file_ids, ids_list, noun and
the returned string accordingly so the hint stays bounded and you still report
the total count via len(file_ids).

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py`:
- Around line 157-239: Add a regression test inside TestExtractContentBlock that
verifies MIME values with parameters are accepted: create a JSON payload with
"content_base64": "JVBERi0=" and "mime_type": "application/pdf; charset=binary",
call _extract_content_block(payload), assert the result is not None, assert
block["type"] == "document" and that block["source"]["media_type"] starts with
"application/pdf" (or equals "application/pdf" if implementation strips
parameters). Place this new test near test_pdf_returns_document_block so future
changes to _extract_content_block will be covered.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2629883c-2462-4edc-9349-086c5170af02

📥 Commits

Reviewing files that changed from the base of the PR and between da8802f and d8e9dd7.

📒 Files selected for processing (6)
  • autogpt_platform/backend/backend/copilot/sdk/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Seer Code Review
  • GitHub Check: types
  • GitHub Check: Analyze (python)
  • GitHub Check: Check PR Status
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
🧰 Additional context used
📓 Path-based instructions (6)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
🧠 Learnings (5)
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/tools/workspace_files.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/service.py
  • autogpt_platform/backend/backend/copilot/sdk/service_test.py
  • autogpt_platform/backend/backend/copilot/sdk/service.py
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/backend/backend/blocks/**/*.py : Write tests alongside block implementation when adding new blocks in backend

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-02-04T16:50:20.508Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-02-04T16:50:20.508Z
Learning: Applies to autogpt_platform/backend/backend/blocks/*.py : Never hardcode workspace checks when using `store_media_file()` - let `for_block_output` handle context adaptation automatically

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🔇 Additional comments (5)
autogpt_platform/backend/backend/copilot/service.py (1)

326-374: Nice compatibility guard for file_ids in non-SDK flow.

The signature expansion plus explicit warning path on Line 326 and Lines 368-374 is clean and prevents silent misuse.

autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (1)

267-277: Great handling of multimodal truncation safety and base64 de-duplication.

This keeps non-text blocks intact while truncating only text, and avoids corrupting multimodal payloads.

Also applies to: 517-543

autogpt_platform/backend/backend/copilot/tools/workspace_files.py (1)

216-220: Looks good: MIME normalization + split inline thresholds are correctly implemented.

The text vs multimodal size split and normalized MIME checks are consistent with the intended behavior and avoid the previous large-text inlining problem.

Based on learnings: "In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path."

Also applies to: 441-557

autogpt_platform/backend/backend/copilot/sdk/service_test.py (1)

6-26: Good helper coverage for attachment hint generation.

The empty/singular/plural assertions cover the core contract of _build_file_attachment_hint well.

autogpt_platform/backend/backend/copilot/sdk/service.py (1)

568-568: file_ids propagation and query-level hint injection look correct.

This wires attachment context into the SDK path without changing the stream contract.

Also applies to: 852-864

Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py Outdated
majdyz added 2 commits March 4, 2026 15:11
- Increase _IMAGE_MAX_B64 from 27M to 28M so 20 MiB images are not dropped
  (ceil(20*1024*1024 * 4/3) ≈ 27,962,028)
- Normalize MIME type in _extract_content_block (strip parameters like
  "application/pdf; charset=binary") to match workspace_files.py
- Add tests for MIME normalization in multimodal extraction
Extract the content-block splitting logic into a reusable
_split_content_blocks() function used by both _text_from_mcp_result
and the _truncating wrapper.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py (1)

199-207: Add an explicit SVG exclusion regression test

Please add a dedicated image/svg+xml case in the unsupported MIME tests so this behavior is locked and doesn’t regress.

Based on learnings: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding image/svg+xml from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py` around
lines 199 - 207, Add a regression test case asserting that payloads with
mime_type "image/svg+xml" are treated as unsupported: update the test function
(or add a new test) to call _extract_content_block with a JSON payload where
"mime_type": "image/svg+xml" and assert the result is None. Also ensure the
implementation in tool_adapter.py excludes "image/svg+xml" from
INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES so SVGs are not classified as
vision/inlineable image types (adjust those constants or their construction
accordingly).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py`:
- Around line 223-230: The test builds an oversized base64 string using the
wrong constant (_MCP_MAX_CHARS) so it may not exceed the image ceiling checked
by _extract_content_block; change the test to construct huge using
_IMAGE_MAX_B64 (e.g. huge = "A" * (_IMAGE_MAX_B64 + 1_000_000)) so the payload's
content_base64 truly exceeds the image limit and the assert
_extract_content_block(payload) is None reliably validates the oversize-image
branch.

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py`:
- Around line 199-207: Add a regression test case asserting that payloads with
mime_type "image/svg+xml" are treated as unsupported: update the test function
(or add a new test) to call _extract_content_block with a JSON payload where
"mime_type": "image/svg+xml" and assert the result is None. Also ensure the
implementation in tool_adapter.py excludes "image/svg+xml" from
INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES so SVGs are not classified as
vision/inlineable image types (adjust those constants or their construction
accordingly).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e1dffd99-c5dc-4532-bd03-d631bcbdcb3a

📥 Commits

Reviewing files that changed from the base of the PR and between d8e9dd7 and 438036a.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Seer Code Review
  • GitHub Check: types
  • GitHub Check: test (3.12)
  • GitHub Check: Analyze (python)
  • GitHub Check: test (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (6)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
🧠 Learnings (3)
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py
  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
📚 Learning: 2026-02-27T10:45:55.700Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:55.700Z
Learning: As of PR `#12213`, MCP tool response types (MCPToolsDiscoveredResponse, MCPToolOutputResponse) are defined in openapi.json and frontend code in autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx uses the generated types from `@/app/api/__generated__/`. Other tools like RunBlock still use inline TypeScript interfaces (e.g., BlockDetailsResponse) for SSE stream payloads that are not included in openapi.json schemas. The pattern is tool-specific: use generated types when available in openapi.json, use inline types only when the payload schema is truly SSE-stream-only and not exposed via OpenAPI.

Applied to files:

  • autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py
🔇 Additional comments (2)
autogpt_platform/backend/backend/copilot/sdk/tool_adapter.py (2)

267-277: Good multimodal/text dedup handling

This correctly avoids duplicating content_base64 in both text and multimodal blocks, which keeps payloads smaller and cleaner for downstream handling.


519-545: Truncation hardening looks solid

Separating non-text blocks before truncate() and reattaching them intact is the right protection against base64/data corruption.

Comment thread autogpt_platform/backend/backend/copilot/sdk/tool_adapter_test.py Outdated
@github-actions github-actions Bot mentioned this pull request Mar 4, 2026
8 tasks
Dev refactored stream_chat_completion into baseline/service.py and
changed SDK function signature to **_kwargs. Kept file_ids as explicit
param in SDK path, added _on_stop and CompactionTracker from dev's
restructured code, and re-applied vision content block logic.
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label Mar 4, 2026
@github-actions

github-actions Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly.

Comment thread autogpt_platform/backend/backend/copilot/executor/processor.py
Comment thread autogpt_platform/backend/backend/copilot/sdk/service.py
ntindle
ntindle previously requested changes Mar 5, 2026
Comment thread autogpt_platform/backend/backend/copilot/sdk/service.py Outdated
@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 🚧 Needs work in AutoGPT development kanban Mar 5, 2026
@github-actions

github-actions Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

@github-actions github-actions Bot added the conflicts Automatically applied to PRs with merge conflicts label Mar 5, 2026
…eModel

- Resolve workspace_files.py conflict: take dev's ranged read and
  image inlining, restore _IMAGE_MIME_TYPES, use MAX_INLINE_SIZE_BYTES
- Convert PreparedAttachments from @DataClass to Pydantic BaseModel
  (per reviewer feedback)
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label Mar 5, 2026
@github-actions

github-actions Bot commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly.

@majdyz
majdyz added this pull request to the merge queue Mar 5, 2026
Merged via the queue into dev with commit 3d0ede9 Mar 5, 2026
29 checks passed
@majdyz
majdyz deleted the otto/open-3022-featbackendcopilot-attach-uploaded-images-and-pdfs-as branch March 5, 2026 09:26
@github-project-automation github-project-automation Bot moved this from 🚧 Needs work to ✅ Done in AutoGPT development kanban Mar 5, 2026
@github-project-automation github-project-automation Bot moved this to Done in Frontend Mar 5, 2026
@sentry

sentry Bot commented Mar 8, 2026

Copy link
Copy Markdown

Issues attributed to commits in this pull request

This pull request was merged and Sentry observed the following issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform/backend AutoGPT Platform - Back end platform/frontend AutoGPT Platform - Front end size/l size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants