nothumanallowed 15.1.19 → 15.1.20
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 +1 -1
- package/src/constants.mjs +1 -1
- package/src/server/routes/webcraft.mjs +97 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "15.1.
|
|
3
|
+
"version": "15.1.20",
|
|
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.
|
|
8
|
+
export const VERSION = '15.1.20';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -289,19 +289,99 @@ class SandboxManager {
|
|
|
289
289
|
|
|
290
290
|
const matchedPattern = runtimePatterns.find(p => p.re.test(stderrBuf));
|
|
291
291
|
if (matchedPattern && _attempt < MAX_RETRIES) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
292
|
+
emit({ type: 'phase', phase: 'autofix', msg: `Runtime error detected: ${matchedPattern.name} — analyzing...` });
|
|
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
|
+
const pkgPath = path.join(projectDir, 'package.json');
|
|
301
|
+
const isRequireError = /require is not defined/i.test(stderrBuf);
|
|
302
|
+
const isImportError = /Cannot use import statement outside a module/i.test(stderrBuf);
|
|
303
|
+
|
|
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
|
+
// ── Extract file path from stack trace (multiple patterns) ──
|
|
326
|
+
// Try several regex forms to be robust against various Node stack formats.
|
|
327
|
+
const allPaths = new Set();
|
|
328
|
+
// Form A: "at /abs/path/file.js:N:M" or "at file:///abs/path/file.js:N:M"
|
|
329
|
+
for (const m of stderrBuf.matchAll(/(?:file:\/\/)?(\/[^\s:()'"]+\.(?:m?js|cjs|jsx?|tsx?)):\d+(?::\d+)?/g)) {
|
|
330
|
+
allPaths.add(m[1]);
|
|
331
|
+
}
|
|
332
|
+
// Form B: ESM error header "file:///path/file.js:N"
|
|
333
|
+
for (const m of stderrBuf.matchAll(/file:\/\/(\/[^\s:'"]+\.(?:m?js|cjs|jsx?|tsx?)):?\d*/g)) {
|
|
334
|
+
allPaths.add(m[1]);
|
|
335
|
+
}
|
|
336
|
+
// Form C: bare absolute path at start of line (Node prints this for CJS syntax)
|
|
337
|
+
for (const m of stderrBuf.matchAll(/^(\/[^\s:'"]+\.(?:m?js|cjs|jsx?|tsx?))(?::\d+)?$/gm)) {
|
|
338
|
+
allPaths.add(m[1]);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// First filter: paths that look like they live in this project
|
|
342
|
+
let projectFiles = [...allPaths]
|
|
343
|
+
.filter(p => p.startsWith(projectDir) || p.includes('/' + path.basename(projectDir) + '/'))
|
|
344
|
+
.map(p => p.startsWith(projectDir) ? path.relative(projectDir, p) : null)
|
|
345
|
+
.filter(Boolean)
|
|
300
346
|
.filter((v, i, a) => a.indexOf(v) === i)
|
|
301
|
-
.slice(0,
|
|
347
|
+
.slice(0, 5);
|
|
348
|
+
|
|
349
|
+
// FALLBACK: if no stack-trace files matched, scan the project directory
|
|
350
|
+
// for all .js / .mjs / .cjs files (excluding node_modules) and pick the
|
|
351
|
+
// ones that contain `require(` or `import` — those are the candidates.
|
|
352
|
+
if (projectFiles.length === 0) {
|
|
353
|
+
emit({ type: 'status', msg: `Stack trace did not reveal a file in project — scanning project files...` });
|
|
354
|
+
try {
|
|
355
|
+
const _walk = (dir, out = []) => {
|
|
356
|
+
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
357
|
+
if (ent.name === 'node_modules' || ent.name.startsWith('.')) continue;
|
|
358
|
+
const abs = path.join(dir, ent.name);
|
|
359
|
+
if (ent.isDirectory()) _walk(abs, out);
|
|
360
|
+
else if (/\.(m?js|cjs)$/.test(ent.name)) out.push(abs);
|
|
361
|
+
}
|
|
362
|
+
return out;
|
|
363
|
+
};
|
|
364
|
+
const allJs = _walk(projectDir);
|
|
365
|
+
// Heuristic — pick files matching the error semantics
|
|
366
|
+
const triggers = isRequireError
|
|
367
|
+
? /\brequire\s*\(/
|
|
368
|
+
: isImportError ? /^\s*import\s+/m
|
|
369
|
+
: /\brequire\s*\(|^\s*import\s+/m;
|
|
370
|
+
const candidates = allJs
|
|
371
|
+
.filter(abs => {
|
|
372
|
+
try { return triggers.test(fs.readFileSync(abs, 'utf-8')); } catch { return false; }
|
|
373
|
+
})
|
|
374
|
+
.slice(0, 3);
|
|
375
|
+
projectFiles = candidates.map(abs => path.relative(projectDir, abs));
|
|
376
|
+
} catch (e) {
|
|
377
|
+
emit({ type: 'warn', msg: `Project scan failed: ${e.message.slice(0, 200)}` });
|
|
378
|
+
}
|
|
379
|
+
}
|
|
302
380
|
|
|
303
|
-
if (projectFiles.length
|
|
304
|
-
emit({ type: '
|
|
381
|
+
if (projectFiles.length === 0) {
|
|
382
|
+
emit({ type: 'warn', msg: `Auto-fix: could not identify a target file to repair. Stack trace shown above.` });
|
|
383
|
+
} else {
|
|
384
|
+
emit({ type: 'phase', phase: 'autofix', msg: `Auto-fix repairing ${projectFiles.length} file(s): ${projectFiles.join(', ')}` });
|
|
305
385
|
let anyFixed = false;
|
|
306
386
|
for (const rel of projectFiles) {
|
|
307
387
|
const abs = path.join(projectDir, rel);
|
|
@@ -309,8 +389,6 @@ class SandboxManager {
|
|
|
309
389
|
try { original = fs.readFileSync(abs, 'utf-8'); } catch { continue; }
|
|
310
390
|
if (!original) continue;
|
|
311
391
|
|
|
312
|
-
// Build a focused repair prompt — include the runtime error so the
|
|
313
|
-
// model knows exactly what to fix.
|
|
314
392
|
const errSnippet = stderrBuf.split('\n').slice(0, 30).join('\n');
|
|
315
393
|
const fixPrompt =
|
|
316
394
|
`A Node.js sandbox crashed with this runtime error:
|
|
@@ -327,40 +405,26 @@ Current file content:
|
|
|
327
405
|
${original.slice(0, 12_000)}`;
|
|
328
406
|
|
|
329
407
|
try {
|
|
408
|
+
emit({ type: 'status', msg: `Auto-fix: rewriting ${rel}...` });
|
|
330
409
|
let fixed = '';
|
|
331
410
|
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
411
|
fixed = fixed.replace(/^```[\w]*\n/, '').replace(/\n```$/, '').trim();
|
|
333
412
|
if (fixed.length > 20 && fixed !== original) {
|
|
334
413
|
fs.writeFileSync(abs, fixed, 'utf-8');
|
|
335
|
-
emit({ type: 'status', msg: `
|
|
414
|
+
emit({ type: 'status', msg: `Auto-fix: ✓ repaired ${rel} (${fixed.length} chars)` });
|
|
336
415
|
anyFixed = true;
|
|
416
|
+
} else {
|
|
417
|
+
emit({ type: 'warn', msg: `Auto-fix: LLM returned no useful change for ${rel}` });
|
|
337
418
|
}
|
|
338
419
|
} catch (e) {
|
|
339
|
-
emit({ type: 'warn', msg: `LLM repair of ${rel} failed
|
|
420
|
+
emit({ type: 'warn', msg: `Auto-fix: LLM repair of ${rel} failed — ${(e.message || '').slice(0, 200)}` });
|
|
340
421
|
}
|
|
341
422
|
}
|
|
342
423
|
if (anyFixed) {
|
|
343
|
-
emit({ type: 'status', msg: `
|
|
424
|
+
emit({ type: 'status', msg: `Auto-fix: restarting sandbox (attempt ${_attempt + 1}/${MAX_RETRIES})...` });
|
|
344
425
|
return this.start(projectName, projectDir, emit, _attempt + 1);
|
|
345
426
|
}
|
|
346
427
|
}
|
|
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
428
|
}
|
|
365
429
|
|
|
366
430
|
// Show the actual error from stderr — include full trace for debugging
|