feat: API key routes, search endpoint, conversation type wiring

- GET/POST/DELETE /api/api-keys blueprint registered
- GET /api/search?q=&content_type=&limit= semantic search endpoint
- create_conversation gains conversation_type param (default "chat")
- cleanup_old_conversations excludes mcp type from retention sweep
- POST /api/chat/conversations accepts conversation_type body field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 21:01:04 -04:00
parent e8a4ca915a
commit 47b4af281b
6 changed files with 122 additions and 4 deletions
+7 -3
View File
@@ -15,10 +15,10 @@ logger = logging.getLogger(__name__)
async def create_conversation(
user_id: int, title: str = "", model: str = ""
user_id: int, title: str = "", model: str = "", conversation_type: str = "chat"
) -> Conversation:
async with async_session() as session:
conv = Conversation(user_id=user_id, title=title, model=model)
conv = Conversation(user_id=user_id, title=title, model=model, conversation_type=conversation_type)
session.add(conv)
await session.commit()
# Re-fetch with messages eagerly loaded to avoid lazy-load in async context
@@ -128,7 +128,11 @@ async def cleanup_old_conversations(user_id: int, days: int) -> int:
async with async_session() as session:
result = await session.execute(
sa_delete(Conversation)
.where(Conversation.user_id == user_id, Conversation.updated_at < cutoff)
.where(
Conversation.user_id == user_id,
Conversation.updated_at < cutoff,
Conversation.conversation_type != "mcp", # preserve MCP audit trail
)
.returning(Conversation.id)
)
await session.commit()