a2acalling 0.6.22 → 0.6.23

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.
Files changed (2) hide show
  1. package/bin/cli.js +106 -67
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1126,6 +1126,40 @@ https://github.com/onthegonow/a2a_calling`;
1126
1126
  }
1127
1127
  },
1128
1128
 
1129
+ config: (args) => {
1130
+ const { A2AConfig } = require('../src/lib/config');
1131
+ const config = new A2AConfig();
1132
+
1133
+ const hostname = args.flags.hostname || args.flags.h;
1134
+ const port = args.flags.port || args.flags.p;
1135
+ const show = args.flags.show || args.flags.s || (!hostname && !port);
1136
+
1137
+ if (show) {
1138
+ const agent = config.getAgent();
1139
+ console.log('A2A Configuration:\n');
1140
+ console.log(` Hostname: ${agent.hostname || '(not set)'}`);
1141
+ console.log(` Name: ${agent.name || '(not set)'}`);
1142
+ console.log(` Description: ${agent.description || '(not set)'}`);
1143
+ const onboarding = config.getAll().onboarding || {};
1144
+ console.log(` Server port: ${onboarding.server_port || '(not running)'}`);
1145
+ console.log(` Onboarding step: ${onboarding.step || 'not started'}`);
1146
+ return;
1147
+ }
1148
+
1149
+ const updates = {};
1150
+ if (hostname) {
1151
+ // Remove port from hostname if it's :80 (default)
1152
+ const cleanHostname = hostname.replace(/:80$/, '');
1153
+ updates.hostname = cleanHostname;
1154
+ console.log(` Hostname updated to: ${cleanHostname}`);
1155
+ }
1156
+
1157
+ if (Object.keys(updates).length > 0) {
1158
+ config.setAgent(updates);
1159
+ console.log(' ✅ Configuration saved.');
1160
+ }
1161
+ },
1162
+
1129
1163
  server: (args) => {
1130
1164
  const explicitPort = args.flags.port || args.flags.p || process.env.PORT;
1131
1165
  if (explicitPort) {
@@ -1220,15 +1254,28 @@ https://github.com/onthegonow/a2a_calling`;
1220
1254
  }
1221
1255
 
1222
1256
  // ── Step 1: Port selection ───────────────────────────────────────────
1223
- // Scan ports 80, 3001-3020 and pick the first available one.
1224
- // Only show the selected port agents don't need to see every candidate.
1225
- // Interactive users can override with a custom port; non-interactive
1226
- // auto-accepts the recommendation.
1257
+ // Port 80 is strongly preferred (no firewall config needed for external access).
1258
+ // If port 80 is available and bindable, use it. Otherwise fall back to 3001-3020.
1227
1259
  printSection('Port Configuration');
1228
1260
  const preferredPort = parsePort(args.flags.port || args.flags.p, null);
1229
1261
  const candidates = await inspectPorts(preferredPort);
1230
1262
  const availableCandidates = candidates.filter(c => c.available);
1231
- const recommendedPort = availableCandidates.length ? availableCandidates[0].port : null;
1263
+
1264
+ // Strongly prefer port 80 if available
1265
+ const port80Candidate = candidates.find(c => c.port === 80);
1266
+ const port80Available = port80Candidate && port80Candidate.available;
1267
+
1268
+ let recommendedPort;
1269
+ if (port80Available) {
1270
+ recommendedPort = 80;
1271
+ console.log(' Port 80 is available — using it for easiest external access.');
1272
+ } else if (availableCandidates.length) {
1273
+ recommendedPort = availableCandidates[0].port;
1274
+ console.log(` Port 80 is in use. Using fallback port ${recommendedPort}.`);
1275
+ console.log(' (Reverse proxy or firewall config will be needed for external access.)');
1276
+ } else {
1277
+ recommendedPort = null;
1278
+ }
1232
1279
 
1233
1280
  if (!recommendedPort) {
1234
1281
  console.error(' Could not find a bindable port in the scan range.');
@@ -1240,9 +1287,14 @@ https://github.com/onthegonow/a2a_calling`;
1240
1287
  process.exit(1);
1241
1288
  }
1242
1289
 
1243
- console.log(` Selected port: ${recommendedPort}`);
1244
1290
  let serverPort = recommendedPort;
1245
- const portChoice = await promptText(`Use port ${recommendedPort}? [Y/n/custom]: `, 'y');
1291
+
1292
+ // If we got port 80, just confirm briefly. Otherwise allow override.
1293
+ const portPrompt = port80Available
1294
+ ? `Use port 80? [Y/n]: `
1295
+ : `Use port ${recommendedPort}? [Y/n/custom]: `;
1296
+ const portChoice = await promptText(portPrompt, 'y');
1297
+
1246
1298
  if (!interactive) {
1247
1299
  serverPort = recommendedPort;
1248
1300
  } else if (!['', 'y', 'Y', 'yes', 'YES', 'ye'].includes(String(portChoice).trim())) {
@@ -1389,77 +1441,64 @@ https://github.com/onthegonow/a2a_calling`;
1389
1441
  console.log(' ✅ A2A server is running');
1390
1442
 
1391
1443
  if (externalIp) {
1392
- const verifyUrl = `http://${publicHost}/api/a2a/ping`;
1393
- if (serverPort !== 80) {
1394
- // Check what's using port 80 and detect web servers
1395
- const port80Status = await isPortListening(80, '127.0.0.1', { timeoutMs: 250 });
1444
+ if (serverPort === 80) {
1445
+ // Port 80 — optimal setup, no extra config needed
1446
+ console.log(`\n ✅ Running on port 80 external agents can reach you directly.`);
1447
+ console.log(` Invite hostname: ${externalIp}`);
1448
+ // Update publicHost to not include port since 80 is default
1449
+ publicHost = externalIp;
1450
+ } else {
1451
+ // Not on port 80 — need reverse proxy or firewall config
1396
1452
  const { spawnSync } = require('child_process');
1397
1453
  const hasNginx = spawnSync('which', ['nginx'], { encoding: 'utf8' }).status === 0;
1398
1454
  const hasCaddy = spawnSync('which', ['caddy'], { encoding: 'utf8' }).status === 0;
1399
- const hasSudo = spawnSync('sudo', ['-n', 'true'], { encoding: 'utf8' }).status === 0;
1400
1455
 
1401
- console.log(`\n ━━━ IMPORTANT: Port Configuration ━━━`);
1402
- console.log(`\n A2A works best on port 80. Other ports require firewall configuration.`);
1403
- console.log(` Current: A2A server on port ${serverPort}`);
1456
+ console.log(`\n ━━━ IMPORTANT: External Access Configuration ━━━`);
1457
+ console.log(`\n A2A server is on port ${serverPort}, but external callers expect port 80.`);
1458
+ console.log(` Port 80 is in use by ${hasNginx ? 'nginx' : hasCaddy ? 'Caddy' : 'another web server'}.`);
1459
+ console.log(`\n RECOMMENDED: Configure reverse proxy to route /api/a2a/* to port ${serverPort}`);
1404
1460
 
1405
- if (port80Status.listening) {
1406
- console.log(` Port 80: IN USE (likely ${hasNginx ? 'nginx' : hasCaddy ? 'caddy' : 'a web server'})`);
1407
- console.log(`\n RECOMMENDED: Configure reverse proxy to route /api/a2a/* from port 80 to ${serverPort}`);
1408
- console.log(` This is the easiest option — no firewall changes needed.\n`);
1409
-
1410
- if (hasNginx) {
1411
- console.log(` ── nginx config (add to /etc/nginx/sites-available/default) ──`);
1412
- console.log(` location /api/a2a/ {`);
1413
- console.log(` proxy_pass http://127.0.0.1:${serverPort}/api/a2a/;`);
1414
- console.log(` proxy_http_version 1.1;`);
1415
- console.log(` proxy_set_header Host $host;`);
1416
- console.log(` proxy_set_header X-Real-IP $remote_addr;`);
1417
- console.log(` }`);
1418
- console.log(` ────────────────────────────────────────────────────────────`);
1419
- console.log(`\n To apply: sudo nano /etc/nginx/sites-available/default`);
1420
- console.log(` (add the location block inside your server {})`);
1421
- console.log(` sudo nginx -t && sudo systemctl reload nginx`);
1422
- }
1423
-
1424
- if (hasCaddy) {
1425
- console.log(`\n ── Caddy config ──`);
1426
- console.log(` handle /api/a2a/* {`);
1427
- console.log(` reverse_proxy 127.0.0.1:${serverPort}`);
1428
- console.log(` }`);
1429
- console.log(` ───────────────────`);
1430
- }
1431
-
1432
- console.log(`\n After configuring, your invite hostname should be: ${externalIp}`);
1433
- console.log(` (port 80 is the default, so no port number needed)`);
1434
-
1435
- } else {
1436
- console.log(` Port 80: AVAILABLE`);
1437
- console.log(`\n RECOMMENDED: Restart A2A on port 80 for easiest setup.`);
1438
- console.log(` Run: a2a stop && a2a start --port 80`);
1439
- if (!hasSudo) {
1440
- console.log(` Note: Port 80 may require sudo. Try: sudo a2a start --port 80`);
1441
- }
1461
+ if (hasNginx) {
1462
+ console.log(`\n ── nginx config (add to /etc/nginx/sites-available/default) ──`);
1463
+ console.log(` location /api/a2a/ {`);
1464
+ console.log(` proxy_pass http://127.0.0.1:${serverPort}/api/a2a/;`);
1465
+ console.log(` proxy_http_version 1.1;`);
1466
+ console.log(` proxy_set_header Host $host;`);
1467
+ console.log(` proxy_set_header X-Real-IP $remote_addr;`);
1468
+ console.log(` }`);
1469
+ console.log(` ────────────────────────────────────────────────────────────`);
1470
+ console.log(`\n To apply:`);
1471
+ console.log(` sudo nano /etc/nginx/sites-available/default`);
1472
+ console.log(` (add the location block inside your server {})`);
1473
+ console.log(` sudo nginx -t && sudo systemctl reload nginx`);
1474
+ }
1475
+
1476
+ if (hasCaddy) {
1477
+ console.log(`\n ── Caddy config ──`);
1478
+ console.log(` handle /api/a2a/* {`);
1479
+ console.log(` reverse_proxy 127.0.0.1:${serverPort}`);
1480
+ console.log(` }`);
1481
+ console.log(` ───────────────────`);
1442
1482
  }
1443
1483
 
1444
- console.log(`\n ── Alternative: Firewall route (more complex) ──`);
1445
- console.log(` If you can't use port 80, open port ${serverPort} in your firewall:`);
1484
+ console.log(`\n After reverse proxy is configured:`);
1485
+ console.log(` Invite hostname will be: ${externalIp} (no port needed)`);
1486
+
1487
+ console.log(`\n ── Alternative: Direct firewall access ──`);
1488
+ console.log(` Open port ${serverPort} directly (less recommended):`);
1446
1489
  console.log(` sudo ufw allow ${serverPort}/tcp # Ubuntu/Debian`);
1447
- console.log(` sudo firewall-cmd --add-port=${serverPort}/tcp --permanent && sudo firewall-cmd --reload # RHEL/CentOS`);
1448
- console.log(` Your invite will then use: ${publicHost}`);
1490
+ console.log(` Invite hostname will then be: ${publicHost}`);
1449
1491
 
1450
1492
  console.log(`\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
1451
- console.log(`\n AGENT ACTION: Configure ingress for A2A to receive external calls.`);
1452
- console.log(` Options (in order of preference):`);
1453
- if (!port80Status.listening) {
1454
- console.log(` 1. Restart on port 80: a2a stop && ${hasSudo ? '' : 'sudo '}a2a start --port 80`);
1455
- console.log(` 2. Configure firewall for port ${serverPort} (see commands above)`);
1456
- } else {
1457
- console.log(` 1. Add reverse proxy config to ${hasNginx ? 'nginx' : hasCaddy ? 'Caddy' : 'your web server'} (see above)`);
1458
- console.log(` 2. Configure firewall for port ${serverPort} (see commands above)`);
1459
- }
1460
- console.log(` 3. Skip (local-only testing, external agents won't be able to call)`);
1461
- console.log(`\n Ask your owner which option to proceed with.`);
1493
+ console.log(`\n AGENT ACTION REQUIRED:`);
1494
+ console.log(` 1. Configure reverse proxy (recommended) add nginx/caddy config above`);
1495
+ console.log(` 2. OR open firewall for port ${serverPort} — run the ufw/firewall-cmd command`);
1496
+ console.log(` 3. OR skip (local-only, external agents cannot call)`);
1497
+ console.log(`\n Ask your owner which option to use, then proceed.`);
1498
+ console.log(` If reverse proxy is configured, update hostname with: a2a config --hostname ${externalIp}`);
1462
1499
  }
1500
+
1501
+ const verifyUrl = `http://${publicHost}/api/a2a/ping`;
1463
1502
  console.log(`\n Verify: curl -s ${verifyUrl}`);
1464
1503
  }
1465
1504
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "a2acalling",
3
- "version": "0.6.22",
3
+ "version": "0.6.23",
4
4
  "description": "Agent-to-agent calling for OpenClaw - A2A agent communication",
5
5
  "main": "src/index.js",
6
6
  "bin": {