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.

101 lines 16 kB
/** * Element Type Resolver - Shared utility for resolving missing element_type * fields by searching the portfolio across all element managers. * * Used by any composite element type (ensembles, and future types like * teams, workflows, pipelines) that references other elements. * * Issue #466: Replaces the silent '|| skill' default with portfolio lookup. */ import { logger } from './logger.js'; import { ELEMENT_TYPE_MAP } from './elementTypeNormalization.js'; /** * Resolve missing element_type fields by searching the portfolio. * * For each element without an element_type (or legacy type field), searches * all provided managers to find which type the element belongs to. * * Resolution outcomes: * - Found in exactly 1 type → element_type is set automatically * - Found in multiple types → element is skipped with ambiguity warning * - Not found in any type → element is skipped with not-found warning * - Already has element_type → passed through unchanged * * @param elements - Raw element array (may have missing element_type) * @param managers - Available element managers for portfolio lookup * @returns Structured result with resolved elements and disambiguation info */ export async function resolveElementTypes(elements, managers) { const resolved = []; const ambiguous = []; const notFound = []; for (let i = 0; i < elements.length; i++) { const elem = elements[i]; // Issue #507: Guard against non-object elements (e.g., bare strings like "my-skill") if (typeof elem !== 'object' || elem === null) { const valueType = elem === null ? 'null' : typeof elem; logger.warn(`[resolveElementTypes] Element at index ${i} is a ${valueType} ("${String(elem).substring(0, 50)}"), ` + `but must be an object with { element_name, element_type }. Skipping.`); notFound.push(String(elem)); continue; } const elementName = elem.element_name || elem.name; const elementType = elem.element_type || elem.type; if (elementType || !elementName) { // Type is already known, or no name to search for — pass through as-is resolved.push(elem); continue; } // Search all managers for this element name const typeMap = [ ['skill', managers.skillManager], ['template', managers.templateManager], ['agent', managers.agentManager], ['memory', managers.memoryManager], ['persona', managers.personaManager], ['ensemble', managers.ensembleManager], ]; const matches = []; for (const [typeName, manager] of typeMap) { if (!manager) continue; try { if (typeName === 'persona' && manager.findPersona) { const found = manager.findPersona(elementName); if (found) matches.push(typeName); } else if (manager.findByName) { const found = await manager.findByName(elementName); if (found) matches.push(typeName); } } catch { // Manager lookup failed — skip this type silently } } if (matches.length === 1) { const resolvedType = matches[0]; // Validate the resolved type against the canonical element type map if (!(resolvedType in ELEMENT_TYPE_MAP)) { logger.warn(`[resolveElementTypes] Element '${elementName}': resolved to unrecognized type '${resolvedType}'. Skipping element.`); notFound.push(elementName); continue; } resolved.push({ ...elem, element_type: resolvedType }); } else if (matches.length > 1) { ambiguous.push({ element_name: elementName, found_in: [...matches] }); logger.warn(`[resolveElementTypes] Element '${elementName}': found in multiple types (${matches.join(', ')}). ` + `Provide element_type explicitly. Skipping element.`); } else { notFound.push(elementName); logger.warn(`[resolveElementTypes] Element '${elementName}': not found in any element type. ` + `Provide element_type explicitly or ensure the element exists in the portfolio. Skipping element.`); } } return { resolved, ambiguous, notFound }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudFR5cGVSZXNvbHZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9lbGVtZW50VHlwZVJlc29sdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQStCakU7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxtQkFBbUIsQ0FDdkMsUUFBZSxFQUNmLFFBQXNDO0lBRXRDLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNwQixNQUFNLFNBQVMsR0FBd0QsRUFBRSxDQUFDO0lBQzFFLE1BQU0sUUFBUSxHQUFhLEVBQUUsQ0FBQztJQUU5QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV6QixxRkFBcUY7UUFDckYsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzlDLE1BQU0sU0FBUyxHQUFHLElBQUksS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUM7WUFDdkQsTUFBTSxDQUFDLElBQUksQ0FDVCwwQ0FBMEMsQ0FBQyxTQUFTLFNBQVMsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTTtnQkFDdEcsc0VBQXNFLENBQ3ZFLENBQUM7WUFDRixRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lB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Q1Qsa0NBQWtDLFdBQVcsb0NBQW9DO2dCQUNqRixrR0FBa0csQ0FDbkcsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLENBQUM7QUFDM0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRWxlbWVudCBUeXBlIFJlc29sdmVyIC0gU2hhcmVkIHV0aWxpdHkgZm9yIHJlc29sdmluZyBtaXNzaW5nIGVsZW1lbnRfdHlwZVxuICogZmllbGRzIGJ5IHNlYXJjaGluZyB0aGUgcG9ydGZvbGlvIGFjcm9zcyBhbGwgZWxlbWVudCBtYW5hZ2Vycy5cbiAqXG4gKiBVc2VkIGJ5IGFueSBjb21wb3NpdGUgZWxlbWVudCB0eXBlIChlbnNlbWJsZXMsIGFuZCBmdXR1cmUgdHlwZXMgbGlrZVxuICogdGVhbXMsIHdvcmtmbG93cywgcGlwZWxpbmVzKSB0aGF0IHJlZmVyZW5jZXMgb3RoZXIgZWxlbWVudHMuXG4gKlxuICogSXNzdWUgIzQ2NjogUmVwbGFjZXMgdGhlIHNpbGVudCAnfHwgc2tpbGwnIGRlZmF1bHQgd2l0aCBwb3J0Zm9saW8gbG9va3VwLlxuICovXG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IEVMRU1FTlRfVFlQRV9NQVAgfSBmcm9tICcuL2VsZW1lbnRUeXBlTm9ybWFsaXphdGlvbi5qcyc7XG5cbi8qKlxuICogSW50ZXJmYWNlIGZvciBtYW5hZ2VycyBwYXNzZWQgdG8gcmVzb2x2ZUVsZW1lbnRUeXBlcygpLlxuICogRWFjaCBtYW5hZ2VyIGlzIG9wdGlvbmFsIOKAlCBvbmx5IGF2YWlsYWJsZSBtYW5hZ2VycyBhcmUgc2VhcmNoZWQuXG4gKlxuICogUGVyc29uYU1hbmFnZXIgdXNlcyBmaW5kUGVyc29uYSgpIChzeW5jaHJvbm91cykgaW5zdGVhZCBvZiB0aGUgc3RhbmRhcmRcbiAqIGZpbmRCeU5hbWUoKSDigJQgYm90aCBhcmUgc3VwcG9ydGVkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVsZW1lbnRNYW5hZ2Vyc0ZvclJlc29sdXRpb24ge1xuICBza2lsbE1hbmFnZXI/OiB7IGZpbmRCeU5hbWUobmFtZTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IH07XG4gIHRlbXBsYXRlTWFuYWdlcj86IHsgZmluZEJ5TmFtZShuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGFueT4gfTtcbiAgYWdlbnRNYW5hZ2VyPzogeyBmaW5kQnlOYW1lKG5hbWU6IHN0cmluZyk6IFByb21pc2U8YW55PiB9O1xuICBtZW1vcnlNYW5hZ2VyPzogeyBmaW5kQnlOYW1lKG5hbWU6IHN0cmluZyk6IFByb21pc2U8YW55PiB9O1xuICBwZXJzb25hTWFuYWdlcj86IHsgZmluZFBlcnNvbmE/KG5hbWU6IHN0cmluZyk6IGFueSB9O1xuICBlbnNlbWJsZU1hbmFnZXI/OiB7IGZpbmRCeU5hbWUobmFtZTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IH07XG59XG5cbi8qKlxuICogU3RydWN0dXJlZCByZXN1bHQgZnJvbSByZXNvbHZlRWxlbWVudFR5cGVzKCkuXG4gKiBDYWxsZXJzIGNhbiBpbnNwZWN0IGFtYmlndW91cy9ub3RGb3VuZCB0byBzdXJmYWNlIHdhcm5pbmdzIHRvIHRoZSB1c2VyLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVFbGVtZW50VHlwZXNSZXN1bHQge1xuICAvKiogRWxlbWVudHMgc3VjY2Vzc2Z1bGx5IHJlc29sdmVkIG9yIGFscmVhZHkgdHlwZWQgKi9cbiAgcmVzb2x2ZWQ6IGFueVtdO1xuICAvKiogRWxlbWVudHMgZm91bmQgaW4gbXVsdGlwbGUgdHlwZXMg4oCUIHVzZXIgbXVzdCBwcm92aWRlIGVsZW1lbnRfdHlwZSAqL1xuICBhbWJpZ3VvdXM6IEFycmF5PHsgZWxlbWVudF9uYW1lOiBzdHJpbmc7IGZvdW5kX2luOiBzdHJpbmdbXSB9PjtcbiAgLyoqIEVsZW1lbnQgbmFtZXMgbm90IGZvdW5kIGluIGFueSBtYW5hZ2VyICovXG4gIG5vdEZvdW5kOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIG1pc3NpbmcgZWxlbWVudF90eXBlIGZpZWxkcyBieSBzZWFyY2hpbmcgdGhlIHBvcnRmb2xpby5cbiAqXG4gKiBGb3IgZWFjaCBlbGVtZW50IHdpdGhvdXQgYW4gZWxlbWVudF90eXBlIChvciBsZWdhY3kgdHlwZSBmaWVsZCksIHNlYXJjaGVzXG4gKiBhbGwgcHJvdmlkZWQgbWFuYWdlcnMgdG8gZmluZCB3aGljaCB0eXBlIHRoZSBlbGVtZW50IGJlbG9uZ3MgdG8uXG4gKlxuICogUmVzb2x1dGlvbiBvdXRjb21lczpcbiAqIC0gRm91bmQgaW4gZXhhY3RseSAxIHR5cGUg4oaSIGVsZW1lbnRfdHlwZSBpcyBzZXQgYXV0b21hdGljYWxseVxuICogLSBGb3VuZCBpbiBtdWx0aXBsZSB0eXBlcyDihpIgZWxlbWVudCBpcyBza2lwcGVkIHdpdGggYW1iaWd1aXR5IHdhcm5pbmdcbiAqIC0gTm90IGZvdW5kIGluIGFueSB0eXBlIOKGkiBlbGVtZW50IGlzIHNraXBwZWQgd2l0aCBub3QtZm91bmQgd2FybmluZ1xuICogLSBBbHJlYWR5IGhhcyBlbGVtZW50X3R5cGUg4oaSIHBhc3NlZCB0aHJvdWdoIHVuY2hhbmdlZFxuICpcbiAqIEBwYXJhbSBlbGVtZW50cyAtIFJhdyBlbGVtZW50IGFycmF5IChtYXkgaGF2ZSBtaXNzaW5nIGVsZW1lbnRfdHlwZSlcbiAqIEBwYXJhbSBtYW5hZ2VycyAtIEF2YWlsYWJsZSBlbGVtZW50IG1hbmFnZXJzIGZvciBwb3J0Zm9saW8gbG9va3VwXG4gKiBAcmV0dXJucyBTdHJ1Y3R1cmVkIHJlc3VsdCB3aXRoIHJlc29sdmVkIGVsZW1lbnRzIGFuZCBkaXNhbWJpZ3VhdGlvbiBpbmZvXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlRWxlbWVudFR5cGVzKFxuICBlbGVtZW50czogYW55W10sXG4gIG1hbmFnZXJzOiBFbGVtZW50TWFuYWdlcnNGb3JSZXNvbHV0aW9uXG4pOiBQcm9taXNlPFJlc29sdmVFbGVtZW50VHlwZXNSZXN1bHQ+IHtcbiAgY29uc3QgcmVzb2x2ZWQgPSBbXTtcbiAgY29uc3QgYW1iaWd1b3VzOiBBcnJheTx7IGVsZW1lbnRfbmFtZTogc3RyaW5nOyBmb3VuZF9pbjogc3RyaW5nW10gfT4gPSBbXTtcbiAgY29uc3Qgbm90Rm91bmQ6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGVsZW0gPSBlbGVtZW50c1tpXTtcblxuICAgIC8vIElzc3VlICM1MDc6IEd1YXJkIGFnYWluc3Qgbm9uLW9iamVjdCBlbGVtZW50cyAoZS5nLiwgYmFyZSBzdHJpbmdzIGxpa2UgXCJteS1za2lsbFwiKVxuICAgIGlmICh0eXBlb2YgZWxlbSAhPT0gJ29iamVjdCcgfHwgZWxlbSA9PT0gbnVsbCkge1xuICAgICAgY29uc3QgdmFsdWVUeXBlID0gZWxlbSA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiBlbGVtO1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgIGBbcmVzb2x2ZUVsZW1lbnRUeXBlc10gRWxlbWVudCBhdCBpbmRleCAke2l9IGlzIGEgJHt2YWx1ZVR5cGV9IChcIiR7U3RyaW5nKGVsZW0pLnN1YnN0cmluZygwLCA1MCl9XCIpLCBgICtcbiAgICAgICAgYGJ1dCBtdXN0IGJlIGFuIG9iamVjdCB3aXRoIHsgZWxlbWVudF9uYW1lLCBlbGVtZW50X3R5cGUgfS4gU2tpcHBpbmcuYFxuICAgICAgKTtcbiAgICAgIG5vdEZvdW5kLnB1c2goU3RyaW5nKGVsZW0pKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnROYW1lID0gZWxlbS5lbGVtZW50X25hbWUgfHwgZWxlbS5uYW1lO1xuICAgIGNvbnN0IGVsZW1lbnRUeXBlID0gZWxlbS5lbGVtZW50X3R5cGUgfHwgZWxlbS50eXBlO1xuXG4gICAgaWYgKGVsZW1lbnRUeXBlIHx8ICFlbGVtZW50TmFtZSkge1xuICAgICAgLy8gVHlwZSBpcyBhbHJlYWR5IGtub3duLCBvciBubyBuYW1lIHRvIHNlYXJjaCBmb3Ig4oCUIHBhc3MgdGhyb3VnaCBhcy1pc1xuICAgICAgcmVzb2x2ZWQucHVzaChlbGVtKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIC8vIFNlYXJjaCBhbGwgbWFuYWdlcnMgZm9yIHRoaXMgZWxlbWVudCBuYW1lXG4gICAgY29uc3QgdHlwZU1hcDogW3N0cmluZywgYW55XVtdID0gW1xuICAgICAgWydza2lsbCcsIG1hbmFnZXJzLnNraWxsTWFuYWdlcl0sXG4gICAgICBbJ3RlbXBsYXRlJywgbWFuYWdlcnMudGVtcGxhdGVNYW5hZ2VyXSxcbiAgICAgIFsnYWdlbnQnLCBtYW5hZ2Vycy5hZ2VudE1hbmFnZXJdLFxuICAgICAgWydtZW1vcnknLCBtYW5hZ2Vycy5tZW1vcnlNYW5hZ2VyXSxcbiAgICAgIFsncGVyc29uYScsIG1hbmFnZXJzLnBlcnNvbmFNYW5hZ2VyXSxcbiAgICAgIFsnZW5zZW1ibGUnLCBtYW5hZ2Vycy5lbnNlbWJsZU1hbmFnZXJdLFxuICAgIF07XG5cbiAgICBjb25zdCBtYXRjaGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW3R5cGVOYW1lLCBtYW5hZ2VyXSBvZiB0eXBlTWFwKSB7XG4gICAgICBpZiAoIW1hbmFnZXIpIGNvbnRpbnVlO1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKHR5cGVOYW1lID09PSAncGVyc29uYScgJiYgbWFuYWdlci5maW5kUGVyc29uYSkge1xuICAgICAgICAgIGNvbnN0IGZvdW5kID0gbWFuYWdlci5maW5kUGVyc29uYShlbGVtZW50TmFtZSk7XG4gICAgICAgICAgaWYgKGZvdW5kKSBtYXRjaGVzLnB1c2godHlwZU5hbWUpO1xuICAgICAgICB9IGVsc2UgaWYgKG1hbmFnZXIuZmluZEJ5TmFtZSkge1xuICAgICAgICAgIGNvbnN0IGZvdW5kID0gYXdhaXQgbWFuYWdlci5maW5kQnlOYW1lKGVsZW1lbnROYW1lKTtcbiAgICAgICAgICBpZiAoZm91bmQpIG1hdGNoZXMucHVzaCh0eXBlTmFtZSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBNYW5hZ2VyIGxvb2t1cCBmYWlsZWQg4oCUIHNraXAgdGhpcyB0eXBlIHNpbGVudGx5XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1hdGNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICBjb25zdCByZXNvbHZlZFR5cGUgPSBtYXRjaGVzWzBdO1xuICAgICAgLy8gVmFsaWRhdGUgdGhlIHJlc29sdmVkIHR5cGUgYWdhaW5zdCB0aGUgY2Fub25pY2FsIGVsZW1lbnQgdHlwZSBtYXBcbiAgICAgIGlmICghKHJlc29sdmVkVHlwZSBpbiBFTEVNRU5UX1RZUEVfTUFQKSkge1xuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgW3Jlc29sdmVFbGVtZW50VHlwZXNdIEVsZW1lbnQgJyR7ZWxlbWVudE5hbWV9JzogcmVzb2x2ZWQgdG8gdW5yZWNvZ25pemVkIHR5cGUgJyR7cmVzb2x2ZWRUeXBlfScuIFNraXBwaW5nIGVsZW1lbnQuYFxuICAgICAgICApO1xuICAgICAgICBub3RGb3VuZC5wdXNoKGVsZW1lbnROYW1lKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZXNvbHZlZC5wdXNoKHsgLi4uZWxlbSwgZWxlbWVudF90eXBlOiByZXNvbHZlZFR5cGUgfSk7XG4gICAgfSBlbHNlIGlmIChtYXRjaGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGFtYmlndW91cy5wdXNoKHsgZWxlbWVudF9uYW1lOiBlbGVtZW50TmFtZSwgZm91bmRfaW46IFsuLi5tYXRjaGVzXSB9KTtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgW3Jlc29sdmVFbGVtZW50VHlwZXNdIEVsZW1lbnQgJyR7ZWxlbWVudE5hbWV9JzogZm91bmQgaW4gbXVsdGlwbGUgdHlwZXMgKCR7bWF0Y2hlcy5qb2luKCcsICcpfSkuIGAgK1xuICAgICAgICBgUHJvdmlkZSBlbGVtZW50X3R5cGUgZXhwbGljaXRseS4gU2tpcHBpbmcgZWxlbWVudC5gXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBub3RGb3VuZC5wdXNoKGVsZW1lbnROYW1lKTtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgW3Jlc29sdmVFbGVtZW50VHlwZXNdIEVsZW1lbnQgJyR7ZWxlbWVudE5hbWV9Jzogbm90IGZvdW5kIGluIGFueSBlbGVtZW50IHR5cGUuIGAgK1xuICAgICAgICBgUHJvdmlkZSBlbGVtZW50X3R5cGUgZXhwbGljaXRseSBvciBlbnN1cmUgdGhlIGVsZW1lbnQgZXhpc3RzIGluIHRoZSBwb3J0Zm9saW8uIFNraXBwaW5nIGVsZW1lbnQuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyByZXNvbHZlZCwgYW1iaWd1b3VzLCBub3RGb3VuZCB9O1xufVxuIl19