nothumanallowed 13.2.46 → 13.2.48

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.2.46",
3
+ "version": "13.2.48",
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": {
@@ -2570,6 +2570,9 @@ export async function cmdUI(args) {
2570
2570
  const extractSearchQuery = (t) => {
2571
2571
  const m = t.match(/(?:cerca|search|find|ricerca|notizie su|news about|latest on|aggiornamenti su|ultime su|tendenz|trend)\s+(.{5,80}?)(?:\s+(?:e |and |per |for |poi |then )|[,\n]|$)/i);
2572
2572
  if (m) return m[1].trim();
2573
+ // If task contains a domain/URL, use it as the search anchor
2574
+ const domainMatch = t.match(/(?:https?:\/\/)?(?:www\.)?([a-z0-9-]+\.[a-z]{2,}(?:\.[a-z]{2,})?)/i);
2575
+ if (domainMatch) return domainMatch[0].replace(/^https?:\/\//,'');
2573
2576
  const stripped = t.replace(/^[^:]+:\s*/,'').split(/[,\n]/)[0].slice(0,100).trim();
2574
2577
  return stripped || t.slice(0,80).trim();
2575
2578
  };
@@ -2709,24 +2712,35 @@ export async function cmdUI(args) {
2709
2712
  } else if (agent === 'WebSearchAgent' || agent === 'ResearchAgent') {
2710
2713
  sendToken('[Searching the web and reading pages...] ');
2711
2714
  try {
2712
- // Extract a concise search query from the step prompt (avoid sending the whole task as query)
2713
- // The planner should provide a short query, but if not, extract key terms
2715
+ // Extract a concise search query from the step prompt
2714
2716
  let searchQuery = stepPrompt;
2715
- // If the prompt is very long (> 120 chars), extract the core search terms
2716
2717
  if (searchQuery.length > 120) {
2717
- // Try to extract a meaningful short query
2718
2718
  const keywordMatch = searchQuery.match(/(?:cerca|search|find|ricerca|notizie su|news about|latest on|aggiornamenti su)\s+(.{5,80}?)(?:\s+(?:e|and|per|for|poi|then)|$)/i);
2719
2719
  if (keywordMatch) {
2720
2720
  searchQuery = keywordMatch[1].trim();
2721
2721
  } else {
2722
- // Take first meaningful clause before comma/period
2723
2722
  searchQuery = searchQuery.split(/[,\.\n]/)[0].slice(0, 100).trim();
2724
2723
  }
2725
2724
  }
2726
- // Use deep search: fetches and reads top 3 pages for real content
2725
+ // If step prompt / task contains a specific domain, fetch that page directly first
2726
+ const domainMatch = (stepPrompt + ' ' + task).match(/(?:https?:\/\/)?(?:www\.)?([a-z0-9-]+\.[a-z]{2,}(?:\/[^\s,]*)?)/i);
2727
+ if (domainMatch) {
2728
+ let targetUrl = domainMatch[0];
2729
+ if (!targetUrl.startsWith('http')) targetUrl = 'https://' + targetUrl;
2730
+ sendToken(`[Fetching ${targetUrl}...] `);
2731
+ try {
2732
+ const fetchResult = await withTimeout(executeTool('fetch_url', { url: targetUrl }, config), 20000);
2733
+ const fetchStr = typeof fetchResult === 'string' ? fetchResult : JSON.stringify(fetchResult);
2734
+ if (fetchStr && !fetchStr.startsWith('HTTP ') && !fetchStr.startsWith('Content blocked')) {
2735
+ toolData = `## Content from ${targetUrl}:\n${fetchStr.slice(0, 5000)}`;
2736
+ }
2737
+ } catch {}
2738
+ }
2739
+ // Deep web search for broader context
2727
2740
  const searchResult = await withTimeout(executeTool('web_search', { query: searchQuery, deep: true }, config), 25000);
2728
- toolData = typeof searchResult === 'string' ? searchResult : JSON.stringify(searchResult);
2729
- } catch (e) { toolData = `Web search failed: ${e.message}`; }
2741
+ const searchStr = typeof searchResult === 'string' ? searchResult : JSON.stringify(searchResult);
2742
+ toolData += (toolData ? '\n\n' : '') + `## Web search results for "${searchQuery}":\n${searchStr}`;
2743
+ } catch (e) { toolData = toolData || `Web search failed: ${e.message}`; }
2730
2744
 
2731
2745
  } else if (agent === 'BrowserAgent') {
2732
2746
  const urlMatch = stepPrompt.match(/https?:\/\/[^\s"']+/);
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.2.46';
8
+ export const VERSION = '13.2.48';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -639,7 +639,16 @@ function onConversationSwitch(){
639
639
 
640
640
  function openCanvasPanel(){
641
641
  var cp = document.getElementById('canvasPanel');
642
- if (cp) cp.classList.add('open');
642
+ if (!cp) return;
643
+ cp.classList.add('open');
644
+ // If no canvas data, show a tip in the frame area
645
+ if (!studioState.canvas) {
646
+ var cf = document.getElementById('canvasFrame');
647
+ if (cf) {
648
+ var tip = \x27<!DOCTYPE html><html><body style="background:#0a0a0a;color:#6b7280;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;text-align:center;padding:20px"><div><div style="font-size:32px;margin-bottom:16px">&#9632;</div><div style="font-size:13px;line-height:1.6">Nessun Canvas in questo workflow.<br>Aggiungi <strong style=\x22color:#4ade80\x22>html</strong>, <strong style=\x22color:#4ade80\x22>dashboard</strong> o <strong style=\x22color:#4ade80\x22>visual</strong> al prompt,<br>oppure usa un task con 2+ agenti specialisti.</div></div></body></html>\x27;
649
+ cf.srcdoc = tip;
650
+ }
651
+ }
643
652
  }
644
653
 
645
654
  function reopenCanvas(){
@@ -697,8 +706,15 @@ function canvasCopyImage(){
697
706
  }
698
707
  function toggleCanvasSize(){
699
708
  var p=document.getElementById('canvasPanel');if(!p)return;
700
- if(p.style.width==='80vw'){p.style.width='';p.style.height='';p.style.top='';p.style.right='';}
701
- else{p.style.width='80vw';p.style.height='80vh';p.style.top='10vh';p.style.right='10vw';}
709
+ if(p.dataset.expanded==='1'){
710
+ p.dataset.expanded='';
711
+ p.style.width='';p.style.height='';p.style.top='';p.style.right='';p.style.left='';p.style.transform='';
712
+ } else {
713
+ p.dataset.expanded='1';
714
+ p.style.width='80vw';p.style.height='80vh';
715
+ p.style.top='10vh';p.style.left='50%';p.style.right='auto';
716
+ p.style.transform='translateX(-50%)';
717
+ }
702
718
  }
703
719
  // ---- MSG ACTIONS ----
704
720
  function copyMsg(i){
@@ -3006,6 +3022,8 @@ function studioReset() {
3006
3022
  studioState.running = false;
3007
3023
  studioState.planned = false;
3008
3024
  studioTokens = {in:0, out:0};
3025
+ var nudgeEl = document.getElementById(\x27studioParliamentNudge\x27);
3026
+ if (nudgeEl) nudgeEl.remove();
3009
3027
  var ta = document.getElementById('studioTaskInput');
3010
3028
  if (ta) ta.value = '';
3011
3029
  var tb = document.getElementById('studioTokenBar');
@@ -3101,9 +3119,21 @@ function renderStudioResult() {
3101
3119
  ? '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><span style="color:var(--dim);font-size:13px">&#10003; ' + t('canvas_generated') + '</span><button onclick="openCanvasPanel()" style="padding:6px 14px;background:var(--greendim);border:1px solid var(--green3);border-radius:8px;color:var(--green);font-size:12px;cursor:pointer;font-weight:700">&#x25A3; ' + t('canvas_open') + '</button></div>'
3102
3120
  : '<div class="md-body">' + renderMd(studioState.result) + '</div>';
3103
3121
  el.innerHTML = '<div class="studio-result__title">&#10003; ' + t('workflow_complete') + '</div>' + body;
3104
- // Show canvas button in toolbar whenever canvas data exists
3122
+ // Update canvas button style: bright green when canvas exists, dimmed otherwise
3105
3123
  var canvasBtn = document.getElementById('studioCanvasBtn');
3106
- if (canvasBtn) canvasBtn.style.display = hasCanvas ? '' : 'none';
3124
+ if (canvasBtn) {
3125
+ if (hasCanvas) {
3126
+ canvasBtn.style.background = 'var(--greendim)';
3127
+ canvasBtn.style.borderColor = 'var(--green3)';
3128
+ canvasBtn.style.color = 'var(--green)';
3129
+ canvasBtn.title = t(\x27canvas_open\x27);
3130
+ } else {
3131
+ canvasBtn.style.background = \x27none\x27;
3132
+ canvasBtn.style.borderColor = \x27var(--border)\x27;
3133
+ canvasBtn.style.color = \x27var(--dim)\x27;
3134
+ canvasBtn.title = \x27Canvas non disponibile per questo workflow\x27;
3135
+ }
3136
+ }
3107
3137
  }
3108
3138
 
3109
3139
  function studioSetNodeStatus(idx, status) {
@@ -3158,6 +3188,21 @@ async function runStudio() {
3158
3188
  renderStudioNodes();
3159
3189
  studioLog('Studio', '&#10003;', 'Workflow planned: ' + planRes.steps.map(function(s){return s.label}).join(' -> '), 'system');
3160
3190
 
3191
+ // Parliament suggestion: show nudge if 3+ specialist steps and Parliament not already enabled
3192
+ var specialistAgents = planRes.steps.filter(function(s){ return !['WebSearchAgent','EmailAgent','CalendarAgent','GitHubAgent','SlackAgent','NotionAgent','CanvasAgent','HERALD'].includes(s.agent); });
3193
+ var parliamentChkEarly = document.getElementById(\x27studioParliamentMode\x27);
3194
+ if (specialistAgents.length >= 2 && parliamentChkEarly && !parliamentChkEarly.checked) {
3195
+ var nudge = document.getElementById(\x27studioParliamentNudge\x27);
3196
+ if (!nudge) {
3197
+ nudge = document.createElement(\x27div\x27);
3198
+ nudge.id = \x27studioParliamentNudge\x27;
3199
+ nudge.style.cssText = \x27margin:8px 0;padding:8px 12px;background:#1a1a2e;border:1px solid #6366f1;border-radius:8px;font-size:11px;color:#a5b4fc;display:flex;align-items:center;gap:10px\x27;
3200
+ nudge.innerHTML = \x27&#x2656; <span><strong>Suggerimento:</strong> questo workflow ha \x27 + specialistAgents.length + \x27 agenti specialisti — attiva <strong>Parlamento</strong> per un confronto critico tra le loro analisi.</span><button onclick="document.getElementById(\\\x27studioParliamentMode\\\x27).checked=true;studioState.parliamentMode=true;this.parentNode.remove()" style="margin-left:auto;background:#6366f1;border:none;border-radius:6px;color:#fff;padding:4px 10px;cursor:pointer;font-size:10px;white-space:nowrap">Attiva &#x2656;</button>\x27;
3201
+ var tokenBar = document.getElementById(\x27studioTokenBar\x27);
3202
+ if (tokenBar && tokenBar.parentNode) tokenBar.parentNode.insertBefore(nudge, tokenBar.parentNode.firstChild);
3203
+ }
3204
+ }
3205
+
3161
3206
  // Step 2: execute each step via SSE
3162
3207
  var context = '';
3163
3208
  for (var i = 0; i < studioState.nodes.length; i++) {
@@ -3584,7 +3629,7 @@ function renderStudio(el) {
3584
3629
 
3585
3630
  '<div style="display:flex;align-items:center;gap:8px;margin:8px 0">' +
3586
3631
  '<div id="studioTokenBar" style="font-size:10px;color:var(--dim);font-family:var(--mono);flex:1"></div>' +
3587
- '<button id="studioCanvasBtn" onclick="openCanvasPanel()" style="display:none;font-size:12px;padding:5px 14px;background:var(--greendim);border:1px solid var(--green3);border-radius:6px;color:var(--green);cursor:pointer;font-weight:700">&#9632; ' + t('canvas_open') + '</button>' +
3632
+ '<button id="studioCanvasBtn" onclick="openCanvasPanel()" title="' + t('canvas_open') + '" style="font-size:12px;padding:5px 14px;background:none;border:1px solid var(--border);border-radius:6px;color:var(--dim);cursor:pointer;font-weight:700;transition:all .2s">&#9632; Canvas</button>' +
3588
3633
  '</div>' +
3589
3634
  '<div class="studio-canvas" id="studioNodes"></div>' +
3590
3635
  '<div class="studio-log" id="studioLog" style="display:none"></div>' +