💬 Commit message: Update 2026-02-06 21:32:05, 5 files, 447 lines
📁 Files changed: 5 📝 Lines changed: 447 • settings.local.json • cli.ts • logger.ts • mcp.ts • server.ts
This commit is contained in:
+6
-107
@@ -2,114 +2,13 @@ import chalk from 'chalk';
|
||||
import express, { type Request, type Response } from 'express';
|
||||
import logSymbols from 'log-symbols';
|
||||
import { ClaudeBrowser } from './browser.js';
|
||||
import type { BrowserCommand, BrowserOptions, CommandResponse } from './types.js';
|
||||
import { logger, ts } from './logger.js';
|
||||
import type { BrowserCommand, BrowserOptions } from './types.js';
|
||||
|
||||
export interface ServerOptions extends BrowserOptions {
|
||||
port?: number;
|
||||
}
|
||||
|
||||
// Icons for commands
|
||||
const icons = {
|
||||
goto: '→',
|
||||
click: '◉',
|
||||
type: '⌨',
|
||||
query: '?',
|
||||
screenshot: '📷',
|
||||
url: '🔗',
|
||||
html: '<>',
|
||||
back: '←',
|
||||
forward: '→',
|
||||
reload: '↻',
|
||||
wait: '⏳',
|
||||
newpage: '+',
|
||||
close: '✕',
|
||||
eval: '⚡',
|
||||
};
|
||||
|
||||
// Colors for command types
|
||||
const cmdColor: Record<string, (s: string) => string> = {
|
||||
goto: chalk.cyan,
|
||||
click: chalk.yellow,
|
||||
type: chalk.magenta,
|
||||
query: chalk.blue,
|
||||
screenshot: chalk.green,
|
||||
url: chalk.cyan,
|
||||
html: chalk.blue,
|
||||
back: chalk.yellow,
|
||||
forward: chalk.yellow,
|
||||
reload: chalk.yellow,
|
||||
wait: chalk.gray,
|
||||
newpage: chalk.green,
|
||||
close: chalk.red,
|
||||
eval: chalk.magenta,
|
||||
};
|
||||
|
||||
function ts(): string {
|
||||
return chalk.gray(`[${new Date().toISOString()}]`);
|
||||
}
|
||||
|
||||
function truncate(str: string, max: number): string {
|
||||
return str.length > max ? `${str.slice(0, max)}...` : str;
|
||||
}
|
||||
|
||||
function getCommandDetail(cmd: BrowserCommand): string | undefined {
|
||||
switch (cmd.cmd) {
|
||||
case 'goto':
|
||||
return chalk.white(cmd.url);
|
||||
case 'click':
|
||||
case 'query':
|
||||
return chalk.white(cmd.selector);
|
||||
case 'type':
|
||||
return `${chalk.white(cmd.selector)} ${chalk.dim(`="${cmd.text}"`)}`;
|
||||
case 'screenshot':
|
||||
return chalk.dim(cmd.path || 'screenshot.png');
|
||||
case 'html':
|
||||
return cmd.full ? chalk.dim('(full)') : undefined;
|
||||
case 'wait':
|
||||
return chalk.dim(`${cmd.ms || 1000}ms`);
|
||||
case 'eval':
|
||||
return chalk.dim(truncate(cmd.script, 50));
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function logCommand(cmd: BrowserCommand): void {
|
||||
const color = cmdColor[cmd.cmd] || chalk.white;
|
||||
const icon = icons[cmd.cmd as keyof typeof icons] || '•';
|
||||
const detail = getCommandDetail(cmd);
|
||||
const suffix = detail ? ` ${detail}` : '';
|
||||
console.log(`${ts()} ${chalk.bold(color(icon))} ${color(cmd.cmd.toUpperCase())}${suffix}`);
|
||||
}
|
||||
|
||||
type ResultFormatter = (result: CommandResponse) => string | undefined;
|
||||
|
||||
const resultFormatters: Record<string, ResultFormatter> = {
|
||||
goto: (r) => ('title' in r ? r.title : undefined),
|
||||
click: (r) => ('url' in r ? `→ ${r.url}` : undefined),
|
||||
query: (r) => ('count' in r ? `Found ${r.count} element(s)` : undefined),
|
||||
screenshot: (r) => ('path' in r ? `Saved to ${r.path}` : undefined),
|
||||
url: (r) => ('url' in r ? r.url : undefined),
|
||||
html: (r) => ('html' in r ? `${r.html?.length || 0} chars` : undefined),
|
||||
eval: (r) => ('result' in r ? truncate(JSON.stringify(r.result), 80) : undefined),
|
||||
};
|
||||
|
||||
function getResultMessage(cmd: BrowserCommand, result: CommandResponse): string | undefined {
|
||||
if (!result.ok) return undefined;
|
||||
const formatter = resultFormatters[cmd.cmd];
|
||||
return formatter ? formatter(result) : undefined;
|
||||
}
|
||||
|
||||
function logResult(cmd: BrowserCommand, result: CommandResponse): void {
|
||||
if (!result.ok) {
|
||||
console.log(`${ts()} ${logSymbols.error} ${chalk.red(result.error)}`);
|
||||
return;
|
||||
}
|
||||
const msg = getResultMessage(cmd, result);
|
||||
const suffix = msg ? ` ${chalk.dim(msg)}` : '';
|
||||
console.log(`${ts()} ${logSymbols.success}${suffix}`);
|
||||
}
|
||||
|
||||
function printBanner(port: number): void {
|
||||
console.log();
|
||||
console.log(chalk.cyan.bold(' 🌐 Claude Browse Server'));
|
||||
@@ -139,7 +38,7 @@ export class BrowserServer {
|
||||
|
||||
constructor(options: ServerOptions = {}) {
|
||||
this.browser = new ClaudeBrowser(options);
|
||||
this.port = options.port ?? 3000;
|
||||
this.port = options.port ?? 13373;
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
}
|
||||
@@ -156,17 +55,17 @@ export class BrowserServer {
|
||||
private async handleCommand(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const cmd: BrowserCommand = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
|
||||
logCommand(cmd);
|
||||
logger.command(cmd);
|
||||
|
||||
if (cmd.cmd === 'close') {
|
||||
logResult(cmd, { ok: true });
|
||||
logger.result(cmd, { ok: true });
|
||||
res.json({ ok: true });
|
||||
await this.stop();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const result = await this.browser.executeCommand(cmd);
|
||||
logResult(cmd, result);
|
||||
logger.result(cmd, result);
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
const error = (err as Error).message;
|
||||
|
||||
Reference in New Issue
Block a user