nothumanallowed 15.1.11 → 15.1.12

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.11",
3
+ "version": "15.1.12",
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.11';
8
+ export const VERSION = '15.1.12';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -1566,16 +1566,26 @@ export async function executeTool(action, params, config) {
1566
1566
  if (Object.keys(patch).length === 0) {
1567
1567
  return 'No fields to update. Specify at least one of: summary (title), location, description, start, end.';
1568
1568
  }
1569
- await updateEvent(config, 'primary', eventId, patch);
1569
+ try {
1570
+ await updateEvent(config, 'primary', eventId, patch);
1571
+ } catch (err) {
1572
+ const msg = String(err?.message || err);
1573
+ if (msg.includes('404') || msg.toLowerCase().includes('not found')) {
1574
+ return `eventId "${eventId}" does NOT exist in Google Calendar. The ID looks invented — DO NOT retry with this value. Call calendar_date or calendar_find FIRST to retrieve real eventIds, then call calendar_update with one of those.`;
1575
+ }
1576
+ throw err;
1577
+ }
1570
1578
  const changes = Object.keys(patch).join(', ');
1571
1579
  return `Event updated successfully (changed: ${changes})${newSummary ? `. New title: "${newSummary}"` : ''}${params.location ? `. New location: ${params.location}` : ''}`;
1572
1580
  }
1573
1581
 
1574
1582
  case 'calendar_delete': {
1575
- if (!params.eventId) return 'eventId required. Call calendar_find first to get the eventId.';
1576
- // Smart eventId resolution: if it looks like a name instead of a Google Calendar ID, search for it
1583
+ if (!params.eventId) return 'eventId required. Call calendar_find or calendar_date first to get the REAL eventId.';
1577
1584
  let delEventId = params.eventId;
1578
- if (delEventId && (delEventId.includes(' ') || delEventId.length < 10 || /[A-Z]/.test(delEventId))) {
1585
+
1586
+ // Branch A — looks like a free-text search query (spaces, caps, very short).
1587
+ // The model passed a NAME instead of an ID — resolve to ID via listEvents.
1588
+ if (delEventId.includes(' ') || delEventId.length < 10 || /[A-Z]/.test(delEventId)) {
1579
1589
  const fromD = new Date();
1580
1590
  const toD = new Date(fromD.getTime() + 60 * 86400000);
1581
1591
  const evts = await listEvents(config, 'primary', fromD, toD);
@@ -1583,11 +1593,39 @@ export async function executeTool(action, params, config) {
1583
1593
  if (m) {
1584
1594
  delEventId = m.id;
1585
1595
  } else {
1586
- return `Could not find event matching "${params.eventId}" in the next 60 days. Use calendar_find to search first.`;
1596
+ return `Could not find event matching "${params.eventId}" in the next 60 days. Use calendar_find or calendar_date to get the real eventId first.`;
1597
+ }
1598
+ }
1599
+
1600
+ // Branch B — try the delete. If Google returns 404 the ID is invalid
1601
+ // (almost always means the model hallucinated it). Surface this clearly
1602
+ // to the LLM so its next turn doesn't try the same fake ID again.
1603
+ try {
1604
+ await deleteEvent(config, 'primary', delEventId);
1605
+ return `Event ${delEventId} deleted successfully.`;
1606
+ } catch (err) {
1607
+ const msg = String(err?.message || err);
1608
+ const is404 = msg.includes('404') || msg.toLowerCase().includes('not found');
1609
+ if (is404) {
1610
+ // Try to look up real events near the requested date (if user hinted one)
1611
+ const hintDate = params.date || params.day || params.on;
1612
+ let hint = '';
1613
+ if (hintDate) {
1614
+ try {
1615
+ const d = new Date(hintDate + 'T00:00:00');
1616
+ const from = d;
1617
+ const to = new Date(d.getTime() + 86400000);
1618
+ const evts = await listEvents(config, 'primary', from, to);
1619
+ if (evts.length > 0) {
1620
+ hint = `\n\nReal events on ${hintDate} (use these IDs, NOT invented ones):\n` +
1621
+ evts.map(e => `- [eventId: ${e.id}] ${formatTime(e.start)} — ${e.summary || '(no title)'}`).join('\n');
1622
+ }
1623
+ } catch { /* ignore */ }
1624
+ }
1625
+ return `eventId "${delEventId}" does NOT exist in Google Calendar. Looks like it was invented — DO NOT retry with this ID. Call calendar_date(YYYY-MM-DD) or calendar_find(query) FIRST to get the real eventId, then call calendar_delete with the value you receive.${hint}`;
1587
1626
  }
1627
+ throw err;
1588
1628
  }
1589
- await deleteEvent(config, 'primary', delEventId);
1590
- return `Event deleted successfully.`;
1591
1629
  }
1592
1630
 
1593
1631
  // ── Smart Scheduling ──────────────────────────────────────────────────