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.

79 lines 9.82 kB
/** * Shared element type normalization utilities. * * Provides a single canonical mapping from both singular and plural * element type names to ElementType enum values. All code paths that * accept user-provided element type strings should use these utilities * to ensure consistent behaviour. * * Issue #433 - Singular element type names rejected in search/portfolio operations */ import { ElementType } from '../portfolio/types.js'; /** * Canonical mapping from user-facing type strings (singular and plural) * to ElementType enum values. Keys are lowercase. */ export const ELEMENT_TYPE_MAP = { // Singular forms persona: ElementType.PERSONA, skill: ElementType.SKILL, template: ElementType.TEMPLATE, agent: ElementType.AGENT, memory: ElementType.MEMORY, ensemble: ElementType.ENSEMBLE, // Plural forms (canonical enum values) personas: ElementType.PERSONA, skills: ElementType.SKILL, templates: ElementType.TEMPLATE, agents: ElementType.AGENT, memories: ElementType.MEMORY, ensembles: ElementType.ENSEMBLE, }; /** All canonical ElementType values (plural forms). */ export const ALL_ELEMENT_TYPES = Object.values(ElementType); // Runtime validation: every ElementType enum value must appear as a value in ELEMENT_TYPE_MAP. // Catches cases where a new ElementType is added to the enum but the map is not updated. for (const enumValue of ALL_ELEMENT_TYPES) { const mappedValues = Object.values(ELEMENT_TYPE_MAP); if (!mappedValues.includes(enumValue)) { throw new Error(`elementTypeNormalization: ElementType '${enumValue}' is missing from ELEMENT_TYPE_MAP. ` + `Update ELEMENT_TYPE_MAP to include both singular and plural entries for this type.`); } } /** Singular labels for each ElementType. */ export const SINGULAR_LABELS = { [ElementType.PERSONA]: 'persona', [ElementType.SKILL]: 'skill', [ElementType.TEMPLATE]: 'template', [ElementType.AGENT]: 'agent', [ElementType.MEMORY]: 'memory', [ElementType.ENSEMBLE]: 'ensemble', }; /** * Convert an ElementType enum value to its singular label. * e.g. ElementType.PERSONA ("personas") → "persona" */ export function toSingularLabel(type) { return SINGULAR_LABELS[type] ?? type; } /** * Normalize a user-provided element type string to an ElementType enum value. * * Accepts both singular (`"memory"`) and plural (`"memories"`) forms, * case-insensitively. Returns `null` for unrecognised input. */ export function normalizeElementType(input) { if (!input || typeof input !== 'string') { return null; } return ELEMENT_TYPE_MAP[input.trim().toLowerCase()] ?? null; } /** * Format a human-readable list of valid element types for error messages. */ export function formatElementTypesList() { const singularList = Object.values(SINGULAR_LABELS).join(', '); const pluralList = ALL_ELEMENT_TYPES.join(', '); return `${singularList} (plural forms also accepted: ${pluralList})`; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudFR5cGVOb3JtYWxpemF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL2VsZW1lbnRUeXBlTm9ybWFsaXphdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7O0dBU0c7QUFFSCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFcEQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQWdDO0lBQzNELGlCQUFpQjtJQUNqQixPQUFPLEVBQUUsV0FBVyxDQUFDLE9BQU87SUFDNUIsS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLO0lBQ3hCLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUTtJQUM5QixLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUs7SUFDeEIsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNO0lBQzFCLFFBQVEsRUFBRSxXQUFXLENBQUMsUUFBUTtJQUM5Qix1Q0FBdUM7SUFDdkMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxPQUFPO0lBQzdCLE1BQU0sRUFBRSxXQUFXLENBQUMsS0FBSztJQUN6QixTQUFTLEVBQUUsV0FBVyxDQUFDLFFBQVE7SUFDL0IsTUFBTSxFQUFFLFdBQVcsQ0FBQyxLQUFLO0lBQ3pCLFFBQVEsRUFBRSxXQUFXLENBQUMsTUFBTTtJQUM1QixTQUFTLEVBQUUsV0FBVyxDQUFDLFFBQVE7Q0FDaEMsQ0FBQztBQUVGLHVEQUF1RDtBQUN2RCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBa0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUUzRSwrRkFBK0Y7QUFDL0YseUZBQXlGO0FBQ3pGLEtBQUssTUFBTSxTQUFTLElBQUksaUJBQWlCLEVBQUUsQ0FBQztJQUMxQyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDckQsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztRQUN0QyxNQUFNLElBQUksS0FBSyxDQUNiLDBDQUEwQyxTQUFTLHNDQUFzQztZQUN6RixvRkFBb0YsQ0FDckYsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDO0FBRUQsNENBQTRDO0FBQzVDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBZ0M7SUFDMUQsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLEVBQUUsU0FBUztJQUNoQyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPO0lBQzVCLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFVBQVU7SUFDbEMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTztJQUM1QixDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsRUFBRSxRQUFRO0lBQzlCLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFVBQVU7Q0FDbkMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsSUFBaUI7SUFDL0MsT0FBTyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxLQUFnQztJQUNuRSxJQUFJLENBQUMsS0FBSyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sZ0JBQWdCLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksSUFBSSxDQUFDO0FBQzlELENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sVUFBVSxzQkFBc0I7SUFDcEMsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0QsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hELE9BQU8sR0FBRyxZQUFZLGlDQUFpQyxVQUFVLEdBQUcsQ0FBQztBQUN2RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTaGFyZWQgZWxlbWVudCB0eXBlIG5vcm1hbGl6YXRpb24gdXRpbGl0aWVzLlxuICpcbiAqIFByb3ZpZGVzIGEgc2luZ2xlIGNhbm9uaWNhbCBtYXBwaW5nIGZyb20gYm90aCBzaW5ndWxhciBhbmQgcGx1cmFsXG4gKiBlbGVtZW50IHR5cGUgbmFtZXMgdG8gRWxlbWVudFR5cGUgZW51bSB2YWx1ZXMuIEFsbCBjb2RlIHBhdGhzIHRoYXRcbiAqIGFjY2VwdCB1c2VyLXByb3ZpZGVkIGVsZW1lbnQgdHlwZSBzdHJpbmdzIHNob3VsZCB1c2UgdGhlc2UgdXRpbGl0aWVzXG4gKiB0byBlbnN1cmUgY29uc2lzdGVudCBiZWhhdmlvdXIuXG4gKlxuICogSXNzdWUgIzQzMyAtIFNpbmd1bGFyIGVsZW1lbnQgdHlwZSBuYW1lcyByZWplY3RlZCBpbiBzZWFyY2gvcG9ydGZvbGlvIG9wZXJhdGlvbnNcbiAqL1xuXG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uL3BvcnRmb2xpby90eXBlcy5qcyc7XG5cbi8qKlxuICogQ2Fub25pY2FsIG1hcHBpbmcgZnJvbSB1c2VyLWZhY2luZyB0eXBlIHN0cmluZ3MgKHNpbmd1bGFyIGFuZCBwbHVyYWwpXG4gKiB0byBFbGVtZW50VHlwZSBlbnVtIHZhbHVlcy4gS2V5cyBhcmUgbG93ZXJjYXNlLlxuICovXG5leHBvcnQgY29uc3QgRUxFTUVOVF9UWVBFX01BUDogUmVjb3JkPHN0cmluZywgRWxlbWVudFR5cGU+ID0ge1xuICAvLyBTaW5ndWxhciBmb3Jtc1xuICBwZXJzb25hOiBFbGVtZW50VHlwZS5QRVJTT05BLFxuICBza2lsbDogRWxlbWVudFR5cGUuU0tJTEwsXG4gIHRlbXBsYXRlOiBFbGVtZW50VHlwZS5URU1QTEFURSxcbiAgYWdlbnQ6IEVsZW1lbnRUeXBlLkFHRU5ULFxuICBtZW1vcnk6IEVsZW1lbnRUeXBlLk1FTU9SWSxcbiAgZW5zZW1ibGU6IEVsZW1lbnRUeXBlLkVOU0VNQkxFLFxuICAvLyBQbHVyYWwgZm9ybXMgKGNhbm9uaWNhbCBlbnVtIHZhbHVlcylcbiAgcGVyc29uYXM6IEVsZW1lbnRUeXBlLlBFUlNPTkEsXG4gIHNraWxsczogRWxlbWVudFR5cGUuU0tJTEwsXG4gIHRlbXBsYXRlczogRWxlbWVudFR5cGUuVEVNUExBVEUsXG4gIGFnZW50czogRWxlbWVudFR5cGUuQUdFTlQsXG4gIG1lbW9yaWVzOiBFbGVtZW50VHlwZS5NRU1PUlksXG4gIGVuc2VtYmxlczogRWxlbWVudFR5cGUuRU5TRU1CTEUsXG59O1xuXG4vKiogQWxsIGNhbm9uaWNhbCBFbGVtZW50VHlwZSB2YWx1ZXMgKHBsdXJhbCBmb3JtcykuICovXG5leHBvcnQgY29uc3QgQUxMX0VMRU1FTlRfVFlQRVM6IEVsZW1lbnRUeXBlW10gPSBPYmplY3QudmFsdWVzKEVsZW1lbnRUeXBlKTtcblxuLy8gUnVudGltZSB2YWxpZGF0aW9uOiBldmVyeSBFbGVtZW50VHlwZSBlbnVtIHZhbHVlIG11c3QgYXBwZWFyIGFzIGEgdmFsdWUgaW4gRUxFTUVOVF9UWVBFX01BUC5cbi8vIENhdGNoZXMgY2FzZXMgd2hlcmUgYSBuZXcgRWxlbWVudFR5cGUgaXMgYWRkZWQgdG8gdGhlIGVudW0gYnV0IHRoZSBtYXAgaXMgbm90IHVwZGF0ZWQuXG5mb3IgKGNvbnN0IGVudW1WYWx1ZSBvZiBBTExfRUxFTUVOVF9UWVBFUykge1xuICBjb25zdCBtYXBwZWRWYWx1ZXMgPSBPYmplY3QudmFsdWVzKEVMRU1FTlRfVFlQRV9NQVApO1xuICBpZiAoIW1hcHBlZFZhbHVlcy5pbmNsdWRlcyhlbnVtVmFsdWUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYGVsZW1lbnRUeXBlTm9ybWFsaXphdGlvbjogRWxlbWVudFR5cGUgJyR7ZW51bVZhbHVlfScgaXMgbWlzc2luZyBmcm9tIEVMRU1FTlRfVFlQRV9NQVAuIGAgK1xuICAgICAgYFVwZGF0ZSBFTEVNRU5UX1RZUEVfTUFQIHRvIGluY2x1ZGUgYm90aCBzaW5ndWxhciBhbmQgcGx1cmFsIGVudHJpZXMgZm9yIHRoaXMgdHlwZS5gXG4gICAgKTtcbiAgfVxufVxuXG4vKiogU2luZ3VsYXIgbGFiZWxzIGZvciBlYWNoIEVsZW1lbnRUeXBlLiAqL1xuZXhwb3J0IGNvbnN0IFNJTkdVTEFSX0xBQkVMUzogUmVjb3JkPEVsZW1lbnRUeXBlLCBzdHJpbmc+ID0ge1xuICBbRWxlbWVudFR5cGUuUEVSU09OQV06ICdwZXJzb25hJyxcbiAgW0VsZW1lbnRUeXBlLlNLSUxMXTogJ3NraWxsJyxcbiAgW0VsZW1lbnRUeXBlLlRFTVBMQVRFXTogJ3RlbXBsYXRlJyxcbiAgW0VsZW1lbnRUeXBlLkFHRU5UXTogJ2FnZW50JyxcbiAgW0VsZW1lbnRUeXBlLk1FTU9SWV06ICdtZW1vcnknLFxuICBbRWxlbWVudFR5cGUuRU5TRU1CTEVdOiAnZW5zZW1ibGUnLFxufTtcblxuLyoqXG4gKiBDb252ZXJ0IGFuIEVsZW1lbnRUeXBlIGVudW0gdmFsdWUgdG8gaXRzIHNpbmd1bGFyIGxhYmVsLlxuICogZS5nLiBFbGVtZW50VHlwZS5QRVJTT05BIChcInBlcnNvbmFzXCIpIOKGkiBcInBlcnNvbmFcIlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TaW5ndWxhckxhYmVsKHR5cGU6IEVsZW1lbnRUeXBlKTogc3RyaW5nIHtcbiAgcmV0dXJuIFNJTkdVTEFSX0xBQkVMU1t0eXBlXSA/PyB0eXBlO1xufVxuXG4vKipcbiAqIE5vcm1hbGl6ZSBhIHVzZXItcHJvdmlkZWQgZWxlbWVudCB0eXBlIHN0cmluZyB0byBhbiBFbGVtZW50VHlwZSBlbnVtIHZhbHVlLlxuICpcbiAqIEFjY2VwdHMgYm90aCBzaW5ndWxhciAoYFwibWVtb3J5XCJgKSBhbmQgcGx1cmFsIChgXCJtZW1vcmllc1wiYCkgZm9ybXMsXG4gKiBjYXNlLWluc2Vuc2l0aXZlbHkuIFJldHVybnMgYG51bGxgIGZvciB1bnJlY29nbmlzZWQgaW5wdXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVFbGVtZW50VHlwZShpbnB1dDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IEVsZW1lbnRUeXBlIHwgbnVsbCB7XG4gIGlmICghaW5wdXQgfHwgdHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHJldHVybiBFTEVNRU5UX1RZUEVfTUFQW2lucHV0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXSA/PyBudWxsO1xufVxuXG4vKipcbiAqIEZvcm1hdCBhIGh1bWFuLXJlYWRhYmxlIGxpc3Qgb2YgdmFsaWQgZWxlbWVudCB0eXBlcyBmb3IgZXJyb3IgbWVzc2FnZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXRFbGVtZW50VHlwZXNMaXN0KCk6IHN0cmluZyB7XG4gIGNvbnN0IHNpbmd1bGFyTGlzdCA9IE9iamVjdC52YWx1ZXMoU0lOR1VMQVJfTEFCRUxTKS5qb2luKCcsICcpO1xuICBjb25zdCBwbHVyYWxMaXN0ID0gQUxMX0VMRU1FTlRfVFlQRVMuam9pbignLCAnKTtcbiAgcmV0dXJuIGAke3Npbmd1bGFyTGlzdH0gKHBsdXJhbCBmb3JtcyBhbHNvIGFjY2VwdGVkOiAke3BsdXJhbExpc3R9KWA7XG59XG4iXX0=