phase 5: edge transforms, soleprint-ui rename, infra fixes
- pipeline edge transforms: stages can declare accepted_transforms, edges carry a transform dict, runner injects per-stage and nodes apply (e.g. invert_mask before edge detection); editable from UI via PUT /config/edge-transform - rename mpr-ui-framework -> soleprint-ui (now an external package synced via .spr from /home/mariano/wdir/spr); add @vue-flow/core and uplot to detection-app so linked package resolves them - Tiltfile guards kubectl context, k8s commands pin --context kind-mpr - kind-config: gateway on hostPort 30080 (Caddy fronts mpr.local.ar) - modelgen: pyproject.toml, .spr marker, dict default_factory support
This commit is contained in:
@@ -38,6 +38,14 @@ class StageOutputHintInfo(BaseModel):
|
||||
src_format: str = "png"
|
||||
|
||||
|
||||
class TransformOptionInfo(BaseModel):
|
||||
key: str
|
||||
type: str
|
||||
default: object = False
|
||||
label: str = ""
|
||||
description: str = ""
|
||||
|
||||
|
||||
class StageConfigInfo(BaseModel):
|
||||
name: str
|
||||
label: str
|
||||
@@ -45,6 +53,7 @@ class StageConfigInfo(BaseModel):
|
||||
category: str
|
||||
config_fields: list[dict]
|
||||
output_hints: list[StageOutputHintInfo] = []
|
||||
accepted_transforms: list[TransformOptionInfo] = []
|
||||
reads: list[str]
|
||||
writes: list[str]
|
||||
|
||||
@@ -87,6 +96,51 @@ def get_pipeline_config(profile_name: str):
|
||||
return profile["pipeline"]
|
||||
|
||||
|
||||
class UpdateEdgeTransformRequest(BaseModel):
|
||||
profile_name: str = "soccer_broadcast"
|
||||
source_stage: str
|
||||
target_stage: str
|
||||
transform: dict
|
||||
|
||||
|
||||
@router.put("/config/edge-transform")
|
||||
def update_edge_transform(req: UpdateEdgeTransformRequest):
|
||||
"""Update the transform on an edge in a profile's pipeline config."""
|
||||
from uuid import UUID
|
||||
from core.db.models import Profile
|
||||
from core.db.connection import get_session
|
||||
from sqlmodel import select
|
||||
from fastapi import HTTPException
|
||||
|
||||
with get_session() as session:
|
||||
stmt = select(Profile).where(Profile.name == req.profile_name)
|
||||
profile = session.exec(stmt).first()
|
||||
if not profile:
|
||||
raise HTTPException(status_code=404, detail=f"Profile not found: {req.profile_name}")
|
||||
|
||||
pipeline = dict(profile.pipeline)
|
||||
edges = pipeline.get("edges", [])
|
||||
|
||||
found = False
|
||||
for edge in edges:
|
||||
if edge.get("source") == req.source_stage and edge.get("target") == req.target_stage:
|
||||
edge["transform"] = req.transform
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail=f"Edge not found: {req.source_stage} → {req.target_stage}",
|
||||
)
|
||||
|
||||
pipeline["edges"] = edges
|
||||
profile.pipeline = pipeline
|
||||
session.commit()
|
||||
|
||||
return {"status": "updated", "edge": f"{req.source_stage} → {req.target_stage}", "transform": req.transform}
|
||||
|
||||
|
||||
@router.get("/config/stages", response_model=list[StageConfigInfo])
|
||||
def list_stage_configs():
|
||||
"""Return the stage palette with config field metadata for the editor."""
|
||||
@@ -137,6 +191,13 @@ def _stage_to_info(stage) -> StageConfigInfo:
|
||||
)
|
||||
for h in getattr(stage, "output_hints", [])
|
||||
],
|
||||
accepted_transforms=[
|
||||
TransformOptionInfo(
|
||||
key=t.key, type=t.type, default=t.default,
|
||||
label=t.label, description=t.description,
|
||||
)
|
||||
for t in getattr(stage, "accepted_transforms", [])
|
||||
],
|
||||
reads=stage.io.reads,
|
||||
writes=stage.io.writes,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user