neoagent 2.4.1-beta.36 → 2.4.1-beta.38

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": "neoagent",
3
- "version": "2.4.1-beta.36",
3
+ "version": "2.4.1-beta.38",
4
4
  "description": "Proactive personal AI agent with no limits",
5
5
  "license": "AGPL-3.0-only",
6
6
  "main": "server/index.js",
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ // Shared builder for SQLite FTS5 MATCH expressions. Any code path that feeds a
4
+ // user-supplied string into a `... MATCH ?` query must route it through here:
5
+ // raw input regularly contains characters that are special in FTS5's query
6
+ // grammar and would otherwise throw at query time.
7
+ //
8
+ // Two pitfalls are handled:
9
+ // 1. Hyphens — inside a MATCH a `-` is the NOT/column operator, so a bareword
10
+ // like `covid-19*` parses as `covid AND NOT column "19"` and throws
11
+ // "no such column: 19". The token regex excludes `-`, splitting on it.
12
+ // 2. Bareword operators — an uppercase token such as AND/OR/NOT/NEAR is parsed
13
+ // as an operator ("syntax error near AND"). FTS5's tokenizer is
14
+ // case-insensitive, so lowercasing each token neutralizes the collision
15
+ // while preserving matches.
16
+ //
17
+ // Returns a prefix-matched AND query (e.g. `covid* AND 19*`), or null when the
18
+ // input yields no usable tokens — callers should treat null as "no FTS filter".
19
+
20
+ function buildFtsQuery(query) {
21
+ const tokens = String(query || '')
22
+ .match(/[\p{L}\p{N}_]{2,}/gu) || [];
23
+ if (!tokens.length) return null;
24
+ return tokens.map((token) => `${token.toLowerCase().replace(/"/g, '')}*`).join(' AND ');
25
+ }
26
+
27
+ module.exports = { buildFtsQuery };
@@ -18,43 +18,4 @@ function requireNoAuth(req, res, next) {
18
18
  next();
19
19
  }
20
20
 
21
- function attachUser(req, res, next) {
22
- if (req.session && req.session.userId) {
23
- const db = require('../db/database');
24
- const now = Date.now();
25
- const cacheMaxAgeMs = 5 * 60 * 1000;
26
- const cachedUser = req.session._cachedUser;
27
- const cachedAt = Number(req.session._cachedUserAt || 0);
28
- const cacheFresh = (
29
- cachedUser
30
- && Number(cachedUser.id) === Number(req.session.userId)
31
- && cachedAt > 0
32
- && (now - cachedAt) < cacheMaxAgeMs
33
- );
34
-
35
- if (cacheFresh) {
36
- req.user = { ...cachedUser };
37
- return next();
38
- }
39
-
40
- const user = db.prepare('SELECT id, username, email, created_at FROM users WHERE id = ?').get(req.session.userId);
41
- if (user) {
42
- req.user = { ...user };
43
- req.session._cachedUser = { ...user };
44
- req.session._cachedUserAt = now;
45
- console.log(`[Auth] Attached user ${user.id} (${user.username}) to ${req.method} ${req.originalUrl || req.url}`);
46
- return next();
47
- }
48
-
49
- console.warn(`[Auth] Session user ${req.session.userId} not found for ${req.method} ${req.originalUrl || req.url}; destroying session`);
50
- req.session.destroy(() => {});
51
- const requestPath = req.originalUrl || req.url || req.path || '';
52
- if (requestPath.startsWith('/api/')) {
53
- return res.status(401).json({ error: 'Session invalid' });
54
- }
55
- return res.redirect('/login');
56
- }
57
- next();
58
- }
59
-
60
- module.exports = { requireAuth, requireNoAuth, attachUser };
21
+ module.exports = { requireAuth, requireNoAuth };
@@ -1 +1 @@
1
- cd629bebff6e6d3f781e6810f13e3583
1
+ 36f9d961cabc8d433b6d33a95164922c
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"c416acfeb8126e097f758c664aaa3da929e27d
37
37
 
38
38
  _flutter.loader.load({
39
39
  serviceWorkerSettings: {
40
- serviceWorkerVersion: "4109168282" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
40
+ serviceWorkerVersion: "434669552" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
41
41
  }
42
42
  });