Skip to content

symfonic.platform.transport_input

transport_input

Validate native HTTP turn inputs without giving browser history authority.

history_of

history_of(payload: dict[str, Any]) -> tuple[Any, ...]

Validate caller history only for deployments with no chat store.

Source code in src/symfonic/platform/transport_input.py
def history_of(payload: dict[str, Any]) -> tuple[Any, ...]:
    """Validate caller history only for deployments with no chat store."""
    from fastapi import HTTPException

    raw = payload.get("history", ())
    if raw in (None, ()):
        return ()
    if not isinstance(raw, list) or len(raw) > 100:
        raise HTTPException(422, "history must be a list of at most 100 messages")
    from symfonic.agent.facade_types import Message

    parsed = []
    for item in raw:
        if not isinstance(item, dict):
            raise HTTPException(422, "invalid history message")
        _refuse_history_attachments(item)
        role, content = item.get("role"), item.get("content")
        if role not in ("user", "assistant") or not isinstance(content, str):
            raise HTTPException(
                422, "history messages require a user/assistant role and text content",
            )
        parsed.append(Message(role=role, content=content))
    return tuple(parsed)

refuse_attachments

refuse_attachments(payload: dict[str, Any]) -> None

Refuse attachments instead of silently answering without them (CORE-390).

Forwarding needs a replay contract for persisted chats (CORE-387) and a body cap enforced before JSON parsing; neither exists on this route. Only an absent key, null or [] means "no attachments". The detail never echoes the payload, which may carry private file bytes.

Source code in src/symfonic/platform/transport_input.py
def refuse_attachments(payload: dict[str, Any]) -> None:
    """Refuse attachments instead of silently answering without them (CORE-390).

    Forwarding needs a replay contract for persisted chats (CORE-387) and a
    body cap enforced before JSON parsing; neither exists on this route. Only
    an absent key, ``null`` or ``[]`` means "no attachments". The detail never
    echoes the payload, which may carry private file bytes.
    """
    from fastapi import HTTPException

    if payload.get("attachments") in (None, []):
        return
    raise HTTPException(422, "attachments are not supported on this route; send text only")