@doist/todoist-ai 4.0.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/index.d.ts +381 -13
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +13 -1
  4. package/dist/mcp-server.d.ts.map +1 -1
  5. package/dist/mcp-server.js +2 -0
  6. package/dist/tools/__tests__/find-completed-tasks.test.js +136 -2
  7. package/dist/tools/__tests__/find-tasks-by-date.test.js +121 -2
  8. package/dist/tools/__tests__/find-tasks.test.js +257 -10
  9. package/dist/tools/__tests__/update-sections.test.js +1 -0
  10. package/dist/tools/__tests__/user-info.test.d.ts +2 -0
  11. package/dist/tools/__tests__/user-info.test.d.ts.map +1 -0
  12. package/dist/tools/__tests__/user-info.test.js +139 -0
  13. package/dist/tools/add-comments.d.ts +25 -2
  14. package/dist/tools/add-comments.d.ts.map +1 -1
  15. package/dist/tools/add-projects.d.ts +46 -2
  16. package/dist/tools/add-projects.d.ts.map +1 -1
  17. package/dist/tools/add-sections.d.ts +14 -2
  18. package/dist/tools/add-sections.d.ts.map +1 -1
  19. package/dist/tools/add-tasks.d.ts +3 -3
  20. package/dist/tools/find-comments.d.ts +25 -2
  21. package/dist/tools/find-comments.d.ts.map +1 -1
  22. package/dist/tools/find-completed-tasks.d.ts +8 -2
  23. package/dist/tools/find-completed-tasks.d.ts.map +1 -1
  24. package/dist/tools/find-completed-tasks.js +19 -3
  25. package/dist/tools/find-tasks-by-date.d.ts +6 -0
  26. package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
  27. package/dist/tools/find-tasks-by-date.js +18 -1
  28. package/dist/tools/find-tasks.d.ts +6 -0
  29. package/dist/tools/find-tasks.d.ts.map +1 -1
  30. package/dist/tools/find-tasks.js +63 -9
  31. package/dist/tools/update-comments.d.ts +25 -2
  32. package/dist/tools/update-comments.d.ts.map +1 -1
  33. package/dist/tools/update-projects.d.ts +46 -2
  34. package/dist/tools/update-projects.d.ts.map +1 -1
  35. package/dist/tools/update-sections.d.ts +14 -2
  36. package/dist/tools/update-sections.d.ts.map +1 -1
  37. package/dist/tools/update-tasks.d.ts +3 -3
  38. package/dist/tools/user-info.d.ts +44 -0
  39. package/dist/tools/user-info.d.ts.map +1 -0
  40. package/dist/tools/user-info.js +142 -0
  41. package/dist/utils/labels.d.ts +10 -0
  42. package/dist/utils/labels.d.ts.map +1 -0
  43. package/dist/utils/labels.js +18 -0
  44. package/dist/utils/test-helpers.d.ts.map +1 -1
  45. package/dist/utils/test-helpers.js +1 -0
  46. package/dist/utils/tool-names.d.ts +1 -0
  47. package/dist/utils/tool-names.d.ts.map +1 -1
  48. package/dist/utils/tool-names.js +1 -0
  49. package/package.json +3 -3
@@ -0,0 +1,139 @@
1
+ import { jest } from '@jest/globals';
2
+ import { TEST_ERRORS, extractStructuredContent, extractTextContent, } from '../../utils/test-helpers.js';
3
+ import { ToolNames } from '../../utils/tool-names.js';
4
+ import { userInfo } from '../user-info.js';
5
+ // Mock the Todoist API
6
+ const mockTodoistApi = {
7
+ getUser: jest.fn(),
8
+ };
9
+ const { USER_INFO } = ToolNames;
10
+ // Helper function to create a mock user with default values that can be overridden
11
+ function createMockUser(overrides = {}) {
12
+ return {
13
+ id: '123',
14
+ fullName: 'Test User',
15
+ email: 'test@example.com',
16
+ isPremium: true,
17
+ completedToday: 12,
18
+ dailyGoal: 10,
19
+ weeklyGoal: 100,
20
+ startDay: 1, // Monday
21
+ tzInfo: {
22
+ timezone: 'Europe/Madrid',
23
+ gmtString: '+02:00',
24
+ hours: 2,
25
+ minutes: 0,
26
+ isDst: 1,
27
+ },
28
+ lang: 'en',
29
+ avatarBig: 'https://example.com/avatar.jpg',
30
+ avatarMedium: null,
31
+ avatarS640: null,
32
+ avatarSmall: null,
33
+ karma: 86394.0,
34
+ karmaTrend: 'up',
35
+ nextWeek: 1,
36
+ weekendStartDay: 6,
37
+ timeFormat: 0,
38
+ dateFormat: 0,
39
+ daysOff: [6, 7],
40
+ businessAccountId: null,
41
+ completedCount: 102920,
42
+ inboxProjectId: '6PVw8cMf7m8fWwRp',
43
+ startPage: 'overdue',
44
+ ...overrides,
45
+ };
46
+ }
47
+ describe(`${USER_INFO} tool`, () => {
48
+ beforeEach(() => {
49
+ jest.clearAllMocks();
50
+ });
51
+ it('should generate user info with all required fields', async () => {
52
+ const mockUser = createMockUser();
53
+ mockTodoistApi.getUser.mockResolvedValue(mockUser);
54
+ const result = await userInfo.execute({}, mockTodoistApi);
55
+ expect(mockTodoistApi.getUser).toHaveBeenCalledWith();
56
+ // Test text content contains expected information
57
+ const textContent = extractTextContent(result);
58
+ expect(textContent).toContain('User ID:** 123');
59
+ expect(textContent).toContain('Test User');
60
+ expect(textContent).toContain('test@example.com');
61
+ expect(textContent).toContain('Europe/Madrid');
62
+ expect(textContent).toContain('Monday (1)');
63
+ expect(textContent).toContain('Completed Today:** 12');
64
+ expect(textContent).toContain('Plan:** Todoist Pro');
65
+ // Test structured content
66
+ const structuredContent = extractStructuredContent(result);
67
+ expect(structuredContent).toEqual(expect.objectContaining({
68
+ type: 'user_info',
69
+ userId: '123',
70
+ fullName: 'Test User',
71
+ email: 'test@example.com',
72
+ timezone: 'Europe/Madrid',
73
+ startDay: 1,
74
+ startDayName: 'Monday',
75
+ completedToday: 12,
76
+ dailyGoal: 10,
77
+ weeklyGoal: 100,
78
+ plan: 'Todoist Pro',
79
+ currentLocalTime: expect.any(String),
80
+ weekStartDate: expect.any(String),
81
+ weekEndDate: expect.any(String),
82
+ currentWeekNumber: expect.any(Number),
83
+ }));
84
+ // Verify date formats
85
+ expect(structuredContent.weekStartDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
86
+ expect(structuredContent.weekEndDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
87
+ expect(structuredContent.currentLocalTime).toMatch(/^\d{2}\/\d{2}\/\d{4}, \d{2}:\d{2}:\d{2}$/);
88
+ });
89
+ it('should handle missing timezone info', async () => {
90
+ const mockUser = createMockUser({
91
+ isPremium: false,
92
+ tzInfo: {
93
+ timezone: 'UTC',
94
+ gmtString: '+00:00',
95
+ hours: 0,
96
+ minutes: 0,
97
+ isDst: 0,
98
+ },
99
+ });
100
+ mockTodoistApi.getUser.mockResolvedValue(mockUser);
101
+ const result = await userInfo.execute({}, mockTodoistApi);
102
+ const textContent = extractTextContent(result);
103
+ expect(textContent).toContain('UTC'); // Should default to UTC
104
+ expect(textContent).toContain('Monday (1)'); // Should default to Monday
105
+ expect(textContent).toContain('Plan:** Todoist Free');
106
+ const structuredContent = extractStructuredContent(result);
107
+ expect(structuredContent.timezone).toBe('UTC');
108
+ expect(structuredContent.startDay).toBe(1);
109
+ expect(structuredContent.startDayName).toBe('Monday');
110
+ expect(structuredContent.plan).toBe('Todoist Free');
111
+ });
112
+ it('should handle invalid timezone and fallback to UTC', async () => {
113
+ const mockUser = createMockUser({
114
+ startDay: 2, // Tuesday
115
+ tzInfo: {
116
+ timezone: 'Invalid/Timezone',
117
+ gmtString: '+05:30',
118
+ hours: 5,
119
+ minutes: 30,
120
+ isDst: 0,
121
+ },
122
+ });
123
+ mockTodoistApi.getUser.mockResolvedValue(mockUser);
124
+ const result = await userInfo.execute({}, mockTodoistApi);
125
+ const textContent = extractTextContent(result);
126
+ expect(textContent).toContain('UTC'); // Should fallback to UTC
127
+ expect(textContent).toContain('Tuesday (2)');
128
+ const structuredContent = extractStructuredContent(result);
129
+ expect(structuredContent.timezone).toBe('UTC'); // Should be UTC, not the invalid timezone
130
+ expect(structuredContent.startDay).toBe(2);
131
+ expect(structuredContent.startDayName).toBe('Tuesday');
132
+ expect(structuredContent.currentLocalTime).toMatch(/^\d{2}\/\d{2}\/\d{4}, \d{2}:\d{2}:\d{2}$/);
133
+ });
134
+ it('should propagate API errors', async () => {
135
+ const apiError = new Error(TEST_ERRORS.API_UNAUTHORIZED);
136
+ mockTodoistApi.getUser.mockRejectedValue(apiError);
137
+ await expect(userInfo.execute({}, mockTodoistApi)).rejects.toThrow(TEST_ERRORS.API_UNAUTHORIZED);
138
+ });
139
+ });
@@ -1,4 +1,3 @@
1
- import type { Comment } from '@doist/todoist-api-typescript';
2
1
  import { z } from 'zod';
3
2
  declare const addComments: {
4
3
  name: "add-comments";
@@ -30,7 +29,31 @@ declare const addComments: {
30
29
  text: string;
31
30
  }[];
32
31
  structuredContent: {
33
- comments: Comment[];
32
+ comments: {
33
+ taskId: string | undefined;
34
+ id: string;
35
+ content: string;
36
+ postedAt: string;
37
+ fileAttachment: {
38
+ resourceType: string;
39
+ fileName?: string | null | undefined;
40
+ fileSize?: number | null | undefined;
41
+ fileType?: string | null | undefined;
42
+ fileUrl?: string | null | undefined;
43
+ fileDuration?: number | null | undefined;
44
+ uploadState?: "pending" | "completed" | null | undefined;
45
+ image?: string | null | undefined;
46
+ imageWidth?: number | null | undefined;
47
+ imageHeight?: number | null | undefined;
48
+ url?: string | null | undefined;
49
+ title?: string | null | undefined;
50
+ } | null;
51
+ postedUid: string;
52
+ uidsToNotify: string[] | null;
53
+ reactions: Record<string, string[]> | null;
54
+ isDeleted: boolean;
55
+ projectId?: string | undefined;
56
+ }[];
34
57
  totalCount: number;
35
58
  addedCommentIds: string[];
36
59
  };
@@ -1 +1 @@
1
- {"version":3,"file":"add-comments.d.ts","sourceRoot":"","sources":["../../src/tools/add-comments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAC5E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAkBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CyB,CAAA;AA6C1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"add-comments.d.ts","sourceRoot":"","sources":["../../src/tools/add-comments.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAkBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAwFggV,CAAC;4BAA6C,CAAC;4BAA6C,CAAC;2BAA4C,CAAC;gCAAiD,CAAC;+BAAgD,CAAC;yBAA2D,CAAC;8BAA+C,CAAC;+BAAgD,CAAC;uBAAwC,CAAC;yBAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;CA9Cr8V,CAAA;AA6C1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -1,4 +1,3 @@
1
- import type { PersonalProject, WorkspaceProject } from '@doist/todoist-api-typescript';
2
1
  import { z } from 'zod';
3
2
  declare const addProjects: {
4
3
  name: "add-projects";
@@ -30,7 +29,52 @@ declare const addProjects: {
30
29
  text: string;
31
30
  }[];
32
31
  structuredContent: {
33
- projects: (PersonalProject | WorkspaceProject)[];
32
+ projects: ({
33
+ url: string;
34
+ id: string;
35
+ canAssignTasks: boolean;
36
+ childOrder: number;
37
+ color: string;
38
+ createdAt: string | null;
39
+ isArchived: boolean;
40
+ isDeleted: boolean;
41
+ isFavorite: boolean;
42
+ isFrozen: boolean;
43
+ name: string;
44
+ updatedAt: string | null;
45
+ viewStyle: string;
46
+ defaultOrder: number;
47
+ description: string;
48
+ isCollapsed: boolean;
49
+ isShared: boolean;
50
+ parentId: string | null;
51
+ inboxProject: boolean;
52
+ } | {
53
+ url: string;
54
+ id: string;
55
+ canAssignTasks: boolean;
56
+ childOrder: number;
57
+ color: string;
58
+ createdAt: string | null;
59
+ isArchived: boolean;
60
+ isDeleted: boolean;
61
+ isFavorite: boolean;
62
+ isFrozen: boolean;
63
+ name: string;
64
+ updatedAt: string | null;
65
+ viewStyle: string;
66
+ defaultOrder: number;
67
+ description: string;
68
+ isCollapsed: boolean;
69
+ isShared: boolean;
70
+ collaboratorRoleDefault: string;
71
+ folderId: string | null;
72
+ isInviteOnly: boolean | null;
73
+ isLinkSharingEnabled: boolean;
74
+ role: string | null;
75
+ status: string;
76
+ workspaceId: string;
77
+ })[];
34
78
  totalCount: number;
35
79
  };
36
80
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"add-projects.d.ts","sourceRoot":"","sources":["../../src/tools/add-projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AACtF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgByB,CAAA;AAmC1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"add-projects.d.ts","sourceRoot":"","sources":["../../src/tools/add-projects.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAwBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgByB,CAAA;AAmC1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -1,4 +1,3 @@
1
- import type { Section } from '@doist/todoist-api-typescript';
2
1
  import { z } from 'zod';
3
2
  declare const addSections: {
4
3
  name: "add-sections";
@@ -26,7 +25,20 @@ declare const addSections: {
26
25
  text: string;
27
26
  }[];
28
27
  structuredContent: {
29
- sections: Section[];
28
+ sections: {
29
+ url: string;
30
+ id: string;
31
+ userId: string;
32
+ projectId: string;
33
+ addedAt: string;
34
+ updatedAt: string;
35
+ archivedAt: string | null;
36
+ name: string;
37
+ sectionOrder: number;
38
+ isArchived: boolean;
39
+ isDeleted: boolean;
40
+ isCollapsed: boolean;
41
+ }[];
30
42
  totalCount: number;
31
43
  };
32
44
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"add-sections.d.ts","sourceRoot":"","sources":["../../src/tools/add-sections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAiBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgByB,CAAA;AAiD1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"add-sections.d.ts","sourceRoot":"","sources":["../../src/tools/add-sections.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAiBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgByB,CAAA;AAiD1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
@@ -19,18 +19,18 @@ declare const addTasks: {
19
19
  parentId?: string | undefined;
20
20
  projectId?: string | undefined;
21
21
  sectionId?: string | undefined;
22
+ duration?: string | undefined;
22
23
  priority?: number | undefined;
23
24
  dueString?: string | undefined;
24
- duration?: string | undefined;
25
25
  }, {
26
26
  content: string;
27
27
  description?: string | undefined;
28
28
  parentId?: string | undefined;
29
29
  projectId?: string | undefined;
30
30
  sectionId?: string | undefined;
31
+ duration?: string | undefined;
31
32
  priority?: number | undefined;
32
33
  dueString?: string | undefined;
33
- duration?: string | undefined;
34
34
  }>, "many">;
35
35
  };
36
36
  execute({ tasks }: {
@@ -40,9 +40,9 @@ declare const addTasks: {
40
40
  parentId?: string | undefined;
41
41
  projectId?: string | undefined;
42
42
  sectionId?: string | undefined;
43
+ duration?: string | undefined;
43
44
  priority?: number | undefined;
44
45
  dueString?: string | undefined;
45
- duration?: string | undefined;
46
46
  }[];
47
47
  }, client: TodoistApi): Promise<{
48
48
  content: {
@@ -1,4 +1,3 @@
1
- import type { Comment } from '@doist/todoist-api-typescript';
2
1
  import { z } from 'zod';
3
2
  declare const findComments: {
4
3
  name: "find-comments";
@@ -22,7 +21,31 @@ declare const findComments: {
22
21
  text: string;
23
22
  }[];
24
23
  structuredContent: {
25
- comments: Comment[];
24
+ comments: {
25
+ taskId: string | undefined;
26
+ id: string;
27
+ content: string;
28
+ postedAt: string;
29
+ fileAttachment: {
30
+ resourceType: string;
31
+ fileName?: string | null | undefined;
32
+ fileSize?: number | null | undefined;
33
+ fileType?: string | null | undefined;
34
+ fileUrl?: string | null | undefined;
35
+ fileDuration?: number | null | undefined;
36
+ uploadState?: "pending" | "completed" | null | undefined;
37
+ image?: string | null | undefined;
38
+ imageWidth?: number | null | undefined;
39
+ imageHeight?: number | null | undefined;
40
+ url?: string | null | undefined;
41
+ title?: string | null | undefined;
42
+ } | null;
43
+ postedUid: string;
44
+ uidsToNotify: string[] | null;
45
+ reactions: Record<string, string[]> | null;
46
+ isDeleted: boolean;
47
+ projectId?: string | undefined;
48
+ }[];
26
49
  searchType: string;
27
50
  searchId: string;
28
51
  hasMore: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"find-comments.d.ts","sourceRoot":"","sources":["../../src/tools/find-comments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAuBvB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsEwB,CAAA;AAoF1C,OAAO,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"find-comments.d.ts","sourceRoot":"","sources":["../../src/tools/find-comments.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAuBvB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA2J++P,CAAC;4BAA6C,CAAC;4BAA6C,CAAC;2BAA4C,CAAC;gCAAiD,CAAC;+BAAgD,CAAC;yBAA2D,CAAC;8BAA+C,CAAC;+BAAgD,CAAC;uBAAwC,CAAC;yBAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;CArFr7Q,CAAA;AAoF1C,OAAO,EAAE,YAAY,EAAE,CAAA"}
@@ -3,6 +3,8 @@ declare const findCompletedTasks: {
3
3
  name: "find-completed-tasks";
4
4
  description: string;
5
5
  parameters: {
6
+ labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
7
+ labelsOperator: z.ZodOptional<z.ZodEnum<["and", "or"]>>;
6
8
  getBy: z.ZodDefault<z.ZodEnum<["completion", "due"]>>;
7
9
  since: z.ZodString;
8
10
  until: z.ZodString;
@@ -15,14 +17,16 @@ declare const findCompletedTasks: {
15
17
  };
16
18
  execute(args: {
17
19
  limit: number;
18
- getBy: "completion" | "due";
20
+ getBy: "due" | "completion";
19
21
  since: string;
20
22
  until: string;
21
23
  parentId?: string | undefined;
22
24
  workspaceId?: string | undefined;
23
25
  projectId?: string | undefined;
24
26
  sectionId?: string | undefined;
27
+ labels?: string[] | undefined;
25
28
  cursor?: string | undefined;
29
+ labelsOperator?: "and" | "or" | undefined;
26
30
  }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
27
31
  content: {
28
32
  type: "text";
@@ -47,14 +51,16 @@ declare const findCompletedTasks: {
47
51
  hasMore: boolean;
48
52
  appliedFilters: {
49
53
  limit: number;
50
- getBy: "completion" | "due";
54
+ getBy: "due" | "completion";
51
55
  since: string;
52
56
  until: string;
53
57
  parentId?: string | undefined;
54
58
  workspaceId?: string | undefined;
55
59
  projectId?: string | undefined;
56
60
  sectionId?: string | undefined;
61
+ labels?: string[] | undefined;
57
62
  cursor?: string | undefined;
63
+ labelsOperator?: "and" | "or" | undefined;
58
64
  };
59
65
  };
60
66
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"find-completed-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-completed-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA8CvB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BkB,CAAA;AA2D1C,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
1
+ {"version":3,"file":"find-completed-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-completed-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAiDvB,QAAA,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCkB,CAAA;AAmE1C,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { getToolOutput } from '../mcp-helpers.js';
3
3
  import { mapTask } from '../tool-helpers.js';
4
4
  import { ApiLimits } from '../utils/constants.js';
5
+ import { LabelsSchema, generateLabelsFilter } from '../utils/labels.js';
5
6
  import { previewTasks, summarizeList } from '../utils/response-builders.js';
6
7
  import { ToolNames } from '../utils/tool-names.js';
7
8
  const { FIND_TASKS_BY_DATE, GET_OVERVIEW } = ToolNames;
@@ -35,16 +36,24 @@ const ArgsSchema = {
35
36
  .string()
36
37
  .optional()
37
38
  .describe('The cursor to get the next page of tasks (cursor is obtained from the previous call to this tool, with the same parameters).'),
39
+ ...LabelsSchema,
38
40
  };
39
41
  const findCompletedTasks = {
40
42
  name: ToolNames.FIND_COMPLETED_TASKS,
41
43
  description: 'Get completed tasks.',
42
44
  parameters: ArgsSchema,
43
45
  async execute(args, client) {
44
- const { getBy, ...rest } = args;
46
+ const { getBy, labels, labelsOperator, ...rest } = args;
47
+ const labelsFilter = generateLabelsFilter(labels, labelsOperator);
45
48
  const { items, nextCursor } = getBy === 'completion'
46
- ? await client.getCompletedTasksByCompletionDate(rest)
47
- : await client.getCompletedTasksByDueDate(rest);
49
+ ? await client.getCompletedTasksByCompletionDate({
50
+ ...rest,
51
+ ...(labelsFilter ? { filterQuery: labelsFilter, filterLang: 'en' } : {}),
52
+ })
53
+ : await client.getCompletedTasksByDueDate({
54
+ ...rest,
55
+ ...(labelsFilter ? { filterQuery: labelsFilter, filterLang: 'en' } : {}),
56
+ });
48
57
  const mappedTasks = items.map(mapTask);
49
58
  const textContent = generateTextContent({
50
59
  tasks: mappedTasks,
@@ -78,6 +87,13 @@ function generateTextContent({ tasks, args, nextCursor, }) {
78
87
  filterHints.push(`parent: ${args.parentId}`);
79
88
  if (args.workspaceId)
80
89
  filterHints.push(`workspace: ${args.workspaceId}`);
90
+ // Add label filter information
91
+ if (args.labels && args.labels.length > 0) {
92
+ const labelText = args.labels
93
+ .map((label) => `@${label}`)
94
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
95
+ filterHints.push(`labels: ${labelText}`);
96
+ }
81
97
  // Generate helpful suggestions for empty results
82
98
  const zeroReasonHints = [];
83
99
  if (tasks.length === 0) {
@@ -3,6 +3,8 @@ declare const findTasksByDate: {
3
3
  name: "find-tasks-by-date";
4
4
  description: string;
5
5
  parameters: {
6
+ labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
7
+ labelsOperator: z.ZodOptional<z.ZodEnum<["and", "or"]>>;
6
8
  startDate: z.ZodString;
7
9
  daysCount: z.ZodDefault<z.ZodNumber>;
8
10
  limit: z.ZodDefault<z.ZodNumber>;
@@ -12,7 +14,9 @@ declare const findTasksByDate: {
12
14
  limit: number;
13
15
  startDate: string;
14
16
  daysCount: number;
17
+ labels?: string[] | undefined;
15
18
  cursor?: string | undefined;
19
+ labelsOperator?: "and" | "or" | undefined;
16
20
  }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
17
21
  content: {
18
22
  type: "text";
@@ -39,7 +43,9 @@ declare const findTasksByDate: {
39
43
  limit: number;
40
44
  startDate: string;
41
45
  daysCount: number;
46
+ labels?: string[] | undefined;
42
47
  cursor?: string | undefined;
48
+ labelsOperator?: "and" | "or" | undefined;
43
49
  };
44
50
  };
45
51
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"find-tasks-by-date.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks-by-date.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA4CvB,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CqB,CAAA;AAiE1C,OAAO,EAAE,eAAe,EAAE,CAAA"}
1
+ {"version":3,"file":"find-tasks-by-date.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks-by-date.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA8CvB,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDqB,CAAA;AAyE1C,OAAO,EAAE,eAAe,EAAE,CAAA"}
@@ -3,6 +3,7 @@ import { z } from 'zod';
3
3
  import { getToolOutput } from '../mcp-helpers.js';
4
4
  import { getTasksByFilter } from '../tool-helpers.js';
5
5
  import { ApiLimits } from '../utils/constants.js';
6
+ import { LabelsSchema, generateLabelsFilter } from '../utils/labels.js';
6
7
  import { generateTaskNextSteps, getDateString, previewTasks, summarizeList, } from '../utils/response-builders.js';
7
8
  import { ToolNames } from '../utils/tool-names.js';
8
9
  const ArgsSchema = {
@@ -28,13 +29,14 @@ const ArgsSchema = {
28
29
  .string()
29
30
  .optional()
30
31
  .describe('The cursor to get the next page of tasks (cursor is obtained from the previous call to this tool, with the same parameters).'),
32
+ ...LabelsSchema,
31
33
  };
32
34
  const findTasksByDate = {
33
35
  name: ToolNames.FIND_TASKS_BY_DATE,
34
36
  description: "Get tasks by date range or overdue tasks. Use startDate 'overdue' for overdue tasks, or provide a date/date range.",
35
37
  parameters: ArgsSchema,
36
38
  async execute(args, client) {
37
- let query;
39
+ let query = '';
38
40
  if (args.startDate === 'overdue') {
39
41
  query = 'overdue';
40
42
  }
@@ -46,6 +48,14 @@ const findTasksByDate = {
46
48
  const endDateStr = formatISO(endDate, { representation: 'date' });
47
49
  query = `(due after: ${startDate} | due: ${startDate}) & due before: ${endDateStr}`;
48
50
  }
51
+ const labelsFilter = generateLabelsFilter(args.labels, args.labelsOperator);
52
+ if (labelsFilter.length > 0) {
53
+ // If there is already a query, we need to append the & operator first
54
+ if (query.length > 0)
55
+ query += ' & ';
56
+ // Add the labels to the filter
57
+ query += `(${labelsFilter})`;
58
+ }
49
59
  const result = await getTasksByFilter({
50
60
  client,
51
61
  query,
@@ -81,6 +91,13 @@ function generateTextContent({ tasks, args, nextCursor, }) {
81
91
  else {
82
92
  filterHints.push(`${args.startDate}${args.daysCount > 1 ? ` to ${getDateString(addDays(args.startDate, args.daysCount))}` : ''}`);
83
93
  }
94
+ // Add label filter information
95
+ if (args.labels && args.labels.length > 0) {
96
+ const labelText = args.labels
97
+ .map((label) => `@${label}`)
98
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
99
+ filterHints.push(`labels: ${labelText}`);
100
+ }
84
101
  // Generate subject description
85
102
  const subject = args.startDate === 'overdue'
86
103
  ? 'Overdue tasks'
@@ -3,6 +3,8 @@ declare const findTasks: {
3
3
  name: "find-tasks";
4
4
  description: string;
5
5
  parameters: {
6
+ labels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
7
+ labelsOperator: z.ZodOptional<z.ZodEnum<["and", "or"]>>;
6
8
  searchText: z.ZodOptional<z.ZodString>;
7
9
  projectId: z.ZodOptional<z.ZodString>;
8
10
  sectionId: z.ZodOptional<z.ZodString>;
@@ -15,7 +17,9 @@ declare const findTasks: {
15
17
  parentId?: string | undefined;
16
18
  projectId?: string | undefined;
17
19
  sectionId?: string | undefined;
20
+ labels?: string[] | undefined;
18
21
  cursor?: string | undefined;
22
+ labelsOperator?: "and" | "or" | undefined;
19
23
  searchText?: string | undefined;
20
24
  }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
21
25
  content: {
@@ -44,7 +48,9 @@ declare const findTasks: {
44
48
  parentId?: string | undefined;
45
49
  projectId?: string | undefined;
46
50
  sectionId?: string | undefined;
51
+ labels?: string[] | undefined;
47
52
  cursor?: string | undefined;
53
+ labelsOperator?: "and" | "or" | undefined;
48
54
  searchText?: string | undefined;
49
55
  };
50
56
  };
@@ -1 +1 @@
1
- {"version":3,"file":"find-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAoCvB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmF2B,CAAA;AAyG1C,OAAO,EAAE,SAAS,EAAE,CAAA"}
1
+ {"version":3,"file":"find-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAsCvB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2H2B,CAAA;AAqI1C,OAAO,EAAE,SAAS,EAAE,CAAA"}