feat: complete image console and add verified REST and MCP workflows

This commit is contained in:
2026-11-04 00:41:54 +08:00
parent 3140cd51d2
commit bef8af53ed
48 changed files with 5167 additions and 1176 deletions
+1
View File
@@ -0,0 +1 @@
"""路由包。"""
+34
View File
@@ -0,0 +1,34 @@
"""画廊 API。"""
from __future__ import annotations
from fastapi import APIRouter, HTTPException
from ..services import gallery as svc
from ..providers import ProviderError
router = APIRouter(prefix="/api/galleries", tags=["gallery"])
@router.get("")
def list_galleries():
return svc.list_galleries()
@router.get("/{profile_name}")
def list_gallery(profile_name: str):
try:
return svc.list_gallery(profile_name)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.delete("/{profile_name}/{filename}")
def delete_gallery_item(profile_name: str, filename: str):
try:
svc.delete_gallery_item(profile_name, filename)
except FileNotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc))
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
return {"ok": True}
+33
View File
@@ -0,0 +1,33 @@
"""出图 API。"""
from __future__ import annotations
from fastapi import APIRouter, HTTPException
from ..providers import ProviderError
from ..schemas import GenerateIn
from ..services import generation as svc
router = APIRouter(prefix="/api", tags=["generate"])
@router.post("/generate")
def generate(payload: GenerateIn):
try:
return svc.generate(
provider_id=payload.provider_id,
model=payload.model,
prompt=payload.prompt,
size=payload.size,
ratio=payload.ratio,
n=payload.n,
images=payload.images,
profile_name=payload.profile_name,
)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.get("/generations")
def list_generations():
return svc.list_generations()
+33
View File
@@ -0,0 +1,33 @@
"""模型 API。"""
from __future__ import annotations
from fastapi import APIRouter, HTTPException
from ..providers import ProviderError
from ..schemas import ModelBulkIn, ModelPatchIn
from ..services import providers as svc
router = APIRouter(prefix="/api/models", tags=["models"])
@router.get("")
def list_models(provider_id: str | None = None):
return svc.list_models(provider_id)
@router.patch("/{model_id:path}")
def patch_model(model_id: str, payload: ModelPatchIn):
try:
if payload.enabled is not None:
svc.set_model_enabled(model_id, payload.enabled)
if payload.note is not None:
svc.set_model_note(model_id, payload.note)
return svc.get_model(model_id)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.post("/bulk")
def bulk_models(payload: ModelBulkIn):
return svc.set_models_enabled(payload.ids, payload.enabled)
+65
View File
@@ -0,0 +1,65 @@
"""供应商与模型 API。"""
from __future__ import annotations
from fastapi import APIRouter, HTTPException
from ..providers import ProviderError
from ..schemas import DiscoverIn, ModelUpsertIn, ProviderIn
from ..services import providers as svc
router = APIRouter(prefix="/api/providers", tags=["providers"])
@router.get("")
def list_providers():
return svc.list_providers()
@router.post("")
def save_provider(payload: ProviderIn):
try:
return svc.save_provider(payload.model_dump())
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.delete("/{provider_id}")
def delete_provider(provider_id: str):
svc.delete_provider(provider_id)
return {"ok": True}
@router.post("/discover")
def discover_with_credentials(payload: DiscoverIn):
"""尚未保存供应商时,用手填的 Base URL + Key 临时拉取模型清单。"""
try:
return svc.discover_with_credentials(
payload.adapter, payload.base_url.rstrip("/"), payload.api_key
)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.post("/{provider_id}/discover")
def discover_provider_models(provider_id: str):
"""按已保存的供应商拉取上游模型(命中规则:模型 ID 含 image)。"""
try:
return svc.discover(provider_id)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
@router.post("/{provider_id}/models")
def upsert_provider_models(provider_id: str, payload: ModelUpsertIn):
"""保存勾选的模型,并设置启用状态(未勾选的自动停用)。"""
try:
return svc.upsert_models(
provider_id,
payload.model_ids,
enabled=payload.enabled,
note=payload.note or "自动发现",
exclusive=True,
)
except ProviderError as exc:
raise HTTPException(status_code=exc.status, detail=exc.message)
+20
View File
@@ -0,0 +1,20 @@
"""SKILL.md API。"""
from __future__ import annotations
from fastapi import APIRouter
from fastapi.responses import PlainTextResponse
from ..services import skill_doc
router = APIRouter(prefix="/api", tags=["skills"])
@router.get("/skills")
def get_skills():
return skill_doc.get_skill()
@router.get("/skills/raw", response_class=PlainTextResponse)
def get_skills_raw():
return skill_doc.get_skill()["body"]