screenshot-to-code 如何为 screenshot_preview 工具接入自定义渲染后端?
【免费下载链接】screenshot-to-codeDrop in a screenshot and convert it to clean code (HTML/Tailwind/React/Vue)项目地址: https://gitcode.com/GitHub_Trending/sc/screenshot-to-code
screenshot-to-code 的 agent 有一个screenshot_preview工具:它把当前生成的 HTML 渲染成桌面端和移动端的整页截图,让模型"看到"自己写的页面来验证效果。默认渲染走本地无头 Chromium(Playwright 驱动)。如果你的部署环境跑不了本地浏览器,或者想把渲染统一交给自己的渲染服务(文档注释中给出的示例场景就是"an external rendering API"),你不需要改screenshot_preview工具本身——项目把它设计成了一个可插拔接口,实现ScreenshotBackend并在启动探测之前注册即可。
这篇文章基于 backend/preview_screenshot/ 模块的真实代码,给出实现、注册和验证的完整路径。
先看清调用链:工具只对接一个接口
整条链路是单向的:
- 工具执行入口 run_screenshot_preview 遍历
("desktop", "mobile")两个视口,对每个视口调用capture_preview_screenshot(html, device=viewport, full_page=True); - registry.py 中的
capture_preview_screenshot先对 HTML 做 Babel CDN 归一化(normalize_babel_cdn,保证生成的 React 页面真正挂载后再截图),然后转交给当前激活的后端; - 后端的选择对调用方完全不可见。main.py 在启动时运行
probe_screenshot_preview_on_startup(),调用probe_screenshot_preview()探测后端是否可用。
preview_screenshot/__init__.py对外导出七个名称:ScreenshotBackend、VIEWPORT_SIZES、PlaywrightBackend、capture_preview_screenshot、is_screenshot_preview_available、probe_screenshot_preview、set_screenshot_backend。接入自定义后端你只需要用到前者和set_screenshot_backend。
接口定义:两个方法、两种视口
接口定义在 base.py,是一个typing.Protocol:
class ScreenshotBackend(Protocol): async def capture(self, html: str, device: str, full_page: bool) -> bytes: """Render ``html`` to PNG bytes at the given device viewport.""" ... async def available(self) -> bool: """Whether this backend can run here (warming it up if needed).""" ...两个方法的职责:
capture(html, device, full_page) -> bytes:把 HTML 渲染成 PNG 字节返回。device只会是"desktop"或"mobile",对应共享视口常量VIEWPORT_SIZES:device 视口尺寸(宽 × 高,像素) desktop1280 × 832 mobile342 × 684 available() -> bool:探测当前环境能否渲染,必要时顺手预热(warm up)。这个结果会被启动探测缓存一次,并用于决定是否向模型暴露该工具——registry 中的注释原文是 "Used to gate the tool so it isn't offered when it can't"。
默认实现 PlaywrightBackend 的关键参数可供参考:页面加载超时PAGE_LOAD_TIMEOUT_MS = 15000、渲染稳定等待RENDER_SETTLE_MS = 250,截图固定type="png"。它的 docstring 同时解释了为什么默认要本地渲染:本地页面可以加载来自 localhost 的资源(例如/local-assets/这类 URL),而外部截图 API 是够不到的——如果你的生成页面依赖本地资产 URL,切换外部渲染前先确认这一点。
实现你的自定义后端
接口没有规定实现方式,下面是一个针对"外部渲染服务"的骨架示例。其中对渲染服务的实际请求由你的服务接口决定,示例中标注了需要替换的位置:
class ExternalRenderBackend: """示例骨架:把 HTML 交给外部渲染服务,取回 PNG 字节。 实际 HTTP 请求细节按你的渲染服务接口自行实现; 返回值必须是 PNG 字节(bytes)。 """ async def available(self) -> bool: # 检查渲染服务是否可用(例如做一次健康检查); # 也可以在这里完成预热。返回 False 时工具将不会暴露给模型。 return True async def capture(self, html: str, device: str, full_page: bool) -> bytes: # 将 html 连同 device / full_page 参数发给你的渲染服务, # 返回渲染结果的 PNG 字节 raise NotImplementedError("替换为对渲染服务的真实调用")两点来自源文档的约束:
device只有"desktop"与"mobile"两个取值,full_page在工具调用链中固定为True,你的实现只需覆盖这两个组合;- 传给
capture的html已经被normalize_babel_cdn处理过,后端拿到的是可直接挂载的页面,不要重复做 CDN 归一化。
注册后端:只调用一次,且在启动探测之前
替换动作只有一行,入口在 registry.py:
from preview_screenshot import set_screenshot_backend set_screenshot_backend(ExternalRenderBackend())registry 的 docstring 对调用时机有明确要求:"Install the screenshot backend (call once, before the startup probe)"——只安装一次,且必须发生在启动探测之前。对照 main.py:服务启动时会执行probe_screenshot_preview_on_startup(),它调用probe_screenshot_preview()对当前后端做一次探测并缓存结果。所以自定义后端的安装必须排在这个启动探测运行之前,否则被探测、被缓存下来的仍是默认PlaywrightBackend。
理解探测的缓存行为对验证很有用:
probe_screenshot_preview()只在第一次调用时执行available(),之后直接返回缓存值;is_screenshot_preview_available()在探测尚未运行时默认返回True(避免启动检查完成前误隐藏工具),探测完成后返回缓存结果。
也就是说available()的结果在整个进程生命周期内只算一次,你的实现要能如实反映"此刻能否渲染",而不是临时状态。
验证接入是否生效
文档给出的验证依据集中在探测结果对工具的 gating 上,可按以下顺序确认:
- 看探测日志。默认后端的
available()会打印明确的状态行(以下均为源码中的日志原文,此处作为文档示例展示):- 可用:
[screenshot_preview] Chromium available — tool enabled. - 不可用:
[screenshot_preview] Chromium unavailable — tool disabled. Install it withplaywright install chromium. Cause: {exc}换成自定义后端后,建议在自己的available()里打印同样清晰的状态行,方便在启动日志中确认被调用的是你的实现。
- 可用:
- 确认工具暴露。探测失败(
available()返回False)时,screenshot_preview不会提供给模型——反过来,你的后端返回True后,模型在生成流程中可以正常调用该工具。 - 跑一次真实生成。工具成功时的行为在 screenshot_preview.py 中有明确描述:对当前 HTML 输出桌面端和移动端两张整页 PNG(
preview_desktop.png、preview_mobile.png),作为多模态图片附给模型查看。这些预览只用于模型验证工作结果,不会作为资产持久化,UI 仅内联 data URL 展示缩略图。如果你想核对图片确实来自你的后端,可以在capture()中记录收到的device/full_page参数或返回的字节长度(工具结果image_bytes字段会透出大小)。
相关消费点可以顺带查看:backend/routes/capabilities.py 引用了 screenshot preview 的可用状态;工具行为测试见 backend/tests/test_agent_tools.py。
限制与边界
- 一次安装、一次探测。
set_screenshot_backend与启动探测都只生效一次,不支持运行中热切换后端;探测缓存意味着服务中途不可用不会被自动感知,只能靠调用时的容错(工具侧会把渲染异常包装成Screenshot failed错误返回)。 - 本地资源可达性。如前所述,
PlaywrightBackend的默认理由之一就是能访问 localhost 资产;外部渲染服务天然够不到这类 URL,切换前确认你的页面不依赖它们。 - 不切换时的默认依赖。若仍用默认后端,Chromium 缺失时按文档日志提示安装:
playwright install chromium。
完成上述接入后,可核对的最终结果是:启动日志显示你的后端通过了available()探测,screenshot_preview工具对模型可见,且一次生成流程中返回的桌面/移动端预览 PNG 出自你的渲染服务。
【免费下载链接】screenshot-to-codeDrop in a screenshot and convert it to clean code (HTML/Tailwind/React/Vue)项目地址: https://gitcode.com/GitHub_Trending/sc/screenshot-to-code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考