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/README.md ADDED
@@ -0,0 +1,544 @@
1
+ # Web Agent Bridge (WAB)
2
+
3
+ [![CI](https://github.com/abokenan444/web-agent-bridge/actions/workflows/ci.yml/badge.svg)](https://github.com/abokenan444/web-agent-bridge/actions/workflows/ci.yml)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org/)
6
+ [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](https://hub.docker.com/)
7
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](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
+ }