@doist/todoist-ai 4.13.1 → 4.13.3

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.
@@ -54,6 +54,8 @@ describe(`${FETCH} tool`, () => {
54
54
  duration: null,
55
55
  responsibleUid: null,
56
56
  assignedByUid: null,
57
+ checked: false,
58
+ completedAt: null,
57
59
  },
58
60
  });
59
61
  });
@@ -79,6 +81,8 @@ describe(`${FETCH} tool`, () => {
79
81
  duration: null,
80
82
  responsibleUid: null,
81
83
  assignedByUid: null,
84
+ checked: false,
85
+ completedAt: null,
82
86
  });
83
87
  });
84
88
  it('should handle tasks with recurring due dates', async () => {
@@ -5,7 +5,7 @@ import { updateTasks } from '../update-tasks.js';
5
5
  // Mock the Todoist API
6
6
  const mockTodoistApi = {
7
7
  updateTask: jest.fn(),
8
- moveTasks: jest.fn(),
8
+ moveTask: jest.fn(),
9
9
  };
10
10
  const { UPDATE_TASKS } = ToolNames;
11
11
  describe(`${UPDATE_TASKS} tool`, () => {
@@ -132,7 +132,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
132
132
  url: 'https://todoist.com/showTask?id=8485093750',
133
133
  addedAt: '2025-08-13T22:09:56.123456Z',
134
134
  });
135
- mockTodoistApi.moveTasks.mockResolvedValue([mockApiResponse]);
135
+ mockTodoistApi.moveTask.mockResolvedValue(mockApiResponse);
136
136
  const result = await updateTasks.execute({
137
137
  tasks: [
138
138
  {
@@ -141,7 +141,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
141
141
  },
142
142
  ],
143
143
  }, mockTodoistApi);
144
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093750'], {
144
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093750', {
145
145
  projectId: 'new-project-id',
146
146
  });
147
147
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -159,7 +159,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
159
159
  url: 'https://todoist.com/showTask?id=8485093751',
160
160
  addedAt: '2025-08-13T22:09:56.123456Z',
161
161
  });
162
- mockTodoistApi.moveTasks.mockResolvedValue([mockApiResponse]);
162
+ mockTodoistApi.moveTask.mockResolvedValue(mockApiResponse);
163
163
  const result = await updateTasks.execute({
164
164
  tasks: [
165
165
  {
@@ -168,7 +168,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
168
168
  },
169
169
  ],
170
170
  }, mockTodoistApi);
171
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093751'], {
171
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093751', {
172
172
  parentId: 'parent-task-123',
173
173
  });
174
174
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -200,7 +200,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
200
200
  timezone: null,
201
201
  },
202
202
  });
203
- mockTodoistApi.moveTasks.mockResolvedValue([movedTask]);
203
+ mockTodoistApi.moveTask.mockResolvedValue(movedTask);
204
204
  mockTodoistApi.updateTask.mockResolvedValue(updatedTask);
205
205
  const result = await updateTasks.execute({
206
206
  tasks: [
@@ -214,8 +214,8 @@ describe(`${UPDATE_TASKS} tool`, () => {
214
214
  },
215
215
  ],
216
216
  }, mockTodoistApi);
217
- // Should call moveTasks first for the projectId
218
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093752'], {
217
+ // Should call moveTask first for the projectId
218
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093752', {
219
219
  projectId: 'different-project-id',
220
220
  });
221
221
  // Then call updateTask for the other properties
@@ -307,7 +307,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
307
307
  duration: { amount: 120, unit: 'minute' },
308
308
  projectId: 'new-project-id',
309
309
  });
310
- mockTodoistApi.moveTasks.mockResolvedValue([movedTask]);
310
+ mockTodoistApi.moveTask.mockResolvedValue(movedTask);
311
311
  mockTodoistApi.updateTask.mockResolvedValue(updatedTask);
312
312
  const result = await updateTasks.execute({
313
313
  tasks: [
@@ -319,8 +319,8 @@ describe(`${UPDATE_TASKS} tool`, () => {
319
319
  },
320
320
  ],
321
321
  }, mockTodoistApi);
322
- // Should call moveTasks first
323
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093755'], {
322
+ // Should call moveTask first
323
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093755', {
324
324
  projectId: 'new-project-id',
325
325
  });
326
326
  // Then call updateTask with duration
@@ -485,21 +485,21 @@ describe(`${UPDATE_TASKS} tool`, () => {
485
485
  createMockTask({ id: '6cPHJj2MV4HMj92W', content: 'Second task', sectionId }),
486
486
  ];
487
487
  // Each task should be moved individually to avoid bulk operation issues
488
- mockTodoistApi.moveTasks
489
- .mockResolvedValueOnce([mockResponses[0]])
490
- .mockResolvedValueOnce([mockResponses[1]]);
488
+ mockTodoistApi.moveTask
489
+ .mockResolvedValueOnce(mockResponses[0])
490
+ .mockResolvedValueOnce(mockResponses[1]);
491
491
  const result = await updateTasks.execute({
492
492
  tasks: [
493
493
  { id: '6cPHJm59x4WhMwR4', sectionId },
494
494
  { id: '6cPHJj2MV4HMj92W', sectionId },
495
495
  ],
496
496
  }, mockTodoistApi);
497
- // Should call moveTasks twice, once for each task individually
498
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledTimes(2);
499
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(1, ['6cPHJm59x4WhMwR4'], {
497
+ // Should call moveTask twice, once for each task individually
498
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledTimes(2);
499
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(1, '6cPHJm59x4WhMwR4', {
500
500
  sectionId,
501
501
  });
502
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(2, ['6cPHJj2MV4HMj92W'], {
502
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(2, '6cPHJj2MV4HMj92W', {
503
503
  sectionId,
504
504
  });
505
505
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -518,10 +518,10 @@ describe(`${UPDATE_TASKS} tool`, () => {
518
518
  createMockTask({ id: TASK_3, content: 'Task 3', parentId: 'parent-task-123' }),
519
519
  ];
520
520
  // Each task should be moved individually
521
- mockTodoistApi.moveTasks
522
- .mockResolvedValueOnce([mockResponses[0]])
523
- .mockResolvedValueOnce([mockResponses[1]])
524
- .mockResolvedValueOnce([mockResponses[2]]);
521
+ mockTodoistApi.moveTask
522
+ .mockResolvedValueOnce(mockResponses[0])
523
+ .mockResolvedValueOnce(mockResponses[1])
524
+ .mockResolvedValueOnce(mockResponses[2]);
525
525
  const result = await updateTasks.execute({
526
526
  tasks: [
527
527
  { id: '8485093748', projectId: 'new-project-id' },
@@ -530,14 +530,14 @@ describe(`${UPDATE_TASKS} tool`, () => {
530
530
  ],
531
531
  }, mockTodoistApi);
532
532
  // Verify API was called correctly - 3 individual move calls
533
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledTimes(3);
534
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(1, ['8485093748'], {
533
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledTimes(3);
534
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(1, '8485093748', {
535
535
  projectId: 'new-project-id',
536
536
  });
537
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(2, ['8485093749'], {
537
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(2, '8485093749', {
538
538
  sectionId: 'new-section-id',
539
539
  });
540
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(3, ['8485093750'], {
540
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(3, '8485093750', {
541
541
  parentId: 'parent-task-123',
542
542
  });
543
543
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -556,10 +556,10 @@ describe(`${UPDATE_TASKS} tool`, () => {
556
556
  url: 'https://todoist.com/showTask?id=8485093751',
557
557
  addedAt: '2025-08-13T22:09:59.123456Z',
558
558
  });
559
- mockTodoistApi.moveTasks.mockResolvedValue([mockTaskResponse]);
559
+ mockTodoistApi.moveTask.mockResolvedValue(mockTaskResponse);
560
560
  const result = await updateTasks.execute({ tasks: [{ id: '8485093751', sectionId: 'target-section' }] }, mockTodoistApi);
561
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledTimes(1);
562
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093751'], {
561
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledTimes(1);
562
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093751', {
563
563
  sectionId: 'target-section',
564
564
  });
565
565
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -600,10 +600,10 @@ describe(`${UPDATE_TASKS} tool`, () => {
600
600
  }),
601
601
  ];
602
602
  // Each task should be moved individually
603
- mockTodoistApi.moveTasks
604
- .mockResolvedValueOnce([mockResponses[0]])
605
- .mockResolvedValueOnce([mockResponses[1]])
606
- .mockResolvedValueOnce([mockResponses[2]]);
603
+ mockTodoistApi.moveTask
604
+ .mockResolvedValueOnce(mockResponses[0])
605
+ .mockResolvedValueOnce(mockResponses[1])
606
+ .mockResolvedValueOnce(mockResponses[2]);
607
607
  const result = await updateTasks.execute({
608
608
  tasks: [
609
609
  { id: 'task-1', projectId: 'project-new' },
@@ -612,14 +612,14 @@ describe(`${UPDATE_TASKS} tool`, () => {
612
612
  ],
613
613
  }, mockTodoistApi);
614
614
  // Verify API was called correctly - 3 individual move calls
615
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledTimes(3);
616
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(1, ['task-1'], {
615
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledTimes(3);
616
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(1, 'task-1', {
617
617
  projectId: 'project-new',
618
618
  });
619
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(2, ['task-2'], {
619
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(2, 'task-2', {
620
620
  parentId: 'task-1',
621
621
  });
622
- expect(mockTodoistApi.moveTasks).toHaveBeenNthCalledWith(3, ['task-3'], {
622
+ expect(mockTodoistApi.moveTask).toHaveBeenNthCalledWith(3, 'task-3', {
623
623
  sectionId: 'section-new',
624
624
  });
625
625
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -640,7 +640,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
640
640
  url: 'https://todoist.com/showTask?id=8485093752',
641
641
  addedAt: '2025-08-13T22:10:07.123456Z',
642
642
  });
643
- mockTodoistApi.moveTasks.mockResolvedValue([mockResponse]);
643
+ mockTodoistApi.moveTask.mockResolvedValue(mockResponse);
644
644
  const result = await updateTasks.execute({
645
645
  tasks: [
646
646
  {
@@ -650,7 +650,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
650
650
  },
651
651
  ],
652
652
  }, mockTodoistApi);
653
- expect(mockTodoistApi.moveTasks).toHaveBeenCalledWith(['8485093752'], {
653
+ expect(mockTodoistApi.moveTask).toHaveBeenCalledWith('8485093752', {
654
654
  projectId: 'new-project-only',
655
655
  });
656
656
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
@@ -667,7 +667,7 @@ describe(`${UPDATE_TASKS} tool`, () => {
667
667
  it('should handle empty updates (only id provided)', async () => {
668
668
  const result = await updateTasks.execute({ tasks: [{ id: '8485093753' }] }, mockTodoistApi);
669
669
  // No API calls should be made since no move parameters are provided
670
- expect(mockTodoistApi.moveTasks).not.toHaveBeenCalled();
670
+ expect(mockTodoistApi.moveTask).not.toHaveBeenCalled();
671
671
  expect(mockTodoistApi.updateTask).not.toHaveBeenCalled();
672
672
  // Returns empty results since no moves were processed
673
673
  const textContent = extractTextContent(result);
@@ -691,22 +691,22 @@ describe(`${UPDATE_TASKS} tool`, () => {
691
691
  });
692
692
  it('should propagate API errors for individual task moves', async () => {
693
693
  const apiError = new Error('API Error: Task not found');
694
- mockTodoistApi.moveTasks.mockRejectedValue(apiError);
694
+ mockTodoistApi.moveTask.mockRejectedValue(apiError);
695
695
  await expect(updateTasks.execute({ tasks: [{ id: 'non-existent-task', projectId: 'some-project' }] }, mockTodoistApi)).rejects.toThrow('API Error: Task not found');
696
696
  });
697
697
  it('should handle validation errors', async () => {
698
698
  const validationError = new Error('API Error: Invalid section ID');
699
- mockTodoistApi.moveTasks.mockRejectedValue(validationError);
699
+ mockTodoistApi.moveTask.mockRejectedValue(validationError);
700
700
  await expect(updateTasks.execute({ tasks: [{ id: 'task-1', sectionId: 'invalid-section-format' }] }, mockTodoistApi)).rejects.toThrow('API Error: Invalid section ID');
701
701
  });
702
702
  it('should handle permission errors', async () => {
703
703
  const permissionError = new Error('API Error: Insufficient permissions to move task');
704
- mockTodoistApi.moveTasks.mockRejectedValue(permissionError);
704
+ mockTodoistApi.moveTask.mockRejectedValue(permissionError);
705
705
  await expect(updateTasks.execute({ tasks: [{ id: 'restricted-task', projectId: 'restricted-project' }] }, mockTodoistApi)).rejects.toThrow('API Error: Insufficient permissions to move task');
706
706
  });
707
707
  it('should handle circular parent dependency errors', async () => {
708
708
  const circularError = new Error('API Error: Circular dependency detected');
709
- mockTodoistApi.moveTasks.mockRejectedValue(circularError);
709
+ mockTodoistApi.moveTask.mockRejectedValue(circularError);
710
710
  await expect(updateTasks.execute({
711
711
  tasks: [
712
712
  {
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAuBvB,KAAK,eAAe,GAAG;IACnB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;GAKG;AACH,QAAA,MAAM,KAAK;;;;;;;;oEAKsB,OAAO,CAAC,eAAe,CAAC;CAsFf,CAAA;AAE1C,OAAO,EAAE,KAAK,EAAE,CAAA"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAuBvB,KAAK,eAAe,GAAG;IACnB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;GAKG;AACH,QAAA,MAAM,KAAK;;;;;;;;oEAKsB,OAAO,CAAC,eAAe,CAAC;CAwFf,CAAA;AAE1C,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -56,6 +56,8 @@ const fetch = {
56
56
  duration: mappedTask.duration,
57
57
  responsibleUid: mappedTask.responsibleUid,
58
58
  assignedByUid: mappedTask.assignedByUid,
59
+ checked: mappedTask.checked,
60
+ completedAt: mappedTask.completedAt,
59
61
  },
60
62
  };
61
63
  }
@@ -97,16 +97,16 @@ const updateTasks = {
97
97
  updateArgs = { ...updateArgs, assigneeId: validation.resolvedUser?.userId };
98
98
  }
99
99
  }
100
- // If no move parameters are provided, use updateTask without moveTasks
100
+ // If no move parameters are provided, use updateTask without moveTask
101
101
  if (!projectId && !sectionId && !parentId) {
102
102
  return await client.updateTask(id, updateArgs);
103
103
  }
104
104
  const moveArgs = createMoveTaskArgs(id, projectId, sectionId, parentId);
105
- const movedTasks = await client.moveTasks([id], moveArgs);
105
+ const movedTask = await client.moveTask(id, moveArgs);
106
106
  if (Object.keys(updateArgs).length > 0) {
107
107
  return await client.updateTask(id, updateArgs);
108
108
  }
109
- return movedTasks[0];
109
+ return movedTask;
110
110
  });
111
111
  const updatedTasks = (await Promise.all(updateTasksPromises)).filter((task) => task !== undefined);
112
112
  const mappedTasks = updatedTasks.map(mapTask);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/todoist-ai",
3
- "version": "4.13.1",
3
+ "version": "4.13.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "prepare": "husky"
46
46
  },
47
47
  "dependencies": {
48
- "@doist/todoist-api-typescript": "5.6.4",
48
+ "@doist/todoist-api-typescript": "5.7.0",
49
49
  "@modelcontextprotocol/sdk": "^1.11.1",
50
50
  "date-fns": "^4.1.0",
51
51
  "dotenv": "^16.5.0",