Files
cursor2api/test/unit-handler-truncation.mjs
小海 2933df2697 fix: improve truncation recovery and diagnostics for v2.7.7
- mark degraded requests in logs and viewer when execution quality drops
- record Anthropic toolCallsDetected correctly in summaries
- continue semantically incomplete long Write/Edit tool payloads
- restore truncated OpenAI stream long Write tool_calls
- update release docs, sample config, docker notes, and README guidance
2026-03-23 11:39:00 +08:00

157 lines
4.2 KiB
JavaScript

import { shouldAutoContinueTruncatedToolResponse } from '../dist/handler.js';
let passed = 0;
let failed = 0;
function test(name, fn) {
try {
fn();
console.log(` OK ${name}`);
passed++;
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.error(` FAIL ${name}`);
console.error(` ${message}`);
failed++;
}
}
function assertEqual(actual, expected, message) {
if (actual !== expected) {
throw new Error(message || `Expected ${expected}, got ${actual}`);
}
}
console.log('\nhandler continuation detection\n');
test('short-argument Read tool can be recovered without continuation', () => {
const text = [
'I will read the config first.',
'',
'```json action',
'{',
' "tool": "Read",',
' "parameters": {',
' "file_path": "/app/config.yaml"',
' }',
].join('\n');
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
false,
'Read-like short tool calls should not force continuation',
);
});
test('large Write payload still needs continuation when the action block is unclosed', () => {
const longContent = 'A'.repeat(4000);
const text = [
'```json action',
'{',
' "tool": "Write",',
' "parameters": {',
' "file_path": "/tmp/large.txt",',
` "content": "${longContent}`,
].join('\n');
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
true,
'Large Write payloads should continue until parameters are complete',
);
});
test('short non-action code block truncation should not continue', () => {
const text = '```ts\nexport const answer = {';
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
false,
'Very short non-action code blocks should not trigger continuation',
);
});
test('an unclosed json action block still continues even when very short', () => {
const text = '```json action\n{\n "tool": "Write",';
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
true,
'Unclosed json action blocks should always continue',
);
});
test('a closed large Write that ends on a dangling table row should continue', () => {
const content = 'A'.repeat(1800) + '\n' + [
'# Summary',
'',
'## API',
'',
'| Path | Method | Notes |',
'|------|--------|-------|',
'| /v1/messages | POST | Anthropic Messages API |',
'| /v1/models | GET | Model list |',
'|',
].join('\n');
const text = [
'```json action',
'{',
' "tool": "Write",',
' "parameters": {',
' "file_path": "/tmp/summary.md",',
` "content": ${JSON.stringify(content)}`,
' }',
'}',
'```',
].join('\n');
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
true,
'Large closed Write payloads that clearly stop mid-structure should continue',
);
});
test('a closed large Write with a clean ending should not continue', () => {
const content = [
'# Summary',
'',
'## API',
'',
'| Path | Method | Notes |',
'|------|--------|-------|',
'| /v1/messages | POST | Anthropic Messages API |',
'| /v1/models | GET | Model list |',
'',
'## References',
'',
'- README.md',
'- CHANGELOG.md',
'',
'Completed.',
].join('\n') + '\n' + 'A'.repeat(1800) + '\nDone.\n';
const text = [
'```json action',
'{',
' "tool": "Write",',
' "parameters": {',
' "file_path": "/tmp/summary.md",',
` "content": ${JSON.stringify(content)}`,
' }',
'}',
'```',
].join('\n');
assertEqual(
shouldAutoContinueTruncatedToolResponse(text, true),
false,
'Large closed Write payloads with a clean ending should not be misclassified',
);
});
console.log(`\nresult: ${passed} passed / ${failed} failed / ${passed + failed} total\n`);
if (failed > 0) process.exit(1);