feat: image generation service — ComfyUI cluster integration

- POST /api/image/generate proxy endpoint (admin required)
- GET /api/image/status lists available image gen nodes
- Cluster AMQP protocol: cmd.image_generate, image_generated, image_failed
- Node agent auto-detects ComfyUI, registers image_gen capability
- ComfyUI workflow builder: CheckpointLoader → KSampler → VAEDecode → SaveImage
- Hardware probe checks ComfyUI reachability + checkpoint model list
- 27 tests covering cluster handlers, router, node agent, hardware, capabilities
- Config: CAIC_COMFYUI_BASE, CAIC_COMFYUI_TIMEOUT, comfyui_port in agent.ini
- Version bump to v1.1.0
- Documentation: ai.md, wiki/Developer-Architecture.md, current-wip.md, README.md, .env.example
This commit is contained in:
gramps
2026-07-27 08:06:03 -07:00
parent 576d9333b3
commit aecd3330fd
15 changed files with 2115 additions and 1005 deletions
+18 -2
View File
@@ -12,7 +12,7 @@ from pathlib import Path
import httpx
import psutil
from config import LLAMA_SERVER_BASE, SEARXNG_BASE, QDRANT_URL, HW_STATE_PATH
from config import LLAMA_SERVER_BASE, SEARXNG_BASE, QDRANT_URL, HW_STATE_PATH, COMFYUI_BASE
log = logging.getLogger("caic")
@@ -113,6 +113,20 @@ async def assess_hardware() -> dict:
except Exception:
log.warning("SearXNG not reachable")
comfyui_reachable = False
comfyui_models = []
try:
async with httpx.AsyncClient(timeout=5) as client:
resp = await client.get(f"{COMFYUI_BASE}/object_info/CheckpointLoaderSimple")
if resp.status_code == 200:
comfyui_reachable = True
data = resp.json()
ckpt_info = data.get("CheckpointLoaderSimple", {}).get("input", {}).get("required", {})
ckpt_list = ckpt_info.get("ckpt_name", [[]])[0]
comfyui_models = ckpt_list if isinstance(ckpt_list, list) else []
except Exception:
log.warning("ComfyUI not reachable")
state = {
"ram_total_gb": ram_total_gb,
"ram_available_gb": ram_available_gb,
@@ -124,10 +138,12 @@ async def assess_hardware() -> dict:
"qdrant_reachable": qdrant_reachable,
"qdrant_collections": qdrant_collections,
"searxng_reachable": searxng_reachable,
"comfyui_reachable": comfyui_reachable,
"comfyui_models": comfyui_models,
}
HARDWARE_STATE_PATH.write_text(json.dumps(state, indent=2))
log.info(
f"HW: {ram_total_gb}GB RAM, {vram_total_mb}MB VRAM, "
f"llama={llama_reachable}, qdrant={qdrant_reachable}, searxng={searxng_reachable}"
f"llama={llama_reachable}, qdrant={qdrant_reachable}, searxng={searxng_reachable}, comfyui={comfyui_reachable}"
)
return state