nothumanallowed 9.9.3 → 9.9.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 +1 -1
- package/src/commands/ui.mjs +49 -10
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +12 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "9.9.
|
|
3
|
+
"version": "9.9.5",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents, 53 tools. Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, GitHub, Notion, Slack, voice chat, 28 languages. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/commands/ui.mjs
CHANGED
|
@@ -1869,17 +1869,56 @@ export async function cmdUI(args) {
|
|
|
1869
1869
|
|
|
1870
1870
|
const server = http.createServer(handleRequest);
|
|
1871
1871
|
|
|
1872
|
-
// ── WebSocket
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1872
|
+
// ── WebSocket handler — accept browser WS and relay daemon events ──
|
|
1873
|
+
server.on('upgrade', (req, socket) => {
|
|
1874
|
+
const key = req.headers['sec-websocket-key'];
|
|
1875
|
+
if (!key) { socket.destroy(); return; }
|
|
1876
|
+
|
|
1877
|
+
const acceptKey = crypto
|
|
1878
|
+
.createHash('sha1')
|
|
1879
|
+
.update(key + '258EAFA5-E914-47DA-95CA-5AB5DC86C11B')
|
|
1880
|
+
.digest('base64');
|
|
1881
|
+
|
|
1882
|
+
socket.write(
|
|
1883
|
+
'HTTP/1.1 101 Switching Protocols\r\n' +
|
|
1884
|
+
'Upgrade: websocket\r\n' +
|
|
1885
|
+
'Connection: Upgrade\r\n' +
|
|
1886
|
+
'Sec-WebSocket-Accept: ' + acceptKey + '\r\n' +
|
|
1887
|
+
'\r\n'
|
|
1888
|
+
);
|
|
1889
|
+
|
|
1890
|
+
// Connect to daemon WS on port 3848 and relay messages
|
|
1891
|
+
let daemonWs = null;
|
|
1892
|
+
try {
|
|
1893
|
+
const daemonReq = http.request({
|
|
1894
|
+
hostname: '127.0.0.1', port: 3848, path: '/',
|
|
1895
|
+
headers: { 'Upgrade': 'websocket', 'Connection': 'Upgrade', 'Sec-WebSocket-Key': crypto.randomBytes(16).toString('base64'), 'Sec-WebSocket-Version': '13' },
|
|
1896
|
+
});
|
|
1897
|
+
daemonReq.on('upgrade', (res, daemonSocket) => {
|
|
1898
|
+
daemonWs = daemonSocket;
|
|
1899
|
+
// Relay daemon → browser
|
|
1900
|
+
daemonSocket.on('data', (buf) => { try { socket.write(buf); } catch {} });
|
|
1901
|
+
daemonSocket.on('close', () => {});
|
|
1902
|
+
daemonSocket.on('error', () => {});
|
|
1903
|
+
});
|
|
1904
|
+
daemonReq.on('error', () => {}); // daemon not running — WS works without it
|
|
1905
|
+
daemonReq.end();
|
|
1906
|
+
} catch {}
|
|
1907
|
+
|
|
1908
|
+
// Handle browser → daemon (ping/pong)
|
|
1909
|
+
socket.on('data', (buf) => {
|
|
1910
|
+
if (buf.length < 2) return;
|
|
1911
|
+
const opcode = buf[0] & 0x0f;
|
|
1912
|
+
if (opcode === 0x08) { socket.end(); if (daemonWs) daemonWs.end(); return; }
|
|
1913
|
+
if (opcode === 0x09) { // ping → pong
|
|
1914
|
+
const pong = Buffer.alloc(2);
|
|
1915
|
+
pong[0] = 0x8a; pong[1] = 0;
|
|
1916
|
+
socket.write(pong);
|
|
1917
|
+
}
|
|
1879
1918
|
});
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
}
|
|
1919
|
+
socket.on('close', () => { if (daemonWs) try { daemonWs.end(); } catch {} });
|
|
1920
|
+
socket.on('error', () => { if (daemonWs) try { daemonWs.end(); } catch {} });
|
|
1921
|
+
});
|
|
1883
1922
|
|
|
1884
1923
|
server.on('error', (err) => {
|
|
1885
1924
|
if (err.code === 'EADDRINUSE') {
|
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 = '9.9.
|
|
8
|
+
export const VERSION = '9.9.5';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -624,29 +624,27 @@ function renderCanvasPanel(){
|
|
|
624
624
|
var tabB=document.getElementById('canvasTabB');
|
|
625
625
|
if(tabC)tabC.style.borderBottom=canvasMode==='canvas'?'2px solid var(--green)':'none';
|
|
626
626
|
if(tabB)tabB.style.borderBottom=canvasMode==='browser'?'2px solid var(--green)':'none';
|
|
627
|
-
// Render iframe content
|
|
627
|
+
// Render iframe content via srcdoc (no allow-same-origin needed)
|
|
628
628
|
var f=document.getElementById('canvasFrame');if(!f)return;
|
|
629
|
-
var doc=f.contentDocument||f.contentWindow.document;
|
|
630
629
|
if(canvasMode==='browser'){
|
|
631
|
-
// Browser tab: gallery of visited page thumbnails
|
|
632
630
|
var d=getConvCanvasData();
|
|
633
631
|
if(d.browsers.length===0){
|
|
634
|
-
|
|
632
|
+
f.srcdoc='<html><body style="margin:0;background:#111;display:flex;align-items:center;justify-content:center;height:100vh;font-family:monospace;color:#555"><div style="text-align:center"><div style="font-size:48px;margin-bottom:12px">🌐</div><div>No pages visited yet</div><div style="font-size:11px;margin-top:8px;color:#333">in this conversation</div><div style="margin-top:16px;font-size:11px;color:#888">Ask me to search or open a page</div></div></body></html>';
|
|
635
633
|
} else {
|
|
636
634
|
var apiBase=window.API||'';
|
|
637
635
|
var gallery='<html><head><style>*{margin:0;padding:0;box-sizing:border-box}body{background:#111;padding:12px;font-family:monospace}h3{color:#00ff41;font-size:12px;margin-bottom:12px}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px}.card{background:#1a1a1a;border:1px solid #333;border-radius:8px;overflow:hidden;cursor:pointer;transition:border-color .2s}.card:hover{border-color:#00ff41}.card img{width:100%;height:120px;object-fit:cover;display:block;background:#222}.card .info{padding:6px 8px}.card .url{color:#8ab4f8;font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.card .time{color:#555;font-size:9px;margin-top:2px}</style></head><body><h3>Pages visited ('+d.browsers.length+')</h3><div class="grid">';
|
|
638
636
|
for(var bi=0;bi<d.browsers.length;bi++){
|
|
639
637
|
var b=d.browsers[bi];
|
|
640
638
|
var imgSrc=b.file?apiBase+'/api/screenshots/'+b.file:(b.base64?'data:image/jpeg;base64,'+b.base64:'');
|
|
641
|
-
gallery+='<div class="card" onclick="parent.
|
|
639
|
+
gallery+='<div class="card" onclick="window.parent.postMessage({type:\\x27selectBrowser\\x27,index:'+bi+'},\\x27*\\x27)">'+(imgSrc?'<img src="'+imgSrc+'" alt="'+b.url+'"/>':'<div style="height:120px;display:flex;align-items:center;justify-content:center;color:#555">No preview</div>')+'<div class="info"><div class="url">'+b.url+'</div><div class="time">'+(b.ts||'')+'</div></div></div>';
|
|
642
640
|
}
|
|
643
641
|
gallery+='</div></body></html>';
|
|
644
|
-
|
|
642
|
+
f.srcdoc=gallery;
|
|
645
643
|
}
|
|
646
644
|
} else if(!item){
|
|
647
|
-
|
|
645
|
+
f.srcdoc='<html><body style="margin:0;background:#111;display:flex;align-items:center;justify-content:center;height:100vh;font-family:monospace;color:#555"><div style="text-align:center"><div style="font-size:48px;margin-bottom:12px">▣</div><div>No canvas content</div><div style="font-size:11px;margin-top:8px;color:#333">in this conversation</div></div></body></html>';
|
|
648
646
|
} else {
|
|
649
|
-
|
|
647
|
+
f.srcdoc=item.html;
|
|
650
648
|
}
|
|
651
649
|
}
|
|
652
650
|
|
|
@@ -660,6 +658,10 @@ function canvasNext(){
|
|
|
660
658
|
if(canvasMode==='browser'){if(browserIdx<d.browsers.length-1){browserIdx++;renderCanvasPanel();}}
|
|
661
659
|
else{if(canvasIdx<d.canvases.length-1){canvasIdx++;renderCanvasPanel();}}
|
|
662
660
|
}
|
|
661
|
+
// Listen for messages from sandboxed canvas iframe
|
|
662
|
+
window.addEventListener('message',function(e){
|
|
663
|
+
if(e.data&&e.data.type==='selectBrowser'&&typeof e.data.index==='number'){selectBrowserPage(e.data.index);}
|
|
664
|
+
});
|
|
663
665
|
function selectBrowserPage(i){
|
|
664
666
|
browserIdx=i;canvasMode='browser';renderCanvasPanel();
|
|
665
667
|
// Also show in monitor viewer
|
|
@@ -1926,7 +1928,7 @@ var wsMaxRetries = 3;
|
|
|
1926
1928
|
function connectWebSocket() {
|
|
1927
1929
|
if (wsRetryCount >= wsMaxRetries) return; // Stop trying after 3 failures
|
|
1928
1930
|
try {
|
|
1929
|
-
ws = new WebSocket('ws://' + window.location.
|
|
1931
|
+
ws = new WebSocket('ws://' + window.location.host + '/ws');
|
|
1930
1932
|
} catch(e) { return; }
|
|
1931
1933
|
|
|
1932
1934
|
ws.onopen = function() {
|
|
@@ -2182,7 +2184,7 @@ init();
|
|
|
2182
2184
|
</div>
|
|
2183
2185
|
</div>
|
|
2184
2186
|
|
|
2185
|
-
<div id="canvasPanel"><div class="cvs-header"><div style="display:flex;align-items:center;gap:8px"><button id="canvasTabC" onclick="canvasShowCanvas()" style="background:none;border:none;border-bottom:2px solid var(--green);color:var(--green);cursor:pointer;font-family:var(--mono);font-size:11px;padding:2px 6px">Canvas</button><button id="canvasTabB" onclick="canvasShowBrowser()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-family:var(--mono);font-size:11px;padding:2px 6px">Browser</button><span id="canvasTitle" style="font-family:var(--mono);color:var(--green);font-size:11px;margin-left:8px">Canvas</span></div><div style="display:flex;align-items:center;gap:4px"><span id="canvasNav" style="display:none;gap:4px"><button onclick="canvasPrev()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Previous">◀</button><button onclick="canvasNext()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Next">▶</button></span><button onclick="toggleCanvasSize()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Resize">⤢</button><button onclick="closeCanvas()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Close">×</button></div></div><iframe id="canvasFrame" sandbox="allow-scripts
|
|
2187
|
+
<div id="canvasPanel"><div class="cvs-header"><div style="display:flex;align-items:center;gap:8px"><button id="canvasTabC" onclick="canvasShowCanvas()" style="background:none;border:none;border-bottom:2px solid var(--green);color:var(--green);cursor:pointer;font-family:var(--mono);font-size:11px;padding:2px 6px">Canvas</button><button id="canvasTabB" onclick="canvasShowBrowser()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-family:var(--mono);font-size:11px;padding:2px 6px">Browser</button><span id="canvasTitle" style="font-family:var(--mono);color:var(--green);font-size:11px;margin-left:8px">Canvas</span></div><div style="display:flex;align-items:center;gap:4px"><span id="canvasNav" style="display:none;gap:4px"><button onclick="canvasPrev()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Previous">◀</button><button onclick="canvasNext()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Next">▶</button></span><button onclick="toggleCanvasSize()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Resize">⤢</button><button onclick="closeCanvas()" style="background:none;border:none;color:var(--dim);cursor:pointer;font-size:14px" title="Close">×</button></div></div><iframe id="canvasFrame" sandbox="allow-scripts" srcdoc=""></iframe></div>
|
|
2186
2188
|
<script>${JS}</script>
|
|
2187
2189
|
</body>
|
|
2188
2190
|
</html>`;
|