feat(scada): add calibrated monitoring and incident recovery
This commit is contained in:
@@ -5,8 +5,10 @@ import re
|
||||
from typing import Annotated, Literal
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import Field, JsonValue, model_validator
|
||||
from app.domain.schemas.answer_ui import ReportUiBlock, validate_report_ui_blocks
|
||||
from pydantic import Field, JsonValue, model_serializer, model_validator
|
||||
from app.domain.schemas.answer_ui import (
|
||||
CHART_SAMPLE_TIME_PATTERN, ReportUiBlock, validate_chart_sample_time, validate_report_ui_blocks,
|
||||
)
|
||||
|
||||
from app.domain.schemas.task_question import TaskQuestionRequest
|
||||
from app.domain.schemas.shared import NonEmptyStr, PositiveInt, StrictBool, StrictModel
|
||||
@@ -588,6 +590,7 @@ class OperationalTaskSummary(StrictModel):
|
||||
execution_request_id: UUID
|
||||
title: NonEmptyStr
|
||||
summary: NonEmptyStr
|
||||
handling_context: dict[str, JsonValue] = Field(default_factory=dict)
|
||||
source: TaskSource
|
||||
trigger: TaskTrigger
|
||||
scheduled_for: WorkbenchDateTime | None
|
||||
@@ -692,15 +695,42 @@ class AgentArtifactsResult(StrictModel):
|
||||
|
||||
class TaskSafeChartSeries(StrictModel):
|
||||
name: Annotated[str, Field(max_length=128)]
|
||||
data: Annotated[list[Annotated[float, Field(strict=True, allow_inf_nan=False)]], Field(min_length=1, max_length=100)]
|
||||
type: Literal["line", "bar", "scatter"] | None = None
|
||||
data: Annotated[list[Annotated[float, Field(strict=True, allow_inf_nan=False)] | None], Field(min_length=1, max_length=100)]
|
||||
sample_times: Annotated[list[Annotated[str, Field(
|
||||
strict=True, max_length=64,
|
||||
pattern=CHART_SAMPLE_TIME_PATTERN,
|
||||
)] | None], Field(min_length=1, max_length=100)] | None = None
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_optional_fields(self, handler):
|
||||
return {key: value for key, value in handler(self).items() if value is not None}
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_sample_times(self):
|
||||
if self.sample_times is not None:
|
||||
if len(self.sample_times) != len(self.data):
|
||||
raise ValueError("chart sample_times must align with data")
|
||||
for value, at in zip(self.data, self.sample_times, strict=True):
|
||||
if at is not None:
|
||||
if value is None:
|
||||
raise ValueError("chart sample_times require an observed value")
|
||||
validate_chart_sample_time(at)
|
||||
return self
|
||||
|
||||
|
||||
class TaskSafeChart(StrictModel):
|
||||
title: Annotated[str, Field(max_length=200)]
|
||||
chart_type: Literal["line", "bar"]
|
||||
x_axis_name: Annotated[str, Field(max_length=128)] | None = None
|
||||
y_axis_name: Annotated[str, Field(max_length=128)] | None = None
|
||||
x_data: Annotated[list[Annotated[str, Field(max_length=128)]], Field(min_length=1, max_length=100)]
|
||||
series: Annotated[list[TaskSafeChartSeries], Field(min_length=1, max_length=8)]
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def serialize_optional_fields(self, handler):
|
||||
return {key: value for key, value in handler(self).items() if value is not None}
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_alignment(self):
|
||||
if any(len(series.data) != len(self.x_data) for series in self.series):
|
||||
|
||||
Reference in New Issue
Block a user