본문으로 건너뛰기
cccskills
무료GitHub에 공개

verify

Build and run computer-use-demo in Docker, then use Playwright to test its Streamlit interface without opening a visible browser. Save conversation transcripts, API exchanges, and screenshots to inspect behavior after changes.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Build the computer-use-demo image and drive the Streamlit UI headlessly to verify changes end-to-end.

연동 도구Playwright
설치 방법 보기

이럴 때 유용합니다

  • Checking the interface after changing computer-use-demo
  • Testing combinations of models and tool versions
  • Checking Thinking settings and model changes during a session
  • Saving conversations, API exchanges, and screenshots for review

포함된 파일(1)

  • SKILL.md6.1 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Verifying changes to this demo

The surface is the Streamlit app inside the container. Build the image from this directory, run it, and drive the UI with Playwright. pytest, ruff, and pyright are CI's job, not evidence.

Build and run

docker build . -t computer-use-demo:verify
docker rm -f cu-verify 2>/dev/null
docker run -d --name cu-verify \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY -e WIDTH=1024 -e HEIGHT=768 \
  -p 18501:8501 -p 18080:8080 -p 16080:6080 computer-use-demo:verify
until curl -sf localhost:18501/_stcore/health >/dev/null; do sleep 1; done

A cold build takes several minutes (apt, LibreOffice, a pyenv Python compile). The requirements.txt layer is cached separately, so source-only changes rebuild in seconds.

To iterate without rebuilding, copy sources over the baked copy before the first browser session compiles the script:

docker cp computer_use_demo/. cu-verify:/home/computeruse/computer_use_demo/

Streamlit's file watcher does not notice docker cp replacements once a session has run. Recreate the container instead of docker restart, which fails on a stale X lock (tint2: could not open display).

Drive the UI

Install Playwright in any venv (pip install playwright && python -m playwright install chromium) and run the script below. It sets the model, picks a tool version, optionally sets the thinking mode, sends a prompt, waits for the loop to go idle, then dumps the chat transcript and every HTTP exchange (request headers and JSON, response JSON) with auth headers redacted.

THINKING=Adaptive python drive.py 18501 claude-sonnet-5 computer_toolset_20260801 \
  "Take a screenshot, then zoom in on the taskbar and list the icons." out/ 240

Pass - for model or tool version to keep the default. THINKING=Off|Adaptive|Extended clicks that radio. TOKEN_EFFICIENT=1 ticks the beta checkbox.

What to read afterwards:

  • out/chat.txt: the rendered conversation, including Tool Use: <name> lines and any error box with its traceback.
  • out/exchange-NN.txt: one file per API round trip. Check tools, anthropic-beta, and the tool_use / tool_result blocks here rather than trusting the chat rendering.
  • out/02-chat.png, out/04-http-logs-expanded.png: full-page screenshots.

Useful probes: an older model with a newer tool version (expect a clean 400 in the error box, not a crash), toggling Thinking to Off before the first message, and switching models mid-session.

"""drive.py <port> <model|-> <tool_version|-> <prompt> <outdir> [wait_secs]"""

import os
import re
import sys
import time
from pathlib import Path

from playwright.sync_api import sync_playwright

port, model, tool_version, prompt, outdir = sys.argv[1:6]
wait_secs = int(sys.argv[6]) if len(sys.argv) > 6 else 180
out = Path(outdir)
out.mkdir(parents=True, exist_ok=True)
MAIN = "[data-testid='stMain'], section.main, [data-testid='stAppViewContainer']"


def log(msg: str) -> None:
    print(f"[{time.strftime('%H:%M:%S')}] {msg}", flush=True)


with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page(viewport={"width": 1400, "height": 1600})
    page.goto(f"http://localhost:{port}", wait_until="networkidle", timeout=120_000)
    page.wait_for_selector("text=Tool Versions", timeout=120_000)
    sidebar = page.locator("[data-testid='stSidebar']")

    model_input = page.get_by_label("Model", exact=True)
    if model != "-":
        model_input.fill(model)
        model_input.press("Enter")  # commits the text_input and fires on_change
        time.sleep(2)
    if tool_version != "-":
        sidebar.get_by_text(tool_version, exact=True).click()
        time.sleep(2)
    if thinking := os.environ.get("THINKING"):
        sidebar.get_by_text(thinking, exact=True).click()
        time.sleep(2)
    if os.environ.get("TOKEN_EFFICIENT"):
        sidebar.get_by_text("Enable token-efficient tools beta", exact=True).click()
        time.sleep(2)
    log(f"model={model_input.input_value()!r} tools={tool_version} thinking={thinking}")
    page.screenshot(path=str(out / "01-sidebar.png"), full_page=True)

    chat = page.locator("textarea[data-testid='stChatInputTextArea']")
    chat.fill(prompt)
    chat.press("Enter")
    log("prompt sent")

    # The status widget is present while the script (and so the sampling loop) runs.
    deadline = time.time() + wait_secs
    time.sleep(5)
    while time.time() < deadline:
        running = page.locator("[data-testid='stStatusWidget']").count() > 0
        msgs = page.locator("[data-testid='stChatMessage']").count()
        log(f"running={running} chat_messages={msgs}")
        if not running and msgs >= 2:
            time.sleep(4)
            if page.locator("[data-testid='stStatusWidget']").count() == 0:
                break
        time.sleep(5)

    page.screenshot(path=str(out / "02-chat.png"), full_page=True)
    (out / "chat.txt").write_text(page.locator(MAIN).first.inner_text(timeout=10_000))

    page.get_by_role("tab", name="HTTP Exchange Logs").click()
    time.sleep(3)
    expanders = page.locator("[data-testid='stExpander']")
    for i in range(expanders.count()):
        exp = expanders.nth(i)
        exp.locator("summary").click()
        time.sleep(1.5)
        txt = exp.inner_text(timeout=15_000)
        txt = re.sub(r"(?im)^(`?)(authorization|x-api-key): .*$", r"\1\2: [REDACTED]", txt)
        (out / f"exchange-{i + 1:02d}.txt").write_text(txt)
    page.screenshot(path=str(out / "04-http-logs-expanded.png"), full_page=True)
    log(f"captured {expanders.count()} exchanges")
    browser.close()

Gotchas

  • The sidebar requires a non-empty API key for the Anthropic provider before it renders the chat. ANTHROPIC_API_KEY in the container env pre-fills it.
  • Each Playwright run is a fresh Streamlit session, so the HTTP exchange log only contains that run's requests. Capture it in the same run.
  • If PYTEST_DISABLE_PLUGIN_AUTOLOAD is set in your shell, pytest silently skips every async test. Run with -p pytest_asyncio or unset it.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

first-run

무료

Guide a first computer-use agent run from environment checks to a browser-only task and a viewer of the run history. Explain each stage so users can understand the output and review screenshots afterward.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Checking the environment before a first agent run
  • Trying browser automation without moving the mouse or keyboard
  • Reviewing screenshots and prompts from a completed run
anthropics/claude-quickstarts1.9만2026년 10월 9일 업데이트

verify

무료

Verify changes to the copilot-kit-ag-ui demo by building and running its server. Check API routing, cross-origin access settings, and build configuration, then use real credentials to confirm that a requested chart appears.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Checking server routing after changes
  • Testing API wiring without real Anthropic credentials
  • Checking which website origins can access the server
anthropics/claude-quickstarts1.9만2026년 10월 9일 업데이트

anthropics의 스킬 모두 보기

이 스킬의 문제 신고