101c08d447
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 lines
2.3 KiB
JavaScript
46 lines
2.3 KiB
JavaScript
// LLM-извлечение сути (обёртка зовёт мотор; здесь — чистые prompt-builder + parser).
|
|
|
|
/** Собрать запрос к LLM: из последнего обмена + списка открытых дел → {system, user}. */
|
|
export function buildExtractionPrompt({ lastExchange = {}, worksIndex = [] } = {}) {
|
|
const system = [
|
|
'Ты — секретарь протокола работ. Извлеки СУТЬ последнего обмена по 9 пунктам.',
|
|
'Верни ТОЛЬКО JSON без markdown, поля:',
|
|
'{ "work":"<slug дела или NEW>", "decisions":[{"text","why","turns":[]}],',
|
|
' "supersede":[{"oldText","newText","turns":[]}], "will":[{"text","turns":[]}],',
|
|
' "open":[{"text","turns":[]}], "doneNext":[{"text","done":false,"turns":[]}] }',
|
|
'Если сути нет — все массивы пустые.',
|
|
].join('\n');
|
|
const works = worksIndex.length
|
|
? worksIndex.map((w) => `- ${w.slug}: ${w.title} — ${w.goal}`).join('\n')
|
|
: '(нет открытых дел)';
|
|
const acts = (lastExchange.actions ?? []).map((a) => a.tool).join(', ') || '—';
|
|
const user = [
|
|
'Открытые дела:', works, '',
|
|
'Последний обмен:',
|
|
`Пользователь: ${lastExchange.user ?? ''}`,
|
|
`Ассистент: ${lastExchange.assistant ?? ''}`,
|
|
`Действия: ${acts}`,
|
|
'', 'Извлеки суть. Верни JSON.',
|
|
].join('\n');
|
|
return { system, user };
|
|
}
|
|
|
|
/** Разобрать ответ LLM в структуру для applyExtraction; null при сбое (тихо). */
|
|
export function parseExtractionResponse(llmText) {
|
|
if (typeof llmText !== 'string' || !llmText.trim()) return null;
|
|
let s = llmText.trim().replace(/^```(?:json)?\s*\n?/, '').replace(/\n?```$/, '').trim();
|
|
s = s.replace(/,(\s*[}\]])/g, '$1'); // хвостовые запятые — частый quirk LLM
|
|
let parsed;
|
|
try { parsed = JSON.parse(s); } catch { return null; }
|
|
if (!parsed || typeof parsed !== 'object') return null;
|
|
const arr = (x) => (Array.isArray(x) ? x : []);
|
|
return {
|
|
work: typeof parsed.work === 'string' ? parsed.work : null,
|
|
decisions: arr(parsed.decisions),
|
|
supersede: arr(parsed.supersede),
|
|
will: arr(parsed.will),
|
|
open: arr(parsed.open),
|
|
doneNext: arr(parsed.doneNext),
|
|
};
|
|
}
|