nothumanallowed 13.5.59 → 13.5.60

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.59",
3
+ "version": "13.5.60",
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": {
@@ -4632,12 +4632,40 @@ REGOLE CRITICHE:
4632
4632
  }
4633
4633
 
4634
4634
  // Parse and execute tool calls from response
4635
+ // Sanitize JSON from LLM: replace literal newlines inside JSON strings with \n
4636
+ // Models often write multiline strings without escaping, which breaks JSON.parse
4637
+ const sanitizeToolJson = (raw) => {
4638
+ // Replace literal CR/LF inside JSON string values with escaped versions
4639
+ // Strategy: walk char by char, track if we're inside a JSON string
4640
+ let out = '';
4641
+ let inStr = false;
4642
+ let escaped = false;
4643
+ for (let ci = 0; ci < raw.length; ci++) {
4644
+ const ch = raw[ci];
4645
+ if (escaped) { out += ch; escaped = false; continue; }
4646
+ if (ch === '\\') { out += ch; escaped = true; continue; }
4647
+ if (ch === '"') { inStr = !inStr; out += ch; continue; }
4648
+ if (inStr && (ch === '\n' || ch === '\r')) {
4649
+ out += ch === '\n' ? '\\n' : '\\r';
4650
+ continue;
4651
+ }
4652
+ out += ch;
4653
+ }
4654
+ return out;
4655
+ };
4656
+
4635
4657
  const toolRegex = /<tool>([\s\S]*?)<\/tool>/g;
4636
4658
  let toolMatch;
4637
4659
  const toolResults = [];
4638
4660
  while ((toolMatch = toolRegex.exec(fullResponse)) !== null) {
4639
4661
  let toolCall;
4640
- try { toolCall = JSON.parse(toolMatch[1]); } catch(e) { continue; }
4662
+ try {
4663
+ const raw = toolMatch[1].trim();
4664
+ toolCall = JSON.parse(sanitizeToolJson(raw));
4665
+ } catch(e) {
4666
+ sendEv({ type: 'tool', op: 'parse_error', path: '?', result: 'JSON malformato: ' + e.message.slice(0, 80) });
4667
+ continue;
4668
+ }
4641
4669
 
4642
4670
  if (toolCall.op === 'read') {
4643
4671
  const fp = path.join(sandboxDir, toolCall.path.replace(/^\/+/, ''));
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.59';
8
+ export const VERSION = '13.5.60';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -6984,16 +6984,23 @@ function wcChatPanelHtml() {
6984
6984
  }
6985
6985
  } else {
6986
6986
  var toolBadges = (msg.tools || []).map(function(tool){
6987
- var icon = tool.op === 'edit' ? '&#9998;' : (tool.op === 'write' ? '&#10133;' : '&#128065;');
6988
- var color = tool.result === 'ok' ? 'var(--green)' : 'var(--red)';
6989
- return '<span style="display:inline-flex;align-items:center;gap:3px;background:var(--bg3);border:1px solid var(--border);border-radius:4px;padding:2px 6px;font-size:9px;font-family:var(--mono);color:'+color+'">'+icon+' '+wcEsc(tool.path)+'</span>';
6987
+ var isOk = tool.result === 'ok';
6988
+ var isParseErr = tool.op === 'parse_error';
6989
+ var icon = isParseErr ? '&#10067;' : (tool.op === 'edit' ? '&#9998;' : (tool.op === 'write' ? '&#10133;' : '&#128065;'));
6990
+ var color = isOk ? 'var(--green)' : 'var(--red)';
6991
+ var label = isParseErr ? ('JSON err: ' + wcEsc(tool.result)) : wcEsc(tool.path);
6992
+ var title = isOk ? tool.op + ': ' + tool.path : (tool.result || '');
6993
+ return '<span title="'+wcEsc(title)+'" style="display:inline-flex;align-items:center;gap:3px;background:var(--bg3);border:1px solid '+(isOk?'var(--green3)':'var(--red)')+';border-radius:4px;padding:2px 6px;font-size:9px;font-family:var(--mono);color:'+color+'">' +
6994
+ icon + ' ' + label + '</span>';
6990
6995
  }).join(' ');
6991
- messagesHtml += '<div style="margin:4px 12px">' +
6992
- '<div style="display:flex;align-items:center;gap:6px;margin-bottom:3px">' +
6993
- '<span style="font-size:10px;font-weight:700;color:var(--green)">&#129302; WebCraft Agent</span>' +
6996
+ var agentText = wcEsc(msg.text.replace(new RegExp('<tool>[\\s\\S]*?<\\/tool>', 'g'), '').trim());
6997
+ messagesHtml += '<div style="margin:6px 12px;border:1px solid rgba(255,255,255,0.12);border-radius:10px;background:var(--bg3);overflow:hidden">' +
6998
+ '<div style="display:flex;align-items:center;gap:6px;padding:6px 10px;border-bottom:1px solid rgba(255,255,255,0.06);background:rgba(255,255,255,0.03)">' +
6999
+ '<span style="font-size:13px">&#129302;</span>' +
7000
+ '<span style="font-size:10px;font-weight:700;color:var(--green)">WebCraft Agent</span>' +
6994
7001
  '</div>' +
6995
- '<div style="font-size:11px;color:var(--text);line-height:1.6;white-space:pre-wrap;max-width:85%">'+wcEsc(msg.text.replace(new RegExp('<tool>[\\s\\S]*?<\\/tool>', 'g'), '').trim())+'</div>' +
6996
- (toolBadges ? '<div style="display:flex;flex-wrap:wrap;gap:4px;margin-top:5px">'+toolBadges+'</div>' : '') +
7002
+ '<div style="padding:8px 10px;font-size:11px;color:var(--text);line-height:1.6;white-space:pre-wrap">'+agentText+'</div>' +
7003
+ (toolBadges ? '<div style="display:flex;flex-wrap:wrap;gap:4px;padding:6px 10px;border-top:1px solid rgba(255,255,255,0.06)">'+toolBadges+'</div>' : '') +
6997
7004
  '</div>';
6998
7005
  }
6999
7006
  }