mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
fix: 修复截图 MIME 类型硬编码导致 API 拒绝的问题
macOS screencapture 输出 PNG,但代码硬编码 mimeType 为 image/jpeg, 导致 API 报错 "specified using image/jpeg but appears to be image/png"。 改为通过 magic bytes 检测实际图片格式。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,19 @@
|
|||||||
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
||||||
import { randomUUID } from "node:crypto";
|
import { randomUUID } from "node:crypto";
|
||||||
|
|
||||||
|
/** Detect actual image MIME type from base64 data using magic bytes. */
|
||||||
|
function detectMimeFromBase64(b64: string): string {
|
||||||
|
// First byte is enough to distinguish PNG (0x89) from JPEG (0xFF)
|
||||||
|
const c = b64.charCodeAt(0);
|
||||||
|
if (c === 0x89) return "image/png";
|
||||||
|
if (c === 0xFF) return "image/jpeg";
|
||||||
|
// RIFF = WebP
|
||||||
|
if (c === 0x52) return "image/webp";
|
||||||
|
// GIF
|
||||||
|
if (c === 0x47) return "image/gif";
|
||||||
|
return "image/png";
|
||||||
|
}
|
||||||
|
|
||||||
import { getDefaultTierForApp, getDeniedCategoryForApp, isPolicyDenied } from "./deniedApps.js";
|
import { getDefaultTierForApp, getDeniedCategoryForApp, isPolicyDenied } from "./deniedApps.js";
|
||||||
import type {
|
import type {
|
||||||
ComputerExecutor,
|
ComputerExecutor,
|
||||||
@@ -2162,7 +2175,7 @@ async function handleScreenshot(
|
|||||||
{
|
{
|
||||||
type: "image",
|
type: "image",
|
||||||
data: shot.base64,
|
data: shot.base64,
|
||||||
mimeType: "image/jpeg",
|
mimeType: detectMimeFromBase64(shot.base64),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
screenshot: shot,
|
screenshot: shot,
|
||||||
@@ -2231,7 +2244,7 @@ async function handleScreenshot(
|
|||||||
{
|
{
|
||||||
type: "image",
|
type: "image",
|
||||||
data: shot.base64,
|
data: shot.base64,
|
||||||
mimeType: "image/jpeg",
|
mimeType: detectMimeFromBase64(shot.base64),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// Piggybacked for serverDef.ts to stash on InternalServerContext.
|
// Piggybacked for serverDef.ts to stash on InternalServerContext.
|
||||||
@@ -2310,7 +2323,7 @@ async function handleZoom(
|
|||||||
|
|
||||||
// Return the image. NO `.screenshot` piggyback — this is the invariant.
|
// Return the image. NO `.screenshot` piggyback — this is the invariant.
|
||||||
return {
|
return {
|
||||||
content: [{ type: "image", data: zoomed.base64, mimeType: "image/jpeg" }],
|
content: [{ type: "image", data: zoomed.base64, mimeType: detectMimeFromBase64(zoomed.base64) }],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { getSessionId } from '../../bootstrap/state.js'
|
|||||||
import { ComputerUseApproval } from '../../components/permissions/ComputerUseApproval/ComputerUseApproval.js'
|
import { ComputerUseApproval } from '../../components/permissions/ComputerUseApproval/ComputerUseApproval.js'
|
||||||
import type { Tool, ToolUseContext } from '../../Tool.js'
|
import type { Tool, ToolUseContext } from '../../Tool.js'
|
||||||
import { logForDebugging } from '../debug.js'
|
import { logForDebugging } from '../debug.js'
|
||||||
|
import { detectImageFormatFromBase64 } from '../imageResizer.js'
|
||||||
import {
|
import {
|
||||||
checkComputerUseLock,
|
checkComputerUseLock,
|
||||||
tryAcquireComputerUseLock,
|
tryAcquireComputerUseLock,
|
||||||
@@ -330,7 +331,7 @@ export function getComputerUseMCPToolOverrides(
|
|||||||
type: 'image' as const,
|
type: 'image' as const,
|
||||||
source: {
|
source: {
|
||||||
type: 'base64' as const,
|
type: 'base64' as const,
|
||||||
media_type: item.mimeType ?? 'image/jpeg',
|
media_type: item.mimeType ?? detectImageFormatFromBase64(item.data),
|
||||||
data: item.data,
|
data: item.data,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user