web-agent-bridge 1.0.0
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/LICENSE +21 -0
- package/README.ar.md +446 -0
- package/README.md +544 -0
- package/bin/cli.js +80 -0
- package/bin/wab.js +80 -0
- package/examples/bidi-agent.js +119 -0
- package/examples/puppeteer-agent.js +108 -0
- package/examples/vision-agent.js +159 -0
- package/package.json +67 -0
- package/public/css/styles.css +1235 -0
- package/public/dashboard.html +566 -0
- package/public/docs.html +582 -0
- package/public/index.html +306 -0
- package/public/login.html +81 -0
- package/public/register.html +94 -0
- package/script/ai-agent-bridge.js +1282 -0
- package/sdk/README.md +55 -0
- package/sdk/index.js +167 -0
- package/sdk/package.json +14 -0
- package/server/index.js +105 -0
- package/server/middleware/auth.js +44 -0
- package/server/models/adapters/index.js +33 -0
- package/server/models/adapters/mysql.js +183 -0
- package/server/models/adapters/postgresql.js +172 -0
- package/server/models/adapters/sqlite.js +7 -0
- package/server/models/db.js +205 -0
- package/server/routes/api.js +121 -0
- package/server/routes/auth.js +51 -0
- package/server/routes/license.js +51 -0
- package/server/ws.js +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
# Web Agent Bridge (WAB)
|
|
2
|
+
|
|
3
|
+
[](https://github.com/abokenan444/web-agent-bridge/actions/workflows/ci.yml)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
[](https://hub.docker.com/)
|
|
7
|
+
[](CONTRIBUTING.md)
|
|
8
|
+
|
|
9
|
+
**Open-source middleware that bridges AI agents and websites — providing a standardized command interface for intelligent automation.**
|
|
10
|
+
|
|
11
|
+
**English** | **[العربية](README.ar.md)**
|
|
12
|
+
|
|
13
|
+
WAB gives website owners a script they embed in their pages that exposes a `window.AICommands` interface. AI agents read this interface to discover available actions, execute commands, and interact with sites accurately — without parsing raw DOM.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Auto-Discovery** — Automatically detects buttons, forms, and navigation on the page
|
|
20
|
+
- **Permission System** — Granular control over what AI agents can do (click, fill forms, API access, etc.)
|
|
21
|
+
- **Standardized Interface** — Unified `window.AICommands` object any agent can consume
|
|
22
|
+
- **Rate Limiting** — Built-in abuse protection with configurable limits
|
|
23
|
+
- **Analytics Dashboard** — Track how AI agents interact with your site
|
|
24
|
+
- **Real-Time Analytics** — WebSocket-based live event streaming for Enterprise users
|
|
25
|
+
- **WebDriver BiDi Compatible** — Standard protocol support via `window.__wab_bidi`
|
|
26
|
+
- **CDN Versioning** — Serve scripts via versioned URLs (`/v1/ai-agent-bridge.js`, `/latest/ai-agent-bridge.js`)
|
|
27
|
+
- **Docker Ready** — One-command deployment with Docker Compose
|
|
28
|
+
- **Custom Actions** — Register your own actions with custom handlers
|
|
29
|
+
- **Subscription Tiers** — Free core + paid premium features (API access, analytics, automated login)
|
|
30
|
+
- **Event System** — Subscribe to bridge events for monitoring
|
|
31
|
+
- **Security Sandbox** — Origin validation, session tokens, command signing, audit logging, auto-lockdown
|
|
32
|
+
- **Self-Healing Selectors** — Resilient element resolution with fuzzy matching for dynamic SPAs
|
|
33
|
+
- **Stealth Mode** — Human-like interaction patterns (mouse events, typing delays, natural scrolling)
|
|
34
|
+
- **Multi-Database** — SQLite (default), PostgreSQL, MySQL via pluggable adapters
|
|
35
|
+
- **Agent SDK** — Built-in SDK for building AI agents with Puppeteer/Playwright
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### 1. Install & Run the Server
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Option A: Clone and run
|
|
45
|
+
git clone https://github.com/abokenan444/web-agent-bridge.git
|
|
46
|
+
cd web-agent-bridge
|
|
47
|
+
npm install
|
|
48
|
+
cp .env.example .env
|
|
49
|
+
npm start
|
|
50
|
+
|
|
51
|
+
# Option B: npx (one command)
|
|
52
|
+
npx web-agent-bridge start
|
|
53
|
+
|
|
54
|
+
# Option C: Docker
|
|
55
|
+
docker compose up -d
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Create an Account
|
|
59
|
+
|
|
60
|
+
Visit `http://localhost:3000/register` and create an account, then add your site from the dashboard.
|
|
61
|
+
|
|
62
|
+
### 3. Add the Script to Your Website
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<script>
|
|
66
|
+
window.AIBridgeConfig = {
|
|
67
|
+
licenseKey: "WAB-XXXXX-XXXXX-XXXXX-XXXXX",
|
|
68
|
+
agentPermissions: {
|
|
69
|
+
readContent: true,
|
|
70
|
+
click: true,
|
|
71
|
+
fillForms: true,
|
|
72
|
+
scroll: true
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
</script>
|
|
76
|
+
<script src="http://localhost:3000/script/ai-agent-bridge.js"></script>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 4. AI Agents Can Now Interact
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
// From the AI agent's side
|
|
83
|
+
const bridge = window.AICommands;
|
|
84
|
+
const actions = bridge.getActions(); // discover actions
|
|
85
|
+
await bridge.execute("signup"); // execute an action
|
|
86
|
+
const info = bridge.getPageInfo(); // get page metadata
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Project Structure
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
web-agent-bridge/
|
|
95
|
+
├── server/ # Express.js backend
|
|
96
|
+
│ ├── index.js # Server entry point
|
|
97
|
+
│ ├── routes/
|
|
98
|
+
│ │ ├── auth.js # Authentication (register/login)
|
|
99
|
+
│ │ ├── api.js # Sites, config, analytics API
|
|
100
|
+
│ │ └── license.js # License verification & tracking
|
|
101
|
+
│ ├── middleware/
|
|
102
|
+
│ │ └── auth.js # JWT authentication middleware
|
|
103
|
+
│ └── models/
|
|
104
|
+
│ └── db.js # SQLite database & operations
|
|
105
|
+
├── public/ # Frontend
|
|
106
|
+
│ ├── index.html # Landing page
|
|
107
|
+
│ ├── dashboard.html # Management dashboard
|
|
108
|
+
│ ├── docs.html # Documentation
|
|
109
|
+
│ ├── login.html # Sign in
|
|
110
|
+
│ ├── register.html # Sign up
|
|
111
|
+
│ └── css/styles.css # Design system
|
|
112
|
+
├── script/
|
|
113
|
+
│ └── ai-agent-bridge.js # The bridge script (embed in websites)
|
|
114
|
+
├── .env # Environment variables
|
|
115
|
+
└── package.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## API Endpoints
|
|
121
|
+
|
|
122
|
+
### Authentication
|
|
123
|
+
| Endpoint | Method | Description |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| `/api/auth/register` | POST | Create account |
|
|
126
|
+
| `/api/auth/login` | POST | Sign in, receive JWT |
|
|
127
|
+
| `/api/auth/me` | GET | Get current user |
|
|
128
|
+
|
|
129
|
+
### Sites
|
|
130
|
+
| Endpoint | Method | Description |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| `/api/sites` | GET | List your sites |
|
|
133
|
+
| `/api/sites` | POST | Add a new site |
|
|
134
|
+
| `/api/sites/:id` | GET | Get site details |
|
|
135
|
+
| `/api/sites/:id/config` | PUT | Update configuration |
|
|
136
|
+
| `/api/sites/:id/tier` | PUT | Change subscription tier |
|
|
137
|
+
| `/api/sites/:id` | DELETE | Delete a site |
|
|
138
|
+
| `/api/sites/:id/snippet` | GET | Get install code snippet |
|
|
139
|
+
| `/api/sites/:id/analytics` | GET | Get analytics data |
|
|
140
|
+
|
|
141
|
+
### License (Public)
|
|
142
|
+
| Endpoint | Method | Description |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `/api/license/verify` | POST | Verify license key for domain |
|
|
145
|
+
| `/api/license/track` | POST | Record analytics event |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Bridge Script API
|
|
150
|
+
|
|
151
|
+
Once loaded, `window.AICommands` exposes:
|
|
152
|
+
|
|
153
|
+
| Method | Description |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `getActions(category?)` | List available actions |
|
|
156
|
+
| `getAction(name)` | Get a specific action |
|
|
157
|
+
| `execute(name, params?)` | Execute an action |
|
|
158
|
+
| `readContent(selector)` | Read element content |
|
|
159
|
+
| `getPageInfo()` | Get page and bridge metadata |
|
|
160
|
+
| `waitForElement(selector, timeout?)` | Wait for DOM element |
|
|
161
|
+
| `waitForNavigation(timeout?)` | Wait for URL change |
|
|
162
|
+
| `registerAction(def)` | Register a custom action |
|
|
163
|
+
| `authenticate(key, meta?)` | Authenticate an agent |
|
|
164
|
+
| `refresh()` | Re-scan the page |
|
|
165
|
+
| `onReady(callback)` | Callback when bridge is ready |
|
|
166
|
+
| `events.on(event, cb)` | Subscribe to events |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Configuration
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
window.AIBridgeConfig = {
|
|
174
|
+
licenseKey: "WAB-XXXXX-XXXXX-XXXXX-XXXXX",
|
|
175
|
+
agentPermissions: {
|
|
176
|
+
readContent: true, // Read page text
|
|
177
|
+
click: true, // Click elements
|
|
178
|
+
fillForms: false, // Fill/submit forms
|
|
179
|
+
scroll: true, // Scroll page
|
|
180
|
+
navigate: false, // Navigate pages
|
|
181
|
+
apiAccess: false, // Internal API calls (Pro+)
|
|
182
|
+
automatedLogin: false, // Auto login (Starter+)
|
|
183
|
+
extractData: false // Data extraction (Pro+)
|
|
184
|
+
},
|
|
185
|
+
restrictions: {
|
|
186
|
+
allowedSelectors: [],
|
|
187
|
+
blockedSelectors: [".private", "[data-private]"],
|
|
188
|
+
requireLoginForActions: ["apiAccess"],
|
|
189
|
+
rateLimit: { maxCallsPerMinute: 60 }
|
|
190
|
+
},
|
|
191
|
+
logging: { enabled: false, level: "basic" }
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Subscription Tiers
|
|
198
|
+
|
|
199
|
+
| Feature | Free | Starter | Pro | Enterprise |
|
|
200
|
+
|---|:---:|:---:|:---:|:---:|
|
|
201
|
+
| Auto-discovery | ✓ | ✓ | ✓ | ✓ |
|
|
202
|
+
| Click/Scroll | ✓ | ✓ | ✓ | ✓ |
|
|
203
|
+
| Form filling | ✓ | ✓ | ✓ | ✓ |
|
|
204
|
+
| Basic logging | ✓ | ✓ | ✓ | ✓ |
|
|
205
|
+
| Automated login | ✗ | ✓ | ✓ | ✓ |
|
|
206
|
+
| Analytics dashboard | ✗ | ✓ | ✓ | ✓ |
|
|
207
|
+
| API access | ✗ | ✗ | ✓ | ✓ |
|
|
208
|
+
| Data extraction | ✗ | ✗ | ✓ | ✓ |
|
|
209
|
+
| Custom rate limits | ✗ | ✗ | ✗ | ✓ |
|
|
210
|
+
| Webhooks | ✗ | ✗ | ✗ | ✓ |
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Tech Stack
|
|
215
|
+
|
|
216
|
+
- **Backend**: Node.js + Express + WebSocket (ws)
|
|
217
|
+
- **Database**: SQLite (via better-sqlite3)
|
|
218
|
+
- **Auth**: JWT + bcrypt
|
|
219
|
+
- **Frontend**: Vanilla HTML/CSS/JS (no framework dependencies)
|
|
220
|
+
- **Security**: Helmet, CORS, CSP, rate limiting
|
|
221
|
+
- **Containers**: Docker + Docker Compose
|
|
222
|
+
- **Testing**: Jest + Supertest
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## WebDriver BiDi Compatibility
|
|
227
|
+
|
|
228
|
+
WAB exposes a `window.__wab_bidi` interface for agents using standardized WebDriver BiDi protocol:
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
// Get BiDi context
|
|
232
|
+
const context = window.__wab_bidi.getContext();
|
|
233
|
+
|
|
234
|
+
// Send BiDi command
|
|
235
|
+
const result = await window.__wab_bidi.send({
|
|
236
|
+
id: 1,
|
|
237
|
+
method: 'wab.executeAction',
|
|
238
|
+
params: { name: 'signup', data: {} }
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Supported methods:
|
|
242
|
+
// wab.getContext, wab.getActions, wab.executeAction, wab.readContent, wab.getPageInfo
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Real-Time Analytics (WebSocket)
|
|
248
|
+
|
|
249
|
+
Connect to `ws://localhost:3000/ws/analytics` for live analytics:
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
const ws = new WebSocket('ws://localhost:3000/ws/analytics');
|
|
253
|
+
ws.onopen = () => ws.send(JSON.stringify({ type: 'auth', token: 'jwt-token', siteId: 'site-id' }));
|
|
254
|
+
ws.onmessage = (e) => console.log(JSON.parse(e.data));
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### WebSocket Message Protocol
|
|
258
|
+
|
|
259
|
+
**Client → Server Messages:**
|
|
260
|
+
|
|
261
|
+
| Message | Fields | Description |
|
|
262
|
+
|---|---|---|
|
|
263
|
+
| `auth` | `type`, `token`, `siteId` | Authenticate and subscribe to a site's events |
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{ "type": "auth", "token": "eyJhbGciOi...", "siteId": "uuid-of-site" }
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Server → Client Messages:**
|
|
270
|
+
|
|
271
|
+
| Message Type | Fields | Description |
|
|
272
|
+
|---|---|---|
|
|
273
|
+
| `auth:success` | `type`, `siteId` | Authentication succeeded |
|
|
274
|
+
| `analytic` | `type`, `timestamp`, `actionName`, `agentId`, `success` | Real-time analytics event |
|
|
275
|
+
| `error` | `type`, `message` | Error (invalid auth, malformed message) |
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
// Success response
|
|
279
|
+
{ "type": "auth:success", "siteId": "uuid-of-site" }
|
|
280
|
+
|
|
281
|
+
// Analytics event
|
|
282
|
+
{
|
|
283
|
+
"type": "analytic",
|
|
284
|
+
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
285
|
+
"actionName": "click-signup",
|
|
286
|
+
"agentId": "agent-123",
|
|
287
|
+
"triggerType": "click",
|
|
288
|
+
"success": true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Error
|
|
292
|
+
{ "type": "error", "message": "Invalid message or auth failed" }
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Connection Lifecycle:**
|
|
296
|
+
1. Connect to `ws://host:port/ws/analytics`
|
|
297
|
+
2. Send `auth` message with valid JWT and site ID
|
|
298
|
+
3. Receive `auth:success` confirmation
|
|
299
|
+
4. Receive `analytic` events as they occur
|
|
300
|
+
5. Server sends heartbeat pings every 30 seconds — dead connections are cleaned up automatically
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## CDN & Versioning
|
|
305
|
+
|
|
306
|
+
Scripts are served at versioned URLs for cache-safe deployments:
|
|
307
|
+
|
|
308
|
+
| URL | Description |
|
|
309
|
+
|---|---|
|
|
310
|
+
| `/script/ai-agent-bridge.js` | Default path |
|
|
311
|
+
| `/v1/ai-agent-bridge.js` | Version-pinned (recommended) |
|
|
312
|
+
| `/latest/ai-agent-bridge.js` | Always latest (use with caution) |
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Docker
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
# Quick start
|
|
320
|
+
docker compose up -d
|
|
321
|
+
|
|
322
|
+
# Or build manually
|
|
323
|
+
docker build -t web-agent-bridge .
|
|
324
|
+
docker run -p 3000:3000 -e JWT_SECRET=your-secret web-agent-bridge
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Testing
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
npm test
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Tests cover: authentication, site CRUD, config management, license verification, analytics tracking, and static pages.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Agent SDK
|
|
340
|
+
|
|
341
|
+
WAB includes a built-in SDK for building AI agents. See [`sdk/README.md`](sdk/README.md) for full documentation.
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
const puppeteer = require('puppeteer');
|
|
345
|
+
const { WABAgent } = require('web-agent-bridge/sdk');
|
|
346
|
+
|
|
347
|
+
const browser = await puppeteer.launch();
|
|
348
|
+
const page = await browser.newPage();
|
|
349
|
+
const agent = new WABAgent(page);
|
|
350
|
+
|
|
351
|
+
await agent.navigateAndWait('https://example.com');
|
|
352
|
+
const actions = await agent.getActions();
|
|
353
|
+
await agent.execute('signup', { email: 'user@test.com' });
|
|
354
|
+
await browser.close();
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Agent Examples
|
|
360
|
+
|
|
361
|
+
Ready-to-run agent examples in the [`examples/`](examples/) directory:
|
|
362
|
+
|
|
363
|
+
| File | Description |
|
|
364
|
+
|---|---|
|
|
365
|
+
| `puppeteer-agent.js` | Basic agent using Puppeteer + `window.AICommands` |
|
|
366
|
+
| `bidi-agent.js` | Agent using WebDriver BiDi protocol via `window.__wab_bidi` |
|
|
367
|
+
| `vision-agent.js` | Vision/NLP agent — resolves natural language intents to actions |
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
node examples/puppeteer-agent.js http://localhost:3000
|
|
371
|
+
node examples/bidi-agent.js http://localhost:3000
|
|
372
|
+
node examples/vision-agent.js http://localhost:3000
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Multi-Database Support
|
|
378
|
+
|
|
379
|
+
WAB defaults to SQLite but supports PostgreSQL and MySQL via database adapters.
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
# SQLite (default — no setup needed)
|
|
383
|
+
npm start
|
|
384
|
+
|
|
385
|
+
# PostgreSQL
|
|
386
|
+
npm install pg
|
|
387
|
+
DB_ADAPTER=postgresql DATABASE_URL=postgres://user:pass@localhost:5432/wab npm start
|
|
388
|
+
|
|
389
|
+
# MySQL
|
|
390
|
+
npm install mysql2
|
|
391
|
+
DB_ADAPTER=mysql DATABASE_URL=mysql://user:pass@localhost:3306/wab npm start
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### When to Choose Which Database
|
|
395
|
+
|
|
396
|
+
| Scenario | Recommended DB | Why |
|
|
397
|
+
|---|---|---|
|
|
398
|
+
| Local dev / prototyping | SQLite | Zero setup, single file, instant |
|
|
399
|
+
| Small production (< 100 sites) | SQLite | Fast, no external dependencies |
|
|
400
|
+
| Medium production (100-10K sites) | PostgreSQL | Better concurrency, JSONB support |
|
|
401
|
+
| Large / enterprise production | PostgreSQL | Replication, backups, scalability |
|
|
402
|
+
| Existing MySQL infrastructure | MySQL | Integrate with what you already use |
|
|
403
|
+
|
|
404
|
+
See [`server/models/adapters/`](server/models/adapters/) for adapter implementations.
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Security Architecture
|
|
409
|
+
|
|
410
|
+
WAB implements defense-in-depth to protect the bridge from misuse:
|
|
411
|
+
|
|
412
|
+
### Security Sandbox
|
|
413
|
+
|
|
414
|
+
Every bridge instance runs inside a `SecuritySandbox` that provides:
|
|
415
|
+
|
|
416
|
+
- **Session tokens** — Unique cryptographic token per session prevents replay attacks
|
|
417
|
+
- **Origin validation** — Only whitelisted origins can interact with the bridge
|
|
418
|
+
- **Command validation** — All commands are validated for format, length, and blocklist
|
|
419
|
+
- **Audit logging** — Every action is logged with timestamp, agent fingerprint, and status
|
|
420
|
+
- **Escalation protection** — Attempts to access higher-tier features trigger automatic lockdown after 5 violations
|
|
421
|
+
- **Auto-lockdown** — Bridge becomes read-only when security violations are detected
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
// Get security status
|
|
425
|
+
const info = bridge.getPageInfo();
|
|
426
|
+
console.log(info.security);
|
|
427
|
+
// { sandboxActive: true, locked: false, sessionToken: "a3f2..." }
|
|
428
|
+
|
|
429
|
+
// View audit log
|
|
430
|
+
const audit = bridge.security.getAuditLog(20);
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Selector Restrictions
|
|
434
|
+
|
|
435
|
+
Block sensitive page sections from agent access:
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
window.AIBridgeConfig = {
|
|
439
|
+
restrictions: {
|
|
440
|
+
blockedSelectors: [".private", "[data-private]", "#payment-form"],
|
|
441
|
+
allowedSelectors: [".public-content"]
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Self-Healing Selectors
|
|
449
|
+
|
|
450
|
+
Modern SPAs frequently change their DOM structure. WAB's self-healing system ensures selectors keep working even when the page changes:
|
|
451
|
+
|
|
452
|
+
### How It Works
|
|
453
|
+
|
|
454
|
+
1. **Fingerprinting** — When actions are discovered, WAB stores a rich fingerprint of each element (tag, id, classes, text, ARIA attributes, position)
|
|
455
|
+
2. **7-Strategy Resolution** — When a selector breaks, WAB tries these strategies in order:
|
|
456
|
+
- `data-wab-id` attribute (most stable — add to your HTML)
|
|
457
|
+
- `data-testid` attribute
|
|
458
|
+
- Element ID
|
|
459
|
+
- `aria-label` (semantic, usually survives redesigns)
|
|
460
|
+
- `name` attribute
|
|
461
|
+
- Fuzzy text matching (bigram similarity > 70%)
|
|
462
|
+
- Role + position heuristic
|
|
463
|
+
3. **SPA Observer** — A `MutationObserver` watches for DOM changes and automatically re-discovers actions with a 500ms debounce
|
|
464
|
+
|
|
465
|
+
```javascript
|
|
466
|
+
// Check healing stats
|
|
467
|
+
const info = bridge.getPageInfo();
|
|
468
|
+
console.log(info.selfHealing);
|
|
469
|
+
// { tracked: 12, healed: 3, failed: 0 }
|
|
470
|
+
|
|
471
|
+
// Listen for healing events
|
|
472
|
+
bridge.events.on('selector:healed', (data) => {
|
|
473
|
+
console.log(`Healed: ${data.action} via ${data.strategy}`);
|
|
474
|
+
});
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Best Practices for Site Owners
|
|
478
|
+
|
|
479
|
+
Add `data-wab-id` attributes to critical elements for maximum stability:
|
|
480
|
+
|
|
481
|
+
```html
|
|
482
|
+
<button data-wab-id="signup-btn">Sign Up</button>
|
|
483
|
+
<form data-wab-id="login-form">...</form>
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## Stealth Mode
|
|
489
|
+
|
|
490
|
+
For sites with anti-bot protection, WAB can simulate human-like interaction patterns:
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
window.AIBridgeConfig = {
|
|
494
|
+
stealth: { enabled: true }
|
|
495
|
+
};
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
When enabled, all interactions use:
|
|
499
|
+
|
|
500
|
+
| Feature | Description |
|
|
501
|
+
|---|---|
|
|
502
|
+
| **Mouse event chain** | `mouseover → mouseenter → mousemove → mousedown → mouseup → click` with natural coordinates |
|
|
503
|
+
| **Typing simulation** | Character-by-character input with 30-120ms delays per keystroke |
|
|
504
|
+
| **Scroll easing** | Multi-step scrolling with variable speed |
|
|
505
|
+
| **Random delays** | 50-400ms natural pauses between actions |
|
|
506
|
+
|
|
507
|
+
```javascript
|
|
508
|
+
// Enable/disable at runtime
|
|
509
|
+
bridge.stealth.enable();
|
|
510
|
+
bridge.stealth.disable();
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
## CLI
|
|
516
|
+
|
|
517
|
+
Install globally or use via npx:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
# Run the server
|
|
521
|
+
npx web-agent-bridge start
|
|
522
|
+
npx web-agent-bridge start --port 8080
|
|
523
|
+
|
|
524
|
+
# Initialize a new project
|
|
525
|
+
npx web-agent-bridge init
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
## Environment Variables
|
|
531
|
+
|
|
532
|
+
```
|
|
533
|
+
PORT=3000
|
|
534
|
+
JWT_SECRET=your-secret-here
|
|
535
|
+
NODE_ENV=development
|
|
536
|
+
DB_ADAPTER=sqlite # sqlite | postgresql | mysql
|
|
537
|
+
DATABASE_URL= # Required for postgresql/mysql
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## License
|
|
543
|
+
|
|
544
|
+
MIT — Free to use, modify, and distribute.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Web Agent Bridge CLI
|
|
5
|
+
* Usage: npx web-agent-bridge [command]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const command = args[0] || 'start';
|
|
13
|
+
|
|
14
|
+
function printHelp() {
|
|
15
|
+
console.log(`
|
|
16
|
+
Web Agent Bridge CLI
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
npx web-agent-bridge <command> [options]
|
|
20
|
+
|
|
21
|
+
Commands:
|
|
22
|
+
start Start the WAB server (default)
|
|
23
|
+
init Create .env file from template
|
|
24
|
+
help Show this help message
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--port, -p Set server port (default: 3000)
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
npx web-agent-bridge start
|
|
31
|
+
npx web-agent-bridge start --port 4000
|
|
32
|
+
npx web-agent-bridge init
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
switch (command) {
|
|
37
|
+
case 'start': {
|
|
38
|
+
const portIdx = args.indexOf('--port') !== -1 ? args.indexOf('--port') : args.indexOf('-p');
|
|
39
|
+
if (portIdx !== -1 && args[portIdx + 1]) {
|
|
40
|
+
process.env.PORT = args[portIdx + 1];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
44
|
+
if (fs.existsSync(envPath)) {
|
|
45
|
+
require('dotenv').config({ path: envPath });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
require('../server/index.js');
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case 'init': {
|
|
53
|
+
const envExample = path.join(__dirname, '..', '.env.example');
|
|
54
|
+
const envTarget = path.join(process.cwd(), '.env');
|
|
55
|
+
|
|
56
|
+
if (fs.existsSync(envTarget)) {
|
|
57
|
+
console.log(' .env file already exists. Skipping.');
|
|
58
|
+
} else if (fs.existsSync(envExample)) {
|
|
59
|
+
fs.copyFileSync(envExample, envTarget);
|
|
60
|
+
console.log(' Created .env file from template.');
|
|
61
|
+
console.log(' Edit .env to set your JWT_SECRET before starting.');
|
|
62
|
+
} else {
|
|
63
|
+
const defaultEnv = 'PORT=3000\nJWT_SECRET=change-this-to-a-strong-random-secret-in-production\nNODE_ENV=development\n';
|
|
64
|
+
fs.writeFileSync(envTarget, defaultEnv);
|
|
65
|
+
console.log(' Created default .env file.');
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case 'help':
|
|
71
|
+
case '--help':
|
|
72
|
+
case '-h':
|
|
73
|
+
printHelp();
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
default:
|
|
77
|
+
console.error(` Unknown command: ${command}`);
|
|
78
|
+
printHelp();
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
package/bin/wab.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Web Agent Bridge CLI
|
|
5
|
+
* Usage: npx web-agent-bridge [command]
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const command = args[0] || 'start';
|
|
13
|
+
|
|
14
|
+
function printHelp() {
|
|
15
|
+
console.log(`
|
|
16
|
+
Web Agent Bridge CLI
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
npx web-agent-bridge <command> [options]
|
|
20
|
+
|
|
21
|
+
Commands:
|
|
22
|
+
start Start the WAB server (default)
|
|
23
|
+
init Create .env file from template
|
|
24
|
+
help Show this help message
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--port, -p Set server port (default: 3000)
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
npx web-agent-bridge start
|
|
31
|
+
npx web-agent-bridge start --port 4000
|
|
32
|
+
npx web-agent-bridge init
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
switch (command) {
|
|
37
|
+
case 'start': {
|
|
38
|
+
const portIdx = args.indexOf('--port') !== -1 ? args.indexOf('--port') : args.indexOf('-p');
|
|
39
|
+
if (portIdx !== -1 && args[portIdx + 1]) {
|
|
40
|
+
process.env.PORT = args[portIdx + 1];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
44
|
+
if (fs.existsSync(envPath)) {
|
|
45
|
+
require('dotenv').config({ path: envPath });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
require('../server/index.js');
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case 'init': {
|
|
53
|
+
const envExample = path.join(__dirname, '..', '.env.example');
|
|
54
|
+
const envTarget = path.join(process.cwd(), '.env');
|
|
55
|
+
|
|
56
|
+
if (fs.existsSync(envTarget)) {
|
|
57
|
+
console.log(' .env file already exists. Skipping.');
|
|
58
|
+
} else if (fs.existsSync(envExample)) {
|
|
59
|
+
fs.copyFileSync(envExample, envTarget);
|
|
60
|
+
console.log(' Created .env file from template.');
|
|
61
|
+
console.log(' Edit .env to set your JWT_SECRET before starting.');
|
|
62
|
+
} else {
|
|
63
|
+
const defaultEnv = 'PORT=3000\nJWT_SECRET=change-this-to-a-strong-random-secret-in-production\nNODE_ENV=development\n';
|
|
64
|
+
fs.writeFileSync(envTarget, defaultEnv);
|
|
65
|
+
console.log(' Created default .env file.');
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case 'help':
|
|
71
|
+
case '--help':
|
|
72
|
+
case '-h':
|
|
73
|
+
printHelp();
|
|
74
|
+
break;
|
|
75
|
+
|
|
76
|
+
default:
|
|
77
|
+
console.error(` Unknown command: ${command}`);
|
|
78
|
+
printHelp();
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|