feat: filter chat conversations by type; add get_weather and get_rss_items LLM tools
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ async def list_conversations_route():
|
||||
uid = get_current_user_id()
|
||||
limit = min(request.args.get("limit", 50, type=int), 500)
|
||||
offset = request.args.get("offset", 0, type=int)
|
||||
conv_type = request.args.get("type", "chat")
|
||||
# Apply retention policy before returning list
|
||||
retention_str = await get_setting(uid, "chat_retention_days", "90")
|
||||
try:
|
||||
@@ -48,7 +49,7 @@ async def list_conversations_route():
|
||||
retention_days = 90
|
||||
if retention_days > 0:
|
||||
await cleanup_old_conversations(uid, retention_days)
|
||||
conversations, total = await list_conversations(uid, limit=limit, offset=offset)
|
||||
conversations, total = await list_conversations(uid, limit=limit, offset=offset, conv_type=conv_type)
|
||||
return jsonify({
|
||||
"conversations": conversations,
|
||||
"total": total,
|
||||
|
||||
@@ -46,12 +46,13 @@ async def get_conversation(
|
||||
|
||||
|
||||
async def list_conversations(
|
||||
user_id: int, limit: int = 50, offset: int = 0
|
||||
user_id: int, limit: int = 50, offset: int = 0, conv_type: str = "chat"
|
||||
) -> tuple[list[dict], int]:
|
||||
async with async_session() as session:
|
||||
total = await session.scalar(
|
||||
select(func.count(Conversation.id)).where(
|
||||
Conversation.user_id == user_id
|
||||
Conversation.user_id == user_id,
|
||||
Conversation.conversation_type == conv_type,
|
||||
)
|
||||
) or 0
|
||||
|
||||
@@ -65,7 +66,7 @@ async def list_conversations(
|
||||
|
||||
result = await session.execute(
|
||||
select(Conversation, msg_count.label("message_count"))
|
||||
.where(Conversation.user_id == user_id)
|
||||
.where(Conversation.user_id == user_id, Conversation.conversation_type == conv_type)
|
||||
.order_by(Conversation.updated_at.desc())
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
@@ -78,6 +79,8 @@ async def list_conversations(
|
||||
"id": conv.id,
|
||||
"title": conv.title,
|
||||
"model": conv.model,
|
||||
"conversation_type": conv.conversation_type,
|
||||
"briefing_date": conv.briefing_date.isoformat() if conv.briefing_date else None,
|
||||
"message_count": row[1],
|
||||
"created_at": conv.created_at.isoformat(),
|
||||
"updated_at": conv.updated_at.isoformat(),
|
||||
|
||||
@@ -478,6 +478,51 @@ _CORE_TOOLS = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_weather",
|
||||
"description": (
|
||||
"Get the current 7-day weather forecast for the user's configured locations. "
|
||||
"Returns temperature, precipitation, and conditions for each day. "
|
||||
"Also reports any changes since the last forecast was fetched."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location_key": {
|
||||
"type": "string",
|
||||
"description": "Which location to focus on: 'home', 'work', or 'all'. Defaults to 'all'.",
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "get_rss_items",
|
||||
"description": (
|
||||
"Get recent items from the user's RSS feeds (news, blogs, Reddit, podcasts). "
|
||||
"Returns titles, URLs, and summaries of recent posts."
|
||||
),
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"description": "Number of items to return (default 15, max 50)",
|
||||
},
|
||||
"category": {
|
||||
"type": "string",
|
||||
"description": "Filter by feed category (e.g. 'news', 'tech'). Omit for all.",
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
# CalDAV tools — only included when user has CalDAV configured
|
||||
@@ -1568,6 +1613,20 @@ async def execute_tool(user_id: int, tool_name: str, arguments: dict) -> dict:
|
||||
return {"success": False, "error": str(e)}
|
||||
return {"success": True, "log": log.to_dict(), "task": note.title}
|
||||
|
||||
elif tool_name == "get_weather":
|
||||
from fabledassistant.services.weather import get_cached_weather
|
||||
location_key = arguments.get("location_key", "all")
|
||||
locations = await get_cached_weather(user_id)
|
||||
if location_key != "all":
|
||||
locations = [loc for loc in locations if loc["location_key"] == location_key]
|
||||
return {"data": {"locations": locations}}
|
||||
|
||||
elif tool_name == "get_rss_items":
|
||||
from fabledassistant.services.rss import get_recent_items
|
||||
limit = min(int(arguments.get("limit", 15)), 50)
|
||||
items = await get_recent_items(user_id, limit=limit)
|
||||
return {"data": {"items": items, "count": len(items)}}
|
||||
|
||||
else:
|
||||
return {"success": False, "error": f"Unknown tool: {tool_name}"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user