dsh-image-base64
A DeepSeek Harness plugin that fixes:
This turn failed 400 "'url' field must be a base64 encoded image."
INVALID_REQUEST
when a vision-capable model (e.g. meta/muse-glimmer) is served through an
OpenAI-compatible gateway that validates the image MIME type strictly, such
as LM Studio.
Why this happens
See deepseek-ai/deepseek-harness#4615 for the full discussion. The short version:
dsh-attachment-local's request-image quality ladder re-encodes an image asimage/webpwhenever the source has an alpha channel (JPEG has no alpha channel to fall back to). A pasted screenshot or a PNG with transparency very often has one.- LM Studio's OpenAI-compatible endpoint only accepts
image/png,image/jpeg, andimage/gifinside a base64data:URL. It rejectsimage/webp(and anything else) at the protocol layer with400, before the request reaches the model. dsh-llm-pi-aiforwards whatevermediaTypethe attachment store gives it straight into the request — there's no format negotiation between the two, so the mismatch reaches LM Studio unchanged.
What this plugin does
It wraps the attachment store's readImageRequest() (the call
dsh-llm-pi-ai makes to get the exact bytes/MIME type that go into the
request) and transcodes the result to image/png with sharp whenever its
media type isn't in an accepted list (image/png, image/jpeg, image/gif
by default). Everything already in an accepted format passes through
untouched — only the images that would otherwise be rejected pay the
transcode cost.
Install
From your DSH profile directory (or via dsh plugin --profile <name> add,
which forwards to pnpm inside the profile):
dsh plugin --profile <name> add /home/pakkapon/dsh-image-base64
Then list it in that profile's package.json under dsh.profile.bundles:
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-image-base64"
]
}
}
}
Restart the profile (or let it pick it up automatically if
patchReload: live is set) to load it.
Configuration
Accepted media types default to [image/png, image/jpeg, image/gif] (LM
Studio's whitelist). To widen or narrow that, target the plugin's id from
your own patch layer (profile cordis.patch.yml or $DSH_HOME/cordis.patch.yml):
- id: image-base64-compat
config:
acceptedMediaTypes: [image/png, image/jpeg, image/gif, image/webp]
Caveats
- This patches the attachment store's request-image projection only — it doesn't touch how images are stored, just what's sent on the wire for a model request.
- Transcoding to PNG is lossless for the pixels it's given, but a PNG
re-encode of a large photo is bigger than an equivalent JPEG/WebP. If your
gateway actually accepts WebP, add it to
acceptedMediaTypesinstead of relying on the default.
License
MIT
No comments yet. Be the first to write one.