diff --git a/comfy_api/latest/_io.py b/comfy_api/latest/_io.py index 189d7d9bc..a88db1e83 100644 --- a/comfy_api/latest/_io.py +++ b/comfy_api/latest/_io.py @@ -1347,6 +1347,7 @@ class NodeInfoV1: price_badge: dict | None = None search_aliases: list[str]=None essentials_category: str=None + eager_eval: dict | None = None @dataclass @@ -1413,6 +1414,35 @@ class PriceBadge: } +@dataclass +class EagerEval: + """Frontend-evaluated expression badge for pure-computation nodes. + + When declared, the frontend evaluates the JSONata expression against + widget values whenever they change, displaying the result as a badge + without a backend round-trip. + """ + expr: str | None = None + """Static JSONata expression (e.g. "a + b").""" + expr_widget: str | None = None + """Name of a widget whose value is the dynamic expression.""" + engine: str = field(default="jsonata") + + def validate(self) -> None: + if self.engine != "jsonata": + raise ValueError(f"Unsupported EagerEval.engine '{self.engine}'. Only 'jsonata' is supported.") + if not self.expr and not self.expr_widget: + raise ValueError("EagerEval requires either 'expr' or 'expr_widget'.") + + def as_dict(self) -> dict[str, Any]: + d: dict[str, Any] = {"engine": self.engine} + if self.expr is not None: + d["expr"] = self.expr + if self.expr_widget is not None: + d["expr_widget"] = self.expr_widget + return d + + @dataclass class Schema: """Definition of V3 node properties.""" @@ -1470,6 +1500,8 @@ class Schema: """When True, all inputs from the prompt will be passed to the node as kwargs, even if not defined in the schema.""" essentials_category: str | None = None """Optional category for the Essentials tab. Path-based like category field (e.g., 'Basic', 'Image Tools/Editing').""" + eager_eval: EagerEval | None = None + """Optional frontend-evaluated expression badge for pure-computation nodes.""" def validate(self): '''Validate the schema: @@ -1498,6 +1530,8 @@ class Schema: output.validate() if self.price_badge is not None: self.price_badge.validate() + if self.eager_eval is not None: + self.eager_eval.validate() def finalize(self): """Add hidden based on selected schema options, and give outputs without ids default ids.""" @@ -1577,6 +1611,7 @@ class Schema: price_badge=self.price_badge.as_dict(self.inputs) if self.price_badge is not None else None, search_aliases=self.search_aliases if self.search_aliases else None, essentials_category=self.essentials_category, + eager_eval=self.eager_eval.as_dict() if self.eager_eval is not None else None, ) return info @@ -2225,6 +2260,7 @@ __all__ = [ "ImageCompare", "PriceBadgeDepends", "PriceBadge", + "EagerEval", "BoundingBox", "NodeReplace", ]