nothumanallowed 3.1.0 → 3.1.1

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": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "NotHumanAllowed — 38 AI agents for security, code, DevOps, data & daily ops. Ask agents directly, plan your day with 5 specialist agents, manage tasks, connect Gmail + Calendar.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -658,7 +658,7 @@ export async function cmdUI(args) {
658
658
  console.log('');
659
659
 
660
660
  if (!noBrowser) {
661
- openBrowser(url);
661
+ openBrowser(localUrl);
662
662
  }
663
663
  });
664
664
 
@@ -99,7 +99,7 @@ export async function runPlanningPipeline(config, opts = {}) {
99
99
  if (emails.length > 0) {
100
100
  parallelPromises.push(
101
101
  callAgent(config, 'saber',
102
- `Scan these emails for security threats. For each email, classify as SAFE or FLAGGED with reason.\n\nEMAILS:\n${emailContext}\n\nRespond with a JSON object: { "safe": [indices], "flagged": [{ "index": N, "reason": "..." }], "risk_notes": ["..."] }`,
102
+ `Analyze these emails for REAL security threats. Be smart — distinguish between:\n- LEGITIMATE notifications (Google login alerts from the user's own devices, npm publish confirmations, GitHub 2FA, password change confirmations the user initiated) → these are SAFE\n- ACTUAL threats (phishing links, spoofed senders, social engineering, urgent money requests, unknown login locations, credential harvesting) → these are FLAGGED\n\nDo NOT flag routine service notifications as threats. Only flag emails that require the user's immediate security attention.\n\nEMAILS:\n${emailContext}\n\nRespond with a JSON object: { "safe": [indices], "flagged": [{ "index": N, "reason": "..." }], "risk_notes": ["..."] }`,
103
103
  ).then(r => { agentResults.saber = r; ok('SABER: Email security scan complete'); })
104
104
  .catch(e => { warn(`SABER failed: ${e.message}`); agentResults.saber = '{"safe":[],"flagged":[],"risk_notes":["scan failed"]}'; })
105
105
  );
@@ -141,7 +141,13 @@ export async function runPlanningPipeline(config, opts = {}) {
141
141
  // ── Phase 6: CONDUCTOR — Synthesize daily plan ─────────────────────────
142
142
  info('Phase 6: CONDUCTOR synthesizing daily plan...');
143
143
 
144
- const conductorPrompt = `You are the NHA Daily Planner. Synthesize intelligence from 4 specialist agents into a structured daily plan.
144
+ const conductorPrompt = `You are the NHA Daily Planner. Synthesize intelligence from 4 specialist agents into a structured, practical daily plan.
145
+
146
+ IMPORTANT GUIDELINES:
147
+ - Be PRACTICAL, not alarmist. Routine notifications (Google login alerts from your own devices, npm publish confirmations, GitHub security notices) are NOT security incidents.
148
+ - Only escalate to "security_alerts" if there is a GENUINE, actionable threat (unknown logins from strange locations, actual phishing, credential leaks).
149
+ - Focus on making the user's day productive, not on creating false urgency.
150
+ - Suggest realistic time blocks based on the actual task complexity.
145
151
 
146
152
  AGENT REPORTS:
147
153
  ${agentResults.saber ? `\n[SABER — Security Scan]\n${agentResults.saber}` : ''}
@@ -70,8 +70,8 @@ input:focus,textarea:focus{border-color:var(--green3)}
70
70
  .dash-section h2{font-size:13px;color:var(--cyan);margin-bottom:12px;text-transform:uppercase;letter-spacing:1px}
71
71
 
72
72
  /* Chat */
73
- #chat-view{display:flex;flex-direction:column;height:100%;overflow:hidden}
74
- #chat-messages{flex:1;overflow-y:auto;padding:0 0 12px 0}
73
+ #chat-view{display:flex;flex-direction:column;height:calc(100vh - 52px);overflow:hidden}
74
+ #chat-messages{flex:1;overflow-y:auto;padding:0 0 12px 0;-webkit-overflow-scrolling:touch}
75
75
  .msg{margin-bottom:12px;display:flex;gap:10px}
76
76
  .msg-user .msg-bubble{background:var(--bg3);border:1px solid var(--borderbright);border-radius:8px 8px 2px 8px;padding:10px 14px;max-width:80%;margin-left:auto;color:var(--textbright)}
77
77
  .msg-assistant .msg-bubble{background:var(--greendim);border:1px solid var(--green3);border-radius:8px 8px 8px 2px;padding:10px 14px;max-width:85%;color:var(--text);white-space:pre-wrap;word-wrap:break-word}
@@ -185,9 +185,11 @@ input:focus,textarea:focus{border-color:var(--green3)}
185
185
  /* Mobile */
186
186
  #mobile-toggle{display:none;background:none;color:var(--green);font-size:20px;padding:4px 8px}
187
187
  @media(max-width:768px){
188
- #sidebar{position:fixed;left:-260px;top:0;height:100%;z-index:100;transition:left .25s;width:260px}
188
+ #sidebar{position:fixed;left:-260px;top:0;height:100%;z-index:100;transition:left .25s;width:260px;box-shadow:4px 0 20px rgba(0,0,0,0.8)}
189
189
  #sidebar.open{left:0}
190
+ #sidebar.open~#main #content::before{content:'';position:fixed;inset:52px 0 0 0;background:rgba(0,0,0,0.6);z-index:50}
190
191
  #mobile-toggle{display:block}
192
+ #content{padding:12px}
191
193
  .dash-grid{grid-template-columns:1fr}
192
194
  .agents-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
193
195
  .msg-user .msg-bubble,.msg-assistant .msg-bubble{max-width:95%}
@@ -287,6 +289,13 @@ function switchView(view) {
287
289
  function toggleSidebar() {
288
290
  document.getElementById('sidebar').classList.toggle('open');
289
291
  }
292
+ // Close sidebar when tapping outside on mobile
293
+ document.getElementById('main').addEventListener('click', (e) => {
294
+ const sidebar = document.getElementById('sidebar');
295
+ if (sidebar.classList.contains('open')) {
296
+ sidebar.classList.remove('open');
297
+ }
298
+ });
290
299
 
291
300
  // ── Clock ──────────────────────────────────────────────────────────────────
292
301
  function updateClock() {
@@ -779,18 +788,20 @@ document.getElementById('agent-modal').addEventListener('click', e => {
779
788
 
780
789
  // ── Init ───────────────────────────────────────────────────────────────────
781
790
  async function init() {
791
+ // Show loading immediately
792
+ const el = document.getElementById('content');
793
+ if (el) el.innerHTML = '<div style="display:flex;align-items:center;justify-content:center;height:60vh;flex-direction:column"><div class="spinner"></div><div style="color:var(--textdim);margin-top:12px">Loading dashboard...</div></div>';
794
+
782
795
  try {
783
796
  await loadDashboard();
784
797
  } catch (e) {
785
798
  console.error('Dashboard load error:', e);
786
799
  }
787
- try {
788
- loadPlan().catch(e => console.error('Plan load error:', e));
789
- loadAgents().catch(e => console.error('Agents load error:', e));
790
- } catch (e) {
791
- console.error('Init error:', e);
792
- }
793
800
  renderView();
801
+ try {
802
+ loadPlan().catch(()=>{});
803
+ loadAgents().catch(()=>{});
804
+ } catch {}
794
805
  // Auto-refresh every 2 minutes
795
806
  setInterval(() => loadDashboard().then(() => { if (currentView === 'dashboard') renderView(); }).catch(()=>{}), 120000);
796
807
  }