nothumanallowed 15.1.58 → 15.1.60

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.58",
3
+ "version": "15.1.60",
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/cli.mjs CHANGED
@@ -63,6 +63,10 @@ export async function main(argv) {
63
63
  info(`Run "nha update" (recommended — auto-installs npm + agents)`);
64
64
  info(`Or copy-paste this ENTIRE line (note: --prefer-online, not --pref-online):`);
65
65
  info(` npm cache clean --force && npm install -g nothumanallowed@${result.latest} --prefer-online && hash -r && nha version`);
66
+ info(`⚠ If you ran the install WITHOUT "hash -r" at the end and now get`);
67
+ info(` "bash: ...node/vX.Y.Z/bin/nha: No such file", run: hash -r`);
68
+ info(` (or just close and reopen the terminal). It's a bash path cache issue,`);
69
+ info(` not an install failure — your nha package is already updated.`);
66
70
  }
67
71
  }).catch(() => {});
68
72
  }
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.58';
8
+ export const VERSION = '15.1.60';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -952,6 +952,7 @@ class TelegramResponder {
952
952
  // the LLM entirely: parse the proposal, resolve the eventId via
953
953
  // calendar_date / calendar_find, then call calendar_delete /
954
954
  // calendar_move directly. The user gets a guaranteed real result.
955
+ this._lastDirectAuditChatId = chatId;
955
956
  const directResult = await this._tryDirectAction(lastCtx.agentReply || '', this.config);
956
957
  if (directResult) {
957
958
  this.log(`[Telegram] ${fromUser}: direct-action ${directResult.action} → ${directResult.success ? 'OK' : 'FAIL'}`);
@@ -1043,6 +1044,7 @@ class TelegramResponder {
1043
1044
  // touching the API, OR invent the event list when asked for "all
1044
1045
  // appointments of May". By running the calendar tool server-side, the
1045
1046
  // user always sees REAL data — never fabricated.
1047
+ this._lastDirectAuditChatId = chatId;
1046
1048
  const directFresh = await this._tryDirectFreshCalendarAction(cleanText, this.config);
1047
1049
  if (directFresh) {
1048
1050
  this.log(`[Telegram] ${fromUser}: direct-fresh ${directFresh.action} → ${directFresh.success ? 'OK' : 'FAIL'}`);
@@ -1103,6 +1105,13 @@ class TelegramResponder {
1103
1105
  let responseText;
1104
1106
  let responseHistory = null;
1105
1107
 
1108
+ // Inject cross-agent action audit log into the enriched message so any
1109
+ // agent invoked for this chat is aware of what other agents already did
1110
+ // (calendar deletes, email sends, task creations, etc.). Without this,
1111
+ // HERALD would forget a deletion executed via direct-action 2 turns ago.
1112
+ const auditNote = this._renderAuditForPrompt(chatId);
1113
+ if (auditNote) enrichedMessage = auditNote + enrichedMessage;
1114
+
1106
1115
  if (TOOL_AGENTS.has(agent)) {
1107
1116
  const result = await callAgentWithTools(this.config, agent, enrichedMessage, detectedLang, preHistory);
1108
1117
  responseText = result.text;
@@ -1271,6 +1280,13 @@ class TelegramResponder {
1271
1280
  const message = ok
1272
1281
  ? `Fatto. Ho cancellato "${summary}"${dateStr ? ` del ${this._formatDateIT(dateStr)}` : ''}${match.time ? ` alle ${match.time}` : ''}.`
1273
1282
  : `Non sono riuscito a cancellare l'evento: ${delResult}`;
1283
+ if (this._lastDirectAuditChatId) {
1284
+ this._recordAudit(this._lastDirectAuditChatId, {
1285
+ tool: 'calendar_delete',
1286
+ success: ok,
1287
+ summary: `${summary}${dateStr ? ` del ${this._formatDateIT(dateStr)}` : ''}${match.time ? ` alle ${match.time}` : ''} (eventId ${match.eventId.slice(0, 16)}…)`,
1288
+ });
1289
+ }
1274
1290
  return { action: 'calendar_delete', success: ok, message };
1275
1291
  } catch (err) {
1276
1292
  return { action: 'calendar_delete', success: false, message: `Errore nella cancellazione: ${err.message}` };
@@ -1354,6 +1370,36 @@ class TelegramResponder {
1354
1370
  return events;
1355
1371
  }
1356
1372
 
1373
+ // ── Action audit log (cross-agent memory of REAL executions) ─────────────
1374
+ // Every direct-action OR LLM-mediated tool call that mutates external state
1375
+ // (calendar, email, tasks, contacts, files, github, slack…) is appended
1376
+ // here. The log is per chatId, persisted to disk, capped at 50 entries.
1377
+ //
1378
+ // When ANY agent is invoked for this chat, the recent audit entries are
1379
+ // prepended to the user message as "AZIONI RECENTI ESEGUITE". Result: a
1380
+ // user who deleted a calendar event via HERALD and then asks JARVIS about
1381
+ // it ten minutes later — JARVIS sees the deletion in the audit log and
1382
+ // can answer factually. No more "have I done that?" amnesia.
1383
+ _recordAudit(chatId, entry) {
1384
+ const ctx = this._lastContextByChatId[chatId] || (this._lastContextByChatId[chatId] = {});
1385
+ if (!Array.isArray(ctx.auditLog)) ctx.auditLog = [];
1386
+ ctx.auditLog.push({ ts: Date.now(), ...entry });
1387
+ if (ctx.auditLog.length > 50) ctx.auditLog = ctx.auditLog.slice(-50);
1388
+ this._persistContext();
1389
+ }
1390
+
1391
+ _renderAuditForPrompt(chatId, maxEntries = 10) {
1392
+ const ctx = this._lastContextByChatId[chatId];
1393
+ if (!ctx || !Array.isArray(ctx.auditLog) || ctx.auditLog.length === 0) return '';
1394
+ const recent = ctx.auditLog.slice(-maxEntries);
1395
+ const lines = recent.map(e => {
1396
+ const time = new Date(e.ts).toLocaleString('it-IT', { day: '2-digit', month: 'short', hour: '2-digit', minute: '2-digit' });
1397
+ const status = e.success === false ? '✗ FALLITA' : '✓ OK';
1398
+ return `- ${time} · ${e.tool} · ${status} · ${e.summary || ''}`;
1399
+ });
1400
+ return `\n\n[AZIONI RECENTI ESEGUITE IN QUESTA CONVERSAZIONE — fonte di verità sui fatti già accaduti]\n${lines.join('\n')}\n[FINE AZIONI RECENTI]\n`;
1401
+ }
1402
+
1357
1403
  _formatDateIT(isoDate) {
1358
1404
  const m = String(isoDate || '').match(/^(\d{4})-(\d{2})-(\d{2})$/);
1359
1405
  if (!m) return isoDate;
@@ -1564,6 +1610,15 @@ class TelegramResponder {
1564
1610
  const message = ok
1565
1611
  ? `Fatto. Ho cancellato "${summary}"${dateStr ? ` del ${this._formatDateIT(dateStr)}` : ''}${match.time ? ` alle ${match.time}` : ''}.`
1566
1612
  : `Non sono riuscito a cancellare l'evento: ${delResult}`;
1613
+ // Audit log — every agent in this chat will see this entry on their
1614
+ // next invocation, so no one forgets the deletion happened.
1615
+ if (this._lastDirectAuditChatId) {
1616
+ this._recordAudit(this._lastDirectAuditChatId, {
1617
+ tool: 'calendar_delete',
1618
+ success: ok,
1619
+ summary: `${summary}${dateStr ? ` del ${this._formatDateIT(dateStr)}` : ''}${match.time ? ` alle ${match.time}` : ''} (eventId ${match.eventId.slice(0, 16)}…)`,
1620
+ });
1621
+ }
1567
1622
  return { action: 'calendar_delete', success: ok, message };
1568
1623
  } catch (e) {
1569
1624
  return { action: 'calendar_delete', success: false, message: `Errore nella cancellazione: ${e.message}` };