feat(investigations): add event impact and work-order feedback flows
Add isolated burst and pollution impact evidence, parallel work-order workflows, persisted notifications and graph updates. Checkpoint current code. Known follow-ups remain for large pollution result previews and graceful geometry failure.
This commit is contained in:
@@ -5,8 +5,34 @@ from uuid import NAMESPACE_URL, uuid5
|
||||
from app.mcp.models import QueryResult
|
||||
|
||||
|
||||
def saved_burst_result_preview(result: QueryResult, task_id: str) -> dict | None:
|
||||
"""Keep durable full-network results usable without copying node arrays inline."""
|
||||
if result.source != "run_burst_simulation" or not result.evidence_id:
|
||||
return None
|
||||
data = result.data if isinstance(result.data, dict) else {}
|
||||
analysis = data.get("result", {})
|
||||
impact = analysis.get("impact") if isinstance(analysis, dict) else None
|
||||
if not isinstance(impact, dict):
|
||||
return None
|
||||
summary = {key: value for key, value in impact.items()
|
||||
if key not in {"comparisons", "grades", "unavailable_node_ids"}}
|
||||
summary["unavailable_node_count"] = len(impact.get("unavailable_node_ids", []))
|
||||
summary["grades"] = [
|
||||
{**{key: value for key, value in grade.items() if key != "node_ids"},
|
||||
"node_count": len(grade.get("node_ids", []))} for grade in impact.get("grades", [])
|
||||
]
|
||||
preview = {
|
||||
"resource_uri": f"tjwater://tasks/{task_id}/evidence/{result.evidence_id}",
|
||||
"parameters": data.get("parameters", {}), "result": {"impact": summary},
|
||||
}
|
||||
presentation = saved_presentation_preview(result)
|
||||
if presentation is not None:
|
||||
preview["presentation"] = presentation
|
||||
return preview
|
||||
|
||||
|
||||
def saved_presentation_preview(result: QueryResult) -> dict | None:
|
||||
if result.source != "generate_node_coverage" or not result.evidence_id:
|
||||
if result.source not in {"generate_node_coverage", "run_burst_simulation", "run_contaminant_simulation"} or not result.evidence_id:
|
||||
return None
|
||||
analysis = result.data.get("result") if isinstance(result.data, dict) else None
|
||||
if not isinstance(analysis, dict):
|
||||
@@ -15,11 +41,18 @@ def saved_presentation_preview(result: QueryResult) -> dict | None:
|
||||
if not isinstance(payload, dict) or not payload.get("features"):
|
||||
return None
|
||||
coverage = analysis.get("coverage", {})
|
||||
burst = result.source == "run_burst_simulation"
|
||||
contaminant = result.source == "run_contaminant_simulation"
|
||||
if burst and analysis.get("impact", {}).get("phase") != "after_burst_before_intervention":
|
||||
return None
|
||||
if contaminant and analysis.get("impact", {}).get("phase") != "after_contamination_before_intervention":
|
||||
return None
|
||||
return {
|
||||
"command": {
|
||||
"action": "set_overlay", "mode": "geometry", "evidence_id": result.evidence_id,
|
||||
"overlay_id": f"node-coverage-{uuid5(NAMESPACE_URL, result.evidence_id)}",
|
||||
"title": "节点空间覆盖示意",
|
||||
"title": ("爆管后、处置前的预计影响范围(米水头)" if burst else
|
||||
"水污染传播预计影响范围(处置前情景)" if contaminant else "节点空间覆盖示意"),
|
||||
},
|
||||
"display_only": True,
|
||||
"coverage_status": coverage.get("status"),
|
||||
|
||||
Reference in New Issue
Block a user