from typing import Generic, TypeVar from pydantic import BaseModel, ConfigDict, Field # Action Input Models class SearchGoogleAction(BaseModel): query: str class GoToUrlAction(BaseModel): url: str new_tab: bool = False # True to open in new tab, False to navigate in current tab class ClickElementAction(BaseModel): index: int = Field(ge=1, description='index of the element to click') while_holding_ctrl: bool | None = Field( default=None, description='Set to True to open the navigation in a new background tab (Ctrl+Click behavior). Optional.', ) # expect_download: bool = Field(default=False, description='set True if expecting a download, False otherwise') # moved to downloads_watchdog.py # click_count: int = 1 # TODO class InputTextAction(BaseModel): index: int = Field(ge=0, description='index of the element to input text into, 0 is the page') text: str clear_existing: bool = Field(default=True, description='set True to clear existing text, False to append to existing text') class DoneAction(BaseModel): text: str success: bool files_to_display: list[str] | None = [] T = TypeVar('T', bound=BaseModel) class StructuredOutputAction(BaseModel, Generic[T]): success: bool = True data: T class SwitchTabAction(BaseModel): tab_id: str = Field( min_length=4, max_length=4, description='Last 4 chars of TargetID', ) # last 4 chars of TargetID class CloseTabAction(BaseModel): tab_id: str = Field(min_length=4, max_length=4, description='4 character Tab ID') # last 4 chars of TargetID class ScrollAction(BaseModel): down: bool # True to scroll down, False to scroll up num_pages: float # Number of pages to scroll (0.5 = half page, 1.0 = one page, etc.) frame_element_index: int | None = None # Optional element index to find scroll container for class SendKeysAction(BaseModel): keys: str class UploadFileAction(BaseModel): index: int path: str class ExtractPageContentAction(BaseModel): value: str class NoParamsAction(BaseModel): """ Accepts absolutely anything in the incoming data and discards it, so the final parsed model is empty. """ model_config = ConfigDict(extra='ignore') # No fields defined - all inputs are ignored automatically class GetDropdownOptionsAction(BaseModel): index: int = Field(ge=1, description='index of the dropdown element to get the option values for') class SelectDropdownOptionAction(BaseModel): index: int = Field(ge=1, description='index of the dropdown element to select an option for') text: str = Field(description='the text or exact value of the option to select')