nothumanallowed 16.0.21 → 16.0.22
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.
|
|
3
|
+
"version": "16.0.22",
|
|
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.22';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -752,7 +752,9 @@ class TelegramResponder {
|
|
|
752
752
|
async start() {
|
|
753
753
|
if (!this.enabled) return;
|
|
754
754
|
this.running = true;
|
|
755
|
-
|
|
755
|
+
// Explicit version log at boot so the user can verify what's running.
|
|
756
|
+
// Critical when chasing "bot still mentes" — answers "are you on v16.0.21?".
|
|
757
|
+
this.log(`[Telegram] Responder started — VERSION ${VERSION} — polling for messages`);
|
|
756
758
|
this._pollLoop();
|
|
757
759
|
// Check for npm updates after 60s, then every 24h
|
|
758
760
|
this._updateCheckTimer = setTimeout(() => this._scheduleUpdateCheck(), 60 * 1000);
|
|
@@ -774,8 +776,41 @@ class TelegramResponder {
|
|
|
774
776
|
|
|
775
777
|
async _scheduleUpdateCheck() {
|
|
776
778
|
await this._checkAndNotifyUpdate();
|
|
777
|
-
|
|
779
|
+
await this._checkLocalUpdateAndRestart();
|
|
780
|
+
// Then every 24h for the npm registry check + every 5 min for local install check
|
|
778
781
|
this._updateCheckTimer = setInterval(() => this._checkAndNotifyUpdate(), 24 * 60 * 60 * 1000);
|
|
782
|
+
setInterval(() => this._checkLocalUpdateAndRestart(), 5 * 60 * 1000);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Detect that a NEW version of nha-cli has been installed on disk while
|
|
787
|
+
* this process is still running the OLD code in memory. When detected,
|
|
788
|
+
* exit cleanly so PM2 / launchd / the dispatcher respawns us on the
|
|
789
|
+
* latest code. Without this, the user runs `npm i -g nothumanallowed@latest`
|
|
790
|
+
* but the Telegram bot keeps mentes-ing with the old logic forever.
|
|
791
|
+
*/
|
|
792
|
+
async _checkLocalUpdateAndRestart() {
|
|
793
|
+
try {
|
|
794
|
+
const fileURL = await import('url');
|
|
795
|
+
const here = fileURL.fileURLToPath(import.meta.url);
|
|
796
|
+
// ../../package.json relative to this file (services/message-responder.mjs)
|
|
797
|
+
const pkgPath = path.join(path.dirname(here), '..', '..', 'package.json');
|
|
798
|
+
if (!fs.existsSync(pkgPath)) return;
|
|
799
|
+
const onDisk = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version;
|
|
800
|
+
if (!onDisk || onDisk === VERSION) return;
|
|
801
|
+
this.log(`[Telegram] Detected new install: running v${VERSION}, on-disk v${onDisk}. Restarting to pick up new code…`);
|
|
802
|
+
// Notify any active chat that we're restarting (best-effort, fire and forget)
|
|
803
|
+
try {
|
|
804
|
+
const chatIds = getAllTelegramChatIds();
|
|
805
|
+
for (const chatId of chatIds.slice(0, 3)) {
|
|
806
|
+
this._telegramCall('sendMessage', { chat_id: parseInt(chatId, 10), text: `🔄 Aggiornamento NHA v${VERSION} → v${onDisk} in corso. Torno tra 2 secondi.` }).catch(() => {});
|
|
807
|
+
}
|
|
808
|
+
} catch {}
|
|
809
|
+
// Give the message a moment to flush, then exit. PM2 / dispatcher restarts us.
|
|
810
|
+
setTimeout(() => process.exit(0), 800);
|
|
811
|
+
} catch (e) {
|
|
812
|
+
this.log(`[Telegram] Local update check failed: ${e.message}`);
|
|
813
|
+
}
|
|
779
814
|
}
|
|
780
815
|
|
|
781
816
|
async _checkAndNotifyUpdate() {
|
|
@@ -2018,11 +2018,45 @@ export async function executeTool(action, params, config) {
|
|
|
2018
2018
|
|
|
2019
2019
|
case 'calendar_move': {
|
|
2020
2020
|
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2021
|
+
// ── Resolve eventId from optional query/oldDate (v16.0.22) ──
|
|
2022
|
+
// Agent models often pass {query: 'BMW', newStart} without an eventId.
|
|
2023
|
+
// Instead of failing, resolve it here via listEvents so the move
|
|
2024
|
+
// actually happens. Returns honest error if multiple/no matches.
|
|
2025
|
+
let eventId = params.eventId;
|
|
2026
|
+
if (!eventId && (params.query || params.title || params.oldDate)) {
|
|
2027
|
+
const range = (() => {
|
|
2028
|
+
if (params.oldDate && /^\d{4}-\d{2}-\d{2}$/.test(params.oldDate)) {
|
|
2029
|
+
const [yy, mm, dd] = params.oldDate.split('-').map(n => parseInt(n, 10));
|
|
2030
|
+
const from = new Date(yy, mm - 1, dd);
|
|
2031
|
+
return { from, to: new Date(from.getTime() + 86400000) };
|
|
2032
|
+
}
|
|
2033
|
+
const from = new Date();
|
|
2034
|
+
return { from, to: new Date(from.getTime() + 90 * 86400000) };
|
|
2035
|
+
})();
|
|
2036
|
+
const candidates = await listEvents(config, 'primary', range.from, range.to);
|
|
2037
|
+
const q = String(params.query || params.title || '').toLowerCase();
|
|
2038
|
+
const matching = q
|
|
2039
|
+
? candidates.filter(e => String(e.summary || '').toLowerCase().includes(q))
|
|
2040
|
+
: candidates;
|
|
2041
|
+
if (matching.length === 0) {
|
|
2042
|
+
return `Error: no event found matching "${q || params.oldDate}" — calendar_move did NOT execute.`;
|
|
2043
|
+
}
|
|
2044
|
+
if (matching.length > 1) {
|
|
2045
|
+
const list = matching.slice(0, 5).map((e, i) =>
|
|
2046
|
+
`${i + 1}. ${(e.start || '').slice(0, 10)} ${e.summary}`).join('\n');
|
|
2047
|
+
return `Error: multiple events match "${q}" — be more specific. Candidates:\n${list}`;
|
|
2048
|
+
}
|
|
2049
|
+
eventId = matching[0].id;
|
|
2050
|
+
}
|
|
2051
|
+
if (!eventId) return 'Error: eventId or query/title required.';
|
|
2052
|
+
if (!params.newStart) return 'Error: newStart required.';
|
|
2053
|
+
const newStartISO = new Date(params.newStart).toISOString();
|
|
2054
|
+
const newEndISO = new Date(params.newEnd || (new Date(params.newStart).getTime() + 3600000)).toISOString();
|
|
2055
|
+
await updateEvent(config, 'primary', eventId, {
|
|
2056
|
+
start: { dateTime: newStartISO, timeZone: tz },
|
|
2057
|
+
end: { dateTime: newEndISO, timeZone: tz },
|
|
2024
2058
|
});
|
|
2025
|
-
return `Event rescheduled to ${formatTime(
|
|
2059
|
+
return `Event rescheduled to ${formatTime(newStartISO)} - ${formatTime(newEndISO)}.`;
|
|
2026
2060
|
}
|
|
2027
2061
|
|
|
2028
2062
|
case 'calendar_week': {
|