Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -911,6 +911,105 @@
}
}
},
"/pipeline-templates": {
"get": {
"tags": [
"pipeline-templates"
],
"summary": "Get Pipeline Templates",
"description": "List all available pipeline templates.\n\nOperation:\n Return all read-only pipeline templates loaded from configuration.\n Properties that require user-supplied values (e.g. input source URI, model paths)\n are stored as empty strings. Use templates as a starting point \u2013 copy the desired variant's graph,\n fill in the empty properties with real values, and submit it as a new\n pipeline via ``POST /pipelines``.\n\nPath / query parameters:\n None.\n\nReturns:\n 200 OK:\n JSON array of Pipeline objects with ``source=TEMPLATE``.\n Each pipeline includes:\n * id, name, description, source, tags\n * variants (list of Variant objects with graphs and timestamps),\n all variants have ``read_only=True``\n * thumbnail (always null for templates)\n * created_at, modified_at (UTC datetime, serialized as ISO 8601 strings)\n\nSuccess conditions:\n * PipelineTemplateManager is initialized (even if no templates are loaded,\n an empty array is returned).\n\nFailure conditions:\n * Unexpected errors will be returned as 500 Internal Server Error.\n\nResponse example (200):\n .. code-block:: json\n\n [\n {\n \"id\": \"detect-only\",\n \"name\": \"Detect Only\",\n \"description\": \"Template pipeline with a single object detection model.\",\n \"source\": \"TEMPLATE\",\n \"tags\": [\"template\", \"detection\"],\n \"variants\": [\n {\n \"id\": \"cpu\",\n \"name\": \"CPU\",\n \"read_only\": true,\n \"pipeline_graph\": {},\n \"pipeline_graph_simple\": {},\n \"created_at\": \"2026-02-05T14:30:45.123000+00:00\",\n \"modified_at\": \"2026-02-05T14:30:45.123000+00:00\"\n }\n ],\n \"thumbnail\": null,\n \"created_at\": \"2026-02-05T14:30:45.123000+00:00\",\n \"modified_at\": \"2026-02-05T14:30:45.123000+00:00\"\n }\n ]",
"operationId": "get_pipeline_templates",
"responses": {
"200": {
"description": "List of all available pipeline templates",
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/Pipeline"
},
"type": "array",
"title": "Response 200 Get Pipeline Templates"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageResponse"
}
}
}
}
}
}
},
"/pipeline-templates/{template_id}": {
"get": {
"tags": [
"pipeline-templates"
],
"summary": "Get Pipeline Template",
"description": "Get a single pipeline template by its ID.\n\nOperation:\n Look up a template by its unique identifier and return it.\n\nPath / query parameters:\n template_id: Unique identifier of the template.\n\nReturns:\n 200 OK:\n Pipeline object with ``source=TEMPLATE``.\n Includes:\n * id, name, description, source, tags\n * variants (list of Variant objects with graphs and timestamps),\n all variants have ``read_only=True``\n * thumbnail (always null for templates)\n * created_at, modified_at (UTC datetime, serialized as ISO 8601 strings)\n 404 Not Found:\n MessageResponse if a template with the given ID does not exist.\n 500 Internal Server Error:\n MessageResponse when an unexpected error occurs.\n\nSuccess conditions:\n * Template with the given ID exists.\n\nFailure conditions:\n * Template with the given ID does not exist \u2013 404 Not Found.\n * Unexpected errors will be returned as 500 Internal Server Error.\n\nResponse example (200):\n .. code-block:: json\n\n {\n \"id\": \"detect-only\",\n \"name\": \"Detect Only\",\n \"description\": \"Template pipeline with a single object detection model.\",\n \"source\": \"TEMPLATE\",\n \"tags\": [\"template\", \"detection\"],\n \"variants\": [\n {\n \"id\": \"cpu\",\n \"name\": \"CPU\",\n \"read_only\": true,\n \"pipeline_graph\": {},\n \"pipeline_graph_simple\": {},\n \"created_at\": \"2026-02-05T14:30:45.123000+00:00\",\n \"modified_at\": \"2026-02-05T14:30:45.123000+00:00\"\n }\n ],\n \"thumbnail\": null,\n \"created_at\": \"2026-02-05T14:30:45.123000+00:00\",\n \"modified_at\": \"2026-02-05T14:30:45.123000+00:00\"\n }",
"operationId": "get_pipeline_template",
"parameters": [
{
"name": "template_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"title": "Template Id"
}
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pipeline"
}
}
}
},
"404": {
"description": "Template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageResponse"
}
}
}
},
"500": {
"description": "Internal server error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageResponse"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
}
}
}
}
},
"/pipelines": {
"get": {
"tags": [
Expand Down Expand Up @@ -2707,6 +2806,16 @@
},
"type": "array",
"title": "Profiles"
},
"best_profile": {
"anyOf": [
{
"$ref": "#/components/schemas/CameraProfileInfo"
},
{
"type": "null"
}
]
}
},
"type": "object",
Expand All @@ -2716,7 +2825,7 @@
"profiles"
],
"title": "NetworkCameraDetails",
"description": "Network camera specific details.\n\nAttributes:\n ip: IP address of the camera.\n port: Port number for ONVIF communication.\n profiles: List of ONVIF profiles available on this camera (populated after authentication)."
"description": "Network camera details including ONVIF profiles and the best\nprofile selected by the scoring algorithm.\n\nAttributes:\n ip: IP address of the camera.\n port: Port number for ONVIF communication.\n profiles: List of ONVIF profiles available on this camera (populated after authentication).\n best_profile: Best profile selected by scoring algorithm."
},
"Node": {
"properties": {
Expand Down Expand Up @@ -3497,7 +3606,8 @@
"type": "string",
"enum": [
"PREDEFINED",
"USER_CREATED"
"USER_CREATED",
"TEMPLATE"
],
"title": "PipelineSource"
},
Expand Down Expand Up @@ -3698,25 +3808,52 @@
"type": "string",
"title": "Device Path"
},
"resolution": {
"best_capture": {
"anyOf": [
{
"type": "string"
"$ref": "#/components/schemas/V4L2BestCapture"
},
{
"type": "null"
}
],
"title": "Resolution"
]
}
},
"type": "object",
"required": [
"device_path",
"resolution"
"device_path"
],
"title": "USBCameraDetails",
"description": "USB camera specific details.\n\nAttributes:\n device_path: System device path (e.g., /dev/video0).\n resolution: Supported or current resolution (optional, e.g., \"1920x1080\")."
"description": "USB camera details including the best capture configuration\nselected by the scoring algorithm.\n\nAttributes:\n device_path: System device path (e.g., /dev/video0).\n best_capture: Best capture configuration selected by scoring algorithm."
},
"V4L2BestCapture": {
"properties": {
"fourcc": {
"type": "string",
"title": "Fourcc"
},
"width": {
"type": "integer",
"title": "Width"
},
"height": {
"type": "integer",
"title": "Height"
},
"fps": {
"type": "number",
"title": "Fps"
}
},
"type": "object",
"required": [
"fourcc",
"width",
"height",
"fps"
],
"title": "V4L2BestCapture",
"description": "Best capture configuration selected from available V4L2 formats."
},
"ValidationError": {
"properties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class PipelineSource(str, Enum):
PREDEFINED = "PREDEFINED"
USER_CREATED = "USER_CREATED"
TEMPLATE = "TEMPLATE"


class AppStatus(str, Enum):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from api.routes import health, metrics
from managers.app_state_manager import AppStateManager
from managers.pipeline_manager import PipelineManager
from managers.pipeline_template_manager import PipelineTemplateManager
from videos import VideosManager

# Configure logging
Expand Down Expand Up @@ -54,6 +55,9 @@ def _initialize_in_background(app: FastAPI) -> None:
# Initialize PipelineManager - loads predefined pipelines
PipelineManager()

# Initialize PipelineTemplateManager - loads pipeline templates
PipelineTemplateManager()

# Register remaining routers after VideosManager and PipelineManager are initialized
register_routers(app)

Expand All @@ -78,6 +82,7 @@ def register_routers(app: FastAPI) -> None:
devices,
jobs,
models,
pipeline_templates,
pipelines,
tests,
videos,
Expand All @@ -89,6 +94,11 @@ def register_routers(app: FastAPI) -> None:
app.include_router(devices.router, prefix="/devices", tags=["devices"])
app.include_router(jobs.router, prefix="/jobs", tags=["jobs"])
app.include_router(models.router, prefix="/models", tags=["models"])
app.include_router(
pipeline_templates.router,
prefix="/pipeline-templates",
tags=["pipeline-templates"],
)
app.include_router(pipelines.router, prefix="/pipelines", tags=["pipelines"])
app.include_router(tests.router, prefix="/tests", tags=["tests"])
app.include_router(videos.router, prefix="/videos", tags=["videos"])
Expand Down
Loading
Loading