nothumanallowed 6.4.2 → 6.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "6.4.2",
3
+ "version": "6.4.4",
4
4
  "description": "NotHumanAllowed — 38 AI agents for security, code, DevOps, data & daily ops. Per-agent memory, Telegram + Discord auto-responder, proactive intelligence daemon, voice chat, plugin system.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -490,6 +490,11 @@ export async function cmdUI(args) {
490
490
  // ── Route Handlers ──────────────────────────────────────────────────────
491
491
 
492
492
  async function handleRequest(req, res) {
493
+ // Skip WebSocket upgrade requests — handled by server.on('upgrade')
494
+ if (req.headers.upgrade && req.headers.upgrade.toLowerCase() === 'websocket') {
495
+ return; // Don't respond — let the upgrade event handle it
496
+ }
497
+
493
498
  const start = Date.now();
494
499
  const url = new URL(req.url, `http://${HOST}:${port}`);
495
500
  const pathname = url.pathname;
@@ -533,8 +538,8 @@ export async function cmdUI(args) {
533
538
  return;
534
539
  }
535
540
 
536
- // ── Favicon + Apple touch icons (no-content, suppress 404) ────────
537
- if (pathname === '/favicon.ico' || pathname.startsWith('/apple-touch-icon')) {
541
+ // ── Favicon + Apple touch icons + browser probes (suppress 404) ────
542
+ if (pathname === '/favicon.ico' || pathname.startsWith('/apple-touch-icon') || pathname.startsWith('/.well-known')) {
538
543
  res.writeHead(204);
539
544
  res.end();
540
545
  return;
@@ -887,12 +892,10 @@ export async function cmdUI(args) {
887
892
 
888
893
  const server = http.createServer(handleRequest);
889
894
 
890
- // ── WebSocket on separate port (3848) to avoid HTTP handler conflicts ──
891
- const wsPort = port + 1; // 3848 when port is 3847
892
- const wsHttpServer = http.createServer((req, res) => { res.writeHead(426); res.end(); });
895
+ // ── WebSocket on same port as HTTP (upgrade handler) ──────────────────
893
896
  const wsClients = new Set();
894
897
 
895
- wsHttpServer.on('upgrade', (req, socket, head) => {
898
+ server.on('upgrade', (req, socket, head) => {
896
899
  const key = req.headers['sec-websocket-key'];
897
900
  if (!key) { socket.destroy(); return; }
898
901
 
@@ -921,9 +924,6 @@ export async function cmdUI(args) {
921
924
  socket.on('error', () => wsClients.delete(socket));
922
925
  });
923
926
 
924
- wsHttpServer.on('error', () => {}); // Silently ignore if port busy
925
- wsHttpServer.listen(wsPort, HOST, () => {});
926
-
927
927
  server.on('error', (err) => {
928
928
  if (err.code === 'EADDRINUSE') {
929
929
  fail(`Port ${port} is already in use. Try: nha ui --port=${port + 1}`);
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '6.4.2';
8
+ export const VERSION = '6.4.4';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -878,15 +878,18 @@ function showToast(type, title, body, durationMs) {
878
878
  // ---- WEBSOCKET (connect to daemon for real-time events) ----
879
879
  var ws = null;
880
880
  var wsReconnectTimer = null;
881
+ var wsRetryCount = 0;
882
+ var wsMaxRetries = 3;
881
883
  function connectWebSocket() {
884
+ if (wsRetryCount >= wsMaxRetries) return; // Stop trying after 3 failures
882
885
  try {
883
- var wsPort = parseInt(window.location.port || '3847') + 1;
884
- ws = new WebSocket('ws://' + window.location.hostname + ':' + wsPort);
886
+ ws = new WebSocket('ws://' + window.location.host);
885
887
  } catch(e) { return; }
886
888
 
887
889
  ws.onopen = function() {
890
+ wsRetryCount = 0;
888
891
  var indicator = document.getElementById('wsIndicator');
889
- if (indicator) indicator.style.color = 'var(--green)';
892
+ if (indicator) { indicator.style.color = 'var(--green)'; indicator.title = 'Live updates: connected'; }
890
893
  };
891
894
 
892
895
  ws.onmessage = function(event) {
@@ -898,14 +901,14 @@ function connectWebSocket() {
898
901
 
899
902
  ws.onclose = function() {
900
903
  var indicator = document.getElementById('wsIndicator');
901
- if (indicator) indicator.style.color = 'var(--dim)';
904
+ if (indicator) { indicator.style.color = 'var(--dim)'; indicator.title = 'Live updates: disconnected'; }
902
905
  ws = null;
903
- // Reconnect after 10 seconds
904
- if (!wsReconnectTimer) {
906
+ wsRetryCount++;
907
+ if (wsRetryCount < wsMaxRetries && !wsReconnectTimer) {
905
908
  wsReconnectTimer = setTimeout(function() {
906
909
  wsReconnectTimer = null;
907
910
  connectWebSocket();
908
- }, 10000);
911
+ }, 30000); // 30s between retries
909
912
  }
910
913
  };
911
914