nothumanallowed 16.0.45 → 16.0.46

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.45",
3
+ "version": "16.0.46",
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.45';
8
+ export const VERSION = '16.0.46';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -233,12 +233,24 @@ class SandboxManager {
233
233
  // Detects "incomplete styling" (LLM truncated CSS generation) and calls
234
234
  // the LLM automatically to extend the CSS file with rules for the missing
235
235
  // HTML selectors. NO user intervention required.
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).
236
238
  try {
237
239
  const projectName = path.basename(projectDir);
238
240
  const cfg = loadConfig();
239
- const styleResult = await _autoExtendStylesIfNeeded(projectName, cfg, emit, { minCoverage: 0.6 });
240
- if (styleResult.extended) {
241
- emit({ type: 'status', msg: `Auto-extended styles: ${styleResult.file} (${styleResult.missingBefore - styleResult.missingAfter} new selectors covered).` });
241
+ const maxPasses = 2;
242
+ let totalCovered = 0;
243
+ for (let pass = 1; pass <= maxPasses; pass++) {
244
+ const styleResult = await _autoExtendStylesIfNeeded(projectName, cfg, emit, { minCoverage: 0.85 });
245
+ if (!styleResult.extended) {
246
+ if (styleResult.reason === 'coverage acceptable') break;
247
+ // LLM failed or skipped — don't loop on a broken provider
248
+ break;
249
+ }
250
+ const newlyCovered = (styleResult.missingBefore || 0) - (styleResult.missingAfter || 0);
251
+ totalCovered += newlyCovered;
252
+ emit({ type: 'status', msg: `Pass ${pass}/${maxPasses}: ${styleResult.file} extended — ${newlyCovered} new selectors covered (total ${totalCovered}).` });
253
+ if ((styleResult.coverageAfter || 0) >= 0.85) break;
242
254
  }
243
255
  } catch (e) {
244
256
  emit({ type: 'warn', msg: `Auto-extend styles failed: ${(e.message || e).slice(0, 200)}` });
@@ -4254,27 +4266,57 @@ export async function _autoExtendStylesIfNeeded(projectName, config, emit, opts)
4254
4266
  } catch {}
4255
4267
  }
4256
4268
 
4257
- const sys = 'You are an expert frontend designer. Extend the existing CSS to cover ALL classes/ids found in the HTML, maintaining the existing design language (colors, gradients, typography, spacing). Add responsive mobile-first rules. Output ONLY the complete extended CSS file content — no markdown fences, no explanations.';
4269
+ const sys = `You are an expert frontend designer producing PRODUCTION-QUALITY CSS.
4270
+
4271
+ DESIGN REQUIREMENTS (NON-NEGOTIABLE):
4272
+ - WCAG AA contrast: text-on-background ratio >= 4.5:1. NO washed-out pastels for text. Body text must be near-black on light bg, or near-white on dark bg.
4273
+ - Use VIBRANT accent colors with sufficient saturation (HSL S >= 60%, L between 35-65% for accents).
4274
+ - Cover EVERY selector listed — including footer, header, nav, hero, sections, cards, buttons, forms, modals, tooltips.
4275
+ - Use modern CSS: flex/grid layouts, custom properties for colors, smooth transitions (200-300ms), subtle shadows.
4276
+
4277
+ OUTPUT: ONLY the complete extended CSS file content. No markdown fences, no explanations, no preamble. The output will be written directly to disk.`;
4258
4278
  const user =
4259
4279
  `Extend this CSS file: \`${targetRel}\`\n\n` +
4260
4280
  `Current CSS (${target.size} bytes, ${analysis.cssRuleCount} rules):\n\`\`\`css\n${target.content.slice(0, 6000)}\n\`\`\`\n\n` +
4261
- `Missing selectors (${analysis.missing.length}):\n${analysis.missing.slice(0, 50).join(', ')}\n\n` +
4281
+ `ALL missing selectors (${analysis.missing.length} — cover every single one):\n${analysis.missing.join(', ')}\n\n` +
4262
4282
  `HTML files for context:\n${htmlSample}\n\n` +
4263
- `Output the COMPLETE extended CSS file (existing rules + new rules for all missing selectors). Add:\n` +
4264
- `- img { max-width: 100%; height: auto; object-fit: cover; }\n` +
4265
- `- Layout for each missing class/id, coherent with the existing design language\n` +
4266
- `- Responsive breakpoints at 768px and 480px\n` +
4267
- `- Hover/transition states for interactive elements`;
4268
-
4269
- if (emit) emit({ type: 'status', msg: `CSS coverage ${(analysis.coverage * 100).toFixed(0)}% (${analysis.missing.length} selectors missing). Auto-extending ${targetRel} via LLM...` });
4270
-
4283
+ `Output the COMPLETE extended CSS file. Required additions:\n` +
4284
+ `- img { max-width: 100%; height: auto; object-fit: cover; display: block; }\n` +
4285
+ `- Footer, header, nav with proper layout and visible styling (NOT transparent backgrounds with low-contrast text)\n` +
4286
+ `- Rules for EVERY one of the ${analysis.missing.length} missing selectors above\n` +
4287
+ `- Responsive breakpoints at 1024px, 768px, 480px (mobile-first)\n` +
4288
+ `- Hover/focus/transition states for buttons, links, cards\n` +
4289
+ `- Color contrast must pass WCAG AA: text-on-bg >= 4.5:1`;
4290
+
4291
+ if (emit) emit({ type: 'status', msg: `CSS coverage ${(analysis.coverage * 100).toFixed(0)}% (${analysis.missing.length} selectors missing). Auto-extending ${targetRel} via LLM (timeout 60s)...` });
4292
+
4293
+ // Call LLM with timeout + progress heartbeat. Otherwise a slow/stuck Liara
4294
+ // leaves the user staring at "Auto-extending..." forever with no feedback.
4271
4295
  let body = '';
4296
+ let lastChunkAt = Date.now();
4297
+ const startedAt = Date.now();
4298
+ const timeoutMs = 60_000;
4299
+ const heartbeatInterval = setInterval(() => {
4300
+ if (!emit) return;
4301
+ const elapsed = ((Date.now() - startedAt) / 1000).toFixed(0);
4302
+ const sinceLast = ((Date.now() - lastChunkAt) / 1000).toFixed(0);
4303
+ emit({ type: 'status', msg: `LLM extend: ${elapsed}s elapsed, ${body.length} bytes received (${sinceLast}s since last chunk)` });
4304
+ }, 5_000);
4305
+
4272
4306
  try {
4273
- await callLLMStream(config, sys, user, (chunk) => { body += chunk; }, { max_tokens: 8192 });
4307
+ await Promise.race([
4308
+ callLLMStream(config, sys, user, (chunk) => {
4309
+ body += chunk;
4310
+ lastChunkAt = Date.now();
4311
+ }, { max_tokens: 8192 }),
4312
+ new Promise((_, reject) => setTimeout(() => reject(new Error('LLM timeout after ' + (timeoutMs / 1000) + 's')), timeoutMs)),
4313
+ ]);
4274
4314
  } catch (e) {
4275
- if (emit) emit({ type: 'warn', msg: `CSS extend failed: ${(e.message || e).slice(0, 200)}` });
4276
- return { extended: false, reason: 'llm_failed', error: e.message };
4315
+ clearInterval(heartbeatInterval);
4316
+ if (emit) emit({ type: 'warn', msg: `CSS extend failed: ${(e.message || e).slice(0, 200)}. Sandbox continues with current CSS — open chat to extend manually.` });
4317
+ return { extended: false, reason: 'llm_failed', error: e.message, partialBytes: body.length };
4277
4318
  }
4319
+ clearInterval(heartbeatInterval);
4278
4320
 
4279
4321
  // Strip markdown fences
4280
4322
  body = body.replace(/^```[a-zA-Z]*\n?/m, '').replace(/\n?```\s*$/m, '').trim();