nothumanallowed 6.3.3 → 6.3.5

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.3.3",
3
+ "version": "6.3.5",
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": {
@@ -9,6 +9,7 @@
9
9
 
10
10
  import http from 'http';
11
11
  import os from 'os';
12
+ import crypto from 'crypto';
12
13
  import { exec } from 'child_process';
13
14
  import fs from 'fs';
14
15
  import path from 'path';
@@ -868,6 +869,57 @@ export async function cmdUI(args) {
868
869
 
869
870
  const server = http.createServer(handleRequest);
870
871
 
872
+ // ── WebSocket server on port 3848 (so the frontend can connect) ──────
873
+ const wsServer = http.createServer((req, res) => {
874
+ if (req.url === '/health') {
875
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
876
+ res.end(JSON.stringify({ ok: true }));
877
+ return;
878
+ }
879
+ res.writeHead(404);
880
+ res.end();
881
+ });
882
+
883
+ const wsClients = new Set();
884
+
885
+ wsServer.on('upgrade', (req, socket, head) => {
886
+ const key = req.headers['sec-websocket-key'];
887
+ if (!key) { socket.destroy(); return; }
888
+
889
+ const acceptKey = crypto
890
+ .createHash('sha1')
891
+ .update(key + '258EAFA5-E914-47DA-95CA-5AB5DC86C11B')
892
+ .digest('base64');
893
+
894
+ socket.write(
895
+ 'HTTP/1.1 101 Switching Protocols\r\n' +
896
+ 'Upgrade: websocket\r\n' +
897
+ 'Connection: Upgrade\r\n' +
898
+ `Sec-WebSocket-Accept: ${acceptKey}\r\n` +
899
+ '\r\n'
900
+ );
901
+
902
+ wsClients.add(socket);
903
+
904
+ socket.on('data', (buf) => {
905
+ if (buf.length < 2) return;
906
+ const opcode = buf[0] & 0x0f;
907
+ if (opcode === 0x08) { wsClients.delete(socket); socket.end(); }
908
+ if (opcode === 0x09) { socket.write(Buffer.from([0x8a, 0])); }
909
+ });
910
+ socket.on('close', () => wsClients.delete(socket));
911
+ socket.on('error', () => wsClients.delete(socket));
912
+ });
913
+
914
+ wsServer.on('error', (err) => {
915
+ if (err.code === 'EADDRINUSE') {
916
+ // Daemon already has it — that's fine, frontend will connect to daemon
917
+ return;
918
+ }
919
+ });
920
+
921
+ wsServer.listen(3848, HOST, () => {});
922
+
871
923
  server.on('error', (err) => {
872
924
  if (err.code === 'EADDRINUSE') {
873
925
  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.3.3';
8
+ export const VERSION = '6.3.5';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -840,7 +840,7 @@ var ws = null;
840
840
  var wsReconnectTimer = null;
841
841
  function connectWebSocket() {
842
842
  try {
843
- ws = new WebSocket('ws://127.0.0.1:3848');
843
+ ws = new WebSocket('ws://' + window.location.hostname + ':3848');
844
844
  } catch(e) { return; }
845
845
 
846
846
  ws.onopen = function() {