@doist/todoist-ai 2.2.2 → 3.0.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.
- package/README.md +11 -3
- package/dist/index.d.ts +496 -255
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -29
- package/dist/mcp-helpers.d.ts +25 -3
- package/dist/mcp-helpers.d.ts.map +1 -1
- package/dist/mcp-helpers.js +37 -19
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +32 -28
- package/dist/tools/__tests__/add-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/add-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-add-multiple.test.js → add-tasks.test.js} +85 -81
- package/dist/tools/__tests__/complete-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/complete-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/complete-tasks.test.js +206 -0
- package/dist/tools/__tests__/delete-object.test.d.ts +2 -0
- package/dist/tools/__tests__/delete-object.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{delete-one.test.js → delete-object.test.js} +42 -22
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-completed-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-completed.test.js → find-completed-tasks.test.js} +13 -36
- package/dist/tools/__tests__/find-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/find-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{projects-list.test.js → find-projects.test.js} +55 -39
- package/dist/tools/__tests__/find-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/find-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{sections-search.test.js → find-sections.test.js} +64 -50
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks-by-date.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{tasks-list-by-date.test.js → find-tasks-by-date.test.js} +96 -14
- package/dist/tools/__tests__/find-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/find-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/find-tasks.test.js +334 -0
- package/dist/tools/__tests__/get-overview.test.d.ts +2 -0
- package/dist/tools/__tests__/get-overview.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{overview.test.js → get-overview.test.js} +77 -13
- package/dist/tools/__tests__/manage-projects.test.d.ts +2 -0
- package/dist/tools/__tests__/manage-projects.test.d.ts.map +1 -0
- package/dist/tools/__tests__/{projects-manage.test.js → manage-projects.test.js} +33 -30
- package/dist/tools/__tests__/manage-sections.test.d.ts +2 -0
- package/dist/tools/__tests__/manage-sections.test.d.ts.map +1 -0
- package/dist/tools/__tests__/manage-sections.test.js +162 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts +2 -0
- package/dist/tools/__tests__/update-tasks.test.d.ts.map +1 -0
- package/dist/tools/__tests__/update-tasks.test.js +645 -0
- package/dist/tools/{tasks-add-multiple.d.ts → add-tasks.d.ts} +36 -16
- package/dist/tools/add-tasks.d.ts.map +1 -0
- package/dist/tools/{tasks-add-multiple.js → add-tasks.js} +39 -4
- package/dist/tools/complete-tasks.d.ts +40 -0
- package/dist/tools/complete-tasks.d.ts.map +1 -0
- package/dist/tools/complete-tasks.js +68 -0
- package/dist/tools/delete-object.d.ts +38 -0
- package/dist/tools/delete-object.d.ts.map +1 -0
- package/dist/tools/delete-object.js +69 -0
- package/dist/tools/find-completed-tasks.d.ts +74 -0
- package/dist/tools/find-completed-tasks.d.ts.map +1 -0
- package/dist/tools/find-completed-tasks.js +112 -0
- package/dist/tools/find-projects.d.ts +53 -0
- package/dist/tools/find-projects.d.ts.map +1 -0
- package/dist/tools/find-projects.js +101 -0
- package/dist/tools/find-sections.d.ts +42 -0
- package/dist/tools/find-sections.d.ts.map +1 -0
- package/dist/tools/find-sections.js +96 -0
- package/dist/tools/find-tasks-by-date.d.ts +59 -0
- package/dist/tools/find-tasks-by-date.d.ts.map +1 -0
- package/dist/tools/find-tasks-by-date.js +121 -0
- package/dist/tools/find-tasks.d.ts +65 -0
- package/dist/tools/find-tasks.d.ts.map +1 -0
- package/dist/tools/find-tasks.js +182 -0
- package/dist/tools/get-overview.d.ts +67 -0
- package/dist/tools/get-overview.d.ts.map +1 -0
- package/dist/tools/{overview.js → get-overview.js} +66 -19
- package/dist/tools/manage-projects.d.ts +35 -0
- package/dist/tools/manage-projects.d.ts.map +1 -0
- package/dist/tools/manage-projects.js +63 -0
- package/dist/tools/manage-sections.d.ts +38 -0
- package/dist/tools/manage-sections.d.ts.map +1 -0
- package/dist/tools/manage-sections.js +78 -0
- package/dist/tools/update-tasks.d.ts +94 -0
- package/dist/tools/update-tasks.d.ts.map +1 -0
- package/dist/tools/update-tasks.js +120 -0
- package/dist/utils/constants.d.ts +35 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +37 -0
- package/dist/utils/response-builders.d.ts +88 -0
- package/dist/utils/response-builders.d.ts.map +1 -0
- package/dist/utils/response-builders.js +202 -0
- package/dist/{tools → utils}/test-helpers.d.ts +16 -0
- package/dist/utils/test-helpers.d.ts.map +1 -0
- package/dist/{tools → utils}/test-helpers.js +51 -0
- package/dist/utils/tool-names.d.ts +23 -0
- package/dist/utils/tool-names.d.ts.map +1 -0
- package/dist/utils/tool-names.js +25 -0
- package/package.json +1 -1
- package/dist/tools/__tests__/delete-one.test.d.ts +0 -2
- package/dist/tools/__tests__/delete-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/overview.test.d.ts +0 -2
- package/dist/tools/__tests__/overview.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-list.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-list.test.d.ts.map +0 -1
- package/dist/tools/__tests__/projects-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/projects-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/sections-manage.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-manage.test.d.ts.map +0 -1
- package/dist/tools/__tests__/sections-manage.test.js +0 -138
- package/dist/tools/__tests__/sections-search.test.d.ts +0 -2
- package/dist/tools/__tests__/sections-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-add-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-complete-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-complete-multiple.test.js +0 -146
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-by-date.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-completed.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-list-for-container.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-list-for-container.test.js +0 -232
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-organize-multiple.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-organize-multiple.test.js +0 -245
- package/dist/tools/__tests__/tasks-search.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-search.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-search.test.js +0 -106
- package/dist/tools/__tests__/tasks-update-one.test.d.ts +0 -2
- package/dist/tools/__tests__/tasks-update-one.test.d.ts.map +0 -1
- package/dist/tools/__tests__/tasks-update-one.test.js +0 -251
- package/dist/tools/delete-one.d.ts +0 -17
- package/dist/tools/delete-one.d.ts.map +0 -1
- package/dist/tools/delete-one.js +0 -25
- package/dist/tools/overview.d.ts +0 -14
- package/dist/tools/overview.d.ts.map +0 -1
- package/dist/tools/projects-list.d.ts +0 -29
- package/dist/tools/projects-list.d.ts.map +0 -1
- package/dist/tools/projects-list.js +0 -39
- package/dist/tools/projects-manage.d.ts +0 -24
- package/dist/tools/projects-manage.d.ts.map +0 -1
- package/dist/tools/projects-manage.js +0 -26
- package/dist/tools/sections-manage.d.ts +0 -23
- package/dist/tools/sections-manage.d.ts.map +0 -1
- package/dist/tools/sections-manage.js +0 -37
- package/dist/tools/sections-search.d.ts +0 -18
- package/dist/tools/sections-search.d.ts.map +0 -1
- package/dist/tools/sections-search.js +0 -27
- package/dist/tools/tasks-add-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-complete-multiple.d.ts +0 -16
- package/dist/tools/tasks-complete-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-complete-multiple.js +0 -23
- package/dist/tools/tasks-list-by-date.d.ts +0 -34
- package/dist/tools/tasks-list-by-date.d.ts.map +0 -1
- package/dist/tools/tasks-list-by-date.js +0 -53
- package/dist/tools/tasks-list-completed.d.ts +0 -44
- package/dist/tools/tasks-list-completed.d.ts.map +0 -1
- package/dist/tools/tasks-list-completed.js +0 -49
- package/dist/tools/tasks-list-for-container.d.ts +0 -34
- package/dist/tools/tasks-list-for-container.d.ts.map +0 -1
- package/dist/tools/tasks-list-for-container.js +0 -48
- package/dist/tools/tasks-organize-multiple.d.ts +0 -37
- package/dist/tools/tasks-organize-multiple.d.ts.map +0 -1
- package/dist/tools/tasks-organize-multiple.js +0 -34
- package/dist/tools/tasks-search.d.ts +0 -32
- package/dist/tools/tasks-search.d.ts.map +0 -1
- package/dist/tools/tasks-search.js +0 -30
- package/dist/tools/tasks-update-one.d.ts +0 -29
- package/dist/tools/tasks-update-one.d.ts.map +0 -1
- package/dist/tools/tasks-update-one.js +0 -63
- package/dist/tools/test-helpers.d.ts.map +0 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Section, TodoistApi } from '@doist/todoist-api-typescript';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { mapTask } from '../tool-helpers.js';
|
|
4
|
+
type ProjectStructure = {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
parentId: string | null;
|
|
8
|
+
sections: Section[];
|
|
9
|
+
children: ProjectStructure[];
|
|
10
|
+
};
|
|
11
|
+
type AccountOverviewStructured = Record<string, unknown> & {
|
|
12
|
+
type: 'account_overview';
|
|
13
|
+
inbox: {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
sections: Section[];
|
|
17
|
+
} | null;
|
|
18
|
+
projects: ProjectStructure[];
|
|
19
|
+
totalProjects: number;
|
|
20
|
+
totalSections: number;
|
|
21
|
+
hasNestedProjects: boolean;
|
|
22
|
+
};
|
|
23
|
+
interface ProjectOverviewStructured extends Record<string, unknown> {
|
|
24
|
+
type: 'project_overview';
|
|
25
|
+
project: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
sections: Section[];
|
|
30
|
+
tasks: Array<ReturnType<typeof mapTask> & {
|
|
31
|
+
children: never[];
|
|
32
|
+
}>;
|
|
33
|
+
stats: {
|
|
34
|
+
totalTasks: number;
|
|
35
|
+
totalSections: number;
|
|
36
|
+
tasksWithoutSection: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
declare const getOverview: {
|
|
40
|
+
name: "get-overview";
|
|
41
|
+
description: string;
|
|
42
|
+
parameters: {
|
|
43
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
44
|
+
};
|
|
45
|
+
execute(args: {
|
|
46
|
+
projectId?: string | undefined;
|
|
47
|
+
}, client: TodoistApi): Promise<{
|
|
48
|
+
content: {
|
|
49
|
+
type: "text";
|
|
50
|
+
text: string;
|
|
51
|
+
}[];
|
|
52
|
+
structuredContent: AccountOverviewStructured | ProjectOverviewStructured;
|
|
53
|
+
} | {
|
|
54
|
+
content: ({
|
|
55
|
+
type: "text";
|
|
56
|
+
text: string;
|
|
57
|
+
mimeType?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
type: "text";
|
|
60
|
+
mimeType: string;
|
|
61
|
+
text: string;
|
|
62
|
+
})[];
|
|
63
|
+
structuredContent?: undefined;
|
|
64
|
+
}>;
|
|
65
|
+
};
|
|
66
|
+
export { getOverview, type AccountOverviewStructured, type ProjectOverviewStructured };
|
|
67
|
+
//# sourceMappingURL=get-overview.d.ts.map
|
|
@@ -0,0 +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,5 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { getToolOutput } from '../mcp-helpers.js';
|
|
2
3
|
import { isPersonalProject, mapTask } from '../tool-helpers.js';
|
|
4
|
+
import { ApiLimits } from '../utils/constants.js';
|
|
5
|
+
import { ToolNames } from '../utils/tool-names.js';
|
|
3
6
|
const ArgsSchema = {
|
|
4
7
|
projectId: z
|
|
5
8
|
.string()
|
|
@@ -101,13 +104,22 @@ function renderTaskTreeMarkdown(tasks, indent = '') {
|
|
|
101
104
|
}
|
|
102
105
|
return lines;
|
|
103
106
|
}
|
|
107
|
+
function buildProjectStructure(project, sectionsByProject) {
|
|
108
|
+
return {
|
|
109
|
+
id: project.id,
|
|
110
|
+
name: project.name,
|
|
111
|
+
parentId: isPersonalProject(project) ? (project.parentId ?? null) : null,
|
|
112
|
+
sections: sectionsByProject[project.id] || [],
|
|
113
|
+
children: project.children.map((child) => buildProjectStructure(child, sectionsByProject)),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
104
116
|
async function getAllTasksForProject(client, projectId) {
|
|
105
117
|
let allTasks = [];
|
|
106
118
|
let cursor = undefined;
|
|
107
119
|
do {
|
|
108
120
|
const { results, nextCursor } = await client.getTasks({
|
|
109
121
|
projectId,
|
|
110
|
-
limit:
|
|
122
|
+
limit: ApiLimits.TASKS_BATCH_SIZE,
|
|
111
123
|
cursor: cursor ?? undefined,
|
|
112
124
|
});
|
|
113
125
|
allTasks = allTasks.concat(results.map(mapTask));
|
|
@@ -119,7 +131,6 @@ async function getProjectSections(client, projectId) {
|
|
|
119
131
|
const { results } = await client.getSections({ projectId });
|
|
120
132
|
return results;
|
|
121
133
|
}
|
|
122
|
-
// Account overview implementation
|
|
123
134
|
async function generateAccountOverview(client) {
|
|
124
135
|
const { results: projects } = await client.getProjects({});
|
|
125
136
|
const inbox = projects.find((p) => isPersonalProject(p) && p.inboxProject === true);
|
|
@@ -127,6 +138,7 @@ async function generateAccountOverview(client) {
|
|
|
127
138
|
const tree = buildProjectTree(nonInbox);
|
|
128
139
|
const allProjectIds = projects.map((p) => p.id);
|
|
129
140
|
const sectionsByProject = await getSectionsByProject(client, allProjectIds);
|
|
141
|
+
// Generate markdown text content
|
|
130
142
|
const lines = ['# Personal Projects', ''];
|
|
131
143
|
if (inbox) {
|
|
132
144
|
lines.push(`- Inbox Project: ${inbox.name} (id=${inbox.id})`);
|
|
@@ -148,9 +160,24 @@ async function generateAccountOverview(client) {
|
|
|
148
160
|
if (hasNested) {
|
|
149
161
|
lines.push('_Note: Indentation indicates that a project is a sub-project of the one above it. This allows for organizing projects hierarchically, with parent projects containing related sub-projects._', '');
|
|
150
162
|
}
|
|
151
|
-
|
|
163
|
+
const textContent = lines.join('\n');
|
|
164
|
+
// Generate structured content
|
|
165
|
+
const structuredContent = {
|
|
166
|
+
type: 'account_overview',
|
|
167
|
+
inbox: inbox
|
|
168
|
+
? {
|
|
169
|
+
id: inbox.id,
|
|
170
|
+
name: inbox.name,
|
|
171
|
+
sections: sectionsByProject[inbox.id] || [],
|
|
172
|
+
}
|
|
173
|
+
: null,
|
|
174
|
+
projects: tree.map((project) => buildProjectStructure(project, sectionsByProject)),
|
|
175
|
+
totalProjects: projects.length,
|
|
176
|
+
totalSections: allProjectIds.reduce((total, id) => total + (sectionsByProject[id]?.length || 0), 0),
|
|
177
|
+
hasNestedProjects: hasNested,
|
|
178
|
+
};
|
|
179
|
+
return { textContent, structuredContent };
|
|
152
180
|
}
|
|
153
|
-
// Project overview implementation
|
|
154
181
|
async function generateProjectOverview(client, projectId) {
|
|
155
182
|
const project = await client.getProject(projectId);
|
|
156
183
|
const sections = await getProjectSections(client, projectId);
|
|
@@ -162,14 +189,12 @@ async function generateProjectOverview(client, projectId) {
|
|
|
162
189
|
}
|
|
163
190
|
const tasksWithoutSection = [];
|
|
164
191
|
for (const task of allTasks) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
else {
|
|
170
|
-
tasksWithoutSection.push(task);
|
|
171
|
-
}
|
|
192
|
+
const sectionTasks = task.sectionId
|
|
193
|
+
? (tasksBySection[task.sectionId] ?? tasksWithoutSection)
|
|
194
|
+
: tasksWithoutSection;
|
|
195
|
+
sectionTasks.push(task);
|
|
172
196
|
}
|
|
197
|
+
// Generate markdown text content
|
|
173
198
|
const lines = [`# ${project.name}`];
|
|
174
199
|
if (tasksWithoutSection.length > 0) {
|
|
175
200
|
lines.push('');
|
|
@@ -186,17 +211,39 @@ async function generateProjectOverview(client, projectId) {
|
|
|
186
211
|
const tree = buildTaskTree(sectionTasks);
|
|
187
212
|
lines.push(...renderTaskTreeMarkdown(tree));
|
|
188
213
|
}
|
|
189
|
-
|
|
214
|
+
const textContent = lines.join('\n');
|
|
215
|
+
// Generate structured content
|
|
216
|
+
const structuredContent = {
|
|
217
|
+
type: 'project_overview',
|
|
218
|
+
project: {
|
|
219
|
+
id: project.id,
|
|
220
|
+
name: project.name,
|
|
221
|
+
},
|
|
222
|
+
sections: sections,
|
|
223
|
+
tasks: allTasks.map((task) => ({
|
|
224
|
+
...task,
|
|
225
|
+
children: [], // Tasks already include hierarchical info via parentId
|
|
226
|
+
})),
|
|
227
|
+
stats: {
|
|
228
|
+
totalTasks: allTasks.length,
|
|
229
|
+
totalSections: sections.length,
|
|
230
|
+
tasksWithoutSection: tasksWithoutSection.length,
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
return { textContent, structuredContent };
|
|
190
234
|
}
|
|
191
|
-
const
|
|
192
|
-
name:
|
|
235
|
+
const getOverview = {
|
|
236
|
+
name: ToolNames.GET_OVERVIEW,
|
|
193
237
|
description: 'Get a Markdown overview. If no projectId is provided, shows all projects with hierarchy and sections (useful for navigation). If projectId is provided, shows detailed overview of that specific project including all tasks grouped by sections.',
|
|
194
238
|
parameters: ArgsSchema,
|
|
195
239
|
async execute(args, client) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return
|
|
240
|
+
const result = args.projectId
|
|
241
|
+
? await generateProjectOverview(client, args.projectId)
|
|
242
|
+
: await generateAccountOverview(client);
|
|
243
|
+
return getToolOutput({
|
|
244
|
+
textContent: result.textContent,
|
|
245
|
+
structuredContent: result.structuredContent,
|
|
246
|
+
});
|
|
200
247
|
},
|
|
201
248
|
};
|
|
202
|
-
export {
|
|
249
|
+
export { getOverview };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const manageProjects: {
|
|
3
|
+
name: "manage-projects";
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: {
|
|
6
|
+
id: z.ZodOptional<z.ZodString>;
|
|
7
|
+
name: z.ZodString;
|
|
8
|
+
};
|
|
9
|
+
execute(args: {
|
|
10
|
+
name: string;
|
|
11
|
+
id?: string | undefined;
|
|
12
|
+
}, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
structuredContent: {
|
|
18
|
+
project: import("@doist/todoist-api-typescript").PersonalProject | import("@doist/todoist-api-typescript").WorkspaceProject;
|
|
19
|
+
operation: string;
|
|
20
|
+
};
|
|
21
|
+
} | {
|
|
22
|
+
content: ({
|
|
23
|
+
type: "text";
|
|
24
|
+
text: string;
|
|
25
|
+
mimeType?: undefined;
|
|
26
|
+
} | {
|
|
27
|
+
type: "text";
|
|
28
|
+
mimeType: string;
|
|
29
|
+
text: string;
|
|
30
|
+
})[];
|
|
31
|
+
structuredContent?: undefined;
|
|
32
|
+
}>;
|
|
33
|
+
};
|
|
34
|
+
export { manageProjects };
|
|
35
|
+
//# sourceMappingURL=manage-projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage-projects.d.ts","sourceRoot":"","sources":["../../src/tools/manage-projects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAmBvB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgCsB,CAAA;AA+B1C,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getToolOutput } from '../mcp-helpers.js';
|
|
3
|
+
import { formatNextSteps } from '../utils/response-builders.js';
|
|
4
|
+
import { ToolNames } from '../utils/tool-names.js';
|
|
5
|
+
const { MANAGE_SECTIONS, ADD_TASKS, FIND_PROJECTS, FIND_TASKS, GET_OVERVIEW } = ToolNames;
|
|
6
|
+
const ArgsSchema = {
|
|
7
|
+
id: z
|
|
8
|
+
.string()
|
|
9
|
+
.min(1)
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('The ID of the project to update. If provided, updates the project. If omitted, creates a new project.'),
|
|
12
|
+
name: z.string().min(1).describe('The name of the project.'),
|
|
13
|
+
};
|
|
14
|
+
const manageProjects = {
|
|
15
|
+
name: ToolNames.MANAGE_PROJECTS,
|
|
16
|
+
description: 'Add a new project or update an existing project. If id is provided, updates the project. If id is omitted, creates a new project.',
|
|
17
|
+
parameters: ArgsSchema,
|
|
18
|
+
async execute(args, client) {
|
|
19
|
+
if (args.id) {
|
|
20
|
+
// Update existing project
|
|
21
|
+
const project = await client.updateProject(args.id, { name: args.name });
|
|
22
|
+
const textContent = generateTextContent({ project, operation: 'updated' });
|
|
23
|
+
return getToolOutput({
|
|
24
|
+
textContent,
|
|
25
|
+
structuredContent: {
|
|
26
|
+
project,
|
|
27
|
+
operation: 'updated',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// Create new project
|
|
32
|
+
const project = await client.addProject({ name: args.name });
|
|
33
|
+
const textContent = generateTextContent({ project, operation: 'created' });
|
|
34
|
+
return getToolOutput({
|
|
35
|
+
textContent,
|
|
36
|
+
structuredContent: {
|
|
37
|
+
project,
|
|
38
|
+
operation: 'created',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
function generateTextContent({ project, operation, }) {
|
|
44
|
+
const action = operation === 'created' ? 'Created' : 'Updated';
|
|
45
|
+
const summary = `${action} project: ${project.name} • id=${project.id}`;
|
|
46
|
+
// Context-aware next steps based on operation
|
|
47
|
+
const nextSteps = [];
|
|
48
|
+
if (operation === 'created') {
|
|
49
|
+
// For new projects, suggest logical setup workflow
|
|
50
|
+
nextSteps.push(`Use ${MANAGE_SECTIONS} to organize this project with sections`);
|
|
51
|
+
nextSteps.push(`Use ${ADD_TASKS} to add your first tasks`);
|
|
52
|
+
nextSteps.push(`Use ${GET_OVERVIEW} with projectId to see updated project structure.`);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
// For updated projects, suggest review and management
|
|
56
|
+
nextSteps.push(`Use ${GET_OVERVIEW} with projectId=${project.id} to see project structure`);
|
|
57
|
+
nextSteps.push(`Use ${FIND_PROJECTS} to see all projects with updated name`);
|
|
58
|
+
nextSteps.push(`Use ${FIND_TASKS} with projectId=${project.id} to review existing tasks`);
|
|
59
|
+
}
|
|
60
|
+
const next = formatNextSteps(nextSteps);
|
|
61
|
+
return `${summary}\n${next}`;
|
|
62
|
+
}
|
|
63
|
+
export { manageProjects };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Section } from '@doist/todoist-api-typescript';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
declare const manageSections: {
|
|
4
|
+
name: "manage-sections";
|
|
5
|
+
description: string;
|
|
6
|
+
parameters: {
|
|
7
|
+
id: z.ZodOptional<z.ZodString>;
|
|
8
|
+
name: z.ZodString;
|
|
9
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
10
|
+
};
|
|
11
|
+
execute(args: {
|
|
12
|
+
name: string;
|
|
13
|
+
id?: string | undefined;
|
|
14
|
+
projectId?: string | undefined;
|
|
15
|
+
}, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
|
|
16
|
+
content: {
|
|
17
|
+
type: "text";
|
|
18
|
+
text: string;
|
|
19
|
+
}[];
|
|
20
|
+
structuredContent: {
|
|
21
|
+
section: Section;
|
|
22
|
+
operation: string;
|
|
23
|
+
};
|
|
24
|
+
} | {
|
|
25
|
+
content: ({
|
|
26
|
+
type: "text";
|
|
27
|
+
text: string;
|
|
28
|
+
mimeType?: undefined;
|
|
29
|
+
} | {
|
|
30
|
+
type: "text";
|
|
31
|
+
mimeType: string;
|
|
32
|
+
text: string;
|
|
33
|
+
})[];
|
|
34
|
+
structuredContent?: undefined;
|
|
35
|
+
}>;
|
|
36
|
+
};
|
|
37
|
+
export { manageSections };
|
|
38
|
+
//# sourceMappingURL=manage-sections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage-sections.d.ts","sourceRoot":"","sources":["../../src/tools/manage-sections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAA;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA0BvB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CsB,CAAA;AAuC1C,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getToolOutput } from '../mcp-helpers.js';
|
|
3
|
+
import { formatNextSteps } from '../utils/response-builders.js';
|
|
4
|
+
import { ToolNames } from '../utils/tool-names.js';
|
|
5
|
+
const { ADD_TASKS, FIND_TASKS, GET_OVERVIEW, FIND_SECTIONS } = ToolNames;
|
|
6
|
+
const ArgsSchema = {
|
|
7
|
+
id: z
|
|
8
|
+
.string()
|
|
9
|
+
.min(1)
|
|
10
|
+
.optional()
|
|
11
|
+
.describe('The ID of the section to update. If provided, updates the section. If omitted, creates a new section.'),
|
|
12
|
+
name: z.string().min(1).describe('The name of the section.'),
|
|
13
|
+
projectId: z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('The ID of the project to add the section to. Required when creating a new section (when id is not provided).'),
|
|
18
|
+
};
|
|
19
|
+
const manageSections = {
|
|
20
|
+
name: ToolNames.MANAGE_SECTIONS,
|
|
21
|
+
description: 'Add a new section to a project or update an existing section. If id is provided, updates the section. If id is omitted, creates a new section (requires projectId).',
|
|
22
|
+
parameters: ArgsSchema,
|
|
23
|
+
async execute(args, client) {
|
|
24
|
+
if (args.id) {
|
|
25
|
+
// Update existing section
|
|
26
|
+
const section = await client.updateSection(args.id, { name: args.name });
|
|
27
|
+
const textContent = generateTextContent({ section, operation: 'updated' });
|
|
28
|
+
return getToolOutput({
|
|
29
|
+
textContent,
|
|
30
|
+
structuredContent: {
|
|
31
|
+
section,
|
|
32
|
+
operation: 'updated',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// Create new section - projectId is required
|
|
37
|
+
if (!args.projectId) {
|
|
38
|
+
throw new Error('Error: projectId is required when creating a new section (when id is not provided).');
|
|
39
|
+
}
|
|
40
|
+
const section = await client.addSection({
|
|
41
|
+
name: args.name,
|
|
42
|
+
projectId: args.projectId,
|
|
43
|
+
});
|
|
44
|
+
const textContent = generateTextContent({ section, operation: 'created' });
|
|
45
|
+
return getToolOutput({
|
|
46
|
+
textContent,
|
|
47
|
+
structuredContent: {
|
|
48
|
+
section,
|
|
49
|
+
operation: 'created',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
function generateTextContent({ section, operation, }) {
|
|
55
|
+
const action = operation === 'created' ? 'Created' : 'Updated';
|
|
56
|
+
const summary = `${action} section: ${section.name} • id=${section.id}`;
|
|
57
|
+
// Workflow-aware next steps based on operation and section context
|
|
58
|
+
const nextSteps = [];
|
|
59
|
+
if (operation === 'created') {
|
|
60
|
+
// For new sections, suggest immediate setup workflow
|
|
61
|
+
nextSteps.push(`Use ${ADD_TASKS} with sectionId=${section.id} to add your first tasks`);
|
|
62
|
+
nextSteps.push(`Use ${FIND_TASKS} with sectionId=${section.id} to verify setup`);
|
|
63
|
+
// Suggest related organization
|
|
64
|
+
if (section.projectId) {
|
|
65
|
+
nextSteps.push(`Use ${GET_OVERVIEW} with projectId=${section.projectId} to see project organization`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// For updated sections, suggest review and management
|
|
70
|
+
nextSteps.push(`Use ${FIND_TASKS} with sectionId=${section.id} to see existing tasks`);
|
|
71
|
+
nextSteps.push(`Use ${FIND_SECTIONS} to see all sections in this project`);
|
|
72
|
+
// Suggest task updates if section was renamed
|
|
73
|
+
nextSteps.push('Consider updating task descriptions if section purpose changed');
|
|
74
|
+
}
|
|
75
|
+
const next = formatNextSteps(nextSteps);
|
|
76
|
+
return `${summary}\n${next}`;
|
|
77
|
+
}
|
|
78
|
+
export { manageSections };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const updateTasks: {
|
|
3
|
+
name: "update-tasks";
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: {
|
|
6
|
+
tasks: z.ZodArray<z.ZodObject<{
|
|
7
|
+
id: z.ZodString;
|
|
8
|
+
content: z.ZodOptional<z.ZodString>;
|
|
9
|
+
description: z.ZodOptional<z.ZodString>;
|
|
10
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
11
|
+
sectionId: z.ZodOptional<z.ZodString>;
|
|
12
|
+
parentId: z.ZodOptional<z.ZodString>;
|
|
13
|
+
order: z.ZodOptional<z.ZodNumber>;
|
|
14
|
+
priority: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
dueString: z.ZodOptional<z.ZodString>;
|
|
16
|
+
duration: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, "strip", z.ZodTypeAny, {
|
|
18
|
+
id: string;
|
|
19
|
+
content?: string | undefined;
|
|
20
|
+
description?: string | undefined;
|
|
21
|
+
parentId?: string | undefined;
|
|
22
|
+
projectId?: string | undefined;
|
|
23
|
+
sectionId?: string | undefined;
|
|
24
|
+
priority?: number | undefined;
|
|
25
|
+
dueString?: string | undefined;
|
|
26
|
+
duration?: string | undefined;
|
|
27
|
+
order?: number | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
id: string;
|
|
30
|
+
content?: string | undefined;
|
|
31
|
+
description?: string | undefined;
|
|
32
|
+
parentId?: string | undefined;
|
|
33
|
+
projectId?: string | undefined;
|
|
34
|
+
sectionId?: string | undefined;
|
|
35
|
+
priority?: number | undefined;
|
|
36
|
+
dueString?: string | undefined;
|
|
37
|
+
duration?: string | undefined;
|
|
38
|
+
order?: number | undefined;
|
|
39
|
+
}>, "many">;
|
|
40
|
+
};
|
|
41
|
+
execute(args: {
|
|
42
|
+
tasks: {
|
|
43
|
+
id: string;
|
|
44
|
+
content?: string | undefined;
|
|
45
|
+
description?: string | undefined;
|
|
46
|
+
parentId?: string | undefined;
|
|
47
|
+
projectId?: string | undefined;
|
|
48
|
+
sectionId?: string | undefined;
|
|
49
|
+
priority?: number | undefined;
|
|
50
|
+
dueString?: string | undefined;
|
|
51
|
+
duration?: string | undefined;
|
|
52
|
+
order?: number | undefined;
|
|
53
|
+
}[];
|
|
54
|
+
}, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
|
|
55
|
+
content: {
|
|
56
|
+
type: "text";
|
|
57
|
+
text: string;
|
|
58
|
+
}[];
|
|
59
|
+
structuredContent: {
|
|
60
|
+
tasks: {
|
|
61
|
+
id: string;
|
|
62
|
+
content: string;
|
|
63
|
+
description: string;
|
|
64
|
+
dueDate: string | undefined;
|
|
65
|
+
recurring: string | boolean;
|
|
66
|
+
priority: number;
|
|
67
|
+
projectId: string;
|
|
68
|
+
sectionId: string | null;
|
|
69
|
+
parentId: string | null;
|
|
70
|
+
labels: string[];
|
|
71
|
+
duration: string | null;
|
|
72
|
+
}[];
|
|
73
|
+
totalCount: number;
|
|
74
|
+
updatedTaskIds: string[];
|
|
75
|
+
appliedOperations: {
|
|
76
|
+
updateCount: number;
|
|
77
|
+
skippedCount: number;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
} | {
|
|
81
|
+
content: ({
|
|
82
|
+
type: "text";
|
|
83
|
+
text: string;
|
|
84
|
+
mimeType?: undefined;
|
|
85
|
+
} | {
|
|
86
|
+
type: "text";
|
|
87
|
+
mimeType: string;
|
|
88
|
+
text: string;
|
|
89
|
+
})[];
|
|
90
|
+
structuredContent?: undefined;
|
|
91
|
+
}>;
|
|
92
|
+
};
|
|
93
|
+
export { updateTasks };
|
|
94
|
+
//# sourceMappingURL=update-tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/update-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2CvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6EyB,CAAA;AAqC1C,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getToolOutput } from '../mcp-helpers.js';
|
|
3
|
+
import { createMoveTaskArgs, mapTask } from '../tool-helpers.js';
|
|
4
|
+
import { DurationParseError, parseDuration } from '../utils/duration-parser.js';
|
|
5
|
+
import { summarizeTaskOperation } from '../utils/response-builders.js';
|
|
6
|
+
import { ToolNames } from '../utils/tool-names.js';
|
|
7
|
+
const { FIND_TASKS_BY_DATE, GET_OVERVIEW } = ToolNames;
|
|
8
|
+
const TasksUpdateSchema = z.object({
|
|
9
|
+
id: z.string().min(1).describe('The ID of the task to update.'),
|
|
10
|
+
content: z.string().optional().describe('The new content of the task.'),
|
|
11
|
+
description: z.string().optional().describe('The new description of the task.'),
|
|
12
|
+
projectId: z.string().optional().describe('The new project ID for the task.'),
|
|
13
|
+
sectionId: z.string().optional().describe('The new section ID for the task.'),
|
|
14
|
+
parentId: z.string().optional().describe('The new parent task ID (for subtasks).'),
|
|
15
|
+
order: z.number().optional().describe('The new order of the task within its parent/section.'),
|
|
16
|
+
priority: z
|
|
17
|
+
.number()
|
|
18
|
+
.int()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(4)
|
|
21
|
+
.optional()
|
|
22
|
+
.describe('The new priority of the task (1-4).'),
|
|
23
|
+
dueString: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("The new due date for the task, in natural language (e.g., 'tomorrow at 5pm')."),
|
|
27
|
+
duration: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('The duration of the task. Use format: "2h" (hours), "90m" (minutes), "2h30m" (combined), or "1.5h" (decimal hours). Max 24h.'),
|
|
31
|
+
});
|
|
32
|
+
const ArgsSchema = {
|
|
33
|
+
tasks: z.array(TasksUpdateSchema).min(1).describe('The tasks to update.'),
|
|
34
|
+
};
|
|
35
|
+
const updateTasks = {
|
|
36
|
+
name: ToolNames.UPDATE_TASKS,
|
|
37
|
+
description: 'Update multiple existing tasks with new values.',
|
|
38
|
+
parameters: ArgsSchema,
|
|
39
|
+
async execute(args, client) {
|
|
40
|
+
const { tasks } = args;
|
|
41
|
+
const updateTasksPromises = tasks.map(async (task) => {
|
|
42
|
+
if (!hasUpdatesToMake(task)) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const { id, projectId, sectionId, parentId, duration: durationStr, ...otherUpdateArgs } = task;
|
|
46
|
+
let updateArgs = { ...otherUpdateArgs };
|
|
47
|
+
// Parse duration if provided
|
|
48
|
+
if (durationStr) {
|
|
49
|
+
try {
|
|
50
|
+
const { minutes } = parseDuration(durationStr);
|
|
51
|
+
updateArgs = {
|
|
52
|
+
...updateArgs,
|
|
53
|
+
duration: minutes,
|
|
54
|
+
durationUnit: 'minute',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof DurationParseError) {
|
|
59
|
+
throw new Error(`Task ${id}: ${error.message}`);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// If no move parameters are provided, use updateTask without moveTasks
|
|
65
|
+
if (!projectId && !sectionId && !parentId) {
|
|
66
|
+
return await client.updateTask(id, updateArgs);
|
|
67
|
+
}
|
|
68
|
+
const moveArgs = createMoveTaskArgs(id, projectId, sectionId, parentId);
|
|
69
|
+
const movedTasks = await client.moveTasks([id], moveArgs);
|
|
70
|
+
if (Object.keys(updateArgs).length > 0) {
|
|
71
|
+
return await client.updateTask(id, updateArgs);
|
|
72
|
+
}
|
|
73
|
+
return movedTasks[0];
|
|
74
|
+
});
|
|
75
|
+
const updatedTasks = (await Promise.all(updateTasksPromises)).filter((task) => task !== undefined);
|
|
76
|
+
const mappedTasks = updatedTasks.map(mapTask);
|
|
77
|
+
const textContent = generateTextContent({
|
|
78
|
+
tasks: mappedTasks,
|
|
79
|
+
args,
|
|
80
|
+
});
|
|
81
|
+
return getToolOutput({
|
|
82
|
+
textContent,
|
|
83
|
+
structuredContent: {
|
|
84
|
+
tasks: mappedTasks,
|
|
85
|
+
totalCount: mappedTasks.length,
|
|
86
|
+
updatedTaskIds: updatedTasks.map((task) => task.id),
|
|
87
|
+
appliedOperations: {
|
|
88
|
+
updateCount: mappedTasks.length,
|
|
89
|
+
skippedCount: tasks.length - mappedTasks.length,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
function generateTextContent({ tasks, args, }) {
|
|
96
|
+
const totalRequested = args.tasks.length;
|
|
97
|
+
const actuallyUpdated = tasks.length;
|
|
98
|
+
const skipped = totalRequested - actuallyUpdated;
|
|
99
|
+
let context = '';
|
|
100
|
+
if (skipped > 0) {
|
|
101
|
+
context = ` (${skipped} skipped - no changes)`;
|
|
102
|
+
}
|
|
103
|
+
const nextSteps = [];
|
|
104
|
+
if (tasks.length > 0) {
|
|
105
|
+
nextSteps.push(`Use ${FIND_TASKS_BY_DATE} to see your updated schedule`);
|
|
106
|
+
nextSteps.push(`Use ${GET_OVERVIEW} to see updated project organization`);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
nextSteps.push(`Use ${FIND_TASKS_BY_DATE} to see current tasks`);
|
|
110
|
+
}
|
|
111
|
+
return summarizeTaskOperation('Updated', tasks, {
|
|
112
|
+
context,
|
|
113
|
+
nextSteps,
|
|
114
|
+
showDetails: tasks.length <= 5,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function hasUpdatesToMake({ id, ...otherUpdateArgs }) {
|
|
118
|
+
return Object.keys(otherUpdateArgs).length > 0;
|
|
119
|
+
}
|
|
120
|
+
export { updateTasks };
|