import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import path from 'node:path'; import { extensionLaunch, installedExtensionDirs } from '../browser-use/extensions.js'; import { formatBrowserReading, pageSliceOffsets } from '../browser-use/reading.js'; import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const truncate = require('../vendor/agent-harness/agent/truncate.js'); const compaction = require('../vendor/agent-harness/agent/compaction.js'); test('a browser reading keeps the page text ahead of refs and survives voice compaction', () => { const article = 'The launch date is 14 September 2026. The price is 42 dollars. '.repeat(40); const reading = formatBrowserReading({ url: 'https://example.com/story', title: 'Story', text: article, headings: ['Launch'], tables: ['Item | Price\nWidget | 42'], seen: ['A chart of the price'], refs: [{ ref: '1', role: 'a', name: 'Accept cookies' }], }); const textAt = reading.indexOf('page_text:'); assert.ok(textAt >= 0); assert.ok(textAt < reading.indexOf('refs:')); assert.match(reading, /14 September 2026/); assert.match(reading, /A chart of the price/); const rendered = truncate.renderToolResult({ reading, images: [{ path: '/tmp/page.jpg' }] }, 8000); assert.match(rendered, /page_text:/); assert.doesNotMatch(rendered, /\/tmp\/page\.jpg/); const history = [ { role: 'system', content: 'You are Jarvis.' }, { role: 'user', content: 'What is the launch date and price?' }, { role: 'assistant', content: '', tool_calls: [{ id: 'call_1', name: 'browser', arguments: { action: 'snapshot' } }] }, { role: 'tool', name: 'browser', tool_call_id: 'call_1', content: reading }, ]; const compacted = compaction.heuristicCompact(history, { budgetTokens: 400, voice: true, aggressive: true, browserFloor: 4000, }); const page = compacted.find((msg) => msg.role === 'tool' && msg.name === 'browser'); assert.ok(page, 'browser page was discarded'); assert.match(page.content, /14 September 2026/); assert.ok(page.content.length > 500, 'page text was crushed: ' + page.content.length); }); test('page slices cover a tall page from top to bottom', () => { assert.deepEqual(pageSliceOffsets(700, 800, 4), [0]); const slices = pageSliceOffsets(8000, 800, 4); assert.equal(slices[0], 0); assert.equal(slices[slices.length - 1], 7200); assert.ok(slices.length >= 2 && slices.length <= 4); const reading = formatBrowserReading({ url: 'https://example.com/long', title: 'Long', coverage: 'full page, 10 screens', text: 'Section near the bottom: the code is 4412.', }); assert.match(reading, /coverage: full page, 10 screens/); assert.match(reading, /full readable page after scrolling/); assert.match(reading, /4412/); }); test('browser loads only unpacked extensions that have a manifest', () => { const root = mkdtempSync(path.join(tmpdir(), 'jarvis-ext-')); try { mkdirSync(path.join(root, 'ublock-origin-lite')); writeFileSync(path.join(root, 'ublock-origin-lite', 'manifest.json'), '{"name":"uBOL","version":"1"}'); mkdirSync(path.join(root, 'dark-reader')); const missing = extensionLaunch(installedExtensionDirs(root)); assert.deepEqual(missing.extensions, ['ublock-origin-lite']); assert.match(missing.args[1], /--load-extension=/); assert.deepEqual(missing.ignoreDefaultArgs, ['--disable-extensions']); writeFileSync(path.join(root, 'dark-reader', 'manifest.json'), '{"name":"Dark Reader","version":"1"}'); const both = extensionLaunch(installedExtensionDirs(root)); assert.deepEqual(both.extensions, ['ublock-origin-lite', 'dark-reader']); assert.match(both.args[0], /disable-extensions-except=/); assert.match(both.args[1], /ublock-origin-lite,.*dark-reader/); assert.deepEqual(extensionLaunch([]).args, []); } finally { rmSync(root, { recursive: true, force: true }); } });