@agenticmail/enterprise 0.5.79 → 0.5.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4F3OU3JP.js +898 -0
- package/dist/chunk-7MILGDAA.js +2191 -0
- package/dist/chunk-BTSK5YLA.js +15035 -0
- package/dist/chunk-GWUIYH7I.js +15035 -0
- package/dist/chunk-WRPZCOWC.js +898 -0
- package/dist/chunk-XE6U6O6I.js +2191 -0
- package/dist/cli.js +1 -1
- package/dist/dashboard/pages/agent-detail.js +466 -98
- package/dist/index.js +3 -4
- package/dist/routes-YPPF3NE7.js +6759 -0
- package/dist/runtime-GYVO3NF3.js +47 -0
- package/dist/runtime-YCSAKNM7.js +47 -0
- package/dist/server-VNW6G4GB.js +12 -0
- package/dist/server-YEI32L2Q.js +12 -0
- package/dist/setup-AANLREEL.js +20 -0
- package/dist/setup-CEXMJIEB.js +20 -0
- package/package.json +1 -1
- package/src/agent-tools/index.ts +3 -2
- package/src/dashboard/pages/agent-detail.js +466 -98
- package/src/engine/agent-routes.ts +93 -0
|
@@ -3993,12 +3993,14 @@ function BrowserConfigCard(props) {
|
|
|
3993
3993
|
var _d = useApp(); var toast = _d.toast;
|
|
3994
3994
|
var _cfg = useState(null); var cfg = _cfg[0]; var setCfg = _cfg[1];
|
|
3995
3995
|
var _saving = useState(false); var saving = _saving[0]; var setSaving = _saving[1];
|
|
3996
|
-
var
|
|
3996
|
+
var _testing = useState(false); var testing = _testing[0]; var setTesting = _testing[1];
|
|
3997
|
+
var _testResult = useState(null); var testResult = _testResult[0]; var setTestResult = _testResult[1];
|
|
3998
|
+
var _collapsed = useState(false); var collapsed = _collapsed[0]; var setCollapsed = _collapsed[1];
|
|
3997
3999
|
|
|
3998
4000
|
function load() {
|
|
3999
4001
|
engineCall('/bridge/agents/' + agentId + '/browser-config')
|
|
4000
|
-
.then(function(d) { setCfg(d.config || {}); })
|
|
4001
|
-
.catch(function() { setCfg({}); });
|
|
4002
|
+
.then(function(d) { setCfg(d.config || { provider: 'local' }); })
|
|
4003
|
+
.catch(function() { setCfg({ provider: 'local' }); });
|
|
4002
4004
|
}
|
|
4003
4005
|
|
|
4004
4006
|
useEffect(function() { load(); }, [agentId]);
|
|
@@ -4012,14 +4014,37 @@ function BrowserConfigCard(props) {
|
|
|
4012
4014
|
.catch(function(e) { toast(e.message, 'error'); setSaving(false); });
|
|
4013
4015
|
}
|
|
4014
4016
|
|
|
4017
|
+
function testConnection() {
|
|
4018
|
+
setTesting(true); setTestResult(null);
|
|
4019
|
+
engineCall('/bridge/agents/' + agentId + '/browser-config/test', { method: 'POST' })
|
|
4020
|
+
.then(function(d) { setTestResult(d); setTesting(false); })
|
|
4021
|
+
.catch(function(e) { setTestResult({ error: e.message }); setTesting(false); });
|
|
4022
|
+
}
|
|
4023
|
+
|
|
4015
4024
|
function update(key, value) {
|
|
4016
4025
|
setCfg(function(prev) { var n = Object.assign({}, prev); n[key] = value; return n; });
|
|
4017
4026
|
}
|
|
4018
4027
|
|
|
4019
4028
|
if (!cfg) return null;
|
|
4020
4029
|
|
|
4030
|
+
var provider = cfg.provider || 'local';
|
|
4021
4031
|
var labelStyle = { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 };
|
|
4022
4032
|
var helpStyle = { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 };
|
|
4033
|
+
var sectionStyle = { padding: '12px 0', borderBottom: '1px solid var(--border)' };
|
|
4034
|
+
var sectionTitle = function(icon, text) {
|
|
4035
|
+
return h('div', { style: { fontSize: 13, fontWeight: 600, color: 'var(--text-primary)', marginBottom: 12, display: 'flex', alignItems: 'center', gap: 6 } },
|
|
4036
|
+
h('span', null, icon), text);
|
|
4037
|
+
};
|
|
4038
|
+
|
|
4039
|
+
// Provider descriptions
|
|
4040
|
+
var providers = [
|
|
4041
|
+
{ id: 'local', name: 'Local Chromium', icon: '\uD83D\uDCBB', desc: 'Built-in headless Chromium on this server. Best for web automation, scraping, screenshots, form filling.' },
|
|
4042
|
+
{ id: 'remote-cdp', name: 'Remote Browser (CDP)', icon: '\uD83C\uDF10', desc: 'Connect to a Chrome/Chromium instance via Chrome DevTools Protocol. Required for headed mode, video calls, persistent sessions.' },
|
|
4043
|
+
{ id: 'browserless', name: 'Browserless.io', icon: '\u2601\uFE0F', desc: 'Cloud browser service. Scalable, managed infrastructure. Supports stealth mode, residential proxies, and concurrent sessions.' },
|
|
4044
|
+
{ id: 'browserbase', name: 'Browserbase', icon: '\uD83D\uDE80', desc: 'AI-native cloud browser. Built for agent automation with session replay, anti-detection, and managed infrastructure.' },
|
|
4045
|
+
{ id: 'steel', name: 'Steel.dev', icon: '\u26A1', desc: 'Open-source browser API designed for AI agents. Self-hostable, session management, built-in stealth.' },
|
|
4046
|
+
{ id: 'scrapingbee', name: 'ScrapingBee', icon: '\uD83D\uDC1D', desc: 'Web scraping API with browser rendering, proxy rotation, and CAPTCHA solving.' },
|
|
4047
|
+
];
|
|
4023
4048
|
|
|
4024
4049
|
return h('div', { className: 'card', style: { marginTop: 16 } },
|
|
4025
4050
|
h('div', {
|
|
@@ -4027,118 +4052,461 @@ function BrowserConfigCard(props) {
|
|
|
4027
4052
|
style: { cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'space-between' },
|
|
4028
4053
|
onClick: function() { setCollapsed(!collapsed); }
|
|
4029
4054
|
},
|
|
4030
|
-
h('span',
|
|
4055
|
+
h('span', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
4056
|
+
'\uD83C\uDF10 Browser & Web Automation',
|
|
4057
|
+
cfg.provider && cfg.provider !== 'local' && h('span', { className: 'badge', style: { fontSize: 10, padding: '1px 6px', background: 'var(--accent-soft)', color: 'var(--accent)' } },
|
|
4058
|
+
providers.find(function(p) { return p.id === cfg.provider; })?.name || cfg.provider
|
|
4059
|
+
)
|
|
4060
|
+
),
|
|
4031
4061
|
h('span', { style: { fontSize: 12, color: 'var(--text-muted)' } }, collapsed ? '\u25BC' : '\u25B2')
|
|
4032
4062
|
),
|
|
4033
|
-
!collapsed && h('div', { style: { padding: 16
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4063
|
+
!collapsed && h('div', { style: { padding: 16 } },
|
|
4064
|
+
|
|
4065
|
+
// ─── Section 1: Browser Provider ─────────────────
|
|
4066
|
+
h('div', { style: sectionStyle },
|
|
4067
|
+
sectionTitle('\uD83D\uDD27', 'Browser Provider'),
|
|
4068
|
+
h('div', { style: { display: 'grid', gap: 8, gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))' } },
|
|
4069
|
+
providers.map(function(p) {
|
|
4070
|
+
var selected = provider === p.id;
|
|
4071
|
+
return h('div', {
|
|
4072
|
+
key: p.id,
|
|
4073
|
+
onClick: function() { update('provider', p.id); },
|
|
4074
|
+
style: {
|
|
4075
|
+
padding: '12px 14px', borderRadius: 'var(--radius)', cursor: 'pointer',
|
|
4076
|
+
border: '2px solid ' + (selected ? 'var(--accent)' : 'var(--border)'),
|
|
4077
|
+
background: selected ? 'var(--accent-soft)' : 'var(--bg-secondary)',
|
|
4078
|
+
transition: 'all 0.15s',
|
|
4079
|
+
}
|
|
4080
|
+
},
|
|
4081
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 } },
|
|
4082
|
+
h('span', { style: { fontSize: 18 } }, p.icon),
|
|
4083
|
+
h('span', { style: { fontWeight: 600, fontSize: 13 } }, p.name),
|
|
4084
|
+
selected && h('span', { style: { marginLeft: 'auto', color: 'var(--accent)', fontSize: 14 } }, '\u2713')
|
|
4085
|
+
),
|
|
4086
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', lineHeight: 1.4 } }, p.desc)
|
|
4087
|
+
);
|
|
4088
|
+
})
|
|
4089
|
+
)
|
|
4045
4090
|
),
|
|
4046
4091
|
|
|
4047
|
-
//
|
|
4048
|
-
h('div', {
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4092
|
+
// ─── Section 2: Provider-Specific Config ─────────
|
|
4093
|
+
h('div', { style: sectionStyle },
|
|
4094
|
+
|
|
4095
|
+
// Local Chromium
|
|
4096
|
+
provider === 'local' && h(Fragment, null,
|
|
4097
|
+
sectionTitle('\uD83D\uDCBB', 'Local Chromium Settings'),
|
|
4098
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4099
|
+
h('div', { className: 'form-group' },
|
|
4100
|
+
h('label', { style: labelStyle }, 'Display Mode'),
|
|
4101
|
+
h('select', { className: 'input', value: cfg.headless !== false ? 'true' : 'false',
|
|
4102
|
+
onChange: function(e) { update('headless', e.target.value === 'true'); }
|
|
4103
|
+
},
|
|
4104
|
+
h('option', { value: 'true' }, 'Headless (no window)'),
|
|
4105
|
+
h('option', { value: 'false' }, 'Headed (visible window)')
|
|
4106
|
+
),
|
|
4107
|
+
h('div', { style: helpStyle }, 'Headed mode requires a display server (X11/Wayland).')
|
|
4108
|
+
),
|
|
4109
|
+
h('div', { className: 'form-group' },
|
|
4110
|
+
h('label', { style: labelStyle }, 'Executable Path'),
|
|
4111
|
+
h('input', { className: 'input', placeholder: 'Auto-detect (recommended)',
|
|
4112
|
+
value: cfg.executablePath || '',
|
|
4113
|
+
onChange: function(e) { update('executablePath', e.target.value || undefined); }
|
|
4114
|
+
}),
|
|
4115
|
+
h('div', { style: helpStyle }, 'Leave empty to use bundled Chromium.')
|
|
4116
|
+
),
|
|
4117
|
+
h('div', { className: 'form-group' },
|
|
4118
|
+
h('label', { style: labelStyle }, 'User Data Directory'),
|
|
4119
|
+
h('input', { className: 'input', placeholder: 'Temporary (new profile each session)',
|
|
4120
|
+
value: cfg.userDataDir || '',
|
|
4121
|
+
onChange: function(e) { update('userDataDir', e.target.value || undefined); }
|
|
4122
|
+
}),
|
|
4123
|
+
h('div', { style: helpStyle }, 'Persist cookies, logins, and extensions across sessions.')
|
|
4124
|
+
),
|
|
4125
|
+
h('div', { className: 'form-group' },
|
|
4126
|
+
h('label', { style: labelStyle }, 'Extra Chrome Args'),
|
|
4127
|
+
h('input', { className: 'input', placeholder: '--no-sandbox, --disable-gpu',
|
|
4128
|
+
value: (cfg.extraArgs || []).join(', '),
|
|
4129
|
+
onChange: function(e) { update('extraArgs', e.target.value.split(',').map(function(s) { return s.trim(); }).filter(Boolean)); }
|
|
4130
|
+
}),
|
|
4131
|
+
h('div', { style: helpStyle }, 'Additional Chromium launch arguments.')
|
|
4132
|
+
)
|
|
4133
|
+
)
|
|
4057
4134
|
),
|
|
4058
|
-
h('div', { style: helpStyle }, 'Controls which URLs the agent can navigate to.')
|
|
4059
|
-
),
|
|
4060
4135
|
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4136
|
+
// Remote CDP
|
|
4137
|
+
provider === 'remote-cdp' && h(Fragment, null,
|
|
4138
|
+
sectionTitle('\uD83C\uDF10', 'Remote Browser Connection'),
|
|
4139
|
+
h('div', { style: { padding: '10px 14px', background: 'var(--info-soft)', borderRadius: 'var(--radius)', marginBottom: 12, fontSize: 12, lineHeight: 1.5 } },
|
|
4140
|
+
h('strong', null, 'How it works: '),
|
|
4141
|
+
'The agent connects to a Chrome/Chromium browser running on another machine via the Chrome DevTools Protocol (CDP). ',
|
|
4142
|
+
'This is required for video calls (Google Meet, Teams, Zoom) where the browser needs a camera, microphone, and display. ',
|
|
4143
|
+
h('br', null), h('br', null),
|
|
4144
|
+
h('strong', null, 'Setup options:'), h('br', null),
|
|
4145
|
+
'\u2022 Run Chrome with --remote-debugging-port=9222 on a VM/desktop', h('br', null),
|
|
4146
|
+
'\u2022 Use a cloud desktop (AWS WorkSpaces, Azure Virtual Desktop, Hetzner)', h('br', null),
|
|
4147
|
+
'\u2022 Set up a dedicated browser VM with virtual camera/audio for meetings', h('br', null),
|
|
4148
|
+
'\u2022 Use SSH tunneling to expose Chrome DevTools securely'
|
|
4149
|
+
),
|
|
4150
|
+
h('div', { style: { display: 'grid', gap: 12 } },
|
|
4151
|
+
h('div', { className: 'form-group' },
|
|
4152
|
+
h('label', { style: labelStyle }, 'CDP WebSocket URL *'),
|
|
4153
|
+
h('input', { className: 'input', placeholder: 'ws://192.168.1.100:9222/devtools/browser/...',
|
|
4154
|
+
value: cfg.cdpUrl || '',
|
|
4155
|
+
onChange: function(e) { update('cdpUrl', e.target.value); }
|
|
4156
|
+
}),
|
|
4157
|
+
h('div', { style: helpStyle }, 'WebSocket URL from chrome://inspect or --remote-debugging-port output. Format: ws://host:port/devtools/browser/<id>')
|
|
4158
|
+
),
|
|
4159
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4160
|
+
h('div', { className: 'form-group' },
|
|
4161
|
+
h('label', { style: labelStyle }, 'Auth Token'),
|
|
4162
|
+
h('input', { className: 'input', type: 'password', placeholder: 'Optional — for authenticated CDP endpoints',
|
|
4163
|
+
value: cfg.cdpAuthToken || '',
|
|
4164
|
+
onChange: function(e) { update('cdpAuthToken', e.target.value || undefined); }
|
|
4165
|
+
})
|
|
4166
|
+
),
|
|
4167
|
+
h('div', { className: 'form-group' },
|
|
4168
|
+
h('label', { style: labelStyle }, 'Connection Timeout (ms)'),
|
|
4169
|
+
h('input', { className: 'input', type: 'number', min: 5000, max: 60000,
|
|
4170
|
+
value: cfg.cdpTimeout || 30000,
|
|
4171
|
+
onChange: function(e) { update('cdpTimeout', parseInt(e.target.value) || 30000); }
|
|
4172
|
+
})
|
|
4173
|
+
)
|
|
4174
|
+
),
|
|
4175
|
+
h('div', { className: 'form-group' },
|
|
4176
|
+
h('label', { style: labelStyle }, 'SSH Tunnel (auto-connect)'),
|
|
4177
|
+
h('input', { className: 'input', placeholder: 'ssh -L 9222:localhost:9222 user@remote-host (optional)',
|
|
4178
|
+
value: cfg.sshTunnel || '',
|
|
4179
|
+
onChange: function(e) { update('sshTunnel', e.target.value || undefined); }
|
|
4180
|
+
}),
|
|
4181
|
+
h('div', { style: helpStyle }, 'SSH command to establish tunnel before connecting. Agent will run this automatically.')
|
|
4182
|
+
)
|
|
4183
|
+
)
|
|
4184
|
+
),
|
|
4072
4185
|
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4186
|
+
// Browserless
|
|
4187
|
+
provider === 'browserless' && h(Fragment, null,
|
|
4188
|
+
sectionTitle('\u2601\uFE0F', 'Browserless.io Configuration'),
|
|
4189
|
+
h('div', { style: { display: 'grid', gap: 12 } },
|
|
4190
|
+
h('div', { className: 'form-group' },
|
|
4191
|
+
h('label', { style: labelStyle }, 'API Token *'),
|
|
4192
|
+
h('input', { className: 'input', type: 'password', placeholder: 'Your Browserless API token',
|
|
4193
|
+
value: cfg.browserlessToken || '',
|
|
4194
|
+
onChange: function(e) { update('browserlessToken', e.target.value); }
|
|
4195
|
+
}),
|
|
4196
|
+
h('div', { style: helpStyle }, h('a', { href: 'https://www.browserless.io/dashboard', target: '_blank', style: { color: 'var(--accent)' } }, 'Get your API token'), ' from the Browserless dashboard.')
|
|
4197
|
+
),
|
|
4198
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4199
|
+
h('div', { className: 'form-group' },
|
|
4200
|
+
h('label', { style: labelStyle }, 'Endpoint'),
|
|
4201
|
+
h('input', { className: 'input', placeholder: 'wss://chrome.browserless.io (default)',
|
|
4202
|
+
value: cfg.browserlessEndpoint || '',
|
|
4203
|
+
onChange: function(e) { update('browserlessEndpoint', e.target.value || undefined); }
|
|
4204
|
+
}),
|
|
4205
|
+
h('div', { style: helpStyle }, 'Custom endpoint for self-hosted or enterprise plans.')
|
|
4206
|
+
),
|
|
4207
|
+
h('div', { className: 'form-group' },
|
|
4208
|
+
h('label', { style: labelStyle }, 'Concurrent Sessions'),
|
|
4209
|
+
h('input', { className: 'input', type: 'number', min: 1, max: 100,
|
|
4210
|
+
value: cfg.browserlessConcurrency || 5,
|
|
4211
|
+
onChange: function(e) { update('browserlessConcurrency', parseInt(e.target.value) || 5); }
|
|
4212
|
+
})
|
|
4213
|
+
)
|
|
4214
|
+
),
|
|
4215
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4216
|
+
h('div', { className: 'form-group' },
|
|
4217
|
+
h('label', { style: labelStyle }, 'Stealth Mode'),
|
|
4218
|
+
h('select', { className: 'input', value: cfg.browserlessStealth ? 'true' : 'false',
|
|
4219
|
+
onChange: function(e) { update('browserlessStealth', e.target.value === 'true'); }
|
|
4220
|
+
},
|
|
4221
|
+
h('option', { value: 'false' }, 'Off'),
|
|
4222
|
+
h('option', { value: 'true' }, 'On — Evade bot detection')
|
|
4223
|
+
)
|
|
4224
|
+
),
|
|
4225
|
+
h('div', { className: 'form-group' },
|
|
4226
|
+
h('label', { style: labelStyle }, 'Proxy'),
|
|
4227
|
+
h('input', { className: 'input', placeholder: 'Optional proxy URL',
|
|
4228
|
+
value: cfg.browserlessProxy || '',
|
|
4229
|
+
onChange: function(e) { update('browserlessProxy', e.target.value || undefined); }
|
|
4230
|
+
})
|
|
4231
|
+
)
|
|
4232
|
+
)
|
|
4233
|
+
)
|
|
4234
|
+
),
|
|
4084
4235
|
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4236
|
+
// Browserbase
|
|
4237
|
+
provider === 'browserbase' && h(Fragment, null,
|
|
4238
|
+
sectionTitle('\uD83D\uDE80', 'Browserbase Configuration'),
|
|
4239
|
+
h('div', { style: { display: 'grid', gap: 12 } },
|
|
4240
|
+
h('div', { className: 'form-group' },
|
|
4241
|
+
h('label', { style: labelStyle }, 'API Key *'),
|
|
4242
|
+
h('input', { className: 'input', type: 'password', placeholder: 'Your Browserbase API key',
|
|
4243
|
+
value: cfg.browserbaseApiKey || '',
|
|
4244
|
+
onChange: function(e) { update('browserbaseApiKey', e.target.value); }
|
|
4245
|
+
}),
|
|
4246
|
+
h('div', { style: helpStyle }, h('a', { href: 'https://www.browserbase.com/settings', target: '_blank', style: { color: 'var(--accent)' } }, 'Get your API key'), ' from Browserbase settings.')
|
|
4247
|
+
),
|
|
4248
|
+
h('div', { className: 'form-group' },
|
|
4249
|
+
h('label', { style: labelStyle }, 'Project ID *'),
|
|
4250
|
+
h('input', { className: 'input', placeholder: 'Your Browserbase project ID',
|
|
4251
|
+
value: cfg.browserbaseProjectId || '',
|
|
4252
|
+
onChange: function(e) { update('browserbaseProjectId', e.target.value); }
|
|
4253
|
+
})
|
|
4254
|
+
),
|
|
4255
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4256
|
+
h('div', { className: 'form-group' },
|
|
4257
|
+
h('label', { style: labelStyle }, 'Session Recording'),
|
|
4258
|
+
h('select', { className: 'input', value: cfg.browserbaseRecording !== false ? 'true' : 'false',
|
|
4259
|
+
onChange: function(e) { update('browserbaseRecording', e.target.value === 'true'); }
|
|
4260
|
+
},
|
|
4261
|
+
h('option', { value: 'true' }, 'Enabled — Record sessions for replay'),
|
|
4262
|
+
h('option', { value: 'false' }, 'Disabled')
|
|
4263
|
+
)
|
|
4264
|
+
),
|
|
4265
|
+
h('div', { className: 'form-group' },
|
|
4266
|
+
h('label', { style: labelStyle }, 'Keep Session Alive'),
|
|
4267
|
+
h('select', { className: 'input', value: cfg.browserbaseKeepAlive ? 'true' : 'false',
|
|
4268
|
+
onChange: function(e) { update('browserbaseKeepAlive', e.target.value === 'true'); }
|
|
4269
|
+
},
|
|
4270
|
+
h('option', { value: 'false' }, 'Close after task'),
|
|
4271
|
+
h('option', { value: 'true' }, 'Keep alive for reuse')
|
|
4272
|
+
)
|
|
4273
|
+
)
|
|
4274
|
+
)
|
|
4275
|
+
)
|
|
4276
|
+
),
|
|
4095
4277
|
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4278
|
+
// Steel
|
|
4279
|
+
provider === 'steel' && h(Fragment, null,
|
|
4280
|
+
sectionTitle('\u26A1', 'Steel.dev Configuration'),
|
|
4281
|
+
h('div', { style: { display: 'grid', gap: 12 } },
|
|
4282
|
+
h('div', { className: 'form-group' },
|
|
4283
|
+
h('label', { style: labelStyle }, 'API Key *'),
|
|
4284
|
+
h('input', { className: 'input', type: 'password', placeholder: 'Your Steel API key',
|
|
4285
|
+
value: cfg.steelApiKey || '',
|
|
4286
|
+
onChange: function(e) { update('steelApiKey', e.target.value); }
|
|
4287
|
+
}),
|
|
4288
|
+
h('div', { style: helpStyle }, h('a', { href: 'https://app.steel.dev', target: '_blank', style: { color: 'var(--accent)' } }, 'Get your API key'), ' — or self-host Steel for free.')
|
|
4289
|
+
),
|
|
4290
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4291
|
+
h('div', { className: 'form-group' },
|
|
4292
|
+
h('label', { style: labelStyle }, 'Endpoint'),
|
|
4293
|
+
h('input', { className: 'input', placeholder: 'https://api.steel.dev (default)',
|
|
4294
|
+
value: cfg.steelEndpoint || '',
|
|
4295
|
+
onChange: function(e) { update('steelEndpoint', e.target.value || undefined); }
|
|
4296
|
+
})
|
|
4297
|
+
),
|
|
4298
|
+
h('div', { className: 'form-group' },
|
|
4299
|
+
h('label', { style: labelStyle }, 'Session Duration (min)'),
|
|
4300
|
+
h('input', { className: 'input', type: 'number', min: 1, max: 120,
|
|
4301
|
+
value: cfg.steelSessionDuration || 15,
|
|
4302
|
+
onChange: function(e) { update('steelSessionDuration', parseInt(e.target.value) || 15); }
|
|
4303
|
+
})
|
|
4304
|
+
)
|
|
4305
|
+
)
|
|
4306
|
+
)
|
|
4307
|
+
),
|
|
4308
|
+
|
|
4309
|
+
// ScrapingBee
|
|
4310
|
+
provider === 'scrapingbee' && h(Fragment, null,
|
|
4311
|
+
sectionTitle('\uD83D\uDC1D', 'ScrapingBee Configuration'),
|
|
4312
|
+
h('div', { style: { display: 'grid', gap: 12 } },
|
|
4313
|
+
h('div', { className: 'form-group' },
|
|
4314
|
+
h('label', { style: labelStyle }, 'API Key *'),
|
|
4315
|
+
h('input', { className: 'input', type: 'password', placeholder: 'Your ScrapingBee API key',
|
|
4316
|
+
value: cfg.scrapingbeeApiKey || '',
|
|
4317
|
+
onChange: function(e) { update('scrapingbeeApiKey', e.target.value); }
|
|
4318
|
+
}),
|
|
4319
|
+
h('div', { style: helpStyle }, h('a', { href: 'https://www.scrapingbee.com/dashboard', target: '_blank', style: { color: 'var(--accent)' } }, 'Get your API key'), ' from ScrapingBee dashboard.')
|
|
4320
|
+
),
|
|
4321
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr 1fr' } },
|
|
4322
|
+
h('div', { className: 'form-group' },
|
|
4323
|
+
h('label', { style: labelStyle }, 'JavaScript Rendering'),
|
|
4324
|
+
h('select', { className: 'input', value: cfg.scrapingbeeJsRendering !== false ? 'true' : 'false',
|
|
4325
|
+
onChange: function(e) { update('scrapingbeeJsRendering', e.target.value === 'true'); }
|
|
4326
|
+
},
|
|
4327
|
+
h('option', { value: 'true' }, 'Enabled'),
|
|
4328
|
+
h('option', { value: 'false' }, 'Disabled (faster)')
|
|
4329
|
+
)
|
|
4330
|
+
),
|
|
4331
|
+
h('div', { className: 'form-group' },
|
|
4332
|
+
h('label', { style: labelStyle }, 'Premium Proxy'),
|
|
4333
|
+
h('select', { className: 'input', value: cfg.scrapingbeePremiumProxy ? 'true' : 'false',
|
|
4334
|
+
onChange: function(e) { update('scrapingbeePremiumProxy', e.target.value === 'true'); }
|
|
4335
|
+
},
|
|
4336
|
+
h('option', { value: 'false' }, 'Standard'),
|
|
4337
|
+
h('option', { value: 'true' }, 'Premium (residential IPs)')
|
|
4338
|
+
)
|
|
4339
|
+
),
|
|
4340
|
+
h('div', { className: 'form-group' },
|
|
4341
|
+
h('label', { style: labelStyle }, 'Country'),
|
|
4342
|
+
h('input', { className: 'input', placeholder: 'us, gb, de...',
|
|
4343
|
+
value: cfg.scrapingbeeCountry || '',
|
|
4344
|
+
onChange: function(e) { update('scrapingbeeCountry', e.target.value || undefined); }
|
|
4345
|
+
})
|
|
4346
|
+
)
|
|
4347
|
+
)
|
|
4348
|
+
)
|
|
4349
|
+
)
|
|
4105
4350
|
),
|
|
4106
4351
|
|
|
4107
|
-
//
|
|
4108
|
-
h('div', {
|
|
4109
|
-
|
|
4110
|
-
h('
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4352
|
+
// ─── Section 3: Security & Limits ────────────────
|
|
4353
|
+
h('div', { style: sectionStyle },
|
|
4354
|
+
sectionTitle('\uD83D\uDD12', 'Security & Limits'),
|
|
4355
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4356
|
+
h('div', { className: 'form-group' },
|
|
4357
|
+
h('label', { style: labelStyle }, 'URL Protection'),
|
|
4358
|
+
h('select', { className: 'input', value: cfg.ssrfProtection || 'permissive',
|
|
4359
|
+
onChange: function(e) { update('ssrfProtection', e.target.value); }
|
|
4360
|
+
},
|
|
4361
|
+
h('option', { value: 'off' }, 'Off — No URL restrictions'),
|
|
4362
|
+
h('option', { value: 'permissive' }, 'Permissive — Block dangerous URLs'),
|
|
4363
|
+
h('option', { value: 'strict' }, 'Strict — Allowlist only')
|
|
4364
|
+
)
|
|
4365
|
+
),
|
|
4366
|
+
h('div', { className: 'form-group' },
|
|
4367
|
+
h('label', { style: labelStyle }, 'JavaScript Evaluation'),
|
|
4368
|
+
h('select', { className: 'input', value: cfg.allowEvaluate !== false ? 'true' : 'false',
|
|
4369
|
+
onChange: function(e) { update('allowEvaluate', e.target.value === 'true'); }
|
|
4370
|
+
},
|
|
4371
|
+
h('option', { value: 'true' }, 'Allowed'),
|
|
4372
|
+
h('option', { value: 'false' }, 'Blocked')
|
|
4373
|
+
)
|
|
4374
|
+
),
|
|
4375
|
+
h('div', { className: 'form-group' },
|
|
4376
|
+
h('label', { style: labelStyle }, 'File URLs (file://)'),
|
|
4377
|
+
h('select', { className: 'input', value: cfg.allowFileUrls ? 'true' : 'false',
|
|
4378
|
+
onChange: function(e) { update('allowFileUrls', e.target.value === 'true'); }
|
|
4379
|
+
},
|
|
4380
|
+
h('option', { value: 'false' }, 'Blocked'),
|
|
4381
|
+
h('option', { value: 'true' }, 'Allowed')
|
|
4382
|
+
)
|
|
4383
|
+
),
|
|
4384
|
+
h('div', { className: 'form-group' },
|
|
4385
|
+
h('label', { style: labelStyle }, 'Max Concurrent Tabs'),
|
|
4386
|
+
h('input', { className: 'input', type: 'number', min: 1, max: 50,
|
|
4387
|
+
value: cfg.maxContexts || 10,
|
|
4388
|
+
onChange: function(e) { update('maxContexts', parseInt(e.target.value) || 10); }
|
|
4389
|
+
})
|
|
4390
|
+
),
|
|
4391
|
+
h('div', { className: 'form-group' },
|
|
4392
|
+
h('label', { style: labelStyle }, 'Navigation Timeout (ms)'),
|
|
4393
|
+
h('input', { className: 'input', type: 'number', min: 5000, max: 120000, step: 1000,
|
|
4394
|
+
value: cfg.navigationTimeoutMs || 30000,
|
|
4395
|
+
onChange: function(e) { update('navigationTimeoutMs', parseInt(e.target.value) || 30000); }
|
|
4396
|
+
})
|
|
4397
|
+
),
|
|
4398
|
+
h('div', { className: 'form-group' },
|
|
4399
|
+
h('label', { style: labelStyle }, 'Idle Timeout (min)'),
|
|
4400
|
+
h('input', { className: 'input', type: 'number', min: 1, max: 60,
|
|
4401
|
+
value: Math.round((cfg.idleTimeoutMs || 300000) / 60000),
|
|
4402
|
+
onChange: function(e) { update('idleTimeoutMs', (parseInt(e.target.value) || 5) * 60000); }
|
|
4403
|
+
})
|
|
4404
|
+
)
|
|
4405
|
+
),
|
|
4406
|
+
h('div', { className: 'form-group', style: { marginTop: 12 } },
|
|
4407
|
+
h('label', { style: labelStyle }, 'Blocked URL Patterns'),
|
|
4408
|
+
h('input', { className: 'input', placeholder: '*://169.254.*, *://metadata.google.*',
|
|
4409
|
+
value: (cfg.blockedUrlPatterns || []).join(', '),
|
|
4410
|
+
onChange: function(e) { update('blockedUrlPatterns', e.target.value.split(',').map(function(s) { return s.trim(); }).filter(Boolean)); }
|
|
4411
|
+
})
|
|
4412
|
+
),
|
|
4413
|
+
cfg.ssrfProtection === 'strict' && h('div', { className: 'form-group', style: { marginTop: 8 } },
|
|
4414
|
+
h('label', { style: labelStyle }, 'Allowed URL Patterns'),
|
|
4415
|
+
h('input', { className: 'input', placeholder: '*://example.com/*, *://app.service.com/*',
|
|
4416
|
+
value: (cfg.allowedUrlPatterns || []).join(', '),
|
|
4417
|
+
onChange: function(e) { update('allowedUrlPatterns', e.target.value.split(',').map(function(s) { return s.trim(); }).filter(Boolean)); }
|
|
4418
|
+
})
|
|
4419
|
+
)
|
|
4116
4420
|
),
|
|
4117
4421
|
|
|
4118
|
-
//
|
|
4119
|
-
h('div', {
|
|
4120
|
-
|
|
4121
|
-
h('
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4422
|
+
// ─── Section 4: Meeting & Video Capabilities ─────
|
|
4423
|
+
h('div', { style: sectionStyle },
|
|
4424
|
+
sectionTitle('\uD83C\uDFA5', 'Meeting & Video Call Capabilities'),
|
|
4425
|
+
h('div', { style: { padding: '10px 14px', background: 'var(--bg-secondary)', borderRadius: 'var(--radius)', marginBottom: 12, fontSize: 12, lineHeight: 1.6 } },
|
|
4426
|
+
h('div', { style: { fontWeight: 600, marginBottom: 6 } }, 'For Google Meet, Teams, and Zoom:'),
|
|
4427
|
+
h('div', null, '\u2022 Use ', h('strong', null, 'Remote Browser (CDP)'), ' provider pointed at a VM with display + virtual camera'),
|
|
4428
|
+
h('div', null, '\u2022 The remote machine needs: X11/Wayland display, PulseAudio/PipeWire (audio), v4l2loopback (virtual camera)'),
|
|
4429
|
+
h('div', null, '\u2022 Agent will navigate to meeting URL, handle permissions, and interact with the meeting UI'),
|
|
4430
|
+
h('div', null, '\u2022 For voice participation: integrate with a Speech-to-Text / Text-to-Speech service'),
|
|
4431
|
+
h('div', { style: { marginTop: 8 } },
|
|
4432
|
+
h('strong', null, 'Quick VM Setup (Linux):'),
|
|
4433
|
+
h('pre', { style: { margin: '6px 0', padding: 8, background: 'var(--bg-tertiary)', borderRadius: 4, fontSize: 11, overflow: 'auto' } },
|
|
4434
|
+
'# Install deps\nsudo apt install -y xvfb pulseaudio chromium v4l2loopback-dkms\n\n# Start virtual display + audio\nXvfb :99 -screen 0 1920x1080x24 &\nexport DISPLAY=:99\npulseaudio --start\n\n# Launch Chrome with remote debugging\nchromium --remote-debugging-port=9222 \\\n --no-first-run --disable-gpu \\\n --use-fake-ui-for-media-stream \\\n --use-fake-device-for-media-stream \\\n --auto-accept-camera-and-microphone-capture'
|
|
4435
|
+
)
|
|
4436
|
+
)
|
|
4437
|
+
),
|
|
4438
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4439
|
+
h('div', { className: 'form-group' },
|
|
4440
|
+
h('label', { style: labelStyle }, 'Auto-Accept Permissions'),
|
|
4441
|
+
h('select', { className: 'input', value: cfg.autoAcceptPermissions !== false ? 'true' : 'false',
|
|
4442
|
+
onChange: function(e) { update('autoAcceptPermissions', e.target.value === 'true'); }
|
|
4443
|
+
},
|
|
4444
|
+
h('option', { value: 'true' }, 'Yes — Auto-grant camera/microphone access'),
|
|
4445
|
+
h('option', { value: 'false' }, 'No — Require manual permission grants')
|
|
4446
|
+
)
|
|
4447
|
+
),
|
|
4448
|
+
h('div', { className: 'form-group' },
|
|
4449
|
+
h('label', { style: labelStyle }, 'Virtual Camera Feed'),
|
|
4450
|
+
h('input', { className: 'input', placeholder: '/dev/video0 or URL to video feed',
|
|
4451
|
+
value: cfg.virtualCameraSource || '',
|
|
4452
|
+
onChange: function(e) { update('virtualCameraSource', e.target.value || undefined); }
|
|
4453
|
+
}),
|
|
4454
|
+
h('div', { style: helpStyle }, 'Video source for the agent\'s "camera" in meetings.')
|
|
4455
|
+
),
|
|
4456
|
+
h('div', { className: 'form-group' },
|
|
4457
|
+
h('label', { style: labelStyle }, 'Audio Input'),
|
|
4458
|
+
h('input', { className: 'input', placeholder: 'PulseAudio source (e.g. virtual_mic)',
|
|
4459
|
+
value: cfg.audioInput || '',
|
|
4460
|
+
onChange: function(e) { update('audioInput', e.target.value || undefined); }
|
|
4461
|
+
}),
|
|
4462
|
+
h('div', { style: helpStyle }, 'Audio source for the agent to speak in meetings.')
|
|
4463
|
+
),
|
|
4464
|
+
h('div', { className: 'form-group' },
|
|
4465
|
+
h('label', { style: labelStyle }, 'Audio Output'),
|
|
4466
|
+
h('input', { className: 'input', placeholder: 'PulseAudio sink (e.g. virtual_speaker)',
|
|
4467
|
+
value: cfg.audioOutput || '',
|
|
4468
|
+
onChange: function(e) { update('audioOutput', e.target.value || undefined); }
|
|
4469
|
+
}),
|
|
4470
|
+
h('div', { style: helpStyle }, 'Audio sink for the agent to hear meeting participants.')
|
|
4471
|
+
)
|
|
4472
|
+
)
|
|
4127
4473
|
),
|
|
4128
4474
|
|
|
4129
|
-
//
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
h('
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4475
|
+
// ─── Section 5: Persistent Sessions ──────────────
|
|
4476
|
+
h('div', { style: { paddingTop: 12 } },
|
|
4477
|
+
sectionTitle('\uD83D\uDD04', 'Session Persistence'),
|
|
4478
|
+
h('div', { style: { display: 'grid', gap: 12, gridTemplateColumns: '1fr 1fr' } },
|
|
4479
|
+
h('div', { className: 'form-group' },
|
|
4480
|
+
h('label', { style: labelStyle }, 'Persist Login Sessions'),
|
|
4481
|
+
h('select', { className: 'input', value: cfg.persistSessions ? 'true' : 'false',
|
|
4482
|
+
onChange: function(e) { update('persistSessions', e.target.value === 'true'); }
|
|
4483
|
+
},
|
|
4484
|
+
h('option', { value: 'false' }, 'No — Fresh session each time'),
|
|
4485
|
+
h('option', { value: 'true' }, 'Yes — Keep cookies, localStorage, logins')
|
|
4486
|
+
),
|
|
4487
|
+
h('div', { style: helpStyle }, 'Persistent sessions let agents stay logged into web apps.')
|
|
4488
|
+
),
|
|
4489
|
+
h('div', { className: 'form-group' },
|
|
4490
|
+
h('label', { style: labelStyle }, 'Session Storage Path'),
|
|
4491
|
+
h('input', { className: 'input', placeholder: '/data/browser-sessions/' + agentId.slice(0, 8),
|
|
4492
|
+
value: cfg.sessionStoragePath || '',
|
|
4493
|
+
onChange: function(e) { update('sessionStoragePath', e.target.value || undefined); }
|
|
4494
|
+
}),
|
|
4495
|
+
h('div', { style: helpStyle }, 'Directory to store persistent browser state.')
|
|
4496
|
+
)
|
|
4497
|
+
)
|
|
4138
4498
|
),
|
|
4139
4499
|
|
|
4140
|
-
//
|
|
4141
|
-
h('div', { style: { display: 'flex', justifyContent: '
|
|
4500
|
+
// ─── Actions Bar ─────────────────────────────────
|
|
4501
|
+
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingTop: 16, marginTop: 8, borderTop: '1px solid var(--border)' } },
|
|
4502
|
+
h('div', { style: { display: 'flex', gap: 8 } },
|
|
4503
|
+
h('button', { className: 'btn btn-sm', disabled: testing, onClick: testConnection },
|
|
4504
|
+
testing ? 'Testing...' : '\u{1F50C} Test Connection'
|
|
4505
|
+
),
|
|
4506
|
+
testResult && h('span', { style: { fontSize: 12, color: testResult.error ? 'var(--danger)' : 'var(--success)', alignSelf: 'center' } },
|
|
4507
|
+
testResult.error ? '\u274C ' + testResult.error : '\u2705 Connected — ' + (testResult.browserVersion || 'OK')
|
|
4508
|
+
)
|
|
4509
|
+
),
|
|
4142
4510
|
h('button', { className: 'btn', disabled: saving, onClick: save }, saving ? 'Saving...' : 'Save Browser Config')
|
|
4143
4511
|
)
|
|
4144
4512
|
)
|