nothumanallowed 9.0.1 → 9.0.3

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": "9.0.1",
3
+ "version": "9.0.3",
4
4
  "description": "NotHumanAllowed — 38 AI agents + unified productivity suite. Gmail, Calendar, Drive, Contacts, Tasks, GitHub, Notion, Slack, voice chat, smart scheduler. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -309,6 +309,21 @@ export async function cmdUI(args) {
309
309
  return;
310
310
  }
311
311
 
312
+ // POST /api/email/mark-all-read — mark ALL unread as read
313
+ if (method === 'POST' && pathname === '/api/email/mark-all-read') {
314
+ try {
315
+ const gmail = await import('../services/google-gmail.mjs');
316
+ const result = await gmail.markAllAsRead(config);
317
+ // Update local cache
318
+ dash.emails.forEach(e => { e.isUnread = false; });
319
+ sendJSON(res, 200, { ok: true, count: result.count });
320
+ } catch (e) {
321
+ sendJSON(res, 200, { ok: false, error: e.message });
322
+ }
323
+ logRequest(method, pathname, 200, Date.now() - start);
324
+ return;
325
+ }
326
+
312
327
  // POST /api/contacts — create contact
313
328
  if (method === 'POST' && pathname === '/api/contacts') {
314
329
  try {
@@ -521,9 +536,9 @@ export async function cmdUI(args) {
521
536
  } else {
522
537
  // Show all recent inbox emails (read + unread)
523
538
  const gm = await import('../services/google-gmail.mjs');
524
- const msgRefs = await gm.listMessages(config, 'in:inbox', 30);
539
+ const msgRefs = await gm.listMessages(config, 'in:inbox', 50);
525
540
  emails = [];
526
- for (const ref of msgRefs.slice(0, 30)) {
541
+ for (const ref of msgRefs.slice(0, 50)) {
527
542
  try {
528
543
  const msg = await gm.getMessage(config, ref.id);
529
544
  emails.push(msg);
@@ -743,6 +758,24 @@ export async function cmdUI(args) {
743
758
  return;
744
759
  }
745
760
 
761
+ // ── Direct intent handlers (bypass LLM for reliability) ──
762
+ const msgLower = msg.toLowerCase();
763
+
764
+ // Mark all emails as read
765
+ if (msgLower.match(/segna.*tutt.*lett|mark.*all.*read|tutte.*lett[ae]|read.*all.*email|segna.*email.*lett/)) {
766
+ try {
767
+ const gmail = await import('../services/google-gmail.mjs');
768
+ const result = await gmail.markAllAsRead(config);
769
+ dash.emails.forEach(e => { e.isUnread = false; });
770
+ const count = result.count || 0;
771
+ sendJSON(res, 200, { response: count > 0 ? `Done! ${count} email${count !== 1 ? 's' : ''} marked as read.` : 'All emails are already read.' });
772
+ } catch (e) {
773
+ sendJSON(res, 200, { response: `Error marking emails as read: ${e.message}` });
774
+ }
775
+ logRequest(method, pathname, 200, Date.now() - start);
776
+ return;
777
+ }
778
+
746
779
  // ── @agent inline routing ────────────────────────────────
747
780
  let effectiveSystemPrompt = config._chatAgent?.systemPrompt || null;
748
781
  const atMatch = msg.match(/^@(\w+)\s+([\s\S]*)/);
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.0.1';
8
+ export const VERSION = '9.0.3';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -490,13 +490,30 @@ function refreshPlan(){
490
490
  // ---- EMAILS ----
491
491
  function renderEmails(el){
492
492
  var e=dash.emails;
493
- if(e.length===0){el.innerHTML='<div class="card" style="text-align:center;color:var(--dim);padding:30px">No unread emails</div>';return}
494
- var h='';e.forEach(function(x){
493
+ if(e.length===0){el.innerHTML='<div class="card" style="text-align:center;color:var(--dim);padding:30px">No emails</div>';return}
494
+ var unreadCount=e.filter(function(x){return x.isUnread}).length;
495
+ var h='<div style="display:flex;gap:8px;margin-bottom:10px;align-items:center">';
496
+ h+='<span style="font-size:12px;color:var(--dim)">'+e.length+' emails'+( unreadCount>0?' ('+unreadCount+' unread)':'')+'</span>';
497
+ if(unreadCount>0)h+='<button class="btn btn--secondary" style="font-size:10px;padding:4px 10px" onclick="markAllEmailsRead()">Mark all read</button>';
498
+ h+='</div>';
499
+ e.forEach(function(x){
495
500
  var unreadStyle=x.isUnread?'border-left:3px solid var(--green);font-weight:700':'border-left:3px solid transparent;opacity:0.7';
496
501
  h+='<div class="card email" style="cursor:pointer;'+unreadStyle+'" onclick="openEmail(\\x27'+esc(x.id)+'\\x27)"><div class="email__header"><span class="email__from">'+esc(x.from)+'</span><span class="email__date">'+esc(x.date)+(x.isUnread?' <span style="color:var(--green);font-size:9px">NEW</span>':'')+'</span></div><div class="email__subject">'+esc(x.subject)+'</div><div class="email__snippet" style="font-weight:400">'+esc((x.snippet||'').slice(0,150))+'</div></div>';
497
502
  });
498
503
  el.innerHTML=h;
499
504
  }
505
+ function markAllEmailsRead(){
506
+ apiPost('/api/email/mark-all-read',{}).then(function(r){
507
+ if(r&&r.ok){
508
+ dash.emails.forEach(function(e){e.isUnread=false});
509
+ updateBadges();
510
+ renderEmails(document.getElementById('content'));
511
+ showToast('success','All Read','Marked '+( r.count||0)+' emails as read');
512
+ }else{
513
+ showToast('error','Error',r&&r.error||'Failed');
514
+ }
515
+ });
516
+ }
500
517
  var openEmailId=null;
501
518
  function openEmail(id){
502
519
  openEmailId=id;