nothumanallowed 14.1.45 → 14.1.47
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": "14.1.
|
|
3
|
+
"version": "14.1.47",
|
|
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": {
|
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 = '14.1.
|
|
8
|
+
export const VERSION = '14.1.47';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -37,11 +37,12 @@ export function register(router) {
|
|
|
37
37
|
const limit = parseInt(url.searchParams.get('pageSize') || url.searchParams.get('limit') || '200');
|
|
38
38
|
const offset = parseInt(url.searchParams.get('page') || url.searchParams.get('offset') || '0') * (url.searchParams.get('page') ? limit : 1);
|
|
39
39
|
try {
|
|
40
|
-
//
|
|
41
|
-
//
|
|
40
|
+
// getAllEmails returns ALL messages (read + unread) for local-first architecture
|
|
41
|
+
// This ensures email like Luca's are downloaded even if read in Gmail
|
|
42
42
|
let emails;
|
|
43
43
|
if (folder === 'inbox' || folder === 'INBOX') {
|
|
44
|
-
|
|
44
|
+
const { getAllEmails } = await import('../../services/google-gmail.mjs');
|
|
45
|
+
emails = await getAllEmails(config, 'INBOX', limit + offset);
|
|
45
46
|
} else {
|
|
46
47
|
const gmailQuery = folder === 'sent' ? 'in:sent' : folder === 'spam' ? 'in:spam' : folder === 'trash' ? 'in:trash' : `in:${folder}`;
|
|
47
48
|
const refs = await listMessages(config, gmailQuery, limit + offset);
|
|
@@ -19,7 +19,7 @@ import { createServer } from 'net';
|
|
|
19
19
|
import { promisify } from 'util';
|
|
20
20
|
import { sendJSON, sendError, parseBody, sendSSE } from '../index.mjs';
|
|
21
21
|
import { loadConfig } from '../../config.mjs';
|
|
22
|
-
import { callLLM, callLLMStream
|
|
22
|
+
import { callLLM, callLLMStream } from '../../services/llm.mjs';
|
|
23
23
|
import { NHA_DIR } from '../../constants.mjs';
|
|
24
24
|
|
|
25
25
|
const execAsync = promisify(exec);
|
|
@@ -487,10 +487,8 @@ RULES:
|
|
|
487
487
|
|
|
488
488
|
await callLLMStream(config, systemPrompt, userContent, (token) => {
|
|
489
489
|
fullResponse += token;
|
|
490
|
-
// Apply BPE fix for better Italian text quality
|
|
491
|
-
const fixedToken = fixQwen3BPE(token);
|
|
492
490
|
// Suppress raw <tool> blocks from text stream — only emit visible text
|
|
493
|
-
const visibleToken =
|
|
491
|
+
const visibleToken = token.replace(/<tool>[\s\S]*?<\/tool>/g, '');
|
|
494
492
|
if (visibleToken) emit({ type: 'text', token: visibleToken });
|
|
495
493
|
}, { max_tokens: 8192 });
|
|
496
494
|
|
|
@@ -95,6 +95,38 @@ export async function getUnreadImportant(config, maxResults = 30) {
|
|
|
95
95
|
return messages;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Get ALL emails from a folder (read + unread) for local-first architecture.
|
|
100
|
+
* This replaces getUnreadImportant to ensure ALL emails are downloaded locally.
|
|
101
|
+
*/
|
|
102
|
+
export async function getAllEmails(config, folder = 'INBOX', maxResults = 200) {
|
|
103
|
+
// Map folder names to Gmail queries
|
|
104
|
+
const folderQueries = {
|
|
105
|
+
'INBOX': 'in:inbox',
|
|
106
|
+
'SENT': 'in:sent',
|
|
107
|
+
'DRAFTS': 'in:drafts',
|
|
108
|
+
'SPAM': 'in:spam',
|
|
109
|
+
'TRASH': 'in:trash',
|
|
110
|
+
'STARRED': 'is:starred',
|
|
111
|
+
'IMPORTANT': 'is:important'
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const query = folderQueries[folder.toUpperCase()] || `in:${folder.toLowerCase()}`;
|
|
115
|
+
const messageRefs = await listMessages(config, query, maxResults);
|
|
116
|
+
const messages = [];
|
|
117
|
+
|
|
118
|
+
for (const ref of messageRefs.slice(0, maxResults)) {
|
|
119
|
+
try {
|
|
120
|
+
const msg = await getMessage(config, ref.id);
|
|
121
|
+
messages.push(msg);
|
|
122
|
+
} catch { /* skip failed messages */ }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Cache messages locally - this ensures local-first access
|
|
126
|
+
await cacheMessages(messages);
|
|
127
|
+
return messages;
|
|
128
|
+
}
|
|
129
|
+
|
|
98
130
|
/**
|
|
99
131
|
* Get emails from today (read + unread).
|
|
100
132
|
*/
|
|
@@ -362,24 +394,35 @@ async function cacheMessages(messages) {
|
|
|
362
394
|
|
|
363
395
|
// ENTERPRISE LOCAL-FIRST: Also save to IMAP database for Web UI offline access
|
|
364
396
|
try {
|
|
397
|
+
if (!messages.length) return; // Nothing to cache
|
|
398
|
+
|
|
365
399
|
const { ensureGoogleAccount, upsertFolder, getSystemLabel, saveMessage } = await import('./email-db.mjs');
|
|
366
400
|
|
|
401
|
+
// Extract email from first message for account setup
|
|
402
|
+
const firstMsg = messages[0];
|
|
403
|
+
const accountEmail = extractEmail(firstMsg.to) || 'gmail@account';
|
|
404
|
+
|
|
367
405
|
// Ensure Google account exists in IMAP database
|
|
368
406
|
const googleAccount = ensureGoogleAccount({
|
|
369
407
|
id: 'google',
|
|
370
408
|
display_name: 'Gmail',
|
|
371
|
-
email_address:
|
|
409
|
+
email_address: accountEmail,
|
|
372
410
|
imap_host: 'gmail.googleapis.com',
|
|
373
411
|
imap_port: 993,
|
|
374
412
|
imap_secure: true,
|
|
375
413
|
is_active: 1
|
|
376
414
|
});
|
|
377
415
|
|
|
416
|
+
if (!googleAccount) {
|
|
417
|
+
throw new Error('Failed to create/get Google account');
|
|
418
|
+
}
|
|
419
|
+
|
|
378
420
|
// Ensure INBOX folder exists for Gmail account
|
|
379
421
|
const inboxFolderId = upsertFolder(googleAccount.id, 'INBOX', 'Inbox', 'inbox', 1, 0);
|
|
380
422
|
|
|
381
|
-
|
|
382
|
-
|
|
423
|
+
if (!inboxFolderId) {
|
|
424
|
+
throw new Error('Failed to create/get INBOX folder');
|
|
425
|
+
}
|
|
383
426
|
|
|
384
427
|
// Save each message to IMAP database
|
|
385
428
|
for (const msg of messages) {
|
package/src/services/llm.mjs
CHANGED
|
@@ -371,7 +371,7 @@ function repairFragmentRuns(line) {
|
|
|
371
371
|
return result.join(' ');
|
|
372
372
|
}
|
|
373
373
|
|
|
374
|
-
function fixQwen3BPE(text) {
|
|
374
|
+
export function fixQwen3BPE(text) {
|
|
375
375
|
let inCode = false;
|
|
376
376
|
return text.split('\n').map((line) => {
|
|
377
377
|
if (line.trimStart().startsWith('```')) { inCode = !inCode; return line; }
|