nothumanallowed 16.0.40 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "16.0.40",
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.40';
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
 
@@ -5027,15 +5027,40 @@ function compilePath(p) {
5027
5027
  }
5028
5028
 
5029
5029
  function createApp() {
5030
- const stack = [];
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 = [];
5031
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
+
5032
5041
  function use(arg, ...rest) {
5033
- if (typeof arg === 'function') stack.push({ method: 'ALL', re: /.*/, keys: [], handlers: [arg, ...rest] });
5034
- else { const c = compilePath(arg); stack.push({ method: 'ALL', re: c.re, keys: c.keys, handlers: rest.flat() }); }
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
+ }
5035
5053
  return app;
5036
5054
  }
5037
5055
  function addRoute(method) {
5038
- return (path, ...handlers) => { const c = compilePath(path); stack.push({ method, re: c.re, keys: c.keys, handlers: handlers.flat() }); return app; };
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
+ };
5039
5064
  }
5040
5065
  const app = async function (req, res) {
5041
5066
  const parsed = url.parse(req.url, true);
@@ -5049,30 +5074,52 @@ function createApp() {
5049
5074
  res.sendStatus = function (n) { this.statusCode = n; this.end(http.STATUS_CODES[n] || ''); return this; };
5050
5075
  res.redirect = function (loc) { this.statusCode = 302; this.setHeader('Location', loc); this.end(); return this; };
5051
5076
  }
5052
- let i = 0;
5053
- const next = (err) => {
5054
- if (err) { res.statusCode = 500; return res.end('Error: ' + (err.message || err)); }
5055
- while (i < stack.length) {
5056
- const layer = stack[i++];
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
5057
5088
  if (layer.method !== 'ALL' && layer.method !== req.method) continue;
5058
- const m = req.path.match(layer.re);
5059
- if (!m) continue;
5060
- req.params = {};
5061
- layer.keys.forEach((k, idx) => { req.params[k] = m[idx + 1]; });
5062
- let hIdx = 0;
5063
- const runHandlers = (e) => {
5064
- if (e) return next(e);
5065
- if (hIdx >= layer.handlers.length) return next();
5066
- const h = layer.handlers[hIdx++];
5067
- try { return h.length === 4 ? h(e, req, res, runHandlers) : h(req, res, runHandlers); }
5068
- catch (err) { return next(err); }
5069
- };
5070
- return runHandlers();
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); }
5071
5112
  }
5072
- res.statusCode = 404;
5073
- res.end('Cannot ' + req.method + ' ' + req.path);
5074
- };
5075
- next();
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();
5076
5123
  };
5077
5124
  app.use = use;
5078
5125
  app.get = addRoute('GET'); app.post = addRoute('POST'); app.put = addRoute('PUT');