chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:39:17 +08:00
commit 4ed4e9ff99
1368 changed files with 334957 additions and 0 deletions
@@ -0,0 +1,41 @@
# Vision UI reproduction
## Goal
Use the sandbox `view_image` tool to inspect a reference app screenshot, then reproduce the visible screen as a static HTML/CSS artifact. This is a narrow UI repro target for vision and screenshot-debugging; it is not a web-app scaffold.
This demo is intentionally file-only: no FastAPI, no exposed port, and no local browser server. The agent calls `view_image`, lazy-loads the `playwright` skill, writes the site under `output/site/`, captures browser screenshots for visual revision, and the host copies the generated site plus the visual-review artifacts back to this example's `output/` directory.
## Setup
Run the Unix-local example from the repository root:
```bash
uv run python examples/sandbox/tutorials/vision_website_clone/main.py
```
To run the same manifest in Docker, build the shared tutorial image once and pass
`--docker`:
```bash
docker build -t sandbox-tutorials:latest -f examples/sandbox/tutorials/Dockerfile .
uv run python examples/sandbox/tutorials/vision_website_clone/main.py --docker
```
## Expected artifact
- `output/index.html`
- `output/styles.css`
- `output/screenshots/draft-1.png`
- `output/screenshots/draft-2.png`
- `output/visual-notes.md`
Open `output/index.html` locally after the run to inspect the generated clone. Open the copied draft screenshots to inspect the agent's visual-debug loop.
## Demo shape
- Inputs: one checked-in PNG reference screenshot mounted under `reference/`.
- Runtime primitives: sandbox-local shell/edit tools, `view_image`, and the lazy-loaded `playwright` skill.
- Required vision call: `view_image("reference/reference-site.png")`.
- Required debug loop: capture `output/screenshots/draft-1.png`, view it with `view_image`, revise, then repeat with `output/screenshots/draft-2.png`.
- Artifact path: the sandbox agent writes `output/site/`, `output/screenshots/`, and `output/visual-notes.md`; `main.py` copies the site files and review artifacts to this example's `output/`.
@@ -0,0 +1 @@
@@ -0,0 +1,253 @@
"""
Clone a reference app screenshot as static HTML/CSS with the sandbox filesystem tools.
"""
from __future__ import annotations
import argparse
import asyncio
import os
import sys
from pathlib import Path
from textwrap import dedent
from agents import ModelSettings, Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig, WorkspaceReadNotFoundError
from agents.sandbox.capabilities import (
Filesystem,
LocalDirLazySkillSource,
Shell,
Skills,
)
from agents.sandbox.entries import Dir, File, LocalDir, LocalFile
from agents.sandbox.session import BaseSandboxSession
if __package__ is None or __package__ == "":
sys.path.insert(0, str(Path(__file__).resolve().parents[4]))
from examples.sandbox.tutorials.misc import (
DEFAULT_SANDBOX_IMAGE,
console,
create_sandbox_client_and_session,
load_env_defaults,
print_event,
)
DEMO_DIR = Path(__file__).resolve().parent
REFERENCE_IMAGE = DEMO_DIR / "reference-site.png"
SKILLS_SOURCE_DIR = DEMO_DIR / "skills"
SANDBOX_SITE_DIR = Path("output") / "site"
REMOTE_REVIEW_ARTIFACTS = (
Path("output") / "screenshots" / "draft-1.png",
Path("output") / "screenshots" / "draft-2.png",
Path("output") / "visual-notes.md",
)
DEFAULT_MODEL = "gpt-5.4-mini"
DEFAULT_QUESTION = (
"Inspect the reference screenshot and build a static HTML/CSS reproduction of the "
"screen. Write output/site/index.html and output/site/styles.css, then capture "
"browser screenshots, inspect them, and revise the site."
)
AGENTS_MD = dedent(
"""\
# Vision UI Reproduction Instructions
Create a static HTML/CSS reproduction of the provided reference screenshot.
Build only the single screen shown in the reference.
## Required workflow (must do)
- First call `view_image` on `reference/reference-site.png`.
- Before writing code, write `output/visual-notes.md` with brief layout + typography notes.
- Write the site to `output/site/index.html` and `output/site/styles.css`.
- Before taking screenshots, call `load_skill("playwright")` and read `skills/playwright/SKILL.md`.
- Capture `output/screenshots/draft-1.png`, inspect it, revise, then capture `output/screenshots/draft-2.png`.
- Do not finish without the screenshots.
"""
)
def default_output_dir() -> Path:
"""Return the local directory for copied example artifacts."""
artifacts_dir = os.environ.get("EXAMPLES_ARTIFACTS_DIR")
if artifacts_dir:
return Path(artifacts_dir)
return DEMO_DIR / "output"
def build_manifest() -> Manifest:
return Manifest(
entries={
"AGENTS.md": File(content=AGENTS_MD.encode("utf-8")),
"reference": Dir(
children={
"reference-site.png": LocalFile(src=REFERENCE_IMAGE),
},
description="Reference app screenshot to clone.",
),
"output": Dir(description="Write generated website files here."),
}
)
def build_agent(model: str) -> SandboxAgent:
return SandboxAgent(
name="Vision Website Clone Builder",
model=model,
instructions=AGENTS_MD,
capabilities=[
Shell(),
Filesystem(),
Skills(
lazy_from=LocalDirLazySkillSource(
# This is a host path read by the SDK process.
# Requested skills are copied into `skills_path` in the sandbox.
source=LocalDir(src=SKILLS_SOURCE_DIR),
),
skills_path="skills",
),
],
model_settings=ModelSettings(tool_choice="required"),
)
async def copy_site_output_dir(
*,
session: BaseSandboxSession,
output_dir: Path,
) -> list[Path]:
output_dir.mkdir(parents=True, exist_ok=True)
remote_site_dir = session.normalize_path(SANDBOX_SITE_DIR)
pending_dirs = [remote_site_dir]
copied_files: list[Path] = []
while pending_dirs:
current_dir = pending_dirs.pop()
for entry in await session.ls(current_dir):
entry_path = Path(entry.path)
if entry.is_dir():
pending_dirs.append(entry_path)
continue
relative_path = entry_path.relative_to(remote_site_dir)
local_path = output_dir / relative_path
local_path.parent.mkdir(parents=True, exist_ok=True)
handle = await session.read(entry_path)
try:
payload = handle.read()
finally:
handle.close()
if isinstance(payload, str):
local_path.write_text(payload, encoding="utf-8")
else:
local_path.write_bytes(bytes(payload))
copied_files.append(local_path)
return copied_files
async def copy_review_artifacts(
*,
session: BaseSandboxSession,
output_dir: Path,
remote_artifacts: tuple[Path, ...] = REMOTE_REVIEW_ARTIFACTS,
) -> list[Path]:
output_dir.mkdir(parents=True, exist_ok=True)
copied_files: list[Path] = []
for remote_artifact in remote_artifacts:
remote_path = session.normalize_path(remote_artifact)
relative_artifact = remote_artifact.relative_to(Path("output"))
local_path = output_dir / relative_artifact
local_path.parent.mkdir(parents=True, exist_ok=True)
try:
handle = await session.read(remote_path)
except WorkspaceReadNotFoundError:
continue
try:
payload = handle.read()
finally:
handle.close()
if isinstance(payload, str):
local_path.write_text(payload, encoding="utf-8")
else:
local_path.write_bytes(bytes(payload))
copied_files.append(local_path)
return copied_files
async def main(model: str, question: str, use_docker: bool, image: str, output_dir: Path) -> None:
client, sandbox = await create_sandbox_client_and_session(
manifest=build_manifest(),
use_docker=use_docker,
image=image,
)
try:
async with sandbox:
result = Runner.run_streamed(
build_agent(model),
[{"role": "user", "content": question}],
max_turns=30,
run_config=RunConfig(
sandbox=SandboxRunConfig(session=sandbox),
tracing_disabled=True,
workflow_name="Vision Website Clone example",
),
)
async for event in result.stream_events():
print_event(event)
if result.final_output is None:
raise RuntimeError("Vision Website Clone Builder returned no final message.")
print_event(str(result.final_output).strip())
copied_files = await copy_site_output_dir(session=sandbox, output_dir=output_dir)
copied_review_files = await copy_review_artifacts(
session=sandbox,
output_dir=output_dir,
)
finally:
await client.delete(sandbox)
expected_files = {output_dir / "index.html", output_dir / "styles.css"}
if not expected_files <= set(copied_files):
raise RuntimeError(
"Vision Website Clone Builder must write output/site/index.html and "
"output/site/styles.css."
)
console.print(f"[green]Copied static site to {output_dir / 'index.html'}[/green]")
for path in copied_review_files:
console.print(f"[green]Copied review artifact to {path}[/green]")
if __name__ == "__main__":
load_env_defaults(DEMO_DIR / ".env")
parser = argparse.ArgumentParser()
parser.add_argument("--model", default=DEFAULT_MODEL, help="Model name to use.")
parser.add_argument("--question", default=DEFAULT_QUESTION, help="Prompt to send to the agent.")
parser.add_argument(
"--docker",
action="store_true",
help="Run this example in Docker instead of Unix-local.",
)
parser.add_argument(
"--image",
default=DEFAULT_SANDBOX_IMAGE,
help="Docker image to use when --docker is set.",
)
parser.add_argument(
"--output-dir",
type=Path,
default=default_output_dir(),
help="Directory for copied website files.",
)
args = parser.parse_args()
asyncio.run(main(args.model, args.question, args.docker, args.image, args.output_dir))
Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

@@ -0,0 +1,23 @@
---
name: "playwright"
description: "Use when the task requires capturing or automating a real browser from the terminal."
---
# Playwright
Use Playwright to capture the static site directly. Do not start a server for this example.
```sh
mkdir -p output/screenshots output/playwright/.tmp
export TMPDIR="$PWD/output/playwright/.tmp"
export TEMP="$TMPDIR"
export TMP="$TMPDIR"
npx --yes --package playwright@1.50.0 playwright install chromium
npx --yes --package playwright@1.50.0 playwright screenshot \
--browser=chromium \
--viewport-size=2048,1152 \
"file://$PWD/output/site/index.html" \
output/screenshots/draft-1.png
```
Change the final path to `output/screenshots/draft-2.png` for the second pass.