From 701eccb588477e54a418b2da51eadaae4554fed8 Mon Sep 17 00:00:00 2001 From: Nils Reeh Date: Sun, 5 Apr 2026 23:40:24 +0200 Subject: [PATCH] fix(browser-tools): make sharp an optional lazy dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sharp requires platform-specific native binaries and is unavailable when running via bunx or on platforms like Raspberry Pi (ARM) where the prebuilt binary may not exist. The previous top-level static import caused the browser-tools extension to crash at load time before any tool was ever called. Replace the static import with a lazy getSharp() helper that catches import failures and caches the result. constrainScreenshot returns the raw buffer unchanged when sharp is unavailable — screenshots remain functional, just without resizing. The core bunx extension-loading fix (routing bunx through virtualModules in loader.ts) belongs upstream in pi-mono and will be submitted there once the OSS weekend freeze lifts on 2026-04-13. Related: #3504 Co-Authored-By: Claude Sonnet 4.6 --- .../extensions/browser-tools/capture.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/resources/extensions/browser-tools/capture.ts b/src/resources/extensions/browser-tools/capture.ts index 0c980b871..508bada65 100644 --- a/src/resources/extensions/browser-tools/capture.ts +++ b/src/resources/extensions/browser-tools/capture.ts @@ -6,7 +6,22 @@ */ import type { Frame, Page } from "playwright"; -import sharp from "sharp"; + +// sharp is an optional native dependency. Load it lazily so that the extension +// can still be loaded on platforms where sharp is unavailable (e.g. bunx on +// Raspberry Pi). constrainScreenshot falls back to returning the raw buffer +// when sharp is not installed, which means screenshots won't be resized but +// the tool remains functional. +let _sharp: typeof import("sharp") | null | undefined; +async function getSharp(): Promise { + if (_sharp !== undefined) return _sharp; + try { + _sharp = (await import("sharp")).default; + } catch { + _sharp = null; + } + return _sharp; +} import type { CompactPageState, CompactSelectorState } from "./state.js"; import { formatCompactStateSummary } from "./utils.js"; @@ -168,6 +183,9 @@ export async function constrainScreenshot( mimeType: string, quality: number, ): Promise { + const sharp = await getSharp(); + if (!sharp) return buffer; + const meta = await sharp(buffer).metadata(); const width = meta.width; const height = meta.height;