nothumanallowed 15.1.30 → 15.1.31

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": "15.1.30",
3
+ "version": "15.1.31",
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 = '15.1.30';
8
+ export const VERSION = '15.1.31';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -227,6 +227,15 @@ class SandboxManager {
227
227
  if (line) emit({ type: 'log', msg: `[stderr] ${line}` });
228
228
  });
229
229
 
230
+ // Capture spawn-level errors (e.g. ENOENT on 'node', permission denied).
231
+ // Without this handler, Node would throw an unhandled 'error' event and
232
+ // the whole nha ui process could die silently. This is the missing path
233
+ // that produced the "[error] require is not defined" with no autofix flow.
234
+ proc.on('error', (err) => {
235
+ stderrBuf += `\n[spawn error] ${err.message}\n${err.stack || ''}\n`;
236
+ emit({ type: 'warn', msg: `[spawn error] ${err.code || ''} ${err.message}` });
237
+ });
238
+
230
239
  // Wait for exit or healthy
231
240
  const exitPromise = new Promise((resolve) => {
232
241
  proc.once('exit', (code) => {
@@ -266,14 +275,14 @@ class SandboxManager {
266
275
  emit({ type: 'warn', msg: 'Crash handling skipped: _stoppedByUser=true (user pressed Stop, or previous stop() leaked the flag). If this is unexpected, restart nha ui to pick up the latest fix.' });
267
276
  return;
268
277
  }
269
- emit({ type: 'status', msg: `Process exited with code ${exitCode}` });
278
+ emit({ type: 'status', msg: `Process exited with code ${exitCode} (attempt ${_attempt}/${MAX_RETRIES})` });
270
279
  // Surface the captured stderr right away so the user sees the REAL error
271
280
  // (not just the post-Tier-2 summary). This is the diagnostic gold.
272
281
  if (stderrBuf && stderrBuf.trim()) {
273
- const stderrSnippet = stderrBuf.split('\n').slice(0, 12).join('\n');
274
- emit({ type: 'log', msg: `[stderr captured]\n${stderrSnippet}` });
282
+ const stderrSnippet = stderrBuf.split('\n').slice(0, 20).join('\n');
283
+ emit({ type: 'log', msg: `[stderr full capture, ${stderrBuf.length} bytes]\n${stderrSnippet}` });
275
284
  } else {
276
- emit({ type: 'warn', msg: 'Process exited but no stderr was capturedexit may have been instant.' });
285
+ emit({ type: 'warn', msg: 'Process exited but stderr is EMPTYcould be: process killed by OS, spawn failed before any output, or stdio mis-routed. Run "node .nha-launcher.js" manually in the project dir to reproduce.' });
277
286
  }
278
287
 
279
288
  // ── Tier 1: missing module → npm install + retry ─────────────────────
@@ -318,6 +327,14 @@ class SandboxManager {
318
327
  ];
319
328
 
320
329
  const matchedPattern = runtimePatterns.find(p => p.re.test(stderrBuf));
330
+ // ALWAYS log the autofix decision, so the user can see why Tier 2 fires
331
+ // or doesn't fire. Previous versions emitted nothing when matchedPattern
332
+ // was undefined — leaving the user confused why no autofix ran.
333
+ if (!matchedPattern) {
334
+ emit({ type: 'warn', msg: `Auto-fix: no known runtime pattern matched in stderr. Patterns checked: ${runtimePatterns.map(p => p.name).join(', ')}. stderr starts with: "${stderrBuf.slice(0, 200).replace(/\n/g, ' ⏎ ')}"` });
335
+ } else if (_attempt >= MAX_RETRIES) {
336
+ emit({ type: 'warn', msg: `Auto-fix: pattern "${matchedPattern.name}" matched but MAX_RETRIES (${MAX_RETRIES}) reached. Stopping.` });
337
+ }
321
338
  if (matchedPattern && _attempt < MAX_RETRIES) {
322
339
  emit({ type: 'phase', phase: 'autofix', msg: `Runtime error detected: ${matchedPattern.name} — analyzing...` });
323
340