UNPKG

ken-you-code

Version:

Connect your codebase to Kimi: Ultra-fast AI code analysis with Kimi-K2 model via MCP

82 lines (68 loc) 2.31 kB
import { readFile, stat } from 'fs/promises'; import path from 'path'; import { config } from '../config/index.js'; export interface ReadFileResult { content: string; size: number; extension: string; } export class FileOperations { private static isPathSafe(filePath: string): boolean { const resolvedPath = path.resolve(filePath); // Check if workspace root is configured and enforce it if (config.workspaceRoot) { const workspaceRoot = path.resolve(config.workspaceRoot); if (!resolvedPath.startsWith(workspaceRoot)) { return false; } } // Check for forbidden paths const forbiddenPaths = ['.env', '.git/', 'node_modules/', '__pycache__/']; for (const forbidden of forbiddenPaths) { if (resolvedPath.includes(forbidden)) { return false; } } return true; } private static isExtensionAllowed(filePath: string): boolean { const ext = path.extname(filePath).toLowerCase(); return config.allowedExtensions.includes(ext); } static async readFileSecurely(filePath: string): Promise<ReadFileResult> { // Validate path safety if (!this.isPathSafe(filePath)) { throw new Error(`Access denied: Path '${filePath}' is not allowed`); } // Validate file extension if (!this.isExtensionAllowed(filePath)) { throw new Error(`File type not allowed: ${path.extname(filePath)}`); } try { // Check file exists and get stats const fileStats = await stat(filePath); if (!fileStats.isFile()) { throw new Error(`Path is not a file: ${filePath}`); } // Check file size const fileSizeMB = fileStats.size / (1024 * 1024); if (fileSizeMB > config.maxFileSizeMB) { throw new Error( `File too large: ${fileSizeMB.toFixed(2)}MB (max: ${config.maxFileSizeMB}MB)` ); } // Read file content const content = await readFile(filePath, 'utf-8'); return { content, size: fileStats.size, extension: path.extname(filePath), }; } catch (error) { if (error instanceof Error) { throw new Error(`Failed to read file '${filePath}': ${error.message}`); } throw new Error(`Failed to read file '${filePath}': Unknown error`); } } }