nothumanallowed 16.0.41 → 16.0.42

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.41",
3
+ "version": "16.0.42",
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.41';
8
+ export const VERSION = '16.0.42';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -5136,7 +5136,76 @@ function createApp() {
5136
5136
  const express = createApp;
5137
5137
  express.json = function (opts) { return async (req, res, next) => { if (/json/i.test(req.headers['content-type'] || '')) req.body = await parseBody(req); next(); }; };
5138
5138
  express.urlencoded = function (opts) { return async (req, res, next) => { if (/urlencoded/i.test(req.headers['content-type'] || '')) req.body = await parseBody(req); next(); }; };
5139
- express.static = function (root) { return (req, res, next) => next(); };
5139
+
5140
+ // MIME type table for static files
5141
+ const _MIME = {
5142
+ '.html': 'text/html; charset=utf-8',
5143
+ '.htm': 'text/html; charset=utf-8',
5144
+ '.css': 'text/css; charset=utf-8',
5145
+ '.js': 'application/javascript; charset=utf-8',
5146
+ '.mjs': 'application/javascript; charset=utf-8',
5147
+ '.json': 'application/json; charset=utf-8',
5148
+ '.png': 'image/png',
5149
+ '.jpg': 'image/jpeg',
5150
+ '.jpeg': 'image/jpeg',
5151
+ '.gif': 'image/gif',
5152
+ '.webp': 'image/webp',
5153
+ '.svg': 'image/svg+xml',
5154
+ '.ico': 'image/x-icon',
5155
+ '.woff': 'font/woff',
5156
+ '.woff2': 'font/woff2',
5157
+ '.ttf': 'font/ttf',
5158
+ '.otf': 'font/otf',
5159
+ '.eot': 'application/vnd.ms-fontobject',
5160
+ '.txt': 'text/plain; charset=utf-8',
5161
+ '.xml': 'application/xml',
5162
+ '.pdf': 'application/pdf',
5163
+ '.map': 'application/json',
5164
+ '.mp4': 'video/mp4',
5165
+ '.webm': 'video/webm',
5166
+ '.mp3': 'audio/mpeg',
5167
+ '.wav': 'audio/wav',
5168
+ };
5169
+
5170
+ // Real express.static implementation — serves files from disk with proper
5171
+ // MIME types. Supports index.html for directory requests, path traversal
5172
+ // protection. Falls through to next() when the file doesn't exist.
5173
+ express.static = function (root, opts) {
5174
+ opts = opts || {};
5175
+ const indexFile = opts.index === false ? null : (opts.index || 'index.html');
5176
+ const rootAbs = require('path').resolve(root);
5177
+ return function (req, res, next) {
5178
+ if (req.method !== 'GET' && req.method !== 'HEAD') return next();
5179
+ try {
5180
+ let relPath = decodeURIComponent((req.path || req.url || '/').split('?')[0]);
5181
+ // Path traversal protection
5182
+ if (relPath.includes('\\\\0') || relPath.includes('..')) return next();
5183
+ if (relPath.startsWith('/')) relPath = relPath.slice(1);
5184
+ const abs = require('path').resolve(rootAbs, relPath);
5185
+ // Ensure resolved path stays within root
5186
+ if (!abs.startsWith(rootAbs)) return next();
5187
+ let stat;
5188
+ try { stat = require('fs').statSync(abs); } catch { return next(); }
5189
+ let filePath = abs;
5190
+ if (stat.isDirectory()) {
5191
+ if (!indexFile) return next();
5192
+ filePath = require('path').join(abs, indexFile);
5193
+ try { stat = require('fs').statSync(filePath); } catch { return next(); }
5194
+ if (!stat.isFile()) return next();
5195
+ }
5196
+ const ext = require('path').extname(filePath).toLowerCase();
5197
+ const mime = _MIME[ext] || 'application/octet-stream';
5198
+ res.setHeader('Content-Type', mime);
5199
+ res.setHeader('Content-Length', String(stat.size));
5200
+ res.setHeader('Cache-Control', 'public, max-age=0');
5201
+ if (req.method === 'HEAD') return res.end();
5202
+ require('fs').createReadStream(filePath).pipe(res);
5203
+ } catch (e) {
5204
+ return next();
5205
+ }
5206
+ };
5207
+ };
5208
+
5140
5209
  express.Router = function () { const r = createApp(); return r; };
5141
5210
  module.exports = express;
5142
5211
  module.exports.default = express;