@doist/todoist-ai 5.2.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +6 -0
  2. package/dist/index.d.ts +272 -901
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -2
  5. package/dist/main.js +1 -1
  6. package/dist/mcp-helpers.d.ts +7 -1
  7. package/dist/mcp-helpers.d.ts.map +1 -1
  8. package/dist/mcp-server-BhXFK7dP.js +3220 -0
  9. package/dist/mcp-server.d.ts.map +1 -1
  10. package/dist/todoist-tool.d.ts +6 -0
  11. package/dist/todoist-tool.d.ts.map +1 -1
  12. package/dist/tools/add-comments.d.ts +9 -82
  13. package/dist/tools/add-comments.d.ts.map +1 -1
  14. package/dist/tools/add-projects.d.ts +11 -73
  15. package/dist/tools/add-projects.d.ts.map +1 -1
  16. package/dist/tools/add-sections.d.ts +2 -14
  17. package/dist/tools/add-sections.d.ts.map +1 -1
  18. package/dist/tools/add-tasks.d.ts +24 -76
  19. package/dist/tools/add-tasks.d.ts.map +1 -1
  20. package/dist/tools/complete-tasks.d.ts +3 -11
  21. package/dist/tools/complete-tasks.d.ts.map +1 -1
  22. package/dist/tools/delete-object.d.ts +15 -11
  23. package/dist/tools/delete-object.d.ts.map +1 -1
  24. package/dist/tools/fetch.d.ts.map +1 -1
  25. package/dist/tools/find-activity.d.ts +25 -31
  26. package/dist/tools/find-activity.d.ts.map +1 -1
  27. package/dist/tools/find-comments.d.ts +9 -74
  28. package/dist/tools/find-comments.d.ts.map +1 -1
  29. package/dist/tools/find-completed-tasks.d.ts +28 -53
  30. package/dist/tools/find-completed-tasks.d.ts.map +1 -1
  31. package/dist/tools/find-project-collaborators.d.ts +2 -18
  32. package/dist/tools/find-project-collaborators.d.ts.map +1 -1
  33. package/dist/tools/find-projects.d.ts +3 -21
  34. package/dist/tools/find-projects.d.ts.map +1 -1
  35. package/dist/tools/find-sections.d.ts +1 -7
  36. package/dist/tools/find-sections.d.ts.map +1 -1
  37. package/dist/tools/find-tasks-by-date.d.ts +34 -54
  38. package/dist/tools/find-tasks-by-date.d.ts.map +1 -1
  39. package/dist/tools/find-tasks-by-date.resource.d.ts +28 -0
  40. package/dist/tools/find-tasks-by-date.resource.d.ts.map +1 -0
  41. package/dist/tools/find-tasks.d.ts +31 -55
  42. package/dist/tools/find-tasks.d.ts.map +1 -1
  43. package/dist/tools/get-overview.d.ts +8 -15
  44. package/dist/tools/get-overview.d.ts.map +1 -1
  45. package/dist/tools/manage-assignments.d.ts +9 -27
  46. package/dist/tools/manage-assignments.d.ts.map +1 -1
  47. package/dist/tools/search.d.ts +1 -9
  48. package/dist/tools/search.d.ts.map +1 -1
  49. package/dist/tools/update-comments.d.ts +10 -85
  50. package/dist/tools/update-comments.d.ts.map +1 -1
  51. package/dist/tools/update-projects.d.ts +12 -80
  52. package/dist/tools/update-projects.d.ts.map +1 -1
  53. package/dist/tools/update-sections.d.ts +4 -16
  54. package/dist/tools/update-sections.d.ts.map +1 -1
  55. package/dist/tools/update-tasks.d.ts +25 -87
  56. package/dist/tools/update-tasks.d.ts.map +1 -1
  57. package/dist/tools/user-info.d.ts +6 -2
  58. package/dist/tools/user-info.d.ts.map +1 -1
  59. package/dist/utils/labels.d.ts +5 -2
  60. package/dist/utils/labels.d.ts.map +1 -1
  61. package/dist/utils/output-schemas.d.ts +20 -176
  62. package/dist/utils/output-schemas.d.ts.map +1 -1
  63. package/dist/utils/priorities.d.ts +6 -1
  64. package/dist/utils/priorities.d.ts.map +1 -1
  65. package/dist/utils/widget-loader.d.ts +7 -0
  66. package/dist/utils/widget-loader.d.ts.map +1 -0
  67. package/package.json +21 -11
  68. package/scripts/inline-widget-builder.ts +87 -0
  69. package/scripts/inline-widgets-vite-plugin.ts +134 -0
  70. package/scripts/validate-schemas.ts +66 -65
  71. package/dist/mcp-server-D0ROki3I.js +0 -3171
@@ -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
+ }
@@ -17,37 +17,37 @@
17
17
 
18
18
  import { z } from 'zod'
19
19
 
20
- interface ValidationIssue {
20
+ type ValidationIssue = {
21
21
  toolName: string
22
22
  parameterPath: string
23
23
  issue: string
24
24
  suggestion: string
25
25
  }
26
26
 
27
- interface ValidationResult {
27
+ type ValidationResult = {
28
28
  success: boolean
29
29
  issues: ValidationIssue[]
30
30
  toolsChecked: number
31
31
  parametersChecked: number
32
32
  }
33
33
 
34
+ type AnyZodSchema = z.ZodTypeAny | { _zod: { def: unknown } }
35
+
34
36
  /**
35
37
  * Recursively walk a Zod schema and detect problematic patterns
36
38
  */
37
39
  function walkZodSchema(
38
- schema: z.ZodTypeAny,
40
+ schema: AnyZodSchema,
39
41
  path: string,
40
42
  issues: ValidationIssue[],
41
43
  toolName: string,
42
44
  ): void {
43
- const typeName = schema._def.typeName
44
-
45
45
  // Check for ZodOptional containing a ZodNullable ZodString
46
- if (typeName === 'ZodOptional') {
47
- const innerSchema = schema._def.innerType
48
- if (innerSchema._def.typeName === 'ZodNullable') {
49
- const nullableInner = innerSchema._def.innerType
50
- if (nullableInner._def.typeName === 'ZodString') {
46
+ if (schema instanceof z.ZodOptional) {
47
+ const innerSchema = schema.unwrap()
48
+ if (innerSchema instanceof z.ZodNullable) {
49
+ const nullableInner = innerSchema.unwrap()
50
+ if (nullableInner instanceof z.ZodString) {
51
51
  issues.push({
52
52
  toolName,
53
53
  parameterPath: path,
@@ -60,11 +60,11 @@ function walkZodSchema(
60
60
  }
61
61
 
62
62
  // Check for ZodNullable containing a ZodOptional ZodString
63
- if (typeName === 'ZodNullable') {
64
- const innerSchema = schema._def.innerType
65
- if (innerSchema._def.typeName === 'ZodOptional') {
66
- const optionalInner = innerSchema._def.innerType
67
- if (optionalInner._def.typeName === 'ZodString') {
63
+ if (schema instanceof z.ZodNullable) {
64
+ const innerSchema = schema.unwrap()
65
+ if (innerSchema instanceof z.ZodOptional) {
66
+ const optionalInner = innerSchema.unwrap()
67
+ if (optionalInner instanceof z.ZodString) {
68
68
  issues.push({
69
69
  toolName,
70
70
  parameterPath: path,
@@ -77,61 +77,60 @@ function walkZodSchema(
77
77
  }
78
78
 
79
79
  // Recursively check nested schemas
80
- switch (typeName) {
81
- case 'ZodObject': {
82
- const shape = schema._def.shape()
83
- for (const [key, value] of Object.entries(shape)) {
84
- const newPath = path ? `${path}.${key}` : key
85
- walkZodSchema(value as z.ZodTypeAny, newPath, issues, toolName)
86
- }
87
- break
88
- }
89
- case 'ZodArray':
90
- walkZodSchema(schema._def.type, `${path}[]`, issues, toolName)
91
- break
92
-
93
- case 'ZodOptional':
94
- case 'ZodNullable':
95
- case 'ZodDefault':
96
- walkZodSchema(schema._def.innerType, path, issues, toolName)
97
- break
98
-
99
- case 'ZodUnion':
100
- case 'ZodDiscriminatedUnion': {
101
- const options = schema._def.options || schema._def.discriminatedUnion
102
- if (Array.isArray(options)) {
103
- options.forEach((option: z.ZodTypeAny, index: number) => {
104
- walkZodSchema(option, `${path}[union:${index}]`, issues, toolName)
105
- })
106
- }
107
- break
80
+ if (schema instanceof z.ZodObject) {
81
+ const shape = schema.shape
82
+ for (const [key, value] of Object.entries(shape)) {
83
+ const newPath = path ? `${path}.${key}` : key
84
+ walkZodSchema(value as AnyZodSchema, newPath, issues, toolName)
108
85
  }
109
- case 'ZodIntersection':
110
- walkZodSchema(schema._def.left, `${path}[left]`, issues, toolName)
111
- walkZodSchema(schema._def.right, `${path}[right]`, issues, toolName)
112
- break
113
-
114
- case 'ZodRecord':
115
- if (schema._def.valueType) {
116
- walkZodSchema(schema._def.valueType, `${path}[value]`, issues, toolName)
117
- }
118
- break
119
-
120
- case 'ZodTuple':
121
- if (schema._def.items) {
122
- schema._def.items.forEach((item: z.ZodTypeAny, index: number) => {
123
- walkZodSchema(item, `${path}[${index}]`, issues, toolName)
124
- })
125
- }
126
- break
86
+ } else if (schema instanceof z.ZodArray) {
87
+ const element = (schema as unknown as { _zod: { def: { element: AnyZodSchema } } })._zod.def
88
+ .element
89
+ walkZodSchema(element, `${path}[]`, issues, toolName)
90
+ } else if (
91
+ schema instanceof z.ZodOptional ||
92
+ schema instanceof z.ZodNullable ||
93
+ schema instanceof z.ZodDefault
94
+ ) {
95
+ walkZodSchema(schema.unwrap() as AnyZodSchema, path, issues, toolName)
96
+ } else if (schema instanceof z.ZodUnion) {
97
+ const options = (schema as unknown as { _zod: { def: { options: AnyZodSchema[] } } })._zod
98
+ .def.options
99
+ options.forEach((option: AnyZodSchema, index: number) => {
100
+ walkZodSchema(option, `${path}[union:${index}]`, issues, toolName)
101
+ })
102
+ } else if (schema instanceof z.ZodDiscriminatedUnion) {
103
+ const options = (schema as unknown as { _zod: { def: { options: AnyZodSchema[] } } })._zod
104
+ .def.options
105
+ options.forEach((option: AnyZodSchema, index: number) => {
106
+ walkZodSchema(option, `${path}[union:${index}]`, issues, toolName)
107
+ })
108
+ } else if (schema instanceof z.ZodIntersection) {
109
+ const left = (schema as unknown as { _zod: { def: { left: AnyZodSchema } } })._zod.def.left
110
+ const right = (schema as unknown as { _zod: { def: { right: AnyZodSchema } } })._zod.def
111
+ .right
112
+ walkZodSchema(left, `${path}[left]`, issues, toolName)
113
+ walkZodSchema(right, `${path}[right]`, issues, toolName)
114
+ } else if (schema instanceof z.ZodRecord) {
115
+ const valueType = (schema as unknown as { _zod: { def: { valueType: AnyZodSchema } } })._zod
116
+ .def.valueType
117
+ walkZodSchema(valueType, `${path}[value]`, issues, toolName)
118
+ } else if (schema instanceof z.ZodTuple) {
119
+ const items = (schema as unknown as { _zod: { def: { items: AnyZodSchema[] } } })._zod.def
120
+ .items
121
+ items.forEach((item: AnyZodSchema, index: number) => {
122
+ walkZodSchema(item, `${path}[${index}]`, issues, toolName)
123
+ })
127
124
  }
128
125
  }
129
126
 
130
127
  /**
131
128
  * Validate a single tool's parameter schema
132
129
  */
133
- // biome-ignore lint/suspicious/noExplicitAny: this is a tooling script
134
- function validateToolSchema(tool: any): ValidationIssue[] {
130
+ function validateToolSchema(tool: {
131
+ name?: string
132
+ parameters?: Record<string, z.ZodTypeAny>
133
+ }): ValidationIssue[] {
135
134
  const issues: ValidationIssue[] = []
136
135
  const toolName = tool.name || 'unknown'
137
136
 
@@ -174,8 +173,10 @@ async function validateAllSchemas(verbose: boolean = false): Promise<ValidationR
174
173
  if (tool.parameters) {
175
174
  try {
176
175
  const schema = z.object(tool.parameters)
177
- const shape = schema._def.shape()
178
- totalParameters += Object.keys(shape).length
176
+ const shape = schema.shape
177
+ if (shape) {
178
+ totalParameters += Object.keys(shape).length
179
+ }
179
180
  } catch {
180
181
  // Skip counting if schema is invalid
181
182
  }