nothumanallowed 14.4.23 → 14.5.0

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": "14.4.23",
3
+ "version": "14.5.0",
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.4.23';
8
+ export const VERSION = '14.5.0';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -1939,6 +1939,36 @@ export function register(router) {
1939
1939
  sendJSON(res, 200, sandbox.status());
1940
1940
  });
1941
1941
 
1942
+ // ── Sandbox runtime errors (reported by injected script in iframe) ────────
1943
+ const sandboxErrors = [];
1944
+ router.post('/api/studio/webcraft/sandbox/errors', async (req, res) => {
1945
+ try {
1946
+ const body = await parseBody(req);
1947
+ if (body.error) {
1948
+ sandboxErrors.push({
1949
+ ts: new Date().toISOString(),
1950
+ message: String(body.error).slice(0, 500),
1951
+ source: String(body.source || '').slice(0, 200),
1952
+ line: body.line || 0,
1953
+ col: body.col || 0,
1954
+ stack: String(body.stack || '').slice(0, 1000),
1955
+ });
1956
+ // Keep only last 20 errors
1957
+ if (sandboxErrors.length > 20) sandboxErrors.splice(0, sandboxErrors.length - 20);
1958
+ }
1959
+ sendJSON(res, 200, { ok: true });
1960
+ } catch { sendJSON(res, 200, { ok: true }); }
1961
+ });
1962
+
1963
+ router.get('/api/studio/webcraft/sandbox/errors', (_req, res) => {
1964
+ sendJSON(res, 200, { errors: sandboxErrors.slice(-10) });
1965
+ });
1966
+
1967
+ router.delete('/api/studio/webcraft/sandbox/errors', (_req, res) => {
1968
+ sandboxErrors.length = 0;
1969
+ sendJSON(res, 200, { ok: true });
1970
+ });
1971
+
1942
1972
  // ── WebCraft Agent chat — SSE ─────────────────────────────────────────────
1943
1973
  router.post('/api/studio/webcraft/agent', async (req, res) => {
1944
1974
  const body = await parseBody(req, 10_485_760);
@@ -2053,16 +2083,37 @@ function _detectEntry(dir) {
2053
2083
  }
2054
2084
 
2055
2085
  function _patchEntry(projectDir, entryFile, shimDir, port) {
2056
- // Write a launcher that injects shims and then requires the actual entry
2057
2086
  const launcherPath = path.join(projectDir, '.nha-launcher.js');
2058
2087
  const entryAbs = path.join(projectDir, entryFile).replace(/\\/g, '/');
2059
2088
  const shimAbs = path.join(shimDir, 'index.js').replace(/\\/g, '/');
2089
+
2090
+ // Error reporter script — injected into HTML pages to catch runtime errors
2091
+ const nhaHost = `http://127.0.0.1:${process.env.NHA_UI_PORT || 3847}`;
2092
+ const errorScript = `<script>
2093
+ (function(){var h="${nhaHost}";window.onerror=function(m,s,l,c,e){fetch(h+"/api/studio/webcraft/sandbox/errors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({error:m,source:s,line:l,col:c,stack:e?e.stack:""})}).catch(function(){});};window.addEventListener("unhandledrejection",function(e){fetch(h+"/api/studio/webcraft/sandbox/errors",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({error:"Unhandled: "+(e.reason?e.reason.message||e.reason:"unknown"),stack:e.reason?e.reason.stack:""})}).catch(function(){});});})();
2094
+ </script>`;
2095
+
2096
+ // Write error reporter script file
2097
+ fs.writeFileSync(path.join(shimDir, 'error-reporter.html'), errorScript, 'utf-8');
2098
+
2060
2099
  const launcher = [
2061
2100
  `// NHA WebCraft Sandbox Launcher — auto-generated`,
2062
2101
  `process.env.PORT = '${port}';`,
2063
2102
  `process.env.NODE_ENV = 'development';`,
2064
- `// Inject shims before loading user code`,
2065
2103
  `require('${shimAbs}');`,
2104
+ `// Inject error reporter into HTML responses`,
2105
+ `const _nhaErrScript = require('fs').readFileSync('${path.join(shimDir, 'error-reporter.html').replace(/\\/g, '/')}', 'utf-8');`,
2106
+ `const _origWrite = require('http').ServerResponse.prototype.write;`,
2107
+ `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
+ `require('http').ServerResponse.prototype.end = function(chunk, enc, cb) {`,
2114
+ ` if (this.getHeader && (this.getHeader('content-type')||'').includes('html')) { arguments[0] = _inject(chunk); delete this._headers['content-length']; }`,
2115
+ ` return _origEnd.apply(this, arguments);`,
2116
+ `};`,
2066
2117
  `require('${entryAbs}');`,
2067
2118
  ].join('\n');
2068
2119
  fs.writeFileSync(launcherPath, launcher, 'utf-8');