@doist/todoist-ai 4.1.0 → 4.5.1

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 (97) hide show
  1. package/dist/index.d.ts +405 -50
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +26 -16
  4. package/dist/mcp-helpers.d.ts.map +1 -1
  5. package/dist/mcp-helpers.js +1 -1
  6. package/dist/mcp-server.d.ts.map +1 -1
  7. package/dist/mcp-server.js +80 -17
  8. package/dist/tool-helpers.d.ts +4 -0
  9. package/dist/tool-helpers.d.ts.map +1 -1
  10. package/dist/tool-helpers.js +2 -0
  11. package/dist/tools/__tests__/add-projects.test.js +1 -1
  12. package/dist/tools/__tests__/add-sections.test.js +1 -1
  13. package/dist/tools/__tests__/add-tasks.test.js +52 -13
  14. package/dist/tools/__tests__/assignment-integration.test.d.ts +2 -0
  15. package/dist/tools/__tests__/assignment-integration.test.d.ts.map +1 -0
  16. package/dist/tools/__tests__/assignment-integration.test.js +415 -0
  17. package/dist/tools/__tests__/find-completed-tasks.test.js +136 -2
  18. package/dist/tools/__tests__/find-projects.test.js +1 -1
  19. package/dist/tools/__tests__/find-sections.test.js +1 -1
  20. package/dist/tools/__tests__/find-tasks-by-date.test.js +122 -3
  21. package/dist/tools/__tests__/find-tasks.test.js +258 -11
  22. package/dist/tools/__tests__/get-overview.test.js +1 -1
  23. package/dist/tools/__tests__/update-sections.test.js +1 -0
  24. package/dist/tools/__tests__/update-tasks.test.js +6 -6
  25. package/dist/tools/__tests__/user-info.test.d.ts +2 -0
  26. package/dist/tools/__tests__/user-info.test.d.ts.map +1 -0
  27. package/dist/tools/__tests__/user-info.test.js +139 -0
  28. package/dist/tools/add-comments.d.ts +28 -5
  29. package/dist/tools/add-comments.d.ts.map +1 -1
  30. package/dist/tools/add-comments.js +1 -1
  31. package/dist/tools/add-projects.d.ts +46 -2
  32. package/dist/tools/add-projects.d.ts.map +1 -1
  33. package/dist/tools/add-projects.js +1 -1
  34. package/dist/tools/add-sections.d.ts +14 -2
  35. package/dist/tools/add-sections.d.ts.map +1 -1
  36. package/dist/tools/add-sections.js +1 -1
  37. package/dist/tools/add-tasks.d.ts +16 -10
  38. package/dist/tools/add-tasks.d.ts.map +1 -1
  39. package/dist/tools/add-tasks.js +49 -3
  40. package/dist/tools/find-comments.d.ts +27 -4
  41. package/dist/tools/find-comments.d.ts.map +1 -1
  42. package/dist/tools/find-completed-tasks.d.ts +12 -4
  43. package/dist/tools/find-completed-tasks.d.ts.map +1 -1
  44. package/dist/tools/find-completed-tasks.js +20 -4
  45. package/dist/tools/find-project-collaborators.d.ts +64 -0
  46. package/dist/tools/find-project-collaborators.d.ts.map +1 -0
  47. package/dist/tools/find-project-collaborators.js +151 -0
  48. package/dist/tools/find-tasks-by-date.d.ts +8 -0
  49. package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
  50. package/dist/tools/find-tasks-by-date.js +19 -2
  51. package/dist/tools/find-tasks.d.ts +13 -2
  52. package/dist/tools/find-tasks.d.ts.map +1 -1
  53. package/dist/tools/find-tasks.js +172 -23
  54. package/dist/tools/get-overview.d.ts +2 -2
  55. package/dist/tools/get-overview.d.ts.map +1 -1
  56. package/dist/tools/get-overview.js +1 -1
  57. package/dist/tools/manage-assignments.d.ts +52 -0
  58. package/dist/tools/manage-assignments.d.ts.map +1 -0
  59. package/dist/tools/manage-assignments.js +337 -0
  60. package/dist/tools/update-comments.d.ts +25 -2
  61. package/dist/tools/update-comments.d.ts.map +1 -1
  62. package/dist/tools/update-comments.js +1 -1
  63. package/dist/tools/update-projects.d.ts +46 -2
  64. package/dist/tools/update-projects.d.ts.map +1 -1
  65. package/dist/tools/update-sections.d.ts +14 -2
  66. package/dist/tools/update-sections.d.ts.map +1 -1
  67. package/dist/tools/update-sections.js +1 -1
  68. package/dist/tools/update-tasks.d.ts +16 -10
  69. package/dist/tools/update-tasks.d.ts.map +1 -1
  70. package/dist/tools/update-tasks.js +32 -9
  71. package/dist/tools/user-info.d.ts +44 -0
  72. package/dist/tools/user-info.d.ts.map +1 -0
  73. package/dist/tools/user-info.js +142 -0
  74. package/dist/utils/assignment-validator.d.ts +69 -0
  75. package/dist/utils/assignment-validator.d.ts.map +1 -0
  76. package/dist/utils/assignment-validator.js +253 -0
  77. package/dist/utils/duration-parser.d.ts +2 -2
  78. package/dist/utils/duration-parser.d.ts.map +1 -1
  79. package/dist/utils/labels.d.ts +10 -0
  80. package/dist/utils/labels.d.ts.map +1 -0
  81. package/dist/utils/labels.js +18 -0
  82. package/dist/utils/priorities.d.ts +8 -0
  83. package/dist/utils/priorities.d.ts.map +1 -0
  84. package/dist/utils/priorities.js +15 -0
  85. package/dist/utils/response-builders.d.ts +2 -2
  86. package/dist/utils/response-builders.d.ts.map +1 -1
  87. package/dist/utils/response-builders.js +8 -1
  88. package/dist/utils/test-helpers.d.ts +2 -0
  89. package/dist/utils/test-helpers.d.ts.map +1 -1
  90. package/dist/utils/test-helpers.js +3 -0
  91. package/dist/utils/tool-names.d.ts +3 -0
  92. package/dist/utils/tool-names.d.ts.map +1 -1
  93. package/dist/utils/tool-names.js +4 -0
  94. package/dist/utils/user-resolver.d.ts +39 -0
  95. package/dist/utils/user-resolver.d.ts.map +1 -0
  96. package/dist/utils/user-resolver.js +179 -0
  97. package/package.json +7 -7
@@ -2,14 +2,20 @@ import { z } from 'zod';
2
2
  import { getToolOutput } from '../mcp-helpers.js';
3
3
  import { getTasksByFilter, mapTask } from '../tool-helpers.js';
4
4
  import { ApiLimits } from '../utils/constants.js';
5
+ import { generateLabelsFilter, LabelsSchema } from '../utils/labels.js';
5
6
  import { generateTaskNextSteps, getDateString, previewTasks, summarizeList, } from '../utils/response-builders.js';
6
7
  import { ToolNames } from '../utils/tool-names.js';
8
+ import { resolveUserNameToId } from '../utils/user-resolver.js';
7
9
  const { FIND_COMPLETED_TASKS, ADD_TASKS } = ToolNames;
8
10
  const ArgsSchema = {
9
11
  searchText: z.string().optional().describe('The text to search for in tasks.'),
10
12
  projectId: z.string().optional().describe('Find tasks in this project.'),
11
13
  sectionId: z.string().optional().describe('Find tasks in this section.'),
12
14
  parentId: z.string().optional().describe('Find subtasks of this parent task.'),
15
+ responsibleUser: z
16
+ .string()
17
+ .optional()
18
+ .describe('Find tasks assigned to this user. Can be a user ID, name, or email address.'),
13
19
  limit: z
14
20
  .number()
15
21
  .int()
@@ -21,16 +27,36 @@ const ArgsSchema = {
21
27
  .string()
22
28
  .optional()
23
29
  .describe('The cursor to get the next page of tasks (cursor is obtained from the previous call to this tool, with the same parameters).'),
30
+ ...LabelsSchema,
24
31
  };
25
32
  const findTasks = {
26
33
  name: ToolNames.FIND_TASKS,
27
- description: 'Find tasks by text search, or by project/section/parent container. At least one filter must be provided.',
34
+ description: 'Find tasks by text search, or by project/section/parent container/responsible user. At least one filter must be provided.',
28
35
  parameters: ArgsSchema,
29
36
  async execute(args, client) {
30
- const { searchText, projectId, sectionId, parentId, limit, cursor } = args;
37
+ const { searchText, projectId, sectionId, parentId, responsibleUser, limit, cursor, labels, labelsOperator, } = args;
31
38
  // Validate at least one filter is provided
32
- if (!searchText && !projectId && !sectionId && !parentId) {
33
- throw new Error('At least one filter must be provided: searchText, projectId, sectionId, or parentId');
39
+ const hasLabels = labels && labels.length > 0;
40
+ if (!searchText &&
41
+ !projectId &&
42
+ !sectionId &&
43
+ !parentId &&
44
+ !responsibleUser &&
45
+ !hasLabels) {
46
+ throw new Error('At least one filter must be provided: searchText, projectId, sectionId, parentId, responsibleUser, or labels');
47
+ }
48
+ // Resolve assignee name to user ID if provided
49
+ let resolvedAssigneeId = responsibleUser;
50
+ let assigneeDisplayName;
51
+ if (responsibleUser) {
52
+ const resolved = await resolveUserNameToId(client, responsibleUser);
53
+ if (resolved) {
54
+ resolvedAssigneeId = resolved.userId;
55
+ assigneeDisplayName = resolved.displayName;
56
+ }
57
+ else {
58
+ throw new Error(`Could not find user: "${responsibleUser}". Make sure the user is a collaborator on a shared project.`);
59
+ }
34
60
  }
35
61
  // If using container-based filtering, use direct API
36
62
  if (projectId || sectionId || parentId) {
@@ -46,47 +72,108 @@ const findTasks = {
46
72
  taskParams.parentId = parentId;
47
73
  const { results, nextCursor } = await client.getTasks(taskParams);
48
74
  const mappedTasks = results.map(mapTask);
49
- // If also has searchText, filter the results
50
- const finalTasks = searchText
75
+ // Apply search text filter
76
+ let filteredTasks = searchText
51
77
  ? mappedTasks.filter((task) => task.content.toLowerCase().includes(searchText.toLowerCase()) ||
52
78
  task.description?.toLowerCase().includes(searchText.toLowerCase()))
53
79
  : mappedTasks;
80
+ // Apply responsibleUid filter
81
+ if (resolvedAssigneeId) {
82
+ filteredTasks = filteredTasks.filter((task) => task.responsibleUid === resolvedAssigneeId);
83
+ }
84
+ // Apply label filter
85
+ if (labels && labels.length > 0) {
86
+ filteredTasks =
87
+ labelsOperator === 'and'
88
+ ? filteredTasks.filter((task) => labels.every((label) => task.labels.includes(label)))
89
+ : filteredTasks.filter((task) => labels.some((label) => task.labels.includes(label)));
90
+ }
54
91
  const textContent = generateTextContent({
55
- tasks: finalTasks,
92
+ tasks: filteredTasks,
56
93
  args,
57
94
  nextCursor,
58
95
  isContainerSearch: true,
96
+ assigneeDisplayName,
59
97
  });
60
98
  return getToolOutput({
61
99
  textContent,
62
100
  structuredContent: {
63
- tasks: finalTasks,
101
+ tasks: filteredTasks,
64
102
  nextCursor,
65
- totalCount: finalTasks.length,
103
+ totalCount: filteredTasks.length,
66
104
  hasMore: Boolean(nextCursor),
67
105
  appliedFilters: args,
68
106
  },
69
107
  });
70
108
  }
71
- // Text-only search using filter query
109
+ // If only responsibleUid is provided (without containers), use assignee filter
110
+ if (resolvedAssigneeId && !searchText && !hasLabels) {
111
+ const tasks = await client.getTasksByFilter({
112
+ query: `assigned to: ${assigneeDisplayName}`,
113
+ lang: 'en',
114
+ limit,
115
+ cursor: cursor ?? null,
116
+ });
117
+ const mappedTasks = tasks.results.map(mapTask);
118
+ const textContent = generateTextContent({
119
+ tasks: mappedTasks,
120
+ args,
121
+ nextCursor: tasks.nextCursor,
122
+ isContainerSearch: false,
123
+ assigneeDisplayName,
124
+ });
125
+ return getToolOutput({
126
+ textContent,
127
+ structuredContent: {
128
+ tasks: mappedTasks,
129
+ nextCursor: tasks.nextCursor,
130
+ totalCount: mappedTasks.length,
131
+ hasMore: Boolean(tasks.nextCursor),
132
+ appliedFilters: args,
133
+ },
134
+ });
135
+ }
136
+ // Handle search text and/or labels using filter query (responsibleUid filtering done client-side)
137
+ let query = '';
138
+ // Add search text component
139
+ if (searchText) {
140
+ query = `search: ${searchText}`;
141
+ }
142
+ // Add labels component
143
+ const labelsFilter = generateLabelsFilter(labels, labelsOperator);
144
+ if (labelsFilter.length > 0) {
145
+ if (query.length > 0) {
146
+ query += ` & ${labelsFilter}`;
147
+ }
148
+ else {
149
+ query = labelsFilter;
150
+ }
151
+ }
152
+ // Execute filter query
72
153
  const result = await getTasksByFilter({
73
154
  client,
74
- query: `search: ${searchText}`,
155
+ query,
75
156
  cursor: args.cursor,
76
157
  limit: args.limit,
77
158
  });
159
+ // Always filter by responsibleUid client-side (API doesn't reliably support responsibleUid filtering)
160
+ let tasks = result.tasks;
161
+ if (resolvedAssigneeId) {
162
+ tasks = result.tasks.filter((task) => task.responsibleUid === resolvedAssigneeId);
163
+ }
78
164
  const textContent = generateTextContent({
79
- tasks: result.tasks,
165
+ tasks,
80
166
  args,
81
167
  nextCursor: result.nextCursor,
82
168
  isContainerSearch: false,
169
+ assigneeDisplayName,
83
170
  });
84
171
  return getToolOutput({
85
172
  textContent,
86
173
  structuredContent: {
87
- tasks: result.tasks,
174
+ tasks,
88
175
  nextCursor: result.nextCursor,
89
- totalCount: result.tasks.length,
176
+ totalCount: tasks.length,
90
177
  hasMore: Boolean(result.nextCursor),
91
178
  appliedFilters: args,
92
179
  },
@@ -119,9 +206,9 @@ function getContainerZeroReasonHints(args) {
119
206
  }
120
207
  return [];
121
208
  }
122
- function generateTextContent({ tasks, args, nextCursor, isContainerSearch, }) {
209
+ function generateTextContent({ tasks, args, nextCursor, isContainerSearch, assigneeDisplayName, }) {
123
210
  // Generate subject and filter descriptions based on search type
124
- let subject;
211
+ let subject = 'Tasks';
125
212
  const filterHints = [];
126
213
  const zeroReasonHints = [];
127
214
  if (isContainerSearch) {
@@ -146,19 +233,81 @@ function generateTextContent({ tasks, args, nextCursor, isContainerSearch, }) {
146
233
  subject += ` matching "${args.searchText}"`;
147
234
  filterHints.push(`containing "${args.searchText}"`);
148
235
  }
236
+ // Add responsibleUid filter if present
237
+ if (args.responsibleUser) {
238
+ const displayName = assigneeDisplayName || args.responsibleUser;
239
+ subject += ` assigned to ${displayName}`;
240
+ filterHints.push(`assigned to ${displayName}`);
241
+ }
242
+ // Add label filter information
243
+ if (args.labels && args.labels.length > 0) {
244
+ const labelText = args.labels
245
+ .map((label) => `@${label}`)
246
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
247
+ filterHints.push(`labels: ${labelText}`);
248
+ }
149
249
  // Container-specific zero result hints
150
250
  if (tasks.length === 0) {
151
251
  zeroReasonHints.push(...getContainerZeroReasonHints(args));
152
252
  }
153
253
  }
154
254
  else {
155
- // Text-only search
156
- subject = `Search results for "${args.searchText}"`;
157
- filterHints.push(`matching "${args.searchText}"`);
255
+ // Text, responsibleUid, or labels search
256
+ const displayName = assigneeDisplayName || args.responsibleUser;
257
+ // Build subject based on filters
258
+ const subjectParts = [];
259
+ if (args.searchText) {
260
+ subjectParts.push(`"${args.searchText}"`);
261
+ }
262
+ if (args.responsibleUser) {
263
+ subjectParts.push(`assigned to ${displayName}`);
264
+ }
265
+ if (args.labels && args.labels.length > 0) {
266
+ const labelText = args.labels
267
+ .map((label) => `@${label}`)
268
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
269
+ subjectParts.push(`with labels: ${labelText}`);
270
+ }
271
+ if (args.searchText) {
272
+ subject = `Search results for ${subjectParts.join(' ')}`;
273
+ filterHints.push(`matching "${args.searchText}"`);
274
+ }
275
+ else if (args.responsibleUser && (!args.labels || args.labels.length === 0)) {
276
+ subject = `Tasks assigned to ${displayName}`;
277
+ }
278
+ else if (args.labels && args.labels.length > 0 && !args.responsibleUser) {
279
+ const labelText = args.labels
280
+ .map((label) => `@${label}`)
281
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
282
+ subject = `Tasks with labels: ${labelText}`;
283
+ }
284
+ else {
285
+ subject = `Tasks ${subjectParts.join(' ')}`;
286
+ }
287
+ // Add filter hints
288
+ if (args.responsibleUser) {
289
+ filterHints.push(`assigned to ${displayName}`);
290
+ }
291
+ if (args.labels && args.labels.length > 0) {
292
+ const labelText = args.labels
293
+ .map((label) => `@${label}`)
294
+ .join(args.labelsOperator === 'and' ? ' & ' : ' | ');
295
+ filterHints.push(`labels: ${labelText}`);
296
+ }
158
297
  if (tasks.length === 0) {
159
- zeroReasonHints.push('Try broader search terms');
160
- zeroReasonHints.push(`Check completed tasks with ${FIND_COMPLETED_TASKS}`);
161
- zeroReasonHints.push('Verify spelling and try partial words');
298
+ if (args.responsibleUser) {
299
+ const displayName = assigneeDisplayName || args.responsibleUser;
300
+ zeroReasonHints.push(`No tasks assigned to ${displayName}`);
301
+ zeroReasonHints.push('Check if the user name is correct');
302
+ zeroReasonHints.push(`Check completed tasks with ${FIND_COMPLETED_TASKS}`);
303
+ }
304
+ if (args.searchText) {
305
+ zeroReasonHints.push('Try broader search terms');
306
+ zeroReasonHints.push('Verify spelling and try partial words');
307
+ if (!args.responsibleUser) {
308
+ zeroReasonHints.push(`Check completed tasks with ${FIND_COMPLETED_TASKS}`);
309
+ }
310
+ }
162
311
  }
163
312
  }
164
313
  // Generate contextual next steps
@@ -174,7 +323,7 @@ function generateTextContent({ tasks, args, nextCursor, isContainerSearch, }) {
174
323
  limit: args.limit,
175
324
  nextCursor: nextCursor ?? undefined,
176
325
  filterHints,
177
- previewLines: previewTasks(tasks),
326
+ previewLines: previewTasks(tasks, Math.min(tasks.length, args.limit)),
178
327
  zeroReasonHints,
179
328
  nextSteps,
180
329
  });
@@ -20,7 +20,7 @@ type AccountOverviewStructured = Record<string, unknown> & {
20
20
  totalSections: number;
21
21
  hasNestedProjects: boolean;
22
22
  };
23
- interface ProjectOverviewStructured extends Record<string, unknown> {
23
+ type ProjectOverviewStructured = Record<string, unknown> & {
24
24
  type: 'project_overview';
25
25
  project: {
26
26
  id: string;
@@ -35,7 +35,7 @@ interface ProjectOverviewStructured extends Record<string, unknown> {
35
35
  totalSections: number;
36
36
  tasksWithoutSection: number;
37
37
  };
38
- }
38
+ };
39
39
  declare const getOverview: {
40
40
  name: "get-overview";
41
41
  description: string;
@@ -1 +1 @@
1
- {"version":3,"file":"get-overview.d.ts","sourceRoot":"","sources":["../../src/tools/get-overview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAAmC,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAgI7E,KAAK,gBAAgB,GAAG;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC/B,CAAA;AAED,KAAK,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvD,IAAI,EAAE,kBAAkB,CAAA;IACxB,KAAK,EAAE;QACH,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,OAAO,EAAE,CAAA;KACtB,GAAG,IAAI,CAAA;IACR,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,UAAU,yBAA0B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;KACf,CAAA;IACD,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,GAAG;QAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC,CAAA;IAChE,KAAK,EAAE;QACH,UAAU,EAAE,MAAM,CAAA;QAClB,aAAa,EAAE,MAAM,CAAA;QACrB,mBAAmB,EAAE,MAAM,CAAA;KAC9B,CAAA;CACJ;AA6JD,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;CAeyB,CAAA;AAE1C,OAAO,EAAE,WAAW,EAAE,KAAK,yBAAyB,EAAE,KAAK,yBAAyB,EAAE,CAAA"}
1
+ {"version":3,"file":"get-overview.d.ts","sourceRoot":"","sources":["../../src/tools/get-overview.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,EAAqB,OAAO,EAAgB,MAAM,oBAAoB,CAAA;AAgI7E,KAAK,gBAAgB,GAAG;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC/B,CAAA;AAED,KAAK,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvD,IAAI,EAAE,kBAAkB,CAAA;IACxB,KAAK,EAAE;QACH,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,OAAO,EAAE,CAAA;KACtB,GAAG,IAAI,CAAA;IACR,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,KAAK,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvD,IAAI,EAAE,kBAAkB,CAAA;IACxB,OAAO,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;KACf,CAAA;IACD,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,OAAO,CAAC,GAAG;QAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC,CAAA;IAChE,KAAK,EAAE;QACH,UAAU,EAAE,MAAM,CAAA;QAClB,aAAa,EAAE,MAAM,CAAA;QACrB,mBAAmB,EAAE,MAAM,CAAA;KAC9B,CAAA;CACJ,CAAA;AA6JD,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;CAeyB,CAAA;AAE1C,OAAO,EAAE,WAAW,EAAE,KAAK,yBAAyB,EAAE,KAAK,yBAAyB,EAAE,CAAA"}
@@ -115,7 +115,7 @@ function buildProjectStructure(project, sectionsByProject) {
115
115
  }
116
116
  async function getAllTasksForProject(client, projectId) {
117
117
  let allTasks = [];
118
- let cursor = undefined;
118
+ let cursor;
119
119
  do {
120
120
  const { results, nextCursor } = await client.getTasks({
121
121
  projectId,
@@ -0,0 +1,52 @@
1
+ import { z } from 'zod';
2
+ export type OperationResult = {
3
+ taskId: string;
4
+ success: boolean;
5
+ error?: string;
6
+ originalAssigneeId?: string | null;
7
+ newAssigneeId?: string | null;
8
+ };
9
+ declare const manageAssignments: {
10
+ name: "manage-assignments";
11
+ description: string;
12
+ parameters: {
13
+ operation: z.ZodEnum<["assign", "unassign", "reassign"]>;
14
+ taskIds: z.ZodArray<z.ZodString, "many">;
15
+ responsibleUser: z.ZodOptional<z.ZodString>;
16
+ fromAssigneeUser: z.ZodOptional<z.ZodString>;
17
+ dryRun: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
18
+ };
19
+ execute(args: {
20
+ operation: "assign" | "unassign" | "reassign";
21
+ taskIds: string[];
22
+ dryRun: boolean;
23
+ responsibleUser?: string | undefined;
24
+ fromAssigneeUser?: string | undefined;
25
+ }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
26
+ content: {
27
+ type: "text";
28
+ text: string;
29
+ }[];
30
+ structuredContent: {
31
+ operation: "assign" | "unassign" | "reassign";
32
+ results: OperationResult[];
33
+ totalRequested: number;
34
+ successful: number;
35
+ failed: number;
36
+ dryRun: boolean;
37
+ };
38
+ } | {
39
+ content: ({
40
+ type: "text";
41
+ text: string;
42
+ mimeType?: undefined;
43
+ } | {
44
+ type: "text";
45
+ mimeType: string;
46
+ text: string;
47
+ })[];
48
+ structuredContent?: undefined;
49
+ }>;
50
+ };
51
+ export { manageAssignments };
52
+ //# sourceMappingURL=manage-assignments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manage-assignments.d.ts","sourceRoot":"","sources":["../../src/tools/manage-assignments.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA4CvB,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC,CAAA;AAED,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoRmB,CAAA;AAuF1C,OAAO,EAAE,iBAAiB,EAAE,CAAA"}