feat: add abs alias, refresh extension panel, and bump to 0.16.1-fork.1
This commit is contained in:
@@ -5,7 +5,7 @@ Stealth-first fork of `agent-browser` for production browser automation under an
|
|||||||
This README focuses on stealth architecture and principles. For full command coverage inherited from upstream, use:
|
This README focuses on stealth architecture and principles. For full command coverage inherited from upstream, use:
|
||||||
|
|
||||||
- upstream docs: <https://github.com/vercel-labs/agent-browser>
|
- upstream docs: <https://github.com/vercel-labs/agent-browser>
|
||||||
- local help: `agent-browser --help`
|
- local help: `agent-browser --help` (short alias: `abs --help`)
|
||||||
|
|
||||||
## What This Fork Optimizes
|
## What This Fork Optimizes
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ This README focuses on stealth architecture and principles. For full command cov
|
|||||||
People often ask this: "What's the anti-detection approach compared to `agent-browser-stealth` on npm?"
|
People often ask this: "What's the anti-detection approach compared to `agent-browser-stealth` on npm?"
|
||||||
|
|
||||||
- `agent-browser-stealth` on npm is the package name for this fork.
|
- `agent-browser-stealth` on npm is the package name for this fork.
|
||||||
- The CLI keeps upstream-compatible command names (`agent-browser` is still the main executable, with `agent-browser-stealth` as an alias).
|
- The CLI keeps upstream-compatible command names (`agent-browser` is still the main executable, with `agent-browser-stealth` and `abs` as aliases).
|
||||||
- The practical difference vs upstream `agent-browser` is not one single "stealth switch"; it is a defense-in-depth stack designed for anti-bot pressure.
|
- The practical difference vs upstream `agent-browser` is not one single "stealth switch"; it is a defense-in-depth stack designed for anti-bot pressure.
|
||||||
|
|
||||||
The core idea is layered hardening across the full automation lifecycle:
|
The core idea is layered hardening across the full automation lifecycle:
|
||||||
@@ -40,6 +40,8 @@ Goal: reduce detection probability and improve stability in production automatio
|
|||||||
```bash
|
```bash
|
||||||
npm install -g agent-browser-stealth
|
npm install -g agent-browser-stealth
|
||||||
agent-browser install
|
agent-browser install
|
||||||
|
# same CLI, short alias
|
||||||
|
abs install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Minimal Usage
|
### Minimal Usage
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.16.1-fork.0"
|
version = "0.16.1-fork.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Stealth browser automation CLI for AI agents with anti-bot evasions"
|
description = "Stealth browser automation CLI for AI agents with anti-bot evasions"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -2393,6 +2393,7 @@ pub fn print_help() {
|
|||||||
agent-browser - fast browser automation CLI for AI agents
|
agent-browser - fast browser automation CLI for AI agents
|
||||||
|
|
||||||
Usage: agent-browser <command> [args] [options]
|
Usage: agent-browser <command> [args] [options]
|
||||||
|
Aliases: agent-browser, agent-browser-stealth, abs
|
||||||
|
|
||||||
Core Commands:
|
Core Commands:
|
||||||
open <url> Navigate to URL
|
open <url> Navigate to URL
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ export const metadata = pageMetadata('commands');
|
|||||||
|
|
||||||
# Commands
|
# Commands
|
||||||
|
|
||||||
|
Executable aliases: `agent-browser`, `agent-browser-stealth`, `abs`.
|
||||||
|
|
||||||
## Core
|
## Core
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ brew install agent-browser # macOS
|
|||||||
npx agent-browser-stealth open example.com
|
npx agent-browser-stealth open example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Executable aliases after install: `agent-browser`, `agent-browser-stealth`, and `abs`.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Agent-first** - Compact text output uses fewer tokens than JSON, designed for AI context efficiency
|
- **Agent-first** - Compact text output uses fewer tokens than JSON, designed for AI context efficiency
|
||||||
|
|||||||
@@ -1,119 +1,192 @@
|
|||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
--bg: #0d1117;
|
||||||
--bg: #111827;
|
--panel: #161b22;
|
||||||
--card: #1f2937;
|
--item-bg: rgba(255, 255, 255, 0.03);
|
||||||
--border: #374151;
|
--item-hover: rgba(255, 255, 255, 0.06);
|
||||||
--text: #f9fafb;
|
--border: #30363d;
|
||||||
--muted: #d1d5db;
|
--border-focus: #484f58;
|
||||||
--accent: #22c55e;
|
--text-main: #e6edf3;
|
||||||
|
--text-muted: #848d97;
|
||||||
|
--accent: #2f81f7;
|
||||||
|
--accent-soft: rgba(47, 129, 247, 0.1);
|
||||||
|
--success: #3fb950;
|
||||||
|
--warning: #d29922;
|
||||||
|
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 12px;
|
padding: 20px;
|
||||||
background: radial-gradient(circle at top left, #1f2937, #111827);
|
background-color: var(--bg);
|
||||||
color: var(--text);
|
color: var(--text-main);
|
||||||
font:
|
font-family: var(--font-family);
|
||||||
13px/1.5 -apple-system,
|
font-size: 13px;
|
||||||
BlinkMacSystemFont,
|
line-height: 1.5;
|
||||||
'Segoe UI',
|
|
||||||
sans-serif;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scrollbar */
|
||||||
|
::-webkit-scrollbar { width: 8px; }
|
||||||
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
|
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
|
||||||
|
::-webkit-scrollbar-thumb:hover { background: var(--border-focus); }
|
||||||
|
|
||||||
header {
|
header {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
gap: 16px;
|
||||||
align-items: center;
|
margin-bottom: 24px;
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
h1::before {
|
||||||
background: #0f172a;
|
content: "";
|
||||||
color: var(--text);
|
display: block;
|
||||||
border: 1px solid var(--border);
|
width: 12px;
|
||||||
border-radius: 8px;
|
height: 12px;
|
||||||
padding: 6px 8px;
|
background: var(--accent);
|
||||||
cursor: pointer;
|
border-radius: 3px;
|
||||||
}
|
box-shadow: 0 0 10px var(--accent);
|
||||||
|
|
||||||
button:hover {
|
|
||||||
border-color: var(--accent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
all: unset;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: var(--panel);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--text-main);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: var(--item-hover);
|
||||||
|
border-color: var(--border-focus);
|
||||||
|
}
|
||||||
|
|
||||||
|
#refresh-btn {
|
||||||
|
background: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#refresh-btn:hover {
|
||||||
|
background: #4493f8;
|
||||||
|
border-color: #4493f8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
background: color-mix(in srgb, var(--card) 88%, #000 12%);
|
background: var(--panel);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 16px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stack {
|
.stack {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-title {
|
.session-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
margin-bottom: 12px;
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.session-title strong {
|
.session-title h4 {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags {
|
.tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 6px;
|
gap: 4px;
|
||||||
margin: 6px 0;
|
margin: 8px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
border: 1px solid var(--border);
|
background: var(--accent-soft);
|
||||||
border-radius: 999px;
|
color: var(--accent);
|
||||||
padding: 2px 7px;
|
border: 1px solid transparent;
|
||||||
color: var(--muted);
|
padding: 1px 6px;
|
||||||
font-size: 12px;
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 4px;
|
gap: 1px; /* Divider effect */
|
||||||
|
background: var(--border);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
border: 1px solid color-mix(in srgb, var(--border) 85%, #000 15%);
|
background: var(--panel);
|
||||||
border-radius: 8px;
|
padding: 10px 12px;
|
||||||
padding: 6px 7px;
|
display: flex;
|
||||||
background: rgba(255, 255, 255, 0.03);
|
flex-direction: column;
|
||||||
overflow: hidden;
|
gap: 2px;
|
||||||
|
transition: background 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background: var(--item-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-title {
|
.item-title {
|
||||||
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
color: var(--text-main);
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-url {
|
.item-url {
|
||||||
color: var(--muted);
|
color: var(--text-muted);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -122,9 +195,45 @@ button:hover {
|
|||||||
|
|
||||||
.row-actions {
|
.row-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 6px;
|
gap: 4px;
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-actions button {
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
color: var(--muted);
|
color: var(--text-muted);
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
|
background: rgba(110, 118, 129, 0.4);
|
||||||
|
padding: 2px 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summary code {
|
||||||
|
color: var(--warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Summary Grid */
|
||||||
|
#summary .tags {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#summary .tag {
|
||||||
|
text-align: center;
|
||||||
|
padding: 6px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,45 +16,54 @@ function createTag(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderSummary(state) {
|
function renderSummary(state) {
|
||||||
summaryEl.innerHTML = '';
|
summaryEl.innerHTML = '<h3>Overview</h3>';
|
||||||
const options = state.options || {};
|
const options = state.options || {};
|
||||||
const title = document.createElement('div');
|
|
||||||
title.innerHTML = `<strong>Overview</strong> · extensionId: <code>${state.extensionId}</code>`;
|
const idInfo = document.createElement('div');
|
||||||
|
idInfo.style.marginBottom = '12px';
|
||||||
|
idInfo.style.fontSize = '11px';
|
||||||
|
idInfo.style.color = 'var(--text-muted)';
|
||||||
|
idInfo.innerHTML = `Extension ID: <code>${state.extensionId}</code>`;
|
||||||
|
summaryEl.appendChild(idInfo);
|
||||||
|
|
||||||
const tags = document.createElement('div');
|
const tags = document.createElement('div');
|
||||||
tags.className = 'tags';
|
tags.className = 'tags';
|
||||||
tags.appendChild(createTag(`sessions: ${state.totals.sessions}`));
|
tags.appendChild(createTag(`Sessions: ${state.totals.sessions}`));
|
||||||
tags.appendChild(createTag(`tabs: ${state.totals.tabs}`));
|
tags.appendChild(createTag(`Tabs: ${state.totals.tabs}`));
|
||||||
tags.appendChild(
|
tags.appendChild(
|
||||||
createTag(`isolation: ${options.strictWindowIsolation === false ? 'off' : 'on'}`)
|
createTag(`Isolation: ${options.strictWindowIsolation === false ? 'Off' : 'On'}`)
|
||||||
);
|
);
|
||||||
tags.appendChild(
|
tags.appendChild(
|
||||||
createTag(`activation-guard: ${options.suppressCrossWindowActivation === false ? 'off' : 'on'}`)
|
createTag(`Guard: ${options.suppressCrossWindowActivation === false ? 'Off' : 'On'}`)
|
||||||
);
|
);
|
||||||
tags.appendChild(
|
tags.appendChild(
|
||||||
createTag(`auto-clean: ${options.autoCleanEmptyGroups === false ? 'off' : 'on'}`)
|
createTag(`Auto-Clean: ${options.autoCleanEmptyGroups === false ? 'Off' : 'On'}`)
|
||||||
);
|
);
|
||||||
|
|
||||||
const optionActions = document.createElement('div');
|
const optionActions = document.createElement('div');
|
||||||
optionActions.className = 'row-actions';
|
optionActions.className = 'row-actions';
|
||||||
|
|
||||||
const isolationBtn = document.createElement('button');
|
const createOptionBtn = (text, active, onClick) => {
|
||||||
isolationBtn.type = 'button';
|
const btn = document.createElement('button');
|
||||||
isolationBtn.textContent =
|
btn.type = 'button';
|
||||||
options.strictWindowIsolation === false ? 'Enable Isolation' : 'Disable Isolation';
|
btn.textContent = text;
|
||||||
isolationBtn.addEventListener('click', async () => {
|
if (active) btn.style.borderColor = 'var(--accent)';
|
||||||
|
btn.addEventListener('click', onClick);
|
||||||
|
return btn;
|
||||||
|
};
|
||||||
|
|
||||||
|
optionActions.appendChild(
|
||||||
|
createOptionBtn('Strict Isolation', options.strictWindowIsolation !== false, async () => {
|
||||||
await send({
|
await send({
|
||||||
type: 'AB_PANEL_SET_OPTIONS',
|
type: 'AB_PANEL_SET_OPTIONS',
|
||||||
options: { ...options, strictWindowIsolation: options.strictWindowIsolation === false },
|
options: { ...options, strictWindowIsolation: options.strictWindowIsolation === false },
|
||||||
});
|
});
|
||||||
await refresh();
|
await refresh();
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const guardBtn = document.createElement('button');
|
optionActions.appendChild(
|
||||||
guardBtn.type = 'button';
|
createOptionBtn('Activation Guard', options.suppressCrossWindowActivation !== false, async () => {
|
||||||
guardBtn.textContent =
|
|
||||||
options.suppressCrossWindowActivation === false ? 'Enable Guard' : 'Disable Guard';
|
|
||||||
guardBtn.addEventListener('click', async () => {
|
|
||||||
await send({
|
await send({
|
||||||
type: 'AB_PANEL_SET_OPTIONS',
|
type: 'AB_PANEL_SET_OPTIONS',
|
||||||
options: {
|
options: {
|
||||||
@@ -63,13 +72,11 @@ function renderSummary(state) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await refresh();
|
await refresh();
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const autoCleanBtn = document.createElement('button');
|
optionActions.appendChild(
|
||||||
autoCleanBtn.type = 'button';
|
createOptionBtn('Auto-Clean', options.autoCleanEmptyGroups !== false, async () => {
|
||||||
autoCleanBtn.textContent =
|
|
||||||
options.autoCleanEmptyGroups === false ? 'Enable Auto-Clean' : 'Disable Auto-Clean';
|
|
||||||
autoCleanBtn.addEventListener('click', async () => {
|
|
||||||
await send({
|
await send({
|
||||||
type: 'AB_PANEL_SET_OPTIONS',
|
type: 'AB_PANEL_SET_OPTIONS',
|
||||||
options: {
|
options: {
|
||||||
@@ -78,24 +85,20 @@ function renderSummary(state) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
await refresh();
|
await refresh();
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
optionActions.appendChild(isolationBtn);
|
|
||||||
optionActions.appendChild(guardBtn);
|
|
||||||
optionActions.appendChild(autoCleanBtn);
|
|
||||||
|
|
||||||
summaryEl.appendChild(title);
|
|
||||||
summaryEl.appendChild(tags);
|
summaryEl.appendChild(tags);
|
||||||
summaryEl.appendChild(optionActions);
|
summaryEl.appendChild(optionActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSessions(state) {
|
function renderSessions(state) {
|
||||||
sessionsEl.innerHTML = '';
|
sessionsEl.innerHTML = '<h3>Active Sessions</h3>';
|
||||||
|
|
||||||
if (!state.sessions || state.sessions.length === 0) {
|
if (!state.sessions || state.sessions.length === 0) {
|
||||||
const empty = document.createElement('div');
|
const empty = document.createElement('div');
|
||||||
empty.className = 'card empty';
|
empty.className = 'card empty';
|
||||||
empty.textContent = 'No managed sessions yet.';
|
empty.textContent = 'No active sessions monitored.';
|
||||||
sessionsEl.appendChild(empty);
|
sessionsEl.appendChild(empty);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -107,31 +110,71 @@ function renderSessions(state) {
|
|||||||
const titleRow = document.createElement('div');
|
const titleRow = document.createElement('div');
|
||||||
titleRow.className = 'session-title';
|
titleRow.className = 'session-title';
|
||||||
|
|
||||||
const titleLeft = document.createElement('strong');
|
const titleLeft = document.createElement('h4');
|
||||||
titleLeft.textContent = session.session;
|
titleLeft.textContent = session.session;
|
||||||
|
|
||||||
const actions = document.createElement('div');
|
|
||||||
actions.className = 'row-actions';
|
|
||||||
|
|
||||||
const focusBtn = document.createElement('button');
|
const focusBtn = document.createElement('button');
|
||||||
focusBtn.type = 'button';
|
|
||||||
focusBtn.textContent = 'Focus';
|
focusBtn.textContent = 'Focus';
|
||||||
focusBtn.addEventListener('click', async () => {
|
focusBtn.addEventListener('click', async () => {
|
||||||
await send({ type: 'AB_PANEL_FOCUS_SESSION', session: session.session });
|
await send({ type: 'AB_PANEL_FOCUS_SESSION', session: session.session });
|
||||||
await refresh();
|
await refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
titleRow.appendChild(titleLeft);
|
||||||
|
titleRow.appendChild(focusBtn);
|
||||||
|
|
||||||
|
const tags = document.createElement('div');
|
||||||
|
tags.className = 'tags';
|
||||||
|
tags.appendChild(createTag(`Window: ${session.windowId ?? 'N/A'}`));
|
||||||
|
tags.appendChild(createTag(`Tabs: ${session.tabs.length}`));
|
||||||
|
|
||||||
|
if (session.group) {
|
||||||
|
tags.appendChild(createTag(`G: ${session.group.title || 'Untitled'}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session.allowedDomains && session.allowedDomains.length > 0) {
|
||||||
|
tags.appendChild(createTag(`Allowlist: ${session.allowedDomains.length} domains`));
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = document.createElement('div');
|
||||||
|
list.className = 'list';
|
||||||
|
for (const tab of session.tabs.slice(0, 10)) {
|
||||||
|
const item = document.createElement('div');
|
||||||
|
item.className = 'item';
|
||||||
|
|
||||||
|
const t = document.createElement('div');
|
||||||
|
t.className = 'item-title';
|
||||||
|
if (tab.active) {
|
||||||
|
const dot = document.createElement('span');
|
||||||
|
dot.textContent = '●';
|
||||||
|
dot.style.color = 'var(--success)';
|
||||||
|
dot.style.marginRight = '6px';
|
||||||
|
dot.style.fontSize = '10px';
|
||||||
|
t.appendChild(dot);
|
||||||
|
}
|
||||||
|
t.appendChild(document.createTextNode(tab.title || '(Untitled)'));
|
||||||
|
|
||||||
|
const u = document.createElement('div');
|
||||||
|
u.className = 'item-url';
|
||||||
|
u.textContent = tab.url || 'about:blank';
|
||||||
|
|
||||||
|
item.appendChild(t);
|
||||||
|
item.appendChild(u);
|
||||||
|
list.appendChild(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
const footerActions = document.createElement('div');
|
||||||
|
footerActions.className = 'row-actions';
|
||||||
|
|
||||||
const keepBtn = document.createElement('button');
|
const keepBtn = document.createElement('button');
|
||||||
keepBtn.type = 'button';
|
keepBtn.textContent = 'Isolate Session';
|
||||||
keepBtn.textContent = 'Keep Only This';
|
|
||||||
keepBtn.addEventListener('click', async () => {
|
keepBtn.addEventListener('click', async () => {
|
||||||
await send({ type: 'AB_PANEL_CLOSE_OTHER_SESSION_TABS', session: session.session });
|
await send({ type: 'AB_PANEL_CLOSE_OTHER_SESSION_TABS', session: session.session });
|
||||||
await refresh();
|
await refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
const policyBtn = document.createElement('button');
|
const policyBtn = document.createElement('button');
|
||||||
policyBtn.type = 'button';
|
policyBtn.textContent = 'Config Policy';
|
||||||
policyBtn.textContent = 'Set Allowlist';
|
|
||||||
policyBtn.addEventListener('click', async () => {
|
policyBtn.addEventListener('click', async () => {
|
||||||
const current = (session.allowedDomains || []).join(',');
|
const current = (session.allowedDomains || []).join(',');
|
||||||
const input = window.prompt('Allowed domains (comma-separated)', current);
|
const input = window.prompt('Allowed domains (comma-separated)', current);
|
||||||
@@ -144,62 +187,19 @@ function renderSessions(state) {
|
|||||||
await refresh();
|
await refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.appendChild(focusBtn);
|
footerActions.appendChild(keepBtn);
|
||||||
actions.appendChild(keepBtn);
|
footerActions.appendChild(policyBtn);
|
||||||
actions.appendChild(policyBtn);
|
|
||||||
|
|
||||||
titleRow.appendChild(titleLeft);
|
|
||||||
titleRow.appendChild(actions);
|
|
||||||
|
|
||||||
const tags = document.createElement('div');
|
|
||||||
tags.className = 'tags';
|
|
||||||
tags.appendChild(createTag(`window: ${session.windowId ?? 'n/a'}`));
|
|
||||||
tags.appendChild(createTag(`tabs: ${session.tabs.length}`));
|
|
||||||
|
|
||||||
if (session.group) {
|
|
||||||
tags.appendChild(createTag(`group: ${session.group.title || session.group.id}`));
|
|
||||||
tags.appendChild(createTag(`color: ${session.group.color}`));
|
|
||||||
tags.appendChild(createTag(`collapsed: ${session.group.collapsed}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.allowedDomains && session.allowedDomains.length > 0) {
|
|
||||||
tags.appendChild(createTag(`allowlist: ${session.allowedDomains.join(', ')}`));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.riskHints && session.riskHints.length > 0) {
|
|
||||||
for (const hint of session.riskHints) {
|
|
||||||
tags.appendChild(createTag(`risk: ${hint}`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const list = document.createElement('div');
|
|
||||||
list.className = 'list';
|
|
||||||
for (const tab of session.tabs.slice(0, 10)) {
|
|
||||||
const item = document.createElement('div');
|
|
||||||
item.className = 'item';
|
|
||||||
|
|
||||||
const t = document.createElement('div');
|
|
||||||
t.className = 'item-title';
|
|
||||||
t.textContent = `${tab.active ? '● ' : ''}${tab.title || '(untitled)'}`;
|
|
||||||
|
|
||||||
const u = document.createElement('div');
|
|
||||||
u.className = 'item-url';
|
|
||||||
u.textContent = tab.url || 'about:blank';
|
|
||||||
|
|
||||||
item.appendChild(t);
|
|
||||||
item.appendChild(u);
|
|
||||||
list.appendChild(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
card.appendChild(titleRow);
|
card.appendChild(titleRow);
|
||||||
card.appendChild(tags);
|
card.appendChild(tags);
|
||||||
card.appendChild(list);
|
card.appendChild(list);
|
||||||
|
card.appendChild(footerActions);
|
||||||
sessionsEl.appendChild(card);
|
sessionsEl.appendChild(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderDownloads(state) {
|
function renderDownloads(state) {
|
||||||
downloadsEl.innerHTML = '<strong>Recent Downloads</strong>';
|
downloadsEl.innerHTML = '<h3>Recent Downloads</h3>';
|
||||||
|
|
||||||
const list = document.createElement('div');
|
const list = document.createElement('div');
|
||||||
list.className = 'list';
|
list.className = 'list';
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agent-browser-stealth",
|
"name": "agent-browser-stealth",
|
||||||
"version": "0.16.1-fork.0",
|
"version": "0.16.1-fork.1",
|
||||||
"description": "Stealth browser automation CLI for AI agents with anti-bot evasions",
|
"description": "Stealth browser automation CLI for AI agents with anti-bot evasions",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/daemon.js",
|
"main": "dist/daemon.js",
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
],
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"agent-browser-stealth": "./bin/agent-browser.js",
|
"agent-browser-stealth": "./bin/agent-browser.js",
|
||||||
"agent-browser": "./bin/agent-browser.js"
|
"agent-browser": "./bin/agent-browser.js",
|
||||||
|
"abs": "./bin/agent-browser.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
---
|
---
|
||||||
name: agent-browser
|
name: agent-browser
|
||||||
description: Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.
|
description: Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction.
|
||||||
allowed-tools: Bash(npx agent-browser-stealth:*), Bash(npx agent-browser:*), Bash(agent-browser:*)
|
allowed-tools: Bash(npx agent-browser-stealth:*), Bash(npx agent-browser:*), Bash(agent-browser:*), Bash(abs:*)
|
||||||
---
|
---
|
||||||
|
|
||||||
# Browser Automation with agent-browser
|
# Browser Automation with agent-browser
|
||||||
|
|
||||||
Install package: `pnpm add -g agent-browser-stealth` (CLI command remains `agent-browser` for compatibility). If global install is unavailable in your environment, use `pnpm dlx agent-browser-stealth <command>` for one-off runs.
|
Install package: `pnpm add -g agent-browser-stealth` (CLI commands: `agent-browser`, `agent-browser-stealth`, and short alias `abs`). If global install is unavailable in your environment, use `pnpm dlx agent-browser-stealth <command>` for one-off runs.
|
||||||
|
|
||||||
## Core Workflow
|
## Core Workflow
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user