Summary
ds4-server rejects a well-formed OpenAI Chat Completions request that includes an inline PNG/JPEG data URI on a role=tool (or role=function) message. The HTTP status is 400 with "invalid JSON request", even though the body is valid JSON.
This breaks OpenAI-compatible coding agents that attach tool-result screenshots as image_url content parts on the tool message, which is the normal Chat Completions shape. A role=user data URI of the same image is accepted.
Repro
POST /v1/chat/completions with messages:
role=user text
role=assistant with a tool_calls entry
role=tool whose content is an array of {type:text} plus {type:image_url, image_url:{url:"data:image/png;base64,..."}} (or jpeg)
Observed: 400 {"error":{"message":"invalid JSON request","type":"invalid_request_error"}} before vision encode.
The same data URI on role=user returns 200.
Cause
In parse_messages / parse_anthropic_messages, any message with images whose role is not exactly "user" fails parse. That path always reports "invalid JSON request".
The user-only restriction matches the GLM note that image tokens should land on a user-shaped turn, and ds4-agent already remaps view_image onto a user turn. The server still needs to accept the OpenAI wire format: DeepSeek already wraps tool results in a user turn (<|User|><tool_result>…).
File paths and remote URLs should stay rejected.
Suggested fix
Allow inline images on user, tool, and function. Keep rejecting assistant/system images, paths, and https URLs. Prefer a specific error string for remaining schema failures instead of "invalid JSON request" (optional, not required for the role check).
I can send a PR with a parser unit test for the tool-role shape.
Summary
ds4-serverrejects a well-formed OpenAI Chat Completions request that includes an inline PNG/JPEG data URI on arole=tool(orrole=function) message. The HTTP status is 400 with"invalid JSON request", even though the body is valid JSON.This breaks OpenAI-compatible coding agents that attach tool-result screenshots as
image_urlcontent parts on the tool message, which is the normal Chat Completions shape. Arole=userdata URI of the same image is accepted.Repro
POST /v1/chat/completionswith messages:role=usertextrole=assistantwith atool_callsentryrole=toolwhosecontentis an array of{type:text}plus{type:image_url, image_url:{url:"data:image/png;base64,..."}}(or jpeg)Observed:
400 {"error":{"message":"invalid JSON request","type":"invalid_request_error"}}before vision encode.The same data URI on
role=userreturns 200.Cause
In
parse_messages/parse_anthropic_messages, any message with images whose role is not exactly"user"fails parse. That path always reports"invalid JSON request".The user-only restriction matches the GLM note that image tokens should land on a user-shaped turn, and
ds4-agentalready remapsview_imageonto a user turn. The server still needs to accept the OpenAI wire format: DeepSeek already wraps tool results in a user turn (<|User|><tool_result>…).File paths and remote URLs should stay rejected.
Suggested fix
Allow inline images on
user,tool, andfunction. Keep rejecting assistant/system images, paths, andhttpsURLs. Prefer a specific error string for remaining schema failures instead of"invalid JSON request"(optional, not required for the role check).I can send a PR with a parser unit test for the tool-role shape.