Weight syntax:
- Grammar: `(arg:SIGNED_NUMBER)` parses to a WeightedGroup
- emph(text|w) is a function-style alias for the same
- Nested weights multiply: ((cat:1.2):0.5) -> 0.6, matching A1111
- Weights are emitted in the (token, weight) tuples that comfy's
stock encode_token_weights already applies post-transformer
To make per-position weight indexing work, rows are now always
exactly max_length entries: a multi-slot Action emits as one
(action, w) entry followed by (ACTION_CONTINUATION, w) placeholders
that process_tokens drops before handing to super().process_tokens.
This replaces the previous variable-length-row + padding-math.
PromptLang Inspect:
- New node: CLIP + text -> STRING report of per-slot weight, L2
norm, and top-k nearest vocab tokens for the resolved embedding
- lib/inspect.py uses the wrapper's stored attr name (cond.clip /
tok.clip) rather than hardcoding 'clip_l', and uses the
tokenizer's inv_vocab for decode
Fix: parse_numeric_arg now rejects WeightedGroup (was only Action).
SegOrAction widened to include WeightedGroup.
Rebase the DSL text encoder on comfy.sd1_clip.SDClipModel and
comfy.clip_model.CLIPTextModel_, replacing the old HuggingFace
transformers CLIPTextModel/CLIPTextTransformer/CLIPTextEmbeddings
subclasses (which are no longer how ComfyUI implements CLIP).
Structure:
- Merge lib/action/ into lib/actions/; drop lib/fun_clip_stuff.py
and the bundled clip_config*.json (comfy ships its own)
- Convert all custom_nodes.KepPromptLang.* absolute imports to
relative imports so installs via Manager work regardless of
install directory name
Encoder:
- PromptLangSDClipModel overrides encode_token_weights to walk
the segment/action tree, assemble [B, seq, hidden] embeds, and
call self.transformer(None, mask, embeds=..., num_tokens=...)
- posScale / postPos are supported without patching the transformer
by pre-baking the delta (modified - default) into embeds, so the
transformer's inline add yields the modified position embedding
- Drop the unused empty-baseline batch that was prepended and then
sliced off; halves the per-encode forward pass for single prompts
Actions:
- Fix copy-pasted broken __repr__ / depth_repr across sum/diff/avg/
slerp that referenced fields that didn't exist
- Fix NameError in AverageAction._validate_args (start_arg_token_length)
- Fix class-level mutable state in RandAction
- Unify _parse_scalar / _parse_scalar_weight / _parse_int into a
single parse_numeric_arg helper in action_utils.py
- Share add_with_broadcast between SumAction and DiffAction
- Convert PostModifiers from TypedDict to dataclass (attribute
access catches typos that .get() on string keys hides)
Drop the two _exp-pooler / _exp-pooledAvg actions: they recursively
invoked the HF CLIPTextTransformer and would need a rework to fit
the current CLIPTextModel_ interface. They were experimental and
not documented as stable.
BuildGif node:
- Collapse the 10-positional-arg _save_* helpers onto a small
_SaveContext dataclass
- Stop mutating the input arg semantics (split_every_val was
reassigned to len(images) when -1)
Tests:
- Add pytest suite covering the parser (grammar, nesting, errors)
and every action (embedding math, shape, modifier payloads)
- conftest stubs ComfyUI at collection time so tests don't need a
real ComfyUI install
Drop the broken test_files/ scripts (CI helpers, not a test suite)
and regenerate the README from tools/build_docs.py.