feat(secretary): захват выдачи инструмента (N3) + сверка имени дела при включении (N2)
- parseLastExchange привязывает результат инструмента к действию по tool_use_id, склеивает text-блоки, усекает до 1200 симв.; [ВЫДАЧА] в Слое 1 теперь наполняется - resolveCaseActivation: похожее имя дела (опечатка/подстрока) -> переспросить, не заводя дело-двойник; хук secretary-prompt-hook выводит подсказку с кандидатами - TDD: тесты secretary-transcript/flag/prompt-hook; полный свод зелёный Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -39,3 +39,50 @@ describe('parseLastExchange', () => {
|
||||
expect(ex.actions).toEqual([{ tool: 'Read', input: '{"f":"a"}' }]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseLastExchange — захват выдачи инструмента (tool_result по tool_use_id)', () => {
|
||||
it('привязывает результат к действию по совпадающему id', () => {
|
||||
const t = [
|
||||
JSON.stringify({ message: { role: 'user', content: 'вопрос' } }),
|
||||
JSON.stringify({ message: { role: 'assistant', content: [
|
||||
{ type: 'tool_use', id: 'tu_1', name: 'Read', input: { f: 'a' } }] } }),
|
||||
JSON.stringify({ message: { role: 'user', content: [
|
||||
{ type: 'tool_result', tool_use_id: 'tu_1', content: 'СОДЕРЖИМОЕ ФАЙЛА' }] } }),
|
||||
].join('\n');
|
||||
const ex = parseLastExchange(t);
|
||||
expect(ex.actions).toEqual([{ tool: 'Read', input: '{"f":"a"}', result: 'СОДЕРЖИМОЕ ФАЙЛА' }]);
|
||||
});
|
||||
it('результат из массива text-блоков склеивается', () => {
|
||||
const t = [
|
||||
JSON.stringify({ message: { role: 'user', content: 'в' } }),
|
||||
JSON.stringify({ message: { role: 'assistant', content: [
|
||||
{ type: 'tool_use', id: 'tu_9', name: 'Bash', input: {} }] } }),
|
||||
JSON.stringify({ message: { role: 'user', content: [
|
||||
{ type: 'tool_result', tool_use_id: 'tu_9', content: [{ type: 'text', text: 'строка вывода' }] }] } }),
|
||||
].join('\n');
|
||||
const ex = parseLastExchange(t);
|
||||
expect(ex.actions[0].result).toBe('строка вывода');
|
||||
});
|
||||
it('длинный результат усечён и оканчивается маркером …', () => {
|
||||
const big = 'x'.repeat(5000);
|
||||
const t = [
|
||||
JSON.stringify({ message: { role: 'user', content: 'в' } }),
|
||||
JSON.stringify({ message: { role: 'assistant', content: [
|
||||
{ type: 'tool_use', id: 'tu_2', name: 'Read', input: {} }] } }),
|
||||
JSON.stringify({ message: { role: 'user', content: [
|
||||
{ type: 'tool_result', tool_use_id: 'tu_2', content: big }] } }),
|
||||
].join('\n');
|
||||
const ex = parseLastExchange(t);
|
||||
expect(ex.actions[0].result.length).toBeLessThan(big.length);
|
||||
expect(ex.actions[0].result.endsWith('…')).toBe(true);
|
||||
});
|
||||
it('без совпадающего id результат не привязывается — старая форма {tool,input} цела', () => {
|
||||
const t = [
|
||||
JSON.stringify({ message: { role: 'user', content: 'в' } }),
|
||||
JSON.stringify({ message: { role: 'assistant', content: [
|
||||
{ type: 'tool_use', id: 'tu_3', name: 'Read', input: { f: 'z' } }] } }),
|
||||
].join('\n');
|
||||
const ex = parseLastExchange(t);
|
||||
expect(ex.actions).toEqual([{ tool: 'Read', input: '{"f":"z"}' }]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user