Files
liqiang b119135836
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
2026-08-20 13:12:50 +00:00

102 lines
2.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Slidev 渲染器:把 Proposer 生成的 slides.md 真正渲染成“每页一张 PNG”。
这是本实验的关键——Reviewer 之所以能看到 Proposer 看不到的“新信息”,
正是因为我们真的把代码跑起来、渲染出了像素级的截图。
实现:调用本地安装的 Slidev CLI
npx slidev export slides.md --format png --output <dir> --timeout 60000
Slidev 的 PNG 导出底层用 playwright-chromium 打开每一页并截图。
"""
import glob
import os
import shutil
import subprocess
WORKSPACE = os.path.join(os.path.dirname(__file__), "slidev_workspace")
class RenderError(RuntimeError):
pass
def render_slides(slides_md: str, out_subdir: str) -> list[str]:
"""
将 slides_md 文本写入工作区并导出为逐页 PNG。
参数:
slides_md: 完整的 Slidev markdown 源码
out_subdir: 输出子目录名(如 'proposer_iter1'
返回:
按页码排序的 PNG 绝对路径列表。
"""
os.makedirs(WORKSPACE, exist_ok=True)
slides_path = os.path.join(WORKSPACE, "slides.md")
with open(slides_path, "w", encoding="utf-8") as f:
f.write(slides_md)
out_dir = os.path.join(WORKSPACE, "exports", out_subdir)
if os.path.exists(out_dir):
shutil.rmtree(out_dir)
os.makedirs(out_dir, exist_ok=True)
# Slidev 的 PNG 导出会在 output 目录下生成 1.png, 2.png ...
cmd = [
"npx", "--no-install", "slidev", "export", "slides.md",
"--format", "png",
"--output", out_dir,
"--timeout", "60000",
"--dark", "false",
]
env = dict(os.environ)
# 让 playwright 使用项目内安装的 chromiumpackage.json 里的 playwright-chromium
proc = subprocess.run(
cmd, cwd=WORKSPACE, env=env,
capture_output=True, text=True, timeout=600,
)
if proc.returncode != 0:
raise RenderError(
"Slidev export 失败:\n"
f"stdout:\n{proc.stdout[-2000:]}\n"
f"stderr:\n{proc.stderr[-2000:]}"
)
pngs = sorted(
glob.glob(os.path.join(out_dir, "*.png")),
key=lambda p: _page_num(p),
)
if not pngs:
raise RenderError(
f"Slidev export 未产出 PNG。stdout:\n{proc.stdout[-2000:]}"
)
return pngs
def _page_num(path: str) -> int:
base = os.path.splitext(os.path.basename(path))[0]
digits = "".join(ch for ch in base if ch.isdigit())
return int(digits) if digits else 0
if __name__ == "__main__":
# 自检:渲染一个最小的两页 slidev
demo = """---
theme: default
---
# Hello Slidev
第一页
---
# 第二页
- 渲染自检成功
"""
paths = render_slides(demo, "selftest")
print("渲染出的 PNG")
for p in paths:
print(" ", p)