feat(server): integrate MCP queries and investigation messaging

Add project-bound OAuth MCP queries and controlled analysis with scoped evidence,
limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs.
Default nearby searches to 200 meters and five results.

Integrate investigation messaging/presentation, health/readiness and typed history;
remove duplicate web search and fix online simulation and compressed baseline writes.
Include project migrations 023-025; keep local credentials and demo seeding excluded.

Validation: 319 focused pytest checks; real PostGIS temporary-table regression;
read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
This commit is contained in:
2026-10-19 18:46:58 +08:00
parent 2b6fc5aa52
commit be6317eb48
117 changed files with 12703 additions and 638 deletions
+11 -12
View File
@@ -31,6 +31,7 @@ def _load_simulation_module(monkeypatch):
{
"get_time": lambda name: {"HYDRAULIC TIMESTEP": "0:15:00"},
"run_simulation": lambda **kwargs: None,
"run_online_simulation": lambda **kwargs: None,
"query_corresponding_element_id_and_query_id": lambda name: SimpleNamespace(
fixed_pumps={}, variable_pumps={}
),
@@ -145,13 +146,13 @@ def test_pressure_regulation_requires_scheme_name(monkeypatch):
assert response.status_code == 422
def test_run_simulation_manually_by_date_uses_utc_aware_timestamps(monkeypatch):
def test_run_simulation_manually_by_date_passes_aware_time_and_converts_minutes(monkeypatch):
module = _load_simulation_module(monkeypatch)
captured_calls = []
monkeypatch.setattr(
module.simulation,
"run_simulation",
"run_online_simulation",
lambda **kwargs: captured_calls.append(kwargs),
)
@@ -161,13 +162,13 @@ def test_run_simulation_manually_by_date_uses_utc_aware_timestamps(monkeypatch):
30,
)
assert [call["modify_pattern_start_time"] for call in captured_calls] == [
"2025-01-01T19:04:05+00:00",
"2025-01-01T19:19:05+00:00",
]
assert captured_calls == [{
"name": "demo", "start_time": datetime(2025, 1, 1, 19, 4, 5, tzinfo=timezone.utc),
"duration_seconds": 1800,
}]
def test_run_simulation_manually_by_date_uses_hydraulic_timestep(monkeypatch):
def test_run_simulation_manually_by_date_preserves_two_hour_window(monkeypatch):
module = _load_simulation_module(monkeypatch)
captured_calls = []
@@ -178,7 +179,7 @@ def test_run_simulation_manually_by_date_uses_hydraulic_timestep(monkeypatch):
)
monkeypatch.setattr(
module.simulation,
"run_simulation",
"run_online_simulation",
lambda **kwargs: captured_calls.append(kwargs),
)
@@ -188,10 +189,8 @@ def test_run_simulation_manually_by_date_uses_hydraulic_timestep(monkeypatch):
120,
)
assert [call["modify_pattern_start_time"] for call in captured_calls] == [
"2025-01-01T16:00:00+00:00",
"2025-01-01T17:00:00+00:00",
]
assert captured_calls[0]["duration_seconds"] == 7200
assert captured_calls[0]["start_time"] == datetime(2025, 1, 1, 16, 0, 0, tzinfo=timezone.utc)
def test_runsimulationmanuallybydate_endpoint_accepts_timezone_aware_start_time(monkeypatch):