资讯动态

qwen-code Terminal Capture:基于 node-pty + xterm.js + Playwright 的 CLI 终端截图自动化方案

发布时间:2026/9/12 10:07:08 来源:尧图企业网站定制
qwen-code Terminal Capture基于 node-pty xterm.js Playwright 的 CLI 终端截图自动化方案【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code本文围绕 qwen-code 仓库中.qwen/skills/terminal-capture/SKILL.md所定义的终端截图自动化能力展开介绍如何通过 TypeScript 场景配置驱动真实终端交互并产出像素级截图用于 PR 评审中的 CLI 视觉验证、斜杠命令/about、/context、/auth、/export回归测试与视觉文档生成。读完本文你将掌握从编写场景配置、运行批量截图到理解底层 PTY 渲染原理与排查常见问题的完整实战方案。一、为什么需要终端截图自动化qwen-code 是一套运行在终端中的 AI 编码 Agent其 CLI 界面基于 Ink 组件构建输出大量 ANSI 转义序列颜色、粗体、光标移动、滚动等。现有的测试体系见 integration-tests/terminal-capture/motivation.md已经覆盖了多个层面测试层工具覆盖范围单元测试Vitest ink-testing-libraryInk 组件、核心逻辑、工具函数集成测试Vitest TestRig / SDKTestHelperCLI E2E、SDK 多轮对话、MCP、鉴权终端 UI 文本快照toMatchSnapshot() ink-testing-libraryInk 组件渲染出的 ANSI 文本Web Shell 回归Playwright 视觉测试packages/web-shell浏览器 UI终端 UI 视觉terminal-captureCLI 终端真实渲染截图其中的文本快照只能验证文字内容却无法回答三个关键问题颜色是否正确红色分隔线、绿色高亮、Logo 渐变布局是否对齐表格边框、多列布局整体观感如何组件间距、留白、溢出这些只能通过在真实终端模拟器中渲染才能看到。terminal-capture 正是为此补齐的终端 UI 视觉层。二、架构原理WYSIWYG 所见即所得terminal-capture 的核心哲学是WYSIWYG——让 xterm.js 在浏览器中完整完成终端模拟与渲染截图永远捕捉终端当前的真实状态无需任何手工清理输出。其数据链路如下node-pty (伪终端) ↓ 原始 ANSI 字节流 xterm.js (运行在 Playwright headless Chromium 中) ↓ 完美渲染颜色、粗体、光标、滚动 Playwright 元素截图 ↓ 像素级截图可选 macOS 窗口装饰这条链路在 terminal-capture.ts 的文件头注释中有明确阐述。三个环节各司其职node-ptylydell/node-pty负责以真实伪终端方式启动被测命令命令在 PTY 中运行时产出的原始 ANSI 字节流被累积收集xterm.jsxterm/xterm运行在 Playwright 启动的无头 Chromium 页面内把 ANSI 流原样渲染成终端画面——颜色、粗体、光标、滚动行为与真实终端一致Playwright对渲染出的终端元素执行截图输出像素级 PNG可选叠加 macOS 风格窗口装饰条。三、核心文件地图文件职责integration-tests/terminal-capture/terminal-capture.ts底层引擎PTY、xterm.js、Playwright 的封装提供TerminalCapture类integration-tests/terminal-capture/scenario-runner.ts场景执行器解析配置、驱动交互、自动截图、生成 GIFintegration-tests/terminal-capture/run.tsCLI 入口批量运行场景并输出汇总报告integration-tests/terminal-capture/scenarios/*.ts场景配置文件如about.ts、all.ts、streaming-shell.tsintegration-tests/terminal-capture/package.json依赖声明与npm run capture等快捷脚本依赖方面见 package.jsonlydell/node-pty1.2.0-beta.10、xterm/xterm^5.5.0、playwright^1.50.0、strip-ansi^7.1.2。四、环境准备与 CI 注意事项npm install # 安装项目依赖 npx playwright install chromium # 安装 Playwright 浏览器CI / verify 上下文的重要提醒当设置了QWEN_VERIFY_CHROMIUM1时浏览器已经预先安装好且PLAYWRIGHT_BROWSERS_PATH指向该浏览器。此时不要再执行playwright install——它会下载约 170 MB 的浏览器并且会因系统依赖缺失而失败agent 用户没有安装系统依赖的权限。此外运行含 GIF 生成的 streaming 场景前应确认ffmpeg已安装# 检查 which ffmpeg # 安装 (macOS) brew install ffmpeg若用户拒绝安装 ffmpeg场景仍会正常运行仅跳过 GIF 生成并给出警告对应 scenario-runner.ts 中的兜底逻辑。五、快速开始1. 编写场景配置在integration-tests/terminal-capture/scenarios/下创建.ts文件import type { ScenarioConfig } from ../scenario-runner.js; export default { name: /about, spawn: [node, dist/cli.js, --yolo], // cwd 相对于本配置文件所在位置 terminal: { title: qwen-code, cwd: ../../.. }, flow: [ { type: Hi, can you help me understand this codebase? }, { type: /about }, ], } satisfies ScenarioConfig;2. 运行# 单个场景 npx tsx integration-tests/terminal-capture/run.ts \ integration-tests/terminal-capture/scenarios/about.ts # 批量整个目录 npx tsx integration-tests/terminal-capture/run.ts \ integration-tests/terminal-capture/scenarios/ # glob 通配多个文件 npx tsx integration-tests/terminal-capture/run.ts \ integration-tests/terminal-capture/scenarios/*.ts也可以在integration-tests/terminal-capture目录内使用 package.json 中预置的脚本npm run capture全量、npm run capture:about、npm run capture:all、npm run capture:markdown-rendering。3. 输出产物截图保存在integration-tests/terminal-capture/scenarios/screenshots/{name}/下文件说明01-01.png第 1 步输入状态01-02.png第 1 步执行结果02-01.png第 2 步输入状态02-02.png第 2 步执行结果full-flow.png最终状态全长度截图含回滚缓冲区01-streaming-01.pngstreaming 模式帧 1若有streaming.gif由各帧生成的动画 GIF需 ffmpeg从源码看文件名采用确定性命名无时间戳便于回归对比由 scenario-runner.ts 中的pad()函数按步骤序号零填充生成且每次运行前输出目录会被清空rmSync避免残留旧截图干扰判断。场景名会作为子目录名非法字符被替换为-见 scenario-runner.ts。六、FlowStep API 详解每个 flow 步骤FlowStep可以包含以下字段type: string— 输入文本自动行为输入文本 → 截图 (01) → 回车 → 等待输出稳定 → 截图 (02)。{ type: Hello; } // 纯文本 { type: /about; } // 斜杠命令自动补全由 runner 自动处理特殊规则若下一步是key则不会自动按回车把控制权交给后续按键序列。对应实现见 scenario-runner.tsautoEnter !nextStep?.key同时对于以/开头且自动回车的命令会额外发送一次\x1bEscape关闭自动补全弹层避免干扰截图。key: string | string[]— 发送按键用于菜单选择、Tab 补全等交互。不自动回车、不自动截图。支持的按键名ArrowUp、ArrowDown、ArrowLeft、ArrowRight、Enter、Tab、Escape、Backspace、Space、Home、End、PageUp、PageDown、Delete。{ key: ArrowDown; } // 单键 { key: [ArrowDown, ArrowDown, Enter]; } // 多键序列按键名到 PTY 转义序列的映射定义在 scenario-runner.ts 的KEY_MAP中例如ArrowUp → \x1b[A、Enter → \r、Backspace → \x7f、PageDown → \x1b[6~。未识别的字符串会原样透传给 PTY因此也可以直接传入 ANSI 转义序列。当按键序列结束下一步不再是key时runner 会自动补拍结果截图XX-02.png与全长度截图。按键步骤也可显式携带capture/captureFull字段强制截图。streaming— 执行过程中的连续捕获针对长时间输出如进度条按固定间隔捕获多帧可选生成动画 GIF{ type: Run this command: bash progress.sh, streaming: { delayMs: 7000, // 首次捕获前等待跳过初始等待阶段如模型思考/审批时间 intervalMs: 500, // 两次捕获之间的间隔毫秒 count: 20, // 最大捕获帧数 gif: true, // 生成动画 GIF默认 true需 ffmpeg }, }delayMs可选按回车后、开始捕获前的等待毫秒数用于跳过模型思考/审批耗时若终端输出连续 3 个间隔无变化捕获会提前停止见 scenario-runner.ts无输出变化的重复帧会被自动跳过。streaming对应的真实仓库场景包括scenarios/streaming-shell.ts执行bash progress.sh约 10 秒、20 次迭代的进度条脚本用\r覆盖同一行以delayMs: 7000, intervalMs: 500, count: 20捕获实时渲染效果scenarios/streaming-insight.ts/insight命令分析代码库并流式输出时以intervalMs: 5000, count: 50展示实时进度。进度条测试脚本 scenarios/progress.sh 本身也用于验证 PTY 对回车/光标移动的处理能力。GIF 生成逻辑见 scenario-runner.ts使用 ffmpeg 的 concat demuxer 加调色板方案streaming 帧每帧 300ms、普通帧每帧 1s最终输出streaming.gifffmpeg 缺失时静默降级并打印警告。capture/captureFull— 显式截图可作为独立步骤使用或覆盖自动命名{ capture: initial.png; } // 只截当前视口 { captureFull: all-output.png; } // 截完整回滚缓冲区长图纯截图步骤无type/key会被 runner 当作独立步骤执行见 scenario-runner.ts。此外FlowStep还支持一个源码中才有的扩展字段sleep在执行该步骤前固定等待若干毫秒用于弥合输出已稳定但异步响应稍后到达的场景如/btw旁路问题在主线流式任务之后才返回例如{ sleep: 20000, capture: btw-answered.png }。七、实战场景示例基础输入 命令flow: [{ type: explain this project }, { type: /about }];二级菜单选择/authflow: [ { type: /auth }, { key: ArrowDown }, // 选择 API Key 选项 { key: Enter }, // 确认 { type: sk-xxx }, // 输入 API key ];Tab 补全选择/exportflow: [ { type: Tell me about yourself }, { type: /export }, // 不自动回车下一步是 key { key: Tab }, // 弹出格式选择 { key: ArrowDown }, // 选择格式 { key: Enter }, // 确认 → 自动截图 ];数组批量一个文件内多个场景export default [ { name: /about, spawn: [...], flow: [...] }, { name: /context, spawn: [...], flow: [...] }, ] satisfies ScenarioConfig[];仓库中 scenarios/all.ts 即采用数组形式一口气覆盖/about、/context、/export (tab select)、/auth四个场景run.ts会顺序执行每个文件单个文件可导出数组最后输出汇总通过数、失败数、截图总数与耗时任一失败则以退出码 1 结束见 run.ts。若.ts文件没有 default 导出如独立驱动脚本agent-team-demo.ts会被loadScenarios静默跳过避免批量运行时误报见 scenario-runner.ts。八、终端外观与内置主题terminal字段控制终端渲染外观源码中的默认值见 terminal-capture.ts 与 scenario-runner.ts整理如下字段说明默认值cols终端列数场景层 100引擎层 120rows终端行数场景层 28引擎层 40theme主题dracula|one-dark|github-dark|monokai|night-owl也支持传入自定义主题对象draculachrome是否显示 macOS 窗口装饰红绿灯 标题栏默认 truetruetitle窗口标题仅chrometrue时生效TerminalfontSize字号14cwd工作目录相对配置文件配置文件上一级目录outputDir截图输出目录相对配置文件screenshots/{name}五个内置主题的完整 16 色调色板定义在 terminal-capture.ts 的THEMES常量中。此外引擎层还支持env自定义环境变量与fontFamily字体族默认Menlo, Monaco, Consolas, Courier New, monospace两个扩展选项。值得注意的底层细节引擎在构造时会构建一个适合终端渲染的干净环境——删除NO_COLOR它与FORCE_COLOR冲突可能导致渐变组件崩溃、强制FORCE_COLOR1与TERMxterm-256color、设置NODE_NO_WARNINGS1抑制 Node 警告噪音见 terminal-capture.ts。九、底层实现原理纵深PTY 数据 → xterm.js 的冲刷flushTerminalCapture把 PTY 累积的原始输出按64 KB 分块写入浏览器内的 xterm.jsterm.write(data, callback)的 callback 保证数据已解析完成再等一个requestAnimationFrame确保渲染完成见 terminal-capture.ts。截图前会先 flush 全部数据并等待渲染保证画面是最新状态。captureFull 长图原理captureFull()并不会简单放大页面而是查询 xterm.js buffer 中最后一个非空行号得到真实内容高度只在浏览器内临时把 xterm.jsresize到contentLines 2行并scrollToTop()——注意不改变 PTY 尺寸因此不会向子进程发送 SIGWINCHCLI 不会触发重渲染按约 22px/行fontSize 14 × lineHeight 1.2 padding估算并扩大 Playwright 视口截图后恢复原始尺寸。实现见 terminal-capture.ts。普通capture()在截图前还会执行term.scrollToBottom()把视口锚定到最新输出避免在空闲/整屏重绘后截到过期的回滚内容见 terminal-capture.ts。智能等待Runner 内置两级等待启动后idle(1500, 30000)等待 CLI 就绪每个交互后idle(2000, 60000)等待输出稳定idle()在持续无新输出stableMs毫秒后返回超时不算错误。引擎层还提供waitFor(text)轮询 200ms 直到出现指定文本超时抛出带最近 500 字符的错误信息、waitForAndIdle()、type(text, {slow: true, delay})逐字符模拟真人打字等 API见 terminal-capture.ts。输出访问引擎提供getOutput()去 ANSI 的累积输出与getRawOutput()含 ANSI 的原始流。另外getScreenText()会从 xterm.js buffer 中读取当前屏幕实际渲染的文本含回滚缓冲与getOutput()的区别在于它反映的是用户此刻看到的内容而不是包含 Ink TUI 重绘重复内容的原始字节流见 terminal-capture.ts。十、与 PR Review 的集成该工具常用于 PR 评审期间的视觉验证当评审涉及 CLI 输出改动、测试斜杠命令/about、/context、/auth、/export、生成视觉文档或提到终端截图 / CLI 测试 / 视觉测试 / terminal-capture时即可启用本技能驱动场景运行把截图作为评审依据。从 motivation.md 的定位看terminal-capture 填补了测试体系的最后一块拼图┌─────────────────────────────────────┐ │ 既有测试体系 │ ├─────────────────────────────────────┤ │ 单元测试 (Vitest) │ ← 函数/组件级 │ 文本快照 (ink-testing-lib) │ ← ANSI 字符串对比 │ 集成测试 (TestRig/SDK) │ ← E2E 功能 │ Web Shell 回归 (Playwright) │ ← 浏览器 UI 场景 ├─────────────────────────────────────┤ │ terminal-capture │ ← 终端 UI 视觉层 │ (xterm.js Playwright) │ 填补空白 └─────────────────────────────────────┘该文档还列出了后续方向接入 PlaywrighttoHaveScreenshot()做像素级基线对比实现 CI 视觉回归驱动 Agent 自动切分支 → 构建 → 截图 → 附到评审评论与 Web Shell 视觉测试互补一个覆盖浏览器 UI一个覆盖 CLI 终端 UI。十一、常见问题排查现象原因解决方案Playwright 报错browser not found浏览器未安装npx playwright install chromium仅限本地开发CI verify 环境中出现此错误说明预装步骤失败应上报而不是自行安装截图空白进程启动缓慢或构建失败检查构建是否成功以及spawn命令是否正确PTY 相关错误node-pty 原生模块未编译npm rebuild node-pty截图输出不稳定终端输出尚未完全渲染为场景增加等待时间如sleep或增大idle稳定窗口十二、完整 ScenarioConfig 类型参考interface FlowStep { type?: string; // 输入文本 key?: string | string[]; // 按键可传 ANSI 转义序列 capture?: string; // 视口截图文件名 captureFull?: string; // 完整回滚缓冲截图文件名 sleep?: number; // 执行本步骤前的固定等待毫秒 streaming?: { delayMs?: number; // 首次捕获前延迟默认 0 intervalMs: number; // 捕获间隔毫秒 count: number; // 最大捕获帧数 gif?: boolean; // 生成动画 GIF默认 true }; } interface ScenarioConfig { name: string; // 场景名同时作为截图子目录名 spawn: string[]; // 启动命令如 [node, dist/cli.js, --yolo] flow: FlowStep[]; // 交互步骤 terminal?: { cols?: number; // 列数默认 100 rows?: number; // 行数默认 28 theme?: string; // 主题dracula|one-dark|github-dark|monokai|night-owl chrome?: boolean; // macOS 窗口装饰默认 true title?: string; // 窗口标题默认 Terminal fontSize?: number; // 字号 cwd?: string; // 工作目录相对配置文件 }; outputDir?: string; // 截图输出目录相对配置文件 gif?: boolean; // 是否生成动画 GIF默认 true }十三、小结terminal-capture 以TypeScript 配置驱动 WYSIWYG 渲染为核心设计配置层只需声明type输入与key按键两类动作runner 自动处理 CLI 就绪等待、斜杠命令自动补全干扰、输入前后截图、末步全长度截图、streaming 连续帧与 GIF 生成引擎层则用 node-pty 保证真实终端语义、用 xterm.js 保证像素级渲染、用 Playwright 保证跨平台截图一致性。它既是 qwen-code CLI 视觉回归的利器也可以作为任何终端程序截图自动化方案的参考实现。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价