fix: Handle case-insensitive format parameter and add jpeg alias

The image tool now properly handles:
- Case-insensitive format values (e.g., "PNG", "Png", "png" all work)
- "jpeg" as an alias for "jpg" format
- Invalid format values gracefully fall back to "png"

This is implemented through Zod schema preprocessing that normalizes
the format parameter before it reaches the Swift CLI, which only
accepts lowercase "png" and "jpg".

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Peter Steinberger 2025-06-08 06:49:49 +01:00
parent 0301df2608
commit e74796f7e3
3 changed files with 20 additions and 14 deletions

View file

@ -32,13 +32,9 @@ export async function imageToolHandler(
const isScreenCapture = !input.app_target || input.app_target.startsWith("screen:");
let formatWarning: string | undefined;
// Validate format - if invalid, fall back to PNG
const validFormats = ["png", "jpg", "data"];
// Format validation is now handled by the schema preprocessor
// The format here is already normalized (lowercase, jpeg->jpg mapping applied)
let effectiveFormat = input.format;
if (effectiveFormat && !validFormats.includes(effectiveFormat)) {
logger.warn(`Invalid format '${effectiveFormat}' provided, falling back to PNG`);
effectiveFormat = "png";
}
// Auto-fallback to PNG for screen captures with format 'data'
if (isScreenCapture && effectiveFormat === "data") {

View file

@ -141,13 +141,24 @@ export const imageToolSchema = z.object({
if (val === null || val === undefined || val === "") {
return undefined;
}
// If the value is not a valid format, fall back to 'png'
const validFormats = ["png", "jpg", "data"];
return validFormats.includes(val as string) ? val : "png";
// Convert to lowercase for case-insensitive matching
const lowerVal = String(val).toLowerCase();
// Map common aliases
const formatMap: Record<string, string> = {
"jpeg": "jpg",
"png": "png",
"jpg": "jpg",
"data": "data"
};
// Return mapped value or fall back to 'png'
return formatMap[lowerVal] || "png";
},
z.enum(["png", "jpg", "data"]).optional().describe(
"Optional. Output format.\n" +
"Can be `'png'`, `'jpg'`, or `'data'`.\n" +
"Can be `'png'`, `'jpg'`, `'jpeg'` (alias for jpg), or `'data'`.\n" +
"Format is case-insensitive (e.g., 'PNG', 'Png', 'png' are all valid).\n" +
"If `'png'` or `'jpg'`, saves the image to the specified `path`.\n" +
"If `'data'`, returns Base64 encoded PNG data inline in the response.\n" +
"If `path` is also provided when `format` is `'data'`, the image is saved (as PNG) AND Base64 data is returned.\n" +

View file

@ -53,10 +53,9 @@ export function buildSwiftCliArgs(
const args = ["image"];
// Use provided format or derive from input
// If format is invalid (not png, jpg, or data), fall back to png
const validFormats = ["png", "jpg", "data"];
const inputFormat = input.format && validFormats.includes(input.format) ? input.format : "png";
const actualFormat = swiftFormat || (inputFormat === "data" ? "png" : inputFormat) || "png";
// Format validation is already handled by the schema preprocessor
const inputFormat = input.format || "png";
const actualFormat = swiftFormat || (inputFormat === "data" ? "png" : inputFormat);
// Create a logger if not provided (for backward compatibility)
const log = logger || {