ComfyUI/comfy_extras
Dante e544c65db9
feat: add Math Expression node with simpleeval evaluation (#12687)
* feat: add EagerEval dataclass for frontend-side node evaluation

Add EagerEval to the V3 API schema, enabling nodes to declare
frontend-evaluated JSONata expressions. The frontend uses this to
display computation results as badges without a backend round-trip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add Math Expression node with JSONata evaluation

Add ComfyMathExpression node that evaluates JSONata expressions against
dynamically-grown numeric inputs using Autogrow + MatchType. Sends
input context via ui output so the frontend can re-evaluate when
the expression changes without a backend round-trip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: register nodes_math.py in extras_files loader list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address CodeRabbit review feedback

- Harden EagerEval.validate with type checks and strip() for empty strings
- Add _positional_alias for spreadsheet-style names beyond z (aa, ab...)
- Validate JSONata result is numeric before returning
- Add jsonata to requirements.txt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove EagerEval, scope PR to math node only

Remove EagerEval dataclass from _io.py and eager_eval usage from
nodes_math.py. Eager execution will be designed as a general-purpose
system in a separate effort.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use TemplateNames, cap inputs at 26, improve error message

Address Kosinkadink review feedback:
- Switch from Autogrow.TemplatePrefix to Autogrow.TemplateNames so input
  slots are named a-z, matching expression variables directly
- Cap max inputs at 26 (a-z) instead of 100
- Simplify execute() by removing dual-mapping hack
- Include expression and result value in error message

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add unit tests for Math Expression node

Add tests for _positional_alias (a-z mapping) and execute() covering
arithmetic operations, float inputs, $sum(values), and error cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace jsonata with simpleeval for math evaluation

jsonata PyPI package has critical issues: no Python 3.12/3.13 wheels,
no ARM/Apple Silicon wheels, abandoned (last commit 2023), C extension.

Replace with simpleeval (pure Python, 3.4M downloads/month, MIT,
AST-based security). Add math module functions (sqrt, ceil, floor,
log, sin, cos, tan) and variadic sum() supporting both sum(values)
and sum(a, b, c). Pin version to >=1.0,<2.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: update tests for simpleeval migration

Update JSONata syntax to Python syntax ($sum -> sum, $string -> str),
add tests for math functions (sqrt, ceil, floor, sin, log10) and
variadic sum(a, b, c).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace MatchType with MultiType inputs and dual FLOAT/INT outputs

Allow mixing INT and FLOAT connections on the same node by switching
from MatchType (which forces all inputs to the same type) to MultiType.
Output both FLOAT and INT so users can pick the type they need.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: update tests for mixed INT/FLOAT inputs and dual outputs

Add assertions for both FLOAT (result[0]) and INT (result[1]) outputs.
Add test_mixed_int_float_inputs and test_mixed_resolution_scale to
verify the primary use case of multiplying resolutions by a float factor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: make expression input multiline and validate empty expression

- Add multiline=True to expression input for better UX with longer expressions
- Add empty expression validation with clear "Expression cannot be empty." message

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add tests for empty expression validation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback — safe pow, isfinite guard, test coverage

- Wrap pow() with _safe_pow to prevent DoS via huge exponents
  (pow() bypasses simpleeval's safe_power guard on **)
- Add math.isfinite() check to catch inf/nan before int() conversion
- Add int/float converters to MATH_FUNCTIONS for explicit casting
- Add "calculator" search alias
- Replace _positional_alias helper with string.ascii_lowercase
- Narrow test assertions and add error path + function coverage tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update requirements.txt

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com>
Co-authored-by: Christian Byrne <abolkonsky.rem@gmail.com>
2026-03-05 18:51:28 -08:00
..
chainner_models
nodes_ace.py Update ace15.py to allow min_p sampling (#12373) 2026-02-11 20:28:48 -05:00
nodes_advanced_samplers.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_align_your_steps.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_apg.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_attention_multiply.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_audio_encoder.py convert nodes_audio_encoder.py to V3 schema (#10123) 2025-09-30 23:00:22 -07:00
nodes_audio.py Fix VAEDecodeAudioTiled ignoring tile_size input (#12735) (#12738) 2026-03-02 20:17:51 -05:00
nodes_camera_trajectory.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_canny.py feat: add essential subgraph blueprints (#12552) 2026-02-20 23:40:13 -08:00
nodes_cfg.py convert CFG nodes to V3 schema (#9717) 2025-09-12 17:39:55 -04:00
nodes_chroma_radiance.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_clip_sdxl.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_color.py Add color type and Color to RGB Int node (#12145) 2026-01-30 15:01:33 -08:00
nodes_compositing.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_cond.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_context_windows.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_controlnet.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_cosmos.py convert Cosmos nodes to V3 schema (#9721) 2025-09-12 17:38:46 -04:00
nodes_custom_sampler.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_dataset.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_differential_diffusion.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_easycache.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_edit_model.py convert nodes_edit_model.py to V3 schema (#10147) 2025-10-03 13:24:42 -07:00
nodes_eps.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_flux.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_freelunch.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_fresca.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_gits.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_glsl.py fix torch.cat requiring inputs to all be same dimensions (#12673) 2026-02-27 08:13:24 -08:00
nodes_hidream.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_hooks.py Disable dynamic_vram when weight hooks applied (#12653) 2026-02-28 16:50:18 -05:00
nodes_hunyuan3d.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_hunyuan.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_hypernetwork.py convert nodes_hypernetwork.py to V3 schema (#10583) 2025-11-03 00:21:47 -08:00
nodes_hypertile.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_image_compare.py add node - image compare (#11343) 2026-01-08 21:31:19 -08:00
nodes_images.py Limit overlap in image tile and combine nodes to prevent issues. (#12688) 2026-02-27 20:16:24 -05:00
nodes_ip2p.py convert nodes_ip2p.pt to V3 schema (#10097) 2025-10-01 12:20:30 -07:00
nodes_kandinsky5.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_latent.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_load_3d.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_logic.py add support for kwargs inputs to allow arbitrary inputs from frontend (#12063) 2026-01-24 17:30:40 -08:00
nodes_lora_debug.py Move nodes from previous PR into their own file. (#12066) 2026-01-24 23:02:32 -05:00
nodes_lora_extract.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_lotus.py convert nodes_lotus.py to V3 schema (#10057) 2025-09-27 19:11:36 -07:00
nodes_lt_audio.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_lt_upsampler.py Support the LTXV 2 model. (#11632) 2026-01-05 01:58:59 -05:00
nodes_lt.py feat: add causal_fix parameter to add_keyframe_index and append_keyframe (#12797) 2026-03-05 16:51:20 -05:00
nodes_lumina2.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_mahiro.py refactor: rename Mahiro CFG to Similarity-Adaptive Guidance (#12172) 2026-02-28 20:59:24 -08:00
nodes_mask.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_math.py feat: add Math Expression node with simpleeval evaluation (#12687) 2026-03-05 18:51:28 -08:00
nodes_mochi.py convert nodes_mochi.py to V3 schema (#10069) 2025-09-29 12:03:35 -07:00
nodes_model_advanced.py initial FlowRVS support (#12637) 2026-02-25 23:38:46 -05:00
nodes_model_downscale.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_model_merging_model_specific.py Qwen Image model merging node. (#9202) 2025-08-06 04:07:04 -04:00
nodes_model_merging.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_model_patch.py Reduce RAM usage, fix VRAM OOMs, and fix Windows shared memory spilling with adaptive model loading (#11845) 2026-02-01 01:01:11 -05:00
nodes_morphology.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_nag.py Add category to Normalized Attention Guidance node (#12565) 2026-02-21 19:51:21 -05:00
nodes_nop.py Native block swap custom nodes considered harmful. (#10783) 2025-11-18 00:26:44 -05:00
nodes_optimalsteps.py convert nodes_optimalsteps.py to V3 schema (#10074) 2025-10-01 12:18:04 -07:00
nodes_pag.py convert nodes_pag.py to V3 schema (#10080) 2025-10-01 12:18:49 -07:00
nodes_perpneg.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_photomaker.py convert nodes_photomaker.py to V3 schema (#10017) 2025-09-27 02:36:43 -07:00
nodes_pixart.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_post_processing.py fix: move essentials_category to correct replacement nodes (#12568) 2026-02-26 01:00:32 -08:00
nodes_preview_any.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_primitive.py fix: swap essentials_category from CLIPTextEncode to PrimitiveStringMultiline (#12553) 2026-02-20 23:46:46 -08:00
nodes_qwen.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_rebatch.py convert nodes_rebatch.py to V3 schema (#9945) 2025-09-26 14:10:49 -07:00
nodes_replacements.py Node Replacement API (#12014) 2026-02-15 02:12:30 -08:00
nodes_resolution.py refactor: use AspectRatio enum members as ASPECT_RATIOS dict keys (#12689) 2026-02-27 20:53:46 -08:00
nodes_rope.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_sag.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_sd3.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_sdpose.py feat: Support SDPose-OOD (#12661) 2026-02-26 19:59:05 -05:00
nodes_sdupscale.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_slg.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_stable3d.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_stable_cascade.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_string.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_tcfg.py convert nodes_tcfg.py to V3 schema (#9942) 2025-09-26 14:13:05 -07:00
nodes_textgen.py Force min length 1 when tokenizing for text generation. (#12538) 2026-02-19 22:57:44 -05:00
nodes_tomesd.py convert nodes_tomesd.py to V3 schema (#10180) 2025-10-03 11:50:38 -07:00
nodes_toolkit.py Add a Create List node (#12173) 2026-02-05 01:18:21 -05:00
nodes_torch_compile.py Disable dynamic_vram when using torch compiler (#12612) 2026-02-24 19:13:46 -05:00
nodes_train.py dynamic_vram: Training fixes (#12442) 2026-02-13 15:29:37 -05:00
nodes_upscale_model.py feat: Add search_aliases field to node schema (#12010) 2026-01-21 15:36:02 -08:00
nodes_video_model.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_video.py fix: move essentials_category to correct replacement nodes (#12568) 2026-02-26 01:00:32 -08:00
nodes_wan.py feat: Support SCAIL WanVideo model (#12614) 2026-02-28 16:49:12 -05:00
nodes_wanmove.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00
nodes_webcam.py add search aliases to all nodes (#12035) 2026-01-22 18:36:58 -08:00
nodes_zimage.py feat: mark 429 widgets as advanced for collapsible UI (#12197) 2026-02-19 19:20:02 -08:00