nothumanallowed 16.0.53 → 16.0.55
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": "16.0.
|
|
3
|
+
"version": "16.0.55",
|
|
4
4
|
"description": "Local AI assistant: 80 tools (Gmail, Calendar, Drive, GitHub, Slack, browser, code, files), 38 agents, visual workflows (Studio, AWF, WebCraft). Install with `npm i -g nothumanallowed`, run with `nha ui`. Free tier built-in (Liara), no API key required. Your data stays on your PC — OAuth tokens local, no cloud. Open-source MIT.",
|
|
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 = '16.0.
|
|
8
|
+
export const VERSION = '16.0.55';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -794,12 +794,36 @@ ${original.slice(0, 12_000)}`;
|
|
|
794
794
|
let fixed = '';
|
|
795
795
|
await callLLMStream(loadConfig(), 'You are a precise code repair assistant. Output only the corrected file, no explanation.', fixPrompt, (c) => { fixed += c; }, { max_tokens: 16384 });
|
|
796
796
|
fixed = fixed.replace(/^```[\w]*\n/, '').replace(/\n```$/, '').trim();
|
|
797
|
-
|
|
797
|
+
|
|
798
|
+
// VALIDATION: prevent rollback hell. Reject the LLM output if:
|
|
799
|
+
// 1. Empty / too short (< 20 chars or < 30% of original)
|
|
800
|
+
// 2. Identical to original (no fix attempted)
|
|
801
|
+
// 3. Looks like LLM error response leaked
|
|
802
|
+
// 4. Syntax-checkable file (.js/.mjs) that doesn't parse — would be worse than original
|
|
803
|
+
const tooShort = fixed.length < 20 || fixed.length < original.length * 0.3;
|
|
804
|
+
const isErrorLeak = _looksLikeLLMError(fixed);
|
|
805
|
+
let syntaxBroken = false;
|
|
806
|
+
if (!tooShort && !isErrorLeak && (rel.endsWith('.js') || rel.endsWith('.mjs') || rel.endsWith('.cjs'))) {
|
|
807
|
+
try { new Function(fixed); } catch (synErr) {
|
|
808
|
+
// Try with sourceType:module via acorn before declaring broken
|
|
809
|
+
try { acorn.parse(fixed, { ecmaVersion: 'latest', sourceType: 'module', allowReturnOutsideFunction: true }); }
|
|
810
|
+
catch { syntaxBroken = true; }
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
if (tooShort || isErrorLeak || syntaxBroken || fixed === original) {
|
|
814
|
+
// Backup the LLM attempt for debugging, but DON'T overwrite the file
|
|
815
|
+
try { fs.writeFileSync(abs + '.llm-rejected-' + Date.now(), fixed, 'utf-8'); } catch {}
|
|
816
|
+
const reason = tooShort ? `output too short (${fixed.length} vs ${original.length} chars)`
|
|
817
|
+
: isErrorLeak ? 'output looks like an LLM/provider error response'
|
|
818
|
+
: syntaxBroken ? 'output has worse syntax errors than input'
|
|
819
|
+
: 'no change';
|
|
820
|
+
emit({ type: 'warn', msg: `Auto-fix REJECTED for ${rel}: ${reason}. Original file preserved.` });
|
|
821
|
+
} else {
|
|
822
|
+
// Backup original before overwriting
|
|
823
|
+
try { fs.writeFileSync(abs + '.before-autofix-' + Date.now(), original, 'utf-8'); } catch {}
|
|
798
824
|
fs.writeFileSync(abs, fixed, 'utf-8');
|
|
799
|
-
emit({ type: 'status', msg: `Auto-fix: ✓ repaired ${rel} (${fixed.length} chars)` });
|
|
825
|
+
emit({ type: 'status', msg: `Auto-fix: ✓ repaired ${rel} (${original.length} → ${fixed.length} chars)` });
|
|
800
826
|
anyFixed = true;
|
|
801
|
-
} else {
|
|
802
|
-
emit({ type: 'warn', msg: `Auto-fix: LLM returned no useful change for ${rel}` });
|
|
803
827
|
}
|
|
804
828
|
} catch (e) {
|
|
805
829
|
emit({ type: 'warn', msg: `Auto-fix: LLM repair of ${rel} failed — ${(e.message || '').slice(0, 200)}` });
|
|
@@ -4336,43 +4360,58 @@ OUTPUT: ONLY the complete extended CSS file content. No markdown fences, no expl
|
|
|
4336
4360
|
const model = config?.llm?.model || config?.llm?.[provider]?.model || 'default';
|
|
4337
4361
|
if (emit) emit({ type: 'status', msg: `CSS coverage ${(analysis.coverage * 100).toFixed(0)}% (${analysis.missing.length} selectors missing). Auto-extending ${targetRel} via ${provider}:${model} (timeout 60s)...` });
|
|
4338
4362
|
|
|
4339
|
-
//
|
|
4340
|
-
//
|
|
4341
|
-
//
|
|
4342
|
-
//
|
|
4343
|
-
// Liara responsive.
|
|
4363
|
+
// Smart timeout: timeout ONLY if no bytes received for N seconds (provider
|
|
4364
|
+
// stuck/dead), NOT if total elapsed exceeds N (the LLM might be legitimately
|
|
4365
|
+
// streaming a large CSS file at 250 b/s for 90+ seconds). Absolute hard cap
|
|
4366
|
+
// at 300s to prevent runaway.
|
|
4344
4367
|
let body = '';
|
|
4345
4368
|
let lastChunkAt = Date.now();
|
|
4346
4369
|
const startedAt = Date.now();
|
|
4347
|
-
const
|
|
4370
|
+
const noProgressTimeoutMs = 30_000; // no bytes for 30s → timeout
|
|
4371
|
+
const absoluteTimeoutMs = 300_000; // 5min absolute cap
|
|
4348
4372
|
let earlyWarningEmitted = false;
|
|
4373
|
+
let timedOut = false;
|
|
4374
|
+
let aborted = false;
|
|
4375
|
+
const abortController = new AbortController();
|
|
4376
|
+
|
|
4349
4377
|
const heartbeatInterval = setInterval(() => {
|
|
4350
4378
|
if (!emit) return;
|
|
4351
4379
|
const elapsed = ((Date.now() - startedAt) / 1000).toFixed(0);
|
|
4352
4380
|
const sinceLast = ((Date.now() - lastChunkAt) / 1000).toFixed(0);
|
|
4353
4381
|
emit({ type: 'status', msg: `LLM extend: ${elapsed}s elapsed, ${body.length} bytes received (${sinceLast}s since last chunk)` });
|
|
4354
|
-
// Early warning if no bytes at all after 15s — provider is likely stuck or rate-limited
|
|
4355
4382
|
if (!earlyWarningEmitted && body.length === 0 && Date.now() - startedAt > 15_000) {
|
|
4356
4383
|
earlyWarningEmitted = true;
|
|
4357
|
-
emit({ type: 'warn', msg: `Provider ${provider} hasn't sent any data in 15s. If this is Liara, the free tier may be under load — try switching to Anthropic/OpenAI in Settings
|
|
4384
|
+
emit({ type: 'warn', msg: `Provider ${provider} hasn't sent any data in 15s. If this is Liara, the free tier may be under load — try switching to Anthropic/OpenAI in Settings.` });
|
|
4385
|
+
}
|
|
4386
|
+
// No-progress timeout: only if STUCK (zero chunks for 30s)
|
|
4387
|
+
if (Date.now() - lastChunkAt > noProgressTimeoutMs && body.length > 0) {
|
|
4388
|
+
timedOut = true;
|
|
4389
|
+
aborted = true;
|
|
4390
|
+
abortController.abort();
|
|
4391
|
+
}
|
|
4392
|
+
// Absolute timeout
|
|
4393
|
+
if (Date.now() - startedAt > absoluteTimeoutMs) {
|
|
4394
|
+
timedOut = true;
|
|
4395
|
+
aborted = true;
|
|
4396
|
+
abortController.abort();
|
|
4358
4397
|
}
|
|
4359
4398
|
}, 5_000);
|
|
4360
4399
|
|
|
4361
4400
|
try {
|
|
4362
|
-
await
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error('LLM timeout after ' + (timeoutMs / 1000) + 's — provider ' + provider + ' did not respond')), timeoutMs)),
|
|
4368
|
-
]);
|
|
4401
|
+
await callLLMStream(config, sys, user, (chunk) => {
|
|
4402
|
+
if (aborted) return;
|
|
4403
|
+
body += chunk;
|
|
4404
|
+
lastChunkAt = Date.now();
|
|
4405
|
+
}, { max_tokens: 4096, signal: abortController.signal });
|
|
4369
4406
|
} catch (e) {
|
|
4370
4407
|
clearInterval(heartbeatInterval);
|
|
4371
|
-
const errMsg =
|
|
4408
|
+
const errMsg = timedOut
|
|
4409
|
+
? `no chunks received for ${(noProgressTimeoutMs / 1000)}s — provider ${provider} appears stuck (received ${body.length} bytes before stalling)`
|
|
4410
|
+
: (e.message || String(e)).slice(0, 200);
|
|
4372
4411
|
if (emit) {
|
|
4373
4412
|
emit({ type: 'warn', msg: `CSS extend failed: ${errMsg}` });
|
|
4374
|
-
if (
|
|
4375
|
-
emit({ type: 'warn', msg: `
|
|
4413
|
+
if (timedOut && body.length > 0) {
|
|
4414
|
+
emit({ type: 'warn', msg: `Got ${body.length} bytes of partial CSS but provider stalled. Keeping current file unchanged. Try again or switch provider.` });
|
|
4376
4415
|
}
|
|
4377
4416
|
}
|
|
4378
4417
|
return { extended: false, reason: 'llm_failed', error: errMsg, partialBytes: body.length };
|