@doist/todoist-ai 6.0.0 → 6.2.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 +6 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/main.js +1 -1
- package/dist/mcp-helpers.d.ts +7 -1
- package/dist/mcp-helpers.d.ts.map +1 -1
- package/dist/mcp-server-B9j96GQ2.js +3304 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/todoist-tool.d.ts +6 -0
- package/dist/todoist-tool.d.ts.map +1 -1
- package/dist/tools/fetch-object.d.ts +168 -0
- package/dist/tools/fetch-object.d.ts.map +1 -0
- package/dist/tools/fetch.d.ts +8 -0
- package/dist/tools/fetch.d.ts.map +1 -1
- package/dist/tools/find-comments.d.ts +3 -0
- package/dist/tools/find-comments.d.ts.map +1 -1
- package/dist/tools/find-tasks-by-date.resource.d.ts +28 -0
- package/dist/tools/find-tasks-by-date.resource.d.ts.map +1 -0
- package/dist/utils/tool-names.d.ts +1 -0
- package/dist/utils/tool-names.d.ts.map +1 -1
- package/dist/utils/widget-loader.d.ts +7 -0
- package/dist/utils/widget-loader.d.ts.map +1 -0
- package/package.json +11 -1
- package/scripts/inline-widget-builder.ts +87 -0
- package/scripts/inline-widgets-vite-plugin.ts +134 -0
- package/dist/mcp-server-BwerBJpX.js +0 -3161
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAwGnE;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,aA0E5F;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
package/dist/todoist-tool.d.ts
CHANGED
|
@@ -44,6 +44,12 @@ type TodoistTool<Params extends z.ZodRawShape, Output extends z.ZodRawShape> = {
|
|
|
44
44
|
* This is used to generate appropriate MCP annotation hints (readOnlyHint, destructiveHint).
|
|
45
45
|
*/
|
|
46
46
|
mutability: ToolMutability;
|
|
47
|
+
/**
|
|
48
|
+
* The meta data of the tool.
|
|
49
|
+
*
|
|
50
|
+
* This is used to store additional information about the tool.
|
|
51
|
+
*/
|
|
52
|
+
_meta?: Record<string, unknown>;
|
|
47
53
|
/**
|
|
48
54
|
* The function that executes the tool.
|
|
49
55
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todoist-tool.d.ts","sourceRoot":"","sources":["../src/todoist-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,KAAK,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;CACnD,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,KAAK,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAE1D;;GAEG;AACH,KAAK,WAAW,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,EAAE,MAAM,SAAS,CAAC,CAAC,WAAW,IAAI;IAC3E;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,UAAU,EAAE,cAAc,CAAA;IAE1B;;;;;;;;OAQG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,KAAK,aAAa,CAAC,MAAM,CAAC,CAAA;CAC7F,CAAA;AAED,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"todoist-tool.d.ts","sourceRoot":"","sources":["../src/todoist-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,KAAK,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;CACnD,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,KAAK,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAA;AAE1D;;GAEG;AACH,KAAK,WAAW,CAAC,MAAM,SAAS,CAAC,CAAC,WAAW,EAAE,MAAM,SAAS,CAAC,CAAC,WAAW,IAAI;IAC3E;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAA;IAElB;;;;OAIG;IACH,YAAY,EAAE,MAAM,CAAA;IAEpB;;;;OAIG;IACH,UAAU,EAAE,cAAc,CAAA;IAE1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAE/B;;;;;;;;OAQG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,KAAK,aAAa,CAAC,MAAM,CAAC,CAAA;CAC7F,CAAA;AAED,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const fetchObject: {
|
|
3
|
+
name: "fetch-object";
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: {
|
|
6
|
+
type: z.ZodEnum<{
|
|
7
|
+
task: "task";
|
|
8
|
+
comment: "comment";
|
|
9
|
+
project: "project";
|
|
10
|
+
section: "section";
|
|
11
|
+
}>;
|
|
12
|
+
id: z.ZodString;
|
|
13
|
+
};
|
|
14
|
+
outputSchema: {
|
|
15
|
+
type: z.ZodEnum<{
|
|
16
|
+
task: "task";
|
|
17
|
+
comment: "comment";
|
|
18
|
+
project: "project";
|
|
19
|
+
section: "section";
|
|
20
|
+
}>;
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
object: z.ZodUnion<readonly [z.ZodObject<{
|
|
23
|
+
id: z.ZodString;
|
|
24
|
+
content: z.ZodString;
|
|
25
|
+
description: z.ZodString;
|
|
26
|
+
dueDate: z.ZodOptional<z.ZodString>;
|
|
27
|
+
recurring: z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>;
|
|
28
|
+
deadlineDate: z.ZodOptional<z.ZodString>;
|
|
29
|
+
priority: z.ZodEnum<{
|
|
30
|
+
p1: "p1";
|
|
31
|
+
p2: "p2";
|
|
32
|
+
p3: "p3";
|
|
33
|
+
p4: "p4";
|
|
34
|
+
}>;
|
|
35
|
+
projectId: z.ZodString;
|
|
36
|
+
sectionId: z.ZodOptional<z.ZodString>;
|
|
37
|
+
parentId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
39
|
+
duration: z.ZodOptional<z.ZodString>;
|
|
40
|
+
responsibleUid: z.ZodOptional<z.ZodString>;
|
|
41
|
+
isUncompletable: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
assignedByUid: z.ZodOptional<z.ZodString>;
|
|
43
|
+
checked: z.ZodBoolean;
|
|
44
|
+
completedAt: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
46
|
+
id: z.ZodString;
|
|
47
|
+
name: z.ZodString;
|
|
48
|
+
color: z.ZodString;
|
|
49
|
+
isFavorite: z.ZodBoolean;
|
|
50
|
+
isShared: z.ZodBoolean;
|
|
51
|
+
parentId: z.ZodOptional<z.ZodString>;
|
|
52
|
+
inboxProject: z.ZodBoolean;
|
|
53
|
+
viewStyle: z.ZodString;
|
|
54
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
55
|
+
id: z.ZodString;
|
|
56
|
+
taskId: z.ZodOptional<z.ZodString>;
|
|
57
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
58
|
+
content: z.ZodString;
|
|
59
|
+
postedAt: z.ZodString;
|
|
60
|
+
postedUid: z.ZodOptional<z.ZodString>;
|
|
61
|
+
fileAttachment: z.ZodOptional<z.ZodObject<{
|
|
62
|
+
resourceType: z.ZodString;
|
|
63
|
+
fileName: z.ZodOptional<z.ZodString>;
|
|
64
|
+
fileSize: z.ZodOptional<z.ZodNumber>;
|
|
65
|
+
fileType: z.ZodOptional<z.ZodString>;
|
|
66
|
+
fileUrl: z.ZodOptional<z.ZodString>;
|
|
67
|
+
fileDuration: z.ZodOptional<z.ZodNumber>;
|
|
68
|
+
uploadState: z.ZodOptional<z.ZodEnum<{
|
|
69
|
+
pending: "pending";
|
|
70
|
+
completed: "completed";
|
|
71
|
+
}>>;
|
|
72
|
+
url: z.ZodOptional<z.ZodString>;
|
|
73
|
+
title: z.ZodOptional<z.ZodString>;
|
|
74
|
+
image: z.ZodOptional<z.ZodString>;
|
|
75
|
+
imageWidth: z.ZodOptional<z.ZodNumber>;
|
|
76
|
+
imageHeight: z.ZodOptional<z.ZodNumber>;
|
|
77
|
+
}, z.core.$strip>>;
|
|
78
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
79
|
+
id: z.ZodString;
|
|
80
|
+
name: z.ZodString;
|
|
81
|
+
}, z.core.$strip>]>;
|
|
82
|
+
};
|
|
83
|
+
mutability: "readonly";
|
|
84
|
+
execute(args: {
|
|
85
|
+
type: "task" | "comment" | "project" | "section";
|
|
86
|
+
id: string;
|
|
87
|
+
}, client: import('@doist/todoist-api-typescript').TodoistApi): Promise<{
|
|
88
|
+
textContent: string;
|
|
89
|
+
structuredContent: {
|
|
90
|
+
type: "task";
|
|
91
|
+
id: string;
|
|
92
|
+
object: {
|
|
93
|
+
id: string;
|
|
94
|
+
content: string;
|
|
95
|
+
description: string;
|
|
96
|
+
dueDate: string | undefined;
|
|
97
|
+
recurring: string | boolean;
|
|
98
|
+
deadlineDate: string | undefined;
|
|
99
|
+
priority: "p1" | "p2" | "p3" | "p4";
|
|
100
|
+
projectId: string;
|
|
101
|
+
sectionId: string | undefined;
|
|
102
|
+
parentId: string | undefined;
|
|
103
|
+
labels: string[];
|
|
104
|
+
duration: string | undefined;
|
|
105
|
+
responsibleUid: string | undefined;
|
|
106
|
+
assignedByUid: string | undefined;
|
|
107
|
+
checked: boolean;
|
|
108
|
+
completedAt: string | undefined;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
} | {
|
|
112
|
+
textContent: string;
|
|
113
|
+
structuredContent: {
|
|
114
|
+
type: "project";
|
|
115
|
+
id: string;
|
|
116
|
+
object: {
|
|
117
|
+
id: string;
|
|
118
|
+
name: string;
|
|
119
|
+
color: string;
|
|
120
|
+
isFavorite: boolean;
|
|
121
|
+
isShared: boolean;
|
|
122
|
+
parentId: string | undefined;
|
|
123
|
+
inboxProject: boolean;
|
|
124
|
+
viewStyle: string;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
} | {
|
|
128
|
+
textContent: string;
|
|
129
|
+
structuredContent: {
|
|
130
|
+
type: "comment";
|
|
131
|
+
id: string;
|
|
132
|
+
object: {
|
|
133
|
+
id: string;
|
|
134
|
+
taskId: string | undefined;
|
|
135
|
+
projectId: string | undefined;
|
|
136
|
+
content: string;
|
|
137
|
+
postedAt: string;
|
|
138
|
+
postedUid: string;
|
|
139
|
+
fileAttachment: {
|
|
140
|
+
resourceType: string;
|
|
141
|
+
fileName: string | undefined;
|
|
142
|
+
fileSize: number | undefined;
|
|
143
|
+
fileType: string | undefined;
|
|
144
|
+
fileUrl: string | undefined;
|
|
145
|
+
fileDuration: number | undefined;
|
|
146
|
+
uploadState: "pending" | "completed" | undefined;
|
|
147
|
+
url: string | undefined;
|
|
148
|
+
title: string | undefined;
|
|
149
|
+
image: string | undefined;
|
|
150
|
+
imageWidth: number | undefined;
|
|
151
|
+
imageHeight: number | undefined;
|
|
152
|
+
} | undefined;
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
} | {
|
|
156
|
+
textContent: string;
|
|
157
|
+
structuredContent: {
|
|
158
|
+
type: "section";
|
|
159
|
+
id: string;
|
|
160
|
+
object: {
|
|
161
|
+
id: string;
|
|
162
|
+
name: string;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
}>;
|
|
166
|
+
};
|
|
167
|
+
export { fetchObject };
|
|
168
|
+
//# sourceMappingURL=fetch-object.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-object.d.ts","sourceRoot":"","sources":["../../src/tools/fetch-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+E8C,CAAA;AAE/D,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
package/dist/tools/fetch.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
type FetchResult = {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
text: string;
|
|
6
|
+
url: string;
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
};
|
|
2
9
|
/**
|
|
3
10
|
* OpenAI MCP fetch tool - retrieves the full contents of a task or project by ID.
|
|
4
11
|
*
|
|
@@ -23,6 +30,7 @@ declare const fetch: {
|
|
|
23
30
|
id: string;
|
|
24
31
|
}, client: import('@doist/todoist-api-typescript').TodoistApi): Promise<{
|
|
25
32
|
textContent: string;
|
|
33
|
+
structuredContent: FetchResult;
|
|
26
34
|
}>;
|
|
27
35
|
};
|
|
28
36
|
export { fetch };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/tools/fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAcvB,KAAK,WAAW,GAAG;IACf,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC,CAAA;AAaD;;;;;GAKG;AACH,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;CA2FoD,CAAA;AAE/D,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -35,6 +35,9 @@ declare const findComments: {
|
|
|
35
35
|
imageHeight: z.ZodOptional<z.ZodNumber>;
|
|
36
36
|
}, z.core.$strip>>;
|
|
37
37
|
}, z.core.$strip>>;
|
|
38
|
+
searchType: z.ZodString;
|
|
39
|
+
searchId: z.ZodString;
|
|
40
|
+
hasMore: z.ZodBoolean;
|
|
38
41
|
nextCursor: z.ZodOptional<z.ZodString>;
|
|
39
42
|
totalCount: z.ZodNumber;
|
|
40
43
|
};
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAwCvB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8E6C,CAAA;AAmD/D,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare function createFindTasksByDateResource(uri: string, rawHtml: string): {
|
|
2
|
+
name: string;
|
|
3
|
+
uri: string;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
text: string;
|
|
6
|
+
_meta: {
|
|
7
|
+
/**
|
|
8
|
+
* Renders the widget within a rounded border and shadow.
|
|
9
|
+
* Otherwise, the HTML is rendered full-bleed in the conversation
|
|
10
|
+
*/
|
|
11
|
+
'openai/widgetDescription': string;
|
|
12
|
+
'openai/widgetPrefersBorder': boolean;
|
|
13
|
+
'openai/widgetAccessible': boolean;
|
|
14
|
+
'openai/toolInvocation/invoking': string;
|
|
15
|
+
'openai/toolInvocation/invoked': string;
|
|
16
|
+
'openai/widgetDomain': string;
|
|
17
|
+
/**
|
|
18
|
+
* Required to make external network requests from the HTML code.
|
|
19
|
+
* Also used to validate `openai.openExternal()` requests.
|
|
20
|
+
*/
|
|
21
|
+
'openai/widgetCSP': {
|
|
22
|
+
connect_domains: string[];
|
|
23
|
+
resource_domains: string[];
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export { createFindTasksByDateResource };
|
|
28
|
+
//# sourceMappingURL=find-tasks-by-date.resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-tasks-by-date.resource.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks-by-date.resource.ts"],"names":[],"mappings":"AAAA,iBAAS,6BAA6B,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;QAOvD;;;WAGG;;;;;;;QAOH;;;WAGG;;;;;;EASd;AAED,OAAO,EAAE,6BAA6B,EAAE,CAAA"}
|
|
@@ -26,6 +26,7 @@ export declare const ToolNames: {
|
|
|
26
26
|
readonly FIND_ACTIVITY: "find-activity";
|
|
27
27
|
readonly GET_OVERVIEW: "get-overview";
|
|
28
28
|
readonly DELETE_OBJECT: "delete-object";
|
|
29
|
+
readonly FETCH_OBJECT: "fetch-object";
|
|
29
30
|
readonly USER_INFO: "user-info";
|
|
30
31
|
readonly SEARCH: "search";
|
|
31
32
|
readonly FETCH: "fetch";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-names.d.ts","sourceRoot":"","sources":["../../src/utils/tool-names.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"tool-names.d.ts","sourceRoot":"","sources":["../../src/utils/tool-names.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;CAwCZ,CAAA;AAGV,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-loader.d.ts","sourceRoot":"","sources":["../../src/utils/widget-loader.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAYD,iBAAS,kBAAkB,CAAC,YAAY,GAAE,cAA+B,GAAG,cAAc,CAMzF;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doist/todoist-ai",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
|
+
"!dist/dev",
|
|
13
14
|
"scripts",
|
|
14
15
|
"package.json",
|
|
15
16
|
"LICENSE.txt",
|
|
@@ -34,6 +35,7 @@
|
|
|
34
35
|
"postbuild": "chmod +x dist/main.js",
|
|
35
36
|
"start": "npm run build && npx @modelcontextprotocol/inspector node dist/main.js",
|
|
36
37
|
"dev": "concurrently \"vite build --watch\" \"npx @modelcontextprotocol/inspector npx nodemon --quiet --watch dist --ext js --exec node dist/main.js\"",
|
|
38
|
+
"dev:widget": "vite build --watch --minify false",
|
|
37
39
|
"setup": "cp .env.example .env && npm install && npm run build",
|
|
38
40
|
"test:executable": "npm run build && node scripts/test-executable.cjs",
|
|
39
41
|
"type-check": "npx tsc --noEmit",
|
|
@@ -51,14 +53,18 @@
|
|
|
51
53
|
"@doist/todoist-api-typescript": "6.2.1",
|
|
52
54
|
"@modelcontextprotocol/sdk": "1.24.3",
|
|
53
55
|
"date-fns": "4.1.0",
|
|
56
|
+
"dompurify": "3.3.1",
|
|
54
57
|
"dotenv": "17.2.3",
|
|
55
58
|
"zod": "4.1.13"
|
|
56
59
|
},
|
|
57
60
|
"devDependencies": {
|
|
58
61
|
"@biomejs/biome": "2.3.8",
|
|
62
|
+
"@types/dompurify": "3.0.5",
|
|
59
63
|
"@types/express": "5.0.6",
|
|
60
64
|
"@types/morgan": "1.9.10",
|
|
61
65
|
"@types/node": "22.19.2",
|
|
66
|
+
"@types/react": "19.2.2",
|
|
67
|
+
"@types/react-dom": "19.2.2",
|
|
62
68
|
"concurrently": "9.2.1",
|
|
63
69
|
"express": "5.2.1",
|
|
64
70
|
"husky": "9.1.7",
|
|
@@ -66,6 +72,10 @@
|
|
|
66
72
|
"morgan": "1.10.1",
|
|
67
73
|
"nodemon": "3.1.11",
|
|
68
74
|
"rimraf": "6.1.2",
|
|
75
|
+
"react": "19.2.0",
|
|
76
|
+
"react-dom": "19.2.0",
|
|
77
|
+
"snarkdown": "2.0.0",
|
|
78
|
+
"tsx": "4.20.6",
|
|
69
79
|
"typescript": "5.9.3",
|
|
70
80
|
"vite": "7.2.7",
|
|
71
81
|
"vite-plugin-dts": "4.5.4",
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import type { BuildResult } from 'esbuild'
|
|
5
|
+
import { build } from 'esbuild'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
8
|
+
const __dirname = dirname(__filename)
|
|
9
|
+
|
|
10
|
+
const PLACEHOLDER = '<!-- INLINE_WIDGET_SCRIPT -->'
|
|
11
|
+
|
|
12
|
+
type InlineWidget = {
|
|
13
|
+
entryFile: string
|
|
14
|
+
htmlTemplate: string
|
|
15
|
+
outputName: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type InlineWidgetBuildResult = {
|
|
19
|
+
fileName: string
|
|
20
|
+
content: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export async function buildInlineWidget(
|
|
24
|
+
widget: InlineWidget,
|
|
25
|
+
{ buildTimestamp }: { buildTimestamp: string },
|
|
26
|
+
): Promise<InlineWidgetBuildResult> {
|
|
27
|
+
const projectRoot = resolve(__dirname, '..')
|
|
28
|
+
const entryPath = join(projectRoot, widget.entryFile)
|
|
29
|
+
const templatePath = join(projectRoot, widget.htmlTemplate)
|
|
30
|
+
const outputFileName = `${widget.outputName}-${buildTimestamp}.html`
|
|
31
|
+
|
|
32
|
+
if (!existsSync(templatePath)) {
|
|
33
|
+
throw new Error(`HTML template not found: ${templatePath}`)
|
|
34
|
+
}
|
|
35
|
+
const htmlTemplateContent = readFileSync(templatePath, 'utf-8')
|
|
36
|
+
if (!htmlTemplateContent.includes(PLACEHOLDER)) {
|
|
37
|
+
throw new Error(`Placeholder ${PLACEHOLDER} not found in ${templatePath}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const result: BuildResult = await build({
|
|
41
|
+
entryPoints: [entryPath],
|
|
42
|
+
bundle: true,
|
|
43
|
+
write: false,
|
|
44
|
+
format: 'iife',
|
|
45
|
+
platform: 'browser',
|
|
46
|
+
target: 'es2020',
|
|
47
|
+
minify: true,
|
|
48
|
+
jsx: 'automatic',
|
|
49
|
+
globalName: 'Widget',
|
|
50
|
+
outdir: 'out',
|
|
51
|
+
loader: {
|
|
52
|
+
'.svg': 'dataurl',
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
if (!result.outputFiles || result.outputFiles.length === 0) {
|
|
57
|
+
throw new Error(`Failed to build ${widget.entryFile}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const jsFile = result.outputFiles.find((file) => file.path.endsWith('.js'))
|
|
61
|
+
const cssFile = result.outputFiles.find((file) => file.path.endsWith('.css'))
|
|
62
|
+
|
|
63
|
+
if (!jsFile) {
|
|
64
|
+
throw new Error(`No JavaScript output found for ${widget.entryFile}`)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const bundledCode = jsFile.text
|
|
68
|
+
const sanitizedBundledCode = bundledCode
|
|
69
|
+
.replace(/<\/script/gi, '<\\/script')
|
|
70
|
+
.replace(/<!--/g, '<\\!--')
|
|
71
|
+
|
|
72
|
+
// Build the inline style tag if CSS exists
|
|
73
|
+
const inlinedStyle = cssFile ? `<style>${cssFile.text}</style>` : ''
|
|
74
|
+
|
|
75
|
+
const inlinedScript = `
|
|
76
|
+
${inlinedStyle}
|
|
77
|
+
<script>
|
|
78
|
+
${sanitizedBundledCode}
|
|
79
|
+
if (typeof Widget !== 'undefined' && typeof Widget.renderWidget === 'function') {
|
|
80
|
+
Widget.renderWidget();
|
|
81
|
+
}
|
|
82
|
+
</script>
|
|
83
|
+
`
|
|
84
|
+
const finalHtml = htmlTemplateContent.replace(PLACEHOLDER, () => inlinedScript)
|
|
85
|
+
|
|
86
|
+
return { fileName: outputFileName, content: finalHtml }
|
|
87
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import type { Plugin, PluginContext } from 'vite'
|
|
5
|
+
|
|
6
|
+
import { buildInlineWidget, type InlineWidgetBuildResult } from './inline-widget-builder.js'
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
9
|
+
const __dirname = dirname(__filename)
|
|
10
|
+
|
|
11
|
+
type InlineWidgetConfig = {
|
|
12
|
+
entryFile: string
|
|
13
|
+
htmlTemplate: string
|
|
14
|
+
outputName: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const TASK_LIST_WIDGET: InlineWidgetConfig = {
|
|
18
|
+
entryFile: 'src/widgets/task-list/widget.tsx',
|
|
19
|
+
htmlTemplate: 'src/widgets/task-list/template.html',
|
|
20
|
+
outputName: 'task-list-widget',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const WIDGET_SOURCE_PATTERN = /src[\\/]widgets[\\/].+\.(tsx?|css|html|svg)$/
|
|
24
|
+
const WIDGET_FILE_EXTENSIONS = /\.(tsx?|css|html|svg)$/
|
|
25
|
+
const WIDGET_SOURCE_DIR = 'src/widgets'
|
|
26
|
+
|
|
27
|
+
function getWidgetSourceFiles(rootDir: string): string[] {
|
|
28
|
+
const widgetsDir = join(rootDir, WIDGET_SOURCE_DIR)
|
|
29
|
+
if (!existsSync(widgetsDir)) {
|
|
30
|
+
return []
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const files: string[] = []
|
|
34
|
+
const entries = readdirSync(widgetsDir, { withFileTypes: true, recursive: true })
|
|
35
|
+
|
|
36
|
+
for (const entry of entries) {
|
|
37
|
+
if (entry.isFile() && WIDGET_FILE_EXTENSIONS.test(entry.name)) {
|
|
38
|
+
const parentPath = entry.parentPath ?? entry.path
|
|
39
|
+
files.push(join(parentPath, entry.name))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return files
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function inlineWidgetsVitePlugin(): Plugin {
|
|
47
|
+
let cachedResult: InlineWidgetBuildResult | undefined
|
|
48
|
+
let isWatchMode = false
|
|
49
|
+
let projectRoot: string
|
|
50
|
+
const virtualModuleId = 'virtual:todoist-ai-widgets'
|
|
51
|
+
const resolvedVirtualModuleId = `\0${virtualModuleId}`
|
|
52
|
+
|
|
53
|
+
async function rebuildWidget(): Promise<void> {
|
|
54
|
+
const buildTimestamp = process.env.BUILD_TIMESTAMP ?? Date.now().toString()
|
|
55
|
+
cachedResult = await buildInlineWidget(TASK_LIST_WIDGET, { buildTimestamp })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function writePreviewHtml(): void {
|
|
59
|
+
if (!cachedResult) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const previewDir = resolve(projectRoot, 'dist', 'dev')
|
|
64
|
+
if (!existsSync(previewDir)) {
|
|
65
|
+
mkdirSync(previewDir, { recursive: true })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const previewPath = resolve(previewDir, `${TASK_LIST_WIDGET.outputName}.html`)
|
|
69
|
+
writeFileSync(previewPath, cachedResult.content, 'utf-8')
|
|
70
|
+
console.log(`[widgets] Preview written to ${previewPath}`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function addWidgetFilesToWatch(ctx: PluginContext): void {
|
|
74
|
+
const widgetFiles = getWidgetSourceFiles(projectRoot)
|
|
75
|
+
for (const file of widgetFiles) {
|
|
76
|
+
ctx.addWatchFile(file)
|
|
77
|
+
}
|
|
78
|
+
if (widgetFiles.length > 0) {
|
|
79
|
+
console.log(`[widgets] Watching ${widgetFiles.length} widget source files`)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
name: 'todoist-ai-inline-widgets',
|
|
85
|
+
enforce: 'pre' as const,
|
|
86
|
+
|
|
87
|
+
configResolved(config) {
|
|
88
|
+
projectRoot = config.root
|
|
89
|
+
isWatchMode = config.command === 'build' && Boolean(config.build.watch)
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
async buildStart() {
|
|
93
|
+
await rebuildWidget()
|
|
94
|
+
addWidgetFilesToWatch(this)
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
async watchChange(id) {
|
|
98
|
+
if (WIDGET_SOURCE_PATTERN.test(id)) {
|
|
99
|
+
console.log(`[widgets] Detected change in ${id}, rebuilding...`)
|
|
100
|
+
await rebuildWidget()
|
|
101
|
+
|
|
102
|
+
// Write preview HTML in watch mode
|
|
103
|
+
if (isWatchMode) {
|
|
104
|
+
writePreviewHtml()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
writeBundle() {
|
|
110
|
+
writePreviewHtml()
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
resolveId(id: string) {
|
|
114
|
+
if (id === virtualModuleId) {
|
|
115
|
+
return resolvedVirtualModuleId
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return null
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
load(id: string) {
|
|
122
|
+
if (id !== resolvedVirtualModuleId || !cachedResult) {
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const moduleSource = `
|
|
127
|
+
const taskListWidget = ${JSON.stringify(cachedResult)};
|
|
128
|
+
export { taskListWidget };
|
|
129
|
+
export default { taskListWidget };
|
|
130
|
+
`
|
|
131
|
+
return moduleSource
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
}
|