Expose MSR image analysis payload debug

This commit is contained in:
OpenClaw Agent
2026-07-10 11:40:10 +00:00
parent 2da1de2f6d
commit f372a2ed69
2 changed files with 63 additions and 11 deletions

View File

@@ -60,7 +60,22 @@ function resolveCandidateImageUrls(originNode) {
async function imageInputToDataUrl(node, inputName) { async function imageInputToDataUrl(node, inputName) {
const originNode = getOriginNodeForInput(node, inputName); const originNode = getOriginNodeForInput(node, inputName);
const candidateUrls = resolveCandidateImageUrls(originNode); const candidateUrls = resolveCandidateImageUrls(originNode);
if (!candidateUrls.length) return null; if (!candidateUrls.length) {
return {
dataUrl: null,
debug: {
inputName,
originNodeId: originNode?.id ?? null,
originNodeType: originNode?.type ?? null,
candidateUrls: [],
selectedUrl: null,
mimeType: null,
blobBytes: 0,
dataUrlLength: 0,
error: "No candidate image URLs found",
},
};
}
for (const imageUrl of candidateUrls) { for (const imageUrl of candidateUrls) {
try { try {
@@ -72,17 +87,44 @@ async function imageInputToDataUrl(node, inputName) {
if (!blob.type.startsWith("image/")) { if (!blob.type.startsWith("image/")) {
throw new Error(`Unexpected blob type: ${blob.type || "unknown"}`); throw new Error(`Unexpected blob type: ${blob.type || "unknown"}`);
} }
return await new Promise((resolve) => { const dataUrl = await new Promise((resolve) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onloadend = () => resolve(reader.result); reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(blob); reader.readAsDataURL(blob);
}); });
return {
dataUrl,
debug: {
inputName,
originNodeId: originNode?.id ?? null,
originNodeType: originNode?.type ?? null,
candidateUrls,
selectedUrl: imageUrl,
mimeType: blob.type || null,
blobBytes: blob.size || 0,
dataUrlLength: typeof dataUrl === "string" ? dataUrl.length : 0,
error: null,
},
};
} catch (error) { } catch (error) {
console.warn("[MSRCharacter] Failed candidate image source", imageUrl, error); console.warn("[MSRCharacter] Failed candidate image source", imageUrl, error);
} }
} }
return null; return {
dataUrl: null,
debug: {
inputName,
originNodeId: originNode?.id ?? null,
originNodeType: originNode?.type ?? null,
candidateUrls,
selectedUrl: null,
mimeType: null,
blobBytes: 0,
dataUrlLength: 0,
error: "All candidate image URLs failed",
},
};
} }
function setWidgetValue(node, widget, value) { function setWidgetValue(node, widget, value) {
@@ -330,11 +372,13 @@ async function analyzeCharacterNode(node, buttonWidget) {
node.setDirtyCanvas?.(true, true); node.setDirtyCanvas?.(true, true);
try { try {
const imageResults = await Promise.all([
imageInputToDataUrl(node, "image_1"),
imageInputToDataUrl(node, "image_2"),
]);
const imageDebug = imageResults.map((result) => result?.debug || null).filter(Boolean);
const images = ( const images = (
await Promise.all([ imageResults.map((result) => result?.dataUrl || null)
imageInputToDataUrl(node, "image_1"),
imageInputToDataUrl(node, "image_2"),
])
).filter(Boolean); ).filter(Boolean);
if (!images.length) { if (!images.length) {
@@ -348,10 +392,15 @@ async function analyzeCharacterNode(node, buttonWidget) {
base_url: baseUrlWidget?.value || "", base_url: baseUrlWidget?.value || "",
model: modelWidget?.value || "", model: modelWidget?.value || "",
image_b64: images, image_b64: images,
image_debug: imageDebug,
}), }),
}); });
const result = await response.json(); const result = await response.json();
if (result.status !== "success") { if (result.status !== "success") {
console.warn("[MSRCharacter] analyze debug", {
sentImages: imageDebug,
response: result,
});
throw new Error(result.message || "Unknown analysis error"); throw new Error(result.message || "Unknown analysis error");
} }

View File

@@ -551,6 +551,7 @@ async def analyze_character_endpoint(request):
import aiohttp import aiohttp
data = await request.json() data = await request.json()
image_b64 = data.get("image_b64", "") image_b64 = data.get("image_b64", "")
image_debug = data.get("image_debug") or []
char_index = int(data.get("char_index", 0)) char_index = int(data.get("char_index", 0))
provider, base_url, model_name = _resolve_provider(data) provider, base_url, model_name = _resolve_provider(data)
@@ -639,6 +640,8 @@ async def analyze_character_endpoint(request):
"status": "error", "status": "error",
"message": "Ollama returned only a truncated analysis response.", "message": "Ollama returned only a truncated analysis response.",
"debug_candidates": debug_candidates, "debug_candidates": debug_candidates,
"image_debug": image_debug,
"image_lengths": [len(b64) for b64 in cleaned_b64_list],
"description": generated_text, "description": generated_text,
}) })
else: else: