From bc1f3d9d735f510e42fbaf4820a6f465ea5d3a12 Mon Sep 17 00:00:00 2001 From: Adam Ladachowski Date: Sun, 8 Feb 2026 03:08:02 +0100 Subject: [PATCH] Add Claude Code plugin support with MCP prompts and resources - Add .claude-plugin/plugin.json manifest (name: browse) - Add 11 slash commands: start, end, goto, screenshot, scrape, analyze, extract, fill, compare, save, restore - Add MCP resources: browser://state, browser://html, browser://screenshot - Add MCP prompts: analyze_page, extract_data, navigate_to, fill_form, compare_screenshots - Add session management tools: close, session_save, session_restore - Include dist/ for plugin installation Co-Authored-By: Claude Opus 4.5 --- .gitignore | 1 - README.md | 10 +- dist/browser.d.ts | 48 +++ dist/browser.d.ts.map | 1 + dist/browser.integration.test.d.ts | 2 + dist/browser.integration.test.d.ts.map | 1 + dist/browser.integration.test.js | 173 ++++++++ dist/browser.integration.test.js.map | 1 + dist/browser.js | 250 ++++++++++++ dist/browser.js.map | 1 + dist/browser.test.d.ts | 2 + dist/browser.test.d.ts.map | 1 + dist/browser.test.js | 73 ++++ dist/browser.test.js.map | 1 + dist/cli.d.ts | 3 + dist/cli.d.ts.map | 1 + dist/cli.js | 243 +++++++++++ dist/cli.js.map | 1 + dist/image.d.ts | 21 + dist/image.d.ts.map | 1 + dist/image.js | 131 ++++++ dist/image.js.map | 1 + dist/index.d.ts | 6 + dist/index.d.ts.map | 1 + dist/index.js | 4 + dist/index.js.map | 1 + dist/logger.d.ts | 41 ++ dist/logger.d.ts.map | 1 + dist/logger.js | 103 +++++ dist/logger.js.map | 1 + dist/logger.test.d.ts | 2 + dist/logger.test.d.ts.map | 1 + dist/logger.test.js | 146 +++++++ dist/logger.test.js.map | 1 + dist/mcp.d.ts | 3 + dist/mcp.d.ts.map | 1 + dist/mcp.js | 536 +++++++++++++++++++++++++ dist/mcp.js.map | 1 + dist/server.d.ts | 20 + dist/server.d.ts.map | 1 + dist/server.js | 88 ++++ dist/server.js.map | 1 + dist/server.test.d.ts | 2 + dist/server.test.d.ts.map | 1 + dist/server.test.js | 164 ++++++++ dist/server.test.js.map | 1 + dist/types.d.ts | 125 ++++++ dist/types.d.ts.map | 1 + dist/types.js | 2 + dist/types.js.map | 1 + 50 files changed, 2218 insertions(+), 5 deletions(-) create mode 100644 dist/browser.d.ts create mode 100644 dist/browser.d.ts.map create mode 100644 dist/browser.integration.test.d.ts create mode 100644 dist/browser.integration.test.d.ts.map create mode 100644 dist/browser.integration.test.js create mode 100644 dist/browser.integration.test.js.map create mode 100644 dist/browser.js create mode 100644 dist/browser.js.map create mode 100644 dist/browser.test.d.ts create mode 100644 dist/browser.test.d.ts.map create mode 100644 dist/browser.test.js create mode 100644 dist/browser.test.js.map create mode 100644 dist/cli.d.ts create mode 100644 dist/cli.d.ts.map create mode 100755 dist/cli.js create mode 100644 dist/cli.js.map create mode 100644 dist/image.d.ts create mode 100644 dist/image.d.ts.map create mode 100644 dist/image.js create mode 100644 dist/image.js.map create mode 100644 dist/index.d.ts create mode 100644 dist/index.d.ts.map create mode 100644 dist/index.js create mode 100644 dist/index.js.map create mode 100644 dist/logger.d.ts create mode 100644 dist/logger.d.ts.map create mode 100644 dist/logger.js create mode 100644 dist/logger.js.map create mode 100644 dist/logger.test.d.ts create mode 100644 dist/logger.test.d.ts.map create mode 100644 dist/logger.test.js create mode 100644 dist/logger.test.js.map create mode 100644 dist/mcp.d.ts create mode 100644 dist/mcp.d.ts.map create mode 100755 dist/mcp.js create mode 100644 dist/mcp.js.map create mode 100644 dist/server.d.ts create mode 100644 dist/server.d.ts.map create mode 100644 dist/server.js create mode 100644 dist/server.js.map create mode 100644 dist/server.test.d.ts create mode 100644 dist/server.test.d.ts.map create mode 100644 dist/server.test.js create mode 100644 dist/server.test.js.map create mode 100644 dist/types.d.ts create mode 100644 dist/types.d.ts.map create mode 100644 dist/types.js create mode 100644 dist/types.js.map diff --git a/.gitignore b/.gitignore index d435a7f..29614e8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /node_modules/ /public/ -/dist/ /screenshots/ coverage/ screenshots/ diff --git a/README.md b/README.md index cec43cb..bbe3f1d 100644 --- a/README.md +++ b/README.md @@ -90,13 +90,15 @@ curl -X POST localhost:3000 -d '{"cmd":"close"}' Install as a Claude Code plugin for the best integration: ```bash -# Install the plugin -claude plugin install https://github.com/aladac/claude-browse +# Install from GitHub +claude plugin install github:aladac/claude-browse -# Or load temporarily during development -claude --plugin-dir /path/to/claude-browse +# Or install from local path +claude plugin install /path/to/claude-browse ``` +**Prerequisites:** Node.js 18+ (the MCP server runs via npx) + ### Plugin Features **Slash Commands:** diff --git a/dist/browser.d.ts b/dist/browser.d.ts new file mode 100644 index 0000000..60cc3be --- /dev/null +++ b/dist/browser.d.ts @@ -0,0 +1,48 @@ +import { type BrowserContext, type Page } from 'playwright'; +import type { BrowserCommand, BrowserOptions, CommandResponse, ElementInfo } from './types.js'; +export declare class ClaudeBrowser { + private browser; + private context; + private page; + private options; + constructor(options?: BrowserOptions); + launch(): Promise; + close(): Promise; + private ensurePage; + /** Get the current page instance (for advanced usage) */ + getPage(): Page | null; + /** Get the browser context (for advanced usage like cookies) */ + getContext(): BrowserContext | null; + goto(url: string): Promise<{ + url: string; + title: string; + }>; + click(selector: string): Promise<{ + url: string; + }>; + type(selector: string, text: string): Promise; + query(selector: string): Promise; + screenshot(path?: string, fullPage?: boolean): Promise<{ + path: string; + buffer?: Buffer; + }>; + getUrl(): Promise<{ + url: string; + title: string; + }>; + getHtml(full?: boolean): Promise; + back(): Promise<{ + url: string; + }>; + forward(): Promise<{ + url: string; + }>; + reload(): Promise<{ + url: string; + }>; + wait(ms?: number): Promise; + newPage(): Promise; + eval(script: string): Promise; + executeCommand(cmd: BrowserCommand): Promise; +} +//# sourceMappingURL=browser.d.ts.map \ No newline at end of file diff --git a/dist/browser.d.ts.map b/dist/browser.d.ts.map new file mode 100644 index 0000000..426cf1b --- /dev/null +++ b/dist/browser.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,cAAc,EAAE,KAAK,IAAI,EAAU,MAAM,YAAY,CAAC;AAElF,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/F,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,OAAO,CAA2B;gBAE9B,OAAO,GAAE,cAAmB;IAQlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAWvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,OAAO,CAAC,UAAU;IAOlB,yDAAyD;IACzD,OAAO,IAAI,IAAI,GAAG,IAAI;IAItB,gEAAgE;IAChE,UAAU,IAAI,cAAc,GAAG,IAAI;IAI7B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAM1D,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAOjD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAiB/C,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAOvF,MAAM,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAKjD,OAAO,CAAC,IAAI,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAMtC,IAAI,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAMhC,OAAO,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAMnC,MAAM,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAMlC,IAAI,CAAC,EAAE,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxB,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKtC,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;CAsIpE"} \ No newline at end of file diff --git a/dist/browser.integration.test.d.ts b/dist/browser.integration.test.d.ts new file mode 100644 index 0000000..5d69abe --- /dev/null +++ b/dist/browser.integration.test.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=browser.integration.test.d.ts.map \ No newline at end of file diff --git a/dist/browser.integration.test.d.ts.map b/dist/browser.integration.test.d.ts.map new file mode 100644 index 0000000..1af846b --- /dev/null +++ b/dist/browser.integration.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.integration.test.d.ts","sourceRoot":"","sources":["../src/browser.integration.test.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/browser.integration.test.js b/dist/browser.integration.test.js new file mode 100644 index 0000000..944a526 --- /dev/null +++ b/dist/browser.integration.test.js @@ -0,0 +1,173 @@ +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { ClaudeBrowser } from './browser.js'; +describe('ClaudeBrowser Integration', () => { + let browser; + beforeAll(async () => { + browser = new ClaudeBrowser({ headless: true }); + await browser.launch(); + }, 30000); + afterAll(async () => { + await browser.close(); + }); + describe('navigation', () => { + it('navigates to a URL and returns title', async () => { + const result = await browser.goto('https://example.com'); + expect(result.url).toContain('example.com'); + expect(result.title).toBe('Example Domain'); + }); + it('gets current URL and title', async () => { + const result = await browser.getUrl(); + expect(result.url).toContain('example.com'); + expect(result.title).toBe('Example Domain'); + }); + it('gets page HTML', async () => { + const html = await browser.getHtml(); + expect(html.toLowerCase()).toContain(''); + expect(html).toContain('Example Domain'); + }); + it('gets full page HTML', async () => { + const html = await browser.getHtml(true); + expect(html.toLowerCase()).toContain(''); + expect(html.length).toBeGreaterThan(100); + }); + it('reloads the page', async () => { + const result = await browser.reload(); + expect(result.url).toContain('example.com'); + }); + }); + describe('DOM interaction', () => { + it('queries elements', async () => { + const elements = await browser.query('h1'); + expect(elements.length).toBe(1); + expect(elements[0].tag).toBe('h1'); + expect(elements[0].text).toContain('Example Domain'); + }); + it('queries multiple elements', async () => { + const elements = await browser.query('p'); + expect(elements.length).toBeGreaterThan(0); + expect(elements[0].tag).toBe('p'); + }); + it('clicks an element', async () => { + await browser.goto('https://example.com'); + const result = await browser.click('a'); + expect(result.url).toBeDefined(); + }); + }); + describe('screenshots', () => { + it('takes a screenshot', async () => { + await browser.goto('https://example.com'); + const result = await browser.screenshot('screenshots/test-integration.png'); + expect(result.path).toContain('test-integration.png'); + expect(result.buffer).toBeDefined(); + }); + it('takes a full page screenshot', async () => { + const result = await browser.screenshot('screenshots/test-full.png', true); + expect(result.path).toContain('test-full.png'); + }); + }); + describe('wait', () => { + it('waits for specified time', async () => { + const start = Date.now(); + await browser.wait(100); + const elapsed = Date.now() - start; + expect(elapsed).toBeGreaterThanOrEqual(90); + }); + }); + describe('eval', () => { + it('evaluates JavaScript', async () => { + await browser.goto('https://example.com'); + const result = await browser.eval('document.title'); + expect(result).toBe('Example Domain'); + }); + it('evaluates expressions', async () => { + const result = await browser.eval('1 + 1'); + expect(result).toBe(2); + }); + it('evaluates complex expressions', async () => { + const result = await browser.eval('document.querySelectorAll("p").length'); + expect(result).toBeGreaterThan(0); + }); + }); + describe('pages', () => { + it('creates a new page', async () => { + await browser.newPage(); + const result = await browser.getUrl(); + expect(result.url).toBe('about:blank'); + }); + it('navigates in new page', async () => { + const result = await browser.goto('https://example.com'); + expect(result.title).toBe('Example Domain'); + }); + }); + describe('executeCommand', () => { + it('handles goto command', async () => { + const result = await browser.executeCommand({ cmd: 'goto', url: 'https://example.com' }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.title).toBe('Example Domain'); + } + }); + it('handles query command', async () => { + const result = await browser.executeCommand({ cmd: 'query', selector: 'h1' }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.count).toBe(1); + } + }); + it('handles url command', async () => { + const result = await browser.executeCommand({ cmd: 'url' }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.url).toContain('example.com'); + } + }); + it('handles html command', async () => { + const result = await browser.executeCommand({ cmd: 'html' }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.html).toContain('Example'); + } + }); + it('handles wait command', async () => { + const result = await browser.executeCommand({ cmd: 'wait', ms: 50 }); + expect(result.ok).toBe(true); + }); + it('handles eval command', async () => { + const result = await browser.executeCommand({ cmd: 'eval', script: '2+2' }); + expect(result.ok).toBe(true); + if (result.ok) { + expect(result.result).toBe(4); + } + }); + it('handles screenshot command', async () => { + const result = await browser.executeCommand({ + cmd: 'screenshot', + path: 'screenshots/cmd-test.png', + }); + expect(result.ok).toBe(true); + }); + it('handles reload command', async () => { + const result = await browser.executeCommand({ cmd: 'reload' }); + expect(result.ok).toBe(true); + }); + it('handles click command', async () => { + await browser.executeCommand({ cmd: 'goto', url: 'https://example.com' }); + const result = await browser.executeCommand({ cmd: 'click', selector: 'a' }); + expect(result.ok).toBe(true); + }); + it('handles newpage command', async () => { + const result = await browser.executeCommand({ cmd: 'newpage' }); + expect(result.ok).toBe(true); + }); + it('handles back command', async () => { + await browser.executeCommand({ cmd: 'goto', url: 'https://example.com' }); + const result = await browser.executeCommand({ cmd: 'back' }); + expect(result.ok).toBe(true); + }); + it('handles forward command', async () => { + const result = await browser.executeCommand({ cmd: 'forward' }); + expect(result.ok).toBe(true); + }); + }); +}); +//# sourceMappingURL=browser.integration.test.js.map \ No newline at end of file diff --git a/dist/browser.integration.test.js.map b/dist/browser.integration.test.js.map new file mode 100644 index 0000000..74581fa --- /dev/null +++ b/dist/browser.integration.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.integration.test.js","sourceRoot":"","sources":["../src/browser.integration.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/browser.js b/dist/browser.js new file mode 100644 index 0000000..7e30a8d --- /dev/null +++ b/dist/browser.js @@ -0,0 +1,250 @@ +import { resolve } from 'node:path'; +import { webkit } from 'playwright'; +import * as image from './image.js'; +export class ClaudeBrowser { + browser = null; + context = null; + page = null; + options; + constructor(options = {}) { + this.options = { + headless: options.headless ?? true, + width: options.width ?? 1280, + height: options.height ?? 800, + }; + } + async launch() { + this.browser = await webkit.launch({ headless: this.options.headless }); + this.context = await this.browser.newContext({ + viewport: { + width: this.options.width, + height: this.options.height, + }, + }); + this.page = await this.context.newPage(); + } + async close() { + if (this.browser) { + await this.browser.close(); + this.browser = null; + this.context = null; + this.page = null; + } + } + ensurePage() { + if (!this.page) { + throw new Error('Browser not launched. Call launch() first.'); + } + return this.page; + } + /** Get the current page instance (for advanced usage) */ + getPage() { + return this.page; + } + /** Get the browser context (for advanced usage like cookies) */ + getContext() { + return this.context; + } + async goto(url) { + const page = this.ensurePage(); + await page.goto(url, { waitUntil: 'networkidle' }); + return { url: page.url(), title: await page.title() }; + } + async click(selector) { + const page = this.ensurePage(); + await page.click(selector); + await page.waitForLoadState('networkidle').catch(() => { }); + return { url: page.url() }; + } + async type(selector, text) { + const page = this.ensurePage(); + await page.fill(selector, text); + } + async query(selector) { + const page = this.ensurePage(); + return page.$$eval(selector, (nodes) => nodes.map((el) => { + const attrs = {}; + for (const attr of el.attributes) { + attrs[attr.name] = attr.value; + } + return { + tag: el.tagName.toLowerCase(), + text: el.textContent?.trim().slice(0, 200) || '', + attributes: attrs, + }; + })); + } + async screenshot(path, fullPage = false) { + const page = this.ensurePage(); + const resolvedPath = resolve(path || 'screenshot.png'); + const buffer = await page.screenshot({ path: resolvedPath, fullPage }); + return { path: resolvedPath, buffer }; + } + async getUrl() { + const page = this.ensurePage(); + return { url: page.url(), title: await page.title() }; + } + async getHtml(full = false) { + const page = this.ensurePage(); + const html = await page.content(); + return full ? html : html.slice(0, 10000); + } + async back() { + const page = this.ensurePage(); + await page.goBack(); + return { url: page.url() }; + } + async forward() { + const page = this.ensurePage(); + await page.goForward(); + return { url: page.url() }; + } + async reload() { + const page = this.ensurePage(); + await page.reload(); + return { url: page.url() }; + } + async wait(ms = 1000) { + const page = this.ensurePage(); + await page.waitForTimeout(ms); + } + async newPage() { + if (!this.context) { + throw new Error('Browser not launched. Call launch() first.'); + } + this.page = await this.context.newPage(); + } + async eval(script) { + const page = this.ensurePage(); + return page.evaluate(script); + } + async executeCommand(cmd) { + try { + switch (cmd.cmd) { + case 'goto': { + const result = await this.goto(cmd.url); + return { ok: true, ...result }; + } + case 'click': { + const result = await this.click(cmd.selector); + return { ok: true, ...result }; + } + case 'type': { + await this.type(cmd.selector, cmd.text); + return { ok: true }; + } + case 'query': { + const elements = await this.query(cmd.selector); + return { ok: true, count: elements.length, elements }; + } + case 'screenshot': { + const result = await this.screenshot(cmd.path, cmd.fullPage); + return { ok: true, path: result.path }; + } + case 'url': { + const result = await this.getUrl(); + return { ok: true, ...result }; + } + case 'html': { + const html = await this.getHtml(cmd.full); + return { ok: true, html }; + } + case 'back': { + const result = await this.back(); + return { ok: true, ...result }; + } + case 'forward': { + const result = await this.forward(); + return { ok: true, ...result }; + } + case 'reload': { + const result = await this.reload(); + return { ok: true, ...result }; + } + case 'wait': { + await this.wait(cmd.ms); + return { ok: true }; + } + case 'newpage': { + await this.newPage(); + return { ok: true }; + } + case 'close': { + await this.close(); + return { ok: true }; + } + case 'eval': { + const result = await this.eval(cmd.script); + return { ok: true, result }; + } + case 'favicon': { + const result = await image.createFavicon(cmd.input, cmd.outputDir); + return { ok: true, files: result.files, outputDir: result.outputDir }; + } + case 'convert': { + const result = await image.convert(cmd.input, cmd.output, cmd.format); + return { + ok: true, + path: result.path, + width: result.width, + height: result.height, + format: result.format, + size: result.size, + }; + } + case 'resize': { + const result = await image.resize(cmd.input, cmd.output, cmd.width, cmd.height, cmd.fit); + return { + ok: true, + path: result.path, + width: result.width, + height: result.height, + format: result.format, + size: result.size, + }; + } + case 'crop': { + const result = await image.crop(cmd.input, cmd.output, cmd.left, cmd.top, cmd.width, cmd.height); + return { + ok: true, + path: result.path, + width: result.width, + height: result.height, + format: result.format, + size: result.size, + }; + } + case 'compress': { + const result = await image.compress(cmd.input, cmd.output, cmd.quality); + return { + ok: true, + path: result.path, + width: result.width, + height: result.height, + format: result.format, + size: result.size, + }; + } + case 'thumbnail': { + const result = await image.thumbnail(cmd.input, cmd.output, cmd.size); + return { + ok: true, + path: result.path, + width: result.width, + height: result.height, + format: result.format, + size: result.size, + }; + } + default: { + const _exhaustive = cmd; + return { ok: false, error: `Unknown command: ${_exhaustive.cmd}` }; + } + } + } + catch (err) { + return { ok: false, error: err.message }; + } + } +} +//# sourceMappingURL=browser.js.map \ No newline at end of file diff --git a/dist/browser.js.map b/dist/browser.js.map new file mode 100644 index 0000000..3b9f5fd --- /dev/null +++ b/dist/browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/browser.test.d.ts b/dist/browser.test.d.ts new file mode 100644 index 0000000..fde4f05 --- /dev/null +++ b/dist/browser.test.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=browser.test.d.ts.map \ No newline at end of file diff --git a/dist/browser.test.d.ts.map b/dist/browser.test.d.ts.map new file mode 100644 index 0000000..3ab0deb --- /dev/null +++ b/dist/browser.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.test.d.ts","sourceRoot":"","sources":["../src/browser.test.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/browser.test.js b/dist/browser.test.js new file mode 100644 index 0000000..1b1f1e2 --- /dev/null +++ b/dist/browser.test.js @@ -0,0 +1,73 @@ +import { describe, expect, it } from 'vitest'; +import { ClaudeBrowser } from './browser.js'; +describe('ClaudeBrowser', () => { + describe('constructor', () => { + it('creates browser with default options', () => { + const browser = new ClaudeBrowser(); + expect(browser).toBeInstanceOf(ClaudeBrowser); + }); + it('accepts custom options', () => { + const browser = new ClaudeBrowser({ + headless: false, + width: 1920, + height: 1080, + }); + expect(browser).toBeInstanceOf(ClaudeBrowser); + }); + }); + describe('ensurePage (via executeCommand)', () => { + it('throws error when browser not launched', async () => { + const browser = new ClaudeBrowser(); + const result = await browser.executeCommand({ cmd: 'url' }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toContain('Browser not launched'); + } + }); + }); + describe('executeCommand', () => { + it('returns error for commands without launch', async () => { + const browser = new ClaudeBrowser(); + const gotoResult = await browser.executeCommand({ cmd: 'goto', url: 'https://example.com' }); + expect(gotoResult.ok).toBe(false); + const clickResult = await browser.executeCommand({ cmd: 'click', selector: '#btn' }); + expect(clickResult.ok).toBe(false); + const typeResult = await browser.executeCommand({ + cmd: 'type', + selector: '#input', + text: 'test', + }); + expect(typeResult.ok).toBe(false); + const queryResult = await browser.executeCommand({ cmd: 'query', selector: '.item' }); + expect(queryResult.ok).toBe(false); + const screenshotResult = await browser.executeCommand({ cmd: 'screenshot' }); + expect(screenshotResult.ok).toBe(false); + const htmlResult = await browser.executeCommand({ cmd: 'html' }); + expect(htmlResult.ok).toBe(false); + const backResult = await browser.executeCommand({ cmd: 'back' }); + expect(backResult.ok).toBe(false); + const forwardResult = await browser.executeCommand({ cmd: 'forward' }); + expect(forwardResult.ok).toBe(false); + const reloadResult = await browser.executeCommand({ cmd: 'reload' }); + expect(reloadResult.ok).toBe(false); + const waitResult = await browser.executeCommand({ cmd: 'wait', ms: 100 }); + expect(waitResult.ok).toBe(false); + const evalResult = await browser.executeCommand({ cmd: 'eval', script: '1+1' }); + expect(evalResult.ok).toBe(false); + }); + it('handles close command without error when not launched', async () => { + const browser = new ClaudeBrowser(); + const result = await browser.executeCommand({ cmd: 'close' }); + expect(result.ok).toBe(true); + }); + it('handles newpage command error when not launched', async () => { + const browser = new ClaudeBrowser(); + const result = await browser.executeCommand({ cmd: 'newpage' }); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toContain('Browser not launched'); + } + }); + }); +}); +//# sourceMappingURL=browser.test.js.map \ No newline at end of file diff --git a/dist/browser.test.js.map b/dist/browser.test.js.map new file mode 100644 index 0000000..4947aba --- /dev/null +++ b/dist/browser.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser.test.js","sourceRoot":"","sources":["../src/browser.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/cli.d.ts b/dist/cli.d.ts new file mode 100644 index 0000000..faaadd5 --- /dev/null +++ b/dist/cli.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export {}; +//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/dist/cli.d.ts.map b/dist/cli.d.ts.map new file mode 100644 index 0000000..f022439 --- /dev/null +++ b/dist/cli.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/cli.js b/dist/cli.js new file mode 100755 index 0000000..8b44a86 --- /dev/null +++ b/dist/cli.js @@ -0,0 +1,243 @@ +#!/usr/bin/env node +import { resolve } from 'node:path'; +import { parseArgs } from 'node:util'; +import { ClaudeBrowser } from './browser.js'; +import * as image from './image.js'; +import { startServer } from './server.js'; +const { values, positionals } = parseArgs({ + allowPositionals: true, + options: { + output: { type: 'string', short: 'o', default: 'screenshot.png' }, + width: { type: 'string', short: 'w', default: '1280' }, + height: { type: 'string', short: 'h', default: '800' }, + fullpage: { type: 'boolean', short: 'f', default: false }, + wait: { type: 'string', default: '2000' }, + headed: { type: 'boolean', default: false }, + interactive: { type: 'boolean', short: 'i', default: false }, + query: { type: 'string', short: 'q' }, + json: { type: 'boolean', short: 'j', default: false }, + click: { type: 'string', short: 'c', multiple: true }, + type: { type: 'string', short: 't', multiple: true }, + help: { type: 'boolean', default: false }, + version: { type: 'boolean', short: 'v', default: false }, + // Image processing options + favicon: { type: 'string' }, + convert: { type: 'string' }, + resize: { type: 'string' }, + compress: { type: 'string' }, + }, +}); +const HELP = ` +Usage: claude-browse [options] + +Options: + -o, --output Output screenshot path (default: screenshot.png) + -w, --width Viewport width (default: 1280) + -h, --height Viewport height (default: 800) + -f, --fullpage Capture full page scroll + --wait Wait time after load (default: 2000) + --headed Show browser window + -i, --interactive Keep browser open for manual interaction + -q, --query Query elements by CSS selector and show attributes + -j, --json Output query results as JSON + -c, --click Click on element (can be repeated for multiple clicks) + -t, --type = Type text into input (can be repeated) + -v, --version Show version + --help Show this help + +Image Processing: + --favicon Generate favicon set to directory (from screenshot or input) + --convert Convert screenshot to format (png, jpeg, webp, avif) + --resize Resize screenshot (e.g., 800x600 or 800 for width only) + --compress Compress with quality 1-100 + +Examples: + claude-browse https://example.com + claude-browse -o page.png -w 1920 -h 1080 https://example.com + claude-browse -i --headed https://example.com + claude-browse -q "a[href]" https://example.com + claude-browse -q "img" -j https://example.com + claude-browse -c "button.submit" https://example.com + claude-browse -t "input[name=q]=hello" -c "button[type=submit]" https://google.com + claude-browse -c ".cookie-accept" -c "a.nav-link" -q "h1" https://example.com + +Image processing examples: + claude-browse https://example.com --favicon ./favicons/ + claude-browse https://example.com -o page.webp --convert webp + claude-browse https://example.com --resize 800x600 + claude-browse https://example.com --compress 60 + +Server mode (default): + claude-browse # Start server on port 13373 + claude-browse --headed # Start with visible browser + + # Send commands via curl: + curl -X POST http://localhost:13373 -d '{"cmd":"goto","url":"https://example.com"}' + curl -X POST http://localhost:13373 -d '{"cmd":"click","selector":"button"}' + curl -X POST http://localhost:13373 -d '{"cmd":"type","selector":"input","text":"hello"}' + curl -X POST http://localhost:13373 -d '{"cmd":"query","selector":"a[href]"}' + curl -X POST http://localhost:13373 -d '{"cmd":"screenshot","path":"shot.png"}' + curl -X POST http://localhost:13373 -d '{"cmd":"url"}' + curl -X POST http://localhost:13373 -d '{"cmd":"html"}' + curl -X POST http://localhost:13373 -d '{"cmd":"close"}' + + # Image processing via server: + curl localhost:13373 -d '{"cmd":"favicon","input":"screenshot.png","outputDir":"./favicons"}' + curl localhost:13373 -d '{"cmd":"convert","input":"img.png","output":"img.webp","format":"webp"}' + curl localhost:13373 -d '{"cmd":"resize","input":"img.png","output":"small.png","width":400}' + curl localhost:13373 -d '{"cmd":"compress","input":"img.png","output":"compressed.png","quality":60}' +`; +function getViewportConfig() { + return { + headless: !values.headed, + width: Number.parseInt(values.width), + height: Number.parseInt(values.height), + }; +} +async function runServerMode() { + const port = 13373; + const server = await startServer({ port, ...getViewportConfig() }); + process.on('SIGINT', async () => { + console.log('\nShutting down...'); + await server.stop(); + process.exit(0); + }); + await new Promise(() => { }); +} +async function processTypeActions(browser) { + const typeActions = values.type; + if (!typeActions?.length) + return; + for (const typeAction of typeActions) { + const eqIndex = typeAction.indexOf('='); + if (eqIndex === -1) { + console.error(`Invalid --type format: "${typeAction}" (expected selector=text)`); + continue; + } + const selector = typeAction.slice(0, eqIndex); + const text = typeAction.slice(eqIndex + 1); + console.log(`Typing "${text}" into: ${selector}`); + await browser.type(selector, text); + } +} +async function processClickActions(browser) { + const clickActions = values.click; + if (!clickActions?.length) + return; + for (const selector of clickActions) { + console.log(`Clicking: ${selector}`); + await browser.click(selector); + await browser.wait(500); + } + const { url: currentUrl } = await browser.getUrl(); + console.log(`Current URL: ${currentUrl}`); +} +function printElement(el, index) { + console.log(`[${index + 1}] <${el.tag}>`); + for (const [name, value] of Object.entries(el.attributes)) { + console.log(` ${name}="${value}"`); + } + if (el.text) { + const truncated = el.text.length > 100 ? `${el.text.slice(0, 100)}...` : el.text; + console.log(` text: "${truncated}"`); + } + console.log(); +} +async function runQueryMode(browser) { + const elements = await browser.query(values.query); + if (values.json) { + console.log(JSON.stringify(elements, null, 2)); + } + else { + console.log(`Found ${elements.length} element(s) matching "${values.query}":\n`); + elements.forEach(printElement); + } + await browser.close(); + process.exit(0); +} +async function runInteractiveMode(browser) { + console.log('Interactive mode - browser will stay open.'); + console.log('Press Ctrl+C to exit.'); + process.on('SIGINT', async () => { + console.log('\nClosing browser...'); + await browser.close(); + process.exit(0); + }); + await new Promise(() => { }); +} +async function processImageOptions(screenshotPath) { + // Process image options on the screenshot + if (values.favicon) { + console.log(`Generating favicon set to: ${values.favicon}`); + const result = await image.createFavicon(screenshotPath, values.favicon); + console.log(`Created ${result.files.length} favicon files`); + } + if (values.convert) { + const format = values.convert; + const outputPath = screenshotPath.replace(/\.[^.]+$/, `.${format}`); + console.log(`Converting to ${format}: ${outputPath}`); + await image.convert(screenshotPath, outputPath, format); + } + if (values.resize) { + const resizeValue = values.resize; + const [widthStr, heightStr] = resizeValue.split('x'); + const width = Number.parseInt(widthStr); + const height = heightStr ? Number.parseInt(heightStr) : undefined; + console.log(`Resizing to ${width}${height ? `x${height}` : ''}`); + await image.resize(screenshotPath, screenshotPath, width, height); + } + if (values.compress) { + const quality = Number.parseInt(values.compress); + console.log(`Compressing with quality ${quality}`); + await image.compress(screenshotPath, screenshotPath, quality); + } +} +async function runScreenshotMode(browser) { + const outputPath = resolve(values.output); + console.log(`Saving screenshot to: ${outputPath}`); + await browser.screenshot(outputPath, values.fullpage); + // Process any image options + await processImageOptions(outputPath); + await browser.close(); + console.log('Done!'); +} +async function runBrowserMode() { + const url = positionals[0]; + const browser = new ClaudeBrowser(getViewportConfig()); + await browser.launch(); + console.log(`Navigating to: ${url}`); + await browser.goto(url); + await browser.wait(Number.parseInt(values.wait)); + await processTypeActions(browser); + await processClickActions(browser); + if (values.query) { + await runQueryMode(browser); + return; + } + if (values.interactive) { + await runInteractiveMode(browser); + } + else { + await runScreenshotMode(browser); + } +} +async function main() { + if (values.version) { + console.log('claude-browse 0.1.0'); + process.exit(0); + } + if (values.help) { + console.log(HELP); + process.exit(0); + } + if (positionals.length === 0) { + await runServerMode(); + return; + } + await runBrowserMode(); +} +main().catch((err) => { + console.error('Error:', err.message); + process.exit(1); +}); +//# sourceMappingURL=cli.js.map \ No newline at end of file diff --git a/dist/cli.js.map b/dist/cli.js.map new file mode 100644 index 0000000..bbb67fd --- /dev/null +++ b/dist/cli.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/image.d.ts b/dist/image.d.ts new file mode 100644 index 0000000..117d4e0 --- /dev/null +++ b/dist/image.d.ts @@ -0,0 +1,21 @@ +export type FitType = 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; +export type FormatType = 'png' | 'jpeg' | 'webp' | 'avif'; +export type ThumbnailSize = 'small' | 'medium' | 'large'; +export interface FaviconResult { + files: string[]; + outputDir: string; +} +export interface ImageResult { + path: string; + width?: number; + height?: number; + format?: string; + size?: number; +} +export declare function createFavicon(input: string, outputDir: string): Promise; +export declare function convert(input: string, output: string, format: FormatType): Promise; +export declare function resize(input: string, output: string, width: number, height?: number, fit?: FitType): Promise; +export declare function crop(input: string, output: string, left: number, top: number, width: number, height: number): Promise; +export declare function compress(input: string, output: string, quality?: number): Promise; +export declare function thumbnail(input: string, output: string, size?: ThumbnailSize): Promise; +//# sourceMappingURL=image.d.ts.map \ No newline at end of file diff --git a/dist/image.d.ts.map b/dist/image.d.ts.map new file mode 100644 index 0000000..d374a88 --- /dev/null +++ b/dist/image.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC1E,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAiBzD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B5F;AAED,wBAAsB,OAAO,CAC3B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,WAAW,CAAC,CA+BtB;AAED,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,GAAG,GAAE,OAAiB,GACrB,OAAO,CAAC,WAAW,CAAC,CAatB;AAED,wBAAsB,IAAI,CACxB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,WAAW,CAAC,CAatB;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,SAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAqChG;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,aAAwB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAGtB"} \ No newline at end of file diff --git a/dist/image.js b/dist/image.js new file mode 100644 index 0000000..9d3f852 --- /dev/null +++ b/dist/image.js @@ -0,0 +1,131 @@ +import { mkdir } from 'node:fs/promises'; +import { dirname, join, resolve } from 'node:path'; +import sharp from 'sharp'; +const THUMBNAIL_SIZES = { + small: 150, + medium: 300, + large: 600, +}; +const FAVICON_SIZES = [ + { name: 'favicon-16x16.png', size: 16 }, + { name: 'favicon-32x32.png', size: 32 }, + { name: 'favicon-48x48.png', size: 48 }, + { name: 'apple-touch-icon.png', size: 180 }, + { name: 'android-chrome-192x192.png', size: 192 }, + { name: 'android-chrome-512x512.png', size: 512 }, +]; +async function ensureDir(filePath) { + await mkdir(dirname(filePath), { recursive: true }); +} +export async function createFavicon(input, outputDir) { + const resolvedDir = resolve(outputDir); + await mkdir(resolvedDir, { recursive: true }); + const files = []; + const image = sharp(input); + for (const { name, size } of FAVICON_SIZES) { + const outputPath = join(resolvedDir, name); + await image.clone().resize(size, size, { fit: 'cover' }).png().toFile(outputPath); + files.push(outputPath); + } + // Create favicon.ico with multiple sizes (16, 32, 48) + const icoPath = join(resolvedDir, 'favicon.ico'); + const sizes = [16, 32, 48]; + const buffers = await Promise.all(sizes.map((size) => image.clone().resize(size, size, { fit: 'cover' }).png().toBuffer())); + // ICO format: simple approach - use largest PNG as ICO + // For true multi-size ICO, we'd need a dedicated library + // Sharp doesn't support ICO output, so we'll use the 32x32 PNG + await image.clone().resize(32, 32, { fit: 'cover' }).png().toFile(icoPath); + files.push(icoPath); + return { files, outputDir: resolvedDir }; +} +export async function convert(input, output, format) { + const resolvedOutput = resolve(output); + await ensureDir(resolvedOutput); + const image = sharp(input); + let result; + switch (format) { + case 'png': + result = image.png(); + break; + case 'jpeg': + result = image.jpeg(); + break; + case 'webp': + result = image.webp(); + break; + case 'avif': + result = image.avif(); + break; + } + const info = await result.toFile(resolvedOutput); + return { + path: resolvedOutput, + width: info.width, + height: info.height, + format: info.format, + size: info.size, + }; +} +export async function resize(input, output, width, height, fit = 'cover') { + const resolvedOutput = resolve(output); + await ensureDir(resolvedOutput); + const info = await sharp(input).resize(width, height, { fit }).toFile(resolvedOutput); + return { + path: resolvedOutput, + width: info.width, + height: info.height, + format: info.format, + size: info.size, + }; +} +export async function crop(input, output, left, top, width, height) { + const resolvedOutput = resolve(output); + await ensureDir(resolvedOutput); + const info = await sharp(input).extract({ left, top, width, height }).toFile(resolvedOutput); + return { + path: resolvedOutput, + width: info.width, + height: info.height, + format: info.format, + size: info.size, + }; +} +export async function compress(input, output, quality = 80) { + const resolvedOutput = resolve(output); + await ensureDir(resolvedOutput); + const image = sharp(input); + const metadata = await image.metadata(); + const format = metadata.format; + let result; + switch (format) { + case 'png': + result = image.png({ quality }); + break; + case 'jpeg': + case 'jpg': + result = image.jpeg({ quality }); + break; + case 'webp': + result = image.webp({ quality }); + break; + case 'avif': + result = image.avif({ quality }); + break; + default: + // Default to PNG for unknown formats + result = image.png({ quality }); + } + const info = await result.toFile(resolvedOutput); + return { + path: resolvedOutput, + width: info.width, + height: info.height, + format: info.format, + size: info.size, + }; +} +export async function thumbnail(input, output, size = 'medium') { + const dimension = THUMBNAIL_SIZES[size]; + return resize(input, output, dimension, dimension, 'cover'); +} +//# sourceMappingURL=image.js.map \ No newline at end of file diff --git a/dist/image.js.map b/dist/image.js.map new file mode 100644 index 0000000..d9abfaa --- /dev/null +++ b/dist/image.js.map @@ -0,0 +1 @@ +{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..a3ae16b --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,6 @@ +export { ClaudeBrowser } from './browser.js'; +export { BrowserServer, startServer } from './server.js'; +export { createFavicon, convert, resize, crop, compress, thumbnail, type FaviconResult, type ImageResult, type FitType, type FormatType, type ThumbnailSize, } from './image.js'; +export type { BrowserOptions, BrowserCommand, CommandResponse, ElementInfo, SuccessResponse, ErrorResponse, GotoCommand, ClickCommand, TypeCommand, QueryCommand, ScreenshotCommand, UrlCommand, HtmlCommand, BackCommand, ForwardCommand, ReloadCommand, WaitCommand, NewPageCommand, CloseCommand, EvalCommand, FaviconCommand, ConvertCommand, ResizeCommand, CropCommand, CompressCommand, ThumbnailCommand, } from './types.js'; +export type { ServerOptions } from './server.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map new file mode 100644 index 0000000..816a3b9 --- /dev/null +++ b/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,aAAa,EACb,OAAO,EACP,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,UAAU,EACf,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,UAAU,EACV,WAAW,EACX,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..09004f2 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,4 @@ +export { ClaudeBrowser } from './browser.js'; +export { BrowserServer, startServer } from './server.js'; +export { createFavicon, convert, resize, crop, compress, thumbnail, } from './image.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..726528c --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,aAAa,EACb,OAAO,EACP,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,SAAS,GAMV,MAAM,YAAY,CAAC"} \ No newline at end of file diff --git a/dist/logger.d.ts b/dist/logger.d.ts new file mode 100644 index 0000000..47d8dd8 --- /dev/null +++ b/dist/logger.d.ts @@ -0,0 +1,41 @@ +export declare const icons: Record; +export declare const cmdColor: Record string>; +export declare function ts(): string; +export declare function truncate(str: string, max: number): string; +export interface CommandLike { + cmd: string; + url?: string; + selector?: string; + text?: string; + path?: string; + full?: boolean; + ms?: number; + script?: string; +} +export declare function getCommandDetail(cmd: CommandLike): string | undefined; +export declare function formatCommand(cmd: CommandLike): string; +export interface ResultLike { + ok: boolean; + error?: string; + title?: string; + url?: string; + count?: number; + path?: string; + html?: string; + result?: unknown; +} +export declare function formatResult(cmd: CommandLike, result: ResultLike): string; +export type LogFn = (msg: string) => void; +export declare function createLogger(logFn?: LogFn): { + command(cmd: CommandLike): void; + result(cmd: CommandLike, result: ResultLike): void; +}; +export declare const logger: { + command(cmd: CommandLike): void; + result(cmd: CommandLike, result: ResultLike): void; +}; +export declare const stderrLogger: { + command(cmd: CommandLike): void; + result(cmd: CommandLike, result: ResultLike): void; +}; +//# sourceMappingURL=logger.d.ts.map \ No newline at end of file diff --git a/dist/logger.d.ts.map b/dist/logger.d.ts.map new file mode 100644 index 0000000..0ed017e --- /dev/null +++ b/dist/logger.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAexC,CAAC;AAGF,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAe1D,CAAC;AAEF,wBAAgB,EAAE,IAAI,MAAM,CAE3B;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAoBrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAMtD;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAYD,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAQzE;AAED,MAAM,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAE1C,wBAAgB,YAAY,CAAC,KAAK,GAAE,KAAmB;iBAEtC,WAAW,GAAG,IAAI;gBAGnB,WAAW,UAAU,UAAU,GAAG,IAAI;EAIrD;AAGD,eAAO,MAAM,MAAM;iBAVF,WAAW,GAAG,IAAI;gBAGnB,WAAW,UAAU,UAAU,GAAG,IAAI;CAOlB,CAAC;AAGrC,eAAO,MAAM,YAAY;iBAbR,WAAW,GAAG,IAAI;gBAGnB,WAAW,UAAU,UAAU,GAAG,IAAI;CAU6B,CAAC"} \ No newline at end of file diff --git a/dist/logger.js b/dist/logger.js new file mode 100644 index 0000000..1d2b980 --- /dev/null +++ b/dist/logger.js @@ -0,0 +1,103 @@ +import chalk from 'chalk'; +import logSymbols from 'log-symbols'; +// Icons for commands +export const icons = { + goto: '→', + click: '◉', + type: '⌨', + query: '?', + screenshot: '📷', + url: '🔗', + html: '<>', + back: '←', + forward: '→', + reload: '↻', + wait: '⏳', + newpage: '+', + close: '✕', + eval: '⚡', +}; +// Colors for command types +export const cmdColor = { + 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, +}; +export function ts() { + return chalk.gray(`[${new Date().toISOString()}]`); +} +export function truncate(str, max) { + return str.length > max ? `${str.slice(0, max)}...` : str; +} +export function getCommandDetail(cmd) { + 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; + } +} +export function formatCommand(cmd) { + const color = cmdColor[cmd.cmd] || chalk.white; + const icon = icons[cmd.cmd] || '•'; + const detail = getCommandDetail(cmd); + const suffix = detail ? ` ${detail}` : ''; + return `${ts()} ${chalk.bold(color(icon))} ${color(cmd.cmd.toUpperCase())}${suffix}`; +} +const resultFormatters = { + goto: (r) => r.title, + click: (r) => (r.url ? `→ ${r.url}` : undefined), + query: (r) => (r.count !== undefined ? `Found ${r.count} element(s)` : undefined), + screenshot: (r) => (r.path ? `Saved to ${r.path}` : undefined), + url: (r) => r.url, + html: (r) => (r.html !== undefined ? `${r.html.length} chars` : undefined), + eval: (r) => (r.result !== undefined ? truncate(JSON.stringify(r.result), 80) : undefined), +}; +export function formatResult(cmd, result) { + if (!result.ok) { + return `${ts()} ${logSymbols.error} ${chalk.red(result.error)}`; + } + const formatter = resultFormatters[cmd.cmd]; + const msg = formatter ? formatter(result) : undefined; + const suffix = msg ? ` ${chalk.dim(msg)}` : ''; + return `${ts()} ${logSymbols.success}${suffix}`; +} +export function createLogger(logFn = console.log) { + return { + command(cmd) { + logFn(formatCommand(cmd)); + }, + result(cmd, result) { + logFn(formatResult(cmd, result)); + }, + }; +} +// Default logger to stdout +export const logger = createLogger(); +// Logger to stderr (for MCP) +export const stderrLogger = createLogger((msg) => process.stderr.write(`${msg}\n`)); +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/dist/logger.js.map b/dist/logger.js.map new file mode 100644 index 0000000..ea6fc1a --- /dev/null +++ b/dist/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/logger.test.d.ts b/dist/logger.test.d.ts new file mode 100644 index 0000000..c33838e --- /dev/null +++ b/dist/logger.test.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=logger.test.d.ts.map \ No newline at end of file diff --git a/dist/logger.test.d.ts.map b/dist/logger.test.d.ts.map new file mode 100644 index 0000000..cbcd822 --- /dev/null +++ b/dist/logger.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.test.d.ts","sourceRoot":"","sources":["../src/logger.test.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/logger.test.js b/dist/logger.test.js new file mode 100644 index 0000000..df2727f --- /dev/null +++ b/dist/logger.test.js @@ -0,0 +1,146 @@ +import { describe, expect, it, vi } from 'vitest'; +import { createLogger, formatCommand, formatResult, getCommandDetail, icons, truncate, } from './logger.js'; +describe('truncate', () => { + it('returns string unchanged if shorter than max', () => { + expect(truncate('hello', 10)).toBe('hello'); + }); + it('truncates and adds ellipsis if longer than max', () => { + expect(truncate('hello world', 5)).toBe('hello...'); + }); + it('handles exact length', () => { + expect(truncate('hello', 5)).toBe('hello'); + }); +}); +describe('icons', () => { + it('has icon for each command type', () => { + expect(icons.goto).toBe('→'); + expect(icons.click).toBe('◉'); + expect(icons.type).toBe('⌨'); + expect(icons.screenshot).toBe('📷'); + }); +}); +describe('getCommandDetail', () => { + it('returns url for goto command', () => { + const result = getCommandDetail({ cmd: 'goto', url: 'https://example.com' }); + expect(result).toContain('https://example.com'); + }); + it('returns selector for click command', () => { + const result = getCommandDetail({ cmd: 'click', selector: '#btn' }); + expect(result).toContain('#btn'); + }); + it('returns selector and text for type command', () => { + const result = getCommandDetail({ cmd: 'type', selector: '#input', text: 'hello' }); + expect(result).toContain('#input'); + expect(result).toContain('hello'); + }); + it('returns path for screenshot command', () => { + const result = getCommandDetail({ cmd: 'screenshot', path: 'test.png' }); + expect(result).toContain('test.png'); + }); + it('returns default path when none provided for screenshot', () => { + const result = getCommandDetail({ cmd: 'screenshot' }); + expect(result).toContain('screenshot.png'); + }); + it('returns undefined for url command', () => { + expect(getCommandDetail({ cmd: 'url' })).toBeUndefined(); + }); + it('returns ms for wait command', () => { + const result = getCommandDetail({ cmd: 'wait', ms: 500 }); + expect(result).toContain('500'); + }); + it('returns default ms for wait command without ms', () => { + const result = getCommandDetail({ cmd: 'wait' }); + expect(result).toContain('1000'); + }); + it('returns script for eval command', () => { + const result = getCommandDetail({ cmd: 'eval', script: 'document.title' }); + expect(result).toContain('document.title'); + }); + it('truncates long eval scripts', () => { + const longScript = 'a'.repeat(100); + const result = getCommandDetail({ cmd: 'eval', script: longScript }); + expect(result).toContain('...'); + }); + it('returns (full) for html command with full=true', () => { + const result = getCommandDetail({ cmd: 'html', full: true }); + expect(result).toContain('full'); + }); + it('returns undefined for html command with full=false', () => { + expect(getCommandDetail({ cmd: 'html', full: false })).toBeUndefined(); + }); + it('returns selector for query command', () => { + const result = getCommandDetail({ cmd: 'query', selector: '.items' }); + expect(result).toContain('.items'); + }); +}); +describe('formatCommand', () => { + it('formats goto command', () => { + const result = formatCommand({ cmd: 'goto', url: 'https://example.com' }); + expect(result).toContain('GOTO'); + expect(result).toContain('https://example.com'); + }); + it('formats click command', () => { + const result = formatCommand({ cmd: 'click', selector: '#btn' }); + expect(result).toContain('CLICK'); + expect(result).toContain('#btn'); + }); +}); +describe('formatResult', () => { + it('formats error result', () => { + const result = formatResult({ cmd: 'goto' }, { ok: false, error: 'Failed' }); + expect(result).toContain('Failed'); + }); + it('formats successful goto result with title', () => { + const result = formatResult({ cmd: 'goto' }, { ok: true, title: 'Example' }); + expect(result).toContain('Example'); + }); + it('formats query result with count', () => { + const result = formatResult({ cmd: 'query' }, { ok: true, count: 5 }); + expect(result).toContain('5'); + }); + it('formats click result with url', () => { + const result = formatResult({ cmd: 'click' }, { ok: true, url: '/page' }); + expect(result).toContain('/page'); + }); + it('formats screenshot result with path', () => { + const result = formatResult({ cmd: 'screenshot' }, { ok: true, path: 'test.png' }); + expect(result).toContain('Saved to test.png'); + }); + it('formats url result', () => { + const result = formatResult({ cmd: 'url' }, { ok: true, url: 'https://example.com' }); + expect(result).toContain('https://example.com'); + }); + it('formats html result with length', () => { + const result = formatResult({ cmd: 'html' }, { ok: true, html: '' }); + expect(result).toContain('13 chars'); + }); + it('formats eval result', () => { + const result = formatResult({ cmd: 'eval' }, { ok: true, result: { foo: 'bar' } }); + expect(result).toContain('foo'); + expect(result).toContain('bar'); + }); + it('formats result without formatter', () => { + const result = formatResult({ cmd: 'wait' }, { ok: true }); + expect(result).toBeDefined(); + }); +}); +describe('createLogger', () => { + it('creates logger with custom log function', () => { + const logs = []; + const logFn = (msg) => logs.push(msg); + const logger = createLogger(logFn); + logger.command({ cmd: 'goto', url: 'https://example.com' }); + expect(logs).toHaveLength(1); + expect(logs[0]).toContain('GOTO'); + logger.result({ cmd: 'goto' }, { ok: true, title: 'Example' }); + expect(logs).toHaveLength(2); + }); + it('logs command and result', () => { + const spy = vi.fn(); + const logger = createLogger(spy); + logger.command({ cmd: 'click', selector: '#btn' }); + logger.result({ cmd: 'click' }, { ok: true, url: '/page' }); + expect(spy).toHaveBeenCalledTimes(2); + }); +}); +//# sourceMappingURL=logger.test.js.map \ No newline at end of file diff --git a/dist/logger.test.js.map b/dist/logger.test.js.map new file mode 100644 index 0000000..a72aa7b --- /dev/null +++ b/dist/logger.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../src/logger.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/mcp.d.ts b/dist/mcp.d.ts new file mode 100644 index 0000000..2cbf15d --- /dev/null +++ b/dist/mcp.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export {}; +//# sourceMappingURL=mcp.d.ts.map \ No newline at end of file diff --git a/dist/mcp.d.ts.map b/dist/mcp.d.ts.map new file mode 100644 index 0000000..08fe7fa --- /dev/null +++ b/dist/mcp.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/mcp.js b/dist/mcp.js new file mode 100755 index 0000000..9fe5ece --- /dev/null +++ b/dist/mcp.js @@ -0,0 +1,536 @@ +#!/usr/bin/env node +import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { z } from 'zod'; +import { ClaudeBrowser } from './browser.js'; +import * as image from './image.js'; +import { stderrLogger as log } from './logger.js'; +const browser = new ClaudeBrowser({ headless: true, width: 1280, height: 800 }); +let launched = false; +let currentScreenshotBuffer = null; +async function ensureLaunched() { + if (!launched) { + await browser.launch(); + launched = true; + } +} +function textResult(text) { + return { content: [{ type: 'text', text }] }; +} +function withLogging(cmd, fn) { + return async (args) => { + const cmdLike = { cmd, ...args }; + log.command(cmdLike); + try { + const result = await fn(args); + const parsed = JSON.parse(result.content[0]?.text || '{}'); + const resultLike = { ok: true, ...parsed }; + log.result(cmdLike, resultLike); + return result; + } + catch (err) { + log.result(cmdLike, { ok: false, error: err.message }); + throw err; + } + }; +} +const server = new McpServer({ + name: 'claude-browse', + version: '0.1.0', +}); +// Navigation +server.tool('goto', 'Navigate to a URL', { url: z.string().url() }, withLogging('goto', async ({ url }) => { + await ensureLaunched(); + const result = await browser.goto(url); + return textResult(JSON.stringify(result)); +})); +server.tool('back', 'Go back in browser history', {}, withLogging('back', async () => { + await ensureLaunched(); + const result = await browser.back(); + return textResult(JSON.stringify(result)); +})); +server.tool('forward', 'Go forward in browser history', {}, withLogging('forward', async () => { + await ensureLaunched(); + const result = await browser.forward(); + return textResult(JSON.stringify(result)); +})); +server.tool('reload', 'Reload the current page', {}, withLogging('reload', async () => { + await ensureLaunched(); + const result = await browser.reload(); + return textResult(JSON.stringify(result)); +})); +// Interaction +server.tool('click', 'Click on an element', { selector: z.string() }, withLogging('click', async ({ selector }) => { + await ensureLaunched(); + const result = await browser.click(selector); + return textResult(JSON.stringify(result)); +})); +server.tool('type', 'Type text into an input field', { selector: z.string(), text: z.string() }, withLogging('type', async ({ selector, text }) => { + await ensureLaunched(); + await browser.type(selector, text); + return textResult(JSON.stringify({ ok: true })); +})); +// Query +server.tool('query', 'Query elements by CSS selector, returns tag, text, and attributes', { selector: z.string() }, withLogging('query', async ({ selector }) => { + await ensureLaunched(); + const elements = await browser.query(selector); + return textResult(JSON.stringify({ ok: true, count: elements.length, elements })); +})); +server.tool('url', 'Get current URL and page title', {}, withLogging('url', async () => { + await ensureLaunched(); + const result = await browser.getUrl(); + return textResult(JSON.stringify(result)); +})); +server.tool('html', 'Get page HTML content', { full: z.boolean().optional().default(false) }, withLogging('html', async ({ full }) => { + await ensureLaunched(); + const html = await browser.getHtml(full); + return textResult(JSON.stringify({ ok: true, html })); +})); +// Screenshot +server.tool('screenshot', 'Take a screenshot of the current page', { + path: z.string().optional().default('screenshots/screenshot.png'), + fullPage: z.boolean().optional().default(false), +}, withLogging('screenshot', async ({ path, fullPage }) => { + await ensureLaunched(); + const result = await browser.screenshot(path, fullPage); + return textResult(JSON.stringify({ ok: true, path: result.path })); +})); +// Eval +server.tool('eval', 'Execute JavaScript in the browser context', { script: z.string() }, withLogging('eval', async ({ script }) => { + await ensureLaunched(); + const result = await browser.eval(script); + return textResult(JSON.stringify({ ok: true, result })); +})); +// Utility +server.tool('wait', 'Wait for a specified time in milliseconds', { ms: z.number().optional().default(1000) }, withLogging('wait', async ({ ms }) => { + await ensureLaunched(); + await browser.wait(ms); + return textResult(JSON.stringify({ ok: true })); +})); +// Session management +server.tool('close', 'Close the browser and end the current session', {}, withLogging('close', async () => { + if (launched) { + await browser.close(); + launched = false; + } + return textResult(JSON.stringify({ ok: true, message: 'Browser closed' })); +})); +server.tool('session_save', 'Save the current session state (URL, cookies, localStorage, sessionStorage) to a JSON file', { + path: z.string().optional().default('session.json').describe('Path to save session file'), +}, withLogging('session_save', async ({ path }) => { + await ensureLaunched(); + const { writeFile } = await import('node:fs/promises'); + const { resolve } = await import('node:path'); + const page = browser.getPage(); + const context = browser.getContext(); + if (!page || !context) { + return textResult(JSON.stringify({ ok: false, error: 'No active page' })); + } + const url = page.url(); + const title = await page.title(); + const cookies = await context.cookies(); + // Get localStorage and sessionStorage (runs in browser context) + const storage = await page.evaluate(`({ + localStorage: Object.fromEntries( + Array.from({ length: localStorage.length }, (_, i) => localStorage.key(i)) + .filter(k => k !== null) + .map(k => [k, localStorage.getItem(k) || '']) + ), + sessionStorage: Object.fromEntries( + Array.from({ length: sessionStorage.length }, (_, i) => sessionStorage.key(i)) + .filter(k => k !== null) + .map(k => [k, sessionStorage.getItem(k) || '']) + ), + })`); + const sessionData = { + url, + title, + cookies, + localStorage: storage.localStorage, + sessionStorage: storage.sessionStorage, + savedAt: new Date().toISOString(), + }; + const resolvedPath = resolve(path); + await writeFile(resolvedPath, JSON.stringify(sessionData, null, 2)); + return textResult(JSON.stringify({ ok: true, path: resolvedPath, url, cookieCount: cookies.length })); +})); +server.tool('session_restore', 'Restore a previously saved session state from a JSON file', { + path: z.string().optional().default('session.json').describe('Path to session file'), +}, withLogging('session_restore', async ({ path }) => { + await ensureLaunched(); + const { readFile } = await import('node:fs/promises'); + const { resolve } = await import('node:path'); + const resolvedPath = resolve(path); + const data = JSON.parse(await readFile(resolvedPath, 'utf-8')); + const page = browser.getPage(); + const context = browser.getContext(); + if (!page || !context) { + return textResult(JSON.stringify({ ok: false, error: 'No active page' })); + } + // Restore cookies first + if (data.cookies?.length > 0) { + await context.addCookies(data.cookies); + } + // Navigate to saved URL + if (data.url) { + await page.goto(data.url, { waitUntil: 'networkidle' }); + } + // Restore storage (runs in browser context) + const local = data.localStorage || {}; + const session = data.sessionStorage || {}; + await page.evaluate(`((data) => { + for (const [k, v] of Object.entries(data.local)) localStorage.setItem(k, v); + for (const [k, v] of Object.entries(data.session)) sessionStorage.setItem(k, v); + })(${JSON.stringify({ local, session })})`); + return textResult(JSON.stringify({ + ok: true, + url: data.url, + title: data.title, + cookiesRestored: data.cookies?.length || 0, + savedAt: data.savedAt, + })); +})); +// Image processing +server.tool('favicon', 'Generate a complete favicon set from an image (16x16, 32x32, 48x48, apple-touch-icon 180x180, android-chrome 192x192 and 512x512)', { + input: z.string().describe('Path to source image'), + outputDir: z.string().describe('Directory to output favicon files'), +}, withLogging('favicon', async ({ input, outputDir }) => { + const result = await image.createFavicon(input, outputDir); + return textResult(JSON.stringify({ ok: true, files: result.files, outputDir: result.outputDir })); +})); +server.tool('convert', 'Convert an image to a different format (png, jpeg, webp, avif)', { + input: z.string().describe('Path to source image'), + output: z.string().describe('Path for output image'), + format: z.enum(['png', 'jpeg', 'webp', 'avif']).describe('Target format'), +}, withLogging('convert', async ({ input, output, format }) => { + const result = await image.convert(input, output, format); + return textResult(JSON.stringify({ ok: true, ...result })); +})); +server.tool('resize', 'Resize an image to specified dimensions', { + input: z.string().describe('Path to source image'), + output: z.string().describe('Path for output image'), + width: z.number().describe('Target width in pixels'), + height: z + .number() + .optional() + .describe('Target height in pixels (optional, maintains aspect ratio if omitted)'), + fit: z + .enum(['cover', 'contain', 'fill', 'inside', 'outside']) + .optional() + .default('cover') + .describe('How to fit the image'), +}, withLogging('resize', async ({ input, output, width, height, fit }) => { + const result = await image.resize(input, output, width, height, fit); + return textResult(JSON.stringify({ ok: true, ...result })); +})); +server.tool('crop', 'Crop a region from an image', { + input: z.string().describe('Path to source image'), + output: z.string().describe('Path for output image'), + left: z.number().describe('Left edge position in pixels'), + top: z.number().describe('Top edge position in pixels'), + width: z.number().describe('Width of crop region in pixels'), + height: z.number().describe('Height of crop region in pixels'), +}, withLogging('crop', async ({ input, output, left, top, width, height }) => { + const result = await image.crop(input, output, left, top, width, height); + return textResult(JSON.stringify({ ok: true, ...result })); +})); +server.tool('compress', 'Compress an image to reduce file size', { + input: z.string().describe('Path to source image'), + output: z.string().describe('Path for output image'), + quality: z.number().min(1).max(100).optional().default(80).describe('Quality level 1-100'), +}, withLogging('compress', async ({ input, output, quality }) => { + const result = await image.compress(input, output, quality); + return textResult(JSON.stringify({ ok: true, ...result })); +})); +server.tool('thumbnail', 'Create a thumbnail from an image', { + input: z.string().describe('Path to source image'), + output: z.string().describe('Path for output image'), + size: z + .enum(['small', 'medium', 'large']) + .optional() + .default('medium') + .describe('Thumbnail size preset (small=150px, medium=300px, large=600px)'), +}, withLogging('thumbnail', async ({ input, output, size }) => { + const result = await image.thumbnail(input, output, size); + return textResult(JSON.stringify({ ok: true, ...result })); +})); +// ============================================================================ +// MCP Resources - Browser state accessible via @ mentions +// ============================================================================ +// Resource: browser://state - Current browser state (URL, title, launched status) +server.resource('Browser State', 'browser://state', { + description: 'Current browser state including URL, title, and status', + mimeType: 'application/json', +}, async () => { + if (!launched) { + return { + contents: [ + { + uri: 'browser://state', + mimeType: 'application/json', + text: JSON.stringify({ launched: false, url: null, title: null }), + }, + ], + }; + } + const state = await browser.getUrl(); + return { + contents: [ + { + uri: 'browser://state', + mimeType: 'application/json', + text: JSON.stringify({ launched: true, ...state }), + }, + ], + }; +}); +// Resource: browser://html - Current page HTML content +server.resource('Page HTML', 'browser://html', { description: 'HTML content of the current page (truncated to 10KB)', mimeType: 'text/html' }, async () => { + if (!launched) { + return { + contents: [ + { + uri: 'browser://html', + mimeType: 'text/plain', + text: 'Browser not launched. Use goto tool first.', + }, + ], + }; + } + const html = await browser.getHtml(false); + return { + contents: [ + { + uri: 'browser://html', + mimeType: 'text/html', + text: html, + }, + ], + }; +}); +// Resource: browser://html/full - Full page HTML content +server.resource('Full Page HTML', 'browser://html/full', { description: 'Complete HTML content of the current page', mimeType: 'text/html' }, async () => { + if (!launched) { + return { + contents: [ + { + uri: 'browser://html/full', + mimeType: 'text/plain', + text: 'Browser not launched. Use goto tool first.', + }, + ], + }; + } + const html = await browser.getHtml(true); + return { + contents: [ + { + uri: 'browser://html/full', + mimeType: 'text/html', + text: html, + }, + ], + }; +}); +// Resource: browser://screenshot - Current page screenshot (base64) +server.resource('Page Screenshot', 'browser://screenshot', { description: 'Screenshot of the current page as base64 PNG', mimeType: 'image/png' }, async () => { + if (!launched) { + return { + contents: [ + { + uri: 'browser://screenshot', + mimeType: 'text/plain', + text: 'Browser not launched. Use goto tool first.', + }, + ], + }; + } + const result = await browser.screenshot(undefined, false); + currentScreenshotBuffer = result.buffer || null; + return { + contents: [ + { + uri: 'browser://screenshot', + mimeType: 'image/png', + blob: result.buffer?.toString('base64') || '', + }, + ], + }; +}); +// ============================================================================ +// MCP Prompts - Common workflows accessible via / commands +// ============================================================================ +// Prompt: Analyze current page +server.prompt('analyze_page', 'Analyze the current page content and structure', async () => { + if (!launched) { + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: 'The browser is not launched yet. Please use the goto tool to navigate to a URL first, then I can analyze the page.', + }, + }, + ], + }; + } + const state = await browser.getUrl(); + const html = await browser.getHtml(false); + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `Analyze the following webpage: + +URL: ${state.url} +Title: ${state.title} + +HTML Content (truncated): +\`\`\`html +${html} +\`\`\` + +Please provide: +1. A summary of the page purpose and content +2. Key interactive elements (forms, buttons, links) +3. Any notable structure or patterns +4. Suggestions for what actions might be useful`, + }, + }, + ], + }; +}); +// Prompt: Extract data from page +server.prompt('extract_data', 'Extract structured data from the current page', { selector: z.string().optional().describe('CSS selector to focus extraction (optional)') }, async ({ selector }) => { + if (!launched) { + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: 'The browser is not launched yet. Please use the goto tool to navigate to a URL first.', + }, + }, + ], + }; + } + const state = await browser.getUrl(); + let elements = []; + if (selector) { + elements = await browser.query(selector); + } + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `Extract structured data from this webpage: + +URL: ${state.url} +Title: ${state.title} +${selector ? `\nSelector: ${selector}\nMatched Elements: ${elements.length}\n\nElements:\n${JSON.stringify(elements, null, 2)}` : ''} + +Please: +1. Use the query tool to find relevant data elements +2. Extract and structure the data in a useful format (JSON, table, etc.) +3. Identify patterns that could help with similar pages`, + }, + }, + ], + }; +}); +// Prompt: Navigate and interact +server.prompt('navigate_to', 'Navigate to a URL and describe what you find', { url: z.string().url().describe('URL to navigate to') }, async ({ url }) => { + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `Please navigate to ${url} and: + +1. Use the goto tool to navigate there +2. Take a screenshot to see the page +3. Describe what you see +4. Identify the main interactive elements +5. Suggest what actions might be useful + +Start by navigating to the URL.`, + }, + }, + ], + }; +}); +// Prompt: Fill form +server.prompt('fill_form', 'Help fill out a form on the current page', { formData: z.string().optional().describe('JSON object with field names and values to fill') }, async ({ formData }) => { + if (!launched) { + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: 'The browser is not launched yet. Please use the goto tool to navigate to a page with a form first.', + }, + }, + ], + }; + } + const state = await browser.getUrl(); + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `Help fill out a form on this page: + +URL: ${state.url} +Title: ${state.title} +${formData ? `\nData to fill: ${formData}` : ''} + +Please: +1. Use the query tool to find form inputs (input, textarea, select) +2. Identify required fields and their types +3. Use the type tool to fill in each field +4. Report what was filled and any issues encountered`, + }, + }, + ], + }; +}); +// Prompt: Screenshot comparison +server.prompt('compare_screenshots', 'Take screenshots and compare changes', async () => { + return { + messages: [ + { + role: 'user', + content: { + type: 'text', + text: `I'll help you compare page states: + +1. Take an initial screenshot +2. Perform some action (click, navigate, etc.) +3. Take another screenshot +4. Describe the differences + +What action would you like me to perform between screenshots?`, + }, + }, + ], + }; +}); +// ============================================================================ +// Start server +// ============================================================================ +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); +} +main().catch(console.error); +//# sourceMappingURL=mcp.js.map \ No newline at end of file diff --git a/dist/mcp.js.map b/dist/mcp.js.map new file mode 100644 index 0000000..cc5a714 --- /dev/null +++ b/dist/mcp.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/server.d.ts b/dist/server.d.ts new file mode 100644 index 0000000..dd69181 --- /dev/null +++ b/dist/server.d.ts @@ -0,0 +1,20 @@ +import type { BrowserOptions } from './types.js'; +export interface ServerOptions extends BrowserOptions { + port?: number; +} +export declare class BrowserServer { + private browser; + private app; + private server; + private port; + constructor(options?: ServerOptions); + private setupMiddleware; + private setupRoutes; + private handleCommand; + start(): Promise; + stop(): Promise; + getPort(): number; + getApp(): import("express-serve-static-core").Express; +} +export declare function startServer(options?: ServerOptions): Promise; +//# sourceMappingURL=server.d.ts.map \ No newline at end of file diff --git a/dist/server.d.ts.map b/dist/server.d.ts.map new file mode 100644 index 0000000..296c5ae --- /dev/null +++ b/dist/server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAuBD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,MAAM,CAAmD;IACjE,OAAO,CAAC,IAAI,CAAS;gBAET,OAAO,GAAE,aAAkB;IAOvC,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,WAAW;YAIL,aAAa;IAsBrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,OAAO,IAAI,MAAM;IAIjB,MAAM;CAGP;AAED,wBAAsB,WAAW,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,CAAC,CAIrF"} \ No newline at end of file diff --git a/dist/server.js b/dist/server.js new file mode 100644 index 0000000..8d220b5 --- /dev/null +++ b/dist/server.js @@ -0,0 +1,88 @@ +import chalk from 'chalk'; +import express from 'express'; +import logSymbols from 'log-symbols'; +import { ClaudeBrowser } from './browser.js'; +import { logger, ts } from './logger.js'; +function printBanner(port) { + console.log(); + console.log(chalk.cyan.bold(' 🌐 Claude Browse Server')); + console.log(chalk.dim(' ─────────────────────────')); + console.log(` ${logSymbols.success} Listening on ${chalk.bold(`http://localhost:${port}`)}`); + console.log(); + console.log(chalk.dim(' Commands:')); + console.log(` ${chalk.cyan('goto')} ${chalk.yellow('click')} ${chalk.magenta('type')} ${chalk.blue('query')} ${chalk.green('screenshot')}`); + console.log(` ${chalk.cyan('url')} ${chalk.blue('html')} ${chalk.yellow('back')} ${chalk.yellow('forward')} ${chalk.yellow('reload')} ${chalk.gray('wait')} ${chalk.red('close')}`); + console.log(); + console.log(chalk.dim(' Example:')); + console.log(chalk.gray(` curl -X POST localhost:${port} -d '{"cmd":"goto","url":"https://example.com"}'`)); + console.log(); +} +export class BrowserServer { + browser; + app = express(); + server = null; + port; + constructor(options = {}) { + this.browser = new ClaudeBrowser(options); + this.port = options.port ?? 13373; + this.setupMiddleware(); + this.setupRoutes(); + } + setupMiddleware() { + this.app.use(express.json()); + this.app.use(express.text({ type: '*/*' })); + } + setupRoutes() { + this.app.post('/', (req, res) => this.handleCommand(req, res)); + } + async handleCommand(req, res) { + try { + const cmd = typeof req.body === 'string' ? JSON.parse(req.body) : req.body; + logger.command(cmd); + if (cmd.cmd === 'close') { + logger.result(cmd, { ok: true }); + res.json({ ok: true }); + await this.stop(); + process.exit(0); + } + const result = await this.browser.executeCommand(cmd); + logger.result(cmd, result); + res.json(result); + } + catch (err) { + const error = err.message; + console.log(`${ts()} ${logSymbols.error} ${chalk.red(error)}`); + res.status(500).json({ ok: false, error }); + } + } + async start() { + await this.browser.launch(); + return new Promise((resolve) => { + this.server = this.app.listen(this.port, () => { + printBanner(this.port); + resolve(); + }); + }); + } + async stop() { + console.log(chalk.dim('\n Shutting down...')); + if (this.server) { + this.server.close(); + this.server = null; + } + await this.browser.close(); + console.log(` ${logSymbols.success} Browser closed\n`); + } + getPort() { + return this.port; + } + getApp() { + return this.app; + } +} +export async function startServer(options = {}) { + const server = new BrowserServer(options); + await server.start(); + return server; +} +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/server.js.map b/dist/server.js.map new file mode 100644 index 0000000..8342227 --- /dev/null +++ b/dist/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/server.test.d.ts b/dist/server.test.d.ts new file mode 100644 index 0000000..964123b --- /dev/null +++ b/dist/server.test.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=server.test.d.ts.map \ No newline at end of file diff --git a/dist/server.test.d.ts.map b/dist/server.test.d.ts.map new file mode 100644 index 0000000..bf805bc --- /dev/null +++ b/dist/server.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/server.test.js b/dist/server.test.js new file mode 100644 index 0000000..f60f107 --- /dev/null +++ b/dist/server.test.js @@ -0,0 +1,164 @@ +import request from 'supertest'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { BrowserServer } from './server.js'; +// Mock the browser module +vi.mock('./browser.js', () => ({ + ClaudeBrowser: class MockClaudeBrowser { + async launch() { } + async close() { } + async executeCommand(cmd) { + switch (cmd.cmd) { + case 'goto': + return { ok: true, url: cmd.url, title: 'Test Page' }; + case 'click': + return { ok: true, url: '/clicked' }; + case 'type': + return { ok: true }; + case 'query': + return { ok: true, count: 2, elements: [] }; + case 'url': + return { ok: true, url: 'https://example.com', title: 'Example' }; + case 'html': + return { ok: true, html: '' }; + case 'back': + return { ok: true, url: '/previous' }; + case 'forward': + return { ok: true, url: '/next' }; + case 'reload': + return { ok: true, url: '/current' }; + case 'wait': + return { ok: true }; + case 'screenshot': + return { ok: true, path: cmd.path || 'screenshot.png' }; + case 'eval': + return { ok: true, result: 2 }; + case 'newpage': + return { ok: true }; + case 'error': + throw new Error('Test error'); + default: + return { ok: true }; + } + } + }, +})); +describe('BrowserServer', () => { + let server; + beforeAll(async () => { + server = new BrowserServer({ port: 0 }); // Use port 0 to get random available port + }); + afterAll(async () => { + await server.stop(); + }); + describe('constructor', () => { + it('creates server with default port', () => { + const s = new BrowserServer(); + expect(s.getPort()).toBe(13373); + }); + it('creates server with custom port', () => { + const s = new BrowserServer({ port: 8080 }); + expect(s.getPort()).toBe(8080); + }); + }); + describe('POST /', () => { + it('handles goto command', async () => { + const app = server.getApp(); + const res = await request(app) + .post('/') + .send({ cmd: 'goto', url: 'https://example.com' }) + .expect(200); + expect(res.body.ok).toBe(true); + expect(res.body.url).toBe('https://example.com'); + expect(res.body.title).toBe('Test Page'); + }); + it('handles click command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'click', selector: '#btn' }).expect(200); + expect(res.body.ok).toBe(true); + expect(res.body.url).toBe('/clicked'); + }); + it('handles type command', async () => { + const app = server.getApp(); + const res = await request(app) + .post('/') + .send({ cmd: 'type', selector: '#input', text: 'hello' }) + .expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles query command', async () => { + const app = server.getApp(); + const res = await request(app) + .post('/') + .send({ cmd: 'query', selector: '.items' }) + .expect(200); + expect(res.body.ok).toBe(true); + expect(res.body.count).toBe(2); + }); + it('handles url command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'url' }).expect(200); + expect(res.body.ok).toBe(true); + expect(res.body.url).toBe('https://example.com'); + }); + it('handles html command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'html' }).expect(200); + expect(res.body.ok).toBe(true); + expect(res.body.html).toBe(''); + }); + it('handles JSON string body', async () => { + const app = server.getApp(); + const res = await request(app) + .post('/') + .set('Content-Type', 'text/plain') + .send(JSON.stringify({ cmd: 'url' })) + .expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles back command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'back' }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles forward command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'forward' }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles reload command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'reload' }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles wait command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'wait', ms: 100 }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles screenshot command', async () => { + const app = server.getApp(); + const res = await request(app) + .post('/') + .send({ cmd: 'screenshot', path: 'test.png' }) + .expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles eval command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'eval', script: '1+1' }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles newpage command', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'newpage' }).expect(200); + expect(res.body.ok).toBe(true); + }); + it('handles errors and returns 500', async () => { + const app = server.getApp(); + const res = await request(app).post('/').send({ cmd: 'error' }).expect(500); + expect(res.body.ok).toBe(false); + expect(res.body.error).toBe('Test error'); + }); + }); +}); +//# sourceMappingURL=server.test.js.map \ No newline at end of file diff --git a/dist/server.test.js.map b/dist/server.test.js.map new file mode 100644 index 0000000..405484f --- /dev/null +++ b/dist/server.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.test.js","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,0BAA0B;AAC1B,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,iBAAiB;QACpC,KAAK,CAAC,MAAM,KAAI,CAAC;QACjB,KAAK,CAAC,KAAK,KAAI,CAAC;QAChB,KAAK,CAAC,cAAc,CAAC,GAAiD;YACpE,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC;gBAChB,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;gBACxD,KAAK,OAAO;oBACV,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;gBACvC,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;gBACtB,KAAK,OAAO;oBACV,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;gBAC9C,KAAK,KAAK;oBACR,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,qBAAqB,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;gBACpE,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;gBAC7C,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;gBACxC,KAAK,SAAS;oBACZ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;gBACpC,KAAK,QAAQ;oBACX,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;gBACvC,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;gBACtB,KAAK,YAAY;oBACf,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,gBAAgB,EAAE,CAAC;gBAC1D,KAAK,MAAM;oBACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;gBACjC,KAAK,SAAS;oBACZ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;gBACtB,KAAK,OAAO;oBACV,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;gBAChC;oBACE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;KACF;CACF,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,MAAqB,CAAC;IAE1B,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,0CAA0C;IACrF,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,GAAG,IAAI,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,qBAAqB,EAAE,CAAC;iBACjD,MAAM,CAAC,GAAG,CAAC,CAAC;YAEf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACjD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAE9F,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;iBACxD,MAAM,CAAC,GAAG,CAAC,CAAC;YAEf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;YACrC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;iBAC1C,MAAM,CAAC,GAAG,CAAC,CAAC;YAEf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;YACnC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAE1E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAE3E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC;iBACT,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC;iBACjC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;iBACpC,MAAM,CAAC,GAAG,CAAC,CAAC;YAEf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpF,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;iBAC3B,IAAI,CAAC,GAAG,CAAC;iBACT,IAAI,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;iBAC7C,MAAM,CAAC,GAAG,CAAC,CAAC;YACf,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1F,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5E,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts new file mode 100644 index 0000000..ce5c7fd --- /dev/null +++ b/dist/types.d.ts @@ -0,0 +1,125 @@ +export interface BrowserOptions { + headless?: boolean; + width?: number; + height?: number; +} +export interface ElementInfo { + tag: string; + text: string; + attributes: Record; +} +export interface GotoCommand { + cmd: 'goto'; + url: string; +} +export interface ClickCommand { + cmd: 'click'; + selector: string; +} +export interface TypeCommand { + cmd: 'type'; + selector: string; + text: string; +} +export interface QueryCommand { + cmd: 'query'; + selector: string; +} +export interface ScreenshotCommand { + cmd: 'screenshot'; + path?: string; + fullPage?: boolean; +} +export interface UrlCommand { + cmd: 'url'; +} +export interface HtmlCommand { + cmd: 'html'; + full?: boolean; +} +export interface BackCommand { + cmd: 'back'; +} +export interface ForwardCommand { + cmd: 'forward'; +} +export interface ReloadCommand { + cmd: 'reload'; +} +export interface WaitCommand { + cmd: 'wait'; + ms?: number; +} +export interface NewPageCommand { + cmd: 'newpage'; +} +export interface CloseCommand { + cmd: 'close'; +} +export interface EvalCommand { + cmd: 'eval'; + script: string; +} +export interface FaviconCommand { + cmd: 'favicon'; + input: string; + outputDir: string; +} +export interface ConvertCommand { + cmd: 'convert'; + input: string; + output: string; + format: 'png' | 'jpeg' | 'webp' | 'avif'; +} +export interface ResizeCommand { + cmd: 'resize'; + input: string; + output: string; + width: number; + height?: number; + fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; +} +export interface CropCommand { + cmd: 'crop'; + input: string; + output: string; + left: number; + top: number; + width: number; + height: number; +} +export interface CompressCommand { + cmd: 'compress'; + input: string; + output: string; + quality?: number; +} +export interface ThumbnailCommand { + cmd: 'thumbnail'; + input: string; + output: string; + size?: 'small' | 'medium' | 'large'; +} +export type BrowserCommand = GotoCommand | ClickCommand | TypeCommand | QueryCommand | ScreenshotCommand | UrlCommand | HtmlCommand | BackCommand | ForwardCommand | ReloadCommand | WaitCommand | NewPageCommand | CloseCommand | EvalCommand | FaviconCommand | ConvertCommand | ResizeCommand | CropCommand | CompressCommand | ThumbnailCommand; +export interface SuccessResponse { + ok: true; + url?: string; + title?: string; + path?: string; + html?: string; + count?: number; + elements?: ElementInfo[]; + result?: unknown; + files?: string[]; + outputDir?: string; + width?: number; + height?: number; + format?: string; + size?: number; +} +export interface ErrorResponse { + ok: false; + error: string; +} +export type CommandResponse = SuccessResponse | ErrorResponse; +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/dist/types.d.ts.map b/dist/types.d.ts.map new file mode 100644 index 0000000..1184137 --- /dev/null +++ b/dist/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/types.js b/dist/types.js new file mode 100644 index 0000000..718fd38 --- /dev/null +++ b/dist/types.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/types.js.map b/dist/types.js.map new file mode 100644 index 0000000..c768b79 --- /dev/null +++ b/dist/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""} \ No newline at end of file