2026-06-22 05:59:28 +03:00
|
|
|
|
// Чистый разбор хвоста стенограммы: последний обмен (user + assistant + действия).
|
|
|
|
|
|
// Схема сверена с observer-transcript-parser: entry.message.role / entry.message.content
|
|
|
|
|
|
// (строка или массив блоков text/tool_use{name,input}).
|
|
|
|
|
|
|
|
|
|
|
|
function parseLines(text) {
|
|
|
|
|
|
const entries = [];
|
|
|
|
|
|
for (const line of String(text || '').split(/\r?\n/)) {
|
|
|
|
|
|
const t = line.trim();
|
|
|
|
|
|
if (!t) continue;
|
|
|
|
|
|
try { entries.push(JSON.parse(t)); } catch { /* битую строку пропускаем */ }
|
|
|
|
|
|
}
|
|
|
|
|
|
return entries;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-22 07:21:09 +03:00
|
|
|
|
// Настоящий промпт пользователя (НЕ tool_result): content — строка или массив с text-блоком.
|
|
|
|
|
|
// В формате Anthropic tool_result — это сообщения role:user, их пропускаем, иначе теряются
|
|
|
|
|
|
// и настоящий промпт, и все действия ассистента до него.
|
|
|
|
|
|
function isRealUserPrompt(msg) {
|
|
|
|
|
|
if (!msg || msg.role !== 'user') return false;
|
|
|
|
|
|
const c = msg.content;
|
|
|
|
|
|
if (typeof c === 'string') return true;
|
|
|
|
|
|
if (Array.isArray(c)) return c.some((b) => b && b.type === 'text');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-22 05:59:28 +03:00
|
|
|
|
/** Последний обмен из стенограммы: { user, assistant, actions:[{tool,input}] }. */
|
|
|
|
|
|
export function parseLastExchange(transcriptText) {
|
|
|
|
|
|
const entries = parseLines(transcriptText);
|
|
|
|
|
|
let u = -1;
|
|
|
|
|
|
for (let i = entries.length - 1; i >= 0; i--) {
|
2026-06-22 07:21:09 +03:00
|
|
|
|
if (entries[i] && isRealUserPrompt(entries[i].message)) { u = i; break; }
|
2026-06-22 05:59:28 +03:00
|
|
|
|
}
|
|
|
|
|
|
const userContent = u >= 0 ? entries[u].message.content : '';
|
|
|
|
|
|
const user = typeof userContent === 'string'
|
|
|
|
|
|
? userContent
|
|
|
|
|
|
: (Array.isArray(userContent)
|
|
|
|
|
|
? userContent.filter((b) => b && b.type === 'text').map((b) => b.text).join('\n')
|
|
|
|
|
|
: '');
|
|
|
|
|
|
|
|
|
|
|
|
let assistant = '';
|
|
|
|
|
|
const actions = [];
|
|
|
|
|
|
for (let i = u + 1; i < entries.length; i++) {
|
|
|
|
|
|
const m = entries[i] && entries[i].message;
|
|
|
|
|
|
if (!m || m.role !== 'assistant') continue;
|
|
|
|
|
|
const c = m.content;
|
|
|
|
|
|
if (Array.isArray(c)) {
|
|
|
|
|
|
for (const b of c) {
|
|
|
|
|
|
if (b && b.type === 'text' && b.text) assistant += (assistant ? '\n' : '') + b.text;
|
|
|
|
|
|
if (b && b.type === 'tool_use') actions.push({ tool: b.name, input: JSON.stringify(b.input ?? {}) });
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (typeof c === 'string') {
|
|
|
|
|
|
assistant += (assistant ? '\n' : '') + c;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return { user, assistant, actions };
|
|
|
|
|
|
}
|