agent-zero/plugins/_browser_agent/webui/main.html
Alessandro d30a565549 browser-agent: selectable _model_config preset for browser runs
This PR keeps the Browser Agent runtime behavior as-is and only adds in the model-preset option for browser runs (highly requested by our users).

The Browser Agent can now use either:
- the effective Main Model from `_model_config`, or
- one saved `_model_config` preset dedicated to browser tasks

- this PR brings back LLM customization for Browser Agent plugin, but without over engineering. Model presets-only, not custom provider + LLM, like we have in Email Integration.
- created a separate `browser-agent-store.js` page store to remove JS from within x-data in the HTML markup of main.html
2026-04-12 03:38:41 +02:00

239 lines
8.8 KiB
HTML

<html>
<head>
<title>Browser Agent</title>
<script type="module">
import { store } from "/plugins/_browser_agent/webui/browser-agent-store.js";
</script>
</head>
<body>
<div x-data>
<template x-if="$store.browserAgentPage">
<div
x-create="$store.browserAgentPage.onOpen()"
x-destroy="$store.browserAgentPage.cleanup()"
class="browser-agent-page"
>
<div class="section-title">Browser Agent</div>
<div class="section-description">
Built-in browser automation plugin backed by `browser-use` and Playwright.
Model selection stays in `_model_config`; the browser agent can follow the effective Main Model or use one saved preset just for browser tasks.
</div>
<div class="browser-agent-card" x-show="$store.browserAgentPage.loading">
<div class="status-row">
<span class="material-symbols-outlined spinning">progress_activity</span>
<span>Loading browser status...</span>
</div>
</div>
<div class="browser-agent-card error" x-show="!$store.browserAgentPage.loading && $store.browserAgentPage.error">
<div class="field-title">Status check failed</div>
<div class="field-description" x-text="$store.browserAgentPage.error"></div>
</div>
<template x-if="!$store.browserAgentPage.loading && $store.browserAgentPage.status">
<div class="browser-agent-grid">
<div class="browser-agent-card">
<div class="field-title">Model Source</div>
<div class="field-description" x-text="$store.browserAgentPage.status.model_source"></div>
<div class="field-description" x-show="$store.browserAgentPage.status.preset_warning" x-text="$store.browserAgentPage.status.preset_warning"></div>
</div>
<div class="browser-agent-card">
<div class="field-title">Resolved Browser Model</div>
<div class="status-row">
<span class="status-key">Provider</span>
<span class="status-value" x-text="$store.browserAgentPage.status.model.provider || 'Not configured'"></span>
</div>
<div class="status-row">
<span class="status-key">Model</span>
<span class="status-value" x-text="$store.browserAgentPage.status.model.name || 'Not configured'"></span>
</div>
<div class="status-row">
<span class="status-key">Vision</span>
<span class="status-badge" :class="$store.browserAgentPage.status.model.vision ? 'ok' : 'warn'" x-text="$store.browserAgentPage.status.model.vision ? 'Enabled' : 'Disabled'"></span>
</div>
</div>
<div class="browser-agent-card">
<div class="field-title">Browser Model Preset</div>
<div class="field-description">
Pick an optional `_model_config` preset for browser-only runs. Leave it empty to keep using the effective Main Model.
</div>
<label class="browser-agent-select-label" for="browser-agent-preset-select">Preset</label>
<select
id="browser-agent-preset-select"
class="browser-agent-select"
:disabled="$store.browserAgentPage.savingPreset"
x-model="$store.browserAgentPage.status.selected_preset_name"
@change="$store.browserAgentPage.savePreset($store.browserAgentPage.status.selected_preset_name)"
>
<option value="">Use Main Model</option>
<template x-for="preset in $store.browserAgentPage.status.available_presets" :key="preset.name">
<option :value="preset.name" x-text="preset.label"></option>
</template>
</select>
<div class="field-description" x-show="$store.browserAgentPage.savingPreset">Saving browser preset...</div>
</div>
<div class="browser-agent-card">
<div class="field-title">Playwright Runtime</div>
<div class="status-row">
<span class="status-key">Binary</span>
<span class="status-badge" :class="$store.browserAgentPage.status.playwright.binary_found ? 'ok' : 'fail'" x-text="$store.browserAgentPage.status.playwright.binary_found ? 'Found' : 'Missing'"></span>
</div>
<div class="status-row">
<span class="status-key">Cache</span>
<span class="status-value mono" x-text="$store.browserAgentPage.status.playwright.cache_dir"></span>
</div>
<div class="status-row" x-show="$store.browserAgentPage.status.playwright.binary_path">
<span class="status-key">Path</span>
<span class="status-value mono" x-text="$store.browserAgentPage.status.playwright.binary_path"></span>
</div>
<div class="field-description" x-show="!$store.browserAgentPage.status.playwright.binary_found">
Docker images ship the Playwright Chromium shell preinstalled. In local development, the first run installs it on demand via <span class="mono">ensure_playwright_binary()</span> if missing.
</div>
</div>
<div class="browser-agent-card">
<div class="field-title">browser-use</div>
<div class="status-row">
<span class="status-key">Import</span>
<span class="status-badge" :class="$store.browserAgentPage.status.browser_use.import_ok ? 'ok' : 'fail'" x-text="$store.browserAgentPage.status.browser_use.import_ok ? 'Ready' : 'Error'"></span>
</div>
<div class="status-row" x-show="$store.browserAgentPage.status.browser_use.version">
<span class="status-key">Version</span>
<span class="status-value" x-text="$store.browserAgentPage.status.browser_use.version"></span>
</div>
<div class="field-description mono" x-show="$store.browserAgentPage.status.browser_use.error" x-text="$store.browserAgentPage.status.browser_use.error"></div>
</div>
</div>
</template>
<div class="browser-agent-actions">
<button
class="btn btn-field"
@click="$store.browserAgentPage.openModelSettings()"
>
Open Model Settings
</button>
<button class="btn btn-field" @click="openModal('/plugins/_model_config/webui/main.html')">
Open Presets
</button>
<button class="btn btn-field" @click="openModal('/plugins/_model_config/webui/api-keys.html')">
Open API Keys
</button>
</div>
</div>
</template>
</div>
<style>
.browser-agent-page {
display: flex;
flex-direction: column;
gap: 14px;
}
.browser-agent-grid {
display: grid;
gap: 12px;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.browser-agent-card {
display: flex;
flex-direction: column;
gap: 10px;
padding: 14px;
background: var(--color-input);
border: 1px solid var(--color-border);
border-radius: 10px;
}
.browser-agent-card.error {
border-color: rgba(214, 40, 40, 0.35);
}
.browser-agent-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.browser-agent-select-label {
font-size: 0.78rem;
opacity: 0.75;
}
.browser-agent-select {
width: 100%;
min-height: 36px;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid var(--color-border);
background: var(--color-bg);
color: var(--color-text);
}
.browser-agent-select:disabled {
opacity: 0.7;
cursor: wait;
}
.status-row {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
font-size: 0.84rem;
}
.status-key {
opacity: 0.7;
min-width: 64px;
}
.status-value {
text-align: right;
word-break: break-word;
}
.status-badge {
padding: 2px 8px;
border-radius: 999px;
font-size: 0.76rem;
font-weight: 600;
border: 1px solid transparent;
}
.status-badge.ok {
color: #1b5e20;
background: rgba(46, 125, 50, 0.14);
border-color: rgba(46, 125, 50, 0.24);
}
.status-badge.warn {
color: #8a6100;
background: rgba(191, 144, 0, 0.14);
border-color: rgba(191, 144, 0, 0.24);
}
.status-badge.fail {
color: #9f1239;
background: rgba(190, 24, 93, 0.12);
border-color: rgba(190, 24, 93, 0.24);
}
.mono {
font-family: var(--font-mono);
font-size: 0.78rem;
}
option {
background: var(--color-input);
color: var(--color-text);
}
</style>
</body>
</html>