Expose the Scene Analyzer as a ComfyUI node (MASTER_SPEC §20) plus the node registration plumbing and a shared output adapter. - nodes/scene_analyzer_node.py: SceneAnalyzerNode, a thin adapter. Inputs are Natural Language, Model Name, Temperature, Timeout, and an optional System Prompt override; it builds a Config, constructs OllamaBackend.from_config, and delegates to analyze(). Outputs (scene, warnings, errors): the SCENE model and the warnings/errors formatted for display. No compiler logic in the node. - nodes/adapters.py: format_messages() renders diagnostics as CODE: description lines. - Registration: nodes/__init__.py aggregates NODE_CLASS_MAPPINGS / NODE_DISPLAY_NAME_MAPPINGS; the root __init__.py re-exports them. ComfyUI compatibility: the node package uses relative imports internally so our `nodes` package is never resolved as ComfyUI's own top-level `nodes` module, and the entry point puts the repo root on sys.path so `compiler`/`schemas` resolve when ComfyUI loads the package by file path. Tests (no live Ollama): INPUT_TYPES/RETURN metadata, delegation to analyze (monkeypatched) with warnings/errors surfaced, empty-message strings, system prompt override passthrough, and ComfyUI registration. Co-authored-by: kunail0804 <kunail0804@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
78 lines
2.7 KiB
Python
78 lines
2.7 KiB
Python
"""Tests for the Scene Analyzer ComfyUI node (issue #19). No live Ollama."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import nodes
|
|
import nodes.scene_analyzer_node as node_module
|
|
from compiler.common.message_codes import message
|
|
from compiler.common.result import CompilerResult
|
|
from nodes.scene_analyzer_node import SceneAnalyzerNode
|
|
|
|
|
|
def test_input_types_structure() -> None:
|
|
inputs = SceneAnalyzerNode.INPUT_TYPES()
|
|
assert set(inputs["required"]) == {
|
|
"natural_language",
|
|
"model_name",
|
|
"temperature",
|
|
"timeout",
|
|
}
|
|
assert "system_prompt" in inputs["optional"]
|
|
|
|
|
|
def test_node_metadata() -> None:
|
|
assert SceneAnalyzerNode.RETURN_TYPES == ("SCENE", "STRING", "STRING")
|
|
assert SceneAnalyzerNode.RETURN_NAMES == ("scene", "warnings", "errors")
|
|
assert SceneAnalyzerNode.FUNCTION == "run"
|
|
assert SceneAnalyzerNode.CATEGORY == "Scene Compiler"
|
|
|
|
|
|
def test_run_delegates_to_analyzer_and_surfaces_messages(monkeypatch) -> None:
|
|
captured = {}
|
|
|
|
def fake_analyze(description, backend, config):
|
|
captured["description"] = description
|
|
captured["model"] = config.analyzer.model
|
|
return (
|
|
CompilerResult(data="SCENE_MODEL")
|
|
.add_warning(message("SC0001", "unknown concept 'x'"))
|
|
.add_error(message("SC0011", "bad response"))
|
|
)
|
|
|
|
monkeypatch.setattr(node_module, "analyze", fake_analyze)
|
|
|
|
scene, warnings, errors = SceneAnalyzerNode().run(
|
|
natural_language="A girl.",
|
|
model_name="mistral",
|
|
temperature=0.0,
|
|
timeout=60,
|
|
)
|
|
assert scene == "SCENE_MODEL"
|
|
assert captured["description"] == "A girl."
|
|
assert captured["model"] == "mistral"
|
|
assert "SC0001: unknown concept 'x'" in warnings
|
|
assert "SC0011: bad response" in errors
|
|
|
|
|
|
def test_no_messages_yield_empty_strings(monkeypatch) -> None:
|
|
monkeypatch.setattr(node_module, "analyze", lambda d, b, c: CompilerResult(data="S"))
|
|
scene, warnings, errors = SceneAnalyzerNode().run("x", "llama3", 0.0, 60)
|
|
assert (warnings, errors) == ("", "")
|
|
|
|
|
|
def test_system_prompt_override_is_passed(monkeypatch) -> None:
|
|
captured = {}
|
|
|
|
def fake_analyze(description, backend, config):
|
|
captured["system_prompt"] = config.analyzer.system_prompt
|
|
return CompilerResult(data="S")
|
|
|
|
monkeypatch.setattr(node_module, "analyze", fake_analyze)
|
|
SceneAnalyzerNode().run("x", "llama3", 0.0, 60, system_prompt="CUSTOM")
|
|
assert captured["system_prompt"] == "CUSTOM"
|
|
|
|
|
|
def test_registered_for_comfyui() -> None:
|
|
assert nodes.NODE_CLASS_MAPPINGS["SceneCompilerAnalyzer"] is SceneAnalyzerNode
|
|
assert nodes.NODE_DISPLAY_NAME_MAPPINGS["SceneCompilerAnalyzer"] == "Scene Analyzer"
|