a2acalling 0.6.21 → 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 +114 -36
  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,38 +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
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
1452
+ const { spawnSync } = require('child_process');
1453
+ const hasNginx = spawnSync('which', ['nginx'], { encoding: 'utf8' }).status === 0;
1454
+ const hasCaddy = spawnSync('which', ['caddy'], { encoding: 'utf8' }).status === 0;
1396
1455
 
1397
- console.log(`\n ━━━ Reverse Proxy Setup ━━━`);
1398
- console.log(` Server running on port ${serverPort}, but external callers expect port 80/443.`);
1399
- if (port80Status.listening) {
1400
- console.log(` Port 80: in use (likely nginx, caddy, or another web server)`);
1401
- } else {
1402
- console.log(` Port 80: available (but A2A is on ${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}`);
1460
+
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`);
1403
1474
  }
1404
- console.log(`\n RECOMMENDED: Configure your web server to proxy A2A requests:\n`);
1405
- console.log(` For nginx, add to your server block:`);
1406
- console.log(` location /api/a2a/ {`);
1407
- console.log(` proxy_pass http://127.0.0.1:${serverPort}/api/a2a/;`);
1408
- console.log(` proxy_http_version 1.1;`);
1409
- console.log(` proxy_set_header Host $host;`);
1410
- console.log(` }`);
1411
- console.log(`\n For Caddy:`);
1412
- console.log(` handle /api/a2a/* {`);
1413
- console.log(` reverse_proxy 127.0.0.1:${serverPort}`);
1414
- console.log(` }`);
1415
- console.log(`\n After configuring, update the invite hostname to use port 80:`);
1416
- console.log(` Current: ${publicHost}`);
1417
- console.log(` Should be: ${externalIp} (without port, defaults to 80)`);
1418
- console.log(`\n Or open port ${serverPort} directly in your firewall if no proxy is used.`);
1419
- console.log(` ━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
1420
- console.log(`\n ACTION REQUIRED: Ask your owner if they want to configure a reverse proxy.`);
1421
- console.log(` If they say yes, help them add the nginx/caddy config above.`);
1422
- console.log(` If they say no or skip, the invite will use port ${serverPort} directly.`);
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(` ───────────────────`);
1482
+ }
1483
+
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):`);
1489
+ console.log(` sudo ufw allow ${serverPort}/tcp # Ubuntu/Debian`);
1490
+ console.log(` Invite hostname will then be: ${publicHost}`);
1491
+
1492
+ console.log(`\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
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}`);
1423
1499
  }
1500
+
1501
+ const verifyUrl = `http://${publicHost}/api/a2a/ping`;
1424
1502
  console.log(`\n Verify: curl -s ${verifyUrl}`);
1425
1503
  }
1426
1504
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "a2acalling",
3
- "version": "0.6.21",
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": {