Wildcard options, fixed values and combines can carry a `negative`, and a
derivation action gains the `negative` ("Add to negative") mode. The
engine files negatives per variable in `__wp_negatives__`, carries them
across nodes, and the Assembler gets a `negative` output built from the
variables its template rendered, filled into a `negative_template` at
`$negatives`. Negatives resolve on their own seed stream and refs inside
them resolve quietly, so picks never shift. Injector rows can set a
negative, the Prompt Cleaner cleans an optional negative with its own
rule column, and the preview endpoint returns the negatives table.
Schema v8 stamps payloads that use a negative.
76 lines
2.2 KiB
Python
76 lines
2.2 KiB
Python
"""End-to-end node integration — simulate a small ComfyUI workflow."""
|
|
|
|
import json
|
|
|
|
from wp_nodes.assembler_node import WPPromptAssembler
|
|
from wp_nodes.context_node import WPContext
|
|
from wp_nodes.debug_node import WPDebug
|
|
from wp_nodes.types import ContextPayload
|
|
|
|
|
|
def _mods(entries):
|
|
return json.dumps({
|
|
"version": 1,
|
|
"modules": [{
|
|
"id": "auto",
|
|
"type": "fixed_values",
|
|
"entries": entries,
|
|
}],
|
|
})
|
|
|
|
|
|
def test_chain_of_two_context_nodes_into_assembler():
|
|
# Upstream context sets style + subject.
|
|
upstream = WPContext.execute(
|
|
seed=1,
|
|
wp_modules=_mods([
|
|
{"variable_name": "style", "value": "photoreal"},
|
|
{"variable_name": "subject", "value": "knight"},
|
|
]),
|
|
upstream=None,
|
|
).values[0]
|
|
|
|
# Downstream context adds environment vars + overrides style.
|
|
downstream = WPContext.execute(
|
|
seed=2,
|
|
wp_modules=_mods([
|
|
{"variable_name": "style", "value": "painted"},
|
|
{"variable_name": "location", "value": "forest"},
|
|
]),
|
|
upstream=upstream,
|
|
).values[0]
|
|
|
|
assert isinstance(downstream, ContextPayload)
|
|
assert downstream.context == {
|
|
"subject": "knight",
|
|
"style": "painted",
|
|
"location": "forest",
|
|
}
|
|
|
|
# Assembler renders the final template.
|
|
assembled = WPPromptAssembler.execute(
|
|
context=downstream,
|
|
template="A $style $subject in the $location",
|
|
)
|
|
assert assembled.values == ("A painted knight in the forest", "")
|
|
|
|
|
|
def test_debug_node_snapshots_downstream_context():
|
|
upstream = WPContext.execute(
|
|
seed=7,
|
|
wp_modules=_mods([
|
|
{"variable_name": "style", "value": "photoreal"},
|
|
]),
|
|
upstream=None,
|
|
).values[0]
|
|
|
|
out = WPDebug.execute(context=upstream, wp_viewer=None)
|
|
snapshot = json.loads(out.ui["wp_debug_snapshot"][0])
|
|
|
|
# Flat snapshot shape — user vars at the top, engine internals
|
|
# under `__wp_*` keys ready for the per-tab readers in
|
|
# `DebugViewer.vue`.
|
|
assert snapshot["style"] == "photoreal"
|
|
assert snapshot["__wp_node_seed__"] == 7
|
|
assert len(snapshot["__wp_trace__"]) == 1
|