fix(coding-agent): process BMP images from disk

closes #6047
This commit is contained in:
Armin Ronacher
2026-06-25 12:51:21 +02:00
parent 6ca7ba7c05
commit 4cc339f58d
9 changed files with 329 additions and 67 deletions
+10 -21
View File
@@ -8,7 +8,7 @@ import { type Static, Type } from "typebox";
import { getReadmePath } from "../../config.ts";
import { keyHint, keyText } from "../../modes/interactive/components/keybinding-hints.ts";
import { getLanguageFromPath, highlightCode, type Theme } from "../../modes/interactive/theme/theme.ts";
import { formatDimensionNote, resizeImage } from "../../utils/image-resize.ts";
import { processImage } from "../../utils/image-process.ts";
import { detectSupportedImageMimeTypeFromFile } from "../../utils/mime.ts";
import { formatPathRelativeToCwdOrAbsolute } from "../../utils/paths.ts";
import type { ToolDefinition, ToolRenderResultOptions } from "../extensions/types.ts";
@@ -209,7 +209,7 @@ export function createReadToolDefinition(
return {
name: "read",
label: "read",
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
promptSnippet: "Read file contents",
promptGuidelines: ["Use read to examine files instead of cat or sed."],
parameters: readSchema,
@@ -247,29 +247,18 @@ export function createReadToolDefinition(
if (mimeType) {
// Read image as binary.
const buffer = await ops.readFile(absolutePath);
if (autoResizeImages) {
// Resize image if needed before sending it back to the model.
const resized = await resizeImage(buffer, mimeType);
if (!resized) {
let textNote = `Read image file [${mimeType}]\n[Image omitted: could not be resized below the inline image size limit.]`;
if (nonVisionImageNote) textNote += `\n${nonVisionImageNote}`;
content = [{ type: "text", text: textNote }];
} else {
const dimensionNote = formatDimensionNote(resized);
let textNote = `Read image file [${resized.mimeType}]`;
if (dimensionNote) textNote += `\n${dimensionNote}`;
if (nonVisionImageNote) textNote += `\n${nonVisionImageNote}`;
content = [
{ type: "text", text: textNote },
{ type: "image", data: resized.data, mimeType: resized.mimeType },
];
}
const processed = await processImage(buffer, mimeType, { autoResizeImages });
if (!processed.ok) {
let textNote = `Read image file [${mimeType}]\n${processed.message}`;
if (nonVisionImageNote) textNote += `\n${nonVisionImageNote}`;
content = [{ type: "text", text: textNote }];
} else {
let textNote = `Read image file [${mimeType}]`;
let textNote = `Read image file [${processed.mimeType}]`;
if (processed.hints.length > 0) textNote += `\n${processed.hints.join("\n")}`;
if (nonVisionImageNote) textNote += `\n${nonVisionImageNote}`;
content = [
{ type: "text", text: textNote },
{ type: "image", data: buffer.toString("base64"), mimeType },
{ type: "image", data: processed.data, mimeType: processed.mimeType },
];
}
} else {