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
+59
View File
@@ -0,0 +1,59 @@
"""Private, durable messages between an ordinary chat and one investigation run."""
from typing import Annotated, Literal
from uuid import UUID
from pydantic import Field
from app.domain.schemas.shared import NonEmptyStr, StrictModel
from app.domain.schemas.workbench_runtime import WorkbenchDateTime
MessageText = Annotated[str, Field(min_length=1, max_length=12000, pattern=r"\S")]
MessageStatus = Literal["pending", "enqueued", "delivered", "failed"]
class AgentMessageCreate(StrictModel):
request_id: UUID
task_id: UUID
run_id: UUID
source_session_id: NonEmptyStr
text: MessageText
class AgentMessageReply(StrictModel):
request_id: UUID
source_session_id: NonEmptyStr
text: MessageText
class AgentMessageDelivery(StrictModel):
status: Literal["enqueued", "delivered", "failed"]
target_session_id: NonEmptyStr | None = None
native_message_id: NonEmptyStr | None = None
failure_detail: Annotated[str, Field(max_length=500)] | None = None
class AgentMessage(StrictModel):
project_id: UUID
message_id: UUID
request_id: UUID
task_id: UUID
run_id: UUID
source_session_id: NonEmptyStr
source_owner_id: UUID
conversation_owner_id: UUID
target_session_id: NonEmptyStr | None = None
direction: Literal["to_task", "to_chat"]
in_reply_to: UUID | None = None
text: MessageText
status: MessageStatus
native_message_id: NonEmptyStr
failure_detail: str | None = None
created_at: WorkbenchDateTime
updated_at: WorkbenchDateTime
delivered_at: WorkbenchDateTime | None = None
class AgentMessagePage(StrictModel):
items: list[AgentMessage]
next_cursor: str | None = None