mcpmark / src /mcp_services /filesystem /filesystem_task_manager.py
haochengsama's picture
Add files using upload-large-folder tool
a2ec7b6 verified
Raw
History Blame Contribute Delete
4.97 kB
"""
Simplified Filesystem Task Manager using Enhanced Base Class
============================================================
This module shows how the filesystem task manager can be simplified
using the enhanced base task manager.
"""
import os
import subprocess
from dataclasses import dataclass
from pathlib import Path
from typing import List, Optional, Dict, Any
from src.base.task_manager import BaseTask, BaseTaskManager
from src.logger import get_logger
logger = get_logger(__name__)
@dataclass
class FilesystemTask(BaseTask):
"""Filesystem-specific task with additional fields."""
test_directory: Optional[str] = None
expected_files: Optional[List[str]] = None
expected_directories: Optional[List[str]] = None
class FilesystemTaskManager(BaseTaskManager):
"""Simplified filesystem task manager using enhanced base class."""
def __init__(self, tasks_root: Path = None, task_suite: str = "standard"):
"""Initialize filesystem task manager."""
if tasks_root is None:
tasks_root = Path(__file__).resolve().parents[3] / "tasks"
super().__init__(
tasks_root,
mcp_service="filesystem",
task_class=FilesystemTask,
task_organization="directory",
task_suite=task_suite,
)
# Override only what's needed for filesystem-specific behavior
def _create_task_from_files(
self, category_id: str, task_files_info: Dict[str, Any]
) -> BaseTask:
"""Instantiate a `BaseTask` from the dictionary returned by `_find_task_files`."""
import json
# Support arbitrary task names, not just task_n format
task_name = task_files_info["task_id"]
# Use task_name as default task_id
task_id = task_name
# Check for meta.json
meta_path = task_files_info["instruction_path"].parent / "meta.json"
final_category_id = category_id
if meta_path.exists():
try:
with open(meta_path, 'r') as f:
meta_data = json.load(f)
# Use values from meta.json if available
final_category_id = meta_data.get("category_id", category_id)
task_id = meta_data.get("task_id", task_id)
except Exception as e:
logger.warning(f"Failed to load meta.json from {meta_path}: {e}")
return self.task_class(
task_instruction_path=task_files_info["instruction_path"],
task_verification_path=task_files_info["verification_path"],
service="filesystem",
category_id=final_category_id,
task_id=task_id,
)
def run_verification(self, task: BaseTask) -> subprocess.CompletedProcess:
"""Run verification with filesystem-specific environment."""
env = os.environ.copy()
# Pass test directory to verification script
# Priority: task.test_directory (set by state manager) > environment variable
test_dir = None
if hasattr(task, "test_directory") and task.test_directory:
test_dir = task.test_directory
else:
test_dir = os.getenv("FILESYSTEM_TEST_DIR")
if test_dir:
env["FILESYSTEM_TEST_DIR"] = test_dir
logger.debug(f"Setting FILESYSTEM_TEST_DIR to: {test_dir}")
return subprocess.run(
self._get_verification_command(task),
capture_output=True,
text=True,
timeout=300,
env=env,
)
def filter_tasks(self, task_filter: str) -> List[BaseTask]:
"""Filter tasks based on category or specific task pattern with support for arbitrary task names."""
all_tasks = self.discover_all_tasks()
if not task_filter or task_filter.lower() == "all":
return all_tasks
# Check if it's a category filter
categories = self.get_categories()
if task_filter in categories:
return [task for task in all_tasks if task.category_id == task_filter]
# Check for specific task pattern (category_id/task_X or category_id/arbitrary_name)
if "/" in task_filter:
try:
category_id, task_id = task_filter.split("/", 1)
# Direct string matching for task_id
for task in all_tasks:
if task.category_id == category_id and str(task.task_id) == task_id:
return [task]
except (ValueError, IndexError):
pass
# Fallback: check for partial matches in task names or categories
filtered_tasks = []
for task in all_tasks:
if (
task_filter in task.category_id
or task_filter in task.name
or task_filter == str(task.task_id)
):
filtered_tasks.append(task)
return filtered_tasks