web-agent-bridge 3.4.0 → 3.8.1
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 -84
- package/README.ar.md +1563 -1304
- package/README.md +137 -298
- package/bin/agent-runner.js +474 -474
- package/bin/cli.js +237 -237
- package/bin/wab-init.js +244 -223
- package/bin/wab.js +80 -80
- package/examples/azure-dns-wab.js +83 -83
- package/examples/bidi-agent.js +119 -119
- package/examples/cloudflare-wab-dns.js +121 -121
- package/examples/cpanel-wab-dns.js +114 -114
- package/examples/cross-site-agent.js +91 -91
- package/examples/dns-discovery-agent.js +166 -166
- package/examples/gcp-dns-wab.js +76 -76
- package/examples/governance-agent.js +169 -169
- package/examples/mcp-agent.js +94 -94
- package/examples/next-app-router/README.md +44 -44
- package/examples/plesk-wab-dns.js +103 -103
- package/examples/puppeteer-agent.js +108 -108
- package/examples/route53-wab-dns.js +144 -144
- package/examples/saas-dashboard/README.md +55 -55
- package/examples/safe-mode-agent.js +96 -96
- package/examples/self-discovery.js +106 -0
- package/examples/shopify-hydrogen/README.md +74 -74
- package/examples/vision-agent.js +171 -171
- package/examples/wab-sign.js +74 -74
- package/examples/wab-verify.js +60 -60
- package/examples/wordpress-elementor/README.md +77 -77
- package/package.json +93 -93
- 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 -8
- package/public/.well-known/wab.json +28 -28
- package/public/activate.html +448 -368
- package/public/adopt.html +236 -0
- package/public/adoption-metrics.html +188 -188
- package/public/agent-workspace.html +359 -349
- package/public/ai.html +198 -198
- package/public/api.html +397 -413
- package/public/azure-dns-integration.html +289 -289
- package/public/browser.html +486 -486
- package/public/cloudflare-integration.html +380 -380
- package/public/commander-dashboard.html +243 -243
- package/public/cookies.html +210 -210
- package/public/cpanel-integration.html +398 -398
- package/public/css/agent-workspace.css +1713 -1713
- package/public/css/premium.css +317 -317
- package/public/css/styles.css +1401 -1263
- package/public/dashboard-shieldlink.html +295 -0
- package/public/dashboard.html +711 -707
- package/public/dns.html +436 -436
- package/public/docs.html +588 -588
- package/public/enterprise-mesh.ar.html +80 -0
- package/public/enterprise-mesh.html +81 -0
- package/public/feed.xml +89 -89
- package/public/gcp-dns-integration.html +318 -318
- package/public/governance.ar.html +70 -0
- package/public/governance.html +69 -0
- package/public/growth.html +465 -465
- package/public/index.html +1372 -1266
- package/public/integrations.html +556 -556
- package/public/js/activate.js +449 -145
- package/public/js/agent-workspace.js +1740 -1740
- package/public/js/auth-nav.js +117 -65
- package/public/js/auth-redirect.js +12 -12
- package/public/js/cookie-consent.js +56 -56
- package/public/js/dns.js +438 -438
- package/public/js/wab-demo-page.js +721 -721
- package/public/js/ws-client.js +74 -74
- package/public/l-preview.html +242 -0
- 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/milestones.html +346 -0
- package/public/one-click.html +779 -0
- package/public/openapi.json +669 -669
- package/public/partners.ar.html +145 -0
- package/public/partners.html +143 -0
- package/public/phone-shield.html +281 -281
- package/public/plesk-integration.html +375 -375
- 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 -172
- package/public/provider-sandbox.html +134 -134
- package/public/providers.html +359 -359
- package/public/refusals.html +172 -0
- package/public/register.html +105 -105
- package/public/registrar-integrations.html +141 -141
- package/public/ring4.html +292 -0
- package/public/robots.txt +99 -99
- package/public/route53-integration.html +531 -531
- package/public/score.html +263 -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 -8
- package/public/shieldlink.html +244 -0
- package/public/shieldqr.html +231 -231
- package/public/sitemap.xml +13 -1
- package/public/terms.html +256 -256
- package/public/trust-graph-api.ar.html +92 -0
- package/public/trust-graph-api.html +91 -0
- package/public/wab-features.html +560 -0
- package/public/wab-trust.html +200 -200
- package/public/wab-truth.html +375 -0
- package/public/wab-vs-protocols.html +210 -210
- package/public/whitepaper.html +449 -449
- 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 +301 -288
- package/sdk/commander.js +262 -262
- package/sdk/governance.js +262 -262
- package/sdk/index.d.ts +464 -464
- package/sdk/index.js +649 -649
- package/sdk/multi-agent.js +318 -318
- package/sdk/safe-mode.js +221 -221
- package/sdk/safety-shield.js +219 -219
- package/sdk/schema-discovery.js +83 -83
- package/server/adapters/index.js +520 -520
- package/server/config/plans.js +412 -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 +790 -670
- package/server/llm/index.js +404 -404
- package/server/middleware/adminAuth.js +35 -35
- package/server/middleware/api-tier.js +170 -0
- 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 -157
- package/server/middleware/wab-trust.js +141 -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/006_growth_suite.sql +138 -0
- package/server/migrations/007_governance.sql +106 -106
- package/server/migrations/008_plans.sql +144 -144
- package/server/migrations/009_shieldqr.sql +30 -30
- package/server/migrations/010_extended_trust.sql +33 -33
- package/server/migrations/011_outreach.sql +47 -0
- package/server/migrations/012_shieldlink.sql +116 -0
- package/server/migrations/013_ct_monitor.sql +13 -0
- package/server/migrations/014_wab_advanced_features.sql +128 -0
- package/server/migrations/015_wab_truth_layer.sql +101 -0
- package/server/migrations/016_ring4_external_trust.sql +84 -0
- package/server/migrations/017_ring4_extensions.sql +69 -0
- package/server/migrations/018_commercial_foundations.sql +167 -0
- package/server/migrations/019_unify_tier_constraints.sql +133 -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 -740
- 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/activate.js +478 -0
- package/server/routes/admin-outreach.js +239 -0
- package/server/routes/admin-plans.js +76 -76
- package/server/routes/admin-premium.js +674 -673
- package/server/routes/admin-shieldlink.js +137 -0
- package/server/routes/admin-shieldqr.js +90 -90
- package/server/routes/admin-trust-monitor.js +139 -83
- package/server/routes/admin.js +550 -549
- package/server/routes/adopt.js +61 -0
- package/server/routes/ads.js +130 -130
- package/server/routes/agent-workspace.js +540 -540
- package/server/routes/api-keys.js +127 -0
- package/server/routes/api.js +150 -150
- package/server/routes/auth.js +71 -71
- package/server/routes/billing.js +57 -57
- package/server/routes/commander.js +316 -316
- package/server/routes/customer-shieldlink.js +133 -0
- package/server/routes/demo-showcase.js +332 -332
- package/server/routes/demo-store.js +154 -154
- package/server/routes/diagnose.js +373 -0
- package/server/routes/discovery.js +2348 -2348
- package/server/routes/enterprise-mesh.js +170 -0
- package/server/routes/gateway.js +173 -173
- package/server/routes/governance-saas.js +203 -0
- package/server/routes/governance.js +208 -208
- package/server/routes/growth.js +1048 -0
- package/server/routes/intent.js +328 -0
- package/server/routes/license.js +251 -251
- package/server/routes/mesh.js +469 -469
- package/server/routes/noscript.js +543 -543
- package/server/routes/partners.js +201 -0
- package/server/routes/plans.js +33 -33
- package/server/routes/premium-v2.js +686 -686
- package/server/routes/premium.js +724 -724
- package/server/routes/providers.js +650 -650
- package/server/routes/reputation.js +411 -0
- package/server/routes/ring4.js +885 -0
- package/server/routes/runtime.js +2148 -2148
- package/server/routes/shieldlink.js +70 -0
- package/server/routes/shieldqr.js +88 -88
- package/server/routes/sovereign.js +465 -465
- package/server/routes/truth-layer.js +670 -0
- package/server/routes/universal.js +200 -200
- package/server/routes/unsubscribe.js +51 -0
- package/server/routes/wab-api.js +850 -850
- package/server/routes/wab-cache.js +282 -0
- 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/secrets/wab-signing-key.pem +3 -0
- package/server/secrets/wab-signing-pub.pem +3 -0
- package/server/security/cross-site-redactor.js +196 -196
- package/server/security/dry-run.js +180 -180
- package/server/security/human-gate-rate-limit.js +147 -147
- package/server/security/human-gate-transports.js +178 -178
- package/server/security/human-gate.js +281 -281
- package/server/security/index.js +368 -368
- package/server/security/intent-engine.js +245 -245
- package/server/security/reward-guard.js +171 -171
- package/server/security/rollback-store.js +239 -239
- package/server/security/token-scope.js +404 -404
- package/server/security/url-policy.js +139 -139
- package/server/services/adoption-agent.js +182 -0
- package/server/services/agent-chat.js +506 -506
- package/server/services/agent-learning.js +601 -601
- package/server/services/agent-memory.js +625 -625
- package/server/services/agent-mesh.js +555 -555
- package/server/services/agent-symphony.js +717 -717
- package/server/services/agent-tasks.js +1807 -1807
- package/server/services/api-key-engine.js +292 -292
- 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 -233
- package/server/services/fairness-engine.js +409 -0
- package/server/services/fairness.js +420 -0
- package/server/services/governance.js +466 -466
- 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/outreach-agent.js +312 -0
- package/server/services/plans.js +214 -214
- package/server/services/plugins.js +771 -771
- package/server/services/price-intelligence.js +566 -566
- package/server/services/price-shield.js +1137 -1137
- package/server/services/provider-clients.js +740 -740
- 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/shieldlink.js +492 -0
- package/server/services/shieldqr.js +322 -322
- package/server/services/sovereign-shield.js +542 -542
- package/server/services/ssl-ct-monitor.js +224 -0
- package/server/services/ssl-inspector.js +42 -42
- package/server/services/ssl-monitor.js +167 -167
- package/server/services/stripe.js +206 -205
- package/server/services/swarm.js +788 -788
- package/server/services/universal-scraper.js +662 -662
- package/server/services/verification.js +481 -481
- package/server/services/vision.js +1163 -1163
- package/server/services/wab-crypto.js +178 -178
- package/server/utils/cache.js +125 -125
- package/server/utils/migrate.js +81 -81
- package/server/utils/safe-fetch.js +228 -228
- 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/templates/ring4/banking-sovereign.yaml +55 -0
- package/templates/ring4/ecommerce-sovereign.yaml +58 -0
- package/templates/ring4/healthcare-sovereign.yaml +60 -0
package/bin/wab-init.js
CHANGED
|
@@ -1,223 +1,244 @@
|
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
console.log(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
|
|
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
|
+
// --auto-from <url>: ask the public Adoption Agent to draft the wab.json.
|
|
193
|
+
// The remote agent inspects metadata, sitemap, robots, OpenGraph, schema.org
|
|
194
|
+
// and TLS to produce a richer document than our local templates.
|
|
195
|
+
let wab;
|
|
196
|
+
if (ARG['auto-from'] || ARG.autoFrom) {
|
|
197
|
+
const sourceUrl = ARG['auto-from'] || ARG.autoFrom;
|
|
198
|
+
const endpoint = ARG.endpoint || 'https://www.webagentbridge.com';
|
|
199
|
+
console.log(` → Asking Adoption Agent at ${endpoint} to inspect ${sourceUrl}…`);
|
|
200
|
+
try {
|
|
201
|
+
const r = await fetch(`${endpoint}/api/adopt/suggest?url=${encodeURIComponent(sourceUrl)}`);
|
|
202
|
+
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
203
|
+
const j = await r.json();
|
|
204
|
+
if (!j.ok) throw new Error(j.error || 'agent rejected');
|
|
205
|
+
wab = j.wab_json;
|
|
206
|
+
console.log(` ✓ Agent suggested ${wab.actions.length} actions; stack=${j.stack && j.stack.type}; ssl_fp=${j.ssl ? 'yes' : 'no'}\n`);
|
|
207
|
+
} catch (e) {
|
|
208
|
+
console.error(` ! Adoption Agent failed: ${e.message}. Falling back to local templates.`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (!wab) {
|
|
212
|
+
wab = buildWabJson({ siteUrl, name, description, projectType: detected.type });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const pubDir = publicDirFor(detected.type, cwd);
|
|
216
|
+
const wellKnownDir = path.join(cwd, pubDir, '.well-known');
|
|
217
|
+
const wabPath = path.join(wellKnownDir, 'wab.json');
|
|
218
|
+
|
|
219
|
+
if (fs.existsSync(wabPath) && !ARG.force && !ARG.yes) {
|
|
220
|
+
console.log(`\n ! ${path.relative(cwd, wabPath)} already exists. Use --force to overwrite.`);
|
|
221
|
+
process.exit(2);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fs.mkdirSync(wellKnownDir, { recursive: true });
|
|
225
|
+
fs.writeFileSync(wabPath, JSON.stringify(wab, null, 2) + '\n');
|
|
226
|
+
|
|
227
|
+
console.log(`\n Wrote: ${path.relative(cwd, wabPath)}`);
|
|
228
|
+
console.log(` URL: ${siteUrl}/.well-known/wab.json`);
|
|
229
|
+
console.log(dnsInstructions(host));
|
|
230
|
+
console.log(` Next steps:`);
|
|
231
|
+
console.log(` 1. Deploy your site so /.well-known/wab.json is publicly reachable.`);
|
|
232
|
+
console.log(` 2. Add the DNS TXT record above.`);
|
|
233
|
+
console.log(` 3. (Optional) Sign with Ed25519: see scripts/sign-wab-domain.js`);
|
|
234
|
+
console.log(` 4. Verify: https://www.webagentbridge.com/check?host=${host}\n`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (require.main === module) {
|
|
238
|
+
main().catch((e) => {
|
|
239
|
+
console.error('wab-init failed:', e.message);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = { detectProject, buildWabJson, publicDirFor };
|
package/bin/wab.js
CHANGED
|
@@ -1,80 +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
|
-
}
|
|
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
|
+
}
|