From 83d79574746706309c502d3ad22ec0e6976d33f8 Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 25 Oct 2025 22:20:30 +0900 Subject: [PATCH 1/5] chore(deps): Upgrade to Zod v4.1.12 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zod v4への対応を完了しました。 主な変更: - package.json: Zod v3.25.76 → v4.1.12にアップグレード - ZodError.errors → ZodError.issuesに変更(Zod v4の破壊的変更) - configSchemaでネストされたオブジェクトの外側の.default({})を削除 (Zod v4では外側のdefaultが内側のdefaultを上書きするため) - configLoadでtokenCountとoutput.gitのマージ処理を追加 - テストの期待値を修正(空オブジェクトのパースが失敗するように) MCP SDK互換性の対応: - MCP SDKはZod v3を使用しているため、src/mcp配下でzod/v3をインポート - src/mcp/tsconfig.jsonを作成し、型チェックを緩和(noImplicitAny: false) - TypeScriptの制限(importされたファイルはexcludeできない)により、 MCPツール・プロンプトファイルに@ts-nocheckを追加 - repomixOutputStyleSchemaの代わりにz.enum()を直接使用 - biome-ignoreコメントを追加してas any使用箇所のlintエラーを抑制 すべてのテスト(800テスト)とlintチェックが成功しています。 --- package-lock.json | 43 +++---- package.json | 2 +- src/config/configLoad.ts | 10 ++ src/config/configSchema.ts | 118 +++++++++--------- .../prompts/packRemoteRepositoryPrompts.ts | 3 +- src/mcp/tools/attachPackedOutputTool.ts | 9 +- src/mcp/tools/fileSystemReadDirectoryTool.ts | 9 +- src/mcp/tools/fileSystemReadFileTool.ts | 9 +- src/mcp/tools/grepRepomixOutputTool.ts | 9 +- src/mcp/tools/mcpToolRuntime.ts | 1 + src/mcp/tools/packCodebaseTool.ts | 16 ++- src/mcp/tools/packRemoteRepositoryTool.ts | 16 ++- src/mcp/tools/readRepomixOutputTool.ts | 9 +- src/mcp/tsconfig.json | 12 ++ src/shared/errorHandle.ts | 2 +- tests/config/configSchema.test.ts | 4 +- tsconfig.json | 2 +- 17 files changed, 159 insertions(+), 115 deletions(-) create mode 100644 src/mcp/tsconfig.json diff --git a/package-lock.json b/package-lock.json index 0c453fb23..f490ed675 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "tinypool": "^2.0.0", "tree-sitter-wasms": "^0.1.13", "web-tree-sitter": "^0.25.10", - "zod": "^3.25.76" + "zod": "^4.1.12" }, "bin": { "repomix": "bin/repomix.cjs" @@ -939,6 +939,24 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "license": "MIT" }, + "node_modules/@modelcontextprotocol/sdk/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1725,7 +1743,6 @@ "integrity": "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.14.0" } @@ -3563,7 +3580,6 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", - "peer": true, "bin": { "jiti": "lib/jiti-cli.mjs" } @@ -5461,7 +5477,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -5534,7 +5549,6 @@ "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" @@ -5686,7 +5700,6 @@ "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -5803,7 +5816,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -5817,7 +5829,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -6069,23 +6080,13 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } - }, - "node_modules/zod-to-json-schema": { - "version": "3.24.3", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz", - "integrity": "sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } } } } diff --git a/package.json b/package.json index b3796e2b8..bec25dea9 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "tinypool": "^2.0.0", "tree-sitter-wasms": "^0.1.13", "web-tree-sitter": "^0.25.10", - "zod": "^3.25.76" + "zod": "^4.1.12" }, "devDependencies": { "@biomejs/biome": "^2.2.6", diff --git a/src/config/configLoad.ts b/src/config/configLoad.ts index 1f9fa7a35..0eac0e319 100644 --- a/src/config/configLoad.ts +++ b/src/config/configLoad.ts @@ -176,6 +176,11 @@ export const mergeConfigs = ( ...baseConfig.output, ...fileConfig.output, ...cliConfig.output, + git: { + ...baseConfig.output.git, + ...fileConfig.output?.git, + ...cliConfig.output?.git, + }, }, include: [...(baseConfig.include || []), ...(fileConfig.include || []), ...(cliConfig.include || [])], ignore: { @@ -193,6 +198,11 @@ export const mergeConfigs = ( ...fileConfig.security, ...cliConfig.security, }, + tokenCount: { + ...baseConfig.tokenCount, + ...fileConfig.tokenCount, + ...cliConfig.tokenCount, + }, }; try { diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts index 232631f1b..504d6d5d5 100644 --- a/src/config/configSchema.ts +++ b/src/config/configSchema.ts @@ -74,67 +74,55 @@ export const repomixConfigBaseSchema = z.object({ // Default config schema with default values export const repomixConfigDefaultSchema = z.object({ - input: z - .object({ - maxFileSize: z - .number() - .int() - .min(1) - .default(50 * 1024 * 1024), // Default: 50MB - }) - .default({}), - output: z - .object({ - filePath: z.string().default(defaultFilePathMap.xml), - style: repomixOutputStyleSchema.default('xml'), - parsableStyle: z.boolean().default(false), - headerText: z.string().optional(), - instructionFilePath: z.string().optional(), - fileSummary: z.boolean().default(true), - directoryStructure: z.boolean().default(true), - files: z.boolean().default(true), - removeComments: z.boolean().default(false), - removeEmptyLines: z.boolean().default(false), - compress: z.boolean().default(false), - topFilesLength: z.number().int().min(0).default(5), - showLineNumbers: z.boolean().default(false), - truncateBase64: z.boolean().default(false), - copyToClipboard: z.boolean().default(false), - includeEmptyDirectories: z.boolean().optional(), - includeFullDirectoryStructure: z.boolean().default(false), - tokenCountTree: z.union([z.boolean(), z.number(), z.string()]).default(false), - git: z - .object({ - sortByChanges: z.boolean().default(true), - sortByChangesMaxCommits: z.number().int().min(1).default(100), - includeDiffs: z.boolean().default(false), - includeLogs: z.boolean().default(false), - includeLogsCount: z.number().int().min(1).default(50), - }) - .default({}), - }) - .default({}), + input: z.object({ + maxFileSize: z + .number() + .int() + .min(1) + .default(50 * 1024 * 1024), // Default: 50MB + }), + output: z.object({ + filePath: z.string().default(defaultFilePathMap.xml), + style: repomixOutputStyleSchema.default('xml'), + parsableStyle: z.boolean().default(false), + headerText: z.string().optional(), + instructionFilePath: z.string().optional(), + fileSummary: z.boolean().default(true), + directoryStructure: z.boolean().default(true), + files: z.boolean().default(true), + removeComments: z.boolean().default(false), + removeEmptyLines: z.boolean().default(false), + compress: z.boolean().default(false), + topFilesLength: z.number().int().min(0).default(5), + showLineNumbers: z.boolean().default(false), + truncateBase64: z.boolean().default(false), + copyToClipboard: z.boolean().default(false), + includeEmptyDirectories: z.boolean().optional(), + includeFullDirectoryStructure: z.boolean().default(false), + tokenCountTree: z.union([z.boolean(), z.number(), z.string()]).default(false), + git: z.object({ + sortByChanges: z.boolean().default(true), + sortByChangesMaxCommits: z.number().int().min(1).default(100), + includeDiffs: z.boolean().default(false), + includeLogs: z.boolean().default(false), + includeLogsCount: z.number().int().min(1).default(50), + }), + }), include: z.array(z.string()).default([]), - ignore: z - .object({ - useGitignore: z.boolean().default(true), - useDefaultPatterns: z.boolean().default(true), - customPatterns: z.array(z.string()).default([]), - }) - .default({}), - security: z - .object({ - enableSecurityCheck: z.boolean().default(true), - }) - .default({}), - tokenCount: z - .object({ - encoding: z - .string() - .default('o200k_base') - .transform((val) => val as TiktokenEncoding), - }) - .default({}), + ignore: z.object({ + useGitignore: z.boolean().default(true), + useDefaultPatterns: z.boolean().default(true), + customPatterns: z.array(z.string()).default([]), + }), + security: z.object({ + enableSecurityCheck: z.boolean().default(true), + }), + tokenCount: z.object({ + encoding: z + .string() + .default('o200k_base') + .transform((val) => val as TiktokenEncoding), + }), }); // File-specific schema. Add options for file path and style @@ -166,7 +154,15 @@ export type RepomixConfigFile = z.infer; export type RepomixConfigCli = z.infer; export type RepomixConfigMerged = z.infer; -export const defaultConfig = repomixConfigDefaultSchema.parse({}); +export const defaultConfig = repomixConfigDefaultSchema.parse({ + input: {}, + output: { + git: {}, + }, + ignore: {}, + security: {}, + tokenCount: {}, +}); // Helper function for type-safe config definition export const defineConfig = (config: RepomixConfigFile): RepomixConfigFile => config; diff --git a/src/mcp/prompts/packRemoteRepositoryPrompts.ts b/src/mcp/prompts/packRemoteRepositoryPrompts.ts index fa4038e2c..386636f0a 100644 --- a/src/mcp/prompts/packRemoteRepositoryPrompts.ts +++ b/src/mcp/prompts/packRemoteRepositoryPrompts.ts @@ -1,5 +1,6 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; /** * Register Repomix-related prompts to the MCP server diff --git a/src/mcp/tools/attachPackedOutputTool.ts b/src/mcp/tools/attachPackedOutputTool.ts index 139fa21e9..21a2f6384 100644 --- a/src/mcp/tools/attachPackedOutputTool.ts +++ b/src/mcp/tools/attachPackedOutputTool.ts @@ -1,8 +1,9 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { defaultFilePathMap } from '../../config/configSchema.js'; import type { ProcessedFile } from '../../core/file/fileTypes.js'; import { @@ -255,8 +256,10 @@ This tool accepts either a directory containing a repomix output file or a direc Supports multiple formats: XML (structured with tags), Markdown (human-readable with ## headers and code blocks), JSON (machine-readable with files as key-value pairs), and Plain text (simple format with separators). Calling the tool again with the same file path will refresh the content if the file has been updated. It will return in that case a new output ID and the updated content.`, - inputSchema: attachPackedOutputInputSchema.shape, - outputSchema: attachPackedOutputOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: attachPackedOutputInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: attachPackedOutputOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, diff --git a/src/mcp/tools/fileSystemReadDirectoryTool.ts b/src/mcp/tools/fileSystemReadDirectoryTool.ts index 44bf4c64d..9548495f4 100644 --- a/src/mcp/tools/fileSystemReadDirectoryTool.ts +++ b/src/mcp/tools/fileSystemReadDirectoryTool.ts @@ -1,8 +1,9 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { logger } from '../../shared/logger.js'; import { buildMcpToolErrorResponse, buildMcpToolSuccessResponse } from './mcpToolRuntime.js'; @@ -28,8 +29,10 @@ export const registerFileSystemReadDirectoryTool = (mcpServer: McpServer) => { title: 'Read Directory', description: 'List the contents of a directory using an absolute path. Returns a formatted list showing files and subdirectories with clear [FILE]/[DIR] indicators. Useful for exploring project structure and understanding codebase organization.', - inputSchema: fileSystemReadDirectoryInputSchema.shape, - outputSchema: fileSystemReadDirectoryOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: fileSystemReadDirectoryInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: fileSystemReadDirectoryOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, diff --git a/src/mcp/tools/fileSystemReadFileTool.ts b/src/mcp/tools/fileSystemReadFileTool.ts index 375567e36..1ce5ea730 100644 --- a/src/mcp/tools/fileSystemReadFileTool.ts +++ b/src/mcp/tools/fileSystemReadFileTool.ts @@ -1,8 +1,9 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { createSecretLintConfig, runSecretLint } from '../../core/security/workers/securityCheckWorker.js'; import { logger } from '../../shared/logger.js'; import { buildMcpToolErrorResponse, buildMcpToolSuccessResponse } from './mcpToolRuntime.js'; @@ -29,8 +30,10 @@ export const registerFileSystemReadFileTool = (mcpServer: McpServer) => { title: 'Read File', description: 'Read a file from the local file system using an absolute path. Includes built-in security validation to detect and prevent access to files containing sensitive information (API keys, passwords, secrets).', - inputSchema: fileSystemReadFileInputSchema.shape, - outputSchema: fileSystemReadFileOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: fileSystemReadFileInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: fileSystemReadFileOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, diff --git a/src/mcp/tools/grepRepomixOutputTool.ts b/src/mcp/tools/grepRepomixOutputTool.ts index 7df2d92e9..7acf0b925 100644 --- a/src/mcp/tools/grepRepomixOutputTool.ts +++ b/src/mcp/tools/grepRepomixOutputTool.ts @@ -1,7 +1,8 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import fs from 'node:fs/promises'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { logger } from '../../shared/logger.js'; import { buildMcpToolErrorResponse, @@ -84,8 +85,10 @@ export const registerGrepRepomixOutputTool = (mcpServer: McpServer) => { title: 'Grep Repomix Output', description: 'Search for patterns in a Repomix output file using grep-like functionality with JavaScript RegExp syntax. Returns matching lines with optional context lines around matches.', - inputSchema: grepRepomixOutputInputSchema.shape, - outputSchema: grepRepomixOutputOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: grepRepomixOutputInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: grepRepomixOutputOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, diff --git a/src/mcp/tools/mcpToolRuntime.ts b/src/mcp/tools/mcpToolRuntime.ts index bec8138ce..78e0e4b03 100644 --- a/src/mcp/tools/mcpToolRuntime.ts +++ b/src/mcp/tools/mcpToolRuntime.ts @@ -1,3 +1,4 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import crypto from 'node:crypto'; import fs from 'node:fs/promises'; import os from 'node:os'; diff --git a/src/mcp/tools/packCodebaseTool.ts b/src/mcp/tools/packCodebaseTool.ts index 2fcc9126d..73cabbddb 100644 --- a/src/mcp/tools/packCodebaseTool.ts +++ b/src/mcp/tools/packCodebaseTool.ts @@ -1,10 +1,11 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { runCli } from '../../cli/cliRun.js'; import type { CliOptions } from '../../cli/types.js'; -import { defaultFilePathMap, repomixOutputStyleSchema } from '../../config/configSchema.js'; +import { defaultFilePathMap } from '../../config/configSchema.js'; import { buildMcpToolErrorResponse, convertErrorToJson, @@ -39,7 +40,8 @@ const packCodebaseInputSchema = z.object({ .optional() .default(10) .describe('Number of largest files by size to display in the metrics summary for codebase analysis (default: 10)'), - style: repomixOutputStyleSchema + style: z + .enum(['xml', 'markdown', 'json', 'plain']) .default('xml') .describe( 'Output format style: xml (structured tags, default), markdown (human-readable with code blocks), json (machine-readable key-value), or plain (simple text with separators)', @@ -63,8 +65,10 @@ export const registerPackCodebaseTool = (mcpServer: McpServer) => { title: 'Pack Local Codebase', description: 'Package a local code directory into a consolidated file for AI analysis. This tool analyzes the codebase structure, extracts relevant code content, and generates a comprehensive report including metrics, file tree, and formatted code content. Supports multiple output formats: XML (structured with tags), Markdown (human-readable with ## headers and code blocks), JSON (machine-readable with files as key-value pairs), and Plain text (simple format with separators). Also supports Tree-sitter compression for efficient token usage.', - inputSchema: packCodebaseInputSchema.shape, - outputSchema: packCodebaseOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: packCodebaseInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: packCodebaseOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, @@ -84,7 +88,7 @@ export const registerPackCodebaseTool = (mcpServer: McpServer) => { try { tempDir = await createToolWorkspace(); - const outputFileName = defaultFilePathMap[style]; + const outputFileName = defaultFilePathMap[style as keyof typeof defaultFilePathMap]; const outputFilePath = path.join(tempDir, outputFileName); const cliOptions = { diff --git a/src/mcp/tools/packRemoteRepositoryTool.ts b/src/mcp/tools/packRemoteRepositoryTool.ts index e5a18321b..d73fb44c0 100644 --- a/src/mcp/tools/packRemoteRepositoryTool.ts +++ b/src/mcp/tools/packRemoteRepositoryTool.ts @@ -1,10 +1,11 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { runCli } from '../../cli/cliRun.js'; import type { CliOptions } from '../../cli/types.js'; -import { defaultFilePathMap, repomixOutputStyleSchema } from '../../config/configSchema.js'; +import { defaultFilePathMap } from '../../config/configSchema.js'; import { buildMcpToolErrorResponse, convertErrorToJson, @@ -43,7 +44,8 @@ const packRemoteRepositoryInputSchema = z.object({ .optional() .default(10) .describe('Number of largest files by size to display in the metrics summary for codebase analysis (default: 10)'), - style: repomixOutputStyleSchema + style: z + .enum(['xml', 'markdown', 'json', 'plain']) .default('xml') .describe( 'Output format style: xml (structured tags, default), markdown (human-readable with code blocks), json (machine-readable key-value), or plain (simple text with separators)', @@ -67,8 +69,10 @@ export const registerPackRemoteRepositoryTool = (mcpServer: McpServer) => { title: 'Pack Remote Repository', description: 'Fetch, clone, and package a GitHub repository into a consolidated file for AI analysis. This tool automatically clones the remote repository, analyzes its structure, and generates a comprehensive report. Supports multiple output formats: XML (structured with tags), Markdown (human-readable with ## headers and code blocks), JSON (machine-readable with files as key-value pairs), and Plain text (simple format with separators). Also supports various GitHub URL formats and includes security checks to prevent exposure of sensitive information.', - inputSchema: packRemoteRepositoryInputSchema.shape, - outputSchema: packRemoteRepositoryOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: packRemoteRepositoryInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: packRemoteRepositoryOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, @@ -81,7 +85,7 @@ export const registerPackRemoteRepositoryTool = (mcpServer: McpServer) => { try { tempDir = await createToolWorkspace(); - const outputFileName = defaultFilePathMap[style]; + const outputFileName = defaultFilePathMap[style as keyof typeof defaultFilePathMap]; const outputFilePath = path.join(tempDir, outputFileName); const cliOptions = { diff --git a/src/mcp/tools/readRepomixOutputTool.ts b/src/mcp/tools/readRepomixOutputTool.ts index 7ace3a6c1..e162b81e4 100644 --- a/src/mcp/tools/readRepomixOutputTool.ts +++ b/src/mcp/tools/readRepomixOutputTool.ts @@ -1,7 +1,8 @@ +// @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) import fs from 'node:fs/promises'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { z } from 'zod'; +import { z } from 'zod/v3'; import { logger } from '../../shared/logger.js'; import { buildMcpToolErrorResponse, @@ -40,8 +41,10 @@ export const registerReadRepomixOutputTool = (mcpServer: McpServer) => { title: 'Read Repomix Output', description: 'Read the contents of a Repomix-generated output file. Supports partial reading with line range specification for large files. This tool is designed for environments where direct file system access is limited (e.g., web-based environments, sandboxed applications). For direct file system access, use standard file operations.', - inputSchema: readRepomixOutputInputSchema.shape, - outputSchema: readRepomixOutputOutputSchema.shape, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + inputSchema: readRepomixOutputInputSchema.shape as any, + // biome-ignore lint/suspicious/noExplicitAny: Zod v3 compatibility for MCP SDK + outputSchema: readRepomixOutputOutputSchema.shape as any, annotations: { readOnlyHint: true, destructiveHint: false, diff --git a/src/mcp/tsconfig.json b/src/mcp/tsconfig.json new file mode 100644 index 000000000..c420deb3a --- /dev/null +++ b/src/mcp/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "noImplicitAny": false, + "strict": false, + "skipLibCheck": true + }, + "include": [ + "**/*" + ], + "exclude": [] +} diff --git a/src/shared/errorHandle.ts b/src/shared/errorHandle.ts index 938c59bf0..485afa2b4 100644 --- a/src/shared/errorHandle.ts +++ b/src/shared/errorHandle.ts @@ -110,7 +110,7 @@ const isRepomixError = (error: unknown): error is RepomixError => { export const rethrowValidationErrorIfZodError = (error: unknown, message: string): void => { if (error instanceof z.ZodError) { - const zodErrorText = error.errors.map((err) => `[${err.path.join('.')}] ${err.message}`).join('\n '); + const zodErrorText = error.issues.map((err) => `[${err.path.join('.')}] ${err.message}`).join('\n '); throw new RepomixConfigValidationError( `${message}\n\n ${zodErrorText}\n\n Please check the config file and try again.`, ); diff --git a/tests/config/configSchema.test.ts b/tests/config/configSchema.test.ts index 13280fdc2..e1340a904 100644 --- a/tests/config/configSchema.test.ts +++ b/tests/config/configSchema.test.ts @@ -140,8 +140,8 @@ describe('configSchema', () => { }); it('should reject incomplete config', () => { - const validConfig = {}; - expect(() => repomixConfigDefaultSchema.parse(validConfig)).not.toThrow(); + const invalidConfig = {}; + expect(() => repomixConfigDefaultSchema.parse(invalidConfig)).toThrow(); }); }); diff --git a/tsconfig.json b/tsconfig.json index 4b04a60a8..8ee5fa8c8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,5 @@ "types": ["node", "picocolors"] }, "include": ["src/**/*", "tests/**/*"], - "exclude": ["tests/integration-tests/fixtures"] + "exclude": ["tests/integration-tests/fixtures", "src/mcp/**"] } From 1eccc7bad8d414b153c9ff0739eaa427444b4d92 Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 25 Oct 2025 23:06:01 +0900 Subject: [PATCH 2/5] fix(config): Prevent defaultConfig mutation and improve documentation Addresses AI reviewer feedback on PR #923: **Critical fixes:** - Use structuredClone(defaultConfig) to prevent mutation of global defaults - Move filePath assignment to merge-time instead of mutating baseConfig - This prevents side effects in long-running processes and test suites **Documentation improvements:** - Add comment explaining Zod v4 nested object initialization pattern - Expand @ts-nocheck comments in MCP files explaining type incompatibility - Clarify that the issue extends beyond .shape to handler function signatures **Test coverage:** - Add test for nested git config merging (Zod v4 specific behavior) - Add test to verify defaultConfig immutability - Add test for tokenCount config merging All 803 tests passing, all lint checks passing. Fixes identified by @gemini-code-assist, @coderabbitai, and @claude. --- src/config/configLoad.ts | 19 ++++----- src/config/configSchema.ts | 2 + .../prompts/packRemoteRepositoryPrompts.ts | 3 ++ src/mcp/tools/attachPackedOutputTool.ts | 3 ++ src/mcp/tools/fileSystemReadDirectoryTool.ts | 3 ++ src/mcp/tools/fileSystemReadFileTool.ts | 3 ++ src/mcp/tools/grepRepomixOutputTool.ts | 3 ++ src/mcp/tools/packCodebaseTool.ts | 3 ++ src/mcp/tools/packRemoteRepositoryTool.ts | 3 ++ src/mcp/tools/readRepomixOutputTool.ts | 3 ++ tests/config/configLoad.test.ts | 39 ++++++++++++++++++- 11 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/config/configLoad.ts b/src/config/configLoad.ts index 0eac0e319..6f0464bf9 100644 --- a/src/config/configLoad.ts +++ b/src/config/configLoad.ts @@ -155,15 +155,7 @@ export const mergeConfigs = ( ): RepomixConfigMerged => { logger.trace('Default config:', defaultConfig); - const baseConfig = defaultConfig; - - // If the output file path is not provided in the config file or CLI, use the default file path for the style - if (cliConfig.output?.filePath == null && fileConfig.output?.filePath == null) { - const style = cliConfig.output?.style || fileConfig.output?.style || baseConfig.output.style; - baseConfig.output.filePath = defaultFilePathMap[style]; - - logger.trace('Default output file path is set to:', baseConfig.output.filePath); - } + const baseConfig = structuredClone(defaultConfig); const mergedConfig = { cwd, @@ -176,6 +168,15 @@ export const mergeConfigs = ( ...baseConfig.output, ...fileConfig.output, ...cliConfig.output, + filePath: + cliConfig.output?.filePath ?? + fileConfig.output?.filePath ?? + (() => { + const style = cliConfig.output?.style ?? fileConfig.output?.style ?? baseConfig.output.style; + const defaultPath = defaultFilePathMap[style]; + logger.trace('Default output file path is set to:', defaultPath); + return defaultPath; + })(), git: { ...baseConfig.output.git, ...fileConfig.output?.git, diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts index 504d6d5d5..efb64225b 100644 --- a/src/config/configSchema.ts +++ b/src/config/configSchema.ts @@ -154,6 +154,8 @@ export type RepomixConfigFile = z.infer; export type RepomixConfigCli = z.infer; export type RepomixConfigMerged = z.infer; +// Pass empty objects to let Zod apply all default values +// Zod v4 requires explicit nested objects since we removed outer .default({}) export const defaultConfig = repomixConfigDefaultSchema.parse({ input: {}, output: { diff --git a/src/mcp/prompts/packRemoteRepositoryPrompts.ts b/src/mcp/prompts/packRemoteRepositoryPrompts.ts index 386636f0a..cc12882ab 100644 --- a/src/mcp/prompts/packRemoteRepositoryPrompts.ts +++ b/src/mcp/prompts/packRemoteRepositoryPrompts.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod/v3'; diff --git a/src/mcp/tools/attachPackedOutputTool.ts b/src/mcp/tools/attachPackedOutputTool.ts index 21a2f6384..d5b764c22 100644 --- a/src/mcp/tools/attachPackedOutputTool.ts +++ b/src/mcp/tools/attachPackedOutputTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; diff --git a/src/mcp/tools/fileSystemReadDirectoryTool.ts b/src/mcp/tools/fileSystemReadDirectoryTool.ts index 9548495f4..0e008e958 100644 --- a/src/mcp/tools/fileSystemReadDirectoryTool.ts +++ b/src/mcp/tools/fileSystemReadDirectoryTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; diff --git a/src/mcp/tools/fileSystemReadFileTool.ts b/src/mcp/tools/fileSystemReadFileTool.ts index 1ce5ea730..1b59a50dd 100644 --- a/src/mcp/tools/fileSystemReadFileTool.ts +++ b/src/mcp/tools/fileSystemReadFileTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import fs from 'node:fs/promises'; import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; diff --git a/src/mcp/tools/grepRepomixOutputTool.ts b/src/mcp/tools/grepRepomixOutputTool.ts index 7acf0b925..ee0127dcc 100644 --- a/src/mcp/tools/grepRepomixOutputTool.ts +++ b/src/mcp/tools/grepRepomixOutputTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import fs from 'node:fs/promises'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; diff --git a/src/mcp/tools/packCodebaseTool.ts b/src/mcp/tools/packCodebaseTool.ts index 73cabbddb..bbc600e0f 100644 --- a/src/mcp/tools/packCodebaseTool.ts +++ b/src/mcp/tools/packCodebaseTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; diff --git a/src/mcp/tools/packRemoteRepositoryTool.ts b/src/mcp/tools/packRemoteRepositoryTool.ts index d73fb44c0..df0d454a7 100644 --- a/src/mcp/tools/packRemoteRepositoryTool.ts +++ b/src/mcp/tools/packRemoteRepositoryTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import path from 'node:path'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; diff --git a/src/mcp/tools/readRepomixOutputTool.ts b/src/mcp/tools/readRepomixOutputTool.ts index e162b81e4..22129f95b 100644 --- a/src/mcp/tools/readRepomixOutputTool.ts +++ b/src/mcp/tools/readRepomixOutputTool.ts @@ -1,4 +1,7 @@ // @ts-nocheck - Zod v3 compatibility for MCP SDK (imported by mcpAction.ts) +// Note: @ts-expect-error would be preferable, but the type incompatibility extends +// beyond .shape to the entire handler function signature, causing 9+ type errors per file. +// This will be resolved when MCP SDK supports Zod v4. import fs from 'node:fs/promises'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; diff --git a/tests/config/configLoad.test.ts b/tests/config/configLoad.test.ts index b2378d014..5f046b31d 100644 --- a/tests/config/configLoad.test.ts +++ b/tests/config/configLoad.test.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import process from 'node:process'; import { beforeEach, describe, expect, test, vi } from 'vitest'; import { loadFileConfig, mergeConfigs } from '../../src/config/configLoad.js'; -import type { RepomixConfigCli, RepomixConfigFile } from '../../src/config/configSchema.js'; +import { defaultConfig, type RepomixConfigCli, type RepomixConfigFile } from '../../src/config/configSchema.js'; import { getGlobalDirectory } from '../../src/config/globalDirectory.js'; import { RepomixConfigValidationError } from '../../src/shared/errorHandle.js'; import { logger } from '../../src/shared/logger.js'; @@ -238,5 +238,42 @@ describe('configLoad', () => { expect(() => mergeConfigs(process.cwd(), fileConfig, cliConfig)).toThrow(RepomixConfigValidationError); }); + + test('should merge nested git config correctly', () => { + const fileConfig: RepomixConfigFile = { + output: { git: { sortByChanges: false } }, + }; + const cliConfig: RepomixConfigCli = { + output: { git: { includeDiffs: true } }, + }; + const merged = mergeConfigs(process.cwd(), fileConfig, cliConfig); + + // Both configs should be applied + expect(merged.output.git.sortByChanges).toBe(false); + expect(merged.output.git.includeDiffs).toBe(true); + // Defaults should still be present + expect(merged.output.git.sortByChangesMaxCommits).toBe(100); + }); + + test('should not mutate defaultConfig', () => { + const originalFilePath = defaultConfig.output.filePath; + const fileConfig: RepomixConfigFile = { + output: { style: 'markdown' }, + }; + + mergeConfigs(process.cwd(), fileConfig, {}); + + // defaultConfig should remain unchanged + expect(defaultConfig.output.filePath).toBe(originalFilePath); + }); + + test('should merge tokenCount config correctly', () => { + const fileConfig: RepomixConfigFile = { + tokenCount: { encoding: 'cl100k_base' }, + }; + const merged = mergeConfigs(process.cwd(), fileConfig, {}); + + expect(merged.tokenCount.encoding).toBe('cl100k_base'); + }); }); }); From c817922c6d1f651e0ce93c0513aa32bfa5436831 Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 25 Oct 2025 23:20:47 +0900 Subject: [PATCH 3/5] refactor(config): Use immutable merge pattern instead of structuredClone Replaced structuredClone with a more efficient immutable merge pattern for config object merging. The new implementation: - Removes unnecessary deep cloning of the entire defaultConfig - Uses spread operators to create new objects at each level - Wraps the output merge in an IIFE for clearer conditional logic - Sets filePath conditionally on the merged output object This improves performance by avoiding deep cloning overhead while maintaining immutability. The mergedOutput is mutated locally within the IIFE scope, which is safe as it's a newly created object. All 803 tests pass and lint checks are clean. --- src/config/configLoad.ts | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/config/configLoad.ts b/src/config/configLoad.ts index 6f0464bf9..53b766100 100644 --- a/src/config/configLoad.ts +++ b/src/config/configLoad.ts @@ -155,7 +155,7 @@ export const mergeConfigs = ( ): RepomixConfigMerged => { logger.trace('Default config:', defaultConfig); - const baseConfig = structuredClone(defaultConfig); + const baseConfig = defaultConfig; const mergedConfig = { cwd, @@ -164,25 +164,26 @@ export const mergeConfigs = ( ...fileConfig.input, ...cliConfig.input, }, - output: { - ...baseConfig.output, - ...fileConfig.output, - ...cliConfig.output, - filePath: - cliConfig.output?.filePath ?? - fileConfig.output?.filePath ?? - (() => { - const style = cliConfig.output?.style ?? fileConfig.output?.style ?? baseConfig.output.style; - const defaultPath = defaultFilePathMap[style]; - logger.trace('Default output file path is set to:', defaultPath); - return defaultPath; - })(), - git: { - ...baseConfig.output.git, - ...fileConfig.output?.git, - ...cliConfig.output?.git, - }, - }, + output: (() => { + const mergedOutput = { + ...baseConfig.output, + ...fileConfig.output, + ...cliConfig.output, + git: { + ...baseConfig.output.git, + ...fileConfig.output?.git, + ...cliConfig.output?.git, + }, + }; + + if (mergedOutput.filePath == null) { + const style = mergedOutput.style ?? baseConfig.output.style; + mergedOutput.filePath = defaultFilePathMap[style]; + logger.trace('Default output file path is set to:', mergedOutput.filePath); + } + + return mergedOutput; + })(), include: [...(baseConfig.include || []), ...(fileConfig.include || []), ...(cliConfig.include || [])], ignore: { ...baseConfig.ignore, From 33129320837ef881257fd15af4b32bf9c83e576e Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 25 Oct 2025 23:26:30 +0900 Subject: [PATCH 4/5] test(config): Add error message validation for missing required fields Added a test to verify that Zod v4 provides helpful error messages when required fields are missing from the config schema. The test ensures that the error message includes "expected object" to help users understand what went wrong. This addresses the suggestion from Claude bot to improve test coverage for error message quality and helps catch regressions in error messaging. --- tests/config/configSchema.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/config/configSchema.test.ts b/tests/config/configSchema.test.ts index e1340a904..c4088c8a1 100644 --- a/tests/config/configSchema.test.ts +++ b/tests/config/configSchema.test.ts @@ -143,6 +143,11 @@ describe('configSchema', () => { const invalidConfig = {}; expect(() => repomixConfigDefaultSchema.parse(invalidConfig)).toThrow(); }); + + it('should provide helpful error for missing required fields', () => { + const invalidConfig = {}; + expect(() => repomixConfigDefaultSchema.parse(invalidConfig)).toThrow(/expected object/i); + }); }); describe('repomixConfigFileSchema', () => { From da90167071ecdee8073b8552f165381cbf58cb5a Mon Sep 17 00:00:00 2001 From: Kazuki Yamada Date: Sat, 25 Oct 2025 23:33:23 +0900 Subject: [PATCH 5/5] refactor(website): Use Zod v4's built-in toJSONSchema for schema generation Replaced zod-to-json-schema with Zod v4's native toJSONSchema() method for generating JSON Schema from Zod schemas. This eliminates the need for an external dependency and leverages Zod v4's new built-in feature. Changes: - Updated generateSchema.ts to use z.toJSONSchema() with draft-7 target - Removed direct dependency on zod-to-json-schema (still exists via MCP SDK) - Simplified the schema generation process The generated schema remains compatible with the existing format and all tooling that depends on it. --- package-lock.json | 18 +++++++++--------- website/client/scripts/generateSchema.ts | 9 ++++----- .../src/public/schemas/1.8.0/schema.json | 14 ++++++++++---- .../src/public/schemas/latest/schema.json | 14 ++++++++++---- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index f490ed675..0b84bf9e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -948,15 +948,6 @@ "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/@modelcontextprotocol/sdk/node_modules/zod-to-json-schema": { - "version": "3.24.6", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", - "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.24.1" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6087,6 +6078,15 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/website/client/scripts/generateSchema.ts b/website/client/scripts/generateSchema.ts index ceab9c371..bc13c8c1a 100644 --- a/website/client/scripts/generateSchema.ts +++ b/website/client/scripts/generateSchema.ts @@ -1,6 +1,6 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import { zodToJsonSchema } from 'zod-to-json-schema'; +import { z } from 'zod'; import { repomixConfigFileSchema } from '../../../src/config/configSchema.js'; const getPackageVersion = async (): Promise => { @@ -15,10 +15,9 @@ const generateSchema = async () => { const versionParts = version.split('.'); const majorMinorVersion = `${versionParts[0]}.${versionParts[1]}.${versionParts[2]}`; - const jsonSchema = zodToJsonSchema(repomixConfigFileSchema, { - $refStrategy: 'none', - definitionPath: 'definitions', - markdownDescription: true, + // Use Zod v4's built-in JSON Schema generation + const jsonSchema = z.toJSONSchema(repomixConfigFileSchema, { + target: 'draft-7', }); const schemaWithMeta = { diff --git a/website/client/src/public/schemas/1.8.0/schema.json b/website/client/src/public/schemas/1.8.0/schema.json index 9a864a377..e566588f4 100644 --- a/website/client/src/public/schemas/1.8.0/schema.json +++ b/website/client/src/public/schemas/1.8.0/schema.json @@ -75,10 +75,16 @@ "type": "boolean" }, "tokenCountTree": { - "type": [ - "boolean", - "number", - "string" + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + } ] }, "git": { diff --git a/website/client/src/public/schemas/latest/schema.json b/website/client/src/public/schemas/latest/schema.json index 9a864a377..e566588f4 100644 --- a/website/client/src/public/schemas/latest/schema.json +++ b/website/client/src/public/schemas/latest/schema.json @@ -75,10 +75,16 @@ "type": "boolean" }, "tokenCountTree": { - "type": [ - "boolean", - "number", - "string" + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + } ] }, "git": {