Files
f2027a89f8 feat(config)!: trim Configuration inputs and rewrite tooltips (#150)
Remove settings the user should not have to touch, and make every tooltip
plain-language:

- knowledge_base path: removed; the Knowledge Base ships in the package, so the
  path is fixed rather than a prompted input.
- prompt_target: removed (reserved; to be replaced in V3).
- prompt_separator: removed; always ',' this version. Both keep their compiler
  defaults, just no longer exposed as node inputs.
- analyzer_system_prompt (Configuration) and system_prompt (Scene Analyzer):
  removed. A user-authored system prompt is not UX-friendly; the built-in analyzer
  prompt is always used.
- Rewrite all node tooltips in plain language reflecting the current nodes.

Example workflow and node tests updated; docs/nodes.md refreshed.

BREAKING CHANGE: the Configuration node's knowledge_base, prompt_target,
prompt_separator, and analyzer_system_prompt inputs and the Scene Analyzer's
system_prompt input are removed.

Co-authored-by: kunail0804 <kunail0804@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:37:28 +02:00

78 lines
2.9 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.config import Config
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()
# Analyzer settings live on the Configuration node; only the per-run text and
# the optional config connection remain.
assert set(inputs["required"]) == {"natural_language"}
assert set(inputs["optional"]) == {"config"}
def test_node_metadata() -> None:
assert SceneAnalyzerNode.RETURN_TYPES == ("SCENE", "STRING", "STRING", "STRING")
assert SceneAnalyzerNode.RETURN_NAMES == ("scene", "warnings", "errors", "raw")
assert SceneAnalyzerNode.FUNCTION == "run"
assert SceneAnalyzerNode.CATEGORY == "Scene Compiler"
def test_run_uses_model_from_config(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)
config = Config.from_json({"analyzer": {"model": "mistral"}})
scene, warnings, errors, *_ = SceneAnalyzerNode().run(
natural_language="A girl.",
config=config,
)
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_defaults_apply_without_a_configuration_node(monkeypatch) -> None:
captured = {}
def fake_analyze(description, backend, config):
captured["model"] = config.analyzer.model
captured["timeout"] = config.analyzer.timeout
return CompilerResult(data="S")
monkeypatch.setattr(node_module, "analyze", fake_analyze)
SceneAnalyzerNode().run("A girl.")
# Falls back to the built-in model with a cold-load-friendly timeout.
assert captured["model"] == "llama3"
assert captured["timeout"] == 300
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")
assert (warnings, errors) == ("", "")
def test_registered_for_comfyui() -> None:
assert nodes.NODE_CLASS_MAPPINGS["SceneCompilerAnalyzer"] is SceneAnalyzerNode
assert nodes.NODE_DISPLAY_NAME_MAPPINGS["SceneCompilerAnalyzer"] == "Scene Analyzer"