Expose MSR image analysis payload debug
This commit is contained in:
@@ -60,7 +60,22 @@ function resolveCandidateImageUrls(originNode) {
|
||||
async function imageInputToDataUrl(node, inputName) {
|
||||
const originNode = getOriginNodeForInput(node, inputName);
|
||||
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) {
|
||||
try {
|
||||
@@ -72,17 +87,44 @@ async function imageInputToDataUrl(node, inputName) {
|
||||
if (!blob.type.startsWith("image/")) {
|
||||
throw new Error(`Unexpected blob type: ${blob.type || "unknown"}`);
|
||||
}
|
||||
return await new Promise((resolve) => {
|
||||
const dataUrl = await new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(reader.result);
|
||||
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) {
|
||||
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) {
|
||||
@@ -330,11 +372,13 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
||||
node.setDirtyCanvas?.(true, true);
|
||||
|
||||
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 = (
|
||||
await Promise.all([
|
||||
imageInputToDataUrl(node, "image_1"),
|
||||
imageInputToDataUrl(node, "image_2"),
|
||||
])
|
||||
imageResults.map((result) => result?.dataUrl || null)
|
||||
).filter(Boolean);
|
||||
|
||||
if (!images.length) {
|
||||
@@ -348,10 +392,15 @@ async function analyzeCharacterNode(node, buttonWidget) {
|
||||
base_url: baseUrlWidget?.value || "",
|
||||
model: modelWidget?.value || "",
|
||||
image_b64: images,
|
||||
image_debug: imageDebug,
|
||||
}),
|
||||
});
|
||||
const result = await response.json();
|
||||
if (result.status !== "success") {
|
||||
console.warn("[MSRCharacter] analyze debug", {
|
||||
sentImages: imageDebug,
|
||||
response: result,
|
||||
});
|
||||
throw new Error(result.message || "Unknown analysis error");
|
||||
}
|
||||
|
||||
|
||||
@@ -549,10 +549,11 @@ def _resolve_provider(data):
|
||||
async def analyze_character_endpoint(request):
|
||||
try:
|
||||
import aiohttp
|
||||
data = await request.json()
|
||||
image_b64 = data.get("image_b64", "")
|
||||
char_index = int(data.get("char_index", 0))
|
||||
provider, base_url, model_name = _resolve_provider(data)
|
||||
data = await request.json()
|
||||
image_b64 = data.get("image_b64", "")
|
||||
image_debug = data.get("image_debug") or []
|
||||
char_index = int(data.get("char_index", 0))
|
||||
provider, base_url, model_name = _resolve_provider(data)
|
||||
|
||||
if provider == "off":
|
||||
return web.json_response({"status": "error", "message": "Analyze is set to Off / Manual."})
|
||||
@@ -639,6 +640,8 @@ async def analyze_character_endpoint(request):
|
||||
"status": "error",
|
||||
"message": "Ollama returned only a truncated analysis response.",
|
||||
"debug_candidates": debug_candidates,
|
||||
"image_debug": image_debug,
|
||||
"image_lengths": [len(b64) for b64 in cleaned_b64_list],
|
||||
"description": generated_text,
|
||||
})
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user