69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
|
|
"""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)
|