chat / src /lib /server /metacognitiveConfig.ts
Andrew
feat(tree): Add ELK port-based layout and persona-specific branching
cb5990d
/**
* Metacognitive Prompts Configuration
*
* Parses environment variables for metacognitive prompt feature:
* - METACOGNITIVE_FREQUENCIES: Comma-separated list of integers (e.g., "3,5,10")
* - METACOGNITIVE_PROMPTS_COMPREHENSION: JSON array of prompt templates
* - METACOGNITIVE_PROMPTS_PERSPECTIVE: JSON array of prompt templates with {{personaName}} placeholder
*/
import { config } from "./config";
import { logger } from "./logger";
export interface MetacognitiveConfig {
frequencies: number[];
comprehensionPrompts: string[];
perspectivePrompts: string[];
enabled: boolean;
}
const DEFAULT_FREQUENCIES = [5];
const DEFAULT_COMPREHENSION_PROMPTS = [
"Is there anything in this response that you do not fully understand? If yes, try asking a follow-up question.",
];
const DEFAULT_PERSPECTIVE_PROMPTS = [
"Want to know what {{personaName}} thinks about this?",
"You've been talking with the same persona for a while. Maybe see what {{personaName}} would say?",
];
function parseFrequencies(value: string | undefined): number[] {
if (!value || value.trim() === "") {
return DEFAULT_FREQUENCIES;
}
try {
const parsed = value
.split(",")
.map((s) => parseInt(s.trim(), 10))
.filter((n) => !isNaN(n) && n > 0);
if (parsed.length === 0) {
logger.warn("METACOGNITIVE_FREQUENCIES parsed to empty array, using defaults");
return DEFAULT_FREQUENCIES;
}
return parsed;
} catch (e) {
logger.error(e, "Failed to parse METACOGNITIVE_FREQUENCIES");
return DEFAULT_FREQUENCIES;
}
}
function parsePrompts(value: string | undefined, defaults: string[]): string[] {
if (!value || value.trim() === "") {
return defaults;
}
try {
const parsed = JSON.parse(value);
if (Array.isArray(parsed) && parsed.length > 0 && parsed.every((p) => typeof p === "string")) {
return parsed;
}
logger.warn("Parsed prompts not a valid string array, using defaults");
return defaults;
} catch (e) {
logger.error(e, "Failed to parse metacognitive prompts JSON");
return defaults;
}
}
let cachedConfig: MetacognitiveConfig | null = null;
export function getMetacognitiveConfig(): MetacognitiveConfig {
if (cachedConfig) {
return cachedConfig;
}
const frequencies = parseFrequencies(config.METACOGNITIVE_FREQUENCIES);
const comprehensionPrompts = parsePrompts(
config.METACOGNITIVE_PROMPTS_COMPREHENSION,
DEFAULT_COMPREHENSION_PROMPTS
);
const perspectivePrompts = parsePrompts(
config.METACOGNITIVE_PROMPTS_PERSPECTIVE,
DEFAULT_PERSPECTIVE_PROMPTS
);
// Feature is enabled if frequencies are configured (even defaults)
const enabled = frequencies.length > 0;
cachedConfig = {
frequencies,
comprehensionPrompts,
perspectivePrompts,
enabled,
};
logger.info(
{
frequencies,
comprehensionPromptsCount: comprehensionPrompts.length,
perspectivePromptsCount: perspectivePrompts.length,
enabled,
},
"Metacognitive config loaded"
);
return cachedConfig;
}
/**
* Select a random frequency from the configured list
*/
export function selectRandomFrequency(): number {
const { frequencies } = getMetacognitiveConfig();
return frequencies[Math.floor(Math.random() * frequencies.length)];
}
/**
* Select a random comprehension prompt
*/
export function selectComprehensionPrompt(): string {
const { comprehensionPrompts } = getMetacognitiveConfig();
return comprehensionPrompts[Math.floor(Math.random() * comprehensionPrompts.length)];
}
/**
* Select a random perspective prompt and substitute the persona name
*/
export function selectPerspectivePrompt(personaName: string): string {
const { perspectivePrompts } = getMetacognitiveConfig();
const template = perspectivePrompts[Math.floor(Math.random() * perspectivePrompts.length)];
return template.replace(/\{\{personaName\}\}/g, personaName);
}