diff --git a/src/fabledassistant/services/llm.py b/src/fabledassistant/services/llm.py index 4af17eb..fdb924c 100644 --- a/src/fabledassistant/services/llm.py +++ b/src/fabledassistant/services/llm.py @@ -508,17 +508,10 @@ async def build_context( "next line. Never describe images as text or list their URLs — always render them as markdown images." ) tool_lines.append( - "Use update_note to edit/expand an existing note OR to update a task's status/priority/due_date. " - "Use create_note ONLY for genuinely new notes with a different title. " - "Use list_tasks to find tasks by status, priority, or due date (e.g. overdue, high priority, in progress). " - "If a note was created earlier in the conversation and the user provides more content for it, use update_note. " - "Use get_note to read the full content of a specific note. " - "Use list_notes to browse notes by recency or tag. " - "Use search_notes for conceptual/semantic queries — e.g. 'what notes do I have about X' or " - "'find notes related to Y' — it uses semantic understanding to find thematically related content " - "even when exact words don't match. Pass project= to scope the search to a specific project. " - "Use delete_note / delete_task only when explicitly asked to delete — these require confirmation. " - "Never proactively search notes or comment on the absence of notes/context unless the user explicitly asks about their notes." + "Use update_note for existing notes/tasks; use create_note only for new content. " + "Use search_notes for semantic/conceptual queries. " + "Delete tools require an explicit user request. " + "Never proactively search notes or comment on absent context." ) tool_guidance = "\n".join(tool_lines) diff --git a/src/fabledassistant/services/tools.py b/src/fabledassistant/services/tools.py index 5280f49..457beb7 100644 --- a/src/fabledassistant/services/tools.py +++ b/src/fabledassistant/services/tools.py @@ -107,16 +107,7 @@ _CORE_TOOLS = [ }, "recurrence_rule": { "type": "object", - "description": ( - "Optional recurrence schedule so the task repeats automatically. Two forms:\n" - " Interval — repeat every N units from the due date:\n" - ' {"type": "interval", "every": 3, "unit": "month"}\n' - " unit options: day | week | month | year\n" - " Calendar/monthly — specific day each month:\n" - ' {"type": "calendar", "unit": "month", "day_of_month": 1}\n' - " Calendar/annual — specific day each year:\n" - ' {"type": "calendar", "unit": "year", "day_of_month": 15, "month": 6}' - ), + "description": 'Optional recurrence. Interval form: {"type":"interval","every":3,"unit":"month"} (units: day/week/month/year). Calendar form: {"type":"calendar","unit":"month","day_of_month":1}. Annual: add "month":6.', }, }, "required": ["title"], @@ -161,12 +152,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "update_note", - "description": ( - "Update an existing note or task — content, title, status, priority, or due date. " - "Use this when the user asks to add to, edit, expand, or modify a note, " - "OR to mark a task done/in-progress, change its priority, or set a due date. " - "NEVER use create_note when updating an existing note — always use update_note." - ), + "description": "Update an existing note or task — content, title, status, priority, or due date. Use for edits, marking tasks done, changing priority. Never use create_note for existing notes.", "parameters": { "type": "object", "properties": { @@ -220,10 +206,7 @@ _CORE_TOOLS = [ }, "recurrence_rule": { "type": "object", - "description": ( - "Set or update the recurrence schedule. Pass null to remove recurrence. " - "Same format as create_task recurrence_rule." - ), + "description": "Set or update recurrence (same format as create_task). Pass null to remove.", }, }, "required": ["query"], @@ -234,13 +217,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "search_notes", - "description": ( - "Search notes and tasks using semantic understanding. Finds content related to a concept, " - "theme, or topic — even when exact keywords don't appear in the title or body. " - "Use this when the user asks what notes they have about a topic, wants to explore related " - "content, or is looking for something they've written. Falls back to keyword search " - "automatically if semantic search is unavailable." - ), + "description": "Search notes and tasks by semantic meaning — finds content by concept or theme even when exact keywords don't appear.", "parameters": { "type": "object", "properties": { @@ -363,12 +340,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "list_tasks", - "description": ( - "List the user's tasks with optional filters. Use this when the user asks about their tasks " - "by status (e.g. 'what's in progress'), priority (e.g. 'high priority tasks'), " - "or due date (e.g. 'overdue tasks', 'due this week'). " - "For 'overdue', set due_before to today's date. For 'due today', set due_after to today and due_before to tomorrow." - ), + "description": "List tasks with optional filters. For overdue tasks, set due_before to today's date.", "parameters": { "type": "object", "properties": { @@ -378,11 +350,7 @@ _CORE_TOOLS = [ "type": "string", "enum": ["todo", "in_progress", "done", "cancelled"], }, - "description": ( - "Filter by one or more task statuses. " - 'Example: ["todo", "in_progress"] to list all active tasks. ' - "Omit to return tasks of any status." - ), + "description": "Filter by one or more statuses. Omit for all.", }, "priority": { "type": "string", @@ -417,7 +385,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "create_project", - "description": "Create a brand-new project. IMPORTANT: NEVER call this because a project name was not found — always use list_projects first to confirm no similar project exists. Only call this when the user has explicitly asked to create a new project AND confirmed it. Call with confirmed=true only after the user has explicitly approved. The system will block creation if any project with a similar name already exists.", + "description": "Create a new project. Use list_projects first to check for duplicates. Only call after user has explicitly confirmed.", "parameters": { "type": "object", "properties": { @@ -482,7 +450,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "create_milestone", - "description": "Create a new milestone inside a project. IMPORTANT: You MUST ask the user to confirm the milestone name and which project it belongs to before calling this tool. Only call with confirmed=true after the user has explicitly approved creation.", + "description": "Create a milestone inside a project. Confirm name and project with user before calling.", "parameters": { "type": "object", "properties": { @@ -569,10 +537,7 @@ _CORE_TOOLS = [ "properties": { "location": { "type": "string", - "description": ( - "City, region, or country to look up — e.g. 'Portland, Oregon', 'Tokyo', 'home', 'work'. " - "Use 'home' or 'work' to get the user's saved locations. Omit for all saved locations." - ), + "description": "City/region to look up, or 'home'/'work' for saved locations. Omit for all saved.", }, "days": { "type": "integer", @@ -614,11 +579,7 @@ _CORE_TOOLS = [ "type": "function", "function": { "name": "add_rss_feed", - "description": ( - "Add a new RSS feed to the user's briefing. Use this when the user asks to " - "subscribe to, follow, add, or track a feed, blog, news source, subreddit, or podcast URL. " - "The feed will be fetched immediately after adding." - ), + "description": "Add an RSS/Atom feed. Use when user asks to subscribe to or track a feed, blog, subreddit, or podcast.", "parameters": { "type": "object", "properties": { @@ -645,15 +606,15 @@ _CORE_TOOLS = [ "properties": { "title": { "type": "string", - "description": "A descriptive event title (e.g. 'John's Birthday' not just 'Birthday')", + "description": "A descriptive event title", }, "start": { "type": "string", - "description": "Start date (YYYY-MM-DD for all-day) or datetime (ISO 8601, e.g. 2025-01-15T14:00:00)", + "description": "Start date (YYYY-MM-DD) or datetime (ISO 8601 with timezone offset)", }, "end": { "type": "string", - "description": "Optional end date or datetime in same format as start", + "description": "Optional end date or datetime", }, "duration": { "type": "integer", @@ -673,7 +634,7 @@ _CORE_TOOLS = [ }, "all_day": { "type": "boolean", - "description": "Set to true for all-day events like birthdays, holidays, deadlines (default false)", + "description": "True for all-day events (birthdays, holidays, deadlines)", }, "recurrence": { "type": "string", @@ -874,14 +835,7 @@ _IMAGE_TOOLS = [ "type": "function", "function": { "name": "search_images", - "description": ( - "Search the web for images and display them inline in the response. " - "ONLY use this when the user explicitly asks to SEE, SHOW, VIEW, or DISPLAY " - "an image or photo — e.g. 'show me a picture of X', 'what does X look like', " - "'find a photo of X', 'display an image of X'. " - "Do NOT use for general descriptions, factual questions, or when the user just " - "wants information without visual content. Returns at most 2 images." - ), + "description": "Search and display images inline. Use ONLY when user explicitly asks to see or show an image or photo. Not for factual questions.", "parameters": { "type": "object", "properties": {