Add a message to a conversation.
(project_dir: Path, conversation_id: int, role: str, content: str)
| 245 | # ============================================================================ |
| 246 | |
| 247 | def add_message(project_dir: Path, conversation_id: int, role: str, content: str) -> Optional[dict]: |
| 248 | """Add a message to a conversation.""" |
| 249 | session = get_session(project_dir) |
| 250 | try: |
| 251 | conversation = session.query(Conversation).filter(Conversation.id == conversation_id).first() |
| 252 | if not conversation: |
| 253 | return None |
| 254 | |
| 255 | message = ConversationMessage( |
| 256 | conversation_id=conversation_id, |
| 257 | role=role, |
| 258 | content=content, |
| 259 | ) |
| 260 | session.add(message) |
| 261 | |
| 262 | # Update conversation's updated_at timestamp |
| 263 | conversation.updated_at = _utc_now() |
| 264 | |
| 265 | # Auto-generate title from first user message if not set |
| 266 | if not conversation.title and role == "user": |
| 267 | # Take first 50 chars of first user message as title |
| 268 | conversation.title = content[:50] + ("..." if len(content) > 50 else "") |
| 269 | |
| 270 | session.commit() |
| 271 | session.refresh(message) |
| 272 | |
| 273 | logger.debug(f"Added {role} message to conversation {conversation_id}") |
| 274 | return { |
| 275 | "id": message.id, |
| 276 | "role": message.role, |
| 277 | "content": message.content, |
| 278 | "timestamp": message.timestamp.isoformat() if message.timestamp else None, |
| 279 | } |
| 280 | finally: |
| 281 | session.close() |
| 282 | |
| 283 | |
| 284 | def get_messages(project_dir: Path, conversation_id: int) -> list[dict]: |
no test coverage detected