@eldrex/personas
Advanced tools
+116
-155
@@ -66,3 +66,6 @@ "use strict"; | ||
| if (!persona.emoji_usage) { | ||
| result = result.replace(/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, ""); | ||
| result = result.replace( | ||
| /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, | ||
| "" | ||
| ); | ||
| } | ||
@@ -78,157 +81,111 @@ if (persona.verbosity === 1) { | ||
| // src/built-in/developer.ts | ||
| var developer = { | ||
| id: "developer", | ||
| name: "Developer", | ||
| description: "Technical, precise, code-focused", | ||
| tone: "technical", | ||
| verbosity: 3, | ||
| focus: ["code_changes", "architecture", "breaking_changes", "dependencies"], | ||
| ignore: ["business_impact", "revenue", "marketing"], | ||
| format_preference: "bullets", | ||
| emoji_usage: true, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a senior developer reviewing code changes. | ||
| Be technical and precise. Use code snippets. Focus on architecture decisions. | ||
| Highlight breaking changes and migration paths. Use developer terminology.` | ||
| // src/built-in.ts | ||
| var BUILTIN_PERSONAS = { | ||
| developer: { | ||
| id: "developer", | ||
| name: "Developer", | ||
| description: "Technical, precise, code-focused", | ||
| tone: "technical", | ||
| verbosity: 3, | ||
| focus: ["code_changes", "architecture", "breaking_changes"], | ||
| ignore: ["business_impact", "revenue", "marketing"], | ||
| format_preference: "bullets", | ||
| emoji_usage: true, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a senior developer reviewing code changes. Be technical and precise." | ||
| }, | ||
| ceo: { | ||
| id: "ceo", | ||
| name: "CEO", | ||
| description: "Executive summary, business-focused", | ||
| tone: "executive", | ||
| verbosity: 1, | ||
| focus: ["business_impact", "timeline", "risk"], | ||
| ignore: ["code_changes", "dependencies"], | ||
| format_preference: "bullets", | ||
| emoji_usage: false, | ||
| jargon_level: "none", | ||
| system_prompt: "You are a CEO reading a technical update. 3 bullet points maximum. No jargon." | ||
| }, | ||
| educator: { | ||
| id: "educator", | ||
| name: "Educator", | ||
| description: "Educational, patient, explanatory", | ||
| tone: "educational", | ||
| verbosity: 5, | ||
| focus: ["learning_points", "patterns", "best_practices"], | ||
| ignore: ["internal_details"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: "You are an educator explaining changes to learners. Be thorough and patient." | ||
| }, | ||
| robot: { | ||
| id: "robot", | ||
| name: "Robot", | ||
| description: "Structured data, no opinions", | ||
| tone: "robotic", | ||
| verbosity: 1, | ||
| focus: ["facts", "metrics", "files_changed"], | ||
| ignore: ["commentary", "opinions"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a machine. Output only structured data. No opinions." | ||
| }, | ||
| "data-analyst": { | ||
| id: "data-analyst", | ||
| name: "Data Analyst", | ||
| description: "Metrics, trends, statistics", | ||
| tone: "formal", | ||
| verbosity: 3, | ||
| focus: ["metrics", "trends", "patterns", "statistics"], | ||
| ignore: ["narratives"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "moderate", | ||
| system_prompt: "You are a data analyst. Quantify everything. Provide metrics and trends." | ||
| }, | ||
| journalist: { | ||
| id: "journalist", | ||
| name: "Journalist", | ||
| description: "Engaging story, human angle", | ||
| tone: "casual", | ||
| verbosity: 4, | ||
| focus: ["narrative", "impact", "human_angle"], | ||
| ignore: ["dry_stats"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "none", | ||
| system_prompt: "You are a tech journalist. Tell a story. Make it engaging." | ||
| }, | ||
| pm: { | ||
| id: "pm", | ||
| name: "Product Manager", | ||
| description: "User impact, features, bugs", | ||
| tone: "casual", | ||
| verbosity: 2, | ||
| focus: ["features", "user_impact", "roadmap", "bugs_fixed"], | ||
| ignore: ["technical_jargon"], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: "You are a Product Manager. Focus on user-facing changes." | ||
| }, | ||
| compliance: { | ||
| id: "compliance", | ||
| name: "Compliance Auditor", | ||
| description: "Security, compliance, licenses", | ||
| tone: "formal", | ||
| verbosity: 4, | ||
| focus: ["security", "data_handling", "dependencies", "licenses"], | ||
| ignore: ["marketing", "design"], | ||
| format_preference: "mixed", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a compliance auditor. Focus on security and regulatory implications." | ||
| } | ||
| }; | ||
| // src/built-in/ceo.ts | ||
| var ceo = { | ||
| id: "ceo", | ||
| name: "CEO / Executive", | ||
| description: "High-level business impact, concise", | ||
| tone: "executive", | ||
| verbosity: 1, | ||
| focus: ["business_impact", "timeline", "risk", "resource_changes"], | ||
| ignore: ["code_details", "linting", "formatting", "minor_fixes"], | ||
| format_preference: "bullets", | ||
| emoji_usage: false, | ||
| jargon_level: "none", | ||
| system_prompt: `You are a CEO reading a technical update. | ||
| Be extremely concise \u2014 3 bullet points maximum. | ||
| Focus on business impact, timelines, and risks. | ||
| No technical jargon. No code. Plain English only.` | ||
| }; | ||
| // src/built-in/data-analyst.ts | ||
| var dataAnalyst = { | ||
| id: "data-analyst", | ||
| name: "Data Analyst", | ||
| description: "Metrics-focused, chart-ready, statistical", | ||
| tone: "formal", | ||
| verbosity: 3, | ||
| focus: ["metrics", "trends", "patterns", "statistics"], | ||
| ignore: ["opinion", "aesthetics"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "moderate", | ||
| system_prompt: `You are a data analyst reviewing code changes. | ||
| Quantify everything. Provide metrics, trends, and statistics. | ||
| Compare to previous periods. Identify patterns and anomalies. | ||
| Output should be chart-ready with clear data points.` | ||
| }; | ||
| // src/built-in/educator.ts | ||
| var educator = { | ||
| id: "educator", | ||
| name: "Educator / Tutorial Writer", | ||
| description: "Explanatory, verbose, teaching-focused", | ||
| tone: "educational", | ||
| verbosity: 5, | ||
| focus: ["learning_points", "patterns", "best_practices", "why_not_how"], | ||
| ignore: [], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: `You are an educator explaining code changes to learners. | ||
| Be thorough and patient. Explain WHY not just WHAT. | ||
| Use analogies. Link to documentation. | ||
| Break down complex concepts. Include "Learning Takeaways" section.` | ||
| }; | ||
| // src/built-in/robot.ts | ||
| var robot = { | ||
| id: "robot", | ||
| name: "Robot / Machine", | ||
| description: "Ultra-structured, parseable, minimal", | ||
| tone: "robotic", | ||
| verbosity: 1, | ||
| focus: ["facts", "metrics", "files_changed"], | ||
| ignore: ["opinion", "context", "explanation", "rationale"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a machine. Output only structured data. | ||
| No opinions. No explanations. No pleasantries. | ||
| Just facts in the requested format. | ||
| Optimal for downstream parsing by other systems.` | ||
| }; | ||
| // src/built-in/journalist.ts | ||
| var journalist = { | ||
| id: "journalist", | ||
| name: "Journalist / Blogger", | ||
| description: "Narrative, engaging, story-driven", | ||
| tone: "casual", | ||
| verbosity: 4, | ||
| focus: ["narrative", "impact", "human_angle", "community"], | ||
| ignore: ["technical_minutiae"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "none", | ||
| system_prompt: `You are a tech journalist writing about code changes. | ||
| Tell a story. Make it engaging. Lead with the most interesting change. | ||
| Use metaphors and analogies. Write for a general technical audience. | ||
| Include quotes if possible. End with "What's Next" section.` | ||
| }; | ||
| // src/built-in/pm.ts | ||
| var pm = { | ||
| id: "pm", | ||
| name: "Product Manager", | ||
| description: "Feature-focused, user-impact, roadmap", | ||
| tone: "casual", | ||
| verbosity: 2, | ||
| focus: ["features", "user_impact", "roadmap", "bugs_fixed"], | ||
| ignore: ["code_quality", "refactoring", "technical_debt"], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: `You are a Product Manager reviewing engineering updates. | ||
| Focus on user-facing changes. Connect to product roadmap. | ||
| Highlight bugs fixed and features added. | ||
| Flag any UX changes. Keep it scannable for stakeholder updates.` | ||
| }; | ||
| // src/built-in/compliance.ts | ||
| var compliance = { | ||
| id: "compliance", | ||
| name: "Compliance / Security Auditor", | ||
| description: "Regulatory, risk-focused, audit-ready", | ||
| tone: "formal", | ||
| verbosity: 4, | ||
| focus: ["security", "data_handling", "dependencies", "licenses", "compliance"], | ||
| ignore: ["performance", "ux", "aesthetics"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a compliance auditor reviewing code changes. | ||
| Focus on security implications, data handling, and regulatory compliance. | ||
| Flag any dependency changes with license implications. | ||
| Note any changes to authentication, authorization, or data storage. | ||
| Output should be audit-ready with clear risk assessments.` | ||
| }; | ||
| // src/registry.ts | ||
| var BUILTIN_PERSONAS = { | ||
| developer, | ||
| ceo, | ||
| "data-analyst": dataAnalyst, | ||
| educator, | ||
| robot, | ||
| journalist, | ||
| pm, | ||
| compliance | ||
| }; | ||
| var PersonaRegistry = class { | ||
@@ -266,3 +223,5 @@ static customPersonas = /* @__PURE__ */ new Map(); | ||
| if (!parsed.id) { | ||
| throw new Error(`Custom persona file at ${filePath} is missing required 'id' field.`); | ||
| throw new Error( | ||
| `Custom persona file at ${filePath} is missing required 'id' field.` | ||
| ); | ||
| } | ||
@@ -273,3 +232,5 @@ let basePersona = {}; | ||
| if (!inherited) { | ||
| throw new Error(`Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`); | ||
| throw new Error( | ||
| `Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.` | ||
| ); | ||
| } | ||
@@ -276,0 +237,0 @@ basePersona = { ...inherited }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts","../src/engine.ts","../src/built-in/developer.ts","../src/built-in/ceo.ts","../src/built-in/data-analyst.ts","../src/built-in/educator.ts","../src/built-in/robot.ts","../src/built-in/journalist.ts","../src/built-in/pm.ts","../src/built-in/compliance.ts","../src/registry.ts","../src/custom-loader.ts"],"sourcesContent":["export { Persona, PersonaEngine } from './engine'\nexport { BUILTIN_PERSONAS, PersonaRegistry } from './registry'\nexport { CustomPersonaLoader } from './custom-loader'\n","export interface Persona {\n id: string\n name: string\n description: string\n tone: 'formal' | 'casual' | 'technical' | 'executive' | 'educational' | 'robotic'\n verbosity: 1 | 2 | 3 | 4 | 5 // 1 = ultra-concise, 5 = exhaustive\n focus: string[] // What to emphasize\n ignore: string[] // What to omit\n format_preference: 'paragraphs' | 'bullets' | 'tables' | 'mixed'\n emoji_usage: boolean\n jargon_level: 'none' | 'minimal' | 'moderate' | 'heavy'\n system_prompt: string\n}\n\nexport class PersonaEngine {\n /**\n * Generates the system prompt to instruct the AI based on the Persona properties.\n */\n static generateSystemPrompt(persona: Persona): string {\n const focusStr = persona.focus.length > 0 ? `Focus on: ${persona.focus.join(', ')}.` : '';\n const ignoreStr = persona.ignore.length > 0 ? `Ignore or omit: ${persona.ignore.join(', ')}.` : '';\n \n return `${persona.system_prompt}\n \nGuidelines for your response:\n- Tone: ${persona.tone}\n- Verbosity level: ${persona.verbosity}/5 (1 is ultra-concise/minimalist, 5 is extremely detailed and explanatory).\n- Format preference: ${persona.format_preference}.\n- Emojis: ${persona.emoji_usage ? 'Use emojis where appropriate to make the text lively.' : 'DO NOT use emojis under any circumstance.'}\n- Technical Jargon: ${persona.jargon_level} level.\n${focusStr}\n${ignoreStr}\n`;\n }\n\n /**\n * Post-processes the output to align it closer to the persona config (fallback filter).\n */\n static postProcess(output: string, persona: Persona): string {\n let result = output;\n \n // If emojis are disabled, clean them up\n if (!persona.emoji_usage) {\n // Basic emoji regex pattern to strip emojis\n result = result.replace(/[\\u{1F600}-\\u{1F64F}\\u{1F300}-\\u{1F5FF}\\u{1F680}-\\u{1F6FF}\\u{1F700}-\\u{1F77F}\\u{1F780}-\\u{1F7FF}\\u{1F800}-\\u{1F8FF}\\u{1F900}-\\u{1F9FF}\\u{1FA00}-\\u{1FAFF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}]/gu, '');\n }\n\n // Enforce verbosity constraint post-processing if necessary (e.g. ultra-concise max limits)\n if (persona.verbosity === 1) {\n const lines = result.split('\\n');\n if (lines.length > 10) {\n // Just keeping it reasonably compact if it somehow exceeded\n }\n }\n\n return result.trim();\n }\n}\n","import { Persona } from '../engine'\n\nexport const developer: Persona = {\n id: 'developer',\n name: 'Developer',\n description: 'Technical, precise, code-focused',\n tone: 'technical',\n verbosity: 3,\n focus: ['code_changes', 'architecture', 'breaking_changes', 'dependencies'],\n ignore: ['business_impact', 'revenue', 'marketing'],\n format_preference: 'bullets',\n emoji_usage: true,\n jargon_level: 'heavy',\n system_prompt: `You are a senior developer reviewing code changes. \nBe technical and precise. Use code snippets. Focus on architecture decisions.\nHighlight breaking changes and migration paths. Use developer terminology.`\n}\n","import { Persona } from '../engine'\n\nexport const ceo: Persona = {\n id: 'ceo',\n name: 'CEO / Executive',\n description: 'High-level business impact, concise',\n tone: 'executive',\n verbosity: 1,\n focus: ['business_impact', 'timeline', 'risk', 'resource_changes'],\n ignore: ['code_details', 'linting', 'formatting', 'minor_fixes'],\n format_preference: 'bullets',\n emoji_usage: false,\n jargon_level: 'none',\n system_prompt: `You are a CEO reading a technical update. \nBe extremely concise — 3 bullet points maximum. \nFocus on business impact, timelines, and risks. \nNo technical jargon. No code. Plain English only.`\n}\n","import { Persona } from '../engine'\n\nexport const dataAnalyst: Persona = {\n id: 'data-analyst',\n name: 'Data Analyst',\n description: 'Metrics-focused, chart-ready, statistical',\n tone: 'formal',\n verbosity: 3,\n focus: ['metrics', 'trends', 'patterns', 'statistics'],\n ignore: ['opinion', 'aesthetics'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'moderate',\n system_prompt: `You are a data analyst reviewing code changes.\nQuantify everything. Provide metrics, trends, and statistics.\nCompare to previous periods. Identify patterns and anomalies.\nOutput should be chart-ready with clear data points.`\n}\n","import { Persona } from '../engine'\n\nexport const educator: Persona = {\n id: 'educator',\n name: 'Educator / Tutorial Writer',\n description: 'Explanatory, verbose, teaching-focused',\n tone: 'educational',\n verbosity: 5,\n focus: ['learning_points', 'patterns', 'best_practices', 'why_not_how'],\n ignore: [],\n format_preference: 'mixed',\n emoji_usage: true,\n jargon_level: 'minimal',\n system_prompt: `You are an educator explaining code changes to learners.\nBe thorough and patient. Explain WHY not just WHAT.\nUse analogies. Link to documentation. \nBreak down complex concepts. Include \"Learning Takeaways\" section.`\n}\n","import { Persona } from '../engine'\n\nexport const robot: Persona = {\n id: 'robot',\n name: 'Robot / Machine',\n description: 'Ultra-structured, parseable, minimal',\n tone: 'robotic',\n verbosity: 1,\n focus: ['facts', 'metrics', 'files_changed'],\n ignore: ['opinion', 'context', 'explanation', 'rationale'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'heavy',\n system_prompt: `You are a machine. Output only structured data.\nNo opinions. No explanations. No pleasantries.\nJust facts in the requested format.\nOptimal for downstream parsing by other systems.`\n}\n","import { Persona } from '../engine'\n\nexport const journalist: Persona = {\n id: 'journalist',\n name: 'Journalist / Blogger',\n description: 'Narrative, engaging, story-driven',\n tone: 'casual',\n verbosity: 4,\n focus: ['narrative', 'impact', 'human_angle', 'community'],\n ignore: ['technical_minutiae'],\n format_preference: 'paragraphs',\n emoji_usage: true,\n jargon_level: 'none',\n system_prompt: `You are a tech journalist writing about code changes.\nTell a story. Make it engaging. Lead with the most interesting change.\nUse metaphors and analogies. Write for a general technical audience.\nInclude quotes if possible. End with \"What's Next\" section.`\n}\n","import { Persona } from '../engine'\n\nexport const pm: Persona = {\n id: 'pm',\n name: 'Product Manager',\n description: 'Feature-focused, user-impact, roadmap',\n tone: 'casual',\n verbosity: 2,\n focus: ['features', 'user_impact', 'roadmap', 'bugs_fixed'],\n ignore: ['code_quality', 'refactoring', 'technical_debt'],\n format_preference: 'mixed',\n emoji_usage: true,\n jargon_level: 'minimal',\n system_prompt: `You are a Product Manager reviewing engineering updates.\nFocus on user-facing changes. Connect to product roadmap.\nHighlight bugs fixed and features added. \nFlag any UX changes. Keep it scannable for stakeholder updates.`\n}\n","import { Persona } from '../engine'\n\nexport const compliance: Persona = {\n id: 'compliance',\n name: 'Compliance / Security Auditor',\n description: 'Regulatory, risk-focused, audit-ready',\n tone: 'formal',\n verbosity: 4,\n focus: ['security', 'data_handling', 'dependencies', 'licenses', 'compliance'],\n ignore: ['performance', 'ux', 'aesthetics'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'heavy',\n system_prompt: `You are a compliance auditor reviewing code changes.\nFocus on security implications, data handling, and regulatory compliance.\nFlag any dependency changes with license implications.\nNote any changes to authentication, authorization, or data storage.\nOutput should be audit-ready with clear risk assessments.`\n}\n","import { Persona } from './engine'\nimport { developer } from './built-in/developer'\nimport { ceo } from './built-in/ceo'\nimport { dataAnalyst } from './built-in/data-analyst'\nimport { educator } from './built-in/educator'\nimport { robot } from './built-in/robot'\nimport { journalist } from './built-in/journalist'\nimport { pm } from './built-in/pm'\nimport { compliance } from './built-in/compliance'\n\nexport const BUILTIN_PERSONAS: Record<string, Persona> = {\n developer,\n ceo,\n 'data-analyst': dataAnalyst,\n educator,\n robot,\n journalist,\n pm,\n compliance,\n}\n\nexport class PersonaRegistry {\n private static customPersonas: Map<string, Persona> = new Map()\n\n static get(id: string): Persona | undefined {\n return BUILTIN_PERSONAS[id] || this.customPersonas.get(id)\n }\n\n static register(persona: Persona): void {\n this.customPersonas.set(persona.id, persona)\n }\n\n static list(): Persona[] {\n return [\n ...Object.values(BUILTIN_PERSONAS),\n ...Array.from(this.customPersonas.values()),\n ]\n }\n\n static clearCustom(): void {\n this.customPersonas.clear()\n }\n}\n","import * as fs from 'fs/promises'\nimport * as path from 'path'\nimport yaml from 'js-yaml'\nimport { Persona } from './engine'\nimport { PersonaRegistry } from './registry'\n\nexport class CustomPersonaLoader {\n /**\n * Loads a custom persona from a YAML configuration file.\n * If the persona extends an existing persona, it will inherit and override properties.\n */\n static async loadFromFile(filePath: string): Promise<Persona> {\n const rawContent = await fs.readFile(filePath, 'utf-8')\n const parsed = yaml.load(rawContent) as Partial<Persona> & { extends?: string }\n\n if (!parsed.id) {\n throw new Error(`Custom persona file at ${filePath} is missing required 'id' field.`)\n }\n\n let basePersona: Partial<Persona> = {}\n if (parsed.extends) {\n const inherited = PersonaRegistry.get(parsed.extends)\n if (!inherited) {\n throw new Error(`Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`)\n }\n basePersona = { ...inherited }\n }\n\n // Merge base persona with overrides\n const mergedPersona: Persona = {\n id: parsed.id,\n name: parsed.name ?? basePersona.name ?? parsed.id,\n description: parsed.description ?? basePersona.description ?? '',\n tone: parsed.tone ?? basePersona.tone ?? 'technical',\n verbosity: parsed.verbosity ?? basePersona.verbosity ?? 3,\n focus: parsed.focus ?? basePersona.focus ?? [],\n ignore: parsed.ignore ?? basePersona.ignore ?? [],\n format_preference: parsed.format_preference ?? basePersona.format_preference ?? 'mixed',\n emoji_usage: parsed.emoji_usage ?? basePersona.emoji_usage ?? false,\n jargon_level: parsed.jargon_level ?? basePersona.jargon_level ?? 'moderate',\n system_prompt: parsed.system_prompt ?? basePersona.system_prompt ?? '',\n }\n\n PersonaRegistry.register(mergedPersona)\n return mergedPersona\n }\n\n /**\n * Discovers and loads all custom personas in a directory.\n */\n static async loadDirectory(dirPath: string): Promise<Persona[]> {\n const loaded: Persona[] = []\n try {\n const files = await fs.readdir(dirPath)\n for (const file of files) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n try {\n const persona = await this.loadFromFile(path.join(dirPath, file))\n loaded.push(persona)\n } catch (err) {\n console.error(`Failed to load custom persona from ${file}:`, err)\n }\n }\n }\n } catch (err) {\n // Directory may not exist, ignore\n }\n return loaded\n }\n}\n"],"mappings":"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","names":["yaml"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/engine.ts","../src/built-in.ts","../src/registry.ts","../src/custom-loader.ts"],"sourcesContent":["export { Persona, PersonaEngine } from \"./engine\";\nexport { BUILTIN_PERSONAS, PersonaRegistry } from \"./registry\";\nexport { CustomPersonaLoader } from \"./custom-loader\";\n","export interface Persona {\n id: string;\n name: string;\n description: string;\n tone:\n \"formal\" | \"casual\" | \"technical\" | \"executive\" | \"educational\" | \"robotic\";\n verbosity: 1 | 2 | 3 | 4 | 5; // 1 = ultra-concise, 5 = exhaustive\n focus: string[]; // What to emphasize\n ignore: string[]; // What to omit\n format_preference: \"paragraphs\" | \"bullets\" | \"tables\" | \"mixed\";\n emoji_usage: boolean;\n jargon_level: \"none\" | \"minimal\" | \"moderate\" | \"heavy\";\n system_prompt: string;\n}\n\nexport class PersonaEngine {\n /**\n * Generates the system prompt to instruct the AI based on the Persona properties.\n */\n static generateSystemPrompt(persona: Persona): string {\n const focusStr =\n persona.focus.length > 0 ? `Focus on: ${persona.focus.join(\", \")}.` : \"\";\n const ignoreStr =\n persona.ignore.length > 0\n ? `Ignore or omit: ${persona.ignore.join(\", \")}.`\n : \"\";\n\n return `${persona.system_prompt}\n \nGuidelines for your response:\n- Tone: ${persona.tone}\n- Verbosity level: ${persona.verbosity}/5 (1 is ultra-concise/minimalist, 5 is extremely detailed and explanatory).\n- Format preference: ${persona.format_preference}.\n- Emojis: ${persona.emoji_usage ? \"Use emojis where appropriate to make the text lively.\" : \"DO NOT use emojis under any circumstance.\"}\n- Technical Jargon: ${persona.jargon_level} level.\n${focusStr}\n${ignoreStr}\n`;\n }\n\n /**\n * Post-processes the output to align it closer to the persona config (fallback filter).\n */\n static postProcess(output: string, persona: Persona): string {\n let result = output;\n\n // If emojis are disabled, clean them up\n if (!persona.emoji_usage) {\n // Basic emoji regex pattern to strip emojis\n result = result.replace(\n /[\\u{1F600}-\\u{1F64F}\\u{1F300}-\\u{1F5FF}\\u{1F680}-\\u{1F6FF}\\u{1F700}-\\u{1F77F}\\u{1F780}-\\u{1F7FF}\\u{1F800}-\\u{1F8FF}\\u{1F900}-\\u{1F9FF}\\u{1FA00}-\\u{1FAFF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}]/gu,\n \"\",\n );\n }\n\n // Enforce verbosity constraint post-processing if necessary (e.g. ultra-concise max limits)\n if (persona.verbosity === 1) {\n const lines = result.split(\"\\n\");\n if (lines.length > 10) {\n // Just keeping it reasonably compact if it somehow exceeded\n }\n }\n\n return result.trim();\n }\n}\n","import { Persona } from \"./engine\";\n\nexport const BUILTIN_PERSONAS: Record<string, Persona> = {\n developer: {\n id: \"developer\",\n name: \"Developer\",\n description: \"Technical, precise, code-focused\",\n tone: \"technical\",\n verbosity: 3,\n focus: [\"code_changes\", \"architecture\", \"breaking_changes\"],\n ignore: [\"business_impact\", \"revenue\", \"marketing\"],\n format_preference: \"bullets\",\n emoji_usage: true,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a senior developer reviewing code changes. Be technical and precise.\",\n },\n ceo: {\n id: \"ceo\",\n name: \"CEO\",\n description: \"Executive summary, business-focused\",\n tone: \"executive\",\n verbosity: 1,\n focus: [\"business_impact\", \"timeline\", \"risk\"],\n ignore: [\"code_changes\", \"dependencies\"],\n format_preference: \"bullets\",\n emoji_usage: false,\n jargon_level: \"none\",\n system_prompt:\n \"You are a CEO reading a technical update. 3 bullet points maximum. No jargon.\",\n },\n educator: {\n id: \"educator\",\n name: \"Educator\",\n description: \"Educational, patient, explanatory\",\n tone: \"educational\",\n verbosity: 5,\n focus: [\"learning_points\", \"patterns\", \"best_practices\"],\n ignore: [\"internal_details\"],\n format_preference: \"paragraphs\",\n emoji_usage: true,\n jargon_level: \"minimal\",\n system_prompt:\n \"You are an educator explaining changes to learners. Be thorough and patient.\",\n },\n robot: {\n id: \"robot\",\n name: \"Robot\",\n description: \"Structured data, no opinions\",\n tone: \"robotic\",\n verbosity: 1,\n focus: [\"facts\", \"metrics\", \"files_changed\"],\n ignore: [\"commentary\", \"opinions\"],\n format_preference: \"tables\",\n emoji_usage: false,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a machine. Output only structured data. No opinions.\",\n },\n \"data-analyst\": {\n id: \"data-analyst\",\n name: \"Data Analyst\",\n description: \"Metrics, trends, statistics\",\n tone: \"formal\",\n verbosity: 3,\n focus: [\"metrics\", \"trends\", \"patterns\", \"statistics\"],\n ignore: [\"narratives\"],\n format_preference: \"tables\",\n emoji_usage: false,\n jargon_level: \"moderate\",\n system_prompt:\n \"You are a data analyst. Quantify everything. Provide metrics and trends.\",\n },\n journalist: {\n id: \"journalist\",\n name: \"Journalist\",\n description: \"Engaging story, human angle\",\n tone: \"casual\",\n verbosity: 4,\n focus: [\"narrative\", \"impact\", \"human_angle\"],\n ignore: [\"dry_stats\"],\n format_preference: \"paragraphs\",\n emoji_usage: true,\n jargon_level: \"none\",\n system_prompt: \"You are a tech journalist. Tell a story. Make it engaging.\",\n },\n pm: {\n id: \"pm\",\n name: \"Product Manager\",\n description: \"User impact, features, bugs\",\n tone: \"casual\",\n verbosity: 2,\n focus: [\"features\", \"user_impact\", \"roadmap\", \"bugs_fixed\"],\n ignore: [\"technical_jargon\"],\n format_preference: \"mixed\",\n emoji_usage: true,\n jargon_level: \"minimal\",\n system_prompt: \"You are a Product Manager. Focus on user-facing changes.\",\n },\n compliance: {\n id: \"compliance\",\n name: \"Compliance Auditor\",\n description: \"Security, compliance, licenses\",\n tone: \"formal\",\n verbosity: 4,\n focus: [\"security\", \"data_handling\", \"dependencies\", \"licenses\"],\n ignore: [\"marketing\", \"design\"],\n format_preference: \"mixed\",\n emoji_usage: false,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a compliance auditor. Focus on security and regulatory implications.\",\n },\n};\n","import { Persona } from \"./engine\";\nimport { BUILTIN_PERSONAS } from \"./built-in\";\n\nexport { BUILTIN_PERSONAS };\n\nexport class PersonaRegistry {\n private static customPersonas: Map<string, Persona> = new Map();\n\n static get(id: string): Persona | undefined {\n return BUILTIN_PERSONAS[id] || this.customPersonas.get(id);\n }\n\n static register(persona: Persona): void {\n this.customPersonas.set(persona.id, persona);\n }\n\n static list(): Persona[] {\n return [\n ...Object.values(BUILTIN_PERSONAS),\n ...Array.from(this.customPersonas.values()),\n ];\n }\n\n static clearCustom(): void {\n this.customPersonas.clear();\n }\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport yaml from \"js-yaml\";\nimport { Persona } from \"./engine\";\nimport { PersonaRegistry } from \"./registry\";\n\nexport class CustomPersonaLoader {\n /**\n * Loads a custom persona from a YAML configuration file.\n * If the persona extends an existing persona, it will inherit and override properties.\n */\n static async loadFromFile(filePath: string): Promise<Persona> {\n const rawContent = await fs.readFile(filePath, \"utf-8\");\n const parsed = yaml.load(rawContent) as Partial<Persona> & {\n extends?: string;\n };\n\n if (!parsed.id) {\n throw new Error(\n `Custom persona file at ${filePath} is missing required 'id' field.`,\n );\n }\n\n let basePersona: Partial<Persona> = {};\n if (parsed.extends) {\n const inherited = PersonaRegistry.get(parsed.extends);\n if (!inherited) {\n throw new Error(\n `Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`,\n );\n }\n basePersona = { ...inherited };\n }\n\n // Merge base persona with overrides\n const mergedPersona: Persona = {\n id: parsed.id,\n name: parsed.name ?? basePersona.name ?? parsed.id,\n description: parsed.description ?? basePersona.description ?? \"\",\n tone: parsed.tone ?? basePersona.tone ?? \"technical\",\n verbosity: parsed.verbosity ?? basePersona.verbosity ?? 3,\n focus: parsed.focus ?? basePersona.focus ?? [],\n ignore: parsed.ignore ?? basePersona.ignore ?? [],\n format_preference:\n parsed.format_preference ?? basePersona.format_preference ?? \"mixed\",\n emoji_usage: parsed.emoji_usage ?? basePersona.emoji_usage ?? false,\n jargon_level:\n parsed.jargon_level ?? basePersona.jargon_level ?? \"moderate\",\n system_prompt: parsed.system_prompt ?? basePersona.system_prompt ?? \"\",\n };\n\n PersonaRegistry.register(mergedPersona);\n return mergedPersona;\n }\n\n /**\n * Discovers and loads all custom personas in a directory.\n */\n static async loadDirectory(dirPath: string): Promise<Persona[]> {\n const loaded: Persona[] = [];\n try {\n const files = await fs.readdir(dirPath);\n for (const file of files) {\n if (file.endsWith(\".yaml\") || file.endsWith(\".yml\")) {\n try {\n const persona = await this.loadFromFile(path.join(dirPath, file));\n loaded.push(persona);\n } catch (err) {\n console.error(`Failed to load custom persona from ${file}:`, err);\n }\n }\n }\n } catch (err) {\n // Directory may not exist, ignore\n }\n return loaded;\n }\n}\n"],"mappings":"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","names":["yaml"]} |
+4
-3
@@ -5,9 +5,9 @@ interface Persona { | ||
| description: string; | ||
| tone: 'formal' | 'casual' | 'technical' | 'executive' | 'educational' | 'robotic'; | ||
| tone: "formal" | "casual" | "technical" | "executive" | "educational" | "robotic"; | ||
| verbosity: 1 | 2 | 3 | 4 | 5; | ||
| focus: string[]; | ||
| ignore: string[]; | ||
| format_preference: 'paragraphs' | 'bullets' | 'tables' | 'mixed'; | ||
| format_preference: "paragraphs" | "bullets" | "tables" | "mixed"; | ||
| emoji_usage: boolean; | ||
| jargon_level: 'none' | 'minimal' | 'moderate' | 'heavy'; | ||
| jargon_level: "none" | "minimal" | "moderate" | "heavy"; | ||
| system_prompt: string; | ||
@@ -27,2 +27,3 @@ } | ||
| declare const BUILTIN_PERSONAS: Record<string, Persona>; | ||
| declare class PersonaRegistry { | ||
@@ -29,0 +30,0 @@ private static customPersonas; |
+4
-3
@@ -5,9 +5,9 @@ interface Persona { | ||
| description: string; | ||
| tone: 'formal' | 'casual' | 'technical' | 'executive' | 'educational' | 'robotic'; | ||
| tone: "formal" | "casual" | "technical" | "executive" | "educational" | "robotic"; | ||
| verbosity: 1 | 2 | 3 | 4 | 5; | ||
| focus: string[]; | ||
| ignore: string[]; | ||
| format_preference: 'paragraphs' | 'bullets' | 'tables' | 'mixed'; | ||
| format_preference: "paragraphs" | "bullets" | "tables" | "mixed"; | ||
| emoji_usage: boolean; | ||
| jargon_level: 'none' | 'minimal' | 'moderate' | 'heavy'; | ||
| jargon_level: "none" | "minimal" | "moderate" | "heavy"; | ||
| system_prompt: string; | ||
@@ -27,2 +27,3 @@ } | ||
| declare const BUILTIN_PERSONAS: Record<string, Persona>; | ||
| declare class PersonaRegistry { | ||
@@ -29,0 +30,0 @@ private static customPersonas; |
+116
-155
@@ -27,3 +27,6 @@ // src/engine.ts | ||
| if (!persona.emoji_usage) { | ||
| result = result.replace(/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, ""); | ||
| result = result.replace( | ||
| /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FAFF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, | ||
| "" | ||
| ); | ||
| } | ||
@@ -39,157 +42,111 @@ if (persona.verbosity === 1) { | ||
| // src/built-in/developer.ts | ||
| var developer = { | ||
| id: "developer", | ||
| name: "Developer", | ||
| description: "Technical, precise, code-focused", | ||
| tone: "technical", | ||
| verbosity: 3, | ||
| focus: ["code_changes", "architecture", "breaking_changes", "dependencies"], | ||
| ignore: ["business_impact", "revenue", "marketing"], | ||
| format_preference: "bullets", | ||
| emoji_usage: true, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a senior developer reviewing code changes. | ||
| Be technical and precise. Use code snippets. Focus on architecture decisions. | ||
| Highlight breaking changes and migration paths. Use developer terminology.` | ||
| // src/built-in.ts | ||
| var BUILTIN_PERSONAS = { | ||
| developer: { | ||
| id: "developer", | ||
| name: "Developer", | ||
| description: "Technical, precise, code-focused", | ||
| tone: "technical", | ||
| verbosity: 3, | ||
| focus: ["code_changes", "architecture", "breaking_changes"], | ||
| ignore: ["business_impact", "revenue", "marketing"], | ||
| format_preference: "bullets", | ||
| emoji_usage: true, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a senior developer reviewing code changes. Be technical and precise." | ||
| }, | ||
| ceo: { | ||
| id: "ceo", | ||
| name: "CEO", | ||
| description: "Executive summary, business-focused", | ||
| tone: "executive", | ||
| verbosity: 1, | ||
| focus: ["business_impact", "timeline", "risk"], | ||
| ignore: ["code_changes", "dependencies"], | ||
| format_preference: "bullets", | ||
| emoji_usage: false, | ||
| jargon_level: "none", | ||
| system_prompt: "You are a CEO reading a technical update. 3 bullet points maximum. No jargon." | ||
| }, | ||
| educator: { | ||
| id: "educator", | ||
| name: "Educator", | ||
| description: "Educational, patient, explanatory", | ||
| tone: "educational", | ||
| verbosity: 5, | ||
| focus: ["learning_points", "patterns", "best_practices"], | ||
| ignore: ["internal_details"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: "You are an educator explaining changes to learners. Be thorough and patient." | ||
| }, | ||
| robot: { | ||
| id: "robot", | ||
| name: "Robot", | ||
| description: "Structured data, no opinions", | ||
| tone: "robotic", | ||
| verbosity: 1, | ||
| focus: ["facts", "metrics", "files_changed"], | ||
| ignore: ["commentary", "opinions"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a machine. Output only structured data. No opinions." | ||
| }, | ||
| "data-analyst": { | ||
| id: "data-analyst", | ||
| name: "Data Analyst", | ||
| description: "Metrics, trends, statistics", | ||
| tone: "formal", | ||
| verbosity: 3, | ||
| focus: ["metrics", "trends", "patterns", "statistics"], | ||
| ignore: ["narratives"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "moderate", | ||
| system_prompt: "You are a data analyst. Quantify everything. Provide metrics and trends." | ||
| }, | ||
| journalist: { | ||
| id: "journalist", | ||
| name: "Journalist", | ||
| description: "Engaging story, human angle", | ||
| tone: "casual", | ||
| verbosity: 4, | ||
| focus: ["narrative", "impact", "human_angle"], | ||
| ignore: ["dry_stats"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "none", | ||
| system_prompt: "You are a tech journalist. Tell a story. Make it engaging." | ||
| }, | ||
| pm: { | ||
| id: "pm", | ||
| name: "Product Manager", | ||
| description: "User impact, features, bugs", | ||
| tone: "casual", | ||
| verbosity: 2, | ||
| focus: ["features", "user_impact", "roadmap", "bugs_fixed"], | ||
| ignore: ["technical_jargon"], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: "You are a Product Manager. Focus on user-facing changes." | ||
| }, | ||
| compliance: { | ||
| id: "compliance", | ||
| name: "Compliance Auditor", | ||
| description: "Security, compliance, licenses", | ||
| tone: "formal", | ||
| verbosity: 4, | ||
| focus: ["security", "data_handling", "dependencies", "licenses"], | ||
| ignore: ["marketing", "design"], | ||
| format_preference: "mixed", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: "You are a compliance auditor. Focus on security and regulatory implications." | ||
| } | ||
| }; | ||
| // src/built-in/ceo.ts | ||
| var ceo = { | ||
| id: "ceo", | ||
| name: "CEO / Executive", | ||
| description: "High-level business impact, concise", | ||
| tone: "executive", | ||
| verbosity: 1, | ||
| focus: ["business_impact", "timeline", "risk", "resource_changes"], | ||
| ignore: ["code_details", "linting", "formatting", "minor_fixes"], | ||
| format_preference: "bullets", | ||
| emoji_usage: false, | ||
| jargon_level: "none", | ||
| system_prompt: `You are a CEO reading a technical update. | ||
| Be extremely concise \u2014 3 bullet points maximum. | ||
| Focus on business impact, timelines, and risks. | ||
| No technical jargon. No code. Plain English only.` | ||
| }; | ||
| // src/built-in/data-analyst.ts | ||
| var dataAnalyst = { | ||
| id: "data-analyst", | ||
| name: "Data Analyst", | ||
| description: "Metrics-focused, chart-ready, statistical", | ||
| tone: "formal", | ||
| verbosity: 3, | ||
| focus: ["metrics", "trends", "patterns", "statistics"], | ||
| ignore: ["opinion", "aesthetics"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "moderate", | ||
| system_prompt: `You are a data analyst reviewing code changes. | ||
| Quantify everything. Provide metrics, trends, and statistics. | ||
| Compare to previous periods. Identify patterns and anomalies. | ||
| Output should be chart-ready with clear data points.` | ||
| }; | ||
| // src/built-in/educator.ts | ||
| var educator = { | ||
| id: "educator", | ||
| name: "Educator / Tutorial Writer", | ||
| description: "Explanatory, verbose, teaching-focused", | ||
| tone: "educational", | ||
| verbosity: 5, | ||
| focus: ["learning_points", "patterns", "best_practices", "why_not_how"], | ||
| ignore: [], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: `You are an educator explaining code changes to learners. | ||
| Be thorough and patient. Explain WHY not just WHAT. | ||
| Use analogies. Link to documentation. | ||
| Break down complex concepts. Include "Learning Takeaways" section.` | ||
| }; | ||
| // src/built-in/robot.ts | ||
| var robot = { | ||
| id: "robot", | ||
| name: "Robot / Machine", | ||
| description: "Ultra-structured, parseable, minimal", | ||
| tone: "robotic", | ||
| verbosity: 1, | ||
| focus: ["facts", "metrics", "files_changed"], | ||
| ignore: ["opinion", "context", "explanation", "rationale"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a machine. Output only structured data. | ||
| No opinions. No explanations. No pleasantries. | ||
| Just facts in the requested format. | ||
| Optimal for downstream parsing by other systems.` | ||
| }; | ||
| // src/built-in/journalist.ts | ||
| var journalist = { | ||
| id: "journalist", | ||
| name: "Journalist / Blogger", | ||
| description: "Narrative, engaging, story-driven", | ||
| tone: "casual", | ||
| verbosity: 4, | ||
| focus: ["narrative", "impact", "human_angle", "community"], | ||
| ignore: ["technical_minutiae"], | ||
| format_preference: "paragraphs", | ||
| emoji_usage: true, | ||
| jargon_level: "none", | ||
| system_prompt: `You are a tech journalist writing about code changes. | ||
| Tell a story. Make it engaging. Lead with the most interesting change. | ||
| Use metaphors and analogies. Write for a general technical audience. | ||
| Include quotes if possible. End with "What's Next" section.` | ||
| }; | ||
| // src/built-in/pm.ts | ||
| var pm = { | ||
| id: "pm", | ||
| name: "Product Manager", | ||
| description: "Feature-focused, user-impact, roadmap", | ||
| tone: "casual", | ||
| verbosity: 2, | ||
| focus: ["features", "user_impact", "roadmap", "bugs_fixed"], | ||
| ignore: ["code_quality", "refactoring", "technical_debt"], | ||
| format_preference: "mixed", | ||
| emoji_usage: true, | ||
| jargon_level: "minimal", | ||
| system_prompt: `You are a Product Manager reviewing engineering updates. | ||
| Focus on user-facing changes. Connect to product roadmap. | ||
| Highlight bugs fixed and features added. | ||
| Flag any UX changes. Keep it scannable for stakeholder updates.` | ||
| }; | ||
| // src/built-in/compliance.ts | ||
| var compliance = { | ||
| id: "compliance", | ||
| name: "Compliance / Security Auditor", | ||
| description: "Regulatory, risk-focused, audit-ready", | ||
| tone: "formal", | ||
| verbosity: 4, | ||
| focus: ["security", "data_handling", "dependencies", "licenses", "compliance"], | ||
| ignore: ["performance", "ux", "aesthetics"], | ||
| format_preference: "tables", | ||
| emoji_usage: false, | ||
| jargon_level: "heavy", | ||
| system_prompt: `You are a compliance auditor reviewing code changes. | ||
| Focus on security implications, data handling, and regulatory compliance. | ||
| Flag any dependency changes with license implications. | ||
| Note any changes to authentication, authorization, or data storage. | ||
| Output should be audit-ready with clear risk assessments.` | ||
| }; | ||
| // src/registry.ts | ||
| var BUILTIN_PERSONAS = { | ||
| developer, | ||
| ceo, | ||
| "data-analyst": dataAnalyst, | ||
| educator, | ||
| robot, | ||
| journalist, | ||
| pm, | ||
| compliance | ||
| }; | ||
| var PersonaRegistry = class { | ||
@@ -227,3 +184,5 @@ static customPersonas = /* @__PURE__ */ new Map(); | ||
| if (!parsed.id) { | ||
| throw new Error(`Custom persona file at ${filePath} is missing required 'id' field.`); | ||
| throw new Error( | ||
| `Custom persona file at ${filePath} is missing required 'id' field.` | ||
| ); | ||
| } | ||
@@ -234,3 +193,5 @@ let basePersona = {}; | ||
| if (!inherited) { | ||
| throw new Error(`Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`); | ||
| throw new Error( | ||
| `Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.` | ||
| ); | ||
| } | ||
@@ -237,0 +198,0 @@ basePersona = { ...inherited }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/engine.ts","../src/built-in/developer.ts","../src/built-in/ceo.ts","../src/built-in/data-analyst.ts","../src/built-in/educator.ts","../src/built-in/robot.ts","../src/built-in/journalist.ts","../src/built-in/pm.ts","../src/built-in/compliance.ts","../src/registry.ts","../src/custom-loader.ts"],"sourcesContent":["export interface Persona {\n id: string\n name: string\n description: string\n tone: 'formal' | 'casual' | 'technical' | 'executive' | 'educational' | 'robotic'\n verbosity: 1 | 2 | 3 | 4 | 5 // 1 = ultra-concise, 5 = exhaustive\n focus: string[] // What to emphasize\n ignore: string[] // What to omit\n format_preference: 'paragraphs' | 'bullets' | 'tables' | 'mixed'\n emoji_usage: boolean\n jargon_level: 'none' | 'minimal' | 'moderate' | 'heavy'\n system_prompt: string\n}\n\nexport class PersonaEngine {\n /**\n * Generates the system prompt to instruct the AI based on the Persona properties.\n */\n static generateSystemPrompt(persona: Persona): string {\n const focusStr = persona.focus.length > 0 ? `Focus on: ${persona.focus.join(', ')}.` : '';\n const ignoreStr = persona.ignore.length > 0 ? `Ignore or omit: ${persona.ignore.join(', ')}.` : '';\n \n return `${persona.system_prompt}\n \nGuidelines for your response:\n- Tone: ${persona.tone}\n- Verbosity level: ${persona.verbosity}/5 (1 is ultra-concise/minimalist, 5 is extremely detailed and explanatory).\n- Format preference: ${persona.format_preference}.\n- Emojis: ${persona.emoji_usage ? 'Use emojis where appropriate to make the text lively.' : 'DO NOT use emojis under any circumstance.'}\n- Technical Jargon: ${persona.jargon_level} level.\n${focusStr}\n${ignoreStr}\n`;\n }\n\n /**\n * Post-processes the output to align it closer to the persona config (fallback filter).\n */\n static postProcess(output: string, persona: Persona): string {\n let result = output;\n \n // If emojis are disabled, clean them up\n if (!persona.emoji_usage) {\n // Basic emoji regex pattern to strip emojis\n result = result.replace(/[\\u{1F600}-\\u{1F64F}\\u{1F300}-\\u{1F5FF}\\u{1F680}-\\u{1F6FF}\\u{1F700}-\\u{1F77F}\\u{1F780}-\\u{1F7FF}\\u{1F800}-\\u{1F8FF}\\u{1F900}-\\u{1F9FF}\\u{1FA00}-\\u{1FAFF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}]/gu, '');\n }\n\n // Enforce verbosity constraint post-processing if necessary (e.g. ultra-concise max limits)\n if (persona.verbosity === 1) {\n const lines = result.split('\\n');\n if (lines.length > 10) {\n // Just keeping it reasonably compact if it somehow exceeded\n }\n }\n\n return result.trim();\n }\n}\n","import { Persona } from '../engine'\n\nexport const developer: Persona = {\n id: 'developer',\n name: 'Developer',\n description: 'Technical, precise, code-focused',\n tone: 'technical',\n verbosity: 3,\n focus: ['code_changes', 'architecture', 'breaking_changes', 'dependencies'],\n ignore: ['business_impact', 'revenue', 'marketing'],\n format_preference: 'bullets',\n emoji_usage: true,\n jargon_level: 'heavy',\n system_prompt: `You are a senior developer reviewing code changes. \nBe technical and precise. Use code snippets. Focus on architecture decisions.\nHighlight breaking changes and migration paths. Use developer terminology.`\n}\n","import { Persona } from '../engine'\n\nexport const ceo: Persona = {\n id: 'ceo',\n name: 'CEO / Executive',\n description: 'High-level business impact, concise',\n tone: 'executive',\n verbosity: 1,\n focus: ['business_impact', 'timeline', 'risk', 'resource_changes'],\n ignore: ['code_details', 'linting', 'formatting', 'minor_fixes'],\n format_preference: 'bullets',\n emoji_usage: false,\n jargon_level: 'none',\n system_prompt: `You are a CEO reading a technical update. \nBe extremely concise — 3 bullet points maximum. \nFocus on business impact, timelines, and risks. \nNo technical jargon. No code. Plain English only.`\n}\n","import { Persona } from '../engine'\n\nexport const dataAnalyst: Persona = {\n id: 'data-analyst',\n name: 'Data Analyst',\n description: 'Metrics-focused, chart-ready, statistical',\n tone: 'formal',\n verbosity: 3,\n focus: ['metrics', 'trends', 'patterns', 'statistics'],\n ignore: ['opinion', 'aesthetics'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'moderate',\n system_prompt: `You are a data analyst reviewing code changes.\nQuantify everything. Provide metrics, trends, and statistics.\nCompare to previous periods. Identify patterns and anomalies.\nOutput should be chart-ready with clear data points.`\n}\n","import { Persona } from '../engine'\n\nexport const educator: Persona = {\n id: 'educator',\n name: 'Educator / Tutorial Writer',\n description: 'Explanatory, verbose, teaching-focused',\n tone: 'educational',\n verbosity: 5,\n focus: ['learning_points', 'patterns', 'best_practices', 'why_not_how'],\n ignore: [],\n format_preference: 'mixed',\n emoji_usage: true,\n jargon_level: 'minimal',\n system_prompt: `You are an educator explaining code changes to learners.\nBe thorough and patient. Explain WHY not just WHAT.\nUse analogies. Link to documentation. \nBreak down complex concepts. Include \"Learning Takeaways\" section.`\n}\n","import { Persona } from '../engine'\n\nexport const robot: Persona = {\n id: 'robot',\n name: 'Robot / Machine',\n description: 'Ultra-structured, parseable, minimal',\n tone: 'robotic',\n verbosity: 1,\n focus: ['facts', 'metrics', 'files_changed'],\n ignore: ['opinion', 'context', 'explanation', 'rationale'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'heavy',\n system_prompt: `You are a machine. Output only structured data.\nNo opinions. No explanations. No pleasantries.\nJust facts in the requested format.\nOptimal for downstream parsing by other systems.`\n}\n","import { Persona } from '../engine'\n\nexport const journalist: Persona = {\n id: 'journalist',\n name: 'Journalist / Blogger',\n description: 'Narrative, engaging, story-driven',\n tone: 'casual',\n verbosity: 4,\n focus: ['narrative', 'impact', 'human_angle', 'community'],\n ignore: ['technical_minutiae'],\n format_preference: 'paragraphs',\n emoji_usage: true,\n jargon_level: 'none',\n system_prompt: `You are a tech journalist writing about code changes.\nTell a story. Make it engaging. Lead with the most interesting change.\nUse metaphors and analogies. Write for a general technical audience.\nInclude quotes if possible. End with \"What's Next\" section.`\n}\n","import { Persona } from '../engine'\n\nexport const pm: Persona = {\n id: 'pm',\n name: 'Product Manager',\n description: 'Feature-focused, user-impact, roadmap',\n tone: 'casual',\n verbosity: 2,\n focus: ['features', 'user_impact', 'roadmap', 'bugs_fixed'],\n ignore: ['code_quality', 'refactoring', 'technical_debt'],\n format_preference: 'mixed',\n emoji_usage: true,\n jargon_level: 'minimal',\n system_prompt: `You are a Product Manager reviewing engineering updates.\nFocus on user-facing changes. Connect to product roadmap.\nHighlight bugs fixed and features added. \nFlag any UX changes. Keep it scannable for stakeholder updates.`\n}\n","import { Persona } from '../engine'\n\nexport const compliance: Persona = {\n id: 'compliance',\n name: 'Compliance / Security Auditor',\n description: 'Regulatory, risk-focused, audit-ready',\n tone: 'formal',\n verbosity: 4,\n focus: ['security', 'data_handling', 'dependencies', 'licenses', 'compliance'],\n ignore: ['performance', 'ux', 'aesthetics'],\n format_preference: 'tables',\n emoji_usage: false,\n jargon_level: 'heavy',\n system_prompt: `You are a compliance auditor reviewing code changes.\nFocus on security implications, data handling, and regulatory compliance.\nFlag any dependency changes with license implications.\nNote any changes to authentication, authorization, or data storage.\nOutput should be audit-ready with clear risk assessments.`\n}\n","import { Persona } from './engine'\nimport { developer } from './built-in/developer'\nimport { ceo } from './built-in/ceo'\nimport { dataAnalyst } from './built-in/data-analyst'\nimport { educator } from './built-in/educator'\nimport { robot } from './built-in/robot'\nimport { journalist } from './built-in/journalist'\nimport { pm } from './built-in/pm'\nimport { compliance } from './built-in/compliance'\n\nexport const BUILTIN_PERSONAS: Record<string, Persona> = {\n developer,\n ceo,\n 'data-analyst': dataAnalyst,\n educator,\n robot,\n journalist,\n pm,\n compliance,\n}\n\nexport class PersonaRegistry {\n private static customPersonas: Map<string, Persona> = new Map()\n\n static get(id: string): Persona | undefined {\n return BUILTIN_PERSONAS[id] || this.customPersonas.get(id)\n }\n\n static register(persona: Persona): void {\n this.customPersonas.set(persona.id, persona)\n }\n\n static list(): Persona[] {\n return [\n ...Object.values(BUILTIN_PERSONAS),\n ...Array.from(this.customPersonas.values()),\n ]\n }\n\n static clearCustom(): void {\n this.customPersonas.clear()\n }\n}\n","import * as fs from 'fs/promises'\nimport * as path from 'path'\nimport yaml from 'js-yaml'\nimport { Persona } from './engine'\nimport { PersonaRegistry } from './registry'\n\nexport class CustomPersonaLoader {\n /**\n * Loads a custom persona from a YAML configuration file.\n * If the persona extends an existing persona, it will inherit and override properties.\n */\n static async loadFromFile(filePath: string): Promise<Persona> {\n const rawContent = await fs.readFile(filePath, 'utf-8')\n const parsed = yaml.load(rawContent) as Partial<Persona> & { extends?: string }\n\n if (!parsed.id) {\n throw new Error(`Custom persona file at ${filePath} is missing required 'id' field.`)\n }\n\n let basePersona: Partial<Persona> = {}\n if (parsed.extends) {\n const inherited = PersonaRegistry.get(parsed.extends)\n if (!inherited) {\n throw new Error(`Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`)\n }\n basePersona = { ...inherited }\n }\n\n // Merge base persona with overrides\n const mergedPersona: Persona = {\n id: parsed.id,\n name: parsed.name ?? basePersona.name ?? parsed.id,\n description: parsed.description ?? basePersona.description ?? '',\n tone: parsed.tone ?? basePersona.tone ?? 'technical',\n verbosity: parsed.verbosity ?? basePersona.verbosity ?? 3,\n focus: parsed.focus ?? basePersona.focus ?? [],\n ignore: parsed.ignore ?? basePersona.ignore ?? [],\n format_preference: parsed.format_preference ?? basePersona.format_preference ?? 'mixed',\n emoji_usage: parsed.emoji_usage ?? basePersona.emoji_usage ?? false,\n jargon_level: parsed.jargon_level ?? basePersona.jargon_level ?? 'moderate',\n system_prompt: parsed.system_prompt ?? basePersona.system_prompt ?? '',\n }\n\n PersonaRegistry.register(mergedPersona)\n return mergedPersona\n }\n\n /**\n * Discovers and loads all custom personas in a directory.\n */\n static async loadDirectory(dirPath: string): Promise<Persona[]> {\n const loaded: Persona[] = []\n try {\n const files = await fs.readdir(dirPath)\n for (const file of files) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n try {\n const persona = await this.loadFromFile(path.join(dirPath, file))\n loaded.push(persona)\n } catch (err) {\n console.error(`Failed to load custom persona from ${file}:`, err)\n }\n }\n }\n } catch (err) {\n // Directory may not exist, ignore\n }\n return loaded\n }\n}\n"],"mappings":"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","names":[]} | ||
| {"version":3,"sources":["../src/engine.ts","../src/built-in.ts","../src/registry.ts","../src/custom-loader.ts"],"sourcesContent":["export interface Persona {\n id: string;\n name: string;\n description: string;\n tone:\n \"formal\" | \"casual\" | \"technical\" | \"executive\" | \"educational\" | \"robotic\";\n verbosity: 1 | 2 | 3 | 4 | 5; // 1 = ultra-concise, 5 = exhaustive\n focus: string[]; // What to emphasize\n ignore: string[]; // What to omit\n format_preference: \"paragraphs\" | \"bullets\" | \"tables\" | \"mixed\";\n emoji_usage: boolean;\n jargon_level: \"none\" | \"minimal\" | \"moderate\" | \"heavy\";\n system_prompt: string;\n}\n\nexport class PersonaEngine {\n /**\n * Generates the system prompt to instruct the AI based on the Persona properties.\n */\n static generateSystemPrompt(persona: Persona): string {\n const focusStr =\n persona.focus.length > 0 ? `Focus on: ${persona.focus.join(\", \")}.` : \"\";\n const ignoreStr =\n persona.ignore.length > 0\n ? `Ignore or omit: ${persona.ignore.join(\", \")}.`\n : \"\";\n\n return `${persona.system_prompt}\n \nGuidelines for your response:\n- Tone: ${persona.tone}\n- Verbosity level: ${persona.verbosity}/5 (1 is ultra-concise/minimalist, 5 is extremely detailed and explanatory).\n- Format preference: ${persona.format_preference}.\n- Emojis: ${persona.emoji_usage ? \"Use emojis where appropriate to make the text lively.\" : \"DO NOT use emojis under any circumstance.\"}\n- Technical Jargon: ${persona.jargon_level} level.\n${focusStr}\n${ignoreStr}\n`;\n }\n\n /**\n * Post-processes the output to align it closer to the persona config (fallback filter).\n */\n static postProcess(output: string, persona: Persona): string {\n let result = output;\n\n // If emojis are disabled, clean them up\n if (!persona.emoji_usage) {\n // Basic emoji regex pattern to strip emojis\n result = result.replace(\n /[\\u{1F600}-\\u{1F64F}\\u{1F300}-\\u{1F5FF}\\u{1F680}-\\u{1F6FF}\\u{1F700}-\\u{1F77F}\\u{1F780}-\\u{1F7FF}\\u{1F800}-\\u{1F8FF}\\u{1F900}-\\u{1F9FF}\\u{1FA00}-\\u{1FAFF}\\u{2600}-\\u{26FF}\\u{2700}-\\u{27BF}]/gu,\n \"\",\n );\n }\n\n // Enforce verbosity constraint post-processing if necessary (e.g. ultra-concise max limits)\n if (persona.verbosity === 1) {\n const lines = result.split(\"\\n\");\n if (lines.length > 10) {\n // Just keeping it reasonably compact if it somehow exceeded\n }\n }\n\n return result.trim();\n }\n}\n","import { Persona } from \"./engine\";\n\nexport const BUILTIN_PERSONAS: Record<string, Persona> = {\n developer: {\n id: \"developer\",\n name: \"Developer\",\n description: \"Technical, precise, code-focused\",\n tone: \"technical\",\n verbosity: 3,\n focus: [\"code_changes\", \"architecture\", \"breaking_changes\"],\n ignore: [\"business_impact\", \"revenue\", \"marketing\"],\n format_preference: \"bullets\",\n emoji_usage: true,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a senior developer reviewing code changes. Be technical and precise.\",\n },\n ceo: {\n id: \"ceo\",\n name: \"CEO\",\n description: \"Executive summary, business-focused\",\n tone: \"executive\",\n verbosity: 1,\n focus: [\"business_impact\", \"timeline\", \"risk\"],\n ignore: [\"code_changes\", \"dependencies\"],\n format_preference: \"bullets\",\n emoji_usage: false,\n jargon_level: \"none\",\n system_prompt:\n \"You are a CEO reading a technical update. 3 bullet points maximum. No jargon.\",\n },\n educator: {\n id: \"educator\",\n name: \"Educator\",\n description: \"Educational, patient, explanatory\",\n tone: \"educational\",\n verbosity: 5,\n focus: [\"learning_points\", \"patterns\", \"best_practices\"],\n ignore: [\"internal_details\"],\n format_preference: \"paragraphs\",\n emoji_usage: true,\n jargon_level: \"minimal\",\n system_prompt:\n \"You are an educator explaining changes to learners. Be thorough and patient.\",\n },\n robot: {\n id: \"robot\",\n name: \"Robot\",\n description: \"Structured data, no opinions\",\n tone: \"robotic\",\n verbosity: 1,\n focus: [\"facts\", \"metrics\", \"files_changed\"],\n ignore: [\"commentary\", \"opinions\"],\n format_preference: \"tables\",\n emoji_usage: false,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a machine. Output only structured data. No opinions.\",\n },\n \"data-analyst\": {\n id: \"data-analyst\",\n name: \"Data Analyst\",\n description: \"Metrics, trends, statistics\",\n tone: \"formal\",\n verbosity: 3,\n focus: [\"metrics\", \"trends\", \"patterns\", \"statistics\"],\n ignore: [\"narratives\"],\n format_preference: \"tables\",\n emoji_usage: false,\n jargon_level: \"moderate\",\n system_prompt:\n \"You are a data analyst. Quantify everything. Provide metrics and trends.\",\n },\n journalist: {\n id: \"journalist\",\n name: \"Journalist\",\n description: \"Engaging story, human angle\",\n tone: \"casual\",\n verbosity: 4,\n focus: [\"narrative\", \"impact\", \"human_angle\"],\n ignore: [\"dry_stats\"],\n format_preference: \"paragraphs\",\n emoji_usage: true,\n jargon_level: \"none\",\n system_prompt: \"You are a tech journalist. Tell a story. Make it engaging.\",\n },\n pm: {\n id: \"pm\",\n name: \"Product Manager\",\n description: \"User impact, features, bugs\",\n tone: \"casual\",\n verbosity: 2,\n focus: [\"features\", \"user_impact\", \"roadmap\", \"bugs_fixed\"],\n ignore: [\"technical_jargon\"],\n format_preference: \"mixed\",\n emoji_usage: true,\n jargon_level: \"minimal\",\n system_prompt: \"You are a Product Manager. Focus on user-facing changes.\",\n },\n compliance: {\n id: \"compliance\",\n name: \"Compliance Auditor\",\n description: \"Security, compliance, licenses\",\n tone: \"formal\",\n verbosity: 4,\n focus: [\"security\", \"data_handling\", \"dependencies\", \"licenses\"],\n ignore: [\"marketing\", \"design\"],\n format_preference: \"mixed\",\n emoji_usage: false,\n jargon_level: \"heavy\",\n system_prompt:\n \"You are a compliance auditor. Focus on security and regulatory implications.\",\n },\n};\n","import { Persona } from \"./engine\";\nimport { BUILTIN_PERSONAS } from \"./built-in\";\n\nexport { BUILTIN_PERSONAS };\n\nexport class PersonaRegistry {\n private static customPersonas: Map<string, Persona> = new Map();\n\n static get(id: string): Persona | undefined {\n return BUILTIN_PERSONAS[id] || this.customPersonas.get(id);\n }\n\n static register(persona: Persona): void {\n this.customPersonas.set(persona.id, persona);\n }\n\n static list(): Persona[] {\n return [\n ...Object.values(BUILTIN_PERSONAS),\n ...Array.from(this.customPersonas.values()),\n ];\n }\n\n static clearCustom(): void {\n this.customPersonas.clear();\n }\n}\n","import * as fs from \"fs/promises\";\nimport * as path from \"path\";\nimport yaml from \"js-yaml\";\nimport { Persona } from \"./engine\";\nimport { PersonaRegistry } from \"./registry\";\n\nexport class CustomPersonaLoader {\n /**\n * Loads a custom persona from a YAML configuration file.\n * If the persona extends an existing persona, it will inherit and override properties.\n */\n static async loadFromFile(filePath: string): Promise<Persona> {\n const rawContent = await fs.readFile(filePath, \"utf-8\");\n const parsed = yaml.load(rawContent) as Partial<Persona> & {\n extends?: string;\n };\n\n if (!parsed.id) {\n throw new Error(\n `Custom persona file at ${filePath} is missing required 'id' field.`,\n );\n }\n\n let basePersona: Partial<Persona> = {};\n if (parsed.extends) {\n const inherited = PersonaRegistry.get(parsed.extends);\n if (!inherited) {\n throw new Error(\n `Persona '${parsed.id}' extends unknown persona '${parsed.extends}'.`,\n );\n }\n basePersona = { ...inherited };\n }\n\n // Merge base persona with overrides\n const mergedPersona: Persona = {\n id: parsed.id,\n name: parsed.name ?? basePersona.name ?? parsed.id,\n description: parsed.description ?? basePersona.description ?? \"\",\n tone: parsed.tone ?? basePersona.tone ?? \"technical\",\n verbosity: parsed.verbosity ?? basePersona.verbosity ?? 3,\n focus: parsed.focus ?? basePersona.focus ?? [],\n ignore: parsed.ignore ?? basePersona.ignore ?? [],\n format_preference:\n parsed.format_preference ?? basePersona.format_preference ?? \"mixed\",\n emoji_usage: parsed.emoji_usage ?? basePersona.emoji_usage ?? false,\n jargon_level:\n parsed.jargon_level ?? basePersona.jargon_level ?? \"moderate\",\n system_prompt: parsed.system_prompt ?? basePersona.system_prompt ?? \"\",\n };\n\n PersonaRegistry.register(mergedPersona);\n return mergedPersona;\n }\n\n /**\n * Discovers and loads all custom personas in a directory.\n */\n static async loadDirectory(dirPath: string): Promise<Persona[]> {\n const loaded: Persona[] = [];\n try {\n const files = await fs.readdir(dirPath);\n for (const file of files) {\n if (file.endsWith(\".yaml\") || file.endsWith(\".yml\")) {\n try {\n const persona = await this.loadFromFile(path.join(dirPath, file));\n loaded.push(persona);\n } catch (err) {\n console.error(`Failed to load custom persona from ${file}:`, err);\n }\n }\n }\n } catch (err) {\n // Directory may not exist, ignore\n }\n return loaded;\n }\n}\n"],"mappings":"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","names":[]} |
+1
-1
| { | ||
| "name": "@eldrex/personas", | ||
| "version": "1.0.0", | ||
| "version": "1.0.2", | ||
| "description": "Personality engine for DevDiff — AI output formatting and tones", | ||
@@ -5,0 +5,0 @@ "type": "module", |
51396
-12.78%551
-10.41%