From 4df5ec2d65f234eae495553664eff4b27a5d6666 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 17 Feb 2026 23:22:02 -0500 Subject: [PATCH] Add update_task fields, list_tasks, and update_todo tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - update_note: extend with status/priority/due_date fields so task attributes can be changed via chat (mark done, set priority, move due date). body is now optional — task field updates work without touching content. - list_tasks: new core tool with status/priority/due_before/due_after/limit filters backed by list_notes(is_task=True). Enables queries like "overdue tasks", "high priority tasks", "what's in progress". - update_todo: new CalDAV tool to modify VTODO summary, due date, description, and priority — follows update_event pattern (modify component, rebuild ical, save). Completes the CalDAV todo CRUD suite. - tools.py: add update_todo import + execute case (type: todo_updated) - llm.py: add list_tasks and update_todo to available actions + guidance - intent.py: routing rules for mark-done/priority/due-date → update_note, overdue/in-progress/high-priority queries → list_tasks, CalDAV todo updates → update_todo - ToolCallCard.vue: tasks list block (linked titles + due + priority badges), todo_updated label, tool-task-priority CSS classes Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/ToolCallCard.vue | 41 +++++- src/fabledassistant/services/caldav.py | 75 ++++++++++ src/fabledassistant/services/intent.py | 5 + src/fabledassistant/services/llm.py | 9 +- src/fabledassistant/services/tools.py | 167 +++++++++++++++++++++-- 5 files changed, 284 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/ToolCallCard.vue b/frontend/src/components/ToolCallCard.vue index 17548d5..cccf571 100644 --- a/frontend/src/components/ToolCallCard.vue +++ b/frontend/src/components/ToolCallCard.vue @@ -19,6 +19,10 @@ const label = computed(() => { return "Created note"; case "note_updated": return "Updated note"; + case "tasks": + return "Tasks"; + case "todo_updated": + return "Updated todo"; case "search": return "Searched notes"; case "event": @@ -95,7 +99,7 @@ const calendarList = computed(() => { const todoData = computed(() => { const data = props.toolCall.result.data; const type = props.toolCall.result.type; - if (!data || (type !== "todo" && type !== "todo_completed" && type !== "todo_deleted")) return null; + if (!data || (type !== "todo" && type !== "todo_completed" && type !== "todo_deleted" && type !== "todo_updated")) return null; return data as { summary: string; due?: string; status?: string }; }); @@ -141,6 +145,19 @@ function formatEventTime(iso: string): string { } } +const taskList = computed(() => { + const data = props.toolCall.result.data; + if (!data || props.toolCall.result.type !== "tasks") return null; + const results = data.results as Array<{ id: number; title: string; status: string; priority: string; due_date?: string }> | undefined; + return results ?? []; +}); + +const taskCount = computed(() => { + const data = props.toolCall.result.data; + if (!data || props.toolCall.result.type !== "tasks") return 0; + return (data.total as number) ?? 0; +}); + const searchResults = computed(() => { const data = props.toolCall.result.data; if (!data || props.toolCall.result.type !== "search") return null; @@ -215,6 +232,17 @@ async function applyTag(tag: string) { +