Files
Claude-Code-Workflow/.claude/commands/workflow/ui-design/capture.md
catlog22 2fcd44e856 feat: Add imitate-auto-v3 workflow for high-speed multi-page UI replication
- Introduced a new workflow named `imitate-auto-v3` that allows for batch screenshot capture and optional token refinement.
- Implemented a comprehensive 5-phase execution protocol to handle initialization, screenshot capture, style extraction, token processing, and UI generation.
- Added support for multiple target URLs through a `--url-map` parameter, enhancing flexibility in design replication.
- Included optional parameters for session management and token refinement, allowing users to customize their workflow experience.
- Enhanced error handling and reporting throughout the workflow to ensure clarity and ease of debugging.
- Deprecated the previous `imitate-auto.md` workflow in favor of this more robust version.
2025-10-11 11:42:33 +08:00

534 lines
21 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
---
name: capture
description: Batch screenshot capture for UI design workflows using MCP or local fallback
usage: /workflow:ui-design:capture --url-map "<map>" [--base-path <path>] [--session <id>]
examples:
- /workflow:ui-design:capture --url-map "home:https://linear.app, pricing:https://linear.app/pricing"
- /workflow:ui-design:capture --session WFS-auth --url-map "dashboard:https://app.com/dash"
- /workflow:ui-design:capture --base-path ".workflow/.design/run-20250110" --url-map "hero:https://example.com#hero"
allowed-tools: TodoWrite(*), Read(*), Write(*), Bash(*), Glob(*), mcp__browser__screenshot(*)
---
# Batch Screenshot Capture Command
## Overview
独立的批量截图命令支持MCP优先策略和多级降级机制。可被其他工作流复用。
## Core Philosophy
- **MCP优先**优先使用mcp__browser__screenshot如果可用
- **智能降级**MCP失败 → Playwright → Chrome → 手动上传
- **批量处理**一次处理多个URL并行截图
- **结构化输出**按target_name组织截图文件
- **错误容忍**:部分失败不阻塞整体流程
## Execution Protocol
### Phase 0: 初始化和路径解析
```bash
# 确定base path
IF --base-path:
base_path = {provided_base_path}
ELSE IF --session:
# 查找session最新design run
session_design_dirs = Glob(".workflow/WFS-{session}/design-*")
IF session_design_dirs:
base_path = most_recent(session_design_dirs)
ELSE:
# 创建新的design run
run_id = "run-$(date +%Y%m%d-%H%M%S)"
base_path = ".workflow/WFS-{session}/design-{run_id}"
ELSE:
# Standalone模式
run_id = "run-$(date +%Y%m%d-%H%M%S)"
base_path = ".workflow/.design/{run_id}"
# 创建截图目录
screenshot_dir = "{base_path}/screenshots"
Bash(mkdir -p "{screenshot_dir}")
REPORT: "📸 Batch Screenshot Capture"
REPORT: " Output: {screenshot_dir}/"
# 解析url-map
url_map_string = {--url-map} # "home:https://a.com, pricing:https://a.com/pricing"
# 解析逻辑
url_entries = []
FOR pair IN split(url_map_string, ","):
pair = pair.strip()
IF ":" NOT IN pair:
ERROR: "Invalid url-map format: '{pair}'"
ERROR: "Expected format: 'target:url'"
ERROR: "Example: 'home:https://example.com, pricing:https://example.com/pricing'"
EXIT 1
target, url = pair.split(":", 1)
target = target.strip().lower().replace(" ", "-")
url = url.strip()
# 验证target名称
IF NOT regex_match(target, r"^[a-z0-9][a-z0-9_-]*$"):
ERROR: "Invalid target name: '{target}'"
ERROR: "Target names must start with alphanumeric and contain only [a-z0-9_-]"
EXIT 1
# 验证URL格式
IF NOT (url.startswith("http://") OR url.startswith("https://")):
WARN: "URL '{url}' does not start with http:// or https://"
WARN: "Prepending https:// automatically"
url = f"https://{url}"
url_entries.append({"target": target, "url": url})
VALIDATE: len(url_entries) > 0, "url-map must contain at least one target:url pair"
total_targets = len(url_entries)
REPORT: " Targets: {total_targets}"
FOR entry IN url_entries:
REPORT: " • {entry.target}: {entry.url}"
TodoWrite({todos: [
{content: "Initialize and parse url-map", status: "completed", activeForm: "Initializing"},
{content: "MCP batch screenshot capture", status: "pending", activeForm: "Capturing via MCP"},
{content: "Local tool fallback (if needed)", status: "pending", activeForm: "Local fallback"},
{content: "Verify and summarize results", status: "pending", activeForm: "Verifying"}
]})
```
### Phase 1: MCP批量截图优先策略
```bash
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "🚀 Phase 1: MCP Batch Screenshot"
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# 检测MCP工具可用性
mcp_available = check_tool_availability("mcp__browser__screenshot")
success_captures = []
failed_captures = []
IF mcp_available:
REPORT: "✓ MCP browser screenshot tool detected"
# 构建MCP调用参数
urls = [entry.url for entry in url_entries]
file_prefixes = [entry.target for entry in url_entries]
TRY:
# MCP批量截图调用
REPORT: " Calling MCP for {len(urls)} URLs..."
result = mcp__browser__screenshot({
urls: urls,
output_dir: screenshot_dir,
file_prefix: file_prefixes,
full_page: true,
viewport: "1920,1080",
timeout: 30000
})
# 处理MCP返回结果
success_count = len(result.success)
failed_count = len(result.failed)
REPORT: " MCP capture complete: {success_count} succeeded, {failed_count} failed"
FOR item IN result.success:
success_captures.append(item.target)
REPORT: " ✓ {item.target}.png"
FOR item IN result.failed:
failed_captures.append({"target": item.target, "url": item.url, "error": item.error})
REPORT: " ✗ {item.target}: {item.error}"
# 如果有部分失败标记需要fallback
IF failed_count > 0:
failed_targets = [item.target for item in result.failed]
REPORT: " → {failed_count} failed, proceeding to local fallback..."
TodoWrite(mark_completed: "MCP batch screenshot capture", mark_in_progress: "Local tool fallback")
GOTO Phase 2 (fallback_targets = failed_targets)
ELSE:
REPORT: "✅ All screenshots captured via MCP"
TodoWrite(mark_completed: "MCP batch screenshot capture", mark_completed: "Local tool fallback", mark_in_progress: "Verify results")
GOTO Phase 3 (verification)
CATCH error:
REPORT: "⚠️ MCP call failed: {error}"
REPORT: " Falling back to local tools for all targets"
failed_targets = [entry.target for entry in url_entries]
TodoWrite(mark_completed: "MCP batch screenshot capture", mark_in_progress: "Local tool fallback")
GOTO Phase 2 (fallback_targets = failed_targets)
ELSE:
REPORT: " MCP browser screenshot tool not available"
REPORT: " Using local tool fallback strategy"
failed_targets = [entry.target for entry in url_entries]
TodoWrite(mark_completed: "MCP batch screenshot capture", mark_in_progress: "Local tool fallback")
GOTO Phase 2 (fallback_targets = failed_targets)
```
### Phase 2: Local工具降级Playwright → Chrome
```bash
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "🔧 Phase 2: Local Tool Fallback"
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# 仅处理Phase 1失败的targets
targets_to_capture = [entry for entry in url_entries if entry.target IN fallback_targets]
REPORT: "Processing {len(targets_to_capture)} target(s) with local tools..."
# 检测本地工具(检查可执行文件,不触发安装)
playwright_path = Bash(which playwright 2>/dev/null || echo "")
chrome_path = Bash(which google-chrome 2>/dev/null || which chrome 2>/dev/null || which chromium 2>/dev/null || echo "")
playwright_available = playwright_path != ""
chrome_available = chrome_path != ""
REPORT: " Tool availability:"
REPORT: " Playwright: {playwright_available ? '✓ Available' : '✗ Not found'}"
REPORT: " Chrome: {chrome_available ? '✓ Available' : '✗ Not found'}"
local_success = []
local_failed = []
FOR entry IN targets_to_capture:
target = entry.target
url = entry.url
output_file = "{screenshot_dir}/{target}.png"
captured = false
method_used = null
# 尝试Playwright
IF playwright_available AND NOT captured:
TRY:
REPORT: " Trying Playwright for '{target}'..."
Bash({playwright_path} screenshot "{url}" "{output_file}" --full-page --timeout 30000)
IF exists(output_file) AND file_size(output_file) > 1000: # >1KB验证有效
captured = true
method_used = "Playwright"
local_success.append(target)
success_captures.append(target)
REPORT: " ✓ {target}.png (Playwright, {file_size(output_file)/1024:.1f} KB)"
CATCH error:
REPORT: " ⚠️ Playwright failed: {error}"
# 尝试Chrome
IF chrome_available AND NOT captured:
TRY:
REPORT: " Trying Chrome for '{target}'..."
Bash({chrome_path} --headless --disable-gpu --screenshot="{output_file}" --window-size=1920,1080 "{url}")
IF exists(output_file) AND file_size(output_file) > 1000:
captured = true
method_used = "Chrome"
local_success.append(target)
success_captures.append(target)
REPORT: " ✓ {target}.png (Chrome, {file_size(output_file)/1024:.1f} KB)"
CATCH error:
REPORT: " ⚠️ Chrome failed: {error}"
# 标记彻底失败
IF NOT captured:
local_failed.append(entry)
failed_captures.append({"target": target, "url": url, "error": "All local tools failed"})
REPORT: " ✗ {target}: All tools failed"
REPORT: ""
REPORT: "Local fallback summary:"
REPORT: " Succeeded: {len(local_success)}/{len(targets_to_capture)}"
REPORT: " Failed: {len(local_failed)}/{len(targets_to_capture)}"
# 如果仍有失败,进入手动模式
IF len(local_failed) > 0:
TodoWrite(mark_completed: "Local tool fallback", mark_in_progress: "Manual upload mode")
GOTO Phase 2.5 (manual_upload)
ELSE:
TodoWrite(mark_completed: "Local tool fallback", mark_in_progress: "Verify results")
GOTO Phase 3 (verification)
```
### Phase 2.5: 手动上传降级
```bash
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "⚠️ Phase 2.5: Manual Screenshot Required"
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "Failed to auto-capture {len(local_failed)} target(s):"
REPORT: ""
FOR entry IN local_failed:
REPORT: " {entry.target}:"
REPORT: " URL: {entry.url}"
REPORT: " Save to: {screenshot_dir}/{entry.target}.png"
REPORT: ""
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "📋 Manual Steps:"
REPORT: " 1. Visit each URL above in your browser"
REPORT: " 2. Take full-page screenshot (Browser DevTools or extensions)"
REPORT: " 3. Save screenshot to specified path"
REPORT: " 4. Return here and choose an option"
REPORT: ""
REPORT: "Options:"
REPORT: " • Type 'ready' : I've uploaded screenshot(s), continue workflow"
REPORT: " • Type 'skip' : Skip failed screenshots, continue with available"
REPORT: " • Type 'abort' : Cancel entire capture workflow"
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
user_response = WAIT_FOR_USER_INPUT()
MATCH user_response.lower():
"ready" | "done" | "ok" | "continue":
# 验证手动上传的文件
manual_uploaded = []
REPORT: "🔍 Checking for manual screenshots..."
FOR entry IN local_failed:
expected_path = f"{screenshot_dir}/{entry.target}.png"
IF exists(expected_path) AND file_size(expected_path) > 1000:
manual_uploaded.append(entry.target)
success_captures.append(entry.target)
REPORT: " ✓ {entry.target}.png (manual, {file_size(expected_path)/1024:.1f} KB)"
ELSE:
REPORT: " ✗ {entry.target}.png not found or invalid"
IF len(manual_uploaded) > 0:
REPORT: "✅ Detected {len(manual_uploaded)} manual screenshot(s)"
# 移除已上传的targets from failed list
failed_captures = [f for f in failed_captures if f.target NOT IN manual_uploaded]
ELSE:
REPORT: "⚠️ No valid manual screenshots detected"
REPORT: " Proceeding with available screenshots only"
TodoWrite(mark_completed: "Manual upload mode", mark_in_progress: "Verify results")
GOTO Phase 3
"skip" | "s":
REPORT: "⏭️ Skipping {len(local_failed)} failed screenshot(s)"
REPORT: " Proceeding with {len(success_captures)} available screenshot(s)"
TodoWrite(mark_completed: "Manual upload mode", mark_in_progress: "Verify results")
GOTO Phase 3
"abort" | "cancel" | "exit":
ERROR: "Workflow aborted by user"
TodoWrite(mark_failed: "Manual upload mode")
EXIT 1
_:
REPORT: "⚠️ Invalid input '{user_response}', interpreting as 'skip'"
REPORT: " Proceeding with available screenshots"
TodoWrite(mark_completed: "Manual upload mode", mark_in_progress: "Verify results")
GOTO Phase 3
```
### Phase 3: 验证和总结
```bash
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
REPORT: "✅ Phase 3: Verification & Summary"
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# 扫描实际截图文件
captured_files = Glob("{screenshot_dir}/*.{png,jpg,jpeg,webp}")
captured_targets_actual = [extract_basename_without_ext(f) for f in captured_files]
# 与请求对比
total_requested = len(url_entries)
total_captured = len(captured_targets_actual)
missing_targets = [entry.target for entry in url_entries if entry.target NOT IN captured_targets_actual]
REPORT: "📊 Capture Summary:"
REPORT: " Total requested: {total_requested}"
REPORT: " Successfully captured: {total_captured}"
REPORT: " Success rate: {(total_captured / total_requested * 100):.1f}%"
IF missing_targets:
REPORT: ""
REPORT: "⚠️ Missing screenshots ({len(missing_targets)}):"
FOR target IN missing_targets:
REPORT: " • {target}"
ELSE:
REPORT: ""
REPORT: "✅ All requested screenshots captured!"
# 生成capture元数据
metadata = {
"timestamp": current_timestamp(),
"total_requested": total_requested,
"total_captured": total_captured,
"success_rate": round(total_captured / total_requested * 100, 2),
"screenshots": []
}
FOR entry IN url_entries:
target = entry.target
url = entry.url
is_captured = target IN captured_targets_actual
screenshot_info = {
"target": target,
"url": url,
"captured": is_captured
}
IF is_captured:
file_path = f"{screenshot_dir}/{target}.png"
screenshot_info["path"] = file_path
screenshot_info["size_kb"] = round(file_size(file_path) / 1024, 2)
# 查找捕获方法
IF target IN [s.target for s in result.success if mcp_available]:
screenshot_info["method"] = "MCP"
ELSE IF target IN local_success:
screenshot_info["method"] = "Local (Playwright/Chrome)"
ELSE:
screenshot_info["method"] = "Manual"
ELSE:
screenshot_info["path"] = null
screenshot_info["error"] = next((f.error for f in failed_captures if f.target == target), "Unknown error")
metadata.screenshots.append(screenshot_info)
# 写入元数据文件
metadata_path = "{screenshot_dir}/capture-metadata.json"
Write(metadata_path, JSON.stringify(metadata, null, 2))
REPORT: ""
REPORT: "📁 Output:"
REPORT: " Directory: {screenshot_dir}/"
REPORT: " Metadata: capture-metadata.json"
TodoWrite(mark_completed: "Verify and summarize results")
```
### Phase 4: 完成
```javascript
TodoWrite({todos: [
{content: "Initialize and parse url-map", status: "completed", activeForm: "Initializing"},
{content: "MCP batch screenshot capture", status: "completed", activeForm: "MCP capture"},
{content: "Local tool fallback (if needed)", status: "completed", activeForm: "Local fallback"},
{content: "Verify and summarize results", status: "completed", activeForm: "Verifying"}
]});
```
**Completion Message**:
```
✅ Batch Screenshot Capture Complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Capture Summary
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Requested: {total_requested} screenshots
Captured: {total_captured} screenshots
Success Rate: {success_rate}%
Capture Methods:
{IF mcp_available AND mcp_success_count > 0:
• MCP: {mcp_success_count} screenshot(s)
}
{IF local_success_count > 0:
• Local tools: {local_success_count} screenshot(s)
}
{IF manual_count > 0:
• Manual upload: {manual_count} screenshot(s)
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📂 Output Structure
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{screenshot_dir}/
├── {target1}.png ({size1} KB)
├── {target2}.png ({size2} KB)
{FOR each captured screenshot}
└── capture-metadata.json
{IF missing_targets:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ Missing Screenshots ({len(missing_targets)})
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{FOR target IN missing_targets:
• {target} - {get_error_for_target(target)}
}
💡 Tip: Re-run capture command for failed targets:
/workflow:ui-design:capture --base-path "{base_path}" --url-map "{build_failed_url_map()}"
}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚀 Next Steps
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Extract design style from captured screenshots:
/workflow:ui-design:extract --base-path "{base_path}" --images "{screenshot_dir}/*.png" --mode imitate --variants 1
2. Or continue with full imitate workflow:
(capture is automatically called by /workflow:ui-design:imitate-auto-v3)
```
## MCP API设计假设实现
```typescript
// 假设的MCP工具签名
mcp__browser__screenshot({
urls: string[], // 要截图的URL列表
output_dir: string, // 输出目录
file_prefix: string[], // 文件名前缀列表对应urls
full_page?: boolean, // 全页截图默认true
viewport?: string, // 视口大小(默认"1920,1080"
timeout?: number // 每个URL的超时默认30000ms
}): {
success: Array<{
target: string, // file_prefix对应的target名称
url: string, // 成功截图的URL
path: string // 生成的截图文件路径
}>,
failed: Array<{
target: string, // file_prefix对应的target名称
url: string, // 失败的URL
error: string // 错误信息
}>
}
```
**注意事项**
- 如果`mcp__browser__screenshot`工具不存在,命令会自动降级到本地工具
- MCP工具应该支持并行截图以提高性能
- 返回结果应该区分成功和失败,允许部分失败
## Error Handling
- **无效url-map格式**:清晰的错误信息+格式示例
- **MCP不可用**静默降级到本地工具Playwright/Chrome
- **所有自动工具失败**:进入交互式手动上传模式
- **部分失败**:记录成功项,继续流程(非阻塞),提供重试建议
## Key Features
1. **MCP优先策略** - 使用托管工具提高可靠性和一致性
2. **多级降级机制** - MCP → Playwright → Chrome → 手动上传
3. **批量并行处理** - 一次处理多个URLMCP支持并行
4. **错误容忍设计** - 部分失败不阻塞整体流程
5. **高度可复用** - 可被imitate-auto-v3、explore-auto等工作流调用
6. **结构化输出** - capture-metadata.json记录完整捕获信息
7. **交互式降级** - 手动模式提供清晰的用户指导
8. **智能路径管理** - 支持session集成和standalone模式
## Integration Points
- **Input**: `--url-map` (target:url pairs) + `--base-path` or `--session`
- **Output**: `{base_path}/screenshots/*.png` + `capture-metadata.json`
- **Callers**: `/workflow:ui-design:imitate-auto-v3`, potentially `/workflow:ui-design:explore-auto-v2`
- **Next Command**: `/workflow:ui-design:extract --images "{screenshot_dir}/*.png"`