Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions browse/src/browser-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* restores state. Falls back to clean slate on any failure.
*/

import { chromium, type Browser, type BrowserContext, type Page, type Locator } from 'playwright';
import { chromium, type Browser, type BrowserContext, type BrowserContextOptions, type Page, type Locator } from 'playwright';
import { addConsoleEntry, addNetworkEntry, addDialogEntry, networkBuffer, type DialogEntry } from './buffers';

export interface RefEntry {
Expand Down Expand Up @@ -57,7 +57,7 @@ export class BrowserManager {
process.exit(1);
});

const contextOptions: any = {
const contextOptions: BrowserContextOptions = {
viewport: { width: 1280, height: 720 },
};
if (this.customUserAgent) {
Expand Down Expand Up @@ -282,7 +282,7 @@ export class BrowserManager {
try {
// 1. Save state from current context
const savedCookies = await this.context.cookies();
const savedPages: Array<{ url: string; isActive: boolean; storage: any }> = [];
const savedPages: Array<{ url: string; isActive: boolean; storage: { localStorage: Record<string, string>; sessionStorage: Record<string, string> } | null }> = [];

for (const [id, page] of this.pages) {
const url = page.url();
Expand All @@ -308,7 +308,7 @@ export class BrowserManager {
await this.context.close().catch(() => {});

// 3. Create new context with updated settings
const contextOptions: any = {
const contextOptions: BrowserContextOptions = {
viewport: { width: 1280, height: 720 },
};
if (this.customUserAgent) {
Expand Down Expand Up @@ -340,15 +340,15 @@ export class BrowserManager {
// 6. Restore storage
if (saved.storage) {
try {
await page.evaluate((s: any) => {
await page.evaluate((s: { localStorage: Record<string, string>; sessionStorage: Record<string, string> }) => {
if (s.localStorage) {
for (const [k, v] of Object.entries(s.localStorage)) {
localStorage.setItem(k, v as string);
localStorage.setItem(k, v);
}
}
if (s.sessionStorage) {
for (const [k, v] of Object.entries(s.sessionStorage)) {
sessionStorage.setItem(k, v as string);
sessionStorage.setItem(k, v);
}
}
}, saved.storage);
Expand All @@ -369,13 +369,13 @@ export class BrowserManager {
this.clearRefs();

return null; // success
} catch (err: any) {
} catch (err: unknown) {
// Fallback: create a clean context + blank tab
try {
this.pages.clear();
if (this.context) await this.context.close().catch(() => {});

const contextOptions: any = {
const contextOptions: BrowserContextOptions = {
viewport: { width: 1280, height: 720 },
};
if (this.customUserAgent) {
Expand All @@ -387,7 +387,7 @@ export class BrowserManager {
} catch {
// If even the fallback fails, we're in trouble — but browser is still alive
}
return `Context recreation failed: ${err.message}. Browser reset to blank tab.`;
return `Context recreation failed: ${err instanceof Error ? err.message : String(err)}. Browser reset to blank tab.`;
}
}

Expand Down
29 changes: 4 additions & 25 deletions browse/src/meta-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import type { BrowserManager } from './browser-manager';
import { handleSnapshot } from './snapshot';
import { getCleanText } from './read-commands';
import { READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS } from './commands';
import * as Diff from 'diff';
import * as fs from 'fs';
import * as path from 'path';
Expand All @@ -20,28 +21,6 @@ function validateOutputPath(filePath: string): void {
}
}

// Command sets for chain routing (mirrors server.ts — kept local to avoid circular import)
const CHAIN_READ = new Set([
'text', 'html', 'links', 'forms', 'accessibility',
'js', 'eval', 'css', 'attrs',
'console', 'network', 'cookies', 'storage', 'perf',
'dialog', 'is',
]);
const CHAIN_WRITE = new Set([
'goto', 'back', 'forward', 'reload',
'click', 'fill', 'select', 'hover', 'type', 'press', 'scroll', 'wait',
'viewport', 'cookie', 'cookie-import', 'header', 'useragent',
'upload', 'dialog-accept', 'dialog-dismiss',
'cookie-import-browser',
]);
const CHAIN_META = new Set([
'tabs', 'tab', 'newtab', 'closetab',
'status', 'stop', 'restart',
'screenshot', 'pdf', 'responsive',
'chain', 'diff',
'url', 'snapshot',
]);

export async function handleMetaCommand(
command: string,
args: string[],
Expand Down Expand Up @@ -223,9 +202,9 @@ export async function handleMetaCommand(
const [name, ...cmdArgs] = cmd;
try {
let result: string;
if (CHAIN_WRITE.has(name)) result = await handleWriteCommand(name, cmdArgs, bm);
else if (CHAIN_READ.has(name)) result = await handleReadCommand(name, cmdArgs, bm);
else if (CHAIN_META.has(name)) result = await handleMetaCommand(name, cmdArgs, bm, shutdown);
if (WRITE_COMMANDS.has(name)) result = await handleWriteCommand(name, cmdArgs, bm);
else if (READ_COMMANDS.has(name)) result = await handleReadCommand(name, cmdArgs, bm);
else if (META_COMMANDS.has(name)) result = await handleMetaCommand(name, cmdArgs, bm, shutdown);
else throw new Error(`Unknown command: ${name}`);
results.push(`[${name}] ${result}`);
} catch (err: any) {
Expand Down
6 changes: 3 additions & 3 deletions browse/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async function flushBuffers() {
const lines = entries.map(e =>
`[${new Date(e.timestamp).toISOString()}] [${e.level}] ${e.text}`
).join('\n') + '\n';
await Bun.write(CONSOLE_LOG_PATH, (await Bun.file(CONSOLE_LOG_PATH).text().catch(() => '')) + lines);
fs.appendFileSync(CONSOLE_LOG_PATH, lines);
lastConsoleFlushed = consoleBuffer.totalAdded;
}

Expand All @@ -115,7 +115,7 @@ async function flushBuffers() {
const lines = entries.map(e =>
`[${new Date(e.timestamp).toISOString()}] ${e.method} ${e.url} → ${e.status || 'pending'} (${e.duration || '?'}ms, ${e.size || '?'}B)`
).join('\n') + '\n';
await Bun.write(NETWORK_LOG_PATH, (await Bun.file(NETWORK_LOG_PATH).text().catch(() => '')) + lines);
fs.appendFileSync(NETWORK_LOG_PATH, lines);
lastNetworkFlushed = networkBuffer.totalAdded;
}

Expand All @@ -126,7 +126,7 @@ async function flushBuffers() {
const lines = entries.map(e =>
`[${new Date(e.timestamp).toISOString()}] [${e.type}] "${e.message}" → ${e.action}${e.response ? ` "${e.response}"` : ''}`
).join('\n') + '\n';
await Bun.write(DIALOG_LOG_PATH, (await Bun.file(DIALOG_LOG_PATH).text().catch(() => '')) + lines);
fs.appendFileSync(DIALOG_LOG_PATH, lines);
lastDialogFlushed = dialogBuffer.totalAdded;
}
} catch {
Expand Down