feat: reconcile legacy message identities
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / pytest-smoke (push) Failing after 2s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a0230c-b06c-7641-808a-e191b6d1da49
This commit is contained in:
tegwick 2026-08-23 11:59:52 +02:00
parent ab936a1e98
commit ed3feed310
13 changed files with 693 additions and 10 deletions

View file

@ -1,4 +1,3 @@
import uuid
from collections.abc import Callable
from datetime import datetime, timezone
from typing import Any
@ -8,6 +7,8 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from hub_core.models.agent_message import AgentMessage
from hub_core.models.message_identity_alias import MessageIdentityAlias
from hub_core.message_identity import resolve_message_reference
from hub_core.schemas.agent_message import MessageCreate, MessageRead, MessageReply
@ -15,13 +16,27 @@ def create_messages_router(
get_session: Callable[..., AsyncSession],
*,
message_model: type[AgentMessage] = AgentMessage,
message_alias_model: type[MessageIdentityAlias] | None = MessageIdentityAlias,
) -> APIRouter:
router = APIRouter(prefix="/messages", tags=["messages"])
async def _get_message(message_id: uuid.UUID, session: AsyncSession) -> Any:
async def _get_message(message_reference: str, session: AsyncSession) -> Any:
message_id = await resolve_message_reference(
session,
message_reference,
alias_model=message_alias_model,
)
if message_id is None:
raise HTTPException(
status_code=404,
detail=f"Message reference {message_reference!r} not found",
)
msg = await session.get(message_model, message_id)
if msg is None:
raise HTTPException(status_code=404, detail=f"Message {message_id} not found")
raise HTTPException(
status_code=404,
detail=f"Message reference {message_reference!r} not found",
)
return msg
@router.post("/", response_model=MessageRead, status_code=status.HTTP_201_CREATED)
@ -62,18 +77,29 @@ def create_messages_router(
@router.get("/thread/{thread_id}", response_model=list[MessageRead])
async def get_thread(
thread_id: uuid.UUID,
thread_id: str,
session: AsyncSession = Depends(get_session),
) -> list[Any]:
resolved_thread_id = await resolve_message_reference(
session,
thread_id,
alias_model=message_alias_model,
)
if resolved_thread_id is None:
raise HTTPException(
status_code=404,
detail=f"Message reference {thread_id!r} not found",
)
q = select(message_model).where(
(message_model.id == thread_id) | (message_model.thread_id == thread_id)
(message_model.id == resolved_thread_id)
| (message_model.thread_id == resolved_thread_id)
).order_by(message_model.created_at)
result = await session.execute(q)
return list(result.scalars().all())
@router.patch("/{message_id}/read", response_model=MessageRead)
async def mark_read(
message_id: uuid.UUID,
message_id: str,
session: AsyncSession = Depends(get_session),
) -> Any:
msg = await _get_message(message_id, session)
@ -85,7 +111,7 @@ def create_messages_router(
@router.patch("/{message_id}/archive", response_model=MessageRead)
async def archive_message(
message_id: uuid.UUID,
message_id: str,
session: AsyncSession = Depends(get_session),
) -> Any:
msg = await _get_message(message_id, session)
@ -98,7 +124,7 @@ def create_messages_router(
@router.post("/{message_id}/reply", response_model=MessageRead, status_code=status.HTTP_201_CREATED)
async def reply_to_message(
message_id: uuid.UUID,
message_id: str,
body: MessageReply,
session: AsyncSession = Depends(get_session),
) -> Any: