File size: 5,267 Bytes
310260a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Update Task MCP Tool

This tool enables the AI agent to update existing task details.
Supports updating title and/or description.
"""

from typing import Dict, Any, Optional
from sqlmodel import Session, select
from datetime import datetime
from ..models.task import Task
from .mcp_server import MCPContext


async def update_task_internal(
    ctx: MCPContext,
    task_id: int,
    title: Optional[str] = None,
    description: Optional[str] = None
) -> Dict[str, Any]:
    """
    Internal MCP tool for updating a task's details.

    This function is called by the AgentService with user_id pre-bound.
    It updates the task's title and/or description.

    Args:
        ctx: MCP context containing db_engine and user_id
        task_id: ID of the task to update
        title: New task title (optional, 1-200 chars)
        description: New task description (optional, max 2000 chars)

    Returns:
        Dict containing:
            - task: Updated task details
            - status: "success" or "error"
            - error: Error message (only if status is "error")

    Error Cases:
        - Task not found: Returns error "Task not found"
        - Task belongs to different user: Returns error "Task not found" (security)
        - Empty title: Returns error "Title cannot be empty"
        - Title too long: Returns error "Title exceeds 200 characters"
        - No fields to update: Returns error "No fields provided to update"
        - Database error: Returns error with message
    """
    try:
        # Validate that at least one field is provided
        if title is None and description is None:
            return {
                "status": "error",
                "error": "No fields provided to update"
            }

        # Validate title if provided
        if title is not None:
            title = title.strip()
            if not title:
                return {
                    "status": "error",
                    "error": "Title cannot be empty"
                }
            if len(title) > 200:
                return {
                    "status": "error",
                    "error": "Title exceeds 200 characters"
                }

        # Validate description length if provided
        if description is not None and len(description) > 2000:
            return {
                "status": "error",
                "error": "Description exceeds 2000 characters"
            }

        # Query task with user_id scoping for security
        with ctx.get_session() as session:
            statement = select(Task).where(
                Task.id == task_id,
                Task.user_id == ctx.user_id
            )
            task = session.exec(statement).first()

            if not task:
                return {
                    "status": "error",
                    "error": "Task not found"
                }

            # Update fields
            if title is not None:
                task.title = title
            if description is not None:
                task.description = description

            task.updated_at = datetime.utcnow()

            session.add(task)
            session.commit()
            session.refresh(task)

            # Return structured result
            return {
                "status": "success",
                "task": {
                    "id": task.id,
                    "title": task.title,
                    "description": task.description,
                    "completed": task.completed,
                    "created_at": task.created_at.isoformat(),
                    "updated_at": task.updated_at.isoformat()
                }
            }

    except Exception as e:
        # Log error and return structured error response
        print(f"Error updating task: {str(e)}")
        return {
            "status": "error",
            "error": f"Database error: {str(e)}"
        }


def get_tool_definition() -> Dict[str, Any]:
    """
    Get OpenAI function calling definition for update_task tool.

    Returns:
        Tool definition in OpenAI function calling format
    """
    return {
        "type": "function",
        "function": {
            "name": "update_task",
            "description": (
                "Update an existing task's title or description. "
                "Use this when the user wants to modify, change, or edit a task. "
                "Examples: 'change X to Y', 'update the task', 'edit task 3', "
                "'rename X to Y', 'add details to the task'."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "task_id": {
                        "type": "integer",
                        "description": "The ID of the task to update"
                    },
                    "title": {
                        "type": "string",
                        "description": "New task title (optional, 1-200 characters)"
                    },
                    "description": {
                        "type": "string",
                        "description": "New task description (optional, max 2000 characters)"
                    }
                },
                "required": ["task_id"]
            }
        }
    }