fix: use detected media type for screenshots instead of hard-coded image/png

browser_screenshot declared every capture as image/png regardless of the
actual bytes. On Chromium/Edge builds where captureVisibleTab returns JPEG
bytes, the stored attachment reference recorded mediaType "image/png" against
JPEG bytes, so dsh-attachment-local's read-time metadata verification fails
with ATTACHMENT_CORRUPT ("Stored attachment metadata does not match its
reference"), surfacing as code UNKNOWN and triggering endless LLM retries.

- image.ts: sniff the capture's magic bytes (PNG/JPEG/WebP/GIF) and declare
  that real media type to attachments.saveImage, instead of always "image/png".
- tools.ts: assemble the tool result from ref.mediaType (the store's verified
  type) rather than re-declaring "image/png" as const, and relax the output
  schema's const to the accepted media-type enum.
- tests: add a regression case asserting JPEG capture bytes surface as
  image/jpeg.

Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
This commit is contained in:
cyhano
2026-08-24 15:31:34 +08:00
co-authored by DeepSeek Harness
parent 4b6cdde168
commit 60fbf30e24
3 changed files with 124 additions and 11 deletions
@@ -772,7 +772,11 @@ export function registerTools(deps: ToolDeps): () => void {
additionalProperties: false,
properties: {
attachmentId: { type: "string", required: true },
mediaType: { type: "string", required: true, const: "image/png" },
mediaType: {
type: "string",
required: true,
enum: ["image/png", "image/jpeg", "image/webp", "image/gif"],
},
bytes: { type: "integer", required: true },
width: { type: "integer", required: true },
height: { type: "integer", required: true },
@@ -842,7 +846,7 @@ export function registerTools(deps: ToolDeps): () => void {
? {
image: {
attachmentId: String(ref.attachmentId),
mediaType: "image/png" as const,
mediaType: ref.mediaType,
bytes: ref.bytes,
width: ref.width,
height: ref.height,