learning_ai_common_plat/packages/palace/src/halls.ts
saravanakumardb1 d1c6cf47c8 feat(palace): add @bytelyst/palace shared package — MemPalace primitives (91 tests)
New shared package: packages/palace/ (@bytelyst/palace)

Modules:
- types.ts — BasePalaceWingDoc, RoomDoc, MemoryDoc, TunnelDoc, KGTripleDoc, DiaryDoc
- halls.ts — HallType union, HALL_PRESETS (notelett/mindlyst/coding), hallFromLabel()
- cosine.ts — cosineSimilarity(), topKByCosine(), normalizeVector()
- dedup.ts — isContentDuplicate(), isExactDuplicate(), findClosestMatch()
- decay.ts — computeDecayedRelevance(), boostRelevance()
- extraction.ts — buildExtractionPrompt(), parseExtractionResponse(), regexFallbackExtraction()
- kg.ts — findContradictions(), mergeTriples(), isTripleCurrent()
- wakeup.ts — buildWakeUpLayers(), truncateToTokenBudget(), WAKEUP_PRESETS
- config.ts — palaceConfigSchema (Zod)

7 test files, 91 tests passing.
Consumed by NoteLett, MindLyst, and future palace-enabled products.
2026-04-10 00:57:00 -07:00

104 lines
2.7 KiB
TypeScript

/**
* Hall types and presets for different products.
*
* Each product picks a preset (or defines custom halls).
* Halls categorize memories by type — decisions, events, discoveries, etc.
*/
export const ALL_HALL_TYPES = [
'decisions',
'events',
'discoveries',
'preferences',
'advice',
'insights',
'patterns',
'emotions',
'errors',
] as const;
export type HallType = (typeof ALL_HALL_TYPES)[number];
export interface HallPreset {
name: string;
halls: HallType[];
}
/**
* Product-specific hall presets.
*
* - notelett: insights instead of errors (note-taking domain)
* - mindlyst: patterns + emotions (multimodal/emotional domain)
* - coding: errors + advice (developer/agent domain, e.g. Claw-Cowork)
*/
export const HALL_PRESETS: Record<string, HallPreset> = {
notelett: {
name: 'NoteLett',
halls: ['decisions', 'events', 'discoveries', 'preferences', 'advice', 'insights'],
},
mindlyst: {
name: 'MindLyst',
halls: ['decisions', 'events', 'discoveries', 'preferences', 'patterns', 'emotions'],
},
coding: {
name: 'Coding Agent',
halls: ['decisions', 'events', 'discoveries', 'preferences', 'advice', 'errors'],
},
};
/**
* Get a hall preset by name.
* Returns undefined if the preset does not exist.
*/
export function getHallPreset(presetName: string): HallPreset | undefined {
return HALL_PRESETS[presetName];
}
/**
* Classify a label string to the closest hall type.
* Case-insensitive, tries exact match first, then substring.
* Returns undefined if no match.
*/
export function hallFromLabel(label: string, allowedHalls?: HallType[]): HallType | undefined {
const normalized = label.toLowerCase().trim();
const candidates = allowedHalls ?? (ALL_HALL_TYPES as unknown as HallType[]);
// Exact match
const exact = candidates.find(h => h === normalized);
if (exact) return exact;
// Substring match (e.g. "decision" → "decisions")
const partial = candidates.find(h => h.startsWith(normalized) || normalized.startsWith(h));
if (partial) return partial;
// Common synonyms
const synonymMap: Record<string, HallType> = {
decision: 'decisions',
event: 'events',
discovery: 'discoveries',
preference: 'preferences',
insight: 'insights',
pattern: 'patterns',
emotion: 'emotions',
error: 'errors',
fact: 'discoveries',
finding: 'discoveries',
todo: 'decisions',
task: 'decisions',
bug: 'errors',
fix: 'decisions',
feeling: 'emotions',
mood: 'emotions',
trend: 'patterns',
recurring: 'patterns',
tip: 'advice',
recommendation: 'advice',
suggestion: 'advice',
};
const synonym = synonymMap[normalized];
if (synonym && candidates.includes(synonym)) return synonym;
return undefined;
}