File size: 4,319 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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);