agent-go / src /lib /browser.ts
arudradey's picture
Update src/lib/browser.ts
2e6fbe5 verified
import { Browser, BrowserContext, Page, chromium } from "playwright";
let browser: Browser | null = null;
let context: BrowserContext | null = null;
let page: Page | null = null;
function getLaunchArgs(): string[] {
return [
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-dev-shm-usage",
"--disable-gpu",
"--disable-software-rasterizer",
"--no-first-run",
"--no-default-browser-check",
"--disable-extensions",
"--disable-sync",
"--mute-audio",
"--window-size=1280,720",
];
}
function ensureNodeRuntimeEnv() {
process.env.HOME = process.env.HOME || "/home/node";
process.env.XDG_CACHE_HOME =
process.env.XDG_CACHE_HOME || "/home/node/.cache";
process.env.XDG_CONFIG_HOME =
process.env.XDG_CONFIG_HOME || "/home/node/.config";
process.env.XDG_RUNTIME_DIR =
process.env.XDG_RUNTIME_DIR || "/tmp/runtime-node";
process.env.DBUS_SESSION_BUS_ADDRESS =
process.env.DBUS_SESSION_BUS_ADDRESS || "disabled";
process.env.PLAYWRIGHT_BROWSERS_PATH =
process.env.PLAYWRIGHT_BROWSERS_PATH || "/home/node/.cache/ms-playwright";
}
export async function initBrowser(): Promise<void> {
await closeBrowser();
ensureNodeRuntimeEnv();
console.log(`[Browser] UID : ${process.getuid?.() ?? "unknown"}`);
console.log(`[Browser] HOME : ${process.env.HOME}`);
console.log(`[Browser] PW path : ${process.env.PLAYWRIGHT_BROWSERS_PATH}`);
browser = await chromium.launch({
headless: true,
args: getLaunchArgs(),
env: {
...process.env,
HOME: process.env.HOME,
XDG_CACHE_HOME: process.env.XDG_CACHE_HOME,
XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME,
XDG_RUNTIME_DIR: process.env.XDG_RUNTIME_DIR,
DBUS_SESSION_BUS_ADDRESS: process.env.DBUS_SESSION_BUS_ADDRESS,
PLAYWRIGHT_BROWSERS_PATH: process.env.PLAYWRIGHT_BROWSERS_PATH,
},
});
context = await browser.newContext({
viewport: { width: 1280, height: 720 },
locale: "en-US",
ignoreHTTPSErrors: true,
userAgent:
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
});
context.setDefaultTimeout(10_000);
context.setDefaultNavigationTimeout(15_000);
page = await context.newPage();
await page.route("**/*.{woff,woff2,ttf,otf,eot}", (route) => route.abort());
await page.route(
"**/{analytics,gtag,ga.js,fbq,hotjar,clarity,segment,mixpanel}*",
(route) => route.abort()
);
await page.setExtraHTTPHeaders({
"Accept-Language": "en-US,en;q=0.9",
});
await page.goto("about:blank", { timeout: 5_000 });
console.log("[Browser] Ready on about:blank");
}
export async function navigateTo(url: string): Promise<void> {
if (!page) {
throw new Error("No active browser page");
}
console.log(`[Browser] Navigating to ${url}`);
try {
const response = await page.goto(url, {
waitUntil: "commit",
timeout: 15_000,
});
console.log("[Browser] commit ok:", response?.status() ?? "no-response");
await page
.waitForLoadState("domcontentloaded", { timeout: 8_000 })
.catch(() => {});
await page.waitForTimeout(1200);
return;
} catch (err) {
console.warn("[Browser] commit failed, retrying with domcontentloaded", err);
}
try {
await page.goto(url, {
waitUntil: "domcontentloaded",
timeout: 15_000,
});
console.log("[Browser] Navigation OK (domcontentloaded)");
await page.waitForTimeout(1200);
return;
} catch (err) {
console.warn("[Browser] domcontentloaded failed, waiting for body", err);
}
try {
await page.waitForSelector("body", {
timeout: 8_000,
});
console.log("[Browser] Body detected");
await page.waitForTimeout(800);
return;
} catch {
throw new Error(`Navigation failed for ${url}`);
}
}
export function getPage(): Page | null {
return page;
}
export function isBrowserAlive(): boolean {
return !!browser && browser.isConnected() && !!context && !!page && !page.isClosed();
}
export async function closeBrowser(): Promise<void> {
try {
if (page && !page.isClosed()) {
await page.close().catch(() => {});
}
page = null;
if (context) {
await context.close().catch(() => {});
}
context = null;
if (browser && browser.isConnected()) {
await browser.close().catch(() => {});
}
browser = null;
} catch (e) {
console.warn("[Browser] Close warning:", e);
page = null;
context = null;
browser = null;
} finally {
console.log("[Browser] Session closed cleanly.");
}
}