Files
moss-ai/mcp/didatodolist-mcp/tools/task_tools.py
雷雨 8635b84b2d init
2025-12-15 22:05:56 +08:00

941 lines
35 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
任务相关MCP工具
"""
from typing import Dict, List, Optional, Any, Union
from datetime import datetime, timedelta
import pytz
from fastmcp import FastMCP
from .adapter import adapter, APIError
# --- 模块级辅助函数 ---
_completed_columns = set()
def _parse_date(date_str: Optional[str]) -> Optional[datetime]:
"""解析日期字符串为datetime对象将UTC时间转换为北京时间"""
if not date_str:
return None
local_tz = pytz.timezone('Asia/Shanghai')
try:
# 处理ISO格式
if 'T' in date_str:
base_time = date_str.split('.')[0]
if date_str.endswith('Z') or '+0000' in date_str:
# UTC时间需要转换
dt = datetime.strptime(base_time.replace('T', ' '), "%Y-%m-%d %H:%M:%S")
dt = pytz.UTC.localize(dt)
return dt.astimezone(local_tz)
else:
# 尝试使用fromisoformat
try:
dt = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
return dt.astimezone(local_tz)
except ValueError:
# 假定为本地时间
dt = datetime.strptime(base_time.replace('T', ' '), "%Y-%m-%d %H:%M:%S")
return local_tz.localize(dt)
except ValueError:
pass
try:
# 标准格式 (假定为本地时间)
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
return local_tz.localize(dt)
except ValueError:
# 尝试其他可能的格式
try:
dt = datetime.strptime(date_str, "%Y-%m-%d")
return local_tz.localize(dt)
except ValueError:
return None
def _format_date_for_api(date_str: Optional[str]) -> Optional[str]:
"""
'YYYY-MM-DD HH:MM:SS'格式的日期转换为API所需的'YYYY-MM-DDThh:mm:ss.000+0000'格式
Args:
date_str: 'YYYY-MM-DD HH:MM:SS'格式的日期字符串
Returns:
转换后的API格式日期字符串
"""
if not date_str:
return None
try:
# 解析输入的日期字符串为datetime对象假设为本地时间
local_tz = pytz.timezone('Asia/Shanghai')
# 尝试解析不同格式
try:
# 带时间的完整格式
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
except ValueError:
try:
# 仅日期格式
dt = datetime.strptime(date_str, "%Y-%m-%d")
except ValueError:
# 如果已经是ISO格式直接返回
if 'T' in date_str:
return date_str
# 其他格式无法解析
return date_str
# 将解析的datetime转换为本地时区的datetime
dt = local_tz.localize(dt)
# 转换为UTC时间
utc_dt = dt.astimezone(pytz.UTC)
# 格式化为API需要的格式YYYY-MM-DDThh:mm:ss.000+0000
return utc_dt.strftime("%Y-%m-%dT%H:%M:%S.000+0000")
except Exception as e:
# 日期格式转换错误禁用print避免干扰JSONRPC
pass
return date_str
def _simplify_task_data(task_data: Dict[str, Any], projects_data: List[Dict[str, Any]] = None) -> Dict[str, Any]:
"""简化任务数据,保留重要字段并格式化日期"""
# 格式化日期函数
def format_date(date_str, is_due_date=False):
if not date_str:
return None
dt = _parse_date(date_str)
if not dt:
return date_str
# 如果是截止日期且时间是0点考虑添加一天
if is_due_date and dt.hour == 0 and dt.minute == 0 and dt.second == 0:
dt = dt + timedelta(days=1)
return dt.strftime("%Y-%m-%d %H:%M:%S")
# 如果提供了项目数据列表且当前任务只有projectId但没有projectName则匹配项目名称
if projects_data and task_data.get('projectId') and not task_data.get('projectName'):
task_data = _merge_project_info_logic(task_data, projects_data)
# 处理子任务
children = []
if task_data.get('items'):
for item in task_data['items']:
# 递归调用,同时传递项目数据
child_task = _simplify_task_data(item, projects_data)
children.append(child_task)
# 创建基础任务数据
simplified = {
"id": task_data.get("id"),
"title": task_data.get("title"),
"content": task_data.get("content"),
"priority": task_data.get("priority"),
"status": task_data.get("status"),
"completed": task_data.get("isCompleted", False),
"projectId": task_data.get("projectId"),
"projectName": task_data.get("projectName", "默认清单"),
"projectKind": task_data.get("projectKind"),
"columnId": task_data.get("columnId"),
"tags": task_data.get("tags", []),
"tagDetails": task_data.get("tagDetails", []),
"startDate": format_date(task_data.get("startDate")),
"dueDate": format_date(task_data.get("dueDate"), is_due_date=True),
"completedTime": format_date(task_data.get("completedTime")),
"createdTime": format_date(task_data.get("createdTime")),
"modifiedTime": format_date(task_data.get("modifiedTime")),
"isAllDay": task_data.get("isAllDay", False),
"reminder": task_data.get("reminder"),
"progress": task_data.get("progress", 0),
"kind": task_data.get("kind"),
"isCompleted": task_data.get("isCompleted", False),
"items": children,
"timeZone": "Asia/Shanghai",
"reminders": task_data.get("reminders", []),
"creator": task_data.get("creator"),
"sortOrder": task_data.get("sortOrder", 0),
"parentId": task_data.get("parentId"),
"children": children
}
# 移除None值
simplified = {k: v for k, v in simplified.items() if v is not None}
return simplified
def _get_completed_tasks_info_logic() -> Dict[str, Any]:
"""(已废弃路径) 兼容占位官方API不提供旧批量接口返回空。"""
return {}
def _update_column_info_logic(projects: List[Dict[str, Any]], completed_columns_set: set):
"""更新栏目信息,识别已完成状态的栏目 (逻辑部分)"""
for project in projects:
if 'columns' in project:
for column in project.get('columns', []):
# 检查栏目是否为已完成状态
if column.get('type') == 'COMPLETED':
completed_columns_set.add(column.get('id'))
def _merge_project_info_logic(task_data: Dict[str, Any], projects: List[Dict[str, Any]]) -> Dict[str, Any]:
"""将项目信息合并到任务数据中 (逻辑部分)"""
if not task_data.get('projectId'):
return task_data
for project in projects:
if project.get('id') == task_data['projectId']:
task_data['projectName'] = project.get('name')
task_data['projectKind'] = project.get('kind')
break
return task_data
def _merge_tag_info_logic(task_data: Dict[str, Any], tags: List[Dict[str, Any]]) -> Dict[str, Any]:
"""将标签详细信息合并到任务数据中 (逻辑部分)"""
if not task_data.get('tags'):
return task_data
tag_details = []
for tag_name in task_data['tags']:
for tag in tags:
if tag.get('name') == tag_name:
tag_details.append({
'name': tag.get('name'),
'label': tag.get('label')
})
break
task_data['tagDetails'] = tag_details
return task_data
def _get_all_tasks_logic() -> tuple[List[Dict[str, Any]], List[Dict[str, Any]], List[Dict[str, Any]]]:
"""获取所有任务,包括已完成和未完成的任务,并合并相关信息 (逻辑部分)"""
global _completed_columns
# 使用官方接口获取项目与任务
projects_data = []
try:
projects_data = adapter.list_projects()
except Exception:
projects_data = []
# 官方任务接口通常需要分别获取未完成/已完成,视文档具体筛选实现
tasks_data: List[Dict[str, Any]] = []
tags_data: List[Dict[str, Any]] = [] # 若官方没有标签API则保留空集合
try:
# 遍历项目聚合任务(官方无全局列表端点)
incomplete = adapter.list_tasks(completed=False)
complete = adapter.list_tasks(completed=True)
tasks_data = (incomplete or []) + (complete or [])
except Exception as e:
# 获取任务列表失败禁用print避免干扰JSONRPC
pass
tasks_data = []
# 更新栏目信息 (使用全局变量)
_update_column_info_logic(projects_data, _completed_columns)
# 旧逻辑依赖批量端点合并“已完成”,现在已通过 adapter 分开获取,这里置空
completed_tasks_info = {}
# 处理所有任务(未完成+已完成)
all_tasks = []
# 处理未完成任务
for task in tasks_data:
# 只处理文本类型的任务
if task.get('kind') != 'TEXT':
continue
# 合并项目和标签信息
task = _merge_project_info_logic(task, projects_data)
task = _merge_tag_info_logic(task, tags_data)
# 检查是否在已完成任务列表中
key = f"{task.get('creator')}_{task.get('title')}"
# adapter.normalize_task_status 已处理 isCompleted/status这里不再强制覆盖
all_tasks.append(task)
# 不再需要从已完成任务列表补充adapter 已统一返回
return all_tasks, projects_data, tags_data
# --- 模块级核心逻辑函数 ---
def get_tasks_logic(
mode: Optional[str] = "all",
keyword: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
completed: Optional[bool] = None
) -> List[Dict[str, Any]]:
"""
获取任务列表 (逻辑部分)
Args:
mode: 任务模式,支持 'all'(所有), 'today'(今天), 'yesterday'(昨天), 'recent_7_days'(最近7天)
keyword: 关键词筛选
priority: 优先级筛选 (0-最低, 1-低, 3-中, 5-高)
project_name: 项目名称筛选
completed: 是否已完成True表示已完成False表示未完成None表示全部
Returns:
符合条件的任务列表
"""
try:
# 如果是查询今天的任务,默认只显示未完成的任务
if mode == "today" and completed is None:
completed = False
# 获取所有任务
all_tasks, projects_data, tags_data = _get_all_tasks_logic()
# 确保所有任务都有正确的project_name (在过滤之前)
for task in all_tasks:
if task.get('projectId') and not task.get('projectName'):
_merge_project_info_logic(task, projects_data)
def is_today(task):
# 检查任务是否为今天
local_tz = pytz.timezone('Asia/Shanghai')
now = datetime.now(local_tz)
today = now.date()
# 解析日期并获取日期部分
start_date = _parse_date(task.get('startDate'))
due_date = _parse_date(task.get('dueDate'))
# 简化判断逻辑:使用截止日期或开始日期判断
task_date = due_date or start_date
# 判断日期是否为今天
if task_date and task_date.date() == today:
return True
# 如果任务跨越今天(开始日期在今天之前,截止日期在今天之后或无截止日期)
if start_date and start_date.date() < today:
if not due_date or due_date.date() >= today:
return True
return False
def is_yesterday(task):
# 检查任务是否为昨天
local_tz = pytz.timezone('Asia/Shanghai')
now = datetime.now(local_tz)
yesterday = (now - timedelta(days=1)).date()
# 解析日期
start_date = _parse_date(task.get('startDate'))
due_date = _parse_date(task.get('dueDate'))
# 简化判断逻辑:使用截止日期或开始日期判断
task_date = due_date or start_date
return task_date and task_date.date() == yesterday
def is_recent_7_days(task):
# 检查任务是否属于最近7天
local_tz = pytz.timezone('Asia/Shanghai')
now = datetime.now(local_tz)
seven_days_ago = (now - timedelta(days=7))
# 解析日期
start_date = _parse_date(task.get('startDate'))
due_date = _parse_date(task.get('dueDate'))
# 简化判断逻辑:使用截止日期或开始日期判断
task_date = due_date or start_date
# 最近7天的任务
if task_date and task_date >= seven_days_ago:
return True
# 跨越这7天的任务
if start_date and start_date < seven_days_ago:
if due_date and due_date >= seven_days_ago:
return True
return False
# 过滤任务
result = []
for task in all_tasks:
# 根据完成状态筛选
if completed is not None:
is_task_completed = task.get('isCompleted', False)
if is_task_completed != completed:
continue
# 根据模式筛选
if mode == "today" and not is_today(task):
continue
elif mode == "yesterday" and not is_yesterday(task):
continue
elif mode == "recent_7_days" and not is_recent_7_days(task):
continue
# 根据其他条件筛选
if keyword and keyword.lower() not in task.get('title', '').lower() and keyword.lower() not in task.get('content', '').lower():
continue
if priority is not None and task.get('priority') != priority:
continue
# 根据项目名称筛选 (现在任务已经有了正确的project_name)
if project_name and project_name not in task.get('projectName', ''):
continue
# 保留简化后的任务数据,传递项目数据
simplified_task = _simplify_task_data(task, projects_data)
result.append(simplified_task)
return result
except Exception as e:
# 获取任务列表时发生错误禁用print避免干扰JSONRPC
pass
return []
def create_task_logic(
title: Optional[str] = None,
content: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
tag_names: Optional[List[str]] = None,
start_date: Optional[str] = None,
due_date: Optional[str] = None,
is_all_day: Optional[bool] = None,
reminder: Optional[str] = None,
kind: Optional[str] = None,
# 官方字段(新增)
project_id: Optional[str] = None,
desc: Optional[str] = None,
time_zone: Optional[str] = None,
reminders: Optional[List[str]] = None,
repeat_flag: Optional[str] = None,
sort_order: Optional[int] = None,
items: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]:
"""
创建新任务 (逻辑部分)
Args:
title: 任务标题
content: 任务内容
priority: 优先级 (0-最低, 1-低, 3-中, 5-高)
project_name: 项目名称
tag_names: 标签名称列表
start_date: 开始日期,格式 'YYYY-MM-DD HH:MM:SS'
due_date: 截止日期,格式 'YYYY-MM-DD HH:MM:SS'
is_all_day: 是否为全天任务
reminder: 提醒选项,如 "0"(准时), "-5M"(提前5分钟), "-1H"(提前1小时), "-1D"(提前1天)
Returns:
创建的任务信息
"""
resolved_project_id = project_id
projects_data = adapter.list_projects()
if not resolved_project_id and project_name:
# 尝试精确匹配
for project in projects_data:
if project.get('name') == project_name:
resolved_project_id = project.get('id')
break
# 如果精确匹配失败,尝试不区分大小写的匹配
if not resolved_project_id and project_name:
project_name_lower = project_name.lower()
for project in projects_data:
if project.get('name', '').lower() == project_name_lower:
# 不区分大小写匹配到项目禁用print避免干扰JSONRPC
pass
resolved_project_id = project.get('id')
break
# 如果仍然失败,尝试部分匹配
if not resolved_project_id and project_name:
for project in projects_data:
if project_name.lower() in project.get('name', '').lower() or project.get('name', '').lower() in project_name.lower():
# 部分匹配到项目禁用print避免干扰JSONRPC
pass
resolved_project_id = project.get('id')
break
# 准备任务数据
task_data = {
"title": title,
"content": content,
"priority": priority,
"projectId": resolved_project_id,
# 官方任务未公开 tags 字段,保留为兼容逻辑但不强制发送
# "tags": tag_names or [],
"isAllDay": is_all_day,
"reminder": reminder,
"status": 0,
"kind": kind,
# 官方字段
"desc": desc,
"timeZone": time_zone,
"reminders": reminders,
"repeatFlag": repeat_flag,
"sortOrder": sort_order,
"items": items,
}
# 处理日期和提醒
if start_date:
# 转换为API所需的格式
task_data["startDate"] = _format_date_for_api(start_date)
if due_date:
# 转换为API所需的格式
task_data["dueDate"] = _format_date_for_api(due_date)
if reminder:
task_data["reminder"] = reminder
# 移除None值的字段
task_data = {k: v for k, v in task_data.items() if v is not None}
# Debug: task_data (禁用print以避免干扰JSONRPC)
# 发送创建请求
response = adapter.create_task(task_data)
# 返回简化后的响应,同时传递项目数据
return _simplify_task_data(response, projects_data)
def update_task_logic(
task_id_or_title: str,
title: Optional[str] = None,
content: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
tag_names: Optional[List[str]] = None,
start_date: Optional[str] = None,
due_date: Optional[str] = None,
is_all_day: Optional[bool] = None,
reminder: Optional[str] = None,
status: Optional[int] = None,
# 官方字段(新增)
project_id: Optional[str] = None,
desc: Optional[str] = None,
time_zone: Optional[str] = None,
reminders: Optional[List[str]] = None,
repeat_flag: Optional[str] = None,
sort_order: Optional[int] = None,
items: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]:
"""
更新任务 (逻辑部分)
Args:
task_id_or_title: 任务ID或任务标题
title: 新任务标题
content: 新任务内容
priority: 新优先级 (0-最低, 1-低, 3-中, 5-高)
project_name: 新项目名称
tag_names: 新标签名称列表
start_date: 新开始日期,格式 'YYYY-MM-DD HH:MM:SS'
due_date: 新截止日期,格式 'YYYY-MM-DD HH:MM:SS'
is_all_day: 是否为全天任务
reminder: 新提醒选项
status: 新状态0表示未完成2表示已完成
Returns:
更新后的任务信息字典 (包含 success, info, data)
"""
try:
# 获取所有任务
all_tasks, projects_data, _ = _get_all_tasks_logic()
# 查找任务
task = None
# 先尝试按ID查找
for t in all_tasks:
if t.get('id') == task_id_or_title:
task = t
break
# 如果没找到,按标题查找
if not task:
for t in all_tasks:
if t.get('title') == task_id_or_title:
task = t
break
if not task:
return {
"success": False,
"info": f"未找到ID或标题为 '{task_id_or_title}' 的任务",
"data": None
}
task_id = task.get('id')
# 查找项目ID如果指定了项目名称
project_id = project_id or task.get('projectId')
if project_name and not project_id:
for project in projects_data:
if project.get('name') == project_name:
project_id = project.get('id')
break
# 准备更新数据
update_data = {
"id": task_id,
"title": title if title is not None else task.get('title'),
"content": content if content is not None else task.get('content'),
"priority": priority if priority is not None else task.get('priority'),
"projectId": project_id,
# 官方未公开 tags 写入,去除发送
"isAllDay": is_all_day if is_all_day is not None else task.get('isAllDay'),
"status": status if status is not None else task.get('status'),
# 官方字段
"desc": desc if desc is not None else task.get('desc'),
"timeZone": time_zone if time_zone is not None else task.get('timeZone'),
"reminders": reminders if reminders is not None else task.get('reminders'),
"repeatFlag": repeat_flag if repeat_flag is not None else task.get('repeatFlag'),
"sortOrder": sort_order if sort_order is not None else task.get('sortOrder'),
"items": items if items is not None else task.get('items'),
}
# 处理日期和提醒
if start_date is not None:
# 转换为API所需的格式
update_data["startDate"] = _format_date_for_api(start_date)
elif 'startDate' in task:
update_data["startDate"] = task['startDate']
if due_date is not None:
# 转换为API所需的格式
update_data["dueDate"] = _format_date_for_api(due_date)
elif 'dueDate' in task:
update_data["dueDate"] = task['dueDate']
if reminder is not None:
update_data["reminder"] = reminder
elif 'reminder' in task:
update_data["reminder"] = task['reminder']
# 移除None值的字段
update_data = {k: v for k, v in update_data.items() if v is not None}
# 状态变更:对齐官方逻辑(仅支持完成)
if status is not None:
if status == 2:
if not project_id:
return {
"success": False,
"info": "完成任务失败:缺少 projectId",
"data": None
}
try:
adapter.complete_task(project_id, task_id)
# 完成后刷新一次该项目任务,返回最新数据
refreshed = adapter.list_tasks(project_id=project_id)
fresh = next((t for t in refreshed if t.get('id') == task_id), None)
if fresh:
return {
"success": True,
"info": "任务已完成",
"data": _simplify_task_data(fresh, projects_data)
}
except Exception as e:
return {
"success": False,
"info": f"完成任务失败: {e}",
"data": None
}
# 若无法刷新,基于原任务构造完成态返回
task_after = dict(task)
task_after['status'] = 2
task_after['isCompleted'] = True
return {
"success": True,
"info": "任务已完成",
"data": _simplify_task_data(task_after, projects_data)
}
elif status == 0:
return {
"success": False,
"info": "取消完成未在官方开放API中提供暂不支持",
"data": None
}
# 非状态变更:走常规更新
# Debug: 更新数据禁用print避免干扰JSONRPC
pass
response = adapter.update_task(task_id, update_data)
# 返回更新结果
return {
"success": True,
"info": "任务更新成功",
"data": _simplify_task_data(response, projects_data)
}
except Exception as e:
# 更新任务失败禁用print避免干扰JSONRPC
return {
"success": False,
"info": f"更新任务失败: {str(e)}",
"data": None
}
def delete_task_logic(task_id_or_title: str) -> Dict[str, Any]:
"""
删除任务 (逻辑部分)
Args:
task_id_or_title: 任务ID或任务标题
Returns:
删除操作的响应字典 (包含 success, info, data)
"""
try:
# 获取所有任务
all_tasks, projects_data, _ = _get_all_tasks_logic()
task = None
# 先尝试按ID查找
for t in all_tasks:
if t.get('id') == task_id_or_title:
task = t
break
# 如果没找到,按标题查找
if not task:
for t in all_tasks:
if t.get('title') == task_id_or_title:
task = t
break
if not task:
return {
"success": False,
"info": f"未找到ID或标题为 '{task_id_or_title}' 的任务",
"data": None
}
task_id = task.get('id')
project_id = task.get('projectId')
# 发送删除请求
# 官方删除需要 projectId
adapter.delete_task(project_id, task_id)
# 返回删除结果
return {
"success": True,
"info": f"成功删除任务 '{task.get('title')}'",
"data": _simplify_task_data(task, projects_data)
}
except Exception as e:
# 删除任务失败禁用print避免干扰JSONRPC
return {
"success": False,
"info": f"删除任务失败: {str(e)}",
"data": None
}
def complete_task_logic(task_id_or_title: str) -> Dict[str, Any]:
"""
完成任务(调用官方 complete 接口)
Args:
task_id_or_title: 任务ID或任务标题
Returns:
操作结果字典
"""
try:
all_tasks, projects_data, _ = _get_all_tasks_logic()
task = None
for t in all_tasks:
if t.get('id') == task_id_or_title or t.get('title') == task_id_or_title:
task = t
break
if not task:
return {
"success": False,
"info": f"未找到ID或标题为 '{task_id_or_title}' 的任务",
"data": None
}
task_id = task.get('id')
project_id = task.get('projectId')
if not project_id:
return {
"success": False,
"info": "完成任务失败:缺少 projectId",
"data": None
}
adapter.complete_task(project_id, task_id)
# 刷新该项目任务,返回最新数据
refreshed = adapter.list_tasks(project_id=project_id)
fresh = next((t for t in refreshed if t.get('id') == task_id), None)
if fresh:
return {
"success": True,
"info": "任务已完成",
"data": _simplify_task_data(fresh, projects_data)
}
# 无法刷新则回退构造
task_after = dict(task)
task_after['status'] = 2
task_after['isCompleted'] = True
return {
"success": True,
"info": "任务已完成",
"data": _simplify_task_data(task_after, projects_data)
}
except Exception as e:
return {
"success": False,
"info": f"完成任务失败: {e}",
"data": None
}
# --- MCP工具注册 ---
def register_task_tools(server: FastMCP, auth_info: Dict[str, Any]):
"""
注册任务相关工具到MCP服务器
Args:
server: MCP服务器实例
auth_info: 认证信息字典包含token或email/password
"""
# 适配层按需初始化,无需在此显式初始化
@server.tool()
def get_tasks(
mode: Optional[str] = "all",
keyword: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
completed: Optional[bool] = None
) -> List[Dict[str, Any]]:
"""
获取任务列表
(调用模块级逻辑函数)
Args:
mode: 任务模式,支持 'all'(所有), 'today'(今天), 'yesterday'(昨天), 'recent_7_days'(最近7天)
keyword: 关键词筛选
priority: 优先级筛选 (0-最低, 1-低, 3-中, 5-高)
project_name: 项目名称筛选
completed: 是否已完成True表示已完成False表示未完成None表示全部
Returns:
符合条件的任务列表
"""
return get_tasks_logic(mode=mode, keyword=keyword, priority=priority, project_name=project_name, completed=completed)
@server.tool()
def create_task(
title: Optional[str] = None,
content: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
tag_names: Optional[List[str]] = None,
start_date: Optional[str] = None,
due_date: Optional[str] = None,
is_all_day: Optional[bool] = None,
reminder: Optional[str] = None,
# 官方字段(新增)
project_id: Optional[str] = None,
desc: Optional[str] = None,
time_zone: Optional[str] = None,
reminders: Optional[List[str]] = None,
repeat_flag: Optional[str] = None,
sort_order: Optional[int] = None,
items: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]:
"""
创建新任务
(调用模块级逻辑函数)
Args:
title: 任务标题
content: 任务内容
priority: 优先级 (0-最低, 1-低, 3-中, 5-高)
project_name: 项目名称
tag_names: 标签名称列表
start_date: 开始日期,格式 'YYYY-MM-DD HH:MM:SS'会自动转换为API所需的时区和格式
due_date: 截止日期,格式 'YYYY-MM-DD HH:MM:SS'会自动转换为API所需的时区和格式
is_all_day: 是否为全天任务
reminder: 提醒选项,如 "0"(准时), "-5M"(提前5分钟), "-1H"(提前1小时), "-1D"(提前1天)
Returns:
创建的任务信息
"""
return create_task_logic(title=title, content=content, priority=priority, project_name=project_name, tag_names=tag_names, start_date=start_date, due_date=due_date, is_all_day=is_all_day, reminder=reminder, project_id=project_id, desc=desc, time_zone=time_zone, reminders=reminders, repeat_flag=repeat_flag, sort_order=sort_order, items=items)
@server.tool()
def update_task(
task_id_or_title: str,
title: Optional[str] = None,
content: Optional[str] = None,
priority: Optional[int] = None,
project_name: Optional[str] = None,
tag_names: Optional[List[str]] = None,
start_date: Optional[str] = None,
due_date: Optional[str] = None,
is_all_day: Optional[bool] = None,
reminder: Optional[str] = None,
status: Optional[int] = None
) -> Dict[str, Any]:
"""
更新任务
(调用模块级逻辑函数)
Args:
task_id_or_title: 任务ID或任务标题
title: 新任务标题
content: 新任务内容
priority: 新优先级 (0-最低, 1-低, 3-中, 5-高)
project_name: 新项目名称
tag_names: 新标签名称列表
start_date: 新开始日期,格式 'YYYY-MM-DD HH:MM:SS'会自动转换为API所需的时区和格式
due_date: 新截止日期,格式 'YYYY-MM-DD HH:MM:SS'会自动转换为API所需的时区和格式
is_all_day: 是否为全天任务
reminder: 新提醒选项
status: 新状态0表示未完成2表示已完成
Returns:
更新后的任务信息
"""
return update_task_logic(task_id_or_title=task_id_or_title, title=title, content=content, priority=priority, project_name=project_name, tag_names=tag_names, start_date=start_date, due_date=due_date, is_all_day=is_all_day, reminder=reminder, status=status)
@server.tool()
def delete_task(task_id_or_title: str) -> Dict[str, Any]:
"""
删除任务
(调用模块级逻辑函数)
Args:
task_id_or_title: 任务ID或任务标题
Returns:
删除操作的响应
"""
return delete_task_logic(task_id_or_title=task_id_or_title)
@server.tool()
def complete_task(task_id_or_title: str) -> Dict[str, Any]:
"""
完成任务官方POST /open/v1/project/{projectId}/task/{taskId}/complete
Args:
task_id_or_title: 任务ID或任务标题
Returns:
操作结果
"""
return complete_task_logic(task_id_or_title)
# 导出可供外部引用的函数
__all__ = [
'get_tasks_logic',
'create_task_logic',
'update_task_logic',
'delete_task_logic',
'complete_task_logic',
'register_task_tools',
'_get_all_tasks_logic' # 如果需要外部访问
]