Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions decart/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class ImageToImageInput(DecartBaseModel):
max_length=1000,
)
data: FileInput
reference_image: Optional[FileInput] = None
seed: Optional[int] = None
resolution: Optional[str] = None
enhance_prompt: Optional[bool] = None
Expand Down
2 changes: 1 addition & 1 deletion decart/process/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ async def send_request(

for key, value in inputs.items():
if value is not None:
if key in ("data", "start", "end"):
if key in ("data", "start", "end", "reference_image"):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FILE_FIELDS missing reference_image causes inconsistent file handling

Medium Severity

FILE_FIELDS in client.py was not updated to include "reference_image", even though request.py now treats it as a file field. This causes reference_image to bypass the file-field handling path — it goes into non_file_inputs, passes through model_dump(), and is never placed in file_inputs. While this happens to work for bytes and str, it breaks the established pattern where file inputs get placeholder bytes for validation and their original values are preserved separately. For file-like objects (HasRead), model_dump() may not correctly round-trip the value, leading to a runtime failure.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2addaa9. Configure here.

content, content_type = await file_input_to_bytes(value, session)
form_data.add_field(key, content, content_type=content_type)
else:
Expand Down
32 changes: 32 additions & 0 deletions tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ async def test_process_image_to_image() -> None:
assert result == b"fake image data"


@pytest.mark.asyncio
async def test_process_image_to_image_with_reference_image() -> None:
"""Test image-to-image with optional reference_image."""
client = DecartClient(api_key="test-key")

with patch("aiohttp.ClientSession") as mock_session_cls:
mock_response = MagicMock()
mock_response.ok = True
mock_response.read = AsyncMock(return_value=b"fake image data")

mock_session = MagicMock()
mock_session.__aenter__ = AsyncMock(return_value=mock_session)
mock_session.__aexit__ = AsyncMock(return_value=None)
mock_session.post = MagicMock()
mock_session.post.return_value.__aenter__ = AsyncMock(return_value=mock_response)
mock_session.post.return_value.__aexit__ = AsyncMock(return_value=None)

mock_session_cls.return_value = mock_session

result = await client.process(
{
"model": models.image("lucy-pro-i2i"),
"prompt": "Add the object from the reference image",
"data": b"fake input image",
"reference_image": b"fake reference image",
"enhance_prompt": False,
}
)

assert result == b"fake image data"


@pytest.mark.asyncio
async def test_process_rejects_video_models() -> None:
"""Test that process() rejects video models with helpful error message."""
Expand Down
Loading