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.
104 lines
2.7 KiB
TypeScript
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;
|
|
}
|