""" Standalone init command for browser-use template generation. This module provides a minimal command-line interface for generating browser-use templates without requiring heavy TUI dependencies. """ import json import sys from pathlib import Path from typing import Any from urllib import request from urllib.error import URLError import click from InquirerPy.base.control import Choice from InquirerPy.prompts.list import ListPrompt from InquirerPy.utils import InquirerPyStyle from rich.console import Console from rich.panel import Panel from rich.text import Text # Rich console for styled output console = Console() # GitHub template repository URL (for runtime fetching) TEMPLATE_REPO_URL = 'https://raw.githubusercontent.com/browser-use/template-library/main' # Export for backward compatibility with cli.py # Templates are fetched at runtime via _get_template_list() INIT_TEMPLATES: dict[str, Any] = {} def _fetch_template_list() -> dict[str, Any] | None: """ Fetch template list from GitHub templates.json. Returns template dict if successful, None if failed. """ try: url = f'{TEMPLATE_REPO_URL}/templates.json' with request.urlopen(url, timeout=5) as response: data = response.read().decode('utf-8') return json.loads(data) except (URLError, TimeoutError, json.JSONDecodeError, Exception): return None def _get_template_list() -> dict[str, Any]: """ Get template list from GitHub. Raises FileNotFoundError if GitHub fetch fails. """ templates = _fetch_template_list() if templates is not None: return templates raise FileNotFoundError('Could not fetch templates from GitHub. Check your internet connection.') def _fetch_from_github(file_path: str) -> str | None: """ Fetch template file from GitHub. Returns file content if successful, None if failed. """ try: url = f'{TEMPLATE_REPO_URL}/{file_path}' with request.urlopen(url, timeout=5) as response: return response.read().decode('utf-8') except (URLError, TimeoutError, Exception): return None def _fetch_binary_from_github(file_path: str) -> bytes | None: """ Fetch binary file from GitHub. Returns file content if successful, None if failed. """ try: url = f'{TEMPLATE_REPO_URL}/{file_path}' with request.urlopen(url, timeout=5) as response: return response.read() except (URLError, TimeoutError, Exception): return None def _get_template_content(file_path: str) -> str: """ Get template file content from GitHub. Raises exception if fetch fails. """ content = _fetch_from_github(file_path) if content is not None: return content raise FileNotFoundError(f'Could not fetch template from GitHub: {file_path}') # InquirerPy style for template selection (browser-use orange theme) inquirer_style = InquirerPyStyle( { 'pointer': '#fe750e bold', 'highlighted': '#fe750e bold', 'question': 'bold', 'answer': '#fe750e bold', 'questionmark': '#fe750e bold', } ) def _write_init_file(output_path: Path, content: str, force: bool = False) -> bool: """Write content to a file, with safety checks.""" # Check if file already exists if output_path.exists() and not force: console.print(f'[yellow]⚠[/yellow] File already exists: [cyan]{output_path}[/cyan]') if not click.confirm('Overwrite?', default=False): console.print('[red]✗[/red] Cancelled') return False # Ensure parent directory exists output_path.parent.mkdir(parents=True, exist_ok=True) # Write file try: output_path.write_text(content, encoding='utf-8') return True except Exception as e: console.print(f'[red]✗[/red] Error writing file: {e}') return False @click.command('browser-use-init') @click.option( '--template', '-t', type=str, help='Template to use', ) @click.option( '--output', '-o', type=click.Path(), help='Output file path (default: browser_use_