Skip to content

Commit 4d767cf

Browse files
authored
Merge pull request #497 from Mng-dev-ai/fix/skip-attachment-notes-for-native-types
Skip redundant attachment notes for natively supported file types
2 parents c4b0b10 + 4dd0e39 commit 4d767cf

1 file changed

Lines changed: 35 additions & 27 deletions

File tree

backend/app/services/acp/session.py

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@
3939
# default 64 KB stream buffer limit.
4040
STDIO_BUFFER_LIMIT = 100 * 1024 * 1024
4141

42+
IMAGE_MIME_BY_EXT: dict[str, str] = {
43+
".png": "image/png",
44+
".jpg": "image/jpeg",
45+
".jpeg": "image/jpeg",
46+
".gif": "image/gif",
47+
".webp": "image/webp",
48+
}
49+
50+
NON_IMAGE_MIME: dict[str, str] = {
51+
"pdf": "application/pdf",
52+
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
53+
}
54+
55+
EMPTY_FROZENSET: frozenset[str] = frozenset()
56+
57+
# File types each agent can consume natively in the ACP prompt —
58+
# no sandbox-path note needed for these since the content is inline.
59+
NATIVE_FILE_TYPES: dict[AgentKind, frozenset[str]] = {
60+
AgentKind.CLAUDE: frozenset({"image", "pdf"}),
61+
AgentKind.CODEX: frozenset({"image"}),
62+
}
63+
4264

4365
@dataclass
4466
class AcpSessionConfig:
@@ -102,7 +124,7 @@ async def send_prompt(
102124
TextContentBlock(type="text", text=content),
103125
]
104126
if attachments:
105-
attachment_note = self._build_attachment_note(attachments)
127+
attachment_note = self._build_attachment_note(attachments, agent_kind)
106128
if attachment_note:
107129
prompt_blocks.append(
108130
TextContentBlock(type="text", text=attachment_note)
@@ -121,23 +143,17 @@ async def send_prompt(
121143
finally:
122144
self._handler.finish(prompt_completed=prompt_completed)
123145

124-
IMAGE_MIME_BY_EXT: dict[str, str] = {
125-
".png": "image/png",
126-
".jpg": "image/jpeg",
127-
".jpeg": "image/jpeg",
128-
".gif": "image/gif",
129-
".webp": "image/webp",
130-
}
131-
132-
NON_IMAGE_MIME: dict[str, str] = {
133-
"pdf": "application/pdf",
134-
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
135-
}
136-
137146
@staticmethod
138-
def _build_attachment_note(attachments: list[dict[str, Any]]) -> str:
147+
def _build_attachment_note(
148+
attachments: list[dict[str, Any]],
149+
agent_kind: AgentKind,
150+
) -> str:
151+
native_types = NATIVE_FILE_TYPES.get(agent_kind, EMPTY_FROZENSET)
139152
lines: list[str] = []
140153
for att in attachments:
154+
file_type = att.get("file_type", "")
155+
if file_type in native_types:
156+
continue
141157
file_path = att.get("file_path")
142158
if not isinstance(file_path, str) or not file_path:
143159
continue
@@ -170,14 +186,8 @@ def _build_attachment_blocks(
170186
if not file_path:
171187
continue
172188
file_type = att.get("file_type", "")
173-
# Native ACP attachment support differs by agent: Claude can consume
174-
# images and PDFs in the prompt, while Codex only handles images.
175-
# Other uploaded files still exist in the sandbox for tool-based reads.
176-
if file_type == "image":
177-
pass
178-
elif file_type == "pdf" and agent_kind == AgentKind.CLAUDE:
179-
pass
180-
else:
189+
# Only include file types this agent can consume natively in the prompt.
190+
if file_type not in NATIVE_FILE_TYPES.get(agent_kind, EMPTY_FROZENSET):
181191
continue
182192
full_path = storage_path / file_path
183193
try:
@@ -190,7 +200,7 @@ def _build_attachment_blocks(
190200

191201
if file_type == "image":
192202
ext = Path(filename).suffix.lower()
193-
mime = AcpSession.IMAGE_MIME_BY_EXT.get(ext, "image/png")
203+
mime = IMAGE_MIME_BY_EXT.get(ext, "image/png")
194204
blocks.append(
195205
ImageContentBlock(
196206
type="image",
@@ -199,9 +209,7 @@ def _build_attachment_blocks(
199209
)
200210
)
201211
else:
202-
mime = AcpSession.NON_IMAGE_MIME.get(
203-
file_type, "application/octet-stream"
204-
)
212+
mime = NON_IMAGE_MIME.get(file_type, "application/octet-stream")
205213
blocks.append(
206214
EmbeddedResourceContentBlock(
207215
type="resource",

0 commit comments

Comments
 (0)