fix: Checkpoint changing metamessage schema
This commit is contained in:
parent
25c8058bae
commit
84c9f81273
141
src/crud.py
141
src/crud.py
|
|
@ -581,6 +581,8 @@ async def clone_session(
|
|||
# Prepare bulk insert data for metamessages
|
||||
new_metamessages = [
|
||||
{
|
||||
"user_id": user_id,
|
||||
"session_id": new_session.public_id,
|
||||
"message_id": message_id_map[meta.message_id],
|
||||
"metamessage_type": meta.metamessage_type,
|
||||
"content": meta.content,
|
||||
|
|
@ -744,29 +746,49 @@ async def create_metamessage(
|
|||
db: AsyncSession,
|
||||
metamessage: schemas.MetamessageCreate,
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
):
|
||||
message = await get_message(
|
||||
db,
|
||||
app_id=app_id,
|
||||
session_id=session_id,
|
||||
user_id=user_id,
|
||||
message_id=metamessage.message_id,
|
||||
)
|
||||
if message is None:
|
||||
raise ValueError("Session not found or does not belong to user")
|
||||
|
||||
honcho_metamessage = models.Metamessage(
|
||||
message_id=metamessage.message_id,
|
||||
metamessage_type=metamessage.metamessage_type,
|
||||
content=metamessage.content,
|
||||
h_metadata=metamessage.metadata,
|
||||
)
|
||||
|
||||
# Validate user exists
|
||||
user = await get_user(db, app_id=app_id, user_id=metamessage.user_id)
|
||||
if user is None:
|
||||
raise ResourceNotFoundException(f"User with ID '{metamessage.user_id}' not found")
|
||||
|
||||
# Initialize metamessage data
|
||||
metamessage_data = {
|
||||
"user_id": metamessage.user_id,
|
||||
"metamessage_type": metamessage.metamessage_type,
|
||||
"content": metamessage.content,
|
||||
"h_metadata": metamessage.metadata,
|
||||
}
|
||||
|
||||
# Validate session_id if provided
|
||||
if metamessage.session_id is not None:
|
||||
session = await get_session(
|
||||
db, app_id=app_id, user_id=metamessage.user_id, session_id=metamessage.session_id
|
||||
)
|
||||
if session is None:
|
||||
raise ResourceNotFoundException(f"Session not found or does not belong to user")
|
||||
metamessage_data["session_id"] = metamessage.session_id
|
||||
|
||||
# Validate message_id if provided
|
||||
if metamessage.message_id is not None:
|
||||
message = await get_message(
|
||||
db,
|
||||
app_id=app_id,
|
||||
session_id=metamessage.session_id,
|
||||
user_id=metamessage.user_id,
|
||||
message_id=metamessage.message_id,
|
||||
)
|
||||
if message is None:
|
||||
raise ResourceNotFoundException(f"Message not found or does not belong to session")
|
||||
metamessage_data["message_id"] = metamessage.message_id
|
||||
elif metamessage.message_id is not None:
|
||||
# If message_id provided but no session_id, that's an error
|
||||
raise ValidationException("Cannot specify message_id without session_id")
|
||||
|
||||
# Create metamessage
|
||||
honcho_metamessage = models.Metamessage(**metamessage_data)
|
||||
db.add(honcho_metamessage)
|
||||
await db.commit()
|
||||
# await db.refresh(honcho_metamessage)
|
||||
return honcho_metamessage
|
||||
|
||||
|
||||
|
|
@ -780,28 +802,32 @@ async def get_metamessages(
|
|||
filter: Optional[dict] = None,
|
||||
reverse: Optional[bool] = False,
|
||||
) -> Select:
|
||||
# Base query starts with metamessage and user relationship
|
||||
stmt = (
|
||||
select(models.Metamessage)
|
||||
.join(models.Message, models.Message.public_id == models.Metamessage.message_id)
|
||||
.join(models.Session, models.Message.session_id == models.Session.public_id)
|
||||
.join(models.User, models.User.public_id == models.Session.user_id)
|
||||
.join(models.User, models.User.public_id == models.Metamessage.user_id)
|
||||
.join(models.App, models.App.public_id == models.User.app_id)
|
||||
.where(models.App.public_id == app_id)
|
||||
.where(models.User.public_id == user_id)
|
||||
)
|
||||
|
||||
# If session_id is provided, filter by it
|
||||
if session_id is not None:
|
||||
stmt = stmt.where(models.Session.public_id == session_id)
|
||||
stmt = stmt.where(models.Metamessage.session_id == session_id)
|
||||
|
||||
# If message_id is provided, filter by it
|
||||
if message_id is not None:
|
||||
stmt = stmt.where(models.Metamessage.message_id == message_id)
|
||||
|
||||
# Filter by metamessage_type if provided
|
||||
if metamessage_type is not None:
|
||||
stmt = stmt.where(models.Metamessage.metamessage_type == metamessage_type)
|
||||
|
||||
# Apply metadata filter if provided
|
||||
if filter is not None:
|
||||
stmt = stmt.where(models.Metamessage.h_metadata.contains(filter))
|
||||
|
||||
# Apply sort order
|
||||
if reverse:
|
||||
stmt = stmt.order_by(models.Metamessage.id.desc())
|
||||
else:
|
||||
|
|
@ -814,22 +840,28 @@ async def get_metamessage(
|
|||
db: AsyncSession,
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
message_id: str,
|
||||
metamessage_id: str,
|
||||
session_id: Optional[str] = None,
|
||||
message_id: Optional[str] = None,
|
||||
) -> Optional[models.Metamessage]:
|
||||
# Base query for metamessage by ID
|
||||
stmt = (
|
||||
select(models.Metamessage)
|
||||
.join(models.Message, models.Message.public_id == models.Metamessage.message_id)
|
||||
.join(models.Session, models.Message.session_id == models.Session.public_id)
|
||||
.join(models.User, models.User.public_id == models.Session.user_id)
|
||||
.join(models.User, models.User.public_id == models.Metamessage.user_id)
|
||||
.join(models.App, models.App.public_id == models.User.app_id)
|
||||
.where(models.App.public_id == app_id)
|
||||
.where(models.User.public_id == user_id)
|
||||
.where(models.Message.session_id == session_id)
|
||||
.where(models.Metamessage.message_id == message_id)
|
||||
.where(models.Metamessage.public_id == metamessage_id)
|
||||
)
|
||||
|
||||
# Add session filter if provided
|
||||
if session_id is not None:
|
||||
stmt = stmt.where(models.Metamessage.session_id == session_id)
|
||||
|
||||
# Add message filter if provided
|
||||
if message_id is not None:
|
||||
stmt = stmt.where(models.Metamessage.message_id == message_id)
|
||||
|
||||
result = await db.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
|
|
@ -838,28 +870,55 @@ async def update_metamessage(
|
|||
db: AsyncSession,
|
||||
metamessage: schemas.MetamessageUpdate,
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
metamessage_id: str,
|
||||
) -> bool:
|
||||
# First retrieve the metamessage
|
||||
honcho_metamessage = await get_metamessage(
|
||||
db,
|
||||
app_id=app_id,
|
||||
session_id=session_id,
|
||||
user_id=user_id,
|
||||
message_id=metamessage.message_id,
|
||||
user_id=metamessage.user_id,
|
||||
metamessage_id=metamessage_id,
|
||||
session_id=metamessage.session_id,
|
||||
message_id=metamessage.message_id,
|
||||
)
|
||||
|
||||
if honcho_metamessage is None:
|
||||
raise ValueError("Metamessage not found or does not belong to user")
|
||||
if (
|
||||
metamessage.metadata is not None
|
||||
): # Need to explicitly be there won't make it empty by default
|
||||
raise ResourceNotFoundException("Metamessage not found or does not belong to user")
|
||||
|
||||
# Validate the consistency of relationships if they're being changed
|
||||
# If we're setting message_id, we must have a session_id
|
||||
if metamessage.message_id is not None and metamessage.session_id is None:
|
||||
# If updating message_id but not session_id, use the existing session_id
|
||||
metamessage.session_id = honcho_metamessage.session_id
|
||||
if metamessage.session_id is None:
|
||||
raise ValidationException("Cannot specify message_id without session_id")
|
||||
|
||||
# If we're updating session_id and message_id, validate they belong together
|
||||
if metamessage.session_id is not None and metamessage.message_id is not None:
|
||||
message = await get_message(
|
||||
db,
|
||||
app_id=app_id,
|
||||
session_id=metamessage.session_id,
|
||||
user_id=metamessage.user_id,
|
||||
message_id=metamessage.message_id,
|
||||
)
|
||||
if message is None:
|
||||
raise ResourceNotFoundException("Message not found or doesn't belong to session")
|
||||
|
||||
# Update fields
|
||||
if metamessage.session_id is not None:
|
||||
honcho_metamessage.session_id = metamessage.session_id
|
||||
|
||||
if metamessage.message_id is not None:
|
||||
honcho_metamessage.message_id = metamessage.message_id
|
||||
|
||||
if metamessage.metadata is not None:
|
||||
honcho_metamessage.h_metadata = metamessage.metadata
|
||||
|
||||
if metamessage.metamessage_type is not None:
|
||||
honcho_metamessage.metamessage_type = metamessage.metamessage_type
|
||||
|
||||
await db.commit()
|
||||
# await db.refresh(honcho_metamessage)
|
||||
return honcho_metamessage
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ app.include_router(users.router, prefix="/v1")
|
|||
app.include_router(sessions.router, prefix="/v1")
|
||||
app.include_router(messages.router, prefix="/v1")
|
||||
app.include_router(metamessages.router, prefix="/v1")
|
||||
app.include_router(metamessages.router_user_level, prefix="/v1")
|
||||
app.include_router(collections.router, prefix="/v1")
|
||||
app.include_router(documents.router, prefix="/v1")
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class User(Base):
|
|||
app = relationship("App", back_populates="users")
|
||||
sessions = relationship("Session", back_populates="user")
|
||||
collections = relationship("Collection", back_populates="user")
|
||||
metamessages = relationship("Metamessage", back_populates="user")
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("name", "app_id", name="unique_name_app_user"),
|
||||
|
|
@ -89,6 +90,7 @@ class Session(Base):
|
|||
DateTime(timezone=True), index=True, default=func.now()
|
||||
)
|
||||
messages = relationship("Message", back_populates="session")
|
||||
metamessages = relationship("Metamessage", back_populates="session")
|
||||
user_id: Mapped[str] = mapped_column(ForeignKey("users.public_id"), index=True)
|
||||
user = relationship("User", back_populates="sessions")
|
||||
|
||||
|
|
@ -149,11 +151,23 @@ class Metamessage(Base):
|
|||
)
|
||||
metamessage_type: Mapped[str] = mapped_column(TEXT, index=True)
|
||||
content: Mapped[str] = mapped_column(TEXT)
|
||||
message_id: Mapped[str] = mapped_column(
|
||||
ForeignKey("messages.public_id"), index=True
|
||||
|
||||
# Foreign keys - message_id is now optional
|
||||
user_id: Mapped[str] = mapped_column(
|
||||
ForeignKey("users.public_id"), index=True
|
||||
)
|
||||
session_id: Mapped[str | None] = mapped_column(
|
||||
ForeignKey("sessions.public_id"), index=True, nullable=True
|
||||
)
|
||||
message_id: Mapped[str | None] = mapped_column(
|
||||
ForeignKey("messages.public_id"), index=True, nullable=True
|
||||
)
|
||||
|
||||
# Relationships
|
||||
user = relationship("User", back_populates="metamessages")
|
||||
session = relationship("Session", back_populates="metamessages")
|
||||
message = relationship("Message", back_populates="metamessages")
|
||||
|
||||
created_at: Mapped[datetime.datetime] = mapped_column(
|
||||
DateTime(timezone=True), index=True, default=func.now()
|
||||
)
|
||||
|
|
@ -166,16 +180,41 @@ class Metamessage(Base):
|
|||
CheckConstraint(
|
||||
"length(metamessage_type) <= 512", name="metamessage_type_length"
|
||||
),
|
||||
# Added constraints to ensure consistency
|
||||
CheckConstraint(
|
||||
"(message_id IS NULL) OR (session_id IS NOT NULL)",
|
||||
name="message_requires_session"
|
||||
),
|
||||
# Keep existing index
|
||||
Index(
|
||||
"idx_metamessages_lookup",
|
||||
"metamessage_type",
|
||||
text("id DESC"),
|
||||
postgresql_include=["public_id", "message_id", "created_at"],
|
||||
),
|
||||
# Add new indices for user, session, and message lookups
|
||||
Index(
|
||||
"idx_metamessages_user_lookup",
|
||||
"user_id",
|
||||
"metamessage_type",
|
||||
text("id DESC"),
|
||||
),
|
||||
Index(
|
||||
"idx_metamessages_session_lookup",
|
||||
"session_id",
|
||||
"metamessage_type",
|
||||
text("id DESC"),
|
||||
),
|
||||
Index(
|
||||
"idx_metamessages_message_lookup",
|
||||
"message_id",
|
||||
"metamessage_type",
|
||||
text("id DESC"),
|
||||
),
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Metamessages(id={self.id}, message_id={self.message_id}, metamessage_type={self.metamessage_type}, content={self.content[10:]})"
|
||||
return f"Metamessages(id={self.id}, user_id={self.user_id}, session_id={self.session_id}, message_id={self.message_id}, metamessage_type={self.metamessage_type})"
|
||||
|
||||
|
||||
class Collection(Base):
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ from src.security import auth
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/apps/{app_id}/users/{user_id}/sessions/{session_id}/metamessages",
|
||||
tags=["metamessages"],
|
||||
dependencies=[Depends(auth)],
|
||||
)
|
||||
|
||||
router_user_level = APIRouter(
|
||||
prefix="/apps/{app_id}/users/{user_id}/metamessages",
|
||||
tags=["metamessages"],
|
||||
dependencies=[Depends(auth)],
|
||||
|
|
@ -29,42 +23,53 @@ router_user_level = APIRouter(
|
|||
async def create_metamessage(
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
metamessage: schemas.MetamessageCreate,
|
||||
db=db,
|
||||
):
|
||||
"""Adds a message to a session"""
|
||||
"""
|
||||
Create a new metamessage associated with a user.
|
||||
Optionally link to a session and message by providing those IDs in the request body.
|
||||
"""
|
||||
try:
|
||||
# Set the user_id from the URL parameters
|
||||
metamessage.user_id = user_id
|
||||
|
||||
metamessage_obj = await crud.create_metamessage(
|
||||
db,
|
||||
metamessage=metamessage,
|
||||
app_id=app_id,
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
)
|
||||
logger.info(f"Metamessage created successfully for session {session_id}")
|
||||
logger.info(f"Metamessage created successfully for user {user_id}")
|
||||
return metamessage_obj
|
||||
except ValueError as e:
|
||||
logger.warning(f"Failed to create metamessage for session {session_id}: {str(e)}")
|
||||
raise ResourceNotFoundException("Session not found") from e
|
||||
except (ResourceNotFoundException, ValidationException) as e:
|
||||
logger.warning(f"Failed to create metamessage: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@router.post("/list", response_model=Page[schemas.Metamessage])
|
||||
async def get_metamessages(
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
options: schemas.MetamessageGet,
|
||||
reverse: Optional[bool] = False,
|
||||
db=db,
|
||||
):
|
||||
"""Get all messages for a session"""
|
||||
"""
|
||||
Get metamessages with flexible filtering.
|
||||
|
||||
- Filter by user only: No additional parameters needed
|
||||
- Filter by session: Provide session_id
|
||||
- Filter by message: Provide message_id (and session_id)
|
||||
- Filter by type: Provide metamessage_type
|
||||
- Filter by metadata: Provide filter object
|
||||
"""
|
||||
try:
|
||||
# Use user_id from URL path
|
||||
metamessages_query = await crud.get_metamessages(
|
||||
db,
|
||||
app_id=app_id,
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
session_id=options.session_id,
|
||||
message_id=options.message_id,
|
||||
metamessage_type=options.metamessage_type,
|
||||
filter=options.filter,
|
||||
|
|
@ -72,34 +77,9 @@ async def get_metamessages(
|
|||
)
|
||||
|
||||
return await paginate(db, metamessages_query)
|
||||
except ValueError as e:
|
||||
logger.warning(f"Failed to get metamessages for session {session_id}: {str(e)}")
|
||||
raise ResourceNotFoundException("Session not found") from e
|
||||
|
||||
|
||||
@router_user_level.post("/list", response_model=Page[schemas.Metamessage])
|
||||
async def get_metamessages_by_user(
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
options: schemas.MetamessageGetUserLevel,
|
||||
reverse: Optional[bool] = False,
|
||||
db=db,
|
||||
):
|
||||
"""Paginate through the user metamessages for a user"""
|
||||
try:
|
||||
metamessages_query = await crud.get_metamessages(
|
||||
db,
|
||||
app_id=app_id,
|
||||
user_id=user_id,
|
||||
metamessage_type=options.metamessage_type,
|
||||
reverse=reverse,
|
||||
filter=options.filter,
|
||||
)
|
||||
|
||||
return await paginate(db, metamessages_query)
|
||||
except ValueError as e:
|
||||
logger.warning(f"Failed to get metamessages for user {user_id}: {str(e)}")
|
||||
raise ResourceNotFoundException("User not found") from e
|
||||
except (ResourceNotFoundException, ValidationException) as e:
|
||||
logger.warning(f"Failed to get metamessages: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@router.get(
|
||||
|
|
@ -109,8 +89,6 @@ async def get_metamessages_by_user(
|
|||
async def get_metamessage(
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
message_id: str,
|
||||
metamessage_id: str,
|
||||
db=db,
|
||||
):
|
||||
|
|
@ -118,13 +96,11 @@ async def get_metamessage(
|
|||
honcho_metamessage = await crud.get_metamessage(
|
||||
db,
|
||||
app_id=app_id,
|
||||
session_id=session_id,
|
||||
user_id=user_id,
|
||||
message_id=message_id,
|
||||
metamessage_id=metamessage_id,
|
||||
)
|
||||
if honcho_metamessage is None:
|
||||
logger.warning(f"Metamessage {metamessage_id} not found for message {message_id}")
|
||||
logger.warning(f"Metamessage {metamessage_id} not found")
|
||||
raise ResourceNotFoundException(f"Metamessage with ID {metamessage_id} not found")
|
||||
return honcho_metamessage
|
||||
|
||||
|
|
@ -136,27 +112,23 @@ async def get_metamessage(
|
|||
async def update_metamessage(
|
||||
app_id: str,
|
||||
user_id: str,
|
||||
session_id: str,
|
||||
metamessage_id: str,
|
||||
metamessage: schemas.MetamessageUpdate,
|
||||
db=db,
|
||||
):
|
||||
"""Update's the metadata of a metamessage"""
|
||||
if metamessage.metadata is None:
|
||||
logger.warning(f"Update attempted with empty metadata for metamessage {metamessage_id}")
|
||||
raise ValidationException("Metamessage metadata cannot be empty")
|
||||
|
||||
"""Update a metamessage's metadata, type, or relationships"""
|
||||
# Ensure user_id from URL path is used
|
||||
metamessage.user_id = user_id
|
||||
|
||||
try:
|
||||
updated_metamessage = await crud.update_metamessage(
|
||||
db,
|
||||
metamessage=metamessage,
|
||||
app_id=app_id,
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
metamessage_id=metamessage_id,
|
||||
)
|
||||
logger.info(f"Metamessage {metamessage_id} updated successfully")
|
||||
return updated_metamessage
|
||||
except ValueError as e:
|
||||
except (ResourceNotFoundException, ValidationException) as e:
|
||||
logger.warning(f"Failed to update metamessage {metamessage_id}: {str(e)}")
|
||||
raise ResourceNotFoundException("Session or metamessage not found") from e
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -172,23 +172,24 @@ class MetamessageBase(BaseModel):
|
|||
class MetamessageCreate(MetamessageBase):
|
||||
metamessage_type: Annotated[str, Field(min_length=1, max_length=50)]
|
||||
content: Annotated[str, Field(min_length=0, max_length=50000)]
|
||||
message_id: str
|
||||
user_id: str | None = None # Will be set from URL parameter in endpoint
|
||||
session_id: str | None = None
|
||||
message_id: str | None = None
|
||||
metadata: dict = {}
|
||||
|
||||
|
||||
class MetamessageGet(MetamessageBase):
|
||||
metamessage_type: str | None = None
|
||||
user_id: str | None = None # Can be provided in URL or body
|
||||
session_id: str | None = None
|
||||
message_id: str | None = None
|
||||
filter: dict | None = None
|
||||
|
||||
|
||||
class MetamessageGetUserLevel(MessageBase):
|
||||
filter: dict | None = None
|
||||
metamessage_type: str | None = None
|
||||
|
||||
|
||||
class MetamessageUpdate(MetamessageBase):
|
||||
message_id: str
|
||||
user_id: str | None = None # Will be set from URL parameter in endpoint
|
||||
session_id: str | None = None
|
||||
message_id: str | None = None
|
||||
metamessage_type: str | None = None
|
||||
metadata: dict | None = None
|
||||
|
||||
|
|
@ -198,7 +199,9 @@ class Metamessage(MetamessageBase):
|
|||
id: str
|
||||
metamessage_type: str
|
||||
content: str
|
||||
message_id: str
|
||||
user_id: str
|
||||
session_id: str | None
|
||||
message_id: str | None
|
||||
h_metadata: dict = Field(exclude=True)
|
||||
metadata: dict
|
||||
created_at: datetime.datetime
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@ async def test_create_metamessage(client, db_session, sample_data):
|
|||
await db_session.commit()
|
||||
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{test_session.public_id}/metamessages",
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages",
|
||||
json={
|
||||
"session_id": str(test_session.public_id),
|
||||
"message_id": str(test_message.public_id),
|
||||
"content": "Test Metamessage",
|
||||
"metadata": {},
|
||||
|
|
@ -27,6 +28,8 @@ async def test_create_metamessage(client, db_session, sample_data):
|
|||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["user_id"] == str(test_user.public_id)
|
||||
assert data["session_id"] == str(test_session.public_id)
|
||||
assert data["message_id"] == str(test_message.public_id)
|
||||
assert data["content"] == "Test Metamessage"
|
||||
assert data["metadata"] == {}
|
||||
|
|
@ -46,19 +49,23 @@ async def test_get_metamessage(client, db_session, sample_data):
|
|||
db_session.add(test_message)
|
||||
await db_session.commit()
|
||||
test_metamessage = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
metadata={},
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
db_session.add(test_metamessage)
|
||||
await db_session.commit()
|
||||
|
||||
response = client.get(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{test_session.public_id}/metamessages/{test_metamessage.public_id}/?message_id={test_message.public_id}"
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages/{test_metamessage.public_id}"
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["user_id"] == str(test_user.public_id)
|
||||
assert data["session_id"] == str(test_session.public_id)
|
||||
assert data["message_id"] == str(test_message.public_id)
|
||||
assert data["content"] == "Test Metamessage"
|
||||
assert data["metadata"] == {}
|
||||
|
|
@ -66,7 +73,7 @@ async def test_get_metamessage(client, db_session, sample_data):
|
|||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_metamessages(client, db_session, sample_data):
|
||||
async def test_get_metamessages_by_session(client, db_session, sample_data):
|
||||
test_app, test_user = sample_data
|
||||
# Create a test session
|
||||
test_session = models.Session(user_id=test_user.public_id)
|
||||
|
|
@ -77,25 +84,35 @@ async def test_get_metamessages(client, db_session, sample_data):
|
|||
)
|
||||
db_session.add(test_message)
|
||||
await db_session.commit()
|
||||
|
||||
# Create metamessages for the same session
|
||||
test_metamessage_1 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_2 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_3 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_4 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
|
|
@ -107,25 +124,29 @@ async def test_get_metamessages(client, db_session, sample_data):
|
|||
db_session.add(test_metamessage_4)
|
||||
await db_session.commit()
|
||||
|
||||
# Filter by session and type
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{test_session.public_id}/metamessages/list",
|
||||
json={"metamessage_type": "test_type"},
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages/list",
|
||||
json={
|
||||
"session_id": str(test_session.public_id),
|
||||
"metamessage_type": "test_type"
|
||||
},
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "items" in data
|
||||
assert len(data["items"]) > 0
|
||||
assert len(data["items"]) == 3
|
||||
assert data["items"][0]["content"] == "Test Metamessage"
|
||||
assert data["items"][0]["metamessage_type"] == "test_type"
|
||||
assert data["items"][0]["session_id"] == str(test_session.public_id)
|
||||
assert data["items"][0]["metadata"] == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_metamessage_by_user(client, db_session, sample_data):
|
||||
test_app, test_user = sample_data
|
||||
# Create a 3 test sessions
|
||||
# Create 3 test sessions
|
||||
test_session_1 = models.Session(user_id=test_user.public_id)
|
||||
test_session_2 = models.Session(user_id=test_user.public_id)
|
||||
test_session_3 = models.Session(user_id=test_user.public_id)
|
||||
|
|
@ -149,48 +170,87 @@ async def test_get_metamessage_by_user(client, db_session, sample_data):
|
|||
db_session.add(test_message_3)
|
||||
await db_session.commit()
|
||||
|
||||
# create a metamessage on each message
|
||||
# Create metamessages across different sessions
|
||||
test_metamessage_1 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session_1.public_id,
|
||||
message_id=test_message_1.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_2 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session_2.public_id,
|
||||
message_id=test_message_2.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_3 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session_3.public_id,
|
||||
message_id=test_message_3.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_4 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session_3.public_id,
|
||||
message_id=test_message_3.public_id,
|
||||
content="Test Metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type_2",
|
||||
)
|
||||
# Create a user-level metamessage (no session/message)
|
||||
test_metamessage_5 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
content="User level metamessage",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
db_session.add(test_metamessage_1)
|
||||
db_session.add(test_metamessage_2)
|
||||
db_session.add(test_metamessage_3)
|
||||
db_session.add(test_metamessage_4)
|
||||
db_session.add(test_metamessage_5)
|
||||
await db_session.commit()
|
||||
|
||||
# Filter only by type across all user's metamessages
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages/list",
|
||||
json={"metamessage_type": "test_type"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data["items"]) > 0
|
||||
assert len(data["items"]) == 3
|
||||
assert data["items"][0]["content"] == "Test Metamessage"
|
||||
assert len(data["items"]) == 4 # All test_type metamessages for the user
|
||||
assert data["items"][0]["content"] in ["Test Metamessage", "User level metamessage"]
|
||||
assert data["items"][0]["metamessage_type"] == "test_type"
|
||||
assert data["items"][0]["metadata"] == {}
|
||||
assert data["items"][0]["user_id"] == str(test_user.public_id)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_user_level_metamessage(client, db_session, sample_data):
|
||||
test_app, test_user = sample_data
|
||||
|
||||
# Create a user-level metamessage (no session or message)
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages",
|
||||
json={
|
||||
"content": "User level insight",
|
||||
"metadata": {"source": "user_profile"},
|
||||
"metamessage_type": "user_insight",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["user_id"] == str(test_user.public_id)
|
||||
assert data["session_id"] is None
|
||||
assert data["message_id"] is None
|
||||
assert data["content"] == "User level insight"
|
||||
assert data["metadata"] == {"source": "user_profile"}
|
||||
assert data["metamessage_type"] == "user_insight"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
|
@ -206,21 +266,28 @@ async def test_update_metamessage(client, db_session, sample_data):
|
|||
db_session.add(test_message)
|
||||
await db_session.commit()
|
||||
test_metamessage = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage",
|
||||
metadata={},
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
db_session.add(test_metamessage)
|
||||
await db_session.commit()
|
||||
|
||||
response = client.put(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{test_session.public_id}/metamessages/{test_metamessage.public_id}",
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages/{test_metamessage.public_id}",
|
||||
json={
|
||||
"message_id": str(test_message.public_id),
|
||||
"user_id": str(test_user.public_id),
|
||||
"metadata": {"new_key": "new_value"},
|
||||
"metamessage_type": "updated_type"
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["metadata"] == {"new_key": "new_value"}
|
||||
assert data["metamessage_type"] == "updated_type"
|
||||
assert data["user_id"] == str(test_user.public_id)
|
||||
assert data["session_id"] == str(test_session.public_id)
|
||||
assert data["message_id"] == str(test_message.public_id)
|
||||
|
|
|
|||
|
|
@ -266,24 +266,32 @@ async def test_deep_clone_session(client, db_session, sample_data):
|
|||
await db_session.commit()
|
||||
|
||||
test_metamessage_1 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage 1",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_2 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage 2",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_3 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message2.public_id,
|
||||
content="Test Metamessage 3",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_4 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message2.public_id,
|
||||
content="Test Metamessage 4",
|
||||
h_metadata={},
|
||||
|
|
@ -374,24 +382,32 @@ async def test_partial_deep_clone_session(client, db_session, sample_data):
|
|||
await db_session.commit()
|
||||
|
||||
test_metamessage_1 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage 1",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_2 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message.public_id,
|
||||
content="Test Metamessage 2",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_3 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message2.public_id,
|
||||
content="Test Metamessage 3",
|
||||
h_metadata={},
|
||||
metamessage_type="test_type",
|
||||
)
|
||||
test_metamessage_4 = models.Metamessage(
|
||||
user_id=test_user.public_id,
|
||||
session_id=test_session.public_id,
|
||||
message_id=test_message2.public_id,
|
||||
content="Test Metamessage 4",
|
||||
h_metadata={},
|
||||
|
|
|
|||
|
|
@ -262,10 +262,11 @@ def test_metamessage_validations_api(client, sample_data):
|
|||
|
||||
# Test metamessage_type too short
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{session_id}/metamessages",
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages",
|
||||
json={
|
||||
"metamessage_type": "",
|
||||
"content": "test content",
|
||||
"session_id": session_id,
|
||||
"message_id": message_id,
|
||||
"metadata": {}
|
||||
}
|
||||
|
|
@ -278,10 +279,11 @@ def test_metamessage_validations_api(client, sample_data):
|
|||
|
||||
# Test metamessage_type too long
|
||||
response = client.post(
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/sessions/{session_id}/metamessages",
|
||||
f"/v1/apps/{test_app.public_id}/users/{test_user.public_id}/metamessages",
|
||||
json={
|
||||
"metamessage_type": "a" * 51,
|
||||
"content": "test content",
|
||||
"session_id": session_id,
|
||||
"message_id": message_id,
|
||||
"metadata": {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue