UNPKG

@dollhousemcp/mcp-server

Version:

DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.

615 lines 79.6 kB
/** * AgentManager - Handles CRUD operations for Agent elements * Follows patterns from PersonaElementManager and MemoryManager * * SECURITY: Uses FileLockManager for atomic operations and SecureYamlParser for safe YAML parsing */ import { promises as fs } from 'fs'; import * as path from 'path'; import { Agent } from './Agent.js'; import { ElementType } from '../../portfolio/types.js'; import { FileLockManager } from '../../security/fileLockManager.js'; import { SecureYamlParser } from '../../security/secureYamlParser.js'; import * as yaml from 'js-yaml'; import { sanitizeInput } from '../../security/InputValidator.js'; import { UnicodeValidator } from '../../security/validators/unicodeValidator.js'; import { SecurityMonitor } from '../../security/securityMonitor.js'; import { logger } from '../../utils/logger.js'; // Constants const AGENT_FILE_EXTENSION = '.md'; const STATE_DIRECTORY = '.state'; const STATE_FILE_EXTENSION = '.state.yaml'; const MAX_FILE_SIZE = 100 * 1024; // 100KB const MAX_YAML_SIZE = 64 * 1024; // 64KB for frontmatter export class AgentManager { agentsPath; stateCache = new Map(); constructor(portfolioPath) { this.agentsPath = path.join(portfolioPath, ElementType.AGENT); } /** * Initialize the agents directory structure */ async initialize() { try { // Create agents directory if it doesn't exist await fs.mkdir(this.agentsPath, { recursive: true }); // Create .state directory for agent states const statePath = path.join(this.agentsPath, STATE_DIRECTORY); await fs.mkdir(statePath, { recursive: true }); logger.info('AgentManager initialized', { path: this.agentsPath }); } catch (error) { logger.error('Failed to initialize AgentManager', error); throw error; } } /** * Create a new agent */ async create(name, description, content, metadata) { try { // Sanitize inputs const sanitizedName = sanitizeInput(UnicodeValidator.normalize(name).normalizedContent, 100); const sanitizedDescription = sanitizeInput(UnicodeValidator.normalize(description).normalizedContent, 500); const sanitizedContent = sanitizeInput(UnicodeValidator.normalize(content).normalizedContent, 50000); // Validate name if (!this.validateElementName(sanitizedName)) { return { success: false, message: 'Invalid agent name. Use only letters, numbers, hyphens, and underscores.' }; } // Check if agent already exists const filename = this.getFilename(sanitizedName); const filepath = path.join(this.agentsPath, filename); // Create agent instance const agent = new Agent({ name: sanitizedName, description: sanitizedDescription, ...metadata }); // Set author agent.metadata.author = this.getCurrentUserForAttribution(); // Prepare file content const fileContent = this.serializeToFile(agent, sanitizedContent); // SECURITY FIX: Use atomic file creation to prevent race conditions // Previously: Used access() check followed by write, which could race // Now: Use exclusive file creation that fails atomically if file exists try { const fd = await fs.open(filepath, 'wx'); // 'wx' = exclusive write, fails if exists await fd.writeFile(fileContent, 'utf-8'); await fd.close(); } catch (error) { if (error.code === 'EEXIST') { return { success: false, message: `Agent '${sanitizedName}' already exists` }; } throw error; } // Log security event SecurityMonitor.logSecurityEvent({ type: 'ELEMENT_CREATED', severity: 'LOW', source: 'AgentManager.create', details: `Agent '${sanitizedName}' created`, additionalData: { agentId: agent.id } }); logger.info(`Agent created: ${sanitizedName}`); return { success: true, message: `🤖 **${sanitizedName}** by ${agent.metadata.author || 'anonymous'}`, element: agent }; } catch (error) { logger.error('Failed to create agent', error); return { success: false, message: error instanceof Error ? error.message : 'Failed to create agent' }; } } /** * Read an agent by name */ async read(name) { try { const sanitizedName = sanitizeInput(name, 100); const filename = this.getFilename(sanitizedName); const filepath = path.join(this.agentsPath, filename); // Read file with lock const content = await FileLockManager.atomicReadFile(filepath, { encoding: 'utf-8' }); // Check file size if (content.length > MAX_FILE_SIZE) { throw new Error(`Agent file exceeds maximum size of ${MAX_FILE_SIZE} bytes`); } // Parse file const agentData = this.parseAgentFile(content); // Create agent instance - ensure metadata is passed correctly const agent = new Agent(agentData.metadata); // Load state if available const state = await this.loadAgentState(sanitizedName); if (state) { agent.deserialize(JSON.stringify({ ...JSON.parse(agent.serialize()), state })); } return agent; } catch (error) { if (error.code === 'ENOENT') { return null; } logger.error(`Failed to read agent: ${name}`, error); throw error; } } /** * Update an agent */ async update(name, updates, content) { try { const agent = await this.read(name); if (!agent) { logger.warn(`Agent not found for update: ${name}`); return false; } // Apply metadata updates if (updates.description !== undefined) { agent.metadata.description = sanitizeInput(UnicodeValidator.normalize(updates.description).normalizedContent, 500); } if (updates.specializations !== undefined) { agent.extensions = { ...agent.extensions, specializations: updates.specializations.map((s) => sanitizeInput(s, 50)) }; } if (updates.decisionFramework !== undefined) { agent.extensions = { ...agent.extensions, decisionFramework: updates.decisionFramework }; } if (updates.riskTolerance !== undefined) { agent.extensions = { ...agent.extensions, riskTolerance: updates.riskTolerance }; } // Update modification time agent.metadata.modified = new Date().toISOString(); // Get current content if not provided if (content === undefined) { const filename = this.getFilename(name); const filepath = path.join(this.agentsPath, filename); const fileContent = await FileLockManager.atomicReadFile(filepath, { encoding: 'utf-8' }); const parsed = this.parseAgentFile(fileContent); content = parsed.content; } // Save agent const filename = this.getFilename(name); const filepath = path.join(this.agentsPath, filename); const fileContent = this.serializeToFile(agent, content); await FileLockManager.atomicWriteFile(filepath, fileContent, { encoding: 'utf-8' }); // Save state if needed if (agent.needsStatePersistence()) { await this.saveAgentState(name, agent.getState()); agent.markStatePersisted(); } logger.info(`Agent updated: ${name}`); return true; } catch (error) { logger.error(`Failed to update agent: ${name}`, error); return false; } } /** * Delete an agent */ async delete(name) { try { const sanitizedName = sanitizeInput(name, 100); const filename = this.getFilename(sanitizedName); const filepath = path.join(this.agentsPath, filename); // Check if file exists try { await fs.access(filepath); } catch { return; } // Delete main file await fs.unlink(filepath); // Delete state file if exists const stateFilename = `${sanitizedName}${STATE_FILE_EXTENSION}`; const stateFilepath = path.join(this.agentsPath, STATE_DIRECTORY, stateFilename); try { await fs.unlink(stateFilepath); this.stateCache.delete(sanitizedName); } catch { // State file might not exist } // Log security event SecurityMonitor.logSecurityEvent({ type: 'ELEMENT_DELETED', severity: 'MEDIUM', source: 'AgentManager.delete', details: `Agent '${sanitizedName}' deleted` }); logger.info(`Agent deleted: ${sanitizedName}`); } catch (error) { logger.error(`Failed to delete agent: ${name}`, error); throw error; } } /** * List all agents */ async list() { try { const files = await fs.readdir(this.agentsPath); // Filter for agent files const agentFiles = files.filter(file => file.endsWith(AGENT_FILE_EXTENSION) && !file.startsWith('.') && file !== STATE_DIRECTORY); // Load all agents const agents = []; for (const file of agentFiles) { const name = file.substring(0, file.length - AGENT_FILE_EXTENSION.length); try { const agent = await this.read(name); if (agent) { agents.push(agent); } } catch (error) { logger.warn(`Failed to load agent ${name}:`, error); } } return agents; } catch (error) { // Handle missing directory gracefully with type-safe check if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') { logger.debug('Agents directory does not exist yet, returning empty array'); return []; } logger.error('Failed to list agents', error); return []; } } /** * Check if an agent exists */ async exists(name) { try { const sanitizedName = sanitizeInput(name, 100); const filename = this.getFilename(sanitizedName); const filepath = path.join(this.agentsPath, filename); await fs.access(filepath); return true; } catch { return false; } } /** * Validate an agent name */ validateName(name) { if (!name || name.trim().length === 0) { return { valid: false, error: 'Name cannot be empty' }; } if (name.length > 100) { return { valid: false, error: 'Name cannot exceed 100 characters' }; } if (!this.validateElementName(name)) { return { valid: false, error: 'Name can only contain letters, numbers, hyphens, and underscores' }; } return { valid: true }; } /** * Get element type */ getElementType() { return ElementType.AGENT; } /** * Load agent state from file */ async loadAgentState(name) { try { // Check cache first if (this.stateCache.has(name)) { return this.stateCache.get(name); } const stateFilename = `${name}${STATE_FILE_EXTENSION}`; const stateFilepath = path.join(this.agentsPath, STATE_DIRECTORY, stateFilename); const content = await FileLockManager.atomicReadFile(stateFilepath, { encoding: 'utf-8' }); // Parse YAML safely const parsedContent = SecureYamlParser.parse(content, { maxYamlSize: MAX_YAML_SIZE, validateContent: true }); const state = parsedContent.data; // Convert string numbers back to numbers if (state.sessionCount !== undefined) { state.sessionCount = parseInt(state.sessionCount, 10); } // Convert goal numbers if (state.goals) { state.goals.forEach((goal) => { if (goal.importance !== undefined) goal.importance = parseInt(goal.importance, 10); if (goal.urgency !== undefined) goal.urgency = parseInt(goal.urgency, 10); if (goal.estimatedEffort !== undefined) goal.estimatedEffort = parseFloat(goal.estimatedEffort); }); } // Convert decision confidence if (state.decisions) { state.decisions.forEach((decision) => { if (decision.confidence !== undefined) decision.confidence = parseFloat(decision.confidence); }); } // Cache the state this.stateCache.set(name, state); return state; } catch (error) { if (error.code === 'ENOENT') { return null; } logger.error(`Failed to load agent state: ${name}`, error); return null; } } /** * Save agent state to file */ async saveAgentState(name, state) { try { const stateFilename = `${name}${STATE_FILE_EXTENSION}`; const stateFilepath = path.join(this.agentsPath, STATE_DIRECTORY, stateFilename); // Convert dates to ISO strings and numbers to strings for FAILSAFE_SCHEMA const serializedState = { ...state, lastActive: state.lastActive instanceof Date ? state.lastActive.toISOString() : state.lastActive, sessionCount: String(state.sessionCount), goals: state.goals.map(goal => ({ ...goal, createdAt: goal.createdAt instanceof Date ? goal.createdAt.toISOString() : goal.createdAt, updatedAt: goal.updatedAt instanceof Date ? goal.updatedAt.toISOString() : goal.updatedAt, completedAt: goal.completedAt instanceof Date ? goal.completedAt.toISOString() : goal.completedAt, importance: goal.importance !== undefined ? String(goal.importance) : undefined, urgency: goal.urgency !== undefined ? String(goal.urgency) : undefined, estimatedEffort: goal.estimatedEffort !== undefined ? String(goal.estimatedEffort) : undefined })), decisions: state.decisions.map(decision => ({ ...decision, timestamp: decision.timestamp instanceof Date ? decision.timestamp.toISOString() : decision.timestamp, confidence: decision.confidence !== undefined ? String(decision.confidence) : undefined })) }; // Convert state to YAML const yamlContent = yaml.dump(serializedState, { schema: yaml.FAILSAFE_SCHEMA, noRefs: true, sortKeys: true }); // Validate size if (yamlContent.length > MAX_YAML_SIZE) { throw new Error(`State size exceeds maximum of ${MAX_YAML_SIZE} bytes`); } // Write atomically await FileLockManager.atomicWriteFile(stateFilepath, yamlContent, { encoding: 'utf-8' }); // Update cache this.stateCache.set(name, state); logger.debug(`Agent state saved: ${name}`); } catch (error) { logger.error(`Failed to save agent state: ${name}`, error); throw error; } } /** * Parse agent file content */ parseAgentFile(content) { // Extract frontmatter and content const frontmatterRegex = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/; const match = content.match(frontmatterRegex); if (!match) { throw new Error('Invalid agent file format - missing frontmatter'); } const [, frontmatter, body] = match; // Parse frontmatter - SecureYamlParser expects full content with frontmatter markers // but we're passing just the YAML content, so we need to parse it directly const parsedYaml = SecureYamlParser.parse(`---\n${frontmatter}\n---`, { maxYamlSize: MAX_YAML_SIZE, validateContent: false // We'll validate body separately }); const metadata = parsedYaml.data; // Validate type if using the typed metadata const typedMetadata = metadata; if (typedMetadata.type && typedMetadata.type !== ElementType.AGENT && typedMetadata.type !== 'agent') { throw new Error(`Invalid element type: expected '${ElementType.AGENT}', got '${typedMetadata.type}'`); } return { metadata, content: body.trim() }; } /** * Serialize agent to file format */ serializeToFile(agent, content) { const metadata = { name: agent.metadata.name, type: ElementType.AGENT, version: agent.metadata.version, author: agent.metadata.author, created: agent.metadata.created || new Date().toISOString(), modified: agent.metadata.modified || new Date().toISOString(), description: agent.metadata.description, decisionFramework: agent.extensions?.decisionFramework, riskTolerance: agent.extensions?.riskTolerance, learningEnabled: agent.extensions?.learningEnabled !== undefined ? String(agent.extensions.learningEnabled) : undefined, maxConcurrentGoals: agent.metadata.maxConcurrentGoals, specializations: agent.extensions?.specializations }; // Remove undefined values Object.keys(metadata).forEach(key => { if (metadata[key] === undefined) { delete metadata[key]; } }); const yamlContent = yaml.dump(metadata, { schema: yaml.FAILSAFE_SCHEMA, noRefs: true, sortKeys: true }); return `---\n${yamlContent}---\n\n${content}`; } /** * Get filename for agent */ getFilename(name) { return `${name}${AGENT_FILE_EXTENSION}`; } /** * Validate element name */ validateElementName(name) { // Only letters, numbers, hyphens, and underscores return /^[a-zA-Z0-9_-]+$/.test(name); } /** * Get current user for attribution */ getCurrentUserForAttribution() { return process.env.DOLLHOUSE_USER || 'anonymous'; } /** * Find an agent by predicate */ async find(predicate) { const agents = await this.list(); return agents.find(predicate); } /** * Find many agents by predicate */ async findMany(predicate) { const agents = await this.list(); return agents.filter(predicate); } /** * Validate an agent */ validate(element) { return element.validate(); } /** * Validate a path */ validatePath(path) { // Check for path traversal if (path.includes('..') || path.includes('~')) { return false; } // Check for absolute paths if (path.startsWith('/') || path.match(/^[A-Za-z]:/)) { return false; } return true; } /** * Get file extension */ getFileExtension() { return AGENT_FILE_EXTENSION; } /** * Import an agent from data */ async importElement(data, format) { if (format === 'json') { const parsed = JSON.parse(data); const agent = new Agent(parsed.metadata); if (parsed.state) { agent.deserialize(JSON.stringify(parsed)); } return agent; } else { // Parse as markdown with YAML frontmatter const agentData = this.parseAgentFile(data); const agent = new Agent(agentData.metadata); if (agentData.state) { agent.deserialize(JSON.stringify({ ...JSON.parse(agent.serialize()), state: agentData.state })); } return agent; } } /** * Export an agent to a format */ async exportElement(element, format) { if (format === 'json') { return element.serialize(); } else { // Export as markdown with YAML frontmatter const content = `# ${element.metadata.name}\n\n${element.metadata.description || ''}`; return this.serializeToFile(element, content); } } /** * Save an agent to a specific path */ async save(element, targetPath) { const name = targetPath.replace(AGENT_FILE_EXTENSION, ''); const content = `# ${element.metadata.name}\n\n${element.metadata.description || ''}`; // Save the agent file const filename = this.getFilename(name); const filepath = path.isAbsolute(targetPath) ? targetPath : path.join(this.agentsPath, filename); const fileContent = this.serializeToFile(element, content); await FileLockManager.atomicWriteFile(filepath, fileContent, { encoding: 'utf-8' }); // Save state if needed if (element.needsStatePersistence()) { await this.saveAgentState(name, element.getState()); element.markStatePersisted(); } } /** * Load an agent from a specific path */ async load(targetPath) { const agent = await this.read(targetPath.replace(AGENT_FILE_EXTENSION, '')); if (!agent) { // SECURITY FIX #206: Don't expose file paths in error messages logger.error('Agent not found', { path: targetPath }); throw new Error('Agent not found'); } return agent; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdlbnRNYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VsZW1lbnRzL2FnZW50cy9BZ2VudE1hbmFnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLElBQUksQ0FBQztBQUNwQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBR25DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDdEUsT0FBTyxLQUFLLElBQUksTUFBTSxTQUFTLENBQUM7QUFDaEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ2pGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFL0MsWUFBWTtBQUNaLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxDQUFDO0FBQ25DLE1BQU0sZUFBZSxHQUFHLFFBQVEsQ0FBQztBQUNqQyxNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQztBQUMzQyxNQUFNLGFBQWEsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLENBQUMsUUFBUTtBQUMxQyxNQUFNLGFBQWEsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsdUJBQXVCO0FBZXhELE1BQU0sT0FBTyxZQUFZO0lBQ04sVUFBVSxDQUFTO0lBQ25CLFVBQVUsR0FBNEIsSUFBSSxHQUFHLEVBQUUsQ0FB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Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWdlbnRNYW5hZ2VyIC0gSGFuZGxlcyBDUlVEIG9wZXJhdGlvbnMgZm9yIEFnZW50IGVsZW1lbnRzXG4gKiBGb2xsb3dzIHBhdHRlcm5zIGZyb20gUGVyc29uYUVsZW1lbnRNYW5hZ2VyIGFuZCBNZW1vcnlNYW5hZ2VyXG4gKiBcbiAqIFNFQ1VSSVRZOiBVc2VzIEZpbGVMb2NrTWFuYWdlciBmb3IgYXRvbWljIG9wZXJhdGlvbnMgYW5kIFNlY3VyZVlhbWxQYXJzZXIgZm9yIHNhZmUgWUFNTCBwYXJzaW5nXG4gKi9cblxuaW1wb3J0IHsgcHJvbWlzZXMgYXMgZnMgfSBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQWdlbnQgfSBmcm9tICcuL0FnZW50LmpzJztcbmltcG9ydCB7IEFnZW50TWV0YWRhdGEsIEFnZW50U3RhdGUgfSBmcm9tICcuL3R5cGVzLmpzJztcbmltcG9ydCB7IElFbGVtZW50TWFuYWdlciwgRWxlbWVudFZhbGlkYXRpb25SZXN1bHQgfSBmcm9tICcuLi8uLi90eXBlcy9lbGVtZW50cy9pbmRleC5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uLy4uL3BvcnRmb2xpby90eXBlcy5qcyc7XG5pbXBvcnQgeyBGaWxlTG9ja01hbmFnZXIgfSBmcm9tICcuLi8uLi9zZWN1cml0eS9maWxlTG9ja01hbmFnZXIuanMnO1xuaW1wb3J0IHsgU2VjdXJlWWFtbFBhcnNlciB9IGZyb20gJy4uLy4uL3NlY3VyaXR5L3NlY3VyZVlhbWxQYXJzZXIuanMnO1xuaW1wb3J0ICogYXMgeWFtbCBmcm9tICdqcy15YW1sJztcbmltcG9ydCB7IHNhbml0aXplSW5wdXQgfSBmcm9tICcuLi8uLi9zZWN1cml0eS9JbnB1dFZhbGlkYXRvci5qcy