nothumanallowed 16.0.39 → 16.0.41
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 +123 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.41",
|
|
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.41';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -4198,6 +4198,56 @@ function _patchEntry(projectDir, entryFile, shimDir, port) {
|
|
|
4198
4198
|
` } catch(e) {}`,
|
|
4199
4199
|
` return _origEnd.apply(this, arguments);`,
|
|
4200
4200
|
`};`,
|
|
4201
|
+
`// Monkey-patch Express to neutralize next(falsy) — common LLM bug where`,
|
|
4202
|
+
`// middleware calls next(err) with err === undefined for EVERY request,`,
|
|
4203
|
+
`// causing 500 on all routes including static files. Express treats any`,
|
|
4204
|
+
`// truthy first arg as an error; if it's falsy (null/undefined/0/''),`,
|
|
4205
|
+
`// it's semantically equivalent to next() per Express docs. We rewrite.`,
|
|
4206
|
+
`(function() {`,
|
|
4207
|
+
` const Module = require('module');`,
|
|
4208
|
+
` const _origLoad = Module._load;`,
|
|
4209
|
+
` function wrapMiddleware(fn) {`,
|
|
4210
|
+
` if (typeof fn !== 'function' || fn.length !== 3) return fn;`,
|
|
4211
|
+
` const wrapped = function(req, res, next) {`,
|
|
4212
|
+
` const safeNext = function(err) {`,
|
|
4213
|
+
` if (err === undefined || err === null || err === false || err === 0) return next();`,
|
|
4214
|
+
` return next(err);`,
|
|
4215
|
+
` };`,
|
|
4216
|
+
` try { return fn.call(this, req, res, safeNext); }`,
|
|
4217
|
+
` catch (e) { return next(e); }`,
|
|
4218
|
+
` };`,
|
|
4219
|
+
` wrapped._nhaWrapped = true;`,
|
|
4220
|
+
` return wrapped;`,
|
|
4221
|
+
` }`,
|
|
4222
|
+
` function patchExpressApp(express) {`,
|
|
4223
|
+
` if (!express || express._nhaPatched) return express;`,
|
|
4224
|
+
` try {`,
|
|
4225
|
+
` // express() returns an app; patch app.use to wrap middleware`,
|
|
4226
|
+
` const _origExpress = express;`,
|
|
4227
|
+
` const factory = function(...args) {`,
|
|
4228
|
+
` const app = _origExpress.apply(this, args);`,
|
|
4229
|
+
` if (app && typeof app.use === 'function' && !app._nhaUseWrapped) {`,
|
|
4230
|
+
` const _origUse = app.use;`,
|
|
4231
|
+
` app.use = function(...uArgs) {`,
|
|
4232
|
+
` const mapped = uArgs.map(a => (typeof a === 'function' && a.length === 3 && !a._nhaWrapped) ? wrapMiddleware(a) : a);`,
|
|
4233
|
+
` return _origUse.apply(this, mapped);`,
|
|
4234
|
+
` };`,
|
|
4235
|
+
` app._nhaUseWrapped = true;`,
|
|
4236
|
+
` }`,
|
|
4237
|
+
` return app;`,
|
|
4238
|
+
` };`,
|
|
4239
|
+
` // Preserve static props: Router, json(), urlencoded(), etc.`,
|
|
4240
|
+
` Object.assign(factory, _origExpress);`,
|
|
4241
|
+
` factory._nhaPatched = true;`,
|
|
4242
|
+
` return factory;`,
|
|
4243
|
+
` } catch { return express; }`,
|
|
4244
|
+
` }`,
|
|
4245
|
+
` Module._load = function(name, parent, isMain) {`,
|
|
4246
|
+
` const result = _origLoad.call(this, name, parent, isMain);`,
|
|
4247
|
+
` if (name === 'express') return patchExpressApp(result);`,
|
|
4248
|
+
` return result;`,
|
|
4249
|
+
` };`,
|
|
4250
|
+
`})();`,
|
|
4201
4251
|
`// Strip headers that break sandbox iframe preview:`,
|
|
4202
4252
|
`// - X-Frame-Options: blocks iframe embedding entirely`,
|
|
4203
4253
|
`// - X-Content-Type-Options: nosniff: when LLM references /js/*.js files`,
|
|
@@ -4977,15 +5027,40 @@ function compilePath(p) {
|
|
|
4977
5027
|
}
|
|
4978
5028
|
|
|
4979
5029
|
function createApp() {
|
|
4980
|
-
|
|
5030
|
+
// Flat layer list — each handler is its own layer (matches Express semantics).
|
|
5031
|
+
// Layer types: 'normal' (3-arg) or 'error' (4-arg). Path-mounted layers
|
|
5032
|
+
// ('app.use("/api", router)') get a prefix that must match the URL.
|
|
5033
|
+
const layers = [];
|
|
4981
5034
|
const settings = {};
|
|
5035
|
+
|
|
5036
|
+
function addLayer(method, re, keys, prefix, handler) {
|
|
5037
|
+
const isErrHandler = typeof handler === 'function' && handler.length === 4;
|
|
5038
|
+
layers.push({ method, re, keys, prefix, handler, isErrHandler });
|
|
5039
|
+
}
|
|
5040
|
+
|
|
4982
5041
|
function use(arg, ...rest) {
|
|
4983
|
-
|
|
4984
|
-
|
|
5042
|
+
let prefix = '';
|
|
5043
|
+
let handlers = rest;
|
|
5044
|
+
if (typeof arg === 'function') {
|
|
5045
|
+
handlers = [arg, ...rest];
|
|
5046
|
+
} else {
|
|
5047
|
+
prefix = String(arg).replace(/\\/+$/, '');
|
|
5048
|
+
}
|
|
5049
|
+
for (const h of handlers.flat()) {
|
|
5050
|
+
if (typeof h !== 'function') continue;
|
|
5051
|
+
addLayer('ALL', /.*/, [], prefix, h);
|
|
5052
|
+
}
|
|
4985
5053
|
return app;
|
|
4986
5054
|
}
|
|
4987
5055
|
function addRoute(method) {
|
|
4988
|
-
return (
|
|
5056
|
+
return (p, ...handlers) => {
|
|
5057
|
+
const c = compilePath(p);
|
|
5058
|
+
for (const h of handlers.flat()) {
|
|
5059
|
+
if (typeof h !== 'function') continue;
|
|
5060
|
+
addLayer(method, c.re, c.keys, '', h);
|
|
5061
|
+
}
|
|
5062
|
+
return app;
|
|
5063
|
+
};
|
|
4989
5064
|
}
|
|
4990
5065
|
const app = async function (req, res) {
|
|
4991
5066
|
const parsed = url.parse(req.url, true);
|
|
@@ -4999,30 +5074,52 @@ function createApp() {
|
|
|
4999
5074
|
res.sendStatus = function (n) { this.statusCode = n; this.end(http.STATUS_CODES[n] || ''); return this; };
|
|
5000
5075
|
res.redirect = function (loc) { this.statusCode = 302; this.setHeader('Location', loc); this.end(); return this; };
|
|
5001
5076
|
}
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5077
|
+
|
|
5078
|
+
// Real Express-style routing chain:
|
|
5079
|
+
// - 3-arg handlers run ONLY when err is null/undefined
|
|
5080
|
+
// - 4-arg handlers run ONLY when err is truthy
|
|
5081
|
+
// - Path-mounted middleware ('/api') only runs if req.path matches prefix
|
|
5082
|
+
// - Method-specific layers (GET/POST/...) only run for that method
|
|
5083
|
+
let idx = 0;
|
|
5084
|
+
function nextLayer(err) {
|
|
5085
|
+
while (idx < layers.length) {
|
|
5086
|
+
const layer = layers[idx++];
|
|
5087
|
+
// Method filter
|
|
5007
5088
|
if (layer.method !== 'ALL' && layer.method !== req.method) continue;
|
|
5008
|
-
|
|
5009
|
-
if (
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
}
|
|
5020
|
-
|
|
5089
|
+
// Path filter
|
|
5090
|
+
if (layer.prefix) {
|
|
5091
|
+
if (!req.path.startsWith(layer.prefix)) continue;
|
|
5092
|
+
const remaining = req.path.slice(layer.prefix.length);
|
|
5093
|
+
if (remaining && !remaining.startsWith('/')) continue;
|
|
5094
|
+
} else if (layer.re && layer.method !== 'ALL') {
|
|
5095
|
+
// Specific route — must match
|
|
5096
|
+
const m = req.path.match(layer.re);
|
|
5097
|
+
if (!m) continue;
|
|
5098
|
+
req.params = {};
|
|
5099
|
+
layer.keys.forEach((k, i) => { req.params[k] = m[i + 1]; });
|
|
5100
|
+
}
|
|
5101
|
+
// Error chain filter: skip normal handlers when in error, and skip
|
|
5102
|
+
// error handlers when not in error. THIS is the fix for the MySaaS bug.
|
|
5103
|
+
if (err && !layer.isErrHandler) continue;
|
|
5104
|
+
if (!err && layer.isErrHandler) continue;
|
|
5105
|
+
|
|
5106
|
+
try {
|
|
5107
|
+
if (layer.isErrHandler) {
|
|
5108
|
+
return layer.handler(err, req, res, nextLayer);
|
|
5109
|
+
}
|
|
5110
|
+
return layer.handler(req, res, nextLayer);
|
|
5111
|
+
} catch (e) { return nextLayer(e); }
|
|
5021
5112
|
}
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5113
|
+
// End of chain — default response
|
|
5114
|
+
if (err) {
|
|
5115
|
+
res.statusCode = err.status || err.statusCode || 500;
|
|
5116
|
+
res.end('Error: ' + ((err && err.message) || String(err)));
|
|
5117
|
+
} else {
|
|
5118
|
+
res.statusCode = 404;
|
|
5119
|
+
res.end('Cannot ' + req.method + ' ' + req.path);
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
5122
|
+
nextLayer();
|
|
5026
5123
|
};
|
|
5027
5124
|
app.use = use;
|
|
5028
5125
|
app.get = addRoute('GET'); app.post = addRoute('POST'); app.put = addRoute('PUT');
|