diff options
Diffstat (limited to 'modules/test/test-tool-context-bound.js')
| -rw-r--r-- | modules/test/test-tool-context-bound.js | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/modules/test/test-tool-context-bound.js b/modules/test/test-tool-context-bound.js index 8cf2a5e..0b42eeb 100644 --- a/modules/test/test-tool-context-bound.js +++ b/modules/test/test-tool-context-bound.js @@ -85,6 +85,52 @@ function ok(name, cond, detail) { ok('D1 small tool results stay verbatim', messages[1].content === 'small result', messages[1].content); } +// E. MAINT-023b: the clip must preserve envelope keys. A read_file page is a JSON string; +// clipping it blind deletes `truncated` and `next_offset`, so the model cannot page. +{ + const ai = mk(); + const page = JSON.stringify({ + path: '/big.txt', offset: 0, returned: 16000, total_chars: 40000, + truncated: true, next_offset: 16000, + content: 'x'.repeat(16000), + }); + const clipped = ai._clipToolResult(page); + let parsed = null; + try { parsed = JSON.parse(clipped); } catch (e) {} + ok('E1 clip keeps JSON parseable', !!parsed, clipped.slice(-80)); + ok('E2 clip keeps next_offset', parsed && parsed.next_offset === 16000); + ok('E3 clip keeps truncated flag', parsed && parsed.truncated === true); + 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)); +} + +// F. budgets are resolvable per model class, with precedence call arg > profile > ai-config > default +{ + let PROF = null, profErr = ''; + try { PROF = require(path.join(__dirname, '..', 'core', 'model-profiles.js')); } catch (e) { profErr = e.message; } + ok('F0 model-profiles.js loads', !!PROF, profErr); + const ai = mk(); + ai.modelProfiles = PROF; + ai.terminal.ollamaManager = { currentModel: 'gemma4:31b-cloud' }; + ok('F1 cloud profile read page', ai._toolLimit('readPageChars') === 32000, String(ai._toolLimit('readPageChars'))); + ai.terminal.ollamaManager.currentModel = 'qwen3:0.6b'; + ok('F2 tiny profile read page', ai._toolLimit('readPageChars') === 4000, String(ai._toolLimit('readPageChars'))); + ai.terminal.ollamaManager.currentModel = 'llama3.1:8b'; + ok('F3 small profile result clip', ai._toolLimit('toolResultChars') === 4000, String(ai._toolLimit('toolResultChars'))); + ai.maxToolResultChars = 1234; + ok('F4 ai-config overrides the model default', ai._toolLimit('toolResultChars') === 1234, String(ai._toolLimit('toolResultChars'))); + // an id with no size token is unclassifiable -> mid; "unknown:1b" is NOT unknown, it is a 1B model + ok('F5 unclassifiable model falls back to mid', (function () { + ai.terminal.ollamaManager.currentModel = 'mystery-model'; + return ai._toolLimit('readPageChars') === 16000; + })()); + ok('F6 a 1b id is classified tiny, not mid', (function () { + ai.terminal.ollamaManager.currentModel = 'unknown:1b'; + return ai._toolLimit('readPageChars') === 4000; + })()); +} + if (fails === 0) { console.log('test-tool-context-bound: ' + passes + ' passed, 0 failed'); } else { |