@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.
- package/README.md +6 -0
- package/dist/index.d.ts +272 -901
- 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-BhXFK7dP.js +3220 -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/add-comments.d.ts +9 -82
- package/dist/tools/add-comments.d.ts.map +1 -1
- package/dist/tools/add-projects.d.ts +11 -73
- package/dist/tools/add-projects.d.ts.map +1 -1
- package/dist/tools/add-sections.d.ts +2 -14
- package/dist/tools/add-sections.d.ts.map +1 -1
- package/dist/tools/add-tasks.d.ts +24 -76
- package/dist/tools/add-tasks.d.ts.map +1 -1
- package/dist/tools/complete-tasks.d.ts +3 -11
- package/dist/tools/complete-tasks.d.ts.map +1 -1
- package/dist/tools/delete-object.d.ts +15 -11
- package/dist/tools/delete-object.d.ts.map +1 -1
- package/dist/tools/fetch.d.ts.map +1 -1
- package/dist/tools/find-activity.d.ts +25 -31
- package/dist/tools/find-activity.d.ts.map +1 -1
- package/dist/tools/find-comments.d.ts +9 -74
- package/dist/tools/find-comments.d.ts.map +1 -1
- package/dist/tools/find-completed-tasks.d.ts +28 -53
- package/dist/tools/find-completed-tasks.d.ts.map +1 -1
- package/dist/tools/find-project-collaborators.d.ts +2 -18
- package/dist/tools/find-project-collaborators.d.ts.map +1 -1
- package/dist/tools/find-projects.d.ts +3 -21
- package/dist/tools/find-projects.d.ts.map +1 -1
- package/dist/tools/find-sections.d.ts +1 -7
- package/dist/tools/find-sections.d.ts.map +1 -1
- package/dist/tools/find-tasks-by-date.d.ts +34 -54
- package/dist/tools/find-tasks-by-date.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/tools/find-tasks.d.ts +31 -55
- package/dist/tools/find-tasks.d.ts.map +1 -1
- package/dist/tools/get-overview.d.ts +8 -15
- package/dist/tools/get-overview.d.ts.map +1 -1
- package/dist/tools/manage-assignments.d.ts +9 -27
- package/dist/tools/manage-assignments.d.ts.map +1 -1
- package/dist/tools/search.d.ts +1 -9
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/update-comments.d.ts +10 -85
- package/dist/tools/update-comments.d.ts.map +1 -1
- package/dist/tools/update-projects.d.ts +12 -80
- package/dist/tools/update-projects.d.ts.map +1 -1
- package/dist/tools/update-sections.d.ts +4 -16
- package/dist/tools/update-sections.d.ts.map +1 -1
- package/dist/tools/update-tasks.d.ts +25 -87
- package/dist/tools/update-tasks.d.ts.map +1 -1
- package/dist/tools/user-info.d.ts +6 -2
- package/dist/tools/user-info.d.ts.map +1 -1
- package/dist/utils/labels.d.ts +5 -2
- package/dist/utils/labels.d.ts.map +1 -1
- package/dist/utils/output-schemas.d.ts +20 -176
- package/dist/utils/output-schemas.d.ts.map +1 -1
- package/dist/utils/priorities.d.ts +6 -1
- package/dist/utils/priorities.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 +21 -11
- package/scripts/inline-widget-builder.ts +87 -0
- package/scripts/inline-widgets-vite-plugin.ts +134 -0
- package/scripts/validate-schemas.ts +66 -65
- 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
|
-
|
|
20
|
+
type ValidationIssue = {
|
|
21
21
|
toolName: string
|
|
22
22
|
parameterPath: string
|
|
23
23
|
issue: string
|
|
24
24
|
suggestion: string
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
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:
|
|
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 (
|
|
47
|
-
const innerSchema = schema.
|
|
48
|
-
if (innerSchema
|
|
49
|
-
const nullableInner = innerSchema.
|
|
50
|
-
if (nullableInner
|
|
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 (
|
|
64
|
-
const innerSchema = schema.
|
|
65
|
-
if (innerSchema
|
|
66
|
-
const optionalInner = innerSchema.
|
|
67
|
-
if (optionalInner
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
134
|
-
|
|
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.
|
|
178
|
-
|
|
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
|
}
|