Add persistent any text preview node

This commit is contained in:
2026-06-26 09:32:11 +02:00
parent 49c6ee77a6
commit a3371afe0c
4 changed files with 159 additions and 0 deletions
+102
View File
@@ -50,6 +50,7 @@ ACCUMULATOR_PREVIEW_DELETE_ACTIONS = ["none", "delete_entry_id", "delete_index",
INDEX_SWITCH_MODES = ["pick_input", "route_output"]
INDEX_SWITCH_BASES = ["one_based", "zero_based"]
INDEX_SWITCH_MISSING_BEHAVIORS = ["fallback", "none", "clamp", "wrap"]
PREVIEW_TEXT_FORMATS = ["auto", "json", "repr", "str"]
_ACCUMULATOR_STORES: dict[str, list[dict[str, Any]]] = {}
@@ -248,6 +249,66 @@ def _attach_preview_images(entries: list[dict[str, Any]], images: list[dict[str,
entry["preview_image"] = image
def _jsonable_preview_value(value: Any, depth: int = 4, max_items: int = 80) -> Any:
if depth < 0:
return "..."
if value is None or isinstance(value, (str, int, float, bool)):
return value
if isinstance(value, dict):
items = list(value.items())
output = {
str(key): _jsonable_preview_value(item, depth - 1, max_items)
for key, item in items[:max_items]
}
if len(items) > max_items:
output["..."] = f"{len(items) - max_items} more"
return output
if isinstance(value, (list, tuple, set)):
items = list(value)
output = [_jsonable_preview_value(item, depth - 1, max_items) for item in items[:max_items]]
if len(items) > max_items:
output.append(f"... {len(items) - max_items} more")
return output
shape = getattr(value, "shape", None)
if shape is not None:
try:
return {
"type": type(value).__name__,
"shape": [int(part) for part in shape],
"dtype": str(getattr(value, "dtype", "")),
"device": str(getattr(value, "device", "")),
}
except Exception:
pass
return str(value)
def _truncate_preview_text(text: str, max_chars: int) -> str:
max_chars = max(0, int(max_chars or 0))
if max_chars <= 0 or len(text) <= max_chars:
return text
omitted = len(text) - max_chars
return f"{text[:max_chars]}\n... truncated {omitted} characters"
def _any_to_preview_text(value: Any, preview_format: str, max_chars: int) -> str:
preview_format = preview_format if preview_format in PREVIEW_TEXT_FORMATS else "auto"
if preview_format == "str":
text = str(value)
elif preview_format == "repr":
text = repr(value)
elif preview_format == "json":
text = json.dumps(_jsonable_preview_value(value), ensure_ascii=True, indent=2, sort_keys=True)
elif isinstance(value, str):
text = value
else:
try:
text = json.dumps(_jsonable_preview_value(value), ensure_ascii=True, indent=2, sort_keys=True)
except Exception:
text = str(value)
return _truncate_preview_text(text, max_chars)
def _accumulator_status(key: str, store: list[dict[str, Any]]) -> str:
images = [entry.get("image") for entry in store if entry.get("image") is not None]
shapes = []
@@ -1194,6 +1255,45 @@ class SxCPAccumulatorPreview:
}
class SxCPPreviewAnyAsText:
OUTPUT_NODE = True
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"preview_text": ("STRING", {"default": "", "multiline": True}),
"preview_format": (PREVIEW_TEXT_FORMATS, {"default": "auto"}),
"max_chars": ("INT", {"default": 20000, "min": 0, "max": 200000, "step": 1000}),
},
"optional": {
"value": (ANY_TYPE, {"forceInput": True}),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("text",)
FUNCTION = "preview"
CATEGORY = "prompt_builder/util"
@classmethod
def IS_CHANGED(cls, *args, **kwargs):
return random.random()
def preview(self, preview_text, preview_format, max_chars, **kwargs):
if "value" not in kwargs:
text = _truncate_preview_text(str(preview_text or ""), int(max_chars))
else:
value = kwargs.get("value")
text = _any_to_preview_text(value, str(preview_format or "auto"), int(max_chars))
return {
"ui": {
"preview_text": [text],
},
"result": (text,),
}
class SxCPForLoopEnd:
@classmethod
def INPUT_TYPES(cls):
@@ -1320,6 +1420,7 @@ LOOP_NODE_CLASS_MAPPINGS = {
"SxCPIndexSwitch": SxCPIndexSwitch,
"SxCPAccumulator": SxCPAccumulator,
"SxCPAccumulatorPreview": SxCPAccumulatorPreview,
"SxCPPreviewAnyAsText": SxCPPreviewAnyAsText,
"SxCPLoopIntAdd": SxCPLoopIntAdd,
"SxCPLoopLessThan": SxCPLoopLessThan,
"SxCPLoopLessThanOrEqual": SxCPLoopLessThanOrEqual,
@@ -1334,6 +1435,7 @@ LOOP_NODE_DISPLAY_NAME_MAPPINGS = {
"SxCPIndexSwitch": "SxCP Index Switch",
"SxCPAccumulator": "SxCP Accumulator",
"SxCPAccumulatorPreview": "SxCP Accumulator Preview",
"SxCPPreviewAnyAsText": "SxCP Preview Any As Text",
"SxCPLoopIntAdd": "SxCP Loop Int Add",
"SxCPLoopLessThan": "SxCP Loop Less Than",
"SxCPLoopLessThanOrEqual": "SxCP Loop Less Than Or Equal",