nothumanallowed 4.1.0 → 6.0.0
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 +10 -3
- package/src/cli.mjs +181 -5
- package/src/commands/autostart.mjs +342 -0
- package/src/commands/chat.mjs +14 -8
- package/src/commands/microsoft-auth.mjs +29 -0
- package/src/commands/ops.mjs +37 -0
- package/src/commands/plugin.mjs +481 -0
- package/src/commands/ui.mjs +28 -7
- package/src/commands/voice.mjs +845 -0
- package/src/config.mjs +61 -0
- package/src/constants.mjs +9 -1
- package/src/services/llm.mjs +22 -1
- package/src/services/mail-router.mjs +298 -0
- package/src/services/memory.mjs +627 -0
- package/src/services/message-responder.mjs +778 -0
- package/src/services/microsoft-calendar.mjs +319 -0
- package/src/services/microsoft-mail.mjs +308 -0
- package/src/services/microsoft-oauth.mjs +345 -0
- package/src/services/ops-daemon.mjs +620 -11
- package/src/services/ops-pipeline.mjs +7 -8
- package/src/services/token-store.mjs +41 -14
- package/src/services/tool-executor.mjs +392 -0
- package/src/services/web-ui.mjs +187 -1
package/src/services/web-ui.mjs
CHANGED
|
@@ -151,6 +151,29 @@ input:focus,textarea:focus{border-color:var(--green3)}
|
|
|
151
151
|
/* ---- SPINNER ---- */
|
|
152
152
|
.spinner{width:24px;height:24px;border:2px solid var(--border);border-top-color:var(--green);border-radius:50%;animation:spin .6s linear infinite;margin:0 auto 12px}
|
|
153
153
|
@keyframes spin{to{transform:rotate(360deg)}}
|
|
154
|
+
|
|
155
|
+
/* ---- TOASTS (real-time notifications) ---- */
|
|
156
|
+
.toast-container{position:fixed;top:16px;right:16px;z-index:500;display:flex;flex-direction:column;gap:8px;pointer-events:none}
|
|
157
|
+
.toast{background:var(--bg3);border:1px solid var(--green);border-radius:8px;padding:12px 16px;max-width:320px;animation:toastIn .3s;pointer-events:auto;cursor:pointer;box-shadow:0 4px 20px rgba(0,0,0,0.5)}
|
|
158
|
+
.toast--email{border-color:var(--cyan)}
|
|
159
|
+
.toast--meeting{border-color:var(--amber)}
|
|
160
|
+
.toast--security{border-color:var(--red)}
|
|
161
|
+
.toast--plan{border-color:var(--green)}
|
|
162
|
+
.toast__title{font-size:11px;font-weight:700;margin-bottom:3px}
|
|
163
|
+
.toast--email .toast__title{color:var(--cyan)}
|
|
164
|
+
.toast--meeting .toast__title{color:var(--amber)}
|
|
165
|
+
.toast--security .toast__title{color:var(--red)}
|
|
166
|
+
.toast--plan .toast__title{color:var(--green)}
|
|
167
|
+
.toast__body{font-size:11px;color:var(--text);line-height:1.4}
|
|
168
|
+
.toast--fadeout{animation:toastOut .3s forwards}
|
|
169
|
+
@keyframes toastIn{from{transform:translateX(100%);opacity:0}to{transform:none;opacity:1}}
|
|
170
|
+
@keyframes toastOut{from{opacity:1}to{opacity:0;transform:translateX(40px)}}
|
|
171
|
+
|
|
172
|
+
/* ---- VOICE MIC BUTTON (in chat bar) ---- */
|
|
173
|
+
.chat__mic{background:var(--bg3);color:var(--green);border:1px solid var(--border2);width:40px;height:40px;border-radius:var(--r);display:flex;align-items:center;justify-content:center;font-size:18px;cursor:pointer;flex-shrink:0;transition:all .2s}
|
|
174
|
+
.chat__mic:hover{border-color:var(--green3);background:var(--greendim)}
|
|
175
|
+
.chat__mic--recording{border-color:var(--red);color:var(--red);background:rgba(255,23,68,0.1);animation:micPulse 1.5s ease-in-out infinite}
|
|
176
|
+
@keyframes micPulse{0%,100%{box-shadow:none}50%{box-shadow:0 0 0 6px rgba(255,23,68,0.2)}}
|
|
154
177
|
`;
|
|
155
178
|
|
|
156
179
|
// JS as clean block
|
|
@@ -256,7 +279,7 @@ function renderDash(el){
|
|
|
256
279
|
var chatReady=false;
|
|
257
280
|
function renderChat(el){
|
|
258
281
|
if(!chatReady||!document.getElementById('chatMessages')){
|
|
259
|
-
el.innerHTML='<div class="chat"><div class="chat__messages" id="chatMessages"></div><div class="chat__bar"><textarea class="chat__input" id="chatInput" placeholder="Ask anything..." rows="1"></textarea><button class="chat__send" id="chatSend">Send</button></div></div>';
|
|
282
|
+
el.innerHTML='<div class="chat"><div class="chat__messages" id="chatMessages"></div><div class="chat__bar"><button class="chat__mic" id="chatMic" onclick="toggleVoiceInput()" title="Voice input">🎤</button><textarea class="chat__input" id="chatInput" placeholder="Ask anything..." rows="1"></textarea><button class="chat__send" id="chatSend">Send</button></div></div>';
|
|
260
283
|
chatReady=true;
|
|
261
284
|
document.getElementById('chatSend').onclick=sendChat;
|
|
262
285
|
document.getElementById('chatInput').onkeydown=function(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendChat()}};
|
|
@@ -644,6 +667,165 @@ function askAgent(){
|
|
|
644
667
|
});
|
|
645
668
|
}
|
|
646
669
|
|
|
670
|
+
// ---- TOASTS (real-time notification overlay) ----
|
|
671
|
+
function showToast(type, title, body, durationMs) {
|
|
672
|
+
var container = document.getElementById('toastContainer');
|
|
673
|
+
if (!container) return;
|
|
674
|
+
var toast = document.createElement('div');
|
|
675
|
+
toast.className = 'toast toast--' + type;
|
|
676
|
+
toast.innerHTML = '<div class="toast__title">' + esc(title) + '</div><div class="toast__body">' + esc(body) + '</div>';
|
|
677
|
+
toast.onclick = function() {
|
|
678
|
+
toast.classList.add('toast--fadeout');
|
|
679
|
+
setTimeout(function() { toast.remove(); }, 300);
|
|
680
|
+
// Navigate to relevant view
|
|
681
|
+
if (type === 'email') switchView('emails');
|
|
682
|
+
else if (type === 'meeting') switchView('calendar');
|
|
683
|
+
else if (type === 'plan') switchView('plan');
|
|
684
|
+
};
|
|
685
|
+
container.appendChild(toast);
|
|
686
|
+
// Auto-remove after duration
|
|
687
|
+
setTimeout(function() {
|
|
688
|
+
if (toast.parentNode) {
|
|
689
|
+
toast.classList.add('toast--fadeout');
|
|
690
|
+
setTimeout(function() { toast.remove(); }, 300);
|
|
691
|
+
}
|
|
692
|
+
}, durationMs || 8000);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// ---- WEBSOCKET (connect to daemon for real-time events) ----
|
|
696
|
+
var ws = null;
|
|
697
|
+
var wsReconnectTimer = null;
|
|
698
|
+
function connectWebSocket() {
|
|
699
|
+
try {
|
|
700
|
+
ws = new WebSocket('ws://127.0.0.1:3848');
|
|
701
|
+
} catch(e) { return; }
|
|
702
|
+
|
|
703
|
+
ws.onopen = function() {
|
|
704
|
+
var indicator = document.getElementById('wsIndicator');
|
|
705
|
+
if (indicator) indicator.style.color = 'var(--green)';
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
ws.onmessage = function(event) {
|
|
709
|
+
try {
|
|
710
|
+
var msg = JSON.parse(event.data);
|
|
711
|
+
handleDaemonEvent(msg);
|
|
712
|
+
} catch(e) {}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
ws.onclose = function() {
|
|
716
|
+
var indicator = document.getElementById('wsIndicator');
|
|
717
|
+
if (indicator) indicator.style.color = 'var(--dim)';
|
|
718
|
+
ws = null;
|
|
719
|
+
// Reconnect after 10 seconds
|
|
720
|
+
if (!wsReconnectTimer) {
|
|
721
|
+
wsReconnectTimer = setTimeout(function() {
|
|
722
|
+
wsReconnectTimer = null;
|
|
723
|
+
connectWebSocket();
|
|
724
|
+
}, 10000);
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
ws.onerror = function() {
|
|
729
|
+
try { ws.close(); } catch(e) {}
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function handleDaemonEvent(msg) {
|
|
734
|
+
switch(msg.type) {
|
|
735
|
+
case 'new_email':
|
|
736
|
+
showToast('email', 'New Email', 'From: ' + (msg.data.from || 'unknown') + '\\n' + (msg.data.subject || ''), 10000);
|
|
737
|
+
// Auto-refresh emails
|
|
738
|
+
loadDash().then(function() {
|
|
739
|
+
if (currentView === 'dashboard' || currentView === 'emails') render();
|
|
740
|
+
}).catch(function(){});
|
|
741
|
+
break;
|
|
742
|
+
|
|
743
|
+
case 'meeting_alert':
|
|
744
|
+
showToast('meeting', 'Meeting in ' + msg.data.minutesUntil + ' min', msg.data.summary + (msg.data.location ? '\\n@ ' + msg.data.location : ''), 15000);
|
|
745
|
+
// Auto-refresh calendar
|
|
746
|
+
loadDash().then(function() {
|
|
747
|
+
if (currentView === 'dashboard' || currentView === 'calendar') render();
|
|
748
|
+
}).catch(function(){});
|
|
749
|
+
break;
|
|
750
|
+
|
|
751
|
+
case 'security_alert':
|
|
752
|
+
showToast('security', 'Security Alert', 'Suspicious: ' + (msg.data.from || '') + ' — ' + (msg.data.subject || ''), 20000);
|
|
753
|
+
break;
|
|
754
|
+
|
|
755
|
+
case 'plan_ready':
|
|
756
|
+
showToast('plan', 'Daily Plan Ready', 'Your plan for ' + msg.data.date + ' has been generated.', 10000);
|
|
757
|
+
if (currentView === 'plan') renderPlan(document.getElementById('content'));
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// ---- VOICE INPUT (in chat view) ----
|
|
763
|
+
var voiceRecognition = null;
|
|
764
|
+
var voiceRecording = false;
|
|
765
|
+
|
|
766
|
+
function toggleVoiceInput() {
|
|
767
|
+
if (voiceRecording) {
|
|
768
|
+
stopVoiceInput();
|
|
769
|
+
} else {
|
|
770
|
+
startVoiceInput();
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function startVoiceInput() {
|
|
775
|
+
var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
776
|
+
if (!SpeechRecognition) {
|
|
777
|
+
showToast('security', 'Not Supported', 'Speech Recognition requires Chrome or Edge.', 5000);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
voiceRecording = true;
|
|
782
|
+
var mic = document.getElementById('chatMic');
|
|
783
|
+
if (mic) mic.classList.add('chat__mic--recording');
|
|
784
|
+
|
|
785
|
+
voiceRecognition = new SpeechRecognition();
|
|
786
|
+
voiceRecognition.continuous = false;
|
|
787
|
+
voiceRecognition.interimResults = false;
|
|
788
|
+
voiceRecognition.lang = navigator.language || 'en-US';
|
|
789
|
+
|
|
790
|
+
voiceRecognition.onresult = function(event) {
|
|
791
|
+
var transcript = '';
|
|
792
|
+
for (var i = 0; i < event.results.length; i++) {
|
|
793
|
+
transcript += event.results[i][0].transcript;
|
|
794
|
+
}
|
|
795
|
+
if (transcript.trim()) {
|
|
796
|
+
var inp = document.getElementById('chatInput');
|
|
797
|
+
if (inp) {
|
|
798
|
+
inp.value = transcript.trim();
|
|
799
|
+
sendChat();
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
stopVoiceInput();
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
voiceRecognition.onerror = function(e) {
|
|
806
|
+
if (e.error !== 'no-speech') {
|
|
807
|
+
showToast('security', 'Voice Error', e.error, 4000);
|
|
808
|
+
}
|
|
809
|
+
stopVoiceInput();
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
voiceRecognition.onend = function() {
|
|
813
|
+
stopVoiceInput();
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
voiceRecognition.start();
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
function stopVoiceInput() {
|
|
820
|
+
voiceRecording = false;
|
|
821
|
+
var mic = document.getElementById('chatMic');
|
|
822
|
+
if (mic) mic.classList.remove('chat__mic--recording');
|
|
823
|
+
if (voiceRecognition) {
|
|
824
|
+
try { voiceRecognition.stop(); } catch(e) {}
|
|
825
|
+
voiceRecognition = null;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
647
829
|
// ---- INIT ----
|
|
648
830
|
function init(){
|
|
649
831
|
var el=document.getElementById('content');
|
|
@@ -651,6 +833,8 @@ function init(){
|
|
|
651
833
|
loadDash().then(function(){render()}).catch(function(){render()});
|
|
652
834
|
loadAgents().catch(function(){});
|
|
653
835
|
setInterval(function(){loadDash().then(function(){if(currentView==='dashboard')render()}).catch(function(){})},120000);
|
|
836
|
+
// Connect to daemon WebSocket for real-time notifications
|
|
837
|
+
connectWebSocket();
|
|
654
838
|
}
|
|
655
839
|
init();
|
|
656
840
|
`;
|
|
@@ -671,6 +855,7 @@ init();
|
|
|
671
855
|
</head>
|
|
672
856
|
<body>
|
|
673
857
|
|
|
858
|
+
<div class="toast-container" id="toastContainer"></div>
|
|
674
859
|
<div class="sidebar__overlay" id="overlay" onclick="closeSidebar()"></div>
|
|
675
860
|
|
|
676
861
|
<div class="app">
|
|
@@ -700,6 +885,7 @@ init();
|
|
|
700
885
|
<div class="header">
|
|
701
886
|
<button class="header__burger" onclick="toggleSidebar()">☰</button>
|
|
702
887
|
<span class="header__title" id="headerTitle">Dashboard</span>
|
|
888
|
+
<span id="wsIndicator" style="color:var(--dim);font-size:8px;margin-right:4px" title="Daemon WebSocket">●</span>
|
|
703
889
|
<span class="header__clock" id="clock"></span>
|
|
704
890
|
</div>
|
|
705
891
|
|