Skip to content

Commit 4bacaf3

Browse files
committed
simplified page representation.
1 parent 46faa4d commit 4bacaf3

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

packages/agent/src/tools/browser/browseMessage.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { zodToJsonSchema } from 'zod-to-json-schema';
33

44
import { Tool } from '../../core/types.js';
55
import { errorToString } from '../../utils/errorToString.js';
6+
import { sleep } from '../../utils/sleep.js';
67

8+
import { getRenderedDOM } from './getRenderedDOM.js';
79
import { browserSessions, type BrowserAction, SelectorType } from './types.js';
810

911
// Schema for browser action
@@ -111,7 +113,8 @@ export const browseMessageTool: Tool<Parameters, ReturnType> = {
111113
`Navigating to ${action.url} with 'domcontentloaded' waitUntil`,
112114
);
113115
await page.goto(action.url, { waitUntil: 'domcontentloaded' });
114-
const content = await page.content();
116+
await sleep(3000);
117+
const content = await getRenderedDOM(page);
115118
logger.verbose(
116119
'Navigation completed with domcontentloaded strategy',
117120
);
@@ -128,7 +131,8 @@ export const browseMessageTool: Tool<Parameters, ReturnType> = {
128131

129132
try {
130133
await page.goto(action.url);
131-
const content = await page.content();
134+
await sleep(3000);
135+
const content = await getRenderedDOM(page);
132136
logger.verbose('Navigation completed with basic strategy');
133137
logger.verbose(`Content: ${content}`);
134138
return { status: 'success', content };

packages/agent/src/tools/browser/browseStart.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { zodToJsonSchema } from 'zod-to-json-schema';
55

66
import { Tool } from '../../core/types.js';
77
import { errorToString } from '../../utils/errorToString.js';
8+
import { sleep } from '../../utils/sleep.js';
89

10+
import { getRenderedDOM } from './getRenderedDOM.js';
911
import { browserSessions } from './types.js';
1012

1113
const parameterSchema = z.object({
@@ -99,7 +101,8 @@ export const browseStartTool: Tool<Parameters, ReturnType> = {
99101
`Navigating to ${url} with 'domcontentloaded' waitUntil`,
100102
);
101103
await page.goto(url, { waitUntil: 'domcontentloaded', timeout });
102-
content = await page.content();
104+
await sleep(3000);
105+
content = await getRenderedDOM(page);
103106
logger.verbose('Navigation completed with domcontentloaded strategy');
104107
} catch (error) {
105108
// If that fails, try with no waitUntil option at all (most basic)
@@ -112,7 +115,8 @@ export const browseStartTool: Tool<Parameters, ReturnType> = {
112115

113116
try {
114117
await page.goto(url, { timeout });
115-
content = await page.content();
118+
await sleep(3000);
119+
content = await getRenderedDOM(page);
116120
logger.verbose('Navigation completed with basic strategy');
117121
} catch (innerError) {
118122
logger.error(
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Page } from 'playwright';
2+
3+
export async function getRenderedDOM(page: Page): Promise<string> {
4+
// Get the serialized HTML after JavaScript execution
5+
const domContent = await page.evaluate(() => {
6+
// Clone the document to avoid modifying the original
7+
const clone = document.documentElement; //.cloneNode(true) as HTMLElement;
8+
9+
// for each element, get computed styles to determine visibility, and remove if not visible
10+
const elements = clone.querySelectorAll('*');
11+
12+
const elementsToRemove: Element[] = [];
13+
elements.forEach((element) => {
14+
const computedStyle = window.getComputedStyle(element);
15+
const isVisible =
16+
computedStyle.display !== 'none' &&
17+
computedStyle.visibility !== 'hidden' &&
18+
computedStyle.opacity !== '0';
19+
20+
if (!isVisible) {
21+
elementsToRemove.push(element);
22+
}
23+
});
24+
25+
// Optional: Remove other non-visual elements
26+
const nonVisualTags = clone.querySelectorAll(
27+
'noscript, iframe, link[rel="stylesheet"], meta, svg, img, symbol, path, style, script',
28+
);
29+
nonVisualTags.forEach((element) => elementsToRemove.push(element));
30+
31+
elementsToRemove.forEach((element) => element.remove());
32+
33+
console.log(
34+
'removing ',
35+
elementsToRemove.length,
36+
' elements out of a total ',
37+
elements.length,
38+
);
39+
40+
return clone.outerHTML;
41+
});
42+
43+
// remove all newlines using a regex, and also collapse multiple spaces into one
44+
return domContent.replace(/\n/g, '').replace(/\s+/g, ' ');
45+
}

0 commit comments

Comments
 (0)