@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
JavaScript
/**
* 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