feat: Add Comfy Agent service for NODE3 image/video generation
- Create comfy-agent service with FastAPI + NATS integration - ComfyUI client with HTTP/WebSocket support - REST API: /generate/image, /generate/video, /status, /result - NATS subjects: agent.invoke.comfy, comfy.request.* - Async job queue with progress tracking - Docker compose configuration for NODE3 - Update PROJECT-MASTER-INDEX.md with NODE2/NODE3 docs Co-Authored-By: Warp <agent@warp.dev>
This commit is contained in:
51
services/comfy-agent/app/api.py
Normal file
51
services/comfy-agent/app/api.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# services/comfy-agent/app/api.py
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from .models import GenerateImageRequest, GenerateVideoRequest, JobStatus
|
||||
from .jobs import JOB_STORE
|
||||
from .worker import enqueue
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
def _build_workflow_t2i(req: GenerateImageRequest) -> dict:
|
||||
# MVP: placeholder graph; you will replace with your canonical Comfy workflow JSON.
|
||||
# Keep it deterministic and param-driven.
|
||||
return {
|
||||
"1": {"class_type": "CLIPTextEncode", "inputs": {"text": req.prompt, "clip": ["2", 0]}},
|
||||
"2": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "sdxl.safetensors"}},
|
||||
# TODO: Add complete workflow JSON for text-to-image
|
||||
}
|
||||
|
||||
def _build_workflow_t2v(req: GenerateVideoRequest) -> dict:
|
||||
# MVP placeholder for LTX-2 pipeline; replace with actual LTX-2 workflow.
|
||||
return {
|
||||
"1": {"class_type": "CLIPTextEncode", "inputs": {"text": req.prompt, "clip": ["2", 0]}},
|
||||
# TODO: Add complete workflow JSON for text-to-video with LTX-2
|
||||
}
|
||||
|
||||
@router.post("/generate/image", response_model=JobStatus)
|
||||
async def generate_image(req: GenerateImageRequest):
|
||||
job = JOB_STORE.create("text-to-image")
|
||||
graph = _build_workflow_t2i(req)
|
||||
enqueue(job.job_id, "text-to-image", graph)
|
||||
return JOB_STORE.get(job.job_id)
|
||||
|
||||
@router.post("/generate/video", response_model=JobStatus)
|
||||
async def generate_video(req: GenerateVideoRequest):
|
||||
job = JOB_STORE.create("text-to-video")
|
||||
graph = _build_workflow_t2v(req)
|
||||
enqueue(job.job_id, "text-to-video", graph)
|
||||
return JOB_STORE.get(job.job_id)
|
||||
|
||||
@router.get("/status/{job_id}", response_model=JobStatus)
|
||||
async def status(job_id: str):
|
||||
job = JOB_STORE.get(job_id)
|
||||
if not job:
|
||||
raise HTTPException(status_code=404, detail="job_not_found")
|
||||
return job
|
||||
|
||||
@router.get("/result/{job_id}", response_model=JobStatus)
|
||||
async def result(job_id: str):
|
||||
job = JOB_STORE.get(job_id)
|
||||
if not job:
|
||||
raise HTTPException(status_code=404, detail="job_not_found")
|
||||
return job
|
||||
Reference in New Issue
Block a user