import { MAX_LINE } from './examples' import type { IndexEntry } from './retrieval' import { isFunctionTag } from './tags' const DEFAULT_DIR = '.claude/anime-companion' // 對白索引由建置流水線產生,放在使用者資料目錄(不在插件裡、不入版本控制)。 // dataDir 留空時用 ~/.claude/anime-companion;找不到家目錄就回傳 null。 export function indexPath(dataDir: string, home: string | undefined, code: string): string | null { const base = dataDir.trim() !== '' ? dataDir.trim() : home ? `${home}/${DEFAULT_DIR}` : null return base === null ? null : `${base.replace(/\/+$/, '')}/${code}/index.jsonl` } // 一行一筆;格式不對的行略過,不讓壞掉的資料擋住載入。 export function parseIndex(text: string): IndexEntry[] { const out: IndexEntry[] = [] for (const line of text.split('\n')) { if (line.trim() === '') continue try { const e = JSON.parse(line) as Record if ( typeof e.id === 'string' && isFunctionTag(e.function) && typeof e.emotion === 'string' && (e.mode === null || typeof e.mode === 'string') && typeof e.text === 'string' && e.text.length > 0 && e.text.length <= MAX_LINE ) { out.push({ id: e.id, function: e.function, emotion: e.emotion, mode: e.mode, text: e.text }) } } catch { // 略過壞行 } } return out } export async function loadIndex(read: (path: string) => Promise, path: string | null): Promise { if (path === null) return [] try { return parseIndex(await read(path)) } catch { return [] } }