nothumanallowed 15.1.13 → 15.1.14

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": "15.1.13",
3
+ "version": "15.1.14",
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 = '15.1.13';
8
+ export const VERSION = '15.1.14';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -320,12 +320,50 @@ async function callAgentWithTools(config, agentName, userMessage, languageOverri
320
320
  }
321
321
 
322
322
  history.push({ role: 'assistant', content: response });
323
- userMessage = 'Tool results:\n' + toolResults.join('\n') + '\n\nNow give the user a short, clear confirmation in ' + language + '. Be direct no preamble, no HERALD format. If an action was completed, say so clearly.';
323
+ // LANGUAGE enforcement up FRONTputting it last allows Liara to ignore it.
324
+ // Repeat the instruction at the top so the model commits to it before reading
325
+ // the tool results, then again at the bottom for reinforcement.
326
+ userMessage =
327
+ `RISPOSTA OBBLIGATORIA IN ${language.toUpperCase()}. Tutta la frase deve essere in ${language}, niente inglese, niente lingue miste.\n\n` +
328
+ `Tool results:\n${toolResults.join('\n')}\n\n` +
329
+ `Now give the user a short, clear confirmation. Be direct — no preamble, no HERALD format. ` +
330
+ `If an action was completed, say so clearly. REMEMBER: reply ONLY in ${language}.`;
331
+ }
332
+
333
+ // Defensive language post-check: small models sometimes drop back to English
334
+ // even when instructed otherwise (especially after tool execution, where the
335
+ // English tool-result text biases the continuation). If the final reply is
336
+ // in a clearly different language than expected, translate it.
337
+ if (finalText && language && !looksLikeLanguage(finalText, language)) {
338
+ try {
339
+ const translatePrompt =
340
+ `Traduci il seguente messaggio in ${language}. Mantieni lo stesso significato, lo stesso tono, la stessa lunghezza. Restituisci SOLO la traduzione, senza preamboli o note.\n\nMessaggio:\n${finalText}`;
341
+ const translated = await callLLM(config,
342
+ `You are a precise translator. Translate the given text into ${language}. Output ONLY the translation, no commentary.`,
343
+ translatePrompt,
344
+ { max_tokens: 800 },
345
+ );
346
+ const cleaned = (translated || '').trim();
347
+ if (cleaned && cleaned.length > 0) finalText = cleaned;
348
+ } catch { /* keep the original if translation fails */ }
324
349
  }
325
350
 
326
351
  return { text: finalText || 'Fatto.', history };
327
352
  }
328
353
 
354
+ /**
355
+ * Detect if a text is in the expected language. Used as a defensive check
356
+ * after the LLM produces the final tool-confirmation reply — small models
357
+ * sometimes drop back to English even when instructed otherwise.
358
+ * Returns true if the language seems right, false if a strong mismatch.
359
+ */
360
+ function looksLikeLanguage(text, expectedLanguage) {
361
+ if (!text || !expectedLanguage) return true;
362
+ const detected = detectLanguage(text);
363
+ if (!detected) return true; // not enough signal, give benefit of the doubt
364
+ return detected === expectedLanguage;
365
+ }
366
+
329
367
  // ── Telegram Bot (Long Polling via native fetch) ─────────────────────────────
330
368
 
331
369
  // ── User store for Telegram chat IDs (for broadcast notifications) ──────────
@@ -165,12 +165,11 @@ TOOLS:
165
165
  Use this when the user says: "inserisci", "aggiungi", "crea", "metti", "fissa", "prenota", "add", "create", "schedule", "book".
166
166
 
167
167
  PARAMETER MEANING (CRITICAL — most common mistake):
168
- - summary = the TITLE of the event (what you'd write on a calendar grid). Short, like "Tagliando BMW", "Riunione Cliente X", "Cena con Marta".
168
+ - summary = the TITLE of the event (what you'd write on a calendar grid). Short, derived from what the user said.
169
169
  - description = optional NOTES/details. Leave empty unless the user gave extra context that doesn't fit in the title.
170
170
  - NEVER put the title in description. NEVER leave summary empty.
171
171
 
172
- Example user says "fissa tagliando BMW per il 15 maggio alle 17":
173
- { "action": "calendar_create", "params": { "summary": "Tagliando BMW", "start": "2026-05-15T17:00:00", "end": "2026-05-15T18:00:00" } }
172
+ Always derive summary, date and time from the actual user message never use literal values from this documentation.
174
173
 
175
174
  IMPORTANT: When user says "inserisci appuntamento" or "crea evento" → use calendar_create, NOT calendar_find.
176
175
  Extract the summary, date, and time from the user message. If end time is not specified, default to 1 hour after start.
@@ -667,7 +666,15 @@ RULES:
667
666
  // Used ONLY when provider === 'nha'. Liara already knows tool signatures from
668
667
  // LoRA training — no verbose descriptions needed. Dynamic values (today, tz,
669
668
  // language, profile, imap accounts) are still injected at runtime below.
670
- export const LIARA_TOOL_DEFINITIONS = `You are Liara, the NHA personal AI assistant.
669
+ export const LIARA_TOOL_DEFINITIONS = `## LANGUAGE HIGHEST PRIORITY
670
+
671
+ You MUST write your ENTIRE response in {{LANGUAGE}}. Every sentence, every confirmation, every error message. This overrides everything else. Even when this prompt itself is written in English, your reply to the user must be in {{LANGUAGE}} only. Do NOT mix languages. Do NOT default to English.
672
+
673
+ If {{LANGUAGE}} is Italian, write only in Italian: "L'appuntamento è stato cancellato." NOT "The event has been deleted." or "Both events have been deleted."
674
+
675
+ ---
676
+
677
+ You are Liara, the NHA personal AI assistant.
671
678
  Today: {{TODAY}} | Timezone: {{TIMEZONE}} | Language: {{LANGUAGE}}
672
679
 
673
680
  When the user's request requires an action, output one or more fenced JSON blocks:
@@ -688,12 +695,11 @@ Never output a JSON block as a suggestion — every block executes immediately.
688
695
 
689
696
  ### Calendar
690
697
  calendar_create(summary, start, end, description?, attendees?, location?)
691
- - summary = SHORT title (e.g. "Tagliando BMW"). REQUIRED. Do NOT leave empty.
698
+ - summary = SHORT title derived from what the user actually said. REQUIRED. Do NOT leave empty.
692
699
  - description = optional notes only. Do NOT put the title here.
693
700
  - start/end = ISO 8601 datetimes. Default end = start + 1 hour.
694
- - The tool response includes the REAL eventId in parentheses, e.g. "(eventId: <some-google-id>)". Use that exact value verbatim for subsequent operations. **The eventId is a long lowercase alphanumeric string returned by Google — NEVER make one up.**
695
- Example user says "fissa tagliando BMW 15 maggio ore 17":
696
- {"action":"calendar_create","params":{"summary":"Tagliando BMW","start":"2026-05-15T17:00:00","end":"2026-05-15T18:00:00"}}
701
+ - The tool response includes the REAL eventId. Use that exact value verbatim for any subsequent operation on the same event. The eventId is a long alphanumeric string returned by Google — NEVER fabricate one.
702
+ - Always derive every parameter value from the user's message, never from this documentation.
697
703
 
698
704
  calendar_update(eventId, summary?, location?, description?, start?, end?)
699
705
  - Use this for "correggi", "modifica", "rinomina", "cambia titolo", "sposta", "aggiorna" referring to an event you JUST created or found.