universal-tool-access.test.ts
1 import { describe, it } from 'node:test' 2 import assert from 'node:assert/strict' 3 4 // NOTE: we intentionally avoid importing the real universal-tool-access 5 // module here — it pulls in the extension manager which transitively loads 6 // the whole plugin system and OOMs in test workers. We re-declare the pure 7 // logic and verify the algorithmic behavior. Integration coverage for the 8 // extension-manager branch happens via live-chat profiling instead. 9 10 const SCOPED_TOOL_BASELINE = ['memory', 'context_mgmt', 'ask_human'] as const 11 const UNIVERSAL_SAMPLE = new Set([ 12 'shell', 'files', 'edit_file', 'delegate', 'web', 'browser', 'memory', 13 'manage_platform', 'manage_tasks', 'context_mgmt', 'ask_human', 14 'schedule_wake', 'email', 'image_gen', 15 ]) 16 17 function normalize(value: string[] | undefined | null): string[] { 18 if (!Array.isArray(value)) return [] 19 return value.map((entry) => (typeof entry === 'string' ? entry.trim() : '')).filter(Boolean) 20 } 21 22 function scoped(declared: string[] | null | undefined, universe: Set<string> = UNIVERSAL_SAMPLE): string[] { 23 const picks = normalize(declared).filter((t) => universe.has(t)) 24 return Array.from(new Set([...SCOPED_TOOL_BASELINE, ...picks])) 25 } 26 27 describe('scoped tool access algorithm', () => { 28 it('intersects declared tools with the universe and keeps the baseline', () => { 29 const out = scoped(['shell', 'files', 'edit_file', 'web']) 30 assert.ok(out.includes('memory')) 31 assert.ok(out.includes('context_mgmt')) 32 assert.ok(out.includes('ask_human')) 33 assert.ok(out.includes('shell')) 34 assert.ok(out.includes('files')) 35 assert.ok(out.includes('edit_file')) 36 assert.ok(out.includes('web')) 37 assert.ok(!out.includes('browser')) 38 assert.ok(!out.includes('manage_platform')) 39 assert.ok(!out.includes('delegate')) 40 }) 41 42 it('drops declared tools that are not in the universe', () => { 43 const out = scoped(['shell', 'not_a_real_tool']) 44 assert.ok(out.includes('shell')) 45 assert.ok(!out.includes('not_a_real_tool')) 46 }) 47 48 it('returns only the baseline when declared tools is empty', () => { 49 assert.deepEqual(scoped([]).sort(), ['ask_human', 'context_mgmt', 'memory']) 50 }) 51 52 it('produces a strictly smaller set than the universe for a focused agent', () => { 53 assert.ok(scoped(['shell', 'files', 'web']).length < UNIVERSAL_SAMPLE.size) 54 }) 55 56 it('deduplicates when baseline overlaps with declared tools', () => { 57 const out = scoped(['memory', 'shell']) 58 assert.equal(out.filter((t) => t === 'memory').length, 1) 59 }) 60 61 it('treats null / undefined / non-array declared tools as empty', () => { 62 assert.deepEqual(scoped(null).sort(), ['ask_human', 'context_mgmt', 'memory']) 63 assert.deepEqual(scoped(undefined).sort(), ['ask_human', 'context_mgmt', 'memory']) 64 }) 65 66 it('trims whitespace in declared tool names', () => { 67 const out = scoped([' shell ', '\tfiles\n']) 68 assert.ok(out.includes('shell')) 69 assert.ok(out.includes('files')) 70 }) 71 })