diff options
Diffstat (limited to 'modules/test/test-tool-context-bound.js')
| -rw-r--r-- | modules/test/test-tool-context-bound.js | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/modules/test/test-tool-context-bound.js b/modules/test/test-tool-context-bound.js index 0b42eeb..848b307 100644 --- a/modules/test/test-tool-context-bound.js +++ b/modules/test/test-tool-context-bound.js @@ -103,6 +103,23 @@ function ok(name, cond, detail) { ok('E4 clip shortens content', parsed && parsed.content.length < 16000 && parsed.content.length >= 3000, parsed && String(parsed.content.length)); ok('E5 clipped envelope fits the limit', clipped.length <= 6000 + 400, String(clipped.length)); + + // E6-E8: the last page of a file has next_offset=null. If the clip removes its tail, + // telling the caller "truncated: false" hides the remainder with no way to ask for it + // (measured 2026-11-02: 8 109 of 19 999 chars withheld, returned claimed 19 999). + const lastPage = JSON.stringify({ + path: '/big.txt', offset: 0, returned: 19999, total_chars: 19999, + truncated: false, next_offset: null, + content: 'y'.repeat(19999), + }); + const lc = ai._clipToolResult(lastPage); + let lp = null; + try { lp = JSON.parse(lc); } catch (e) {} + ok('E6 a clipped last page reports truncated=true', lp && lp.truncated === true, lp && String(lp.truncated)); + ok('E7 it gives a resumable next_offset', lp && lp.next_offset === lp.returned_chars, + lp && String(lp.next_offset) + ' vs ' + String(lp.returned_chars)); + ok('E8 returned no longer claims the whole file', lp && lp.returned === lp.returned_chars, + lp && String(lp.returned)); } // F. budgets are resolvable per model class, with precedence call arg > profile > ai-config > default |