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()
|
uid = get_current_user_id()
|
||||||
limit = min(request.args.get("limit", 50, type=int), 500)
|
limit = min(request.args.get("limit", 50, type=int), 500)
|
||||||
offset = request.args.get("offset", 0, type=int)
|
offset = request.args.get("offset", 0, type=int)
|
||||||
|
conv_type = request.args.get("type", "chat")
|
||||||
# Apply retention policy before returning list
|
# Apply retention policy before returning list
|
||||||
retention_str = await get_setting(uid, "chat_retention_days", "90")
|
retention_str = await get_setting(uid, "chat_retention_days", "90")
|
||||||
try:
|
try:
|
||||||
@@ -48,7 +49,7 @@ async def list_conversations_route():
|
|||||||
retention_days = 90
|
retention_days = 90
|
||||||
if retention_days > 0:
|
if retention_days > 0:
|
||||||
await cleanup_old_conversations(uid, retention_days)
|
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({
|
return jsonify({
|
||||||
"conversations": conversations,
|
"conversations": conversations,
|
||||||
"total": total,
|
"total": total,
|
||||||
|
|||||||
@@ -46,12 +46,13 @@ async def get_conversation(
|
|||||||
|
|
||||||
|
|
||||||
async def list_conversations(
|
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]:
|
) -> tuple[list[dict], int]:
|
||||||
async with async_session() as session:
|
async with async_session() as session:
|
||||||
total = await session.scalar(
|
total = await session.scalar(
|
||||||
select(func.count(Conversation.id)).where(
|
select(func.count(Conversation.id)).where(
|
||||||
Conversation.user_id == user_id
|
Conversation.user_id == user_id,
|
||||||
|
Conversation.conversation_type == conv_type,
|
||||||
)
|
)
|
||||||
) or 0
|
) or 0
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ async def list_conversations(
|
|||||||
|
|
||||||
result = await session.execute(
|
result = await session.execute(
|
||||||
select(Conversation, msg_count.label("message_count"))
|
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())
|
.order_by(Conversation.updated_at.desc())
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
@@ -78,6 +79,8 @@ async def list_conversations(
|
|||||||
"id": conv.id,
|
"id": conv.id,
|
||||||
"title": conv.title,
|
"title": conv.title,
|
||||||
"model": conv.model,
|
"model": conv.model,
|
||||||
|
"conversation_type": conv.conversation_type,
|
||||||
|
"briefing_date": conv.briefing_date.isoformat() if conv.briefing_date else None,
|
||||||
"message_count": row[1],
|
"message_count": row[1],
|
||||||
"created_at": conv.created_at.isoformat(),
|
"created_at": conv.created_at.isoformat(),
|
||||||
"updated_at": conv.updated_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
|
# 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": False, "error": str(e)}
|
||||||
return {"success": True, "log": log.to_dict(), "task": note.title}
|
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:
|
else:
|
||||||
return {"success": False, "error": f"Unknown tool: {tool_name}"}
|
return {"success": False, "error": f"Unknown tool: {tool_name}"}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user