web-agent-bridge 3.2.0 → 3.4.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 +84 -72
- package/README.ar.md +1304 -1152
- package/README.md +298 -1635
- package/bin/agent-runner.js +474 -474
- package/bin/cli.js +237 -138
- package/bin/wab-init.js +223 -0
- package/bin/wab.js +80 -80
- package/examples/azure-dns-wab.js +83 -0
- package/examples/bidi-agent.js +119 -119
- package/examples/cloudflare-wab-dns.js +121 -0
- package/examples/cpanel-wab-dns.js +114 -0
- package/examples/cross-site-agent.js +91 -91
- package/examples/dns-discovery-agent.js +166 -0
- package/examples/gcp-dns-wab.js +76 -0
- package/examples/governance-agent.js +169 -0
- package/examples/mcp-agent.js +94 -94
- package/examples/next-app-router/README.md +44 -44
- package/examples/plesk-wab-dns.js +103 -0
- package/examples/puppeteer-agent.js +108 -108
- package/examples/route53-wab-dns.js +144 -0
- package/examples/saas-dashboard/README.md +55 -55
- package/examples/safe-mode-agent.js +96 -0
- package/examples/shopify-hydrogen/README.md +74 -74
- package/examples/vision-agent.js +171 -171
- package/examples/wab-sign.js +74 -0
- package/examples/wab-verify.js +60 -0
- package/examples/wordpress-elementor/README.md +77 -77
- package/package.json +19 -6
- package/public/.well-known/agent-tools.json +180 -180
- package/public/.well-known/ai-assets.json +59 -59
- package/public/.well-known/security.txt +8 -0
- package/public/.well-known/wab.json +28 -0
- package/public/activate.html +368 -0
- package/public/adoption-metrics.html +188 -0
- package/public/agent-workspace.html +349 -349
- package/public/ai.html +198 -198
- package/public/api.html +413 -412
- package/public/azure-dns-integration.html +289 -0
- package/public/browser.html +486 -486
- package/public/cloudflare-integration.html +380 -0
- package/public/commander-dashboard.html +243 -243
- package/public/cookies.html +210 -210
- package/public/cpanel-integration.html +398 -0
- package/public/css/agent-workspace.css +1713 -1713
- package/public/css/premium.css +317 -317
- package/public/css/styles.css +1263 -1235
- package/public/dashboard.html +707 -706
- package/public/dns.html +436 -0
- package/public/docs.html +588 -587
- package/public/feed.xml +89 -89
- package/public/gcp-dns-integration.html +318 -0
- package/public/growth.html +465 -463
- package/public/index.html +1266 -982
- package/public/integrations.html +556 -0
- package/public/js/activate.js +145 -0
- package/public/js/agent-workspace.js +1740 -1740
- package/public/js/auth-nav.js +65 -31
- package/public/js/auth-redirect.js +12 -12
- package/public/js/cookie-consent.js +56 -56
- package/public/js/dns.js +438 -0
- package/public/js/wab-demo-page.js +721 -721
- package/public/js/ws-client.js +74 -74
- package/public/llms-full.txt +360 -360
- package/public/llms.txt +125 -125
- package/public/login.html +85 -85
- package/public/mesh-dashboard.html +328 -328
- package/public/openapi.json +669 -580
- package/public/phone-shield.html +281 -0
- package/public/plesk-integration.html +375 -0
- package/public/premium-dashboard.html +2489 -2489
- package/public/premium.html +793 -793
- package/public/privacy.html +297 -297
- package/public/provider-onboarding.html +172 -0
- package/public/provider-sandbox.html +134 -0
- package/public/providers.html +359 -0
- package/public/register.html +105 -105
- package/public/registrar-integrations.html +141 -0
- package/public/robots.txt +99 -87
- package/public/route53-integration.html +531 -0
- package/public/script/wab-consent.d.ts +36 -36
- package/public/script/wab-consent.js +104 -104
- package/public/script/wab-schema.js +131 -131
- package/public/script/wab.d.ts +108 -108
- package/public/script/wab.min.js +580 -580
- package/public/security.txt +8 -0
- package/public/shieldqr.html +231 -0
- package/public/sitemap.xml +6 -0
- package/public/terms.html +256 -256
- package/public/wab-trust.html +200 -0
- package/public/wab-vs-protocols.html +210 -0
- package/public/whitepaper.html +449 -0
- package/script/ai-agent-bridge.js +1754 -1754
- package/sdk/README.md +99 -99
- package/sdk/agent-mesh.js +449 -449
- package/sdk/auto-discovery.js +288 -0
- package/sdk/commander.js +262 -262
- package/sdk/governance.js +262 -0
- package/sdk/index.d.ts +464 -464
- package/sdk/index.js +25 -1
- package/sdk/multi-agent.js +318 -318
- package/sdk/package.json +2 -2
- package/sdk/safe-mode.js +221 -0
- package/sdk/safety-shield.js +219 -0
- package/sdk/schema-discovery.js +83 -83
- package/server/adapters/index.js +520 -520
- package/server/config/plans.js +367 -367
- package/server/config/secrets.js +102 -102
- package/server/control-plane/index.js +301 -301
- package/server/data-plane/index.js +354 -354
- package/server/index.js +670 -427
- package/server/llm/index.js +404 -404
- package/server/middleware/adminAuth.js +35 -35
- package/server/middleware/auth.js +50 -50
- package/server/middleware/featureGate.js +88 -88
- package/server/middleware/rateLimits.js +100 -100
- package/server/middleware/sensitiveAction.js +157 -0
- package/server/migrations/001_add_analytics_indexes.sql +7 -7
- package/server/migrations/002_premium_features.sql +418 -418
- package/server/migrations/003_ads_integer_cents.sql +33 -33
- package/server/migrations/004_agent_os.sql +158 -158
- package/server/migrations/005_marketplace_metering.sql +126 -126
- package/server/migrations/007_governance.sql +106 -0
- package/server/migrations/008_plans.sql +144 -0
- package/server/migrations/009_shieldqr.sql +30 -0
- package/server/migrations/010_extended_trust.sql +33 -0
- package/server/models/adapters/index.js +33 -33
- package/server/models/adapters/mysql.js +183 -183
- package/server/models/adapters/postgresql.js +172 -172
- package/server/models/adapters/sqlite.js +7 -7
- package/server/models/db.js +740 -681
- package/server/observability/failure-analysis.js +337 -337
- package/server/observability/index.js +394 -394
- package/server/protocol/capabilities.js +223 -223
- package/server/protocol/index.js +243 -243
- package/server/protocol/schema.js +584 -584
- package/server/registry/certification.js +271 -271
- package/server/registry/index.js +326 -326
- package/server/routes/admin-plans.js +76 -0
- package/server/routes/admin-premium.js +673 -671
- package/server/routes/admin-shieldqr.js +90 -0
- package/server/routes/admin-trust-monitor.js +83 -0
- package/server/routes/admin.js +549 -261
- package/server/routes/ads.js +130 -130
- package/server/routes/agent-workspace.js +540 -540
- package/server/routes/api.js +150 -150
- package/server/routes/auth.js +71 -71
- package/server/routes/billing.js +57 -45
- package/server/routes/commander.js +316 -316
- package/server/routes/demo-showcase.js +332 -332
- package/server/routes/demo-store.js +154 -0
- package/server/routes/discovery.js +2348 -417
- package/server/routes/gateway.js +173 -157
- package/server/routes/governance.js +208 -0
- package/server/routes/license.js +251 -240
- package/server/routes/mesh.js +469 -469
- package/server/routes/noscript.js +543 -543
- package/server/routes/plans.js +33 -0
- package/server/routes/premium-v2.js +686 -686
- package/server/routes/premium.js +724 -724
- package/server/routes/providers.js +650 -0
- package/server/routes/runtime.js +2148 -2147
- package/server/routes/shieldqr.js +88 -0
- package/server/routes/sovereign.js +465 -385
- package/server/routes/universal.js +200 -185
- package/server/routes/wab-api.js +850 -501
- package/server/runtime/container-worker.js +111 -111
- package/server/runtime/container.js +448 -448
- package/server/runtime/distributed-worker.js +362 -362
- package/server/runtime/event-bus.js +210 -210
- package/server/runtime/index.js +253 -253
- package/server/runtime/queue.js +599 -599
- package/server/runtime/replay.js +666 -666
- package/server/runtime/sandbox.js +266 -266
- package/server/runtime/scheduler.js +534 -534
- package/server/runtime/session-engine.js +293 -293
- package/server/runtime/state-manager.js +188 -188
- package/server/security/cross-site-redactor.js +196 -0
- package/server/security/dry-run.js +180 -0
- package/server/security/human-gate-rate-limit.js +147 -0
- package/server/security/human-gate-transports.js +178 -0
- package/server/security/human-gate.js +281 -0
- package/server/security/index.js +368 -368
- package/server/security/intent-engine.js +245 -0
- package/server/security/reward-guard.js +171 -0
- package/server/security/rollback-store.js +239 -0
- package/server/security/token-scope.js +404 -0
- package/server/security/url-policy.js +139 -0
- package/server/services/agent-chat.js +506 -506
- package/server/services/agent-learning.js +601 -575
- package/server/services/agent-memory.js +625 -625
- package/server/services/agent-mesh.js +555 -539
- package/server/services/agent-symphony.js +717 -717
- package/server/services/agent-tasks.js +1807 -1807
- package/server/services/api-key-engine.js +292 -261
- package/server/services/cluster.js +894 -894
- package/server/services/commander.js +738 -738
- package/server/services/edge-compute.js +440 -440
- package/server/services/email.js +233 -204
- package/server/services/governance.js +466 -0
- package/server/services/hosted-runtime.js +205 -205
- package/server/services/lfd.js +635 -635
- package/server/services/local-ai.js +389 -389
- package/server/services/marketplace.js +270 -270
- package/server/services/metering.js +182 -182
- package/server/services/modules/affiliate-intelligence.js +93 -93
- package/server/services/modules/agent-firewall.js +90 -90
- package/server/services/modules/bounty.js +89 -89
- package/server/services/modules/collective-bargaining.js +92 -92
- package/server/services/modules/dark-pattern.js +66 -66
- package/server/services/modules/gov-intelligence.js +45 -45
- package/server/services/modules/neural.js +55 -55
- package/server/services/modules/notary.js +49 -49
- package/server/services/modules/price-time-machine.js +86 -86
- package/server/services/modules/protocol.js +104 -104
- package/server/services/negotiation.js +439 -439
- package/server/services/plans.js +214 -0
- package/server/services/plugins.js +771 -771
- package/server/services/premium.js +1 -1
- package/server/services/price-intelligence.js +566 -566
- package/server/services/price-shield.js +1137 -1137
- package/server/services/provider-clients.js +740 -0
- package/server/services/reputation.js +465 -465
- package/server/services/search-engine.js +357 -357
- package/server/services/security.js +513 -513
- package/server/services/self-healing.js +843 -843
- package/server/services/shieldqr.js +322 -0
- package/server/services/sovereign-shield.js +542 -0
- package/server/services/ssl-inspector.js +42 -0
- package/server/services/ssl-monitor.js +167 -0
- package/server/services/stripe.js +205 -192
- package/server/services/swarm.js +788 -788
- package/server/services/universal-scraper.js +662 -661
- package/server/services/verification.js +481 -481
- package/server/services/vision.js +1163 -1163
- package/server/services/wab-crypto.js +178 -0
- package/server/utils/cache.js +125 -125
- package/server/utils/migrate.js +81 -81
- package/server/utils/safe-fetch.js +228 -0
- package/server/utils/secureFields.js +50 -50
- package/server/ws.js +161 -161
- package/templates/artisan-marketplace.yaml +104 -104
- package/templates/book-price-scout.yaml +98 -98
- package/templates/electronics-price-tracker.yaml +108 -108
- package/templates/flight-deal-hunter.yaml +113 -113
- package/templates/freelancer-direct.yaml +116 -116
- package/templates/grocery-price-compare.yaml +93 -93
- package/templates/hotel-direct-booking.yaml +113 -113
- package/templates/local-services.yaml +98 -98
- package/templates/olive-oil-tunisia.yaml +88 -88
- package/templates/organic-farm-fresh.yaml +101 -101
- package/templates/restaurant-direct.yaml +97 -97
- package/public/score.html +0 -263
- package/server/migrations/006_growth_suite.sql +0 -138
- package/server/routes/growth.js +0 -962
- package/server/services/fairness-engine.js +0 -409
- package/server/services/fairness.js +0 -420
package/bin/cli.js
CHANGED
|
@@ -1,138 +1,237 @@
|
|
|
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
|
|
24
|
-
run <file> Run an agent template (YAML)
|
|
25
|
-
templates List available agent templates
|
|
26
|
-
help Show this help message
|
|
27
|
-
|
|
28
|
-
Options:
|
|
29
|
-
--port, -p
|
|
30
|
-
--server
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
npx wab
|
|
37
|
-
npx wab
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
console.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (!
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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 Make this site AI-discoverable — scaffold wab.json + security.txt + .env, print DNS records
|
|
24
|
+
run <file> Run an agent template (YAML)
|
|
25
|
+
templates List available agent templates
|
|
26
|
+
help Show this help message
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
--port, -p Set server port (default: 3000)
|
|
30
|
+
--server WAB server URL (for agent templates)
|
|
31
|
+
--site <url> Canonical site URL for 'init' (default: from package.json or localhost)
|
|
32
|
+
--env-only 'init' skips wab.json, only creates .env
|
|
33
|
+
--force 'init' overwrites existing wab.json
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
npx wab init # make this site AI-discoverable
|
|
37
|
+
npx wab init --site https://example.com # explicit site URL
|
|
38
|
+
npx wab start
|
|
39
|
+
npx wab start --port 4000
|
|
40
|
+
npx wab-agent run olive-oil-tunisia.yaml
|
|
41
|
+
npx wab-agent templates
|
|
42
|
+
`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
switch (command) {
|
|
46
|
+
case 'start': {
|
|
47
|
+
const portIdx = args.indexOf('--port') !== -1 ? args.indexOf('--port') : args.indexOf('-p');
|
|
48
|
+
if (portIdx !== -1 && args[portIdx + 1]) {
|
|
49
|
+
process.env.PORT = args[portIdx + 1];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
53
|
+
if (fs.existsSync(envPath)) {
|
|
54
|
+
require('dotenv').config({ path: envPath });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
require('../server/index.js');
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
case 'init': {
|
|
62
|
+
// `npx wab init` — make this site AI-discoverable in 5 minutes.
|
|
63
|
+
// Scaffolds:
|
|
64
|
+
// 1. ./.well-known/wab.json (the discovery contract)
|
|
65
|
+
// 2. ./.well-known/security.txt (RFC 9116, helpful default)
|
|
66
|
+
// 3. .env (server config, only if missing)
|
|
67
|
+
// 4. Prints the exact DNS records to paste at the registrar.
|
|
68
|
+
// Flags:
|
|
69
|
+
// --site <url> Canonical site URL (default: detect or http://localhost:3000)
|
|
70
|
+
// --env-only Only create .env, skip discovery scaffolding
|
|
71
|
+
// --force Overwrite existing wab.json
|
|
72
|
+
const flags = {};
|
|
73
|
+
for (let i = 1; i < args.length; i++) {
|
|
74
|
+
if (args[i] === '--env-only') flags.envOnly = true;
|
|
75
|
+
else if (args[i] === '--force') flags.force = true;
|
|
76
|
+
else if (args[i] === '--site' && args[i + 1]) { flags.site = args[i + 1]; i++; }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const cwd = process.cwd();
|
|
80
|
+
const envExample = path.join(__dirname, '..', '.env.example');
|
|
81
|
+
const envTarget = path.join(cwd, '.env');
|
|
82
|
+
|
|
83
|
+
// Always handle .env
|
|
84
|
+
if (fs.existsSync(envTarget)) {
|
|
85
|
+
console.log(' ✓ .env already exists');
|
|
86
|
+
} else if (fs.existsSync(envExample)) {
|
|
87
|
+
fs.copyFileSync(envExample, envTarget);
|
|
88
|
+
console.log(' ✓ Created .env from template');
|
|
89
|
+
} else {
|
|
90
|
+
const defaultEnv = 'PORT=3000\nJWT_SECRET=change-this-to-a-strong-random-secret-in-production\nNODE_ENV=development\n';
|
|
91
|
+
fs.writeFileSync(envTarget, defaultEnv);
|
|
92
|
+
console.log(' ✓ Created default .env');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (flags.envOnly) break;
|
|
96
|
+
|
|
97
|
+
// Detect site URL
|
|
98
|
+
let site = flags.site;
|
|
99
|
+
if (!site) {
|
|
100
|
+
try {
|
|
101
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
|
|
102
|
+
site = pkg.homepage || (pkg.repository && pkg.repository.url) || '';
|
|
103
|
+
if (site && !/^https?:\/\//.test(site)) site = '';
|
|
104
|
+
} catch { /* no pkg */ }
|
|
105
|
+
}
|
|
106
|
+
if (!site) site = 'http://localhost:3000';
|
|
107
|
+
site = site.replace(/\/$/, '');
|
|
108
|
+
|
|
109
|
+
let host = site;
|
|
110
|
+
try { host = new URL(site).hostname; } catch { /* keep as-is */ }
|
|
111
|
+
const apex = host.replace(/^www\./, '').split('.').slice(-2).join('.') || host;
|
|
112
|
+
|
|
113
|
+
// 1. wab.json scaffold
|
|
114
|
+
const wabDir = path.join(cwd, '.well-known');
|
|
115
|
+
const wabFile = path.join(wabDir, 'wab.json');
|
|
116
|
+
if (!fs.existsSync(wabFile) || flags.force) {
|
|
117
|
+
if (!fs.existsSync(wabDir)) fs.mkdirSync(wabDir, { recursive: true });
|
|
118
|
+
const wabJson = {
|
|
119
|
+
version: '1.0',
|
|
120
|
+
protocol: 'wab',
|
|
121
|
+
site: site,
|
|
122
|
+
endpoints: {
|
|
123
|
+
discover: site + '/.well-known/wab.json',
|
|
124
|
+
api: site + '/api/wab',
|
|
125
|
+
actions: site + '/api/wab/actions'
|
|
126
|
+
},
|
|
127
|
+
capabilities: ['readContent', 'click', 'scroll', 'extractData'],
|
|
128
|
+
permissions: { fillForms: false, automatedLogin: false, navigate: false },
|
|
129
|
+
rate_limit: { requests_per_minute: 60 },
|
|
130
|
+
contact: { security: site + '/.well-known/security.txt' },
|
|
131
|
+
ai_friendly: true,
|
|
132
|
+
generated_by: 'npx wab init',
|
|
133
|
+
generated_at: new Date().toISOString()
|
|
134
|
+
};
|
|
135
|
+
fs.writeFileSync(wabFile, JSON.stringify(wabJson, null, 2));
|
|
136
|
+
console.log(' ✓ Created .well-known/wab.json');
|
|
137
|
+
} else {
|
|
138
|
+
console.log(' ✓ .well-known/wab.json already exists (use --force to overwrite)');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 2. security.txt scaffold (only if missing)
|
|
142
|
+
const secFile = path.join(wabDir, 'security.txt');
|
|
143
|
+
if (!fs.existsSync(secFile)) {
|
|
144
|
+
const expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString();
|
|
145
|
+
const sec =
|
|
146
|
+
'Contact: mailto:security@' + apex + '\n' +
|
|
147
|
+
'Expires: ' + expires + '\n' +
|
|
148
|
+
'Preferred-Languages: en, ar\n' +
|
|
149
|
+
'Canonical: ' + site + '/.well-known/security.txt\n';
|
|
150
|
+
fs.writeFileSync(secFile, sec);
|
|
151
|
+
console.log(' ✓ Created .well-known/security.txt');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 3. Print DNS records
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log(' ───────────────────────────────────────────────────────────');
|
|
157
|
+
console.log(' Make your site AI-discoverable — paste these at your DNS panel:');
|
|
158
|
+
console.log(' ───────────────────────────────────────────────────────────');
|
|
159
|
+
console.log('');
|
|
160
|
+
console.log(' Type Name Value');
|
|
161
|
+
console.log(' ──── ───────────── ──────────────────────────────────────────────');
|
|
162
|
+
console.log(' TXT _wab v=wab1; endpoint=' + site + '/.well-known/wab.json');
|
|
163
|
+
console.log(' TXT _wab-trust trust=' + site + '/trust.json; security=' + site + '/.well-known/security.txt');
|
|
164
|
+
console.log(' TXT _wab-agent agent=' + site + '/agent-bridge.json; ver=2');
|
|
165
|
+
console.log('');
|
|
166
|
+
console.log(' Apex domain detected: ' + apex);
|
|
167
|
+
console.log(' Verify after propagation: https://webagentbridge.com/dns#verifier');
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(' ✓ Done. Your site speaks WAB. Run `npx wab start` to launch the local server.');
|
|
170
|
+
console.log('');
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
case 'help':
|
|
175
|
+
case '--help':
|
|
176
|
+
case '-h':
|
|
177
|
+
printHelp();
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
case 'run': {
|
|
181
|
+
const templateArg = args[1];
|
|
182
|
+
if (!templateArg) {
|
|
183
|
+
console.error(' Error: Please specify a template file.');
|
|
184
|
+
console.error(' Usage: npx wab-agent run <template.yaml> [--param value ...]');
|
|
185
|
+
console.error(' Run "npx wab-agent templates" to see available templates.');
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
const runner = require('./agent-runner');
|
|
189
|
+
const cliParams = {};
|
|
190
|
+
for (let i = 2; i < args.length; i++) {
|
|
191
|
+
if (args[i].startsWith('--') && args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
192
|
+
cliParams[args[i].slice(2)] = args[i + 1];
|
|
193
|
+
i++;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
runner.run(templateArg, cliParams).catch(function(err) {
|
|
197
|
+
console.error(' Agent error:', err.message);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
});
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
case 'templates': {
|
|
204
|
+
const templatesDir = path.join(__dirname, '..', 'templates');
|
|
205
|
+
if (!fs.existsSync(templatesDir)) {
|
|
206
|
+
console.log(' No templates directory found.');
|
|
207
|
+
process.exit(0);
|
|
208
|
+
}
|
|
209
|
+
const files = fs.readdirSync(templatesDir).filter(function(f) { return f.endsWith('.yaml') || f.endsWith('.yml'); });
|
|
210
|
+
if (files.length === 0) {
|
|
211
|
+
console.log(' No templates found.');
|
|
212
|
+
process.exit(0);
|
|
213
|
+
}
|
|
214
|
+
console.log('\n Available Agent Templates:\n');
|
|
215
|
+
console.log(' ' + '─'.repeat(70));
|
|
216
|
+
for (const file of files) {
|
|
217
|
+
try {
|
|
218
|
+
const content = fs.readFileSync(path.join(templatesDir, file), 'utf8');
|
|
219
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
220
|
+
const descMatch = content.match(/^description:\s*(.+)$/m);
|
|
221
|
+
const name = nameMatch ? nameMatch[1].trim() : file.replace(/\.ya?ml$/, '');
|
|
222
|
+
const desc = descMatch ? descMatch[1].trim() : '';
|
|
223
|
+
console.log(` ${name.padEnd(30)} ${desc.slice(0, 50)}`);
|
|
224
|
+
} catch(e) {
|
|
225
|
+
console.log(` ${file}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
console.log(' ' + '─'.repeat(70));
|
|
229
|
+
console.log(`\n Run: npx wab-agent run <template-name>.yaml\n`);
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
default:
|
|
234
|
+
console.error(` Unknown command: ${command}`);
|
|
235
|
+
printHelp();
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
package/bin/wab-init.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* wab-init — Zero-Config WAB initializer
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx wab-init # interactive
|
|
7
|
+
* npx wab-init --site=https://acme.com --name="Acme" --yes
|
|
8
|
+
*
|
|
9
|
+
* Detects project type (Next.js, Nuxt, Laravel, WordPress, static) and
|
|
10
|
+
* scaffolds /.well-known/wab.json with sensible defaults plus prints
|
|
11
|
+
* platform-specific DNS TXT instructions.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const readline = require('readline');
|
|
19
|
+
|
|
20
|
+
const ARG = parseArgs(process.argv.slice(2));
|
|
21
|
+
|
|
22
|
+
function parseArgs(argv) {
|
|
23
|
+
const out = { _: [] };
|
|
24
|
+
for (const a of argv) {
|
|
25
|
+
if (a.startsWith('--')) {
|
|
26
|
+
const [k, ...rest] = a.slice(2).split('=');
|
|
27
|
+
out[k] = rest.length ? rest.join('=') : true;
|
|
28
|
+
} else out._.push(a);
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ask(rl, q, def) {
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
const prompt = def ? `${q} [${def}]: ` : `${q}: `;
|
|
36
|
+
rl.question(prompt, (ans) => resolve((ans || '').trim() || def || ''));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* ------------------------------------------------------------------ */
|
|
41
|
+
/* Project detection */
|
|
42
|
+
/* ------------------------------------------------------------------ */
|
|
43
|
+
|
|
44
|
+
function detectProject(cwd) {
|
|
45
|
+
const has = (f) => fs.existsSync(path.join(cwd, f));
|
|
46
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
47
|
+
let pkg = null;
|
|
48
|
+
if (has('package.json')) {
|
|
49
|
+
try { pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); } catch {}
|
|
50
|
+
}
|
|
51
|
+
const deps = pkg ? Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {}) : {};
|
|
52
|
+
|
|
53
|
+
if (deps.next) return { type: 'nextjs', pkg };
|
|
54
|
+
if (deps.nuxt || deps.nuxt3 || deps['nuxt-edge']) return { type: 'nuxt', pkg };
|
|
55
|
+
if (deps['@sveltejs/kit']) return { type: 'sveltekit', pkg };
|
|
56
|
+
if (deps.astro) return { type: 'astro', pkg };
|
|
57
|
+
if (deps.gatsby) return { type: 'gatsby', pkg };
|
|
58
|
+
if (deps['react-scripts'] || deps.vite) return { type: 'spa', pkg };
|
|
59
|
+
if (has('wp-config.php') || has('wp-content')) return { type: 'wordpress', pkg };
|
|
60
|
+
if (has('artisan') && has('composer.json')) return { type: 'laravel', pkg };
|
|
61
|
+
if (has('composer.json')) return { type: 'php', pkg };
|
|
62
|
+
if (has('manage.py')) return { type: 'django', pkg };
|
|
63
|
+
if (has('Gemfile')) return { type: 'rails', pkg };
|
|
64
|
+
if (pkg) return { type: 'node', pkg };
|
|
65
|
+
return { type: 'static', pkg: null };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function publicDirFor(type, cwd) {
|
|
69
|
+
const candidates = {
|
|
70
|
+
nextjs: ['public'],
|
|
71
|
+
nuxt: ['public', 'static'],
|
|
72
|
+
sveltekit: ['static'],
|
|
73
|
+
astro: ['public'],
|
|
74
|
+
gatsby: ['static'],
|
|
75
|
+
spa: ['public'],
|
|
76
|
+
wordpress: ['.'],
|
|
77
|
+
laravel: ['public'],
|
|
78
|
+
php: ['public', '.'],
|
|
79
|
+
django: ['static'],
|
|
80
|
+
rails: ['public'],
|
|
81
|
+
node: ['public', '.'],
|
|
82
|
+
static: ['.']
|
|
83
|
+
};
|
|
84
|
+
for (const c of candidates[type] || ['.']) {
|
|
85
|
+
if (fs.existsSync(path.join(cwd, c))) return c;
|
|
86
|
+
}
|
|
87
|
+
return '.';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* ------------------------------------------------------------------ */
|
|
91
|
+
/* wab.json builder */
|
|
92
|
+
/* ------------------------------------------------------------------ */
|
|
93
|
+
|
|
94
|
+
function buildWabJson({ siteUrl, name, description, projectType }) {
|
|
95
|
+
const baseActions = [
|
|
96
|
+
{ name: 'home', description: 'Open homepage', url: siteUrl }
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
// Project-aware default action hints (heuristic, user can edit).
|
|
100
|
+
const hints = {
|
|
101
|
+
wordpress: [
|
|
102
|
+
{ name: 'browseBlog', description: 'Browse blog posts', url: `${siteUrl}/?feed=rss2` },
|
|
103
|
+
{ name: 'searchSite', description: 'Search the site', urlTemplate: `${siteUrl}/?s={query}` }
|
|
104
|
+
],
|
|
105
|
+
nextjs: [
|
|
106
|
+
{ name: 'browseSitemap', description: 'Site URL inventory', url: `${siteUrl}/sitemap.xml` }
|
|
107
|
+
],
|
|
108
|
+
laravel: [
|
|
109
|
+
{ name: 'browseSitemap', description: 'Site URL inventory', url: `${siteUrl}/sitemap.xml` }
|
|
110
|
+
],
|
|
111
|
+
static: []
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
version: '1.0',
|
|
116
|
+
site: name,
|
|
117
|
+
description: description || `${name} — managed by Web Agent Bridge`,
|
|
118
|
+
url: siteUrl,
|
|
119
|
+
project_type: projectType,
|
|
120
|
+
generated_at: new Date().toISOString(),
|
|
121
|
+
generator: 'wab-init',
|
|
122
|
+
discovery: {
|
|
123
|
+
well_known: `${siteUrl}/.well-known/wab.json`,
|
|
124
|
+
dns_txt_record: `_wab.${new URL(siteUrl).hostname}`
|
|
125
|
+
},
|
|
126
|
+
actions: [...baseActions, ...(hints[projectType] || [])],
|
|
127
|
+
trust: {
|
|
128
|
+
signed: false,
|
|
129
|
+
note: 'Run `npm run wab:sign` (or scripts/sign-wab-domain.js) to add an Ed25519 signature.'
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* ------------------------------------------------------------------ */
|
|
135
|
+
/* DNS instructions */
|
|
136
|
+
/* ------------------------------------------------------------------ */
|
|
137
|
+
|
|
138
|
+
function dnsInstructions(host) {
|
|
139
|
+
return `
|
|
140
|
+
DNS Discovery (recommended for full WAB Trust):
|
|
141
|
+
Add this TXT record at your DNS provider:
|
|
142
|
+
|
|
143
|
+
Name: _wab.${host}
|
|
144
|
+
Type: TXT
|
|
145
|
+
Value: v=wab1; well-known=https://${host}/.well-known/wab.json
|
|
146
|
+
|
|
147
|
+
Cloudflare: DNS → Records → Add record (Type=TXT)
|
|
148
|
+
Route 53: Hosted zones → Create record (Type=TXT)
|
|
149
|
+
Namecheap: Advanced DNS → Add New Record (Type=TXT)
|
|
150
|
+
GoDaddy: DNS Management → Add → TXT
|
|
151
|
+
cPanel: Zone Editor → Add Record → TXT
|
|
152
|
+
|
|
153
|
+
After publishing, verify at:
|
|
154
|
+
https://www.webagentbridge.com/check?host=${host}
|
|
155
|
+
`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* ------------------------------------------------------------------ */
|
|
159
|
+
/* Main */
|
|
160
|
+
/* ------------------------------------------------------------------ */
|
|
161
|
+
|
|
162
|
+
async function main() {
|
|
163
|
+
const cwd = process.cwd();
|
|
164
|
+
const detected = detectProject(cwd);
|
|
165
|
+
console.log(`\n Web Agent Bridge — wab-init`);
|
|
166
|
+
console.log(` Detected project: ${detected.type}` +
|
|
167
|
+
(detected.pkg && detected.pkg.name ? ` (${detected.pkg.name})` : '') + '\n');
|
|
168
|
+
|
|
169
|
+
let siteUrl = ARG.site || ARG.url;
|
|
170
|
+
let name = ARG.name;
|
|
171
|
+
let description = ARG.description;
|
|
172
|
+
|
|
173
|
+
if (!ARG.yes && (!siteUrl || !name)) {
|
|
174
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
175
|
+
try {
|
|
176
|
+
siteUrl = siteUrl || await ask(rl, 'Site URL (https://example.com)', 'https://example.com');
|
|
177
|
+
name = name || await ask(rl, 'Site name', detected.pkg && detected.pkg.name || 'My Site');
|
|
178
|
+
description = description || await ask(rl, 'Short description', '');
|
|
179
|
+
} finally {
|
|
180
|
+
rl.close();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (!siteUrl) siteUrl = 'https://example.com';
|
|
185
|
+
if (!name) name = (detected.pkg && detected.pkg.name) || 'My Site';
|
|
186
|
+
|
|
187
|
+
// Normalize URL
|
|
188
|
+
if (!/^https?:\/\//i.test(siteUrl)) siteUrl = `https://${siteUrl}`;
|
|
189
|
+
siteUrl = siteUrl.replace(/\/+$/, '');
|
|
190
|
+
const host = new URL(siteUrl).hostname;
|
|
191
|
+
|
|
192
|
+
const wab = buildWabJson({ siteUrl, name, description, projectType: detected.type });
|
|
193
|
+
|
|
194
|
+
const pubDir = publicDirFor(detected.type, cwd);
|
|
195
|
+
const wellKnownDir = path.join(cwd, pubDir, '.well-known');
|
|
196
|
+
const wabPath = path.join(wellKnownDir, 'wab.json');
|
|
197
|
+
|
|
198
|
+
if (fs.existsSync(wabPath) && !ARG.force && !ARG.yes) {
|
|
199
|
+
console.log(`\n ! ${path.relative(cwd, wabPath)} already exists. Use --force to overwrite.`);
|
|
200
|
+
process.exit(2);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
fs.mkdirSync(wellKnownDir, { recursive: true });
|
|
204
|
+
fs.writeFileSync(wabPath, JSON.stringify(wab, null, 2) + '\n');
|
|
205
|
+
|
|
206
|
+
console.log(`\n Wrote: ${path.relative(cwd, wabPath)}`);
|
|
207
|
+
console.log(` URL: ${siteUrl}/.well-known/wab.json`);
|
|
208
|
+
console.log(dnsInstructions(host));
|
|
209
|
+
console.log(` Next steps:`);
|
|
210
|
+
console.log(` 1. Deploy your site so /.well-known/wab.json is publicly reachable.`);
|
|
211
|
+
console.log(` 2. Add the DNS TXT record above.`);
|
|
212
|
+
console.log(` 3. (Optional) Sign with Ed25519: see scripts/sign-wab-domain.js`);
|
|
213
|
+
console.log(` 4. Verify: https://www.webagentbridge.com/check?host=${host}\n`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (require.main === module) {
|
|
217
|
+
main().catch((e) => {
|
|
218
|
+
console.error('wab-init failed:', e.message);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = { detectProject, buildWabJson, publicDirFor };
|