@doist/todoist-ai 4.15.0 → 4.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -605,7 +605,6 @@ declare const tools: {
605
605
  projects: import("zod").ZodArray<import("zod").ZodObject<{
606
606
  id: import("zod").ZodString;
607
607
  name: import("zod").ZodOptional<import("zod").ZodString>;
608
- parentId: import("zod").ZodOptional<import("zod").ZodString>;
609
608
  isFavorite: import("zod").ZodOptional<import("zod").ZodBoolean>;
610
609
  viewStyle: import("zod").ZodOptional<import("zod").ZodEnum<["list", "board", "calendar"]>>;
611
610
  }, "strip", import("zod").ZodTypeAny, {
@@ -613,13 +612,11 @@ declare const tools: {
613
612
  name?: string | undefined;
614
613
  isFavorite?: boolean | undefined;
615
614
  viewStyle?: "list" | "board" | "calendar" | undefined;
616
- parentId?: string | undefined;
617
615
  }, {
618
616
  id: string;
619
617
  name?: string | undefined;
620
618
  isFavorite?: boolean | undefined;
621
619
  viewStyle?: "list" | "board" | "calendar" | undefined;
622
- parentId?: string | undefined;
623
620
  }>, "many">;
624
621
  };
625
622
  execute(args: {
@@ -628,7 +625,6 @@ declare const tools: {
628
625
  name?: string | undefined;
629
626
  isFavorite?: boolean | undefined;
630
627
  viewStyle?: "list" | "board" | "calendar" | undefined;
631
- parentId?: string | undefined;
632
628
  }[];
633
629
  }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
634
630
  content: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAEpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uCAAuC,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE/C,QAAA,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAqEqnX,CAAC;gCAA6C,CAAC;gCAA6C,CAAC;+BAA4C,CAAC;oCAAiD,CAAC;mCAAgD,CAAC;6BAA2D,CAAC;kCAA+C,CAAC;mCAAgD,CAAC;2BAAwC,CAAC;6BAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAA9d,CAAC;gCAA6C,CAAC;gCAA6C,CAAC;+BAA4C,CAAC;oCAAiD,CAAC;mCAAgD,CAAC;6BAA2D,CAAC;kCAA+C,CAAC;mCAAgD,CAAC;2BAAwC,CAAC;6BAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAA9d,CAAC;gCAA6C,CAAC;gCAA6C,CAAC;+BAA4C,CAAC;oCAAiD,CAAC;mCAAgD,CAAC;6BAA2D,CAAC;kCAA+C,CAAC;mCAAgD,CAAC;2BAAwC,CAAC;6BAA0C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CArC7lY,CAAA;AAED,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAA;AAE9B,OAAO,EAEH,QAAQ,EACR,aAAa,EACb,WAAW,EACX,SAAS,EACT,eAAe,EACf,kBAAkB,EAElB,WAAW,EACX,cAAc,EACd,YAAY,EAEZ,WAAW,EACX,cAAc,EACd,YAAY,EAEZ,WAAW,EACX,cAAc,EACd,YAAY,EAEZ,YAAY,EAEZ,WAAW,EACX,YAAY,EACZ,QAAQ,EAER,wBAAwB,EACxB,iBAAiB,EAEjB,MAAM,EACN,KAAK,GACR,CAAA"}
@@ -104,24 +104,6 @@ describe(`${UPDATE_PROJECTS} tool`, () => {
104
104
  expect(textContent).toContain('Updated 1 project:');
105
105
  expect(textContent).toContain('Updated Favorite Project (id=project-123)');
106
106
  });
107
- it('should update project with parentId to move it to a sub-project', async () => {
108
- const mockApiResponse = createMockProject({
109
- id: 'project-child',
110
- name: 'Child Project',
111
- parentId: 'project-parent',
112
- });
113
- mockTodoistApi.updateProject.mockResolvedValue(mockApiResponse);
114
- const result = await updateProjects.execute({
115
- projects: [{ id: 'project-child', parentId: 'project-parent' }],
116
- }, mockTodoistApi);
117
- expect(mockTodoistApi.updateProject).toHaveBeenCalledWith('project-child', {
118
- parentId: 'project-parent',
119
- });
120
- const textContent = extractTextContent(result);
121
- expect(textContent).toMatchSnapshot();
122
- expect(textContent).toContain('Updated 1 project:');
123
- expect(textContent).toContain('Child Project (id=project-child)');
124
- });
125
107
  });
126
108
  describe('updating multiple projects', () => {
127
109
  it('should update multiple projects and return mapped results', async () => {
@@ -57,7 +57,7 @@ const findActivity = {
57
57
  // Add optional filters
58
58
  if (objectType)
59
59
  apiArgs.objectType = objectType;
60
- if (objectId)
60
+ if (objectId && objectId !== 'remove')
61
61
  apiArgs.objectId = objectId;
62
62
  if (eventType)
63
63
  apiArgs.eventType = eventType;
@@ -1 +1 @@
1
- {"version":3,"file":"find-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAsDvB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqL2B,CAAA;AA2K1C,OAAO,EAAE,SAAS,EAAE,CAAA"}
1
+ {"version":3,"file":"find-tasks.d.ts","sourceRoot":"","sources":["../../src/tools/find-tasks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2DvB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwL2B,CAAA;AA2K1C,OAAO,EAAE,SAAS,EAAE,CAAA"}
@@ -9,7 +9,10 @@ import { ToolNames } from '../utils/tool-names.js';
9
9
  const { FIND_COMPLETED_TASKS, ADD_TASKS } = ToolNames;
10
10
  const ArgsSchema = {
11
11
  searchText: z.string().optional().describe('The text to search for in tasks.'),
12
- projectId: z.string().optional().describe('Find tasks in this project.'),
12
+ projectId: z
13
+ .string()
14
+ .optional()
15
+ .describe('Find tasks in this project. Project ID should be an ID string, or the text "inbox", for inbox tasks.'),
13
16
  sectionId: z.string().optional().describe('Find tasks in this section.'),
14
17
  parentId: z.string().optional().describe('Find subtasks of this parent task.'),
15
18
  responsibleUser: z
@@ -60,8 +63,10 @@ const findTasks = {
60
63
  limit,
61
64
  cursor: cursor ?? null,
62
65
  };
63
- if (projectId)
64
- taskParams.projectId = projectId;
66
+ if (projectId) {
67
+ taskParams.projectId =
68
+ projectId === 'inbox' ? todoistUser.inboxProjectId : projectId;
69
+ }
65
70
  if (sectionId)
66
71
  taskParams.sectionId = sectionId;
67
72
  if (parentId)
@@ -6,7 +6,6 @@ declare const updateProjects: {
6
6
  projects: z.ZodArray<z.ZodObject<{
7
7
  id: z.ZodString;
8
8
  name: z.ZodOptional<z.ZodString>;
9
- parentId: z.ZodOptional<z.ZodString>;
10
9
  isFavorite: z.ZodOptional<z.ZodBoolean>;
11
10
  viewStyle: z.ZodOptional<z.ZodEnum<["list", "board", "calendar"]>>;
12
11
  }, "strip", z.ZodTypeAny, {
@@ -14,13 +13,11 @@ declare const updateProjects: {
14
13
  name?: string | undefined;
15
14
  isFavorite?: boolean | undefined;
16
15
  viewStyle?: "list" | "board" | "calendar" | undefined;
17
- parentId?: string | undefined;
18
16
  }, {
19
17
  id: string;
20
18
  name?: string | undefined;
21
19
  isFavorite?: boolean | undefined;
22
20
  viewStyle?: "list" | "board" | "calendar" | undefined;
23
- parentId?: string | undefined;
24
21
  }>, "many">;
25
22
  };
26
23
  execute(args: {
@@ -29,7 +26,6 @@ declare const updateProjects: {
29
26
  name?: string | undefined;
30
27
  isFavorite?: boolean | undefined;
31
28
  viewStyle?: "list" | "board" | "calendar" | undefined;
32
- parentId?: string | undefined;
33
29
  }[];
34
30
  }, client: import("@doist/todoist-api-typescript").TodoistApi): Promise<{
35
31
  content: {
@@ -1 +1 @@
1
- {"version":3,"file":"update-projects.d.ts","sourceRoot":"","sources":["../../src/tools/update-projects.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA2BvB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCsB,CAAA;AAuD1C,OAAO,EAAE,cAAc,EAAE,CAAA"}
1
+ {"version":3,"file":"update-projects.d.ts","sourceRoot":"","sources":["../../src/tools/update-projects.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAqBvB,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCsB,CAAA;AAuD1C,OAAO,EAAE,cAAc,EAAE,CAAA"}
@@ -6,10 +6,6 @@ const { FIND_PROJECTS, FIND_TASKS, GET_OVERVIEW } = ToolNames;
6
6
  const ProjectUpdateSchema = z.object({
7
7
  id: z.string().min(1).describe('The ID of the project to update.'),
8
8
  name: z.string().min(1).optional().describe('The new name of the project.'),
9
- parentId: z
10
- .string()
11
- .optional()
12
- .describe('The ID of the parent project. If provided, moves this project to be a sub-project.'),
13
9
  isFavorite: z.boolean().optional().describe('Whether the project is a favorite.'),
14
10
  viewStyle: z.enum(['list', 'board', 'calendar']).optional().describe('The project view style.'),
15
11
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doist/todoist-ai",
3
- "version": "4.15.0",
3
+ "version": "4.15.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -40,19 +40,20 @@
40
40
  "lint:write": "biome lint --write",
41
41
  "format:check": "biome format",
42
42
  "format:write": "biome format --write",
43
- "check": "biome check",
43
+ "lint:schemas": "npm run build && npx tsc scripts/validate-schemas.ts --outDir dist/scripts --moduleResolution node --module ESNext --target es2021 --esModuleInterop --skipLibCheck --declaration false && node dist/scripts/validate-schemas.js",
44
+ "check": "biome check && npm run lint:schemas",
44
45
  "check:fix": "biome check --fix --unsafe",
45
46
  "prepare": "husky"
46
47
  },
47
48
  "dependencies": {
48
49
  "@modelcontextprotocol/sdk": "^1.11.1",
49
50
  "date-fns": "^4.1.0",
50
- "@doist/todoist-api-typescript": "5.7.1",
51
+ "@doist/todoist-api-typescript": "5.9.0",
51
52
  "dotenv": "^17.0.0",
52
53
  "zod": "^3.25.7"
53
54
  },
54
55
  "devDependencies": {
55
- "@biomejs/biome": "2.2.6",
56
+ "@biomejs/biome": "2.3.2",
56
57
  "@types/express": "^5.0.2",
57
58
  "@types/jest": "30.0.0",
58
59
  "@types/morgan": "^1.9.9",
@@ -71,6 +72,15 @@
71
72
  "lint-staged": {
72
73
  "*": [
73
74
  "biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
75
+ ],
76
+ "src/tools/*.ts": [
77
+ "npm run lint:schemas"
78
+ ],
79
+ "src/index.ts": [
80
+ "npm run lint:schemas"
81
+ ],
82
+ "scripts/validate-schemas.ts": [
83
+ "npm run lint:schemas"
74
84
  ]
75
85
  }
76
86
  }
@@ -0,0 +1,280 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Schema Validation Script for Todoist AI MCP Server
5
+ *
6
+ * This script validates that all tool parameter schemas follow Gemini API compatibility rules.
7
+ * Specifically, it checks that no Zod string schemas use both .nullable() and .optional().
8
+ *
9
+ * This version imports the actual tools from the compiled index.js and validates their
10
+ * runtime Zod schemas for maximum accuracy.
11
+ *
12
+ * Usage:
13
+ * npm run build && node scripts/validate-schemas.js
14
+ * npm run build && node scripts/validate-schemas.js --verbose
15
+ * npm run build && node scripts/validate-schemas.js --json
16
+ */
17
+
18
+ import { z } from 'zod'
19
+
20
+ interface ValidationIssue {
21
+ toolName: string
22
+ parameterPath: string
23
+ issue: string
24
+ suggestion: string
25
+ }
26
+
27
+ interface ValidationResult {
28
+ success: boolean
29
+ issues: ValidationIssue[]
30
+ toolsChecked: number
31
+ parametersChecked: number
32
+ }
33
+
34
+ /**
35
+ * Recursively walk a Zod schema and detect problematic patterns
36
+ */
37
+ function walkZodSchema(
38
+ schema: z.ZodTypeAny,
39
+ path: string,
40
+ issues: ValidationIssue[],
41
+ toolName: string,
42
+ ): void {
43
+ const typeName = schema._def.typeName
44
+
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') {
51
+ issues.push({
52
+ toolName,
53
+ parameterPath: path,
54
+ issue: 'GEMINI_API_INCOMPATIBLE: z.string().nullable().optional() pattern detected',
55
+ suggestion:
56
+ 'REQUIRED FIX: Change "z.string().nullable().optional()" to "z.string().optional()" and use special strings like "remove" or "unassign" in description to handle clearing. This pattern causes HTTP 400 errors in Google Gemini API due to OpenAPI 3.1 nullable type incompatibility.',
57
+ })
58
+ }
59
+ }
60
+ }
61
+
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') {
68
+ issues.push({
69
+ toolName,
70
+ parameterPath: path,
71
+ issue: 'GEMINI_API_INCOMPATIBLE: z.string().optional().nullable() pattern detected',
72
+ suggestion:
73
+ 'REQUIRED FIX: Change "z.string().optional().nullable()" to "z.string().optional()" and use special strings like "remove" or "unassign" in description to handle clearing. This pattern causes HTTP 400 errors in Google Gemini API due to OpenAPI 3.1 nullable type incompatibility.',
74
+ })
75
+ }
76
+ }
77
+ }
78
+
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
108
+ }
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
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Validate a single tool's parameter schema
132
+ */
133
+ // biome-ignore lint/suspicious/noExplicitAny: this is a tooling script
134
+ function validateToolSchema(tool: any): ValidationIssue[] {
135
+ const issues: ValidationIssue[] = []
136
+ const toolName = tool.name || 'unknown'
137
+
138
+ if (!tool.parameters) {
139
+ return issues
140
+ }
141
+
142
+ try {
143
+ const schema = z.object(tool.parameters)
144
+ walkZodSchema(schema, '', issues, toolName)
145
+ } catch (error) {
146
+ issues.push({
147
+ toolName,
148
+ parameterPath: 'root',
149
+ issue: `Failed to analyze schema: ${error}`,
150
+ suggestion: 'Check that the tool parameters are valid Zod schemas',
151
+ })
152
+ }
153
+
154
+ return issues
155
+ }
156
+
157
+ /**
158
+ * Main validation function using runtime schema analysis
159
+ */
160
+ async function validateAllSchemas(verbose: boolean = false): Promise<ValidationResult> {
161
+ try {
162
+ const { tools } = await import(`${process.cwd()}/dist/index.js`)
163
+
164
+ const allIssues: ValidationIssue[] = []
165
+ let totalParameters = 0
166
+ const toolNames = Object.keys(tools)
167
+
168
+ for (const toolName of toolNames) {
169
+ const tool = tools[toolName]
170
+ const toolIssues = validateToolSchema(tool)
171
+ allIssues.push(...toolIssues)
172
+
173
+ // Count parameters for stats
174
+ if (tool.parameters) {
175
+ try {
176
+ const schema = z.object(tool.parameters)
177
+ const shape = schema._def.shape()
178
+ totalParameters += Object.keys(shape).length
179
+ } catch {
180
+ // Skip counting if schema is invalid
181
+ }
182
+ }
183
+
184
+ if (verbose) {
185
+ const issueCount = toolIssues.length
186
+ const status = issueCount === 0 ? '✅' : `❌ (${issueCount} issues)`
187
+ const paramCount = tool.parameters ? Object.keys(tool.parameters).length : 0
188
+ console.log(`${status} ${toolName} (${paramCount} parameters)`)
189
+
190
+ if (issueCount > 0) {
191
+ toolIssues.forEach((issue) => {
192
+ console.log(` ${issue.parameterPath}: ${issue.issue}`)
193
+ })
194
+ }
195
+ }
196
+ }
197
+
198
+ return {
199
+ success: allIssues.length === 0,
200
+ issues: allIssues,
201
+ toolsChecked: toolNames.length,
202
+ parametersChecked: totalParameters,
203
+ }
204
+ } catch (error) {
205
+ return {
206
+ success: false,
207
+ issues: [
208
+ {
209
+ toolName: 'system',
210
+ parameterPath: 'import',
211
+ issue: `Failed to import tools: ${error}`,
212
+ suggestion: 'Ensure the project is built and dist/index.js exists',
213
+ },
214
+ ],
215
+ toolsChecked: 0,
216
+ parametersChecked: 0,
217
+ }
218
+ }
219
+ }
220
+
221
+ /**
222
+ * CLI interface
223
+ */
224
+ async function main() {
225
+ const args = process.argv.slice(2)
226
+ const verbose = args.includes('--verbose')
227
+ const jsonOutput = args.includes('--json')
228
+
229
+ try {
230
+ const result = await validateAllSchemas(verbose)
231
+
232
+ if (jsonOutput) {
233
+ console.log(JSON.stringify(result, null, 2))
234
+ } else {
235
+ if (result.success) {
236
+ console.log('✅ Schema validation passed!')
237
+ console.log(
238
+ ` Checked ${result.toolsChecked} tools with ${result.parametersChecked} parameters`,
239
+ )
240
+ console.log(
241
+ ' All schemas are Gemini API compatible (no .nullable() on optional strings)',
242
+ )
243
+ } else {
244
+ console.log('❌ Schema validation failed!')
245
+ console.log(
246
+ ` Found ${result.issues.length} issue(s) in ${result.toolsChecked} tools:\n`,
247
+ )
248
+
249
+ result.issues.forEach((issue, index) => {
250
+ console.log(`\n${index + 1}. 🚫 VALIDATION FAILURE`)
251
+ console.log(` Tool: ${issue.toolName}`)
252
+ console.log(` Parameter: ${issue.parameterPath}`)
253
+ console.log(` Issue: ${issue.issue}`)
254
+ console.log(` Action Required: ${issue.suggestion}`)
255
+ console.log(` File Location: src/tools/${issue.toolName}.ts`)
256
+ console.log(` Fix Pattern: Remove .nullable() from the parameter schema`)
257
+ console.log(
258
+ ` Example Fix: Change z.string().nullable().optional() → z.string().optional()`,
259
+ )
260
+ console.log(
261
+ ` ⚠️ This validation failure will cause Gemini API HTTP 400 errors\n`,
262
+ )
263
+ })
264
+ }
265
+ }
266
+
267
+ process.exit(result.success ? 0 : 1)
268
+ } catch (error) {
269
+ console.error('Fatal error during schema validation:', error)
270
+ process.exit(1)
271
+ }
272
+ }
273
+
274
+ // Run if this script is executed directly
275
+ if (process.argv[1]?.endsWith('validate-schemas.js')) {
276
+ main()
277
+ }
278
+
279
+ export type { ValidationResult, ValidationIssue }
280
+ export { validateAllSchemas }