@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.
112 lines • 15.1 kB
JavaScript
import { formatIndicator } from '../config/indicator-config.js';
import { ElementType } from '../portfolio/types.js';
import { SecurityMonitor } from '../security/securityMonitor.js';
/**
* SOURCE OF TRUTH for persona indicator formatting. Mirrors the
* HandlerContext.getPersonaIndicator responsibility so handlers can rely on
* explicit constructor injection instead of the service locator pattern.
*/
export class PersonaIndicatorService {
personaManager;
indicatorConfig;
notifier;
eventDispatcher;
cachedIndicator = null;
cachedPersonaId = null;
boundListener;
boundElementListener;
elementUnsubscribes = [];
fallbackProvider;
constructor(personaManager, indicatorConfig, notifier, eventDispatcher) {
this.personaManager = personaManager;
this.indicatorConfig = indicatorConfig;
this.notifier = notifier;
this.eventDispatcher = eventDispatcher;
if (this.notifier) {
this.boundListener = this.handlePersonaChange.bind(this);
this.notifier.on('state-change:persona-activated', this.boundListener);
this.notifier.on('state-change:persona-deactivated', this.boundListener);
this.notifier.on('state-change:user-changed', this.boundListener);
}
if (this.eventDispatcher) {
this.boundElementListener = this.handleElementEvent.bind(this);
this.elementUnsubscribes.push(this.eventDispatcher.on('element:activate', this.boundElementListener), this.eventDispatcher.on('element:deactivate', this.boundElementListener));
}
}
getPersonaIndicator() {
const persona = this.personaManager.getActivePersona();
if (!persona) {
return this.fallbackProvider ? this.fallbackProvider() : '';
}
if (this.cachedIndicator !== null && this.cachedPersonaId === persona.filename) {
return this.cachedIndicator;
}
const indicator = formatIndicator(this.indicatorConfig, {
name: persona.metadata.name,
version: persona.metadata.version,
author: persona.metadata.author,
category: persona.metadata.category,
});
this.cachedIndicator = indicator;
this.cachedPersonaId = persona.filename;
return indicator;
}
/**
* Get the current indicator configuration.
* Used by ConfigHandler to read current settings before applying updates.
*
* @returns Current IndicatorConfig
*/
getConfig() {
return { ...this.indicatorConfig };
}
updateConfig(config) {
// FIX: DMCP-SEC-006 - Add security audit logging for configuration changes
SecurityMonitor.logSecurityEvent({
type: 'CONFIG_UPDATED',
severity: 'LOW',
source: 'PersonaIndicatorService.updateConfig',
details: `Indicator configuration updated: style=${config.style}, enabled=${config.enabled}`,
additionalData: {
style: config.style,
enabled: config.enabled,
showVersion: config.showVersion,
showAuthor: config.showAuthor
}
});
this.indicatorConfig = config;
this.invalidateCache();
}
setFallbackProvider(provider) {
this.fallbackProvider = provider;
this.invalidateCache();
}
invalidateCache() {
this.cachedIndicator = null;
this.cachedPersonaId = null;
}
async dispose() {
if (this.boundListener && this.notifier) {
this.notifier.off('state-change:persona-activated', this.boundListener);
this.notifier.off('state-change:persona-deactivated', this.boundListener);
this.notifier.off('state-change:user-changed', this.boundListener);
}
while (this.elementUnsubscribes.length > 0) {
const unsubscribe = this.elementUnsubscribes.pop();
if (unsubscribe) {
unsubscribe();
}
}
this.invalidateCache();
}
handlePersonaChange(_event) {
this.invalidateCache();
}
handleElementEvent(payload) {
if (payload.elementType !== ElementType.PERSONA) {
return;
}
this.invalidateCache();
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGVyc29uYUluZGljYXRvclNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvUGVyc29uYUluZGljYXRvclNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFtQixlQUFlLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQU9qRixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWpFOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sdUJBQXVCO0lBU3hCO0lBQ0E7SUFDQTtJQUNBO0lBWEYsZUFBZSxHQUFrQixJQUFJLENBQUM7SUFDdEMsZUFBZSxHQUFrQixJQUFJLENBQUM7SUFDN0IsYUFBYSxDQUE0QztJQUN6RCxvQkFBb0IsQ0FBMEM7SUFDOUQsbUJBQW1CLEdBQXNCLEVBQUUsQ0FBQztJQUNyRCxnQkFBZ0IsQ0FBZ0I7SUFFeEMsWUFDVSxjQUE4QixFQUM5QixlQUFnQyxFQUNoQyxRQUE4QixFQUM5QixlQUF3QztRQUh4QyxtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQ2hDLGFBQVEsR0FBUixRQUFRLENBQXNCO1FBQzlCLG9CQUFlLEdBQWYsZUFBZSxDQUF5QjtRQUVoRCxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDekQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3ZFLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLGtDQUFrQyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN6RSxJQUFJ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LENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxnQ0FBZ0MsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDeEUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsa0NBQWtDLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQzFFLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLDJCQUEyQixFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNuRCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixXQUFXLEVBQUUsQ0FBQztZQUNoQixDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRU8sbUJBQW1CLENBQUMsTUFBK0I7UUFDekQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxPQUE0QjtRQUNyRCxJQUFJLE9BQU8sQ0FBQyxXQUFXLEtBQUssV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hELE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBQ3pCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluZGljYXRvckNvbmZpZywgZm9ybWF0SW5kaWNhdG9yIH0gZnJvbSAnLi4vY29uZmlnL2luZGljYXRvci1jb25maWcuanMnO1xuaW1wb3J0IHsgUGVyc29uYU1hbmFnZXIgfSBmcm9tICcuLi9wZXJzb25hL1BlcnNvbmFNYW5hZ2VyLmpzJztcbmltcG9ydCB7XG4gIFN0YXRlQ2hhbmdlTm90aWZpZXIsXG4gIHR5cGUgUGVyc29uYVN0YXRlQ2hhbmdlRXZlbnQsXG59IGZyb20gJy4vU3RhdGVDaGFuZ2VOb3RpZmllci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50RXZlbnREaXNwYXRjaGVyLCB0eXBlIEVsZW1lbnRFdmVudFBheWxvYWQgfSBmcm9tICcuLi9ldmVudHMvRWxlbWVudEV2ZW50RGlzcGF0Y2hlci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uL3BvcnRmb2xpby90eXBlcy5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuXG4vKipcbiAqIFNPVVJDRSBPRiBUUlVUSCBmb3IgcGVyc29uYSBpbmRpY2F0b3IgZm9ybWF0dGluZy4gTWlycm9ycyB0aGVcbiAqIEhhbmRsZXJDb250ZXh0LmdldFBlcnNvbmFJbmRpY2F0b3IgcmVzcG9uc2liaWxpdHkgc28gaGFuZGxlcnMgY2FuIHJlbHkgb25cbiAqIGV4cGxpY2l0IGNvbnN0cnVjdG9yIGluamVjdGlvbiBpbnN0ZWFkIG9mIHRoZSBzZXJ2aWNlIGxvY2F0b3IgcGF0dGVybi5cbiAqL1xuZXhwb3J0IGNsYXNzIFBlcnNvbmFJbmRpY2F0b3JTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBjYWNoZWRJbmRpY2F0b3I6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGNhY2hlZFBlcnNvbmFJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgYm91bmRMaXN0ZW5lcj86IChldmVudDogUGVyc29uYVN0YXRlQ2hhbmdlRXZlbnQpID0+IHZvaWQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgYm91bmRFbGVtZW50TGlzdGVuZXI/OiAocGF5bG9hZDogRWxlbWVudEV2ZW50UGF5bG9hZCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBlbGVtZW50VW5zdWJzY3JpYmVzOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xuICBwcml2YXRlIGZhbGxiYWNrUHJvdmlkZXI/OiAoKSA9PiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBwZXJzb25hTWFuYWdlcjogUGVyc29uYU1hbmFnZXIsXG4gICAgcHJpdmF0ZSBpbmRpY2F0b3JDb25maWc6IEluZGljYXRvckNvbmZpZyxcbiAgICBwcml2YXRlIG5vdGlmaWVyPzogU3RhdGVDaGFuZ2VOb3RpZmllcixcbiAgICBwcml2YXRlIGV2ZW50RGlzcGF0Y2hlcj86IEVsZW1lbnRFdmVudERpc3BhdGNoZXJcbiAgKSB7XG4gICAgaWYgKHRoaXMubm90aWZpZXIpIHtcbiAgICAgIHRoaXMuYm91bmRMaXN0ZW5lciA9IHRoaXMuaGFuZGxlUGVyc29uYUNoYW5nZS5iaW5kKHRoaXMpO1xuICAgICAgdGhpcy5ub3RpZmllci5vbignc3RhdGUtY2hhbmdlOnBlcnNvbmEtYWN0aXZhdGVkJywgdGhpcy5ib3VuZExpc3RlbmVyKTtcbiAgICAgIHRoaXMubm90aWZpZXIub24oJ3N0YXRlLWNoYW5nZTpwZXJzb25hLWRlYWN0aXZhdGVkJywgdGhpcy5ib3VuZExpc3RlbmVyKTtcbiAgICAgIHRoaXMubm90aWZpZXIub24oJ3N0YXRlLWNoYW5nZTp1c2VyLWNoYW5nZWQnLCB0aGlzLmJvdW5kTGlzdGVuZXIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmV2ZW50RGlzcGF0Y2hlcikge1xuICAgICAgdGhpcy5ib3VuZEVsZW1lbnRMaXN0ZW5lciA9IHRoaXMuaGFuZGxlRWxlbWVudEV2ZW50LmJpbmQodGhpcyk7XG4gICAgICB0aGlzLmVsZW1lbnRVbnN1YnNjcmliZXMucHVzaChcbiAgICAgICAgdGhpcy5ldmVudERpc3BhdGNoZXIub24oJ2VsZW1lbnQ6YWN0aXZhdGUnLCB0aGlzLmJvdW5kRWxlbWVudExpc3RlbmVyKSxcbiAgICAgICAgdGhpcy5ldmVudERpc3BhdGNoZXIub24oJ2VsZW1lbnQ6ZGVhY3RpdmF0ZScsIHRoaXMuYm91bmRFbGVtZW50TGlzdGVuZXIpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGdldFBlcnNvbmFJbmRpY2F0b3IoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwZXJzb25hID0gdGhpcy5wZXJzb25hTWFuYWdlci5nZXRBY3RpdmVQZXJzb25hKCk7XG5cbiAgICBpZiAoIXBlcnNvbmEpIHtcbiAgICAgIHJldHVybiB0aGlzLmZhbGxiYWNrUHJvdmlkZXIgPyB0aGlzLmZhbGxiYWNrUHJvdmlkZXIoKSA6ICcnO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNhY2hlZEluZGljYXRvciAhPT0gbnVsbCAmJiB0aGlzLmNhY2hlZFBlcnNvbmFJZCA9PT0gcGVyc29uYS5maWxlbmFtZSkge1xuICAgICAgcmV0dXJuIHRoaXMuY2FjaGVkSW5kaWNhdG9yO1xuICAgIH1cblxuICAgIGNvbnN0IGluZGljYXRvciA9IGZvcm1hdEluZGljYXRvcih0aGlzLmluZGljYXRvckNvbmZpZywge1xuICAgICAgbmFtZTogcGVyc29uYS5tZXRhZGF0YS5uYW1lLFxuICAgICAgdmVyc2lvbjogcGVyc29uYS5tZXRhZGF0YS52ZXJzaW9uLFxuICAgICAgYXV0aG9yOiBwZXJzb25hLm1ldGFkYXRhLmF1dGhvcixcbiAgICAgIGNhdGVnb3J5OiBwZXJzb25hLm1ldGFkYXRhLmNhdGVnb3J5LFxuICAgIH0pO1xuXG4gICAgdGhpcy5jYWNoZWRJbmRpY2F0b3IgPSBpbmRpY2F0b3I7XG4gICAgdGhpcy5jYWNoZWRQZXJzb25hSWQgPSBwZXJzb25hLmZpbGVuYW1lO1xuICAgIHJldHVybiBpbmRpY2F0b3I7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IGluZGljYXRvciBjb25maWd1cmF0aW9uLlxuICAgKiBVc2VkIGJ5IENvbmZpZ0hhbmRsZXIgdG8gcmVhZCBjdXJyZW50IHNldHRpbmdzIGJlZm9yZSBhcHBseWluZyB1cGRhdGVzLlxuICAgKlxuICAgKiBAcmV0dXJucyBDdXJyZW50IEluZGljYXRvckNvbmZpZ1xuICAgKi9cbiAgZ2V0Q29uZmlnKCk6IEluZGljYXRvckNvbmZpZyB7XG4gICAgcmV0dXJuIHsgLi4udGhpcy5pbmRpY2F0b3JDb25maWcgfTtcbiAgfVxuXG4gIHVwZGF0ZUNvbmZpZyhjb25maWc6IEluZGljYXRvckNvbmZpZyk6IHZvaWQge1xuICAgIC8vIEZJWDogRE1DUC1TRUMtMDA2IC0gQWRkIHNlY3VyaXR5IGF1ZGl0IGxvZ2dpbmcgZm9yIGNvbmZpZ3VyYXRpb24gY2hhbmdlc1xuICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgIHR5cGU6ICdDT05GSUdfVVBEQVRFRCcsXG4gICAgICBzZXZlcml0eTogJ0xPVycsXG4gICAgICBzb3VyY2U6ICdQZXJzb25hSW5kaWNhdG9yU2VydmljZS51cGRhdGVDb25maWcnLFxuICAgICAgZGV0YWlsczogYEluZGljYXRvciBjb25maWd1cmF0aW9uIHVwZGF0ZWQ6IHN0eWxlPSR7Y29uZmlnLnN0eWxlfSwgZW5hYmxlZD0ke2NvbmZpZy5lbmFibGVkfWAsXG4gICAgICBhZGRpdGlvbmFsRGF0YToge1xuICAgICAgICBzdHlsZTogY29uZmlnLnN0eWxlLFxuICAgICAgICBlbmFibGVkOiBjb25maWcuZW5hYmxlZCxcbiAgICAgICAgc2hvd1ZlcnNpb246IGNvbmZpZy5zaG93VmVyc2lvbixcbiAgICAgICAgc2hvd0F1dGhvcjogY29uZmlnLnNob3dBdXRob3JcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuaW5kaWNhdG9yQ29uZmlnID0gY29uZmlnO1xuICAgIHRoaXMuaW52YWxpZGF0ZUNhY2hlKCk7XG4gIH1cblxuICBzZXRGYWxsYmFja1Byb3ZpZGVyKHByb3ZpZGVyPzogKCkgPT4gc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5mYWxsYmFja1Byb3ZpZGVyID0gcHJvdmlkZXI7XG4gICAgdGhpcy5pbnZhbGlkYXRlQ2FjaGUoKTtcbiAgfVxuXG4gIGludmFsaWRhdGVDYWNoZSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhY2hlZEluZGljYXRvciA9IG51bGw7XG4gICAgdGhpcy5jYWNoZWRQZXJzb25hSWQgPSBudWxsO1xuICB9XG5cbiAgYXN5bmMgZGlzcG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5ib3VuZExpc3RlbmVyICYmIHRoaXMubm90aWZpZXIpIHtcbiAgICAgIHRoaXMubm90aWZpZXIub2ZmKCdzdGF0ZS1jaGFuZ2U6cGVyc29uYS1hY3RpdmF0ZWQnLCB0aGlzLmJvdW5kTGlzdGVuZXIpO1xuICAgICAgdGhpcy5ub3RpZmllci5vZmYoJ3N0YXRlLWNoYW5nZTpwZXJzb25hLWRlYWN0aXZhdGVkJywgdGhpcy5ib3VuZExpc3RlbmVyKTtcbiAgICAgIHRoaXMubm90aWZpZXIub2ZmKCdzdGF0ZS1jaGFuZ2U6dXNlci1jaGFuZ2VkJywgdGhpcy5ib3VuZExpc3RlbmVyKTtcbiAgICB9XG4gICAgd2hpbGUgKHRoaXMuZWxlbWVudFVuc3Vic2NyaWJlcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB1bnN1YnNjcmliZSA9IHRoaXMuZWxlbWVudFVuc3Vic2NyaWJlcy5wb3AoKTtcbiAgICAgIGlmICh1bnN1YnNjcmliZSkge1xuICAgICAgICB1bnN1YnNjcmliZSgpO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmludmFsaWRhdGVDYWNoZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVQZXJzb25hQ2hhbmdlKF9ldmVudDogUGVyc29uYVN0YXRlQ2hhbmdlRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmludmFsaWRhdGVDYWNoZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVFbGVtZW50RXZlbnQocGF5bG9hZDogRWxlbWVudEV2ZW50UGF5bG9hZCk6IHZvaWQge1xuICAgIGlmIChwYXlsb2FkLmVsZW1lbnRUeXBlICE9PSBFbGVtZW50VHlwZS5QRVJTT05BKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuaW52YWxpZGF0ZUNhY2hlKCk7XG4gIH1cbn1cbiJdfQ==