nothumanallowed 14.5.1 → 14.5.3
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 +82 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "14.5.
|
|
3
|
+
"version": "14.5.3",
|
|
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 = '14.5.
|
|
8
|
+
export const VERSION = '14.5.3';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -1624,6 +1624,56 @@ Continue from here:`;
|
|
|
1624
1624
|
}
|
|
1625
1625
|
}
|
|
1626
1626
|
|
|
1627
|
+
// ── Cross-reference check: verify HTML src/href point to existing files ────
|
|
1628
|
+
if (!abortSignal?.aborted) {
|
|
1629
|
+
const allFileNames = new Set(generatedFiles.map((f) => f.name));
|
|
1630
|
+
let refsFixed = 0;
|
|
1631
|
+
for (const f of generatedFiles) {
|
|
1632
|
+
if (!f.name.endsWith('.html')) continue;
|
|
1633
|
+
let modified = false;
|
|
1634
|
+
let html = f.content;
|
|
1635
|
+
|
|
1636
|
+
// Find all src="..." and href="..." references to local files
|
|
1637
|
+
const refRegex = /(?:src|href)=["']([^"']*?\.(?:js|css|mjs))["']/gi;
|
|
1638
|
+
let match;
|
|
1639
|
+
while ((match = refRegex.exec(html)) !== null) {
|
|
1640
|
+
const ref = match[1];
|
|
1641
|
+
if (ref.startsWith('http') || ref.startsWith('//') || ref.startsWith('data:')) continue;
|
|
1642
|
+
|
|
1643
|
+
// Resolve relative path from HTML file location
|
|
1644
|
+
const htmlDir = path.dirname(f.name);
|
|
1645
|
+
const refPath = ref.startsWith('/') ? ref.slice(1) : path.join(htmlDir, ref).replace(/\\/g, '/');
|
|
1646
|
+
const publicRef = refPath.startsWith('public/') ? refPath : `public/${refPath}`;
|
|
1647
|
+
|
|
1648
|
+
// Check if file exists in generated files
|
|
1649
|
+
if (!allFileNames.has(refPath) && !allFileNames.has(publicRef) && !allFileNames.has(ref)) {
|
|
1650
|
+
// Try to find the actual file by name
|
|
1651
|
+
const baseName = path.basename(ref);
|
|
1652
|
+
const actualFile = generatedFiles.find((g) => g.name.endsWith('/' + baseName) || g.name === baseName);
|
|
1653
|
+
if (actualFile) {
|
|
1654
|
+
// Fix the reference
|
|
1655
|
+
const correctRef = actualFile.name.startsWith('public/') ? actualFile.name.slice(7) : actualFile.name;
|
|
1656
|
+
html = html.replace(match[0], match[0].replace(ref, correctRef));
|
|
1657
|
+
modified = true;
|
|
1658
|
+
refsFixed++;
|
|
1659
|
+
emit({ type: 'status', msg: `Fixed reference: ${ref} → ${correctRef} in ${f.name}` });
|
|
1660
|
+
} else {
|
|
1661
|
+
emit({ type: 'status', msg: `Warning: ${f.name} references missing file: ${ref}` });
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
if (modified) {
|
|
1667
|
+
f.content = html;
|
|
1668
|
+
const abs = path.join(projectDir, f.name);
|
|
1669
|
+
fs.writeFileSync(abs, html, 'utf-8');
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
if (refsFixed > 0) {
|
|
1673
|
+
emit({ type: 'status', msg: `Auto-fixed ${refsFixed} broken file reference(s)` });
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1627
1677
|
// Save project metadata
|
|
1628
1678
|
const meta = {
|
|
1629
1679
|
description,
|
|
@@ -1894,6 +1944,28 @@ export function register(router) {
|
|
|
1894
1944
|
message: 'Missing </html> closing tag',
|
|
1895
1945
|
});
|
|
1896
1946
|
}
|
|
1947
|
+
// Check references to local files
|
|
1948
|
+
const refRegex = /(?:src|href)=["']([^"']*?\.(?:js|css|mjs))["']/gi;
|
|
1949
|
+
let refMatch;
|
|
1950
|
+
const lines = content.split('\n');
|
|
1951
|
+
while ((refMatch = refRegex.exec(content)) !== null) {
|
|
1952
|
+
const ref = refMatch[1];
|
|
1953
|
+
if (ref.startsWith('http') || ref.startsWith('//') || ref.startsWith('data:')) continue;
|
|
1954
|
+
const htmlDir = path.dirname(relPath);
|
|
1955
|
+
const refPath = ref.startsWith('/') ? ref.slice(1) : path.join(htmlDir, ref).replace(/\\/g, '/');
|
|
1956
|
+
const publicRef = refPath.startsWith('public/') ? refPath : `public/${refPath}`;
|
|
1957
|
+
const fileExists = ProjectStore.readFile(projectName, refPath) !== null
|
|
1958
|
+
|| ProjectStore.readFile(projectName, publicRef) !== null
|
|
1959
|
+
|| ProjectStore.readFile(projectName, ref) !== null;
|
|
1960
|
+
if (!fileExists) {
|
|
1961
|
+
const lineNum = content.slice(0, refMatch.index).split('\n').length;
|
|
1962
|
+
diagnostics.push({
|
|
1963
|
+
from: { line: lineNum, col: 0 },
|
|
1964
|
+
severity: 'error',
|
|
1965
|
+
message: `Referenced file not found: ${ref}`,
|
|
1966
|
+
});
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1897
1969
|
}
|
|
1898
1970
|
|
|
1899
1971
|
sendJSON(res, 200, { diagnostics });
|
|
@@ -2105,13 +2177,17 @@ function _patchEntry(projectDir, entryFile, shimDir, port) {
|
|
|
2105
2177
|
`const _nhaErrScript = require('fs').readFileSync('${path.join(shimDir, 'error-reporter.html').replace(/\\/g, '/')}', 'utf-8');`,
|
|
2106
2178
|
`const _origWrite = require('http').ServerResponse.prototype.write;`,
|
|
2107
2179
|
`const _origEnd = require('http').ServerResponse.prototype.end;`,
|
|
2108
|
-
`function _inject(chunk) {`,
|
|
2109
|
-
` if (typeof chunk === 'string' && chunk.includes('</head>')) return chunk.replace('</head>', _nhaErrScript + '</head>');`,
|
|
2110
|
-
` if (Buffer.isBuffer(chunk)) { var s = chunk.toString(); if (s.includes('</head>')) return Buffer.from(s.replace('</head>', _nhaErrScript + '</head>')); }`,
|
|
2111
|
-
` return chunk;`,
|
|
2112
|
-
`}`,
|
|
2113
2180
|
`require('http').ServerResponse.prototype.end = function(chunk, enc, cb) {`,
|
|
2114
|
-
`
|
|
2181
|
+
` try {`,
|
|
2182
|
+
` if (chunk && this.getHeader && (this.getHeader('content-type')||'').includes('html')) {`,
|
|
2183
|
+
` var s = typeof chunk === 'string' ? chunk : Buffer.isBuffer(chunk) ? chunk.toString() : null;`,
|
|
2184
|
+
` if (s && s.includes('</head>')) {`,
|
|
2185
|
+
` var patched = s.replace('</head>', _nhaErrScript + '</head>');`,
|
|
2186
|
+
` try { this.removeHeader('content-length'); } catch(e) {}`,
|
|
2187
|
+
` return _origEnd.call(this, patched, enc, cb);`,
|
|
2188
|
+
` }`,
|
|
2189
|
+
` }`,
|
|
2190
|
+
` } catch(e) {}`,
|
|
2115
2191
|
` return _origEnd.apply(this, arguments);`,
|
|
2116
2192
|
`};`,
|
|
2117
2193
|
`require('${entryAbs}');`,
|