nothumanallowed 15.1.17 → 15.1.18

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.17",
3
+ "version": "15.1.18",
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.17';
8
+ export const VERSION = '15.1.18';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -246,11 +246,10 @@ class SandboxManager {
246
246
  if (this._stoppedByUser) return;
247
247
  emit({ type: 'status', msg: `Process exited with code ${exitCode}` });
248
248
 
249
- // Extract missing module name from stderr
249
+ // ── Tier 1: missing module npm install + retry ─────────────────────
250
250
  const missingMatch = stderrBuf.match(/Cannot find module ['"]([^'"]+)['"]/);
251
251
  if (missingMatch && _attempt < MAX_RETRIES) {
252
252
  const missingMod = missingMatch[1];
253
- // Skip shim-able or built-in modules
254
253
  if (!missingMod.startsWith('.') && !missingMod.startsWith('/') && !missingMod.startsWith('node:')) {
255
254
  const pkgName = missingMod.startsWith('@') ? missingMod.split('/').slice(0, 2).join('/') : missingMod.split('/')[0];
256
255
  emit({ type: 'phase', phase: 'autofix', msg: `Missing module "${pkgName}" — installing...` });
@@ -268,6 +267,102 @@ class SandboxManager {
268
267
  }
269
268
  }
270
269
 
270
+ // ── Tier 2: runtime errors that need code fix (require/import mismatch,
271
+ // SyntaxError, ReferenceError, TypeError) — extract failing file from
272
+ // stack trace and ask LLM to repair it. This is the bug the user hit:
273
+ // "require is not defined" inside an ESM project should auto-rewrite
274
+ // require() → import statements, or flip package.json "type" field. ───
275
+ const runtimePatterns = [
276
+ { name: 'CJS/ESM mismatch', re: /require is not defined/i,
277
+ hint: 'The file uses CommonJS `require()` but the project is ESM ("type":"module" in package.json or .mjs extension). Convert all `require(\'X\')` to ES module `import` statements. Convert `module.exports = ...` to `export default ...`. Keep all logic identical.' },
278
+ { name: 'ESM/CJS mismatch', re: /Cannot use import statement outside a module/i,
279
+ hint: 'The file uses ES module `import` but the project is CommonJS. Either add `"type":"module"` to package.json (preferred for new projects) or convert imports to `require()`.' },
280
+ { name: 'import.meta misuse', re: /import\.meta(?:\.url)? is only valid in/i,
281
+ hint: 'The file uses `import.meta` in a CommonJS context. Either switch the project to ESM (add `"type":"module"` to package.json) or replace `import.meta.url` with `__filename` / `__dirname`.' },
282
+ { name: 'SyntaxError', re: /SyntaxError:.+/i,
283
+ hint: 'The file has a JavaScript syntax error. Fix the syntax issue — unclosed brackets, missing commas, invalid tokens. Output the complete corrected file.' },
284
+ { name: 'ReferenceError', re: /ReferenceError: (\w+) is not defined/i,
285
+ hint: 'A variable is referenced but never declared/imported. Either import it from the correct module or declare it. Common missing globals: "require" (use import), "process" (Node only — add `import process from \'node:process\'` in ESM), "__dirname" (in ESM use `import.meta.url` + fileURLToPath).' },
286
+ { name: 'TypeError null/undefined', re: /TypeError: Cannot read prop(?:erties|erty)? .+ of (?:undefined|null)/i,
287
+ hint: 'Null/undefined access. Add a null-check or optional chaining (?.) before the failing access.' },
288
+ ];
289
+
290
+ const matchedPattern = runtimePatterns.find(p => p.re.test(stderrBuf));
291
+ if (matchedPattern && _attempt < MAX_RETRIES) {
292
+ // Extract the file path from the stack trace.
293
+ // Patterns: "at /abs/path/file.js:N:M", "at file:///abs/path/file.js:N:M",
294
+ // "at Object.<anonymous> (/path/file.js:N:M)", or simply at start of stderr.
295
+ const fileMatches = [...stderrBuf.matchAll(/(?:at\s+(?:[\w<>\.\s]+\s+)?\(?)?(?:file:\/\/)?(\/[^\s:()'"]+\.(?:m?js|cjs|jsx?|tsx?)):\d+(?::\d+)?/g)];
296
+ const projectFiles = fileMatches
297
+ .map(m => m[1])
298
+ .filter(p => p && p.startsWith(projectDir))
299
+ .map(p => path.relative(projectDir, p))
300
+ .filter((v, i, a) => a.indexOf(v) === i)
301
+ .slice(0, 3);
302
+
303
+ if (projectFiles.length > 0) {
304
+ emit({ type: 'phase', phase: 'autofix', msg: `Runtime error (${matchedPattern.name}) — repairing ${projectFiles.length} file(s)...` });
305
+ let anyFixed = false;
306
+ for (const rel of projectFiles) {
307
+ const abs = path.join(projectDir, rel);
308
+ let original = '';
309
+ try { original = fs.readFileSync(abs, 'utf-8'); } catch { continue; }
310
+ if (!original) continue;
311
+
312
+ // Build a focused repair prompt — include the runtime error so the
313
+ // model knows exactly what to fix.
314
+ const errSnippet = stderrBuf.split('\n').slice(0, 30).join('\n');
315
+ const fixPrompt =
316
+ `A Node.js sandbox crashed with this runtime error:
317
+
318
+ ${errSnippet.slice(0, 1500)}
319
+
320
+ The failing file is: ${rel}
321
+
322
+ What to fix: ${matchedPattern.hint}
323
+
324
+ CRITICAL: Output ONLY the complete corrected file content. No commentary, no markdown fences. Keep all working logic intact — only change what's necessary to fix the error.
325
+
326
+ Current file content:
327
+ ${original.slice(0, 12_000)}`;
328
+
329
+ try {
330
+ let fixed = '';
331
+ await callLLMStream(loadConfig(), 'You are a precise code repair assistant. Output only the corrected file, no explanation.', fixPrompt, (c) => { fixed += c; }, { max_tokens: 16384 });
332
+ fixed = fixed.replace(/^```[\w]*\n/, '').replace(/\n```$/, '').trim();
333
+ if (fixed.length > 20 && fixed !== original) {
334
+ fs.writeFileSync(abs, fixed, 'utf-8');
335
+ emit({ type: 'status', msg: `Repaired ${rel} (${fixed.length} chars)` });
336
+ anyFixed = true;
337
+ }
338
+ } catch (e) {
339
+ emit({ type: 'warn', msg: `LLM repair of ${rel} failed: ${(e.message || '').slice(0, 200)}` });
340
+ }
341
+ }
342
+ if (anyFixed) {
343
+ emit({ type: 'status', msg: `Restarting sandbox (attempt ${_attempt + 1}/${MAX_RETRIES})...` });
344
+ return this.start(projectName, projectDir, emit, _attempt + 1);
345
+ }
346
+ }
347
+
348
+ // Special fallback for CJS/ESM mismatches: try flipping package.json "type"
349
+ if (matchedPattern.name.includes('CJS/ESM') || matchedPattern.name.includes('ESM/CJS')) {
350
+ const pkgPath = path.join(projectDir, 'package.json');
351
+ if (fs.existsSync(pkgPath)) {
352
+ try {
353
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
354
+ const isCjsError = /Cannot use import statement outside a module/i.test(stderrBuf);
355
+ if (isCjsError && pkg.type !== 'module') {
356
+ pkg.type = 'module';
357
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
358
+ emit({ type: 'status', msg: 'Added "type":"module" to package.json — retrying...' });
359
+ return this.start(projectName, projectDir, emit, _attempt + 1);
360
+ }
361
+ } catch { /* ignore */ }
362
+ }
363
+ }
364
+ }
365
+
271
366
  // Show the actual error from stderr — include full trace for debugging
272
367
  const stderrLines = stderrBuf.split('\n').filter(l => l.trim());
273
368
  const errLine = stderrLines.find((l) => l.includes('Error') || l.includes('error'));