# generated by datamodel-codegen:
#   filename:  openapi.json

from __future__ import annotations

from enum import Enum
from typing import Any, Dict, List
from uuid import UUID

from pydantic import AwareDatetime, BaseModel, ConfigDict, Field, RootModel


class AccountNotFoundError(BaseModel):
    detail: str | None = Field('Account not found', title='Detail')


class BrowserSessionStatus(Enum):
    active = 'active'
    stopped = 'stopped'


class BrowserSessionUpdateAction(Enum):
    stop = 'stop'


class BrowserSessionView(BaseModel):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    id: UUID = Field(..., description='Unique identifier for the session', title='ID')
    status: BrowserSessionStatus = Field(
        ...,
        description='Current status of the session (active/stopped)',
        title='Status',
    )
    live_url: str | None = Field(
        None,
        alias='liveUrl',
        description='URL where the browser can be viewed live in real-time',
        title='Live URL',
    )
    cdp_url: str | None = Field(
        None,
        alias='cdpUrl',
        description='Chrome DevTools Protocol URL for browser automation',
        title='CDP URL',
    )
    timeout_at: AwareDatetime = Field(
        ...,
        alias='timeoutAt',
        description='Timestamp when the session will timeout',
        title='Timeout At',
    )
    started_at: AwareDatetime = Field(
        ...,
        alias='startedAt',
        description='Timestamp when the session was created and started',
        title='Started At',
    )
    finished_at: AwareDatetime | None = Field(
        None,
        alias='finishedAt',
        description='Timestamp when the session was stopped (None if still active)',
        title='Finished At',
    )
    proxy_used_mb: str | None = Field(
        '0',
        alias='proxyUsedMb',
        description='Amount of proxy data used in MB',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxy Used MB',
    )
    proxy_cost: str | None = Field(
        '0',
        alias='proxyCost',
        description='Cost of proxy usage in USD',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxy Cost',
    )
    browser_cost: str | None = Field(
        '0',
        alias='browserCost',
        description='Cost of browser session hosting in USD',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Browser Cost',
    )
    agent_session_id: UUID | None = Field(
        None,
        alias='agentSessionId',
        description='ID of the agent session that created this browser (None for standalone BaaS sessions)',
        title='Agent Session ID',
    )
    recording_url: str | None = Field(
        None,
        alias='recordingUrl',
        description='Presigned URL to download the session recording (available after session ends, if recording was enabled)',
        title='Recording URL',
    )


class BuAgentSessionStatus(Enum):
    created = 'created'
    idle = 'idle'
    running = 'running'
    stopped = 'stopped'
    timed_out = 'timed_out'
    error = 'error'


class BuModel(Enum):
    bu_mini = 'bu-mini'
    bu_max = 'bu-max'
    bu_ultra = 'bu-ultra'
    gemini_3_flash = 'gemini-3-flash'
    claude_sonnet_4_6 = 'claude-sonnet-4.6'
    claude_opus_4_6 = 'claude-opus-4.6'
    gpt_5_4_mini = 'gpt-5.4-mini'


class BrowserScreenWidth(RootModel[int]):
    root: int = Field(
        ...,
        description='Custom screen width in pixels for the browser.',
        ge=320,
        le=6144,
        title='Browser Screen Width',
    )


class BrowserScreenHeight(RootModel[int]):
    root: int = Field(
        ...,
        description='Custom screen height in pixels for the browser.',
        ge=320,
        le=3456,
        title='Browser Screen Height',
    )


class Username(RootModel[str]):
    root: str = Field(
        ...,
        description='Username for proxy authentication.',
        max_length=255,
        min_length=1,
        title='Username',
    )


class Password(RootModel[str]):
    root: str = Field(
        ...,
        description='Password for proxy authentication.',
        max_length=255,
        min_length=1,
        title='Password',
    )


class CustomProxy(BaseModel):
    host: str = Field(
        ...,
        description='Host of the proxy.',
        max_length=255,
        min_length=1,
        title='Host',
    )
    port: int = Field(
        ..., description='Port of the proxy.', ge=1, le=65535, title='Port'
    )
    username: Username | None = Field(
        None, description='Username for proxy authentication.', title='Username'
    )
    password: Password | None = Field(
        None, description='Password for proxy authentication.', title='Password'
    )


class FileInfo(BaseModel):
    path: str = Field(
        ...,
        description='File path relative to the session workspace root.',
        title='Path',
    )
    size: int = Field(..., description='File size in bytes.', title='Size')
    last_modified: AwareDatetime = Field(
        ...,
        alias='lastModified',
        description='When the file was last modified.',
        title='Lastmodified',
    )
    url: str | None = Field(
        None,
        description='Presigned download URL (60s expiry). Only included when `includeUrls=true`.',
        title='Url',
    )


class FileListResponse(BaseModel):
    files: List[FileInfo] = Field(..., title='Files')
    folders: List[str] | None = Field(
        None,
        description='Immediate sub-folder names at this prefix level',
        title='Folders',
    )
    next_cursor: str | None = Field(
        None,
        alias='nextCursor',
        description='Cursor for the next page. Pass as the `cursor` query parameter to fetch the next page.',
        title='Nextcursor',
    )
    has_more: bool | None = Field(
        False,
        alias='hasMore',
        description='Whether there are more files beyond this page.',
        title='Hasmore',
    )


class Size(RootModel[int]):
    root: int = Field(
        ...,
        description='File size in bytes (required for workspace uploads)',
        ge=1,
        title='Size',
    )


class FileUploadItem(BaseModel):
    name: str = Field(
        ...,
        description='Filename, e.g. "data.csv"',
        max_length=255,
        min_length=1,
        title='Name',
    )
    content_type: str | None = Field(
        'application/octet-stream',
        alias='contentType',
        description='MIME type, e.g. "text/csv"',
        max_length=255,
        title='Contenttype',
    )
    size: Size | None = Field(
        None,
        description='File size in bytes (required for workspace uploads)',
        title='Size',
    )


class FileUploadRequest(BaseModel):
    files: List[FileUploadItem] = Field(..., max_length=10, min_length=1, title='Files')


class FileUploadResponseItem(BaseModel):
    name: str = Field(..., description='Original filename as requested.', title='Name')
    upload_url: str = Field(
        ...,
        alias='uploadUrl',
        description='Presigned PUT URL. Upload the file by sending a PUT request to this URL with the file content and matching Content-Type header. Expires after 5 minutes.',
        title='Uploadurl',
    )
    path: str = Field(
        ...,
        description='Path where the file will be stored in the workspace, e.g. "uploads/data.csv".',
        title='Path',
    )


class InsufficientCreditsError(BaseModel):
    detail: str | None = Field('Insufficient credits', title='Detail')


class MessageResponse(BaseModel):
    id: UUID = Field(..., description='Unique message identifier.', title='Id')
    session_id: UUID = Field(
        ...,
        alias='sessionId',
        description='ID of the session this message belongs to.',
        title='Sessionid',
    )
    role: str = Field(
        ...,
        description='Message role: "human" for user-submitted tasks, "ai" for agent actions and responses.',
        title='Role',
    )
    data: str = Field(
        ...,
        description='Raw message content. Format depends on the message type — may be plain text, JSON, or structured action data.',
        title='Data',
    )
    type: str | None = Field(
        '',
        description='Message category. Common values: `user_message`, `assistant_message`, `browser_action`, `file_operation`, `code_execution`, `integration`, `planning`, `completion`, `browser_action_result`, `browser_action_error`.',
        title='Type',
    )
    summary: str | None = Field(
        '',
        description='One-liner human-readable description of the message (e.g. "Navigating to google.com", "Clicking element #5"). Useful for building activity feeds.',
        title='Summary',
    )
    screenshot_url: str | None = Field(
        None,
        alias='screenshotUrl',
        description='Browser screenshot captured at the time of this message. Presigned URL, expires after 5 minutes.',
        title='Screenshoturl',
    )
    hidden: bool | None = Field(
        False,
        description='Whether this message should be hidden from the user in a chat UI.',
        title='Hidden',
    )
    created_at: AwareDatetime = Field(
        ...,
        alias='createdAt',
        description='When this message was created.',
        title='Createdat',
    )


class PlanInfo(BaseModel):
    plan_name: str = Field(
        ..., alias='planName', description='The name of the plan', title='Plan Name'
    )
    subscription_status: str | None = Field(
        ...,
        alias='subscriptionStatus',
        description='The status of the subscription',
        title='Subscription Status',
    )
    subscription_id: str | None = Field(
        ...,
        alias='subscriptionId',
        description='The ID of the subscription',
        title='Subscription ID',
    )
    subscription_current_period_end: str | None = Field(
        ...,
        alias='subscriptionCurrentPeriodEnd',
        description='The end of the current period',
        title='Subscription Current Period End',
    )
    subscription_canceled_at: str | None = Field(
        ...,
        alias='subscriptionCanceledAt',
        description='The date the subscription was canceled',
        title='Subscription Canceled At',
    )


class Name(RootModel[str]):
    root: str = Field(
        ..., description='Optional name for the profile', max_length=100, title='Name'
    )


class UserId(RootModel[str]):
    root: str = Field(
        ...,
        description='Your internal user identifier for this profile. Use this to associate a profile with a user in your system.',
        max_length=255,
        title='User ID',
    )


class ProfileCreateRequest(BaseModel):
    name: Name | None = Field(
        None, description='Optional name for the profile', title='Name'
    )
    user_id: UserId | None = Field(
        None,
        alias='userId',
        description='Your internal user identifier for this profile. Use this to associate a profile with a user in your system.',
        title='User ID',
    )


class ProfileNotFoundError(BaseModel):
    detail: str | None = Field('Profile not found', title='Detail')


class ProfileUpdateRequest(BaseModel):
    name: Name | None = Field(
        None, description='Optional name for the profile', title='Name'
    )
    user_id: UserId | None = Field(
        None,
        alias='userId',
        description='Your internal user identifier for this profile. Use this to associate a profile with a user in your system.',
        title='User ID',
    )


class ProfileView(BaseModel):
    id: UUID = Field(..., description='Unique identifier for the profile', title='ID')
    user_id: str | None = Field(
        None,
        alias='userId',
        description='Your internal user identifier for this profile. Use this to associate a profile with a user in your system.',
        title='User ID',
    )
    name: str | None = Field(
        None, description='Optional name for the profile', title='Name'
    )
    last_used_at: AwareDatetime | None = Field(
        None,
        alias='lastUsedAt',
        description='Timestamp when the profile was last used',
        title='Last Used At',
    )
    created_at: AwareDatetime = Field(
        ...,
        alias='createdAt',
        description='Timestamp when the profile was created',
        title='Created At',
    )
    updated_at: AwareDatetime = Field(
        ...,
        alias='updatedAt',
        description='Timestamp when the profile was last updated',
        title='Updated At',
    )
    cookie_domains: List[str] | None = Field(
        None,
        alias='cookieDomains',
        description='List of domain URLs that have cookies stored for this profile',
        title='Cookie Domains',
    )


class ProxyCountryCode(Enum):
    ad = 'ad'
    ae = 'ae'
    af = 'af'
    ag = 'ag'
    ai = 'ai'
    al = 'al'
    am = 'am'
    an = 'an'
    ao = 'ao'
    aq = 'aq'
    ar = 'ar'
    as_ = 'as'
    at = 'at'
    au = 'au'
    aw = 'aw'
    az = 'az'
    ba = 'ba'
    bb = 'bb'
    bd = 'bd'
    be = 'be'
    bf = 'bf'
    bg = 'bg'
    bh = 'bh'
    bi = 'bi'
    bj = 'bj'
    bl = 'bl'
    bm = 'bm'
    bn = 'bn'
    bo = 'bo'
    bq = 'bq'
    br = 'br'
    bs = 'bs'
    bt = 'bt'
    bv = 'bv'
    bw = 'bw'
    by = 'by'
    bz = 'bz'
    ca = 'ca'
    cc = 'cc'
    cd = 'cd'
    cf = 'cf'
    cg = 'cg'
    ch = 'ch'
    ck = 'ck'
    cl = 'cl'
    cm = 'cm'
    co = 'co'
    cr = 'cr'
    cs = 'cs'
    cu = 'cu'
    cv = 'cv'
    cw = 'cw'
    cx = 'cx'
    cy = 'cy'
    cz = 'cz'
    de = 'de'
    dj = 'dj'
    dk = 'dk'
    dm = 'dm'
    do = 'do'
    dz = 'dz'
    ec = 'ec'
    ee = 'ee'
    eg = 'eg'
    eh = 'eh'
    er = 'er'
    es = 'es'
    et = 'et'
    fi = 'fi'
    fj = 'fj'
    fk = 'fk'
    fm = 'fm'
    fo = 'fo'
    fr = 'fr'
    ga = 'ga'
    gd = 'gd'
    ge = 'ge'
    gf = 'gf'
    gg = 'gg'
    gh = 'gh'
    gi = 'gi'
    gl = 'gl'
    gm = 'gm'
    gn = 'gn'
    gp = 'gp'
    gq = 'gq'
    gr = 'gr'
    gs = 'gs'
    gt = 'gt'
    gu = 'gu'
    gw = 'gw'
    gy = 'gy'
    hk = 'hk'
    hm = 'hm'
    hn = 'hn'
    hr = 'hr'
    ht = 'ht'
    hu = 'hu'
    id = 'id'
    ie = 'ie'
    il = 'il'
    im = 'im'
    in_ = 'in'
    iq = 'iq'
    ir = 'ir'
    is_ = 'is'
    it = 'it'
    je = 'je'
    jm = 'jm'
    jo = 'jo'
    jp = 'jp'
    ke = 'ke'
    kg = 'kg'
    kh = 'kh'
    ki = 'ki'
    km = 'km'
    kn = 'kn'
    kp = 'kp'
    kr = 'kr'
    kw = 'kw'
    ky = 'ky'
    kz = 'kz'
    la = 'la'
    lb = 'lb'
    lc = 'lc'
    li = 'li'
    lk = 'lk'
    lr = 'lr'
    ls = 'ls'
    lt = 'lt'
    lu = 'lu'
    lv = 'lv'
    ly = 'ly'
    ma = 'ma'
    mc = 'mc'
    md = 'md'
    me = 'me'
    mf = 'mf'
    mg = 'mg'
    mh = 'mh'
    mk = 'mk'
    ml = 'ml'
    mm = 'mm'
    mn = 'mn'
    mo = 'mo'
    mp = 'mp'
    mq = 'mq'
    mr = 'mr'
    ms = 'ms'
    mt = 'mt'
    mu = 'mu'
    mv = 'mv'
    mw = 'mw'
    mx = 'mx'
    my = 'my'
    mz = 'mz'
    na = 'na'
    nc = 'nc'
    ne = 'ne'
    nf = 'nf'
    ng = 'ng'
    ni = 'ni'
    nl = 'nl'
    no = 'no'
    np = 'np'
    nr = 'nr'
    nu = 'nu'
    nz = 'nz'
    om = 'om'
    pa = 'pa'
    pe = 'pe'
    pf = 'pf'
    pg = 'pg'
    ph = 'ph'
    pk = 'pk'
    pl = 'pl'
    pm = 'pm'
    pn = 'pn'
    pr = 'pr'
    ps = 'ps'
    pt = 'pt'
    pw = 'pw'
    py = 'py'
    qa = 'qa'
    re = 're'
    ro = 'ro'
    rs = 'rs'
    ru = 'ru'
    rw = 'rw'
    sa = 'sa'
    sb = 'sb'
    sc = 'sc'
    sd = 'sd'
    se = 'se'
    sg = 'sg'
    sh = 'sh'
    si = 'si'
    sj = 'sj'
    sk = 'sk'
    sl = 'sl'
    sm = 'sm'
    sn = 'sn'
    so = 'so'
    sr = 'sr'
    ss = 'ss'
    st = 'st'
    sv = 'sv'
    sx = 'sx'
    sy = 'sy'
    sz = 'sz'
    tc = 'tc'
    td = 'td'
    tf = 'tf'
    tg = 'tg'
    th = 'th'
    tj = 'tj'
    tk = 'tk'
    tl = 'tl'
    tm = 'tm'
    tn = 'tn'
    to = 'to'
    tr = 'tr'
    tt = 'tt'
    tv = 'tv'
    tw = 'tw'
    tz = 'tz'
    ua = 'ua'
    ug = 'ug'
    uk = 'uk'
    us = 'us'
    uy = 'uy'
    uz = 'uz'
    va = 'va'
    vc = 'vc'
    ve = 've'
    vg = 'vg'
    vi = 'vi'
    vn = 'vn'
    vu = 'vu'
    wf = 'wf'
    ws = 'ws'
    xk = 'xk'
    ye = 'ye'
    yt = 'yt'
    za = 'za'
    zm = 'zm'
    zw = 'zw'


class MaxCostUsd(RootModel[str]):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    root: str = Field(
        ...,
        description='Maximum total cost in USD allowed for this session. The task will be stopped if this limit is reached. If omitted, a default limit applies (capped by your available balance).',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Maxcostusd',
    )


class RunTaskRequest(BaseModel):
    task: str | None = Field(
        None,
        description='The natural-language instruction for the agent to execute (e.g. "Go to amazon.com and find the best-rated wireless mouse under $50"). Required when dispatching to an existing session.',
        title='Task',
    )
    model: BuModel | None = Field(
        BuModel.claude_sonnet_4_6,
        description='The model to use. "gemini-3-flash" is fast and cheap, "claude-sonnet-4.6" is balanced, "claude-opus-4.6" is most capable. See BuModel for details.',
    )
    session_id: UUID | None = Field(
        None,
        alias='sessionId',
        description='ID of an existing idle session to dispatch the task to. If omitted, a new session is created.',
        title='Sessionid',
    )
    keep_alive: bool | None = Field(
        False,
        alias='keepAlive',
        description='If true, the session stays alive in idle state after the task completes instead of automatically stopping. This lets you dispatch follow-up tasks to the same session, preserving browser state and files.',
        title='Keepalive',
    )
    max_cost_usd: float | MaxCostUsd | None = Field(
        None,
        alias='maxCostUsd',
        description='Maximum total cost in USD allowed for this session. The task will be stopped if this limit is reached. If omitted, a default limit applies (capped by your available balance).',
        title='Maxcostusd',
    )
    profile_id: UUID | None = Field(
        None,
        alias='profileId',
        description='ID of a browser profile to load into the session. Profiles persist cookies, local storage, and other browser state across sessions. Create profiles via the Profiles API.',
        title='Profileid',
    )
    workspace_id: UUID | None = Field(
        None,
        alias='workspaceId',
        description='ID of a workspace to attach to the session. Workspaces provide persistent file storage that carries across sessions. Create workspaces via the Workspaces API.',
        title='Workspaceid',
    )
    proxy_country_code: ProxyCountryCode | None = Field(
        ProxyCountryCode.us,
        alias='proxyCountryCode',
        description='Country code for the browser proxy (e.g. "US", "DE", "JP"). Set to null to disable the proxy. The proxy routes browser traffic through the specified country, useful for accessing geo-restricted content.',
    )
    output_schema: Dict[str, Any] | None = Field(
        None,
        alias='outputSchema',
        description='A JSON Schema that the agent\'s final output must conform to. When set, the agent will return structured data matching this schema in the `output` field of the response. Example: {"type": "object", "properties": {"price": {"type": "number"}, "title": {"type": "string"}}}.',
        title='Outputschema',
    )
    enable_scheduled_tasks: bool | None = Field(
        False,
        alias='enableScheduledTasks',
        description='If true, the agent can create scheduled tasks that run on a recurring basis (e.g. "every Monday morning, check my inbox and summarize new emails"). Scheduled tasks are tied to your project and persist beyond the session. Note: all scheduled tasks are visible project-wide, so avoid enabling this in multi-user setups where task isolation is needed.',
        title='Enablescheduledtasks',
    )
    enable_recording: bool | None = Field(
        False,
        alias='enableRecording',
        description='If true, records a video of the browser session. The recording URLs will be available in the `recordingUrls` field of the session response after the task completes.',
        title='Enablerecording',
    )
    skills: bool | None = Field(
        True,
        description='If true, enables built-in agent skills like Google Sheets integration and file management. Set to false to restrict the agent to browser-only actions.',
        title='Skills',
    )
    agentmail: bool | None = Field(
        True,
        description='If true, provisions a temporary email inbox (via AgentMail) for the session. The email address is available in the `agentmailEmail` field of the session response. Useful for tasks that require email verification or sign-ups.',
        title='Agentmail',
    )
    cache_script: bool | None = Field(
        None,
        alias='cacheScript',
        description='Controls deterministic script caching. `null` (default): auto-detected — enabled when the task contains `@{{value}}` brackets and a workspace is attached. `true`: force-enable script caching even without brackets (caches the exact task). `false`: force-disable, even if brackets are present. When active, the first call runs the full agent and saves a reusable script. Subsequent calls with the same task template execute the cached script with $0 LLM cost. Requires workspace_id when enabled. Example: "Get prices from @{{https://example.com}} for @{{electronics}}".',
        title='Cachescript',
    )
    auto_heal: bool | None = Field(
        True,
        alias='autoHeal',
        description='When cache_script is active, controls whether a lightweight LLM validates the cached script output. If the output looks incorrect (empty, error, wrong structure), the system automatically re-triggers the full agent to generate a new version of the script. Set to false to disable validation and always return the raw script output.',
        title='Autoheal',
    )


class SessionNotFoundError(BaseModel):
    detail: str | None = Field('Session not found', title='Detail')


class MaxCostUsd1(RootModel[str]):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    root: str = Field(
        ...,
        description='Maximum cost limit in USD set for this session.',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Maxcostusd',
    )


class SessionResponse(BaseModel):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    id: UUID = Field(..., description='Unique session identifier.', title='Id')
    status: BuAgentSessionStatus = Field(
        ...,
        description='Current session lifecycle status. Progresses through: `created` (sandbox starting) → `idle` (ready, waiting for task) → `running` (task executing) → `stopped` / `timed_out` / `error`. Poll this field to track progress.',
    )
    model: BuModel = Field(..., description='The model tier used for this session.')
    title: str | None = Field(
        None,
        description='Auto-generated short title summarizing the task. Available after the task starts running.',
        title='Title',
    )
    output: Any = Field(
        None,
        description="The agent's final output. If `outputSchema` was provided, this will be structured data conforming to that schema. Otherwise it may be a free-form string or null. Populated once the task completes, regardless of whether `isTaskSuccessful` is true or false.",
        title='Output',
    )
    output_schema: Dict[str, Any] | None = Field(
        None,
        alias='outputSchema',
        description='The JSON Schema that was requested for structured output, if any.',
        title='Outputschema',
    )
    step_count: int | None = Field(
        0,
        alias='stepCount',
        description='Number of steps the agent has executed so far.',
        title='Stepcount',
    )
    last_step_summary: str | None = Field(
        None,
        alias='lastStepSummary',
        description='Human-readable summary of the most recent agent step (e.g. "Clicking the Submit button"). Useful for showing real-time progress.',
        title='Laststepsummary',
    )
    is_task_successful: bool | None = Field(
        None,
        alias='isTaskSuccessful',
        description='Whether the task completed successfully. `true` if the agent achieved the goal, `false` if it failed or gave up, `null` if the task is still running or no task was dispatched.',
        title='Istasksuccessful',
    )
    live_url: str | None = Field(
        None,
        alias='liveUrl',
        description='URL to view the live browser session. Available immediately on session creation — can be embedded in an iframe to show the browser in real time.',
        title='Liveurl',
    )
    recording_urls: List[str] | None = Field(
        [],
        alias='recordingUrls',
        description='URLs to download session recordings. Only populated if `enableRecording` was set to true and the task has completed.',
        title='Recordingurls',
    )
    profile_id: UUID | None = Field(
        None,
        alias='profileId',
        description='ID of the browser profile loaded in this session, if any.',
        title='Profileid',
    )
    workspace_id: UUID | None = Field(
        None,
        alias='workspaceId',
        description='ID of the workspace attached to this session, if any.',
        title='Workspaceid',
    )
    proxy_country_code: ProxyCountryCode | None = Field(
        None,
        alias='proxyCountryCode',
        description='Country code of the proxy used for this session, or null if no proxy.',
    )
    max_cost_usd: MaxCostUsd1 | None = Field(
        None,
        alias='maxCostUsd',
        description='Maximum cost limit in USD set for this session.',
        title='Maxcostusd',
    )
    total_input_tokens: int | None = Field(
        0,
        alias='totalInputTokens',
        description='Total LLM input tokens consumed by this session.',
        title='Totalinputtokens',
    )
    total_output_tokens: int | None = Field(
        0,
        alias='totalOutputTokens',
        description='Total LLM output tokens consumed by this session.',
        title='Totaloutputtokens',
    )
    proxy_used_mb: str | None = Field(
        '0',
        alias='proxyUsedMb',
        description='Proxy bandwidth used in megabytes.',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxyusedmb',
    )
    llm_cost_usd: str | None = Field(
        '0',
        alias='llmCostUsd',
        description='Cost of LLM usage in USD.',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Llmcostusd',
    )
    proxy_cost_usd: str | None = Field(
        '0',
        alias='proxyCostUsd',
        description='Cost of proxy bandwidth in USD.',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxycostusd',
    )
    browser_cost_usd: str | None = Field(
        '0',
        alias='browserCostUsd',
        description='Cost of browser compute time in USD.',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Browsercostusd',
    )
    total_cost_usd: str | None = Field(
        '0',
        alias='totalCostUsd',
        description='Total session cost in USD (LLM + proxy + browser).',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Totalcostusd',
    )
    screenshot_url: str | None = Field(
        None,
        alias='screenshotUrl',
        description='URL of the latest browser screenshot. This is a presigned URL that expires after 5 minutes. A new URL is generated each time you fetch the session.',
        title='Screenshoturl',
    )
    agentmail_email: str | None = Field(
        None,
        alias='agentmailEmail',
        description='Temporary email address provisioned for this session (via AgentMail). Only present if `agentmail` was enabled.',
        title='Agentmailemail',
    )
    created_at: AwareDatetime = Field(
        ...,
        alias='createdAt',
        description='When the session was created.',
        title='Createdat',
    )
    updated_at: AwareDatetime = Field(
        ...,
        alias='updatedAt',
        description='When the session was last updated.',
        title='Updatedat',
    )


class SessionTimeoutLimitExceededError(BaseModel):
    detail: str | None = Field(
        'Maximum session timeout is 4 hours (240 minutes).', title='Detail'
    )


class StopStrategy(Enum):
    task = 'task'
    session = 'session'


class TooManyConcurrentActiveSessionsError(BaseModel):
    detail: str | None = Field(
        'Too many concurrent active sessions. Please wait for one to finish, kill one, or upgrade your plan.',
        title='Detail',
    )


class UpdateBrowserSessionRequest(BaseModel):
    action: BrowserSessionUpdateAction = Field(
        ..., description='The action to perform on the session', title='Action'
    )


class ValidationError(BaseModel):
    loc: List[str | int] = Field(..., title='Location')
    msg: str = Field(..., title='Message')
    type: str = Field(..., title='Error Type')


class Name2(RootModel[str]):
    root: str = Field(
        ..., description='Optional name for the workspace', max_length=100, title='Name'
    )


class WorkspaceCreateRequest(BaseModel):
    name: Name2 | None = Field(
        None, description='Optional name for the workspace', title='Name'
    )


class WorkspaceUpdateRequest(BaseModel):
    name: Name2 | None = Field(
        None, description='Optional name for the workspace', title='Name'
    )


class WorkspaceView(BaseModel):
    id: UUID = Field(..., description='Unique identifier for the workspace', title='ID')
    name: str | None = Field(
        None, description='Optional name for the workspace', title='Name'
    )
    created_at: AwareDatetime = Field(
        ...,
        alias='createdAt',
        description='Timestamp when the workspace was created',
        title='Created At',
    )
    updated_at: AwareDatetime = Field(
        ...,
        alias='updatedAt',
        description='Timestamp when the workspace was last updated',
        title='Updated At',
    )


class AccountView(BaseModel):
    name: str | None = Field(None, description='The name of the user', title='Name')
    total_credits_balance_usd: float = Field(
        ...,
        alias='totalCreditsBalanceUsd',
        description='The total credits balance in USD',
        title='Credits Balance USD',
    )
    monthly_credits_balance_usd: float = Field(
        ...,
        alias='monthlyCreditsBalanceUsd',
        description='Monthly subscription credits balance in USD',
        title='Monthly Credits Balance USD',
    )
    additional_credits_balance_usd: float = Field(
        ...,
        alias='additionalCreditsBalanceUsd',
        description='Additional top-up credits balance in USD',
        title='Additional Credits Balance USD',
    )
    rate_limit: int = Field(
        ...,
        alias='rateLimit',
        description='The rate limit for the account',
        title='Rate Limit',
    )
    plan_info: PlanInfo = Field(
        ..., alias='planInfo', description='The plan information', title='Plan Info'
    )
    project_id: UUID = Field(
        ..., alias='projectId', description='The ID of the project', title='Project ID'
    )


class BrowserSessionItemView(BaseModel):
    model_config = ConfigDict(
        regex_engine="python-re",
    )
    id: UUID = Field(..., description='Unique identifier for the session', title='ID')
    status: BrowserSessionStatus = Field(
        ...,
        description='Current status of the session (active/stopped)',
        title='Status',
    )
    live_url: str | None = Field(
        None,
        alias='liveUrl',
        description='URL where the browser can be viewed live in real-time',
        title='Live URL',
    )
    cdp_url: str | None = Field(
        None,
        alias='cdpUrl',
        description='Chrome DevTools Protocol URL for browser automation',
        title='CDP URL',
    )
    timeout_at: AwareDatetime = Field(
        ...,
        alias='timeoutAt',
        description='Timestamp when the session will timeout',
        title='Timeout At',
    )
    started_at: AwareDatetime = Field(
        ...,
        alias='startedAt',
        description='Timestamp when the session was created and started',
        title='Started At',
    )
    finished_at: AwareDatetime | None = Field(
        None,
        alias='finishedAt',
        description='Timestamp when the session was stopped (None if still active)',
        title='Finished At',
    )
    proxy_used_mb: str | None = Field(
        '0',
        alias='proxyUsedMb',
        description='Amount of proxy data used in MB',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxy Used MB',
    )
    proxy_cost: str | None = Field(
        '0',
        alias='proxyCost',
        description='Cost of proxy usage in USD',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Proxy Cost',
    )
    browser_cost: str | None = Field(
        '0',
        alias='browserCost',
        description='Cost of browser session hosting in USD',
        pattern='^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$',
        title='Browser Cost',
    )
    agent_session_id: UUID | None = Field(
        None,
        alias='agentSessionId',
        description='ID of the agent session that created this browser (None for standalone BaaS sessions)',
        title='Agent Session ID',
    )
    recording_url: str | None = Field(
        None,
        alias='recordingUrl',
        description='Presigned URL to download the session recording (available after session ends, if recording was enabled)',
        title='Recording URL',
    )


class BrowserSessionListResponse(BaseModel):
    items: List[BrowserSessionItemView] = Field(
        ...,
        description='List of browser session views for the current page',
        title='Items',
    )
    total_items: int = Field(
        ...,
        alias='totalItems',
        description='Total number of items in the list',
        title='Total Items',
    )
    page_number: int = Field(
        ..., alias='pageNumber', description='Page number', title='Page Number'
    )
    page_size: int = Field(
        ..., alias='pageSize', description='Number of items per page', title='Page Size'
    )


class CreateBrowserSessionRequest(BaseModel):
    profile_id: UUID | None = Field(
        None,
        alias='profileId',
        description='The ID of the profile to use for the session',
        title='Profile ID',
    )
    proxy_country_code: ProxyCountryCode | None = Field(
        ProxyCountryCode.us,
        alias='proxyCountryCode',
        description='Country code for proxy location. Defaults to US. Set to null to disable proxy.',
        title='Proxy Country Code',
    )
    timeout: int | None = Field(
        60,
        description='The timeout for the session in minutes. All users can use up to 240 minutes (4 hours). Pay As You Go users are charged $0.06/hour, subscribers get 50% off.',
        title='Timeout',
    )
    browser_screen_width: BrowserScreenWidth | None = Field(
        None,
        alias='browserScreenWidth',
        description='Custom screen width in pixels for the browser.',
        title='Browser Screen Width',
    )
    browser_screen_height: BrowserScreenHeight | None = Field(
        None,
        alias='browserScreenHeight',
        description='Custom screen height in pixels for the browser.',
        title='Browser Screen Height',
    )
    allow_resizing: bool | None = Field(
        False,
        alias='allowResizing',
        description='Whether to allow the browser to be resized during the session (not recommended since it reduces stealthiness).',
        title='Allow Resizing',
    )
    custom_proxy: CustomProxy | None = Field(
        None,
        alias='customProxy',
        description='Custom proxy settings to use for the session. If not provided, our proxies will be used. Custom proxies are available on any active subscription.',
        title='Custom Proxy',
    )
    enable_recording: bool | None = Field(
        False,
        alias='enableRecording',
        description='If True, enables session recording. Defaults to False.',
        title='Enable Recording',
    )


class FileUploadResponse(BaseModel):
    files: List[FileUploadResponseItem] = Field(..., title='Files')


class HTTPValidationError(BaseModel):
    detail: List[ValidationError] | None = Field(None, title='Detail')


class MessageListResponse(BaseModel):
    messages: List[MessageResponse] = Field(
        ..., description='List of messages in chronological order.', title='Messages'
    )
    has_more: bool = Field(
        ...,
        alias='hasMore',
        description='Whether there are more messages available beyond this page. Use cursor-based pagination with the `after` or `before` query parameters to fetch more.',
        title='Hasmore',
    )


class ProfileListResponse(BaseModel):
    items: List[ProfileView] = Field(
        ..., description='List of profile views for the current page', title='Items'
    )
    total_items: int = Field(
        ...,
        alias='totalItems',
        description='Total number of items in the list',
        title='Total Items',
    )
    page_number: int = Field(
        ..., alias='pageNumber', description='Page number', title='Page Number'
    )
    page_size: int = Field(
        ..., alias='pageSize', description='Number of items per page', title='Page Size'
    )


class SessionListResponse(BaseModel):
    sessions: List[SessionResponse] = Field(
        ..., description='List of sessions.', title='Sessions'
    )
    total: int = Field(
        ..., description='Total number of sessions matching the query.', title='Total'
    )
    page: int = Field(..., description='Current page number (1-indexed).', title='Page')
    page_size: int = Field(
        ...,
        alias='pageSize',
        description='Number of sessions per page.',
        title='Pagesize',
    )


class StopSessionRequest(BaseModel):
    strategy: StopStrategy | None = Field(
        StopStrategy.session,
        description='How to stop the session. Use "task" to stop only the current task and keep the session alive, or "session" to destroy the sandbox entirely.',
    )


class WorkspaceListResponse(BaseModel):
    items: List[WorkspaceView] = Field(
        ..., description='List of workspace views for the current page', title='Items'
    )
    total_items: int = Field(
        ...,
        alias='totalItems',
        description='Total number of items in the list',
        title='Total Items',
    )
    page_number: int = Field(
        ..., alias='pageNumber', description='Page number', title='Page Number'
    )
    page_size: int = Field(
        ..., alias='pageSize', description='Number of items per page', title='Page Size'
    )
