agentlytics 0.2.3 → 0.2.4

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/index.js +38 -33
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -277,13 +277,46 @@ const BOT_STYLES = [
277
277
  process.exit(0);
278
278
  }
279
279
 
280
- // Start server (kill stale agentlytics if port is busy)
280
+ // Start server (kill stale agentlytics or find free port)
281
281
  const app = require('./server');
282
282
  const http = require('http');
283
+ const net = require('net');
284
+
285
+ function isPortFree(port) {
286
+ return new Promise((resolve) => {
287
+ const tester = net.createServer()
288
+ .once('error', () => resolve(false))
289
+ .once('listening', () => tester.close(() => resolve(true)))
290
+ .listen(port, '0.0.0.0');
291
+ });
292
+ }
293
+
294
+ async function startServer(port) {
295
+ const free = await isPortFree(port);
296
+ if (!free) {
297
+ // Port in use — check if it's a previous agentlytics instance
298
+ try {
299
+ const data = await new Promise((resolve, reject) => {
300
+ const req = http.get(`http://127.0.0.1:${port}/api/ping`, { timeout: 2000 }, (res) => {
301
+ let body = '';
302
+ res.on('data', (d) => body += d);
303
+ res.on('end', () => { try { resolve(JSON.parse(body)); } catch { reject(); } });
304
+ });
305
+ req.on('error', reject);
306
+ });
307
+ if (data.app === 'agentlytics' && data.pid) {
308
+ console.log(chalk.yellow(` ⟳ Killing previous Agentlytics instance (PID ${data.pid})...`));
309
+ try { process.kill(data.pid, 'SIGTERM'); } catch {}
310
+ await new Promise(r => setTimeout(r, 1000));
311
+ return startServer(port);
312
+ }
313
+ } catch {}
314
+ console.log(chalk.yellow(` ⚠ Port ${port} is in use by another app, trying ${port + 1}...`));
315
+ return startServer(port + 1);
316
+ }
283
317
 
284
- function tryListen() {
285
- app.listen(PORT, () => {
286
- const url = `http://localhost:${PORT}`;
318
+ app.listen(port, '0.0.0.0', () => {
319
+ const url = `http://localhost:${port}`;
287
320
  console.log(chalk.green(` ✓ Dashboard ready at ${chalk.bold.white(url)}`));
288
321
  console.log('');
289
322
  console.log(chalk.dim(' Press Ctrl+C to stop\n'));
@@ -291,36 +324,8 @@ const BOT_STYLES = [
291
324
  // Auto-open browser
292
325
  const open = require('open');
293
326
  open(url).catch(() => {});
294
- }).on('error', (err) => {
295
- if (err.code !== 'EADDRINUSE') throw err;
296
-
297
- // Port in use — check if it's a previous agentlytics instance
298
- const req = http.get(`http://localhost:${PORT}/api/ping`, { timeout: 2000 }, (res) => {
299
- let body = '';
300
- res.on('data', (d) => body += d);
301
- res.on('end', () => {
302
- try {
303
- const data = JSON.parse(body);
304
- if (data.app === 'agentlytics' && data.pid) {
305
- console.log(chalk.yellow(` ⟳ Killing previous Agentlytics instance (PID ${data.pid})...`));
306
- try { process.kill(data.pid, 'SIGTERM'); } catch {}
307
- setTimeout(tryListen, 1000);
308
- } else {
309
- console.error(chalk.red(` ✖ Port ${PORT} is in use by another application.`));
310
- process.exit(1);
311
- }
312
- } catch {
313
- console.error(chalk.red(` ✖ Port ${PORT} is in use by another application.`));
314
- process.exit(1);
315
- }
316
- });
317
- });
318
- req.on('error', () => {
319
- console.error(chalk.red(` ✖ Port ${PORT} is in use but not responding. Kill the process manually or use PORT=<n> env.`));
320
- process.exit(1);
321
- });
322
327
  });
323
328
  }
324
329
 
325
- tryListen();
330
+ startServer(parseInt(PORT));
326
331
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlytics",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Comprehensive analytics dashboard for AI coding agents — Cursor, Windsurf, Claude Code, VS Code Copilot, Zed, Antigravity, OpenCode, Command Code",
5
5
  "main": "index.js",
6
6
  "bin": {