nothumanallowed 16.0.10 → 16.0.11
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 +76 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.11",
|
|
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.
|
|
8
|
+
export const VERSION = '16.0.11';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -1908,6 +1908,52 @@ class TelegramResponder {
|
|
|
1908
1908
|
async _tryDirectFreshCalendarAction(userMessage, config) {
|
|
1909
1909
|
if (!userMessage || typeof userMessage !== 'string') return null;
|
|
1910
1910
|
const lower = userMessage.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '');
|
|
1911
|
+
const chatId = this._lastDirectAuditChatId;
|
|
1912
|
+
const { executeTool: _executeToolPre } = await import('./tool-executor.mjs');
|
|
1913
|
+
|
|
1914
|
+
// ─── ANAPHORIC delete + CONFIRMATION yes ────────────────────────────────
|
|
1915
|
+
// If the previous turn ran a LIST/LAST-SHOWN and the user now says
|
|
1916
|
+
// "cancellalo / eliminalo / quello / si / conferma / fallo", resolve the
|
|
1917
|
+
// referent from this._lastContextByChatId[chatId].lastCalendarEvents.
|
|
1918
|
+
const isAnaphoric = /\b(cancell|elimin|rimuov)[aeiloy]+(lo|la|li|le|gli)?\b/.test(lower)
|
|
1919
|
+
&& !this._extractCalendarProposal(userMessage).date
|
|
1920
|
+
&& !this._extractCalendarProposal(userMessage).title;
|
|
1921
|
+
const isYesConfirm = /^\s*(s[ìi]\b|si\s|sì\s|ok\b|okay\b|certo\b|certamente\b|d'?accordo\b|fai|fallo|procedi|esegui|conferm[oa]|yes\b|yep\b|confirm\b|do\s*it|go\s*ahead)/i.test(userMessage.trim());
|
|
1922
|
+
if (chatId && (isAnaphoric || isYesConfirm)) {
|
|
1923
|
+
const ctx = this._lastContextByChatId[chatId] || {};
|
|
1924
|
+
const pendingEvents = ctx.lastCalendarEvents || ctx.pendingDeleteEvents || [];
|
|
1925
|
+
// Strict: only auto-execute if the previous turn LIST/proposal had a
|
|
1926
|
+
// single deletable event, or if pendingDelete is explicitly set.
|
|
1927
|
+
const eligible = ctx.pendingDeleteEvents && ctx.pendingDeleteEvents.length > 0
|
|
1928
|
+
? ctx.pendingDeleteEvents
|
|
1929
|
+
: (pendingEvents.length === 1 ? pendingEvents : null);
|
|
1930
|
+
if (eligible && eligible.length > 0) {
|
|
1931
|
+
let ok = 0, ko = 0;
|
|
1932
|
+
const failed = [];
|
|
1933
|
+
for (const ev of eligible) {
|
|
1934
|
+
if (!ev.eventId) { ko++; failed.push(ev.summary || '(no id)'); continue; }
|
|
1935
|
+
try {
|
|
1936
|
+
await _executeToolPre('calendar_delete', { eventId: ev.eventId }, config);
|
|
1937
|
+
ok++;
|
|
1938
|
+
} catch (e) {
|
|
1939
|
+
ko++;
|
|
1940
|
+
failed.push(`${ev.summary || ev.eventId} (${e.message?.slice(0, 60) || 'err'})`);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
// Clear the pending state so we don't double-delete on next yes.
|
|
1944
|
+
delete this._lastContextByChatId[chatId].pendingDeleteEvents;
|
|
1945
|
+
delete this._lastContextByChatId[chatId].lastCalendarEvents;
|
|
1946
|
+
try { (await import('./telegram-context.mjs')).saveTelegramContext(this._lastContextByChatId); } catch {}
|
|
1947
|
+
|
|
1948
|
+
const subject = eligible.length === 1 ? `"${eligible[0].summary}"` : `${eligible.length} appuntamenti`;
|
|
1949
|
+
const lines = [`Ho cancellato ${subject}.`];
|
|
1950
|
+
if (ko > 0) lines.push(`Non sono riuscito a cancellarne ${ko}: ${failed.slice(0, 3).join(', ')}`);
|
|
1951
|
+
this._recordAudit(chatId, { tool: 'calendar_delete', success: ok > 0, summary: `cancellati ${ok}` });
|
|
1952
|
+
return { action: 'calendar_delete', success: ok > 0, message: lines.join('\n') };
|
|
1953
|
+
}
|
|
1954
|
+
// No eligible referent — fall through; the LLM will ask for clarification.
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1911
1957
|
|
|
1912
1958
|
const MONTHS_IT = { gennaio:1, febbraio:2, marzo:3, aprile:4, maggio:5, giugno:6, luglio:7, agosto:8, settembre:9, ottobre:10, novembre:11, dicembre:12 };
|
|
1913
1959
|
const MONTHS_EN = { january:1, february:2, march:3, april:4, may:5, june:6, july:7, august:8, september:9, october:10, november:11, december:12, jan:1, feb:2, mar:3, apr:4, jun:6, jul:7, aug:8, sep:9, oct:10, nov:11, dec:12 };
|
|
@@ -2090,54 +2136,44 @@ class TelegramResponder {
|
|
|
2090
2136
|
|
|
2091
2137
|
// ─── LIST intents ──────────────────────────────────────────────────────
|
|
2092
2138
|
if (isList && !isDelete && !isVerify && !isCreate && !isMove) {
|
|
2093
|
-
//
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
const out = await executeTool('calendar_today', {}, config);
|
|
2097
|
-
return { action: 'calendar_today', success: true, message: String(out) };
|
|
2098
|
-
} catch (e) { return { action: 'calendar_today', success: false, message: `Errore: ${e.message}` }; }
|
|
2099
|
-
}
|
|
2100
|
-
// "appuntamenti di domani"
|
|
2101
|
-
if (/\b(domani|tomorrow)\b/.test(lower)) {
|
|
2139
|
+
// Helper that runs the tool, parses the events and remembers them for
|
|
2140
|
+
// anaphoric resolution in the NEXT turn ("cancellalo", "spostali tutti").
|
|
2141
|
+
const runListAndRemember = async (toolName, args, actionKey) => {
|
|
2102
2142
|
try {
|
|
2103
|
-
const out = await executeTool(
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2143
|
+
const out = await executeTool(toolName, args, config);
|
|
2144
|
+
const events = this._parseEventsFromToolOutput(String(out));
|
|
2145
|
+
if (chatId) {
|
|
2146
|
+
const prev = this._lastContextByChatId[chatId] || {};
|
|
2147
|
+
this._lastContextByChatId[chatId] = {
|
|
2148
|
+
...prev,
|
|
2149
|
+
lastCalendarEvents: events,
|
|
2150
|
+
lastCalendarListAt: Date.now(),
|
|
2151
|
+
lastCalendarSource: { tool: toolName, args },
|
|
2152
|
+
};
|
|
2153
|
+
try { (await import('./telegram-context.mjs')).saveTelegramContext(this._lastContextByChatId); } catch {}
|
|
2154
|
+
}
|
|
2155
|
+
return { action: actionKey, success: true, message: String(out) };
|
|
2156
|
+
} catch (e) { return { action: actionKey, success: false, message: `Errore: ${e.message}` }; }
|
|
2157
|
+
};
|
|
2158
|
+
|
|
2159
|
+
if (/\b(oggi|today)\b/.test(lower))
|
|
2160
|
+
return await runListAndRemember('calendar_today', {}, 'calendar_today');
|
|
2161
|
+
if (/\b(domani|tomorrow)\b/.test(lower))
|
|
2162
|
+
return await runListAndRemember('calendar_tomorrow', {}, 'calendar_tomorrow');
|
|
2163
|
+
if (/\b(settimana|week|questa\s+settimana|this\s+week)\b/.test(lower))
|
|
2164
|
+
return await runListAndRemember('calendar_week', {}, 'calendar_week');
|
|
2115
2165
|
const monthMatch = lower.match(new RegExp(`\\b(${Object.keys(MONTH_MAP).join('|')})(?:\\s+(20\\d{2}))?\\b`));
|
|
2116
2166
|
if (monthMatch) {
|
|
2117
2167
|
const monthNum = MONTH_MAP[monthMatch[1]];
|
|
2118
2168
|
const yearNum = parseInt(monthMatch[2] || String(new Date().getFullYear()), 10);
|
|
2119
|
-
// calendar_month accepts a month string like "2026-05"
|
|
2120
2169
|
const monthStr = `${yearNum}-${String(monthNum).padStart(2, '0')}`;
|
|
2121
|
-
|
|
2122
|
-
const out = await executeTool('calendar_month', { month: monthStr }, config);
|
|
2123
|
-
return { action: 'calendar_month', success: true, message: String(out) };
|
|
2124
|
-
} catch (e) { return { action: 'calendar_month', success: false, message: `Errore: ${e.message}` }; }
|
|
2170
|
+
return await runListAndRemember('calendar_month', { month: monthStr }, 'calendar_month');
|
|
2125
2171
|
}
|
|
2126
|
-
// "appuntamenti del 15 maggio" — specific date
|
|
2127
2172
|
const dateExtracted = this._extractCalendarProposal(userMessage);
|
|
2128
|
-
if (dateExtracted.date)
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
} catch (e) { return { action: 'calendar_date', success: false, message: `Errore: ${e.message}` }; }
|
|
2133
|
-
}
|
|
2134
|
-
// Generic "appuntamenti prossimi" → upcoming 48h
|
|
2135
|
-
if (/\b(prossim|next|upcoming|in\s+arrivo)/.test(lower)) {
|
|
2136
|
-
try {
|
|
2137
|
-
const out = await executeTool('calendar_upcoming', { hours: 48 }, config);
|
|
2138
|
-
return { action: 'calendar_upcoming', success: true, message: String(out) };
|
|
2139
|
-
} catch (e) { return { action: 'calendar_upcoming', success: false, message: `Errore: ${e.message}` }; }
|
|
2140
|
-
}
|
|
2173
|
+
if (dateExtracted.date)
|
|
2174
|
+
return await runListAndRemember('calendar_date', { date: dateExtracted.date }, 'calendar_date');
|
|
2175
|
+
if (/\b(prossim|next|upcoming|in\s+arrivo)/.test(lower))
|
|
2176
|
+
return await runListAndRemember('calendar_upcoming', { hours: 48 }, 'calendar_upcoming');
|
|
2141
2177
|
// Fall through — let the LLM handle ambiguous list requests.
|
|
2142
2178
|
}
|
|
2143
2179
|
|