nothumanallowed 13.5.119 → 13.5.120

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": "13.5.119",
3
+ "version": "13.5.120",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -873,6 +873,30 @@ export async function cmdUI(args) {
873
873
  logRequest(method, pathname, 200, Date.now() - start); return;
874
874
  }
875
875
 
876
+ // GET /api/imap/unread-count — total unread across all active IMAP accounts
877
+ if (method === 'GET' && pathname === '/api/imap/unread-count') {
878
+ try {
879
+ const { listAccounts, getDb } = await import('../services/email-db.mjs');
880
+ const accounts = listAccounts();
881
+ const db = getDb();
882
+ let total = 0;
883
+ for (const acc of accounts) {
884
+ const row = db.prepare(`
885
+ SELECT COUNT(*) as n FROM email_messages m
886
+ JOIN email_message_labels eml ON eml.message_id = m.id
887
+ JOIN email_labels l ON l.id = eml.label_id
888
+ LEFT JOIN email_message_state s ON s.message_id = m.id
889
+ WHERE m.account_id = ? AND l.system_type = 'inbox'
890
+ AND COALESCE(s.is_read, 0) = 0
891
+ AND m.permanently_deleted = 0
892
+ `).get(acc.id);
893
+ total += row?.n || 0;
894
+ }
895
+ sendJSON(res, 200, { unread: total });
896
+ } catch (e) { sendJSON(res, 500, { error: e.message }); }
897
+ logRequest(method, pathname, 200, Date.now() - start); return;
898
+ }
899
+
876
900
  // POST /api/imap/mark-read
877
901
  if (method === 'POST' && pathname === '/api/imap/mark-read') {
878
902
  try {
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 = '13.5.119';
8
+ export const VERSION = '13.5.120';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -295,11 +295,27 @@ function loadDash(){
295
295
  }
296
296
  function loadAgents(){return apiGet('/api/agents').then(function(r){agentsList=(r&&r.agents)||[]})}
297
297
  function updateBadges(){
298
- var eb=document.getElementById('emailBadge'),tb=document.getElementById('taskBadge'),cb=document.getElementById('calBadge');
299
- var ue=dash.emails.filter(function(e){return e.isUnread}).length,ut=dash.tasks.filter(function(t){return t.status!=='done'}).length,uc=dash.events.length;
300
- if(eb){eb.textContent=ue;eb.style.display=ue>0?'':'none'}
298
+ var tb=document.getElementById('taskBadge'),cb=document.getElementById('calBadge');
299
+ var ut=dash.tasks.filter(function(t){return t.status!=='done'}).length,uc=dash.events.length;
301
300
  if(tb){tb.textContent=ut;tb.style.display=ut>0?'':'none'}
302
301
  if(cb){cb.textContent=uc;cb.style.display=uc>0?'':'none'}
302
+ updateEmailBadge();
303
+ }
304
+ function updateEmailBadge(){
305
+ var eb=document.getElementById('emailBadge');
306
+ if(!eb)return;
307
+ // Try IMAP unread first; fall back to Google dash count
308
+ apiGet('/api/imap/unread-count').then(function(r){
309
+ var imapUnread=r.unread||0;
310
+ var googleUnread=dash.emails?dash.emails.filter(function(e){return e.isUnread}).length:0;
311
+ var total=imapUnread+googleUnread;
312
+ eb.textContent=total;
313
+ eb.style.display=total>0?'':'none';
314
+ }).catch(function(){
315
+ var ue=dash.emails?dash.emails.filter(function(e){return e.isUnread}).length:0;
316
+ eb.textContent=ue;
317
+ eb.style.display=ue>0?'':'none';
318
+ });
303
319
  }
304
320
 
305
321
  // ---- HELPERS ----
@@ -1397,7 +1413,7 @@ function emailOpenMessage(id) {
1397
1413
  emailRenderReadingPane(pane, r.message);
1398
1414
  // Update read state in local list
1399
1415
  var msg = emailState.messages.find(function(m) { return m.id === id; });
1400
- if (msg) msg.is_read = true;
1416
+ if (msg && !msg.is_read) { msg.is_read = true; updateEmailBadge(); }
1401
1417
  emailRenderMessageList();
1402
1418
  }).catch(function(e) {
1403
1419
  pane.innerHTML = '<div style="padding:20px;color:var(--red);font-size:12px">' + esc(e.message) + '</div>';
@@ -1689,7 +1705,8 @@ function emailSyncCurrent() {
1689
1705
  if (!emailState.accountId || emailState.accountType !== 'imap') return;
1690
1706
  apiPost('/api/imap/sync', { accountId: emailState.accountId }).then(function() {
1691
1707
  showToast('success', 'Sync', 'Sync started — messages will appear shortly');
1692
- setTimeout(function() { emailLoadMessages(); }, 5000);
1708
+ setTimeout(function() { emailLoadMessages(); updateEmailBadge(); }, 5000);
1709
+ setTimeout(function() { emailLoadMessages(); updateEmailBadge(); }, 15000);
1693
1710
  });
1694
1711
  }
1695
1712