Spaces:
Sleeping
Sleeping
| """ | |
| Task registry for the Dalaal Browser-Use Environment. | |
| Each task defines a goal, a mock site to load, and JavaScript-based | |
| success criteria that are evaluated in the browser context. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from dataclasses import dataclass | |
| class Task: | |
| """A browser task with success criteria.""" | |
| id: str | |
| description: str | |
| site_file: str # relative path from mock_sites/ to HTML file | |
| max_steps: int | |
| success_check_js: str # JS expression returning true/false | |
| # Resolve the mock_sites directory relative to this file | |
| _MOCK_SITES_DIR = os.path.join( | |
| os.path.dirname(os.path.dirname(os.path.abspath(__file__))), | |
| "mock_sites", | |
| ) | |
| def get_mock_sites_dir() -> str: | |
| return _MOCK_SITES_DIR | |
| TASKS: dict[str, Task] = {} | |
| def _register(task: Task): | |
| TASKS[task.id] = task | |
| # ββ Todo App Tasks ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="todo_add", | |
| description='Add a new todo item called "Buy milk" to the todo list.', | |
| site_file="todo_app/index.html", | |
| max_steps=10, | |
| success_check_js=""" | |
| (() => { | |
| const items = document.querySelectorAll('.todo-text'); | |
| return Array.from(items).some(el => el.textContent.trim().toLowerCase() === 'buy milk'); | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="todo_add_and_complete", | |
| description='Add a todo item called "Buy milk" and mark it as completed.', | |
| site_file="todo_app/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const items = document.querySelectorAll('.todo-item.completed'); | |
| return Array.from(items).some(el => el.querySelector('.todo-text')?.textContent.trim().toLowerCase() === 'buy milk'); | |
| })() | |
| """, | |
| )) | |
| # ββ Login Form Tasks ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="login", | |
| description='Log in with username "admin" and password "secret123".', | |
| site_file="login_form/index.html", | |
| max_steps=10, | |
| success_check_js=""" | |
| document.getElementById('success-message') !== null && | |
| document.getElementById('success-message').style.display !== 'none' | |
| """, | |
| )) | |
| # ββ Search Engine Tasks βββββββββββββββββββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="search_and_click", | |
| description='Search for "machine learning" and click on the first result link.', | |
| site_file="search_engine/index.html", | |
| max_steps=10, | |
| success_check_js=""" | |
| document.getElementById('result-page') !== null && | |
| document.getElementById('result-page').style.display !== 'none' | |
| """, | |
| )) | |
| # ββ E-commerce Tasks ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="add_to_cart", | |
| description='Add the "Wireless Headphones" product to your shopping cart.', | |
| site_file="ecommerce/index.html", | |
| max_steps=10, | |
| success_check_js=""" | |
| (() => { | |
| const cartCount = document.getElementById('cart-count'); | |
| return cartCount && parseInt(cartCount.textContent) > 0; | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="add_to_cart_and_checkout", | |
| description='Add the "Wireless Headphones" to your cart and proceed to checkout.', | |
| site_file="ecommerce/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| document.getElementById('checkout-page') !== null && | |
| document.getElementById('checkout-page').style.display !== 'none' | |
| """, | |
| )) | |
| # ββ Registration Form Tasks βββββββββββββββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="fill_registration", | |
| description='Fill the registration form with: Name "John Doe", Email "john@example.com", select country "United States", and submit.', | |
| site_file="registration_form/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| document.getElementById('success-message') !== null && | |
| document.getElementById('success-message').style.display !== 'none' | |
| """, | |
| )) | |
| # ββ Email Inbox Tasks (MiniWoB++ inspired) ββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="email_forward", | |
| description='Find the email from Bob Martinez about "Meeting Notes - Sprint Planning" and forward it to alice@company.com.', | |
| site_file="email_inbox/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('forward-success'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.from === 'Bob Martinez' && | |
| msg.dataset.to === 'alice@company.com'; | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="email_find_and_forward", | |
| description='Find the email that mentions an overdue invoice and forward it to finance@company.com.', | |
| site_file="email_inbox/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('forward-success'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.from === 'Frank Wilson' && | |
| msg.dataset.to === 'finance@company.com'; | |
| })() | |
| """, | |
| )) | |
| # ββ Flight Booking Tasks (MiniWoB++ / Mind2Web inspired) ββββββββββββ | |
| _register(Task( | |
| id="book_cheapest_flight", | |
| description='Search for flights from San Francisco (SFO) to Tokyo (NRT) and book the cheapest available flight.', | |
| site_file="flight_booking/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const panel = document.getElementById('confirm-panel'); | |
| return panel && panel.style.display !== 'none' && | |
| panel.dataset.from === 'SFO' && panel.dataset.to === 'TYO' && | |
| parseInt(panel.dataset.price) === 489; | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="book_nonstop_flight", | |
| description='Search for flights from San Francisco (SFO) to Tokyo (NRT), filter to nonstop only, and book the cheapest nonstop flight.', | |
| site_file="flight_booking/index.html", | |
| max_steps=20, | |
| success_check_js=""" | |
| (() => { | |
| const panel = document.getElementById('confirm-panel'); | |
| return panel && panel.style.display !== 'none' && | |
| panel.dataset.from === 'SFO' && panel.dataset.to === 'TYO' && | |
| parseInt(panel.dataset.price) === 892; | |
| })() | |
| """, | |
| )) | |
| # ββ Date Picker Tasks (MiniWoB++ inspired) ββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="schedule_event", | |
| description='Schedule an event called "Team Offsite" on December 25, 2025 using the calendar date picker.', | |
| site_file="date_picker/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('success-message'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.eventName === 'Team Offsite' && | |
| msg.dataset.date === '2025-12-25'; | |
| })() | |
| """, | |
| )) | |
| # ββ Data Table Tasks (WebArena inspired) βββββββββββββββββββββββββββββ | |
| _register(Task( | |
| id="delete_inactive_employees", | |
| description='In the employee directory, filter by status "Inactive" and delete all inactive employees.', | |
| site_file="data_table/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('action-result'); | |
| if (!msg || msg.style.display === 'none') return false; | |
| const names = JSON.parse(msg.dataset.deletedNames || '[]'); | |
| return names.includes('Henry Brown'); | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="find_highest_salary", | |
| description='Sort the employee directory by salary (highest first) and delete the highest-paid employee in the Engineering department.', | |
| site_file="data_table/index.html", | |
| max_steps=20, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('action-result'); | |
| if (!msg || msg.style.display === 'none') return false; | |
| const names = JSON.parse(msg.dataset.deletedNames || '[]'); | |
| return names.includes('Carol White'); | |
| })() | |
| """, | |
| )) | |
| # ββ Multi-Step Wizard Tasks (Mind2Web DMV inspired) ββββββββββββββββββ | |
| _register(Task( | |
| id="renew_registration_2yr", | |
| description='Renew vehicle registration for plate "ABC1234". Confirm the existing address is correct. Select the 2-year renewal option and submit.', | |
| site_file="multi_step_wizard/index.html", | |
| max_steps=20, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('success-message'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.plate === 'ABC1234' && | |
| msg.dataset.years === '2' && | |
| msg.dataset.addressConfirmed === 'true'; | |
| })() | |
| """, | |
| )) | |
| # ββ Recipe Site Tasks (WebVoyager Allrecipes inspired) βββββββββββββββ | |
| _register(Task( | |
| id="find_vegan_recipe", | |
| description='Search for "vegan" recipes, open the highest-rated vegan recipe, and save it to favorites.', | |
| site_file="recipe_site/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('save-success'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.recipeName === 'Vegan Buddha Bowl'; | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="find_quick_vegetarian", | |
| description='Filter recipes to "Vegetarian" diet and sort by quickest cooking time. Open the fastest vegetarian recipe and save it to favorites.', | |
| site_file="recipe_site/index.html", | |
| max_steps=15, | |
| success_check_js=""" | |
| (() => { | |
| const msg = document.getElementById('save-success'); | |
| return msg && msg.style.display !== 'none' && | |
| msg.dataset.recipeName === 'Mushroom Risotto'; | |
| })() | |
| """, | |
| )) | |
| # ββ Issue Tracker Tasks (WebArena GitLab inspired) βββββββββββββββββββ | |
| _register(Task( | |
| id="label_timeout_issues", | |
| description='Filter issues to show only those assigned to "maria". Find any open issue that mentions "timeout" in its description and add the "urgent" label to it.', | |
| site_file="issue_tracker/index.html", | |
| max_steps=25, | |
| success_check_js=""" | |
| (() => { | |
| // Issues assigned to maria that mention "timeout": #101, #107 | |
| // Check if at least one has the urgent label | |
| const issue101 = document.querySelector('[data-id="101"]') || | |
| (() => { const msg = document.getElementById('label-success'); | |
| return msg && msg.dataset.issueId === '101' && msg.dataset.label === 'urgent'; })(); | |
| // Check via the issues array directly | |
| const script = document.querySelector('script:last-of-type'); | |
| const i101 = typeof issues !== 'undefined' && issues.find(i => i.id === 101); | |
| const i107 = typeof issues !== 'undefined' && issues.find(i => i.id === 107); | |
| return (i101 && i101.labels.includes('urgent')) || (i107 && i107.labels.includes('urgent')); | |
| })() | |
| """, | |
| )) | |
| _register(Task( | |
| id="label_all_timeout_issues", | |
| description='Find ALL open issues assigned to "maria" that mention "timeout" in their description, and add the "urgent" label to each one. There may be multiple such issues.', | |
| site_file="issue_tracker/index.html", | |
| max_steps=35, | |
| success_check_js=""" | |
| (() => { | |
| // maria's open issues mentioning "timeout": #101 (gateway timeout), #107 (timeout-like delay) | |
| const i101 = typeof issues !== 'undefined' && issues.find(i => i.id === 101); | |
| const i107 = typeof issues !== 'undefined' && issues.find(i => i.id === 107); | |
| return i101 && i101.labels.includes('urgent') && i107 && i107.labels.includes('urgent'); | |
| })() | |
| """, | |
| )) | |
| def get_task(task_id: str) -> Task: | |
| """Get a task by ID. Raises KeyError if not found.""" | |
| if task_id not in TASKS: | |
| available = ", ".join(sorted(TASKS.keys())) | |
| raise KeyError(f"Unknown task '{task_id}'. Available tasks: {available}") | |
| return TASKS[task_id] | |
| def list_tasks() -> list[str]: | |
| """Return all available task IDs.""" | |
| return sorted(TASKS.keys()) | |