nothumanallowed 13.2.13 → 13.2.15

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.13",
3
+ "version": "13.2.15",
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": {
@@ -2745,10 +2745,8 @@ Respond with ONLY valid JSON, no markdown:
2745
2745
 
2746
2746
  // ── Build system prompt with real tool data ───────────────────
2747
2747
  const isCanvasAgent = agent === 'CanvasAgent';
2748
- // Synthesis agents: do NOT wrap with TOOL_DEFINITIONS use focused prompts only
2749
- const isSynthesisAgent = ['WriterAgent','SummaryAgent','DataAnalystAgent','SecurityAgent','DevOpsAgent'].includes(agent);
2750
- const isToolOutputAgent = ['CalendarAgent','EmailAgent','GitHubAgent','NotionAgent','SlackAgent'].includes(agent);
2751
- const isPureAnalysis = isSynthesisAgent || isToolOutputAgent;
2748
+ // Tool-data agents: fetch real live data and use buildSystemPrompt (tool calls allowed)
2749
+ const isLiveDataAgent = ['CalendarAgent','EmailAgent','GitHubAgent','NotionAgent','SlackAgent','DriveAgent','BrowserAgent','WebSearchAgent','ResearchAgent'].includes(agent);
2752
2750
 
2753
2751
  const canvasSystemPrompt = `You are an HTML report generator. Output a single complete HTML document. No preamble, no explanation.
2754
2752
  RULES:
@@ -2763,33 +2761,38 @@ RULES:
2763
2761
  if (isCanvasAgent) {
2764
2762
  sysPrompt = canvasSystemPrompt;
2765
2763
  userMsg = `Generate a beautiful HTML dashboard report for this content. Start immediately with <!DOCTYPE html>:\n\n${context.slice(0, 8000)}`;
2766
- } else if (isSynthesisAgent) {
2767
- // Focused system promptno TOOL_DEFINITIONS bloat
2768
- const today = new Date().toISOString().split('T')[0];
2769
- const language = config?.language || 'Italian';
2770
- sysPrompt = `You are ${agent}, a specialist AI agent inside NHA Studio. Today is ${today}. Respond in ${language}.
2771
- Task: ${stepPrompt}
2772
- ${toolData ? `\n## LIVE DATA:\n${toolData.slice(0, 4000)}\n` : ''}
2773
- ${context ? `\n## CONTEXT FROM PREVIOUS STEPS:\n${context.slice(0, 5000)}\n` : ''}
2774
- Write your full response in plain prose. Do NOT output JSON, tool calls, or code blocks unless explicitly asked. Use the context and data above — do not ask for more information.`;
2775
- userMsg = toolData
2776
- ? `Use the live data and context above to complete: ${stepPrompt}`
2777
- : context
2778
- ? `Based on the context above, complete: ${stepPrompt}`
2779
- : stepPrompt;
2780
- } else {
2764
+ } else if (isLiveDataAgent) {
2765
+ // These agents fetched real data use buildSystemPrompt so they can call tools too
2781
2766
  const agentInstruction = `You are ${agent}, a specialist AI agent inside NHA Studio.\nYour task: ${stepPrompt}\n` +
2782
2767
  (toolData ? `\n## DATA FROM TOOLS:\n${toolData.slice(0, 4000)}\n` : '') +
2783
2768
  (context ? `\n## OUTPUT FROM PREVIOUS AGENTS:\n${context.slice(0, 3000)}\n` : '') +
2784
- (isToolOutputAgent
2785
- ? '\nWrite your analysis in plain text. Do NOT output JSON, tool calls, or code blocks. Use the context above.'
2786
- : '\nOutput your result directly. No preamble.');
2769
+ '\nWrite your analysis in plain text. Do NOT output JSON, tool calls, or code blocks. Summarize the data clearly.';
2787
2770
  sysPrompt = buildSystemPrompt(agent, agentInstruction, config);
2788
2771
  userMsg = toolData
2789
- ? `Use the data above to complete: ${stepPrompt}`
2772
+ ? `Summarize the data above for: ${stepPrompt}`
2790
2773
  : context
2791
2774
  ? `Based on the previous output, complete: ${stepPrompt}`
2792
2775
  : stepPrompt;
2776
+ } else {
2777
+ // All other agents (WriterAgent, DataAnalystAgent, specialist agents, etc.)
2778
+ // Use a focused prompt with NO TOOL_DEFINITIONS to prevent JSON/tool-call output
2779
+ const today = new Date().toISOString().split('T')[0];
2780
+ const language = config?.language || 'Italian';
2781
+ sysPrompt = `You are ${agent}, a specialist AI agent inside NHA Studio. Today is ${today}. Respond in ${language}.
2782
+
2783
+ CRITICAL RULES:
2784
+ - Do NOT output JSON, tool calls, function calls, or code blocks
2785
+ - Do NOT ask for more information — use only the data provided below
2786
+ - Write in plain prose, structured with headers and bullet points where appropriate
2787
+ - Be thorough and specific — this is for an executive briefing
2788
+
2789
+ ${toolData ? `## LIVE DATA:\n${toolData.slice(0, 4000)}\n` : ''}
2790
+ ${context ? `## CONTEXT FROM PREVIOUS AGENTS:\n${context.slice(0, 5000)}\n` : ''}`;
2791
+ userMsg = toolData
2792
+ ? `Use the live data and context above to complete this task: ${stepPrompt}`
2793
+ : context
2794
+ ? `Using the context from previous steps, complete this task: ${stepPrompt}`
2795
+ : stepPrompt;
2793
2796
  }
2794
2797
 
2795
2798
  // ── Stream LLM response ───────────────────────────────────────
@@ -2798,7 +2801,14 @@ Write your full response in plain prose. Do NOT output JSON, tool calls, or code
2798
2801
  try {
2799
2802
  await withTimeout(
2800
2803
  callLLMStream(config, sysPrompt, userMsg,
2801
- (token) => { fullOutput += token; if (!isCanvasAgent) sendToken(token); },
2804
+ (token) => {
2805
+ fullOutput += token;
2806
+ if (!isCanvasAgent) {
2807
+ // Strip JSON tool calls from synthesis agent output before sending to client
2808
+ const stripped = token.replace(/\{[\s\S]*?"action"[\s\S]*?\}/g, '').trim();
2809
+ if (stripped) sendToken(stripped);
2810
+ }
2811
+ },
2802
2812
  ),
2803
2813
  isCanvasAgent ? 60000 : 35000
2804
2814
  );
@@ -2806,6 +2816,12 @@ Write your full response in plain prose. Do NOT output JSON, tool calls, or code
2806
2816
  if (!isCanvasAgent) sendToken(`[Error: ${e.message}]`);
2807
2817
  }
2808
2818
 
2819
+ // Fallback: if LLM returned empty and we have tool data, send that directly
2820
+ if (!isCanvasAgent && !fullOutput.trim() && toolData) {
2821
+ fullOutput = toolData;
2822
+ sendToken(toolData.slice(0, 2000));
2823
+ }
2824
+
2809
2825
  if (isCanvasAgent) {
2810
2826
  let html = fullOutput.trim();
2811
2827
  // Strip thinking tags if not already filtered
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.13';
8
+ export const VERSION = '13.2.15';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -2715,6 +2715,24 @@ var studioState = {
2715
2715
  planned: false
2716
2716
  };
2717
2717
 
2718
+ function studioReset() {
2719
+ if (studioState.running) return;
2720
+ studioState.task = '';
2721
+ studioState.nodes = [];
2722
+ studioState.log = [];
2723
+ studioState.result = '';
2724
+ studioState.running = false;
2725
+ studioState.planned = false;
2726
+ studioTokens = {in:0, out:0};
2727
+ var ta = document.getElementById('studioTaskInput');
2728
+ if (ta) ta.value = '';
2729
+ var tb = document.getElementById('studioTokenBar');
2730
+ if (tb) tb.textContent = '';
2731
+ renderStudioNodes();
2732
+ renderStudioLog();
2733
+ renderStudioResult();
2734
+ }
2735
+
2718
2736
  var STUDIO_EXAMPLES = [
2719
2737
  'Analyze my unread emails and create a priority action plan',
2720
2738
  'Search the web for AI news today and summarize it in a canvas report',
@@ -2748,18 +2766,25 @@ function renderStudioNodes() {
2748
2766
  else if (n.status === 'done') cls += ' studio-node--done';
2749
2767
  else if (n.status === 'error') cls += ' studio-node--error';
2750
2768
  var statusLabel = {waiting:'&#9711; wait', running:'&#9654; running', done:'&#10003; done', error:'&#10005; error'}[n.status] || '';
2751
- html += '<div class="' + cls + '">';
2769
+ // Only animate nodes that haven't been rendered yet (first appearance)
2770
+ var style = n._rendered ? '' : 'animation-delay:' + (i * 110) + 'ms';
2771
+ html += '<div class="' + cls + '" style="' + style + '">';
2752
2772
  html += '<div class="studio-node__circle">' + n.icon + '</div>';
2753
2773
  html += '<div class="studio-node__label">' + esc(n.label) + '</div>';
2754
2774
  html += '<div class="studio-node__status studio-node__status--' + n.status + '">' + statusLabel + '</div>';
2775
+ if (n.status === 'running') {
2776
+ html += '<div class="studio-node__progress"><span></span><span></span><span></span></div>';
2777
+ }
2755
2778
  html += '</div>';
2756
2779
  if (i < studioState.nodes.length - 1) {
2757
2780
  var next = studioState.nodes[i + 1];
2758
2781
  var arrowCls = 'studio-arrow';
2759
2782
  if (n.status === 'done' && next.status === 'running') arrowCls += ' studio-arrow--active';
2760
2783
  else if (n.status === 'done') arrowCls += ' studio-arrow--done';
2761
- html += '<div class="' + arrowCls + '">&#8594;</div>';
2784
+ var arrowStyle = n._rendered ? '' : 'opacity:0;animation:stNodeIn .3s ease ' + (i * 110 + 55) + 'ms forwards';
2785
+ html += '<div class="' + arrowCls + '" style="' + arrowStyle + '">&#8594;</div>';
2762
2786
  }
2787
+ n._rendered = true;
2763
2788
  });
2764
2789
  html += '</div>';
2765
2790
  el.innerHTML = html;
@@ -2914,7 +2939,8 @@ function renderStudioSessionsBar() {
2914
2939
  if (!sessions.length) { el.style.display = 'none'; return; }
2915
2940
  el.style.display = 'block';
2916
2941
  el.innerHTML = '<div style="font-size:10px;color:var(--dim);margin-bottom:8px;text-transform:uppercase;letter-spacing:1px">Recent sessions</div>' +
2917
- sessions.slice(0,5).map(function(s,i) {
2942
+ '<div style="max-height:220px;overflow-y:auto;padding-right:4px">' +
2943
+ sessions.map(function(s,i) {
2918
2944
  return '<div class="studio-session-item">' +
2919
2945
  '<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
2920
2946
  '<span class="studio-session-task">' + esc(s.task.slice(0,60)) + (s.task.length>60?'...':'') + '</span>' +
@@ -2926,7 +2952,7 @@ function renderStudioSessionsBar() {
2926
2952
  '<button onclick="deleteStudioSession('+i+')" style="font-size:10px;padding:3px 8px;background:none;border:none;color:var(--dim);cursor:pointer">&times;</button>' +
2927
2953
  '</div>' +
2928
2954
  '</div>';
2929
- }).join('');
2955
+ }).join('') + '</div>';
2930
2956
  }
2931
2957
 
2932
2958
  function restoreStudioSession(idx) {
@@ -3031,6 +3057,8 @@ function runStudioStep(idx, node, task, context, stepDef) {
3031
3057
  var ct2 = document.getElementById('canvasTitle');
3032
3058
  if (ct2) ct2.textContent = 'Studio Report';
3033
3059
  }
3060
+ var scb = document.getElementById('studioCanvasBtn');
3061
+ if (scb) scb.style.display = '';
3034
3062
  }
3035
3063
  if (ev.usage) { studioAddTokens(ev.usage.input||0, ev.usage.output||0); }
3036
3064
  if (ev.done) { resolve({output: output || '(no output)', canvas: canvasHtml}); return; }
@@ -3148,7 +3176,10 @@ function renderStudio(el) {
3148
3176
  '</div>' +
3149
3177
  '<div class="studio-input-row">' +
3150
3178
  '<textarea id="studioTaskInput" placeholder="Describe what you want to accomplish... (Ctrl+Enter to run)" onkeydown="if(event.key===\\x27Enter\\x27&&(event.ctrlKey||event.metaKey)){runStudio();event.preventDefault()}">' + esc(studioState.task) + '</textarea>' +
3151
- '<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" ' + (studioState.running ? 'disabled' : '') + '>&#9654; Run</button>' +
3179
+ '<div style="display:flex;gap:6px">' +
3180
+ '<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>&#9654; Run</button>' +
3181
+ '<button onclick="studioReset()" title="New workflow" style="padding:8px 12px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--dim);cursor:pointer;font-size:16px;line-height:1" ' + (studioState.running ? 'disabled' : '') + '>&#8635;</button>' +
3182
+ '</div>' +
3152
3183
  '</div>' +
3153
3184
  '</div>' +
3154
3185
 
@@ -3166,7 +3197,10 @@ function renderStudio(el) {
3166
3197
  '</div>' +
3167
3198
  '</div>' +
3168
3199
 
3169
- '<div id="studioTokenBar" style="font-size:10px;color:var(--dim);margin:8px 0;font-family:var(--mono)"></div>' +
3200
+ '<div style="display:flex;align-items:center;gap:8px;margin:8px 0">' +
3201
+ '<div id="studioTokenBar" style="font-size:10px;color:var(--dim);font-family:var(--mono);flex:1"></div>' +
3202
+ '<button id="studioCanvasBtn" onclick="var p=document.getElementById(\\x27canvasPanel\\x27);if(p)p.classList.add(\\x27open\\x27)" style="display:none;font-size:10px;padding:3px 9px;background:none;border:1px solid var(--green3);border-radius:5px;color:var(--green);cursor:pointer;font-family:var(--mono)">&#9632; Open Canvas</button>' +
3203
+ '</div>' +
3170
3204
  '<div class="studio-canvas" id="studioNodes"></div>' +
3171
3205
  '<div class="studio-log" id="studioLog" style="display:none"></div>' +
3172
3206
  '<div id="studioResult"></div>' +
@@ -3678,9 +3712,15 @@ input:focus,textarea:focus{border-color:var(--green3)}
3678
3712
  .studio-canvas__empty{display:flex;align-items:center;justify-content:center;height:180px;color:var(--dim);font-size:11px;flex-direction:column;gap:8px}
3679
3713
  .studio-canvas__empty-icon{font-size:32px;opacity:.3}
3680
3714
  .studio-nodes{display:flex;align-items:center;gap:0;padding:28px 24px;overflow-x:auto;min-height:130px;background:var(--bg2);border-radius:10px;border:1px solid var(--border);margin-bottom:16px}
3681
- .studio-node{position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;min-width:106px;max-width:126px}
3715
+ .studio-node{position:relative;display:flex;flex-direction:column;align-items:center;gap:7px;min-width:106px;max-width:126px;opacity:0;animation:stNodeIn .35s ease forwards}
3716
+ @keyframes stNodeIn{from{opacity:0;transform:translateY(10px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}
3682
3717
  .studio-node__circle{width:56px;height:56px;border-radius:14px;border:1.5px solid var(--border2);background:var(--bg3);display:flex;align-items:center;justify-content:center;font-size:22px;transition:all .35s;flex-shrink:0}
3683
- .studio-node--active .studio-node__circle{border-color:var(--green3);box-shadow:0 0 0 4px rgba(99,102,241,.15);background:var(--greendim);animation:stRing 1.4s ease-out infinite}
3718
+ .studio-node__progress{display:flex;gap:4px;align-items:center;margin-top:2px}
3719
+ .studio-node__progress span{width:5px;height:5px;border-radius:50%;background:var(--green3);animation:stDot 1.1s ease-in-out infinite}
3720
+ .studio-node__progress span:nth-child(2){animation-delay:.18s}
3721
+ .studio-node__progress span:nth-child(3){animation-delay:.36s}
3722
+ @keyframes stDot{0%,80%,100%{opacity:.2;transform:scale(.7)}40%{opacity:1;transform:scale(1)}}
3723
+ .studio-node--active .studio-node__circle{border-color:var(--green3);box-shadow:0 0 0 6px rgba(99,102,241,.18),0 0 20px rgba(99,102,241,.25);background:var(--greendim);animation:stRing 1.6s ease-out infinite}
3684
3724
  .studio-node--done .studio-node__circle{border-color:#22c55e;background:rgba(34,197,94,.08);box-shadow:0 0 0 3px rgba(34,197,94,.12)}
3685
3725
  .studio-node--error .studio-node__circle{border-color:var(--red);background:rgba(239,68,68,.07)}
3686
3726
  .studio-node__label{font-size:10px;color:var(--dim);text-align:center;line-height:1.3;max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}