nothumanallowed 13.2.14 → 13.2.16

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.14",
3
+ "version": "13.2.16",
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": {
@@ -2658,11 +2658,14 @@ Respond with ONLY valid JSON, no markdown:
2658
2658
  // Keepalive: send a comment every 5s so the connection doesn't time out during slow tool calls
2659
2659
  const keepalive = setInterval(() => { try { res.write(': keepalive\n\n'); } catch {} }, 5000);
2660
2660
 
2661
- // Timeout wrapper for tool calls 25s max
2662
- const withTimeout = (promise, label) => Promise.race([
2663
- promise,
2664
- new Promise((_, rej) => setTimeout(() => rej(new Error(`${label} timed out after 25s`)), 25000)),
2665
- ]);
2661
+ // Timeout wrapper ms param optional (default 25s for tool calls)
2662
+ const withTimeout = (promise, ms) => {
2663
+ const delay = typeof ms === 'number' ? ms : 25000;
2664
+ return Promise.race([
2665
+ promise,
2666
+ new Promise((_, rej) => setTimeout(() => rej(new Error(`Step timed out after ${delay/1000}s`)), delay)),
2667
+ ]);
2668
+ };
2666
2669
 
2667
2670
  try {
2668
2671
  const stepPrompt = stepDef?.prompt || task;
@@ -2801,7 +2804,14 @@ ${context ? `## CONTEXT FROM PREVIOUS AGENTS:\n${context.slice(0, 5000)}\n` : ''
2801
2804
  try {
2802
2805
  await withTimeout(
2803
2806
  callLLMStream(config, sysPrompt, userMsg,
2804
- (token) => { fullOutput += token; if (!isCanvasAgent) sendToken(token); },
2807
+ (token) => {
2808
+ fullOutput += token;
2809
+ if (!isCanvasAgent) {
2810
+ // Strip JSON tool calls from synthesis agent output before sending to client
2811
+ const stripped = token.replace(/\{[\s\S]*?"action"[\s\S]*?\}/g, '').trim();
2812
+ if (stripped) sendToken(stripped);
2813
+ }
2814
+ },
2805
2815
  ),
2806
2816
  isCanvasAgent ? 60000 : 35000
2807
2817
  );
@@ -2809,6 +2819,12 @@ ${context ? `## CONTEXT FROM PREVIOUS AGENTS:\n${context.slice(0, 5000)}\n` : ''
2809
2819
  if (!isCanvasAgent) sendToken(`[Error: ${e.message}]`);
2810
2820
  }
2811
2821
 
2822
+ // Fallback: if LLM returned empty and we have tool data, send that directly
2823
+ if (!isCanvasAgent && !fullOutput.trim() && toolData) {
2824
+ fullOutput = toolData;
2825
+ sendToken(toolData.slice(0, 2000));
2826
+ }
2827
+
2812
2828
  if (isCanvasAgent) {
2813
2829
  let html = fullOutput.trim();
2814
2830
  // 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.14';
8
+ export const VERSION = '13.2.16';
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,20 +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:'◯ wait', running:'▶ running', done:'✓ done', error:'✕ error'}[n.status] || '';
2751
- var delay = (i * 120) + 'ms';
2752
- html += '<div class="' + cls + '" style="animation-delay:' + delay + '">';
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 + '">';
2753
2772
  html += '<div class="studio-node__circle">' + n.icon + '</div>';
2754
2773
  html += '<div class="studio-node__label">' + esc(n.label) + '</div>';
2755
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
+ }
2756
2778
  html += '</div>';
2757
2779
  if (i < studioState.nodes.length - 1) {
2758
2780
  var next = studioState.nodes[i + 1];
2759
2781
  var arrowCls = 'studio-arrow';
2760
2782
  if (n.status === 'done' && next.status === 'running') arrowCls += ' studio-arrow--active';
2761
2783
  else if (n.status === 'done') arrowCls += ' studio-arrow--done';
2762
- var arrowDelay = (i * 120 + 60) + 'ms';
2763
- html += '<div class="' + arrowCls + '" style="opacity:0;animation:stNodeIn .3s ease ' + arrowDelay + ' forwards">&#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>';
2764
2786
  }
2787
+ n._rendered = true;
2765
2788
  });
2766
2789
  html += '</div>';
2767
2790
  el.innerHTML = html;
@@ -2916,7 +2939,8 @@ function renderStudioSessionsBar() {
2916
2939
  if (!sessions.length) { el.style.display = 'none'; return; }
2917
2940
  el.style.display = 'block';
2918
2941
  el.innerHTML = '<div style="font-size:10px;color:var(--dim);margin-bottom:8px;text-transform:uppercase;letter-spacing:1px">Recent sessions</div>' +
2919
- 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) {
2920
2944
  return '<div class="studio-session-item">' +
2921
2945
  '<div style="display:flex;align-items:center;justify-content:space-between;gap:8px">' +
2922
2946
  '<span class="studio-session-task">' + esc(s.task.slice(0,60)) + (s.task.length>60?'...':'') + '</span>' +
@@ -2928,7 +2952,7 @@ function renderStudioSessionsBar() {
2928
2952
  '<button onclick="deleteStudioSession('+i+')" style="font-size:10px;padding:3px 8px;background:none;border:none;color:var(--dim);cursor:pointer">&times;</button>' +
2929
2953
  '</div>' +
2930
2954
  '</div>';
2931
- }).join('');
2955
+ }).join('') + '</div>';
2932
2956
  }
2933
2957
 
2934
2958
  function restoreStudioSession(idx) {
@@ -3033,6 +3057,8 @@ function runStudioStep(idx, node, task, context, stepDef) {
3033
3057
  var ct2 = document.getElementById('canvasTitle');
3034
3058
  if (ct2) ct2.textContent = 'Studio Report';
3035
3059
  }
3060
+ var scb = document.getElementById('studioCanvasBtn');
3061
+ if (scb) scb.style.display = '';
3036
3062
  }
3037
3063
  if (ev.usage) { studioAddTokens(ev.usage.input||0, ev.usage.output||0); }
3038
3064
  if (ev.done) { resolve({output: output || '(no output)', canvas: canvasHtml}); return; }
@@ -3150,7 +3176,10 @@ function renderStudio(el) {
3150
3176
  '</div>' +
3151
3177
  '<div class="studio-input-row">' +
3152
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>' +
3153
- '<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>' +
3154
3183
  '</div>' +
3155
3184
  '</div>' +
3156
3185
 
@@ -3168,7 +3197,10 @@ function renderStudio(el) {
3168
3197
  '</div>' +
3169
3198
  '</div>' +
3170
3199
 
3171
- '<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>' +
3172
3204
  '<div class="studio-canvas" id="studioNodes"></div>' +
3173
3205
  '<div class="studio-log" id="studioLog" style="display:none"></div>' +
3174
3206
  '<div id="studioResult"></div>' +
@@ -3683,7 +3715,12 @@ input:focus,textarea:focus{border-color:var(--green3)}
3683
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}
3684
3716
  @keyframes stNodeIn{from{opacity:0;transform:translateY(10px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}
3685
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}
3686
- .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}
3687
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)}
3688
3725
  .studio-node--error .studio-node__circle{border-color:var(--red);background:rgba(239,68,68,.07)}
3689
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}