# Copyright 2026 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import base64 import os from pathlib import Path import subprocess def generate_showcase(lang="zh", source_image=None): assets_dir = Path(__file__).resolve().parent if source_image and os.path.exists(source_image): image_path = Path(source_image) else: # Default lookup order candidates = [ assets_dir / "ui_raw.png", assets_dir.parent.parent / "image.png", assets_dir / "artemis-ui-showcase.png", ] image_path = next((p for p in candidates if p.exists()), None) if lang == "zh": output_path = assets_dir / "artemis-ui-showcase.png" else: output_path = assets_dir / "artemis-ui-showcase-en.png" if not image_path or not image_path.exists(): print(f"Skipping showcase generation: source image not found for {lang}") return with open(image_path, "rb") as f: img_b64 = base64.b64encode(f.read()).decode("utf-8") if lang == "zh": tag1_title, tag1_desc = "顶栏视图切换", "主页 / 工作区" tag2_title, tag2_desc = "运行模式与录屏回放", "Pro / Flash · 回放" tag3_title = "实时推理流与操作轨迹" tag4_title, tag4_desc = "自然语言下发胶囊", "一句话驱动真机" tag5_title, tag5_desc = "任务队列看板", "状态流转 · 历史回溯" card3_title = "③ 实时感知推理流解析" card3_tag = "LIVE STREAM" row1_title, row1_desc = ( "动作感知与定位", "捕获点击、滑动与定位坐标(如 [[381, 430]])", ) row2_title, row2_desc = ( "资源开销统计", "记录每步耗时(Worked for 13s)与 Token 消耗", ) row3_title, row3_desc = ( "挂载 Outputter 结构化输出", "任务结束时自动调起 Outputter 进行全轨迹证据核验与提取 (output.md / JSON)", ) tag1_pos = "top: 20px; left: 295px;" tag2_pos = "top: 76px; left: 660px;" tag3_pos = "top: 68px; left: 24px;" tag4_pos = "top: 494px; left: 360px;" tag5_pos = "top: 70px; left: 1075px;" card3_width = "545px" else: tag1_title, tag1_desc = "View Switcher", "Home / Workspace" tag2_title, tag2_desc = "Model & Replay", "Pro / Flash · Replay" tag3_title = "Live Agent Execution Stream" tag4_title, tag4_desc = "Prompt Dock", "Autonomous Execution" tag5_title, tag5_desc = "Task Queue & Dashboard", "Lifecycle & History" card3_title = "③ Live Agent Reasoning & Stream" card3_tag = "LIVE STREAM" row1_title, row1_desc = ( "Action Grounding & Perception", "Real-time gestures, taps & coordinates (e.g. [[381, 430]])", ) row2_title, row2_desc = ( "Latency & Token Metrics", "Per-step duration tracking (Worked for 13s) & token cost", ) row3_title, row3_desc = ( "Mounted Outputter Synthesis", "Post-execution trace verification & structured data extraction into output.md / JSON", ) tag1_pos = "top: 20px; left: 295px;" tag2_pos = "top: 76px; left: 660px;" tag3_pos = "top: 68px; left: 24px;" tag4_pos = "top: 494px; left: 350px;" tag5_pos = "top: 70px; left: 1075px;" card3_width = "550px" html_content = f"""
Artemis Console
1 {tag1_title} {tag1_desc}
2 {tag2_title} {tag2_desc}
3 {tag3_title}
⚡
{card3_title}
{card3_tag}
{row1_title}: {row1_desc}
{row2_title}: {row2_desc}
{row3_title}: {row3_desc}
4 {tag4_title} {tag4_desc}
5 {tag5_title} {tag5_desc}
""" temp_html = f"/tmp/ui_showcase_render_{lang}.html" with open(temp_html, "w", encoding="utf-8") as f: f.write(html_content) chrome_candidates = [ "google-chrome", "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "/Applications/Chromium.app/Contents/MacOS/Chromium", "chromium", "chromium-browser", ] chrome_bin = next( ( c for c in chrome_candidates if os.path.exists(c) or subprocess.run(["which", c], capture_output=True).returncode == 0 ), "google-chrome", ) cmd = [ chrome_bin, "--headless=new", "--disable-gpu", "--virtual-time-budget=2000", "--window-size=1545,618", "--device-scale-factor=2", "--hide-scrollbars", f"--screenshot={output_path}", f"file://{temp_html}", ] res = subprocess.run(cmd, capture_output=True, text=True) if os.path.exists(output_path): print(f"Successfully generated {output_path} ({os.path.getsize(output_path)} bytes)") else: print(f"Error rendering: {res.stderr}") if __name__ == "__main__": generate_showcase("zh") generate_showcase("en")