87 lines
2.7 KiB
JavaScript
87 lines
2.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { repairConversationToolHistory } from './chat-tool-history-repair.mjs';
|
|
|
|
function toolRequest(id, name = 'write_file') {
|
|
return {
|
|
role: 'assistant',
|
|
content: [{
|
|
type: 'toolRequest',
|
|
id,
|
|
toolCall: { status: 'success', value: { name, arguments: {} } },
|
|
}],
|
|
};
|
|
}
|
|
|
|
function toolResponse(id) {
|
|
return {
|
|
role: 'user',
|
|
content: [{
|
|
type: 'toolResponse',
|
|
id,
|
|
toolResult: {
|
|
status: 'success',
|
|
value: { content: [{ type: 'text', text: 'ok' }], isError: false },
|
|
},
|
|
}],
|
|
};
|
|
}
|
|
|
|
test('repairConversationToolHistory pairs interleaved and reversed tool responses', () => {
|
|
const conversation = [
|
|
{ role: 'user', content: [{ type: 'text', text: '生成页面' }] },
|
|
toolRequest('call-a'),
|
|
toolRequest('call-b'),
|
|
toolResponse('call-b'),
|
|
{ role: 'assistant', content: [{ type: 'text', text: '继续处理' }] },
|
|
toolResponse('call-a'),
|
|
toolResponse('call-c'),
|
|
toolRequest('call-c'),
|
|
{ role: 'assistant', content: [{ type: 'text', text: '完成' }] },
|
|
];
|
|
|
|
const result = repairConversationToolHistory(conversation);
|
|
|
|
assert.equal(result.changed, true);
|
|
assert.deepEqual(
|
|
result.conversation.map((message) => message.content[0]?.id ?? message.content[0]?.text),
|
|
['生成页面', 'call-a', 'call-a', 'call-b', 'call-b', '继续处理', 'call-c', 'call-c', '完成'],
|
|
);
|
|
assert.equal(result.repairedToolResponses, 3);
|
|
assert.equal(result.droppedToolRequests, 0);
|
|
assert.equal(result.droppedOrphanResponses, 0);
|
|
});
|
|
|
|
test('repairConversationToolHistory leaves valid tool history unchanged', () => {
|
|
const conversation = [
|
|
{ role: 'user', content: [{ type: 'text', text: '生成页面' }] },
|
|
toolRequest('call-a'),
|
|
toolResponse('call-a'),
|
|
{ role: 'assistant', content: [{ type: 'text', text: '完成' }] },
|
|
];
|
|
|
|
const result = repairConversationToolHistory(conversation);
|
|
|
|
assert.equal(result.changed, false);
|
|
assert.equal(result.conversation, conversation);
|
|
});
|
|
|
|
test('repairConversationToolHistory drops unmatched requests and orphan responses', () => {
|
|
const conversation = [
|
|
{ role: 'user', content: [{ type: 'text', text: '生成页面' }] },
|
|
toolRequest('call-missing'),
|
|
toolResponse('call-orphan'),
|
|
{ role: 'assistant', content: [{ type: 'text', text: '稍后继续' }] },
|
|
];
|
|
|
|
const result = repairConversationToolHistory(conversation);
|
|
|
|
assert.equal(result.changed, true);
|
|
assert.deepEqual(
|
|
result.conversation.map((message) => message.content[0]?.text),
|
|
['生成页面', '稍后继续'],
|
|
);
|
|
assert.equal(result.droppedToolRequests, 1);
|
|
assert.equal(result.droppedOrphanResponses, 1);
|
|
});
|