nothumanallowed 16.0.16 → 16.0.17

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": "16.0.16",
3
+ "version": "16.0.17",
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 = '16.0.16';
8
+ export const VERSION = '16.0.17';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -1160,19 +1160,42 @@ class TelegramResponder {
1160
1160
  // appointments of May". By running the calendar tool server-side, the
1161
1161
  // user always sees REAL data — never fabricated.
1162
1162
  this._lastDirectAuditChatId = chatId;
1163
+
1164
+ // ── UNIVERSAL ANAPHORIC PRE-STEP (v16.0.17) ──
1165
+ // Same logic as tryDirectActionAll on the chat web: intercept
1166
+ // anaphoric commands ("cancellalo", "il primo", "si") BEFORE the
1167
+ // per-domain handlers, since the calendar regex doesn't catch
1168
+ // pronouns and the LLM otherwise hallucinates.
1169
+ let directFresh = null;
1170
+ try {
1171
+ const anaphor = this._detectAnaphoricAction(cleanText);
1172
+ if (anaphor) {
1173
+ const resolved = this._resolveAnaphoric(null, cleanText);
1174
+ if (resolved?.item) {
1175
+ directFresh = await this._executeAnaphoricVerb(anaphor, resolved.kind, resolved.item, cleanText, this.config);
1176
+ } else {
1177
+ this.log(`[Telegram] anaphoric verb=${anaphor} but no item to resolve`);
1178
+ }
1179
+ }
1180
+ } catch (e) {
1181
+ this.log(`[Telegram] anaphoric dispatcher error: ${e.message}`);
1182
+ }
1183
+
1163
1184
  // Run the per-domain direct-action dispatcher. First match wins; falls
1164
1185
  // through to LLM if no handler claims the message.
1165
1186
  // Fast-path specialised handlers (regex-driven, lower latency for the
1166
1187
  // common cases), then the universal dispatcher that covers ALL 50+
1167
1188
  // mutation tools via a single LLM-NLU+deterministic-execute pass.
1168
- const directFresh =
1169
- await this._tryDirectFreshCalendarAction(cleanText, this.config) ||
1170
- await this._tryDirectFreshEmailAction(cleanText, this.config) ||
1171
- await this._tryDirectFreshTaskAction(cleanText, this.config) ||
1172
- await this._tryDirectFreshNoteAction(cleanText, this.config) ||
1173
- await this._tryDirectFreshReminderAction(cleanText, this.config) ||
1174
- await this._tryDirectFreshSlackAction(cleanText, this.config) ||
1175
- await this._tryDirectFreshUniversalAction(cleanText, this.config);
1189
+ if (!directFresh) {
1190
+ directFresh =
1191
+ await this._tryDirectFreshCalendarAction(cleanText, this.config) ||
1192
+ await this._tryDirectFreshEmailAction(cleanText, this.config) ||
1193
+ await this._tryDirectFreshTaskAction(cleanText, this.config) ||
1194
+ await this._tryDirectFreshNoteAction(cleanText, this.config) ||
1195
+ await this._tryDirectFreshReminderAction(cleanText, this.config) ||
1196
+ await this._tryDirectFreshSlackAction(cleanText, this.config) ||
1197
+ await this._tryDirectFreshUniversalAction(cleanText, this.config);
1198
+ }
1176
1199
  if (directFresh) {
1177
1200
  this.log(`[Telegram] ${fromUser}: direct-fresh ${directFresh.action} → ${directFresh.success ? 'OK' : 'FAIL'}`);
1178
1201
  const personaName = this.config.responder?.telegram?.botName || this.config.responder?.botName || '';
@@ -1700,7 +1723,14 @@ class TelegramResponder {
1700
1723
  return { from, to: new Date(from.getTime() + 86400000) };
1701
1724
  }
1702
1725
  if (toolName === 'calendar_week') {
1703
- const from = new Date(now.getFullYear(), now.getMonth(), now.getDate());
1726
+ // Respect optional startDate (e.g. for "settimana prossima").
1727
+ let from;
1728
+ if (args?.startDate && /^\d{4}-\d{2}-\d{2}$/.test(args.startDate)) {
1729
+ const [yy, mm, dd] = args.startDate.split('-').map(n => parseInt(n, 10));
1730
+ from = new Date(yy, mm - 1, dd);
1731
+ } else {
1732
+ from = new Date(now.getFullYear(), now.getMonth(), now.getDate());
1733
+ }
1704
1734
  return { from, to: new Date(from.getTime() + 7 * 86400000) };
1705
1735
  }
1706
1736
  if (toolName === 'calendar_month') {
@@ -2543,6 +2573,26 @@ class TelegramResponder {
2543
2573
  return await runListAndRemember('calendar_today', {}, 'calendar_today');
2544
2574
  if (/\b(domani|tomorrow)\b/.test(lower))
2545
2575
  return await runListAndRemember('calendar_tomorrow', {}, 'calendar_tomorrow');
2576
+ // "settimana prossima / next week / settimana che viene" → calendar_week
2577
+ // starting next Monday. Without this offset, calendar_week always shows
2578
+ // the CURRENT week, which is wrong for "settimana prossima" and lets
2579
+ // the LLM hallucinate a fake list of upcoming events.
2580
+ if (/\b(settimana\s+(prossima|che\s+viene|seguente)|next\s+week|prossima\s+settimana)\b/.test(lower)) {
2581
+ const today = new Date();
2582
+ const dayOfWeek = today.getDay(); // 0=sun..6=sat
2583
+ const daysUntilMonday = ((1 - dayOfWeek + 7) % 7) || 7;
2584
+ const nextMonday = new Date(today.getFullYear(), today.getMonth(), today.getDate() + daysUntilMonday);
2585
+ const startDate = nextMonday.toISOString().slice(0, 10);
2586
+ return await runListAndRemember('calendar_week', { startDate }, 'calendar_week_next');
2587
+ }
2588
+ if (/\b(settimana\s+scorsa|last\s+week|scorsa\s+settimana)\b/.test(lower)) {
2589
+ const today = new Date();
2590
+ const dayOfWeek = today.getDay();
2591
+ const daysToLastMonday = (dayOfWeek === 0 ? 6 : dayOfWeek - 1) + 7;
2592
+ const lastMonday = new Date(today.getFullYear(), today.getMonth(), today.getDate() - daysToLastMonday);
2593
+ const startDate = lastMonday.toISOString().slice(0, 10);
2594
+ return await runListAndRemember('calendar_week', { startDate }, 'calendar_week_last');
2595
+ }
2546
2596
  if (/\b(settimana|week|questa\s+settimana|this\s+week)\b/.test(lower))
2547
2597
  return await runListAndRemember('calendar_week', {}, 'calendar_week');
2548
2598
  const monthMatch = lower.match(new RegExp(`\\b(${Object.keys(MONTH_MAP).join('|')})(?:\\s+(20\\d{2}))?\\b`));