# Copyright (c) 2025 Patrick Motsch # All rights reserved. """Shared helpers for AI workflow actions.""" import json from typing import Any def is_image_action_document_list(val: Any) -> bool: """True if ``val`` is a non-empty list of ActionDocument-shaped dicts (mimeType image/*).""" if not isinstance(val, list) or not val: return False for item in val: if not isinstance(item, dict): return False mime = str(item.get("mimeType") or "").strip().lower() if not mime.startswith("image/"): return False return True def serialize_context(val: Any) -> str: """Convert any context value to a readable string for use in AI prompts. - None / empty string → "" - empty dict (no keys) → "" (avoids literal "{}" in file.create / prompts) - str → as-is - dict / list → pretty-printed JSON - anything else → str() """ if val is None or val == "" or val == []: return "" if isinstance(val, dict) and len(val) == 0: return "" if isinstance(val, str): return val.strip() try: return json.dumps(val, ensure_ascii=False, indent=2) except Exception: return str(val) def applyCommonAiParams(parameters: dict, request) -> None: """Apply common AI parameters (requireNeutralization, allowedModels) from node to request.""" requireNeutralization = parameters.get("requireNeutralization") if requireNeutralization is not None: request.requireNeutralization = bool(requireNeutralization) allowedModels = parameters.get("allowedModels") if allowedModels and isinstance(allowedModels, list): if not request.options: from modules.datamodels.datamodelAi import AiCallOptions request.options = AiCallOptions() request.options.allowedModels = allowedModels