nothumanallowed 16.0.46 → 16.0.48
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 +67 -42
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.48",
|
|
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.48';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -229,28 +229,42 @@ class SandboxManager {
|
|
|
229
229
|
}
|
|
230
230
|
} catch {}
|
|
231
231
|
|
|
232
|
-
// Pre-flight: auto-extend CSS
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
// Iterates up to 2 times to handle large projects where a single extend
|
|
237
|
-
// might not cover all selectors (e.g. 200+ missing selectors).
|
|
232
|
+
// Pre-flight: auto-extend CSS until 100% coverage (or LLM stops making
|
|
233
|
+
// progress). Target = 100%; max 5 passes as safety; early-exit if two
|
|
234
|
+
// consecutive passes don't reduce missing count (LLM stuck) or LLM fails.
|
|
235
|
+
// Goal: ZERO uncovered selectors when the LLM is capable of producing them.
|
|
238
236
|
try {
|
|
239
237
|
const projectName = path.basename(projectDir);
|
|
240
238
|
const cfg = loadConfig();
|
|
241
|
-
const maxPasses =
|
|
239
|
+
const maxPasses = 5;
|
|
242
240
|
let totalCovered = 0;
|
|
241
|
+
let prevMissing = Infinity;
|
|
242
|
+
let stuckPasses = 0;
|
|
243
243
|
for (let pass = 1; pass <= maxPasses; pass++) {
|
|
244
|
-
const styleResult = await _autoExtendStylesIfNeeded(projectName, cfg, emit, { minCoverage: 0
|
|
244
|
+
const styleResult = await _autoExtendStylesIfNeeded(projectName, cfg, emit, { minCoverage: 1.0 });
|
|
245
245
|
if (!styleResult.extended) {
|
|
246
|
-
if (styleResult.reason === 'coverage acceptable') break;
|
|
247
|
-
// LLM failed or skipped —
|
|
246
|
+
if (styleResult.reason === 'coverage acceptable') break; // already 100%
|
|
247
|
+
// LLM failed or skipped — stop loop
|
|
248
248
|
break;
|
|
249
249
|
}
|
|
250
250
|
const newlyCovered = (styleResult.missingBefore || 0) - (styleResult.missingAfter || 0);
|
|
251
251
|
totalCovered += newlyCovered;
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
const missingNow = styleResult.missingAfter || 0;
|
|
253
|
+
emit({ type: 'status', msg: `Pass ${pass}/${maxPasses}: ${styleResult.file} extended — ${newlyCovered} new selectors covered (${missingNow} still missing, ${((styleResult.coverageAfter || 0) * 100).toFixed(0)}% coverage).` });
|
|
254
|
+
if (missingNow === 0) {
|
|
255
|
+
emit({ type: 'status', msg: `100% CSS coverage reached after ${pass} pass${pass === 1 ? '' : 'es'}. Total ${totalCovered} selectors covered.` });
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
if (missingNow >= prevMissing) {
|
|
259
|
+
stuckPasses++;
|
|
260
|
+
if (stuckPasses >= 2) {
|
|
261
|
+
emit({ type: 'warn', msg: `LLM stopped making progress on extension (${missingNow} selectors still missing — likely pseudo-classes or JS-state classes the model can't infer). Stopping at ${((styleResult.coverageAfter || 0) * 100).toFixed(0)}%.` });
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
stuckPasses = 0;
|
|
266
|
+
}
|
|
267
|
+
prevMissing = missingNow;
|
|
254
268
|
}
|
|
255
269
|
} catch (e) {
|
|
256
270
|
emit({ type: 'warn', msg: `Auto-extend styles failed: ${(e.message || e).slice(0, 200)}` });
|
|
@@ -3132,48 +3146,59 @@ export function register(router) {
|
|
|
3132
3146
|
}
|
|
3133
3147
|
|
|
3134
3148
|
router.post('/api/studio/webcraft/lint', async (req, res) => {
|
|
3149
|
+
// ROBUST lint endpoint — NEVER returns 500. If any linter crashes,
|
|
3150
|
+
// returns 200 with empty diagnostics + the error logged. A failed lint
|
|
3151
|
+
// must not break the IDE streaming flow.
|
|
3135
3152
|
try {
|
|
3136
3153
|
const { projectName, path: relPath } = await parseBody(req);
|
|
3137
3154
|
if (!projectName || !relPath) return sendError(res, 400, 'projectName and path required');
|
|
3138
|
-
|
|
3139
|
-
|
|
3155
|
+
let content;
|
|
3156
|
+
try { content = ProjectStore.readFile(projectName, relPath); }
|
|
3157
|
+
catch { content = null; }
|
|
3158
|
+
if (content === null || content === undefined) return sendJSON(res, 200, { diagnostics: [] });
|
|
3140
3159
|
|
|
3141
3160
|
const ext = (relPath.split('.').pop() || '').toLowerCase();
|
|
3142
3161
|
let diagnostics = [];
|
|
3143
3162
|
|
|
3144
|
-
//
|
|
3163
|
+
// Each linter wrapped individually — a crash in one doesn't kill the others
|
|
3145
3164
|
if (['js', 'mjs', 'jsx', 'cjs'].includes(ext)) {
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
try { JSON.parse(content); } catch (e) {
|
|
3154
|
-
const posMatch = e.message.match(/position (\d+)/i);
|
|
3155
|
-
const pos = posMatch ? parseInt(posMatch[1]) : 0;
|
|
3156
|
-
const before = content.slice(0, pos).split('\n');
|
|
3157
|
-
diagnostics.push({
|
|
3158
|
-
from: { line: before.length, col: (before[before.length - 1] || '').length },
|
|
3159
|
-
severity: 'error',
|
|
3160
|
-
message: e.message,
|
|
3161
|
-
});
|
|
3165
|
+
try {
|
|
3166
|
+
const projectDir = ProjectStore.dir(projectName);
|
|
3167
|
+
const tsDiags = await lintJSWithTypeScript(projectDir, relPath).catch(() => null);
|
|
3168
|
+
diagnostics = tsDiags || lintJS(content, relPath, projectName) || [];
|
|
3169
|
+
} catch (e) {
|
|
3170
|
+
console.error('[lint] JS linter crashed for', relPath, ':', e.message);
|
|
3171
|
+
diagnostics = [];
|
|
3162
3172
|
}
|
|
3163
|
-
}
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
+
} else if (ext === 'json') {
|
|
3174
|
+
try {
|
|
3175
|
+
JSON.parse(content);
|
|
3176
|
+
} catch (e) {
|
|
3177
|
+
try {
|
|
3178
|
+
const posMatch = e.message.match(/position (\d+)/i);
|
|
3179
|
+
const pos = posMatch ? parseInt(posMatch[1]) : 0;
|
|
3180
|
+
const before = content.slice(0, pos).split('\n');
|
|
3181
|
+
diagnostics.push({
|
|
3182
|
+
from: { line: before.length, col: (before[before.length - 1] || '').length },
|
|
3183
|
+
severity: 'error',
|
|
3184
|
+
message: e.message,
|
|
3185
|
+
});
|
|
3186
|
+
} catch {}
|
|
3187
|
+
}
|
|
3188
|
+
} else if (ext === 'css') {
|
|
3189
|
+
try { diagnostics = lintCSS(content) || []; }
|
|
3190
|
+
catch (e) { console.error('[lint] CSS linter crashed:', e.message); diagnostics = []; }
|
|
3191
|
+
} else if (ext === 'html' || ext === 'htm') {
|
|
3192
|
+
try { diagnostics = lintHTML(content, relPath, projectName) || []; }
|
|
3193
|
+
catch (e) { console.error('[lint] HTML linter crashed:', e.message); diagnostics = []; }
|
|
3173
3194
|
}
|
|
3174
3195
|
|
|
3175
3196
|
sendJSON(res, 200, { diagnostics });
|
|
3176
|
-
} catch (e) {
|
|
3197
|
+
} catch (e) {
|
|
3198
|
+
// Even the outer catch returns 200 — lint failures must not break the IDE
|
|
3199
|
+
console.error('[lint] outer error:', e.message);
|
|
3200
|
+
sendJSON(res, 200, { diagnostics: [], error: e.message });
|
|
3201
|
+
}
|
|
3177
3202
|
});
|
|
3178
3203
|
|
|
3179
3204
|
// ── File write (from IDE editor) ──────────────────────────────────────────
|