nothumanallowed 13.5.106 → 13.5.108

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": "13.5.106",
3
+ "version": "13.5.108",
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": {
@@ -3206,9 +3206,24 @@ ${rawText.slice(0, 18000)}`;
3206
3206
  }
3207
3207
  }
3208
3208
 
3209
- // City: "a Mantova", "in Bologna", "near Milan", "vicino a Firenze"
3210
- const cityMatch = travelTask.match(/\b(?:a|in|near|vicino\s+a|at|around)\s+([A-Za-z][a-zA-Z\s]{2,25}?)(?:\s*[,\.!?\n]|\s+(?:il|la|per|con|un|una|mi|mia|del|della|per\s+la|il\s+|la\s+)|$)/i);
3211
- const city = cityMatch ? cityMatch[1].trim().replace(/\s+$/, '') : null;
3209
+ // City extraction multi-attempt, most specific first
3210
+ let city = null;
3211
+ const _stopRx = /\s+(il|la|lo|i|le|gli|per|con|un|una|del|della|dei|delle|e|o|\d).*$/i;
3212
+ // P1: "vicino a/near/around <City>"
3213
+ const _cp1 = travelTask.match(/\b(?:vicino\s+a|near|around)\s+([A-Z][a-zA-Z\u00C0-\u017E]{1,}(?:\s+[A-Z][a-zA-Z\u00C0-\u017E]+)?)/);
3214
+ // P2: "a/in <Capitalized City>"
3215
+ const _cp2 = travelTask.match(/\b(?:a|in)\s+([A-Z][a-zA-Z\u00C0-\u017E]{2,}(?:\s+[A-Z][a-zA-Z\u00C0-\u017E]+)?)/);
3216
+ // P3: "a/in <lowercase city>" (case insensitive)
3217
+ const _cp3 = travelTask.match(/\b(?:a|in|at|near)\s+([a-zA-Z\u00C0-\u017E]{3,}(?:\s+[a-zA-Z\u00C0-\u017E]+)?)/i);
3218
+ // P4: standalone known Italian cities (capitalized, no preposition needed)
3219
+ // Known cities worldwide (no preposition needed) — covers IT, EU, global
3220
+ const _knownCities = 'Milano|Roma|Napoli|Torino|Firenze|Bologna|Venezia|Genova|Palermo|Bari|Catania|Verona|Padova|Trieste|Brescia|Bergamo|Modena|Parma|Reggio|Mantova|Ferrara|Vicenza|Treviso|Udine|Trento|Bolzano|Perugia|Ancona|Pescara|Foggia|Salerno|Taranto|Cagliari|Sassari|Siena|Pisa|Lucca|Arezzo|Rimini|Ravenna|Prato|Livorno|Messina|Paris|Lyon|Marseille|Nice|Bordeaux|Toulouse|Strasbourg|Nantes|Madrid|Barcelona|Sevilla|Valencia|Bilbao|Malaga|Lisbon|Porto|Berlin|Munich|Hamburg|Frankfurt|Stuttgart|Cologne|Amsterdam|Rotterdam|Brussels|Vienna|Zurich|Geneva|Prague|Warsaw|Budapest|Bucharest|Athens|Istanbul|London|Manchester|Edinburgh|Dublin|Copenhagen|Stockholm|Oslo|Helsinki|New York|Los Angeles|Chicago|San Francisco|Miami|Boston|Seattle|Tokyo|Osaka|Seoul|Beijing|Shanghai|Singapore|Sydney|Melbourne|Toronto|Montreal|Vancouver|Dubai|Bangkok|Mumbai|Delhi|Cairo|Nairobi';
3221
+ const _cp4 = travelTask.match(new RegExp('\\b(' + _knownCities + ')\\b', 'i'));
3222
+ const _cityRaw = (_cp1 && _cp1[1]) || (_cp2 && _cp2[1]) || (_cp3 && _cp3[1]) || (_cp4 && _cp4[1]) || null;
3223
+ if (_cityRaw) {
3224
+ city = _cityRaw.replace(_stopRx, '').trim();
3225
+ if (city.length < 2) city = null;
3226
+ }
3212
3227
 
3213
3228
  // Cuisine type → OSM cuisine tag
3214
3229
  const cuisineMap = {sushi:'sushi',pizza:'pizza',giapponese:'japanese',japanese:'japanese',italiano:'italian',italian:'italian',cinese:'chinese',chinese:'chinese',indiano:'indian',indian:'indian',steakhouse:'steak_house',trattoria:'italian',osteria:'italian'};
@@ -3341,15 +3356,17 @@ ${rawText.slice(0, 18000)}`;
3341
3356
  sendToken('[Geocoding failed, skipping Overpass] ');
3342
3357
  }
3343
3358
 
3344
- // ── TIER 2: Web search fallback — targeted queries ──
3345
- const dataFound = portalResults.length > 0 && portalResults.some(r => r.includes('trovati') && !r.includes('0 risultati'));
3359
+ // ── TIER 2: Web search fallback — only if Overpass found nothing ──
3360
+ const dataFound = portalResults.length > 0;
3346
3361
  if (!dataFound) {
3347
3362
  sendToken('[Web search fallback...] ');
3348
3363
  try {
3349
- const queries = [
3350
- [cuisineRaw, 'ristorante', city].filter(Boolean).join(' '),
3351
- hasAccommodation ? ['b&b romantico', city, targetDateStr ? targetDateStr.slice(0,5) : ''].filter(Boolean).join(' ') : null
3352
- ].filter(Boolean);
3364
+ const cityStr = city || '';
3365
+ const queries = [];
3366
+ if (hasRestaurant && cityStr) queries.push((cuisineRaw ? cuisineRaw + ' ' : '') + 'ristorante ' + cityStr + ' prenotazione');
3367
+ else if (hasRestaurant) queries.push((cuisineRaw ? cuisineRaw + ' ' : '') + 'ristorante prenotazione online');
3368
+ if (hasAccommodation && cityStr) queries.push('b&b hotel ' + cityStr + (targetDateStr ? ' ' + targetDateStr.slice(0,5) : ''));
3369
+ if (queries.length === 0) queries.push(travelTask.slice(0, 80));
3353
3370
  for (const q of queries) {
3354
3371
  const sr = await withTimeout(executeTool('web_search', { query: q, deep: true }, config), 30000);
3355
3372
  if (sr && sr.length > 100) portalResults.push('## Web search: "' + q + '"\n' + (typeof sr === 'string' ? sr : JSON.stringify(sr)));
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 = '13.5.106';
8
+ export const VERSION = '13.5.108';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11