magicciv/tools/sprite-generation/engine/factory.py
Natalie 7eb2897854 feat(@projects/@magic-civilization): 🎨 Grok sprite-generation pipeline + starter orchestration
Adds a Grok image backend (grok_generator.py) behind a generator factory, a
starter-set orchestrator (starter.py, orchestrate_starter.py, starter_manifest.json)
and a Grok PoC harness with proof renders. Updates the ranker/processor/composition
prompts and sprite-config; refreshes the sprite-gallery design preview.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 17:57:01 -05:00

57 lines
No EOL
2 KiB
Python

"""Generator backend factory — dual-backend dispatch.
Both backends remain first-class:
- model-boss local GPU diffusion (juggernaut-xi-v11) via Redis pubsub
- grok Grok Build CLI via grok-build-batch-sdk (GenerateImage tool)
Set sprite-config.json → "backend" for the default, or pass --backend on the CLI.
"""
from __future__ import annotations
from pathlib import Path
from typing import Callable, Awaitable
from engine.registry import SpriteRegistry
BACKENDS = ("model-boss", "grok")
OnComplete = Callable[[int, str], Awaitable[None]]
def resolve_backend(config: dict, override: str | None = None) -> str:
"""Return the active backend name, validating against BACKENDS."""
backend = override or config.get("backend", "model-boss")
if backend not in BACKENDS:
raise ValueError(
f"Unknown backend {backend!r}. Choose one of: {', '.join(BACKENDS)}"
)
return backend
def with_backend(config: dict, backend: str | None = None) -> dict:
"""Return a config copy with the resolved backend field set."""
resolved = resolve_backend(config, backend)
merged = dict(config)
merged["backend"] = resolved
return merged
def backend_summary(config: dict) -> str:
"""Human-readable label for log output."""
backend = config.get("backend", "model-boss")
if backend == "grok":
grok = config.get("grok", {})
return f"grok-build ({grok.get('model', 'grok-build')} CLI)"
return f"model-boss ({config.get('model', 'juggernaut-xi-v11')})"
def create_generator(config: dict, registry: SpriteRegistry, raw_dir: Path, *, backend: str | None = None):
"""Return the sprite generator for the configured (or overridden) backend."""
cfg = with_backend(config, backend)
active = cfg["backend"]
if active == "grok":
from engine.grok_generator import GrokSpriteGenerator
return GrokSpriteGenerator(config=cfg, registry=registry, raw_dir=raw_dir)
from engine.generator import SpriteGenerator
return SpriteGenerator(config=cfg, registry=registry, raw_dir=raw_dir)