Skip to main content
Glama

Aidderall MCP Server

by cheezcake
test_task_manager.py16.8 kB
# Aidderall MCP Server - Hierarchical task management for AI assistants # Copyright (C) 2024 Briam R. <briamr@gmail.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. import pytest from src.models import MainTask, SubTask, TaskStatus from src.task_manager import TaskManager class TestTaskManager: def setup_method(self): self.manager = TaskManager() def test_zen_state(self): assert self.manager.is_zen_state assert self.manager.current_task is None assert len(self.manager.global_tasks) == 0 def test_create_new_task(self): task = self.manager.create_new_task("First Task", "Body of first task") assert isinstance(task, MainTask) assert task.title == "First Task" assert task.body == "Body of first task" assert task.status == TaskStatus.CURRENT assert not self.manager.is_zen_state assert self.manager.current_task == task assert len(self.manager.global_tasks) == 1 def test_extend_current_task_in_zen_state(self): with pytest.raises(ValueError, match="Cannot extend task in zen state"): self.manager.extend_current_task("Sub Task", "Sub body") def test_extend_current_task(self): main_task = self.manager.create_new_task("Main Task", "Main body") sub_task = self.manager.extend_current_task("Sub Task", "Sub body") assert isinstance(sub_task, SubTask) assert sub_task.title == "Sub Task" assert sub_task.status == TaskStatus.CURRENT assert main_task.status == TaskStatus.PENDING assert self.manager.current_task == sub_task assert len(main_task.sub_tasks) == 1 def test_complete_current_task_subtask(self): main_task = self.manager.create_new_task("Main Task", "Main body") sub_task1 = self.manager.extend_current_task("Sub Task 1", "Sub body 1") sub_task2 = self.manager.extend_current_task("Sub Task 2", "Sub body 2") completed = self.manager.complete_current_task() assert completed == sub_task2 assert completed.status == TaskStatus.COMPLETED assert completed.completed_at is not None assert self.manager.current_task == sub_task1 assert sub_task1.status == TaskStatus.CURRENT assert len(self.manager.completed_tasks) == 1 def test_complete_current_task_main_task(self): task = self.manager.create_new_task("Only Task", "Body") completed = self.manager.complete_current_task() assert completed == task # Task should stay in structure but be marked completed assert self.manager.is_zen_state # Single completed task = zen assert len(self.manager.global_tasks) == 1 assert self.manager.global_tasks[0] == task assert task.status == TaskStatus.COMPLETED assert ( self.manager.current_task == task ) # Still returns the task even if completed assert len(self.manager.completed_tasks) == 1 def test_update_current_task(self): task = self.manager.create_new_task("Task", "Original body") updated = self.manager.update_current_task("Updated body") assert updated == task assert task.body == "Updated body" assert task.title == "Task" def test_update_current_task_no_current(self): with pytest.raises(ValueError, match="No current task to update"): self.manager.update_current_task("New body") def test_get_siblings_to_left(self): main_task = self.manager.create_new_task("Main", "Main body") sub1 = self.manager.extend_current_task("Sub 1", "Body 1") sub2 = self.manager.extend_current_task("Sub 2", "Body 2") sub3 = self.manager.extend_current_task("Sub 3", "Body 3") siblings = self.manager.get_siblings_to_left() assert len(siblings) == 2 assert siblings[0] == sub1 assert siblings[1] == sub2 def test_get_breadcrumb_trail(self): main1 = self.manager.create_new_task("Main 1", "Body 1") sub1 = self.manager.extend_current_task("Sub 1", "Sub body 1") main2 = self.manager.create_new_task("Main 2", "Body 2") sub2 = self.manager.extend_current_task("Sub 2", "Sub body 2") trail = self.manager.get_breadcrumb_trail() assert len(trail) == 2 assert trail[0] == main1 assert trail[1] == main2 def test_get_big_picture(self): picture = self.manager.get_big_picture() assert picture == "No tasks (zen state)" main1 = self.manager.create_new_task("Main Task", "Body") picture = self.manager.get_big_picture() assert "Main Task (current) <-- YOU ARE HERE" in picture sub1 = self.manager.extend_current_task("Sub Task", "Sub body") picture = self.manager.get_big_picture() assert "Main Task (pending)" in picture assert " Sub Task (current) <-- YOU ARE HERE" in picture def test_get_completed_tasks(self): task1 = self.manager.create_new_task("Task 1", "Body 1") self.manager.complete_current_task() task2 = self.manager.create_new_task("Task 2", "Body 2") self.manager.complete_current_task() chrono = self.manager.get_completed_tasks("chronological") assert len(chrono) == 2 assert chrono[0] == task1 assert chrono[1] == task2 logical = self.manager.get_completed_tasks("logical") assert len(logical) == 2 assert logical[0] == task2 assert logical[1] == task1 with pytest.raises(ValueError): self.manager.get_completed_tasks("invalid") def test_get_stack_overview(self): overview = self.manager.get_stack_overview() assert overview["zen_state"] is True assert overview["stack_depth"] == 0 assert overview["current_task_id"] is None main = self.manager.create_new_task("Main", "Body") sub = self.manager.extend_current_task("Sub", "Sub body") overview = self.manager.get_stack_overview() assert overview["zen_state"] is False assert overview["stack_depth"] == 2 assert overview["current_task_id"] == sub.id assert len(overview["global_tasks"]) == 1 assert len(overview["global_tasks"][0]["sub_tasks"]) == 1 def test_peek_context_subtask(self): main = self.manager.create_new_task("Main", "Body") sub1 = self.manager.extend_current_task("Sub 1", "Body 1") sub2 = self.manager.extend_current_task("Sub 2", "Body 2") parent, immediate = self.manager.peek_context() assert parent == main assert immediate == sub1 def test_peek_context_main_task(self): main1 = self.manager.create_new_task("Main 1", "Body 1") sub1 = self.manager.extend_current_task("Sub 1", "Sub body") main2 = self.manager.create_new_task("Main 2", "Body 2") parent, immediate = self.manager.peek_context() assert parent == main1 assert immediate == sub1 def test_list_siblings(self): main = self.manager.create_new_task("Main", "Body") siblings = self.manager.list_siblings() assert len(siblings) == 0 sub1 = self.manager.extend_current_task("Sub 1", "Body 1") sub2 = self.manager.extend_current_task("Sub 2", "Body 2") siblings = self.manager.list_siblings() assert len(siblings) == 1 assert siblings[0] == sub1 def test_complex_scenario(self): main1 = self.manager.create_new_task("Design Feature", "Design specs") sub1_1 = self.manager.extend_current_task("Research", "Research notes") sub1_2 = self.manager.extend_current_task("Interview", "Interview results") self.manager.complete_current_task() assert self.manager.current_task == sub1_1 self.manager.complete_current_task() assert self.manager.current_task == main1 sub1_3 = self.manager.extend_current_task("Specification", "Spec doc") self.manager.complete_current_task() self.manager.complete_current_task() # Tasks should stay in structure assert self.manager.is_zen_state # All tasks completed = zen assert len(self.manager.global_tasks) == 1 assert main1.status == TaskStatus.COMPLETED assert len(self.manager.completed_tasks) == 4 def test_switch_focus_basic(self): # Create multiple tasks main1 = self.manager.create_new_task("Main 1", "Body 1") sub1 = self.manager.extend_current_task("Sub 1", "Sub body 1") main2 = self.manager.create_new_task("Main 2", "Body 2") # Current focus should be main2 assert self.manager.current_task == main2 assert main2.status == TaskStatus.CURRENT assert sub1.status == TaskStatus.PENDING assert main1.status == TaskStatus.PENDING # Switch to sub1 result = self.manager.switch_focus(sub1.id) assert result["success"] is True assert self.manager.current_task == sub1 assert sub1.status == TaskStatus.CURRENT assert main2.status == TaskStatus.PENDING # Switch to main1 result = self.manager.switch_focus(main1.id) assert result["success"] is True assert self.manager.current_task == main1 assert main1.status == TaskStatus.CURRENT assert sub1.status == TaskStatus.PENDING def test_switch_focus_same_task(self): task = self.manager.create_new_task("Task", "Body") result = self.manager.switch_focus(task.id) assert result["success"] is True assert result["message"] == "Task is already the current focus" def test_switch_focus_invalid_task(self): with pytest.raises(ValueError, match="Task with ID 'invalid-id' not found"): self.manager.switch_focus("invalid-id") def test_switch_focus_completed_task(self): task = self.manager.create_new_task("Task", "Body") task_id = task.id self.manager.complete_current_task() with pytest.raises(ValueError, match="not found or already completed"): self.manager.switch_focus(task_id) def test_switch_focus_complex_scenario(self): # Create a complex task structure main1 = self.manager.create_new_task("Project A", "Project A details") sub1_1 = self.manager.extend_current_task("Research", "Research notes") sub1_2 = self.manager.extend_current_task("Analysis", "Analysis data") main2 = self.manager.create_new_task("Urgent Bug", "Bug details") sub2_1 = self.manager.extend_current_task("Debug", "Debug info") # Current focus is sub2_1 assert self.manager.current_task == sub2_1 # Jump back to sub1_2 without completing anything result = self.manager.switch_focus(sub1_2.id) assert self.manager.current_task == sub1_2 assert "Analysis" in result["new_focus_path"] # All tasks should still be pending except the current one assert sub1_2.status == TaskStatus.CURRENT assert sub1_1.status == TaskStatus.PENDING assert main1.status == TaskStatus.PENDING assert sub2_1.status == TaskStatus.PENDING assert main2.status == TaskStatus.PENDING def test_complete_task_stays_in_structure(self): # Create tasks main = self.manager.create_new_task("Main Task", "Body") sub1 = self.manager.extend_current_task("Sub 1", "Sub body 1") sub2 = self.manager.extend_current_task("Sub 2", "Sub body 2") # Complete sub2 completed = self.manager.complete_current_task() assert completed == sub2 # Task should still be in structure assert len(main.sub_tasks) == 2 assert main.sub_tasks[1] == sub2 assert sub2.status == TaskStatus.COMPLETED # Current should be sub1 assert self.manager.current_task == sub1 assert sub1.status == TaskStatus.CURRENT # Task should also be in completed_tasks assert len(self.manager.completed_tasks) == 1 assert self.manager.completed_tasks[0] == sub2 def test_remove_task_basic(self): # Create tasks main1 = self.manager.create_new_task("Main 1", "Body 1") sub1 = self.manager.extend_current_task("Sub 1", "Sub body 1") main2 = self.manager.create_new_task("Main 2", "Body 2") # Remove sub1 result = self.manager.remove_task(sub1.id) assert result["success"] is True assert "Sub 1" in result["message"] # Sub1 should be gone from structure assert len(main1.sub_tasks) == 0 # Global tasks should still have both main tasks assert len(self.manager.global_tasks) == 2 def test_remove_main_task_with_children(self): # Create tasks main1 = self.manager.create_new_task("Main 1", "Body 1") sub1 = self.manager.extend_current_task("Sub 1", "Sub body 1") sub2 = self.manager.extend_current_task("Sub 2", "Sub body 2") main2 = self.manager.create_new_task("Main 2", "Body 2") # Remove main1 (should remove it entirely with children) result = self.manager.remove_task(main1.id) assert result["success"] is True # Only main2 should remain assert len(self.manager.global_tasks) == 1 assert self.manager.global_tasks[0] == main2 def test_remove_completed_task_stays_in_history(self): # Create and complete a task task = self.manager.create_new_task("Task", "Body") self.manager.complete_current_task() # Task should be in structure and completed_tasks assert len(self.manager.global_tasks) == 1 assert len(self.manager.completed_tasks) == 1 # Remove it from structure result = self.manager.remove_task(task.id) assert result["was_completed"] is True # Should be gone from structure but still in completed_tasks assert len(self.manager.global_tasks) == 0 assert len(self.manager.completed_tasks) == 1 assert self.manager.completed_tasks[0] == task def test_remove_nonexistent_task(self): with pytest.raises(ValueError, match="not found in structure"): self.manager.remove_task("invalid-id") def test_focus_navigation_with_completed_tasks(self): # Create structure main = self.manager.create_new_task("Main", "Body") sub1 = self.manager.extend_current_task("Sub 1", "Body 1") sub2 = self.manager.extend_current_task("Sub 2", "Body 2") sub3 = self.manager.extend_current_task("Sub 3", "Body 3") # Complete sub3, focus should go to sub2 self.manager.complete_current_task() assert self.manager.current_task == sub2 # Complete sub2, focus should go to sub1 self.manager.complete_current_task() assert self.manager.current_task == sub1 # All tasks should still be in structure assert len(main.sub_tasks) == 3 assert sub3.status == TaskStatus.COMPLETED assert sub2.status == TaskStatus.COMPLETED assert sub1.status == TaskStatus.CURRENT def test_zen_state_with_completed_tasks(self): # Empty = zen assert self.manager.is_zen_state # Create tasks main = self.manager.create_new_task("Main", "Body") sub = self.manager.extend_current_task("Sub", "Sub body") # With incomplete tasks = not zen assert not self.manager.is_zen_state # Complete sub self.manager.complete_current_task() assert not self.manager.is_zen_state # Main still incomplete # Complete main self.manager.complete_current_task() assert self.manager.is_zen_state # All completed = zen # Tasks still in structure assert len(self.manager.global_tasks) == 1 assert len(main.sub_tasks) == 1 # Remove a task self.manager.remove_task(sub.id) assert self.manager.is_zen_state # Still zen (all remaining completed) # Remove main task self.manager.remove_task(main.id) assert self.manager.is_zen_state # Empty = zen

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cheezcake/aidderall_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server