nothumanallowed 13.2.65 → 13.2.67

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.65",
3
+ "version": "13.2.67",
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 = '13.2.65';
8
+ export const VERSION = '13.2.67';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -420,8 +420,11 @@ function renderMessages(){
420
420
  if(isA&&m.inlineHtml){
421
421
  inlineBlock=m.inlineHtml.replace(/\\[INLINE_CARD\\]([\\s\\S]*?)\\[\\/INLINE_CARD\\]/g,function(_,htm){return '<div class="inline-card">'+htm+'</div>';}).replace(/\\[INLINE_BROWSER\\]([^|]+)\\|([^\\]]+)\\[\\/INLINE_BROWSER\\]/g,function(_,file,url){return '<div class="inline-browser"><div class="inline-browser-bar"><span class="inline-browser-dot"></span><span class="inline-browser-dot"></span><span class="inline-browser-dot"></span><span class="inline-browser-url">'+esc(url)+'</span></div><img src="/api/screenshots/'+esc(file)+'" alt="'+esc(url)+'" onclick="openLightbox(this.src)" style="cursor:zoom-in"></div>';});
422
422
  }
423
+ var isStreaming=isA&&(m.content==='Thinking...'||m.content==='');
423
424
  var bubbleCls=isA?'msg__bubble md-body':'msg__bubble';
424
- h+='<div class="msg msg--'+esc(m.role)+'"><div class="msg__label">'+esc(m.role==='user'?'You':'NHA')+'</div><div class="'+bubbleCls+'">'+content+'</div>'+inlineBlock+acts+'</div>';
425
+ var displayContent=isStreaming?'<div class="typing-dots"><span></span><span></span><span></span></div>':content;
426
+ var streamCls=isStreaming?' msg--streaming':'';
427
+ h+='<div class="msg msg--'+esc(m.role)+streamCls+'"><div class="msg__label">'+esc(m.role==='user'?'You':'NHA')+'</div><div class="'+bubbleCls+'">'+displayContent+'</div>'+inlineBlock+acts+'</div>';
425
428
  });
426
429
  el.innerHTML=h;el.scrollTop=el.scrollHeight;
427
430
  // Load fork info for messages that have IDs
@@ -882,7 +885,7 @@ function sendChat(){
882
885
  displayContent=displayContent.replace(/<think>[\\s\\S]*?<\\/think>/g,'').trim();
883
886
  }
884
887
  var el=document.getElementById('chatMessages');
885
- if(el){var msgs=el.querySelectorAll('.msg');var last=msgs[msgs.length-1];if(last){var bub=last.querySelector('.msg__bubble');if(bub){bub.className='msg__bubble md-body';bub.innerHTML=isThinking?displayContent:renderMd(displayContent)||'Thinking...';}}el.scrollTop=el.scrollHeight;}
888
+ if(el){var msgs=el.querySelectorAll('.msg');var last=msgs[msgs.length-1];if(last){last.classList.add('msg--streaming');var bub=last.querySelector('.msg__bubble');if(bub){bub.className='msg__bubble md-body';var renderedContent=isThinking?displayContent:renderMd(displayContent);bub.innerHTML=renderedContent||'<div class="typing-dots"><span></span><span></span><span></span></div>';}}el.scrollTop=el.scrollHeight;}
886
889
  }
887
890
  if(currentEvent==='tool'){
888
891
  var toolLabels={browser_open:'Opening page',browser_screenshot:'Taking screenshot',browser_click:'Clicking element',browser_type:'Typing text',browser_extract:'Extracting content',browser_js:'Running JavaScript',browser_wait:'Waiting for element',browser_scroll:'Scrolling page',browser_key:'Pressing key',browser_close:'Closing browser',web_search:'Searching the web',fetch_url:'Fetching URL',gmail_list:'Searching emails',gmail_read:'Reading email',gmail_send:'Sending email',calendar_today:'Loading calendar',calendar_create:'Creating event'};
@@ -3238,6 +3241,8 @@ function studioReset() {
3238
3241
  studioState.canvas = null;
3239
3242
  studioState.running = false;
3240
3243
  studioState.planned = false;
3244
+ studioState.attachmentContext = '';
3245
+ studioState.attachmentName = '';
3241
3246
  studioTokens = {in:0, out:0};
3242
3247
  var nudgeEl = document.getElementById(\x27studioParliamentNudge\x27);
3243
3248
  if (nudgeEl) nudgeEl.remove();
@@ -3250,6 +3255,42 @@ function studioReset() {
3250
3255
  renderStudioResult();
3251
3256
  }
3252
3257
 
3258
+ function studioClearAttach() {
3259
+ studioState.attachmentContext = '';
3260
+ studioState.attachmentName = '';
3261
+ var badge = document.getElementById('studioAttachBadge');
3262
+ if (badge) badge.remove();
3263
+ var fi = document.getElementById('studioFileInput');
3264
+ if (fi) fi.value = '';
3265
+ }
3266
+
3267
+ function studioHandleAttach(file) {
3268
+ if (!file) return;
3269
+ var name = file.name;
3270
+ var isPdf = name.toLowerCase().endsWith('.pdf');
3271
+ var isImg = /\.(png|jpe?g|gif|webp)$/i.test(name);
3272
+ if (!isPdf && !isImg) { alert('Supported: PDF, PNG, JPG, GIF, WEBP'); return; }
3273
+
3274
+ var reader = new FileReader();
3275
+ reader.onload = function(ev) {
3276
+ var dataUrl = ev.target.result;
3277
+ studioState.attachmentName = name;
3278
+ studioState.attachmentContext = (isPdf ? '[ATTACHED PDF: ' : '[ATTACHED IMAGE: ') + name + ']\nBase64: ' + dataUrl;
3279
+ // Show badge inline without full re-render
3280
+ var inputRow = document.querySelector('.studio-input-row');
3281
+ if (inputRow) {
3282
+ var existing = document.getElementById('studioAttachBadge');
3283
+ if (existing) existing.remove();
3284
+ var badge = document.createElement('div');
3285
+ badge.id = 'studioAttachBadge';
3286
+ badge.style.cssText = 'display:flex;align-items:center;gap:6px;padding:4px 10px;background:var(--greendim);border:1px solid var(--green3);border-radius:6px;margin-bottom:6px;font-size:11px;color:var(--green);font-family:var(--mono)';
3287
+ badge.innerHTML = '&#128206; ' + esc(name) + ' <span onclick="studioClearAttach()" style="cursor:pointer;color:var(--dim);font-size:13px;margin-left:4px" title="Remove">&#215;</span>';
3288
+ inputRow.insertBefore(badge, inputRow.children[1]);
3289
+ }
3290
+ };
3291
+ reader.readAsDataURL(file);
3292
+ }
3293
+
3253
3294
  var STUDIO_EXAMPLES = [
3254
3295
  'Analyze my unread emails and create a priority action plan',
3255
3296
  'Search the web for AI news today and summarize it in a canvas report',
@@ -3395,11 +3436,17 @@ function downloadStudioPDF() {
3395
3436
  '<div class="footer-bar">NHA Studio &nbsp;·&nbsp; nothumanallowed.com &nbsp;·&nbsp; ' + today + '</div>' +
3396
3437
  '</body></html>';
3397
3438
 
3398
- var win = window.open('', '_blank');
3399
- if (!win) { alert('Popup bloccato — abilita i popup per scaricare il PDF'); return; }
3400
- win.document.write(html);
3401
- win.document.close();
3402
- win.onload = function() { setTimeout(function(){ win.print(); }, 300); };
3439
+ // Use Blob URL to avoid popup blockers — opens in new tab, user can Cmd+P to print as PDF
3440
+ var blob = new Blob([html], {type: 'text/html'});
3441
+ var url = URL.createObjectURL(blob);
3442
+ var a = document.createElement('a');
3443
+ a.href = url;
3444
+ a.target = '_blank';
3445
+ a.download = (studioState.task || 'NHA Studio Report').slice(0, 60).replace(/[^a-z0-9\s]/gi,'').trim().replace(/\s+/g,'-') + '.html';
3446
+ document.body.appendChild(a);
3447
+ a.click();
3448
+ document.body.removeChild(a);
3449
+ setTimeout(function(){ URL.revokeObjectURL(url); }, 5000);
3403
3450
  }
3404
3451
 
3405
3452
  function renderStudioResult() {
@@ -3450,6 +3497,7 @@ async function runStudio() {
3450
3497
  studioState.canvas = null;
3451
3498
  studioState.running = true;
3452
3499
  studioState.planned = false;
3500
+ // Keep attachmentContext — it was loaded before hitting Run
3453
3501
  renderStudioNodes();
3454
3502
  renderStudioLog();
3455
3503
  renderStudioResult();
@@ -3468,7 +3516,10 @@ async function runStudio() {
3468
3516
 
3469
3517
  try {
3470
3518
  // Step 1: plan the workflow
3471
- var planRes = await apiPost('/api/studio/plan', {task: task});
3519
+ var taskForPlan = studioState.attachmentContext
3520
+ ? task + '\n\n[User has attached a file: ' + studioState.attachmentName + '. Agents will receive the full content.]'
3521
+ : task;
3522
+ var planRes = await apiPost('/api/studio/plan', {task: taskForPlan});
3472
3523
  if (!planRes || !planRes.steps || !planRes.steps.length) {
3473
3524
  studioLog('Studio', '&#9888;', 'Could not plan workflow. Check your LLM provider config.', 'error');
3474
3525
  studioState.running = false;
@@ -3728,7 +3779,11 @@ function runStudioStep(idx, node, task, context, stepDef, signal) {
3728
3779
  return new Promise(function(resolve) {
3729
3780
  var output = '';
3730
3781
  var canvasHtml = null;
3731
- var body = JSON.stringify({stepIdx: idx, agent: node.agent, task: task, context: context, stepDef: stepDef});
3782
+ // Inject attachment context into first step (idx===0) if present
3783
+ var effectiveContext = (idx === 0 && studioState.attachmentContext)
3784
+ ? (studioState.attachmentContext + (context ? '\n\n' + context : ''))
3785
+ : context;
3786
+ var body = JSON.stringify({stepIdx: idx, agent: node.agent, task: task, context: effectiveContext, stepDef: stepDef});
3732
3787
  var fetchOpts = {method: 'POST', headers: {'Content-Type': 'application/json'}, body: body};
3733
3788
  if (signal) fetchOpts.signal = signal;
3734
3789
 
@@ -3901,7 +3956,10 @@ function renderStudio(el) {
3901
3956
  '</div>' +
3902
3957
  '<div class="studio-input-row">' +
3903
3958
  '<textarea id="studioTaskInput" placeholder="' + t('placeholder_studio') + '" onkeydown="if(event.key===\\x27Enter\\x27&&(event.ctrlKey||event.metaKey)){runStudio();event.preventDefault()}">' + esc(studioState.task) + '</textarea>' +
3959
+ (studioState.attachmentName ? '<div id="studioAttachBadge" style="display:flex;align-items:center;gap:6px;padding:4px 10px;background:var(--greendim);border:1px solid var(--green3);border-radius:6px;margin-bottom:6px;font-size:11px;color:var(--green);font-family:var(--mono)">&#128206; ' + esc(studioState.attachmentName) + ' <span onclick="studioClearAttach()" style="cursor:pointer;color:var(--dim);font-size:13px;margin-left:4px" title="Rimuovi">&#215;</span></div>' : '') +
3960
+ '<input type="file" id="studioFileInput" accept=".pdf,.png,.jpg,.jpeg,.gif,.webp" style="display:none" onchange="studioHandleAttach(this.files[0])">' +
3904
3961
  '<div style="display:flex;gap:6px">' +
3962
+ '<button onclick="document.getElementById(\\x27studioFileInput\\x27).click()" title="Attach PDF or image" style="padding:8px 10px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--dim);cursor:pointer;font-size:15px" ' + (studioState.running ? 'disabled' : '') + '>&#128206;</button>' +
3905
3963
  '<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>' + t('run') + '</button>' +
3906
3964
  '<button id="studioStopBtn" onclick="stopStudio()" title="' + t('stop') + '" style="padding:8px 14px;background:#7f1d1d;border:1px solid #ef4444;border-radius:8px;color:#ef4444;cursor:pointer;font-size:13px;font-weight:700;white-space:nowrap;' + (studioState.running ? '' : 'display:none') + '">&#9632; ' + t('stop') + '</button>' +
3907
3965
  '<button onclick="studioReset()" title="' + t('reset') + '" 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>' +
@@ -4144,6 +4202,10 @@ function init(){
4144
4202
  if(bv)makeDraggable(bv,\x27.browser-viewer__header\x27);
4145
4203
  var cp=document.getElementById('canvasPanel');
4146
4204
  if(cp)makeDraggable(cp,\x27.cvs-header\x27);
4205
+ // Telemetry ping — fire and forget
4206
+ setTimeout(function(){
4207
+ fetch(\x27https://nothumanallowed.com/api/v1/telemetry/ping\x27,{method:\x27POST\x27,headers:{\x27Content-Type\x27:\x27application/json\x27},body:JSON.stringify({platform:\x27web-ui\x27,version:VERSION})}).catch(function(){});
4208
+ },3000);
4147
4209
  }
4148
4210
  init();
4149
4211
  `;
@@ -4248,9 +4310,15 @@ input:focus,textarea:focus{border-color:var(--green3)}
4248
4310
  .chat__empty-hint{font-size:11px;margin-top:12px}
4249
4311
  .msg{margin-bottom:12px}
4250
4312
  .msg--user .msg__bubble{background:var(--bg3);border:1px solid var(--border2);border-radius:8px 8px 2px 8px;padding:10px 14px;max-width:85%;margin-left:auto;color:var(--bright)}
4251
- .msg--assistant .msg__bubble{background:var(--greendim);border:1px solid var(--green3);border-radius:8px 8px 8px 2px;padding:10px 14px;max-width:85%;color:var(--text);white-space:pre-wrap;word-wrap:break-word;line-height:1.5}
4313
+ .msg--assistant .msg__bubble{background:var(--greendim);border:1px solid var(--green3);border-radius:8px 8px 8px 2px;padding:10px 14px;max-width:85%;color:var(--text);white-space:pre-wrap;word-wrap:break-word;line-height:1.5;min-height:40px;min-width:60px}
4252
4314
  .msg--assistant .msg__bubble img{max-width:100%;border-radius:8px;margin:8px 0;border:1px solid rgba(0,255,65,0.2)}
4315
+ .msg--assistant.msg--streaming .msg__bubble{border-color:var(--green);box-shadow:0 0 8px rgba(0,255,65,0.15)}
4253
4316
  .msg__label{font-size:10px;color:var(--dim);margin-bottom:2px}
4317
+ .typing-dots{display:inline-flex;align-items:center;gap:4px;padding:4px 0}
4318
+ .typing-dots span{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--green);opacity:0.3;animation:tdot 1.2s ease-in-out infinite}
4319
+ .typing-dots span:nth-child(2){animation-delay:0.2s}
4320
+ .typing-dots span:nth-child(3){animation-delay:0.4s}
4321
+ @keyframes tdot{0%,80%,100%{opacity:0.2;transform:scale(0.8)}40%{opacity:1;transform:scale(1.2)}}
4254
4322
  .msg__actions{display:flex;gap:6px;margin-top:4px;opacity:0.4;transition:opacity 0.2s}
4255
4323
  .msg:hover .msg__actions{opacity:1}
4256
4324
  .msg__actions button{background:none;border:none;color:var(--dim);cursor:pointer;font-size:10px;font-family:var(--mono);padding:2px 4px}