Separate user-facing layout from API fixtures, keep provider menus scalable, and lock media-family boundaries before more integrations are delegated. Constraint: User workflows must remain readable as providers and media families grow. Rejected: Mechanical row-major workflow layout | valid but obscures data flow and wastes space. Confidence: high Scope-risk: narrow Directive: Add new providers under MediaHub/Provider and add new media families as independent vertical slices. Tested: 123 pytest tests; JavaScript syntax; Python compilation; JSON validation; restarted ComfyUI object_info; all eight prompt smoke workflows. Not-tested: Manual visual import of all eight updated user workflows.
77 lines
2.0 KiB
Python
77 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Apply the canonical three-region layout to user-facing workflows."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
INPUT_X = 80
|
|
CONFIG_X = 620
|
|
OUTPUT_X = 1160
|
|
|
|
NODE_LAYOUT = {
|
|
"MediaHubAPIKey": (INPUT_X, 100, 340, 72),
|
|
"PrimitiveStringMultiline": (INPUT_X, 220, 420, 170),
|
|
"LoadImage": (INPUT_X, 450, 420, 320),
|
|
"MediaHubGenerateImage": (OUTPUT_X, 140, 360, 130),
|
|
"MediaHubSubmitVideo": (OUTPUT_X, 100, 360, 130),
|
|
"MediaHubResolveVideo": (OUTPUT_X, 300, 360, 140),
|
|
"PreviewImage": (OUTPUT_X, 350, 460, 380),
|
|
"SaveVideo": (OUTPUT_X, 520, 420, 220),
|
|
}
|
|
|
|
GROUPS = [
|
|
{
|
|
"id": 1,
|
|
"title": "Inputs / 输入",
|
|
"bounding": [40, 40, 500, 780],
|
|
"color": "#3f789e",
|
|
"font_size": 24,
|
|
"flags": {},
|
|
},
|
|
{
|
|
"id": 2,
|
|
"title": "Provider Config / 配置",
|
|
"bounding": [580, 40, 500, 780],
|
|
"color": "#9e7b3f",
|
|
"font_size": 24,
|
|
"flags": {},
|
|
},
|
|
{
|
|
"id": 3,
|
|
"title": "Outputs / 输出",
|
|
"bounding": [1120, 40, 540, 780],
|
|
"color": "#4b8a55",
|
|
"font_size": 24,
|
|
"flags": {},
|
|
},
|
|
]
|
|
|
|
|
|
def layout_workflow(path: Path) -> None:
|
|
workflow = json.loads(path.read_text())
|
|
for node in workflow["nodes"]:
|
|
node_type = node["type"]
|
|
if node_type.endswith("Config"):
|
|
node["pos"] = [CONFIG_X, 140]
|
|
node["size"] = [420, max(node["size"][1], 300)]
|
|
continue
|
|
if node_type in NODE_LAYOUT:
|
|
x, y, width, height = NODE_LAYOUT[node_type]
|
|
node["pos"] = [x, y]
|
|
node["size"] = [width, height]
|
|
workflow["groups"] = GROUPS
|
|
path.write_text(json.dumps(workflow, ensure_ascii=False, indent=2) + "\n")
|
|
|
|
|
|
def main() -> int:
|
|
for path in sorted((ROOT / "examples").glob("*_preview.json")):
|
|
layout_workflow(path)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|