nothumanallowed 15.1.20 → 15.1.22

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.20",
3
+ "version": "15.1.22",
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/cli.mjs CHANGED
@@ -521,7 +521,7 @@ function cmdConfig(args) {
521
521
  if (!key || !value) {
522
522
  fail('Usage: nha config set <key> <value>');
523
523
  console.log('');
524
- info('Keys: provider, key, openai-key, gemini-key, deepseek-key, grok-key, model, timeout');
524
+ info('Keys: provider, key, openai-key, gemini-key, deepseek-key, grok-key, groq-key (voice/Whisper), model, timeout');
525
525
  info(' verbose, immersive, deliberation, rounds, convergence, tribunal, knowledge');
526
526
  info(' google-client-id, google-client-secret');
527
527
  info(' microsoft-client-id, microsoft-client-secret, microsoft-tenant');
@@ -553,7 +553,10 @@ function cmdConfig(args) {
553
553
  if (config.llm.openaiKey) console.log(` OpenAI Key: ${G}${config.llm.openaiKey.slice(0, 12)}...${NC}`);
554
554
  if (config.llm.geminiKey) console.log(` Gemini Key: ${G}${config.llm.geminiKey.slice(0, 12)}...${NC}`);
555
555
  if (config.llm.deepseekKey) console.log(` DeepSeek Key: ${G}${config.llm.deepseekKey.slice(0, 12)}...${NC}`);
556
- if (config.llm.grokKey) console.log(` Grok Key: ${G}${config.llm.grokKey.slice(0, 12)}...${NC}`);
556
+ if (config.llm.grokKey) console.log(` Grok Key: ${G}${config.llm.grokKey.slice(0, 12)}...${NC} ${D}(X.AI Grok LLM)${NC}`);
557
+ // Groq is for voice transcription (Whisper). ALWAYS show so users can see
558
+ // whether it's configured — voice in Telegram needs this when NHA proxy is down.
559
+ console.log(` Groq Key: ${config.llm.groqKey ? G + config.llm.groqKey.slice(0, 12) + '...' : R + '(not set)'}${NC} ${D}(voice transcription, free at https://console.groq.com/keys)${NC}`);
557
560
  if (config.llm.model) console.log(` Model: ${W}${config.llm.model}${NC}`);
558
561
  console.log(` Timeout: ${D}${config.llm.timeout}ms${NC}`);
559
562
 
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.20';
8
+ export const VERSION = '15.1.22';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -291,37 +291,10 @@ class SandboxManager {
291
291
  if (matchedPattern && _attempt < MAX_RETRIES) {
292
292
  emit({ type: 'phase', phase: 'autofix', msg: `Runtime error detected: ${matchedPattern.name} — analyzing...` });
293
293
 
294
- // ── Special pre-fix for require/import mismatches ──
295
- // For "require is not defined" the project is ESM but uses CJS syntax.
296
- // Easiest fix: flip package.json — REMOVE "type":"module" so CJS works,
297
- // OR rewrite files. We try the package.json toggle FIRST (cheaper) only
298
- // when the failing files clearly use `require()`. For the inverse case
299
- // ("Cannot use import statement outside a module") we ADD "type":"module".
300
294
  const pkgPath = path.join(projectDir, 'package.json');
301
295
  const isRequireError = /require is not defined/i.test(stderrBuf);
302
296
  const isImportError = /Cannot use import statement outside a module/i.test(stderrBuf);
303
297
 
304
- if ((isRequireError || isImportError) && fs.existsSync(pkgPath)) {
305
- try {
306
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
307
- if (isImportError && pkg.type !== 'module') {
308
- pkg.type = 'module';
309
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
310
- emit({ type: 'status', msg: 'Auto-fix: added "type":"module" to package.json — retrying...' });
311
- return this.start(projectName, projectDir, emit, _attempt + 1);
312
- }
313
- if (isRequireError && pkg.type === 'module') {
314
- // Flip OFF "type":"module" so require() works again
315
- delete pkg.type;
316
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
317
- emit({ type: 'status', msg: 'Auto-fix: removed "type":"module" from package.json — retrying...' });
318
- return this.start(projectName, projectDir, emit, _attempt + 1);
319
- }
320
- } catch (e) {
321
- emit({ type: 'warn', msg: `package.json toggle failed: ${e.message.slice(0, 200)}` });
322
- }
323
- }
324
-
325
298
  // ── Extract file path from stack trace (multiple patterns) ──
326
299
  // Try several regex forms to be robust against various Node stack formats.
327
300
  const allPaths = new Set();
@@ -378,10 +351,89 @@ class SandboxManager {
378
351
  }
379
352
  }
380
353
 
354
+ // ── Deterministic fixes BEFORE LLM repair (faster, no token cost) ──
355
+ // The trick is to consider the file extension because it overrides
356
+ // package.json "type" in Node.
357
+ let deterministicFixApplied = false;
358
+ if ((isRequireError || isImportError) && projectFiles.length > 0) {
359
+ for (const rel of projectFiles) {
360
+ const ext = path.extname(rel).toLowerCase();
361
+ const abs = path.join(projectDir, rel);
362
+
363
+ // Case A: file is .mjs (forced ESM) using require() → rename to .cjs
364
+ // This is the FAST fix Node itself suggests in the error message.
365
+ if (isRequireError && ext === '.mjs') {
366
+ const newAbs = abs.replace(/\.mjs$/i, '.cjs');
367
+ try {
368
+ fs.renameSync(abs, newAbs);
369
+ // Update package.json "main" if it pointed to the old file
370
+ if (fs.existsSync(pkgPath)) {
371
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
372
+ if (pkg.main && pkg.main.endsWith(rel)) {
373
+ pkg.main = pkg.main.replace(/\.mjs$/i, '.cjs');
374
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
375
+ }
376
+ }
377
+ emit({ type: 'status', msg: `Auto-fix: renamed ${rel} → ${path.basename(newAbs)} (Node suggests this for CJS-in-.mjs)` });
378
+ deterministicFixApplied = true;
379
+ } catch (e) {
380
+ emit({ type: 'warn', msg: `Rename ${rel} failed: ${e.message.slice(0, 200)}` });
381
+ }
382
+ }
383
+ // Case B: file is .cjs (forced CJS) using import → rename to .mjs
384
+ else if (isImportError && ext === '.cjs') {
385
+ const newAbs = abs.replace(/\.cjs$/i, '.mjs');
386
+ try {
387
+ fs.renameSync(abs, newAbs);
388
+ if (fs.existsSync(pkgPath)) {
389
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
390
+ if (pkg.main && pkg.main.endsWith(rel)) {
391
+ pkg.main = pkg.main.replace(/\.cjs$/i, '.mjs');
392
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
393
+ }
394
+ }
395
+ emit({ type: 'status', msg: `Auto-fix: renamed ${rel} → ${path.basename(newAbs)} (Node suggests this for import-in-.cjs)` });
396
+ deterministicFixApplied = true;
397
+ } catch (e) {
398
+ emit({ type: 'warn', msg: `Rename ${rel} failed: ${e.message.slice(0, 200)}` });
399
+ }
400
+ }
401
+ }
402
+ }
403
+
404
+ // Case C: ambiguous .js files — toggle package.json "type"
405
+ // ONLY effective when files are .js (extension doesn't force a mode)
406
+ if (!deterministicFixApplied && (isRequireError || isImportError) && fs.existsSync(pkgPath)) {
407
+ const onlyJsFiles = projectFiles.every(p => path.extname(p).toLowerCase() === '.js');
408
+ if (onlyJsFiles) {
409
+ try {
410
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
411
+ if (isImportError && pkg.type !== 'module') {
412
+ pkg.type = 'module';
413
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
414
+ emit({ type: 'status', msg: 'Auto-fix: added "type":"module" to package.json (for .js with import)' });
415
+ deterministicFixApplied = true;
416
+ } else if (isRequireError && pkg.type === 'module') {
417
+ delete pkg.type;
418
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
419
+ emit({ type: 'status', msg: 'Auto-fix: removed "type":"module" from package.json (for .js with require)' });
420
+ deterministicFixApplied = true;
421
+ }
422
+ } catch (e) {
423
+ emit({ type: 'warn', msg: `package.json toggle failed: ${e.message.slice(0, 200)}` });
424
+ }
425
+ }
426
+ }
427
+
428
+ if (deterministicFixApplied) {
429
+ emit({ type: 'status', msg: `Auto-fix: restarting sandbox (attempt ${_attempt + 1}/${MAX_RETRIES})...` });
430
+ return this.start(projectName, projectDir, emit, _attempt + 1);
431
+ }
432
+
381
433
  if (projectFiles.length === 0) {
382
434
  emit({ type: 'warn', msg: `Auto-fix: could not identify a target file to repair. Stack trace shown above.` });
383
435
  } else {
384
- emit({ type: 'phase', phase: 'autofix', msg: `Auto-fix repairing ${projectFiles.length} file(s): ${projectFiles.join(', ')}` });
436
+ emit({ type: 'phase', phase: 'autofix', msg: `Auto-fix repairing ${projectFiles.length} file(s) with LLM: ${projectFiles.join(', ')}` });
385
437
  let anyFixed = false;
386
438
  for (const rel of projectFiles) {
387
439
  const abs = path.join(projectDir, rel);