"""TaskCreateTool — create a new task in the current conversation scope. Persists tasks as JSON files under ``~/.cache/crystal/tasks/{conversation_id}/``. """ from __future__ import annotations from typing import Any, ClassVar from ..base import Tool, ToolParameter, ToolResult from .task_storage import TaskStorage class TaskCreateTool(Tool): """Create a new task with subject, description, and optional activeForm.""" name: ClassVar[str] = "task_create" description: ClassVar[str] = ( "Create a new task for tracking work. Returns the created task " "with a unique ID and 'pending' status." ) parameters: ClassVar[list[ToolParameter]] = [ ToolParameter( name="subject", type="string", description="Brief, actionable title in imperative form (e.g. 'Fix auth bug')", ), ToolParameter( name="description", type="string", description="Detailed description of what needs to be done", ), ToolParameter( name="activeForm", type="string", description=( "Present continuous form shown while task is in progress " "(e.g. 'Fixing auth bug')" ), required=False, ), ToolParameter( name="conversation_id", type="string", description="Conversation scope for task storage", ), ] async def execute(self, **kwargs: Any) -> ToolResult: conversation_id: str = kwargs["conversation_id"] subject: str = kwargs["subject"] description: str = kwargs["description"] active_form: str | None = kwargs.get("activeForm") if not subject.strip(): return ToolResult.fail("Subject cannot be empty") if not description.strip(): return ToolResult.fail("Description cannot be empty") storage = TaskStorage(conversation_id) task = storage.create( subject=subject, description=description, active_form=active_form, ) return ToolResult.success(task)