File size: 4,954 Bytes
097fb32 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | /**
* test/unit-log-persist-compact.mjs
*
* 回归测试:compact 落盘模式应保留摘要信息,同时显著压缩 JSONL payload。
* 运行方式:npm run build && node test/unit-log-persist-compact.mjs
*/
import fs from 'fs';
import path from 'path';
const LOG_DIR = '/tmp/cursor2api-log-compact';
process.env.LOG_FILE_ENABLED = '1';
process.env.LOG_DIR = LOG_DIR;
process.env.LOG_PERSIST_MODE = 'compact';
const { createRequestLogger, clearAllLogs, getRequestPayload } = await import('../dist/logger.js');
let passed = 0;
let failed = 0;
function assert(condition, msg) {
if (!condition) throw new Error(msg || 'Assertion failed');
}
function assertEqual(a, b, msg) {
const as = JSON.stringify(a);
const bs = JSON.stringify(b);
if (as !== bs) throw new Error(msg || `Expected ${bs}, got ${as}`);
}
function resetLogs() {
clearAllLogs();
fs.rmSync(LOG_DIR, { recursive: true, force: true });
}
function latestPersistedRecord() {
const files = fs.readdirSync(LOG_DIR).filter(name => name.endsWith('.jsonl')).sort();
assert(files.length > 0, '应生成 JSONL 文件');
const lastFile = path.join(LOG_DIR, files[files.length - 1]);
const lines = fs.readFileSync(lastFile, 'utf8').split('\n').filter(Boolean);
assert(lines.length > 0, 'JSONL 文件不应为空');
return JSON.parse(lines[lines.length - 1]);
}
async function runTest(name, fn) {
try {
resetLogs();
await fn();
console.log(` ✅ ${name}`);
passed++;
} catch (e) {
console.error(` ❌ ${name}`);
console.error(` ${e.message}`);
failed++;
}
}
console.log('\n📦 [1] compact 落盘模式回归\n');
await runTest('磁盘 payload 应截断长文本并去掉重复 rawResponse', async () => {
const hugePrompt = 'PROMPT-'.repeat(1200);
const hugeResponse = 'RESPONSE-'.repeat(1600);
const hugeCursor = 'CURSOR-'.repeat(900);
const hugeToolDesc = 'DESC-'.repeat(500);
const logger = createRequestLogger({
method: 'POST',
path: '/v1/chat/completions',
model: 'gpt-4.1',
stream: true,
hasTools: true,
toolCount: 1,
messageCount: 1,
apiFormat: 'openai',
});
logger.recordOriginalRequest({
model: 'gpt-4.1',
stream: true,
temperature: 0.2,
messages: [{ role: 'user', content: hugePrompt }],
tools: [{
type: 'function',
function: {
name: 'write_file',
description: hugeToolDesc,
},
}],
});
logger.recordCursorRequest({
model: 'anthropic/claude-sonnet-4.6',
messages: [{
role: 'user',
parts: [{ type: 'text', text: hugeCursor }],
}],
});
logger.recordToolCalls([{
name: 'write_file',
arguments: {
path: '/tmp/demo.txt',
content: 'X'.repeat(5000),
},
}]);
logger.recordRawResponse(hugeResponse);
logger.recordFinalResponse(hugeResponse);
logger.complete(hugeResponse.length, 'stop');
const persisted = latestPersistedRecord();
const diskPayload = persisted.payload;
const memoryPayload = getRequestPayload(persisted.summary.requestId);
assert(memoryPayload, '内存 payload 应存在');
assert(memoryPayload.rawResponse.length > diskPayload.finalResponse.length, '内存 payload 应保留完整文本');
assertEqual(persisted.summary.status, 'success');
assert(diskPayload.finalResponse.length < hugeResponse.length, '落盘 finalResponse 应被截断');
assert(diskPayload.finalResponse.includes('...[截断 '), '落盘 finalResponse 应标记截断');
assertEqual(diskPayload.rawResponse, undefined, 'rawResponse 与 finalResponse 相同,应省略落盘 rawResponse');
assert(diskPayload.messages[0].contentPreview.length < hugePrompt.length, '落盘消息预览应被截断');
assert(diskPayload.messages[0].contentPreview.includes('...[截断 '), '落盘消息预览应标记截断');
assert(diskPayload.cursorMessages[0].contentPreview.length < hugeCursor.length, '落盘 Cursor 消息应被截断');
assert(diskPayload.tools[0].description.length < hugeToolDesc.length, '落盘工具描述应被截断');
assert(diskPayload.originalRequest.messageCount === 1, '落盘 originalRequest 应转为精简 meta');
assertEqual(Array.isArray(diskPayload.originalRequest.messages), false, '落盘 originalRequest 不应保留完整 messages 数组');
const compactToolCalls = JSON.stringify(diskPayload.toolCalls);
assert(compactToolCalls.length < JSON.stringify(memoryPayload.toolCalls).length, '落盘 toolCalls 应被递归压缩');
});
console.log('\n' + '═'.repeat(55));
console.log(` 结果: ${passed} 通过 / ${failed} 失败 / ${passed + failed} 总计`);
console.log('═'.repeat(55) + '\n');
if (failed > 0) process.exit(1);
|