feat(scada): add calibrated monitoring and incident recovery

This commit is contained in:
2026-11-07 19:44:58 +08:00
parent 26fa5d1909
commit ff8aba4964
109 changed files with 9165 additions and 629 deletions
+13 -4
View File
@@ -32,6 +32,8 @@ from app.mcp.catalog import TOOLS
from app.mcp.config import McpSettings
from app.mcp.contexts import resolve_context, verify_task
from app.mcp.models import QueryResult
from app.mcp.display_time import display_query_result, display_time_text
from app.mcp.scada_catalog import compact_scada_catalog
from app.mcp.errors import CalculationCapacityExceeded
from app.mcp.scope import project_scope
from app.mcp.query_service import execute_query, task_service, authorize_query
@@ -43,6 +45,7 @@ logger = logging.getLogger(__name__)
def tool_error(code, message):
message = display_time_text(message)
return types.CallToolResult(
isError=True,
content=[types.TextContent(type="text", text=message)],
@@ -358,7 +361,8 @@ class McpQueryApplication:
result = QueryResult.model_validate(previous["result"])
else:
from app.mcp.calculation_jobs import should_queue, submit_calculation
if should_queue(tool, args):
queued = should_queue(tool, args, project_code=getattr(scope.project, "project_code", None))
if queued:
result = await submit_calculation(
scope, binding, tool, args, call_id,
job_timeout_seconds=self.settings.max_calculation_timeout_seconds,
@@ -377,7 +381,7 @@ class McpQueryApplication:
"RESULT_TOO_LARGE",
"Narrow the query or request a smaller page",
)
if binding.task_id and not should_queue(tool, args) and name not in {
if binding.task_id and not queued and name not in {
"get_calculation_job", "get_calculation_result", "cancel_calculation_job", "list_calculation_jobs",
"get_task_context",
"get_task_evidence",
@@ -422,9 +426,14 @@ class McpQueryApplication:
parameters,
result.model_dump(mode="json"),
)
output = result.model_dump(mode="json")
output = display_query_result(result.model_dump(mode="json"))
content = []
from app.mcp.extended_service import ARTIFACT_TOOLS
if (not include_full and name == "list_scada_devices"
and len(json.dumps(output, ensure_ascii=False).encode()) > 12000):
preview = compact_scada_catalog(output, budget=12000)
if preview is not None:
output = preview
if (
not include_full
and name not in ARTIFACT_TOOLS
@@ -444,7 +453,7 @@ class McpQueryApplication:
from app.mcp.presentation_preview import saved_presentation_preview
presentation = saved_presentation_preview(result)
if presentation is not None:
output["data"]["presentation"] = presentation
output["data"]["presentation"] = display_query_result(presentation)
output["truncated"] = True
output["data_gaps"] = [
*result.data_gaps,