From 9e5ffd2ccfa0223c7d0acbff52269b81cb7e6d55 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 27 May 2025 01:25:09 -0700 Subject: [PATCH] fix(cursor): allow enforcing images for cursor --image-responses=allow (#478) Fixes https://github.com/microsoft/playwright-mcp/issues/449 --- config.d.ts | 4 ++-- src/config.ts | 8 ++------ src/connection.ts | 3 +-- src/context.ts | 9 +++++++++ src/program.ts | 2 +- src/tools/screenshot.ts | 2 +- tests/screenshot.spec.ts | 4 ++-- 7 files changed, 18 insertions(+), 14 deletions(-) diff --git a/config.d.ts b/config.d.ts index 8b38e6d..1c010aa 100644 --- a/config.d.ts +++ b/config.d.ts @@ -117,7 +117,7 @@ export type Config = { }; /** - * Do not send image responses to the client. + * Whether to send image responses to the client. Can be "allow", "omit", or "auto". Defaults to "auto", which sends images if the client can display them. */ - noImageResponses?: boolean; + imageResponses?: 'allow' | 'omit' | 'auto'; }; diff --git a/src/config.ts b/src/config.ts index ef768da..047fdc0 100644 --- a/src/config.ts +++ b/src/config.ts @@ -38,7 +38,7 @@ export type CLIOptions = { host?: string; ignoreHttpsErrors?: boolean; isolated?: boolean; - imageResponses: boolean; + imageResponses?: 'allow' | 'omit' | 'auto'; sandbox: boolean; outputDir?: string; port?: number; @@ -188,13 +188,9 @@ export async function configFromCLIOptions(cliOptions: CLIOptions): Promise(resolve => { this.server.oninitialized = () => resolve(); }); - if (this.server.getClientVersion()?.name.includes('cursor')) - this.context.config.noImageResponses = true; + this.context.clientVersion = this.server.getClientVersion(); } async close() { diff --git a/src/context.ts b/src/context.ts index d131609..8da2dbb 100644 --- a/src/context.ts +++ b/src/context.ts @@ -48,12 +48,21 @@ export class Context { private _modalStates: (ModalState & { tab: Tab })[] = []; private _pendingAction: PendingAction | undefined; private _downloads: { download: playwright.Download, finished: boolean, outputFile: string }[] = []; + clientVersion: { name: string; version: string; } | undefined; constructor(tools: Tool[], config: FullConfig) { this.tools = tools; this.config = config; } + clientSupportsImages(): boolean { + if (this.config.imageResponses === 'allow') + return true; + if (this.config.imageResponses === 'omit') + return false; + return !this.clientVersion?.name.includes('cursor'); + } + modalStates(): ModalState[] { return this._modalStates; } diff --git a/src/program.ts b/src/program.ts index 1f49736..8638342 100644 --- a/src/program.ts +++ b/src/program.ts @@ -40,7 +40,7 @@ program .option('--host ', 'host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.') .option('--ignore-https-errors', 'ignore https errors') .option('--isolated', 'keep the browser profile in memory, do not save it to disk.') - .option('--no-image-responses', 'do not send image responses to the client.') + .option('--image-responses ', 'whether to send image responses to the client. Can be "allow", "omit", or "auto". Defaults to "auto", which sends images if the client can display them.') .option('--no-sandbox', 'disable the sandbox for all process types that are normally sandboxed.') .option('--output-dir ', 'path to the directory for output files.') .option('--port ', 'port to listen on for SSE transport.') diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts index 3317103..439d79a 100644 --- a/src/tools/screenshot.ts +++ b/src/tools/screenshot.ts @@ -64,7 +64,7 @@ const screenshot = defineTool({ else code.push(`await page.screenshot(${javascript.formatObject(options)});`); - const includeBase64 = !context.config.noImageResponses; + const includeBase64 = context.clientSupportsImages(); const action = async () => { const screenshot = locator ? await locator.screenshot(options) : await tab.page.screenshot(options); return { diff --git a/tests/screenshot.spec.ts b/tests/screenshot.spec.ts index b1d73f6..d771359 100644 --- a/tests/screenshot.spec.ts +++ b/tests/screenshot.spec.ts @@ -172,12 +172,12 @@ test('browser_take_screenshot (filename: "output.jpeg")', async ({ startClient, expect(files[0]).toMatch(/^output\.jpeg$/); }); -test('browser_take_screenshot (noImageResponses)', async ({ startClient, server }, testInfo) => { +test('browser_take_screenshot (imageResponses=omit)', async ({ startClient, server }, testInfo) => { const outputDir = testInfo.outputPath('output'); const client = await startClient({ config: { outputDir, - noImageResponses: true, + imageResponses: 'omit', }, });