nothumanallowed 13.5.190 → 13.5.192
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 +1 -1
- package/src/constants.mjs +1 -1
- package/src/services/message-responder.mjs +47 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.192",
|
|
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 = '13.5.
|
|
8
|
+
export const VERSION = '13.5.192';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -136,7 +136,7 @@ function routeMessage(text, useAutoRoute = true) {
|
|
|
136
136
|
|
|
137
137
|
// ── Language detection from message text ─────────────────────────────────────
|
|
138
138
|
|
|
139
|
-
const IT_WORDS = new Set(['il','lo','la','le','gli','un','una','che','di','da','in','con','su','per','tra','fra','non','ma','se','come','dove','quando','chi','cosa','ho','hai','ha','sono','sei','siamo','avere','essere','fare','dire','andare','mi','ti','ci','si','vi','li','le','gli','mio','tuo','suo','nostro','vostro','loro','questo','quello','questi','quelli','anche','già','ancora','sempre','mai','oggi','domani','ieri','adesso','ora','poi','dopo','prima','qui','qua','lì','là','più','meno','molto','poco','bene','male','sì','no','grazie','prego','ciao','buongiorno','buonasera','appuntamenti','calendario','riunione','meteo','temperatura','email','posta','notizie']);
|
|
139
|
+
const IT_WORDS = new Set(['il','lo','la','le','gli','un','una','che','di','da','in','con','su','per','tra','fra','non','ma','se','come','dove','quando','chi','cosa','ho','hai','ha','sono','sei','siamo','avere','essere','fare','dire','andare','mi','ti','ci','si','vi','li','le','gli','mio','tuo','suo','nostro','vostro','loro','questo','quello','questi','quelli','anche','già','ancora','sempre','mai','oggi','domani','ieri','adesso','ora','poi','dopo','prima','qui','qua','lì','là','più','meno','molto','poco','bene','male','sì','no','grazie','prego','ciao','buongiorno','buonasera','appuntamenti','appuntamento','calendario','riunione','meteo','temperatura','email','posta','notizie','del','dello','della','degli','delle','nel','nello','nella','negli','nelle','dal','dallo','dalla','dagli','dalle','sul','sullo','sulla','sugli','sulle','col','coi','quello','quella','quelli','quelle','cancella','cancellare','elimina','eliminare','crea','creare','sposta','spostare','aggiungi','aggiungere','modifica','modificare','ricerca','trovami','trovare','mostra','mostrami','dimmi','rispondimi','aiutami','puoi','voglio','vorrei','devo','posso','giorno','giorni','mese','mesi','anno','anni','settimana','settimane','ore','minuto','minuti','mattina','pomeriggio','sera','notte','veterinario','medico','dentista','dottore','riunioni','scadenza','scadenze']);
|
|
140
140
|
const ES_WORDS = new Set(['el','la','los','las','un','una','que','de','en','con','por','para','pero','como','donde','cuando','quien','qué','tengo','tienes','tiene','somos','soy','eres','hacer','decir','ir','me','te','se','nos','este','ese','estos','esos','también','ya','todavía','siempre','nunca','hoy','mañana','ayer','aquí','allí','más','menos','muy','bien','mal','sí','no','gracias','hola','buenos']);
|
|
141
141
|
const FR_WORDS = new Set(['le','la','les','un','une','des','que','de','en','avec','pour','par','mais','comme','où','quand','qui','je','tu','il','elle','nous','vous','ils','elles','avoir','être','faire','dire','aller','me','te','se','ce','cet','cette','ces','aussi','déjà','toujours','jamais','aujourd','demain','hier','ici','là','plus','moins','très','bien','mal','oui','non','merci','bonjour','bonsoir']);
|
|
142
142
|
const DE_WORDS = new Set(['der','die','das','ein','eine','und','oder','aber','nicht','mit','für','von','zu','an','auf','ist','sind','hat','haben','sein','werden','ich','du','er','sie','es','wir','ihr','mich','dich','sich','uns','euch','diesem','diesen','dieser','dieses','auch','schon','noch','immer','nie','heute','morgen','gestern','hier','dort','mehr','weniger','sehr','gut','schlecht','ja','nein','danke','hallo']);
|
|
@@ -313,6 +313,9 @@ class TelegramResponder {
|
|
|
313
313
|
this.maxConcurrent = 3;
|
|
314
314
|
this._updateCheckTimer = null;
|
|
315
315
|
this._lastNotifiedVersion = null;
|
|
316
|
+
// Per-chat sticky agent: remembers last agent used, plus last turn context
|
|
317
|
+
this._lastAgentByChatId = {}; // chatId → agentName
|
|
318
|
+
this._lastContextByChatId = {}; // chatId → { agent, userMsg, agentReply, ts }
|
|
316
319
|
}
|
|
317
320
|
|
|
318
321
|
get enabled() {
|
|
@@ -359,11 +362,10 @@ class TelegramResponder {
|
|
|
359
362
|
if (chatIds.length === 0) return;
|
|
360
363
|
|
|
361
364
|
const msg =
|
|
362
|
-
`🆕
|
|
365
|
+
`🆕 NHA v${latest} disponibile!\n\n` +
|
|
363
366
|
`Una nuova versione di NotHumanAllowed è stata pubblicata.\n\n` +
|
|
364
|
-
`Aggiorna con:\n` +
|
|
365
|
-
|
|
366
|
-
`Poi riavvia il bot con: \`nha responder restart\``;
|
|
367
|
+
`Aggiorna con:\nnpm install -g nothumanallowed@latest\n\n` +
|
|
368
|
+
`Poi riavvia il bot con: nha ops stop && nha ops start`;
|
|
367
369
|
|
|
368
370
|
this.log(`[Telegram] Broadcasting update notification v${latest} to ${chatIds.length} users`);
|
|
369
371
|
|
|
@@ -372,7 +374,6 @@ class TelegramResponder {
|
|
|
372
374
|
await this._telegramCall('sendMessage', {
|
|
373
375
|
chat_id: parseInt(chatId, 10),
|
|
374
376
|
text: msg,
|
|
375
|
-
parse_mode: 'Markdown',
|
|
376
377
|
});
|
|
377
378
|
} catch {
|
|
378
379
|
// User blocked bot or chat no longer exists — ignore
|
|
@@ -566,15 +567,37 @@ class TelegramResponder {
|
|
|
566
567
|
if (isVoice) {
|
|
567
568
|
await this._telegramCall('sendMessage', {
|
|
568
569
|
chat_id: chatId,
|
|
569
|
-
text: `🎤
|
|
570
|
-
parse_mode: 'Markdown',
|
|
570
|
+
text: `🎤 "${cleanText}"`,
|
|
571
571
|
}).catch(() => {});
|
|
572
572
|
}
|
|
573
573
|
|
|
574
574
|
this.pendingRequests++;
|
|
575
575
|
try {
|
|
576
|
-
|
|
577
|
-
|
|
576
|
+
// Sticky agent: for short/ambiguous messages (< 6 words), reuse last agent for this chat
|
|
577
|
+
// This handles confirmation messages like "Sì", "Ok", "Fallo", "Confermo", etc.
|
|
578
|
+
const wordCount = cleanText.trim().split(/\s+/).length;
|
|
579
|
+
const isAmbiguous = wordCount <= 5;
|
|
580
|
+
const lastCtx = this._lastContextByChatId[chatId];
|
|
581
|
+
const stickyAge = lastCtx ? (Date.now() - lastCtx.ts) : Infinity;
|
|
582
|
+
const useStickyAgent = isAmbiguous && lastCtx && stickyAge < 5 * 60 * 1000; // sticky for 5 min
|
|
583
|
+
|
|
584
|
+
let agent;
|
|
585
|
+
let enrichedMessage = cleanText;
|
|
586
|
+
if (useStickyAgent) {
|
|
587
|
+
agent = lastCtx.agent;
|
|
588
|
+
// Inject previous turn context so agent understands what "Sì" refers to
|
|
589
|
+
const nl = '\n';
|
|
590
|
+
enrichedMessage =
|
|
591
|
+
'[Conversazione precedente]' + nl +
|
|
592
|
+
'Utente: ' + lastCtx.userMsg + nl +
|
|
593
|
+
'Tu (' + agent.toUpperCase() + '): ' + lastCtx.agentReply.slice(0, 400) + nl + nl +
|
|
594
|
+
'[Nuovo messaggio utente]' + nl +
|
|
595
|
+
cleanText;
|
|
596
|
+
this.log(`[Telegram] ${fromUser}: sticky agent ${agent.toUpperCase()} (ambiguous message, last ctx ${Math.round(stickyAge/1000)}s ago)`);
|
|
597
|
+
} else {
|
|
598
|
+
agent = routeMessage(cleanText, this.autoRoute);
|
|
599
|
+
this.log(`[Telegram] ${fromUser} (chat ${chatId}): routed to ${agent.toUpperCase()}${isVoice ? ' [voice]' : ''}`);
|
|
600
|
+
}
|
|
578
601
|
|
|
579
602
|
// Broadcast event
|
|
580
603
|
this.wsBroadcast({
|
|
@@ -587,18 +610,19 @@ class TelegramResponder {
|
|
|
587
610
|
await this._telegramCall('sendChatAction', { chat_id: chatId, action: 'typing' });
|
|
588
611
|
|
|
589
612
|
// Detect language from the message text — overrides system locale
|
|
590
|
-
|
|
613
|
+
// For sticky context, use lang from previous turn if current message is ambiguous
|
|
614
|
+
const detectedLang = detectLanguage(cleanText) || (lastCtx ? detectLanguage(lastCtx.userMsg) : null);
|
|
591
615
|
|
|
592
616
|
// Tool-capable agents use the full tool execution loop
|
|
593
617
|
// Pure reasoning/analysis agents use the simple callAgent (no tools)
|
|
594
618
|
const TOOL_AGENTS = new Set(['herald', 'hermes', 'edi', 'jarvis', 'flux', 'echo', 'mercury', 'pipe', 'navi', 'link', 'prometheus', 'tempest']);
|
|
595
619
|
let response;
|
|
596
620
|
if (TOOL_AGENTS.has(agent)) {
|
|
597
|
-
response = await callAgentWithTools(this.config, agent,
|
|
621
|
+
response = await callAgentWithTools(this.config, agent, enrichedMessage, detectedLang);
|
|
598
622
|
} else {
|
|
599
623
|
// For non-tool agents: inject language instruction into the message
|
|
600
624
|
const langInstruction = detectedLang ? `[Respond in ${detectedLang}] ` : '';
|
|
601
|
-
response = await callAgent(this.config, agent, langInstruction +
|
|
625
|
+
response = await callAgent(this.config, agent, langInstruction + enrichedMessage);
|
|
602
626
|
}
|
|
603
627
|
|
|
604
628
|
// Truncate if too long for Telegram (4096 char limit)
|
|
@@ -606,11 +630,19 @@ class TelegramResponder {
|
|
|
606
630
|
? response.slice(0, 3950) + '\n\n... [truncated]'
|
|
607
631
|
: response;
|
|
608
632
|
|
|
609
|
-
//
|
|
633
|
+
// Save context for sticky agent continuity (next short message reuses this agent)
|
|
634
|
+
this._lastContextByChatId[chatId] = {
|
|
635
|
+
agent,
|
|
636
|
+
userMsg: cleanText,
|
|
637
|
+
agentReply: response,
|
|
638
|
+
ts: Date.now(),
|
|
639
|
+
};
|
|
640
|
+
this._lastAgentByChatId[chatId] = agent;
|
|
641
|
+
|
|
642
|
+
// Send response as plain text — no parse_mode to avoid Markdown entity parse errors
|
|
610
643
|
await this._telegramCall('sendMessage', {
|
|
611
644
|
chat_id: chatId,
|
|
612
645
|
text: `[${agent.toUpperCase()}]\n\n${truncated}`,
|
|
613
|
-
parse_mode: 'Markdown',
|
|
614
646
|
});
|
|
615
647
|
|
|
616
648
|
this.log(`[Telegram] Responded to ${fromUser} via ${agent.toUpperCase()} (${response.length} chars)`);
|