Skip to main content
Glama
path-resolver.ts•5.13 kB
import path from 'path'; import logger from '../../../logger.js'; import { UnifiedSecurityEngine, createDefaultSecurityConfig } from '../core/unified-security-engine.js'; /** * Centralized path resolution utility for Vibe Task Manager * Follows existing patterns from project-operations.ts and unified security configuration */ export class PathResolver { private static instance: PathResolver; private securityEngine: UnifiedSecurityEngine | null = null; private constructor() {} static getInstance(): PathResolver { if (!PathResolver.instance) { PathResolver.instance = new PathResolver(); } return PathResolver.instance; } /** * Get or initialize the security engine */ private async getSecurityEngine(): Promise<UnifiedSecurityEngine> { if (!this.securityEngine) { const config = createDefaultSecurityConfig(); this.securityEngine = UnifiedSecurityEngine.getInstance(config); await this.securityEngine.initialize(); } return this.securityEngine; } /** * Resolve project root path following existing patterns from project-operations.ts * Priority: 1) Provided path, 2) Environment variable, 3) Current working directory */ resolveProjectRootPath(providedPath?: string, contextId?: string): string { // 1. Try provided path first if (providedPath && providedPath !== '/' && providedPath.length > 1) { logger.debug({ providedPath, contextId }, 'Using provided project path'); return path.resolve(providedPath); } // 2. Use environment variable (following existing security patterns) const envProjectPath = process.env.VIBE_TASK_MANAGER_READ_DIR; if (envProjectPath && envProjectPath !== '/' && envProjectPath.length > 1) { logger.debug({ envProjectPath, contextId }, 'Using environment project path'); return path.resolve(envProjectPath); } // 3. Fallback to current working directory const cwd = process.cwd(); logger.debug({ cwd, contextId }, 'Using current working directory as project path'); return cwd; } /** * Resolve project path from command execution context */ resolveProjectPathFromContext(context: { projectPath?: string; sessionId?: string }): string { return this.resolveProjectRootPath(context.projectPath, context.sessionId); } /** * Get the configured read directory for Vibe Task Manager */ getReadDirectory(): string { return this.resolveProjectRootPath(); } /** * Get the configured output directory for Vibe Task Manager */ getOutputDirectory(): string { const outputDir = process.env.VIBE_CODER_OUTPUT_DIR; if (outputDir) { return path.resolve(outputDir); } // Fallback to default output directory const projectRoot = this.resolveProjectRootPath(); return path.join(projectRoot, 'VibeCoderOutput'); } /** * Create a secure path within the read directory using unified security engine */ async createSecureReadPath(relativePath: string): Promise<string> { const readDir = this.getReadDirectory(); const resolvedPath = path.resolve(readDir, relativePath); // Use the unified security engine for consistent boundary enforcement const securityEngine = await this.getSecurityEngine(); const validationResponse = await securityEngine.validatePath(resolvedPath, 'read'); if (!validationResponse.success) { throw new Error(`Path validation failed: ${validationResponse.error?.message || 'Unknown error'}`); } const validationResult = validationResponse.data; if (!validationResult.isValid) { throw new Error(`Path validation failed: ${validationResult.error || 'Path validation failed'}`); } return validationResult.normalizedPath || resolvedPath; } /** * Create a secure path within the output directory using unified security engine */ async createSecureOutputPath(relativePath: string): Promise<string> { const outputDir = this.getOutputDirectory(); const resolvedPath = path.resolve(outputDir, relativePath); // Use the unified security engine for consistent boundary enforcement const securityEngine = await this.getSecurityEngine(); const validationResponse = await securityEngine.validatePath(resolvedPath, 'write'); if (!validationResponse.success) { throw new Error(`Path validation failed: ${validationResponse.error?.message || 'Unknown error'}`); } const validationResult = validationResponse.data; if (!validationResult.isValid) { throw new Error(`Path validation failed: ${validationResult.error || 'Path validation failed'}`); } return validationResult.normalizedPath || resolvedPath; } } /** * Convenience function to get the singleton PathResolver instance */ export function getPathResolver(): PathResolver { return PathResolver.getInstance(); } /** * Convenience function to resolve project root path */ export function resolveProjectPath(providedPath?: string, contextId?: string): string { return getPathResolver().resolveProjectRootPath(providedPath, contextId); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/freshtechbro/vibe-coder-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server